@datalayer/core 1.1.66 → 1.2.12

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 (237) hide show
  1. package/README.md +43 -20
  2. package/lib/api/constants.d.ts +1 -1
  3. package/lib/api/constants.js +1 -1
  4. package/lib/api/contents/attachments.js +3 -7
  5. package/lib/api/contents/datasets.d.ts +48 -0
  6. package/lib/api/contents/datasets.js +44 -7
  7. package/lib/api/contents/runtimeMounts.js +1 -1
  8. package/lib/api/contents/sandboxUid.d.ts +13 -45
  9. package/lib/api/contents/sandboxUid.js +14 -65
  10. package/lib/api/evals/client.d.ts +402 -0
  11. package/lib/api/evals/client.js +359 -0
  12. package/lib/api/evals/index.d.ts +10 -0
  13. package/lib/api/evals/index.js +18 -0
  14. package/lib/api/evals/request.d.ts +43 -0
  15. package/lib/api/evals/request.js +67 -0
  16. package/lib/api/evals/status.d.ts +27 -0
  17. package/lib/api/evals/status.js +122 -0
  18. package/lib/api/evals/types.d.ts +1335 -0
  19. package/lib/api/evals/types.js +5 -0
  20. package/lib/api/iam/authentication.js +6 -4
  21. package/lib/api/iam/connectedAgents.d.ts +29 -0
  22. package/lib/api/iam/connectedAgents.js +35 -0
  23. package/lib/api/iam/healthz.js +2 -2
  24. package/lib/api/iam/identityProviders.d.ts +76 -0
  25. package/lib/api/iam/identityProviders.js +187 -0
  26. package/lib/api/iam/index.d.ts +1 -0
  27. package/lib/api/iam/index.js +1 -0
  28. package/lib/api/iam/mcpPolicy.d.ts +102 -1
  29. package/lib/api/iam/mcpPolicy.js +38 -2
  30. package/lib/api/iam/oauth2.js +18 -12
  31. package/lib/api/iam/profile.d.ts +17 -1
  32. package/lib/api/iam/profile.js +27 -0
  33. package/lib/api/iam/scimTokens.d.ts +79 -0
  34. package/lib/api/iam/scimTokens.js +141 -0
  35. package/lib/api/iam/secrets.js +10 -23
  36. package/lib/api/iam/trials.d.ts +38 -0
  37. package/lib/api/iam/trials.js +66 -0
  38. package/lib/api/index.d.ts +4 -0
  39. package/lib/api/index.js +4 -0
  40. package/lib/api/mcp/observability.d.ts +34 -11
  41. package/lib/api/mcp/observability.js +97 -59
  42. package/lib/api/orchestration/client.d.ts +53 -0
  43. package/lib/api/orchestration/client.js +105 -0
  44. package/lib/api/orchestration/events.d.ts +88 -0
  45. package/lib/api/orchestration/events.js +245 -0
  46. package/lib/api/orchestration/generated.d.ts +693 -0
  47. package/lib/api/orchestration/generated.js +687 -0
  48. package/lib/api/orchestration/index.d.ts +30 -0
  49. package/lib/api/orchestration/index.js +34 -0
  50. package/lib/api/orchestration/lifecycle.d.ts +39 -0
  51. package/lib/api/orchestration/lifecycle.js +57 -0
  52. package/lib/api/orchestration/measures.d.ts +55 -0
  53. package/lib/api/orchestration/measures.js +99 -0
  54. package/lib/api/otel/dashboards.d.ts +56 -0
  55. package/lib/api/otel/dashboards.js +50 -0
  56. package/lib/api/otel/index.d.ts +1 -0
  57. package/lib/api/otel/index.js +1 -0
  58. package/lib/api/otel/metrics.d.ts +16 -0
  59. package/lib/api/otel/metrics.js +15 -0
  60. package/lib/api/scheduler/client.d.ts +32 -0
  61. package/lib/api/scheduler/client.js +42 -0
  62. package/lib/api/scheduler/index.d.ts +8 -0
  63. package/lib/api/scheduler/index.js +16 -0
  64. package/lib/api/scheduler/request.d.ts +28 -0
  65. package/lib/api/scheduler/request.js +50 -0
  66. package/lib/api/scheduler/types.d.ts +88 -0
  67. package/lib/api/scheduler/types.js +5 -0
  68. package/lib/api/spacer/comments.d.ts +97 -0
  69. package/lib/api/spacer/comments.js +45 -0
  70. package/lib/api/spacer/index.d.ts +9 -0
  71. package/lib/api/spacer/index.js +17 -0
  72. package/lib/api/spacer/notebooks.d.ts +33 -0
  73. package/lib/api/spacer/notebooks.js +39 -0
  74. package/lib/api/spacer/request.d.ts +25 -0
  75. package/lib/api/spacer/request.js +46 -0
  76. package/lib/api/spacer/spaces.d.ts +68 -0
  77. package/lib/api/spacer/spaces.js +45 -0
  78. package/lib/api/utils/validation.d.ts +4 -4
  79. package/lib/api/utils/validation.js +10 -7
  80. package/lib/client/auth/strategies.js +1 -1
  81. package/lib/client/constants.d.ts +1 -0
  82. package/lib/client/constants.js +1 -0
  83. package/lib/client/mixins/IAMMixin.js +2 -2
  84. package/lib/components/animation/AnimatedText.d.ts +1 -44
  85. package/lib/components/animation/AnimatedText.js +6 -122
  86. package/lib/components/anonymous/AnonymousKeyExpired.d.ts +56 -0
  87. package/lib/components/anonymous/AnonymousKeyExpired.js +96 -0
  88. package/lib/components/anonymous/AnonymousKeyTimer.d.ts +63 -0
  89. package/lib/components/anonymous/AnonymousKeyTimer.js +140 -0
  90. package/lib/components/anonymous/index.d.ts +7 -0
  91. package/lib/components/anonymous/index.js +15 -0
  92. package/lib/components/avatars/UserAvatar.d.ts +7 -1
  93. package/lib/components/avatars/UserAvatar.js +15 -1
  94. package/lib/components/billing/BillingEntitySelect.d.ts +6 -0
  95. package/lib/components/billing/BillingEntitySelect.js +49 -10
  96. package/lib/components/billing/eligibility.d.ts +22 -0
  97. package/lib/components/billing/eligibility.js +27 -0
  98. package/lib/components/billing/index.d.ts +1 -0
  99. package/lib/components/billing/index.js +1 -0
  100. package/lib/components/checkout/StripeCheckout.d.ts +1 -1
  101. package/lib/components/checkout/StripeCheckout.js +1 -1
  102. package/lib/components/collaboration/LiveEditorCollaborators.d.ts +5 -0
  103. package/lib/components/collaboration/LiveEditorCollaborators.js +3 -1
  104. package/lib/components/display/DatalayerBox.d.ts +2 -3
  105. package/lib/components/display/DatalayerBox.js +1 -1
  106. package/lib/components/display/NavLink.js +3 -2
  107. package/lib/components/display/VisuallyHidden.d.ts +1 -2
  108. package/lib/components/labels/StatusLabels.d.ts +2 -10
  109. package/lib/components/labels/StatusLabels.js +2 -26
  110. package/lib/components/principal/PrincipalAppearance.d.ts +21 -42
  111. package/lib/components/principal/PrincipalAppearance.js +232 -174
  112. package/lib/components/principal/PrincipalAvatar.d.ts +8 -1
  113. package/lib/components/principal/PrincipalAvatar.js +2 -2
  114. package/lib/components/principal/PrincipalDetailsOverlay.d.ts +8 -1
  115. package/lib/components/principal/PrincipalDetailsOverlay.js +2 -2
  116. package/lib/components/screencapture/Screencapture.js +46 -3
  117. package/lib/components/sharing/ShareAccessComponent.d.ts +45 -4
  118. package/lib/components/sharing/ShareAccessComponent.js +110 -78
  119. package/lib/components/sharing/SharingEditor.d.ts +5 -1
  120. package/lib/components/sharing/SharingEditor.js +9 -4
  121. package/lib/components/sharing/index.d.ts +1 -0
  122. package/lib/components/sharing/index.js +1 -0
  123. package/lib/components/sharing/sandboxSharing.d.ts +26 -0
  124. package/lib/components/sharing/sandboxSharing.js +47 -0
  125. package/lib/components/spaces/SpaceDetailsOverlay.d.ts +39 -0
  126. package/lib/components/spaces/SpaceDetailsOverlay.js +80 -0
  127. package/lib/components/spaces/SpaceDisplay.d.ts +38 -0
  128. package/lib/components/spaces/SpaceDisplay.js +92 -0
  129. package/lib/components/spaces/index.d.ts +4 -0
  130. package/lib/components/spaces/index.js +7 -0
  131. package/lib/components/spaces/spaceDisplayModel.d.ts +93 -0
  132. package/lib/components/spaces/spaceDisplayModel.js +170 -0
  133. package/lib/config/Configuration.d.ts +4 -4
  134. package/lib/config/Configuration.js +7 -7
  135. package/lib/config/index.d.ts +1 -0
  136. package/lib/config/index.js +1 -0
  137. package/lib/config/planes.d.ts +45 -0
  138. package/lib/config/planes.js +53 -0
  139. package/lib/hooks/cacheConverters.d.ts +0 -7
  140. package/lib/hooks/cacheConverters.js +0 -25
  141. package/lib/hooks/index.d.ts +1 -0
  142. package/lib/hooks/index.js +1 -0
  143. package/lib/hooks/useBackdrop.d.ts +4 -5
  144. package/lib/hooks/useBillingEntityStore.js +3 -0
  145. package/lib/hooks/useCache.d.ts +197 -44
  146. package/lib/hooks/useCache.js +1586 -494
  147. package/lib/hooks/useContents.d.ts +22 -1
  148. package/lib/hooks/useContents.js +90 -21
  149. package/lib/hooks/useMcp.d.ts +87 -1
  150. package/lib/hooks/useMcp.js +248 -13
  151. package/lib/hooks/useNavigate.d.ts +41 -3
  152. package/lib/hooks/useNavigate.js +116 -52
  153. package/lib/hooks/usePrincipalCacheStore.js +3 -0
  154. package/lib/hooks/usePrincipalStore.js +3 -0
  155. package/lib/hooks/useSpaceCacheStore.d.ts +50 -0
  156. package/lib/hooks/useSpaceCacheStore.js +85 -0
  157. package/lib/hooks/useWindowSize.js +1 -1
  158. package/lib/models/CreditsDTO.d.ts +6 -5
  159. package/lib/models/CreditsDTO.js +7 -5
  160. package/lib/models/IAMProvidersSpecs.d.ts +10 -5
  161. package/lib/models/IAMProvidersSpecs.js +0 -23
  162. package/lib/models/McpBinding.d.ts +6 -0
  163. package/lib/models/Organization.d.ts +69 -0
  164. package/lib/models/Organization.js +96 -0
  165. package/lib/models/Secret.d.ts +1 -2
  166. package/lib/models/Secret.js +2 -18
  167. package/lib/models/StartedBy.d.ts +34 -0
  168. package/lib/models/StartedBy.js +36 -0
  169. package/lib/models/Team.d.ts +2 -0
  170. package/lib/models/Team.js +2 -0
  171. package/lib/models/User.d.ts +4 -0
  172. package/lib/models/User.js +3 -0
  173. package/lib/models/UserSettings.d.ts +13 -0
  174. package/lib/models/UserSettings.js +9 -0
  175. package/lib/models/contents/__fixtures__/v1-contracts.json +158 -30
  176. package/lib/navigation/adapters/react-router.d.ts +1 -1
  177. package/lib/navigation/adapters/react-router.js +3 -0
  178. package/lib/navigation/components.js +2 -3
  179. package/lib/routes/publicPaths.js +4 -0
  180. package/lib/state/index.d.ts +1 -0
  181. package/lib/state/index.js +1 -0
  182. package/lib/state/sessionEnd.d.ts +55 -0
  183. package/lib/state/sessionEnd.js +162 -0
  184. package/lib/state/substates/CoreState.js +3 -16
  185. package/lib/state/substates/IAMState.d.ts +3 -3
  186. package/lib/state/substates/IAMState.js +7 -0
  187. package/lib/state/substates/LayoutState.js +12 -0
  188. package/lib/state/substates/NavigationState.d.ts +82 -0
  189. package/lib/state/substates/NavigationState.js +255 -0
  190. package/lib/state/substates/ProfileState.d.ts +1 -0
  191. package/lib/state/substates/ProfileState.js +1 -0
  192. package/lib/state/substates/index.d.ts +1 -0
  193. package/lib/state/substates/index.js +1 -0
  194. package/lib/utils/Lazy.d.ts +20 -0
  195. package/lib/utils/Lazy.js +32 -6
  196. package/lib/utils/Screencapture.d.ts +15 -0
  197. package/lib/utils/Screencapture.js +26 -20
  198. package/lib/utils/WithSuspense.d.ts +11 -1
  199. package/lib/utils/WithSuspense.js +11 -1
  200. package/lib/views/mcp/AdmittedClients.d.ts +44 -0
  201. package/lib/views/mcp/AdmittedClients.js +59 -0
  202. package/lib/views/mcp/ApprovalQueue.d.ts +66 -0
  203. package/lib/views/mcp/ApprovalQueue.js +95 -0
  204. package/lib/views/mcp/ConnectedAgents.js +38 -3
  205. package/lib/views/mcp/EnterpriseConsole.d.ts +1 -1
  206. package/lib/views/mcp/EnterpriseConsole.js +23 -1
  207. package/lib/views/mcp/IdentityProviders.d.ts +33 -0
  208. package/lib/views/mcp/IdentityProviders.js +299 -0
  209. package/lib/views/mcp/McpDashboard.js +90 -7
  210. package/lib/views/mcp/McpHome.js +1 -1
  211. package/lib/views/mcp/McpObservability.d.ts +30 -1
  212. package/lib/views/mcp/McpObservability.js +105 -19
  213. package/lib/views/mcp/NotebookRuns.d.ts +39 -0
  214. package/lib/views/mcp/NotebookRuns.js +44 -0
  215. package/lib/views/mcp/OrganizationPolicy.js +2 -1
  216. package/lib/views/mcp/PersonalPolicy.js +2 -1
  217. package/lib/views/mcp/PolicyForm.d.ts +17 -1
  218. package/lib/views/mcp/PolicyForm.js +25 -3
  219. package/lib/views/mcp/PolicyHistory.d.ts +13 -0
  220. package/lib/views/mcp/PolicyHistory.js +14 -1
  221. package/lib/views/mcp/RunDetail.d.ts +87 -0
  222. package/lib/views/mcp/RunDetail.js +186 -0
  223. package/lib/views/mcp/ScimProvisioning.d.ts +54 -0
  224. package/lib/views/mcp/ScimProvisioning.js +173 -0
  225. package/lib/views/mcp/TeamPolicies.js +66 -5
  226. package/lib/views/mcp/ToolAccess.d.ts +60 -0
  227. package/lib/views/mcp/ToolAccess.js +101 -0
  228. package/lib/views/mcp/TraceTimeline.d.ts +81 -0
  229. package/lib/views/mcp/TraceTimeline.js +132 -0
  230. package/lib/views/mcp/index.d.ts +5 -0
  231. package/lib/views/mcp/index.js +5 -0
  232. package/lib/views/otel/simpleAuthStore.js +3 -0
  233. package/lib/views/secrets/SecretEdit.js +3 -2
  234. package/lib/views/secrets/SecretNew.js +5 -1
  235. package/package.json +271 -264
  236. package/scripts/generate-mcp-types.py +16 -10
  237. package/scripts/generate-orchestration-types.py +920 -0
