@kortix/ui 0.14.6 → 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.
Files changed (123) hide show
  1. package/dist/_vendor/kortix-shared.js +489 -381
  2. package/dist/customize/agents/agent-authority-card.js +1 -2
  3. package/dist/customize/agents/agent-detail-aside.js +15 -14
  4. package/dist/customize/agents/agent-drives-section.js +5 -6
  5. package/dist/customize/agents/agent-grant-pages.js +68 -70
  6. package/dist/customize/agents/agent-nav.prototype.d.ts +35 -0
  7. package/dist/customize/agents/agent-nav.prototype.js +95 -0
  8. package/dist/customize/agents/agent-page.js +57 -22
  9. package/dist/customize/agents/agent-people-section.js +18 -17
  10. package/dist/customize/agents/agent-triggers-section.js +6 -5
  11. package/dist/customize/connectors/catalog/catalog-entry.d.ts +14 -0
  12. package/dist/customize/connectors/catalog/catalog-entry.js +18 -1
  13. package/dist/customize/connectors/catalog/connector-browse.d.ts +28 -0
  14. package/dist/customize/connectors/catalog/connector-browse.js +18 -5
  15. package/dist/customize/connectors/detail/app-page.js +19 -5
  16. package/dist/customize/connectors/detail/connector-modal.d.ts +10 -13
  17. package/dist/customize/connectors/detail/connector-modal.js +18 -101
  18. package/dist/customize/connectors/detail/connector-notice.js +6 -2
  19. package/dist/customize/connectors/detail/connector-page.d.ts +30 -0
  20. package/dist/customize/connectors/detail/connector-page.js +26 -13
  21. package/dist/customize/sections/llm-provider/custom-provider-form.js +24 -7
  22. package/dist/customize/sections/llm-provider/custom-provider-panel.js +44 -8
  23. package/dist/customize/sections/llm-provider/types.d.ts +3 -0
  24. package/dist/customize/sections/llm-provider/utils.js +2 -2
  25. package/dist/customize/sections/view/agent-editor-access-fields.d.ts +9 -16
  26. package/dist/customize/sections/view/agent-editor-access-fields.js +30 -30
  27. package/dist/customize/sections/view/agent-editor-basics-fields.js +3 -10
  28. package/dist/customize/sections/view/agent-editor-primitives.d.ts +28 -10
  29. package/dist/customize/sections/view/agent-editor-primitives.js +32 -19
  30. package/dist/customize/sections/view/agent-editor.js +3 -3
  31. package/dist/customize/sections/view/gateway/gateway-routing.js +3 -3
  32. package/dist/customize/sections/view/grant-mode-field.d.ts +2 -5
  33. package/dist/customize/sections/view/grant-mode-field.js +10 -18
  34. package/dist/customize/sections/view/permission-editor.js +11 -8
  35. package/dist/customize/sections/view/secrets-view.js +2 -1
  36. package/dist/customize/settings/tabs/general-tab.d.ts +9 -2
  37. package/dist/customize/settings/tabs/general-tab.js +33 -11
  38. package/dist/customize/settings/tabs/transfer-workspace-dialog.d.ts +4 -0
  39. package/dist/customize/settings/tabs/transfer-workspace-dialog.js +82 -0
  40. package/dist/files/project/api/runtime-files.js +3 -2
  41. package/dist/files/project/file-source.js +18 -1
  42. package/dist/files/project/hooks/use-file-content.js +2 -0
  43. package/dist/files/viewer/file-header.js +1 -1
  44. package/dist/files/viewer/file-preview-modal.d.ts +1 -1
  45. package/dist/files/viewer/file-preview-modal.js +12 -2
  46. package/dist/files/viewer/file-source.d.ts +3 -1
  47. package/dist/files/viewer/use-file-content-state.js +26 -7
  48. package/dist/files/viewer/viewer-actions.js +2 -2
  49. package/dist/i18n/en.d.ts +345 -12
  50. package/dist/i18n/en.js +350 -17
  51. package/dist/internal/files/types.d.ts +2 -0
  52. package/dist/internal/goals/goal-meta.d.ts +30 -0
  53. package/dist/internal/goals/goal-meta.js +55 -0
  54. package/dist/internal/lib/query-client-singleton.d.ts +9 -3
  55. package/dist/internal/lib/query-client-singleton.js +18 -12
  56. package/dist/internal/share/session-shares-modal.js +3 -7
  57. package/dist/internal/stores/kortix-computer-store.js +14 -2
  58. package/dist/internal/stores/session-hover-store.d.ts +32 -0
  59. package/dist/internal/stores/session-hover-store.js +38 -0
  60. package/dist/internal/stores/sidebar-nav-store.d.ts +1 -1
  61. package/dist/internal/stores/sidebar-nav-store.js +3 -1
  62. package/dist/lib/routes.d.ts +2 -0
  63. package/dist/lib/routes.js +1 -0
  64. package/dist/primitives/settings-section-header.d.ts +1 -1
  65. package/dist/session/composer/attachment-tile.d.ts +0 -2
  66. package/dist/session/composer/attachment-tile.js +0 -8
  67. package/dist/session/composer/clipboard-files.d.ts +2 -1
  68. package/dist/session/composer/composer-draft-recovery.d.ts +1 -2
  69. package/dist/session/composer/composer-draft-recovery.js +0 -13
  70. package/dist/session/composer/context-ring.d.ts +1 -1
  71. package/dist/session/composer/context-ring.js +2 -2
  72. package/dist/session/composer/context-usage.d.ts +3 -6
  73. package/dist/session/composer/context-usage.js +3 -6
  74. package/dist/session/composer/inbox-row-claims.d.ts +2 -2
  75. package/dist/session/composer/inbox-row-claims.js +1 -1
  76. package/dist/session/composer/queue-projection.d.ts +3 -2
  77. package/dist/session/composer/queued-prompt-edit.d.ts +1 -1
  78. package/dist/session/composer/reasoning-effort-selector.d.ts +2 -1
  79. package/dist/session/composer/session-composer-readiness.d.ts +7 -22
  80. package/dist/session/composer/session-composer-readiness.js +12 -40
  81. package/dist/session/composer/token-progress.d.ts +1 -1
  82. package/dist/session/composer/token-progress.js +2 -2
  83. package/dist/session/header/session-goal-indicator.d.ts +1 -0
  84. package/dist/session/header/session-goal-indicator.js +41 -0
  85. package/dist/session/header/session-site-header.js +2 -1
  86. package/dist/session/panel/session-action-panel-column.js +11 -1
  87. package/dist/session/panel/session-audit-shared.d.ts +0 -4
  88. package/dist/session/panel/session-audit-shared.js +1 -1
  89. package/dist/session/panel/session-changes-shared.d.ts +2 -1
  90. package/dist/session/prompts/session-permission-prompt.js +6 -3
  91. package/dist/session/status/provisioning-failure.d.ts +2 -1
  92. package/dist/session/status/session-error-banner.js +8 -6
  93. package/dist/session/status/session-starting-loader.d.ts +24 -31
  94. package/dist/session/status/session-starting-loader.js +32 -81
  95. package/dist/session/thread/chat-minimap-items.d.ts +4 -4
  96. package/dist/session/thread/first-prompt-handover.d.ts +3 -2
  97. package/dist/session/thread/message-parsing.d.ts +3 -3
  98. package/dist/session/thread/session-chat.js +3 -10
  99. package/dist/session/thread/session-history-scroll.d.ts +2 -1
  100. package/dist/session/thread/session-thread.js +1 -1
  101. package/dist/styles.css +1 -1
  102. package/dist/terminal/pty-connection.d.ts +5 -4
  103. package/dist/workspace/index.d.ts +1 -0
  104. package/dist/workspace/index.js +1 -0
  105. package/dist/workspace/saved-session-skeleton-shape.d.ts +4 -3
  106. package/dist/workspace/saved-session-skeleton.d.ts +5 -1
  107. package/dist/workspace/saved-session-skeleton.js +5 -4
  108. package/dist/workspace/session-workspace.js +4 -5
  109. package/dist/workspace/sidebar/footer/project-goals-nav.d.ts +6 -0
  110. package/dist/workspace/sidebar/footer/project-goals-nav.js +26 -0
  111. package/dist/workspace/sidebar/modal/session-embed-section.d.ts +25 -0
  112. package/dist/workspace/sidebar/modal/session-embed-section.js +71 -0
  113. package/dist/workspace/sidebar/modal/share-session-modal.js +2 -2
  114. package/dist/workspace/sidebar/nav-row-meta.js +14 -2
  115. package/dist/workspace/sidebar/project-nav-items.js +3 -0
  116. package/dist/workspace/sidebar/project-session-list.js +12 -3
  117. package/dist/workspace/sidebar/session-brief-hover-card.js +5 -8
  118. package/package.json +4 -4
  119. package/skills/kortix-ui/references/modules.md +2 -0
  120. package/dist/session/status/use-readiness-settling.d.ts +0 -18
  121. package/dist/session/status/use-readiness-settling.js +0 -43
  122. package/dist/workspace/sidebar/modal/session-public-link-section.d.ts +0 -13
  123. package/dist/workspace/sidebar/modal/session-public-link-section.js +0 -66
@@ -9,7 +9,6 @@ import { useTranslations as useI18nTranslations } from '../../../i18n/index.js';
9
9
  * (`kortix.yaml`) rather than the question they answer. Same writes, same
10
10
  * platform enforcement; the heading now says what it governs.
11
11
  */
12
- import { Badge } from '../../../primitives/badge.js';
13
12
  import { Button } from '../../../primitives/button.js';
14
13
  import Hint from '../../../primitives/hint.js';
15
14
  import { Switch } from '../../../primitives/switch.js';
