@datalayer/core 1.2.18 → 1.2.19

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 (107) hide show
  1. package/lib/cli-login.js +5 -51
  2. package/lib/components/anonymous/AnonymousKeyExpired.js +1 -15
  3. package/lib/components/anonymous/AnonymousKeyTimer.js +5 -15
  4. package/lib/components/auth/SignIn.js +2 -2
  5. package/lib/components/avatars/UserAvatar.js +3 -27
  6. package/lib/components/billing/BillingEntitySelect.js +6 -48
  7. package/lib/components/checkout/StripeCheckout.js +33 -217
  8. package/lib/components/contents/ContentSourceCard.js +2 -11
  9. package/lib/components/contents/HomeFolderObjectsBrowser.d.ts +1 -1
  10. package/lib/components/contents/HomeFolderObjectsBrowser.js +11 -35
  11. package/lib/components/display/CenteredSpinner.js +1 -6
  12. package/lib/components/display/DatalayerBox.js +2 -14
  13. package/lib/components/flashes/FlashClosable.js +2 -17
  14. package/lib/components/mcp/ClientBadge.js +1 -1
  15. package/lib/components/mcp/McpErrorBlankslate.js +1 -1
  16. package/lib/components/mcp/ScopeList.js +1 -1
  17. package/lib/components/notebooks/JupyterNotebook.js +1 -2
  18. package/lib/components/principal/Principal.js +2 -10
  19. package/lib/components/principal/PrincipalAppearance.js +19 -63
  20. package/lib/components/principal/PrincipalAvatar.js +5 -25
  21. package/lib/components/principal/PrincipalBadge.js +3 -13
  22. package/lib/components/principal/PrincipalBanner.js +4 -32
  23. package/lib/components/principal/PrincipalDetailsOverlay.js +7 -23
  24. package/lib/components/principal/PrincipalHoverCard.js +15 -18
  25. package/lib/components/principal/PrincipalSwitcherMenu.js +15 -83
  26. package/lib/components/progress/ConsumptionBar.js +1 -1
  27. package/lib/components/sharing/ShareAccessComponent.js +21 -229
  28. package/lib/components/sharing/SharingEditor.js +1 -1
  29. package/lib/components/spaces/SpaceDetailsOverlay.js +4 -35
  30. package/lib/components/spaces/SpaceDisplay.js +1 -8
  31. package/lib/components/storage/ContentsBrowser.js +3 -26
  32. package/lib/components/storage/ContentsTable.js +4 -23
  33. package/lib/components/students/StudentResultCircle.js +7 -29
  34. package/lib/components/timeline/Timeline.js +4 -36
  35. package/lib/hooks/layouts/LayoutBackdrop.js +2 -1
  36. package/lib/hooks/layouts/LayoutScreencapture.js +1 -1
  37. package/lib/hooks/libraryApp.d.ts +6 -1
  38. package/lib/hooks/libraryApp.js +10 -1
  39. package/lib/hooks/useAuthorization.js +6 -1
  40. package/lib/mocks/components/FlashMock.js +3 -8
  41. package/lib/mocks/views/DashboardMock.js +6 -72
  42. package/lib/mocks/views/FormMock.js +3 -2
  43. package/lib/mocks/views/TableMock.js +3 -2
  44. package/lib/mocks/views/WipMock.js +2 -1
  45. package/lib/models/Person.d.ts +9 -0
  46. package/lib/models/Person.js +23 -0
  47. package/lib/otel/views/OtelLive.js +4 -62
  48. package/lib/otel/views/OtelLiveSpans.js +4 -29
  49. package/lib/otel/views/OtelLogsList.js +13 -64
  50. package/lib/otel/views/OtelMetricsChart.js +4 -19
  51. package/lib/otel/views/OtelMetricsList.js +8 -77
  52. package/lib/otel/views/OtelSearchBar.js +3 -12
  53. package/lib/otel/views/OtelSpanDetail.js +9 -79
  54. package/lib/otel/views/OtelSpanTree.js +7 -57
  55. package/lib/otel/views/OtelSqlView.js +5 -99
  56. package/lib/otel/views/OtelSystemView.js +4 -34
  57. package/lib/otel/views/OtelTimeline.js +7 -37
  58. package/lib/otel/views/OtelTimelineRangeSlider.js +7 -140
  59. package/lib/otel/views/OtelTracesList.js +12 -76
  60. package/lib/portable/index.d.ts +8 -0
  61. package/lib/portable/index.js +12 -0
  62. package/lib/state/substates/NavigationState.d.ts +6 -4
  63. package/lib/state/substates/NavigationState.js +6 -5
  64. package/lib/views/api-keys/APIKeyEdit.js +2 -11
  65. package/lib/views/api-keys/APIKeyNew.js +3 -19
  66. package/lib/views/api-keys/APIKeys.js +6 -11
  67. package/lib/views/api-keys/APIKeysStandalone.js +1 -1
  68. package/lib/views/datasources/DatasourceDetail.d.ts +1 -1
  69. package/lib/views/datasources/DatasourceDetail.js +24 -17
  70. package/lib/views/datasources/DatasourceNew.js +2 -6
  71. package/lib/views/datasources/Datasources.js +2 -14
  72. package/lib/views/iam/SignInSimple.js +8 -64
  73. package/lib/views/mcp/AdmittedClients.js +3 -16
  74. package/lib/views/mcp/AlertDestinations.js +2 -10
  75. package/lib/views/mcp/AlertRules.js +4 -9
  76. package/lib/views/mcp/ApprovalQueue.js +4 -21
  77. package/lib/views/mcp/AuditLog.js +7 -44
  78. package/lib/views/mcp/ConnectedAgents.js +1 -6
  79. package/lib/views/mcp/EnterpriseConsole.js +10 -23
  80. package/lib/views/mcp/IdentityProviders.js +7 -31
  81. package/lib/views/mcp/McpDashboard.js +14 -30
  82. package/lib/views/mcp/McpHome.js +7 -54
  83. package/lib/views/mcp/McpObservability.js +13 -85
  84. package/lib/views/mcp/NotebookRuns.js +5 -12
  85. package/lib/views/mcp/OrganizationPolicy.js +3 -9
  86. package/lib/views/mcp/OrganizationUsage.js +4 -11
  87. package/lib/views/mcp/PersonalPolicy.js +3 -3
  88. package/lib/views/mcp/Policies.js +5 -46
  89. package/lib/views/mcp/PolicyForm.js +1 -9
  90. package/lib/views/mcp/PolicyHistory.js +2 -8
  91. package/lib/views/mcp/RunDetail.js +3 -25
  92. package/lib/views/mcp/ScimProvisioning.js +3 -15
  93. package/lib/views/mcp/ServiceAgents.js +4 -17
  94. package/lib/views/mcp/TeamPolicies.js +7 -19
  95. package/lib/views/mcp/ToolAccess.js +15 -22
  96. package/lib/views/mcp/TraceTimeline.js +8 -23
  97. package/lib/views/otel/DashboardView.js +2 -2
  98. package/lib/views/otel/LogsView.js +2 -2
  99. package/lib/views/otel/MetricsView.js +2 -2
  100. package/lib/views/otel/OtelHeader.js +6 -40
  101. package/lib/views/otel/SqlView.js +2 -2
  102. package/lib/views/otel/SystemView.js +2 -2
  103. package/lib/views/otel/TracesView.js +2 -2
  104. package/lib/views/profile/UserBadge.js +6 -98
  105. package/lib/views/secrets/SecretEdit.js +2 -11
  106. package/lib/views/secrets/SecretNew.js +1 -1
  107. package/package.json +1 -1
@@ -166,7 +166,7 @@ export const AlertRules = ({ errorState, orgUid, readOnly = false, showTitle = t
166
166
  id: 'condition',
167
167
  rowHeader: true,
168
168
  width: 'growCollapse',
169
- renderCell: row => (_jsxs(Box, { sx: { display: 'grid' }, children: [_jsxs(Text, { sx: { fontSize: 1 }, children: [labelOf(row.condition), " ", operatorOf(row.operator), " ", row.threshold] }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: ["over ", windowOf(row.windowSeconds), row.scopeKind !== 'organization' && ` · this ${row.scopeKind}`] })] })),
169
+ renderCell: row => (_jsxs(Box, { display: "grid", children: [_jsxs(Text, { sx: { fontSize: 1 }, children: [labelOf(row.condition), " ", operatorOf(row.operator), " ", row.threshold] }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: ["over ", windowOf(row.windowSeconds), row.scopeKind !== 'organization' && ` · this ${row.scopeKind}`] })] })),
170
170
  },
