@dexto/tui 1.8.0 → 1.8.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/dist/components/Footer.cjs +3 -2
- package/dist/components/Footer.d.ts.map +1 -1
- package/dist/components/Footer.js +2 -5
- package/dist/components/overlays/ApiKeyInput.d.ts +1 -1
- package/dist/components/overlays/ApiKeyInput.d.ts.map +1 -1
- package/dist/components/overlays/ConnectOverlay.cjs +423 -0
- package/dist/components/overlays/ConnectOverlay.d.ts +21 -0
- package/dist/components/overlays/ConnectOverlay.d.ts.map +1 -0
- package/dist/components/overlays/ConnectOverlay.js +412 -0
- package/dist/components/overlays/CustomModelWizard.d.ts.map +1 -1
- package/dist/components/overlays/ModelSelectorRefactored.cjs +4 -3
- package/dist/components/overlays/ModelSelectorRefactored.d.ts +1 -1
- package/dist/components/overlays/ModelSelectorRefactored.d.ts.map +1 -1
- package/dist/components/overlays/ModelSelectorRefactored.js +1 -2
- package/dist/components/overlays/ReasoningOverlay.cjs +3 -3
- package/dist/components/overlays/ReasoningOverlay.js +1 -1
- package/dist/components/overlays/custom-model-wizard/provider-config.cjs +4 -3
- package/dist/components/overlays/custom-model-wizard/provider-config.d.ts.map +1 -1
- package/dist/components/overlays/custom-model-wizard/provider-config.js +2 -4
- package/dist/containers/InputContainer.cjs +2 -2
- package/dist/containers/InputContainer.js +1 -1
- package/dist/containers/OverlayContainer.cjs +64 -5
- package/dist/containers/OverlayContainer.d.ts.map +1 -1
- package/dist/containers/OverlayContainer.js +60 -7
- package/dist/hooks/useAgentEvents.cjs +2 -1
- package/dist/hooks/useAgentEvents.d.ts.map +1 -1
- package/dist/hooks/useAgentEvents.js +2 -4
- package/dist/hooks/useCLIState.cjs +2 -1
- package/dist/hooks/useCLIState.d.ts.map +1 -1
- package/dist/hooks/useCLIState.js +2 -1
- package/dist/host/index.d.ts +1 -1
- package/dist/host/index.d.ts.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/interactive-commands/auth/index.cjs +9 -0
- package/dist/interactive-commands/auth/index.d.ts +1 -0
- package/dist/interactive-commands/auth/index.d.ts.map +1 -1
- package/dist/interactive-commands/auth/index.js +8 -0
- package/dist/interactive-commands/commands.cjs +3 -1
- package/dist/interactive-commands/commands.d.ts.map +1 -1
- package/dist/interactive-commands/commands.js +4 -2
- package/dist/state/types.d.ts +3 -2
- package/dist/state/types.d.ts.map +1 -1
- package/dist/utils/chatgpt-rate-limit.cjs +4 -4
- package/dist/utils/chatgpt-rate-limit.d.ts.map +1 -1
- package/dist/utils/chatgpt-rate-limit.js +1 -1
- package/dist/utils/commandOverlays.cjs +1 -0
- package/dist/utils/commandOverlays.d.ts.map +1 -1
- package/dist/utils/commandOverlays.js +1 -0
- package/dist/utils/llm-provider-display.d.ts +1 -1
- package/dist/utils/llm-provider-display.d.ts.map +1 -1
- package/package.json +5 -4
|
@@ -35,6 +35,7 @@ var import_jsx_runtime = require("react/jsx-runtime");
|
|
|
35
35
|
var import_react = require("react");
|
|
36
36
|
var import_node_path = __toESM(require("node:path"), 1);
|
|
37
37
|
var import_ink = require("ink");
|
|
38
|
+
var import_llm = require("@dexto/llm");
|
|
38
39
|
var import_core = require("@dexto/core");
|
|
39
40
|
var import_llm_provider_display = require("../utils/llm-provider-display.js");
|
|
40
41
|
var import_chatgpt_rate_limit = require("../utils/chatgpt-rate-limit.js");
|
|
@@ -52,13 +53,13 @@ function Footer({
|
|
|
52
53
|
chatgptRateLimitStatus
|
|
53
54
|
}) {
|
|
54
55
|
const displayPath = cwd ? import_node_path.default.basename(cwd) || cwd : "";
|
|
55
|
-
const displayModelName = (0,
|
|
56
|
+
const displayModelName = (0, import_llm.getModelDisplayName)(modelName);
|
|
56
57
|
const [contextLeft, setContextLeft] = (0, import_react.useState)(null);
|
|
57
58
|
const [, setLlmTick] = (0, import_react.useState)(0);
|
|
58
59
|
const llmConfig = sessionId ? agent.getCurrentLLMConfig(sessionId) : null;
|
|
59
60
|
const provider = llmConfig?.provider ?? null;
|
|
60
61
|
const providerLabel = provider ? (0, import_llm_provider_display.getLLMProviderDisplayName)(provider, llmConfig?.baseURL) : null;
|
|
61
|
-
const reasoningProfile = provider && llmConfig ? (0,
|
|
62
|
+
const reasoningProfile = provider && llmConfig ? (0, import_llm.getReasoningProfile)(provider, llmConfig.model) : null;
|
|
62
63
|
const reasoningVariant = llmConfig?.reasoning?.variant ?? reasoningProfile?.defaultVariant ?? void 0;
|
|
63
64
|
const showReasoningVariant = reasoningProfile?.capable === true && typeof reasoningVariant === "string";
|
|
64
65
|
const isChatGPTLogin = provider === "openai-compatible" && (0, import_core.parseCodexBaseURL)(llmConfig?.baseURL)?.authMode === "chatgpt";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Footer.d.ts","sourceRoot":"","sources":["../../src/components/Footer.tsx"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"Footer.d.ts","sourceRoot":"","sources":["../../src/components/Footer.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EAAqB,KAAK,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAM7E,OAAO,EAAwB,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEjF,UAAU,WAAW;IACjB,KAAK,EAAE,eAAe,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,kEAAkE;IAClE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,sBAAsB,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAC;CAC1D;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,EACnB,KAAK,EACL,SAAS,EACT,SAAS,EACT,GAAG,EACH,UAAU,EACV,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,WAAW,EACX,sBAAsB,GACzB,EAAE,WAAW,2CA8Kb"}
|
|
@@ -2,11 +2,8 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useEffect, useState } from "react";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { Box, Text } from "ink";
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
getReasoningProfile,
|
|
8
|
-
parseCodexBaseURL
|
|
9
|
-
} from "@dexto/core";
|
|
5
|
+
import { getModelDisplayName, getReasoningProfile } from "@dexto/llm";
|
|
6
|
+
import { parseCodexBaseURL } from "@dexto/core";
|
|
10
7
|
import { getLLMProviderDisplayName } from "../utils/llm-provider-display.js";
|
|
11
8
|
import {
|
|
12
9
|
getChatGPTRateLimitHint,
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import React from 'react';
|
|
6
6
|
import type { Key } from '../../hooks/useInputOrchestrator.js';
|
|
7
|
-
import type { LLMProvider } from '@dexto/
|
|
7
|
+
import type { LLMProvider } from '@dexto/llm';
|
|
8
8
|
export interface ApiKeyInputProps {
|
|
9
9
|
isVisible: boolean;
|
|
10
10
|
provider: LLMProvider;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApiKeyInput.d.ts","sourceRoot":"","sources":["../../../src/components/overlays/ApiKeyInput.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAA4E,MAAM,OAAO,CAAC;AAEjG,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,qCAAqC,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"ApiKeyInput.d.ts","sourceRoot":"","sources":["../../../src/components/overlays/ApiKeyInput.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAA4E,MAAM,OAAO,CAAC;AAEjG,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,qCAAqC,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAS9C,MAAM,WAAW,gBAAgB;IAC7B,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,WAAW,CAAC;IACtB,OAAO,EAAE,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,WAAW,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACnE,OAAO,EAAE,MAAM,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAC9B,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC;CACrD;AAED;;;GAGG;AACH,QAAA,MAAM,WAAW,4FA+Jf,CAAC;AAEH,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var ConnectOverlay_exports = {};
|
|
30
|
+
__export(ConnectOverlay_exports, {
|
|
31
|
+
default: () => ConnectOverlay_default
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(ConnectOverlay_exports);
|
|
34
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
35
|
+
var import_react = require("react");
|
|
36
|
+
var import_ink = require("ink");
|
|
37
|
+
var import_open = __toESM(require("open"), 1);
|
|
38
|
+
var import_BaseSelector = require("../base/BaseSelector.js");
|
|
39
|
+
var import_agent_management = require("@dexto/agent-management");
|
|
40
|
+
var import_llm = require("@dexto/llm");
|
|
41
|
+
var import_host = require("../../host/index.js");
|
|
42
|
+
function methodHint(method, profile, defaultProfileId) {
|
|
43
|
+
const parts = [
|
|
44
|
+
profile ? profile.id === defaultProfileId ? "Connected (default)" : "Connected" : void 0,
|
|
45
|
+
method.hint
|
|
46
|
+
].filter((part) => Boolean(part));
|
|
47
|
+
return parts.length ? parts.join(" - ") : void 0;
|
|
48
|
+
}
|
|
49
|
+
function maskSecret(secret) {
|
|
50
|
+
if (secret.length <= 8) {
|
|
51
|
+
return "*".repeat(secret.length);
|
|
52
|
+
}
|
|
53
|
+
return `${secret.slice(0, 4)}${"*".repeat(Math.min(secret.length - 8, 24))}${secret.slice(-4)}`;
|
|
54
|
+
}
|
|
55
|
+
function toLlmProvider(providerId) {
|
|
56
|
+
const provider = import_llm.LLM_PROVIDERS.find((candidate) => candidate === providerId);
|
|
57
|
+
if (!provider) {
|
|
58
|
+
throw new Error(`API-key auth is not implemented for provider: ${providerId}`);
|
|
59
|
+
}
|
|
60
|
+
return provider;
|
|
61
|
+
}
|
|
62
|
+
const ConnectOverlay = (0, import_react.forwardRef)(
|
|
63
|
+
function ConnectOverlay2({ isVisible, onDone }, ref) {
|
|
64
|
+
const selectorRef = (0, import_react.useRef)(null);
|
|
65
|
+
const loginCancelRef = (0, import_react.useRef)(null);
|
|
66
|
+
const [step, setStep] = (0, import_react.useState)("provider");
|
|
67
|
+
const [selectedIndex, setSelectedIndex] = (0, import_react.useState)(0);
|
|
68
|
+
const [provider, setProvider] = (0, import_react.useState)(null);
|
|
69
|
+
const [method, setMethod] = (0, import_react.useState)(null);
|
|
70
|
+
const [profiles, setProfiles] = (0, import_react.useState)([]);
|
|
71
|
+
const [defaultProfileId, setDefaultProfileId] = (0, import_react.useState)(null);
|
|
72
|
+
const [apiKey, setApiKey] = (0, import_react.useState)("");
|
|
73
|
+
const [status, setStatus] = (0, import_react.useState)("Choose a provider to connect.");
|
|
74
|
+
const [error, setError] = (0, import_react.useState)(null);
|
|
75
|
+
const currentProfileId = provider && method ? (0, import_agent_management.getModelAuthProfileId)(provider.providerId, method.id) : null;
|
|
76
|
+
const existingProfile = currentProfileId ? profiles.find((profile) => profile.id === currentProfileId) ?? null : null;
|
|
77
|
+
const close = (0, import_react.useCallback)(
|
|
78
|
+
(outcome) => {
|
|
79
|
+
void loginCancelRef.current?.();
|
|
80
|
+
loginCancelRef.current = null;
|
|
81
|
+
onDone(outcome);
|
|
82
|
+
},
|
|
83
|
+
[onDone]
|
|
84
|
+
);
|
|
85
|
+
const handleActionError = (0, import_react.useCallback)((err) => {
|
|
86
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
87
|
+
setStep("error");
|
|
88
|
+
}, []);
|
|
89
|
+
(0, import_react.useEffect)(() => {
|
|
90
|
+
if (!isVisible) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
setStep("provider");
|
|
94
|
+
setSelectedIndex(0);
|
|
95
|
+
setProvider(null);
|
|
96
|
+
setMethod(null);
|
|
97
|
+
setProfiles([]);
|
|
98
|
+
setDefaultProfileId(null);
|
|
99
|
+
setApiKey("");
|
|
100
|
+
setStatus("Choose a provider to connect.");
|
|
101
|
+
setError(null);
|
|
102
|
+
}, [isVisible]);
|
|
103
|
+
const providerOptions = (0, import_react.useMemo)(
|
|
104
|
+
() => (0, import_agent_management.getProviderAuthDefinitions)().map((item) => ({
|
|
105
|
+
value: item.providerId,
|
|
106
|
+
label: item.label,
|
|
107
|
+
hint: `${item.methods.length} method${item.methods.length === 1 ? "" : "s"}`
|
|
108
|
+
})),
|
|
109
|
+
[]
|
|
110
|
+
);
|
|
111
|
+
const methodOptions = (0, import_react.useMemo)(() => {
|
|
112
|
+
if (!provider) {
|
|
113
|
+
return [];
|
|
114
|
+
}
|
|
115
|
+
return provider.methods.map((item) => {
|
|
116
|
+
const profile = profiles.find(
|
|
117
|
+
(candidate) => candidate.id === (0, import_agent_management.getModelAuthProfileId)(provider.providerId, item.id)
|
|
118
|
+
);
|
|
119
|
+
return {
|
|
120
|
+
value: item.id,
|
|
121
|
+
label: item.label,
|
|
122
|
+
hint: methodHint(item, profile, defaultProfileId)
|
|
123
|
+
};
|
|
124
|
+
});
|
|
125
|
+
}, [defaultProfileId, profiles, provider]);
|
|
126
|
+
const existingActionOptions = (0, import_react.useMemo)(() => {
|
|
127
|
+
if (!existingProfile) {
|
|
128
|
+
return [];
|
|
129
|
+
}
|
|
130
|
+
return [
|
|
131
|
+
{
|
|
132
|
+
value: "use",
|
|
133
|
+
label: existingProfile.id === defaultProfileId ? "Keep as default" : "Use existing",
|
|
134
|
+
hint: existingProfile.id === defaultProfileId ? "No changes" : "Set this method as provider default"
|
|
135
|
+
},
|
|
136
|
+
{ value: "replace", label: "Replace credentials", hint: "Reconnect this method" },
|
|
137
|
+
{
|
|
138
|
+
value: "delete",
|
|
139
|
+
label: "Delete credentials",
|
|
140
|
+
...existingProfile.id === defaultProfileId ? { hint: "Also clears default" } : {}
|
|
141
|
+
}
|
|
142
|
+
];
|
|
143
|
+
}, [defaultProfileId, existingProfile]);
|
|
144
|
+
const activeItems = step === "provider" ? providerOptions : step === "method" ? methodOptions : step === "existing-action" ? existingActionOptions : [];
|
|
145
|
+
const loadProvider = (0, import_react.useCallback)(async (nextProvider) => {
|
|
146
|
+
setProvider(nextProvider);
|
|
147
|
+
setMethod(null);
|
|
148
|
+
setStatus(`Loading saved ${nextProvider.label} profiles...`);
|
|
149
|
+
const [savedProfiles, savedDefaultProfileId] = await Promise.all([
|
|
150
|
+
(0, import_agent_management.listSavedModelAuthProfiles)(nextProvider.providerId),
|
|
151
|
+
(0, import_agent_management.getDefaultModelAuthProfileIdForProvider)(nextProvider.providerId)
|
|
152
|
+
]);
|
|
153
|
+
setProfiles(savedProfiles);
|
|
154
|
+
setDefaultProfileId(savedDefaultProfileId);
|
|
155
|
+
setSelectedIndex(0);
|
|
156
|
+
setStatus(`Choose how to connect ${nextProvider.label}.`);
|
|
157
|
+
setStep("method");
|
|
158
|
+
}, []);
|
|
159
|
+
const saveApiKey = (0, import_react.useCallback)(async () => {
|
|
160
|
+
if (!provider || !method) {
|
|
161
|
+
close({ outcome: "cancelled" });
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const trimmed = apiKey.trim();
|
|
165
|
+
if (!trimmed) {
|
|
166
|
+
setError("API key is required");
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
const llmProvider = toLlmProvider(provider.providerId);
|
|
170
|
+
if (!(0, import_host.isValidApiKeyFormat)(trimmed, llmProvider)) {
|
|
171
|
+
setError(`${provider.label} API key format is invalid`);
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
setError(null);
|
|
175
|
+
try {
|
|
176
|
+
setStatus(`Saving ${provider.label} API key...`);
|
|
177
|
+
await (0, import_agent_management.saveProviderApiKey)(llmProvider, trimmed, process.cwd());
|
|
178
|
+
await (0, import_host.applyLayeredEnvironmentLoading)();
|
|
179
|
+
await (0, import_agent_management.saveApiKeyModelAuthProfile)(llmProvider);
|
|
180
|
+
await (0, import_agent_management.markModelAuthProviderConnected)(provider.providerId);
|
|
181
|
+
close({
|
|
182
|
+
outcome: "success",
|
|
183
|
+
providerId: provider.providerId,
|
|
184
|
+
message: `Connected ${provider.label} (${method.label})`
|
|
185
|
+
});
|
|
186
|
+
} catch (err) {
|
|
187
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
188
|
+
}
|
|
189
|
+
}, [apiKey, close, method, provider]);
|
|
190
|
+
const connectOAuth = (0, import_react.useCallback)(
|
|
191
|
+
async (nextProvider, nextMethod) => {
|
|
192
|
+
setStep("oauth-progress");
|
|
193
|
+
setStatus(`Starting ${nextMethod.label}...`);
|
|
194
|
+
let timeout = null;
|
|
195
|
+
try {
|
|
196
|
+
const login = await (0, import_agent_management.startModelAuthBrowserLogin)({
|
|
197
|
+
providerId: nextProvider.providerId,
|
|
198
|
+
methodId: nextMethod.id
|
|
199
|
+
});
|
|
200
|
+
loginCancelRef.current = login.cancel;
|
|
201
|
+
setStatus(`Opening browser for ${nextMethod.label}...`);
|
|
202
|
+
await (0, import_open.default)(login.authUrl).catch(() => void 0);
|
|
203
|
+
setStatus("Waiting for browser authorization...");
|
|
204
|
+
await Promise.race([
|
|
205
|
+
login.waitForProfile(),
|
|
206
|
+
new Promise((_, reject) => {
|
|
207
|
+
timeout = setTimeout(
|
|
208
|
+
() => reject(new Error(`${nextMethod.label} timed out`)),
|
|
209
|
+
5 * 60 * 1e3
|
|
210
|
+
);
|
|
211
|
+
})
|
|
212
|
+
]);
|
|
213
|
+
await (0, import_agent_management.markModelAuthProviderConnected)(nextProvider.providerId);
|
|
214
|
+
close({
|
|
215
|
+
outcome: "success",
|
|
216
|
+
providerId: nextProvider.providerId,
|
|
217
|
+
message: `Connected ${nextProvider.label} (${nextMethod.label})`
|
|
218
|
+
});
|
|
219
|
+
} catch (err) {
|
|
220
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
221
|
+
setStep("error");
|
|
222
|
+
} finally {
|
|
223
|
+
if (timeout) {
|
|
224
|
+
clearTimeout(timeout);
|
|
225
|
+
}
|
|
226
|
+
await loginCancelRef.current?.();
|
|
227
|
+
loginCancelRef.current = null;
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
[close]
|
|
231
|
+
);
|
|
232
|
+
const startConnect = (0, import_react.useCallback)(async () => {
|
|
233
|
+
if (!provider || !method) {
|
|
234
|
+
close({ outcome: "cancelled" });
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
if (method.kind === "api_key") {
|
|
238
|
+
setApiKey("");
|
|
239
|
+
setError(null);
|
|
240
|
+
setStatus(`Enter your ${provider.label} API key.`);
|
|
241
|
+
setStep("api-key");
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
if (method.kind === "oauth") {
|
|
245
|
+
await connectOAuth(provider, method);
|
|
246
|
+
}
|
|
247
|
+
}, [close, connectOAuth, method, provider]);
|
|
248
|
+
const handleSelect = (0, import_react.useCallback)(
|
|
249
|
+
async (option) => {
|
|
250
|
+
if (step === "provider") {
|
|
251
|
+
const nextProvider = (0, import_agent_management.getProviderAuthDefinitions)().find(
|
|
252
|
+
(candidate) => candidate.providerId === option.value
|
|
253
|
+
);
|
|
254
|
+
if (nextProvider) {
|
|
255
|
+
await loadProvider(nextProvider);
|
|
256
|
+
}
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
if (step === "method" && provider) {
|
|
260
|
+
const nextMethod = provider.methods.find(
|
|
261
|
+
(candidate) => candidate.id === option.value
|
|
262
|
+
);
|
|
263
|
+
if (nextMethod) {
|
|
264
|
+
setMethod(nextMethod);
|
|
265
|
+
const profileId = (0, import_agent_management.getModelAuthProfileId)(provider.providerId, nextMethod.id);
|
|
266
|
+
if (profiles.some((item) => item.id === profileId)) {
|
|
267
|
+
setStatus(`Manage ${provider.label} ${nextMethod.label}.`);
|
|
268
|
+
setStep("existing-action");
|
|
269
|
+
setSelectedIndex(0);
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
if (nextMethod.kind === "api_key") {
|
|
273
|
+
setApiKey("");
|
|
274
|
+
setError(null);
|
|
275
|
+
setStatus(`Enter your ${provider.label} API key.`);
|
|
276
|
+
setStep("api-key");
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
if (nextMethod.kind === "oauth") {
|
|
280
|
+
await connectOAuth(provider, nextMethod);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
if (step === "existing-action" && provider && method && currentProfileId) {
|
|
286
|
+
if (option.value === "use") {
|
|
287
|
+
await (0, import_agent_management.setDefaultModelAuthProfile)({
|
|
288
|
+
providerId: provider.providerId,
|
|
289
|
+
profileId: currentProfileId
|
|
290
|
+
});
|
|
291
|
+
close({
|
|
292
|
+
outcome: "success",
|
|
293
|
+
providerId: provider.providerId,
|
|
294
|
+
message: `Using ${provider.label} ${method.label}`
|
|
295
|
+
});
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
if (option.value === "replace") {
|
|
299
|
+
await startConnect();
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
if (option.value === "delete") {
|
|
303
|
+
setStatus(`Press Enter to delete ${provider.label} ${method.label}.`);
|
|
304
|
+
setStep("delete-confirm");
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
},
|
|
308
|
+
[
|
|
309
|
+
close,
|
|
310
|
+
connectOAuth,
|
|
311
|
+
currentProfileId,
|
|
312
|
+
loadProvider,
|
|
313
|
+
method,
|
|
314
|
+
profiles,
|
|
315
|
+
provider,
|
|
316
|
+
startConnect,
|
|
317
|
+
step
|
|
318
|
+
]
|
|
319
|
+
);
|
|
320
|
+
(0, import_react.useImperativeHandle)(
|
|
321
|
+
ref,
|
|
322
|
+
() => ({
|
|
323
|
+
handleInput: (input, key) => {
|
|
324
|
+
if (!isVisible) return false;
|
|
325
|
+
if (step === "api-key") {
|
|
326
|
+
if (key.escape) {
|
|
327
|
+
close({ outcome: "cancelled" });
|
|
328
|
+
return true;
|
|
329
|
+
}
|
|
330
|
+
if (key.return) {
|
|
331
|
+
void saveApiKey().catch(handleActionError);
|
|
332
|
+
return true;
|
|
333
|
+
}
|
|
334
|
+
if (key.backspace || key.delete) {
|
|
335
|
+
setApiKey((prev) => prev.slice(0, -1));
|
|
336
|
+
setError(null);
|
|
337
|
+
return true;
|
|
338
|
+
}
|
|
339
|
+
if (input && !key.ctrl && !key.meta) {
|
|
340
|
+
setApiKey((prev) => prev + input);
|
|
341
|
+
setError(null);
|
|
342
|
+
return true;
|
|
343
|
+
}
|
|
344
|
+
return true;
|
|
345
|
+
}
|
|
346
|
+
if (step === "delete-confirm") {
|
|
347
|
+
if (key.escape) {
|
|
348
|
+
close({ outcome: "cancelled" });
|
|
349
|
+
return true;
|
|
350
|
+
}
|
|
351
|
+
if (key.return && provider && method && currentProfileId) {
|
|
352
|
+
void (0, import_agent_management.deleteModelAuthProfile)(currentProfileId).then(
|
|
353
|
+
() => close({
|
|
354
|
+
outcome: "success",
|
|
355
|
+
providerId: provider.providerId,
|
|
356
|
+
message: `Deleted ${provider.label} ${method.label}`
|
|
357
|
+
})
|
|
358
|
+
).catch(handleActionError);
|
|
359
|
+
return true;
|
|
360
|
+
}
|
|
361
|
+
return true;
|
|
362
|
+
}
|
|
363
|
+
if (step === "oauth-progress") {
|
|
364
|
+
if (key.escape) {
|
|
365
|
+
close({ outcome: "cancelled" });
|
|
366
|
+
}
|
|
367
|
+
return true;
|
|
368
|
+
}
|
|
369
|
+
if (step === "error") {
|
|
370
|
+
if (key.escape || key.return) {
|
|
371
|
+
close({ outcome: "closed" });
|
|
372
|
+
}
|
|
373
|
+
return true;
|
|
374
|
+
}
|
|
375
|
+
return selectorRef.current?.handleInput(input, key) ?? false;
|
|
376
|
+
}
|
|
377
|
+
}),
|
|
378
|
+
[
|
|
379
|
+
close,
|
|
380
|
+
currentProfileId,
|
|
381
|
+
handleActionError,
|
|
382
|
+
isVisible,
|
|
383
|
+
method,
|
|
384
|
+
provider,
|
|
385
|
+
saveApiKey,
|
|
386
|
+
step
|
|
387
|
+
]
|
|
388
|
+
);
|
|
389
|
+
if (!isVisible) return null;
|
|
390
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
|
|
391
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Box, { marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { bold: true, color: "cyan", children: "Connect Model Provider" }) }),
|
|
392
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { color: error ? "red" : "gray", children: error ?? status }),
|
|
393
|
+
step === "api-key" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Box, { flexDirection: "column", marginTop: 1, children: [
|
|
394
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { children: maskSecret(apiKey) }),
|
|
395
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { color: "gray", children: "Enter save \u2022 Esc cancel" })
|
|
396
|
+
] }) : step === "delete-confirm" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Box, { flexDirection: "column", marginTop: 1, children: [
|
|
397
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { color: "red", children: "This removes saved credentials for this method." }),
|
|
398
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { color: "gray", children: "Enter delete \u2022 Esc cancel" })
|
|
399
|
+
] }) : step === "oauth-progress" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Box, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { color: "gray", children: "Esc cancel" }) }) : step === "error" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Box, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { color: "gray", children: "Enter close \u2022 Esc close" }) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Box, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
400
|
+
import_BaseSelector.BaseSelector,
|
|
401
|
+
{
|
|
402
|
+
ref: selectorRef,
|
|
403
|
+
items: activeItems,
|
|
404
|
+
isVisible: true,
|
|
405
|
+
selectedIndex,
|
|
406
|
+
onSelectIndex: setSelectedIndex,
|
|
407
|
+
onSelect: (item) => void handleSelect(item).catch(handleActionError),
|
|
408
|
+
onClose: () => close({ outcome: "cancelled" }),
|
|
409
|
+
title: step === "provider" ? "Providers" : step === "method" ? `${provider?.label ?? "Provider"} methods` : "Existing profile",
|
|
410
|
+
formatItem: (item, selected) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Text, { ...selected ? { color: "cyan" } : {}, children: [
|
|
411
|
+
selected ? "\u203A " : " ",
|
|
412
|
+
item.label,
|
|
413
|
+
item.hint ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Text, { color: "gray", children: [
|
|
414
|
+
" \u2014 ",
|
|
415
|
+
item.hint
|
|
416
|
+
] }) : null
|
|
417
|
+
] })
|
|
418
|
+
}
|
|
419
|
+
) })
|
|
420
|
+
] });
|
|
421
|
+
}
|
|
422
|
+
);
|
|
423
|
+
var ConnectOverlay_default = ConnectOverlay;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Key } from '../../hooks/useInputOrchestrator.js';
|
|
3
|
+
export type ConnectOverlayOutcome = {
|
|
4
|
+
outcome: 'success';
|
|
5
|
+
providerId: string;
|
|
6
|
+
message: string;
|
|
7
|
+
} | {
|
|
8
|
+
outcome: 'cancelled';
|
|
9
|
+
} | {
|
|
10
|
+
outcome: 'closed';
|
|
11
|
+
};
|
|
12
|
+
export interface ConnectOverlayProps {
|
|
13
|
+
isVisible: boolean;
|
|
14
|
+
onDone: (outcome: ConnectOverlayOutcome) => void;
|
|
15
|
+
}
|
|
16
|
+
export interface ConnectOverlayHandle {
|
|
17
|
+
handleInput: (input: string, key: Key) => boolean;
|
|
18
|
+
}
|
|
19
|
+
declare const ConnectOverlay: React.ForwardRefExoticComponent<ConnectOverlayProps & React.RefAttributes<ConnectOverlayHandle>>;
|
|
20
|
+
export default ConnectOverlay;
|
|
21
|
+
//# sourceMappingURL=ConnectOverlay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConnectOverlay.d.ts","sourceRoot":"","sources":["../../../src/components/overlays/ConnectOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAQN,MAAM,OAAO,CAAC;AAGf,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,qCAAqC,CAAC;AAmC/D,MAAM,MAAM,qBAAqB,GAC3B;IAAE,OAAO,EAAE,SAAS,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,OAAO,EAAE,WAAW,CAAA;CAAE,GACxB;IAAE,OAAO,EAAE,QAAQ,CAAA;CAAE,CAAC;AAE5B,MAAM,WAAW,mBAAmB;IAChC,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAC;CACpD;AAED,MAAM,WAAW,oBAAoB;IACjC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC;CACrD;AAiCD,QAAA,MAAM,cAAc,kGAsbnB,CAAC;AAEF,eAAe,cAAc,CAAC"}
|