@@ -17,11 +16,11 @@ import { capabilityTabHref } from '../../../internal/lib/capability-tab-routes.j
17
16
  import { SandboxTemplateMenu, describeSandboxTemplate, } from '../../../access/sandbox-template-menu.js';
18
17
  import { cn } from '../../../internal/lib/utils.js';
19
18
  import { useKortixRouteProjectId } from '@kortix/sdk/react';
20
- import { ArrowRightIcon, CaretDownIcon, CubeIcon } from '@phosphor-icons/react';
19
+ import { CaretDownIcon, CubeIcon } from '@phosphor-icons/react';
21
20
  import { UiLink as Link } from '../../../providers/ui-provider.js';
22
21
  import { EditorSection, SettingRow } from './agent-editor-primitives.js';
23
22
  import { pruneRequiredConnectors } from './connectors-personal.js';
24
- import { GrantSetField, KortixPermissionsField, grantSummary } from './grant-mode-field.js';
23
+ import { GrantSetField, KortixPermissionsField } from './grant-mode-field.js';
25
24
  /**
26
25
  * Marks one granted connector as required before session start.
27
26
  *
@@ -31,27 +30,28 @@ import { GrantSetField, KortixPermissionsField, grantSummary } from './grant-mod
31
30
  */
32
31
  export function RequiredConnectorToggle({ active, onToggle, }) {
33
32
  const tI18nComplete = useI18nTranslations('hardcodedUi.i18nComplete');
34
- return (_jsx(Hint, { label: active ? tI18nComplete.raw('text49c8975f345b') : tI18nComplete.raw('texta54220c82b33'), children: _jsx("button", { type: "button", "aria-pressed": active, "aria-label": active ? tI18nComplete.raw('textd16c94c19673') : tI18nComplete.raw('text63336c8a8e83'), onClick: onToggle, className: cn('shrink-0 rounded px-1.5 py-1 text-xs transition-[color,background-color,transform] active:scale-[0.96]', active
35
- ? 'bg-kortix-purple/15 text-kortix-purple font-medium'
36
- : 'text-muted-foreground/50 hover:text-muted-foreground hover:bg-muted/50'), children: tI18nComplete.raw('text4850b174b713') }) }));
37
- }
38
- /** The summary chip at a grant card's right edge — "All", "3 picked", "None". */
39
- export function GrantChip({ value }) {
40
- const tI18nComplete = useI18nTranslations('hardcodedUi.i18nComplete');
41
- const summary = grantSummary(value, tI18nComplete);
42
- return (_jsx(Badge, { variant: summary.tone === 'muted' ? 'muted' : 'outline', size: "sm", className: "tabular-nums", children: summary.label }));
33
+ return (_jsx(Hint, { label: active ? tI18nComplete.raw('text49c8975f345b') : tI18nComplete.raw('texta54220c82b33'), children: _jsx(Button, { type: "button", variant: active ? 'secondary' : 'ghost', size: "sm", "aria-pressed": active, "aria-label": active ? tI18nComplete.raw('textd16c94c19673') : tI18nComplete.raw('text63336c8a8e83'), onClick: onToggle, className: cn('shrink-0', !active && 'text-muted-foreground'), children: tI18nComplete.raw('text4850b174b713') }) }));
43
34
  }
44
35
  /**
45
- * Chip plus a link to the project-wide page for the same thing. A grant page
46
- * picks from what the project has; adding, editing or removing one of them
47
- * happens on its own Customize tab (Marko, 2026-09-03: "for now … point to
48
- * the general page … to see & browse em all"). Full CRUD in place is the
49
- * follow-up.
36
+ * The section action of a grant page: one `secondary` button to the
37
+ * project-wide page for the same thing. A grant page picks from what the
38
+ * project has; adding, editing or removing one happens on its own Customize
39
+ * tab. The grant mode row already states All / Pick / None, so the header
40
+ * carries no summary chip.
50
41
  */
51
- export function GrantHeaderTrailing({ value, tab, href, label, }) {
42
+ export function ManageButton({ tab, href, }) {
43
+ const tEditor = useI18nTranslations('agentEditor');
52
44
  const projectId = useKortixRouteProjectId();
53
- const target = projectId ? (href ? href(projectId) : tab ? capabilityTabHref(projectId, tab) : null) : null;
54
- return (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(GrantChip, { value: value }), target ? (_jsx(Button, { asChild: true, variant: "ghost", size: "sm", className: "gap-1 px-2", children: _jsxs(Link, { href: target, prefetch: true, children: [label, _jsx(ArrowRightIcon, { className: "size-3.5 shrink-0" })] }) })) : null] }));
45
+ const target = projectId
46
+ ? href
47
+ ? href(projectId)
48
+ : tab
49
+ ? capabilityTabHref(projectId, tab)
50
+ : null
51
+ : null;
52
+ if (!target)
53
+ return null;
54
+ return (_jsx(Button, { asChild: true, variant: "secondary", size: "sm", children: _jsx(Link, { href: target, prefetch: true, children: tEditor('manage') }) }));
55
55
  }
56
56
  /*
57
57
  * Each grant set is its own page on the agent editor's rail (Marko,
@@ -60,17 +60,17 @@ export function GrantHeaderTrailing({ value, tab, href, label, }) {
60
60
  */
61
61
  export function SkillsSection({ draft, set, options }) {
62
62
  const tI18nComplete = useI18nTranslations('hardcodedUi.i18nComplete');
63
- return (_jsx(EditorSection, { title: tI18nComplete.raw('text66d0f523a379'), description: tI18nComplete.raw('textb27e54100c96'), trailing: _jsx(GrantHeaderTrailing, { value: draft.skills, tab: "skills", label: tI18nComplete.raw('text78abcbbfb830') }), children: _jsx("div", { className: "py-4", children: _jsx(GrantSetField, { value: draft.skills, onChange: (v) => set('skills', v), options: options, allLabel: tI18nComplete.raw('textf059c2dbe260'), emptyLabel: tI18nComplete.raw('text66e36043ff7c') }) }) }));
63
+ return (_jsx(EditorSection, { title: tI18nComplete.raw('text66d0f523a379'), description: tI18nComplete.raw('textb27e54100c96'), trailing: _jsx(ManageButton, { tab: "skills" }), lead: true, bare: true, children: _jsx(GrantSetField, { value: draft.skills, onChange: (v) => set('skills', v), options: options, emptyLabel: tI18nComplete.raw('text66e36043ff7c') }) }));
64
64
  }
