@puredesktop/puredesktop-ui-bridge 1.0.0-beta.1 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -2
- package/src/agents/appAgentConnectors.test.ts +37 -0
- package/src/agents/appAgentConnectors.ts +138 -0
- package/src/agents/runtime/agentLiveReducer.test.ts +72 -72
- package/src/agents/runtime/agentLiveReducer.ts +139 -139
- package/src/agents/runtime/agentRunEventTypes.ts +115 -115
- package/src/agents/runtime/contextWindowUsage.test.ts +38 -38
- package/src/agents/runtime/contextWindowUsage.ts +25 -25
- package/src/agents/runtime/index.ts +24 -24
- package/src/agents/runtime/mapAgentMessages.ts +79 -54
- package/src/agents/runtime/mapAgentSnapshot.test.ts +98 -0
- package/src/agents/runtime/mapAgentSnapshot.ts +124 -71
- package/src/agents/runtime/mergeUsageTurn.ts +23 -23
- package/src/agents/runtime/pendingToolCalls.test.ts +85 -85
- package/src/agents/runtime/pendingToolCalls.ts +14 -14
- package/src/agents/runtime/toolRequiresApproval.ts +20 -20
- package/src/agents/runtime/unresolvedToolCalls.ts +42 -42
- package/src/bridge/agentModelTiers.ts +50 -50
- package/src/bridge/agentToolHandlers.ts +23 -23
- package/src/bridge/agentToolHelpers.test.ts +27 -27
- package/src/bridge/agentToolHelpers.ts +20 -20
- package/src/bridge/agentTypes.ts +377 -294
- package/src/bridge/agents.d.mts +144 -113
- package/src/bridge/agents.mjs +287 -233
- package/src/bridge/agents.ts +77 -62
- package/src/bridge/appSettings.d.mts +9 -9
- package/src/bridge/appSettings.mjs +18 -18
- package/src/bridge/appSettings.ts +4 -4
- package/src/bridge/applyThemeFromHost.d.mts +7 -7
- package/src/bridge/applyThemeFromHost.mjs +33 -33
- package/src/bridge/assets.d.mts +66 -66
- package/src/bridge/assets.mjs +121 -121
- package/src/bridge/calendarDraftIntent.ts +55 -0
- package/src/bridge/calendarInviteIntent.ts +64 -0
- package/src/bridge/catalog.d.mts +5 -5
- package/src/bridge/catalog.mjs +24 -24
- package/src/bridge/catalog.ts +1 -1
- package/src/bridge/client.d.mts +19 -19
- package/src/bridge/client.mjs +102 -102
- package/src/bridge/collectionAssetAdapter.ts +63 -63
- package/src/bridge/collectionAssets.d.mts +1 -1
- package/src/bridge/collectionAssets.mjs +2 -2
- package/src/bridge/collectionAssets.ts +1 -1
- package/src/bridge/collectionDocumentHtml.test.ts +71 -71
- package/src/bridge/collectionDocumentHtml.ts +118 -118
- package/src/bridge/collectionImagePaste.test.ts +32 -32
- package/src/bridge/collectionImagePaste.ts +130 -130
- package/src/bridge/context.mjs +12 -12
- package/src/bridge/credentials.mjs +22 -22
- package/src/bridge/dialog.d.mts +5 -5
- package/src/bridge/dialog.mjs +13 -13
- package/src/bridge/events.d.mts +14 -14
- package/src/bridge/events.mjs +12 -12
- package/src/bridge/filePreviewKind.test.ts +43 -43
- package/src/bridge/filePreviewKind.ts +76 -76
- package/src/bridge/fs.d.mts +41 -41
- package/src/bridge/fs.mjs +82 -82
- package/src/bridge/fs.test.ts +16 -16
- package/src/bridge/fs.ts +10 -10
- package/src/bridge/googleAuth.ts +159 -0
- package/src/bridge/googleProviderConfig.ts +73 -0
- package/src/bridge/index.ts +12 -12
- package/src/bridge/inlinePreview.d.mts +35 -35
- package/src/bridge/inlinePreview.mjs +99 -99
- package/src/bridge/inlinePreview.test.ts +56 -56
- package/src/bridge/inlinePreview.ts +13 -13
- package/src/bridge/methods.d.mts +125 -115
- package/src/bridge/methods.mjs +143 -132
- package/src/bridge/os.d.mts +11 -11
- package/src/bridge/os.mjs +26 -26
- package/src/bridge/plugins.d.mts +9 -9
- package/src/bridge/plugins.mjs +31 -31
- package/src/bridge/plugins.ts +5 -5
- package/src/bridge/preferences.d.mts +7 -7
- package/src/bridge/preferences.mjs +17 -17
- package/src/bridge/preferences.ts +13 -13
- package/src/bridge/printDocument.test.ts +47 -47
- package/src/bridge/printDocument.ts +75 -75
- package/src/bridge/pureRender/adapters.test.ts +144 -144
- package/src/bridge/pureRender/adapters.ts +175 -175
- package/src/bridge/pureRender/assets.test.ts +44 -44
- package/src/bridge/pureRender/base.css +76 -76
- package/src/bridge/pureRender/compiler.test.ts +279 -279
- package/src/bridge/pureRender/compiler.ts +660 -660
- package/src/bridge/pureRender/document.test.ts +283 -283
- package/src/bridge/pureRender/document.ts +35 -35
- package/src/bridge/pureRender/extraction.test.ts +432 -432
- package/src/bridge/pureRender/extraction.ts +1023 -1023
- package/src/bridge/pureRender/flow.css +3 -3
- package/src/bridge/pureRender/index.ts +66 -66
- package/src/bridge/pureRender/normalize.test.ts +442 -442
- package/src/bridge/pureRender/normalize.ts +682 -682
- package/src/bridge/pureRender/presets.ts +365 -365
- package/src/bridge/pureRender/profiles/book.css +19 -19
- package/src/bridge/pureRender/profiles/manuscript.css +11 -11
- package/src/bridge/pureRender/profiles/writer.css +10 -10
- package/src/bridge/pureRender/reset.css +5 -5
- package/src/bridge/pureRender/samples.ts +94 -94
- package/src/bridge/pureRender/styles.ts +164 -164
- package/src/bridge/pureRender/theme.test.ts +53 -53
- package/src/bridge/pureRender/theme.ts +258 -258
- package/src/bridge/pureRender/tokens/default.css +36 -36
- package/src/bridge/pureRender/tokens/default.json +32 -32
- package/src/bridge/pureRender/types.ts +264 -264
- package/src/bridge/pureRender/visualLayoutInspection.test.ts +57 -57
- package/src/bridge/pureRender/visualLayoutInspection.ts +161 -161
- package/src/bridge/react/useDebouncedEffect.ts +21 -21
- package/src/bridge/react/useIpc.tsx +75 -75
- package/src/bridge/react/usePlatformAgentRunLiveState.tsx +78 -78
- package/src/bridge/react/usePlatformAgentSessionDrive.test.tsx +134 -0
- package/src/bridge/react/usePlatformAgentSessionDrive.tsx +749 -729
- package/src/bridge/react/usePlatformAgentSessions.tsx +60 -60
- package/src/bridge/react/usePlatformAgentTools.tsx +82 -82
- package/src/bridge/react/usePlatformAppManifest.tsx +32 -32
- package/src/bridge/react/usePlatformBridge.tsx +56 -56
- package/src/bridge/react/usePlatformDeepLink.tsx +57 -57
- package/src/bridge/react/usePlatformFileBinaryDataUrl.tsx +54 -54
- package/src/bridge/react/usePlatformFilePreview.tsx +92 -92
- package/src/bridge/react/usePlatformPreferences.tsx +77 -77
- package/src/bridge/react/usePlatformThemeDocumentAttrs.ts +35 -35
- package/src/bridge/react/usePlatformThemeFromBridge.tsx +16 -16
- package/src/bridge/react/usePlatformViewportResource.test.tsx +106 -106
- package/src/bridge/react/usePlatformViewportResource.tsx +72 -72
- package/src/bridge/react/useScheduledTask.tsx +59 -59
- package/src/bridge/render.d.mts +31 -31
- package/src/bridge/render.mjs +62 -62
- package/src/bridge/render.ts +8 -8
- package/src/bridge/screenAnnotation.test.ts +103 -103
- package/src/bridge/screenAnnotation.ts +269 -269
- package/src/bridge/theme.d.mts +3 -3
- package/src/bridge/theme.mjs +9 -9
- package/src/bridge/types.ts +447 -439
- package/src/bridge/vision.d.mts +22 -0
- package/src/bridge/vision.mjs +20 -0
- package/src/bridge/watch.d.mts +9 -9
- package/src/bridge/watch.mjs +34 -34
- package/src/bridge/watch.ts +1 -1
- package/src/bridge/window.d.mts +44 -44
- package/src/bridge/window.mjs +33 -33
- package/src/chrome/index.ts +1 -1
- package/src/commitments/commitments.test.ts +201 -0
- package/src/commitments/commitments.ts +358 -0
- package/src/components/accessibility/AccessibilityReviewDialog.test.tsx +104 -104
- package/src/components/accessibility/AccessibilityReviewDialog.tsx +350 -350
- package/src/components/accessibility/accessibilityReview.test.ts +101 -101
- package/src/components/accessibility/accessibilityReview.ts +639 -639
- package/src/components/accessibility/index.ts +16 -16
- package/src/components/agent-feedback/ScreenAnnotationAgentDialog.tsx +509 -509
- package/src/components/agent-feedback/index.ts +5 -5
- package/src/components/agents/AgentComposer.tsx +135 -34
- package/src/components/agents/AgentContextUsageBar.tsx +127 -127
- package/src/components/agents/AgentDrawerPanel.test.tsx +361 -0
- package/src/components/agents/AgentDrawerPanel.tsx +122 -82
- package/src/components/agents/AgentFollowUpList.tsx +56 -0
- package/src/components/agents/AgentMarkdown.tsx +12 -12
- package/src/components/agents/AgentMessageBubble.tsx +171 -82
- package/src/components/agents/AgentMessageList.tsx +50 -47
- package/src/components/agents/AgentModelMenu.tsx +59 -55
- package/src/components/agents/AgentQuestionPromptList.tsx +284 -0
- package/src/components/agents/AgentThinkingBlock.tsx +66 -66
- package/src/components/agents/AgentToolApprovalActions.tsx +65 -65
- package/src/components/agents/AgentToolCallCard.tsx +13 -8
- package/src/components/agents/AgentToolPendingList.tsx +39 -39
- package/src/components/agents/AgentToolPendingReview.tsx +118 -118
- package/src/components/agents/agentPanelStyles.ts +150 -79
- package/src/components/agents/agentToolDisplay.ts +87 -0
- package/src/components/agents/agentTypes.ts +139 -96
- package/src/components/agents/formatToolCallArguments.test.ts +16 -16
- package/src/components/agents/formatToolCallArguments.ts +9 -9
- package/src/components/agents/index.ts +40 -40
- package/src/components/assets/AssetLibraryDialog.tsx +5 -5
- package/src/components/assets/asset-library/AssetLibraryDialog.tsx +43 -43
- package/src/components/assets/asset-library/AssetLibraryWorkspace.tsx +54 -54
- package/src/components/assets/asset-library/detail/AssetLibraryDetailActions.tsx +68 -68
- package/src/components/assets/asset-library/detail/AssetLibraryDetailHeader.tsx +56 -56
- package/src/components/assets/asset-library/detail/AssetLibraryDetailPane.tsx +90 -90
- package/src/components/assets/asset-library/detail/AssetLibraryDetailPreview.tsx +67 -67
- package/src/components/assets/asset-library/detail/AssetLibraryInlinePreview.tsx +87 -87
- package/src/components/assets/asset-library/detail/AssetLibraryInlineSourceField.tsx +29 -29
- package/src/components/assets/asset-library/detail/AssetLibraryMetadataFields.tsx +34 -34
- package/src/components/assets/asset-library/detail/AssetLibraryUsagePanel.tsx +46 -46
- package/src/components/assets/asset-library/detail/AssetLibraryVersionsPanel.tsx +145 -145
- package/src/components/assets/asset-library/helpers/assetKind.ts +74 -74
- package/src/components/assets/asset-library/helpers.ts +41 -41
- package/src/components/assets/asset-library/hooks/useAssetDetailDraft.ts +81 -81
- package/src/components/assets/asset-library/hooks/useAssetLibraryDialog.ts +233 -233
- package/src/components/assets/asset-library/hooks/useAssetLibraryMutations.ts +266 -266
- package/src/components/assets/asset-library/hooks/useAssetLibrarySelectionSync.ts +24 -24
- package/src/components/assets/asset-library/hooks/useAssetLibraryVersions.ts +145 -145
- package/src/components/assets/asset-library/hooks/useInlineAssetPreview.ts +44 -44
- package/src/components/assets/asset-library/index.ts +19 -19
- package/src/components/assets/asset-library/layout/assetLibraryLayout.ts +201 -201
- package/src/components/assets/asset-library/shared/fieldStyles.ts +62 -62
- package/src/components/assets/asset-library/sidebar/AssetLibraryFilterPills.tsx +89 -89
- package/src/components/assets/asset-library/sidebar/AssetLibraryList.tsx +91 -91
- package/src/components/assets/asset-library/sidebar/AssetLibraryListRow.tsx +99 -99
- package/src/components/assets/asset-library/sidebar/AssetLibraryListStatus.tsx +24 -24
- package/src/components/assets/asset-library/sidebar/AssetLibrarySidebar.tsx +48 -48
- package/src/components/assets/asset-library/sidebar/AssetLibrarySidebarActions.tsx +38 -38
- package/src/components/assets/asset-library/sidebar/AssetLibrarySidebarToolbar.tsx +78 -78
- package/src/components/assets/asset-library/sidebar/AssetListThumbnail.tsx +86 -86
- package/src/components/assets/asset-library/types.ts +128 -128
- package/src/components/assets/asset-library/utils/assetLibraryUtils.ts +181 -181
- package/src/components/assets/asset-library/utils/pathBasename.ts +5 -5
- package/src/components/assets/asset-library/utils/sanitizeUploadFileName.ts +7 -7
- package/src/components/assets/asset-library/utils/uploadCollectionAsset.ts +52 -52
- package/src/components/chrome/OverlayActionCapsule.test.tsx +82 -82
- package/src/components/chrome/OverlayActionCapsule.tsx +90 -90
- package/src/components/chrome/PanelTabStrip.tsx +113 -113
- package/src/components/chrome/PlatformIcon.tsx +27 -27
- package/src/components/chrome/PureAppWordmark.tsx +94 -89
- package/src/components/chrome/ShellWindowControls.tsx +58 -51
- package/src/components/chrome/ThemeModeButton.tsx +16 -16
- package/src/components/chrome/Titlebar.tsx +79 -79
- package/src/components/chrome/WorkspaceTabStrip.tsx +321 -300
- package/src/components/chrome/index.ts +31 -31
- package/src/components/chrome/workspaceTabTypes.ts +29 -29
- package/src/components/common/buttons/Button.tsx +241 -241
- package/src/components/common/buttons/ChoiceChip.tsx +73 -73
- package/src/components/common/buttons/CleanButton.tsx +34 -34
- package/src/components/common/buttons/IconButton.tsx +89 -89
- package/src/components/common/buttons/QuietAction.tsx +29 -29
- package/src/components/common/buttons/SegmentedControl.tsx +67 -67
- package/src/components/common/buttons/TextActionButton.tsx +55 -55
- package/src/components/common/buttons/TextLink.tsx +38 -38
- package/src/components/common/canvas/CanvasElementFrame.test.tsx +79 -79
- package/src/components/common/canvas/CanvasElementFrame.tsx +182 -182
- package/src/components/common/canvas/canvasGeometry.test.ts +66 -66
- package/src/components/common/canvas/canvasGeometry.ts +133 -133
- package/src/components/common/canvas/index.ts +27 -27
- package/src/components/common/canvas/useCanvasDragResize.test.tsx +152 -152
- package/src/components/common/canvas/useCanvasDragResize.ts +161 -161
- package/src/components/common/cards/OpenReviewCard.tsx +209 -0
- package/src/components/common/cards/index.ts +5 -0
- package/src/components/common/chat/ChatAssistantMessage.tsx +81 -81
- package/src/components/common/chat/ChatBox.test.tsx +61 -0
- package/src/components/common/chat/ChatBox.tsx +193 -189
- package/src/components/common/chat/ChatMarkdown.tsx +109 -109
- package/src/components/common/chat/ChatModelMenu.tsx +290 -258
- package/src/components/common/chat/ChatStatusRow.tsx +24 -24
- package/src/components/common/chat/ChatThinkingIndicator.tsx +54 -54
- package/src/components/common/chat/ChatThread.tsx +59 -59
- package/src/components/common/chat/ChatToolRow.tsx +147 -141
- package/src/components/common/chat/ChatUserBubble.tsx +45 -45
- package/src/components/common/chat/chatUtils.ts +7 -7
- package/src/components/common/chat/index.ts +24 -24
- package/src/components/common/connections/ConnectionSetup.tsx +534 -529
- package/src/components/common/connections/index.ts +26 -26
- package/src/components/common/containers/AppFrame.test.tsx +87 -41
- package/src/components/common/containers/AppFrame.tsx +66 -65
- package/src/components/common/containers/AppHeader.tsx +60 -60
- package/src/components/common/containers/AutoFillGrid.tsx +43 -37
- package/src/components/common/containers/Collapsible.tsx +43 -43
- package/src/components/common/containers/CollapsibleGrid.tsx +185 -174
- package/src/components/common/containers/MotionScope.tsx +32 -32
- package/src/components/common/containers/PageHeader.tsx +35 -35
- package/src/components/common/containers/PanelToolbarHeader.tsx +114 -113
- package/src/components/common/containers/QuietDisclosure.tsx +91 -91
- package/src/components/common/containers/QuietSurface.tsx +40 -41
- package/src/components/common/containers/ScrollPanel.tsx +33 -33
- package/src/components/common/containers/StatusBar.tsx +42 -42
- package/src/components/common/containers/SurfacePanel.tsx +66 -66
- package/src/components/common/containers/ToolbarStrip.tsx +80 -80
- package/src/components/common/containers/flex.ts +117 -117
- package/src/components/common/containers/useOpacityPresence.ts +80 -0
- package/src/components/common/containers/useOpenTransition.ts +33 -33
- package/src/components/common/context/ContextSelector.tsx +277 -269
- package/src/components/common/context/index.ts +7 -7
- package/src/components/common/desk/ActionReader.tsx +270 -270
- package/src/components/common/desk/ActivityLedger.tsx +143 -143
- package/src/components/common/desk/CreationDesk.tsx +139 -139
- package/src/components/common/desk/DailyBrief.tsx +160 -160
- package/src/components/common/desk/DeskCard.tsx +157 -157
- package/src/components/common/desk/index.ts +30 -30
- package/src/components/common/dropdown/ContextMenu.tsx +87 -87
- package/src/components/common/dropdown/MenuButtonDropdown.tsx +121 -121
- package/src/components/common/dropdown/MenuDropdown.tsx +63 -63
- package/src/components/common/dropdown/MenuDropdownEntry.tsx +51 -51
- package/src/components/common/dropdown/MenuDropdownItem.tsx +82 -82
- package/src/components/common/dropdown/MenuDropdownSubmenu.tsx +145 -145
- package/src/components/common/dropdown/MenuPanel.tsx +75 -69
- package/src/components/common/dropdown/MenuPortal.tsx +164 -162
- package/src/components/common/dropdown/MenuPortalLayer.tsx +6 -6
- package/src/components/common/dropdown/SelectMenu.tsx +246 -243
- package/src/components/common/dropdown/SelectMenuControl.tsx +23 -23
- package/src/components/common/dropdown/SelectMenuOptions.tsx +60 -38
- package/src/components/common/dropdown/menuPortalConstants.ts +11 -11
- package/src/components/common/dropdown/menuTypes.ts +71 -71
- package/src/components/common/dropdown/menuViewportPosition.test.ts +139 -139
- package/src/components/common/dropdown/menuViewportPosition.ts +122 -122
- package/src/components/common/dropdown/selectMenuLayout.test.ts +42 -42
- package/src/components/common/dropdown/selectMenuLayout.ts +123 -123
- package/src/components/common/dropdown/useMenuAnchorPosition.ts +109 -109
- package/src/components/common/dropdown/useSelectMenuAnchor.ts +30 -30
- package/src/components/common/evidence/StructuredEvidenceView.test.tsx +77 -77
- package/src/components/common/evidence/StructuredEvidenceView.tsx +312 -312
- package/src/components/common/evidence/index.ts +13 -13
- package/src/components/common/feedback/Badge.tsx +35 -33
- package/src/components/common/feedback/CapabilityPills.tsx +36 -36
- package/src/components/common/feedback/EmptyState.tsx +166 -132
- package/src/components/common/feedback/InfoHint.tsx +67 -67
- package/src/components/common/feedback/InlineBanner.tsx +82 -82
- package/src/components/common/feedback/PlatformChip.tsx +104 -104
- package/src/components/common/feedback/QuietPill.tsx +75 -75
- package/src/components/common/feedback/WorkProgressPanel.tsx +156 -156
- package/src/components/common/feedback/index.ts +33 -33
- package/src/components/common/files/FileTable.tsx +225 -0
- package/src/components/common/inputs/BareInput.tsx +31 -31
- package/src/components/common/inputs/BareTextarea.tsx +10 -10
- package/src/components/common/inputs/Checkbox.tsx +13 -13
- package/src/components/common/inputs/EditableSecretField.tsx +292 -0
- package/src/components/common/inputs/FieldControlShell.tsx +49 -49
- package/src/components/common/inputs/FormField.tsx +40 -40
- package/src/components/common/inputs/HybridSearchField.tsx +295 -280
- package/src/components/common/inputs/InlineComposer.tsx +197 -197
- package/src/components/common/inputs/PaletteCirclePicker.tsx +26 -26
- package/src/components/common/inputs/PaletteDropdown.tsx +418 -413
- package/src/components/common/inputs/Radio.tsx +19 -19
- package/src/components/common/inputs/SearchField.tsx +128 -128
- package/src/components/common/inputs/SelectField.tsx +170 -169
- package/src/components/common/inputs/SurfacePalettePicker.tsx +54 -54
- package/src/components/common/inputs/TextAreaField.tsx +22 -22
- package/src/components/common/inputs/TextField.tsx +51 -51
- package/src/components/common/inputs/ToggleSwitch.tsx +110 -110
- package/src/components/common/inputs/WorkspacePicker.tsx +349 -349
- package/src/components/common/inputs/fieldStyles.ts +141 -137
- package/src/components/common/layout/PanelGroup.tsx +485 -479
- package/src/components/common/layout/index.ts +31 -31
- package/src/components/common/layout/panelLayoutConstants.ts +7 -7
- package/src/components/common/layout/panelLayoutPersistence.ts +35 -35
- package/src/components/common/layout/panelLayoutState.test.ts +38 -38
- package/src/components/common/layout/panelLayoutState.ts +174 -174
- package/src/components/common/layout/panelLayoutTypes.ts +19 -19
- package/src/components/common/layout/tabs/Tabs.tsx +136 -136
- package/src/components/common/lists/listRowStyles.ts +32 -32
- package/src/components/common/lists/quiet-ledger/QuietActivityList.tsx +64 -64
- package/src/components/common/lists/quiet-ledger/QuietLedgerRow.tsx +119 -119
- package/src/components/common/lists/quiet-ledger/index.ts +9 -9
- package/src/components/common/lists/reorderable/DragHandle.tsx +65 -65
- package/src/components/common/lists/reorderable/ReorderableList.tsx +280 -280
- package/src/components/common/lists/reorderable/ReorderableListRow.tsx +102 -102
- package/src/components/common/lists/reorderable/ReorderableSections.tsx +344 -344
- package/src/components/common/lists/reorderable/ReorderableSectionsDemo.tsx +94 -94
- package/src/components/common/lists/reorderable/index.ts +15 -15
- package/src/components/common/lists/reorderable/reorderableUtils.test.ts +28 -28
- package/src/components/common/lists/reorderable/reorderableUtils.ts +23 -23
- package/src/components/common/lists/reorderable/types.ts +40 -40
- package/src/components/common/lists/reorderable/useReorderableDragState.ts +49 -49
- package/src/components/common/media/ImageReferencePicker.tsx +242 -242
- package/src/components/common/menubar/MenuBar.tsx +78 -78
- package/src/components/common/menubar/MenuBarTrigger.tsx +70 -70
- package/src/components/common/narrative/NarrativeMention.tsx +74 -74
- package/src/components/common/navigation/NavigationCardRow.tsx +98 -0
- package/src/components/common/navigation/PathBreadcrumbs.tsx +78 -78
- package/src/components/common/navigation/UnderlineTabs.tsx +83 -83
- package/src/components/common/navigation/index.ts +15 -0
- package/src/components/common/overlays/InstallAppPromptDialog.tsx +59 -59
- package/src/components/common/overlays/Modal.tsx +292 -285
- package/src/components/common/overlays/ModalChromeHeader.tsx +105 -105
- package/src/components/common/overlays/ObjectActionStrip.tsx +80 -80
- package/src/components/common/people/AutoUpdateReviewList.tsx +182 -182
- package/src/components/common/people/EntityList.tsx +122 -122
- package/src/components/common/people/EntityPortrait.tsx +64 -64
- package/src/components/common/people/LinkedDossierList.tsx +99 -99
- package/src/components/common/people/OpportunityList.tsx +94 -94
- package/src/components/common/people/PeopleSourceList.tsx +145 -145
- package/src/components/common/people/RelationshipDossier.tsx +168 -168
- package/src/components/common/people/RelationshipMap.tsx +362 -362
- package/src/components/common/people/index.ts +40 -40
- package/src/components/common/preview/FileAudioPreview.tsx +89 -89
- package/src/components/common/preview/FileImagePreview.tsx +88 -88
- package/src/components/common/preview/FilePdfPreview.tsx +87 -87
- package/src/components/common/preview/FileTextPreview.tsx +96 -96
- package/src/components/common/preview/FileVideoPreview.tsx +87 -87
- package/src/components/common/preview/PlatformFilePreview.tsx +166 -166
- package/src/components/common/preview/previewLayout.ts +27 -27
- package/src/components/common/render/Each.tsx +42 -42
- package/src/components/common/research/EvidenceDossier.tsx +904 -894
- package/src/components/common/research/index.ts +7 -7
- package/src/components/common/tiles/CatalogCard.tsx +116 -116
- package/src/components/common/tiles/Tile.tsx +45 -45
- package/src/components/common/tiles/TileGrid.tsx +19 -13
- package/src/components/common/typography/Heading.tsx +27 -27
- package/src/components/common/typography/Kicker.tsx +36 -30
- package/src/components/common/typography/Text.tsx +80 -80
- package/src/components/credentials/CredentialsPanel.tsx +236 -169
- package/src/components/credentials/credentialProviderIcon.tsx +79 -0
- package/src/components/credentials/credentialsTypes.ts +14 -14
- package/src/components/credentials/lobeIcons.d.ts +4 -0
- package/src/components/data/DataChart.tsx +913 -913
- package/src/components/data/dataTable.ts +99 -99
- package/src/components/editor/EditorCommentPromptDialog.tsx +124 -124
- package/src/components/editor/EditorLinkPromptDialog.tsx +65 -65
- package/src/components/print-design/PrintDesignPanel.test.tsx +1446 -1446
- package/src/components/print-design/PrintDesignPanel.tsx +3045 -3043
- package/src/components/print-design/index.ts +9 -9
- package/src/components/proofing/PagedProofDialog.tsx +453 -453
- package/src/components/proofing/index.ts +4 -4
- package/src/editor/DocumentEditor.tsx +28 -28
- package/src/editor/EditorViewModeToggle.tsx +38 -35
- package/src/editor/index.ts +98 -97
- package/src/editor/toolbarOverlays.ts +8 -8
- package/src/index.ts +231 -209
- package/src/theme/ThemeProvider.tsx +115 -113
- package/src/theme/appAccents.ts +115 -87
- package/src/theme/buildThemeBridgePayload.ts +23 -23
- package/src/theme/composePlatformTheme.test.ts +47 -30
- package/src/theme/composePlatformTheme.ts +23 -23
- package/src/theme/platformFont.d.mts +7 -7
- package/src/theme/platformFont.mjs +20 -20
- package/src/theme/platformFont.ts +6 -6
- package/src/theme/reportsShellChromeSelectors.ts +136 -136
- package/src/theme/styled.d.ts +5 -5
- package/src/theme/surfacePalettes.ts +179 -178
- package/src/theme/surfaceRoleSelectors.ts +113 -113
- package/src/theme/themeVars.ts +13 -13
- package/src/theme/themes/dark.ts +59 -59
- package/src/theme/themes/light.ts +60 -60
- package/src/theme/themes/palette.ts +44 -44
- package/src/theme/themes/shared.ts +68 -68
- package/src/theme/tokens.ts +114 -114
- package/src/theme/utils/GlobalStyles.ts +88 -88
- package/src/theme/utils/appFrameDocumentStyles.d.mts +5 -5
- package/src/theme/utils/appFrameDocumentStyles.mjs +89 -89
- package/src/theme/utils/appFrameDocumentStyles.ts +5 -5
- package/src/theme/utils/applyTheme.test.ts +19 -0
- package/src/theme/utils/applyTheme.ts +59 -50
- package/src/theme/utils/cssVariables.ts +49 -49
- package/src/theme/utils/useInjectThemeIntoIframe.ts +40 -40
- package/src/utils/extensionIconMap.ts +123 -123
- package/src/utils/generalUtils.ts +157 -157
- package/src/writing/DraftAssistantDialog.tsx +279 -279
- package/src/writing/WritingStyleManager.tsx +416 -416
- package/src/writing/condenseWritingStyle.ts +103 -103
- package/src/writing/draftTextWithAgent.ts +134 -134
- package/src/writing/index.ts +39 -39
- package/src/writing/styleStore.ts +32 -32
- package/src/writing/writingStyle.test.ts +122 -122
- package/src/writing/writingStyle.ts +217 -217
|
@@ -1,217 +1,217 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Writing-style guidance for book generation and in-editor drafting.
|
|
3
|
-
*
|
|
4
|
-
* There are no built-in generic presets. Every style is authored and named by
|
|
5
|
-
* the user. A style carries:
|
|
6
|
-
* - SOURCES: the author's own writing samples, mirrored for VOICE only and
|
|
7
|
-
* never lifted as content.
|
|
8
|
-
* - NOTES: free-text guidance the author writes themselves (their own rules).
|
|
9
|
-
* - SKILL: a compact, distilled style guide generated from the sources+notes
|
|
10
|
-
* (see condenseWritingStyleWithAgent). It is editable and, when enabled, is
|
|
11
|
-
* sent to the agent instead of the raw sources+notes to save tokens.
|
|
12
|
-
*
|
|
13
|
-
* Styles are saved app-wide (book app settings) and reused across book creation
|
|
14
|
-
* and the editor drafter. Which styles apply is chosen per book / per draft.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
export interface StyleSource {
|
|
18
|
-
id: string
|
|
19
|
-
label: string
|
|
20
|
-
text: string
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface WritingStyle {
|
|
24
|
-
id: string
|
|
25
|
-
name: string
|
|
26
|
-
sources: StyleSource[]
|
|
27
|
-
notes: string
|
|
28
|
-
/** Words/phrases to prefer (whitelist). Free text — comma or newline separated. */
|
|
29
|
-
include: string
|
|
30
|
-
/** Words/phrases to avoid (blacklist). Free text — comma or newline separated. */
|
|
31
|
-
exclude: string
|
|
32
|
-
/** Distilled compact style guide; editable. Empty until distilled. */
|
|
33
|
-
skill: string
|
|
34
|
-
/** When true and a skill exists, the skill is used instead of raw sources. */
|
|
35
|
-
skillEnabled: boolean
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export interface BookWritingStyle {
|
|
39
|
-
styles: WritingStyle[]
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export const EMPTY_WRITING_STYLE: BookWritingStyle = { styles: [] }
|
|
43
|
-
|
|
44
|
-
function randomId(prefix: string): string {
|
|
45
|
-
return `${prefix}-${Math.random().toString(36).slice(2)}-${Date.now()}`
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export function createWritingStyle(name = 'New style'): WritingStyle {
|
|
49
|
-
return {
|
|
50
|
-
id: randomId('style'),
|
|
51
|
-
name,
|
|
52
|
-
sources: [],
|
|
53
|
-
notes: '',
|
|
54
|
-
include: '',
|
|
55
|
-
exclude: '',
|
|
56
|
-
skill: '',
|
|
57
|
-
skillEnabled: false,
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export function createStyleSource(label = 'Sample'): StyleSource {
|
|
62
|
-
return { id: randomId('src'), label, text: '' }
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function coerceSource(item: unknown): StyleSource | null {
|
|
66
|
-
if (!item || typeof item !== 'object') return null
|
|
67
|
-
const entry = item as Record<string, unknown>
|
|
68
|
-
const text = typeof entry.text === 'string' ? entry.text : ''
|
|
69
|
-
return {
|
|
70
|
-
id: typeof entry.id === 'string' && entry.id ? entry.id : randomId('src'),
|
|
71
|
-
label:
|
|
72
|
-
typeof entry.label === 'string' && entry.label.trim()
|
|
73
|
-
? entry.label.trim()
|
|
74
|
-
: 'Sample',
|
|
75
|
-
text,
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function coerceStyle(item: unknown): WritingStyle | null {
|
|
80
|
-
if (!item || typeof item !== 'object') return null
|
|
81
|
-
const entry = item as Record<string, unknown>
|
|
82
|
-
|
|
83
|
-
// Current shape: a style with its own sources.
|
|
84
|
-
let sources = Array.isArray(entry.sources)
|
|
85
|
-
? entry.sources
|
|
86
|
-
.map(coerceSource)
|
|
87
|
-
.filter((source): source is StyleSource => source !== null)
|
|
88
|
-
: []
|
|
89
|
-
|
|
90
|
-
// Legacy migration: a flat StyleExample { label, text } becomes one source.
|
|
91
|
-
if (sources.length === 0 && typeof entry.text === 'string' && entry.text.trim()) {
|
|
92
|
-
sources = [
|
|
93
|
-
{
|
|
94
|
-
id: typeof entry.id === 'string' && entry.id ? entry.id : randomId('src'),
|
|
95
|
-
label:
|
|
96
|
-
typeof entry.label === 'string' && entry.label.trim()
|
|
97
|
-
? entry.label.trim()
|
|
98
|
-
: 'Sample',
|
|
99
|
-
text: entry.text,
|
|
100
|
-
},
|
|
101
|
-
]
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const name =
|
|
105
|
-
typeof entry.name === 'string' && entry.name.trim()
|
|
106
|
-
? entry.name.trim()
|
|
107
|
-
: typeof entry.label === 'string' && entry.label.trim()
|
|
108
|
-
? entry.label.trim()
|
|
109
|
-
: 'Untitled style'
|
|
110
|
-
const notes = typeof entry.notes === 'string' ? entry.notes : ''
|
|
111
|
-
const include = typeof entry.include === 'string' ? entry.include : ''
|
|
112
|
-
const exclude = typeof entry.exclude === 'string' ? entry.exclude : ''
|
|
113
|
-
const skill = typeof entry.skill === 'string' ? entry.skill : ''
|
|
114
|
-
|
|
115
|
-
// Keep a style only if it has something to say.
|
|
116
|
-
if (
|
|
117
|
-
sources.length === 0 &&
|
|
118
|
-
!notes.trim() &&
|
|
119
|
-
!include.trim() &&
|
|
120
|
-
!exclude.trim() &&
|
|
121
|
-
!skill.trim()
|
|
122
|
-
) {
|
|
123
|
-
return null
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return {
|
|
127
|
-
id: typeof entry.id === 'string' && entry.id ? entry.id : randomId('style'),
|
|
128
|
-
name,
|
|
129
|
-
sources,
|
|
130
|
-
notes,
|
|
131
|
-
include,
|
|
132
|
-
exclude,
|
|
133
|
-
skill,
|
|
134
|
-
skillEnabled: entry.skillEnabled === true && skill.trim().length > 0,
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
export function normalizeWritingStyle(value: unknown): BookWritingStyle {
|
|
139
|
-
const record =
|
|
140
|
-
value && typeof value === 'object' ? (value as Record<string, unknown>) : {}
|
|
141
|
-
// Current shape: { styles }. Legacy shape: { presets, examples }.
|
|
142
|
-
const source = Array.isArray(record.styles)
|
|
143
|
-
? record.styles
|
|
144
|
-
: Array.isArray(record.examples)
|
|
145
|
-
? record.examples
|
|
146
|
-
: []
|
|
147
|
-
const styles = source
|
|
148
|
-
.map(coerceStyle)
|
|
149
|
-
.filter((style): style is WritingStyle => style !== null)
|
|
150
|
-
return { styles }
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Raw guidance for ONE style: the author's notes plus their voice samples,
|
|
155
|
-
* explicitly marked voice-only. Used both as the distillation input and as the
|
|
156
|
-
* applied guidance when no skill is enabled.
|
|
157
|
-
*/
|
|
158
|
-
export function styleRawGuidance(style: WritingStyle): string {
|
|
159
|
-
const lines: string[] = []
|
|
160
|
-
if (style.notes.trim()) lines.push(`Guidance: ${style.notes.trim()}`)
|
|
161
|
-
if (style.include.trim()) {
|
|
162
|
-
lines.push(
|
|
163
|
-
`Prefer these words and phrases where they fit naturally: ${normalizeWordList(style.include)}.`,
|
|
164
|
-
)
|
|
165
|
-
}
|
|
166
|
-
if (style.exclude.trim()) {
|
|
167
|
-
lines.push(`Avoid these words and phrases entirely: ${normalizeWordList(style.exclude)}.`)
|
|
168
|
-
}
|
|
169
|
-
const samples = style.sources
|
|
170
|
-
.map(source => source.text.trim())
|
|
171
|
-
.filter(Boolean)
|
|
172
|
-
if (samples.length > 0) {
|
|
173
|
-
lines.push(
|
|
174
|
-
'Match the VOICE of these writing samples — sentence rhythm, tone, and word choice only. Do NOT reuse their wording, facts, or subject matter as content:',
|
|
175
|
-
)
|
|
176
|
-
samples.forEach((text, index) => {
|
|
177
|
-
lines.push(`Sample ${index + 1}: """${text.slice(0, 1200)}"""`)
|
|
178
|
-
})
|
|
179
|
-
}
|
|
180
|
-
return lines.join('\n')
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/** Flatten a comma/newline-separated word list into a single comma-separated line. */
|
|
184
|
-
function normalizeWordList(value: string): string {
|
|
185
|
-
return value
|
|
186
|
-
.split(/[\n,]/)
|
|
187
|
-
.map(word => word.trim())
|
|
188
|
-
.filter(Boolean)
|
|
189
|
-
.join(', ')
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/** True when a style contributes anything to the prompt. */
|
|
193
|
-
export function styleHasContent(style: WritingStyle): boolean {
|
|
194
|
-
return (
|
|
195
|
-
style.skill.trim().length > 0 ||
|
|
196
|
-
style.notes.trim().length > 0 ||
|
|
197
|
-
style.include.trim().length > 0 ||
|
|
198
|
-
style.exclude.trim().length > 0 ||
|
|
199
|
-
style.sources.some(source => source.text.trim().length > 0)
|
|
200
|
-
)
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Build the style-guidance prompt block from the SELECTED styles. For each
|
|
205
|
-
* style, prefer its distilled skill when enabled; otherwise fall back to the
|
|
206
|
-
* raw notes + voice samples.
|
|
207
|
-
*/
|
|
208
|
-
export function buildStyleGuidance(styles: WritingStyle[]): string | undefined {
|
|
209
|
-
const blocks: string[] = []
|
|
210
|
-
styles.forEach(style => {
|
|
211
|
-
const useSkill = style.skillEnabled && style.skill.trim().length > 0
|
|
212
|
-
const body = useSkill ? style.skill.trim() : styleRawGuidance(style)
|
|
213
|
-
if (body.trim()) blocks.push(`Style — ${style.name}:\n${body.trim()}`)
|
|
214
|
-
})
|
|
215
|
-
if (blocks.length === 0) return undefined
|
|
216
|
-
return ['Writing style guidance:', ...blocks].join('\n\n')
|
|
217
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Writing-style guidance for book generation and in-editor drafting.
|
|
3
|
+
*
|
|
4
|
+
* There are no built-in generic presets. Every style is authored and named by
|
|
5
|
+
* the user. A style carries:
|
|
6
|
+
* - SOURCES: the author's own writing samples, mirrored for VOICE only and
|
|
7
|
+
* never lifted as content.
|
|
8
|
+
* - NOTES: free-text guidance the author writes themselves (their own rules).
|
|
9
|
+
* - SKILL: a compact, distilled style guide generated from the sources+notes
|
|
10
|
+
* (see condenseWritingStyleWithAgent). It is editable and, when enabled, is
|
|
11
|
+
* sent to the agent instead of the raw sources+notes to save tokens.
|
|
12
|
+
*
|
|
13
|
+
* Styles are saved app-wide (book app settings) and reused across book creation
|
|
14
|
+
* and the editor drafter. Which styles apply is chosen per book / per draft.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
export interface StyleSource {
|
|
18
|
+
id: string
|
|
19
|
+
label: string
|
|
20
|
+
text: string
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface WritingStyle {
|
|
24
|
+
id: string
|
|
25
|
+
name: string
|
|
26
|
+
sources: StyleSource[]
|
|
27
|
+
notes: string
|
|
28
|
+
/** Words/phrases to prefer (whitelist). Free text — comma or newline separated. */
|
|
29
|
+
include: string
|
|
30
|
+
/** Words/phrases to avoid (blacklist). Free text — comma or newline separated. */
|
|
31
|
+
exclude: string
|
|
32
|
+
/** Distilled compact style guide; editable. Empty until distilled. */
|
|
33
|
+
skill: string
|
|
34
|
+
/** When true and a skill exists, the skill is used instead of raw sources. */
|
|
35
|
+
skillEnabled: boolean
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface BookWritingStyle {
|
|
39
|
+
styles: WritingStyle[]
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const EMPTY_WRITING_STYLE: BookWritingStyle = { styles: [] }
|
|
43
|
+
|
|
44
|
+
function randomId(prefix: string): string {
|
|
45
|
+
return `${prefix}-${Math.random().toString(36).slice(2)}-${Date.now()}`
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function createWritingStyle(name = 'New style'): WritingStyle {
|
|
49
|
+
return {
|
|
50
|
+
id: randomId('style'),
|
|
51
|
+
name,
|
|
52
|
+
sources: [],
|
|
53
|
+
notes: '',
|
|
54
|
+
include: '',
|
|
55
|
+
exclude: '',
|
|
56
|
+
skill: '',
|
|
57
|
+
skillEnabled: false,
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function createStyleSource(label = 'Sample'): StyleSource {
|
|
62
|
+
return { id: randomId('src'), label, text: '' }
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function coerceSource(item: unknown): StyleSource | null {
|
|
66
|
+
if (!item || typeof item !== 'object') return null
|
|
67
|
+
const entry = item as Record<string, unknown>
|
|
68
|
+
const text = typeof entry.text === 'string' ? entry.text : ''
|
|
69
|
+
return {
|
|
70
|
+
id: typeof entry.id === 'string' && entry.id ? entry.id : randomId('src'),
|
|
71
|
+
label:
|
|
72
|
+
typeof entry.label === 'string' && entry.label.trim()
|
|
73
|
+
? entry.label.trim()
|
|
74
|
+
: 'Sample',
|
|
75
|
+
text,
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function coerceStyle(item: unknown): WritingStyle | null {
|
|
80
|
+
if (!item || typeof item !== 'object') return null
|
|
81
|
+
const entry = item as Record<string, unknown>
|
|
82
|
+
|
|
83
|
+
// Current shape: a style with its own sources.
|
|
84
|
+
let sources = Array.isArray(entry.sources)
|
|
85
|
+
? entry.sources
|
|
86
|
+
.map(coerceSource)
|
|
87
|
+
.filter((source): source is StyleSource => source !== null)
|
|
88
|
+
: []
|
|
89
|
+
|
|
90
|
+
// Legacy migration: a flat StyleExample { label, text } becomes one source.
|
|
91
|
+
if (sources.length === 0 && typeof entry.text === 'string' && entry.text.trim()) {
|
|
92
|
+
sources = [
|
|
93
|
+
{
|
|
94
|
+
id: typeof entry.id === 'string' && entry.id ? entry.id : randomId('src'),
|
|
95
|
+
label:
|
|
96
|
+
typeof entry.label === 'string' && entry.label.trim()
|
|
97
|
+
? entry.label.trim()
|
|
98
|
+
: 'Sample',
|
|
99
|
+
text: entry.text,
|
|
100
|
+
},
|
|
101
|
+
]
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const name =
|
|
105
|
+
typeof entry.name === 'string' && entry.name.trim()
|
|
106
|
+
? entry.name.trim()
|
|
107
|
+
: typeof entry.label === 'string' && entry.label.trim()
|
|
108
|
+
? entry.label.trim()
|
|
109
|
+
: 'Untitled style'
|
|
110
|
+
const notes = typeof entry.notes === 'string' ? entry.notes : ''
|
|
111
|
+
const include = typeof entry.include === 'string' ? entry.include : ''
|
|
112
|
+
const exclude = typeof entry.exclude === 'string' ? entry.exclude : ''
|
|
113
|
+
const skill = typeof entry.skill === 'string' ? entry.skill : ''
|
|
114
|
+
|
|
115
|
+
// Keep a style only if it has something to say.
|
|
116
|
+
if (
|
|
117
|
+
sources.length === 0 &&
|
|
118
|
+
!notes.trim() &&
|
|
119
|
+
!include.trim() &&
|
|
120
|
+
!exclude.trim() &&
|
|
121
|
+
!skill.trim()
|
|
122
|
+
) {
|
|
123
|
+
return null
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
id: typeof entry.id === 'string' && entry.id ? entry.id : randomId('style'),
|
|
128
|
+
name,
|
|
129
|
+
sources,
|
|
130
|
+
notes,
|
|
131
|
+
include,
|
|
132
|
+
exclude,
|
|
133
|
+
skill,
|
|
134
|
+
skillEnabled: entry.skillEnabled === true && skill.trim().length > 0,
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function normalizeWritingStyle(value: unknown): BookWritingStyle {
|
|
139
|
+
const record =
|
|
140
|
+
value && typeof value === 'object' ? (value as Record<string, unknown>) : {}
|
|
141
|
+
// Current shape: { styles }. Legacy shape: { presets, examples }.
|
|
142
|
+
const source = Array.isArray(record.styles)
|
|
143
|
+
? record.styles
|
|
144
|
+
: Array.isArray(record.examples)
|
|
145
|
+
? record.examples
|
|
146
|
+
: []
|
|
147
|
+
const styles = source
|
|
148
|
+
.map(coerceStyle)
|
|
149
|
+
.filter((style): style is WritingStyle => style !== null)
|
|
150
|
+
return { styles }
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Raw guidance for ONE style: the author's notes plus their voice samples,
|
|
155
|
+
* explicitly marked voice-only. Used both as the distillation input and as the
|
|
156
|
+
* applied guidance when no skill is enabled.
|
|
157
|
+
*/
|
|
158
|
+
export function styleRawGuidance(style: WritingStyle): string {
|
|
159
|
+
const lines: string[] = []
|
|
160
|
+
if (style.notes.trim()) lines.push(`Guidance: ${style.notes.trim()}`)
|
|
161
|
+
if (style.include.trim()) {
|
|
162
|
+
lines.push(
|
|
163
|
+
`Prefer these words and phrases where they fit naturally: ${normalizeWordList(style.include)}.`,
|
|
164
|
+
)
|
|
165
|
+
}
|
|
166
|
+
if (style.exclude.trim()) {
|
|
167
|
+
lines.push(`Avoid these words and phrases entirely: ${normalizeWordList(style.exclude)}.`)
|
|
168
|
+
}
|
|
169
|
+
const samples = style.sources
|
|
170
|
+
.map(source => source.text.trim())
|
|
171
|
+
.filter(Boolean)
|
|
172
|
+
if (samples.length > 0) {
|
|
173
|
+
lines.push(
|
|
174
|
+
'Match the VOICE of these writing samples — sentence rhythm, tone, and word choice only. Do NOT reuse their wording, facts, or subject matter as content:',
|
|
175
|
+
)
|
|
176
|
+
samples.forEach((text, index) => {
|
|
177
|
+
lines.push(`Sample ${index + 1}: """${text.slice(0, 1200)}"""`)
|
|
178
|
+
})
|
|
179
|
+
}
|
|
180
|
+
return lines.join('\n')
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/** Flatten a comma/newline-separated word list into a single comma-separated line. */
|
|
184
|
+
function normalizeWordList(value: string): string {
|
|
185
|
+
return value
|
|
186
|
+
.split(/[\n,]/)
|
|
187
|
+
.map(word => word.trim())
|
|
188
|
+
.filter(Boolean)
|
|
189
|
+
.join(', ')
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** True when a style contributes anything to the prompt. */
|
|
193
|
+
export function styleHasContent(style: WritingStyle): boolean {
|
|
194
|
+
return (
|
|
195
|
+
style.skill.trim().length > 0 ||
|
|
196
|
+
style.notes.trim().length > 0 ||
|
|
197
|
+
style.include.trim().length > 0 ||
|
|
198
|
+
style.exclude.trim().length > 0 ||
|
|
199
|
+
style.sources.some(source => source.text.trim().length > 0)
|
|
200
|
+
)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Build the style-guidance prompt block from the SELECTED styles. For each
|
|
205
|
+
* style, prefer its distilled skill when enabled; otherwise fall back to the
|
|
206
|
+
* raw notes + voice samples.
|
|
207
|
+
*/
|
|
208
|
+
export function buildStyleGuidance(styles: WritingStyle[]): string | undefined {
|
|
209
|
+
const blocks: string[] = []
|
|
210
|
+
styles.forEach(style => {
|
|
211
|
+
const useSkill = style.skillEnabled && style.skill.trim().length > 0
|
|
212
|
+
const body = useSkill ? style.skill.trim() : styleRawGuidance(style)
|
|
213
|
+
if (body.trim()) blocks.push(`Style — ${style.name}:\n${body.trim()}`)
|
|
214
|
+
})
|
|
215
|
+
if (blocks.length === 0) return undefined
|
|
216
|
+
return ['Writing style guidance:', ...blocks].join('\n\n')
|
|
217
|
+
}
|