@tomsun28/pizza 0.0.9 → 0.1.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.
- package/README.md +20 -143
- package/README.zh-CN.md +36 -0
- package/dist/bun/cli.d.ts +2 -0
- package/dist/bun/cli.js +6 -0
- package/dist/bun/register-bedrock.d.ts +1 -0
- package/dist/bun/register-bedrock.js +3 -0
- package/dist/cli/args.d.ts +48 -0
- package/dist/cli/args.js +330 -0
- package/dist/cli/config-selector.d.ts +13 -0
- package/dist/cli/config-selector.js +30 -0
- package/dist/cli/file-processor.d.ts +14 -0
- package/dist/cli/file-processor.js +82 -0
- package/dist/cli/initial-message.d.ts +17 -0
- package/dist/cli/initial-message.js +21 -0
- package/dist/cli/list-models.d.ts +8 -0
- package/dist/cli/list-models.js +96 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +68 -0
- package/dist/config.d.ts +79 -0
- package/dist/config.js +223 -0
- package/dist/core/agent/index.d.ts +6 -0
- package/dist/core/agent/index.js +6 -0
- package/dist/core/agent/types.d.ts +202 -0
- package/dist/core/agent/types.js +51 -0
- package/dist/core/auth-storage.d.ts +135 -0
- package/dist/core/auth-storage.js +417 -0
- package/dist/core/bash-executor.d.ts +31 -0
- package/dist/core/bash-executor.js +107 -0
- package/dist/core/compaction/branch-summarization.d.ts +87 -0
- package/dist/core/compaction/branch-summarization.js +242 -0
- package/dist/core/compaction/compaction-engine.d.ts +40 -0
- package/dist/core/compaction/compaction-engine.js +292 -0
- package/dist/core/compaction/compaction.d.ts +106 -0
- package/dist/core/compaction/compaction.js +295 -0
- package/dist/core/compaction/index.d.ts +7 -0
- package/dist/core/compaction/index.js +7 -0
- package/dist/core/compaction/utils.d.ts +37 -0
- package/dist/core/compaction/utils.js +152 -0
- package/dist/core/defaults.d.ts +2 -0
- package/dist/core/defaults.js +1 -0
- package/dist/core/diagnostics.d.ts +14 -0
- package/dist/core/diagnostics.js +1 -0
- package/dist/core/event-bus.d.ts +8 -0
- package/dist/core/event-bus.js +24 -0
- package/dist/core/event-store/events.d.ts +465 -0
- package/dist/core/event-store/events.js +6 -0
- package/dist/core/event-store/index.d.ts +10 -0
- package/dist/core/event-store/index.js +10 -0
- package/dist/core/event-store/sqlite-store.d.ts +27 -0
- package/dist/core/event-store/sqlite-store.js +275 -0
- package/dist/core/event-store/store.d.ts +91 -0
- package/dist/core/event-store/store.js +7 -0
- package/dist/core/event-store/thread-scoped-store.d.ts +29 -0
- package/dist/core/event-store/thread-scoped-store.js +50 -0
- package/dist/core/event-store/types.d.ts +70 -0
- package/dist/core/event-store/types.js +7 -0
- package/dist/core/event-store/workspace.d.ts +37 -0
- package/dist/core/event-store/workspace.js +71 -0
- package/dist/core/exec.d.ts +28 -0
- package/dist/core/exec.js +74 -0
- package/dist/core/export-html/ansi-to-html.d.ts +21 -0
- package/dist/core/export-html/ansi-to-html.js +248 -0
- package/dist/core/export-html/index.d.ts +29 -0
- package/dist/core/export-html/index.js +186 -0
- package/dist/core/export-html/template.css +1017 -0
- package/dist/core/export-html/template.html +55 -0
- package/dist/core/export-html/template.js +1742 -0
- package/dist/core/export-html/tool-renderer.d.ts +39 -0
- package/dist/core/export-html/tool-renderer.js +94 -0
- package/dist/core/export-html/vendor/highlight.min.js +1213 -0
- package/dist/core/export-html/vendor/marked.min.js +6 -0
- package/dist/core/extensions/index.d.ts +12 -0
- package/dist/core/extensions/index.js +9 -0
- package/dist/core/extensions/loader.d.ts +24 -0
- package/dist/core/extensions/loader.js +492 -0
- package/dist/core/extensions/runner.d.ts +167 -0
- package/dist/core/extensions/runner.js +898 -0
- package/dist/core/extensions/session-context.d.ts +67 -0
- package/dist/core/extensions/session-context.js +272 -0
- package/dist/core/extensions/types.d.ts +1147 -0
- package/dist/core/extensions/types.js +44 -0
- package/dist/core/extensions/wrapper.d.ts +19 -0
- package/dist/core/extensions/wrapper.js +21 -0
- package/dist/core/footer-data-provider.d.ts +47 -0
- package/dist/core/footer-data-provider.js +321 -0
- package/dist/core/goal/index.d.ts +3 -0
- package/dist/core/goal/index.js +1 -0
- package/dist/core/goal/scheduler.d.ts +83 -0
- package/dist/core/goal/scheduler.js +154 -0
- package/dist/core/goal/types.d.ts +182 -0
- package/dist/core/goal/types.js +11 -0
- package/dist/core/index.d.ts +8 -0
- package/dist/core/index.js +8 -0
- package/dist/core/intent/classifier.d.ts +53 -0
- package/dist/core/intent/classifier.js +353 -0
- package/dist/core/intent/index.d.ts +8 -0
- package/dist/core/intent/index.js +8 -0
- package/dist/core/intent/tool-adapter.d.ts +31 -0
- package/dist/core/intent/tool-adapter.js +168 -0
- package/dist/core/intent/types.d.ts +71 -0
- package/dist/core/intent/types.js +6 -0
- package/dist/core/keybindings.d.ts +297 -0
- package/dist/core/keybindings.js +250 -0
- package/dist/core/messages.d.ts +30 -0
- package/dist/core/messages.js +134 -0
- package/dist/core/model-registry.d.ts +131 -0
- package/dist/core/model-registry.js +634 -0
- package/dist/core/model-resolver.d.ts +109 -0
- package/dist/core/model-resolver.js +486 -0
- package/dist/core/output-guard.d.ts +5 -0
- package/dist/core/output-guard.js +58 -0
- package/dist/core/package-manager.d.ts +196 -0
- package/dist/core/package-manager.js +1873 -0
- package/dist/core/projection/boundary-inferrer.d.ts +58 -0
- package/dist/core/projection/boundary-inferrer.js +122 -0
- package/dist/core/projection/event-to-message.d.ts +35 -0
- package/dist/core/projection/event-to-message.js +253 -0
- package/dist/core/projection/goal-projection.d.ts +67 -0
- package/dist/core/projection/goal-projection.js +339 -0
- package/dist/core/projection/index.d.ts +13 -0
- package/dist/core/projection/index.js +13 -0
- package/dist/core/projection/session-manager.d.ts +100 -0
- package/dist/core/projection/session-manager.js +331 -0
- package/dist/core/projection/session-projection.d.ts +58 -0
- package/dist/core/projection/session-projection.js +257 -0
- package/dist/core/projection/task-history.d.ts +13 -0
- package/dist/core/projection/task-history.js +61 -0
- package/dist/core/projection/timeline-projection.d.ts +82 -0
- package/dist/core/projection/timeline-projection.js +276 -0
- package/dist/core/projection/types.d.ts +69 -0
- package/dist/core/projection/types.js +6 -0
- package/dist/core/prompt-templates.d.ts +51 -0
- package/dist/core/prompt-templates.js +249 -0
- package/dist/core/resolve-config-value.d.ts +22 -0
- package/dist/core/resolve-config-value.js +125 -0
- package/dist/core/resource-loader.d.ts +193 -0
- package/dist/core/resource-loader.js +685 -0
- package/dist/core/runtime/ai-client.d.ts +12 -0
- package/dist/core/runtime/ai-client.js +153 -0
- package/dist/core/runtime/checkpoint.d.ts +12 -0
- package/dist/core/runtime/checkpoint.js +78 -0
- package/dist/core/runtime/index.d.ts +12 -0
- package/dist/core/runtime/index.js +12 -0
- package/dist/core/runtime/llm-types.d.ts +99 -0
- package/dist/core/runtime/llm-types.js +6 -0
- package/dist/core/runtime/local-runtime.d.ts +23 -0
- package/dist/core/runtime/local-runtime.js +59 -0
- package/dist/core/runtime/policies.d.ts +72 -0
- package/dist/core/runtime/policies.js +37 -0
- package/dist/core/runtime/reactor.d.ts +213 -0
- package/dist/core/runtime/reactor.js +992 -0
- package/dist/core/runtime/runtime.d.ts +191 -0
- package/dist/core/runtime/runtime.js +449 -0
- package/dist/core/runtime/types.d.ts +42 -0
- package/dist/core/runtime/types.js +1 -0
- package/dist/core/sdk.d.ts +12 -0
- package/dist/core/sdk.js +10 -0
- package/dist/core/session-context-builder.d.ts +9 -0
- package/dist/core/session-context-builder.js +87 -0
- package/dist/core/session-cwd.d.ts +18 -0
- package/dist/core/session-cwd.js +36 -0
- package/dist/core/session-facade-factory.d.ts +79 -0
- package/dist/core/session-facade-factory.js +460 -0
- package/dist/core/session-facade.d.ts +57 -0
- package/dist/core/session-facade.js +91 -0
- package/dist/core/session-listing.d.ts +30 -0
- package/dist/core/session-listing.js +168 -0
- package/dist/core/session-reader.d.ts +19 -0
- package/dist/core/session-reader.js +101 -0
- package/dist/core/session-ref.d.ts +7 -0
- package/dist/core/session-ref.js +25 -0
- package/dist/core/session-services.d.ts +51 -0
- package/dist/core/session-services.js +90 -0
- package/dist/core/session-stats.d.ts +43 -0
- package/dist/core/session-stats.js +41 -0
- package/dist/core/settings-manager.d.ts +236 -0
- package/dist/core/settings-manager.js +706 -0
- package/dist/core/skill-block-parser.d.ts +12 -0
- package/dist/core/skill-block-parser.js +15 -0
- package/dist/core/skills.d.ts +59 -0
- package/dist/core/skills.js +408 -0
- package/dist/core/slash-commands.d.ts +13 -0
- package/dist/core/slash-commands.js +17 -0
- package/dist/core/source-info.d.ts +17 -0
- package/dist/core/source-info.js +18 -0
- package/dist/core/system-prompt.d.ts +27 -0
- package/dist/core/system-prompt.js +179 -0
- package/dist/core/timings.d.ts +7 -0
- package/dist/core/timings.js +30 -0
- package/dist/core/tools/bash.d.ts +95 -0
- package/dist/core/tools/bash.js +513 -0
- package/dist/core/tools/builtin-commands.d.ts +75 -0
- package/dist/core/tools/builtin-commands.js +503 -0
- package/dist/core/tools/compat-commands.d.ts +12 -0
- package/dist/core/tools/compat-commands.js +1280 -0
- package/dist/core/tools/edit-diff.d.ts +59 -0
- package/dist/core/tools/edit-diff.js +263 -0
- package/dist/core/tools/edit.d.ts +49 -0
- package/dist/core/tools/edit.js +340 -0
- package/dist/core/tools/file-mutation-queue.d.ts +5 -0
- package/dist/core/tools/file-mutation-queue.js +36 -0
- package/dist/core/tools/find.d.ts +34 -0
- package/dist/core/tools/find.js +459 -0
- package/dist/core/tools/grep.d.ts +36 -0
- package/dist/core/tools/grep.js +422 -0
- package/dist/core/tools/index.d.ts +70 -0
- package/dist/core/tools/index.js +129 -0
- package/dist/core/tools/line-anchors.d.ts +33 -0
- package/dist/core/tools/line-anchors.js +151 -0
- package/dist/core/tools/ls.d.ts +36 -0
- package/dist/core/tools/ls.js +268 -0
- package/dist/core/tools/path-utils.d.ts +7 -0
- package/dist/core/tools/path-utils.js +80 -0
- package/dist/core/tools/read.d.ts +35 -0
- package/dist/core/tools/read.js +244 -0
- package/dist/core/tools/render-utils.d.ts +20 -0
- package/dist/core/tools/render-utils.js +48 -0
- package/dist/core/tools/session-split.d.ts +9 -0
- package/dist/core/tools/session-split.js +77 -0
- package/dist/core/tools/tool-definition-wrapper.d.ts +13 -0
- package/dist/core/tools/tool-definition-wrapper.js +32 -0
- package/dist/core/tools/truncate.d.ts +69 -0
- package/dist/core/tools/truncate.js +204 -0
- package/dist/core/tools/write.d.ts +25 -0
- package/dist/core/tools/write.js +211 -0
- package/dist/core/types/session-types.d.ts +123 -0
- package/dist/core/types/session-types.js +8 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +38 -0
- package/dist/main.d.ts +11 -2
- package/dist/main.js +577 -149
- package/dist/modes/event-mapper.d.ts +115 -0
- package/dist/modes/event-mapper.js +200 -0
- package/dist/modes/gui/server.d.ts +14 -0
- package/dist/modes/gui/server.js +1032 -0
- package/dist/modes/index.d.ts +10 -0
- package/dist/modes/index.js +9 -0
- package/dist/modes/interactive/assets/clankolas.png +0 -0
- package/dist/modes/interactive/components/armin.d.ts +33 -0
- package/dist/modes/interactive/components/armin.js +328 -0
- package/dist/modes/interactive/components/assistant-message.d.ts +19 -0
- package/dist/modes/interactive/components/assistant-message.js +115 -0
- package/dist/modes/interactive/components/bash-execution.d.ts +33 -0
- package/dist/modes/interactive/components/bash-execution.js +169 -0
- package/dist/modes/interactive/components/bordered-loader.d.ts +15 -0
- package/dist/modes/interactive/components/bordered-loader.js +50 -0
- package/dist/modes/interactive/components/branch-summary-message.d.ts +15 -0
- package/dist/modes/interactive/components/branch-summary-message.js +41 -0
- package/dist/modes/interactive/components/brand-header.d.ts +33 -0
- package/dist/modes/interactive/components/brand-header.js +235 -0
- package/dist/modes/interactive/components/compaction-summary-message.d.ts +15 -0
- package/dist/modes/interactive/components/compaction-summary-message.js +42 -0
- package/dist/modes/interactive/components/config-selector.d.ts +70 -0
- package/dist/modes/interactive/components/config-selector.js +469 -0
- package/dist/modes/interactive/components/countdown-timer.d.ts +13 -0
- package/dist/modes/interactive/components/countdown-timer.js +27 -0
- package/dist/modes/interactive/components/custom-editor.d.ts +27 -0
- package/dist/modes/interactive/components/custom-editor.js +94 -0
- package/dist/modes/interactive/components/custom-message.d.ts +19 -0
- package/dist/modes/interactive/components/custom-message.js +73 -0
- package/dist/modes/interactive/components/daxnuts.d.ts +22 -0
- package/dist/modes/interactive/components/daxnuts.js +137 -0
- package/dist/modes/interactive/components/diff.d.ts +11 -0
- package/dist/modes/interactive/components/diff.js +132 -0
- package/dist/modes/interactive/components/dynamic-border.d.ts +14 -0
- package/dist/modes/interactive/components/dynamic-border.js +19 -0
- package/dist/modes/interactive/components/earendil-announcement.d.ts +4 -0
- package/dist/modes/interactive/components/earendil-announcement.js +39 -0
- package/dist/modes/interactive/components/extension-editor.d.ts +19 -0
- package/dist/modes/interactive/components/extension-editor.js +105 -0
- package/dist/modes/interactive/components/extension-input.d.ts +22 -0
- package/dist/modes/interactive/components/extension-input.js +54 -0
- package/dist/modes/interactive/components/extension-selector.d.ts +23 -0
- package/dist/modes/interactive/components/extension-selector.js +70 -0
- package/dist/modes/interactive/components/footer.d.ts +55 -0
- package/dist/modes/interactive/components/footer.js +207 -0
- package/dist/modes/interactive/components/index.d.ts +31 -0
- package/dist/modes/interactive/components/index.js +32 -0
- package/dist/modes/interactive/components/keybinding-hints.d.ts +7 -0
- package/dist/modes/interactive/components/keybinding-hints.js +21 -0
- package/dist/modes/interactive/components/login-dialog.d.ts +41 -0
- package/dist/modes/interactive/components/login-dialog.js +138 -0
- package/dist/modes/interactive/components/model-selector.d.ts +32 -0
- package/dist/modes/interactive/components/model-selector.js +209 -0
- package/dist/modes/interactive/components/oauth-selector.d.ts +18 -0
- package/dist/modes/interactive/components/oauth-selector.js +91 -0
- package/dist/modes/interactive/components/settings-selector.d.ts +57 -0
- package/dist/modes/interactive/components/settings-selector.js +299 -0
- package/dist/modes/interactive/components/show-images-selector.d.ts +9 -0
- package/dist/modes/interactive/components/show-images-selector.js +37 -0
- package/dist/modes/interactive/components/skill-invocation-message.d.ts +16 -0
- package/dist/modes/interactive/components/skill-invocation-message.js +44 -0
- package/dist/modes/interactive/components/theme-selector.d.ts +10 -0
- package/dist/modes/interactive/components/theme-selector.js +47 -0
- package/dist/modes/interactive/components/thinking-selector.d.ts +10 -0
- package/dist/modes/interactive/components/thinking-selector.js +50 -0
- package/dist/modes/interactive/components/timeline-view.d.ts +31 -0
- package/dist/modes/interactive/components/timeline-view.js +81 -0
- package/dist/modes/interactive/components/tool-execution.d.ts +64 -0
- package/dist/modes/interactive/components/tool-execution.js +305 -0
- package/dist/modes/interactive/components/tree-selector.d.ts +88 -0
- package/dist/modes/interactive/components/tree-selector.js +1072 -0
- package/dist/modes/interactive/components/user-message-selector.d.ts +29 -0
- package/dist/modes/interactive/components/user-message-selector.js +110 -0
- package/dist/modes/interactive/components/user-message.d.ts +9 -0
- package/dist/modes/interactive/components/user-message.js +27 -0
- package/dist/modes/interactive/components/visual-truncate.d.ts +23 -0
- package/dist/modes/interactive/components/visual-truncate.js +32 -0
- package/dist/modes/interactive/interactive-mode.d.ts +394 -0
- package/dist/modes/interactive/interactive-mode.js +4116 -0
- package/dist/modes/interactive/theme/dark.json +85 -0
- package/dist/modes/interactive/theme/light.json +84 -0
- package/dist/modes/interactive/theme/theme-schema.json +335 -0
- package/dist/modes/interactive/theme/theme.d.ts +80 -0
- package/dist/modes/interactive/theme/theme.js +973 -0
- package/dist/modes/print-mode.d.ts +27 -0
- package/dist/modes/print-mode.js +102 -0
- package/dist/modes/rpc/jsonl.d.ts +16 -0
- package/dist/modes/rpc/jsonl.js +48 -0
- package/dist/modes/rpc/rpc-client.d.ts +219 -0
- package/dist/modes/rpc/rpc-client.js +405 -0
- package/dist/modes/rpc/rpc-mode.d.ts +19 -0
- package/dist/modes/rpc/rpc-mode.js +381 -0
- package/dist/modes/rpc/rpc-types.d.ts +406 -0
- package/dist/modes/rpc/rpc-types.js +7 -0
- package/dist/package-manager-cli.d.ts +3 -0
- package/dist/package-manager-cli.js +233 -0
- package/dist/utils/changelog.d.ts +20 -0
- package/dist/utils/changelog.js +86 -0
- package/dist/utils/child-process.d.ts +10 -0
- package/dist/utils/child-process.js +77 -0
- package/dist/utils/clipboard-image.d.ts +10 -0
- package/dist/utils/clipboard-image.js +244 -0
- package/dist/utils/clipboard-native.d.ts +7 -0
- package/dist/utils/clipboard-native.js +13 -0
- package/dist/utils/clipboard.d.ts +1 -0
- package/dist/utils/clipboard.js +77 -0
- package/dist/utils/exif-orientation.d.ts +4 -0
- package/dist/utils/exif-orientation.js +157 -0
- package/dist/utils/frontmatter.d.ts +7 -0
- package/dist/utils/frontmatter.js +25 -0
- package/dist/utils/git.d.ts +25 -0
- package/dist/utils/git.js +162 -0
- package/dist/utils/image-convert.d.ts +8 -0
- package/dist/utils/image-convert.js +38 -0
- package/dist/utils/image-resize.d.ts +35 -0
- package/dist/utils/image-resize.js +136 -0
- package/dist/utils/mime.d.ts +1 -0
- package/dist/utils/mime.js +25 -0
- package/dist/utils/path-shims.d.ts +1 -0
- package/dist/utils/path-shims.js +90 -0
- package/dist/utils/paths.d.ts +6 -0
- package/dist/utils/paths.js +18 -0
- package/dist/utils/photon.d.ts +20 -0
- package/dist/utils/photon.js +120 -0
- package/dist/utils/shell.d.ts +29 -0
- package/dist/utils/shell.js +189 -0
- package/dist/utils/sleep.d.ts +4 -0
- package/dist/utils/sleep.js +16 -0
- package/dist/utils/tools-manager.d.ts +3 -0
- package/dist/utils/tools-manager.js +101 -0
- package/dist/vendor/bin/darwin-arm64/fd +0 -0
- package/dist/vendor/bin/darwin-arm64/rg +0 -0
- package/dist/vendor/bin/darwin-x64/fd +0 -0
- package/dist/vendor/bin/darwin-x64/rg +0 -0
- package/dist/vendor/bin/linux-arm64/fd +0 -0
- package/dist/vendor/bin/linux-arm64/rg +0 -0
- package/dist/vendor/bin/linux-x64/fd +0 -0
- package/dist/vendor/bin/linux-x64/rg +0 -0
- package/dist/vendor/bin/win32-arm64/fd.exe +0 -0
- package/dist/vendor/bin/win32-arm64/rg.exe +0 -0
- package/dist/vendor/bin/win32-x64/fd.exe +0 -0
- package/dist/vendor/bin/win32-x64/rg.exe +0 -0
- package/package.json +90 -26
- package/dist/extension/core.d.ts +0 -69
- package/dist/extension/core.js +0 -270
- package/dist/extension/core.js.map +0 -1
- package/dist/extension/index.d.ts +0 -25
- package/dist/extension/index.js +0 -303
- package/dist/extension/index.js.map +0 -1
- package/dist/main.js.map +0 -1
- package/themes/pizza.json +0 -87
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Container, type Focusable, type TUI } from "@earendil-works/pi-tui";
|
|
2
|
+
/**
|
|
3
|
+
* Login dialog component - replaces editor during OAuth login flow
|
|
4
|
+
*/
|
|
5
|
+
export declare class LoginDialogComponent extends Container implements Focusable {
|
|
6
|
+
private onComplete;
|
|
7
|
+
private contentContainer;
|
|
8
|
+
private input;
|
|
9
|
+
private tui;
|
|
10
|
+
private abortController;
|
|
11
|
+
private inputResolver?;
|
|
12
|
+
private inputRejecter?;
|
|
13
|
+
private _focused;
|
|
14
|
+
get focused(): boolean;
|
|
15
|
+
set focused(value: boolean);
|
|
16
|
+
constructor(tui: TUI, providerId: string, onComplete: (success: boolean, message?: string) => void);
|
|
17
|
+
get signal(): AbortSignal;
|
|
18
|
+
private cancel;
|
|
19
|
+
/**
|
|
20
|
+
* Called by onAuth callback - show URL and optional instructions
|
|
21
|
+
*/
|
|
22
|
+
showAuth(url: string, instructions?: string): void;
|
|
23
|
+
/**
|
|
24
|
+
* Show input for manual code/URL entry (for callback server providers)
|
|
25
|
+
*/
|
|
26
|
+
showManualInput(prompt: string): Promise<string>;
|
|
27
|
+
/**
|
|
28
|
+
* Called by onPrompt callback - show prompt and wait for input
|
|
29
|
+
* Note: Does NOT clear content, appends to existing (preserves URL from showAuth)
|
|
30
|
+
*/
|
|
31
|
+
showPrompt(message: string, placeholder?: string): Promise<string>;
|
|
32
|
+
/**
|
|
33
|
+
* Show waiting message (for polling flows like GitHub Copilot)
|
|
34
|
+
*/
|
|
35
|
+
showWaiting(message: string): void;
|
|
36
|
+
/**
|
|
37
|
+
* Called by onProgress callback
|
|
38
|
+
*/
|
|
39
|
+
showProgress(message: string): void;
|
|
40
|
+
handleInput(data: string): void;
|
|
41
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { getOAuthProviders } from "@earendil-works/pi-ai/oauth";
|
|
2
|
+
import { Container, getKeybindings, Input, Spacer, Text } from "@earendil-works/pi-tui";
|
|
3
|
+
import { exec } from "child_process";
|
|
4
|
+
import { theme } from "../theme/theme.js";
|
|
5
|
+
import { DynamicBorder } from "./dynamic-border.js";
|
|
6
|
+
import { keyHint } from "./keybinding-hints.js";
|
|
7
|
+
/**
|
|
8
|
+
* Login dialog component - replaces editor during OAuth login flow
|
|
9
|
+
*/
|
|
10
|
+
export class LoginDialogComponent extends Container {
|
|
11
|
+
get focused() {
|
|
12
|
+
return this._focused;
|
|
13
|
+
}
|
|
14
|
+
set focused(value) {
|
|
15
|
+
this._focused = value;
|
|
16
|
+
this.input.focused = value;
|
|
17
|
+
}
|
|
18
|
+
constructor(tui, providerId, onComplete) {
|
|
19
|
+
super();
|
|
20
|
+
this.onComplete = onComplete;
|
|
21
|
+
this.abortController = new AbortController();
|
|
22
|
+
// Focusable implementation - propagate to input for IME cursor positioning
|
|
23
|
+
this._focused = false;
|
|
24
|
+
this.tui = tui;
|
|
25
|
+
const providerInfo = getOAuthProviders().find((p) => p.id === providerId);
|
|
26
|
+
const providerName = providerInfo?.name || providerId;
|
|
27
|
+
// Top border
|
|
28
|
+
this.addChild(new DynamicBorder());
|
|
29
|
+
// Title
|
|
30
|
+
this.addChild(new Text(theme.fg("warning", `Login to ${providerName}`), 1, 0));
|
|
31
|
+
// Dynamic content area
|
|
32
|
+
this.contentContainer = new Container();
|
|
33
|
+
this.addChild(this.contentContainer);
|
|
34
|
+
// Input (always present, used when needed)
|
|
35
|
+
this.input = new Input();
|
|
36
|
+
this.input.onSubmit = () => {
|
|
37
|
+
if (this.inputResolver) {
|
|
38
|
+
this.inputResolver(this.input.getValue());
|
|
39
|
+
this.inputResolver = undefined;
|
|
40
|
+
this.inputRejecter = undefined;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
this.input.onEscape = () => {
|
|
44
|
+
this.cancel();
|
|
45
|
+
};
|
|
46
|
+
// Bottom border
|
|
47
|
+
this.addChild(new DynamicBorder());
|
|
48
|
+
}
|
|
49
|
+
get signal() {
|
|
50
|
+
return this.abortController.signal;
|
|
51
|
+
}
|
|
52
|
+
cancel() {
|
|
53
|
+
this.abortController.abort();
|
|
54
|
+
if (this.inputRejecter) {
|
|
55
|
+
this.inputRejecter(new Error("Login cancelled"));
|
|
56
|
+
this.inputResolver = undefined;
|
|
57
|
+
this.inputRejecter = undefined;
|
|
58
|
+
}
|
|
59
|
+
this.onComplete(false, "Login cancelled");
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Called by onAuth callback - show URL and optional instructions
|
|
63
|
+
*/
|
|
64
|
+
showAuth(url, instructions) {
|
|
65
|
+
this.contentContainer.clear();
|
|
66
|
+
this.contentContainer.addChild(new Spacer(1));
|
|
67
|
+
this.contentContainer.addChild(new Text(theme.fg("accent", url), 1, 0));
|
|
68
|
+
const clickHint = process.platform === "darwin" ? "Cmd+click to open" : "Ctrl+click to open";
|
|
69
|
+
const hyperlink = `\x1b]8;;${url}\x07${clickHint}\x1b]8;;\x07`;
|
|
70
|
+
this.contentContainer.addChild(new Text(theme.fg("dim", hyperlink), 1, 0));
|
|
71
|
+
if (instructions) {
|
|
72
|
+
this.contentContainer.addChild(new Spacer(1));
|
|
73
|
+
this.contentContainer.addChild(new Text(theme.fg("warning", instructions), 1, 0));
|
|
74
|
+
}
|
|
75
|
+
// Try to open browser
|
|
76
|
+
const openCmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
77
|
+
exec(`${openCmd} "${url}"`);
|
|
78
|
+
this.tui.requestRender();
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Show input for manual code/URL entry (for callback server providers)
|
|
82
|
+
*/
|
|
83
|
+
showManualInput(prompt) {
|
|
84
|
+
this.contentContainer.addChild(new Spacer(1));
|
|
85
|
+
this.contentContainer.addChild(new Text(theme.fg("dim", prompt), 1, 0));
|
|
86
|
+
this.contentContainer.addChild(this.input);
|
|
87
|
+
this.contentContainer.addChild(new Text(`(${keyHint("tui.select.cancel", "to cancel")})`, 1, 0));
|
|
88
|
+
this.tui.requestRender();
|
|
89
|
+
return new Promise((resolve, reject) => {
|
|
90
|
+
this.inputResolver = resolve;
|
|
91
|
+
this.inputRejecter = reject;
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Called by onPrompt callback - show prompt and wait for input
|
|
96
|
+
* Note: Does NOT clear content, appends to existing (preserves URL from showAuth)
|
|
97
|
+
*/
|
|
98
|
+
showPrompt(message, placeholder) {
|
|
99
|
+
this.contentContainer.addChild(new Spacer(1));
|
|
100
|
+
this.contentContainer.addChild(new Text(theme.fg("text", message), 1, 0));
|
|
101
|
+
if (placeholder) {
|
|
102
|
+
this.contentContainer.addChild(new Text(theme.fg("dim", `e.g., ${placeholder}`), 1, 0));
|
|
103
|
+
}
|
|
104
|
+
this.contentContainer.addChild(this.input);
|
|
105
|
+
this.contentContainer.addChild(new Text(`(${keyHint("tui.select.cancel", "to cancel,")} ${keyHint("tui.select.confirm", "to submit")})`, 1, 0));
|
|
106
|
+
this.input.setValue("");
|
|
107
|
+
this.tui.requestRender();
|
|
108
|
+
return new Promise((resolve, reject) => {
|
|
109
|
+
this.inputResolver = resolve;
|
|
110
|
+
this.inputRejecter = reject;
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Show waiting message (for polling flows like GitHub Copilot)
|
|
115
|
+
*/
|
|
116
|
+
showWaiting(message) {
|
|
117
|
+
this.contentContainer.addChild(new Spacer(1));
|
|
118
|
+
this.contentContainer.addChild(new Text(theme.fg("dim", message), 1, 0));
|
|
119
|
+
this.contentContainer.addChild(new Text(`(${keyHint("tui.select.cancel", "to cancel")})`, 1, 0));
|
|
120
|
+
this.tui.requestRender();
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Called by onProgress callback
|
|
124
|
+
*/
|
|
125
|
+
showProgress(message) {
|
|
126
|
+
this.contentContainer.addChild(new Text(theme.fg("dim", message), 1, 0));
|
|
127
|
+
this.tui.requestRender();
|
|
128
|
+
}
|
|
129
|
+
handleInput(data) {
|
|
130
|
+
const kb = getKeybindings();
|
|
131
|
+
if (kb.matches(data, "tui.select.cancel")) {
|
|
132
|
+
this.cancel();
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
// Pass to input
|
|
136
|
+
this.input.handleInput(data);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type Model } from "@earendil-works/pi-ai/compat";
|
|
2
|
+
import { Container, type Focusable, Input, type TUI } from "@earendil-works/pi-tui";
|
|
3
|
+
import type { ModelRegistry } from "../../../core/model-registry.js";
|
|
4
|
+
import type { SettingsManager } from "../../../core/settings-manager.js";
|
|
5
|
+
/**
|
|
6
|
+
* Component that renders a model selector with search
|
|
7
|
+
*/
|
|
8
|
+
export declare class ModelSelectorComponent extends Container implements Focusable {
|
|
9
|
+
private searchInput;
|
|
10
|
+
private _focused;
|
|
11
|
+
get focused(): boolean;
|
|
12
|
+
set focused(value: boolean);
|
|
13
|
+
private listContainer;
|
|
14
|
+
private allModels;
|
|
15
|
+
private filteredModels;
|
|
16
|
+
private selectedIndex;
|
|
17
|
+
private currentModel?;
|
|
18
|
+
private settingsManager;
|
|
19
|
+
private modelRegistry;
|
|
20
|
+
private onSelectCallback;
|
|
21
|
+
private onCancelCallback;
|
|
22
|
+
private errorMessage?;
|
|
23
|
+
private tui;
|
|
24
|
+
constructor(tui: TUI, currentModel: Model<any> | undefined, settingsManager: SettingsManager, modelRegistry: ModelRegistry, onSelect: (model: Model<any>) => void, onCancel: () => void, initialSearchInput?: string);
|
|
25
|
+
private loadModels;
|
|
26
|
+
private sortModels;
|
|
27
|
+
private filterModels;
|
|
28
|
+
private updateList;
|
|
29
|
+
handleInput(keyData: string): void;
|
|
30
|
+
private handleSelect;
|
|
31
|
+
getSearchInput(): Input;
|
|
32
|
+
}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { modelsAreEqual } from "@earendil-works/pi-ai/compat";
|
|
2
|
+
import { Container, fuzzyFilter, getKeybindings, Input, Spacer, Text, } from "@earendil-works/pi-tui";
|
|
3
|
+
import { theme } from "../theme/theme.js";
|
|
4
|
+
import { DynamicBorder } from "./dynamic-border.js";
|
|
5
|
+
/**
|
|
6
|
+
* Component that renders a model selector with search
|
|
7
|
+
*/
|
|
8
|
+
export class ModelSelectorComponent extends Container {
|
|
9
|
+
get focused() {
|
|
10
|
+
return this._focused;
|
|
11
|
+
}
|
|
12
|
+
set focused(value) {
|
|
13
|
+
this._focused = value;
|
|
14
|
+
this.searchInput.focused = value;
|
|
15
|
+
}
|
|
16
|
+
constructor(tui, currentModel, settingsManager, modelRegistry, onSelect, onCancel, initialSearchInput) {
|
|
17
|
+
super();
|
|
18
|
+
// Focusable implementation - propagate to searchInput for IME cursor positioning
|
|
19
|
+
this._focused = false;
|
|
20
|
+
this.allModels = [];
|
|
21
|
+
this.filteredModels = [];
|
|
22
|
+
this.selectedIndex = 0;
|
|
23
|
+
this.tui = tui;
|
|
24
|
+
this.currentModel = currentModel;
|
|
25
|
+
this.settingsManager = settingsManager;
|
|
26
|
+
this.modelRegistry = modelRegistry;
|
|
27
|
+
this.onSelectCallback = onSelect;
|
|
28
|
+
this.onCancelCallback = onCancel;
|
|
29
|
+
// Add top border
|
|
30
|
+
this.addChild(new DynamicBorder());
|
|
31
|
+
this.addChild(new Spacer(1));
|
|
32
|
+
// Add hint about model filtering
|
|
33
|
+
const hintText = "Only showing models with configured API keys (see README for details)";
|
|
34
|
+
this.addChild(new Text(theme.fg("warning", hintText), 0, 0));
|
|
35
|
+
this.addChild(new Spacer(1));
|
|
36
|
+
// Create search input
|
|
37
|
+
this.searchInput = new Input();
|
|
38
|
+
if (initialSearchInput) {
|
|
39
|
+
this.searchInput.setValue(initialSearchInput);
|
|
40
|
+
}
|
|
41
|
+
this.searchInput.onSubmit = () => {
|
|
42
|
+
// Enter on search input selects the first filtered item
|
|
43
|
+
if (this.filteredModels[this.selectedIndex]) {
|
|
44
|
+
this.handleSelect(this.filteredModels[this.selectedIndex].model);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
this.addChild(this.searchInput);
|
|
48
|
+
this.addChild(new Spacer(1));
|
|
49
|
+
// Create list container
|
|
50
|
+
this.listContainer = new Container();
|
|
51
|
+
this.addChild(this.listContainer);
|
|
52
|
+
this.addChild(new Spacer(1));
|
|
53
|
+
// Add bottom border
|
|
54
|
+
this.addChild(new DynamicBorder());
|
|
55
|
+
// Load models and do initial render
|
|
56
|
+
this.loadModels().then(() => {
|
|
57
|
+
if (initialSearchInput) {
|
|
58
|
+
this.filterModels(initialSearchInput);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
this.updateList();
|
|
62
|
+
}
|
|
63
|
+
// Request re-render after models are loaded
|
|
64
|
+
this.tui.requestRender();
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
async loadModels() {
|
|
68
|
+
let models;
|
|
69
|
+
// Refresh to pick up any changes to models.json
|
|
70
|
+
this.modelRegistry.refresh();
|
|
71
|
+
// Check for models.json errors
|
|
72
|
+
const loadError = this.modelRegistry.getError();
|
|
73
|
+
if (loadError) {
|
|
74
|
+
this.errorMessage = loadError;
|
|
75
|
+
}
|
|
76
|
+
// Load available models (built-in models still work even if models.json failed)
|
|
77
|
+
try {
|
|
78
|
+
const availableModels = await this.modelRegistry.getAvailable();
|
|
79
|
+
models = availableModels.map((model) => ({
|
|
80
|
+
provider: model.provider,
|
|
81
|
+
id: model.id,
|
|
82
|
+
model,
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
this.allModels = [];
|
|
87
|
+
this.filteredModels = [];
|
|
88
|
+
this.errorMessage = error instanceof Error ? error.message : String(error);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
this.allModels = this.sortModels(models);
|
|
92
|
+
this.filteredModels = this.allModels;
|
|
93
|
+
const currentIndex = this.filteredModels.findIndex((item) => modelsAreEqual(this.currentModel, item.model));
|
|
94
|
+
this.selectedIndex =
|
|
95
|
+
currentIndex >= 0 ? currentIndex : Math.min(this.selectedIndex, Math.max(0, this.filteredModels.length - 1));
|
|
96
|
+
}
|
|
97
|
+
sortModels(models) {
|
|
98
|
+
const sorted = [...models];
|
|
99
|
+
// Sort: current model first, then by provider
|
|
100
|
+
sorted.sort((a, b) => {
|
|
101
|
+
const aIsCurrent = modelsAreEqual(this.currentModel, a.model);
|
|
102
|
+
const bIsCurrent = modelsAreEqual(this.currentModel, b.model);
|
|
103
|
+
if (aIsCurrent && !bIsCurrent)
|
|
104
|
+
return -1;
|
|
105
|
+
if (!aIsCurrent && bIsCurrent)
|
|
106
|
+
return 1;
|
|
107
|
+
return a.provider.localeCompare(b.provider);
|
|
108
|
+
});
|
|
109
|
+
return sorted;
|
|
110
|
+
}
|
|
111
|
+
filterModels(query) {
|
|
112
|
+
this.filteredModels = query
|
|
113
|
+
? fuzzyFilter(this.allModels, query, ({ id, provider }) => `${id} ${provider} ${provider}/${id} ${provider} ${id}`)
|
|
114
|
+
: this.allModels;
|
|
115
|
+
this.selectedIndex = Math.min(this.selectedIndex, Math.max(0, this.filteredModels.length - 1));
|
|
116
|
+
this.updateList();
|
|
117
|
+
}
|
|
118
|
+
updateList() {
|
|
119
|
+
this.listContainer.clear();
|
|
120
|
+
const maxVisible = 10;
|
|
121
|
+
const startIndex = Math.max(0, Math.min(this.selectedIndex - Math.floor(maxVisible / 2), this.filteredModels.length - maxVisible));
|
|
122
|
+
const endIndex = Math.min(startIndex + maxVisible, this.filteredModels.length);
|
|
123
|
+
// Show visible slice of filtered models
|
|
124
|
+
for (let i = startIndex; i < endIndex; i++) {
|
|
125
|
+
const item = this.filteredModels[i];
|
|
126
|
+
if (!item)
|
|
127
|
+
continue;
|
|
128
|
+
const isSelected = i === this.selectedIndex;
|
|
129
|
+
const isCurrent = modelsAreEqual(this.currentModel, item.model);
|
|
130
|
+
let line = "";
|
|
131
|
+
if (isSelected) {
|
|
132
|
+
const prefix = theme.fg("accent", "→ ");
|
|
133
|
+
const modelText = `${item.id}`;
|
|
134
|
+
const providerBadge = theme.fg("muted", `[${item.provider}]`);
|
|
135
|
+
const checkmark = isCurrent ? theme.fg("success", " ✓") : "";
|
|
136
|
+
line = `${prefix + theme.fg("accent", modelText)} ${providerBadge}${checkmark}`;
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
const modelText = ` ${item.id}`;
|
|
140
|
+
const providerBadge = theme.fg("muted", `[${item.provider}]`);
|
|
141
|
+
const checkmark = isCurrent ? theme.fg("success", " ✓") : "";
|
|
142
|
+
line = `${modelText} ${providerBadge}${checkmark}`;
|
|
143
|
+
}
|
|
144
|
+
this.listContainer.addChild(new Text(line, 0, 0));
|
|
145
|
+
}
|
|
146
|
+
// Add scroll indicator if needed
|
|
147
|
+
if (startIndex > 0 || endIndex < this.filteredModels.length) {
|
|
148
|
+
const scrollInfo = theme.fg("muted", ` (${this.selectedIndex + 1}/${this.filteredModels.length})`);
|
|
149
|
+
this.listContainer.addChild(new Text(scrollInfo, 0, 0));
|
|
150
|
+
}
|
|
151
|
+
// Show error message or "no results" if empty
|
|
152
|
+
if (this.errorMessage) {
|
|
153
|
+
// Show error in red
|
|
154
|
+
const errorLines = this.errorMessage.split("\n");
|
|
155
|
+
for (const line of errorLines) {
|
|
156
|
+
this.listContainer.addChild(new Text(theme.fg("error", line), 0, 0));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
else if (this.filteredModels.length === 0) {
|
|
160
|
+
this.listContainer.addChild(new Text(theme.fg("muted", " No matching models"), 0, 0));
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
const selected = this.filteredModels[this.selectedIndex];
|
|
164
|
+
this.listContainer.addChild(new Spacer(1));
|
|
165
|
+
this.listContainer.addChild(new Text(theme.fg("muted", ` Model Name: ${selected.model.name}`), 0, 0));
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
handleInput(keyData) {
|
|
169
|
+
const kb = getKeybindings();
|
|
170
|
+
// Up arrow - wrap to bottom when at top
|
|
171
|
+
if (kb.matches(keyData, "tui.select.up")) {
|
|
172
|
+
if (this.filteredModels.length === 0)
|
|
173
|
+
return;
|
|
174
|
+
this.selectedIndex = this.selectedIndex === 0 ? this.filteredModels.length - 1 : this.selectedIndex - 1;
|
|
175
|
+
this.updateList();
|
|
176
|
+
}
|
|
177
|
+
// Down arrow - wrap to top when at bottom
|
|
178
|
+
else if (kb.matches(keyData, "tui.select.down")) {
|
|
179
|
+
if (this.filteredModels.length === 0)
|
|
180
|
+
return;
|
|
181
|
+
this.selectedIndex = this.selectedIndex === this.filteredModels.length - 1 ? 0 : this.selectedIndex + 1;
|
|
182
|
+
this.updateList();
|
|
183
|
+
}
|
|
184
|
+
// Enter
|
|
185
|
+
else if (kb.matches(keyData, "tui.select.confirm")) {
|
|
186
|
+
const selectedModel = this.filteredModels[this.selectedIndex];
|
|
187
|
+
if (selectedModel) {
|
|
188
|
+
this.handleSelect(selectedModel.model);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
// Escape or Ctrl+C
|
|
192
|
+
else if (kb.matches(keyData, "tui.select.cancel")) {
|
|
193
|
+
this.onCancelCallback();
|
|
194
|
+
}
|
|
195
|
+
// Pass everything else to search input
|
|
196
|
+
else {
|
|
197
|
+
this.searchInput.handleInput(keyData);
|
|
198
|
+
this.filterModels(this.searchInput.getValue());
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
handleSelect(model) {
|
|
202
|
+
// Save as new default
|
|
203
|
+
this.settingsManager.setDefaultModelAndProvider(model.provider, model.id);
|
|
204
|
+
this.onSelectCallback(model);
|
|
205
|
+
}
|
|
206
|
+
getSearchInput() {
|
|
207
|
+
return this.searchInput;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Container } from "@earendil-works/pi-tui";
|
|
2
|
+
import type { AuthStorage } from "../../../core/auth-storage.js";
|
|
3
|
+
/**
|
|
4
|
+
* Component that renders an OAuth provider selector
|
|
5
|
+
*/
|
|
6
|
+
export declare class OAuthSelectorComponent extends Container {
|
|
7
|
+
private listContainer;
|
|
8
|
+
private allProviders;
|
|
9
|
+
private selectedIndex;
|
|
10
|
+
private mode;
|
|
11
|
+
private authStorage;
|
|
12
|
+
private onSelectCallback;
|
|
13
|
+
private onCancelCallback;
|
|
14
|
+
constructor(mode: "login" | "logout", authStorage: AuthStorage, onSelect: (providerId: string) => void, onCancel: () => void);
|
|
15
|
+
private loadProviders;
|
|
16
|
+
private updateList;
|
|
17
|
+
handleInput(keyData: string): void;
|
|
18
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { getOAuthProviders } from "@earendil-works/pi-ai/oauth";
|
|
2
|
+
import { Container, getKeybindings, Spacer, TruncatedText } from "@earendil-works/pi-tui";
|
|
3
|
+
import { theme } from "../theme/theme.js";
|
|
4
|
+
import { DynamicBorder } from "./dynamic-border.js";
|
|
5
|
+
/**
|
|
6
|
+
* Component that renders an OAuth provider selector
|
|
7
|
+
*/
|
|
8
|
+
export class OAuthSelectorComponent extends Container {
|
|
9
|
+
constructor(mode, authStorage, onSelect, onCancel) {
|
|
10
|
+
super();
|
|
11
|
+
this.allProviders = [];
|
|
12
|
+
this.selectedIndex = 0;
|
|
13
|
+
this.mode = mode;
|
|
14
|
+
this.authStorage = authStorage;
|
|
15
|
+
this.onSelectCallback = onSelect;
|
|
16
|
+
this.onCancelCallback = onCancel;
|
|
17
|
+
// Load all OAuth providers
|
|
18
|
+
this.loadProviders();
|
|
19
|
+
// Add top border
|
|
20
|
+
this.addChild(new DynamicBorder());
|
|
21
|
+
this.addChild(new Spacer(1));
|
|
22
|
+
// Add title
|
|
23
|
+
const title = mode === "login" ? "Select provider to login:" : "Select provider to logout:";
|
|
24
|
+
this.addChild(new TruncatedText(theme.bold(title)));
|
|
25
|
+
this.addChild(new Spacer(1));
|
|
26
|
+
// Create list container
|
|
27
|
+
this.listContainer = new Container();
|
|
28
|
+
this.addChild(this.listContainer);
|
|
29
|
+
this.addChild(new Spacer(1));
|
|
30
|
+
// Add bottom border
|
|
31
|
+
this.addChild(new DynamicBorder());
|
|
32
|
+
// Initial render
|
|
33
|
+
this.updateList();
|
|
34
|
+
}
|
|
35
|
+
loadProviders() {
|
|
36
|
+
this.allProviders = getOAuthProviders();
|
|
37
|
+
}
|
|
38
|
+
updateList() {
|
|
39
|
+
this.listContainer.clear();
|
|
40
|
+
for (let i = 0; i < this.allProviders.length; i++) {
|
|
41
|
+
const provider = this.allProviders[i];
|
|
42
|
+
if (!provider)
|
|
43
|
+
continue;
|
|
44
|
+
const isSelected = i === this.selectedIndex;
|
|
45
|
+
// Check if user is logged in for this provider
|
|
46
|
+
const credentials = this.authStorage.get(provider.id);
|
|
47
|
+
const isLoggedIn = credentials?.type === "oauth";
|
|
48
|
+
const statusIndicator = isLoggedIn ? theme.fg("success", " ✓ logged in") : "";
|
|
49
|
+
let line = "";
|
|
50
|
+
if (isSelected) {
|
|
51
|
+
const prefix = theme.fg("accent", "→ ");
|
|
52
|
+
const text = theme.fg("accent", provider.name);
|
|
53
|
+
line = prefix + text + statusIndicator;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
const text = ` ${provider.name}`;
|
|
57
|
+
line = text + statusIndicator;
|
|
58
|
+
}
|
|
59
|
+
this.listContainer.addChild(new TruncatedText(line, 0, 0));
|
|
60
|
+
}
|
|
61
|
+
// Show "no providers" if empty
|
|
62
|
+
if (this.allProviders.length === 0) {
|
|
63
|
+
const message = this.mode === "login" ? "No OAuth providers available" : "No OAuth providers logged in. Use /login first.";
|
|
64
|
+
this.listContainer.addChild(new TruncatedText(theme.fg("muted", ` ${message}`), 0, 0));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
handleInput(keyData) {
|
|
68
|
+
const kb = getKeybindings();
|
|
69
|
+
// Up arrow
|
|
70
|
+
if (kb.matches(keyData, "tui.select.up")) {
|
|
71
|
+
this.selectedIndex = Math.max(0, this.selectedIndex - 1);
|
|
72
|
+
this.updateList();
|
|
73
|
+
}
|
|
74
|
+
// Down arrow
|
|
75
|
+
else if (kb.matches(keyData, "tui.select.down")) {
|
|
76
|
+
this.selectedIndex = Math.min(this.allProviders.length - 1, this.selectedIndex + 1);
|
|
77
|
+
this.updateList();
|
|
78
|
+
}
|
|
79
|
+
// Enter
|
|
80
|
+
else if (kb.matches(keyData, "tui.select.confirm")) {
|
|
81
|
+
const selectedProvider = this.allProviders[this.selectedIndex];
|
|
82
|
+
if (selectedProvider) {
|
|
83
|
+
this.onSelectCallback(selectedProvider.id);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Escape or Ctrl+C
|
|
87
|
+
else if (kb.matches(keyData, "tui.select.cancel")) {
|
|
88
|
+
this.onCancelCallback();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { ThinkingLevel } from "../../../core/agent/types.js";
|
|
2
|
+
import type { Transport } from "@earendil-works/pi-ai/compat";
|
|
3
|
+
import { Container, SettingsList } from "@earendil-works/pi-tui";
|
|
4
|
+
export interface SettingsConfig {
|
|
5
|
+
autoCompact: boolean;
|
|
6
|
+
showImages: boolean;
|
|
7
|
+
imageWidthCells: number;
|
|
8
|
+
autoResizeImages: boolean;
|
|
9
|
+
blockImages: boolean;
|
|
10
|
+
enableSkillCommands: boolean;
|
|
11
|
+
transport: Transport;
|
|
12
|
+
thinkingLevel: ThinkingLevel;
|
|
13
|
+
availableThinkingLevels: ThinkingLevel[];
|
|
14
|
+
currentTheme: string;
|
|
15
|
+
availableThemes: string[];
|
|
16
|
+
hideThinkingBlock: boolean;
|
|
17
|
+
collapseChangelog: boolean;
|
|
18
|
+
enableInstallTelemetry: boolean;
|
|
19
|
+
doubleEscapeAction: "fork" | "tree" | "none";
|
|
20
|
+
treeFilterMode: "default" | "no-tools" | "user-only" | "labeled-only" | "all";
|
|
21
|
+
showHardwareCursor: boolean;
|
|
22
|
+
editorPaddingX: number;
|
|
23
|
+
autocompleteMaxVisible: number;
|
|
24
|
+
quietStartup: boolean;
|
|
25
|
+
clearOnShrink: boolean;
|
|
26
|
+
}
|
|
27
|
+
export interface SettingsCallbacks {
|
|
28
|
+
onAutoCompactChange: (enabled: boolean) => void;
|
|
29
|
+
onShowImagesChange: (enabled: boolean) => void;
|
|
30
|
+
onImageWidthCellsChange: (width: number) => void;
|
|
31
|
+
onAutoResizeImagesChange: (enabled: boolean) => void;
|
|
32
|
+
onBlockImagesChange: (blocked: boolean) => void;
|
|
33
|
+
onEnableSkillCommandsChange: (enabled: boolean) => void;
|
|
34
|
+
onTransportChange: (transport: Transport) => void;
|
|
35
|
+
onThinkingLevelChange: (level: ThinkingLevel) => void;
|
|
36
|
+
onThemeChange: (theme: string) => void;
|
|
37
|
+
onThemePreview?: (theme: string) => void;
|
|
38
|
+
onHideThinkingBlockChange: (hidden: boolean) => void;
|
|
39
|
+
onCollapseChangelogChange: (collapsed: boolean) => void;
|
|
40
|
+
onEnableInstallTelemetryChange: (enabled: boolean) => void;
|
|
41
|
+
onDoubleEscapeActionChange: (action: "fork" | "tree" | "none") => void;
|
|
42
|
+
onTreeFilterModeChange: (mode: "default" | "no-tools" | "user-only" | "labeled-only" | "all") => void;
|
|
43
|
+
onShowHardwareCursorChange: (enabled: boolean) => void;
|
|
44
|
+
onEditorPaddingXChange: (padding: number) => void;
|
|
45
|
+
onAutocompleteMaxVisibleChange: (maxVisible: number) => void;
|
|
46
|
+
onQuietStartupChange: (enabled: boolean) => void;
|
|
47
|
+
onClearOnShrinkChange: (enabled: boolean) => void;
|
|
48
|
+
onCancel: () => void;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Main settings selector component.
|
|
52
|
+
*/
|
|
53
|
+
export declare class SettingsSelectorComponent extends Container {
|
|
54
|
+
private settingsList;
|
|
55
|
+
constructor(config: SettingsConfig, callbacks: SettingsCallbacks);
|
|
56
|
+
getSettingsList(): SettingsList;
|
|
57
|
+
}
|