@kortix/ui 0.14.4 → 0.14.5
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 +8 -4
- package/dist/customize/sections/llm-provider/constants.d.ts +0 -1
- package/dist/customize/sections/llm-provider/constants.js +0 -2
- package/dist/customize/sections/llm-provider/models-tab-group.d.ts +1 -1
- package/dist/customize/sections/llm-provider/models-tab-group.js +7 -4
- package/dist/customize/sections/llm-provider/models-tab-row.d.ts +2 -18
- package/dist/customize/sections/llm-provider/models-tab-row.js +6 -30
- package/dist/customize/sections/llm-provider/models-tab.d.ts +0 -1
- package/dist/customize/sections/llm-provider/models-tab.js +1 -10
- package/dist/customize/sections/llm-provider/use-connected-providers.js +2 -2
- package/dist/customize/sections/llm-provider/utils.d.ts +1 -1
- package/dist/customize/sections/llm-provider/utils.js +7 -14
- package/dist/customize/sections/view/gateway/_shared.js +1 -2
- package/dist/customize/sections/view/gateway/gateway-routing.js +3 -2
- package/dist/customize/sections/view/sandbox-provider-coverage.d.ts +3 -18
- package/dist/customize/sections/view/sandbox-provider-coverage.js +7 -27
- package/dist/customize/settings/tabs/sandbox-tab.d.ts +2 -27
- package/dist/customize/settings/tabs/sandbox-tab.js +13 -112
- package/dist/customize/shared/entity/entity-modal.d.ts +5 -1
- package/dist/customize/shared/entity/entity-modal.js +7 -4
- package/dist/customize/skills/remove-skill-button.d.ts +16 -0
- package/dist/customize/skills/remove-skill-button.js +42 -0
- package/dist/customize/skills/skills-page.js +1 -1
- package/dist/customize/triggers/schedule/trigger-list.d.ts +0 -2
- package/dist/customize/triggers/schedule/trigger-list.js +1 -18
- package/dist/customize/triggers/schedule/trigger-tile.d.ts +1 -32
- package/dist/customize/triggers/schedule/trigger-tile.js +1 -16
- package/dist/files/project/hooks/use-change-requests.d.ts +14 -1
- package/dist/files/project/hooks/use-change-requests.js +44 -25
- package/dist/files/renderers/docx/docx-viewer.js +4 -1
- package/dist/files/renderers/pdf/pdf-renderer.d.ts +3 -1
- package/dist/files/renderers/pdf/pdf-renderer.js +2 -2
- package/dist/files/renderers/pdf/pdf-viewer.d.ts +3 -0
- package/dist/files/renderers/pdf/pdf-viewer.js +15 -6
- package/dist/files/viewer/file-content-renderer.d.ts +4 -1
- package/dist/files/viewer/file-content-renderer.js +2 -2
- package/dist/i18n/en.d.ts +26 -35
- package/dist/i18n/en.js +35 -44
- package/dist/index.d.ts +1 -1
- package/dist/internal/hooks/use-notification-center.js +21 -15
- package/dist/internal/hooks/use-review-session-summary.d.ts +6 -0
- package/dist/internal/hooks/use-review-session-summary.js +11 -0
- package/dist/internal/lib/browser-error-noise.d.ts +1 -1
- package/dist/internal/lib/browser-error-noise.js +1 -1
- package/dist/internal/lib/browser-noise/rules/rejections.d.ts +10 -0
- package/dist/internal/lib/browser-noise/rules/rejections.js +27 -1
- package/dist/internal/lib/provider-branding.js +14 -3
- package/dist/internal/lib/trigger-clock.d.ts +42 -0
- package/dist/internal/lib/trigger-clock.js +34 -0
- package/dist/internal/lib/web-notifications.d.ts +6 -0
- package/dist/internal/lib/web-notifications.js +57 -7
- package/dist/internal/notifications/notification-bell.d.ts +13 -0
- package/dist/internal/notifications/notification-bell.js +1 -1
- package/dist/internal/reminders/reminder-filter.d.ts +12 -0
- package/dist/internal/reminders/reminder-filter.js +34 -0
- package/dist/internal/reminders/reminder-format.d.ts +6 -0
- package/dist/internal/reminders/reminder-format.js +20 -2
- package/dist/internal/stores/kortix-computer-store.d.ts +1 -1
- package/dist/internal/stores/session-hover-store.d.ts +20 -5
- package/dist/internal/stores/session-hover-store.js +31 -13
- package/dist/internal/stores/session-panel-memory-store.js +2 -0
- package/dist/primitives/count-badge.d.ts +3 -1
- package/dist/primitives/count-badge.js +3 -3
- package/dist/primitives/glyph-paths-source.js +1 -1
- package/dist/primitives/glyph-paths.generated.js +1 -1
- package/dist/providers/ui-provider.d.ts +57 -0
- package/dist/providers/ui-provider.js +4 -0
- package/dist/session/composer/ComposerCard.d.ts +2 -0
- package/dist/session/composer/ComposerCard.js +5 -1
- package/dist/session/composer/agent-selector.js +12 -5
- package/dist/session/composer/composer-toolbar.js +4 -2
- package/dist/session/composer/composer-underbar.js +3 -1
- package/dist/session/composer/composer.js +34 -5
- package/dist/session/composer/menus/slash-actions.d.ts +22 -2
- package/dist/session/composer/menus/slash-actions.js +20 -0
- package/dist/session/composer/menus/slash-items.js +19 -3
- package/dist/session/header/reminder-parts.d.ts +285 -0
- package/dist/session/header/reminder-parts.js +115 -0
- package/dist/session/header/session-reminders-indicator.d.ts +13 -0
- package/dist/session/header/session-reminders-indicator.js +142 -35
- package/dist/session/models/model-availability.d.ts +23 -0
- package/dist/session/models/model-availability.js +20 -0
- package/dist/session/models/model-grouping.js +1 -4
- package/dist/session/models/model-selector.js +23 -14
- package/dist/session/models/use-model-connection-gate.js +4 -1
- package/dist/session/outcomes/session-outcomes-provider.d.ts +3 -1
- package/dist/session/outcomes/session-outcomes-provider.js +31 -3
- package/dist/session/overrides/session-overrides-composer.d.ts +1 -1
- package/dist/session/overrides/session-overrides-composer.js +5 -1
- package/dist/session/panel/mobile-tool-drawer.js +4 -2
- package/dist/session/panel/open-session-quick-view.js +2 -1
- package/dist/session/panel/panel-fallback.js +8 -4
- package/dist/session/panel/session-panel-provider.d.ts +1 -0
- package/dist/session/panel/session-panel-provider.js +13 -1
- package/dist/session/panel/session-reminders-panel.d.ts +4 -0
- package/dist/session/panel/session-reminders-panel.js +109 -0
- package/dist/session/panel/shared/use-panel-handoffs.d.ts +2 -2
- package/dist/session/panel/shared/use-panel-handoffs.js +5 -1
- package/dist/session/print/session-print-header.d.ts +0 -10
- package/dist/session/print/session-print-header.js +16 -1
- package/dist/session/status/session-surface.js +1 -1
- package/dist/session/thread/optimistic-turn.d.ts +5 -1
- package/dist/session/thread/optimistic-turn.js +8 -6
- package/dist/session/thread/session-chat.d.ts +6 -1
- package/dist/session/thread/session-chat.js +22 -3
- package/dist/session/thread/session-thread.d.ts +10 -1
- package/dist/session/thread/session-thread.js +2 -2
- package/dist/session/turn/burst-step-body.js +4 -0
- package/dist/styles.css +1 -1
- package/dist/workspace/sidebar/project-session-list.js +52 -55
- package/dist/workspace/sidebar/session-brief-hover-card.d.ts +35 -18
- package/dist/workspace/sidebar/session-brief-hover-card.js +114 -37
- package/dist/workspace/sidebar/session-status-mark.d.ts +15 -1
- package/dist/workspace/sidebar/session-status-mark.js +63 -17
- package/package.json +7 -3
- package/skills/kortix-ui/SKILL.md +1 -1
- package/dist/customize/sections/view/sandbox-provider-result.d.ts +0 -47
- package/dist/customize/sections/view/sandbox-provider-result.js +0 -79
package/README.md
CHANGED
|
@@ -6,10 +6,14 @@ by CSS variables. The whole session UI lives here, one module per
|
|
|
6
6
|
responsibility (layout below). `apps/web` imports it like any host: the module
|
|
7
7
|
entries, the primitives, and a short list of deep paths (below).
|
|
8
8
|
|
|
9
|
-
**Built with @kortix/ui:**
|
|
10
|
-
|
|
9
|
+
**Built with @kortix/ui:** three white-label examples in `apps/white-label/`
|
|
10
|
+
([README](../../apps/white-label/README.md)):
|
|
11
|
+
[Lumen Workspace](../../apps/white-label/reskin), the Kortix workspace under its own
|
|
12
|
+
theme, where every screen is a module of this package;
|
|
13
|
+
[Team Console](../../apps/white-label/team-console), an internal tool; and
|
|
14
|
+
[Lumen](../../apps/white-label/lumen), a legal AI SaaS with its own stack.
|
|
11
15
|
|
|
12
|
-
<p align="center"><img src="https://github.com/kortix-ai/suna/raw/dev/apps/
|
|
16
|
+
<p align="center"><img src="https://github.com/kortix-ai/suna/raw/dev/apps/white-label/lumen/public/screenshots/assistant-source.png" width="720" alt="Lumen: the @kortix/ui session thread in Lumen's brand, with a cited answer and its source" /></p>
|
|
13
17
|
|
|
14
18
|
Install: `npm i @kortix/ui @kortix/sdk`. Both packages carry the Kortix release
|
|
15
19
|
version, so install the same version of each. The module entries (`session`,
|
|
@@ -298,7 +302,7 @@ const brand: KortixTheme = {
|
|
|
298
302
|
`THEME_COLOR_VARS` maps each color key to its variable. Plain CSS works too:
|
|
299
303
|
set the same variables in your own `:root` / `.dark` after the import. Never
|
|
300
304
|
fork a component. Roobert (`--font-roobert`) is for Kortix-owned surfaces only.
|
|
301
|
-
`apps/
|
|
305
|
+
`apps/white-label/reskin/src/config/theme.ts` is the reference.
|
|
302
306
|
|
|
303
307
|
How it stays themable:
|
|
304
308
|
|
|
@@ -1,4 +1,2 @@
|
|
|
1
|
-
import { DEFAULT_MANAGED_MODEL_IDS } from '@kortix/llm-catalog';
|
|
2
|
-
export const MANAGED_MODEL_ID_SET = new Set(DEFAULT_MANAGED_MODEL_IDS);
|
|
3
1
|
export const CODEX_AUTH_JSON_SECRET_NAME = 'CODEX_AUTH_JSON';
|
|
4
2
|
export const LEGACY_RUNTIME_AUTH_JSON_SECRET_NAME = 'OPENCODE_AUTH_JSON';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ModelContext } from './models-tab-row.js';
|
|
2
2
|
import type { ModelGroup } from './model-rows.js';
|
|
3
|
-
export declare function ModelsTabGroup({ group, access, enablement, defaults,
|
|
3
|
+
export declare function ModelsTabGroup({ group, access, enablement, defaults, canWrite, platformFee, }: ModelContext & {
|
|
4
4
|
group: ModelGroup;
|
|
5
5
|
platformFee: number | undefined;
|
|
6
6
|
}): import("react").JSX.Element;
|
|
@@ -6,18 +6,21 @@ import { errorToast } from '../../../primitives/toast.js';
|
|
|
6
6
|
import { ProviderLogoStatus } from '../../providers/provider-connect.js';
|
|
7
7
|
import { useTranslations } from '../../../i18n/index.js';
|
|
8
8
|
import { ModelsTabRow } from './models-tab-row.js';
|
|
9
|
-
export function ModelsTabGroup({ group, access, enablement, defaults,
|
|
9
|
+
export function ModelsTabGroup({ group, access, enablement, defaults, canWrite, platformFee, }) {
|
|
10
10
|
const tAccess = useTranslations('modelAccess');
|
|
11
11
|
const tList = useTranslations('modelsList');
|
|
12
12
|
const providerDisabled = access.data?.disabledProviders.includes(group.providerID) ?? false;
|
|
13
13
|
const groupOn = group.rows.filter(({ model }) => model.enabled).length;
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
// Platinum Inference serves every model it lists on zero-retention terms:
|
|
15
|
+
// the Kortix managed models and the Platinum provider alike.
|
|
16
|
+
const dataClaim = group.providerID === 'platinum' ||
|
|
17
|
+
(group.providerID === 'kortix' &&
|
|
18
|
+
group.rows.every(({ model }) => !model.modelID.includes('/')));
|
|
16
19
|
return (_jsxs("section", { "data-provider-group": group.providerID, className: "bg-popover overflow-hidden rounded-lg border", children: [_jsxs("header", { className: "border-border flex items-center gap-3 border-b px-4 py-3", children: [_jsx(ProviderLogoStatus, { providerId: group.providerID, label: group.providerName, status: providerDisabled
|
|
17
20
|
? 'none'
|
|
18
21
|
: group.providerID === 'kortix'
|
|
19
22
|
? 'included'
|
|
20
|
-
: 'connected', size: "medium" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("p", { className: "text-foreground truncate text-sm font-medium", children: group.providerName }), group.providerID === 'kortix' && platformFee !== undefined ? (_jsx("p", { className: "text-muted-foreground text-xs", children: tList('platformFee', { fee: platformFee }) })) : null, dataClaim ? (
|
|
23
|
+
: 'connected', size: "medium" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("p", { className: "text-foreground truncate text-sm font-medium", children: group.providerName }), group.providerID === 'kortix' && platformFee !== undefined ? (_jsx("p", { className: "text-muted-foreground text-xs", children: tList('platformFee', { fee: platformFee }) })) : null, dataClaim ? (_jsx("p", { className: "text-muted-foreground text-xs", children: _jsx(Hint, { label: tAccess('zdrDescription'), side: "top", className: "max-w-xs", children: _jsx("span", { tabIndex: 0, className: "cursor-help", children: tAccess('zdrTitle') }) }) })) : null] }), _jsx("span", { className: "text-muted-foreground shrink-0 text-xs tabular-nums", children: tList('onCount', { on: groupOn, total: group.rows.length }) }), _jsx(ProviderSwitch, { access: access, providerId: group.providerID, name: group.providerName, canWrite: canWrite })] }), group.rows.map(({ model, wireId, isRollingAlias }) => (_jsx(ModelsTabRow, { model: model, wireId: wireId, isRollingAlias: isRollingAlias, group: group, providerDisabled: providerDisabled, access: access, enablement: enablement, defaults: defaults, canWrite: canWrite }, wireId)))] }, group.providerID));
|
|
21
24
|
}
|
|
22
25
|
/**
|
|
23
26
|
* A whole provider on or off for this project. Credentials stay either way.
|
|
@@ -1,28 +1,12 @@
|
|
|
1
|
-
import { useModelAccess, useModelDefaults, useModelEnablement
|
|
2
|
-
import { type ReactNode } from 'react';
|
|
1
|
+
import { useModelAccess, useModelDefaults, useModelEnablement } from '@kortix/sdk/react';
|
|
3
2
|
import type { ModelGroup, ModelRow } from './model-rows.js';
|
|
4
3
|
export type ModelContext = {
|
|
5
4
|
access: ReturnType<typeof useModelAccess>;
|
|
6
5
|
enablement: ReturnType<typeof useModelEnablement>;
|
|
7
6
|
defaults: ReturnType<typeof useModelDefaults>;
|
|
8
|
-
pickerCatalog: ReturnType<typeof useProjectModelPickerCatalog>;
|
|
9
7
|
canWrite: boolean;
|
|
10
|
-
holdsDataClaim: (modelID: string) => boolean;
|
|
11
8
|
};
|
|
12
|
-
export declare function ModelsTabRow({ model, wireId, isRollingAlias, group, providerDisabled, access, enablement, defaults,
|
|
9
|
+
export declare function ModelsTabRow({ model, wireId, isRollingAlias, group, providerDisabled, access, enablement, defaults, canWrite, }: ModelRow & ModelContext & {
|
|
13
10
|
group: ModelGroup;
|
|
14
11
|
providerDisabled: boolean;
|
|
15
12
|
}): import("react").JSX.Element;
|
|
16
|
-
type ManagedPricingRoute = NonNullable<NonNullable<ReturnType<typeof useProjectModelPickerCatalog>>['managedPricingRoutes']>[string][number];
|
|
17
|
-
/**
|
|
18
|
-
* The row's price, underlined; hovering opens every serving route's price and
|
|
19
|
-
* the data notes. The routes used to be printed as full sentences under each
|
|
20
|
-
* managed model — four lines of numbers per row.
|
|
21
|
-
*/
|
|
22
|
-
export declare function ModelPriceHoverCard({ modelName, routes, dataClaim, children, }: {
|
|
23
|
-
modelName: string;
|
|
24
|
-
routes: readonly ManagedPricingRoute[];
|
|
25
|
-
dataClaim: boolean;
|
|
26
|
-
children: ReactNode;
|
|
27
|
-
}): import("react").JSX.Element;
|
|
28
|
-
export {};
|
|
@@ -2,13 +2,11 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { Badge } from '../../../primitives/badge.js';
|
|
4
4
|
import Hint from '../../../primitives/hint.js';
|
|
5
|
-
import { HoverCard, HoverCardContent, HoverCardTrigger } from '../../../primitives/hover-card.js';
|
|
6
5
|
import { Switch } from '../../../primitives/switch.js';
|
|
7
6
|
import { Tag } from '../../../primitives/tag.js';
|
|
8
7
|
import { errorToast } from '../../../primitives/toast.js';
|
|
9
8
|
import { useTranslations } from '../../../i18n/index.js';
|
|
10
9
|
import { cn } from '../../../internal/lib/utils.js';
|
|
11
|
-
import { isManagedModelId, MANAGED_ENDPOINT_PROVIDERS } from '@kortix/llm-catalog';
|
|
12
10
|
import { wireToModelKey, } from '@kortix/sdk/react';
|
|
13
11
|
import { CheckIcon as Check, FolderSimpleIcon as Folder, DotsThreeIcon as MoreHorizontal, StarIcon as Star, } from '@phosphor-icons/react';
|
|
14
12
|
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from '../../../primitives/dropdown-menu.js';
|
|
@@ -18,11 +16,11 @@ import { formatPricePerMillion, formatTokenCount } from './utils.js';
|
|
|
18
16
|
/** A row status pill as the Models board draws it: sentence case, Roobert,
|
|
19
17
|
* round. `Badge`'s default is the uppercase mono label used elsewhere. */
|
|
20
18
|
const STATUS_PILL = 'rounded-full font-sans text-xs tracking-normal normal-case';
|
|
21
|
-
export function ModelsTabRow({ model, wireId, isRollingAlias, group, providerDisabled, access, enablement, defaults,
|
|
19
|
+
export function ModelsTabRow({ model, wireId, isRollingAlias, group, providerDisabled, access, enablement, defaults, canWrite, }) {
|
|
22
20
|
const tAccess = useTranslations('modelAccess');
|
|
23
21
|
const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
|
|
24
22
|
const tList = useTranslations('modelsList');
|
|
25
|
-
const isManaged = group.providerID === 'kortix' &&
|
|
23
|
+
const isManaged = group.providerID === 'kortix' && !model.modelID.includes('/');
|
|
26
24
|
const enabled = !!model.enabled;
|
|
27
25
|
const modelDisabled = access.data?.disabledModels.includes(wireId) ?? false;
|
|
28
26
|
const hiddenFromPicker = !!access.data && !enabled && !providerDisabled && !modelDisabled;
|
|
@@ -36,19 +34,8 @@ export function ModelsTabRow({ model, wireId, isRollingAlias, group, providerDis
|
|
|
36
34
|
// provider — so this is the same comparison as the line above.
|
|
37
35
|
const isAccountDefault = defaults.accountDefault?.modelID === wireId;
|
|
38
36
|
const ctx = formatTokenCount(model.contextWindow);
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
: undefined;
|
|
42
|
-
// The row shows ONE price — the cheapest route's, as "from" —
|
|
43
|
-
// and the hover card shows every route. The routes used to be
|
|
44
|
-
// printed as full sentences under each managed model.
|
|
45
|
-
const hasRoutes = !!pricingRoutes && pricingRoutes.length > 0;
|
|
46
|
-
const priceIn = formatPricePerMillion(hasRoutes
|
|
47
|
-
? Math.min(...pricingRoutes.map((route) => route.input))
|
|
48
|
-
: model.cost?.input);
|
|
49
|
-
const priceOut = formatPricePerMillion(hasRoutes
|
|
50
|
-
? Math.min(...pricingRoutes.map((route) => route.output))
|
|
51
|
-
: model.cost?.output);
|
|
37
|
+
const priceIn = formatPricePerMillion(model.cost?.input);
|
|
38
|
+
const priceOut = formatPricePerMillion(model.cost?.output);
|
|
52
39
|
const turnedOff = modelDisabled || providerDisabled;
|
|
53
40
|
const metaLine = hiddenFromPicker
|
|
54
41
|
? tList('hiddenLine')
|
|
@@ -62,7 +49,7 @@ export function ModelsTabRow({ model, wireId, isRollingAlias, group, providerDis
|
|
|
62
49
|
: null,
|
|
63
50
|
ctx ? tList('context', { value: ctx }) : null,
|
|
64
51
|
priceIn && priceOut
|
|
65
|
-
? tList(
|
|
52
|
+
? tList('price', {
|
|
66
53
|
input: priceIn,
|
|
67
54
|
output: priceOut,
|
|
68
55
|
})
|
|
@@ -74,7 +61,7 @@ export function ModelsTabRow({ model, wireId, isRollingAlias, group, providerDis
|
|
|
74
61
|
// A plain row, NOT a <label>: it holds several controls and a
|
|
75
62
|
// label binds to the FIRST labelable one, so "click the row
|
|
76
63
|
// to toggle" never did what it looked like.
|
|
77
|
-
_jsxs("div", { "data-model-id": wireId, className: "border-border hover:bg-hover flex min-h-13 items-center gap-3 border-t px-4 py-2 transition-[background-color] duration-(--duration-normal) first-of-type:border-t-0", children: [_jsxs("div", { className: "min-w-0 flex-1 space-y-0.5", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx("span", { className: cn('truncate text-sm font-medium', turnedOff ? 'text-muted-foreground' : 'text-foreground'), children: model.modelName }), isProjectDefault && (_jsx(Hint, { label: tI18nComplete.raw('text68cde35131cf'), side: "bottom", children: _jsx(Badge, { variant: "info", size: "sm", className: STATUS_PILL, children: tI18nComplete.raw('text5e06ae1125b5') }) })), isAccountDefault && (_jsx(Hint, { label: tI18nComplete.raw('textd197e66e9634'), side: "bottom", children: _jsx(Badge, { variant: "info", size: "sm", className: STATUS_PILL, children: tI18nComplete.raw('text071c0f5e8495') }) })), hiddenFromPicker && (_jsx(Hint, { label: tAccess('hiddenHint'), side: "bottom", children: _jsx(Badge, { variant: "muted", size: "sm", className: STATUS_PILL, children: tAccess('hidden') }) })), modelDisabled && !providerDisabled && (_jsx(Badge, { variant: "destructive", size: "sm", className: STATUS_PILL, children: tAccess('disabled') })), isRollingAlias && (_jsx(Hint, { label: tI18nComplete.raw('text7482f09d1b13'), side: "bottom", children: _jsx(Tag, { children: tI18nComplete.raw('textf096ba0a2aa6') }) }))] }), metaLine ? (
|
|
64
|
+
_jsxs("div", { "data-model-id": wireId, className: "border-border hover:bg-hover flex min-h-13 items-center gap-3 border-t px-4 py-2 transition-[background-color] duration-(--duration-normal) first-of-type:border-t-0", children: [_jsxs("div", { className: "min-w-0 flex-1 space-y-0.5", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx("span", { className: cn('truncate text-sm font-medium', turnedOff ? 'text-muted-foreground' : 'text-foreground'), children: model.modelName }), isProjectDefault && (_jsx(Hint, { label: tI18nComplete.raw('text68cde35131cf'), side: "bottom", children: _jsx(Badge, { variant: "info", size: "sm", className: STATUS_PILL, children: tI18nComplete.raw('text5e06ae1125b5') }) })), isAccountDefault && (_jsx(Hint, { label: tI18nComplete.raw('textd197e66e9634'), side: "bottom", children: _jsx(Badge, { variant: "info", size: "sm", className: STATUS_PILL, children: tI18nComplete.raw('text071c0f5e8495') }) })), hiddenFromPicker && (_jsx(Hint, { label: tAccess('hiddenHint'), side: "bottom", children: _jsx(Badge, { variant: "muted", size: "sm", className: STATUS_PILL, children: tAccess('hidden') }) })), modelDisabled && !providerDisabled && (_jsx(Badge, { variant: "destructive", size: "sm", className: STATUS_PILL, children: tAccess('disabled') })), isRollingAlias && (_jsx(Hint, { label: tI18nComplete.raw('text7482f09d1b13'), side: "bottom", children: _jsx(Tag, { children: tI18nComplete.raw('textf096ba0a2aa6') }) }))] }), metaLine ? (_jsx("p", { className: "text-muted-foreground text-xs tabular-nums", children: metaLine })) : null] }), _jsx("div", { className: "flex w-18 shrink-0 justify-end", children: _jsx(ModelCapabilityIcons, { chips: true, reasoning: model.capabilities?.reasoning, toolCall: model.capabilities?.toolcall, vision: model.capabilities?.vision }) }), canWrite && (enabled || hiddenFromPicker) ? (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx("button", { type: "button", disabled: defaults.isUpdating, "aria-label": tI18nComplete('text43d1a2b807aa', {
|
|
78
65
|
value0: model.modelName,
|
|
79
66
|
}), title: tI18nComplete.raw('textc3b312278ee5'), className: "text-muted-foreground hover:text-foreground hover:bg-muted data-[state=open]:bg-muted data-[state=open]:text-foreground flex size-6 shrink-0 cursor-pointer items-center justify-center rounded-md transition-[color,background-color] duration-(--duration-normal) disabled:cursor-not-allowed disabled:opacity-50", children: _jsx(MoreHorizontal, { className: "size-4" }) }) }), _jsxs(DropdownMenuContent, { align: "end", className: "w-90", children: [hiddenFromPicker && (_jsx(DropdownMenuItem, { disabled: access.isUpdating, onSelect: () => void access
|
|
80
67
|
.setEnabled({ target: 'model', id: wireId, enabled: false })
|
|
@@ -96,14 +83,3 @@ export function ModelsTabRow({ model, wireId, isRollingAlias, group, providerDis
|
|
|
96
83
|
.setEnabled({ target: 'model', id: wireId, enabled: next })
|
|
97
84
|
.catch((error) => errorToast(error instanceof Error ? error.message : tAccess('modelError'))), className: "shrink-0" })] }, wireId));
|
|
98
85
|
}
|
|
99
|
-
/**
|
|
100
|
-
* The row's price, underlined; hovering opens every serving route's price and
|
|
101
|
-
* the data notes. The routes used to be printed as full sentences under each
|
|
102
|
-
* managed model — four lines of numbers per row.
|
|
103
|
-
*/
|
|
104
|
-
export function ModelPriceHoverCard({ modelName, routes, dataClaim, children, }) {
|
|
105
|
-
const tAccess = useTranslations('modelAccess');
|
|
106
|
-
const tList = useTranslations('modelsList');
|
|
107
|
-
return (_jsxs(HoverCard, { openDelay: 150, children: [_jsx(HoverCardTrigger, { asChild: true, children: _jsx("button", { type: "button", className: "text-foreground decoration-muted-foreground block cursor-help text-left text-xs tabular-nums underline decoration-dotted underline-offset-3", children: children }) }), _jsxs(HoverCardContent, { align: "start", className: "w-98 space-y-3 p-4", children: [_jsxs("div", { className: "flex items-baseline justify-between gap-3", children: [_jsx("p", { className: "text-foreground text-sm font-medium tabular-nums", children: tList('perMillion', { model: modelName }) }), _jsx(Hint, { label: tAccess('pricingEstimate'), children: _jsx("span", { tabIndex: 0, className: "text-muted-foreground cursor-help text-xs", children: tList('estimate') }) })] }), _jsxs("div", { className: "space-y-1.5 text-xs tabular-nums", children: [_jsxs("div", { className: "text-muted-foreground flex gap-2", children: [_jsx("span", { className: "min-w-0 flex-1", children: tList('route') }), _jsx("span", { className: "w-13 shrink-0 text-right", children: tList('input') }), _jsx("span", { className: "w-13 shrink-0 text-right", children: tList('cached') }), _jsx("span", { className: "w-13 shrink-0 text-right", children: tList('output') })] }), routes.map((price) => (_jsxs("div", { className: "text-foreground flex gap-2", "data-pricing-route": price.route, children: [_jsxs("span", { className: "min-w-0 flex-1 truncate", children: [MANAGED_ENDPOINT_PROVIDERS[price.route] ??
|
|
108
|
-
price.route.split('/')[0], price.role === 'preferred' ? ` · ${tAccess('pricingPreferred')}` : ''] }), _jsx("span", { className: "w-13 shrink-0 text-right", children: formatPricePerMillion(price.input) }), _jsx("span", { className: "w-13 shrink-0 text-right", children: formatPricePerMillion(price.cacheRead) }), _jsx("span", { className: "w-13 shrink-0 text-right", children: formatPricePerMillion(price.output) })] }, price.route)))] }), dataClaim ? (_jsxs("div", { className: "border-border text-muted-foreground space-y-1 border-t pt-3 text-xs text-pretty", children: [_jsxs("p", { children: [tAccess('zdrTitle'), ". ", tAccess('zdrDescription')] }), _jsxs("p", { children: [tAccess('usProvidersTitle'), ". ", tAccess('usProvidersDescription')] })] })) : null] })] }));
|
|
109
|
-
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { ModelsTabGroup } from './models-tab-group.js';
|
|
4
|
-
export { ModelPriceHoverCard } from './models-tab-row.js';
|
|
5
4
|
import { useTranslations } from '../../../i18n/index.js';
|
|
6
5
|
/**
|
|
7
6
|
* `ModelsTab` — "which models can this project use".
|
|
@@ -23,7 +22,6 @@ import { useTranslations } from '../../../i18n/index.js';
|
|
|
23
22
|
*/
|
|
24
23
|
import { Button } from '../../../primitives/button.js';
|
|
25
24
|
import { errorToast } from '../../../primitives/toast.js';
|
|
26
|
-
import { isManagedModelId } from '@kortix/llm-catalog';
|
|
27
25
|
import { useModelAccess, useModelDefaults, useModelEnablement, useProjectModelPickerCatalog, useProjectModels, } from '@kortix/sdk/react';
|
|
28
26
|
import { useMemo, useRef, useState } from 'react';
|
|
29
27
|
import { InputGroupSearch, InputGroupSearchClear, InputGroupSearchIcon, InputGroupSearchInput, } from '../../../primitives/input-group.js';
|
|
@@ -74,13 +72,6 @@ export function ModelsTab({ projectId, search: hostSearch, canWrite = false, })
|
|
|
74
72
|
if (models.length === 0) {
|
|
75
73
|
return (_jsxs("div", { className: "flex min-h-[200px] flex-col items-center justify-center gap-1 px-6 text-center", children: [_jsx("p", { className: "text-foreground text-sm", children: tI18nComplete.raw('textc7a9aa43558f') }), _jsx("p", { className: "text-muted-foreground max-w-xs text-xs text-pretty", children: tI18nComplete.raw('text2cedbc7a36d8') })] }));
|
|
76
74
|
}
|
|
77
|
-
// One managed model clears the ZDR + US claim when it serves from Kortix's
|
|
78
|
-
// own managed pool. Only a Morph route breaks it; a missing price feed still
|
|
79
|
-
// serves from the verified US ZDR pool.
|
|
80
|
-
const holdsDataClaim = (modelID) => {
|
|
81
|
-
const routes = pickerCatalog?.managedPricingRoutes?.[modelID];
|
|
82
|
-
return isManagedModelId(modelID) && !routes?.some((route) => route.route === 'morph');
|
|
83
|
-
};
|
|
84
75
|
// No horizontal padding of its own: `CapabilityPageShell` supplies the page
|
|
85
76
|
// column, and 20px more here indented this tab's content past the tab strip
|
|
86
77
|
// that selects it.
|
|
@@ -89,6 +80,6 @@ export function ModelsTab({ projectId, search: hostSearch, canWrite = false, })
|
|
|
89
80
|
.catch((error) => errorToast(error instanceof Error ? error.message : tAccess('resetError'))), children: tI18nComplete.raw('text5eed7e9fc8f3') })), _jsx("span", { className: "text-muted-foreground ml-auto shrink-0 text-xs tabular-nums", children: tList('onCount', { on: enabledCount, total: models.length }) })] }), groups.length === 0 ? (_jsx("div", { className: "flex min-h-[200px] items-center justify-center px-6 text-center", children: _jsx("p", { className: "text-muted-foreground text-xs", children: search
|
|
90
81
|
? tI18nComplete('textb475669b9d30', { value0: search })
|
|
91
82
|
: tI18nComplete.raw('textb12da9202e8c') }) })) : (_jsx("div", { className: "space-y-6", children: groups.map((group) => {
|
|
92
|
-
return (_jsx(ModelsTabGroup, { group: group, access: access, enablement: enablement, defaults: defaults,
|
|
83
|
+
return (_jsx(ModelsTabGroup, { group: group, access: access, enablement: enablement, defaults: defaults, canWrite: canWrite, platformFee: platformFee }, group.providerID));
|
|
93
84
|
}) }))] }));
|
|
94
85
|
}
|
|
@@ -9,7 +9,7 @@ import { useMemo } from 'react';
|
|
|
9
9
|
import { useTranslations } from '../../../i18n/index.js';
|
|
10
10
|
import { PROJECT_ACTIONS } from '../../../internal/lib/project-actions.js';
|
|
11
11
|
import { useProjectCan } from '../../../internal/lib/use-project-can.js';
|
|
12
|
-
import { CODEX_AUTH_JSON_SECRET_NAME, LEGACY_RUNTIME_AUTH_JSON_SECRET_NAME,
|
|
12
|
+
import { CODEX_AUTH_JSON_SECRET_NAME, LEGACY_RUNTIME_AUTH_JSON_SECRET_NAME, } from './constants.js';
|
|
13
13
|
import { isProviderStateLoading } from './provider-loading-state.js';
|
|
14
14
|
import { useLlmProviderCatalogRevision } from './use-live-catalog.js';
|
|
15
15
|
import { buildCodexProvider, buildKortixManagedProvider } from './utils.js';
|
|
@@ -50,7 +50,7 @@ export function useConnectedProviders(projectId, enabled) {
|
|
|
50
50
|
models: Object.fromEntries(Object.entries(pickerCatalog.models).filter(([, model]) => model.enabled !== false)),
|
|
51
51
|
},
|
|
52
52
|
],
|
|
53
|
-
},
|
|
53
|
+
}, tI18nComplete.raw('texte0a770200f93'));
|
|
54
54
|
}, [managedModelsEnabled, pickerCatalog, tI18nComplete]);
|
|
55
55
|
const connectedProviders = useMemo(() => {
|
|
56
56
|
const hasCodexSubscription = secretNames.has(CODEX_AUTH_JSON_SECRET_NAME) ||
|
|
@@ -32,7 +32,7 @@ export declare function buildCodexProvider(ocProviders: RuntimeProvidersSnapshot
|
|
|
32
32
|
* Pure and exported so both rules are pinned by tests; the hook only wires
|
|
33
33
|
* inputs in.
|
|
34
34
|
*/
|
|
35
|
-
export declare function buildKortixManagedProvider(ocProviders: RuntimeProvidersSnapshot,
|
|
35
|
+
export declare function buildKortixManagedProvider(ocProviders: RuntimeProvidersSnapshot, includedHint: string): LlmProviderEntry | null;
|
|
36
36
|
/**
|
|
37
37
|
* The managed provider row's note on the "Add a key" grid.
|
|
38
38
|
*
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { getManagedModel } from '@kortix/llm-catalog';
|
|
2
1
|
import { CODEX_AUTH_JSON_SECRET_NAME, LEGACY_RUNTIME_AUTH_JSON_SECRET_NAME } from './constants.js';
|
|
3
2
|
export function providerDisconnectPlan(provider) {
|
|
4
3
|
const removesSubscription = provider.id === 'codex' || provider.id === 'openai';
|
|
@@ -72,32 +71,26 @@ export function buildCodexProvider(ocProviders, tI18nComplete) {
|
|
|
72
71
|
* Pure and exported so both rules are pinned by tests; the hook only wires
|
|
73
72
|
* inputs in.
|
|
74
73
|
*/
|
|
75
|
-
export function buildKortixManagedProvider(ocProviders,
|
|
74
|
+
export function buildKortixManagedProvider(ocProviders, includedHint) {
|
|
76
75
|
const connectedIds = new Set(ocProviders?.connected ?? []);
|
|
77
76
|
const kortix = (ocProviders?.all ?? []).find((p) => p.id === 'kortix');
|
|
78
77
|
if (!kortix || !connectedIds.has('kortix'))
|
|
79
78
|
return null;
|
|
80
79
|
const models = [];
|
|
81
80
|
for (const [id, m] of Object.entries(kortix.models ?? {})) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
// Best-effort capability/limit passthrough for the "Models in depth"
|
|
85
|
-
// display (models-tab.tsx / catalog-tab.tsx) — the opencode provider
|
|
86
|
-
// snapshot mirrors these when it has them; `vision`/`limit` otherwise
|
|
87
|
-
// fall back to `@kortix/llm-catalog`'s curated managed-model table,
|
|
88
|
-
// the canonical home for both (see MANAGED_MODELS' doc comment —
|
|
89
|
-
// managed slugs aren't reliably on models.dev, so this table is
|
|
90
|
-
// authoritative for them, not a guess).
|
|
81
|
+
// Managed = served under the `kortix` provider: what Platinum Inference
|
|
82
|
+
// offers. Capabilities and limits come with the served entry.
|
|
91
83
|
const raw = m;
|
|
92
|
-
|
|
84
|
+
if (raw.provider !== 'kortix' || id.includes('/'))
|
|
85
|
+
continue;
|
|
93
86
|
models.push({
|
|
94
87
|
id,
|
|
95
88
|
name: (raw.name || id).replace('(latest)', '').trim(),
|
|
96
89
|
released: raw.release_date ?? null,
|
|
97
90
|
reasoning: raw.reasoning,
|
|
98
91
|
tool_call: raw.tool_call,
|
|
99
|
-
attachment:
|
|
100
|
-
limit: raw.limit
|
|
92
|
+
attachment: raw.attachment,
|
|
93
|
+
limit: raw.limit,
|
|
101
94
|
});
|
|
102
95
|
}
|
|
103
96
|
if (models.length === 0)
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { getManagedModel } from '@kortix/llm-catalog';
|
|
4
3
|
import { CheckIcon as Check } from '@phosphor-icons/react';
|
|
5
4
|
import { Copy } from '../../../../icons/copy.js';
|
|
6
5
|
import { useTranslations } from '../../../../i18n/index.js';
|
|
@@ -17,7 +16,7 @@ export function modelLabel(id) {
|
|
|
17
16
|
return tail.replace(/[-_]/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase());
|
|
18
17
|
}
|
|
19
18
|
export function displayModel(id) {
|
|
20
|
-
return
|
|
19
|
+
return id.split('/').pop() ?? id;
|
|
21
20
|
}
|
|
22
21
|
export function tint(accent, pct) {
|
|
23
22
|
return `color-mix(in oklch, ${accent} ${pct}%, transparent)`;
|
|
@@ -425,8 +425,9 @@ export function GatewayRouting({ projectId, canWrite, projectDefaultPending, })
|
|
|
425
425
|
if (current.defaultFallback?.models.length)
|
|
426
426
|
return current;
|
|
427
427
|
const inherited = routing.data.effective.defaultFallback.models.filter((model) => model !== primaryModel);
|
|
428
|
-
|
|
429
|
-
|
|
428
|
+
// No model id is hardcoded: the platform fallback already follows the
|
|
429
|
+
// served lineup (`inherited`); otherwise take the first other model.
|
|
430
|
+
const preferred = models.find((model) => modelKeyToWire(model) !== primaryModel);
|
|
430
431
|
return {
|
|
431
432
|
...current,
|
|
432
433
|
defaultFallback: {
|
|
@@ -8,19 +8,14 @@ export type SandboxProviderMode = 'automatic' | 'pinned';
|
|
|
8
8
|
export declare function SandboxProviderLabel({ provider }: {
|
|
9
9
|
provider: string;
|
|
10
10
|
}): import("react").JSX.Element;
|
|
11
|
-
export declare function describeProviderMode(mode: SandboxProviderMode, selectedProvider: SandboxProvider | null, tI18nComplete: UiTranslator): {
|
|
12
|
-
label: string;
|
|
13
|
-
selectedProvider: string | null;
|
|
14
|
-
};
|
|
15
11
|
export declare function describeProviderCoverage(status: ProviderCoverageStatus, tI18nComplete: UiTranslator): {
|
|
16
12
|
label: string;
|
|
17
13
|
tone: 'ok' | 'busy' | 'fail' | 'idle';
|
|
18
14
|
};
|
|
19
15
|
export interface SandboxProviderBadgeCopy {
|
|
20
16
|
states?: Partial<Record<ProviderCoverageStatus, string>>;
|
|
21
|
-
selected?: string;
|
|
22
|
-
selectedAria?: string;
|
|
23
17
|
}
|
|
18
|
+
/** Every sandbox runs on Platinum: a deprecated provider's coverage is not shown. */
|
|
24
19
|
export declare function availableProviderCoverage(coverage: SandboxTemplate['provider_coverage'] | null | undefined): ProviderCoverageEntry[];
|
|
25
20
|
/**
|
|
26
21
|
* The freshest observation across every routable provider, or `null` when
|
|
@@ -34,19 +29,9 @@ export declare function latestObservedAt(coverage: SandboxTemplate['provider_cov
|
|
|
34
29
|
*
|
|
35
30
|
* It replaces `SandboxTemplateProviderCoverage`, which baked its own
|
|
36
31
|
* "Session runtime" label, its badge list and its "Checked …" stamp into one
|
|
37
|
-
* `flex` block.
|
|
38
|
-
* so `sandbox-tab.tsx` ended up nesting a labelled row inside another labelled
|
|
39
|
-
* row — two labels and an un-positionable timestamp in a single wrapping
|
|
40
|
-
* footer. Owning just the badge lets the caller build the row.
|
|
41
|
-
*
|
|
42
|
-
* `SandboxTemplateProviderModeBadge` is gone with it: routing mode is static
|
|
43
|
-
* configuration, not live status, so the card states it as a labelled fact in
|
|
44
|
-
* the spec grid (`describeProviderMode` still supplies the words) rather than
|
|
45
|
-
* floating a bare badge in the runtime strip.
|
|
32
|
+
* `flex` block. Owning just the badge lets the caller build the row.
|
|
46
33
|
*/
|
|
47
|
-
export declare function SandboxProviderBadge({ item,
|
|
34
|
+
export declare function SandboxProviderBadge({ item, copy, }: {
|
|
48
35
|
item: ProviderCoverageEntry;
|
|
49
|
-
/** Pinned mode only — marks the provider sessions actually route to. */
|
|
50
|
-
selected?: boolean;
|
|
51
36
|
copy?: SandboxProviderBadgeCopy;
|
|
52
37
|
}): import("react").JSX.Element;
|
|
@@ -1,21 +1,12 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useTranslations } from '../../../i18n/index.js';
|
|
3
3
|
import { Badge } from '../../../primitives/badge.js';
|
|
4
|
-
import { formatSandboxProvider, isLegacySandboxProvider,
|
|
4
|
+
import { formatSandboxProvider, isLegacySandboxProvider, } from '../../../internal/lib/sandbox-providers.js';
|
|
5
5
|
/** A provider's name, with a `Legacy` badge for the legacy fallback provider (Daytona). */
|
|
6
6
|
export function SandboxProviderLabel({ provider }) {
|
|
7
7
|
const t = useTranslations('settings.sandbox');
|
|
8
8
|
return (_jsxs("span", { className: "inline-flex items-center gap-1.5", children: [formatSandboxProvider(provider), isLegacySandboxProvider(provider) ? (_jsx(Badge, { variant: "muted", size: "sm", children: t('provider.legacy') })) : null] }));
|
|
9
9
|
}
|
|
10
|
-
export function describeProviderMode(mode, selectedProvider, tI18nComplete) {
|
|
11
|
-
if (mode === 'automatic')
|
|
12
|
-
return { label: tI18nComplete.raw('textd461a493a375'), selectedProvider: null };
|
|
13
|
-
const selected = selectedProvider ? formatSandboxProvider(selectedProvider) : null;
|
|
14
|
-
return {
|
|
15
|
-
label: tI18nComplete.raw('text3b3c31642567'),
|
|
16
|
-
selectedProvider: selected,
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
10
|
export function describeProviderCoverage(status, tI18nComplete) {
|
|
20
11
|
switch (status) {
|
|
21
12
|
case 'ready':
|
|
@@ -32,10 +23,9 @@ export function describeProviderCoverage(status, tI18nComplete) {
|
|
|
32
23
|
return { label: tI18nComplete.raw('textb764cdc0eab7'), tone: 'idle' };
|
|
33
24
|
}
|
|
34
25
|
}
|
|
26
|
+
/** Every sandbox runs on Platinum: a deprecated provider's coverage is not shown. */
|
|
35
27
|
export function availableProviderCoverage(coverage) {
|
|
36
|
-
return (coverage ?? [])
|
|
37
|
-
.filter((item) => item.available)
|
|
38
|
-
.sort((a, b) => sandboxProviderRank(a.provider) - sandboxProviderRank(b.provider));
|
|
28
|
+
return (coverage ?? []).filter((item) => item.available && !isLegacySandboxProvider(item.provider));
|
|
39
29
|
}
|
|
40
30
|
function providerCoverageVariant(tone) {
|
|
41
31
|
if (tone === 'ok')
|
|
@@ -64,22 +54,12 @@ export function latestObservedAt(coverage) {
|
|
|
64
54
|
*
|
|
65
55
|
* It replaces `SandboxTemplateProviderCoverage`, which baked its own
|
|
66
56
|
* "Session runtime" label, its badge list and its "Checked …" stamp into one
|
|
67
|
-
* `flex` block.
|
|
68
|
-
* so `sandbox-tab.tsx` ended up nesting a labelled row inside another labelled
|
|
69
|
-
* row — two labels and an un-positionable timestamp in a single wrapping
|
|
70
|
-
* footer. Owning just the badge lets the caller build the row.
|
|
71
|
-
*
|
|
72
|
-
* `SandboxTemplateProviderModeBadge` is gone with it: routing mode is static
|
|
73
|
-
* configuration, not live status, so the card states it as a labelled fact in
|
|
74
|
-
* the spec grid (`describeProviderMode` still supplies the words) rather than
|
|
75
|
-
* floating a bare badge in the runtime strip.
|
|
57
|
+
* `flex` block. Owning just the badge lets the caller build the row.
|
|
76
58
|
*/
|
|
77
|
-
export function SandboxProviderBadge({ item,
|
|
59
|
+
export function SandboxProviderBadge({ item, copy = {}, }) {
|
|
78
60
|
const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
|
|
79
|
-
const t = useTranslations('settings.sandbox');
|
|
80
|
-
const legacy = isLegacySandboxProvider(item.provider);
|
|
81
61
|
const state = describeProviderCoverage(item.status, tI18nComplete);
|
|
82
62
|
const stateLabel = copy.states?.[item.status] ?? state.label;
|
|
83
63
|
const provider = formatSandboxProvider(item.provider);
|
|
84
|
-
return (_jsxs(Badge, { variant: providerCoverageVariant(state.tone), size: "xs", "aria-label": `${provider}
|
|
64
|
+
return (_jsxs(Badge, { variant: providerCoverageVariant(state.tone), size: "xs", "aria-label": `${provider}: ${stateLabel}`, children: [provider, _jsx("span", { className: "opacity-50", "aria-hidden": "true", children: tI18nComplete.raw('text3b9453dad42b') }), stateLabel] }));
|
|
85
65
|
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
|
-
import type { UiTranslator } from '../../../i18n/index.js';
|
|
3
2
|
import { type SandboxTemplate } from '@kortix/sdk';
|
|
4
3
|
import { type Icon as PhosphorIcon } from '@phosphor-icons/react';
|
|
5
|
-
import { type SandboxProvider, type SandboxProviderMode } from '../../sections/view/sandbox-provider-coverage.js';
|
|
6
4
|
type TemplateTone = 'ok' | 'busy' | 'fail' | 'idle';
|
|
7
5
|
/** Exported for test only — `TemplateCard` itself owns mutations and cannot
|
|
8
6
|
* render under `renderToStaticMarkup`, so the presentation decisions are
|
|
@@ -36,27 +34,13 @@ export declare function describeBase(template: SandboxTemplate, labels?: {
|
|
|
36
34
|
icon: PhosphorIcon;
|
|
37
35
|
mono: boolean;
|
|
38
36
|
};
|
|
39
|
-
/** Where sessions built from this template actually run. Static configuration,
|
|
40
|
-
* not live status — which is why it belongs in the spec grid next to CPU and
|
|
41
|
-
* memory, and NOT in the runtime footer where a bare `Automatic` badge used
|
|
42
|
-
* to float with no label attached to it. */
|
|
43
|
-
export declare function describeRouting(providerMode: SandboxProviderMode, selectedProvider: SandboxProvider | null, tI18nComplete: UiTranslator, labels?: {
|
|
44
|
-
automatic?: string;
|
|
45
|
-
pinned?: string;
|
|
46
|
-
pinnedWithProvider?: (provider: string) => string;
|
|
47
|
-
}): {
|
|
48
|
-
label: string;
|
|
49
|
-
icon: PhosphorIcon;
|
|
50
|
-
};
|
|
51
37
|
/** Locale-aware age for the runtime footer's "Checked …" stamp. */
|
|
52
38
|
export declare function TemplateStateLine({ tone, label }: {
|
|
53
39
|
tone: TemplateTone;
|
|
54
40
|
label: string;
|
|
55
41
|
}): import("react").JSX.Element;
|
|
56
|
-
export declare function TemplateRuntimeFooter({ coverage,
|
|
42
|
+
export declare function TemplateRuntimeFooter({ coverage, formatObservedAt, runtimeLabel, checkedLabel, badgeCopy, }: {
|
|
57
43
|
coverage: SandboxTemplate['provider_coverage'] | null | undefined;
|
|
58
|
-
providerMode: SandboxProviderMode;
|
|
59
|
-
selectedProvider: SandboxProvider | null;
|
|
60
44
|
formatObservedAt: (observedAt: string) => string;
|
|
61
45
|
runtimeLabel: string;
|
|
62
46
|
checkedLabel: (value: string) => string;
|
|
@@ -71,15 +55,6 @@ export interface SandboxTabViewProps {
|
|
|
71
55
|
* by the container from the same `canManage` gate as everything else in
|
|
72
56
|
* this tab. `undefined` (not rendered) for a non-manager. */
|
|
73
57
|
headerAction?: ReactNode;
|
|
74
|
-
/** `SandboxProviderRow` — the per-project provider pin, moved here from
|
|
75
|
-
* `general-tab.tsx`. A slot for the same reason `templatesSlot` is one: it
|
|
76
|
-
* owns a `useMutation`/`useQueryClient` and cannot render under
|
|
77
|
-
* `renderToStaticMarkup` with no `QueryClientProvider`.
|
|
78
|
-
*
|
|
79
|
-
* Rendered ABOVE the loading/error branch on purpose. It is fed by the
|
|
80
|
-
* PROJECT query, not the snapshots query, so a slow or failed template read
|
|
81
|
-
* must not hide a control that has nothing to do with it. */
|
|
82
|
-
sandboxProviderSlot?: ReactNode;
|
|
83
58
|
/** `1 | 2 | null` — drives whether the manifest hint below reads
|
|
84
59
|
* `kortix.toml` or `kortix.yaml`. `null`/anything else falls back to
|
|
85
60
|
* `kortix.toml`, matching `sandbox-view.tsx`'s own ternary default. */
|
|
@@ -110,7 +85,7 @@ export interface SandboxTabViewProps {
|
|
|
110
85
|
* read. Kept separate from `SandboxTab` so this renders under
|
|
111
86
|
* `renderToStaticMarkup` with no `QueryClientProvider` — see
|
|
112
87
|
* `GeneralTabView` for the same split. */
|
|
113
|
-
export declare function SandboxTabView({ isLoading, isError, errorMessage, onRetry, headerAction,
|
|
88
|
+
export declare function SandboxTabView({ isLoading, isError, errorMessage, onRetry, headerAction, manifestVersion, templatesError, isEmpty, emptyAction, templatesSlot, copy: copyOverride, }: SandboxTabViewProps): import("react").JSX.Element;
|
|
114
89
|
/** Container: owns every hook (project + snapshots queries, the template
|
|
115
90
|
* form's open/edit state) and renders `SandboxTabView` with real data +
|
|
116
91
|
* the templates slot, plus `SandboxTemplateForm` as a sibling (it owns its
|