poe-code 4.0.19 → 4.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/credentials.compile-check.d.ts +1 -0
- package/dist/credentials.compile-check.js +2 -0
- package/dist/credentials.compile-check.js.map +1 -0
- package/dist/credentials.d.ts +2 -0
- package/dist/credentials.js +2586 -0
- package/dist/credentials.js.map +7 -0
- package/dist/index.js +165 -59
- package/dist/index.js.map +3 -3
- package/dist/metafile.json +1 -1
- package/package.json +5 -1
- package/packages/poe-oauth/dist/index.d.ts +5 -2
- package/packages/poe-oauth/dist/index.js +3 -1
- package/packages/poe-oauth/dist/loopback-authorization.d.ts +7 -0
- package/packages/poe-oauth/dist/loopback-authorization.js +59 -26
- package/packages/poe-oauth/dist/oauth-client.d.ts +17 -0
- package/packages/poe-oauth/dist/oauth-client.js +70 -24
- package/packages/poe-oauth/dist/pkce.d.ts +2 -0
- package/packages/poe-oauth/dist/pkce.js +27 -1
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../packages/auth-store/src/encrypted-file-store.ts", "../packages/auth-store/src/error-codes.ts", "../packages/auth-store/src/keychain-store.ts", "../packages/auth-store/src/create-secret-store.ts", "../src/cli/errors.ts", "../src/cli/environment.ts", "../packages/poe-code-config/src/runtime.ts", "../packages/poe-code-config/src/schema.ts", "../packages/poe-code-config/src/compile/schema-compiler.ts", "../packages/toolcraft-schema/src/json-schema/compiler.ts", "../packages/poe-code-config/src/plan-scope.ts", "../packages/poe-code-config/src/store.ts", "../packages/config-extends/src/discover.ts", "../packages/config-extends/src/parse.ts", "../packages/frontmatter/src/parse.ts", "../packages/frontmatter/src/stringify.ts", "../packages/config-extends/src/resolve.ts", "../packages/toolcraft-design/src/internal/color-support.ts", "../packages/toolcraft-design/src/components/color.ts", "../packages/toolcraft-design/src/tokens/brand.ts", "../packages/toolcraft-design/src/internal/theme-state.ts", "../packages/toolcraft-design/src/tokens/colors.ts", "../packages/toolcraft-design/src/internal/output-format.ts", "../packages/toolcraft-design/src/internal/theme-detect.ts", "../packages/toolcraft-design/src/components/symbols.ts", "../packages/toolcraft-design/src/internal/strip-ansi.ts", "../packages/toolcraft-design/src/prompts/primitives/log.ts", "../packages/toolcraft-design/src/components/logger.ts", "../packages/toolcraft-design/src/components/help-formatter.ts", "../packages/toolcraft-design/src/components/table.ts", "../packages/toolcraft-design/src/components/detail-card.ts", "../packages/toolcraft-design/src/components/browser.ts", "../packages/toolcraft-design/src/terminal-markdown/parser/code-highlight.ts", "../packages/toolcraft-design/src/dashboard/terminal-width.ts", "../packages/toolcraft-design/src/acp/writer.ts", "../packages/toolcraft-design/src/dashboard/terminal.ts", "../packages/toolcraft-design/src/explorer/state.ts", "../packages/toolcraft-design/src/prompts/interactive/glyphs.ts", "../packages/toolcraft-design/src/prompts/interactive/core.ts", "../packages/toolcraft-design/src/prompts/interactive/wrap.ts", "../packages/toolcraft-design/src/prompts/interactive/pagination.ts", "../packages/toolcraft-design/src/static/spinner.ts", "../packages/config-extends/src/prompt-document.ts", "../packages/config-mutations/src/execution/apply-mutation.ts", "../packages/config-mutations/src/formats/json.ts", "../packages/config-mutations/src/formats/toml.ts", "../packages/config-mutations/src/formats/yaml.ts", "../packages/config-mutations/src/execution/path-utils.ts", "../packages/poe-code-config/src/inspect.ts", "../packages/poe-code-config/src/configured-services.ts", "../packages/agent-defs/src/agents/claude-code.ts", "../packages/agent-defs/src/agents/claude-desktop.ts", "../packages/agent-defs/src/agents/codex.ts", "../packages/agent-defs/src/agents/cursor.ts", "../packages/agent-defs/src/agents/gemini-cli.ts", "../packages/agent-defs/src/agents/opencode.ts", "../packages/agent-defs/src/agents/kimi.ts", "../packages/agent-defs/src/agents/goose.ts", "../packages/agent-defs/src/agents/pi.ts", "../packages/agent-defs/src/agents/poe-agent.ts", "../packages/agent-defs/src/registry.ts", "../packages/providers/src/auth/api-key.ts", "../packages/providers/src/compatibility.ts", "../packages/providers/src/registry.ts", "../packages/providers/src/types.ts", "../packages/providers/src/providers/poe.ts", "../packages/providers/src/provider-order.ts", "../packages/providers/src/providers/anthropic.ts", "../packages/providers/src/providers/cloudflare.ts", "../packages/providers/src/providers/openai.ts", "../packages/providers/src/providers/generated.ts", "../packages/poe-code-config/src/state/index.ts", "../packages/poe-code-config/src/state/jobs.ts", "../packages/poe-code-config/src/state/fs.ts", "../packages/poe-code-config/src/state/templates.ts", "../src/sdk/credentials.ts"],
|
|
4
|
+
"sourcesContent": ["import { createCipheriv, createDecipheriv, randomBytes, randomUUID, scrypt } from \"node:crypto\";\nimport { promises as fs } from \"node:fs\";\nimport { homedir, hostname, userInfo } from \"node:os\";\nimport path from \"node:path\";\nimport { hasOwnErrorCode } from \"./error-codes.js\";\nimport type { SecretStore } from \"./types.js\";\n\nconst derivedKeyCache = new Map<string, Promise<Buffer>>();\n\nconst ENCRYPTION_ALGORITHM = \"aes-256-gcm\";\nconst ENCRYPTION_VERSION = 1;\nconst ENCRYPTION_KEY_BYTES = 32;\nconst ENCRYPTION_IV_BYTES = 12;\nconst ENCRYPTION_AUTH_TAG_BYTES = 16;\nconst ENCRYPTION_FILE_MODE = 0o600;\n\ninterface EncryptedDocument {\n version: number;\n iv: string;\n authTag: string;\n ciphertext: string;\n}\n\nexport interface MachineIdentity {\n hostname: string;\n username: string;\n}\n\nexport interface EncryptedFileStoreFileSystem {\n readFile(path: string, encoding: BufferEncoding): Promise<string>;\n writeFile(\n path: string,\n data: string | NodeJS.ArrayBufferView,\n options?: { encoding?: BufferEncoding; flag?: string; mode?: number }\n ): Promise<void>;\n mkdir(path: string, options?: { recursive?: boolean }): Promise<void | string | undefined>;\n rename(oldPath: string, newPath: string): Promise<void>;\n lstat(path: string): Promise<{ isSymbolicLink(): boolean }>;\n unlink(path: string): Promise<void>;\n chmod(path: string, mode: number): Promise<void>;\n}\n\nexport interface EncryptedFileStoreInput {\n fs?: EncryptedFileStoreFileSystem;\n filePath?: string;\n salt: string;\n defaultDirectory?: string;\n defaultFileName?: string;\n getMachineIdentity?: () => MachineIdentity | Promise<MachineIdentity>;\n getHomeDirectory?: () => string;\n getRandomBytes?: (size: number) => Buffer;\n}\n\nexport class EncryptedFileStore implements SecretStore {\n private readonly fs: EncryptedFileStoreFileSystem;\n private readonly filePath: string;\n private readonly symbolicLinkCheckStartPath: string | null;\n private readonly salt: string;\n private readonly getMachineIdentity: () => MachineIdentity | Promise<MachineIdentity>;\n private readonly getRandomBytes: (size: number) => Buffer;\n private keyPromise: Promise<Buffer> | null = null;\n\n constructor(input: EncryptedFileStoreInput) {\n this.fs = input.fs ?? fs;\n this.salt = input.salt;\n if (input.filePath === undefined) {\n const homeDirectory = (input.getHomeDirectory ?? homedir)();\n const defaultDirectory = input.defaultDirectory ?? \".auth-store\";\n const defaultFileName = input.defaultFileName ?? \"credentials.enc\";\n assertSafeDefaultDirectory(defaultDirectory);\n assertSafeDefaultFileName(defaultFileName);\n this.filePath = path.join(\n homeDirectory,\n defaultDirectory,\n defaultFileName\n );\n this.symbolicLinkCheckStartPath = resolveDefaultDirectoryCheckStart(\n homeDirectory,\n defaultDirectory\n );\n } else {\n this.filePath = input.filePath;\n this.symbolicLinkCheckStartPath = null;\n }\n this.getMachineIdentity = input.getMachineIdentity ?? defaultMachineIdentity;\n this.getRandomBytes = input.getRandomBytes ?? randomBytes;\n }\n\n async get(): Promise<string | null> {\n await this.assertCredentialPathHasNoSymbolicLinks(this.filePath);\n let rawDocument: string;\n try {\n rawDocument = await this.fs.readFile(this.filePath, \"utf8\");\n } catch (error) {\n if (isNotFoundError(error)) {\n return null;\n }\n throw error;\n }\n\n const document = parseEncryptedDocument(rawDocument);\n if (!document) {\n return null;\n }\n\n const key = await this.getEncryptionKey();\n\n try {\n const iv = Buffer.from(document.iv, \"base64\");\n const authTag = Buffer.from(document.authTag, \"base64\");\n const ciphertext = Buffer.from(document.ciphertext, \"base64\");\n\n if (\n iv.byteLength !== ENCRYPTION_IV_BYTES ||\n authTag.byteLength !== ENCRYPTION_AUTH_TAG_BYTES\n ) {\n return null;\n }\n\n const decipher = createDecipheriv(ENCRYPTION_ALGORITHM, key, iv);\n decipher.setAuthTag(authTag);\n const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]);\n return plaintext.toString(\"utf8\");\n } catch {\n return null;\n }\n }\n\n async set(value: string): Promise<void> {\n await this.assertCredentialPathHasNoSymbolicLinks(this.filePath);\n const key = await this.getEncryptionKey();\n const iv = this.getRandomBytes(ENCRYPTION_IV_BYTES);\n const cipher = createCipheriv(ENCRYPTION_ALGORITHM, key, iv);\n const ciphertext = Buffer.concat([\n cipher.update(value, \"utf8\"),\n cipher.final()\n ]);\n const authTag = cipher.getAuthTag();\n\n const document: EncryptedDocument = {\n version: ENCRYPTION_VERSION,\n iv: iv.toString(\"base64\"),\n authTag: authTag.toString(\"base64\"),\n ciphertext: ciphertext.toString(\"base64\")\n };\n\n await this.fs.mkdir(path.dirname(this.filePath), { recursive: true });\n await this.assertCredentialPathHasNoSymbolicLinks(this.filePath);\n const temporaryPath = `${this.filePath}.${process.pid}.${randomUUID()}.tmp`;\n let temporaryCreated = false;\n\n try {\n await this.assertCredentialPathHasNoSymbolicLinks(temporaryPath);\n await this.fs.writeFile(temporaryPath, JSON.stringify(document), {\n encoding: \"utf8\",\n flag: \"wx\",\n mode: ENCRYPTION_FILE_MODE\n });\n temporaryCreated = true;\n await this.fs.chmod(temporaryPath, ENCRYPTION_FILE_MODE);\n await this.fs.rename(temporaryPath, this.filePath);\n } catch (error) {\n if (temporaryCreated || !isAlreadyExistsError(error)) {\n await removeIfPresent(this.fs, temporaryPath).catch(() => undefined);\n }\n throw error;\n }\n }\n\n async delete(): Promise<void> {\n await this.assertCredentialPathHasNoSymbolicLinks(this.filePath);\n try {\n await this.fs.unlink(this.filePath);\n } catch (error) {\n if (!isNotFoundError(error)) {\n throw error;\n }\n }\n }\n\n private async assertCredentialPathHasNoSymbolicLinks(targetPath: string): Promise<void> {\n const resolvedPath = path.resolve(targetPath);\n const protectedPaths = getProtectedCredentialPaths(\n resolvedPath,\n this.symbolicLinkCheckStartPath\n );\n\n for (const currentPath of protectedPaths) {\n try {\n const stats = await this.fs.lstat(currentPath);\n if (stats.isSymbolicLink()) {\n throw new Error(`Refusing to use encrypted credential path through symbolic link: ${currentPath}`);\n }\n } catch (error) {\n if (isNotFoundError(error)) {\n return;\n }\n throw error;\n }\n }\n }\n\n private getEncryptionKey(): Promise<Buffer> {\n if (!this.keyPromise) {\n const retryableKeyPromise = deriveEncryptionKey(this.getMachineIdentity, this.salt).catch((error) => {\n if (this.keyPromise === retryableKeyPromise) {\n this.keyPromise = null;\n }\n throw error;\n });\n this.keyPromise = retryableKeyPromise;\n }\n return this.keyPromise;\n }\n}\n\nfunction resolveDefaultDirectoryCheckStart(\n homeDirectory: string,\n defaultDirectory: string\n): string {\n const [firstSegment] = defaultDirectory.split(/[\\\\/]+/).filter(Boolean);\n return path.resolve(homeDirectory, firstSegment ?? \".\");\n}\n\nfunction getProtectedCredentialPaths(\n resolvedPath: string,\n symbolicLinkCheckStartPath: string | null\n): string[] {\n if (symbolicLinkCheckStartPath === null) {\n return getExplicitProtectedCredentialPaths(resolvedPath);\n }\n\n const resolvedStartPath = path.resolve(symbolicLinkCheckStartPath);\n if (!isPathInsideOrEqual(resolvedPath, resolvedStartPath)) {\n return [path.dirname(resolvedPath), resolvedPath];\n }\n\n const protectedPaths = [resolvedStartPath];\n let currentPath = resolvedStartPath;\n for (const segment of path.relative(resolvedStartPath, resolvedPath).split(path.sep).filter(Boolean)) {\n currentPath = path.join(currentPath, segment);\n protectedPaths.push(currentPath);\n }\n return protectedPaths;\n}\n\nfunction assertSafeDefaultDirectory(defaultDirectory: string): void {\n if (path.isAbsolute(defaultDirectory) || path.win32.isAbsolute(defaultDirectory)) {\n throw new Error(\"defaultDirectory must be a relative path inside the home directory\");\n }\n\n for (const segment of splitPathSegments(defaultDirectory)) {\n if (segment === \"..\") {\n throw new Error(\"defaultDirectory must be a relative path inside the home directory\");\n }\n }\n}\n\nfunction assertSafeDefaultFileName(defaultFileName: string): void {\n if (\n defaultFileName.trim().length === 0 ||\n defaultFileName === \".\" ||\n defaultFileName === \"..\" ||\n splitPathSegments(defaultFileName).length !== 1\n ) {\n throw new Error(\"defaultFileName must be a file name without path separators\");\n }\n}\n\nfunction splitPathSegments(value: string): string[] {\n return value\n .split(\"/\")\n .flatMap((segment) => segment.split(\"\\\\\"))\n .filter((segment) => segment.length > 0);\n}\n\nfunction getExplicitProtectedCredentialPaths(resolvedPath: string): string[] {\n const parsed = path.parse(resolvedPath);\n const segments = resolvedPath\n .slice(parsed.root.length)\n .split(path.sep)\n .filter((segment) => segment.length > 0);\n if (segments.length <= 1) {\n return [resolvedPath];\n }\n\n const protectedPaths: string[] = [];\n let currentPath = parsed.root;\n for (const [index, segment] of segments.entries()) {\n currentPath = path.join(currentPath, segment);\n if (index === 0) {\n continue;\n }\n protectedPaths.push(currentPath);\n }\n return protectedPaths;\n}\n\nfunction isPathInsideOrEqual(childPath: string, parentPath: string): boolean {\n const relativePath = path.relative(parentPath, childPath);\n return relativePath === \"\" || (!relativePath.startsWith(\"..\") && !path.isAbsolute(relativePath));\n}\n\nasync function removeIfPresent(fileSystem: EncryptedFileStoreFileSystem, filePath: string): Promise<void> {\n try {\n await fileSystem.unlink(filePath);\n } catch (error) {\n if (!isNotFoundError(error)) {\n throw error;\n }\n }\n}\n\nfunction defaultMachineIdentity(): MachineIdentity {\n return {\n hostname: hostname(),\n username: userInfo().username\n };\n}\n\nasync function deriveEncryptionKey(\n getMachineIdentity: () => MachineIdentity | Promise<MachineIdentity>,\n salt: string\n): Promise<Buffer> {\n const machineIdentity = await getMachineIdentity();\n const secret = `${machineIdentity.hostname}:${machineIdentity.username}`;\n const cacheKey = JSON.stringify([machineIdentity.hostname, machineIdentity.username, salt]);\n\n const cached = derivedKeyCache.get(cacheKey);\n if (cached) {\n return cached;\n }\n\n const keyPromise = new Promise<Buffer>((resolve, reject) => {\n scrypt(secret, salt, ENCRYPTION_KEY_BYTES, (error, derivedKey) => {\n if (error) {\n reject(error);\n return;\n }\n resolve(Buffer.from(derivedKey));\n });\n });\n\n derivedKeyCache.set(cacheKey, keyPromise);\n return keyPromise.catch((error) => {\n if (derivedKeyCache.get(cacheKey) === keyPromise) {\n derivedKeyCache.delete(cacheKey);\n }\n throw error;\n });\n}\n\nfunction parseEncryptedDocument(raw: string): EncryptedDocument | null {\n try {\n const parsed = JSON.parse(raw);\n if (!isRecord(parsed)) {\n return null;\n }\n const version = getOwnEntry(parsed, \"version\");\n const iv = getOwnEntry(parsed, \"iv\");\n const authTag = getOwnEntry(parsed, \"authTag\");\n const ciphertext = getOwnEntry(parsed, \"ciphertext\");\n if (version !== ENCRYPTION_VERSION) {\n return null;\n }\n if (\n typeof iv !== \"string\" ||\n typeof authTag !== \"string\" ||\n typeof ciphertext !== \"string\"\n ) {\n return null;\n }\n return {\n version,\n iv,\n authTag,\n ciphertext\n };\n } catch {\n return null;\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value && typeof value === \"object\" && !Array.isArray(value));\n}\n\nfunction getOwnEntry(record: Record<string, unknown>, key: string): unknown {\n return Object.prototype.hasOwnProperty.call(record, key) ? record[key] : undefined;\n}\n\nfunction isNotFoundError(error: unknown): error is NodeJS.ErrnoException {\n return hasOwnErrorCode(error, \"ENOENT\");\n}\n\nfunction isAlreadyExistsError(error: unknown): error is NodeJS.ErrnoException {\n return hasOwnErrorCode(error, \"EEXIST\");\n}\n", "export function hasOwnErrorCode(error: unknown, code: string): boolean {\n return (\n error instanceof Error &&\n Object.prototype.hasOwnProperty.call(error, \"code\") &&\n (error as { code?: unknown }).code === code\n );\n}\n", "import { spawn } from \"node:child_process\";\nimport type { SecretStore } from \"./types.js\";\n\nconst SECURITY_CLI = \"security\";\nconst KEYCHAIN_ITEM_NOT_FOUND_EXIT_CODE = 44;\n\nexport interface KeychainCommandResult {\n stdout: string;\n stderr: string;\n exitCode: number;\n}\n\nexport interface KeychainCommandOptions {\n stdin?: string;\n}\n\nexport type KeychainCommandRunner = (\n command: string,\n args: string[],\n options?: KeychainCommandOptions\n) => Promise<KeychainCommandResult>;\n\nexport interface KeychainStoreInput {\n runCommand?: KeychainCommandRunner;\n service: string;\n account: string;\n}\n\nexport class KeychainStore implements SecretStore {\n private readonly runCommand: KeychainCommandRunner;\n private readonly service: string;\n private readonly account: string;\n\n constructor(input: KeychainStoreInput) {\n this.runCommand = input.runCommand ?? runSecurityCommand;\n this.service = input.service.trim();\n this.account = input.account.trim();\n if (this.service.length === 0) {\n throw new Error(\"Keychain service must not be empty\");\n }\n if (this.account.length === 0) {\n throw new Error(\"Keychain account must not be empty\");\n }\n }\n\n async get(): Promise<string | null> {\n const result = await this.executeSecurityCommand(\n [\"find-generic-password\", \"-s\", this.service, \"-a\", this.account, \"-w\"],\n \"read secret from macOS Keychain\"\n );\n\n if (getCommandExitCode(result) === 0) {\n return stripTrailingLineBreak(getCommandOutput(result, \"stdout\"));\n }\n\n if (isKeychainEntryNotFound(result)) {\n return null;\n }\n\n throw createSecurityCliFailure(\"read secret from macOS Keychain\", result);\n }\n\n async set(value: string): Promise<void> {\n if (value.includes(\"\\n\") || value.includes(\"\\r\")) {\n throw new Error(\"Keychain secrets cannot contain line breaks\");\n }\n\n const result = await this.executeSecurityCommand(\n [\n \"add-generic-password\",\n \"-s\",\n this.service,\n \"-a\",\n this.account,\n \"-U\",\n \"-w\",\n value\n ],\n \"store secret in macOS Keychain\"\n );\n\n if (getCommandExitCode(result) !== 0) {\n throw createSecurityCliFailure(\"store secret in macOS Keychain\", result);\n }\n }\n\n async delete(): Promise<void> {\n const result = await this.executeSecurityCommand(\n [\"delete-generic-password\", \"-s\", this.service, \"-a\", this.account],\n \"delete secret from macOS Keychain\"\n );\n\n if (getCommandExitCode(result) === 0 || isKeychainEntryNotFound(result)) {\n return;\n }\n\n throw createSecurityCliFailure(\"delete secret from macOS Keychain\", result);\n }\n\n private async executeSecurityCommand(\n args: string[],\n operation: string,\n options?: KeychainCommandOptions\n ): Promise<KeychainCommandResult> {\n try {\n if (options === undefined) {\n return await this.runCommand(SECURITY_CLI, args);\n }\n return await this.runCommand(SECURITY_CLI, args, options);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to ${operation}: ${message}`);\n }\n }\n}\n\nfunction runSecurityCommand(\n command: string,\n args: string[],\n options?: KeychainCommandOptions\n): Promise<KeychainCommandResult> {\n return new Promise((resolve) => {\n const child = spawn(command, args, {\n stdio: [options?.stdin === undefined ? \"ignore\" : \"pipe\", \"pipe\", \"pipe\"]\n });\n\n let stdout = \"\";\n let stderr = \"\";\n let stdinErrorMessage: string | undefined;\n const appendStderr = (message: string): void => {\n stderr = stderr.length === 0\n ? message\n : `${stderr}${stderr.endsWith(\"\\n\") ? \"\" : \"\\n\"}${message}`;\n };\n const appendStdinError = (): void => {\n if (stdinErrorMessage === undefined) {\n return;\n }\n\n appendStderr(stdinErrorMessage);\n stdinErrorMessage = undefined;\n };\n\n child.stdout?.setEncoding(\"utf8\");\n child.stdout?.on(\"data\", (chunk: string | Buffer) => {\n stdout += chunk.toString();\n });\n\n child.stderr?.setEncoding(\"utf8\");\n child.stderr?.on(\"data\", (chunk: string | Buffer) => {\n stderr += chunk.toString();\n });\n\n if (options?.stdin !== undefined) {\n child.stdin?.once(\"error\", (error) => {\n stdinErrorMessage = error instanceof Error ? error.message : String(error);\n });\n child.stdin?.end(options.stdin);\n }\n\n child.on(\"error\", (error: NodeJS.ErrnoException) => {\n const message =\n error instanceof Error ? error.message : String(error ?? \"Unknown error\");\n appendStdinError();\n appendStderr(message);\n resolve({\n stdout,\n stderr,\n exitCode: 127\n });\n });\n\n child.on(\"close\", (code) => {\n appendStdinError();\n resolve({\n stdout,\n stderr,\n exitCode: code ?? 1\n });\n });\n });\n}\n\nfunction stripTrailingLineBreak(value: string): string {\n if (value.endsWith(\"\\r\\n\")) {\n return value.slice(0, -2);\n }\n\n if (value.endsWith(\"\\n\") || value.endsWith(\"\\r\")) {\n return value.slice(0, -1);\n }\n\n return value;\n}\n\nfunction isKeychainEntryNotFound(result: KeychainCommandResult): boolean {\n return getCommandExitCode(result) === KEYCHAIN_ITEM_NOT_FOUND_EXIT_CODE;\n}\n\nfunction createSecurityCliFailure(\n operation: string,\n result: KeychainCommandResult\n): Error {\n const exitCode = getCommandExitCode(result);\n const details =\n getCommandOutput(result, \"stderr\").trim()\n || getCommandOutput(result, \"stdout\").trim();\n if (details) {\n return new Error(\n `Failed to ${operation}: security exited with code ${exitCode}: ${details}`\n );\n }\n\n return new Error(`Failed to ${operation}: security exited with code ${exitCode}`);\n}\n\nfunction getCommandExitCode(result: KeychainCommandResult): number {\n const value = getOwnEntry(result, \"exitCode\");\n return typeof value === \"number\" && Number.isInteger(value) ? value : 1;\n}\n\nfunction getCommandOutput(\n result: KeychainCommandResult,\n key: \"stdout\" | \"stderr\"\n): string {\n const value = getOwnEntry(result, key);\n return typeof value === \"string\" ? value : \"\";\n}\n\nfunction getOwnEntry(record: object, key: string): unknown {\n return Object.prototype.hasOwnProperty.call(record, key)\n ? (record as Record<string, unknown>)[key]\n : undefined;\n}\n", "import type {\n CreateSecretStoreInput,\n CreateSecretStoreResult,\n StoreBackend\n} from \"./types.js\";\nimport { EncryptedFileStore } from \"./encrypted-file-store.js\";\nimport { KeychainStore } from \"./keychain-store.js\";\n\nconst DEFAULT_BACKEND_ENV_VAR = \"AUTH_BACKEND\";\nconst MACOS_PLATFORM = \"darwin\";\n\nconst storeFactories: Record<\n StoreBackend,\n (input: CreateSecretStoreInput) => CreateSecretStoreResult[\"store\"]\n> = {\n file: (input) => {\n if (!input.fileStore) {\n throw new Error(\"fileStore configuration is required for file backend\");\n }\n return new EncryptedFileStore(input.fileStore);\n },\n keychain: (input) => {\n if (!input.keychainStore) {\n throw new Error(\"keychainStore configuration is required for keychain backend\");\n }\n return new KeychainStore(input.keychainStore);\n }\n};\n\nexport function createSecretStore(\n input: CreateSecretStoreInput\n): CreateSecretStoreResult {\n const backend = resolveBackend(input);\n const platform = input.platform ?? process.platform;\n\n if (backend === \"keychain\" && platform !== MACOS_PLATFORM) {\n throw new Error(\n `Keychain backend is only supported on macOS. Current platform: ${platform}`\n );\n }\n\n const store = storeFactories[backend](input);\n\n return { backend, store };\n}\n\nfunction resolveBackend(input: CreateSecretStoreInput): StoreBackend {\n const envVar = input.backendEnvVar ?? DEFAULT_BACKEND_ENV_VAR;\n const configuredBackend =\n input.backend ?? getOwnEnvValue(input.env, envVar) ?? getOwnEnvValue(process.env, envVar);\n const backend = configuredBackend?.trim();\n\n if (backend === \"keychain\") {\n return \"keychain\";\n }\n\n if (backend === undefined || backend === \"file\") {\n return \"file\";\n }\n\n throw new Error(`Unsupported auth store backend: ${backend}`);\n}\n\nfunction getOwnEnvValue(\n env: NodeJS.ProcessEnv | undefined,\n key: string\n): string | undefined {\n return env !== undefined && Object.prototype.hasOwnProperty.call(env, key)\n ? env[key]\n : undefined;\n}\n", "import type { ErrorContext } from \"./error-logger.js\";\n\n/**\n * Base error class for all CLI errors with context support\n */\nexport class CliError extends Error {\n public readonly context?: ErrorContext;\n public readonly isUserError: boolean;\n\n constructor(\n message: string,\n context?: ErrorContext,\n options?: { isUserError?: boolean }\n ) {\n super(message);\n this.name = this.constructor.name;\n this.context = context;\n this.isUserError = options?.isUserError ?? false;\n\n // Maintains proper stack trace for where error was thrown\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n}\n\n/**\n * Error used purely for control flow: exits the CLI silently with code 0.\n */\nexport class SilentError extends CliError {\n constructor(message = \"\", options?: { isUserError?: boolean }) {\n super(message, undefined, { isUserError: options?.isUserError ?? false });\n }\n}\n\nexport class ReportedError extends CliError {\n constructor(message: string) {\n super(message);\n }\n}\n\n/**\n * API-related errors (network, HTTP status, API responses)\n */\nexport class ApiError extends CliError {\n public readonly httpStatus?: number;\n public readonly endpoint?: string;\n\n constructor(\n message: string,\n options?: {\n httpStatus?: number;\n endpoint?: string;\n context?: ErrorContext;\n }\n ) {\n super(message, {\n ...options?.context,\n httpStatus: options?.httpStatus,\n apiEndpoint: options?.endpoint\n });\n this.httpStatus = options?.httpStatus;\n this.endpoint = options?.endpoint;\n }\n}\n\n/**\n * Configuration and validation errors (user input, config files)\n */\nexport class ValidationError extends CliError {\n constructor(message: string, context?: ErrorContext) {\n super(message, context, { isUserError: true });\n }\n}\n\n/**\n * File system operation errors\n */\nexport class FileSystemError extends CliError {\n public readonly filePath?: string;\n public readonly operation?: string;\n\n constructor(\n message: string,\n options?: {\n filePath?: string;\n operation?: string;\n context?: ErrorContext;\n }\n ) {\n super(message, {\n ...options?.context,\n filePath: options?.filePath,\n operation: options?.operation\n });\n this.filePath = options?.filePath;\n this.operation = options?.operation;\n }\n}\n\n/**\n * Authentication and credential errors\n */\nexport class AuthenticationError extends CliError {\n constructor(message: string, context?: ErrorContext) {\n super(message, context, { isUserError: true });\n }\n}\n\n/**\n * Command execution errors\n */\nexport class CommandExecutionError extends CliError {\n public readonly command?: string;\n public readonly exitCode?: number;\n\n constructor(\n message: string,\n options?: {\n command?: string;\n exitCode?: number;\n context?: ErrorContext;\n }\n ) {\n super(message, {\n ...options?.context,\n command: options?.command,\n exitCode: options?.exitCode\n });\n this.command = options?.command;\n this.exitCode = options?.exitCode;\n }\n}\n\n/**\n * Service provider errors (MCP, Codex, etc.)\n */\nexport class ServiceError extends CliError {\n public readonly service?: string;\n\n constructor(\n message: string,\n options?: {\n service?: string;\n context?: ErrorContext;\n }\n ) {\n super(message, {\n ...options?.context,\n service: options?.service\n });\n this.service = options?.service;\n }\n}\n\n/**\n * Graceful cancellation triggered by the user (Ctrl+C, escape, etc.)\n */\nexport class OperationCancelledError extends SilentError {\n constructor(message = \"Operation cancelled.\") {\n super(message, { isUserError: true });\n }\n}\n\n/**\n * Detects silent control-flow exits, including cross-bundle/classloader cases\n * where instanceof checks may fail.\n */\nexport function isSilentError(error: unknown): boolean {\n if (error instanceof SilentError) {\n return true;\n }\n if (!(error instanceof Error)) {\n return false;\n }\n return (\n error.name === \"SilentError\" ||\n error.name === \"OperationCancelledError\"\n );\n}\n\nexport function isReportedError(error: unknown): boolean {\n if (error instanceof ReportedError) {\n return true;\n }\n return error instanceof Error && error.name === \"ReportedError\";\n}\n\n/**\n * Helper to determine if an error should be shown to users\n */\nexport function isUserFacingError(error: unknown): boolean {\n return error instanceof CliError && error.isUserError;\n}\n\n/**\n * Helper to extract error context from any error\n */\nexport function extractErrorContext(error: unknown): ErrorContext | undefined {\n if (error instanceof CliError) {\n return error.context;\n }\n return undefined;\n}\n\n/**\n * Helper to create a standardized error message with context\n */\nexport function formatErrorWithContext(\n error: Error,\n context?: ErrorContext\n): string {\n const parts = [error.message];\n\n if (context) {\n if (context.operation) {\n parts.push(`Operation: ${context.operation}`);\n }\n if (context.component) {\n parts.push(`Component: ${context.component}`);\n }\n }\n\n return parts.join(\" | \");\n}\n", "import path from \"node:path\";\nimport {\n resolveConfigPath,\n resolveProjectConfigPath,\n resolveServicesConfigPath\n} from \"@poe-code/poe-code-config\";\n\nexport interface CliEnvironmentInit {\n cwd: string;\n homeDir: string;\n platform?: NodeJS.Platform;\n variables?: Record<string, string | undefined>;\n}\n\nexport interface CliEnvironment {\n readonly cwd: string;\n readonly homeDir: string;\n readonly platform: NodeJS.Platform;\n readonly configPath: string;\n readonly servicesConfigPath: string;\n readonly projectConfigPath: string;\n readonly logDir: string;\n readonly poeApiBaseUrl: string;\n readonly poeBaseUrl: string;\n readonly variables: Record<string, string | undefined>;\n resolveHomePath: (...segments: string[]) => string;\n getVariable: (name: string) => string | undefined;\n}\n\nexport function createCliEnvironment(init: CliEnvironmentInit): CliEnvironment {\n const platform = init.platform ?? process.platform;\n const variables = normalizeEnvironment(init.variables ?? process.env);\n const configPath = resolveConfigPath(init.homeDir);\n const servicesConfigPath = resolveServicesConfigPath(init.homeDir);\n const projectConfigPath = resolveProjectConfigPath(init.cwd);\n const logDir = resolveLogDir(init.homeDir);\n const { poeApiBaseUrl, poeBaseUrl } = resolvePoeBaseUrls(variables);\n\n const resolveHomePath = (...segments: string[]): string => path.join(init.homeDir, ...segments);\n\n const getVariable = (name: string): string | undefined => variables[name];\n\n return {\n cwd: init.cwd,\n homeDir: init.homeDir,\n platform,\n configPath,\n servicesConfigPath,\n projectConfigPath,\n logDir,\n poeApiBaseUrl,\n poeBaseUrl,\n variables,\n resolveHomePath,\n getVariable\n };\n}\n\nfunction normalizeEnvironment(\n input: Record<string, string | undefined>\n): Record<string, string | undefined> {\n const output = Object.create(null) as Record<string, string | undefined>;\n for (const [key, value] of Object.entries(input)) {\n if (typeof value === \"string\") {\n output[key] = value;\n }\n }\n return output;\n}\n\nexport function resolveLogDir(homeDir: string): string {\n return path.join(homeDir, \".poe-code\", \"logs\");\n}\n\nexport function resolveSpawnLogDir(homeDir: string): string {\n const dir = path.join(homeDir, \".poe-code\", \"spawn-logs\");\n return dir.endsWith(path.sep) ? dir : `${dir}${path.sep}`;\n}\n\nconst DEFAULT_POE_API_BASE_URL = \"https://api.poe.com/v1\";\n\nexport function resolvePoeApiBaseUrl(\n variables: Record<string, string | undefined> = process.env\n): string {\n return resolvePoeBaseUrls(variables).poeApiBaseUrl;\n}\n\nfunction resolvePoeBaseUrls(variables: Record<string, string | undefined>): {\n poeApiBaseUrl: string;\n poeBaseUrl: string;\n} {\n const raw = Object.hasOwn(variables, \"POE_BASE_URL\") ? variables.POE_BASE_URL : undefined;\n const baseInput =\n typeof raw === \"string\" && raw.trim().length > 0 ? raw.trim() : DEFAULT_POE_API_BASE_URL;\n const parsed = parseUrl(baseInput);\n if (!parsed) {\n const trimmed = trimTrailingSlash(baseInput.trim());\n return {\n poeApiBaseUrl: ensureV1Suffix(trimmed),\n poeBaseUrl: stripV1Suffix(trimmed)\n };\n }\n\n const normalizedPath = normalizePath(parsed.pathname);\n return {\n poeApiBaseUrl: buildApiBaseUrl(parsed.origin, normalizedPath),\n poeBaseUrl: buildPoeBaseUrl(parsed.origin, normalizedPath)\n };\n}\n\nfunction parseUrl(value: string): URL | null {\n try {\n return new URL(value);\n } catch {\n return null;\n }\n}\n\nfunction normalizePath(pathname: string): string {\n if (pathname === \"/\" || pathname === \"\") {\n return \"\";\n }\n if (pathname.endsWith(\"/\")) {\n return pathname.slice(0, -1);\n }\n return pathname;\n}\n\nfunction buildApiBaseUrl(origin: string, pathname: string): string {\n if (pathname === \"\" || pathname === \"/\") {\n return `${origin}/v1`;\n }\n if (pathname.endsWith(\"/v1\")) {\n return `${origin}${pathname}`;\n }\n return `${origin}${pathname}/v1`;\n}\n\nfunction buildPoeBaseUrl(origin: string, pathname: string): string {\n if (pathname.endsWith(\"/v1\")) {\n const trimmed = pathname.slice(0, -3);\n return trimmed.length > 0 ? `${origin}${trimmed}` : origin;\n }\n return pathname.length > 0 ? `${origin}${pathname}` : origin;\n}\n\nfunction trimTrailingSlash(value: string): string {\n if (value.length > 1 && value.endsWith(\"/\")) {\n return value.slice(0, -1);\n }\n if (value === \"/\") {\n return \"\";\n }\n return value;\n}\n\nfunction ensureV1Suffix(value: string): string {\n if (value.endsWith(\"/v1\")) {\n return value;\n }\n if (value === \"\") {\n return \"/v1\";\n }\n return `${value}/v1`;\n}\n\nfunction stripV1Suffix(value: string): string {\n if (value.endsWith(\"/v1\")) {\n return value.slice(0, -3);\n }\n return value;\n}\n", "import { existsSync, realpathSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { ResolvedConfig, SchemaField, ScopeDefinition } from \"./types.js\";\n\nexport interface RuntimeMount {\n source: string;\n target: string;\n readonly?: boolean;\n}\n\nexport interface RunnerScope {\n detach: boolean;\n upload_max_file_mb: number;\n download_conflict: \"refuse\" | \"overwrite\";\n sync: \"both\" | \"upload\" | \"none\";\n workspace?: {\n exclude?: string[];\n };\n}\n\ninterface SharedRuntimeFields {\n build_args: Record<string, string>;\n mounts: RuntimeMount[];\n link?: string;\n}\n\nexport interface HostRuntime extends SharedRuntimeFields {\n type: \"host\";\n}\n\nexport interface DockerRuntime extends SharedRuntimeFields {\n type: \"docker\";\n image?: string;\n dockerfile?: string;\n build_context?: string;\n engine?: \"docker\" | \"podman\";\n network?: string;\n extra_args?: string[];\n}\n\nexport type RuntimeConfig = HostRuntime | DockerRuntime;\nexport type RuntimeRunner = RuntimeConfig[\"type\"];\n\nconst defaultWorkspaceExclude = [\n \".git\",\n \"node_modules\",\n \"dist\",\n \".turbo\",\n \".next\",\n \".poe-code/state.json\"\n];\n\nexport interface RuntimeResolveResult {\n runtime: RuntimeConfig;\n runner: RuntimeRunner;\n dockerfilePath: string | null;\n buildContext: string | null;\n}\n\ntype RuntimeResolver = (input: { cwd: string; runtime: RuntimeConfig }) => RuntimeResolveResult;\n\nexport const runtimeConfigScope = deepFreeze({\n scope: \"runtime\",\n schema: {\n type: {\n type: \"string\",\n default: \"host\",\n doc: \"Runtime backend: host or docker\"\n },\n build_args: {\n type: \"json\",\n default: {} as Record<string, string>,\n parse: parseBuildArgs,\n doc: \"Build arguments passed to the runtime image build\"\n },\n mounts: {\n type: \"json\",\n default: [] as RuntimeMount[],\n parse: parseMounts,\n doc: \"Additional runtime mounts\"\n },\n runner: {\n type: \"json\",\n default: createDefaultRunnerScope(),\n parse: parseRunner,\n doc: \"Runner process and workspace transfer settings\"\n },\n link: {\n type: \"string\",\n default: \"\",\n doc: \"Informational link for the runtime definition\"\n },\n image: {\n type: \"string\",\n default: \"\",\n doc: \"Prebuilt Docker image\"\n },\n dockerfile: {\n type: \"string\",\n default: \"\",\n doc: \"Path to the Dockerfile used for Docker builds\"\n },\n build_context: {\n type: \"string\",\n default: \"\",\n doc: \"Path to the Docker build context\"\n },\n engine: {\n type: \"string\",\n default: \"\",\n doc: \"Container engine for Docker runtime\"\n },\n network: {\n type: \"string\",\n default: \"\",\n doc: \"Docker network\"\n },\n extra_args: {\n type: \"json\",\n default: undefined as string[] | undefined,\n parse: parseOptionalStringArray,\n doc: \"Extra Docker runtime arguments\"\n }\n }\n} satisfies ScopeDefinition<Record<string, SchemaField>>);\n\nexport function parseRunner(raw: unknown): RunnerScope {\n if (raw === undefined) {\n return createDefaultRunnerScope();\n }\n const record = asRecord(raw);\n if (record === undefined) {\n throw new Error(\"runner: expected an object.\");\n }\n\n const uploadMaxFileMb =\n parseOptionalNumber(getOwnEntry(record, \"upload_max_file_mb\"), \"runner.upload_max_file_mb\") ??\n 100;\n if (uploadMaxFileMb <= 0) {\n throw new Error(\"runner.upload_max_file_mb: expected a positive finite number.\");\n }\n\n return omitUndefined({\n detach: parseOptionalBoolean(getOwnEntry(record, \"detach\"), \"runner.detach\") ?? false,\n upload_max_file_mb: uploadMaxFileMb,\n download_conflict: parseDownloadConflict(getOwnEntry(record, \"download_conflict\")),\n sync: parseRunnerSync(getOwnEntry(record, \"sync\")),\n workspace: parseRunnerWorkspace(getOwnEntry(record, \"workspace\"))\n });\n}\n\nexport function parseRuntime(raw: unknown): RuntimeConfig {\n if (raw === undefined) {\n return {\n type: \"host\",\n build_args: {},\n mounts: []\n };\n }\n const record = asRecord(raw);\n if (record === undefined) {\n throw new Error(\"runtime: expected an object.\");\n }\n const type = parseRuntimeType(getOwnEntry(record, \"type\"));\n const shared = parseSharedRuntimeFields(record);\n\n if (type === \"docker\") {\n return omitUndefined({\n ...shared,\n type,\n image: parseOptionalNonEmptyString(getOwnEntry(record, \"image\"), \"image\"),\n dockerfile: parseOptionalString(getOwnEntry(record, \"dockerfile\")),\n build_context: parseOptionalString(getOwnEntry(record, \"build_context\")),\n engine: parseEngine(getOwnEntry(record, \"engine\")),\n network: parseOptionalString(getOwnEntry(record, \"network\")),\n extra_args: parseOptionalStringArray(getOwnEntry(record, \"extra_args\"))\n });\n }\n\n return {\n ...shared,\n type\n };\n}\n\nexport function resolveRuntime({\n cwd,\n config\n}: {\n cwd: string;\n config: Pick<ResolvedConfig, \"runtime\">;\n}): RuntimeResolveResult {\n const runtime = getOwnEntry(config as unknown as Record<string, unknown>, \"runtime\");\n if (!isRuntimeConfig(runtime)) {\n throw new Error(\"runtime config is required.\");\n }\n const type = getRuntimeType(runtime);\n return runtimeResolvers[type]({ cwd, runtime });\n}\n\nconst runtimeResolvers: Record<RuntimeConfig[\"type\"], RuntimeResolver> = {\n host({ runtime }) {\n return {\n runtime,\n runner: \"host\",\n dockerfilePath: null,\n buildContext: null\n };\n },\n docker({ cwd, runtime }) {\n const dockerRuntime = runtime as DockerRuntime;\n if (getOptionalRuntimeString(dockerRuntime, \"image\") !== undefined) {\n return {\n runtime: dockerRuntime,\n runner: \"docker\",\n dockerfilePath: null,\n buildContext: null\n };\n }\n\n const { dockerfilePath, buildContext } = resolveRuntimeBuildPaths(cwd, dockerRuntime);\n if (!existsSync(dockerfilePath)) {\n throw new Error(`Docker runtime requires image or a Dockerfile at ${dockerfilePath}.`);\n }\n if (!existsSync(buildContext)) {\n throw new Error(`runtime.build_context does not exist: ${buildContext}.`);\n }\n assertRuntimePathInsideCwd(cwd, dockerfilePath, \"runtime.dockerfile\");\n assertRuntimePathInsideCwd(cwd, buildContext, \"runtime.build_context\");\n return {\n runtime: dockerRuntime,\n runner: \"docker\",\n dockerfilePath,\n buildContext\n };\n }\n};\n\nfunction resolveRuntimeBuildPaths(\n cwd: string,\n runtime: DockerRuntime\n): { dockerfilePath: string; buildContext: string } {\n return {\n dockerfilePath: path.resolve(\n cwd,\n getOptionalRuntimeString(runtime, \"dockerfile\") ?? path.join(\".poe-code\", \"Dockerfile\")\n ),\n buildContext: path.resolve(cwd, getOptionalRuntimeString(runtime, \"build_context\") ?? \".\")\n };\n}\n\nfunction assertRuntimePathInsideCwd(cwd: string, targetPath: string, fieldName: string): void {\n const canonicalCwd = realpathSync(cwd);\n const canonicalTarget = realpathSync(targetPath);\n if (!isPathInsideOrEqual(canonicalCwd, canonicalTarget)) {\n throw new Error(`${fieldName} must remain inside runtime cwd ${canonicalCwd}.`);\n }\n}\n\nfunction isPathInsideOrEqual(rootPath: string, targetPath: string): boolean {\n const relativePath = path.relative(rootPath, targetPath);\n return relativePath === \"\" || (!relativePath.startsWith(\"..\") && !path.isAbsolute(relativePath));\n}\n\nfunction parseSharedRuntimeFields(record: Record<string, unknown>): SharedRuntimeFields {\n return omitUndefined({\n build_args: parseBuildArgs(getOwnEntry(record, \"build_args\")),\n mounts: parseMounts(getOwnEntry(record, \"mounts\")),\n link: parseOptionalString(getOwnEntry(record, \"link\"))\n });\n}\n\nfunction parseRuntimeType(value: unknown): RuntimeConfig[\"type\"] {\n if (value === undefined) {\n return \"host\";\n }\n if (value === \"host\" || value === \"docker\") {\n return value;\n }\n throw new Error('type: expected \"host\" or \"docker\".');\n}\n\nfunction createDefaultRunnerScope(): RunnerScope {\n return {\n detach: false,\n upload_max_file_mb: 100,\n download_conflict: \"refuse\",\n sync: \"both\",\n workspace: {\n exclude: [...defaultWorkspaceExclude]\n }\n };\n}\n\nfunction parseRunnerWorkspace(value: unknown): RunnerScope[\"workspace\"] {\n if (value === undefined) {\n return {\n exclude: [...defaultWorkspaceExclude]\n };\n }\n const record = asRecord(value);\n if (record === undefined) {\n throw new Error(\"runner.workspace: expected an object.\");\n }\n\n return {\n exclude: parseOptionalStringArray(getOwnEntry(record, \"exclude\"), \"runner.workspace.exclude\") ??\n [...defaultWorkspaceExclude]\n };\n}\n\nfunction parseDownloadConflict(value: unknown): RunnerScope[\"download_conflict\"] {\n if (value === undefined) {\n return \"refuse\";\n }\n if (value === \"refuse\" || value === \"overwrite\") {\n return value;\n }\n throw new Error('runner.download_conflict: expected \"refuse\" or \"overwrite\".');\n}\n\nfunction parseRunnerSync(value: unknown): RunnerScope[\"sync\"] {\n if (value === undefined) {\n return \"both\";\n }\n if (value === \"both\" || value === \"upload\" || value === \"none\") {\n return value;\n }\n throw new Error('runner.sync: expected \"both\", \"upload\", or \"none\".');\n}\n\nfunction parseBuildArgs(value: unknown): Record<string, string> {\n if (value === undefined) {\n return {};\n }\n const record = asRecord(value);\n if (record === undefined) {\n throw new Error(\"build_args: expected an object.\");\n }\n\n const parsed: Record<string, string> = {};\n for (const [key, entry] of Object.entries(record)) {\n assertBuildArgName(key);\n if (typeof entry !== \"string\") {\n throw new Error(`build_args.${key}: expected a string.`);\n }\n defineDataProperty(parsed, key, entry);\n }\n return parsed;\n}\n\nfunction parseMounts(value: unknown): RuntimeMount[] {\n if (value === undefined) {\n return [];\n }\n if (!Array.isArray(value)) {\n throw new Error(\"mounts: expected an array.\");\n }\n\n return value.map((entry, index) => {\n const record = asRecord(entry);\n if (record === undefined) {\n throw new Error(`mounts[${index}]: expected an object.`);\n }\n const source = getOwnEntry(record, \"source\");\n const target = getOwnEntry(record, \"target\");\n if (typeof source !== \"string\") {\n throw new Error(`mounts[${index}].source: expected a string.`);\n }\n if (source.trim().length === 0) {\n throw new Error(`mounts[${index}].source: expected a non-empty string.`);\n }\n if (typeof target !== \"string\") {\n throw new Error(`mounts[${index}].target: expected a string.`);\n }\n if (\n target.trim().length === 0 ||\n target !== target.trim() ||\n !path.posix.isAbsolute(target)\n ) {\n throw new Error(`mounts[${index}].target: expected a non-empty absolute sandbox path.`);\n }\n\n return omitUndefined({\n source,\n target,\n readonly: parseOptionalBoolean(getOwnEntry(record, \"readonly\"), `mounts[${index}].readonly`)\n });\n });\n}\n\nfunction parseOptionalString(value: unknown): string | undefined {\n if (value === undefined) {\n return undefined;\n }\n if (typeof value !== \"string\") {\n throw new Error(\"expected a string.\");\n }\n if (value.length === 0) {\n return undefined;\n }\n return value;\n}\n\nfunction parseOptionalNonEmptyString(value: unknown, key: string): string | undefined {\n const parsed = parseOptionalString(value);\n if (parsed === undefined) {\n return undefined;\n }\n if (parsed.trim().length === 0) {\n throw new Error(`${key}: expected a non-empty string.`);\n }\n return parsed;\n}\n\nfunction assertBuildArgName(key: string): void {\n if (key.length === 0 || key !== key.trim()) {\n throw new Error(`build_args.${key}: expected an environment-style argument name.`);\n }\n for (let index = 0; index < key.length; index += 1) {\n const charCode = key.charCodeAt(index);\n const isUppercase = charCode >= 65 && charCode <= 90;\n const isLowercase = charCode >= 97 && charCode <= 122;\n const isDigit = charCode >= 48 && charCode <= 57;\n const isUnderscore = charCode === 95;\n if (!isUppercase && !isLowercase && !isDigit && !isUnderscore) {\n throw new Error(`build_args.${key}: expected an environment-style argument name.`);\n }\n }\n}\n\nfunction defineDataProperty(object: Record<string, unknown>, key: string, value: unknown): void {\n Object.defineProperty(object, key, {\n configurable: true,\n enumerable: true,\n value,\n writable: true\n });\n}\n\nfunction deepFreeze<T>(value: T): T {\n if (!value || typeof value !== \"object\" || Object.isFrozen(value)) {\n return value;\n }\n\n for (const entry of Object.values(value)) {\n deepFreeze(entry);\n }\n\n return Object.freeze(value);\n}\n\nfunction parseOptionalStringArray(value: unknown, key = \"\"): string[] | undefined {\n if (value === undefined) {\n return undefined;\n }\n if (!Array.isArray(value)) {\n throw new Error(`${key ? `${key}: ` : \"\"}expected an array.`);\n }\n return value.map((entry, index) => {\n if (typeof entry !== \"string\") {\n throw new Error(`${key}[${index}]: expected a string.`);\n }\n return entry;\n });\n}\n\nfunction parseEngine(value: unknown): \"docker\" | \"podman\" | undefined {\n const engine = parseOptionalString(value);\n if (engine === undefined || engine === \"docker\" || engine === \"podman\") {\n return engine;\n }\n throw new Error('engine: expected \"docker\" or \"podman\".');\n}\n\nfunction parseOptionalNumber(value: unknown, key = \"\"): number | undefined {\n if (value === undefined) {\n return undefined;\n }\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n throw new Error(`${key ? `${key}: ` : \"\"}expected a finite number.`);\n }\n return value;\n}\n\nfunction parseOptionalBoolean(value: unknown, key: string): boolean | undefined {\n if (value === undefined) {\n return undefined;\n }\n if (typeof value !== \"boolean\") {\n throw new Error(`${key}: expected a boolean.`);\n }\n return value;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return undefined;\n }\n return value as Record<string, unknown>;\n}\n\nfunction getOwnEntry(record: Record<string, unknown>, key: string): unknown {\n return Object.prototype.hasOwnProperty.call(record, key) ? record[key] : undefined;\n}\n\nfunction isRuntimeConfig(value: unknown): value is RuntimeConfig {\n return asRecord(value) !== undefined;\n}\n\nfunction getRuntimeType(runtime: RuntimeConfig): RuntimeConfig[\"type\"] {\n const type = getOwnEntry(runtime as unknown as Record<string, unknown>, \"type\");\n if (type === \"host\" || type === \"docker\") {\n return type;\n }\n throw new Error('runtime.type: expected \"host\" or \"docker\".');\n}\n\nfunction getOptionalRuntimeString(\n runtime: DockerRuntime,\n key: \"build_context\" | \"dockerfile\" | \"image\"\n): string | undefined {\n const value = getOwnEntry(runtime as unknown as Record<string, unknown>, key);\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction omitUndefined<T extends Record<string, unknown>>(value: T): T {\n return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined)) as T;\n}\n", "import type {\n BraintrustIntegrationConfig,\n ScopeDefinition,\n ScopeSchema\n} from \"./types.js\";\n\nexport function defineScope<const S extends ScopeSchema>(\n scope: string,\n schema: S\n): ScopeDefinition<S> {\n return {\n scope,\n schema\n };\n}\n\nexport const integrationsConfigScope = defineScope(\"integrations\", {\n braintrust: {\n type: \"json\",\n default: {\n enabled: false\n } satisfies BraintrustIntegrationConfig,\n parse: parseBraintrustIntegrationConfig,\n doc: \"Braintrust integration configuration\"\n }\n});\n\nexport { runtimeConfigScope } from \"./runtime.js\";\n\nfunction parseBraintrustIntegrationConfig(value: unknown): BraintrustIntegrationConfig {\n if (!isRecord(value)) {\n throw new Error(\"expected an object\");\n }\n\n const enabled = value.enabled === undefined ? false : value.enabled;\n if (typeof enabled !== \"boolean\") {\n throw new Error(\"enabled must be a boolean\");\n }\n\n return {\n enabled,\n ...optionalStringEntry(\"apiKey\", value.apiKey),\n ...optionalStringEntry(\"apiUrl\", value.apiUrl),\n ...optionalStringEntry(\"project\", value.project)\n };\n}\n\nfunction optionalStringEntry(key: string, value: unknown): Record<string, string> {\n if (value === undefined) {\n return {};\n }\n\n if (typeof value !== \"string\") {\n throw new Error(`${key} must be a string`);\n }\n\n return { [key]: value };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n", "import { existsSync, readFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { Node, Project, ScriptKind, SyntaxKind, ts } from \"ts-morph\";\nimport { S, toJsonSchemaDocument } from \"toolcraft-schema\";\nimport type {\n CallExpression,\n Expression,\n ObjectLiteralExpression,\n PropertyName,\n SourceFile\n} from \"ts-morph\";\nimport type { AnySchema, JsonSchemaDocument, JsonSchemaDocumentOptions } from \"toolcraft-schema\";\n\ninterface CompileConfigSchemaOptions {\n entrypoints: readonly string[];\n document?: JsonSchemaDocumentOptions;\n}\n\nexport interface CompileConfigSchemaFromSourceTextsOptions extends CompileConfigSchemaOptions {\n files: Record<string, string>;\n}\n\ntype LiteralValue = string | number | boolean | null | { [key: string]: LiteralValue };\n\ntype CollectedField =\n | {\n type: \"string\";\n default: string;\n doc: string;\n env?: string;\n }\n | {\n type: \"number\";\n default: number;\n doc: string;\n env?: string;\n }\n | {\n type: \"boolean\";\n default: boolean;\n doc: string;\n env?: string;\n };\n\ninterface ScopeFragment {\n scope: string;\n fields: Record<string, CollectedField>;\n sourceFilePath: string;\n}\n\nconst supportedFieldMetadata = new Set([\"type\", \"default\", \"doc\", \"env\"]);\nconst unsafeSchemaNames = new Set([\"__proto__\"]);\n\nconst defaultDocumentOptions: JsonSchemaDocumentOptions = {\n id: \"https://poe-code.dev/schemas/poe-code.schema.json\",\n title: \"poe-code config\",\n description: \"Schema for poe-code config files\"\n};\n\nexport function compileConfigSchemaFromEntrypoints(\n options: CompileConfigSchemaOptions\n): JsonSchemaDocument {\n const normalizedEntrypoints = options.entrypoints.map(normalizeFilePath);\n const project = createProject();\n\n const sourceFiles = collectReachableSourceFiles({\n entrypoints: normalizedEntrypoints,\n project,\n readSourceText(filePath) {\n if (!existsSync(filePath)) {\n return undefined;\n }\n\n return readFileSync(filePath, \"utf8\");\n }\n });\n\n return compileReachableSourceFiles(sourceFiles, options.document);\n}\n\nexport function compileConfigSchemaFromSourceTexts(\n options: CompileConfigSchemaFromSourceTextsOptions\n): JsonSchemaDocument {\n const files = new Map(\n Object.entries(options.files).map(([filePath, sourceText]) => [\n normalizeFilePath(filePath),\n sourceText\n ])\n );\n const project = createProject();\n\n const sourceFiles = collectReachableSourceFiles({\n entrypoints: options.entrypoints.map(normalizeFilePath),\n project,\n readSourceText(filePath) {\n return files.get(filePath);\n }\n });\n\n return compileReachableSourceFiles(sourceFiles, options.document);\n}\n\nfunction compileReachableSourceFiles(\n sourceFiles: ReturnType<typeof collectReachableSourceFiles>,\n documentOptions: JsonSchemaDocumentOptions | undefined\n): JsonSchemaDocument {\n const fragments = sourceFiles.flatMap((sourceFile) => extractScopeFragments(sourceFile));\n const mergedScopes = mergeScopeFragments(fragments);\n const rootShape = {\n version: S.Number({ default: 1 })\n } as Record<string, AnySchema>;\n\n for (const [scopeName, fields] of mergedScopes) {\n const scopeShape: Record<string, AnySchema> = {};\n\n for (const [fieldName, field] of Object.entries(fields)) {\n scopeShape[fieldName] = fieldToToolcraftSchema(field);\n }\n\n rootShape[scopeName] = S.Optional(S.Object(scopeShape));\n }\n\n return toJsonSchemaDocument(S.Object(rootShape), {\n ...defaultDocumentOptions,\n ...documentOptions\n });\n}\n\nfunction createProject(): Project {\n return new Project({\n useInMemoryFileSystem: true,\n compilerOptions: {\n allowJs: false,\n esModuleInterop: true,\n module: ts.ModuleKind.NodeNext,\n moduleResolution: ts.ModuleResolutionKind.NodeNext,\n target: ts.ScriptTarget.ES2022\n },\n skipAddingFilesFromTsConfig: true\n });\n}\n\nfunction collectReachableSourceFiles(options: {\n entrypoints: readonly string[];\n project: Project;\n readSourceText: (filePath: string) => string | undefined;\n}) {\n const sourceFiles = [];\n const visited = new Set<string>();\n const pending = [...options.entrypoints];\n\n while (pending.length > 0) {\n const filePath = pending.shift();\n if (filePath === undefined || visited.has(filePath)) {\n continue;\n }\n\n const sourceText = options.readSourceText(filePath);\n if (sourceText === undefined) {\n throw new Error(`Unable to read schema compilation entrypoint or import: ${filePath}`);\n }\n\n visited.add(filePath);\n const sourceFile = options.project.createSourceFile(filePath, sourceText, {\n overwrite: true,\n scriptKind: ScriptKind.TS\n });\n sourceFiles.push(sourceFile);\n\n for (const specifier of getStaticModuleSpecifiers(sourceFile)) {\n const resolved = resolveRelativeModuleSpecifier(filePath, specifier, options.readSourceText);\n if (resolved !== undefined && !visited.has(resolved)) {\n pending.push(resolved);\n }\n }\n }\n\n return sourceFiles;\n}\n\nfunction getStaticModuleSpecifiers(sourceFile: SourceFile): string[] {\n const specifiers: string[] = [];\n\n for (const declaration of sourceFile.getImportDeclarations()) {\n if (!declaration.isTypeOnly()) {\n specifiers.push(declaration.getModuleSpecifierValue());\n }\n }\n\n for (const declaration of sourceFile.getExportDeclarations()) {\n if (declaration.isTypeOnly()) {\n continue;\n }\n\n const specifier = declaration.getModuleSpecifierValue();\n if (specifier !== undefined) {\n specifiers.push(specifier);\n }\n }\n\n return specifiers;\n}\n\nfunction resolveRelativeModuleSpecifier(\n importerPath: string,\n specifier: string,\n readSourceText: (filePath: string) => string | undefined\n): string | undefined {\n if (!specifier.startsWith(\".\")) {\n return undefined;\n }\n\n const importerDir = path.posix.dirname(importerPath);\n const candidateBase = normalizeFilePath(path.posix.resolve(importerDir, specifier));\n const candidates = createModuleCandidates(candidateBase);\n\n return candidates.find((candidate) => readSourceText(candidate) !== undefined);\n}\n\nfunction createModuleCandidates(candidateBase: string): string[] {\n const extension = path.posix.extname(candidateBase);\n\n if (extension === \".js\" || extension === \".mjs\" || extension === \".cjs\") {\n const withoutExtension = candidateBase.slice(0, -extension.length);\n return [\n `${withoutExtension}.ts`,\n `${withoutExtension}.tsx`,\n `${withoutExtension}.mts`,\n `${withoutExtension}.cts`,\n candidateBase\n ];\n }\n\n if (extension !== \"\") {\n return [candidateBase];\n }\n\n return [\n `${candidateBase}.ts`,\n `${candidateBase}.tsx`,\n `${candidateBase}/index.ts`,\n `${candidateBase}/index.tsx`\n ];\n}\n\nfunction extractScopeFragments(sourceFile: SourceFile): ScopeFragment[] {\n const defineScopeNames = getDefineScopeImportNames(sourceFile);\n if (defineScopeNames.size === 0) {\n return [];\n }\n\n const exportedDeclarations = sourceFile.getExportedDeclarations();\n const fragments: ScopeFragment[] = [];\n\n for (const statement of sourceFile.getVariableStatements()) {\n for (const declaration of statement.getDeclarations()) {\n const name = declaration.getName();\n if (!exportedDeclarations.has(name)) {\n continue;\n }\n\n const initializer = declaration.getInitializer();\n if (!Node.isCallExpression(initializer)) {\n continue;\n }\n\n const expression = initializer.getExpression();\n if (!Node.isIdentifier(expression) || !defineScopeNames.has(expression.getText())) {\n continue;\n }\n\n fragments.push(extractScopeFragment(sourceFile.getFilePath(), initializer));\n }\n }\n\n return fragments;\n}\n\nfunction getDefineScopeImportNames(sourceFile: SourceFile): Set<string> {\n const names = new Set<string>();\n\n for (const declaration of sourceFile.getImportDeclarations()) {\n if (declaration.getModuleSpecifierValue() !== \"@poe-code/poe-code-config\") {\n continue;\n }\n\n for (const namedImport of declaration.getNamedImports()) {\n if (namedImport.getName() !== \"defineScope\") {\n continue;\n }\n\n names.add(namedImport.getAliasNode()?.getText() ?? namedImport.getName());\n }\n }\n\n return names;\n}\n\nfunction extractScopeFragment(\n sourceFilePath: string,\n callExpression: CallExpression\n): ScopeFragment {\n const [scopeArg, schemaArg] = callExpression.getArguments();\n\n if (!Node.isStringLiteral(scopeArg)) {\n throw new Error(`${sourceFilePath}: defineScope scope name must be a string literal`);\n }\n\n if (!Node.isObjectLiteralExpression(schemaArg)) {\n throw new Error(`${sourceFilePath}: defineScope schema must be an object literal`);\n }\n\n const scopeName = scopeArg.getLiteralText();\n assertSafeSchemaName(scopeName, sourceFilePath);\n\n return {\n scope: scopeName,\n fields: extractScopeFields(sourceFilePath, scopeName, schemaArg),\n sourceFilePath\n };\n}\n\nfunction extractScopeFields(\n sourceFilePath: string,\n scopeName: string,\n schemaObject: ObjectLiteralExpression\n): Record<string, CollectedField> {\n const fields: Record<string, CollectedField> = {};\n const seenFieldNames = new Set<string>();\n\n for (const property of schemaObject.getProperties()) {\n if (!Node.isPropertyAssignment(property)) {\n throw new Error(`${sourceFilePath}: scope schema fields must be property assignments`);\n }\n\n const fieldName = getPropertyName(property.getNameNode(), sourceFilePath);\n if (seenFieldNames.has(fieldName)) {\n throw new Error(`Duplicate config field \"${scopeName}.${fieldName}\" in ${sourceFilePath}`);\n }\n seenFieldNames.add(fieldName);\n\n const initializer = property.getInitializer();\n if (!Node.isObjectLiteralExpression(initializer)) {\n throw new Error(`${sourceFilePath}: config field \"${fieldName}\" must be an object literal`);\n }\n\n fields[fieldName] = extractConfigField(sourceFilePath, fieldName, initializer);\n }\n\n return fields;\n}\n\nfunction extractConfigField(\n sourceFilePath: string,\n fieldName: string,\n fieldObject: ObjectLiteralExpression\n): CollectedField {\n const metadata = extractFieldMetadataExpressions(sourceFilePath, fieldObject);\n const typeExpression = metadata.get(\"type\");\n if (typeExpression === undefined) {\n throw new Error(`${sourceFilePath}: config field \"${fieldName}\" type must be a string literal`);\n }\n\n const type = extractLiteralValue(sourceFilePath, typeExpression);\n if (type === \"json\") {\n throw new Error(\n `${sourceFilePath}: config field \"${fieldName}\" uses json, which schema compilation does not support yet`\n );\n }\n\n validateFieldMetadataKeys(sourceFilePath, fieldName, metadata);\n\n if (type !== \"string\" && type !== \"number\" && type !== \"boolean\") {\n throw new Error(\n `${sourceFilePath}: config field \"${fieldName}\" must use a primitive type supported by schema compilation`\n );\n }\n\n const defaultValue = extractOptionalLiteralValue(sourceFilePath, metadata.get(\"default\"));\n const doc = extractOptionalLiteralValue(sourceFilePath, metadata.get(\"doc\"));\n const env = extractOptionalLiteralValue(sourceFilePath, metadata.get(\"env\"));\n\n if (typeof defaultValue !== type) {\n throw new Error(`${sourceFilePath}: config field \"${fieldName}\" default must match its type`);\n }\n\n if (typeof doc !== \"string\") {\n throw new Error(`${sourceFilePath}: config field \"${fieldName}\" doc must be a string literal`);\n }\n\n if (env !== undefined && typeof env !== \"string\") {\n throw new Error(`${sourceFilePath}: config field \"${fieldName}\" env must be a string literal`);\n }\n\n if (type === \"string\" && typeof defaultValue === \"string\") {\n return {\n type,\n default: defaultValue,\n doc,\n ...(env === undefined ? {} : { env })\n };\n }\n\n if (type === \"number\" && typeof defaultValue === \"number\") {\n return {\n type,\n default: defaultValue,\n doc,\n ...(env === undefined ? {} : { env })\n };\n }\n\n if (type === \"boolean\" && typeof defaultValue === \"boolean\") {\n return {\n type,\n default: defaultValue,\n doc,\n ...(env === undefined ? {} : { env })\n };\n }\n\n throw new Error(`${sourceFilePath}: config field \"${fieldName}\" default must match its type`);\n}\n\nfunction extractFieldMetadataExpressions(\n sourceFilePath: string,\n fieldObject: ObjectLiteralExpression\n): Map<string, Expression> {\n const metadata = new Map<string, Expression>();\n\n for (const property of fieldObject.getProperties()) {\n if (!Node.isPropertyAssignment(property)) {\n throw new Error(`${sourceFilePath}: object literals in config schemas must be static`);\n }\n\n const metadataName = getPropertyName(property.getNameNode(), sourceFilePath);\n if (metadata.has(metadataName)) {\n throw new Error(`${sourceFilePath}: duplicate object literal key \"${metadataName}\"`);\n }\n\n metadata.set(metadataName, property.getInitializerOrThrow());\n }\n\n return metadata;\n}\n\nfunction extractObjectLiteral(\n sourceFilePath: string,\n objectLiteral: ObjectLiteralExpression\n): Record<string, LiteralValue> {\n const value: Record<string, LiteralValue> = {};\n const seenNames = new Set<string>();\n\n for (const property of objectLiteral.getProperties()) {\n if (!Node.isPropertyAssignment(property)) {\n throw new Error(`${sourceFilePath}: object literals in config schemas must be static`);\n }\n\n const propertyName = getPropertyName(property.getNameNode(), sourceFilePath);\n if (seenNames.has(propertyName)) {\n throw new Error(`${sourceFilePath}: duplicate object literal key \"${propertyName}\"`);\n }\n seenNames.add(propertyName);\n\n value[propertyName] = extractLiteralValue(sourceFilePath, property.getInitializerOrThrow());\n }\n\n return value;\n}\n\nfunction validateFieldMetadataKeys(\n sourceFilePath: string,\n fieldName: string,\n metadata: ReadonlyMap<string, Expression>\n): void {\n for (const metadataName of metadata.keys()) {\n if (!supportedFieldMetadata.has(metadataName)) {\n throw new Error(\n `${sourceFilePath}: Unsupported metadata \"${metadataName}\" on config field \"${fieldName}\"`\n );\n }\n }\n}\n\nfunction extractOptionalLiteralValue(\n sourceFilePath: string,\n expression: Expression | undefined\n): LiteralValue | undefined {\n if (expression === undefined) {\n return undefined;\n }\n\n return extractLiteralValue(sourceFilePath, expression);\n}\n\nfunction extractLiteralValue(sourceFilePath: string, expression: Expression): LiteralValue {\n if (Node.isStringLiteral(expression) || Node.isNoSubstitutionTemplateLiteral(expression)) {\n return expression.getLiteralText();\n }\n\n if (Node.isNumericLiteral(expression)) {\n return Number(expression.getLiteralText());\n }\n\n if (expression.getKind() === SyntaxKind.TrueKeyword) {\n return true;\n }\n\n if (expression.getKind() === SyntaxKind.FalseKeyword) {\n return false;\n }\n\n if (expression.getKind() === SyntaxKind.NullKeyword) {\n return null;\n }\n\n if (Node.isObjectLiteralExpression(expression)) {\n return extractObjectLiteral(sourceFilePath, expression);\n }\n\n if (Node.isArrayLiteralExpression(expression)) {\n throw new Error(`${sourceFilePath}: array literals are not supported in v1 config schemas`);\n }\n\n throw new Error(`${sourceFilePath}: config schemas must contain only static literal values`);\n}\n\nfunction getPropertyName(nameNode: PropertyName, sourceFilePath: string): string {\n if (Node.isIdentifier(nameNode) || Node.isStringLiteral(nameNode)) {\n const propertyName = Node.isIdentifier(nameNode)\n ? nameNode.getText()\n : nameNode.getLiteralText();\n assertSafeSchemaName(propertyName, sourceFilePath);\n return propertyName;\n }\n\n throw new Error(`${sourceFilePath}: config schema property names must be static`);\n}\n\nfunction assertSafeSchemaName(name: string, sourceFilePath: string): void {\n if (unsafeSchemaNames.has(name)) {\n throw new Error(`${sourceFilePath}: Unsafe config schema name \"${name}\"`);\n }\n}\n\nfunction mergeScopeFragments(\n fragments: readonly ScopeFragment[]\n): Map<string, Record<string, CollectedField>> {\n const merged = new Map<string, Record<string, CollectedField>>();\n const fieldOrigins = new Map<string, string>();\n\n for (const fragment of fragments) {\n const scope = merged.get(fragment.scope) ?? {};\n\n for (const [fieldName, field] of Object.entries(fragment.fields)) {\n const fieldKey = `${fragment.scope}.${fieldName}`;\n const previousOrigin = fieldOrigins.get(fieldKey);\n if (previousOrigin !== undefined) {\n throw new Error(\n `Duplicate config field \"${fieldKey}\" in ${fragment.sourceFilePath}; first defined in ${previousOrigin}`\n );\n }\n\n scope[fieldName] = field;\n fieldOrigins.set(fieldKey, fragment.sourceFilePath);\n }\n\n merged.set(fragment.scope, scope);\n }\n\n return merged;\n}\n\nfunction fieldToToolcraftSchema(field: CollectedField): AnySchema {\n switch (field.type) {\n case \"string\":\n return S.String({ default: field.default, description: field.doc });\n case \"number\":\n return S.Number({ default: field.default, description: field.doc });\n case \"boolean\":\n return S.Boolean({ default: field.default, description: field.doc });\n }\n}\n\nfunction normalizeFilePath(filePath: string): string {\n return path.posix.normalize(filePath.replaceAll(path.win32.sep, path.posix.sep));\n}\n", "import type {\n CompileJsonSchemaOptions,\n Dialect,\n JsonSchema,\n SchemaNode,\n SchemaObject\n} from \"./types.js\";\nimport {\n dialectFor,\n escapePointer,\n fragmentOf,\n isObject,\n isSchema,\n resolveUri,\n withoutFragment\n} from \"./utils.js\";\n\nconst schemaMapKeywords = new Set([\n \"$defs\",\n \"definitions\",\n \"properties\",\n \"patternProperties\",\n \"dependentSchemas\",\n \"dependencies\"\n]);\nconst schemaArrayKeywords = new Set([\"allOf\", \"anyOf\", \"oneOf\", \"prefixItems\"]);\nconst schemaKeywords = new Set([\n \"additionalItems\",\n \"additionalProperties\",\n \"contains\",\n \"else\",\n \"if\",\n \"items\",\n \"not\",\n \"propertyNames\",\n \"then\",\n \"unevaluatedItems\",\n \"unevaluatedProperties\"\n]);\nconst draftTypes = [\"null\", \"boolean\", \"object\", \"array\", \"number\", \"integer\", \"string\"];\nconst draftTypeSet = new Set(draftTypes);\nconst metaSchemaKeywordProperties = {\n type: {\n anyOf: [\n { enum: draftTypes },\n { type: \"array\", items: { enum: draftTypes }, minItems: 1, uniqueItems: true }\n ]\n },\n minLength: { type: \"integer\", minimum: 0 },\n maxLength: { type: \"integer\", minimum: 0 },\n minItems: { type: \"integer\", minimum: 0 },\n maxItems: { type: \"integer\", minimum: 0 },\n minProperties: { type: \"integer\", minimum: 0 },\n maxProperties: { type: \"integer\", minimum: 0 }\n};\nconst builtInRegistry: Record<string, unknown> = {\n \"https://json-schema.org/draft/2020-12/schema\": {\n $id: \"https://json-schema.org/draft/2020-12/schema\",\n type: [\"object\", \"boolean\"],\n properties: {\n ...metaSchemaKeywordProperties,\n $defs: { type: \"object\", additionalProperties: { $ref: \"#\" } }\n }\n },\n \"http://json-schema.org/draft-07/schema\": {\n $id: \"http://json-schema.org/draft-07/schema#\",\n type: [\"object\", \"boolean\"],\n properties: {\n ...metaSchemaKeywordProperties,\n definitions: { type: \"object\", additionalProperties: { $ref: \"#\" } }\n }\n }\n};\n\nexport interface CompiledGraph {\n root: SchemaNode;\n locations: Map<string, SchemaNode>;\n resources: Map<string, SchemaNode>;\n anchors: Map<string, SchemaNode>;\n dynamicAnchors: Map<string, SchemaNode>;\n resolve(node: SchemaNode, reference: string): SchemaNode;\n dynamicAnchor(scope: SchemaNode, name: string): SchemaNode | undefined;\n}\n\nfunction mapKey(dialect: Dialect, uri: string): string {\n return `${dialect}\\0${uri}`;\n}\n\nfunction assertSchemaArray(value: unknown, keyword: string): asserts value is JsonSchema[] {\n if (!Array.isArray(value) || value.length === 0 || !value.every(isSchema)) {\n throw new Error(`${keyword} must be a non-empty array of schemas.`);\n }\n}\n\nfunction assertStringArray(value: unknown, keyword: string): asserts value is string[] {\n if (!Array.isArray(value) || !value.every((item) => typeof item === \"string\")) {\n throw new Error(`${keyword} must be an array of strings.`);\n }\n if (new Set(value).size !== value.length) {\n throw new Error(`${keyword} must contain unique strings.`);\n }\n}\n\nfunction assertSchemaMap(value: unknown, keyword: string): asserts value is SchemaObject {\n if (!isObject(value) || !Object.values(value).every(isSchema)) {\n throw new Error(`${keyword} must be an object containing schemas.`);\n }\n}\n\nfunction assertNonNegativeInteger(value: unknown, keyword: string): void {\n if (!Number.isInteger(value) || (value as number) < 0) {\n throw new Error(`${keyword} must be a non-negative integer.`);\n }\n}\n\nfunction validateSchemaObject(schema: SchemaObject, dialect: Dialect): void {\n if (schema.type !== undefined) {\n const types = Array.isArray(schema.type) ? schema.type : [schema.type];\n if (\n types.length === 0 ||\n !types.every((type) => typeof type === \"string\" && draftTypeSet.has(type)) ||\n new Set(types).size !== types.length\n ) {\n throw new Error(\"type must be a JSON Schema type or a unique array of JSON Schema types.\");\n }\n }\n for (const keyword of [\"minimum\", \"maximum\", \"exclusiveMinimum\", \"exclusiveMaximum\"] as const) {\n if (schema[keyword] !== undefined && typeof schema[keyword] !== \"number\") {\n throw new Error(`${keyword} must be a number.`);\n }\n }\n if (\n schema.multipleOf !== undefined &&\n (typeof schema.multipleOf !== \"number\" || schema.multipleOf <= 0)\n ) {\n throw new Error(\"multipleOf must be a number greater than zero.\");\n }\n for (const keyword of [\n \"minLength\",\n \"maxLength\",\n \"minItems\",\n \"maxItems\",\n \"minContains\",\n \"maxContains\",\n \"minProperties\",\n \"maxProperties\"\n ] as const) {\n if (schema[keyword] !== undefined) {\n assertNonNegativeInteger(schema[keyword], keyword);\n }\n }\n if (schema.pattern !== undefined && typeof schema.pattern !== \"string\") {\n throw new Error(\"pattern must be a string.\");\n }\n for (const keyword of [\"uniqueItems\", \"$recursiveAnchor\"] as const) {\n if (schema[keyword] !== undefined && typeof schema[keyword] !== \"boolean\") {\n throw new Error(`${keyword} must be a boolean.`);\n }\n }\n if (schema.required !== undefined) {\n assertStringArray(schema.required, \"required\");\n }\n if (schema.dependentRequired !== undefined) {\n if (!isObject(schema.dependentRequired)) {\n throw new Error(\"dependentRequired must be an object containing string arrays.\");\n }\n for (const dependencies of Object.values(schema.dependentRequired)) {\n assertStringArray(dependencies, \"dependentRequired\");\n }\n }\n for (const keyword of schemaMapKeywords) {\n const value = schema[keyword];\n if (value === undefined || keyword === \"dependencies\") continue;\n assertSchemaMap(value, keyword);\n }\n if (schema.dependencies !== undefined) {\n if (!isObject(schema.dependencies)) {\n throw new Error(\"dependencies must be an object containing schemas or string arrays.\");\n }\n for (const dependency of Object.values(schema.dependencies)) {\n if (!isSchema(dependency)) assertStringArray(dependency, \"dependencies\");\n }\n }\n for (const keyword of [\"allOf\", \"anyOf\", \"oneOf\"] as const) {\n if (schema[keyword] !== undefined) assertSchemaArray(schema[keyword], keyword);\n }\n if (schema.prefixItems !== undefined) {\n if (!Array.isArray(schema.prefixItems) || !schema.prefixItems.every(isSchema)) {\n throw new Error(\"prefixItems must be an array of schemas.\");\n }\n }\n for (const keyword of schemaKeywords) {\n const value = schema[keyword];\n if (value === undefined) continue;\n if (keyword === \"items\" && dialect === \"draft7\" && Array.isArray(value)) {\n if (!value.every(isSchema)) throw new Error(\"items must contain only schemas.\");\n } else if (!isSchema(value)) {\n throw new Error(`${keyword} must be a schema.`);\n }\n }\n if (schema.enum !== undefined && !Array.isArray(schema.enum)) {\n throw new Error(\"enum must be an array.\");\n }\n}\n\nexport function compileGraph(\n schema: unknown,\n options: CompileJsonSchemaOptions = {}\n): CompiledGraph {\n if (!isSchema(schema)) {\n throw new Error(\"JSON Schema must be a boolean or object.\");\n }\n\n const locations = new Map<string, SchemaNode>();\n const resources = new Map<string, SchemaNode>();\n const anchors = new Map<string, SchemaNode>();\n const dynamicAnchors = new Map<string, SchemaNode>();\n const nodesBySchema = new WeakMap<SchemaObject, SchemaNode[]>();\n const pendingReferences: Array<{ node: SchemaNode; reference: string }> = [];\n const registry = { ...builtInRegistry, ...options.registry };\n const rootBase = \"https://toolcraft.invalid/root\";\n\n function validationVocabularyFor(schemaObject: SchemaObject): boolean {\n const metaSchema = schemaObject.$schema;\n if (typeof metaSchema !== \"string\") {\n return true;\n }\n const registered = registry[metaSchema];\n if (!isObject(registered) || !isObject(registered.$vocabulary)) {\n return true;\n }\n return Object.prototype.hasOwnProperty.call(\n registered.$vocabulary,\n \"https://json-schema.org/draft/2020-12/vocab/validation\"\n );\n }\n\n function recordNode(schemaObject: SchemaObject | undefined, node: SchemaNode): void {\n if (schemaObject === undefined) {\n return;\n }\n const nodes = nodesBySchema.get(schemaObject) ?? [];\n nodes.push(node);\n nodesBySchema.set(schemaObject, nodes);\n }\n\n function setLocation(dialect: Dialect, uri: string, node: SchemaNode): void {\n locations.set(mapKey(dialect, uri), node);\n }\n\n function scan(\n currentSchema: JsonSchema,\n inheritedDialect: Dialect,\n inheritedBase: string,\n resourceRoot: SchemaNode | undefined,\n pointer: string,\n validationVocabulary: boolean,\n documentId: string\n ): SchemaNode {\n const schemaObject = isObject(currentSchema) ? currentSchema : undefined;\n const dialect =\n schemaObject === undefined ? inheritedDialect : dialectFor(schemaObject, inheritedDialect);\n if (schemaObject !== undefined) {\n validateSchemaObject(schemaObject, dialect);\n }\n const declaredId =\n dialect === \"draft7\" ? (schemaObject?.$id ?? schemaObject?.id) : schemaObject?.$id;\n const effectiveId =\n dialect === \"draft7\" && typeof schemaObject?.$ref === \"string\" ? undefined : declaredId;\n const baseUri =\n typeof effectiveId === \"string\" ? resolveUri(effectiveId, inheritedBase) : inheritedBase;\n const node = {\n schema: currentSchema,\n documentId,\n dialect,\n baseUri,\n resourceUri: resourceRoot?.resourceUri ?? withoutFragment(baseUri),\n resourceRoot: undefined as unknown as SchemaNode,\n pointer,\n validationVocabulary,\n children: new Map<string, SchemaNode>()\n };\n recordNode(schemaObject, node);\n\n if (resourceRoot !== undefined) {\n setLocation(\n resourceRoot.dialect,\n resolveUri(`#${encodeURI(pointer)}`, resourceRoot.resourceUri),\n node\n );\n }\n\n const startsResource =\n resourceRoot === undefined || withoutFragment(baseUri) !== resourceRoot.resourceUri;\n node.resourceRoot = startsResource ? node : resourceRoot;\n node.resourceUri = startsResource ? withoutFragment(baseUri) : resourceRoot.resourceUri;\n const resourcePointer = startsResource ? \"\" : pointer;\n node.pointer = resourcePointer;\n\n if (startsResource) {\n resources.set(mapKey(node.dialect, node.resourceUri), node);\n setLocation(node.dialect, node.resourceUri, node);\n }\n setLocation(node.dialect, resolveUri(`#${encodeURI(resourcePointer)}`, node.resourceUri), node);\n\n if (schemaObject === undefined) {\n return node;\n }\n\n if (typeof schemaObject.$anchor === \"string\") {\n anchors.set(mapKey(node.dialect, `${node.resourceUri}#${schemaObject.$anchor}`), node);\n }\n if (typeof schemaObject.$dynamicAnchor === \"string\") {\n const anchorUri = `${node.resourceUri}#${schemaObject.$dynamicAnchor}`;\n anchors.set(mapKey(node.dialect, anchorUri), node);\n dynamicAnchors.set(mapKey(node.dialect, anchorUri), node);\n }\n if (dialect === \"draft7\" && typeof effectiveId === \"string\" && fragmentOf(baseUri) !== \"\") {\n anchors.set(mapKey(dialect, baseUri), node);\n }\n for (const keyword of [\"$ref\", \"$dynamicRef\", \"$recursiveRef\"] as const) {\n const reference = schemaObject[keyword];\n if (reference !== undefined) {\n if (typeof reference !== \"string\") {\n throw new Error(`${keyword} must be a string.`);\n }\n pendingReferences.push({ node, reference });\n }\n }\n if (typeof schemaObject.pattern === \"string\") {\n new RegExp(schemaObject.pattern, \"u\");\n }\n if (isObject(schemaObject.patternProperties)) {\n for (const pattern of Object.keys(schemaObject.patternProperties)) {\n new RegExp(pattern, \"u\");\n }\n }\n\n const nextValidationVocabulary =\n resourceRoot === undefined ? validationVocabularyFor(schemaObject) : validationVocabulary;\n for (const [keyword, value] of Object.entries(schemaObject)) {\n if (schemaMapKeywords.has(keyword) && isObject(value)) {\n for (const [key, childSchema] of Object.entries(value)) {\n if (isSchema(childSchema)) {\n node.children.set(\n `${keyword}/${key}`,\n scan(\n childSchema,\n dialect,\n baseUri,\n node.resourceRoot,\n `${resourcePointer}/${escapePointer(keyword)}/${escapePointer(key)}`,\n nextValidationVocabulary,\n documentId\n )\n );\n }\n }\n } else if (schemaArrayKeywords.has(keyword) && Array.isArray(value)) {\n value.forEach((childSchema, index) => {\n if (isSchema(childSchema)) {\n node.children.set(\n `${keyword}/${index}`,\n scan(\n childSchema,\n dialect,\n baseUri,\n node.resourceRoot,\n `${resourcePointer}/${escapePointer(keyword)}/${index}`,\n nextValidationVocabulary,\n documentId\n )\n );\n }\n });\n } else if (schemaKeywords.has(keyword)) {\n if (keyword === \"items\" && Array.isArray(value)) {\n value.forEach((childSchema, index) => {\n if (isSchema(childSchema)) {\n node.children.set(\n `items/${index}`,\n scan(\n childSchema,\n dialect,\n baseUri,\n node.resourceRoot,\n `${resourcePointer}/items/${index}`,\n nextValidationVocabulary,\n documentId\n )\n );\n }\n });\n } else if (isSchema(value)) {\n node.children.set(\n keyword,\n scan(\n value,\n dialect,\n baseUri,\n node.resourceRoot,\n `${resourcePointer}/${escapePointer(keyword)}`,\n nextValidationVocabulary,\n documentId\n )\n );\n }\n }\n }\n return node;\n }\n\n const root = scan(schema, \"draft2020-12\", rootBase, undefined, \"\", true, \"root\");\n resources.set(mapKey(root.dialect, rootBase), root);\n setLocation(root.dialect, rootBase, root);\n setLocation(root.dialect, `${rootBase}#`, root);\n\n for (const [uri, registeredSchema] of Object.entries(registry)) {\n if (!isSchema(registeredSchema)) {\n throw new Error(`Registered JSON Schema ${uri} must be a boolean or object.`);\n }\n for (const inheritedDialect of [\"draft2020-12\", \"draft7\"] as const) {\n const remote = scan(\n registeredSchema,\n inheritedDialect,\n uri,\n undefined,\n \"\",\n true,\n `${inheritedDialect}:${uri}`\n );\n resources.set(mapKey(remote.dialect, withoutFragment(uri)), remote);\n setLocation(remote.dialect, withoutFragment(uri), remote);\n setLocation(remote.dialect, `${withoutFragment(uri)}#`, remote);\n }\n }\n\n function findByDialect<T>(map: Map<string, T>, dialect: Dialect, uri: string): T | undefined {\n const alternate = dialect === \"draft7\" ? \"draft2020-12\" : \"draft7\";\n return map.get(mapKey(dialect, uri)) ?? map.get(mapKey(alternate, uri));\n }\n\n function resolve(node: SchemaNode, reference: string): SchemaNode {\n const absolute = resolveUri(reference, node.baseUri);\n const direct =\n findByDialect(locations, node.dialect, absolute) ??\n findByDialect(resources, node.dialect, absolute) ??\n findByDialect(anchors, node.dialect, absolute);\n if (direct !== undefined) {\n return direct;\n }\n const resource = findByDialect(resources, node.dialect, withoutFragment(absolute));\n const fragment = fragmentOf(absolute);\n if (resource !== undefined && fragment === \"\") {\n return resource;\n }\n if (fragment.startsWith(\"/\")) {\n const pointerTarget = findByDialect(\n locations,\n node.dialect,\n `${withoutFragment(absolute)}#${fragment}`\n );\n if (pointerTarget !== undefined) {\n return pointerTarget;\n }\n if (resource !== undefined && isObject(resource.schema)) {\n let target: unknown = resource.schema;\n for (const segment of fragment.slice(1).split(\"/\")) {\n if (!isObject(target) && !Array.isArray(target)) {\n target = undefined;\n break;\n }\n const key = decodeURIComponent(segment).replaceAll(\"~1\", \"/\").replaceAll(\"~0\", \"~\");\n target = Array.isArray(target) ? target[Number(key)] : target[key];\n }\n if (isObject(target)) {\n const targetNode = nodesBySchema\n .get(target)\n ?.find((candidate) => candidate.dialect === node.dialect);\n if (targetNode !== undefined) {\n return targetNode;\n }\n }\n }\n }\n throw new Error(`Unresolvable $ref: ${reference}`);\n }\n\n const reachableDocuments = new Set([root.documentId]);\n let discoveredDocument = true;\n while (discoveredDocument) {\n discoveredDocument = false;\n for (const pending of pendingReferences) {\n if (!reachableDocuments.has(pending.node.documentId)) {\n continue;\n }\n const target = resolve(pending.node, pending.reference);\n if (!reachableDocuments.has(target.documentId)) {\n reachableDocuments.add(target.documentId);\n discoveredDocument = true;\n }\n }\n }\n\n return {\n root,\n locations,\n resources,\n anchors,\n dynamicAnchors,\n resolve,\n dynamicAnchor(scope, name) {\n return dynamicAnchors.get(mapKey(scope.dialect, `${scope.resourceUri}#${name}`));\n }\n };\n}\n", "import { defineScope } from \"./schema.js\";\n\nexport const planConfigScope = defineScope(\"plan\", {\n plan_directory: {\n type: \"string\",\n default: \"docs/plans\",\n env: \"POE_PLAN_DIRECTORY\",\n doc: \"Directory where planning documents are stored\"\n }\n});\n", "import { randomUUID } from \"node:crypto\";\nimport path from \"node:path\";\nimport { resolve, type FileSystem as ResolveFileSystem } from \"@poe-code/config-extends\";\nimport { createTimestamp, isNotFound, type FileSystem } from \"@poe-code/config-mutations\";\nimport { hasOwnErrorCode } from \"./errors.js\";\nimport type { ConfigDocument } from \"./types.js\";\n\nexport async function readDocument(fs: FileSystem, filePath: string): Promise<ConfigDocument> {\n await assertConfigPathSafe(fs, filePath);\n const document = await readStoredDocument(fs, filePath);\n return document.data;\n}\n\nexport async function readDocumentReadonly(fs: FileSystem, filePath: string): Promise<ConfigDocument> {\n await assertConfigPathSafe(fs, filePath);\n const document = await readStoredDocument(fs, filePath, false);\n return document.data;\n}\n\nexport async function writeScope(\n fs: FileSystem,\n filePath: string,\n scope: string,\n values: Record<string, unknown>\n): Promise<void> {\n const document = await readDocument(fs, filePath);\n const normalizedValues = normalizeScopeValues(values);\n\n if (Object.keys(normalizedValues).length === 0) {\n delete document[scope];\n } else {\n defineDataProperty(document, scope, normalizedValues);\n }\n\n await writeDocument(fs, filePath, document);\n}\n\nexport async function readMergedDocument(\n fs: FileSystem,\n globalPath: string,\n projectPath?: string\n): Promise<ConfigDocument> {\n return readMergedStoredDocument(fs, globalPath, projectPath, true);\n}\n\nexport async function readMergedDocumentReadonly(\n fs: FileSystem,\n globalPath: string,\n projectPath?: string\n): Promise<ConfigDocument> {\n return readMergedStoredDocument(fs, globalPath, projectPath, false);\n}\n\nasync function readMergedStoredDocument(\n fs: FileSystem,\n globalPath: string,\n projectPath: string | undefined,\n recoverInvalid: boolean\n): Promise<ConfigDocument> {\n await assertConfigPathSafe(fs, globalPath);\n const globalDocument = await readStoredDocument(fs, globalPath, recoverInvalid);\n if (!projectPath || projectPath === globalPath) {\n return globalDocument.data;\n }\n\n await assertConfigPathSafe(fs, projectPath);\n const projectDocument = await readStoredDocument(fs, projectPath, recoverInvalid);\n const resolved = await resolve(\n [\n {\n source: \"project\",\n filePath: projectPath,\n content: projectDocument.content\n },\n {\n source: \"base\",\n path: path.dirname(globalPath)\n }\n ],\n {\n fs: createResolvedConfigFs(fs, globalPath, globalDocument.content),\n autoExtend: true\n }\n );\n\n return normalizeDocument(resolved.data);\n}\n\nasync function readStoredDocument(\n fs: FileSystem,\n filePath: string,\n recoverInvalid = true\n): Promise<{ content: string; data: ConfigDocument }> {\n try {\n const raw = await fs.readFile(filePath, \"utf8\");\n return await parseStoredDocument(fs, filePath, raw, recoverInvalid);\n } catch (error) {\n if (isNotFound(error)) {\n return {\n content: EMPTY_DOCUMENT,\n data: {}\n };\n }\n\n throw error;\n }\n}\n\nasync function parseStoredDocument(\n fs: FileSystem,\n filePath: string,\n raw: string,\n recoverInvalid: boolean\n): Promise<{ content: string; data: ConfigDocument }> {\n try {\n return {\n content: raw,\n data: normalizeDocument(JSON.parse(raw))\n };\n } catch (error) {\n if (error instanceof SyntaxError) {\n if (!recoverInvalid) {\n throw error;\n }\n await recoverInvalidDocument(fs, filePath, raw);\n return {\n content: EMPTY_DOCUMENT,\n data: {}\n };\n }\n throw error;\n }\n}\n\nfunction normalizeDocument(value: unknown): ConfigDocument {\n if (!isRecord(value)) {\n return {};\n }\n\n const document: ConfigDocument = {};\n for (const [scope, scopeValues] of Object.entries(value)) {\n const normalizedValues = normalizeScopeValues(scopeValues);\n if (Object.keys(normalizedValues).length > 0) {\n defineDataProperty(document, scope, normalizedValues);\n }\n }\n\n return document;\n}\n\nfunction normalizeScopeValues(value: unknown): Record<string, unknown> {\n if (!isRecord(value)) {\n return {};\n }\n\n const normalized: Record<string, unknown> = {};\n for (const [key, entry] of Object.entries(value)) {\n if (entry !== undefined) {\n defineDataProperty(normalized, key, entry);\n }\n }\n\n return normalized;\n}\n\nfunction defineDataProperty(object: Record<string, unknown>, key: string, value: unknown): void {\n Object.defineProperty(object, key, {\n configurable: true,\n enumerable: true,\n value,\n writable: true\n });\n}\n\nfunction createResolvedConfigFs(\n fs: FileSystem,\n globalPath: string,\n globalContent: string\n): ResolveFileSystem {\n return {\n readFile(filePath: string, _encoding: BufferEncoding) {\n if (filePath === globalPath) {\n return Promise.resolve(globalContent);\n }\n\n return fs.readFile(filePath, \"utf8\");\n }\n };\n}\n\nexport async function writeDocument(\n fs: FileSystem,\n filePath: string,\n document: ConfigDocument\n): Promise<void> {\n await assertConfigPathSafe(fs, filePath);\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n await assertConfigPathSafe(fs, filePath);\n await writeFileAtomically(fs, filePath, `${JSON.stringify(document, null, 2)}\\n`);\n}\n\nasync function recoverInvalidDocument(\n fs: FileSystem,\n filePath: string,\n content: string\n): Promise<void> {\n await assertConfigPathSafe(fs, filePath);\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n await assertConfigPathSafe(fs, filePath);\n await writeInvalidBackup(fs, filePath, content);\n await writeFileAtomically(fs, filePath, EMPTY_DOCUMENT);\n}\n\nexport async function assertConfigPathSafe(fs: FileSystem, filePath: string): Promise<void> {\n for (const target of [path.dirname(filePath), filePath]) {\n try {\n if ((await fs.lstat(target)).isSymbolicLink()) {\n throw new Error(`Refusing configuration access through symbolic link: ${target}`);\n }\n } catch (error) {\n if (!isNotFound(error)) {\n throw error;\n }\n }\n }\n}\n\nfunction createInvalidBackupPath(filePath: string): string {\n const directory = path.dirname(filePath);\n const baseName = path.basename(filePath);\n return path.join(directory, `${baseName}.invalid-${createTimestamp()}.json`);\n}\n\nasync function writeInvalidBackup(fs: FileSystem, filePath: string, content: string): Promise<void> {\n const backupPath = createInvalidBackupPath(filePath);\n const backupStem = backupPath.slice(0, -\".json\".length);\n\n for (let suffix = 0; ; suffix += 1) {\n const candidate = suffix === 0 ? backupPath : `${backupStem}-${suffix}.json`;\n\n try {\n await fs.writeFile(candidate, content, { encoding: \"utf8\", flag: \"wx\" });\n return;\n } catch (error) {\n if (!isAlreadyExists(error)) {\n await fs.unlink(candidate).catch(() => undefined);\n throw error;\n }\n }\n }\n}\n\nasync function writeFileAtomically(fs: FileSystem, filePath: string, content: string): Promise<void> {\n const tempPath = `${filePath}.${process.pid}.${randomUUID()}.tmp`;\n let tempCreated = false;\n\n try {\n await fs.writeFile(tempPath, content, { encoding: \"utf8\", flag: \"wx\" });\n tempCreated = true;\n await fs.rename(tempPath, filePath);\n } catch (error) {\n if (tempCreated || !isAlreadyExists(error)) {\n await fs.unlink(tempPath).catch(() => undefined);\n }\n throw error;\n }\n}\n\nfunction isAlreadyExists(error: unknown): boolean {\n return hasOwnErrorCode(error, \"EEXIST\");\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value && typeof value === \"object\" && !Array.isArray(value));\n}\n\nexport function resolveConfigPath(homeDir: string): string {\n return path.join(homeDir, \".poe-code\", \"config.json\");\n}\n\nexport function resolveServicesConfigPath(homeDir: string): string {\n return path.join(homeDir, \".config\", \"poe-code\", \"services.json\");\n}\n\nexport function resolveProjectConfigPath(cwd: string): string {\n return path.join(cwd, \".poe-code\", \"config.json\");\n}\n\nconst EMPTY_DOCUMENT = `${JSON.stringify({}, null, 2)}\\n`;\n", "import path from \"node:path\";\nimport { hasOwnErrorCode } from \"./error-codes.js\";\nimport type { FileSystem } from \"./types.js\";\n\nexport interface DiscoveredBase {\n content: string;\n filePath: string;\n}\n\nexport async function findBase(\n name: string,\n bases: string[],\n fs: FileSystem\n): Promise<DiscoveredBase> {\n const checkedPaths: string[] = [];\n\n for (const basePath of bases) {\n for (const extension of [\".md\", \".yaml\", \".yml\", \".json\"]) {\n const filePath = path.join(basePath, `${name}${extension}`);\n const relativePath = path.relative(path.resolve(basePath), path.resolve(filePath));\n\n if (\n relativePath === \"..\" ||\n relativePath.startsWith(`..${path.sep}`) ||\n path.isAbsolute(relativePath)\n ) {\n throw new Error(\"Base name must remain inside configured base directories.\");\n }\n\n checkedPaths.push(filePath);\n\n try {\n return {\n content: await fs.readFile(filePath, \"utf8\"),\n filePath\n };\n } catch (error) {\n if (hasOwnErrorCode(error, \"ENOENT\")) {\n continue;\n }\n\n throw error;\n }\n }\n }\n\n throw new Error(`Base \"${name}\" not found.\\nChecked paths:\\n- ${checkedPaths.join(\"\\n- \")}`);\n}\n", "import path from \"node:path\";\nimport { FrontmatterParseError, parseFrontmatter } from \"@poe-code/frontmatter\";\nimport { parse as parseYaml } from \"yaml\";\nimport type { ParsedDocument } from \"./types.js\";\n\nexport function parseDocument(content: string, filePath: string): ParsedDocument {\n const normalizedContent = stripBom(content);\n const format = detectFormat(normalizedContent, filePath);\n const data =\n format === \"markdown\"\n ? parseMarkdown(normalizedContent, filePath)\n : toData(\n format === \"json\"\n ? parseJson(normalizedContent, filePath)\n : (parseYaml(normalizedContent) ?? {}),\n filePath\n );\n const hasExtendsField = Object.hasOwn(data, \"extends\");\n const extendsValue = hasExtendsField ? data.extends : undefined;\n const parsedExtends = parseExtendsValue(extendsValue, hasExtendsField, filePath);\n\n delete data.extends;\n\n return {\n data,\n format,\n extends: parsedExtends,\n hasExtendsField\n };\n}\n\nfunction parseExtendsValue(\n value: unknown,\n hasExtendsField: boolean,\n filePath: string\n): ParsedDocument[\"extends\"] {\n if (!hasExtendsField || value === false || value === undefined) {\n return false;\n }\n\n if (value === true) {\n return true;\n }\n\n if (typeof value !== \"string\") {\n throw new Error(\n `Invalid extends value in ${filePath}: expected a boolean or relative string path.`\n );\n }\n\n const trimmedValue = value.trim();\n\n if (trimmedValue.length === 0) {\n throw new Error(`Invalid extends value in ${filePath}: expected a non-empty relative path.`);\n }\n\n if (path.isAbsolute(trimmedValue)) {\n throw new Error(`Invalid extends value in ${filePath}: expected a relative path.`);\n }\n\n return trimmedValue;\n}\n\nfunction detectFormat(\n content: string,\n filePath: string\n): ParsedDocument[\"format\"] {\n const extension = path.extname(filePath).toLowerCase();\n\n if (extension === \".md\") {\n return \"markdown\";\n }\n\n if (extension === \".yaml\" || extension === \".yml\") {\n return \"yaml\";\n }\n\n if (extension === \".json\") {\n return \"json\";\n }\n\n if (content.startsWith(\"{\")) {\n return \"json\";\n }\n\n if (content.startsWith(\"---\\n\") || content.startsWith(\"---\\r\\n\") || content.startsWith(\"---\\r\")) {\n return \"markdown\";\n }\n\n return \"yaml\";\n}\n\nfunction parseMarkdown(content: string, filePath: string): Record<string, unknown> {\n let document;\n\n try {\n document = parseFrontmatter(normalizeMarkdownLineEndings(content));\n } catch (error) {\n if (\n error instanceof FrontmatterParseError &&\n error.message === \"Missing YAML frontmatter end delimiter (---).\"\n ) {\n return { prompt: content };\n }\n\n throw error;\n }\n\n const data = toData(document.frontmatter, filePath);\n if (document.body !== \"\" || !Object.hasOwn(data, \"prompt\")) {\n return {\n ...data,\n prompt: document.body\n };\n }\n\n return data;\n}\n\nfunction parseJson(content: string, filePath: string): unknown {\n try {\n return JSON.parse(content);\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Unknown JSON parse error\";\n throw new Error(`Invalid JSON configuration in ${filePath}: ${message}`);\n }\n}\n\nfunction normalizeMarkdownLineEndings(content: string): string {\n let normalized = \"\";\n\n for (let index = 0; index < content.length; index += 1) {\n const character = content[index];\n\n if (character === \"\\r\" && content[index + 1] !== \"\\n\") {\n normalized += \"\\n\";\n continue;\n }\n\n normalized += character;\n }\n\n return normalized;\n}\n\nfunction toData(value: unknown, filePath: string): Record<string, unknown> {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new Error(`Invalid configuration in ${filePath}: expected an object root.`);\n }\n\n return {\n ...(value as Record<string, unknown>)\n };\n}\n\nfunction stripBom(content: string): string {\n if (!content.startsWith(\"\\uFEFF\")) {\n return content;\n }\n\n return content.slice(1);\n}\n", "import { LineCounter, parse, parseDocument } from \"yaml\";\nimport { inspectFrontmatterBlock, splitFrontmatterBlock } from \"./fences.js\";\n\nexport interface ParsedFrontmatter {\n frontmatter: Record<string, unknown>;\n body: string;\n}\n\nexport interface ParsedFrontmatterDocument extends ParsedFrontmatter {\n errors: readonly { message: string; pos?: [number, number] }[];\n lineCounter: LineCounter;\n}\n\nexport interface ParseFrontmatterOptions {\n uniqueKeys?: boolean;\n}\n\nexport class FrontmatterParseError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"FrontmatterParseError\";\n }\n}\n\nexport class FrontmatterKindError extends FrontmatterParseError {\n readonly expectedKind: string;\n readonly foundKind: string;\n\n constructor(message: string, kinds: { expected: string; found: string }) {\n super(message);\n this.name = \"FrontmatterKindError\";\n this.expectedKind = kinds.expected;\n this.foundKind = kinds.found;\n }\n}\n\nexport function isFrontmatterKindError(error: unknown): error is FrontmatterKindError {\n return (\n error instanceof Error &&\n error.name === \"FrontmatterKindError\" &&\n typeof (error as { expectedKind?: unknown }).expectedKind === \"string\" &&\n typeof (error as { foundKind?: unknown }).foundKind === \"string\"\n );\n}\n\nexport function parseFrontmatter(\n source: string,\n options: ParseFrontmatterOptions = {}\n): ParsedFrontmatter {\n const split = splitFrontmatter(source);\n\n if (split.raw === undefined) {\n return {\n frontmatter: {},\n body: split.body\n };\n }\n\n return {\n frontmatter: parseYamlFrontmatter(split.raw, options),\n body: split.body\n };\n}\n\nexport function parseFrontmatterDocument(\n source: string,\n options: ParseFrontmatterOptions = {}\n): ParsedFrontmatterDocument {\n const split = inspectFrontmatterBlock(source);\n const lineCounter = createSourceLineCounter(source);\n\n if (split.kind === \"body\") {\n return {\n frontmatter: {},\n body: split.body,\n errors: [],\n lineCounter\n };\n }\n\n if (split.kind === \"missing-closing-fence\") {\n return {\n frontmatter: {},\n body: split.body,\n errors: [{ message: split.message, pos: [split.position, split.position] }],\n lineCounter\n };\n }\n\n const yamlLineCounter = new LineCounter();\n const normalizedYaml = normalizeYamlLineEndings(split.raw);\n const document = parseDocument(normalizedYaml, {\n lineCounter: yamlLineCounter,\n prettyErrors: false,\n uniqueKeys: options.uniqueKeys ?? false\n });\n const errors = document.errors.map((error) => ({\n message: error.message,\n ...(error.pos === undefined\n ? {}\n : { pos: translateYamlErrorPosition(error.pos as [number, number], split) })\n }));\n\n if (errors.length > 0) {\n return {\n frontmatter: {},\n body: split.body,\n errors,\n lineCounter\n };\n }\n\n try {\n return {\n frontmatter: normalizeYamlFrontmatter(document.toJSON()),\n body: split.body,\n errors,\n lineCounter\n };\n } catch (error) {\n if (error instanceof FrontmatterParseError) {\n return {\n frontmatter: {},\n body: split.body,\n errors: [{ message: error.message }],\n lineCounter\n };\n }\n\n throw error;\n }\n}\n\nfunction createSourceLineCounter(source: string): LineCounter {\n const lineCounter = new LineCounter();\n lineCounter.addNewLine(0);\n\n for (let index = 0; index < source.length; index += 1) {\n const character = source[index];\n\n if (character === \"\\n\") {\n lineCounter.addNewLine(index + 1);\n continue;\n }\n\n if (character === \"\\r\") {\n lineCounter.addNewLine(index + (source[index + 1] === \"\\n\" ? 2 : 1));\n if (source[index + 1] === \"\\n\") {\n index += 1;\n }\n }\n }\n\n return lineCounter;\n}\n\nfunction translateYamlErrorPosition(\n pos: [number, number],\n split: { raw: string; rawStart: number }\n): [number, number] {\n return pos.map((offset) => split.rawStart + normalizeYamlErrorOffset(split.raw, offset)) as [\n number,\n number\n ];\n}\n\nfunction normalizeYamlErrorOffset(raw: string, offset: number): number {\n if (offset >= raw.length && endsWithLineBreak(raw)) {\n return findPreviousLineStart(raw, raw.length);\n }\n\n return offset;\n}\n\nfunction endsWithLineBreak(value: string): boolean {\n return value.endsWith(\"\\n\") || value.endsWith(\"\\r\");\n}\n\nfunction findPreviousLineStart(value: string, end: number): number {\n let index = end - 1;\n\n if (value[index] === \"\\n\") {\n index -= 1;\n }\n\n if (value[index] === \"\\r\") {\n index -= 1;\n }\n\n while (index >= 0) {\n const character = value[index];\n\n if (character === \"\\n\" || character === \"\\r\") {\n return index + 1;\n }\n\n index -= 1;\n }\n\n return 0;\n}\n\nfunction splitFrontmatter(source: string): { raw?: string; body: string } {\n try {\n return splitFrontmatterBlock(source);\n } catch (error) {\n if (error instanceof Error) {\n throw new FrontmatterParseError(error.message);\n }\n\n throw error;\n }\n}\n\nfunction parseYamlFrontmatter(\n yamlBlock: string,\n options: ParseFrontmatterOptions\n): Record<string, unknown> {\n let parsed: unknown;\n\n try {\n parsed = parse(normalizeYamlLineEndings(yamlBlock), {\n uniqueKeys: options.uniqueKeys ?? false\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Unknown YAML parse error\";\n throw new FrontmatterParseError(`Invalid YAML frontmatter: ${message}`);\n }\n\n return normalizeYamlFrontmatter(parsed);\n}\n\nfunction normalizeYamlLineEndings(value: string): string {\n if (!value.includes(\"\\r\")) {\n return value;\n }\n\n let normalized = \"\";\n\n for (let index = 0; index < value.length; index += 1) {\n const character = value[index];\n\n if (character !== \"\\r\") {\n normalized += character;\n continue;\n }\n\n if (value[index + 1] === \"\\n\") {\n normalized += \"\\r\\n\";\n index += 1;\n continue;\n }\n\n normalized += \"\\n\";\n }\n\n return normalized;\n}\n\nfunction normalizeYamlFrontmatter(value: unknown): Record<string, unknown> {\n if (value === null || value === undefined) {\n return {};\n }\n\n if (!isPlainRecord(value)) {\n throw new FrontmatterParseError(\"YAML frontmatter must parse to an object.\");\n }\n\n return normalizeYamlValue(value) as Record<string, unknown>;\n}\n\nfunction normalizeYamlValue(value: unknown): unknown {\n if (Array.isArray(value)) {\n return value.map((item) => normalizeYamlValue(item));\n }\n\n if (!isPlainRecord(value)) {\n return value;\n }\n\n const normalized: Record<string, unknown> = {};\n\n for (const [key, entryValue] of Object.entries(value)) {\n Object.defineProperty(normalized, key, {\n configurable: true,\n enumerable: true,\n value: normalizeYamlValue(entryValue),\n writable: true\n });\n }\n\n return normalized;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n if (!isRecord(value)) {\n return false;\n }\n\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n}\n", "import { stringify } from \"yaml\";\nimport { FrontmatterParseError } from \"./parse.js\";\n\nexport function stringifyFrontmatter(frontmatter: Record<string, unknown>, body: string): string {\n try {\n assertFrontmatterRoot(frontmatter);\n assertAcyclic(frontmatter);\n return `---\\n${stringify(frontmatter, { aliasDuplicateObjects: false }).trimEnd()}\\n---\\n${body}`;\n } catch (error) {\n if (error instanceof FrontmatterParseError) {\n throw error;\n }\n\n const message = error instanceof Error ? error.message : \"Unknown YAML stringify error\";\n throw new FrontmatterParseError(`Invalid YAML frontmatter: ${message}`);\n }\n}\n\nfunction assertFrontmatterRoot(value: unknown): asserts value is Record<string, unknown> {\n if (!isPlainRecord(value)) {\n throw new FrontmatterParseError(\"YAML frontmatter must parse to an object.\");\n }\n}\n\nfunction assertAcyclic(value: unknown, seen: WeakSet<object> = new WeakSet()): void {\n if (typeof value !== \"object\" || value === null) {\n return;\n }\n\n if (seen.has(value)) {\n throw new FrontmatterParseError(\"Cannot stringify cyclic frontmatter.\");\n }\n\n seen.add(value);\n\n if (Array.isArray(value)) {\n for (const item of value) {\n assertAcyclic(item, seen);\n }\n } else {\n for (const item of Object.values(value)) {\n assertAcyclic(item, seen);\n }\n }\n\n seen.delete(value);\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return false;\n }\n\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n}\n", "import path from \"node:path\";\nimport {\n getTemplatePartialNames,\n renderTemplate,\n resolveTemplatePartials\n} from \"toolcraft-design\";\nimport { findBase } from \"./discover.js\";\nimport { hasOwnErrorCode } from \"./error-codes.js\";\nimport { mergeLayers } from \"./merge.js\";\nimport { parseDocument } from \"./parse.js\";\nimport type {\n BaseLayer,\n ChainLayer,\n DataLayer,\n DocumentLayer,\n ResolveOptions,\n ResolvedDocument\n} from \"./types.js\";\n\nconst MAX_EXTENDS_DEPTH = 5;\nconst YIELD_TOKEN = \"{{yield}}\";\n\ninterface ClassifiedChain {\n baseLayers: BaseLayer[];\n documentIndex: number;\n documentLayer: DocumentLayer;\n}\n\ninterface ResolvedBaseChain {\n chain: string[];\n layers: DataLayer[];\n}\n\ninterface ResolvedBase {\n content: string;\n filePath: string;\n source: string;\n matchedBaseIndex?: number;\n}\n\nexport async function resolve(\n chain: ChainLayer[],\n options: ResolveOptions\n): Promise<ResolvedDocument> {\n const { baseLayers, documentIndex, documentLayer } = classifyChain(chain);\n const parsedDocument = parseDocument(documentLayer.content, documentLayer.filePath);\n const resolvedBase = shouldResolveBase(parsedDocument, options.autoExtend)\n ? await resolveBaseChain({\n name: documentLayer.baseName ?? getBaseName(documentLayer.filePath),\n baseLayers,\n extendsValue: parsedDocument.extends,\n fromFilePath: documentLayer.filePath,\n options,\n optional: !parsedDocument.extends,\n visited: new Set([path.resolve(documentLayer.filePath)]),\n depth: 1\n })\n : undefined;\n const promptFiles = [documentLayer.filePath, ...(resolvedBase?.chain ?? [])];\n const expandedPrompts = await expandPromptPartials(\n {\n source: documentLayer.source,\n data: parsedDocument.data\n },\n resolvedBase?.layers ?? [],\n promptFiles,\n options\n );\n const composedPrompt = composePromptChain(\n expandedPrompts.documentLayer,\n expandedPrompts.baseLayers\n );\n const renderedPrompt =\n composedPrompt === undefined ? undefined : renderPrompt(composedPrompt.prompt, options);\n const merged = mergeLayers([\n ...collectDataLayers(chain.slice(0, documentIndex)),\n {\n source: documentLayer.source,\n data: withResolvedPrompt(parsedDocument.data, renderedPrompt)\n },\n ...stripResolvedBasePrompts(\n resolvedBase?.layers ?? [],\n composedPrompt?.consumedBaseIndexes ?? new Set<number>()\n ),\n ...collectDataLayers(chain.slice(documentIndex + 1))\n ]);\n\n if (\n composedPrompt !== undefined &&\n getOwnEntry(merged.sources, \"prompt\") === documentLayer.source &&\n composedPrompt.source !== undefined\n ) {\n merged.sources.prompt = composedPrompt.source;\n }\n\n return {\n data: merged.data,\n sources: merged.sources,\n chain: [...promptFiles, ...expandedPrompts.partialFiles]\n };\n}\n\nfunction classifyChain(chain: ChainLayer[]): ClassifiedChain {\n const baseLayers: BaseLayer[] = [];\n const documentLayers: Array<{ index: number; layer: DocumentLayer }> = [];\n\n for (const [index, layer] of chain.entries()) {\n if (isDataLayer(layer)) {\n continue;\n }\n\n if (isDocumentLayer(layer)) {\n documentLayers.push({ index, layer });\n continue;\n }\n\n if (isBaseLayer(layer)) {\n baseLayers.push(layer);\n }\n }\n\n if (documentLayers.length !== 1) {\n throw new Error(`Exactly one document layer is required, received ${documentLayers.length}.`);\n }\n\n return {\n baseLayers,\n documentIndex: documentLayers[0].index,\n documentLayer: documentLayers[0].layer\n };\n}\n\nasync function resolveBaseChain({\n name,\n baseLayers,\n extendsValue,\n fromFilePath,\n options,\n optional,\n visited,\n depth\n}: {\n name: string;\n baseLayers: BaseLayer[];\n extendsValue: boolean | string;\n fromFilePath: string;\n options: ResolveOptions;\n optional: boolean;\n visited: Set<string>;\n depth: number;\n}): Promise<ResolvedBaseChain | undefined> {\n if (depth > MAX_EXTENDS_DEPTH) {\n throw new Error(`Maximum extends depth exceeded (${MAX_EXTENDS_DEPTH}).`);\n }\n\n const discoveredBase = await resolveBase({\n name,\n baseLayers,\n extendsValue,\n fromFilePath,\n options,\n optional\n });\n\n if (discoveredBase === undefined) {\n return undefined;\n }\n\n const resolvedBasePath = path.resolve(discoveredBase.filePath);\n\n if (visited.has(resolvedBasePath)) {\n if (optional) {\n return undefined;\n }\n\n throw new Error(\n `Circular extends detected.\\nVisited files:\\n- ${[...visited, resolvedBasePath].join(\"\\n- \")}`\n );\n }\n\n const parsedBase = parseDocument(discoveredBase.content, discoveredBase.filePath);\n const nextVisited = new Set(visited);\n nextVisited.add(resolvedBasePath);\n const nestedBase = parsedBase.extends\n ? await resolveBaseChain({\n name: getBaseName(discoveredBase.filePath),\n baseLayers:\n discoveredBase.matchedBaseIndex === undefined\n ? baseLayers\n : baseLayers.slice(discoveredBase.matchedBaseIndex + 1),\n extendsValue: parsedBase.extends,\n fromFilePath: discoveredBase.filePath,\n options,\n optional: false,\n visited: nextVisited,\n depth: depth + 1\n })\n : undefined;\n\n return {\n layers: [\n {\n source: discoveredBase.source,\n data: parsedBase.data\n },\n ...(nestedBase?.layers ?? [])\n ],\n chain: [discoveredBase.filePath, ...(nestedBase?.chain ?? [])]\n };\n}\n\nasync function resolveBase({\n name,\n baseLayers,\n extendsValue,\n fromFilePath,\n options,\n optional\n}: {\n name: string;\n baseLayers: BaseLayer[];\n extendsValue: boolean | string;\n fromFilePath: string;\n options: ResolveOptions;\n optional: boolean;\n}): Promise<ResolvedBase | undefined> {\n if (typeof extendsValue === \"string\") {\n return readPathValuedBase(extendsValue, fromFilePath, options);\n }\n\n let discoveredBase;\n\n try {\n discoveredBase = await findBase(\n name,\n baseLayers.map((layer) => layer.path),\n options.fs\n );\n } catch (error) {\n if (optional && isBaseNotFoundError(error)) {\n return undefined;\n }\n\n throw error;\n }\n\n const discoveredBaseDirectory = path.resolve(path.dirname(discoveredBase.filePath));\n const matchedBaseIndex = baseLayers.findIndex(\n (layer) => path.resolve(layer.path) === discoveredBaseDirectory\n );\n\n if (matchedBaseIndex === -1) {\n throw new Error(`Resolved base is outside configured base paths: ${discoveredBase.filePath}`);\n }\n\n return {\n content: discoveredBase.content,\n filePath: discoveredBase.filePath,\n matchedBaseIndex,\n source: baseLayers[matchedBaseIndex].source\n };\n}\n\nasync function readPathValuedBase(\n extendsPath: string,\n fromFilePath: string,\n options: ResolveOptions\n): Promise<ResolvedBase> {\n const filePath = path.resolve(path.dirname(fromFilePath), extendsPath);\n\n try {\n return {\n content: await options.fs.readFile(filePath, \"utf8\"),\n filePath,\n source: filePath\n };\n } catch (error) {\n if (hasOwnErrorCode(error, \"ENOENT\") || hasOwnErrorCode(error, \"ENOTDIR\")) {\n throw new Error(`base file not found at ${filePath}`);\n }\n\n throw error;\n }\n}\n\nfunction collectDataLayers(chain: ChainLayer[]): DataLayer[] {\n return chain.filter(isDataLayer);\n}\n\ninterface ComposedPromptResult {\n consumedBaseIndexes: Set<number>;\n prompt: string;\n source?: string;\n}\n\nfunction composePromptChain(\n documentLayer: DataLayer,\n baseLayers: DataLayer[]\n): ComposedPromptResult | undefined {\n const documentPrompt = getOwnEntry(documentLayer.data, \"prompt\");\n\n if (documentPrompt !== undefined && typeof documentPrompt !== \"string\") {\n return undefined;\n }\n\n if (documentPrompt !== undefined) {\n assertValidYieldCount(documentPrompt);\n }\n\n let prompt = documentPrompt;\n let source = prompt === undefined || prompt === \"\" ? undefined : documentLayer.source;\n const consumedBaseIndexes = new Set<number>();\n\n for (const [index, layer] of baseLayers.entries()) {\n const candidate = getOwnEntry(layer.data, \"prompt\");\n\n if (candidate === undefined) {\n continue;\n }\n\n if (typeof candidate !== \"string\") {\n break;\n }\n\n assertValidYieldCount(candidate);\n consumedBaseIndexes.add(index);\n prompt = composeAdjacentPrompts(prompt, candidate);\n\n if (source === undefined && candidate !== \"\") {\n source = layer.source;\n }\n }\n\n if (prompt !== undefined && prompt.includes(YIELD_TOKEN)) {\n throw new Error('Final resolved prompt contains an unresolved \"{{yield}}\" token.');\n }\n\n if (prompt === undefined) {\n return undefined;\n }\n\n return {\n consumedBaseIndexes,\n prompt,\n source\n };\n}\n\nfunction composeAdjacentPrompts(high: string | undefined, low: string): string {\n if (high === undefined || high === \"\") {\n return low.includes(YIELD_TOKEN) ? replaceYield(low, \"\") : low;\n }\n\n if (high.includes(YIELD_TOKEN)) {\n return replaceYield(high, low);\n }\n\n if (low.includes(YIELD_TOKEN)) {\n return replaceYield(low, high);\n }\n\n return high;\n}\n\nfunction replaceYield(prompt: string, replacement: string): string {\n return prompt.split(YIELD_TOKEN).join(replacement);\n}\n\nasync function expandPromptPartials(\n documentLayer: DataLayer,\n baseLayers: DataLayer[],\n promptFiles: string[],\n options: ResolveOptions\n): Promise<{ baseLayers: DataLayer[]; documentLayer: DataLayer; partialFiles: string[] }> {\n const directories = unique(promptFiles.map((filePath) => path.dirname(filePath)));\n const partials: Record<string, string> = Object.create(null) as Record<string, string>;\n const partialFiles: string[] = [];\n\n const loadPartial = async (name: string): Promise<void> => {\n if (name.trim().length === 0) {\n throw new Error(\"Partial name must be non-empty.\");\n }\n\n if (Object.hasOwn(partials, name)) {\n return;\n }\n\n const partial = await findPartial(name, directories, options.fs);\n partials[name] = partial.content;\n partialFiles.push(partial.filePath);\n for (const nestedName of getTemplatePartialNames(partial.content)) {\n await loadPartial(nestedName);\n }\n };\n\n const promptLayers = [documentLayer, ...baseLayers];\n for (const layer of promptLayers) {\n const prompt = getOwnEntry(layer.data, \"prompt\");\n if (typeof prompt !== \"string\") {\n continue;\n }\n for (const name of getTemplatePartialNames(prompt)) {\n await loadPartial(name);\n }\n }\n\n const expandedLayers = promptLayers.map((layer) => withExpandedPrompt(layer, partials));\n\n return {\n documentLayer: expandedLayers[0],\n baseLayers: expandedLayers.slice(1),\n partialFiles\n };\n}\n\nfunction withExpandedPrompt(layer: DataLayer, partials: Record<string, string>): DataLayer {\n const prompt = getOwnEntry(layer.data, \"prompt\");\n if (typeof prompt !== \"string\") {\n return layer;\n }\n\n return {\n source: layer.source,\n data: {\n ...layer.data,\n prompt: resolveTemplatePartials(prompt, partials)\n }\n };\n}\n\nfunction renderPrompt(prompt: string, options: ResolveOptions): string {\n if (options.view === undefined && options.validate !== true) {\n return prompt;\n }\n\n return renderTemplate(prompt, options.view ?? {}, { escape: \"none\", validate: options.validate });\n}\n\nasync function findPartial(\n name: string,\n directories: string[],\n fs: ResolveOptions[\"fs\"]\n): Promise<{ content: string; filePath: string }> {\n const checkedPaths: string[] = [];\n\n for (const directory of directories) {\n const filePath = path.join(directory, `${name}.md`);\n assertInsideDirectory(name, directory, filePath);\n checkedPaths.push(filePath);\n\n try {\n return { content: await fs.readFile(filePath, \"utf8\"), filePath };\n } catch (error) {\n if (hasOwnErrorCode(error, \"ENOENT\")) {\n continue;\n }\n throw error;\n }\n }\n\n throw new Error(`Partial \"${name}\" not found.\\nChecked paths:\\n- ${checkedPaths.join(\"\\n- \")}`);\n}\n\nfunction assertInsideDirectory(name: string, directory: string, filePath: string): void {\n const relativePath = path.relative(path.resolve(directory), path.resolve(filePath));\n if (\n relativePath === \"..\" ||\n relativePath.startsWith(`..${path.sep}`) ||\n path.isAbsolute(relativePath)\n ) {\n throw new Error(`Partial name must remain inside prompt directories: \"${name}\".`);\n }\n}\n\nfunction unique(values: string[]): string[] {\n return [...new Set(values)];\n}\n\nfunction assertValidYieldCount(prompt: string): void {\n if (countYieldTokens(prompt) > 1) {\n throw new Error('Prompt composition supports exactly one \"{{yield}}\" token per prompt.');\n }\n}\n\nfunction countYieldTokens(prompt: string): number {\n return prompt.split(YIELD_TOKEN).length - 1;\n}\n\nfunction withResolvedPrompt(\n data: Record<string, unknown>,\n prompt: string | undefined\n): Record<string, unknown> {\n if (prompt === undefined) {\n return data;\n }\n\n return {\n ...data,\n prompt\n };\n}\n\nfunction stripResolvedBasePrompts(\n layers: DataLayer[],\n consumedBaseIndexes: Set<number>\n): DataLayer[] {\n return layers.map((layer, index) => {\n if (!consumedBaseIndexes.has(index) || typeof getOwnEntry(layer.data, \"prompt\") !== \"string\") {\n return layer;\n }\n\n const { prompt: ignoredPrompt, ...data } = layer.data;\n\n void ignoredPrompt;\n\n return {\n source: layer.source,\n data\n };\n });\n}\n\nfunction getBaseName(filePath: string): string {\n return path.basename(filePath, path.extname(filePath));\n}\n\nfunction shouldResolveBase(\n parsedDocument: ReturnType<typeof parseDocument>,\n autoExtend: boolean | undefined\n): boolean {\n return parsedDocument.extends !== false || (autoExtend === true && !parsedDocument.hasExtendsField);\n}\n\nfunction getOwnEntry(record: Record<string, unknown>, key: string): unknown {\n return Object.prototype.hasOwnProperty.call(record, key) ? record[key] : undefined;\n}\n\nfunction isBaseNotFoundError(error: unknown): error is Error {\n return (\n error instanceof Error &&\n error.message.startsWith('Base \"') &&\n error.message.includes('\" not found.\\nChecked paths:')\n );\n}\n\nfunction isDataLayer(layer: ChainLayer): layer is DataLayer {\n return \"data\" in layer;\n}\n\nfunction isDocumentLayer(layer: ChainLayer): layer is DocumentLayer {\n return \"filePath\" in layer && \"content\" in layer;\n}\n\nfunction isBaseLayer(layer: ChainLayer): layer is BaseLayer {\n return \"path\" in layer;\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 let output = \"\";\n let index = 0;\n\n while (index < value.length) {\n const char = value[index];\n\n if (char === \"\\u001b\") {\n index = skipEscapeSequence(value, index);\n continue;\n }\n\n if (char === \"\\u009b\") {\n index = skipCsiSequence(value, index + 1);\n continue;\n }\n\n output += char;\n index += char.length;\n }\n\n return output;\n}\n\nfunction skipEscapeSequence(value: string, index: number): number {\n const next = value[index + 1];\n\n if (next === \"[\") {\n return skipCsiSequence(value, index + 2);\n }\n\n if (next === \"]\") {\n return skipOscSequence(value, index + 2);\n }\n\n return Math.min(value.length, index + 2);\n}\n\nfunction skipCsiSequence(value: string, index: number): number {\n while (index < value.length) {\n const codePoint = value.charCodeAt(index);\n index += 1;\n\n if (codePoint >= 0x40 && codePoint <= 0x7e) {\n break;\n }\n }\n\n return index;\n}\n\nfunction skipOscSequence(value: string, index: number): number {\n while (index < value.length) {\n if (value[index] === \"\\u0007\") {\n return index + 1;\n }\n\n if (value[index] === \"\\u001b\" && value[index + 1] === \"\\\\\") {\n return index + 2;\n }\n\n index += 1;\n }\n\n return index;\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 { resolveOutputFormat } from \"../internal/output-format.js\";\nimport { typography } from \"../tokens/typography.js\";\nimport { text } from \"./text.js\";\n\nexport type HelpTokenRole = \"command\" | \"argument\" | \"option\" | \"literal\" | \"dim\";\n\nexport interface HelpToken {\n text: string;\n role: HelpTokenRole;\n}\n\nexport interface CommandInfo {\n name: string;\n /** Structured tokens for TTY/markdown styling. Plain `name` is used when absent. */\n nameTokens?: HelpToken[];\n description: string;\n /** Nesting depth relative to the help target. Depth 0 is a direct child. */\n depth?: number;\n}\n\nexport interface OptionInfo {\n flags: string;\n /** Structured tokens for TTY/markdown styling. Plain `flags` is used when absent. */\n flagTokens?: HelpToken[];\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 leadingWhitespaceWidth(value: string): { prefix: string; rest: string } {\n let index = 0;\n while (index < value.length && isWhitespace(value[index])) {\n index += 1;\n }\n return { prefix: value.slice(0, index), rest: value.slice(index) };\n}\n\nfunction takeVisiblePrefix(value: string, width: number): { prefix: string; rest: string } {\n let visible = 0;\n let index = 0;\n\n while (index < value.length) {\n const controlEnd = readControlSequence(value, index);\n if (controlEnd !== undefined) {\n index = controlEnd;\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 ?? value[index] ?? \"\";\n const nextWidth = clusterWidth(cluster);\n if (visible > 0 && visible + nextWidth > width) {\n break;\n }\n visible += nextWidth;\n index += cluster.length || 1;\n }\n\n return { prefix: value.slice(0, index), rest: value.slice(index) };\n}\n\nfunction wrapWords(value: string, width: number, continuationWidth = width): string[] {\n // Preserve leading whitespace only on the first wrapped line so hang-indented\n // left cells (command depth prefixes) do not re-indent every continuation.\n const { prefix, rest } = leadingWhitespaceWidth(value);\n const prefixWidth = visibleWidth(prefix);\n const firstContentWidth = Math.max(1, width - prefixWidth);\n const words = splitWords(rest);\n if (words.length === 0) {\n return [prefix];\n }\n\n const lines: string[] = [];\n let line = \"\";\n let isFirstLine = true;\n\n for (const word of words) {\n const limit = isFirstLine ? firstContentWidth : continuationWidth;\n if (line && visibleWidth(line) + 1 + visibleWidth(word) <= limit) {\n line += ` ${word}`;\n continue;\n }\n if (line) {\n lines.push(isFirstLine ? `${prefix}${line}` : line);\n isFirstLine = false;\n line = \"\";\n }\n\n let remaining = word;\n while (visibleWidth(remaining) > (isFirstLine ? firstContentWidth : continuationWidth)) {\n const chunk = takeVisiblePrefix(\n remaining,\n isFirstLine ? firstContentWidth : continuationWidth\n );\n lines.push(isFirstLine ? `${prefix}${chunk.prefix}` : chunk.prefix);\n isFirstLine = false;\n remaining = chunk.rest;\n }\n line = remaining;\n }\n\n lines.push(isFirstLine ? `${prefix}${line}` : 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(1, totalWidth - leftWidth - indent);\n const leftWrapWidth = Math.max(1, totalWidth - indent);\n const firstIndent = \" \".repeat(indent);\n const continuationIndent = \" \".repeat(indent + leftWidth);\n\n return rows\n .flatMap((row) => {\n const leftLeading = leadingWhitespaceWidth(row.left).prefix;\n // Continuations hang under the left cell start (including depth prefix) by +2.\n const leftHangIndent = \" \".repeat(indent + visibleWidth(leftLeading) + 2);\n const leftLines = wrapWords(\n row.left,\n leftWrapWidth,\n Math.max(1, totalWidth - visibleWidth(leftHangIndent))\n );\n\n if (row.right.length === 0) {\n return leftLines.map((line, index) =>\n index === 0 ? `${firstIndent}${line}` : `${leftHangIndent}${line}`\n );\n }\n\n const rightLines = wrapWords(row.right, rightWidth);\n const leftFitsInColumn = visibleWidth(row.left) < leftWidth;\n\n if (leftFitsInColumn && leftLines.length === 1) {\n const firstLine = `${firstIndent}${padEndVisible(leftLines[0] ?? \"\", leftWidth)}${rightLines[0]}`;\n const continuationLines = rightLines\n .slice(1)\n .map((line) => `${continuationIndent}${line}`);\n return [firstLine, ...continuationLines];\n }\n\n const renderedLeft = leftLines.map((line, index) =>\n index === 0 ? `${firstIndent}${line}` : `${leftHangIndent}${line}`\n );\n const renderedRight = rightLines.map((line) => `${continuationIndent}${line}`);\n return [...renderedLeft, ...renderedRight];\n })\n .join(\"\\n\");\n}\n\nexport function styleHelpToken(token: HelpToken): string {\n switch (token.role) {\n case \"command\":\n return text.command(token.text);\n case \"argument\":\n return styleArgumentToken(token.text);\n case \"option\":\n return text.option(token.text);\n case \"dim\":\n return styleDim(token.text);\n case \"literal\":\n return token.text;\n }\n}\n\nfunction styleArgumentToken(content: string): string {\n // Token text already includes angle brackets. text.argument re-wraps in markdown,\n // so strip first there; terminal/json keep the full `<value>` form.\n const format = resolveOutputFormat();\n if (format === \"markdown\" && content.startsWith(\"<\") && content.endsWith(\">\")) {\n return text.argument(content.slice(1, -1));\n }\n if (format === \"json\") {\n return content;\n }\n return text.argument(content);\n}\n\nfunction styleDim(content: string): string {\n // Structural brackets stay unstyled in markdown/json; italicizing them as muted is wrong.\n const format = resolveOutputFormat();\n if (format === \"json\" || format === \"markdown\") {\n return content;\n }\n return typography.dim(content);\n}\n\nexport function joinHelpTokens(tokens: HelpToken[]): string {\n return tokens.map((token) => token.text).join(\"\");\n}\n\nexport function renderHelpTokens(tokens: HelpToken[]): string {\n return tokens.map((token) => styleHelpToken(token)).join(\"\");\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 const depthPrefix = \" \".repeat((cmd.depth ?? 0) * 2);\n const styledName =\n cmd.nameTokens !== undefined && cmd.nameTokens.length > 0\n ? renderHelpTokens(cmd.nameTokens)\n : text.command(cmd.name);\n return {\n left: `${depthPrefix}${styledName}`,\n right: cmd.description\n };\n })\n });\n}\n\nexport function formatOptionList(options: OptionInfo[]): string {\n return formatColumns({\n rows: options.map((opt) => ({\n left:\n opt.flagTokens !== undefined && opt.flagTokens.length > 0\n ? renderHelpTokens(opt.flagTokens)\n : 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 styleHelpToken,\n joinHelpTokens,\n renderHelpTokens\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 minCellWidth = 4;\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\n// Each column is framed as \"\u2502 cell \", plus the closing \"\u2502\".\nfunction frameWidth(columnCount: number): number {\n return columnCount * 3 + 1;\n}\n\n// Log output indents every line with a \"\u2502 \" guide, so a table emitted through the\n// logger has that much less room than the terminal. Undefined without a terminal:\n// piped output has no width to fit.\nexport function loggerTableWidth(): number | undefined {\n const columns = process.stdout.columns;\n return columns === undefined ? undefined : columns - 3;\n}\n\n// Without an explicit budget or a TTY there is no width to fit: the consumer of the\n// piped output decides, so columns keep their declared widths.\nfunction budgetColumns(columns: ComputedColumn[], maxWidth: number | undefined): ComputedColumn[] {\n if (maxWidth === undefined) {\n return columns;\n }\n\n const available = maxWidth - frameWidth(columns.length);\n const contentWidth = (cap: number) =>\n columns.reduce((total, column) => total + Math.min(column.width, cap), 0);\n\n if (columns.reduce((total, column) => total + column.width, 0) <= available) {\n return columns;\n }\n\n // Widest-first: raise a shared cap as far as the budget allows, so narrow columns\n // keep their declared width and only the columns above the cap lose room.\n let cap = minCellWidth;\n while (contentWidth(cap + 1) <= available) {\n cap += 1;\n }\n\n const budgeted = columns.map((column) => ({ ...column, width: Math.min(column.width, cap) }));\n let slack = available - contentWidth(cap);\n while (slack > 0) {\n const growable = budgeted.filter((column, index) => column.width < columns[index]!.width);\n if (growable.length === 0) {\n break;\n }\n for (const column of growable) {\n if (slack === 0) {\n break;\n }\n column.width += 1;\n slack -= 1;\n }\n }\n\n return budgeted;\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 budgetedColumns = budgetColumns(computedColumns, options.maxWidth ?? process.stdout.columns);\n\n const top = renderBorder(budgetedColumns, theme, { left: \"\u250C\", mid: \"\u252C\", right: \"\u2510\" });\n const header = renderTerminalRow(\n budgetedColumns.map((column) => theme.header(column.title)),\n budgetedColumns,\n theme\n );\n const headerBottom = renderBorder(budgetedColumns, theme, { left: \"\u251C\", mid: \"\u253C\", right: \"\u2524\" });\n const bottom = renderBorder(budgetedColumns, 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 budgetedColumns.map((column) => getCell(row, column.name)),\n budgetedColumns,\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 stringWidth from \"fast-string-width\";\nimport { wrapAnsi } from \"fast-wrap-ansi\";\nimport type { ThemePalette } from \"../tokens/colors.js\";\nimport { widths } from \"../tokens/widths.js\";\n\nexport interface DetailCardRow {\n label: string;\n value: string;\n}\n\nexport interface DetailCardSection {\n title?: string;\n rows: DetailCardRow[];\n}\n\nexport interface RenderDetailCardOptions {\n theme: ThemePalette;\n title: string;\n subtitle?: string;\n badges?: string[];\n prose?: Array<{ title?: string; value: string }>;\n sections?: DetailCardSection[];\n width?: number;\n}\n\nfunction wrap(value: string, width: number): string[] {\n return wrapAnsi(value, Math.max(1, width), { hard: true, trim: true }).split(\"\\n\");\n}\n\nfunction renderRows(rows: DetailCardRow[], theme: ThemePalette, width: number): string[] {\n if (rows.length === 0) return [];\n const labelWidth = Math.max(...rows.map((row) => stringWidth(row.label)));\n const valueWidth = Math.max(20, width - labelWidth - 2);\n const continuation = \" \".repeat(labelWidth + 2);\n\n return rows.flatMap((row) => {\n const values = wrap(row.value, valueWidth);\n return [\n `${theme.muted(row.label.padEnd(labelWidth))} ${values[0] ?? \"\"}`,\n ...values.slice(1).map((value) => `${continuation}${value}`)\n ];\n });\n}\n\nexport function renderDetailCard(options: RenderDetailCardOptions): string {\n const width = options.width ?? widths.maxLine;\n const identity = [\n options.theme.header(options.title),\n options.subtitle ? options.theme.muted(options.subtitle) : undefined\n ]\n .filter((value): value is string => value !== undefined)\n .join(\" \");\n\n const hero = options.badges?.length\n ? `${identity}\\n${options.theme.muted(options.badges.map((badge) => badge[0] + badge.slice(1).toLowerCase()).join(\" \u00B7 \"))}`\n : identity;\n const blocks: string[] = [hero];\n for (const prose of options.prose ?? []) {\n blocks.push(\n prose.title\n ? [options.theme.header(prose.title), wrap(prose.value, width).join(\"\\n\")].join(\"\\n\")\n : wrap(prose.value, width).join(\"\\n\")\n );\n }\n\n for (const section of options.sections ?? []) {\n if (section.rows.length === 0) continue;\n const rows = renderRows(section.rows, options.theme, width);\n blocks.push(\n section.title ? [options.theme.header(section.title), ...rows].join(\"\\n\") : rows.join(\"\\n\")\n );\n }\n\n return blocks.join(\"\\n\\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 type { CodeToken, CodeTokenKind, MdNode } from \"../ast.js\";\n\ntype CodeHighlightFamily = \"lexical\" | \"data\" | \"style\" | \"line\" | \"markup\";\n\ntype CodeLanguageInfo = {\n id: string;\n aliases: readonly string[];\n family?: CodeHighlightFamily;\n spec?: string;\n plain?: boolean;\n};\n\ntype CodeTokenizer = (source: string, language: CodeLanguageInfo) => CodeToken[];\n\ntype TokenEmitter = {\n push(kind: CodeTokenKind, start: number, end: number): void;\n pushPlain(start: number, end: number): void;\n};\n\ntype LexicalSpec = {\n keywords?: ReadonlySet<string>;\n types?: ReadonlySet<string>;\n constants?: ReadonlySet<string>;\n booleans?: ReadonlySet<string>;\n nulls?: ReadonlySet<string>;\n commands?: ReadonlySet<string>;\n lineComments?: readonly string[];\n blockComments?: readonly BlockCommentDelimiter[];\n stringQuotes?: readonly string[];\n templateQuotes?: boolean;\n tripleStringQuotes?: boolean;\n decorators?: boolean;\n rustAttributes?: boolean;\n variablePrefix?: \"$\";\n flags?: boolean;\n caseInsensitive?: boolean;\n};\n\ntype BlockCommentDelimiter = {\n start: string;\n end: string;\n};\n\nconst cStyleBlockComments = [{ start: \"/*\", end: \"*/\" }] as const;\n\nconst codeLanguages: readonly CodeLanguageInfo[] = [\n {\n id: \"javascript\",\n aliases: [\"js\", \"javascript\", \"mjs\", \"cjs\", \"es6\"],\n family: \"lexical\",\n spec: \"javascript\"\n },\n { id: \"javascriptreact\", aliases: [\"jsx\"], family: \"lexical\", spec: \"javascript\" },\n {\n id: \"typescript\",\n aliases: [\"ts\", \"typescript\", \"mts\", \"cts\"],\n family: \"lexical\",\n spec: \"typescript\"\n },\n { id: \"typescriptreact\", aliases: [\"tsx\"], family: \"lexical\", spec: \"typescript\" },\n { id: \"json\", aliases: [\"json\"], family: \"data\", spec: \"json\" },\n { id: \"jsonc\", aliases: [\"jsonc\"], family: \"data\", spec: \"jsonc\" },\n { id: \"jsonl\", aliases: [\"jsonl\"], family: \"data\", spec: \"json\" },\n { id: \"yaml\", aliases: [\"yaml\", \"yml\"], family: \"data\", spec: \"yaml\" },\n { id: \"css\", aliases: [\"css\"], family: \"style\", spec: \"css\" },\n { id: \"scss\", aliases: [\"scss\"], family: \"style\", spec: \"css\" },\n { id: \"sass\", aliases: [\"sass\"], family: \"style\", spec: \"css\" },\n { id: \"less\", aliases: [\"less\"], family: \"style\", spec: \"css\" },\n { id: \"postcss\", aliases: [\"postcss\"], family: \"style\", spec: \"css\" },\n { id: \"shellscript\", aliases: [\"sh\", \"bash\", \"shell\", \"shellscript\", \"zsh\", \"fish\"], family: \"lexical\", spec: \"shell\" },\n { id: \"python\", aliases: [\"py\", \"python\"], family: \"lexical\", spec: \"python\" },\n { id: \"sql\", aliases: [\"sql\", \"ddl\", \"dml\"], family: \"lexical\", spec: \"sql\" },\n { id: \"html\", aliases: [\"html\"], family: \"markup\", spec: \"html\" },\n { id: \"xml\", aliases: [\"xml\", \"svg\"], family: \"markup\", spec: \"xml\" },\n { id: \"markdown\", aliases: [\"md\", \"markdown\"], family: \"line\", spec: \"markdown\" },\n { id: \"diff\", aliases: [\"diff\", \"patch\"], family: \"line\", spec: \"diff\" },\n { id: \"dockerfile\", aliases: [\"dockerfile\", \"docker\"], family: \"line\", spec: \"dockerfile\" },\n { id: \"ini\", aliases: [\"ini\", \"properties\"], family: \"data\", spec: \"ini\" },\n { id: \"toml\", aliases: [\"toml\"], family: \"data\", spec: \"toml\" },\n { id: \"plaintext\", aliases: [\"text\", \"txt\", \"plain\", \"plaintext\"], plain: true },\n { id: \"ruby\", aliases: [\"rb\", \"ruby\"], family: \"lexical\", spec: \"ruby\" },\n { id: \"go\", aliases: [\"go\", \"golang\"], family: \"lexical\", spec: \"go\" },\n { id: \"java\", aliases: [\"java\"], family: \"lexical\", spec: \"java\" },\n { id: \"kotlin\", aliases: [\"kt\", \"kotlin\", \"kts\"], family: \"lexical\", spec: \"kotlin\" },\n { id: \"swift\", aliases: [\"swift\"], family: \"lexical\", spec: \"swift\" },\n { id: \"dart\", aliases: [\"dart\"], family: \"lexical\", spec: \"dart\" },\n { id: \"scala\", aliases: [\"scala\", \"sc\"], family: \"lexical\", spec: \"scala\" },\n { id: \"groovy\", aliases: [\"groovy\", \"gvy\", \"gy\", \"gsp\"], family: \"lexical\", spec: \"groovy\" },\n { id: \"c\", aliases: [\"c\"], family: \"lexical\", spec: \"c\" },\n { id: \"cpp\", aliases: [\"cpp\", \"c++\", \"cc\", \"cxx\"], family: \"lexical\", spec: \"cpp\" },\n { id: \"csharp\", aliases: [\"cs\", \"csharp\", \"c#\"], family: \"lexical\", spec: \"csharp\" },\n { id: \"objective-c\", aliases: [\"objc\", \"objectivec\", \"objective-c\", \"m\", \"mm\"], family: \"lexical\", spec: \"objectivec\" },\n { id: \"rust\", aliases: [\"rs\", \"rust\"], family: \"lexical\", spec: \"rust\" },\n { id: \"php\", aliases: [\"php\"], family: \"lexical\", spec: \"php\" },\n { id: \"lua\", aliases: [\"lua\"], family: \"lexical\", spec: \"lua\" },\n { id: \"perl\", aliases: [\"pl\", \"perl\", \"pm\"], family: \"lexical\", spec: \"perl\" },\n { id: \"r\", aliases: [\"r\", \"rscript\"], family: \"lexical\", spec: \"r\" },\n { id: \"powershell\", aliases: [\"ps1\", \"powershell\", \"pwsh\"], family: \"lexical\", spec: \"powershell\" },\n { id: \"elixir\", aliases: [\"ex\", \"exs\", \"elixir\"], family: \"lexical\", spec: \"elixir\" },\n { id: \"erlang\", aliases: [\"erl\", \"erlang\", \"hrl\"], family: \"lexical\", spec: \"erlang\" },\n { id: \"haskell\", aliases: [\"hs\", \"haskell\"], family: \"lexical\", spec: \"haskell\" },\n { id: \"clojure\", aliases: [\"clj\", \"cljs\", \"cljc\", \"clojure\"], family: \"lexical\", spec: \"clojure\" },\n { id: \"fsharp\", aliases: [\"fs\", \"fsi\", \"fsx\", \"fsharp\"], family: \"lexical\", spec: \"fsharp\" },\n { id: \"vb\", aliases: [\"vb\", \"vbnet\"], family: \"lexical\", spec: \"vb\" },\n { id: \"graphql\", aliases: [\"graphql\", \"gql\"], family: \"lexical\", spec: \"graphql\" },\n { id: \"protobuf\", aliases: [\"proto\", \"protobuf\"], family: \"lexical\", spec: \"protobuf\" },\n { id: \"hcl\", aliases: [\"hcl\", \"tf\", \"terraform\"], family: \"lexical\", spec: \"hcl\" },\n { id: \"nginx\", aliases: [\"nginx\", \"nginxconf\"], family: \"lexical\", spec: \"nginx\" },\n { id: \"makefile\", aliases: [\"makefile\", \"mk\"], family: \"lexical\", spec: \"makefile\" },\n { id: \"cmake\", aliases: [\"cmake\"], family: \"lexical\", spec: \"cmake\" },\n { id: \"gradle\", aliases: [\"gradle\"], family: \"lexical\", spec: \"groovy\" },\n { id: \"env\", aliases: [\"env\", \"dotenv\"], family: \"data\", spec: \"ini\" },\n { id: \"vue\", aliases: [\"vue\"], family: \"markup\", spec: \"html\" },\n { id: \"svelte\", aliases: [\"svelte\"], family: \"markup\", spec: \"html\" }\n] as const;\n\nconst languageByAlias = new Map<string, CodeLanguageInfo>();\n\nfor (const language of codeLanguages) {\n languageByAlias.set(language.id.toLowerCase(), language);\n\n for (const alias of language.aliases) {\n languageByAlias.set(alias.toLowerCase(), language);\n }\n}\n\nconst jsKeywords = new Set([\n \"as\",\n \"async\",\n \"await\",\n \"break\",\n \"case\",\n \"catch\",\n \"class\",\n \"const\",\n \"continue\",\n \"debugger\",\n \"default\",\n \"delete\",\n \"do\",\n \"else\",\n \"export\",\n \"extends\",\n \"finally\",\n \"for\",\n \"from\",\n \"function\",\n \"get\",\n \"if\",\n \"import\",\n \"in\",\n \"instanceof\",\n \"let\",\n \"new\",\n \"of\",\n \"return\",\n \"set\",\n \"static\",\n \"super\",\n \"switch\",\n \"throw\",\n \"try\",\n \"typeof\",\n \"var\",\n \"void\",\n \"while\",\n \"with\",\n \"yield\"\n]);\n\nconst tsKeywords = new Set([\n ...jsKeywords,\n \"abstract\",\n \"declare\",\n \"enum\",\n \"implements\",\n \"interface\",\n \"keyof\",\n \"namespace\",\n \"private\",\n \"protected\",\n \"public\",\n \"readonly\",\n \"satisfies\",\n \"type\"\n]);\n\nconst tsTypes = new Set([\n \"any\",\n \"bigint\",\n \"boolean\",\n \"never\",\n \"number\",\n \"object\",\n \"string\",\n \"symbol\",\n \"unknown\",\n \"void\"\n]);\n\nconst jsConstants = new Set([\"true\", \"false\", \"null\", \"undefined\", \"NaN\", \"Infinity\"]);\n\nconst pythonKeywords = new Set([\n \"and\",\n \"as\",\n \"assert\",\n \"async\",\n \"await\",\n \"break\",\n \"case\",\n \"class\",\n \"continue\",\n \"def\",\n \"del\",\n \"elif\",\n \"else\",\n \"except\",\n \"finally\",\n \"for\",\n \"from\",\n \"global\",\n \"if\",\n \"import\",\n \"in\",\n \"is\",\n \"lambda\",\n \"match\",\n \"nonlocal\",\n \"not\",\n \"or\",\n \"pass\",\n \"raise\",\n \"return\",\n \"try\",\n \"while\",\n \"with\",\n \"yield\"\n]);\n\nconst pythonTypes = new Set([\"Any\", \"Callable\", \"Iterable\", \"None\", \"Protocol\", \"Self\", \"TypeVar\", \"bool\", \"bytes\", \"dict\", \"float\", \"int\", \"list\", \"object\", \"set\", \"str\", \"tuple\"]);\nconst pythonBooleans = new Set([\"True\", \"False\"]);\nconst pythonNulls = new Set([\"None\", \"NotImplemented\", \"Ellipsis\"]);\n\nconst shellKeywords = new Set([\"case\", \"do\", \"done\", \"elif\", \"else\", \"esac\", \"fi\", \"for\", \"function\", \"if\", \"in\", \"select\", \"then\", \"until\", \"while\"]);\nconst shellCommands = new Set([\"awk\", \"cat\", \"cd\", \"chmod\", \"cp\", \"echo\", \"env\", \"export\", \"find\", \"grep\", \"mkdir\", \"mv\", \"printf\", \"pwd\", \"rm\", \"sed\", \"test\"]);\n\nconst sqlKeywords = new Set([\n \"add\",\n \"alter\",\n \"and\",\n \"as\",\n \"by\",\n \"case\",\n \"create\",\n \"delete\",\n \"desc\",\n \"distinct\",\n \"drop\",\n \"else\",\n \"end\",\n \"exists\",\n \"from\",\n \"group\",\n \"having\",\n \"in\",\n \"insert\",\n \"into\",\n \"is\",\n \"join\",\n \"left\",\n \"limit\",\n \"not\",\n \"null\",\n \"on\",\n \"or\",\n \"order\",\n \"outer\",\n \"primary\",\n \"references\",\n \"right\",\n \"select\",\n \"set\",\n \"table\",\n \"then\",\n \"union\",\n \"update\",\n \"values\",\n \"when\",\n \"where\"\n]);\n\nconst rubyKeywords = new Set([\"alias\", \"and\", \"begin\", \"break\", \"case\", \"class\", \"def\", \"defined?\", \"do\", \"else\", \"elsif\", \"end\", \"ensure\", \"false\", \"for\", \"if\", \"in\", \"module\", \"next\", \"nil\", \"not\", \"or\", \"redo\", \"rescue\", \"retry\", \"return\", \"self\", \"super\", \"then\", \"true\", \"undef\", \"unless\", \"until\", \"when\", \"while\", \"yield\"]);\nconst rubyBooleans = new Set([\"true\", \"false\"]);\nconst rubyNulls = new Set([\"nil\"]);\n\nconst goKeywords = new Set([\"break\", \"case\", \"chan\", \"const\", \"continue\", \"default\", \"defer\", \"else\", \"fallthrough\", \"for\", \"func\", \"go\", \"goto\", \"if\", \"import\", \"interface\", \"map\", \"package\", \"range\", \"return\", \"select\", \"struct\", \"switch\", \"type\", \"var\"]);\nconst goTypes = new Set([\"any\", \"bool\", \"byte\", \"complex128\", \"complex64\", \"error\", \"float32\", \"float64\", \"int\", \"int16\", \"int32\", \"int64\", \"int8\", \"rune\", \"string\", \"uint\", \"uint16\", \"uint32\", \"uint64\", \"uint8\", \"uintptr\"]);\nconst goBooleans = new Set([\"true\", \"false\"]);\nconst goNulls = new Set([\"nil\"]);\n\nconst javaKeywords = new Set([\"abstract\", \"assert\", \"break\", \"case\", \"catch\", \"class\", \"const\", \"continue\", \"default\", \"do\", \"else\", \"enum\", \"extends\", \"final\", \"finally\", \"for\", \"if\", \"implements\", \"import\", \"instanceof\", \"interface\", \"native\", \"new\", \"package\", \"private\", \"protected\", \"public\", \"return\", \"static\", \"strictfp\", \"super\", \"switch\", \"synchronized\", \"this\", \"throw\", \"throws\", \"transient\", \"try\", \"volatile\", \"while\"]);\nconst javaTypes = new Set([\"Boolean\", \"Byte\", \"Character\", \"Double\", \"Float\", \"Integer\", \"Long\", \"Object\", \"Optional\", \"Short\", \"String\", \"Void\", \"boolean\", \"byte\", \"char\", \"double\", \"float\", \"int\", \"long\", \"short\", \"void\"]);\nconst javaBooleans = new Set([\"true\", \"false\"]);\nconst javaNulls = new Set([\"null\"]);\n\nconst kotlinKeywords = new Set([\"as\", \"break\", \"by\", \"catch\", \"class\", \"companion\", \"constructor\", \"continue\", \"data\", \"do\", \"else\", \"enum\", \"expect\", \"finally\", \"for\", \"fun\", \"if\", \"import\", \"in\", \"interface\", \"internal\", \"is\", \"object\", \"out\", \"override\", \"package\", \"private\", \"protected\", \"public\", \"return\", \"sealed\", \"suspend\", \"throw\", \"try\", \"typealias\", \"val\", \"var\", \"when\", \"where\", \"while\"]);\nconst kotlinTypes = new Set([\"Any\", \"Boolean\", \"Byte\", \"Char\", \"Double\", \"Float\", \"Int\", \"List\", \"Long\", \"Map\", \"Nothing\", \"Set\", \"Short\", \"String\", \"Unit\"]);\n\nconst swiftKeywords = new Set([\"actor\", \"as\", \"associatedtype\", \"async\", \"await\", \"break\", \"case\", \"catch\", \"class\", \"continue\", \"defer\", \"deinit\", \"do\", \"else\", \"enum\", \"extension\", \"fallthrough\", \"for\", \"func\", \"guard\", \"if\", \"import\", \"in\", \"init\", \"inout\", \"let\", \"nil\", \"operator\", \"private\", \"protocol\", \"public\", \"repeat\", \"return\", \"self\", \"Self\", \"static\", \"struct\", \"subscript\", \"super\", \"switch\", \"throw\", \"throws\", \"try\", \"typealias\", \"var\", \"where\", \"while\"]);\nconst swiftTypes = new Set([\"Any\", \"Array\", \"Bool\", \"Character\", \"Dictionary\", \"Double\", \"Float\", \"Int\", \"Optional\", \"Result\", \"Set\", \"String\", \"UInt\", \"Void\"]);\n\nconst dartKeywords = new Set([\"abstract\", \"as\", \"assert\", \"async\", \"await\", \"base\", \"break\", \"case\", \"catch\", \"class\", \"const\", \"continue\", \"covariant\", \"default\", \"deferred\", \"do\", \"else\", \"enum\", \"export\", \"extends\", \"extension\", \"external\", \"factory\", \"false\", \"final\", \"finally\", \"for\", \"function\", \"get\", \"hide\", \"if\", \"implements\", \"import\", \"in\", \"interface\", \"is\", \"late\", \"library\", \"mixin\", \"new\", \"null\", \"on\", \"operator\", \"part\", \"required\", \"return\", \"sealed\", \"set\", \"show\", \"static\", \"super\", \"switch\", \"sync\", \"this\", \"throw\", \"true\", \"try\", \"typedef\", \"var\", \"void\", \"when\", \"while\", \"with\", \"yield\"]);\nconst dartTypes = new Set([\"BigInt\", \"bool\", \"DateTime\", \"double\", \"Duration\", \"dynamic\", \"Future\", \"int\", \"Iterable\", \"List\", \"Map\", \"Never\", \"num\", \"Object\", \"Pattern\", \"Record\", \"Set\", \"Stream\", \"String\", \"Symbol\", \"Uri\", \"void\"]);\n\nconst scalaKeywords = new Set([\"abstract\", \"case\", \"catch\", \"class\", \"def\", \"do\", \"else\", \"enum\", \"export\", \"extends\", \"false\", \"final\", \"finally\", \"for\", \"forSome\", \"given\", \"if\", \"implicit\", \"import\", \"lazy\", \"macro\", \"match\", \"new\", \"null\", \"object\", \"override\", \"package\", \"private\", \"protected\", \"return\", \"sealed\", \"super\", \"then\", \"this\", \"throw\", \"trait\", \"true\", \"try\", \"type\", \"val\", \"var\", \"while\", \"with\", \"yield\"]);\nconst scalaTypes = new Set([\"Any\", \"Boolean\", \"Byte\", \"Char\", \"Double\", \"Either\", \"Float\", \"Int\", \"List\", \"Long\", \"Map\", \"None\", \"Option\", \"Seq\", \"Set\", \"Short\", \"Some\", \"String\", \"Unit\"]);\n\nconst groovyKeywords = new Set([\"abstract\", \"as\", \"assert\", \"break\", \"case\", \"catch\", \"class\", \"const\", \"continue\", \"def\", \"default\", \"do\", \"else\", \"enum\", \"extends\", \"false\", \"final\", \"finally\", \"for\", \"goto\", \"if\", \"implements\", \"import\", \"in\", \"instanceof\", \"interface\", \"new\", \"null\", \"package\", \"private\", \"protected\", \"public\", \"return\", \"static\", \"super\", \"switch\", \"this\", \"throw\", \"throws\", \"trait\", \"true\", \"try\", \"var\", \"void\", \"while\"]);\nconst groovyTypes = new Set([\"BigDecimal\", \"Boolean\", \"Closure\", \"Date\", \"Integer\", \"List\", \"Map\", \"Object\", \"String\", \"boolean\", \"def\", \"int\", \"long\", \"void\"]);\n\nconst cKeywords = new Set([\"auto\", \"break\", \"case\", \"const\", \"continue\", \"default\", \"do\", \"else\", \"enum\", \"extern\", \"for\", \"goto\", \"if\", \"inline\", \"register\", \"restrict\", \"return\", \"sizeof\", \"static\", \"struct\", \"switch\", \"typedef\", \"union\", \"volatile\", \"while\"]);\nconst cTypes = new Set([\"bool\", \"char\", \"double\", \"float\", \"int\", \"int16_t\", \"int32_t\", \"int64_t\", \"int8_t\", \"long\", \"short\", \"size_t\", \"uint16_t\", \"uint32_t\", \"uint64_t\", \"uint8_t\", \"void\"]);\n\nconst cppKeywords = new Set([...cKeywords, \"alignas\", \"alignof\", \"and\", \"bitand\", \"bitor\", \"catch\", \"class\", \"concept\", \"constexpr\", \"consteval\", \"constinit\", \"decltype\", \"delete\", \"explicit\", \"export\", \"friend\", \"mutable\", \"namespace\", \"new\", \"noexcept\", \"not\", \"operator\", \"or\", \"private\", \"protected\", \"public\", \"requires\", \"template\", \"this\", \"throw\", \"try\", \"typename\", \"using\", \"virtual\", \"xor\"]);\nconst cppTypes = new Set([...cTypes, \"auto\", \"bool\", \"char16_t\", \"char32_t\", \"std\", \"string\", \"wstring\"]);\nconst cppBooleans = new Set([\"true\", \"false\"]);\nconst cppNulls = new Set([\"nullptr\", \"NULL\"]);\n\nconst csharpKeywords = new Set([\"abstract\", \"as\", \"base\", \"break\", \"case\", \"catch\", \"checked\", \"class\", \"const\", \"continue\", \"default\", \"delegate\", \"do\", \"else\", \"enum\", \"event\", \"explicit\", \"extern\", \"finally\", \"fixed\", \"for\", \"foreach\", \"if\", \"implicit\", \"in\", \"interface\", \"internal\", \"is\", \"lock\", \"namespace\", \"new\", \"operator\", \"out\", \"override\", \"params\", \"private\", \"protected\", \"public\", \"readonly\", \"record\", \"ref\", \"return\", \"sealed\", \"sizeof\", \"stackalloc\", \"static\", \"struct\", \"switch\", \"this\", \"throw\", \"try\", \"typeof\", \"unchecked\", \"unsafe\", \"using\", \"virtual\", \"void\", \"volatile\", \"while\"]);\nconst csharpTypes = new Set([\"bool\", \"byte\", \"char\", \"decimal\", \"double\", \"dynamic\", \"float\", \"int\", \"long\", \"nint\", \"nuint\", \"object\", \"sbyte\", \"short\", \"string\", \"uint\", \"ulong\", \"ushort\", \"var\"]);\n\nconst objectiveCKeywords = new Set([...cKeywords, \"@autoreleasepool\", \"@catch\", \"@class\", \"@dynamic\", \"@end\", \"@finally\", \"@implementation\", \"@import\", \"@interface\", \"@optional\", \"@package\", \"@private\", \"@property\", \"@protected\", \"@protocol\", \"@public\", \"@selector\", \"@synthesize\", \"@throw\", \"@try\", \"YES\", \"NO\", \"nil\", \"self\", \"super\"]);\nconst objectiveCTypes = new Set([...cTypes, \"BOOL\", \"Class\", \"CGFloat\", \"NSInteger\", \"NSObject\", \"NSString\", \"NSUInteger\", \"SEL\", \"id\"]);\n\nconst rustKeywords = new Set([\"as\", \"async\", \"await\", \"box\", \"break\", \"const\", \"continue\", \"crate\", \"dyn\", \"else\", \"enum\", \"extern\", \"false\", \"fn\", \"for\", \"if\", \"impl\", \"in\", \"let\", \"loop\", \"match\", \"mod\", \"move\", \"mut\", \"pub\", \"ref\", \"return\", \"self\", \"Self\", \"static\", \"struct\", \"super\", \"trait\", \"true\", \"type\", \"unsafe\", \"use\", \"where\", \"while\"]);\nconst rustTypes = new Set([\"Box\", \"Option\", \"Result\", \"Some\", \"String\", \"Vec\", \"bool\", \"char\", \"f32\", \"f64\", \"i128\", \"i16\", \"i32\", \"i64\", \"i8\", \"isize\", \"str\", \"u128\", \"u16\", \"u32\", \"u64\", \"u8\", \"usize\"]);\nconst rustBooleans = new Set([\"true\", \"false\"]);\nconst rustNulls = new Set([\"None\"]);\n\nconst phpKeywords = new Set([\"abstract\", \"and\", \"array\", \"as\", \"break\", \"callable\", \"case\", \"catch\", \"class\", \"clone\", \"const\", \"continue\", \"declare\", \"default\", \"do\", \"echo\", \"else\", \"elseif\", \"empty\", \"enddeclare\", \"endfor\", \"endforeach\", \"endif\", \"endswitch\", \"endwhile\", \"enum\", \"extends\", \"final\", \"finally\", \"fn\", \"for\", \"foreach\", \"function\", \"global\", \"if\", \"implements\", \"include\", \"instanceof\", \"interface\", \"isset\", \"match\", \"namespace\", \"new\", \"or\", \"private\", \"protected\", \"public\", \"readonly\", \"require\", \"return\", \"static\", \"switch\", \"throw\", \"trait\", \"try\", \"use\", \"var\", \"while\", \"xor\", \"yield\"]);\nconst phpTypes = new Set([\"array\", \"bool\", \"callable\", \"false\", \"float\", \"int\", \"iterable\", \"mixed\", \"never\", \"null\", \"object\", \"self\", \"static\", \"string\", \"true\", \"void\"]);\n\nconst luaKeywords = new Set([\"and\", \"break\", \"do\", \"else\", \"elseif\", \"end\", \"false\", \"for\", \"function\", \"goto\", \"if\", \"in\", \"local\", \"nil\", \"not\", \"or\", \"repeat\", \"return\", \"then\", \"true\", \"until\", \"while\"]);\nconst perlKeywords = new Set([\"continue\", \"do\", \"else\", \"elsif\", \"for\", \"foreach\", \"given\", \"if\", \"last\", \"local\", \"my\", \"next\", \"our\", \"package\", \"redo\", \"require\", \"return\", \"state\", \"sub\", \"unless\", \"until\", \"use\", \"when\", \"while\"]);\nconst rKeywords = new Set([\"break\", \"else\", \"FALSE\", \"for\", \"function\", \"if\", \"Inf\", \"in\", \"NA\", \"NaN\", \"next\", \"NULL\", \"repeat\", \"return\", \"TRUE\", \"while\"]);\nconst powershellKeywords = new Set([\"begin\", \"break\", \"catch\", \"class\", \"continue\", \"data\", \"default\", \"do\", \"dynamicparam\", \"else\", \"elseif\", \"end\", \"enum\", \"exit\", \"filter\", \"finally\", \"for\", \"foreach\", \"from\", \"function\", \"if\", \"in\", \"param\", \"process\", \"return\", \"switch\", \"throw\", \"trap\", \"try\", \"until\", \"using\", \"var\", \"while\"]);\nconst elixirKeywords = new Set([\"after\", \"alias\", \"and\", \"case\", \"catch\", \"cond\", \"def\", \"defdelegate\", \"defexception\", \"defimpl\", \"defmacro\", \"defmodule\", \"defp\", \"defprotocol\", \"defstruct\", \"do\", \"else\", \"end\", \"false\", \"fn\", \"for\", \"if\", \"import\", \"in\", \"nil\", \"not\", \"or\", \"quote\", \"raise\", \"receive\", \"require\", \"rescue\", \"super\", \"throw\", \"true\", \"try\", \"unless\", \"unquote\", \"use\", \"when\", \"with\"]);\nconst erlangKeywords = new Set([\"after\", \"and\", \"andalso\", \"band\", \"begin\", \"bnot\", \"bor\", \"bsl\", \"bsr\", \"bxor\", \"case\", \"catch\", \"cond\", \"div\", \"end\", \"fun\", \"if\", \"let\", \"not\", \"of\", \"or\", \"orelse\", \"receive\", \"rem\", \"try\", \"when\", \"xor\"]);\nconst haskellKeywords = new Set([\"as\", \"case\", \"class\", \"data\", \"default\", \"deriving\", \"do\", \"else\", \"family\", \"forall\", \"foreign\", \"hiding\", \"if\", \"import\", \"in\", \"infix\", \"infixl\", \"infixr\", \"instance\", \"let\", \"module\", \"newtype\", \"of\", \"qualified\", \"then\", \"type\", \"where\"]);\nconst clojureKeywords = new Set([\"def\", \"defmacro\", \"defmethod\", \"defmulti\", \"defn\", \"defonce\", \"do\", \"doseq\", \"false\", \"fn\", \"for\", \"if\", \"let\", \"loop\", \"nil\", \"ns\", \"quote\", \"recur\", \"require\", \"true\", \"try\", \"when\"]);\nconst fsharpKeywords = new Set([\"abstract\", \"and\", \"as\", \"assert\", \"base\", \"begin\", \"class\", \"default\", \"delegate\", \"do\", \"done\", \"downcast\", \"downto\", \"elif\", \"else\", \"end\", \"exception\", \"extern\", \"false\", \"finally\", \"for\", \"fun\", \"function\", \"global\", \"if\", \"in\", \"inherit\", \"inline\", \"interface\", \"internal\", \"lazy\", \"let\", \"match\", \"member\", \"module\", \"mutable\", \"namespace\", \"new\", \"null\", \"of\", \"open\", \"or\", \"override\", \"private\", \"public\", \"rec\", \"return\", \"static\", \"struct\", \"then\", \"to\", \"true\", \"try\", \"type\", \"upcast\", \"use\", \"val\", \"void\", \"when\", \"while\", \"with\", \"yield\"]);\nconst vbKeywords = new Set([\"AddHandler\", \"And\", \"As\", \"Boolean\", \"ByRef\", \"Byte\", \"ByVal\", \"Call\", \"Case\", \"Catch\", \"Class\", \"Const\", \"Continue\", \"Date\", \"Decimal\", \"Dim\", \"Do\", \"Double\", \"Each\", \"Else\", \"ElseIf\", \"End\", \"Enum\", \"Erase\", \"Error\", \"Event\", \"Exit\", \"False\", \"Finally\", \"For\", \"Friend\", \"Function\", \"Get\", \"Global\", \"GoTo\", \"Handles\", \"If\", \"Implements\", \"Imports\", \"In\", \"Inherits\", \"Integer\", \"Interface\", \"Is\", \"Let\", \"Lib\", \"Like\", \"Long\", \"Loop\", \"Me\", \"Mod\", \"Module\", \"MustInherit\", \"MustOverride\", \"MyBase\", \"Namespace\", \"New\", \"Next\", \"Not\", \"Nothing\", \"Object\", \"Of\", \"On\", \"Option\", \"Or\", \"Overloads\", \"Overrides\", \"ParamArray\", \"Partial\", \"Private\", \"Property\", \"Protected\", \"Public\", \"RaiseEvent\", \"ReadOnly\", \"ReDim\", \"REM\", \"RemoveHandler\", \"Resume\", \"Return\", \"Select\", \"Set\", \"Shadows\", \"Shared\", \"Short\", \"Single\", \"Static\", \"Step\", \"Stop\", \"String\", \"Structure\", \"Sub\", \"SyncLock\", \"Then\", \"Throw\", \"To\", \"True\", \"Try\", \"Using\", \"Variant\", \"Wend\", \"When\", \"While\", \"With\", \"WithEvents\", \"WriteOnly\"]);\nconst graphqlKeywords = new Set([\"directive\", \"enum\", \"extend\", \"false\", \"fragment\", \"implements\", \"input\", \"interface\", \"mutation\", \"null\", \"on\", \"query\", \"repeatable\", \"scalar\", \"schema\", \"subscription\", \"true\", \"type\", \"union\"]);\nconst protobufKeywords = new Set([\"bool\", \"bytes\", \"double\", \"enum\", \"false\", \"fixed32\", \"fixed64\", \"float\", \"import\", \"int32\", \"int64\", \"map\", \"message\", \"oneof\", \"optional\", \"package\", \"proto2\", \"proto3\", \"public\", \"repeated\", \"reserved\", \"returns\", \"rpc\", \"service\", \"sfixed32\", \"sfixed64\", \"sint32\", \"sint64\", \"stream\", \"string\", \"syntax\", \"to\", \"true\", \"uint32\", \"uint64\"]);\nconst hclKeywords = new Set([\"and\", \"bool\", \"data\", \"dynamic\", \"false\", \"for\", \"if\", \"in\", \"locals\", \"module\", \"null\", \"number\", \"or\", \"output\", \"provider\", \"resource\", \"string\", \"terraform\", \"true\", \"variable\"]);\nconst nginxKeywords = new Set([\"access_log\", \"add_header\", \"deny\", \"error_log\", \"events\", \"fastcgi_pass\", \"gzip\", \"http\", \"include\", \"index\", \"listen\", \"location\", \"log_format\", \"proxy_pass\", \"return\", \"rewrite\", \"root\", \"server\", \"server_name\", \"try_files\", \"upstream\"]);\nconst makefileKeywords = new Set([\"define\", \"else\", \"endef\", \"endif\", \"export\", \"ifneq\", \"ifeq\", \"ifdef\", \"ifndef\", \"include\", \"override\", \"private\", \"sinclude\", \"undefine\", \"unexport\", \"vpath\"]);\nconst cmakeKeywords = new Set([\"add_compile_definitions\", \"add_custom_command\", \"add_custom_target\", \"add_executable\", \"add_library\", \"cmake_minimum_required\", \"else\", \"elseif\", \"endforeach\", \"endif\", \"endfunction\", \"endmacro\", \"find_package\", \"foreach\", \"function\", \"if\", \"include\", \"macro\", \"message\", \"option\", \"project\", \"return\", \"set\", \"target_compile_features\", \"target_include_directories\", \"target_link_libraries\"]);\n\nconst lexicalSpecs: Readonly<Record<string, LexicalSpec>> = {\n javascript: {\n keywords: jsKeywords,\n constants: jsConstants,\n booleans: new Set([\"true\", \"false\"]),\n nulls: new Set([\"null\"]),\n lineComments: [\"//\"],\n blockComments: cStyleBlockComments,\n stringQuotes: ['\"', \"'\"],\n templateQuotes: true,\n decorators: true\n },\n typescript: {\n keywords: tsKeywords,\n types: tsTypes,\n constants: jsConstants,\n booleans: new Set([\"true\", \"false\"]),\n nulls: new Set([\"null\"]),\n lineComments: [\"//\"],\n blockComments: cStyleBlockComments,\n stringQuotes: ['\"', \"'\"],\n templateQuotes: true,\n decorators: true\n },\n shell: {\n keywords: shellKeywords,\n commands: shellCommands,\n lineComments: [\"#\"],\n stringQuotes: ['\"', \"'\"],\n variablePrefix: \"$\",\n flags: true\n },\n python: {\n keywords: pythonKeywords,\n types: pythonTypes,\n booleans: pythonBooleans,\n nulls: pythonNulls,\n lineComments: [\"#\"],\n stringQuotes: ['\"', \"'\"],\n tripleStringQuotes: true,\n decorators: true\n },\n sql: {\n keywords: sqlKeywords,\n booleans: new Set([\"true\", \"false\"]),\n nulls: new Set([\"null\"]),\n lineComments: [\"--\"],\n blockComments: cStyleBlockComments,\n stringQuotes: ['\"', \"'\"],\n caseInsensitive: true\n },\n ruby: {\n keywords: rubyKeywords,\n booleans: rubyBooleans,\n nulls: rubyNulls,\n lineComments: [\"#\"],\n stringQuotes: ['\"', \"'\"]\n },\n go: {\n keywords: goKeywords,\n types: goTypes,\n booleans: goBooleans,\n nulls: goNulls,\n lineComments: [\"//\"],\n blockComments: cStyleBlockComments,\n stringQuotes: ['\"', \"'\", \"`\"]\n },\n java: {\n keywords: javaKeywords,\n types: javaTypes,\n booleans: javaBooleans,\n nulls: javaNulls,\n lineComments: [\"//\"],\n blockComments: cStyleBlockComments,\n stringQuotes: ['\"', \"'\"],\n decorators: true\n },\n kotlin: {\n keywords: kotlinKeywords,\n types: kotlinTypes,\n booleans: javaBooleans,\n nulls: javaNulls,\n lineComments: [\"//\"],\n blockComments: cStyleBlockComments,\n stringQuotes: ['\"', \"'\"],\n templateQuotes: true,\n decorators: true\n },\n swift: {\n keywords: swiftKeywords,\n types: swiftTypes,\n booleans: cppBooleans,\n nulls: new Set([\"nil\"]),\n lineComments: [\"//\"],\n blockComments: cStyleBlockComments,\n stringQuotes: ['\"', \"'\"],\n decorators: true\n },\n dart: {\n keywords: dartKeywords,\n types: dartTypes,\n booleans: javaBooleans,\n nulls: javaNulls,\n lineComments: [\"//\"],\n blockComments: cStyleBlockComments,\n stringQuotes: ['\"', \"'\"],\n decorators: true\n },\n scala: {\n keywords: scalaKeywords,\n types: scalaTypes,\n booleans: javaBooleans,\n nulls: javaNulls,\n lineComments: [\"//\"],\n blockComments: cStyleBlockComments,\n stringQuotes: ['\"', \"'\"],\n decorators: true\n },\n groovy: {\n keywords: groovyKeywords,\n types: groovyTypes,\n booleans: javaBooleans,\n nulls: javaNulls,\n lineComments: [\"//\"],\n blockComments: cStyleBlockComments,\n stringQuotes: ['\"', \"'\"],\n decorators: true\n },\n c: {\n keywords: cKeywords,\n types: cTypes,\n booleans: cppBooleans,\n nulls: cppNulls,\n lineComments: [\"//\"],\n blockComments: cStyleBlockComments,\n stringQuotes: ['\"', \"'\"]\n },\n cpp: {\n keywords: cppKeywords,\n types: cppTypes,\n booleans: cppBooleans,\n nulls: cppNulls,\n lineComments: [\"//\"],\n blockComments: cStyleBlockComments,\n stringQuotes: ['\"', \"'\"]\n },\n csharp: {\n keywords: csharpKeywords,\n types: csharpTypes,\n booleans: cppBooleans,\n nulls: javaNulls,\n lineComments: [\"//\"],\n blockComments: cStyleBlockComments,\n stringQuotes: ['\"', \"'\"],\n decorators: true\n },\n objectivec: {\n keywords: objectiveCKeywords,\n types: objectiveCTypes,\n booleans: new Set([\"YES\", \"NO\", \"true\", \"false\"]),\n nulls: new Set([\"nil\", \"NULL\", \"nullptr\"]),\n lineComments: [\"//\"],\n blockComments: cStyleBlockComments,\n stringQuotes: ['\"', \"'\"],\n decorators: true\n },\n rust: {\n keywords: rustKeywords,\n types: rustTypes,\n booleans: rustBooleans,\n nulls: rustNulls,\n lineComments: [\"//\"],\n blockComments: cStyleBlockComments,\n stringQuotes: ['\"', \"'\"],\n rustAttributes: true\n },\n php: {\n keywords: phpKeywords,\n types: phpTypes,\n booleans: new Set([\"true\", \"false\"]),\n nulls: new Set([\"null\"]),\n lineComments: [\"//\", \"#\"],\n blockComments: cStyleBlockComments,\n stringQuotes: ['\"', \"'\"],\n variablePrefix: \"$\"\n },\n lua: {\n keywords: luaKeywords,\n booleans: new Set([\"true\", \"false\"]),\n nulls: new Set([\"nil\"]),\n lineComments: [\"--\"],\n stringQuotes: ['\"', \"'\"]\n },\n perl: {\n keywords: perlKeywords,\n booleans: new Set([\"true\", \"false\"]),\n nulls: new Set([\"undef\"]),\n lineComments: [\"#\"],\n stringQuotes: ['\"', \"'\"],\n variablePrefix: \"$\"\n },\n r: {\n keywords: rKeywords,\n booleans: new Set([\"TRUE\", \"FALSE\", \"T\", \"F\"]),\n nulls: new Set([\"NULL\", \"NA\", \"NaN\"]),\n lineComments: [\"#\"],\n stringQuotes: ['\"', \"'\"]\n },\n powershell: {\n keywords: powershellKeywords,\n booleans: new Set([\"$true\", \"$false\", \"true\", \"false\"]),\n nulls: new Set([\"$null\", \"null\"]),\n commands: new Set([\"Get-ChildItem\", \"Get-Content\", \"Invoke-Run\", \"Join-Path\", \"New-Item\", \"Remove-Item\", \"Set-Content\", \"Test-Path\", \"Write-Host\", \"Write-Output\"]),\n lineComments: [\"#\"],\n blockComments: [{ start: \"<#\", end: \"#>\" }],\n stringQuotes: ['\"', \"'\"],\n variablePrefix: \"$\",\n flags: true\n },\n elixir: {\n keywords: elixirKeywords,\n booleans: new Set([\"true\", \"false\"]),\n nulls: new Set([\"nil\"]),\n lineComments: [\"#\"],\n stringQuotes: ['\"', \"'\"]\n },\n erlang: {\n keywords: erlangKeywords,\n booleans: new Set([\"true\", \"false\"]),\n lineComments: [\"%\"],\n stringQuotes: ['\"', \"'\"]\n },\n haskell: {\n keywords: haskellKeywords,\n types: new Set([\"Bool\", \"Char\", \"Double\", \"Either\", \"False\", \"Float\", \"IO\", \"Int\", \"Integer\", \"Maybe\", \"Nothing\", \"String\", \"True\"]),\n booleans: new Set([\"True\", \"False\"]),\n nulls: new Set([\"Nothing\"]),\n lineComments: [\"--\"],\n blockComments: [{ start: \"{-\", end: \"-}\" }],\n stringQuotes: ['\"', \"'\"]\n },\n clojure: {\n keywords: clojureKeywords,\n booleans: new Set([\"true\", \"false\"]),\n nulls: new Set([\"nil\"]),\n lineComments: [\";\"],\n stringQuotes: ['\"']\n },\n fsharp: {\n keywords: fsharpKeywords,\n types: new Set([\"Async\", \"bool\", \"decimal\", \"float\", \"int\", \"list\", \"Map\", \"option\", \"Result\", \"seq\", \"string\", \"unit\"]),\n booleans: new Set([\"true\", \"false\"]),\n nulls: new Set([\"null\", \"None\"]),\n lineComments: [\"//\"],\n blockComments: [{ start: \"(*\", end: \"*)\" }],\n stringQuotes: ['\"', \"'\"],\n decorators: true\n },\n vb: {\n keywords: vbKeywords,\n types: new Set([\"Boolean\", \"Byte\", \"Date\", \"Decimal\", \"Double\", \"Integer\", \"Long\", \"Object\", \"Short\", \"Single\", \"String\"]),\n booleans: new Set([\"True\", \"False\"]),\n nulls: new Set([\"Nothing\", \"Null\"]),\n lineComments: [\"'\"],\n stringQuotes: ['\"'],\n caseInsensitive: true\n },\n graphql: {\n keywords: graphqlKeywords,\n booleans: javaBooleans,\n nulls: javaNulls,\n lineComments: [\"#\"],\n stringQuotes: ['\"']\n },\n protobuf: {\n keywords: protobufKeywords,\n types: new Set([\"Any\", \"Duration\", \"Timestamp\"]),\n booleans: javaBooleans,\n nulls: javaNulls,\n lineComments: [\"//\"],\n blockComments: cStyleBlockComments,\n stringQuotes: ['\"', \"'\"]\n },\n hcl: {\n keywords: hclKeywords,\n booleans: javaBooleans,\n nulls: javaNulls,\n lineComments: [\"#\", \"//\"],\n blockComments: cStyleBlockComments,\n stringQuotes: ['\"', \"'\"]\n },\n nginx: {\n keywords: nginxKeywords,\n lineComments: [\"#\"],\n stringQuotes: ['\"', \"'\"]\n },\n makefile: {\n keywords: makefileKeywords,\n commands: shellCommands,\n lineComments: [\"#\"],\n stringQuotes: ['\"', \"'\"],\n variablePrefix: \"$\",\n flags: true\n },\n cmake: {\n keywords: cmakeKeywords,\n booleans: new Set([\"ON\", \"OFF\", \"TRUE\", \"FALSE\"]),\n nulls: new Set([\"NOTFOUND\"]),\n lineComments: [\"#\"],\n stringQuotes: ['\"', \"'\"],\n caseInsensitive: true\n }\n};\n\nconst tokenizers: Readonly<Record<CodeHighlightFamily, CodeTokenizer>> = {\n lexical: tokenizeLexical,\n data: tokenizeData,\n style: tokenizeStyle,\n line: tokenizeLine,\n markup: tokenizeMarkup\n};\n\nexport function highlightCodeBlock(\n node: Pick<Extract<MdNode, { type: \"code\" }>, \"lang\" | \"value\" | \"tokens\">\n): CodeToken[] | undefined {\n if (node.tokens !== undefined) {\n return node.tokens;\n }\n\n const language = resolveCodeLanguage(node.lang);\n if (\n language === undefined ||\n language.plain === true ||\n language.family === undefined ||\n node.value.length === 0\n ) {\n return undefined;\n }\n\n const tokenize = tokenizers[language.family];\n const tokens = tokenize(node.value, language);\n\n return tokens.some((token) => token.kind !== \"plain\") ? tokens : undefined;\n}\n\nfunction resolveCodeLanguage(lang: string | undefined): CodeLanguageInfo | undefined {\n if (lang === undefined || lang.length === 0) {\n return undefined;\n }\n\n return languageByAlias.get(lang.toLowerCase());\n}\n\nfunction tokenizeLexical(source: string, language: CodeLanguageInfo): CodeToken[] {\n const spec = lexicalSpecs[language.spec ?? \"\"];\n if (spec === undefined) {\n return [{ kind: \"plain\", value: source }];\n }\n\n const emitter = createEmitter(source);\n let index = 0;\n\n while (index < source.length) {\n const start = index;\n const char = source[index]!;\n\n index = readWhitespace(source, index);\n if (index > start) {\n emitter.pushPlain(start, index);\n continue;\n }\n\n const lineCommentEnd = readAnyLineComment(source, index, spec.lineComments ?? []);\n if (lineCommentEnd > index) {\n emitter.push(\"comment\", index, lineCommentEnd);\n index = lineCommentEnd;\n continue;\n }\n\n const blockCommentEnd = readAnyBlockComment(source, index, spec.blockComments ?? []);\n if (blockCommentEnd > index) {\n emitter.push(\"comment\", index, blockCommentEnd);\n index = blockCommentEnd;\n continue;\n }\n\n if (spec.rustAttributes === true && source.startsWith(\"#[\", index)) {\n index = readUntil(source, index + 2, \"]\");\n emitter.push(\"decorator\", start, index);\n continue;\n }\n\n if (spec.decorators === true && char === \"@\" && isIdentifierStart(source[index + 1] ?? \"\")) {\n index = readIdentifier(source, index + 1);\n emitter.push(\"decorator\", start, index);\n continue;\n }\n\n if (spec.variablePrefix === \"$\" && char === \"$\" && isIdentifierStart(source[index + 1] ?? \"\")) {\n index = readIdentifier(source, index + 1);\n const variableKind = classifyLexicalWord(source.slice(start, index), spec);\n emitter.push(variableKind === \"plain\" ? \"variable\" : variableKind, start, index);\n continue;\n }\n\n const commandEnd = readCommandIdentifier(source, index);\n if (commandEnd > index) {\n const commandKind = classifyLexicalWord(source.slice(start, commandEnd), spec);\n if (commandKind === \"command\") {\n emitter.push(\"command\", start, commandEnd);\n index = commandEnd;\n continue;\n }\n }\n\n if (spec.flags === true && char === \"-\" && isFlagStart(source[index + 1] ?? \"\")) {\n index = readFlag(source, index + 1);\n emitter.push(\"flag\", start, index);\n continue;\n }\n\n if (\n spec.tripleStringQuotes === true &&\n (char === '\"' || char === \"'\") &&\n source.startsWith(char.repeat(3), index)\n ) {\n index = readTripleQuotedString(source, index, char);\n emitter.push(\"string\", start, index);\n continue;\n }\n\n if ((spec.stringQuotes ?? []).includes(char)) {\n index = readQuotedString(source, index, char);\n emitter.push(\"string\", start, index);\n continue;\n }\n\n if (spec.templateQuotes === true && char === \"`\") {\n index = readQuotedString(source, index, \"`\");\n emitter.push(\"template\", start, index);\n continue;\n }\n\n index = readNumber(source, index);\n if (index > start) {\n emitter.push(\"number\", start, index);\n continue;\n }\n\n index = readIdentifier(source, index);\n if (index > start) {\n emitter.push(classifyLexicalWord(source.slice(start, index), spec), start, index);\n continue;\n }\n\n emitter.pushPlain(start, start + 1);\n index = start + 1;\n }\n\n return emitter.tokens;\n}\n\nfunction tokenizeData(source: string, language: CodeLanguageInfo): CodeToken[] {\n if (language.spec === \"toml\" || language.spec === \"ini\") {\n return tokenizeConfig(source);\n }\n\n return language.spec === \"yaml\" ? tokenizeYaml(source) : tokenizeJsonLike(source, language.spec === \"jsonc\");\n}\n\nfunction tokenizeJsonLike(source: string, allowComments: boolean): CodeToken[] {\n const emitter = createEmitter(source);\n let index = 0;\n\n while (index < source.length) {\n const start = index;\n\n index = readWhitespace(source, index);\n if (index > start) {\n emitter.pushPlain(start, index);\n continue;\n }\n\n if (allowComments) {\n const lineCommentEnd = readAnyLineComment(source, index, [\"//\"]);\n if (lineCommentEnd > index) {\n emitter.push(\"comment\", index, lineCommentEnd);\n index = lineCommentEnd;\n continue;\n }\n\n const blockCommentEnd = readAnyBlockComment(source, index, cStyleBlockComments);\n if (blockCommentEnd > index) {\n emitter.push(\"comment\", index, blockCommentEnd);\n index = blockCommentEnd;\n continue;\n }\n }\n\n if (source[index] === '\"') {\n index = readQuotedString(source, index, '\"');\n emitter.push(isJsonKey(source, index) ? \"key\" : \"string\", start, index);\n continue;\n }\n\n index = readNumber(source, index);\n if (index > start) {\n emitter.push(\"number\", start, index);\n continue;\n }\n\n index = readIdentifier(source, index);\n if (index > start) {\n emitter.push(classifyDataWord(source.slice(start, index)), start, index);\n continue;\n }\n\n emitter.pushPlain(start, start + 1);\n index = start + 1;\n }\n\n return emitter.tokens;\n}\n\nfunction tokenizeYaml(source: string): CodeToken[] {\n const emitter = createEmitter(source);\n let index = 0;\n let atLineStart = true;\n\n while (index < source.length) {\n const start = index;\n\n if (source[index] === \"\\n\") {\n emitter.pushPlain(index, index + 1);\n index += 1;\n atLineStart = true;\n continue;\n }\n\n const whitespaceEnd = readSpacesAndTabs(source, index);\n if (whitespaceEnd > index) {\n emitter.pushPlain(index, whitespaceEnd);\n index = whitespaceEnd;\n continue;\n }\n\n if (source[index] === \"#\") {\n index = readUntilLineEnd(source, index);\n emitter.push(\"comment\", start, index);\n atLineStart = false;\n continue;\n }\n\n if (source[index] === '\"' || source[index] === \"'\") {\n const quote = source[index]!;\n index = readQuotedString(source, index, quote);\n emitter.push(\"string\", start, index);\n atLineStart = false;\n continue;\n }\n\n if (atLineStart) {\n const keyEnd = readYamlKey(source, index);\n if (keyEnd > index) {\n emitter.push(\"key\", index, keyEnd);\n index = keyEnd;\n atLineStart = false;\n continue;\n }\n }\n\n index = readNumber(source, index);\n if (index > start) {\n emitter.push(\"number\", start, index);\n atLineStart = false;\n continue;\n }\n\n index = readIdentifier(source, index);\n if (index > start) {\n emitter.push(classifyDataWord(source.slice(start, index)), start, index);\n atLineStart = false;\n continue;\n }\n\n emitter.pushPlain(start, start + 1);\n index = start + 1;\n atLineStart = false;\n }\n\n return emitter.tokens;\n}\n\nfunction tokenizeStyle(source: string): CodeToken[] {\n const emitter = createEmitter(source);\n let index = 0;\n\n while (index < source.length) {\n const start = index;\n\n index = readWhitespace(source, index);\n if (index > start) {\n emitter.pushPlain(start, index);\n continue;\n }\n\n const blockCommentEnd = readAnyBlockComment(source, index, cStyleBlockComments);\n if (blockCommentEnd > index) {\n emitter.push(\"comment\", index, blockCommentEnd);\n index = blockCommentEnd;\n continue;\n }\n\n if (source[index] === \"@\") {\n index = readCssName(source, index + 1);\n if (index > start + 1) {\n emitter.push(\"at-rule\", start, index);\n continue;\n }\n }\n\n if (source[index] === \"#\" && isHex(source[index + 1] ?? \"\")) {\n index = readCssColor(source, index + 1);\n emitter.push(\"color\", start, index);\n continue;\n }\n\n if (source.startsWith(\"!important\", index)) {\n index += \"!important\".length;\n emitter.push(\"important\", start, index);\n continue;\n }\n\n if (source[index] === '\"' || source[index] === \"'\") {\n const quote = source[index]!;\n index = readQuotedString(source, index, quote);\n emitter.push(\"string\", start, index);\n continue;\n }\n\n index = readNumber(source, index);\n if (index > start) {\n emitter.push(\"number\", start, index);\n continue;\n }\n\n index = readCssName(source, index);\n if (index > start) {\n emitter.push(isCssProperty(source, index) ? \"property\" : \"selector\", start, index);\n continue;\n }\n\n emitter.pushPlain(start, start + 1);\n index = start + 1;\n }\n\n return emitter.tokens;\n}\n\nfunction tokenizeConfig(source: string): CodeToken[] {\n const emitter = createEmitter(source);\n let index = 0;\n let atLineStart = true;\n\n while (index < source.length) {\n const start = index;\n\n if (source[index] === \"\\n\") {\n emitter.pushPlain(index, index + 1);\n index += 1;\n atLineStart = true;\n continue;\n }\n\n index = readSpacesAndTabs(source, index);\n if (index > start) {\n emitter.pushPlain(start, index);\n continue;\n }\n\n if (source[index] === \"#\" || source[index] === \";\") {\n index = readUntilLineEnd(source, index);\n emitter.push(\"comment\", start, index);\n atLineStart = false;\n continue;\n }\n\n if (atLineStart && source[index] === \"[\") {\n index = readUntil(source, index + 1, \"]\");\n emitter.push(\"selector\", start, index);\n atLineStart = false;\n continue;\n }\n\n if (atLineStart) {\n const keyEnd = readConfigKey(source, index);\n if (keyEnd > index) {\n emitter.push(\"key\", index, keyEnd);\n index = keyEnd;\n atLineStart = false;\n continue;\n }\n }\n\n if (source[index] === '\"' || source[index] === \"'\") {\n const quote = source[index]!;\n index = readQuotedString(source, index, quote);\n emitter.push(\"string\", start, index);\n atLineStart = false;\n continue;\n }\n\n index = readNumber(source, index);\n if (index > start) {\n emitter.push(\"number\", start, index);\n atLineStart = false;\n continue;\n }\n\n index = readIdentifier(source, index);\n if (index > start) {\n emitter.push(classifyDataWord(source.slice(start, index)), start, index);\n atLineStart = false;\n continue;\n }\n\n emitter.pushPlain(start, start + 1);\n index = start + 1;\n atLineStart = false;\n }\n\n return emitter.tokens;\n}\n\nfunction tokenizeLine(source: string, language: CodeLanguageInfo): CodeToken[] {\n const emitter = createEmitter(source);\n let index = 0;\n let atLineStart = true;\n\n while (index < source.length) {\n const start = index;\n\n if (source[index] === \"\\n\") {\n emitter.pushPlain(index, index + 1);\n index += 1;\n atLineStart = true;\n continue;\n }\n\n if (atLineStart && language.spec === \"diff\" && (source[index] === \"+\" || source[index] === \"-\")) {\n index = readUntilLineEnd(source, index);\n emitter.push(source[start] === \"+\" ? \"string\" : \"important\", start, index);\n atLineStart = false;\n continue;\n }\n\n if (atLineStart && language.spec === \"markdown\" && source[index] === \"#\") {\n index = readUntilLineEnd(source, index);\n emitter.push(\"keyword\", start, index);\n atLineStart = false;\n continue;\n }\n\n if (atLineStart && language.spec === \"dockerfile\") {\n const directiveEnd = readIdentifier(source, index);\n if (directiveEnd > index) {\n emitter.push(\"directive\", index, directiveEnd);\n index = directiveEnd;\n atLineStart = false;\n continue;\n }\n }\n\n if (source[index] === \"#\" && language.spec !== \"diff\") {\n index = readUntilLineEnd(source, index);\n emitter.push(\"comment\", start, index);\n atLineStart = false;\n continue;\n }\n\n if (source[index] === '\"' || source[index] === \"'\") {\n const quote = source[index]!;\n index = readQuotedString(source, index, quote);\n emitter.push(\"string\", start, index);\n atLineStart = false;\n continue;\n }\n\n index = readNumber(source, index);\n if (index > start) {\n emitter.push(\"number\", start, index);\n atLineStart = false;\n continue;\n }\n\n emitter.pushPlain(start, start + 1);\n index = start + 1;\n atLineStart = false;\n }\n\n return emitter.tokens;\n}\n\nfunction tokenizeMarkup(source: string): CodeToken[] {\n const emitter = createEmitter(source);\n let index = 0;\n\n while (index < source.length) {\n const start = index;\n\n if (source.startsWith(\"<!--\", index)) {\n index = readUntil(source, index + 4, \"-->\");\n emitter.push(\"comment\", start, index);\n continue;\n }\n\n if (source[index] === \"<\") {\n emitter.push(\"punctuation\", index, index + 1);\n index += 1;\n if (source[index] === \"/\") {\n emitter.push(\"punctuation\", index, index + 1);\n index += 1;\n }\n\n const tagStart = index;\n index = readIdentifier(source, index);\n if (index > tagStart) {\n emitter.push(\"tag\", tagStart, index);\n }\n\n while (index < source.length && source[index] !== \">\") {\n const innerStart = index;\n index = readWhitespace(source, index);\n if (index > innerStart) {\n emitter.pushPlain(innerStart, index);\n continue;\n }\n\n if (source[index] === '\"' || source[index] === \"'\") {\n const quote = source[index]!;\n index = readQuotedString(source, index, quote);\n emitter.push(\"string\", innerStart, index);\n continue;\n }\n\n index = readIdentifier(source, index);\n if (index > innerStart) {\n emitter.push(\"attribute\", innerStart, index);\n continue;\n }\n\n emitter.push(\"punctuation\", innerStart, innerStart + 1);\n index = innerStart + 1;\n }\n\n if (source[index] === \">\") {\n emitter.push(\"punctuation\", index, index + 1);\n index += 1;\n }\n continue;\n }\n\n emitter.pushPlain(start, start + 1);\n index = start + 1;\n }\n\n return emitter.tokens;\n}\n\nfunction createEmitter(source: string): TokenEmitter & { tokens: CodeToken[] } {\n const tokens: CodeToken[] = [];\n\n return {\n tokens,\n push(kind, start, end) {\n pushToken(tokens, source, kind, start, end);\n },\n pushPlain(start, end) {\n pushToken(tokens, source, \"plain\", start, end);\n }\n };\n}\n\nfunction pushToken(\n tokens: CodeToken[],\n source: string,\n kind: CodeTokenKind,\n start: number,\n end: number\n): void {\n if (end <= start) {\n return;\n }\n\n const value = source.slice(start, end);\n const previous = tokens[tokens.length - 1];\n if (previous?.kind === kind) {\n previous.value += value;\n return;\n }\n\n tokens.push({ kind, value });\n}\n\nfunction classifyLexicalWord(word: string, spec: LexicalSpec): CodeTokenKind {\n const lookup = spec.caseInsensitive === true ? word.toLowerCase() : word;\n\n if (spec.booleans?.has(lookup) === true || spec.booleans?.has(word) === true) {\n return \"boolean\";\n }\n\n if (spec.nulls?.has(lookup) === true || spec.nulls?.has(word) === true) {\n return \"null\";\n }\n\n if (spec.keywords?.has(lookup) === true || spec.keywords?.has(word) === true) {\n return \"keyword\";\n }\n\n if (spec.types?.has(lookup) === true || spec.types?.has(word) === true) {\n return \"type\";\n }\n\n if (spec.commands?.has(lookup) === true || spec.commands?.has(word) === true) {\n return \"command\";\n }\n\n if (spec.constants?.has(lookup) === true || spec.constants?.has(word) === true) {\n return \"number\";\n }\n\n return \"plain\";\n}\n\nfunction classifyDataWord(word: string): CodeTokenKind {\n switch (word) {\n case \"true\":\n case \"false\":\n return \"boolean\";\n case \"null\":\n case \"Null\":\n case \"NULL\":\n case \"~\":\n return \"null\";\n default:\n return \"plain\";\n }\n}\n\nfunction readWhitespace(source: string, index: number): number {\n while (index < source.length && isWhitespace(source[index]!)) {\n index += 1;\n }\n\n return index;\n}\n\nfunction readSpacesAndTabs(source: string, index: number): number {\n while (index < source.length && (source[index] === \" \" || source[index] === \"\\t\")) {\n index += 1;\n }\n\n return index;\n}\n\nfunction readIdentifier(source: string, index: number): number {\n if (!isIdentifierStart(source[index] ?? \"\")) {\n return index;\n }\n\n index += 1;\n while (index < source.length && isIdentifierPart(source[index]!)) {\n index += 1;\n }\n\n return index;\n}\n\nfunction readCommandIdentifier(source: string, index: number): number {\n if (!isIdentifierStart(source[index] ?? \"\")) {\n return index;\n }\n\n index += 1;\n while (index < source.length && (isIdentifierPart(source[index]!) || source[index] === \"-\")) {\n index += 1;\n }\n\n return index;\n}\n\nfunction readCssName(source: string, index: number): number {\n if (!isCssNameStart(source[index] ?? \"\")) {\n return index;\n }\n\n index += 1;\n while (index < source.length && isCssNamePart(source[index]!)) {\n index += 1;\n }\n\n return index;\n}\n\nfunction readNumber(source: string, index: number): number {\n const start = index;\n if (source[index] === \"-\") {\n index += 1;\n }\n\n let hasDigit = false;\n while (index < source.length && isDigit(source[index]!)) {\n index += 1;\n hasDigit = true;\n }\n\n if (source[index] === \".\" && isDigit(source[index + 1] ?? \"\")) {\n index += 1;\n while (index < source.length && isDigit(source[index]!)) {\n index += 1;\n hasDigit = true;\n }\n }\n\n if (!hasDigit) {\n return start;\n }\n\n if ((source[index] === \"e\" || source[index] === \"E\") && isExponentStart(source[index + 1] ?? \"\")) {\n const exponentStart = index;\n index += 1;\n if (source[index] === \"+\" || source[index] === \"-\") {\n index += 1;\n }\n\n const digitsStart = index;\n while (index < source.length && isDigit(source[index]!)) {\n index += 1;\n }\n\n if (index === digitsStart) {\n return exponentStart;\n }\n }\n\n return index;\n}\n\nfunction readQuotedString(source: string, index: number, quote: string): number {\n index += 1;\n\n while (index < source.length) {\n const char = source[index]!;\n index += 1;\n\n if (char === \"\\\\\") {\n index = Math.min(source.length, index + 1);\n continue;\n }\n\n if (char === quote) {\n return index;\n }\n }\n\n return index;\n}\n\nfunction readTripleQuotedString(source: string, index: number, quote: string): number {\n const marker = quote.repeat(3);\n index += marker.length;\n\n while (index < source.length) {\n if (source.startsWith(marker, index)) {\n return index + marker.length;\n }\n\n if (source[index] === \"\\\\\") {\n index = Math.min(source.length, index + 2);\n continue;\n }\n\n index += 1;\n }\n\n return index;\n}\n\nfunction readAnyLineComment(\n source: string,\n index: number,\n markers: readonly string[]\n): number {\n for (const marker of markers) {\n if (source.startsWith(marker, index)) {\n return readUntilLineEnd(source, index);\n }\n }\n\n return index;\n}\n\nfunction readAnyBlockComment(\n source: string,\n index: number,\n delimiters: readonly BlockCommentDelimiter[]\n): number {\n for (const delimiter of delimiters) {\n if (source.startsWith(delimiter.start, index)) {\n return readDelimitedBlock(source, index + delimiter.start.length, delimiter.end);\n }\n }\n\n return index;\n}\n\nfunction readDelimitedBlock(source: string, index: number, endMarker: string): number {\n while (index < source.length) {\n if (source.startsWith(endMarker, index)) {\n return index + endMarker.length;\n }\n\n index += 1;\n }\n\n return source.length;\n}\n\nfunction readUntilLineEnd(source: string, index: number): number {\n while (index < source.length && source[index] !== \"\\n\") {\n index += 1;\n }\n\n return index;\n}\n\nfunction readUntil(source: string, index: number, marker: string): number {\n while (index < source.length) {\n if (source.startsWith(marker, index)) {\n return index + marker.length;\n }\n\n index += 1;\n }\n\n return index;\n}\n\nfunction readYamlKey(source: string, index: number): number {\n const start = index;\n while (index < source.length) {\n const char = source[index]!;\n if (char === \":\") {\n return index > start ? index : start;\n }\n\n if (char === \"\\n\" || char === \"#\" || char === \"{\" || char === \"}\" || char === \"[\" || char === \"]\") {\n return start;\n }\n\n index += 1;\n }\n\n return start;\n}\n\nfunction readConfigKey(source: string, index: number): number {\n const start = index;\n while (index < source.length) {\n const char = source[index]!;\n if (char === \"=\" || char === \":\") {\n return trimRightIndex(source, start, index);\n }\n\n if (char === \"\\n\" || char === \"#\" || char === \";\") {\n return start;\n }\n\n index += 1;\n }\n\n return start;\n}\n\nfunction readFlag(source: string, index: number): number {\n while (index < source.length && isFlagPart(source[index]!)) {\n index += 1;\n }\n\n return index;\n}\n\nfunction trimRightIndex(source: string, start: number, end: number): number {\n while (end > start && (source[end - 1] === \" \" || source[end - 1] === \"\\t\")) {\n end -= 1;\n }\n\n return end;\n}\n\nfunction readCssColor(source: string, index: number): number {\n let count = 0;\n\n while (index < source.length && isHex(source[index]!) && count < 8) {\n index += 1;\n count += 1;\n }\n\n return index;\n}\n\nfunction isJsonKey(source: string, index: number): boolean {\n index = readWhitespace(source, index);\n return source[index] === \":\";\n}\n\nfunction isCssProperty(source: string, index: number): boolean {\n index = readWhitespace(source, index);\n return source[index] === \":\";\n}\n\nfunction isWhitespace(char: string): boolean {\n return char === \" \" || char === \"\\n\" || char === \"\\r\" || char === \"\\t\";\n}\n\nfunction isIdentifierStart(char: string): boolean {\n return isAlpha(char) || char === \"_\" || char === \"$\";\n}\n\nfunction isIdentifierPart(char: string): boolean {\n return isIdentifierStart(char) || isDigit(char);\n}\n\nfunction isCssNameStart(char: string): boolean {\n return isAlpha(char) || char === \"_\" || char === \"-\" || char === \".\";\n}\n\nfunction isCssNamePart(char: string): boolean {\n return isCssNameStart(char) || isDigit(char);\n}\n\nfunction isFlagStart(char: string): boolean {\n return isAlpha(char) || char === \"-\";\n}\n\nfunction isFlagPart(char: string): boolean {\n return isAlpha(char) || isDigit(char) || char === \"-\";\n}\n\nfunction isExponentStart(char: string): boolean {\n return isDigit(char) || char === \"+\" || char === \"-\";\n}\n\nfunction isAlpha(char: string): boolean {\n const code = char.charCodeAt(0);\n return (code >= 65 && code <= 90) || (code >= 97 && code <= 122);\n}\n\nfunction isDigit(char: string): boolean {\n const code = char.charCodeAt(0);\n return code >= 48 && code <= 57;\n}\n\nfunction isHex(char: string): boolean {\n const code = char.charCodeAt(0);\n return (\n (code >= 48 && code <= 57) ||\n (code >= 65 && code <= 70) ||\n (code >= 97 && code <= 102)\n );\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 { 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", "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 on(event: \"data\", listener: (chunk: Buffer | string) => void): KeypressInput;\n off(event: \"data\", listener: (chunk: Buffer | string) => 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<(chunk: Buffer | string) => 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 = (chunk: Buffer | string) => {\n for (const event of parseKeypressChunk(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk))) {\n handler(event);\n }\n };\n\n keypressListeners.add(listener);\n stdin.on(\"data\", listener);\n\n return () => {\n if (!keypressListeners.delete(listener)) {\n return;\n }\n\n stdin.off(\"data\", listener);\n };\n }\n\n function destroy(): void {\n if (destroyed) {\n return;\n }\n\n for (const listener of keypressListeners) {\n stdin.off(\"data\", 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 if (data.length === 1 && data[0] === 0x1b) {\n return { name: \"escape\", ctrl: false, meta: false, shift: false };\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 parseKeypressChunk(data: Buffer): KeypressEvent[] {\n const events: KeypressEvent[] = [];\n const input = data.toString(\"utf8\");\n let index = 0;\n\n while (index < input.length) {\n const sequence = nextKeySequence(input, index);\n if (sequence.length === 0) {\n break;\n }\n\n const event = parseKeypress(Buffer.from(sequence));\n if (event !== undefined) {\n events.push(event);\n }\n index += sequence.length;\n }\n\n return events;\n}\n\nfunction nextKeySequence(input: string, index: number): string {\n const character = input[index];\n if (character === undefined) {\n return \"\";\n }\n\n if (character !== \"\\u001b\") {\n return character;\n }\n\n const next = input[index + 1];\n if (next === undefined) {\n return character;\n }\n\n if (next !== \"[\") {\n return input.slice(index, index + 2);\n }\n\n for (let cursor = index + 2; cursor < input.length; cursor += 1) {\n const code = input.charCodeAt(cursor);\n if ((code >= 0x40 && code <= 0x7e) || input[cursor] === \"~\") {\n return input.slice(index, cursor + 1);\n }\n }\n\n return input.slice(index);\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 {\n width: number;\n height: number;\n signal: AbortSignal;\n row: Row;\n /** Re-run detail.items for the focused row and repaint the preview pane. */\n reloadDetail?: () => void;\n}\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 /** Re-run detail.items for the focused row and repaint the preview pane. */\n reloadDetail: () => void;\n suspendAnd: <T>(fn: () => Promise<T>) => Promise<T>;\n openModal: (content: { title: string; content: string }) => void;\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 /** Synchronous first paint rows; still refreshed via `rows()` after start. */\n initialRows?: Row[];\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 | { kind: \"content\"; title: string; content: string; scroll: 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 const initialRows = config.initialRows ?? [];\n const initialFilter = config.initialFilter ?? \"\";\n // Defer filtering to first rowsLoaded when empty; seed list immediately when provided.\n return {\n title: config.title,\n emptyHint: config.emptyHint ?? \"No detail\",\n rows: initialRows,\n filtered: initialRows.map((_, index) => index),\n matchPositions: new Map(),\n cursor: 0,\n filter: initialFilter,\n filterFocused: false,\n focused: \"list\",\n detail: {\n rowId: initialRows[0]?.id ?? null,\n items: null,\n cursor: 0,\n scroll: 0,\n token: initialRows.length > 0 ? 1 : 0,\n loading: initialRows.length > 0\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 type { PromptStateName } from \"./core.js\";\n\nfunction supportsUnicode(): boolean {\n if (!process.platform.startsWith(\"win\")) {\n return process.env.TERM !== \"linux\";\n }\n\n return Boolean(\n process.env.CI ||\n process.env.WT_SESSION ||\n process.env.TERMINUS_SUBLIME ||\n process.env.ConEmuTask === \"{cmd::Cmder}\" ||\n process.env.TERM_PROGRAM === \"Terminus-Sublime\" ||\n process.env.TERM_PROGRAM === \"vscode\" ||\n process.env.TERM === \"xterm-256color\" ||\n process.env.TERM === \"alacritty\" ||\n process.env.TERMINAL_EMULATOR === \"JetBrains-JediTerm\"\n );\n}\n\nexport const UNICODE = supportsUnicode();\n\nfunction glyph(unicode: string, ascii: string): string {\n return UNICODE ? unicode : ascii;\n}\n\nexport const GLYPHS = {\n stepActive: glyph(\"\u25C6\", \"*\"),\n stepCancel: glyph(\"\u25A0\", \"x\"),\n stepError: glyph(\"\u25B2\", \"x\"),\n stepSubmit: glyph(\"\u25C7\", \"o\"),\n barStart: glyph(\"\u250C\", \"T\"),\n bar: glyph(\"\u2502\", \"|\"),\n barEnd: glyph(\"\u2514\", \"-\"),\n radioActive: glyph(\"\u25CF\", \">\"),\n radioInactive: glyph(\"\u25CB\", \" \"),\n checkboxActive: \"[ ]\",\n checkboxSelected: \"[x]\",\n checkboxInactive: \"[ ]\",\n passwordMask: glyph(\"\u2022\", \"*\"),\n ellipsis: \"...\"\n} as const;\n\nexport function symbol(state: PromptStateName): string {\n if (state === \"cancel\") return color.red(GLYPHS.stepCancel);\n if (state === \"error\") return color.yellow(GLYPHS.stepError);\n if (state === \"submit\") return color.green(GLYPHS.stepSubmit);\n return color.cyan(GLYPHS.stepActive);\n}\n\nexport function symbolBar(state: PromptStateName): string {\n if (state === \"cancel\") return color.red(GLYPHS.bar);\n if (state === \"error\") return color.yellow(GLYPHS.bar);\n if (state === \"submit\") return color.green(GLYPHS.bar);\n return color.cyan(GLYPHS.bar);\n}\n", "import { EventEmitter } from \"node:events\";\nimport * as readline from \"node:readline\";\nimport { CANCEL } from \"./cancel-symbol.js\";\nimport { mapKey, type Action } from \"./keys.js\";\nimport { wrapFrame } from \"./wrap.js\";\n\nconst cursor = {\n hide: \"\\x1b[?25l\",\n show: \"\\x1b[?25h\",\n move: (x: number, y: number) => {\n let output = \"\";\n if (x < 0) output += `\\x1b[${-x}D`;\n if (x > 0) output += `\\x1b[${x}C`;\n if (y < 0) output += `\\x1b[${-y}A`;\n if (y > 0) output += `\\x1b[${y}B`;\n return output;\n }\n};\n\nconst erase = {\n down: \"\\x1b[J\"\n};\n\nexport type PromptStateName = \"initial\" | \"active\" | \"submit\" | \"cancel\" | \"error\";\n\n/**\n * Builds the non-TTY rejection message, naming the documented `--yes` flag for the\n * command being run and keeping `POE_NO_PROMPT=1` as the secondary CI alternative.\n */\nexport function nonTtyPromptMessage(argv: string[] = process.argv): string {\n const tokens: string[] = [];\n for (const arg of argv.slice(2)) {\n if (arg.startsWith(\"-\")) break;\n tokens.push(arg);\n }\n const retry = [...tokens, \"--yes\"].join(\" \");\n return `Interactive prompt requires a TTY. Re-run with \\`${retry}\\` to accept defaults non-interactively, or set POE_NO_PROMPT=1 in CI.`;\n}\n\nexport interface PromptState<Value> {\n state: PromptStateName;\n value: Value | undefined;\n error: string;\n cursor: number;\n userInput: string;\n}\n\nexport interface PromptOptions<Value> {\n render: (state: Prompt<Value>) => string;\n initialValue?: Value;\n initialUserInput?: string;\n validate?: (value: Value | undefined) => string | Error | undefined;\n signal?: AbortSignal;\n input?: NodeJS.ReadableStream;\n output?: NodeJS.WritableStream;\n}\n\ntype InputStream = NodeJS.ReadableStream & {\n isTTY?: boolean;\n setRawMode?: (enabled: boolean) => void;\n unpipe?: () => void;\n};\n\ntype KeyMeta = {\n name?: string;\n ctrl?: boolean;\n};\n\nexport class Prompt<Value> extends EventEmitter {\n state: PromptStateName = \"initial\";\n value: Value | undefined;\n error = \"\";\n userInput = \"\";\n protected _cursor = 0;\n protected input: InputStream;\n protected output: NodeJS.WritableStream;\n private readonly renderFrame: (state: Prompt<Value>) => string;\n private readonly validate?: (value: Value | undefined) => string | Error | undefined;\n private readonly signal?: AbortSignal;\n private readonly trackValue: boolean;\n private previousFrame = \"\";\n private readlineInterface?: readline.Interface;\n private abortListener?: () => void;\n private closed = false;\n\n constructor(opts: PromptOptions<Value>, trackValue = true) {\n super();\n this.input = (opts.input ?? process.stdin) as InputStream;\n this.output = opts.output ?? process.stdout;\n this.renderFrame = opts.render;\n this.validate = opts.validate;\n this.signal = opts.signal;\n this.value = opts.initialValue;\n this.trackValue = trackValue;\n this.userInput = opts.initialUserInput ?? \"\";\n this._cursor = this.userInput.length;\n }\n\n get cursor(): number {\n return this._cursor;\n }\n\n prompt(): Promise<Value | typeof CANCEL> {\n if (this.signal?.aborted) {\n this.state = \"cancel\";\n return Promise.resolve(CANCEL);\n }\n\n if (this.input.isTTY !== true) {\n return this.promptNonTty();\n }\n\n return new Promise((resolve) => {\n const onSubmit = (value: Value | undefined) => resolve(value as Value);\n const onCancel = () => resolve(CANCEL);\n this.once(\"submit\", onSubmit);\n this.once(\"cancel\", onCancel);\n\n this.abortListener = () => {\n this.state = \"cancel\";\n this.emit(\"finalize\");\n this.render();\n this.close();\n };\n this.signal?.addEventListener(\"abort\", this.abortListener, { once: true });\n\n this.readlineInterface = readline.createInterface({\n input: this.input,\n output: undefined,\n tabSize: 2,\n prompt: \"\",\n escapeCodeTimeout: 50,\n terminal: true\n });\n readline.emitKeypressEvents(this.input, this.readlineInterface);\n this.readlineInterface.prompt();\n this.input.on(\"keypress\", this.onKeypress);\n if (this.input.setRawMode) {\n this.input.setRawMode(true);\n }\n this.output.on(\"resize\", this.render);\n this.render();\n });\n }\n\n protected promptNonTty(): Promise<Value | typeof CANCEL> {\n return Promise.reject(new Error(nonTtyPromptMessage()));\n }\n\n protected readNonTtyLine(): Promise<string> {\n return new Promise((resolve) => {\n const rl = readline.createInterface({ input: this.input, terminal: false });\n let settled = false;\n\n const settle = (value: string) => {\n if (settled) {\n return;\n }\n settled = true;\n rl.close();\n resolve(value);\n };\n\n rl.once(\"line\", settle);\n rl.once(\"close\", () => settle(rl.line));\n });\n }\n\n protected setValue(value: Value | undefined): void {\n this.value = value;\n this.emit(\"value\", value);\n }\n\n protected setError(message: string): void {\n this.error = message;\n }\n\n protected setUserInput(value: string): void {\n this.userInput = value;\n this._cursor = Math.min(this._cursor, this.userInput.length);\n this.emit(\"userInput\", this.userInput);\n }\n\n protected clearUserInput(): void {\n this.userInput = \"\";\n this._cursor = 0;\n this.emit(\"userInput\", this.userInput);\n }\n\n private readonly onKeypress = (char: string | undefined, key: KeyMeta = {}) => {\n let action = mapKey(key.name, char);\n if (this.trackValue && char && char >= \" \" && key.name !== \"return\" && key.name !== \"enter\" && key.name !== \"escape\") {\n action = undefined;\n }\n\n if (this.trackValue && action !== \"enter\") {\n this.updateTrackedInput(char, key, action);\n }\n\n if (this.state === \"error\") {\n this.state = \"active\";\n this.error = \"\";\n }\n\n if (!this.trackValue && action) {\n this.emit(\"cursor\", action);\n } else if (this.trackValue && action && action !== \"enter\") {\n this.emit(\"cursor\", action);\n }\n\n if (char && /^[yn]$/i.test(char)) {\n this.emit(\"confirm\", char.toLowerCase() === \"y\");\n }\n\n if (char) {\n this.emit(\"key\", char.toLowerCase(), key);\n }\n\n if (action === \"enter\") {\n const error = this.validate?.(this.value);\n if (error) {\n this.error = error instanceof Error ? error.message : error;\n this.state = \"error\";\n } else {\n this.state = \"submit\";\n }\n }\n\n if (action === \"cancel\") {\n this.state = \"cancel\";\n }\n\n if (this.state === \"submit\" || this.state === \"cancel\") {\n this.emit(\"finalize\");\n }\n\n this.render();\n\n if (this.state === \"submit\" || this.state === \"cancel\") {\n this.close();\n }\n };\n\n private updateTrackedInput(char: string | undefined, key: KeyMeta, action: Action | undefined): void {\n if (key.ctrl) {\n if (key.name === \"a\") {\n this._cursor = 0;\n return;\n }\n if (key.name === \"e\") {\n this._cursor = this.userInput.length;\n return;\n }\n if (key.name === \"u\") {\n this.userInput = this.userInput.slice(this._cursor);\n this._cursor = 0;\n this.emit(\"userInput\", this.userInput);\n return;\n }\n if (key.name === \"k\") {\n this.userInput = this.userInput.slice(0, this._cursor);\n this.emit(\"userInput\", this.userInput);\n return;\n }\n }\n\n if (action === \"left\") {\n this._cursor = Math.max(0, this._cursor - 1);\n return;\n }\n if (action === \"right\") {\n this._cursor = Math.min(this.userInput.length, this._cursor + 1);\n return;\n }\n if (action === \"cancel\" || action === \"up\" || action === \"down\" || action === \"space\") {\n return;\n }\n if (key.name === \"backspace\" || char === \"\\b\" || char === \"\\x7f\") {\n if (this._cursor > 0) {\n this.userInput = `${this.userInput.slice(0, this._cursor - 1)}${this.userInput.slice(this._cursor)}`;\n this._cursor -= 1;\n this.emit(\"userInput\", this.userInput);\n }\n return;\n }\n if (key.name === \"delete\") {\n if (this._cursor < this.userInput.length) {\n this.userInput = `${this.userInput.slice(0, this._cursor)}${this.userInput.slice(this._cursor + 1)}`;\n this.emit(\"userInput\", this.userInput);\n }\n return;\n }\n if (!char || char < \" \" || key.ctrl) {\n return;\n }\n\n this.userInput = `${this.userInput.slice(0, this._cursor)}${char}${this.userInput.slice(this._cursor)}`;\n this._cursor += char.length;\n this.emit(\"userInput\", this.userInput);\n }\n\n protected readonly render = () => {\n if (this.closed) {\n return;\n }\n\n const frame = wrapFrame(this.output, this.renderFrame(this) ?? \"\");\n if (frame === this.previousFrame) {\n return;\n }\n\n if (!this.previousFrame) {\n this.output.write(`${cursor.hide}${frame}`);\n this.previousFrame = frame;\n if (this.state === \"initial\") {\n this.state = \"active\";\n }\n return;\n }\n\n const previousLineCount = this.previousFrame.split(\"\\n\").length - 1;\n this.output.write(`${cursor.move(-999, -previousLineCount)}${erase.down}${frame}`);\n this.previousFrame = frame;\n };\n\n protected close(): void {\n if (this.closed) {\n return;\n }\n\n this.closed = true;\n this.input.removeListener(\"keypress\", this.onKeypress);\n this.output.removeListener(\"resize\", this.render);\n if (this.abortListener) {\n this.signal?.removeEventListener(\"abort\", this.abortListener);\n }\n this.output.write(`${cursor.show}\\n`);\n if (!process.platform.startsWith(\"win\") && this.input.setRawMode) {\n this.input.setRawMode(false);\n }\n this.readlineInterface?.close();\n this.input.unpipe?.();\n\n if (this.state === \"cancel\") {\n this.emit(\"cancel\");\n } else {\n this.emit(\"submit\", this.value);\n }\n this.removeAllListeners();\n }\n}\n", "import { wrapAnsi } from \"fast-wrap-ansi\";\nimport stringWidth from \"fast-string-width\";\n\ninterface StreamSize {\n columns?: number;\n rows?: number;\n}\n\nexport function getColumns(output: NodeJS.WritableStream): number {\n return Math.max(1, (output as StreamSize).columns ?? 80);\n}\n\nexport function getRows(output: NodeJS.WritableStream): number {\n return Math.max(1, (output as StreamSize).rows ?? 20);\n}\n\nexport function wrapTextWithPrefix(\n output: NodeJS.WritableStream,\n text: string,\n prefix: string,\n startPrefix = prefix\n): string {\n const width = Math.max(1, getColumns(output) - stringWidth(prefix));\n return wrapAnsi(text, width, { hard: true, trim: false })\n .split(\"\\n\")\n .map((line, index) => `${index === 0 ? startPrefix : prefix}${line}`)\n .join(\"\\n\");\n}\n\nexport function wrapFrame(output: NodeJS.WritableStream, frame: string): string {\n return wrapAnsi(frame, getColumns(output), { hard: true, trim: false });\n}\n", "import { color } from \"../../components/color.js\";\nimport { GLYPHS } from \"./glyphs.js\";\nimport { getColumns, getRows } from \"./wrap.js\";\nimport { wrapAnsi } from \"fast-wrap-ansi\";\n\nexport interface PaginationOptions<Option> {\n cursor: number;\n options: Option[];\n style: (option: Option, active: boolean) => string;\n output: NodeJS.WritableStream;\n maxItems?: number;\n columnPadding?: number;\n rowPadding?: number;\n}\n\nfunction countLines(values: string[]): number {\n return values.reduce((sum, value) => sum + value.split(\"\\n\").length, 0);\n}\n\nfunction trimToRows(values: string[], cursorOffset: number, rows: number, hasTop: boolean, hasBottom: boolean): string[] {\n const output = [...values];\n while (countLines(output) > rows && output.length > 1) {\n const removeFromTop = hasTop && cursorOffset > 0;\n const removeFromBottom = hasBottom && cursorOffset < output.length - 1;\n if (removeFromTop) {\n output.shift();\n cursorOffset -= 1;\n } else if (removeFromBottom) {\n output.pop();\n } else {\n output.pop();\n }\n }\n return output;\n}\n\nexport function limitOptions<Option>(opts: PaginationOptions<Option>): string[] {\n const {\n cursor,\n options,\n style,\n output,\n maxItems = Number.POSITIVE_INFINITY,\n columnPadding = 0,\n rowPadding = 4\n } = opts;\n\n if (options.length === 0) {\n return [];\n }\n\n const columns = Math.max(1, getColumns(output) - columnPadding);\n const rowBudget = Math.max(getRows(output) - rowPadding, 0);\n const visibleCount = Math.max(Math.min(maxItems, rowBudget), 5);\n const cappedVisibleCount = Math.min(visibleCount, options.length);\n let start = 0;\n\n if (cursor >= cappedVisibleCount - 3) {\n start = Math.max(Math.min(cursor - cappedVisibleCount + 3, options.length - cappedVisibleCount), 0);\n }\n\n const hasTopMarker = cappedVisibleCount < options.length && start > 0;\n const hasBottomMarker = cappedVisibleCount < options.length && start + cappedVisibleCount < options.length;\n const visible = options\n .slice(start, start + cappedVisibleCount)\n .map((option, index) => wrapAnsi(style(option, start + index === cursor), columns, { hard: true, trim: false }));\n const trimmed = trimToRows(\n visible,\n Math.max(cursor - start, 0),\n Math.max(rowBudget - Number(hasTopMarker) - Number(hasBottomMarker), 1),\n hasTopMarker,\n hasBottomMarker\n );\n\n if (hasTopMarker) {\n trimmed.unshift(color.dim(GLYPHS.ellipsis));\n }\n if (hasBottomMarker) {\n trimmed.push(color.dim(GLYPHS.ellipsis));\n }\n\n return trimmed;\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 `- ${renderMarkdownInline(options.message)}${options.timer ? ` [${renderMarkdownInline(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 { readFile, realpath } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { hasOwnErrorCode } from \"./error-codes.js\";\nimport { resolve as resolveConfigDocument } from \"./resolve.js\";\n\nexport interface PromptDocumentFileSystem {\n readFile(filePath: string, encoding: BufferEncoding): Promise<string>;\n realpath(filePath: string): Promise<string>;\n}\n\nexport interface PromptDocumentBaseDocument {\n filePath: string;\n content: string;\n}\n\nexport interface ResolvePromptDocumentInput {\n cwd: string;\n filePath: string;\n content?: string;\n optional?: boolean;\n basePaths?: readonly string[];\n baseDocuments?: readonly PromptDocumentBaseDocument[];\n variables?: Record<string, unknown>;\n validate?: boolean;\n fs?: PromptDocumentFileSystem;\n}\n\nexport interface ResolvedPromptDocument {\n template: string;\n prompt: string;\n metadata: Record<string, unknown>;\n sources: Record<string, string>;\n source: string;\n chain: string[];\n}\n\nconst nativeFs: PromptDocumentFileSystem = {\n readFile: (filePath, encoding) => readFile(filePath, encoding),\n realpath: (filePath) => realpath(filePath)\n};\n\nexport async function resolvePromptDocument(\n input: ResolvePromptDocumentInput\n): Promise<ResolvedPromptDocument> {\n const cwd = path.resolve(input.cwd);\n const filePath = path.resolve(cwd, input.filePath);\n assertInsideRoot(filePath, cwd, \"Prompt document path must remain inside cwd\");\n const baseDocuments = (input.baseDocuments ?? []).map((document) => ({\n filePath: requireAbsolutePath(document.filePath, \"Prompt document base document paths\"),\n content: document.content\n }));\n const basePaths = [\n ...(input.basePaths ?? []).map((basePath) =>\n requireAbsolutePath(basePath, \"Prompt document base paths\")\n ),\n ...baseDocuments.map(({ filePath: baseFilePath }) => path.dirname(baseFilePath))\n ];\n const fs = createRootedFileSystem(\n createDocumentFileSystem(input.fs ?? nativeFs, baseDocuments),\n [cwd, ...basePaths]\n );\n const content = input.content ?? (await readDocumentContent(fs, filePath, input.optional));\n const chain = [\n { source: \"document\", filePath, content },\n ...basePaths.map((basePath, index) => ({ source: `base-${index + 1}`, path: basePath }))\n ];\n const composed = await resolveConfigDocument(chain, { fs });\n const rendered = await resolveConfigDocument(chain, {\n fs,\n view: input.variables ?? {},\n validate: input.validate ?? true\n });\n const template = requirePrompt(getOwnEntry(composed.data, \"prompt\"), filePath);\n const prompt = requirePrompt(getOwnEntry(rendered.data, \"prompt\"), filePath);\n const { prompt: _ignored, ...metadata } = rendered.data;\n void _ignored;\n return {\n template,\n prompt,\n metadata,\n sources: rendered.sources,\n source: filePath,\n chain: rendered.chain\n };\n}\n\nfunction createDocumentFileSystem(\n fs: PromptDocumentFileSystem,\n documents: readonly PromptDocumentBaseDocument[]\n): PromptDocumentFileSystem {\n const contentByPath = new Map(\n documents.map(({ filePath, content }) => [path.resolve(filePath), content] as const)\n );\n return {\n readFile(filePath, encoding) {\n const content = contentByPath.get(path.resolve(filePath));\n return content === undefined ? fs.readFile(filePath, encoding) : Promise.resolve(content);\n },\n realpath(filePath) {\n const resolvedPath = path.resolve(filePath);\n return contentByPath.has(resolvedPath) ? Promise.resolve(resolvedPath) : fs.realpath(filePath);\n }\n };\n}\n\nasync function readDocumentContent(\n fs: PromptDocumentFileSystem,\n filePath: string,\n optional: boolean | undefined\n): Promise<string> {\n try {\n return await fs.readFile(filePath, \"utf8\");\n } catch (error) {\n if (optional && hasOwnErrorCode(error, \"ENOENT\")) {\n return \"---\\nextends: true\\n---\\n\";\n }\n throw error;\n }\n}\n\nfunction createRootedFileSystem(\n fs: PromptDocumentFileSystem,\n roots: readonly string[]\n): PromptDocumentFileSystem {\n return {\n async readFile(filePath, encoding) {\n await assertRealPathInsideOriginalRoot(fs, filePath, roots);\n return fs.readFile(filePath, encoding);\n },\n realpath: (filePath) => fs.realpath(filePath)\n };\n}\n\nasync function assertRealPathInsideOriginalRoot(\n fs: PromptDocumentFileSystem,\n filePath: string,\n roots: readonly string[]\n): Promise<void> {\n const resolvedPath = path.resolve(await fs.realpath(filePath));\n const originalRoot = roots.find((root) => isInsideRoot(filePath, root));\n if (!originalRoot) {\n throw new Error(`Prompt document path escapes configured root: ${filePath}`);\n }\n\n const resolvedRoot = await resolveRootPath(fs, originalRoot);\n if (!isInsideRoot(resolvedPath, resolvedRoot)) {\n throw new Error(`Prompt document path escapes configured root: ${filePath}`);\n }\n}\n\nasync function resolveRootPath(\n fs: PromptDocumentFileSystem,\n root: string\n): Promise<string> {\n try {\n return path.resolve(await fs.realpath(root));\n } catch {\n return path.resolve(root);\n }\n}\n\nfunction requireAbsolutePath(filePath: string, label: string): string {\n if (!path.isAbsolute(filePath)) {\n throw new Error(`${label} must be absolute: ${filePath}`);\n }\n return path.resolve(filePath);\n}\n\nfunction assertInsideRoot(filePath: string, root: string, message: string): void {\n if (!isInsideRoot(filePath, root)) {\n throw new Error(`${message}: ${filePath}`);\n }\n}\n\nfunction isInsideRoot(filePath: string, root: string): boolean {\n const relativePath = path.relative(path.resolve(root), path.resolve(filePath));\n return (\n relativePath === \"\" ||\n (relativePath !== \"..\" && !relativePath.startsWith(`..${path.sep}`) && !path.isAbsolute(relativePath))\n );\n}\n\nfunction requirePrompt(value: unknown, filePath: string): string {\n if (typeof value !== \"string\") {\n throw new Error(`Prompt document does not resolve to a Markdown prompt: ${filePath}`);\n }\n return value;\n}\n\nfunction getOwnEntry(record: Record<string, unknown>, key: string): unknown {\n return Object.prototype.hasOwnProperty.call(record, key) ? record[key] : undefined;\n}\n", "import { randomUUID } from \"node:crypto\";\nimport 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\";\nimport { hasOwnErrorCode } from \"../error-codes.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 await context.fs.unlink(backupPath).catch(() => undefined);\n throw error;\n }\n attempt += 1;\n }\n }\n}\n\nfunction isAlreadyExists(error: unknown): boolean {\n return hasOwnErrorCode(error, \"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 for (let attempt = 0; attempt < 10; attempt += 1) {\n const tempPath = `${targetPath}.mutation-tmp-${process.pid}-${randomUUID()}`;\n let tempCreated = false;\n try {\n await assertRegularWriteTarget(context, tempPath);\n await context.fs.writeFile(tempPath, content, { encoding: \"utf8\", flag: \"wx\" });\n tempCreated = true;\n await context.fs.rename(tempPath, targetPath);\n tempCreated = false;\n return;\n } catch (error) {\n const alreadyExists = isAlreadyExists(error);\n if (tempCreated || !alreadyExists) {\n try {\n await context.fs.unlink(tempPath);\n } catch (cleanupError) {\n if (!isNotFound(cleanupError)) {\n void cleanupError;\n }\n }\n }\n\n if (alreadyExists) {\n continue;\n }\n\n throw error;\n }\n }\n\n throw new Error(`Unable to create temporary mutation file for ${targetPath}.`);\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 mutationTargetPath(\n mutation: Mutation,\n options: MutationOptions\n): string | undefined {\n switch (mutation.kind) {\n case \"ensureDirectory\":\n case \"removeDirectory\":\n return resolveValue(mutation.path, options);\n case \"removeFile\":\n case \"chmod\":\n case \"backup\":\n case \"restoreBackup\":\n case \"configMerge\":\n case \"configPrune\":\n case \"configTransform\":\n case \"templateWrite\":\n case \"templateMergeToml\":\n case \"templateMergeJson\":\n return resolveValue(mutation.target, options);\n default:\n return undefined;\n }\n}\n\nexport function resolveMutationDetails(\n mutation: Mutation,\n context: MutationContext,\n options: MutationOptions\n): MutationDetails {\n try {\n const rawTarget = mutationTargetPath(mutation, options);\n if (rawTarget === undefined) {\n return {\n kind: mutation.kind,\n label: mutation.label ?? mutation.kind\n };\n }\n\n try {\n const targetPath = resolvePath(rawTarget, context.homeDir, context.pathMapper);\n return {\n kind: mutation.kind,\n label: mutation.label ?? describeMutation(mutation.kind, targetPath),\n targetPath\n };\n } catch {\n return {\n kind: mutation.kind,\n label: mutation.label ?? describeMutation(mutation.kind, rawTarget),\n targetPath: undefined\n };\n }\n } catch {\n return {\n kind: mutation.kind,\n label: mutation.label ?? mutation.kind\n };\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 await assertRegularWriteTarget(context, targetPath);\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 await assertRegularWriteTarget(context, targetPath);\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 await assertRegularWriteTarget(context, targetPath);\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 await context.fs.unlink(backupPath).catch(() => undefined);\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 if (!isConfigObject(value)) {\n throw new Error(`configMerge value must be an object for \"${rawPath}\".`);\n }\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 const serializedChanged = serialized !== rawContent;\n if (!serializedChanged) {\n return {\n outcome: { changed: false, effect: \"none\", detail: \"noop\" },\n details\n };\n }\n\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", "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 = hasConfigEntry(result, key) ? result[key] : undefined;\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 = hasConfigEntry(result, key) ? result[key] : undefined;\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 = hasConfigEntry(result, key) ? result[key] : undefined;\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 path from \"node:path\";\nimport { pathExists, type FileSystem } from \"@poe-code/config-mutations\";\nimport { hasOwnErrorCode } from \"./errors.js\";\nimport { assertConfigPathSafe } from \"./store.js\";\nimport type { ConfigDocument, ConfigFieldType, ScopeDefinition, ScopeSchema } from \"./types.js\";\n\nexport interface EnvOverrides {\n entries: string[];\n document: ConfigDocument;\n}\n\nexport interface EditTargetOptions {\n global?: boolean;\n project?: boolean;\n}\n\nexport function collectEnvOverrides(\n scopes: ReadonlyArray<ScopeDefinition<ScopeSchema>>,\n env: Record<string, string | undefined>\n): EnvOverrides {\n const document: ConfigDocument = {};\n const entries: string[] = [];\n\n for (const definition of scopes) {\n const scopeResult = collectScopeEnvOverrides(definition, env);\n if (Object.keys(scopeResult.values).length === 0) {\n continue;\n }\n\n defineDataProperty(document, definition.scope, scopeResult.values);\n entries.push(...scopeResult.entries);\n }\n\n return { entries, document };\n}\n\nexport async function resolveEditTarget(\n fs: FileSystem,\n configPath: string,\n projectConfigPath: string,\n options: EditTargetOptions\n): Promise<string> {\n if (options.global && options.project) {\n throw new Error(\"Choose either --global or --project, not both.\");\n }\n\n if (options.global) {\n return configPath;\n }\n if (options.project) {\n return projectConfigPath;\n }\n if (await pathExists(fs, projectConfigPath)) {\n return projectConfigPath;\n }\n return configPath;\n}\n\nexport async function initProjectConfig(\n fs: FileSystem,\n targetPath: string\n): Promise<\"created\" | \"already-exists\"> {\n await assertConfigPathSafe(fs, targetPath);\n if (await pathExists(fs, targetPath)) {\n return \"already-exists\";\n }\n\n await fs.mkdir(path.dirname(targetPath), { recursive: true });\n await assertConfigPathSafe(fs, targetPath);\n try {\n await fs.writeFile(targetPath, EMPTY_DOCUMENT, { encoding: \"utf8\", flag: \"wx\" });\n return \"created\";\n } catch (error) {\n if (isAlreadyExists(error)) {\n return \"already-exists\";\n }\n await fs.unlink(targetPath).catch(() => undefined);\n throw error;\n }\n}\n\nfunction isAlreadyExists(error: unknown): boolean {\n return hasOwnErrorCode(error, \"EEXIST\");\n}\n\nfunction collectScopeEnvOverrides<S extends ScopeSchema>(\n definition: ScopeDefinition<S>,\n env: Record<string, string | undefined>\n): {\n entries: string[];\n values: Record<string, unknown>;\n} {\n const entries: string[] = [];\n const values: Record<string, unknown> = {};\n\n for (const [key, field] of Object.entries(definition.schema) as Array<\n [keyof S & string, S[keyof S & string]]\n >) {\n if (!field.env) {\n continue;\n }\n\n const value = coerceEnvValue(field.type, env[field.env]);\n if (value === undefined) {\n continue;\n }\n\n defineDataProperty(values, key, value);\n entries.push(` ${field.env} = ${String(value)}`);\n }\n\n return { entries, values };\n}\n\nfunction defineDataProperty(object: Record<string, unknown>, key: string, value: unknown): void {\n Object.defineProperty(object, key, {\n configurable: true,\n enumerable: true,\n value,\n writable: true\n });\n}\n\nfunction coerceEnvValue(\n type: ConfigFieldType,\n raw: string | undefined\n): unknown {\n if (raw === undefined) {\n return undefined;\n }\n\n if (type === \"string\") {\n return raw;\n }\n if (type === \"number\") {\n if (raw.length === 0) {\n return undefined;\n }\n const parsed = Number(raw);\n return Number.isFinite(parsed) ? parsed : undefined;\n }\n if (type === \"json\") {\n try {\n return JSON.parse(raw);\n } catch {\n return undefined;\n }\n }\n if (raw === \"true\" || raw === \"1\") {\n return true;\n }\n if (raw === \"false\" || raw === \"0\") {\n return false;\n }\n return undefined;\n}\n\nconst EMPTY_DOCUMENT = `${JSON.stringify({}, null, 2)}\\n`;\n", "import { randomUUID } from \"node:crypto\";\nimport path from \"node:path\";\nimport { allAgents, resolveAgentId, type AgentDefinition } from \"@poe-code/agent-defs\";\nimport { createTimestamp, readFileIfExists, type FileSystem } from \"@poe-code/config-mutations\";\nimport {\n allAuthProviders,\n ProviderRegistry,\n resolveApiShape,\n type ApiShapeId\n} from \"@poe-code/providers\";\nimport { hasOwnErrorCode } from \"./errors.js\";\nimport { readDocument, readMergedDocument, readMergedDocumentReadonly, writeScope } from \"./store.js\";\n\nexport interface ConfigStoreOptions {\n fs: FileSystem;\n filePath: string;\n projectFilePath?: string;\n providerRegistry?: Pick<ProviderRegistry, \"get\">;\n warn?: (message: string) => void;\n readOnly?: boolean;\n}\n\nexport interface ConfiguredServiceMetadata {\n provider: string;\n apiShape?: ApiShapeId;\n files: string[];\n model?: string;\n reasoningEffort?: string;\n baseUrl?: string;\n shapeBaseUrl?: string[];\n}\n\ninterface LegacyConfigDocument {\n apiKey?: string;\n configured_services?: Record<string, ConfiguredServiceMetadata>;\n}\n\nexport interface SaveConfiguredServiceOptions extends ConfigStoreOptions {\n service: string;\n metadata: ConfiguredServiceMetadata;\n}\n\nexport interface UnconfigureServiceOptions extends ConfigStoreOptions {\n service: string;\n}\n\nexport async function loadConfiguredServices(\n options: ConfigStoreOptions\n): Promise<Record<string, ConfiguredServiceMetadata>> {\n const { fs, filePath, projectFilePath } = options;\n if (!options.readOnly) {\n await migrateLegacyCredentialsIfNeeded(fs, filePath);\n await migrateConfiguredServiceLayers(options, [\n filePath,\n ...(projectFilePath && projectFilePath !== filePath ? [projectFilePath] : [])\n ]);\n }\n\n const readConfig = options.readOnly ? readMergedDocumentReadonly : readMergedDocument;\n const document = await readConfig(fs, filePath, projectFilePath);\n return normalizeConfiguredServices(getOwnEntry(document, configuredServicesScope));\n}\n\nexport async function saveConfiguredService(options: SaveConfiguredServiceOptions): Promise<void> {\n const { fs, filePath, service, metadata } = options;\n await migrateLegacyCredentialsIfNeeded(fs, filePath);\n await migrateConfiguredServicesIfNeeded(options, filePath);\n\n const document = await readDocument(fs, filePath);\n const services = normalizeConfiguredServices(getOwnEntry(document, configuredServicesScope));\n const registry = options.providerRegistry ?? defaultProviderRegistry;\n defineDataProperty(services, service, normalizeConfiguredServiceMetadata({\n ...metadata,\n apiShape:\n metadata.apiShape ??\n deriveApiShape({\n service,\n provider: metadata.provider,\n registry,\n warn: options.warn ?? console.warn\n })\n }));\n\n await writeScope(fs, filePath, configuredServicesScope, services);\n}\n\nexport async function unconfigureService(options: UnconfigureServiceOptions): Promise<boolean> {\n const { fs, filePath, projectFilePath, service } = options;\n await migrateLegacyCredentialsIfNeeded(fs, filePath);\n const filePaths = [\n filePath,\n ...(projectFilePath && projectFilePath !== filePath ? [projectFilePath] : [])\n ];\n await migrateConfiguredServiceLayers(options, filePaths);\n\n const removals: ConfiguredServicesRemoval[] = [];\n for (const configPath of filePaths) {\n const document = await readDocument(fs, configPath);\n const original = normalizeConfiguredServices(getOwnEntry(document, configuredServicesScope));\n if (!Object.hasOwn(original, service)) {\n continue;\n }\n\n const updated = { ...original };\n delete updated[service];\n removals.push({ filePath: configPath, original, updated });\n }\n\n if (removals.length === 0) {\n return false;\n }\n\n const committed: ConfiguredServicesRemoval[] = [];\n try {\n for (const removal of removals) {\n await writeScope(fs, removal.filePath, configuredServicesScope, removal.updated);\n committed.push(removal);\n }\n } catch (error) {\n for (const removal of committed.reverse()) {\n await writeScope(fs, removal.filePath, configuredServicesScope, removal.original).catch(() => undefined);\n }\n throw error;\n }\n\n return true;\n}\n\nasync function migrateConfiguredServicesIfNeeded(\n options: ConfigStoreOptions,\n filePath: string\n): Promise<void> {\n const migration = await prepareConfiguredServicesMigration(options, filePath);\n if (migration) {\n await writeScope(options.fs, filePath, configuredServicesScope, migration.migrated);\n }\n}\n\nasync function migrateConfiguredServiceLayers(\n options: ConfigStoreOptions,\n filePaths: string[]\n): Promise<void> {\n const migrations = (await Promise.all(\n filePaths.map((filePath) => prepareConfiguredServicesMigration(options, filePath))\n )).filter((migration) => migration !== undefined);\n const committed: ConfiguredServicesMigration[] = [];\n\n try {\n for (const migration of migrations) {\n await writeScope(options.fs, migration.filePath, configuredServicesScope, migration.migrated);\n committed.push(migration);\n }\n } catch (error) {\n for (const migration of committed.reverse()) {\n await writeScope(options.fs, migration.filePath, configuredServicesScope, migration.original).catch(() => undefined);\n }\n throw error;\n }\n}\n\ninterface ConfiguredServicesMigration {\n filePath: string;\n migrated: Record<string, unknown>;\n original: Record<string, unknown>;\n}\n\ninterface ConfiguredServicesRemoval {\n filePath: string;\n original: Record<string, ConfiguredServiceMetadata>;\n updated: Record<string, ConfiguredServiceMetadata>;\n}\n\nasync function prepareConfiguredServicesMigration(\n options: ConfigStoreOptions,\n filePath: string\n): Promise<ConfiguredServicesMigration | undefined> {\n const document = await readDocument(options.fs, filePath);\n const rawServices = getOwnEntry(document, configuredServicesScope);\n if (!isRecord(rawServices)) {\n return undefined;\n }\n\n let needsMigration = false;\n const migrated: Record<string, unknown> = {};\n const registry = options.providerRegistry ?? defaultProviderRegistry;\n\n for (const [service, entry] of Object.entries(rawServices)) {\n if (!isRecord(entry)) {\n continue;\n }\n\n const providerValue = getOwnEntry(entry, \"provider\");\n const provider = typeof providerValue === \"string\" ? providerValue : \"poe\";\n const normalizedEntry: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(entry)) {\n defineDataProperty(normalizedEntry, key, value);\n }\n defineDataProperty(normalizedEntry, \"provider\", provider);\n\n if (typeof providerValue !== \"string\") {\n needsMigration = true;\n }\n\n const apiShapeValue = getOwnEntry(entry, \"apiShape\");\n if (!isApiShape(apiShapeValue)) {\n const apiShape = deriveApiShape({\n service,\n provider,\n registry,\n warn: options.warn ?? console.warn\n });\n if (apiShape) {\n defineDataProperty(normalizedEntry, \"apiShape\", apiShape);\n needsMigration = true;\n }\n }\n\n defineDataProperty(migrated, service, normalizedEntry);\n }\n\n if (needsMigration) {\n return {\n filePath,\n migrated,\n original: rawServices\n };\n }\n\n return undefined;\n}\n\nfunction deriveApiShape(input: {\n service: string;\n provider: string;\n registry: Pick<ProviderRegistry, \"get\">;\n warn: (message: string) => void;\n}): ApiShapeId | undefined {\n const provider = input.registry.get(input.provider);\n const agent = resolveConfiguredAgent(input.service);\n const apiShape = provider && agent ? resolveApiShape(provider, agent) : undefined;\n if (!apiShape) {\n input.warn(\n `Unable to derive apiShape for configured service \"${input.service}\" with provider \"${input.provider}\".`\n );\n }\n return apiShape;\n}\n\nfunction resolveConfiguredAgent(service: string): AgentDefinition | undefined {\n const agentId = resolveAgentId(service);\n return agentId ? agentsById.get(agentId) : undefined;\n}\n\nfunction normalizeConfiguredServices(value: unknown): Record<string, ConfiguredServiceMetadata> {\n if (!isRecord(value)) {\n return {};\n }\n\n const entries: Record<string, ConfiguredServiceMetadata> = {};\n for (const [key, entry] of Object.entries(value)) {\n if (!isRecord(entry)) {\n continue;\n }\n\n const providerValue = getOwnEntry(entry, \"provider\");\n const apiShapeValue = getOwnEntry(entry, \"apiShape\");\n const filesValue = getOwnEntry(entry, \"files\");\n const modelValue = getOwnEntry(entry, \"model\");\n const reasoningEffortValue = getOwnEntry(entry, \"reasoningEffort\");\n const baseUrlValue = getOwnEntry(entry, \"baseUrl\");\n const shapeBaseUrlValue = getOwnEntry(entry, \"shapeBaseUrl\");\n\n defineDataProperty(entries, key, normalizeConfiguredServiceMetadata({\n provider: typeof providerValue === \"string\" ? providerValue : \"poe\",\n apiShape: isApiShape(apiShapeValue) ? apiShapeValue : undefined,\n files: Array.isArray(filesValue) ? filesValue : [],\n model: typeof modelValue === \"string\" ? modelValue : undefined,\n reasoningEffort: typeof reasoningEffortValue === \"string\" ? reasoningEffortValue : undefined,\n baseUrl: typeof baseUrlValue === \"string\" ? baseUrlValue : undefined,\n shapeBaseUrl: Array.isArray(shapeBaseUrlValue) ? shapeBaseUrlValue : undefined\n }));\n }\n\n return entries;\n}\n\nfunction normalizeConfiguredServiceMetadata(\n metadata: ConfiguredServiceMetadata\n): ConfiguredServiceMetadata {\n const seen = new Set<string>();\n const files: string[] = [];\n\n for (const entry of metadata.files ?? []) {\n if (typeof entry !== \"string\" || entry.length === 0) {\n continue;\n }\n if (!seen.has(entry)) {\n files.push(entry);\n seen.add(entry);\n }\n }\n\n return omitUndefined({\n provider: metadata.provider,\n apiShape: metadata.apiShape,\n files,\n model: normalizeOptionalText(metadata.model),\n reasoningEffort: normalizeOptionalText(metadata.reasoningEffort),\n baseUrl: normalizeOptionalText(metadata.baseUrl),\n shapeBaseUrl: normalizeOptionalTextList(metadata.shapeBaseUrl)\n });\n}\n\nfunction normalizeOptionalText(value: string | undefined): string | undefined {\n const normalized = value?.trim();\n return normalized && normalized.length > 0 ? normalized : undefined;\n}\n\nfunction normalizeOptionalTextList(value: string[] | undefined): string[] | undefined {\n if (!value) {\n return undefined;\n }\n const normalized = value.map((entry) => entry.trim()).filter((entry) => entry.length > 0);\n return normalized.length > 0 ? normalized : undefined;\n}\n\nasync function migrateLegacyCredentialsIfNeeded(fs: FileSystem, filePath: string): Promise<void> {\n const currentRaw = await readFileIfExists(fs, filePath);\n if (currentRaw !== null) {\n return;\n }\n\n await migrateLegacyCredentialsFile(fs, filePath);\n}\n\nasync function migrateLegacyCredentialsFile(fs: FileSystem, configPath: string): Promise<void> {\n const legacyPath = path.join(path.dirname(configPath), \"credentials.json\");\n const raw = await readFileIfExists(fs, legacyPath);\n if (raw === null) {\n return;\n }\n\n let legacyDocument: LegacyConfigDocument;\n try {\n legacyDocument = normalizeLegacyConfigDocument(JSON.parse(raw));\n } catch (error) {\n if (error instanceof SyntaxError) {\n await recoverInvalidConfig(fs, legacyPath, raw);\n await fs.unlink(legacyPath);\n return;\n }\n throw error;\n }\n\n const configuredServices = getOwnEntry(legacyDocument, \"configured_services\");\n if (isRecord(configuredServices)) {\n await writeScope(fs, configPath, configuredServicesScope, configuredServices);\n }\n\n const apiKey = getOwnEntry(legacyDocument, \"apiKey\");\n if (typeof apiKey === \"string\" && apiKey.length > 0) {\n await writeScope(fs, configPath, CORE_SCOPE, {\n apiKey\n });\n }\n\n await fs.unlink(legacyPath);\n}\n\nfunction normalizeLegacyConfigDocument(value: unknown): LegacyConfigDocument {\n if (!isRecord(value)) {\n return {};\n }\n\n const document = Object.create(null) as LegacyConfigDocument;\n const apiKey = getOwnEntry(value, \"apiKey\");\n if (typeof apiKey === \"string\" && apiKey.length > 0) {\n document.apiKey = apiKey;\n }\n\n const services = normalizeConfiguredServices(getOwnEntry(value, \"configured_services\"));\n if (Object.keys(services).length > 0) {\n document.configured_services = services;\n }\n\n return document;\n}\n\nasync function recoverInvalidConfig(\n fs: FileSystem,\n filePath: string,\n content: string\n): Promise<void> {\n await writeInvalidBackup(fs, filePath, content);\n await writeFileAtomically(fs, filePath, EMPTY_DOCUMENT);\n}\n\nfunction createInvalidBackupPath(filePath: string): string {\n const directory = path.dirname(filePath);\n const baseName = path.basename(filePath);\n return path.join(directory, `${baseName}.invalid-${createTimestamp()}.json`);\n}\n\nasync function writeInvalidBackup(fs: FileSystem, filePath: string, content: string): Promise<void> {\n const backupPath = createInvalidBackupPath(filePath);\n const backupStem = backupPath.slice(0, -\".json\".length);\n\n for (let suffix = 0; ; suffix += 1) {\n const candidate = suffix === 0 ? backupPath : `${backupStem}-${suffix}.json`;\n\n try {\n await fs.writeFile(candidate, content, { encoding: \"utf8\", flag: \"wx\" });\n return;\n } catch (error) {\n if (!isAlreadyExists(error)) {\n await fs.unlink(candidate).catch(() => undefined);\n throw error;\n }\n }\n }\n}\n\nasync function writeFileAtomically(fs: FileSystem, filePath: string, content: string): Promise<void> {\n const tempPath = `${filePath}.${process.pid}.${randomUUID()}.tmp`;\n let tempCreated = false;\n\n try {\n await fs.writeFile(tempPath, content, { encoding: \"utf8\", flag: \"wx\" });\n tempCreated = true;\n await fs.rename(tempPath, filePath);\n } catch (error) {\n if (tempCreated || !isAlreadyExists(error)) {\n await fs.unlink(tempPath).catch(() => undefined);\n }\n throw error;\n }\n}\n\nfunction isAlreadyExists(error: unknown): boolean {\n return hasOwnErrorCode(error, \"EEXIST\");\n}\n\nfunction omitUndefined<T extends Record<string, unknown>>(value: T): T {\n return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined)) as T;\n}\n\nfunction isApiShape(value: unknown): value is ApiShapeId {\n return (\n value === \"openai-chat-completions\" ||\n value === \"openai-responses\" ||\n value === \"anthropic-messages\" ||\n value === \"google-generations\"\n );\n}\n\nfunction getOwnEntry(record: object, key: string): unknown {\n return Object.prototype.hasOwnProperty.call(record, key)\n ? (record as Record<string, unknown>)[key]\n : undefined;\n}\n\nfunction defineDataProperty(object: Record<string, unknown>, key: string, value: unknown): void {\n Object.defineProperty(object, key, {\n configurable: true,\n enumerable: true,\n value,\n writable: true\n });\n}\n\nfunction isRecord(value: unknown): value is Record<string, any> {\n return Boolean(value && typeof value === \"object\" && !Array.isArray(value));\n}\n\nconst agentsById = new Map(allAgents.map((agent) => [agent.id, agent]));\nconst defaultProviderRegistry = new ProviderRegistry(allAuthProviders);\nconst CORE_SCOPE = \"core\";\nconst configuredServicesScope = \"configured_services\";\nconst EMPTY_DOCUMENT = `${JSON.stringify({}, null, 2)}\\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: \"Anthropic's agentic coding tool for the terminal.\",\n aliases: [\"claude\"],\n binaryName: \"claude\",\n apiShapes: [\"anthropic-messages\"],\n otelCapture: {\n env: {\n CLAUDE_CODE_ENABLE_TELEMETRY: \"1\"\n }\n },\n configPath: \"~/.claude.json\",\n capabilities: [\"spawn\", \"configure\", \"install\", \"test\", \"skill\", \"mcp\"],\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: \"~/.config/Claude/claude_desktop_config.json\",\n configPaths: {\n darwin: \"~/Library/Application Support/Claude/claude_desktop_config.json\",\n linux: \"~/.config/Claude/claude_desktop_config.json\",\n win32: \"~/AppData/Roaming/Claude/claude_desktop_config.json\"\n },\n capabilities: [\"mcp\"],\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: \"OpenAI's coding agent for the terminal.\",\n binaryName: \"codex\",\n apiShapes: [\"openai-responses\"],\n otelCapture: {\n args: (endpoint, content) => [\n \"-c\",\n `otel.trace_exporter={\"otlp-http\"={endpoint=${JSON.stringify(`${endpoint}/v1/traces`)},protocol=\"json\"}}`,\n \"-c\",\n `otel.exporter={\"otlp-http\"={endpoint=${JSON.stringify(`${endpoint}/v1/logs`)},protocol=\"json\"}}`,\n \"-c\",\n `otel.log_user_prompt=${content}`\n ]\n },\n configPath: \"~/.codex/config.toml\",\n capabilities: [\"spawn\", \"configure\", \"install\", \"test\", \"skill\", \"mcp\"],\n branding: {\n colors: {\n dark: \"#D5D9DF\",\n light: \"#7A7F86\"\n }\n }\n};\n", "import type { AgentDefinition } from \"../types.js\";\n\nexport const cursorAgent: AgentDefinition = {\n id: \"cursor\",\n name: \"cursor\",\n aliases: [\"cursor-agent\"],\n label: \"Cursor\",\n summary: \"Cursor's CLI coding agent.\",\n binaryName: \"cursor-agent\",\n configPath: \"~/.cursor/mcp.json\",\n capabilities: [\"spawn\", \"configure\", \"install\", \"test\", \"skill\", \"mcp\"],\n branding: {\n colors: {\n dark: \"#FFFFFF\",\n light: \"#000000\"\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: \"Google's open-source AI agent for the terminal.\",\n binaryName: \"gemini\",\n configPath: \"~/.gemini/settings.json\",\n apiShapes: [\"google-generations\"],\n capabilities: [\"spawn\", \"configure\", \"install\", \"test\", \"skill\"],\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: \"Open-source AI coding agent for the terminal.\",\n binaryName: \"opencode\",\n apiShapes: [\"openai-chat-completions\"],\n otelCapture: {\n env: {\n OPENCODE_CONFIG_CONTENT: '{\"experimental\":{\"openTelemetry\":true}}'\n }\n },\n configPath: \"~/.config/opencode/opencode.json\",\n capabilities: [\"spawn\", \"configure\", \"install\", \"test\", \"skill\", \"mcp\"],\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: \"Moonshot AI's coding agent for the terminal.\",\n aliases: [\"kimi-cli\"],\n binaryName: \"kimi\",\n apiShapes: [\"openai-chat-completions\"],\n configPath: \"~/.kimi/mcp.json\",\n capabilities: [\"spawn\", \"configure\", \"install\", \"test\", \"mcp\"],\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 otelCapture: {},\n configPath: \"~/.config/goose/config.yaml\",\n capabilities: [\"spawn\", \"configure\", \"install\", \"test\", \"skill\", \"mcp\"],\n branding: {\n colors: {\n dark: \"#FF6B35\",\n light: \"#E85D26\"\n }\n }\n};\n", "import type { AgentDefinition } from \"../types.js\";\n\nexport const piAgent: AgentDefinition = {\n id: \"pi\",\n name: \"pi\",\n aliases: [\"pi-agent\"],\n label: \"Pi\",\n summary: \"Minimal AI coding agent for the terminal.\",\n binaryName: \"pi\",\n capabilities: [\"spawn\"],\n branding: {\n colors: {\n dark: \"#F2F2F2\",\n light: \"#242424\"\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 capabilities: [\"configure\"],\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 cursorAgent,\n geminiCliAgent,\n openCodeAgent,\n kimiAgent,\n gooseAgent,\n piAgent,\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 if (agent.capabilities !== undefined) {\n Object.freeze(agent.capabilities);\n }\n if (agent.otelCapture?.env !== undefined) {\n Object.freeze(agent.otelCapture.env);\n }\n if (agent.otelCapture !== undefined) {\n Object.freeze(agent.otelCapture);\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(cursorAgent),\n freezeAgent(geminiCliAgent),\n freezeAgent(openCodeAgent),\n freezeAgent(kimiAgent),\n freezeAgent(gooseAgent),\n freezeAgent(piAgent),\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 type { ApiKeyAuth, AuthProvider } from \"../types.js\";\nimport type { AuthStrategy, AuthStrategyContext } from \"./types.js\";\n\nexport interface ApiKeyLoginOptions {\n apiKey?: string;\n}\n\nfunction requireApiKeyAuth(provider: AuthProvider): ApiKeyAuth {\n if (provider.auth.kind !== \"api-key\") {\n throw new Error(\n `Provider ${provider.id} does not use api-key auth (got ${provider.auth.kind}).`\n );\n }\n return provider.auth;\n}\n\nasync function acquireApiKey(\n provider: AuthProvider,\n options: ApiKeyLoginOptions,\n context: AuthStrategyContext\n): Promise<string> {\n const auth = requireApiKeyAuth(provider);\n const candidate =\n options.apiKey ?? (await context.promptForSecret?.(auth.prompt));\n const trimmed = candidate?.trim();\n if (!trimmed) {\n throw new Error(\n `No API key available for provider \"${provider.id}\". Pass --api-key or run interactively.`\n );\n }\n return trimmed;\n}\n\nexport const apiKeyAuthStrategy: AuthStrategy<ApiKeyLoginOptions> = {\n async login(provider, options, context) {\n const apiKey = await acquireApiKey(provider, options, context);\n await context.secretStore.set(apiKey);\n return apiKey;\n },\n\n async logout(_provider, context) {\n await context.secretStore.delete();\n },\n\n async isLoggedIn(_provider, context) {\n const value = await context.secretStore.get({ readOnly: context.readOnly });\n return typeof value === \"string\" && value.trim().length > 0;\n },\n\n async resolveCredential(provider, context) {\n requireApiKeyAuth(provider);\n const value = await context.secretStore.get({ readOnly: context.readOnly });\n if (!value || value.trim().length === 0) {\n throw new Error(\n `No stored credential for provider \"${provider.id}\". Run \\`poe-code provider login ${provider.id}\\`.`\n );\n }\n return value.trim();\n }\n};\n", "import type { ApiShapeId, AuthProvider } from \"./types.js\";\n\nexport function resolveApiShape(\n provider: AuthProvider,\n agent: { apiShapes?: readonly ApiShapeId[] }\n): ApiShapeId | undefined {\n if (!provider.apiShapes || !agent.apiShapes) {\n return undefined;\n }\n for (const shapeId of agent.apiShapes) {\n if (provider.apiShapes.some((shape) => shape.id === shapeId)) {\n return shapeId;\n }\n }\n return undefined;\n}\n", "import type { ApiShapeId, AuthProvider } from \"./types.js\";\nimport type { SecretStore } from \"auth-store\";\nimport { apiKeyAuthStrategy } from \"./auth/api-key.js\";\nimport type { ApiKeyLoginOptions } from \"./auth/api-key.js\";\nimport type { PromptForSecret } from \"./auth/types.js\";\nimport { resolveApiShape } from \"./compatibility.js\";\n\nexport interface LoginContext {\n promptForSecret?: PromptForSecret;\n envVars?: Record<string, string | undefined>;\n store?: SecretStore;\n resolvePreferredLogin?: (input: {\n provider: AuthProvider;\n apiKey?: string;\n envValue?: string;\n }) => Promise<string>;\n}\n\nexport type ProviderStoreFactory = (provider: AuthProvider) => SecretStore;\n\nexport interface ProviderRegistryOptions {\n envVars?: Record<string, string | undefined>;\n}\n\nexport interface ProviderAgent {\n id: string;\n apiShapes?: readonly ApiShapeId[];\n}\n\nexport class ProviderRegistry {\n private readonly providers: readonly AuthProvider[];\n private readonly byId: ReadonlyMap<string, AuthProvider>;\n private readonly storeFactory?: ProviderStoreFactory;\n private readonly envVars: Record<string, string | undefined>;\n\n constructor(\n providers: readonly AuthProvider[],\n storeFactory?: ProviderStoreFactory,\n options?: ProviderRegistryOptions\n ) {\n const byId = new Map<string, AuthProvider>();\n const storageKeys = new Map<string, string>();\n for (const provider of providers) {\n const providerId = provider.id.trim();\n if (providerId.length === 0) {\n throw new Error(\"Provider id must not be blank.\");\n }\n if (provider.id !== providerId) {\n throw new Error(\n `Provider id must not include surrounding whitespace: ${JSON.stringify(provider.id)}`\n );\n }\n if (byId.has(providerId)) {\n throw new Error(`Duplicate provider id: ${providerId}`);\n }\n if (provider.auth.kind === \"api-key\") {\n if (storageKeys.has(provider.auth.storageKey)) {\n throw new Error(\n `Duplicate provider credential storage key: ${provider.auth.storageKey}`\n );\n }\n storageKeys.set(provider.auth.storageKey, providerId);\n }\n byId.set(providerId, provider);\n }\n this.providers = Object.freeze([...providers]);\n this.byId = byId;\n this.storeFactory = storeFactory;\n this.envVars = options?.envVars ?? {};\n }\n\n list(): readonly AuthProvider[] {\n return this.providers;\n }\n\n get(id: string): AuthProvider | undefined {\n return this.byId.get(id);\n }\n\n forAgent(agent: ProviderAgent): readonly AuthProvider[] {\n return this.providers.filter((provider) => {\n return resolveApiShape(provider, agent) !== undefined;\n });\n }\n\n async isLoggedIn(id: string, options: { readOnly?: boolean } = {}): Promise<boolean> {\n const provider = this.requireProvider(id);\n if (provider.auth.kind === \"api-key\") {\n const envValue = readOwnEnvValue(this.envVars, provider.auth.envVar);\n if (typeof envValue === \"string\" && envValue.trim().length > 0) {\n return true;\n }\n }\n const store = this.requireStore(provider);\n const credential = await store.get({ readOnly: options.readOnly });\n return typeof credential === \"string\" && credential.trim().length > 0;\n }\n\n async login(id: string, options: ApiKeyLoginOptions, context?: LoginContext): Promise<void> {\n const provider = this.requireProvider(id);\n const store = context?.store ?? this.requireStore(provider);\n if (provider.auth.kind !== \"api-key\") {\n throw new Error(`Provider \"${id}\" does not use api-key auth.`);\n }\n const auth = provider.auth;\n const envApiKey = readOwnEnvValue(context?.envVars ?? this.envVars, auth.envVar);\n const resolvedApiKey =\n options.apiKey ??\n (typeof envApiKey === \"string\" && envApiKey.trim() ? envApiKey : undefined);\n if (auth.preferredLogin && context?.resolvePreferredLogin) {\n const apiKey = normalizeRequiredCredential(provider.id, await context.resolvePreferredLogin({\n provider,\n apiKey: options.apiKey,\n envValue: typeof envApiKey === \"string\" ? envApiKey : undefined\n }));\n await store.set(apiKey);\n return;\n }\n await apiKeyAuthStrategy.login(\n provider,\n { apiKey: resolvedApiKey },\n { secretStore: store, promptForSecret: context?.promptForSecret }\n );\n }\n\n async resolveCredential(\n id: string,\n options: ApiKeyLoginOptions = {},\n context?: Pick<LoginContext, \"envVars\"> & { readOnly?: boolean }\n ): Promise<string> {\n const provider = this.requireProvider(id);\n if (provider.auth.kind !== \"api-key\") {\n throw new Error(`Provider \"${id}\" does not use api-key auth.`);\n }\n\n if (options.apiKey !== undefined) {\n return normalizeRequiredCredential(provider.id, options.apiKey);\n }\n\n const envVars = context?.envVars ?? this.envVars;\n const envApiKey = readOwnEnvValue(envVars, provider.auth.envVar);\n if (typeof envApiKey === \"string\" && envApiKey.trim().length > 0) {\n return envApiKey.trim();\n }\n\n const store = this.requireStore(provider);\n return apiKeyAuthStrategy.resolveCredential(provider, {\n secretStore: store,\n readOnly: context?.readOnly\n });\n }\n\n async logout(id: string, options: { store?: SecretStore } = {}): Promise<void> {\n const provider = this.requireProvider(id);\n const store = options.store ?? this.requireStore(provider);\n await store.delete();\n }\n\n private requireProvider(id: string): AuthProvider {\n const provider = this.byId.get(id);\n if (!provider) {\n throw new Error(`Unknown provider: \"${id}\".`);\n }\n return provider;\n }\n\n private requireStore(provider: AuthProvider): SecretStore {\n if (!this.storeFactory) {\n throw new Error(`No store factory configured for ProviderRegistry.`);\n }\n return this.storeFactory(provider);\n }\n}\n\nfunction normalizeRequiredCredential(providerId: string, value: string): string {\n const trimmed = value.trim();\n if (trimmed.length === 0) {\n throw new Error(`No API key available for provider \"${providerId}\".`);\n }\n return trimmed;\n}\n\nfunction readOwnEnvValue(\n envVars: Record<string, string | undefined>,\n name: string\n): string | undefined {\n return Object.prototype.hasOwnProperty.call(envVars, name) ? envVars[name] : undefined;\n}\n", "import type { ApiShapeId } from \"@poe-code/agent-defs\";\n\nexport type { ApiShapeId } from \"@poe-code/agent-defs\";\n\nexport type EnvValueSource =\n | { kind: \"literal\"; value: string }\n | { kind: \"providerCredential\"; prefix?: string }\n | { kind: \"providerBaseUrl\" }\n | { kind: \"providerField\"; path: string };\n\nexport interface ApiKeyPrompt {\n title: string;\n placeholder?: string;\n}\n\nexport interface ApiKeyAuth {\n kind: \"api-key\";\n envVar: string;\n storageKey: string;\n prompt: ApiKeyPrompt;\n preferredLogin?: \"oauth\";\n}\n\nexport interface OAuthAuth {\n kind: \"oauth\";\n}\n\nexport type AuthMethod = ApiKeyAuth | OAuthAuth;\n\nexport interface ApiShapeBinding {\n readonly id: ApiShapeId;\n readonly baseUrlPath?: string;\n readonly envBaseUrlPath?: string;\n readonly defaultBaseUrl?: string;\n}\n\nexport interface ProviderModelInput {\n readonly kind: \"freeform\";\n}\n\nexport interface AuthProvider {\n readonly id: string;\n readonly label: string;\n readonly summary?: string;\n readonly baseUrl?: string;\n readonly agentBaseUrl?: string;\n readonly baseUrlEnvVar?: string;\n readonly baseUrlEnvPath?: string;\n readonly agentBaseUrlPath?: string;\n readonly requiresBaseUrl?: boolean;\n readonly modelInput?: ProviderModelInput;\n readonly auth: AuthMethod;\n readonly apiShapes?: readonly ApiShapeBinding[];\n readonly env?: Readonly<Record<string, EnvValueSource>>;\n}\n\nexport function defineProvider(provider: AuthProvider): AuthProvider {\n if (provider.auth.kind === \"api-key\") {\n Object.freeze(provider.auth.prompt);\n }\n Object.freeze(provider.auth);\n for (const shape of provider.apiShapes ?? []) {\n Object.freeze(shape);\n }\n if (provider.apiShapes !== undefined) {\n Object.freeze(provider.apiShapes);\n }\n if (provider.modelInput !== undefined) {\n Object.freeze(provider.modelInput);\n }\n for (const source of Object.values(provider.env ?? {})) {\n Object.freeze(source);\n }\n if (provider.env !== undefined) {\n Object.freeze(provider.env);\n }\n return Object.freeze(provider);\n}\n", "import { defineProvider } from \"../types.js\";\n\nexport const POE_PROVIDER_ID = \"poe\" as const;\n\nexport const poeProvider = defineProvider({\n id: POE_PROVIDER_ID,\n label: \"Poe\",\n summary: \"Route AI coding agents through Poe's API.\",\n baseUrl: \"https://api.poe.com\",\n agentBaseUrl: \"https://api.poe.com\",\n baseUrlEnvVar: \"POE_BASE_URL\",\n baseUrlEnvPath: \"v1\",\n agentBaseUrlPath: \"\",\n auth: {\n kind: \"api-key\",\n envVar: \"POE_API_KEY\",\n storageKey: \"provider:poe\",\n prompt: { title: \"Poe API key\" },\n preferredLogin: \"oauth\"\n },\n env: {\n ANTHROPIC_CUSTOM_HEADERS: {\n kind: \"providerCredential\",\n prefix: \"Authorization: Bearer \"\n }\n },\n apiShapes: [\n {\n id: \"openai-chat-completions\",\n envBaseUrlPath: \"v1\"\n },\n {\n id: \"openai-responses\",\n envBaseUrlPath: \"v1\"\n },\n {\n id: \"anthropic-messages\",\n envBaseUrlPath: \"anthropic\"\n }\n ]\n});\n", "import type { AuthProvider } from \"./types.js\";\n\nexport function orderAuthProviders(providers: readonly AuthProvider[]): readonly AuthProvider[] {\n return Object.freeze([...providers].sort(compareAuthProviders));\n}\n\nfunction compareAuthProviders(left: AuthProvider, right: AuthProvider): number {\n const rankDifference = authProviderRank(left) - authProviderRank(right);\n if (rankDifference !== 0) {\n return rankDifference;\n }\n return left.id.localeCompare(right.id);\n}\n\nfunction authProviderRank(provider: AuthProvider): number {\n if (provider.auth.kind === \"api-key\" && provider.auth.preferredLogin === \"oauth\") {\n return 0;\n }\n if (provider.requiresBaseUrl === true) {\n return 2;\n }\n return 1;\n}\n", "import { defineProvider } from \"../types.js\";\n\nexport const anthropicProvider = defineProvider({\n id: \"anthropic\",\n label: \"Anthropic\",\n summary: \"Route AI coding agents through Anthropic's API.\",\n baseUrl: \"https://api.anthropic.com\",\n auth: {\n kind: \"api-key\",\n envVar: \"ANTHROPIC_API_KEY\",\n storageKey: \"provider:anthropic\",\n prompt: { title: \"Anthropic API key\" }\n },\n env: {\n ANTHROPIC_API_KEY: { kind: \"providerCredential\" }\n },\n apiShapes: [\n {\n id: \"anthropic-messages\"\n }\n ]\n});\n", "import { defineProvider } from \"../types.js\";\n\nexport const cloudflareProvider = defineProvider({\n id: \"cloudflare\",\n label: \"Cloudflare AI Gateway\",\n summary: \"Route coding agents through Cloudflare AI Gateway.\",\n baseUrlEnvVar: \"CF_AIG_BASE_URL\",\n requiresBaseUrl: true,\n modelInput: { kind: \"freeform\" },\n auth: {\n kind: \"api-key\",\n envVar: \"CF_AIG_TOKEN\",\n storageKey: \"provider:cloudflare\",\n prompt: { title: \"Cloudflare AI Gateway token\" }\n },\n env: {\n ANTHROPIC_CUSTOM_HEADERS: {\n kind: \"providerCredential\",\n prefix: \"Authorization: Bearer \"\n }\n },\n apiShapes: [\n {\n id: \"openai-chat-completions\",\n baseUrlPath: \"compat\"\n },\n {\n id: \"openai-responses\",\n baseUrlPath: \"openai\"\n },\n {\n id: \"anthropic-messages\",\n baseUrlPath: \"anthropic\"\n },\n {\n id: \"google-generations\",\n baseUrlPath: \"google-ai-studio\"\n }\n ]\n});\n", "import { defineProvider } from \"../types.js\";\n\nexport const openaiProvider = defineProvider({\n id: \"openai\",\n label: \"OpenAI\",\n summary: \"Route AI coding agents through OpenAI's API.\",\n baseUrl: \"https://api.openai.com/v1\",\n auth: {\n kind: \"api-key\",\n envVar: \"OPENAI_API_KEY\",\n storageKey: \"provider:openai\",\n prompt: { title: \"OpenAI API key\" }\n },\n apiShapes: [\n {\n id: \"openai-responses\"\n },\n {\n id: \"openai-chat-completions\"\n }\n ]\n});\n", "// Generated by packages/providers/scripts/generate-provider-registry.mjs. Do not edit manually.\nimport { orderAuthProviders } from \"../provider-order.js\";\nimport { anthropicProvider } from \"./anthropic.js\";\nimport { cloudflareProvider } from \"./cloudflare.js\";\nimport { openaiProvider } from \"./openai.js\";\nimport { poeProvider } from \"./poe.js\";\n\nexport * from \"./anthropic.js\";\nexport * from \"./cloudflare.js\";\nexport * from \"./openai.js\";\nexport * from \"./poe.js\";\n\nexport const allAuthProviders = orderAuthProviders([\n anthropicProvider,\n cloudflareProvider,\n openaiProvider,\n poeProvider\n]);\n", "import os from \"node:os\";\nimport { createJobRegistry, type JobRegistry } from \"./jobs.js\";\nimport { createTemplateRegistry, type TemplateRegistry } from \"./templates.js\";\nimport type { StateFileSystem } from \"./fs.js\";\n\nexport interface StateManager {\n templates: TemplateRegistry;\n jobs: JobRegistry;\n}\n\nexport async function loadStateManager(homeDir: string = os.homedir()): Promise<StateManager> {\n return {\n templates: createTemplateRegistry(homeDir),\n jobs: createJobRegistry(homeDir)\n };\n}\n\nexport function createStateManager(homeDir: string, fs?: StateFileSystem): StateManager {\n return {\n templates: createTemplateRegistry(homeDir, fs),\n jobs: createJobRegistry(homeDir, fs)\n };\n}\n\nexport {\n createJobRegistry,\n type JobEntry,\n type JobListFilter,\n type JobRegistry,\n type JobStatus\n} from \"./jobs.js\";\nexport {\n createTemplateRegistry,\n type TemplateBackend,\n type TemplateEntry,\n type TemplateRegistry\n} from \"./templates.js\";\nexport type { StateFileSystem } from \"./fs.js\";\n", "import { randomUUID } from \"node:crypto\";\nimport path from \"node:path\";\nimport {\n assertPathHasNoSymbolicLinks,\n defaultStateFs,\n isNotFoundError,\n type StateFileSystem\n} from \"./fs.js\";\nimport { hasOwnErrorCode } from \"../errors.js\";\n\nexport type JobStatus = \"pending\" | \"running\" | \"exited\" | \"killed\" | \"lost\";\n\nexport interface JobEntry {\n id: string;\n env_id: string;\n env_kind: string;\n tool: string;\n argv: string[];\n cwd: string;\n started_at: string;\n status: JobStatus;\n exit_code?: number;\n exited_at?: string;\n log_file?: string;\n reattach_context?: Record<string, unknown>;\n}\n\nexport interface JobListFilter {\n env_id?: string;\n env_kind?: string;\n tool?: string;\n status?: JobStatus;\n since?: Date;\n limit?: number;\n}\n\nexport interface JobRegistry {\n get(id: string): Promise<JobEntry | null>;\n put(entry: JobEntry): Promise<void>;\n update(id: string, patch: Partial<JobEntry>): Promise<JobEntry | null>;\n /** Newest first, capped by filter.limit when provided. */\n list(filter?: JobListFilter): Promise<JobEntry[]>;\n remove(id: string): Promise<void>;\n}\n\nexport function createJobRegistry(\n homeDir: string,\n fs: StateFileSystem = defaultStateFs\n): JobRegistry {\n const jobsDir = path.join(homeDir, \".poe-code\", \"state\", \"jobs\");\n let pendingMutation: Promise<void> = Promise.resolve();\n\n function jobPath(id: string): string {\n assertSafeJobId(id);\n return path.join(jobsDir, `${id}.json`);\n }\n\n async function assertSafeJobsDir(): Promise<void> {\n await assertPathHasNoSymbolicLinks(\n fs,\n jobsDir,\n \"Refusing runtime job state access through symbolic link\"\n );\n }\n\n async function assertSafeJobPath(filePath: string): Promise<void> {\n await assertPathHasNoSymbolicLinks(\n fs,\n filePath,\n \"Refusing runtime job state access through symbolic link\"\n );\n }\n\n async function get(id: string): Promise<JobEntry | null> {\n const filePath = jobPath(id);\n await assertSafeJobPath(filePath);\n try {\n return parseJobEntry(await fs.readFile(filePath, \"utf8\"), id);\n } catch (error) {\n if (isNotFoundError(error)) {\n return null;\n }\n\n throw error;\n }\n }\n\n async function put(entry: JobEntry): Promise<void> {\n assertJobEntry(entry);\n const filePath = jobPath(entry.id);\n await mutate(async () => {\n await assertSafeJobsDir();\n await fs.mkdir(jobsDir, { recursive: true });\n await assertSafeJobsDir();\n await writeJobAtomically(filePath, entry);\n });\n }\n\n async function update(id: string, patch: Partial<JobEntry>): Promise<JobEntry | null> {\n const filePath = jobPath(id);\n return mutate(async () => {\n await assertSafeJobsDir();\n await fs.mkdir(jobsDir, { recursive: true });\n await assertSafeJobsDir();\n const current = await get(id);\n if (current === null) {\n return null;\n }\n\n const updated = {\n ...current,\n ...patch,\n id: current.id\n };\n assertJobEntry(updated);\n await writeJobAtomically(filePath, updated);\n return updated;\n });\n }\n\n async function list(filter: JobListFilter = {}): Promise<JobEntry[]> {\n await assertSafeJobsDir();\n let entries: string[];\n\n try {\n entries = await fs.readdir(jobsDir);\n } catch (error) {\n if (isNotFoundError(error)) {\n return [];\n }\n\n throw error;\n }\n\n const jobs: JobEntry[] = [];\n for (const entry of entries.sort()) {\n if (!entry.endsWith(\".json\")) {\n continue;\n }\n\n const filePath = path.join(jobsDir, entry);\n await assertSafeJobPath(filePath);\n const stat = await fs.stat(filePath);\n if (!stat.isFile()) {\n continue;\n }\n\n const job = parseJobEntry(\n await fs.readFile(filePath, \"utf8\"),\n entry.slice(0, -\".json\".length)\n );\n if (job !== null && matchesFilter(job, filter)) {\n jobs.push(job);\n }\n }\n\n jobs.sort((left, right) => startedAtTime(right) - startedAtTime(left));\n return filter.limit === undefined ? jobs : jobs.slice(0, filter.limit);\n }\n\n async function remove(id: string): Promise<void> {\n const filePath = jobPath(id);\n await mutate(async () => {\n await assertSafeJobsDir();\n try {\n await fs.stat(jobsDir);\n } catch (error) {\n if (isNotFoundError(error)) {\n return;\n }\n\n throw error;\n }\n\n try {\n await assertSafeJobPath(filePath);\n await fs.unlink(filePath);\n } catch (error) {\n if (!isNotFoundError(error)) {\n throw error;\n }\n }\n });\n }\n\n async function mutate<Result>(operation: () => Promise<Result>): Promise<Result> {\n const mutation = pendingMutation.then(operation);\n pendingMutation = mutation.then(\n () => undefined,\n () => undefined\n );\n return mutation;\n }\n\n async function writeJobAtomically(filePath: string, entry: JobEntry): Promise<void> {\n await assertSafeJobPath(filePath);\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n const tempPath = `${filePath}.${process.pid}.${randomUUID()}.tmp`;\n let tempCreated = false;\n\n try {\n await assertSafeJobPath(tempPath);\n await fs.writeFile(tempPath, `${JSON.stringify(entry, null, 2)}\\n`, {\n encoding: \"utf8\",\n flag: \"wx\"\n });\n tempCreated = true;\n await assertSafeJobPath(filePath);\n await fs.rename(tempPath, filePath);\n } catch (error) {\n if (tempCreated || !isAlreadyExistsError(error)) {\n await removeTempFile(tempPath).catch(() => undefined);\n }\n throw error;\n }\n }\n\n async function removeTempFile(tempPath: string): Promise<void> {\n try {\n await fs.unlink(tempPath);\n } catch (error) {\n if (!isNotFoundError(error)) {\n throw error;\n }\n }\n }\n\n return {\n get,\n put,\n update,\n list,\n remove\n };\n}\n\nfunction assertSafeJobId(id: string): void {\n if (\n id.length === 0 ||\n id === \".\" ||\n id === \"..\" ||\n path.isAbsolute(id) ||\n id.includes(\"/\") ||\n id.includes(\"\\\\\") ||\n id.includes(\"\\0\")\n ) {\n throw new Error(\"Invalid job id.\");\n }\n}\n\nfunction isAlreadyExistsError(error: unknown): boolean {\n return hasOwnErrorCode(error, \"EEXIST\");\n}\n\nfunction assertJobEntry(entry: JobEntry): void {\n if (!isJobEntry(entry)) {\n throw new Error(\"Invalid job entry.\");\n }\n}\n\nfunction matchesFilter(job: JobEntry, filter: JobListFilter): boolean {\n return (\n (filter.env_id === undefined || job.env_id === filter.env_id) &&\n (filter.env_kind === undefined || job.env_kind === filter.env_kind) &&\n (filter.tool === undefined || job.tool === filter.tool) &&\n (filter.status === undefined || job.status === filter.status) &&\n isWithinSince(job, filter.since)\n );\n}\n\nfunction isWithinSince(job: JobEntry, since: Date | undefined): boolean {\n if (since === undefined) {\n return true;\n }\n\n const startedAt = Date.parse(job.started_at);\n return !Number.isFinite(startedAt) || startedAt >= since.getTime();\n}\n\nfunction startedAtTime(job: JobEntry): number {\n const startedAt = Date.parse(job.started_at);\n return Number.isFinite(startedAt) ? startedAt : 0;\n}\n\nfunction parseJobEntry(content: string, expectedId: string): JobEntry | null {\n const parsed = JSON.parse(content) as unknown;\n if (!isJobEntry(parsed)) {\n throw new Error(\"Invalid job state file.\");\n }\n return parsed.id === expectedId ? parsed : null;\n}\n\nfunction isJobEntry(value: unknown): value is JobEntry {\n return (\n isRecord(value) &&\n typeof value.id === \"string\" &&\n typeof value.env_id === \"string\" &&\n typeof value.env_kind === \"string\" &&\n typeof value.tool === \"string\" &&\n Array.isArray(value.argv) &&\n value.argv.every((arg) => typeof arg === \"string\") &&\n typeof value.cwd === \"string\" &&\n typeof value.started_at === \"string\" &&\n isJobStatus(value.status) &&\n (value.exit_code === undefined ||\n (typeof value.exit_code === \"number\" && Number.isInteger(value.exit_code))) &&\n (value.exited_at === undefined || typeof value.exited_at === \"string\") &&\n (value.log_file === undefined || typeof value.log_file === \"string\") &&\n (value.reattach_context === undefined || isRecord(value.reattach_context))\n );\n}\n\nfunction isJobStatus(value: unknown): value is JobStatus {\n return (\n value === \"pending\" ||\n value === \"running\" ||\n value === \"exited\" ||\n value === \"killed\" ||\n value === \"lost\"\n );\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value && typeof value === \"object\" && !Array.isArray(value));\n}\n\nexport type { StateFileSystem } from \"./fs.js\";\n", "import * as nodeFs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { hasOwnErrorCode } from \"../errors.js\";\n\nexport interface StateFileSystem {\n mkdir(path: string, options: { recursive: true }): Promise<unknown>;\n readFile(path: string, encoding: BufferEncoding): Promise<string>;\n writeFile(\n path: string,\n data: string,\n options?: BufferEncoding | { encoding?: BufferEncoding; flag?: string; mode?: number }\n ): Promise<void>;\n rename(oldPath: string, newPath: string): Promise<void>;\n readdir(path: string): Promise<string[]>;\n stat(path: string): Promise<{\n isFile(): boolean;\n mtimeMs: number;\n }>;\n lstat?(path: string): Promise<{\n isSymbolicLink(): boolean;\n }>;\n unlink(path: string): Promise<void>;\n}\n\nexport const defaultStateFs = nodeFs as unknown as StateFileSystem;\n\nexport function isNotFoundError(error: unknown): boolean {\n return hasOwnErrorCode(error, \"ENOENT\");\n}\n\nexport async function assertPathHasNoSymbolicLinks(\n fs: StateFileSystem,\n targetPath: string,\n message: string\n): Promise<void> {\n if (fs.lstat === undefined) {\n return;\n }\n\n const absolutePath = path.resolve(targetPath);\n const root = path.parse(absolutePath).root;\n let inspectedPath = root;\n\n for (const segment of absolutePath.slice(root.length).split(path.sep).filter(Boolean)) {\n inspectedPath = path.join(inspectedPath, segment);\n try {\n if ((await fs.lstat(inspectedPath)).isSymbolicLink()) {\n throw new Error(`${message}: ${targetPath}`);\n }\n } catch (error) {\n if (isNotFoundError(error)) {\n return;\n }\n\n throw error;\n }\n }\n}\n", "import { randomUUID } from \"node:crypto\";\nimport path from \"node:path\";\nimport {\n assertPathHasNoSymbolicLinks,\n defaultStateFs,\n isNotFoundError,\n type StateFileSystem\n} from \"./fs.js\";\nimport { hasOwnErrorCode } from \"../errors.js\";\n\nexport type TemplateBackend = \"docker\";\n\nexport interface TemplateEntry {\n hash: string;\n template_id?: string;\n image?: string;\n runtime_type: string;\n dockerfile_path: string;\n built_at: string;\n}\n\ntype TemplateState = Record<TemplateBackend, Record<string, TemplateEntry>>;\n\nexport interface TemplateRegistry {\n get(backend: TemplateBackend, hash: string): Promise<TemplateEntry | null>;\n put(backend: TemplateBackend, entry: TemplateEntry): Promise<void>;\n remove(backend: TemplateBackend, hash: string): Promise<void>;\n list(backend?: TemplateBackend): Promise<TemplateEntry[]>;\n}\n\nexport function createTemplateRegistry(\n homeDir: string,\n fs: StateFileSystem = defaultStateFs\n): TemplateRegistry {\n const filePath = path.join(homeDir, \".poe-code\", \"state\", \"templates.json\");\n let pendingUpdate: Promise<void> = Promise.resolve();\n\n async function readState(): Promise<TemplateState> {\n await assertSafeStateFile();\n try {\n const raw = await fs.readFile(filePath, \"utf8\");\n return normalizeTemplateState(JSON.parse(raw));\n } catch (error) {\n if (isNotFoundError(error)) {\n return createEmptyState();\n }\n\n throw error;\n }\n }\n\n async function writeState(state: TemplateState): Promise<void> {\n await assertSafeStateFile();\n const tempPath = `${filePath}.${process.pid}.${randomUUID()}.tmp`;\n let tempCreated = false;\n\n try {\n await assertSafeStatePath(tempPath);\n await fs.writeFile(tempPath, `${JSON.stringify(state, null, 2)}\\n`, {\n encoding: \"utf8\",\n flag: \"wx\"\n });\n tempCreated = true;\n await assertSafeStateFile();\n await fs.rename(tempPath, filePath);\n } catch (error) {\n if (tempCreated || !isAlreadyExistsError(error)) {\n await fs.unlink(tempPath).catch(() => undefined);\n }\n throw error;\n }\n }\n\n async function updateState(mutator: (state: TemplateState) => void): Promise<void> {\n const update = pendingUpdate.then(async () => {\n await assertSafeStateFile();\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n await assertSafeStateFile();\n const state = await readState();\n mutator(state);\n await writeState(state);\n });\n pendingUpdate = update.catch(() => undefined);\n await update;\n }\n\n async function assertSafeStateFile(): Promise<void> {\n await assertSafeStatePath(filePath);\n }\n\n async function assertSafeStatePath(statePath: string): Promise<void> {\n await assertPathHasNoSymbolicLinks(\n fs,\n statePath,\n \"Refusing template state access through symbolic link\"\n );\n }\n\n async function get(backend: TemplateBackend, hash: string): Promise<TemplateEntry | null> {\n const state = await readState();\n return state[backend][hash] ?? null;\n }\n\n async function put(backend: TemplateBackend, entry: TemplateEntry): Promise<void> {\n await updateState((state) => {\n state[backend][entry.hash] = entry;\n });\n }\n\n async function remove(backend: TemplateBackend, hash: string): Promise<void> {\n await updateState((state) => {\n delete state[backend][hash];\n });\n }\n\n async function list(backend?: TemplateBackend): Promise<TemplateEntry[]> {\n const state = await readState();\n const entries = Object.values(state[backend ?? \"docker\"]);\n\n return entries.sort((left, right) => left.hash.localeCompare(right.hash));\n }\n\n return {\n get,\n put,\n remove,\n list\n };\n}\n\nfunction createEmptyState(): TemplateState {\n return {\n docker: Object.create(null) as Record<string, TemplateEntry>\n };\n}\n\nfunction normalizeTemplateState(value: unknown): TemplateState {\n if (!isRecord(value)) {\n return createEmptyState();\n }\n\n return {\n docker: normalizeTemplateEntries(value.docker)\n };\n}\n\nfunction normalizeTemplateEntries(value: unknown): Record<string, TemplateEntry> {\n if (!isRecord(value)) {\n return Object.create(null) as Record<string, TemplateEntry>;\n }\n\n const entries = Object.create(null) as Record<string, TemplateEntry>;\n for (const [hash, entry] of Object.entries(value)) {\n if (isTemplateEntry(entry) && entry.hash === hash) {\n entries[hash] = entry;\n }\n }\n return entries;\n}\n\nfunction isTemplateEntry(value: unknown): value is TemplateEntry {\n return (\n isRecord(value) &&\n typeof value.hash === \"string\" &&\n typeof value.runtime_type === \"string\" &&\n typeof value.dockerfile_path === \"string\" &&\n typeof value.built_at === \"string\" &&\n (value.template_id === undefined || typeof value.template_id === \"string\") &&\n (value.image === undefined || typeof value.image === \"string\")\n );\n}\n\nfunction isAlreadyExistsError(error: unknown): boolean {\n return hasOwnErrorCode(error, \"EEXIST\");\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value && typeof value === \"object\" && !Array.isArray(value));\n}\n\nexport type { StateFileSystem } from \"./fs.js\";\n", "import { createSecretStore } from \"auth-store\";\nimport { ApiError, AuthenticationError } from \"../cli/errors.js\";\nimport type { HttpClient } from \"../cli/http.js\";\nimport { resolvePoeApiBaseUrl } from \"../cli/environment.js\";\n\nexport interface PoeAuthIdentity {\n user_id: number;\n handle: string;\n name: string;\n profile_picture: string;\n [key: string]: unknown;\n}\n\nexport interface FetchPoeAuthIdentityOptions {\n apiKey: string;\n baseUrl?: string;\n httpClient?: HttpClient;\n}\n\nexport interface GetPoeAuthIdentityOptions {\n apiKey?: string;\n baseUrl?: string;\n variables?: Record<string, string | undefined>;\n httpClient?: HttpClient;\n}\n\n/**\n * Reads the Poe API key with the following priority:\n * 1. `POE_API_KEY` environment variable (if set)\n * 2. Auth store (`auth-store`)\n *\n * @returns The API key\n * @throws AuthenticationError if no credentials found\n */\nexport async function getPoeApiKey(): Promise<string> {\n const envKey = Object.hasOwn(process.env, \"POE_API_KEY\") ? process.env.POE_API_KEY : undefined;\n if (typeof envKey === \"string\" && envKey.trim().length > 0) {\n return envKey.trim();\n }\n\n const { store } = createSecretStore({\n backendEnvVar: \"POE_AUTH_BACKEND\",\n fileStore: {\n salt: \"poe-code:encrypted-file-auth-store:v1\",\n defaultDirectory: \".poe-code\",\n defaultFileName: \"credentials.enc\"\n }\n });\n const storedKey = await store.get();\n\n if (typeof storedKey === \"string\" && storedKey.trim().length > 0) {\n return storedKey.trim();\n }\n\n throw new AuthenticationError(\"No API key found. Set POE_API_KEY or run 'poe-code login'.\");\n}\n\nexport async function ensurePoeApiKeyEnv(): Promise<void> {\n const envKey = Object.hasOwn(process.env, \"POE_API_KEY\") ? process.env.POE_API_KEY : undefined;\n if (typeof envKey === \"string\" && envKey.trim().length > 0) {\n return;\n }\n\n process.env.POE_API_KEY = await getPoeApiKey();\n}\n\nexport async function getPoeAuthIdentity(\n options: GetPoeAuthIdentityOptions = {}\n): Promise<PoeAuthIdentity> {\n const apiKey = options.apiKey ?? await getPoeApiKey();\n return fetchPoeAuthIdentity({\n apiKey,\n baseUrl: options.baseUrl ?? resolvePoeApiBaseUrl(options.variables),\n httpClient: options.httpClient\n });\n}\n\nexport async function fetchPoeAuthIdentity(\n options: FetchPoeAuthIdentityOptions\n): Promise<PoeAuthIdentity> {\n const httpClient = options.httpClient ?? createDefaultHttpClient();\n const response = await httpClient(`${trimTrailingSlashes(options.baseUrl ?? resolvePoeApiBaseUrl())}/whoami`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${options.apiKey}`\n }\n });\n\n if (!response.ok) {\n throw new ApiError(`Failed to fetch identity (HTTP ${response.status})`, {\n httpStatus: response.status,\n endpoint: \"/v1/whoami\"\n });\n }\n\n return parsePoeAuthIdentity(await response.json());\n}\n\nfunction parsePoeAuthIdentity(value: unknown): PoeAuthIdentity {\n if (\n typeof value !== \"object\" ||\n value === null ||\n Array.isArray(value)\n ) {\n throw new ApiError(\"Malformed identity response from Poe API.\", {\n endpoint: \"/v1/whoami\"\n });\n }\n\n const identity = value as Partial<PoeAuthIdentity>;\n if (\n typeof identity.user_id !== \"number\" ||\n !Number.isFinite(identity.user_id) ||\n typeof identity.handle !== \"string\" ||\n identity.handle.trim().length === 0 ||\n typeof identity.name !== \"string\" ||\n identity.name.trim().length === 0 ||\n typeof identity.profile_picture !== \"string\"\n ) {\n throw new ApiError(\"Malformed identity response from Poe API.\", {\n endpoint: \"/v1/whoami\"\n });\n }\n\n return value as PoeAuthIdentity;\n}\n\nfunction createDefaultHttpClient(): HttpClient {\n return async (url, init) => {\n const response = await globalThis.fetch(url, init as RequestInit);\n return {\n ok: response.ok,\n status: response.status,\n json: () => response.json()\n };\n };\n}\n\nfunction trimTrailingSlashes(value: string): string {\n return value.replace(/\\/+$/, \"\");\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["error", "error", "key", "cached", "resolve", "error", "message", "resolve", "getOwnEntry", "key", "key", "message", "message", "message", "path", "path", "getOwnEntry", "getOwnEntry", "key", "path", "key", "key", "getOwnEntry", "isRecord", "key", "existsSync", "path", "randomUUID", "path", "path", "path", "path", "text", "active", "prompt", "number", "text", "config", "revision", "symbol", "spacing", "message", "symbol", "graphemeSegmenter", "spawn", "process", "graphemeSegmenter", "AsyncLocalStorage", "readline", "wrapAnsi", "stringWidth", "wrapAnsi", "path", "randomUUID", "path", "parseYaml", "path", "path", "EMPTY_DOCUMENT", "randomUUID", "path", "EMPTY_DOCUMENT", "randomUUID", "path", "path", "randomUUID", "path"]
|
|
7
|
+
}
|