@tai42/studio-sdk 16.0.0 → 17.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/code-block.js +1 -1
- package/dist/components/code-block.js.map +1 -1
- package/dist/components/confirm-dialog.js +1 -1
- package/dist/components/confirm-dialog.js.map +1 -1
- package/dist/components/copy-field.js +1 -1
- package/dist/components/copy-field.js.map +1 -1
- package/dist/components/date-range-picker.d.ts.map +1 -1
- package/dist/components/date-range-picker.js.map +1 -1
- package/dist/components/dialog.d.ts.map +1 -1
- package/dist/components/dialog.js.map +1 -1
- package/dist/components/dirty-guard.d.ts.map +1 -1
- package/dist/components/dirty-guard.js +1 -1
- package/dist/components/dirty-guard.js.map +1 -1
- package/dist/components/explorer-body.d.ts +49 -0
- package/dist/components/explorer-body.d.ts.map +1 -0
- package/dist/components/explorer-body.js +67 -0
- package/dist/components/explorer-body.js.map +1 -0
- package/dist/components/explorer-page-size.d.ts +4 -0
- package/dist/components/explorer-page-size.d.ts.map +1 -0
- package/dist/components/explorer-page-size.js +36 -0
- package/dist/components/explorer-page-size.js.map +1 -0
- package/dist/components/explorer-tag-filter.d.ts +17 -0
- package/dist/components/explorer-tag-filter.d.ts.map +1 -0
- package/dist/components/explorer-tag-filter.js +29 -0
- package/dist/components/explorer-tag-filter.js.map +1 -0
- package/dist/components/explorer-tags.d.ts +22 -0
- package/dist/components/explorer-tags.d.ts.map +1 -0
- package/dist/components/explorer-tags.js +51 -0
- package/dist/components/explorer-tags.js.map +1 -0
- package/dist/components/explorer-view.d.ts +3 -17
- package/dist/components/explorer-view.d.ts.map +1 -1
- package/dist/components/explorer-view.js +53 -170
- package/dist/components/explorer-view.js.map +1 -1
- package/dist/components/extension-combo-builder.d.ts +1 -6
- package/dist/components/extension-combo-builder.d.ts.map +1 -1
- package/dist/components/extension-combo-builder.js +4 -79
- package/dist/components/extension-combo-builder.js.map +1 -1
- package/dist/components/extension-combo-parts.d.ts +44 -0
- package/dist/components/extension-combo-parts.d.ts.map +1 -0
- package/dist/components/extension-combo-parts.js +52 -0
- package/dist/components/extension-combo-parts.js.map +1 -0
- package/dist/components/field.d.ts +8 -0
- package/dist/components/field.d.ts.map +1 -1
- package/dist/components/field.js +0 -8
- package/dist/components/field.js.map +1 -1
- package/dist/components/fleet-report.d.ts +1 -1
- package/dist/components/fleet-report.d.ts.map +1 -1
- package/dist/components/fleet-report.js +51 -37
- package/dist/components/fleet-report.js.map +1 -1
- package/dist/components/folder-nav.d.ts.map +1 -1
- package/dist/components/folder-nav.js +1 -1
- package/dist/components/folder-nav.js.map +1 -1
- package/dist/components/form-dialog.d.ts.map +1 -1
- package/dist/components/form-dialog.js +1 -1
- package/dist/components/form-dialog.js.map +1 -1
- package/dist/components/icons/chrome-marks.d.ts +50 -0
- package/dist/components/icons/chrome-marks.d.ts.map +1 -0
- package/dist/components/icons/chrome-marks.js +51 -0
- package/dist/components/icons/chrome-marks.js.map +1 -0
- package/dist/components/icons/icon-frame.d.ts +29 -0
- package/dist/components/icons/icon-frame.d.ts.map +1 -0
- package/dist/components/icons/icon-frame.js +19 -0
- package/dist/components/icons/icon-frame.js.map +1 -0
- package/dist/components/icons/index.d.ts +40 -0
- package/dist/components/icons/index.d.ts.map +1 -0
- package/dist/components/icons/index.js +39 -0
- package/dist/components/icons/index.js.map +1 -0
- package/dist/components/icons/nav-map.d.ts +14 -0
- package/dist/components/icons/nav-map.d.ts.map +1 -0
- package/dist/components/icons/nav-map.js +28 -0
- package/dist/components/icons/nav-map.js.map +1 -0
- package/dist/components/icons/nav-marks.d.ts +44 -0
- package/dist/components/icons/nav-marks.d.ts.map +1 -0
- package/dist/components/icons/nav-marks.js +45 -0
- package/dist/components/icons/nav-marks.js.map +1 -0
- package/dist/components/icons/status-marks.d.ts +21 -0
- package/dist/components/icons/status-marks.d.ts.map +1 -0
- package/dist/components/icons/status-marks.js +22 -0
- package/dist/components/icons/status-marks.js.map +1 -0
- package/dist/components/icons/theme-marks.d.ts +9 -0
- package/dist/components/icons/theme-marks.d.ts.map +1 -0
- package/dist/components/icons/theme-marks.js +10 -0
- package/dist/components/icons/theme-marks.js.map +1 -0
- package/dist/components/inputs.js.map +1 -1
- package/dist/components/json-diff.d.ts.map +1 -1
- package/dist/components/json-diff.js +1 -3
- package/dist/components/json-diff.js.map +1 -1
- package/dist/components/json-tree-context.d.ts +13 -0
- package/dist/components/json-tree-context.d.ts.map +1 -0
- package/dist/components/json-tree-context.js +15 -0
- package/dist/components/json-tree-context.js.map +1 -0
- package/dist/components/json-tree-model.d.ts +56 -0
- package/dist/components/json-tree-model.d.ts.map +1 -0
- package/dist/components/json-tree-model.js +125 -0
- package/dist/components/json-tree-model.js.map +1 -0
- package/dist/components/json-tree-nodes.d.ts +35 -0
- package/dist/components/json-tree-nodes.d.ts.map +1 -0
- package/dist/components/json-tree-nodes.js +113 -0
- package/dist/components/json-tree-nodes.js.map +1 -0
- package/dist/components/json-tree.d.ts +20 -0
- package/dist/components/json-tree.d.ts.map +1 -1
- package/dist/components/json-tree.js +7 -315
- package/dist/components/json-tree.js.map +1 -1
- package/dist/components/json-value-format.d.ts +20 -0
- package/dist/components/json-value-format.d.ts.map +1 -0
- package/dist/components/json-value-format.js +63 -0
- package/dist/components/json-value-format.js.map +1 -0
- package/dist/components/markdown-blocks.d.ts +38 -0
- package/dist/components/markdown-blocks.d.ts.map +1 -0
- package/dist/components/markdown-blocks.js +168 -0
- package/dist/components/markdown-blocks.js.map +1 -0
- package/dist/components/markdown-inline.d.ts +24 -0
- package/dist/components/markdown-inline.d.ts.map +1 -0
- package/dist/components/markdown-inline.js +257 -0
- package/dist/components/markdown-inline.js.map +1 -0
- package/dist/components/markdown.d.ts +3 -52
- package/dist/components/markdown.d.ts.map +1 -1
- package/dist/components/markdown.js +4 -376
- package/dist/components/markdown.js.map +1 -1
- package/dist/components/observer-registry.d.ts +38 -0
- package/dist/components/observer-registry.d.ts.map +1 -0
- package/dist/components/observer-registry.js +131 -0
- package/dist/components/observer-registry.js.map +1 -0
- package/dist/components/overflow-measure.d.ts +38 -0
- package/dist/components/overflow-measure.d.ts.map +1 -0
- package/dist/components/overflow-measure.js +54 -0
- package/dist/components/overflow-measure.js.map +1 -0
- package/dist/components/page-fill.d.ts.map +1 -1
- package/dist/components/page-fill.js.map +1 -1
- package/dist/components/prose-regions.d.ts +81 -0
- package/dist/components/prose-regions.d.ts.map +1 -0
- package/dist/components/prose-regions.js +128 -0
- package/dist/components/prose-regions.js.map +1 -0
- package/dist/components/radio-group.d.ts.map +1 -1
- package/dist/components/radio-group.js.map +1 -1
- package/dist/components/scroll-region.d.ts +24 -0
- package/dist/components/scroll-region.d.ts.map +1 -1
- package/dist/components/scroll-region.js +3 -322
- package/dist/components/scroll-region.js.map +1 -1
- package/dist/components/tab-stop-parse.d.ts +53 -0
- package/dist/components/tab-stop-parse.d.ts.map +1 -0
- package/dist/components/tab-stop-parse.js +202 -0
- package/dist/components/tab-stop-parse.js.map +1 -0
- package/dist/components/table.d.ts +1 -1
- package/dist/components/table.d.ts.map +1 -1
- package/dist/components/tags.d.ts.map +1 -1
- package/dist/components/tags.js +1 -1
- package/dist/components/tags.js.map +1 -1
- package/dist/components/templated-text-field.d.ts +1 -1
- package/dist/components/templated-text-field.d.ts.map +1 -1
- package/dist/components/templated-text-field.js +10 -174
- package/dist/components/templated-text-field.js.map +1 -1
- package/dist/components/templated-text-kwargs-editor.d.ts +24 -0
- package/dist/components/templated-text-kwargs-editor.d.ts.map +1 -0
- package/dist/components/templated-text-kwargs-editor.js +48 -0
- package/dist/components/templated-text-kwargs-editor.js.map +1 -0
- package/dist/components/templated-text-kwargs.d.ts +37 -0
- package/dist/components/templated-text-kwargs.d.ts.map +1 -0
- package/dist/components/templated-text-kwargs.js +66 -0
- package/dist/components/templated-text-kwargs.js.map +1 -0
- package/dist/components/templated-text-source.d.ts +33 -0
- package/dist/components/templated-text-source.d.ts.map +1 -0
- package/dist/components/templated-text-source.js +53 -0
- package/dist/components/templated-text-source.js.map +1 -0
- package/dist/components/tool-picker-parts.d.ts +39 -0
- package/dist/components/tool-picker-parts.d.ts.map +1 -0
- package/dist/components/tool-picker-parts.js +87 -0
- package/dist/components/tool-picker-parts.js.map +1 -0
- package/dist/components/tool-picker.d.ts +1 -2
- package/dist/components/tool-picker.d.ts.map +1 -1
- package/dist/components/tool-picker.js +4 -66
- package/dist/components/tool-picker.js.map +1 -1
- package/dist/components/version-history-panel.d.ts.map +1 -1
- package/dist/components/version-history-panel.js +7 -34
- package/dist/components/version-history-panel.js.map +1 -1
- package/dist/components/version-history-rows.d.ts +48 -0
- package/dist/components/version-history-rows.d.ts.map +1 -0
- package/dist/components/version-history-rows.js +51 -0
- package/dist/components/version-history-rows.js.map +1 -0
- package/dist/components/view-toggle.d.ts.map +1 -1
- package/dist/components/view-toggle.js.map +1 -1
- package/dist/element-slot.d.ts +11 -0
- package/dist/element-slot.d.ts.map +1 -1
- package/dist/element-slot.js +0 -11
- package/dist/element-slot.js.map +1 -1
- package/dist/guards.d.ts +6 -0
- package/dist/guards.d.ts.map +1 -0
- package/dist/guards.js +8 -0
- package/dist/guards.js.map +1 -0
- package/dist/hooks/interactions-connection.d.ts +43 -0
- package/dist/hooks/interactions-connection.d.ts.map +1 -0
- package/dist/hooks/interactions-connection.js +171 -0
- package/dist/hooks/interactions-connection.js.map +1 -0
- package/dist/hooks/interactions-stream.d.ts +80 -0
- package/dist/hooks/interactions-stream.d.ts.map +1 -0
- package/dist/hooks/interactions-stream.js +233 -0
- package/dist/hooks/interactions-stream.js.map +1 -0
- package/dist/hooks/useApi.d.ts +2259 -2189
- package/dist/hooks/useApi.d.ts.map +1 -1
- package/dist/hooks/useApi.js +0 -11
- package/dist/hooks/useApi.js.map +1 -1
- package/dist/hooks/useAuth.d.ts +6 -0
- package/dist/hooks/useAuth.d.ts.map +1 -1
- package/dist/hooks/useAuth.js +0 -6
- package/dist/hooks/useAuth.js.map +1 -1
- package/dist/hooks/useCapabilities.d.ts +18 -2
- package/dist/hooks/useCapabilities.d.ts.map +1 -1
- package/dist/hooks/useCapabilities.js +1 -17
- package/dist/hooks/useCapabilities.js.map +1 -1
- package/dist/hooks/useSse.d.ts +34 -6
- package/dist/hooks/useSse.d.ts.map +1 -1
- package/dist/hooks/useSse.js +27 -471
- package/dist/hooks/useSse.js.map +1 -1
- package/dist/hooks/useSystemKinds.d.ts +1 -1
- package/dist/hooks/useSystemKinds.d.ts.map +1 -1
- package/dist/hooks/useSystemKinds.js +0 -18
- package/dist/hooks/useSystemKinds.js.map +1 -1
- package/dist/hooks/useTheme.d.ts +15 -0
- package/dist/hooks/useTheme.d.ts.map +1 -1
- package/dist/hooks/useTheme.js +0 -15
- package/dist/hooks/useTheme.js.map +1 -1
- package/dist/hooks/useToolDisplayNames.d.ts +0 -14
- package/dist/hooks/useToolDisplayNames.d.ts.map +1 -1
- package/dist/hooks/useToolDisplayNames.js +0 -14
- package/dist/hooks/useToolDisplayNames.js.map +1 -1
- package/dist/host.d.ts +3 -3
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +2 -9
- package/dist/host.js.map +1 -1
- package/dist/index.d.ts +103 -103
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +49 -62
- package/dist/index.js.map +1 -1
- package/dist/navigation/app-link.d.ts +25 -0
- package/dist/navigation/app-link.d.ts.map +1 -0
- package/dist/navigation/app-link.js +33 -0
- package/dist/navigation/app-link.js.map +1 -0
- package/dist/navigation/context.d.ts +3 -20
- package/dist/navigation/context.d.ts.map +1 -1
- package/dist/navigation/context.js +7 -267
- package/dist/navigation/context.js.map +1 -1
- package/dist/navigation/entry-state.d.ts +23 -0
- package/dist/navigation/entry-state.d.ts.map +1 -0
- package/dist/navigation/entry-state.js +39 -0
- package/dist/navigation/entry-state.js.map +1 -0
- package/dist/navigation/guard-registry.d.ts +30 -0
- package/dist/navigation/guard-registry.d.ts.map +1 -0
- package/dist/navigation/guard-registry.js +46 -0
- package/dist/navigation/guard-registry.js.map +1 -0
- package/dist/navigation/guarded-navigation.d.ts +24 -0
- package/dist/navigation/guarded-navigation.d.ts.map +1 -0
- package/dist/navigation/guarded-navigation.js +102 -0
- package/dist/navigation/guarded-navigation.js.map +1 -0
- package/dist/navigation/index.d.ts +5 -4
- package/dist/navigation/index.d.ts.map +1 -1
- package/dist/navigation/index.js +2 -1
- package/dist/navigation/index.js.map +1 -1
- package/dist/navigation/types.d.ts +8 -11
- package/dist/navigation/types.d.ts.map +1 -1
- package/dist/navigation/use-back-forward-guard.d.ts +12 -0
- package/dist/navigation/use-back-forward-guard.d.ts.map +1 -0
- package/dist/navigation/use-back-forward-guard.js +75 -0
- package/dist/navigation/use-back-forward-guard.js.map +1 -0
- package/dist/navigation/use-search-commit.d.ts.map +1 -1
- package/dist/navigation/use-search-commit.js.map +1 -1
- package/dist/plugin/host-state.d.ts.map +1 -1
- package/dist/plugin/host-state.js.map +1 -1
- package/dist/plugin/registry.d.ts +6 -15
- package/dist/plugin/registry.d.ts.map +1 -1
- package/dist/plugin/registry.js +83 -75
- package/dist/plugin/registry.js.map +1 -1
- package/dist/schema-editor/SchemaEditor.d.ts.map +1 -1
- package/dist/schema-editor/SchemaEditor.js.map +1 -1
- package/dist/schema-editor/index.d.ts +3 -3
- package/dist/schema-editor/index.d.ts.map +1 -1
- package/dist/schema-editor/index.js +1 -6
- package/dist/schema-editor/index.js.map +1 -1
- package/dist/schema-form/SecretRefField.d.ts +18 -3
- package/dist/schema-form/SecretRefField.d.ts.map +1 -1
- package/dist/schema-form/SecretRefField.js +21 -26
- package/dist/schema-form/SecretRefField.js.map +1 -1
- package/dist/schema-form/classify.d.ts +1 -113
- package/dist/schema-form/classify.d.ts.map +1 -1
- package/dist/schema-form/classify.js +174 -246
- package/dist/schema-form/classify.js.map +1 -1
- package/dist/schema-form/context.d.ts +6 -0
- package/dist/schema-form/context.d.ts.map +1 -1
- package/dist/schema-form/context.js +0 -6
- package/dist/schema-form/context.js.map +1 -1
- package/dist/schema-form/default-value.d.ts.map +1 -1
- package/dist/schema-form/default-value.js +42 -19
- package/dist/schema-form/default-value.js.map +1 -1
- package/dist/schema-form/enum-field.d.ts +1 -1
- package/dist/schema-form/enum-field.d.ts.map +1 -1
- package/dist/schema-form/field-group.d.ts +6 -0
- package/dist/schema-form/field-group.d.ts.map +1 -1
- package/dist/schema-form/field-group.js +0 -6
- package/dist/schema-form/field-group.js.map +1 -1
- package/dist/schema-form/field-model.d.ts +121 -0
- package/dist/schema-form/field-model.d.ts.map +1 -0
- package/dist/schema-form/field-model.js +2 -0
- package/dist/schema-form/field-model.js.map +1 -0
- package/dist/schema-form/field-node.d.ts.map +1 -1
- package/dist/schema-form/field-node.js +25 -14
- package/dist/schema-form/field-node.js.map +1 -1
- package/dist/schema-form/index.d.ts +8 -8
- package/dist/schema-form/index.d.ts.map +1 -1
- package/dist/schema-form/index.js +3 -34
- package/dist/schema-form/index.js.map +1 -1
- package/dist/schema-form/json-field.d.ts +19 -0
- package/dist/schema-form/json-field.d.ts.map +1 -1
- package/dist/schema-form/json-field.js +0 -19
- package/dist/schema-form/json-field.js.map +1 -1
- package/dist/schema-form/media-field.d.ts +1 -1
- package/dist/schema-form/media-field.d.ts.map +1 -1
- package/dist/schema-form/media-field.js +49 -30
- package/dist/schema-form/media-field.js.map +1 -1
- package/dist/schema-form/record-field.d.ts +12 -0
- package/dist/schema-form/record-field.d.ts.map +1 -1
- package/dist/schema-form/record-field.js +1 -13
- package/dist/schema-form/record-field.js.map +1 -1
- package/dist/schema-form/string-annotations.d.ts +20 -0
- package/dist/schema-form/string-annotations.d.ts.map +1 -0
- package/dist/schema-form/string-annotations.js +105 -0
- package/dist/schema-form/string-annotations.js.map +1 -0
- package/dist/schema-form/string-field.d.ts +1 -1
- package/dist/schema-form/string-field.d.ts.map +1 -1
- package/dist/schema-form/string-field.js +1 -1
- package/dist/schema-form/string-field.js.map +1 -1
- package/dist/schema-form/union-field.d.ts +1 -1
- package/dist/schema-form/union-field.d.ts.map +1 -1
- package/dist/schema-form/union-field.js.map +1 -1
- package/dist/schema-form/union.d.ts +8 -1
- package/dist/schema-form/union.d.ts.map +1 -1
- package/dist/schema-form/union.js +0 -7
- package/dist/schema-form/union.js.map +1 -1
- package/dist/schema-form/validate.d.ts.map +1 -1
- package/dist/schema-form/validate.js +126 -105
- package/dist/schema-form/validate.js.map +1 -1
- package/dist/state-binding/AdapterMapping.d.ts.map +1 -1
- package/dist/state-binding/AdapterMapping.js +0 -0
- package/dist/state-binding/AdapterMapping.js.map +1 -1
- package/dist/state-binding/BindingJqField.d.ts.map +1 -1
- package/dist/state-binding/BindingJqField.js +2 -2
- package/dist/state-binding/BindingJqField.js.map +1 -1
- package/dist/state-binding/InputInjectionRow.d.ts.map +1 -1
- package/dist/state-binding/InputInjectionRow.js +3 -3
- package/dist/state-binding/InputInjectionRow.js.map +1 -1
- package/dist/state-binding/StateAttachRow.d.ts.map +1 -1
- package/dist/state-binding/StateAttachRow.js +57 -41
- package/dist/state-binding/StateAttachRow.js.map +1 -1
- package/dist/state-binding/StateBindingSection.d.ts.map +1 -1
- package/dist/state-binding/StateBindingSection.js.map +1 -1
- package/dist/state-binding/SubjectScopeFields.d.ts.map +1 -1
- package/dist/state-binding/SubjectScopeFields.js.map +1 -1
- package/dist/state-binding/UpdateRow.d.ts.map +1 -1
- package/dist/state-binding/UpdateRow.js +2 -2
- package/dist/state-binding/UpdateRow.js.map +1 -1
- package/dist/state-binding/adapter-mapping-row.d.ts +17 -0
- package/dist/state-binding/adapter-mapping-row.d.ts.map +1 -0
- package/dist/state-binding/adapter-mapping-row.js +87 -0
- package/dist/state-binding/adapter-mapping-row.js.map +1 -0
- package/dist/state-binding/index.d.ts +21 -21
- package/dist/state-binding/index.d.ts.map +1 -1
- package/dist/state-binding/index.js +9 -15
- package/dist/state-binding/index.js.map +1 -1
- package/dist/state-binding/templated-text-catalog.d.ts.map +1 -1
- package/dist/state-binding/templated-text-catalog.js.map +1 -1
- package/dist/state-binding/types.d.ts +2 -2
- package/dist/state-binding/types.d.ts.map +1 -1
- package/dist/structured-output/StructuredOutput.d.ts.map +1 -1
- package/dist/structured-output/StructuredOutput.js +1 -3
- package/dist/structured-output/StructuredOutput.js.map +1 -1
- package/package.json +2 -2
- package/src/components/code-block.tsx +1 -1
- package/src/components/confirm-dialog.tsx +1 -1
- package/src/components/copy-field.tsx +1 -1
- package/src/components/date-range-picker.tsx +1 -1
- package/src/components/dialog.tsx +1 -1
- package/src/components/dirty-guard.tsx +3 -3
- package/src/components/explorer-body.tsx +239 -0
- package/src/components/explorer-page-size.ts +39 -0
- package/src/components/explorer-tag-filter.tsx +80 -0
- package/src/components/explorer-tags.ts +64 -0
- package/src/components/explorer-view.tsx +115 -367
- package/src/components/extension-combo-builder.tsx +35 -153
- package/src/components/extension-combo-parts.tsx +236 -0
- package/src/components/field.tsx +1 -1
- package/src/components/fleet-report.tsx +98 -55
- package/src/components/folder-nav.tsx +2 -2
- package/src/components/form-dialog.tsx +2 -2
- package/src/components/icons/chrome-marks.tsx +195 -0
- package/src/components/icons/icon-frame.tsx +50 -0
- package/src/components/icons/index.ts +84 -0
- package/src/components/icons/nav-map.ts +55 -0
- package/src/components/icons/nav-marks.tsx +205 -0
- package/src/components/icons/status-marks.tsx +46 -0
- package/src/components/icons/theme-marks.tsx +33 -0
- package/src/components/inputs.tsx +1 -1
- package/src/components/json-diff.tsx +1 -4
- package/src/components/json-tree-context.ts +26 -0
- package/src/components/json-tree-model.ts +139 -0
- package/src/components/json-tree-nodes.tsx +224 -0
- package/src/components/json-tree.tsx +15 -434
- package/src/components/json-value-format.ts +64 -0
- package/src/components/markdown-blocks.ts +198 -0
- package/src/components/markdown-inline.tsx +365 -0
- package/src/components/markdown.tsx +6 -472
- package/src/components/observer-registry.ts +139 -0
- package/src/components/overflow-measure.ts +69 -0
- package/src/components/page-fill.tsx +1 -1
- package/src/components/prose-regions.ts +153 -0
- package/src/components/radio-group.tsx +1 -1
- package/src/components/scroll-region.tsx +22 -361
- package/src/components/tab-stop-parse.ts +217 -0
- package/src/components/table.tsx +1 -1
- package/src/components/tags.tsx +2 -2
- package/src/components/templated-text-field.tsx +39 -332
- package/src/components/templated-text-kwargs-editor.tsx +147 -0
- package/src/components/templated-text-kwargs.ts +92 -0
- package/src/components/templated-text-source.tsx +226 -0
- package/src/components/tool-picker-parts.tsx +184 -0
- package/src/components/tool-picker.tsx +22 -114
- package/src/components/version-history-panel.tsx +39 -143
- package/src/components/version-history-rows.tsx +220 -0
- package/src/components/view-toggle.tsx +1 -1
- package/src/element-slot.ts +1 -1
- package/src/guards.ts +7 -0
- package/src/hooks/interactions-connection.ts +227 -0
- package/src/hooks/interactions-stream.ts +274 -0
- package/src/hooks/useApi.ts +1 -1
- package/src/hooks/useAuth.ts +1 -1
- package/src/hooks/useCapabilities.ts +3 -3
- package/src/hooks/useSse.ts +51 -478
- package/src/hooks/useSystemKinds.tsx +2 -2
- package/src/hooks/useTheme.ts +1 -1
- package/src/hooks/useToolDisplayNames.tsx +2 -2
- package/src/host.ts +7 -7
- package/src/index.ts +292 -292
- package/src/navigation/app-link.tsx +70 -0
- package/src/navigation/context.tsx +12 -331
- package/src/navigation/entry-state.ts +42 -0
- package/src/navigation/guard-registry.ts +65 -0
- package/src/navigation/guarded-navigation.ts +147 -0
- package/src/navigation/index.ts +14 -14
- package/src/navigation/types.ts +8 -11
- package/src/navigation/use-back-forward-guard.ts +90 -0
- package/src/navigation/use-search-commit.ts +1 -1
- package/src/plugin/host-state.ts +1 -1
- package/src/plugin/registry.ts +111 -90
- package/src/schema-editor/SchemaEditor.tsx +1 -1
- package/src/schema-editor/index.ts +3 -3
- package/src/schema-form/SecretRefField.tsx +122 -72
- package/src/schema-form/classify.ts +245 -396
- package/src/schema-form/context.ts +1 -1
- package/src/schema-form/default-value.ts +48 -17
- package/src/schema-form/enum-field.tsx +1 -1
- package/src/schema-form/field-group.tsx +1 -1
- package/src/schema-form/field-model.ts +133 -0
- package/src/schema-form/field-node.tsx +95 -39
- package/src/schema-form/index.ts +10 -10
- package/src/schema-form/json-field.tsx +1 -1
- package/src/schema-form/media-field.tsx +136 -67
- package/src/schema-form/record-field.tsx +2 -2
- package/src/schema-form/string-annotations.ts +111 -0
- package/src/schema-form/string-field.tsx +2 -2
- package/src/schema-form/union-field.tsx +3 -2
- package/src/schema-form/union.ts +1 -1
- package/src/schema-form/validate.ts +185 -104
- package/src/state-binding/AdapterMapping.tsx +0 -0
- package/src/state-binding/BindingJqField.tsx +3 -3
- package/src/state-binding/InputInjectionRow.tsx +4 -4
- package/src/state-binding/StateAttachRow.tsx +229 -154
- package/src/state-binding/StateBindingSection.tsx +1 -1
- package/src/state-binding/SubjectScopeFields.tsx +1 -1
- package/src/state-binding/UpdateRow.tsx +3 -3
- package/src/state-binding/adapter-mapping-row.tsx +232 -0
- package/src/state-binding/index.ts +43 -43
- package/src/state-binding/templated-text-catalog.ts +0 -1
- package/src/state-binding/types.ts +2 -2
- package/src/structured-output/StructuredOutput.tsx +1 -4
- package/dist/components/icons.d.ts +0 -160
- package/dist/components/icons.d.ts.map +0 -1
- package/dist/components/icons.js +0 -160
- package/dist/components/icons.js.map +0 -1
- package/src/components/icons.tsx +0 -586
package/dist/element-slot.d.ts
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The runtime half of the `asChild` slot contract.
|
|
3
|
+
*
|
|
4
|
+
* Radix clones its own props onto the node an `asChild` slot is given, so the
|
|
5
|
+
* slot takes exactly one ELEMENT. `ReactElement` states half of that: it rejects
|
|
6
|
+
* a string, which would throw inside Radix anyway. It does NOT reject a
|
|
7
|
+
* FRAGMENT — `<></>` is a `ReactElement` whose `type` is the fragment symbol —
|
|
8
|
+
* and a fragment is the worse of the two, because React drops every prop cloned
|
|
9
|
+
* onto it: the opener renders, carries no `aria-haspopup`/`aria-expanded`/
|
|
10
|
+
* `aria-controls` and no handler, and fails nothing.
|
|
11
|
+
*/
|
|
1
12
|
import type { ReactElement } from 'react';
|
|
2
13
|
/** Raises when an `asChild` slot is handed a fragment. `slot` names the prop. */
|
|
3
14
|
export declare function assertSlotElement(element: ReactElement, slot: string): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"element-slot.d.ts","sourceRoot":"","sources":["../src/element-slot.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"element-slot.d.ts","sourceRoot":"","sources":["../src/element-slot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAG1C,iFAAiF;AACjF,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAM3E"}
|
package/dist/element-slot.js
CHANGED
|
@@ -1,14 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The runtime half of the `asChild` slot contract.
|
|
3
|
-
*
|
|
4
|
-
* Radix clones its own props onto the node an `asChild` slot is given, so the
|
|
5
|
-
* slot takes exactly one ELEMENT. `ReactElement` states half of that: it rejects
|
|
6
|
-
* a string, which would throw inside Radix anyway. It does NOT reject a
|
|
7
|
-
* FRAGMENT — `<></>` is a `ReactElement` whose `type` is the fragment symbol —
|
|
8
|
-
* and a fragment is the worse of the two, because React drops every prop cloned
|
|
9
|
-
* onto it: the opener renders, carries no `aria-haspopup`/`aria-expanded`/
|
|
10
|
-
* `aria-controls` and no handler, and fails nothing.
|
|
11
|
-
*/
|
|
12
1
|
import { Fragment } from 'react';
|
|
13
2
|
/** Raises when an `asChild` slot is handed a fragment. `slot` names the prop. */
|
|
14
3
|
export function assertSlotElement(element, slot) {
|
package/dist/element-slot.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"element-slot.js","sourceRoot":"","sources":["../src/element-slot.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"element-slot.js","sourceRoot":"","sources":["../src/element-slot.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEjC,iFAAiF;AACjF,MAAM,UAAU,iBAAiB,CAAC,OAAqB,EAAE,IAAY;IACnE,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO;IACtC,MAAM,IAAI,KAAK,CACb,GAAG,IAAI,qEAAqE;QAC1E,mEAAmE,CACtE,CAAC;AACJ,CAAC"}
|
package/dist/guards.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared runtime type guards. Internal to studio-sdk — never re-exported from
|
|
3
|
+
* `index.ts` or any subpath, so it stays off the public plugin surface.
|
|
4
|
+
*/
|
|
5
|
+
export declare function isRecord(value: unknown): value is Record<string, unknown>;
|
|
6
|
+
//# sourceMappingURL=guards.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guards.d.ts","sourceRoot":"","sources":["../src/guards.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzE"}
|
package/dist/guards.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared runtime type guards. Internal to studio-sdk — never re-exported from
|
|
3
|
+
* `index.ts` or any subpath, so it stays off the public plugin surface.
|
|
4
|
+
*/
|
|
5
|
+
export function isRecord(value) {
|
|
6
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=guards.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guards.js","sourceRoot":"","sources":["../src/guards.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAc;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The SSE reconnect driver behind `useInteractionsStream`: it owns the fetch +
|
|
3
|
+
* ReadableStream tail (via the api-client's `streamInteractions`, never
|
|
4
|
+
* EventSource), the capped-exponential-with-jitter reconnect backoff, the
|
|
5
|
+
* on-(re)connect resync, and the wiring that folds each frame through the pure
|
|
6
|
+
* overlay reducer and republishes the merged list. React state flows in as the
|
|
7
|
+
* dispatchers the hook passes; this file holds no React.
|
|
8
|
+
*/
|
|
9
|
+
import type { ApiClient, Interaction } from '@tai42/api-client';
|
|
10
|
+
import type { Dispatch, RefObject, SetStateAction } from 'react';
|
|
11
|
+
import { type LiveOverlay, type StreamInteraction } from './interactions-stream';
|
|
12
|
+
/** The live connection status the hook renders from. */
|
|
13
|
+
export interface ConnectionState {
|
|
14
|
+
readonly connected: boolean;
|
|
15
|
+
readonly error: Error | null;
|
|
16
|
+
/**
|
|
17
|
+
* The interactions store is not configured on this deployment: the stream
|
|
18
|
+
* answered with a terminal 501 `interactions-not-configured`. Reconnection is
|
|
19
|
+
* abandoned (retrying would replay the same refusal forever) and the consumer
|
|
20
|
+
* renders the muted OFF state instead of a red error or a floating badge.
|
|
21
|
+
*/
|
|
22
|
+
readonly disabled: boolean;
|
|
23
|
+
}
|
|
24
|
+
/** Everything the driver reads or writes, supplied by the hook's render. */
|
|
25
|
+
export interface InteractionsStreamDeps {
|
|
26
|
+
readonly api: ApiClient;
|
|
27
|
+
readonly overlayRef: RefObject<LiveOverlay>;
|
|
28
|
+
readonly epochRef: RefObject<number>;
|
|
29
|
+
readonly seedRef: RefObject<readonly Interaction[]>;
|
|
30
|
+
readonly onResyncRef: RefObject<() => boolean | Promise<boolean>>;
|
|
31
|
+
readonly onUnauthorized: () => void;
|
|
32
|
+
readonly setConnectionState: Dispatch<SetStateAction<ConnectionState>>;
|
|
33
|
+
readonly setInteractions: Dispatch<SetStateAction<StreamInteraction[]>>;
|
|
34
|
+
readonly setCountEpoch: Dispatch<SetStateAction<number>>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Start the tail-only interactions stream and return the effect cleanup. The
|
|
38
|
+
* abort signal is the single cancellation source of truth: cleanup aborts it, every
|
|
39
|
+
* loop guard reads it fresh, and a fresh mount starts from an empty overlay at epoch
|
|
40
|
+
* 0 so a re-run never inherits the prior run's tail or its epoch stamps.
|
|
41
|
+
*/
|
|
42
|
+
export declare function startInteractionsStream(deps: InteractionsStreamDeps): () => void;
|
|
43
|
+
//# sourceMappingURL=interactions-connection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactions-connection.d.ts","sourceRoot":"","sources":["../../src/hooks/interactions-connection.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAGjE,OAAO,EAEL,KAAK,WAAW,EAOhB,KAAK,iBAAiB,EAEvB,MAAM,uBAAuB,CAAC;AAW/B,wDAAwD;AACxD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAC7B;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAED,4EAA4E;AAC5E,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC,WAAW,CAAC,CAAC;IAC5C,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC,SAAS,WAAW,EAAE,CAAC,CAAC;IACpD,QAAQ,CAAC,WAAW,EAAE,SAAS,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IAClE,QAAQ,CAAC,cAAc,EAAE,MAAM,IAAI,CAAC;IACpC,QAAQ,CAAC,kBAAkB,EAAE,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC,CAAC;IACvE,QAAQ,CAAC,eAAe,EAAE,QAAQ,CAAC,cAAc,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC;IACxE,QAAQ,CAAC,aAAa,EAAE,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;CAC1D;AAwJD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,sBAAsB,GAAG,MAAM,IAAI,CAUhF"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { isFeatureDisabled } from '../feature-disabled';
|
|
2
|
+
import { emptyOverlay, merge, overlayApplyAdd, overlayApplyAnswered, overlayApplyRemoved, parseAddFrame, parseId, sweepAnswered, } from './interactions-stream';
|
|
3
|
+
// Reconnect backoff: capped exponential with full jitter. The delay for attempt
|
|
4
|
+
// n is a random value in [0, min(CAP, BASE * 2**n)); the attempt counter resets
|
|
5
|
+
// only when a connection PROVES HEALTHY — it stayed open at least
|
|
6
|
+
// `HEALTHY_CONNECTION_MS` — not merely when it opens, so a server that accepts the
|
|
7
|
+
// request then drops the body still backs off instead of tight-looping.
|
|
8
|
+
const RECONNECT_BASE_MS = 1500;
|
|
9
|
+
const RECONNECT_CAP_MS = 30000;
|
|
10
|
+
const HEALTHY_CONNECTION_MS = RECONNECT_BASE_MS;
|
|
11
|
+
function aborted(ctx) {
|
|
12
|
+
return ctx.controller.signal.aborted;
|
|
13
|
+
}
|
|
14
|
+
function surfaceMalformed(ctx, event) {
|
|
15
|
+
ctx.setConnectionState((prev) => ({
|
|
16
|
+
...prev,
|
|
17
|
+
error: new Error(`malformed interaction frame: ${event}`),
|
|
18
|
+
}));
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A successful data frame sweeps aged answered cards, republishes the merged list,
|
|
22
|
+
* and clears any transient frame-parse error — one bad frame on a healthy stream
|
|
23
|
+
* must not stick. It does NOT refetch: the overlay already updated the list and the
|
|
24
|
+
* derived count, and the resync fires on (re)connect only.
|
|
25
|
+
*/
|
|
26
|
+
function commit(ctx) {
|
|
27
|
+
if (aborted(ctx))
|
|
28
|
+
return;
|
|
29
|
+
sweepAnswered(ctx.overlay);
|
|
30
|
+
ctx.setConnectionState((prev) => (prev.error === null ? prev : { ...prev, error: null }));
|
|
31
|
+
ctx.setInteractions(merge(ctx.seedRef.current, ctx.overlay));
|
|
32
|
+
}
|
|
33
|
+
function applyFrame(ctx, event, data) {
|
|
34
|
+
if (event === 'interaction.removed') {
|
|
35
|
+
const id = parseId(data);
|
|
36
|
+
if (id === null) {
|
|
37
|
+
surfaceMalformed(ctx, event);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
overlayApplyRemoved(ctx.overlay, id, ctx.epochRef.current);
|
|
41
|
+
commit(ctx);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (event === 'interaction.answered') {
|
|
45
|
+
const id = parseId(data);
|
|
46
|
+
if (id === null) {
|
|
47
|
+
surfaceMalformed(ctx, event);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
overlayApplyAnswered(ctx.overlay, id, ctx.epochRef.current, ctx.seedRef.current);
|
|
51
|
+
commit(ctx);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
// interaction.add — the full question.
|
|
55
|
+
const interaction = parseAddFrame(data);
|
|
56
|
+
if (interaction === null) {
|
|
57
|
+
surfaceMalformed(ctx, event);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
overlayApplyAdd(ctx.overlay, interaction, ctx.epochRef.current);
|
|
61
|
+
commit(ctx);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Open one connection and consume its frames until the tail ends. Refetches the
|
|
65
|
+
* paged base on connect under a fresh epoch (tail-only carries no backlog) and
|
|
66
|
+
* records that epoch as `countEpoch` only once the refetch LANDED, so the count
|
|
67
|
+
* applies only deltas not yet folded into the fresh `total`.
|
|
68
|
+
*/
|
|
69
|
+
async function connectAndConsume(ctx, cursor) {
|
|
70
|
+
const frames = await ctx.api.streamInteractions(ctx.controller.signal, cursor.lastEventId);
|
|
71
|
+
if (aborted(ctx))
|
|
72
|
+
return;
|
|
73
|
+
ctx.setConnectionState((prev) => ({ ...prev, connected: true, error: null, disabled: false }));
|
|
74
|
+
const epoch = (ctx.epochRef.current += 1);
|
|
75
|
+
const landed = await ctx.onResyncRef.current();
|
|
76
|
+
if (aborted(ctx))
|
|
77
|
+
return;
|
|
78
|
+
if (landed)
|
|
79
|
+
ctx.setCountEpoch(epoch);
|
|
80
|
+
for await (const frame of frames) {
|
|
81
|
+
if (aborted(ctx))
|
|
82
|
+
return;
|
|
83
|
+
applyFrame(ctx, frame.event, frame.data);
|
|
84
|
+
// Advance the resume cursor to every id-bearing frame (even a malformed one)
|
|
85
|
+
// so a reconnect never re-requests a frame already delivered.
|
|
86
|
+
if (frame.id !== undefined)
|
|
87
|
+
cursor.lastEventId = frame.id;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/** Classify a connection error into whether the driver should stop or reconnect. */
|
|
91
|
+
function handleConnectionError(ctx, err) {
|
|
92
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
93
|
+
ctx.setConnectionState((prev) => ({ ...prev, connected: false, error }));
|
|
94
|
+
if (error.name === 'ApiUnauthorizedError') {
|
|
95
|
+
// A dead credential — reconnecting would replay the same bad key forever. Hand
|
|
96
|
+
// off to the app's 401→login handler, the same path every other call takes.
|
|
97
|
+
ctx.onUnauthorized();
|
|
98
|
+
return 'stop';
|
|
99
|
+
}
|
|
100
|
+
if (isFeatureDisabled(error)) {
|
|
101
|
+
// A terminal 501 `interactions-not-configured`: reconnecting would replay the
|
|
102
|
+
// same refusal on every backoff forever. Flag the OFF state and stop.
|
|
103
|
+
ctx.setConnectionState((prev) => ({ ...prev, connected: false, disabled: true }));
|
|
104
|
+
return 'stop';
|
|
105
|
+
}
|
|
106
|
+
return 'retry';
|
|
107
|
+
}
|
|
108
|
+
/** Wait out the backoff for `attempt`, resolving early if the signal aborts. */
|
|
109
|
+
function waitBackoff(signal, attempt) {
|
|
110
|
+
const ceiling = Math.min(RECONNECT_CAP_MS, RECONNECT_BASE_MS * 2 ** attempt);
|
|
111
|
+
const delay = Math.random() * ceiling;
|
|
112
|
+
return new Promise((resolve) => {
|
|
113
|
+
const onAbort = () => {
|
|
114
|
+
clearTimeout(timer);
|
|
115
|
+
resolve();
|
|
116
|
+
};
|
|
117
|
+
const timer = setTimeout(() => {
|
|
118
|
+
// Normal wake: drop the abort listener so it does not accumulate across
|
|
119
|
+
// reconnects ({ once: true } only self-removes on firing).
|
|
120
|
+
signal.removeEventListener('abort', onAbort);
|
|
121
|
+
resolve();
|
|
122
|
+
}, delay);
|
|
123
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
/** The reconnect loop: connect, consume, back off, repeat until aborted or terminal. */
|
|
127
|
+
async function runConnectionLoop(ctx) {
|
|
128
|
+
const cursor = { lastEventId: undefined };
|
|
129
|
+
let reconnectAttempt = 0;
|
|
130
|
+
while (!aborted(ctx)) {
|
|
131
|
+
const openedAt = Date.now();
|
|
132
|
+
try {
|
|
133
|
+
await connectAndConsume(ctx, cursor);
|
|
134
|
+
if (aborted(ctx))
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
catch (err) {
|
|
138
|
+
if (aborted(ctx))
|
|
139
|
+
return;
|
|
140
|
+
if (handleConnectionError(ctx, err) === 'stop')
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
// A connection open at least HEALTHY_CONNECTION_MS proved healthy — clear the
|
|
144
|
+
// backoff so the next drop reconnects promptly; an accept-then-drop flap does not.
|
|
145
|
+
if (Date.now() - openedAt >= HEALTHY_CONNECTION_MS)
|
|
146
|
+
reconnectAttempt = 0;
|
|
147
|
+
if (aborted(ctx))
|
|
148
|
+
return;
|
|
149
|
+
ctx.setConnectionState((prev) => ({ ...prev, connected: false }));
|
|
150
|
+
await waitBackoff(ctx.controller.signal, reconnectAttempt);
|
|
151
|
+
reconnectAttempt += 1;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Start the tail-only interactions stream and return the effect cleanup. The
|
|
156
|
+
* abort signal is the single cancellation source of truth: cleanup aborts it, every
|
|
157
|
+
* loop guard reads it fresh, and a fresh mount starts from an empty overlay at epoch
|
|
158
|
+
* 0 so a re-run never inherits the prior run's tail or its epoch stamps.
|
|
159
|
+
*/
|
|
160
|
+
export function startInteractionsStream(deps) {
|
|
161
|
+
const controller = new AbortController();
|
|
162
|
+
const ctx = { ...deps, controller, overlay: deps.overlayRef.current };
|
|
163
|
+
void runConnectionLoop(ctx);
|
|
164
|
+
return () => {
|
|
165
|
+
controller.abort();
|
|
166
|
+
deps.overlayRef.current = emptyOverlay();
|
|
167
|
+
deps.epochRef.current = 0;
|
|
168
|
+
deps.setCountEpoch(0);
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=interactions-connection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactions-connection.js","sourceRoot":"","sources":["../../src/hooks/interactions-connection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pure reducer behind the live interactions inbox: frame parsing, the live
|
|
3
|
+
* overlay accumulated over the paged base, and the two derived projections
|
|
4
|
+
* (`merge` → the published list, `pendingCount` → the live badge tally). No React,
|
|
5
|
+
* no I/O — the connection driver owns the SSE loop and feeds frames through here.
|
|
6
|
+
*/
|
|
7
|
+
import type { Interaction } from '@tai42/api-client';
|
|
8
|
+
/** A live interaction plus the client-maintained `answered` flag. */
|
|
9
|
+
export type StreamInteraction = Interaction & {
|
|
10
|
+
readonly answered: boolean;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Validate an `interaction.add` frame into an `Interaction`, or null when it is
|
|
14
|
+
* malformed. This mirrors the api-client `interaction` zod schema exactly — it
|
|
15
|
+
* accepts what that schema accepts, no more, no less — so the caller surfaces a
|
|
16
|
+
* malformed frame as an error rather than rendering a blank card, and never
|
|
17
|
+
* silently coerces one.
|
|
18
|
+
*/
|
|
19
|
+
export declare function parseAddFrame(data: string): Interaction | null;
|
|
20
|
+
/** The interaction id from an `answered` / `removed` frame, or null. */
|
|
21
|
+
export declare function parseId(data: string): string | null;
|
|
22
|
+
/**
|
|
23
|
+
* The live overlay a connection accumulates over the paged base: the tail's own
|
|
24
|
+
* adds (kept whether or not the base already lists them, so a fresher add wins),
|
|
25
|
+
* the answered stamps (wall-clock ms, for the aging sweep), and the tombstones for
|
|
26
|
+
* ids removed on the tail OR aged out of the answered window (a tombstone stops a
|
|
27
|
+
* still-stale seed from re-showing a gone card; ids are never reused). `addEpoch`
|
|
28
|
+
* and `goneEpoch` carry the resync epoch current when an add / a first terminal frame
|
|
29
|
+
* arrived, so the count applies an add (or subtracts a terminal) only while it is not
|
|
30
|
+
* yet folded into the refetched `total`; the merge and the aging sweep ignore them.
|
|
31
|
+
*/
|
|
32
|
+
export interface LiveOverlay {
|
|
33
|
+
readonly adds: Map<string, Interaction>;
|
|
34
|
+
readonly addEpoch: Map<string, number>;
|
|
35
|
+
readonly answeredAt: Map<string, number>;
|
|
36
|
+
readonly removed: Set<string>;
|
|
37
|
+
readonly goneEpoch: Map<string, number>;
|
|
38
|
+
}
|
|
39
|
+
export declare function emptyOverlay(): LiveOverlay;
|
|
40
|
+
/** Record an `interaction.add`: a live add overwrites any prior copy in place. */
|
|
41
|
+
export declare function overlayApplyAdd(overlay: LiveOverlay, interaction: Interaction, epoch: number): void;
|
|
42
|
+
/**
|
|
43
|
+
* Record an `interaction.answered`. The answered time and terminal epoch are
|
|
44
|
+
* stamped on the FIRST answered frame only (a redelivery keeps the original stamp,
|
|
45
|
+
* so the retention window is not extended and a later terminal never re-dates it
|
|
46
|
+
* into a fresher resync). A seed-origin card is promoted into the overlay so it
|
|
47
|
+
* lingers uniformly with a live-add card, since the paged base never carries
|
|
48
|
+
* answered items and a refetch would otherwise drop it before its window elapses.
|
|
49
|
+
*/
|
|
50
|
+
export declare function overlayApplyAnswered(overlay: LiveOverlay, id: string, epoch: number, seed: readonly Interaction[]): void;
|
|
51
|
+
/** Record an `interaction.removed`: tombstone the id and stamp its first terminal epoch. */
|
|
52
|
+
export declare function overlayApplyRemoved(overlay: LiveOverlay, id: string, epoch: number): void;
|
|
53
|
+
/**
|
|
54
|
+
* Age answered cards out (the server sends no removal for them): tombstone any past
|
|
55
|
+
* the retention window, then — as a flood backstop — the oldest beyond the count
|
|
56
|
+
* cap. A tombstone (not a bare delete) so a still-stale seed cannot resurrect a card
|
|
57
|
+
* the client has retired; the id keeps its original `goneEpoch` so moving
|
|
58
|
+
* answered→removed never re-dates it into a fresher resync.
|
|
59
|
+
*/
|
|
60
|
+
export declare function sweepAnswered(overlay: LiveOverlay): void;
|
|
61
|
+
/** Fold the paged base and the live overlay into the published, ordered list. */
|
|
62
|
+
export declare function merge(seed: readonly Interaction[], live: LiveOverlay): StreamInteraction[];
|
|
63
|
+
/**
|
|
64
|
+
* The live pending tally: the door's `total` for the seed, plus live adds whose id
|
|
65
|
+
* is absent from the seed AND stamped at or after `countEpoch` (a new question not
|
|
66
|
+
* yet folded into `total`), minus one for every terminal id — answered OR removed —
|
|
67
|
+
* stamped at or after `countEpoch`, deduped per id so an id counts once however many
|
|
68
|
+
* terminal frames it drew. `countEpoch` is the epoch of the last resync whose refetch
|
|
69
|
+
* LANDED (a failed refetch never advances it): a delta stamped before it is already
|
|
70
|
+
* reflected in the fresh `total`, so it is NOT applied again — this is what stops a
|
|
71
|
+
* resync from re-subtracting a terminal it already dropped from `total`, while a
|
|
72
|
+
* failed refetch keeps the prior-epoch deltas applying against the prior total. One
|
|
73
|
+
* residual race remains: a frame arriving while a refetch is in flight may already be
|
|
74
|
+
* reflected in that refetch's `total`, so the raw tally can transiently dip below zero
|
|
75
|
+
* until the next resync reconciles. A pending tally below zero is meaningless, so the
|
|
76
|
+
* published count clamps at 0; the clamp covers only the negative symptom (a transient
|
|
77
|
+
* positive under-count reconciles on the next resync, not here).
|
|
78
|
+
*/
|
|
79
|
+
export declare function pendingCount(seed: readonly Interaction[], total: number, live: LiveOverlay, countEpoch: number): number;
|
|
80
|
+
//# sourceMappingURL=interactions-stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactions-stream.d.ts","sourceRoot":"","sources":["../../src/hooks/interactions-stream.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIrD,qEAAqE;AACrE,MAAM,MAAM,iBAAiB,GAAG,WAAW,GAAG;IAAE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC;AAoG7E;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAK9D;AAED,wEAAwE;AACxE,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGnD;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACxC,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC;AAED,wBAAgB,YAAY,IAAI,WAAW,CAQ1C;AAED,kFAAkF;AAClF,wBAAgB,eAAe,CAC7B,OAAO,EAAE,WAAW,EACpB,WAAW,EAAE,WAAW,EACxB,KAAK,EAAE,MAAM,GACZ,IAAI,CAGN;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,WAAW,EACpB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,SAAS,WAAW,EAAE,GAC3B,IAAI,CAUN;AAED,4FAA4F;AAC5F,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAMzF;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAexD;AAED,iFAAiF;AACjF,wBAAgB,KAAK,CAAC,IAAI,EAAE,SAAS,WAAW,EAAE,EAAE,IAAI,EAAE,WAAW,GAAG,iBAAiB,EAAE,CAW1F;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,SAAS,WAAW,EAAE,EAC5B,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,WAAW,EACjB,UAAU,EAAE,MAAM,GACjB,MAAM,CAWR"}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { isRecord } from '../guards';
|
|
2
|
+
// The server emits no removal for an answered card — only `interaction.answered`,
|
|
3
|
+
// never `interaction.removed` for it — and the paged base never carries answered
|
|
4
|
+
// items, so answered cards would otherwise pile up unbounded in the always-mounted
|
|
5
|
+
// badge/inbox. The client ages them out: drop an answered card
|
|
6
|
+
// ANSWERED_RETENTION_MS after its answered frame, keeping at most ANSWERED_CAP as a
|
|
7
|
+
// hard flood backstop. Swept lazily on frame/reconnect ticks (the stream carries no
|
|
8
|
+
// idle heartbeat frame), never a per-item timer.
|
|
9
|
+
const ANSWERED_RETENTION_MS = 10 * 60 * 1000;
|
|
10
|
+
const ANSWERED_CAP = 200;
|
|
11
|
+
// The wire `answer_format` values. Duplicated from the api-client enum by design:
|
|
12
|
+
// the SDK is the leaf and must not import api-client at runtime. The `satisfies`
|
|
13
|
+
// pin against `Interaction['answer_format']` fails to compile if a listed value
|
|
14
|
+
// leaves the union, so this runtime guard cannot silently drift from the type.
|
|
15
|
+
const ANSWER_FORMATS = new Set([
|
|
16
|
+
'text',
|
|
17
|
+
'confirm',
|
|
18
|
+
'select',
|
|
19
|
+
'form',
|
|
20
|
+
'external',
|
|
21
|
+
]);
|
|
22
|
+
/** Parse a frame's JSON to a plain object, or null when it is not one. */
|
|
23
|
+
function parseJson(data) {
|
|
24
|
+
if (!data)
|
|
25
|
+
return null;
|
|
26
|
+
try {
|
|
27
|
+
const obj = JSON.parse(data);
|
|
28
|
+
return isRecord(obj) ? obj : null;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The strict-required fields: `interaction_id`, `group_id`, `created_at`,
|
|
36
|
+
* `timeout_at` must each be a string and `answer_format` a known enum value.
|
|
37
|
+
* `question` is `z.string().default('')` — a missing question is valid (normalized
|
|
38
|
+
* to `''` on assembly) but a present non-string is malformed; `format_payload` is
|
|
39
|
+
* nullish — absent/null is valid but a present non-object is malformed.
|
|
40
|
+
*/
|
|
41
|
+
function requiredFieldsValid(obj) {
|
|
42
|
+
if (typeof obj.interaction_id !== 'string')
|
|
43
|
+
return false;
|
|
44
|
+
if (typeof obj.group_id !== 'string')
|
|
45
|
+
return false;
|
|
46
|
+
if (obj.question !== undefined && typeof obj.question !== 'string')
|
|
47
|
+
return false;
|
|
48
|
+
if (typeof obj.created_at !== 'string')
|
|
49
|
+
return false;
|
|
50
|
+
if (typeof obj.timeout_at !== 'string')
|
|
51
|
+
return false;
|
|
52
|
+
if (typeof obj.answer_format !== 'string' || !ANSWER_FORMATS.has(obj.answer_format))
|
|
53
|
+
return false;
|
|
54
|
+
if (obj.format_payload != null && !isRecord(obj.format_payload))
|
|
55
|
+
return false;
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The optional fields, each rejected only when PRESENT with the wrong type: an
|
|
60
|
+
* absent value stays absent (or takes its schema default on assembly). `media`
|
|
61
|
+
* items stay unknown by design — each is validated per item by the renderer.
|
|
62
|
+
*/
|
|
63
|
+
function optionalFieldsValid(obj) {
|
|
64
|
+
if (obj.sensitive !== undefined && typeof obj.sensitive !== 'boolean')
|
|
65
|
+
return false;
|
|
66
|
+
if (obj.server_verified !== undefined && typeof obj.server_verified !== 'boolean')
|
|
67
|
+
return false;
|
|
68
|
+
if (obj.channel !== undefined && typeof obj.channel !== 'string')
|
|
69
|
+
return false;
|
|
70
|
+
if (obj.recipient !== undefined && typeof obj.recipient !== 'string')
|
|
71
|
+
return false;
|
|
72
|
+
if (obj.origin !== undefined && typeof obj.origin !== 'string')
|
|
73
|
+
return false;
|
|
74
|
+
if (obj.audience !== undefined && typeof obj.audience !== 'string')
|
|
75
|
+
return false;
|
|
76
|
+
if (obj.media !== undefined && !Array.isArray(obj.media))
|
|
77
|
+
return false;
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
/** Assemble the validated frame into an `Interaction`, applying the schema defaults. */
|
|
81
|
+
function buildInteraction(obj) {
|
|
82
|
+
return {
|
|
83
|
+
interaction_id: obj.interaction_id,
|
|
84
|
+
group_id: obj.group_id,
|
|
85
|
+
question: typeof obj.question === 'string' ? obj.question : '',
|
|
86
|
+
answer_format: obj.answer_format,
|
|
87
|
+
format_payload: isRecord(obj.format_payload) ? obj.format_payload : {},
|
|
88
|
+
created_at: obj.created_at,
|
|
89
|
+
timeout_at: obj.timeout_at,
|
|
90
|
+
sensitive: typeof obj.sensitive === 'boolean' ? obj.sensitive : false,
|
|
91
|
+
...(typeof obj.server_verified === 'boolean' ? { server_verified: obj.server_verified } : {}),
|
|
92
|
+
...(typeof obj.channel === 'string' ? { channel: obj.channel } : {}),
|
|
93
|
+
...(typeof obj.recipient === 'string' ? { recipient: obj.recipient } : {}),
|
|
94
|
+
...(typeof obj.origin === 'string' ? { origin: obj.origin } : {}),
|
|
95
|
+
...(typeof obj.audience === 'string' ? { audience: obj.audience } : {}),
|
|
96
|
+
...(Array.isArray(obj.media) ? { media: obj.media } : {}),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Validate an `interaction.add` frame into an `Interaction`, or null when it is
|
|
101
|
+
* malformed. This mirrors the api-client `interaction` zod schema exactly — it
|
|
102
|
+
* accepts what that schema accepts, no more, no less — so the caller surfaces a
|
|
103
|
+
* malformed frame as an error rather than rendering a blank card, and never
|
|
104
|
+
* silently coerces one.
|
|
105
|
+
*/
|
|
106
|
+
export function parseAddFrame(data) {
|
|
107
|
+
const obj = parseJson(data);
|
|
108
|
+
if (obj === null)
|
|
109
|
+
return null;
|
|
110
|
+
if (!requiredFieldsValid(obj) || !optionalFieldsValid(obj))
|
|
111
|
+
return null;
|
|
112
|
+
return buildInteraction(obj);
|
|
113
|
+
}
|
|
114
|
+
/** The interaction id from an `answered` / `removed` frame, or null. */
|
|
115
|
+
export function parseId(data) {
|
|
116
|
+
const id = parseJson(data)?.interaction_id;
|
|
117
|
+
return typeof id === 'string' ? id : null;
|
|
118
|
+
}
|
|
119
|
+
export function emptyOverlay() {
|
|
120
|
+
return {
|
|
121
|
+
adds: new Map(),
|
|
122
|
+
addEpoch: new Map(),
|
|
123
|
+
answeredAt: new Map(),
|
|
124
|
+
removed: new Set(),
|
|
125
|
+
goneEpoch: new Map(),
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/** Record an `interaction.add`: a live add overwrites any prior copy in place. */
|
|
129
|
+
export function overlayApplyAdd(overlay, interaction, epoch) {
|
|
130
|
+
overlay.adds.set(interaction.interaction_id, interaction);
|
|
131
|
+
overlay.addEpoch.set(interaction.interaction_id, epoch);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Record an `interaction.answered`. The answered time and terminal epoch are
|
|
135
|
+
* stamped on the FIRST answered frame only (a redelivery keeps the original stamp,
|
|
136
|
+
* so the retention window is not extended and a later terminal never re-dates it
|
|
137
|
+
* into a fresher resync). A seed-origin card is promoted into the overlay so it
|
|
138
|
+
* lingers uniformly with a live-add card, since the paged base never carries
|
|
139
|
+
* answered items and a refetch would otherwise drop it before its window elapses.
|
|
140
|
+
*/
|
|
141
|
+
export function overlayApplyAnswered(overlay, id, epoch, seed) {
|
|
142
|
+
if (!overlay.answeredAt.has(id))
|
|
143
|
+
overlay.answeredAt.set(id, Date.now());
|
|
144
|
+
if (!overlay.goneEpoch.has(id))
|
|
145
|
+
overlay.goneEpoch.set(id, epoch);
|
|
146
|
+
if (!overlay.adds.has(id)) {
|
|
147
|
+
const seeded = seed.find((item) => item.interaction_id === id);
|
|
148
|
+
if (seeded !== undefined) {
|
|
149
|
+
overlay.adds.set(id, seeded);
|
|
150
|
+
overlay.addEpoch.set(id, epoch);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
/** Record an `interaction.removed`: tombstone the id and stamp its first terminal epoch. */
|
|
155
|
+
export function overlayApplyRemoved(overlay, id, epoch) {
|
|
156
|
+
overlay.adds.delete(id);
|
|
157
|
+
overlay.addEpoch.delete(id);
|
|
158
|
+
overlay.answeredAt.delete(id);
|
|
159
|
+
overlay.removed.add(id);
|
|
160
|
+
if (!overlay.goneEpoch.has(id))
|
|
161
|
+
overlay.goneEpoch.set(id, epoch);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Age answered cards out (the server sends no removal for them): tombstone any past
|
|
165
|
+
* the retention window, then — as a flood backstop — the oldest beyond the count
|
|
166
|
+
* cap. A tombstone (not a bare delete) so a still-stale seed cannot resurrect a card
|
|
167
|
+
* the client has retired; the id keeps its original `goneEpoch` so moving
|
|
168
|
+
* answered→removed never re-dates it into a fresher resync.
|
|
169
|
+
*/
|
|
170
|
+
export function sweepAnswered(overlay) {
|
|
171
|
+
const now = Date.now();
|
|
172
|
+
const retire = (id) => {
|
|
173
|
+
overlay.answeredAt.delete(id);
|
|
174
|
+
overlay.adds.delete(id);
|
|
175
|
+
overlay.addEpoch.delete(id);
|
|
176
|
+
overlay.removed.add(id);
|
|
177
|
+
};
|
|
178
|
+
for (const [id, at] of overlay.answeredAt) {
|
|
179
|
+
if (now - at >= ANSWERED_RETENTION_MS)
|
|
180
|
+
retire(id);
|
|
181
|
+
}
|
|
182
|
+
if (overlay.answeredAt.size > ANSWERED_CAP) {
|
|
183
|
+
const oldest = [...overlay.answeredAt.entries()].sort((a, b) => a[1] - b[1]);
|
|
184
|
+
for (const [id] of oldest.slice(0, oldest.length - ANSWERED_CAP))
|
|
185
|
+
retire(id);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/** Fold the paged base and the live overlay into the published, ordered list. */
|
|
189
|
+
export function merge(seed, live) {
|
|
190
|
+
const out = new Map();
|
|
191
|
+
for (const item of seed) {
|
|
192
|
+
if (live.removed.has(item.interaction_id))
|
|
193
|
+
continue;
|
|
194
|
+
out.set(item.interaction_id, { ...item, answered: live.answeredAt.has(item.interaction_id) });
|
|
195
|
+
}
|
|
196
|
+
for (const [id, item] of live.adds) {
|
|
197
|
+
if (live.removed.has(id))
|
|
198
|
+
continue;
|
|
199
|
+
out.set(id, { ...item, answered: live.answeredAt.has(id) });
|
|
200
|
+
}
|
|
201
|
+
return Array.from(out.values());
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* The live pending tally: the door's `total` for the seed, plus live adds whose id
|
|
205
|
+
* is absent from the seed AND stamped at or after `countEpoch` (a new question not
|
|
206
|
+
* yet folded into `total`), minus one for every terminal id — answered OR removed —
|
|
207
|
+
* stamped at or after `countEpoch`, deduped per id so an id counts once however many
|
|
208
|
+
* terminal frames it drew. `countEpoch` is the epoch of the last resync whose refetch
|
|
209
|
+
* LANDED (a failed refetch never advances it): a delta stamped before it is already
|
|
210
|
+
* reflected in the fresh `total`, so it is NOT applied again — this is what stops a
|
|
211
|
+
* resync from re-subtracting a terminal it already dropped from `total`, while a
|
|
212
|
+
* failed refetch keeps the prior-epoch deltas applying against the prior total. One
|
|
213
|
+
* residual race remains: a frame arriving while a refetch is in flight may already be
|
|
214
|
+
* reflected in that refetch's `total`, so the raw tally can transiently dip below zero
|
|
215
|
+
* until the next resync reconciles. A pending tally below zero is meaningless, so the
|
|
216
|
+
* published count clamps at 0; the clamp covers only the negative symptom (a transient
|
|
217
|
+
* positive under-count reconciles on the next resync, not here).
|
|
218
|
+
*/
|
|
219
|
+
export function pendingCount(seed, total, live, countEpoch) {
|
|
220
|
+
const seedIds = new Set(seed.map((item) => item.interaction_id));
|
|
221
|
+
let count = total;
|
|
222
|
+
for (const id of live.adds.keys()) {
|
|
223
|
+
if (!seedIds.has(id) && (live.addEpoch.get(id) ?? 0) >= countEpoch)
|
|
224
|
+
count += 1;
|
|
225
|
+
}
|
|
226
|
+
const gone = new Set([...live.answeredAt.keys(), ...live.removed]);
|
|
227
|
+
for (const id of gone) {
|
|
228
|
+
if ((live.goneEpoch.get(id) ?? 0) >= countEpoch)
|
|
229
|
+
count -= 1;
|
|
230
|
+
}
|
|
231
|
+
return Math.max(count, 0);
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=interactions-stream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactions-stream.js","sourceRoot":"","sources":["../../src/hooks/interactions-stream.ts"],"names":[],"mappings":"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"}
|