@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
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom onboarding plugin for Analytics.
|
|
3
|
+
*
|
|
4
|
+
* Overrides the framework's default onboarding plugin to add an optional
|
|
5
|
+
* "Session replay storage" step and register the S3 file upload provider. Must
|
|
6
|
+
* live in server/plugins/ so the framework skips its default onboarding plugin,
|
|
7
|
+
* and all registrations share the same module context as the onboarding route
|
|
8
|
+
* handlers (which read from the same in-memory Map).
|
|
9
|
+
*
|
|
10
|
+
* The step is `required: false` because session replay is opt-in: capturing
|
|
11
|
+
* replays only matters once a site embeds the tracking SDK with replay enabled,
|
|
12
|
+
* so we surface storage setup without forcing it into the onboarding checklist.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { registerFileUploadProvider } from "@agent-native/core/file-upload";
|
|
16
|
+
import {
|
|
17
|
+
createOnboardingPlugin,
|
|
18
|
+
registerOnboardingStep,
|
|
19
|
+
} from "@agent-native/core/onboarding";
|
|
20
|
+
|
|
21
|
+
import { hasRequestReplayStorage } from "../lib/replay-storage.js";
|
|
22
|
+
import { s3FileUploadProvider } from "../lib/s3-upload-provider.js";
|
|
23
|
+
|
|
24
|
+
const basePlugin = createOnboardingPlugin();
|
|
25
|
+
|
|
26
|
+
export default async (nitroApp: any): Promise<void> => {
|
|
27
|
+
// Mount the framework's default onboarding plugin (routes + default steps).
|
|
28
|
+
await basePlugin(nitroApp);
|
|
29
|
+
|
|
30
|
+
// Register S3-compatible file upload provider for session-replay chunks.
|
|
31
|
+
registerFileUploadProvider(s3FileUploadProvider);
|
|
32
|
+
|
|
33
|
+
// Add the optional "Session replay storage" onboarding step.
|
|
34
|
+
registerOnboardingStep({
|
|
35
|
+
id: "replay-storage",
|
|
36
|
+
order: 15,
|
|
37
|
+
required: false,
|
|
38
|
+
title: "Session replay storage",
|
|
39
|
+
description:
|
|
40
|
+
"Store session replay recordings with Builder.io or S3-compatible storage.",
|
|
41
|
+
methods: [
|
|
42
|
+
{
|
|
43
|
+
id: "builder",
|
|
44
|
+
kind: "builder-cli-auth",
|
|
45
|
+
label: "Connect Builder.io",
|
|
46
|
+
description:
|
|
47
|
+
"Builder.io's free tier includes object storage for replay chunks.",
|
|
48
|
+
primary: true,
|
|
49
|
+
badge: "free",
|
|
50
|
+
payload: { scope: "browser" },
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
id: "s3",
|
|
54
|
+
kind: "form",
|
|
55
|
+
label: "Use S3-compatible storage",
|
|
56
|
+
description:
|
|
57
|
+
"AWS S3, Cloudflare R2, DigitalOcean Spaces, MinIO, or any S3-compatible service.",
|
|
58
|
+
payload: {
|
|
59
|
+
writeScope: "workspace",
|
|
60
|
+
fields: [
|
|
61
|
+
{
|
|
62
|
+
key: "S3_ENDPOINT",
|
|
63
|
+
label: "Endpoint URL",
|
|
64
|
+
placeholder: "https://s3.us-east-1.amazonaws.com",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
key: "S3_BUCKET",
|
|
68
|
+
label: "Bucket name",
|
|
69
|
+
placeholder: "my-replays-bucket",
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
key: "S3_ACCESS_KEY_ID",
|
|
73
|
+
label: "Access key ID",
|
|
74
|
+
placeholder: "AKIA...",
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
key: "S3_SECRET_ACCESS_KEY",
|
|
78
|
+
label: "Secret access key",
|
|
79
|
+
secret: true,
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
key: "S3_REGION",
|
|
83
|
+
label: "Region (optional)",
|
|
84
|
+
placeholder: "us-east-1",
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
key: "S3_PUBLIC_BASE_URL",
|
|
88
|
+
label: "Public base URL (optional)",
|
|
89
|
+
placeholder: "https://cdn.example.com",
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
isComplete: hasRequestReplayStorage,
|
|
96
|
+
});
|
|
97
|
+
};
|
|
@@ -2069,6 +2069,8 @@ async function startNativeFullscreenRecording(
|
|
|
2069
2069
|
.then(() => {
|
|
2070
2070
|
pausedAt = at;
|
|
2071
2071
|
emitState();
|
|
2072
|
+
console.log("[clips-recorder] native pause: pausing transcription");
|
|
2073
|
+
void transcriptionCapture?.pause().catch(() => {});
|
|
2072
2074
|
})
|
|
2073
2075
|
.catch((err) => {
|
|
2074
2076
|
console.warn("[clips-recorder] native pause failed:", err);
|
|
@@ -2076,6 +2078,8 @@ async function startNativeFullscreenRecording(
|
|
|
2076
2078
|
}),
|
|
2077
2079
|
listen("clips:recorder-resume", () => {
|
|
2078
2080
|
if (pausedAt == null) return;
|
|
2081
|
+
// Only resume transcription once the recorder actually resumed, so a
|
|
2082
|
+
// rejected IPC can't leave transcription running over a paused recording.
|
|
2079
2083
|
invoke("native_fullscreen_recording_resume")
|
|
2080
2084
|
.then(() => {
|
|
2081
2085
|
if (pausedAt != null) {
|
|
@@ -2083,6 +2087,8 @@ async function startNativeFullscreenRecording(
|
|
|
2083
2087
|
pausedAt = null;
|
|
2084
2088
|
}
|
|
2085
2089
|
emitState();
|
|
2090
|
+
console.log("[clips-recorder] native resume: resuming transcription");
|
|
2091
|
+
void transcriptionCapture?.resume().catch(() => {});
|
|
2086
2092
|
})
|
|
2087
2093
|
.catch((err) => {
|
|
2088
2094
|
console.warn("[clips-recorder] native resume failed:", err);
|
|
@@ -2125,6 +2131,12 @@ async function startNativeFullscreenRecording(
|
|
|
2125
2131
|
if (stopped && transcriptionCapture) {
|
|
2126
2132
|
void transcriptionCapture.cancel().catch(() => {});
|
|
2127
2133
|
transcriptionCapture = null;
|
|
2134
|
+
} else if (pausedAt != null && transcriptionCapture) {
|
|
2135
|
+
// The user paused while the engine was still starting; honor it now.
|
|
2136
|
+
console.log(
|
|
2137
|
+
"[clips-recorder] native: paused during startup, pausing transcription",
|
|
2138
|
+
);
|
|
2139
|
+
void transcriptionCapture.pause().catch(() => {});
|
|
2128
2140
|
} else if (
|
|
2129
2141
|
wantsAudio &&
|
|
2130
2142
|
!transcriptionCapture &&
|
|
@@ -2885,6 +2897,8 @@ async function startRecordingInner(
|
|
|
2885
2897
|
recorder.pause();
|
|
2886
2898
|
pausedAt = Date.now();
|
|
2887
2899
|
emitState(true);
|
|
2900
|
+
console.log("[clips-recorder] recorder pause: pausing transcription");
|
|
2901
|
+
void transcriptionCapture?.pause().catch(() => {});
|
|
2888
2902
|
} catch {
|
|
2889
2903
|
// ignore
|
|
2890
2904
|
}
|
|
@@ -2897,6 +2911,10 @@ async function startRecordingInner(
|
|
|
2897
2911
|
if (pausedAt) accumulatedPauseMs += Date.now() - pausedAt;
|
|
2898
2912
|
pausedAt = null;
|
|
2899
2913
|
emitState(false);
|
|
2914
|
+
console.log(
|
|
2915
|
+
"[clips-recorder] recorder resume: resuming transcription",
|
|
2916
|
+
);
|
|
2917
|
+
void transcriptionCapture?.resume().catch(() => {});
|
|
2900
2918
|
} catch {
|
|
2901
2919
|
// ignore
|
|
2902
2920
|
}
|
|
@@ -2951,6 +2969,12 @@ async function startRecordingInner(
|
|
|
2951
2969
|
if (stopped && transcriptionCapture) {
|
|
2952
2970
|
void transcriptionCapture.cancel().catch(() => {});
|
|
2953
2971
|
transcriptionCapture = null;
|
|
2972
|
+
} else if (pausedAt != null && transcriptionCapture) {
|
|
2973
|
+
// The user paused while the engine was still starting; honor it now.
|
|
2974
|
+
console.log(
|
|
2975
|
+
"[clips-recorder] recorder: paused during startup, pausing transcription",
|
|
2976
|
+
);
|
|
2977
|
+
void transcriptionCapture.pause().catch(() => {});
|
|
2954
2978
|
} else if (
|
|
2955
2979
|
wantsAudio &&
|
|
2956
2980
|
!transcriptionCapture &&
|
|
@@ -41,6 +41,10 @@ export interface CapturedTranscript {
|
|
|
41
41
|
export interface TranscriptionCapture {
|
|
42
42
|
stop(): Promise<CapturedTranscript>;
|
|
43
43
|
cancel(): Promise<void>;
|
|
44
|
+
/** Suspend the audio engine without discarding the captured transcript. */
|
|
45
|
+
pause(): Promise<void>;
|
|
46
|
+
/** Restart the audio engine after a `pause()`. */
|
|
47
|
+
resume(): Promise<void>;
|
|
44
48
|
}
|
|
45
49
|
|
|
46
50
|
interface SpeechRecognitionResultLike {
|
|
@@ -154,6 +158,7 @@ async function startBrowserTranscriptionCapture(): Promise<TranscriptionCapture
|
|
|
154
158
|
const recognition = new Ctor();
|
|
155
159
|
let disposed = false;
|
|
156
160
|
let stopped = false;
|
|
161
|
+
let paused = false;
|
|
157
162
|
const transcriptBuffer = createWebSpeechTranscriptBuffer();
|
|
158
163
|
let stopResolver: ((value: CapturedTranscript) => void) | null = null;
|
|
159
164
|
let settleTimer: ReturnType<typeof window.setTimeout> | null = null;
|
|
@@ -195,11 +200,13 @@ async function startBrowserTranscriptionCapture(): Promise<TranscriptionCapture
|
|
|
195
200
|
|
|
196
201
|
recognition.onend = () => {
|
|
197
202
|
if (disposed) return;
|
|
198
|
-
transcriptBuffer.commitSession({ preserveInterim: stopped });
|
|
203
|
+
transcriptBuffer.commitSession({ preserveInterim: stopped || paused });
|
|
199
204
|
if (stopped) {
|
|
200
205
|
settleStop();
|
|
201
206
|
return;
|
|
202
207
|
}
|
|
208
|
+
// While paused, keep the committed transcript but don't restart the engine.
|
|
209
|
+
if (paused) return;
|
|
203
210
|
try {
|
|
204
211
|
recognition.start();
|
|
205
212
|
} catch (err) {
|
|
@@ -245,6 +252,29 @@ async function startBrowserTranscriptionCapture(): Promise<TranscriptionCapture
|
|
|
245
252
|
// ignore
|
|
246
253
|
}
|
|
247
254
|
},
|
|
255
|
+
async pause() {
|
|
256
|
+
if (disposed || stopped || paused) return;
|
|
257
|
+
paused = true;
|
|
258
|
+
console.log("[clips-recorder] transcription paused (web-speech)");
|
|
259
|
+
try {
|
|
260
|
+
recognition.stop();
|
|
261
|
+
} catch {
|
|
262
|
+
// ignore
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
async resume() {
|
|
266
|
+
if (disposed || stopped || !paused) return;
|
|
267
|
+
paused = false;
|
|
268
|
+
console.log("[clips-recorder] transcription resumed (web-speech)");
|
|
269
|
+
try {
|
|
270
|
+
recognition.start();
|
|
271
|
+
} catch (err) {
|
|
272
|
+
console.warn(
|
|
273
|
+
"[clips-recorder] Web Speech transcription resume failed:",
|
|
274
|
+
err,
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
},
|
|
248
278
|
};
|
|
249
279
|
}
|
|
250
280
|
|
|
@@ -260,6 +290,13 @@ export async function startTranscriptionCapture(
|
|
|
260
290
|
const lines: string[] = [];
|
|
261
291
|
const segments: SourcedTranscriptSegment[] = [];
|
|
262
292
|
let disposed = false;
|
|
293
|
+
let paused = false;
|
|
294
|
+
let desiredPaused = false;
|
|
295
|
+
let transitioning = false;
|
|
296
|
+
// When a pause stops the engine, Whisper still flushes trailing finals
|
|
297
|
+
// asynchronously. Track when those are expected to have landed so a stop
|
|
298
|
+
// soon after a pause waits for them instead of dropping the last words.
|
|
299
|
+
let pauseFinalsSettleUntil = 0;
|
|
263
300
|
const unlistens: UnlistenFn[] = [];
|
|
264
301
|
|
|
265
302
|
const cleanup = () => {
|
|
@@ -299,8 +336,59 @@ export async function startTranscriptionCapture(
|
|
|
299
336
|
: null;
|
|
300
337
|
}
|
|
301
338
|
|
|
339
|
+
// Pause/resume run fire-and-forget from the recorder, so a quick
|
|
340
|
+
// pause→resume can arrive while a transition is still awaiting the engine.
|
|
341
|
+
// Track the desired state and re-apply once the in-flight transition settles
|
|
342
|
+
// so the last request always wins (instead of being dropped).
|
|
343
|
+
const applyAudioState = async () => {
|
|
344
|
+
if (transitioning || disposed || desiredPaused === paused) return;
|
|
345
|
+
transitioning = true;
|
|
346
|
+
try {
|
|
347
|
+
if (desiredPaused) {
|
|
348
|
+
await stopTranscriptionEngine(engine);
|
|
349
|
+
paused = true;
|
|
350
|
+
pauseFinalsSettleUntil = Date.now() + WHISPER_STOP_SETTLE_MS;
|
|
351
|
+
console.log(`[clips-recorder] transcription paused (${engine})`);
|
|
352
|
+
} else {
|
|
353
|
+
engine = await startTranscriptionEngine({ mic, captureSystem });
|
|
354
|
+
// stop()/cancel() can run during the await above; if it did, the new
|
|
355
|
+
// engine would leak (mic/system capture stays live). Tear it down.
|
|
356
|
+
if (disposed) {
|
|
357
|
+
await stopTranscriptionEngine(engine).catch(() => {});
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
paused = false;
|
|
361
|
+
console.log(`[clips-recorder] transcription resumed (${engine})`);
|
|
362
|
+
}
|
|
363
|
+
} catch (err) {
|
|
364
|
+
// Transition failed. Keep `desiredPaused` as the still-unmet intent (don't
|
|
365
|
+
// reset it) so the next pause/resume toggle retries and converges, and
|
|
366
|
+
// return early so we don't busy-loop re-applying a persistently failing
|
|
367
|
+
// transition. `paused` still reflects the real engine state.
|
|
368
|
+
console.warn(
|
|
369
|
+
`[clips-recorder] transcription ${desiredPaused ? "pause" : "resume"} failed; engine still ${paused ? "paused" : "live"}:`,
|
|
370
|
+
err,
|
|
371
|
+
);
|
|
372
|
+
// `finally` resets `transitioning`; returning skips the auto re-apply.
|
|
373
|
+
return;
|
|
374
|
+
} finally {
|
|
375
|
+
transitioning = false;
|
|
376
|
+
}
|
|
377
|
+
// Re-apply in case the desired state changed mid-transition.
|
|
378
|
+
void applyAudioState();
|
|
379
|
+
};
|
|
380
|
+
|
|
302
381
|
return {
|
|
303
382
|
async stop() {
|
|
383
|
+
// Already paused: the engine is stopped, but the pause-time flush may
|
|
384
|
+
// still be in flight. Wait out any remaining settle window so trailing
|
|
385
|
+
// finals land before we drop the listener.
|
|
386
|
+
if (paused) {
|
|
387
|
+
const remaining = pauseFinalsSettleUntil - Date.now();
|
|
388
|
+
if (remaining > 0) await wait(remaining);
|
|
389
|
+
cleanup();
|
|
390
|
+
return captured();
|
|
391
|
+
}
|
|
304
392
|
try {
|
|
305
393
|
await stopTranscriptionEngine(engine);
|
|
306
394
|
} catch (err) {
|
|
@@ -314,12 +402,24 @@ export async function startTranscriptionCapture(
|
|
|
314
402
|
return captured();
|
|
315
403
|
},
|
|
316
404
|
async cancel() {
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
405
|
+
if (!paused) {
|
|
406
|
+
try {
|
|
407
|
+
await stopTranscriptionEngine(engine);
|
|
408
|
+
} catch {
|
|
409
|
+
// ignore
|
|
410
|
+
}
|
|
321
411
|
}
|
|
322
412
|
cleanup();
|
|
323
413
|
},
|
|
414
|
+
async pause() {
|
|
415
|
+
if (disposed) return;
|
|
416
|
+
desiredPaused = true;
|
|
417
|
+
await applyAudioState();
|
|
418
|
+
},
|
|
419
|
+
async resume() {
|
|
420
|
+
if (disposed) return;
|
|
421
|
+
desiredPaused = false;
|
|
422
|
+
await applyAudioState();
|
|
423
|
+
},
|
|
324
424
|
};
|
|
325
425
|
}
|
|
@@ -52,7 +52,7 @@ function imageAltCandidates({
|
|
|
52
52
|
const candidates: ImageAltCandidate[] = [];
|
|
53
53
|
|
|
54
54
|
const markdownImagePattern = new RegExp(
|
|
55
|
-
`!\\[[^\\]]*\\]\\((${escapedUrl})(\\s
|
|
55
|
+
`!\\[[^\\]]*\\]\\((${escapedUrl})(\\s+"[^"]*")?\\)`,
|
|
56
56
|
"g",
|
|
57
57
|
);
|
|
58
58
|
for (const match of content.matchAll(markdownImagePattern)) {
|
|
@@ -115,7 +115,7 @@ function inlineMarkdownToHtml(text: string): string {
|
|
|
115
115
|
.replace(/\*\*([^*]+)\*\*/g, "<strong>$1</strong>")
|
|
116
116
|
.replace(/__([^_]+)__/g, "<strong>$1</strong>")
|
|
117
117
|
.replace(/~~([^~]+)~~/g, "<s>$1</s>")
|
|
118
|
-
.replace(/(^|[
|
|
118
|
+
.replace(/(^|[^*])\*([^*]+)\*/g, "$1<em>$2</em>")
|
|
119
119
|
.replace(/(^|[^_])_([^_]+)_/g, "$1<em>$2</em>");
|
|
120
120
|
}
|
|
121
121
|
|
|
@@ -145,18 +145,18 @@ Returns CSS custom properties, colors, fonts, Google Fonts links, theme-color, O
|
|
|
145
145
|
### Source: GitHub Repository
|
|
146
146
|
|
|
147
147
|
```bash
|
|
148
|
-
pnpm action
|
|
148
|
+
pnpm action index-design-system-with-builder --githubRepoUrl "https://github.com/acme/ui"
|
|
149
149
|
```
|
|
150
150
|
|
|
151
|
-
|
|
151
|
+
Starts Builder design-system indexing for the repository. Builder is the source of truth for the indexed brand kit, generated docs, and usage guidance. If Builder is not connected, stop and ask the user to connect Builder.
|
|
152
152
|
|
|
153
153
|
### Source: Local Code Files
|
|
154
154
|
|
|
155
155
|
```bash
|
|
156
|
-
pnpm action
|
|
156
|
+
pnpm action index-design-system-with-builder --codeFiles '[{"filename":"globals.css","content":"..."}]'
|
|
157
157
|
```
|
|
158
158
|
|
|
159
|
-
|
|
159
|
+
Uploads code/design files to Builder and starts design-system indexing. Do not create a local design system from uploaded code files unless the user explicitly asks for a manual local fallback.
|
|
160
160
|
|
|
161
161
|
### Source: Documents (DOCX, PPTX, PDF)
|
|
162
162
|
|
|
@@ -192,20 +192,10 @@ effects to CSS box-shadow, and text styles to font tokens; snap spacing to a
|
|
|
192
192
|
4/8px scale. If no Figma MCP is connected, ask the user to paste the token
|
|
193
193
|
values or describe the file.
|
|
194
194
|
|
|
195
|
-
**When the user uploads a raw `.fig` file**,
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
pnpm action import-figma-file --fileBase64 "<base64 of the .fig>" # or --fileDataUrl
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
It decodes the binary `.fig`, returns `frames` (each Figma frame rendered to
|
|
203
|
-
HTML), an extracted `designSystem` (colors with assigned roles, typography,
|
|
204
|
-
spacing, radius, shadows — ready for `DesignSystemData`), and image metadata.
|
|
205
|
-
It's read-only/preview: review the result, then call `create-design-system`
|
|
206
|
-
with the `designSystem` and/or `create-design` + `generate-design` with the
|
|
207
|
-
`frames`. The full `palette` is returned too, so re-assign a color role if a
|
|
208
|
-
heuristic looks off.
|
|
195
|
+
**When the user uploads a raw `.fig` file**, send it to Builder design-system
|
|
196
|
+
indexing through the setup page upload route. Do not parse `.fig` files locally
|
|
197
|
+
and do not call `create-design-system` from raw `.fig` output; Builder owns the
|
|
198
|
+
indexed brand kit, generated docs, and usage guidance.
|
|
209
199
|
|
|
210
200
|
### Source: Brand Analysis (combines website + notes)
|
|
211
201
|
|
|
@@ -28,6 +28,9 @@ iframe-backed screens on the infinite canvas.
|
|
|
28
28
|
new flow state.
|
|
29
29
|
- Flow visualization is just multiple URL states: `/checkout?step=shipping`,
|
|
30
30
|
`/checkout?step=payment`, `/checkout?step=done`, etc.
|
|
31
|
+
- When the user gives a named flow or numbered screen list, preserve that order
|
|
32
|
+
and create one screen per URL/path. Shorthand like
|
|
33
|
+
`localhost:1234/onboarding/1` means `http://localhost:1234/onboarding/1`.
|
|
31
34
|
|
|
32
35
|
## Required Local Bridge
|
|
33
36
|
|
|
@@ -92,6 +95,20 @@ pnpm action add-localhost-screens '{
|
|
|
92
95
|
}'
|
|
93
96
|
```
|
|
94
97
|
|
|
98
|
+
For a numbered flow the user describes in chat, keep the labels and order:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
pnpm action add-localhost-screens '{
|
|
102
|
+
"designId": "<design-id>",
|
|
103
|
+
"connectionId": "<connection-id>",
|
|
104
|
+
"routes": [
|
|
105
|
+
{ "url": "localhost:1234/onboarding/1", "title": "Screen 1" },
|
|
106
|
+
{ "url": "localhost:1234/onboarding/2", "title": "Screen 2" },
|
|
107
|
+
{ "url": "localhost:1234/onboarding/3", "title": "Screen 3" }
|
|
108
|
+
]
|
|
109
|
+
}'
|
|
110
|
+
```
|
|
111
|
+
|
|
95
112
|
If no `routes` or `paths` are supplied, `add-localhost-screens` uses every route
|
|
96
113
|
from the latest localhost manifest. Use `paths` for a concise flow:
|
|
97
114
|
|
|
@@ -67,14 +67,40 @@ function normalizeBaseUrl(value: string): string {
|
|
|
67
67
|
return parsed.toString().replace(/\/$/, "");
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
function
|
|
70
|
+
function withLocalhostProtocol(value: string): string {
|
|
71
|
+
const raw = value.trim();
|
|
72
|
+
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(raw)) return raw;
|
|
73
|
+
if (
|
|
74
|
+
/^(localhost|127(?:\.\d{1,3}){3}|0\.0\.0\.0|\[::1\]|::1)(?::\d+)?(?:[/?#]|$)/i.test(
|
|
75
|
+
raw,
|
|
76
|
+
)
|
|
77
|
+
) {
|
|
78
|
+
return `http://${raw}`;
|
|
79
|
+
}
|
|
80
|
+
return raw;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function routeUrl(
|
|
84
|
+
baseUrl: string,
|
|
85
|
+
route: { path?: string; url?: string },
|
|
86
|
+
) {
|
|
71
87
|
const raw = route.url ?? route.path ?? "/";
|
|
72
|
-
|
|
88
|
+
let parsed: URL;
|
|
89
|
+
try {
|
|
90
|
+
parsed = new URL(withLocalhostProtocol(raw), `${baseUrl}/`);
|
|
91
|
+
} catch {
|
|
92
|
+
throw new Error(
|
|
93
|
+
`Invalid localhost screen URL "${raw}". Use a path like /pricing or an http(s) localhost URL.`,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
97
|
+
throw new Error(`Localhost screen URL must be an http(s) URL: ${raw}`);
|
|
98
|
+
}
|
|
73
99
|
parsed.hash = "";
|
|
74
100
|
return parsed.toString();
|
|
75
101
|
}
|
|
76
102
|
|
|
77
|
-
function pathFromUrl(baseUrl: string, url: string, fallback?: string) {
|
|
103
|
+
export function pathFromUrl(baseUrl: string, url: string, fallback?: string) {
|
|
78
104
|
try {
|
|
79
105
|
const parsed = new URL(url);
|
|
80
106
|
const base = new URL(baseUrl);
|
|
@@ -87,10 +113,11 @@ function pathFromUrl(baseUrl: string, url: string, fallback?: string) {
|
|
|
87
113
|
return fallback ?? "/";
|
|
88
114
|
}
|
|
89
115
|
|
|
90
|
-
function slugForPath(pathOrUrl: string) {
|
|
116
|
+
export function slugForPath(pathOrUrl: string) {
|
|
91
117
|
const parsed = (() => {
|
|
92
118
|
try {
|
|
93
|
-
|
|
119
|
+
const url = new URL(withLocalhostProtocol(pathOrUrl));
|
|
120
|
+
return url.pathname + url.search;
|
|
94
121
|
} catch {
|
|
95
122
|
return pathOrUrl;
|
|
96
123
|
}
|