@@ -16,7 +16,7 @@ export function hasRealAvatar(url) {
16
16
  }
17
17
  return true;
18
18
  }
19
- export const UserAvatar = ({ avatarUrl, avatarIcon, size = 100, square = true, iconSize, fallbackBackground, fallbackForeground, ring = false, className, }) => {
19
+ export const UserAvatar = ({ avatarUrl, avatarIcon, avatarEmoji, size = 100, square = true, iconSize, fallbackBackground, fallbackForeground, ring = false, className, }) => {
20
20
  const palette = useColorPalette();
21
21
  /*
22
22
  * The ring, as a shadow rather than a border.
@@ -28,6 +28,20 @@ export const UserAvatar = ({ avatarUrl, avatarIcon, size = 100, square = true, i
28
28
  const ringSx = ring
29
29
  ? { boxShadow: '0 0 0 1px var(--borderColor-default, currentColor)' }
30
30
  : undefined;
31
+ if (avatarEmoji) {
32
+ return (_jsx(Box, { role: "img", "aria-label": avatarEmoji, className: className, sx: {
33
+ width: size,
34
+ height: size,
35
+ borderRadius: square ? 2 : '50%',
36
+ display: 'flex',
37
+ alignItems: 'center',
38
+ justifyContent: 'center',
39
+ bg: fallbackBackground || 'canvas.default',
40
+ fontSize: Math.round(size * 0.5),
41
+ lineHeight: 1,
42
+ ...ringSx,
43
+ }, children: avatarEmoji }));
44
+ }
31
45
  const SelectedIcon = getPrincipalAvatarIcon(avatarIcon);
32
46
  if (SelectedIcon) {
33
47
  return (_jsx(Box, { className: className, sx: {
@@ -17,6 +17,12 @@ export type BillingEntity = {
17
17
  planName: string;
18
18
  isEligible: boolean;
19
19
  isPaidPlan: boolean;
20
+ /**
21
+ * Billed through the AWS Marketplace: an organization created from an AWS
22
+ * subscription, or one of its teams. Work started under it is metered and
23
+ * reaches the AWS bill; work started under any other entry never does.
24
+ */
25
+ isAwsBilled: boolean;
20
26
  sourceOrganizationUid?: string;
21
27
  sourceOrganizationHandle?: string;
22
28
  teamHandle?: string;
@@ -6,6 +6,7 @@ import { Box } from '@datalayer/primer-addons';
6
6
  import { useCache } from '../../hooks/useCache.js';
7
7
  import { useSelectedPrincipal } from '../../hooks/useSelectedPrincipal.js';
8
8
  import { useIAMStore } from '../../state/index.js';
9
+ import { isBillingEntityEligible } from './eligibility.js';
9
10
  const PLAN_FREE_TERMS = ['free', 'starter'];
10
11
  const PLAN_PRO_TERMS = ['pro', 'paid', 'team', 'enterprise', 'business'];
11
12
  const BILLING_ENTITY_COOKIE = 'datalayer-billing-entity-uid';
@@ -24,6 +25,19 @@ function writeBillingEntityCookie(value) {
24
25
  `${BILLING_ENTITY_COOKIE}=${encodeURIComponent(value)};` +
25
26
  ` path=/; max-age=${BILLING_ENTITY_COOKIE_MAX_AGE}; SameSite=Lax`;
26
27
  }
28
+ const AWS_ORIGIN_PREFIX = 'urn:dla:iam:ext::aws:';
29
+ const AWS_BILLING_PROVIDER = 'aws-marketplace';
30
+ /** Whether an origin URN names an AWS Marketplace subscription. */
31
+ const isAwsOriginUrn = (origin) => String(origin ?? '')
32
+ .trim()
33
+ .toLowerCase()
34
+ .startsWith(AWS_ORIGIN_PREFIX);
35
+ /** Whether IAM names the AWS Marketplace as who bills an account. */
36
+ const isAwsBillingProvider = (provider) => String(provider ?? '')
37
+ .trim()
38
+ .toLowerCase() === AWS_BILLING_PROVIDER;
39
+ /** The label beside an entry billed through the AWS Marketplace. */
40
+ const AwsBilledLabel = () => (_jsx(Label, { size: "small", variant: "accent", title: "Billed through AWS Marketplace: work started here is reported to AWS", children: "AWS" }));
27
41
  const planContains = (value, terms) => terms.some(term => value.includes(term));
28
42
  export function resolveBillingPlanTier(value) {
29
43
  const normalized = String(value ?? '').toLowerCase();
@@ -57,6 +71,8 @@ export function BillingEntitySelect({ value, onChange, onSelectedAccountChange,
57
71
  String(entry.account_handle || '').trim() ||
58
72
  String(entry.account_uid || '').trim(),
59
73
  planName: String(entry?.subscription?.plan_name || entry?.plan?.plan_name || '').trim(),
74
+ isAwsBilled: isAwsBillingProvider(entry?.billing_provider) ||
75
+ isAwsBillingProvider(entry?.plan?.billing_provider),
60
76
  })), [eligibleAccountsRaw]);
61
77
  const personalAccountUid = String(user?.id || '');
62
78
  const allContextAccounts = useMemo(() => {
@@ -68,6 +84,7 @@ export function BillingEntitySelect({ value, onChange, onSelectedAccountChange,
68
84
  accountHandle: String(user?.handle || '').trim(),
69
85
  accountName: String(user?.handle || '').trim() || personalAccountUid,
70
86
  planName: '',
87
+ isAwsBilled: false,
71
88
  });
72
89
  }
73
90
  for (const organization of (userOrganizationsQuery.data || [])) {
@@ -84,6 +101,8 @@ export function BillingEntitySelect({ value, onChange, onSelectedAccountChange,
84
101
  planName: String(organization?.subscription?.plan_name ||
85
102
  organization?.plan_name ||
86
103
  '').trim(),
104
+ isAwsBilled: Boolean(organization?.awsMarketplace) ||
105
+ isAwsOriginUrn(organization?.origin ?? organization?.origin_s),
87
106
  });
88
107
  }
89
108
  return Array.from(accountMap.values());
@@ -117,6 +136,11 @@ export function BillingEntitySelect({ value, onChange, onSelectedAccountChange,
117
136
  accountMap.set(a.accountUid, a);
118
137
  const merged = Array.from(accountMap.values());
119
138
  const mergedByUid = new Map(merged.map(a => [a.accountUid, a]));
139
+ // Either list may say it: the organizations carry their origin, and IAM
140
+ // names the billing provider on each eligible entry.
141
+ const awsBilledUids = new Set([...allContextAccounts, ...eligibleAccounts]
142
+ .filter(a => a.isAwsBilled)
143
+ .map(a => a.accountUid));
120
144
  return merged.map(account => {
121
145
  const eligible = eligibleAccountByUid.get(account.accountUid);
122
146
  const details = detailsByUid.get(account.accountUid);
@@ -132,15 +156,22 @@ export function BillingEntitySelect({ value, onChange, onSelectedAccountChange,
132
156
  details?.wallet_balance ??
133
157
  0));
134
158
  const hasPositiveWallet = Number.isFinite(walletBalance) && walletBalance > 0;
135
- const isEligible = accountType === 'team'
136
- ? hasPositiveWallet
137
- : typeof details?.is_eligible === 'boolean'
138
- ? details.is_eligible ||
139
- (accountType === 'user' && hasPositiveWallet)
140
- : Boolean(eligible);
141
159
  const sourceOrganizationUid = accountType === 'team'
142
160
  ? String(details?.plan_source_account_uid || '').trim() || undefined
143
161
  : undefined;
162
+ // A team inherits it from the organization that pays for it.
163
+ const isAwsBilled = awsBilledUids.has(account.accountUid) ||
164
+ Boolean(sourceOrganizationUid && awsBilledUids.has(sourceOrganizationUid)) ||
165
+ isAwsBillingProvider(details?.subscription?.billing_provider);
166
+ const isEligible = isBillingEntityEligible({
167
+ accountType,
168
+ iamEligible: typeof details?.is_eligible === 'boolean'
169
+ ? details.is_eligible
170
+ : undefined,
171
+ isAwsBilled,
172
+ hasPositiveWallet,
173
+ listedEligible: Boolean(eligible),
174
+ });
144
175
  const sourceOrgDetails = sourceOrganizationUid
145
176
  ? detailsByUid.get(sourceOrganizationUid)
146
177
  : undefined;
@@ -160,6 +191,7 @@ export function BillingEntitySelect({ value, onChange, onSelectedAccountChange,
160
191
  planName,
161
192
  isEligible,
162
193
  isPaidPlan: resolveBillingPlanTier(planName || 'free') === 'pro',
194
+ isAwsBilled,
163
195
  sourceOrganizationUid,
164
196
  sourceOrganizationHandle,
165
197
  teamHandle: accountType === 'team' ? accountHandle : undefined,
@@ -307,7 +339,7 @@ export function BillingEntitySelect({ value, onChange, onSelectedAccountChange,
307
339
  ? 'Organization'
308
340
  : selectedAccount.accountType === 'team'
309
341
  ? 'Team'
310
- : 'User', children: selectedAccount.accountType === 'organization' ? (_jsx(OrganizationIcon, { size: 12 })) : selectedAccount.accountType === 'team' ? (_jsx(PeopleIcon, { size: 12 })) : (_jsx(PersonIcon, { size: 12 })) }), _jsx(Label, { size: "small", variant: selectedAccount.isPaidPlan ? 'success' : 'attention', children: formatBillingEntityPlanLabel(selectedAccount.planName) })] })] })) : !hasEligibleAccount ? (emptyMessage) : ('Select a billing entity') }) }), _jsxs(ActionMenu.Overlay, { width: "large", children: [_jsx(Box, { sx: { p: 2 }, children: _jsx(Box, { sx: {
342
+ : 'User', children: selectedAccount.accountType === 'organization' ? (_jsx(OrganizationIcon, { size: 12 })) : selectedAccount.accountType === 'team' ? (_jsx(PeopleIcon, { size: 12 })) : (_jsx(PersonIcon, { size: 12 })) }), selectedAccount.isAwsBilled ? _jsx(AwsBilledLabel, {}) : null, _jsx(Label, { size: "small", variant: selectedAccount.isPaidPlan ? 'success' : 'attention', children: formatBillingEntityPlanLabel(selectedAccount.planName) })] })] })) : !hasEligibleAccount ? (emptyMessage) : ('Select a billing entity') }) }), _jsxs(ActionMenu.Overlay, { width: "large", children: [_jsx(Box, { sx: { p: 2 }, children: _jsxs(Box, { sx: {
311
343
  borderRadius: 2,
312
344
  border: '1px solid',
313
345
  borderColor: 'border.default',
@@ -315,7 +347,12 @@ export function BillingEntitySelect({ value, onChange, onSelectedAccountChange,
315
347
  color: 'fg.muted',
316
348
  px: 3,
317
349
  py: 2,
318
- }, children: _jsx(Text, { sx: { fontSize: 1, lineHeight: 1.5 }, children: flashMessage }) }) }), _jsx(ActionList, { selectionVariant: "single", children: isLoading ? (_jsx(ActionList.Item, { disabled: true, children: _jsxs(Box, { sx: {
350
+ }, children: [_jsx(Text, { sx: { fontSize: 1, lineHeight: 1.5 }, children: flashMessage }), accounts.some(account => account.isAwsBilled) ? (_jsx(Text, { sx: {
351
+ display: 'block',
352
+ fontSize: 1,
353
+ lineHeight: 1.5,
354
+ mt: 2,
355
+ }, children: "Entries marked AWS are billed through AWS Marketplace: only work started under them is reported to AWS. Work started under any other entry is charged to the credits of that account and never reaches the AWS bill." })) : null] }) }), _jsx(ActionList, { selectionVariant: "single", children: isLoading ? (_jsx(ActionList.Item, { disabled: true, children: _jsxs(Box, { sx: {
319
356
  display: 'inline-flex',
320
357
  alignItems: 'center',
321
358
  gap: 2,
@@ -357,9 +394,11 @@ export function BillingEntitySelect({ value, onChange, onSelectedAccountChange,
357
394
  ? 'Organization'
358
395
  : account.accountType === 'team'
359
396
  ? 'Team'
360
- : 'User', children: account.accountType === 'organization' ? (_jsx(OrganizationIcon, { size: 12 })) : account.accountType === 'team' ? (_jsx(PeopleIcon, { size: 12 })) : (_jsx(PersonIcon, { size: 12 })) }), !account.isEligible &&
397
+ : 'User', children: account.accountType === 'organization' ? (_jsx(OrganizationIcon, { size: 12 })) : account.accountType === 'team' ? (_jsx(PeopleIcon, { size: 12 })) : (_jsx(PersonIcon, { size: 12 })) }), account.isAwsBilled ? _jsx(AwsBilledLabel, {}) : null, !account.isEligible &&
361
398
  account.accountType === 'team' && (_jsx(Label, { size: "small", variant: "attention", children: "No credits" })), _jsx(Label, { size: "small", variant: account.isPaidPlan ? 'success' : 'attention', children: formatBillingEntityPlanLabel(account.planName) })] })] }), _jsx(ActionList.Description, { variant: "block", children: account.isEligible
362
- ? 'Eligible'
399
+ ? account.isAwsBilled
400
+ ? 'Eligible — billed through AWS Marketplace'
401
+ : 'Eligible'
363
402
  : account.accountType === 'team'
364
403
  ? 'Not eligible — no team credits allocated'
365
404
  : 'Not eligible — activate a plan or add credits to use this account' })] })] }, account.accountUid));
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Whether work may be started under a billing entity: the rule the launch
3
+ * picker enables an entry by.
4
+ *
5
+ * IAM answers `is_eligible` from what its reservation door would accept, for
6
+ * every kind of account. For an entity AWS does not pay for, that door reads
7
+ * the entity's own wallet and asks no plan — so credits in the wallet make it
8
+ * eligible, personal, organization or team, on a paid plan or none. That is
9
+ * said here as well as in IAM, so an IAM that still asked organizations for a
10
+ * paid plan does not grey out an organization with credits to spend. An
11
+ * entity AWS pays for has no wallet: IAM alone decides it, from the
12
+ * subscription.
13
+ */
14
+ export declare function isBillingEntityEligible({ accountType, iamEligible, isAwsBilled, hasPositiveWallet, listedEligible, }: {
15
+ accountType: string;
16
+ /** `is_eligible` from IAM's account details, when it answered one. */
17
+ iamEligible?: boolean;
18
+ isAwsBilled: boolean;
19
+ hasPositiveWallet: boolean;
20
+ /** Whether IAM's eligible-accounts listing named the entity. */
21
+ listedEligible: boolean;
22
+ }): boolean;
@@ -0,0 +1,27 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ /*
6
+ * Copyright (c) 2023-2026 Datalayer, Inc.
7
+ * Distributed under the terms of the Modified BSD License.
8
+ */
9
+ /**
10
+ * Whether work may be started under a billing entity: the rule the launch
11
+ * picker enables an entry by.
12
+ *
13
+ * IAM answers `is_eligible` from what its reservation door would accept, for
14
+ * every kind of account. For an entity AWS does not pay for, that door reads
15
+ * the entity's own wallet and asks no plan — so credits in the wallet make it
16
+ * eligible, personal, organization or team, on a paid plan or none. That is
17
+ * said here as well as in IAM, so an IAM that still asked organizations for a
18
+ * paid plan does not grey out an organization with credits to spend. An
19
+ * entity AWS pays for has no wallet: IAM alone decides it, from the
20
+ * subscription.
21
+ */
22
+ export function isBillingEntityEligible({ accountType, iamEligible, isAwsBilled, hasPositiveWallet, listedEligible, }) {
23
+ if (typeof iamEligible === 'boolean') {
24
+ return iamEligible || (!isAwsBilled && hasPositiveWallet);
25
+ }
26
+ return accountType === 'team' ? hasPositiveWallet : listedEligible;
27
+ }
@@ -1 +1,2 @@
1
1
  export * from './BillingEntitySelect';
2
+ export * from './eligibility';
@@ -3,3 +3,4 @@
3
3
  * Distributed under the terms of the Modified BSD License.
4
4
  */
5
5
  export * from './BillingEntitySelect.js';
6
+ export * from './eligibility.js';
@@ -50,4 +50,4 @@ export type StripeCheckoutProps = {
50
50
  /**
51
51
  * Stripe checkout.
52
52
  */
53
- export declare function StripeCheckout({ checkoutPortal, appearance, accountUid, showStatusUsageSummary, onCheckoutSuccess, }: StripeCheckoutProps): import("react").JSX.Element;
53
+ export declare function StripeCheckout({ checkoutPortal, appearance, accountUid, showStatusUsageSummary, onCheckoutSuccess, }: StripeCheckoutProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
@@ -1067,7 +1067,7 @@ export function StripeCheckout({ checkoutPortal, appearance, accountUid, showSta
1067
1067
  }, children: [_jsx(Button, { variant: "danger", onClick: () => void onConfirmCancelSubscription(), disabled: isCancelActionPending, leadingVisual: () => isCancelActionPending ? _jsx(Spinner, { size: "small" }) : undefined, children: isCancelActionPending
1068
1068
  ? 'Waiting for confirmation...'
1069
1069
  : 'Confirm downgrade' }), _jsx(Button, { variant: "default", onClick: onAbortCancelView, disabled: isCancelActionPending, children: "Keep current plan" })] })] }))] }) })) : null;
