@caupulican/pi-adaptative 0.81.31 → 0.81.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (237) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/bundled-resources/extensions/tmux-agent-manager/README.md +69 -0
  3. package/dist/bundled-resources/extensions/tmux-agent-manager/index.d.ts +53 -0
  4. package/dist/bundled-resources/extensions/tmux-agent-manager/index.d.ts.map +1 -0
  5. package/dist/bundled-resources/extensions/tmux-agent-manager/index.js +1282 -0
  6. package/dist/bundled-resources/extensions/tmux-agent-manager/index.js.map +1 -0
  7. package/dist/bundled-resources/extensions/tmux-agent-manager/index.ts +1453 -0
  8. package/dist/bundled-resources/extensions/tmux-agent-manager/templates/builder-validator.json +14 -0
  9. package/dist/bundled-resources/extensions/tmux-agent-manager/templates/claude-trio.json +32 -0
  10. package/dist/bundled-resources/extensions/tmux-agent-manager/templates/full-provider-review.json +15 -0
  11. package/dist/bundled-resources/extensions/tmux-agent-manager/templates/provider-prompt-smoke.json +14 -0
  12. package/dist/bundled-resources/prompts/extensionify.md +5 -4
  13. package/dist/bundled-resources/prompts/skillify.md +5 -5
  14. package/dist/bundled-resources/skills/pi-harness-learning/SKILL.md +6 -3
  15. package/dist/config.d.ts +5 -1
  16. package/dist/config.d.ts.map +1 -1
  17. package/dist/config.js +10 -2
  18. package/dist/config.js.map +1 -1
  19. package/dist/core/agent-session.d.ts +7 -0
  20. package/dist/core/agent-session.d.ts.map +1 -1
  21. package/dist/core/agent-session.js +25 -2
  22. package/dist/core/agent-session.js.map +1 -1
  23. package/dist/core/background-lane-controller.d.ts +12 -3
  24. package/dist/core/background-lane-controller.d.ts.map +1 -1
  25. package/dist/core/background-lane-controller.js +67 -26
  26. package/dist/core/background-lane-controller.js.map +1 -1
  27. package/dist/core/bash-executor.d.ts.map +1 -1
  28. package/dist/core/bash-executor.js +7 -3
  29. package/dist/core/bash-executor.js.map +1 -1
  30. package/dist/core/context/context-store-retention.d.ts +4 -1
  31. package/dist/core/context/context-store-retention.d.ts.map +1 -1
  32. package/dist/core/context/context-store-retention.js +42 -151
  33. package/dist/core/context/context-store-retention.js.map +1 -1
  34. package/dist/core/context-pipeline.d.ts.map +1 -1
  35. package/dist/core/context-pipeline.js +6 -6
  36. package/dist/core/context-pipeline.js.map +1 -1
  37. package/dist/core/exec.d.ts.map +1 -1
  38. package/dist/core/exec.js +25 -39
  39. package/dist/core/exec.js.map +1 -1
  40. package/dist/core/extensions/loader.d.ts +9 -2
  41. package/dist/core/extensions/loader.d.ts.map +1 -1
  42. package/dist/core/extensions/loader.js +105 -21
  43. package/dist/core/extensions/loader.js.map +1 -1
  44. package/dist/core/footer-data-provider.d.ts.map +1 -1
  45. package/dist/core/footer-data-provider.js +2 -0
  46. package/dist/core/footer-data-provider.js.map +1 -1
  47. package/dist/core/goals/goal-state.d.ts +10 -0
  48. package/dist/core/goals/goal-state.d.ts.map +1 -1
  49. package/dist/core/goals/goal-state.js +37 -0
  50. package/dist/core/goals/goal-state.js.map +1 -1
  51. package/dist/core/goals/goal-tool-core.d.ts +11 -0
  52. package/dist/core/goals/goal-tool-core.d.ts.map +1 -1
  53. package/dist/core/goals/goal-tool-core.js +51 -1
  54. package/dist/core/goals/goal-tool-core.js.map +1 -1
  55. package/dist/core/improvement-loop.d.ts.map +1 -1
  56. package/dist/core/improvement-loop.js +26 -5
  57. package/dist/core/improvement-loop.js.map +1 -1
  58. package/dist/core/models/fitness-store.d.ts.map +1 -1
  59. package/dist/core/models/fitness-store.js +1 -1
  60. package/dist/core/models/fitness-store.js.map +1 -1
  61. package/dist/core/models/local-runtime.d.ts +6 -4
  62. package/dist/core/models/local-runtime.d.ts.map +1 -1
  63. package/dist/core/models/local-runtime.js +108 -36
  64. package/dist/core/models/local-runtime.js.map +1 -1
  65. package/dist/core/output-guard.d.ts.map +1 -1
  66. package/dist/core/output-guard.js +23 -8
  67. package/dist/core/output-guard.js.map +1 -1
  68. package/dist/core/package-manager.d.ts.map +1 -1
  69. package/dist/core/package-manager.js +44 -59
  70. package/dist/core/package-manager.js.map +1 -1
  71. package/dist/core/profile-resource-selection.d.ts +16 -0
  72. package/dist/core/profile-resource-selection.d.ts.map +1 -1
  73. package/dist/core/profile-resource-selection.js +41 -0
  74. package/dist/core/profile-resource-selection.js.map +1 -1
  75. package/dist/core/reflection-controller.d.ts.map +1 -1
  76. package/dist/core/reflection-controller.js +18 -1
  77. package/dist/core/reflection-controller.js.map +1 -1
  78. package/dist/core/reload-blockers.d.ts +1 -0
  79. package/dist/core/reload-blockers.d.ts.map +1 -1
  80. package/dist/core/reload-blockers.js +6 -2
  81. package/dist/core/reload-blockers.js.map +1 -1
  82. package/dist/core/resource-loader.d.ts +2 -0
  83. package/dist/core/resource-loader.d.ts.map +1 -1
  84. package/dist/core/resource-loader.js +50 -28
  85. package/dist/core/resource-loader.js.map +1 -1
  86. package/dist/core/settings-manager.d.ts.map +1 -1
  87. package/dist/core/settings-manager.js +1 -1
  88. package/dist/core/settings-manager.js.map +1 -1
  89. package/dist/core/slash-commands.d.ts.map +1 -1
  90. package/dist/core/slash-commands.js +1 -1
  91. package/dist/core/slash-commands.js.map +1 -1
  92. package/dist/core/toolkit/script-runner.d.ts.map +1 -1
  93. package/dist/core/toolkit/script-runner.js +58 -24
  94. package/dist/core/toolkit/script-runner.js.map +1 -1
  95. package/dist/core/tools/bash.d.ts.map +1 -1
  96. package/dist/core/tools/bash.js +13 -26
  97. package/dist/core/tools/bash.js.map +1 -1
  98. package/dist/core/tools/extensionify.d.ts +2 -1
  99. package/dist/core/tools/extensionify.d.ts.map +1 -1
  100. package/dist/core/tools/extensionify.js +11 -8
  101. package/dist/core/tools/extensionify.js.map +1 -1
  102. package/dist/core/tools/find.d.ts.map +1 -1
  103. package/dist/core/tools/find.js +54 -48
  104. package/dist/core/tools/find.js.map +1 -1
  105. package/dist/core/tools/git-filter.d.ts.map +1 -1
  106. package/dist/core/tools/git-filter.js +20 -32
  107. package/dist/core/tools/git-filter.js.map +1 -1
  108. package/dist/core/tools/goal.d.ts +1 -1
  109. package/dist/core/tools/goal.d.ts.map +1 -1
  110. package/dist/core/tools/goal.js +10 -3
  111. package/dist/core/tools/goal.js.map +1 -1
  112. package/dist/core/tools/grep.d.ts.map +1 -1
  113. package/dist/core/tools/grep.js +89 -80
  114. package/dist/core/tools/grep.js.map +1 -1
  115. package/dist/core/tools/output-accumulator.d.ts +2 -0
  116. package/dist/core/tools/output-accumulator.d.ts.map +1 -1
  117. package/dist/core/tools/output-accumulator.js +7 -4
  118. package/dist/core/tools/output-accumulator.js.map +1 -1
  119. package/dist/core/tools/read.d.ts.map +1 -1
  120. package/dist/core/tools/read.js +4 -3
  121. package/dist/core/tools/read.js.map +1 -1
  122. package/dist/index.d.ts +2 -1
  123. package/dist/index.d.ts.map +1 -1
  124. package/dist/index.js +2 -1
  125. package/dist/index.js.map +1 -1
  126. package/dist/main.d.ts +2 -0
  127. package/dist/main.d.ts.map +1 -1
  128. package/dist/main.js +23 -4
  129. package/dist/main.js.map +1 -1
  130. package/dist/migrations.d.ts.map +1 -1
  131. package/dist/migrations.js +18 -4
  132. package/dist/migrations.js.map +1 -1
  133. package/dist/modes/interactive/auth-dialogs-controller.d.ts +10 -0
  134. package/dist/modes/interactive/auth-dialogs-controller.d.ts.map +1 -1
  135. package/dist/modes/interactive/auth-dialogs-controller.js +94 -27
  136. package/dist/modes/interactive/auth-dialogs-controller.js.map +1 -1
  137. package/dist/modes/interactive/auto-learn-controller.d.ts.map +1 -1
  138. package/dist/modes/interactive/auto-learn-controller.js +2 -1
  139. package/dist/modes/interactive/auto-learn-controller.js.map +1 -1
  140. package/dist/modes/interactive/components/bordered-loader.d.ts +1 -0
  141. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  142. package/dist/modes/interactive/components/bordered-loader.js +8 -0
  143. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  144. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  145. package/dist/modes/interactive/components/extension-editor.js +6 -15
  146. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  147. package/dist/modes/interactive/components/login-dialog.d.ts +3 -1
  148. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  149. package/dist/modes/interactive/components/login-dialog.js +20 -8
  150. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  151. package/dist/modes/interactive/components/profile-resource-editor.d.ts +4 -1
  152. package/dist/modes/interactive/components/profile-resource-editor.d.ts.map +1 -1
  153. package/dist/modes/interactive/components/profile-resource-editor.js +22 -39
  154. package/dist/modes/interactive/components/profile-resource-editor.js.map +1 -1
  155. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  156. package/dist/modes/interactive/components/session-selector.js +1 -1
  157. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  158. package/dist/modes/interactive/config-backup.d.ts +1 -0
  159. package/dist/modes/interactive/config-backup.d.ts.map +1 -1
  160. package/dist/modes/interactive/config-backup.js +14 -3
  161. package/dist/modes/interactive/config-backup.js.map +1 -1
  162. package/dist/modes/interactive/editor-overlay-host.d.ts +12 -0
  163. package/dist/modes/interactive/editor-overlay-host.d.ts.map +1 -1
  164. package/dist/modes/interactive/editor-overlay-host.js +55 -0
  165. package/dist/modes/interactive/editor-overlay-host.js.map +1 -1
  166. package/dist/modes/interactive/extension-ui-host.d.ts +2 -1
  167. package/dist/modes/interactive/extension-ui-host.d.ts.map +1 -1
  168. package/dist/modes/interactive/extension-ui-host.js +161 -96
  169. package/dist/modes/interactive/extension-ui-host.js.map +1 -1
  170. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  171. package/dist/modes/interactive/external-editor.js +23 -28
  172. package/dist/modes/interactive/external-editor.js.map +1 -1
  173. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  174. package/dist/modes/interactive/interactive-mode.js +14 -8
  175. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  176. package/dist/modes/interactive/profile-menu-controller.d.ts +5 -1
  177. package/dist/modes/interactive/profile-menu-controller.d.ts.map +1 -1
  178. package/dist/modes/interactive/profile-menu-controller.js +118 -24
  179. package/dist/modes/interactive/profile-menu-controller.js.map +1 -1
  180. package/dist/modes/interactive/resource-shell-commands.d.ts +1 -0
  181. package/dist/modes/interactive/resource-shell-commands.d.ts.map +1 -1
  182. package/dist/modes/interactive/resource-shell-commands.js +5 -1
  183. package/dist/modes/interactive/resource-shell-commands.js.map +1 -1
  184. package/dist/modes/interactive/session-flow-commands.d.ts.map +1 -1
  185. package/dist/modes/interactive/session-flow-commands.js +100 -7
  186. package/dist/modes/interactive/session-flow-commands.js.map +1 -1
  187. package/dist/modes/interactive/session-io-commands.d.ts.map +1 -1
  188. package/dist/modes/interactive/session-io-commands.js +80 -50
  189. package/dist/modes/interactive/session-io-commands.js.map +1 -1
  190. package/dist/modes/interactive/startup-checks.d.ts.map +1 -1
  191. package/dist/modes/interactive/startup-checks.js +14 -17
  192. package/dist/modes/interactive/startup-checks.js.map +1 -1
  193. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  194. package/dist/modes/rpc/rpc-client.js +20 -19
  195. package/dist/modes/rpc/rpc-client.js.map +1 -1
  196. package/dist/package-manager-cli.d.ts.map +1 -1
  197. package/dist/package-manager-cli.js +10 -19
  198. package/dist/package-manager-cli.js.map +1 -1
  199. package/dist/utils/child-process.d.ts +13 -7
  200. package/dist/utils/child-process.d.ts.map +1 -1
  201. package/dist/utils/child-process.js +56 -3
  202. package/dist/utils/child-process.js.map +1 -1
  203. package/dist/utils/clipboard-image.d.ts.map +1 -1
  204. package/dist/utils/clipboard-image.js +3 -2
  205. package/dist/utils/clipboard-image.js.map +1 -1
  206. package/dist/utils/clipboard.d.ts.map +1 -1
  207. package/dist/utils/clipboard.js +17 -10
  208. package/dist/utils/clipboard.js.map +1 -1
  209. package/dist/utils/external-editor-command.d.ts +8 -0
  210. package/dist/utils/external-editor-command.d.ts.map +1 -0
  211. package/dist/utils/external-editor-command.js +60 -0
  212. package/dist/utils/external-editor-command.js.map +1 -0
  213. package/dist/utils/paths.d.ts.map +1 -1
  214. package/dist/utils/paths.js +10 -2
  215. package/dist/utils/paths.js.map +1 -1
  216. package/dist/utils/tools-manager.d.ts.map +1 -1
  217. package/dist/utils/tools-manager.js +23 -10
  218. package/dist/utils/tools-manager.js.map +1 -1
  219. package/dist/utils/work-directory.d.ts +36 -0
  220. package/dist/utils/work-directory.d.ts.map +1 -0
  221. package/dist/utils/work-directory.js +462 -0
  222. package/dist/utils/work-directory.js.map +1 -0
  223. package/docs/index.md +2 -0
  224. package/docs/resources.md +2 -2
  225. package/docs/rpc.md +1 -1
  226. package/docs/tmux-agent-manager.md +48 -0
  227. package/docs/windows.md +100 -7
  228. package/docs/work-directory.md +41 -0
  229. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  230. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  231. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  232. package/examples/extensions/sandbox/package-lock.json +2 -2
  233. package/examples/extensions/sandbox/package.json +1 -1
  234. package/examples/extensions/with-deps/package-lock.json +2 -2
  235. package/examples/extensions/with-deps/package.json +1 -1
  236. package/npm-shrinkwrap.json +42 -42
  237. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"migrations.js","sourceRoot":"","sources":["../src/migrations.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * One-time migrations that run on startup.\n */\n\nimport chalk from \"chalk\";\nimport { chmodSync, existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { CONFIG_DIR_NAME, getAgentDir, getBinDir } from \"./config.ts\";\nimport { migrateKeybindingsConfig } from \"./core/keybindings.ts\";\nimport { isLegacyEnvVarNameConfigValue } from \"./core/resolve-config-value.ts\";\nimport { stripJsonComments } from \"./utils/json.ts\";\n\nconst MIGRATION_GUIDE_URL =\n\t\"https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/CHANGELOG.md#extensions-migration\";\nconst EXTENSIONS_DOC_URL =\n\t\"https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/docs/extensions.md\";\n\n/**\n * Migrate legacy oauth.json and settings.json apiKeys to auth.json.\n *\n * @returns Array of provider names that were migrated\n */\nexport function migrateAuthToAuthJson(): string[] {\n\tconst agentDir = getAgentDir();\n\tconst authPath = join(agentDir, \"auth.json\");\n\tconst oauthPath = join(agentDir, \"oauth.json\");\n\tconst settingsPath = join(agentDir, \"settings.json\");\n\n\t// Skip if auth.json already exists\n\tif (existsSync(authPath)) return [];\n\n\tconst migrated: Record<string, unknown> = {};\n\tconst providers: string[] = [];\n\n\t// Migrate oauth.json\n\tif (existsSync(oauthPath)) {\n\t\ttry {\n\t\t\tconst oauth = JSON.parse(readFileSync(oauthPath, \"utf-8\"));\n\t\t\tfor (const [provider, cred] of Object.entries(oauth)) {\n\t\t\t\tmigrated[provider] = { type: \"oauth\", ...(cred as object) };\n\t\t\t\tproviders.push(provider);\n\t\t\t}\n\t\t\trenameSync(oauthPath, `${oauthPath}.migrated`);\n\t\t} catch {\n\t\t\t// Skip on error\n\t\t}\n\t}\n\n\t// Migrate settings.json apiKeys\n\tif (existsSync(settingsPath)) {\n\t\ttry {\n\t\t\tconst content = readFileSync(settingsPath, \"utf-8\");\n\t\t\tconst settings = JSON.parse(content);\n\t\t\tif (settings.apiKeys && typeof settings.apiKeys === \"object\") {\n\t\t\t\tfor (const [provider, key] of Object.entries(settings.apiKeys)) {\n\t\t\t\t\tif (!migrated[provider] && typeof key === \"string\") {\n\t\t\t\t\t\tmigrated[provider] = { type: \"api_key\", key };\n\t\t\t\t\t\tproviders.push(provider);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdelete settings.apiKeys;\n\t\t\t\twriteFileSync(settingsPath, JSON.stringify(settings, null, 2));\n\t\t\t}\n\t\t} catch {\n\t\t\t// Skip on error\n\t\t}\n\t}\n\n\tif (Object.keys(migrated).length > 0) {\n\t\tmkdirSync(dirname(authPath), { recursive: true });\n\t\twriteFileSync(authPath, JSON.stringify(migrated, null, 2), { mode: 0o600 });\n\t}\n\n\treturn providers;\n}\n\ninterface ConfigValueMigration {\n\tlocation: string;\n\tfrom: string;\n\tto: string;\n}\n\nfunction migrateLegacyEnvVarString(value: string): string | undefined {\n\treturn isLegacyEnvVarNameConfigValue(value) ? `$${value}` : undefined;\n}\n\nfunction migrateStringProperty(\n\trecord: Record<string, unknown>,\n\tkey: string,\n\tlocation: string,\n\tmigrations: ConfigValueMigration[],\n): boolean {\n\tconst value = record[key];\n\tif (typeof value !== \"string\") return false;\n\tconst migrated = migrateLegacyEnvVarString(value);\n\tif (migrated === undefined) return false;\n\trecord[key] = migrated;\n\tmigrations.push({ location, from: value, to: migrated });\n\treturn true;\n}\n\nfunction migrateHeadersConfig(headers: unknown, location: string, migrations: ConfigValueMigration[]): boolean {\n\tif (typeof headers !== \"object\" || headers === null || Array.isArray(headers)) return false;\n\tconst headerRecord = headers as Record<string, unknown>;\n\tlet migrated = false;\n\tfor (const [key, value] of Object.entries(headerRecord)) {\n\t\tif (typeof value !== \"string\") continue;\n\t\tconst migratedValue = migrateLegacyEnvVarString(value);\n\t\tif (migratedValue === undefined) continue;\n\t\theaderRecord[key] = migratedValue;\n\t\tmigrations.push({ location: `${location}[${JSON.stringify(key)}]`, from: value, to: migratedValue });\n\t\tmigrated = true;\n\t}\n\treturn migrated;\n}\n\nfunction migrateAuthJsonConfigValues(agentDir: string): ConfigValueMigration[] {\n\tconst authPath = join(agentDir, \"auth.json\");\n\tif (!existsSync(authPath)) return [];\n\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(authPath, \"utf-8\")) as unknown;\n\t\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) return [];\n\t\tconst authData = parsed as Record<string, unknown>;\n\n\t\tconst migrations: ConfigValueMigration[] = [];\n\t\tfor (const [provider, credential] of Object.entries(authData)) {\n\t\t\tif (typeof credential !== \"object\" || credential === null || Array.isArray(credential)) continue;\n\t\t\tconst credentialRecord = credential as Record<string, unknown>;\n\t\t\tif (credentialRecord.type !== \"api_key\") continue;\n\t\t\tmigrateStringProperty(credentialRecord, \"key\", `auth.json[${JSON.stringify(provider)}].key`, migrations);\n\t\t}\n\n\t\tif (migrations.length === 0) return [];\n\t\twriteFileSync(authPath, `${JSON.stringify(parsed, null, 2)}\\n`, \"utf-8\");\n\t\tchmodSync(authPath, 0o600);\n\t\treturn migrations;\n\t} catch {\n\t\treturn [];\n\t}\n}\n\nfunction migrateModelsJsonConfigValues(agentDir: string): ConfigValueMigration[] {\n\tconst modelsPath = join(agentDir, \"models.json\");\n\tif (!existsSync(modelsPath)) return [];\n\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(stripJsonComments(readFileSync(modelsPath, \"utf-8\"))) as unknown;\n\t} catch {\n\t\treturn [];\n\t}\n\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) return [];\n\tconst modelsData = parsed as Record<string, unknown>;\n\tconst providers = modelsData.providers;\n\tif (typeof providers !== \"object\" || providers === null || Array.isArray(providers)) return [];\n\n\tconst migrations: ConfigValueMigration[] = [];\n\tfor (const [provider, providerConfig] of Object.entries(providers)) {\n\t\tif (typeof providerConfig !== \"object\" || providerConfig === null || Array.isArray(providerConfig)) continue;\n\t\tconst providerRecord = providerConfig as Record<string, unknown>;\n\t\tconst providerLocation = `models.json.providers[${JSON.stringify(provider)}]`;\n\t\tmigrateStringProperty(providerRecord, \"apiKey\", `${providerLocation}.apiKey`, migrations);\n\t\tmigrateHeadersConfig(providerRecord.headers, `${providerLocation}.headers`, migrations);\n\n\t\tif (Array.isArray(providerRecord.models)) {\n\t\t\tfor (let index = 0; index < providerRecord.models.length; index++) {\n\t\t\t\tconst modelConfig = providerRecord.models[index];\n\t\t\t\tif (typeof modelConfig !== \"object\" || modelConfig === null || Array.isArray(modelConfig)) continue;\n\t\t\t\tconst modelRecord = modelConfig as Record<string, unknown>;\n\t\t\t\tconst modelKey = typeof modelRecord.id === \"string\" ? JSON.stringify(modelRecord.id) : String(index);\n\t\t\t\tmigrateHeadersConfig(modelRecord.headers, `${providerLocation}.models[${modelKey}].headers`, migrations);\n\t\t\t}\n\t\t}\n\n\t\tconst modelOverrides = providerRecord.modelOverrides;\n\t\tif (typeof modelOverrides === \"object\" && modelOverrides !== null && !Array.isArray(modelOverrides)) {\n\t\t\tfor (const [modelId, modelOverride] of Object.entries(modelOverrides)) {\n\t\t\t\tif (typeof modelOverride !== \"object\" || modelOverride === null || Array.isArray(modelOverride)) continue;\n\t\t\t\tconst modelOverrideRecord = modelOverride as Record<string, unknown>;\n\t\t\t\tmigrateHeadersConfig(\n\t\t\t\t\tmodelOverrideRecord.headers,\n\t\t\t\t\t`${providerLocation}.modelOverrides[${JSON.stringify(modelId)}].headers`,\n\t\t\t\t\tmigrations,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (migrations.length === 0) return [];\n\twriteFileSync(modelsPath, `${JSON.stringify(parsed, null, 2)}\\n`, \"utf-8\");\n\treturn migrations;\n}\n\nfunction migrateExplicitEnvVarConfigValues(): void {\n\tconst agentDir = getAgentDir();\n\tconst migrations = [...migrateAuthJsonConfigValues(agentDir), ...migrateModelsJsonConfigValues(agentDir)];\n\tif (migrations.length === 0) return;\n\n\tconst details = migrations.map((migration) => ` - ${migration.location}: ${migration.from} -> ${migration.to}`);\n\tconsole.log(\n\t\tchalk.yellow(\n\t\t\t[\n\t\t\t\t\"Warning: Migrated API key/header environment references to explicit $ENV_VAR syntax. Plain strings will be treated as literals.\",\n\t\t\t\t...details,\n\t\t\t].join(\"\\n\"),\n\t\t),\n\t);\n}\n\n/**\n * Migrate sessions from ~/.pi/agent/*.jsonl to proper session directories.\n *\n * Bug in v0.30.0: Sessions were saved to ~/.pi/agent/ instead of\n * ~/.pi/agent/sessions/<encoded-cwd>/. This migration moves them\n * to the correct location based on the cwd in their session header.\n *\n * See: https://github.com/earendil-works/pi-mono/issues/320\n */\nexport function getMigratedSessionFileName(file: string): string | undefined {\n\tconst fileName = file.split(/[\\\\/]/).pop();\n\treturn fileName || undefined;\n}\n\nexport function migrateSessionsFromAgentRoot(): void {\n\tconst agentDir = getAgentDir();\n\n\t// Find all .jsonl files directly in agentDir (not in subdirectories)\n\tlet files: string[];\n\ttry {\n\t\tfiles = readdirSync(agentDir)\n\t\t\t.filter((f) => f.endsWith(\".jsonl\"))\n\t\t\t.map((f) => join(agentDir, f));\n\t} catch {\n\t\treturn;\n\t}\n\n\tif (files.length === 0) return;\n\n\tfor (const file of files) {\n\t\ttry {\n\t\t\t// Read first line to get session header\n\t\t\tconst content = readFileSync(file, \"utf8\");\n\t\t\tconst firstLine = content.split(\"\\n\")[0];\n\t\t\tif (!firstLine?.trim()) continue;\n\n\t\t\tconst header = JSON.parse(firstLine);\n\t\t\tif (header.type !== \"session\" || !header.cwd) continue;\n\n\t\t\tconst cwd: string = header.cwd;\n\n\t\t\t// Compute the correct session directory (same encoding as session-manager.ts)\n\t\t\tconst safePath = `--${cwd.replace(/^[/\\\\]/, \"\").replace(/[/\\\\:]/g, \"-\")}--`;\n\t\t\tconst correctDir = join(agentDir, \"sessions\", safePath);\n\n\t\t\t// Create directory if needed\n\t\t\tif (!existsSync(correctDir)) {\n\t\t\t\tmkdirSync(correctDir, { recursive: true });\n\t\t\t}\n\n\t\t\t// Move the file\n\t\t\tconst fileName = getMigratedSessionFileName(file);\n\t\t\tif (!fileName) continue;\n\t\t\tconst newPath = join(correctDir, fileName);\n\n\t\t\tif (existsSync(newPath)) continue; // Skip if target exists\n\n\t\t\trenameSync(file, newPath);\n\t\t} catch {\n\t\t\t// Skip files that can't be migrated\n\t\t}\n\t}\n}\n\n/**\n * Migrate commands/ to prompts/ if needed.\n * Works for both regular directories and symlinks.\n */\nfunction migrateCommandsToPrompts(baseDir: string, label: string): boolean {\n\tconst commandsDir = join(baseDir, \"commands\");\n\tconst promptsDir = join(baseDir, \"prompts\");\n\n\tif (existsSync(commandsDir) && !existsSync(promptsDir)) {\n\t\ttry {\n\t\t\trenameSync(commandsDir, promptsDir);\n\t\t\tconsole.log(chalk.green(`Migrated ${label} commands/ → prompts/`));\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\tconsole.log(\n\t\t\t\tchalk.yellow(\n\t\t\t\t\t`Warning: Could not migrate ${label} commands/ to prompts/: ${err instanceof Error ? err.message : err}`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\treturn false;\n}\n\nfunction migrateKeybindingsConfigFile(): void {\n\tconst configPath = join(getAgentDir(), \"keybindings.json\");\n\tif (!existsSync(configPath)) return;\n\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(configPath, \"utf-8\")) as unknown;\n\t\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n\t\t\treturn;\n\t\t}\n\t\tconst { config, migrated } = migrateKeybindingsConfig(parsed as Record<string, unknown>);\n\t\tif (!migrated) return;\n\t\twriteFileSync(configPath, `${JSON.stringify(config, null, 2)}\\n`, \"utf-8\");\n\t} catch {\n\t\t// Ignore malformed files during migration\n\t}\n}\n\n/**\n * Move fd/rg binaries from tools/ to bin/ if they exist.\n */\nfunction migrateToolsToBin(): void {\n\tconst agentDir = getAgentDir();\n\tconst toolsDir = join(agentDir, \"tools\");\n\tconst binDir = getBinDir();\n\n\tif (!existsSync(toolsDir)) return;\n\n\tconst binaries = [\"fd\", \"rg\", \"fd.exe\", \"rg.exe\"];\n\tlet movedAny = false;\n\n\tfor (const bin of binaries) {\n\t\tconst oldPath = join(toolsDir, bin);\n\t\tconst newPath = join(binDir, bin);\n\n\t\tif (existsSync(oldPath)) {\n\t\t\tif (!existsSync(binDir)) {\n\t\t\t\tmkdirSync(binDir, { recursive: true });\n\t\t\t}\n\t\t\tif (!existsSync(newPath)) {\n\t\t\t\ttry {\n\t\t\t\t\trenameSync(oldPath, newPath);\n\t\t\t\t\tmovedAny = true;\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore errors\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Target exists, just delete the old one\n\t\t\t\ttry {\n\t\t\t\t\trmSync?.(oldPath, { force: true });\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (movedAny) {\n\t\tconsole.log(chalk.green(`Migrated managed binaries tools/ → bin/`));\n\t}\n}\n\n/**\n * Check for deprecated hooks/ and tools/ directories.\n * Note: tools/ may contain fd/rg binaries extracted by pi, so only warn if it has other files.\n */\nfunction checkDeprecatedExtensionDirs(baseDir: string, label: string): string[] {\n\tconst hooksDir = join(baseDir, \"hooks\");\n\tconst toolsDir = join(baseDir, \"tools\");\n\tconst warnings: string[] = [];\n\n\tif (existsSync(hooksDir)) {\n\t\twarnings.push(`${label} hooks/ directory found. Hooks have been renamed to extensions.`);\n\t}\n\n\tif (existsSync(toolsDir)) {\n\t\t// Check if tools/ contains anything other than fd/rg (which are auto-extracted binaries)\n\t\ttry {\n\t\t\tconst entries = readdirSync(toolsDir);\n\t\t\tconst customTools = entries.filter((e) => {\n\t\t\t\tconst lower = e.toLowerCase();\n\t\t\t\treturn (\n\t\t\t\t\tlower !== \"fd\" && lower !== \"rg\" && lower !== \"fd.exe\" && lower !== \"rg.exe\" && !e.startsWith(\".\") // Ignore .DS_Store and other hidden files\n\t\t\t\t);\n\t\t\t});\n\t\t\tif (customTools.length > 0) {\n\t\t\t\twarnings.push(\n\t\t\t\t\t`${label} tools/ directory contains custom tools. Custom tools have been merged into extensions.`,\n\t\t\t\t);\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore read errors\n\t\t}\n\t}\n\n\treturn warnings;\n}\n\n/**\n * Run extension system migrations (commands→prompts) and collect warnings about deprecated directories.\n */\nfunction migrateExtensionSystem(cwd: string): string[] {\n\tconst agentDir = getAgentDir();\n\tconst projectDir = join(cwd, CONFIG_DIR_NAME);\n\n\t// Migrate commands/ to prompts/\n\tmigrateCommandsToPrompts(agentDir, \"Global\");\n\tmigrateCommandsToPrompts(projectDir, \"Project\");\n\n\t// Check for deprecated directories\n\tconst warnings = [\n\t\t...checkDeprecatedExtensionDirs(agentDir, \"Global\"),\n\t\t...checkDeprecatedExtensionDirs(projectDir, \"Project\"),\n\t];\n\n\treturn warnings;\n}\n\n/**\n * Print deprecation warnings and wait for keypress.\n */\nexport async function showDeprecationWarnings(warnings: string[]): Promise<void> {\n\tif (warnings.length === 0) return;\n\n\tfor (const warning of warnings) {\n\t\tconsole.log(chalk.yellow(`Warning: ${warning}`));\n\t}\n\tconsole.log(chalk.yellow(`\\nMove your extensions to the extensions/ directory.`));\n\tconsole.log(chalk.yellow(`Migration guide: ${MIGRATION_GUIDE_URL}`));\n\tconsole.log(chalk.yellow(`Documentation: ${EXTENSIONS_DOC_URL}`));\n\tconsole.log(chalk.dim(`\\nPress any key to continue...`));\n\n\tawait new Promise<void>((resolve) => {\n\t\tprocess.stdin.setRawMode?.(true);\n\t\tprocess.stdin.resume();\n\t\tprocess.stdin.once(\"data\", () => {\n\t\t\tprocess.stdin.setRawMode?.(false);\n\t\t\tprocess.stdin.pause();\n\t\t\tresolve();\n\t\t});\n\t});\n\tconsole.log();\n}\n\n/**\n * Run all migrations. Called once on startup.\n *\n * @returns Object with migration results and deprecation warnings\n */\nexport function runMigrations(cwd: string): {\n\tmigratedAuthProviders: string[];\n\tdeprecationWarnings: string[];\n} {\n\tconst migratedAuthProviders = migrateAuthToAuthJson();\n\tmigrateExplicitEnvVarConfigValues();\n\tmigrateSessionsFromAgentRoot();\n\tmigrateToolsToBin();\n\tmigrateKeybindingsConfigFile();\n\tconst deprecationWarnings = migrateExtensionSystem(cwd);\n\treturn { migratedAuthProviders, deprecationWarnings };\n}\n"]}
