@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
|
@@ -86,9 +86,11 @@ export function diffAgentGrants(current, next) {
|
|
|
86
86
|
if (next.mode === 'all')
|
|
87
87
|
return { add: [], remove: [...currentIds] };
|
|
88
88
|
const nextIds = next.ids;
|
|
89
|
+
const currentSet = new Set(currentIds);
|
|
90
|
+
const nextSet = new Set(nextIds);
|
|
89
91
|
return {
|
|
90
|
-
add: nextIds.filter((id) => !
|
|
91
|
-
remove: currentIds.filter((id) => !
|
|
92
|
+
add: nextIds.filter((id) => !currentSet.has(id)),
|
|
93
|
+
remove: currentIds.filter((id) => !nextSet.has(id)),
|
|
92
94
|
};
|
|
93
95
|
}
|
|
94
96
|
/**
|
|
@@ -339,10 +341,11 @@ function PrincipalAccessDialog({ open, onOpenChange, accountId, scope, mode, acc
|
|
|
339
341
|
...contract('inventory'),
|
|
340
342
|
});
|
|
341
343
|
const projectAgents = useMemo(() => resourceGrantsQuery.data?.resources.agents ?? [], [resourceGrantsQuery.data]);
|
|
344
|
+
const selectedAgentIdSet = useMemo(() => new Set(agents.ids), [agents.ids]);
|
|
342
345
|
const selectedAgentDeclares = useMemo(() => {
|
|
343
346
|
if (agents.mode !== 'subset' || agents.ids.length === 0)
|
|
344
347
|
return null;
|
|
345
|
-
const picked = projectAgents.filter((a) =>
|
|
348
|
+
const picked = projectAgents.filter((a) => selectedAgentIdSet.has(a.id));
|
|
346
349
|
if (picked.length === 0)
|
|
347
350
|
return null;
|
|
348
351
|
const union = (key) => {
|
|
@@ -351,7 +354,7 @@ function PrincipalAccessDialog({ open, onOpenChange, accountId, scope, mode, acc
|
|
|
351
354
|
return [...new Set(picked.flatMap((a) => a.declares?.[key] ?? []))];
|
|
352
355
|
};
|
|
353
356
|
return { secrets: union('secrets'), connectors: union('connectors') };
|
|
354
|
-
}, [agents, projectAgents]);
|
|
357
|
+
}, [agents, projectAgents, selectedAgentIdSet]);
|
|
355
358
|
// ── Expiry ────────────────────────────────────────────────────────────
|
|
356
359
|
// `expires_at` is a column on every assignment, so every grant this dialog
|
|
357
360
|
// writes can carry one. It used to be offered only where the underlying store
|
|
@@ -879,7 +882,7 @@ function PrincipalAccessDialog({ open, onOpenChange, accountId, scope, mode, acc
|
|
|
879
882
|
? ['member', 'admin']
|
|
880
883
|
: undefined }), scope.kind === 'project' && principals.groupIds.length > 0 ? (_jsx(FieldDescription, { children: tI18nComplete.raw('text237f1a28cf06') })) : null] })) : null, scope.kind === 'project' && everyoneSelected ? (_jsx(InfoBanner, { tone: "neutral", icon: UsersThreeIcon, children: tSharing('everyoneRoleNote', { project: scope.projectName }) })) : null, scope.kind === 'project' && showAgentCeilingNote ? (_jsx(InfoBanner, { tone: "neutral", icon: RobotIcon, title: tAgents('ceilingNoteTitle'), children: _jsx("span", { "data-testid": "agent-ceiling-note", children: tAgents('ceilingNote') }) })) : null, showAgents ? (_jsxs(Field, { className: "gap-1.5", children: [_jsx(FieldLabel, { children: tI18nComplete.raw('text279b44d2ab4b') }), resourceGrantsQuery.isError ? (_jsx(InfoBanner, { tone: "destructive", action: _jsx(Button, { size: "sm", variant: "outline", onClick: () => void resourceGrantsQuery.refetch(), children: tCommon('retry') }), children: resourceGrantsQuery.error.message })) : resourceGrantsQuery.isLoading ? (_jsx(Skeleton, { className: "h-6 w-full rounded-md" })) : null, _jsx(Tabs, { value: agents.mode, onValueChange: (next) => setAgents(next === 'all' ? ALL_AGENTS : { mode: 'subset', ids: agents.ids }), children: _jsxs(TabsListCompact, { children: [_jsx(TabsTriggerCompact, { value: "all", children: tI18nComplete.raw('text54c32d3e2cfa') }), _jsx(TabsTriggerCompact, { value: "subset", children: tI18nComplete.raw('textb080141d6840') })] }) }), agents.mode === 'all' ? (_jsx(FieldDescription, { children: projectAgents.length === 0
|
|
881
884
|
? tI18nComplete.raw('text7bf9d07dcb99')
|
|
882
|
-
: tI18nComplete('textc5bb9fda9711', { value0: projectAgents.length }) })) : null, agents.mode === 'subset' ? (resourceGrantsQuery.isLoading ? (_jsx(Skeleton, { className: "h-24 w-full rounded-md" })) : projectAgents.length === 0 ? (_jsx("p", { className: "text-muted-foreground text-xs", children: tI18nComplete.raw('text7bf9d07dcb99') })) : (_jsx("div", { className: "border-border max-h-40 overflow-y-auto rounded-md border p-1", children: projectAgents.map((agent) => (_jsx(Checkbox, { label: agent.name, checked:
|
|
885
|
+
: tI18nComplete('textc5bb9fda9711', { value0: projectAgents.length }) })) : null, agents.mode === 'subset' ? (resourceGrantsQuery.isLoading ? (_jsx(Skeleton, { className: "h-24 w-full rounded-md" })) : projectAgents.length === 0 ? (_jsx("p", { className: "text-muted-foreground text-xs", children: tI18nComplete.raw('text7bf9d07dcb99') })) : (_jsx("div", { className: "border-border max-h-40 overflow-y-auto rounded-md border p-1", children: projectAgents.map((agent) => (_jsx(Checkbox, { label: agent.name, checked: selectedAgentIdSet.has(agent.id), disabled: pending, onCheckedChange: () => setAgents((prev) => ({
|
|
883
886
|
mode: 'subset',
|
|
884
887
|
ids: prev.ids.includes(agent.id)
|
|
885
888
|
? prev.ids.filter((x) => x !== agent.id)
|
|
@@ -13,7 +13,7 @@ import { errorToast, successToast } from '../../primitives/toast.js';
|
|
|
13
13
|
import { useCopy } from '../../internal/hooks/use-copy.js';
|
|
14
14
|
import { cn } from '../../internal/lib/utils.js';
|
|
15
15
|
import { CheckIcon, CopyIcon } from '@phosphor-icons/react';
|
|
16
|
-
import { AnimatePresence,
|
|
16
|
+
import { AnimatePresence, m } from 'motion/react';
|
|
17
17
|
/**
|
|
18
18
|
* Imperative copy for call sites that are not a `CopyRow` (a kebab item, a
|
|
19
19
|
* toast action button). Same toast pair the three private copies used.
|
|
@@ -37,5 +37,5 @@ export function CopyRow({ value, label, display, successMessage, actions, classN
|
|
|
37
37
|
const copyLabel = copied
|
|
38
38
|
? tI18nComplete.raw('text8d525e5f158b')
|
|
39
39
|
: tI18nComplete.raw('texte21f935f11d7');
|
|
40
|
-
return (_jsxs("div", { className: cn('space-y-1.5', className), children: [label ? _jsx("span", { className: "text-muted-foreground text-xs font-medium", children: label }) : null, _jsxs("div", { className: "bg-popover flex items-center gap-2 rounded-md border px-3 py-2", children: [_jsx("code", { className: "text-foreground min-w-0 flex-1 truncate font-mono text-xs", children: display ?? value }), actions, _jsx(Hint, { label: copyLabel, children: _jsx(Button, { type: "button", variant: "ghost", size: "icon-xs", "aria-label": copyLabel, onClick: () => void copy(value), className: "text-muted-foreground hover:text-foreground shrink-0", children: _jsx("span", { className: "relative inline-flex size-3.5 items-center justify-center", children: _jsx(AnimatePresence, { initial: false, mode: "popLayout", children: _jsx(
|
|
40
|
+
return (_jsxs("div", { className: cn('space-y-1.5', className), children: [label ? _jsx("span", { className: "text-muted-foreground text-xs font-medium", children: label }) : null, _jsxs("div", { className: "bg-popover flex items-center gap-2 rounded-md border px-3 py-2", children: [_jsx("code", { className: "text-foreground min-w-0 flex-1 truncate font-mono text-xs", children: display ?? value }), actions, _jsx(Hint, { label: copyLabel, children: _jsx(Button, { type: "button", variant: "ghost", size: "icon-xs", "aria-label": copyLabel, onClick: () => void copy(value), className: "text-muted-foreground hover:text-foreground shrink-0", children: _jsx("span", { className: "relative inline-flex size-3.5 items-center justify-center", children: _jsx(AnimatePresence, { initial: false, mode: "popLayout", children: _jsx(m.span, { initial: { scale: 0.25, opacity: 0, filter: 'blur(4px)' }, animate: { scale: 1, opacity: 1, filter: 'blur(0px)' }, exit: { scale: 0.25, opacity: 0, filter: 'blur(4px)' }, transition: { type: 'spring', duration: 0.3, bounce: 0 }, className: "absolute inset-0 inline-flex items-center justify-center", children: copied ? (_jsx(CheckIcon, { className: "text-kortix-green size-3.5" })) : (_jsx(CopyIcon, { className: "size-3.5" })) }, copied ? 'check' : 'copy') }) }) }) })] })] }));
|
|
41
41
|
}
|
|
@@ -42,6 +42,7 @@ export function SharingPicker({ projectId, value, onChange, copy, showHeading =
|
|
|
42
42
|
const offerMembers = !hideMembers && (accountApiEnabled || value.mode === 'members');
|
|
43
43
|
return (_jsxs("div", { className: "space-y-3", children: [showHeading && _jsx(Label, { children: c.heading }), _jsxs(RadioGroup, { value: value.mode, onValueChange: (v) => onChange({ ...value, mode: v }), className: "space-y-2", children: [_jsx(ShareOption, { value: "project", label: c.project.label, desc: c.project.desc, disabled: isDisabled('project') }), _jsx(ShareOption, { value: "private", label: c.private.label, desc: c.private.desc, disabled: isDisabled('private') }), offerMembers && (_jsx(ShareOption, { value: "members", label: c.members.label, desc: c.members.desc, disabled: isDisabled('members') }))] }), offerMembers && value.mode === 'members' && (_jsx(SubjectPicker, { projectId: projectId, memberIds: value.memberIds, groupIds: value.groupIds, onChange: (memberIds, groupIds) => onChange({ ...value, memberIds, groupIds }) })), hideMembers && !legacyMembers && (_jsxs("p", { className: "text-muted-foreground text-xs leading-relaxed", children: [tI18nComplete.raw('text558b36e065df'), ' ', _jsx("span", { className: "text-foreground/80 font-medium", children: tI18nComplete.raw('textd4f0bc5a29de') }), ' ', tI18nComplete.raw('text3a71ebb2d593')] })), legacyMembers && (_jsx("p", { className: "text-xs leading-relaxed text-amber-600 dark:text-amber-400", children: tI18nComplete.raw('text64f4c4bd39c9') }))] }));
|
|
44
44
|
}
|
|
45
|
+
const NO_INVITE_EMAILS = [];
|
|
45
46
|
/**
|
|
46
47
|
* Legacy adapter over {@link PrincipalPicker}, kept ONLY for the
|
|
47
48
|
* non-access callers of this module (`features/apps/apps-view.tsx` and
|
|
@@ -52,7 +53,7 @@ export function SharingPicker({ projectId, value, onChange, copy, showHeading =
|
|
|
52
53
|
* @deprecated Use `PrincipalPicker` from
|
|
53
54
|
* `@/features/workspace/shared/access`.
|
|
54
55
|
*/
|
|
55
|
-
export function SubjectPicker({ projectId, accountId, memberIds, groupIds, inviteEmails =
|
|
56
|
+
export function SubjectPicker({ projectId, accountId, memberIds, groupIds, inviteEmails = NO_INVITE_EMAILS, onChange, allowInvite = false, kinds = ['member', 'group'], excludeUserIds, emptyLabel = 'No members or groups in this project yet.', allExcludedLabel = 'Everyone is already added.', }) {
|
|
56
57
|
const value = useMemo(() => ({ memberIds, groupIds, inviteEmails }), [memberIds, groupIds, inviteEmails]);
|
|
57
58
|
const scope = projectId
|
|
58
59
|
? { kind: 'project', projectId }
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
import { isKortixAppUrl } from '../apps/kortix-app-url.js';
|
|
12
12
|
import { APP_ACCESS_PARAM, withoutAppAccessToken } from '../internal/lib/utils/app-access-token.js';
|
|
13
13
|
import { useAppAccess, useProjectApps } from '@kortix/sdk/react';
|
|
14
|
-
import { useRef } from 'react';
|
|
14
|
+
import { useLayoutEffect, useRef } from 'react';
|
|
15
15
|
import { appCan } from '../apps/app-shared.js';
|
|
16
16
|
export { withoutAppAccessToken };
|
|
17
17
|
function hostOf(url) {
|
|
@@ -72,8 +72,10 @@ export function useAppInBrowser(projectId, url) {
|
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
const pinned = useRef(null);
|
|
75
|
-
if (url && resolved && pinned.current?.url !== url)
|
|
76
|
-
pinned.current = { url, src: resolved };
|
|
77
75
|
const src = url && pinned.current?.url === url ? pinned.current.src : resolved;
|
|
76
|
+
useLayoutEffect(() => {
|
|
77
|
+
if (url && src && pinned.current?.url !== url)
|
|
78
|
+
pinned.current = { url, src };
|
|
79
|
+
});
|
|
78
80
|
return { app, apps: apps.data ?? [], src };
|
|
79
81
|
}
|
|
@@ -23,7 +23,7 @@ import { buildWebProxyUrl, isExternalUrl, isWebProxyUrl, normalizeExternalInput,
|
|
|
23
23
|
import { useBrowserRecentsStore } from '../internal/stores/browser-recents-store.js';
|
|
24
24
|
import { useTabStore } from '../internal/stores/tab-store.js';
|
|
25
25
|
import { WarningIcon as AlertTriangle, ArrowSquareOutIcon, GlobeIcon as Globe, LinkSimpleIcon as Link2, DotsThreeIcon as MoreHorizontal, ArrowClockwiseIcon as RefreshCw, GearSixIcon as Settings2, } from '@phosphor-icons/react';
|
|
26
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
26
|
+
import { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react';
|
|
27
27
|
import { BrowserLanding } from './browser-landing.js';
|
|
28
28
|
import { PreviewLoadingOverlay, SandboxAddressBar } from './sandbox-browser-chrome.js';
|
|
29
29
|
function normalizePreviewLabel(value, fallback) {
|
|
@@ -34,6 +34,7 @@ function normalizePreviewLabel(value, fallback) {
|
|
|
34
34
|
return fallback;
|
|
35
35
|
return trimmed;
|
|
36
36
|
}
|
|
37
|
+
const subscribeNoop = () => () => { };
|
|
37
38
|
/**
|
|
38
39
|
* Preview tab content — renders a proxied sandbox URL in an iframe
|
|
39
40
|
* with a browser-like toolbar: editable address bar, refresh, back/forward, open externally.
|
|
@@ -56,8 +57,7 @@ export function BrowserPanel({ tabId, projectId, projectSessionId }) {
|
|
|
56
57
|
const loadTimeoutRef = useRef(null);
|
|
57
58
|
// Recents come from a persisted store — render them only after mount so the
|
|
58
59
|
// server and first client render agree.
|
|
59
|
-
const
|
|
60
|
-
useEffect(() => setMounted(true), []);
|
|
60
|
+
const mounted = useSyncExternalStore(subscribeNoop, () => true, () => false);
|
|
61
61
|
// Extract metadata from tab
|
|
62
62
|
const rawPreviewUrl = tab?.metadata?.url || '';
|
|
63
63
|
const port = tab?.metadata?.port || 0;
|
|
@@ -199,7 +199,7 @@ export function BrowserPanel({ tabId, projectId, projectSessionId }) {
|
|
|
199
199
|
});
|
|
200
200
|
pushHistory(newProxyUrl);
|
|
201
201
|
handleRefresh();
|
|
202
|
-
}, [subdomainOpts, rewritePortPath, tabId, updateTabMetadata, pushHistory, handleRefresh]);
|
|
202
|
+
}, [subdomainOpts, rewritePortPath, tabId, appPreviewTitle, updateTabMetadata, pushHistory, handleRefresh]);
|
|
203
203
|
const canGoBack = historyIndex > 0;
|
|
204
204
|
const canGoForward = historyIndex < history.length - 1;
|
|
205
205
|
/** Walk the history stack in either direction; the two directions were two
|
|
@@ -248,7 +248,7 @@ export function BrowserPanel({ tabId, projectId, projectSessionId }) {
|
|
|
248
248
|
handleRefresh();
|
|
249
249
|
}
|
|
250
250
|
}
|
|
251
|
-
}, [canGoBack, canGoForward, historyIndex, history, tabId, updateTabMetadata, handleRefresh]);
|
|
251
|
+
}, [canGoBack, canGoForward, historyIndex, history, tabId, appPreviewTitle, updateTabMetadata, handleRefresh]);
|
|
252
252
|
/** Home: the landing (Apps + recents). An empty url is what renders it. */
|
|
253
253
|
const handleHome = useCallback(() => {
|
|
254
254
|
updateTabMetadata({
|
|
@@ -290,7 +290,7 @@ export function BrowserPanel({ tabId, projectId, projectSessionId }) {
|
|
|
290
290
|
path,
|
|
291
291
|
},
|
|
292
292
|
};
|
|
293
|
-
}, [fullUrl, isExternalBrowsing, originalUrl, port, tab?.metadata?.path, tab?.title]);
|
|
293
|
+
}, [fullUrl, isExternalBrowsing, originalUrl, port, tab?.metadata?.path, tab?.title, appPreviewTitle]);
|
|
294
294
|
const hasPreview = !!previewUrl || hostPreview.failed;
|
|
295
295
|
const emptyState = (_jsx(EmptyState, { icon: Globe, className: "h-full", title: tHardcodedUi.raw('autoComponentsTabsPreviewTabContentJsxTextPreviewBrowser8136da05'), description: _jsxs(_Fragment, { children: [tHardcodedUi.raw('autoComponentsTabsPreviewTabContentJsxTextOpenAnAppda305669'), ' ', _jsx("span", { className: "text-foreground/80 font-mono", children: "3000" }), ' ', tHardcodedUi.raw('autoComponentsTabsPreviewTabContentJsxTextIfYouKnow6745fa88')] }) }));
|
|
296
296
|
// Copy-public-link action, surfaced from the "⋯" overflow menu.
|
|
@@ -64,6 +64,9 @@ export declare function SandboxAddressBar({ displayValue, hasPreview, isLoading,
|
|
|
64
64
|
* Cross-origin iframes frequently never fire onLoad, so neither surface may
|
|
65
65
|
* trust the event alone — the parent decides when to show and dismiss this.
|
|
66
66
|
*/
|
|
67
|
-
export declare function PreviewLoadingOverlay({ label }: {
|
|
67
|
+
export declare function PreviewLoadingOverlay({ label, detail, action, }: {
|
|
68
68
|
label: string;
|
|
69
|
+
/** A second line once the load is slow: why, and the way out. */
|
|
70
|
+
detail?: string;
|
|
71
|
+
action?: React.ReactNode;
|
|
69
72
|
}): import("react").JSX.Element;
|
|
@@ -80,6 +80,7 @@ export function parseAddressInput(value) {
|
|
|
80
80
|
return null;
|
|
81
81
|
return toInternalUrl(parsed.port, parsed.path);
|
|
82
82
|
}
|
|
83
|
+
const NO_SUGGESTIONS = [];
|
|
83
84
|
/**
|
|
84
85
|
* The back / forward buttons and the home / address / reload group every
|
|
85
86
|
* sandbox preview surface renders, with the hostname highlighted at rest. The bar
|
|
@@ -88,7 +89,7 @@ export function parseAddressInput(value) {
|
|
|
88
89
|
* controls around it (`BrowserPanel`'s overflow menu, `AppPreview`'s viewer
|
|
89
90
|
* actions and close) — the component is a fragment, so it slots between them.
|
|
90
91
|
*/
|
|
91
|
-
export function SandboxAddressBar({ displayValue, hasPreview, isLoading, canGoBack, canGoForward, onBack, onForward, onReload, onHome, onNavigate, suggestions =
|
|
92
|
+
export function SandboxAddressBar({ displayValue, hasPreview, isLoading, canGoBack, canGoForward, onBack, onForward, onReload, onHome, onNavigate, suggestions = NO_SUGGESTIONS, placeholder, ariaLabel, inputRef, resetOnEscape = true, trailing, }) {
|
|
92
93
|
const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
|
|
93
94
|
const [addressValue, setAddressValue] = useState(displayValue);
|
|
94
95
|
const [isEditing, setIsEditing] = useState(false);
|
|
@@ -144,6 +145,6 @@ export function SandboxAddressBar({ displayValue, hasPreview, isLoading, canGoBa
|
|
|
144
145
|
* Cross-origin iframes frequently never fire onLoad, so neither surface may
|
|
145
146
|
* trust the event alone — the parent decides when to show and dismiss this.
|
|
146
147
|
*/
|
|
147
|
-
export function PreviewLoadingOverlay({ label }) {
|
|
148
|
-
return (_jsx("div", { className: "bg-background/80 absolute inset-0 z-10 flex items-center justify-center", children: _jsxs("div", { className: "text-muted-foreground flex flex-col items-center gap-2", children: [_jsx(Loading, { className: "size-4" }), _jsx("p", { className: "text-xs", children: label })] }) }));
|
|
148
|
+
export function PreviewLoadingOverlay({ label, detail, action, }) {
|
|
149
|
+
return (_jsx("div", { className: "bg-background/80 absolute inset-0 z-10 flex items-center justify-center", children: _jsxs("div", { className: "text-muted-foreground flex max-w-xs flex-col items-center gap-2 px-4 text-center", children: [_jsx(Loading, { className: "size-4" }), _jsx("p", { className: "text-xs", children: label }), detail && _jsx("p", { className: "text-xs text-pretty", children: detail }), action] }) }));
|
|
149
150
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ProjectConfigSummary } from '@kortix/sdk';
|
|
2
|
+
type AgentScope = NonNullable<ProjectConfigSummary['agents'][number]['scope']>;
|
|
3
|
+
/** One grant on the card: everything (`'all'`) or how many are listed. */
|
|
4
|
+
export interface AgentAccessPart {
|
|
5
|
+
kind: 'connectors' | 'secrets' | 'actions';
|
|
6
|
+
value: 'all' | number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* What an agent's configuration grants, for its card. The card used to show
|
|
10
|
+
* only the agent's own description, and the starter's says "full tool access"
|
|
11
|
+
* whatever the configuration grants (KRTX-3025). Null for an agent that
|
|
12
|
+
* kortix.yaml does not govern: there is nothing to summarize.
|
|
13
|
+
*/
|
|
14
|
+
export declare function agentAccess(scope: AgentScope | undefined): {
|
|
15
|
+
kind: 'full';
|
|
16
|
+
} | {
|
|
17
|
+
kind: 'scoped';
|
|
18
|
+
parts: AgentAccessPart[];
|
|
19
|
+
} | null;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What an agent's configuration grants, for its card. The card used to show
|
|
3
|
+
* only the agent's own description, and the starter's says "full tool access"
|
|
4
|
+
* whatever the configuration grants (KRTX-3025). Null for an agent that
|
|
5
|
+
* kortix.yaml does not govern: there is nothing to summarize.
|
|
6
|
+
*/
|
|
7
|
+
export function agentAccess(scope) {
|
|
8
|
+
if (!scope)
|
|
9
|
+
return null;
|
|
10
|
+
const grant = (value) => value === 'all' ? 'all' : (value?.length ?? 0);
|
|
11
|
+
const parts = [
|
|
12
|
+
{ kind: 'connectors', value: grant(scope.connectors) },
|
|
13
|
+
{ kind: 'secrets', value: grant(scope.env) },
|
|
14
|
+
{ kind: 'actions', value: grant(scope.kortix_permissions ?? scope.kortix_cli) },
|
|
15
|
+
];
|
|
16
|
+
return parts.every((part) => part.value === 'all') ? { kind: 'full' } : { kind: 'scoped', parts };
|
|
17
|
+
}
|
|
@@ -22,7 +22,6 @@ import { useAgentAuthority, } from '../../access/access/agent-principals.js';
|
|
|
22
22
|
import { useTranslations as useI18nTranslations } from '../../i18n/index.js';
|
|
23
23
|
import { getProjectDetail } from '@kortix/sdk';
|
|
24
24
|
import { contract, qk } from '@kortix/sdk/react';
|
|
25
|
-
import { ArrowUpRightIcon } from '@phosphor-icons/react';
|
|
26
25
|
import { useQuery } from '@tanstack/react-query';
|
|
27
26
|
export function AgentAuthorityCard({ projectId, agentName, grant, }) {
|
|
28
27
|
const t = useI18nTranslations('agentPrincipals');
|
|
@@ -39,7 +38,7 @@ export function AgentAuthorityCard({ projectId, agentName, grant, }) {
|
|
|
39
38
|
: authority.declared.length === 0
|
|
40
39
|
? t('declaredNone')
|
|
41
40
|
: t('declaredCount', { count: authority.declared.length });
|
|
42
|
-
return (_jsx("div", { "data-testid": "agent-authority", children: _jsxs(EditorSection, { title: t('title'), description: t('description'),
|
|
41
|
+
return (_jsx("div", { "data-testid": "agent-authority", children: _jsxs(EditorSection, { title: t('title'), description: t('description'), children: [_jsx(SettingRow, { label: t('kortixPermissions'), help: t('kortixPermissionsHelp', { agent: agentName }), children: _jsx("span", { className: "text-foreground block text-sm sm:text-right", children: declaredLabel }) }), _jsx(SettingRow, { label: t('ceiling'), help: t('ceilingHelp'), children: _jsxs("div", { className: "flex flex-wrap items-center gap-1.5 sm:justify-end", "data-testid": "agent-ceiling", children: [ceiling.kind === 'loading' ? (_jsx(Skeleton, { className: "h-5 w-32" })) : ceiling.kind === 'hidden' ? (_jsx("span", { className: "text-muted-foreground text-sm", children: t('ceilingHidden') })) : ceiling.kind === 'default' ? (_jsx("span", { className: "text-foreground text-sm", children: t('ceilingDefault') })) : (ceiling.roleKeys.map((key) => (_jsx(Badge, { variant: "outline", size: "sm", className: "capitalize", children: key }, key)))), accountId && ceiling.kind !== 'hidden' && ceiling.kind !== 'loading' ? (_jsx(Button, { asChild: true, variant: "secondary", size: "sm", children: _jsx(HubLink, { to: hubTarget(accountId, { tab: 'access-projects', project: projectId }), children: t('changeCeiling') }) })) : null] }) }), _jsx(SettingRow, { label: t('humanOnly'), help: t('humanOnlyHelp'), children: _jsx("span", { className: "text-foreground block text-sm sm:text-right", children: t('humanOnlyValue') }) }), _jsxs(SettingBlock, { label: t('effective'), help: t('effectiveHelp'), children: [_jsx("ul", { className: "flex flex-wrap gap-1", "data-testid": "agent-effective-permissions", children: authority.effective.map((permission) => (_jsx("li", { children: _jsx(Badge, { variant: "outline", size: "xs", className: "font-mono", children: permission }) }, permission))) }), authority.outsideCeiling.length > 0 ? (_jsx(DroppedList, { label: t('outsideCeiling'), permissions: authority.outsideCeiling, testId: "agent-outside-ceiling" })) : null, authority.humanOnly.length > 0 ? (_jsx(DroppedList, { label: t('droppedHumanOnly'), permissions: authority.humanOnly, testId: "agent-dropped-human-only" })) : null] })] }) }));
|
|
43
42
|
}
|
|
44
43
|
function DroppedList({ label, permissions, testId, }) {
|
|
45
44
|
return (_jsxs("div", { className: "space-y-1.5", "data-testid": testId, children: [_jsx("p", { className: "text-muted-foreground text-xs", children: label }), _jsx("ul", { className: "flex flex-wrap gap-1", children: permissions.map((permission) => (_jsx("li", { children: _jsx(Badge, { variant: "muted", size: "xs", className: "font-mono line-through", children: permission }) }, permission))) })] }));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { jsx as _jsx,
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useTranslations as useI18nTranslations } from '../../i18n/index.js';
|
|
4
4
|
/**
|
|
5
5
|
* The v1 fallback cards of the agent page, plus the scope-checklist helpers
|
|
@@ -19,10 +19,10 @@ import { useTranslations as useI18nTranslations } from '../../i18n/index.js';
|
|
|
19
19
|
*/
|
|
20
20
|
import { Badge } from '../../primitives/badge.js';
|
|
21
21
|
import { Button } from '../../primitives/button.js';
|
|
22
|
-
import { Label } from '../../primitives/label.js';
|
|
23
22
|
import Loading from '../../primitives/loading.js';
|
|
24
23
|
import { errorToast, successToast } from '../../primitives/toast.js';
|
|
25
24
|
import { ModelSelector } from '../../session/models/model-selector.js';
|
|
25
|
+
import { EditorSection, SettingRow } from '../sections/view/agent-editor-primitives.js';
|
|
26
26
|
import { PROJECT_ACTIONS } from '../../internal/lib/project-actions.js';
|
|
27
27
|
import { useProjectCan } from '../../internal/lib/use-project-can.js';
|
|
28
28
|
import { cn } from '../../internal/lib/utils.js';
|
|
@@ -51,7 +51,11 @@ export function AgentModel({ projectId, agentName }) {
|
|
|
51
51
|
? (models.find((x) => x.providerID === m.providerID && x.modelID === m.modelID)?.modelName ??
|
|
52
52
|
`${m.providerID}/${m.modelID}`)
|
|
53
53
|
: null;
|
|
54
|
-
|
|
54
|
+
const help = explicit ? (_jsxs(_Fragment, { children: [tI18nComplete.raw('text40124896532d'), ' ', _jsx("span", { className: "text-foreground font-medium", children: nameOf(explicit) }), "."] })) : (_jsxs(_Fragment, { children: [tI18nComplete.raw('text46e3bd02feee'), resolved ? (_jsxs(_Fragment, { children: [' ', "(", _jsx("span", { className: "text-foreground font-medium", children: nameOf(resolved) }), ")"] })) : null, tI18nComplete.raw('textd5bf3036405d')] }));
|
|
55
|
+
return (_jsx(EditorSection, { title: tI18nComplete.raw('text5e2c614c23f0'), description: help, lead: true, children: _jsx(SettingRow, { label: tI18nComplete.raw('text34455bf1d857'), children: canManage ? (_jsxs("div", { className: "flex items-center gap-2 sm:justify-end", children: [explicit ? (_jsx(Button, { variant: "ghost", size: "sm", onClick: () => {
|
|
56
|
+
void defaults.clearAgentDefault(agentName);
|
|
57
|
+
successToast(tI18nComplete('text86781ce4c5b4', { value0: agentName }));
|
|
58
|
+
}, children: tI18nComplete.raw('textbc5b45ae7b60') })) : null, _jsx(ModelSelector, { models: models, providers: providers, selectedModel: explicit, onSelect: (m) => {
|
|
55
59
|
if (m) {
|
|
56
60
|
void defaults.setAgentDefault(agentName, m);
|
|
57
61
|
successToast(`${agentName} → ${nameOf(m)}`);
|
|
@@ -59,10 +63,7 @@ export function AgentModel({ projectId, agentName }) {
|
|
|
59
63
|
else {
|
|
60
64
|
void defaults.clearAgentDefault(agentName);
|
|
61
65
|
}
|
|
62
|
-
} })
|
|
63
|
-
void defaults.clearAgentDefault(agentName);
|
|
64
|
-
successToast(tI18nComplete('text86781ce4c5b4', { value0: agentName }));
|
|
65
|
-
}, children: tI18nComplete.raw('textbc5b45ae7b60') })) : null] })) : (_jsx(Badge, { variant: "outline", size: "sm", className: "font-mono", children: nameOf(resolved) ?? tI18nComplete.raw('text1f0a5246c481') })), _jsx("p", { className: "text-muted-foreground text-xs leading-relaxed text-pretty", children: explicit ? (_jsxs(_Fragment, { children: [tI18nComplete.raw('text40124896532d'), ' ', _jsx("span", { className: "text-foreground font-medium", children: nameOf(explicit) }), "."] })) : (_jsxs(_Fragment, { children: [tI18nComplete.raw('text46e3bd02feee'), resolved ? (_jsxs(_Fragment, { children: [' ', "(", _jsx("span", { className: "text-foreground font-medium", children: nameOf(resolved) }), ")"] })) : null, tI18nComplete.raw('textd5bf3036405d')] })) })] }));
|
|
66
|
+
} })] })) : (_jsx("span", { className: "text-foreground block truncate text-sm sm:text-right", children: nameOf(resolved) ?? tI18nComplete.raw('text1f0a5246c481') })) }) }));
|
|
66
67
|
}
|
|
67
68
|
/**
|
|
68
69
|
* An agent's manifest allowlist (`agents:` in kortix.yaml, or the legacy
|
|
@@ -125,13 +126,13 @@ function AgentScopeCard({ projectId, agentName, scope, }) {
|
|
|
125
126
|
});
|
|
126
127
|
// Non-managers get the read-only mirror (the old presentation).
|
|
127
128
|
if (!canManage) {
|
|
128
|
-
return (_jsxs("div", { className: "bg-popover space-y-3 rounded-md border px-4 py-4", children: [
|
|
129
|
+
return (_jsx(EditorSection, { title: tI18nComplete.raw('textec5ba0abb717'), bare: true, children: _jsxs("div", { className: "bg-popover space-y-3 rounded-md border px-4 py-4", children: [_jsxs("dl", { className: "space-y-2", children: [_jsx(ScopeRow, { label: tI18nComplete.raw('textd8707d411d99'), value: scope.env }), _jsx(ScopeRow, { label: tI18nComplete.raw('textc3d2e79ebdd0'), value: scope.connectors }), _jsx(ScopeRow, { label: tI18nComplete.raw('text8f12a6e05e6d'), value: scope.kortix_permissions ?? scope.kortix_cli })] }), _jsx("p", { className: "text-muted-foreground text-xs leading-relaxed text-pretty", children: tI18nComplete.raw('textac4c418e412f') })] }) }));
|
|
129
130
|
}
|
|
130
|
-
return (_jsxs("div", { className: "bg-popover space-y-4 rounded-md border px-4 py-4", children: [_jsx(
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
131
|
+
return (_jsx(EditorSection, { title: tI18nComplete.raw('textec5ba0abb717'), bare: true, children: _jsxs("div", { className: "bg-popover space-y-4 rounded-md border px-4 py-4", children: [_jsx(ScopeEditor, { label: tI18nComplete.raw('textd8707d411d99'), allLabel: tI18nComplete.raw('text922315177668'), emptyLabel: tI18nComplete.raw('text82a37b8c2266'), value: env, options: secretOptions, match: "case-insensitive", onChange: setEnv }, `env-${editorNonce}`), _jsx(ScopeEditor, { label: tI18nComplete.raw('textc3d2e79ebdd0'), allLabel: tI18nComplete.raw('texta2e8754e4899'), emptyLabel: tI18nComplete.raw('text389fb5217392'), value: connectors, options: connectorOptions, onChange: setConnectors }, `connectors-${editorNonce}`), _jsx("dl", { children: _jsx(ScopeRow, { label: tI18nComplete.raw('text8f12a6e05e6d'), value: scope.kortix_permissions ?? scope.kortix_cli }) }), dirty ? (_jsxs("div", { className: "border-border/50 flex items-center justify-end gap-2 border-t pt-3", children: [_jsx(Button, { variant: "ghost", size: "sm", disabled: save.isPending, onClick: () => {
|
|
132
|
+
setEnv(scope.env);
|
|
133
|
+
setConnectors(scope.connectors);
|
|
134
|
+
setEditorNonce((n) => n + 1);
|
|
135
|
+
}, children: tI18nComplete.raw('textdaee7606b339') }), _jsxs(Button, { size: "sm", disabled: save.isPending, onClick: () => save.mutate(), children: [save.isPending && _jsx(Loading, { className: "size-3.5 shrink-0" }), tI18nComplete.raw('text1509f561f241')] })] })) : null] }) }));
|
|
135
136
|
}
|
|
136
137
|
/**
|
|
137
138
|
* The Secrets checklist, built from the project's secrets.
|
|
@@ -233,7 +234,7 @@ function ScopeEditor({ label, allLabel, emptyLabel, value, options, match = 'exa
|
|
|
233
234
|
return (_jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsx("span", { className: "text-muted-foreground text-xs", children: label }), _jsx("div", { className: "border-border/70 inline-flex shrink-0 overflow-hidden rounded-md border", children: ['all', 'specific', 'none'].map((m) => (_jsx("button", { type: "button", onClick: () => pick(m), className: cn('px-2.5 py-1 text-xs capitalize', 'transition-[color,background-color] active:scale-[0.96]', mode === m
|
|
234
235
|
? 'bg-secondary text-foreground font-medium'
|
|
235
236
|
: 'text-muted-foreground hover:bg-muted/50'), children: m }, m))) })] }), mode === 'all' ? (_jsx("p", { className: "text-muted-foreground text-xs text-pretty", children: allLabel })) : null, mode === 'specific' &&
|
|
236
|
-
(rows.length === 0 ? (_jsx("p", { className: "text-muted-foreground text-xs", children: emptyLabel })) : (_jsx("div", { className: "border-border/60 max-h-44 overflow-y-auto rounded-md border p-1", children: rows.map((o) => (_jsxs("button", { type: "button", "aria-pressed": o.selected, onClick: () => toggle(o.id), className: cn('flex w-full items-center gap-2 rounded px-2 py-1 text-left text-xs transition-colors', o.selected ? 'bg-secondary' : 'hover:bg-muted/50'), children: [_jsx("span", { className: cn('flex size-4 shrink-0 items-center justify-center rounded border', o.selected
|
|
237
|
+
(rows.length === 0 ? (_jsx("p", { className: "text-muted-foreground text-xs", children: emptyLabel })) : (_jsx("div", { className: "border-border/60 max-h-44 overflow-y-auto rounded-md border p-1", children: rows.map((o) => (_jsxs("button", { type: "button", "aria-pressed": o.selected, onClick: () => toggle(o.id), className: cn('flex w-full items-center gap-2 rounded-sm px-2 py-1 text-left text-xs transition-colors', o.selected ? 'bg-secondary' : 'hover:bg-muted/50'), children: [_jsx("span", { className: cn('flex size-4 shrink-0 items-center justify-center rounded-sm border', o.selected
|
|
237
238
|
? 'border-foreground bg-foreground text-background'
|
|
238
239
|
: 'border-border/70'), children: o.selected && _jsx(Check, { className: "size-3" }) }), _jsx("span", { className: "min-w-0 flex-1 truncate font-mono", children: o.label }), o.hint ? (_jsx("span", { className: "text-muted-foreground max-w-[40%] shrink-0 truncate font-mono", children: o.hint })) : null, o.orphan && (_jsx("span", { className: "text-kortix-orange", children: tI18nComplete.raw('textffa63583dfa6') }))] }, o.id))) })))] }));
|
|
239
240
|
}
|
|
@@ -3,14 +3,13 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { uiRoutes } from '../../lib/routes.js';
|
|
4
4
|
import { EmptyState } from '../../primitives/empty-state.js';
|
|
5
5
|
import { ErrorState } from '../../primitives/error-state.js';
|
|
6
|
-
import { EditorSection } from '../sections/view/agent-editor-primitives.js';
|
|
6
|
+
import { EditorList, EditorSection } from '../sections/view/agent-editor-primitives.js';
|
|
7
7
|
import { Button } from '../../primitives/button.js';
|
|
8
8
|
import { Skeleton } from '../../primitives/skeleton.js';
|
|
9
9
|
import { Switch } from '../../primitives/switch.js';
|
|
10
10
|
import { errorToast } from '../../primitives/toast.js';
|
|
11
11
|
import { useDriveFolder, useFolderAccess, useProjectDrive, useShareFolder, useUnshareFolder, } from '../../files/drives/use-drives.js';
|
|
12
12
|
import { useTranslations } from '../../i18n/index.js';
|
|
13
|
-
import { HardDriveIcon } from '@phosphor-icons/react';
|
|
14
13
|
import { UiLink as Link } from '../../providers/ui-provider.js';
|
|
15
14
|
/**
|
|
16
15
|
* Which shared drives an agent gets, on the agent's page, beside Apps and
|
|
@@ -27,7 +26,7 @@ export function AgentDrivesSection({ projectId, agentName }) {
|
|
|
27
26
|
const drives = (root.data?.entries ?? []).filter((e) => e.type === 'dir' && !/^\/?Users(\/|$)/.test(e.path));
|
|
28
27
|
let body;
|
|
29
28
|
if (drive.isLoading || root.isLoading) {
|
|
30
|
-
body = (
|
|
29
|
+
body = (_jsx(EditorList, { children: [0, 1].map((i) => (_jsx("li", { className: "flex items-center gap-3 px-4 py-3", children: _jsx(Skeleton, { className: "h-4 w-40 rounded-sm" }) }, i))) }));
|
|
31
30
|
}
|
|
32
31
|
else if (drive.isError || root.isError || !drive.data) {
|
|
33
32
|
body = (_jsx(ErrorState, { size: "sm", title: t('loadError'), action: _jsx(Button, { variant: "outline", size: "sm", onClick: () => void root.refetch(), children: t('retry') }) }));
|
|
@@ -36,9 +35,9 @@ export function AgentDrivesSection({ projectId, agentName }) {
|
|
|
36
35
|
body = _jsx(EmptyState, { size: "sm", title: t('noCompanyDrives') });
|
|
37
36
|
}
|
|
38
37
|
else {
|
|
39
|
-
body = (_jsx(
|
|
38
|
+
body = (_jsx(EditorList, { children: drives.map((entry) => (_jsx(AgentDriveRow, { driveId: drive.data.driveId, entry: entry, agentName: agentName }, entry.path))) }));
|
|
40
39
|
}
|
|
41
|
-
return (_jsx(EditorSection, { title: t('customizeTitle'), description: t('accessAgentsCompanyHint'), trailing: driveHref ? (_jsx(Button, { asChild: true, variant: "
|
|
40
|
+
return (_jsx(EditorSection, { title: t('customizeTitle'), description: t('accessAgentsCompanyHint'), trailing: driveHref ? (_jsx(Button, { asChild: true, variant: "secondary", size: "sm", children: _jsx(Link, { href: driveHref, children: t('driveLabel') }) })) : undefined, lead: true, bare: true, children: body }));
|
|
42
41
|
}
|
|
43
42
|
function AgentDriveRow({ driveId, entry, agentName }) {
|
|
44
43
|
const t = useTranslations('drives');
|
|
@@ -63,5 +62,5 @@ function AgentDriveRow({ driveId, entry, agentName }) {
|
|
|
63
62
|
errorToast(t('shareFailed'));
|
|
64
63
|
}
|
|
65
64
|
};
|
|
66
|
-
return (_jsxs("li", { className: "
|
|
65
|
+
return (_jsxs("li", { className: "flex items-center gap-3 px-4 py-2.5", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("p", { className: "text-foreground truncate text-sm font-medium", children: entry.name }), _jsx("p", { className: "text-muted-foreground truncate font-mono text-xs", children: inherited ? t('everyoneInProject') : `/drives${path}` })] }), access.isLoading ? (_jsx(Skeleton, { className: "h-5 w-9 rounded-full" })) : (_jsx(Switch, { checked: !!own || inherited, disabled: !canManage || inherited || pending, onCheckedChange: (v) => void toggle(v), "aria-label": t('levelFor', { name: entry.name }) }))] }));
|
|
67
66
|
}
|