@flanksource/clicky-ui 0.3.29 → 0.3.31
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/dist/ai.cjs +48 -3
- package/dist/ai.cjs.map +1 -1
- package/dist/ai.js +46 -1
- package/dist/ai.js.map +1 -1
- package/dist/comments/CommentCard.cjs +110 -262
- package/dist/comments/CommentCard.cjs.map +1 -1
- package/dist/comments/CommentCard.d.ts +3 -1
- package/dist/comments/CommentCard.d.ts.map +1 -1
- package/dist/comments/CommentCard.js +105 -257
- package/dist/comments/CommentCard.js.map +1 -1
- package/dist/comments/CommentCardParts.cjs +95 -0
- package/dist/comments/CommentCardParts.cjs.map +1 -0
- package/dist/comments/CommentCardParts.d.ts +17 -0
- package/dist/comments/CommentCardParts.d.ts.map +1 -0
- package/dist/comments/CommentCardParts.js +95 -0
- package/dist/comments/CommentCardParts.js.map +1 -0
- package/dist/comments/CommentSidePanel.cjs +14 -7
- package/dist/comments/CommentSidePanel.cjs.map +1 -1
- package/dist/comments/CommentSidePanel.d.ts +3 -1
- package/dist/comments/CommentSidePanel.d.ts.map +1 -1
- package/dist/comments/CommentSidePanel.js +14 -7
- package/dist/comments/CommentSidePanel.js.map +1 -1
- package/dist/comments/CommentThread.cjs +2 -0
- package/dist/comments/CommentThread.cjs.map +1 -1
- package/dist/comments/CommentThread.d.ts +2 -1
- package/dist/comments/CommentThread.d.ts.map +1 -1
- package/dist/comments/CommentThread.js +2 -0
- package/dist/comments/CommentThread.js.map +1 -1
- package/dist/comments/CommentThreadList.cjs +50 -34
- package/dist/comments/CommentThreadList.cjs.map +1 -1
- package/dist/comments/CommentThreadList.d.ts +3 -1
- package/dist/comments/CommentThreadList.d.ts.map +1 -1
- package/dist/comments/CommentThreadList.js +50 -34
- package/dist/comments/CommentThreadList.js.map +1 -1
- package/dist/components/ComboboxMenu.cjs +4 -1
- package/dist/components/ComboboxMenu.cjs.map +1 -1
- package/dist/components/ComboboxMenu.d.ts.map +1 -1
- package/dist/components/ComboboxMenu.js +5 -2
- package/dist/components/ComboboxMenu.js.map +1 -1
- package/dist/components/ComboboxTags.cjs +5 -1
- package/dist/components/ComboboxTags.cjs.map +1 -1
- package/dist/components/ComboboxTags.d.ts.map +1 -1
- package/dist/components/ComboboxTags.js +6 -2
- package/dist/components/ComboboxTags.js.map +1 -1
- package/dist/components/ConnectionLoggingPolicy.cjs +24 -35
- package/dist/components/ConnectionLoggingPolicy.cjs.map +1 -1
- package/dist/components/ConnectionLoggingPolicy.d.ts.map +1 -1
- package/dist/components/ConnectionLoggingPolicy.js +24 -35
- package/dist/components/ConnectionLoggingPolicy.js.map +1 -1
- package/dist/components/DateField.d.ts +1 -1
- package/dist/components/DatePicker.d.ts +1 -1
- package/dist/components/DateTimePicker.d.ts +1 -1
- package/dist/components/MultiSelect.cjs.map +1 -1
- package/dist/components/MultiSelect.d.ts +7 -0
- package/dist/components/MultiSelect.d.ts.map +1 -1
- package/dist/components/MultiSelect.js.map +1 -1
- package/dist/components/filter-bar-multi.cjs +10 -1
- package/dist/components/filter-bar-multi.cjs.map +1 -1
- package/dist/components/filter-bar-multi.d.ts.map +1 -1
- package/dist/components/filter-bar-multi.js +11 -2
- package/dist/components/filter-bar-multi.js.map +1 -1
- package/dist/components/mdx-editor-callout-model.d.ts +1 -1
- package/dist/data/MarkdownEditor.model.d.ts +1 -1
- package/dist/data/ai/ChatWindow.catalogs.cjs +11 -5
- package/dist/data/ai/ChatWindow.catalogs.cjs.map +1 -1
- package/dist/data/ai/ChatWindow.catalogs.d.ts +2 -1
- package/dist/data/ai/ChatWindow.catalogs.d.ts.map +1 -1
- package/dist/data/ai/ChatWindow.catalogs.js +11 -5
- package/dist/data/ai/ChatWindow.catalogs.js.map +1 -1
- package/dist/data/ai/ChatWindow.cjs +1 -0
- package/dist/data/ai/ChatWindow.cjs.map +1 -1
- package/dist/data/ai/ChatWindow.d.ts.map +1 -1
- package/dist/data/ai/ChatWindow.js +1 -0
- package/dist/data/ai/ChatWindow.js.map +1 -1
- package/dist/data/ai/PromptRunEditor/VariablesField.cjs +79 -0
- package/dist/data/ai/PromptRunEditor/VariablesField.cjs.map +1 -0
- package/dist/data/ai/PromptRunEditor/VariablesField.d.ts +8 -0
- package/dist/data/ai/PromptRunEditor/VariablesField.d.ts.map +1 -0
- package/dist/data/ai/PromptRunEditor/VariablesField.js +79 -0
- package/dist/data/ai/PromptRunEditor/VariablesField.js.map +1 -0
- package/dist/data/ai/PromptRunEditor/index.cjs +61 -69
- package/dist/data/ai/PromptRunEditor/index.cjs.map +1 -1
- package/dist/data/ai/PromptRunEditor/index.d.ts +11 -1
- package/dist/data/ai/PromptRunEditor/index.d.ts.map +1 -1
- package/dist/data/ai/PromptRunEditor/index.js +61 -69
- package/dist/data/ai/PromptRunEditor/index.js.map +1 -1
- package/dist/data/ai/PromptRunEditor/model.cjs.map +1 -1
- package/dist/data/ai/PromptRunEditor/model.d.ts +2 -0
- package/dist/data/ai/PromptRunEditor/model.d.ts.map +1 -1
- package/dist/data/ai/PromptRunEditor/model.js.map +1 -1
- package/dist/data/ai/SessionViewer.model.cjs +23 -8
- package/dist/data/ai/SessionViewer.model.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.model.d.ts +8 -0
- package/dist/data/ai/SessionViewer.model.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.model.js +23 -8
- package/dist/data/ai/SessionViewer.model.js.map +1 -1
- package/dist/data/ai/SessionViewer.rows.cjs +9 -1
- package/dist/data/ai/SessionViewer.rows.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.rows.js +9 -1
- package/dist/data/ai/SessionViewer.rows.js.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/ModelSection.cjs +4 -3
- package/dist/data/ai/SpecRuntimeEditor/ModelSection.cjs.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/ModelSection.d.ts.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/ModelSection.js +2 -1
- package/dist/data/ai/SpecRuntimeEditor/ModelSection.js.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/PermissionModeField.cjs +2 -2
- package/dist/data/ai/SpecRuntimeEditor/PermissionModeField.cjs.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/PermissionModeField.js +1 -1
- package/dist/data/ai/SpecRuntimeEditor/VerifySection.cjs +24 -2
- package/dist/data/ai/SpecRuntimeEditor/VerifySection.cjs.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/VerifySection.d.ts.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/VerifySection.js +25 -3
- package/dist/data/ai/SpecRuntimeEditor/VerifySection.js.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/index.cjs +4 -3
- package/dist/data/ai/SpecRuntimeEditor/index.cjs.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/index.d.ts.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/index.js +2 -1
- package/dist/data/ai/SpecRuntimeEditor/index.js.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/summaries.cjs.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/summaries.d.ts.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/summaries.js.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor.model.cjs +4 -0
- package/dist/data/ai/SpecRuntimeEditor.model.cjs.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor.model.d.ts +4 -0
- package/dist/data/ai/SpecRuntimeEditor.model.d.ts.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor.model.js +4 -0
- package/dist/data/ai/SpecRuntimeEditor.model.js.map +1 -1
- package/dist/data/ai/index.d.ts +3 -2
- package/dist/data/ai/index.d.ts.map +1 -1
- package/dist/data/ai/runtime-profile.cjs.map +1 -1
- package/dist/data/ai/runtime-profile.d.ts +9 -7
- package/dist/data/ai/runtime-profile.d.ts.map +1 -1
- package/dist/data/ai/runtime-profile.js.map +1 -1
- package/dist/data/ai/runtime-profiles/OrderedPresetSelect.cjs +111 -0
- package/dist/data/ai/runtime-profiles/OrderedPresetSelect.cjs.map +1 -0
- package/dist/data/ai/runtime-profiles/OrderedPresetSelect.d.ts +7 -0
- package/dist/data/ai/runtime-profiles/OrderedPresetSelect.d.ts.map +1 -0
- package/dist/data/ai/runtime-profiles/OrderedPresetSelect.js +111 -0
- package/dist/data/ai/runtime-profiles/OrderedPresetSelect.js.map +1 -0
- package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.cjs +313 -0
- package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.cjs.map +1 -0
- package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.d.ts +8 -0
- package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.d.ts.map +1 -0
- package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.js +313 -0
- package/dist/data/ai/runtime-profiles/PermissionStrategiesEditor.js.map +1 -0
- package/dist/data/ai/runtime-profiles/PermissionStrategyConditionRow.cjs +98 -0
- package/dist/data/ai/runtime-profiles/PermissionStrategyConditionRow.cjs.map +1 -0
- package/dist/data/ai/runtime-profiles/PermissionStrategyConditionRow.d.ts +11 -0
- package/dist/data/ai/runtime-profiles/PermissionStrategyConditionRow.d.ts.map +1 -0
- package/dist/data/ai/runtime-profiles/PermissionStrategyConditionRow.js +98 -0
- package/dist/data/ai/runtime-profiles/PermissionStrategyConditionRow.js.map +1 -0
- package/dist/data/ai/runtime-profiles/PresetSpecEditor.cjs +35 -0
- package/dist/data/ai/runtime-profiles/PresetSpecEditor.cjs.map +1 -0
- package/dist/data/ai/runtime-profiles/PresetSpecEditor.d.ts +11 -0
- package/dist/data/ai/runtime-profiles/PresetSpecEditor.d.ts.map +1 -0
- package/dist/data/ai/runtime-profiles/PresetSpecEditor.js +35 -0
- package/dist/data/ai/runtime-profiles/PresetSpecEditor.js.map +1 -0
- package/dist/data/ai/runtime-profiles/PresetWorkspace.cjs +179 -0
- package/dist/data/ai/runtime-profiles/PresetWorkspace.cjs.map +1 -0
- package/dist/data/ai/runtime-profiles/PresetWorkspace.d.ts +22 -0
- package/dist/data/ai/runtime-profiles/PresetWorkspace.d.ts.map +1 -0
- package/dist/data/ai/runtime-profiles/PresetWorkspace.js +179 -0
- package/dist/data/ai/runtime-profiles/PresetWorkspace.js.map +1 -0
- package/dist/data/ai/runtime-profiles/ProfileSpecEditor.cjs +57 -0
- package/dist/data/ai/runtime-profiles/ProfileSpecEditor.cjs.map +1 -0
- package/dist/data/ai/runtime-profiles/ProfileSpecEditor.d.ts +18 -0
- package/dist/data/ai/runtime-profiles/ProfileSpecEditor.d.ts.map +1 -0
- package/dist/data/ai/runtime-profiles/ProfileSpecEditor.js +57 -0
- package/dist/data/ai/runtime-profiles/ProfileSpecEditor.js.map +1 -0
- package/dist/data/ai/runtime-profiles/ProfileWorkspace.cjs +135 -0
- package/dist/data/ai/runtime-profiles/ProfileWorkspace.cjs.map +1 -0
- package/dist/data/ai/runtime-profiles/ProfileWorkspace.d.ts +23 -0
- package/dist/data/ai/runtime-profiles/ProfileWorkspace.d.ts.map +1 -0
- package/dist/data/ai/runtime-profiles/ProfileWorkspace.js +135 -0
- package/dist/data/ai/runtime-profiles/ProfileWorkspace.js.map +1 -0
- package/dist/data/ai/runtime-profiles/ResolutionInspector.cjs +85 -0
- package/dist/data/ai/runtime-profiles/ResolutionInspector.cjs.map +1 -0
- package/dist/data/ai/runtime-profiles/ResolutionInspector.d.ts +7 -0
- package/dist/data/ai/runtime-profiles/ResolutionInspector.d.ts.map +1 -0
- package/dist/data/ai/runtime-profiles/ResolutionInspector.js +85 -0
- package/dist/data/ai/runtime-profiles/ResolutionInspector.js.map +1 -0
- package/dist/data/ai/runtime-profiles/ResolutionTrace.cjs +42 -0
- package/dist/data/ai/runtime-profiles/ResolutionTrace.cjs.map +1 -0
- package/dist/data/ai/runtime-profiles/ResolutionTrace.d.ts +6 -0
- package/dist/data/ai/runtime-profiles/ResolutionTrace.d.ts.map +1 -0
- package/dist/data/ai/runtime-profiles/ResolutionTrace.js +42 -0
- package/dist/data/ai/runtime-profiles/ResolutionTrace.js.map +1 -0
- package/dist/data/ai/runtime-profiles/RuntimeLibraryList.cjs +93 -0
- package/dist/data/ai/runtime-profiles/RuntimeLibraryList.cjs.map +1 -0
- package/dist/data/ai/runtime-profiles/RuntimeLibraryList.d.ts +18 -0
- package/dist/data/ai/runtime-profiles/RuntimeLibraryList.d.ts.map +1 -0
- package/dist/data/ai/runtime-profiles/RuntimeLibraryList.js +93 -0
- package/dist/data/ai/runtime-profiles/RuntimeLibraryList.js.map +1 -0
- package/dist/data/ai/runtime-profiles/RuntimePersistenceBar.cjs +44 -0
- package/dist/data/ai/runtime-profiles/RuntimePersistenceBar.cjs.map +1 -0
- package/dist/data/ai/runtime-profiles/RuntimePersistenceBar.d.ts +6 -0
- package/dist/data/ai/runtime-profiles/RuntimePersistenceBar.d.ts.map +1 -0
- package/dist/data/ai/runtime-profiles/RuntimePersistenceBar.js +44 -0
- package/dist/data/ai/runtime-profiles/RuntimePersistenceBar.js.map +1 -0
- package/dist/data/ai/runtime-profiles/RuntimeProfilePicker.cjs +198 -0
- package/dist/data/ai/runtime-profiles/RuntimeProfilePicker.cjs.map +1 -0
- package/dist/data/ai/runtime-profiles/RuntimeProfilePicker.d.ts +12 -0
- package/dist/data/ai/runtime-profiles/RuntimeProfilePicker.d.ts.map +1 -0
- package/dist/data/ai/runtime-profiles/RuntimeProfilePicker.js +198 -0
- package/dist/data/ai/runtime-profiles/RuntimeProfilePicker.js.map +1 -0
- package/dist/data/ai/runtime-profiles/RuntimeProfilePicker.model.cjs +97 -0
- package/dist/data/ai/runtime-profiles/RuntimeProfilePicker.model.cjs.map +1 -0
- package/dist/data/ai/runtime-profiles/RuntimeProfilePicker.model.d.ts +26 -0
- package/dist/data/ai/runtime-profiles/RuntimeProfilePicker.model.d.ts.map +1 -0
- package/dist/data/ai/runtime-profiles/RuntimeProfilePicker.model.js +97 -0
- package/dist/data/ai/runtime-profiles/RuntimeProfilePicker.model.js.map +1 -0
- package/dist/data/ai/runtime-profiles/RuntimeProfilesWorkspace.cjs +143 -0
- package/dist/data/ai/runtime-profiles/RuntimeProfilesWorkspace.cjs.map +1 -0
- package/dist/data/ai/runtime-profiles/RuntimeProfilesWorkspace.d.ts +25 -0
- package/dist/data/ai/runtime-profiles/RuntimeProfilesWorkspace.d.ts.map +1 -0
- package/dist/data/ai/runtime-profiles/RuntimeProfilesWorkspace.js +143 -0
- package/dist/data/ai/runtime-profiles/RuntimeProfilesWorkspace.js.map +1 -0
- package/dist/data/ai/runtime-profiles/RuntimeStatusNotice.cjs +41 -0
- package/dist/data/ai/runtime-profiles/RuntimeStatusNotice.cjs.map +1 -0
- package/dist/data/ai/runtime-profiles/RuntimeStatusNotice.d.ts +8 -0
- package/dist/data/ai/runtime-profiles/RuntimeStatusNotice.d.ts.map +1 -0
- package/dist/data/ai/runtime-profiles/RuntimeStatusNotice.js +41 -0
- package/dist/data/ai/runtime-profiles/RuntimeStatusNotice.js.map +1 -0
- package/dist/data/ai/runtime-profiles/index.d.ts +20 -0
- package/dist/data/ai/runtime-profiles/index.d.ts.map +1 -0
- package/dist/data/ai/runtime-profiles/types.d.ts +50 -0
- package/dist/data/ai/runtime-profiles/types.d.ts.map +1 -0
- package/dist/data/ai/runtime-profiles/use-permission-catalog.cjs +37 -0
- package/dist/data/ai/runtime-profiles/use-permission-catalog.cjs.map +1 -0
- package/dist/data/ai/runtime-profiles/use-permission-catalog.d.ts +5 -0
- package/dist/data/ai/runtime-profiles/use-permission-catalog.d.ts.map +1 -0
- package/dist/data/ai/runtime-profiles/use-permission-catalog.js +37 -0
- package/dist/data/ai/runtime-profiles/use-permission-catalog.js.map +1 -0
- package/dist/data/ai/runtime-profiles/use-resolution.cjs +43 -0
- package/dist/data/ai/runtime-profiles/use-resolution.cjs.map +1 -0
- package/dist/data/ai/runtime-profiles/use-resolution.d.ts +4 -0
- package/dist/data/ai/runtime-profiles/use-resolution.d.ts.map +1 -0
- package/dist/data/ai/runtime-profiles/use-resolution.js +43 -0
- package/dist/data/ai/runtime-profiles/use-resolution.js.map +1 -0
- package/dist/data/ai/runtime-profiles/use-runtime-families.cjs +38 -0
- package/dist/data/ai/runtime-profiles/use-runtime-families.cjs.map +1 -0
- package/dist/data/ai/runtime-profiles/use-runtime-families.d.ts +3 -0
- package/dist/data/ai/runtime-profiles/use-runtime-families.d.ts.map +1 -0
- package/dist/data/ai/runtime-profiles/use-runtime-families.js +38 -0
- package/dist/data/ai/runtime-profiles/use-runtime-families.js.map +1 -0
- package/dist/data/ai/runtime-profiles/use-runtime-profile-picker.cjs +107 -0
- package/dist/data/ai/runtime-profiles/use-runtime-profile-picker.cjs.map +1 -0
- package/dist/data/ai/runtime-profiles/use-runtime-profile-picker.d.ts +35 -0
- package/dist/data/ai/runtime-profiles/use-runtime-profile-picker.d.ts.map +1 -0
- package/dist/data/ai/runtime-profiles/use-runtime-profile-picker.js +107 -0
- package/dist/data/ai/runtime-profiles/use-runtime-profile-picker.js.map +1 -0
- package/dist/data/ai/use-session-scroll.cjs.map +1 -1
- package/dist/data/ai/use-session-scroll.d.ts +2 -2
- package/dist/data/ai/use-session-scroll.d.ts.map +1 -1
- package/dist/data/ai/use-session-scroll.js.map +1 -1
- package/dist/data/badge-variants.d.ts +1 -1
- package/dist/data/runtime/RuntimeBar.cjs +3 -2
- package/dist/data/runtime/RuntimeBar.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBar.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBar.js +3 -2
- package/dist/data/runtime/RuntimeBar.js.map +1 -1
- package/dist/data/runtime/runtime-field-support.cjs +3 -3
- package/dist/data/runtime/runtime-field-support.cjs.map +1 -1
- package/dist/data/runtime/runtime-field-support.js +1 -1
- package/dist/data/runtime/runtime-mode.cjs +14 -47
- package/dist/data/runtime/runtime-mode.cjs.map +1 -1
- package/dist/data/runtime/runtime-mode.d.ts +5 -7
- package/dist/data/runtime/runtime-mode.d.ts.map +1 -1
- package/dist/data/runtime/runtime-mode.js +7 -39
- package/dist/data/runtime/runtime-mode.js.map +1 -1
- package/dist/data/test-runner/TestRunner.cjs +6 -4
- package/dist/data/test-runner/TestRunner.cjs.map +1 -1
- package/dist/data/test-runner/TestRunner.d.ts +10 -1
- package/dist/data/test-runner/TestRunner.d.ts.map +1 -1
- package/dist/data/test-runner/TestRunner.js +6 -4
- package/dist/data/test-runner/TestRunner.js.map +1 -1
- package/dist/data/verification/VerificationResults.cjs +99 -0
- package/dist/data/verification/VerificationResults.cjs.map +1 -0
- package/dist/data/verification/VerificationResults.d.ts +27 -0
- package/dist/data/verification/VerificationResults.d.ts.map +1 -0
- package/dist/data/verification/VerificationResults.js +99 -0
- package/dist/data/verification/VerificationResults.js.map +1 -0
- package/dist/data/verification/adapterViews.cjs +116 -0
- package/dist/data/verification/adapterViews.cjs.map +1 -0
- package/dist/data/verification/adapterViews.d.ts +13 -0
- package/dist/data/verification/adapterViews.d.ts.map +1 -0
- package/dist/data/verification/adapterViews.js +116 -0
- package/dist/data/verification/adapterViews.js.map +1 -0
- package/dist/data/verification/adapters.cjs +26 -0
- package/dist/data/verification/adapters.cjs.map +1 -0
- package/dist/data/verification/adapters.d.ts +6 -0
- package/dist/data/verification/adapters.d.ts.map +1 -0
- package/dist/data/verification/adapters.js +26 -0
- package/dist/data/verification/adapters.js.map +1 -0
- package/dist/data/verification/index.d.ts +5 -0
- package/dist/data/verification/index.d.ts.map +1 -0
- package/dist/data/verification/verify-report.cjs +58 -0
- package/dist/data/verification/verify-report.cjs.map +1 -0
- package/dist/data/verification/verify-report.d.ts +96 -0
- package/dist/data/verification/verify-report.d.ts.map +1 -0
- package/dist/data/verification/verify-report.js +58 -0
- package/dist/data/verification/verify-report.js.map +1 -0
- package/dist/data/verification/verifyReportTests.cjs +83 -0
- package/dist/data/verification/verifyReportTests.cjs.map +1 -0
- package/dist/data/verification/verifyReportTests.d.ts +13 -0
- package/dist/data/verification/verifyReportTests.d.ts.map +1 -0
- package/dist/data/verification/verifyReportTests.js +83 -0
- package/dist/data/verification/verifyReportTests.js.map +1 -0
- package/dist/data/version-info.cjs +3 -3
- package/dist/data/version-info.js +3 -3
- package/dist/data.cjs +10 -0
- package/dist/data.cjs.map +1 -1
- package/dist/data.d.ts +1 -0
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +10 -0
- package/dist/data.js.map +1 -1
- package/dist/index.cjs +62 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +62 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/permission-strategies.cjs +155 -0
- package/dist/lib/permission-strategies.cjs.map +1 -0
- package/dist/lib/permission-strategies.d.ts +35 -0
- package/dist/lib/permission-strategies.d.ts.map +1 -0
- package/dist/lib/permission-strategies.js +155 -0
- package/dist/lib/permission-strategies.js.map +1 -0
- package/dist/lib/runtime-family.cjs +51 -0
- package/dist/lib/runtime-family.cjs.map +1 -0
- package/dist/lib/runtime-family.d.ts +25 -0
- package/dist/lib/runtime-family.d.ts.map +1 -0
- package/dist/lib/runtime-family.js +51 -0
- package/dist/lib/runtime-family.js.map +1 -0
- package/dist/lib/runtime-profile-model.cjs +129 -0
- package/dist/lib/runtime-profile-model.cjs.map +1 -0
- package/dist/lib/runtime-profile-model.d.ts +30 -0
- package/dist/lib/runtime-profile-model.d.ts.map +1 -0
- package/dist/lib/runtime-profile-model.js +129 -0
- package/dist/lib/runtime-profile-model.js.map +1 -0
- package/dist/styles.css +1 -1
- package/dist/utils.cjs +52 -0
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.ts +5 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +53 -1
- package/dist/utils.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-resolution.js","sources":["../../../../src/data/ai/runtime-profiles/use-resolution.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\nimport type { RuntimePreset, RuntimeProfile } from \"../runtime-profile\";\nimport type {\n RuntimeProfileResolutionState,\n RuntimeProfilesClient,\n} from \"./types\";\n\nconst EMPTY_PROFILE: RuntimeProfile = {\n id: \"empty\",\n name: \"Empty profile\",\n spec: {},\n presets: [],\n};\n\nexport function useRuntimeProfileResolution(\n client: RuntimeProfilesClient,\n profile: RuntimeProfile | undefined,\n presets: RuntimePreset[],\n): RuntimeProfileResolutionState {\n const [state, setState] = useState<RuntimeProfileResolutionState>({\n status: \"loading\",\n });\n\n useEffect(() => {\n const controller = new AbortController();\n setState({ status: \"loading\" });\n const timer = window.setTimeout(() => {\n void client\n .resolve(\n { profile: profile ?? EMPTY_PROFILE, presets },\n controller.signal,\n )\n .then(\n (result) => {\n if (controller.signal.aborted) return;\n setState({ status: \"resolved\", result });\n },\n (error: unknown) => {\n if (controller.signal.aborted) return;\n setState({\n status: \"error\",\n error: error instanceof Error ? error.message : String(error),\n });\n },\n );\n }, 150);\n return () => {\n window.clearTimeout(timer);\n controller.abort();\n };\n }, [client, presets, profile]);\n\n return state;\n}\n"],"names":[],"mappings":";AAOA,MAAM,gBAAgC;AAAA,EACpC,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,MAAM,CAAA;AAAA,EACN,SAAS,CAAA;AACX;AAEO,SAAS,4BACd,QACA,SACA,SAC+B;AAC/B,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwC;AAAA,IAChE,QAAQ;AAAA,EAAA,CACT;AAED,YAAU,MAAM;AACd,UAAM,aAAa,IAAI,gBAAA;AACvB,aAAS,EAAE,QAAQ,WAAW;AAC9B,UAAM,QAAQ,OAAO,WAAW,MAAM;AACpC,WAAK,OACF;AAAA,QACC,EAAE,SAAS,WAAW,eAAe,QAAA;AAAA,QACrC,WAAW;AAAA,MAAA,EAEZ;AAAA,QACC,CAAC,WAAW;AACV,cAAI,WAAW,OAAO,QAAS;AAC/B,mBAAS,EAAE,QAAQ,YAAY,OAAA,CAAQ;AAAA,QACzC;AAAA,QACA,CAAC,UAAmB;AAClB,cAAI,WAAW,OAAO,QAAS;AAC/B,mBAAS;AAAA,YACP,QAAQ;AAAA,YACR,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,UAAA,CAC7D;AAAA,QACH;AAAA,MAAA;AAAA,IAEN,GAAG,GAAG;AACN,WAAO,MAAM;AACX,aAAO,aAAa,KAAK;AACzB,iBAAW,MAAA;AAAA,IACb;AAAA,EACF,GAAG,CAAC,QAAQ,SAAS,OAAO,CAAC;AAE7B,SAAO;AACT;"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const react = require("react");
|
|
4
|
+
function useRuntimeFamilies(client) {
|
|
5
|
+
const [attempt, setAttempt] = react.useState(0);
|
|
6
|
+
const [state, setState] = react.useState({
|
|
7
|
+
families: [],
|
|
8
|
+
status: client.loadFamilies ? "loading" : "resolved"
|
|
9
|
+
});
|
|
10
|
+
const retry = react.useCallback(() => setAttempt((current) => current + 1), []);
|
|
11
|
+
const { loadFamilies } = client;
|
|
12
|
+
react.useEffect(() => {
|
|
13
|
+
if (!loadFamilies) {
|
|
14
|
+
setState({ families: [], status: "resolved" });
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const controller = new AbortController();
|
|
18
|
+
setState({ families: [], status: "loading" });
|
|
19
|
+
void loadFamilies(controller.signal).then(
|
|
20
|
+
(families) => {
|
|
21
|
+
if (controller.signal.aborted) return;
|
|
22
|
+
setState({ families, status: "resolved" });
|
|
23
|
+
},
|
|
24
|
+
(error) => {
|
|
25
|
+
if (controller.signal.aborted) return;
|
|
26
|
+
setState({
|
|
27
|
+
families: [],
|
|
28
|
+
status: "error",
|
|
29
|
+
error: error instanceof Error ? error.message : String(error)
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
);
|
|
33
|
+
return () => controller.abort();
|
|
34
|
+
}, [attempt, loadFamilies]);
|
|
35
|
+
return { ...state, retry };
|
|
36
|
+
}
|
|
37
|
+
exports.useRuntimeFamilies = useRuntimeFamilies;
|
|
38
|
+
//# sourceMappingURL=use-runtime-families.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-runtime-families.cjs","sources":["../../../../src/data/ai/runtime-profiles/use-runtime-families.ts"],"sourcesContent":["import { useCallback, useEffect, useState } from \"react\";\nimport type { RuntimeFamiliesState, RuntimeProfilesClient } from \"./types\";\n\nexport function useRuntimeFamilies(\n client: RuntimeProfilesClient,\n): RuntimeFamiliesState {\n const [attempt, setAttempt] = useState(0);\n const [state, setState] = useState<Omit<RuntimeFamiliesState, \"retry\">>({\n families: [],\n status: client.loadFamilies ? \"loading\" : \"resolved\",\n });\n const retry = useCallback(() => setAttempt((current) => current + 1), []);\n const { loadFamilies } = client;\n\n useEffect(() => {\n if (!loadFamilies) {\n setState({ families: [], status: \"resolved\" });\n return;\n }\n const controller = new AbortController();\n setState({ families: [], status: \"loading\" });\n void loadFamilies(controller.signal).then(\n (families) => {\n if (controller.signal.aborted) return;\n setState({ families, status: \"resolved\" });\n },\n (error: unknown) => {\n if (controller.signal.aborted) return;\n setState({\n families: [],\n status: \"error\",\n error: error instanceof Error ? error.message : String(error),\n });\n },\n );\n return () => controller.abort();\n }, [attempt, loadFamilies]);\n\n return { ...state, retry };\n}\n"],"names":["useState","useCallback","useEffect"],"mappings":";;;AAGO,SAAS,mBACd,QACsB;AACtB,QAAM,CAAC,SAAS,UAAU,IAAIA,MAAAA,SAAS,CAAC;AACxC,QAAM,CAAC,OAAO,QAAQ,IAAIA,eAA8C;AAAA,IACtE,UAAU,CAAA;AAAA,IACV,QAAQ,OAAO,eAAe,YAAY;AAAA,EAAA,CAC3C;AACD,QAAM,QAAQC,MAAAA,YAAY,MAAM,WAAW,CAAC,YAAY,UAAU,CAAC,GAAG,EAAE;AACxE,QAAM,EAAE,iBAAiB;AAEzBC,QAAAA,UAAU,MAAM;AACd,QAAI,CAAC,cAAc;AACjB,eAAS,EAAE,UAAU,CAAA,GAAI,QAAQ,YAAY;AAC7C;AAAA,IACF;AACA,UAAM,aAAa,IAAI,gBAAA;AACvB,aAAS,EAAE,UAAU,CAAA,GAAI,QAAQ,WAAW;AAC5C,SAAK,aAAa,WAAW,MAAM,EAAE;AAAA,MACnC,CAAC,aAAa;AACZ,YAAI,WAAW,OAAO,QAAS;AAC/B,iBAAS,EAAE,UAAU,QAAQ,WAAA,CAAY;AAAA,MAC3C;AAAA,MACA,CAAC,UAAmB;AAClB,YAAI,WAAW,OAAO,QAAS;AAC/B,iBAAS;AAAA,UACP,UAAU,CAAA;AAAA,UACV,QAAQ;AAAA,UACR,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,QAAA,CAC7D;AAAA,MACH;AAAA,IAAA;AAEF,WAAO,MAAM,WAAW,MAAA;AAAA,EAC1B,GAAG,CAAC,SAAS,YAAY,CAAC;AAE1B,SAAO,EAAE,GAAG,OAAO,MAAA;AACrB;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-runtime-families.d.ts","sourceRoot":"","sources":["../../../../src/data/ai/runtime-profiles/use-runtime-families.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAE3E,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,qBAAqB,GAC5B,oBAAoB,CAkCtB"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { useState, useCallback, useEffect } from "react";
|
|
2
|
+
function useRuntimeFamilies(client) {
|
|
3
|
+
const [attempt, setAttempt] = useState(0);
|
|
4
|
+
const [state, setState] = useState({
|
|
5
|
+
families: [],
|
|
6
|
+
status: client.loadFamilies ? "loading" : "resolved"
|
|
7
|
+
});
|
|
8
|
+
const retry = useCallback(() => setAttempt((current) => current + 1), []);
|
|
9
|
+
const { loadFamilies } = client;
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
if (!loadFamilies) {
|
|
12
|
+
setState({ families: [], status: "resolved" });
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const controller = new AbortController();
|
|
16
|
+
setState({ families: [], status: "loading" });
|
|
17
|
+
void loadFamilies(controller.signal).then(
|
|
18
|
+
(families) => {
|
|
19
|
+
if (controller.signal.aborted) return;
|
|
20
|
+
setState({ families, status: "resolved" });
|
|
21
|
+
},
|
|
22
|
+
(error) => {
|
|
23
|
+
if (controller.signal.aborted) return;
|
|
24
|
+
setState({
|
|
25
|
+
families: [],
|
|
26
|
+
status: "error",
|
|
27
|
+
error: error instanceof Error ? error.message : String(error)
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
);
|
|
31
|
+
return () => controller.abort();
|
|
32
|
+
}, [attempt, loadFamilies]);
|
|
33
|
+
return { ...state, retry };
|
|
34
|
+
}
|
|
35
|
+
export {
|
|
36
|
+
useRuntimeFamilies
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=use-runtime-families.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-runtime-families.js","sources":["../../../../src/data/ai/runtime-profiles/use-runtime-families.ts"],"sourcesContent":["import { useCallback, useEffect, useState } from \"react\";\nimport type { RuntimeFamiliesState, RuntimeProfilesClient } from \"./types\";\n\nexport function useRuntimeFamilies(\n client: RuntimeProfilesClient,\n): RuntimeFamiliesState {\n const [attempt, setAttempt] = useState(0);\n const [state, setState] = useState<Omit<RuntimeFamiliesState, \"retry\">>({\n families: [],\n status: client.loadFamilies ? \"loading\" : \"resolved\",\n });\n const retry = useCallback(() => setAttempt((current) => current + 1), []);\n const { loadFamilies } = client;\n\n useEffect(() => {\n if (!loadFamilies) {\n setState({ families: [], status: \"resolved\" });\n return;\n }\n const controller = new AbortController();\n setState({ families: [], status: \"loading\" });\n void loadFamilies(controller.signal).then(\n (families) => {\n if (controller.signal.aborted) return;\n setState({ families, status: \"resolved\" });\n },\n (error: unknown) => {\n if (controller.signal.aborted) return;\n setState({\n families: [],\n status: \"error\",\n error: error instanceof Error ? error.message : String(error),\n });\n },\n );\n return () => controller.abort();\n }, [attempt, loadFamilies]);\n\n return { ...state, retry };\n}\n"],"names":[],"mappings":";AAGO,SAAS,mBACd,QACsB;AACtB,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,CAAC;AACxC,QAAM,CAAC,OAAO,QAAQ,IAAI,SAA8C;AAAA,IACtE,UAAU,CAAA;AAAA,IACV,QAAQ,OAAO,eAAe,YAAY;AAAA,EAAA,CAC3C;AACD,QAAM,QAAQ,YAAY,MAAM,WAAW,CAAC,YAAY,UAAU,CAAC,GAAG,EAAE;AACxE,QAAM,EAAE,iBAAiB;AAEzB,YAAU,MAAM;AACd,QAAI,CAAC,cAAc;AACjB,eAAS,EAAE,UAAU,CAAA,GAAI,QAAQ,YAAY;AAC7C;AAAA,IACF;AACA,UAAM,aAAa,IAAI,gBAAA;AACvB,aAAS,EAAE,UAAU,CAAA,GAAI,QAAQ,WAAW;AAC5C,SAAK,aAAa,WAAW,MAAM,EAAE;AAAA,MACnC,CAAC,aAAa;AACZ,YAAI,WAAW,OAAO,QAAS;AAC/B,iBAAS,EAAE,UAAU,QAAQ,WAAA,CAAY;AAAA,MAC3C;AAAA,MACA,CAAC,UAAmB;AAClB,YAAI,WAAW,OAAO,QAAS;AAC/B,iBAAS;AAAA,UACP,UAAU,CAAA;AAAA,UACV,QAAQ;AAAA,UACR,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,QAAA,CAC7D;AAAA,MACH;AAAA,IAAA;AAEF,WAAO,MAAM,WAAW,MAAA;AAAA,EAC1B,GAAG,CAAC,SAAS,YAAY,CAAC;AAE1B,SAAO,EAAE,GAAG,OAAO,MAAA;AACrB;"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const react = require("react");
|
|
4
|
+
const runtimeProfileModel = require("../../../lib/runtime-profile-model.cjs");
|
|
5
|
+
const RuntimeProfilePicker_model = require("./RuntimeProfilePicker.model.cjs");
|
|
6
|
+
const DETACH_NOTICE = "Detached from the authored profile spec; presets were not resolved.";
|
|
7
|
+
function useRuntimeProfilePicker({
|
|
8
|
+
value,
|
|
9
|
+
onChange,
|
|
10
|
+
profiles,
|
|
11
|
+
presets,
|
|
12
|
+
onSaveProfile,
|
|
13
|
+
onCreateProfile,
|
|
14
|
+
onResolveProfile,
|
|
15
|
+
newId = () => crypto.randomUUID()
|
|
16
|
+
}) {
|
|
17
|
+
const [state, setState] = react.useState(() => RuntimeProfilePicker_model.pickerStateFor(value, profiles));
|
|
18
|
+
const [pending, setPending] = react.useState();
|
|
19
|
+
const [busy, setBusy] = react.useState();
|
|
20
|
+
const [error, setError] = react.useState();
|
|
21
|
+
const [notice, setNotice] = react.useState();
|
|
22
|
+
const saved = RuntimeProfilePicker_model.profileForRef(value.runtimeProfile, profiles);
|
|
23
|
+
const dirty = RuntimeProfilePicker_model.isDraftDirty(state, profiles);
|
|
24
|
+
react.useEffect(() => {
|
|
25
|
+
var _a;
|
|
26
|
+
const refChanged = value.runtimeProfile !== state.selectedRef;
|
|
27
|
+
const draftMissing = saved !== void 0 && ((_a = state.draft) == null ? void 0 : _a.id) !== saved.id && !dirty;
|
|
28
|
+
if (!refChanged && !draftMissing) return;
|
|
29
|
+
setState(RuntimeProfilePicker_model.pickerStateFor(value, profiles));
|
|
30
|
+
setPending(void 0);
|
|
31
|
+
}, [value.runtimeProfile, saved]);
|
|
32
|
+
const apply = (ref) => {
|
|
33
|
+
const profile = RuntimeProfilePicker_model.profileForRef(ref, profiles);
|
|
34
|
+
setState({
|
|
35
|
+
selectedRef: profile == null ? void 0 : profile.id,
|
|
36
|
+
draft: profile ? structuredClone(profile) : void 0,
|
|
37
|
+
layer: "run"
|
|
38
|
+
});
|
|
39
|
+
setPending(void 0);
|
|
40
|
+
setError(void 0);
|
|
41
|
+
setNotice(void 0);
|
|
42
|
+
onChange(RuntimeProfilePicker_model.selectProfile(value, profile));
|
|
43
|
+
};
|
|
44
|
+
const run = async (kind, action) => {
|
|
45
|
+
setBusy(kind);
|
|
46
|
+
setError(void 0);
|
|
47
|
+
setNotice(void 0);
|
|
48
|
+
try {
|
|
49
|
+
await action();
|
|
50
|
+
} catch (cause) {
|
|
51
|
+
setError(cause instanceof Error ? cause.message : String(cause));
|
|
52
|
+
} finally {
|
|
53
|
+
setBusy(void 0);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
const persist = async (handler, draft) => {
|
|
57
|
+
const persisted = await handler(draft);
|
|
58
|
+
const next = RuntimeProfilePicker_model.afterSave(value, state, persisted);
|
|
59
|
+
setState(next.state);
|
|
60
|
+
if (next.value !== value) onChange(next.value);
|
|
61
|
+
};
|
|
62
|
+
return {
|
|
63
|
+
state,
|
|
64
|
+
dirty,
|
|
65
|
+
pending,
|
|
66
|
+
busy,
|
|
67
|
+
error,
|
|
68
|
+
notice,
|
|
69
|
+
canSave: onSaveProfile !== void 0,
|
|
70
|
+
canCreate: onCreateProfile !== void 0,
|
|
71
|
+
select: (ref) => {
|
|
72
|
+
if (ref === state.selectedRef) return;
|
|
73
|
+
if (dirty) setPending({ ref });
|
|
74
|
+
else apply(ref);
|
|
75
|
+
},
|
|
76
|
+
confirmPending: () => {
|
|
77
|
+
if (pending) apply(pending.ref);
|
|
78
|
+
},
|
|
79
|
+
cancelPending: () => setPending(void 0),
|
|
80
|
+
setLayer: (layer) => setState((current) => ({ ...current, layer })),
|
|
81
|
+
editDraft: (draft) => setState((current) => RuntimeProfilePicker_model.editDraft(current, draft)),
|
|
82
|
+
save: () => run("save", async () => {
|
|
83
|
+
if (!onSaveProfile || !state.draft) return;
|
|
84
|
+
await persist(onSaveProfile, state.draft);
|
|
85
|
+
}),
|
|
86
|
+
saveAsNew: () => run("create", async () => {
|
|
87
|
+
if (!onCreateProfile || !state.draft) return;
|
|
88
|
+
await persist(
|
|
89
|
+
onCreateProfile,
|
|
90
|
+
RuntimeProfilePicker_model.saveAsNewDraft(state.draft, profiles, newId())
|
|
91
|
+
);
|
|
92
|
+
}),
|
|
93
|
+
detach: () => run("detach", async () => {
|
|
94
|
+
const draft = state.draft;
|
|
95
|
+
if (!draft) return;
|
|
96
|
+
const resolved = onResolveProfile ? (await onResolveProfile({
|
|
97
|
+
profile: draft,
|
|
98
|
+
presets: runtimeProfileModel.presetsOf(draft, presets).found
|
|
99
|
+
})).resolved.spec : draft.spec;
|
|
100
|
+
onChange(RuntimeProfilePicker_model.detachedValue(value, resolved));
|
|
101
|
+
setState({ selectedRef: void 0, draft: void 0, layer: "run" });
|
|
102
|
+
if (!onResolveProfile) setNotice(DETACH_NOTICE);
|
|
103
|
+
})
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
exports.useRuntimeProfilePicker = useRuntimeProfilePicker;
|
|
107
|
+
//# sourceMappingURL=use-runtime-profile-picker.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-runtime-profile-picker.cjs","sources":["../../../../src/data/ai/runtime-profiles/use-runtime-profile-picker.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\nimport type { AIPromptRunValue } from \"../PromptRunEditor/model\";\nimport type {\n ResolvedRuntimeProfile,\n RuntimePreset,\n RuntimeProfile,\n RuntimeProfileResolveRequest,\n} from \"../runtime-profile\";\nimport { presetsOf } from \"../../../lib/runtime-profile-model\";\nimport {\n afterSave,\n detachedValue,\n editDraft,\n isDraftDirty,\n pickerStateFor,\n profileForRef,\n saveAsNewDraft,\n selectProfile,\n type RuntimeProfileLayer,\n type RuntimeProfilePickerState,\n} from \"./RuntimeProfilePicker.model\";\n\nexport type RuntimeProfilePickerBusy = \"save\" | \"create\" | \"detach\";\n\nexport type RuntimeProfilePickerController = {\n state: RuntimeProfilePickerState;\n dirty: boolean;\n pending: { ref: string | undefined } | undefined;\n busy: RuntimeProfilePickerBusy | undefined;\n error: string | undefined;\n notice: string | undefined;\n canSave: boolean;\n canCreate: boolean;\n select: (ref: string | undefined) => void;\n confirmPending: () => void;\n cancelPending: () => void;\n setLayer: (layer: RuntimeProfileLayer) => void;\n editDraft: (draft: RuntimeProfile) => void;\n save: () => Promise<void>;\n saveAsNew: () => Promise<void>;\n detach: () => Promise<void>;\n};\n\nconst DETACH_NOTICE =\n \"Detached from the authored profile spec; presets were not resolved.\";\n\nexport function useRuntimeProfilePicker({\n value,\n onChange,\n profiles,\n presets,\n onSaveProfile,\n onCreateProfile,\n onResolveProfile,\n newId = () => crypto.randomUUID(),\n}: {\n value: AIPromptRunValue;\n onChange: (value: AIPromptRunValue) => void;\n profiles: RuntimeProfile[];\n presets: RuntimePreset[];\n onSaveProfile?:\n | ((profile: RuntimeProfile) => Promise<RuntimeProfile>)\n | undefined;\n onCreateProfile?:\n | ((profile: RuntimeProfile) => Promise<RuntimeProfile>)\n | undefined;\n onResolveProfile?:\n | ((\n request: RuntimeProfileResolveRequest,\n ) => Promise<ResolvedRuntimeProfile>)\n | undefined;\n newId?: (() => string) | undefined;\n}): RuntimeProfilePickerController {\n const [state, setState] = useState(() => pickerStateFor(value, profiles));\n const [pending, setPending] = useState<{ ref: string | undefined }>();\n const [busy, setBusy] = useState<RuntimeProfilePickerBusy>();\n const [error, setError] = useState<string>();\n const [notice, setNotice] = useState<string>();\n const saved = profileForRef(value.runtimeProfile, profiles);\n const dirty = isDraftDirty(state, profiles);\n\n useEffect(() => {\n const refChanged = value.runtimeProfile !== state.selectedRef;\n const draftMissing =\n saved !== undefined && state.draft?.id !== saved.id && !dirty;\n if (!refChanged && !draftMissing) return;\n setState(pickerStateFor(value, profiles));\n setPending(undefined);\n }, [value.runtimeProfile, saved]);\n\n const apply = (ref: string | undefined) => {\n const profile = profileForRef(ref, profiles);\n setState({\n selectedRef: profile?.id,\n draft: profile ? structuredClone(profile) : undefined,\n layer: \"run\",\n });\n setPending(undefined);\n setError(undefined);\n setNotice(undefined);\n onChange(selectProfile(value, profile));\n };\n\n const run = async (\n kind: RuntimeProfilePickerBusy,\n action: () => Promise<void>,\n ) => {\n setBusy(kind);\n setError(undefined);\n setNotice(undefined);\n try {\n await action();\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause));\n } finally {\n setBusy(undefined);\n }\n };\n\n const persist = async (\n handler: (profile: RuntimeProfile) => Promise<RuntimeProfile>,\n draft: RuntimeProfile,\n ) => {\n const persisted = await handler(draft);\n const next = afterSave(value, state, persisted);\n setState(next.state);\n if (next.value !== value) onChange(next.value);\n };\n\n return {\n state,\n dirty,\n pending,\n busy,\n error,\n notice,\n canSave: onSaveProfile !== undefined,\n canCreate: onCreateProfile !== undefined,\n select: (ref) => {\n if (ref === state.selectedRef) return;\n if (dirty) setPending({ ref });\n else apply(ref);\n },\n confirmPending: () => {\n if (pending) apply(pending.ref);\n },\n cancelPending: () => setPending(undefined),\n setLayer: (layer) => setState((current) => ({ ...current, layer })),\n editDraft: (draft) => setState((current) => editDraft(current, draft)),\n save: () =>\n run(\"save\", async () => {\n if (!onSaveProfile || !state.draft) return;\n await persist(onSaveProfile, state.draft);\n }),\n saveAsNew: () =>\n run(\"create\", async () => {\n if (!onCreateProfile || !state.draft) return;\n await persist(\n onCreateProfile,\n saveAsNewDraft(state.draft, profiles, newId()),\n );\n }),\n detach: () =>\n run(\"detach\", async () => {\n const draft = state.draft;\n if (!draft) return;\n const resolved = onResolveProfile\n ? (\n await onResolveProfile({\n profile: draft,\n presets: presetsOf(draft, presets).found,\n })\n ).resolved.spec\n : draft.spec;\n onChange(detachedValue(value, resolved));\n setState({ selectedRef: undefined, draft: undefined, layer: \"run\" });\n if (!onResolveProfile) setNotice(DETACH_NOTICE);\n }),\n };\n}\n"],"names":["useState","pickerStateFor","profileForRef","isDraftDirty","useEffect","selectProfile","afterSave","editDraft","saveAsNewDraft","presetsOf","detachedValue"],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { AIPromptRunValue } from '../PromptRunEditor/model';
|
|
2
|
+
import { ResolvedRuntimeProfile, RuntimePreset, RuntimeProfile, RuntimeProfileResolveRequest } from '../runtime-profile';
|
|
3
|
+
import { RuntimeProfileLayer, RuntimeProfilePickerState } from './RuntimeProfilePicker.model';
|
|
4
|
+
export type RuntimeProfilePickerBusy = "save" | "create" | "detach";
|
|
5
|
+
export type RuntimeProfilePickerController = {
|
|
6
|
+
state: RuntimeProfilePickerState;
|
|
7
|
+
dirty: boolean;
|
|
8
|
+
pending: {
|
|
9
|
+
ref: string | undefined;
|
|
10
|
+
} | undefined;
|
|
11
|
+
busy: RuntimeProfilePickerBusy | undefined;
|
|
12
|
+
error: string | undefined;
|
|
13
|
+
notice: string | undefined;
|
|
14
|
+
canSave: boolean;
|
|
15
|
+
canCreate: boolean;
|
|
16
|
+
select: (ref: string | undefined) => void;
|
|
17
|
+
confirmPending: () => void;
|
|
18
|
+
cancelPending: () => void;
|
|
19
|
+
setLayer: (layer: RuntimeProfileLayer) => void;
|
|
20
|
+
editDraft: (draft: RuntimeProfile) => void;
|
|
21
|
+
save: () => Promise<void>;
|
|
22
|
+
saveAsNew: () => Promise<void>;
|
|
23
|
+
detach: () => Promise<void>;
|
|
24
|
+
};
|
|
25
|
+
export declare function useRuntimeProfilePicker({ value, onChange, profiles, presets, onSaveProfile, onCreateProfile, onResolveProfile, newId, }: {
|
|
26
|
+
value: AIPromptRunValue;
|
|
27
|
+
onChange: (value: AIPromptRunValue) => void;
|
|
28
|
+
profiles: RuntimeProfile[];
|
|
29
|
+
presets: RuntimePreset[];
|
|
30
|
+
onSaveProfile?: ((profile: RuntimeProfile) => Promise<RuntimeProfile>) | undefined;
|
|
31
|
+
onCreateProfile?: ((profile: RuntimeProfile) => Promise<RuntimeProfile>) | undefined;
|
|
32
|
+
onResolveProfile?: ((request: RuntimeProfileResolveRequest) => Promise<ResolvedRuntimeProfile>) | undefined;
|
|
33
|
+
newId?: (() => string) | undefined;
|
|
34
|
+
}): RuntimeProfilePickerController;
|
|
35
|
+
//# sourceMappingURL=use-runtime-profile-picker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-runtime-profile-picker.d.ts","sourceRoot":"","sources":["../../../../src/data/ai/runtime-profiles/use-runtime-profile-picker.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EACV,sBAAsB,EACtB,aAAa,EACb,cAAc,EACd,4BAA4B,EAC7B,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EASL,KAAK,mBAAmB,EACxB,KAAK,yBAAyB,EAC/B,MAAM,8BAA8B,CAAC;AAEtC,MAAM,MAAM,wBAAwB,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEpE,MAAM,MAAM,8BAA8B,GAAG;IAC3C,KAAK,EAAE,yBAAyB,CAAC;IACjC,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,GAAG,SAAS,CAAC;IACjD,IAAI,EAAE,wBAAwB,GAAG,SAAS,CAAC;IAC3C,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAC1C,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,QAAQ,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC/C,SAAS,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC3C,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B,CAAC;AAKF,wBAAgB,uBAAuB,CAAC,EACtC,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,KAAiC,GAClC,EAAE;IACD,KAAK,EAAE,gBAAgB,CAAC;IACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC5C,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,aAAa,CAAC,EACV,CAAC,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC,GACtD,SAAS,CAAC;IACd,eAAe,CAAC,EACZ,CAAC,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC,GACtD,SAAS,CAAC;IACd,gBAAgB,CAAC,EACb,CAAC,CACC,OAAO,EAAE,4BAA4B,KAClC,OAAO,CAAC,sBAAsB,CAAC,CAAC,GACrC,SAAS,CAAC;IACd,KAAK,CAAC,EAAE,CAAC,MAAM,MAAM,CAAC,GAAG,SAAS,CAAC;CACpC,GAAG,8BAA8B,CA2GjC"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { useState, useEffect } from "react";
|
|
2
|
+
import { presetsOf } from "../../../lib/runtime-profile-model.js";
|
|
3
|
+
import { pickerStateFor, profileForRef, isDraftDirty, editDraft, selectProfile, detachedValue, saveAsNewDraft, afterSave } from "./RuntimeProfilePicker.model.js";
|
|
4
|
+
const DETACH_NOTICE = "Detached from the authored profile spec; presets were not resolved.";
|
|
5
|
+
function useRuntimeProfilePicker({
|
|
6
|
+
value,
|
|
7
|
+
onChange,
|
|
8
|
+
profiles,
|
|
9
|
+
presets,
|
|
10
|
+
onSaveProfile,
|
|
11
|
+
onCreateProfile,
|
|
12
|
+
onResolveProfile,
|
|
13
|
+
newId = () => crypto.randomUUID()
|
|
14
|
+
}) {
|
|
15
|
+
const [state, setState] = useState(() => pickerStateFor(value, profiles));
|
|
16
|
+
const [pending, setPending] = useState();
|
|
17
|
+
const [busy, setBusy] = useState();
|
|
18
|
+
const [error, setError] = useState();
|
|
19
|
+
const [notice, setNotice] = useState();
|
|
20
|
+
const saved = profileForRef(value.runtimeProfile, profiles);
|
|
21
|
+
const dirty = isDraftDirty(state, profiles);
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
var _a;
|
|
24
|
+
const refChanged = value.runtimeProfile !== state.selectedRef;
|
|
25
|
+
const draftMissing = saved !== void 0 && ((_a = state.draft) == null ? void 0 : _a.id) !== saved.id && !dirty;
|
|
26
|
+
if (!refChanged && !draftMissing) return;
|
|
27
|
+
setState(pickerStateFor(value, profiles));
|
|
28
|
+
setPending(void 0);
|
|
29
|
+
}, [value.runtimeProfile, saved]);
|
|
30
|
+
const apply = (ref) => {
|
|
31
|
+
const profile = profileForRef(ref, profiles);
|
|
32
|
+
setState({
|
|
33
|
+
selectedRef: profile == null ? void 0 : profile.id,
|
|
34
|
+
draft: profile ? structuredClone(profile) : void 0,
|
|
35
|
+
layer: "run"
|
|
36
|
+
});
|
|
37
|
+
setPending(void 0);
|
|
38
|
+
setError(void 0);
|
|
39
|
+
setNotice(void 0);
|
|
40
|
+
onChange(selectProfile(value, profile));
|
|
41
|
+
};
|
|
42
|
+
const run = async (kind, action) => {
|
|
43
|
+
setBusy(kind);
|
|
44
|
+
setError(void 0);
|
|
45
|
+
setNotice(void 0);
|
|
46
|
+
try {
|
|
47
|
+
await action();
|
|
48
|
+
} catch (cause) {
|
|
49
|
+
setError(cause instanceof Error ? cause.message : String(cause));
|
|
50
|
+
} finally {
|
|
51
|
+
setBusy(void 0);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
const persist = async (handler, draft) => {
|
|
55
|
+
const persisted = await handler(draft);
|
|
56
|
+
const next = afterSave(value, state, persisted);
|
|
57
|
+
setState(next.state);
|
|
58
|
+
if (next.value !== value) onChange(next.value);
|
|
59
|
+
};
|
|
60
|
+
return {
|
|
61
|
+
state,
|
|
62
|
+
dirty,
|
|
63
|
+
pending,
|
|
64
|
+
busy,
|
|
65
|
+
error,
|
|
66
|
+
notice,
|
|
67
|
+
canSave: onSaveProfile !== void 0,
|
|
68
|
+
canCreate: onCreateProfile !== void 0,
|
|
69
|
+
select: (ref) => {
|
|
70
|
+
if (ref === state.selectedRef) return;
|
|
71
|
+
if (dirty) setPending({ ref });
|
|
72
|
+
else apply(ref);
|
|
73
|
+
},
|
|
74
|
+
confirmPending: () => {
|
|
75
|
+
if (pending) apply(pending.ref);
|
|
76
|
+
},
|
|
77
|
+
cancelPending: () => setPending(void 0),
|
|
78
|
+
setLayer: (layer) => setState((current) => ({ ...current, layer })),
|
|
79
|
+
editDraft: (draft) => setState((current) => editDraft(current, draft)),
|
|
80
|
+
save: () => run("save", async () => {
|
|
81
|
+
if (!onSaveProfile || !state.draft) return;
|
|
82
|
+
await persist(onSaveProfile, state.draft);
|
|
83
|
+
}),
|
|
84
|
+
saveAsNew: () => run("create", async () => {
|
|
85
|
+
if (!onCreateProfile || !state.draft) return;
|
|
86
|
+
await persist(
|
|
87
|
+
onCreateProfile,
|
|
88
|
+
saveAsNewDraft(state.draft, profiles, newId())
|
|
89
|
+
);
|
|
90
|
+
}),
|
|
91
|
+
detach: () => run("detach", async () => {
|
|
92
|
+
const draft = state.draft;
|
|
93
|
+
if (!draft) return;
|
|
94
|
+
const resolved = onResolveProfile ? (await onResolveProfile({
|
|
95
|
+
profile: draft,
|
|
96
|
+
presets: presetsOf(draft, presets).found
|
|
97
|
+
})).resolved.spec : draft.spec;
|
|
98
|
+
onChange(detachedValue(value, resolved));
|
|
99
|
+
setState({ selectedRef: void 0, draft: void 0, layer: "run" });
|
|
100
|
+
if (!onResolveProfile) setNotice(DETACH_NOTICE);
|
|
101
|
+
})
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
export {
|
|
105
|
+
useRuntimeProfilePicker
|
|
106
|
+
};
|
|
107
|
+
//# sourceMappingURL=use-runtime-profile-picker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-runtime-profile-picker.js","sources":["../../../../src/data/ai/runtime-profiles/use-runtime-profile-picker.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\nimport type { AIPromptRunValue } from \"../PromptRunEditor/model\";\nimport type {\n ResolvedRuntimeProfile,\n RuntimePreset,\n RuntimeProfile,\n RuntimeProfileResolveRequest,\n} from \"../runtime-profile\";\nimport { presetsOf } from \"../../../lib/runtime-profile-model\";\nimport {\n afterSave,\n detachedValue,\n editDraft,\n isDraftDirty,\n pickerStateFor,\n profileForRef,\n saveAsNewDraft,\n selectProfile,\n type RuntimeProfileLayer,\n type RuntimeProfilePickerState,\n} from \"./RuntimeProfilePicker.model\";\n\nexport type RuntimeProfilePickerBusy = \"save\" | \"create\" | \"detach\";\n\nexport type RuntimeProfilePickerController = {\n state: RuntimeProfilePickerState;\n dirty: boolean;\n pending: { ref: string | undefined } | undefined;\n busy: RuntimeProfilePickerBusy | undefined;\n error: string | undefined;\n notice: string | undefined;\n canSave: boolean;\n canCreate: boolean;\n select: (ref: string | undefined) => void;\n confirmPending: () => void;\n cancelPending: () => void;\n setLayer: (layer: RuntimeProfileLayer) => void;\n editDraft: (draft: RuntimeProfile) => void;\n save: () => Promise<void>;\n saveAsNew: () => Promise<void>;\n detach: () => Promise<void>;\n};\n\nconst DETACH_NOTICE =\n \"Detached from the authored profile spec; presets were not resolved.\";\n\nexport function useRuntimeProfilePicker({\n value,\n onChange,\n profiles,\n presets,\n onSaveProfile,\n onCreateProfile,\n onResolveProfile,\n newId = () => crypto.randomUUID(),\n}: {\n value: AIPromptRunValue;\n onChange: (value: AIPromptRunValue) => void;\n profiles: RuntimeProfile[];\n presets: RuntimePreset[];\n onSaveProfile?:\n | ((profile: RuntimeProfile) => Promise<RuntimeProfile>)\n | undefined;\n onCreateProfile?:\n | ((profile: RuntimeProfile) => Promise<RuntimeProfile>)\n | undefined;\n onResolveProfile?:\n | ((\n request: RuntimeProfileResolveRequest,\n ) => Promise<ResolvedRuntimeProfile>)\n | undefined;\n newId?: (() => string) | undefined;\n}): RuntimeProfilePickerController {\n const [state, setState] = useState(() => pickerStateFor(value, profiles));\n const [pending, setPending] = useState<{ ref: string | undefined }>();\n const [busy, setBusy] = useState<RuntimeProfilePickerBusy>();\n const [error, setError] = useState<string>();\n const [notice, setNotice] = useState<string>();\n const saved = profileForRef(value.runtimeProfile, profiles);\n const dirty = isDraftDirty(state, profiles);\n\n useEffect(() => {\n const refChanged = value.runtimeProfile !== state.selectedRef;\n const draftMissing =\n saved !== undefined && state.draft?.id !== saved.id && !dirty;\n if (!refChanged && !draftMissing) return;\n setState(pickerStateFor(value, profiles));\n setPending(undefined);\n }, [value.runtimeProfile, saved]);\n\n const apply = (ref: string | undefined) => {\n const profile = profileForRef(ref, profiles);\n setState({\n selectedRef: profile?.id,\n draft: profile ? structuredClone(profile) : undefined,\n layer: \"run\",\n });\n setPending(undefined);\n setError(undefined);\n setNotice(undefined);\n onChange(selectProfile(value, profile));\n };\n\n const run = async (\n kind: RuntimeProfilePickerBusy,\n action: () => Promise<void>,\n ) => {\n setBusy(kind);\n setError(undefined);\n setNotice(undefined);\n try {\n await action();\n } catch (cause) {\n setError(cause instanceof Error ? cause.message : String(cause));\n } finally {\n setBusy(undefined);\n }\n };\n\n const persist = async (\n handler: (profile: RuntimeProfile) => Promise<RuntimeProfile>,\n draft: RuntimeProfile,\n ) => {\n const persisted = await handler(draft);\n const next = afterSave(value, state, persisted);\n setState(next.state);\n if (next.value !== value) onChange(next.value);\n };\n\n return {\n state,\n dirty,\n pending,\n busy,\n error,\n notice,\n canSave: onSaveProfile !== undefined,\n canCreate: onCreateProfile !== undefined,\n select: (ref) => {\n if (ref === state.selectedRef) return;\n if (dirty) setPending({ ref });\n else apply(ref);\n },\n confirmPending: () => {\n if (pending) apply(pending.ref);\n },\n cancelPending: () => setPending(undefined),\n setLayer: (layer) => setState((current) => ({ ...current, layer })),\n editDraft: (draft) => setState((current) => editDraft(current, draft)),\n save: () =>\n run(\"save\", async () => {\n if (!onSaveProfile || !state.draft) return;\n await persist(onSaveProfile, state.draft);\n }),\n saveAsNew: () =>\n run(\"create\", async () => {\n if (!onCreateProfile || !state.draft) return;\n await persist(\n onCreateProfile,\n saveAsNewDraft(state.draft, profiles, newId()),\n );\n }),\n detach: () =>\n run(\"detach\", async () => {\n const draft = state.draft;\n if (!draft) return;\n const resolved = onResolveProfile\n ? (\n await onResolveProfile({\n profile: draft,\n presets: presetsOf(draft, presets).found,\n })\n ).resolved.spec\n : draft.spec;\n onChange(detachedValue(value, resolved));\n setState({ selectedRef: undefined, draft: undefined, layer: \"run\" });\n if (!onResolveProfile) setNotice(DETACH_NOTICE);\n }),\n };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-session-scroll.cjs","sources":["../../../src/data/ai/use-session-scroll.ts"],"sourcesContent":["import { useCallback, useEffect, useLayoutEffect, useRef, useState, type RefObject } from \"react\";\n\n// Progressive windowing for the SessionViewer log. A recorded session runs to\n// thousands of rows (many with syntax-highlighted code blocks), so rendering the\n// whole transcript blocks first paint. Instead we render the *newest* screenful,\n// keep the view pinned to the bottom (most recent activity), and backfill older\n// rows as the reader scrolls up — the classic reverse-infinite-scroll of a chat\n// log. The pure helpers below hold the windowing math; the hook wires the DOM\n// listeners that drive it. Load-more is driven off scroll position rather than an\n// IntersectionObserver so it stays reliable in backgrounded/hidden tabs (where the\n// browser pauses observer callbacks tied to the render loop).\n\n/** The last `visibleCount` of `items`, plus where the window starts and whether\n * older items remain above it. */\nexport function windowSlice<T>(\n items: readonly T[],\n visibleCount: number,\n): { items: T[]; startIndex: number; hasMore: boolean } {\n const clamped = Math.max(0, Math.min(visibleCount, items.length));\n const startIndex = items.length - clamped;\n return { items: items.slice(startIndex), startIndex, hasMore: startIndex > 0 };\n}\n\n/** Grow the window by `batchSize`, never past `total`. */\nexport function nextVisibleCount(current: number, batchSize: number, total: number): number {\n return Math.min(current + Math.max(1, batchSize), total);\n}\n\n/** True when the scroll position sits within `threshold` px of the bottom. */\nexport function isPinnedToBottom(\n metrics: { scrollTop: number; scrollHeight: number; clientHeight: number },\n threshold: number,\n): boolean {\n return metrics.scrollHeight - metrics.scrollTop - metrics.clientHeight <= threshold;\n}\n\n/** True when the scroll position sits within `threshold` px of the top. */\nexport function isNearTop(scrollTop: number, threshold: number): boolean {\n return scrollTop <= threshold;\n}\n\nexport interface SessionScrollOptions {\n /** Number of filtered events available to render. */\n total: number;\n /** Turns the whole mechanism on; when false the hook renders every event. */\n enabled: boolean;\n /** Rows rendered on first paint (and after a session change). */\n windowSize: number;\n /** Rows added each time older content is loaded. */\n batchSize: number;\n /** Changing this resets the window and re-pins to the bottom — pass a value\n * derived from the session identity, not the filter state. */\n resetKey: string;\n /** Distance (px) from the bottom still counted as \"pinned\". */\n bottomThreshold?: number;\n /** Distance (px) from the top at which older rows start loading. */\n topThreshold?: number;\n}\n\nexport interface SessionScrollState {\n scrollRef: RefObject<HTMLDivElement>;\n contentRef: RefObject<HTMLDivElement>;\n startIndex: number;\n hasMore: boolean;\n}\n\nconst idleWindow = () =>\n (typeof window === \"undefined\" ? undefined : window) as\n | (Window & {\n requestIdleCallback?: (cb: () => void) => number;\n cancelIdleCallback?: (handle: number) => void;\n })\n | undefined;\n\nexport function useSessionScroll(options: SessionScrollOptions): SessionScrollState {\n const { total, enabled, windowSize, batchSize, resetKey } = options;\n const bottomThreshold = options.bottomThreshold ?? 64;\n const topThreshold = options.topThreshold ?? 600;\n\n const scrollRef = useRef<HTMLDivElement>(null);\n const contentRef = useRef<HTMLDivElement>(null);\n const pinnedRef = useRef(true);\n const anchorHeightRef = useRef<number | null>(null);\n const scrollBottomPendingRef = useRef(true);\n const loadingOlderRef = useRef(false);\n\n const [visibleCount, setVisibleCount] = useState(() => Math.min(windowSize, total));\n const effectiveCount = enabled ? visibleCount : total;\n const startIndex = Math.max(0, total - effectiveCount);\n const hasMore = enabled && startIndex > 0;\n const hasMoreRef = useRef(hasMore);\n hasMoreRef.current = hasMore;\n\n const scrollToBottom = useCallback(() => {\n const el = scrollRef.current;\n if (el) el.scrollTop = el.scrollHeight;\n }, []);\n\n // Prepend an older batch, latching until the layout effect settles the prepend so\n // rapid scroll events don't stack multiple batches at once.\n const growOlder = useCallback(() => {\n if (loadingOlderRef.current || !hasMoreRef.current) return;\n loadingOlderRef.current = true;\n const el = scrollRef.current;\n anchorHeightRef.current = el ? el.scrollHeight : null;\n setVisibleCount((count) => nextVisibleCount(count, batchSize, total));\n }, [batchSize, total]);\n\n const growOlderRef = useRef(growOlder);\n growOlderRef.current = growOlder;\n\n // A new session (resetKey change) snaps back to the newest screenful and re-pins.\n useLayoutEffect(() => {\n if (!enabled) return;\n setVisibleCount(Math.min(windowSize, total));\n pinnedRef.current = true;\n loadingOlderRef.current = false;\n scrollBottomPendingRef.current = true;\n }, [enabled, resetKey, windowSize, total]);\n\n // After each commit, either snap to bottom (pending pin) or preserve the reader's\n // position when older rows were prepended (anchor), then release the load latch.\n useLayoutEffect(() => {\n const el = scrollRef.current;\n if (!enabled || !el) return;\n if (scrollBottomPendingRef.current) {\n scrollBottomPendingRef.current = false;\n anchorHeightRef.current = null;\n el.scrollTop = el.scrollHeight;\n } else if (anchorHeightRef.current != null) {\n el.scrollTop += el.scrollHeight - anchorHeightRef.current;\n anchorHeightRef.current = null;\n }\n loadingOlderRef.current = false;\n }, [enabled, visibleCount]);\n\n // Track pinned-to-bottom, and load older rows as the reader nears the top.\n useEffect(() => {\n const el = scrollRef.current;\n if (!enabled || !el) return;\n const onScroll = () => {\n pinnedRef.current = isPinnedToBottom(el, bottomThreshold);\n if (hasMoreRef.current && isNearTop(el.scrollTop, topThreshold)) growOlderRef.current();\n };\n el.addEventListener(\"scroll\", onScroll, { passive: true });\n return () => el.removeEventListener(\"scroll\", onScroll);\n }, [enabled, bottomThreshold, topThreshold]);\n\n // Keep the newest row in view as rows grow (shiki highlighting settles after paint).\n useEffect(() => {\n const content = contentRef.current;\n if (!enabled || !content || typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(() => {\n if (pinnedRef.current) scrollToBottom();\n });\n observer.observe(content);\n return () => observer.disconnect();\n }, [enabled, scrollToBottom]);\n\n // Prefetch one batch while idle so the first scroll up is instant.\n useEffect(() => {\n if (!enabled || !hasMore) return;\n const win = idleWindow();\n const request = win?.requestIdleCallback ?? ((cb: () => void) => window.setTimeout(cb, 200));\n const cancel = win?.cancelIdleCallback ?? window.clearTimeout;\n const handle = request(() => growOlderRef.current());\n return () => cancel(handle);\n }, [enabled, resetKey, hasMore]);\n\n return { scrollRef, contentRef, startIndex, hasMore };\n}\n"],"names":["useRef","useState","useCallback","useLayoutEffect","useEffect"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"use-session-scroll.cjs","sources":["../../../src/data/ai/use-session-scroll.ts"],"sourcesContent":["import { useCallback, useEffect, useLayoutEffect, useRef, useState, type RefObject } from \"react\";\n\n// Progressive windowing for the SessionViewer log. A recorded session runs to\n// thousands of rows (many with syntax-highlighted code blocks), so rendering the\n// whole transcript blocks first paint. Instead we render the *newest* screenful,\n// keep the view pinned to the bottom (most recent activity), and backfill older\n// rows as the reader scrolls up — the classic reverse-infinite-scroll of a chat\n// log. The pure helpers below hold the windowing math; the hook wires the DOM\n// listeners that drive it. Load-more is driven off scroll position rather than an\n// IntersectionObserver so it stays reliable in backgrounded/hidden tabs (where the\n// browser pauses observer callbacks tied to the render loop).\n\n/** The last `visibleCount` of `items`, plus where the window starts and whether\n * older items remain above it. */\nexport function windowSlice<T>(\n items: readonly T[],\n visibleCount: number,\n): { items: T[]; startIndex: number; hasMore: boolean } {\n const clamped = Math.max(0, Math.min(visibleCount, items.length));\n const startIndex = items.length - clamped;\n return { items: items.slice(startIndex), startIndex, hasMore: startIndex > 0 };\n}\n\n/** Grow the window by `batchSize`, never past `total`. */\nexport function nextVisibleCount(current: number, batchSize: number, total: number): number {\n return Math.min(current + Math.max(1, batchSize), total);\n}\n\n/** True when the scroll position sits within `threshold` px of the bottom. */\nexport function isPinnedToBottom(\n metrics: { scrollTop: number; scrollHeight: number; clientHeight: number },\n threshold: number,\n): boolean {\n return metrics.scrollHeight - metrics.scrollTop - metrics.clientHeight <= threshold;\n}\n\n/** True when the scroll position sits within `threshold` px of the top. */\nexport function isNearTop(scrollTop: number, threshold: number): boolean {\n return scrollTop <= threshold;\n}\n\nexport interface SessionScrollOptions {\n /** Number of filtered events available to render. */\n total: number;\n /** Turns the whole mechanism on; when false the hook renders every event. */\n enabled: boolean;\n /** Rows rendered on first paint (and after a session change). */\n windowSize: number;\n /** Rows added each time older content is loaded. */\n batchSize: number;\n /** Changing this resets the window and re-pins to the bottom — pass a value\n * derived from the session identity, not the filter state. */\n resetKey: string;\n /** Distance (px) from the bottom still counted as \"pinned\". */\n bottomThreshold?: number;\n /** Distance (px) from the top at which older rows start loading. */\n topThreshold?: number;\n}\n\nexport interface SessionScrollState {\n scrollRef: RefObject<HTMLDivElement | null>;\n contentRef: RefObject<HTMLDivElement | null>;\n startIndex: number;\n hasMore: boolean;\n}\n\nconst idleWindow = () =>\n (typeof window === \"undefined\" ? undefined : window) as\n | (Window & {\n requestIdleCallback?: (cb: () => void) => number;\n cancelIdleCallback?: (handle: number) => void;\n })\n | undefined;\n\nexport function useSessionScroll(options: SessionScrollOptions): SessionScrollState {\n const { total, enabled, windowSize, batchSize, resetKey } = options;\n const bottomThreshold = options.bottomThreshold ?? 64;\n const topThreshold = options.topThreshold ?? 600;\n\n const scrollRef = useRef<HTMLDivElement>(null);\n const contentRef = useRef<HTMLDivElement>(null);\n const pinnedRef = useRef(true);\n const anchorHeightRef = useRef<number | null>(null);\n const scrollBottomPendingRef = useRef(true);\n const loadingOlderRef = useRef(false);\n\n const [visibleCount, setVisibleCount] = useState(() => Math.min(windowSize, total));\n const effectiveCount = enabled ? visibleCount : total;\n const startIndex = Math.max(0, total - effectiveCount);\n const hasMore = enabled && startIndex > 0;\n const hasMoreRef = useRef(hasMore);\n hasMoreRef.current = hasMore;\n\n const scrollToBottom = useCallback(() => {\n const el = scrollRef.current;\n if (el) el.scrollTop = el.scrollHeight;\n }, []);\n\n // Prepend an older batch, latching until the layout effect settles the prepend so\n // rapid scroll events don't stack multiple batches at once.\n const growOlder = useCallback(() => {\n if (loadingOlderRef.current || !hasMoreRef.current) return;\n loadingOlderRef.current = true;\n const el = scrollRef.current;\n anchorHeightRef.current = el ? el.scrollHeight : null;\n setVisibleCount((count) => nextVisibleCount(count, batchSize, total));\n }, [batchSize, total]);\n\n const growOlderRef = useRef(growOlder);\n growOlderRef.current = growOlder;\n\n // A new session (resetKey change) snaps back to the newest screenful and re-pins.\n useLayoutEffect(() => {\n if (!enabled) return;\n setVisibleCount(Math.min(windowSize, total));\n pinnedRef.current = true;\n loadingOlderRef.current = false;\n scrollBottomPendingRef.current = true;\n }, [enabled, resetKey, windowSize, total]);\n\n // After each commit, either snap to bottom (pending pin) or preserve the reader's\n // position when older rows were prepended (anchor), then release the load latch.\n useLayoutEffect(() => {\n const el = scrollRef.current;\n if (!enabled || !el) return;\n if (scrollBottomPendingRef.current) {\n scrollBottomPendingRef.current = false;\n anchorHeightRef.current = null;\n el.scrollTop = el.scrollHeight;\n } else if (anchorHeightRef.current != null) {\n el.scrollTop += el.scrollHeight - anchorHeightRef.current;\n anchorHeightRef.current = null;\n }\n loadingOlderRef.current = false;\n }, [enabled, visibleCount]);\n\n // Track pinned-to-bottom, and load older rows as the reader nears the top.\n useEffect(() => {\n const el = scrollRef.current;\n if (!enabled || !el) return;\n const onScroll = () => {\n pinnedRef.current = isPinnedToBottom(el, bottomThreshold);\n if (hasMoreRef.current && isNearTop(el.scrollTop, topThreshold)) growOlderRef.current();\n };\n el.addEventListener(\"scroll\", onScroll, { passive: true });\n return () => el.removeEventListener(\"scroll\", onScroll);\n }, [enabled, bottomThreshold, topThreshold]);\n\n // Keep the newest row in view as rows grow (shiki highlighting settles after paint).\n useEffect(() => {\n const content = contentRef.current;\n if (!enabled || !content || typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(() => {\n if (pinnedRef.current) scrollToBottom();\n });\n observer.observe(content);\n return () => observer.disconnect();\n }, [enabled, scrollToBottom]);\n\n // Prefetch one batch while idle so the first scroll up is instant.\n useEffect(() => {\n if (!enabled || !hasMore) return;\n const win = idleWindow();\n const request = win?.requestIdleCallback ?? ((cb: () => void) => window.setTimeout(cb, 200));\n const cancel = win?.cancelIdleCallback ?? window.clearTimeout;\n const handle = request(() => growOlderRef.current());\n return () => cancel(handle);\n }, [enabled, resetKey, hasMore]);\n\n return { scrollRef, contentRef, startIndex, hasMore };\n}\n"],"names":["useRef","useState","useCallback","useLayoutEffect","useEffect"],"mappings":"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"}
|
|
@@ -34,8 +34,8 @@ export interface SessionScrollOptions {
|
|
|
34
34
|
topThreshold?: number;
|
|
35
35
|
}
|
|
36
36
|
export interface SessionScrollState {
|
|
37
|
-
scrollRef: RefObject<HTMLDivElement>;
|
|
38
|
-
contentRef: RefObject<HTMLDivElement>;
|
|
37
|
+
scrollRef: RefObject<HTMLDivElement | null>;
|
|
38
|
+
contentRef: RefObject<HTMLDivElement | null>;
|
|
39
39
|
startIndex: number;
|
|
40
40
|
hasMore: boolean;
|
|
41
41
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-session-scroll.d.ts","sourceRoot":"","sources":["../../../src/data/ai/use-session-scroll.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6D,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAYlG;mCACmC;AACnC,wBAAgB,WAAW,CAAC,CAAC,EAC3B,KAAK,EAAE,SAAS,CAAC,EAAE,EACnB,YAAY,EAAE,MAAM,GACnB;IAAE,KAAK,EAAE,CAAC,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAItD;AAED,0DAA0D;AAC1D,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1F;AAED,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,EAC1E,SAAS,EAAE,MAAM,GAChB,OAAO,CAET;AAED,2EAA2E;AAC3E,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAEvE;AAED,MAAM,WAAW,oBAAoB;IACnC,qDAAqD;IACrD,KAAK,EAAE,MAAM,CAAC;IACd,6EAA6E;IAC7E,OAAO,EAAE,OAAO,CAAC;IACjB,iEAAiE;IACjE,UAAU,EAAE,MAAM,CAAC;IACnB,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;IAClB;mEAC+D;IAC/D,QAAQ,EAAE,MAAM,CAAC;IACjB,+DAA+D;IAC/D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oEAAoE;IACpE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,SAAS,CAAC,cAAc,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"use-session-scroll.d.ts","sourceRoot":"","sources":["../../../src/data/ai/use-session-scroll.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6D,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAYlG;mCACmC;AACnC,wBAAgB,WAAW,CAAC,CAAC,EAC3B,KAAK,EAAE,SAAS,CAAC,EAAE,EACnB,YAAY,EAAE,MAAM,GACnB;IAAE,KAAK,EAAE,CAAC,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAItD;AAED,0DAA0D;AAC1D,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1F;AAED,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,EAC1E,SAAS,EAAE,MAAM,GAChB,OAAO,CAET;AAED,2EAA2E;AAC3E,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAEvE;AAED,MAAM,WAAW,oBAAoB;IACnC,qDAAqD;IACrD,KAAK,EAAE,MAAM,CAAC;IACd,6EAA6E;IAC7E,OAAO,EAAE,OAAO,CAAC;IACjB,iEAAiE;IACjE,UAAU,EAAE,MAAM,CAAC;IACnB,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;IAClB;mEAC+D;IAC/D,QAAQ,EAAE,MAAM,CAAC;IACjB,+DAA+D;IAC/D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oEAAoE;IACpE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC5C,UAAU,EAAE,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;CAClB;AAUD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,oBAAoB,GAAG,kBAAkB,CAgGlF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-session-scroll.js","sources":["../../../src/data/ai/use-session-scroll.ts"],"sourcesContent":["import { useCallback, useEffect, useLayoutEffect, useRef, useState, type RefObject } from \"react\";\n\n// Progressive windowing for the SessionViewer log. A recorded session runs to\n// thousands of rows (many with syntax-highlighted code blocks), so rendering the\n// whole transcript blocks first paint. Instead we render the *newest* screenful,\n// keep the view pinned to the bottom (most recent activity), and backfill older\n// rows as the reader scrolls up — the classic reverse-infinite-scroll of a chat\n// log. The pure helpers below hold the windowing math; the hook wires the DOM\n// listeners that drive it. Load-more is driven off scroll position rather than an\n// IntersectionObserver so it stays reliable in backgrounded/hidden tabs (where the\n// browser pauses observer callbacks tied to the render loop).\n\n/** The last `visibleCount` of `items`, plus where the window starts and whether\n * older items remain above it. */\nexport function windowSlice<T>(\n items: readonly T[],\n visibleCount: number,\n): { items: T[]; startIndex: number; hasMore: boolean } {\n const clamped = Math.max(0, Math.min(visibleCount, items.length));\n const startIndex = items.length - clamped;\n return { items: items.slice(startIndex), startIndex, hasMore: startIndex > 0 };\n}\n\n/** Grow the window by `batchSize`, never past `total`. */\nexport function nextVisibleCount(current: number, batchSize: number, total: number): number {\n return Math.min(current + Math.max(1, batchSize), total);\n}\n\n/** True when the scroll position sits within `threshold` px of the bottom. */\nexport function isPinnedToBottom(\n metrics: { scrollTop: number; scrollHeight: number; clientHeight: number },\n threshold: number,\n): boolean {\n return metrics.scrollHeight - metrics.scrollTop - metrics.clientHeight <= threshold;\n}\n\n/** True when the scroll position sits within `threshold` px of the top. */\nexport function isNearTop(scrollTop: number, threshold: number): boolean {\n return scrollTop <= threshold;\n}\n\nexport interface SessionScrollOptions {\n /** Number of filtered events available to render. */\n total: number;\n /** Turns the whole mechanism on; when false the hook renders every event. */\n enabled: boolean;\n /** Rows rendered on first paint (and after a session change). */\n windowSize: number;\n /** Rows added each time older content is loaded. */\n batchSize: number;\n /** Changing this resets the window and re-pins to the bottom — pass a value\n * derived from the session identity, not the filter state. */\n resetKey: string;\n /** Distance (px) from the bottom still counted as \"pinned\". */\n bottomThreshold?: number;\n /** Distance (px) from the top at which older rows start loading. */\n topThreshold?: number;\n}\n\nexport interface SessionScrollState {\n scrollRef: RefObject<HTMLDivElement>;\n contentRef: RefObject<HTMLDivElement>;\n startIndex: number;\n hasMore: boolean;\n}\n\nconst idleWindow = () =>\n (typeof window === \"undefined\" ? undefined : window) as\n | (Window & {\n requestIdleCallback?: (cb: () => void) => number;\n cancelIdleCallback?: (handle: number) => void;\n })\n | undefined;\n\nexport function useSessionScroll(options: SessionScrollOptions): SessionScrollState {\n const { total, enabled, windowSize, batchSize, resetKey } = options;\n const bottomThreshold = options.bottomThreshold ?? 64;\n const topThreshold = options.topThreshold ?? 600;\n\n const scrollRef = useRef<HTMLDivElement>(null);\n const contentRef = useRef<HTMLDivElement>(null);\n const pinnedRef = useRef(true);\n const anchorHeightRef = useRef<number | null>(null);\n const scrollBottomPendingRef = useRef(true);\n const loadingOlderRef = useRef(false);\n\n const [visibleCount, setVisibleCount] = useState(() => Math.min(windowSize, total));\n const effectiveCount = enabled ? visibleCount : total;\n const startIndex = Math.max(0, total - effectiveCount);\n const hasMore = enabled && startIndex > 0;\n const hasMoreRef = useRef(hasMore);\n hasMoreRef.current = hasMore;\n\n const scrollToBottom = useCallback(() => {\n const el = scrollRef.current;\n if (el) el.scrollTop = el.scrollHeight;\n }, []);\n\n // Prepend an older batch, latching until the layout effect settles the prepend so\n // rapid scroll events don't stack multiple batches at once.\n const growOlder = useCallback(() => {\n if (loadingOlderRef.current || !hasMoreRef.current) return;\n loadingOlderRef.current = true;\n const el = scrollRef.current;\n anchorHeightRef.current = el ? el.scrollHeight : null;\n setVisibleCount((count) => nextVisibleCount(count, batchSize, total));\n }, [batchSize, total]);\n\n const growOlderRef = useRef(growOlder);\n growOlderRef.current = growOlder;\n\n // A new session (resetKey change) snaps back to the newest screenful and re-pins.\n useLayoutEffect(() => {\n if (!enabled) return;\n setVisibleCount(Math.min(windowSize, total));\n pinnedRef.current = true;\n loadingOlderRef.current = false;\n scrollBottomPendingRef.current = true;\n }, [enabled, resetKey, windowSize, total]);\n\n // After each commit, either snap to bottom (pending pin) or preserve the reader's\n // position when older rows were prepended (anchor), then release the load latch.\n useLayoutEffect(() => {\n const el = scrollRef.current;\n if (!enabled || !el) return;\n if (scrollBottomPendingRef.current) {\n scrollBottomPendingRef.current = false;\n anchorHeightRef.current = null;\n el.scrollTop = el.scrollHeight;\n } else if (anchorHeightRef.current != null) {\n el.scrollTop += el.scrollHeight - anchorHeightRef.current;\n anchorHeightRef.current = null;\n }\n loadingOlderRef.current = false;\n }, [enabled, visibleCount]);\n\n // Track pinned-to-bottom, and load older rows as the reader nears the top.\n useEffect(() => {\n const el = scrollRef.current;\n if (!enabled || !el) return;\n const onScroll = () => {\n pinnedRef.current = isPinnedToBottom(el, bottomThreshold);\n if (hasMoreRef.current && isNearTop(el.scrollTop, topThreshold)) growOlderRef.current();\n };\n el.addEventListener(\"scroll\", onScroll, { passive: true });\n return () => el.removeEventListener(\"scroll\", onScroll);\n }, [enabled, bottomThreshold, topThreshold]);\n\n // Keep the newest row in view as rows grow (shiki highlighting settles after paint).\n useEffect(() => {\n const content = contentRef.current;\n if (!enabled || !content || typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(() => {\n if (pinnedRef.current) scrollToBottom();\n });\n observer.observe(content);\n return () => observer.disconnect();\n }, [enabled, scrollToBottom]);\n\n // Prefetch one batch while idle so the first scroll up is instant.\n useEffect(() => {\n if (!enabled || !hasMore) return;\n const win = idleWindow();\n const request = win?.requestIdleCallback ?? ((cb: () => void) => window.setTimeout(cb, 200));\n const cancel = win?.cancelIdleCallback ?? window.clearTimeout;\n const handle = request(() => growOlderRef.current());\n return () => cancel(handle);\n }, [enabled, resetKey, hasMore]);\n\n return { scrollRef, contentRef, startIndex, hasMore };\n}\n"],"names":[],"mappings":";AAwBO,SAAS,iBAAiB,SAAiB,WAAmB,OAAuB;AAC1F,SAAO,KAAK,IAAI,UAAU,KAAK,IAAI,GAAG,SAAS,GAAG,KAAK;AACzD;AAGO,SAAS,iBACd,SACA,WACS;AACT,SAAO,QAAQ,eAAe,QAAQ,YAAY,QAAQ,gBAAgB;AAC5E;AAGO,SAAS,UAAU,WAAmB,WAA4B;AACvE,SAAO,aAAa;AACtB;AA2BA,MAAM,aAAa,MAChB,OAAO,WAAW,cAAc,SAAY;AAOxC,SAAS,iBAAiB,SAAmD;AAClF,QAAM,EAAE,OAAO,SAAS,YAAY,WAAW,aAAa;AAC5D,QAAM,kBAAkB,QAAQ,mBAAmB;AACnD,QAAM,eAAe,QAAQ,gBAAgB;AAE7C,QAAM,YAAY,OAAuB,IAAI;AAC7C,QAAM,aAAa,OAAuB,IAAI;AAC9C,QAAM,YAAY,OAAO,IAAI;AAC7B,QAAM,kBAAkB,OAAsB,IAAI;AAClD,QAAM,yBAAyB,OAAO,IAAI;AAC1C,QAAM,kBAAkB,OAAO,KAAK;AAEpC,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,MAAM,KAAK,IAAI,YAAY,KAAK,CAAC;AAClF,QAAM,iBAAiB,UAAU,eAAe;AAChD,QAAM,aAAa,KAAK,IAAI,GAAG,QAAQ,cAAc;AACrD,QAAM,UAAU,WAAW,aAAa;AACxC,QAAM,aAAa,OAAO,OAAO;AACjC,aAAW,UAAU;AAErB,QAAM,iBAAiB,YAAY,MAAM;AACvC,UAAM,KAAK,UAAU;AACrB,QAAI,GAAI,IAAG,YAAY,GAAG;AAAA,EAC5B,GAAG,CAAA,CAAE;AAIL,QAAM,YAAY,YAAY,MAAM;AAClC,QAAI,gBAAgB,WAAW,CAAC,WAAW,QAAS;AACpD,oBAAgB,UAAU;AAC1B,UAAM,KAAK,UAAU;AACrB,oBAAgB,UAAU,KAAK,GAAG,eAAe;AACjD,oBAAgB,CAAC,UAAU,iBAAiB,OAAO,WAAW,KAAK,CAAC;AAAA,EACtE,GAAG,CAAC,WAAW,KAAK,CAAC;AAErB,QAAM,eAAe,OAAO,SAAS;AACrC,eAAa,UAAU;AAGvB,kBAAgB,MAAM;AACpB,QAAI,CAAC,QAAS;AACd,oBAAgB,KAAK,IAAI,YAAY,KAAK,CAAC;AAC3C,cAAU,UAAU;AACpB,oBAAgB,UAAU;AAC1B,2BAAuB,UAAU;AAAA,EACnC,GAAG,CAAC,SAAS,UAAU,YAAY,KAAK,CAAC;AAIzC,kBAAgB,MAAM;AACpB,UAAM,KAAK,UAAU;AACrB,QAAI,CAAC,WAAW,CAAC,GAAI;AACrB,QAAI,uBAAuB,SAAS;AAClC,6BAAuB,UAAU;AACjC,sBAAgB,UAAU;AAC1B,SAAG,YAAY,GAAG;AAAA,IACpB,WAAW,gBAAgB,WAAW,MAAM;AAC1C,SAAG,aAAa,GAAG,eAAe,gBAAgB;AAClD,sBAAgB,UAAU;AAAA,IAC5B;AACA,oBAAgB,UAAU;AAAA,EAC5B,GAAG,CAAC,SAAS,YAAY,CAAC;AAG1B,YAAU,MAAM;AACd,UAAM,KAAK,UAAU;AACrB,QAAI,CAAC,WAAW,CAAC,GAAI;AACrB,UAAM,WAAW,MAAM;AACrB,gBAAU,UAAU,iBAAiB,IAAI,eAAe;AACxD,UAAI,WAAW,WAAW,UAAU,GAAG,WAAW,YAAY,gBAAgB,QAAA;AAAA,IAChF;AACA,OAAG,iBAAiB,UAAU,UAAU,EAAE,SAAS,MAAM;AACzD,WAAO,MAAM,GAAG,oBAAoB,UAAU,QAAQ;AAAA,EACxD,GAAG,CAAC,SAAS,iBAAiB,YAAY,CAAC;AAG3C,YAAU,MAAM;AACd,UAAM,UAAU,WAAW;AAC3B,QAAI,CAAC,WAAW,CAAC,WAAW,OAAO,mBAAmB,YAAa;AACnE,UAAM,WAAW,IAAI,eAAe,MAAM;AACxC,UAAI,UAAU,QAAS,gBAAA;AAAA,IACzB,CAAC;AACD,aAAS,QAAQ,OAAO;AACxB,WAAO,MAAM,SAAS,WAAA;AAAA,EACxB,GAAG,CAAC,SAAS,cAAc,CAAC;AAG5B,YAAU,MAAM;AACd,QAAI,CAAC,WAAW,CAAC,QAAS;AAC1B,UAAM,MAAM,WAAA;AACZ,UAAM,WAAU,2BAAK,yBAAwB,CAAC,OAAmB,OAAO,WAAW,IAAI,GAAG;AAC1F,UAAM,UAAS,2BAAK,uBAAsB,OAAO;AACjD,UAAM,SAAS,QAAQ,MAAM,aAAa,SAAS;AACnD,WAAO,MAAM,OAAO,MAAM;AAAA,EAC5B,GAAG,CAAC,SAAS,UAAU,OAAO,CAAC;AAE/B,SAAO,EAAE,WAAW,YAAY,YAAY,QAAA;AAC9C;"}
|
|
1
|
+
{"version":3,"file":"use-session-scroll.js","sources":["../../../src/data/ai/use-session-scroll.ts"],"sourcesContent":["import { useCallback, useEffect, useLayoutEffect, useRef, useState, type RefObject } from \"react\";\n\n// Progressive windowing for the SessionViewer log. A recorded session runs to\n// thousands of rows (many with syntax-highlighted code blocks), so rendering the\n// whole transcript blocks first paint. Instead we render the *newest* screenful,\n// keep the view pinned to the bottom (most recent activity), and backfill older\n// rows as the reader scrolls up — the classic reverse-infinite-scroll of a chat\n// log. The pure helpers below hold the windowing math; the hook wires the DOM\n// listeners that drive it. Load-more is driven off scroll position rather than an\n// IntersectionObserver so it stays reliable in backgrounded/hidden tabs (where the\n// browser pauses observer callbacks tied to the render loop).\n\n/** The last `visibleCount` of `items`, plus where the window starts and whether\n * older items remain above it. */\nexport function windowSlice<T>(\n items: readonly T[],\n visibleCount: number,\n): { items: T[]; startIndex: number; hasMore: boolean } {\n const clamped = Math.max(0, Math.min(visibleCount, items.length));\n const startIndex = items.length - clamped;\n return { items: items.slice(startIndex), startIndex, hasMore: startIndex > 0 };\n}\n\n/** Grow the window by `batchSize`, never past `total`. */\nexport function nextVisibleCount(current: number, batchSize: number, total: number): number {\n return Math.min(current + Math.max(1, batchSize), total);\n}\n\n/** True when the scroll position sits within `threshold` px of the bottom. */\nexport function isPinnedToBottom(\n metrics: { scrollTop: number; scrollHeight: number; clientHeight: number },\n threshold: number,\n): boolean {\n return metrics.scrollHeight - metrics.scrollTop - metrics.clientHeight <= threshold;\n}\n\n/** True when the scroll position sits within `threshold` px of the top. */\nexport function isNearTop(scrollTop: number, threshold: number): boolean {\n return scrollTop <= threshold;\n}\n\nexport interface SessionScrollOptions {\n /** Number of filtered events available to render. */\n total: number;\n /** Turns the whole mechanism on; when false the hook renders every event. */\n enabled: boolean;\n /** Rows rendered on first paint (and after a session change). */\n windowSize: number;\n /** Rows added each time older content is loaded. */\n batchSize: number;\n /** Changing this resets the window and re-pins to the bottom — pass a value\n * derived from the session identity, not the filter state. */\n resetKey: string;\n /** Distance (px) from the bottom still counted as \"pinned\". */\n bottomThreshold?: number;\n /** Distance (px) from the top at which older rows start loading. */\n topThreshold?: number;\n}\n\nexport interface SessionScrollState {\n scrollRef: RefObject<HTMLDivElement | null>;\n contentRef: RefObject<HTMLDivElement | null>;\n startIndex: number;\n hasMore: boolean;\n}\n\nconst idleWindow = () =>\n (typeof window === \"undefined\" ? undefined : window) as\n | (Window & {\n requestIdleCallback?: (cb: () => void) => number;\n cancelIdleCallback?: (handle: number) => void;\n })\n | undefined;\n\nexport function useSessionScroll(options: SessionScrollOptions): SessionScrollState {\n const { total, enabled, windowSize, batchSize, resetKey } = options;\n const bottomThreshold = options.bottomThreshold ?? 64;\n const topThreshold = options.topThreshold ?? 600;\n\n const scrollRef = useRef<HTMLDivElement>(null);\n const contentRef = useRef<HTMLDivElement>(null);\n const pinnedRef = useRef(true);\n const anchorHeightRef = useRef<number | null>(null);\n const scrollBottomPendingRef = useRef(true);\n const loadingOlderRef = useRef(false);\n\n const [visibleCount, setVisibleCount] = useState(() => Math.min(windowSize, total));\n const effectiveCount = enabled ? visibleCount : total;\n const startIndex = Math.max(0, total - effectiveCount);\n const hasMore = enabled && startIndex > 0;\n const hasMoreRef = useRef(hasMore);\n hasMoreRef.current = hasMore;\n\n const scrollToBottom = useCallback(() => {\n const el = scrollRef.current;\n if (el) el.scrollTop = el.scrollHeight;\n }, []);\n\n // Prepend an older batch, latching until the layout effect settles the prepend so\n // rapid scroll events don't stack multiple batches at once.\n const growOlder = useCallback(() => {\n if (loadingOlderRef.current || !hasMoreRef.current) return;\n loadingOlderRef.current = true;\n const el = scrollRef.current;\n anchorHeightRef.current = el ? el.scrollHeight : null;\n setVisibleCount((count) => nextVisibleCount(count, batchSize, total));\n }, [batchSize, total]);\n\n const growOlderRef = useRef(growOlder);\n growOlderRef.current = growOlder;\n\n // A new session (resetKey change) snaps back to the newest screenful and re-pins.\n useLayoutEffect(() => {\n if (!enabled) return;\n setVisibleCount(Math.min(windowSize, total));\n pinnedRef.current = true;\n loadingOlderRef.current = false;\n scrollBottomPendingRef.current = true;\n }, [enabled, resetKey, windowSize, total]);\n\n // After each commit, either snap to bottom (pending pin) or preserve the reader's\n // position when older rows were prepended (anchor), then release the load latch.\n useLayoutEffect(() => {\n const el = scrollRef.current;\n if (!enabled || !el) return;\n if (scrollBottomPendingRef.current) {\n scrollBottomPendingRef.current = false;\n anchorHeightRef.current = null;\n el.scrollTop = el.scrollHeight;\n } else if (anchorHeightRef.current != null) {\n el.scrollTop += el.scrollHeight - anchorHeightRef.current;\n anchorHeightRef.current = null;\n }\n loadingOlderRef.current = false;\n }, [enabled, visibleCount]);\n\n // Track pinned-to-bottom, and load older rows as the reader nears the top.\n useEffect(() => {\n const el = scrollRef.current;\n if (!enabled || !el) return;\n const onScroll = () => {\n pinnedRef.current = isPinnedToBottom(el, bottomThreshold);\n if (hasMoreRef.current && isNearTop(el.scrollTop, topThreshold)) growOlderRef.current();\n };\n el.addEventListener(\"scroll\", onScroll, { passive: true });\n return () => el.removeEventListener(\"scroll\", onScroll);\n }, [enabled, bottomThreshold, topThreshold]);\n\n // Keep the newest row in view as rows grow (shiki highlighting settles after paint).\n useEffect(() => {\n const content = contentRef.current;\n if (!enabled || !content || typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(() => {\n if (pinnedRef.current) scrollToBottom();\n });\n observer.observe(content);\n return () => observer.disconnect();\n }, [enabled, scrollToBottom]);\n\n // Prefetch one batch while idle so the first scroll up is instant.\n useEffect(() => {\n if (!enabled || !hasMore) return;\n const win = idleWindow();\n const request = win?.requestIdleCallback ?? ((cb: () => void) => window.setTimeout(cb, 200));\n const cancel = win?.cancelIdleCallback ?? window.clearTimeout;\n const handle = request(() => growOlderRef.current());\n return () => cancel(handle);\n }, [enabled, resetKey, hasMore]);\n\n return { scrollRef, contentRef, startIndex, hasMore };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare const badgeVariants: (props?: ({
|
|
2
|
-
tone?: "
|
|
2
|
+
tone?: "neutral" | "info" | "warning" | "success" | "danger" | null | undefined;
|
|
3
3
|
variant?: "solid" | "outline" | "soft" | null | undefined;
|
|
4
4
|
size?: "xs" | "sm" | "md" | "lg" | "xxs" | null | undefined;
|
|
5
5
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
@@ -9,6 +9,7 @@ const RuntimeBarSegments = require("./RuntimeBarSegments.cjs");
|
|
|
9
9
|
const availability = require("./availability.cjs");
|
|
10
10
|
const modelCapabilities = require("./model-capabilities.cjs");
|
|
11
11
|
const runtimeMode = require("./runtime-mode.cjs");
|
|
12
|
+
const runtimeFamily = require("../../lib/runtime-family.cjs");
|
|
12
13
|
function RuntimeBar({
|
|
13
14
|
value,
|
|
14
15
|
onChange,
|
|
@@ -26,7 +27,7 @@ function RuntimeBar({
|
|
|
26
27
|
}) {
|
|
27
28
|
var _a;
|
|
28
29
|
const [preferredFamily, setPreferredFamily] = react.useState();
|
|
29
|
-
const specMode =
|
|
30
|
+
const specMode = runtimeFamily.runtimeModeFromModel(value.model) || ((_a = value.mode) == null ? void 0 : _a.trim()) || (effectiveMode == null ? void 0 : effectiveMode.trim());
|
|
30
31
|
const selection = runtimeMode.selectionForRuntime(
|
|
31
32
|
families,
|
|
32
33
|
specMode,
|
|
@@ -39,7 +40,7 @@ function RuntimeBar({
|
|
|
39
40
|
const modelOptions = runtimeMode.modelsForFamily(models, family, specMode);
|
|
40
41
|
const resolvedModel = RuntimeBar_model.runtimeModelForValue(models, value, availability.isSelectableModel);
|
|
41
42
|
const selectedModelUnavailable = Boolean(
|
|
42
|
-
(value.id || value.model) && RuntimeBar_model.runtimeModelForValue(models, value, (entry) => !availability.isSelectableModel(entry))
|
|
43
|
+
!resolvedModel && (value.id || value.model) && RuntimeBar_model.runtimeModelForValue(models, value, (entry) => !availability.isSelectableModel(entry))
|
|
43
44
|
);
|
|
44
45
|
const supportedEfforts = modelCapabilities.effortOptionsForModel(
|
|
45
46
|
resolvedModel,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuntimeBar.cjs","sources":["../../../src/data/runtime/RuntimeBar.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { DEFAULT_REASONING_EFFORTS } from \"../chat/effort-icons\";\nimport type { ChatModel, ChatModelRuntime } from \"../chat/types\";\nimport { applyRuntimeMode, runtimeModelForValue } from \"./RuntimeBar.model\";\nimport { RuntimeBarCombo } from \"./RuntimeBarCombo\";\nimport { RuntimeBarSegments } from \"./RuntimeBarSegments\";\nimport { isSelectableModel } from \"./availability\";\nimport {\n effortOptionsForModel,\n reconcileModelCapabilities,\n} from \"./model-capabilities\";\nimport {\n SPEC_RUNTIME_FAMILIES,\n familyById,\n firstMode,\n modelsForFamily,\n selectionForRuntime,\n runtimeModeFromModel,\n type SpecRuntimeFamily,\n} from \"./runtime-mode\";\n\nexport type RuntimeBarValue = ChatModelRuntime & {\n cliArgs?: Record<string, unknown>;\n};\n\nexport type RuntimeBarProps<T extends RuntimeBarValue = RuntimeBarValue> = {\n value: T;\n onChange: (value: T) => void;\n /** `segmented` uses field triggers; `combo` uses one direct-edit menu. */\n variant?: \"combo\" | \"segmented\";\n /** Model catalog. Only the selected family's models are listed; a family the\n * catalog does not describe is served by the segment's free-text entry. */\n models?: ChatModel[] | undefined;\n families?: SpecRuntimeFamily[] | undefined;\n /** Resolved mode shown when the editable value inherits it from another layer. */\n effectiveMode?: string | undefined;\n /** Resolved model used to identify the inherited provider family without persisting it. */\n effectiveModel?: string | undefined;\n /** Effort tiers offered when the catalog does not describe the model. */\n reasoningEfforts?: string[] | undefined;\n /** Locks model identity (family, mode, and model) while leaving effort editable. */\n locked?: boolean | undefined;\n /** Whether the selected runtime exposes a model argument. */\n showModel?: boolean | undefined;\n /** Whether the selected runtime exposes reasoning effort. */\n showEffort?: boolean | undefined;\n ariaLabel?: string | undefined;\n className?: string | undefined;\n};\n\n/** Self-describing runtime controls with segmented and combo presentations. */\nexport function RuntimeBar<T extends RuntimeBarValue>({\n value,\n onChange,\n variant = \"segmented\",\n models = [],\n families = SPEC_RUNTIME_FAMILIES,\n effectiveMode,\n effectiveModel,\n reasoningEfforts = DEFAULT_REASONING_EFFORTS,\n locked = false,\n showModel = true,\n showEffort = true,\n ariaLabel = \"Runtime\",\n className,\n}: RuntimeBarProps<T>) {\n const [preferredFamily, setPreferredFamily] = useState<string>();\n const specMode =\n runtimeModeFromModel(value.model) ||\n value.mode?.trim() ||\n effectiveMode?.trim();\n const selection = selectionForRuntime(\n families,\n specMode,\n value.model || effectiveModel,\n models,\n preferredFamily,\n );\n const family = familyById(families, selection.family);\n const mode =\n family.modes.find((entry) => entry.id === selection.mode) ??\n firstMode(family);\n const modelOptions = modelsForFamily(models, family, specMode);\n const resolvedModel = runtimeModelForValue(models, value, isSelectableModel);\n const selectedModelUnavailable = Boolean(\n (value.id || value.model) &&\n runtimeModelForValue(models, value, (entry) => !isSelectableModel(entry)),\n );\n const supportedEfforts = effortOptionsForModel(\n resolvedModel,\n reasoningEfforts,\n );\n\n const applyMode = (familyId: string, modeId: string) => {\n setPreferredFamily(familyId);\n const next = applyRuntimeMode(\n value,\n models,\n families,\n familyId,\n modeId,\n reasoningEfforts,\n );\n if (next !== value) onChange(next);\n };\n\n const applyCustomModel = (model: string) => {\n onChange(\n withOptionalRuntimeValue(withoutCatalogModel(value), \"model\", model),\n );\n };\n // A family's model catalog can serve several modes. Selecting a row must not\n // silently move the user away from the mode they chose.\n const applyModel = (model: ChatModel) => {\n const next = reconcileModelCapabilities(\n withoutCatalogModel(value),\n model,\n reasoningEfforts,\n { mode: mode.id },\n );\n onChange(next);\n };\n const clearModel = () => {\n onChange(withoutCatalogModel(value));\n };\n const applyEffort = (effort: string) =>\n onChange(withOptionalRuntimeValue(value, \"effort\", effort));\n\n if (variant === \"combo\") {\n return (\n <RuntimeBarCombo\n value={value}\n families={families}\n family={family}\n mode={mode}\n selectedMode={selection.mode}\n models={modelOptions}\n selectedModel={resolvedModel}\n selectedModelUnavailable={selectedModelUnavailable}\n supportedEfforts={supportedEfforts}\n locked={locked}\n showModel={showModel}\n showEffort={showEffort}\n ariaLabel={ariaLabel}\n className={className}\n onFamilyChange={(familyId) => applyMode(familyId, selection.mode)}\n onModeChange={(modeId) => applyMode(family.id, modeId)}\n onModelSelect={applyModel}\n onModelClear={clearModel}\n onEffortChange={applyEffort}\n />\n );\n }\n\n return (\n <RuntimeBarSegments\n value={value}\n models={models}\n modelOptions={modelOptions}\n resolvedModel={resolvedModel}\n selectedModelUnavailable={selectedModelUnavailable}\n families={families}\n family={family}\n mode={mode}\n selectedMode={selection.mode}\n reasoningEfforts={reasoningEfforts}\n supportedEfforts={supportedEfforts}\n locked={locked}\n showModel={showModel}\n showEffort={showEffort}\n ariaLabel={ariaLabel}\n className={className}\n onModeChange={applyMode}\n onCustomModel={applyCustomModel}\n onModelSelect={applyModel}\n onModelClear={clearModel}\n onEffortChange={applyEffort}\n />\n );\n}\n\nfunction withoutCatalogModel<T extends RuntimeBarValue>(value: T): T {\n return withOptionalRuntimeValue(\n withOptionalRuntimeValue(value, \"model\", undefined),\n \"id\",\n undefined,\n );\n}\n\nfunction withOptionalRuntimeValue<T extends RuntimeBarValue>(\n value: T,\n key: keyof RuntimeBarValue,\n next: unknown,\n): T {\n const updated = { ...value } as Record<string, unknown>;\n if (next === undefined || next === \"\") {\n delete updated[key];\n } else {\n updated[key] = next;\n }\n return updated as T;\n}\n"],"names":["SPEC_RUNTIME_FAMILIES","DEFAULT_REASONING_EFFORTS","useState","runtimeModeFromModel","selectionForRuntime","familyById","firstMode","modelsForFamily","runtimeModelForValue","isSelectableModel","effortOptionsForModel","applyRuntimeMode","reconcileModelCapabilities","jsx","RuntimeBarCombo","RuntimeBarSegments"],"mappings":"
|
|
1
|
+
{"version":3,"file":"RuntimeBar.cjs","sources":["../../../src/data/runtime/RuntimeBar.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { DEFAULT_REASONING_EFFORTS } from \"../chat/effort-icons\";\nimport type { ChatModel, ChatModelRuntime } from \"../chat/types\";\nimport { applyRuntimeMode, runtimeModelForValue } from \"./RuntimeBar.model\";\nimport { RuntimeBarCombo } from \"./RuntimeBarCombo\";\nimport { RuntimeBarSegments } from \"./RuntimeBarSegments\";\nimport { isSelectableModel } from \"./availability\";\nimport {\n effortOptionsForModel,\n reconcileModelCapabilities,\n} from \"./model-capabilities\";\nimport {\n SPEC_RUNTIME_FAMILIES,\n familyById,\n firstMode,\n modelsForFamily,\n selectionForRuntime,\n runtimeModeFromModel,\n type SpecRuntimeFamily,\n} from \"./runtime-mode\";\n\nexport type RuntimeBarValue = ChatModelRuntime & {\n cliArgs?: Record<string, unknown>;\n};\n\nexport type RuntimeBarProps<T extends RuntimeBarValue = RuntimeBarValue> = {\n value: T;\n onChange: (value: T) => void;\n /** `segmented` uses field triggers; `combo` uses one direct-edit menu. */\n variant?: \"combo\" | \"segmented\";\n /** Model catalog. Only the selected family's models are listed; a family the\n * catalog does not describe is served by the segment's free-text entry. */\n models?: ChatModel[] | undefined;\n families?: SpecRuntimeFamily[] | undefined;\n /** Resolved mode shown when the editable value inherits it from another layer. */\n effectiveMode?: string | undefined;\n /** Resolved model used to identify the inherited provider family without persisting it. */\n effectiveModel?: string | undefined;\n /** Effort tiers offered when the catalog does not describe the model. */\n reasoningEfforts?: string[] | undefined;\n /** Locks model identity (family, mode, and model) while leaving effort editable. */\n locked?: boolean | undefined;\n /** Whether the selected runtime exposes a model argument. */\n showModel?: boolean | undefined;\n /** Whether the selected runtime exposes reasoning effort. */\n showEffort?: boolean | undefined;\n ariaLabel?: string | undefined;\n className?: string | undefined;\n};\n\n/** Self-describing runtime controls with segmented and combo presentations. */\nexport function RuntimeBar<T extends RuntimeBarValue>({\n value,\n onChange,\n variant = \"segmented\",\n models = [],\n families = SPEC_RUNTIME_FAMILIES,\n effectiveMode,\n effectiveModel,\n reasoningEfforts = DEFAULT_REASONING_EFFORTS,\n locked = false,\n showModel = true,\n showEffort = true,\n ariaLabel = \"Runtime\",\n className,\n}: RuntimeBarProps<T>) {\n const [preferredFamily, setPreferredFamily] = useState<string>();\n const specMode =\n runtimeModeFromModel(value.model) ||\n value.mode?.trim() ||\n effectiveMode?.trim();\n const selection = selectionForRuntime(\n families,\n specMode,\n value.model || effectiveModel,\n models,\n preferredFamily,\n );\n const family = familyById(families, selection.family);\n const mode =\n family.modes.find((entry) => entry.id === selection.mode) ??\n firstMode(family);\n const modelOptions = modelsForFamily(models, family, specMode);\n const resolvedModel = runtimeModelForValue(models, value, isSelectableModel);\n const selectedModelUnavailable = Boolean(\n !resolvedModel &&\n (value.id || value.model) &&\n runtimeModelForValue(models, value, (entry) => !isSelectableModel(entry)),\n );\n const supportedEfforts = effortOptionsForModel(\n resolvedModel,\n reasoningEfforts,\n );\n\n const applyMode = (familyId: string, modeId: string) => {\n setPreferredFamily(familyId);\n const next = applyRuntimeMode(\n value,\n models,\n families,\n familyId,\n modeId,\n reasoningEfforts,\n );\n if (next !== value) onChange(next);\n };\n\n const applyCustomModel = (model: string) => {\n onChange(\n withOptionalRuntimeValue(withoutCatalogModel(value), \"model\", model),\n );\n };\n // A family's model catalog can serve several modes. Selecting a row must not\n // silently move the user away from the mode they chose.\n const applyModel = (model: ChatModel) => {\n const next = reconcileModelCapabilities(\n withoutCatalogModel(value),\n model,\n reasoningEfforts,\n { mode: mode.id },\n );\n onChange(next);\n };\n const clearModel = () => {\n onChange(withoutCatalogModel(value));\n };\n const applyEffort = (effort: string) =>\n onChange(withOptionalRuntimeValue(value, \"effort\", effort));\n\n if (variant === \"combo\") {\n return (\n <RuntimeBarCombo\n value={value}\n families={families}\n family={family}\n mode={mode}\n selectedMode={selection.mode}\n models={modelOptions}\n selectedModel={resolvedModel}\n selectedModelUnavailable={selectedModelUnavailable}\n supportedEfforts={supportedEfforts}\n locked={locked}\n showModel={showModel}\n showEffort={showEffort}\n ariaLabel={ariaLabel}\n className={className}\n onFamilyChange={(familyId) => applyMode(familyId, selection.mode)}\n onModeChange={(modeId) => applyMode(family.id, modeId)}\n onModelSelect={applyModel}\n onModelClear={clearModel}\n onEffortChange={applyEffort}\n />\n );\n }\n\n return (\n <RuntimeBarSegments\n value={value}\n models={models}\n modelOptions={modelOptions}\n resolvedModel={resolvedModel}\n selectedModelUnavailable={selectedModelUnavailable}\n families={families}\n family={family}\n mode={mode}\n selectedMode={selection.mode}\n reasoningEfforts={reasoningEfforts}\n supportedEfforts={supportedEfforts}\n locked={locked}\n showModel={showModel}\n showEffort={showEffort}\n ariaLabel={ariaLabel}\n className={className}\n onModeChange={applyMode}\n onCustomModel={applyCustomModel}\n onModelSelect={applyModel}\n onModelClear={clearModel}\n onEffortChange={applyEffort}\n />\n );\n}\n\nfunction withoutCatalogModel<T extends RuntimeBarValue>(value: T): T {\n return withOptionalRuntimeValue(\n withOptionalRuntimeValue(value, \"model\", undefined),\n \"id\",\n undefined,\n );\n}\n\nfunction withOptionalRuntimeValue<T extends RuntimeBarValue>(\n value: T,\n key: keyof RuntimeBarValue,\n next: unknown,\n): T {\n const updated = { ...value } as Record<string, unknown>;\n if (next === undefined || next === \"\") {\n delete updated[key];\n } else {\n updated[key] = next;\n }\n return updated as T;\n}\n"],"names":["SPEC_RUNTIME_FAMILIES","DEFAULT_REASONING_EFFORTS","useState","runtimeModeFromModel","selectionForRuntime","familyById","firstMode","modelsForFamily","runtimeModelForValue","isSelectableModel","effortOptionsForModel","applyRuntimeMode","reconcileModelCapabilities","jsx","RuntimeBarCombo","RuntimeBarSegments"],"mappings":"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"}
|