65
65
  export function ConnectorsSection({ draft, set, options }) {
66
66
  const tI18nComplete = useI18nTranslations('hardcodedUi.i18nComplete');
67
- return (_jsx(EditorSection, { title: tI18nComplete.raw('textc3d2e79ebdd0'), description: tI18nComplete.raw('text00f5aae9f9d3'), trailing: _jsx(GrantHeaderTrailing, { value: draft.connectors, tab: "connectors", label: tI18nComplete.raw('textd83250185d41') }), children: _jsxs("div", { className: "space-y-2 py-4", children: [_jsx(GrantSetField, { value: draft.connectors, onChange: (v) => {
67
+ return (_jsx(EditorSection, { title: tI18nComplete.raw('textc3d2e79ebdd0'), description: tI18nComplete.raw('text00f5aae9f9d3'), trailing: _jsx(ManageButton, { tab: "connectors" }), lead: true, bare: true, children: _jsxs("div", { className: "space-y-3", children: [_jsx(GrantSetField, { value: draft.connectors, onChange: (v) => {
68
68
  set('connectors', v);
69
69
  const pruned = pruneRequiredConnectors(draft.connectors_required, v);
70
70
  if (pruned?.length !== draft.connectors_required?.length) {
71
71
  set('connectors_required', pruned);
72
72
  }
73
- }, options: options, allLabel: tI18nComplete.raw('text35e54cea7f41'), emptyLabel: tI18nComplete.raw('text389fb5217392'), rowAccessory: (id, isSelected) => isSelected ? (_jsx(RequiredConnectorToggle, { active: draft.connectors_required?.includes(id) === true, onToggle: () => {
73
+ }, options: options, emptyLabel: tI18nComplete.raw('text389fb5217392'), rowAccessory: (id, isSelected) => isSelected ? (_jsx(RequiredConnectorToggle, { active: draft.connectors_required?.includes(id) === true, onToggle: () => {
74
74
  const current = draft.connectors_required ?? [];
75
75
  const next = current.includes(id)
76
76
  ? current.filter((a) => a !== id)
@@ -80,7 +80,7 @@ export function ConnectorsSection({ draft, set, options }) {
80
80
  }
81
81
  export function SecretsSection({ draft, set, options }) {
82
82
  const tI18nComplete = useI18nTranslations('hardcodedUi.i18nComplete');
83
- return (_jsx(EditorSection, { title: tI18nComplete.raw('textd8707d411d99'), description: tI18nComplete.raw('text7f619d9e30a8'), trailing: _jsx(GrantHeaderTrailing, { value: draft.secrets, tab: "secrets", label: tI18nComplete.raw('text0b38e3daeb93') }), children: _jsx("div", { className: "py-4", children: _jsx(GrantSetField, { value: draft.secrets, onChange: (v) => set('secrets', v), options: options, allLabel: tI18nComplete.raw('text86fdc0c950d5'), emptyLabel: tI18nComplete.raw('text82a37b8c2266') }) }) }));
83
+ return (_jsx(EditorSection, { title: tI18nComplete.raw('textd8707d411d99'), description: tI18nComplete.raw('text7f619d9e30a8'), trailing: _jsx(ManageButton, { tab: "secrets" }), lead: true, bare: true, children: _jsx(GrantSetField, { value: draft.secrets, onChange: (v) => set('secrets', v), options: options, emptyLabel: tI18nComplete.raw('text82a37b8c2266') }) }));
84
84
  }
85
85
  /**
86
86
  * A kortix_version 3 grant over a project registry: the declared subagents
@@ -90,7 +90,7 @@ export function SecretsSection({ draft, set, options }) {
90
90
  */
91
91
  export function RegistryGrantSection({ grant, draft, set, options, }) {
92
92
  const t = useI18nTranslations('agents.grants');
93
- return (_jsx(EditorSection, { title: t(`${grant}.title`), description: t(`${grant}.description`), trailing: _jsx(GrantChip, { value: draft[grant] }), children: _jsx("div", { className: "py-4", children: _jsx(GrantSetField, { value: draft[grant], onChange: (v) => set(grant, v), options: options, allLabel: t(`${grant}.all`), emptyLabel: t(`${grant}.empty`) }) }) }));
93
+ return (_jsx(EditorSection, { title: t(`${grant}.title`), description: t(`${grant}.description`), lead: true, bare: true, children: _jsx(GrantSetField, { value: draft[grant], onChange: (v) => set(grant, v), options: options, emptyLabel: t(`${grant}.empty`) }) }));
94
94
  }
95
95
  /** Kortix permissions (`kortix_permissions` in kortix.yaml): which project
96
96
  * operations the agent may perform, through any surface. A block read from a
@@ -99,10 +99,10 @@ export function RegistryGrantSection({ grant, draft, set, options, }) {
99
99
  export function ProjectActionsSection({ draft, set }) {
100
100
  const tI18nComplete = useI18nTranslations('hardcodedUi.i18nComplete');
101
101
  const permissions = draft.kortix_permissions ?? draft.kortix_cli;
102
- return (_jsx(EditorSection, { title: tI18nComplete.raw('text8f12a6e05e6d'), description: tI18nComplete.raw('text15365eb45e29'), trailing: _jsx(GrantChip, { value: permissions }), children: _jsx("div", { className: "py-4", children: _jsx(KortixPermissionsField, { value: permissions, onChange: (v) => {
103
- set('kortix_cli', undefined);
104
- set('kortix_permissions', v);
105
- } }) }) }));
102
+ return (_jsx(EditorSection, { title: tI18nComplete.raw('text8f12a6e05e6d'), description: tI18nComplete.raw('text15365eb45e29'), lead: true, bare: true, children: _jsx(KortixPermissionsField, { value: permissions, onChange: (v) => {
103
+ set('kortix_cli', undefined);
104
+ set('kortix_permissions', v);
105
+ } }) }));
106
106
  }
107
107
  export function WorkspaceSection({ draft, set, sandboxTemplates, defaultSandboxSlug, }) {
108
108
  const tI18nComplete = useI18nTranslations('hardcodedUi.i18nComplete');
@@ -116,7 +116,7 @@ export function WorkspaceSection({ draft, set, sandboxTemplates, defaultSandboxS
116
116
  // manifest on the next save.
117
117
  const stalePin = draft.sandbox && !pinned ? draft.sandbox : null;
118
118
  const PinnedIcon = pinned ? describeSandboxTemplate(pinned).Icon : CubeIcon;
119
- return (_jsxs(EditorSection, { title: tI18nComplete.raw('text87bb59ba2f92'), description: tI18nComplete.raw('text76a5e5a39b4a'), children: [_jsx(SettingRow, { label: tI18nComplete.raw('text9e471951a1b4'), help: draft.sandbox
119
+ return (_jsxs(EditorSection, { title: tI18nComplete.raw('text87bb59ba2f92'), description: tI18nComplete.raw('text76a5e5a39b4a'), lead: true, children: [_jsx(SettingRow, { label: tI18nComplete.raw('text9e471951a1b4'), help: draft.sandbox
120
120
  ? stalePin
121
121
  ? tI18nComplete.raw('textb1a5c13d215e')
122
122
  : tI18nComplete.raw('text0703d9121fd7')
@@ -16,7 +16,6 @@ import { useTranslations as useI18nTranslations } from '../../../i18n/index.js';
16
16
  * section to match would strand one switch in a section of its own for a
17
17
  * reason no reader could see.
18
18
  */
19
- import { Badge } from '../../../primitives/badge.js';
20
19
  import { Button } from '../../../primitives/button.js';
21
20
  import { Disclosure, DisclosureContent, DisclosureTrigger } from '../../../primitives/disclosure.js';
22
21
  import { Input } from '../../../primitives/input.js';
@@ -34,7 +33,7 @@ import { EditorSection, InlineAction, SettingBlock, SettingRow } from './agent-e
34
33
  const INHERIT = '__inherit__';
35
34
  export function BasicsSection({ draft, set, oc, setOc, showDescription = true, }) {
36
35
  const tI18nComplete = useI18nTranslations('hardcodedUi.i18nComplete');
37
- return (_jsxs(EditorSection, { title: tI18nComplete.raw('text8fdd2ee8475e'), description: tI18nComplete.raw('text4e420a5186f0'), children: [_jsx(SettingRow, { label: tI18nComplete.raw('text92c1cdfdf4cb'), help: tI18nComplete.raw('textbe90a56d29da'), children: _jsx("div", { className: "flex sm:justify-end", children: _jsx(Switch, { "aria-label": tI18nComplete.raw('text92c1cdfdf4cb'), checked: draft.enabled !== false, onCheckedChange: (v) => set('enabled', v ? undefined : false) }) }) }), showDescription ? (_jsx(SettingBlock, { label: tI18nComplete.raw('text526e0087cc3f'), help: oc.mode === 'subagent'
36
+ return (_jsxs(EditorSection, { title: tI18nComplete.raw('text8fdd2ee8475e'), description: tI18nComplete.raw('text4e420a5186f0'), lead: true, children: [_jsx(SettingRow, { label: tI18nComplete.raw('text92c1cdfdf4cb'), help: tI18nComplete.raw('textbe90a56d29da'), children: _jsx("div", { className: "flex sm:justify-end", children: _jsx(Switch, { "aria-label": tI18nComplete.raw('text92c1cdfdf4cb'), checked: draft.enabled !== false, onCheckedChange: (v) => set('enabled', v ? undefined : false) }) }) }), showDescription ? (_jsx(SettingBlock, { label: tI18nComplete.raw('text526e0087cc3f'), help: oc.mode === 'subagent'
38
37
  ? tI18nComplete.raw('text77e2bc11f6ab')
39
38
  : tI18nComplete.raw('text9965df7c3221'), children: _jsx(Textarea, { "aria-label": tI18nComplete.raw('text526e0087cc3f'), value: oc.description ?? '', placeholder: tI18nComplete.raw('text446f4eabf99f'), minHeight: 44, className: "text-sm", onChange: (e) => setOc('description', e.target.value) }) })) : null, _jsx(SettingRow, { label: tI18nComplete.raw('text12f67f8539c4'), help: oc.mode ? AGENT_MODE_HELP[oc.mode] : tI18nComplete.raw('text64f405e80a8d'), children: _jsxs(Select, { value: oc.mode ?? INHERIT, onValueChange: (value) => setOc('mode', value === INHERIT ? undefined : value), children: [_jsx(SelectTrigger, { "aria-label": tI18nComplete.raw('text12f67f8539c4'), className: "h-9 w-full", children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: INHERIT, children: tI18nComplete.raw('texte8cb80e5c5cb') }), AGENT_MODES.map((mode) => (_jsx(SelectItem, { value: mode, children: AGENT_MODE_LABEL[mode] }, mode)))] })] }) }), _jsx(SettingRow, { label: tI18nComplete.raw('textc7bcb471c03d'), help: tI18nComplete.raw('textdd4971af3f91'), children: _jsx("div", { className: "flex sm:justify-end", children: _jsx(Switch, { "aria-label": tI18nComplete.raw('textc7bcb471c03d'), checked: !oc.hidden, onCheckedChange: (v) => setOc('hidden', v ? undefined : true) }) }) })] }));
40
39
  }
@@ -51,17 +50,11 @@ export function ModelSection({ oc, setOc, showPrompt = true, }) {
51
50
  ? models.find((m) => m.providerID === selectedModelKey.providerID && m.modelID === selectedModelKey.modelID)
52
51
  : undefined;
53
52
  const variantChoices = selectedModel?.variants ? Object.keys(selectedModel.variants) : [];
54
- // The sampling knobs and the step cap are set on a handful of agents and
55
- // read by fewer. They open only when one of them carries a value, so an
56
- // agent that tunes nothing shows one row — the model — and nothing else.
57
- const advancedSet = !isSliderAtDefault(oc.temperature, 0) ||
58
- !isSliderAtDefault(oc.top_p, 1) ||
59
- oc.steps !== undefined;
60
- return (_jsxs(_Fragment, { children: [_jsxs(EditorSection, { title: tI18nComplete.raw('text5e2c614c23f0'), description: tI18nComplete.raw('text32398dbb68e2'), children: [_jsx(SettingRow, { label: tI18nComplete.raw('text34455bf1d857'), help: oc.model ? (_jsx(InlineAction, { onClick: () => setOc('model', undefined), children: tI18nComplete.raw('text9db60344e984') })) : (tI18nComplete.raw('text64f405e80a8d')), children: _jsx("div", { className: "flex sm:justify-end", children: _jsx(ModelSelector, { models: models, providers: providers, selectedModel: selectedModelKey, unsetLabel: tI18nComplete.raw('texte8cb80e5c5cb'), onSelect: (m) => setOc('model', m ? modelKeyToWire(m) : undefined) }) }) }), variantChoices.length > 0 ? (_jsx(SettingRow, { label: tI18nComplete.raw('text264c28cbf01c'), help: oc.variant
53
+ return (_jsxs(_Fragment, { children: [_jsxs(EditorSection, { title: tI18nComplete.raw('text5e2c614c23f0'), description: tI18nComplete.raw('text32398dbb68e2'), lead: true, children: [_jsx(SettingRow, { label: tI18nComplete.raw('text34455bf1d857'), help: oc.model ? (_jsx(InlineAction, { onClick: () => setOc('model', undefined), children: tI18nComplete.raw('text9db60344e984') })) : (tI18nComplete.raw('text64f405e80a8d')), children: _jsx("div", { className: "flex sm:justify-end", children: _jsx(ModelSelector, { models: models, providers: providers, selectedModel: selectedModelKey, unsetLabel: tI18nComplete.raw('texte8cb80e5c5cb'), onSelect: (m) => setOc('model', m ? modelKeyToWire(m) : undefined) }) }) }), variantChoices.length > 0 ? (_jsx(SettingRow, { label: tI18nComplete.raw('text264c28cbf01c'), help: oc.variant
61
54
  ? tI18nComplete.raw('text4dd21464c579')
62
55
  : tI18nComplete.raw('textf39c806f5724'), children: _jsx("div", { className: "flex sm:justify-end", children: _jsx(ReasoningEffortSelector, { variants: variantChoices, selectedVariant: oc.variant ?? null, onVariantChange: (v) => setOc('variant', v ?? undefined) }) }) })) : (_jsx(SettingRow, { label: tI18nComplete.raw('text3f19fe84a2de'), help: selectedModelKey
63
56
  ? tI18nComplete.raw('text0443f619cb33')
64
- : tI18nComplete.raw('text6376d74077c0'), children: _jsx(Input, { "aria-label": tI18nComplete.raw('text3f19fe84a2de'), value: oc.variant ?? '', placeholder: tI18nComplete.raw('text352a25678fb9'), variant: "popover", className: "h-9 w-full text-sm", onChange: (e) => setOc('variant', e.target.value) }) })), showPrompt ? (_jsx(SettingBlock, { label: tI18nComplete.raw('text561257c019e5'), help: tI18nComplete.raw('textad63817393a7'), children: _jsxs(Disclosure, { variant: "outline", className: "overflow-hidden rounded-md", children: [_jsx(DisclosureTrigger, { variant: "outline", children: _jsxs(Button, { variant: "popover", className: "flex w-full items-center justify-between gap-3 rounded-none text-sm font-normal", children: [_jsx("span", { className: "min-w-0 truncate", children: oc.prompt ? firstLine(oc.prompt) : tI18nComplete.raw('textdaaf5ab03267') }), _jsx("span", { className: "text-muted-foreground shrink-0 text-xs", children: oc.prompt ? 'Edit' : tI18nComplete.raw('text47f3fe537320') })] }) }), _jsx(DisclosureContent, { variant: "outline", contentClassName: "border-border border-t", children: _jsx(Textarea, { "aria-label": tI18nComplete.raw('text561257c019e5'), value: oc.prompt ?? '', placeholder: tI18nComplete.raw('text94a18ea1d428'), minHeight: 160, className: "rounded-none border-0 font-mono text-xs focus-visible:border-0 focus-visible:ring-0", onChange: (e) => setOc('prompt', e.target.value) }) })] }) })) : null] }), _jsxs(EditorSection, { title: tI18nComplete.raw('text6d06116595a9'), description: tI18nComplete.raw('text33439eb47c9a'), trailing: _jsx(Badge, { variant: advancedSet ? 'outline' : 'muted', size: "sm", children: advancedSet ? 'Customized' : 'Defaults' }), children: [_jsx(SliderRow, { label: tI18nComplete.raw('textb958ce8b871a'), help: tI18nComplete.raw('textd380d30f3d60'), value: oc.temperature, fallback: 0, min: 0, max: 2, step: 0.05, onChange: (v) => setOc('temperature', v) }), _jsx(SliderRow, { label: tI18nComplete.raw('text714db3dbb0b7'), help: tI18nComplete.raw('text4f370db531ba'), value: oc.top_p, fallback: 1, min: 0, max: 1, step: 0.01, onChange: (v) => setOc('top_p', v) }), _jsx(SettingRow, { label: tI18nComplete.raw('textfdc639c47624'), help: tI18nComplete.raw('textbf7ff92baea3'), children: _jsx(Input, { "aria-label": tI18nComplete.raw('textfdc639c47624'), type: "number", min: 1, value: oc.steps ?? '', placeholder: tI18nComplete.raw('textf7fcff0d8fea'), variant: "popover", className: "h-9 w-full text-sm tabular-nums", onChange: (e) => setOc('steps', e.target.value ? Math.max(1, Number(e.target.value)) : undefined) }) })] })] }));
57
+ : tI18nComplete.raw('text6376d74077c0'), children: _jsx(Input, { "aria-label": tI18nComplete.raw('text3f19fe84a2de'), value: oc.variant ?? '', placeholder: tI18nComplete.raw('text352a25678fb9'), variant: "popover", className: "h-9 w-full text-sm", onChange: (e) => setOc('variant', e.target.value) }) })), showPrompt ? (_jsx(SettingBlock, { label: tI18nComplete.raw('text561257c019e5'), help: tI18nComplete.raw('textad63817393a7'), children: _jsxs(Disclosure, { variant: "outline", className: "overflow-hidden rounded-md", children: [_jsx(DisclosureTrigger, { variant: "outline", children: _jsxs(Button, { variant: "popover", className: "flex w-full items-center justify-between gap-3 rounded-none text-sm font-normal", children: [_jsx("span", { className: "min-w-0 truncate", children: oc.prompt ? firstLine(oc.prompt) : tI18nComplete.raw('textdaaf5ab03267') }), _jsx("span", { className: "text-muted-foreground shrink-0 text-xs", children: oc.prompt ? 'Edit' : tI18nComplete.raw('text47f3fe537320') })] }) }), _jsx(DisclosureContent, { variant: "outline", contentClassName: "border-border border-t", children: _jsx(Textarea, { "aria-label": tI18nComplete.raw('text561257c019e5'), value: oc.prompt ?? '', placeholder: tI18nComplete.raw('text94a18ea1d428'), minHeight: 160, className: "rounded-none border-0 font-mono text-xs focus-visible:border-0 focus-visible:ring-0", onChange: (e) => setOc('prompt', e.target.value) }) })] }) })) : null] }), _jsxs(EditorSection, { title: tI18nComplete.raw('text6d06116595a9'), description: tI18nComplete.raw('text33439eb47c9a'), children: [_jsx(SliderRow, { label: tI18nComplete.raw('textb958ce8b871a'), help: tI18nComplete.raw('textd380d30f3d60'), value: oc.temperature, fallback: 0, min: 0, max: 2, step: 0.05, onChange: (v) => setOc('temperature', v) }), _jsx(SliderRow, { label: tI18nComplete.raw('text714db3dbb0b7'), help: tI18nComplete.raw('text4f370db531ba'), value: oc.top_p, fallback: 1, min: 0, max: 1, step: 0.01, onChange: (v) => setOc('top_p', v) }), _jsx(SettingRow, { label: tI18nComplete.raw('textfdc639c47624'), help: tI18nComplete.raw('textbf7ff92baea3'), children: _jsx(Input, { "aria-label": tI18nComplete.raw('textfdc639c47624'), type: "number", min: 1, value: oc.steps ?? '', placeholder: tI18nComplete.raw('textf7fcff0d8fea'), variant: "popover", className: "h-9 w-full text-sm tabular-nums", onChange: (e) => setOc('steps', e.target.value ? Math.max(1, Number(e.target.value)) : undefined) }) })] })] }));
65
58
  }
66
59
  /**
67
60
  * Whether a slider row is showing its default.
@@ -9,6 +9,7 @@
9
9
  * titles at `text-sm font-medium`, help at `text-xs text-muted-foreground`.
10
10
  * Those two sizes are the whole scale; nothing in the editor is smaller.
11
11
  */
12
+ import type * as React from 'react';
12
13
  import { type ReactNode } from 'react';
13
14
  /**
14
15
  * How a section draws itself. `flat` is the original: a heading over
@@ -27,19 +28,36 @@ export type EditorSectionStyle = 'flat' | 'panel';
27
28
  export declare function EditorSectionStyleProvider({ value, children, }: {
28
29
  value: EditorSectionStyle;
29
30
  children: ReactNode;
30
- }): import("react").JSX.Element;
31
+ }): React.JSX.Element;
31
32
  /**
32
- * One titled group of settings. Rows inside are separated by hairlines rather
33
- * than boxed individually. See `EditorSectionStyle` for the two dialects.
33
+ * One titled group of settings, in the Settings page's dialect
34
+ * (`settings/tabs/general-tab.tsx`): the heading sits on the page, never
35
+ * inside a box, and only the rows below it share one bordered group.
36
+ *
37
+ * `lead` marks the first section of a pane. It takes the pane title
38
+ * (`SettingsSectionHeader`, `text-base lg:text-xl`). Every later section
39
+ * takes the quieter `SettingsSubsectionHeader`. Neither shows `description`
40
+ * on the agent page; it renders only in the legacy `flat` style.
41
+ *
42
+ * `bare` hands the body to the caller unwrapped: a list (`GrantList`), a
43
+ * markdown preview, or a textarea draws its own surface.
34
44
  */
35
- export declare function EditorSection({ title, description, trailing, children, }: {
45
+ export declare function EditorSection({ title, description, trailing, lead, bare, children, }: {
36
46
  title: string;
37
47
  description?: ReactNode;
38
- /** A summary at the header's right edge — a `Badge` saying "All" or
39
- * "3 picked" — so a card answers its question before it is opened. */
48
+ /** The section's action at the header's right edge: one `secondary`
49
+ * button (New, Manage) or a small control such as the Edit / Preview tabs. */
40
50
  trailing?: ReactNode;
51
+ lead?: boolean;
52
+ bare?: boolean;
41
53
  children: ReactNode;
42
- }): import("react").JSX.Element;
54
+ }): React.JSX.Element;
55
+ /**
56
+ * The bordered list a section hands its rows to: one `bg-popover` group,
57
+ * hairlines between rows, no per-row box. A stack of individually bordered
58
+ * cards read as ten announcements; one group reads as one list.
59
+ */
60
+ export declare function EditorList({ className, ...props }: React.ComponentProps<'ul'>): React.JSX.Element;
43
61
  /**
44
62
  * Label and help on the left, control on the right — for anything that fits a
45
63
  * switch, a select, a slider, or a short input. Stacks under `sm` so a narrow
@@ -52,7 +70,7 @@ export declare function SettingRow({ label, help, children, }: {
52
70
  label: string;
53
71
  help?: ReactNode;
54
72
  children: ReactNode;
55
- }): import("react").JSX.Element;
73
+ }): React.JSX.Element;
56
74
  /**
57
75
  * Label and help above a full-width control — for anything a row cannot hold:
58
76
  * a textarea, a grant checklist, the permission tree.
@@ -61,7 +79,7 @@ export declare function SettingBlock({ label, help, children, }: {
61
79
  label: string;
62
80
  help?: ReactNode;
63
81
  children: ReactNode;
64
- }): import("react").JSX.Element;
82
+ }): React.JSX.Element;
65
83
  /**
66
84
  * A text button that lives inside a help line — "Reset", "Clear". Text, not an
67
85
  * icon: at this size an icon is a guess, and the word is three characters
@@ -70,4 +88,4 @@ export declare function SettingBlock({ label, help, children, }: {
70
88
  export declare function InlineAction({ onClick, children }: {
71
89
  onClick: () => void;
72
90
  children: ReactNode;
73
- }): import("react").JSX.Element;
91
+ }): React.JSX.Element;
@@ -1,33 +1,44 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- /**
4
- * Layout primitives for the agent editor. Three shapes and nothing else: a
5
- * titled section, a row (label left, control right), and a block (label above
6
- * a full-width control).
7
- *
8
- * There is deliberately NO icon slot. Every group used to open with a glyph —
9
- * a stack, a chip, a gauge, a shield — and not one of them named anything the
10
- * words beside it did not already say. Type carries the hierarchy: section
11
- * titles at `text-sm font-medium`, help at `text-xs text-muted-foreground`.
12
- * Those two sizes are the whole scale; nothing in the editor is smaller.
13
- */
14
3
  import { createContext, useContext } from 'react';
4
+ import { SettingsRowGroup } from '../../../primitives/settings-row.js';
5
+ import { SettingsSectionHeader } from '../../../primitives/settings-section-header.js';
6
+ import { SettingsSubsectionHeader } from '../../../primitives/settings-subsection-header.js';
15
7
  import { cn } from '../../../internal/lib/utils.js';
16
8
  const EditorSectionStyleContext = createContext('flat');
17
9
  export function EditorSectionStyleProvider({ value, children, }) {
18
10
  return (_jsx(EditorSectionStyleContext.Provider, { value: value, children: children }));
19
11
  }
20
12
  /**
21
- * One titled group of settings. Rows inside are separated by hairlines rather
22
- * than boxed individually. See `EditorSectionStyle` for the two dialects.
13
+ * One titled group of settings, in the Settings page's dialect
14
+ * (`settings/tabs/general-tab.tsx`): the heading sits on the page, never
15
+ * inside a box, and only the rows below it share one bordered group.
16
+ *
17
+ * `lead` marks the first section of a pane. It takes the pane title
18
+ * (`SettingsSectionHeader`, `text-base lg:text-xl`). Every later section
19
+ * takes the quieter `SettingsSubsectionHeader`. Neither shows `description`
20
+ * on the agent page; it renders only in the legacy `flat` style.
21
+ *
22
+ * `bare` hands the body to the caller unwrapped: a list (`GrantList`), a
23
+ * markdown preview, or a textarea draws its own surface.
23
24
  */
24
- export function EditorSection({ title, description, trailing, children, }) {
25
+ export function EditorSection({ title, description, trailing, lead = false, bare = false, children, }) {
25
26
  const style = useContext(EditorSectionStyleContext);
26
- const heading = (_jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { className: "min-w-0 space-y-1", children: [_jsx("h3", { className: "text-foreground text-sm font-medium", children: title }), description ? (_jsx("p", { className: "text-muted-foreground text-xs leading-relaxed text-pretty", children: description })) : null] }), trailing ? _jsx("div", { className: "shrink-0", children: trailing }) : null] }));
27
27
  if (style === 'panel') {
28
- return (_jsxs("section", { className: "bg-popover rounded-md border", children: [_jsx("div", { className: "border-border/60 border-b px-4 pt-4 pb-3", children: heading }), _jsx("div", { className: cn('divide-border/60 divide-y px-4'), children: children })] }));
28
+ return (_jsxs("section", { className: lead ? 'space-y-6' : 'space-y-3', children: [lead ? (
29
+ // Headings stand alone (Jay, 2026-10-20): a sentence under every
30
+ // title made the page read as prose.
31
+ _jsx(SettingsSectionHeader, { title: title, action: trailing, className: "pb-1" })) : (_jsx(SettingsSubsectionHeader, { title: title, action: trailing })), bare ? children : _jsx(SettingsRowGroup, { children: children })] }));
29
32
  }
30
- return (_jsxs("section", { className: "space-y-2", children: [heading, _jsx("div", { className: "divide-border/60 divide-y", children: children })] }));
33
+ return (_jsxs("section", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { className: "min-w-0 space-y-1", children: [_jsx("h3", { className: "text-foreground text-sm font-medium", children: title }), description ? (_jsx("p", { className: "text-muted-foreground text-xs leading-relaxed text-pretty", children: description })) : null] }), trailing ? _jsx("div", { className: "shrink-0", children: trailing }) : null] }), _jsx("div", { className: "divide-border/60 divide-y", children: children })] }));
34
+ }
35
+ /**
36
+ * The bordered list a section hands its rows to: one `bg-popover` group,
37
+ * hairlines between rows, no per-row box. A stack of individually bordered
38
+ * cards read as ten announcements; one group reads as one list.
39
+ */
40
+ export function EditorList({ className, ...props }) {
41
+ return (_jsx("ul", { className: cn('bg-popover divide-border divide-y overflow-hidden rounded-md border', className), ...props }));
31
42
  }
32
43
  /**
33
44
  * Label and help on the left, control on the right — for anything that fits a
@@ -38,14 +49,16 @@ export function EditorSection({ title, description, trailing, children, }) {
38
49
  * three deep.
39
50
  */
40
51
  export function SettingRow({ label, help, children, }) {
41
- return (_jsxs("div", { className: "flex flex-col gap-2 py-3.5 sm:flex-row sm:items-center sm:justify-between sm:gap-6", children: [_jsx(SettingLabel, { label: label, help: help }), _jsx("div", { className: "w-full shrink-0 sm:w-52", children: children })] }));
52
+ const style = useContext(EditorSectionStyleContext);
53
+ return (_jsxs("div", { className: cn('flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between sm:gap-6', style === 'panel' ? 'px-4 py-3' : 'py-3.5'), children: [_jsx(SettingLabel, { label: label, help: help }), _jsx("div", { className: "w-full shrink-0 sm:w-52", children: children })] }));
42
54
  }
43
55
  /**
44
56
  * Label and help above a full-width control — for anything a row cannot hold:
45
57
  * a textarea, a grant checklist, the permission tree.
46
58
  */
47
59
  export function SettingBlock({ label, help, children, }) {
48
- return (_jsxs("div", { className: "space-y-2.5 py-3.5", children: [_jsx(SettingLabel, { label: label, help: help }), children] }));
60
+ const style = useContext(EditorSectionStyleContext);
61
+ return (_jsxs("div", { className: cn('space-y-2.5', style === 'panel' ? 'px-4 py-3' : 'py-3.5'), children: [_jsx(SettingLabel, { label: label, help: help }), children] }));
49
62
  }
50
63
  /**
51
64
  * The label pair. A plain `<span>`, not `<Label>`: none of these controls take
@@ -317,8 +317,8 @@ export function isAgentConfigSectionKey(value) {
317
317
  */
318
318
  export function AgentConfigSections({ section, editor, options, skillsOptions, registryOptions, overview, triggers, people, skills, connectors, secrets, apps, drives, authority, }) {
319
319
  const { draft, oc, set, setOc } = editor;
320
- // Every section is a card (`EditorSectionStyle` 'panel'), so a tab holding
321
- // two of them — Access holds the people and the grants — shows two blocks.
320
+ // Every pane opens with a `lead` section (the pane title) and stacks its
321
+ // later sections under Settings subsection headings.
322
322
  const body = (() => {
323
323
  switch (section) {
324
324
  case 'overview':
@@ -353,6 +353,6 @@ export function AgentConfigSections({ section, editor, options, skillsOptions, r
353
353
  return (_jsx(BasicsSection, { draft: draft, set: set, oc: oc, setOc: setOc, showDescription: false }));
354
354
  }
355
355
  })();
356
- return (_jsx(EditorSectionStyleProvider, { value: "panel", children: _jsx("div", { className: "space-y-4", children: body }) }));
356
+ return (_jsx(EditorSectionStyleProvider, { value: "panel", children: _jsx("div", { className: "space-y-8", children: body }) }));
357
357
  }
358
358
  export { grantSummary } from './grant-mode-field.js';
@@ -47,13 +47,13 @@ import { useTranslations } from '../../../../i18n/index.js';
47
47
  *
48
48
  * | Capability | Where it is now |
49
49
  * | --- | --- |
50
- * | Inherit / custom / no fallback | "When the default fails" row (primary) |
50
+ * | Inherit / custom / no fallback | "When a model fails" row (primary) |
51
51
  * | Ordered default chain, reorder + remove, max 8 | Chain row — one line per step (primary) |
52
52
  * | Fallback condition (transient / any error) | "Retry on" line, inside the chain it belongs to |
53
53
  * | Per-model override rules, max 20 | "Per-model overrides" — one row per rule, promoted second (primary) |
54
54
  * | Vision (image-input) override | "Vision model" row, inside Advanced |
55
55
  * | Per-model generation defaults | "Generation defaults" section, inside Advanced |
56
- * | Provider-availability preview | `AvailabilityBadge`, unchanged, now also on the primary |
56
+ * | Provider-availability preview | `AvailabilityBadge`, on every chain step and override |
57
57
  * | Reset / dirty / validation / save | Header action + sticky footer, unchanged |
58
58
  *
59
59
  * The data contract is untouched: same props in, same `routing.set` /
@@ -438,7 +438,7 @@ export function GatewayRouting({ projectId, canWrite, projectDefaultPending, })
438
438
  };
439
439
  });
440
440
  };
441
- return (_jsxs(RoutingSection, { action: writable ? (_jsxs(Button, { type: "button", variant: "outline", size: "sm", disabled: controlsDisabled, onClick: () => setResetOpen(true), children: [_jsx(RotateCcw, { className: "size-3.5" }), " ", tI18nComplete.raw('textdaee7606b339')] })) : (_jsx(Badge, { variant: "muted", size: "sm", children: tI18nComplete.raw('text8ac767353080') })), children: [_jsxs("div", { className: "space-y-8", children: [_jsxs("section", { className: "space-y-1", children: [_jsx(Label, { className: "text-foreground", children: tI18nComplete.raw('text325e84939c64') }), _jsxs("div", { className: "flex flex-col", children: [_jsx(RoutingRow, { label: tI18nComplete.raw('text146b38e7fa80'), hint: tI18nComplete.raw('textd48d1b0dbdd6'), children: _jsxs(Select, { value: fallbackMode, disabled: controlsDisabled, onValueChange: (mode) => changeFallbackMode(mode), children: [_jsx(SelectTrigger, { className: "w-48 max-w-full", "aria-label": tI18nComplete.raw('textdf33a10e5579'), children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "inherit", children: tI18nComplete.raw('text975aa2ab538e') }), _jsx(SelectItem, { value: "custom", children: tI18nComplete.raw('texta913ec01bd04') }), _jsx(SelectItem, { value: "disabled", children: tI18nComplete.raw('text3822b0412ed7') })] })] }) }), fallbackMode === 'custom' && draft.defaultFallback ? (_jsx(RoutingRow, { align: "start", label: _jsx("span", { className: "truncate font-mono text-xs", children: primaryModel }), hint: tI18nComplete.raw('textc3ecd3cd791b'), children: _jsxs("div", { className: "space-y-1.5", children: [_jsx(AvailabilityBadge, { available: availability[primaryModel] }), _jsx(ChainRows, { primary: primaryModel, chain: draft.defaultFallback, models: models, disabled: controlsDisabled, availability: availability, onChange: (defaultFallback) => setDraft({ ...draft, defaultFallback }) })] }) })) : fallbackMode === 'inherit' ? (_jsx(RoutingRow, { label: tI18nComplete.raw('text74a1a0f65906'), children: _jsx("p", { className: "text-muted-foreground truncate font-mono text-xs", children: inheritedRoute }) })) : (_jsx(RoutingRow, { label: tI18nComplete.raw('text0af465ef42c0'), children: _jsx("p", { className: "text-muted-foreground text-xs text-pretty", children: tI18nComplete.raw('texta3df3f9e4422') }) }))] })] }), _jsxs("section", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Label, { className: "text-foreground", children: tI18nComplete.raw('text5c63c15261bb') }), draft.rules.length > 0 ? (_jsx(Badge, { variant: "secondary", size: "sm", children: draft.rules.length })) : null] }), writable ? (_jsxs(Button, { type: "button", size: "sm", variant: "secondary", disabled: controlsDisabled || !newRuleModel || draft.rules.length >= MAX_RULES, onClick: () => newRuleModel &&
441
+ return (_jsxs(RoutingSection, { action: writable ? (_jsxs(Button, { type: "button", variant: "outline", size: "sm", disabled: controlsDisabled, onClick: () => setResetOpen(true), children: [_jsx(RotateCcw, { className: "size-3.5" }), " ", tI18nComplete.raw('textdaee7606b339')] })) : (_jsx(Badge, { variant: "muted", size: "sm", children: tI18nComplete.raw('text8ac767353080') })), children: [_jsxs("div", { className: "space-y-8", children: [_jsxs("section", { className: "space-y-1", children: [_jsx(Label, { className: "text-foreground", children: tI18nComplete.raw('text325e84939c64') }), _jsxs("div", { className: "flex flex-col", children: [_jsx(RoutingRow, { label: tI18nComplete.raw('text146b38e7fa80'), hint: tI18nComplete.raw('textd48d1b0dbdd6'), children: _jsxs(Select, { value: fallbackMode, disabled: controlsDisabled, onValueChange: (mode) => changeFallbackMode(mode), children: [_jsx(SelectTrigger, { className: "w-48 max-w-full", "aria-label": tI18nComplete.raw('textdf33a10e5579'), children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "inherit", children: tI18nComplete.raw('text975aa2ab538e') }), _jsx(SelectItem, { value: "custom", children: tI18nComplete.raw('texta913ec01bd04') }), _jsx(SelectItem, { value: "disabled", children: tI18nComplete.raw('text3822b0412ed7') })] })] }) }), fallbackMode === 'custom' && draft.defaultFallback ? (_jsx(RoutingRow, { align: "start", label: tI18nComplete.raw('texte75d99a42dba'), hint: tI18nComplete.raw('textc3ecd3cd791b'), children: _jsx("div", { className: "space-y-1.5", children: _jsx(ChainRows, { primary: primaryModel, chain: draft.defaultFallback, models: models, disabled: controlsDisabled, availability: availability, onChange: (defaultFallback) => setDraft({ ...draft, defaultFallback }) }) }) })) : fallbackMode === 'inherit' ? (_jsx(RoutingRow, { label: tI18nComplete.raw('text74a1a0f65906'), children: _jsx("p", { className: "text-muted-foreground truncate font-mono text-xs", children: inheritedRoute }) })) : (_jsx(RoutingRow, { label: tI18nComplete.raw('text0af465ef42c0'), children: _jsx("p", { className: "text-muted-foreground text-xs text-pretty", children: tI18nComplete.raw('texta3df3f9e4422') }) }))] })] }), _jsxs("section", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Label, { className: "text-foreground", children: tI18nComplete.raw('text5c63c15261bb') }), draft.rules.length > 0 ? (_jsx(Badge, { variant: "secondary", size: "sm", children: draft.rules.length })) : null] }), writable ? (_jsxs(Button, { type: "button", size: "sm", variant: "secondary", disabled: controlsDisabled || !newRuleModel || draft.rules.length >= MAX_RULES, onClick: () => newRuleModel &&
442
442
  setDraft({
443
443
  ...draft,
444
444
  rules: [
@@ -7,11 +7,9 @@ export declare function grantSummary(v: AgentGrantSetV2 | undefined, tI18nComple
7
7
  label: string;
8
8
  tone: 'muted' | 'outline';
9
9
  };
10
- export declare function GrantModeField({ value, onChange, allLabel, noneLabel, alwaysRender, children, }: {
10
+ export declare function GrantModeField({ value, onChange, alwaysRender, children, }: {
11
11
  value: AgentGrantSetV2 | undefined;
12
12
  onChange: (v: AgentGrantSetV2) => void;
13
- allLabel: string;
14
- noneLabel: string;
15
13
  /** Render `children` in every mode, not only Pick — for a catalog that
16
14
  * stays on screen and shows each card as included / excluded. */
17
15
  alwaysRender?: boolean;
@@ -34,12 +32,11 @@ export interface GrantOption {
34
32
  /** At the row's right edge — a `Badge` for a connector that needs auth. */
35
33
  trailing?: ReactNode;
36
34
  }
37
- export declare function GrantSetField({ value, onChange, options, emptyLabel, allLabel, rowAccessory, }: {
35
+ export declare function GrantSetField({ value, onChange, options, emptyLabel, rowAccessory, }: {
38
36
  value: AgentGrantSetV2 | undefined;
39
37
  onChange: (v: AgentGrantSetV2) => void;
40
38
  options: GrantOption[];
41
39
  emptyLabel: string;
42
- allLabel: string;
43
40
  /** Optional control rendered BESIDE each granted row (e.g. the connectors
44
41
  * field's "personal" toggle). The row itself is a `<button>`, so an
45
42
  * interactive accessory cannot be nested inside it — when this returns a
@@ -7,9 +7,9 @@ import { useTranslations as useI18nTranslations } from '../../../i18n/index.js';
7
7
  * (kortix_permissions) share the same state transitions instead of re-implementing
8
8
  * them twice.
9
9
  */
10
- import { Tabs, TabsListCompact, TabsTriggerCompact } from '../../../primitives/tabs.js';
11
- import { cn } from '../../../internal/lib/utils.js';
12
- import { CheckIcon } from '@phosphor-icons/react';
10
+ import { Tabs, TabsList, TabsTrigger } from '../../../primitives/tabs.js';
11
+ import { Badge } from '../../../primitives/badge.js';
12
+ import { Checkbox } from '../../../primitives/checkbox.js';
13
13
  import { useState } from 'react';
14
14
  import { KORTIX_PERMISSIONS_CATALOG } from './agent-editor-catalog.js';
15
15
  import { useUiParams } from '../../../providers/ui-provider.js';
@@ -31,7 +31,7 @@ const GRANT_MODES = [
31
31
  { value: 'pick', label: 'Pick' },
32
32
  { value: 'none', label: 'None' },
33
33
  ];
34
- export function GrantModeField({ value, onChange, allLabel, noneLabel, alwaysRender = false, children, }) {
34
+ export function GrantModeField({ value, onChange, alwaysRender = false, children, }) {
35
35
  const tI18nComplete = useI18nTranslations('hardcodedUi.i18nComplete');
36
36
  const mode = value === 'all' ? 'all' : value === 'none' || value === undefined ? 'none' : 'pick';
37
37
  const [wantPick, setWantPick] = useState(() => Array.isArray(value) && value.length > 0);
@@ -57,13 +57,13 @@ export function GrantModeField({ value, onChange, allLabel, noneLabel, alwaysRen
57
57
  next.add(id);
58
58
  onChange([...next]);
59
59
  };
60
- return (_jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx(Tabs, { value: effectiveMode, onValueChange: (m) => pick(m), className: "w-fit", children: _jsx(TabsListCompact, { type: "default", "aria-label": tI18nComplete.raw('text74009e6664f5'), children: GRANT_MODES.map((m) => (_jsx(TabsTriggerCompact, { value: m.value, children: m.label }, m.value))) }) }), effectiveMode === 'all' && (_jsx("span", { className: "text-muted-foreground text-xs", children: allLabel })), effectiveMode === 'none' && (_jsx("span", { className: "text-muted-foreground text-xs", children: noneLabel }))] }), effectiveMode === 'pick' || alwaysRender
60
+ return (_jsxs("div", { className: "space-y-3", children: [_jsx(Tabs, { value: effectiveMode, onValueChange: (m) => pick(m), children: _jsx(TabsList, { "aria-label": tI18nComplete.raw('text74009e6664f5'), children: GRANT_MODES.map((m) => (_jsx(TabsTrigger, { value: m.value, children: m.label }, m.value))) }) }), effectiveMode === 'pick' || alwaysRender
61
61
  ? children({ selected, toggle, mode: effectiveMode })
62
62
  : null] }));
63
63
  }
64
- export function GrantSetField({ value, onChange, options, emptyLabel, allLabel, rowAccessory, }) {
64
+ export function GrantSetField({ value, onChange, options, emptyLabel, rowAccessory, }) {
65
65
  const tI18nComplete = useI18nTranslations('hardcodedUi.i18nComplete');
66
- return (_jsx(GrantModeField, { value: value, onChange: onChange, allLabel: allLabel, noneLabel: tI18nComplete.raw('text765b240c2900'), children: ({ selected, toggle }) => {
66
+ return (_jsx(GrantModeField, { value: value, onChange: onChange, children: ({ selected, toggle }) => {
67
67
  const optionIds = new Set(options.map((o) => o.id));
68
68
  const orphans = [];
69
69
  for (const id of selected) {
@@ -71,14 +71,11 @@ export function GrantSetField({ value, onChange, options, emptyLabel, allLabel,
71
71
  orphans.push({ id, label: id });
72
72
  }
73
73
  const rows = [...options, ...orphans];
74
- return rows.length === 0 ? (_jsx("p", { className: "text-muted-foreground text-xs", children: emptyLabel })) : (_jsx("div", { className: "border-border/60 max-h-80 overflow-y-auto rounded-md border p-1", children: rows.map((o) => {
74
+ return rows.length === 0 ? (_jsx("p", { className: "text-muted-foreground text-xs", children: emptyLabel })) : (_jsx("ul", { className: "bg-popover divide-border max-h-96 divide-y overflow-y-auto rounded-md border", children: rows.map((o) => {
75
75
  const isSel = selected.has(o.id);
76
76
  const isOrphan = !optionIds.has(o.id);
77
77
  const accessory = rowAccessory?.(o.id, isSel);
78
- const row = (_jsxs("button", { type: "button", "aria-pressed": isSel, onClick: () => toggle(o.id), className: cn('flex items-center gap-2.5 rounded px-2 text-left text-xs transition-[color,background-color,transform] active:scale-[0.98]', o.description ? 'py-2' : 'py-1.5', accessory ? 'min-w-0 flex-1' : 'w-full', isSel ? 'bg-secondary' : 'hover:bg-muted/50'), children: [_jsx("span", { className: cn('flex size-4 shrink-0 items-center justify-center rounded-[4px] border', isSel
79
- ? 'border-foreground bg-foreground text-background'
80
- : 'border-border/70'), children: isSel ? _jsx(CheckIcon, { className: "size-2.5" }) : null }), _jsxs("span", { className: "min-w-0 flex-1", children: [_jsx("span", { className: "block truncate font-mono", children: o.label }), o.description ? (_jsx("span", { className: "text-muted-foreground block truncate text-xs leading-4", children: o.description })) : null] }), o.trailing ? _jsx("span", { className: "shrink-0", children: o.trailing }) : null, isOrphan && (_jsx("span", { className: "text-kortix-orange shrink-0", children: tI18nComplete.raw('textffa63583dfa6') }))] }, o.id));
81
- return accessory ? (_jsxs("div", { className: "flex items-center gap-1", children: [row, accessory] }, o.id)) : (row);
78
+ return (_jsxs("li", { className: "flex items-center gap-3 px-4 py-2.5", children: [_jsx(Checkbox, { variant: "black", checked: isSel, onCheckedChange: () => toggle(o.id), "aria-label": o.label }), _jsxs("span", { className: "min-w-0 flex-1", children: [_jsx("span", { className: "text-foreground block truncate font-mono text-sm", children: o.label }), o.description ? (_jsx("span", { className: "text-muted-foreground block truncate text-xs", children: o.description })) : null] }), isOrphan ? (_jsx(Badge, { variant: "warning", size: "xs", children: tI18nComplete.raw('textffa63583dfa6') })) : null, o.trailing, accessory] }, o.id));
82
79
  }) }));
83
80
  } }));
84
81
  }
@@ -88,10 +85,5 @@ export function KortixPermissionsField({ value, onChange, }) {
88
85
  const params = useUiParams();
89
86
  const { flags } = useProjectFeatureFlags(typeof params.id === 'string' ? params.id : null);
90
87
  const groups = KORTIX_PERMISSIONS_CATALOG.filter((grp) => !grp.featureFlag || flags[grp.featureFlag] === true);
91
- return (_jsx(GrantModeField, { value: value, onChange: onChange, allLabel: tI18nComplete.raw('text75a5e3a6d5d3'), noneLabel: tI18nComplete.raw('text765b240c2900'), children: ({ selected, toggle }) => (_jsx("div", { className: "border-border/60 max-h-64 space-y-3 overflow-y-auto rounded-md border p-2.5", children: groups.map((grp) => (_jsxs("div", { className: "space-y-1.5", children: [_jsx("p", { className: "text-muted-foreground text-xs font-medium", children: grp.group }), _jsx("div", { className: "flex flex-wrap gap-1", children: grp.actions.map((action) => {
92
- const isSel = selected.has(action);
93
- return (_jsx("button", { type: "button", "aria-pressed": isSel, onClick: () => toggle(action), className: cn('rounded px-1.5 py-1 font-mono text-xs transition-[color,background-color,transform] active:scale-[0.96]', isSel
94
- ? 'bg-foreground text-background'
95
- : 'bg-muted/40 text-muted-foreground hover:bg-muted'), children: action.replace(/^project\./, '') }, action));
96
- }) })] }, grp.group))) })) }));
88
+ return (_jsx(GrantModeField, { value: value, onChange: onChange, children: ({ selected, toggle }) => (_jsx("div", { className: "bg-popover divide-border divide-y rounded-md border", children: groups.map((grp) => (_jsxs("div", { className: "space-y-2.5 px-4 py-3", children: [_jsx("p", { className: "text-muted-foreground text-xs font-medium", children: grp.group }), _jsx("div", { className: "-mx-3 grid gap-x-2 gap-y-0.5 sm:grid-cols-2", children: grp.actions.map((action) => (_jsx(Checkbox, { variant: "black", checked: selected.has(action), onCheckedChange: () => toggle(action), label: _jsx("span", { className: "font-mono text-xs", children: action.replace(/^project\./, '') }) }, action))) })] }, grp.group))) })) }));
97
89
  }
@@ -3,7 +3,6 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useTranslations as useI18nTranslations } from '../../../i18n/index.js';
4
4
  /** The tool-permission editor — a default action plus per-tool rules (a bare
5
5
  * action, or a map of path/command patterns to actions). */
6
- import { Badge } from '../../../primitives/badge.js';
7
6
  import { Button } from '../../../primitives/button.js';
8
7
  import Hint from '../../../primitives/hint.js';
9
8
  import { Input } from '../../../primitives/input.js';
@@ -12,6 +11,8 @@ import { PlusIcon as Plus, TrashIcon as Trash2 } from '@phosphor-icons/react';
12
11
  import { AnimatePresence, m } from 'motion/react';
13
12
  import { useState } from 'react';
14
13
  import { PERMISSION_ACTION_LABEL, PERMISSION_ACTION_ONLY_GROUP_LABEL, PERMISSION_ACTION_ONLY_KEYS, PERMISSION_ACTIONS, PERMISSION_KEY_HELP, PERMISSION_KEY_LABEL, PERMISSION_RULE_GROUPS, PERMISSION_RULE_KEYS, } from './agent-editor-catalog.js';
14
+ import { SettingsRow, SettingsRowGroup } from '../../../primitives/settings-row.js';
15
+ import { SettingsSubsectionHeader } from '../../../primitives/settings-subsection-header.js';
15
16
  import { EditorSection } from './agent-editor-primitives.js';
16
17
  /** Radix forbids `""` as an item value, so the inherit state carries a sentinel. */
17
18
  const INHERIT = '__inherit__';
@@ -41,7 +42,7 @@ function asPermObject(permission) {
41
42
  * leads; the token stays because people grep for it and hand-edit the YAML.
42
43
  */
43
44
  function PermissionKeyName({ permKey }) {
44
- return (_jsx(Hint, { label: PERMISSION_KEY_HELP[permKey] ?? permKey, side: "top", children: _jsxs("span", { className: "flex min-w-0 cursor-default items-baseline gap-2", children: [_jsx("span", { className: "text-foreground truncate text-sm", children: PERMISSION_KEY_LABEL[permKey] ?? permKey }), _jsx("span", { className: "text-muted-foreground/70 shrink-0 font-mono text-xs", children: permKey })] }) }));
45
+ return (_jsx(Hint, { label: PERMISSION_KEY_HELP[permKey] ?? permKey, side: "top", children: _jsxs("span", { className: "flex min-w-0 cursor-default items-baseline gap-2", children: [_jsx("span", { className: "text-foreground truncate text-sm", children: PERMISSION_KEY_LABEL[permKey] ?? permKey }), _jsx("span", { className: "text-muted-foreground shrink-0 font-mono text-xs", children: permKey })] }) }));
45
46
  }
46
47
  /** One action-typed key: a bare allow/ask/deny/inherit, plus expandable
47
48
  * pattern → action rules. */
@@ -68,7 +69,7 @@ function PermissionRuleRow({ label, rule, onChange, }) {
68
69
  next[k === from ? to : k] = v;
69
70
  onChange(next);
70
71
  };
71
- return (_jsxs("div", { className: "space-y-2 px-3 py-2.5", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsx(PermissionKeyName, { permKey: label }), _jsxs("div", { className: "flex shrink-0 items-center gap-1.5", children: [_jsx(ActionSelect, { value: isMap ? undefined : bare, onChange: setBare, inheritLabel: tI18nComplete.raw('text3f72f0385768'), label: tI18nComplete('textfaaaefbff336', {
72
+ return (_jsxs("div", { className: "space-y-2 px-4 py-3", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsx(PermissionKeyName, { permKey: label }), _jsxs("div", { className: "flex shrink-0 items-center gap-1.5", children: [_jsx(ActionSelect, { value: isMap ? undefined : bare, onChange: setBare, inheritLabel: tI18nComplete.raw('text3f72f0385768'), label: tI18nComplete('textfaaaefbff336', {
72
73
  value0: PERMISSION_KEY_LABEL[label] ?? label,
73
74
  }) }), _jsxs(Button, { type: "button", variant: isMap || showRules ? 'secondary' : 'outline', size: "sm", className: "gap-1 px-2 text-xs", "aria-expanded": showRules, onClick: () => setShowRules((s) => !s), children: [tI18nComplete.raw('text4228aeb07c41'), ruleCount > 0 ? _jsx("span", { className: "tabular-nums", children: ruleCount }) : null] })] })] }), _jsx(AnimatePresence, { initial: false, children: showRules && (_jsx(m.div, { initial: { opacity: 0, height: 0 }, animate: { opacity: 1, height: 'auto' }, exit: { opacity: 0, height: 0 }, transition: { type: 'spring', duration: 0.3, bounce: 0 }, className: "overflow-hidden", children: _jsxs("div", { className: "bg-muted/40 space-y-1.5 rounded-md p-2", children: [ruleCount === 0 ? (_jsx("p", { className: "text-muted-foreground px-1 pt-0.5 text-xs text-pretty", children: tI18nComplete.raw('text8d1833ac5f65') })) : null, Object.entries(map).map(([pattern, action]) => (_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx(Input, { value: pattern, "aria-label": tI18nComplete.raw('text4288ade73ff9'), placeholder: tI18nComplete.raw('textcf134a1de504'), variant: "popover", className: "h-8 flex-1 font-mono text-xs", onChange: (e) => renameRule(pattern, e.target.value) }), _jsx(ActionSelect, { value: action, label: tI18nComplete('text494cb0162c19', {
74
75
  value0: pattern || tI18nComplete.raw('textc6fbcde46fa9'),
@@ -92,9 +93,9 @@ export function ToolsSection({ permission, onChange, }) {
92
93
  : permission && Object.keys(permission).length > 0
93
94
  ? `${Object.keys(permission).length} tool${Object.keys(permission).length === 1 ? '' : 's'} customized`
94
95
  : 'Every tool follows the runtime default';
95
- return (_jsx(EditorSection, { title: tI18nComplete.raw('textea93d6a262ec'), description: tI18nComplete.raw('text765f388e2ce6'), trailing: _jsx(Badge, { variant: "outline", size: "sm", children: summary }), children: _jsx("div", { className: "py-4", children: _jsx(PermissionEditor, { permission: permission, onChange: onChange }) }) }));
96
+ return (_jsx(EditorSection, { title: tI18nComplete.raw('textea93d6a262ec'), description: tI18nComplete.raw('text765f388e2ce6'), lead: true, bare: true, children: _jsx(PermissionEditor, { permission: permission, onChange: onChange, summary: summary }) }));
96
97
  }
97
- function PermissionEditor({ permission, onChange, }) {
98
+ function PermissionEditor({ permission, onChange, summary, }) {
98
99
  const tI18nComplete = useI18nTranslations('hardcodedUi.i18nComplete');
99
100
  const obj = asPermObject(permission);
100
101
  const bareDefault = typeof permission === 'string' ? permission : undefined;
@@ -111,7 +112,9 @@ function PermissionEditor({ permission, onChange, }) {
111
112
  next[key] = value;
112
113
  onChange(Object.keys(next).length ? next : undefined);
113
114
  };
114
- return (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3 rounded-md border px-3 py-2.5", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "text-foreground text-sm", children: tI18nComplete.raw('text9b99443d24c5') }), _jsx("p", { className: "text-muted-foreground text-xs", children: bareDefault
115
- ? tI18nComplete.raw('textabba11786cee')
116
- : tI18nComplete.raw('texte640da5d14fd') })] }), _jsx(ActionSelect, { value: bareDefault, onChange: setDefault, inheritLabel: tI18nComplete.raw('text8d2dd4e8c7ca'), label: tI18nComplete.raw('text9b99443d24c5') })] }), PERMISSION_RULE_GROUPS.map((group) => (_jsxs("div", { className: "space-y-1.5", children: [_jsx("p", { className: "text-muted-foreground text-xs font-medium", children: group.label }), _jsx("div", { className: "divide-border/60 divide-y rounded-md border", children: group.keys.map((key) => (_jsx(PermissionRuleRow, { label: key, rule: obj[key], onChange: (next) => setKey(key, next) }, key))) })] }, group.label))), _jsxs("div", { className: "space-y-1.5", children: [_jsx("p", { className: "text-muted-foreground text-xs font-medium", children: PERMISSION_ACTION_ONLY_GROUP_LABEL }), _jsx("div", { className: "divide-border/60 divide-y rounded-md border", children: PERMISSION_ACTION_ONLY_KEYS.map((key) => (_jsxs("div", { className: "flex items-center justify-between gap-3 px-3 py-2.5", children: [_jsx(PermissionKeyName, { permKey: key }), _jsx(ActionSelect, { value: typeof obj[key] === 'string' ? obj[key] : undefined, onChange: (v) => setKey(key, v), inheritLabel: tI18nComplete.raw('text3f72f0385768'), label: PERMISSION_KEY_LABEL[key] ?? key })] }, key))) })] })] }));
115
+ return (_jsxs("div", { className: "space-y-8", children: [_jsx(SettingsRowGroup, { children: _jsx(SettingsRow, { label: tI18nComplete.raw('text9b99443d24c5'), description: bareDefault
116
+ ? tI18nComplete.raw('textabba11786cee')
117
+ : Object.keys(obj).length > 0
118
+ ? `${summary}.`
119
+ : tI18nComplete.raw('texte640da5d14fd'), children: _jsx(ActionSelect, { value: bareDefault, onChange: setDefault, inheritLabel: tI18nComplete.raw('text8d2dd4e8c7ca'), label: tI18nComplete.raw('text9b99443d24c5') }) }) }), PERMISSION_RULE_GROUPS.map((group) => (_jsxs("section", { className: "space-y-3", children: [_jsx(SettingsSubsectionHeader, { title: group.label }), _jsx("div", { className: "bg-popover divide-border divide-y rounded-md border", children: group.keys.map((key) => (_jsx(PermissionRuleRow, { label: key, rule: obj[key], onChange: (next) => setKey(key, next) }, key))) })] }, group.label))), _jsxs("section", { className: "space-y-3", children: [_jsx(SettingsSubsectionHeader, { title: PERMISSION_ACTION_ONLY_GROUP_LABEL }), _jsx("div", { className: "bg-popover divide-border divide-y rounded-md border", children: PERMISSION_ACTION_ONLY_KEYS.map((key) => (_jsxs("div", { className: "flex items-center justify-between gap-3 px-4 py-3", children: [_jsx(PermissionKeyName, { permKey: key }), _jsx(ActionSelect, { value: typeof obj[key] === 'string' ? obj[key] : undefined, onChange: (v) => setKey(key, v), inheritLabel: tI18nComplete.raw('text3f72f0385768'), label: PERMISSION_KEY_LABEL[key] ?? key })] }, key))) })] })] }));
117
120
  }