@happyvertical/smrt-svelte 0.53.1 → 0.53.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +15 -15
- package/dist/__tests__/app-state.test.js +0 -156
- package/dist/__tests__/data-surface-bridge.test.js +0 -351
- package/dist/__tests__/provider-mode-harness.svelte +0 -14
- package/dist/__tests__/provider-mode-harness.svelte.d.ts +0 -11
- package/dist/__tests__/provider-mode-harness.svelte.d.ts.map +0 -1
- package/dist/__tests__/provider-mode-probe.svelte +0 -13
- package/dist/__tests__/provider-mode-probe.svelte.d.ts +0 -8
- package/dist/__tests__/provider-mode-probe.svelte.d.ts.map +0 -1
- package/dist/__tests__/provider-webmcp-harness.svelte +0 -14
- package/dist/__tests__/provider-webmcp-harness.svelte.d.ts +0 -8
- package/dist/__tests__/provider-webmcp-harness.svelte.d.ts.map +0 -1
- package/dist/__tests__/success-never-text.test.js +0 -100
- package/dist/__tests__/warm-clients.test.js +0 -186
- package/dist/browser-ai/adapters/llm/bitgpu-inference-backend.test.js +0 -464
- package/dist/browser-ai/adapters/llm/webllm-inference-backend.test.js +0 -646
- package/dist/browser-ai/adapters/stt/browser-speech.test.js +0 -113
- package/dist/browser-ai/adapters/stt/dictation-source.test.js +0 -52
- package/dist/browser-ai/svelte/components/__tests__/ModelStatusControl.test.js +0 -172
- package/dist/components/board/__tests__/Board.test.js +0 -498
- package/dist/components/board/__tests__/BoardSsrHarness.svelte +0 -30
- package/dist/components/board/__tests__/BoardSsrHarness.svelte.d.ts +0 -19
- package/dist/components/board/__tests__/BoardSsrHarness.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/AddressInput.behavior.test.js +0 -216
- package/dist/components/forms/__tests__/CheckboxInput.test.js +0 -92
- package/dist/components/forms/__tests__/DateRangeInput.behavior.test.js +0 -135
- package/dist/components/forms/__tests__/DateTimeInput.behavior.test.js +0 -113
- package/dist/components/forms/__tests__/FileUpload.error-alert.test.js +0 -37
- package/dist/components/forms/__tests__/FileUpload.native-form.test.js +0 -249
- package/dist/components/forms/__tests__/FileUpload.test.js +0 -90
- package/dist/components/forms/__tests__/FileUploadReset.fixture.svelte +0 -24
- package/dist/components/forms/__tests__/FileUploadReset.fixture.svelte.d.ts +0 -10
- package/dist/components/forms/__tests__/FileUploadReset.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/Form.behavior.test.js +0 -137
- package/dist/components/forms/__tests__/Form.extraction.test.js +0 -68
- package/dist/components/forms/__tests__/Form.stt-error.test.js +0 -57
- package/dist/components/forms/__tests__/Form.test.js +0 -86
- package/dist/components/forms/__tests__/Form.ui-controls.test.js +0 -119
- package/dist/components/forms/__tests__/Form.webmcp.test.js +0 -2336
- package/dist/components/forms/__tests__/FormMicButton.test.js +0 -92
- package/dist/components/forms/__tests__/FormScope.test.js +0 -39
- package/dist/components/forms/__tests__/MeasurementInput.behavior.test.js +0 -129
- package/dist/components/forms/__tests__/MoneyInput.behavior.test.js +0 -124
- package/dist/components/forms/__tests__/NumberInput.behavior.test.js +0 -151
- package/dist/components/forms/__tests__/PhoneInput.behavior.test.js +0 -96
- package/dist/components/forms/__tests__/SearchInput.test.js +0 -79
- package/dist/components/forms/__tests__/SelectInput.behavior.test.js +0 -132
- package/dist/components/forms/__tests__/TextInput.behavior.test.js +0 -131
- package/dist/components/forms/__tests__/TextareaInput.behavior.test.js +0 -96
- package/dist/components/forms/__tests__/async-invalid-field.fixture.svelte +0 -30
- package/dist/components/forms/__tests__/async-invalid-field.fixture.svelte.d.ts +0 -7
- package/dist/components/forms/__tests__/async-invalid-field.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/async-validation-form.fixture.svelte +0 -19
- package/dist/components/forms/__tests__/async-validation-form.fixture.svelte.d.ts +0 -9
- package/dist/components/forms/__tests__/async-validation-form.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/async-validation-snapshot-form.fixture.svelte +0 -21
- package/dist/components/forms/__tests__/async-validation-snapshot-form.fixture.svelte.d.ts +0 -8
- package/dist/components/forms/__tests__/async-validation-snapshot-form.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/composite-inputs-a11y.test.js +0 -69
- package/dist/components/forms/__tests__/compound-registration-wrapper.fixture.svelte +0 -27
- package/dist/components/forms/__tests__/compound-registration-wrapper.fixture.svelte.d.ts +0 -9
- package/dist/components/forms/__tests__/compound-registration-wrapper.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/custom-registration-field.fixture.svelte +0 -48
- package/dist/components/forms/__tests__/custom-registration-field.fixture.svelte.d.ts +0 -10
- package/dist/components/forms/__tests__/custom-registration-field.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/form-extraction-values.fixture.svelte +0 -26
- package/dist/components/forms/__tests__/form-extraction-values.fixture.svelte.d.ts +0 -13
- package/dist/components/forms/__tests__/form-extraction-values.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/form-registration-lifecycle.fixture.svelte +0 -52
- package/dist/components/forms/__tests__/form-registration-lifecycle.fixture.svelte.d.ts +0 -16
- package/dist/components/forms/__tests__/form-registration-lifecycle.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/form-scope.fixture.svelte +0 -30
- package/dist/components/forms/__tests__/form-scope.fixture.svelte.d.ts +0 -10
- package/dist/components/forms/__tests__/form-scope.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/form-with-fields.fixture.svelte +0 -158
- package/dist/components/forms/__tests__/form-with-fields.fixture.svelte.d.ts +0 -51
- package/dist/components/forms/__tests__/form-with-fields.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/form-with-policy-field.fixture.svelte +0 -24
- package/dist/components/forms/__tests__/form-with-policy-field.fixture.svelte.d.ts +0 -11
- package/dist/components/forms/__tests__/form-with-policy-field.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/form-with-structured-fields.fixture.svelte +0 -105
- package/dist/components/forms/__tests__/form-with-structured-fields.fixture.svelte.d.ts +0 -42
- package/dist/components/forms/__tests__/form-with-structured-fields.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/form-with-ui-controls.fixture.svelte +0 -84
- package/dist/components/forms/__tests__/form-with-ui-controls.fixture.svelte.d.ts +0 -14
- package/dist/components/forms/__tests__/form-with-ui-controls.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/legacy-form-context.fixture.svelte +0 -44
- package/dist/components/forms/__tests__/legacy-form-context.fixture.svelte.d.ts +0 -9
- package/dist/components/forms/__tests__/legacy-form-context.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/mic-keyboard-a11y.test.js +0 -74
- package/dist/components/forms/__tests__/policy-field.fixture.svelte +0 -35
- package/dist/components/forms/__tests__/policy-field.fixture.svelte.d.ts +0 -8
- package/dist/components/forms/__tests__/policy-field.fixture.svelte.d.ts.map +0 -1
- package/dist/components/forms/__tests__/rich-inputs-a11y.test.js +0 -87
- package/dist/components/settings/__tests__/SettingsCatalog.test.js +0 -69
- package/dist/components/settings/__tests__/catalog.test.js +0 -46
- package/dist/components/workspace/__tests__/AdminShell.responsive.test.js +0 -597
- package/dist/components/workspace/__tests__/AdminShell.test.js +0 -572
- package/dist/components/workspace/__tests__/RoleShell.test.js +0 -772
- package/dist/components/workspace/__tests__/TenantNav.test.js +0 -208
- package/dist/components/workspace/__tests__/WorkspaceAccountMenu.test.js +0 -79
- package/dist/components/workspace/__tests__/WorkspaceShell.test.js +0 -630
- package/dist/components/workspace/__tests__/admin-shell-header-overflow.test.js +0 -25
- package/dist/components/workspace/__tests__/admin-shell-hotkeys.test.js +0 -34
- package/dist/components/workspace/__tests__/admin-shell-mobile.test.js +0 -217
- package/dist/components/workspace/__tests__/admin-shell-mutation-effect-harness.svelte +0 -52
- package/dist/components/workspace/__tests__/admin-shell-mutation-effect-harness.svelte.d.ts +0 -23
- package/dist/components/workspace/__tests__/admin-shell-mutation-effect-harness.svelte.d.ts.map +0 -1
- package/dist/components/workspace/__tests__/admin-shell-page-contracts.test.js +0 -30
- package/dist/components/workspace/__tests__/admin-shell-responsive-state.test.js +0 -184
- package/dist/components/workspace/__tests__/admin-shell-settings.test.js +0 -25
- package/dist/components/workspace/__tests__/admin-shell-state.test.js +0 -286
- package/dist/components/workspace/__tests__/admin-shell-theme-hooks.test.js +0 -36
- package/dist/components/workspace/__tests__/breadcrumbs-helpers.test.js +0 -141
- package/dist/components/workspace/__tests__/context-forwarding-harness.svelte +0 -45
- package/dist/components/workspace/__tests__/context-forwarding-harness.svelte.d.ts +0 -21
- package/dist/components/workspace/__tests__/context-forwarding-harness.svelte.d.ts.map +0 -1
- package/dist/components/workspace/__tests__/define-tools-dock.test.js +0 -1188
- package/dist/components/workspace/__tests__/harness.svelte +0 -25
- package/dist/components/workspace/__tests__/harness.svelte.d.ts +0 -14
- package/dist/components/workspace/__tests__/harness.svelte.d.ts.map +0 -1
- package/dist/components/workspace/__tests__/index.test.js +0 -28
- package/dist/components/workspace/__tests__/legacy-index.test.js +0 -9
- package/dist/components/workspace/__tests__/manifest-nav-helpers.test.js +0 -24
- package/dist/components/workspace/__tests__/manifest-nav.test.js +0 -599
- package/dist/components/workspace/__tests__/nav-helpers.test.js +0 -95
- package/dist/components/workspace/__tests__/render-harness.svelte +0 -66
- package/dist/components/workspace/__tests__/render-harness.svelte.d.ts +0 -32
- package/dist/components/workspace/__tests__/render-harness.svelte.d.ts.map +0 -1
- package/dist/components/workspace/__tests__/render-tools-dock.test.js +0 -260
- package/dist/components/workspace/__tests__/role-shell-bind-harness.svelte +0 -58
- package/dist/components/workspace/__tests__/role-shell-bind-harness.svelte.d.ts +0 -16
- package/dist/components/workspace/__tests__/role-shell-bind-harness.svelte.d.ts.map +0 -1
- package/dist/components/workspace/__tests__/role-shell-switch-harness.svelte +0 -41
- package/dist/components/workspace/__tests__/role-shell-switch-harness.svelte.d.ts +0 -13
- package/dist/components/workspace/__tests__/role-shell-switch-harness.svelte.d.ts.map +0 -1
- package/dist/components/workspace/__tests__/shell-chrome-components.test.js +0 -108
- package/dist/components/workspace/__tests__/system-feed.test.js +0 -327
- package/dist/components/workspace/__tests__/test-icon.svelte +0 -17
- package/dist/components/workspace/__tests__/test-icon.svelte.d.ts +0 -19
- package/dist/components/workspace/__tests__/test-icon.svelte.d.ts.map +0 -1
- package/dist/components/workspace/__tests__/typed-tool-fixture/TypedTool.svelte +0 -38
- package/dist/components/workspace/__tests__/typed-tool-fixture/TypedTool.svelte.d.ts +0 -22
- package/dist/components/workspace/__tests__/typed-tool-fixture/TypedTool.svelte.d.ts.map +0 -1
- package/dist/components/workspace/__tests__/typed-tool-fixture/register-typed-tool.d.ts +0 -66
- package/dist/components/workspace/__tests__/typed-tool-fixture/register-typed-tool.d.ts.map +0 -1
- package/dist/components/workspace/__tests__/typed-tool-fixture/register-typed-tool.js +0 -115
- package/dist/components/workspace/__tests__/typed-tool-fixture/typed-tool-types.d.ts +0 -15
- package/dist/components/workspace/__tests__/typed-tool-fixture/typed-tool-types.d.ts.map +0 -1
- package/dist/components/workspace/__tests__/typed-tool-fixture/typed-tool-types.js +0 -7
- package/dist/components/workspace/__tests__/typed-tool-fixture.test.js +0 -115
- package/dist/components/workspace/__tests__/use-harness-orphan.svelte +0 -9
- package/dist/components/workspace/__tests__/use-harness-orphan.svelte.d.ts +0 -19
- package/dist/components/workspace/__tests__/use-harness-orphan.svelte.d.ts.map +0 -1
- package/dist/components/workspace/__tests__/use-harness.svelte +0 -23
- package/dist/components/workspace/__tests__/use-harness.svelte.d.ts +0 -8
- package/dist/components/workspace/__tests__/use-harness.svelte.d.ts.map +0 -1
- package/dist/components/workspace/__tests__/use-tools-dock.test.js +0 -33
- package/dist/components/workspace/__tests__/workspace-shell-bind-harness.svelte +0 -43
- package/dist/components/workspace/__tests__/workspace-shell-bind-harness.svelte.d.ts +0 -11
- package/dist/components/workspace/__tests__/workspace-shell-bind-harness.svelte.d.ts.map +0 -1
- package/dist/components/workspace/server/__tests__/compose-availability.test.js +0 -383
- package/dist/components/workspace/server/__tests__/typed-context-fixture.d.ts +0 -78
- package/dist/components/workspace/server/__tests__/typed-context-fixture.d.ts.map +0 -1
- package/dist/components/workspace/server/__tests__/typed-context-fixture.js +0 -104
- package/dist/hooks/__tests__/stt-consumer.fixture.svelte +0 -25
- package/dist/hooks/__tests__/stt-consumer.fixture.svelte.d.ts +0 -15
- package/dist/hooks/__tests__/stt-consumer.fixture.svelte.d.ts.map +0 -1
- package/dist/hooks/__tests__/stt-ownership-harness.svelte +0 -42
- package/dist/hooks/__tests__/stt-ownership-harness.svelte.d.ts +0 -20
- package/dist/hooks/__tests__/stt-ownership-harness.svelte.d.ts.map +0 -1
- package/dist/hooks/__tests__/useSTT-ownership.test.js +0 -102
- package/dist/i18n/__tests__/server.spec.js +0 -57
- package/dist/internal/logger.test.js +0 -54
- package/dist/provider-mode.test.js +0 -86
- package/dist/provider-webmcp.test.js +0 -244
- package/dist/state/__tests__/app-state-ai-lifecycle.test.js +0 -240
- package/dist/state/__tests__/warm-clients.test.js +0 -40
- package/dist/web/__tests__/activity-feed-harness.svelte +0 -32
- package/dist/web/__tests__/activity-feed-harness.svelte.d.ts +0 -18
- package/dist/web/__tests__/activity-feed-harness.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/activity-feed.integration.svelte.test.js +0 -190
- package/dist/web/__tests__/activity-feed.svelte.test.js +0 -235
- package/dist/web/__tests__/assistant-dock.integration.svelte.test.js +0 -204
- package/dist/web/__tests__/data-surface-conformance.integration.svelte.test.js +0 -1392
- package/dist/web/__tests__/harness.svelte +0 -25
- package/dist/web/__tests__/harness.svelte.d.ts +0 -15
- package/dist/web/__tests__/harness.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/list-data-surface.fixture.svelte +0 -59
- package/dist/web/__tests__/list-data-surface.fixture.svelte.d.ts +0 -14
- package/dist/web/__tests__/list-data-surface.fixture.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/list-data-surface.svelte.test.js +0 -106
- package/dist/web/__tests__/list-data-surface.test.js +0 -651
- package/dist/web/__tests__/list-sort-surface.fixture.svelte +0 -41
- package/dist/web/__tests__/list-sort-surface.fixture.svelte.d.ts +0 -15
- package/dist/web/__tests__/list-sort-surface.fixture.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/list-sort-surface.svelte.test.js +0 -59
- package/dist/web/__tests__/live-collection.svelte.test.js +0 -185
- package/dist/web/__tests__/provider-ui-registry.fixture.svelte +0 -43
- package/dist/web/__tests__/provider-ui-registry.fixture.svelte.d.ts +0 -13
- package/dist/web/__tests__/provider-ui-registry.fixture.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/provider-ui-registry.test.js +0 -235
- package/dist/web/__tests__/remote-query-harness.svelte +0 -27
- package/dist/web/__tests__/remote-query-harness.svelte.d.ts +0 -11
- package/dist/web/__tests__/remote-query-harness.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/remote-query.svelte.test.js +0 -101
- package/dist/web/__tests__/surfaces.child.fixture.svelte +0 -69
- package/dist/web/__tests__/surfaces.child.fixture.svelte.d.ts +0 -16
- package/dist/web/__tests__/surfaces.child.fixture.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/surfaces.fixture.svelte +0 -26
- package/dist/web/__tests__/surfaces.fixture.svelte.d.ts +0 -18
- package/dist/web/__tests__/surfaces.fixture.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/surfaces.svelte.test.js +0 -140
- package/dist/web/__tests__/update-available-harness.svelte +0 -46
- package/dist/web/__tests__/update-available-harness.svelte.d.ts +0 -22
- package/dist/web/__tests__/update-available-harness.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/update-available.svelte.test.js +0 -137
- package/dist/web/__tests__/view-intent-provider.fixture.svelte +0 -28
- package/dist/web/__tests__/view-intent-provider.fixture.svelte.d.ts +0 -13
- package/dist/web/__tests__/view-intent-provider.fixture.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/view-intent.fixture.svelte +0 -33
- package/dist/web/__tests__/view-intent.fixture.svelte.d.ts +0 -15
- package/dist/web/__tests__/view-intent.fixture.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/view-intent.intents.d.ts +0 -14
- package/dist/web/__tests__/view-intent.intents.d.ts.map +0 -1
- package/dist/web/__tests__/view-intent.intents.js +0 -38
- package/dist/web/__tests__/view-intent.svelte.test.js +0 -244
- package/dist/web/__tests__/webmcp-composed.child.fixture.svelte +0 -73
- package/dist/web/__tests__/webmcp-composed.child.fixture.svelte.d.ts +0 -8
- package/dist/web/__tests__/webmcp-composed.child.fixture.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/webmcp-composed.fixture.svelte +0 -52
- package/dist/web/__tests__/webmcp-composed.fixture.svelte.d.ts +0 -12
- package/dist/web/__tests__/webmcp-composed.fixture.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/webmcp-composed.integration.svelte.test.js +0 -251
- package/dist/web/__tests__/webmcp-effects-reactivity.child.fixture.svelte +0 -16
- package/dist/web/__tests__/webmcp-effects-reactivity.child.fixture.svelte.d.ts +0 -19
- package/dist/web/__tests__/webmcp-effects-reactivity.child.fixture.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/webmcp-effects-reactivity.fixture.svelte +0 -11
- package/dist/web/__tests__/webmcp-effects-reactivity.fixture.svelte.d.ts +0 -8
- package/dist/web/__tests__/webmcp-effects-reactivity.fixture.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/webmcp-harness-reactive-samename.svelte +0 -20
- package/dist/web/__tests__/webmcp-harness-reactive-samename.svelte.d.ts +0 -7
- package/dist/web/__tests__/webmcp-harness-reactive-samename.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/webmcp-harness-unannotated.svelte +0 -14
- package/dist/web/__tests__/webmcp-harness-unannotated.svelte.d.ts +0 -19
- package/dist/web/__tests__/webmcp-harness-unannotated.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/webmcp-harness.svelte +0 -18
- package/dist/web/__tests__/webmcp-harness.svelte.d.ts +0 -7
- package/dist/web/__tests__/webmcp-harness.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/webmcp-ssr.fixture.svelte +0 -13
- package/dist/web/__tests__/webmcp-ssr.fixture.svelte.d.ts +0 -19
- package/dist/web/__tests__/webmcp-ssr.fixture.svelte.d.ts.map +0 -1
- package/dist/web/__tests__/webmcp-ui.test.js +0 -723
- package/dist/web/__tests__/webmcp.test.js +0 -234
|
@@ -1,234 +0,0 @@
|
|
|
1
|
-
import { registerWebMcpBespokeTool as registerBespokeDirect, reserveWebMcpToolNames, WebMcpToolNameCollisionError, webMcpToolNameOwner, } from '@happyvertical/smrt-web';
|
|
2
|
-
import { render } from '@testing-library/svelte';
|
|
3
|
-
import { tick } from 'svelte';
|
|
4
|
-
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
5
|
-
// Wrap the registrar in a spy so a test can observe *which* policy each
|
|
6
|
-
// `useWebMcpTool` effect run handed it, including runs the policy excludes
|
|
7
|
-
// before they ever reach document.modelContext.registerTool (#2599).
|
|
8
|
-
const registerBespokeSpy = vi.hoisted(() => vi.fn());
|
|
9
|
-
vi.mock('@happyvertical/smrt-web', async (importOriginal) => {
|
|
10
|
-
const actual = await importOriginal();
|
|
11
|
-
registerBespokeSpy.mockImplementation(actual.registerWebMcpBespokeTool);
|
|
12
|
-
return { ...actual, registerWebMcpBespokeTool: registerBespokeSpy };
|
|
13
|
-
});
|
|
14
|
-
import EffectsReactivity from './webmcp-effects-reactivity.fixture.svelte';
|
|
15
|
-
import Harness from './webmcp-harness.svelte';
|
|
16
|
-
import HarnessReactiveSameName from './webmcp-harness-reactive-samename.svelte';
|
|
17
|
-
import HarnessUnannotated from './webmcp-harness-unannotated.svelte';
|
|
18
|
-
/**
|
|
19
|
-
* Mimics a host that rejects a duplicate tool name while it still considers
|
|
20
|
-
* an earlier registration of that name live, and only forgets that name one
|
|
21
|
-
* microtask after the earlier registration's abort signal fires — modeling
|
|
22
|
-
* a host that does not process deregistration perfectly synchronously with
|
|
23
|
-
* `AbortController.abort()`.
|
|
24
|
-
*/
|
|
25
|
-
function installCollisionAwareModelContext() {
|
|
26
|
-
const registered = [];
|
|
27
|
-
const liveNames = new Set();
|
|
28
|
-
document.modelContext = {
|
|
29
|
-
async registerTool(tool, options) {
|
|
30
|
-
if (liveNames.has(tool.name)) {
|
|
31
|
-
throw new Error(`host collision: ${tool.name}`);
|
|
32
|
-
}
|
|
33
|
-
liveNames.add(tool.name);
|
|
34
|
-
registered.push({ name: tool.name, signal: options?.signal });
|
|
35
|
-
options?.signal?.addEventListener('abort', () => {
|
|
36
|
-
void Promise.resolve().then(() => {
|
|
37
|
-
liveNames.delete(tool.name);
|
|
38
|
-
});
|
|
39
|
-
});
|
|
40
|
-
},
|
|
41
|
-
};
|
|
42
|
-
return { registered, liveNames };
|
|
43
|
-
}
|
|
44
|
-
function installModelContext() {
|
|
45
|
-
const registered = [];
|
|
46
|
-
document.modelContext = {
|
|
47
|
-
async registerTool(tool, options) {
|
|
48
|
-
registered.push({ name: tool.name, signal: options?.signal });
|
|
49
|
-
},
|
|
50
|
-
};
|
|
51
|
-
return registered;
|
|
52
|
-
}
|
|
53
|
-
afterEach(() => {
|
|
54
|
-
delete document.modelContext;
|
|
55
|
-
registerBespokeSpy.mockClear();
|
|
56
|
-
});
|
|
57
|
-
describe('useWebMcpTool', () => {
|
|
58
|
-
it('registers on mount, aborts on spec changes, and aborts on unmount', async () => {
|
|
59
|
-
const registered = installModelContext();
|
|
60
|
-
const view = render(Harness, { props: { version: 1 } });
|
|
61
|
-
// Registration now routes through a dynamically imported registrar
|
|
62
|
-
// (#2586), so it lands one or more microtasks after mount.
|
|
63
|
-
await vi.waitFor(() => expect(registered).toHaveLength(1));
|
|
64
|
-
expect(registered[0].name).toBe('harness_tool_1');
|
|
65
|
-
expect(registered[0].signal?.aborted).toBe(false);
|
|
66
|
-
await view.rerender({ version: 2 });
|
|
67
|
-
await vi.waitFor(() => expect(registered).toHaveLength(2));
|
|
68
|
-
expect(registered[0].signal?.aborted).toBe(true);
|
|
69
|
-
expect(registered[1].name).toBe('harness_tool_2');
|
|
70
|
-
view.unmount();
|
|
71
|
-
expect(registered[1].signal?.aborted).toBe(true);
|
|
72
|
-
});
|
|
73
|
-
it('observes asynchronous host rejection and aborts the failed registration', async () => {
|
|
74
|
-
let rejectRegistration;
|
|
75
|
-
let signal;
|
|
76
|
-
document.modelContext = {
|
|
77
|
-
registerTool(_tool, options) {
|
|
78
|
-
signal = options?.signal;
|
|
79
|
-
return new Promise((_resolve, reject) => {
|
|
80
|
-
rejectRegistration = reject;
|
|
81
|
-
});
|
|
82
|
-
},
|
|
83
|
-
};
|
|
84
|
-
const view = render(Harness);
|
|
85
|
-
await vi.waitFor(() => expect(signal).toBeDefined());
|
|
86
|
-
expect(signal?.aborted).toBe(false);
|
|
87
|
-
rejectRegistration?.(new Error('host collision'));
|
|
88
|
-
await vi.waitFor(() => expect(signal?.aborted).toBe(true));
|
|
89
|
-
view.unmount();
|
|
90
|
-
});
|
|
91
|
-
it('is a no-op when WebMCP is unavailable', async () => {
|
|
92
|
-
const view = render(Harness);
|
|
93
|
-
await tick();
|
|
94
|
-
expect(view.container).toHaveTextContent('1');
|
|
95
|
-
view.unmount();
|
|
96
|
-
});
|
|
97
|
-
it('excludes an undeclared tool under the default read-only exposure policy', async () => {
|
|
98
|
-
const registered = installModelContext();
|
|
99
|
-
const view = render(HarnessUnannotated);
|
|
100
|
-
// No Provider ancestor: the hook falls back to the registrar's default
|
|
101
|
-
// read-only policy. An undeclared spec classifies destructive (#2586)
|
|
102
|
-
// and must never reach document.modelContext.registerTool.
|
|
103
|
-
await tick();
|
|
104
|
-
await tick();
|
|
105
|
-
await tick();
|
|
106
|
-
expect(registered).toHaveLength(0);
|
|
107
|
-
view.unmount();
|
|
108
|
-
expect(registered).toHaveLength(0);
|
|
109
|
-
});
|
|
110
|
-
it('disposes a registered destructive bespoke tool when a Provider policy tightens from destructive to read (#2586 F2)', async () => {
|
|
111
|
-
const registered = installModelContext();
|
|
112
|
-
const view = render(EffectsReactivity, {
|
|
113
|
-
props: { effects: ['destructive'] },
|
|
114
|
-
});
|
|
115
|
-
await vi.waitFor(() => expect(registered.map((tool) => tool.name)).toContain('reactivity_destructive_tool'));
|
|
116
|
-
expect(registered).toHaveLength(1);
|
|
117
|
-
const first = registered[0];
|
|
118
|
-
expect(first.signal?.aborted).toBe(false);
|
|
119
|
-
// `bespokeContext.effects` is read synchronously at the top of the
|
|
120
|
-
// `$effect` body (the F2 fix), so this Provider policy change is
|
|
121
|
-
// tracked as a dependency and re-runs the effect: the previously
|
|
122
|
-
// registered destructive tool is torn down, and re-registration under
|
|
123
|
-
// the new read-only policy is excluded before it ever reaches
|
|
124
|
-
// document.modelContext.registerTool again.
|
|
125
|
-
await view.rerender({ effects: ['read'] });
|
|
126
|
-
await vi.waitFor(() => expect(first.signal?.aborted).toBe(true));
|
|
127
|
-
expect(registered).toHaveLength(1);
|
|
128
|
-
view.unmount();
|
|
129
|
-
});
|
|
130
|
-
it('serializes same-name re-registration across rapid reactive reruns without a host collision', async () => {
|
|
131
|
-
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => { });
|
|
132
|
-
const { registered, liveNames } = installCollisionAwareModelContext();
|
|
133
|
-
const view = render(HarnessReactiveSameName, { props: { version: 1 } });
|
|
134
|
-
await vi.waitFor(() => expect(registered.length).toBeGreaterThan(0));
|
|
135
|
-
// Three reactive reruns in quick succession, all under the SAME tool
|
|
136
|
-
// name. Without serializing against the previous run's registration
|
|
137
|
-
// settling, a new run's registration attempt can reach the host before
|
|
138
|
-
// it has processed the previous run's abort, producing a host
|
|
139
|
-
// collision — this must never happen.
|
|
140
|
-
await view.rerender({ version: 2 });
|
|
141
|
-
await view.rerender({ version: 3 });
|
|
142
|
-
await view.rerender({ version: 4 });
|
|
143
|
-
await vi.waitFor(() => {
|
|
144
|
-
const live = registered.filter((tool) => !tool.signal?.aborted);
|
|
145
|
-
expect(live).toHaveLength(1);
|
|
146
|
-
expect(live[0]?.name).toBe('harness_reactive_tool');
|
|
147
|
-
});
|
|
148
|
-
expect(liveNames.has('harness_reactive_tool')).toBe(true);
|
|
149
|
-
expect(warnSpy).not.toHaveBeenCalled();
|
|
150
|
-
view.unmount();
|
|
151
|
-
warnSpy.mockRestore();
|
|
152
|
-
});
|
|
153
|
-
it('reports a tool-name collision through its warn path, not as an unhandled rejection (#2613)', async () => {
|
|
154
|
-
const registered = installModelContext();
|
|
155
|
-
// Stand in for whatever already holds the name — a generated model tool,
|
|
156
|
-
// a fixed `smrt_ui_*` tool under a custom prefix, or another mounted
|
|
157
|
-
// component. `registerWebMcpBespokeTool` now throws SYNCHRONOUSLY here,
|
|
158
|
-
// inside this hook's fire-and-forget `register()`, so without the
|
|
159
|
-
// narrowed catch the page would see a global unhandled rejection instead
|
|
160
|
-
// of a diagnostic naming the tool and its owner.
|
|
161
|
-
const held = reserveWebMcpToolNames(['harness_tool_1'], 'generated');
|
|
162
|
-
const warn = vi.spyOn(console, 'warn').mockImplementation(() => { });
|
|
163
|
-
const unhandled = vi.fn();
|
|
164
|
-
window.addEventListener('unhandledrejection', unhandled);
|
|
165
|
-
const view = render(Harness, { props: { version: 1 } });
|
|
166
|
-
await vi.waitFor(() => expect(warn).toHaveBeenCalled());
|
|
167
|
-
// Two macrotask turns is enough for an unhandled rejection to surface.
|
|
168
|
-
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
169
|
-
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
170
|
-
expect(unhandled).not.toHaveBeenCalled();
|
|
171
|
-
expect(registered).toHaveLength(0);
|
|
172
|
-
const [message, name, error] = warn.mock.calls[0];
|
|
173
|
-
expect(message).toContain('bespoke WebMCP tool registration failed');
|
|
174
|
-
expect(name).toBe('harness_tool_1');
|
|
175
|
-
expect(error).toBeInstanceOf(WebMcpToolNameCollisionError);
|
|
176
|
-
expect(error.owner).toBe('generated');
|
|
177
|
-
// The losing registrant strands nothing: the holder keeps the name, and
|
|
178
|
-
// unmounting the component leaves it exactly as it was.
|
|
179
|
-
expect(webMcpToolNameOwner('harness_tool_1')).toBe('generated');
|
|
180
|
-
view.unmount();
|
|
181
|
-
expect(webMcpToolNameOwner('harness_tool_1')).toBe('generated');
|
|
182
|
-
held.release();
|
|
183
|
-
expect(webMcpToolNameOwner('harness_tool_1')).toBeUndefined();
|
|
184
|
-
window.removeEventListener('unhandledrejection', unhandled);
|
|
185
|
-
warn.mockRestore();
|
|
186
|
-
});
|
|
187
|
-
it('still propagates a non-collision synchronous registrar throw', async () => {
|
|
188
|
-
installModelContext();
|
|
189
|
-
// The narrowed catch above must not swallow an authoring error. An
|
|
190
|
-
// invalid `effects` policy is the synchronous throw that already existed.
|
|
191
|
-
expect(() => registerBespokeDirect({
|
|
192
|
-
name: 'harness_tool_1',
|
|
193
|
-
description: 'x',
|
|
194
|
-
inputSchema: { type: 'object' },
|
|
195
|
-
annotations: { readOnlyHint: true },
|
|
196
|
-
execute: () => 'ok',
|
|
197
|
-
}, { effects: ['nonsense'] })).toThrow(/Invalid WebMCP effect/);
|
|
198
|
-
expect(webMcpToolNameOwner('harness_tool_1')).toBeUndefined();
|
|
199
|
-
});
|
|
200
|
-
it('registers a previously-excluded bespoke tool when a Provider policy loosens to permit it (#2599)', async () => {
|
|
201
|
-
const registered = installModelContext();
|
|
202
|
-
const view = render(EffectsReactivity, {
|
|
203
|
-
props: { effects: ['read'] },
|
|
204
|
-
});
|
|
205
|
-
// The bespoke tool's static factory declares `destructiveHint: true` and
|
|
206
|
-
// has no rune dependencies of its own, so under a read-only Provider
|
|
207
|
-
// policy the registrar classifies it destructive and excludes it before
|
|
208
|
-
// it ever reaches document.modelContext.registerTool. Wait for that
|
|
209
|
-
// first evaluation to actually happen under the read-only policy — the
|
|
210
|
-
// registrar is reached through a dynamic import, so without this the
|
|
211
|
-
// policy change below could race ahead of the first evaluation and the
|
|
212
|
-
// test would pass even if the effect never re-ran.
|
|
213
|
-
await vi.waitFor(() => expect(registerBespokeSpy).toHaveBeenCalledTimes(1));
|
|
214
|
-
expect(registerBespokeSpy.mock.calls[0][1]).toEqual({
|
|
215
|
-
effects: ['read'],
|
|
216
|
-
});
|
|
217
|
-
expect(registered).toHaveLength(0);
|
|
218
|
-
// `bespokeContext.effects` is read synchronously at the top of the
|
|
219
|
-
// `$effect` body, so this Provider policy change is tracked as a
|
|
220
|
-
// dependency and re-runs the effect even though the component's own
|
|
221
|
-
// factory never changed: the registrar is consulted again under the
|
|
222
|
-
// loosened policy and the tool newly registers.
|
|
223
|
-
await view.rerender({ effects: ['destructive'] });
|
|
224
|
-
await vi.waitFor(() => expect(registerBespokeSpy).toHaveBeenCalledTimes(2));
|
|
225
|
-
expect(registerBespokeSpy.mock.calls[1][1]).toEqual({
|
|
226
|
-
effects: ['destructive'],
|
|
227
|
-
});
|
|
228
|
-
await vi.waitFor(() => expect(registered.map((tool) => tool.name)).toContain('reactivity_destructive_tool'));
|
|
229
|
-
expect(registered).toHaveLength(1);
|
|
230
|
-
expect(registered[0].signal?.aborted).toBe(false);
|
|
231
|
-
view.unmount();
|
|
232
|
-
expect(registered[0].signal?.aborted).toBe(true);
|
|
233
|
-
});
|
|
234
|
-
});
|