terminal-pilot 0.0.20 → 0.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +544 -259
- package/dist/cli.js.map +4 -4
- package/dist/commands/close-session.js.map +1 -1
- package/dist/commands/create-session.js.map +1 -1
- package/dist/commands/fill.js.map +1 -1
- package/dist/commands/get-session.js.map +1 -1
- package/dist/commands/index.js +220 -126
- package/dist/commands/index.js.map +4 -4
- package/dist/commands/install.js +187 -93
- package/dist/commands/install.js.map +4 -4
- package/dist/commands/installer.js +154 -60
- package/dist/commands/installer.js.map +4 -4
- package/dist/commands/list-sessions.js.map +1 -1
- package/dist/commands/press-key.js.map +1 -1
- package/dist/commands/read-history.js.map +1 -1
- package/dist/commands/read-screen.js.map +1 -1
- package/dist/commands/resize.js.map +1 -1
- package/dist/commands/runtime.js.map +1 -1
- package/dist/commands/screenshot.js.map +1 -1
- package/dist/commands/send-signal.js.map +1 -1
- package/dist/commands/type.js.map +1 -1
- package/dist/commands/uninstall.js +187 -93
- package/dist/commands/uninstall.js.map +4 -4
- package/dist/commands/wait-for-exit.js.map +1 -1
- package/dist/commands/wait-for.js.map +1 -1
- package/dist/testing/cli-repl.js +544 -259
- package/dist/testing/cli-repl.js.map +4 -4
- package/dist/testing/qa-cli.js +544 -259
- package/dist/testing/qa-cli.js.map +4 -4
- package/package.json +2 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../src/commands/uninstall.ts", "../../../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", "../../../toolcraft/src/package-metadata.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/gemini-cli.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", "../../../design
|
|
4
|
-
"sourcesContent": ["import { randomUUID } from \"node:crypto\";\nimport { defineCommand, S } from \"toolcraft\";\nimport type { TerminalPilotCommandServices } from \"./runtime.js\";\nimport {\n DEFAULT_INSTALL_AGENT,\n assertNoSymbolicLinkPath,\n getSkillFolderWithHome,\n installableAgents,\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 skills = [localSkill, globalSkill];\n const staged: Array<{ fullPath: string; stagingPath: string; displayPath: string }> = [];\n\n try {\n for (const skill of skills) {\n await assertNoSymbolicLinkPath(services.fs, skill.fullPath);\n\n if (!(await folderExists(services.fs, skill.fullPath))) {\n continue;\n }\n\n const stagingPath = `${skill.fullPath}.removing-${randomUUID()}`;\n await services.fs.rename(skill.fullPath, stagingPath);\n staged.push({ ...skill, stagingPath });\n }\n } catch (error) {\n for (const skill of staged.reverse()) {\n await services.fs.rename(skill.stagingPath, skill.fullPath);\n }\n throw error;\n }\n\n if (typeof services.fs.rm === \"function\") {\n await Promise.allSettled(\n staged.map((skill) => services.fs.rm!(skill.stagingPath, { recursive: true, force: true }))\n );\n }\n\n return {\n agent,\n removedSkillPaths: staged.map((skill) => skill.displayPath)\n };\n }\n});\n\nasync function folderExists(\n fs: ReturnType<typeof resolveInstallerServices>[\"fs\"],\n folderPath: string\n): Promise<boolean> {\n try {\n await fs.stat(folderPath);\n return true;\n } catch (error) {\n if (typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\") {\n return false;\n }\n\n throw error;\n }\n}\n", "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 {\n HumanInLoopConfig,\n HumanInLoopPending,\n HumanInLoopRuntimeOptions\n} from \"./human-in-loop/types.js\";\nimport { mergeHumanInLoopFromGroup, validateHumanInLoopOnDefine } from \"./human-in-loop/config.js\";\nimport { ToolcraftBugError, UserError } from \"./user-error.js\";\nimport { suggest } from \"./suggest.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 {\n mode: infer TMode extends HumanInLoopMode;\n}\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 lstat(path: string): Promise<{ isSymbolicLink(): boolean }>;\n rename(fromPath: string, toPath: string): Promise<void>;\n unlink(path: string): Promise<void>;\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>(\n requires: Requires<TContext> | undefined\n): 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(\n values: Record<string, string> | undefined\n): 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(\n rename: Record<string, string> | undefined\n): 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(\n `Invalid rename target for upstream tool \"${upstreamName}\": path cannot be empty.`\n );\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 =\n 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 =\n 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(\n parent: Requires<any> | undefined,\n child: Requires<any> | undefined\n): 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 (merged.auth === undefined && merged.apiVersion === undefined && merged.check === undefined) {\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 const candidates = Object.keys(env).filter(\n (candidate) => candidate !== secret.env && env[candidate] !== undefined\n );\n const suggestions = suggestSecretEnv(secret.env, candidates);\n const suggestionLine =\n suggestions.length > 0 ? `\\nDid you mean: ${suggestions.join(\", \")}?` : \"\";\n throw new UserError(`Missing required secret ${secret.env}${details}${suggestionLine}`);\n }\n\n Object.defineProperty(secrets, name, {\n value,\n enumerable: true,\n configurable: true,\n writable: true\n });\n }\n\n return secrets;\n}\n\nfunction suggestSecretEnv(input: string, candidates: readonly string[]): string[] {\n const directSuggestions = suggest(input, candidates);\n if (!input.includes(\"_\")) {\n return directSuggestions;\n }\n\n const inputParts = input.split(\"_\");\n const firstPart = inputParts[0];\n const lastPart = inputParts[inputParts.length - 1];\n const relatedCandidates = candidates.filter((candidate) => {\n const candidateParts = candidate.split(\"_\");\n return (\n candidateParts[0] === firstPart &&\n candidateParts[candidateParts.length - 1] === lastPart\n );\n });\n const expandedSuggestions = suggest(input, relatedCandidates, {\n threshold: Math.max(4, Math.floor(input.length / 4))\n });\n\n return [...new Set([...directSuggestions, ...expandedSuggestions])].slice(0, 3);\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 `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 `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 `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 `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 `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(\n ownScope: Scope[] | undefined,\n inheritedScope: Scope[] | undefined\n): Scope[] {\n return cloneScope(ownScope ?? inheritedScope) ?? [\"cli\", \"sdk\"];\n}\n\nfunction resolveGroupScope(\n ownScope: Scope[] | undefined,\n inheritedScope: Scope[] | undefined\n): 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>(\n config: GroupConfig<TServices>\n): 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 (\n command as Command<any, any, any, any> & { [commandConfigSymbol]: InternalCommandConfig }\n )[commandConfigSymbol];\n}\n\nfunction getInternalGroupConfig<TServices extends object>(\n group: Group<TServices>\n): 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) =>\n materializeNode(child, mergedInherited)\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 ToolcraftBugError(\n `Default command \"${internal.default.name}\" must be listed in children.`\n );\n }\n\n const resolvedDefault = materializedChildren[defaultIndex];\n if (resolvedDefault?.kind !== \"command\") {\n throw new ToolcraftBugError(`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<\n CommandConfig<TServices, TParamsSchema, TSecrets, TResult>,\n \"name\" | \"scope\" | \"humanInLoop\"\n > & {\n name: TName;\n scope?: TOwnScope;\n humanInLoop?: TOwnHumanInLoop;\n }\n): Command<TServices, TParamsSchema, TSecrets, TResult> &\n TypedCommandMetadata<\n TName,\n TParamsSchema,\n TResult,\n TOwnScope,\n ResolveOwnHumanInLoopMode<TOwnHumanInLoop>\n > {\n validateHumanInLoopOnDefine(config);\n\n return materializeCommand(\n createBaseCommand(config as CommandConfig<TServices, TParamsSchema, TSecrets, TResult>),\n {\n scope: undefined,\n humanInLoop: undefined,\n secrets: {},\n requires: undefined\n }\n ) as Command<TServices, TParamsSchema, TSecrets, TResult> &\n TypedCommandMetadata<\n TName,\n TParamsSchema,\n TResult,\n TOwnScope,\n ResolveOwnHumanInLoopMode<TOwnHumanInLoop>\n >;\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<\n TServices,\n TName,\n TChildren,\n TOwnScope,\n ResolveOwnHumanInLoopMode<TOwnHumanInLoop>\n > {\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<\n TServices,\n TName,\n TChildren,\n TOwnScope,\n ResolveOwnHumanInLoopMode<TOwnHumanInLoop>\n >;\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, ToolcraftBugError, UserError };\nexport { findPackageMetadata, packageMetadata } from \"./package-metadata.js\";\nexport type { PackageMetadata } from \"./package-metadata.js\";\nexport type {\n AnySchema,\n ArraySchema,\n BooleanSchema,\n EnumSchema,\n JsonSchema,\n NumberSchema,\n ObjectSchema,\n OptionalSchema,\n Static,\n StringSchema\n} from \"toolcraft-schema\";\nexport type { HumanInLoopConfig, HumanInLoopPending, HumanInLoopRuntimeOptions };\n", "export class UserError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = \"UserError\";\n }\n}\n\nexport class ToolcraftBugError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ToolcraftBugError\";\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(\n branches: Record<string, ObjectSchema<any>>,\n discriminator: string\n): void {\n if (Object.keys(branches).length === 0) {\n throw new Error(\"OneOf schema requires at least one branch\");\n }\n\n for (const [branchName, branch] of Object.entries(branches)) {\n if (Object.prototype.hasOwnProperty.call(branch.shape, discriminator)) {\n throw new Error(\n `OneOf branch \"${branchName}\" must not declare discriminator field \"${discriminator}\".`\n );\n }\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, config.discriminator);\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 getRequiredKeys(schema: ObjectSchema<any>): string[] {\n return Object.keys(schema.shape)\n .filter((key) => !isOptionalSchema(schema.shape[key] as AnySchema))\n .sort();\n}\n\nexport function getRequiredKeyFingerprint(schema: ObjectSchema<any>): string {\n return getRequiredKeys(schema).join(\"+\");\n}\n\nfunction assertUniqueRequiredKeyFingerprints(branches: readonly ObjectSchema<any>[]): void {\n const fingerprints = new Map<string, { display: string; indices: number[] }>();\n\n branches.forEach((branch, index) => {\n const requiredKeys = getRequiredKeys(branch);\n const fingerprint = JSON.stringify(requiredKeys);\n const existing = fingerprints.get(fingerprint);\n\n if (existing === undefined) {\n fingerprints.set(fingerprint, {\n display: requiredKeys.join(\"+\"),\n indices: [index],\n });\n return;\n }\n\n existing.indices.push(index);\n });\n\n for (const { display, indices } of fingerprints.values()) {\n if (indices.length > 1) {\n throw new Error(\n `Union branches [${indices.join(\", \")}] share required-key fingerprint \"${display}\". Each branch must require a distinct set of keys.`\n );\n }\n }\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 assertUniqueRequiredKeyFingerprints(branches);\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 { validate } from \"./validate.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\";\nimport type { ValidationIssue, ValidationResult } from \"./validate.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 secret?: boolean;\n};\ntype NumberMetadata = {\n maximum?: number;\n minimum?: number;\n secret?: boolean;\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 global?: boolean;\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 global?: boolean;\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 if (values.some((value) => typeof value === \"number\" && !Number.isFinite(value))) {\n throw new Error(\"Enum schema numeric values must be finite\");\n }\n}\n\nfunction assertNonNegativeInteger(value: number | undefined, name: string): void {\n if (value !== undefined && (!Number.isInteger(value) || value < 0)) {\n throw new Error(`${name} must be a non-negative integer`);\n }\n}\n\nfunction assertFiniteNumber(value: number | undefined, name: string): void {\n if (value !== undefined && !Number.isFinite(value)) {\n throw new Error(`${name} must be finite`);\n }\n}\n\nfunction assertPattern(pattern: string | undefined): void {\n if (pattern === undefined) {\n return;\n }\n try {\n new RegExp(pattern);\n } catch {\n throw new Error(\"pattern must be a valid regular expression\");\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 assertNonNegativeInteger(options.minLength, \"minLength\");\n assertNonNegativeInteger(options.maxLength, \"maxLength\");\n assertPattern(options.pattern);\n return {\n kind: \"string\",\n ...options,\n };\n },\n\n Number(\n options: SchemaOptions<number> & NumberMetadata & { jsonType?: NumberJsonType } = {}\n ): NumberSchema {\n assertFiniteNumber(options.minimum, \"minimum\");\n assertFiniteNumber(options.maximum, \"maximum\");\n assertFiniteNumber(options.default, \"default\");\n if (options.jsonType === \"integer\" && options.default !== undefined && !Number.isInteger(options.default)) {\n throw new Error(\"default must be an integer\");\n }\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 if (options.jsonType === \"integer\" && values.some((value) => typeof value !== \"number\" || !Number.isInteger(value))) {\n throw new Error(\"Integer enum values must be integers\");\n }\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 assertNonNegativeInteger(options.minItems, \"minItems\");\n assertNonNegativeInteger(options.maxItems, \"maxItems\");\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 Object.defineProperty(properties, key, {\n enumerable: true,\n configurable: true,\n writable: true,\n value: toJsonSchema(propertySchema)\n });\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, validate };\nexport type {\n JsonValue,\n JsonValueSchema,\n OneOfSchema,\n RecordSchema,\n UnionSchema,\n ValidationIssue,\n ValidationResult,\n};\n", "import { existsSync, readFileSync, statSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nexport interface PackageMetadata {\n name?: string;\n path: string;\n version?: string;\n}\n\ntype PackageMetadataInput = string | URL;\n\nfunction pathFromInput(from: PackageMetadataInput): string {\n if (from instanceof URL) {\n return fileURLToPath(from);\n }\n\n if (from.startsWith(\"file:\")) {\n return fileURLToPath(from);\n }\n\n return path.resolve(from);\n}\n\nfunction getSearchDirectory(from: PackageMetadataInput): string {\n const resolved = pathFromInput(from);\n\n try {\n return statSync(resolved).isDirectory() ? resolved : path.dirname(resolved);\n } catch {\n return path.dirname(resolved);\n }\n}\n\nfunction readPackageMetadata(packageJsonPath: string): PackageMetadata | undefined {\n const parsed = JSON.parse(readFileSync(packageJsonPath, \"utf8\")) as {\n name?: unknown;\n version?: unknown;\n };\n const metadata: PackageMetadata = { path: packageJsonPath };\n\n if (typeof parsed.name === \"string\") {\n metadata.name = parsed.name;\n }\n\n if (typeof parsed.version === \"string\") {\n metadata.version = parsed.version;\n }\n\n return metadata;\n}\n\nexport function findPackageMetadata(from: PackageMetadataInput): PackageMetadata | undefined {\n let current = getSearchDirectory(from);\n\n while (true) {\n const packageJsonPath = path.join(current, \"package.json\");\n\n if (existsSync(packageJsonPath)) {\n return readPackageMetadata(packageJsonPath);\n }\n\n const parent = path.dirname(current);\n\n if (parent === current) {\n return undefined;\n }\n\n current = parent;\n }\n}\n\nexport function packageMetadata(from: PackageMetadataInput = process.cwd()): PackageMetadata {\n const metadata = findPackageMetadata(from);\n\n if (metadata === undefined) {\n throw new Error(`No package.json found from ${pathFromInput(from)}.`);\n }\n\n return metadata;\n}\n\nexport function findEntrypointPackageMetadata(entrypoint: string | undefined): PackageMetadata | undefined {\n if (entrypoint === undefined || entrypoint.length === 0) {\n return undefined;\n }\n\n if (!path.isAbsolute(entrypoint) && !entrypoint.startsWith(\"file:\")) {\n return undefined;\n }\n\n return findPackageMetadata(entrypoint);\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 \"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 rename(oldPath: string, newPath: string): 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 lstat(path: string): Promise<{ isSymbolicLink(): boolean }>;\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 await assertNoSymbolicLinkPath(fs, folderPath);\n\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\nexport async function assertNoSymbolicLinkPath(\n fs: Pick<TerminalPilotInstallerFileSystem, \"lstat\">,\n targetPath: string\n): Promise<void> {\n const rootPath = path.parse(targetPath).root;\n let currentPath = targetPath;\n\n while (currentPath !== rootPath) {\n try {\n if ((await fs.lstat(currentPath)).isSymbolicLink()) {\n throw new UserError(`Refusing terminal-pilot skill operation through symbolic link: ${currentPath}`);\n }\n } catch (error) {\n if (!isNotFoundError(error)) {\n throw error;\n }\n }\n\n currentPath = path.dirname(currentPath);\n }\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 \"gemini-cli\": {\n globalSkillDir: \"~/.gemini/skills\",\n localSkillDir: \".gemini/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.freeze(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: { ...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, homeDir: string = os.homedir()): string {\n if (!targetPath?.startsWith(\"~\")) {\n return targetPath;\n }\n\n if (targetPath === \"~\") {\n return 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 ? homeDir : path.join(homeDir, remainder);\n}\n\nexport function resolveSkillDir(\n config: AgentSkillConfig,\n scope: SkillScope,\n cwd: string,\n homeDir?: string\n): string {\n if (scope === \"global\") {\n return path.resolve(expandHome(config.globalSkillDir, homeDir));\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 apiShapes: [\"anthropic-messages\"],\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 apiShapes: [\"openai-responses\"],\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 geminiCliAgent: AgentDefinition = {\n id: \"gemini-cli\",\n name: \"gemini-cli\",\n aliases: [\"gemini\"],\n label: \"Gemini CLI\",\n summary: \"Configure Google's Gemini CLI to use a compatible Google generations API.\",\n binaryName: \"gemini\",\n configPath: \"~/.gemini/settings.json\",\n apiShapes: [\"google-generations\"],\n branding: {\n colors: {\n dark: \"#8AB4F8\",\n light: \"#1A73E8\"\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 apiShapes: [\"openai-chat-completions\"],\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 apiShapes: [\"openai-chat-completions\"],\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 apiShapes: [\"openai-chat-completions\"],\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 apiShapes: [\"openai-responses\", \"openai-chat-completions\"],\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 geminiCliAgent,\n openCodeAgent,\n kimiAgent,\n gooseAgent,\n poeAgentAgent\n} from \"./agents/index.js\";\n\nfunction freezeAgent(agent: AgentDefinition): AgentDefinition {\n if (agent.aliases !== undefined) {\n Object.freeze(agent.aliases);\n }\n if (agent.apiShapes !== undefined) {\n Object.freeze(agent.apiShapes);\n }\n Object.freeze(agent.branding.colors);\n Object.freeze(agent.branding);\n return Object.freeze(agent);\n}\n\nexport const allAgents: readonly AgentDefinition[] = Object.freeze([\n freezeAgent(claudeCodeAgent),\n freezeAgent(claudeDesktopAgent),\n freezeAgent(codexAgent),\n freezeAgent(geminiCliAgent),\n freezeAgent(openCodeAgent),\n freezeAgent(kimiAgent),\n freezeAgent(gooseAgent),\n freezeAgent(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.trim().toLowerCase());\n}\n", "import path from \"node:path\";\nimport { renderTemplate } from \"@poe-code/design-system\";\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 { cloneConfigObject, setConfigEntry } from \"../formats/object.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 context: MutationContext,\n targetPath: string,\n content: string\n): Promise<void> {\n const baseBackupPath = createInvalidDocumentBackupPath(targetPath);\n let attempt = 0;\n while (true) {\n const backupPath = attempt === 0 ? baseBackupPath : `${baseBackupPath}-${attempt}`;\n await assertRegularWriteTarget(context, backupPath);\n try {\n await context.fs.writeFile(backupPath, content, { encoding: \"utf8\", flag: \"wx\" });\n return;\n } catch (error) {\n if (!isAlreadyExists(error)) {\n throw error;\n }\n attempt += 1;\n }\n }\n}\n\nfunction isAlreadyExists(error: unknown): boolean {\n return Boolean(error && typeof error === \"object\" && \"code\" in error && error.code === \"EEXIST\");\n}\n\nasync function assertRegularWriteTarget(\n context: MutationContext,\n targetPath: string\n): Promise<void> {\n // Symlinks inside the managed home directory are untrusted: an attacker could\n // plant one to redirect a credential/config write outside it. Symlinks at or\n // above home are legitimate system links (e.g. /tmp -> /private/tmp on macOS,\n // /var -> /private/var) and must not block writes, so bound the walk at home.\n const boundary = path.dirname(path.resolve(context.homeDir));\n let currentPath = path.resolve(targetPath);\n while (currentPath !== boundary) {\n try {\n if ((await context.fs.lstat(currentPath)).isSymbolicLink()) {\n throw new Error(`Refusing mutation write through symbolic link: ${currentPath}`);\n }\n } catch (error) {\n if (!isNotFound(error)) {\n throw error;\n }\n }\n\n const parentPath = path.dirname(currentPath);\n if (parentPath === currentPath) {\n return;\n }\n currentPath = parentPath;\n }\n}\n\nasync function writeAtomically(\n context: MutationContext,\n targetPath: string,\n content: string\n): Promise<void> {\n await assertRegularWriteTarget(context, targetPath);\n let attempt = 0;\n while (true) {\n const tempPath = `${targetPath}.mutation-tmp-${attempt}`;\n try {\n await context.fs.writeFile(tempPath, content, { encoding: \"utf8\", flag: \"wx\" });\n await context.fs.rename(tempPath, targetPath);\n return;\n } catch (error) {\n if (isAlreadyExists(error)) {\n attempt += 1;\n continue;\n }\n try {\n await context.fs.unlink(tempPath);\n } catch (cleanupError) {\n if (!isNotFound(cleanupError)) {\n void cleanupError;\n }\n }\n throw error;\n }\n }\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 \"restoreBackup\":\n return `Restore ${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 setConfigEntry(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 = cloneConfigObject(base);\n const prefixMap = pruneByPrefix ?? {};\n\n for (const [key, value] of Object.entries(patch)) {\n if (value === undefined) {\n continue;\n }\n\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 setConfigEntry(result, key, mergePrunedConfigObject(pruned, value));\n } else {\n setConfigEntry(result, key, mergeWithPruneByPrefix(current, value, prefixMap));\n }\n continue;\n }\n setConfigEntry(result, key, value);\n }\n return result;\n}\n\nfunction mergePrunedConfigObject(base: ConfigObject, patch: ConfigObject): ConfigObject {\n const result = cloneConfigObject(base);\n\n for (const [key, value] of Object.entries(patch)) {\n if (value === undefined) {\n continue;\n }\n\n setConfigEntry(result, key, value);\n }\n\n return result;\n}\n\nfunction serializeConfigUpdate(\n format: ReturnType<typeof getConfigFormat>,\n rawContent: string | null,\n current: ConfigObject,\n next: ConfigObject\n): string {\n if (rawContent !== null && format.serializeUpdate) {\n return format.serializeUpdate(rawContent, current, next);\n }\n return format.serialize(next);\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 \"restoreBackup\":\n return applyRestoreBackup(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) {\n mutation.whenContentMatches.lastIndex = 0;\n }\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 if (mutation.once && (await findLatestGeneratedBackup(context.fs, targetPath)) !== null) {\n return {\n outcome: { changed: false, effect: \"none\", detail: \"noop\" },\n details\n };\n }\n\n const content = await readFileIfExists(context.fs, targetPath);\n if (content === null && !mutation.once) {\n return {\n outcome: { changed: false, effect: \"none\", detail: \"noop\" },\n details\n };\n }\n\n if (!context.dryRun) {\n const baseBackupPath = `${targetPath}.backup-${createTimestamp()}${content === null ? \".missing\" : \"\"}`;\n let attempt = 0;\n while (true) {\n const backupPath = attempt === 0 ? baseBackupPath : `${baseBackupPath}-${attempt}`;\n try {\n await assertRegularWriteTarget(context, backupPath);\n await context.fs.writeFile(backupPath, content ?? \"\", { encoding: \"utf8\", flag: \"wx\" });\n break;\n } catch (error) {\n if (!isAlreadyExists(error)) {\n throw error;\n }\n attempt += 1;\n }\n }\n }\n\n return {\n outcome: { changed: true, effect: \"copy\", detail: \"backup\" },\n details\n };\n}\n\nasync function applyRestoreBackup(\n mutation: Extract<Mutation, { kind: \"restoreBackup\" }>,\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 const details: MutationDetails = {\n kind: mutation.kind,\n label: mutation.label ?? describeMutation(mutation.kind, targetPath),\n targetPath\n };\n const backup = await findLatestGeneratedBackup(context.fs, targetPath);\n\n if (backup === null) {\n return { outcome: { changed: false, effect: \"none\", detail: \"noop\" }, details };\n }\n\n if (!context.dryRun) {\n await assertRegularWriteTarget(context, backup.path);\n if (backup.originallyMissing) {\n try {\n await context.fs.unlink(targetPath);\n } catch (error) {\n if (!isNotFound(error)) {\n throw error;\n }\n }\n } else {\n const content = await context.fs.readFile(backup.path, \"utf8\");\n await writeAtomically(context, targetPath, content);\n }\n await context.fs.unlink(backup.path);\n }\n\n return { outcome: { changed: true, effect: \"copy\", detail: \"restore\" }, details };\n}\n\nasync function findLatestGeneratedBackup(\n fs: FileSystem,\n targetPath: string\n): Promise<{ path: string; originallyMissing: boolean } | null> {\n const separatorIndex = targetPath.lastIndexOf(\"/\");\n const directoryPath = separatorIndex <= 0 ? \"/\" : targetPath.slice(0, separatorIndex);\n const targetName = targetPath.slice(separatorIndex + 1);\n let entries: string[];\n\n try {\n entries = await fs.readdir(directoryPath);\n } catch (error) {\n if (isNotFound(error)) {\n return null;\n }\n throw error;\n }\n\n const backupName = entries\n .filter((entry) => isGeneratedBackupName(entry, targetName))\n .sort()\n .at(-1);\n return backupName === undefined\n ? null\n : {\n path: `${directoryPath}/${backupName}`,\n originallyMissing: backupName.endsWith(\".missing\")\n };\n}\n\nfunction isGeneratedBackupName(entry: string, targetName: string): boolean {\n const prefix = `${targetName}.backup-`;\n if (!entry.startsWith(prefix)) {\n return false;\n }\n\n const suffix = entry.slice(prefix.length);\n const timestamp = suffix.slice(0, 24);\n if (timestamp.length !== 24 || timestamp[4] !== \"-\" || timestamp[7] !== \"-\" || timestamp[10] !== \"T\" || timestamp[13] !== \"-\" || timestamp[16] !== \"-\" || timestamp[19] !== \"-\" || timestamp[23] !== \"Z\") {\n return false;\n }\n const parsedTimestamp = `${timestamp.slice(0, 13)}:${timestamp.slice(14, 16)}:${timestamp.slice(17, 19)}.${timestamp.slice(20)}`;\n if (Number.isNaN(Date.parse(parsedTimestamp))) {\n return false;\n }\n const collisionSuffix = suffix.slice(24);\n if (collisionSuffix.length === 0) {\n return true;\n }\n if (collisionSuffix === \".missing\") {\n return true;\n }\n return collisionSuffix[0] === \"-\" && collisionSuffix.slice(1).length > 0 && [...collisionSuffix.slice(1)].every((character) => character >= \"0\" && character <= \"9\");\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 preserveContent = rawContent;\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 && !context.dryRun) {\n await backupInvalidDocument(context, targetPath, rawContent);\n }\n current = {};\n preserveContent = null;\n }\n\n const value = resolveValue(mutation.value, options);\n\n // Keep prefix pruning on the same proto-safe object-write path as normal merges.\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 = serializeConfigUpdate(format, preserveContent, current, merged);\n const changed = serialized !== rawContent;\n\n if (changed && !context.dryRun) {\n await writeAtomically(context, targetPath, serialized);\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 = serializeConfigUpdate(format, rawContent, current, result);\n if (!context.dryRun) {\n await writeAtomically(context, targetPath, serialized);\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 preserveContent = rawContent;\n let current: ConfigObject;\n try {\n current = rawContent === null ? {} : format.parse(rawContent);\n } catch {\n if (rawContent !== null && !context.dryRun) {\n await backupInvalidDocument(context, targetPath, rawContent);\n }\n current = {};\n preserveContent = null;\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 = serializeConfigUpdate(format, preserveContent, current, transformed);\n if (!context.dryRun) {\n await writeAtomically(context, targetPath, serialized);\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 = renderTemplate(template, templateContext);\n\n const current = await readFileIfExists(context.fs, targetPath);\n const changed = current !== rendered;\n\n if (changed && !context.dryRun) {\n await writeAtomically(context, targetPath, rendered);\n }\n\n return {\n outcome: {\n changed,\n effect: changed ? \"write\" : \"none\",\n detail: changed ? (current === null ? \"create\" : \"update\") : \"noop\"\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 = renderTemplate(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 && !context.dryRun) {\n await backupInvalidDocument(context, 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 writeAtomically(context, targetPath, serialized);\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", "export interface ColorSupportEnv {\n NO_COLOR?: string;\n FORCE_COLOR?: string;\n TERM?: string;\n}\n\nexport interface ColorSupportStream {\n isTTY?: boolean;\n}\n\nexport function supportsColor(\n env: ColorSupportEnv = process.env as ColorSupportEnv,\n stream: ColorSupportStream = process.stdout\n): boolean {\n if (env.FORCE_COLOR !== undefined && env.FORCE_COLOR !== \"0\") {\n return true;\n }\n\n if (env.NO_COLOR !== undefined) {\n return false;\n }\n\n if (stream.isTTY !== true) {\n return false;\n }\n\n return typeof env.TERM === \"string\" && env.TERM.length > 0 && env.TERM !== \"dumb\";\n}\n", "import { supportsColor } from \"../internal/color-support.js\";\n\ntype AnsiStyleName =\n | \"reset\"\n | \"bold\"\n | \"dim\"\n | \"italic\"\n | \"underline\"\n | \"inverse\"\n | \"strikethrough\"\n | \"black\"\n | \"red\"\n | \"green\"\n | \"yellow\"\n | \"blue\"\n | \"magenta\"\n | \"cyan\"\n | \"white\"\n | \"gray\"\n | \"magentaBright\"\n | \"cyanBright\"\n | \"bgRed\"\n | \"bgGreen\"\n | \"bgYellow\"\n | \"bgBlue\"\n | \"bgMagenta\";\n\ninterface AnsiPair {\n open: string;\n}\n\nexport interface Color {\n (text: string): string;\n reset: Color;\n bold: Color;\n dim: Color;\n italic: Color;\n underline: Color;\n inverse: Color;\n strikethrough: Color;\n black: Color;\n red: Color;\n green: Color;\n yellow: Color;\n blue: Color;\n magenta: Color;\n cyan: Color;\n white: Color;\n gray: Color;\n magentaBright: Color;\n cyanBright: Color;\n bgRed: Color;\n bgGreen: Color;\n bgYellow: Color;\n bgBlue: Color;\n bgMagenta: Color;\n hex: (value: string) => Color;\n rgb: (red: number, green: number, blue: number) => Color;\n bgHex: (value: string) => Color;\n bgRgb: (red: number, green: number, blue: number) => Color;\n}\n\nconst reset = \"\\x1b[0m\";\n\nconst ansiStyles: Record<AnsiStyleName, AnsiPair> = {\n reset: { open: reset },\n bold: { open: \"\\x1b[1m\" },\n dim: { open: \"\\x1b[2m\" },\n italic: { open: \"\\x1b[3m\" },\n underline: { open: \"\\x1b[4m\" },\n inverse: { open: \"\\x1b[7m\" },\n strikethrough: { open: \"\\x1b[9m\" },\n black: { open: \"\\x1b[30m\" },\n red: { open: \"\\x1b[31m\" },\n green: { open: \"\\x1b[32m\" },\n yellow: { open: \"\\x1b[33m\" },\n blue: { open: \"\\x1b[34m\" },\n magenta: { open: \"\\x1b[35m\" },\n cyan: { open: \"\\x1b[36m\" },\n white: { open: \"\\x1b[37m\" },\n gray: { open: \"\\x1b[90m\" },\n magentaBright: { open: \"\\x1b[95m\" },\n cyanBright: { open: \"\\x1b[96m\" },\n bgRed: { open: \"\\x1b[41m\" },\n bgGreen: { open: \"\\x1b[42m\" },\n bgYellow: { open: \"\\x1b[43m\" },\n bgBlue: { open: \"\\x1b[44m\" },\n bgMagenta: { open: \"\\x1b[45m\" }\n};\n\nconst styleNames = Object.keys(ansiStyles) as AnsiStyleName[];\n\nfunction replaceAll(value: string, search: string, replacement: string): string {\n return value.split(search).join(replacement);\n}\n\nfunction applyStyles(text: string, styles: AnsiPair[]): string {\n if (!supportsColor() || styles.length === 0) {\n return text;\n }\n\n const open = styles.map((style) => style.open).join(\"\");\n const output = text.includes(reset) ? replaceAll(text, reset, `${reset}${open}`) : text;\n\n return `${open}${output}${reset}`;\n}\n\nfunction clampRgb(value: number): number {\n if (Number.isNaN(value)) {\n return 0;\n }\n\n return Math.min(255, Math.max(0, Math.round(value)));\n}\n\nfunction hexChannel(value: string, offset: number): number {\n return Number.parseInt(value.slice(offset, offset + 2), 16);\n}\n\nfunction normalizeHex(value: string): [number, number, number] {\n const normalized = value.startsWith(\"#\") ? value.slice(1) : value;\n\n if ((normalized.length !== 3 && normalized.length !== 6) ||\n Array.from(normalized).some((char) => !\"0123456789abcdefABCDEF\".includes(char))) {\n throw new Error(`Invalid hexadecimal color: ${value}`);\n }\n\n if (normalized.length === 3) {\n const red = normalized[0]!;\n const green = normalized[1]!;\n const blue = normalized[2]!;\n\n return [\n Number.parseInt(`${red}${red}`, 16),\n Number.parseInt(`${green}${green}`, 16),\n Number.parseInt(`${blue}${blue}`, 16)\n ];\n }\n\n return [\n hexChannel(normalized, 0),\n hexChannel(normalized, 2),\n hexChannel(normalized, 4)\n ];\n}\n\nfunction rgbStyle(red: number, green: number, blue: number): AnsiPair {\n return {\n open: `\\x1b[38;2;${clampRgb(red)};${clampRgb(green)};${clampRgb(blue)}m`\n };\n}\n\nfunction bgRgbStyle(red: number, green: number, blue: number): AnsiPair {\n return {\n open: `\\x1b[48;2;${clampRgb(red)};${clampRgb(green)};${clampRgb(blue)}m`\n };\n}\n\nfunction createColor(styles: AnsiPair[] = []): Color {\n const builder = ((text: string) => applyStyles(String(text), styles)) as Color;\n\n for (const name of styleNames) {\n Object.defineProperty(builder, name, {\n configurable: true,\n enumerable: true,\n get: () => createColor([...styles, ansiStyles[name]])\n });\n }\n\n builder.hex = (value: string) => {\n const [red, green, blue] = normalizeHex(value);\n return createColor([...styles, rgbStyle(red, green, blue)]);\n };\n\n builder.rgb = (red: number, green: number, blue: number) =>\n createColor([...styles, rgbStyle(red, green, blue)]);\n\n builder.bgHex = (value: string) => {\n const [red, green, blue] = normalizeHex(value);\n return createColor([...styles, bgRgbStyle(red, green, blue)]);\n };\n\n builder.bgRgb = (red: number, green: number, blue: number) =>\n createColor([...styles, bgRgbStyle(red, green, blue)]);\n\n return builder;\n}\n\nexport const color = createColor();\n", "import { color } from \"../components/color.js\";\n\nexport const brand = \"#a200ff\";\n\nexport const dark = {\n header: (text: string) => color.magentaBright.bold(text),\n divider: (text: string) => color.dim(text),\n prompt: (text: string) => color.cyan(text),\n number: (text: string) => color.cyanBright(text),\n intro: (text: string) => color.bgMagenta.white(` Poe - ${text} `),\n resolvedSymbol: color.magenta(\"\u25C7\"),\n errorSymbol: color.red(\"\u25A0\"),\n accent: (text: string) => color.cyan(text),\n muted: (text: string) => color.dim(text),\n success: (text: string) => color.green(text),\n warning: (text: string) => color.yellow(text),\n error: (text: string) => color.red(text),\n info: (text: string) => color.magenta(text),\n badge: (text: string) => color.bgYellow.black(` ${text} `)\n};\n\nexport const light = {\n header: (text: string) => color.hex(\"#a200ff\").bold(text),\n divider: (text: string) => color.hex(\"#666666\")(text),\n prompt: (text: string) => color.hex(\"#006699\").bold(text),\n number: (text: string) => color.hex(\"#0077cc\").bold(text),\n intro: (text: string) => color.bgHex(\"#a200ff\").white(` Poe - ${text} `),\n resolvedSymbol: color.hex(\"#a200ff\")(\"\u25C7\"),\n errorSymbol: color.hex(\"#cc0000\")(\"\u25A0\"),\n accent: (text: string) => color.hex(\"#006699\").bold(text),\n muted: (text: string) => color.hex(\"#666666\")(text),\n success: (text: string) => color.hex(\"#008800\")(text),\n warning: (text: string) => color.hex(\"#cc6600\")(text),\n error: (text: string) => color.hex(\"#cc0000\")(text),\n info: (text: string) => color.hex(\"#a200ff\")(text),\n badge: (text: string) => color.bgHex(\"#cc6600\").white(` ${text} `)\n};\n\nexport type ThemeName = \"dark\" | \"light\";\nexport type ThemePalette = typeof dark;\n", "import { AsyncLocalStorage } from \"node:async_hooks\";\n\nexport type OutputFormat = \"terminal\" | \"markdown\" | \"json\";\n\nconst VALID_FORMATS = new Set<OutputFormat>([\"terminal\", \"markdown\", \"json\"]);\nconst formatStorage = new AsyncLocalStorage<OutputFormat>();\n\nlet cached: OutputFormat | undefined;\n\nexport function resolveOutputFormat(\n env: { OUTPUT_FORMAT?: string } = process.env as { OUTPUT_FORMAT?: string }\n): OutputFormat {\n const scoped = formatStorage.getStore();\n if (scoped) {\n return scoped;\n }\n if (cached) {\n return cached;\n }\n const raw = env.OUTPUT_FORMAT?.toLowerCase();\n cached = VALID_FORMATS.has(raw as OutputFormat) ? (raw as OutputFormat) : \"terminal\";\n return cached;\n}\n\nexport function withOutputFormat<T>(format: OutputFormat, fn: () => T): T {\n return formatStorage.run(format, fn);\n}\n\nexport function resetOutputFormatCache(): void {\n cached = undefined;\n}\n", "import { dark, light, type ThemeName, type ThemePalette } from \"../tokens/colors.js\";\n\nexport interface ThemeEnv {\n POE_CODE_THEME?: string;\n POE_THEME?: string;\n APPLE_INTERFACE_STYLE?: string;\n VSCODE_COLOR_THEME_KIND?: string;\n COLORFGBG?: string;\n}\n\nfunction detectThemeFromEnv(env: ThemeEnv): ThemeName | undefined {\n const apple = env.APPLE_INTERFACE_STYLE;\n if (typeof apple === \"string\") {\n return apple.toLowerCase() === \"dark\" ? \"dark\" : \"light\";\n }\n\n const vscodeKind = env.VSCODE_COLOR_THEME_KIND;\n if (typeof vscodeKind === \"string\") {\n const normalized = vscodeKind.toLowerCase();\n if (normalized.includes(\"light\")) {\n return \"light\";\n }\n if (normalized.includes(\"dark\")) {\n return \"dark\";\n }\n }\n\n const colorFGBG = env.COLORFGBG;\n if (typeof colorFGBG === \"string\") {\n const parts = colorFGBG.split(\";\").map((part) => Number.parseInt(part, 10));\n const background = parts.at(-1);\n if (Number.isFinite(background)) {\n return background! >= 8 ? \"light\" : \"dark\";\n }\n }\n\n return undefined;\n}\n\nexport function resolveThemeName(env: ThemeEnv = process.env as ThemeEnv): ThemeName {\n const raw = (env.POE_CODE_THEME ?? env.POE_THEME)?.toLowerCase();\n if (raw === \"light\" || raw === \"dark\") {\n return raw;\n }\n const detected = detectThemeFromEnv(env);\n if (detected) {\n return detected;\n }\n return \"dark\";\n}\n\nlet cachedTheme: ThemePalette | undefined;\n\nexport function getTheme(env?: ThemeEnv): ThemePalette {\n if (cachedTheme) {\n return cachedTheme;\n }\n const themeName = resolveThemeName(env);\n cachedTheme = themeName === \"light\" ? light : dark;\n return cachedTheme;\n}\n\nexport function resetThemeCache(): void {\n cachedTheme = undefined;\n}\n", "import { color } from \"./color.js\";\nimport { resolveOutputFormat } from \"../internal/output-format.js\";\nimport { getTheme } from \"../internal/theme-detect.js\";\n\nexport const symbols = {\n get info(): string {\n const format = resolveOutputFormat();\n if (format === \"json\") return \"info\";\n if (format === \"markdown\") return \"(i)\";\n return color.magenta(\"\u25CF\");\n },\n get success(): string {\n const format = resolveOutputFormat();\n if (format === \"json\") return \"success\";\n if (format === \"markdown\") return \"[ok]\";\n return color.magenta(\"\u25C6\");\n },\n get resolved(): string {\n const format = resolveOutputFormat();\n if (format === \"json\") return \"resolved\";\n if (format === \"markdown\") return \">\";\n return getTheme().resolvedSymbol;\n },\n get errorResolved(): string {\n const format = resolveOutputFormat();\n if (format === \"json\") return \"error\";\n if (format === \"markdown\") return \"[!]\";\n return getTheme().errorSymbol;\n },\n get bar(): string {\n const format = resolveOutputFormat();\n if (format === \"json\") return \"\";\n if (format === \"markdown\") return \"|\";\n return \"\u2502\";\n },\n cornerTopRight: \"\u256E\",\n cornerBottomRight: \"\u256F\",\n get warning(): string {\n const format = resolveOutputFormat();\n if (format === \"json\") return \"warning\";\n if (format === \"markdown\") return \"[!]\";\n return \"\u25B2\";\n },\n get active(): string {\n const format = resolveOutputFormat();\n if (format === \"json\") return \"active\";\n if (format === \"markdown\") return \"[x]\";\n return \"\u25C6\";\n },\n get inactive(): string {\n const format = resolveOutputFormat();\n if (format === \"json\") return \"inactive\";\n if (format === \"markdown\") return \"[ ]\";\n return \"\u25CB\";\n }\n} as const;\n", "export function stripAnsi(value: string): string {\n return value.replace(/\\u001b\\[[0-9;]*m/g, \"\");\n}\n", "import { color } from \"../../components/color.js\";\nimport { symbols } from \"../../components/symbols.js\";\nimport { resolveOutputFormat } from \"../../internal/output-format.js\";\nimport { stripAnsi } from \"../../internal/strip-ansi.js\";\n\nexport interface LogMessageOptions {\n symbol?: string;\n secondarySymbol?: string;\n spacing?: number;\n withGuide?: boolean;\n}\n\nfunction renderMarkdownInline(value: string): string {\n return stripAnsi(value).replaceAll(\"\\r\\n\", \" \").replaceAll(\"\\n\", \" \").replaceAll(\"\\r\", \" \");\n}\n\nfunction writeTerminalMessage(\n msg: string,\n {\n symbol = color.gray(\"\u2502\"),\n secondarySymbol = color.gray(\"\u2502\"),\n spacing = 1,\n withGuide = true\n }: LogMessageOptions = {}\n): void {\n const lines: string[] = [];\n const showGuide = withGuide !== false;\n const contentLines = msg.split(\"\\n\");\n const prefix = showGuide ? `${symbol} ` : \"\";\n const continuationPrefix = showGuide ? `${secondarySymbol} ` : \"\";\n const emptyGuide = showGuide ? secondarySymbol : \"\";\n\n for (let index = 0; index < spacing; index += 1) {\n lines.push(emptyGuide);\n }\n\n if (contentLines.length === 0) {\n process.stdout.write(\"\\n\");\n return;\n }\n\n const [firstLine = \"\", ...continuationLines] = contentLines;\n if (firstLine.length > 0) {\n lines.push(`${prefix}${firstLine}`);\n } else {\n lines.push(showGuide ? symbol : \"\");\n }\n\n for (const line of continuationLines) {\n if (line.length > 0) {\n lines.push(`${continuationPrefix}${line}`);\n continue;\n }\n lines.push(emptyGuide);\n }\n\n process.stdout.write(`${lines.join(\"\\n\")}\\n`);\n}\n\nexport function message(msg: string, options?: LogMessageOptions): void {\n const format = resolveOutputFormat();\n if (format === \"markdown\") {\n process.stdout.write(`- ${renderMarkdownInline(msg)}\\n`);\n return;\n }\n if (format === \"json\") {\n process.stdout.write(\n `${JSON.stringify({ level: \"message\", message: stripAnsi(msg) })}\\n`\n );\n return;\n }\n\n writeTerminalMessage(msg, options);\n}\n\nexport function info(msg: string): void {\n const format = resolveOutputFormat();\n if (format === \"markdown\") {\n process.stdout.write(`- **info:** ${renderMarkdownInline(msg)}\\n`);\n return;\n }\n if (format === \"json\") {\n process.stdout.write(\n `${JSON.stringify({ level: \"info\", message: stripAnsi(msg) })}\\n`\n );\n return;\n }\n\n message(msg, { symbol: symbols.info });\n}\n\nexport function success(msg: string): void {\n const format = resolveOutputFormat();\n if (format === \"markdown\") {\n process.stdout.write(`- **success:** ${renderMarkdownInline(msg)}\\n`);\n return;\n }\n if (format === \"json\") {\n process.stdout.write(\n `${JSON.stringify({ level: \"success\", message: stripAnsi(msg) })}\\n`\n );\n return;\n }\n\n message(msg, { symbol: symbols.success });\n}\n\nexport function warn(msg: string): void {\n const format = resolveOutputFormat();\n if (format === \"markdown\") {\n process.stdout.write(`- **warning:** ${renderMarkdownInline(msg)}\\n`);\n return;\n }\n if (format === \"json\") {\n process.stdout.write(\n `${JSON.stringify({ level: \"warn\", message: stripAnsi(msg) })}\\n`\n );\n return;\n }\n\n message(msg, { symbol: color.yellow(\"\u25B2\") });\n}\n\nexport function error(msg: string): void {\n const format = resolveOutputFormat();\n if (format === \"markdown\") {\n process.stdout.write(`- **error:** ${renderMarkdownInline(msg)}\\n`);\n return;\n }\n if (format === \"json\") {\n process.stdout.write(\n `${JSON.stringify({ level: \"error\", message: stripAnsi(msg) })}\\n`\n );\n return;\n }\n\n message(msg, { symbol: color.red(\"\u25A0\") });\n}\n\nexport const log = {\n info,\n success,\n message,\n warn,\n error\n};\n", "import { color } from \"./color.js\";\nimport { log } from \"../prompts/primitives/log.js\";\nimport { symbols } from \"./symbols.js\";\n\nexport interface LoggerOutput {\n info(message: string): void;\n success(message: string): void;\n warn(message: string): void;\n error(message: string): void;\n resolved(label: string, value: string): void;\n errorResolved(label: string, value: string): void;\n message(message: string, symbol?: string): void;\n}\n\nexport function createLogger(emitter?: (message: string) => void): LoggerOutput {\n const emit = (\n level: \"info\" | \"success\" | \"warn\" | \"error\",\n message: string\n ): void => {\n if (emitter) {\n emitter(message);\n return;\n }\n if (level === \"success\") {\n log.success(message);\n return;\n }\n if (level === \"warn\") {\n log.warn(message);\n return;\n }\n if (level === \"error\") {\n log.error(message);\n return;\n }\n log.info(message);\n };\n\n return {\n info(message: string): void {\n emit(\"info\", message);\n },\n success(message: string): void {\n emit(\"success\", message);\n },\n warn(message: string): void {\n emit(\"warn\", message);\n },\n error(message: string): void {\n emit(\"error\", message);\n },\n resolved(label: string, value: string): void {\n if (emitter) {\n emitter(`${label}: ${value}`);\n return;\n }\n log.message(`${label}\\n ${value}`, { symbol: symbols.resolved });\n },\n errorResolved(label: string, value: string): void {\n if (emitter) {\n emitter(`${label}: ${value}`);\n return;\n }\n log.message(`${label}\\n ${value}`, { symbol: symbols.errorResolved });\n },\n message(message: string, symbol?: string): void {\n if (emitter) {\n emitter(message);\n return;\n }\n log.message(message, { symbol: symbol ?? color.gray(\"\u2502\") });\n }\n };\n}\n\nexport const logger = createLogger();\n", "import { text } from \"./text.js\";\n\nexport interface CommandInfo {\n name: string;\n description: string;\n}\n\nexport interface OptionInfo {\n flags: string;\n description: string;\n}\n\nexport interface FormatColumnsOptions {\n rows: Array<{ left: string; right: string }>;\n totalWidth?: number;\n minLeftWidth?: number;\n maxLeftWidth?: number;\n gap?: number;\n indent?: number;\n}\n\nconst graphemeSegmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n\nfunction normalizeInline(value: string): string {\n return value.replaceAll(\"\\r\\n\", \" \").replaceAll(\"\\n\", \" \").replaceAll(\"\\r\", \" \");\n}\n\nfunction readControlSequence(value: string, index: number): number | undefined {\n if (value[index] !== \"\\u001b\") {\n return undefined;\n }\n\n if (value[index + 1] === \"[\") {\n let nextIndex = index + 2;\n while (nextIndex < value.length) {\n const code = value.charCodeAt(nextIndex);\n nextIndex += 1;\n if (code >= 0x40 && code <= 0x7e) {\n return nextIndex;\n }\n }\n return value.length;\n }\n\n if (value[index + 1] === \"]\") {\n let nextIndex = index + 2;\n while (nextIndex < value.length) {\n if (value[nextIndex] === \"\\u0007\") {\n return nextIndex + 1;\n }\n if (value[nextIndex] === \"\\u001b\" && value[nextIndex + 1] === \"\\\\\") {\n return nextIndex + 2;\n }\n nextIndex += 1;\n }\n return value.length;\n }\n\n return index + 1;\n}\n\nfunction isWideCodePoint(codePoint: number): boolean {\n return (\n (codePoint >= 0x1100 && codePoint <= 0x115f) ||\n codePoint === 0x2329 ||\n codePoint === 0x232a ||\n (codePoint >= 0x2e80 && codePoint <= 0xa4cf && codePoint !== 0x303f) ||\n (codePoint >= 0xac00 && codePoint <= 0xd7a3) ||\n (codePoint >= 0xf900 && codePoint <= 0xfaff) ||\n (codePoint >= 0xfe10 && codePoint <= 0xfe19) ||\n (codePoint >= 0xfe30 && codePoint <= 0xfe6f) ||\n (codePoint >= 0xff00 && codePoint <= 0xff60) ||\n (codePoint >= 0xffe0 && codePoint <= 0xffe6) ||\n (codePoint >= 0x2600 && codePoint <= 0x27bf) ||\n (codePoint >= 0x1f300 && codePoint <= 0x1faff) ||\n (codePoint >= 0x20000 && codePoint <= 0x3fffd)\n );\n}\n\nfunction clusterWidth(cluster: string): number {\n const codePoints = Array.from(cluster).map((char) => char.codePointAt(0) ?? 0);\n if (codePoints.some((codePoint) => codePoint === 0x200d || (codePoint >= 0xfe00 && codePoint <= 0xfe0f))) {\n return 2;\n }\n\n return codePoints.reduce((width, codePoint) => {\n if (codePoint === 0 || codePoint < 0x20 || (codePoint >= 0x7f && codePoint < 0xa0)) {\n return width;\n }\n return width + (isWideCodePoint(codePoint) ? 2 : 1);\n }, 0);\n}\n\nfunction visibleWidth(value: string): number {\n let width = 0;\n let index = 0;\n\n while (index < value.length) {\n const nextIndex = readControlSequence(value, index);\n if (nextIndex !== undefined) {\n index = nextIndex;\n continue;\n }\n\n const segment = graphemeSegmenter.segment(value.slice(index))[Symbol.iterator]().next().value as\n | Intl.SegmentData\n | undefined;\n const cluster = segment?.segment ?? \"\";\n width += clusterWidth(cluster);\n index += cluster.length || 1;\n }\n\n return width;\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\nfunction padEndVisible(value: string, width: number): string {\n return value + \" \".repeat(Math.max(0, width - visibleWidth(value)));\n}\n\nfunction isWhitespace(char: string | undefined): boolean {\n return char === \" \" || char === \"\\n\" || char === \"\\t\" || char === \"\\r\";\n}\n\nfunction splitWords(value: string): string[] {\n const words: string[] = [];\n let word = \"\";\n\n for (const char of value) {\n if (isWhitespace(char)) {\n if (word) {\n words.push(word);\n word = \"\";\n }\n continue;\n }\n word += char;\n }\n\n if (word) {\n words.push(word);\n }\n\n return words;\n}\n\nfunction wrapWords(value: string, width: number): string[] {\n const words = splitWords(value);\n if (words.length === 0) {\n return [\"\"];\n }\n\n const lines: string[] = [];\n let line = \"\";\n\n for (const word of words) {\n if (!line) {\n line = word;\n continue;\n }\n\n if (visibleWidth(line) + 1 + visibleWidth(word) <= width) {\n line += ` ${word}`;\n continue;\n }\n\n lines.push(line);\n line = word;\n }\n\n lines.push(line);\n return lines;\n}\n\nfunction validateLayoutValue(value: number, name: keyof Omit<FormatColumnsOptions, \"rows\">): void {\n if (!Number.isFinite(value) || value < 0) {\n throw new Error(`${name} must be a finite non-negative number.`);\n }\n}\n\nexport function formatColumns(opts: FormatColumnsOptions): string {\n const rows = opts.rows.map((row) => ({\n left: normalizeInline(row.left),\n right: row.right\n }));\n if (rows.length === 0) {\n return \"\";\n }\n\n const totalWidth = opts.totalWidth ?? process.stdout.columns ?? 100;\n const minLeftWidth = opts.minLeftWidth ?? 12;\n const maxLeftWidth = opts.maxLeftWidth ?? 32;\n const gap = opts.gap ?? 3;\n const indent = opts.indent ?? 2;\n validateLayoutValue(totalWidth, \"totalWidth\");\n validateLayoutValue(minLeftWidth, \"minLeftWidth\");\n validateLayoutValue(maxLeftWidth, \"maxLeftWidth\");\n validateLayoutValue(gap, \"gap\");\n validateLayoutValue(indent, \"indent\");\n const maxLeftContentWidth = Math.max(...rows.map((row) => visibleWidth(row.left)));\n const leftWidth = clamp(maxLeftContentWidth + gap, minLeftWidth, maxLeftWidth);\n const rightWidth = Math.max(20, totalWidth - leftWidth - indent);\n const firstIndent = \" \".repeat(indent);\n const continuationIndent = \" \".repeat(indent + leftWidth);\n\n return rows\n .flatMap((row) => {\n if (row.right.length === 0) {\n return [`${firstIndent}${row.left}`];\n }\n\n const rightLines = wrapWords(row.right, rightWidth);\n if (visibleWidth(row.left) > leftWidth) {\n return [\n `${firstIndent}${row.left}`,\n ...rightLines.map((line) => `${continuationIndent}${line}`)\n ];\n }\n const firstLine = `${firstIndent}${padEndVisible(row.left, leftWidth)}${rightLines[0]}`;\n const continuationLines = rightLines\n .slice(1)\n .map((line) => `${continuationIndent}${line}`);\n return [firstLine, ...continuationLines];\n })\n .join(\"\\n\");\n}\n\nexport function formatCommand(name: string, description: string): string {\n return formatColumns({\n rows: [{ left: text.command(name), right: description }]\n });\n}\n\nexport function formatUsage(command: string, args?: string): string {\n const argsStr = args ? ` ${text.argument(args)}` : \"\";\n return `${text.usageCommand(command)}${argsStr}`;\n}\n\nexport function formatOption(flags: string, description: string): string {\n return formatColumns({\n rows: [{ left: text.option(flags), right: description }]\n });\n}\n\nexport function formatCommandList(commands: CommandInfo[]): string {\n return formatColumns({\n rows: commands.map((cmd) => ({\n left: text.command(cmd.name),\n right: cmd.description\n }))\n });\n}\n\nexport function formatOptionList(options: OptionInfo[]): string {\n return formatColumns({\n rows: options.map((opt) => ({\n left: text.option(opt.flags),\n right: opt.description\n }))\n });\n}\n\nexport const helpFormatter = {\n formatColumns,\n formatCommand,\n formatUsage,\n formatOption,\n formatCommandList,\n formatOptionList\n} as const;\n", "import type { ThemePalette } from \"../tokens/colors.js\";\nimport { widths } from \"../tokens/widths.js\";\nimport { resolveOutputFormat } from \"../internal/output-format.js\";\nimport { stripAnsi } from \"../internal/strip-ansi.js\";\n\nexport interface TableColumn {\n name: string;\n title: string;\n alignment: \"left\" | \"right\";\n maxLen: number;\n}\n\nexport interface RenderTableOptions {\n theme: ThemePalette;\n columns: TableColumn[];\n rows: Record<string, string>[];\n variant?: \"table\" | \"detail\";\n maxWidth?: number;\n}\n\ntype TableAlignment = TableColumn[\"alignment\"] | \"center\";\n\ninterface ComputedColumn {\n name: string;\n title: string;\n alignment: TableAlignment;\n width: number;\n}\n\nconst reset = \"\\x1b[0m\";\nconst ellipsis = \"\u2026\";\nconst graphemeSegmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n\nfunction getCell(row: Record<string, string>, name: string): string {\n return Object.prototype.hasOwnProperty.call(row, name) ? row[name] ?? \"\" : \"\";\n}\n\nfunction renderMarkdownCell(value: string): string {\n return stripAnsi(value)\n .replaceAll(\"\\r\\n\", \" \")\n .replaceAll(\"\\n\", \" \")\n .replaceAll(\"\\r\", \" \")\n .replaceAll(\"|\", \"\\\\|\");\n}\n\nfunction isAnsiSequence(value: string, index: number): boolean {\n return value[index] === \"\\u001b\" && value[index + 1] === \"[\";\n}\n\nfunction readAnsiSequence(value: string, index: number): { sequence: string; nextIndex: number } {\n let nextIndex = index + 2;\n while (nextIndex < value.length && value[nextIndex] !== \"m\") {\n nextIndex += 1;\n }\n\n if (nextIndex < value.length) {\n nextIndex += 1;\n }\n\n return { sequence: value.slice(index, nextIndex), nextIndex };\n}\n\nfunction isCombiningCodePoint(codePoint: number): boolean {\n return (\n (codePoint >= 0x0300 && codePoint <= 0x036f) ||\n (codePoint >= 0x1ab0 && codePoint <= 0x1aff) ||\n (codePoint >= 0x1dc0 && codePoint <= 0x1dff) ||\n (codePoint >= 0x20d0 && codePoint <= 0x20ff) ||\n (codePoint >= 0xfe20 && codePoint <= 0xfe2f)\n );\n}\n\nfunction isWideCodePoint(codePoint: number): boolean {\n return (\n (codePoint >= 0x1100 && codePoint <= 0x115f) ||\n codePoint === 0x2329 ||\n codePoint === 0x232a ||\n (codePoint >= 0x2e80 && codePoint <= 0xa4cf && codePoint !== 0x303f) ||\n (codePoint >= 0xac00 && codePoint <= 0xd7a3) ||\n (codePoint >= 0xf900 && codePoint <= 0xfaff) ||\n (codePoint >= 0xfe10 && codePoint <= 0xfe19) ||\n (codePoint >= 0xfe30 && codePoint <= 0xfe6f) ||\n (codePoint >= 0xff00 && codePoint <= 0xff60) ||\n (codePoint >= 0xffe0 && codePoint <= 0xffe6) ||\n (codePoint >= 0x2600 && codePoint <= 0x27bf) ||\n (codePoint >= 0x1f300 && codePoint <= 0x1faff) ||\n (codePoint >= 0x20000 && codePoint <= 0x3fffd)\n );\n}\n\nfunction isEmojiClusterCodePoint(codePoint: number): boolean {\n return (\n (codePoint >= 0x1f1e6 && codePoint <= 0x1f1ff) ||\n (codePoint >= 0x1f300 && codePoint <= 0x1faff) ||\n (codePoint >= 0x2600 && codePoint <= 0x27bf)\n );\n}\n\nfunction codePointWidth(char: string): number {\n const codePoint = char.codePointAt(0) ?? 0;\n\n if (codePoint === 0 || codePoint < 0x20 || (codePoint >= 0x7f && codePoint < 0xa0)) {\n return 0;\n }\n\n if (\n codePoint === 0x200d ||\n (codePoint >= 0xfe00 && codePoint <= 0xfe0f) ||\n isCombiningCodePoint(codePoint)\n ) {\n return 0;\n }\n\n return isWideCodePoint(codePoint) ? 2 : 1;\n}\n\nfunction readPrintableCluster(value: string, index: number): string {\n const nextAnsiIndex = value.indexOf(\"\\u001b[\", index);\n const plainText = value.slice(index, nextAnsiIndex === -1 ? undefined : nextAnsiIndex);\n const firstSegment = graphemeSegmenter.segment(plainText)[Symbol.iterator]().next().value as\n | Intl.SegmentData\n | undefined;\n\n return firstSegment?.segment ?? Array.from(plainText)[0] ?? \"\";\n}\n\nfunction clusterWidth(cluster: string): number {\n const codePoints = Array.from(cluster).map((char) => char.codePointAt(0) ?? 0);\n const isEmojiCluster =\n codePoints.length > 1 &&\n codePoints.some(\n (codePoint) =>\n codePoint === 0x200d ||\n (codePoint >= 0xfe00 && codePoint <= 0xfe0f) ||\n isEmojiClusterCodePoint(codePoint)\n );\n\n if (isEmojiCluster) {\n return 2;\n }\n\n return codePoints.reduce((width, codePoint) => width + codePointWidth(String.fromCodePoint(codePoint)), 0);\n}\n\nfunction displayWidth(value: string): number {\n let width = 0;\n let index = 0;\n\n while (index < value.length) {\n if (isAnsiSequence(value, index)) {\n index = readAnsiSequence(value, index).nextIndex;\n continue;\n }\n\n const cluster = readPrintableCluster(value, index);\n width += clusterWidth(cluster);\n index += cluster.length;\n }\n\n return width;\n}\n\nfunction truncateToWidth(value: string, width: number): string {\n if (displayWidth(value) <= width) {\n return value;\n }\n\n if (width <= 0) {\n return \"\";\n }\n\n const targetWidth = width <= 1 ? 0 : width - displayWidth(ellipsis);\n let output = \"\";\n let currentWidth = 0;\n let index = 0;\n let sawAnsi = false;\n\n while (index < value.length) {\n if (isAnsiSequence(value, index)) {\n const ansi = readAnsiSequence(value, index);\n sawAnsi = true;\n output += ansi.sequence;\n index = ansi.nextIndex;\n continue;\n }\n\n const cluster = readPrintableCluster(value, index);\n const width = clusterWidth(cluster);\n if (currentWidth + width > targetWidth) {\n break;\n }\n\n output += cluster;\n currentWidth += width;\n index += cluster.length;\n }\n\n return `${output}${ellipsis}${sawAnsi ? reset : \"\"}`;\n}\n\nfunction padCell(value: string, width: number, alignment: TableAlignment): string {\n const visibleWidth = displayWidth(value);\n const padding = Math.max(0, width - visibleWidth);\n\n if (alignment === \"right\") {\n return `${\" \".repeat(padding)}${value}`;\n }\n\n if (alignment === \"center\") {\n const left = Math.floor(padding / 2);\n const right = padding - left;\n return `${\" \".repeat(left)}${value}${\" \".repeat(right)}`;\n }\n\n return `${value}${\" \".repeat(padding)}`;\n}\n\nfunction getAlignment(column: TableColumn): TableAlignment {\n const alignment = (column as { alignment: TableAlignment }).alignment;\n return alignment === \"right\" || alignment === \"center\" ? alignment : \"left\";\n}\n\nfunction getColumnWidth(column: TableColumn): number {\n if (!Number.isFinite(column.maxLen) || column.maxLen <= 0) {\n throw new Error(\"maxLen must be a positive finite number.\");\n }\n const configuredMin = (column as { minLen?: number }).minLen;\n const minWidth = Math.max(1, configuredMin ?? 1);\n return Math.max(minWidth, column.maxLen);\n}\n\nfunction computeColumns(columns: TableColumn[]): ComputedColumn[] {\n return columns.map((column) => ({\n name: column.name,\n title: column.title,\n alignment: getAlignment(column),\n width: getColumnWidth(column)\n }));\n}\n\nfunction renderBorder(\n columns: ComputedColumn[],\n theme: ThemePalette,\n parts: { left: string; mid: string; right: string }\n): string {\n const horizontal = theme.muted(\"\u2500\");\n const segments = columns.map((column) => horizontal.repeat(column.width + 2));\n return [\n theme.muted(parts.left),\n segments.join(theme.muted(parts.mid)),\n theme.muted(parts.right)\n ].join(\"\");\n}\n\nfunction renderTerminalRow(values: string[], columns: ComputedColumn[], theme: ThemePalette): string {\n const vertical = theme.muted(\"\u2502\");\n const cells = values.map((value, index) => {\n const column = columns[index]!;\n const truncated = truncateToWidth(value, column.width);\n return ` ${padCell(truncated, column.width, column.alignment)} `;\n });\n\n return `${vertical}${cells.join(vertical)}${vertical}`;\n}\n\nfunction wrapDetailValue(value: string, width: number): string[] {\n const lines: string[] = [];\n\n for (const paragraph of value.split(\"\\n\")) {\n let line = \"\";\n\n for (const rawWord of paragraph.split(\" \")) {\n const words: string[] = [];\n let word = rawWord;\n\n while (displayWidth(word) > width) {\n let chunk = \"\";\n let index = 0;\n\n while (index < word.length) {\n const cluster = readPrintableCluster(word, index);\n if (displayWidth(`${chunk}${cluster}`) > width) {\n break;\n }\n chunk += cluster;\n index += cluster.length;\n }\n\n words.push(chunk);\n word = word.slice(chunk.length);\n }\n\n words.push(word);\n\n for (const word of words) {\n if (line.length === 0) {\n line = word;\n continue;\n }\n\n if (displayWidth(`${line} ${word}`) <= width) {\n line = `${line} ${word}`;\n continue;\n }\n\n lines.push(line);\n line = word;\n }\n }\n\n lines.push(line);\n }\n\n return lines.length > 0 ? lines : [\"\"];\n}\n\nfunction renderTableTerminal(options: RenderTableOptions): string {\n const { theme, columns, rows } = options;\n const computedColumns = computeColumns(columns);\n if (options.variant === \"detail\") {\n const labelColumn = computedColumns[0];\n const valueColumn = computedColumns[1];\n if (!labelColumn || !valueColumn) {\n return \"\";\n }\n\n const detailLabelWidth = widths.helpColumn + 12;\n const labelWidth = Math.min(labelColumn.width, detailLabelWidth);\n const valueWidth = Math.max(20, (options.maxWidth ?? widths.maxLine) - labelWidth - 2);\n const continuation = \" \".repeat(labelWidth + 2);\n\n return rows\n .flatMap((row) => {\n const label = truncateToWidth(getCell(row, labelColumn.name), labelWidth);\n const values = wrapDetailValue(getCell(row, valueColumn.name), valueWidth);\n if (values.length === 1 && values[0] === \"\") {\n return [theme.header(label)];\n }\n return [\n `${theme.muted(padCell(label, labelWidth, \"left\"))} ${values[0] ?? \"\"}`,\n ...values.slice(1).map((value) => `${continuation}${value}`)\n ];\n })\n .join(\"\\n\");\n }\n\n const separatorOptions = options as { rowSeparator?: boolean; rowSeparators?: boolean };\n const includeRowSeparators =\n separatorOptions.rowSeparator === true || separatorOptions.rowSeparators === true;\n\n const top = renderBorder(computedColumns, theme, { left: \"\u250C\", mid: \"\u252C\", right: \"\u2510\" });\n const header = renderTerminalRow(\n computedColumns.map((column) => theme.header(column.title)),\n computedColumns,\n theme\n );\n const headerBottom = renderBorder(computedColumns, theme, { left: \"\u251C\", mid: \"\u253C\", right: \"\u2524\" });\n const bottom = renderBorder(computedColumns, theme, { left: \"\u2514\", mid: \"\u2534\", right: \"\u2518\" });\n\n const renderedRows: string[] = [];\n for (const [index, row] of rows.entries()) {\n if (includeRowSeparators && index > 0) {\n renderedRows.push(headerBottom);\n }\n renderedRows.push(\n renderTerminalRow(\n computedColumns.map((column) => getCell(row, column.name)),\n computedColumns,\n theme\n )\n );\n }\n\n return [top, header, headerBottom, ...renderedRows, bottom].join(\"\\n\");\n}\n\nfunction renderTableMarkdown(options: RenderTableOptions): string {\n const { columns, rows } = options;\n\n const header = `| ${columns.map((c) => renderMarkdownCell(c.title)).join(\" | \")} |`;\n const separator = `| ${columns\n .map((c) => {\n const alignment = getAlignment(c);\n if (alignment === \"right\") {\n return \"---:\";\n }\n if (alignment === \"center\") {\n return \":---:\";\n }\n return \":---\";\n })\n .join(\" | \")} |`;\n\n const dataRows = rows.map(\n (row) =>\n `| ${columns.map((c) => renderMarkdownCell(getCell(row, c.name))).join(\" | \")} |`\n );\n\n return [header, separator, ...dataRows].join(\"\\n\");\n}\n\nfunction renderTableJson(options: RenderTableOptions): string {\n const { columns, rows } = options;\n\n const cleaned = rows.map((row) => {\n const obj = Object.create(null) as Record<string, string>;\n for (const col of columns) {\n obj[col.name] = stripAnsi(getCell(row, col.name));\n }\n return obj;\n });\n\n return JSON.stringify(cleaned, null, 2);\n}\n\nexport function renderTable(options: RenderTableOptions): string {\n const format = resolveOutputFormat();\n switch (format) {\n case \"markdown\":\n return renderTableMarkdown(options);\n case \"json\":\n return renderTableJson(options);\n default:\n return renderTableTerminal(options);\n }\n}\n", "import { spawn } from \"node:child_process\";\nimport process from \"node:process\";\n\ninterface BrowserProcess {\n once(event: \"error\", listener: (error: Error) => void): this;\n once(event: \"close\", listener: (code: number | null, signal: NodeJS.Signals | null) => void): this;\n unref(): void;\n}\n\ntype SpawnBrowserProcess = (\n command: string,\n args: string[],\n options: { detached: true; stdio: \"ignore\" }\n) => BrowserProcess;\n\nexport interface OpenExternalOptions {\n platform?: NodeJS.Platform;\n spawnProcess?: SpawnBrowserProcess;\n}\n\nexport async function openExternal(url: string, options: OpenExternalOptions = {}): Promise<void> {\n const parsed = new URL(url);\n const { command, args } = browserCommand(parsed.href, options.platform ?? process.platform);\n await launchBrowser(command, args, options.spawnProcess ?? spawn);\n}\n\nfunction browserCommand(url: string, platform: NodeJS.Platform): { command: string; args: string[] } {\n if (platform === \"darwin\") {\n return { command: \"open\", args: [url] };\n }\n\n if (platform === \"win32\") {\n return { command: \"cmd\", args: [\"/c\", \"start\", \"\", url] };\n }\n\n return { command: \"xdg-open\", args: [url] };\n}\n\nfunction launchBrowser(\n command: string,\n args: string[],\n spawnProcess: SpawnBrowserProcess\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawnProcess(command, args, { detached: true, stdio: \"ignore\" });\n\n child.once(\"error\", reject);\n child.once(\"close\", (code, signal) => {\n if (code !== 0) {\n const reason = code === null ? `signal ${signal ?? \"unknown\"}` : `code ${code}`;\n reject(new Error(`Browser launcher exited with ${reason}`));\n return;\n }\n\n child.unref();\n resolve();\n });\n });\n}\n", "import { AsyncLocalStorage } from \"node:async_hooks\";\n\nexport type AcpLineWriter = (line: string) => void;\n\nconst storage = new AsyncLocalStorage<AcpLineWriter>();\n\nconst defaultWriter: AcpLineWriter = (line) => {\n process.stdout.write(`${line}\\n`);\n};\n\n/**\n * Return the writer active in the current async context, or the default\n * stdout writer if none is bound.\n */\nexport function getAcpWriter(): AcpLineWriter {\n return storage.getStore() ?? defaultWriter;\n}\n\n/**\n * Run `fn` with `writer` bound as the active ACP line writer. All calls to\n * `renderAgentMessage`, `renderToolStart`, `renderAcpEvent`, etc. made inside\n * `fn` (or async work awaited from `fn`) will go through `writer` instead of\n * writing to `process.stdout`.\n */\nexport function withAcpWriter<T>(writer: AcpLineWriter, fn: () => Promise<T>): Promise<T> {\n return storage.run(writer, fn);\n}\n", "const graphemeSegmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n\nexport function graphemes(value: string): string[] {\n return Array.from(graphemeSegmenter.segment(value), ({ segment }) => segment);\n}\n\nexport function displayWidth(value: string, startColumn = 0): number {\n let column = startColumn;\n\n for (const segment of graphemes(value)) {\n if (segment === \"\\t\") {\n column += 8 - (column % 8);\n continue;\n }\n\n column += graphemeWidth(segment);\n }\n\n return column - startColumn;\n}\n\nexport function expandTabs(value: string, startColumn = 0): string {\n let column = startColumn;\n let expanded = \"\";\n\n for (const segment of graphemes(value)) {\n if (segment === \"\\t\") {\n const spaces = 8 - (column % 8);\n expanded += \" \".repeat(spaces);\n column += spaces;\n continue;\n }\n\n expanded += segment;\n column += graphemeWidth(segment);\n }\n\n return expanded;\n}\n\nexport function graphemeWidth(segment: string): number {\n const codePoint = segment.codePointAt(0);\n\n if (codePoint === undefined || isZeroWidthCodePoint(codePoint)) {\n return 0;\n }\n\n return isWideCodePoint(codePoint) || isFlagSegment(segment) ? 2 : 1;\n}\n\nfunction isZeroWidthCodePoint(codePoint: number): boolean {\n return (codePoint >= 0x0300 && codePoint <= 0x036f)\n || (codePoint >= 0x1ab0 && codePoint <= 0x1aff)\n || (codePoint >= 0x1dc0 && codePoint <= 0x1dff)\n || (codePoint >= 0x20d0 && codePoint <= 0x20ff)\n || (codePoint >= 0xfe20 && codePoint <= 0xfe2f);\n}\n\nfunction isFlagSegment(segment: string): boolean {\n const codePoints = [...segment].map((character) => character.codePointAt(0));\n return codePoints.length === 2\n && codePoints.every(\n (codePoint) => codePoint !== undefined && codePoint >= 0x1f1e6 && codePoint <= 0x1f1ff\n );\n}\n\nfunction isWideCodePoint(codePoint: number): boolean {\n return (\n (codePoint >= 0x1100 && codePoint <= 0x115f)\n || codePoint === 0x2329\n || codePoint === 0x232a\n || (codePoint >= 0x2e80 && codePoint <= 0x303e)\n || (codePoint >= 0x3041 && codePoint <= 0x33bf)\n || (codePoint >= 0x3400 && codePoint <= 0x4dbf)\n || (codePoint >= 0x4e00 && codePoint <= 0xa4cf)\n || (codePoint >= 0xa960 && codePoint <= 0xa97f)\n || (codePoint >= 0xac00 && codePoint <= 0xd7af)\n || (codePoint >= 0xf900 && codePoint <= 0xfaff)\n || (codePoint >= 0xfe10 && codePoint <= 0xfe19)\n || (codePoint >= 0xfe30 && codePoint <= 0xfe6f)\n || (codePoint >= 0xff00 && codePoint <= 0xff60)\n || (codePoint >= 0xffe0 && codePoint <= 0xffe6)\n || (codePoint >= 0x1b000 && codePoint <= 0x1b0ff)\n || codePoint === 0x1f004\n || codePoint === 0x1f0cf\n || (codePoint >= 0x1f200 && codePoint <= 0x1fffd)\n || (codePoint >= 0x20000 && codePoint <= 0x2fffd)\n || (codePoint >= 0x30000 && codePoint <= 0x3fffd)\n );\n}\n", "import readline from \"node:readline\";\nimport { PassThrough } from \"node:stream\";\nimport { cellToAnsi } from \"./buffer.js\";\nimport type { Cell } from \"./types.js\";\n\nexport type KeypressEvent = {\n name?: string;\n ch?: string;\n ctrl: boolean;\n meta: boolean;\n shift: boolean;\n};\n\nexport type TerminalDriver = {\n enterRawMode(): void;\n exitRawMode(): void;\n enterAltScreen(): void;\n exitAltScreen(): void;\n disableLineWrap(): void;\n enableLineWrap(): void;\n hideCursor(): void;\n showCursor(): void;\n moveTo(x: number, y: number): void;\n write(text: string): void;\n flush(changes: Array<{ x: number; y: number; cell: Cell }>): void;\n getSize(): { cols: number; rows: number };\n onResize(handler: () => void): () => void;\n onKeypress(handler: (key: KeypressEvent) => void): () => void;\n destroy(): void;\n};\n\ntype ReadlineKey = {\n sequence?: string;\n name?: string;\n ctrl?: boolean;\n meta?: boolean;\n shift?: boolean;\n};\n\ntype KeypressInput = NodeJS.ReadableStream & {\n on(event: \"keypress\", listener: (str: string | undefined, key: ReadlineKey) => void): KeypressInput;\n off(event: \"keypress\", listener: (str: string | undefined, key: ReadlineKey) => void): KeypressInput;\n};\n\ntype TerminalInput = NodeJS.ReadStream & KeypressInput & {\n setRawMode?: (mode: boolean) => void;\n};\n\ntype TerminalOutput = NodeJS.WriteStream & {\n columns?: number;\n rows?: number;\n on(event: \"resize\", listener: () => void): TerminalOutput;\n off(event: \"resize\", listener: () => void): TerminalOutput;\n};\n\nexport function createTerminalDriver(opts?: {\n stdin?: NodeJS.ReadStream;\n stdout?: NodeJS.WriteStream;\n}): TerminalDriver {\n const stdin = (opts?.stdin ?? process.stdin) as TerminalInput;\n const stdout = (opts?.stdout ?? process.stdout) as TerminalOutput;\n const resizeListeners = new Set<() => void>();\n const keypressListeners = new Set<(str: string | undefined, key: ReadlineKey) => void>();\n let rawMode = false;\n let altScreen = false;\n let lineWrapEnabled = true;\n let cursorHidden = false;\n let destroyed = false;\n\n readline.emitKeypressEvents(stdin);\n\n function enterRawMode(): void {\n if (destroyed || rawMode) {\n return;\n }\n\n stdin.setRawMode?.(true);\n stdin.resume();\n rawMode = true;\n }\n\n function exitRawMode(): void {\n if (destroyed || !rawMode) {\n return;\n }\n\n stdin.setRawMode?.(false);\n stdin.pause();\n rawMode = false;\n }\n\n function enterAltScreen(): void {\n if (destroyed || altScreen) {\n return;\n }\n\n write(\"\\u001b[?1049h\");\n altScreen = true;\n }\n\n function exitAltScreen(): void {\n if (destroyed || !altScreen) {\n return;\n }\n\n write(\"\\u001b[?1049l\");\n altScreen = false;\n }\n\n function disableLineWrap(): void {\n if (destroyed || !lineWrapEnabled) {\n return;\n }\n\n write(\"\\u001b[?7l\");\n lineWrapEnabled = false;\n }\n\n function enableLineWrap(): void {\n if (destroyed || lineWrapEnabled) {\n return;\n }\n\n write(\"\\u001b[?7h\");\n lineWrapEnabled = true;\n }\n\n function hideCursor(): void {\n if (destroyed || cursorHidden) {\n return;\n }\n\n write(\"\\u001b[?25l\");\n cursorHidden = true;\n }\n\n function showCursor(): void {\n if (destroyed || !cursorHidden) {\n return;\n }\n\n write(\"\\u001b[?25h\");\n cursorHidden = false;\n }\n\n function moveTo(x: number, y: number): void {\n if (destroyed) {\n return;\n }\n\n write(cursorPositionAnsi(x, y));\n }\n\n function write(text: string): void {\n if (destroyed || text.length === 0) {\n return;\n }\n\n stdout.write(text);\n }\n\n function flush(changes: Array<{ x: number; y: number; cell: Cell }>): void {\n if (destroyed || changes.length === 0) {\n return;\n }\n\n let output = \"\";\n\n for (const change of changes) {\n output += `${cursorPositionAnsi(change.x, change.y)}${cellToAnsi(change.cell)}`;\n }\n\n write(output);\n }\n\n function getSize(): { cols: number; rows: number } {\n return {\n cols: normalizeSize(stdout.columns),\n rows: normalizeSize(stdout.rows)\n };\n }\n\n function onResize(handler: () => void): () => void {\n if (destroyed) {\n return () => {};\n }\n\n const listener = () => {\n handler();\n };\n\n resizeListeners.add(listener);\n stdout.on(\"resize\", listener);\n\n return () => {\n if (!resizeListeners.delete(listener)) {\n return;\n }\n\n stdout.off(\"resize\", listener);\n };\n }\n\n function onKeypress(handler: (key: KeypressEvent) => void): () => void {\n if (destroyed) {\n return () => {};\n }\n\n const listener = (str: string | undefined, key: ReadlineKey) => {\n const event = toKeypressEvent(str, key);\n if (event !== undefined) {\n handler(event);\n }\n };\n\n keypressListeners.add(listener);\n stdin.on(\"keypress\", listener);\n\n return () => {\n if (!keypressListeners.delete(listener)) {\n return;\n }\n\n stdin.off(\"keypress\", listener);\n };\n }\n\n function destroy(): void {\n if (destroyed) {\n return;\n }\n\n for (const listener of keypressListeners) {\n stdin.off(\"keypress\", listener);\n }\n keypressListeners.clear();\n\n for (const listener of resizeListeners) {\n stdout.off(\"resize\", listener);\n }\n resizeListeners.clear();\n\n exitRawMode();\n enableLineWrap();\n exitAltScreen();\n showCursor();\n destroyed = true;\n }\n\n return {\n enterRawMode,\n exitRawMode,\n enterAltScreen,\n exitAltScreen,\n disableLineWrap,\n enableLineWrap,\n hideCursor,\n showCursor,\n moveTo,\n write,\n flush,\n getSize,\n onResize,\n onKeypress,\n destroy\n };\n}\n\nexport function parseKeypress(data: Buffer): KeypressEvent | undefined {\n if (data.length === 0) {\n return undefined;\n }\n\n const stream = new PassThrough();\n const stdin = stream as unknown as KeypressInput;\n let event: KeypressEvent | undefined;\n\n readline.emitKeypressEvents(stdin);\n stdin.on(\"keypress\", (str, key) => {\n event = toKeypressEvent(str, key);\n });\n stream.emit(\"data\", data);\n stream.destroy();\n\n return event;\n}\n\nfunction toKeypressEvent(str: string | undefined, key: ReadlineKey | undefined): KeypressEvent | undefined {\n const controlCharacter = controlCharacterToKeypress(key?.sequence);\n if (controlCharacter !== undefined) {\n return controlCharacter;\n }\n\n const ctrl = key?.ctrl ?? false;\n const meta = key?.meta ?? false;\n const shift = key?.shift ?? false;\n const ch = extractPrintableCharacter(str, key?.sequence);\n\n if (ch !== undefined) {\n return { ch, ctrl, meta, shift };\n }\n\n if (key?.name === undefined) {\n return undefined;\n }\n\n return {\n name: key.name,\n ctrl,\n meta,\n shift\n };\n}\n\nfunction extractPrintableCharacter(str: string | undefined, sequence: string | undefined): string | undefined {\n if (isPrintableCharacter(str)) {\n return str;\n }\n\n if (isSinglePrintableSequence(sequence)) {\n return sequence;\n }\n\n if (sequence === undefined || sequence.length <= 1 || sequence[0] !== \"\\u001b\") {\n return undefined;\n }\n\n const candidate = sequence.slice(1);\n return isPrintableCharacter(candidate) ? candidate : undefined;\n}\n\nfunction isSinglePrintableSequence(value: string | undefined): boolean {\n if (value === undefined || Array.from(value).length !== 1) {\n return false;\n }\n\n const codePoint = value.codePointAt(0);\n return codePoint !== undefined && codePoint >= 0x20 && codePoint !== 0x7f;\n}\n\nfunction isPrintableCharacter(value: string | undefined): value is string {\n if (value === undefined || Array.from(value).length !== 1) {\n return false;\n }\n\n const codePoint = value.codePointAt(0);\n return codePoint !== undefined && codePoint >= 0x20 && codePoint !== 0x7f;\n}\n\nfunction controlCharacterToKeypress(sequence: string | undefined): KeypressEvent | undefined {\n if (sequence === \"\\u001f\") {\n return { ch: \"/\", ctrl: true, meta: false, shift: false };\n }\n\n if (sequence !== undefined && sequence.length === 1) {\n const code = sequence.charCodeAt(0);\n if (code >= 1 && code <= 26 && code !== 9 && code !== 10 && code !== 13) {\n return {\n name: String.fromCharCode(code + 96),\n ctrl: true,\n meta: false,\n shift: false\n };\n }\n }\n\n return undefined;\n}\n\nfunction cursorPositionAnsi(x: number, y: number): string {\n return `\\u001b[${normalizeCoordinate(y) + 1};${normalizeCoordinate(x) + 1}H`;\n}\n\nfunction normalizeCoordinate(value: number): number {\n return Math.max(0, Math.floor(value));\n}\n\nfunction normalizeSize(value: number | undefined): number {\n if (value === undefined || !Number.isFinite(value)) {\n return 0;\n }\n\n return Math.max(0, Math.floor(value));\n}\n", "import { resolveBindings, type ResolvedBindings } from \"./keymap.js\";\n\nexport type Tone = \"success\" | \"warning\" | \"error\" | \"info\" | \"muted\";\n\nexport interface Row {\n id: string;\n title: string;\n subtitle?: string;\n badge?: { text: string; tone?: Tone };\n group?: string; // grouped rendering; rows with same group cluster under a header\n}\n\nexport interface DetailItem {\n id: string;\n title?: string; // absent => item fills pane with no cursor / no selection chrome\n subtitle?: string;\n badge?: { text: string; tone?: Tone };\n render: (ctx: DetailCtx) => string | Promise<string>;\n renderedContent?: string;\n}\n\nexport interface Detail<R> {\n items: (row: Row, ctx: DetailCtx) => Promise<DetailItem[]>;\n actions?: Action<R>[]; // run against the focused detail item\n}\n\nexport interface DetailCtx { width: number; height: number; signal: AbortSignal; row: Row }\n\nexport interface Action<R> {\n id: string;\n label: string | (() => string); // function form re-evaluated when state changes\n key?: string | string[];\n predicate?: (ctx: ActionContext<R>) => boolean;\n handler: (ctx: ActionContext<R>) => void | Promise<void>;\n destructive?: boolean;\n primary?: boolean; // bound to Enter\n showInFooter?: boolean; // default true\n}\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport interface ActionContext<R> {\n row: Row; // currently highlighted left-pane row\n rows: Row[]; // multi-select; falls back to [row] if no selection\n item?: DetailItem; // populated for actions declared under detail.actions\n filter: string;\n refresh: () => Promise<void>;\n suspendAnd: <T>(fn: () => Promise<T>) => Promise<T>;\n toast: (msg: string, tone?: Tone) => void;\n confirm: (prompt: string) => Promise<boolean>;\n exit: (after?: () => void | Promise<void>) => void;\n}\n\nexport interface ReorderContext {\n refresh: () => Promise<void>;\n toast: (msg: string, tone?: Tone) => void;\n}\n\nexport interface ExplorerConfig<R> {\n title: string;\n rows: () => Promise<Row[]>;\n refresh?: () => Promise<void>;\n detail: Detail<R>;\n actions: Action<R>[];\n reorder?: { onReorder: (orderedIds: string[], ctx?: ReorderContext) => void | Promise<void> };\n multiSelect?: boolean;\n keybindOverrides?: Record<string, string | string[]>;\n emptyHint?: string;\n initialFilter?: string;\n}\n\nexport const REGION_HEADER = 1 << 0;\nexport const REGION_LIST = 1 << 1;\nexport const REGION_DETAIL = 1 << 2;\nexport const REGION_FOOTER = 1 << 3;\nexport const REGION_MODAL = 1 << 4;\nexport const REGION_TOAST = 1 << 5;\nexport const REGION_ALL =\n REGION_HEADER |\n REGION_LIST |\n REGION_DETAIL |\n REGION_FOOTER |\n REGION_MODAL |\n REGION_TOAST;\n\nexport type Dirty = number;\n\nexport type ExplorerLayoutMode =\n | \"wide\"\n | \"medium\"\n | \"narrow-vertical\"\n | \"narrow-list-only\"\n | \"too-narrow\";\n\nexport interface ExplorerSize {\n cols: number;\n rows: number;\n}\n\nexport interface ExplorerState {\n title: string;\n emptyHint: string;\n rows: Row[];\n filtered: number[];\n matchPositions: Map<number, number[]>;\n cursor: number;\n filter: string;\n filterFocused: boolean;\n focused: \"list\" | \"detail\";\n detail: {\n rowId: string | null;\n items: DetailItem[] | null;\n cursor: number;\n scroll: number;\n token: number;\n loading: boolean;\n };\n selected: Set<string>;\n multiSelect: boolean;\n modal:\n | null\n | { kind: \"help\" }\n | { kind: \"confirm\"; action: Action<unknown>; rows: Row[]; resolver: (ok: boolean) => void }\n | { kind: \"palette\"; query: string; cursor: number };\n toast: { message: string; tone: Tone; expiresAt: number } | null;\n dirty: Dirty;\n size: ExplorerSize;\n layout: ExplorerLayoutMode;\n bindings: ResolvedBindings;\n actionState: Map<string, ActionStateEntry>;\n}\n\nexport interface ActionStateEntry {\n available: boolean;\n label: string;\n running?: boolean;\n action?: Action<unknown>;\n source?: \"row\" | \"detail\";\n}\n\nexport function createInitialState<R>(\n config: ExplorerConfig<R>,\n size: ExplorerSize\n): ExplorerState {\n const normalizedSize = {\n cols: normalizeSize(size.cols),\n rows: normalizeSize(size.rows)\n };\n const multiSelect = config.multiSelect ?? true;\n\n return {\n title: config.title,\n emptyHint: config.emptyHint ?? \"No detail\",\n rows: [],\n filtered: [],\n matchPositions: new Map(),\n cursor: 0,\n filter: config.initialFilter ?? \"\",\n filterFocused: false,\n focused: \"list\",\n detail: {\n rowId: null,\n items: null,\n cursor: 0,\n scroll: 0,\n token: 0,\n loading: false\n },\n selected: new Set(),\n multiSelect,\n modal: null,\n toast: null,\n dirty: REGION_ALL,\n size: normalizedSize,\n layout: resolveExplorerLayoutMode(normalizedSize.cols),\n bindings: resolveBindings(config),\n actionState: createInitialActionState(config)\n };\n}\n\nfunction createInitialActionState<R>(\n config: ExplorerConfig<R>\n): Map<string, ActionStateEntry> {\n const state = new Map<string, ActionStateEntry>();\n\n for (const [source, actions] of [[\"row\", config.actions], [\"detail\", config.detail.actions ?? []]] as const) {\n for (const action of actions) {\n if (state.has(action.id)) {\n throw new Error(`Duplicate explorer action id: ${action.id}`);\n }\n\n state.set(action.id, {\n available: true,\n label: typeof action.label === \"function\" ? action.id : action.label,\n action: action as Action<unknown>,\n source\n });\n }\n }\n\n return state;\n}\n\nexport function resolveExplorerLayoutMode(cols: number): ExplorerLayoutMode {\n if (cols < 40) {\n return \"too-narrow\";\n }\n\n if (cols < 80) {\n return \"narrow-list-only\";\n }\n\n if (cols < 100) {\n return \"narrow-vertical\";\n }\n\n if (cols < 120) {\n return \"medium\";\n }\n\n return \"wide\";\n}\n\nfunction normalizeSize(value: number): number {\n if (!Number.isFinite(value)) {\n return 0;\n }\n\n return Math.max(0, Math.floor(value));\n}\n", "import { color } from \"../components/color.js\";\nimport * as clack from \"@clack/prompts\";\nimport { resolveOutputFormat } from \"../internal/output-format.js\";\nimport { stripAnsi } from \"../internal/strip-ansi.js\";\nimport { cancel, isCancel } from \"./primitives/cancel.js\";\nimport { intro } from \"./primitives/intro.js\";\nimport { log } from \"./primitives/log.js\";\nimport { note } from \"./primitives/note.js\";\nimport { outro } from \"./primitives/outro.js\";\nimport { spinner } from \"./primitives/spinner.js\";\n\nexport { isCancel, cancel, log };\nexport { intro, outro, note, spinner };\n\nexport function introPlain(title: string): void {\n const format = resolveOutputFormat();\n if (format === \"markdown\") {\n process.stdout.write(`# ${stripAnsi(title)}\\n\\n`);\n return;\n }\n if (format === \"json\") {\n return;\n }\n process.stdout.write(`${color.gray(\"\u250C\")} ${title}\\n`);\n}\n\nexport interface SelectOptions<Value> {\n message: string;\n options: Array<{ value: Value; label: string; hint?: string }>;\n initialValue?: Value;\n}\n\nexport async function select<Value>(opts: SelectOptions<Value>): Promise<Value | symbol> {\n return clack.select(opts as Parameters<typeof clack.select<Value>>[0]);\n}\n\nexport type MultiselectOptions<Value> = Parameters<typeof clack.multiselect<Value>>[0];\n\n/**\n * Prompts the user to select one or more values from a list.\n *\n * Returns the selected values as an array, or a cancellation symbol if the\n * user cancels. Use `isCancel` to check for cancellation.\n *\n * @example\n * const result = await multiselect({\n * message: \"Pick workflows to run\",\n * options: [{ label: \"Fix Vulnerabilities\", value: \"fix-vulnerabilities\" }],\n * required: true\n * });\n * if (!isCancel(result)) {\n * // result is Value[]\n * }\n */\nexport async function multiselect<Value>(\n opts: MultiselectOptions<Value>\n): Promise<Value[] | symbol> {\n return clack.multiselect(opts);\n}\n\nexport type TextOptions = Parameters<typeof clack.text>[0];\n\nexport async function text(opts: TextOptions): Promise<string | symbol> {\n return clack.text(opts as Parameters<typeof clack.text>[0]);\n}\n\nexport interface ConfirmOptions {\n message: string;\n initialValue?: boolean;\n}\n\nexport async function confirm(opts: ConfirmOptions): Promise<boolean | symbol> {\n return clack.confirm(opts as Parameters<typeof clack.confirm>[0]);\n}\n\nexport class PromptCancelledError extends Error {\n constructor(message = \"Operation cancelled.\") {\n super(message);\n this.name = \"PromptCancelledError\";\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n}\n\nexport async function confirmOrCancel(opts: ConfirmOptions): Promise<boolean> {\n const result = await confirm(opts);\n if (isCancel(result)) {\n cancel(\"Operation cancelled.\");\n throw new PromptCancelledError();\n }\n return result === true;\n}\n\nexport interface PasswordOptions {\n message: string;\n validate?: (value: string) => string | undefined;\n}\n\nexport async function password(opts: PasswordOptions): Promise<string | symbol> {\n return clack.password(opts as Parameters<typeof clack.password>[0]);\n}\n\nexport type SpinnerOptions = {\n start: (message?: string) => void;\n stop: (message?: string, code?: number) => void;\n message: (message?: string) => void;\n};\n\nexport interface WithSpinnerOptions<T> {\n message: string | (() => string);\n fn: () => Promise<T>;\n stopMessage?: (result: T) => string;\n subtext?: (result: T) => string | undefined;\n}\n\nfunction formatElapsed(ms: number): string {\n const totalSeconds = Math.floor(ms / 1000);\n if (totalSeconds < 60) {\n return `${totalSeconds}s`;\n }\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = totalSeconds % 60;\n return `${minutes}m ${seconds}s`;\n}\n\nexport async function withSpinner<T>(options: WithSpinnerOptions<T>): Promise<T> {\n const { message, fn, stopMessage, subtext } = options;\n const readMessage = () => (typeof message === \"function\" ? message() : message);\n\n if (resolveOutputFormat() === \"json\") {\n const result = await fn();\n const sub = subtext ? subtext(result) : undefined;\n if (sub) {\n process.stdout.write(sub + \"\\n\");\n }\n return result;\n }\n\n const noSpinner = process.env.POE_NO_SPINNER === \"1\";\n const isTTY = process.stdout.isTTY;\n\n if (noSpinner || !isTTY) {\n const result = await fn();\n const msg = stopMessage ? stopMessage(result) : undefined;\n if (msg) {\n process.stdout.write(`\\x1b[32m\u25C6\\x1b[0m ${msg}\\n`);\n }\n const sub = subtext ? subtext(result) : undefined;\n if (sub) {\n for (const line of sub.split(\"\\n\")) {\n process.stdout.write(`\\x1b[90m\u2502\\x1b[0m ${line}\\n`);\n }\n }\n return result;\n }\n\n const s = spinner();\n const start = Date.now();\n s.start(readMessage());\n\n const timer = setInterval(() => {\n s.message(`${readMessage()} [${formatElapsed(Date.now() - start)}]`);\n }, 1000);\n\n try {\n const result = await fn();\n clearInterval(timer);\n const elapsed = formatElapsed(Date.now() - start);\n const msg = stopMessage ? stopMessage(result) : undefined;\n s.stop(msg ? `${msg} [${elapsed}]` : `Done [${elapsed}]`);\n\n const sub = subtext ? subtext(result) : undefined;\n if (sub) {\n for (const line of sub.split(\"\\n\")) {\n process.stdout.write(`\\x1b[90m\u2502\\x1b[0m ${line}\\n`);\n }\n }\n\n return result;\n } catch (error) {\n clearInterval(timer);\n s.stop(\"\", 1);\n throw error;\n }\n}\n", "import { color } from \"../../components/color.js\";\nexport { isCancel } from \"@clack/prompts\";\nimport { resolveOutputFormat } from \"../../internal/output-format.js\";\n\nexport function cancel(msg = \"\"): void {\n if (resolveOutputFormat() !== \"terminal\") {\n return;\n }\n\n process.stdout.write(`${color.gray(\"\u2514\")} ${color.red(msg)}\\n\\n`);\n}\n", "import { color } from \"../components/color.js\";\nimport { symbols } from \"../components/symbols.js\";\nimport { resolveOutputFormat } from \"../internal/output-format.js\";\n\nexport const SPINNER_FRAMES = Object.freeze([\"\u25D2\", \"\u25D0\", \"\u25D3\", \"\u25D1\"] as const);\n\nexport interface SpinnerFrameOptions {\n frame?: number;\n message: string;\n timer?: string;\n}\n\nexport function renderSpinnerFrame(options: SpinnerFrameOptions): string {\n const format = resolveOutputFormat();\n\n if (format === \"markdown\") {\n return `- ${options.message}${options.timer ? ` [${options.timer}]` : \"\"}...\\n`;\n }\n\n if (format === \"json\") {\n return `${JSON.stringify({\n type: \"spinner\",\n state: \"running\",\n message: options.message,\n ...(options.timer ? { timer: options.timer } : {})\n })}\\n`;\n }\n\n const frame = options.frame ?? 0;\n const index = ((frame % SPINNER_FRAMES.length) + SPINNER_FRAMES.length) % SPINNER_FRAMES.length;\n const spinnerChar = color.magenta(SPINNER_FRAMES[index]);\n const timerSuffix = options.timer ? color.dim(` [${options.timer}]`) : \"\";\n const bar = color.gray(symbols.bar);\n\n return `${spinnerChar} ${options.message}${timerSuffix}\\n${bar}`;\n}\n\nexport interface SpinnerStoppedOptions {\n message: string;\n code?: number;\n timer?: string;\n subtext?: string;\n}\n\nfunction renderMarkdownInline(value: string): string {\n return value.replaceAll(\"\\r\\n\", \" \").replaceAll(\"\\n\", \" \").replaceAll(\"\\r\", \" \");\n}\n\nexport function renderSpinnerStopped(options: SpinnerStoppedOptions): string {\n const format = resolveOutputFormat();\n\n if (format === \"markdown\") {\n return `- ${renderMarkdownInline(options.message)}${options.timer ? ` [${renderMarkdownInline(options.timer)}]` : \"\"}\\n`;\n }\n\n if (format === \"json\") {\n return `${JSON.stringify({\n type: \"spinner\",\n state: \"stopped\",\n message: options.message,\n code: options.code ?? 0,\n ...(options.timer ? { timer: options.timer } : {}),\n ...(options.subtext ? { subtext: options.subtext } : {})\n })}\\n`;\n }\n\n const code = options.code ?? 0;\n const symbol = code === 0 ? color.green(\"\u25C6\") : color.red(\"\u25A0\");\n const timerSuffix = options.timer ? color.dim(` [${options.timer}]`) : \"\";\n const bar = color.gray(symbols.bar);\n\n let output = `${symbol} ${options.message}${timerSuffix}`;\n if (options.subtext) {\n output += `\\n${bar} ${color.dim(options.subtext)}`;\n }\n return output;\n}\n", "import * as jsonc from \"jsonc-parser\";\nimport type { ConfigFormat, ConfigObject, ConfigValue } from \"../types.js\";\nimport { cloneConfigObject, hasConfigEntry, setConfigEntry } from \"./object.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 cloneConfigObject(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 = cloneConfigObject(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 setConfigEntry(result, key, merge(existing, value));\n continue;\n }\n setConfigEntry(result, key, value as ConfigValue);\n }\n return result;\n}\n\nfunction configValuesEqual(left: ConfigValue | undefined, right: ConfigValue | undefined): boolean {\n return JSON.stringify(left) === JSON.stringify(right);\n}\n\nfunction prune(\n obj: ConfigObject,\n shape: ConfigObject\n): { changed: boolean; result: ConfigObject } {\n let changed = false;\n const result = cloneConfigObject(obj);\n\n for (const [key, pattern] of Object.entries(shape)) {\n if (!hasConfigEntry(result, key)) {\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 setConfigEntry(result, key, childResult);\n }\n continue;\n }\n\n if (isConfigObject(pattern) && Object.keys(pattern).length > 0) {\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 const current = parse(content);\n return serializeUpdate(content || \"{}\", current, merge(current, patch));\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\nfunction serializeUpdate(\n content: string,\n current: ConfigObject,\n next: ConfigObject\n): string {\n let result = content || \"{}\";\n result = applyObjectUpdate(result, [], current, next);\n\n if (!result.endsWith(\"\\n\")) {\n result += \"\\n\";\n }\n\n return result;\n}\n\nfunction applyObjectUpdate(\n content: string,\n path: (string | number)[],\n current: ConfigObject,\n next: ConfigObject\n): string {\n let result = content;\n\n for (const key of Object.keys(current)) {\n if (!hasConfigEntry(next, key)) {\n result = removeAtPath(result, [...path, key]);\n }\n }\n\n for (const [key, nextValue] of Object.entries(next)) {\n const nextPath = [...path, key];\n const hasCurrent = hasConfigEntry(current, key);\n const currentValue = hasCurrent ? current[key] : undefined;\n\n if (hasCurrent && isConfigObject(currentValue) && isConfigObject(nextValue)) {\n result = applyObjectUpdate(result, nextPath, currentValue, nextValue);\n continue;\n }\n\n if (!hasCurrent || !configValuesEqual(currentValue, nextValue)) {\n result = modifyAtPath(result, nextPath, nextValue as ConfigValue);\n }\n }\n\n return result;\n}\n\nexport {\n detectIndent,\n modifyAtPath,\n mergePreservingComments,\n removeAtPath,\n serializeUpdate\n};\n\nexport const jsonFormat: ConfigFormat = {\n parse,\n serialize,\n serializeUpdate,\n merge,\n prune\n};\n", "import { parse as parseToml, stringify as stringifyToml } from \"smol-toml\";\nimport type { ConfigFormat, ConfigObject, ConfigValue } from \"../types.js\";\nimport { cloneConfigObject, hasConfigEntry, setConfigEntry } from \"./object.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 cloneConfigObject(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 = cloneConfigObject(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 setConfigEntry(result, key, merge(existing, value));\n continue;\n }\n setConfigEntry(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 = cloneConfigObject(obj);\n\n for (const [key, pattern] of Object.entries(shape)) {\n if (!hasConfigEntry(result, key)) {\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 setConfigEntry(result, key, childResult);\n }\n continue;\n }\n\n if (!isConfigObject(pattern) || Object.keys(pattern).length === 0) {\n delete result[key];\n changed = true;\n }\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\";\nimport { cloneConfigObject, hasConfigEntry, setConfigEntry } from \"./object.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 cloneConfigObject(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 = cloneConfigObject(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 setConfigEntry(result, key, merge(existing, value));\n continue;\n }\n setConfigEntry(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 = cloneConfigObject(obj);\n\n for (const [key, pattern] of Object.entries(shape)) {\n if (!hasConfigEntry(result, key)) {\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 setConfigEntry(result, key, childResult);\n }\n continue;\n }\n\n if (!isConfigObject(pattern) || Object.keys(pattern).length === 0) {\n delete result[key];\n changed = true;\n }\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 const canonicalHome = path.resolve(homeDir);\n const canonicalExpanded = path.resolve(expanded);\n const relative = path.relative(canonicalHome, canonicalExpanded);\n if (relative === \"..\" || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {\n throw new Error(`Target path resolves outside home directory: \"${rawPath}\"`);\n }\n\n if (!pathMapper) {\n return canonicalExpanded;\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 { 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 { statSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { getAgentConfig, resolveAgentSupport, resolveSkillDir } from \"./configs.js\";\n\nexport interface SkillSource {\n kind: \"resolved\";\n ref: string;\n name: string;\n sourceAgentId?: string;\n sourcePath: string;\n scope: \"project\" | \"user\";\n}\n\nexport type SkillResolutionFailure =\n | { kind: \"malformed\"; ref: string }\n | { kind: \"unknown-agent\"; ref: string; agentInput: string }\n | { kind: \"not-found\"; ref: string; searchedPaths: string[] };\n\nexport type SkillResolution = SkillSource | SkillResolutionFailure;\n\ninterface SearchTier {\n scope: \"project\" | \"user\";\n sourcePath: string;\n}\n\nfunction isMalformedSegment(segment: string): boolean {\n return (\n segment.length === 0 ||\n segment !== segment.trim() ||\n segment === \".\" ||\n segment === \"..\" ||\n segment.includes(\"\\n\") ||\n segment.includes(\"\\r\")\n );\n}\n\nfunction isDirectory(targetPath: string): boolean {\n try {\n return statSync(targetPath).isDirectory();\n } catch {\n return false;\n }\n}\n\nfunction findSkill(\n ref: string,\n name: string,\n tiers: SearchTier[],\n sourceAgentId?: string\n): SkillResolution {\n for (const tier of tiers) {\n if (isDirectory(tier.sourcePath)) {\n return {\n kind: \"resolved\",\n ref,\n name,\n ...(sourceAgentId ? { sourceAgentId } : {}),\n sourcePath: tier.sourcePath,\n scope: tier.scope\n };\n }\n }\n\n return {\n kind: \"not-found\",\n ref,\n searchedPaths: tiers.map((tier) => tier.sourcePath)\n };\n}\n\nexport function resolveSkillReference(ref: string, cwd: string, homeDir: string): SkillResolution {\n const slashIndex = ref.indexOf(\"/\");\n const hasPrefix = slashIndex !== -1;\n\n if (\n ref.length === 0 ||\n ref !== ref.trim() ||\n (hasPrefix && ref.indexOf(\"/\", slashIndex + 1) !== -1)\n ) {\n return { kind: \"malformed\", ref };\n }\n\n if (!hasPrefix) {\n if (isMalformedSegment(ref)) {\n return { kind: \"malformed\", ref };\n }\n\n const tiers: SearchTier[] = [\n {\n scope: \"project\",\n sourcePath: path.resolve(cwd, \".poe-code/skills\", ref)\n },\n {\n scope: \"user\",\n sourcePath: path.resolve(homeDir, \".poe-code/skills\", ref)\n }\n ];\n\n return findSkill(ref, ref, tiers);\n }\n\n const agentInput = ref.slice(0, slashIndex);\n const name = ref.slice(slashIndex + 1);\n if (isMalformedSegment(agentInput) || isMalformedSegment(name)) {\n return { kind: \"malformed\", ref };\n }\n\n const support = resolveAgentSupport(agentInput);\n if (support.status !== \"supported\" || !support.id) {\n return { kind: \"unknown-agent\", ref, agentInput };\n }\n\n const config = getAgentConfig(support.id);\n if (!config) {\n return { kind: \"unknown-agent\", ref, agentInput };\n }\n\n const tiers: SearchTier[] = [\n {\n scope: \"project\",\n sourcePath: path.resolve(resolveSkillDir(config, \"local\", cwd), name)\n },\n {\n scope: \"user\",\n sourcePath: path.resolve(resolveSkillDir(config, \"global\", cwd, homeDir), name)\n }\n ];\n\n return findSkill(ref, name, tiers, support.id);\n}\n", "import { execFileSync } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport path from \"node:path\";\n\nexport type GitDirRunner = (cwd: string) => string | undefined;\n\nconst defaultMarkerPrefix = \"poe-code-spawn-skills\";\n\nfunction defaultGitDirRunner(cwd: string): string | undefined {\n try {\n return execFileSync(\"git\", [\"rev-parse\", \"--git-dir\"], {\n cwd,\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"]\n }).trim();\n } catch {\n return undefined;\n }\n}\n\nlet gitDirRunner: GitDirRunner = defaultGitDirRunner;\nlet tempFileCounter = 0;\n\nexport function setGitDirRunnerForTest(runner: GitDirRunner): () => void {\n const previous = gitDirRunner;\n gitDirRunner = runner;\n return () => {\n gitDirRunner = previous;\n };\n}\n\nfunction resolveExcludePath(cwd: string): string | undefined {\n const gitDir = gitDirRunner(cwd);\n if (gitDir === undefined || gitDir.length === 0) {\n return undefined;\n }\n\n return path.join(path.isAbsolute(gitDir) ? gitDir : path.resolve(cwd, gitDir), \"info/exclude\");\n}\n\nfunction markers(runId: string, markerPrefix: string): { begin: string; end: string } {\n return {\n begin: `# ${markerPrefix}:${runId} begin`,\n end: `# ${markerPrefix}:${runId} end`\n };\n}\n\nfunction assertSingleLine(value: string, label: string): void {\n if (value.includes(\"\\n\") || value.includes(\"\\r\")) {\n throw new Error(`${label} must be a single line`);\n }\n}\n\nfunction readExcludeFile(excludePath: string): string | undefined {\n try {\n return fs.readFileSync(excludePath, \"utf8\");\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") {\n return undefined;\n }\n throw error;\n }\n}\n\nfunction isNodeError(error: unknown): error is NodeJS.ErrnoException {\n return error instanceof Error && \"code\" in error;\n}\n\nfunction assertNoSymbolicLink(targetPath: string): void {\n const parsed = path.parse(path.resolve(targetPath));\n let current = parsed.root;\n\n for (const segment of path.resolve(targetPath).slice(parsed.root.length).split(path.sep)) {\n if (segment.length === 0) {\n continue;\n }\n current = path.join(current, segment);\n try {\n if (fs.lstatSync(current).isSymbolicLink()) {\n throw new Error(`Refusing to update Git exclude path through symbolic link: ${current}`);\n }\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") {\n return;\n }\n throw error;\n }\n }\n}\n\nfunction writeExcludeFile(excludePath: string, content: string): void {\n assertNoSymbolicLink(excludePath);\n fs.mkdirSync(path.dirname(excludePath), { recursive: true });\n assertNoSymbolicLink(excludePath);\n const tempPath = `${excludePath}.poe-code-${process.pid}-${tempFileCounter++}.tmp`;\n try {\n fs.writeFileSync(tempPath, content, \"utf8\");\n fs.renameSync(tempPath, excludePath);\n } catch (error) {\n try {\n fs.rmSync(tempPath, { force: true });\n } catch (cleanupError) {\n void cleanupError;\n }\n throw error;\n }\n}\n\nfunction removeBlock(content: string, runId: string, markerPrefix: string): string {\n const { begin, end } = markers(runId, markerPrefix);\n const lines = content.split(\"\\n\");\n const result: string[] = [];\n\n for (let index = 0; index < lines.length; index += 1) {\n if (lines[index] === begin) {\n const endIndex = lines.indexOf(end, index + 1);\n if (endIndex !== -1) {\n index = endIndex;\n continue;\n }\n }\n\n result.push(lines[index]);\n }\n\n return result.join(\"\\n\");\n}\n\nfunction appendBlock(\n content: string | undefined,\n runId: string,\n entries: string[],\n markerPrefix: string\n): string {\n const { begin, end } = markers(runId, markerPrefix);\n const existing = content ?? \"\";\n const prefix = existing.length === 0 || existing.endsWith(\"\\n\") ? existing : `${existing}\\n`;\n return `${prefix}${[begin, ...entries, end, \"\"].join(\"\\n\")}`;\n}\n\nfunction nextBlockId(content: string | undefined, runId: string, markerPrefix: string): string {\n if (content === undefined || !content.includes(markers(runId, markerPrefix).begin)) {\n return runId;\n }\n\n let suffix = 1;\n while (content.includes(markers(`${runId}:${suffix}`, markerPrefix).begin)) {\n suffix += 1;\n }\n return `${runId}:${suffix}`;\n}\n\nexport function appendExcludeBlock(\n cwd: string,\n runId: string,\n entries: string[],\n opts?: { markerPrefix?: string }\n): string | undefined {\n assertSingleLine(runId, \"runId\");\n assertSingleLine(opts?.markerPrefix ?? defaultMarkerPrefix, \"markerPrefix\");\n for (const entry of entries) {\n assertSingleLine(entry, \"exclude entry\");\n }\n const excludePath = resolveExcludePath(cwd);\n if (excludePath === undefined) {\n return undefined;\n }\n\n assertNoSymbolicLink(excludePath);\n const content = readExcludeFile(excludePath);\n const markerPrefix = opts?.markerPrefix ?? defaultMarkerPrefix;\n const blockId = nextBlockId(content, runId, markerPrefix);\n writeExcludeFile(excludePath, appendBlock(content, blockId, entries, markerPrefix));\n return blockId;\n}\n\nexport function removeExcludeBlock(\n cwd: string,\n runId: string,\n opts?: { markerPrefix?: string }\n): void {\n assertSingleLine(runId, \"runId\");\n assertSingleLine(opts?.markerPrefix ?? defaultMarkerPrefix, \"markerPrefix\");\n const excludePath = resolveExcludePath(cwd);\n if (excludePath === undefined) {\n return;\n }\n\n const content = readExcludeFile(excludePath);\n if (content === undefined) {\n return;\n }\n\n writeExcludeFile(excludePath, removeBlock(content, runId, opts?.markerPrefix ?? defaultMarkerPrefix));\n}\n", "import * as fs from \"node:fs\";\nimport { createHash, randomUUID } from \"node:crypto\";\nimport path from \"node:path\";\nimport {\n getAgentConfig,\n resolveAgentSupport,\n resolveSkillDir,\n supportedAgents\n} from \"./configs.js\";\nimport { appendExcludeBlock, removeExcludeBlock } from \"./git-exclude.js\";\nimport { resolveSkillReference, type SkillResolutionFailure } from \"./resolve-skill-reference.js\";\n\nexport interface BridgeEntry {\n ref: string;\n sourcePath: string;\n targetPath: string;\n createdParents: string[];\n}\n\nexport type BridgeWarningKind =\n | \"local-collision\"\n | \"global-collision\"\n | \"self-reference\"\n | \"intra-batch-collision\";\n\nexport interface BridgeWarning {\n kind: BridgeWarningKind;\n ref: string;\n sourcePath: string;\n conflictingPath: string;\n message: string;\n}\n\nexport interface BridgeManifest {\n spawnAgentId: string;\n cwd: string;\n runId: string;\n entries: BridgeEntry[];\n warnings: BridgeWarning[];\n}\n\ninterface ActiveTarget {\n createdParents: string[];\n fingerprint: string;\n sourcePath: string;\n references: number;\n token: string;\n}\n\ninterface ManifestState {\n excludeBlockId?: string;\n cleaned?: boolean;\n}\n\nconst activeTargets = new Map<string, ActiveTarget>();\nconst manifestStates = new WeakMap<BridgeManifest, ManifestState>();\nconst ownershipFileName = \".poe-code-bridge-owner\";\n\ntype ResolvedSkill = Extract<ReturnType<typeof resolveSkillReference>, { kind: \"resolved\" }>;\n\ninterface ResolvedBridgeSource {\n ref: string;\n source: ResolvedSkill;\n targetPath: string;\n globalTargetPath: string;\n}\n\nfunction isNodeError(error: unknown): error is NodeJS.ErrnoException {\n return error instanceof Error && \"code\" in error;\n}\n\nfunction pathExists(targetPath: string): boolean {\n try {\n fs.statSync(targetPath);\n return true;\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") {\n return false;\n }\n throw error;\n }\n}\n\nfunction assertNoSymbolicLink(targetPath: string): void {\n const parsed = path.parse(path.resolve(targetPath));\n let current = parsed.root;\n\n for (const segment of path.resolve(targetPath).slice(parsed.root.length).split(path.sep)) {\n if (segment.length === 0) {\n continue;\n }\n current = path.join(current, segment);\n try {\n if (fs.lstatSync(current).isSymbolicLink()) {\n throw new Error(`Refusing to bridge skills through symbolic link: ${current}`);\n }\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") {\n return;\n }\n throw error;\n }\n }\n}\n\nfunction isDirectory(targetPath: string): boolean {\n try {\n return fs.statSync(targetPath).isDirectory();\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") {\n return false;\n }\n throw error;\n }\n}\n\nfunction formatResolutionFailureError(failures: SkillResolutionFailure[]): Error {\n const malformed = failures.filter((failure) => failure.kind === \"malformed\");\n const unknownAgent = failures.filter((failure) => failure.kind === \"unknown-agent\");\n const notFound = failures.filter((failure) => failure.kind === \"not-found\");\n const lines = [\n `Failed to bridge active skills: ${failures.length} skill reference(s) could not be resolved.`\n ];\n\n if (malformed.length > 0) {\n lines.push(\"\", \"Malformed skill references:\");\n for (const failure of malformed) {\n lines.push(`- ${failure.ref}`);\n }\n lines.push('Expected syntax: \"<name>\" or \"<agentId>/<name>\".');\n }\n\n if (unknownAgent.length > 0) {\n lines.push(\"\", \"Unknown agent references:\");\n for (const failure of unknownAgent) {\n lines.push(`- ${failure.ref} (agent token: ${failure.agentInput})`);\n }\n lines.push(`Supported agents: ${supportedAgents.join(\", \")}.`);\n }\n\n if (notFound.length > 0) {\n lines.push(\"\", \"Not found skill references.\");\n for (const failure of notFound) {\n lines.push(`- ${failure.ref}`);\n lines.push(\" searched paths:\");\n for (const searchedPath of failure.searchedPaths) {\n lines.push(` - ${searchedPath}`);\n }\n }\n }\n\n return new Error(lines.join(\"\\n\"));\n}\n\nfunction copyDirectory(sourcePath: string, targetPath: string): void {\n assertNoSymbolicLink(sourcePath);\n fs.mkdirSync(targetPath, { recursive: true });\n for (const dirent of fs.readdirSync(sourcePath, { withFileTypes: true })) {\n const childSource = path.join(sourcePath, dirent.name);\n const childTarget = path.join(targetPath, dirent.name);\n\n if (dirent.isSymbolicLink()) {\n throw new Error(`Refusing to bridge skill containing symbolic link: ${childSource}`);\n }\n\n if (dirent.isDirectory()) {\n copyDirectory(childSource, childTarget);\n continue;\n }\n\n if (dirent.isFile()) {\n fs.copyFileSync(childSource, childTarget);\n }\n }\n}\n\nfunction directoryFingerprint(targetPath: string): string {\n const hash = createHash(\"sha256\");\n\n function visit(currentPath: string, relativePath: string): void {\n const stats = fs.lstatSync(currentPath);\n if (stats.isSymbolicLink()) {\n throw new Error(`Refusing to inspect bridged skill through symbolic link: ${currentPath}`);\n }\n if (stats.isDirectory()) {\n hash.update(`d:${relativePath}\\n`);\n for (const name of fs.readdirSync(currentPath).sort()) {\n visit(path.join(currentPath, name), path.join(relativePath, name));\n }\n return;\n }\n if (stats.isFile()) {\n hash.update(`f:${relativePath}\\n`);\n hash.update(fs.readFileSync(currentPath));\n return;\n }\n throw new Error(`Refusing to bridge unsupported filesystem entry: ${currentPath}`);\n }\n\n visit(targetPath, \".\");\n return hash.digest(\"hex\");\n}\n\nfunction ownershipPath(targetPath: string): string {\n return path.join(targetPath, ownershipFileName);\n}\n\nfunction hasOwnershipToken(targetPath: string, token: string): boolean {\n try {\n return fs.readFileSync(ownershipPath(targetPath), \"utf8\") === token;\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") {\n return false;\n }\n throw error;\n }\n}\n\nfunction collectMissingParents(targetPath: string): string[] {\n const parents: string[] = [];\n let current = path.dirname(targetPath);\n\n while (!pathExists(current)) {\n parents.push(current);\n const parent = path.dirname(current);\n if (parent === current) {\n break;\n }\n current = parent;\n }\n\n return parents.reverse();\n}\n\nfunction removeDirectoryIfEmpty(targetPath: string): void {\n try {\n fs.rmdirSync(targetPath);\n } catch (error) {\n if (\n isNodeError(error) &&\n (error.code === \"ENOENT\" || error.code === \"ENOTEMPTY\" || error.code === \"EEXIST\")\n ) {\n return;\n }\n throw error;\n }\n}\n\nfunction removeTarget(targetPath: string): void {\n fs.rmSync(targetPath, { recursive: true, force: true });\n}\n\nfunction rollbackEntries(entries: BridgeEntry[]): void {\n for (const entry of [...entries].reverse()) {\n const activeTarget = activeTargets.get(entry.targetPath);\n if (activeTarget && activeTarget.references > 1) {\n activeTarget.references -= 1;\n continue;\n }\n activeTargets.delete(entry.targetPath);\n removeTarget(entry.targetPath);\n for (const parent of [...(activeTarget?.createdParents ?? entry.createdParents)].reverse()) {\n removeDirectoryIfEmpty(parent);\n }\n }\n}\n\nfunction toCwdRelative(cwd: string, targetPath: string): string {\n return path.relative(cwd, targetPath);\n}\n\nfunction warning(\n kind: BridgeWarningKind,\n ref: string,\n sourcePath: string,\n conflictingPath: string\n): BridgeWarning {\n const messages: Record<BridgeWarningKind, string> = {\n \"intra-batch-collision\": `Skipping ${ref}: an earlier bridged skill already targets ${conflictingPath}.`,\n \"local-collision\": `Skipping ${ref}: local skill already exists at ${conflictingPath}.`,\n \"global-collision\": `Skipping ${ref}: global skill already exists at ${conflictingPath}.`,\n \"self-reference\": `Skipping ${ref}: spawning agent already sees this native skill at ${conflictingPath}.`\n };\n\n return {\n kind,\n ref,\n sourcePath,\n conflictingPath,\n message: messages[kind]\n };\n}\n\nexport function bridgeActiveSkills(\n spawnAgentId: string,\n cwd: string,\n refs: string[],\n homeDir: string,\n runId: string\n): BridgeManifest {\n const spawnConfig = getAgentConfig(spawnAgentId);\n const spawnSupport = resolveAgentSupport(spawnAgentId);\n if (!spawnConfig || spawnSupport.status !== \"supported\" || !spawnSupport.id) {\n throw new Error(\n `Unsupported spawn agent \"${spawnAgentId}\". Supported agents: ${supportedAgents.join(\", \")}.`\n );\n }\n\n const targetDir = resolveSkillDir(spawnConfig, \"local\", cwd);\n const globalTargetDir = resolveSkillDir(spawnConfig, \"global\", cwd, homeDir);\n const resolutions = refs.map((ref) => resolveSkillReference(ref, cwd, homeDir));\n const failures = resolutions.filter(\n (resolution): resolution is SkillResolutionFailure => resolution.kind !== \"resolved\"\n );\n if (failures.length > 0) {\n throw formatResolutionFailureError(failures);\n }\n\n const sources: ResolvedBridgeSource[] = resolutions.map((source, index) => ({\n ref: refs[index]!,\n source: source as ResolvedSkill,\n targetPath: path.resolve(targetDir, (source as ResolvedSkill).name),\n globalTargetPath: path.resolve(globalTargetDir, (source as ResolvedSkill).name)\n }));\n\n const entries: BridgeEntry[] = [];\n const warnings: BridgeWarning[] = [];\n const claimedTargets = new Set<string>();\n\n try {\n for (const item of sources) {\n if (claimedTargets.has(item.targetPath)) {\n warnings.push(\n warning(\"intra-batch-collision\", item.ref, item.source.sourcePath, item.targetPath)\n );\n continue;\n }\n\n if (item.source.sourceAgentId === spawnSupport.id) {\n warnings.push(\n warning(\"self-reference\", item.ref, item.source.sourcePath, item.source.sourcePath)\n );\n continue;\n }\n\n const activeTarget = activeTargets.get(item.targetPath);\n if (activeTarget && pathExists(item.targetPath)) {\n if (\n activeTarget.sourcePath === item.source.sourcePath &&\n hasOwnershipToken(item.targetPath, activeTarget.token) &&\n directoryFingerprint(item.targetPath) === activeTarget.fingerprint\n ) {\n activeTarget.references += 1;\n claimedTargets.add(item.targetPath);\n entries.push({\n ref: item.ref,\n sourcePath: item.source.sourcePath,\n targetPath: item.targetPath,\n createdParents: []\n });\n continue;\n }\n activeTargets.delete(item.targetPath);\n }\n\n if (pathExists(item.targetPath)) {\n warnings.push(warning(\"local-collision\", item.ref, item.source.sourcePath, item.targetPath));\n continue;\n }\n\n if (isDirectory(item.globalTargetPath)) {\n warnings.push(\n warning(\"global-collision\", item.ref, item.source.sourcePath, item.globalTargetPath)\n );\n continue;\n }\n\n const createdParents = collectMissingParents(item.targetPath);\n assertNoSymbolicLink(path.dirname(item.targetPath));\n fs.mkdirSync(path.dirname(item.targetPath), { recursive: true });\n const token = randomUUID();\n try {\n copyDirectory(item.source.sourcePath, item.targetPath);\n fs.writeFileSync(ownershipPath(item.targetPath), token, \"utf8\");\n const fingerprint = directoryFingerprint(item.targetPath);\n claimedTargets.add(item.targetPath);\n entries.push({\n ref: item.ref,\n sourcePath: item.source.sourcePath,\n targetPath: item.targetPath,\n createdParents\n });\n activeTargets.set(item.targetPath, {\n createdParents,\n fingerprint,\n sourcePath: item.source.sourcePath,\n references: 1,\n token\n });\n } catch (error) {\n removeTarget(item.targetPath);\n for (const parent of [...createdParents].reverse()) {\n removeDirectoryIfEmpty(parent);\n }\n throw error;\n }\n }\n\n let excludeBlockId: string | undefined;\n if (entries.length > 0) {\n excludeBlockId = appendExcludeBlock(\n cwd,\n runId,\n entries.map((entry) => toCwdRelative(cwd, entry.targetPath))\n );\n }\n\n const manifest = {\n spawnAgentId,\n cwd,\n runId,\n entries,\n warnings\n };\n manifestStates.set(manifest, { excludeBlockId });\n return manifest;\n } catch (error) {\n rollbackEntries(entries);\n throw error;\n }\n}\n\nexport function cleanupBridgedSkills(manifest: BridgeManifest): void {\n const state = manifestStates.get(manifest);\n if (state?.cleaned) {\n return;\n }\n removeExcludeBlock(manifest.cwd, state?.excludeBlockId ?? manifest.runId);\n for (const entry of manifest.entries) {\n const activeTarget = activeTargets.get(entry.targetPath);\n if (!activeTarget) {\n continue;\n }\n if (activeTarget.references > 1) {\n activeTarget.references -= 1;\n continue;\n }\n activeTargets.delete(entry.targetPath);\n if (\n pathExists(entry.targetPath) &&\n hasOwnershipToken(entry.targetPath, activeTarget.token) &&\n directoryFingerprint(entry.targetPath) === activeTarget.fingerprint\n ) {\n removeTarget(entry.targetPath);\n for (const parent of [...activeTarget.createdParents].reverse()) {\n removeDirectoryIfEmpty(parent);\n }\n }\n }\n if (state) {\n state.cleaned = true;\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["randomUUID", "fileURLToPath", "message", "assertValidBranches", "fileURLToPath", "location", "separatorIndex", "previousSeparatorIndex", "candidate", "os", "path", "readFile", "path", "path", "text", "text", "spacing", "message", "graphemeSegmenter", "process", "AsyncLocalStorage", "graphemeSegmenter", "path", "path", "fileURLToPath", "statSync", "path", "path", "fs", "path", "error", "os", "path", "fs", "path", "error", "params", "randomUUID", "error", "fs"]
|
|
3
|
+
"sources": ["../../src/commands/uninstall.ts", "../../../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", "../../../toolcraft/src/package-metadata.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/gemini-cli.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", "../../../toolcraft-design/src/internal/color-support.ts", "../../../toolcraft-design/src/components/color.ts", "../../../toolcraft-design/src/tokens/brand.ts", "../../../toolcraft-design/src/internal/theme-state.ts", "../../../toolcraft-design/src/tokens/colors.ts", "../../../toolcraft-design/src/internal/output-format.ts", "../../../toolcraft-design/src/internal/theme-detect.ts", "../../../toolcraft-design/src/components/symbols.ts", "../../../toolcraft-design/src/internal/strip-ansi.ts", "../../../toolcraft-design/src/prompts/primitives/log.ts", "../../../toolcraft-design/src/components/logger.ts", "../../../toolcraft-design/src/components/help-formatter.ts", "../../../toolcraft-design/src/components/table.ts", "../../../toolcraft-design/src/components/browser.ts", "../../../toolcraft-design/src/acp/writer.ts", "../../../toolcraft-design/src/dashboard/terminal-width.ts", "../../../toolcraft-design/src/dashboard/terminal.ts", "../../../toolcraft-design/src/explorer/state.ts", "../../../toolcraft-design/src/prompts/index.ts", "../../../toolcraft-design/src/prompts/primitives/cancel.ts", "../../../toolcraft-design/src/static/spinner.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", "../../../agent-skill-config/src/templates.ts", "../../../agent-skill-config/src/resolve-skill-reference.ts", "../../../agent-skill-config/src/git-exclude.ts", "../../../agent-skill-config/src/bridge-active-skills.ts"],
|
|
4
|
+
"sourcesContent": ["import { randomUUID } from \"node:crypto\";\nimport { defineCommand, S } from \"toolcraft\";\nimport type { TerminalPilotCommandServices } from \"./runtime.js\";\nimport {\n DEFAULT_INSTALL_AGENT,\n assertNoSymbolicLinkPath,\n getSkillFolderWithHome,\n installableAgents,\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 skills = [localSkill, globalSkill];\n const staged: Array<{ fullPath: string; stagingPath: string; displayPath: string }> = [];\n\n try {\n for (const skill of skills) {\n await assertNoSymbolicLinkPath(services.fs, skill.fullPath);\n\n if (!(await folderExists(services.fs, skill.fullPath))) {\n continue;\n }\n\n const stagingPath = `${skill.fullPath}.removing-${randomUUID()}`;\n await services.fs.rename(skill.fullPath, stagingPath);\n staged.push({ ...skill, stagingPath });\n }\n } catch (error) {\n for (const skill of staged.reverse()) {\n await services.fs.rename(skill.stagingPath, skill.fullPath);\n }\n throw error;\n }\n\n if (typeof services.fs.rm === \"function\") {\n await Promise.allSettled(\n staged.map((skill) => services.fs.rm!(skill.stagingPath, { recursive: true, force: true }))\n );\n }\n\n return {\n agent,\n removedSkillPaths: staged.map((skill) => skill.displayPath)\n };\n }\n});\n\nasync function folderExists(\n fs: ReturnType<typeof resolveInstallerServices>[\"fs\"],\n folderPath: string\n): Promise<boolean> {\n try {\n await fs.stat(folderPath);\n return true;\n } catch (error) {\n if (typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\") {\n return false;\n }\n\n throw error;\n }\n}\n", "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 \"toolcraft-design\";\nimport { ApprovalDeclinedError } from \"./human-in-loop/types.js\";\nimport type {\n HumanInLoopConfig,\n HumanInLoopPending,\n HumanInLoopRuntimeOptions\n} from \"./human-in-loop/types.js\";\nimport { mergeHumanInLoopFromGroup, validateHumanInLoopOnDefine } from \"./human-in-loop/config.js\";\nimport { ToolcraftBugError, UserError } from \"./user-error.js\";\nimport { suggest } from \"./suggest.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 {\n mode: infer TMode extends HumanInLoopMode;\n}\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 lstat(path: string): Promise<{ isSymbolicLink(): boolean }>;\n rename(fromPath: string, toPath: string): Promise<void>;\n unlink(path: string): Promise<void>;\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>(\n requires: Requires<TContext> | undefined\n): 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(\n values: Record<string, string> | undefined\n): 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(\n rename: Record<string, string> | undefined\n): 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(\n `Invalid rename target for upstream tool \"${upstreamName}\": path cannot be empty.`\n );\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 =\n 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 =\n 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(\n parent: Requires<any> | undefined,\n child: Requires<any> | undefined\n): 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 (merged.auth === undefined && merged.apiVersion === undefined && merged.check === undefined) {\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 const candidates = Object.keys(env).filter(\n (candidate) => candidate !== secret.env && env[candidate] !== undefined\n );\n const suggestions = suggestSecretEnv(secret.env, candidates);\n const suggestionLine =\n suggestions.length > 0 ? `\\nDid you mean: ${suggestions.join(\", \")}?` : \"\";\n throw new UserError(`Missing required secret ${secret.env}${details}${suggestionLine}`);\n }\n\n Object.defineProperty(secrets, name, {\n value,\n enumerable: true,\n configurable: true,\n writable: true\n });\n }\n\n return secrets;\n}\n\nfunction suggestSecretEnv(input: string, candidates: readonly string[]): string[] {\n const directSuggestions = suggest(input, candidates);\n if (!input.includes(\"_\")) {\n return directSuggestions;\n }\n\n const inputParts = input.split(\"_\");\n const firstPart = inputParts[0];\n const lastPart = inputParts[inputParts.length - 1];\n const relatedCandidates = candidates.filter((candidate) => {\n const candidateParts = candidate.split(\"_\");\n return (\n candidateParts[0] === firstPart &&\n candidateParts[candidateParts.length - 1] === lastPart\n );\n });\n const expandedSuggestions = suggest(input, relatedCandidates, {\n threshold: Math.max(4, Math.floor(input.length / 4))\n });\n\n return [...new Set([...directSuggestions, ...expandedSuggestions])].slice(0, 3);\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 `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 `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 `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 `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 `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(\n ownScope: Scope[] | undefined,\n inheritedScope: Scope[] | undefined\n): Scope[] {\n return cloneScope(ownScope ?? inheritedScope) ?? [\"cli\", \"sdk\"];\n}\n\nfunction resolveGroupScope(\n ownScope: Scope[] | undefined,\n inheritedScope: Scope[] | undefined\n): 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>(\n config: GroupConfig<TServices>\n): 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 (\n command as Command<any, any, any, any> & { [commandConfigSymbol]: InternalCommandConfig }\n )[commandConfigSymbol];\n}\n\nfunction getInternalGroupConfig<TServices extends object>(\n group: Group<TServices>\n): 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) =>\n materializeNode(child, mergedInherited)\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 ToolcraftBugError(\n `Default command \"${internal.default.name}\" must be listed in children.`\n );\n }\n\n const resolvedDefault = materializedChildren[defaultIndex];\n if (resolvedDefault?.kind !== \"command\") {\n throw new ToolcraftBugError(`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<\n CommandConfig<TServices, TParamsSchema, TSecrets, TResult>,\n \"name\" | \"scope\" | \"humanInLoop\"\n > & {\n name: TName;\n scope?: TOwnScope;\n humanInLoop?: TOwnHumanInLoop;\n }\n): Command<TServices, TParamsSchema, TSecrets, TResult> &\n TypedCommandMetadata<\n TName,\n TParamsSchema,\n TResult,\n TOwnScope,\n ResolveOwnHumanInLoopMode<TOwnHumanInLoop>\n > {\n validateHumanInLoopOnDefine(config);\n\n return materializeCommand(\n createBaseCommand(config as CommandConfig<TServices, TParamsSchema, TSecrets, TResult>),\n {\n scope: undefined,\n humanInLoop: undefined,\n secrets: {},\n requires: undefined\n }\n ) as Command<TServices, TParamsSchema, TSecrets, TResult> &\n TypedCommandMetadata<\n TName,\n TParamsSchema,\n TResult,\n TOwnScope,\n ResolveOwnHumanInLoopMode<TOwnHumanInLoop>\n >;\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<\n TServices,\n TName,\n TChildren,\n TOwnScope,\n ResolveOwnHumanInLoopMode<TOwnHumanInLoop>\n > {\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<\n TServices,\n TName,\n TChildren,\n TOwnScope,\n ResolveOwnHumanInLoopMode<TOwnHumanInLoop>\n >;\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, ToolcraftBugError, UserError };\nexport { findPackageMetadata, packageMetadata } from \"./package-metadata.js\";\nexport type { PackageMetadata } from \"./package-metadata.js\";\nexport type {\n AnySchema,\n ArraySchema,\n BooleanSchema,\n EnumSchema,\n JsonSchema,\n NumberSchema,\n ObjectSchema,\n OptionalSchema,\n Static,\n StringSchema\n} from \"toolcraft-schema\";\nexport type { HumanInLoopConfig, HumanInLoopPending, HumanInLoopRuntimeOptions };\n", "export class UserError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = \"UserError\";\n }\n}\n\nexport class ToolcraftBugError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ToolcraftBugError\";\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(\n branches: Record<string, ObjectSchema<any>>,\n discriminator: string\n): void {\n if (Object.keys(branches).length === 0) {\n throw new Error(\"OneOf schema requires at least one branch\");\n }\n\n for (const [branchName, branch] of Object.entries(branches)) {\n if (Object.prototype.hasOwnProperty.call(branch.shape, discriminator)) {\n throw new Error(\n `OneOf branch \"${branchName}\" must not declare discriminator field \"${discriminator}\".`\n );\n }\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, config.discriminator);\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 getRequiredKeys(schema: ObjectSchema<any>): string[] {\n return Object.keys(schema.shape)\n .filter((key) => !isOptionalSchema(schema.shape[key] as AnySchema))\n .sort();\n}\n\nexport function getRequiredKeyFingerprint(schema: ObjectSchema<any>): string {\n return getRequiredKeys(schema).join(\"+\");\n}\n\nfunction assertUniqueRequiredKeyFingerprints(branches: readonly ObjectSchema<any>[]): void {\n const fingerprints = new Map<string, { display: string; indices: number[] }>();\n\n branches.forEach((branch, index) => {\n const requiredKeys = getRequiredKeys(branch);\n const fingerprint = JSON.stringify(requiredKeys);\n const existing = fingerprints.get(fingerprint);\n\n if (existing === undefined) {\n fingerprints.set(fingerprint, {\n display: requiredKeys.join(\"+\"),\n indices: [index],\n });\n return;\n }\n\n existing.indices.push(index);\n });\n\n for (const { display, indices } of fingerprints.values()) {\n if (indices.length > 1) {\n throw new Error(\n `Union branches [${indices.join(\", \")}] share required-key fingerprint \"${display}\". Each branch must require a distinct set of keys.`\n );\n }\n }\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 assertUniqueRequiredKeyFingerprints(branches);\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 { validate } from \"./validate.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\";\nimport type { ValidationIssue, ValidationResult } from \"./validate.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 secret?: boolean;\n};\ntype NumberMetadata = {\n maximum?: number;\n minimum?: number;\n secret?: boolean;\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 global?: boolean;\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 global?: boolean;\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 if (values.some((value) => typeof value === \"number\" && !Number.isFinite(value))) {\n throw new Error(\"Enum schema numeric values must be finite\");\n }\n}\n\nfunction assertNonNegativeInteger(value: number | undefined, name: string): void {\n if (value !== undefined && (!Number.isInteger(value) || value < 0)) {\n throw new Error(`${name} must be a non-negative integer`);\n }\n}\n\nfunction assertFiniteNumber(value: number | undefined, name: string): void {\n if (value !== undefined && !Number.isFinite(value)) {\n throw new Error(`${name} must be finite`);\n }\n}\n\nfunction assertPattern(pattern: string | undefined): void {\n if (pattern === undefined) {\n return;\n }\n try {\n new RegExp(pattern);\n } catch {\n throw new Error(\"pattern must be a valid regular expression\");\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 assertNonNegativeInteger(options.minLength, \"minLength\");\n assertNonNegativeInteger(options.maxLength, \"maxLength\");\n assertPattern(options.pattern);\n return {\n kind: \"string\",\n ...options,\n };\n },\n\n Number(\n options: SchemaOptions<number> & NumberMetadata & { jsonType?: NumberJsonType } = {}\n ): NumberSchema {\n assertFiniteNumber(options.minimum, \"minimum\");\n assertFiniteNumber(options.maximum, \"maximum\");\n assertFiniteNumber(options.default, \"default\");\n if (options.jsonType === \"integer\" && options.default !== undefined && !Number.isInteger(options.default)) {\n throw new Error(\"default must be an integer\");\n }\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 if (options.jsonType === \"integer\" && values.some((value) => typeof value !== \"number\" || !Number.isInteger(value))) {\n throw new Error(\"Integer enum values must be integers\");\n }\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 assertNonNegativeInteger(options.minItems, \"minItems\");\n assertNonNegativeInteger(options.maxItems, \"maxItems\");\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 Object.defineProperty(properties, key, {\n enumerable: true,\n configurable: true,\n writable: true,\n value: toJsonSchema(propertySchema)\n });\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, validate };\nexport type {\n JsonValue,\n JsonValueSchema,\n OneOfSchema,\n RecordSchema,\n UnionSchema,\n ValidationIssue,\n ValidationResult,\n};\n", "import { existsSync, readFileSync, statSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nexport interface PackageMetadata {\n name?: string;\n path: string;\n version?: string;\n}\n\ntype PackageMetadataInput = string | URL;\n\nfunction pathFromInput(from: PackageMetadataInput): string {\n if (from instanceof URL) {\n return fileURLToPath(from);\n }\n\n if (from.startsWith(\"file:\")) {\n return fileURLToPath(from);\n }\n\n return path.resolve(from);\n}\n\nfunction getSearchDirectory(from: PackageMetadataInput): string {\n const resolved = pathFromInput(from);\n\n try {\n return statSync(resolved).isDirectory() ? resolved : path.dirname(resolved);\n } catch {\n return path.dirname(resolved);\n }\n}\n\nfunction readPackageMetadata(packageJsonPath: string): PackageMetadata | undefined {\n const parsed = JSON.parse(readFileSync(packageJsonPath, \"utf8\")) as {\n name?: unknown;\n version?: unknown;\n };\n const metadata: PackageMetadata = { path: packageJsonPath };\n\n if (typeof parsed.name === \"string\") {\n metadata.name = parsed.name;\n }\n\n if (typeof parsed.version === \"string\") {\n metadata.version = parsed.version;\n }\n\n return metadata;\n}\n\nexport function findPackageMetadata(from: PackageMetadataInput): PackageMetadata | undefined {\n let current = getSearchDirectory(from);\n\n while (true) {\n const packageJsonPath = path.join(current, \"package.json\");\n\n if (existsSync(packageJsonPath)) {\n return readPackageMetadata(packageJsonPath);\n }\n\n const parent = path.dirname(current);\n\n if (parent === current) {\n return undefined;\n }\n\n current = parent;\n }\n}\n\nexport function packageMetadata(from: PackageMetadataInput = process.cwd()): PackageMetadata {\n const metadata = findPackageMetadata(from);\n\n if (metadata === undefined) {\n throw new Error(`No package.json found from ${pathFromInput(from)}.`);\n }\n\n return metadata;\n}\n\nexport function findEntrypointPackageMetadata(entrypoint: string | undefined): PackageMetadata | undefined {\n if (entrypoint === undefined || entrypoint.length === 0) {\n return undefined;\n }\n\n if (!path.isAbsolute(entrypoint) && !entrypoint.startsWith(\"file:\")) {\n return undefined;\n }\n\n return findPackageMetadata(entrypoint);\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 \"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 rename(oldPath: string, newPath: string): 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 lstat(path: string): Promise<{ isSymbolicLink(): boolean }>;\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 await assertNoSymbolicLinkPath(fs, folderPath);\n\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\nexport async function assertNoSymbolicLinkPath(\n fs: Pick<TerminalPilotInstallerFileSystem, \"lstat\">,\n targetPath: string\n): Promise<void> {\n const rootPath = path.parse(targetPath).root;\n let currentPath = targetPath;\n\n while (currentPath !== rootPath) {\n try {\n if ((await fs.lstat(currentPath)).isSymbolicLink()) {\n throw new UserError(`Refusing terminal-pilot skill operation through symbolic link: ${currentPath}`);\n }\n } catch (error) {\n if (!isNotFoundError(error)) {\n throw error;\n }\n }\n\n currentPath = path.dirname(currentPath);\n }\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 \"gemini-cli\": {\n globalSkillDir: \"~/.gemini/skills\",\n localSkillDir: \".gemini/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.freeze(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: { ...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, homeDir: string = os.homedir()): string {\n if (!targetPath?.startsWith(\"~\")) {\n return targetPath;\n }\n\n if (targetPath === \"~\") {\n return 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 ? homeDir : path.join(homeDir, remainder);\n}\n\nexport function resolveSkillDir(\n config: AgentSkillConfig,\n scope: SkillScope,\n cwd: string,\n homeDir?: string\n): string {\n if (scope === \"global\") {\n return path.resolve(expandHome(config.globalSkillDir, homeDir));\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 apiShapes: [\"anthropic-messages\"],\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 apiShapes: [\"openai-responses\"],\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 geminiCliAgent: AgentDefinition = {\n id: \"gemini-cli\",\n name: \"gemini-cli\",\n aliases: [\"gemini\"],\n label: \"Gemini CLI\",\n summary: \"Configure Google's Gemini CLI to use a compatible Google generations API.\",\n binaryName: \"gemini\",\n configPath: \"~/.gemini/settings.json\",\n apiShapes: [\"google-generations\"],\n branding: {\n colors: {\n dark: \"#8AB4F8\",\n light: \"#1A73E8\"\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 apiShapes: [\"openai-chat-completions\"],\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 apiShapes: [\"openai-chat-completions\"],\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 apiShapes: [\"openai-chat-completions\"],\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 apiShapes: [\"openai-responses\", \"openai-chat-completions\"],\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 geminiCliAgent,\n openCodeAgent,\n kimiAgent,\n gooseAgent,\n poeAgentAgent\n} from \"./agents/index.js\";\n\nfunction freezeAgent(agent: AgentDefinition): AgentDefinition {\n if (agent.aliases !== undefined) {\n Object.freeze(agent.aliases);\n }\n if (agent.apiShapes !== undefined) {\n Object.freeze(agent.apiShapes);\n }\n Object.freeze(agent.branding.colors);\n Object.freeze(agent.branding);\n return Object.freeze(agent);\n}\n\nexport const allAgents: readonly AgentDefinition[] = Object.freeze([\n freezeAgent(claudeCodeAgent),\n freezeAgent(claudeDesktopAgent),\n freezeAgent(codexAgent),\n freezeAgent(geminiCliAgent),\n freezeAgent(openCodeAgent),\n freezeAgent(kimiAgent),\n freezeAgent(gooseAgent),\n freezeAgent(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.trim().toLowerCase());\n}\n", "import path from \"node:path\";\nimport { renderTemplate } from \"toolcraft-design\";\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 { cloneConfigObject, setConfigEntry } from \"../formats/object.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 context: MutationContext,\n targetPath: string,\n content: string\n): Promise<void> {\n const baseBackupPath = createInvalidDocumentBackupPath(targetPath);\n let attempt = 0;\n while (true) {\n const backupPath = attempt === 0 ? baseBackupPath : `${baseBackupPath}-${attempt}`;\n await assertRegularWriteTarget(context, backupPath);\n try {\n await context.fs.writeFile(backupPath, content, { encoding: \"utf8\", flag: \"wx\" });\n return;\n } catch (error) {\n if (!isAlreadyExists(error)) {\n throw error;\n }\n attempt += 1;\n }\n }\n}\n\nfunction isAlreadyExists(error: unknown): boolean {\n return Boolean(error && typeof error === \"object\" && \"code\" in error && error.code === \"EEXIST\");\n}\n\nasync function assertRegularWriteTarget(\n context: MutationContext,\n targetPath: string\n): Promise<void> {\n // Symlinks inside the managed home directory are untrusted: an attacker could\n // plant one to redirect a credential/config write outside it. Symlinks at or\n // above home are legitimate system links (e.g. /tmp -> /private/tmp on macOS,\n // /var -> /private/var) and must not block writes, so bound the walk at home.\n const boundary = path.dirname(path.resolve(context.homeDir));\n let currentPath = path.resolve(targetPath);\n while (currentPath !== boundary) {\n try {\n if ((await context.fs.lstat(currentPath)).isSymbolicLink()) {\n throw new Error(`Refusing mutation write through symbolic link: ${currentPath}`);\n }\n } catch (error) {\n if (!isNotFound(error)) {\n throw error;\n }\n }\n\n const parentPath = path.dirname(currentPath);\n if (parentPath === currentPath) {\n return;\n }\n currentPath = parentPath;\n }\n}\n\nasync function writeAtomically(\n context: MutationContext,\n targetPath: string,\n content: string\n): Promise<void> {\n await assertRegularWriteTarget(context, targetPath);\n let attempt = 0;\n while (true) {\n const tempPath = `${targetPath}.mutation-tmp-${attempt}`;\n try {\n await context.fs.writeFile(tempPath, content, { encoding: \"utf8\", flag: \"wx\" });\n await context.fs.rename(tempPath, targetPath);\n return;\n } catch (error) {\n if (isAlreadyExists(error)) {\n attempt += 1;\n continue;\n }\n try {\n await context.fs.unlink(tempPath);\n } catch (cleanupError) {\n if (!isNotFound(cleanupError)) {\n void cleanupError;\n }\n }\n throw error;\n }\n }\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 \"restoreBackup\":\n return `Restore ${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 setConfigEntry(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 = cloneConfigObject(base);\n const prefixMap = pruneByPrefix ?? {};\n\n for (const [key, value] of Object.entries(patch)) {\n if (value === undefined) {\n continue;\n }\n\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 setConfigEntry(result, key, mergePrunedConfigObject(pruned, value));\n } else {\n setConfigEntry(result, key, mergeWithPruneByPrefix(current, value, prefixMap));\n }\n continue;\n }\n setConfigEntry(result, key, value);\n }\n return result;\n}\n\nfunction mergePrunedConfigObject(base: ConfigObject, patch: ConfigObject): ConfigObject {\n const result = cloneConfigObject(base);\n\n for (const [key, value] of Object.entries(patch)) {\n if (value === undefined) {\n continue;\n }\n\n setConfigEntry(result, key, value);\n }\n\n return result;\n}\n\nfunction serializeConfigUpdate(\n format: ReturnType<typeof getConfigFormat>,\n rawContent: string | null,\n current: ConfigObject,\n next: ConfigObject\n): string {\n if (rawContent !== null && format.serializeUpdate) {\n return format.serializeUpdate(rawContent, current, next);\n }\n return format.serialize(next);\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 \"restoreBackup\":\n return applyRestoreBackup(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) {\n mutation.whenContentMatches.lastIndex = 0;\n }\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 if (mutation.once && (await findLatestGeneratedBackup(context.fs, targetPath)) !== null) {\n return {\n outcome: { changed: false, effect: \"none\", detail: \"noop\" },\n details\n };\n }\n\n const content = await readFileIfExists(context.fs, targetPath);\n if (content === null && !mutation.once) {\n return {\n outcome: { changed: false, effect: \"none\", detail: \"noop\" },\n details\n };\n }\n\n if (!context.dryRun) {\n const baseBackupPath = `${targetPath}.backup-${createTimestamp()}${content === null ? \".missing\" : \"\"}`;\n let attempt = 0;\n while (true) {\n const backupPath = attempt === 0 ? baseBackupPath : `${baseBackupPath}-${attempt}`;\n try {\n await assertRegularWriteTarget(context, backupPath);\n await context.fs.writeFile(backupPath, content ?? \"\", { encoding: \"utf8\", flag: \"wx\" });\n break;\n } catch (error) {\n if (!isAlreadyExists(error)) {\n throw error;\n }\n attempt += 1;\n }\n }\n }\n\n return {\n outcome: { changed: true, effect: \"copy\", detail: \"backup\" },\n details\n };\n}\n\nasync function applyRestoreBackup(\n mutation: Extract<Mutation, { kind: \"restoreBackup\" }>,\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 const details: MutationDetails = {\n kind: mutation.kind,\n label: mutation.label ?? describeMutation(mutation.kind, targetPath),\n targetPath\n };\n const backup = await findLatestGeneratedBackup(context.fs, targetPath);\n\n if (backup === null) {\n return { outcome: { changed: false, effect: \"none\", detail: \"noop\" }, details };\n }\n\n if (!context.dryRun) {\n await assertRegularWriteTarget(context, backup.path);\n if (backup.originallyMissing) {\n try {\n await context.fs.unlink(targetPath);\n } catch (error) {\n if (!isNotFound(error)) {\n throw error;\n }\n }\n } else {\n const content = await context.fs.readFile(backup.path, \"utf8\");\n await writeAtomically(context, targetPath, content);\n }\n await context.fs.unlink(backup.path);\n }\n\n return { outcome: { changed: true, effect: \"copy\", detail: \"restore\" }, details };\n}\n\nasync function findLatestGeneratedBackup(\n fs: FileSystem,\n targetPath: string\n): Promise<{ path: string; originallyMissing: boolean } | null> {\n const separatorIndex = targetPath.lastIndexOf(\"/\");\n const directoryPath = separatorIndex <= 0 ? \"/\" : targetPath.slice(0, separatorIndex);\n const targetName = targetPath.slice(separatorIndex + 1);\n let entries: string[];\n\n try {\n entries = await fs.readdir(directoryPath);\n } catch (error) {\n if (isNotFound(error)) {\n return null;\n }\n throw error;\n }\n\n const backupName = entries\n .filter((entry) => isGeneratedBackupName(entry, targetName))\n .sort()\n .at(-1);\n return backupName === undefined\n ? null\n : {\n path: `${directoryPath}/${backupName}`,\n originallyMissing: backupName.endsWith(\".missing\")\n };\n}\n\nfunction isGeneratedBackupName(entry: string, targetName: string): boolean {\n const prefix = `${targetName}.backup-`;\n if (!entry.startsWith(prefix)) {\n return false;\n }\n\n const suffix = entry.slice(prefix.length);\n const timestamp = suffix.slice(0, 24);\n if (timestamp.length !== 24 || timestamp[4] !== \"-\" || timestamp[7] !== \"-\" || timestamp[10] !== \"T\" || timestamp[13] !== \"-\" || timestamp[16] !== \"-\" || timestamp[19] !== \"-\" || timestamp[23] !== \"Z\") {\n return false;\n }\n const parsedTimestamp = `${timestamp.slice(0, 13)}:${timestamp.slice(14, 16)}:${timestamp.slice(17, 19)}.${timestamp.slice(20)}`;\n if (Number.isNaN(Date.parse(parsedTimestamp))) {\n return false;\n }\n const collisionSuffix = suffix.slice(24);\n if (collisionSuffix.length === 0) {\n return true;\n }\n if (collisionSuffix === \".missing\") {\n return true;\n }\n return collisionSuffix[0] === \"-\" && collisionSuffix.slice(1).length > 0 && [...collisionSuffix.slice(1)].every((character) => character >= \"0\" && character <= \"9\");\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 preserveContent = rawContent;\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 && !context.dryRun) {\n await backupInvalidDocument(context, targetPath, rawContent);\n }\n current = {};\n preserveContent = null;\n }\n\n const value = resolveValue(mutation.value, options);\n\n // Keep prefix pruning on the same proto-safe object-write path as normal merges.\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 = serializeConfigUpdate(format, preserveContent, current, merged);\n const changed = serialized !== rawContent;\n\n if (changed && !context.dryRun) {\n await writeAtomically(context, targetPath, serialized);\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 = serializeConfigUpdate(format, rawContent, current, result);\n if (!context.dryRun) {\n await writeAtomically(context, targetPath, serialized);\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 preserveContent = rawContent;\n let current: ConfigObject;\n try {\n current = rawContent === null ? {} : format.parse(rawContent);\n } catch {\n if (rawContent !== null && !context.dryRun) {\n await backupInvalidDocument(context, targetPath, rawContent);\n }\n current = {};\n preserveContent = null;\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 = serializeConfigUpdate(format, preserveContent, current, transformed);\n if (!context.dryRun) {\n await writeAtomically(context, targetPath, serialized);\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 = renderTemplate(template, templateContext);\n\n const current = await readFileIfExists(context.fs, targetPath);\n const changed = current !== rendered;\n\n if (changed && !context.dryRun) {\n await writeAtomically(context, targetPath, rendered);\n }\n\n return {\n outcome: {\n changed,\n effect: changed ? \"write\" : \"none\",\n detail: changed ? (current === null ? \"create\" : \"update\") : \"noop\"\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 = renderTemplate(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 && !context.dryRun) {\n await backupInvalidDocument(context, 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 writeAtomically(context, targetPath, serialized);\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", "export interface ColorSupportEnv {\n NO_COLOR?: string;\n FORCE_COLOR?: string;\n TERM?: string;\n}\n\nexport interface ColorSupportStream {\n isTTY?: boolean;\n}\n\nexport function supportsColor(\n env: ColorSupportEnv = process.env as ColorSupportEnv,\n stream: ColorSupportStream = process.stdout\n): boolean {\n if (env.FORCE_COLOR !== undefined && env.FORCE_COLOR !== \"0\") {\n return true;\n }\n\n if (env.NO_COLOR !== undefined) {\n return false;\n }\n\n if (stream.isTTY !== true) {\n return false;\n }\n\n return typeof env.TERM === \"string\" && env.TERM.length > 0 && env.TERM !== \"dumb\";\n}\n", "import { supportsColor } from \"../internal/color-support.js\";\n\ntype AnsiStyleName =\n | \"reset\"\n | \"bold\"\n | \"dim\"\n | \"italic\"\n | \"underline\"\n | \"inverse\"\n | \"strikethrough\"\n | \"black\"\n | \"red\"\n | \"green\"\n | \"yellow\"\n | \"blue\"\n | \"magenta\"\n | \"cyan\"\n | \"white\"\n | \"gray\"\n | \"magentaBright\"\n | \"cyanBright\"\n | \"bgRed\"\n | \"bgGreen\"\n | \"bgYellow\"\n | \"bgBlue\"\n | \"bgMagenta\";\n\ninterface AnsiPair {\n open: string;\n}\n\nexport interface Color {\n (text: string): string;\n reset: Color;\n bold: Color;\n dim: Color;\n italic: Color;\n underline: Color;\n inverse: Color;\n strikethrough: Color;\n black: Color;\n red: Color;\n green: Color;\n yellow: Color;\n blue: Color;\n magenta: Color;\n cyan: Color;\n white: Color;\n gray: Color;\n magentaBright: Color;\n cyanBright: Color;\n bgRed: Color;\n bgGreen: Color;\n bgYellow: Color;\n bgBlue: Color;\n bgMagenta: Color;\n hex: (value: string) => Color;\n rgb: (red: number, green: number, blue: number) => Color;\n bgHex: (value: string) => Color;\n bgRgb: (red: number, green: number, blue: number) => Color;\n}\n\nconst reset = \"\\x1b[0m\";\n\nconst ansiStyles: Record<AnsiStyleName, AnsiPair> = {\n reset: { open: reset },\n bold: { open: \"\\x1b[1m\" },\n dim: { open: \"\\x1b[2m\" },\n italic: { open: \"\\x1b[3m\" },\n underline: { open: \"\\x1b[4m\" },\n inverse: { open: \"\\x1b[7m\" },\n strikethrough: { open: \"\\x1b[9m\" },\n black: { open: \"\\x1b[30m\" },\n red: { open: \"\\x1b[31m\" },\n green: { open: \"\\x1b[32m\" },\n yellow: { open: \"\\x1b[33m\" },\n blue: { open: \"\\x1b[34m\" },\n magenta: { open: \"\\x1b[35m\" },\n cyan: { open: \"\\x1b[36m\" },\n white: { open: \"\\x1b[37m\" },\n gray: { open: \"\\x1b[90m\" },\n magentaBright: { open: \"\\x1b[95m\" },\n cyanBright: { open: \"\\x1b[96m\" },\n bgRed: { open: \"\\x1b[41m\" },\n bgGreen: { open: \"\\x1b[42m\" },\n bgYellow: { open: \"\\x1b[43m\" },\n bgBlue: { open: \"\\x1b[44m\" },\n bgMagenta: { open: \"\\x1b[45m\" }\n};\n\nconst styleNames = Object.keys(ansiStyles) as AnsiStyleName[];\n\nfunction replaceAll(value: string, search: string, replacement: string): string {\n return value.split(search).join(replacement);\n}\n\nfunction applyStyles(text: string, styles: AnsiPair[]): string {\n if (!supportsColor() || styles.length === 0) {\n return text;\n }\n\n const open = styles.map((style) => style.open).join(\"\");\n const output = text.includes(reset) ? replaceAll(text, reset, `${reset}${open}`) : text;\n\n return `${open}${output}${reset}`;\n}\n\nfunction clampRgb(value: number): number {\n if (Number.isNaN(value)) {\n return 0;\n }\n\n return Math.min(255, Math.max(0, Math.round(value)));\n}\n\nfunction hexChannel(value: string, offset: number): number {\n return Number.parseInt(value.slice(offset, offset + 2), 16);\n}\n\nfunction normalizeHex(value: string): [number, number, number] {\n const normalized = value.startsWith(\"#\") ? value.slice(1) : value;\n\n if ((normalized.length !== 3 && normalized.length !== 6) ||\n Array.from(normalized).some((char) => !\"0123456789abcdefABCDEF\".includes(char))) {\n throw new Error(`Invalid hexadecimal color: ${value}`);\n }\n\n if (normalized.length === 3) {\n const red = normalized[0]!;\n const green = normalized[1]!;\n const blue = normalized[2]!;\n\n return [\n Number.parseInt(`${red}${red}`, 16),\n Number.parseInt(`${green}${green}`, 16),\n Number.parseInt(`${blue}${blue}`, 16)\n ];\n }\n\n return [\n hexChannel(normalized, 0),\n hexChannel(normalized, 2),\n hexChannel(normalized, 4)\n ];\n}\n\nfunction rgbStyle(red: number, green: number, blue: number): AnsiPair {\n return {\n open: `\\x1b[38;2;${clampRgb(red)};${clampRgb(green)};${clampRgb(blue)}m`\n };\n}\n\nfunction bgRgbStyle(red: number, green: number, blue: number): AnsiPair {\n return {\n open: `\\x1b[48;2;${clampRgb(red)};${clampRgb(green)};${clampRgb(blue)}m`\n };\n}\n\nfunction createColor(styles: AnsiPair[] = []): Color {\n const builder = ((text: string) => applyStyles(String(text), styles)) as Color;\n\n for (const name of styleNames) {\n Object.defineProperty(builder, name, {\n configurable: true,\n enumerable: true,\n get: () => createColor([...styles, ansiStyles[name]])\n });\n }\n\n builder.hex = (value: string) => {\n const [red, green, blue] = normalizeHex(value);\n return createColor([...styles, rgbStyle(red, green, blue)]);\n };\n\n builder.rgb = (red: number, green: number, blue: number) =>\n createColor([...styles, rgbStyle(red, green, blue)]);\n\n builder.bgHex = (value: string) => {\n const [red, green, blue] = normalizeHex(value);\n return createColor([...styles, bgRgbStyle(red, green, blue)]);\n };\n\n builder.bgRgb = (red: number, green: number, blue: number) =>\n createColor([...styles, bgRgbStyle(red, green, blue)]);\n\n return builder;\n}\n\nexport const color = createColor();\n", "export interface Brand {\n name: string;\n primary: string;\n}\n\nexport const brands: Record<string, Brand> = {\n purple: { name: \"purple\", primary: \"#a200ff\" },\n blue: { name: \"blue\", primary: \"#2f6fed\" },\n green: { name: \"green\", primary: \"#1f9d57\" }\n};\n", "import { brands } from \"../tokens/brand.js\";\n\nexport interface ThemeConfig {\n brand: string;\n label: string;\n}\n\nconst defaults: ThemeConfig = {\n brand: \"purple\",\n label: \"Poe\"\n};\n\nlet config: ThemeConfig = { ...defaults };\nlet revision = 0;\nlet brandConfigured = false;\n\nexport function configureTheme(patch: { brand?: string; label?: string }): void {\n if (patch.brand !== undefined && !Object.hasOwn(brands, patch.brand)) {\n throw new Error(`Unknown brand: ${patch.brand}`);\n }\n\n config = {\n brand: patch.brand ?? config.brand,\n label: patch.label ?? config.label\n };\n if (patch.brand !== undefined) {\n brandConfigured = true;\n }\n revision += 1;\n}\n\nexport function getThemeConfig(): ThemeConfig {\n return { ...config };\n}\n\nexport function getThemeRevision(): number {\n return revision;\n}\n\nexport function isThemeBrandConfigured(): boolean {\n return brandConfigured;\n}\n\nexport function resetTheme(): void {\n config = { ...defaults };\n brandConfigured = false;\n revision += 1;\n}\n", "import { color, type Color } from \"../components/color.js\";\nimport { getThemeConfig } from \"../internal/theme-state.js\";\nimport { brands, type Brand } from \"./brand.js\";\n\nexport const brand = brands.purple!.primary;\n\nexport type ThemeName = \"dark\" | \"light\";\n\nexport interface ThemeCellStyle {\n fg?: string;\n bold?: boolean;\n dim?: boolean;\n underline?: boolean;\n}\n\nexport interface ThemeCellStyles {\n accent: ThemeCellStyle;\n muted: ThemeCellStyle;\n success: ThemeCellStyle;\n warning: ThemeCellStyle;\n error: ThemeCellStyle;\n info: ThemeCellStyle;\n}\n\nexport interface ThemePalette {\n header: (text: string) => string;\n divider: (text: string) => string;\n prompt: (text: string) => string;\n number: (text: string) => string;\n intro: (text: string) => string;\n resolvedSymbol: string;\n errorSymbol: string;\n accent: (text: string) => string;\n muted: (text: string) => string;\n success: (text: string) => string;\n warning: (text: string) => string;\n error: (text: string) => string;\n info: (text: string) => string;\n badge: (text: string) => string;\n styles: ThemeCellStyles;\n}\n\nfunction withStyles(palette: Omit<ThemePalette, \"styles\">, styles: ThemeCellStyles): ThemePalette {\n return Object.defineProperty(palette, \"styles\", {\n value: styles,\n enumerable: false\n }) as ThemePalette;\n}\n\nfunction brandColor(activeBrand: Brand, purple: Color): Color {\n return activeBrand.name === \"purple\" ? purple : color.hex(activeBrand.primary);\n}\n\nfunction brandBackground(activeBrand: Brand, purple: Color): Color {\n return activeBrand.name === \"purple\" ? purple : color.bgHex(activeBrand.primary);\n}\n\nexport function createPalette(activeBrand: Brand, mode: ThemeName): ThemePalette {\n const isPurple = activeBrand.name === \"purple\";\n if (mode === \"light\") {\n const active = color.hex(activeBrand.primary);\n const prompt = isPurple ? color.hex(\"#006699\") : active;\n const number = isPurple ? color.hex(\"#0077cc\") : active;\n return withStyles(\n {\n header: (text: string) => active.bold(text),\n divider: (text: string) => color.hex(\"#666666\")(text),\n prompt: (text: string) => prompt.bold(text),\n number: (text: string) => number.bold(text),\n intro: (text: string) =>\n color.bgHex(activeBrand.primary).white(` ${getThemeConfig().label} - ${text} `),\n get resolvedSymbol() {\n return active(\"\u25C7\");\n },\n get errorSymbol() {\n return color.hex(\"#cc0000\")(\"\u25A0\");\n },\n accent: (text: string) => prompt.bold(text),\n muted: (text: string) => color.hex(\"#666666\")(text),\n success: (text: string) => color.hex(\"#008800\")(text),\n warning: (text: string) => color.hex(\"#cc6600\")(text),\n error: (text: string) => color.hex(\"#cc0000\")(text),\n info: (text: string) => active(text),\n badge: (text: string) => color.bgHex(\"#cc6600\").white(` ${text} `)\n },\n {\n accent: { fg: isPurple ? \"#006699\" : activeBrand.primary, bold: true },\n muted: { fg: \"#666666\" },\n success: { fg: \"#008800\" },\n warning: { fg: \"#cc6600\" },\n error: { fg: \"#cc0000\" },\n info: { fg: activeBrand.primary }\n }\n );\n }\n\n const active = brandColor(activeBrand, color.magenta);\n const activeBright = brandColor(activeBrand, color.magentaBright);\n const activeBackground = brandBackground(activeBrand, color.bgMagenta);\n const prompt = isPurple ? color.cyan : active;\n const number = isPurple ? color.cyanBright : active;\n return withStyles(\n {\n header: (text: string) => activeBright.bold(text),\n divider: (text: string) => color.dim(text),\n prompt: (text: string) => prompt(text),\n number: (text: string) => number(text),\n intro: (text: string) => activeBackground.white(` ${getThemeConfig().label} - ${text} `),\n get resolvedSymbol() {\n return active(\"\u25C7\");\n },\n get errorSymbol() {\n return color.red(\"\u25A0\");\n },\n accent: (text: string) => prompt(text),\n muted: (text: string) => color.dim(text),\n success: (text: string) => color.green(text),\n warning: (text: string) => color.yellow(text),\n error: (text: string) => color.red(text),\n info: (text: string) => active(text),\n badge: (text: string) => color.bgYellow.black(` ${text} `)\n },\n {\n accent: { fg: isPurple ? \"cyan\" : activeBrand.primary, bold: true },\n muted: { dim: true },\n success: { fg: \"green\" },\n warning: { fg: \"yellow\" },\n error: { fg: \"red\" },\n info: { fg: isPurple ? \"magenta\" : activeBrand.primary }\n }\n );\n}\n\nexport const dark = createPalette(brands.purple!, \"dark\");\nexport const light = createPalette(brands.purple!, \"light\");\n", "import { AsyncLocalStorage } from \"node:async_hooks\";\n\nexport type OutputFormat = \"terminal\" | \"markdown\" | \"json\";\n\nconst VALID_FORMATS = new Set<OutputFormat>([\"terminal\", \"markdown\", \"json\"]);\nconst formatStorage = new AsyncLocalStorage<OutputFormat>();\n\nlet cached: OutputFormat | undefined;\n\nexport function resolveOutputFormat(\n env: { OUTPUT_FORMAT?: string } = process.env as { OUTPUT_FORMAT?: string }\n): OutputFormat {\n const scoped = formatStorage.getStore();\n if (scoped) {\n return scoped;\n }\n if (cached) {\n return cached;\n }\n const raw = env.OUTPUT_FORMAT?.toLowerCase();\n cached = VALID_FORMATS.has(raw as OutputFormat) ? (raw as OutputFormat) : \"terminal\";\n return cached;\n}\n\nexport function withOutputFormat<T>(format: OutputFormat, fn: () => T): T {\n return formatStorage.run(format, fn);\n}\n\nexport function resetOutputFormatCache(): void {\n cached = undefined;\n}\n", "import { getThemeConfig, getThemeRevision, isThemeBrandConfigured } from \"./theme-state.js\";\nimport { brands } from \"../tokens/brand.js\";\nimport { createPalette, dark, light, type ThemeName, type ThemePalette } from \"../tokens/colors.js\";\n\nexport interface ThemeEnv {\n POE_CODE_THEME?: string;\n POE_THEME?: string;\n POE_BRAND?: string;\n APPLE_INTERFACE_STYLE?: string;\n VSCODE_COLOR_THEME_KIND?: string;\n COLORFGBG?: string;\n}\n\nfunction detectThemeFromEnv(env: ThemeEnv): ThemeName | undefined {\n const apple = env.APPLE_INTERFACE_STYLE;\n if (typeof apple === \"string\") {\n return apple.toLowerCase() === \"dark\" ? \"dark\" : \"light\";\n }\n\n const vscodeKind = env.VSCODE_COLOR_THEME_KIND;\n if (typeof vscodeKind === \"string\") {\n const normalized = vscodeKind.toLowerCase();\n if (normalized.includes(\"light\")) {\n return \"light\";\n }\n if (normalized.includes(\"dark\")) {\n return \"dark\";\n }\n }\n\n const colorFGBG = env.COLORFGBG;\n if (typeof colorFGBG === \"string\") {\n const parts = colorFGBG.split(\";\").map((part) => Number.parseInt(part, 10));\n const background = parts.at(-1);\n if (Number.isFinite(background)) {\n return background! >= 8 ? \"light\" : \"dark\";\n }\n }\n\n return undefined;\n}\n\nexport function resolveThemeName(env: ThemeEnv = process.env as ThemeEnv): ThemeName {\n const raw = (env.POE_CODE_THEME ?? env.POE_THEME)?.toLowerCase();\n if (raw === \"light\" || raw === \"dark\") {\n return raw;\n }\n const detected = detectThemeFromEnv(env);\n if (detected) {\n return detected;\n }\n return \"dark\";\n}\n\nconst themeCache = new Map<string, ThemePalette>();\nlet cachedRevision = -1;\n\nexport function getTheme(env?: ThemeEnv): ThemePalette {\n const themeName = resolveThemeName(env);\n const config = getThemeConfig();\n const requestedBrand = env?.POE_BRAND?.toLowerCase();\n const activeBrandName =\n !isThemeBrandConfigured() && requestedBrand && Object.hasOwn(brands, requestedBrand)\n ? requestedBrand\n : config.brand;\n const revision = getThemeRevision();\n if (revision !== cachedRevision) {\n themeCache.clear();\n cachedRevision = revision;\n }\n const cacheKey = `${activeBrandName}:${themeName}`;\n const cachedTheme = themeCache.get(cacheKey);\n if (cachedTheme) {\n return cachedTheme;\n }\n const activeBrand = brands[activeBrandName]!;\n const theme =\n activeBrandName === \"purple\"\n ? themeName === \"light\"\n ? light\n : dark\n : createPalette(activeBrand, themeName);\n themeCache.set(cacheKey, theme);\n return theme;\n}\n\nexport function resetThemeCache(): void {\n themeCache.clear();\n cachedRevision = getThemeRevision();\n}\n", "import { color } from \"./color.js\";\nimport { resolveOutputFormat } from \"../internal/output-format.js\";\nimport { getTheme } from \"../internal/theme-detect.js\";\n\nexport const symbols = {\n get info(): string {\n const format = resolveOutputFormat();\n if (format === \"json\") return \"info\";\n if (format === \"markdown\") return \"(i)\";\n return color.magenta(\"\u25CF\");\n },\n get success(): string {\n const format = resolveOutputFormat();\n if (format === \"json\") return \"success\";\n if (format === \"markdown\") return \"[ok]\";\n return color.magenta(\"\u25C6\");\n },\n get resolved(): string {\n const format = resolveOutputFormat();\n if (format === \"json\") return \"resolved\";\n if (format === \"markdown\") return \">\";\n return getTheme().resolvedSymbol;\n },\n get errorResolved(): string {\n const format = resolveOutputFormat();\n if (format === \"json\") return \"error\";\n if (format === \"markdown\") return \"[!]\";\n return getTheme().errorSymbol;\n },\n get bar(): string {\n const format = resolveOutputFormat();\n if (format === \"json\") return \"\";\n if (format === \"markdown\") return \"|\";\n return \"\u2502\";\n },\n cornerTopRight: \"\u256E\",\n cornerBottomRight: \"\u256F\",\n get warning(): string {\n const format = resolveOutputFormat();\n if (format === \"json\") return \"warning\";\n if (format === \"markdown\") return \"[!]\";\n return \"\u25B2\";\n },\n get active(): string {\n const format = resolveOutputFormat();\n if (format === \"json\") return \"active\";\n if (format === \"markdown\") return \"[x]\";\n return \"\u25C6\";\n },\n get inactive(): string {\n const format = resolveOutputFormat();\n if (format === \"json\") return \"inactive\";\n if (format === \"markdown\") return \"[ ]\";\n return \"\u25CB\";\n }\n} as const;\n", "export function stripAnsi(value: string): string {\n return value.replace(/\\u001b\\[[0-9;]*m/g, \"\");\n}\n", "import { color } from \"../../components/color.js\";\nimport { symbols } from \"../../components/symbols.js\";\nimport { resolveOutputFormat } from \"../../internal/output-format.js\";\nimport { stripAnsi } from \"../../internal/strip-ansi.js\";\n\nexport interface LogMessageOptions {\n symbol?: string;\n secondarySymbol?: string;\n spacing?: number;\n withGuide?: boolean;\n}\n\nfunction renderMarkdownInline(value: string): string {\n return stripAnsi(value).replaceAll(\"\\r\\n\", \" \").replaceAll(\"\\n\", \" \").replaceAll(\"\\r\", \" \");\n}\n\nfunction writeTerminalMessage(\n msg: string,\n {\n symbol = color.gray(\"\u2502\"),\n secondarySymbol = color.gray(\"\u2502\"),\n spacing = 1,\n withGuide = true\n }: LogMessageOptions = {}\n): void {\n const lines: string[] = [];\n const showGuide = withGuide !== false;\n const contentLines = msg.split(\"\\n\");\n const prefix = showGuide ? `${symbol} ` : \"\";\n const continuationPrefix = showGuide ? `${secondarySymbol} ` : \"\";\n const emptyGuide = showGuide ? secondarySymbol : \"\";\n\n for (let index = 0; index < spacing; index += 1) {\n lines.push(emptyGuide);\n }\n\n if (contentLines.length === 0) {\n process.stdout.write(\"\\n\");\n return;\n }\n\n const [firstLine = \"\", ...continuationLines] = contentLines;\n if (firstLine.length > 0) {\n lines.push(`${prefix}${firstLine}`);\n } else {\n lines.push(showGuide ? symbol : \"\");\n }\n\n for (const line of continuationLines) {\n if (line.length > 0) {\n lines.push(`${continuationPrefix}${line}`);\n continue;\n }\n lines.push(emptyGuide);\n }\n\n process.stdout.write(`${lines.join(\"\\n\")}\\n`);\n}\n\nexport function message(msg: string, options?: LogMessageOptions): void {\n const format = resolveOutputFormat();\n if (format === \"markdown\") {\n process.stdout.write(`- ${renderMarkdownInline(msg)}\\n`);\n return;\n }\n if (format === \"json\") {\n process.stdout.write(\n `${JSON.stringify({ level: \"message\", message: stripAnsi(msg) })}\\n`\n );\n return;\n }\n\n writeTerminalMessage(msg, options);\n}\n\nexport function info(msg: string): void {\n const format = resolveOutputFormat();\n if (format === \"markdown\") {\n process.stdout.write(`- **info:** ${renderMarkdownInline(msg)}\\n`);\n return;\n }\n if (format === \"json\") {\n process.stdout.write(\n `${JSON.stringify({ level: \"info\", message: stripAnsi(msg) })}\\n`\n );\n return;\n }\n\n message(msg, { symbol: symbols.info });\n}\n\nexport function success(msg: string): void {\n const format = resolveOutputFormat();\n if (format === \"markdown\") {\n process.stdout.write(`- **success:** ${renderMarkdownInline(msg)}\\n`);\n return;\n }\n if (format === \"json\") {\n process.stdout.write(\n `${JSON.stringify({ level: \"success\", message: stripAnsi(msg) })}\\n`\n );\n return;\n }\n\n message(msg, { symbol: symbols.success });\n}\n\nexport function warn(msg: string): void {\n const format = resolveOutputFormat();\n if (format === \"markdown\") {\n process.stdout.write(`- **warning:** ${renderMarkdownInline(msg)}\\n`);\n return;\n }\n if (format === \"json\") {\n process.stdout.write(\n `${JSON.stringify({ level: \"warn\", message: stripAnsi(msg) })}\\n`\n );\n return;\n }\n\n message(msg, { symbol: color.yellow(\"\u25B2\") });\n}\n\nexport function error(msg: string): void {\n const format = resolveOutputFormat();\n if (format === \"markdown\") {\n process.stdout.write(`- **error:** ${renderMarkdownInline(msg)}\\n`);\n return;\n }\n if (format === \"json\") {\n process.stdout.write(\n `${JSON.stringify({ level: \"error\", message: stripAnsi(msg) })}\\n`\n );\n return;\n }\n\n message(msg, { symbol: color.red(\"\u25A0\") });\n}\n\nexport const log = {\n info,\n success,\n message,\n warn,\n error\n};\n", "import { color } from \"./color.js\";\nimport { log } from \"../prompts/primitives/log.js\";\nimport { symbols } from \"./symbols.js\";\n\nexport interface LoggerOutput {\n info(message: string): void;\n success(message: string): void;\n warn(message: string): void;\n error(message: string): void;\n resolved(label: string, value: string): void;\n errorResolved(label: string, value: string): void;\n message(message: string, symbol?: string): void;\n}\n\nexport function createLogger(emitter?: (message: string) => void): LoggerOutput {\n const emit = (\n level: \"info\" | \"success\" | \"warn\" | \"error\",\n message: string\n ): void => {\n if (emitter) {\n emitter(message);\n return;\n }\n if (level === \"success\") {\n log.success(message);\n return;\n }\n if (level === \"warn\") {\n log.warn(message);\n return;\n }\n if (level === \"error\") {\n log.error(message);\n return;\n }\n log.info(message);\n };\n\n return {\n info(message: string): void {\n emit(\"info\", message);\n },\n success(message: string): void {\n emit(\"success\", message);\n },\n warn(message: string): void {\n emit(\"warn\", message);\n },\n error(message: string): void {\n emit(\"error\", message);\n },\n resolved(label: string, value: string): void {\n if (emitter) {\n emitter(`${label}: ${value}`);\n return;\n }\n log.message(`${label}\\n ${value}`, { symbol: symbols.resolved });\n },\n errorResolved(label: string, value: string): void {\n if (emitter) {\n emitter(`${label}: ${value}`);\n return;\n }\n log.message(`${label}\\n ${value}`, { symbol: symbols.errorResolved });\n },\n message(message: string, symbol?: string): void {\n if (emitter) {\n emitter(message);\n return;\n }\n log.message(message, { symbol: symbol ?? color.gray(\"\u2502\") });\n }\n };\n}\n\nexport const logger = createLogger();\n", "import { text } from \"./text.js\";\n\nexport interface CommandInfo {\n name: string;\n description: string;\n}\n\nexport interface OptionInfo {\n flags: string;\n description: string;\n}\n\nexport interface FormatColumnsOptions {\n rows: Array<{ left: string; right: string }>;\n totalWidth?: number;\n minLeftWidth?: number;\n maxLeftWidth?: number;\n gap?: number;\n indent?: number;\n}\n\nconst graphemeSegmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n\nfunction normalizeInline(value: string): string {\n return value.replaceAll(\"\\r\\n\", \" \").replaceAll(\"\\n\", \" \").replaceAll(\"\\r\", \" \");\n}\n\nfunction readControlSequence(value: string, index: number): number | undefined {\n if (value[index] !== \"\\u001b\") {\n return undefined;\n }\n\n if (value[index + 1] === \"[\") {\n let nextIndex = index + 2;\n while (nextIndex < value.length) {\n const code = value.charCodeAt(nextIndex);\n nextIndex += 1;\n if (code >= 0x40 && code <= 0x7e) {\n return nextIndex;\n }\n }\n return value.length;\n }\n\n if (value[index + 1] === \"]\") {\n let nextIndex = index + 2;\n while (nextIndex < value.length) {\n if (value[nextIndex] === \"\\u0007\") {\n return nextIndex + 1;\n }\n if (value[nextIndex] === \"\\u001b\" && value[nextIndex + 1] === \"\\\\\") {\n return nextIndex + 2;\n }\n nextIndex += 1;\n }\n return value.length;\n }\n\n return index + 1;\n}\n\nfunction isWideCodePoint(codePoint: number): boolean {\n return (\n (codePoint >= 0x1100 && codePoint <= 0x115f) ||\n codePoint === 0x2329 ||\n codePoint === 0x232a ||\n (codePoint >= 0x2e80 && codePoint <= 0xa4cf && codePoint !== 0x303f) ||\n (codePoint >= 0xac00 && codePoint <= 0xd7a3) ||\n (codePoint >= 0xf900 && codePoint <= 0xfaff) ||\n (codePoint >= 0xfe10 && codePoint <= 0xfe19) ||\n (codePoint >= 0xfe30 && codePoint <= 0xfe6f) ||\n (codePoint >= 0xff00 && codePoint <= 0xff60) ||\n (codePoint >= 0xffe0 && codePoint <= 0xffe6) ||\n (codePoint >= 0x2600 && codePoint <= 0x27bf) ||\n (codePoint >= 0x1f300 && codePoint <= 0x1faff) ||\n (codePoint >= 0x20000 && codePoint <= 0x3fffd)\n );\n}\n\nfunction clusterWidth(cluster: string): number {\n const codePoints = Array.from(cluster).map((char) => char.codePointAt(0) ?? 0);\n if (codePoints.some((codePoint) => codePoint === 0x200d || (codePoint >= 0xfe00 && codePoint <= 0xfe0f))) {\n return 2;\n }\n\n return codePoints.reduce((width, codePoint) => {\n if (codePoint === 0 || codePoint < 0x20 || (codePoint >= 0x7f && codePoint < 0xa0)) {\n return width;\n }\n return width + (isWideCodePoint(codePoint) ? 2 : 1);\n }, 0);\n}\n\nfunction visibleWidth(value: string): number {\n let width = 0;\n let index = 0;\n\n while (index < value.length) {\n const nextIndex = readControlSequence(value, index);\n if (nextIndex !== undefined) {\n index = nextIndex;\n continue;\n }\n\n const segment = graphemeSegmenter.segment(value.slice(index))[Symbol.iterator]().next().value as\n | Intl.SegmentData\n | undefined;\n const cluster = segment?.segment ?? \"\";\n width += clusterWidth(cluster);\n index += cluster.length || 1;\n }\n\n return width;\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\nfunction padEndVisible(value: string, width: number): string {\n return value + \" \".repeat(Math.max(0, width - visibleWidth(value)));\n}\n\nfunction isWhitespace(char: string | undefined): boolean {\n return char === \" \" || char === \"\\n\" || char === \"\\t\" || char === \"\\r\";\n}\n\nfunction splitWords(value: string): string[] {\n const words: string[] = [];\n let word = \"\";\n\n for (const char of value) {\n if (isWhitespace(char)) {\n if (word) {\n words.push(word);\n word = \"\";\n }\n continue;\n }\n word += char;\n }\n\n if (word) {\n words.push(word);\n }\n\n return words;\n}\n\nfunction wrapWords(value: string, width: number): string[] {\n const words = splitWords(value);\n if (words.length === 0) {\n return [\"\"];\n }\n\n const lines: string[] = [];\n let line = \"\";\n\n for (const word of words) {\n if (!line) {\n line = word;\n continue;\n }\n\n if (visibleWidth(line) + 1 + visibleWidth(word) <= width) {\n line += ` ${word}`;\n continue;\n }\n\n lines.push(line);\n line = word;\n }\n\n lines.push(line);\n return lines;\n}\n\nfunction validateLayoutValue(value: number, name: keyof Omit<FormatColumnsOptions, \"rows\">): void {\n if (!Number.isFinite(value) || value < 0) {\n throw new Error(`${name} must be a finite non-negative number.`);\n }\n}\n\nexport function formatColumns(opts: FormatColumnsOptions): string {\n const rows = opts.rows.map((row) => ({\n left: normalizeInline(row.left),\n right: row.right\n }));\n if (rows.length === 0) {\n return \"\";\n }\n\n const totalWidth = opts.totalWidth ?? process.stdout.columns ?? 100;\n const minLeftWidth = opts.minLeftWidth ?? 12;\n const maxLeftWidth = opts.maxLeftWidth ?? 32;\n const gap = opts.gap ?? 3;\n const indent = opts.indent ?? 2;\n validateLayoutValue(totalWidth, \"totalWidth\");\n validateLayoutValue(minLeftWidth, \"minLeftWidth\");\n validateLayoutValue(maxLeftWidth, \"maxLeftWidth\");\n validateLayoutValue(gap, \"gap\");\n validateLayoutValue(indent, \"indent\");\n const maxLeftContentWidth = Math.max(...rows.map((row) => visibleWidth(row.left)));\n const leftWidth = clamp(maxLeftContentWidth + gap, minLeftWidth, maxLeftWidth);\n const rightWidth = Math.max(20, totalWidth - leftWidth - indent);\n const firstIndent = \" \".repeat(indent);\n const continuationIndent = \" \".repeat(indent + leftWidth);\n\n return rows\n .flatMap((row) => {\n if (row.right.length === 0) {\n return [`${firstIndent}${row.left}`];\n }\n\n const rightLines = wrapWords(row.right, rightWidth);\n if (visibleWidth(row.left) > leftWidth) {\n return [\n `${firstIndent}${row.left}`,\n ...rightLines.map((line) => `${continuationIndent}${line}`)\n ];\n }\n const firstLine = `${firstIndent}${padEndVisible(row.left, leftWidth)}${rightLines[0]}`;\n const continuationLines = rightLines\n .slice(1)\n .map((line) => `${continuationIndent}${line}`);\n return [firstLine, ...continuationLines];\n })\n .join(\"\\n\");\n}\n\nexport function formatCommand(name: string, description: string): string {\n return formatColumns({\n rows: [{ left: text.command(name), right: description }]\n });\n}\n\nexport function formatUsage(command: string, args?: string): string {\n const argsStr = args ? ` ${text.argument(args)}` : \"\";\n return `${text.usageCommand(command)}${argsStr}`;\n}\n\nexport function formatOption(flags: string, description: string): string {\n return formatColumns({\n rows: [{ left: text.option(flags), right: description }]\n });\n}\n\nexport function formatCommandList(commands: CommandInfo[]): string {\n return formatColumns({\n rows: commands.map((cmd) => ({\n left: text.command(cmd.name),\n right: cmd.description\n }))\n });\n}\n\nexport function formatOptionList(options: OptionInfo[]): string {\n return formatColumns({\n rows: options.map((opt) => ({\n left: text.option(opt.flags),\n right: opt.description\n }))\n });\n}\n\nexport const helpFormatter = {\n formatColumns,\n formatCommand,\n formatUsage,\n formatOption,\n formatCommandList,\n formatOptionList\n} as const;\n", "import type { ThemePalette } from \"../tokens/colors.js\";\nimport { widths } from \"../tokens/widths.js\";\nimport { resolveOutputFormat } from \"../internal/output-format.js\";\nimport { stripAnsi } from \"../internal/strip-ansi.js\";\n\nexport interface TableColumn {\n name: string;\n title: string;\n alignment: \"left\" | \"right\";\n maxLen: number;\n}\n\nexport interface RenderTableOptions {\n theme: ThemePalette;\n columns: TableColumn[];\n rows: Record<string, string>[];\n variant?: \"table\" | \"detail\";\n maxWidth?: number;\n}\n\ntype TableAlignment = TableColumn[\"alignment\"] | \"center\";\n\ninterface ComputedColumn {\n name: string;\n title: string;\n alignment: TableAlignment;\n width: number;\n}\n\nconst reset = \"\\x1b[0m\";\nconst ellipsis = \"\u2026\";\nconst graphemeSegmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n\nfunction getCell(row: Record<string, string>, name: string): string {\n return Object.prototype.hasOwnProperty.call(row, name) ? row[name] ?? \"\" : \"\";\n}\n\nfunction renderMarkdownCell(value: string): string {\n return stripAnsi(value)\n .replaceAll(\"\\r\\n\", \" \")\n .replaceAll(\"\\n\", \" \")\n .replaceAll(\"\\r\", \" \")\n .replaceAll(\"|\", \"\\\\|\");\n}\n\nfunction isAnsiSequence(value: string, index: number): boolean {\n return value[index] === \"\\u001b\" && value[index + 1] === \"[\";\n}\n\nfunction readAnsiSequence(value: string, index: number): { sequence: string; nextIndex: number } {\n let nextIndex = index + 2;\n while (nextIndex < value.length && value[nextIndex] !== \"m\") {\n nextIndex += 1;\n }\n\n if (nextIndex < value.length) {\n nextIndex += 1;\n }\n\n return { sequence: value.slice(index, nextIndex), nextIndex };\n}\n\nfunction isCombiningCodePoint(codePoint: number): boolean {\n return (\n (codePoint >= 0x0300 && codePoint <= 0x036f) ||\n (codePoint >= 0x1ab0 && codePoint <= 0x1aff) ||\n (codePoint >= 0x1dc0 && codePoint <= 0x1dff) ||\n (codePoint >= 0x20d0 && codePoint <= 0x20ff) ||\n (codePoint >= 0xfe20 && codePoint <= 0xfe2f)\n );\n}\n\nfunction isWideCodePoint(codePoint: number): boolean {\n return (\n (codePoint >= 0x1100 && codePoint <= 0x115f) ||\n codePoint === 0x2329 ||\n codePoint === 0x232a ||\n (codePoint >= 0x2e80 && codePoint <= 0xa4cf && codePoint !== 0x303f) ||\n (codePoint >= 0xac00 && codePoint <= 0xd7a3) ||\n (codePoint >= 0xf900 && codePoint <= 0xfaff) ||\n (codePoint >= 0xfe10 && codePoint <= 0xfe19) ||\n (codePoint >= 0xfe30 && codePoint <= 0xfe6f) ||\n (codePoint >= 0xff00 && codePoint <= 0xff60) ||\n (codePoint >= 0xffe0 && codePoint <= 0xffe6) ||\n (codePoint >= 0x2600 && codePoint <= 0x27bf) ||\n (codePoint >= 0x1f300 && codePoint <= 0x1faff) ||\n (codePoint >= 0x20000 && codePoint <= 0x3fffd)\n );\n}\n\nfunction isEmojiClusterCodePoint(codePoint: number): boolean {\n return (\n (codePoint >= 0x1f1e6 && codePoint <= 0x1f1ff) ||\n (codePoint >= 0x1f300 && codePoint <= 0x1faff) ||\n (codePoint >= 0x2600 && codePoint <= 0x27bf)\n );\n}\n\nfunction codePointWidth(char: string): number {\n const codePoint = char.codePointAt(0) ?? 0;\n\n if (codePoint === 0 || codePoint < 0x20 || (codePoint >= 0x7f && codePoint < 0xa0)) {\n return 0;\n }\n\n if (\n codePoint === 0x200d ||\n (codePoint >= 0xfe00 && codePoint <= 0xfe0f) ||\n isCombiningCodePoint(codePoint)\n ) {\n return 0;\n }\n\n return isWideCodePoint(codePoint) ? 2 : 1;\n}\n\nfunction readPrintableCluster(value: string, index: number): string {\n const nextAnsiIndex = value.indexOf(\"\\u001b[\", index);\n const plainText = value.slice(index, nextAnsiIndex === -1 ? undefined : nextAnsiIndex);\n const firstSegment = graphemeSegmenter.segment(plainText)[Symbol.iterator]().next().value as\n | Intl.SegmentData\n | undefined;\n\n return firstSegment?.segment ?? Array.from(plainText)[0] ?? \"\";\n}\n\nfunction clusterWidth(cluster: string): number {\n const codePoints = Array.from(cluster).map((char) => char.codePointAt(0) ?? 0);\n const isEmojiCluster =\n codePoints.length > 1 &&\n codePoints.some(\n (codePoint) =>\n codePoint === 0x200d ||\n (codePoint >= 0xfe00 && codePoint <= 0xfe0f) ||\n isEmojiClusterCodePoint(codePoint)\n );\n\n if (isEmojiCluster) {\n return 2;\n }\n\n return codePoints.reduce((width, codePoint) => width + codePointWidth(String.fromCodePoint(codePoint)), 0);\n}\n\nfunction displayWidth(value: string): number {\n let width = 0;\n let index = 0;\n\n while (index < value.length) {\n if (isAnsiSequence(value, index)) {\n index = readAnsiSequence(value, index).nextIndex;\n continue;\n }\n\n const cluster = readPrintableCluster(value, index);\n width += clusterWidth(cluster);\n index += cluster.length;\n }\n\n return width;\n}\n\nfunction truncateToWidth(value: string, width: number): string {\n if (displayWidth(value) <= width) {\n return value;\n }\n\n if (width <= 0) {\n return \"\";\n }\n\n const targetWidth = width <= 1 ? 0 : width - displayWidth(ellipsis);\n let output = \"\";\n let currentWidth = 0;\n let index = 0;\n let sawAnsi = false;\n\n while (index < value.length) {\n if (isAnsiSequence(value, index)) {\n const ansi = readAnsiSequence(value, index);\n sawAnsi = true;\n output += ansi.sequence;\n index = ansi.nextIndex;\n continue;\n }\n\n const cluster = readPrintableCluster(value, index);\n const width = clusterWidth(cluster);\n if (currentWidth + width > targetWidth) {\n break;\n }\n\n output += cluster;\n currentWidth += width;\n index += cluster.length;\n }\n\n return `${output}${ellipsis}${sawAnsi ? reset : \"\"}`;\n}\n\nfunction padCell(value: string, width: number, alignment: TableAlignment): string {\n const visibleWidth = displayWidth(value);\n const padding = Math.max(0, width - visibleWidth);\n\n if (alignment === \"right\") {\n return `${\" \".repeat(padding)}${value}`;\n }\n\n if (alignment === \"center\") {\n const left = Math.floor(padding / 2);\n const right = padding - left;\n return `${\" \".repeat(left)}${value}${\" \".repeat(right)}`;\n }\n\n return `${value}${\" \".repeat(padding)}`;\n}\n\nfunction getAlignment(column: TableColumn): TableAlignment {\n const alignment = (column as { alignment: TableAlignment }).alignment;\n return alignment === \"right\" || alignment === \"center\" ? alignment : \"left\";\n}\n\nfunction getColumnWidth(column: TableColumn): number {\n if (!Number.isFinite(column.maxLen) || column.maxLen <= 0) {\n throw new Error(\"maxLen must be a positive finite number.\");\n }\n const configuredMin = (column as { minLen?: number }).minLen;\n const minWidth = Math.max(1, configuredMin ?? 1);\n return Math.max(minWidth, column.maxLen);\n}\n\nfunction computeColumns(columns: TableColumn[]): ComputedColumn[] {\n return columns.map((column) => ({\n name: column.name,\n title: column.title,\n alignment: getAlignment(column),\n width: getColumnWidth(column)\n }));\n}\n\nfunction renderBorder(\n columns: ComputedColumn[],\n theme: ThemePalette,\n parts: { left: string; mid: string; right: string }\n): string {\n const horizontal = theme.muted(\"\u2500\");\n const segments = columns.map((column) => horizontal.repeat(column.width + 2));\n return [\n theme.muted(parts.left),\n segments.join(theme.muted(parts.mid)),\n theme.muted(parts.right)\n ].join(\"\");\n}\n\nfunction renderTerminalRow(values: string[], columns: ComputedColumn[], theme: ThemePalette): string {\n const vertical = theme.muted(\"\u2502\");\n const cells = values.map((value, index) => {\n const column = columns[index]!;\n const truncated = truncateToWidth(value, column.width);\n return ` ${padCell(truncated, column.width, column.alignment)} `;\n });\n\n return `${vertical}${cells.join(vertical)}${vertical}`;\n}\n\nfunction wrapDetailValue(value: string, width: number): string[] {\n const lines: string[] = [];\n\n for (const paragraph of value.split(\"\\n\")) {\n let line = \"\";\n\n for (const rawWord of paragraph.split(\" \")) {\n const words: string[] = [];\n let word = rawWord;\n\n while (displayWidth(word) > width) {\n let chunk = \"\";\n let index = 0;\n\n while (index < word.length) {\n const cluster = readPrintableCluster(word, index);\n if (displayWidth(`${chunk}${cluster}`) > width) {\n break;\n }\n chunk += cluster;\n index += cluster.length;\n }\n\n words.push(chunk);\n word = word.slice(chunk.length);\n }\n\n words.push(word);\n\n for (const word of words) {\n if (line.length === 0) {\n line = word;\n continue;\n }\n\n if (displayWidth(`${line} ${word}`) <= width) {\n line = `${line} ${word}`;\n continue;\n }\n\n lines.push(line);\n line = word;\n }\n }\n\n lines.push(line);\n }\n\n return lines.length > 0 ? lines : [\"\"];\n}\n\nfunction renderTableTerminal(options: RenderTableOptions): string {\n const { theme, columns, rows } = options;\n const computedColumns = computeColumns(columns);\n if (options.variant === \"detail\") {\n const labelColumn = computedColumns[0];\n const valueColumn = computedColumns[1];\n if (!labelColumn || !valueColumn) {\n return \"\";\n }\n\n const detailLabelWidth = widths.helpColumn + 12;\n const labelWidth = Math.min(labelColumn.width, detailLabelWidth);\n const valueWidth = Math.max(20, (options.maxWidth ?? widths.maxLine) - labelWidth - 2);\n const continuation = \" \".repeat(labelWidth + 2);\n\n return rows\n .flatMap((row) => {\n const label = truncateToWidth(getCell(row, labelColumn.name), labelWidth);\n const values = wrapDetailValue(getCell(row, valueColumn.name), valueWidth);\n if (values.length === 1 && values[0] === \"\") {\n return [theme.header(label)];\n }\n return [\n `${theme.muted(padCell(label, labelWidth, \"left\"))} ${values[0] ?? \"\"}`,\n ...values.slice(1).map((value) => `${continuation}${value}`)\n ];\n })\n .join(\"\\n\");\n }\n\n const separatorOptions = options as { rowSeparator?: boolean; rowSeparators?: boolean };\n const includeRowSeparators =\n separatorOptions.rowSeparator === true || separatorOptions.rowSeparators === true;\n\n const top = renderBorder(computedColumns, theme, { left: \"\u250C\", mid: \"\u252C\", right: \"\u2510\" });\n const header = renderTerminalRow(\n computedColumns.map((column) => theme.header(column.title)),\n computedColumns,\n theme\n );\n const headerBottom = renderBorder(computedColumns, theme, { left: \"\u251C\", mid: \"\u253C\", right: \"\u2524\" });\n const bottom = renderBorder(computedColumns, theme, { left: \"\u2514\", mid: \"\u2534\", right: \"\u2518\" });\n\n const renderedRows: string[] = [];\n for (const [index, row] of rows.entries()) {\n if (includeRowSeparators && index > 0) {\n renderedRows.push(headerBottom);\n }\n renderedRows.push(\n renderTerminalRow(\n computedColumns.map((column) => getCell(row, column.name)),\n computedColumns,\n theme\n )\n );\n }\n\n return [top, header, headerBottom, ...renderedRows, bottom].join(\"\\n\");\n}\n\nfunction renderTableMarkdown(options: RenderTableOptions): string {\n const { columns, rows } = options;\n\n const header = `| ${columns.map((c) => renderMarkdownCell(c.title)).join(\" | \")} |`;\n const separator = `| ${columns\n .map((c) => {\n const alignment = getAlignment(c);\n if (alignment === \"right\") {\n return \"---:\";\n }\n if (alignment === \"center\") {\n return \":---:\";\n }\n return \":---\";\n })\n .join(\" | \")} |`;\n\n const dataRows = rows.map(\n (row) =>\n `| ${columns.map((c) => renderMarkdownCell(getCell(row, c.name))).join(\" | \")} |`\n );\n\n return [header, separator, ...dataRows].join(\"\\n\");\n}\n\nfunction renderTableJson(options: RenderTableOptions): string {\n const { columns, rows } = options;\n\n const cleaned = rows.map((row) => {\n const obj = Object.create(null) as Record<string, string>;\n for (const col of columns) {\n obj[col.name] = stripAnsi(getCell(row, col.name));\n }\n return obj;\n });\n\n return JSON.stringify(cleaned, null, 2);\n}\n\nexport function renderTable(options: RenderTableOptions): string {\n const format = resolveOutputFormat();\n switch (format) {\n case \"markdown\":\n return renderTableMarkdown(options);\n case \"json\":\n return renderTableJson(options);\n default:\n return renderTableTerminal(options);\n }\n}\n", "import { spawn } from \"node:child_process\";\nimport process from \"node:process\";\n\ninterface BrowserProcess {\n once(event: \"error\", listener: (error: Error) => void): this;\n once(event: \"close\", listener: (code: number | null, signal: NodeJS.Signals | null) => void): this;\n unref(): void;\n}\n\ntype SpawnBrowserProcess = (\n command: string,\n args: string[],\n options: { detached: true; stdio: \"ignore\" }\n) => BrowserProcess;\n\nexport interface OpenExternalOptions {\n platform?: NodeJS.Platform;\n spawnProcess?: SpawnBrowserProcess;\n}\n\nexport async function openExternal(url: string, options: OpenExternalOptions = {}): Promise<void> {\n const parsed = new URL(url);\n const { command, args } = browserCommand(parsed.href, options.platform ?? process.platform);\n await launchBrowser(command, args, options.spawnProcess ?? spawn);\n}\n\nfunction browserCommand(url: string, platform: NodeJS.Platform): { command: string; args: string[] } {\n if (platform === \"darwin\") {\n return { command: \"open\", args: [url] };\n }\n\n if (platform === \"win32\") {\n return { command: \"rundll32.exe\", args: [\"url.dll,FileProtocolHandler\", url] };\n }\n\n return { command: \"xdg-open\", args: [url] };\n}\n\nfunction launchBrowser(\n command: string,\n args: string[],\n spawnProcess: SpawnBrowserProcess\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawnProcess(command, args, { detached: true, stdio: \"ignore\" });\n\n child.once(\"error\", reject);\n child.once(\"close\", (code, signal) => {\n if (code !== 0) {\n const reason = code === null ? `signal ${signal ?? \"unknown\"}` : `code ${code}`;\n reject(new Error(`Browser launcher exited with ${reason}`));\n return;\n }\n\n child.unref();\n resolve();\n });\n });\n}\n", "import { AsyncLocalStorage } from \"node:async_hooks\";\n\nexport type AcpLineWriter = (line: string) => void;\n\nconst storage = new AsyncLocalStorage<AcpLineWriter>();\n\nconst defaultWriter: AcpLineWriter = (line) => {\n process.stdout.write(`${line}\\n`);\n};\n\n/**\n * Return the writer active in the current async context, or the default\n * stdout writer if none is bound.\n */\nexport function getAcpWriter(): AcpLineWriter {\n return storage.getStore() ?? defaultWriter;\n}\n\n/**\n * Run `fn` with `writer` bound as the active ACP line writer. All calls to\n * `renderAgentMessage`, `renderToolStart`, `renderAcpEvent`, etc. made inside\n * `fn` (or async work awaited from `fn`) will go through `writer` instead of\n * writing to `process.stdout`.\n */\nexport function withAcpWriter<T>(writer: AcpLineWriter, fn: () => Promise<T>): Promise<T> {\n return storage.run(writer, fn);\n}\n", "const graphemeSegmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n\nexport function graphemes(value: string): string[] {\n return Array.from(graphemeSegmenter.segment(value), ({ segment }) => segment);\n}\n\nexport function displayWidth(value: string, startColumn = 0): number {\n let column = startColumn;\n\n for (const segment of graphemes(value)) {\n if (segment === \"\\t\") {\n column += 8 - (column % 8);\n continue;\n }\n\n column += graphemeWidth(segment);\n }\n\n return column - startColumn;\n}\n\nexport function expandTabs(value: string, startColumn = 0): string {\n let column = startColumn;\n let expanded = \"\";\n\n for (const segment of graphemes(value)) {\n if (segment === \"\\t\") {\n const spaces = 8 - (column % 8);\n expanded += \" \".repeat(spaces);\n column += spaces;\n continue;\n }\n\n expanded += segment;\n column += graphemeWidth(segment);\n }\n\n return expanded;\n}\n\nexport function graphemeWidth(segment: string): number {\n const codePoint = segment.codePointAt(0);\n\n if (codePoint === undefined || isZeroWidthCodePoint(codePoint)) {\n return 0;\n }\n\n return isWideCodePoint(codePoint) || isFlagSegment(segment) ? 2 : 1;\n}\n\nfunction isZeroWidthCodePoint(codePoint: number): boolean {\n return (codePoint >= 0x0300 && codePoint <= 0x036f)\n || (codePoint >= 0x1ab0 && codePoint <= 0x1aff)\n || (codePoint >= 0x1dc0 && codePoint <= 0x1dff)\n || (codePoint >= 0x20d0 && codePoint <= 0x20ff)\n || (codePoint >= 0xfe20 && codePoint <= 0xfe2f);\n}\n\nfunction isFlagSegment(segment: string): boolean {\n const codePoints = [...segment].map((character) => character.codePointAt(0));\n return codePoints.length === 2\n && codePoints.every(\n (codePoint) => codePoint !== undefined && codePoint >= 0x1f1e6 && codePoint <= 0x1f1ff\n );\n}\n\nfunction isWideCodePoint(codePoint: number): boolean {\n return (\n (codePoint >= 0x1100 && codePoint <= 0x115f)\n || codePoint === 0x2329\n || codePoint === 0x232a\n || (codePoint >= 0x2e80 && codePoint <= 0x303e)\n || (codePoint >= 0x3041 && codePoint <= 0x33bf)\n || (codePoint >= 0x3400 && codePoint <= 0x4dbf)\n || (codePoint >= 0x4e00 && codePoint <= 0xa4cf)\n || (codePoint >= 0xa960 && codePoint <= 0xa97f)\n || (codePoint >= 0xac00 && codePoint <= 0xd7af)\n || (codePoint >= 0xf900 && codePoint <= 0xfaff)\n || (codePoint >= 0xfe10 && codePoint <= 0xfe19)\n || (codePoint >= 0xfe30 && codePoint <= 0xfe6f)\n || (codePoint >= 0xff00 && codePoint <= 0xff60)\n || (codePoint >= 0xffe0 && codePoint <= 0xffe6)\n || (codePoint >= 0x1b000 && codePoint <= 0x1b0ff)\n || codePoint === 0x1f004\n || codePoint === 0x1f0cf\n || (codePoint >= 0x1f200 && codePoint <= 0x1fffd)\n || (codePoint >= 0x20000 && codePoint <= 0x2fffd)\n || (codePoint >= 0x30000 && codePoint <= 0x3fffd)\n );\n}\n", "import readline from \"node:readline\";\nimport { PassThrough } from \"node:stream\";\nimport { cellToAnsi } from \"./buffer.js\";\nimport type { Cell } from \"./types.js\";\n\nexport type KeypressEvent = {\n name?: string;\n ch?: string;\n ctrl: boolean;\n meta: boolean;\n shift: boolean;\n};\n\nexport type TerminalDriver = {\n enterRawMode(): void;\n exitRawMode(): void;\n enterAltScreen(): void;\n exitAltScreen(): void;\n disableLineWrap(): void;\n enableLineWrap(): void;\n hideCursor(): void;\n showCursor(): void;\n moveTo(x: number, y: number): void;\n write(text: string): void;\n flush(changes: Array<{ x: number; y: number; cell: Cell }>): void;\n getSize(): { cols: number; rows: number };\n onResize(handler: () => void): () => void;\n onKeypress(handler: (key: KeypressEvent) => void): () => void;\n destroy(): void;\n};\n\ntype ReadlineKey = {\n sequence?: string;\n name?: string;\n ctrl?: boolean;\n meta?: boolean;\n shift?: boolean;\n};\n\ntype KeypressInput = NodeJS.ReadableStream & {\n on(event: \"keypress\", listener: (str: string | undefined, key: ReadlineKey) => void): KeypressInput;\n off(event: \"keypress\", listener: (str: string | undefined, key: ReadlineKey) => void): KeypressInput;\n};\n\ntype TerminalInput = NodeJS.ReadStream & KeypressInput & {\n setRawMode?: (mode: boolean) => void;\n};\n\ntype TerminalOutput = NodeJS.WriteStream & {\n columns?: number;\n rows?: number;\n on(event: \"resize\", listener: () => void): TerminalOutput;\n off(event: \"resize\", listener: () => void): TerminalOutput;\n};\n\nexport function createTerminalDriver(opts?: {\n stdin?: NodeJS.ReadStream;\n stdout?: NodeJS.WriteStream;\n}): TerminalDriver {\n const stdin = (opts?.stdin ?? process.stdin) as TerminalInput;\n const stdout = (opts?.stdout ?? process.stdout) as TerminalOutput;\n const resizeListeners = new Set<() => void>();\n const keypressListeners = new Set<(str: string | undefined, key: ReadlineKey) => void>();\n let rawMode = false;\n let altScreen = false;\n let lineWrapEnabled = true;\n let cursorHidden = false;\n let destroyed = false;\n\n readline.emitKeypressEvents(stdin);\n\n function enterRawMode(): void {\n if (destroyed || rawMode) {\n return;\n }\n\n stdin.setRawMode?.(true);\n stdin.resume();\n rawMode = true;\n }\n\n function exitRawMode(): void {\n if (destroyed || !rawMode) {\n return;\n }\n\n stdin.setRawMode?.(false);\n stdin.pause();\n rawMode = false;\n }\n\n function enterAltScreen(): void {\n if (destroyed || altScreen) {\n return;\n }\n\n write(\"\\u001b[?1049h\");\n altScreen = true;\n }\n\n function exitAltScreen(): void {\n if (destroyed || !altScreen) {\n return;\n }\n\n write(\"\\u001b[?1049l\");\n altScreen = false;\n }\n\n function disableLineWrap(): void {\n if (destroyed || !lineWrapEnabled) {\n return;\n }\n\n write(\"\\u001b[?7l\");\n lineWrapEnabled = false;\n }\n\n function enableLineWrap(): void {\n if (destroyed || lineWrapEnabled) {\n return;\n }\n\n write(\"\\u001b[?7h\");\n lineWrapEnabled = true;\n }\n\n function hideCursor(): void {\n if (destroyed || cursorHidden) {\n return;\n }\n\n write(\"\\u001b[?25l\");\n cursorHidden = true;\n }\n\n function showCursor(): void {\n if (destroyed || !cursorHidden) {\n return;\n }\n\n write(\"\\u001b[?25h\");\n cursorHidden = false;\n }\n\n function moveTo(x: number, y: number): void {\n if (destroyed) {\n return;\n }\n\n write(cursorPositionAnsi(x, y));\n }\n\n function write(text: string): void {\n if (destroyed || text.length === 0) {\n return;\n }\n\n stdout.write(text);\n }\n\n function flush(changes: Array<{ x: number; y: number; cell: Cell }>): void {\n if (destroyed || changes.length === 0) {\n return;\n }\n\n let output = \"\";\n\n for (const change of changes) {\n output += `${cursorPositionAnsi(change.x, change.y)}${cellToAnsi(change.cell)}`;\n }\n\n write(output);\n }\n\n function getSize(): { cols: number; rows: number } {\n return {\n cols: normalizeSize(stdout.columns),\n rows: normalizeSize(stdout.rows)\n };\n }\n\n function onResize(handler: () => void): () => void {\n if (destroyed) {\n return () => {};\n }\n\n const listener = () => {\n handler();\n };\n\n resizeListeners.add(listener);\n stdout.on(\"resize\", listener);\n\n return () => {\n if (!resizeListeners.delete(listener)) {\n return;\n }\n\n stdout.off(\"resize\", listener);\n };\n }\n\n function onKeypress(handler: (key: KeypressEvent) => void): () => void {\n if (destroyed) {\n return () => {};\n }\n\n const listener = (str: string | undefined, key: ReadlineKey) => {\n const event = toKeypressEvent(str, key);\n if (event !== undefined) {\n handler(event);\n }\n };\n\n keypressListeners.add(listener);\n stdin.on(\"keypress\", listener);\n\n return () => {\n if (!keypressListeners.delete(listener)) {\n return;\n }\n\n stdin.off(\"keypress\", listener);\n };\n }\n\n function destroy(): void {\n if (destroyed) {\n return;\n }\n\n for (const listener of keypressListeners) {\n stdin.off(\"keypress\", listener);\n }\n keypressListeners.clear();\n\n for (const listener of resizeListeners) {\n stdout.off(\"resize\", listener);\n }\n resizeListeners.clear();\n\n exitRawMode();\n enableLineWrap();\n exitAltScreen();\n showCursor();\n destroyed = true;\n }\n\n return {\n enterRawMode,\n exitRawMode,\n enterAltScreen,\n exitAltScreen,\n disableLineWrap,\n enableLineWrap,\n hideCursor,\n showCursor,\n moveTo,\n write,\n flush,\n getSize,\n onResize,\n onKeypress,\n destroy\n };\n}\n\nexport function parseKeypress(data: Buffer): KeypressEvent | undefined {\n if (data.length === 0) {\n return undefined;\n }\n\n const stream = new PassThrough();\n const stdin = stream as unknown as KeypressInput;\n let event: KeypressEvent | undefined;\n\n readline.emitKeypressEvents(stdin);\n stdin.on(\"keypress\", (str, key) => {\n event = toKeypressEvent(str, key);\n });\n stream.emit(\"data\", data);\n stream.destroy();\n\n return event;\n}\n\nfunction toKeypressEvent(str: string | undefined, key: ReadlineKey | undefined): KeypressEvent | undefined {\n const controlCharacter = controlCharacterToKeypress(key?.sequence);\n if (controlCharacter !== undefined) {\n return controlCharacter;\n }\n\n const ctrl = key?.ctrl ?? false;\n const meta = key?.meta ?? false;\n const shift = key?.shift ?? false;\n const ch = extractPrintableCharacter(str, key?.sequence);\n\n if (ch !== undefined) {\n return { ch, ctrl, meta, shift };\n }\n\n if (key?.name === undefined) {\n return undefined;\n }\n\n return {\n name: key.name,\n ctrl,\n meta,\n shift\n };\n}\n\nfunction extractPrintableCharacter(str: string | undefined, sequence: string | undefined): string | undefined {\n if (isPrintableCharacter(str)) {\n return str;\n }\n\n if (isSinglePrintableSequence(sequence)) {\n return sequence;\n }\n\n if (sequence === undefined || sequence.length <= 1 || sequence[0] !== \"\\u001b\") {\n return undefined;\n }\n\n const candidate = sequence.slice(1);\n return isPrintableCharacter(candidate) ? candidate : undefined;\n}\n\nfunction isSinglePrintableSequence(value: string | undefined): boolean {\n if (value === undefined || Array.from(value).length !== 1) {\n return false;\n }\n\n const codePoint = value.codePointAt(0);\n return codePoint !== undefined && codePoint >= 0x20 && codePoint !== 0x7f;\n}\n\nfunction isPrintableCharacter(value: string | undefined): value is string {\n if (value === undefined || Array.from(value).length !== 1) {\n return false;\n }\n\n const codePoint = value.codePointAt(0);\n return codePoint !== undefined && codePoint >= 0x20 && codePoint !== 0x7f;\n}\n\nfunction controlCharacterToKeypress(sequence: string | undefined): KeypressEvent | undefined {\n if (sequence === \"\\u001f\") {\n return { ch: \"/\", ctrl: true, meta: false, shift: false };\n }\n\n if (sequence !== undefined && sequence.length === 1) {\n const code = sequence.charCodeAt(0);\n if (code >= 1 && code <= 26 && code !== 9 && code !== 10 && code !== 13) {\n return {\n name: String.fromCharCode(code + 96),\n ctrl: true,\n meta: false,\n shift: false\n };\n }\n }\n\n return undefined;\n}\n\nfunction cursorPositionAnsi(x: number, y: number): string {\n return `\\u001b[${normalizeCoordinate(y) + 1};${normalizeCoordinate(x) + 1}H`;\n}\n\nfunction normalizeCoordinate(value: number): number {\n return Math.max(0, Math.floor(value));\n}\n\nfunction normalizeSize(value: number | undefined): number {\n if (value === undefined || !Number.isFinite(value)) {\n return 0;\n }\n\n return Math.max(0, Math.floor(value));\n}\n", "import { resolveBindings, type ResolvedBindings } from \"./keymap.js\";\n\nexport type Tone = \"success\" | \"warning\" | \"error\" | \"info\" | \"muted\";\n\nexport interface Row {\n id: string;\n title: string;\n subtitle?: string;\n badge?: { text: string; tone?: Tone };\n group?: string; // grouped rendering; rows with same group cluster under a header\n}\n\nexport interface DetailItem {\n id: string;\n title?: string; // absent => item fills pane with no cursor / no selection chrome\n subtitle?: string;\n badge?: { text: string; tone?: Tone };\n render: (ctx: DetailCtx) => string | Promise<string>;\n renderedContent?: string;\n}\n\nexport interface Detail<R> {\n items: (row: Row, ctx: DetailCtx) => Promise<DetailItem[]>;\n actions?: Action<R>[]; // run against the focused detail item\n}\n\nexport interface DetailCtx { width: number; height: number; signal: AbortSignal; row: Row }\n\nexport interface Action<R> {\n id: string;\n label: string | (() => string); // function form re-evaluated when state changes\n key?: string | string[];\n predicate?: (ctx: ActionContext<R>) => boolean;\n handler: (ctx: ActionContext<R>) => void | Promise<void>;\n destructive?: boolean;\n primary?: boolean; // bound to Enter\n showInFooter?: boolean; // default true\n}\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport interface ActionContext<R> {\n row: Row; // currently highlighted left-pane row\n rows: Row[]; // multi-select; falls back to [row] if no selection\n item?: DetailItem; // populated for actions declared under detail.actions\n filter: string;\n refresh: () => Promise<void>;\n suspendAnd: <T>(fn: () => Promise<T>) => Promise<T>;\n toast: (msg: string, tone?: Tone) => void;\n confirm: (prompt: string) => Promise<boolean>;\n exit: (after?: () => void | Promise<void>) => void;\n}\n\nexport interface ReorderContext {\n refresh: () => Promise<void>;\n toast: (msg: string, tone?: Tone) => void;\n}\n\nexport interface ExplorerConfig<R> {\n title: string;\n rows: () => Promise<Row[]>;\n refresh?: () => Promise<void>;\n detail: Detail<R>;\n actions: Action<R>[];\n reorder?: { onReorder: (orderedIds: string[], ctx?: ReorderContext) => void | Promise<void> };\n multiSelect?: boolean;\n keybindOverrides?: Record<string, string | string[]>;\n emptyHint?: string;\n initialFilter?: string;\n}\n\nexport const REGION_HEADER = 1 << 0;\nexport const REGION_LIST = 1 << 1;\nexport const REGION_DETAIL = 1 << 2;\nexport const REGION_FOOTER = 1 << 3;\nexport const REGION_MODAL = 1 << 4;\nexport const REGION_TOAST = 1 << 5;\nexport const REGION_ALL =\n REGION_HEADER |\n REGION_LIST |\n REGION_DETAIL |\n REGION_FOOTER |\n REGION_MODAL |\n REGION_TOAST;\n\nexport type Dirty = number;\n\nexport type ExplorerLayoutMode =\n | \"wide\"\n | \"medium\"\n | \"narrow-vertical\"\n | \"narrow-list-only\"\n | \"too-narrow\";\n\nexport interface ExplorerSize {\n cols: number;\n rows: number;\n}\n\nexport interface ExplorerState {\n title: string;\n emptyHint: string;\n rows: Row[];\n filtered: number[];\n matchPositions: Map<number, number[]>;\n cursor: number;\n filter: string;\n filterFocused: boolean;\n focused: \"list\" | \"detail\";\n detail: {\n rowId: string | null;\n items: DetailItem[] | null;\n cursor: number;\n scroll: number;\n token: number;\n loading: boolean;\n };\n selected: Set<string>;\n multiSelect: boolean;\n modal:\n | null\n | { kind: \"help\" }\n | { kind: \"confirm\"; action: Action<unknown>; rows: Row[]; resolver: (ok: boolean) => void }\n | { kind: \"palette\"; query: string; cursor: number };\n toast: { message: string; tone: Tone; expiresAt: number } | null;\n dirty: Dirty;\n size: ExplorerSize;\n layout: ExplorerLayoutMode;\n bindings: ResolvedBindings;\n actionState: Map<string, ActionStateEntry>;\n}\n\nexport interface ActionStateEntry {\n available: boolean;\n label: string;\n running?: boolean;\n action?: Action<unknown>;\n source?: \"row\" | \"detail\";\n}\n\nexport function createInitialState<R>(\n config: ExplorerConfig<R>,\n size: ExplorerSize\n): ExplorerState {\n const normalizedSize = {\n cols: normalizeSize(size.cols),\n rows: normalizeSize(size.rows)\n };\n const multiSelect = config.multiSelect ?? true;\n\n return {\n title: config.title,\n emptyHint: config.emptyHint ?? \"No detail\",\n rows: [],\n filtered: [],\n matchPositions: new Map(),\n cursor: 0,\n filter: config.initialFilter ?? \"\",\n filterFocused: false,\n focused: \"list\",\n detail: {\n rowId: null,\n items: null,\n cursor: 0,\n scroll: 0,\n token: 0,\n loading: false\n },\n selected: new Set(),\n multiSelect,\n modal: null,\n toast: null,\n dirty: REGION_ALL,\n size: normalizedSize,\n layout: resolveExplorerLayoutMode(normalizedSize.cols),\n bindings: resolveBindings(config),\n actionState: createInitialActionState(config)\n };\n}\n\nfunction createInitialActionState<R>(\n config: ExplorerConfig<R>\n): Map<string, ActionStateEntry> {\n const state = new Map<string, ActionStateEntry>();\n\n for (const [source, actions] of [[\"row\", config.actions], [\"detail\", config.detail.actions ?? []]] as const) {\n for (const action of actions) {\n if (state.has(action.id)) {\n throw new Error(`Duplicate explorer action id: ${action.id}`);\n }\n\n state.set(action.id, {\n available: true,\n label: typeof action.label === \"function\" ? action.id : action.label,\n action: action as Action<unknown>,\n source\n });\n }\n }\n\n return state;\n}\n\nexport function resolveExplorerLayoutMode(cols: number): ExplorerLayoutMode {\n if (cols < 40) {\n return \"too-narrow\";\n }\n\n if (cols < 80) {\n return \"narrow-list-only\";\n }\n\n if (cols < 100) {\n return \"narrow-vertical\";\n }\n\n if (cols < 120) {\n return \"medium\";\n }\n\n return \"wide\";\n}\n\nfunction normalizeSize(value: number): number {\n if (!Number.isFinite(value)) {\n return 0;\n }\n\n return Math.max(0, Math.floor(value));\n}\n", "import { color } from \"../components/color.js\";\nimport * as clack from \"@clack/prompts\";\nimport { resolveOutputFormat } from \"../internal/output-format.js\";\nimport { stripAnsi } from \"../internal/strip-ansi.js\";\nimport { cancel, isCancel } from \"./primitives/cancel.js\";\nimport { intro } from \"./primitives/intro.js\";\nimport { log } from \"./primitives/log.js\";\nimport { note } from \"./primitives/note.js\";\nimport { outro } from \"./primitives/outro.js\";\nimport { spinner } from \"./primitives/spinner.js\";\n\nexport { isCancel, cancel, log };\nexport { intro, outro, note, spinner };\n\nexport function introPlain(title: string): void {\n const format = resolveOutputFormat();\n if (format === \"markdown\") {\n process.stdout.write(`# ${stripAnsi(title)}\\n\\n`);\n return;\n }\n if (format === \"json\") {\n return;\n }\n process.stdout.write(`${color.gray(\"\u250C\")} ${title}\\n`);\n}\n\nexport interface SelectOptions<Value> {\n message: string;\n options: Array<{ value: Value; label: string; hint?: string }>;\n initialValue?: Value;\n}\n\nexport async function select<Value>(opts: SelectOptions<Value>): Promise<Value | symbol> {\n return clack.select(opts as Parameters<typeof clack.select<Value>>[0]);\n}\n\nexport type MultiselectOptions<Value> = Parameters<typeof clack.multiselect<Value>>[0];\n\n/**\n * Prompts the user to select one or more values from a list.\n *\n * Returns the selected values as an array, or a cancellation symbol if the\n * user cancels. Use `isCancel` to check for cancellation.\n *\n * @example\n * const result = await multiselect({\n * message: \"Pick workflows to run\",\n * options: [{ label: \"Fix Vulnerabilities\", value: \"fix-vulnerabilities\" }],\n * required: true\n * });\n * if (!isCancel(result)) {\n * // result is Value[]\n * }\n */\nexport async function multiselect<Value>(\n opts: MultiselectOptions<Value>\n): Promise<Value[] | symbol> {\n return clack.multiselect(opts);\n}\n\nexport type TextOptions = Parameters<typeof clack.text>[0];\n\nexport async function text(opts: TextOptions): Promise<string | symbol> {\n return clack.text(opts as Parameters<typeof clack.text>[0]);\n}\n\nexport interface ConfirmOptions {\n message: string;\n initialValue?: boolean;\n}\n\nexport async function confirm(opts: ConfirmOptions): Promise<boolean | symbol> {\n return clack.confirm(opts as Parameters<typeof clack.confirm>[0]);\n}\n\nexport class PromptCancelledError extends Error {\n constructor(message = \"Operation cancelled.\") {\n super(message);\n this.name = \"PromptCancelledError\";\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n}\n\nexport async function confirmOrCancel(opts: ConfirmOptions): Promise<boolean> {\n const result = await confirm(opts);\n if (isCancel(result)) {\n cancel(\"Operation cancelled.\");\n throw new PromptCancelledError();\n }\n return result === true;\n}\n\nexport interface PasswordOptions {\n message: string;\n validate?: (value: string) => string | undefined;\n}\n\nexport async function password(opts: PasswordOptions): Promise<string | symbol> {\n return clack.password(opts as Parameters<typeof clack.password>[0]);\n}\n\nexport type SpinnerOptions = {\n start: (message?: string) => void;\n stop: (message?: string, code?: number) => void;\n message: (message?: string) => void;\n};\n\nexport interface WithSpinnerOptions<T> {\n message: string | (() => string);\n fn: () => Promise<T>;\n stopMessage?: (result: T) => string;\n subtext?: (result: T) => string | undefined;\n}\n\nfunction formatElapsed(ms: number): string {\n const totalSeconds = Math.floor(ms / 1000);\n if (totalSeconds < 60) {\n return `${totalSeconds}s`;\n }\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = totalSeconds % 60;\n return `${minutes}m ${seconds}s`;\n}\n\nexport async function withSpinner<T>(options: WithSpinnerOptions<T>): Promise<T> {\n const { message, fn, stopMessage, subtext } = options;\n const readMessage = () => (typeof message === \"function\" ? message() : message);\n\n if (resolveOutputFormat() === \"json\") {\n const result = await fn();\n const sub = subtext ? subtext(result) : undefined;\n if (sub) {\n process.stdout.write(sub + \"\\n\");\n }\n return result;\n }\n\n const noSpinner = process.env.POE_NO_SPINNER === \"1\";\n const isTTY = process.stdout.isTTY;\n\n if (noSpinner || !isTTY) {\n const result = await fn();\n const msg = stopMessage ? stopMessage(result) : undefined;\n if (msg) {\n process.stdout.write(`${color.green(\"\u25C6\")} ${msg}\\n`);\n }\n const sub = subtext ? subtext(result) : undefined;\n if (sub) {\n for (const line of sub.split(\"\\n\")) {\n process.stdout.write(`${color.gray(\"\u2502\")} ${line}\\n`);\n }\n }\n return result;\n }\n\n const s = spinner();\n const start = Date.now();\n s.start(readMessage());\n\n const timer = setInterval(() => {\n s.message(`${readMessage()} [${formatElapsed(Date.now() - start)}]`);\n }, 1000);\n\n try {\n const result = await fn();\n clearInterval(timer);\n const elapsed = formatElapsed(Date.now() - start);\n const msg = stopMessage ? stopMessage(result) : undefined;\n s.stop(msg ? `${msg} [${elapsed}]` : `Done [${elapsed}]`);\n\n const sub = subtext ? subtext(result) : undefined;\n if (sub) {\n for (const line of sub.split(\"\\n\")) {\n process.stdout.write(`${color.gray(\"\u2502\")} ${line}\\n`);\n }\n }\n\n return result;\n } catch (error) {\n clearInterval(timer);\n s.stop(\"\", 1);\n throw error;\n }\n}\n", "import { color } from \"../../components/color.js\";\nexport { isCancel } from \"@clack/prompts\";\nimport { resolveOutputFormat } from \"../../internal/output-format.js\";\n\nexport function cancel(msg = \"\"): void {\n if (resolveOutputFormat() !== \"terminal\") {\n return;\n }\n\n process.stdout.write(`${color.gray(\"\u2514\")} ${color.red(msg)}\\n\\n`);\n}\n", "import { color } from \"../components/color.js\";\nimport { symbols } from \"../components/symbols.js\";\nimport { resolveOutputFormat } from \"../internal/output-format.js\";\n\nexport const SPINNER_FRAMES = Object.freeze([\"\u25D2\", \"\u25D0\", \"\u25D3\", \"\u25D1\"] as const);\n\nexport interface SpinnerFrameOptions {\n frame?: number;\n message: string;\n timer?: string;\n}\n\nexport function renderSpinnerFrame(options: SpinnerFrameOptions): string {\n const format = resolveOutputFormat();\n\n if (format === \"markdown\") {\n return `- ${options.message}${options.timer ? ` [${options.timer}]` : \"\"}...\\n`;\n }\n\n if (format === \"json\") {\n return `${JSON.stringify({\n type: \"spinner\",\n state: \"running\",\n message: options.message,\n ...(options.timer ? { timer: options.timer } : {})\n })}\\n`;\n }\n\n const frame = options.frame ?? 0;\n const index = ((frame % SPINNER_FRAMES.length) + SPINNER_FRAMES.length) % SPINNER_FRAMES.length;\n const spinnerChar = color.magenta(SPINNER_FRAMES[index]);\n const timerSuffix = options.timer ? color.dim(` [${options.timer}]`) : \"\";\n const bar = color.gray(symbols.bar);\n\n return `${spinnerChar} ${options.message}${timerSuffix}\\n${bar}`;\n}\n\nexport interface SpinnerStoppedOptions {\n message: string;\n code?: number;\n timer?: string;\n subtext?: string;\n}\n\nfunction renderMarkdownInline(value: string): string {\n return value.replaceAll(\"\\r\\n\", \" \").replaceAll(\"\\n\", \" \").replaceAll(\"\\r\", \" \");\n}\n\nexport function renderSpinnerStopped(options: SpinnerStoppedOptions): string {\n const format = resolveOutputFormat();\n\n if (format === \"markdown\") {\n return `- ${renderMarkdownInline(options.message)}${options.timer ? ` [${renderMarkdownInline(options.timer)}]` : \"\"}\\n`;\n }\n\n if (format === \"json\") {\n return `${JSON.stringify({\n type: \"spinner\",\n state: \"stopped\",\n message: options.message,\n code: options.code ?? 0,\n ...(options.timer ? { timer: options.timer } : {}),\n ...(options.subtext ? { subtext: options.subtext } : {})\n })}\\n`;\n }\n\n const code = options.code ?? 0;\n const symbol = code === 0 ? color.green(\"\u25C6\") : color.red(\"\u25A0\");\n const timerSuffix = options.timer ? color.dim(` [${options.timer}]`) : \"\";\n const bar = color.gray(symbols.bar);\n\n let output = `${symbol} ${options.message}${timerSuffix}`;\n if (options.subtext) {\n output += `\\n${bar} ${color.dim(options.subtext)}`;\n }\n return output;\n}\n", "import * as jsonc from \"jsonc-parser\";\nimport type { ConfigFormat, ConfigObject, ConfigValue } from \"../types.js\";\nimport { cloneConfigObject, hasConfigEntry, setConfigEntry } from \"./object.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 cloneConfigObject(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 = cloneConfigObject(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 setConfigEntry(result, key, merge(existing, value));\n continue;\n }\n setConfigEntry(result, key, value as ConfigValue);\n }\n return result;\n}\n\nfunction configValuesEqual(left: ConfigValue | undefined, right: ConfigValue | undefined): boolean {\n return JSON.stringify(left) === JSON.stringify(right);\n}\n\nfunction prune(\n obj: ConfigObject,\n shape: ConfigObject\n): { changed: boolean; result: ConfigObject } {\n let changed = false;\n const result = cloneConfigObject(obj);\n\n for (const [key, pattern] of Object.entries(shape)) {\n if (!hasConfigEntry(result, key)) {\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 setConfigEntry(result, key, childResult);\n }\n continue;\n }\n\n if (isConfigObject(pattern) && Object.keys(pattern).length > 0) {\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 const current = parse(content);\n return serializeUpdate(content || \"{}\", current, merge(current, patch));\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\nfunction serializeUpdate(\n content: string,\n current: ConfigObject,\n next: ConfigObject\n): string {\n let result = content || \"{}\";\n result = applyObjectUpdate(result, [], current, next);\n\n if (!result.endsWith(\"\\n\")) {\n result += \"\\n\";\n }\n\n return result;\n}\n\nfunction applyObjectUpdate(\n content: string,\n path: (string | number)[],\n current: ConfigObject,\n next: ConfigObject\n): string {\n let result = content;\n\n for (const key of Object.keys(current)) {\n if (!hasConfigEntry(next, key)) {\n result = removeAtPath(result, [...path, key]);\n }\n }\n\n for (const [key, nextValue] of Object.entries(next)) {\n const nextPath = [...path, key];\n const hasCurrent = hasConfigEntry(current, key);\n const currentValue = hasCurrent ? current[key] : undefined;\n\n if (hasCurrent && isConfigObject(currentValue) && isConfigObject(nextValue)) {\n result = applyObjectUpdate(result, nextPath, currentValue, nextValue);\n continue;\n }\n\n if (!hasCurrent || !configValuesEqual(currentValue, nextValue)) {\n result = modifyAtPath(result, nextPath, nextValue as ConfigValue);\n }\n }\n\n return result;\n}\n\nexport {\n detectIndent,\n modifyAtPath,\n mergePreservingComments,\n removeAtPath,\n serializeUpdate\n};\n\nexport const jsonFormat: ConfigFormat = {\n parse,\n serialize,\n serializeUpdate,\n merge,\n prune\n};\n", "import { parse as parseToml, stringify as stringifyToml } from \"smol-toml\";\nimport type { ConfigFormat, ConfigObject, ConfigValue } from \"../types.js\";\nimport { cloneConfigObject, hasConfigEntry, setConfigEntry } from \"./object.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 cloneConfigObject(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 = cloneConfigObject(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 setConfigEntry(result, key, merge(existing, value));\n continue;\n }\n setConfigEntry(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 = cloneConfigObject(obj);\n\n for (const [key, pattern] of Object.entries(shape)) {\n if (!hasConfigEntry(result, key)) {\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 setConfigEntry(result, key, childResult);\n }\n continue;\n }\n\n if (!isConfigObject(pattern) || Object.keys(pattern).length === 0) {\n delete result[key];\n changed = true;\n }\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\";\nimport { cloneConfigObject, hasConfigEntry, setConfigEntry } from \"./object.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 cloneConfigObject(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 = cloneConfigObject(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 setConfigEntry(result, key, merge(existing, value));\n continue;\n }\n setConfigEntry(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 = cloneConfigObject(obj);\n\n for (const [key, pattern] of Object.entries(shape)) {\n if (!hasConfigEntry(result, key)) {\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 setConfigEntry(result, key, childResult);\n }\n continue;\n }\n\n if (!isConfigObject(pattern) || Object.keys(pattern).length === 0) {\n delete result[key];\n changed = true;\n }\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 const canonicalHome = path.resolve(homeDir);\n const canonicalExpanded = path.resolve(expanded);\n const relative = path.relative(canonicalHome, canonicalExpanded);\n if (relative === \"..\" || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {\n throw new Error(`Target path resolves outside home directory: \"${rawPath}\"`);\n }\n\n if (!pathMapper) {\n return canonicalExpanded;\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 { 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 { statSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { getAgentConfig, resolveAgentSupport, resolveSkillDir } from \"./configs.js\";\n\nexport interface SkillSource {\n kind: \"resolved\";\n ref: string;\n name: string;\n sourceAgentId?: string;\n sourcePath: string;\n scope: \"project\" | \"user\";\n}\n\nexport type SkillResolutionFailure =\n | { kind: \"malformed\"; ref: string }\n | { kind: \"unknown-agent\"; ref: string; agentInput: string }\n | { kind: \"not-found\"; ref: string; searchedPaths: string[] };\n\nexport type SkillResolution = SkillSource | SkillResolutionFailure;\n\ninterface SearchTier {\n scope: \"project\" | \"user\";\n sourcePath: string;\n}\n\nfunction isMalformedSegment(segment: string): boolean {\n return (\n segment.length === 0 ||\n segment !== segment.trim() ||\n segment === \".\" ||\n segment === \"..\" ||\n segment.includes(\"\\n\") ||\n segment.includes(\"\\r\")\n );\n}\n\nfunction isDirectory(targetPath: string): boolean {\n try {\n return statSync(targetPath).isDirectory();\n } catch {\n return false;\n }\n}\n\nfunction findSkill(\n ref: string,\n name: string,\n tiers: SearchTier[],\n sourceAgentId?: string\n): SkillResolution {\n for (const tier of tiers) {\n if (isDirectory(tier.sourcePath)) {\n return {\n kind: \"resolved\",\n ref,\n name,\n ...(sourceAgentId ? { sourceAgentId } : {}),\n sourcePath: tier.sourcePath,\n scope: tier.scope\n };\n }\n }\n\n return {\n kind: \"not-found\",\n ref,\n searchedPaths: tiers.map((tier) => tier.sourcePath)\n };\n}\n\nexport function resolveSkillReference(ref: string, cwd: string, homeDir: string): SkillResolution {\n const slashIndex = ref.indexOf(\"/\");\n const hasPrefix = slashIndex !== -1;\n\n if (\n ref.length === 0 ||\n ref !== ref.trim() ||\n (hasPrefix && ref.indexOf(\"/\", slashIndex + 1) !== -1)\n ) {\n return { kind: \"malformed\", ref };\n }\n\n if (!hasPrefix) {\n if (isMalformedSegment(ref)) {\n return { kind: \"malformed\", ref };\n }\n\n const tiers: SearchTier[] = [\n {\n scope: \"project\",\n sourcePath: path.resolve(cwd, \".poe-code/skills\", ref)\n },\n {\n scope: \"user\",\n sourcePath: path.resolve(homeDir, \".poe-code/skills\", ref)\n }\n ];\n\n return findSkill(ref, ref, tiers);\n }\n\n const agentInput = ref.slice(0, slashIndex);\n const name = ref.slice(slashIndex + 1);\n if (isMalformedSegment(agentInput) || isMalformedSegment(name)) {\n return { kind: \"malformed\", ref };\n }\n\n const support = resolveAgentSupport(agentInput);\n if (support.status !== \"supported\" || !support.id) {\n return { kind: \"unknown-agent\", ref, agentInput };\n }\n\n const config = getAgentConfig(support.id);\n if (!config) {\n return { kind: \"unknown-agent\", ref, agentInput };\n }\n\n const tiers: SearchTier[] = [\n {\n scope: \"project\",\n sourcePath: path.resolve(resolveSkillDir(config, \"local\", cwd), name)\n },\n {\n scope: \"user\",\n sourcePath: path.resolve(resolveSkillDir(config, \"global\", cwd, homeDir), name)\n }\n ];\n\n return findSkill(ref, name, tiers, support.id);\n}\n", "import { execFileSync } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport path from \"node:path\";\n\nexport type GitDirRunner = (cwd: string) => string | undefined;\n\nconst defaultMarkerPrefix = \"poe-code-spawn-skills\";\n\nfunction defaultGitDirRunner(cwd: string): string | undefined {\n try {\n return execFileSync(\"git\", [\"rev-parse\", \"--git-dir\"], {\n cwd,\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"]\n }).trim();\n } catch {\n return undefined;\n }\n}\n\nlet gitDirRunner: GitDirRunner = defaultGitDirRunner;\nlet tempFileCounter = 0;\n\nexport function setGitDirRunnerForTest(runner: GitDirRunner): () => void {\n const previous = gitDirRunner;\n gitDirRunner = runner;\n return () => {\n gitDirRunner = previous;\n };\n}\n\nfunction resolveExcludePath(cwd: string): string | undefined {\n const gitDir = gitDirRunner(cwd);\n if (gitDir === undefined || gitDir.length === 0) {\n return undefined;\n }\n\n return path.join(path.isAbsolute(gitDir) ? gitDir : path.resolve(cwd, gitDir), \"info/exclude\");\n}\n\nfunction markers(runId: string, markerPrefix: string): { begin: string; end: string } {\n return {\n begin: `# ${markerPrefix}:${runId} begin`,\n end: `# ${markerPrefix}:${runId} end`\n };\n}\n\nfunction assertSingleLine(value: string, label: string): void {\n if (value.includes(\"\\n\") || value.includes(\"\\r\")) {\n throw new Error(`${label} must be a single line`);\n }\n}\n\nfunction readExcludeFile(excludePath: string): string | undefined {\n try {\n return fs.readFileSync(excludePath, \"utf8\");\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") {\n return undefined;\n }\n throw error;\n }\n}\n\nfunction isNodeError(error: unknown): error is NodeJS.ErrnoException {\n return error instanceof Error && \"code\" in error;\n}\n\nfunction assertNoSymbolicLink(targetPath: string): void {\n const parsed = path.parse(path.resolve(targetPath));\n let current = parsed.root;\n\n for (const segment of path.resolve(targetPath).slice(parsed.root.length).split(path.sep)) {\n if (segment.length === 0) {\n continue;\n }\n current = path.join(current, segment);\n try {\n if (fs.lstatSync(current).isSymbolicLink()) {\n throw new Error(`Refusing to update Git exclude path through symbolic link: ${current}`);\n }\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") {\n return;\n }\n throw error;\n }\n }\n}\n\nfunction writeExcludeFile(excludePath: string, content: string): void {\n assertNoSymbolicLink(excludePath);\n fs.mkdirSync(path.dirname(excludePath), { recursive: true });\n assertNoSymbolicLink(excludePath);\n const tempPath = `${excludePath}.poe-code-${process.pid}-${tempFileCounter++}.tmp`;\n try {\n fs.writeFileSync(tempPath, content, \"utf8\");\n fs.renameSync(tempPath, excludePath);\n } catch (error) {\n try {\n fs.rmSync(tempPath, { force: true });\n } catch (cleanupError) {\n void cleanupError;\n }\n throw error;\n }\n}\n\nfunction removeBlock(content: string, runId: string, markerPrefix: string): string {\n const { begin, end } = markers(runId, markerPrefix);\n const lines = content.split(\"\\n\");\n const result: string[] = [];\n\n for (let index = 0; index < lines.length; index += 1) {\n if (lines[index] === begin) {\n const endIndex = lines.indexOf(end, index + 1);\n if (endIndex !== -1) {\n index = endIndex;\n continue;\n }\n }\n\n result.push(lines[index]);\n }\n\n return result.join(\"\\n\");\n}\n\nfunction appendBlock(\n content: string | undefined,\n runId: string,\n entries: string[],\n markerPrefix: string\n): string {\n const { begin, end } = markers(runId, markerPrefix);\n const existing = content ?? \"\";\n const prefix = existing.length === 0 || existing.endsWith(\"\\n\") ? existing : `${existing}\\n`;\n return `${prefix}${[begin, ...entries, end, \"\"].join(\"\\n\")}`;\n}\n\nfunction nextBlockId(content: string | undefined, runId: string, markerPrefix: string): string {\n if (content === undefined || !content.includes(markers(runId, markerPrefix).begin)) {\n return runId;\n }\n\n let suffix = 1;\n while (content.includes(markers(`${runId}:${suffix}`, markerPrefix).begin)) {\n suffix += 1;\n }\n return `${runId}:${suffix}`;\n}\n\nexport function appendExcludeBlock(\n cwd: string,\n runId: string,\n entries: string[],\n opts?: { markerPrefix?: string }\n): string | undefined {\n assertSingleLine(runId, \"runId\");\n assertSingleLine(opts?.markerPrefix ?? defaultMarkerPrefix, \"markerPrefix\");\n for (const entry of entries) {\n assertSingleLine(entry, \"exclude entry\");\n }\n const excludePath = resolveExcludePath(cwd);\n if (excludePath === undefined) {\n return undefined;\n }\n\n assertNoSymbolicLink(excludePath);\n const content = readExcludeFile(excludePath);\n const markerPrefix = opts?.markerPrefix ?? defaultMarkerPrefix;\n const blockId = nextBlockId(content, runId, markerPrefix);\n writeExcludeFile(excludePath, appendBlock(content, blockId, entries, markerPrefix));\n return blockId;\n}\n\nexport function removeExcludeBlock(\n cwd: string,\n runId: string,\n opts?: { markerPrefix?: string }\n): void {\n assertSingleLine(runId, \"runId\");\n assertSingleLine(opts?.markerPrefix ?? defaultMarkerPrefix, \"markerPrefix\");\n const excludePath = resolveExcludePath(cwd);\n if (excludePath === undefined) {\n return;\n }\n\n const content = readExcludeFile(excludePath);\n if (content === undefined) {\n return;\n }\n\n writeExcludeFile(excludePath, removeBlock(content, runId, opts?.markerPrefix ?? defaultMarkerPrefix));\n}\n", "import * as fs from \"node:fs\";\nimport { createHash, randomUUID } from \"node:crypto\";\nimport path from \"node:path\";\nimport {\n getAgentConfig,\n resolveAgentSupport,\n resolveSkillDir,\n supportedAgents\n} from \"./configs.js\";\nimport { appendExcludeBlock, removeExcludeBlock } from \"./git-exclude.js\";\nimport { resolveSkillReference, type SkillResolutionFailure } from \"./resolve-skill-reference.js\";\n\nexport interface BridgeEntry {\n ref: string;\n sourcePath: string;\n targetPath: string;\n createdParents: string[];\n}\n\nexport type BridgeWarningKind =\n | \"local-collision\"\n | \"global-collision\"\n | \"self-reference\"\n | \"intra-batch-collision\";\n\nexport interface BridgeWarning {\n kind: BridgeWarningKind;\n ref: string;\n sourcePath: string;\n conflictingPath: string;\n message: string;\n}\n\nexport interface BridgeManifest {\n spawnAgentId: string;\n cwd: string;\n runId: string;\n entries: BridgeEntry[];\n warnings: BridgeWarning[];\n}\n\ninterface ActiveTarget {\n createdParents: string[];\n fingerprint: string;\n sourcePath: string;\n references: number;\n token: string;\n}\n\ninterface ManifestState {\n excludeBlockId?: string;\n cleaned?: boolean;\n}\n\nconst activeTargets = new Map<string, ActiveTarget>();\nconst manifestStates = new WeakMap<BridgeManifest, ManifestState>();\nconst ownershipFileName = \".poe-code-bridge-owner\";\n\ntype ResolvedSkill = Extract<ReturnType<typeof resolveSkillReference>, { kind: \"resolved\" }>;\n\ninterface ResolvedBridgeSource {\n ref: string;\n source: ResolvedSkill;\n targetPath: string;\n globalTargetPath: string;\n}\n\nfunction isNodeError(error: unknown): error is NodeJS.ErrnoException {\n return error instanceof Error && \"code\" in error;\n}\n\nfunction pathExists(targetPath: string): boolean {\n try {\n fs.statSync(targetPath);\n return true;\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") {\n return false;\n }\n throw error;\n }\n}\n\nfunction assertNoSymbolicLink(targetPath: string): void {\n const parsed = path.parse(path.resolve(targetPath));\n let current = parsed.root;\n\n for (const segment of path.resolve(targetPath).slice(parsed.root.length).split(path.sep)) {\n if (segment.length === 0) {\n continue;\n }\n current = path.join(current, segment);\n try {\n if (fs.lstatSync(current).isSymbolicLink()) {\n throw new Error(`Refusing to bridge skills through symbolic link: ${current}`);\n }\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") {\n return;\n }\n throw error;\n }\n }\n}\n\nfunction isDirectory(targetPath: string): boolean {\n try {\n return fs.statSync(targetPath).isDirectory();\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") {\n return false;\n }\n throw error;\n }\n}\n\nfunction formatResolutionFailureError(failures: SkillResolutionFailure[]): Error {\n const malformed = failures.filter((failure) => failure.kind === \"malformed\");\n const unknownAgent = failures.filter((failure) => failure.kind === \"unknown-agent\");\n const notFound = failures.filter((failure) => failure.kind === \"not-found\");\n const lines = [\n `Failed to bridge active skills: ${failures.length} skill reference(s) could not be resolved.`\n ];\n\n if (malformed.length > 0) {\n lines.push(\"\", \"Malformed skill references:\");\n for (const failure of malformed) {\n lines.push(`- ${failure.ref}`);\n }\n lines.push('Expected syntax: \"<name>\" or \"<agentId>/<name>\".');\n }\n\n if (unknownAgent.length > 0) {\n lines.push(\"\", \"Unknown agent references:\");\n for (const failure of unknownAgent) {\n lines.push(`- ${failure.ref} (agent token: ${failure.agentInput})`);\n }\n lines.push(`Supported agents: ${supportedAgents.join(\", \")}.`);\n }\n\n if (notFound.length > 0) {\n lines.push(\"\", \"Not found skill references.\");\n for (const failure of notFound) {\n lines.push(`- ${failure.ref}`);\n lines.push(\" searched paths:\");\n for (const searchedPath of failure.searchedPaths) {\n lines.push(` - ${searchedPath}`);\n }\n }\n }\n\n return new Error(lines.join(\"\\n\"));\n}\n\nfunction copyDirectory(sourcePath: string, targetPath: string): void {\n assertNoSymbolicLink(sourcePath);\n fs.mkdirSync(targetPath, { recursive: true });\n for (const dirent of fs.readdirSync(sourcePath, { withFileTypes: true })) {\n const childSource = path.join(sourcePath, dirent.name);\n const childTarget = path.join(targetPath, dirent.name);\n\n if (dirent.isSymbolicLink()) {\n throw new Error(`Refusing to bridge skill containing symbolic link: ${childSource}`);\n }\n\n if (dirent.isDirectory()) {\n copyDirectory(childSource, childTarget);\n continue;\n }\n\n if (dirent.isFile()) {\n fs.copyFileSync(childSource, childTarget);\n }\n }\n}\n\nfunction directoryFingerprint(targetPath: string): string {\n const hash = createHash(\"sha256\");\n\n function visit(currentPath: string, relativePath: string): void {\n const stats = fs.lstatSync(currentPath);\n if (stats.isSymbolicLink()) {\n throw new Error(`Refusing to inspect bridged skill through symbolic link: ${currentPath}`);\n }\n if (stats.isDirectory()) {\n hash.update(`d:${relativePath}\\n`);\n for (const name of fs.readdirSync(currentPath).sort()) {\n visit(path.join(currentPath, name), path.join(relativePath, name));\n }\n return;\n }\n if (stats.isFile()) {\n hash.update(`f:${relativePath}\\n`);\n hash.update(fs.readFileSync(currentPath));\n return;\n }\n throw new Error(`Refusing to bridge unsupported filesystem entry: ${currentPath}`);\n }\n\n visit(targetPath, \".\");\n return hash.digest(\"hex\");\n}\n\nfunction ownershipPath(targetPath: string): string {\n return path.join(targetPath, ownershipFileName);\n}\n\nfunction hasOwnershipToken(targetPath: string, token: string): boolean {\n try {\n return fs.readFileSync(ownershipPath(targetPath), \"utf8\") === token;\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") {\n return false;\n }\n throw error;\n }\n}\n\nfunction collectMissingParents(targetPath: string): string[] {\n const parents: string[] = [];\n let current = path.dirname(targetPath);\n\n while (!pathExists(current)) {\n parents.push(current);\n const parent = path.dirname(current);\n if (parent === current) {\n break;\n }\n current = parent;\n }\n\n return parents.reverse();\n}\n\nfunction removeDirectoryIfEmpty(targetPath: string): void {\n try {\n fs.rmdirSync(targetPath);\n } catch (error) {\n if (\n isNodeError(error) &&\n (error.code === \"ENOENT\" || error.code === \"ENOTEMPTY\" || error.code === \"EEXIST\")\n ) {\n return;\n }\n throw error;\n }\n}\n\nfunction removeTarget(targetPath: string): void {\n fs.rmSync(targetPath, { recursive: true, force: true });\n}\n\nfunction rollbackEntries(entries: BridgeEntry[]): void {\n for (const entry of [...entries].reverse()) {\n const activeTarget = activeTargets.get(entry.targetPath);\n if (activeTarget && activeTarget.references > 1) {\n activeTarget.references -= 1;\n continue;\n }\n activeTargets.delete(entry.targetPath);\n removeTarget(entry.targetPath);\n for (const parent of [...(activeTarget?.createdParents ?? entry.createdParents)].reverse()) {\n removeDirectoryIfEmpty(parent);\n }\n }\n}\n\nfunction toCwdRelative(cwd: string, targetPath: string): string {\n return path.relative(cwd, targetPath);\n}\n\nfunction warning(\n kind: BridgeWarningKind,\n ref: string,\n sourcePath: string,\n conflictingPath: string\n): BridgeWarning {\n const messages: Record<BridgeWarningKind, string> = {\n \"intra-batch-collision\": `Skipping ${ref}: an earlier bridged skill already targets ${conflictingPath}.`,\n \"local-collision\": `Skipping ${ref}: local skill already exists at ${conflictingPath}.`,\n \"global-collision\": `Skipping ${ref}: global skill already exists at ${conflictingPath}.`,\n \"self-reference\": `Skipping ${ref}: spawning agent already sees this native skill at ${conflictingPath}.`\n };\n\n return {\n kind,\n ref,\n sourcePath,\n conflictingPath,\n message: messages[kind]\n };\n}\n\nexport function bridgeActiveSkills(\n spawnAgentId: string,\n cwd: string,\n refs: string[],\n homeDir: string,\n runId: string\n): BridgeManifest {\n const spawnConfig = getAgentConfig(spawnAgentId);\n const spawnSupport = resolveAgentSupport(spawnAgentId);\n if (!spawnConfig || spawnSupport.status !== \"supported\" || !spawnSupport.id) {\n throw new Error(\n `Unsupported spawn agent \"${spawnAgentId}\". Supported agents: ${supportedAgents.join(\", \")}.`\n );\n }\n\n const targetDir = resolveSkillDir(spawnConfig, \"local\", cwd);\n const globalTargetDir = resolveSkillDir(spawnConfig, \"global\", cwd, homeDir);\n const resolutions = refs.map((ref) => resolveSkillReference(ref, cwd, homeDir));\n const failures = resolutions.filter(\n (resolution): resolution is SkillResolutionFailure => resolution.kind !== \"resolved\"\n );\n if (failures.length > 0) {\n throw formatResolutionFailureError(failures);\n }\n\n const sources: ResolvedBridgeSource[] = resolutions.map((source, index) => ({\n ref: refs[index]!,\n source: source as ResolvedSkill,\n targetPath: path.resolve(targetDir, (source as ResolvedSkill).name),\n globalTargetPath: path.resolve(globalTargetDir, (source as ResolvedSkill).name)\n }));\n\n const entries: BridgeEntry[] = [];\n const warnings: BridgeWarning[] = [];\n const claimedTargets = new Set<string>();\n\n try {\n for (const item of sources) {\n if (claimedTargets.has(item.targetPath)) {\n warnings.push(\n warning(\"intra-batch-collision\", item.ref, item.source.sourcePath, item.targetPath)\n );\n continue;\n }\n\n if (item.source.sourceAgentId === spawnSupport.id) {\n warnings.push(\n warning(\"self-reference\", item.ref, item.source.sourcePath, item.source.sourcePath)\n );\n continue;\n }\n\n const activeTarget = activeTargets.get(item.targetPath);\n if (activeTarget && pathExists(item.targetPath)) {\n if (\n activeTarget.sourcePath === item.source.sourcePath &&\n hasOwnershipToken(item.targetPath, activeTarget.token) &&\n directoryFingerprint(item.targetPath) === activeTarget.fingerprint\n ) {\n activeTarget.references += 1;\n claimedTargets.add(item.targetPath);\n entries.push({\n ref: item.ref,\n sourcePath: item.source.sourcePath,\n targetPath: item.targetPath,\n createdParents: []\n });\n continue;\n }\n activeTargets.delete(item.targetPath);\n }\n\n if (pathExists(item.targetPath)) {\n warnings.push(warning(\"local-collision\", item.ref, item.source.sourcePath, item.targetPath));\n continue;\n }\n\n if (isDirectory(item.globalTargetPath)) {\n warnings.push(\n warning(\"global-collision\", item.ref, item.source.sourcePath, item.globalTargetPath)\n );\n continue;\n }\n\n const createdParents = collectMissingParents(item.targetPath);\n assertNoSymbolicLink(path.dirname(item.targetPath));\n fs.mkdirSync(path.dirname(item.targetPath), { recursive: true });\n const token = randomUUID();\n try {\n copyDirectory(item.source.sourcePath, item.targetPath);\n fs.writeFileSync(ownershipPath(item.targetPath), token, \"utf8\");\n const fingerprint = directoryFingerprint(item.targetPath);\n claimedTargets.add(item.targetPath);\n entries.push({\n ref: item.ref,\n sourcePath: item.source.sourcePath,\n targetPath: item.targetPath,\n createdParents\n });\n activeTargets.set(item.targetPath, {\n createdParents,\n fingerprint,\n sourcePath: item.source.sourcePath,\n references: 1,\n token\n });\n } catch (error) {\n removeTarget(item.targetPath);\n for (const parent of [...createdParents].reverse()) {\n removeDirectoryIfEmpty(parent);\n }\n throw error;\n }\n }\n\n let excludeBlockId: string | undefined;\n if (entries.length > 0) {\n excludeBlockId = appendExcludeBlock(\n cwd,\n runId,\n entries.map((entry) => toCwdRelative(cwd, entry.targetPath))\n );\n }\n\n const manifest = {\n spawnAgentId,\n cwd,\n runId,\n entries,\n warnings\n };\n manifestStates.set(manifest, { excludeBlockId });\n return manifest;\n } catch (error) {\n rollbackEntries(entries);\n throw error;\n }\n}\n\nexport function cleanupBridgedSkills(manifest: BridgeManifest): void {\n const state = manifestStates.get(manifest);\n if (state?.cleaned) {\n return;\n }\n removeExcludeBlock(manifest.cwd, state?.excludeBlockId ?? manifest.runId);\n for (const entry of manifest.entries) {\n const activeTarget = activeTargets.get(entry.targetPath);\n if (!activeTarget) {\n continue;\n }\n if (activeTarget.references > 1) {\n activeTarget.references -= 1;\n continue;\n }\n activeTargets.delete(entry.targetPath);\n if (\n pathExists(entry.targetPath) &&\n hasOwnershipToken(entry.targetPath, activeTarget.token) &&\n directoryFingerprint(entry.targetPath) === activeTarget.fingerprint\n ) {\n removeTarget(entry.targetPath);\n for (const parent of [...activeTarget.createdParents].reverse()) {\n removeDirectoryIfEmpty(parent);\n }\n }\n }\n if (state) {\n state.cleaned = true;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["randomUUID", "fileURLToPath", "message", "config", "config", "assertValidBranches", "fileURLToPath", "location", "separatorIndex", "previousSeparatorIndex", "candidate", "config", "config", "os", "path", "readFile", "path", "config", "path", "text", "active", "prompt", "number", "text", "config", "revision", "spacing", "message", "graphemeSegmenter", "process", "AsyncLocalStorage", "graphemeSegmenter", "path", "path", "fileURLToPath", "statSync", "path", "path", "fs", "path", "error", "os", "path", "config", "fs", "path", "error", "params", "randomUUID", "error", "fs"]
|
|
7
7
|
}
|