1
+ {"version":3,"file":"migrations.js","sourceRoot":"","sources":["../src/migrations.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * One-time migrations that run on startup.\n */\n\nimport chalk from \"chalk\";\nimport { chmodSync, existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { CONFIG_DIR_NAME, getAgentDir, getBinDir } from \"./config.ts\";\nimport { migrateKeybindingsConfig } from \"./core/keybindings.ts\";\nimport { isLegacyEnvVarNameConfigValue } from \"./core/resolve-config-value.ts\";\nimport { stripJsonComments } from \"./utils/json.ts\";\n\nconst MIGRATION_GUIDE_URL =\n\t\"https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/CHANGELOG.md#extensions-migration\";\nconst EXTENSIONS_DOC_URL =\n\t\"https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/docs/extensions.md\";\n\n/**\n * Migrate legacy oauth.json and settings.json apiKeys to auth.json.\n *\n * @returns Array of provider names that were migrated\n */\nexport function migrateAuthToAuthJson(): string[] {\n\tconst agentDir = getAgentDir();\n\tconst authPath = join(agentDir, \"auth.json\");\n\tconst oauthPath = join(agentDir, \"oauth.json\");\n\tconst settingsPath = join(agentDir, \"settings.json\");\n\n\t// Skip if auth.json already exists\n\tif (existsSync(authPath)) return [];\n\n\tconst migrated: Record<string, unknown> = {};\n\tconst providers: string[] = [];\n\n\t// Migrate oauth.json\n\tif (existsSync(oauthPath)) {\n\t\ttry {\n\t\t\tconst oauth = JSON.parse(readFileSync(oauthPath, \"utf-8\"));\n\t\t\tfor (const [provider, cred] of Object.entries(oauth)) {\n\t\t\t\tmigrated[provider] = { type: \"oauth\", ...(cred as object) };\n\t\t\t\tproviders.push(provider);\n\t\t\t}\n\t\t\trenameSync(oauthPath, `${oauthPath}.migrated`);\n\t\t} catch {\n\t\t\t// Skip on error\n\t\t}\n\t}\n\n\t// Migrate settings.json apiKeys\n\tif (existsSync(settingsPath)) {\n\t\ttry {\n\t\t\tconst content = readFileSync(settingsPath, \"utf-8\");\n\t\t\tconst settings = JSON.parse(content);\n\t\t\tif (settings.apiKeys && typeof settings.apiKeys === \"object\") {\n\t\t\t\tfor (const [provider, key] of Object.entries(settings.apiKeys)) {\n\t\t\t\t\tif (!migrated[provider] && typeof key === \"string\") {\n\t\t\t\t\t\tmigrated[provider] = { type: \"api_key\", key };\n\t\t\t\t\t\tproviders.push(provider);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdelete settings.apiKeys;\n\t\t\t\twriteFileSync(settingsPath, JSON.stringify(settings, null, 2));\n\t\t\t}\n\t\t} catch {\n\t\t\t// Skip on error\n\t\t}\n\t}\n\n\tif (Object.keys(migrated).length > 0) {\n\t\tmkdirSync(dirname(authPath), { recursive: true });\n\t\twriteFileSync(authPath, JSON.stringify(migrated, null, 2), { mode: 0o600 });\n\t}\n\n\treturn providers;\n}\n\ninterface ConfigValueMigration {\n\tlocation: string;\n\tfrom: string;\n\tto: string;\n}\n\nfunction migrateLegacyEnvVarString(value: string): string | undefined {\n\treturn isLegacyEnvVarNameConfigValue(value) ? `$${value}` : undefined;\n}\n\nfunction migrateStringProperty(\n\trecord: Record<string, unknown>,\n\tkey: string,\n\tlocation: string,\n\tmigrations: ConfigValueMigration[],\n): boolean {\n\tconst value = record[key];\n\tif (typeof value !== \"string\") return false;\n\tconst migrated = migrateLegacyEnvVarString(value);\n\tif (migrated === undefined) return false;\n\trecord[key] = migrated;\n\tmigrations.push({ location, from: value, to: migrated });\n\treturn true;\n}\n\nfunction migrateHeadersConfig(headers: unknown, location: string, migrations: ConfigValueMigration[]): boolean {\n\tif (typeof headers !== \"object\" || headers === null || Array.isArray(headers)) return false;\n\tconst headerRecord = headers as Record<string, unknown>;\n\tlet migrated = false;\n\tfor (const [key, value] of Object.entries(headerRecord)) {\n\t\tif (typeof value !== \"string\") continue;\n\t\tconst migratedValue = migrateLegacyEnvVarString(value);\n\t\tif (migratedValue === undefined) continue;\n\t\theaderRecord[key] = migratedValue;\n\t\tmigrations.push({ location: `${location}[${JSON.stringify(key)}]`, from: value, to: migratedValue });\n\t\tmigrated = true;\n\t}\n\treturn migrated;\n}\n\nfunction migrateAuthJsonConfigValues(agentDir: string): ConfigValueMigration[] {\n\tconst authPath = join(agentDir, \"auth.json\");\n\tif (!existsSync(authPath)) return [];\n\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(authPath, \"utf-8\")) as unknown;\n\t\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) return [];\n\t\tconst authData = parsed as Record<string, unknown>;\n\n\t\tconst migrations: ConfigValueMigration[] = [];\n\t\tfor (const [provider, credential] of Object.entries(authData)) {\n\t\t\tif (typeof credential !== \"object\" || credential === null || Array.isArray(credential)) continue;\n\t\t\tconst credentialRecord = credential as Record<string, unknown>;\n\t\t\tif (credentialRecord.type !== \"api_key\") continue;\n\t\t\tmigrateStringProperty(credentialRecord, \"key\", `auth.json[${JSON.stringify(provider)}].key`, migrations);\n\t\t}\n\n\t\tif (migrations.length === 0) return [];\n\t\twriteFileSync(authPath, `${JSON.stringify(parsed, null, 2)}\\n`, \"utf-8\");\n\t\tchmodSync(authPath, 0o600);\n\t\treturn migrations;\n\t} catch {\n\t\treturn [];\n\t}\n}\n\nfunction migrateModelsJsonConfigValues(agentDir: string): ConfigValueMigration[] {\n\tconst modelsPath = join(agentDir, \"models.json\");\n\tif (!existsSync(modelsPath)) return [];\n\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(stripJsonComments(readFileSync(modelsPath, \"utf-8\"))) as unknown;\n\t} catch {\n\t\treturn [];\n\t}\n\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) return [];\n\tconst modelsData = parsed as Record<string, unknown>;\n\tconst providers = modelsData.providers;\n\tif (typeof providers !== \"object\" || providers === null || Array.isArray(providers)) return [];\n\n\tconst migrations: ConfigValueMigration[] = [];\n\tfor (const [provider, providerConfig] of Object.entries(providers)) {\n\t\tif (typeof providerConfig !== \"object\" || providerConfig === null || Array.isArray(providerConfig)) continue;\n\t\tconst providerRecord = providerConfig as Record<string, unknown>;\n\t\tconst providerLocation = `models.json.providers[${JSON.stringify(provider)}]`;\n\t\tmigrateStringProperty(providerRecord, \"apiKey\", `${providerLocation}.apiKey`, migrations);\n\t\tmigrateHeadersConfig(providerRecord.headers, `${providerLocation}.headers`, migrations);\n\n\t\tif (Array.isArray(providerRecord.models)) {\n\t\t\tfor (let index = 0; index < providerRecord.models.length; index++) {\n\t\t\t\tconst modelConfig = providerRecord.models[index];\n\t\t\t\tif (typeof modelConfig !== \"object\" || modelConfig === null || Array.isArray(modelConfig)) continue;\n\t\t\t\tconst modelRecord = modelConfig as Record<string, unknown>;\n\t\t\t\tconst modelKey = typeof modelRecord.id === \"string\" ? JSON.stringify(modelRecord.id) : String(index);\n\t\t\t\tmigrateHeadersConfig(modelRecord.headers, `${providerLocation}.models[${modelKey}].headers`, migrations);\n\t\t\t}\n\t\t}\n\n\t\tconst modelOverrides = providerRecord.modelOverrides;\n\t\tif (typeof modelOverrides === \"object\" && modelOverrides !== null && !Array.isArray(modelOverrides)) {\n\t\t\tfor (const [modelId, modelOverride] of Object.entries(modelOverrides)) {\n\t\t\t\tif (typeof modelOverride !== \"object\" || modelOverride === null || Array.isArray(modelOverride)) continue;\n\t\t\t\tconst modelOverrideRecord = modelOverride as Record<string, unknown>;\n\t\t\t\tmigrateHeadersConfig(\n\t\t\t\t\tmodelOverrideRecord.headers,\n\t\t\t\t\t`${providerLocation}.modelOverrides[${JSON.stringify(modelId)}].headers`,\n\t\t\t\t\tmigrations,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (migrations.length === 0) return [];\n\twriteFileSync(modelsPath, `${JSON.stringify(parsed, null, 2)}\\n`, \"utf-8\");\n\treturn migrations;\n}\n\nfunction migrateExplicitEnvVarConfigValues(): void {\n\tconst agentDir = getAgentDir();\n\tconst migrations = [...migrateAuthJsonConfigValues(agentDir), ...migrateModelsJsonConfigValues(agentDir)];\n\tif (migrations.length === 0) return;\n\n\tconst details = migrations.map((migration) => ` - ${migration.location}: ${migration.from} -> ${migration.to}`);\n\tconsole.log(\n\t\tchalk.yellow(\n\t\t\t[\n\t\t\t\t\"Warning: Migrated API key/header environment references to explicit $ENV_VAR syntax. Plain strings will be treated as literals.\",\n\t\t\t\t...details,\n\t\t\t].join(\"\\n\"),\n\t\t),\n\t);\n}\n\n/**\n * Migrate sessions from ~/.pi/agent/*.jsonl to proper session directories.\n *\n * Bug in v0.30.0: Sessions were saved to ~/.pi/agent/ instead of\n * ~/.pi/agent/sessions/<encoded-cwd>/. This migration moves them\n * to the correct location based on the cwd in their session header.\n *\n * See: https://github.com/earendil-works/pi-mono/issues/320\n */\nexport function getMigratedSessionFileName(file: string): string | undefined {\n\tconst fileName = file.split(/[\\\\/]/).pop();\n\treturn fileName || undefined;\n}\n\nexport function migrateSessionsFromAgentRoot(): void {\n\tconst agentDir = getAgentDir();\n\n\t// Find all .jsonl files directly in agentDir (not in subdirectories)\n\tlet files: string[];\n\ttry {\n\t\tfiles = readdirSync(agentDir)\n\t\t\t.filter((f) => f.endsWith(\".jsonl\"))\n\t\t\t.map((f) => join(agentDir, f));\n\t} catch {\n\t\treturn;\n\t}\n\n\tif (files.length === 0) return;\n\n\tfor (const file of files) {\n\t\ttry {\n\t\t\t// Read first line to get session header\n\t\t\tconst content = readFileSync(file, \"utf8\");\n\t\t\tconst firstLine = content.split(\"\\n\")[0];\n\t\t\tif (!firstLine?.trim()) continue;\n\n\t\t\tconst header = JSON.parse(firstLine);\n\t\t\tif (header.type !== \"session\" || !header.cwd) continue;\n\n\t\t\tconst cwd: string = header.cwd;\n\n\t\t\t// Compute the correct session directory (same encoding as session-manager.ts)\n\t\t\tconst safePath = `--${cwd.replace(/^[/\\\\]/, \"\").replace(/[/\\\\:]/g, \"-\")}--`;\n\t\t\tconst correctDir = join(agentDir, \"sessions\", safePath);\n\n\t\t\t// Create directory if needed\n\t\t\tif (!existsSync(correctDir)) {\n\t\t\t\tmkdirSync(correctDir, { recursive: true });\n\t\t\t}\n\n\t\t\t// Move the file\n\t\t\tconst fileName = getMigratedSessionFileName(file);\n\t\t\tif (!fileName) continue;\n\t\t\tconst newPath = join(correctDir, fileName);\n\n\t\t\tif (existsSync(newPath)) continue; // Skip if target exists\n\n\t\t\trenameSync(file, newPath);\n\t\t} catch {\n\t\t\t// Skip files that can't be migrated\n\t\t}\n\t}\n}\n\n/**\n * Migrate commands/ to prompts/ if needed.\n * Works for both regular directories and symlinks.\n */\nfunction migrateCommandsToPrompts(baseDir: string, label: string): boolean {\n\tconst commandsDir = join(baseDir, \"commands\");\n\tconst promptsDir = join(baseDir, \"prompts\");\n\n\tif (existsSync(commandsDir) && !existsSync(promptsDir)) {\n\t\ttry {\n\t\t\trenameSync(commandsDir, promptsDir);\n\t\t\tconsole.log(chalk.green(`Migrated ${label} commands/ → prompts/`));\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\tconsole.log(\n\t\t\t\tchalk.yellow(\n\t\t\t\t\t`Warning: Could not migrate ${label} commands/ to prompts/: ${err instanceof Error ? err.message : err}`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\treturn false;\n}\n\nfunction migrateKeybindingsConfigFile(): void {\n\tconst configPath = join(getAgentDir(), \"keybindings.json\");\n\tif (!existsSync(configPath)) return;\n\n\ttry {\n\t\tconst parsed = JSON.parse(readFileSync(configPath, \"utf-8\")) as unknown;\n\t\tif (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n\t\t\treturn;\n\t\t}\n\t\tconst { config, migrated } = migrateKeybindingsConfig(parsed as Record<string, unknown>);\n\t\tif (!migrated) return;\n\t\twriteFileSync(configPath, `${JSON.stringify(config, null, 2)}\\n`, \"utf-8\");\n\t} catch {\n\t\t// Ignore malformed files during migration\n\t}\n}\n\n/**\n * Move fd/rg binaries from tools/ to bin/ if they exist.\n */\nfunction migrateToolsToBin(): void {\n\tconst agentDir = getAgentDir();\n\tconst toolsDir = join(agentDir, \"tools\");\n\tconst binDir = getBinDir();\n\n\tif (!existsSync(toolsDir)) return;\n\n\tconst binaries = [\"fd\", \"rg\", \"fd.exe\", \"rg.exe\"];\n\tlet movedAny = false;\n\n\tfor (const bin of binaries) {\n\t\tconst oldPath = join(toolsDir, bin);\n\t\tconst newPath = join(binDir, bin);\n\n\t\tif (existsSync(oldPath)) {\n\t\t\tif (!existsSync(binDir)) {\n\t\t\t\tmkdirSync(binDir, { recursive: true });\n\t\t\t}\n\t\t\tif (!existsSync(newPath)) {\n\t\t\t\ttry {\n\t\t\t\t\trenameSync(oldPath, newPath);\n\t\t\t\t\tmovedAny = true;\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore errors\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Target exists, just delete the old one\n\t\t\t\ttry {\n\t\t\t\t\trmSync?.(oldPath, { force: true });\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (movedAny) {\n\t\tconsole.log(chalk.green(`Migrated managed binaries tools/ → bin/`));\n\t}\n}\n\n/**\n * Check for deprecated hooks/ and tools/ directories.\n * Note: tools/ may contain fd/rg binaries extracted by pi, so only warn if it has other files.\n */\nfunction checkDeprecatedExtensionDirs(baseDir: string, label: string): string[] {\n\tconst hooksDir = join(baseDir, \"hooks\");\n\tconst toolsDir = join(baseDir, \"tools\");\n\tconst warnings: string[] = [];\n\n\tif (existsSync(hooksDir)) {\n\t\twarnings.push(`${label} hooks/ directory found. Hooks have been renamed to extensions.`);\n\t}\n\n\tif (existsSync(toolsDir)) {\n\t\t// Check if tools/ contains anything other than fd/rg (which are auto-extracted binaries)\n\t\ttry {\n\t\t\tconst entries = readdirSync(toolsDir);\n\t\t\tconst customTools = entries.filter((e) => {\n\t\t\t\tconst lower = e.toLowerCase();\n\t\t\t\treturn (\n\t\t\t\t\tlower !== \"fd\" && lower !== \"rg\" && lower !== \"fd.exe\" && lower !== \"rg.exe\" && !e.startsWith(\".\") // Ignore .DS_Store and other hidden files\n\t\t\t\t);\n\t\t\t});\n\t\t\tif (customTools.length > 0) {\n\t\t\t\twarnings.push(\n\t\t\t\t\t`${label} tools/ directory contains custom tools. Custom tools have been merged into extensions.`,\n\t\t\t\t);\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore read errors\n\t\t}\n\t}\n\n\treturn warnings;\n}\n\n/**\n * Run extension system migrations (commands→prompts) and collect warnings about deprecated directories.\n */\nfunction migrateExtensionSystem(cwd: string): string[] {\n\tconst agentDir = getAgentDir();\n\tconst projectDir = join(cwd, CONFIG_DIR_NAME);\n\n\t// Migrate commands/ to prompts/\n\tmigrateCommandsToPrompts(agentDir, \"Global\");\n\tmigrateCommandsToPrompts(projectDir, \"Project\");\n\n\t// Check for deprecated directories\n\tconst warnings = [\n\t\t...checkDeprecatedExtensionDirs(agentDir, \"Global\"),\n\t\t...checkDeprecatedExtensionDirs(projectDir, \"Project\"),\n\t];\n\n\treturn warnings;\n}\n\n/**\n * Print deprecation warnings and wait for keypress.\n */\nexport async function showDeprecationWarnings(warnings: string[]): Promise<void> {\n\tif (warnings.length === 0) return;\n\n\tfor (const warning of warnings) {\n\t\tconsole.log(chalk.yellow(`Warning: ${warning}`));\n\t}\n\tconsole.log(chalk.yellow(`\\nMove your extensions to the extensions/ directory.`));\n\tconsole.log(chalk.yellow(`Migration guide: ${MIGRATION_GUIDE_URL}`));\n\tconsole.log(chalk.yellow(`Documentation: ${EXTENSIONS_DOC_URL}`));\n\tif (!process.stdin.isTTY || !process.stdout.isTTY) {\n\t\tconsole.log();\n\t\treturn;\n\t}\n\tconsole.log(chalk.dim(`\\nPress any key to continue...`));\n\n\tawait new Promise<void>((resolve) => {\n\t\tlet settled = false;\n\t\tconst finish = () => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\tprocess.stdin.removeListener(\"data\", finish);\n\t\t\tprocess.stdin.removeListener(\"end\", finish);\n\t\t\tprocess.stdin.removeListener(\"error\", finish);\n\t\t\tprocess.stdin.setRawMode?.(false);\n\t\t\tprocess.stdin.pause();\n\t\t\tresolve();\n\t\t};\n\t\tprocess.stdin.setRawMode?.(true);\n\t\tprocess.stdin.resume();\n\t\tprocess.stdin.once(\"data\", finish);\n\t\tprocess.stdin.once(\"end\", finish);\n\t\tprocess.stdin.once(\"error\", finish);\n\t});\n\tconsole.log();\n}\n\n/**\n * Run all migrations. Called once on startup.\n *\n * @returns Object with migration results and deprecation warnings\n */\nexport function runMigrations(cwd: string): {\n\tmigratedAuthProviders: string[];\n\tdeprecationWarnings: string[];\n} {\n\tconst migratedAuthProviders = migrateAuthToAuthJson();\n\tmigrateExplicitEnvVarConfigValues();\n\tmigrateSessionsFromAgentRoot();\n\tmigrateToolsToBin();\n\tmigrateKeybindingsConfigFile();\n\tconst deprecationWarnings = migrateExtensionSystem(cwd);\n\treturn { migratedAuthProviders, deprecationWarnings };\n}\n"]}
@@ -40,9 +40,19 @@ export interface AuthDialogsControllerDeps {
40
40
  }
