@averyyy/pi-coding-agent 0.99.1-piclient.1 → 1.0.0-piclient.2
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/CHANGELOG.md +94 -0
- package/dist/bundle/chunks/anthropic-messages-5Z4I6I54.js +6 -0
- package/dist/bundle/chunks/anthropic.js +2 -2
- package/dist/bundle/chunks/{azure-openai-responses-YZ3Q2WVP.js → azure-openai-responses-TXH53UDQ.js} +1 -1
- package/dist/bundle/chunks/bedrock-converse-stream.js +2 -2
- package/dist/bundle/chunks/{chunk-7BINYQ2V.js → chunk-43NAB75E.js} +54 -49
- package/dist/bundle/chunks/{chunk-V7V43FNB.js → chunk-4ILNOXGR.js} +2 -2
- package/dist/bundle/chunks/chunk-AV6LYFGH.js +2 -0
- package/dist/bundle/chunks/{chunk-7JGR3GZN.js → chunk-F42GKQ7R.js} +1 -1
- package/dist/bundle/chunks/chunk-GIUN2MS4.js +16 -0
- package/dist/bundle/chunks/{chunk-W2DOMZSC.js → chunk-JTLRGL3E.js} +2 -2
- package/dist/bundle/chunks/{chunk-F6ORSP6L.js → chunk-KYK7L7MP.js} +18 -78
- package/dist/bundle/chunks/chunk-LD2P6SFZ.js +2 -0
- package/dist/bundle/chunks/chunk-LDPPAHPJ.js +4 -0
- package/dist/bundle/chunks/{chunk-3YXHSP6S.js → chunk-NEUJZQL3.js} +7 -9
- package/dist/bundle/chunks/chunk-OI6YFHHK.js +82 -0
- package/dist/bundle/chunks/{chunk-J4CWPC4N.js → chunk-PXGUCLIP.js} +1 -1
- package/dist/bundle/chunks/chunk-VIV3CWXG.js +2 -0
- package/dist/bundle/chunks/chunk-WGS2XTDX.js +2 -0
- package/dist/bundle/chunks/{chunk-FJTXMIZI.js → chunk-Y5O5BZGX.js} +15 -29
- package/dist/bundle/chunks/{cli-WF6HDHBO.js → cli-JE36AHMI.js} +8 -6
- package/dist/bundle/chunks/{cloudflare-workers-ai-system-one-XJQQYGGU.js → cloudflare-workers-ai-system-one-TF36V7KG.js} +1 -1
- package/dist/bundle/chunks/codemode-worker.js +67 -8
- package/dist/bundle/chunks/execute-UX73LR4F.js +367 -0
- package/dist/bundle/chunks/{google-generative-ai-CQAKKJTA.js → google-generative-ai-XQU2LTWM.js} +1 -1
- package/dist/bundle/chunks/{google-vertex-AE36YXJU.js → google-vertex-F6Q2CN55.js} +1 -1
- package/dist/bundle/chunks/{https-proxy-agent-2VXB7436.js → https-proxy-agent-UDEHOBGS.js} +1 -1
- package/dist/bundle/chunks/{llama-cpp-classify-PJJYKPLD.js → llama-cpp-classify-XT44PI3C.js} +1 -1
- package/dist/bundle/chunks/{mistral-conversations-KEYTXJM7.js → mistral-conversations-XAJWHQFR.js} +1 -1
- package/dist/bundle/chunks/openai-chatgpt.js +1 -1
- package/dist/bundle/chunks/{openai-codex-responses-FUE7WESF.js → openai-codex-responses-3EHOMZYM.js} +1 -1
- package/dist/bundle/chunks/openai-codex.js +1 -1
- package/dist/bundle/chunks/{openai-completions-XW2Q5HVC.js → openai-completions-QC2IQHSC.js} +1 -1
- package/dist/bundle/chunks/{openai-responses-ZUXFVYPI.js → openai-responses-JPLD2GJS.js} +1 -1
- package/dist/bundle/chunks/{openrouter-images-TPQ4V6OR.js → openrouter-images-ZVXWCSIM.js} +1 -1
- package/dist/bundle/chunks/openrouter.js +1 -1
- package/dist/bundle/chunks/pi-logo-animation-APS4JS6B.js +2 -0
- package/dist/bundle/chunks/radius.js +1 -1
- package/dist/bundle/chunks/runtime-MPXPM7VL.js +2 -0
- package/dist/bundle/chunks/{typesafe-system-one-E7A4HNJI.js → typesafe-system-one-7DJTDUKY.js} +1 -1
- package/dist/bundle/chunks/virtual-modules-X5AB6TM6.js +2 -0
- package/dist/bundle/cli-runtime.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/cli/args.js +2 -2
- package/dist/cli/args.js.map +1 -1
- package/dist/config.d.ts +5 -8
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +16 -13
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +15 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +80 -12
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/cache-warmer.d.ts.map +1 -1
- package/dist/core/cache-warmer.js +11 -3
- package/dist/core/cache-warmer.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +13 -1
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/types.d.ts +6 -1
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/mcp-servers.d.ts +34 -7
- package/dist/core/mcp-servers.d.ts.map +1 -1
- package/dist/core/mcp-servers.js +52 -11
- package/dist/core/mcp-servers.js.map +1 -1
- package/dist/core/model-registry.d.ts +3 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +4 -0
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.js +1 -1
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-runtime.d.ts +22 -0
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +347 -49
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/pi-server-client.d.ts +21 -1
- package/dist/core/pi-server-client.d.ts.map +1 -1
- package/dist/core/pi-server-client.js +308 -22
- package/dist/core/pi-server-client.js.map +1 -1
- package/dist/core/pi-server-protocol.d.ts +12 -1
- package/dist/core/pi-server-protocol.d.ts.map +1 -1
- package/dist/core/pi-server-protocol.js +1 -0
- package/dist/core/pi-server-protocol.js.map +1 -1
- package/dist/core/radius.d.ts +2 -0
- package/dist/core/radius.d.ts.map +1 -1
- package/dist/core/radius.js +2 -0
- package/dist/core/radius.js.map +1 -1
- package/dist/core/remote-catalog-provider.d.ts.map +1 -1
- package/dist/core/remote-catalog-provider.js +4 -9
- package/dist/core/remote-catalog-provider.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +52 -18
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/settings-manager.d.ts +7 -5
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +3 -2
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/system-prompt.js +1 -1
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +3 -5
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/renderers/bash.d.ts.map +1 -1
- package/dist/core/tools/renderers/bash.js +11 -31
- package/dist/core/tools/renderers/bash.js.map +1 -1
- package/dist/core/virtual-models.d.ts +2 -0
- package/dist/core/virtual-models.d.ts.map +1 -1
- package/dist/core/virtual-models.js +19 -12
- package/dist/core/virtual-models.js.map +1 -1
- package/dist/extensions/codemode/execute.d.ts.map +1 -1
- package/dist/extensions/codemode/execute.js +197 -51
- package/dist/extensions/codemode/execute.js.map +1 -1
- package/dist/extensions/codemode/renderer.d.ts.map +1 -1
- package/dist/extensions/codemode/renderer.js +43 -25
- package/dist/extensions/codemode/renderer.js.map +1 -1
- package/dist/extensions/codemode/tool.d.ts +12 -11
- package/dist/extensions/codemode/tool.d.ts.map +1 -1
- package/dist/extensions/codemode/tool.js +73 -129
- package/dist/extensions/codemode/tool.js.map +1 -1
- package/dist/extensions/codemode/worker.d.ts +1 -1
- package/dist/extensions/codemode/worker.js +1 -1
- package/dist/extensions/codemode/worker.js.map +1 -1
- package/dist/extensions/mcp/cli.d.ts.map +1 -1
- package/dist/extensions/mcp/cli.js +20 -5
- package/dist/extensions/mcp/cli.js.map +1 -1
- package/dist/extensions/mcp/config.d.ts +4 -2
- package/dist/extensions/mcp/config.d.ts.map +1 -1
- package/dist/extensions/mcp/config.js +14 -2
- package/dist/extensions/mcp/config.js.map +1 -1
- package/dist/extensions/mcp/index.d.ts +32 -8
- package/dist/extensions/mcp/index.d.ts.map +1 -1
- package/dist/extensions/mcp/index.js +220 -56
- package/dist/extensions/mcp/index.js.map +1 -1
- package/dist/extensions/mcp/oauth.d.ts +10 -7
- package/dist/extensions/mcp/oauth.d.ts.map +1 -1
- package/dist/extensions/mcp/oauth.js +56 -31
- package/dist/extensions/mcp/oauth.js.map +1 -1
- package/dist/extensions/mcp/runtime.d.ts +2 -0
- package/dist/extensions/mcp/runtime.d.ts.map +1 -1
- package/dist/extensions/mcp/runtime.js +16 -9
- package/dist/extensions/mcp/runtime.js.map +1 -1
- package/dist/extensions/mcp/tools.d.ts +5 -4
- package/dist/extensions/mcp/tools.d.ts.map +1 -1
- package/dist/extensions/mcp/tools.js +33 -15
- package/dist/extensions/mcp/tools.js.map +1 -1
- package/dist/extensions/mcp/ui.d.ts.map +1 -1
- package/dist/extensions/mcp/ui.js +4 -2
- package/dist/extensions/mcp/ui.js.map +1 -1
- package/dist/extensions/tool-search/tool.d.ts +5 -4
- package/dist/extensions/tool-search/tool.d.ts.map +1 -1
- package/dist/extensions/tool-search/tool.js +7 -28
- package/dist/extensions/tool-search/tool.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +24 -11
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts +8 -2
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +24 -21
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/components/pi-logo-animation.d.ts +68 -0
- package/dist/modes/interactive/components/pi-logo-animation.d.ts.map +1 -0
- package/dist/modes/interactive/components/pi-logo-animation.js +1086 -0
- package/dist/modes/interactive/components/pi-logo-animation.js.map +1 -0
- package/dist/modes/interactive/components/pi-logo-animation.lazy.d.ts +7 -0
- package/dist/modes/interactive/components/pi-logo-animation.lazy.d.ts.map +1 -0
- package/dist/modes/interactive/components/pi-logo-animation.lazy.js +12 -0
- package/dist/modes/interactive/components/pi-logo-animation.lazy.js.map +1 -0
- package/dist/modes/interactive/components/pi-logo.d.ts +7 -0
- package/dist/modes/interactive/components/pi-logo.d.ts.map +1 -1
- package/dist/modes/interactive/components/pi-logo.js +13 -1
- package/dist/modes/interactive/components/pi-logo.js.map +1 -1
- package/dist/modes/interactive/components/radius-login-selector.d.ts +15 -0
- package/dist/modes/interactive/components/radius-login-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/radius-login-selector.js +85 -0
- package/dist/modes/interactive/components/radius-login-selector.js.map +1 -0
- package/dist/modes/interactive/components/settings-selector.d.ts +3 -3
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +5 -5
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js +5 -4
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/components/visual-truncate.d.ts +27 -3
- package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
- package/dist/modes/interactive/components/visual-truncate.js +39 -6
- package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +10 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +153 -40
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/system-theme.d.ts +2 -1
- package/dist/modes/interactive/theme/system-theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/system-theme.js +16 -5
- package/dist/modes/interactive/theme/system-theme.js.map +1 -1
- package/docs/cli.md +8 -18
- package/docs/codemode.md +207 -0
- package/docs/docs.json +5 -1
- package/docs/environment-variables.md +2 -2
- package/docs/extensions.md +3 -3
- package/docs/index.md +1 -1
- package/docs/mcp.md +142 -82
- package/docs/models.md +22 -1
- package/docs/providers.md +18 -6
- package/docs/sdk.md +2 -2
- package/docs/settings.md +5 -3
- package/docs/usage.md +1 -1
- package/examples/extensions/built-in-tool-renderer.ts +16 -40
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/minimal-mode.ts +24 -96
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/sdk/14-codemode-mcp.ts +2 -2
- package/package.json +10 -10
- package/dist/bundle/chunks/anthropic-messages-A6EXUBG6.js +0 -6
- package/dist/bundle/chunks/chunk-HSPCVFST.js +0 -2
- package/dist/bundle/chunks/chunk-KYJKN5BJ.js +0 -2
- package/dist/bundle/chunks/chunk-RO6I2QFQ.js +0 -4
- package/dist/bundle/chunks/chunk-WVKBMRQX.js +0 -82
- package/dist/bundle/chunks/chunk-XNGRGP62.js +0 -2
- package/dist/bundle/chunks/execute-AVGAUHMT.js +0 -308
- package/dist/bundle/chunks/runtime-6ZC4MGWD.js +0 -2
- package/dist/bundle/chunks/virtual-modules-H7OCXN6W.js +0 -2
|
@@ -26,6 +26,7 @@ import { defaultModelPerProvider, findExactModelReferenceMatch, resolveModelScop
|
|
|
26
26
|
import { CredentialSynchronizationError } from "../../core/model-runtime.js";
|
|
27
27
|
import { DefaultPackageManager } from "../../core/package-manager.js";
|
|
28
28
|
import { getCliBinName } from "../../core/pi-client-cli-adapter.js";
|
|
29
|
+
import { RADIUS_MCP_URL, RADIUS_PROVIDER_ID } from "../../core/radius.js";
|
|
29
30
|
import { formatMissingSessionCwdPrompt, MissingSessionCwdError } from "../../core/session-cwd.js";
|
|
30
31
|
import { SessionManager, sessionEntryToContextMessages, } from "../../core/session-manager.js";
|
|
31
32
|
import { BUILTIN_SLASH_COMMANDS } from "../../core/slash-commands.js";
|
|
@@ -33,6 +34,7 @@ import { isInstallTelemetryEnabled } from "../../core/telemetry.js";
|
|
|
33
34
|
import { withBuiltInRenderers } from "../../core/tools/renderers/index.js";
|
|
34
35
|
import { hasTrustRequiringProjectResources, ProjectTrustStore } from "../../core/trust-manager.js";
|
|
35
36
|
import { getUsageCostBreakdown } from "../../core/usage-totals.js";
|
|
37
|
+
import { addMcpServerConfig, loadMcpConfig } from "../../extensions/mcp/config.js";
|
|
36
38
|
import { getChangelogPath, getNewEntries, normalizeChangelogLinks, parseChangelog } from "../../utils/changelog.js";
|
|
37
39
|
import { copyToClipboard, readClipboardFilePaths, readClipboardText } from "../../utils/clipboard.js";
|
|
38
40
|
import { extensionForImageMimeType, readClipboardImage } from "../../utils/clipboard-image.js";
|
|
@@ -64,8 +66,10 @@ import { formatKeyText, keyDisplayText, keyHint, keyText, rawKeyHint } from "./c
|
|
|
64
66
|
import { LoginDialogComponent } from "./components/login-dialog.js";
|
|
65
67
|
import { createMermaidMarkdownTransformer } from "./components/mermaid.js";
|
|
66
68
|
import { ModelSelectorComponent } from "./components/model-selector.js";
|
|
67
|
-
import { formatAuthSelectorProviderType, OAuthSelectorComponent, } from "./components/oauth-selector.js";
|
|
68
|
-
import { piLogoLines } from "./components/pi-logo.js";
|
|
69
|
+
import { formatAuthSelectorProviderStatus, formatAuthSelectorProviderType, OAuthSelectorComponent, } from "./components/oauth-selector.js";
|
|
70
|
+
import { piLogoLines, piWordmark, supportsPiLogo } from "./components/pi-logo.js";
|
|
71
|
+
import { playPiLogoAnimation } from "./components/pi-logo-animation.lazy.js";
|
|
72
|
+
import { createLoginMenuSelector } from "./components/radius-login-selector.js";
|
|
69
73
|
import { ScopedModelsSelectorComponent } from "./components/scoped-models-selector.js";
|
|
70
74
|
import { SessionSelectorComponent } from "./components/session-selector.js";
|
|
71
75
|
import { SettingsSelectorComponent } from "./components/settings-selector.js";
|
|
@@ -107,6 +111,16 @@ class ExpandableText extends ThemedText {
|
|
|
107
111
|
this.invalidate();
|
|
108
112
|
}
|
|
109
113
|
}
|
|
114
|
+
/** The built-in header. Clicking its logo (the first two lines, after one column of padding) plays an easter egg. */
|
|
115
|
+
class BuiltInHeader extends ExpandableText {
|
|
116
|
+
onLogoClick;
|
|
117
|
+
handleMouse(event) {
|
|
118
|
+
if (event.type !== "click" || event.y > 1 || event.x < 1 || event.x > 4 || !this.onLogoClick)
|
|
119
|
+
return undefined;
|
|
120
|
+
this.onLogoClick(event.screenX - event.x + 1, event.screenY - event.y);
|
|
121
|
+
return { handled: true };
|
|
122
|
+
}
|
|
123
|
+
}
|
|
110
124
|
function isCustomSessionEntry(item) {
|
|
111
125
|
return "type" in item && item.type === "custom";
|
|
112
126
|
}
|
|
@@ -176,6 +190,7 @@ function llamaCppPostLoginGuidance(actionLabel, loadedModelCount) {
|
|
|
176
190
|
? `${actionLabel}. No llama.cpp models are loaded. Use /llama to load a model, then /model to select it.`
|
|
177
191
|
: `${actionLabel}. Use /model to select a loaded llama.cpp model, or /llama to manage models.`;
|
|
178
192
|
}
|
|
193
|
+
const RADIUS_LOGIN_INTRO = "Radius is a service crafted for Pi by the builders of Pi, Earendil Works";
|
|
179
194
|
const AUTH_TYPE_ORDER = { oauth: 0, api_key: 1 };
|
|
180
195
|
function createFuzzyAutocompleteItems(items, prefix, getSearchText, toAutocompleteItem) {
|
|
181
196
|
const filtered = fuzzyFilter(items, prefix, getSearchText);
|
|
@@ -198,18 +213,21 @@ function getLoginProviderCompletionOptions(providerOptions) {
|
|
|
198
213
|
id: provider.id,
|
|
199
214
|
name: provider.name,
|
|
200
215
|
authTypes: [provider.authType],
|
|
216
|
+
subscription: provider.subscription,
|
|
201
217
|
});
|
|
202
218
|
}
|
|
203
219
|
return Array.from(byId.values()).sort((a, b) => a.name.localeCompare(b.name));
|
|
204
220
|
}
|
|
205
221
|
function getLoginProviderSearchText(provider) {
|
|
206
222
|
const authTypes = provider.authTypes
|
|
207
|
-
.map((authType) => `${authType} ${formatAuthSelectorProviderType(authType)}`)
|
|
223
|
+
.map((authType) => `${authType} ${formatAuthSelectorProviderType(authType, provider.subscription)}`)
|
|
208
224
|
.join(" ");
|
|
209
225
|
return `${provider.id} ${provider.name} ${authTypes}`;
|
|
210
226
|
}
|
|
211
227
|
function formatLoginProviderCompletionDescription(provider) {
|
|
212
|
-
const authTypes = provider.authTypes
|
|
228
|
+
const authTypes = provider.authTypes
|
|
229
|
+
.map((authType) => formatAuthSelectorProviderType(authType, provider.subscription))
|
|
230
|
+
.join("/");
|
|
213
231
|
return provider.name === provider.id ? authTypes : `${provider.name} · ${authTypes}`;
|
|
214
232
|
}
|
|
215
233
|
export class InteractiveMode {
|
|
@@ -642,7 +660,7 @@ export class InteractiveMode {
|
|
|
642
660
|
this.registerSignalHandlers();
|
|
643
661
|
// Load changelog (only show new entries, skip for resumed sessions)
|
|
644
662
|
this.changelogMarkdown = this.getChangelogForDisplay();
|
|
645
|
-
if (this.session.scopedModels.length > 0 &&
|
|
663
|
+
if (this.session.scopedModels.length > 0 && this.shouldShowStartupDetails()) {
|
|
646
664
|
const modelList = this.session.scopedModels
|
|
647
665
|
.map((sm) => {
|
|
648
666
|
const thinkingStr = sm.thinkingLevel ? `:${sm.thinkingLevel}` : "";
|
|
@@ -694,10 +712,15 @@ export class InteractiveMode {
|
|
|
694
712
|
// reported its colors. This ends at the terminal's DA1 reply, or after 100 ms if it answers nothing.
|
|
695
713
|
await this.themeController.waitForTerminalColors();
|
|
696
714
|
// Add header with keybindings from config (unless silenced)
|
|
697
|
-
if (this.
|
|
715
|
+
if (this.shouldShowStartupHeader()) {
|
|
716
|
+
const showDetails = this.shouldShowStartupDetails();
|
|
698
717
|
// Built on demand so the header follows theme changes. The logo's first line carries the version,
|
|
699
|
-
// its second line the first line of key hints.
|
|
718
|
+
// its second line the first line of key hints. Terminals that cannot render the logo get a
|
|
719
|
+
// "Pi vX" line instead, with the key hints below it.
|
|
720
|
+
const showLogo = supportsPiLogo();
|
|
700
721
|
const withLogo = (hints) => {
|
|
722
|
+
if (!showLogo)
|
|
723
|
+
return `${piWordmark()} ${theme.fg("dim", `v${this.version}`)}\n${hints}`;
|
|
701
724
|
const [top, bottom] = piLogoLines();
|
|
702
725
|
return `${top} ${theme.fg("dim", `v${this.version}`)}\n${bottom} ${hints}`;
|
|
703
726
|
};
|
|
@@ -731,9 +754,12 @@ export class InteractiveMode {
|
|
|
731
754
|
rawKeyHint("!", "bash"),
|
|
732
755
|
hint("app.tools.expand", "more"),
|
|
733
756
|
].join(theme.fg("muted", " · "));
|
|
734
|
-
const compactOnboarding = () => theme.fg("dim", `Press ${keyText("app.tools.expand")} to show full startup help and loaded resources.`);
|
|
757
|
+
const compactOnboarding = () => theme.fg("dim", `Press ${keyText("app.tools.expand")} to show full startup help${showDetails ? " and loaded resources" : ""}.`);
|
|
735
758
|
const onboarding = () => theme.fg("dim", `Pi can explain its own features and look up its docs. Ask it how to use or extend Pi.`);
|
|
736
|
-
|
|
759
|
+
const header = new BuiltInHeader(() => `${withLogo(compactInstructions())}\n${compactOnboarding()}\n\n${onboarding()}`, () => `${withLogo(expandedInstructions())}\n\n${onboarding()}`, this.getStartupExpansionState(), 1, 0);
|
|
760
|
+
if (showLogo)
|
|
761
|
+
header.onLogoClick = (column, row) => playPiLogoAnimation(this.renderer, column, row);
|
|
762
|
+
this.builtInHeader = header;
|
|
737
763
|
// Setup UI layout
|
|
738
764
|
this.headerContainer.addChild(new Spacer(1));
|
|
739
765
|
this.headerContainer.addChild(this.builtInHeader);
|
|
@@ -1046,6 +1072,14 @@ export class InteractiveMode {
|
|
|
1046
1072
|
getStartupExpansionState() {
|
|
1047
1073
|
return this.options.verbose || this.toolOutputExpanded;
|
|
1048
1074
|
}
|
|
1075
|
+
/** Startup header (logo, version, key hints). Hidden only by quietStartup: true. */
|
|
1076
|
+
shouldShowStartupHeader() {
|
|
1077
|
+
return this.options.verbose === true || this.settingsManager.getQuietStartup() !== true;
|
|
1078
|
+
}
|
|
1079
|
+
/** Startup details (model scope, loaded resources). Hidden by quietStartup: true or "header". */
|
|
1080
|
+
shouldShowStartupDetails() {
|
|
1081
|
+
return this.options.verbose === true || this.settingsManager.getQuietStartup() === false;
|
|
1082
|
+
}
|
|
1049
1083
|
/**
|
|
1050
1084
|
* Get a short path relative to the package root for display.
|
|
1051
1085
|
*/
|
|
@@ -1307,7 +1341,7 @@ export class InteractiveMode {
|
|
|
1307
1341
|
showLoadedResources(options) {
|
|
1308
1342
|
// Resource rendering is idempotent; chat clears no longer clear this separate container.
|
|
1309
1343
|
this.loadedResourcesContainer.clear();
|
|
1310
|
-
const showListing = options?.force || this.
|
|
1344
|
+
const showListing = options?.force || this.shouldShowStartupDetails();
|
|
1311
1345
|
const showDiagnostics = showListing || options?.showDiagnosticsWhenQuiet === true;
|
|
1312
1346
|
if (!showListing && !showDiagnostics) {
|
|
1313
1347
|
return;
|
|
@@ -4299,8 +4333,8 @@ export class InteractiveMode {
|
|
|
4299
4333
|
onEnableInstallTelemetryChange: (enabled) => {
|
|
4300
4334
|
this.settingsManager.setEnableInstallTelemetry(enabled);
|
|
4301
4335
|
},
|
|
4302
|
-
onQuietStartupChange: (
|
|
4303
|
-
this.settingsManager.setQuietStartup(
|
|
4336
|
+
onQuietStartupChange: (quiet) => {
|
|
4337
|
+
this.settingsManager.setQuietStartup(quiet);
|
|
4304
4338
|
},
|
|
4305
4339
|
onDefaultProjectTrustChange: (defaultProjectTrust) => {
|
|
4306
4340
|
this.settingsManager.setDefaultProjectTrust(defaultProjectTrust);
|
|
@@ -4952,6 +4986,7 @@ export class InteractiveMode {
|
|
|
4952
4986
|
source: authStatus.label ?? authStatus.source,
|
|
4953
4987
|
}
|
|
4954
4988
|
: undefined;
|
|
4989
|
+
const subscription = provider.auth.oauth?.isSubscription === true;
|
|
4955
4990
|
if ((!authType || authType === "oauth") && provider.auth.oauth) {
|
|
4956
4991
|
options.push({
|
|
4957
4992
|
id: provider.id,
|
|
@@ -4959,6 +4994,7 @@ export class InteractiveMode {
|
|
|
4959
4994
|
authType: "oauth",
|
|
4960
4995
|
method: provider.auth.oauth,
|
|
4961
4996
|
status,
|
|
4997
|
+
subscription,
|
|
4962
4998
|
});
|
|
4963
4999
|
}
|
|
4964
5000
|
if ((!authType || authType === "api_key") && provider.auth.apiKey) {
|
|
@@ -4968,6 +5004,7 @@ export class InteractiveMode {
|
|
|
4968
5004
|
authType: "api_key",
|
|
4969
5005
|
method: provider.auth.apiKey,
|
|
4970
5006
|
status,
|
|
5007
|
+
subscription,
|
|
4971
5008
|
});
|
|
4972
5009
|
}
|
|
4973
5010
|
}
|
|
@@ -4975,12 +5012,16 @@ export class InteractiveMode {
|
|
|
4975
5012
|
}
|
|
4976
5013
|
async getLogoutProviderOptions() {
|
|
4977
5014
|
return (await this.session.modelRuntime.listCredentials({ signal: AbortSignal.timeout(15_000) }))
|
|
4978
|
-
.map(({ providerId, type }) =>
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
5015
|
+
.map(({ providerId, type }) => {
|
|
5016
|
+
const provider = this.session.modelRuntime.getProvider(providerId);
|
|
5017
|
+
return {
|
|
5018
|
+
id: providerId,
|
|
5019
|
+
name: provider?.name ?? providerId,
|
|
5020
|
+
authType: type,
|
|
5021
|
+
status: { type, source: "stored credential" },
|
|
5022
|
+
subscription: provider?.auth.oauth?.isSubscription === true,
|
|
5023
|
+
};
|
|
5024
|
+
})
|
|
4984
5025
|
.sort((a, b) => a.name.localeCompare(b.name));
|
|
4985
5026
|
}
|
|
4986
5027
|
findLoginProviderOptions(providerRef) {
|
|
@@ -5010,18 +5051,25 @@ export class InteractiveMode {
|
|
|
5010
5051
|
}
|
|
5011
5052
|
this.showLoginProviderSelector(undefined, providerRef);
|
|
5012
5053
|
}
|
|
5013
|
-
|
|
5054
|
+
/** `onBack` reopens the selector the login was started from when the user cancels it. */
|
|
5055
|
+
async startProviderLogin(providerOption, onBack) {
|
|
5014
5056
|
if (providerOption.authType === "oauth") {
|
|
5015
|
-
await this.showLoginDialog(providerOption.id, providerOption.name);
|
|
5057
|
+
await this.showLoginDialog(providerOption.id, providerOption.name, onBack);
|
|
5016
5058
|
}
|
|
5017
5059
|
else if (providerOption.method?.login) {
|
|
5018
|
-
await this.showApiKeyLoginDialog(providerOption.id, providerOption.name);
|
|
5060
|
+
await this.showApiKeyLoginDialog(providerOption.id, providerOption.name, onBack);
|
|
5019
5061
|
}
|
|
5020
5062
|
else {
|
|
5021
|
-
this.showAmbientAuthDialog(providerOption);
|
|
5063
|
+
this.showAmbientAuthDialog(providerOption, onBack);
|
|
5022
5064
|
}
|
|
5023
5065
|
}
|
|
5024
5066
|
showLoginAuthTypeSelector(providerOptions) {
|
|
5067
|
+
// The top-level selector offers Radius directly, as its last option.
|
|
5068
|
+
const radiusOption = providerOptions
|
|
5069
|
+
? undefined
|
|
5070
|
+
: this.getLoginProviderOptions("oauth").find((provider) => provider.id === RADIUS_PROVIDER_ID);
|
|
5071
|
+
const radiusText = radiusOption ? `Sign in with ${radiusOption.name}` : undefined;
|
|
5072
|
+
const radiusLabel = radiusOption ? `${radiusText}${formatAuthSelectorProviderStatus(radiusOption)}` : undefined;
|
|
5025
5073
|
const oauthProvider = providerOptions?.find((provider) => provider.authType === "oauth");
|
|
5026
5074
|
const oauthLoginLabel = oauthProvider?.method && "loginLabel" in oauthProvider.method ? oauthProvider.method.loginLabel : undefined;
|
|
5027
5075
|
const subscriptionLabel = oauthLoginLabel ?? "Sign in with an account";
|
|
@@ -5036,6 +5084,8 @@ export class InteractiveMode {
|
|
|
5036
5084
|
if (availableAuthTypes.has("api_key")) {
|
|
5037
5085
|
options.push(apiKeyLabel);
|
|
5038
5086
|
}
|
|
5087
|
+
if (radiusLabel)
|
|
5088
|
+
options.push(radiusLabel);
|
|
5039
5089
|
if (options.length === 0) {
|
|
5040
5090
|
this.showStatus("No login methods available.");
|
|
5041
5091
|
return;
|
|
@@ -5051,29 +5101,37 @@ export class InteractiveMode {
|
|
|
5051
5101
|
? `Select authentication method for ${providerOptions[0].name}:`
|
|
5052
5102
|
: "Select authentication method:";
|
|
5053
5103
|
this.showSelector((done) => {
|
|
5054
|
-
const
|
|
5104
|
+
const onSelect = (option) => {
|
|
5055
5105
|
done();
|
|
5106
|
+
if (radiusOption && option === radiusLabel) {
|
|
5107
|
+
void this.startProviderLogin(radiusOption, () => this.showLoginAuthTypeSelector());
|
|
5108
|
+
return;
|
|
5109
|
+
}
|
|
5056
5110
|
const authType = option === subscriptionLabel ? "oauth" : "api_key";
|
|
5057
5111
|
if (providerOptions) {
|
|
5058
5112
|
const providerOption = providerOptions.find((provider) => provider.authType === authType);
|
|
5059
5113
|
if (providerOption) {
|
|
5060
|
-
void this.startProviderLogin(providerOption);
|
|
5114
|
+
void this.startProviderLogin(providerOption, () => this.showLoginAuthTypeSelector(providerOptions));
|
|
5061
5115
|
}
|
|
5062
5116
|
return;
|
|
5063
5117
|
}
|
|
5064
5118
|
this.showLoginProviderSelector(authType);
|
|
5065
|
-
}
|
|
5119
|
+
};
|
|
5120
|
+
const onCancel = () => {
|
|
5066
5121
|
done();
|
|
5067
5122
|
this.ui.requestRender();
|
|
5068
|
-
}
|
|
5069
|
-
|
|
5123
|
+
};
|
|
5124
|
+
const selector = radiusLabel && radiusText
|
|
5125
|
+
? createLoginMenuSelector(this.ui, title, options, { label: radiusLabel, text: radiusText }, onSelect, onCancel)
|
|
5126
|
+
: new ExtensionSelectorComponent(title, options, onSelect, onCancel);
|
|
5127
|
+
return { component: selector, focus: selector, dispose: () => selector.dispose() };
|
|
5070
5128
|
});
|
|
5071
5129
|
}
|
|
5072
5130
|
showLoginProviderSelector(authType, initialSearchInput) {
|
|
5073
5131
|
const providerOptions = this.getLoginProviderOptions(authType);
|
|
5074
5132
|
if (providerOptions.length === 0) {
|
|
5075
5133
|
const message = authType === "oauth"
|
|
5076
|
-
? "No
|
|
5134
|
+
? "No account providers available."
|
|
5077
5135
|
: authType === "api_key"
|
|
5078
5136
|
? "No API key providers available."
|
|
5079
5137
|
: "No login providers available.";
|
|
@@ -5087,7 +5145,7 @@ export class InteractiveMode {
|
|
|
5087
5145
|
if (!providerOption) {
|
|
5088
5146
|
return;
|
|
5089
5147
|
}
|
|
5090
|
-
await this.startProviderLogin(providerOption);
|
|
5148
|
+
await this.startProviderLogin(providerOption, () => this.showLoginProviderSelector(authType, initialSearchInput));
|
|
5091
5149
|
}, () => {
|
|
5092
5150
|
done();
|
|
5093
5151
|
if (authType) {
|
|
@@ -5241,21 +5299,24 @@ export class InteractiveMode {
|
|
|
5241
5299
|
})
|
|
5242
5300
|
.finally(() => clearTimeout(timeout));
|
|
5243
5301
|
}
|
|
5244
|
-
showAmbientAuthDialog(providerOption) {
|
|
5302
|
+
showAmbientAuthDialog(providerOption, onBack) {
|
|
5245
5303
|
const restoreEditor = () => {
|
|
5246
5304
|
this.editorContainer.clear();
|
|
5247
5305
|
this.editorContainer.addChild(this.editor);
|
|
5248
5306
|
this.ui.setFocus(this.editor);
|
|
5249
5307
|
this.ui.requestRender();
|
|
5250
5308
|
};
|
|
5251
|
-
const dialog = new LoginDialogComponent(this.ui, providerOption.id, () =>
|
|
5309
|
+
const dialog = new LoginDialogComponent(this.ui, providerOption.id, () => {
|
|
5310
|
+
restoreEditor();
|
|
5311
|
+
onBack?.();
|
|
5312
|
+
}, providerOption.name, `${providerOption.name} setup`);
|
|
5252
5313
|
dialog.showInfo(`${providerOption.method?.name ?? "Authentication"} is configured outside ${APP_NAME}.`, [], true);
|
|
5253
5314
|
this.editorContainer.clear();
|
|
5254
5315
|
this.editorContainer.addChild(dialog);
|
|
5255
5316
|
this.ui.setFocus(dialog);
|
|
5256
5317
|
this.ui.requestRender();
|
|
5257
5318
|
}
|
|
5258
|
-
async showApiKeyLoginDialog(providerId, providerName) {
|
|
5319
|
+
async showApiKeyLoginDialog(providerId, providerName, onBack) {
|
|
5259
5320
|
const previousModel = this.session.model;
|
|
5260
5321
|
const dialog = new LoginDialogComponent(this.ui, providerId, (_success, _message) => {
|
|
5261
5322
|
// Completion handled below
|
|
@@ -5288,12 +5349,15 @@ export class InteractiveMode {
|
|
|
5288
5349
|
if (error instanceof CredentialSynchronizationError) {
|
|
5289
5350
|
this.showError(`Saved API key for ${providerName}, but local model state could not be synchronized: ${errorMsg}`);
|
|
5290
5351
|
}
|
|
5291
|
-
else if (errorMsg
|
|
5352
|
+
else if (errorMsg === "Login cancelled") {
|
|
5353
|
+
onBack?.();
|
|
5354
|
+
}
|
|
5355
|
+
else {
|
|
5292
5356
|
this.showError(`Failed to save API key for ${providerName}: ${errorMsg}`);
|
|
5293
5357
|
}
|
|
5294
5358
|
}
|
|
5295
5359
|
}
|
|
5296
|
-
showAuthSelect(dialog, prompt) {
|
|
5360
|
+
showAuthSelect(dialog, prompt, providerId) {
|
|
5297
5361
|
return new Promise((resolve, reject) => {
|
|
5298
5362
|
const restoreDialog = () => {
|
|
5299
5363
|
this.editorContainer.clear();
|
|
@@ -5312,17 +5376,17 @@ export class InteractiveMode {
|
|
|
5312
5376
|
}, () => {
|
|
5313
5377
|
restoreDialog();
|
|
5314
5378
|
reject(new Error("Login cancelled"));
|
|
5315
|
-
});
|
|
5379
|
+
}, { description: providerId === RADIUS_PROVIDER_ID ? RADIUS_LOGIN_INTRO : undefined });
|
|
5316
5380
|
this.editorContainer.clear();
|
|
5317
5381
|
this.editorContainer.addChild(selector);
|
|
5318
5382
|
this.ui.setFocus(selector);
|
|
5319
5383
|
this.ui.requestRender();
|
|
5320
5384
|
});
|
|
5321
5385
|
}
|
|
5322
|
-
async showAuthPrompt(dialog, prompt) {
|
|
5386
|
+
async showAuthPrompt(dialog, prompt, providerId) {
|
|
5323
5387
|
let response;
|
|
5324
5388
|
if (prompt.type === "select") {
|
|
5325
|
-
response = this.showAuthSelect(dialog, prompt);
|
|
5389
|
+
response = this.showAuthSelect(dialog, prompt, providerId);
|
|
5326
5390
|
}
|
|
5327
5391
|
else if (prompt.type === "manual_code") {
|
|
5328
5392
|
response = dialog.showManualInput(prompt.message);
|
|
@@ -5366,11 +5430,11 @@ export class InteractiveMode {
|
|
|
5366
5430
|
async loginProvider(dialog, providerId, method) {
|
|
5367
5431
|
await this.session.modelRuntime.login(providerId, method, {
|
|
5368
5432
|
signal: dialog.signal,
|
|
5369
|
-
prompt: (prompt) => this.showAuthPrompt(dialog, prompt),
|
|
5433
|
+
prompt: (prompt) => this.showAuthPrompt(dialog, prompt, providerId),
|
|
5370
5434
|
notify: (event) => this.notifyAuthDialog(dialog, event),
|
|
5371
5435
|
}, { getDeviceId: () => this.settingsManager.getOrCreateDeviceId() });
|
|
5372
5436
|
}
|
|
5373
|
-
async showLoginDialog(providerId, providerName) {
|
|
5437
|
+
async showLoginDialog(providerId, providerName, onBack) {
|
|
5374
5438
|
const previousModel = this.session.model;
|
|
5375
5439
|
const dialog = new LoginDialogComponent(this.ui, providerId, (_success, _message) => { }, providerName);
|
|
5376
5440
|
this.editorContainer.clear();
|
|
@@ -5387,6 +5451,8 @@ export class InteractiveMode {
|
|
|
5387
5451
|
await this.loginProvider(dialog, providerId, "oauth");
|
|
5388
5452
|
restoreEditor();
|
|
5389
5453
|
await this.completeProviderAuthentication(providerId, providerName, "oauth", previousModel);
|
|
5454
|
+
if (providerId === RADIUS_PROVIDER_ID)
|
|
5455
|
+
this.offerRadiusMcpServer(providerId, providerName);
|
|
5390
5456
|
}
|
|
5391
5457
|
catch (error) {
|
|
5392
5458
|
restoreEditor();
|
|
@@ -5394,11 +5460,58 @@ export class InteractiveMode {
|
|
|
5394
5460
|
if (error instanceof CredentialSynchronizationError) {
|
|
5395
5461
|
this.showError(`Logged in to ${providerName}, but local model state could not be synchronized: ${errorMsg}`);
|
|
5396
5462
|
}
|
|
5397
|
-
else if (errorMsg
|
|
5463
|
+
else if (errorMsg === "Login cancelled") {
|
|
5464
|
+
onBack?.();
|
|
5465
|
+
}
|
|
5466
|
+
else {
|
|
5398
5467
|
this.showError(`Failed to login to ${providerName}: ${errorMsg}`);
|
|
5399
5468
|
}
|
|
5400
5469
|
}
|
|
5401
5470
|
}
|
|
5471
|
+
/**
|
|
5472
|
+
* Offer to point the Radius MCP server in the global mcp.json at the Radius login, adding the server
|
|
5473
|
+
* when missing. Nothing is asked when a global server already uses this login.
|
|
5474
|
+
*/
|
|
5475
|
+
offerRadiusMcpServer(providerId, providerName) {
|
|
5476
|
+
const mcpPath = path.join(getAgentDir(), "mcp.json");
|
|
5477
|
+
const normalizeUrl = (url) => url.replace(/\/+$/u, "");
|
|
5478
|
+
const { servers } = loadMcpConfig({
|
|
5479
|
+
agentDir: getAgentDir(),
|
|
5480
|
+
cwd: this.sessionManager.getCwd(),
|
|
5481
|
+
projectTrusted: false,
|
|
5482
|
+
});
|
|
5483
|
+
const existing = servers.find((server) => "url" in server.config && normalizeUrl(server.config.url) === normalizeUrl(RADIUS_MCP_URL));
|
|
5484
|
+
if (existing && "url" in existing.config && existing.config.auth?.provider === providerId)
|
|
5485
|
+
return;
|
|
5486
|
+
let name = existing?.name ?? "radius";
|
|
5487
|
+
if (!existing && servers.some((server) => server.name === name))
|
|
5488
|
+
name = "radius-mcp";
|
|
5489
|
+
const config = existing && "url" in existing.config
|
|
5490
|
+
? { ...existing.config, auth: { provider: providerId } }
|
|
5491
|
+
: { url: RADIUS_MCP_URL, auth: { provider: providerId } };
|
|
5492
|
+
// `auth` replaces the MCP OAuth sign-in.
|
|
5493
|
+
delete config.oauth;
|
|
5494
|
+
this.showSelector((done) => {
|
|
5495
|
+
const selector = new ExtensionSelectorComponent(`Configure ${providerName} MCP in ${mcpPath}?`, ["Yes", "No"], (option) => {
|
|
5496
|
+
done();
|
|
5497
|
+
if (option !== "Yes")
|
|
5498
|
+
return;
|
|
5499
|
+
try {
|
|
5500
|
+
addMcpServerConfig(mcpPath, name, config);
|
|
5501
|
+
}
|
|
5502
|
+
catch (error) {
|
|
5503
|
+
this.showError(`Could not update ${mcpPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
5504
|
+
return;
|
|
5505
|
+
}
|
|
5506
|
+
// The MCP extension reads mcp.json when the session starts.
|
|
5507
|
+
void this.handleReloadCommand();
|
|
5508
|
+
}, () => {
|
|
5509
|
+
done();
|
|
5510
|
+
this.ui.requestRender();
|
|
5511
|
+
});
|
|
5512
|
+
return { component: selector, focus: selector };
|
|
5513
|
+
});
|
|
5514
|
+
}
|
|
5402
5515
|
// =========================================================================
|
|
5403
5516
|
// Command handlers
|
|
5404
5517
|
// =========================================================================
|