@agent-native/core 0.80.11 → 0.81.0
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 +1 -1
- package/corpus/core/CHANGELOG.md +47 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/cli/design-connect.ts +419 -19
- package/corpus/core/src/client/ConnectBuilderCard.tsx +1 -0
- package/corpus/core/src/client/chat/index.ts +1 -0
- package/corpus/core/src/client/chat/run-recovery.tsx +9 -7
- package/corpus/core/src/client/chat-view-transition.ts +33 -2
- package/corpus/core/src/client/composer/PromptComposer.tsx +21 -2
- package/corpus/core/src/client/index.ts +1 -0
- package/corpus/core/src/client/org/OrgSwitcher.tsx +26 -4
- package/corpus/core/src/client/sharing/ShareButton.tsx +3 -3
- package/corpus/core/src/client/use-agent-chat-home-handoff.ts +31 -3
- package/corpus/core/src/db/client.ts +29 -2
- package/corpus/core/src/provider-api/index.ts +29 -0
- package/corpus/core/src/server/core-routes-plugin.ts +58 -20
- package/corpus/core/src/styles/agent-native.css +54 -0
- package/corpus/core/src/usage/store.ts +2 -2
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +118 -10
- package/corpus/templates/analytics/app/components/layout/layout-route-policy.ts +7 -0
- package/corpus/templates/analytics/app/global.css +8 -0
- package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +7 -1
- package/corpus/templates/analytics/app/lib/chat-handoff.ts +34 -0
- package/corpus/templates/analytics/app/pages/Ask.tsx +9 -18
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +2 -2
- package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +109 -21
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +4 -6
- package/corpus/templates/analytics/changelog/2026-06-30-ask-opens-a-fresh-chat-unless-you-were-just-chatting-and-das.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-30-dashboard-email-reports-are-more-reliable-and-use-cleaner.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-30-dashboard-toolbar-controls-use-a-quieter-share-button-and-ve.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-30-session-replay-rows-show-whole-minute-durations-in-the-playl.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-30-session-replays-now-render-captured-styling-and-keep-the-eve.md +6 -0
- package/corpus/templates/analytics/server/jobs/dashboard-report.ts +16 -3
- package/corpus/templates/analytics/server/lib/dashboard-report.ts +31 -14
- package/corpus/templates/assets/actions/open-asset-picker.ts +9 -0
- package/corpus/templates/assets/app/global.css +15 -0
- package/corpus/templates/assets/app/hooks/use-navigation-state.ts +4 -0
- package/corpus/templates/assets/app/routes/library.tsx +90 -16
- package/corpus/templates/assets/changelog/2026-06-30-the-assets-picker-now-supports-a-vertical-embedded-layout-fo.md +6 -0
- package/corpus/templates/clips/actions/finalize-recording.ts +1 -12
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +10 -5
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +6 -8
- package/corpus/templates/clips/changelog/2026-06-30-extension-save-recovery-avoids-false-upload-failures.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-30-longer-chrome-extension-recordings-now-keep-saving-reliably-.md +6 -0
- package/corpus/templates/clips/chrome-extension/public/manifest.json +1 -1
- package/corpus/templates/clips/chrome-extension/src/background.ts +19 -10
- package/corpus/templates/clips/chrome-extension/src/content-script.ts +38 -12
- package/corpus/templates/clips/chrome-extension/src/finalize-recovery.ts +224 -0
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +119 -16
- package/corpus/templates/clips/chrome-extension/src/overlay.ts +16 -0
- package/corpus/templates/clips/server/lib/recording-upload-state.ts +48 -0
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/abort.post.ts +9 -1
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +63 -13
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/status.get.ts +74 -0
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +32 -0
- package/corpus/templates/design/AGENTS.md +27 -0
- package/corpus/templates/design/CODE_NATIVE_DESIGN_STUDIO_IMPLEMENTATION_PLAN.md +1 -1
- package/corpus/templates/design/DESIGN-STUDIO-PLAN.md +5 -5
- package/corpus/templates/design/actions/apply-component-prop-edit.ts +63 -20
- package/corpus/templates/design/actions/apply-motion-edit.ts +67 -69
- package/corpus/templates/design/actions/apply-shader-fill.ts +148 -56
- package/corpus/templates/design/actions/capture-design-state.ts +27 -4
- package/corpus/templates/design/actions/connect-localhost.ts +59 -22
- package/corpus/templates/design/actions/export-zip.ts +23 -8
- package/corpus/templates/design/actions/generate-design.ts +53 -1
- package/corpus/templates/design/actions/get-component-details.ts +5 -19
- package/corpus/templates/design/actions/get-motion-timeline.ts +135 -10
- package/corpus/templates/design/actions/grant-localhost-write-consent.ts +116 -0
- package/corpus/templates/design/actions/import-design-tokens.ts +521 -0
- package/corpus/templates/design/actions/index-design-tokens.ts +10 -1
- package/corpus/templates/design/actions/insert-design-native-asset.ts +268 -0
- package/corpus/templates/design/actions/insert-figma-library-asset.ts +233 -0
- package/corpus/templates/design/actions/list-design-extensions.ts +32 -10
- package/corpus/templates/design/actions/list-design-native-assets.ts +105 -0
- package/corpus/templates/design/actions/list-figma-library-assets.ts +292 -0
- package/corpus/templates/design/actions/migrate-board-objects-to-file.ts +238 -0
- package/corpus/templates/design/actions/navigate.ts +18 -3
- package/corpus/templates/design/actions/provider-api-catalog.ts +2 -2
- package/corpus/templates/design/actions/provider-api-docs.ts +1 -1
- package/corpus/templates/design/actions/provider-api-request.ts +3 -3
- package/corpus/templates/design/actions/revoke-localhost-write-consent.ts +48 -0
- package/corpus/templates/design/actions/run-design-audit.ts +53 -4
- package/corpus/templates/design/actions/run-design-extension-action.ts +1 -1
- package/corpus/templates/design/actions/view-screen.ts +1 -1
- package/corpus/templates/design/actions/write-local-file.ts +213 -0
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +230 -3308
- package/corpus/templates/design/app/components/design/DesignEditorSkeleton.tsx +30 -20
- package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +776 -287
- package/corpus/templates/design/app/components/design/EditPanel.tsx +212 -208
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +14 -2
- package/corpus/templates/design/app/components/design/LocalhostWriteConsentDialog.tsx +161 -0
- package/corpus/templates/design/app/components/design/MotionDock.tsx +235 -266
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +490 -55
- package/corpus/templates/design/app/components/design/ReviewPanel.tsx +43 -62
- package/corpus/templates/design/app/components/design/StatesPanel.tsx +34 -61
- package/corpus/templates/design/app/components/design/TokensPanel.tsx +251 -0
- package/corpus/templates/design/app/components/design/bridge/codegen.ts +125 -0
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +4037 -0
- package/corpus/templates/design/app/components/design/bridge/embedded-wheel.bridge.ts +62 -0
- package/corpus/templates/design/app/components/design/bridge/hit-test.bridge.ts +272 -0
- package/corpus/templates/design/app/components/design/bridge/nav.bridge.ts +116 -0
- package/corpus/templates/design/app/components/design/bridge/sample.bridge.ts +24 -0
- package/corpus/templates/design/app/components/design/bridge/shader-fill-preview.bridge.ts +78 -0
- package/corpus/templates/design/app/components/design/bridge/tsconfig.json +17 -0
- package/corpus/templates/design/app/components/design/bridge/tweak.bridge.ts +28 -0
- package/corpus/templates/design/app/components/design/bridge/zoom.bridge.ts +43 -0
- package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +45 -16
- package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +88 -9
- package/corpus/templates/design/app/components/editor/PromptDialog.tsx +94 -9
- package/corpus/templates/design/app/components/layout/Layout.tsx +19 -3
- package/corpus/templates/design/app/components/layout/Sidebar.tsx +1 -1
- package/corpus/templates/design/app/global.css +7 -0
- package/corpus/templates/design/app/hooks/use-navigation-state.ts +23 -0
- package/corpus/templates/design/app/i18n/zh-TW.ts +21 -0
- package/corpus/templates/design/app/i18n-data.ts +358 -0
- package/corpus/templates/design/app/lib/pending-generation.ts +1 -0
- package/corpus/templates/design/app/pages/DesignEditor.tsx +2402 -499
- package/corpus/templates/design/app/pages/Index.tsx +5 -1
- package/corpus/templates/design/changelog/2026-06-30-applying-the-one-click-fix-for-a-small-tap-target-accessibil.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-canvas-creation-screen-dragging-undo-redo-and-image-fill-edi.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-component-prop-edits-and-shader-fills-now-preserve-rapid-sam.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-can-browse-figma-library-components-and-insert-them-i.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-now-has-a-figma-style-left-rail-for-file-agent-assets.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-now-has-native-components-embedded-media-and-figma-im.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-preview-now-includes-a-publish-app-waitlist-option-fr.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-s-left-rail-now-matches-the-sidebar-chrome-and-uses-t.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-s-tools-create-menu-now-stays-compact-instead-of-rend.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-starter-prompts-now-begin-generating-immediately-and-.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-design-tools-now-use-a-quieter-figma-style-list-layout.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-drawing-rectangles-on-the-all-screens-canvas-no-longer-flash.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-fixed-code-native-design-studio-edits-so-component-props-mot.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-fixed-visual-editing-hover-overlays-and-spacing-handles-so-s.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-motion-edits-now-save-automatically-without-a-separate-css-a.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-motion-timelines-now-reopen-as-editable-tracks-after-writing.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-new-design-prompts-with-uploaded-screenshots-work-reliably-o.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-screen-previews-in-all-screens-view-now-keep-rounded-outline.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-selection-outlines-now-sit-flush-on-rectangles-drawn-directl.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-share-options-use-a-tighter-design-editor-popover-with-compa.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-the-collapsed-motion-panel-now-stays-tucked-under-the-left-s.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-the-design-inspector-now-shows-states-and-review-in-a-tighte.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-the-sidebar-keeps-the-organization-picker-space-stable-while.md +6 -0
- package/corpus/templates/design/changelog/2026-06-30-tokens-can-now-be-imported-from-pasted-notes-code-files-fold.md +6 -0
- package/corpus/templates/design/e2e/helpers.ts +168 -65
- package/corpus/templates/design/package.json +3 -1
- package/corpus/templates/design/server/db/schema.ts +23 -0
- package/corpus/templates/design/server/handlers/uploads.ts +22 -1
- package/corpus/templates/design/server/lib/provider-api.ts +7 -4
- package/corpus/templates/design/server/lib/verify-write-grant.ts +108 -0
- package/corpus/templates/design/server/plugins/db.ts +39 -0
- package/corpus/templates/design/server/register-secrets.ts +38 -0
- package/corpus/templates/design/shared/board-file.ts +228 -0
- package/corpus/templates/design/shared/board-objects.ts +288 -0
- package/corpus/templates/design/shared/code-layer.ts +52 -0
- package/corpus/templates/design/shared/motion-compiler.ts +58 -7
- package/corpus/templates/design/shared/motion-timeline.ts +2 -2
- package/corpus/templates/design/tsconfig.json +2 -1
- package/corpus/templates/slides/AGENTS.md +9 -0
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +4 -0
- package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +4 -24
- package/corpus/templates/slides/app/lib/export-pdf-client.ts +29 -20
- package/corpus/templates/slides/app/lib/export-pptx-client.ts +365 -0
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +12 -9
- package/corpus/templates/slides/app/vite-env.d.ts +18 -0
- package/corpus/templates/slides/changelog/2026-06-30-powerpoint-downloads-now-preserve-the-rendered-slide-layout-.md +6 -0
- package/corpus/templates/slides/changelog/2026-06-30-unavailable-decks-open-in-a-cleaner-full-height-centered-sta.md +6 -0
- package/corpus/templates/slides/package.json +1 -0
- package/corpus/templates/slides/vite.config.ts +1 -0
- package/dist/cli/design-connect.d.ts +25 -0
- package/dist/cli/design-connect.d.ts.map +1 -1
- package/dist/cli/design-connect.js +357 -18
- package/dist/cli/design-connect.js.map +1 -1
- package/dist/client/ConnectBuilderCard.d.ts.map +1 -1
- package/dist/client/ConnectBuilderCard.js +1 -0
- package/dist/client/ConnectBuilderCard.js.map +1 -1
- package/dist/client/chat/index.d.ts +1 -1
- package/dist/client/chat/index.d.ts.map +1 -1
- package/dist/client/chat/index.js +1 -1
- package/dist/client/chat/index.js.map +1 -1
- package/dist/client/chat/run-recovery.d.ts.map +1 -1
- package/dist/client/chat/run-recovery.js +5 -5
- package/dist/client/chat/run-recovery.js.map +1 -1
- package/dist/client/chat-view-transition.d.ts +6 -0
- package/dist/client/chat-view-transition.d.ts.map +1 -1
- package/dist/client/chat-view-transition.js +23 -2
- package/dist/client/chat-view-transition.js.map +1 -1
- package/dist/client/composer/PromptComposer.d.ts.map +1 -1
- package/dist/client/composer/PromptComposer.js +3 -2
- package/dist/client/composer/PromptComposer.js.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
- package/dist/client/org/OrgSwitcher.js +11 -4
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/sharing/ShareButton.js +3 -3
- package/dist/client/sharing/ShareButton.js.map +1 -1
- package/dist/client/use-agent-chat-home-handoff.d.ts +8 -2
- package/dist/client/use-agent-chat-home-handoff.d.ts.map +1 -1
- package/dist/client/use-agent-chat-home-handoff.js +20 -6
- package/dist/client/use-agent-chat-home-handoff.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/routes.d.ts +2 -2
- package/dist/db/client.d.ts +1 -0
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +28 -2
- package/dist/db/client.js.map +1 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +2 -2
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/index.d.ts +5 -4
- package/dist/provider-api/index.d.ts.map +1 -1
- package/dist/provider-api/index.js +28 -0
- package/dist/provider-api/index.js.map +1 -1
- package/dist/resources/handlers.d.ts +3 -3
- package/dist/server/core-routes-plugin.d.ts +25 -0
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +43 -18
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/styles/agent-native.css +54 -0
- package/dist/usage/store.js +2 -2
- package/dist/usage/store.js.map +1 -1
- package/package.json +1 -1
|
@@ -14,7 +14,6 @@
|
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
import {
|
|
17
|
-
listAppState,
|
|
18
17
|
readAppState,
|
|
19
18
|
writeAppState,
|
|
20
19
|
} from "@agent-native/core/application-state";
|
|
@@ -36,6 +35,7 @@ import {
|
|
|
36
35
|
import finalizeRecording from "../../../../../actions/finalize-recording.js";
|
|
37
36
|
import { getDb, schema } from "../../../../db/index.js";
|
|
38
37
|
import { debugLog } from "../../../../lib/debug.js";
|
|
38
|
+
import { sumRecordingChunkBytes } from "../../../../lib/recording-upload-state.js";
|
|
39
39
|
import {
|
|
40
40
|
getEventOwnerContext,
|
|
41
41
|
ownerEmailMatches,
|
|
@@ -82,14 +82,6 @@ function stateNumber(
|
|
|
82
82
|
return typeof raw === "number" && Number.isFinite(raw) ? raw : undefined;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
async function sumPersistedChunkBytes(recordingId: string): Promise<number> {
|
|
86
|
-
const chunks = await listAppState(`recording-chunks-${recordingId}-`);
|
|
87
|
-
return chunks.reduce(
|
|
88
|
-
(total, entry) => total + (stateNumber(entry.value, "bytes") ?? 0),
|
|
89
|
-
0,
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
85
|
export default defineEventHandler(async (event: H3Event) => {
|
|
94
86
|
const recordingId = getRouterParam(event, "recordingId");
|
|
95
87
|
if (!recordingId) {
|
|
@@ -278,7 +270,7 @@ export default defineEventHandler(async (event: H3Event) => {
|
|
|
278
270
|
recordingId,
|
|
279
271
|
status: "failed",
|
|
280
272
|
failureReason: reason,
|
|
281
|
-
bytesReceived: await
|
|
273
|
+
bytesReceived: await sumRecordingChunkBytes(ownerEmail, recordingId),
|
|
282
274
|
maxBytes: MAX_RECORDING_UPLOAD_BYTES,
|
|
283
275
|
updatedAt: new Date().toISOString(),
|
|
284
276
|
});
|
|
@@ -323,7 +315,10 @@ export default defineEventHandler(async (event: H3Event) => {
|
|
|
323
315
|
const chunkKey = `recording-chunks-${recordingId}-${paddedIndex}`;
|
|
324
316
|
const previousChunk = await readAppState(chunkKey);
|
|
325
317
|
const previousBytes = stateNumber(previousChunk, "bytes") ?? 0;
|
|
326
|
-
const persistedBytesBefore = await
|
|
318
|
+
const persistedBytesBefore = await sumRecordingChunkBytes(
|
|
319
|
+
ownerEmail,
|
|
320
|
+
recordingId,
|
|
321
|
+
);
|
|
327
322
|
const nextBytes =
|
|
328
323
|
Math.max(0, persistedBytesBefore - previousBytes) + bytes.byteLength;
|
|
329
324
|
|
|
@@ -339,7 +334,7 @@ export default defineEventHandler(async (event: H3Event) => {
|
|
|
339
334
|
data: toBase64(bytes),
|
|
340
335
|
createdAt: new Date().toISOString(),
|
|
341
336
|
});
|
|
342
|
-
bytesReceived = await
|
|
337
|
+
bytesReceived = await sumRecordingChunkBytes(ownerEmail, recordingId);
|
|
343
338
|
if (bytesReceived > MAX_RECORDING_UPLOAD_BYTES) {
|
|
344
339
|
return failRecordingTooLarge(bytesReceived);
|
|
345
340
|
}
|
|
@@ -396,7 +391,7 @@ export default defineEventHandler(async (event: H3Event) => {
|
|
|
396
391
|
// Final chunk — kick off finalize. We await so the client gets a single
|
|
397
392
|
// "done" response with the final URL (instead of needing to poll).
|
|
398
393
|
if (isFinal) {
|
|
399
|
-
bytesReceived = await
|
|
394
|
+
bytesReceived = await sumRecordingChunkBytes(ownerEmail, recordingId);
|
|
400
395
|
if (bytesReceived > MAX_RECORDING_UPLOAD_BYTES) {
|
|
401
396
|
return failRecordingTooLarge(bytesReceived);
|
|
402
397
|
}
|
|
@@ -437,6 +432,61 @@ export default defineEventHandler(async (event: H3Event) => {
|
|
|
437
432
|
};
|
|
438
433
|
} catch (err) {
|
|
439
434
|
console.error("[clips] finalize-recording failed:", err);
|
|
435
|
+
const [committed] = await db
|
|
436
|
+
.select({
|
|
437
|
+
id: schema.recordings.id,
|
|
438
|
+
status: schema.recordings.status,
|
|
439
|
+
videoUrl: schema.recordings.videoUrl,
|
|
440
|
+
durationMs: schema.recordings.durationMs,
|
|
441
|
+
width: schema.recordings.width,
|
|
442
|
+
height: schema.recordings.height,
|
|
443
|
+
hasAudio: schema.recordings.hasAudio,
|
|
444
|
+
hasCamera: schema.recordings.hasCamera,
|
|
445
|
+
})
|
|
446
|
+
.from(schema.recordings)
|
|
447
|
+
.where(
|
|
448
|
+
and(
|
|
449
|
+
eq(schema.recordings.id, recordingId),
|
|
450
|
+
ownerEmailMatches(schema.recordings.ownerEmail, ownerEmail),
|
|
451
|
+
),
|
|
452
|
+
);
|
|
453
|
+
if (committed?.status === "ready" && committed.videoUrl) {
|
|
454
|
+
console.warn(
|
|
455
|
+
"[clips] finalize reported an error after committing a ready recording; returning committed success.",
|
|
456
|
+
{
|
|
457
|
+
recordingId,
|
|
458
|
+
error: err instanceof Error ? err.message : String(err),
|
|
459
|
+
},
|
|
460
|
+
);
|
|
461
|
+
try {
|
|
462
|
+
await writeAppState(`recording-upload-${recordingId}`, {
|
|
463
|
+
recordingId,
|
|
464
|
+
status: "ready",
|
|
465
|
+
progress: 100,
|
|
466
|
+
videoUrl: committed.videoUrl,
|
|
467
|
+
finishedAt: new Date().toISOString(),
|
|
468
|
+
});
|
|
469
|
+
} catch (stateErr) {
|
|
470
|
+
console.warn("[clips] committed-ready state repair failed:", {
|
|
471
|
+
recordingId,
|
|
472
|
+
err:
|
|
473
|
+
stateErr instanceof Error ? stateErr.message : String(stateErr),
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
return {
|
|
477
|
+
ok: true,
|
|
478
|
+
finalized: true,
|
|
479
|
+
recoveredAfterFinalizeError: true,
|
|
480
|
+
id: committed.id,
|
|
481
|
+
status: "ready",
|
|
482
|
+
videoUrl: committed.videoUrl,
|
|
483
|
+
durationMs: committed.durationMs,
|
|
484
|
+
width: committed.width,
|
|
485
|
+
height: committed.height,
|
|
486
|
+
hasAudio: committed.hasAudio,
|
|
487
|
+
hasCamera: committed.hasCamera,
|
|
488
|
+
};
|
|
489
|
+
}
|
|
440
490
|
await db
|
|
441
491
|
.update(schema.recordings)
|
|
442
492
|
.set({
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { runWithRequestContext } from "@agent-native/core/server";
|
|
2
|
+
import { and, eq } from "drizzle-orm";
|
|
3
|
+
import {
|
|
4
|
+
createError,
|
|
5
|
+
defineEventHandler,
|
|
6
|
+
getRouterParam,
|
|
7
|
+
setResponseStatus,
|
|
8
|
+
type H3Event,
|
|
9
|
+
} from "h3";
|
|
10
|
+
|
|
11
|
+
import { getDb, schema } from "../../../../db/index.js";
|
|
12
|
+
import { resolvePlayerVideoUrl } from "../../../../lib/player-video-url.js";
|
|
13
|
+
import {
|
|
14
|
+
getEventOwnerContext,
|
|
15
|
+
ownerEmailMatches,
|
|
16
|
+
} from "../../../../lib/recordings.js";
|
|
17
|
+
|
|
18
|
+
function appPath(path: string): string {
|
|
19
|
+
if (!path.startsWith("/")) return path;
|
|
20
|
+
const raw = process.env.VITE_APP_BASE_PATH || process.env.APP_BASE_PATH || "";
|
|
21
|
+
const base = raw.trim().replace(/^\/+/, "").replace(/\/+$/, "");
|
|
22
|
+
return base ? `/${base}${path}` : path;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default defineEventHandler(async (event: H3Event) => {
|
|
26
|
+
const recordingId = getRouterParam(event, "recordingId");
|
|
27
|
+
if (!recordingId) {
|
|
28
|
+
throw createError({ statusCode: 400, message: "Missing recordingId" });
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
let ownerEmail: string;
|
|
32
|
+
let orgId: string | undefined;
|
|
33
|
+
try {
|
|
34
|
+
const context = await getEventOwnerContext(event);
|
|
35
|
+
ownerEmail = context.userEmail;
|
|
36
|
+
orgId = context.orgId;
|
|
37
|
+
} catch {
|
|
38
|
+
throw createError({ statusCode: 401, message: "Unauthorized" });
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return runWithRequestContext({ userEmail: ownerEmail, orgId }, async () => {
|
|
42
|
+
const [recording] = await getDb()
|
|
43
|
+
.select()
|
|
44
|
+
.from(schema.recordings)
|
|
45
|
+
.where(
|
|
46
|
+
and(
|
|
47
|
+
eq(schema.recordings.id, recordingId),
|
|
48
|
+
ownerEmailMatches(schema.recordings.ownerEmail, ownerEmail),
|
|
49
|
+
),
|
|
50
|
+
)
|
|
51
|
+
.limit(1);
|
|
52
|
+
|
|
53
|
+
if (!recording) {
|
|
54
|
+
setResponseStatus(event, 404);
|
|
55
|
+
return { error: "Not found" };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
recording: {
|
|
60
|
+
id: recording.id,
|
|
61
|
+
status: recording.status,
|
|
62
|
+
videoUrl: resolvePlayerVideoUrl(recording, { appPath }),
|
|
63
|
+
durationMs: recording.durationMs,
|
|
64
|
+
width: recording.width,
|
|
65
|
+
height: recording.height,
|
|
66
|
+
hasAudio: Boolean(recording.hasAudio),
|
|
67
|
+
hasCamera: Boolean(recording.hasCamera),
|
|
68
|
+
uploadProgress: recording.uploadProgress,
|
|
69
|
+
failureReason: recording.failureReason,
|
|
70
|
+
updatedAt: recording.updatedAt,
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
});
|
|
@@ -166,6 +166,24 @@ pnpm action index-design-system-with-builder --codeFiles '[{"filename":"globals.
|
|
|
166
166
|
|
|
167
167
|
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.
|
|
168
168
|
|
|
169
|
+
For the active design's Tokens panel, use `import-design-tokens` when the user
|
|
170
|
+
wants to pull reusable CSS vars/tokens straight into the open design without
|
|
171
|
+
creating a full design system:
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
pnpm action import-design-tokens \
|
|
175
|
+
--designId "design_123" \
|
|
176
|
+
--source files \
|
|
177
|
+
--files '[{"filename":"design.md","content":"Primary color: #2563eb"}]'
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Supported sources are `files`, `paste`, and `current-design`. The action parses
|
|
181
|
+
CSS variables, design.md-style labeled lines, Tailwind/theme JSON, colors,
|
|
182
|
+
spacing, radii, and fonts, then persists them through the design's
|
|
183
|
+
`tweakSelections` so the canvas updates like any other token edit. Treat manual
|
|
184
|
+
`apply-design-token-edit` calls as a last-resort one-off edit after import has
|
|
185
|
+
been tried or ruled out.
|
|
186
|
+
|
|
169
187
|
### Source: Documents (DOCX, PPTX, PDF)
|
|
170
188
|
|
|
171
189
|
```bash
|
|
@@ -204,6 +222,20 @@ indexing through the setup page upload route. Do not parse `.fig` files locally
|
|
|
204
222
|
and do not call `create-design-system` from raw `.fig` output; Builder owns the
|
|
205
223
|
indexed brand kit, generated docs, and usage guidance.
|
|
206
224
|
|
|
225
|
+
**When the user wants a Figma Assets-style native component drawer inside
|
|
226
|
+
Design**, do not use Figma or media assets. Use `list-design-native-assets` to
|
|
227
|
+
choose an editable primitive/component/layout, then
|
|
228
|
+
`insert-design-native-asset` to insert it into the active screen. These entries
|
|
229
|
+
are Design-native HTML stamped with component/layer metadata.
|
|
230
|
+
|
|
231
|
+
**When the user wants reusable Figma components/assets**, do not run
|
|
232
|
+
design-system indexing just to insert a component. Use
|
|
233
|
+
`list-figma-library-assets` with a Figma file URL/key, then
|
|
234
|
+
`insert-figma-library-asset` with the returned `renderUrl`, `fileKey`,
|
|
235
|
+
`nodeId`, `componentKey`, and `sourceUrl`. This inserts a rendered
|
|
236
|
+
component/component set with provenance. Styles and variables still belong in
|
|
237
|
+
the Builder-backed design-system path above.
|
|
238
|
+
|
|
207
239
|
### Source: Brand Analysis (combines website + notes)
|
|
208
240
|
|
|
209
241
|
```bash
|
|
@@ -32,6 +32,11 @@ patterns live in `.agents/skills/`.
|
|
|
32
32
|
per direction; avoid lorem ipsum, generic SaaS filler, and decorative
|
|
33
33
|
placeholders. Include expected responsive/accessibility states and visually
|
|
34
34
|
inspect the result before calling it ready.
|
|
35
|
+
- For editable reusable building blocks inside Design, use
|
|
36
|
+
`list-design-native-assets` first, then `insert-design-native-asset` with the
|
|
37
|
+
chosen kind. These are Design-native HTML primitives/components, not external
|
|
38
|
+
media, so prefer them when the user asks for a Figma Assets-style library that
|
|
39
|
+
supports our own primitives.
|
|
35
40
|
- For raster image generation, restyling, or editing existing screenshots/photos,
|
|
36
41
|
use the available first-party Assets MCP tool such as `generate-asset` instead
|
|
37
42
|
of placeholders or generic stock imagery. When the Assets picker returns a
|
|
@@ -43,6 +48,15 @@ patterns live in `.agents/skills/`.
|
|
|
43
48
|
chat-attachment URL or call `upload-image` to create one before delegating. If
|
|
44
49
|
no image/upload provider is configured, say that specific setup is needed and
|
|
45
50
|
continue any non-image Design work separately.
|
|
51
|
+
- For reusable Figma library components, use `list-figma-library-assets` with a
|
|
52
|
+
Figma file URL or file key. It returns components/component sets with
|
|
53
|
+
thumbnails, rendered insert URLs, and Figma provenance. Insert with
|
|
54
|
+
`insert-figma-library-asset`, preserving `fileKey`, `nodeId`, `componentKey`,
|
|
55
|
+
`sourceUrl`, and the rendered URL. This path requires the saved
|
|
56
|
+
`FIGMA_ACCESS_TOKEN` secret; never ask the user to paste that token into chat
|
|
57
|
+
or pass it as an action parameter. Figma styles and variables are design-system
|
|
58
|
+
inputs, not draggable media assets; route full file/design-system extraction
|
|
59
|
+
through Builder-backed indexing.
|
|
46
60
|
- Use Alpine.js and Tailwind CDN for interactive prototypes. Prefer Alpine
|
|
47
61
|
directives over raw inline event handlers.
|
|
48
62
|
- Navigate between prototype screens with Alpine state (`x-show`), a
|
|
@@ -72,6 +86,13 @@ patterns live in `.agents/skills/`.
|
|
|
72
86
|
`inspectorTab: "extensions"` after installing it.
|
|
73
87
|
- Follow linked design-system tokens and `customInstructions` whenever present;
|
|
74
88
|
explicit user instructions in the current turn still win.
|
|
89
|
+
- When a user wants tokens from design.md, CSS, theme/tokens JSON, Tailwind
|
|
90
|
+
config, local files, or the current design, call `import-design-tokens` and
|
|
91
|
+
preserve its `tokens`, `filesAnalyzed`, and provenance in your answer. Manual
|
|
92
|
+
`apply-design-token-edit` / one-by-one token entry is the fallback for a small
|
|
93
|
+
one-off token, not the primary import workflow. For Figma variables/styles or
|
|
94
|
+
raw `.fig` files, keep using Builder-backed design-system indexing instead of
|
|
95
|
+
local `.fig` parsing.
|
|
75
96
|
- Persist useful work early: create/update the design and files as soon as a
|
|
76
97
|
coherent candidate exists, then iterate.
|
|
77
98
|
- For non-trivial new design prompts, ask before generating: create/open the
|
|
@@ -104,6 +125,12 @@ patterns live in `.agents/skills/`.
|
|
|
104
125
|
generated CSS selectors as a compatibility fallback only. For localhost React
|
|
105
126
|
screens, resolve through build-time source/debug metadata (stable generated
|
|
106
127
|
ids, component name, file, and line) before falling back to selectors.
|
|
128
|
+
- For inline/Alpine motion, use `get-motion-timeline` to inspect the active
|
|
129
|
+
file's saved or CSS-recovered timeline, then call `apply-motion-edit` with the
|
|
130
|
+
same `sourceRef`/`fileId` to update it. Motion edits persist as durable
|
|
131
|
+
managed keyframes in `<style data-agent-native-motion>` plus editable timeline
|
|
132
|
+
metadata; it is not a one-way export. Real CSS module or `motion/react`
|
|
133
|
+
write-back remains a localhost/fusion follow-up capability.
|
|
107
134
|
- For multi-variant work, use `present-design-variants` so every candidate is
|
|
108
135
|
saved as a normal overview-board screen and the user gets one inline chat
|
|
109
136
|
button per screen name. After the user picks, delete the unchosen variant
|
|
@@ -396,7 +396,7 @@ Requirements:
|
|
|
396
396
|
- diamond keyframes
|
|
397
397
|
- play/scrub controls
|
|
398
398
|
- auto-keyframe control
|
|
399
|
-
-
|
|
399
|
+
- autosave status for managed CSS persistence
|
|
400
400
|
- compact Motion/Keyframe inspector section
|
|
401
401
|
- no separate motion app/screen
|
|
402
402
|
|
|
@@ -347,7 +347,7 @@ The CSS is the runtime truth; the JSON `tracks` only aid editing.
|
|
|
347
347
|
|
|
348
348
|
- **UI (matches the motion artboard):** a full-width, collapsible **Motion dock**
|
|
349
349
|
at the bottom of `DesignEditor.tsx` (animated layer rows, property tracks, time
|
|
350
|
-
ruler, diamond keyframes, play/scrub, auto-keyframe toggle,
|
|
350
|
+
ruler, diamond keyframes, play/scrub, auto-keyframe toggle, autosave status),
|
|
351
351
|
with the canvas still visible above; a compact **Motion section** in the
|
|
352
352
|
inspector for the selected keyframe (numeric + easing + transform/opacity).
|
|
353
353
|
- **Preview:** scrubbing sends preview-only bridge messages (`motion-preview` /
|
|
@@ -360,8 +360,8 @@ The CSS is the runtime truth; the JSON `tracks` only aid editing.
|
|
|
360
360
|
**Real-app superset:** write keyframes into real CSS modules, optional
|
|
361
361
|
`motion`-react round-trip, Dev Mode export.
|
|
362
362
|
|
|
363
|
-
**Acceptance:** scrubbing never writes;
|
|
364
|
-
diff/rollback proof; multiple layers and tracks animate.
|
|
363
|
+
**Acceptance:** scrubbing never writes; timeline edits autosave through one atomic
|
|
364
|
+
action with diff/rollback proof; multiple layers and tracks animate.
|
|
365
365
|
|
|
366
366
|
### 6.4 States, responsive & captures
|
|
367
367
|
|
|
@@ -615,7 +615,7 @@ motion edits safely, use review outputs, and offer Builder migration CTAs.
|
|
|
615
615
|
runtime + source-write + fallback + diff proof.
|
|
616
616
|
|
|
617
617
|
**First user-visible milestone:** on an inline design, edit a token (live, persisted)
|
|
618
|
-
and add a keyframe animation that
|
|
618
|
+
and add a keyframe animation that autosaves to managed CSS with a visible diff —
|
|
619
619
|
"visual edit becomes persisted code/CSS" without the whole real-app stack.
|
|
620
620
|
|
|
621
621
|
---
|
|
@@ -659,7 +659,7 @@ and add a keyframe animation that **Write to CSS** commits with a visible diff
|
|
|
659
659
|
(Mobile) is untouched; the Desktop frame reflects the cascade; reset-to-base clears
|
|
660
660
|
the override; the same flow works on an inline design and a real-app URL.
|
|
661
661
|
- **Alpine smoke:** edit layout/styles; preview + persist a CSS-var token change;
|
|
662
|
-
add simple keyframes
|
|
662
|
+
add simple keyframes that autosave to managed CSS; run a basic a11y scan; see the real-app CTA
|
|
663
663
|
for full component controls.
|
|
664
664
|
|
|
665
665
|
---
|
|
@@ -25,7 +25,6 @@ import {
|
|
|
25
25
|
agentLeaveDocument,
|
|
26
26
|
agentUpdateSelection,
|
|
27
27
|
applyText,
|
|
28
|
-
getText,
|
|
29
28
|
hasCollabState,
|
|
30
29
|
seedFromText,
|
|
31
30
|
} from "@agent-native/core/collab";
|
|
@@ -117,26 +116,11 @@ export function applyRootAttributeEdit(
|
|
|
117
116
|
};
|
|
118
117
|
}
|
|
119
118
|
|
|
120
|
-
async function liveContent(
|
|
121
|
-
fileId: string,
|
|
122
|
-
storedContent: string,
|
|
123
|
-
): Promise<string> {
|
|
124
|
-
try {
|
|
125
|
-
if (await hasCollabState(fileId)) {
|
|
126
|
-
const live = await getText(fileId, "content");
|
|
127
|
-
if (typeof live === "string") return live;
|
|
128
|
-
}
|
|
129
|
-
} catch {
|
|
130
|
-
// Collab reads are best-effort; SQL content is the fallback.
|
|
131
|
-
}
|
|
132
|
-
return storedContent;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
119
|
async function persistEdit(file: {
|
|
136
120
|
id: string;
|
|
137
121
|
designId: string;
|
|
138
122
|
content: string;
|
|
139
|
-
}): Promise<
|
|
123
|
+
}): Promise<string> {
|
|
140
124
|
await assertAccess("design", file.designId, "editor");
|
|
141
125
|
const db = getDb();
|
|
142
126
|
const now = new Date().toISOString();
|
|
@@ -161,6 +145,8 @@ async function persistEdit(file: {
|
|
|
161
145
|
} finally {
|
|
162
146
|
agentLeaveDocument(file.id);
|
|
163
147
|
}
|
|
148
|
+
|
|
149
|
+
return now;
|
|
164
150
|
}
|
|
165
151
|
|
|
166
152
|
// ─── Action ───────────────────────────────────────────────────────────────────
|
|
@@ -213,8 +199,24 @@ export default defineAction({
|
|
|
213
199
|
}),
|
|
214
200
|
])
|
|
215
201
|
.describe("The prop edit to apply"),
|
|
202
|
+
source: z
|
|
203
|
+
.object({
|
|
204
|
+
currentContent: z
|
|
205
|
+
.string()
|
|
206
|
+
.optional()
|
|
207
|
+
.describe(
|
|
208
|
+
"Latest editor HTML snapshot. Used to compose rapid sequential prop edits before collab persistence catches up.",
|
|
209
|
+
),
|
|
210
|
+
revision: z
|
|
211
|
+
.string()
|
|
212
|
+
.optional()
|
|
213
|
+
.describe(
|
|
214
|
+
"design_files.updatedAt value the currentContent is based on.",
|
|
215
|
+
),
|
|
216
|
+
})
|
|
217
|
+
.optional(),
|
|
216
218
|
}),
|
|
217
|
-
run: async ({ designId, nodeId, fileId, edit }) => {
|
|
219
|
+
run: async ({ designId, nodeId, fileId, edit, source }) => {
|
|
218
220
|
const db = getDb();
|
|
219
221
|
|
|
220
222
|
// ── Access check ────────────────────────────────────────────────────────
|
|
@@ -274,6 +276,7 @@ export default defineAction({
|
|
|
274
276
|
designId: schema.designFiles.designId,
|
|
275
277
|
filename: schema.designFiles.filename,
|
|
276
278
|
content: schema.designFiles.content,
|
|
279
|
+
updatedAt: schema.designFiles.updatedAt,
|
|
277
280
|
})
|
|
278
281
|
.from(schema.designFiles)
|
|
279
282
|
.innerJoin(
|
|
@@ -285,7 +288,31 @@ export default defineAction({
|
|
|
285
288
|
|
|
286
289
|
if (!file) throw new Error("Design HTML file not found.");
|
|
287
290
|
|
|
288
|
-
|
|
291
|
+
if (
|
|
292
|
+
source?.currentContent &&
|
|
293
|
+
source.revision &&
|
|
294
|
+
file.updatedAt &&
|
|
295
|
+
source.revision !== file.updatedAt
|
|
296
|
+
) {
|
|
297
|
+
return {
|
|
298
|
+
designId,
|
|
299
|
+
nodeId,
|
|
300
|
+
persisted: false,
|
|
301
|
+
conflict: true,
|
|
302
|
+
fileId: file.id,
|
|
303
|
+
filename: file.filename,
|
|
304
|
+
error:
|
|
305
|
+
"This file changed since this component prop edit was prepared. Refresh the editor and try again.",
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// Prefer explicit editor content after the caller's revision check, and use
|
|
310
|
+
// the saved SQL content as the fallback. Collab/Yjs reads can be stale
|
|
311
|
+
// across local dev worker processes and make prop controls lag behind.
|
|
312
|
+
const html =
|
|
313
|
+
typeof source?.currentContent === "string"
|
|
314
|
+
? source.currentContent
|
|
315
|
+
: (file.content ?? "");
|
|
289
316
|
|
|
290
317
|
// ── Resolve node ─────────────────────────────────────────────────────────
|
|
291
318
|
const codeLayerSource: CodeLayerSource = {
|
|
@@ -406,7 +433,7 @@ export default defineAction({
|
|
|
406
433
|
const shouldPersist = changed || patchedContent !== (file.content ?? "");
|
|
407
434
|
|
|
408
435
|
if (shouldPersist) {
|
|
409
|
-
await persistEdit({
|
|
436
|
+
const updatedAt = await persistEdit({
|
|
410
437
|
id: file.id,
|
|
411
438
|
designId: file.designId,
|
|
412
439
|
content: patchedContent,
|
|
@@ -418,6 +445,22 @@ export default defineAction({
|
|
|
418
445
|
editingFile: file.filename,
|
|
419
446
|
designId: file.designId,
|
|
420
447
|
});
|
|
448
|
+
return {
|
|
449
|
+
designId,
|
|
450
|
+
nodeId,
|
|
451
|
+
componentName,
|
|
452
|
+
sourceType,
|
|
453
|
+
editKind: edit.kind,
|
|
454
|
+
persisted: shouldPersist,
|
|
455
|
+
ctaRequired: false,
|
|
456
|
+
fileId: file.id,
|
|
457
|
+
filename: file.filename,
|
|
458
|
+
updatedAt,
|
|
459
|
+
content: patchedContent,
|
|
460
|
+
bytesBefore: html.length,
|
|
461
|
+
bytesAfter: patchedContent.length,
|
|
462
|
+
note: "Edit applied and persisted via the deterministic HTML-patch path.",
|
|
463
|
+
};
|
|
421
464
|
}
|
|
422
465
|
|
|
423
466
|
return {
|