41
41
  export declare class AuthDialogsController {
42
42
  private readonly deps;
43
+ private activeLoginDialog;
44
+ private activeLoginDialogOnUnmount;
45
+ private suppressActiveLoginDialogUnmount;
46
+ private activeOAuthSelectorCancel;
43
47
  constructor(deps: AuthDialogsControllerDeps);
44
48
  private get session();
45
49
  private get ui();
50
+ cancelActiveDialog(): void;
51
+ private clearActiveDialog;
52
+ private mountLoginDialog;
53
+ private restoreEditorFromDialog;
54
+ private detachLoginDialogForSelector;
55
+ private remountLoginDialog;
46
56
  private getLoginProviderOptions;
47
57
  private getLogoutProviderOptions;
48
58
  private resolveAuthProviderOption;
@@ -1 +1 @@
1
- {"version":3,"file":"auth-dialogs-controller.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/auth-dialogs-controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAgB,KAAK,KAAK,EAAgD,MAAM,mBAAmB,CAAC;AAC3G,OAAO,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAMhE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAelE,wBAAgB,qBAAqB,CACpC,UAAU,EAAE,MAAM,EAClB,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAAC,EACrC,kBAAkB,GAAE,WAAW,CAAC,MAAM,CAA4B,GAChE,OAAO,CAQT;AAED,MAAM,WAAW,uBAAuB;IACvC,YAAY,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,IAAI,KAAK;QAAE,SAAS,EAAE,SAAS,CAAC;QAAC,KAAK,EAAE,SAAS,CAAA;KAAE,GAAG,IAAI,CAAC;IAC7F,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,aAAa,IAAI,IAAI,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,QAAQ,CAAC,WAAW,EAAE,iBAAiB,CAAC;IACxC,SAAS,IAAI,SAAS,CAAC;IACvB,4BAA4B,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,gBAAgB,IAAI,IAAI,CAAC;IACzB,uBAAuB,IAAI,IAAI,CAAC;IAChC,uCAAuC,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;IAClE,qBAAqB,CAAC,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CACrE;AAED,MAAM,WAAW,yBAAyB;IACzC,UAAU,IAAI,YAAY,CAAC;IAC3B,EAAE,EAAE,uBAAuB,CAAC;CAC5B;AAED,qBAAa,qBAAqB;IACjC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA4B;IAEjD,YAAY,IAAI,EAAE,yBAAyB,EAE1C;IAED,OAAO,KAAK,OAAO,GAElB;IACD,OAAO,KAAK,EAAE,GAEb;IAED,OAAO,CAAC,uBAAuB;IA0B/B,OAAO,CAAC,wBAAwB;IAmBhC,OAAO,CAAC,yBAAyB;YAoBnB,kBAAkB;IAUhC,OAAO,CAAC,yBAAyB;IAqBjC,OAAO,CAAC,yBAAyB;IAkC3B,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,EAAE,iBAAiB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkF3F;YAEa,8BAA8B;IAqD5C,OAAO,CAAC,sBAAsB;YAsBhB,qBAAqB;IAqCnC,OAAO,CAAC,oBAAoB;YAsBd,eAAe;CA2F7B","sourcesContent":["/**\n * Auth / login / OAuth dialog controller.\n *\n * Extracted verbatim from interactive-mode.ts (god-file decomposition). Owns the /login and /logout\n * command flows: provider selection, subscription (OAuth) login dialogs, API-key login dialogs, the\n * Amazon Bedrock setup notice, the OAuth in-dialog select prompt, and post-login model adoption. It\n * holds NO state of its own — every credential/provider fact lives in session.modelRegistry.authStorage\n * — so it takes narrow deps (a live session accessor plus a UI callback surface, including the\n * editor-overlay-backed showSelector and the shared EditorOverlayHost for dialog swaps) rather than\n * the whole InteractiveMode instance.\n */\n\nimport * as path from \"node:path\";\nimport { getProviders, type Model, type OAuthProviderId, type OAuthSelectPrompt } from \"@caupulican/pi-ai\";\nimport type { Component, TUI } from \"@caupulican/pi-tui\";\nimport { getAuthPath, getDocsPath } from \"../../config.ts\";\nimport type { AgentSession } from \"../../core/agent-session.ts\";\nimport { cliProviderAliases, defaultModelPerProvider } from \"../../core/model-resolver.ts\";\nimport { BUILT_IN_PROVIDER_DISPLAY_NAMES } from \"../../core/provider-display-names.ts\";\nimport { ExtensionSelectorComponent } from \"./components/extension-selector.ts\";\nimport { LoginDialogComponent } from \"./components/login-dialog.ts\";\nimport { type AuthSelectorProvider, OAuthSelectorComponent } from \"./components/oauth-selector.ts\";\nimport type { EditorOverlayHost } from \"./editor-overlay-host.ts\";\nimport { theme } from \"./theme/theme.ts\";\n\nfunction isUnknownModel(model: Model<any> | undefined): boolean {\n\treturn !!model && model.provider === \"unknown\" && model.id === \"unknown\" && model.api === \"unknown\";\n}\n\nfunction hasDefaultModelProvider(providerId: string): providerId is keyof typeof defaultModelPerProvider {\n\treturn providerId in defaultModelPerProvider;\n}\n\nconst BEDROCK_PROVIDER_ID = \"amazon-bedrock\";\n\nconst BUILT_IN_MODEL_PROVIDERS = new Set<string>(getProviders());\n\nexport function isApiKeyLoginProvider(\n\tproviderId: string,\n\toauthProviderIds: ReadonlySet<string>,\n\tbuiltInProviderIds: ReadonlySet<string> = BUILT_IN_MODEL_PROVIDERS,\n): boolean {\n\tif (BUILT_IN_PROVIDER_DISPLAY_NAMES[providerId]) {\n\t\treturn true;\n\t}\n\tif (builtInProviderIds.has(providerId)) {\n\t\treturn false;\n\t}\n\treturn !oauthProviderIds.has(providerId);\n}\n\nexport interface AuthDialogsControllerUi {\n\tshowSelector(create: (done: () => void) => { component: Component; focus: Component }): void;\n\tshowStatus(message: string): void;\n\tshowError(message: string): void;\n\trequestRender(): void;\n\treadonly tui: TUI;\n\treadonly overlayHost: EditorOverlayHost;\n\tgetEditor(): Component;\n\tupdateAvailableProviderCount(): Promise<void>;\n\tinvalidateFooter(): void;\n\tupdateEditorBorderColor(): void;\n\tmaybeWarnAboutAnthropicSubscriptionAuth(model?: Model<any>): void;\n\tcheckDaxnutsEasterEgg(model: { provider: string; id: string }): void;\n}\n\nexport interface AuthDialogsControllerDeps {\n\tgetSession(): AgentSession;\n\tui: AuthDialogsControllerUi;\n}\n\nexport class AuthDialogsController {\n\tprivate readonly deps: AuthDialogsControllerDeps;\n\n\tconstructor(deps: AuthDialogsControllerDeps) {\n\t\tthis.deps = deps;\n\t}\n\n\tprivate get session(): AgentSession {\n\t\treturn this.deps.getSession();\n\t}\n\tprivate get ui(): AuthDialogsControllerUi {\n\t\treturn this.deps.ui;\n\t}\n\n\tprivate getLoginProviderOptions(authType?: \"oauth\" | \"api_key\"): AuthSelectorProvider[] {\n\t\tconst authStorage = this.session.modelRegistry.authStorage;\n\t\tconst oauthProviders = authStorage.getOAuthProviders();\n\t\tconst oauthProviderIds = new Set(oauthProviders.map((provider) => provider.id));\n\t\tconst options: AuthSelectorProvider[] = oauthProviders.map((provider) => ({\n\t\t\tid: provider.id,\n\t\t\tname: provider.name,\n\t\t\tauthType: \"oauth\",\n\t\t}));\n\n\t\tconst modelProviders = new Set(this.session.modelRegistry.getAll().map((model) => model.provider));\n\t\tfor (const providerId of modelProviders) {\n\t\t\tif (!isApiKeyLoginProvider(providerId, oauthProviderIds)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\toptions.push({\n\t\t\t\tid: providerId,\n\t\t\t\tname: this.session.modelRegistry.getProviderDisplayName(providerId),\n\t\t\t\tauthType: \"api_key\",\n\t\t\t});\n\t\t}\n\n\t\tconst filteredOptions = authType ? options.filter((option) => option.authType === authType) : options;\n\t\treturn filteredOptions.sort((a, b) => a.name.localeCompare(b.name));\n\t}\n\n\tprivate getLogoutProviderOptions(): AuthSelectorProvider[] {\n\t\tconst authStorage = this.session.modelRegistry.authStorage;\n\t\tconst options: AuthSelectorProvider[] = [];\n\n\t\tfor (const providerId of authStorage.list()) {\n\t\t\tconst credential = authStorage.get(providerId);\n\t\t\tif (!credential) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\toptions.push({\n\t\t\t\tid: providerId,\n\t\t\t\tname: this.session.modelRegistry.getProviderDisplayName(providerId),\n\t\t\t\tauthType: credential.type,\n\t\t\t});\n\t\t}\n\n\t\treturn options.sort((a, b) => a.name.localeCompare(b.name));\n\t}\n\n\tprivate resolveAuthProviderOption(\n\t\tproviderReference: string,\n\t\tproviderOptions: AuthSelectorProvider[],\n\t): AuthSelectorProvider | undefined {\n\t\tconst normalized = providerReference.trim().toLowerCase();\n\t\tif (!normalized) return undefined;\n\t\tconst exactMatch = providerOptions.find((provider) => {\n\t\t\tconst id = provider.id.toLowerCase();\n\t\t\tconst name = provider.name.toLowerCase();\n\t\t\treturn id === normalized || name === normalized;\n\t\t});\n\t\tif (exactMatch) return exactMatch;\n\t\tconst aliasTarget = cliProviderAliases[normalized] ?? normalized;\n\t\treturn providerOptions.find((provider) => {\n\t\t\tconst id = provider.id.toLowerCase();\n\t\t\tconst name = provider.name.toLowerCase();\n\t\t\treturn id === aliasTarget || name === aliasTarget;\n\t\t});\n\t}\n\n\tprivate async startProviderLogin(providerOption: AuthSelectorProvider): Promise<void> {\n\t\tif (providerOption.authType === \"oauth\") {\n\t\t\tawait this.showLoginDialog(providerOption.id, providerOption.name);\n\t\t} else if (providerOption.id === BEDROCK_PROVIDER_ID) {\n\t\t\tthis.showBedrockSetupDialog(providerOption.id, providerOption.name);\n\t\t} else {\n\t\t\tawait this.showApiKeyLoginDialog(providerOption.id, providerOption.name);\n\t\t}\n\t}\n\n\tprivate showLoginAuthTypeSelector(): void {\n\t\tconst subscriptionLabel = \"Use a subscription\";\n\t\tconst apiKeyLabel = \"Use an API key\";\n\t\tthis.ui.showSelector((done) => {\n\t\t\tconst selector = new ExtensionSelectorComponent(\n\t\t\t\t\"Select authentication method:\",\n\t\t\t\t[subscriptionLabel, apiKeyLabel],\n\t\t\t\t(option) => {\n\t\t\t\t\tdone();\n\t\t\t\t\tconst authType = option === subscriptionLabel ? \"oauth\" : \"api_key\";\n\t\t\t\t\tthis.showLoginProviderSelector(authType);\n\t\t\t\t},\n\t\t\t\t() => {\n\t\t\t\t\tdone();\n\t\t\t\t\tthis.ui.requestRender();\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn { component: selector, focus: selector };\n\t\t});\n\t}\n\n\tprivate showLoginProviderSelector(authType: \"oauth\" | \"api_key\"): void {\n\t\tconst providerOptions = this.getLoginProviderOptions(authType);\n\t\tif (providerOptions.length === 0) {\n\t\t\tthis.ui.showStatus(\n\t\t\t\tauthType === \"oauth\" ? \"No subscription providers available.\" : \"No API key providers available.\",\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.ui.showSelector((done) => {\n\t\t\tconst selector = new OAuthSelectorComponent(\n\t\t\t\t\"login\",\n\t\t\t\tthis.session.modelRegistry.authStorage,\n\t\t\t\tproviderOptions,\n\t\t\t\tasync (providerId: string) => {\n\t\t\t\t\tdone();\n\n\t\t\t\t\tconst providerOption = providerOptions.find((provider) => provider.id === providerId);\n\t\t\t\t\tif (!providerOption) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tawait this.startProviderLogin(providerOption);\n\t\t\t\t},\n\t\t\t\t() => {\n\t\t\t\t\tdone();\n\t\t\t\t\tthis.showLoginAuthTypeSelector();\n\t\t\t\t},\n\t\t\t\t(providerId) => this.session.modelRegistry.getProviderAuthStatus(providerId),\n\t\t\t);\n\t\t\treturn { component: selector, focus: selector };\n\t\t});\n\t}\n\n\tasync showOAuthSelector(mode: \"login\" | \"logout\", providerReference?: string): Promise<void> {\n\t\tif (mode === \"login\") {\n\t\t\tif (providerReference) {\n\t\t\t\tconst providerOptions = this.getLoginProviderOptions();\n\t\t\t\tconst providerOption = this.resolveAuthProviderOption(providerReference, providerOptions);\n\t\t\t\tif (!providerOption) {\n\t\t\t\t\tthis.ui.showError(\n\t\t\t\t\t\t`Unknown login provider \"${providerReference}\". Use /login to select from available providers.`,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tawait this.startProviderLogin(providerOption);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.showLoginAuthTypeSelector();\n\t\t\treturn;\n\t\t}\n\n\t\tconst providerOptions = this.getLogoutProviderOptions();\n\t\tif (providerOptions.length === 0) {\n\t\t\tthis.ui.showStatus(\n\t\t\t\t\"No stored credentials to remove. /logout only removes credentials saved by /login; environment variables and models.json config are unchanged.\",\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tif (providerReference) {\n\t\t\tconst providerOption = this.resolveAuthProviderOption(providerReference, providerOptions);\n\t\t\tif (!providerOption) {\n\t\t\t\tthis.ui.showError(\n\t\t\t\t\t`No stored credentials found for \"${providerReference}\". Use /logout to select a saved provider.`,\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tthis.session.modelRegistry.authStorage.logout(providerOption.id);\n\t\t\t\tthis.session.modelRegistry.refresh();\n\t\t\t\tawait this.ui.updateAvailableProviderCount();\n\t\t\t\tconst message =\n\t\t\t\t\tproviderOption.authType === \"oauth\"\n\t\t\t\t\t\t? `Logged out of ${providerOption.name}`\n\t\t\t\t\t\t: `Removed stored API key for ${providerOption.name}. Environment variables and models.json config are unchanged.`;\n\t\t\t\tthis.ui.showStatus(message);\n\t\t\t} catch (error: unknown) {\n\t\t\t\tthis.ui.showError(`Logout failed: ${error instanceof Error ? error.message : String(error)}`);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tthis.ui.showSelector((done) => {\n\t\t\tconst selector = new OAuthSelectorComponent(\n\t\t\t\tmode,\n\t\t\t\tthis.session.modelRegistry.authStorage,\n\t\t\t\tproviderOptions,\n\t\t\t\tasync (providerId: string) => {\n\t\t\t\t\tdone();\n\n\t\t\t\t\tconst providerOption = providerOptions.find((provider) => provider.id === providerId);\n\t\t\t\t\tif (!providerOption) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.session.modelRegistry.authStorage.logout(providerOption.id);\n\t\t\t\t\t\tthis.session.modelRegistry.refresh();\n\t\t\t\t\t\tawait this.ui.updateAvailableProviderCount();\n\t\t\t\t\t\tconst message =\n\t\t\t\t\t\t\tproviderOption.authType === \"oauth\"\n\t\t\t\t\t\t\t\t? `Logged out of ${providerOption.name}`\n\t\t\t\t\t\t\t\t: `Removed stored API key for ${providerOption.name}. Environment variables and models.json config are unchanged.`;\n\t\t\t\t\t\tthis.ui.showStatus(message);\n\t\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\t\tthis.ui.showError(`Logout failed: ${error instanceof Error ? error.message : String(error)}`);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t() => {\n\t\t\t\t\tdone();\n\t\t\t\t\tthis.ui.requestRender();\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn { component: selector, focus: selector };\n\t\t});\n\t}\n\n\tprivate async completeProviderAuthentication(\n\t\tproviderId: string,\n\t\tproviderName: string,\n\t\tauthType: \"oauth\" | \"api_key\",\n\t\tpreviousModel: Model<any> | undefined,\n\t): Promise<void> {\n\t\tthis.session.modelRegistry.refresh();\n\n\t\tconst actionLabel = authType === \"oauth\" ? `Logged in to ${providerName}` : `Saved API key for ${providerName}`;\n\n\t\tlet selectedModel: Model<any> | undefined;\n\t\tlet selectionError: string | undefined;\n\t\tif (isUnknownModel(previousModel)) {\n\t\t\tconst availableModels = this.session.modelRegistry.getAvailable();\n\t\t\tconst providerModels = availableModels.filter((model) => model.provider === providerId);\n\t\t\tif (!hasDefaultModelProvider(providerId)) {\n\t\t\t\tselectionError = `${actionLabel}, but no default model is configured for provider \"${providerId}\". Use /model to select a model.`;\n\t\t\t} else if (providerModels.length === 0) {\n\t\t\t\tselectionError = `${actionLabel}, but no models are available for that provider. Use /model to select a model.`;\n\t\t\t} else {\n\t\t\t\tconst defaultModelId = defaultModelPerProvider[providerId];\n\t\t\t\tselectedModel = providerModels.find((model) => model.id === defaultModelId);\n\t\t\t\tif (!selectedModel) {\n\t\t\t\t\tselectionError = `${actionLabel}, but its default model \"${defaultModelId}\" is not available. Use /model to select a model.`;\n\t\t\t\t} else {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.session.setModel(selectedModel);\n\t\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\t\tselectedModel = undefined;\n\t\t\t\t\t\tconst errorMessage = error instanceof Error ? error.message : String(error);\n\t\t\t\t\t\tselectionError = `${actionLabel}, but selecting its default model failed: ${errorMessage}. Use /model to select a model.`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tawait this.ui.updateAvailableProviderCount();\n\t\tthis.ui.invalidateFooter();\n\t\tthis.ui.updateEditorBorderColor();\n\t\tif (selectedModel) {\n\t\t\tthis.ui.showStatus(`${actionLabel}. Selected ${selectedModel.id}. Credentials saved to ${getAuthPath()}`);\n\t\t\tvoid this.ui.maybeWarnAboutAnthropicSubscriptionAuth(selectedModel);\n\t\t\tthis.ui.checkDaxnutsEasterEgg(selectedModel);\n\t\t} else {\n\t\t\tthis.ui.showStatus(`${actionLabel}. Credentials saved to ${getAuthPath()}`);\n\t\t\tif (selectionError) {\n\t\t\t\tthis.ui.showError(selectionError);\n\t\t\t} else {\n\t\t\t\tvoid this.ui.maybeWarnAboutAnthropicSubscriptionAuth();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate showBedrockSetupDialog(providerId: string, providerName: string): void {\n\t\tconst restoreEditor = () => {\n\t\t\tthis.ui.overlayHost.swap(this.ui.getEditor());\n\t\t};\n\n\t\tconst dialog = new LoginDialogComponent(\n\t\t\tthis.ui.tui,\n\t\t\tproviderId,\n\t\t\t() => restoreEditor(),\n\t\t\tproviderName,\n\t\t\t\"Amazon Bedrock setup\",\n\t\t);\n\t\tdialog.showInfo([\n\t\t\ttheme.fg(\"text\", \"Amazon Bedrock uses AWS credentials instead of a single API key.\"),\n\t\t\ttheme.fg(\"text\", \"Configure an AWS profile, IAM keys, bearer token, or role-based credentials.\"),\n\t\t\ttheme.fg(\"muted\", \"See:\"),\n\t\t\ttheme.fg(\"accent\", ` ${path.join(getDocsPath(), \"providers.md\")}`),\n\t\t]);\n\n\t\tthis.ui.overlayHost.swap(dialog);\n\t}\n\n\tprivate async showApiKeyLoginDialog(providerId: string, providerName: string): Promise<void> {\n\t\tconst previousModel = this.session.model;\n\n\t\tconst dialog = new LoginDialogComponent(\n\t\t\tthis.ui.tui,\n\t\t\tproviderId,\n\t\t\t(_success, _message) => {\n\t\t\t\t// Completion handled below\n\t\t\t},\n\t\t\tproviderName,\n\t\t);\n\n\t\tthis.ui.overlayHost.swap(dialog);\n\n\t\tconst restoreEditor = () => {\n\t\t\tthis.ui.overlayHost.swap(this.ui.getEditor());\n\t\t};\n\n\t\ttry {\n\t\t\tconst apiKey = (await dialog.showPrompt(\"Enter API key:\")).trim();\n\t\t\tif (!apiKey) {\n\t\t\t\tthrow new Error(\"API key cannot be empty.\");\n\t\t\t}\n\n\t\t\tthis.session.modelRegistry.authStorage.set(providerId, { type: \"api_key\", key: apiKey });\n\n\t\t\trestoreEditor();\n\t\t\tawait this.completeProviderAuthentication(providerId, providerName, \"api_key\", previousModel);\n\t\t} catch (error: unknown) {\n\t\t\trestoreEditor();\n\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\t\tif (errorMsg !== \"Login cancelled\") {\n\t\t\t\tthis.ui.showError(`Failed to save API key for ${providerName}: ${errorMsg}`);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate showOAuthLoginSelect(dialog: LoginDialogComponent, prompt: OAuthSelectPrompt): Promise<string | undefined> {\n\t\treturn new Promise((resolve) => {\n\t\t\tconst restoreDialog = () => {\n\t\t\t\tthis.ui.overlayHost.swap(dialog);\n\t\t\t};\n\t\t\tconst labels = prompt.options.map((option) => option.label);\n\t\t\tconst selector = new ExtensionSelectorComponent(\n\t\t\t\tprompt.message,\n\t\t\t\tlabels,\n\t\t\t\t(optionLabel) => {\n\t\t\t\t\trestoreDialog();\n\t\t\t\t\tresolve(prompt.options.find((option) => option.label === optionLabel)?.id);\n\t\t\t\t},\n\t\t\t\t() => {\n\t\t\t\t\trestoreDialog();\n\t\t\t\t\tresolve(undefined);\n\t\t\t\t},\n\t\t\t);\n\t\t\tthis.ui.overlayHost.swap(selector);\n\t\t});\n\t}\n\n\tprivate async showLoginDialog(providerId: string, providerName: string): Promise<void> {\n\t\tconst providerInfo = this.session.modelRegistry.authStorage\n\t\t\t.getOAuthProviders()\n\t\t\t.find((provider) => provider.id === providerId);\n\t\tconst previousModel = this.session.model;\n\n\t\t// Providers that use callback servers (can paste redirect URL)\n\t\tconst usesCallbackServer = providerInfo?.usesCallbackServer ?? false;\n\n\t\t// Create login dialog component\n\t\tconst dialog = new LoginDialogComponent(\n\t\t\tthis.ui.tui,\n\t\t\tproviderId,\n\t\t\t(_success, _message) => {\n\t\t\t\t// Completion handled below\n\t\t\t},\n\t\t\tproviderName,\n\t\t);\n\n\t\t// Show dialog in editor container\n\t\tthis.ui.overlayHost.swap(dialog);\n\n\t\t// Promise for manual code input (racing with callback server)\n\t\tlet manualCodeResolve: ((code: string) => void) | undefined;\n\t\tlet manualCodeReject: ((err: Error) => void) | undefined;\n\t\tconst manualCodePromise = new Promise<string>((resolve, reject) => {\n\t\t\tmanualCodeResolve = resolve;\n\t\t\tmanualCodeReject = reject;\n\t\t});\n\n\t\t// Restore editor helper\n\t\tconst restoreEditor = () => {\n\t\t\tthis.ui.overlayHost.swap(this.ui.getEditor());\n\t\t};\n\n\t\ttry {\n\t\t\tawait this.session.modelRegistry.authStorage.login(providerId as OAuthProviderId, {\n\t\t\t\tonAuth: (info: { url: string; instructions?: string }) => {\n\t\t\t\t\tdialog.showAuth(info.url, info.instructions);\n\n\t\t\t\t\tif (usesCallbackServer) {\n\t\t\t\t\t\t// Show input for manual paste, racing with callback\n\t\t\t\t\t\tdialog\n\t\t\t\t\t\t\t.showManualInput(\"Paste redirect URL below, or complete login in browser:\")\n\t\t\t\t\t\t\t.then((value) => {\n\t\t\t\t\t\t\t\tif (value && manualCodeResolve) {\n\t\t\t\t\t\t\t\t\tmanualCodeResolve(value);\n\t\t\t\t\t\t\t\t\tmanualCodeResolve = undefined;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t.catch(() => {\n\t\t\t\t\t\t\t\tif (manualCodeReject) {\n\t\t\t\t\t\t\t\t\tmanualCodeReject(new Error(\"Login cancelled\"));\n\t\t\t\t\t\t\t\t\tmanualCodeReject = undefined;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\t// For Anthropic: onPrompt is called immediately after\n\t\t\t\t},\n\n\t\t\t\tonDeviceCode: (info) => {\n\t\t\t\t\tdialog.showDeviceCode(info);\n\t\t\t\t\tdialog.showWaiting(\"Waiting for authentication...\");\n\t\t\t\t},\n\n\t\t\t\tonPrompt: async (prompt: { message: string; placeholder?: string }) => {\n\t\t\t\t\treturn dialog.showPrompt(prompt.message, prompt.placeholder);\n\t\t\t\t},\n\n\t\t\t\tonProgress: (message: string) => {\n\t\t\t\t\tdialog.showProgress(message);\n\t\t\t\t},\n\n\t\t\t\tonSelect: (prompt: OAuthSelectPrompt) => this.showOAuthLoginSelect(dialog, prompt),\n\n\t\t\t\tonManualCodeInput: () => manualCodePromise,\n\n\t\t\t\tsignal: dialog.signal,\n\t\t\t});\n\n\t\t\t// Success\n\t\t\trestoreEditor();\n\t\t\tawait this.completeProviderAuthentication(providerId, providerName, \"oauth\", previousModel);\n\t\t} catch (error: unknown) {\n\t\t\trestoreEditor();\n\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\t\tif (errorMsg !== \"Login cancelled\") {\n\t\t\t\tthis.ui.showError(`Failed to login to ${providerName}: ${errorMsg}`);\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"auth-dialogs-controller.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/auth-dialogs-controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAgB,KAAK,KAAK,EAAgD,MAAM,mBAAmB,CAAC;AAC3G,OAAO,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAMhE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAelE,wBAAgB,qBAAqB,CACpC,UAAU,EAAE,MAAM,EAClB,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAAC,EACrC,kBAAkB,GAAE,WAAW,CAAC,MAAM,CAA4B,GAChE,OAAO,CAQT;AAED,MAAM,WAAW,uBAAuB;IACvC,YAAY,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,IAAI,KAAK;QAAE,SAAS,EAAE,SAAS,CAAC;QAAC,KAAK,EAAE,SAAS,CAAA;KAAE,GAAG,IAAI,CAAC;IAC7F,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,aAAa,IAAI,IAAI,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,QAAQ,CAAC,WAAW,EAAE,iBAAiB,CAAC;IACxC,SAAS,IAAI,SAAS,CAAC;IACvB,4BAA4B,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,gBAAgB,IAAI,IAAI,CAAC;IACzB,uBAAuB,IAAI,IAAI,CAAC;IAChC,uCAAuC,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;IAClE,qBAAqB,CAAC,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CACrE;AAED,MAAM,WAAW,yBAAyB;IACzC,UAAU,IAAI,YAAY,CAAC;IAC3B,EAAE,EAAE,uBAAuB,CAAC;CAC5B;AAED,qBAAa,qBAAqB;IACjC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA4B;IACjD,OAAO,CAAC,iBAAiB,CAAmC;IAC5D,OAAO,CAAC,0BAA0B,CAA2B;IAC7D,OAAO,CAAC,gCAAgC,CAAS;IACjD,OAAO,CAAC,yBAAyB,CAA2B;IAE5D,YAAY,IAAI,EAAE,yBAAyB,EAE1C;IAED,OAAO,KAAK,OAAO,GAElB;IACD,OAAO,KAAK,EAAE,GAEb;IAED,kBAAkB,IAAI,IAAI,CAQzB;IAED,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,uBAAuB;IAM/B,OAAO,CAAC,4BAA4B;IAMpC,OAAO,CAAC,kBAAkB;IAM1B,OAAO,CAAC,uBAAuB;IA0B/B,OAAO,CAAC,wBAAwB;IAmBhC,OAAO,CAAC,yBAAyB;YAoBnB,kBAAkB;IAUhC,OAAO,CAAC,yBAAyB;IAqBjC,OAAO,CAAC,yBAAyB;IAkC3B,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,EAAE,iBAAiB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkF3F;YAEa,8BAA8B;IAqD5C,OAAO,CAAC,sBAAsB;YAqBhB,qBAAqB;IAoCnC,OAAO,CAAC,oBAAoB;YA+Bd,eAAe;CA0F7B","sourcesContent":["/**\n * Auth / login / OAuth dialog controller.\n *\n * Extracted verbatim from interactive-mode.ts (god-file decomposition). Owns the /login and /logout\n * command flows: provider selection, subscription (OAuth) login dialogs, API-key login dialogs, the\n * Amazon Bedrock setup notice, the OAuth in-dialog select prompt, and post-login model adoption. It\n * holds NO state of its own — every credential/provider fact lives in session.modelRegistry.authStorage\n * — so it takes narrow deps (a live session accessor plus a UI callback surface, including the\n * editor-overlay-backed showSelector and the shared EditorOverlayHost for dialog swaps) rather than\n * the whole InteractiveMode instance.\n */\n\nimport * as path from \"node:path\";\nimport { getProviders, type Model, type OAuthProviderId, type OAuthSelectPrompt } from \"@caupulican/pi-ai\";\nimport type { Component, TUI } from \"@caupulican/pi-tui\";\nimport { getAuthPath, getDocsPath } from \"../../config.ts\";\nimport type { AgentSession } from \"../../core/agent-session.ts\";\nimport { cliProviderAliases, defaultModelPerProvider } from \"../../core/model-resolver.ts\";\nimport { BUILT_IN_PROVIDER_DISPLAY_NAMES } from \"../../core/provider-display-names.ts\";\nimport { ExtensionSelectorComponent } from \"./components/extension-selector.ts\";\nimport { LoginDialogComponent } from \"./components/login-dialog.ts\";\nimport { type AuthSelectorProvider, OAuthSelectorComponent } from \"./components/oauth-selector.ts\";\nimport type { EditorOverlayHost } from \"./editor-overlay-host.ts\";\nimport { theme } from \"./theme/theme.ts\";\n\nfunction isUnknownModel(model: Model<any> | undefined): boolean {\n\treturn !!model && model.provider === \"unknown\" && model.id === \"unknown\" && model.api === \"unknown\";\n}\n\nfunction hasDefaultModelProvider(providerId: string): providerId is keyof typeof defaultModelPerProvider {\n\treturn providerId in defaultModelPerProvider;\n}\n\nconst BEDROCK_PROVIDER_ID = \"amazon-bedrock\";\n\nconst BUILT_IN_MODEL_PROVIDERS = new Set<string>(getProviders());\n\nexport function isApiKeyLoginProvider(\n\tproviderId: string,\n\toauthProviderIds: ReadonlySet<string>,\n\tbuiltInProviderIds: ReadonlySet<string> = BUILT_IN_MODEL_PROVIDERS,\n): boolean {\n\tif (BUILT_IN_PROVIDER_DISPLAY_NAMES[providerId]) {\n\t\treturn true;\n\t}\n\tif (builtInProviderIds.has(providerId)) {\n\t\treturn false;\n\t}\n\treturn !oauthProviderIds.has(providerId);\n}\n\nexport interface AuthDialogsControllerUi {\n\tshowSelector(create: (done: () => void) => { component: Component; focus: Component }): void;\n\tshowStatus(message: string): void;\n\tshowError(message: string): void;\n\trequestRender(): void;\n\treadonly tui: TUI;\n\treadonly overlayHost: EditorOverlayHost;\n\tgetEditor(): Component;\n\tupdateAvailableProviderCount(): Promise<void>;\n\tinvalidateFooter(): void;\n\tupdateEditorBorderColor(): void;\n\tmaybeWarnAboutAnthropicSubscriptionAuth(model?: Model<any>): void;\n\tcheckDaxnutsEasterEgg(model: { provider: string; id: string }): void;\n}\n\nexport interface AuthDialogsControllerDeps {\n\tgetSession(): AgentSession;\n\tui: AuthDialogsControllerUi;\n}\n\nexport class AuthDialogsController {\n\tprivate readonly deps: AuthDialogsControllerDeps;\n\tprivate activeLoginDialog: LoginDialogComponent | undefined;\n\tprivate activeLoginDialogOnUnmount: (() => void) | undefined;\n\tprivate suppressActiveLoginDialogUnmount = false;\n\tprivate activeOAuthSelectorCancel: (() => void) | undefined;\n\n\tconstructor(deps: AuthDialogsControllerDeps) {\n\t\tthis.deps = deps;\n\t}\n\n\tprivate get session(): AgentSession {\n\t\treturn this.deps.getSession();\n\t}\n\tprivate get ui(): AuthDialogsControllerUi {\n\t\treturn this.deps.ui;\n\t}\n\n\tcancelActiveDialog(): void {\n\t\tconst cancelSelector = this.activeOAuthSelectorCancel;\n\t\tthis.activeOAuthSelectorCancel = undefined;\n\t\tcancelSelector?.();\n\t\tconst dialog = this.activeLoginDialog;\n\t\tif (!dialog || !this.clearActiveDialog(dialog)) return;\n\t\tdialog.cancel();\n\t\tthis.ui.overlayHost.swap(this.ui.getEditor());\n\t}\n\n\tprivate clearActiveDialog(dialog: LoginDialogComponent): boolean {\n\t\tif (this.activeLoginDialog !== dialog) return false;\n\t\tthis.activeLoginDialog = undefined;\n\t\tthis.activeLoginDialogOnUnmount = undefined;\n\t\tthis.suppressActiveLoginDialogUnmount = false;\n\t\treturn true;\n\t}\n\n\tprivate mountLoginDialog(dialog: LoginDialogComponent): void {\n\t\tthis.activeLoginDialog = dialog;\n\t\tconst onUnmount = () => {\n\t\t\tif (this.suppressActiveLoginDialogUnmount && this.activeLoginDialog === dialog) {\n\t\t\t\tthis.suppressActiveLoginDialogUnmount = false;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!this.clearActiveDialog(dialog)) return;\n\t\t\tdialog.cancel();\n\t\t};\n\t\tthis.activeLoginDialogOnUnmount = onUnmount;\n\t\tthis.ui.overlayHost.swap(dialog, { onUnmount });\n\t}\n\n\tprivate restoreEditorFromDialog(dialog: LoginDialogComponent): boolean {\n\t\tif (!this.clearActiveDialog(dialog)) return false;\n\t\tthis.ui.overlayHost.swap(this.ui.getEditor());\n\t\treturn true;\n\t}\n\n\tprivate detachLoginDialogForSelector(dialog: LoginDialogComponent): void {\n\t\tif (this.activeLoginDialog === dialog && this.activeLoginDialogOnUnmount) {\n\t\t\tthis.suppressActiveLoginDialogUnmount = true;\n\t\t}\n\t}\n\n\tprivate remountLoginDialog(dialog: LoginDialogComponent): boolean {\n\t\tif (this.activeLoginDialog !== dialog || !this.activeLoginDialogOnUnmount) return false;\n\t\tthis.ui.overlayHost.swap(dialog, { onUnmount: this.activeLoginDialogOnUnmount });\n\t\treturn true;\n\t}\n\n\tprivate getLoginProviderOptions(authType?: \"oauth\" | \"api_key\"): AuthSelectorProvider[] {\n\t\tconst authStorage = this.session.modelRegistry.authStorage;\n\t\tconst oauthProviders = authStorage.getOAuthProviders();\n\t\tconst oauthProviderIds = new Set(oauthProviders.map((provider) => provider.id));\n\t\tconst options: AuthSelectorProvider[] = oauthProviders.map((provider) => ({\n\t\t\tid: provider.id,\n\t\t\tname: provider.name,\n\t\t\tauthType: \"oauth\",\n\t\t}));\n\n\t\tconst modelProviders = new Set(this.session.modelRegistry.getAll().map((model) => model.provider));\n\t\tfor (const providerId of modelProviders) {\n\t\t\tif (!isApiKeyLoginProvider(providerId, oauthProviderIds)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\toptions.push({\n\t\t\t\tid: providerId,\n\t\t\t\tname: this.session.modelRegistry.getProviderDisplayName(providerId),\n\t\t\t\tauthType: \"api_key\",\n\t\t\t});\n\t\t}\n\n\t\tconst filteredOptions = authType ? options.filter((option) => option.authType === authType) : options;\n\t\treturn filteredOptions.sort((a, b) => a.name.localeCompare(b.name));\n\t}\n\n\tprivate getLogoutProviderOptions(): AuthSelectorProvider[] {\n\t\tconst authStorage = this.session.modelRegistry.authStorage;\n\t\tconst options: AuthSelectorProvider[] = [];\n\n\t\tfor (const providerId of authStorage.list()) {\n\t\t\tconst credential = authStorage.get(providerId);\n\t\t\tif (!credential) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\toptions.push({\n\t\t\t\tid: providerId,\n\t\t\t\tname: this.session.modelRegistry.getProviderDisplayName(providerId),\n\t\t\t\tauthType: credential.type,\n\t\t\t});\n\t\t}\n\n\t\treturn options.sort((a, b) => a.name.localeCompare(b.name));\n\t}\n\n\tprivate resolveAuthProviderOption(\n\t\tproviderReference: string,\n\t\tproviderOptions: AuthSelectorProvider[],\n\t): AuthSelectorProvider | undefined {\n\t\tconst normalized = providerReference.trim().toLowerCase();\n\t\tif (!normalized) return undefined;\n\t\tconst exactMatch = providerOptions.find((provider) => {\n\t\t\tconst id = provider.id.toLowerCase();\n\t\t\tconst name = provider.name.toLowerCase();\n\t\t\treturn id === normalized || name === normalized;\n\t\t});\n\t\tif (exactMatch) return exactMatch;\n\t\tconst aliasTarget = cliProviderAliases[normalized] ?? normalized;\n\t\treturn providerOptions.find((provider) => {\n\t\t\tconst id = provider.id.toLowerCase();\n\t\t\tconst name = provider.name.toLowerCase();\n\t\t\treturn id === aliasTarget || name === aliasTarget;\n\t\t});\n\t}\n\n\tprivate async startProviderLogin(providerOption: AuthSelectorProvider): Promise<void> {\n\t\tif (providerOption.authType === \"oauth\") {\n\t\t\tawait this.showLoginDialog(providerOption.id, providerOption.name);\n\t\t} else if (providerOption.id === BEDROCK_PROVIDER_ID) {\n\t\t\tthis.showBedrockSetupDialog(providerOption.id, providerOption.name);\n\t\t} else {\n\t\t\tawait this.showApiKeyLoginDialog(providerOption.id, providerOption.name);\n\t\t}\n\t}\n\n\tprivate showLoginAuthTypeSelector(): void {\n\t\tconst subscriptionLabel = \"Use a subscription\";\n\t\tconst apiKeyLabel = \"Use an API key\";\n\t\tthis.ui.showSelector((done) => {\n\t\t\tconst selector = new ExtensionSelectorComponent(\n\t\t\t\t\"Select authentication method:\",\n\t\t\t\t[subscriptionLabel, apiKeyLabel],\n\t\t\t\t(option) => {\n\t\t\t\t\tdone();\n\t\t\t\t\tconst authType = option === subscriptionLabel ? \"oauth\" : \"api_key\";\n\t\t\t\t\tthis.showLoginProviderSelector(authType);\n\t\t\t\t},\n\t\t\t\t() => {\n\t\t\t\t\tdone();\n\t\t\t\t\tthis.ui.requestRender();\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn { component: selector, focus: selector };\n\t\t});\n\t}\n\n\tprivate showLoginProviderSelector(authType: \"oauth\" | \"api_key\"): void {\n\t\tconst providerOptions = this.getLoginProviderOptions(authType);\n\t\tif (providerOptions.length === 0) {\n\t\t\tthis.ui.showStatus(\n\t\t\t\tauthType === \"oauth\" ? \"No subscription providers available.\" : \"No API key providers available.\",\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.ui.showSelector((done) => {\n\t\t\tconst selector = new OAuthSelectorComponent(\n\t\t\t\t\"login\",\n\t\t\t\tthis.session.modelRegistry.authStorage,\n\t\t\t\tproviderOptions,\n\t\t\t\tasync (providerId: string) => {\n\t\t\t\t\tdone();\n\n\t\t\t\t\tconst providerOption = providerOptions.find((provider) => provider.id === providerId);\n\t\t\t\t\tif (!providerOption) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tawait this.startProviderLogin(providerOption);\n\t\t\t\t},\n\t\t\t\t() => {\n\t\t\t\t\tdone();\n\t\t\t\t\tthis.showLoginAuthTypeSelector();\n\t\t\t\t},\n\t\t\t\t(providerId) => this.session.modelRegistry.getProviderAuthStatus(providerId),\n\t\t\t);\n\t\t\treturn { component: selector, focus: selector };\n\t\t});\n\t}\n\n\tasync showOAuthSelector(mode: \"login\" | \"logout\", providerReference?: string): Promise<void> {\n\t\tif (mode === \"login\") {\n\t\t\tif (providerReference) {\n\t\t\t\tconst providerOptions = this.getLoginProviderOptions();\n\t\t\t\tconst providerOption = this.resolveAuthProviderOption(providerReference, providerOptions);\n\t\t\t\tif (!providerOption) {\n\t\t\t\t\tthis.ui.showError(\n\t\t\t\t\t\t`Unknown login provider \"${providerReference}\". Use /login to select from available providers.`,\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tawait this.startProviderLogin(providerOption);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.showLoginAuthTypeSelector();\n\t\t\treturn;\n\t\t}\n\n\t\tconst providerOptions = this.getLogoutProviderOptions();\n\t\tif (providerOptions.length === 0) {\n\t\t\tthis.ui.showStatus(\n\t\t\t\t\"No stored credentials to remove. /logout only removes credentials saved by /login; environment variables and models.json config are unchanged.\",\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tif (providerReference) {\n\t\t\tconst providerOption = this.resolveAuthProviderOption(providerReference, providerOptions);\n\t\t\tif (!providerOption) {\n\t\t\t\tthis.ui.showError(\n\t\t\t\t\t`No stored credentials found for \"${providerReference}\". Use /logout to select a saved provider.`,\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tthis.session.modelRegistry.authStorage.logout(providerOption.id);\n\t\t\t\tthis.session.modelRegistry.refresh();\n\t\t\t\tawait this.ui.updateAvailableProviderCount();\n\t\t\t\tconst message =\n\t\t\t\t\tproviderOption.authType === \"oauth\"\n\t\t\t\t\t\t? `Logged out of ${providerOption.name}`\n\t\t\t\t\t\t: `Removed stored API key for ${providerOption.name}. Environment variables and models.json config are unchanged.`;\n\t\t\t\tthis.ui.showStatus(message);\n\t\t\t} catch (error: unknown) {\n\t\t\t\tthis.ui.showError(`Logout failed: ${error instanceof Error ? error.message : String(error)}`);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tthis.ui.showSelector((done) => {\n\t\t\tconst selector = new OAuthSelectorComponent(\n\t\t\t\tmode,\n\t\t\t\tthis.session.modelRegistry.authStorage,\n\t\t\t\tproviderOptions,\n\t\t\t\tasync (providerId: string) => {\n\t\t\t\t\tdone();\n\n\t\t\t\t\tconst providerOption = providerOptions.find((provider) => provider.id === providerId);\n\t\t\t\t\tif (!providerOption) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.session.modelRegistry.authStorage.logout(providerOption.id);\n\t\t\t\t\t\tthis.session.modelRegistry.refresh();\n\t\t\t\t\t\tawait this.ui.updateAvailableProviderCount();\n\t\t\t\t\t\tconst message =\n\t\t\t\t\t\t\tproviderOption.authType === \"oauth\"\n\t\t\t\t\t\t\t\t? `Logged out of ${providerOption.name}`\n\t\t\t\t\t\t\t\t: `Removed stored API key for ${providerOption.name}. Environment variables and models.json config are unchanged.`;\n\t\t\t\t\t\tthis.ui.showStatus(message);\n\t\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\t\tthis.ui.showError(`Logout failed: ${error instanceof Error ? error.message : String(error)}`);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t() => {\n\t\t\t\t\tdone();\n\t\t\t\t\tthis.ui.requestRender();\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn { component: selector, focus: selector };\n\t\t});\n\t}\n\n\tprivate async completeProviderAuthentication(\n\t\tproviderId: string,\n\t\tproviderName: string,\n\t\tauthType: \"oauth\" | \"api_key\",\n\t\tpreviousModel: Model<any> | undefined,\n\t): Promise<void> {\n\t\tthis.session.modelRegistry.refresh();\n\n\t\tconst actionLabel = authType === \"oauth\" ? `Logged in to ${providerName}` : `Saved API key for ${providerName}`;\n\n\t\tlet selectedModel: Model<any> | undefined;\n\t\tlet selectionError: string | undefined;\n\t\tif (isUnknownModel(previousModel)) {\n\t\t\tconst availableModels = this.session.modelRegistry.getAvailable();\n\t\t\tconst providerModels = availableModels.filter((model) => model.provider === providerId);\n\t\t\tif (!hasDefaultModelProvider(providerId)) {\n\t\t\t\tselectionError = `${actionLabel}, but no default model is configured for provider \"${providerId}\". Use /model to select a model.`;\n\t\t\t} else if (providerModels.length === 0) {\n\t\t\t\tselectionError = `${actionLabel}, but no models are available for that provider. Use /model to select a model.`;\n\t\t\t} else {\n\t\t\t\tconst defaultModelId = defaultModelPerProvider[providerId];\n\t\t\t\tselectedModel = providerModels.find((model) => model.id === defaultModelId);\n\t\t\t\tif (!selectedModel) {\n\t\t\t\t\tselectionError = `${actionLabel}, but its default model \"${defaultModelId}\" is not available. Use /model to select a model.`;\n\t\t\t\t} else {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.session.setModel(selectedModel);\n\t\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\t\tselectedModel = undefined;\n\t\t\t\t\t\tconst errorMessage = error instanceof Error ? error.message : String(error);\n\t\t\t\t\t\tselectionError = `${actionLabel}, but selecting its default model failed: ${errorMessage}. Use /model to select a model.`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tawait this.ui.updateAvailableProviderCount();\n\t\tthis.ui.invalidateFooter();\n\t\tthis.ui.updateEditorBorderColor();\n\t\tif (selectedModel) {\n\t\t\tthis.ui.showStatus(`${actionLabel}. Selected ${selectedModel.id}. Credentials saved to ${getAuthPath()}`);\n\t\t\tvoid this.ui.maybeWarnAboutAnthropicSubscriptionAuth(selectedModel);\n\t\t\tthis.ui.checkDaxnutsEasterEgg(selectedModel);\n\t\t} else {\n\t\t\tthis.ui.showStatus(`${actionLabel}. Credentials saved to ${getAuthPath()}`);\n\t\t\tif (selectionError) {\n\t\t\t\tthis.ui.showError(selectionError);\n\t\t\t} else {\n\t\t\t\tvoid this.ui.maybeWarnAboutAnthropicSubscriptionAuth();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate showBedrockSetupDialog(providerId: string, providerName: string): void {\n\t\tthis.cancelActiveDialog();\n\t\tconst dialog = new LoginDialogComponent(\n\t\t\tthis.ui.tui,\n\t\t\tproviderId,\n\t\t\t() => {\n\t\t\t\tthis.restoreEditorFromDialog(dialog);\n\t\t\t},\n\t\t\tproviderName,\n\t\t\t\"Amazon Bedrock setup\",\n\t\t);\n\t\tdialog.showInfo([\n\t\t\ttheme.fg(\"text\", \"Amazon Bedrock uses AWS credentials instead of a single API key.\"),\n\t\t\ttheme.fg(\"text\", \"Configure an AWS profile, IAM keys, bearer token, or role-based credentials.\"),\n\t\t\ttheme.fg(\"muted\", \"See:\"),\n\t\t\ttheme.fg(\"accent\", ` ${path.join(getDocsPath(), \"providers.md\")}`),\n\t\t]);\n\n\t\tthis.mountLoginDialog(dialog);\n\t}\n\n\tprivate async showApiKeyLoginDialog(providerId: string, providerName: string): Promise<void> {\n\t\tthis.cancelActiveDialog();\n\t\tconst previousModel = this.session.model;\n\n\t\tconst dialog = new LoginDialogComponent(\n\t\t\tthis.ui.tui,\n\t\t\tproviderId,\n\t\t\t(_success, _message) => {\n\t\t\t\t// Completion handled below\n\t\t\t},\n\t\t\tproviderName,\n\t\t);\n\n\t\tthis.mountLoginDialog(dialog);\n\n\t\tconst restoreEditor = () => this.restoreEditorFromDialog(dialog);\n\n\t\ttry {\n\t\t\tconst apiKey = (await dialog.showPrompt(\"Enter API key:\")).trim();\n\t\t\tif (!apiKey) {\n\t\t\t\tthrow new Error(\"API key cannot be empty.\");\n\t\t\t}\n\n\t\t\tthis.session.modelRegistry.authStorage.set(providerId, { type: \"api_key\", key: apiKey });\n\n\t\t\tif (!restoreEditor()) return;\n\t\t\tawait this.completeProviderAuthentication(providerId, providerName, \"api_key\", previousModel);\n\t\t} catch (error: unknown) {\n\t\t\tif (!restoreEditor()) return;\n\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\t\tif (errorMsg !== \"Login cancelled\") {\n\t\t\t\tthis.ui.showError(`Failed to save API key for ${providerName}: ${errorMsg}`);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate showOAuthLoginSelect(dialog: LoginDialogComponent, prompt: OAuthSelectPrompt): Promise<string | undefined> {\n\t\tthis.activeOAuthSelectorCancel?.();\n\t\treturn new Promise((resolve) => {\n\t\t\tlet settled = false;\n\t\t\tlet selector: ExtensionSelectorComponent;\n\t\t\tconst finish = (value: string | undefined, restoreDialog = true) => {\n\t\t\t\tif (settled) return;\n\t\t\t\tsettled = true;\n\t\t\t\tif (this.activeOAuthSelectorCancel === cancel) this.activeOAuthSelectorCancel = undefined;\n\t\t\t\tselector.dispose();\n\t\t\t\tif (restoreDialog) {\n\t\t\t\t\tthis.remountLoginDialog(dialog);\n\t\t\t\t} else if (this.clearActiveDialog(dialog)) {\n\t\t\t\t\tdialog.cancel();\n\t\t\t\t}\n\t\t\t\tresolve(value);\n\t\t\t};\n\t\t\tconst cancel = () => finish(undefined);\n\t\t\tthis.activeOAuthSelectorCancel = cancel;\n\t\t\tconst labels = prompt.options.map((option) => option.label);\n\t\t\tselector = new ExtensionSelectorComponent(\n\t\t\t\tprompt.message,\n\t\t\t\tlabels,\n\t\t\t\t(optionLabel) => finish(prompt.options.find((option) => option.label === optionLabel)?.id),\n\t\t\t\tcancel,\n\t\t\t);\n\t\t\tthis.detachLoginDialogForSelector(dialog);\n\t\t\tthis.ui.overlayHost.swap(selector, { onUnmount: () => finish(undefined, false) });\n\t\t});\n\t}\n\n\tprivate async showLoginDialog(providerId: string, providerName: string): Promise<void> {\n\t\tthis.cancelActiveDialog();\n\t\tconst providerInfo = this.session.modelRegistry.authStorage\n\t\t\t.getOAuthProviders()\n\t\t\t.find((provider) => provider.id === providerId);\n\t\tconst previousModel = this.session.model;\n\n\t\t// Providers that use callback servers (can paste redirect URL)\n\t\tconst usesCallbackServer = providerInfo?.usesCallbackServer ?? false;\n\n\t\t// Create login dialog component\n\t\tconst dialog = new LoginDialogComponent(\n\t\t\tthis.ui.tui,\n\t\t\tproviderId,\n\t\t\t(_success, _message) => {\n\t\t\t\t// Completion handled below\n\t\t\t},\n\t\t\tproviderName,\n\t\t);\n\n\t\t// Show dialog in editor container\n\t\tthis.mountLoginDialog(dialog);\n\n\t\t// Promise for manual code input (racing with callback server)\n\t\tlet manualCodeResolve: ((code: string) => void) | undefined;\n\t\tlet manualCodeReject: ((err: Error) => void) | undefined;\n\t\tconst manualCodePromise = new Promise<string>((resolve, reject) => {\n\t\t\tmanualCodeResolve = resolve;\n\t\t\tmanualCodeReject = reject;\n\t\t});\n\n\t\t// Restore editor helper\n\t\tconst restoreEditor = () => this.restoreEditorFromDialog(dialog);\n\n\t\ttry {\n\t\t\tawait this.session.modelRegistry.authStorage.login(providerId as OAuthProviderId, {\n\t\t\t\tonAuth: (info: { url: string; instructions?: string }) => {\n\t\t\t\t\tdialog.showAuth(info.url, info.instructions);\n\n\t\t\t\t\tif (usesCallbackServer) {\n\t\t\t\t\t\t// Show input for manual paste, racing with callback\n\t\t\t\t\t\tdialog\n\t\t\t\t\t\t\t.showManualInput(\"Paste redirect URL below, or complete login in browser:\")\n\t\t\t\t\t\t\t.then((value) => {\n\t\t\t\t\t\t\t\tif (value && manualCodeResolve) {\n\t\t\t\t\t\t\t\t\tmanualCodeResolve(value);\n\t\t\t\t\t\t\t\t\tmanualCodeResolve = undefined;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t.catch(() => {\n\t\t\t\t\t\t\t\tif (manualCodeReject) {\n\t\t\t\t\t\t\t\t\tmanualCodeReject(new Error(\"Login cancelled\"));\n\t\t\t\t\t\t\t\t\tmanualCodeReject = undefined;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\t// For Anthropic: onPrompt is called immediately after\n\t\t\t\t},\n\n\t\t\t\tonDeviceCode: (info) => {\n\t\t\t\t\tdialog.showDeviceCode(info);\n\t\t\t\t\tdialog.showWaiting(\"Waiting for authentication...\");\n\t\t\t\t},\n\n\t\t\t\tonPrompt: async (prompt: { message: string; placeholder?: string }) => {\n\t\t\t\t\treturn dialog.showPrompt(prompt.message, prompt.placeholder);\n\t\t\t\t},\n\n\t\t\t\tonProgress: (message: string) => {\n\t\t\t\t\tdialog.showProgress(message);\n\t\t\t\t},\n\n\t\t\t\tonSelect: (prompt: OAuthSelectPrompt) => this.showOAuthLoginSelect(dialog, prompt),\n\n\t\t\t\tonManualCodeInput: () => manualCodePromise,\n\n\t\t\t\tsignal: dialog.signal,\n\t\t\t});\n\n\t\t\t// Success\n\t\t\tif (!restoreEditor()) return;\n\t\t\tawait this.completeProviderAuthentication(providerId, providerName, \"oauth\", previousModel);\n\t\t} catch (error: unknown) {\n\t\t\tif (!restoreEditor()) return;\n\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\t\tif (errorMsg !== \"Login cancelled\") {\n\t\t\t\tthis.ui.showError(`Failed to login to ${providerName}: ${errorMsg}`);\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
@@ -37,6 +37,10 @@ export function isApiKeyLoginProvider(providerId, oauthProviderIds, builtInProvi
37
37
  }
38
38
  export class AuthDialogsController {
39
39
  deps;
40
+ activeLoginDialog;
41
+ activeLoginDialogOnUnmount;
42
+ suppressActiveLoginDialogUnmount = false;
43
+ activeOAuthSelectorCancel;
40
44
  constructor(deps) {
41
45
  this.deps = deps;
42
46
  }
@@ -46,6 +50,55 @@ export class AuthDialogsController {
46
50
  get ui() {
47
51
  return this.deps.ui;
48
52
  }
53
+ cancelActiveDialog() {
54
+ const cancelSelector = this.activeOAuthSelectorCancel;
55
+ this.activeOAuthSelectorCancel = undefined;
56
+ cancelSelector?.();
57
+ const dialog = this.activeLoginDialog;
58
+ if (!dialog || !this.clearActiveDialog(dialog))
59
+ return;
60
+ dialog.cancel();
61
+ this.ui.overlayHost.swap(this.ui.getEditor());
62
+ }
63
+ clearActiveDialog(dialog) {
64
+ if (this.activeLoginDialog !== dialog)
65
+ return false;
66
+ this.activeLoginDialog = undefined;
67
+ this.activeLoginDialogOnUnmount = undefined;
68
+ this.suppressActiveLoginDialogUnmount = false;
69
+ return true;
70
+ }
71
+ mountLoginDialog(dialog) {
72
+ this.activeLoginDialog = dialog;
73
+ const onUnmount = () => {
74
+ if (this.suppressActiveLoginDialogUnmount && this.activeLoginDialog === dialog) {
75
+ this.suppressActiveLoginDialogUnmount = false;
76
+ return;
77
+ }
78
+ if (!this.clearActiveDialog(dialog))
79
+ return;
80
+ dialog.cancel();
81
+ };
82
+ this.activeLoginDialogOnUnmount = onUnmount;
83
+ this.ui.overlayHost.swap(dialog, { onUnmount });
84
+ }
85
+ restoreEditorFromDialog(dialog) {
86
+ if (!this.clearActiveDialog(dialog))
87
+ return false;
88
+ this.ui.overlayHost.swap(this.ui.getEditor());
89
+ return true;
90
+ }
91
+ detachLoginDialogForSelector(dialog) {
92
+ if (this.activeLoginDialog === dialog && this.activeLoginDialogOnUnmount) {
93
+ this.suppressActiveLoginDialogUnmount = true;
94
+ }
95
+ }
96
+ remountLoginDialog(dialog) {
97
+ if (this.activeLoginDialog !== dialog || !this.activeLoginDialogOnUnmount)
98
+ return false;
99
+ this.ui.overlayHost.swap(dialog, { onUnmount: this.activeLoginDialogOnUnmount });
100
+ return true;
101
+ }
49
102
  getLoginProviderOptions(authType) {
50
103
  const authStorage = this.session.modelRegistry.authStorage;
51
104
  const oauthProviders = authStorage.getOAuthProviders();
@@ -267,38 +320,39 @@ export class AuthDialogsController {
267
320
  }
268
321
  }
269
322
  showBedrockSetupDialog(providerId, providerName) {
270
- const restoreEditor = () => {
271
- this.ui.overlayHost.swap(this.ui.getEditor());
272
- };
273
- const dialog = new LoginDialogComponent(this.ui.tui, providerId, () => restoreEditor(), providerName, "Amazon Bedrock setup");
323
+ this.cancelActiveDialog();
324
+ const dialog = new LoginDialogComponent(this.ui.tui, providerId, () => {
325
+ this.restoreEditorFromDialog(dialog);
326
+ }, providerName, "Amazon Bedrock setup");
274
327
  dialog.showInfo([
275
328
  theme.fg("text", "Amazon Bedrock uses AWS credentials instead of a single API key."),
276
329
  theme.fg("text", "Configure an AWS profile, IAM keys, bearer token, or role-based credentials."),
277
330
  theme.fg("muted", "See:"),
278
331
  theme.fg("accent", ` ${path.join(getDocsPath(), "providers.md")}`),
279
332
  ]);
280
- this.ui.overlayHost.swap(dialog);
333
+ this.mountLoginDialog(dialog);
281
334
  }
282
335
  async showApiKeyLoginDialog(providerId, providerName) {
336
+ this.cancelActiveDialog();
283
337
  const previousModel = this.session.model;
284
338
  const dialog = new LoginDialogComponent(this.ui.tui, providerId, (_success, _message) => {
285
339
  // Completion handled below
286
340
  }, providerName);
287
- this.ui.overlayHost.swap(dialog);
288
- const restoreEditor = () => {
289
- this.ui.overlayHost.swap(this.ui.getEditor());
290
- };
341
+ this.mountLoginDialog(dialog);
342
+ const restoreEditor = () => this.restoreEditorFromDialog(dialog);
291
343
  try {
292
344
  const apiKey = (await dialog.showPrompt("Enter API key:")).trim();
293
345
  if (!apiKey) {
294
346
  throw new Error("API key cannot be empty.");
295
347
  }
296
348
  this.session.modelRegistry.authStorage.set(providerId, { type: "api_key", key: apiKey });
297
- restoreEditor();
349
+ if (!restoreEditor())
350
+ return;
298
351
  await this.completeProviderAuthentication(providerId, providerName, "api_key", previousModel);
299
352
  }
300
353
  catch (error) {
301
- restoreEditor();
354
+ if (!restoreEditor())
355
+ return;
302
356
  const errorMsg = error instanceof Error ? error.message : String(error);
303
357
  if (errorMsg !== "Login cancelled") {
304
358
  this.ui.showError(`Failed to save API key for ${providerName}: ${errorMsg}`);
@@ -306,22 +360,35 @@ export class AuthDialogsController {
306
360
  }
307
361
  }
308
362
  showOAuthLoginSelect(dialog, prompt) {
363
+ this.activeOAuthSelectorCancel?.();
309
364
  return new Promise((resolve) => {
310
- const restoreDialog = () => {
311
- this.ui.overlayHost.swap(dialog);
365
+ let settled = false;
366
+ let selector;
367
+ const finish = (value, restoreDialog = true) => {
368
+ if (settled)
369
+ return;
370
+ settled = true;
371
+ if (this.activeOAuthSelectorCancel === cancel)
372
+ this.activeOAuthSelectorCancel = undefined;
373
+ selector.dispose();
374
+ if (restoreDialog) {
375
+ this.remountLoginDialog(dialog);
376
+ }
377
+ else if (this.clearActiveDialog(dialog)) {
378
+ dialog.cancel();
379
+ }
380
+ resolve(value);
312
381
  };
382
+ const cancel = () => finish(undefined);
383
+ this.activeOAuthSelectorCancel = cancel;
313
384
  const labels = prompt.options.map((option) => option.label);
314
- const selector = new ExtensionSelectorComponent(prompt.message, labels, (optionLabel) => {
315
- restoreDialog();
316
- resolve(prompt.options.find((option) => option.label === optionLabel)?.id);
317
- }, () => {
318
- restoreDialog();
319
- resolve(undefined);
320
- });
321
- this.ui.overlayHost.swap(selector);
385
+ selector = new ExtensionSelectorComponent(prompt.message, labels, (optionLabel) => finish(prompt.options.find((option) => option.label === optionLabel)?.id), cancel);
386
+ this.detachLoginDialogForSelector(dialog);
387
+ this.ui.overlayHost.swap(selector, { onUnmount: () => finish(undefined, false) });
322
388
  });
323
389
  }
324
390
  async showLoginDialog(providerId, providerName) {
391
+ this.cancelActiveDialog();
325
392
  const providerInfo = this.session.modelRegistry.authStorage
326
393
  .getOAuthProviders()
327
394
  .find((provider) => provider.id === providerId);
@@ -333,7 +400,7 @@ export class AuthDialogsController {
333
400
  // Completion handled below
334
401
  }, providerName);
335
402
  // Show dialog in editor container
336
- this.ui.overlayHost.swap(dialog);
403
+ this.mountLoginDialog(dialog);
337
404
  // Promise for manual code input (racing with callback server)
338
405
  let manualCodeResolve;
339
406
  let manualCodeReject;
@@ -342,9 +409,7 @@ export class AuthDialogsController {
342
409
  manualCodeReject = reject;
343
410
  });
344
411
  // Restore editor helper
345
- const restoreEditor = () => {
346
- this.ui.overlayHost.swap(this.ui.getEditor());
347
- };
412
+ const restoreEditor = () => this.restoreEditorFromDialog(dialog);
348
413
  try {
349
414
  await this.session.modelRegistry.authStorage.login(providerId, {
350
415
  onAuth: (info) => {
@@ -383,11 +448,13 @@ export class AuthDialogsController {
383
448
  signal: dialog.signal,
384
449
  });
385
450
  // Success
386
- restoreEditor();
451
+ if (!restoreEditor())
452
+ return;
387
453
  await this.completeProviderAuthentication(providerId, providerName, "oauth", previousModel);
388
454
  }
389
455
  catch (error) {
390
- restoreEditor();
456
+ if (!restoreEditor())
457
+ return;
391
458
  const errorMsg = error instanceof Error ? error.message : String(error);
392
459
  if (errorMsg !== "Login cancelled") {
393
460
  this.ui.showError(`Failed to login to ${providerName}: ${errorMsg}`);