@agent-native/core 0.92.10 → 0.92.11
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 +23 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/production-agent.ts +181 -15
- package/corpus/core/src/agent/run-manager.ts +31 -4
- package/corpus/core/src/agent/run-store.ts +80 -0
- package/corpus/core/src/cli/design-connect.ts +433 -151
- package/corpus/core/src/cli/skills.ts +14 -0
- package/corpus/core/src/client/AssistantChat.tsx +25 -0
- package/corpus/core/src/client/MultiTabAssistantChat.tsx +40 -6
- package/corpus/core/src/client/agent-chat.ts +165 -1
- package/corpus/core/src/client/chat/index.ts +9 -1
- package/corpus/core/src/client/extensions/EmbeddedExtension.tsx +38 -2
- package/corpus/core/src/client/index.ts +5 -0
- package/corpus/core/src/client/rich-markdown-editor/useCollabReconcile.ts +18 -7
- package/corpus/core/src/collab/awareness-store.ts +23 -12
- package/corpus/core/src/collab/client.ts +16 -5
- package/corpus/core/src/collab/index.ts +4 -0
- package/corpus/core/src/collab/recent-edits.ts +65 -2
- package/corpus/core/src/index.browser.ts +1 -0
- package/corpus/core/src/server/agent-chat-plugin.ts +98 -11
- package/corpus/core/src/server/builder-design-systems.ts +30 -4
- package/corpus/templates/clips/.agents/skills/ai-video-tools/SKILL.md +1 -1
- package/corpus/templates/clips/.agents/skills/video-sharing/SKILL.md +12 -6
- package/corpus/templates/clips/AGENTS.md +4 -0
- package/corpus/templates/clips/actions/create-recording.ts +2 -0
- package/corpus/templates/clips/actions/lib/create-recording-schema.ts +5 -3
- package/corpus/templates/clips/actions/request-transcript.ts +102 -33
- package/corpus/templates/clips/app/components/library/library-grid.tsx +1 -0
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +59 -19
- package/corpus/templates/clips/app/components/player/transcript-panel.tsx +48 -4
- package/corpus/templates/clips/app/components/player/video-player.tsx +17 -12
- package/corpus/templates/clips/app/i18n/ar-SA.ts +1 -0
- package/corpus/templates/clips/app/i18n/de-DE.ts +1 -0
- package/corpus/templates/clips/app/i18n/en-US.ts +1 -0
- package/corpus/templates/clips/app/i18n/es-ES.ts +1 -0
- package/corpus/templates/clips/app/i18n/fr-FR.ts +1 -0
- package/corpus/templates/clips/app/i18n/hi-IN.ts +1 -0
- package/corpus/templates/clips/app/i18n/ja-JP.ts +1 -0
- package/corpus/templates/clips/app/i18n/ko-KR.ts +1 -0
- package/corpus/templates/clips/app/i18n/pt-BR.ts +1 -0
- package/corpus/templates/clips/app/i18n/zh-CN.ts +1 -0
- package/corpus/templates/clips/app/i18n/zh-TW.ts +1 -0
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +70 -37
- package/corpus/templates/clips/app/routes/record.tsx +17 -4
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +2 -0
- package/corpus/templates/clips/changelog/2026-07-09-desktop-popover-sits-closer-to-the-menu-bar.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-desktop-recording-optimization-progress-stays-visible-until-the-clip-opens.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-fixed-large-video-file-uploads-failing-before-their-resumabl.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-fixed-new-video-uploads-defaulting-to-private.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-long-recordings-now-get-enough-time-to-download-their-media-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-meeting-notes-no-longer-lowers-your-microphone-volume-for-ot.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-on-mobile-tapping-a-playing-clip-reveals-playback-controls-w.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-regenerate-any-clip-transcript-from-its-saved-recording-or-r.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-slack-previews-now-show-the-clip-length-alongside-its-descri.md +6 -0
- package/corpus/templates/clips/desktop/src/app.tsx +12 -2
- package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +8 -1
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +8 -5
- package/corpus/templates/clips/desktop/src/lib/transcription-engine.ts +5 -5
- package/corpus/templates/clips/desktop/src/lib/voice-dictation.ts +3 -0
- package/corpus/templates/clips/desktop/src/styles.css +6 -3
- package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +29 -11
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +1 -1
- package/corpus/templates/clips/desktop/src-tauri/src/system_audio.rs +103 -21
- package/corpus/templates/clips/desktop/src-tauri/src/whisper_speech.rs +117 -39
- package/corpus/templates/clips/server/lib/slack-unfurls.ts +20 -1
- package/corpus/templates/clips/server/lib/streaming-upload-mode.ts +10 -4
- package/corpus/templates/clips/shared/recording-core.ts +12 -0
- package/corpus/templates/content/AGENTS.md +7 -6
- package/corpus/templates/content/actions/_document-flush.ts +132 -17
- package/corpus/templates/content/actions/_notion-action-utils.ts +15 -0
- package/corpus/templates/content/actions/create-and-link-notion-page.ts +2 -0
- package/corpus/templates/content/actions/link-notion-page.ts +2 -0
- package/corpus/templates/content/actions/pull-document.ts +5 -7
- package/corpus/templates/content/actions/pull-notion-page.ts +2 -0
- package/corpus/templates/content/actions/push-notion-page.ts +10 -0
- package/corpus/templates/content/actions/resolve-notion-sync-conflict.ts +2 -0
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +88 -23
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +32 -2
- package/corpus/templates/content/app/hooks/use-notion.ts +6 -6
- package/corpus/templates/content/app/i18n/zh-TW.ts +1 -0
- package/corpus/templates/content/app/i18n-data.ts +18 -0
- package/corpus/templates/content/changelog/2026-07-09-notion-conflict-choices-and-version-restores-preserve-docume.md +6 -0
- package/corpus/templates/content/server/lib/notion-sync.ts +80 -64
- package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +29 -2
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +86 -0
- package/corpus/templates/design/.agents/skills/export-handoff/SKILL.md +57 -0
- package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +11 -0
- package/corpus/templates/design/AGENTS.md +45 -10
- package/corpus/templates/design/actions/add-localhost-screens.ts +66 -13
- package/corpus/templates/design/actions/apply-component-prop-edit.ts +45 -36
- package/corpus/templates/design/actions/apply-motion-edit.ts +25 -31
- package/corpus/templates/design/actions/apply-shader-fill.ts +29 -42
- package/corpus/templates/design/actions/detach-component-instance.ts +337 -0
- package/corpus/templates/design/actions/export-design-as-figma-svg.ts +219 -0
- package/corpus/templates/design/actions/generate-design.ts +79 -12
- package/corpus/templates/design/actions/generate-screens.ts +57 -12
- package/corpus/templates/design/actions/get-figma-styles.ts +115 -0
- package/corpus/templates/design/actions/go-to-main-component.ts +254 -0
- package/corpus/templates/design/actions/grant-localhost-write-consent.ts +4 -3
- package/corpus/templates/design/actions/import-design-source.ts +4 -31
- package/corpus/templates/design/actions/import-figma-clipboard.ts +134 -0
- package/corpus/templates/design/actions/import-figma-frame.ts +95 -0
- package/corpus/templates/design/actions/index-design-system-with-builder.ts +16 -1
- package/corpus/templates/design/actions/list-design-components.ts +104 -0
- package/corpus/templates/design/actions/list-figma-library-assets.ts +1 -24
- package/corpus/templates/design/actions/open-component-source.ts +2 -4
- package/corpus/templates/design/actions/present-design-variants.ts +412 -16
- package/corpus/templates/design/actions/preview-source-edit.ts +14 -1
- package/corpus/templates/design/actions/run-design-audit.ts +25 -3
- package/corpus/templates/design/actions/show-design-questions.ts +10 -0
- package/corpus/templates/design/actions/swap-component-instance.ts +544 -0
- package/corpus/templates/design/actions/take-design-screenshot.ts +45 -60
- package/corpus/templates/design/actions/write-local-file.ts +25 -1
- package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +152 -0
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +1077 -58
- package/corpus/templates/design/app/components/design/DesignEditorSkeleton.tsx +5 -5
- package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +73 -21
- package/corpus/templates/design/app/components/design/EditPanel.tsx +16 -11
- package/corpus/templates/design/app/components/design/KeyboardShortcutsPanel.tsx +364 -0
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +180 -53
- package/corpus/templates/design/app/components/design/LocalhostWriteConsentDialog.tsx +0 -2
- package/corpus/templates/design/app/components/design/MotionDock.tsx +144 -21
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +1152 -167
- package/corpus/templates/design/app/components/design/QuestionFlow.tsx +27 -5
- package/corpus/templates/design/app/components/design/ReviewPanel.tsx +23 -2
- package/corpus/templates/design/app/components/design/TokensPanel.tsx +63 -49
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +1293 -54
- package/corpus/templates/design/app/components/design/bridge/embedded-wheel.bridge.ts +7 -0
- package/corpus/templates/design/app/components/design/bridge/hit-test.bridge.ts +6 -1
- package/corpus/templates/design/app/components/design/bridge/motion-preview.bridge.ts +23 -6
- package/corpus/templates/design/app/components/design/bridge/sample.bridge.ts +7 -0
- package/corpus/templates/design/app/components/design/code-workbench/CodeWorkbench.tsx +5 -0
- package/corpus/templates/design/app/components/design/code-workbench/editor/MonacoHost.tsx +14 -2
- package/corpus/templates/design/app/components/design/code-workbench/explorer/FileTree.tsx +37 -2
- package/corpus/templates/design/app/components/design/code-workbench/format/format-on-open-guard.ts +25 -0
- package/corpus/templates/design/app/components/design/code-workbench/format/format-on-open.ts +19 -1
- package/corpus/templates/design/app/components/design/code-workbench/model-registry.ts +43 -5
- package/corpus/templates/design/app/components/design/code-workbench/search/SearchView.tsx +27 -2
- package/corpus/templates/design/app/components/design/code-workbench/search/search-engine.ts +10 -1
- package/corpus/templates/design/app/components/design/code-workbench/store.tsx +19 -2
- package/corpus/templates/design/app/components/design/design-canvas/annotation-snapshot.ts +265 -0
- package/corpus/templates/design/app/components/design/design-canvas/annotation-submit.ts +16 -5
- package/corpus/templates/design/app/components/design/design-canvas/coordinate-transforms.ts +16 -2
- package/corpus/templates/design/app/components/design/design-canvas/embedded-frame.ts +7 -2
- package/corpus/templates/design/app/components/design/design-canvas/iframe-events.ts +3 -1
- package/corpus/templates/design/app/components/design/edit-panel/code-inspect-helpers.tsx +78 -8
- package/corpus/templates/design/app/components/design/edit-panel/component-section.tsx +451 -73
- package/corpus/templates/design/app/components/design/edit-panel/document-colors.ts +12 -4
- package/corpus/templates/design/app/components/design/edit-panel/effects-properties.tsx +398 -272
- package/corpus/templates/design/app/components/design/edit-panel/element-classification.ts +41 -7
- package/corpus/templates/design/app/components/design/edit-panel/element-identity.ts +16 -3
- package/corpus/templates/design/app/components/design/edit-panel/field-primitives.tsx +24 -4
- package/corpus/templates/design/app/components/design/edit-panel/fill-gradient-helpers.ts +222 -4
- package/corpus/templates/design/app/components/design/edit-panel/fill-properties.tsx +171 -78
- package/corpus/templates/design/app/components/design/edit-panel/inspector-controls.tsx +45 -5
- package/corpus/templates/design/app/components/design/edit-panel/layout-properties.tsx +299 -28
- package/corpus/templates/design/app/components/design/edit-panel/panel-primitives.tsx +120 -150
- package/corpus/templates/design/app/components/design/edit-panel/position-helpers.ts +53 -1
- package/corpus/templates/design/app/components/design/edit-panel/position-layout-properties.tsx +284 -117
- package/corpus/templates/design/app/components/design/edit-panel/selection-helpers.ts +81 -0
- package/corpus/templates/design/app/components/design/edit-panel/stroke-properties.tsx +19 -14
- package/corpus/templates/design/app/components/design/edit-panel/style-options.ts +7 -0
- package/corpus/templates/design/app/components/design/edit-panel/typography-helpers.ts +155 -0
- package/corpus/templates/design/app/components/design/edit-panel/typography-properties.tsx +268 -46
- package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +350 -31
- package/corpus/templates/design/app/components/design/inspector/ConstraintsWidget.tsx +13 -4
- package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +233 -23
- package/corpus/templates/design/app/components/design/inspector/GradientEditor.tsx +72 -2
- package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +51 -11
- package/corpus/templates/design/app/components/design/inspector/ShaderFillsPanel.tsx +84 -11
- package/corpus/templates/design/app/components/design/inspector/index.ts +3 -0
- package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +552 -0
- package/corpus/templates/design/app/components/design/multi-screen/board-surface-html.ts +157 -0
- package/corpus/templates/design/app/components/design/multi-screen/frame-geometry.ts +53 -0
- package/corpus/templates/design/app/components/design/multi-screen/overview-layout.ts +184 -0
- package/corpus/templates/design/app/components/design/multi-screen/primitive-drop-target.ts +403 -26
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +20 -1
- package/corpus/templates/design/app/components/design/types.ts +33 -0
- package/corpus/templates/design/app/components/editor/PromptDialog.tsx +59 -7
- package/corpus/templates/design/app/components/visual-editor/CanvasCommentPins.tsx +119 -17
- package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +275 -63
- package/corpus/templates/design/app/hooks/use-question-flow.ts +14 -3
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +67 -10
- package/corpus/templates/design/app/i18n/zh-TW.ts +91 -1
- package/corpus/templates/design/app/i18n-data.ts +1217 -10
- package/corpus/templates/design/app/i18n-keyboard-shortcuts.ts +577 -0
- package/corpus/templates/design/app/lib/agent-chat.ts +23 -0
- package/corpus/templates/design/app/lib/design-import.ts +24 -0
- package/corpus/templates/design/app/lib/figma-clipboard.ts +157 -0
- package/corpus/templates/design/app/lib/figma-svg-copy.ts +221 -0
- package/corpus/templates/design/app/pages/design-editor/code-layer-state.ts +143 -30
- package/corpus/templates/design/app/pages/design-editor/collab-sync.ts +15 -0
- package/corpus/templates/design/app/pages/design-editor/editor-session.ts +33 -0
- package/corpus/templates/design/app/pages/design-editor/editor-state.ts +38 -0
- package/corpus/templates/design/app/pages/design-editor/overview-annotation-context.ts +157 -0
- package/corpus/templates/design/app/pages/design-editor/overview-camera.ts +62 -6
- package/corpus/templates/design/app/pages/design-editor/pending-edits.ts +245 -0
- package/corpus/templates/design/app/pages/design-editor/react-semantic-handoff.ts +586 -0
- package/corpus/templates/design/app/pages/design-editor/screen-auto-layout.ts +169 -0
- package/corpus/templates/design/app/pages/design-editor/selection-state.ts +201 -1
- package/corpus/templates/design/changelog/2026-07-09-added-underline-strikethrough-and-text-case-uppercase-lowerc.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-annotate-now-draws-across-the-all-screens-canvas-without-swi.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-auto-layout-children-can-now-be-dragged-into-freeform-screen.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-board-shapes-now-stay-visible-and-nest-correctly-across-the-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-component-source-navigation-now-opens-reliably-from-the-insp.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-cross-screen-local-react-layer-moves-now-hand-off-exact-sour.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-cross-screen-moves-undo-and-redo-now-keep-both-screens-stabl.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-detach-a-component-instance-into-plain-editable-eleme.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-dragging-layers-into-auto-layout-now-respects-ignore-auto-la.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-drawing-annotations-sent-to-the-agent-now-include-a-rendered.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-editor-sidebars-now-use-figma-matched-default-widths-for-a-r.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-empty-frames-and-rectangles-now-expose-full-auto-layout-cont.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-export-any-design-screen-as-a-real-vector-svg-for-figma-with.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-grid-auto-layout-now-uses-true-responsive-rows-and-columns-w.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-hidden-and-locked-screens-now-behave-consistently-between-la.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-image-fills-now-preserve-valid-urls-and-layered-fit-settings.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-import-figma-frames-as-pixel-accurate-design-screens-via-a-s.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-inspect-code-now-hides-internal-styling-metadata-and-wraps-l.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-inspector-blur-and-shadow-effects-now-preserve-other-effects.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-jump-to-a-components-other-instances-from-the-inspecto.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-keyboard-shortcuts-are-now-discoverable-in-a-figma-style-bot.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-layer-selection-now-keeps-cmd-or-ctrl-toggles-and-shift-rang.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-layers-dropped-into-auto-layout-now-participate-correctly-in.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-local-live-edit-screens-now-enter-and-leave-full-view-withou.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-local-preview-urls-now-live-in-the-inspector-instead-of-taki.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-local-react-layers-can-now-be-hidden-and-locked-from-layers-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-local-react-layers-now-keep-exact-source-provenance-and-supp.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-local-react-visual-editing-now-loads-reliably-and-shows-live.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-paste-from-figma-cmd-v-now-imports-exact-editable-nodes-when.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-pressing-escape-after-selecting-a-screen-now-reveals-page-pr.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-right-click-overlapping-or-nested-objects-to-choose-the-exac.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-scale-edge-stretch-and-center-constraints-now-preserve-layer.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-screen-rows-can-now-be-reordered-in-layers-with-matching-can.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-screen-selection-stays-responsive-in-designs-with-hundreds-o.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-shift-a-now-enables-auto-layout-on-a-selected-screen-with-fl.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-swap-a-component-instance-for-another-from-the-libra.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-drawing-annotations-now-stay-available-to-retry-when-the.md +6 -0
- package/corpus/templates/design/e2e/global-setup.ts +3 -6
- package/corpus/templates/design/e2e/helpers.ts +27 -6
- package/corpus/templates/design/server/lib/design-to-figma-svg.ts +1412 -0
- package/corpus/templates/design/server/lib/figma-clipboard-match.ts +196 -0
- package/corpus/templates/design/server/lib/figma-node-import.ts +311 -0
- package/corpus/templates/design/server/lib/figma-node-to-html.ts +1334 -0
- package/corpus/templates/design/server/lib/figma-paste-fallback.ts +64 -0
- package/corpus/templates/design/server/lib/playwright-runtime.ts +78 -0
- package/corpus/templates/design/server/plugins/db.ts +41 -0
- package/corpus/templates/design/server/source-workspace.ts +64 -0
- package/corpus/templates/design/shared/board-file.ts +13 -2
- package/corpus/templates/design/shared/canvas-math.ts +231 -33
- package/corpus/templates/design/shared/code-layer.ts +122 -8
- package/corpus/templates/design/shared/component-library.ts +161 -0
- package/corpus/templates/design/shared/db-conflict.ts +27 -0
- package/corpus/templates/design/shared/design-source-capabilities.ts +2 -1
- package/corpus/templates/design/shared/figma-url.ts +149 -0
- package/corpus/templates/design/shared/pen-path.ts +16 -7
- package/corpus/templates/design/shared/source-mode.ts +1 -0
- package/corpus/templates/plan/app/components/plan/CanvasArea.tsx +7 -19
- package/corpus/templates/plan/changelog/2026-07-09-canvas-panning-now-keeps-zoom-fixed-even-at-the-edges.md +6 -0
- package/corpus/templates/slides/actions/index-design-system-with-builder.ts +16 -1
- package/corpus/templates/slides/app/context/DeckContext.tsx +311 -70
- package/corpus/templates/slides/changelog/2026-07-09-fixed-the-slide-rail-going-permanently-stale-during-a-long-a.md +6 -0
- package/dist/agent/production-agent.d.ts +79 -6
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +161 -14
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +29 -5
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/run-store.d.ts +46 -0
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +61 -0
- package/dist/agent/run-store.js.map +1 -1
- package/dist/cli/design-connect.d.ts +6 -0
- package/dist/cli/design-connect.d.ts.map +1 -1
- package/dist/cli/design-connect.js +336 -139
- package/dist/cli/design-connect.js.map +1 -1
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +14 -0
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +2 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +19 -3
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +38 -18
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/agent-chat.d.ts +60 -0
- package/dist/client/agent-chat.d.ts.map +1 -1
- package/dist/client/agent-chat.js +122 -1
- package/dist/client/agent-chat.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/extensions/EmbeddedExtension.d.ts +12 -0
- package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -1
- package/dist/client/extensions/EmbeddedExtension.js +36 -2
- package/dist/client/extensions/EmbeddedExtension.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/rich-markdown-editor/useCollabReconcile.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/useCollabReconcile.js +18 -6
- package/dist/client/rich-markdown-editor/useCollabReconcile.js.map +1 -1
- package/dist/collab/awareness-store.d.ts +5 -0
- package/dist/collab/awareness-store.d.ts.map +1 -1
- package/dist/collab/awareness-store.js +19 -12
- package/dist/collab/awareness-store.js.map +1 -1
- package/dist/collab/client.d.ts.map +1 -1
- package/dist/collab/client.js +13 -5
- package/dist/collab/client.js.map +1 -1
- package/dist/collab/index.d.ts +1 -0
- package/dist/collab/index.d.ts.map +1 -1
- package/dist/collab/index.js +1 -0
- package/dist/collab/index.js.map +1 -1
- package/dist/collab/recent-edits.d.ts +3 -1
- package/dist/collab/recent-edits.d.ts.map +1 -1
- package/dist/collab/recent-edits.js +57 -2
- package/dist/collab/recent-edits.js.map +1 -1
- package/dist/index.browser.d.ts +1 -1
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.browser.js +1 -1
- package/dist/index.browser.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +87 -10
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/builder-design-systems.d.ts +15 -0
- package/dist/server/builder-design-systems.d.ts.map +1 -1
- package/dist/server/builder-design-systems.js +9 -4
- package/dist/server/builder-design-systems.js.map +1 -1
- package/package.json +1 -1
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
//! | `audio_transcription_reset_timeline`| Rebase transcript timestamps to now. |
|
|
26
26
|
//! | `audio_transcription_stop` | Stop the capture. |
|
|
27
27
|
//!
|
|
28
|
-
//! `start_raw_system_capture` (in the `macos`
|
|
29
|
-
//!
|
|
28
|
+
//! `start_raw_system_capture` and `start_raw_meeting_capture` (in the `macos`
|
|
29
|
+
//! submodule) are the capture entry points the Whisper engine calls directly.
|
|
30
30
|
//!
|
|
31
31
|
//! ## Events
|
|
32
32
|
//! - `voice:audio-level` `{ level, source: "system" }` — waveform meter.
|
|
@@ -124,7 +124,10 @@ pub async fn audio_transcription_start(
|
|
|
124
124
|
mic_device_id,
|
|
125
125
|
mic_device_label,
|
|
126
126
|
capture_system.unwrap_or(true),
|
|
127
|
-
|
|
127
|
+
// Fail safe for meeting/recording callers: an omitted flag must not
|
|
128
|
+
// create a second VoiceProcessingIO stack beside a live call app.
|
|
129
|
+
// Short dictation sessions opt in explicitly from the renderer.
|
|
130
|
+
voice_processing.unwrap_or(false),
|
|
128
131
|
owner,
|
|
129
132
|
)
|
|
130
133
|
.await
|
|
@@ -246,6 +249,8 @@ pub(crate) mod macos {
|
|
|
246
249
|
app: AppHandle,
|
|
247
250
|
cancelled: Arc<AtomicBool>,
|
|
248
251
|
level_tick: Arc<AtomicU32>,
|
|
252
|
+
output_type: SCStreamOutputType,
|
|
253
|
+
source: &'static str,
|
|
249
254
|
}
|
|
250
255
|
|
|
251
256
|
// SAFETY: `Retained<SFSpeech*>` and `Retained<AVAudioFormat>` wrap
|
|
@@ -261,7 +266,7 @@ pub(crate) mod macos {
|
|
|
261
266
|
sample_buffer: CMSampleBuffer,
|
|
262
267
|
of_type: SCStreamOutputType,
|
|
263
268
|
) {
|
|
264
|
-
if of_type !=
|
|
269
|
+
if of_type != self.output_type {
|
|
265
270
|
return;
|
|
266
271
|
}
|
|
267
272
|
if self.cancelled.load(Ordering::SeqCst) {
|
|
@@ -287,7 +292,7 @@ pub(crate) mod macos {
|
|
|
287
292
|
"voice:audio-level",
|
|
288
293
|
AudioLevelPayload {
|
|
289
294
|
level,
|
|
290
|
-
source:
|
|
295
|
+
source: self.source,
|
|
291
296
|
},
|
|
292
297
|
);
|
|
293
298
|
}
|
|
@@ -295,17 +300,18 @@ pub(crate) mod macos {
|
|
|
295
300
|
}
|
|
296
301
|
}
|
|
297
302
|
|
|
298
|
-
/// Handle for a running raw
|
|
299
|
-
|
|
303
|
+
/// Handle for a running raw SCK audio capture. A meeting capture can carry
|
|
304
|
+
/// both system and microphone output handlers on this one stream.
|
|
305
|
+
pub(crate) struct RawSckAudioCapture {
|
|
300
306
|
stream: SCStream,
|
|
301
307
|
cancelled: Arc<AtomicBool>,
|
|
302
308
|
}
|
|
303
309
|
|
|
304
310
|
// SAFETY: `SCStream` is `Send` (the crate marks it so); the atomic is
|
|
305
311
|
// trivially `Send`. We only move the handle through ownership.
|
|
306
|
-
unsafe impl Send for
|
|
312
|
+
unsafe impl Send for RawSckAudioCapture {}
|
|
307
313
|
|
|
308
|
-
impl
|
|
314
|
+
impl RawSckAudioCapture {
|
|
309
315
|
pub(crate) fn stop(self) {
|
|
310
316
|
self.cancelled.store(true, Ordering::SeqCst);
|
|
311
317
|
let _ = self.stream.stop_capture();
|
|
@@ -317,7 +323,50 @@ pub(crate) mod macos {
|
|
|
317
323
|
pub(crate) fn start_raw_system_capture(
|
|
318
324
|
app: AppHandle,
|
|
319
325
|
on_samples: Arc<dyn Fn(&[f32]) + Send + Sync>,
|
|
320
|
-
) -> Result<
|
|
326
|
+
) -> Result<RawSckAudioCapture, String> {
|
|
327
|
+
start_raw_sck_audio_capture(app, true, None, None, Some(on_samples), None)
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/// Whether this macOS version supports ScreenCaptureKit's independent
|
|
331
|
+
/// microphone output (`SCStreamOutputType::Microphone`).
|
|
332
|
+
pub(crate) fn supports_sck_microphone_capture() -> bool {
|
|
333
|
+
let version = NSProcessInfo::processInfo().operatingSystemVersion();
|
|
334
|
+
version.majorVersion >= 15
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/// Start one ScreenCaptureKit stream with independent system-audio and
|
|
338
|
+
/// microphone callbacks. This avoids opening a second AVAudioEngine /
|
|
339
|
+
/// VoiceProcessingIO input while Zoom, Meet, or Teams owns the live-call
|
|
340
|
+
/// microphone uplink.
|
|
341
|
+
pub(crate) fn start_raw_meeting_capture(
|
|
342
|
+
app: AppHandle,
|
|
343
|
+
mic_device_id: Option<String>,
|
|
344
|
+
mic_device_label: Option<String>,
|
|
345
|
+
capture_system: bool,
|
|
346
|
+
on_mic_samples: Arc<dyn Fn(&[f32]) + Send + Sync>,
|
|
347
|
+
on_system_samples: Option<Arc<dyn Fn(&[f32]) + Send + Sync>>,
|
|
348
|
+
) -> Result<RawSckAudioCapture, String> {
|
|
349
|
+
if !supports_sck_microphone_capture() {
|
|
350
|
+
return Err("ScreenCaptureKit microphone capture requires macOS 15 or later.".into());
|
|
351
|
+
}
|
|
352
|
+
start_raw_sck_audio_capture(
|
|
353
|
+
app,
|
|
354
|
+
capture_system,
|
|
355
|
+
mic_device_id,
|
|
356
|
+
mic_device_label,
|
|
357
|
+
on_system_samples,
|
|
358
|
+
Some(on_mic_samples),
|
|
359
|
+
)
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
fn start_raw_sck_audio_capture(
|
|
363
|
+
app: AppHandle,
|
|
364
|
+
capture_system: bool,
|
|
365
|
+
mic_device_id: Option<String>,
|
|
366
|
+
mic_device_label: Option<String>,
|
|
367
|
+
on_system_samples: Option<Arc<dyn Fn(&[f32]) + Send + Sync>>,
|
|
368
|
+
on_mic_samples: Option<Arc<dyn Fn(&[f32]) + Send + Sync>>,
|
|
369
|
+
) -> Result<RawSckAudioCapture, String> {
|
|
321
370
|
let granted = unsafe { CGPreflightScreenCaptureAccess() };
|
|
322
371
|
if !granted {
|
|
323
372
|
let granted_now = unsafe { CGRequestScreenCaptureAccess() };
|
|
@@ -340,13 +389,30 @@ pub(crate) mod macos {
|
|
|
340
389
|
.with_excluding_windows(&[])
|
|
341
390
|
.build();
|
|
342
391
|
|
|
343
|
-
let
|
|
344
|
-
|
|
392
|
+
let capture_microphone = on_mic_samples.is_some();
|
|
393
|
+
let selected_mic = if capture_microphone {
|
|
394
|
+
crate::native_screen::resolve_microphone_capture_device(
|
|
395
|
+
mic_device_id.as_deref(),
|
|
396
|
+
mic_device_label.as_deref(),
|
|
397
|
+
)?
|
|
398
|
+
} else {
|
|
399
|
+
None
|
|
400
|
+
};
|
|
401
|
+
let mut config = SCStreamConfiguration::new()
|
|
402
|
+
.with_captures_audio(capture_system)
|
|
403
|
+
.with_captures_microphone(capture_microphone)
|
|
345
404
|
.with_excludes_current_process_audio(true)
|
|
346
405
|
.with_sample_rate(48000)
|
|
347
406
|
.with_channel_count(2)
|
|
348
407
|
.with_width(2)
|
|
349
408
|
.with_height(2);
|
|
409
|
+
if let Some(device) = selected_mic.as_ref() {
|
|
410
|
+
config.set_microphone_capture_device_id(&device.id);
|
|
411
|
+
eprintln!(
|
|
412
|
+
"[whisper] ScreenCaptureKit meeting microphone pinned to {} ({})",
|
|
413
|
+
device.name, device.id
|
|
414
|
+
);
|
|
415
|
+
}
|
|
350
416
|
|
|
351
417
|
// Mono float32 @ 48 kHz destination format for the mono-mix.
|
|
352
418
|
let speech_format = unsafe {
|
|
@@ -357,21 +423,37 @@ pub(crate) mod macos {
|
|
|
357
423
|
|
|
358
424
|
let cancelled = Arc::new(AtomicBool::new(false));
|
|
359
425
|
let mut stream = SCStream::new(&filter, &config);
|
|
360
|
-
let
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
426
|
+
if let Some(on_samples) = on_system_samples {
|
|
427
|
+
let forwarder = RawAudioForwarder {
|
|
428
|
+
on_samples,
|
|
429
|
+
speech_format: speech_format.clone(),
|
|
430
|
+
app: app.clone(),
|
|
431
|
+
cancelled: cancelled.clone(),
|
|
432
|
+
level_tick: Arc::new(AtomicU32::new(0)),
|
|
433
|
+
output_type: SCStreamOutputType::Audio,
|
|
434
|
+
source: "system",
|
|
435
|
+
};
|
|
436
|
+
stream.add_output_handler(forwarder, SCStreamOutputType::Audio);
|
|
437
|
+
}
|
|
438
|
+
if let Some(on_samples) = on_mic_samples {
|
|
439
|
+
let forwarder = RawAudioForwarder {
|
|
440
|
+
on_samples,
|
|
441
|
+
speech_format,
|
|
442
|
+
app: app.clone(),
|
|
443
|
+
cancelled: cancelled.clone(),
|
|
444
|
+
level_tick: Arc::new(AtomicU32::new(0)),
|
|
445
|
+
output_type: SCStreamOutputType::Microphone,
|
|
446
|
+
source: "mic",
|
|
447
|
+
};
|
|
448
|
+
stream.add_output_handler(forwarder, SCStreamOutputType::Microphone);
|
|
449
|
+
}
|
|
368
450
|
|
|
369
451
|
if let Err(e) = stream.start_capture() {
|
|
370
452
|
cancelled.store(true, Ordering::SeqCst);
|
|
371
453
|
return Err(format!("SCStream start_capture failed: {e:?}"));
|
|
372
454
|
}
|
|
373
455
|
|
|
374
|
-
Ok(
|
|
456
|
+
Ok(RawSckAudioCapture { stream, cancelled })
|
|
375
457
|
}
|
|
376
458
|
|
|
377
459
|
#[derive(Serialize, Clone)]
|
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
//! Capture is reused from the existing modules:
|
|
11
11
|
//! - mic → `native_speech::macos::start_raw_mic_capture` (AVAudioEngine +
|
|
12
12
|
//! optional VoiceProcessingIO AEC, other-audio ducking off)
|
|
13
|
-
//! -
|
|
13
|
+
//! - meetings on macOS 15+ → one ScreenCaptureKit stream with independent
|
|
14
|
+
//! microphone + system-audio outputs
|
|
15
|
+
//! - legacy system audio → `system_audio::macos::start_raw_system_capture`
|
|
14
16
|
//!
|
|
15
17
|
use tauri::AppHandle;
|
|
16
18
|
|
|
@@ -108,7 +110,10 @@ mod macos {
|
|
|
108
110
|
use whisper_rs::{FullParams, SamplingStrategy, WhisperContext, WhisperContextParameters};
|
|
109
111
|
|
|
110
112
|
use crate::native_speech::macos::{start_raw_mic_capture, RawMicCapture};
|
|
111
|
-
use crate::system_audio::macos::{
|
|
113
|
+
use crate::system_audio::macos::{
|
|
114
|
+
start_raw_meeting_capture, start_raw_system_capture, supports_sck_microphone_capture,
|
|
115
|
+
RawSckAudioCapture,
|
|
116
|
+
};
|
|
112
117
|
use crate::whisper_model::{ensure_model, model_file};
|
|
113
118
|
|
|
114
119
|
/// One transcript segment with real timestamps from whisper, already
|
|
@@ -571,11 +576,20 @@ mod macos {
|
|
|
571
576
|
}
|
|
572
577
|
}
|
|
573
578
|
|
|
579
|
+
fn should_use_combined_sck_capture(
|
|
580
|
+
owner: SessionOwner,
|
|
581
|
+
microphone_capture_supported: bool,
|
|
582
|
+
) -> bool {
|
|
583
|
+
owner == SessionOwner::Meeting && microphone_capture_supported
|
|
584
|
+
}
|
|
585
|
+
|
|
574
586
|
struct Session {
|
|
575
|
-
|
|
587
|
+
// macOS 15+ meetings use a combined SCK capture, so there is no
|
|
588
|
+
// competing AVAudioEngine / VoiceProcessingIO mic input to stop.
|
|
589
|
+
mic_cap: Option<RawMicCapture>,
|
|
576
590
|
// System capture is optional — skipped when the user turns system
|
|
577
591
|
// audio off, so neither the recording nor the transcript include it.
|
|
578
|
-
sys_cap: Option<
|
|
592
|
+
sys_cap: Option<RawSckAudioCapture>,
|
|
579
593
|
mic: Arc<WhisperStream>,
|
|
580
594
|
sys: Option<Arc<WhisperStream>>,
|
|
581
595
|
/// Who started this session — see `SessionOwner`.
|
|
@@ -644,8 +658,10 @@ mod macos {
|
|
|
644
658
|
let _ = language;
|
|
645
659
|
let lang: Option<String> = None;
|
|
646
660
|
|
|
647
|
-
//
|
|
648
|
-
//
|
|
661
|
+
// Create both Whisper streams first. On macOS 15+ meetings, one
|
|
662
|
+
// ScreenCaptureKit stream feeds both callbacks without opening a
|
|
663
|
+
// competing VoiceProcessingIO mic input. Older macOS versions (and a
|
|
664
|
+
// failed SCK start) keep the existing split-capture fallback.
|
|
649
665
|
let session_start = Instant::now();
|
|
650
666
|
let mic_stream = WhisperStream::new(
|
|
651
667
|
app.clone(),
|
|
@@ -655,50 +671,92 @@ mod macos {
|
|
|
655
671
|
ctx.clone(),
|
|
656
672
|
session_start,
|
|
657
673
|
);
|
|
658
|
-
let
|
|
659
|
-
|
|
660
|
-
let mic_cap = start_raw_mic_capture(
|
|
661
|
-
app.clone(),
|
|
662
|
-
mic_device_id,
|
|
663
|
-
mic_device_label,
|
|
664
|
-
voice_processing,
|
|
665
|
-
reuse_voice_processing_engine,
|
|
666
|
-
Arc::new(move |s: &[f32]| mic_for_cb.push(s)),
|
|
667
|
-
)
|
|
668
|
-
.map_err(|e| {
|
|
669
|
-
mic_stream.stop();
|
|
670
|
-
format!("mic capture failed: {e}")
|
|
671
|
-
})?;
|
|
672
|
-
mic_stream.set_src_rate(mic_cap.sample_rate());
|
|
673
|
-
|
|
674
|
-
// System stream + capture (SCK delivers 48 kHz). Skipped entirely when
|
|
675
|
-
// system audio is off.
|
|
676
|
-
let (sys_stream, sys_cap) = if capture_system {
|
|
677
|
-
let sys_stream = WhisperStream::new(
|
|
674
|
+
let sys_stream = capture_system.then(|| {
|
|
675
|
+
WhisperStream::new(
|
|
678
676
|
app.clone(),
|
|
679
677
|
"system",
|
|
680
678
|
48000.0,
|
|
681
679
|
lang.clone(),
|
|
682
680
|
ctx.clone(),
|
|
683
681
|
session_start,
|
|
684
|
-
)
|
|
685
|
-
|
|
686
|
-
|
|
682
|
+
)
|
|
683
|
+
});
|
|
684
|
+
let mic_for_cb = mic_stream.clone();
|
|
685
|
+
let mic_callback: Arc<dyn Fn(&[f32]) + Send + Sync> =
|
|
686
|
+
Arc::new(move |samples: &[f32]| mic_for_cb.push(samples));
|
|
687
|
+
let system_callback: Option<Arc<dyn Fn(&[f32]) + Send + Sync>> =
|
|
688
|
+
sys_stream.as_ref().map(|stream| {
|
|
689
|
+
let stream = stream.clone();
|
|
690
|
+
Arc::new(move |samples: &[f32]| stream.push(samples))
|
|
691
|
+
as Arc<dyn Fn(&[f32]) + Send + Sync>
|
|
692
|
+
});
|
|
693
|
+
|
|
694
|
+
let combined_cap = if should_use_combined_sck_capture(
|
|
695
|
+
owner,
|
|
696
|
+
supports_sck_microphone_capture(),
|
|
697
|
+
) {
|
|
698
|
+
match start_raw_meeting_capture(
|
|
687
699
|
app.clone(),
|
|
688
|
-
|
|
700
|
+
mic_device_id.clone(),
|
|
701
|
+
mic_device_label.clone(),
|
|
702
|
+
capture_system,
|
|
703
|
+
mic_callback.clone(),
|
|
704
|
+
system_callback.clone(),
|
|
689
705
|
) {
|
|
690
|
-
Ok(cap) =>
|
|
706
|
+
Ok(cap) => {
|
|
707
|
+
eprintln!("[whisper] using combined ScreenCaptureKit mic + system capture");
|
|
708
|
+
Some(cap)
|
|
709
|
+
}
|
|
691
710
|
Err(e) => {
|
|
692
|
-
|
|
711
|
+
eprintln!(
|
|
712
|
+
"[whisper] combined ScreenCaptureKit meeting capture failed: {e}; falling back to split capture"
|
|
713
|
+
);
|
|
714
|
+
None
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
} else {
|
|
718
|
+
None
|
|
719
|
+
};
|
|
720
|
+
|
|
721
|
+
let (mic_cap, sys_cap) = if let Some(combined_cap) = combined_cap {
|
|
722
|
+
// Both SCK outputs are configured at 48 kHz.
|
|
723
|
+
mic_stream.set_src_rate(48000.0);
|
|
724
|
+
(None, Some(combined_cap))
|
|
725
|
+
} else {
|
|
726
|
+
let reuse_voice_processing_engine = owner == SessionOwner::Dictation && !capture_system;
|
|
727
|
+
let mic_cap = start_raw_mic_capture(
|
|
728
|
+
app.clone(),
|
|
729
|
+
mic_device_id,
|
|
730
|
+
mic_device_label,
|
|
731
|
+
voice_processing,
|
|
732
|
+
reuse_voice_processing_engine,
|
|
733
|
+
mic_callback,
|
|
734
|
+
)
|
|
735
|
+
.map_err(|e| {
|
|
736
|
+
mic_stream.stop();
|
|
737
|
+
if let Some(sys_stream) = &sys_stream {
|
|
693
738
|
sys_stream.stop();
|
|
694
|
-
mic_stream.stop();
|
|
695
|
-
mic_cap.stop();
|
|
696
|
-
return Err(format!("system capture failed: {e}"));
|
|
697
739
|
}
|
|
740
|
+
format!("mic capture failed: {e}")
|
|
741
|
+
})?;
|
|
742
|
+
mic_stream.set_src_rate(mic_cap.sample_rate());
|
|
743
|
+
|
|
744
|
+
let sys_cap = if let Some(system_callback) = system_callback {
|
|
745
|
+
match start_raw_system_capture(app.clone(), system_callback) {
|
|
746
|
+
Ok(cap) => Some(cap),
|
|
747
|
+
Err(e) => {
|
|
748
|
+
if let Some(sys_stream) = &sys_stream {
|
|
749
|
+
sys_stream.stop();
|
|
750
|
+
}
|
|
751
|
+
mic_stream.stop();
|
|
752
|
+
mic_cap.stop();
|
|
753
|
+
return Err(format!("system capture failed: {e}"));
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
} else {
|
|
757
|
+
None
|
|
698
758
|
};
|
|
699
|
-
(Some(
|
|
700
|
-
} else {
|
|
701
|
-
(None, None)
|
|
759
|
+
(Some(mic_cap), sys_cap)
|
|
702
760
|
};
|
|
703
761
|
|
|
704
762
|
let mut slot = session_slot().lock().map_err(|e| e.to_string())?;
|
|
@@ -750,7 +808,9 @@ mod macos {
|
|
|
750
808
|
sys.stop();
|
|
751
809
|
}
|
|
752
810
|
// Stop captures so no more samples arrive while workers flush.
|
|
753
|
-
session.mic_cap
|
|
811
|
+
if let Some(mic_cap) = session.mic_cap {
|
|
812
|
+
mic_cap.stop();
|
|
813
|
+
}
|
|
754
814
|
if let Some(sys_cap) = session.sys_cap {
|
|
755
815
|
sys_cap.stop();
|
|
756
816
|
}
|
|
@@ -769,4 +829,22 @@ mod macos {
|
|
|
769
829
|
}
|
|
770
830
|
eprintln!("[whisper] meeting transcription stopped");
|
|
771
831
|
}
|
|
832
|
+
|
|
833
|
+
#[cfg(test)]
|
|
834
|
+
mod tests {
|
|
835
|
+
use super::{should_use_combined_sck_capture, SessionOwner};
|
|
836
|
+
|
|
837
|
+
#[test]
|
|
838
|
+
fn combined_sck_capture_is_only_selected_for_supported_meetings() {
|
|
839
|
+
assert!(should_use_combined_sck_capture(SessionOwner::Meeting, true));
|
|
840
|
+
assert!(!should_use_combined_sck_capture(
|
|
841
|
+
SessionOwner::Meeting,
|
|
842
|
+
false
|
|
843
|
+
));
|
|
844
|
+
assert!(!should_use_combined_sck_capture(
|
|
845
|
+
SessionOwner::Dictation,
|
|
846
|
+
true
|
|
847
|
+
));
|
|
848
|
+
}
|
|
849
|
+
}
|
|
772
850
|
}
|
|
@@ -28,6 +28,7 @@ type SlackUnfurlRecording = {
|
|
|
28
28
|
id: string;
|
|
29
29
|
title: string;
|
|
30
30
|
description: string;
|
|
31
|
+
durationMs: number;
|
|
31
32
|
thumbnailUrl: string | null;
|
|
32
33
|
animatedThumbnailUrl: string | null;
|
|
33
34
|
visibility: string | null;
|
|
@@ -205,6 +206,19 @@ function isExpired(value: string | null): boolean {
|
|
|
205
206
|
return Number.isFinite(expires) && expires < Date.now();
|
|
206
207
|
}
|
|
207
208
|
|
|
209
|
+
function formatSlackDuration(durationMs: number): string | null {
|
|
210
|
+
if (!Number.isFinite(durationMs) || durationMs <= 0) return null;
|
|
211
|
+
const totalSeconds = Math.floor(durationMs / 1000);
|
|
212
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
213
|
+
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
|
214
|
+
const seconds = totalSeconds % 60;
|
|
215
|
+
return hours > 0
|
|
216
|
+
? `${hours}:${minutes.toString().padStart(2, "0")}:${seconds
|
|
217
|
+
.toString()
|
|
218
|
+
.padStart(2, "0")}`
|
|
219
|
+
: `${minutes}:${seconds.toString().padStart(2, "0")}`;
|
|
220
|
+
}
|
|
221
|
+
|
|
208
222
|
export function isSlackPlayableRecording(
|
|
209
223
|
recording: SlackUnfurlRecording,
|
|
210
224
|
): boolean {
|
|
@@ -236,7 +250,11 @@ export function buildSlackVideoBlock(options: {
|
|
|
236
250
|
origin,
|
|
237
251
|
).toString();
|
|
238
252
|
const title = displayRecordingTitle(recording.title);
|
|
239
|
-
const
|
|
253
|
+
const shareDescription = clipsShareDescription(recording);
|
|
254
|
+
const duration = formatSlackDuration(recording.durationMs);
|
|
255
|
+
const description = duration
|
|
256
|
+
? `${duration} · ${shareDescription}`
|
|
257
|
+
: shareDescription;
|
|
240
258
|
const thumbnailUrl = absoluteUrl(
|
|
241
259
|
recording.thumbnailUrl || recording.animatedThumbnailUrl,
|
|
242
260
|
origin,
|
|
@@ -265,6 +283,7 @@ export async function loadSlackVideoBlockForUrl(
|
|
|
265
283
|
id: schema.recordings.id,
|
|
266
284
|
title: schema.recordings.title,
|
|
267
285
|
description: schema.recordings.description,
|
|
286
|
+
durationMs: schema.recordings.durationMs,
|
|
268
287
|
thumbnailUrl: schema.recordings.thumbnailUrl,
|
|
269
288
|
animatedThumbnailUrl: schema.recordings.animatedThumbnailUrl,
|
|
270
289
|
visibility: schema.recordings.visibility,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { enabledFlag } from "./env-flags.js";
|
|
2
2
|
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
3
|
+
// Local/dev deployments can opt into resumable uploads while retaining their
|
|
4
|
+
// SQL scratch fallback. Hosted deployments have no safe buffered fallback, so
|
|
5
|
+
// requested video uploads use resumable storage unless explicitly disabled.
|
|
6
6
|
export function isStreamingUploadDisabled(): boolean {
|
|
7
7
|
return enabledFlag(process.env.CLIPS_DISABLE_STREAMING_UPLOAD);
|
|
8
8
|
}
|
|
@@ -10,9 +10,15 @@ export function isStreamingUploadDisabled(): boolean {
|
|
|
10
10
|
export function shouldEnableStreamingUpload(args: {
|
|
11
11
|
client?: string | null;
|
|
12
12
|
mimeType?: string | null;
|
|
13
|
+
bufferedFallbackAvailable?: boolean;
|
|
13
14
|
}): boolean {
|
|
14
15
|
if (isStreamingUploadDisabled()) return false;
|
|
15
|
-
if (
|
|
16
|
+
if (
|
|
17
|
+
args.bufferedFallbackAvailable !== false &&
|
|
18
|
+
!enabledFlag(process.env.CLIPS_ENABLE_STREAMING_UPLOAD)
|
|
19
|
+
) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
16
22
|
|
|
17
23
|
const mimeType = (args.mimeType ?? "").split(";")[0]?.trim().toLowerCase();
|
|
18
24
|
return !mimeType || mimeType.startsWith("video/");
|
|
@@ -51,6 +51,18 @@ export function pickMimeType(): string {
|
|
|
51
51
|
* - `"buffered"` — full blob assembled after stop() and uploaded in slices */
|
|
52
52
|
export type UploadMode = "streaming" | "buffered";
|
|
53
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Resumable providers advance a single byte offset, so their chunks must be
|
|
56
|
+
* sent in strict index order. Buffered uploads can retain bounded parallelism.
|
|
57
|
+
*/
|
|
58
|
+
export function chunkUploadParallelism(
|
|
59
|
+
uploadMode: UploadMode | undefined,
|
|
60
|
+
bufferedParallelism: number,
|
|
61
|
+
): number {
|
|
62
|
+
if (uploadMode === "streaming") return 1;
|
|
63
|
+
return Math.max(1, Math.floor(bufferedParallelism));
|
|
64
|
+
}
|
|
65
|
+
|
|
54
66
|
/** Query params understood by the chunk-upload route
|
|
55
67
|
* (`/api/uploads/:id/chunk`). This is the on-the-wire contract — the route in
|
|
56
68
|
* `server/routes/api/uploads/[recordingId]/chunk.post.ts` reads exactly these. */
|
|
@@ -158,13 +158,14 @@ to SQL. `pull-document` closes that gap with a flush handshake — if a live Yjs
|
|
|
158
158
|
collab session exists for the document it writes a one-shot `flush-request-<id>`
|
|
159
159
|
application-state key (scoped to the browser session, just like `navigate`); the
|
|
160
160
|
open editor sees that key, serializes its current document to markdown through
|
|
161
|
-
its own existing serializer, calls `update-document`, and
|
|
162
|
-
`pull-document` waits for
|
|
163
|
-
|
|
161
|
+
its own existing serializer, calls `update-document`, and writes an explicit
|
|
162
|
+
request-id-matched success/error acknowledgement. `pull-document` waits for that
|
|
163
|
+
acknowledgement and fails closed if the open editor cannot save; when no active
|
|
164
|
+
human editor is present, the SQL column is authoritative and the handshake is
|
|
164
165
|
skipped. It is GET + read-only + public-agent exposed (`requiresAuth: true`),
|
|
165
|
-
returns `{ id, title, content, format, deepLink }`, and surfaces an
|
|
166
|
-
|
|
167
|
-
|
|
166
|
+
returns `{ id, title, content, format, deepLink }`, and surfaces an "Open
|
|
167
|
+
document" deep link for external agents. Use `--format text` for a plain-text
|
|
168
|
+
strip of the markdown.
|
|
168
169
|
|
|
169
170
|
### Local Source Files
|
|
170
171
|
|