1070
- let view = (_jsx(Box, { sx: { minHeight: '40px' }, children: _jsx(Spinner, {}) }));
1070
+ let view;
1071
1071
  // While the Stripe payment form is shown, disable interaction with the
1072
1072
  // status / plan picker cards behind it so the only available action is the
1073
1073
  // "Cancel" button next to the form.
@@ -24,6 +24,11 @@ export type LiveCollaborator = {
24
24
  name: string;
25
25
  avatarUrl?: string;
26
26
  avatarIcon?: string;
27
+ /**
28
+ * A literal emoji, for a face this platform draws rather than a person's
29
+ * own — an agent's — checked before `avatarUrl`/`avatarIcon`.
30
+ */
31
+ avatarEmoji?: string;
27
32
  /** Cursor color of the presence, worn by the initials disc. */
28
33
  color?: string;
29
34
  /** The platform uid, when the face is a real account — for its profile. */
@@ -37,6 +37,7 @@ function collaboratorOfState(clientId, state) {
37
37
  name,
38
38
  avatarUrl: user.avatar_url || user.avatarUrl || undefined,
39
39
  avatarIcon: user.avatar_icon_s || user.avatarIcon || undefined,
40
+ avatarEmoji: user.avatar_emoji_s || user.avatarEmoji || undefined,
40
41
  color: user.color || undefined,
41
42
  uid: uid ? String(uid) : undefined,
42
43
  handle: user.handle || username || undefined,
@@ -58,6 +59,7 @@ function mergeCollaborators(known, incoming) {
58
59
  handle: known.handle || incoming.handle,
59
60
  avatarUrl: known.avatarUrl || incoming.avatarUrl,
60
61
  avatarIcon: known.avatarIcon || incoming.avatarIcon,
62
+ avatarEmoji: known.avatarEmoji || incoming.avatarEmoji,
61
63
  color: known.color || incoming.color,
62
64
  };
63
65
  }
@@ -157,6 +159,6 @@ export function LiveEditorCollaborators(props) {
157
159
  // person arrives now under their uid, now under a client id, and a
158
160
  // key that followed that would unmount the hover card mid-open and
159
161
  // leak its overlay. Their identity, not their arrival, names them.
160
- , { kind: "personal", uid: face.uid, handle: face.handle, displayName: face.name, name: face.name, avatarUrl: face.avatarUrl, avatarIcon: face.avatarIcon, onNavigate: onNavigate, children: _jsx(PrincipalAvatar, { kind: "personal", size: size, alt: face.name, avatarUrl: face.avatarUrl, avatarIcon: face.avatarIcon, square: false }) }, face.uid || face.handle || face.name.trim().toLowerCase()))) }));
162
+ , { kind: "personal", uid: face.uid, handle: face.handle, displayName: face.name, name: face.name, avatarUrl: face.avatarUrl, avatarIcon: face.avatarIcon, avatarEmoji: face.avatarEmoji, onNavigate: onNavigate, children: _jsx(PrincipalAvatar, { kind: "personal", size: size, alt: face.name, avatarUrl: face.avatarUrl, avatarIcon: face.avatarIcon, avatarEmoji: face.avatarEmoji, square: false }) }, face.uid || face.handle || face.name.trim().toLowerCase()))) }));
161
163
  }
