@kortix/ui 0.14.5 → 0.14.7
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/_vendor/kortix-shared.js +489 -381
- package/dist/access/access/access-dialog.js +8 -5
- package/dist/access/access/copy-row.js +2 -2
- package/dist/access/sharing-picker.js +2 -1
- package/dist/browser/app-in-browser.js +5 -3
- package/dist/browser/browser-panel.js +6 -6
- package/dist/browser/sandbox-browser-chrome.d.ts +4 -1
- package/dist/browser/sandbox-browser-chrome.js +4 -3
- package/dist/customize/agents/agent-access.d.ts +20 -0
- package/dist/customize/agents/agent-access.js +17 -0
- package/dist/customize/agents/agent-authority-card.js +1 -2
- package/dist/customize/agents/agent-detail-aside.js +15 -14
- package/dist/customize/agents/agent-drives-section.js +5 -6
- package/dist/customize/agents/agent-grant-pages.js +73 -76
- package/dist/customize/agents/agent-nav.prototype.d.ts +35 -0
- package/dist/customize/agents/agent-nav.prototype.js +95 -0
- package/dist/customize/agents/agent-page.js +59 -23
- package/dist/customize/agents/agent-people-section.js +18 -17
- package/dist/customize/agents/agent-triggers-section.js +6 -5
- package/dist/customize/agents/agents-page.js +18 -1
- package/dist/customize/connectors/add-mcp/add-mcp-server.js +4 -2
- package/dist/customize/connectors/catalog/catalog-entry.d.ts +14 -0
- package/dist/customize/connectors/catalog/catalog-entry.js +18 -1
- package/dist/customize/connectors/catalog/connector-browse.d.ts +28 -0
- package/dist/customize/connectors/catalog/connector-browse.js +18 -5
- package/dist/customize/connectors/connector-routes.d.ts +3 -1
- package/dist/customize/connectors/connector-routes.js +18 -0
- package/dist/customize/connectors/connectors-page.js +23 -4
- package/dist/customize/connectors/detail/app-page.js +19 -5
- package/dist/customize/connectors/detail/connector-advanced-tools.js +4 -6
- package/dist/customize/connectors/detail/connector-modal.d.ts +10 -13
- package/dist/customize/connectors/detail/connector-modal.js +18 -101
- package/dist/customize/connectors/detail/connector-notice.js +6 -2
- package/dist/customize/connectors/detail/connector-page.d.ts +30 -0
- package/dist/customize/connectors/detail/connector-page.js +26 -13
- package/dist/customize/providers/provider-accordion.js +2 -1
- package/dist/customize/providers/provider-connect.js +2 -1
- package/dist/customize/sections/component/telegram-channel-row.js +1 -1
- package/dist/customize/sections/connector-connection-modal.js +11 -9
- package/dist/customize/sections/connectors-view.js +11 -13
- package/dist/customize/sections/llm-provider/custom-provider-form.js +24 -7
- package/dist/customize/sections/llm-provider/custom-provider-panel.js +44 -8
- package/dist/customize/sections/llm-provider/types.d.ts +3 -0
- package/dist/customize/sections/llm-provider/utils.js +2 -2
- package/dist/customize/sections/view/agent-editor-access-fields.d.ts +9 -16
- package/dist/customize/sections/view/agent-editor-access-fields.js +30 -30
- package/dist/customize/sections/view/agent-editor-basics-fields.js +3 -10
- package/dist/customize/sections/view/agent-editor-primitives.d.ts +28 -10
- package/dist/customize/sections/view/agent-editor-primitives.js +32 -19
- package/dist/customize/sections/view/agent-editor.js +3 -3
- package/dist/customize/sections/view/gateway/gateway-routing.js +18 -21
- package/dist/customize/sections/view/grant-mode-field.d.ts +2 -5
- package/dist/customize/sections/view/grant-mode-field.js +10 -18
- package/dist/customize/sections/view/permission-editor.js +11 -8
- package/dist/customize/sections/view/secrets-view.js +2 -1
- package/dist/customize/settings/rail-copy-context.js +5 -3
- package/dist/customize/settings/tabs/general-tab.d.ts +9 -2
- package/dist/customize/settings/tabs/general-tab.js +33 -11
- package/dist/customize/settings/tabs/sandbox-template-form.js +9 -12
- package/dist/customize/settings/tabs/transfer-workspace-dialog.d.ts +4 -0
- package/dist/customize/settings/tabs/transfer-workspace-dialog.js +82 -0
- package/dist/customize/shared/capability-tabs.js +2 -1
- package/dist/customize/skills/skills-page.js +3 -5
- package/dist/customize/triggers/schedule/event-trigger-copy.js +3 -2
- package/dist/customize/triggers/schedule/schedule-builder.js +7 -4
- package/dist/customize/triggers/schedule/trigger-composer.js +5 -2
- package/dist/customize/triggers/schedule/when-event.js +1 -1
- package/dist/diff/diff-view.js +9 -10
- package/dist/files/editor/code-editor.js +2 -3
- package/dist/files/project/api/runtime-files.js +3 -2
- package/dist/files/project/components/change-request-detail-dialog.d.ts +3 -1
- package/dist/files/project/components/change-request-detail-dialog.js +3 -5
- package/dist/files/project/components/change-request-status-badge.d.ts +12 -0
- package/dist/files/project/components/change-request-status-badge.js +27 -0
- package/dist/files/project/components/change-requests-panel.js +1 -1
- package/dist/files/project/components/drive-explorer.js +2 -1
- package/dist/files/project/components/drive-grid-view.js +11 -7
- package/dist/files/project/components/drive-list-view.js +4 -4
- package/dist/files/project/components/file-breadcrumbs.js +1 -1
- package/dist/files/project/components/file-explorer-page.js +1 -1
- package/dist/files/project/components/file-history-popover.js +1 -6
- package/dist/files/project/components/file-search.js +6 -1
- package/dist/files/project/components/open-change-request-dialog.js +2 -1
- package/dist/files/project/components/version-selector-logic.d.ts +11 -0
- package/dist/files/project/components/version-selector-logic.js +26 -0
- package/dist/files/project/components/version-selector.js +11 -20
- package/dist/files/project/file-source.js +18 -1
- package/dist/files/project/hooks/use-file-content.js +2 -0
- package/dist/files/project/hooks/use-server-health.js +17 -15
- package/dist/files/renderers/docx/docx-viewer.js +0 -5
- package/dist/files/renderers/image-renderer.js +6 -24
- package/dist/files/renderers/pdf/pdf-viewer.js +1 -1
- package/dist/files/renderers/presentation/FullScreenPresentationViewer.js +2 -11
- package/dist/files/renderers/show-content-renderer.js +1 -1
- package/dist/files/renderers/sqlite-renderer.js +8 -3
- package/dist/files/renderers/xlsx/xlsx-viewer.js +15 -16
- package/dist/files/tree/components/file-tree-item.js +1 -1
- package/dist/files/viewer/file-header.js +1 -1
- package/dist/files/viewer/file-preview-modal.d.ts +1 -1
- package/dist/files/viewer/file-preview-modal.js +13 -3
- package/dist/files/viewer/file-source.d.ts +3 -1
- package/dist/files/viewer/use-file-content-state.js +27 -8
- package/dist/files/viewer/viewer-actions.js +2 -2
- package/dist/i18n/en.d.ts +355 -12
- package/dist/i18n/en.js +360 -17
- package/dist/internal/desktop/desktop-back-button.js +5 -3
- package/dist/internal/files/types.d.ts +2 -0
- package/dist/internal/goals/goal-meta.d.ts +30 -0
- package/dist/internal/goals/goal-meta.js +55 -0
- package/dist/internal/hooks/use-auto-scroll.js +5 -3
- package/dist/internal/lib/query-client-singleton.d.ts +9 -3
- package/dist/internal/lib/query-client-singleton.js +18 -12
- package/dist/internal/notifications/notification-rows.js +2 -1
- package/dist/internal/outcomes/outcome-types.d.ts +5 -0
- package/dist/internal/share/session-shares-modal.js +3 -7
- package/dist/internal/stores/kortix-computer-store.js +14 -2
- package/dist/internal/stores/session-hover-store.d.ts +32 -0
- package/dist/internal/stores/session-hover-store.js +38 -0
- package/dist/internal/stores/sidebar-nav-store.d.ts +1 -1
- package/dist/internal/stores/sidebar-nav-store.js +3 -1
- package/dist/lib/routes.d.ts +2 -0
- package/dist/lib/routes.js +1 -0
- package/dist/markdown/code/inline-code.js +8 -0
- package/dist/markdown/code/output-paths-context.d.ts +18 -0
- package/dist/markdown/code/output-paths-context.js +35 -0
- package/dist/markdown/genui/components/charts.js +6 -5
- package/dist/primitives/map.js +2 -1
- package/dist/primitives/preview-image.js +4 -2
- package/dist/primitives/settings-section-header.d.ts +1 -1
- package/dist/primitives/textarea.js +1 -1
- package/dist/primitives/typed-title.js +12 -14
- package/dist/primitives/typing-animation.js +4 -2
- package/dist/session/composer/agent-selector.js +6 -1
- package/dist/session/composer/attachment-tile.d.ts +0 -2
- package/dist/session/composer/attachment-tile.js +0 -8
- package/dist/session/composer/clipboard-files.d.ts +2 -1
- package/dist/session/composer/composer-chat-input.js +5 -3
- package/dist/session/composer/composer-draft-recovery.d.ts +1 -2
- package/dist/session/composer/composer-draft-recovery.js +0 -13
- package/dist/session/composer/composer-logic.js +8 -7
- package/dist/session/composer/context-ring.d.ts +1 -1
- package/dist/session/composer/context-ring.js +2 -2
- package/dist/session/composer/context-usage.d.ts +3 -6
- package/dist/session/composer/context-usage.js +3 -6
- package/dist/session/composer/draft/composer-draft.js +4 -4
- package/dist/session/composer/inbox-row-claims.d.ts +2 -2
- package/dist/session/composer/inbox-row-claims.js +1 -1
- package/dist/session/composer/pasted-text.js +3 -2
- package/dist/session/composer/queue-projection.d.ts +3 -2
- package/dist/session/composer/queued-prompt-edit.d.ts +1 -1
- package/dist/session/composer/reasoning-effort-selector.d.ts +2 -1
- package/dist/session/composer/session-composer-readiness.d.ts +7 -22
- package/dist/session/composer/session-composer-readiness.js +12 -40
- package/dist/session/composer/stores/queued-draft-store.js +3 -2
- package/dist/session/composer/token-progress.d.ts +1 -1
- package/dist/session/composer/token-progress.js +2 -2
- package/dist/session/header/reminder-parts.d.ts +11 -2
- package/dist/session/header/reminder-parts.js +9 -4
- package/dist/session/header/session-goal-indicator.d.ts +1 -0
- package/dist/session/header/session-goal-indicator.js +41 -0
- package/dist/session/header/session-site-header.js +2 -1
- package/dist/session/media/sandbox-url-detector.js +0 -7
- package/dist/session/outcomes/change-request-outcomes.js +24 -3
- package/dist/session/overrides/provider-secret-pool-editor.js +2 -1
- package/dist/session/panel/advanced/advanced-panel.js +3 -7
- package/dist/session/panel/easy/app-preview.js +12 -2
- package/dist/session/panel/easy/easy-panel-logic.d.ts +1 -1
- package/dist/session/panel/easy/easy-panel-logic.js +1 -1
- package/dist/session/panel/easy/outputs-card.js +2 -1
- package/dist/session/panel/easy/panel-card.js +5 -3
- package/dist/session/panel/easy/preview-load.d.ts +14 -0
- package/dist/session/panel/easy/preview-load.js +15 -0
- package/dist/session/panel/easy/step-detail-body.js +2 -7
- package/dist/session/panel/session-action-panel-column.js +11 -1
- package/dist/session/panel/session-audit-shared.d.ts +0 -4
- package/dist/session/panel/session-audit-shared.js +1 -1
- package/dist/session/panel/session-changes-shared.d.ts +2 -1
- package/dist/session/panel/session-panel-provider.js +6 -2
- package/dist/session/panel/shared/use-panel-derivations.js +6 -4
- package/dist/session/panel/use-session-panel-layout.js +7 -5
- package/dist/session/print/session-print-header.js +9 -8
- package/dist/session/prompts/session-permission-prompt.js +6 -3
- package/dist/session/status/provisioning-failure.d.ts +2 -1
- package/dist/session/status/session-error-banner.js +8 -6
- package/dist/session/status/session-starting-loader.d.ts +24 -31
- package/dist/session/status/session-starting-loader.js +32 -81
- package/dist/session/thread/chat-minimap-items.d.ts +4 -4
- package/dist/session/thread/first-prompt-handover.d.ts +3 -2
- package/dist/session/thread/message-parsing.d.ts +3 -3
- package/dist/session/thread/session-chat.js +15 -19
- package/dist/session/thread/session-history-scroll.d.ts +2 -1
- package/dist/session/thread/session-history.js +3 -1
- package/dist/session/thread/session-thread.js +1 -1
- package/dist/session/thread/transcript.js +13 -7
- package/dist/session/tool/shared/file-list.js +19 -2
- package/dist/session/tool/shared/infrastructure-contexts.d.ts +7 -0
- package/dist/session/tool/shared/infrastructure-contexts.js +7 -0
- package/dist/session/tool/shared/infrastructure-output.js +9 -5
- package/dist/session/tool/shared/infrastructure-row-header.js +9 -1
- package/dist/session/tool/shared/infrastructure-rows.js +7 -5
- package/dist/session/tool/tools/bash-tool.js +10 -6
- package/dist/session/tool/tools/web-search-tool.js +25 -3
- package/dist/session/turn/recovered-failures.d.ts +8 -0
- package/dist/session/turn/recovered-failures.js +32 -0
- package/dist/session/turn/streaming-cadence.js +5 -8
- package/dist/styles.css +1 -1
- package/dist/terminal/pty-connection.d.ts +5 -4
- package/dist/terminal/session-terminal-panel.js +3 -5
- package/dist/theme/theme.js +2 -1
- package/dist/workspace/index.d.ts +1 -0
- package/dist/workspace/index.js +1 -0
- package/dist/workspace/projects/modal/github-import-pickers.js +7 -6
- package/dist/workspace/review/review-center.js +13 -10
- package/dist/workspace/saved-session-skeleton-shape.d.ts +4 -3
- package/dist/workspace/saved-session-skeleton.d.ts +5 -1
- package/dist/workspace/saved-session-skeleton.js +5 -4
- package/dist/workspace/session-workspace.js +9 -14
- package/dist/workspace/sessions/deleted-session-row.js +5 -2
- package/dist/workspace/sidebar/footer/project-computer-nav.js +6 -4
- package/dist/workspace/sidebar/footer/project-goals-nav.d.ts +6 -0
- package/dist/workspace/sidebar/footer/project-goals-nav.js +26 -0
- package/dist/workspace/sidebar/footer/project-mcp-nav.js +6 -2
- package/dist/workspace/sidebar/modal/rename-session-modal.js +8 -3
- package/dist/workspace/sidebar/modal/session-embed-section.d.ts +25 -0
- package/dist/workspace/sidebar/modal/session-embed-section.js +71 -0
- package/dist/workspace/sidebar/modal/share-session-modal.js +2 -2
- package/dist/workspace/sidebar/nav-row-meta.js +14 -2
- package/dist/workspace/sidebar/project-nav-items.js +3 -0
- package/dist/workspace/sidebar/project-session-list.js +12 -3
- package/dist/workspace/sidebar/session-brief-hover-card.js +5 -8
- package/package.json +4 -4
- package/skills/kortix-ui/references/modules.md +2 -0
- package/dist/session/status/use-readiness-settling.d.ts +0 -18
- package/dist/session/status/use-readiness-settling.js +0 -43
- package/dist/workspace/sidebar/modal/session-public-link-section.d.ts +0 -13
- package/dist/workspace/sidebar/modal/session-public-link-section.js +0 -66
|
@@ -421,14 +421,16 @@ function EmailSenderPolicyEditor({ projectId, connectorSlug, policy, canWrite =
|
|
|
421
421
|
const [domains, setDomains] = useState(() => initial.allowedDomains.join('\n'));
|
|
422
422
|
const [regex, setRegex] = useState(initial.allowedRegex ?? '');
|
|
423
423
|
const [error, setError] = useState(null);
|
|
424
|
-
|
|
424
|
+
const [syncedPolicy, setSyncedPolicy] = useState(policy);
|
|
425
|
+
if (policy !== syncedPolicy) {
|
|
426
|
+
setSyncedPolicy(policy);
|
|
425
427
|
const next = normalizeEmailSenderPolicy(policy);
|
|
426
428
|
setRestricted(next.mode === 'restricted');
|
|
427
429
|
setEmails(next.allowedEmails.join('\n'));
|
|
428
430
|
setDomains(next.allowedDomains.join('\n'));
|
|
429
431
|
setRegex(next.allowedRegex ?? '');
|
|
430
432
|
setError(null);
|
|
431
|
-
}
|
|
433
|
+
}
|
|
432
434
|
const nextPolicy = () => ({
|
|
433
435
|
mode: restricted ? 'restricted' : 'allow_all',
|
|
434
436
|
allowedEmails: splitPolicyList(emails),
|
|
@@ -948,17 +950,13 @@ export function CustomConnectorForm({ projectId, emailChannelEnabled, onAdded, }
|
|
|
948
950
|
const timer = window.setTimeout(() => setDiscoveryDraft(draft), 400);
|
|
949
951
|
return () => window.clearTimeout(timer);
|
|
950
952
|
}, [draft]);
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
if (draft.provider === 'channel' && oauth2Selected) {
|
|
959
|
-
setOauth2Selected(false);
|
|
960
|
-
}
|
|
961
|
-
}, [draft.provider, oauth2Selected]);
|
|
953
|
+
if (!emailChannelEnabled && draft.provider === 'channel' && draft.platform === 'email') {
|
|
954
|
+
setDraft((current) => ({ ...current, platform: 'slack' }));
|
|
955
|
+
}
|
|
956
|
+
// Channel connectors have no OAuth2-at-creation offer.
|
|
957
|
+
if (draft.provider === 'channel' && oauth2Selected) {
|
|
958
|
+
setOauth2Selected(false);
|
|
959
|
+
}
|
|
962
960
|
const save = useCreateCustomConnector(projectId, onAdded);
|
|
963
961
|
const discovery = useQuery({
|
|
964
962
|
queryKey: ['connector-auth-discovery', projectId, discoveryDraft],
|
|
@@ -6,6 +6,7 @@ import { InfoBanner } from '../../../primitives/info-banner.js';
|
|
|
6
6
|
import { Input } from '../../../primitives/input.js';
|
|
7
7
|
import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, } from '../../../primitives/input-group.js';
|
|
8
8
|
import Loading from '../../../primitives/loading.js';
|
|
9
|
+
import { Switch } from '../../../primitives/switch.js';
|
|
9
10
|
import { successToast } from '../../../primitives/toast.js';
|
|
10
11
|
import { useTranslations } from '../../../i18n/index.js';
|
|
11
12
|
import { upsertProjectSecret } from '@kortix/sdk';
|
|
@@ -52,7 +53,12 @@ export function CustomProviderForm({ projectId, initialId = '', onSaved, }) {
|
|
|
52
53
|
const name = form.name.trim();
|
|
53
54
|
const baseUrl = form.baseURL.trim();
|
|
54
55
|
const apiKey = form.apiKey.trim();
|
|
55
|
-
const model = {
|
|
56
|
+
const model = {
|
|
57
|
+
id: form.modelId.trim(),
|
|
58
|
+
name: form.modelName.trim(),
|
|
59
|
+
...(form.attachment !== undefined ? { attachment: form.attachment } : {}),
|
|
60
|
+
...(form.reasoning !== undefined ? { reasoning: form.reasoning } : {}),
|
|
61
|
+
};
|
|
56
62
|
if (!providerId || !name || !baseUrl) {
|
|
57
63
|
throw new Error('Provider ID, name, and base URL are required');
|
|
58
64
|
}
|
|
@@ -69,11 +75,7 @@ export function CustomProviderForm({ projectId, initialId = '', onSaved, }) {
|
|
|
69
75
|
throw new Error('Model ID cannot contain spaces');
|
|
70
76
|
}
|
|
71
77
|
const existing = custom.providers.find((p) => p.id === providerId && p.configured);
|
|
72
|
-
|
|
73
|
-
name,
|
|
74
|
-
base_url: baseUrl,
|
|
75
|
-
models: [...(existing?.models ?? []).filter((m) => m.id !== model.id), model],
|
|
76
|
-
});
|
|
78
|
+
// The key first: saving the endpoint reads its `GET /models` for each model's limits.
|
|
77
79
|
if (apiKey) {
|
|
78
80
|
// LLM provider credentials are always project-wide (see
|
|
79
81
|
// api-key-connect-form.tsx) — a per-user key is invisible to the
|
|
@@ -85,6 +87,21 @@ export function CustomProviderForm({ projectId, initialId = '', onSaved, }) {
|
|
|
85
87
|
consumer: 'llm_gateway',
|
|
86
88
|
});
|
|
87
89
|
}
|
|
90
|
+
await custom.save(providerId, {
|
|
91
|
+
name,
|
|
92
|
+
base_url: baseUrl,
|
|
93
|
+
models: [
|
|
94
|
+
...(existing?.models ?? [])
|
|
95
|
+
.filter((m) => m.id !== model.id)
|
|
96
|
+
.map(({ id, name, attachment, reasoning }) => ({
|
|
97
|
+
id,
|
|
98
|
+
name,
|
|
99
|
+
...(attachment !== undefined ? { attachment } : {}),
|
|
100
|
+
...(reasoning !== undefined ? { reasoning } : {}),
|
|
101
|
+
})),
|
|
102
|
+
model,
|
|
103
|
+
],
|
|
104
|
+
});
|
|
88
105
|
return providerId;
|
|
89
106
|
},
|
|
90
107
|
onSuccess: (providerId) => {
|
|
@@ -110,5 +127,5 @@ export function CustomProviderForm({ projectId, initialId = '', onSaved, }) {
|
|
|
110
127
|
// app — a pasted key used to sit in plaintext on screen.
|
|
111
128
|
type: revealKey ? 'text' : 'password', autoComplete: "off", spellCheck: false, "data-1p-ignore": "", "data-lpignore": "true", "data-form-type": "other", value: form.apiKey, onChange: (e) => setField('apiKey', e.target.value), placeholder: tI18nComplete.raw('textb009c6c5299f'), className: "font-mono font-normal" }), form.apiKey ? (_jsx(InputGroupAddon, { align: "inline-end", children: _jsx(InputGroupButton, { size: "icon-xs", onClick: () => setRevealKey((current) => !current), title: revealKey ? 'Hide' : 'Show', "aria-label": revealKey
|
|
112
129
|
? tI18nComplete.raw('text3d0d8c59beb7')
|
|
113
|
-
: tI18nComplete.raw('textcb0b50a0d111'), "aria-pressed": revealKey, className: "text-muted-foreground hover:text-foreground", children: revealKey ? _jsx(EyeSlash, { className: "size-3.5" }) : _jsx(Eye, { className: "size-3.5" }) }) })) : null] }), form.providerId.trim() ? (_jsx("code", { className: "text-muted-foreground font-mono text-xs break-all", children: customProviderSecretName(form.providerId) })) : null] }), _jsxs("div", { className: "flex gap-3", children: [_jsx(FormField, { htmlFor: "custom-model-id", label: tI18nComplete.raw('text089ef2b6dbb3'), children: _jsx(Input, { id: "custom-model-id", type: "text", value: form.modelId, onChange: (e) => setField('modelId', e.target.value), placeholder: tI18nComplete.raw('text34d316295094'), className: "font-mono font-normal" }) }), _jsx(FormField, { htmlFor: "custom-model-name", label: tI18nComplete.raw('texta3c3370cc732'), children: _jsx(Input, { id: "custom-model-name", type: "text", value: form.modelName, onChange: (e) => setField('modelName', e.target.value), placeholder: tI18nComplete.raw('textb70354a1faae'), className: "font-normal" }) })] }), error ? (_jsx(InfoBanner, { tone: "destructive", icon: TriangleAlert, title: tI18nComplete.raw('text464de08899db'), children: error })) : null, _jsx("div", { className: "flex gap-2 pt-1", children: _jsx(Button, { type: "submit", size: "sm", disabled: save.isPending, className: "gap-1.5", children: save.isPending ? (_jsxs(_Fragment, { children: [_jsx(Loading, { className: "size-3.5 shrink-0" }), t('saving')] })) : (t('saveProvider')) }) })] }) }) }));
|
|
130
|
+
: tI18nComplete.raw('textcb0b50a0d111'), "aria-pressed": revealKey, className: "text-muted-foreground hover:text-foreground", children: revealKey ? _jsx(EyeSlash, { className: "size-3.5" }) : _jsx(Eye, { className: "size-3.5" }) }) })) : null] }), form.providerId.trim() ? (_jsx("code", { className: "text-muted-foreground font-mono text-xs break-all", children: customProviderSecretName(form.providerId) })) : null] }), _jsxs("div", { className: "flex gap-3", children: [_jsx(FormField, { htmlFor: "custom-model-id", label: tI18nComplete.raw('text089ef2b6dbb3'), children: _jsx(Input, { id: "custom-model-id", type: "text", value: form.modelId, onChange: (e) => setField('modelId', e.target.value), placeholder: tI18nComplete.raw('text34d316295094'), className: "font-mono font-normal" }) }), _jsx(FormField, { htmlFor: "custom-model-name", label: tI18nComplete.raw('texta3c3370cc732'), children: _jsx(Input, { id: "custom-model-name", type: "text", value: form.modelName, onChange: (e) => setField('modelName', e.target.value), placeholder: tI18nComplete.raw('textb70354a1faae'), className: "font-normal" }) })] }), _jsxs(Field, { className: "gap-2", children: [_jsxs("div", { className: "text-foreground flex flex-wrap items-center gap-x-5 gap-y-2 text-sm", children: [_jsxs("label", { className: "flex items-center gap-2", children: [_jsx(Switch, { checked: form.attachment === true, onCheckedChange: (attachment) => setField('attachment', attachment) }), t('readsImages')] }), _jsxs("label", { className: "flex items-center gap-2", children: [_jsx(Switch, { checked: form.reasoning === true, onCheckedChange: (reasoning) => setField('reasoning', reasoning) }), t('reasoning')] })] }), _jsx(FieldDescription, { children: t('traitsHint') })] }), error ? (_jsx(InfoBanner, { tone: "destructive", icon: TriangleAlert, title: tI18nComplete.raw('text464de08899db'), children: error })) : null, _jsx("div", { className: "flex gap-2 pt-1", children: _jsx(Button, { type: "submit", size: "sm", disabled: save.isPending, className: "gap-1.5", children: save.isPending ? (_jsxs(_Fragment, { children: [_jsx(Loading, { className: "size-3.5 shrink-0" }), t('saving')] })) : (t('saveProvider')) }) })] }) }) }));
|
|
114
131
|
}
|
|
@@ -36,6 +36,7 @@ import { Input } from '../../../primitives/input.js';
|
|
|
36
36
|
import { InputGroup, InputGroupInput } from '../../../primitives/input-group.js';
|
|
37
37
|
import Loading from '../../../primitives/loading.js';
|
|
38
38
|
import { Skeleton } from '../../../primitives/skeleton.js';
|
|
39
|
+
import { Switch } from '../../../primitives/switch.js';
|
|
39
40
|
import { SplitSheetBody, SplitSheetDescription, SplitSheetFooter, SplitSheetHeader, SplitSheetTitle, } from '../../../primitives/split-sheet.js';
|
|
40
41
|
import { errorToast, successToast } from '../../../primitives/toast.js';
|
|
41
42
|
import { ProviderLogoStatus } from '../../providers/provider-connect.js';
|
|
@@ -46,6 +47,7 @@ import { CaretRightIcon, XIcon } from '@phosphor-icons/react';
|
|
|
46
47
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
47
48
|
import { useModelsPageSheet } from '../models-page-sheet.js';
|
|
48
49
|
import { CustomProviderForm } from './custom-provider-form.js';
|
|
50
|
+
import { formatTokenCount } from './utils.js';
|
|
49
51
|
/** One saved custom provider: a configured row opens the sheet, a legacy row
|
|
50
52
|
* pre-fills the form. */
|
|
51
53
|
export function CustomProviderRow({ provider, selected, onSelect, }) {
|
|
@@ -57,6 +59,22 @@ export function CustomProviderRow({ provider, selected, onSelect, }) {
|
|
|
57
59
|
function DetailRow({ label, value, mono = true }) {
|
|
58
60
|
return (_jsxs("div", { className: "flex min-h-10 items-center justify-between gap-4 py-2", children: [_jsx("span", { className: "text-muted-foreground shrink-0 text-sm", children: label }), _jsx("span", { className: cn('text-foreground min-w-0 truncate', mono ? 'font-mono text-xs' : 'text-sm'), children: value })] }));
|
|
59
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* A model as the PUT takes it: the switches travel, the limits do not, so
|
|
64
|
+
* every save reads the window again from the endpoint's `GET /models`.
|
|
65
|
+
*/
|
|
66
|
+
const modelInput = ({ id, name, attachment, reasoning }) => ({
|
|
67
|
+
id,
|
|
68
|
+
name,
|
|
69
|
+
...(attachment !== undefined ? { attachment } : {}),
|
|
70
|
+
...(reasoning !== undefined ? { reasoning } : {}),
|
|
71
|
+
});
|
|
72
|
+
/** One saved model: its window, and the image and reasoning switches (each saves at once). */
|
|
73
|
+
function ModelRow({ model, disabled, onToggle, }) {
|
|
74
|
+
const t = useTranslations('customProvider');
|
|
75
|
+
const context = formatTokenCount(model.context);
|
|
76
|
+
return (_jsxs("div", { className: "space-y-2 py-2", children: [_jsxs("div", { className: "flex min-h-6 items-center justify-between gap-4", children: [_jsx("span", { className: "text-muted-foreground shrink-0 text-sm", children: model.name }), _jsx("span", { className: "text-foreground min-w-0 truncate font-mono text-xs", children: model.id })] }), _jsxs("div", { className: "text-muted-foreground flex flex-wrap items-center gap-x-5 gap-y-2 text-xs", children: [_jsx("span", { className: "tabular-nums", children: context ? t('contextWindow', { tokens: context }) : t('contextDefault') }), _jsxs("label", { className: "flex items-center gap-2", children: [_jsx(Switch, { checked: model.attachment === true, disabled: disabled, onCheckedChange: (attachment) => onToggle({ attachment }) }), t('readsImages')] }), _jsxs("label", { className: "flex items-center gap-2", children: [_jsx(Switch, { checked: model.reasoning === true, disabled: disabled, onCheckedChange: (reasoning) => onToggle({ reasoning }) }), t('reasoning')] })] })] }));
|
|
77
|
+
}
|
|
60
78
|
/**
|
|
61
79
|
* The endpoint editor in the sheet. The PUT replaces the provider's whole
|
|
62
80
|
* definition, so this edits the full model list in place.
|
|
@@ -72,7 +90,7 @@ function EndpointEditor({ projectId, provider, onClose, }) {
|
|
|
72
90
|
const save = useMutation({
|
|
73
91
|
mutationFn: () => {
|
|
74
92
|
const trimmed = models
|
|
75
|
-
.map((m) => ({ id: m.id.trim(), name: m.name.trim() }))
|
|
93
|
+
.map((m) => modelInput({ ...m, id: m.id.trim(), name: m.name.trim() }))
|
|
76
94
|
.filter((m) => m.id || m.name);
|
|
77
95
|
if (!name.trim() || !/^https?:\/\//.test(baseUrl.trim())) {
|
|
78
96
|
throw new Error('Name and an http:// or https:// base URL are required');
|
|
@@ -108,12 +126,22 @@ function CustomProviderDetail({ projectId, provider, onDeleted, }) {
|
|
|
108
126
|
const [confirmDelete, setConfirmDelete] = useState(false);
|
|
109
127
|
const [value, setValue] = useState('');
|
|
110
128
|
const replace = useMutation({
|
|
111
|
-
mutationFn: () =>
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
129
|
+
mutationFn: async () => {
|
|
130
|
+
await upsertProjectSecret(projectId, {
|
|
131
|
+
name: provider.secret_name,
|
|
132
|
+
value: value.trim(),
|
|
133
|
+
strategy: 'broker',
|
|
134
|
+
consumer: 'llm_gateway',
|
|
135
|
+
});
|
|
136
|
+
// Re-save the endpoint: it reads the model limits from `GET /models` with the new key.
|
|
137
|
+
if (provider.configured && provider.base_url) {
|
|
138
|
+
await custom.save(provider.id, {
|
|
139
|
+
name: provider.name,
|
|
140
|
+
base_url: provider.base_url,
|
|
141
|
+
models: provider.models.map(modelInput),
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
},
|
|
117
145
|
onSuccess: () => {
|
|
118
146
|
successToast(t('keyReplaced'));
|
|
119
147
|
setValue('');
|
|
@@ -124,6 +152,14 @@ function CustomProviderDetail({ projectId, provider, onDeleted, }) {
|
|
|
124
152
|
},
|
|
125
153
|
onError: (err) => errorToast(err instanceof Error ? err.message : tI18nComplete.raw('text2c07997249ab')),
|
|
126
154
|
});
|
|
155
|
+
const toggle = useMutation({
|
|
156
|
+
mutationFn: ({ id, patch }) => custom.save(provider.id, {
|
|
157
|
+
name: provider.name,
|
|
158
|
+
base_url: provider.base_url ?? '',
|
|
159
|
+
models: provider.models.map((m) => modelInput(m.id === id ? { ...m, ...patch } : m)),
|
|
160
|
+
}),
|
|
161
|
+
onError: (err) => errorToast(err instanceof Error ? err.message : t('saveFailed')),
|
|
162
|
+
});
|
|
127
163
|
const remove = useMutation({
|
|
128
164
|
mutationFn: () => custom.remove(provider.id),
|
|
129
165
|
onSuccess: () => {
|
|
@@ -139,7 +175,7 @@ function CustomProviderDetail({ projectId, provider, onDeleted, }) {
|
|
|
139
175
|
if (value.trim() && !replace.isPending)
|
|
140
176
|
replace.mutate();
|
|
141
177
|
};
|
|
142
|
-
return (_jsxs(_Fragment, { children: [_jsx(SplitSheetHeader, { closeLabel: tSheet('close'), className: "px-5 py-4", children: _jsxs("div", { className: "flex min-w-0 items-center gap-3", children: [_jsx(ProviderLogoStatus, { providerId: provider.id, label: provider.name, status: "connected", size: "large" }), _jsxs("div", { className: "min-w-0 space-y-0.5", children: [_jsx(SplitSheetTitle, { className: "truncate text-base font-semibold", children: provider.name }), _jsx(SplitSheetDescription, { className: "font-mono", children: provider.id })] })] }) }), _jsxs(SplitSheetBody, { className: "space-y-7", children: [_jsxs("section", { className: "space-y-1", children: [_jsx("h3", { className: "text-foreground text-sm font-medium", children: t('endpoint') }), editing ? (_jsx(EndpointEditor, { projectId: projectId, provider: provider, onClose: () => setEditing(false) })) : (_jsxs(_Fragment, { children: [_jsxs("div", { className: "divide-border divide-y", children: [_jsx(DetailRow, { label: tI18nComplete.raw('text70589413a3c9'), value: provider.base_url ?? '' }), _jsx(DetailRow, { label: tI18nComplete.raw('text16f0ee47f993'), value: provider.has_key ? provider.secret_name : t('noKey'), mono: provider.has_key })] }), _jsx("h3", { className: "text-foreground pt-4 text-sm font-medium", children: t('models') }), _jsx("div", { className: "divide-border divide-y", children: provider.models.map((model) => (_jsx(
|
|
178
|
+
return (_jsxs(_Fragment, { children: [_jsx(SplitSheetHeader, { closeLabel: tSheet('close'), className: "px-5 py-4", children: _jsxs("div", { className: "flex min-w-0 items-center gap-3", children: [_jsx(ProviderLogoStatus, { providerId: provider.id, label: provider.name, status: "connected", size: "large" }), _jsxs("div", { className: "min-w-0 space-y-0.5", children: [_jsx(SplitSheetTitle, { className: "truncate text-base font-semibold", children: provider.name }), _jsx(SplitSheetDescription, { className: "font-mono", children: provider.id })] })] }) }), _jsxs(SplitSheetBody, { className: "space-y-7", children: [_jsxs("section", { className: "space-y-1", children: [_jsx("h3", { className: "text-foreground text-sm font-medium", children: t('endpoint') }), editing ? (_jsx(EndpointEditor, { projectId: projectId, provider: provider, onClose: () => setEditing(false) })) : (_jsxs(_Fragment, { children: [_jsxs("div", { className: "divide-border divide-y", children: [_jsx(DetailRow, { label: tI18nComplete.raw('text70589413a3c9'), value: provider.base_url ?? '' }), _jsx(DetailRow, { label: tI18nComplete.raw('text16f0ee47f993'), value: provider.has_key ? provider.secret_name : t('noKey'), mono: provider.has_key })] }), _jsx("h3", { className: "text-foreground pt-4 text-sm font-medium", children: t('models') }), _jsx("div", { className: "divide-border divide-y", children: provider.models.map((model) => (_jsx(ModelRow, { model: model, disabled: toggle.isPending || !provider.base_url, onToggle: (patch) => toggle.mutate({ id: model.id, patch }) }, model.id))) }), _jsx(Button, { type: "button", size: "sm", variant: "secondary", className: "mt-3", onClick: () => setEditing(true), children: t('editEndpoint') })] }))] }), _jsx("section", { className: "space-y-1", children: replacing ? (_jsxs("form", { onSubmit: submit, className: "space-y-3", "data-custom-provider-replace": "", children: [_jsx("label", { htmlFor: `custom-replace-${provider.id}`, className: "sr-only", children: tI18nComplete.raw('text16f0ee47f993') }), _jsx(InputGroup, { children: _jsx(InputGroupInput, { id: `custom-replace-${provider.id}`, type: "password", autoComplete: "off", spellCheck: false, autoFocus: true, "data-1p-ignore": "", "data-lpignore": "true", "data-form-type": "other", value: value, onChange: (event) => setValue(event.target.value), placeholder: tI18nComplete.raw('textb009c6c5299f'), className: "font-mono" }) }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Button, { type: "submit", size: "sm", disabled: !value.trim() || replace.isPending, className: "gap-1.5", children: [replace.isPending ? _jsx(Loading, { className: "size-3.5 shrink-0" }) : null, tSheet('saveKey')] }), _jsx(Button, { type: "button", size: "sm", variant: "ghost", disabled: replace.isPending, onClick: () => {
|
|
143
179
|
setValue('');
|
|
144
180
|
setReplacing(false);
|
|
145
181
|
}, children: tSheet('cancel') })] })] })) : (_jsx(Button, { type: "button", size: "sm", variant: "secondary", onClick: () => setReplacing(true), children: provider.has_key ? t('replaceKey') : t('addKey') })) }), _jsx("p", { className: "text-muted-foreground text-xs text-pretty", children: t('gatewayNote') })] }), _jsxs(SplitSheetFooter, { className: "justify-between", children: [_jsx(Button, { type: "button", size: "sm", variant: "ghost", className: "text-destructive hover:text-destructive -ml-2", onClick: () => setConfirmDelete(true), children: t('deleteProvider') }), _jsx("span", { className: "text-muted-foreground text-xs", children: tSheet('storedEncrypted') })] }), _jsx(ConfirmDialog, { open: confirmDelete, onOpenChange: setConfirmDelete, title: t('deleteTitle'), description: t('deleteBody', { name: provider.name }), confirmLabel: t('deleteProvider'), confirmVariant: "destructive", isPending: remove.isPending, onConfirm: () => remove.mutate() })] }));
|
|
@@ -35,6 +35,9 @@ export interface CustomFormState {
|
|
|
35
35
|
apiKey: string;
|
|
36
36
|
modelId: string;
|
|
37
37
|
modelName: string;
|
|
38
|
+
/** Unset until the user flips the switch: the endpoint's `GET /models` decides. */
|
|
39
|
+
attachment?: boolean;
|
|
40
|
+
reasoning?: boolean;
|
|
38
41
|
}
|
|
39
42
|
export type ChatGptPhase = 'idle' | 'waiting' | 'done';
|
|
40
43
|
export type ChatGptChallenge = {
|
|
@@ -170,8 +170,8 @@ export function formatTokenCount(tokens) {
|
|
|
170
170
|
if (!tokens || tokens <= 0)
|
|
171
171
|
return '';
|
|
172
172
|
if (tokens >= 1_000_000) {
|
|
173
|
-
|
|
174
|
-
return `${Number.
|
|
173
|
+
// 1,048,576 reads "1M", not "1.0M".
|
|
174
|
+
return `${Number(Math.round((tokens / 1_000_000) * 10) / 10)}M`;
|
|
175
175
|
}
|
|
176
176
|
if (tokens >= 1_000)
|
|
177
177
|
return `${Math.round(tokens / 1000)}K`;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AgentConfigBlock,
|
|
1
|
+
import type { AgentConfigBlock, SandboxTemplate } from '@kortix/sdk';
|
|
2
2
|
import { type GrantOption } from './grant-mode-field.js';
|
|
3
3
|
type SetKortix = <K extends keyof AgentConfigBlock>(key: K, value: AgentConfigBlock[K]) => void;
|
|
4
4
|
/**
|
|
@@ -12,25 +12,18 @@ export declare function RequiredConnectorToggle({ active, onToggle, }: {
|
|
|
12
12
|
active: boolean;
|
|
13
13
|
onToggle: () => void;
|
|
14
14
|
}): import("react").JSX.Element;
|
|
15
|
-
/** The summary chip at a grant card's right edge — "All", "3 picked", "None". */
|
|
16
|
-
export declare function GrantChip({ value }: {
|
|
17
|
-
value: AgentGrantSetV2 | undefined;
|
|
18
|
-
}): import("react").JSX.Element;
|
|
19
15
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
16
|
+
* The section action of a grant page: one `secondary` button to the
|
|
17
|
+
* project-wide page for the same thing. A grant page picks from what the
|
|
18
|
+
* project has; adding, editing or removing one happens on its own Customize
|
|
19
|
+
* tab. The grant mode row already states All / Pick / None, so the header
|
|
20
|
+
* carries no summary chip.
|
|
25
21
|
*/
|
|
26
|
-
export declare function
|
|
27
|
-
value: AgentGrantSetV2 | undefined;
|
|
22
|
+
export declare function ManageButton({ tab, href, }: {
|
|
28
23
|
tab?: 'skills' | 'connectors' | 'secrets';
|
|
29
|
-
/** A page `tab` cannot name
|
|
30
|
-
* through `capabilityTabHref(projectId, 'apps')`. */
|
|
24
|
+
/** A page `tab` cannot name, such as Apps. */
|
|
31
25
|
href?: (projectId: string) => string | null;
|
|
32
|
-
|
|
33
|
-
}): import("react").JSX.Element;
|
|
26
|
+
}): import("react").JSX.Element | null;
|
|
34
27
|
interface GrantSectionProps {
|
|
35
28
|
draft: AgentConfigBlock;
|
|
36
29
|
set: SetKortix;
|
|
@@ -9,7 +9,6 @@ import { useTranslations as useI18nTranslations } from '../../../i18n/index.js';
|
|
|
9
9
|
* (`kortix.yaml`) rather than the question they answer. Same writes, same
|
|
10
10
|
* platform enforcement; the heading now says what it governs.
|
|
11
11
|
*/
|
|
12
|
-
import { Badge } from '../../../primitives/badge.js';
|
|
13
12
|
import { Button } from '../../../primitives/button.js';
|
|
14
13
|
import Hint from '../../../primitives/hint.js';
|
|
15
14
|
import { Switch } from '../../../primitives/switch.js';
|
|
@@ -17,11 +16,11 @@ import { capabilityTabHref } from '../../../internal/lib/capability-tab-routes.j
|
|
|
17
16
|
import { SandboxTemplateMenu, describeSandboxTemplate, } from '../../../access/sandbox-template-menu.js';
|
|
18
17
|
import { cn } from '../../../internal/lib/utils.js';
|
|
19
18
|
import { useKortixRouteProjectId } from '@kortix/sdk/react';
|
|
20
|
-
import {
|
|
19
|
+
import { CaretDownIcon, CubeIcon } from '@phosphor-icons/react';
|
|
21
20
|
import { UiLink as Link } from '../../../providers/ui-provider.js';
|
|
22
21
|
import { EditorSection, SettingRow } from './agent-editor-primitives.js';
|
|
23
22
|
import { pruneRequiredConnectors } from './connectors-personal.js';
|
|
24
|
-
import { GrantSetField, KortixPermissionsField
|
|
23
|
+
import { GrantSetField, KortixPermissionsField } from './grant-mode-field.js';
|
|
25
24
|
/**
|
|
26
25
|
* Marks one granted connector as required before session start.
|
|
27
26
|
*
|
|
@@ -31,27 +30,28 @@ import { GrantSetField, KortixPermissionsField, grantSummary } from './grant-mod
|
|
|
31
30
|
*/
|
|
32
31
|
export function RequiredConnectorToggle({ active, onToggle, }) {
|
|
33
32
|
const tI18nComplete = useI18nTranslations('hardcodedUi.i18nComplete');
|
|
34
|
-
return (_jsx(Hint, { label: active ? tI18nComplete.raw('text49c8975f345b') : tI18nComplete.raw('texta54220c82b33'), children: _jsx(
|
|
35
|
-
? 'bg-kortix-purple/15 text-kortix-purple font-medium'
|
|
36
|
-
: 'text-muted-foreground/50 hover:text-muted-foreground hover:bg-muted/50'), children: tI18nComplete.raw('text4850b174b713') }) }));
|
|
37
|
-
}
|
|
38
|
-
/** The summary chip at a grant card's right edge — "All", "3 picked", "None". */
|
|
39
|
-
export function GrantChip({ value }) {
|
|
40
|
-
const tI18nComplete = useI18nTranslations('hardcodedUi.i18nComplete');
|
|
41
|
-
const summary = grantSummary(value, tI18nComplete);
|
|
42
|
-
return (_jsx(Badge, { variant: summary.tone === 'muted' ? 'muted' : 'outline', size: "sm", className: "tabular-nums", children: summary.label }));
|
|
33
|
+
return (_jsx(Hint, { label: active ? tI18nComplete.raw('text49c8975f345b') : tI18nComplete.raw('texta54220c82b33'), children: _jsx(Button, { type: "button", variant: active ? 'secondary' : 'ghost', size: "sm", "aria-pressed": active, "aria-label": active ? tI18nComplete.raw('textd16c94c19673') : tI18nComplete.raw('text63336c8a8e83'), onClick: onToggle, className: cn('shrink-0', !active && 'text-muted-foreground'), children: tI18nComplete.raw('text4850b174b713') }) }));
|
|
43
34
|
}
|
|
44
35
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
36
|
+
* The section action of a grant page: one `secondary` button to the
|
|
37
|
+
* project-wide page for the same thing. A grant page picks from what the
|
|
38
|
+
* project has; adding, editing or removing one happens on its own Customize
|
|
39
|
+
* tab. The grant mode row already states All / Pick / None, so the header
|
|
40
|
+
* carries no summary chip.
|
|
50
41
|
*/
|
|
51
|
-
export function
|
|
42
|
+
export function ManageButton({ tab, href, }) {
|
|
43
|
+
const tEditor = useI18nTranslations('agentEditor');
|
|
52
44
|
const projectId = useKortixRouteProjectId();
|
|
53
|
-
const target = projectId
|
|
54
|
-
|
|
45
|
+
const target = projectId
|
|
46
|
+
? href
|
|
47
|
+
? href(projectId)
|
|
48
|
+
: tab
|
|
49
|
+
? capabilityTabHref(projectId, tab)
|
|
50
|
+
: null
|
|
51
|
+
: null;
|
|
52
|
+
if (!target)
|
|
53
|
+
return null;
|
|
54
|
+
return (_jsx(Button, { asChild: true, variant: "secondary", size: "sm", children: _jsx(Link, { href: target, prefetch: true, children: tEditor('manage') }) }));
|
|
55
55
|
}
|
|
56
56
|
/*
|
|
57
57
|
* Each grant set is its own page on the agent editor's rail (Marko,
|
|
@@ -60,17 +60,17 @@ export function GrantHeaderTrailing({ value, tab, href, label, }) {
|
|
|
60
60
|
*/
|
|
61
61
|
export function SkillsSection({ draft, set, options }) {
|
|
62
62
|
const tI18nComplete = useI18nTranslations('hardcodedUi.i18nComplete');
|
|
63
|
-
return (_jsx(EditorSection, { title: tI18nComplete.raw('text66d0f523a379'), description: tI18nComplete.raw('textb27e54100c96'), trailing: _jsx(
|
|
63
|
+
return (_jsx(EditorSection, { title: tI18nComplete.raw('text66d0f523a379'), description: tI18nComplete.raw('textb27e54100c96'), trailing: _jsx(ManageButton, { tab: "skills" }), lead: true, bare: true, children: _jsx(GrantSetField, { value: draft.skills, onChange: (v) => set('skills', v), options: options, emptyLabel: tI18nComplete.raw('text66e36043ff7c') }) }));
|
|
64
64
|
}
|
|
65
65
|
export function ConnectorsSection({ draft, set, options }) {
|
|
66
66
|
const tI18nComplete = useI18nTranslations('hardcodedUi.i18nComplete');
|
|
67
|
-
return (_jsx(EditorSection, { title: tI18nComplete.raw('textc3d2e79ebdd0'), description: tI18nComplete.raw('text00f5aae9f9d3'), trailing: _jsx(
|
|
67
|
+
return (_jsx(EditorSection, { title: tI18nComplete.raw('textc3d2e79ebdd0'), description: tI18nComplete.raw('text00f5aae9f9d3'), trailing: _jsx(ManageButton, { tab: "connectors" }), lead: true, bare: true, children: _jsxs("div", { className: "space-y-3", children: [_jsx(GrantSetField, { value: draft.connectors, onChange: (v) => {
|
|
68
68
|
set('connectors', v);
|
|
69
69
|
const pruned = pruneRequiredConnectors(draft.connectors_required, v);
|
|
70
70
|
if (pruned?.length !== draft.connectors_required?.length) {
|
|
71
71
|
set('connectors_required', pruned);
|
|
72
72
|
}
|
|
73
|
-
}, options: options,
|
|
73
|
+
}, options: options, emptyLabel: tI18nComplete.raw('text389fb5217392'), rowAccessory: (id, isSelected) => isSelected ? (_jsx(RequiredConnectorToggle, { active: draft.connectors_required?.includes(id) === true, onToggle: () => {
|
|
74
74
|
const current = draft.connectors_required ?? [];
|
|
75
75
|
const next = current.includes(id)
|
|
76
76
|
? current.filter((a) => a !== id)
|
|
@@ -80,7 +80,7 @@ export function ConnectorsSection({ draft, set, options }) {
|
|
|
80
80
|
}
|
|
81
81
|
export function SecretsSection({ draft, set, options }) {
|
|
82
82
|
const tI18nComplete = useI18nTranslations('hardcodedUi.i18nComplete');
|
|
83
|
-
return (_jsx(EditorSection, { title: tI18nComplete.raw('textd8707d411d99'), description: tI18nComplete.raw('text7f619d9e30a8'), trailing: _jsx(
|
|
83
|
+
return (_jsx(EditorSection, { title: tI18nComplete.raw('textd8707d411d99'), description: tI18nComplete.raw('text7f619d9e30a8'), trailing: _jsx(ManageButton, { tab: "secrets" }), lead: true, bare: true, children: _jsx(GrantSetField, { value: draft.secrets, onChange: (v) => set('secrets', v), options: options, emptyLabel: tI18nComplete.raw('text82a37b8c2266') }) }));
|
|
84
84
|
}
|
|
85
85
|
/**
|
|
86
86
|
* A kortix_version 3 grant over a project registry: the declared subagents
|
|
@@ -90,7 +90,7 @@ export function SecretsSection({ draft, set, options }) {
|
|
|
90
90
|
*/
|
|
91
91
|
export function RegistryGrantSection({ grant, draft, set, options, }) {
|
|
92
92
|
const t = useI18nTranslations('agents.grants');
|
|
93
|
-
return (_jsx(EditorSection, { title: t(`${grant}.title`), description: t(`${grant}.description`),
|
|
93
|
+
return (_jsx(EditorSection, { title: t(`${grant}.title`), description: t(`${grant}.description`), lead: true, bare: true, children: _jsx(GrantSetField, { value: draft[grant], onChange: (v) => set(grant, v), options: options, emptyLabel: t(`${grant}.empty`) }) }));
|
|
94
94
|
}
|
|
95
95
|
/** Kortix permissions (`kortix_permissions` in kortix.yaml): which project
|
|
96
96
|
* operations the agent may perform, through any surface. A block read from a
|
|
@@ -99,10 +99,10 @@ export function RegistryGrantSection({ grant, draft, set, options, }) {
|
|
|
99
99
|
export function ProjectActionsSection({ draft, set }) {
|
|
100
100
|
const tI18nComplete = useI18nTranslations('hardcodedUi.i18nComplete');
|
|
101
101
|
const permissions = draft.kortix_permissions ?? draft.kortix_cli;
|
|
102
|
-
return (_jsx(EditorSection, { title: tI18nComplete.raw('text8f12a6e05e6d'), description: tI18nComplete.raw('text15365eb45e29'),
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
102
|
+
return (_jsx(EditorSection, { title: tI18nComplete.raw('text8f12a6e05e6d'), description: tI18nComplete.raw('text15365eb45e29'), lead: true, bare: true, children: _jsx(KortixPermissionsField, { value: permissions, onChange: (v) => {
|
|
103
|
+
set('kortix_cli', undefined);
|
|
104
|
+
set('kortix_permissions', v);
|
|
105
|
+
} }) }));
|
|
106
106
|
}
|
|
107
107
|
export function WorkspaceSection({ draft, set, sandboxTemplates, defaultSandboxSlug, }) {
|
|
108
108
|
const tI18nComplete = useI18nTranslations('hardcodedUi.i18nComplete');
|
|
@@ -116,7 +116,7 @@ export function WorkspaceSection({ draft, set, sandboxTemplates, defaultSandboxS
|
|
|
116
116
|
// manifest on the next save.
|
|
117
117
|
const stalePin = draft.sandbox && !pinned ? draft.sandbox : null;
|
|
118
118
|
const PinnedIcon = pinned ? describeSandboxTemplate(pinned).Icon : CubeIcon;
|
|
119
|
-
return (_jsxs(EditorSection, { title: tI18nComplete.raw('text87bb59ba2f92'), description: tI18nComplete.raw('text76a5e5a39b4a'), children: [_jsx(SettingRow, { label: tI18nComplete.raw('text9e471951a1b4'), help: draft.sandbox
|
|
119
|
+
return (_jsxs(EditorSection, { title: tI18nComplete.raw('text87bb59ba2f92'), description: tI18nComplete.raw('text76a5e5a39b4a'), lead: true, children: [_jsx(SettingRow, { label: tI18nComplete.raw('text9e471951a1b4'), help: draft.sandbox
|
|
120
120
|
? stalePin
|
|
121
121
|
? tI18nComplete.raw('textb1a5c13d215e')
|
|
122
122
|
: tI18nComplete.raw('text0703d9121fd7')
|
|
@@ -16,7 +16,6 @@ import { useTranslations as useI18nTranslations } from '../../../i18n/index.js';
|
|
|
16
16
|
* section to match would strand one switch in a section of its own for a
|
|
17
17
|
* reason no reader could see.
|
|
18
18
|
*/
|
|
19
|
-
import { Badge } from '../../../primitives/badge.js';
|
|
20
19
|
import { Button } from '../../../primitives/button.js';
|
|
21
20
|
import { Disclosure, DisclosureContent, DisclosureTrigger } from '../../../primitives/disclosure.js';
|
|
22
21
|
import { Input } from '../../../primitives/input.js';
|
|
@@ -34,7 +33,7 @@ import { EditorSection, InlineAction, SettingBlock, SettingRow } from './agent-e
|
|
|
34
33
|
const INHERIT = '__inherit__';
|
|
35
34
|
export function BasicsSection({ draft, set, oc, setOc, showDescription = true, }) {
|
|
36
35
|
const tI18nComplete = useI18nTranslations('hardcodedUi.i18nComplete');
|
|
37
|
-
return (_jsxs(EditorSection, { title: tI18nComplete.raw('text8fdd2ee8475e'), description: tI18nComplete.raw('text4e420a5186f0'), children: [_jsx(SettingRow, { label: tI18nComplete.raw('text92c1cdfdf4cb'), help: tI18nComplete.raw('textbe90a56d29da'), children: _jsx("div", { className: "flex sm:justify-end", children: _jsx(Switch, { "aria-label": tI18nComplete.raw('text92c1cdfdf4cb'), checked: draft.enabled !== false, onCheckedChange: (v) => set('enabled', v ? undefined : false) }) }) }), showDescription ? (_jsx(SettingBlock, { label: tI18nComplete.raw('text526e0087cc3f'), help: oc.mode === 'subagent'
|
|
36
|
+
return (_jsxs(EditorSection, { title: tI18nComplete.raw('text8fdd2ee8475e'), description: tI18nComplete.raw('text4e420a5186f0'), lead: true, children: [_jsx(SettingRow, { label: tI18nComplete.raw('text92c1cdfdf4cb'), help: tI18nComplete.raw('textbe90a56d29da'), children: _jsx("div", { className: "flex sm:justify-end", children: _jsx(Switch, { "aria-label": tI18nComplete.raw('text92c1cdfdf4cb'), checked: draft.enabled !== false, onCheckedChange: (v) => set('enabled', v ? undefined : false) }) }) }), showDescription ? (_jsx(SettingBlock, { label: tI18nComplete.raw('text526e0087cc3f'), help: oc.mode === 'subagent'
|
|
38
37
|
? tI18nComplete.raw('text77e2bc11f6ab')
|
|
39
38
|
: tI18nComplete.raw('text9965df7c3221'), children: _jsx(Textarea, { "aria-label": tI18nComplete.raw('text526e0087cc3f'), value: oc.description ?? '', placeholder: tI18nComplete.raw('text446f4eabf99f'), minHeight: 44, className: "text-sm", onChange: (e) => setOc('description', e.target.value) }) })) : null, _jsx(SettingRow, { label: tI18nComplete.raw('text12f67f8539c4'), help: oc.mode ? AGENT_MODE_HELP[oc.mode] : tI18nComplete.raw('text64f405e80a8d'), children: _jsxs(Select, { value: oc.mode ?? INHERIT, onValueChange: (value) => setOc('mode', value === INHERIT ? undefined : value), children: [_jsx(SelectTrigger, { "aria-label": tI18nComplete.raw('text12f67f8539c4'), className: "h-9 w-full", children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: INHERIT, children: tI18nComplete.raw('texte8cb80e5c5cb') }), AGENT_MODES.map((mode) => (_jsx(SelectItem, { value: mode, children: AGENT_MODE_LABEL[mode] }, mode)))] })] }) }), _jsx(SettingRow, { label: tI18nComplete.raw('textc7bcb471c03d'), help: tI18nComplete.raw('textdd4971af3f91'), children: _jsx("div", { className: "flex sm:justify-end", children: _jsx(Switch, { "aria-label": tI18nComplete.raw('textc7bcb471c03d'), checked: !oc.hidden, onCheckedChange: (v) => setOc('hidden', v ? undefined : true) }) }) })] }));
|
|
40
39
|
}
|
|
@@ -51,17 +50,11 @@ export function ModelSection({ oc, setOc, showPrompt = true, }) {
|
|
|
51
50
|
? models.find((m) => m.providerID === selectedModelKey.providerID && m.modelID === selectedModelKey.modelID)
|
|
52
51
|
: undefined;
|
|
53
52
|
const variantChoices = selectedModel?.variants ? Object.keys(selectedModel.variants) : [];
|
|
54
|
-
|
|
55
|
-
// read by fewer. They open only when one of them carries a value, so an
|
|
56
|
-
// agent that tunes nothing shows one row — the model — and nothing else.
|
|
57
|
-
const advancedSet = !isSliderAtDefault(oc.temperature, 0) ||
|
|
58
|
-
!isSliderAtDefault(oc.top_p, 1) ||
|
|
59
|
-
oc.steps !== undefined;
|
|
60
|
-
return (_jsxs(_Fragment, { children: [_jsxs(EditorSection, { title: tI18nComplete.raw('text5e2c614c23f0'), description: tI18nComplete.raw('text32398dbb68e2'), children: [_jsx(SettingRow, { label: tI18nComplete.raw('text34455bf1d857'), help: oc.model ? (_jsx(InlineAction, { onClick: () => setOc('model', undefined), children: tI18nComplete.raw('text9db60344e984') })) : (tI18nComplete.raw('text64f405e80a8d')), children: _jsx("div", { className: "flex sm:justify-end", children: _jsx(ModelSelector, { models: models, providers: providers, selectedModel: selectedModelKey, unsetLabel: tI18nComplete.raw('texte8cb80e5c5cb'), onSelect: (m) => setOc('model', m ? modelKeyToWire(m) : undefined) }) }) }), variantChoices.length > 0 ? (_jsx(SettingRow, { label: tI18nComplete.raw('text264c28cbf01c'), help: oc.variant
|
|
53
|
+
return (_jsxs(_Fragment, { children: [_jsxs(EditorSection, { title: tI18nComplete.raw('text5e2c614c23f0'), description: tI18nComplete.raw('text32398dbb68e2'), lead: true, children: [_jsx(SettingRow, { label: tI18nComplete.raw('text34455bf1d857'), help: oc.model ? (_jsx(InlineAction, { onClick: () => setOc('model', undefined), children: tI18nComplete.raw('text9db60344e984') })) : (tI18nComplete.raw('text64f405e80a8d')), children: _jsx("div", { className: "flex sm:justify-end", children: _jsx(ModelSelector, { models: models, providers: providers, selectedModel: selectedModelKey, unsetLabel: tI18nComplete.raw('texte8cb80e5c5cb'), onSelect: (m) => setOc('model', m ? modelKeyToWire(m) : undefined) }) }) }), variantChoices.length > 0 ? (_jsx(SettingRow, { label: tI18nComplete.raw('text264c28cbf01c'), help: oc.variant
|
|
61
54
|
? tI18nComplete.raw('text4dd21464c579')
|
|
62
55
|
: tI18nComplete.raw('textf39c806f5724'), children: _jsx("div", { className: "flex sm:justify-end", children: _jsx(ReasoningEffortSelector, { variants: variantChoices, selectedVariant: oc.variant ?? null, onVariantChange: (v) => setOc('variant', v ?? undefined) }) }) })) : (_jsx(SettingRow, { label: tI18nComplete.raw('text3f19fe84a2de'), help: selectedModelKey
|
|
63
56
|
? tI18nComplete.raw('text0443f619cb33')
|
|
64
|
-
: tI18nComplete.raw('text6376d74077c0'), children: _jsx(Input, { "aria-label": tI18nComplete.raw('text3f19fe84a2de'), value: oc.variant ?? '', placeholder: tI18nComplete.raw('text352a25678fb9'), variant: "popover", className: "h-9 w-full text-sm", onChange: (e) => setOc('variant', e.target.value) }) })), showPrompt ? (_jsx(SettingBlock, { label: tI18nComplete.raw('text561257c019e5'), help: tI18nComplete.raw('textad63817393a7'), children: _jsxs(Disclosure, { variant: "outline", className: "overflow-hidden rounded-md", children: [_jsx(DisclosureTrigger, { variant: "outline", children: _jsxs(Button, { variant: "popover", className: "flex w-full items-center justify-between gap-3 rounded-none text-sm font-normal", children: [_jsx("span", { className: "min-w-0 truncate", children: oc.prompt ? firstLine(oc.prompt) : tI18nComplete.raw('textdaaf5ab03267') }), _jsx("span", { className: "text-muted-foreground shrink-0 text-xs", children: oc.prompt ? 'Edit' : tI18nComplete.raw('text47f3fe537320') })] }) }), _jsx(DisclosureContent, { variant: "outline", contentClassName: "border-border border-t", children: _jsx(Textarea, { "aria-label": tI18nComplete.raw('text561257c019e5'), value: oc.prompt ?? '', placeholder: tI18nComplete.raw('text94a18ea1d428'), minHeight: 160, className: "rounded-none border-0 font-mono text-xs focus-visible:border-0 focus-visible:ring-0", onChange: (e) => setOc('prompt', e.target.value) }) })] }) })) : null] }), _jsxs(EditorSection, { title: tI18nComplete.raw('text6d06116595a9'), description: tI18nComplete.raw('text33439eb47c9a'),
|
|
57
|
+
: tI18nComplete.raw('text6376d74077c0'), children: _jsx(Input, { "aria-label": tI18nComplete.raw('text3f19fe84a2de'), value: oc.variant ?? '', placeholder: tI18nComplete.raw('text352a25678fb9'), variant: "popover", className: "h-9 w-full text-sm", onChange: (e) => setOc('variant', e.target.value) }) })), showPrompt ? (_jsx(SettingBlock, { label: tI18nComplete.raw('text561257c019e5'), help: tI18nComplete.raw('textad63817393a7'), children: _jsxs(Disclosure, { variant: "outline", className: "overflow-hidden rounded-md", children: [_jsx(DisclosureTrigger, { variant: "outline", children: _jsxs(Button, { variant: "popover", className: "flex w-full items-center justify-between gap-3 rounded-none text-sm font-normal", children: [_jsx("span", { className: "min-w-0 truncate", children: oc.prompt ? firstLine(oc.prompt) : tI18nComplete.raw('textdaaf5ab03267') }), _jsx("span", { className: "text-muted-foreground shrink-0 text-xs", children: oc.prompt ? 'Edit' : tI18nComplete.raw('text47f3fe537320') })] }) }), _jsx(DisclosureContent, { variant: "outline", contentClassName: "border-border border-t", children: _jsx(Textarea, { "aria-label": tI18nComplete.raw('text561257c019e5'), value: oc.prompt ?? '', placeholder: tI18nComplete.raw('text94a18ea1d428'), minHeight: 160, className: "rounded-none border-0 font-mono text-xs focus-visible:border-0 focus-visible:ring-0", onChange: (e) => setOc('prompt', e.target.value) }) })] }) })) : null] }), _jsxs(EditorSection, { title: tI18nComplete.raw('text6d06116595a9'), description: tI18nComplete.raw('text33439eb47c9a'), children: [_jsx(SliderRow, { label: tI18nComplete.raw('textb958ce8b871a'), help: tI18nComplete.raw('textd380d30f3d60'), value: oc.temperature, fallback: 0, min: 0, max: 2, step: 0.05, onChange: (v) => setOc('temperature', v) }), _jsx(SliderRow, { label: tI18nComplete.raw('text714db3dbb0b7'), help: tI18nComplete.raw('text4f370db531ba'), value: oc.top_p, fallback: 1, min: 0, max: 1, step: 0.01, onChange: (v) => setOc('top_p', v) }), _jsx(SettingRow, { label: tI18nComplete.raw('textfdc639c47624'), help: tI18nComplete.raw('textbf7ff92baea3'), children: _jsx(Input, { "aria-label": tI18nComplete.raw('textfdc639c47624'), type: "number", min: 1, value: oc.steps ?? '', placeholder: tI18nComplete.raw('textf7fcff0d8fea'), variant: "popover", className: "h-9 w-full text-sm tabular-nums", onChange: (e) => setOc('steps', e.target.value ? Math.max(1, Number(e.target.value)) : undefined) }) })] })] }));
|
|
65
58
|
}
|
|
66
59
|
/**
|
|
67
60
|
* Whether a slider row is showing its default.
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* titles at `text-sm font-medium`, help at `text-xs text-muted-foreground`.
|
|
10
10
|
* Those two sizes are the whole scale; nothing in the editor is smaller.
|
|
11
11
|
*/
|
|
12
|
+
import type * as React from 'react';
|
|
12
13
|
import { type ReactNode } from 'react';
|
|
13
14
|
/**
|
|
14
15
|
* How a section draws itself. `flat` is the original: a heading over
|
|
@@ -27,19 +28,36 @@ export type EditorSectionStyle = 'flat' | 'panel';
|
|
|
27
28
|
export declare function EditorSectionStyleProvider({ value, children, }: {
|
|
28
29
|
value: EditorSectionStyle;
|
|
29
30
|
children: ReactNode;
|
|
30
|
-
}):
|
|
31
|
+
}): React.JSX.Element;
|
|
31
32
|
/**
|
|
32
|
-
* One titled group of settings
|
|
33
|
-
*
|
|
33
|
+
* One titled group of settings, in the Settings page's dialect
|
|
34
|
+
* (`settings/tabs/general-tab.tsx`): the heading sits on the page, never
|
|
35
|
+
* inside a box, and only the rows below it share one bordered group.
|
|
36
|
+
*
|
|
37
|
+
* `lead` marks the first section of a pane. It takes the pane title
|
|
38
|
+
* (`SettingsSectionHeader`, `text-base lg:text-xl`). Every later section
|
|
39
|
+
* takes the quieter `SettingsSubsectionHeader`. Neither shows `description`
|
|
40
|
+
* on the agent page; it renders only in the legacy `flat` style.
|
|
41
|
+
*
|
|
42
|
+
* `bare` hands the body to the caller unwrapped: a list (`GrantList`), a
|
|
43
|
+
* markdown preview, or a textarea draws its own surface.
|
|
34
44
|
*/
|
|
35
|
-
export declare function EditorSection({ title, description, trailing, children, }: {
|
|
45
|
+
export declare function EditorSection({ title, description, trailing, lead, bare, children, }: {
|
|
36
46
|
title: string;
|
|
37
47
|
description?: ReactNode;
|
|
38
|
-
/**
|
|
39
|
-
*
|
|
48
|
+
/** The section's action at the header's right edge: one `secondary`
|
|
49
|
+
* button (New, Manage) or a small control such as the Edit / Preview tabs. */
|
|
40
50
|
trailing?: ReactNode;
|
|
51
|
+
lead?: boolean;
|
|
52
|
+
bare?: boolean;
|
|
41
53
|
children: ReactNode;
|
|
42
|
-
}):
|
|
54
|
+
}): React.JSX.Element;
|
|
55
|
+
/**
|
|
56
|
+
* The bordered list a section hands its rows to: one `bg-popover` group,
|
|
57
|
+
* hairlines between rows, no per-row box. A stack of individually bordered
|
|
58
|
+
* cards read as ten announcements; one group reads as one list.
|
|
59
|
+
*/
|
|
60
|
+
export declare function EditorList({ className, ...props }: React.ComponentProps<'ul'>): React.JSX.Element;
|
|
43
61
|
/**
|
|
44
62
|
* Label and help on the left, control on the right — for anything that fits a
|
|
45
63
|
* switch, a select, a slider, or a short input. Stacks under `sm` so a narrow
|
|
@@ -52,7 +70,7 @@ export declare function SettingRow({ label, help, children, }: {
|
|
|
52
70
|
label: string;
|
|
53
71
|
help?: ReactNode;
|
|
54
72
|
children: ReactNode;
|
|
55
|
-
}):
|
|
73
|
+
}): React.JSX.Element;
|
|
56
74
|
/**
|
|
57
75
|
* Label and help above a full-width control — for anything a row cannot hold:
|
|
58
76
|
* a textarea, a grant checklist, the permission tree.
|
|
@@ -61,7 +79,7 @@ export declare function SettingBlock({ label, help, children, }: {
|
|
|
61
79
|
label: string;
|
|
62
80
|
help?: ReactNode;
|
|
63
81
|
children: ReactNode;
|
|
64
|
-
}):
|
|
82
|
+
}): React.JSX.Element;
|
|
65
83
|
/**
|
|
66
84
|
* A text button that lives inside a help line — "Reset", "Clear". Text, not an
|
|
67
85
|
* icon: at this size an icon is a guess, and the word is three characters
|
|
@@ -70,4 +88,4 @@ export declare function SettingBlock({ label, help, children, }: {
|
|
|
70
88
|
export declare function InlineAction({ onClick, children }: {
|
|
71
89
|
onClick: () => void;
|
|
72
90
|
children: ReactNode;
|
|
73
|
-
}):
|
|
91
|
+
}): React.JSX.Element;
|