@agent-native/core 0.80.0 → 0.80.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +8 -0
- package/corpus/core/docs/content/locales/ar-SA/skills-guide.mdx +5 -0
- package/corpus/core/docs/content/locales/ar-SA/template-design.mdx +14 -1
- package/corpus/core/docs/content/locales/de-DE/skills-guide.mdx +5 -0
- package/corpus/core/docs/content/locales/de-DE/template-design.mdx +15 -1
- package/corpus/core/docs/content/locales/es-ES/skills-guide.mdx +5 -0
- package/corpus/core/docs/content/locales/es-ES/template-design.mdx +15 -1
- package/corpus/core/docs/content/locales/fr-FR/skills-guide.mdx +5 -0
- package/corpus/core/docs/content/locales/fr-FR/template-design.mdx +15 -1
- package/corpus/core/docs/content/locales/hi-IN/skills-guide.mdx +5 -0
- package/corpus/core/docs/content/locales/hi-IN/template-design.mdx +15 -1
- package/corpus/core/docs/content/locales/ja-JP/skills-guide.mdx +5 -0
- package/corpus/core/docs/content/locales/ja-JP/template-design.mdx +16 -1
- package/corpus/core/docs/content/locales/ko-KR/skills-guide.mdx +5 -0
- package/corpus/core/docs/content/locales/ko-KR/template-design.mdx +14 -1
- package/corpus/core/docs/content/locales/pt-BR/skills-guide.mdx +5 -0
- package/corpus/core/docs/content/locales/pt-BR/template-design.mdx +14 -1
- package/corpus/core/docs/content/locales/zh-CN/skills-guide.mdx +5 -0
- package/corpus/core/docs/content/locales/zh-CN/template-design.mdx +14 -1
- package/corpus/core/docs/content/locales/zh-TW/skills-guide.mdx +5 -0
- package/corpus/core/docs/content/locales/zh-TW/template-design.mdx +14 -1
- package/corpus/core/docs/content/skills-guide.mdx +5 -0
- package/corpus/core/docs/content/template-design.mdx +14 -1
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/application-state/handlers.ts +1 -1
- package/corpus/core/src/brand-kit/index.ts +1 -1
- package/corpus/core/src/cli/skills.ts +18 -0
- package/corpus/core/src/client/AgentPanel.tsx +1 -1
- package/corpus/core/src/client/MultiTabAssistantChat.tsx +1 -1
- package/corpus/core/src/client/extensions/portable-extension.ts +1 -1
- package/corpus/core/src/code-agents/transcript-normalizer.ts +1 -1
- package/corpus/core/src/extensions/path.ts +1 -4
- package/corpus/core/src/integrations/a2a-continuation-processor.ts +1 -1
- package/corpus/core/src/mcp/build-server.ts +1 -1
- package/corpus/core/src/org/handlers.ts +5 -5
- package/corpus/core/src/org/plugin.ts +2 -2
- package/corpus/core/src/scripts/call-agent.ts +1 -1
- package/corpus/core/src/scripts/db/safety.ts +1 -1
- package/corpus/core/src/server/auth.ts +3 -0
- package/corpus/core/src/server/builder-design-systems.ts +308 -0
- package/corpus/core/src/server/core-routes-plugin.ts +29 -3
- package/corpus/core/src/server/index.ts +8 -0
- package/corpus/core/src/styles/agent-native.css +14 -7
- package/corpus/core/src/usage/store.ts +2 -2
- package/corpus/templates/analytics/actions/dashboard-mutation-api.ts +298 -15
- package/corpus/templates/analytics/actions/get-sql-dashboard.ts +9 -4
- package/corpus/templates/analytics/actions/mutate-dashboard.ts +18 -2
- package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +12 -2
- package/corpus/templates/analytics/app/hooks/use-replay-storage-status.ts +66 -0
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +37 -0
- package/corpus/templates/analytics/app/i18n-data.ts +404 -0
- package/corpus/templates/analytics/app/pages/Settings.tsx +333 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/PanelEditorDialog.tsx +2 -1
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/dashboard-layout.ts +121 -3
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +49 -26
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +137 -36
- package/corpus/templates/analytics/changelog/2026-06-29-analytics-agents-can-now-place-new-charts-into-requested-das.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-29-analytics-queries-now-report-failed-source-query-errors-inst.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-29-charts-can-now-be-dropped-between-full-dashboard-rows-to-cre.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-29-dashboard-email-reports-include-the-full-dashboard-image-wit.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-29-main-surface-border-reaches-the-top.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-29-session-replay-now-records-playable-sessions-in-production-a.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-29-set-up-session-replay-storage-from-settings-connect-builder-.md +6 -0
- package/corpus/templates/analytics/scripts/cleanup-empty-session-recordings.ts +102 -0
- package/corpus/templates/analytics/server/lib/dashboard-report.ts +49 -26
- package/corpus/templates/analytics/server/lib/real-data-actions.ts +81 -20
- package/corpus/templates/analytics/server/lib/replay-storage.ts +79 -0
- package/corpus/templates/analytics/server/lib/s3-upload-provider.ts +255 -0
- package/corpus/templates/analytics/server/lib/session-replay.ts +29 -8
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +11 -2
- package/corpus/templates/analytics/server/plugins/onboarding.ts +97 -0
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +24 -0
- package/corpus/templates/clips/desktop/src/lib/transcription-capture.ts +105 -5
- package/corpus/templates/content/actions/set-image-alt-text.ts +1 -1
- package/corpus/templates/content/shared/document-export.ts +1 -1
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +8 -18
- package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +17 -0
- package/corpus/templates/design/actions/add-localhost-screens.ts +32 -5
- package/corpus/templates/design/actions/index-design-system-with-builder.ts +259 -0
- package/corpus/templates/design/actions/update-file.ts +9 -2
- package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +33 -75
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +72 -9
- package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +41 -39
- package/corpus/templates/design/app/components/design/EditPanel.tsx +1029 -249
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +450 -101
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +978 -154
- package/corpus/templates/design/app/components/design/TweaksPanel.tsx +7 -9
- package/corpus/templates/design/app/components/design/inspector/AlignmentMatrix.tsx +133 -66
- package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +1234 -344
- package/corpus/templates/design/app/components/design/inspector/ConstraintsWidget.tsx +144 -94
- package/corpus/templates/design/app/components/design/inspector/ExportSettingsPanel.tsx +301 -72
- package/corpus/templates/design/app/components/design/inspector/FigmaColorPicker.tsx +876 -286
- package/corpus/templates/design/app/components/design/inspector/GradientEditor.tsx +601 -0
- package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +242 -0
- package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +30 -7
- package/corpus/templates/design/app/components/design/inspector/ShaderControls.tsx +212 -155
- package/corpus/templates/design/app/components/design/inspector/ShaderFillsPanel.tsx +423 -0
- package/corpus/templates/design/app/components/design/inspector/figma-icons.tsx +487 -107
- package/corpus/templates/design/app/components/design/inspector/index.ts +27 -0
- package/corpus/templates/design/app/global.css +29 -3
- package/corpus/templates/design/app/i18n/zh-TW.ts +13 -0
- package/corpus/templates/design/app/i18n-data.ts +239 -1
- package/corpus/templates/design/app/pages/DesignEditor.tsx +1023 -353
- package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +57 -221
- package/corpus/templates/design/changelog/2026-06-29-canvas-selection-no-longer-flashes-broken-prototype-html-whe.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-command-menu-selections-are-clearer-in-dark-mode.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-design-mode-top-chrome-now-groups-collaborators-preview-shar.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-element-selection-now-stays-on-the-intended-layer-after-sele.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-screen-overview-full-view-controls-now-sit-above-frames-inst.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-screen-overview-tools-can-draw-shapes-create-screens-and-kee.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-the-pen-tool-now-creates-anchor-based-bezier-vectors-with-ha.md +6 -0
- package/corpus/templates/design/server/handlers/import-figma-system.ts +38 -85
- package/corpus/templates/design/server/lib/design-snapshot.ts +9 -1
- package/corpus/templates/design/shared/code-layer.ts +209 -9
- package/corpus/templates/design/shared/html-content.ts +21 -0
- package/corpus/templates/design/shared/pen-path.ts +207 -0
- package/corpus/templates/mail/app/lib/utils.ts +2 -2
- package/corpus/templates/slides/.agents/skills/design-systems/SKILL.md +9 -10
- package/corpus/templates/slides/AGENTS.md +3 -2
- package/corpus/templates/slides/actions/import-file.ts +26 -17
- package/corpus/templates/slides/actions/index-design-system-with-builder.ts +259 -0
- package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +35 -167
- package/corpus/templates/slides/app/components/design-system/fig-import-response.ts +9 -13
- package/corpus/templates/slides/app/context/DeckContext.tsx +1 -1
- package/corpus/templates/slides/app/i18n/ar-SA.ts +9 -37
- package/corpus/templates/slides/app/i18n/de-DE.ts +10 -25
- package/corpus/templates/slides/app/i18n/en-US.ts +9 -26
- package/corpus/templates/slides/app/i18n/es-ES.ts +10 -28
- package/corpus/templates/slides/app/i18n/fr-FR.ts +10 -28
- package/corpus/templates/slides/app/i18n/hi-IN.ts +9 -26
- package/corpus/templates/slides/app/i18n/ja-JP.ts +10 -22
- package/corpus/templates/slides/app/i18n/ko-KR.ts +9 -23
- package/corpus/templates/slides/app/i18n/pt-BR.ts +10 -28
- package/corpus/templates/slides/app/i18n/zh-CN.ts +9 -22
- package/corpus/templates/slides/app/i18n/zh-TW.ts +9 -22
- package/corpus/templates/slides/server/handlers/import-figma-system.ts +44 -12
- package/corpus/templates/slides/server/lib/chat-attachments.ts +1 -1
- package/corpus/templates/videos/app/components/NewCompositionPopover.tsx +1 -1
- package/dist/application-state/handlers.js +1 -1
- package/dist/application-state/handlers.js.map +1 -1
- package/dist/brand-kit/index.d.ts +1 -1
- package/dist/brand-kit/index.js +1 -1
- package/dist/brand-kit/index.js.map +1 -1
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +18 -0
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/AgentPanel.js +1 -1
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +1 -1
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/extensions/portable-extension.d.ts +1 -1
- package/dist/client/extensions/portable-extension.d.ts.map +1 -1
- package/dist/client/extensions/portable-extension.js.map +1 -1
- package/dist/code-agents/transcript-normalizer.js +1 -1
- package/dist/code-agents/transcript-normalizer.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/extensions/path.d.ts +1 -1
- package/dist/extensions/path.d.ts.map +1 -1
- package/dist/extensions/path.js.map +1 -1
- package/dist/integrations/a2a-continuation-processor.js +1 -1
- package/dist/integrations/a2a-continuation-processor.js.map +1 -1
- package/dist/mcp/build-server.d.ts +1 -1
- package/dist/mcp/build-server.d.ts.map +1 -1
- package/dist/mcp/build-server.js.map +1 -1
- package/dist/observability/routes.d.ts +3 -3
- package/dist/org/handlers.js +5 -5
- package/dist/org/handlers.js.map +1 -1
- package/dist/org/plugin.js +2 -2
- package/dist/org/plugin.js.map +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/scripts/call-agent.js +1 -1
- package/dist/scripts/call-agent.js.map +1 -1
- package/dist/scripts/db/safety.js +1 -1
- package/dist/scripts/db/safety.js.map +1 -1
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +3 -0
- package/dist/server/auth.js.map +1 -1
- package/dist/server/builder-design-systems.d.ts +28 -0
- package/dist/server/builder-design-systems.d.ts.map +1 -0
- package/dist/server/builder-design-systems.js +217 -0
- package/dist/server/builder-design-systems.js.map +1 -0
- package/dist/server/core-routes-plugin.d.ts +1 -0
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +20 -3
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/styles/agent-native.css +14 -7
- package/dist/usage/store.js +2 -2
- package/dist/usage/store.js.map +1 -1
- package/docs/content/locales/ar-SA/skills-guide.mdx +5 -0
- package/docs/content/locales/ar-SA/template-design.mdx +14 -1
- package/docs/content/locales/de-DE/skills-guide.mdx +5 -0
- package/docs/content/locales/de-DE/template-design.mdx +15 -1
- package/docs/content/locales/es-ES/skills-guide.mdx +5 -0
- package/docs/content/locales/es-ES/template-design.mdx +15 -1
- package/docs/content/locales/fr-FR/skills-guide.mdx +5 -0
- package/docs/content/locales/fr-FR/template-design.mdx +15 -1
- package/docs/content/locales/hi-IN/skills-guide.mdx +5 -0
- package/docs/content/locales/hi-IN/template-design.mdx +15 -1
- package/docs/content/locales/ja-JP/skills-guide.mdx +5 -0
- package/docs/content/locales/ja-JP/template-design.mdx +16 -1
- package/docs/content/locales/ko-KR/skills-guide.mdx +5 -0
- package/docs/content/locales/ko-KR/template-design.mdx +14 -1
- package/docs/content/locales/pt-BR/skills-guide.mdx +5 -0
- package/docs/content/locales/pt-BR/template-design.mdx +14 -1
- package/docs/content/locales/zh-CN/skills-guide.mdx +5 -0
- package/docs/content/locales/zh-CN/template-design.mdx +14 -1
- package/docs/content/locales/zh-TW/skills-guide.mdx +5 -0
- package/docs/content/locales/zh-TW/template-design.mdx +14 -1
- package/docs/content/skills-guide.mdx +5 -0
- package/docs/content/template-design.mdx +14 -1
- package/package.json +1 -1
- package/corpus/templates/design/actions/import-figma-file.ts +0 -166
- package/corpus/templates/slides/server/lib/fig-design-system.ts +0 -110
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* The shared, template-agnostic Brand Kit surface. A Brand Kit unifies what
|
|
5
5
|
* `design` and `slides` previously copy-pasted as a "design system": design
|
|
6
|
-
* tokens + brand assets + custom instructions, extractable from
|
|
6
|
+
* tokens + brand assets + custom instructions, extractable from code,
|
|
7
7
|
* GitHub, a URL, or documents, and used to generate on-brand content.
|
|
8
8
|
*
|
|
9
9
|
* This module is pure (no `defineAction`, no DB, no template imports). Templates
|
|
@@ -404,6 +404,10 @@ iframe-backed screens on the infinite canvas.
|
|
|
404
404
|
iframe frame and URL metadata; change the copy's path/query for a new state.
|
|
405
405
|
- Flow visualization is multiple URL states: \`/checkout?step=shipping\`,
|
|
406
406
|
\`/checkout?step=payment\`, \`/checkout?step=done\`, etc.
|
|
407
|
+
- When the user gives a named flow or numbered screen list, preserve that order
|
|
408
|
+
and create one screen per URL/path. Shorthand like
|
|
409
|
+
\`localhost:1234/onboarding/1\` means
|
|
410
|
+
\`http://localhost:1234/onboarding/1\`.
|
|
407
411
|
|
|
408
412
|
## Required Local Bridge
|
|
409
413
|
|
|
@@ -439,6 +443,20 @@ pnpm action add-localhost-screens '{
|
|
|
439
443
|
}'
|
|
440
444
|
\`\`\`
|
|
441
445
|
|
|
446
|
+
For a numbered flow the user describes in chat, keep the labels and order:
|
|
447
|
+
|
|
448
|
+
\`\`\`bash
|
|
449
|
+
pnpm action add-localhost-screens '{
|
|
450
|
+
"designId": "<design-id>",
|
|
451
|
+
"connectionId": "<connection-id>",
|
|
452
|
+
"routes": [
|
|
453
|
+
{ "url": "localhost:1234/onboarding/1", "title": "Screen 1" },
|
|
454
|
+
{ "url": "localhost:1234/onboarding/2", "title": "Screen 2" },
|
|
455
|
+
{ "url": "localhost:1234/onboarding/3", "title": "Screen 3" }
|
|
456
|
+
]
|
|
457
|
+
}'
|
|
458
|
+
\`\`\`
|
|
459
|
+
|
|
442
460
|
If no \`routes\` or \`paths\` are supplied, \`add-localhost-screens\` uses every
|
|
443
461
|
route from the latest localhost manifest.
|
|
444
462
|
|
|
@@ -1318,7 +1318,7 @@ function AgentPanelInner({
|
|
|
1318
1318
|
data-agent-page-new-chat=""
|
|
1319
1319
|
aria-label={t("agentPanel.newChat")}
|
|
1320
1320
|
onClick={() => {
|
|
1321
|
-
|
|
1321
|
+
addTab();
|
|
1322
1322
|
}}
|
|
1323
1323
|
className="pointer-events-auto inline-flex h-8 items-center gap-1.5 rounded-md border border-border bg-background/95 px-2.5 text-xs font-medium text-foreground shadow-sm backdrop-blur transition-colors hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
1324
1324
|
>
|
|
@@ -47,7 +47,7 @@ export interface AgentNativeExtensionStorageOptions {
|
|
|
47
47
|
export interface AgentNativeExtensionStorageContext {
|
|
48
48
|
extensionId: string;
|
|
49
49
|
slotId?: string;
|
|
50
|
-
scope?: Exclude<AgentNativeExtensionStorageScope, "all"
|
|
50
|
+
scope?: Exclude<AgentNativeExtensionStorageScope, "all">;
|
|
51
51
|
userId?: string;
|
|
52
52
|
organizationId?: string;
|
|
53
53
|
[key: string]: unknown;
|
|
@@ -576,7 +576,7 @@ function joinAssistantChunks(previous: string, next: string): string {
|
|
|
576
576
|
if (!next) return previous;
|
|
577
577
|
if (/\s$/.test(previous) || /^\s/.test(next)) return `${previous}${next}`;
|
|
578
578
|
if (/^[.,!?;:)\]}'"`]/.test(next)) return `${previous}${next}`;
|
|
579
|
-
if (/[(
|
|
579
|
+
if (/[([{'"`]$/.test(previous)) return `${previous}${next}`;
|
|
580
580
|
return `${previous} ${next}`;
|
|
581
581
|
}
|
|
582
582
|
|
|
@@ -19,10 +19,7 @@ export function extensionNameToSlug(
|
|
|
19
19
|
return sliced || "extension";
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
export function extensionPath(
|
|
23
|
-
id: string,
|
|
24
|
-
name?: string | null | undefined,
|
|
25
|
-
): string {
|
|
22
|
+
export function extensionPath(id: string, name?: string | null): string {
|
|
26
23
|
const encodedId = encodeURIComponent(id);
|
|
27
24
|
if (name === undefined) return `/extensions/${encodedId}`;
|
|
28
25
|
return `/extensions/${encodedId}/${extensionNameToSlug(name)}`;
|
|
@@ -528,7 +528,7 @@ function expandRelativeUrls(text: string, agentUrl: string): string {
|
|
|
528
528
|
if (!text || !agentUrl) return text;
|
|
529
529
|
const base = publicAgentBaseUrl(agentUrl);
|
|
530
530
|
return text.replace(
|
|
531
|
-
/(^|[\s(
|
|
531
|
+
/(^|[\s([<"'`])(\/[a-z0-9_-][a-z0-9_/?&=%#.,:-]*)/gi,
|
|
532
532
|
(_match, lead, path) => `${lead}${base}${path}`,
|
|
533
533
|
);
|
|
534
534
|
}
|
|
@@ -1889,7 +1889,7 @@ async function isConnectTokenAllowed(
|
|
|
1889
1889
|
*/
|
|
1890
1890
|
export async function verifyAuth(
|
|
1891
1891
|
authHeader: string | undefined,
|
|
1892
|
-
ownerEmailHeader?: string
|
|
1892
|
+
ownerEmailHeader?: string,
|
|
1893
1893
|
options: { allowDevOpen?: boolean; resourceUrl?: string | string[] } = {},
|
|
1894
1894
|
): Promise<{
|
|
1895
1895
|
authed: boolean;
|
|
@@ -17,8 +17,8 @@ function extractInvitationId(event: H3Event): string | undefined {
|
|
|
17
17
|
if (fromRouter) return fromRouter;
|
|
18
18
|
const path = getRequestURL(event).pathname;
|
|
19
19
|
const match =
|
|
20
|
-
path.match(/^\/([
|
|
21
|
-
path.match(/\/org\/invitations\/([
|
|
20
|
+
path.match(/^\/([^/]+)\/accept\/?$/) ??
|
|
21
|
+
path.match(/\/org\/invitations\/([^/]+)\/accept\/?$/);
|
|
22
22
|
return match?.[1] ? decodeURIComponent(match[1]) : undefined;
|
|
23
23
|
}
|
|
24
24
|
|
|
@@ -28,9 +28,9 @@ function extractMemberEmail(event: H3Event): string | undefined {
|
|
|
28
28
|
if (fromRouter) return fromRouter;
|
|
29
29
|
const path = getRequestURL(event).pathname;
|
|
30
30
|
const match =
|
|
31
|
-
path.match(/^\/([
|
|
32
|
-
path.match(/^\/([
|
|
33
|
-
path.match(/\/org\/members\/([
|
|
31
|
+
path.match(/^\/([^/]+)\/role\/?$/) ??
|
|
32
|
+
path.match(/^\/([^/]+)\/?$/) ??
|
|
33
|
+
path.match(/\/org\/members\/([^/]+)(?:\/role)?\/?$/);
|
|
34
34
|
return match?.[1] ? decodeURIComponent(match[1]) : undefined;
|
|
35
35
|
}
|
|
36
36
|
const nanoid = (): string =>
|
|
@@ -100,7 +100,7 @@ export function createOrgPlugin(): NitroPluginDef {
|
|
|
100
100
|
return listMembersHandler(event);
|
|
101
101
|
}
|
|
102
102
|
// Tail is /:email/role
|
|
103
|
-
if (/^\/[
|
|
103
|
+
if (/^\/[^/]+\/role\/?$/.test(tail)) {
|
|
104
104
|
if (method !== "PUT") {
|
|
105
105
|
setResponseStatus(event, 405);
|
|
106
106
|
return { error: "Method not allowed" };
|
|
@@ -129,7 +129,7 @@ export function createOrgPlugin(): NitroPluginDef {
|
|
|
129
129
|
return { error: "Method not allowed" };
|
|
130
130
|
}
|
|
131
131
|
// Tail is /:id/accept
|
|
132
|
-
if (/^\/[
|
|
132
|
+
if (/^\/[^/]+\/accept\/?$/.test(tail)) {
|
|
133
133
|
if (method !== "POST") {
|
|
134
134
|
setResponseStatus(event, 405);
|
|
135
135
|
return { error: "Method not allowed" };
|
|
@@ -434,7 +434,7 @@ export function expandRelativeUrls(text: string, agentUrl: string): string {
|
|
|
434
434
|
// Path must start at boundary (start, whitespace, or punctuation that isn't
|
|
435
435
|
// ':' — to avoid mangling `https://example.com/foo` or markdown link bodies).
|
|
436
436
|
return text.replace(
|
|
437
|
-
/(^|[\s(
|
|
437
|
+
/(^|[\s([<"'`])(\/[a-z0-9_-][a-z0-9_/?&=%#.,:-]*)/gi,
|
|
438
438
|
(_match, lead, path) => `${lead}${base}${path}`,
|
|
439
439
|
);
|
|
440
440
|
}
|
|
@@ -1855,6 +1855,9 @@ function createAuthGuardFn(): (
|
|
|
1855
1855
|
// the gate below 401s anonymous /_agent-native/* requests before any DB
|
|
1856
1856
|
// query, so the database would never get warmed.
|
|
1857
1857
|
if (p === "/_agent-native/health") return;
|
|
1858
|
+
if (getMethod(event) === "GET" && p.startsWith("/_agent-native/avatar/")) {
|
|
1859
|
+
return;
|
|
1860
|
+
}
|
|
1858
1861
|
if (isPublicPath(normalizedUrl, publicPaths)) return;
|
|
1859
1862
|
if (shouldBypassAuthForBuilderConnect(event, p)) return;
|
|
1860
1863
|
if (isPublicWorkspacePageRequest(event, p, config)) {
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import { FeatureNotConfiguredError } from "./credential-provider.js";
|
|
2
|
+
import {
|
|
3
|
+
getBuilderProxyOrigin,
|
|
4
|
+
resolveBuilderCredentials,
|
|
5
|
+
} from "./credential-provider.js";
|
|
6
|
+
|
|
7
|
+
const DEFAULT_TIMEOUT_MS = 120_000;
|
|
8
|
+
|
|
9
|
+
export interface BuilderDesignSystemIndexFile {
|
|
10
|
+
name: string;
|
|
11
|
+
data: Uint8Array;
|
|
12
|
+
mimeType?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface BuilderDesignSystemIndexOptions {
|
|
16
|
+
projectName?: string;
|
|
17
|
+
description?: string;
|
|
18
|
+
githubRepoUrl?: string;
|
|
19
|
+
connectedProjectId?: string;
|
|
20
|
+
files?: BuilderDesignSystemIndexFile[];
|
|
21
|
+
selection?: Record<string, string[]>;
|
|
22
|
+
devToolsVersion?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface BuilderDesignSystemIndexResult {
|
|
26
|
+
ok: true;
|
|
27
|
+
source: "builder";
|
|
28
|
+
projectId: string;
|
|
29
|
+
jobId: string;
|
|
30
|
+
designSystemId: string;
|
|
31
|
+
suggestedTitle: string | null;
|
|
32
|
+
builderUrl: string;
|
|
33
|
+
status: "in-progress";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface BuilderDesignSystemCredentials {
|
|
37
|
+
privateKey: string;
|
|
38
|
+
publicKey: string;
|
|
39
|
+
userId: string | null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
interface UploadStartResponse {
|
|
43
|
+
uploads?: Array<{ idx: number; uploadUrl: string; uploadToken: string }>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
interface GenerateResponse {
|
|
47
|
+
projectId?: string;
|
|
48
|
+
jobId?: string;
|
|
49
|
+
designSystemId?: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function trimTrailingSlash(value: string): string {
|
|
53
|
+
return value.replace(/\/+$/, "");
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function getBuilderDesignSystemsBaseUrl(): string {
|
|
57
|
+
return (
|
|
58
|
+
process.env.BUILDER_DESIGN_SYSTEMS_BASE_URL ||
|
|
59
|
+
`${trimTrailingSlash(getBuilderProxyOrigin())}/design-systems/v1`
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function getBuilderAppHost(): string {
|
|
64
|
+
return (
|
|
65
|
+
process.env.BUILDER_APP_HOST ||
|
|
66
|
+
process.env.BUILDER_PUBLIC_APP_HOST ||
|
|
67
|
+
"https://builder.io"
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function makeBuilderDesignSystemUrl(
|
|
72
|
+
path: string,
|
|
73
|
+
credentials: BuilderDesignSystemCredentials,
|
|
74
|
+
): URL {
|
|
75
|
+
const base = `${trimTrailingSlash(getBuilderDesignSystemsBaseUrl())}/`;
|
|
76
|
+
const url = new URL(path.replace(/^\/+/, ""), base);
|
|
77
|
+
url.searchParams.set("apiKey", credentials.publicKey);
|
|
78
|
+
if (credentials.userId) url.searchParams.set("userId", credentials.userId);
|
|
79
|
+
return url;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function makeBuilderHeaders(
|
|
83
|
+
credentials: BuilderDesignSystemCredentials,
|
|
84
|
+
): Record<string, string> {
|
|
85
|
+
return {
|
|
86
|
+
Authorization: `Bearer ${credentials.privateKey}`,
|
|
87
|
+
"x-builder-api-key": credentials.publicKey,
|
|
88
|
+
...(credentials.userId ? { "x-builder-user-id": credentials.userId } : {}),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async function resolveBuilderDesignSystemCredentials(): Promise<BuilderDesignSystemCredentials> {
|
|
93
|
+
const credentials = await resolveBuilderCredentials();
|
|
94
|
+
if (!credentials.privateKey || !credentials.publicKey) {
|
|
95
|
+
throw new FeatureNotConfiguredError({
|
|
96
|
+
requiredCredential: "BUILDER_PRIVATE_KEY",
|
|
97
|
+
message:
|
|
98
|
+
"Connect Builder.io before indexing a design system from Figma or code.",
|
|
99
|
+
builderConnectUrl: "/_agent-native/builder/connect",
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
privateKey: credentials.privateKey,
|
|
104
|
+
publicKey: credentials.publicKey,
|
|
105
|
+
userId: credentials.userId ?? null,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function mimeTypeForFile(file: BuilderDesignSystemIndexFile): string {
|
|
110
|
+
if (file.mimeType?.trim()) return file.mimeType.trim();
|
|
111
|
+
const lower = file.name.toLowerCase();
|
|
112
|
+
if (lower.endsWith(".fig")) return "application/octet-stream";
|
|
113
|
+
if (lower.endsWith(".pdf")) return "application/pdf";
|
|
114
|
+
if (lower.endsWith(".md") || lower.endsWith(".markdown"))
|
|
115
|
+
return "text/markdown";
|
|
116
|
+
if (lower.endsWith(".json")) return "application/json";
|
|
117
|
+
if (lower.endsWith(".css")) return "text/css";
|
|
118
|
+
return "text/plain";
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function makeBody(bytes: Uint8Array, mimeType: string): BodyInit {
|
|
122
|
+
return typeof Blob !== "undefined"
|
|
123
|
+
? new Blob([bytes as unknown as BlobPart], { type: mimeType })
|
|
124
|
+
: (bytes as unknown as BodyInit);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async function fetchWithTimeout(
|
|
128
|
+
url: string | URL,
|
|
129
|
+
init: RequestInit,
|
|
130
|
+
timeoutMs = DEFAULT_TIMEOUT_MS,
|
|
131
|
+
): Promise<Response> {
|
|
132
|
+
const controller = new AbortController();
|
|
133
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
134
|
+
try {
|
|
135
|
+
return await fetch(url, { ...init, signal: controller.signal });
|
|
136
|
+
} finally {
|
|
137
|
+
clearTimeout(timer);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async function parseErrorBody(response: Response): Promise<string> {
|
|
142
|
+
const text = await response.text().catch(() => "");
|
|
143
|
+
if (!text) return response.statusText || `HTTP ${response.status}`;
|
|
144
|
+
try {
|
|
145
|
+
const json = JSON.parse(text) as { error?: unknown };
|
|
146
|
+
if (typeof json.error === "string") return json.error;
|
|
147
|
+
if (json.error && typeof json.error === "object") {
|
|
148
|
+
return JSON.stringify(json.error).slice(0, 500);
|
|
149
|
+
}
|
|
150
|
+
} catch {}
|
|
151
|
+
return text.replace(/\s+/g, " ").trim().slice(0, 500);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
async function assertOk(response: Response, label: string): Promise<void> {
|
|
155
|
+
if (response.ok) return;
|
|
156
|
+
throw new Error(
|
|
157
|
+
`${label} (${response.status}): ${await parseErrorBody(response)}`,
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async function uploadToResumableUrl(
|
|
162
|
+
slot: { uploadUrl: string },
|
|
163
|
+
file: BuilderDesignSystemIndexFile,
|
|
164
|
+
): Promise<void> {
|
|
165
|
+
const mimeType = mimeTypeForFile(file);
|
|
166
|
+
const bytes = file.data;
|
|
167
|
+
const start = await fetchWithTimeout(slot.uploadUrl, {
|
|
168
|
+
method: "POST",
|
|
169
|
+
headers: {
|
|
170
|
+
"x-goog-resumable": "start",
|
|
171
|
+
"x-goog-content-length-range": `0,${bytes.byteLength}`,
|
|
172
|
+
"Content-Type": mimeType,
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
await assertOk(start, "Builder design-system upload session failed");
|
|
176
|
+
const sessionUrl = start.headers.get("Location");
|
|
177
|
+
if (!sessionUrl) {
|
|
178
|
+
throw new Error("Builder design-system upload session returned no URL.");
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const response = await fetchWithTimeout(sessionUrl, {
|
|
182
|
+
method: "PUT",
|
|
183
|
+
headers: {
|
|
184
|
+
"Content-Range": `bytes 0-${bytes.byteLength - 1}/${bytes.byteLength}`,
|
|
185
|
+
"Content-Type": mimeType,
|
|
186
|
+
},
|
|
187
|
+
body: makeBody(bytes, mimeType),
|
|
188
|
+
});
|
|
189
|
+
await assertOk(response, "Builder design-system file upload failed");
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function nonEmptyFiles(
|
|
193
|
+
files: BuilderDesignSystemIndexFile[] | undefined,
|
|
194
|
+
): BuilderDesignSystemIndexFile[] {
|
|
195
|
+
return (files ?? []).filter((file) => file.data.byteLength > 0);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export function builderDesignSystemUrl(designSystemId?: string | null): string {
|
|
199
|
+
const host = trimTrailingSlash(getBuilderAppHost());
|
|
200
|
+
return designSystemId
|
|
201
|
+
? `${host}/app/design-system-intelligence/${encodeURIComponent(
|
|
202
|
+
designSystemId,
|
|
203
|
+
)}`
|
|
204
|
+
: `${host}/app/design-system-intelligence`;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export async function startBuilderDesignSystemIndex(
|
|
208
|
+
options: BuilderDesignSystemIndexOptions,
|
|
209
|
+
): Promise<BuilderDesignSystemIndexResult> {
|
|
210
|
+
const files = nonEmptyFiles(options.files);
|
|
211
|
+
const description = options.description?.trim();
|
|
212
|
+
if (description) {
|
|
213
|
+
files.unshift({
|
|
214
|
+
name: "additional-context.txt",
|
|
215
|
+
data: new TextEncoder().encode(description),
|
|
216
|
+
mimeType: "text/plain",
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
if (
|
|
220
|
+
files.length === 0 &&
|
|
221
|
+
!options.githubRepoUrl &&
|
|
222
|
+
!options.connectedProjectId
|
|
223
|
+
) {
|
|
224
|
+
throw new Error(
|
|
225
|
+
"Provide at least one .fig/code/text file or a GitHub repository URL to index with Builder.",
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const credentials = await resolveBuilderDesignSystemCredentials();
|
|
230
|
+
let uploadTokens: string[] = [];
|
|
231
|
+
if (files.length > 0) {
|
|
232
|
+
const uploadStart = await fetchWithTimeout(
|
|
233
|
+
makeBuilderDesignSystemUrl("upload/start", credentials),
|
|
234
|
+
{
|
|
235
|
+
method: "POST",
|
|
236
|
+
headers: {
|
|
237
|
+
...makeBuilderHeaders(credentials),
|
|
238
|
+
"Content-Type": "application/json",
|
|
239
|
+
},
|
|
240
|
+
body: JSON.stringify({
|
|
241
|
+
attachments: files.map((file) => ({
|
|
242
|
+
name: file.name,
|
|
243
|
+
mimetype: mimeTypeForFile(file),
|
|
244
|
+
declaredSize: file.data.byteLength,
|
|
245
|
+
})),
|
|
246
|
+
}),
|
|
247
|
+
},
|
|
248
|
+
);
|
|
249
|
+
await assertOk(uploadStart, "Builder design-system upload start failed");
|
|
250
|
+
const uploadJson = (await uploadStart.json()) as UploadStartResponse;
|
|
251
|
+
const slots = [...(uploadJson.uploads ?? [])].sort((a, b) => a.idx - b.idx);
|
|
252
|
+
if (slots.length !== files.length) {
|
|
253
|
+
throw new Error("Builder did not return upload slots for all files.");
|
|
254
|
+
}
|
|
255
|
+
for (let i = 0; i < slots.length; i++) {
|
|
256
|
+
if (slots[i].idx !== i) {
|
|
257
|
+
throw new Error(`Builder upload slot mismatch: expected ${i}.`);
|
|
258
|
+
}
|
|
259
|
+
await uploadToResumableUrl(slots[i], files[i]);
|
|
260
|
+
}
|
|
261
|
+
uploadTokens = slots.map((slot) => slot.uploadToken);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const generate = await fetchWithTimeout(
|
|
265
|
+
makeBuilderDesignSystemUrl("generate", credentials),
|
|
266
|
+
{
|
|
267
|
+
method: "POST",
|
|
268
|
+
headers: {
|
|
269
|
+
...makeBuilderHeaders(credentials),
|
|
270
|
+
"Content-Type": "application/json",
|
|
271
|
+
},
|
|
272
|
+
body: JSON.stringify({
|
|
273
|
+
uploads: uploadTokens,
|
|
274
|
+
...(options.projectName?.trim()
|
|
275
|
+
? { projectName: options.projectName.trim() }
|
|
276
|
+
: {}),
|
|
277
|
+
...(options.githubRepoUrl?.trim()
|
|
278
|
+
? { githubRepoUrl: options.githubRepoUrl.trim() }
|
|
279
|
+
: {}),
|
|
280
|
+
...(options.connectedProjectId?.trim()
|
|
281
|
+
? { connectedProjectId: options.connectedProjectId.trim() }
|
|
282
|
+
: {}),
|
|
283
|
+
...(options.selection ? { selection: options.selection } : {}),
|
|
284
|
+
...(options.devToolsVersion?.trim()
|
|
285
|
+
? { devToolsVersion: options.devToolsVersion.trim() }
|
|
286
|
+
: {}),
|
|
287
|
+
}),
|
|
288
|
+
},
|
|
289
|
+
);
|
|
290
|
+
await assertOk(generate, "Builder design-system indexing failed");
|
|
291
|
+
const generated = (await generate.json()) as GenerateResponse;
|
|
292
|
+
if (!generated.projectId || !generated.jobId || !generated.designSystemId) {
|
|
293
|
+
throw new Error(
|
|
294
|
+
"Builder design-system indexing returned an incomplete response.",
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
return {
|
|
299
|
+
ok: true,
|
|
300
|
+
source: "builder",
|
|
301
|
+
projectId: generated.projectId,
|
|
302
|
+
jobId: generated.jobId,
|
|
303
|
+
designSystemId: generated.designSystemId,
|
|
304
|
+
suggestedTitle: options.projectName?.trim() || null,
|
|
305
|
+
builderUrl: builderDesignSystemUrl(generated.designSystemId),
|
|
306
|
+
status: "in-progress",
|
|
307
|
+
};
|
|
308
|
+
}
|
|
@@ -383,6 +383,31 @@ function parseBuilderCallbackBoolean(
|
|
|
383
383
|
// inlines them in the DOM. Mirrors SAFE_DATA_IMAGE in sanitize-html.ts.
|
|
384
384
|
export const AVATAR_RASTER_MIME = /^data:image\/(png|jpe?g|gif|webp);/i;
|
|
385
385
|
|
|
386
|
+
export function resolveAvatarEmailParam(
|
|
387
|
+
pathname: string,
|
|
388
|
+
appBasePath = "",
|
|
389
|
+
): string {
|
|
390
|
+
const base = appBasePath.replace(/\/+$/, "");
|
|
391
|
+
const avatarPaths = Array.from(
|
|
392
|
+
new Set([`${base}/_agent-native/avatar/`, "/_agent-native/avatar/"]),
|
|
393
|
+
);
|
|
394
|
+
|
|
395
|
+
for (const avatarPath of avatarPaths) {
|
|
396
|
+
const avatarIndex = pathname.indexOf(avatarPath);
|
|
397
|
+
if (avatarIndex >= 0) {
|
|
398
|
+
return pathname
|
|
399
|
+
.slice(avatarIndex + avatarPath.length)
|
|
400
|
+
.replace(/^\/+/, "")
|
|
401
|
+
.split("/")[0];
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
const firstSegment = pathname.replace(/^\/+/, "").split("/")[0] ?? "";
|
|
406
|
+
if (!firstSegment || firstSegment === "_agent-native") return "";
|
|
407
|
+
if (base && firstSegment === base.replace(/^\/+/, "")) return "";
|
|
408
|
+
return firstSegment;
|
|
409
|
+
}
|
|
410
|
+
|
|
386
411
|
async function detectUsageEngineName(
|
|
387
412
|
event: H3Event,
|
|
388
413
|
userEmail: string | undefined,
|
|
@@ -3010,9 +3035,10 @@ export function createCoreRoutesPlugin(
|
|
|
3010
3035
|
`${P}/avatar`,
|
|
3011
3036
|
defineEventHandler(async (event: H3Event) => {
|
|
3012
3037
|
const method = getMethod(event);
|
|
3013
|
-
const emailParam = (
|
|
3014
|
-
.
|
|
3015
|
-
|
|
3038
|
+
const emailParam = resolveAvatarEmailParam(
|
|
3039
|
+
event.url?.pathname || "",
|
|
3040
|
+
getConfiguredAppBasePath(),
|
|
3041
|
+
);
|
|
3016
3042
|
|
|
3017
3043
|
if (method === "GET") {
|
|
3018
3044
|
if (!emailParam) {
|
|
@@ -386,6 +386,14 @@ export {
|
|
|
386
386
|
deleteBuilderCredentials,
|
|
387
387
|
resolveSecret,
|
|
388
388
|
} from "./credential-provider.js";
|
|
389
|
+
export {
|
|
390
|
+
builderDesignSystemUrl,
|
|
391
|
+
getBuilderDesignSystemsBaseUrl,
|
|
392
|
+
startBuilderDesignSystemIndex,
|
|
393
|
+
type BuilderDesignSystemIndexFile,
|
|
394
|
+
type BuilderDesignSystemIndexOptions,
|
|
395
|
+
type BuilderDesignSystemIndexResult,
|
|
396
|
+
} from "./builder-design-systems.js";
|
|
389
397
|
export {
|
|
390
398
|
getBuilderBranchProjectId,
|
|
391
399
|
isBuilderBranchingEnabled,
|
|
@@ -162,6 +162,17 @@
|
|
|
162
162
|
box-shadow 260ms cubic-bezier(0.32, 0.72, 0, 1);
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
+
.agent-layout-main-surface::before,
|
|
166
|
+
.agent-sidebar-main-surface::before {
|
|
167
|
+
content: "";
|
|
168
|
+
position: absolute;
|
|
169
|
+
inset: 0;
|
|
170
|
+
z-index: 20;
|
|
171
|
+
pointer-events: none;
|
|
172
|
+
border-radius: inherit;
|
|
173
|
+
box-shadow: var(--agent-native-raised-outline);
|
|
174
|
+
}
|
|
175
|
+
|
|
165
176
|
.agent-layout-shell
|
|
166
177
|
:where(.agent-layout-main-surface, .agent-sidebar-main-surface)
|
|
167
178
|
> :first-child
|
|
@@ -213,23 +224,19 @@
|
|
|
213
224
|
.agent-layout-shell > .agent-sidebar-shell > .agent-sidebar-main-surface {
|
|
214
225
|
border-start-start-radius: var(--agent-native-raised-radius);
|
|
215
226
|
border-end-start-radius: var(--agent-native-raised-radius);
|
|
216
|
-
box-shadow:
|
|
217
|
-
var(--agent-native-raised-outline), var(--agent-native-raised-shadow-left);
|
|
227
|
+
box-shadow: var(--agent-native-raised-shadow-left);
|
|
218
228
|
}
|
|
219
229
|
|
|
220
230
|
.agent-sidebar-main-surface[data-agent-sidebar-main-state="open"][data-agent-sidebar-main-position="right"] {
|
|
221
231
|
border-start-end-radius: var(--agent-native-raised-radius);
|
|
222
232
|
border-end-end-radius: var(--agent-native-raised-radius);
|
|
223
|
-
box-shadow:
|
|
224
|
-
var(--agent-native-raised-outline),
|
|
225
|
-
var(--agent-native-raised-shadow-right);
|
|
233
|
+
box-shadow: var(--agent-native-raised-shadow-right);
|
|
226
234
|
}
|
|
227
235
|
|
|
228
236
|
.agent-sidebar-main-surface[data-agent-sidebar-main-state="open"][data-agent-sidebar-main-position="left"] {
|
|
229
237
|
border-start-start-radius: var(--agent-native-raised-radius);
|
|
230
238
|
border-end-start-radius: var(--agent-native-raised-radius);
|
|
231
|
-
box-shadow:
|
|
232
|
-
var(--agent-native-raised-outline), var(--agent-native-raised-shadow-left);
|
|
239
|
+
box-shadow: var(--agent-native-raised-shadow-left);
|
|
233
240
|
}
|
|
234
241
|
}
|
|
235
242
|
|
|
@@ -112,12 +112,12 @@ const PRICING: Array<{ match: RegExp; pricing: ModelPricing }> = [
|
|
|
112
112
|
// ── Google Gemini ───────────────────────────────────────────────────────────
|
|
113
113
|
// Gemini 3 Pro / 3.1 Pro: ~$1.25/$10 per MTok (approximate; verify on billing)
|
|
114
114
|
{
|
|
115
|
-
match: /gemini-3[
|
|
115
|
+
match: /gemini-3[.\-]1-pro/i,
|
|
116
116
|
pricing: { input: 125, output: 1000, cacheRead: 31, cacheWrite: 0 },
|
|
117
117
|
},
|
|
118
118
|
// Gemini 3.5 Flash / 3 Flash: ~$0.15/$0.60 per MTok
|
|
119
119
|
{
|
|
120
|
-
match: /gemini-3[
|
|
120
|
+
match: /gemini-3[.\-][0-9]+-flash/i,
|
|
121
121
|
pricing: { input: 15, output: 60, cacheRead: 4, cacheWrite: 0 },
|
|
122
122
|
},
|
|
123
123
|
// Gemini 2.5 Pro/Flash (catch-all for older 2.5)
|