@miragon/mcp-toolkit-ui 2.7.0 → 2.8.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/README.md +7 -4
- package/dist/app/adapt-data-widget.d.ts +1 -22
- package/dist/app/adapt-data-widget.d.ts.map +1 -1
- package/dist/app/adapt-data-widget.js +1 -35
- package/dist/app/adapt-data-widget.js.map +1 -1
- package/dist/app/builder/BuilderBanners.js +1 -1
- package/dist/app/builder/BuilderBanners.js.map +1 -1
- package/dist/app/builder/CanvasRow.d.ts +4 -2
- package/dist/app/builder/CanvasRow.d.ts.map +1 -1
- package/dist/app/builder/CanvasRow.js +21 -7
- package/dist/app/builder/CanvasRow.js.map +1 -1
- package/dist/app/builder/CatalogueSheet.d.ts.map +1 -1
- package/dist/app/builder/CatalogueSheet.js +11 -4
- package/dist/app/builder/CatalogueSheet.js.map +1 -1
- package/dist/app/builder/CellPropsSheet.d.ts +7 -3
- package/dist/app/builder/CellPropsSheet.d.ts.map +1 -1
- package/dist/app/builder/CellPropsSheet.js +10 -3
- package/dist/app/builder/CellPropsSheet.js.map +1 -1
- package/dist/app/builder/DiscardDialog.d.ts +18 -0
- package/dist/app/builder/DiscardDialog.d.ts.map +1 -0
- package/dist/app/builder/DiscardDialog.js +18 -0
- package/dist/app/builder/DiscardDialog.js.map +1 -0
- package/dist/app/builder/LayoutSurface.d.ts +33 -9
- package/dist/app/builder/LayoutSurface.d.ts.map +1 -1
- package/dist/app/builder/LayoutSurface.js +74 -23
- package/dist/app/builder/LayoutSurface.js.map +1 -1
- package/dist/app/builder/PipelineStrip.d.ts +2 -1
- package/dist/app/builder/PipelineStrip.d.ts.map +1 -1
- package/dist/app/builder/PipelineStrip.js +26 -13
- package/dist/app/builder/PipelineStrip.js.map +1 -1
- package/dist/app/builder/SaveDialog.d.ts +9 -1
- package/dist/app/builder/SaveDialog.d.ts.map +1 -1
- package/dist/app/builder/SaveDialog.js +8 -2
- package/dist/app/builder/SaveDialog.js.map +1 -1
- package/dist/app/builder/Toolbar.d.ts +12 -4
- package/dist/app/builder/Toolbar.d.ts.map +1 -1
- package/dist/app/builder/Toolbar.js +18 -7
- package/dist/app/builder/Toolbar.js.map +1 -1
- package/dist/app/builder/Workspace.d.ts +23 -3
- package/dist/app/builder/Workspace.d.ts.map +1 -1
- package/dist/app/builder/Workspace.js +58 -8
- package/dist/app/builder/Workspace.js.map +1 -1
- package/dist/app/builder/builder-model.d.ts +143 -1
- package/dist/app/builder/builder-model.d.ts.map +1 -1
- package/dist/app/builder/builder-model.js +191 -1
- package/dist/app/builder/builder-model.js.map +1 -1
- package/dist/app/builder/reveal.d.ts +10 -0
- package/dist/app/builder/reveal.d.ts.map +1 -0
- package/dist/app/builder/reveal.js +10 -0
- package/dist/app/builder/reveal.js.map +1 -0
- package/dist/app/builder/use-builder-catalogue.d.ts +4 -1
- package/dist/app/builder/use-builder-catalogue.d.ts.map +1 -1
- package/dist/app/builder/use-builder-catalogue.js +44 -17
- package/dist/app/builder/use-builder-catalogue.js.map +1 -1
- package/dist/app/builder/use-builder-session.d.ts +30 -0
- package/dist/app/builder/use-builder-session.d.ts.map +1 -0
- package/dist/app/builder/use-builder-session.js +58 -0
- package/dist/app/builder/use-builder-session.js.map +1 -0
- package/dist/app/builder/use-display-resolver.d.ts +17 -0
- package/dist/app/builder/use-display-resolver.d.ts.map +1 -0
- package/dist/app/builder/use-display-resolver.js +16 -0
- package/dist/app/builder/use-display-resolver.js.map +1 -0
- package/dist/app/index.d.ts +8 -3
- package/dist/app/index.d.ts.map +1 -1
- package/dist/app/index.js +8 -2
- package/dist/app/index.js.map +1 -1
- package/dist/app/layout-builder.d.ts +13 -25
- package/dist/app/layout-builder.d.ts.map +1 -1
- package/dist/app/layout-builder.js +75 -81
- package/dist/app/layout-builder.js.map +1 -1
- package/dist/app/mcp-app-view-chrome.d.ts +12 -3
- package/dist/app/mcp-app-view-chrome.d.ts.map +1 -1
- package/dist/app/mcp-app-view-chrome.js +21 -5
- package/dist/app/mcp-app-view-chrome.js.map +1 -1
- package/dist/app/mcp-app-view-states.d.ts +11 -3
- package/dist/app/mcp-app-view-states.d.ts.map +1 -1
- package/dist/app/mcp-app-view-states.js +29 -8
- package/dist/app/mcp-app-view-states.js.map +1 -1
- package/dist/app/mcp-app-view.d.ts +33 -1
- package/dist/app/mcp-app-view.d.ts.map +1 -1
- package/dist/app/mcp-app-view.js +181 -127
- package/dist/app/mcp-app-view.js.map +1 -1
- package/dist/app/mcp-toolkit-app.d.ts +6 -1
- package/dist/app/mcp-toolkit-app.d.ts.map +1 -1
- package/dist/app/mcp-toolkit-app.js +8 -1
- package/dist/app/mcp-toolkit-app.js.map +1 -1
- package/dist/app/mcp-use-host-bridge.d.ts +15 -6
- package/dist/app/mcp-use-host-bridge.d.ts.map +1 -1
- package/dist/app/mcp-use-host-bridge.js +51 -22
- package/dist/app/mcp-use-host-bridge.js.map +1 -1
- package/dist/app/model-context.d.ts +71 -0
- package/dist/app/model-context.d.ts.map +1 -0
- package/dist/app/model-context.js +101 -0
- package/dist/app/model-context.js.map +1 -0
- package/dist/app/use-build-mode-focus.d.ts +33 -0
- package/dist/app/use-build-mode-focus.d.ts.map +1 -0
- package/dist/app/use-build-mode-focus.js +59 -0
- package/dist/app/use-build-mode-focus.js.map +1 -0
- package/dist/app/use-view-actions.d.ts +31 -0
- package/dist/app/use-view-actions.d.ts.map +1 -0
- package/dist/app/use-view-actions.js +81 -0
- package/dist/app/use-view-actions.js.map +1 -0
- package/dist/app/use-view-lifecycle.d.ts +4 -0
- package/dist/app/use-view-lifecycle.d.ts.map +1 -1
- package/dist/app/use-view-lifecycle.js +2 -0
- package/dist/app/use-view-lifecycle.js.map +1 -1
- package/dist/app/view-lifecycle.d.ts +80 -4
- package/dist/app/view-lifecycle.d.ts.map +1 -1
- package/dist/app/view-lifecycle.js +90 -3
- package/dist/app/view-lifecycle.js.map +1 -1
- package/dist/app/widget-fixture.d.ts +10 -3
- package/dist/app/widget-fixture.d.ts.map +1 -1
- package/dist/app/widget-fixture.js +21 -8
- package/dist/app/widget-fixture.js.map +1 -1
- package/dist/app/widget-props-sheet.d.ts +3 -1
- package/dist/app/widget-props-sheet.d.ts.map +1 -1
- package/dist/app/widget-props-sheet.js +22 -10
- package/dist/app/widget-props-sheet.js.map +1 -1
- package/dist/app/widget-renderer.js +1 -1
- package/dist/app/widget-renderer.js.map +1 -1
- package/dist/components/DrillButton.d.ts +9 -6
- package/dist/components/DrillButton.d.ts.map +1 -1
- package/dist/components/DrillButton.js +8 -6
- package/dist/components/DrillButton.js.map +1 -1
- package/dist/components/EmptyState.d.ts.map +1 -1
- package/dist/components/EmptyState.js +4 -2
- package/dist/components/EmptyState.js.map +1 -1
- package/dist/components/ErrorState.d.ts +5 -2
- package/dist/components/ErrorState.d.ts.map +1 -1
- package/dist/components/ErrorState.js +25 -8
- package/dist/components/ErrorState.js.map +1 -1
- package/dist/components/FilterBar.d.ts +15 -4
- package/dist/components/FilterBar.d.ts.map +1 -1
- package/dist/components/FilterBar.js +11 -6
- package/dist/components/FilterBar.js.map +1 -1
- package/dist/components/KpiGrid.d.ts +66 -21
- package/dist/components/KpiGrid.d.ts.map +1 -1
- package/dist/components/KpiGrid.js +101 -34
- package/dist/components/KpiGrid.js.map +1 -1
- package/dist/components/ListFooter.d.ts +31 -4
- package/dist/components/ListFooter.d.ts.map +1 -1
- package/dist/components/ListFooter.js +30 -11
- package/dist/components/ListFooter.js.map +1 -1
- package/dist/components/PagedListFooter.d.ts +57 -0
- package/dist/components/PagedListFooter.d.ts.map +1 -0
- package/dist/components/PagedListFooter.js +27 -0
- package/dist/components/PagedListFooter.js.map +1 -0
- package/dist/components/Pills.d.ts +27 -7
- package/dist/components/Pills.d.ts.map +1 -1
- package/dist/components/Pills.js +21 -6
- package/dist/components/Pills.js.map +1 -1
- package/dist/components/SectionHeading.d.ts +3 -1
- package/dist/components/SectionHeading.d.ts.map +1 -1
- package/dist/components/SectionHeading.js +6 -2
- package/dist/components/SectionHeading.js.map +1 -1
- package/dist/components/Toast.d.ts +9 -3
- package/dist/components/Toast.d.ts.map +1 -1
- package/dist/components/Toast.js +31 -16
- package/dist/components/Toast.js.map +1 -1
- package/dist/components/WidgetHeader.d.ts +34 -10
- package/dist/components/WidgetHeader.d.ts.map +1 -1
- package/dist/components/WidgetHeader.js +11 -6
- package/dist/components/WidgetHeader.js.map +1 -1
- package/dist/hooks/index.d.ts +4 -4
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -1
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/tool-result-recovery-model.d.ts +155 -0
- package/dist/hooks/tool-result-recovery-model.d.ts.map +1 -0
- package/dist/hooks/tool-result-recovery-model.js +273 -0
- package/dist/hooks/tool-result-recovery-model.js.map +1 -0
- package/dist/hooks/use-tool-query.d.ts +56 -14
- package/dist/hooks/use-tool-query.d.ts.map +1 -1
- package/dist/hooks/use-tool-query.js +102 -25
- package/dist/hooks/use-tool-query.js.map +1 -1
- package/dist/hooks/use-tool-result-recovery.d.ts +47 -52
- package/dist/hooks/use-tool-result-recovery.d.ts.map +1 -1
- package/dist/hooks/use-tool-result-recovery.js +58 -120
- package/dist/hooks/use-tool-result-recovery.js.map +1 -1
- package/dist/hooks/use-view-data.d.ts +52 -10
- package/dist/hooks/use-view-data.d.ts.map +1 -1
- package/dist/hooks/use-view-data.js +81 -16
- package/dist/hooks/use-view-data.js.map +1 -1
- package/dist/hooks/use-view-tool-query.d.ts +12 -7
- package/dist/hooks/use-view-tool-query.d.ts.map +1 -1
- package/dist/hooks/use-view-tool-query.js +15 -14
- package/dist/hooks/use-view-tool-query.js.map +1 -1
- package/dist/index.d.ts +17 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -6
- package/dist/index.js.map +1 -1
- package/dist/lib/focus-return.d.ts +61 -0
- package/dist/lib/focus-return.d.ts.map +1 -0
- package/dist/lib/focus-return.js +46 -0
- package/dist/lib/focus-return.js.map +1 -0
- package/dist/lib/parse-tool-result.d.ts +23 -1
- package/dist/lib/parse-tool-result.d.ts.map +1 -1
- package/dist/lib/parse-tool-result.js +38 -2
- package/dist/lib/parse-tool-result.js.map +1 -1
- package/dist/lib/toast-model.d.ts +41 -1
- package/dist/lib/toast-model.d.ts.map +1 -1
- package/dist/lib/toast-model.js +67 -1
- package/dist/lib/toast-model.js.map +1 -1
- package/dist/lib/tone-utils.d.ts +58 -6
- package/dist/lib/tone-utils.d.ts.map +1 -1
- package/dist/lib/tone-utils.js +66 -4
- package/dist/lib/tone-utils.js.map +1 -1
- package/dist/lib/tool-query.d.ts +107 -0
- package/dist/lib/tool-query.d.ts.map +1 -0
- package/dist/lib/tool-query.js +182 -0
- package/dist/lib/tool-query.js.map +1 -0
- package/dist/lib/tool-result-observer.d.ts +108 -0
- package/dist/lib/tool-result-observer.d.ts.map +1 -0
- package/dist/lib/tool-result-observer.js +158 -0
- package/dist/lib/tool-result-observer.js.map +1 -0
- package/dist/lib/typography.d.ts +37 -0
- package/dist/lib/typography.d.ts.map +1 -0
- package/dist/lib/typography.js +41 -0
- package/dist/lib/typography.js.map +1 -0
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +11 -1
- package/dist/lib/utils.js.map +1 -1
- package/dist/locale/index.d.ts +1 -1
- package/dist/locale/index.d.ts.map +1 -1
- package/dist/locale/message-types.d.ts +117 -4
- package/dist/locale/message-types.d.ts.map +1 -1
- package/dist/locale/messages-de.d.ts.map +1 -1
- package/dist/locale/messages-de.js +44 -10
- package/dist/locale/messages-de.js.map +1 -1
- package/dist/locale/messages-en.d.ts.map +1 -1
- package/dist/locale/messages-en.js +44 -10
- package/dist/locale/messages-en.js.map +1 -1
- package/dist/locale/toolkit-messages.d.ts +19 -1
- package/dist/locale/toolkit-messages.d.ts.map +1 -1
- package/dist/locale/toolkit-messages.js +54 -1
- package/dist/locale/toolkit-messages.js.map +1 -1
- package/dist/primitives/alert.d.ts +1 -1
- package/dist/primitives/alert.d.ts.map +1 -1
- package/dist/primitives/alert.js +2 -0
- package/dist/primitives/alert.js.map +1 -1
- package/dist/primitives/badge.d.ts +1 -1
- package/dist/primitives/badge.d.ts.map +1 -1
- package/dist/primitives/badge.js +9 -4
- package/dist/primitives/badge.js.map +1 -1
- package/dist/primitives/button.d.ts +1 -1
- package/dist/primitives/button.js +1 -1
- package/dist/primitives/button.js.map +1 -1
- package/dist/primitives/dialog.d.ts +1 -1
- package/dist/primitives/dialog.d.ts.map +1 -1
- package/dist/primitives/dialog.js +10 -3
- package/dist/primitives/dialog.js.map +1 -1
- package/dist/primitives/select.js +1 -1
- package/dist/primitives/select.js.map +1 -1
- package/dist/primitives/sheet.d.ts +1 -1
- package/dist/primitives/sheet.d.ts.map +1 -1
- package/dist/primitives/sheet.js +6 -2
- package/dist/primitives/sheet.js.map +1 -1
- package/dist/providers/query-provider.d.ts +32 -1
- package/dist/providers/query-provider.d.ts.map +1 -1
- package/dist/providers/query-provider.js +53 -4
- package/dist/providers/query-provider.js.map +1 -1
- package/dist/render-cases-primitives.js +1 -1
- package/dist/render-cases-primitives.js.map +1 -1
- package/dist/render-cases.d.ts.map +1 -1
- package/dist/render-cases.js +30 -6
- package/dist/render-cases.js.map +1 -1
- package/dist/render-effects.d.ts +42 -0
- package/dist/render-effects.d.ts.map +1 -0
- package/dist/render-effects.js +81 -0
- package/dist/render-effects.js.map +1 -0
- package/dist/theme/create-theme.d.ts +19 -1
- package/dist/theme/create-theme.d.ts.map +1 -1
- package/dist/theme/create-theme.js +15 -0
- package/dist/theme/create-theme.js.map +1 -1
- package/package.json +5 -4
- package/src/app/adapt-data-widget.tsx +2 -42
- package/src/app/builder/BuilderBanners.tsx +1 -1
- package/src/app/builder/CanvasRow.tsx +63 -17
- package/src/app/builder/CatalogueSheet.tsx +50 -29
- package/src/app/builder/CellPropsSheet.tsx +17 -2
- package/src/app/builder/DiscardDialog.tsx +59 -0
- package/src/app/builder/LayoutSurface.tsx +206 -66
- package/src/app/builder/PipelineStrip.tsx +253 -153
- package/src/app/builder/SaveDialog.tsx +14 -2
- package/src/app/builder/Toolbar.tsx +144 -59
- package/src/app/builder/Workspace.tsx +226 -58
- package/src/app/builder/builder-model.ts +341 -2
- package/src/app/builder/builder-model.ux.test.ts +456 -0
- package/src/app/builder/builder-ux.test.tsx +844 -0
- package/src/app/builder/reveal.ts +10 -0
- package/src/app/builder/use-builder-catalogue.ts +56 -19
- package/src/app/builder/use-builder-session.ts +68 -0
- package/src/app/builder/use-display-resolver.ts +24 -0
- package/src/app/index.ts +12 -2
- package/src/app/layout-builder.tsx +178 -191
- package/src/app/mcp-app-view-chrome.test.tsx +141 -1
- package/src/app/mcp-app-view-chrome.tsx +56 -6
- package/src/app/mcp-app-view-states.tsx +51 -11
- package/src/app/mcp-app-view.effects.test.tsx +292 -0
- package/src/app/mcp-app-view.test.tsx +222 -2
- package/src/app/mcp-app-view.tsx +267 -117
- package/src/app/mcp-toolkit-app.test.tsx +40 -0
- package/src/app/mcp-toolkit-app.tsx +8 -1
- package/src/app/mcp-use-host-bridge.test.tsx +180 -0
- package/src/app/mcp-use-host-bridge.tsx +67 -24
- package/src/app/model-context.test.tsx +116 -0
- package/src/app/model-context.tsx +125 -0
- package/src/app/use-build-mode-focus.ts +62 -0
- package/src/app/use-view-actions.ts +89 -0
- package/src/app/use-view-lifecycle.ts +6 -0
- package/src/app/view-lifecycle.test.ts +216 -0
- package/src/app/view-lifecycle.ts +165 -5
- package/src/app/widget-fixture.effects.test.tsx +51 -0
- package/src/app/widget-fixture.render.test.tsx +81 -0
- package/src/app/widget-fixture.tsx +34 -11
- package/src/app/widget-props-sheet.tsx +57 -16
- package/src/app/widget-renderer.tsx +1 -1
- package/src/components/DrillButton.tsx +23 -10
- package/src/components/EmptyState.tsx +6 -4
- package/src/components/ErrorState.tsx +31 -9
- package/src/components/FilterBar.test.tsx +82 -0
- package/src/components/FilterBar.tsx +52 -26
- package/src/components/KpiGrid.test.tsx +279 -0
- package/src/components/KpiGrid.tsx +297 -90
- package/src/components/ListFooter.test.tsx +116 -0
- package/src/components/ListFooter.tsx +102 -15
- package/src/components/PagedListFooter.test.tsx +140 -0
- package/src/components/PagedListFooter.tsx +107 -0
- package/src/components/Pills.test.tsx +77 -0
- package/src/components/Pills.tsx +63 -10
- package/src/components/SectionHeading.tsx +9 -3
- package/src/components/Toast.tsx +37 -19
- package/src/components/WidgetHeader.test.tsx +78 -0
- package/src/components/WidgetHeader.tsx +63 -16
- package/src/components/feedback-states.test.tsx +98 -9
- package/src/components/tone-figures.test.tsx +8 -4
- package/src/hooks/index.ts +6 -3
- package/src/hooks/tool-result-recovery-model.test.ts +744 -0
- package/src/hooks/tool-result-recovery-model.ts +418 -0
- package/src/hooks/use-tool-query.effects.test.tsx +205 -0
- package/src/hooks/use-tool-query.ts +156 -33
- package/src/hooks/use-tool-result-recovery.effects.test.tsx +141 -0
- package/src/hooks/use-tool-result-recovery.test.ts +3 -4
- package/src/hooks/use-tool-result-recovery.ts +84 -142
- package/src/hooks/use-view-data.test.tsx +118 -9
- package/src/hooks/use-view-data.ts +128 -18
- package/src/hooks/use-view-tool-query.ts +25 -19
- package/src/i18n-coverage.test.tsx +104 -2
- package/src/index.ts +48 -11
- package/src/lib/focus-return.test.ts +288 -0
- package/src/lib/focus-return.ts +96 -0
- package/src/lib/parse-tool-result.test.ts +46 -1
- package/src/lib/parse-tool-result.ts +40 -2
- package/src/lib/toast-model.test.ts +166 -1
- package/src/lib/toast-model.ts +104 -2
- package/src/lib/tone-utils.test.ts +86 -10
- package/src/lib/tone-utils.ts +89 -8
- package/src/lib/tool-query.test.ts +569 -0
- package/src/lib/tool-query.ts +253 -0
- package/src/lib/tool-result-observer.test.ts +296 -0
- package/src/lib/tool-result-observer.ts +211 -0
- package/src/lib/typography.test.ts +45 -0
- package/src/lib/typography.ts +47 -0
- package/src/lib/utils.ts +12 -1
- package/src/locale/index.ts +1 -0
- package/src/locale/message-types.ts +118 -2
- package/src/locale/messages-de.ts +49 -10
- package/src/locale/messages-en.ts +49 -10
- package/src/locale/toolkit-messages.test.ts +133 -0
- package/src/locale/toolkit-messages.ts +63 -2
- package/src/primitives/alert.tsx +3 -0
- package/src/primitives/badge.tsx +9 -4
- package/src/primitives/button.tsx +1 -1
- package/src/primitives/dialog.tsx +10 -1
- package/src/primitives/select.tsx +1 -1
- package/src/primitives/sheet.tsx +7 -0
- package/src/providers/query-provider.test.tsx +154 -0
- package/src/providers/query-provider.tsx +66 -5
- package/src/render-cases-primitives.tsx +1 -1
- package/src/render-cases.tsx +38 -6
- package/src/render-effects.tsx +96 -0
- package/src/theme/cd-tokens.test.ts +3 -1
- package/src/theme/create-theme.test.ts +10 -0
- package/src/theme/create-theme.ts +28 -0
- package/src/theme/theme-css.test.ts +51 -0
- package/src/theme.css +31 -1
- package/ui-catalog.json +448 -41
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The stripped-result recovery of `McpAppView` as plain logic (toolkit#176):
|
|
3
|
+
* WHEN the originating tool may be re-executed ({@link decideRecovery}) and a
|
|
4
|
+
* framework-free controller that runs that decision against the transport
|
|
5
|
+
* observer, a fallback grace timer and a single-flight call
|
|
6
|
+
* ({@link createRecoveryController}). `useToolResultRecovery` only binds the
|
|
7
|
+
* controller to React, so the scenarios here (keep / strip / slow / late
|
|
8
|
+
* observer) are the hook's behaviour.
|
|
9
|
+
*
|
|
10
|
+
* The rule, in order:
|
|
11
|
+
*
|
|
12
|
+
* 1. Never recover a call that was cancelled or failed: the view renders that
|
|
13
|
+
* state (an `isError` is an error, K14).
|
|
14
|
+
* 2. Recover when the host delivered a result the view cannot render: the
|
|
15
|
+
* latch fired with an invalid payload, or the observer saw the stripped,
|
|
16
|
+
* content-only result claude.ai sends. The re-run uses the COMPLETE
|
|
17
|
+
* arguments of the call (N21), never a partial stream.
|
|
18
|
+
* 3. Otherwise wait. A slow tool on a compliant host is simply still running
|
|
19
|
+
* (K13): the observer, listening since the handshake, would have seen its
|
|
20
|
+
* result. Only when it cannot vouch for that (no observer, or installed
|
|
21
|
+
* after the handshake) does the 2.x grace timer still infer a stripped
|
|
22
|
+
* result, and only once the call's arguments arrived.
|
|
23
|
+
* 4. A needed recovery runs only for a tool the policy allows
|
|
24
|
+
* ({@link RecoveryPolicy}: by default never one the host reports as
|
|
25
|
+
* writing) and only when the host names the tool; else it is `blocked`,
|
|
26
|
+
* which the view renders as an error whose retry is the user's own call.
|
|
27
|
+
*/
|
|
28
|
+
import { parseToolResult } from "../lib/parse-tool-result.js";
|
|
29
|
+
function isRecord(value) {
|
|
30
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
31
|
+
}
|
|
32
|
+
/** Read {@link ToolSafety} from `hostContext.toolInfo.tool.annotations` (SEP-1865). */
|
|
33
|
+
export function resolveToolSafety(hostContext) {
|
|
34
|
+
if (!isRecord(hostContext) || !isRecord(hostContext.toolInfo))
|
|
35
|
+
return "unknown";
|
|
36
|
+
const tool = hostContext.toolInfo.tool;
|
|
37
|
+
const annotations = isRecord(tool) ? tool.annotations : undefined;
|
|
38
|
+
if (!isRecord(annotations))
|
|
39
|
+
return "unknown";
|
|
40
|
+
if (annotations.destructiveHint === true || annotations.readOnlyHint === false)
|
|
41
|
+
return "writes";
|
|
42
|
+
return annotations.readOnlyHint === true ? "read-only" : "unknown";
|
|
43
|
+
}
|
|
44
|
+
/** Whether `policy` lets the view re-execute a tool of this `safety` on its own. */
|
|
45
|
+
export function policyAllows(policy, safety) {
|
|
46
|
+
if (policy === "never")
|
|
47
|
+
return false;
|
|
48
|
+
if (policy === "read-only")
|
|
49
|
+
return safety === "read-only";
|
|
50
|
+
return safety !== "writes";
|
|
51
|
+
}
|
|
52
|
+
const NONE = { action: "none" };
|
|
53
|
+
const WAIT = { action: "wait", armGrace: false };
|
|
54
|
+
const WAIT_ARMED = { action: "wait", armGrace: true };
|
|
55
|
+
const RECOVER = { action: "recover" };
|
|
56
|
+
/** Rules 1–3: does the result need recovering, or is it delivered / still on its way? */
|
|
57
|
+
function recoveryNeed(input) {
|
|
58
|
+
if (input.resultReady)
|
|
59
|
+
return input.payloadValid ? NONE : "needed";
|
|
60
|
+
const observed = input.observation?.result ?? "none";
|
|
61
|
+
if (observed === "stripped")
|
|
62
|
+
return "needed";
|
|
63
|
+
// A structured result or an error: the latch is about to follow.
|
|
64
|
+
if (observed !== "none")
|
|
65
|
+
return NONE;
|
|
66
|
+
// Listening since the handshake: nothing arrived because nothing was sent.
|
|
67
|
+
if (input.observation?.sawHandshake)
|
|
68
|
+
return WAIT;
|
|
69
|
+
if (input.toolName === undefined || !input.hasInput)
|
|
70
|
+
return WAIT;
|
|
71
|
+
return input.graceElapsed ? "needed" : WAIT_ARMED;
|
|
72
|
+
}
|
|
73
|
+
/** The recovery rule (see the module comment). Pure: every input is explicit. */
|
|
74
|
+
export function decideRecovery(input) {
|
|
75
|
+
if (input.cancelled || input.errored || input.observation?.cancelled)
|
|
76
|
+
return NONE;
|
|
77
|
+
const need = recoveryNeed(input);
|
|
78
|
+
if (need !== "needed")
|
|
79
|
+
return need;
|
|
80
|
+
if (input.toolName === undefined)
|
|
81
|
+
return { action: "blocked", reason: "no-tool" };
|
|
82
|
+
if (!policyAllows(input.policy, input.safety))
|
|
83
|
+
return { action: "blocked", reason: "policy" };
|
|
84
|
+
return RECOVER;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The arguments a re-execution runs with: the complete tool-input the
|
|
88
|
+
* observer saw, else the view runtime's latest input, else none.
|
|
89
|
+
*/
|
|
90
|
+
export function recoveryArgs(observation, toolInput) {
|
|
91
|
+
return observation?.completeInput ?? toolInput ?? {};
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Content identity of a JSON value, independent of key order and object
|
|
95
|
+
* identity: a re-delivered equal input is the same input (N21).
|
|
96
|
+
*/
|
|
97
|
+
export function stableKey(value) {
|
|
98
|
+
return (JSON.stringify(value, (_key, v) => isRecord(v)
|
|
99
|
+
? Object.fromEntries(Object.keys(v)
|
|
100
|
+
.sort()
|
|
101
|
+
.map((k) => [k, v[k]]))
|
|
102
|
+
: v) ?? "undefined");
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Decodes a re-executed tool result and validates it: the payload, or `null`
|
|
106
|
+
* for an error result, an empty one or one the validator refuses.
|
|
107
|
+
*/
|
|
108
|
+
export function decodeRecoveredResult(result, isValid) {
|
|
109
|
+
let decoded;
|
|
110
|
+
try {
|
|
111
|
+
decoded = parseToolResult(result);
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
return decoded !== null && isValid(decoded) ? decoded : null;
|
|
117
|
+
}
|
|
118
|
+
export const RECOVERY_IDLE = Object.freeze({
|
|
119
|
+
data: null,
|
|
120
|
+
failed: false,
|
|
121
|
+
blocked: null,
|
|
122
|
+
recoveredAt: null,
|
|
123
|
+
args: null,
|
|
124
|
+
});
|
|
125
|
+
/** Run {@link decideRecovery} on the controller's current knowledge. */
|
|
126
|
+
export function evaluateRecovery(inputs, observation, grace) {
|
|
127
|
+
const toolName = inputs.resolveToolName(inputs.hostContext);
|
|
128
|
+
const args = recoveryArgs(observation, inputs.toolInput);
|
|
129
|
+
const argsKey = stableKey(args);
|
|
130
|
+
const decision = decideRecovery({
|
|
131
|
+
resultReady: inputs.resultReady,
|
|
132
|
+
payloadValid: inputs.isValid(inputs.props),
|
|
133
|
+
cancelled: inputs.cancelled,
|
|
134
|
+
errored: inputs.errored,
|
|
135
|
+
observation,
|
|
136
|
+
hasInput: inputs.toolInput != null || observation?.completeInput !== undefined,
|
|
137
|
+
toolName,
|
|
138
|
+
safety: resolveToolSafety(inputs.hostContext),
|
|
139
|
+
policy: inputs.policy,
|
|
140
|
+
graceElapsed: grace.elapsed && grace.key === argsKey,
|
|
141
|
+
});
|
|
142
|
+
return { decision, toolName, args, argsKey, runKey: `${toolName ?? ""}\u0000${argsKey}` };
|
|
143
|
+
}
|
|
144
|
+
/** Re-execute the tool and decode its answer; `null` for anything unusable. */
|
|
145
|
+
async function rerun(callTool, isValid, toolName, args) {
|
|
146
|
+
try {
|
|
147
|
+
const data = decodeRecoveredResult(await callTool(toolName, args), isValid);
|
|
148
|
+
if (data === null) {
|
|
149
|
+
console.warn(`[mcp-toolkit] tool-result recovery: re-executing "${toolName}" returned no usable payload`);
|
|
150
|
+
}
|
|
151
|
+
return data;
|
|
152
|
+
}
|
|
153
|
+
catch (err) {
|
|
154
|
+
console.warn(`[mcp-toolkit] tool-result recovery for "${toolName}" failed:`, err);
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Runs {@link decideRecovery} for the view: re-evaluates on every input
|
|
160
|
+
* update and observer change, arms the fallback grace timer per argument set,
|
|
161
|
+
* and makes at most one call per run (single flight, keyed by the tool and
|
|
162
|
+
* its arguments; a newer run drops an older call's outcome).
|
|
163
|
+
*/
|
|
164
|
+
export function createRecoveryController(options) {
|
|
165
|
+
const { observer } = options;
|
|
166
|
+
const now = options.now ?? Date.now;
|
|
167
|
+
const listeners = new Set();
|
|
168
|
+
let state = RECOVERY_IDLE;
|
|
169
|
+
let inputs = null;
|
|
170
|
+
let unsubscribe = null;
|
|
171
|
+
let flight = null;
|
|
172
|
+
// The fallback grace timer: armed per argument set, elapsed once it fired.
|
|
173
|
+
const grace = { key: null, elapsed: false };
|
|
174
|
+
let graceTimer = null;
|
|
175
|
+
const setState = (next) => {
|
|
176
|
+
if (next === state)
|
|
177
|
+
return;
|
|
178
|
+
state = next;
|
|
179
|
+
for (const listener of [...listeners])
|
|
180
|
+
listener();
|
|
181
|
+
};
|
|
182
|
+
const clearGraceTimer = () => {
|
|
183
|
+
if (graceTimer !== null)
|
|
184
|
+
clearTimeout(graceTimer);
|
|
185
|
+
graceTimer = null;
|
|
186
|
+
};
|
|
187
|
+
const armGrace = (key, ms) => {
|
|
188
|
+
if (grace.key === key && (grace.elapsed || graceTimer !== null))
|
|
189
|
+
return;
|
|
190
|
+
clearGraceTimer();
|
|
191
|
+
grace.key = key;
|
|
192
|
+
grace.elapsed = false;
|
|
193
|
+
graceTimer = setTimeout(() => {
|
|
194
|
+
graceTimer = null;
|
|
195
|
+
grace.elapsed = true;
|
|
196
|
+
evaluate();
|
|
197
|
+
}, ms);
|
|
198
|
+
};
|
|
199
|
+
const launch = (current, run, toolName) => {
|
|
200
|
+
const own = {
|
|
201
|
+
key: run.runKey,
|
|
202
|
+
promise: rerun(current.callTool, current.isValid, toolName, run.args),
|
|
203
|
+
};
|
|
204
|
+
flight = own;
|
|
205
|
+
void own.promise.then((data) => {
|
|
206
|
+
// A newer run superseded this call: its outcome is stale.
|
|
207
|
+
if (flight !== own)
|
|
208
|
+
return;
|
|
209
|
+
setState(data === null
|
|
210
|
+
? { ...RECOVERY_IDLE, failed: true, args: run.args }
|
|
211
|
+
: { data: data, failed: false, blocked: null, recoveredAt: now(), args: run.args });
|
|
212
|
+
});
|
|
213
|
+
};
|
|
214
|
+
/** Act on one evaluation: drop a superseded attempt, launch, block or settle. */
|
|
215
|
+
const apply = (current, run) => {
|
|
216
|
+
const { decision } = run;
|
|
217
|
+
// A new run (the need went away, or new arguments) drops the previous
|
|
218
|
+
// attempt and its outcome.
|
|
219
|
+
if (flight && (decision.action !== "recover" || flight.key !== run.runKey)) {
|
|
220
|
+
flight = null;
|
|
221
|
+
setState(RECOVERY_IDLE);
|
|
222
|
+
}
|
|
223
|
+
if (decision.action === "blocked") {
|
|
224
|
+
if (state.blocked !== decision.reason) {
|
|
225
|
+
setState({ ...RECOVERY_IDLE, blocked: decision.reason });
|
|
226
|
+
}
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
// A lifted block (the tool got named, the policy changed) is gone at once,
|
|
230
|
+
// also while the re-run it allows is still in flight.
|
|
231
|
+
if (state.blocked !== null)
|
|
232
|
+
setState(RECOVERY_IDLE);
|
|
233
|
+
if (decision.action === "recover" && !flight && run.toolName !== undefined) {
|
|
234
|
+
launch(current, run, run.toolName);
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
function evaluate() {
|
|
238
|
+
if (!inputs)
|
|
239
|
+
return;
|
|
240
|
+
const run = evaluateRecovery(inputs, observer?.getSnapshot() ?? null, grace);
|
|
241
|
+
if (run.decision.action === "wait" && run.decision.armGrace)
|
|
242
|
+
armGrace(run.argsKey, inputs.graceMs);
|
|
243
|
+
else
|
|
244
|
+
clearGraceTimer();
|
|
245
|
+
apply(inputs, run);
|
|
246
|
+
}
|
|
247
|
+
return {
|
|
248
|
+
subscribe: (listener) => {
|
|
249
|
+
listeners.add(listener);
|
|
250
|
+
return () => {
|
|
251
|
+
listeners.delete(listener);
|
|
252
|
+
};
|
|
253
|
+
},
|
|
254
|
+
getState: () => state,
|
|
255
|
+
update: (next) => {
|
|
256
|
+
inputs = next;
|
|
257
|
+
evaluate();
|
|
258
|
+
},
|
|
259
|
+
start: () => {
|
|
260
|
+
if (!unsubscribe && observer)
|
|
261
|
+
unsubscribe = observer.subscribe(evaluate);
|
|
262
|
+
evaluate();
|
|
263
|
+
},
|
|
264
|
+
stop: () => {
|
|
265
|
+
unsubscribe?.();
|
|
266
|
+
unsubscribe = null;
|
|
267
|
+
// A stopped timer restarts in full on the next start (armGrace re-arms
|
|
268
|
+
// a key whose timer is gone); an elapsed grace stays elapsed.
|
|
269
|
+
clearGraceTimer();
|
|
270
|
+
},
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
//# sourceMappingURL=tool-result-recovery-model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-result-recovery-model.js","sourceRoot":"","sources":["../../src/hooks/tool-result-recovery-model.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,21 +1,63 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { type UseMutationOptions, type UseMutationResult, type UseQueryResult } from "@tanstack/react-query";
|
|
2
|
+
import { type UseToolQueryOptions } from "../lib/tool-query.js";
|
|
3
|
+
export type { UseToolQueryOptions } from "../lib/tool-query.js";
|
|
4
|
+
/**
|
|
5
|
+
* The exact cache key `useToolQuery`, `useViewToolQuery` and `useViewData`
|
|
6
|
+
* use for this tool and args under the nearest `AppQueryProvider`:
|
|
7
|
+
* `toolQueryKey` with the provider's `toolNameInQueryKey` setting. For
|
|
8
|
+
* `getQueryData`, `setQueryData` or `cancelQueries({ exact: true })`; prefix
|
|
9
|
+
* invalidation needs only the caller's `queryKey`. A new array per render.
|
|
10
|
+
*/
|
|
11
|
+
export declare function useToolQueryKey(queryKey: readonly unknown[], toolName: string, args: object): unknown[];
|
|
12
|
+
/**
|
|
13
|
+
* Warns when two tools use one cache key (toolkit#176 K18): their answers
|
|
14
|
+
* would overwrite each other. Only the 2.x key can collide: with the tool
|
|
15
|
+
* name in the key (`toolNameInQueryKey`), two tools never share one.
|
|
16
|
+
*/
|
|
17
|
+
export declare function useToolKeyGuard(queryKey: readonly unknown[], toolName: string, args: object): void;
|
|
18
|
+
/**
|
|
19
|
+
* Fetches a query again once a tool transport arrives, when it failed for
|
|
20
|
+
* want of one ({@link NoToolTransportError}): a `callTool` that resolves
|
|
21
|
+
* after the first render. TanStack refetches on a new key or `enabled`,
|
|
22
|
+
* never on a new fetcher, so the query would keep the error until a remount.
|
|
23
|
+
*/
|
|
24
|
+
export declare function useRefetchOnTransport(callTool: unknown, query: Pick<UseQueryResult<unknown, Error>, "error" | "refetch">): void;
|
|
5
25
|
/**
|
|
6
26
|
* Loads data from a widget tool via TanStack Query.
|
|
7
27
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* entries
|
|
11
|
-
*
|
|
12
|
-
*
|
|
28
|
+
* The effective cache key is `[...queryKey, args]` (`toolQueryKey`): two
|
|
29
|
+
* callers that share `queryKey` but pass different `args` get separate
|
|
30
|
+
* entries. Two tools must not share a key and args; the hook warns when they
|
|
31
|
+
* do. Under an `AppQueryProvider` with `toolNameInQueryKey` (opt-in in 2.x,
|
|
32
|
+
* the default from the next major) the key is `[...queryKey, toolName,
|
|
33
|
+
* args]` and two tools never collide; `useToolQueryKey` returns the key in
|
|
34
|
+
* force. `opts` passes TanStack's query options through (`retry`,
|
|
35
|
+
* `retryDelay`, `staleTime`, `placeholderData` / `keepPreviousData`,
|
|
36
|
+
* `initialData` + `initialDataUpdatedAt`, `enabled`, `select`, …), and the
|
|
37
|
+
* result exposes `refetch`, `failureCount` and `failureReason`. `retry`
|
|
38
|
+
* defaults to the client's; `retry: shouldRetryToolCall` stops retrying a
|
|
39
|
+
* tool's own `isError` answer.
|
|
40
|
+
*
|
|
41
|
+
* The tool goes through `AppQueryProvider`'s `callTool`, else the nearest
|
|
42
|
+
* `HostBridgeProvider`'s bridge; with neither, the query fails with a
|
|
43
|
+
* "no tool transport" error instead of idling, and fetches once one arrives.
|
|
13
44
|
*/
|
|
14
|
-
export declare function useToolQuery<TData = unknown, TSelected = TData>(queryKey: unknown[], toolName: string, args: object, opts?: UseToolQueryOptions<TData, TSelected>):
|
|
45
|
+
export declare function useToolQuery<TData = unknown, TSelected = TData>(queryKey: readonly unknown[], toolName: string, args: object, opts?: UseToolQueryOptions<TData, TSelected>): UseQueryResult<TSelected, Error>;
|
|
46
|
+
/** Options of {@link useToolMutation}: TanStack's mutation options plus `invalidateKeys`. */
|
|
47
|
+
export type UseToolMutationOptions<TData = unknown> = Omit<UseMutationOptions<TData, Error, Record<string, unknown>, unknown>, "mutationFn" | "onMutate"> & {
|
|
48
|
+
/** Query keys (prefixes) to invalidate after a successful call. */
|
|
49
|
+
invalidateKeys?: unknown[][];
|
|
50
|
+
};
|
|
15
51
|
/**
|
|
16
|
-
* Executes a mutation via a widget tool and invalidates
|
|
52
|
+
* Executes a mutation via a widget tool and invalidates `invalidateKeys`
|
|
53
|
+
* after each successful call (`invalidateQueries`: active queries refetch,
|
|
54
|
+
* inactive ones are marked stale and refetch when they are next used).
|
|
55
|
+
*
|
|
56
|
+
* `mutate(args, { onSuccess, onError, onSettled })` fires its per-call
|
|
57
|
+
* callbacks for EVERY call while the component is mounted, not only for the
|
|
58
|
+
* latest one (TanStack's own rule), so two quick calls each get their
|
|
59
|
+
* confirmation. The hook-level callbacks in `opts` run first; the
|
|
60
|
+
* invalidation runs before the hook-level `onSuccess`.
|
|
17
61
|
*/
|
|
18
|
-
export declare function useToolMutation<TData = unknown>(toolName: string, opts?:
|
|
19
|
-
invalidateKeys?: unknown[][];
|
|
20
|
-
}): import("@tanstack/react-query").UseMutationResult<TData, Error, Record<string, unknown>, unknown>;
|
|
62
|
+
export declare function useToolMutation<TData = unknown>(toolName: string, opts?: UseToolMutationOptions<TData>): UseMutationResult<TData, Error, Record<string, unknown>>;
|
|
21
63
|
//# sourceMappingURL=use-tool-query.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-tool-query.d.ts","sourceRoot":"","sources":["../../src/hooks/use-tool-query.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use-tool-query.d.ts","sourceRoot":"","sources":["../../src/hooks/use-tool-query.ts"],"names":[],"mappings":"AACA,OAAO,EAML,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAA;AAG9B,OAAO,EASL,KAAK,mBAAmB,EACzB,MAAM,sBAAsB,CAAA;AAE7B,YAAY,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAE/D;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,EAAE,CAEX;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,IAAI,CAON;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,OAAO,EACjB,KAAK,EAAE,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC,GAC/D,IAAI,CAKN;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,YAAY,CAAC,KAAK,GAAG,OAAO,EAAE,SAAS,GAAG,KAAK,EAC7D,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,mBAAmB,CAAC,KAAK,EAAE,SAAS,CAAC,GAC3C,cAAc,CAAC,SAAS,EAAE,KAAK,CAAC,CAWlC;AAED,6FAA6F;AAC7F,MAAM,MAAM,sBAAsB,CAAC,KAAK,GAAG,OAAO,IAAI,IAAI,CACxD,kBAAkB,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,EAClE,YAAY,GAAG,UAAU,CAC1B,GAAG;IACF,mEAAmE;IACnE,cAAc,CAAC,EAAE,OAAO,EAAE,EAAE,CAAA;CAC7B,CAAA;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,KAAK,GAAG,OAAO,EAC7C,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,sBAAsB,CAAC,KAAK,CAAC,GACnC,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAgD1D"}
|
|
@@ -1,47 +1,124 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { useCallback, useEffect, useRef } from "react";
|
|
2
|
+
import { hashKey, useMutation, useQuery, useQueryClient, } from "@tanstack/react-query";
|
|
3
|
+
import { useCallTool, useToolNameInQueryKey } from "../providers/query-provider.js";
|
|
3
4
|
import { parseToolResult } from "../lib/parse-tool-result.js";
|
|
5
|
+
import { claimToolQueryKey, invalidateToolQueries, NoToolTransportError, settleEachCall, toolKeyCollisionMessage, toolQueryKey, toolQueryOptions, } from "../lib/tool-query.js";
|
|
6
|
+
/**
|
|
7
|
+
* The exact cache key `useToolQuery`, `useViewToolQuery` and `useViewData`
|
|
8
|
+
* use for this tool and args under the nearest `AppQueryProvider`:
|
|
9
|
+
* `toolQueryKey` with the provider's `toolNameInQueryKey` setting. For
|
|
10
|
+
* `getQueryData`, `setQueryData` or `cancelQueries({ exact: true })`; prefix
|
|
11
|
+
* invalidation needs only the caller's `queryKey`. A new array per render.
|
|
12
|
+
*/
|
|
13
|
+
export function useToolQueryKey(queryKey, toolName, args) {
|
|
14
|
+
return toolQueryKey(queryKey, toolName, args, useToolNameInQueryKey());
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Warns when two tools use one cache key (toolkit#176 K18): their answers
|
|
18
|
+
* would overwrite each other. Only the 2.x key can collide: with the tool
|
|
19
|
+
* name in the key (`toolNameInQueryKey`), two tools never share one.
|
|
20
|
+
*/
|
|
21
|
+
export function useToolKeyGuard(queryKey, toolName, args) {
|
|
22
|
+
const client = useQueryClient();
|
|
23
|
+
const keyId = hashKey(useToolQueryKey(queryKey, toolName, args));
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
const previous = claimToolQueryKey(client, keyId, toolName);
|
|
26
|
+
if (previous !== null)
|
|
27
|
+
console.warn(toolKeyCollisionMessage(keyId, toolName, previous));
|
|
28
|
+
}, [client, keyId, toolName]);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Fetches a query again once a tool transport arrives, when it failed for
|
|
32
|
+
* want of one ({@link NoToolTransportError}): a `callTool` that resolves
|
|
33
|
+
* after the first render. TanStack refetches on a new key or `enabled`,
|
|
34
|
+
* never on a new fetcher, so the query would keep the error until a remount.
|
|
35
|
+
*/
|
|
36
|
+
export function useRefetchOnTransport(callTool, query) {
|
|
37
|
+
const { error, refetch } = query;
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
if (callTool && error instanceof NoToolTransportError)
|
|
40
|
+
void refetch();
|
|
41
|
+
}, [callTool, error, refetch]);
|
|
42
|
+
}
|
|
4
43
|
/**
|
|
5
44
|
* Loads data from a widget tool via TanStack Query.
|
|
6
45
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* entries
|
|
10
|
-
*
|
|
11
|
-
*
|
|
46
|
+
* The effective cache key is `[...queryKey, args]` (`toolQueryKey`): two
|
|
47
|
+
* callers that share `queryKey` but pass different `args` get separate
|
|
48
|
+
* entries. Two tools must not share a key and args; the hook warns when they
|
|
49
|
+
* do. Under an `AppQueryProvider` with `toolNameInQueryKey` (opt-in in 2.x,
|
|
50
|
+
* the default from the next major) the key is `[...queryKey, toolName,
|
|
51
|
+
* args]` and two tools never collide; `useToolQueryKey` returns the key in
|
|
52
|
+
* force. `opts` passes TanStack's query options through (`retry`,
|
|
53
|
+
* `retryDelay`, `staleTime`, `placeholderData` / `keepPreviousData`,
|
|
54
|
+
* `initialData` + `initialDataUpdatedAt`, `enabled`, `select`, …), and the
|
|
55
|
+
* result exposes `refetch`, `failureCount` and `failureReason`. `retry`
|
|
56
|
+
* defaults to the client's; `retry: shouldRetryToolCall` stops retrying a
|
|
57
|
+
* tool's own `isError` answer.
|
|
58
|
+
*
|
|
59
|
+
* The tool goes through `AppQueryProvider`'s `callTool`, else the nearest
|
|
60
|
+
* `HostBridgeProvider`'s bridge; with neither, the query fails with a
|
|
61
|
+
* "no tool transport" error instead of idling, and fetches once one arrives.
|
|
12
62
|
*/
|
|
13
63
|
export function useToolQuery(queryKey, toolName, args, opts) {
|
|
14
64
|
const callTool = useCallTool();
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
},
|
|
23
|
-
select: opts?.select,
|
|
24
|
-
enabled: !!callTool && (opts?.enabled ?? true),
|
|
25
|
-
});
|
|
65
|
+
const toolNameInKey = useToolNameInQueryKey();
|
|
66
|
+
useToolKeyGuard(queryKey, toolName, args);
|
|
67
|
+
const query = useQuery(toolQueryOptions(queryKey, toolName, args, callTool, opts, {
|
|
68
|
+
toolNameInKey,
|
|
69
|
+
}));
|
|
70
|
+
useRefetchOnTransport(callTool, query);
|
|
71
|
+
return query;
|
|
26
72
|
}
|
|
27
73
|
/**
|
|
28
|
-
* Executes a mutation via a widget tool and invalidates
|
|
74
|
+
* Executes a mutation via a widget tool and invalidates `invalidateKeys`
|
|
75
|
+
* after each successful call (`invalidateQueries`: active queries refetch,
|
|
76
|
+
* inactive ones are marked stale and refetch when they are next used).
|
|
77
|
+
*
|
|
78
|
+
* `mutate(args, { onSuccess, onError, onSettled })` fires its per-call
|
|
79
|
+
* callbacks for EVERY call while the component is mounted, not only for the
|
|
80
|
+
* latest one (TanStack's own rule), so two quick calls each get their
|
|
81
|
+
* confirmation. The hook-level callbacks in `opts` run first; the
|
|
82
|
+
* invalidation runs before the hook-level `onSuccess`.
|
|
29
83
|
*/
|
|
30
84
|
export function useToolMutation(toolName, opts) {
|
|
31
85
|
const callTool = useCallTool();
|
|
32
86
|
const queryClient = useQueryClient();
|
|
33
|
-
|
|
87
|
+
const { invalidateKeys, onSuccess, ...options } = opts ?? {};
|
|
88
|
+
const mutation = useMutation({
|
|
89
|
+
...options,
|
|
34
90
|
mutationFn: async (args) => {
|
|
35
91
|
if (!callTool)
|
|
36
|
-
throw new
|
|
92
|
+
throw new NoToolTransportError(toolName);
|
|
37
93
|
const result = await callTool(toolName, args);
|
|
38
94
|
return parseToolResult(result);
|
|
39
95
|
},
|
|
40
|
-
onSuccess: async () => {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
96
|
+
onSuccess: async (data, variables, onMutateResult, context) => {
|
|
97
|
+
await invalidateToolQueries(queryClient, invalidateKeys);
|
|
98
|
+
await onSuccess?.(data, variables, onMutateResult, context);
|
|
44
99
|
},
|
|
45
100
|
});
|
|
101
|
+
// Per-call callbacks fire only while mounted (TanStack's rule, kept), with
|
|
102
|
+
// the latest meta/mutationKey. Both refs are written in effects and read
|
|
103
|
+
// only when a call settles, so `mutate` stays stable across renders.
|
|
104
|
+
const mounted = useRef(false);
|
|
105
|
+
const scope = useRef({
|
|
106
|
+
meta: undefined,
|
|
107
|
+
mutationKey: undefined,
|
|
108
|
+
});
|
|
109
|
+
useEffect(() => {
|
|
110
|
+
scope.current = { meta: options.meta, mutationKey: options.mutationKey };
|
|
111
|
+
});
|
|
112
|
+
useEffect(() => {
|
|
113
|
+
mounted.current = true;
|
|
114
|
+
return () => {
|
|
115
|
+
mounted.current = false;
|
|
116
|
+
};
|
|
117
|
+
}, []);
|
|
118
|
+
const { mutateAsync } = mutation;
|
|
119
|
+
const mutate = useCallback((variables, callbacks) => {
|
|
120
|
+
settleEachCall(mutateAsync(variables), variables, callbacks, () => mounted.current ? { client: queryClient, ...scope.current } : null);
|
|
121
|
+
}, [mutateAsync, queryClient]);
|
|
122
|
+
return { ...mutation, mutate };
|
|
46
123
|
}
|
|
47
124
|
//# sourceMappingURL=use-tool-query.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-tool-query.js","sourceRoot":"","sources":["../../src/hooks/use-tool-query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"use-tool-query.js","sourceRoot":"","sources":["../../src/hooks/use-tool-query.ts"],"names":[],"mappings":"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"}
|