@earendil-works/pi-coding-agent 0.99.2 → 1.0.1

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 (225) hide show
  1. package/CHANGELOG.md +90 -0
  2. package/README.md +32 -7
  3. package/dist/bundle/chunks/{anthropic-messages-UID2PALB.js → anthropic-messages-GXHZP2HL.js} +3 -3
  4. package/dist/bundle/chunks/anthropic.js +2 -2
  5. package/dist/bundle/chunks/{azure-openai-responses-TLHNIYZK.js → azure-openai-responses-AFMVM6NP.js} +1 -1
  6. package/dist/bundle/chunks/bedrock-converse-stream.js +1 -1
  7. package/dist/bundle/chunks/chunk-2KAZSACP.js +2 -0
  8. package/dist/bundle/chunks/{chunk-R5J3MOBF.js → chunk-2VNGUWBO.js} +1 -1
  9. package/dist/bundle/chunks/chunk-5OEJBNHG.js +1203 -0
  10. package/dist/bundle/chunks/{chunk-7QSPBJKW.js → chunk-6FX7UEPL.js} +16 -30
  11. package/dist/bundle/chunks/chunk-F5ZABL6Z.js +20 -0
  12. package/dist/bundle/chunks/chunk-FDW3AYMM.js +2 -0
  13. package/dist/bundle/chunks/chunk-OYBSLV7Y.js +16 -0
  14. package/dist/bundle/chunks/{chunk-45SXDISG.js → chunk-PDFMCAOZ.js} +5 -5
  15. package/dist/bundle/chunks/{chunk-G3UZ5FWD.js → chunk-SYF2TF6W.js} +11 -60
  16. package/dist/bundle/chunks/chunk-WCQZGZ6I.js +82 -0
  17. package/dist/bundle/chunks/chunk-ZSI3BL5Q.js +4 -0
  18. package/dist/bundle/chunks/{cli-ALNBTL3U.js → cli-KILDDGW3.js} +4 -4
  19. package/dist/bundle/chunks/{cloudflare-workers-ai-system-one-NPQN263E.js → cloudflare-workers-ai-system-one-X5PVWWYJ.js} +1 -1
  20. package/dist/bundle/chunks/codemode-worker.js +68 -8
  21. package/dist/bundle/chunks/easter-egg-3d-T5FFWIBR.js +2 -0
  22. package/dist/bundle/chunks/execute-RYVK27GT.js +388 -0
  23. package/dist/bundle/chunks/node-N5BSDOA5.js +16 -0
  24. package/dist/bundle/chunks/openai-chatgpt.js +2 -2
  25. package/dist/bundle/chunks/{openai-codex-responses-3GKGNXC4.js → openai-codex-responses-GK67DQQJ.js} +1 -1
  26. package/dist/bundle/chunks/openai-codex.js +1 -1
  27. package/dist/bundle/chunks/{openai-responses-S7GKCCDG.js → openai-responses-CQDDLDQF.js} +1 -1
  28. package/dist/bundle/chunks/openrouter.js +1 -1
  29. package/dist/bundle/chunks/radius.js +1 -1
  30. package/dist/bundle/chunks/runtime-D5I2NTIF.js +2 -0
  31. package/dist/bundle/chunks/virtual-modules-OO3V5ZPE.js +2 -0
  32. package/dist/bundle/cli-runtime.js +1 -1
  33. package/dist/bundle/index.js +1 -1
  34. package/dist/bundle/rpc-entry.js +1 -1
  35. package/dist/cli/args.d.ts.map +1 -1
  36. package/dist/cli/args.js +6 -3
  37. package/dist/cli/args.js.map +1 -1
  38. package/dist/config.d.ts.map +1 -1
  39. package/dist/config.js +3 -0
  40. package/dist/config.js.map +1 -1
  41. package/dist/core/agent-session.d.ts +8 -0
  42. package/dist/core/agent-session.d.ts.map +1 -1
  43. package/dist/core/agent-session.js +38 -9
  44. package/dist/core/agent-session.js.map +1 -1
  45. package/dist/core/export-html/tool-renderer.d.ts +3 -3
  46. package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
  47. package/dist/core/export-html/tool-renderer.js +3 -3
  48. package/dist/core/export-html/tool-renderer.js.map +1 -1
  49. package/dist/core/extensions/index.d.ts +1 -1
  50. package/dist/core/extensions/index.d.ts.map +1 -1
  51. package/dist/core/extensions/index.js.map +1 -1
  52. package/dist/core/extensions/loader.d.ts.map +1 -1
  53. package/dist/core/extensions/loader.js +5 -0
  54. package/dist/core/extensions/loader.js.map +1 -1
  55. package/dist/core/extensions/runner.d.ts +3 -1
  56. package/dist/core/extensions/runner.d.ts.map +1 -1
  57. package/dist/core/extensions/runner.js +6 -0
  58. package/dist/core/extensions/runner.js.map +1 -1
  59. package/dist/core/extensions/types.d.ts +9 -0
  60. package/dist/core/extensions/types.d.ts.map +1 -1
  61. package/dist/core/extensions/types.js.map +1 -1
  62. package/dist/core/mcp-servers.d.ts +12 -0
  63. package/dist/core/mcp-servers.d.ts.map +1 -1
  64. package/dist/core/mcp-servers.js +18 -0
  65. package/dist/core/mcp-servers.js.map +1 -1
  66. package/dist/core/model-registry.d.ts +3 -1
  67. package/dist/core/model-registry.d.ts.map +1 -1
  68. package/dist/core/model-registry.js +4 -0
  69. package/dist/core/model-registry.js.map +1 -1
  70. package/dist/core/model-resolver.js +1 -1
  71. package/dist/core/model-resolver.js.map +1 -1
  72. package/dist/core/radius.d.ts +2 -0
  73. package/dist/core/radius.d.ts.map +1 -1
  74. package/dist/core/radius.js +2 -0
  75. package/dist/core/radius.js.map +1 -1
  76. package/dist/core/settings-manager.d.ts +7 -5
  77. package/dist/core/settings-manager.d.ts.map +1 -1
  78. package/dist/core/settings-manager.js +3 -2
  79. package/dist/core/settings-manager.js.map +1 -1
  80. package/dist/core/system-prompt.js +1 -1
  81. package/dist/core/system-prompt.js.map +1 -1
  82. package/dist/core/tools/bash.d.ts.map +1 -1
  83. package/dist/core/tools/bash.js +3 -5
  84. package/dist/core/tools/bash.js.map +1 -1
  85. package/dist/core/tools/renderers/index.d.ts +2 -2
  86. package/dist/core/tools/renderers/index.d.ts.map +1 -1
  87. package/dist/core/tools/renderers/index.js.map +1 -1
  88. package/dist/extensions/codemode/execute.d.ts.map +1 -1
  89. package/dist/extensions/codemode/execute.js +154 -47
  90. package/dist/extensions/codemode/execute.js.map +1 -1
  91. package/dist/extensions/codemode/tool.d.ts +7 -7
  92. package/dist/extensions/codemode/tool.d.ts.map +1 -1
  93. package/dist/extensions/codemode/tool.js +55 -102
  94. package/dist/extensions/codemode/tool.js.map +1 -1
  95. package/dist/extensions/mcp/cli.d.ts.map +1 -1
  96. package/dist/extensions/mcp/cli.js +5 -2
  97. package/dist/extensions/mcp/cli.js.map +1 -1
  98. package/dist/extensions/mcp/config.d.ts +15 -3
  99. package/dist/extensions/mcp/config.d.ts.map +1 -1
  100. package/dist/extensions/mcp/config.js +46 -10
  101. package/dist/extensions/mcp/config.js.map +1 -1
  102. package/dist/extensions/mcp/index.d.ts +4 -1
  103. package/dist/extensions/mcp/index.d.ts.map +1 -1
  104. package/dist/extensions/mcp/index.js +97 -51
  105. package/dist/extensions/mcp/index.js.map +1 -1
  106. package/dist/extensions/mcp/oauth.d.ts +12 -8
  107. package/dist/extensions/mcp/oauth.d.ts.map +1 -1
  108. package/dist/extensions/mcp/oauth.js +104 -35
  109. package/dist/extensions/mcp/oauth.js.map +1 -1
  110. package/dist/extensions/mcp/runtime.d.ts.map +1 -1
  111. package/dist/extensions/mcp/runtime.js +3 -1
  112. package/dist/extensions/mcp/runtime.js.map +1 -1
  113. package/dist/extensions/mcp/tools.d.ts +3 -1
  114. package/dist/extensions/mcp/tools.d.ts.map +1 -1
  115. package/dist/extensions/mcp/tools.js +19 -13
  116. package/dist/extensions/mcp/tools.js.map +1 -1
  117. package/dist/extensions/mcp/ui.d.ts.map +1 -1
  118. package/dist/extensions/mcp/ui.js +8 -4
  119. package/dist/extensions/mcp/ui.js.map +1 -1
  120. package/dist/index.d.ts +2 -2
  121. package/dist/index.d.ts.map +1 -1
  122. package/dist/index.js.map +1 -1
  123. package/dist/main.d.ts.map +1 -1
  124. package/dist/main.js +6 -0
  125. package/dist/main.js.map +1 -1
  126. package/dist/modes/interactive/components/armin.d.ts +3 -0
  127. package/dist/modes/interactive/components/armin.d.ts.map +1 -1
  128. package/dist/modes/interactive/components/armin.js +7 -5
  129. package/dist/modes/interactive/components/armin.js.map +1 -1
  130. package/dist/modes/interactive/components/auth-url.d.ts +14 -0
  131. package/dist/modes/interactive/components/auth-url.d.ts.map +1 -0
  132. package/dist/modes/interactive/components/auth-url.js +37 -0
  133. package/dist/modes/interactive/components/auth-url.js.map +1 -0
  134. package/dist/modes/interactive/components/easter-egg-3d.d.ts +104 -0
  135. package/dist/modes/interactive/components/easter-egg-3d.d.ts.map +1 -0
  136. package/dist/modes/interactive/components/easter-egg-3d.js +1139 -0
  137. package/dist/modes/interactive/components/easter-egg-3d.js.map +1 -0
  138. package/dist/modes/interactive/components/easter-egg-3d.lazy.d.ts +6 -0
  139. package/dist/modes/interactive/components/easter-egg-3d.lazy.d.ts.map +1 -0
  140. package/dist/modes/interactive/components/easter-egg-3d.lazy.js +23 -0
  141. package/dist/modes/interactive/components/easter-egg-3d.lazy.js.map +1 -0
  142. package/dist/modes/interactive/components/index.d.ts +0 -1
  143. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  144. package/dist/modes/interactive/components/index.js +0 -1
  145. package/dist/modes/interactive/components/index.js.map +1 -1
  146. package/dist/modes/interactive/components/login-dialog.d.ts +2 -0
  147. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  148. package/dist/modes/interactive/components/login-dialog.js +11 -5
  149. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  150. package/dist/modes/interactive/components/oauth-selector.d.ts +8 -2
  151. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  152. package/dist/modes/interactive/components/oauth-selector.js +24 -21
  153. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  154. package/dist/modes/interactive/components/pi-logo.d.ts +7 -0
  155. package/dist/modes/interactive/components/pi-logo.d.ts.map +1 -1
  156. package/dist/modes/interactive/components/pi-logo.js +13 -1
  157. package/dist/modes/interactive/components/pi-logo.js.map +1 -1
  158. package/dist/modes/interactive/components/radius-login-selector.d.ts +15 -0
  159. package/dist/modes/interactive/components/radius-login-selector.d.ts.map +1 -0
  160. package/dist/modes/interactive/components/radius-login-selector.js +85 -0
  161. package/dist/modes/interactive/components/radius-login-selector.js.map +1 -0
  162. package/dist/modes/interactive/components/settings-selector.d.ts +3 -3
  163. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  164. package/dist/modes/interactive/components/settings-selector.js +5 -5
  165. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  166. package/dist/modes/interactive/components/tool-execution.d.ts +6 -18
  167. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  168. package/dist/modes/interactive/components/tool-execution.js +22 -45
  169. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  170. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  171. package/dist/modes/interactive/components/user-message.js +5 -4
  172. package/dist/modes/interactive/components/user-message.js.map +1 -1
  173. package/dist/modes/interactive/interactive-mode.d.ts +12 -2
  174. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  175. package/dist/modes/interactive/interactive-mode.js +166 -55
  176. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  177. package/dist/modes/interactive/theme/system-theme.d.ts +2 -1
  178. package/dist/modes/interactive/theme/system-theme.d.ts.map +1 -1
  179. package/dist/modes/interactive/theme/system-theme.js +16 -5
  180. package/dist/modes/interactive/theme/system-theme.js.map +1 -1
  181. package/dist/package-manager-cli.d.ts.map +1 -1
  182. package/dist/package-manager-cli.js +12 -0
  183. package/dist/package-manager-cli.js.map +1 -1
  184. package/dist/utils/image-convert.d.ts +12 -0
  185. package/dist/utils/image-convert.d.ts.map +1 -1
  186. package/dist/utils/image-convert.js +45 -6
  187. package/dist/utils/image-convert.js.map +1 -1
  188. package/docs/cli.md +8 -16
  189. package/docs/codemode.md +207 -0
  190. package/docs/docs.json +5 -1
  191. package/docs/environment-variables.md +2 -2
  192. package/docs/extensions.md +4 -0
  193. package/docs/index.md +1 -1
  194. package/docs/keybindings.md +1 -1
  195. package/docs/mcp.md +40 -1
  196. package/docs/models.md +24 -3
  197. package/docs/providers.md +16 -6
  198. package/docs/quickstart.md +16 -2
  199. package/docs/sdk.md +1 -1
  200. package/docs/settings.md +3 -3
  201. package/docs/usage.md +1 -1
  202. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  203. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  204. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  205. package/examples/extensions/gondolin/package-lock.json +2 -2
  206. package/examples/extensions/gondolin/package.json +1 -1
  207. package/examples/extensions/sandbox/package-lock.json +2 -2
  208. package/examples/extensions/sandbox/package.json +1 -1
  209. package/examples/extensions/with-deps/package-lock.json +2 -2
  210. package/examples/extensions/with-deps/package.json +1 -1
  211. package/package.json +13 -14
  212. package/dist/bundle/chunks/chunk-3KYEVQKX.js +0 -82
  213. package/dist/bundle/chunks/chunk-3NVH2HQH.js +0 -4
  214. package/dist/bundle/chunks/chunk-3YAHQSW6.js +0 -1438
  215. package/dist/bundle/chunks/chunk-DTD7JQ7Y.js +0 -42
  216. package/dist/bundle/chunks/chunk-ECRK44UV.js +0 -2
  217. package/dist/bundle/chunks/execute-RC7W4ML3.js +0 -328
  218. package/dist/bundle/chunks/node-O3RIBJRH.js +0 -16
  219. package/dist/bundle/chunks/runtime-NJPX4ID2.js +0 -2
  220. package/dist/bundle/chunks/virtual-modules-5UGH4HRZ.js +0 -2
  221. package/dist/modes/interactive/components/daxnuts.d.ts +0 -23
  222. package/dist/modes/interactive/components/daxnuts.d.ts.map +0 -1
  223. package/dist/modes/interactive/components/daxnuts.js +0 -140
  224. package/dist/modes/interactive/components/daxnuts.js.map +0 -1
  225. package/npm-shrinkwrap.json +0 -1957