162
164
  export default LiveEditorCollaborators;
@@ -1,4 +1,3 @@
1
- import type { PropsWithChildren, ReactNode } from 'react';
2
1
  type DatalayerBoxProps = {
3
2
  id?: string;
4
3
  title: string;
@@ -9,7 +8,7 @@ type DatalayerBoxProps = {
9
8
  *
10
9
  * The link on the trailing edge leads somewhere; this stays here.
11
10
  */
12
- titleAction?: ReactNode;
11
+ titleAction?: React.ReactNode;
13
12
  };
14
- export declare const DatalayerBox: (props: PropsWithChildren<DatalayerBoxProps>) => import("react").JSX.Element;
13
+ export declare const DatalayerBox: (props: React.PropsWithChildren<DatalayerBoxProps>) => import("react").JSX.Element;
15
14
  export default DatalayerBox;
@@ -8,7 +8,7 @@ import { Box } from '@datalayer/primer-addons';
8
8
  import { ArrowRightIcon } from '@primer/octicons-react';
9
9
  import { useNavigate } from '../../hooks/index.js';
10
10
  export const DatalayerBox = (props) => {
11
- const { title, titleAction, linkLabel, linkRoute, children } = props;
11
+ const { title, linkLabel, linkRoute, titleAction, children } = props;
12
12
  const navigate = useNavigate();
13
13
  return (_jsxs(_Fragment, { children: [_jsxs(Box, { sx: {
14
14
  display: 'flex',
@@ -11,9 +11,10 @@ import { useNavigate } from '../../hooks/index.js';
11
11
  */
12
12
  export const NavLink = forwardRef(({ to, children, ...props }, ref) => {
13
13
  const navigate = useNavigate();
14
+ // The hook decides: a plain click navigates here, a modifier click lets
15
+ // the browser open the link in a new tab.
14
16
  const onClick = useCallback((e) => {
15
- e.preventDefault();
16
- navigate(to);
17
+ navigate(to, e);
17
18
  }, [to, navigate]);
18
19
  return (_jsx("a", { ref: ref, href: to, ...props, onClick: onClick, children: children }));
19
20
  });
@@ -1,5 +1,4 @@
1
- import { SxProp } from '@primer/react';
2
1
  export interface IVisuallyHiddenProps {
3
2
  isVisible?: boolean;
4
3
  }
5
- export declare const VisuallyHidden: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, IVisuallyHiddenProps & SxProp>> & string;
4
+ export declare const VisuallyHidden: any;
@@ -9,8 +9,7 @@
9
9
  *
10
10
  * @module components/labels/StatusLabels
11
11
  */
12
- import type { JSX } from 'react';
13
- import type { ReactNode } from 'react';
12
+ import type { JSX, ReactNode } from 'react';
14
13
  /** The tones a status pill is read in. */
15
14
  export type StatusLabelTone = 'accent' | 'attention' | 'success' | 'neutral';
16
15
  export type StatusLabelProps = {
@@ -40,13 +39,6 @@ export declare function AdminLabel(props?: StatusLabelProps): JSX.Element;
40
39
  * The one that is taken when none is chosen — the default space of an account.
41
40
  */
42
41
  export declare function DefaultLabel(props?: StatusLabelProps): JSX.Element;
43
- /**
44
- * Something announced and not there yet.
45
- *
46
- * A tone of its own, and deliberately not the accent an alpha wears: one says
47
- * "you may try this, it may bite", the other "there is nothing to try". Read
48
- * side by side in a navigation, two labels of one colour say the same thing
49
- * about two entries that mean different things.
50
- */
42
+ /** "soon": what is announced but not yet there. */
51
43
  export declare function SoonLabel(props?: StatusLabelProps): JSX.Element;
52
44
  export default StatusLabel;
@@ -33,24 +33,7 @@ export function StatusLabel(props) {
33
33
  return (_jsx(Label, { variant: "secondary", size: size, sx: {
34
34
  textTransform: 'lowercase',
35
35
  lineHeight: 1.2,
36
- /*
37
- * The tone, under a doubled selector.
38
- *
39
- * Primer ships `NavList` and `ActionList` as CSS modules, and the
40
- * colour they set on the contents of an item ties with the one Emotion
41
- * generates for `sx` — so the same label came out in the colour of the
42
- * navigation in one place and in its own colour in another, depending
43
- * on which stylesheet happened to come last. `&&` raises the
44
- * specificity enough that the tone always lands, wherever the label is
45
- * put.
46
- */
47
- '&&': {
48
- ...TONES[tone],
49
- // The navigation of Primer colours the contents of its items, and
50
- // its stylesheet is loaded after ours: a doubled selector was not
51
- // enough on its own, so the colour of the tone is stated as final.
52
- color: `${TONES[tone].color} !important`,
53
- },
36
+ ...TONES[tone],
54
37
  ...sx,
55
38
  }, children: children }));
56
39
  }
@@ -75,14 +58,7 @@ export function DefaultLabel(props = {}) {
75
58
  const { children = 'default', ...rest } = props;
76
59
  return (_jsx(StatusLabel, { tone: "accent", ...rest, children: children }));
77
60
  }
78
- /**
79
- * Something announced and not there yet.
80
- *
81
- * A tone of its own, and deliberately not the accent an alpha wears: one says
82
- * "you may try this, it may bite", the other "there is nothing to try". Read
83
- * side by side in a navigation, two labels of one colour say the same thing
84
- * about two entries that mean different things.
85
- */
61
+ /** "soon": what is announced but not yet there. */
86
62
  export function SoonLabel(props = {}) {
87
63
  const { children = 'soon', ...rest } = props;
88
64
  return (_jsx(StatusLabel, { tone: "neutral", ...rest, children: children }));
@@ -1,26 +1,5 @@
1
1
  import type { JSX } from 'react';
2
2
  import { type ComponentType, type SVGProps } from 'react';
3
- import { SvgAboutHero } from '@datalayer/design/lib/svg/SvgAboutHero';
4
- import { SvgAgentsHero } from '@datalayer/design/lib/svg/SvgAgentsHero';
5
- import { SvgAgentsHomeHero } from '@datalayer/design/lib/svg/SvgAgentsHomeHero';
6
- import { SvgBlogHero } from '@datalayer/design/lib/svg/SvgBlogHero';
7
- import { SvgCareersHero } from '@datalayer/design/lib/svg/SvgCareersHero';
8
- import { SvgChangelogHero } from '@datalayer/design/lib/svg/SvgChangelogHero';
9
- import { SvgCommunityHero } from '@datalayer/design/lib/svg/SvgCommunityHero';
10
- import { SvgContactHero } from '@datalayer/design/lib/svg/SvgContactHero';
11
- import { SvgEarthHero } from '@datalayer/design/lib/svg/SvgEarthHero';
12
- import { SvgEvalsHero } from '@datalayer/design/lib/svg/SvgEvalsHero';
13
- import { SvgEventsHero } from '@datalayer/design/lib/svg/SvgEventsHero';
14
- import { SvgIntegrationsHero } from '@datalayer/design/lib/svg/SvgIntegrationsHero';
15
- import { SvgLoginHero } from '@datalayer/design/lib/svg/SvgLoginHero';
16
- import { SvgPartnersHero } from '@datalayer/design/lib/svg/SvgPartnersHero';
17
- import { SvgPricingHero } from '@datalayer/design/lib/svg/SvgPricingHero';
18
- import { SvgPrivacyHero } from '@datalayer/design/lib/svg/SvgPrivacyHero';
19
- import { SvgResearchHero } from '@datalayer/design/lib/svg/SvgResearchHero';
20
- import { SvgStarsHero } from '@datalayer/design/lib/svg/SvgStarsHero';
21
- import { SvgTermsHero } from '@datalayer/design/lib/svg/SvgTermsHero';
22
- import { SvgTutorialsHero } from '@datalayer/design/lib/svg/SvgTutorialsHero';
23
- import { SvgUsecasesHero } from '@datalayer/design/lib/svg/SvgUsecasesHero';
24
3
  export type PrincipalType = 'personal' | 'organization' | 'team';
25
4
  type AvatarComponent = ComponentType<SVGProps<SVGSVGElement> & {
26
5
  size?: number | 'small' | 'medium' | 'large';
@@ -46,87 +25,87 @@ export declare const PRINCIPAL_AVATAR_ICONS: ReadonlyArray<{
46
25
  export declare const PRINCIPAL_BANNERS: readonly [{
47
26
  readonly name: "SvgAboutHero";
48
27
  readonly label: "About";
49
- readonly Component: typeof SvgAboutHero;
28
+ readonly Component: ComponentType<any>;
50
29
  }, {
51
30
  readonly name: "SvgAgentsHero";
52
31
  readonly label: "Agents";
53
- readonly Component: typeof SvgAgentsHero;
32
+ readonly Component: ComponentType<any>;
54
33
  }, {
55
34
  readonly name: "SvgAgentsHomeHero";
56
35
  readonly label: "Agents home";
57
- readonly Component: typeof SvgAgentsHomeHero;
36
+ readonly Component: ComponentType<any>;
58
37
  }, {
59
38
  readonly name: "SvgBlogHero";
60
39
  readonly label: "Blog";
61
- readonly Component: typeof SvgBlogHero;
40
+ readonly Component: ComponentType<any>;
62
41
  }, {
63
42
  readonly name: "SvgCareersHero";
64
43
  readonly label: "Careers";
65
- readonly Component: typeof SvgCareersHero;
44
+ readonly Component: ComponentType<any>;
66
45
  }, {
67
46
  readonly name: "SvgChangelogHero";
68
47
  readonly label: "Changelog";
69
- readonly Component: typeof SvgChangelogHero;
48
+ readonly Component: ComponentType<any>;
70
49
  }, {
71
50
  readonly name: "SvgCommunityHero";
72
51
  readonly label: "Community";
73
- readonly Component: typeof SvgCommunityHero;
52
+ readonly Component: ComponentType<any>;
74
53
  }, {
75
54
  readonly name: "SvgContactHero";
76
55
  readonly label: "Contact";
77
- readonly Component: typeof SvgContactHero;
56
+ readonly Component: ComponentType<any>;
78
57
  }, {
79
58
  readonly name: "SvgEarthHero";
80
59
  readonly label: "Earth";
81
- readonly Component: typeof SvgEarthHero;
60
+ readonly Component: ComponentType<any>;
82
61
  }, {
83
62
  readonly name: "SvgEvalsHero";
84
63
  readonly label: "Evaluations";
85
- readonly Component: typeof SvgEvalsHero;
64
+ readonly Component: ComponentType<any>;
86
65
  }, {
87
66
  readonly name: "SvgEventsHero";
88
67
  readonly label: "Events";
89
- readonly Component: typeof SvgEventsHero;
68
+ readonly Component: ComponentType<any>;
90
69
  }, {
91
70
  readonly name: "SvgIntegrationsHero";
92
71
  readonly label: "Integrations";
93
- readonly Component: typeof SvgIntegrationsHero;
72
+ readonly Component: ComponentType<any>;
94
73
  }, {
95
74
  readonly name: "SvgLoginHero";
96
75
  readonly label: "Login";
97
- readonly Component: typeof SvgLoginHero;
76
+ readonly Component: ComponentType<any>;
98
77
  }, {
99
78
  readonly name: "SvgPartnersHero";
100
79
  readonly label: "Partners";
101
- readonly Component: typeof SvgPartnersHero;
80
+ readonly Component: ComponentType<any>;
102
81
  }, {
103
82
  readonly name: "SvgPricingHero";
104
83
  readonly label: "Pricing";
105
- readonly Component: typeof SvgPricingHero;
84
+ readonly Component: ComponentType<any>;
106
85
  }, {
107
86
  readonly name: "SvgPrivacyHero";
108
87
  readonly label: "Privacy";
109
- readonly Component: typeof SvgPrivacyHero;
88
+ readonly Component: ComponentType<any>;
110
89
  }, {
111
90
  readonly name: "SvgResearchHero";
112
91
  readonly label: "Research";
113
- readonly Component: typeof SvgResearchHero;
92
+ readonly Component: ComponentType<any>;
114
93
  }, {
115
94
  readonly name: "SvgStarsHero";
116
95
  readonly label: "Stars";
117
- readonly Component: typeof SvgStarsHero;
96
+ readonly Component: ComponentType<any>;
118
97
  }, {
119
98
  readonly name: "SvgTermsHero";
120
99
  readonly label: "Terms";
121
- readonly Component: typeof SvgTermsHero;
100
+ readonly Component: ComponentType<any>;
122
101
  }, {
123
102
  readonly name: "SvgTutorialsHero";
124
103
  readonly label: "Tutorials";
125
- readonly Component: typeof SvgTutorialsHero;
104
+ readonly Component: ComponentType<any>;
126
105
  }, {
127
106
  readonly name: "SvgUsecasesHero";
128
107
  readonly label: "Use cases";
129
- readonly Component: typeof SvgUsecasesHero;
108
+ readonly Component: ComponentType<any>;
130
109
  }];
131
110
  export declare function getPrincipalBannerForSeed(seed: string): string;
132
111
  export declare function getPrincipalAvatarIcon(name?: string): AvatarComponent | undefined;