171
171
  {
172
172
  header: 'Severity',
@@ -201,12 +201,7 @@ export const AlertRules = ({ errorState, orgUid, readOnly = false, showTitle = t
201
201
  return (_jsx(McpErrorBlankslate, { state: errorState(rules.error, 'Alert rules'), onRetry: () => rules.refetch() }));
202
202
  }
203
203
  const chosen = ALERT_CONDITIONS.find(entry => entry.name === draft.condition);
204
- return (_jsxs(Box, { sx: { display: 'grid', gap: 3, minWidth: 0 }, children: [showTitle && (_jsxs(Box, { sx: {
205
- display: 'flex',
206
- alignItems: 'start',
207
- justifyContent: 'space-between',
208
- gap: 3,
209
- }, children: [_jsxs(Box, { children: [_jsx(Heading, { as: "h2", sx: { fontSize: 3, mb: 1 }, children: "Alerts" }), _jsx(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 1, m: 0 }, children: "What this organization asked to be told about. Each rule is checked once a minute and fires at most once per window." })] }), !readOnly && (_jsx(Button, { variant: "primary", onClick: openCreate, children: "New rule" }))] })), rules.isPending && !rules.data ? (_jsx(Box, { sx: { display: 'flex', justifyContent: 'center', py: 5 }, children: _jsx(Spinner, {}) })) : rows.length > 0 ? (_jsxs(Table.Container, { children: [_jsx(Table.Title, { as: "h3", id: "alert-rules", children: "Rules" }), _jsx(Table.Subtitle, { as: "p", id: "alert-rules-subtitle", children: "A rule switched off stays here and stops being evaluated." }), _jsx(DataTable, { "aria-labelledby": "alert-rules", "aria-describedby": "alert-rules-subtitle", data: rows, columns: columns })] })) : (_jsxs(Blankslate, { border: true, spacious: true, children: [_jsx(Blankslate.Visual, { children: _jsx(BellIcon, { size: "medium" }) }), _jsx(Blankslate.Heading, { children: "Nothing is watched" }), _jsx(Blankslate.Description, { children: _jsx(Text, { sx: { textAlign: 'center' }, children: "Runs are recorded either way. A rule is what turns a number somebody would have to go and look at into something that reaches you." }) }), !readOnly && (_jsx(Button, { size: "small", onClick: openCreate, children: "New rule" }))] })), _jsx(AlertDestinations, { errorState: errorState, orgUid: orgUid, readOnly: readOnly }), (creating || editing) && (_jsx(Dialog, { title: editing ? 'Edit rule' : 'New alert rule', onClose: close, returnFocusRef: returnFocusRef, footerButtons: [
204
+ return (_jsxs(Box, { display: "grid", gap: 3, minWidth: 0, children: [showTitle && (_jsxs(Box, { display: "flex", alignItems: "start", justifyContent: "space-between", gap: 3, children: [_jsxs(Box, { children: [_jsx(Heading, { as: "h2", sx: { fontSize: 3, mb: 1 }, children: "Alerts" }), _jsx(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 1, m: 0 }, children: "What this organization asked to be told about. Each rule is checked once a minute and fires at most once per window." })] }), !readOnly && (_jsx(Button, { variant: "primary", onClick: openCreate, children: "New rule" }))] })), rules.isPending && !rules.data ? (_jsx(Box, { display: "flex", justifyContent: "center", py: 5, children: _jsx(Spinner, {}) })) : rows.length > 0 ? (_jsxs(Table.Container, { children: [_jsx(Table.Title, { as: "h3", id: "alert-rules", children: "Rules" }), _jsx(Table.Subtitle, { as: "p", id: "alert-rules-subtitle", children: "A rule switched off stays here and stops being evaluated." }), _jsx(DataTable, { "aria-labelledby": "alert-rules", "aria-describedby": "alert-rules-subtitle", data: rows, columns: columns })] })) : (_jsxs(Blankslate, { border: true, spacious: true, children: [_jsx(Blankslate.Visual, { children: _jsx(BellIcon, { size: "medium" }) }), _jsx(Blankslate.Heading, { children: "Nothing is watched" }), _jsx(Blankslate.Description, { children: _jsx(Text, { sx: { textAlign: 'center' }, children: "Runs are recorded either way. A rule is what turns a number somebody would have to go and look at into something that reaches you." }) }), !readOnly && (_jsx(Button, { size: "small", onClick: openCreate, children: "New rule" }))] })), _jsx(AlertDestinations, { errorState: errorState, orgUid: orgUid, readOnly: readOnly }), (creating || editing) && (_jsx(Dialog, { title: editing ? 'Edit rule' : 'New alert rule', onClose: close, returnFocusRef: returnFocusRef, footerButtons: [
210
205
  { buttonType: 'default', content: 'Cancel', onClick: close },
211
206
  {
212
207
  buttonType: 'default',
@@ -220,7 +215,7 @@ export const AlertRules = ({ errorState, orgUid, readOnly = false, showTitle = t
220
215
  onClick: apply,
221
216
  disabled: create.isPending || update.isPending,
222
217
  },
223
- ], children: _jsxs(Box, { sx: { display: 'grid', gap: 3 }, children: [refusal && (_jsx(Flash, { variant: "danger", children: _jsx(Text, { sx: { fontSize: 1 }, children: refusal }) })), trial && (_jsxs(Flash, { variant: trial.readable ? 'default' : 'warning', children: [_jsx(Text, { sx: { fontSize: 1 }, children: trial.readable
218
+ ], children: _jsxs(Box, { display: "grid", gap: 3, children: [refusal && (_jsx(Flash, { variant: "danger", children: _jsx(Text, { sx: { fontSize: 1 }, children: refusal }) })), trial && (_jsxs(Flash, { variant: trial.readable ? 'default' : 'warning', children: [_jsx(Text, { sx: { fontSize: 1 }, children: trial.readable
224
219
  ? `Right now it reads ${trial.value}, so this rule ${trial.wouldFire ? 'would fire' : 'would not fire'}.`
225
220
  : 'This cannot be read at the moment, so the rule would ' +
226
221
  'not fire — and a rule that never fires looks exactly ' +
@@ -228,7 +223,7 @@ export const AlertRules = ({ errorState, orgUid, readOnly = false, showTitle = t
228
223
  // A condition nothing reads would be stored, evaluated
229
224
  // every minute and never fire. Offering it as though it
230
225
  // worked is the silence rules exist to break.
231
- disabled: !condition.measurable, children: [condition.label, condition.measurable ? '' : ' — not measurable yet'] }, condition.name))) }), chosen && (_jsx(FormControl.Caption, { children: chosen.help }))] }), _jsxs(Box, { sx: { display: 'grid', gap: 2, gridTemplateColumns: '1fr 1fr' }, children: [_jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Comparison" }), _jsx(Select, { value: draft.operator, onChange: event => set('operator', event.target.value), children: ALERT_OPERATORS.map(operator => (_jsx(Select.Option, { value: operator.name, children: operator.label }, operator.name))) })] }), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Threshold" }), _jsx(TextInput, { block: true, type: "number", value: String(draft.threshold), onChange: event => set('threshold', Number(event.target.value)) })] })] }), _jsxs(Box, { sx: { display: 'grid', gap: 2, gridTemplateColumns: '1fr 1fr' }, children: [_jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Over" }), _jsx(Select, { value: String(draft.windowSeconds), onChange: event => set('windowSeconds', Number(event.target.value)), children: WINDOWS.map(window => (_jsx(Select.Option, { value: String(window.seconds), children: window.label }, window.seconds))) }), _jsx(FormControl.Caption, { children: "It fires once per window, not once per check." })] }), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Severity" }), _jsx(Select, { value: draft.severity, onChange: event => set('severity', event.target.value), children: ALERT_SEVERITIES.map(severity => (_jsx(Select.Option, { value: severity, children: severity }, severity))) }), _jsx(FormControl.Caption, { children: "Sets the colour in Slack and the wording of the notice." })] })] }), _jsxs(Box, { sx: { display: 'grid', gap: 2, gridTemplateColumns: '1fr 1fr' }, children: [_jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Measured over" }), _jsxs(Select, { value: draft.scopeKind, onChange: event => set('scopeKind', event.target.value), children: [_jsx(Select.Option, { value: "organization", children: "The whole organization" }), _jsx(Select.Option, { value: "team", children: "One team" }), _jsx(Select.Option, { value: "user", children: "One person" }), _jsx(Select.Option, { value: "agent", children: "One agent" })] })] }), draft.scopeKind !== 'organization' && (_jsxs(FormControl, { required: true, children: [_jsxs(FormControl.Label, { children: ["Which ", draft.scopeKind] }), _jsx(TextInput, { block: true, value: draft.scopeUid, onChange: event => set('scopeUid', event.target.value), placeholder: "uid" }), _jsx(FormControl.Caption, { children: "Without one the rule would be measured over the whole organization under a name saying otherwise." })] }))] })] }) })), removing && (_jsx(Dialog, { title: "Remove this rule?", onClose: () => setRemoving(null), returnFocusRef: returnFocusRef, footerButtons: [
226
+ disabled: !condition.measurable, children: [condition.label, condition.measurable ? '' : ' — not measurable yet'] }, condition.name))) }), chosen && (_jsx(FormControl.Caption, { children: chosen.help }))] }), _jsxs(Box, { display: "grid", gap: 2, gridTemplateColumns: "1fr 1fr", children: [_jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Comparison" }), _jsx(Select, { value: draft.operator, onChange: event => set('operator', event.target.value), children: ALERT_OPERATORS.map(operator => (_jsx(Select.Option, { value: operator.name, children: operator.label }, operator.name))) })] }), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Threshold" }), _jsx(TextInput, { block: true, type: "number", value: String(draft.threshold), onChange: event => set('threshold', Number(event.target.value)) })] })] }), _jsxs(Box, { display: "grid", gap: 2, gridTemplateColumns: "1fr 1fr", children: [_jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Over" }), _jsx(Select, { value: String(draft.windowSeconds), onChange: event => set('windowSeconds', Number(event.target.value)), children: WINDOWS.map(window => (_jsx(Select.Option, { value: String(window.seconds), children: window.label }, window.seconds))) }), _jsx(FormControl.Caption, { children: "It fires once per window, not once per check." })] }), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Severity" }), _jsx(Select, { value: draft.severity, onChange: event => set('severity', event.target.value), children: ALERT_SEVERITIES.map(severity => (_jsx(Select.Option, { value: severity, children: severity }, severity))) }), _jsx(FormControl.Caption, { children: "Sets the colour in Slack and the wording of the notice." })] })] }), _jsxs(Box, { display: "grid", gap: 2, gridTemplateColumns: "1fr 1fr", children: [_jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Measured over" }), _jsxs(Select, { value: draft.scopeKind, onChange: event => set('scopeKind', event.target.value), children: [_jsx(Select.Option, { value: "organization", children: "The whole organization" }), _jsx(Select.Option, { value: "team", children: "One team" }), _jsx(Select.Option, { value: "user", children: "One person" }), _jsx(Select.Option, { value: "agent", children: "One agent" })] })] }), draft.scopeKind !== 'organization' && (_jsxs(FormControl, { required: true, children: [_jsxs(FormControl.Label, { children: ["Which ", draft.scopeKind] }), _jsx(TextInput, { block: true, value: draft.scopeUid, onChange: event => set('scopeUid', event.target.value), placeholder: "uid" }), _jsx(FormControl.Caption, { children: "Without one the rule would be measured over the whole organization under a name saying otherwise." })] }))] })] }) })), removing && (_jsx(Dialog, { title: "Remove this rule?", onClose: () => setRemoving(null), returnFocusRef: returnFocusRef, footerButtons: [
232
227
  {
233
228
  buttonType: 'default',
234
229
  content: 'Keep it',
@@ -3,7 +3,7 @@ import { useState } from 'react';
3
3
  import { Button, Heading, Label, RelativeTime, SegmentedControl, Spinner, Text, Textarea, } from '@primer/react';
4
4
  import { Box } from '@datalayer/primer-addons';
5
5
  import { McpErrorBlankslate } from '../../components/mcp/index.js';
6
- import { useDecideMcpApproval, useMcpApprovals, } from '../../hooks/useContents.js';
6
+ import { useDecideMcpApproval, useMcpApprovals } from '../../hooks/useContents.js';
7
7
  /** How each state of an approval is drawn. */
8
8
  export const APPROVAL_LOOK = {
9
9
  pending: { label: 'Waiting on you', variant: 'attention' },
@@ -54,32 +54,15 @@ export const ApprovalQueue = ({ errorState, sourceUid, }) => {
54
54
  const approvals = useMcpApprovals(status, sourceUid ? { sourceUid } : {});
55
55
  const decide = useDecideMcpApproval();
56
56
  const items = approvals.data?.items ?? [];
57
- return (_jsxs(Box, { sx: { display: 'grid', gap: 3, minWidth: 0 }, children: [_jsxs(Box, { children: [_jsx(Heading, { as: "h3", sx: { fontSize: 2, mb: 1 }, children: "Approvals" }), _jsx(Text, { as: "p", sx: { fontSize: 1, color: 'fg.muted', m: 0 }, children: "A source set to require approval stops each call until you allow it. An approval covers the exact arguments below and nothing else, so a second call with different arguments asks again." })] }), _jsx(SegmentedControl, { "aria-label": "Which approvals", size: "small", children: APPROVAL_FILTERS.map(state => (_jsx(SegmentedControl.Button, { selected: status === state, onClick: () => setStatus(state), children: APPROVAL_LOOK[state].label }, state))) }), approvals.isError ? (_jsx(McpErrorBlankslate, { state: errorState(approvals.error, 'The approvals'), onRetry: () => approvals.refetch() })) : approvals.isPending ? (_jsx(Box, { sx: { display: 'flex', justifyContent: 'center', py: 5 }, children: _jsx(Spinner, {}) })) : items.length === 0 ? (_jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: status === 'pending'
57
+ return (_jsxs(Box, { display: "grid", gap: 3, minWidth: 0, children: [_jsxs(Box, { children: [_jsx(Heading, { as: "h3", sx: { fontSize: 2, mb: 1 }, children: "Approvals" }), _jsx(Text, { as: "p", sx: { fontSize: 1, color: 'fg.muted', m: 0 }, children: "A source set to require approval stops each call until you allow it. An approval covers the exact arguments below and nothing else, so a second call with different arguments asks again." })] }), _jsx(SegmentedControl, { "aria-label": "Which approvals", size: "small", children: APPROVAL_FILTERS.map(state => (_jsx(SegmentedControl.Button, { selected: status === state, onClick: () => setStatus(state), children: APPROVAL_LOOK[state].label }, state))) }), approvals.isError ? (_jsx(McpErrorBlankslate, { state: errorState(approvals.error, 'The approvals'), onRetry: () => approvals.refetch() })) : approvals.isPending ? (_jsx(Box, { display: "flex", justifyContent: "center", py: 5, children: _jsx(Spinner, {}) })) : items.length === 0 ? (_jsx(Text, { sx: { fontSize: 1, color: 'fg.muted' }, children: status === 'pending'
58
58
  ? 'Nothing is waiting on you.'
59
59
  : `No ${APPROVAL_LOOK[status].label.toLowerCase()} approvals.` })) : (items.map(approval => {
60
60
  const look = approvalLook(approval);
61
61
  const decidable = isDecidable(approval);
62
- return (_jsxs(Box, { sx: {
63
- border: '1px solid',
64
- borderColor: decidable ? 'attention.emphasis' : 'border.default',
65
- borderRadius: 2,
66
- p: 3,
67
- display: 'grid',
68
- gap: 2,
69
- minWidth: 0,
70
- }, children: [_jsxs(Box, { sx: { display: 'flex', gap: 2, alignItems: 'center', flexWrap: 'wrap' }, children: [_jsx(Label, { size: "small", variant: look.variant, children: look.label }), _jsx(Text, { sx: { fontSize: 1, fontWeight: 'semibold' }, children: approval.tool }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', fontFamily: 'mono' }, children: approval.actorUid }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: ["asked ", _jsx(RelativeTime, { datetime: approval.createdAt })] }), decidable && (_jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: ["expires ", _jsx(RelativeTime, { datetime: approval.expiresAt })] }))] }), _jsx(Box, { as: "pre", sx: {
71
- fontFamily: 'mono',
72
- fontSize: 0,
73
- whiteSpace: 'pre-wrap',
74
- overflowX: 'auto',
75
- bg: 'canvas.subtle',
76
- borderRadius: 2,
77
- p: 2,
78
- m: 0,
79
- }, children: JSON.stringify(approval.argumentsRedacted, null, 2) }), approval.destinationUri && (_jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: ["Writes to", ' ', _jsx(Text, { as: "span", sx: { fontFamily: 'mono' }, children: approval.destinationUri })] })), decidable ? (_jsxs(_Fragment, { children: [_jsx(Textarea, { "aria-label": `Why, for ${approval.tool}`, rows: 2, placeholder: "Why (optional; kept with the decision)", value: noteFor[approval.uid] ?? '', onChange: event => setNoteFor(current => ({
62
+ return (_jsxs(Box, { border: "1px solid", borderColor: decidable ? 'attention.emphasis' : 'border.default', borderRadius: 2, p: 3, display: "grid", gap: 2, minWidth: 0, children: [_jsxs(Box, { display: "flex", gap: 2, alignItems: "center", flexWrap: "wrap", children: [_jsx(Label, { size: "small", variant: look.variant, children: look.label }), _jsx(Text, { sx: { fontSize: 1, fontWeight: 'semibold' }, children: approval.tool }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', fontFamily: 'mono' }, children: approval.actorUid }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: ["asked ", _jsx(RelativeTime, { datetime: approval.createdAt })] }), decidable && (_jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: ["expires ", _jsx(RelativeTime, { datetime: approval.expiresAt })] }))] }), _jsx(Box, { as: "pre", fontFamily: "mono", fontSize: 0, whiteSpace: "pre-wrap", overflowX: "auto", bg: "canvas.subtle", borderRadius: 2, p: 2, m: 0, children: JSON.stringify(approval.argumentsRedacted, null, 2) }), approval.destinationUri && (_jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: ["Writes to", ' ', _jsx(Text, { as: "span", sx: { fontFamily: 'mono' }, children: approval.destinationUri })] })), decidable ? (_jsxs(_Fragment, { children: [_jsx(Textarea, { "aria-label": `Why, for ${approval.tool}`, rows: 2, placeholder: "Why (optional; kept with the decision)", value: noteFor[approval.uid] ?? '', onChange: event => setNoteFor(current => ({
80
63
  ...current,
81
64
  [approval.uid]: event.target.value,
82
- })) }), _jsxs(Box, { sx: { display: 'flex', gap: 2 }, children: [_jsx(Button, { variant: "primary", disabled: decide.isPending, onClick: () => decide.mutate({
65
+ })) }), _jsxs(Box, { display: "flex", gap: 2, children: [_jsx(Button, { variant: "primary", disabled: decide.isPending, onClick: () => decide.mutate({
83
66
  approvalUid: approval.uid,
84
67
  decision: 'approve',
85
68
  note: noteFor[approval.uid] || undefined,
@@ -81,64 +81,27 @@ export const AuditLog = ({ errorState, routes, filters, onFiltersChange, retenti
81
81
  if (page.isError) {
82
82
  return (_jsx(McpErrorBlankslate, { state: errorState(page.error, 'Audit'), onRetry: () => page.refetch() }));
83
83
  }
84
- return (_jsxs(Box, { sx: { display: 'grid', gap: 3, minWidth: 0 }, children: [showTitle && (_jsxs(Box, { children: [_jsx(Heading, { as: "h2", sx: { fontSize: 3, mb: 1 }, children: "Audit" }), _jsxs(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 1, m: 0 }, children: ["Every call ", subject, " made through MCP, what was decided, and why."] })] })), forwarding.data?.configured && forwarding.data.state && (_jsx(Flash, { variant: forwarding.data.state.healthy ? 'default' : 'danger', children: _jsx(Text, { sx: { fontSize: 1 }, children: forwarding.data.state.healthy ? (_jsxs(_Fragment, { children: ["Forwarded to your own system of record \u2014", ' ', forwarding.data.state.delivered, " batches", forwarding.data.state.lastDeliveredAt && (_jsxs(_Fragment, { children: [", last", ' ', _jsx(RelativeTime, { datetime: forwarding.data.state.lastDeliveredAt })] })), "."] })) : (_jsxs(_Fragment, { children: [_jsx("strong", { children: "Forwarding is failing." }), " These rows are kept here and are not reaching your own system of record:", ' ', forwarding.data.state.lastError, forwarding.data.state.lastErrorAt && (_jsxs(_Fragment, { children: [' ', "(", _jsx(RelativeTime, { datetime: forwarding.data.state.lastErrorAt }), ")"] })), ". ", forwarding.data.state.failed, " batches have failed."] })) }) })), _jsxs(Box, { sx: {
85
- display: 'grid',
86
- gap: 2,
87
- gridTemplateColumns: ['1fr', 'repeat(2, 1fr)', 'repeat(5, 1fr)'],
88
- alignItems: 'end',
89
- }, children: [_jsx(TextInput, { size: "small", "aria-label": "Agent", placeholder: "Agent", value: filters.agent ?? '', onChange: event => set({ agent: event.currentTarget.value || undefined }) }), _jsx(TextInput, { size: "small", "aria-label": "Tool", placeholder: "Tool", value: filters.tool ?? '', onChange: event => set({ tool: event.currentTarget.value || undefined }) }), _jsxs(Select, { size: "small", "aria-label": "Decision", value: filters.decision ?? '', onChange: event => set({
84
+ return (_jsxs(Box, { display: "grid", gap: 3, minWidth: 0, children: [showTitle && (_jsxs(Box, { children: [_jsx(Heading, { as: "h2", sx: { fontSize: 3, mb: 1 }, children: "Audit" }), _jsxs(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 1, m: 0 }, children: ["Every call ", subject, " made through MCP, what was decided, and why."] })] })), forwarding.data?.configured && forwarding.data.state && (_jsx(Flash, { variant: forwarding.data.state.healthy ? 'default' : 'danger', children: _jsx(Text, { sx: { fontSize: 1 }, children: forwarding.data.state.healthy ? (_jsxs(_Fragment, { children: ["Forwarded to your own system of record \u2014", ' ', forwarding.data.state.delivered, " batches", forwarding.data.state.lastDeliveredAt && (_jsxs(_Fragment, { children: [", last", ' ', _jsx(RelativeTime, { datetime: forwarding.data.state.lastDeliveredAt })] })), "."] })) : (_jsxs(_Fragment, { children: [_jsx("strong", { children: "Forwarding is failing." }), " These rows are kept here and are not reaching your own system of record:", ' ', forwarding.data.state.lastError, forwarding.data.state.lastErrorAt && (_jsxs(_Fragment, { children: [' ', "(", _jsx(RelativeTime, { datetime: forwarding.data.state.lastErrorAt }), ")"] })), ". ", forwarding.data.state.failed, " batches have failed."] })) }) })), _jsxs(Box, { display: "grid", gap: 2, gridTemplateColumns: ['1fr', 'repeat(2, 1fr)', 'repeat(5, 1fr)'], alignItems: "end", children: [_jsx(TextInput, { size: "small", "aria-label": "Agent", placeholder: "Agent", value: filters.agent ?? '', onChange: event => set({ agent: event.currentTarget.value || undefined }) }), _jsx(TextInput, { size: "small", "aria-label": "Tool", placeholder: "Tool", value: filters.tool ?? '', onChange: event => set({ tool: event.currentTarget.value || undefined }) }), _jsxs(Select, { size: "small", "aria-label": "Decision", value: filters.decision ?? '', onChange: event => set({
90
85
  decision: (event.currentTarget.value ||
91
86
  undefined),
92
87
  }), children: [_jsx(Select.Option, { value: "", children: "Every decision" }), _jsx(Select.Option, { value: "allowed", children: "Allowed" }), _jsx(Select.Option, { value: "refused", children: "Refused" })] }), _jsxs(Select, { size: "small", "aria-label": "Outcome", value: filters.outcome ?? '', onChange: event => set({
93
88
  outcome: (event.currentTarget.value ||
94
89
  undefined),
95
- }), children: [_jsx(Select.Option, { value: "", children: "Every outcome" }), _jsx(Select.Option, { value: "ok", children: "Succeeded" }), _jsx(Select.Option, { value: "error", children: "Failed" }), _jsx(Select.Option, { value: "is_error", children: "Tool error" })] }), _jsx(Box, { sx: { display: 'flex', gap: 2, justifyContent: 'flex-end' }, children: _jsxs(ActionMenu, { children: [_jsx(ActionMenu.Button, { size: "small", leadingVisual: DownloadIcon, disabled: exporting.isPending, children: "Export" }), _jsx(ActionMenu.Overlay, { align: "end", children: _jsxs(ActionList, { children: [_jsxs(ActionList.Item, { onSelect: () => exportAs('jsonl'), children: ["JSONL", _jsx(ActionList.Description, { variant: "block", children: "One row per line, as a SIEM reads it." })] }), _jsxs(ActionList.Item, { onSelect: () => exportAs('csv'), children: ["CSV", _jsx(ActionList.Description, { variant: "block", children: "The same rows for a spreadsheet." })] })] }) })] }) })] }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.subtle' }, children: ["Audit rows are written once and never changed or deleted by anyone, here or elsewhere. Arguments are redacted before they are written.", ' ', retention] }), page.isPending && !page.data ? (_jsx(Box, { sx: { display: 'flex', justifyContent: 'center', py: 6 }, children: _jsx(Spinner, {}) })) : rows.length === 0 ? (_jsxs(Blankslate, { border: true, spacious: true, children: [_jsx(Blankslate.Visual, { children: _jsx(HistoryIcon, { size: "medium" }) }), _jsx(Blankslate.Heading, { children: "Nothing to audit yet" }), _jsx(Blankslate.Description, { children: _jsx(Text, { sx: { textAlign: 'center' }, children: "Every call an agent makes is written down here with its decision and its outcome. Connect a client and ask it to list your notebooks." }) }), _jsx(Button, { size: "small", onClick: () => navigate(routes.access), children: "Connect an agent" })] })) : (
90
+ }), children: [_jsx(Select.Option, { value: "", children: "Every outcome" }), _jsx(Select.Option, { value: "ok", children: "Succeeded" }), _jsx(Select.Option, { value: "error", children: "Failed" }), _jsx(Select.Option, { value: "is_error", children: "Tool error" })] }), _jsx(Box, { display: "flex", gap: 2, justifyContent: "flex-end", children: _jsxs(ActionMenu, { children: [_jsx(ActionMenu.Button, { size: "small", leadingVisual: DownloadIcon, disabled: exporting.isPending, children: "Export" }), _jsx(ActionMenu.Overlay, { align: "end", children: _jsxs(ActionList, { children: [_jsxs(ActionList.Item, { onSelect: () => exportAs('jsonl'), children: ["JSONL", _jsx(ActionList.Description, { variant: "block", children: "One row per line, as a SIEM reads it." })] }), _jsxs(ActionList.Item, { onSelect: () => exportAs('csv'), children: ["CSV", _jsx(ActionList.Description, { variant: "block", children: "The same rows for a spreadsheet." })] })] }) })] }) })] }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.subtle' }, children: ["Audit rows are written once and never changed or deleted by anyone, here or elsewhere. Arguments are redacted before they are written.", ' ', retention] }), page.isPending && !page.data ? (_jsx(Box, { display: "flex", justifyContent: "center", py: 6, children: _jsx(Spinner, {}) })) : rows.length === 0 ? (_jsxs(Blankslate, { border: true, spacious: true, children: [_jsx(Blankslate.Visual, { children: _jsx(HistoryIcon, { size: "medium" }) }), _jsx(Blankslate.Heading, { children: "Nothing to audit yet" }), _jsx(Blankslate.Description, { children: _jsx(Text, { sx: { textAlign: 'center' }, children: "Every call an agent makes is written down here with its decision and its outcome. Connect a client and ask it to list your notebooks." }) }), _jsx(Button, { size: "small", onClick: () => navigate(routes.access), children: "Connect an agent" })] })) : (
96
91
  /* The rail of the activity view: each mark on a tinted disc, the discs
97
92
  linked by a line, so the rows carry no border of their own. */
98
- _jsx(Box, { sx: { display: 'grid' }, children: rows.map((event, index) => {
93
+ _jsx(Box, { display: "grid", children: rows.map((event, index) => {
99
94
  const look = decisionLook(event);
100
95
  const isLast = index === rows.length - 1;
101
- return (_jsxs(Box, { sx: { display: 'flex', gap: 3 }, children: [_jsxs(Box, { sx: {
102
- display: 'flex',
103
- flexDirection: 'column',
104
- alignItems: 'center',
105
- }, children: [_jsx(Box, { sx: {
106
- width: 26,
107
- height: 26,
108
- borderRadius: '50%',
109
- display: 'inline-flex',
110
- alignItems: 'center',
111
- justifyContent: 'center',
112
- color: look.fg,
113
- bg: look.bg,
114
- flexShrink: 0,
115
- }, children: _jsx(look.Icon, { size: 13 }) }), !isLast && (_jsx(Box, { sx: { width: '2px', flex: 1, bg: 'border.muted', my: 1 } }))] }), _jsxs(Box, { sx: {
116
- flexGrow: 1,
117
- minWidth: 0,
118
- pb: isLast ? 0 : 3,
119
- pt: '3px',
120
- }, children: [_jsx(Link, { as: "button", sx: {
96
+ return (_jsxs(Box, { display: "flex", gap: 3, children: [_jsxs(Box, { display: "flex", flexDirection: "column", alignItems: "center", children: [_jsx(Box, { width: 26, height: 26, borderRadius: "50%", display: "inline-flex", alignItems: "center", justifyContent: "center", color: look.fg, bg: look.bg, flexShrink: 0, children: _jsx(look.Icon, { size: 13 }) }), !isLast && (_jsx(Box, { width: "2px", flex: 1, bg: "border.muted", my: 1 }))] }), _jsxs(Box, { flexGrow: 1, minWidth: 0, pb: isLast ? 0 : 3, pt: "3px", children: [_jsx(Link, { as: "button", sx: {
121
97
  fontSize: 1,
122
98
  display: 'block',
123
99
  textAlign: 'left',
124
100
  cursor: 'pointer',
125
- }, onClick: () => setOpen(event), children: event.tool || event.method }), _jsxs(Box, { sx: {
126
- display: 'flex',
127
- gap: 2,
128
- alignItems: 'center',
129
- mt: 1,
130
- flexWrap: 'wrap',
131
- }, children: [_jsx(Label, { size: "small", variant: event.decision === 'refused' ? 'danger' : 'success', children: event.decision }), event.clientId && (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: event.clientId })), event.itemUid && (_jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: ["on ", event.itemUid] })), event.durationMs !== null &&
101
+ }, onClick: () => setOpen(event), children: event.tool || event.method }), _jsxs(Box, { display: "flex", gap: 2, alignItems: "center", mt: 1, flexWrap: "wrap", children: [_jsx(Label, { size: "small", variant: event.decision === 'refused' ? 'danger' : 'success', children: event.decision }), event.clientId && (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: event.clientId })), event.itemUid && (_jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: ["on ", event.itemUid] })), event.durationMs !== null &&
132
102
  event.durationMs !== undefined && (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: durationLabel(event.durationMs) })), event.refusalReason && (_jsx(Text, { sx: { fontSize: 0, color: 'danger.fg' }, children: event.refusalReason }))] })] }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted', flexShrink: 0 }, children: _jsx(RelativeTime, { datetime: event.at }) })] }, event.uid));
133
- }) })), (walked.length > 0 || nextCursor) && (_jsxs(Box, { sx: { display: 'flex', gap: 2, justifyContent: 'center' }, children: [_jsx(Button, { size: "small", leadingVisual: ChevronLeftIcon, disabled: walked.length === 0, onClick: newer, children: "Newer" }), _jsx(Button, { size: "small", trailingVisual: ChevronRightIcon, disabled: !nextCursor, onClick: older, children: "Older" })] })), open && (_jsx(Dialog, { title: open.tool || open.method, subtitle: `${open.decision} · ${open.outcome ?? 'no outcome recorded'}`, onClose: () => setOpen(null), returnFocusRef: returnFocusRef, width: "large", children: _jsxs(Box, { sx: { display: 'grid', gap: 3 }, children: [_jsxs(Box, { sx: { display: 'grid', gap: 1 }, children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "When" }), _jsxs(Text, { sx: { fontSize: 1 }, children: [_jsx(RelativeTime, { datetime: open.at }), " \u2014 ", open.at] })] }), _jsxs(Box, { sx: { display: 'grid', gap: 1 }, children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Who" }), _jsxs(Text, { sx: { fontSize: 1 }, children: [open.clientId || 'unknown client', open.act &&
103
+ }) })), (walked.length > 0 || nextCursor) && (_jsxs(Box, { display: "flex", gap: 2, justifyContent: "center", children: [_jsx(Button, { size: "small", leadingVisual: ChevronLeftIcon, disabled: walked.length === 0, onClick: newer, children: "Newer" }), _jsx(Button, { size: "small", trailingVisual: ChevronRightIcon, disabled: !nextCursor, onClick: older, children: "Older" })] })), open && (_jsx(Dialog, { title: open.tool || open.method, subtitle: `${open.decision} · ${open.outcome ?? 'no outcome recorded'}`, onClose: () => setOpen(null), returnFocusRef: returnFocusRef, width: "large", children: _jsxs(Box, { display: "grid", gap: 3, children: [_jsxs(Box, { display: "grid", gap: 1, children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "When" }), _jsxs(Text, { sx: { fontSize: 1 }, children: [_jsx(RelativeTime, { datetime: open.at }), " \u2014 ", open.at] })] }), _jsxs(Box, { display: "grid", gap: 1, children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Who" }), _jsxs(Text, { sx: { fontSize: 1 }, children: [open.clientId || 'unknown client', open.act &&
134
104
  open.act.length > 0 &&
135
- ` acting for ${open.act.join(' → ')}`] })] }), open.refusalReason && (_jsxs(Box, { sx: { display: 'grid', gap: 1 }, children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Why it was refused" }), _jsx(Text, { sx: { fontSize: 1, color: 'danger.fg' }, children: open.refusalReason })] })), _jsxs(Box, { sx: { display: 'grid', gap: 1 }, children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Arguments, redacted before they were written" }), _jsx(Box, { as: "pre", sx: {
136
- m: 0,
137
- p: 2,
138
- fontSize: 0,
139
- bg: 'canvas.inset',
140
- borderRadius: 2,
141
- overflowX: 'auto',
142
- }, children: JSON.stringify(open.redactedArguments ?? {}, null, 2) }), open.argumentsHash && (_jsx(Text, { sx: { fontSize: 0, color: 'fg.subtle', fontFamily: 'mono' }, children: open.argumentsHash }))] }), _jsxs(Box, { sx: { display: 'flex', gap: 2, flexWrap: 'wrap' }, children: [open.taskId && (_jsx(Button, { size: "small", onClick: () => navigate(`${routes.runs}/${encodeURIComponent(open.taskId)}`), children: "The run" })), open.traceId && (_jsx(Button, { size: "small", onClick: () => navigate(`${routes.observability}?trace=${encodeURIComponent(open.traceId)}`), children: "The trace" }))] })] }) }))] }));
105
+ ` acting for ${open.act.join(' → ')}`] })] }), open.refusalReason && (_jsxs(Box, { display: "grid", gap: 1, children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Why it was refused" }), _jsx(Text, { sx: { fontSize: 1, color: 'danger.fg' }, children: open.refusalReason })] })), _jsxs(Box, { display: "grid", gap: 1, children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Arguments, redacted before they were written" }), _jsx(Box, { as: "pre", m: 0, p: 2, fontSize: 0, bg: "canvas.inset", borderRadius: 2, overflowX: "auto", children: JSON.stringify(open.redactedArguments ?? {}, null, 2) }), open.argumentsHash && (_jsx(Text, { sx: { fontSize: 0, color: 'fg.subtle', fontFamily: 'mono' }, children: open.argumentsHash }))] }), _jsxs(Box, { display: "flex", gap: 2, flexWrap: "wrap", children: [open.taskId && (_jsx(Button, { size: "small", onClick: () => navigate(`${routes.runs}/${encodeURIComponent(open.taskId)}`), children: "The run" })), open.traceId && (_jsx(Button, { size: "small", onClick: () => navigate(`${routes.observability}?trace=${encodeURIComponent(open.traceId)}`), children: "The trace" }))] })] }) }))] }));
143
106
  };
144
107
  export default AuditLog;
@@ -101,12 +101,7 @@ export const ConnectedAgents = ({ errorState, routes, showTitle = true, readOnly
101
101
  if (agents.isError) {
102
102
  return (_jsx(McpErrorBlankslate, { state: errorState(agents.error, 'Connected agents'), onRetry: () => agents.refetch() }));
103
103
  }
104
- return (_jsxs(Box, { sx: { display: 'grid', gap: 3, minWidth: 0 }, children: [showTitle && (_jsxs(Box, { sx: {
105
- display: 'flex',
106
- alignItems: 'start',
107
- justifyContent: 'space-between',
108
- gap: 3,
109
- }, children: [_jsxs(Box, { children: [_jsx(Heading, { as: "h2", sx: { fontSize: 3, mb: 1 }, children: "Connected Agents" }), _jsx(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 1, m: 0 }, children: "Every agent you have authorized, what it may do, and when it last did it." })] }), !readOnly && rows.length > 0 && (_jsx(Button, { variant: "danger", onClick: () => setDisconnectingEvery(true), disabled: disconnectEvery.isPending, children: "Disconnect all" }))] })), agents.isPending && !agents.data ? (_jsx(Box, { sx: { display: 'flex', justifyContent: 'center', py: 5 }, children: _jsx(Spinner, {}) })) : rows.length > 0 ? (_jsxs(Table.Container, { children: [_jsx(Table.Title, { as: "h3", id: "connected-agents", children: "Agents" }), _jsx(Table.Subtitle, { as: "p", id: "connected-agents-subtitle", children: "An agent acts with exactly the access of the person who authorized it, and no more." }), _jsx(DataTable, { "aria-labelledby": "connected-agents", "aria-describedby": "connected-agents-subtitle", data: rows, columns: columns })] })) : (_jsxs(Blankslate, { border: true, spacious: true, children: [_jsx(Blankslate.Visual, { children: _jsx(PlugIcon, { size: "medium" }) }), _jsx(Blankslate.Heading, { children: "No agent connected" }), _jsx(Blankslate.Description, { children: _jsx(Text, { sx: { textAlign: 'center' }, children: "Connect an MCP client and approve the scopes it asks for; the grant appears here and can be revoked from here." }) }), _jsx(Button, { size: "small", onClick: () => navigate(routes.access), children: "Connect an agent" })] })), _jsx(Text, { sx: { fontSize: 0, color: 'fg.subtle' }, children: "Narrowing a grant to fewer scopes without disconnecting arrives with the organization policy." }), disconnecting && (_jsx(Dialog, { title: "Disconnect this agent?", onClose: () => setDisconnecting(null), returnFocusRef: returnFocusRef, footerButtons: [
104
+ return (_jsxs(Box, { display: "grid", gap: 3, minWidth: 0, children: [showTitle && (_jsxs(Box, { display: "flex", alignItems: "start", justifyContent: "space-between", gap: 3, children: [_jsxs(Box, { children: [_jsx(Heading, { as: "h2", sx: { fontSize: 3, mb: 1 }, children: "Connected Agents" }), _jsx(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 1, m: 0 }, children: "Every agent you have authorized, what it may do, and when it last did it." })] }), !readOnly && rows.length > 0 && (_jsx(Button, { variant: "danger", onClick: () => setDisconnectingEvery(true), disabled: disconnectEvery.isPending, children: "Disconnect all" }))] })), agents.isPending && !agents.data ? (_jsx(Box, { display: "flex", justifyContent: "center", py: 5, children: _jsx(Spinner, {}) })) : rows.length > 0 ? (_jsxs(Table.Container, { children: [_jsx(Table.Title, { as: "h3", id: "connected-agents", children: "Agents" }), _jsx(Table.Subtitle, { as: "p", id: "connected-agents-subtitle", children: "An agent acts with exactly the access of the person who authorized it, and no more." }), _jsx(DataTable, { "aria-labelledby": "connected-agents", "aria-describedby": "connected-agents-subtitle", data: rows, columns: columns })] })) : (_jsxs(Blankslate, { border: true, spacious: true, children: [_jsx(Blankslate.Visual, { children: _jsx(PlugIcon, { size: "medium" }) }), _jsx(Blankslate.Heading, { children: "No agent connected" }), _jsx(Blankslate.Description, { children: _jsx(Text, { sx: { textAlign: 'center' }, children: "Connect an MCP client and approve the scopes it asks for; the grant appears here and can be revoked from here." }) }), _jsx(Button, { size: "small", onClick: () => navigate(routes.access), children: "Connect an agent" })] })), _jsx(Text, { sx: { fontSize: 0, color: 'fg.subtle' }, children: "Narrowing a grant to fewer scopes without disconnecting arrives with the organization policy." }), disconnecting && (_jsx(Dialog, { title: "Disconnect this agent?", onClose: () => setDisconnecting(null), returnFocusRef: returnFocusRef, footerButtons: [
110
105
  {
111
106
  buttonType: 'default',
112
107
  content: 'Keep it',
@@ -90,13 +90,7 @@ export const pagesForRoles = (roles) => {
90
90
  }
91
91
  return [];
92
92
  };
93
- const Metric = ({ label, value, note, tone = 'neutral', }) => (_jsxs(Box, { sx: {
94
- p: 3,
95
- border: '1px solid',
96
- borderColor: 'border.default',
97
- borderRadius: 2,
98
- minWidth: 0,
99
- }, children: [_jsx(Text, { sx: {
93
+ const Metric = ({ label, value, note, tone = 'neutral', }) => (_jsxs(Box, { p: 3, border: "1px solid", borderColor: "border.default", borderRadius: 2, minWidth: 0, children: [_jsx(Text, { sx: {
100
94
  display: 'block',
101
95
  fontSize: 4,
102
96
  fontWeight: 'bold',
@@ -161,7 +155,7 @@ export const EnterpriseConsole = ({ errorState, routes, organization, roles, pag
161
155
  id: 'actions',
162
156
  width: '200px',
163
157
  align: 'end',
164
- renderCell: row => (_jsxs(Box, { sx: { display: 'flex', gap: 2, justifyContent: 'flex-end' }, children: [_jsx(Button, { size: "small", onClick: () => navigate(`${routes.audit}?org=${encodeURIComponent(organization.uid)}&agent=${encodeURIComponent(row.clientId)}`), children: "Audit" }), _jsx(Button, { size: "small", variant: "danger", disabled: !row.grantUid, onClick: () => row.grantUid &&
158
+ renderCell: row => (_jsxs(Box, { display: "flex", gap: 2, justifyContent: "flex-end", children: [_jsx(Button, { size: "small", onClick: () => navigate(`${routes.audit}?org=${encodeURIComponent(organization.uid)}&agent=${encodeURIComponent(row.clientId)}`), children: "Audit" }), _jsx(Button, { size: "small", variant: "danger", disabled: !row.grantUid, onClick: () => row.grantUid &&
165
159
  disconnect.mutate(row.grantUid, {
166
160
  onSuccess: () => enqueueToast(`${row.clientName || row.clientId} is disconnected.`, {
167
161
  variant: 'success',
@@ -170,26 +164,19 @@ export const EnterpriseConsole = ({ errorState, routes, organization, roles, pag
170
164
  }), children: "Revoke" })] })),
171
165
  },
172
166
  ];
173
- return (_jsxs(Box, { sx: { display: 'grid', gap: 4, minWidth: 0 }, children: [_jsxs(Box, { children: [_jsxs(Heading, { as: "h3", sx: { fontSize: 2, mb: 1 }, children: ["MCP \u2014 ", organization.name || organization.handle] }), _jsx(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 1, m: 0 }, children: "What the agents of this organization are doing, what they were allowed to do, and how it ran." })] }), _jsx(SegmentedControl, { "aria-label": "MCP console pages", size: "small", children: ENTERPRISE_CONSOLE_PAGES.filter(entry => allowed.includes(entry.id)).map(entry => (_jsx(SegmentedControl.Button, { selected: current === entry.id, onClick: () => onPageChange(entry.id), children: entry.label }, entry.id))) }), current === 'overview' &&
174
- (overview.isError ? (_jsx(McpErrorBlankslate, { state: errorState(overview.error, 'The overview'), onRetry: () => overview.refetch() })) : overview.isPending && !overview.data ? (_jsx(Box, { sx: { display: 'flex', justifyContent: 'center', py: 6 }, children: _jsx(Spinner, {}) })) : (_jsxs(Box, { sx: { display: 'grid', gap: 4 }, children: [_jsxs(Box, { sx: {
175
- display: 'grid',
176
- gap: 3,
177
- gridTemplateColumns: [
178
- 'repeat(2, 1fr)',
179
- 'repeat(3, 1fr)',
180
- 'repeat(5, 1fr)',
181
- ],
182
- }, children: [_jsx(Metric, { label: "Agents active today", value: overview.data?.agents.activeToday ?? 0, note: `${overview.data?.agents.delegated ?? 0} delegated · ${overview.data?.agents.service ?? 0} service` }), _jsx(Metric, { label: "Runs today", value: overview.data?.runs.today ?? 0 }), _jsx(Metric, { label: "Success rate", value: overview.data?.runs.successRate === null ||
167
+ return (_jsxs(Box, { display: "grid", gap: 4, minWidth: 0, children: [_jsxs(Box, { children: [_jsxs(Heading, { as: "h3", sx: { fontSize: 2, mb: 1 }, children: ["MCP \u2014 ", organization.name || organization.handle] }), _jsx(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 1, m: 0 }, children: "What the agents of this organization are doing, what they were allowed to do, and how it ran." })] }), _jsx(SegmentedControl, { "aria-label": "MCP console pages", size: "small", children: ENTERPRISE_CONSOLE_PAGES.filter(entry => allowed.includes(entry.id)).map(entry => (_jsx(SegmentedControl.Button, { selected: current === entry.id, onClick: () => onPageChange(entry.id), children: entry.label }, entry.id))) }), current === 'overview' &&
168
+ (overview.isError ? (_jsx(McpErrorBlankslate, { state: errorState(overview.error, 'The overview'), onRetry: () => overview.refetch() })) : overview.isPending && !overview.data ? (_jsx(Box, { display: "flex", justifyContent: "center", py: 6, children: _jsx(Spinner, {}) })) : (_jsxs(Box, { display: "grid", gap: 4, children: [_jsxs(Box, { display: "grid", gap: 3, gridTemplateColumns: [
169
+ 'repeat(2, 1fr)',
170
+ 'repeat(3, 1fr)',
171
+ 'repeat(5, 1fr)',
172
+ ], children: [_jsx(Metric, { label: "Agents active today", value: overview.data?.agents.activeToday ?? 0, note: `${overview.data?.agents.delegated ?? 0} delegated · ${overview.data?.agents.service ?? 0} service` }), _jsx(Metric, { label: "Runs today", value: overview.data?.runs.today ?? 0 }), _jsx(Metric, { label: "Success rate", value: overview.data?.runs.successRate === null ||
183
173
  overview.data?.runs.successRate === undefined
184
174
  ? '—'
185
175
  : `${(overview.data.runs.successRate * 100).toFixed(0)}%`, note: `${overview.data?.runs.failed ?? 0} failed` }), _jsx(Metric, { label: "Credits today", value: overview.data?.spend?.creditsToday ?? '—', note: overview.data?.spend?.quotaMonth
186
176
  ? `${overview.data.spend.creditsMonth} of ${overview.data.spend.quotaMonth} this month`
187
177
  : 'Quotas arrive with the organization policy' }), _jsx(Metric, { label: "Refusals today", value: (overview.data?.refusals ?? []).reduce((sum, row) => sum + row.count, 0), tone: (overview.data?.refusals ?? []).length > 0
188
178
  ? 'danger'
189
- : 'neutral' })] }), (overview.data?.refusals ?? []).length > 0 && (_jsxs(Box, { sx: { display: 'grid', gap: 2 }, children: [_jsx(Heading, { as: "h4", sx: { fontSize: 1 }, children: "Why calls were refused" }), _jsx(Box, { sx: { display: 'flex', gap: 2, flexWrap: 'wrap' }, children: (overview.data?.refusals ?? []).map(row => (_jsxs(Label, { size: "small", variant: "danger", children: [row.reason, " \u00B7 ", row.count] }, row.reason))) })] })), _jsxs(Box, { sx: { display: 'grid', gap: 2 }, children: [_jsx(Heading, { as: "h4", sx: { fontSize: 1 }, children: "Compliance" }), (overview.data?.compliance ?? []).length === 0 ? (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Nothing to check yet: the strip fills as the organization's sign-in, admitted clients and audit export are configured." })) : (_jsx(Box, { sx: { display: 'grid', gap: 1 }, children: (overview.data?.compliance ?? []).map(check => (_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Box, { sx: {
190
- color: check.ok ? 'success.fg' : 'attention.fg',
191
- display: 'flex',
192
- }, children: check.ok ? (_jsx(CheckCircleIcon, { size: 14 })) : (_jsx(AlertIcon, { size: 14 })) }), _jsx(Text, { sx: { fontSize: 1 }, children: check.name }), !check.ok && check.detail && (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: check.detail }))] }, check.name))) }))] }), _jsxs(Box, { sx: { display: 'flex', gap: 3, flexWrap: 'wrap' }, children: [_jsx(Metric, { label: "Approvals waiting", value: overview.data?.approvalsWaiting ?? '—', note: "The queue arrives with durable execution" }), _jsx(Metric, { label: "Alerts firing", value: overview.data?.alertsFiring ?? '—', note: "Alert rules arrive with quotas" })] })] }))), current === 'usage' && (_jsx(OrganizationUsage, { errorState: errorState, orgUid: organization.uid, showTitle: false })), current === 'teams' && (_jsx(TeamPolicies, { errorState: errorState, orgUid: organization.uid, readOnly: !roles.includes('organization_owner') })), current === 'identity-providers' && (_jsxs(Box, { sx: { display: 'grid', gap: 5, minWidth: 0 }, children: [_jsx(IdentityProviders, { errorState: errorState, orgUid: organization.uid, readOnly: !roles.includes('organization_owner') }), _jsx(ScimProvisioning, { errorState: errorState, orgUid: organization.uid, readOnly: !roles.includes('organization_owner') })] })), current === 'alerts' && (_jsx(AlertRules, { errorState: errorState, orgUid: organization.uid, readOnly: !roles.includes('organization_owner') })), current === 'approvals' && _jsx(ApprovalQueue, { errorState: errorState }), current === 'policy' && (_jsx(OrganizationPolicy, { errorState: errorState, orgUid: organization.uid, readOnly: !roles.includes('organization_owner') })), current === 'service-agents' && (_jsx(ServiceAgents, { errorState: errorState, orgUid: organization.uid, readOnly: !roles.includes('organization_owner') })), current === 'agents' &&
193
- (activity.isError ? (_jsx(McpErrorBlankslate, { state: errorState(activity.error, "The organization's agents"), onRetry: () => activity.refetch() })) : activity.isPending && !activity.data ? (_jsx(Box, { sx: { display: 'flex', justifyContent: 'center', py: 6 }, children: _jsx(Spinner, {}) })) : agentRows.length === 0 ? (_jsxs(Blankslate, { border: true, spacious: true, children: [_jsx(Blankslate.Visual, { children: _jsx(PlugIcon, { size: "medium" }) }), _jsx(Blankslate.Heading, { children: "No agent acts for this organization" }), _jsx(Blankslate.Description, { children: _jsxs(Text, { sx: { textAlign: 'center' }, children: ["A member who authorizes a client while acting for", ' ', organization.name || organization.handle, " appears here with the scopes the grant carries and what it last did."] }) })] })) : (_jsxs(Table.Container, { children: [_jsx(Table.Title, { as: "h4", id: "org-agents", children: "Agents" }), _jsxs(Table.Subtitle, { as: "p", id: "org-agents-subtitle", children: [plural(agentRows.length, 'principal'), " acting through MCP for this organization. A member's own grant is revoked by that member; revoking on their behalf arrives with the organization's agent directory."] }), _jsx(DataTable, { "aria-labelledby": "org-agents", "aria-describedby": "org-agents-subtitle", data: agentRows, columns: agentColumns })] }))), current === 'audit' && (_jsx(AuditLog, { errorState: errorState, routes: routes, showTitle: false, subject: organization.name || organization.handle, filters: { ...auditFilters, org: organization.uid }, onFiltersChange: filters => onAuditFiltersChange({ ...filters, org: undefined }) })), current === 'observability' && (_jsx(McpObservability, { errorState: errorState, routes: routes, showTitle: false, org: organization.uid, pane: observabilityPane, onPaneChange: onObservabilityPaneChange, taskUid: observabilityTask, traceId: observabilityTrace, onSelect: onObservabilitySelect })), _jsx(Text, { sx: { fontSize: 0, color: 'fg.subtle' }, children: "Teams, Policies, Quotas, Alerts, Approvals and Runs join this console as the layers behind them ship. Identity \u2014 providers, group mapping, SCIM and session controls \u2014 comes last, with enterprise sign-in." })] }));
179
+ : 'neutral' })] }), (overview.data?.refusals ?? []).length > 0 && (_jsxs(Box, { display: "grid", gap: 2, children: [_jsx(Heading, { as: "h4", sx: { fontSize: 1 }, children: "Why calls were refused" }), _jsx(Box, { display: "flex", gap: 2, flexWrap: "wrap", children: (overview.data?.refusals ?? []).map(row => (_jsxs(Label, { size: "small", variant: "danger", children: [row.reason, " \u00B7 ", row.count] }, row.reason))) })] })), _jsxs(Box, { display: "grid", gap: 2, children: [_jsx(Heading, { as: "h4", sx: { fontSize: 1 }, children: "Compliance" }), (overview.data?.compliance ?? []).length === 0 ? (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Nothing to check yet: the strip fills as the organization's sign-in, admitted clients and audit export are configured." })) : (_jsx(Box, { display: "grid", gap: 1, children: (overview.data?.compliance ?? []).map(check => (_jsxs(Box, { display: "flex", alignItems: "center", gap: 2, children: [_jsx(Box, { color: check.ok ? 'success.fg' : 'attention.fg', display: "flex", children: check.ok ? (_jsx(CheckCircleIcon, { size: 14 })) : (_jsx(AlertIcon, { size: 14 })) }), _jsx(Text, { sx: { fontSize: 1 }, children: check.name }), !check.ok && check.detail && (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: check.detail }))] }, check.name))) }))] }), _jsxs(Box, { display: "flex", gap: 3, flexWrap: "wrap", children: [_jsx(Metric, { label: "Approvals waiting", value: overview.data?.approvalsWaiting ?? '—', note: "The queue arrives with durable execution" }), _jsx(Metric, { label: "Alerts firing", value: overview.data?.alertsFiring ?? '—', note: "Alert rules arrive with quotas" })] })] }))), current === 'usage' && (_jsx(OrganizationUsage, { errorState: errorState, orgUid: organization.uid, showTitle: false })), current === 'teams' && (_jsx(TeamPolicies, { errorState: errorState, orgUid: organization.uid, readOnly: !roles.includes('organization_owner') })), current === 'identity-providers' && (_jsxs(Box, { display: "grid", gap: 5, minWidth: 0, children: [_jsx(IdentityProviders, { errorState: errorState, orgUid: organization.uid, readOnly: !roles.includes('organization_owner') }), _jsx(ScimProvisioning, { errorState: errorState, orgUid: organization.uid, readOnly: !roles.includes('organization_owner') })] })), current === 'alerts' && (_jsx(AlertRules, { errorState: errorState, orgUid: organization.uid, readOnly: !roles.includes('organization_owner') })), current === 'approvals' && _jsx(ApprovalQueue, { errorState: errorState }), current === 'policy' && (_jsx(OrganizationPolicy, { errorState: errorState, orgUid: organization.uid, readOnly: !roles.includes('organization_owner') })), current === 'service-agents' && (_jsx(ServiceAgents, { errorState: errorState, orgUid: organization.uid, readOnly: !roles.includes('organization_owner') })), current === 'agents' &&
180
+ (activity.isError ? (_jsx(McpErrorBlankslate, { state: errorState(activity.error, "The organization's agents"), onRetry: () => activity.refetch() })) : activity.isPending && !activity.data ? (_jsx(Box, { display: "flex", justifyContent: "center", py: 6, children: _jsx(Spinner, {}) })) : agentRows.length === 0 ? (_jsxs(Blankslate, { border: true, spacious: true, children: [_jsx(Blankslate.Visual, { children: _jsx(PlugIcon, { size: "medium" }) }), _jsx(Blankslate.Heading, { children: "No agent acts for this organization" }), _jsx(Blankslate.Description, { children: _jsxs(Text, { sx: { textAlign: 'center' }, children: ["A member who authorizes a client while acting for", ' ', organization.name || organization.handle, " appears here with the scopes the grant carries and what it last did."] }) })] })) : (_jsxs(Table.Container, { children: [_jsx(Table.Title, { as: "h4", id: "org-agents", children: "Agents" }), _jsxs(Table.Subtitle, { as: "p", id: "org-agents-subtitle", children: [plural(agentRows.length, 'principal'), " acting through MCP for this organization. A member's own grant is revoked by that member; revoking on their behalf arrives with the organization's agent directory."] }), _jsx(DataTable, { "aria-labelledby": "org-agents", "aria-describedby": "org-agents-subtitle", data: agentRows, columns: agentColumns })] }))), current === 'audit' && (_jsx(AuditLog, { errorState: errorState, routes: routes, showTitle: false, subject: organization.name || organization.handle, filters: { ...auditFilters, org: organization.uid }, onFiltersChange: filters => onAuditFiltersChange({ ...filters, org: undefined }) })), current === 'observability' && (_jsx(McpObservability, { errorState: errorState, routes: routes, showTitle: false, org: organization.uid, pane: observabilityPane, onPaneChange: onObservabilityPaneChange, taskUid: observabilityTask, traceId: observabilityTrace, onSelect: onObservabilitySelect })), _jsx(Text, { sx: { fontSize: 0, color: 'fg.subtle' }, children: "Teams, Policies, Quotas, Alerts, Approvals and Runs join this console as the layers behind them ship. Identity \u2014 providers, group mapping, SCIM and session controls \u2014 comes last, with enterprise sign-in." })] }));
194
181
  };
195
182
  export default EnterpriseConsole;
@@ -165,13 +165,13 @@ export const IdentityProviders = ({ errorState, orgUid, readOnly = false, showTi
165
165
  id: 'name',
166
166
  rowHeader: true,
167
167
  width: 'growCollapse',
168
- renderCell: row => (_jsxs(Box, { sx: { display: 'grid' }, children: [_jsx(Text, { sx: { fontSize: 1, fontWeight: 'bold' }, children: row.name }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: row.issuer })] })),
168
+ renderCell: row => (_jsxs(Box, { display: "grid", children: [_jsx(Text, { sx: { fontSize: 1, fontWeight: 'bold' }, children: row.name }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: row.issuer })] })),
169
169
  },
170
170
  {
171
171
  header: 'Domains',
172
172
  id: 'domains',
173
173
  width: 'growCollapse',
174
- renderCell: row => (_jsxs(Box, { sx: { display: 'flex', flexWrap: 'wrap', gap: 1 }, children: [row.domains.length === 0 && (_jsx(Text, { sx: { fontSize: 0, color: 'fg.subtle' }, children: "none" })), row.domains.map(domain => (_jsxs(Label, { size: "small", variant: row.verifiedDomains.includes(domain) ? 'success' : 'secondary', children: [domain, row.verifiedDomains.includes(domain)
174
+ renderCell: row => (_jsxs(Box, { display: "flex", flexWrap: "wrap", gap: 1, children: [row.domains.length === 0 && (_jsx(Text, { sx: { fontSize: 0, color: 'fg.subtle' }, children: "none" })), row.domains.map(domain => (_jsxs(Label, { size: "small", variant: row.verifiedDomains.includes(domain) ? 'success' : 'secondary', children: [domain, row.verifiedDomains.includes(domain)
175
175
  ? ' · verified'
176
176
  : ' · claimed'] }, domain)))] })),
177
177
  },
@@ -192,12 +192,7 @@ export const IdentityProviders = ({ errorState, orgUid, readOnly = false, showTi
192
192
  if (providers.isError) {
193
193
  return (_jsx(McpErrorBlankslate, { state: errorState(providers.error, 'Identity providers'), onRetry: () => providers.refetch() }));
194
194
  }
195
- return (_jsxs(Box, { sx: { display: 'grid', gap: 3, minWidth: 0 }, children: [showTitle && (_jsxs(Box, { sx: {
196
- display: 'flex',
197
- alignItems: 'start',
198
- justifyContent: 'space-between',
199
- gap: 3,
200
- }, children: [_jsxs(Box, { children: [_jsx(Heading, { as: "h2", sx: { fontSize: 3, mb: 1 }, children: "Identity providers" }), _jsx(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 1, m: 0 }, children: "The directory this organization signs in through. A domain is claimed the moment it is typed here and routes nothing until it is verified." })] }), !readOnly && (_jsx(Button, { variant: "primary", onClick: openCreate, children: "New provider" }))] })), providers.isPending && !providers.data ? (_jsx(Box, { sx: { display: 'flex', justifyContent: 'center', py: 5 }, children: _jsx(Spinner, {}) })) : rows.length > 0 ? (_jsxs(Table.Container, { children: [_jsx(Table.Title, { as: "h3", id: "identity-providers", children: "Providers" }), _jsx(Table.Subtitle, { as: "p", id: "identity-providers-subtitle", children: "A provider switched off keeps its configuration and its verified domains; only sign-in through it stops." }), _jsx(DataTable, { "aria-labelledby": "identity-providers", "aria-describedby": "identity-providers-subtitle", data: rows, columns: columns })] })) : (_jsxs(Blankslate, { border: true, spacious: true, children: [_jsx(Blankslate.Visual, { children: _jsx(KeyIcon, { size: "medium" }) }), _jsx(Blankslate.Heading, { children: "No directory registered" }), _jsx(Blankslate.Description, { children: _jsx(Text, { sx: { textAlign: 'center' }, children: "People here sign in the ordinary way. Register a provider to let them sign in through the directory this organization already has." }) }), !readOnly && (_jsx(Button, { size: "small", onClick: openCreate, children: "New provider" }))] })), (creating || editing) && (_jsx(Dialog, { title: editing ? 'Edit identity provider' : 'New identity provider', onClose: close, returnFocusRef: returnFocusRef, footerButtons: [
195
+ return (_jsxs(Box, { display: "grid", gap: 3, minWidth: 0, children: [showTitle && (_jsxs(Box, { display: "flex", alignItems: "start", justifyContent: "space-between", gap: 3, children: [_jsxs(Box, { children: [_jsx(Heading, { as: "h2", sx: { fontSize: 3, mb: 1 }, children: "Identity providers" }), _jsx(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 1, m: 0 }, children: "The directory this organization signs in through. A domain is claimed the moment it is typed here and routes nothing until it is verified." })] }), !readOnly && (_jsx(Button, { variant: "primary", onClick: openCreate, children: "New provider" }))] })), providers.isPending && !providers.data ? (_jsx(Box, { display: "flex", justifyContent: "center", py: 5, children: _jsx(Spinner, {}) })) : rows.length > 0 ? (_jsxs(Table.Container, { children: [_jsx(Table.Title, { as: "h3", id: "identity-providers", children: "Providers" }), _jsx(Table.Subtitle, { as: "p", id: "identity-providers-subtitle", children: "A provider switched off keeps its configuration and its verified domains; only sign-in through it stops." }), _jsx(DataTable, { "aria-labelledby": "identity-providers", "aria-describedby": "identity-providers-subtitle", data: rows, columns: columns })] })) : (_jsxs(Blankslate, { border: true, spacious: true, children: [_jsx(Blankslate.Visual, { children: _jsx(KeyIcon, { size: "medium" }) }), _jsx(Blankslate.Heading, { children: "No directory registered" }), _jsx(Blankslate.Description, { children: _jsx(Text, { sx: { textAlign: 'center' }, children: "People here sign in the ordinary way. Register a provider to let them sign in through the directory this organization already has." }) }), !readOnly && (_jsx(Button, { size: "small", onClick: openCreate, children: "New provider" }))] })), (creating || editing) && (_jsx(Dialog, { title: editing ? 'Edit identity provider' : 'New identity provider', onClose: close, returnFocusRef: returnFocusRef, footerButtons: [
201
196
  { buttonType: 'default', content: 'Cancel', onClick: close },
202
197
  {
203
198
  buttonType: 'primary',
@@ -205,19 +200,9 @@ export const IdentityProviders = ({ errorState, orgUid, readOnly = false, showTi
205
200
  onClick: apply,
206
201
  disabled: create.isPending || update.isPending,
207
202
  },
208
- ], children: _jsxs(Box, { sx: { display: 'grid', gap: 3 }, children: [refusal && (_jsx(Flash, { variant: "danger", children: _jsx(Text, { sx: { fontSize: 1 }, children: refusal }) })), _jsxs(FormControl, { required: true, children: [_jsx(FormControl.Label, { children: "Name" }), _jsx(TextInput, { block: true, value: draft.name, onChange: event => set('name', event.target.value), placeholder: "Acme Okta" }), _jsx(FormControl.Caption, { children: "What an administrator sees in this list." })] }), _jsxs(FormControl, { required: true, children: [_jsx(FormControl.Label, { children: "Issuer" }), _jsx(TextInput, { block: true, value: draft.issuer, onChange: event => set('issuer', event.target.value), placeholder: "https://acme.okta.com" }), _jsx(FormControl.Caption, { children: "Must be https \u2014 discovery, the signing keys and the sign-in redirect all travel over it." })] }), _jsxs(Box, { sx: { display: 'grid', gap: 2, gridTemplateColumns: '1fr 1fr' }, children: [_jsxs(FormControl, { required: true, children: [_jsx(FormControl.Label, { children: "Client ID" }), _jsx(TextInput, { block: true, value: draft.clientId, onChange: event => set('clientId', event.target.value) })] }), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Client secret" }), _jsx(TextInput, { block: true, value: draft.clientSecretRef, onChange: event => set('clientSecretRef', event.target.value), placeholder: "the secret's name, not the secret" }), _jsx(FormControl.Caption, { children: "The name of a secret already in this organization\u2019s store \u2014 never the secret itself." })] })] }), _jsxs(FormControl, { required: true, children: [_jsx(FormControl.Label, { children: "Email domains" }), _jsx(TextInput, { block: true, value: domainsText, onChange: event => setDomainsText(event.target.value), placeholder: "acme.com, acme.io" }), _jsx(FormControl.Caption, { children: "Comma-separated. Claiming a domain is free and routes nothing \u2014 verify it below once it is registered before anybody can sign in through it." })] }), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Group claim" }), _jsx(TextInput, { block: true, value: draft.groupClaim, onChange: event => set('groupClaim', event.target.value), placeholder: "groups" }), _jsx(FormControl.Caption, { children: "Which claim in the token carries the groups the mapping below reads." })] }), _jsxs(FormControl, { children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(ToggleSwitch, { size: "small", checked: draft.allowEmailLinking, "aria-labelledby": "allow-email-linking-label", onClick: () => set('allowEmailLinking', !draft.allowEmailLinking) }), _jsx(FormControl.Label, { id: "allow-email-linking-label", children: "Adopt an existing account on a verified address" })] }), _jsx(FormControl.Caption, { children: "Off by default: a sign-in whose address already has a Datalayer account is refused rather than signed in as that account, and the person is told to connect the two from a session they already hold. Turn this on only if the smoother rollout is worth it \u2014 the address still has to be on a verified domain, and the provider still has to say it verified it itself." })] }), _jsxs(Box, { children: [_jsxs(Box, { sx: {
209
- display: 'flex',
210
- alignItems: 'center',
211
- justifyContent: 'space-between',
212
- mb: 2,
213
- }, children: [_jsx(FormControl.Label, { children: "Group \u2192 role mapping" }), _jsx(Button, { size: "small", onClick: addMapping, children: "Add mapping" })] }), _jsx(Text, { as: "p", sx: { fontSize: 0, color: 'fg.muted', mt: 0, mb: 2 }, children: "Granted the next time somebody in the group signs in, and never taken back by a sign-in that omits it \u2014 a slow directory sync should not read as a demotion. Reaches no further than this organization and its own teams." }), draft.roleMappings.length === 0 && (_jsx(Text, { sx: { fontSize: 0, color: 'fg.subtle' }, children: "No mapping: everybody who signs in through this provider becomes an organization member and nothing more." })), _jsx(Box, { sx: { display: 'grid', gap: 2 }, children: draft.roleMappings.map((mapping, index) => (_jsxs(Box, { sx: {
214
- display: 'grid',
215
- gap: 2,
216
- gridTemplateColumns: isTeamRole(mapping.role)
217
- ? '1fr 1fr 1fr auto'
218
- : '1fr 1fr auto',
219
- alignItems: 'end',
220
- }, children: [_jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Group" }), _jsx(TextInput, { block: true, value: mapping.group, onChange: event => setMapping(index, { group: event.target.value }), placeholder: "admins" })] }), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Grants" }), _jsxs(Select, { value: mapping.role, onChange: event => setMapping(index, {
203
+ ], children: _jsxs(Box, { display: "grid", gap: 3, children: [refusal && (_jsx(Flash, { variant: "danger", children: _jsx(Text, { sx: { fontSize: 1 }, children: refusal }) })), _jsxs(FormControl, { required: true, children: [_jsx(FormControl.Label, { children: "Name" }), _jsx(TextInput, { block: true, value: draft.name, onChange: event => set('name', event.target.value), placeholder: "Acme Okta" }), _jsx(FormControl.Caption, { children: "What an administrator sees in this list." })] }), _jsxs(FormControl, { required: true, children: [_jsx(FormControl.Label, { children: "Issuer" }), _jsx(TextInput, { block: true, value: draft.issuer, onChange: event => set('issuer', event.target.value), placeholder: "https://acme.okta.com" }), _jsx(FormControl.Caption, { children: "Must be https \u2014 discovery, the signing keys and the sign-in redirect all travel over it." })] }), _jsxs(Box, { display: "grid", gap: 2, gridTemplateColumns: "1fr 1fr", children: [_jsxs(FormControl, { required: true, children: [_jsx(FormControl.Label, { children: "Client ID" }), _jsx(TextInput, { block: true, value: draft.clientId, onChange: event => set('clientId', event.target.value) })] }), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Client secret" }), _jsx(TextInput, { block: true, value: draft.clientSecretRef, onChange: event => set('clientSecretRef', event.target.value), placeholder: "the secret's name, not the secret" }), _jsx(FormControl.Caption, { children: "The name of a secret already in this organization\u2019s store \u2014 never the secret itself." })] })] }), _jsxs(FormControl, { required: true, children: [_jsx(FormControl.Label, { children: "Email domains" }), _jsx(TextInput, { block: true, value: domainsText, onChange: event => setDomainsText(event.target.value), placeholder: "acme.com, acme.io" }), _jsx(FormControl.Caption, { children: "Comma-separated. Claiming a domain is free and routes nothing \u2014 verify it below once it is registered before anybody can sign in through it." })] }), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Group claim" }), _jsx(TextInput, { block: true, value: draft.groupClaim, onChange: event => set('groupClaim', event.target.value), placeholder: "groups" }), _jsx(FormControl.Caption, { children: "Which claim in the token carries the groups the mapping below reads." })] }), _jsxs(FormControl, { children: [_jsxs(Box, { display: "flex", alignItems: "center", gap: 2, children: [_jsx(ToggleSwitch, { size: "small", checked: draft.allowEmailLinking, "aria-labelledby": "allow-email-linking-label", onClick: () => set('allowEmailLinking', !draft.allowEmailLinking) }), _jsx(FormControl.Label, { id: "allow-email-linking-label", children: "Adopt an existing account on a verified address" })] }), _jsx(FormControl.Caption, { children: "Off by default: a sign-in whose address already has a Datalayer account is refused rather than signed in as that account, and the person is told to connect the two from a session they already hold. Turn this on only if the smoother rollout is worth it \u2014 the address still has to be on a verified domain, and the provider still has to say it verified it itself." })] }), _jsxs(Box, { children: [_jsxs(Box, { display: "flex", alignItems: "center", justifyContent: "space-between", mb: 2, children: [_jsx(FormControl.Label, { children: "Group \u2192 role mapping" }), _jsx(Button, { size: "small", onClick: addMapping, children: "Add mapping" })] }), _jsx(Text, { as: "p", sx: { fontSize: 0, color: 'fg.muted', mt: 0, mb: 2 }, children: "Granted the next time somebody in the group signs in, and never taken back by a sign-in that omits it \u2014 a slow directory sync should not read as a demotion. Reaches no further than this organization and its own teams." }), draft.roleMappings.length === 0 && (_jsx(Text, { sx: { fontSize: 0, color: 'fg.subtle' }, children: "No mapping: everybody who signs in through this provider becomes an organization member and nothing more." })), _jsx(Box, { display: "grid", gap: 2, children: draft.roleMappings.map((mapping, index) => (_jsxs(Box, { display: "grid", gap: 2, gridTemplateColumns: isTeamRole(mapping.role)
204
+ ? '1fr 1fr 1fr auto'
205
+ : '1fr 1fr auto', alignItems: "end", children: [_jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Group" }), _jsx(TextInput, { block: true, value: mapping.group, onChange: event => setMapping(index, { group: event.target.value }), placeholder: "admins" })] }), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Grants" }), _jsxs(Select, { value: mapping.role, onChange: event => setMapping(index, {
221
206
  role: event.target.value,
222
207
  }), children: [ORGANIZATION_ROLES.map(role => (_jsx(Select.Option, { value: role, children: roleLabel(role) }, role))), TEAM_ROLES.map(role => (_jsx(Select.Option, { value: role, children: roleLabel(role) }, role)))] })] }), isTeamRole(mapping.role) && (_jsxs(FormControl, { required: true, children: [_jsx(FormControl.Label, { children: "Team" }), _jsx(TextInput, { block: true, value: mapping.teamUid, onChange: event => setMapping(index, { teamUid: event.target.value }), placeholder: "team uid" })] })), _jsx(IconButton, { icon: TrashIcon, variant: "danger", size: "small", "aria-label": "Remove this mapping", onClick: () => removeMapping(index) })] }, index))) })] })] }) })), managingDomains && (_jsx(DomainVerificationDialog, { provider: managingDomains, orgUid: orgUid, onClose: () => setManagingDomains(null), fetchVerification: domainVerification, verify: verifyDomain })), removing && (_jsx(Dialog, { title: "Remove this identity provider?", onClose: () => setRemoving(null), returnFocusRef: returnFocusRef, footerButtons: [
223
208
  {
@@ -285,15 +270,6 @@ const DomainVerificationDialog = ({ provider, onClose, fetchVerification, verify
285
270
  };
286
271
  return (_jsx(Dialog, { title: `Verify a domain for ${provider.name}`, onClose: onClose, returnFocusRef: returnFocusRef, footerButtons: [
287
272
  { buttonType: 'default', content: 'Close', onClick: onClose },
288
- ], children: _jsxs(Box, { sx: { display: 'grid', gap: 3 }, children: [_jsx(Text, { as: "p", sx: { fontSize: 1, color: 'fg.muted', m: 0 }, children: "Publish the record below at your DNS provider, then check it here. Until it checks out, this domain routes no sign-in \u2014 a claim is not proof." }), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Domain" }), _jsx(Select, { value: selected, onChange: event => load(event.target.value), children: provider.domains.map(domain => (_jsxs(Select.Option, { value: domain, children: [domain, provider.verifiedDomains.includes(domain) ? ' — verified' : ''] }, domain))) })] }), refusal && (_jsx(Flash, { variant: "danger", children: _jsx(Text, { sx: { fontSize: 1 }, children: refusal }) })), fetchVerification.isPending ? (_jsx(Spinner, { size: "small" })) : record ? (_jsxs(Box, { sx: {
289
- display: 'grid',
290
- gap: 1,
291
- p: 2,
292
- border: '1px solid',
293
- borderColor: 'border.default',
294
- borderRadius: 2,
295
- fontFamily: 'mono',
296
- fontSize: 0,
297
- }, children: [_jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: ["Type: ", record.type] }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: ["Host: ", record.host] }), _jsxs(Text, { sx: { fontSize: 0, wordBreak: 'break-all' }, children: ["Value: ", record.value] })] })) : (_jsx(Button, { size: "small", onClick: () => load(selected), children: "Show what to publish" })), _jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(Label, { variant: verified ? 'success' : 'secondary', children: verified ? 'Verified — routes sign-in' : 'Not yet verified' }), !verified && (_jsx(Button, { variant: "primary", size: "small", onClick: runVerify, disabled: verify.isPending || !selected, children: verify.isPending ? 'Checking…' : 'Check DNS now' }))] })] }) }));
273
+ ], children: _jsxs(Box, { display: "grid", gap: 3, children: [_jsx(Text, { as: "p", sx: { fontSize: 1, color: 'fg.muted', m: 0 }, children: "Publish the record below at your DNS provider, then check it here. Until it checks out, this domain routes no sign-in \u2014 a claim is not proof." }), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Domain" }), _jsx(Select, { value: selected, onChange: event => load(event.target.value), children: provider.domains.map(domain => (_jsxs(Select.Option, { value: domain, children: [domain, provider.verifiedDomains.includes(domain) ? ' — verified' : ''] }, domain))) })] }), refusal && (_jsx(Flash, { variant: "danger", children: _jsx(Text, { sx: { fontSize: 1 }, children: refusal }) })), fetchVerification.isPending ? (_jsx(Spinner, { size: "small" })) : record ? (_jsxs(Box, { display: "grid", gap: 1, p: 2, border: "1px solid", borderColor: "border.default", borderRadius: 2, fontFamily: "mono", fontSize: 0, children: [_jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: ["Type: ", record.type] }), _jsxs(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: ["Host: ", record.host] }), _jsxs(Text, { sx: { fontSize: 0, wordBreak: 'break-all' }, children: ["Value: ", record.value] })] })) : (_jsx(Button, { size: "small", onClick: () => load(selected), children: "Show what to publish" })), _jsxs(Box, { display: "flex", alignItems: "center", gap: 2, children: [_jsx(Label, { variant: verified ? 'success' : 'secondary', children: verified ? 'Verified — routes sign-in' : 'Not yet verified' }), !verified && (_jsx(Button, { variant: "primary", size: "small", onClick: runVerify, disabled: verify.isPending || !selected, children: verify.isPending ? 'Checking…' : 'Check DNS now' }))] })] }) }));
298
274
  };
299
275
  export default IdentityProviders;
@@ -54,14 +54,7 @@ const boundTo = (client) => {
54
54
  return '';
55
55
  };
56
56
  const countLook = (tone) => tone === 'danger' ? 'danger.fg' : 'fg.default';
57
- const Count = ({ label, value, tone = 'neutral', note, to, onOpen, }) => (_jsxs(Box, { sx: {
58
- p: 3,
59
- border: '1px solid',
60
- borderColor: 'border.default',
61
- borderRadius: 2,
62
- bg: 'canvas.default',
63
- minWidth: 0,
64
- }, children: [_jsx(Text, { sx: {
57
+ const Count = ({ label, value, tone = 'neutral', note, to, onOpen, }) => (_jsxs(Box, { p: 3, border: "1px solid", borderColor: "border.default", borderRadius: 2, bg: "canvas.default", minWidth: 0, children: [_jsx(Text, { sx: {
65
58
  display: 'block',
66
59
  fontSize: 4,
67
60
  fontWeight: 'bold',
@@ -230,7 +223,7 @@ export const McpDashboard = ({ errorState, routes, org, showTitle = true, sectio
230
223
  {
231
224
  header: 'Last tool',
232
225
  id: 'last-tool',
233
- renderCell: row => row.lastCall ? (_jsxs(Box, { sx: { display: 'grid', gap: '2px', minWidth: 0 }, children: [_jsx(Text, { sx: { fontSize: 0 }, children: row.lastCall.tool || row.lastCall.method }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: timeAgo(row.lastCall.at) })] })) : (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Nothing yet" })),
226
+ renderCell: row => row.lastCall ? (_jsxs(Box, { display: "grid", gap: "2px", minWidth: 0, children: [_jsx(Text, { sx: { fontSize: 0 }, children: row.lastCall.tool || row.lastCall.method }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: timeAgo(row.lastCall.at) })] })) : (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "Nothing yet" })),
234
227
  },
235
228
  {
236
229
  header: 'Status',
@@ -298,7 +291,7 @@ export const McpDashboard = ({ errorState, routes, org, showTitle = true, sectio
298
291
  header: 'Capabilities',
299
292
  id: 'capabilities',
300
293
  width: 'growCollapse',
301
- renderCell: row => (_jsxs(Box, { sx: { display: 'flex', gap: 1, flexWrap: 'wrap' }, children: [(row.capabilities ?? []).map(capability => (_jsx(Label, { size: "small", variant: "secondary", children: capability }, capability))), (row.capabilities ?? []).length === 0 && (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "\u2014" }))] })),
294
+ renderCell: row => (_jsxs(Box, { display: "flex", gap: 1, flexWrap: "wrap", children: [(row.capabilities ?? []).map(capability => (_jsx(Label, { size: "small", variant: "secondary", children: capability }, capability))), (row.capabilities ?? []).length === 0 && (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "\u2014" }))] })),
302
295
  },
303
296
  {
304
297
  header: 'Last used',
@@ -320,7 +313,7 @@ export const McpDashboard = ({ errorState, routes, org, showTitle = true, sectio
320
313
  id: 'actions',
321
314
  width: '190px',
322
315
  align: 'end',
323
- renderCell: row => (_jsxs(Box, { sx: { display: 'flex', gap: 2, justifyContent: 'flex-end' }, children: [sandboxSharingUrl(runtimesUrl, row.runtimeName) && (_jsx(Button, { size: "small", disabled: row.state === 'closed', onClick: () => setSharing(row), children: "Share" })), _jsx(Button, { size: "small", variant: "danger", disabled: row.state === 'closed', onClick: () => setTerminating(row), children: "Terminate" })] })),
316
+ renderCell: row => (_jsxs(Box, { display: "flex", gap: 2, justifyContent: "flex-end", children: [sandboxSharingUrl(runtimesUrl, row.runtimeName) && (_jsx(Button, { size: "small", disabled: row.state === 'closed', onClick: () => setSharing(row), children: "Share" })), _jsx(Button, { size: "small", variant: "danger", disabled: row.state === 'closed', onClick: () => setTerminating(row), children: "Terminate" })] })),
324
317
  },
325
318
  ];
326
319
  const callColumns = [
@@ -328,7 +321,7 @@ export const McpDashboard = ({ errorState, routes, org, showTitle = true, sectio
328
321
  header: 'Tool',
329
322
  field: 'tool',
330
323
  rowHeader: true,
331
- renderCell: row => (_jsxs(Box, { sx: { display: 'grid', gap: '2px', minWidth: 0 }, children: [_jsx(Text, { sx: { fontSize: 1 }, children: row.tool || row.method }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: timeAgo(row.at) })] })),
324
+ renderCell: row => (_jsxs(Box, { display: "grid", gap: "2px", minWidth: 0, children: [_jsx(Text, { sx: { fontSize: 1 }, children: row.tool || row.method }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: timeAgo(row.at) })] })),
332
325
  },
333
326
  {
334
327
  header: 'Client',
@@ -369,24 +362,20 @@ export const McpDashboard = ({ errorState, routes, org, showTitle = true, sectio
369
362
  align: 'end',
370
363
  renderCell: row => {
371
364
  const trace = traceFor(row);
372
- return (_jsxs(Box, { sx: { display: 'flex', gap: 2, justifyContent: 'flex-end' }, children: [_jsx(Link, { as: "button", sx: { fontSize: 0, cursor: 'pointer' }, onClick: () => navigate(auditFor(row)), children: "Audit" }), trace && (_jsx(Link, { as: "button", sx: { fontSize: 0, cursor: 'pointer' }, onClick: () => navigate(trace), children: "Trace" }))] }));
365
+ return (_jsxs(Box, { display: "flex", gap: 2, justifyContent: "flex-end", children: [_jsx(Link, { as: "button", sx: { fontSize: 0, cursor: 'pointer' }, onClick: () => navigate(auditFor(row)), children: "Audit" }), trace && (_jsx(Link, { as: "button", sx: { fontSize: 0, cursor: 'pointer' }, onClick: () => navigate(trace), children: "Trace" }))] }));
373
366
  },
374
367
  },
375
368
  ];
376
369
  if (activity.isError) {
377
- return (_jsx(Box, { sx: { display: 'grid', gap: 3 }, children: _jsx(McpErrorBlankslate, { state: errorState(activity.error, 'MCP activity'), onRetry: () => activity.refetch() }) }));
370
+ return (_jsx(Box, { display: "grid", gap: 3, children: _jsx(McpErrorBlankslate, { state: errorState(activity.error, 'MCP activity'), onRetry: () => activity.refetch() }) }));
378
371
  }
379
372
  const loading = activity.isPending && !data;
380
- return (_jsxs(Box, { sx: { display: 'grid', gap: 4, minWidth: 0 }, children: [showTitle && (_jsxs(Box, { children: [_jsx(Heading, { as: "h2", sx: { fontSize: 3, mb: 1 }, children: "MCP" }), _jsx(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 1, m: 0 }, children: "What the agents connected to your workspace are doing right now." })] })), draws('overview') &&
381
- (loading ? (_jsx(Box, { sx: { display: 'flex', justifyContent: 'center', py: 5 }, children: _jsx(Spinner, {}) })) : (_jsxs(Box, { sx: {
382
- display: 'grid',
383
- gap: 3,
384
- gridTemplateColumns: [
385
- 'repeat(2, 1fr)',
386
- 'repeat(3, 1fr)',
387
- 'repeat(6, 1fr)',
388
- ],
389
- }, children: [_jsx(Count, { label: "Clients connected", value: clients.length, to: routes.agents, onOpen: navigate }), _jsx(Count, { label: "Sandboxes bound", to: routes.sandboxes, onOpen: navigate, value: sandboxes.filter(binding => (binding.state ?? 'active') === 'active').length }), _jsx(Count, { label: "Tasks running", value: data?.tasks.length ?? 0, to: routes.runs, onOpen: navigate }), _jsx(Count, { label: "Calls today", value: data?.today.calls ?? 0, to: routes.calls, onOpen: navigate }), _jsx(Count, { label: "Refusals today", value: data?.today.refusals ?? 0, to: routes.audit, onOpen: navigate, tone: (data?.today.refusals ?? 0) > 0 ? 'danger' : 'neutral' }), _jsx(Count, { label: "Credits by agents", value: data?.today.credits ?? 0, note: "today",
373
+ return (_jsxs(Box, { display: "grid", gap: 4, minWidth: 0, children: [showTitle && (_jsxs(Box, { children: [_jsx(Heading, { as: "h2", sx: { fontSize: 3, mb: 1 }, children: "MCP" }), _jsx(Text, { as: "p", sx: { color: 'fg.muted', fontSize: 1, m: 0 }, children: "What the agents connected to your workspace are doing right now." })] })), draws('overview') &&
374
+ (loading ? (_jsx(Box, { display: "flex", justifyContent: "center", py: 5, children: _jsx(Spinner, {}) })) : (_jsxs(Box, { display: "grid", gap: 3, gridTemplateColumns: [
375
+ 'repeat(2, 1fr)',
376
+ 'repeat(3, 1fr)',
377
+ 'repeat(6, 1fr)',
378
+ ], children: [_jsx(Count, { label: "Clients connected", value: clients.length, to: routes.agents, onOpen: navigate }), _jsx(Count, { label: "Sandboxes bound", to: routes.sandboxes, onOpen: navigate, value: sandboxes.filter(binding => (binding.state ?? 'active') === 'active').length }), _jsx(Count, { label: "Tasks running", value: data?.tasks.length ?? 0, to: routes.runs, onOpen: navigate }), _jsx(Count, { label: "Calls today", value: data?.today.calls ?? 0, to: routes.calls, onOpen: navigate }), _jsx(Count, { label: "Refusals today", value: data?.today.refusals ?? 0, to: routes.audit, onOpen: navigate, tone: (data?.today.refusals ?? 0) > 0 ? 'danger' : 'neutral' }), _jsx(Count, { label: "Credits by agents", value: data?.today.credits ?? 0, note: "today",
390
379
  // Credits are summed from the day's calls, which the Calls tab
391
380
  // lists.
392
381
  to: routes.calls, onOpen: navigate })] }))), draws('agents') &&
@@ -398,12 +387,7 @@ export const McpDashboard = ({ errorState, routes, org, showTitle = true, sectio
398
387
  !loading &&
399
388
  (sandboxes.length > 0 ? (_jsxs(Table.Container, { children: [_jsx(Table.Title, { as: "h3", id: "mcp-sandboxes", children: "Sandboxes bound" }), _jsx(Table.Subtitle, { as: "p", id: "mcp-sandboxes-subtitle", children: "The sessions your agents execute in. Terminating one ends its open work." }), _jsx(DataTable, { "aria-labelledby": "mcp-sandboxes", "aria-describedby": "mcp-sandboxes-subtitle", data: sandboxes, columns: sandboxColumns })] })) : (_jsx(PanelEmpty, { icon: StackIcon, heading: "No sandbox bound", description: "An agent that launches a sandbox keeps it for the session; it appears here with its provider, its capabilities and what it is doing." }))), draws('calls') &&
400
389
  !loading &&
401
- (calls.length > 0 ? (_jsxs(Table.Container, { children: [_jsx(Table.Title, { as: "h3", id: "mcp-calls", children: "Recent calls" }), _jsx(Table.Subtitle, { as: "p", id: "mcp-calls-subtitle", children: "The last calls as they landed. Every one of them has an audit row that outlives this page." }), _jsx(Table.Actions, { children: _jsxs(Box, { sx: { display: 'flex', gap: 2, alignItems: 'center' }, children: [_jsxs(Select, { size: "small", "aria-label": "Filter by client", value: callClient, onChange: event => setCallClient(event.currentTarget.value), children: [_jsx(Select.Option, { value: "", children: "Every client" }), clients.map(client => (_jsx(Select.Option, { value: client.clientId, children: client.clientName || client.clientId }, client.clientId)))] }), _jsxs(Select, { size: "small", "aria-label": "Filter by tool", value: callTool, onChange: event => setCallTool(event.currentTarget.value), children: [_jsx(Select.Option, { value: "", children: "Every tool" }), callTools.map(tool => (_jsx(Select.Option, { value: tool, children: tool }, tool)))] }), _jsxs(Select, { size: "small", "aria-label": "Filter by outcome", value: callOutcome, onChange: event => setCallOutcome(event.currentTarget.value), children: [_jsx(Select.Option, { value: "", children: "Every outcome" }), _jsx(Select.Option, { value: "ok", children: "Succeeded" }), _jsx(Select.Option, { value: "error", children: "Failed" }), _jsx(Select.Option, { value: "refused", children: "Refused" })] })] }) }), filteredCalls.length > 0 ? (_jsx(DataTable, { "aria-labelledby": "mcp-calls", "aria-describedby": "mcp-calls-subtitle", data: filteredCalls, columns: callColumns })) : (_jsx(Box, { sx: {
402
- p: 4,
403
- textAlign: 'center',
404
- color: 'fg.muted',
405
- fontSize: 1,
406
- }, children: "No call matches these filters." }))] })) : (_jsx(PanelEmpty, { icon: ChecklistIcon, heading: "No call yet", description: "Ask your agent to list your notebooks. The call, its decision and its outcome land here and in the audit log.", action: {
390
+ (calls.length > 0 ? (_jsxs(Table.Container, { children: [_jsx(Table.Title, { as: "h3", id: "mcp-calls", children: "Recent calls" }), _jsx(Table.Subtitle, { as: "p", id: "mcp-calls-subtitle", children: "The last calls as they landed. Every one of them has an audit row that outlives this page." }), _jsx(Table.Actions, { children: _jsxs(Box, { display: "flex", gap: 2, alignItems: "center", children: [_jsxs(Select, { size: "small", "aria-label": "Filter by client", value: callClient, onChange: event => setCallClient(event.currentTarget.value), children: [_jsx(Select.Option, { value: "", children: "Every client" }), clients.map(client => (_jsx(Select.Option, { value: client.clientId, children: client.clientName || client.clientId }, client.clientId)))] }), _jsxs(Select, { size: "small", "aria-label": "Filter by tool", value: callTool, onChange: event => setCallTool(event.currentTarget.value), children: [_jsx(Select.Option, { value: "", children: "Every tool" }), callTools.map(tool => (_jsx(Select.Option, { value: tool, children: tool }, tool)))] }), _jsxs(Select, { size: "small", "aria-label": "Filter by outcome", value: callOutcome, onChange: event => setCallOutcome(event.currentTarget.value), children: [_jsx(Select.Option, { value: "", children: "Every outcome" }), _jsx(Select.Option, { value: "ok", children: "Succeeded" }), _jsx(Select.Option, { value: "error", children: "Failed" }), _jsx(Select.Option, { value: "refused", children: "Refused" })] })] }) }), filteredCalls.length > 0 ? (_jsx(DataTable, { "aria-labelledby": "mcp-calls", "aria-describedby": "mcp-calls-subtitle", data: filteredCalls, columns: callColumns })) : (_jsx(Box, { p: 4, textAlign: "center", color: "fg.muted", fontSize: 1, children: "No call matches these filters." }))] })) : (_jsx(PanelEmpty, { icon: ChecklistIcon, heading: "No call yet", description: "Ask your agent to list your notebooks. The call, its decision and its outcome land here and in the audit log.", action: {
407
391
  label: 'Open the audit log',
408
392
  onClick: () => navigate(routes.audit),
409
393
  } }))), disconnecting && (_jsx(Dialog, { title: "Disconnect this client?", onClose: () => setDisconnecting(null), returnFocusRef: returnFocusRef, footerButtons: [