@@ -1,8 +1,28 @@
1
1
  import { Container, fuzzyFilter, getKeybindings, Input, Spacer, TruncatedText, } from "@earendil-works/pi-tui";
2
2
  import { theme } from "../theme/theme.js";
3
3
  import { DynamicBorder } from "./dynamic-border.js";
4
- export function formatAuthSelectorProviderType(authType) {
5
- return authType === "oauth" ? "subscription" : "API key";
4
+ export function formatAuthSelectorProviderType(authType, subscription) {
5
+ if (authType === "api_key")
6
+ return "API key";
7
+ return subscription === false ? "account" : "subscription";
8
+ }
9
+ /** Themed suffix describing whether and how a login option is configured, for example " ✓ configured". */
10
+ export function formatAuthSelectorProviderStatus(provider) {
11
+ if (!provider.status)
12
+ return theme.fg("muted", " • not configured");
13
+ if (provider.status.type !== provider.authType) {
14
+ const label = `${formatAuthSelectorProviderType(provider.status.type, provider.subscription)} configured`;
15
+ return theme.fg("muted", " • ") + theme.fg("warning", label);
16
+ }
17
+ if (!provider.status.source ||
18
+ provider.status.source === "OAuth" ||
19
+ provider.status.source === "stored credential") {
20
+ return theme.fg("success", " ✓ configured");
21
+ }
22
+ const source = /^[A-Z][A-Z0-9_]*(?:, [A-Z][A-Z0-9_]*)*$/.test(provider.status.source)
23
+ ? `env: ${provider.status.source}`
24
+ : provider.status.source;
25
+ return theme.fg("success", ` ✓ ${source}`);
6
26
  }
7
27
  /**
8
28
  * Component that renders an auth provider selector
@@ -79,9 +99,9 @@ export class OAuthSelectorComponent extends Container {
79
99
  if (!provider)
80
100
  continue;
81
101
  const isSelected = i === this.selectedIndex;
82
- const statusIndicator = this.formatStatusIndicator(provider);
102
+ const statusIndicator = formatAuthSelectorProviderStatus(provider);
83
103
  const authTypeLabel = this.showAuthTypeLabels
84
- ? theme.fg("muted", ` [${formatAuthSelectorProviderType(provider.authType)}]`)
104
+ ? theme.fg("muted", ` [${formatAuthSelectorProviderType(provider.authType, provider.subscription)}]`)
85
105
  : "";
86
106
  let line = "";
87
107
  if (isSelected) {
@@ -109,23 +129,6 @@ export class OAuthSelectorComponent extends Container {
109
129
  this.listContainer.addChild(new TruncatedText(theme.fg("muted", ` ${message}`), 1, 0));
110
130
  }
111
131
  }
112
- formatStatusIndicator(provider) {
113
- if (!provider.status)
114
- return theme.fg("muted", " • unconfigured");
115
- if (provider.status.type !== provider.authType) {
116
- const label = provider.status.type === "oauth" ? "subscription configured" : "API key configured";
117
- return theme.fg("muted", " • ") + theme.fg("warning", label);
118
- }
119
- if (!provider.status.source ||
120
- provider.status.source === "OAuth" ||
121
- provider.status.source === "stored credential") {
122
- return theme.fg("success", " ✓ configured");
123
- }
124
- const source = /^[A-Z][A-Z0-9_]*(?:, [A-Z][A-Z0-9_]*)*$/.test(provider.status.source)
125
- ? `env: ${provider.status.source}`
126
- : provider.status.source;
127
- return theme.fg("success", ` ✓ ${source}`);
128
- }
129
132
  handleInput(keyData) {
130
133
  const kb = getKeybindings();
131
134
  // Up arrow
@@ -1 +1 @@
1
- {"version":3,"file":"oauth-selector.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/oauth-selector.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ApiKeyAuth, AuthCheck, OAuthAuth } from \"@earendil-works/pi-ai\";\nimport {\n\tContainer,\n\ttype Focusable,\n\tfuzzyFilter,\n\tgetKeybindings,\n\tInput,\n\tSpacer,\n\tTruncatedText,\n} from \"@earendil-works/pi-tui\";\nimport { theme } from \"../theme/theme.ts\";\nimport { DynamicBorder } from \"./dynamic-border.ts\";\n\nexport type AuthSelectorProvider = {\n\tid: string;\n\tname: string;\n\tauthType: \"oauth\" | \"api_key\";\n\tmethod?: ApiKeyAuth | OAuthAuth;\n\tstatus?: AuthCheck;\n};\n\nexport function formatAuthSelectorProviderType(authType: AuthSelectorProvider[\"authType\"]): string {\n\treturn authType === \"oauth\" ? \"subscription\" : \"API key\";\n}\n\n/**\n * Component that renders an auth provider selector\n */\nexport class OAuthSelectorComponent extends Container implements Focusable {\n\tprivate searchInput: Input;\n\n\t// Focusable implementation - propagate to search input for IME cursor positioning\n\tprivate _focused = false;\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.searchInput.focused = value;\n\t}\n\n\tprivate listContainer: Container;\n\tprivate allProviders: AuthSelectorProvider[];\n\tprivate filteredProviders: AuthSelectorProvider[];\n\tprivate selectedIndex: number = 0;\n\tprivate mode: \"login\" | \"logout\";\n\tprivate onSelectCallback: (providerId: string, authType: AuthSelectorProvider[\"authType\"]) => void;\n\tprivate onCancelCallback: () => void;\n\tprivate showAuthTypeLabels: boolean;\n\n\tconstructor(\n\t\tmode: \"login\" | \"logout\",\n\t\tproviders: AuthSelectorProvider[],\n\t\tonSelect: (providerId: string, authType: AuthSelectorProvider[\"authType\"]) => void,\n\t\tonCancel: () => void,\n\t\tinitialSearchInput?: string,\n\t) {\n\t\tsuper();\n\n\t\tthis.mode = mode;\n\t\tthis.allProviders = providers;\n\t\tthis.filteredProviders = providers;\n\t\tthis.showAuthTypeLabels = new Set(providers.map((provider) => provider.authType)).size > 1;\n\t\tthis.onSelectCallback = onSelect;\n\t\tthis.onCancelCallback = onCancel;\n\n\t\t// Add top border\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Add title\n\t\tconst title = mode === \"login\" ? \"Select provider to configure:\" : \"Select provider to logout:\";\n\t\tthis.addChild(new TruncatedText(theme.fg(\"accent\", theme.bold(title)), 1, 0));\n\t\tthis.addChild(new Spacer(1));\n\n\t\tthis.searchInput = new Input();\n\t\tif (initialSearchInput) {\n\t\t\tthis.searchInput.setValue(initialSearchInput);\n\t\t}\n\t\tthis.searchInput.onSubmit = () => {\n\t\t\tconst selectedProvider = this.filteredProviders[this.selectedIndex];\n\t\t\tif (selectedProvider) {\n\t\t\t\tthis.onSelectCallback(selectedProvider.id, selectedProvider.authType);\n\t\t\t}\n\t\t};\n\t\tthis.addChild(this.searchInput);\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Create list container\n\t\tthis.listContainer = new Container();\n\t\tthis.addChild(this.listContainer);\n\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Add bottom border\n\t\tthis.addChild(new DynamicBorder());\n\n\t\t// Initial render\n\t\tthis.filterProviders(initialSearchInput ?? \"\");\n\t}\n\n\tprivate filterProviders(query: string): void {\n\t\tthis.filteredProviders = query\n\t\t\t? fuzzyFilter(\n\t\t\t\t\tthis.allProviders,\n\t\t\t\t\tquery,\n\t\t\t\t\t(provider) => `${provider.name} ${provider.id} ${provider.authType} ${provider.method?.name ?? \"\"}`,\n\t\t\t\t)\n\t\t\t: this.allProviders;\n\t\tthis.selectedIndex = Math.max(0, Math.min(this.selectedIndex, Math.max(0, this.filteredProviders.length - 1)));\n\t\tthis.updateList();\n\t}\n\n\tprivate updateList(): void {\n\t\tthis.listContainer.clear();\n\n\t\tconst maxVisible = 8;\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(this.selectedIndex - Math.floor(maxVisible / 2), this.filteredProviders.length - maxVisible),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + maxVisible, this.filteredProviders.length);\n\n\t\tfor (let i = startIndex; i < endIndex; i++) {\n\t\t\tconst provider = this.filteredProviders[i];\n\t\t\tif (!provider) continue;\n\n\t\t\tconst isSelected = i === this.selectedIndex;\n\n\t\t\tconst statusIndicator = this.formatStatusIndicator(provider);\n\t\t\tconst authTypeLabel = this.showAuthTypeLabels\n\t\t\t\t? theme.fg(\"muted\", ` [${formatAuthSelectorProviderType(provider.authType)}]`)\n\t\t\t\t: \"\";\n\t\t\tlet line = \"\";\n\t\t\tif (isSelected) {\n\t\t\t\tconst prefix = theme.fg(\"accent\", \"→ \");\n\t\t\t\tconst text = theme.fg(\"accent\", provider.name);\n\t\t\t\tline = prefix + text + authTypeLabel + statusIndicator;\n\t\t\t} else {\n\t\t\t\tconst text = ` ${theme.fg(\"text\", provider.name)}`;\n\t\t\t\tline = text + authTypeLabel + statusIndicator;\n\t\t\t}\n\n\t\t\tthis.listContainer.addChild(new TruncatedText(line, 1, 0));\n\t\t}\n\n\t\tif (startIndex > 0 || endIndex < this.filteredProviders.length) {\n\t\t\tconst scrollInfo = theme.fg(\"muted\", ` (${this.selectedIndex + 1}/${this.filteredProviders.length})`);\n\t\t\tthis.listContainer.addChild(new TruncatedText(scrollInfo, 1, 0));\n\t\t}\n\n\t\t// Show \"no providers\" if empty\n\t\tif (this.filteredProviders.length === 0) {\n\t\t\tconst message =\n\t\t\t\tthis.allProviders.length === 0\n\t\t\t\t\t? this.mode === \"login\"\n\t\t\t\t\t\t? \"No providers available\"\n\t\t\t\t\t\t: \"No providers logged in. Use /login first.\"\n\t\t\t\t\t: \"No matching providers\";\n\t\t\tthis.listContainer.addChild(new TruncatedText(theme.fg(\"muted\", ` ${message}`), 1, 0));\n\t\t}\n\t}\n\n\tprivate formatStatusIndicator(provider: AuthSelectorProvider): string {\n\t\tif (!provider.status) return theme.fg(\"muted\", \" • unconfigured\");\n\t\tif (provider.status.type !== provider.authType) {\n\t\t\tconst label = provider.status.type === \"oauth\" ? \"subscription configured\" : \"API key configured\";\n\t\t\treturn theme.fg(\"muted\", \" • \") + theme.fg(\"warning\", label);\n\t\t}\n\t\tif (\n\t\t\t!provider.status.source ||\n\t\t\tprovider.status.source === \"OAuth\" ||\n\t\t\tprovider.status.source === \"stored credential\"\n\t\t) {\n\t\t\treturn theme.fg(\"success\", \" ✓ configured\");\n\t\t}\n\t\tconst source = /^[A-Z][A-Z0-9_]*(?:, [A-Z][A-Z0-9_]*)*$/.test(provider.status.source)\n\t\t\t? `env: ${provider.status.source}`\n\t\t\t: provider.status.source;\n\t\treturn theme.fg(\"success\", ` ✓ ${source}`);\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getKeybindings();\n\t\t// Up arrow\n\t\tif (kb.matches(keyData, \"tui.select.up\")) {\n\t\t\tif (this.filteredProviders.length === 0) return;\n\t\t\tthis.selectedIndex = Math.max(0, this.selectedIndex - 1);\n\t\t\tthis.updateList();\n\t\t}\n\t\t// Down arrow\n\t\telse if (kb.matches(keyData, \"tui.select.down\")) {\n\t\t\tif (this.filteredProviders.length === 0) return;\n\t\t\tthis.selectedIndex = Math.min(this.filteredProviders.length - 1, this.selectedIndex + 1);\n\t\t\tthis.updateList();\n\t\t}\n\t\t// Enter\n\t\telse if (kb.matches(keyData, \"tui.select.confirm\")) {\n\t\t\tconst selectedProvider = this.filteredProviders[this.selectedIndex];\n\t\t\tif (selectedProvider) {\n\t\t\t\tthis.onSelectCallback(selectedProvider.id, selectedProvider.authType);\n\t\t\t}\n\t\t}\n\t\t// Escape or Ctrl+C\n\t\telse if (kb.matches(keyData, \"tui.select.cancel\")) {\n\t\t\tthis.onCancelCallback();\n\t\t}\n\t\t// Pass everything else to search input\n\t\telse {\n\t\t\tthis.searchInput.handleInput(keyData);\n\t\t\tthis.filterProviders(this.searchInput.getValue());\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"oauth-selector.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/oauth-selector.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ApiKeyAuth, AuthCheck, OAuthAuth } from \"@earendil-works/pi-ai\";\nimport {\n\tContainer,\n\ttype Focusable,\n\tfuzzyFilter,\n\tgetKeybindings,\n\tInput,\n\tSpacer,\n\tTruncatedText,\n} from \"@earendil-works/pi-tui\";\nimport { theme } from \"../theme/theme.ts\";\nimport { DynamicBorder } from \"./dynamic-border.ts\";\n\nexport type AuthSelectorProvider = {\n\tid: string;\n\tname: string;\n\tauthType: \"oauth\" | \"api_key\";\n\tmethod?: ApiKeyAuth | OAuthAuth;\n\tstatus?: AuthCheck;\n\t/**\n\t * Whether the provider's OAuth sign-in is backed by a subscription. `false` labels it as an account;\n\t * unset keeps the \"subscription\" label.\n\t */\n\tsubscription?: boolean;\n};\n\nexport function formatAuthSelectorProviderType(\n\tauthType: AuthSelectorProvider[\"authType\"],\n\tsubscription?: boolean,\n): string {\n\tif (authType === \"api_key\") return \"API key\";\n\treturn subscription === false ? \"account\" : \"subscription\";\n}\n\n/** Themed suffix describing whether and how a login option is configured, for example \" ✓ configured\". */\nexport function formatAuthSelectorProviderStatus(provider: AuthSelectorProvider): string {\n\tif (!provider.status) return theme.fg(\"muted\", \" • not configured\");\n\tif (provider.status.type !== provider.authType) {\n\t\tconst label = `${formatAuthSelectorProviderType(provider.status.type, provider.subscription)} configured`;\n\t\treturn theme.fg(\"muted\", \" • \") + theme.fg(\"warning\", label);\n\t}\n\tif (\n\t\t!provider.status.source ||\n\t\tprovider.status.source === \"OAuth\" ||\n\t\tprovider.status.source === \"stored credential\"\n\t) {\n\t\treturn theme.fg(\"success\", \" ✓ configured\");\n\t}\n\tconst source = /^[A-Z][A-Z0-9_]*(?:, [A-Z][A-Z0-9_]*)*$/.test(provider.status.source)\n\t\t? `env: ${provider.status.source}`\n\t\t: provider.status.source;\n\treturn theme.fg(\"success\", ` ✓ ${source}`);\n}\n\n/**\n * Component that renders an auth provider selector\n */\nexport class OAuthSelectorComponent extends Container implements Focusable {\n\tprivate searchInput: Input;\n\n\t// Focusable implementation - propagate to search input for IME cursor positioning\n\tprivate _focused = false;\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.searchInput.focused = value;\n\t}\n\n\tprivate listContainer: Container;\n\tprivate allProviders: AuthSelectorProvider[];\n\tprivate filteredProviders: AuthSelectorProvider[];\n\tprivate selectedIndex: number = 0;\n\tprivate mode: \"login\" | \"logout\";\n\tprivate onSelectCallback: (providerId: string, authType: AuthSelectorProvider[\"authType\"]) => void;\n\tprivate onCancelCallback: () => void;\n\tprivate showAuthTypeLabels: boolean;\n\n\tconstructor(\n\t\tmode: \"login\" | \"logout\",\n\t\tproviders: AuthSelectorProvider[],\n\t\tonSelect: (providerId: string, authType: AuthSelectorProvider[\"authType\"]) => void,\n\t\tonCancel: () => void,\n\t\tinitialSearchInput?: string,\n\t) {\n\t\tsuper();\n\n\t\tthis.mode = mode;\n\t\tthis.allProviders = providers;\n\t\tthis.filteredProviders = providers;\n\t\tthis.showAuthTypeLabels = new Set(providers.map((provider) => provider.authType)).size > 1;\n\t\tthis.onSelectCallback = onSelect;\n\t\tthis.onCancelCallback = onCancel;\n\n\t\t// Add top border\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Add title\n\t\tconst title = mode === \"login\" ? \"Select provider to configure:\" : \"Select provider to logout:\";\n\t\tthis.addChild(new TruncatedText(theme.fg(\"accent\", theme.bold(title)), 1, 0));\n\t\tthis.addChild(new Spacer(1));\n\n\t\tthis.searchInput = new Input();\n\t\tif (initialSearchInput) {\n\t\t\tthis.searchInput.setValue(initialSearchInput);\n\t\t}\n\t\tthis.searchInput.onSubmit = () => {\n\t\t\tconst selectedProvider = this.filteredProviders[this.selectedIndex];\n\t\t\tif (selectedProvider) {\n\t\t\t\tthis.onSelectCallback(selectedProvider.id, selectedProvider.authType);\n\t\t\t}\n\t\t};\n\t\tthis.addChild(this.searchInput);\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Create list container\n\t\tthis.listContainer = new Container();\n\t\tthis.addChild(this.listContainer);\n\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Add bottom border\n\t\tthis.addChild(new DynamicBorder());\n\n\t\t// Initial render\n\t\tthis.filterProviders(initialSearchInput ?? \"\");\n\t}\n\n\tprivate filterProviders(query: string): void {\n\t\tthis.filteredProviders = query\n\t\t\t? fuzzyFilter(\n\t\t\t\t\tthis.allProviders,\n\t\t\t\t\tquery,\n\t\t\t\t\t(provider) => `${provider.name} ${provider.id} ${provider.authType} ${provider.method?.name ?? \"\"}`,\n\t\t\t\t)\n\t\t\t: this.allProviders;\n\t\tthis.selectedIndex = Math.max(0, Math.min(this.selectedIndex, Math.max(0, this.filteredProviders.length - 1)));\n\t\tthis.updateList();\n\t}\n\n\tprivate updateList(): void {\n\t\tthis.listContainer.clear();\n\n\t\tconst maxVisible = 8;\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(this.selectedIndex - Math.floor(maxVisible / 2), this.filteredProviders.length - maxVisible),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + maxVisible, this.filteredProviders.length);\n\n\t\tfor (let i = startIndex; i < endIndex; i++) {\n\t\t\tconst provider = this.filteredProviders[i];\n\t\t\tif (!provider) continue;\n\n\t\t\tconst isSelected = i === this.selectedIndex;\n\n\t\t\tconst statusIndicator = formatAuthSelectorProviderStatus(provider);\n\t\t\tconst authTypeLabel = this.showAuthTypeLabels\n\t\t\t\t? theme.fg(\"muted\", ` [${formatAuthSelectorProviderType(provider.authType, provider.subscription)}]`)\n\t\t\t\t: \"\";\n\t\t\tlet line = \"\";\n\t\t\tif (isSelected) {\n\t\t\t\tconst prefix = theme.fg(\"accent\", \"→ \");\n\t\t\t\tconst text = theme.fg(\"accent\", provider.name);\n\t\t\t\tline = prefix + text + authTypeLabel + statusIndicator;\n\t\t\t} else {\n\t\t\t\tconst text = ` ${theme.fg(\"text\", provider.name)}`;\n\t\t\t\tline = text + authTypeLabel + statusIndicator;\n\t\t\t}\n\n\t\t\tthis.listContainer.addChild(new TruncatedText(line, 1, 0));\n\t\t}\n\n\t\tif (startIndex > 0 || endIndex < this.filteredProviders.length) {\n\t\t\tconst scrollInfo = theme.fg(\"muted\", ` (${this.selectedIndex + 1}/${this.filteredProviders.length})`);\n\t\t\tthis.listContainer.addChild(new TruncatedText(scrollInfo, 1, 0));\n\t\t}\n\n\t\t// Show \"no providers\" if empty\n\t\tif (this.filteredProviders.length === 0) {\n\t\t\tconst message =\n\t\t\t\tthis.allProviders.length === 0\n\t\t\t\t\t? this.mode === \"login\"\n\t\t\t\t\t\t? \"No providers available\"\n\t\t\t\t\t\t: \"No providers logged in. Use /login first.\"\n\t\t\t\t\t: \"No matching providers\";\n\t\t\tthis.listContainer.addChild(new TruncatedText(theme.fg(\"muted\", ` ${message}`), 1, 0));\n\t\t}\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getKeybindings();\n\t\t// Up arrow\n\t\tif (kb.matches(keyData, \"tui.select.up\")) {\n\t\t\tif (this.filteredProviders.length === 0) return;\n\t\t\tthis.selectedIndex = Math.max(0, this.selectedIndex - 1);\n\t\t\tthis.updateList();\n\t\t}\n\t\t// Down arrow\n\t\telse if (kb.matches(keyData, \"tui.select.down\")) {\n\t\t\tif (this.filteredProviders.length === 0) return;\n\t\t\tthis.selectedIndex = Math.min(this.filteredProviders.length - 1, this.selectedIndex + 1);\n\t\t\tthis.updateList();\n\t\t}\n\t\t// Enter\n\t\telse if (kb.matches(keyData, \"tui.select.confirm\")) {\n\t\t\tconst selectedProvider = this.filteredProviders[this.selectedIndex];\n\t\t\tif (selectedProvider) {\n\t\t\t\tthis.onSelectCallback(selectedProvider.id, selectedProvider.authType);\n\t\t\t}\n\t\t}\n\t\t// Escape or Ctrl+C\n\t\telse if (kb.matches(keyData, \"tui.select.cancel\")) {\n\t\t\tthis.onCancelCallback();\n\t\t}\n\t\t// Pass everything else to search input\n\t\telse {\n\t\t\tthis.searchInput.handleInput(keyData);\n\t\t\tthis.filterProviders(this.searchInput.getValue());\n\t\t}\n\t}\n}\n"]}
@@ -9,4 +9,11 @@
9
9
  * The brand colors stay fixed across themes; they follow the terminal's color mode.
10
10
  */
11
11
  export declare function piLogoLines(): [string, string];
12
+ /**
13
+ * Whether the terminal renders the half-block logo correctly. Apple Terminal draws gaps between rows and
14
+ * misaligns the half blocks, so it gets the text wordmark instead.
15
+ */
16
+ export declare function supportsPiLogo(): boolean;
17
+ /** Text fallback for the logo: "Pi" with the logo's coral and yellow. */
18
+ export declare function piWordmark(): string;
12
19
  //# sourceMappingURL=pi-logo.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pi-logo.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/pi-logo.ts"],"names":[],"mappings":"AAQA;;;;;;;;;GASG;AACH,wBAAgB,WAAW,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAO9C"}
1
+ {"version":3,"file":"pi-logo.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/pi-logo.ts"],"names":[],"mappings":"AAQA;;;;;;;;;GASG;AACH,wBAAgB,WAAW,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAO9C;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAExC;AAED,yEAAyE;AACzE,wBAAgB,UAAU,IAAI,MAAM,CAGnC"}
@@ -1,4 +1,4 @@
1
- import { backgroundAnsi, foregroundAnsi, rgbColor } from "@earendil-works/pi-tui";
1
+ import { backgroundAnsi, foregroundAnsi, isAppleTerminalSession, rgbColor } from "@earendil-works/pi-tui";
2
2
  import { theme } from "../theme/theme.js";
3
3
  const CORAL = rgbColor(228, 138, 122);
4
4
  const BLUE = rgbColor(79, 142, 179);
@@ -22,4 +22,16 @@ export function piLogoLines() {
22
22
  const bottom = `${fg(BLUE)}█▀${RESET} ${fg(YELLOW)}█${RESET}`;
23
23
  return [top, bottom];
24
24
  }
25
+ /**
26
+ * Whether the terminal renders the half-block logo correctly. Apple Terminal draws gaps between rows and
27
+ * misaligns the half blocks, so it gets the text wordmark instead.
28
+ */
29
+ export function supportsPiLogo() {
30
+ return !isAppleTerminalSession();
31
+ }
32
+ /** Text fallback for the logo: "Pi" with the logo's coral and yellow. */
33
+ export function piWordmark() {
34
+ const mode = theme.getColorMode();
35
+ return `${foregroundAnsi(CORAL, mode)}P${RESET}${foregroundAnsi(YELLOW, mode)}i${RESET}`;
36
+ }
25
37
  //# sourceMappingURL=pi-logo.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pi-logo.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/pi-logo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClF,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE1C,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AACtC,MAAM,IAAI,GAAG,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AACpC,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;AACtC,MAAM,KAAK,GAAG,SAAS,CAAC;AAExB;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW;IAC1B,MAAM,IAAI,GAAG,KAAK,CAAC,YAAY,EAAE,CAAC;IAClC,MAAM,EAAE,GAAG,CAAC,KAAmB,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAChE,kGAAkG;IAClG,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,GAAG,CAAC;IACxF,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;IAC9D,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;AACtB,CAAC","sourcesContent":["import { backgroundAnsi, foregroundAnsi, rgbColor } from \"@earendil-works/pi-tui\";\nimport { theme } from \"../theme/theme.ts\";\n\nconst CORAL = rgbColor(228, 138, 122);\nconst BLUE = rgbColor(79, 142, 179);\nconst YELLOW = rgbColor(234, 182, 93);\nconst RESET = \"\\x1b[0m\";\n\n/**\n * The pi logo: 4 cells wide and 2 lines tall. Each cell shows two square pixels with half blocks:\n *\n * coral coral coral .\n * blue . coral .\n * blue blue . yellow\n * blue . . yellow\n *\n * The brand colors stay fixed across themes; they follow the terminal's color mode.\n */\nexport function piLogoLines(): [string, string] {\n\tconst mode = theme.getColorMode();\n\tconst fg = (color: typeof CORAL) => foregroundAnsi(color, mode);\n\t// The fourth cell of the top line is empty, so it is padded to the same width as the bottom line.\n\tconst top = `${fg(CORAL)}${backgroundAnsi(BLUE, mode)}▀${RESET}${fg(CORAL)}▀█${RESET} `;\n\tconst bottom = `${fg(BLUE)}█▀${RESET} ${fg(YELLOW)}█${RESET}`;\n\treturn [top, bottom];\n}\n"]}
1
+ {"version":3,"file":"pi-logo.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/pi-logo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,sBAAsB,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAC1G,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE1C,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AACtC,MAAM,IAAI,GAAG,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AACpC,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;AACtC,MAAM,KAAK,GAAG,SAAS,CAAC;AAExB;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW;IAC1B,MAAM,IAAI,GAAG,KAAK,CAAC,YAAY,EAAE,CAAC;IAClC,MAAM,EAAE,GAAG,CAAC,KAAmB,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAChE,kGAAkG;IAClG,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,GAAG,CAAC;IACxF,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;IAC9D,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;AACtB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc;IAC7B,OAAO,CAAC,sBAAsB,EAAE,CAAC;AAClC,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,UAAU;IACzB,MAAM,IAAI,GAAG,KAAK,CAAC,YAAY,EAAE,CAAC;IAClC,OAAO,GAAG,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,KAAK,GAAG,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,KAAK,EAAE,CAAC;AAC1F,CAAC","sourcesContent":["import { backgroundAnsi, foregroundAnsi, isAppleTerminalSession, rgbColor } from \"@earendil-works/pi-tui\";\nimport { theme } from \"../theme/theme.ts\";\n\nconst CORAL = rgbColor(228, 138, 122);\nconst BLUE = rgbColor(79, 142, 179);\nconst YELLOW = rgbColor(234, 182, 93);\nconst RESET = \"\\x1b[0m\";\n\n/**\n * The pi logo: 4 cells wide and 2 lines tall. Each cell shows two square pixels with half blocks:\n *\n * coral coral coral .\n * blue . coral .\n * blue blue . yellow\n * blue . . yellow\n *\n * The brand colors stay fixed across themes; they follow the terminal's color mode.\n */\nexport function piLogoLines(): [string, string] {\n\tconst mode = theme.getColorMode();\n\tconst fg = (color: typeof CORAL) => foregroundAnsi(color, mode);\n\t// The fourth cell of the top line is empty, so it is padded to the same width as the bottom line.\n\tconst top = `${fg(CORAL)}${backgroundAnsi(BLUE, mode)}▀${RESET}${fg(CORAL)}▀█${RESET} `;\n\tconst bottom = `${fg(BLUE)}█▀${RESET} ${fg(YELLOW)}█${RESET}`;\n\treturn [top, bottom];\n}\n\n/**\n * Whether the terminal renders the half-block logo correctly. Apple Terminal draws gaps between rows and\n * misaligns the half blocks, so it gets the text wordmark instead.\n */\nexport function supportsPiLogo(): boolean {\n\treturn !isAppleTerminalSession();\n}\n\n/** Text fallback for the logo: \"Pi\" with the logo's coral and yellow. */\nexport function piWordmark(): string {\n\tconst mode = theme.getColorMode();\n\treturn `${foregroundAnsi(CORAL, mode)}P${RESET}${foregroundAnsi(YELLOW, mode)}i${RESET}`;\n}\n"]}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * The `/login` menu with the animated "Sign in with Radius" option. Internal to the interactive mode: the shimmer
3
+ * is Radius-only and is not exposed to other selectors.
4
+ */
5
+ import { type TUI } from "@earendil-works/pi-tui";
6
+ import { ExtensionSelectorComponent } from "./extension-selector.ts";
7
+ /** The "Sign in with Radius" option: `label` is the full option, starting with the animated `text`. */
8
+ type RadiusOption = {
9
+ label: string;
10
+ text: string;
11
+ };
12
+ /** Top-level `/login` selector whose Radius option shimmers in the Radius logo colors while it is selected. */
13
+ export declare function createLoginMenuSelector(tui: TUI, title: string, options: string[], radiusOption: RadiusOption, onSelect: (option: string) => void, onCancel: () => void): ExtensionSelectorComponent;
14
+ export {};
15
+ //# sourceMappingURL=radius-login-selector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"radius-login-selector.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/radius-login-selector.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAA2D,KAAK,GAAG,EAAE,MAAM,wBAAwB,CAAC;AAE3G,OAAO,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AA8BrE,uGAAuG;AACvG,KAAK,YAAY,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAiEpD,+GAA+G;AAC/G,wBAAgB,uBAAuB,CACtC,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EAAE,EACjB,YAAY,EAAE,YAAY,EAC1B,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,EAClC,QAAQ,EAAE,MAAM,IAAI,GAClB,0BAA0B,CAE5B"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * The `/login` menu with the animated "Sign in with Radius" option. Internal to the interactive mode: the shimmer
3
+ * is Radius-only and is not exposed to other selectors.
4
+ */
5
+ import { foregroundAnsi, mixColors, parseColor, Text } from "@earendil-works/pi-tui";
6
+ import { theme } from "../theme/theme.js";
7
+ import { ExtensionSelectorComponent } from "./extension-selector.js";
8
+ /** The four colors of the Radius logo, in the order they stream across the text. */
9
+ const RADIUS_COLORS = ["#4d9abf", "#83ccd2", "#f1be57", "#f09082"].map((hex) => parseColor(hex));
10
+ /** Width of each color band, in characters. */
11
+ const CHARS_PER_COLOR = 4;
12
+ const CHARS_PER_SECOND = 10;
13
+ const ANIMATION_FRAME_MS = 50;
14
+ /** Color `text` with the Radius logo colors flowing left to right; `elapsedMs` is the animation time. */
15
+ function radiusShimmer(text, elapsedMs) {
16
+ const mode = theme.getColorMode();
17
+ const cycle = RADIUS_COLORS.length * CHARS_PER_COLOR;
18
+ const offset = (elapsedMs / 1000) * CHARS_PER_SECOND;
19
+ let result = "";
20
+ let index = 0;
21
+ for (const char of text) {
22
+ const position = (((index - offset) % cycle) + cycle) % cycle;
23
+ const band = Math.floor(position / CHARS_PER_COLOR);
24
+ const t = position / CHARS_PER_COLOR - band;
25
+ // Smoothstep keeps each band recognizable while still blending into the next one.
26
+ const amount = t * t * (3 - 2 * t);
27
+ const from = RADIUS_COLORS[band];
28
+ const to = RADIUS_COLORS[(band + 1) % RADIUS_COLORS.length];
29
+ result += foregroundAnsi(mixColors(from, to, amount, "srgb"), mode) + char;
30
+ index++;
31
+ }
32
+ return `${result}\x1b[39m`;
33
+ }
34
+ /**
35
+ * Swaps the line `ExtensionSelectorComponent` draws for the selected Radius option with the animated one. When the
36
+ * selector's row style changes or the label wraps, the line no longer matches and the option renders normally.
37
+ */
38
+ class RadiusLoginMenuComponent extends ExtensionSelectorComponent {
39
+ radiusOption;
40
+ animationStart = performance.now();
41
+ animationTimer;
42
+ animating = false;
43
+ constructor(tui, title, options, radiusOption, onSelect, onCancel) {
44
+ super(title, options, (option) => {
45
+ this.stopAnimation();
46
+ onSelect(option);
47
+ }, () => {
48
+ this.stopAnimation();
49
+ onCancel();
50
+ });
51
+ this.radiusOption = radiusOption;
52
+ this.animationTimer = setInterval(() => {
53
+ if (this.animating)
54
+ tui.requestRender();
55
+ }, ANIMATION_FRAME_MS);
56
+ this.animationTimer.unref?.();
57
+ }
58
+ render(width) {
59
+ const lines = super.render(width);
60
+ const { label, text } = this.radiusOption;
61
+ const selectedLine = new Text(theme.fg("accent", "→ ") + theme.fg("accent", label), 1, 0).render(width)[0];
62
+ const index = selectedLine === undefined ? -1 : lines.indexOf(selectedLine);
63
+ this.animating = index >= 0;
64
+ if (this.animating) {
65
+ const shimmer = radiusShimmer(text, performance.now() - this.animationStart);
66
+ const animatedLine = theme.fg("accent", "→ ") + shimmer + label.slice(text.length);
67
+ lines[index] = new Text(animatedLine, 1, 0).render(width)[0] ?? "";
68
+ }
69
+ return lines;
70
+ }
71
+ stopAnimation() {
72
+ clearInterval(this.animationTimer);
73
+ this.animationTimer = undefined;
74
+ this.animating = false;
75
+ }
76
+ dispose() {
77
+ this.stopAnimation();
78
+ super.dispose();
79
+ }
80
+ }
81
+ /** Top-level `/login` selector whose Radius option shimmers in the Radius logo colors while it is selected. */
82
+ export function createLoginMenuSelector(tui, title, options, radiusOption, onSelect, onCancel) {
83
+ return new RadiusLoginMenuComponent(tui, title, options, radiusOption, onSelect, onCancel);
84
+ }
85
+ //# sourceMappingURL=radius-login-selector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"radius-login-selector.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/radius-login-selector.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The `/login` menu with the animated \"Sign in with Radius\" option. Internal to the interactive mode: the shimmer\n * is Radius-only and is not exposed to other selectors.\n */\n\nimport { type Color, foregroundAnsi, mixColors, parseColor, Text, type TUI } from \"@earendil-works/pi-tui\";\nimport { theme } from \"../theme/theme.ts\";\nimport { ExtensionSelectorComponent } from \"./extension-selector.ts\";\n\n/** The four colors of the Radius logo, in the order they stream across the text. */\nconst RADIUS_COLORS: readonly Color[] = [\"#4d9abf\", \"#83ccd2\", \"#f1be57\", \"#f09082\"].map((hex) => parseColor(hex));\n/** Width of each color band, in characters. */\nconst CHARS_PER_COLOR = 4;\nconst CHARS_PER_SECOND = 10;\nconst ANIMATION_FRAME_MS = 50;\n\n/** Color `text` with the Radius logo colors flowing left to right; `elapsedMs` is the animation time. */\nfunction radiusShimmer(text: string, elapsedMs: number): string {\n\tconst mode = theme.getColorMode();\n\tconst cycle = RADIUS_COLORS.length * CHARS_PER_COLOR;\n\tconst offset = (elapsedMs / 1000) * CHARS_PER_SECOND;\n\tlet result = \"\";\n\tlet index = 0;\n\tfor (const char of text) {\n\t\tconst position = (((index - offset) % cycle) + cycle) % cycle;\n\t\tconst band = Math.floor(position / CHARS_PER_COLOR);\n\t\tconst t = position / CHARS_PER_COLOR - band;\n\t\t// Smoothstep keeps each band recognizable while still blending into the next one.\n\t\tconst amount = t * t * (3 - 2 * t);\n\t\tconst from = RADIUS_COLORS[band] as Color;\n\t\tconst to = RADIUS_COLORS[(band + 1) % RADIUS_COLORS.length] as Color;\n\t\tresult += foregroundAnsi(mixColors(from, to, amount, \"srgb\"), mode) + char;\n\t\tindex++;\n\t}\n\treturn `${result}\\x1b[39m`;\n}\n\n/** The \"Sign in with Radius\" option: `label` is the full option, starting with the animated `text`. */\ntype RadiusOption = { label: string; text: string };\n\n/**\n * Swaps the line `ExtensionSelectorComponent` draws for the selected Radius option with the animated one. When the\n * selector's row style changes or the label wraps, the line no longer matches and the option renders normally.\n */\nclass RadiusLoginMenuComponent extends ExtensionSelectorComponent {\n\tprivate readonly radiusOption: RadiusOption;\n\tprivate readonly animationStart = performance.now();\n\tprivate animationTimer: ReturnType<typeof setInterval> | undefined;\n\tprivate animating = false;\n\n\tconstructor(\n\t\ttui: TUI,\n\t\ttitle: string,\n\t\toptions: string[],\n\t\tradiusOption: RadiusOption,\n\t\tonSelect: (option: string) => void,\n\t\tonCancel: () => void,\n\t) {\n\t\tsuper(\n\t\t\ttitle,\n\t\t\toptions,\n\t\t\t(option) => {\n\t\t\t\tthis.stopAnimation();\n\t\t\t\tonSelect(option);\n\t\t\t},\n\t\t\t() => {\n\t\t\t\tthis.stopAnimation();\n\t\t\t\tonCancel();\n\t\t\t},\n\t\t);\n\t\tthis.radiusOption = radiusOption;\n\t\tthis.animationTimer = setInterval(() => {\n\t\t\tif (this.animating) tui.requestRender();\n\t\t}, ANIMATION_FRAME_MS);\n\t\tthis.animationTimer.unref?.();\n\t}\n\n\toverride render(width: number): string[] {\n\t\tconst lines = super.render(width);\n\t\tconst { label, text } = this.radiusOption;\n\t\tconst selectedLine = new Text(theme.fg(\"accent\", \"→ \") + theme.fg(\"accent\", label), 1, 0).render(width)[0];\n\t\tconst index = selectedLine === undefined ? -1 : lines.indexOf(selectedLine);\n\t\tthis.animating = index >= 0;\n\t\tif (this.animating) {\n\t\t\tconst shimmer = radiusShimmer(text, performance.now() - this.animationStart);\n\t\t\tconst animatedLine = theme.fg(\"accent\", \"→ \") + shimmer + label.slice(text.length);\n\t\t\tlines[index] = new Text(animatedLine, 1, 0).render(width)[0] ?? \"\";\n\t\t}\n\t\treturn lines;\n\t}\n\n\tprivate stopAnimation(): void {\n\t\tclearInterval(this.animationTimer);\n\t\tthis.animationTimer = undefined;\n\t\tthis.animating = false;\n\t}\n\n\toverride dispose(): void {\n\t\tthis.stopAnimation();\n\t\tsuper.dispose();\n\t}\n}\n\n/** Top-level `/login` selector whose Radius option shimmers in the Radius logo colors while it is selected. */\nexport function createLoginMenuSelector(\n\ttui: TUI,\n\ttitle: string,\n\toptions: string[],\n\tradiusOption: RadiusOption,\n\tonSelect: (option: string) => void,\n\tonCancel: () => void,\n): ExtensionSelectorComponent {\n\treturn new RadiusLoginMenuComponent(tui, title, options, radiusOption, onSelect, onCancel);\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  import type { ThinkingLevel } from "@earendil-works/pi-agent-core";
2
2
  import { type Model, type Transport } from "@earendil-works/pi-ai";
3
3
  import { Container, type ScrollViewScrollbar, SettingsList, type WheelScrollLines } from "@earendil-works/pi-tui";
4
- import { type CacheWarmingMode, type DefaultProjectTrust, type FullscreenExitOutput, type MermaidRenderingMode, type TuiMode, type WarningSettings } from "../../../core/settings-manager.ts";
4
+ import { type CacheWarmingMode, type DefaultProjectTrust, type FullscreenExitOutput, type MermaidRenderingMode, type QuietStartup, type TuiMode, type WarningSettings } from "../../../core/settings-manager.ts";
5
5
  import { type TerminalTheme } from "../theme/theme.ts";
6
6
  export interface SettingsConfig {
7
7
  autoCompact: boolean;
@@ -35,7 +35,7 @@ export interface SettingsConfig {
35
35
  editorPaddingX: number;
36
36
  outputPad: 0 | 1;
37
37
  autocompleteMaxVisible: number;
38
- quietStartup: boolean;
38
+ quietStartup: QuietStartup;
39
39
  defaultProjectTrust: DefaultProjectTrust;
40
40
  clearOnShrink: boolean;
41
41
  showTerminalProgress: boolean;
@@ -73,7 +73,7 @@ export interface SettingsCallbacks {
73
73
  onEditorPaddingXChange: (padding: number) => void;
74
74
  onOutputPadChange: (padding: 0 | 1) => void;
75
75
  onAutocompleteMaxVisibleChange: (maxVisible: number) => void;
76
- onQuietStartupChange: (enabled: boolean) => void;
76
+ onQuietStartupChange: (quiet: QuietStartup) => void;
77
77
  onDefaultProjectTrustChange: (defaultProjectTrust: DefaultProjectTrust) => void;
78
78
  onClearOnShrinkChange: (enabled: boolean) => void;
79
79
  onShowTerminalProgressChange: (enabled: boolean) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"settings-selector.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/settings-selector.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"settings-selector.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/settings-selector.ts"],"names":[],"mappings":"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"}
@@ -338,9 +338,9 @@ export class SettingsSelectorComponent extends Container {
338
338
  {
339
339
  id: "quiet-startup",
340
340
  label: "Quiet startup",
341
- description: "Disable verbose printing at startup",
342
- currentValue: config.quietStartup ? "true" : "false",
343
- values: ["true", "false"],
341
+ description: "Disable verbose printing at startup (header: keep only the startup header)",
342
+ currentValue: String(config.quietStartup),
343
+ values: ["true", "header", "false"],
344
344
  },
345
345
  {
346
346
  id: "install-telemetry",
@@ -478,7 +478,7 @@ export class SettingsSelectorComponent extends Container {
478
478
  {
479
479
  id: "tui-mode",
480
480
  label: "TUI mode",
481
- description: "Interface layout; fullscreen mode is experimental",
481
+ description: "Interface layout; regular mode uses the terminal's normal scrollback",
482
482
  currentValue: config.tuiMode,
483
483
  values: ["regular", "fullscreen"],
484
484
  },
@@ -676,7 +676,7 @@ export class SettingsSelectorComponent extends Container {
676
676
  callbacks.onCollapseChangelogChange(newValue === "true");
677
677
  break;
678
678
  case "quiet-startup":
679
- callbacks.onQuietStartupChange(newValue === "true");
679
+ callbacks.onQuietStartupChange(newValue === "header" ? "header" : newValue === "true");
680
680
  break;
681
681
  case "install-telemetry":
682
682
  callbacks.onEnableInstallTelemetryChange(newValue === "true");