auricui-skill 0.0.0-stage → 0.1.2
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/LICENSE +21 -0
- package/README.md +29 -2
- package/bin/install.mjs +66 -0
- package/package.json +29 -4
- package/skill/SKILL.md +64 -0
- package/skill/agents/openai.yaml +4 -0
- package/skill/assets/examples/ApprovalCard.tsx +8 -0
- package/skill/assets/examples/BasicApp.tsx +38 -0
- package/skill/assets/examples/BriefingCard.tsx +8 -0
- package/skill/assets/examples/ChatControls.tsx +49 -0
- package/skill/assets/examples/ChatPanel.tsx +73 -0
- package/skill/assets/examples/Checkbox.tsx +13 -0
- package/skill/assets/examples/Combobox.tsx +14 -0
- package/skill/assets/examples/Drawer.tsx +10 -0
- package/skill/assets/examples/MemoryCard.tsx +9 -0
- package/skill/assets/examples/MessageList.tsx +8 -0
- package/skill/assets/examples/Theme.tsx +14 -0
- package/skill/assets/examples/ToolCall.tsx +8 -0
- package/skill/assets/examples/Tree.tsx +15 -0
- package/skill/assets/examples/examples.css +11 -0
- package/skill/assets/library/auricui-0.1.0-preview.1.tgz +0 -0
- package/skill/assets/library/auricui-0.1.0-preview.3.tgz +0 -0
- package/skill/assets/library/auricui-0.1.0-preview.4.tgz +0 -0
- package/skill/assets/upstream/LICENSE +21 -0
- package/skill/assets/upstream/apps/desktop/chat/src/App.tsx +1099 -0
- package/skill/assets/upstream/apps/desktop/chat/src/app-bridge.ts +154 -0
- package/skill/assets/upstream/apps/desktop/chat/src/chat.css +1812 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/AddSkill.tsx +223 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/AgentActivityRow.tsx +716 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/AgentIcons.tsx +46 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/AttachmentCard.tsx +34 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/AttachmentPreview.tsx +331 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/BalanceNotice.tsx +22 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/BrandLogo.tsx +35 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/ComposerCard.tsx +182 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/ConversationSessionBar.tsx +292 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/CopyDiagnostics.tsx +24 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/Divider.tsx +47 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/FileChangesList.tsx +119 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/Markdown.tsx +198 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/ModelPopover.tsx +280 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/NoticeCard.tsx +87 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/Popover.tsx +195 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/PreviewFrame.tsx +129 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/ProjectConversation.tsx +852 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/ProjectStarters.tsx +118 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/Tooltip.tsx +191 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/TurnLog.tsx +583 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/TurnQuestionCard.tsx +133 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/dock-pane-bar.ts +14 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/project-version.ts +37 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/prompt-editor/MentionMenuPlugin.tsx +372 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/prompt-editor/PromptEditor.tsx +476 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/prompt-editor/PromptPill.tsx +399 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/prompt-editor/PromptReferenceNode.tsx +164 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/prompt-editor/index.ts +31 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/prompt-editor/mention-menu.ts +206 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/prompt-editor/prompt-text.ts +171 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/useStickToBottom.ts +320 -0
- package/skill/assets/upstream/apps/desktop/chat/src/components/useTicker.ts +55 -0
- package/skill/assets/upstream/apps/desktop/chat/src/i18n/index.ts +42 -0
- package/skill/assets/upstream/apps/desktop/chat/src/i18n/locales/en-US.ts +408 -0
- package/skill/assets/upstream/apps/desktop/chat/src/i18n/locales/es.ts +407 -0
- package/skill/assets/upstream/apps/desktop/chat/src/i18n/locales/ja.ts +407 -0
- package/skill/assets/upstream/apps/desktop/chat/src/i18n/locales/ko.ts +403 -0
- package/skill/assets/upstream/apps/desktop/chat/src/i18n/locales/words.ts +6 -0
- package/skill/assets/upstream/apps/desktop/chat/src/i18n/locales/zh-CN.ts +407 -0
- package/skill/assets/upstream/apps/desktop/chat/src/i18n/lookup.ts +12 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/agent-activity-runs.ts +154 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/agent-menu-rows.ts +41 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/agent-refs.ts +105 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/agent-transcript.ts +440 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/asset-lists.ts +75 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/attachment-place.ts +17 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/balance.ts +16 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/chat-layer.ts +10 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/chat-menu.ts +18 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/chat-store.ts +101 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/composer-attachments.ts +189 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/desktop-attachments.ts +178 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/desktop-bridge.ts +291 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/developer.ts +39 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/esc-stop.ts +23 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/file-changes.ts +32 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/live-activity.ts +20 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/local-agent-run.ts +1174 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/local-sessions.ts +25 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/model-calls.ts +87 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/pretty-json.ts +12 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/preview-top.ts +15 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/project-resources.ts +66 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/project-sessions.ts +66 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/project-versions.ts +116 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/ref-pictures.ts +119 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/relative-time.ts +46 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/skill-pages.ts +29 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/step-file.ts +23 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/structural-share.ts +52 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/studio-film.ts +44 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/studio-transfer.ts +40 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/unprompted.ts +27 -0
- package/skill/assets/upstream/apps/desktop/chat/src/lib/upload-limits.ts +53 -0
- package/skill/assets/upstream/apps/desktop/chat/src/mount.tsx +19 -0
- package/skill/assets/upstream/apps/desktop/chat/src/state/local-agent-store.ts +296 -0
- package/skill/assets/upstream/apps/desktop/chat/src/studio-refs.ts +307 -0
- package/skill/assets/upstream/apps/desktop/package.json +51 -0
- package/skill/assets/upstream/apps/desktop/shell/bridge.ts +415 -0
- package/skill/assets/upstream/apps/desktop/shell/index.html +27 -0
- package/skill/assets/upstream/apps/desktop/shell/main.tsx +17 -0
- package/skill/assets/upstream/apps/desktop/shell/shell.css +17 -0
- package/skill/assets/upstream/apps/desktop/shell/vite.config.ts +65 -0
- package/skill/assets/upstream/apps/desktop/src/agent-definitions.mjs +31 -0
- package/skill/assets/upstream/packages/openfilm/LICENSE +21 -0
- package/skill/assets/upstream/packages/openfilm/package.json +88 -0
- package/skill/assets/upstream/packages/openfilm/src/film-doc.d.mts +125 -0
- package/skill/assets/upstream/packages/openfilm/src/film-doc.mjs +986 -0
- package/skill/assets/upstream/packages/openfilm/src/overrides.mjs +73 -0
- package/skill/assets/upstream/packages/openfilm/src/timeline.mjs +1280 -0
- package/skill/assets/upstream/packages/openfilm/studio/server/bridge.js +209 -0
- package/skill/assets/upstream/packages/openfilm/studio/server/film-subtitle.mjs +785 -0
- package/skill/assets/upstream/packages/openfilm/studio/server/ops.mjs +403 -0
- package/skill/assets/upstream/packages/openfilm/studio/server/stage.js +1649 -0
- package/skill/assets/upstream/packages/openfilm/studio/server/track-layout.mjs +43 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/App.tsx +156 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/api.ts +328 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/AudioMeters.tsx +188 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/BlockThumbs.tsx +84 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/BlockWaveform.tsx +201 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/BrandLoadingScreen.tsx +56 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/BrandLogo.tsx +25 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/Card.tsx +89 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/ColorPicker.tsx +204 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/ConfirmDialog.tsx +96 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/ContextMenu.tsx +422 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/DesktopDialog.tsx +271 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/ExamplesGallery.tsx +372 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/FilmFullscreenBar.tsx +147 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/FilmInspector.tsx +2310 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/FilmStageSelect.tsx +3296 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/FocusNav.tsx +28 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/FontFamilyPicker.tsx +293 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/FramePicker.tsx +69 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/InspectorPanel.tsx +25 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/Launcher.tsx +38 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/LayersPanel.tsx +277 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/LiveTime.tsx +101 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/MediaPool.tsx +1413 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/MediaPreview.tsx +188 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/MenuSelect.tsx +161 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/MgOutline.tsx +24 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/OperationHistory.tsx +184 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/PaneDivider.tsx +292 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/PasteAttrsDialog.tsx +69 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/PlaybackMenu.tsx +110 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/Popover.tsx +159 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/ProjectCover.tsx +60 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/ProjectHistoryControls.tsx +748 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/ProjectLayoutMenu.tsx +82 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/ProjectMenu.tsx +111 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/ProjectSources.tsx +587 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/ProjectView.tsx +3222 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/ProjectsLibrary.tsx +567 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/ProjectsView.tsx +1593 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/PropertiesSection.tsx +418 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/ResourceInspector.tsx +100 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/SelectionToolbar.tsx +157 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/SkillsLibrary.tsx +504 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/SourcePreview.tsx +464 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/SpendAsks.tsx +88 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/StageMaskOverlay.tsx +299 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/StageTransformFrame.tsx +246 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/SubtitleInspector.module.css +46 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/SubtitleInspector.tsx +884 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/SubtitleOverlay.tsx +148 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/SubtitleRow.tsx +419 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/TabStrip.tsx +188 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/Timeline.tsx +4911 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/TimelineMarkers.tsx +329 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/Toast.tsx +55 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/Tooltip.tsx +193 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/UpdateButton.tsx +104 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/ViewerBar.tsx +98 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/WhatsNew.tsx +147 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/dock-pane-bar.ts +16 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/export/ExportCenter.tsx +1502 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/export/ExportTray.tsx +284 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/film-stage-hit.ts +18 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/inspector-fields.tsx +863 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/inspector-look.tsx +1357 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/player-controls/controls-bar.tsx +397 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/player-controls/transport.tsx +294 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/replace-drop.ts +20 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/settings/AgentsSection.tsx +613 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/settings/CustomServices.tsx +104 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/settings/DiagnosticsGroup.tsx +202 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/settings/ModelsSection.tsx +179 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/settings/ProviderMark.tsx +24 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/settings/ProvidersSection.tsx +177 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/settings/SettingsModal.tsx +511 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/settings/SettingsSelect.tsx +84 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/settings/ShortcutsSection.tsx +291 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/settings/StorageGroup.tsx +119 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/settings/theme.ts +47 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/settings/ui.tsx +139 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/settings/use-settings.ts +10 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/stage-menu.tsx +283 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/timeline-head-extras.tsx +91 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/typing-target.ts +45 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/use-editor-tools.tsx +408 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/use-page-changes.ts +48 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/use-project-history.ts +113 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/components/useBlockDrag.ts +639 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/editor/Preview.tsx +426 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/editor/player.ts +558 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/editor/preview-frames.ts +36 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/editor/steps.ts +36 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/editor/undo.ts +156 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/editor/use-film.ts +212 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/editor/use-preview-renders.ts +89 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/globals.css +559 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/i18n/en.ts +1901 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/i18n/es.ts +1900 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/i18n/index.ts +130 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/i18n/ja.ts +1900 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/i18n/ko.ts +1896 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/i18n/words.ts +6 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/i18n/zh-CN.ts +1901 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/agent-row.ts +21 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/asset-timeline.ts +469 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/audio-levels.ts +60 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/batch-map.ts +28 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/browser.ts +10 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/canvas-fit.ts +116 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/chat-marks.ts +114 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/clip-attrs.ts +102 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/clip-fade.ts +70 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/clip-look.ts +520 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/clip-mask.ts +536 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/clip-replace.ts +60 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/component-props.ts +128 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/context-length.ts +12 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/desktop-build.ts +44 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/diagnostics.ts +68 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/double-press.ts +22 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/dropped-overrides.ts +139 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/export-jobs.ts +191 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/export-spec.ts +261 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/field-input.ts +155 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/film-clip-edits.ts +82 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/film-frame.ts +134 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/film-overrides.ts +107 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/film-shape.ts +172 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/film.ts +80 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/font-menu.ts +236 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/font-styles.ts +129 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/freeze-frame.ts +49 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/host.ts +438 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/inspect-scrub.ts +26 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/keymap-store.ts +74 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/keymap.ts +529 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/layers-tree.ts +133 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/look.ts +83 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/loudness.ts +58 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/markers.ts +152 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/media-bar.ts +58 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/media-folders.ts +45 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/media-place.ts +102 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/media-queue.ts +107 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/media-selection.ts +64 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/menu-position.ts +77 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/mg-transform.ts +111 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/mixed.ts +3 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/page-changes.ts +45 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/picture-files.ts +19 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/preview-prefs.ts +46 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/preview-renders.ts +71 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/project-delete.ts +20 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/project-folders.ts +144 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/project-history.ts +188 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/project-sources.ts +283 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/projects-page.ts +40 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/provider-marks.ts +35 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/providers.ts +163 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/resource-drag.ts +131 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/retry-image.ts +17 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/saved-insert.ts +40 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/saved.ts +125 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/selection-toolbar.ts +158 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/shortcut-hint.ts +21 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/similar-layers.ts +46 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/solo.ts +19 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/stage-clip.ts +60 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/stage-crop.ts +232 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/stage-gesture.ts +277 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/stage-layers.ts +71 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/stage-mask.ts +176 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/stage-measure.ts +53 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/stage-types.ts +155 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/studio-refs.ts +248 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/studio-version.ts +41 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/subtitle-cues.ts +238 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/subtitles.ts +263 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/tab-menu.ts +6 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/template-controls.ts +131 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/theme-changes.ts +31 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/thumb-cache.ts +63 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/thumb-cell.ts +8 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/thumb-frame.ts +76 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/thumb-pick.ts +42 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/timecode.ts +161 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/timeline-clipboard.ts +279 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/timeline-drag.ts +589 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/timeline-edit.ts +1138 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/timeline-keys.ts +63 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/timeline-layout.ts +1038 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/timeline-nav.ts +160 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/timeline-prefs.ts +73 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/timeline-split.ts +40 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/timeline-view.ts +105 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/title.ts +39 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/track-heights.ts +55 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/track-lock.ts +27 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/transitions.ts +459 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/type-metrics.ts +83 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/use-film-subtitles.ts +111 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/use-fonts.ts +181 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/use-loaded-thumbs.ts +91 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/use-subtitle-edits.ts +134 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/use-subtitle-font.ts +51 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/use-subtitle-style.ts +68 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/waveform-columns.ts +48 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/web-update.ts +41 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/whats-new.ts +401 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/lib/workspace-resources.ts +373 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/src/main.tsx +10 -0
- package/skill/assets/upstream/packages/openfilm/studio/ui/vite.config.ts +12 -0
- package/skill/assets/upstream/packages/shared/package.json +45 -0
- package/skill/assets/upstream/packages/shared/src/agent-activity.ts +263 -0
- package/skill/assets/upstream/packages/shared/src/contract.ts +285 -0
- package/skill/assets/upstream/packages/shared/src/index.ts +17 -0
- package/skill/assets/upstream/packages/shared/src/markdown-blocks.ts +252 -0
- package/skill/assets/upstream/packages/shared/src/modality.ts +4 -0
- package/skill/assets/upstream/packages/shared/src/prompt-reference.ts +113 -0
- package/skill/assets/upstream/packages/shared/src/title.ts +76 -0
- package/skill/assets/upstream/packages/shared/src/turn.ts +68 -0
- package/skill/assets/upstream/packages/shared/src/video.ts +26 -0
- package/skill/references/agent-components.md +33 -0
- package/skill/references/api-index.json +2693 -0
- package/skill/references/chat-components.md +65 -0
- package/skill/references/components.md +23 -0
- package/skill/references/core-components.md +44 -0
- package/skill/references/dependencies.md +22 -0
- package/skill/references/esm-package.md +48 -0
- package/skill/references/integration.md +43 -0
- package/skill/references/library-manifest.json +12 -0
- package/skill/references/source-manifest.json +325 -0
- package/skill/references/studio-components.md +24 -0
- package/skill/references/theme-motion.md +49 -0
- package/skill/references/troubleshooting.md +27 -0
- package/skill/references/verification.md +13 -0
- package/skill/scripts/check_dependencies.py +109 -0
- package/skill/scripts/inspect_api.py +60 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The film as Studio has it: film.html, read through Studio's own API (this page is Studio's, so the API is ours too).
|
|
3
|
+
* The chat reads it when a project opens and keeps which file each clip is, so a clip an agent names in its reply gets
|
|
4
|
+
* the icon of what it is.
|
|
5
|
+
*/
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import type { FilmDoc } from 'openfilm/film-doc';
|
|
8
|
+
|
|
9
|
+
/** how long a read may take before it is given up */
|
|
10
|
+
const READ_WAIT_MS = 4000;
|
|
11
|
+
|
|
12
|
+
let clipSrc = new Map<string, string>();
|
|
13
|
+
const listeners = new Set<() => void>();
|
|
14
|
+
|
|
15
|
+
/** The project's film as Studio reads it from its folder; null when it cannot say (no film, one with problems, no answer). */
|
|
16
|
+
export async function readStudioFilm(projectId: string): Promise<FilmDoc | null> {
|
|
17
|
+
const stop = new AbortController();
|
|
18
|
+
const timer = setTimeout(() => stop.abort(), READ_WAIT_MS);
|
|
19
|
+
try {
|
|
20
|
+
const res = await fetch(`/api/projects/${encodeURIComponent(projectId)}`, { signal: stop.signal });
|
|
21
|
+
if (!res.ok) return null;
|
|
22
|
+
const { doc } = await res.json() as { doc?: FilmDoc | null };
|
|
23
|
+
if (!doc || !Array.isArray(doc.tracks)) return null;
|
|
24
|
+
const next = new Map<string, string>();
|
|
25
|
+
for (const track of doc.tracks) for (const clip of track.clips) if (clip?.id && clip.src) next.set(clip.id, clip.src);
|
|
26
|
+
clipSrc = next;
|
|
27
|
+
for (const listener of listeners) listener();
|
|
28
|
+
return doc;
|
|
29
|
+
} catch {
|
|
30
|
+
return null;
|
|
31
|
+
} finally {
|
|
32
|
+
clearTimeout(timer);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function subscribe(listener: () => void): () => void {
|
|
37
|
+
listeners.add(listener);
|
|
38
|
+
return () => { listeners.delete(listener); };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** The file of the clip with this id in the film last read; null when that film has no such clip (or none was read). */
|
|
42
|
+
export function useClipSrc(id: string | null): string | null {
|
|
43
|
+
return React.useSyncExternalStore(subscribe, () => (id ? clipSrc.get(id) ?? null : null), () => null);
|
|
44
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Studio's things carried into the composer, dropped or pasted: what Studio drags out (STUDIO_REF_TYPE, a JSON array
|
|
3
|
+
* of references) and a file dragged from its media pane (RESOURCE_DRAG_TYPE), which becomes a reference to that file.
|
|
4
|
+
*/
|
|
5
|
+
import { STUDIO_REF_TYPE } from 'openfilm/studio-ui/lib/host.ts';
|
|
6
|
+
import { RESOURCE_DRAG_TYPE, readResourceDragData } from 'openfilm/studio-ui/lib/resource-drag.ts';
|
|
7
|
+
import type { StudioRef } from '@/app-bridge';
|
|
8
|
+
|
|
9
|
+
const KINDS = new Set(['clip', 'layer', 'region', 'time', 'range', 'track', 'file', 'subtitle']);
|
|
10
|
+
|
|
11
|
+
/** Whether a drag or a paste carries Studio's things (a drag shows only its types until the drop). */
|
|
12
|
+
export function transferHasStudioRefs(data: Pick<DataTransfer, 'types'>): boolean {
|
|
13
|
+
const types = [...data.types];
|
|
14
|
+
return types.includes(STUDIO_REF_TYPE) || types.includes(RESOURCE_DRAG_TYPE);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The references a drop or a paste carries, none when it carries none. The data comes from outside the chat and may
|
|
19
|
+
* not be what Studio put there: anything not shaped as a reference is left out.
|
|
20
|
+
*/
|
|
21
|
+
export function studioRefsFromTransfer(data: Pick<DataTransfer, 'getData' | 'types'>): StudioRef[] {
|
|
22
|
+
const types = [...data.types];
|
|
23
|
+
if (types.includes(STUDIO_REF_TYPE)) {
|
|
24
|
+
try {
|
|
25
|
+
const list: unknown = JSON.parse(data.getData(STUDIO_REF_TYPE));
|
|
26
|
+
return (Array.isArray(list) ? list : [list]).filter((ref): ref is StudioRef => Boolean(ref) && typeof ref === 'object' && KINDS.has((ref as { kind?: unknown }).kind as string));
|
|
27
|
+
} catch {
|
|
28
|
+
return [];
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const file = types.includes(RESOURCE_DRAG_TYPE) ? readResourceDragData(data) : null;
|
|
32
|
+
if (!file) return [];
|
|
33
|
+
return [{
|
|
34
|
+
kind: 'file',
|
|
35
|
+
path: file.path,
|
|
36
|
+
fileKind: file.kind,
|
|
37
|
+
...(file.durationMs ? { duration: file.durationMs / 1000 } : {}),
|
|
38
|
+
...(file.w && file.h ? { w: file.w, h: file.h } : {}),
|
|
39
|
+
}];
|
|
40
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turns the agent starts by itself: a background task of its own came back after its turn (a command it ran in the
|
|
3
|
+
* background, a subagent), and it takes it up, as in its own chat (lib/local-agent-run onUnpromptedTurn).
|
|
4
|
+
*
|
|
5
|
+
* Pure: no React, no bridge, so `node --test` runs it (src/unprompted.test.mjs).
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The updates that mean the agent has gone on working: it writes, thinks, starts a tool or plans. Not an update of a
|
|
10
|
+
* call (`tool_call_update`): that is the rest of a call already shown, such as a command still running as its turn
|
|
11
|
+
* ended (it was stopped, or ended without waiting), whose output and exit come after.
|
|
12
|
+
*/
|
|
13
|
+
const OPENS_A_TURN = new Set(['agent_message_chunk', 'agent_thought_chunk', 'tool_call', 'plan']);
|
|
14
|
+
|
|
15
|
+
/** Whether this update, with no turn open, is the agent working by itself. */
|
|
16
|
+
export function opensUnprompted(update: { sessionUpdate?: unknown }): boolean {
|
|
17
|
+
return typeof update.sessionUpdate === 'string' && OPENS_A_TURN.has(update.sessionUpdate);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** A turn the agent started by itself that ended with nothing in it: not shown, a line with nothing under it. */
|
|
21
|
+
export function isEmptyBackgroundTurn(
|
|
22
|
+
turn: { origin?: unknown; status?: unknown; error?: unknown },
|
|
23
|
+
items: readonly unknown[],
|
|
24
|
+
): boolean {
|
|
25
|
+
const settled = turn.status === 'ready' || turn.status === 'cancelled';
|
|
26
|
+
return turn.origin === 'background' && settled && !turn.error && items.length === 0;
|
|
27
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attachment formats.
|
|
3
|
+
*
|
|
4
|
+
* The composer doesn't filter by format. Files are sorted only by how they reach the model:
|
|
5
|
+
* · images go into the message (a multimodal model sees the pixels) and are also saved, with a path;
|
|
6
|
+
* · everything else goes as a path only. The model can't read the bytes of a pdf or mp4; a path it can read,
|
|
7
|
+
* open with Python or put in the film is more honest, and more useful, than pretending to send the file.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/*
|
|
11
|
+
* No size limits here: each file is imported into the project folder and the agent gets its path.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Two sets rather than one audio-video set: the UI must pick a tile's icon and open it in `<video>` or `<audio>`;
|
|
16
|
+
* an mp3 in a video player is a screen that stays black.
|
|
17
|
+
*/
|
|
18
|
+
export const VIDEO_UPLOAD_EXTENSIONS = new Set(['mp4', 'mov', 'webm', 'm4v', 'avi', 'mkv']);
|
|
19
|
+
export const AUDIO_UPLOAD_EXTENSIONS = new Set([
|
|
20
|
+
'mp3', 'wav', 'm4a', 'aac', 'ogg', 'oga', 'opus', 'flac',
|
|
21
|
+
]);
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Documents whose mediaType is known. Not an allow-list: the composer takes anything (see the header). The table
|
|
25
|
+
* only supplies a MIME type when the browser reports none.
|
|
26
|
+
*/
|
|
27
|
+
export const DOCUMENT_EXTENSIONS = new Set([
|
|
28
|
+
'csv', 'xlsx', 'pptx', 'docx', 'pdf',
|
|
29
|
+
'txt', 'md', 'markdown',
|
|
30
|
+
'doc', 'xls', 'ppt', 'rtf', 'odt', 'ods', 'odp',
|
|
31
|
+
]);
|
|
32
|
+
|
|
33
|
+
export const DOCUMENT_MEDIA_TYPES: Record<string, string> = {
|
|
34
|
+
csv: 'text/csv',
|
|
35
|
+
xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
36
|
+
pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
|
37
|
+
docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
38
|
+
pdf: 'application/pdf',
|
|
39
|
+
txt: 'text/plain',
|
|
40
|
+
md: 'text/markdown',
|
|
41
|
+
markdown: 'text/markdown',
|
|
42
|
+
doc: 'application/msword',
|
|
43
|
+
xls: 'application/vnd.ms-excel',
|
|
44
|
+
ppt: 'application/vnd.ms-powerpoint',
|
|
45
|
+
rtf: 'application/rtf',
|
|
46
|
+
odt: 'application/vnd.oasis.opendocument.text',
|
|
47
|
+
ods: 'application/vnd.oasis.opendocument.spreadsheet',
|
|
48
|
+
odp: 'application/vnd.oasis.opendocument.presentation',
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
/** Extensions recognized as images, for reference pictures. */
|
|
53
|
+
export const IMAGE_EXTENSIONS = ['png', 'jpg', 'jpeg', 'webp', 'gif', 'svg'] as const;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The chat, mounted in Studio's page (apps/desktop/shell): its column beside Studio, under the top bar. The theme is
|
|
3
|
+
* the page's (`<html data-theme>`, Studio's), so there is nothing to follow; the language is Studio's too, and the
|
|
4
|
+
* chat's own words follow it.
|
|
5
|
+
*/
|
|
6
|
+
import { StrictMode } from 'react';
|
|
7
|
+
import { createRoot } from 'react-dom/client';
|
|
8
|
+
import { App } from './App';
|
|
9
|
+
import { app } from './app-bridge';
|
|
10
|
+
import { setLanguage } from './i18n';
|
|
11
|
+
|
|
12
|
+
export async function mountChat(root: HTMLElement) {
|
|
13
|
+
const hello = await app.hello();
|
|
14
|
+
setLanguage(hello.language);
|
|
15
|
+
app.onLanguage(setLanguage);
|
|
16
|
+
createRoot(root).render(
|
|
17
|
+
<StrictMode><App initialProject={hello.project} initialSelection={hello.selection} initialFfmpeg={hello.ffmpeg} /></StrictMode>,
|
|
18
|
+
);
|
|
19
|
+
}
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The chat's agent and its options, for the composer's agent menu (ModelPopover).
|
|
3
|
+
*
|
|
4
|
+
* Which agents there are, whether each is connected and whether the person switched it on for the chat, is the app's
|
|
5
|
+
* roster (apps/desktop/src/agent-roster.mjs; Settings → Agents changes it): the menu lists the agents switched on,
|
|
6
|
+
* and the chat uses the one picked while it is on and ready, else the first one that is.
|
|
7
|
+
*
|
|
8
|
+
* Kept here, on this computer: which agent was picked, the options picked for each (model, reasoning effort, speed:
|
|
9
|
+
* ACP configOption ids) and the option list each last reported, so the menu shows "6 Astra · Medium" before the
|
|
10
|
+
* first message (the list only comes with a session).
|
|
11
|
+
*/
|
|
12
|
+
import { create } from 'zustand';
|
|
13
|
+
import { isAgentId as isAgent } from '../../../src/agent-definitions.mjs';
|
|
14
|
+
import {
|
|
15
|
+
desktopBridge,
|
|
16
|
+
type LocalAgentId,
|
|
17
|
+
type LocalAgentSessionInfo,
|
|
18
|
+
type RosterAgent,
|
|
19
|
+
} from '@/lib/desktop-bridge';
|
|
20
|
+
import { forgetLocalAgentSessions, keepCommands, readCommands } from '@/lib/local-agent-run';
|
|
21
|
+
|
|
22
|
+
export type AgentPick = LocalAgentId;
|
|
23
|
+
|
|
24
|
+
type ConfigOptions = NonNullable<LocalAgentSessionInfo['configOptions']>;
|
|
25
|
+
|
|
26
|
+
interface Persisted {
|
|
27
|
+
picked: LocalAgentId;
|
|
28
|
+
prefs: Partial<Record<LocalAgentId, Record<string, unknown>>>;
|
|
29
|
+
options: Partial<Record<LocalAgentId, ConfigOptions>>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface LocalAgentStore extends Persisted {
|
|
33
|
+
hydrated: boolean;
|
|
34
|
+
/** The roster as the app last told it; null = not told yet (or not in the app). */
|
|
35
|
+
roster: RosterAgent[] | null;
|
|
36
|
+
/**
|
|
37
|
+
* Asking an agent for its option list failed (its adapter would not start): the menu says so, with what it said
|
|
38
|
+
* (`text`) and why, when known (`code`: 'outdated', a Codex older than the chat needs).
|
|
39
|
+
*/
|
|
40
|
+
optionsError: Partial<Record<LocalAgentId, { text: string; code?: string }>>;
|
|
41
|
+
hydrate(): void;
|
|
42
|
+
refresh(): Promise<void>;
|
|
43
|
+
pick(agent: LocalAgentId): void;
|
|
44
|
+
setPref(agent: LocalAgentId, configId: string, value: unknown): void;
|
|
45
|
+
/** The option list a session reported, kept for the menu. */
|
|
46
|
+
noteOptions(agent: LocalAgentId, options: ConfigOptions | null): void;
|
|
47
|
+
/** No option list yet: ask for one (a session opened and closed, nothing said, nothing spent). */
|
|
48
|
+
/** Ask the agent for its options once; one that failed is asked again only on `retry` (the menu opened, Retry). */
|
|
49
|
+
ensureOptions(agent: LocalAgentId, opts?: { retry?: boolean }): Promise<void>;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const probing = new Set<LocalAgentId>();
|
|
53
|
+
/** the agents asked for their options since the app started: the ones kept from before are shown until then, but an
|
|
54
|
+
agent updated since (Claude Code with new models) has other options, so each is asked once a launch */
|
|
55
|
+
const askedThisLaunch = new Set<LocalAgentId>();
|
|
56
|
+
|
|
57
|
+
const KEY = 'openfilm.local-agents.v2';
|
|
58
|
+
|
|
59
|
+
function load(): Persisted {
|
|
60
|
+
const empty: Persisted = { picked: 'claude', prefs: {}, options: {} };
|
|
61
|
+
if (typeof window === 'undefined') return empty;
|
|
62
|
+
try {
|
|
63
|
+
const raw = JSON.parse(window.localStorage.getItem(KEY) ?? window.localStorage.getItem('openfilm.local-agents.v1') ?? 'null') as Partial<Persisted> | null;
|
|
64
|
+
if (!raw) return empty;
|
|
65
|
+
return {
|
|
66
|
+
picked: isAgent(raw.picked) ? raw.picked : 'claude',
|
|
67
|
+
prefs: raw.prefs && typeof raw.prefs === 'object' ? raw.prefs : {},
|
|
68
|
+
options: raw.options && typeof raw.options === 'object' ? raw.options : {},
|
|
69
|
+
};
|
|
70
|
+
} catch {
|
|
71
|
+
return empty;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function save(s: Persisted): void {
|
|
76
|
+
try {
|
|
77
|
+
window.localStorage.setItem(KEY, JSON.stringify({ picked: s.picked, prefs: s.prefs, options: s.options }));
|
|
78
|
+
} catch { /* private mode */ }
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
type OwnModel = NonNullable<RosterAgent['byok']>['models'][number];
|
|
82
|
+
|
|
83
|
+
/** The own key's models, as Settings sets them up (the first one to begin with). */
|
|
84
|
+
function byokModels(roster: RosterAgent[] | null): OwnModel[] {
|
|
85
|
+
return roster?.find((a) => a.id === 'byok')?.byok?.models ?? [];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Which own model a pick is: its id, or, picked before each model was set up on its own, the model's name at the
|
|
90
|
+
* service (that model kept its name there). Null for one no longer set up.
|
|
91
|
+
*/
|
|
92
|
+
function ownModelPicked(models: OwnModel[], picked: unknown): OwnModel | null {
|
|
93
|
+
const value = String(picked ?? '');
|
|
94
|
+
return models.find((m) => m.id === value) ?? models.find((m) => m.model === value) ?? null;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const EFFORT_NAMES: Record<string, string> = { auto: 'Auto', off: 'Off', minimal: 'Minimal', low: 'Low', medium: 'Medium', high: 'High', xhigh: 'Extra high', max: 'Max' };
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* An agent's option list, for the menu. The own key's is its models, and the efforts of the one picked when it offers
|
|
101
|
+
* more than one, from Settings: no session has to start to know them (the app's own agent reports the same `model` and
|
|
102
|
+
* `effort` options, apps/desktop/src/pi-config.mjs). The person's own agents' is the one a session last reported.
|
|
103
|
+
*/
|
|
104
|
+
export function agentOptions(state: Pick<LocalAgentStore, 'options' | 'roster'> & Partial<Pick<LocalAgentStore, 'prefs'>>, agent: LocalAgentId): ConfigOptions | undefined {
|
|
105
|
+
if (agent !== 'byok') return state.options[agent];
|
|
106
|
+
const models = byokModels(state.roster);
|
|
107
|
+
if (!models.length) return undefined;
|
|
108
|
+
const model = ownModelPicked(models, state.prefs?.byok?.model) ?? models[0]!;
|
|
109
|
+
const options: ConfigOptions = [{ id: 'model', name: 'Model', category: 'model', type: 'select', currentValue: model.id, options: models.map((m) => ({ value: m.id, name: m.name })) }];
|
|
110
|
+
if (model.levels.length > 1) {
|
|
111
|
+
options.push({ id: 'effort', name: 'Effort', category: 'thought_level', type: 'select', currentValue: model.effort,
|
|
112
|
+
options: model.levels.map((l) => ({ value: l, name: EFFORT_NAMES[l] ?? l })) });
|
|
113
|
+
}
|
|
114
|
+
return options;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** Which of an agent's options the menu offers. The app's own agent offers its models and their efforts, and no OpenAI fast mode. */
|
|
118
|
+
export function offeredOption(agent: LocalAgentId, _roster: RosterAgent[] | null, option: { id: string; category?: string; name: string }): boolean {
|
|
119
|
+
if (agent !== 'byok') return true;
|
|
120
|
+
return !(/^(fast|fast-mode|speed)$/i.test(option.id) || option.category === 'speed');
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/* Claude Code's own model picker shows four above its line, the newest of each family; the ones it lists after them
|
|
124
|
+
are older models */
|
|
125
|
+
const CLAUDE_MODELS_OFFERED = 4;
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* The choices a menu row offers, in the agent's order, without a "Default" row (a default is one of the others). Of
|
|
129
|
+
* Claude Code's models, the first four it lists, as its own picker shows them, and the one in use if it is further down.
|
|
130
|
+
*/
|
|
131
|
+
export function offeredChoices<T extends { value: unknown }>(agent: LocalAgentId, option: { id: string; category?: string; options?: T[] }, chosen: unknown): T[] {
|
|
132
|
+
const choices = (option.options ?? []).filter((choice) => choice.value !== 'default');
|
|
133
|
+
if (agent !== 'claude' || (option.category !== 'model' && option.id !== 'model')) return choices;
|
|
134
|
+
return choices.filter((choice, i) => i < CLAUDE_MODELS_OFFERED || choice.value === chosen);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** The agents the menu lists: the ones switched on in Settings, in the roster's order. */
|
|
138
|
+
export function shownAgents(roster: RosterAgent[] | null): RosterAgent[] {
|
|
139
|
+
return (roster ?? []).filter((a) => a.shown);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** The agent the chat uses: the one picked while it is shown and ready, else the first shown one that is ready. */
|
|
143
|
+
export function currentAgent(state: Pick<LocalAgentStore, 'picked' | 'roster'>): LocalAgentId {
|
|
144
|
+
const shown = shownAgents(state.roster);
|
|
145
|
+
const picked = shown.find((a) => a.id === state.picked);
|
|
146
|
+
if (picked?.status === 'ready' || !state.roster) return state.picked;
|
|
147
|
+
return shown.find((a) => a.status === 'ready')?.id ?? picked?.id ?? shown[0]?.id ?? state.picked;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
let listening = false;
|
|
151
|
+
|
|
152
|
+
export const useLocalAgents = create<LocalAgentStore>((set, get) => ({
|
|
153
|
+
picked: 'claude',
|
|
154
|
+
prefs: {},
|
|
155
|
+
options: {},
|
|
156
|
+
hydrated: false,
|
|
157
|
+
roster: null,
|
|
158
|
+
optionsError: {},
|
|
159
|
+
hydrate() {
|
|
160
|
+
if (get().hydrated) return;
|
|
161
|
+
set({ ...load(), hydrated: true });
|
|
162
|
+
const api = desktopBridge()?.agents;
|
|
163
|
+
if (api && !listening) {
|
|
164
|
+
listening = true;
|
|
165
|
+
api.onChange((roster) => {
|
|
166
|
+
/* an agent that stopped being ready: what its sessions held goes (it may be another account next time) */
|
|
167
|
+
for (const before of get().roster ?? []) {
|
|
168
|
+
const now = roster.find((a) => a.id === before.id);
|
|
169
|
+
if (before.status === 'ready' && now?.status !== 'ready') forgetLocalAgentSessions(before.id);
|
|
170
|
+
/* other models (the own key's): its sessions were closed for the next ones to use them */
|
|
171
|
+
else if (JSON.stringify(byokModels([before])) !== JSON.stringify(byokModels(now ? [now] : []))) forgetLocalAgentSessions(before.id);
|
|
172
|
+
}
|
|
173
|
+
set({ roster });
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
void get().refresh();
|
|
177
|
+
},
|
|
178
|
+
async refresh() {
|
|
179
|
+
const roster = await desktopBridge()?.agents?.list().catch(() => null);
|
|
180
|
+
if (roster) set({ roster });
|
|
181
|
+
},
|
|
182
|
+
pick(picked) {
|
|
183
|
+
set({ picked });
|
|
184
|
+
save(get());
|
|
185
|
+
},
|
|
186
|
+
setPref(agent, configId, value) {
|
|
187
|
+
const prefs = { ...get().prefs, [agent]: { ...(get().prefs[agent] ?? {}), [configId]: value } };
|
|
188
|
+
set({ prefs });
|
|
189
|
+
save(get());
|
|
190
|
+
},
|
|
191
|
+
noteOptions(agent, options) {
|
|
192
|
+
if (!options) return;
|
|
193
|
+
set({ options: { ...get().options, [agent]: options } });
|
|
194
|
+
save(get());
|
|
195
|
+
},
|
|
196
|
+
async ensureOptions(agent, { retry = false } = {}) {
|
|
197
|
+
/* the own key's are known from Settings (agentOptions); a failed probe is not tried again on every render, each
|
|
198
|
+
try being a whole session of the agent's */
|
|
199
|
+
if (agent === 'byok' || probing.has(agent)) return;
|
|
200
|
+
const kept = Boolean(get().options[agent]);
|
|
201
|
+
if (kept && askedThisLaunch.has(agent)) return;
|
|
202
|
+
if (get().optionsError[agent] && !retry) return;
|
|
203
|
+
const api = desktopBridge()?.localAgents;
|
|
204
|
+
if (!api) return;
|
|
205
|
+
probing.add(agent);
|
|
206
|
+
askedThisLaunch.add(agent);
|
|
207
|
+
set({ optionsError: { ...get().optionsError, [agent]: undefined } });
|
|
208
|
+
try {
|
|
209
|
+
const r = await api.probe(agent).catch((e: unknown) => ({ ok: false as const, error: e instanceof Error ? e.message : String(e), code: undefined }));
|
|
210
|
+
if (r.ok && r.info.commands?.length) keepCommands(agent, readCommands({ availableCommands: r.info.commands }));
|
|
211
|
+
if (r.ok && r.info.configOptions?.length) get().noteOptions(agent, r.info.configOptions);
|
|
212
|
+
/* the ones kept from before stay when this launch's ask fails */
|
|
213
|
+
else if (!kept) set({ optionsError: { ...get().optionsError, [agent]: r.ok ? { text: 'no options' } : { text: r.error, ...(r.code ? { code: r.code } : {}) } } });
|
|
214
|
+
} finally {
|
|
215
|
+
probing.delete(agent);
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
}));
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* What the app sets for every agent and the menu does not offer: full access (it works in the person's own project
|
|
222
|
+
* folder, every step is in the edit and version history and can be undone; clicking "Allow" a dozen times a turn
|
|
223
|
+
* protects nothing). Ids differ between the adapters; an option a session does not have is skipped. The other agents
|
|
224
|
+
* are started with it (their own flags, apps/desktop/src/agents.mjs), except Kimi and MiniMax Code, whose ACP servers
|
|
225
|
+
* take no flag.
|
|
226
|
+
*/
|
|
227
|
+
const AGENT_FORCED_PREFS: Partial<Record<LocalAgentId, Record<string, unknown>>> = {
|
|
228
|
+
claude: { mode: 'bypassPermissions' },
|
|
229
|
+
codex: { mode: 'agent-full-access' },
|
|
230
|
+
kimi: { mode: 'yolo' },
|
|
231
|
+
minimax: { permissionMode: 'bypassPermissions' },
|
|
232
|
+
byok: { mode: 'agent-full-access' },
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
/** picks the menu no longer offers: plan mode (Claude Code's `plan`, Codex's collaboration mode) */
|
|
236
|
+
const DROPPED_PREFS = new Set(['plan', 'collaboration_mode']);
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* The options in effect for an agent: the person's picks, then the ones the app sets. What the person never picked
|
|
240
|
+
* here is the agent's own, as their config has it: the same model and effort as in their terminal. The own key's model
|
|
241
|
+
* picked by its name at the service (before each model was set up on its own) is its id now.
|
|
242
|
+
*/
|
|
243
|
+
export function effectivePrefs(prefs: Persisted['prefs'], agent: LocalAgentId, roster?: RosterAgent[] | null, options?: ConfigOptions): Record<string, unknown> {
|
|
244
|
+
/* "default" was a row the menu no longer offers (the agents name their default for what it is): the agent's own
|
|
245
|
+
current value stands instead. A mode picked once (plan mode, offered for a while) is not kept: every agent works
|
|
246
|
+
with full access. A pick the agent no longer offers (a model gone in its update, one the own key no longer names)
|
|
247
|
+
is not kept either: the agent's own stands instead */
|
|
248
|
+
const offers = (id: string, value: unknown) => {
|
|
249
|
+
const option = options?.find((o) => o.id === id);
|
|
250
|
+
return !option?.options?.length || option.options.some((o) => o.value === value);
|
|
251
|
+
};
|
|
252
|
+
const models = agent === 'byok' ? byokModels(roster ?? null) : null;
|
|
253
|
+
const own = Object.entries(prefs[agent] ?? {}).map(([id, value]): [string, unknown] => (models && id === 'model' ? [id, ownModelPicked(models, value)?.id ?? null] : [id, value]));
|
|
254
|
+
const kept = Object.fromEntries(own
|
|
255
|
+
.filter(([id, value]) => value !== 'default' && value !== null && !DROPPED_PREFS.has(id) && offers(id, value)));
|
|
256
|
+
return { ...kept, ...(AGENT_FORCED_PREFS[agent] ?? {}) };
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/** An option's current value (the person's pick first, else the value the session reports). */
|
|
260
|
+
export function optionValue(options: ConfigOptions | undefined, prefs: Record<string, unknown> | undefined, id: string): unknown {
|
|
261
|
+
if (prefs && id in prefs) return prefs[id];
|
|
262
|
+
return options?.find((o) => o.id === id)?.currentValue;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/** Option value → display name. */
|
|
266
|
+
export function optionLabel(options: ConfigOptions | undefined, id: string, value: unknown): string | null {
|
|
267
|
+
const option = options?.find((o) => o.id === id);
|
|
268
|
+
const hit = option?.options?.find((o) => o.value === value);
|
|
269
|
+
return hit?.name ?? (typeof value === 'string' ? value : null);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* The agent's current model and effort as a short phrase (for the composer button and the turn footer).
|
|
274
|
+
*
|
|
275
|
+
* Claude Code names its default model "Default (recommended)" and its default effort "Default"; shown as is, that
|
|
276
|
+
* truncates to "Default (recommended) Defa…" and says nothing. For the default, the model name from its
|
|
277
|
+
* description is used ("Opus (1M context)" → "Opus"), without the parenthesis; a default effort is left out.
|
|
278
|
+
*/
|
|
279
|
+
export function agentModelSummary(
|
|
280
|
+
options: ConfigOptions | undefined,
|
|
281
|
+
prefs: Record<string, unknown> | undefined,
|
|
282
|
+
): { model: string | null; effort: string | null } {
|
|
283
|
+
const byCategory = (category: string) => options?.find((o) => o.category === category || o.id === category);
|
|
284
|
+
const modelOpt = byCategory('model');
|
|
285
|
+
const effortOpt = byCategory('thought_level');
|
|
286
|
+
let model: string | null = null;
|
|
287
|
+
if (modelOpt) {
|
|
288
|
+
const value = optionValue(options, prefs, modelOpt.id);
|
|
289
|
+
const choice = modelOpt.options?.find((o) => o.value === value);
|
|
290
|
+
const raw = value === 'default' && choice?.description ? choice.description : optionLabel(options, modelOpt.id, value);
|
|
291
|
+
model = raw ? (raw.split('·')[0]!.replace(/\s*\([^)]*\)/g, '').trim() || raw) : null;
|
|
292
|
+
}
|
|
293
|
+
const effortValue = effortOpt ? optionValue(options, prefs, effortOpt.id) : undefined;
|
|
294
|
+
const effort = effortOpt && effortValue !== 'default' ? optionLabel(options, effortOpt.id, effortValue) : null;
|
|
295
|
+
return { model, effort };
|
|
296
|
+
}
|