@jini-ai/ui 0.4.7 → 0.4.9
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 +2 -0
- package/dist/features/admin-widgets/components/InfoTip.d.ts +23 -2
- package/dist/features/admin-widgets/components/InfoTip.hooks.d.ts +22 -2
- package/dist/features/admin-widgets/components/InfoTip.hooks.js +75 -28
- package/dist/features/admin-widgets/components/InfoTip.js +12 -4
- package/dist/features/admin-widgets/components/InfoTip.rules.d.ts +72 -0
- package/dist/features/admin-widgets/components/InfoTip.rules.js +68 -0
- package/dist/features/admin-widgets/components/SuggestInput/SuggestInput.d.ts +36 -0
- package/dist/features/admin-widgets/components/SuggestInput/SuggestInput.hooks.d.ts +58 -0
- package/dist/features/admin-widgets/components/SuggestInput/SuggestInput.hooks.js +66 -0
- package/dist/features/admin-widgets/components/SuggestInput/SuggestInput.js +24 -0
- package/dist/features/admin-widgets/components/useDebouncedHtmlPreview.hooks.d.ts +23 -0
- package/dist/features/admin-widgets/components/useDebouncedHtmlPreview.hooks.js +28 -0
- package/dist/features/admin-widgets/index.d.ts +9 -0
- package/dist/features/admin-widgets/index.js +5 -0
- package/dist/features/execution/constants.js +11 -10
- package/dist/features/execution/http-adapter.d.ts +3 -1
- package/dist/features/execution/http-adapter.js +9 -4
- package/dist/features/execution/index.d.ts +1 -1
- package/dist/features/execution/index.js +1 -1
- package/dist/features/execution/react/components/ByokProviderForm.d.ts +18 -1
- package/dist/features/execution/react/components/ByokProviderForm.js +14 -16
- package/dist/features/execution/react/components/LocalCliAgentCard.d.ts +5 -1
- package/dist/features/execution/react/components/LocalCliAgentCard.js +12 -87
- package/dist/features/execution/react/components/LocalCliAgentList.d.ts +4 -1
- package/dist/features/execution/react/components/LocalCliAgentList.js +13 -4
- package/dist/features/execution/react/components/LocalCliAgentSettings.d.ts +20 -0
- package/dist/features/execution/react/components/LocalCliAgentSettings.js +20 -0
- package/dist/features/execution/react/hooks/use-byok-field-validation.hooks.d.ts +24 -0
- package/dist/features/execution/react/hooks/use-byok-field-validation.hooks.js +27 -0
- package/dist/features/execution/react/hooks/useExecutionTab.js +10 -1
- package/dist/features/execution/react/hooks/useLocalCliAgentCard.d.ts +48 -0
- package/dist/features/execution/react/hooks/useLocalCliAgentCard.js +110 -0
- package/dist/features/execution/react/hooks/useLocalCliAgentList.d.ts +19 -0
- package/dist/features/execution/react/hooks/useLocalCliAgentList.js +13 -0
- package/dist/features/execution/rules.d.ts +13 -0
- package/dist/features/execution/rules.js +14 -0
- package/dist/features/execution/types.d.ts +2 -0
- package/dist/features/html-editor/canvas-embed-placeholders.d.ts +13 -1
- package/dist/features/html-editor/canvas-embed-placeholders.js +61 -12
- package/dist/features/html-editor/dom.d.ts +5 -0
- package/dist/features/html-editor/dom.js +10 -0
- package/dist/features/html-editor/editor-blocks.d.ts +71 -0
- package/dist/features/html-editor/editor-blocks.js +185 -0
- package/dist/features/html-editor/editor-serialization.d.ts +24 -0
- package/dist/features/html-editor/editor-serialization.js +110 -0
- package/dist/features/html-editor/index.d.ts +5 -0
- package/dist/features/html-editor/index.js +3 -0
- package/dist/features/html-editor/protected-elements.d.ts +64 -0
- package/dist/features/html-editor/protected-elements.js +189 -0
- package/dist/features/html-editor/react/components/InteractiveHtmlEditor.d.ts +6 -4
- package/dist/features/html-editor/react/components/InteractiveHtmlEditor.js +3 -3
- package/dist/features/html-editor/react/hooks/useInteractiveHtmlEditor.d.ts +9 -1
- package/dist/features/html-editor/react/hooks/useInteractiveHtmlEditor.js +107 -196
- package/dist/features/html-editor/source-splice.d.ts +23 -0
- package/dist/features/html-editor/source-splice.js +45 -0
- package/dist/features/i18n/dictionaries/settings-dialog.ar.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.bn.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.de.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.en.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.es.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.fa.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.fr.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.hi.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.hu.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.id.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.it.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.ja.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.ko.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.pl.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.pt-BR.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.ru.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.th.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.tr.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.uk.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.ur.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.zh-CN.js +4 -0
- package/dist/features/i18n/dictionaries/settings-dialog.zh-TW.js +4 -0
- package/dist/features/interactive-ui/interactive-ui.css +1 -1
- package/dist/features/interactive-ui/providers/recharts/bar-chart.js +1 -1
- package/dist/features/interactive-ui/providers/recharts/line-chart.js +1 -1
- package/dist/features/interactive-ui/providers/shadcn/button.d.ts +1 -1
- package/dist/features/mcp-ui/escape.js +2 -6
- package/dist/features/mcp-ui/surfaces/bridge.js +4 -2
- package/dist/features/mcp-ui/surfaces/document.d.ts +11 -4
- package/dist/features/mcp-ui/surfaces/document.js +25 -3
- package/dist/features/mcp-ui/surfaces/outcome.js +1 -1
- package/dist/features/media-providers/constants.d.ts +0 -7
- package/dist/features/media-providers/constants.js +7 -15
- package/dist/features/media-providers/react/components/MediaProvidersTab.js +3 -2
- package/dist/features/media-providers/react/hooks/useMediaProvidersTab.js +6 -3
- package/dist/features/memory/dependencies.d.ts +2 -0
- package/dist/features/memory/dependencies.js +9 -25
- package/dist/features/memory/index.d.ts +1 -0
- package/dist/features/memory/index.js +1 -0
- package/dist/features/memory/react/MemoryPorts.d.ts +17 -0
- package/dist/features/memory/react/MemoryPorts.js +15 -0
- package/dist/features/memory/react/hooks/useMemoryConfig.hooks.d.ts +2 -2
- package/dist/features/memory/react/hooks/useMemoryConfig.hooks.js +7 -7
- package/dist/features/memory/react/hooks/useMemoryConnectors.hooks.d.ts +2 -3
- package/dist/features/memory/react/hooks/useMemoryConnectors.hooks.js +4 -5
- package/dist/features/memory/react/hooks/useMemoryEntries.hooks.d.ts +2 -3
- package/dist/features/memory/react/hooks/useMemoryEntries.hooks.js +4 -5
- package/dist/features/memory/react/hooks/useMemoryExtractions.hooks.js +2 -2
- package/dist/features/panel-kit/fetch-query/adapter.react.d.ts +2 -2
- package/dist/features/panel-kit/fetch-query/adapter.react.js +2 -2
- package/dist/features/panel-kit/fetch-query/adapter.tanstack.d.ts +1 -1
- package/dist/features/panel-kit/fetch-query/adapter.tanstack.js +35 -13
- package/dist/features/panel-kit/fetch-query/binding.react.d.ts +1 -1
- package/dist/features/panel-kit/fetch-query/environment.browser.d.ts +1 -1
- package/dist/features/panel-kit/fetch-query/index.d.ts +4 -2
- package/dist/features/panel-kit/fetch-query/tanstack.d.ts +4 -2
- package/dist/features/panel-kit/helpers/standing-draft-recovery-message.d.ts +3 -1
- package/dist/features/panel-kit/helpers/standing-draft-recovery-message.js +9 -2
- package/dist/features/settings/dialog/styles/settings-dialog.css +169 -21
- package/dist/features/tabbed-dialog/styles/tabbed-dialog.css +91 -0
- package/dist/react/components/RemixIcon.d.ts +1 -41
- package/dist/react/components/RemixIcon.js +3 -176
- package/dist/react/components/RemixIcon.stylesheet.d.ts +84 -0
- package/dist/react/components/RemixIcon.stylesheet.js +208 -0
- package/dist/react/components/remixicon-font-recovery.d.ts +55 -0
- package/dist/react/components/remixicon-font-recovery.js +110 -0
- package/dist/styles/admin.css +8 -2
- package/package.json +12 -7
- package/dist/features/panel-kit/fetch-query/cache.d.ts +0 -125
- package/dist/features/panel-kit/fetch-query/cache.js +0 -232
- package/dist/features/panel-kit/fetch-query/types.d.ts +0 -93
- package/dist/features/panel-kit/fetch-query/types.js +0 -2
|
@@ -6,6 +6,9 @@ export { InfoTip } from './components/InfoTip.js';
|
|
|
6
6
|
export type { InfoTipProps } from './components/InfoTip.js';
|
|
7
7
|
export { useInfoTip } from './components/InfoTip.hooks.js';
|
|
8
8
|
export type { InfoTipController } from './components/InfoTip.hooks.js';
|
|
9
|
+
export { TIP_BOUNDS_ATTRIBUTE } from './components/InfoTip.hooks.js';
|
|
10
|
+
export { placeInfoTipBubble, infoTipBubbleStyle } from './components/InfoTip.rules.js';
|
|
11
|
+
export type { InfoTipPlacement } from './components/InfoTip.rules.js';
|
|
9
12
|
export { SeeMore, resolveSeeMoreView } from './components/SeeMore/SeeMore.js';
|
|
10
13
|
export type { SeeMoreProps, SeeMoreView } from './components/SeeMore/SeeMore.js';
|
|
11
14
|
export { useSeeMoreClamp } from './components/SeeMore/SeeMore.hooks.js';
|
|
@@ -17,4 +20,10 @@ export { ComingSoonPanel } from './components/ComingSoonPanel.js';
|
|
|
17
20
|
export type { ComingSoonPanelProps } from './components/ComingSoonPanel.js';
|
|
18
21
|
export { ComingSoonNotice } from './components/ComingSoonNotice.js';
|
|
19
22
|
export type { ComingSoonNoticeProps } from './components/ComingSoonNotice.js';
|
|
23
|
+
export { SuggestInput } from './components/SuggestInput/SuggestInput.js';
|
|
24
|
+
export type { SuggestInputProps } from './components/SuggestInput/SuggestInput.js';
|
|
25
|
+
export { useSuggestInput, matchSuggestions } from './components/SuggestInput/SuggestInput.hooks.js';
|
|
26
|
+
export type { SuggestInputController } from './components/SuggestInput/SuggestInput.hooks.js';
|
|
27
|
+
export { useDebouncedHtmlPreview } from './components/useDebouncedHtmlPreview.hooks.js';
|
|
28
|
+
export type { HtmlPreviewPort, HtmlPreviewState } from './components/useDebouncedHtmlPreview.hooks.js';
|
|
20
29
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -2,10 +2,15 @@ export { Select, resolveSelectTriggerLabel } from './components/Select/Select.js
|
|
|
2
2
|
export { useSelectDropdown, usePanelPosition } from './components/Select/Select.hooks.js';
|
|
3
3
|
export { InfoTip } from './components/InfoTip.js';
|
|
4
4
|
export { useInfoTip } from './components/InfoTip.hooks.js';
|
|
5
|
+
export { TIP_BOUNDS_ATTRIBUTE } from './components/InfoTip.hooks.js';
|
|
6
|
+
export { placeInfoTipBubble, infoTipBubbleStyle } from './components/InfoTip.rules.js';
|
|
5
7
|
export { SeeMore, resolveSeeMoreView } from './components/SeeMore/SeeMore.js';
|
|
6
8
|
export { useSeeMoreClamp } from './components/SeeMore/SeeMore.hooks.js';
|
|
7
9
|
export { ImagePreviewModal } from './components/ImagePreviewModal.js';
|
|
8
10
|
export { useImagePreviewModal } from './components/ImagePreviewModal.hooks.js';
|
|
9
11
|
export { ComingSoonPanel } from './components/ComingSoonPanel.js';
|
|
10
12
|
export { ComingSoonNotice } from './components/ComingSoonNotice.js';
|
|
13
|
+
export { SuggestInput } from './components/SuggestInput/SuggestInput.js';
|
|
14
|
+
export { useSuggestInput, matchSuggestions } from './components/SuggestInput/SuggestInput.hooks.js';
|
|
15
|
+
export { useDebouncedHtmlPreview } from './components/useDebouncedHtmlPreview.hooks.js';
|
|
11
16
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { VENDOR_API_BASE_URLS } from '@jini-ai/integrations/media-providers/catalog';
|
|
1
2
|
/** Fallback endpoint per protocol, used when a host supplies no preset and
|
|
2
3
|
* the operator has not typed a base URL. Origin: `DEFAULT_BASE_URL_BY_PROTOCOL`. */
|
|
3
4
|
export const DEFAULT_BASE_URL_BY_PROTOCOL = {
|
|
4
|
-
anthropic:
|
|
5
|
-
openai:
|
|
6
|
-
azure:
|
|
7
|
-
google:
|
|
5
|
+
anthropic: VENDOR_API_BASE_URLS.anthropic,
|
|
6
|
+
openai: VENDOR_API_BASE_URLS.openai,
|
|
7
|
+
azure: VENDOR_API_BASE_URLS.azure,
|
|
8
|
+
google: VENDOR_API_BASE_URLS.google,
|
|
8
9
|
};
|
|
9
10
|
/** Display order and English labels for the protocol row. Values are i18n
|
|
10
11
|
* keys (this package's convention is "the English string is the key"). */
|
|
@@ -62,7 +63,7 @@ export const DEFAULT_PROVIDER_PRESETS = [
|
|
|
62
63
|
id: 'anthropic',
|
|
63
64
|
title: 'Anthropic',
|
|
64
65
|
protocol: 'anthropic',
|
|
65
|
-
baseUrl:
|
|
66
|
+
baseUrl: VENDOR_API_BASE_URLS.anthropic,
|
|
66
67
|
preferredModels: ['claude-sonnet-5', 'claude-opus-5', 'claude-haiku-4-5'],
|
|
67
68
|
kind: 'protocol',
|
|
68
69
|
apiKeyPrefix: 'sk-ant-',
|
|
@@ -71,7 +72,7 @@ export const DEFAULT_PROVIDER_PRESETS = [
|
|
|
71
72
|
id: 'openai',
|
|
72
73
|
title: 'OpenAI',
|
|
73
74
|
protocol: 'openai',
|
|
74
|
-
baseUrl:
|
|
75
|
+
baseUrl: VENDOR_API_BASE_URLS.openai,
|
|
75
76
|
// `gpt-4o`/`gpt-4o-mini`/`o3`/`o4-mini` are stale: OpenAI's GPT-5.6 family
|
|
76
77
|
// (released 2026-07-09, per the API changelog) replaced the old
|
|
77
78
|
// flagship/mini/nano naming with named tiers — sol/terra/luna. `sol` is
|
|
@@ -88,7 +89,7 @@ export const DEFAULT_PROVIDER_PRESETS = [
|
|
|
88
89
|
id: 'azure-openai',
|
|
89
90
|
title: 'Azure OpenAI',
|
|
90
91
|
protocol: 'azure',
|
|
91
|
-
baseUrl:
|
|
92
|
+
baseUrl: VENDOR_API_BASE_URLS.azure,
|
|
92
93
|
preferredModels: [],
|
|
93
94
|
kind: 'protocol',
|
|
94
95
|
// No `apiKeyPrefix` deliberately: an Azure OpenAI key is a bare hex string with no vendor
|
|
@@ -101,7 +102,7 @@ export const DEFAULT_PROVIDER_PRESETS = [
|
|
|
101
102
|
id: 'google-gemini',
|
|
102
103
|
title: 'Google Gemini',
|
|
103
104
|
protocol: 'google',
|
|
104
|
-
baseUrl:
|
|
105
|
+
baseUrl: VENDOR_API_BASE_URLS.google,
|
|
105
106
|
// Ordered newest-first: `rules.ts`'s `saved?.model ?? preset.preferredModels[0]` makes entry [0]
|
|
106
107
|
// the default for anyone who has never picked a model, so a stale head silently pins new users
|
|
107
108
|
// to an old generation. Reported live: the field defaulted to `gemini-2.5-flash` while the
|
|
@@ -119,7 +120,7 @@ export const DEFAULT_PROVIDER_PRESETS = [
|
|
|
119
120
|
id: 'openrouter',
|
|
120
121
|
title: 'OpenRouter',
|
|
121
122
|
protocol: 'openai',
|
|
122
|
-
baseUrl:
|
|
123
|
+
baseUrl: VENDOR_API_BASE_URLS.openrouter,
|
|
123
124
|
preferredModels: ['anthropic/claude-sonnet-5', 'google/gemini-2.5-pro', 'openai/gpt-5.6-sol'],
|
|
124
125
|
kind: 'gateway',
|
|
125
126
|
// Longer than OpenAI's `sk-`, and deliberately so: `apiKeyFormatWarning` resolves a key to the
|
|
@@ -130,7 +131,7 @@ export const DEFAULT_PROVIDER_PRESETS = [
|
|
|
130
131
|
id: 'ollama',
|
|
131
132
|
title: 'Ollama',
|
|
132
133
|
protocol: 'openai',
|
|
133
|
-
baseUrl:
|
|
134
|
+
baseUrl: VENDOR_API_BASE_URLS.ollama,
|
|
134
135
|
preferredModels: [],
|
|
135
136
|
kind: 'gateway',
|
|
136
137
|
requiresApiKey: false,
|
|
@@ -2,7 +2,9 @@ import type { ByokConfig, DetectedAgent } from './types.js';
|
|
|
2
2
|
import type { ExecutionPort } from './ports.js';
|
|
3
3
|
/** Decoded HTTP operations; hosts retain auth, URLs and transport validation. */
|
|
4
4
|
export interface ExecutionProbeTransport {
|
|
5
|
-
detectExecutionAgents(required: Record<string, never>, optional?:
|
|
5
|
+
detectExecutionAgents(required: Record<string, never>, optional?: {
|
|
6
|
+
force?: boolean;
|
|
7
|
+
}): Promise<{
|
|
6
8
|
data: readonly DetectedAgent[];
|
|
7
9
|
}>;
|
|
8
10
|
testExecutionConnection(required: Pick<ByokConfig, "protocol" | "baseUrl" | "apiKey" | "model"> & ExecutionProbeFlags, optional?: Record<string, never>): Promise<{
|
|
@@ -58,8 +58,8 @@ export function createExecutionHttpAdapter({ transport }, _options = {}) {
|
|
|
58
58
|
* route call itself fails (session expired, network down, this admin's own
|
|
59
59
|
* route 500ing) — a case with no provider-side answer to report as a value.
|
|
60
60
|
*/
|
|
61
|
-
async function requestAgentDetection() {
|
|
62
|
-
return requireExecutionResponseData({ response: await transport.detectExecutionAgents({}, {}), callSite: "detectExecutionAgents" }, {});
|
|
61
|
+
async function requestAgentDetection({ force = false } = {}) {
|
|
62
|
+
return requireExecutionResponseData({ response: await transport.detectExecutionAgents({}, force ? { force: true } : {}), callSite: "detectExecutionAgents" }, {});
|
|
63
63
|
}
|
|
64
64
|
/**
|
|
65
65
|
* Last detection, shared across every `ExecutionTab` mount in this tab's
|
|
@@ -96,7 +96,12 @@ export function createExecutionHttpAdapter({ transport }, _options = {}) {
|
|
|
96
96
|
// error in place for the rest of the session, and the port's contract is
|
|
97
97
|
// that a failure REJECTS (see this function's doc) — so a retry has to be
|
|
98
98
|
// able to actually retry.
|
|
99
|
-
inFlight.
|
|
99
|
+
inFlight.then((agents) => {
|
|
100
|
+
// A background snapshot is usable but provisional. Subsequent reads must reach the host
|
|
101
|
+
// cache so completed discovery replaces it; they never request another CLI probe.
|
|
102
|
+
if (agents.some(agent => agent.discoveryPending) && cachedDetection === inFlight)
|
|
103
|
+
cachedDetection = null;
|
|
104
|
+
}, () => {
|
|
100
105
|
if (cachedDetection === inFlight)
|
|
101
106
|
cachedDetection = null;
|
|
102
107
|
});
|
|
@@ -116,7 +121,7 @@ export function createExecutionHttpAdapter({ transport }, _options = {}) {
|
|
|
116
121
|
async rescanLocalAgents() {
|
|
117
122
|
// Explicit operator action: always re-probe, and make the fresh result
|
|
118
123
|
// the new baseline for subsequent mounts.
|
|
119
|
-
return cacheDetection(requestAgentDetection());
|
|
124
|
+
return cacheDetection(requestAgentDetection({ force: true }));
|
|
120
125
|
},
|
|
121
126
|
async testConnection(config) {
|
|
122
127
|
return transport.testExecutionConnection({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { API_KEY_CROSS_VENDOR_WARNING, API_KEY_TOO_SHORT_WARNING, CUSTOM_MODEL_SENTINEL, CUSTOM_PRESET_ID, DEFAULT_AGENT_CLI_ENV_FIELDS, DEFAULT_AGENT_DESCRIPTIONS, DEFAULT_BASE_URL_BY_PROTOCOL, DEFAULT_PROVIDER_PRESETS, MIN_PLAUSIBLE_API_KEY_LENGTH, PROTOCOL_OPTIONS, } from './constants.js';
|
|
2
2
|
export { createFakeExecutionPort, type FakeExecutionPortOptions } from './dependencies.js';
|
|
3
3
|
export type { ExecutionPort } from './ports.js';
|
|
4
|
-
export { agentCliEnvValue, agentDiagnosticTooltip, agentExecutableRepairState, agentMetaLabel, type AgentMetaLabels, agentModelSummary, apiKeyFormatWarning, binPathEnvField, cleanAgentVersionLabel, cliEnvFieldsForAgent, credentialsForPreset, customPreset, filterAgentModelOptions, groupPresets, isBaseUrlInvalid, isProviderConfigured, isValidApiBaseUrl, missingRequiredFields, modelIdForReasoningLevel, nextConfigForAgentCliEnvChange, nextConfigForAgentModel, nextConfigForAgentReasoning, nextConfigForAgentSelect, nextConfigForModeChange, nextConfigForPresetSelect, nextConfigForProtocolSelect, parseMaxTokens, presetRequiresApiKey, presetsForProtocol, reasoningModelGroupFor, reasoningModelGroups, resolveSelectedPreset, selectedAgentModel, selectedAgentReasoning, shouldShowCustomModelInput, showsBaseUrlField, sortDetectedAgents, splitReasoningModelId, } from './rules.js';
|
|
4
|
+
export { agentCliEnvValue, agentDiagnosticTooltip, agentExecutableRepairState, agentMetaLabel, type AgentMetaLabels, agentModelSummary, apiKeyFormatWarning, binPathEnvField, cleanAgentVersionLabel, cliEnvFieldsForAgent, credentialsForPreset, customPreset, filterAgentModelOptions, groupPresets, isBaseUrlInvalid, isProviderConfigured, isValidApiBaseUrl, missingRequiredFields, modelIdForReasoningLevel, nextConfigForAgentCliEnvChange, nextConfigForAgentModel, nextConfigForAgentReasoning, nextConfigForAgentSelect, nextConfigForModeChange, nextConfigForPresetSelect, nextConfigForProtocolSelect, parseMaxTokens, presetRequiresApiKey, presetsForProtocol, reasoningModelGroupFor, reasoningModelGroups, resolveSelectedPreset, selectedAgentModel, selectedAgentReasoning, shouldShowCustomModelInput, showsBaseUrlField, sortDetectedAgents, partitionAgentsByInstalled, splitReasoningModelId, } from './rules.js';
|
|
5
5
|
export type { AgentAuthStatus, AgentCliEnvFieldSpec, AgentDiagnostic, AgentDiagnosticReason, AgentDiagnosticSeverity, AgentExecutableRepair, AgentExecutableSource, AgentFixIntent, AgentModelOption, AgentModelSource, AgentScanState, ApiKeyWarning, AgentSupportsCustomModel, AgentTestState, ApiProtocol, ByokConfig, ByokProviderCredentials, ByokRequiredField, ConnectionTestState, DetectedAgent, ExecutionConfig, ExecutionMode, LocalCliConfig, ModelDiscoveryState, ProviderPreset, ProviderPresetKind, ReasoningModelGroup, } from './types.js';
|
|
6
6
|
export { ExecutionTab } from './react/components/ExecutionTab.js';
|
|
7
7
|
export type { ExecutionTabProps } from './react/components/ExecutionTab.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { API_KEY_CROSS_VENDOR_WARNING, API_KEY_TOO_SHORT_WARNING, CUSTOM_MODEL_SENTINEL, CUSTOM_PRESET_ID, DEFAULT_AGENT_CLI_ENV_FIELDS, DEFAULT_AGENT_DESCRIPTIONS, DEFAULT_BASE_URL_BY_PROTOCOL, DEFAULT_PROVIDER_PRESETS, MIN_PLAUSIBLE_API_KEY_LENGTH, PROTOCOL_OPTIONS, } from './constants.js';
|
|
2
2
|
export { createFakeExecutionPort } from './dependencies.js';
|
|
3
|
-
export { agentCliEnvValue, agentDiagnosticTooltip, agentExecutableRepairState, agentMetaLabel, agentModelSummary, apiKeyFormatWarning, binPathEnvField, cleanAgentVersionLabel, cliEnvFieldsForAgent, credentialsForPreset, customPreset, filterAgentModelOptions, groupPresets, isBaseUrlInvalid, isProviderConfigured, isValidApiBaseUrl, missingRequiredFields, modelIdForReasoningLevel, nextConfigForAgentCliEnvChange, nextConfigForAgentModel, nextConfigForAgentReasoning, nextConfigForAgentSelect, nextConfigForModeChange, nextConfigForPresetSelect, nextConfigForProtocolSelect, parseMaxTokens, presetRequiresApiKey, presetsForProtocol, reasoningModelGroupFor, reasoningModelGroups, resolveSelectedPreset, selectedAgentModel, selectedAgentReasoning, shouldShowCustomModelInput, showsBaseUrlField, sortDetectedAgents, splitReasoningModelId, } from './rules.js';
|
|
3
|
+
export { agentCliEnvValue, agentDiagnosticTooltip, agentExecutableRepairState, agentMetaLabel, agentModelSummary, apiKeyFormatWarning, binPathEnvField, cleanAgentVersionLabel, cliEnvFieldsForAgent, credentialsForPreset, customPreset, filterAgentModelOptions, groupPresets, isBaseUrlInvalid, isProviderConfigured, isValidApiBaseUrl, missingRequiredFields, modelIdForReasoningLevel, nextConfigForAgentCliEnvChange, nextConfigForAgentModel, nextConfigForAgentReasoning, nextConfigForAgentSelect, nextConfigForModeChange, nextConfigForPresetSelect, nextConfigForProtocolSelect, parseMaxTokens, presetRequiresApiKey, presetsForProtocol, reasoningModelGroupFor, reasoningModelGroups, resolveSelectedPreset, selectedAgentModel, selectedAgentReasoning, shouldShowCustomModelInput, showsBaseUrlField, sortDetectedAgents, partitionAgentsByInstalled, splitReasoningModelId, } from './rules.js';
|
|
4
4
|
export { ExecutionTab } from './react/components/ExecutionTab.js';
|
|
5
5
|
export { ByokProviderForm } from './react/components/ByokProviderForm.js';
|
|
6
6
|
export { LocalCliAgentList } from './react/components/LocalCliAgentList.js';
|
|
@@ -58,6 +58,8 @@ export interface ByokProviderFormProps {
|
|
|
58
58
|
* Omitted by every existing caller, so the rendered output is byte-identical without it.
|
|
59
59
|
*/
|
|
60
60
|
formFooter?: ReactNode;
|
|
61
|
+
/** Host actions directly below Model and its results, before any Advanced disclosure. */
|
|
62
|
+
modelFooter?: ReactNode;
|
|
61
63
|
/**
|
|
62
64
|
* `true` when a key is already held somewhere the browser cannot read — so the API-key input is
|
|
63
65
|
* legitimately empty and must NOT be treated as a missing required field.
|
|
@@ -91,6 +93,21 @@ export interface ByokProviderFormProps {
|
|
|
91
93
|
apiKeyPlaceholder?: string;
|
|
92
94
|
/** This card's own agent handle — see `ExecutionTab`'s `agentHandle` doc for the split. */
|
|
93
95
|
agentHandle?: string;
|
|
96
|
+
/**
|
|
97
|
+
* A host's button row for the key (Test key / Save key), directly UNDER the input; Show stays on
|
|
98
|
+
* the input's own line (owner, 2026-10-09: the input with Show beside it, actions beneath). Given,
|
|
99
|
+
* the key field renders as a `<div>` whose `<label>` wraps only the field name, so these buttons are
|
|
100
|
+
* never nested inside a label (which would fold their text into the input's accessible name).
|
|
101
|
+
*/
|
|
102
|
+
apiKeyActions?: ReactNode;
|
|
103
|
+
/**
|
|
104
|
+
* Moves Base URL and Max tokens into a collapsed "Advanced" disclosure after the Model row. For
|
|
105
|
+
* hosts where those two are rarely touched; it opens on its own while Base URL is invalid or
|
|
106
|
+
* missing, so a required-field problem is never hidden. Default `false` keeps the original order.
|
|
107
|
+
*/
|
|
108
|
+
collapseAdvanced?: boolean;
|
|
109
|
+
/** Paint required-field errors after that field loses focus; validation gates stay immediate. */
|
|
110
|
+
deferMissingFeedback?: boolean;
|
|
94
111
|
}
|
|
95
112
|
/**
|
|
96
113
|
* The BYOK credential card: API key, base URL, optional token cap, and model.
|
|
@@ -98,5 +115,5 @@ export interface ByokProviderFormProps {
|
|
|
98
115
|
* `ByokModelField`, `ByokConnectionTestControl`) — already factored out
|
|
99
116
|
* upstream, so this is assembly plus the origin's required-field marking.
|
|
100
117
|
*/
|
|
101
|
-
export declare function ByokProviderForm({ config, onConfigChange, preset, presets, modelDiscovery, connectionTest, onTestConnection, canTestConnection, apiKeyFooter, formFooter, apiKeyStoredExternally, apiKeyPlaceholder, agentHandle, }: ByokProviderFormProps): import("react").JSX.Element;
|
|
118
|
+
export declare function ByokProviderForm({ config, onConfigChange, preset, presets, modelDiscovery, connectionTest, onTestConnection, canTestConnection, apiKeyFooter, formFooter, modelFooter, apiKeyStoredExternally, apiKeyPlaceholder, agentHandle, apiKeyActions, collapseAdvanced, deferMissingFeedback, }: ByokProviderFormProps): import("react").JSX.Element;
|
|
102
119
|
//# sourceMappingURL=ByokProviderForm.d.ts.map
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useState } from 'react';
|
|
2
|
+
import { useEffect, useId, useState } from 'react';
|
|
3
3
|
import { agentHandleProps, agentSubHandle } from '@jini-ai/agentic';
|
|
4
4
|
import { useT } from '../../../i18n/index.js';
|
|
5
5
|
import { CUSTOM_MODEL_SENTINEL, DEFAULT_PROVIDER_PRESETS } from '../../constants.js';
|
|
6
|
-
import { apiKeyFormatWarning,
|
|
6
|
+
import { apiKeyFormatWarning, parseMaxTokens, presetRequiresApiKey, shouldShowCustomModelInput, showsBaseUrlField, } from '../../rules.js';
|
|
7
7
|
import { SearchableModelSelect } from './SearchableModelSelect.js';
|
|
8
|
+
import { useByokFieldValidation } from '../hooks/use-byok-field-validation.hooks.js';
|
|
8
9
|
/**
|
|
9
10
|
* The BYOK credential card: API key, base URL, optional token cap, and model.
|
|
10
11
|
* Origin: `components/byok/*` (`ByokKeyField`, `ByokProviderBaseUrl`,
|
|
11
12
|
* `ByokModelField`, `ByokConnectionTestControl`) — already factored out
|
|
12
13
|
* upstream, so this is assembly plus the origin's required-field marking.
|
|
13
14
|
*/
|
|
14
|
-
export function ByokProviderForm({ config, onConfigChange, preset, presets = DEFAULT_PROVIDER_PRESETS, modelDiscovery, connectionTest, onTestConnection, canTestConnection = true, apiKeyFooter, formFooter, apiKeyStoredExternally = false, apiKeyPlaceholder, agentHandle, }) {
|
|
15
|
+
export function ByokProviderForm({ config, onConfigChange, preset, presets = DEFAULT_PROVIDER_PRESETS, modelDiscovery, connectionTest, onTestConnection, canTestConnection = true, apiKeyFooter, formFooter, modelFooter, apiKeyStoredExternally = false, apiKeyPlaceholder, agentHandle, apiKeyActions, collapseAdvanced = false, deferMissingFeedback = false, }) {
|
|
15
16
|
const t = useT();
|
|
17
|
+
const keyInputId = useId();
|
|
18
|
+
const KeyField = apiKeyActions ? 'div' : 'label';
|
|
16
19
|
const [revealKey, setRevealKey] = useState(false);
|
|
17
20
|
/** Whether the operator explicitly picked "Custom…" in the model picker — distinct from "the
|
|
18
21
|
* saved model simply isn't in the live list". Same UI-local toggle, for the same reason, as
|
|
@@ -33,13 +36,7 @@ export function ByokProviderForm({ config, onConfigChange, preset, presets = DEF
|
|
|
33
36
|
useEffect(() => {
|
|
34
37
|
setRevealKey(false);
|
|
35
38
|
}, [config.providerId]);
|
|
36
|
-
const missing =
|
|
37
|
-
// A stored-but-unreadable key satisfies the requirement. Subtracted here rather than threaded into
|
|
38
|
-
// `missingRequiredFields` because that function is a pure rule over `ByokConfig` and this is a fact
|
|
39
|
-
// about the HOST's storage, which does not belong in the config shape.
|
|
40
|
-
if (apiKeyStoredExternally)
|
|
41
|
-
missing.delete('apiKey');
|
|
42
|
-
const baseUrlInvalid = isBaseUrlInvalid(config);
|
|
39
|
+
const { missing, baseUrlInvalid, isMissing, markTouched } = useByokFieldValidation({ config, preset, apiKeyStoredExternally }, { deferMissingFeedback });
|
|
43
40
|
/** Deliberately NOT folded into `missing` above: that set drives `is-missing` styling and the
|
|
44
41
|
* Test-connection disable, and a wrong-SHAPED key must never reach either. */
|
|
45
42
|
const keyFormatWarning = apiKeyFormatWarning(config, preset, presets);
|
|
@@ -70,7 +67,10 @@ export function ByokProviderForm({ config, onConfigChange, preset, presets = DEF
|
|
|
70
67
|
// a hydrated or hand-typed id is never silently replaced by whatever sorts first.
|
|
71
68
|
const customModelActive = showModelPicker && shouldShowCustomModelInput(config.model, liveModels, explicitCustomModel);
|
|
72
69
|
const patch = (next) => onConfigChange({ ...config, ...next });
|
|
73
|
-
|
|
70
|
+
const connectionFields = (_jsx(_Fragment, { children: _jsxs("div", { className: "jini-byok-field-row", children: [showsBaseUrlField(preset) ? (_jsxs("label", { className: "jini-field", onBlurCapture: () => markTouched({ field: 'baseUrl' }), children: [_jsxs("span", { className: "jini-field-label", children: [t('Base URL'), preset?.baseUrl ? null : _jsx("span", { className: "jini-field-required", "aria-hidden": "true", children: "*" })] }), _jsx("input", { className: 'jini-input' + (isMissing({ field: 'baseUrl' }) ? ' is-missing' : ''), type: "url", inputMode: "url", spellCheck: false, value: config.baseUrl, onChange: (event) => patch({ baseUrl: event.target.value }), ...agentHandleProps({}, { base: agentHandle, ...({ action: 'base-url', role: 'field', label: t('Base URL') }) }) }), _jsx("span", { className: 'jini-field-hint' + (baseUrlInvalid ? ' is-error' : ''), children: baseUrlInvalid
|
|
71
|
+
? t('Enter an absolute http(s) URL.')
|
|
72
|
+
: t('Default endpoint. Usually no need to change this.') })] })) : null, _jsxs("label", { className: "jini-field", children: [_jsx("span", { className: "jini-field-label", children: t('Max tokens (optional)') }), _jsx("input", { className: "jini-input", type: "number", min: 1, step: 1, value: config.maxTokens ?? '', onChange: (event) => patch({ maxTokens: parseMaxTokens(event.target.value) }), ...agentHandleProps({}, { base: agentHandle, ...({ action: 'max-tokens', role: 'field', label: t('Max tokens (optional)') }) }) }), _jsx("span", { className: "jini-field-hint", children: t('Cap on the response length. Leave blank to use the model default.') })] })] }) }));
|
|
73
|
+
return (_jsxs("div", { className: "jini-byok-card", children: [_jsx("div", { className: "jini-byok-card-head", children: _jsx("h4", { className: "jini-byok-card-title", children: preset ? preset.title : t('Custom endpoint') }) }), presetRequiresApiKey(preset) ? (_jsxs(_Fragment, { children: [_jsxs(KeyField, { className: "jini-field", onBlurCapture: () => markTouched({ field: 'apiKey' }), children: [_jsxs("span", { className: "jini-field-label", children: [apiKeyActions ? (_jsxs("label", { className: "jini-field-label", htmlFor: keyInputId, children: [_jsx("span", { children: t('API key') }), _jsx("span", { className: "jini-field-required", "aria-hidden": "true", children: "*" })] })) : (_jsxs(_Fragment, { children: [t('API key'), _jsx("span", { className: "jini-field-required", "aria-hidden": "true", children: "*" })] })), preset?.apiKeyConsoleUrl ? (_jsx("a", { className: "jini-field-link", href: preset.apiKeyConsoleUrl, target: "_blank", rel: "noreferrer noopener", children: t('Get key') })) : null] }), _jsxs("span", { className: "jini-field-input-row", children: [_jsx("input", { ...(apiKeyActions ? { id: keyInputId } : {}), className: 'jini-input' + (isMissing({ field: 'apiKey' }) ? ' is-missing' : ''), type: revealKey ? 'text' : 'password',
|
|
74
74
|
/* `new-password`, NOT `"off"` — Chrome deliberately ignores `off` on credential-shaped
|
|
75
75
|
fields (a long-standing intentional decision, not a bug). `off` here is what let the
|
|
76
76
|
reported autofill through: Chrome filled this field with the admin's own saved
|
|
@@ -81,9 +81,7 @@ export function ByokProviderForm({ config, onConfigChange, preset, presets = DEF
|
|
|
81
81
|
|
|
82
82
|
Known trade-off, not fixed here: Chrome may now offer to GENERATE a password on
|
|
83
83
|
this field — a suggestion popup, not a silently wrong value. */
|
|
84
|
-
autoComplete: "new-password", spellCheck: false, placeholder: apiKeyPlaceholder, value: config.apiKey, onChange: (event) => patch({ apiKey: event.target.value }), ...agentHandleProps({}, { base: agentHandle, ...({ action: 'api-key', role: 'field', label: t('API key') }) }) }), _jsx("button", { type: "button", className: "jini-input-affix-btn", "aria-pressed": revealKey, onClick: () => setRevealKey((shown) => !shown), ...agentHandleProps({}, { base: agentHandle, ...({ action: 'reveal-key', role: 'button', label: t('Reveal API key') }) }), children: revealKey ? t('Hide') : t('Show') })] }), _jsx("span", { className: "jini-field-hint", children: t('Stored only by this host.') }), keyFormatWarning ? (_jsx("span", { className: "jini-field-hint is-error", role: "status", children: t(keyFormatWarning.message, keyFormatWarning.vars) })) : null] }), apiKeyFooter ? _jsx("div", { className: "jini-byok-key-footer", children: apiKeyFooter }) : null] })) : null, _jsxs("div", { className: "jini-byok-
|
|
85
|
-
? t('Enter an absolute http(s) URL.')
|
|
86
|
-
: t('Default endpoint. Usually no need to change this.') })] })) : null, _jsxs("label", { className: "jini-field", children: [_jsx("span", { className: "jini-field-label", children: t('Max tokens (optional)') }), _jsx("input", { className: "jini-input", type: "number", min: 1, step: 1, value: config.maxTokens ?? '', onChange: (event) => patch({ maxTokens: parseMaxTokens(event.target.value) }), ...agentHandleProps({}, { base: agentHandle, ...({ action: 'max-tokens', role: 'field', label: t('Max tokens (optional)') }) }) }), _jsx("span", { className: "jini-field-hint", children: t('Cap on the response length. Leave blank to use the model default.') })] })] }), _jsxs("div", { className: "jini-byok-model-row", children: [_jsxs("label", { className: "jini-field", children: [_jsxs("span", { className: "jini-field-label", children: [t('Model'), _jsx("span", { className: "jini-field-required", "aria-hidden": "true", children: "*" })] }), showModelPicker ? (_jsx(SearchableModelSelect, { className: 'jini-input' + (missing.has('model') ? ' is-missing' : ''), ariaLabel: t('Model'), searchPlaceholder: t('Search models'), testId: "jini-byok-model-select", searchInputTestId: "jini-byok-model-search", ...(agentHandle ? { agentHandle: agentSubHandle({ base: agentHandle, action: 'model' }) } : {}), value: customModelActive ? CUSTOM_MODEL_SENTINEL : config.model, models: liveModels.map((model) => ({ id: model, label: model })), additionalOptions: [{ value: CUSTOM_MODEL_SENTINEL, label: t('Custom…') }], onChange: (next) => {
|
|
84
|
+
autoComplete: "new-password", spellCheck: false, placeholder: apiKeyPlaceholder, value: config.apiKey, onChange: (event) => patch({ apiKey: event.target.value }), ...agentHandleProps({}, { base: agentHandle, ...({ action: 'api-key', role: 'field', label: t('API key') }) }) }), _jsx("button", { type: "button", className: "jini-input-affix-btn", "aria-pressed": revealKey, onClick: () => setRevealKey((shown) => !shown), ...agentHandleProps({}, { base: agentHandle, ...({ action: 'reveal-key', role: 'button', label: t('Reveal API key') }) }), children: revealKey ? t('Hide') : t('Show') })] }), apiKeyActions ? _jsx("span", { className: "jini-byok-key-actions", children: apiKeyActions }) : null, _jsx("span", { className: "jini-field-hint", children: t('Stored only by this host.') }), keyFormatWarning ? (_jsx("span", { className: "jini-field-hint is-error", role: "status", children: t(keyFormatWarning.message, keyFormatWarning.vars) })) : null] }), apiKeyFooter ? _jsx("div", { className: "jini-byok-key-footer", children: apiKeyFooter }) : null] })) : null, collapseAdvanced ? null : connectionFields, _jsxs("div", { className: "jini-byok-model-row", children: [_jsxs("label", { className: "jini-field", onBlurCapture: () => markTouched({ field: 'model' }), children: [_jsxs("span", { className: "jini-field-label", children: [t('Model'), _jsx("span", { className: "jini-field-required", "aria-hidden": "true", children: "*" })] }), showModelPicker ? (_jsx(SearchableModelSelect, { className: 'jini-input' + (isMissing({ field: 'model' }) ? ' is-missing' : ''), ariaLabel: t('Model'), searchPlaceholder: t('Search models'), testId: "jini-byok-model-select", searchInputTestId: "jini-byok-model-search", ...(agentHandle ? { agentHandle: agentSubHandle({ base: agentHandle, action: 'model' }) } : {}), value: customModelActive ? CUSTOM_MODEL_SENTINEL : config.model, models: liveModels.map((model) => ({ id: model, label: model })), additionalOptions: [{ value: CUSTOM_MODEL_SENTINEL, label: t('Custom…') }], onChange: (next) => {
|
|
87
85
|
if (next === CUSTOM_MODEL_SENTINEL) {
|
|
88
86
|
// Open the free-text box WITHOUT clearing `config.model`. Blanking it here would
|
|
89
87
|
// discard a working model the moment someone opened the picker to look at it.
|
|
@@ -92,7 +90,7 @@ export function ByokProviderForm({ config, onConfigChange, preset, presets = DEF
|
|
|
92
90
|
}
|
|
93
91
|
setExplicitCustomModel(false);
|
|
94
92
|
patch({ model: next });
|
|
95
|
-
} })) : null, !showModelPicker || customModelActive ? (_jsx("input", { className: 'jini-input' + (
|
|
93
|
+
} })) : null, !showModelPicker || customModelActive ? (_jsx("input", { className: 'jini-input' + (isMissing({ field: 'model' }) ? ' is-missing' : ''), list: !showModelPicker && suggestions.length > 0 ? modelListId : undefined, spellCheck: false, value: config.model, onChange: (event) => patch({ model: event.target.value }), ...agentHandleProps({}, { base: agentHandle, ...({ action: 'model', role: 'field', label: t('Model') }) }) })) : null, !showModelPicker && suggestions.length > 0 ? (_jsx("datalist", { id: modelListId, children: suggestions.map((model) => (_jsx("option", { value: model }, model))) })) : null] }), canTestConnection ? (_jsx("button", { type: "button", className: "jini-btn jini-byok-test-btn", disabled: connectionTest.status === 'testing' || missing.size > 0, onClick: onTestConnection, ...agentHandleProps({}, { base: agentHandle, ...({ action: 'test-connection', role: 'button', label: t('Test connection') }) }), children: connectionTest.status === 'testing' ? t('Testing…') : t('Test connection') })) : null] }), modelDiscovery.status === 'error' ? (
|
|
96
94
|
// Non-blocking (the field above stays editable, with the preset's static
|
|
97
95
|
// suggestions) but never silent — a discovery failure is an operator-actionable
|
|
98
96
|
// fact (bad key, wrong base URL, unreachable endpoint), not "no models exist".
|
|
@@ -103,6 +101,6 @@ export function ByokProviderForm({ config, onConfigChange, preset, presets = DEF
|
|
|
103
101
|
// identity host suites locate it by — only its parent changed.
|
|
104
102
|
_jsx("span", { className: "jini-field-hint is-error", role: "status", children: t('Could not load live models: {message}', { message: t(modelDiscovery.message) }) })) : null, canTestConnection && (connectionTest.status === 'ok' || connectionTest.status === 'error') ? (_jsx("div", { className: "jini-byok-test-row", children: _jsx("span", { className: `jini-byok-test-status is-${connectionTest.status}`, role: connectionTest.status === 'error' ? 'alert' : 'status', children: connectionTest.status === 'ok'
|
|
105
103
|
? (connectionTest.message !== undefined ? t(connectionTest.message) : t('Connection succeeded'))
|
|
106
|
-
: t(connectionTest.message) }) })) : null, formFooter ? _jsx("div", { className: "jini-byok-form-footer", children: formFooter }) : null] }));
|
|
104
|
+
: t(connectionTest.message) }) })) : null, modelFooter ? _jsx("div", { className: "jini-byok-model-footer", children: modelFooter }) : null, collapseAdvanced ? (_jsxs("details", { className: "jini-byok-advanced", open: baseUrlInvalid || missing.has('baseUrl') || undefined, children: [_jsx("summary", { children: t('Advanced') }), connectionFields] })) : null, formFooter ? _jsx("div", { className: "jini-byok-form-footer", children: formFooter }) : null] }));
|
|
107
105
|
}
|
|
108
106
|
//# sourceMappingURL=ByokProviderForm.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
2
|
import type { AgentCliEnvFieldSpec, AgentTestState, DetectedAgent, LocalCliConfig } from '../../types.js';
|
|
3
3
|
export interface LocalCliAgentCardProps {
|
|
4
4
|
agent: DetectedAgent;
|
|
@@ -38,6 +38,10 @@ export interface LocalCliAgentCardProps {
|
|
|
38
38
|
* the origin's managed-runtime card — its wallet balance, plan badges,
|
|
39
39
|
* sign-in pill, and upgrade coachmarks are bound to that product's hosted
|
|
40
40
|
* service, not to the idea of "a CLI on a machine".
|
|
41
|
+
*
|
|
42
|
+
* Owner, 2026-10-09: selection grows this card inside its own grid column.
|
|
43
|
+
* `LocalCliAgentSettings` stays inside it, so the neighbour keeps its normal
|
|
44
|
+
* height rather than sharing a full-row settings strip.
|
|
41
45
|
*/
|
|
42
46
|
export declare function LocalCliAgentCard({ agent, config, selected, onSelect, onModelChange, onReasoningChange, onEnvChange, cliEnvFields, renderIcon, onTest, agentTest, onRescan, agentHandle, }: LocalCliAgentCardProps): import("react").JSX.Element;
|
|
43
47
|
//# sourceMappingURL=LocalCliAgentCard.d.ts.map
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import { jsx as _jsx,
|
|
2
|
-
import {
|
|
3
|
-
import { agentHandleProps, agentSubHandle } from '@jini-ai/agentic';
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { agentHandleProps } from '@jini-ai/agentic';
|
|
4
3
|
import { useT } from '../../../i18n/index.js';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { AgentCliEnvFields } from './AgentCliEnvFields.js';
|
|
4
|
+
import { DEFAULT_AGENT_DESCRIPTIONS } from '../../constants.js';
|
|
5
|
+
import { agentMetaLabel, agentModelSummary } from '../../rules.js';
|
|
6
|
+
import { useLocalCliAgentCard } from '../hooks/useLocalCliAgentCard.js';
|
|
9
7
|
import { AgentDiagnosticRow } from './AgentDiagnosticRow.js';
|
|
10
|
-
import {
|
|
8
|
+
import { LocalCliAgentSettings } from './LocalCliAgentSettings.js';
|
|
11
9
|
/**
|
|
12
10
|
* One detected code-agent CLI, as a selectable card.
|
|
13
11
|
*
|
|
@@ -21,18 +19,14 @@ import { SearchableModelSelect } from './SearchableModelSelect.js';
|
|
|
21
19
|
* the origin's managed-runtime card — its wallet balance, plan badges,
|
|
22
20
|
* sign-in pill, and upgrade coachmarks are bound to that product's hosted
|
|
23
21
|
* service, not to the idea of "a CLI on a machine".
|
|
22
|
+
*
|
|
23
|
+
* Owner, 2026-10-09: selection grows this card inside its own grid column.
|
|
24
|
+
* `LocalCliAgentSettings` stays inside it, so the neighbour keeps its normal
|
|
25
|
+
* height rather than sharing a full-row settings strip.
|
|
24
26
|
*/
|
|
25
27
|
export function LocalCliAgentCard({ agent, config, selected, onSelect, onModelChange, onReasoningChange, onEnvChange, cliEnvFields, renderIcon, onTest, agentTest, onRescan, agentHandle, }) {
|
|
26
28
|
const t = useT();
|
|
27
|
-
|
|
28
|
-
// the model picker's own "Custom…" option — distinct from "the saved model
|
|
29
|
-
// simply isn't in the known list" (`shouldShowCustomModelInput` covers
|
|
30
|
-
// both, but only THIS one needs to be remembered as a UI-local toggle,
|
|
31
|
-
// since it is not itself persisted config: see `LocalCliConfig`, which has
|
|
32
|
-
// nowhere for "the operator is mid-typing a custom id" to live). Scoped to
|
|
33
|
-
// this card instance, so switching to a different agent and back does not
|
|
34
|
-
// leak one agent's custom-mode toggle onto another.
|
|
35
|
-
const [explicitCustomMode, setExplicitCustomMode] = useState(false);
|
|
29
|
+
const card = useLocalCliAgentCard({ agent, config, agentTest, cliEnvFields, onModelChange, onReasoningChange, onRescan, onTest, t });
|
|
36
30
|
const description = agent.description ?? DEFAULT_AGENT_DESCRIPTIONS[agent.id];
|
|
37
31
|
const meta = agentMetaLabel(agent, {
|
|
38
32
|
authRequired: t('Authentication required'),
|
|
@@ -41,77 +35,8 @@ export function LocalCliAgentCard({ agent, config, selected, onSelect, onModelCh
|
|
|
41
35
|
notInstalled: t('Not installed'),
|
|
42
36
|
});
|
|
43
37
|
const summary = agentModelSummary(config, agent);
|
|
44
|
-
const { hasModels, reasoningOptions, hasReasoning, reasoningValue, reasoningDisabled, allowCustomModel, customActive, modelChoices, selectValue, customModelInputValue, resolveNextModelId, resolveReasoningModelId, } = useReasoningControl({
|
|
45
|
-
agent,
|
|
46
|
-
config,
|
|
47
|
-
explicitCustomMode,
|
|
48
|
-
onReasoningChange: (next) => onReasoningChange(agent.id, next),
|
|
49
|
-
});
|
|
50
|
-
// `modelsSource` is optional in the contract, so an absent value means the
|
|
51
|
-
// host did not say where the list came from — NOT that it came from a
|
|
52
|
-
// built-in fallback. Defaulting to 'fallback' rendered "Built-in list" over
|
|
53
|
-
// a list that may well be live, and told the operator to Rescan to fix a
|
|
54
|
-
// problem they do not have. Unknown provenance shows no badge and no claim.
|
|
55
|
-
const source = agent.modelsSource;
|
|
56
|
-
const sourceLabel = source === 'live' ? t('Live from CLI') : source === 'fallback' ? t('Built-in list') : '';
|
|
57
|
-
const sourceHint = source === 'live'
|
|
58
|
-
? t("Model list comes from this CLI. Default uses the CLI's own config.")
|
|
59
|
-
: source === 'fallback'
|
|
60
|
-
? t('Showing built-in defaults. Click Rescan to pull live models from the CLI.')
|
|
61
|
-
: '';
|
|
62
|
-
// The test result belongs to whichever agent was probed, so a stale verdict
|
|
63
|
-
// from a previously-tested CLI never renders under this one.
|
|
64
|
-
const testing = agentTest.status === 'testing' && agentTest.agentId === agent.id;
|
|
65
|
-
const result = (agentTest.status === 'ok' || agentTest.status === 'error') && agentTest.agentId === agent.id
|
|
66
|
-
? agentTest
|
|
67
|
-
: null;
|
|
68
|
-
// The "use the binary that actually ran" / "clear the override" repair
|
|
69
|
-
// affordance — only meaningful when a successful test silently fell back
|
|
70
|
-
// off a configured override, AND this agent's catalog names which field
|
|
71
|
-
// that override lives in. See `agentExecutableRepairState`'s doc.
|
|
72
|
-
//
|
|
73
|
-
// `AgentTestState`'s 'ok' variant spells success as `status: 'ok'`, not an
|
|
74
|
-
// `ok: true` field — `agentExecutableRepairState` takes the latter (it
|
|
75
|
-
// mirrors `ExecutionPort.testAgent`'s raw resolved shape, one layer below
|
|
76
|
-
// this state union), so the two must be translated explicitly here rather
|
|
77
|
-
// than passing `result` straight through.
|
|
78
|
-
const repair = result?.status === 'ok'
|
|
79
|
-
? agentExecutableRepairState({
|
|
80
|
-
ok: true,
|
|
81
|
-
usedExecutableSource: result.usedExecutableSource,
|
|
82
|
-
detectedExecutablePath: result.detectedExecutablePath,
|
|
83
|
-
})
|
|
84
|
-
: null;
|
|
85
|
-
const repairField = repair ? binPathEnvField(cliEnvFields, agent.id) : null;
|
|
86
|
-
const openUrl = (url) => {
|
|
87
|
-
if (!url)
|
|
88
|
-
return;
|
|
89
|
-
window.open(url, '_blank', 'noopener,noreferrer');
|
|
90
|
-
};
|
|
91
|
-
const diagnosticHandlers = {
|
|
92
|
-
onRescan,
|
|
93
|
-
onOpenInstall: agent.installUrl ? () => openUrl(agent.installUrl) : undefined,
|
|
94
|
-
onOpenDocs: agent.docsUrl ? () => openUrl(agent.docsUrl) : undefined,
|
|
95
|
-
};
|
|
96
38
|
return (_jsxs("div", { className: 'jini-agent-card' +
|
|
97
39
|
(selected ? ' is-selected' : '') +
|
|
98
|
-
(agent.installed ? ' is-installed' : ' is-missing'), "data-testid": `jini-agent-card-${agent.id}`, children: [_jsxs("div", { className: "jini-agent-card-main", children: [_jsxs("button", { type: "button", className: "jini-agent-card-select", "data-testid": `jini-agent-select-${agent.id}`, "aria-pressed": selected, disabled: !agent.installed, onClick: () => onSelect(agent.id), ...agentHandleProps({}, { base: agentHandle, ...({ action: 'select', role: 'button', label: agent.label }) }), children: [_jsx("span", { className: "jini-agent-card-icon", "aria-hidden": "true", children: renderIcon ? renderIcon(agent) : agent.label.slice(0, 1).toUpperCase() }), _jsxs("span", { className: "jini-agent-card-body", children: [_jsxs("span", { className: "jini-agent-card-name", children: [_jsx("span", { className: "jini-agent-card-title", children: agent.label }), description ? (
|
|
99
|
-
if (nextValue === CUSTOM_MODEL_SENTINEL) {
|
|
100
|
-
setExplicitCustomMode(true);
|
|
101
|
-
onModelChange(agent.id, '');
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
setExplicitCustomMode(false);
|
|
105
|
-
onModelChange(agent.id, resolveNextModelId(nextValue));
|
|
106
|
-
} })] }), sourceHint ? _jsx("p", { className: "jini-field-hint", children: sourceHint }) : null] })) : null, customActive ? (_jsxs("label", { className: "jini-field", children: [_jsx("span", { className: "jini-field-label", children: t('Custom model id') }), _jsx("input", { className: "jini-input", type: "text", "data-testid": `jini-agent-model-custom-${agent.id}`, value: customModelInputValue, placeholder: t('e.g. my-fine-tuned-model'), spellCheck: false, onChange: (event) => onModelChange(agent.id, event.target.value.trim()), ...agentHandleProps({}, { base: agentHandle, ...({ action: 'custom-model', role: 'field', label: t('Custom model id') }) }) })] })) : null, hasReasoning ? (_jsxs("label", { className: "jini-field", children: [_jsx("span", { className: "jini-field-label", children: t('Reasoning effort') }), _jsx("select", { className: "jini-input", "data-testid": `jini-agent-reasoning-${agent.id}`, value: reasoningValue, disabled: reasoningDisabled, onChange: (event) => {
|
|
107
|
-
// A model-suffix agent has no reasoning value of its own to record: the choice
|
|
108
|
-
// is which model id runs, so it goes back out through `onModelChange`.
|
|
109
|
-
const suffixModelId = resolveReasoningModelId(event.target.value);
|
|
110
|
-
if (suffixModelId !== null) {
|
|
111
|
-
onModelChange(agent.id, suffixModelId);
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
onReasoningChange(agent.id, event.target.value);
|
|
115
|
-
}, ...agentHandleProps({}, { base: agentHandle, ...({ action: 'reasoning', role: 'field', label: t('Reasoning effort') }) }), children: reasoningOptions.map((option) => (_jsx("option", { value: option.id, children: option.label }, option.id))) })] })) : null] })) : null, selected ? (_jsx(AgentCliEnvFields, { agentId: agent.id, fields: cliEnvFields, config: config, onChange: onEnvChange })) : null, result ? (_jsx("p", { className: 'jini-agent-card-test-result is-' + result.status, role: result.status === 'error' ? 'alert' : 'status', children: result.message ?? (result.status === 'ok' ? t('Agent is ready.') : t('Agent check failed')) })) : null, repair && repairField ? (_jsxs("div", { className: "jini-agent-card-path-repair", children: [_jsx("span", { className: "jini-field-hint", children: t('A custom path override did not work, so this used the automatically detected binary instead.') }), _jsxs("div", { className: "jini-agent-card-path-repair-actions", children: [repair.canUseDetected ? (_jsx("button", { type: "button", className: "jini-btn", "data-testid": `jini-agent-path-repair-use-${agent.id}`, onClick: () => onEnvChange(agent.id, repairField.envKey, repair.detectedPath), children: t('Use detected path') })) : null, _jsx("button", { type: "button", className: "jini-btn jini-btn-ghost", "data-testid": `jini-agent-path-repair-clear-${agent.id}`, onClick: () => onEnvChange(agent.id, repairField.envKey, ''), children: t('Clear custom path') })] })] })) : null] }));
|
|
40
|
+
(agent.installed ? ' is-installed' : ' is-missing'), "data-testid": `jini-agent-card-${agent.id}`, children: [_jsxs("div", { className: "jini-agent-card-main", children: [_jsxs("button", { type: "button", className: "jini-agent-card-select", "data-testid": `jini-agent-select-${agent.id}`, "aria-pressed": selected, disabled: !agent.installed, onClick: () => onSelect(agent.id), ...agentHandleProps({}, { base: agentHandle, ...({ action: 'select', role: 'button', label: agent.label }) }), children: [_jsx("span", { className: "jini-agent-card-icon", "aria-hidden": "true", children: renderIcon ? renderIcon(agent) : agent.label.slice(0, 1).toUpperCase() }), _jsxs("span", { className: "jini-agent-card-body", children: [_jsxs("span", { className: "jini-agent-card-name", children: [_jsx("span", { className: "jini-agent-card-title", children: agent.label }), description ? (_jsx("span", { className: "jini-agent-card-tagline", children: description })) : null] }), agent.badges?.length ? (_jsx("span", { className: "jini-agent-card-badges", children: agent.badges.map((badge) => (_jsx("span", { className: "jini-agent-card-badge", children: badge }, badge))) })) : null, meta.text ? (_jsx("span", { className: "jini-agent-card-meta", children: _jsx("span", { title: meta.title || undefined, children: meta.text }) })) : null, !selected && summary ? (_jsxs("span", { className: "jini-agent-card-model-summary", children: [_jsx("span", { children: t('Model') }), _jsx("strong", { children: summary })] })) : null] }), selected ? (_jsx("span", { className: "jini-agent-card-check", "aria-hidden": "true", children: "\u2713" })) : null] }), selected && onTest ? (_jsx("button", { type: "button", className: 'jini-btn jini-agent-card-test' + (card.testing ? ' is-loading' : ''), "data-testid": `jini-agent-test-${agent.id}`, disabled: card.testing, onClick: () => onTest(agent), ...agentHandleProps({}, { base: agentHandle, ...({ action: 'test', role: 'button', label: t('Test') }) }), children: card.testing ? t('Testing…') : t('Test') })) : null] }), (agent.diagnostics ?? []).map((diagnostic, index) => (_jsx(AgentDiagnosticRow, { diagnostic: diagnostic, handlers: card.diagnosticHandlers }, `${diagnostic.reason}-${index}`))), selected && card.hasSettings ? (_jsx(LocalCliAgentSettings, { agent: agent, config: config, card: card, cliEnvFields: cliEnvFields, onModelChange: onModelChange, onEnvChange: onEnvChange, agentHandle: agentHandle })) : null] }));
|
|
116
41
|
}
|
|
117
42
|
//# sourceMappingURL=LocalCliAgentCard.js.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
2
|
import type { AgentCliEnvFieldSpec, AgentScanState, AgentTestState, DetectedAgent, LocalCliConfig } from '../../types.js';
|
|
3
|
+
import { useLocalCliAgentList } from '../hooks/useLocalCliAgentList.js';
|
|
3
4
|
export interface LocalCliAgentListProps {
|
|
4
5
|
agents: readonly DetectedAgent[];
|
|
5
6
|
config: LocalCliConfig;
|
|
@@ -27,6 +28,8 @@ export interface LocalCliAgentListProps {
|
|
|
27
28
|
/** This list's own agent handle — see `ExecutionTab`'s `agentHandle` doc. Each card gets its own
|
|
28
29
|
* distinct sub-handle, derived from the agent's own stable id via `buildAgentListHandles`. */
|
|
29
30
|
agentHandle?: string;
|
|
31
|
+
/** Injection seam for the not-installed disclosure state. */
|
|
32
|
+
useAgentList?: typeof useLocalCliAgentList | undefined;
|
|
30
33
|
}
|
|
31
34
|
/**
|
|
32
35
|
* The detected code-agent CLIs, as a selectable card grid.
|
|
@@ -36,5 +39,5 @@ export interface LocalCliAgentListProps {
|
|
|
36
39
|
* managed-runtime entry (wallet, sign-in, plan upgrades) is left behind; see
|
|
37
40
|
* `LocalCliAgentCard` for what that split does and does not cover.
|
|
38
41
|
*/
|
|
39
|
-
export declare function LocalCliAgentList({ agents, config, scan, onSelect, onModelChange, onReasoningChange, onEnvChange, cliEnvFields, onRescan, onTest, agentTest, renderAgentIcon, scopeLabel, agentHandle, }: LocalCliAgentListProps): import("react").JSX.Element;
|
|
42
|
+
export declare function LocalCliAgentList({ agents, config, scan, onSelect, onModelChange, onReasoningChange, onEnvChange, cliEnvFields, onRescan, onTest, agentTest, renderAgentIcon, scopeLabel, agentHandle, useAgentList, }: LocalCliAgentListProps): import("react").JSX.Element;
|
|
40
43
|
//# sourceMappingURL=LocalCliAgentList.d.ts.map
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { jsxs as _jsxs,
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { agentHandleProps, buildAgentListHandles } from '@jini-ai/agentic';
|
|
3
3
|
import { useT } from '../../../i18n/index.js';
|
|
4
4
|
import { LocalCliAgentCard } from './LocalCliAgentCard.js';
|
|
5
|
+
import { useLocalCliAgentList } from '../hooks/useLocalCliAgentList.js';
|
|
5
6
|
/**
|
|
6
7
|
* The detected code-agent CLIs, as a selectable card grid.
|
|
7
8
|
*
|
|
@@ -10,11 +11,19 @@ import { LocalCliAgentCard } from './LocalCliAgentCard.js';
|
|
|
10
11
|
* managed-runtime entry (wallet, sign-in, plan upgrades) is left behind; see
|
|
11
12
|
* `LocalCliAgentCard` for what that split does and does not cover.
|
|
12
13
|
*/
|
|
13
|
-
export function LocalCliAgentList({ agents, config, scan, onSelect, onModelChange, onReasoningChange, onEnvChange, cliEnvFields, onRescan, onTest, agentTest, renderAgentIcon, scopeLabel, agentHandle, }) {
|
|
14
|
+
export function LocalCliAgentList({ agents, config, scan, onSelect, onModelChange, onReasoningChange, onEnvChange, cliEnvFields, onRescan, onTest, agentTest, renderAgentIcon, scopeLabel, agentHandle, useAgentList = useLocalCliAgentList, }) {
|
|
14
15
|
const t = useT();
|
|
15
16
|
const installed = agents.filter((agent) => agent.installed);
|
|
16
17
|
const scope = scopeLabel ?? t('Runs a code-agent CLI detected by the host.');
|
|
17
|
-
const
|
|
18
|
-
|
|
18
|
+
const handleList = agentHandle ? buildAgentListHandles({ prefix: agentHandle, ids: agents.map((agent) => agent.id) }) : undefined;
|
|
19
|
+
const cardHandles = new Map(agents.map((agent, index) => [agent.id, handleList?.[index]]));
|
|
20
|
+
const list = useAgentList({ agents, selectedAgentId: config.agentId });
|
|
21
|
+
const renderCard = (agent) => {
|
|
22
|
+
const handle = cardHandles.get(agent.id);
|
|
23
|
+
return (_jsx(LocalCliAgentCard, { agent: agent, config: config, selected: config.agentId === agent.id, onSelect: onSelect, onModelChange: onModelChange, onReasoningChange: onReasoningChange, onEnvChange: onEnvChange, cliEnvFields: cliEnvFields, renderIcon: renderAgentIcon, onTest: onTest, agentTest: agentTest, onRescan: onRescan, ...(handle ? { agentHandle: handle } : {}) }, agent.id));
|
|
24
|
+
};
|
|
25
|
+
return (_jsxs("section", { className: "jini-settings-section jini-local-cli", children: [_jsxs("div", { className: "jini-section-head", children: [_jsxs("div", { className: "jini-section-head-text", children: [_jsxs("h4", { className: "jini-agent-group-head", children: [t('Your CLIs'), " (", installed.length, ")"] }), _jsx("p", { className: "jini-field-hint", children: t('Pick the CLI that runs your prompts.') })] }), onRescan ? (_jsx("button", { type: "button", className: "jini-btn jini-local-cli-rescan", disabled: scan.status === 'scanning', onClick: onRescan, ...agentHandleProps({}, { base: agentHandle, ...({ action: 'rescan', role: 'button', label: t('Rescan') }) }), children: scan.status === 'scanning' ? t('Scanning…') : t('↻ Rescan') })) : null] }), _jsx("p", { className: "jini-field-hint jini-local-cli-scope", children: scope }), scan.status === 'error' ? (_jsx("p", { className: "jini-field-hint is-error", role: "alert", children: scan.message })) : null, scan.status === 'scanning' ? (_jsxs("div", { className: "jini-agent-scan-card", role: "status", "aria-live": "polite", children: [_jsx("span", { className: "jini-agent-scan-ring", "aria-hidden": "true" }), _jsx("strong", { children: t('Scanning for installed agents…') })] })) : agents.length === 0 ? (scan.status === 'error' ? null : (_jsx("div", { className: "jini-empty-card", children: t('No agent CLIs detected.') }))) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "jini-agent-grid", children: list.visible.map(renderCard) }), list.collapsed.length > 0 ? (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", className: "jini-btn jini-local-cli-more", "aria-expanded": list.showCollapsed, onClick: list.toggleCollapsed, ...agentHandleProps({}, { base: agentHandle, ...({ action: 'toggle-not-installed', role: 'button', label: t('Show not-installed CLIs') }) }), children: list.showCollapsed
|
|
26
|
+
? t('Hide not installed')
|
|
27
|
+
: t('Show {count} not installed').replace('{count}', String(list.collapsed.length)) }), list.showCollapsed ? _jsx("div", { className: "jini-agent-grid", children: list.collapsed.map(renderCard) }) : null] })) : null] }))] }));
|
|
19
28
|
}
|
|
20
29
|
//# sourceMappingURL=LocalCliAgentList.js.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AgentCliEnvFieldSpec, DetectedAgent, LocalCliConfig } from '../../types.js';
|
|
2
|
+
import type { UseLocalCliAgentCardResult } from '../hooks/useLocalCliAgentCard.js';
|
|
3
|
+
export interface LocalCliAgentSettingsProps {
|
|
4
|
+
agent: DetectedAgent;
|
|
5
|
+
config: LocalCliConfig;
|
|
6
|
+
card: UseLocalCliAgentCardResult;
|
|
7
|
+
cliEnvFields: readonly AgentCliEnvFieldSpec[];
|
|
8
|
+
onModelChange: (agentId: string, model: string) => void;
|
|
9
|
+
onEnvChange: (agentId: string, envKey: string, value: string) => void;
|
|
10
|
+
agentHandle?: string | undefined;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The selected CLI's settings, stacked inside its own card.
|
|
14
|
+
*
|
|
15
|
+
* Owner, 2026-10-09: both the full-row card and the separate settings strip
|
|
16
|
+
* spread selection beyond its own column. Keep full-width controls and a
|
|
17
|
+
* visible provenance sentence inside the card so only that card grows taller.
|
|
18
|
+
*/
|
|
19
|
+
export declare function LocalCliAgentSettings({ agent, config, card, cliEnvFields, onModelChange, onEnvChange, agentHandle, }: LocalCliAgentSettingsProps): import("react").JSX.Element;
|
|
20
|
+
//# sourceMappingURL=LocalCliAgentSettings.d.ts.map
|