@mcp-b/webmcp-polyfill 5.1.0 → 6.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/LICENSE.webmcp-polyfill +21 -0
- package/README.md +76 -140
- package/dist/index.d.ts +20 -13
- package/dist/index.iife.js +6 -1
- package/dist/index.js +1015 -561
- package/dist/index.js.map +1 -1
- package/package.json +10 -12
- package/dist/schema.d.ts +0 -31
- package/dist/schema.js +0 -274
- package/dist/schema.js.map +0 -1
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 WebMCP polyfill contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,186 +1,122 @@
|
|
|
1
1
|
# @mcp-b/webmcp-polyfill
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
browser transport, and a composed MCP server belong to the MCP-B runtime built
|
|
7
|
-
by `@mcp-b/global`.
|
|
3
|
+
This package is a temporary compatibility distribution of the upstream
|
|
4
|
+
[WebMCP polyfill](https://github.com/webmachinelearning/webmcp-polyfill), distributed
|
|
5
|
+
under the existing MCP-B package name with vendored upstream source.
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
**This package will eventually be removed.** There is no removal date yet. Sites
|
|
8
|
+
using declarative tools should keep this package until the upstream polyfill
|
|
9
|
+
supports them. For other sites, follow the
|
|
10
|
+
[upstream installation instructions](https://github.com/webmachinelearning/webmcp-polyfill#readme)
|
|
11
|
+
when its distribution is available.
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
Until then, this package bundles upstream revision
|
|
14
|
+
`6bf6c57bbaf3d1173d7737cfb79572632d9b7871`. It installs the standard
|
|
15
|
+
`document.modelContext` API when the browser does not provide one, plus a
|
|
16
|
+
temporary declarative tools layer. The upstream implementation and types are the
|
|
17
|
+
source of truth for the core runtime. Use [`@mcp-b/global`](../global/README.md)
|
|
18
|
+
for transports, prompts, resources, or MCP `outputSchema` support; MCP-B schema
|
|
19
|
+
helpers live in `@mcp-b/webmcp-ts-sdk/schema`.
|
|
20
|
+
|
|
21
|
+
The [package reference](https://docs.mcp-b.ai/packages/webmcp-polyfill/reference)
|
|
22
|
+
documents the installer, the declarative layer, and the browser baseline.
|
|
23
|
+
|
|
24
|
+
## Use the compatibility package
|
|
13
25
|
|
|
14
26
|
```bash
|
|
15
27
|
pnpm add @mcp-b/webmcp-polyfill
|
|
16
28
|
```
|
|
17
29
|
|
|
18
|
-
##
|
|
30
|
+
## Install the polyfill
|
|
19
31
|
|
|
20
|
-
|
|
32
|
+
Call `installWebMCP()` before your app registers tools:
|
|
21
33
|
|
|
22
34
|
```ts
|
|
23
|
-
import {
|
|
24
|
-
|
|
25
|
-
initializeWebMCPPolyfill();
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
The standalone IIFE initializes when loaded:
|
|
29
|
-
|
|
30
|
-
```html
|
|
31
|
-
<script src="https://unpkg.com/@mcp-b/webmcp-polyfill@latest/dist/index.iife.js"></script>
|
|
32
|
-
```
|
|
35
|
+
import { installWebMCP } from '@mcp-b/webmcp-polyfill';
|
|
33
36
|
|
|
34
|
-
|
|
35
|
-
deprecated Chromium testing surface:
|
|
37
|
+
installWebMCP();
|
|
36
38
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
window.__webMCPPolyfillOptions = { installTestingShim: true };
|
|
40
|
-
</script>
|
|
39
|
+
const context = document.modelContext;
|
|
40
|
+
if (!context) throw new Error('WebMCP is unavailable');
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
The call is idempotent and preserves an existing native context. It does
|
|
44
|
+
nothing when no browser document is available, on an insecure page, or on
|
|
45
|
+
engines older than Chrome 126, Firefox 126, or Safari 18, so
|
|
46
|
+
`if (!document.modelContext)` remains a valid feature check. The upstream
|
|
47
|
+
runtime has no uninstall operation and does not provide the deprecated
|
|
48
|
+
`navigator.modelContext` alias.
|
|
44
49
|
|
|
45
|
-
|
|
46
|
-
the document and its open shadow roots and registers them as tools. It derives
|
|
47
|
-
input schemas from native named controls and keeps registrations synchronized
|
|
48
|
-
with DOM changes.
|
|
50
|
+
For a script tag, load the IIFE before registering tools:
|
|
49
51
|
|
|
50
52
|
```html
|
|
51
|
-
<
|
|
52
|
-
<input name="query" required toolparamdescription="Words to match" />
|
|
53
|
-
<button type="submit">Search</button>
|
|
54
|
-
</form>
|
|
55
|
-
|
|
56
|
-
<script>
|
|
57
|
-
document.querySelector('form').addEventListener('submit', (event) => {
|
|
58
|
-
if (!event.agentInvoked) return;
|
|
59
|
-
|
|
60
|
-
event.preventDefault();
|
|
61
|
-
event.respondWith(Promise.resolve({ matches: [] }));
|
|
62
|
-
});
|
|
63
|
-
</script>
|
|
53
|
+
<script src="https://unpkg.com/@mcp-b/webmcp-polyfill@6/dist/index.iife.js"></script>
|
|
64
54
|
```
|
|
65
55
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
`requestSubmit()`. Agent submissions expose `SubmitEvent.agentInvoked` and
|
|
69
|
-
`SubmitEvent.respondWith()`.
|
|
70
|
-
|
|
71
|
-
CI checks the standalone polyfill against the upstream
|
|
72
|
-
[declarative Web Platform Tests](https://github.com/web-platform-tests/wpt/tree/master/webmcp/declarative).
|
|
73
|
-
Repository-specific browser tests cover the polyfill and composed MCP-B runtime.
|
|
74
|
-
See Chrome's
|
|
75
|
-
[declarative API documentation](https://developer.chrome.com/docs/ai/webmcp/declarative-api)
|
|
76
|
-
for the evolving API. The Community Group draft's
|
|
77
|
-
[declarative section](https://webmachinelearning.github.io/webmcp/#declarative-webmcp)
|
|
78
|
-
is still incomplete.
|
|
56
|
+
The IIFE calls `installWebMCP()` automatically and exposes it as
|
|
57
|
+
`WebMCPPolyfill.installWebMCP`.
|
|
79
58
|
|
|
80
59
|
## Register a tool
|
|
81
60
|
|
|
61
|
+
Tool registrations follow the upstream WebMCP API. Pass an `AbortSignal` when
|
|
62
|
+
the registration has a lifecycle:
|
|
63
|
+
|
|
82
64
|
```ts
|
|
83
65
|
const registration = new AbortController();
|
|
84
66
|
|
|
85
|
-
await
|
|
67
|
+
await context.registerTool(
|
|
86
68
|
{
|
|
87
|
-
name: '
|
|
88
|
-
description: '
|
|
89
|
-
|
|
90
|
-
|
|
69
|
+
name: 'page-title',
|
|
70
|
+
description: 'Get the title of this page',
|
|
71
|
+
execute() {
|
|
72
|
+
return { title: document.title };
|
|
73
|
+
},
|
|
91
74
|
},
|
|
92
75
|
{ signal: registration.signal }
|
|
93
76
|
);
|
|
94
77
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
`registerTool()` resolves after the local `toolchange` notification. Duplicate
|
|
100
|
-
names, invalid descriptors, aborted registrations, and non-serializable schemas
|
|
101
|
-
reject the returned promise.
|
|
102
|
-
|
|
103
|
-
## Discover and execute
|
|
104
|
-
|
|
105
|
-
```ts
|
|
106
|
-
import type { ChromeModelContext } from '@mcp-b/webmcp-types';
|
|
107
|
-
|
|
108
|
-
const context = document.modelContext as ChromeModelContext;
|
|
109
|
-
const [tool] = await context.getTools();
|
|
110
|
-
|
|
111
|
-
if (tool && context.executeTool) {
|
|
112
|
-
const result = await context.executeTool(tool, JSON.stringify({}));
|
|
78
|
+
const tools = await context.getTools();
|
|
79
|
+
const tool = tools.find((item) => item.name === 'page-title');
|
|
80
|
+
if (tool) {
|
|
81
|
+
const result = await context.executeTool(tool);
|
|
113
82
|
console.log(result);
|
|
114
83
|
}
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
`executeTool()` is a Chromium extension, not part of the core `ModelContext`
|
|
118
|
-
interface. Feature-detect it.
|
|
119
|
-
|
|
120
|
-
The local polyfill cannot securely implement cross-document discovery or
|
|
121
|
-
exposure. Non-empty `fromOrigins` and `exposedTo` arrays reject with
|
|
122
|
-
`NotSupportedError`; use native WebMCP for those capabilities. Where the host
|
|
123
|
-
browser exposes the `tools` Permissions Policy, the polyfill enforces it. In
|
|
124
|
-
browsers without that policy feature, cross-origin frames fail closed.
|
|
125
|
-
|
|
126
|
-
## API
|
|
127
|
-
|
|
128
|
-
### `initializeWebMCPPolyfill(options?)`
|
|
129
84
|
|
|
130
|
-
|
|
131
|
-
absent. It also keeps `navigator.modelContext` as the repository's deprecated
|
|
132
|
-
compatibility alias.
|
|
133
|
-
|
|
134
|
-
```ts
|
|
135
|
-
interface WebMCPPolyfillInitOptions {
|
|
136
|
-
installTestingShim?: boolean; // default: false
|
|
137
|
-
}
|
|
85
|
+
registration.abort();
|
|
138
86
|
```
|
|
139
87
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
### `cleanupWebMCPPolyfill()`
|
|
144
|
-
|
|
145
|
-
Removes registrations, detaches their abort listeners, and restores every
|
|
146
|
-
property descriptor changed by initialization.
|
|
147
|
-
|
|
148
|
-
## Testing shim
|
|
88
|
+
See the [WebMCP draft](https://webmachinelearning.github.io/webmcp/) and the
|
|
89
|
+
[upstream polyfill](https://github.com/webmachinelearning/webmcp-polyfill) for
|
|
90
|
+
the standard API and implementation details.
|
|
149
91
|
|
|
150
|
-
|
|
151
|
-
`navigator.modelContextTesting` compatibility surface when it is absent:
|
|
92
|
+
## Declare a tool in HTML
|
|
152
93
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
94
|
+
The declarative layer registers a tool for each form with `toolname` and
|
|
95
|
+
`tooldescription` in the document and its open shadow roots. The input schema
|
|
96
|
+
comes from the form's named controls.
|
|
156
97
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
The `@mcp-b/webmcp-polyfill/schema` entry owns shared browser-runtime adapters
|
|
163
|
-
used by MCP-B packages. `normalizeInputSchema()` accepts plain JSON Schema and
|
|
164
|
-
Standard Schema v1 implementations that expose `~standard.jsonSchema.input()`.
|
|
165
|
-
This conversion is an MCP-B adapter feature; the strict WebMCP registration
|
|
166
|
-
boundary itself accepts JSON Schema.
|
|
98
|
+
```html
|
|
99
|
+
<form toolname="search_catalog" tooldescription="Search the product catalog" toolautosubmit>
|
|
100
|
+
<input name="query" required toolparamdescription="Words to match" />
|
|
101
|
+
<button type="submit">Search</button>
|
|
102
|
+
</form>
|
|
167
103
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
104
|
+
<script>
|
|
105
|
+
document.querySelector('form').addEventListener('submit', (event) => {
|
|
106
|
+
if (!event.agentInvoked) return;
|
|
171
107
|
|
|
172
|
-
|
|
108
|
+
event.preventDefault();
|
|
109
|
+
event.respondWith(Promise.resolve({ matches: [] }));
|
|
110
|
+
});
|
|
111
|
+
</script>
|
|
112
|
+
```
|
|
173
113
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
- Declarative forms do not emulate native CSS tool-state pseudo-classes,
|
|
180
|
-
`toolcancel`, cross-navigation responses, file inputs, or custom
|
|
181
|
-
form-associated elements.
|
|
182
|
-
- Closed shadow roots cannot be inspected.
|
|
114
|
+
An invocation fills the controls and either submits the form (`toolautosubmit`)
|
|
115
|
+
or focuses its submit button for the user. The
|
|
116
|
+
[declarative tools reference](https://docs.mcp-b.ai/packages/webmcp-polyfill/reference#declarative-tools)
|
|
117
|
+
covers results, lifecycle events, cancellation, failures, and native browser
|
|
118
|
+
hooks.
|
|
183
119
|
|
|
184
120
|
## License
|
|
185
121
|
|
|
186
|
-
MIT
|
|
122
|
+
The package includes the upstream polyfill's MIT license notice.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,17 +1,24 @@
|
|
|
1
|
+
import { WebMCP } from "webmcp-types";
|
|
2
|
+
|
|
1
3
|
//#region src/index.d.ts
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Installs upstream WebMCP and the temporary declarative tools layer.
|
|
6
|
+
* Engines missing an API the vendored core calls are left untouched: upstream defines
|
|
7
|
+
* the document getter before it constructs the context, so a failed construction would
|
|
8
|
+
* leave `document.modelContext` throwing.
|
|
9
|
+
*/
|
|
10
|
+
declare function installWebMCP(): void;
|
|
11
|
+
declare global {
|
|
12
|
+
interface SubmitEvent {
|
|
13
|
+
readonly agentInvoked?: boolean;
|
|
14
|
+
respondWith?(agentResponse: Promise<unknown>): void;
|
|
15
|
+
}
|
|
16
|
+
/** Web IDL interface object used for branding and `instanceof`. */
|
|
17
|
+
var ModelContext: (Function & {
|
|
18
|
+
readonly prototype: WebMCP.ModelContext;
|
|
19
|
+
[Symbol.hasInstance](value: Parameters<Function[typeof Symbol.hasInstance]>[0]): value is WebMCP.ModelContext;
|
|
20
|
+
}) | undefined;
|
|
12
21
|
}
|
|
13
|
-
declare function initializeWebMCPPolyfill(options?: WebMCPPolyfillInitOptions): void;
|
|
14
|
-
declare function cleanupWebMCPPolyfill(): void;
|
|
15
22
|
//#endregion
|
|
16
|
-
export {
|
|
23
|
+
export { type WebMCP, installWebMCP };
|
|
17
24
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.iife.js
CHANGED
|
@@ -1 +1,6 @@
|
|
|
1
|
-
var WebMCPPolyfill=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});let t=`Tool was executed but the invocation failed. For example, the script function threw an error`,n=/^[A-Za-z0-9_.-]{1,128}$/u;function r(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function i(e){if(typeof e==`symbol`)throw TypeError(`Symbol values cannot be converted to a DOMString`);return String(e)}function a(e){let t=Reflect.get(e,`name`),n=Reflect.get(e,`description`),a=Reflect.get(e,`title`);if(t===void 0)throw TypeError(`Tool "name" is required`);if(n===void 0)throw TypeError(`Tool "description" is required`);let o=Reflect.get(e,`annotations`),s=r(o)?o:{},c=Reflect.get(e,`inputSchema`),l=Reflect.get(e,`outputSchema`),u=Reflect.get(e,`execute`);return{name:i(t),...a===void 0?{}:{title:i(a).toWellFormed()},description:i(n),...c===void 0?{}:{inputSchema:c},...l===void 0?{}:{outputSchema:l},execute:u,...o===void 0?{}:{annotations:{...s.title===void 0?{}:{title:i(s.title).toWellFormed()},readOnlyHint:!!s.readOnlyHint,...s.destructiveHint===void 0?{}:{destructiveHint:!!s.destructiveHint},...s.idempotentHint===void 0?{}:{idempotentHint:!!s.idempotentHint},...s.openWorldHint===void 0?{}:{openWorldHint:!!s.openWorldHint},untrustedContentHint:!!s.untrustedContentHint}}}}function o(e){return new DOMException(e,`UnknownError`)}function s(e){return o(e instanceof Error?`${t}: ${e.message}`:t)}function c(e){return new DOMException(e,`InvalidStateError`)}function l(e){if(e.name===``)throw c(`Tool "name" must be a non-empty string`);if(typeof e.name!=`string`||!n.test(e.name))throw c(`Tool "name" must be 1–128 characters and contain only ASCII alphanumeric, underscore, hyphen, or period`);if(typeof e.description!=`string`||e.description.length===0)throw c(`Tool "description" must be a non-empty string`);if(typeof e.execute!=`function`)throw TypeError(`Tool "execute" must be a function`)}function u(e){return{readOnlyHint:e.readOnlyHint??!1,untrustedContentHint:e.untrustedContentHint??!1}}function d(e){try{let t=JSON.parse(e);if(Array.isArray(t)||r(t))return t}catch{}throw o(`Failed to parse input arguments`)}function f(e){if(typeof e==`object`&&e||typeof e==`function`)try{let t=JSON.stringify(e);if(t)return t}catch{}return String(e)||`Operation succeeded`}function p(e,t,n=()=>t?.reason){return t?t.aborted?Promise.reject(n()):new Promise((r,i)=>{let a=()=>{o(),i(n())},o=()=>t.removeEventListener(`abort`,a);t.addEventListener(`abort`,a,{once:!0}),e.then(e=>{o(),r(e)},e=>{o(),i(e)})}):e}function m(e){let t=e.origin===`null`?e:new URL(e.origin),n=t.protocol;if([`https:`,`wss:`,`file:`,`chrome-extension:`,`moz-extension:`].includes(n))return!0;let r=t.hostname.toLowerCase(),i=r.split(`.`),a=i.length===4&&i.every(e=>/^\d{1,3}$/u.test(e)&&Number(e)<=255)&&Number(i[0])===127;return r===`::1`||r===`[::1]`||r===`localhost`||r===`localhost.`||r.endsWith(`.localhost`)||r.endsWith(`.localhost.`)||a}function h(e){for(let t of e??[]){let e;try{e=new URL(t)}catch{throw new DOMException(`Invalid or untrustworthy origin: ${String(t)}`,`SecurityError`)}if(!m(e))throw new DOMException(`Invalid or untrustworthy origin: ${t}`,`SecurityError`)}}function g(e){if(ee(),!e)return;let t=e.defaultView?.DOMException??DOMException,n=!1;try{let t=e.defaultView;n=!!(t&&t.document===e)}catch{}if(!n)throw new t(`The associated document is not fully active`,`InvalidStateError`);let r=Reflect.get(e,`permissionsPolicy`)??Reflect.get(e,`featurePolicy`);if(r&&typeof r==`object`){let e=Reflect.get(r,`features`),n=Reflect.get(r,`allowsFeature`);if(typeof e==`function`&&typeof n==`function`){let i=Reflect.apply(e,r,[]);if(Array.isArray(i)&&i.includes(`tools`)){if(Reflect.apply(n,r,[`tools`])===!0)return;throw new t(`WebMCP is disabled by Permissions Policy`,`NotAllowedError`)}}}let i=e.defaultView;if(!(!i||i.parent===i)){try{i.parent.document;return}catch{}throw new t(`WebMCP in cross-origin frames requires native Permissions Policy support`,`NotAllowedError`)}}function ee(){if(globalThis.originAgentCluster===!1&&globalThis.location?.protocol!==`file:`)throw new DOMException(``,`SecurityError`)}function te(e){try{if(new URL(String(e)).origin!==`null`)return}catch{}throw new DOMException(`Unsupported tool origin: ${String(e)}`,`NotSupportedError`)}function ne(e){if(e===null||typeof e!=`object`&&typeof e!=`function`)throw TypeError(`inputSchema must be an object`);let t=JSON.stringify(e);if(t===void 0)throw TypeError(`inputSchema must be JSON-serializable`);return t}let _=new WeakSet,v=new WeakMap,y=new WeakMap;function b(e){return e.isTrusted&&(_.has(e)||e.eventPhase!==Event.NONE&&e.target instanceof HTMLFormElement&&y.has(e.target))}function re(e,t){if(!b(e))throw new DOMException(`respondWith() is only available during an agent-invoked submit event`,`InvalidStateError`);if(!e.defaultPrevented)throw new DOMException(`respondWith() requires preventDefault() during an agent-invoked submit event`,`InvalidStateError`);if(e.eventPhase===Event.NONE)throw new DOMException(`respondWith() is only available while the submit event is being dispatched`,`InvalidStateError`);_.add(e);let n=Promise.resolve(t);v.set(e,n),e.target instanceof HTMLFormElement&&y.get(e.target)?.respond(e)}let x=new Set([`email`,`password`,`search`,`tel`,`text`,`url`]),ie=new Set([...x,`date`,`datetime-local`,`month`,`number`,`time`,`week`]);function S(e){return e instanceof HTMLInputElement||e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement}function C(e){return Reflect.get(HTMLFormElement.prototype,`elements`,e)}function w(e,t){return Reflect.apply(Element.prototype.getAttribute,e,[t])}function T(e,t){return Reflect.apply(Element.prototype.hasAttribute,e,[t])}function ae(e){return Reflect.get(Node.prototype,`isConnected`,e)}function oe(e){return Reflect.get(Element.prototype,`shadowRoot`,e)}function se(e){return Reflect.apply(HTMLFormElement.prototype.checkValidity,e,[])}function ce(e,t){Reflect.apply(HTMLFormElement.prototype.requestSubmit,e,t?[t]:[])}function le(e){return[...C(e)].filter(e=>S(e)&&!e.matches(`:disabled`)&&!(`readOnly`in e&&e.readOnly&&(e instanceof HTMLTextAreaElement||ie.has(e.type))))}function E(e){let t=new Map;for(let n of le(e)){let e=n.name.trim(),r=t.get(e);r?r.push(n):t.set(e,[n])}return t}function D(e){return[...e.labels??[]].map(e=>{let t=e.cloneNode(!0);return t instanceof HTMLElement?(t.querySelectorAll(`button, input, meter, output, progress, select, textarea`).forEach(e=>e.remove()),t.textContent?.trim()??``):``}).filter(Boolean).join(`; `)}function ue(e,t){for(let n=t[0]?.parentElement;n&&n!==e;n=n.parentElement)if(n instanceof HTMLFieldSetElement&&t.every(e=>n.contains(e)))return n}function de(e,t){if(t.length===1){let e=t[0];return e&&(e.getAttribute(`toolparamdescription`)||D(e)||e.getAttribute(`aria-description`))||void 0}return ue(e,t)?.getAttribute(`toolparamdescription`)||void 0}function O(e,t,n,r){let i=de(t,n),a=i&&r?`${i} (${r})`:i||r;return a?{...e,description:a}:e}function k(e,t){let n=e.getAttribute(t);if(n===null||n.trim()===``)return;let r=Number(n);return Number.isFinite(r)?r:void 0}function fe(e,t){let n=e/t;return Math.abs(n-Math.round(n))<2**-52*16}function A(e){let t=e.getAttribute(`pattern`);if(t!==null)try{return new RegExp(t,`v`),t}catch{return}}function j(e,t=!0){let n={type:`number`},r=k(e,`min`),i=k(e,`max`);r!==void 0&&(n.minimum=r),i!==void 0&&(n.maximum=i);let a=e.getAttribute(`step`);if(a!==`any`){let t=a===null||a===``?1:Number(a),i=Number.isFinite(t)&&t>0?t:1,o=Number(e.getAttribute(`value`));fe(r??(Number.isFinite(o)?o:0),i)&&(n.multipleOf=i)}let o=t?A(e):void 0;return o!==void 0&&(n.pattern=o),n}function M(e,t){let n=e.getAttribute(`step`),r=n===null||n===``?60:Number(n),i=Number.isFinite(r)&&r>0?r:60;return i<1?`${t}(:[0-5][0-9](\\.[0-9]{1,3})?)?$`:i<60?`${t}(:[0-5][0-9])?$`:`${t}$`}function pe(e){return{anyOf:e.map(e=>({type:`string`,const:e.value,title:e.textContent??``})),enum:e.map(e=>e.value)}}function N(e){return{anyOf:e.map(e=>{let t=D(e);return{type:`string`,const:e.value,...t?{title:t}:{}}}),enum:e.map(e=>e.value)}}function P(e,t){let n=t[0];if(n){if(t.length>1)return t.every(e=>e instanceof HTMLInputElement)?t.every(e=>e.type===`checkbox`)?O({type:`array`,items:{type:`string`,...N(t)},uniqueItems:!0},e,t):t.every(e=>e.type===`radio`)?O({type:`string`,...N(t)},e,t):void 0:void 0;if(n instanceof HTMLTextAreaElement)return O({type:`string`},e,t);if(n instanceof HTMLSelectElement){let r=pe([...n.options]);return O(n.multiple?{type:`array`,items:{type:`string`,...r},uniqueItems:!0}:{type:`string`,...r},e,t)}if(x.has(n.type)){let r={type:`string`},i=A(n);return i!==void 0&&(r.pattern=i),O(r,e,t)}if(n.type===`hidden`)return n.getAttribute(`toolparamdescription`)?O({type:`string`},e,t):void 0;if(n.type===`number`)return O(j(n),e,t);if(n.type===`range`){let r=j(n,!1);return r.minimum??=0,r.maximum??=100,O(r,e,t)}if(n.type===`checkbox`)return O({type:`boolean`},e,t);if(n.type===`radio`)return O({type:`string`,...N([n])},e,t);if(n.type===`date`)return O({type:`string`,format:`date`},e,t,`Dates MUST be provided in 'YYYY-MM-DD' format.`);if(n.type===`month`)return O({type:`string`,format:`^[0-9]{4}-(0[1-9]|1[0-2])$`},e,t);if(n.type===`week`)return O({type:`string`,format:`^[0-9]{4}-W(0[1-9]|[1-4][0-9]|5[0-3])$`},e,t);if(n.type===`time`)return O({type:`string`,format:M(n,`^([01][0-9]|2[0-3]):[0-5][0-9]`)},e,t);if(n.type===`datetime-local`)return O({type:`string`,format:M(n,`^[0-9]{4}-(0[1-9]|1[0-2])-[0-9]{2}T([01][0-9]|2[0-3]):[0-5][0-9]`)},e,t);if(n.type===`color`)return O({type:`string`,format:`^#[0-9a-zA-Z]{6}$`},e,t)}}function me(e){let t={},n=[];for(let[r,i]of E(e)){if(!r)continue;let a=P(e,i);a&&(Object.defineProperty(t,r,{configurable:!0,enumerable:!0,value:a,writable:!0}),i.some(e=>e.required)&&n.push(r))}return{type:`object`,properties:t,required:n}}function he(e){return{name:w(e,`toolname`)??``,title:w(e,`tooltitle`)??``,description:w(e,`tooldescription`)??``,inputSchema:me(e),autosubmit:T(e,`toolautosubmit`)}}function F(e){if(typeof e==`string`||typeof e==`boolean`||typeof e==`number`&&Number.isFinite(e))return String(e)}function I(e){if(typeof e==`boolean`)return e;if(typeof e==`number`&&Number.isInteger(e))return e!==0;if(typeof e==`string`){if(e===`1`||e.toLowerCase()===`true`)return!0;if(e===`0`||e.toLowerCase()===`false`)return!1}}function L(e,t){if(!Array.isArray(e))return!1;let n=new Set(t);for(let t of e){let e=F(t);if(e===void 0||!n.delete(e))return!1}return!0}function ge(e,t){if(t===``)return e.type!==`number`&&e.type!==`range`;let n=e.ownerDocument.createElement(`input`);return n.type=e.type,n.value=t,n.value!==``}function _e(e,t,n){let r=t[0];if(!r||!P(e,t))return!1;if(t.length>1){if(!t.every(e=>e instanceof HTMLInputElement))return!1;if(t.every(e=>e.type===`checkbox`))return L(n,new Set(t.map(e=>e.value)));if(t.every(e=>e.type===`radio`)){let e=F(n);return e!==void 0&&t.some(t=>t.value===e)}return!1}if(r instanceof HTMLSelectElement){let e=new Set([...r.options].map(e=>e.value));if(r.multiple)return L(n,e);let t=F(n);return t!==void 0&&e.has(t)}if(r instanceof HTMLTextAreaElement)return F(n)!==void 0;if(r.type===`checkbox`)return I(n)!==void 0;if(r.type===`radio`){let e=F(n);return e!==void 0&&r.value===e}let i=F(n);return i!==void 0&&ge(r,i)}function R(e){e.dispatchEvent(new Event(`input`,{bubbles:!0,composed:!0})),e.dispatchEvent(new Event(`change`,{bubbles:!0}))}function ve(e,t){let n=e instanceof HTMLInputElement?HTMLInputElement.prototype:HTMLTextAreaElement.prototype;Object.getOwnPropertyDescriptor(n,`value`)?.set?.call(e,t)}function z(e,t){Object.getOwnPropertyDescriptor(HTMLInputElement.prototype,`checked`)?.set?.call(e,t)}function ye(e,t){let n=e[0];if(!n)return;if(e.length>1&&e.every(e=>e instanceof HTMLInputElement)){if(e.every(e=>e.type===`checkbox`)&&Array.isArray(t)){let n=new Set(t.map(F));for(let t of e){let e=n.has(t.value);t.checked!==e&&(z(t,e),R(t))}return}let n=F(t),r=e.find(e=>e.value===n);r&&!r.checked&&(z(r,!0),R(r));return}if(n instanceof HTMLSelectElement){if(n.multiple&&Array.isArray(t)){let e=new Set(t.map(F)),r=!1;for(let t of n.options){let n=e.has(t.value);t.selected!==n&&(t.selected=n,r=!0)}r&&R(n);return}let e=F(t);e!==void 0&&n.value!==e&&(n.value=e,R(n));return}if(n instanceof HTMLInputElement&&n.type===`checkbox`){let e=I(t);e!==void 0&&n.checked!==e&&(z(n,e),R(n));return}if(n instanceof HTMLInputElement&&n.type===`radio`){F(t)===n.value&&!n.checked&&(z(n,!0),R(n));return}let r=F(t);r!==void 0&&n.value!==r&&(ve(n,r),R(n))}function be(e,t){if(Array.isArray(t))throw TypeError(`Declarative tool input must be an object`);let n=E(e);for(let[r,i]of Object.entries(t)){let t=n.get(r);if(!t||!_e(e,t,i))throw TypeError(`Invalid value for declarative form parameter "${r}"`)}for(let[e,r]of Object.entries(t))ye(n.get(e)??[],r)}function xe(e){return[...C(e)].find(e=>!e.matches(`:disabled`)&&(e instanceof HTMLButtonElement&&e.type===`submit`||e instanceof HTMLInputElement&&[`image`,`submit`].includes(e.type)))}function Se(e){let t=[...C(e)].filter(e=>S(e)&&e.willValidate&&!e.validity.valid).map(e=>`${e.name.trim()||`{unknown}`}: ${e.validationMessage}`).join(`. `);return new DOMException(`Form validation failed: ${t}`,`UnknownError`)}function B(e){let t=new Event(`toolactivated`);return Object.defineProperty(t,"toolName",{enumerable:!0,value:e}),t}function Ce(e,t,n,r){let{form:i}=e;return e.cancelPending?.(new DOMException(`Tool execution cancelled`,`UnknownError`)),new Promise((a,o)=>{let s=!1,c=()=>{Reflect.apply(EventTarget.prototype.removeEventListener,i,[`invalid`,f,!0]),y.delete(i),e.cancelPending===u&&delete e.cancelPending},l=e=>{s||(s=!0,c(),e())},u=e=>l(()=>o(e)),d=e=>{e.then(e=>l(()=>a(e)),e=>l(()=>o(e)))},f=e=>{e.isTrusted&&queueMicrotask(()=>{se(i)||u(Se(i))})};if(y.set(i,{complete(e){queueMicrotask(()=>{let t=v.get(e);t?d(t):e.defaultPrevented?u(new DOMException(`preventDefault() requires respondWith()`,`UnknownError`)):l(()=>a(void 0))})},direct(){l(()=>a(void 0))},respond(e){queueMicrotask(()=>{let t=v.get(e);t&&d(t)})}}),e.cancelPending=u,Reflect.apply(EventTarget.prototype.addEventListener,i,[`invalid`,f,!0]),!n){r?.focus(),window.dispatchEvent(B(t));return}try{ce(i,r),window.dispatchEvent(B(t))}catch(e){u(e)}})}function we(e,t){let n=!0,r=new Map,i=new Map,a=new Map,o=e=>{if(!(e instanceof SubmitEvent)||!e.isTrusted||!(e.target instanceof HTMLFormElement))return;let t=y.get(e.target);t&&(_.add(e),t.complete(e))},s=e=>{if(!e.isTrusted||!(e.target instanceof HTMLFormElement))return;let t=e.target;queueMicrotask(()=>{e.defaultPrevented||r.get(t)?.cancelPending?.(new DOMException(`Tool execution cancelled by form reset`,`UnknownError`))})};function c(e){a.get(e)?.disconnect(),a.delete(e),e.removeEventListener(`reset`,s,!0),e.removeEventListener(`submit`,o,!0)}function l(e){if(a.has(e))return;let t=new MutationObserver(u);a.set(e,t),t.observe(e,{attributes:!0,characterData:!0,childList:!0,subtree:!0}),e.addEventListener(`reset`,s,!0),e.addEventListener(`submit`,o,!0)}function u(){l(e);for(let e of a.keys())e instanceof ShadowRoot&&!Reflect.get(Node.prototype,`isConnected`,e.host)&&c(e);let n=new Set,o=new Map,s=new Map;for(let e of a.keys())for(let t of e.querySelectorAll(`*`)){let e=oe(t);if(e&&l(e),!(t instanceof HTMLFormElement)||!T(t,`toolname`)||!T(t,`tooldescription`)||!ae(t))continue;let r=t;n.add(r);let a=he(r),c=JSON.stringify(a),u=i.get(r);if(u===c)continue;let d=u!==void 0;i.delete(r);let f=s.get(a.name);if(f&&!d){i.set(r,c);continue}if(f){let e=o.get(f);e&&(i.set(f,e.fingerprint),o.delete(f))}s.set(a.name,r),o.set(r,{definition:a,fingerprint:c})}for(let e of i.keys())n.has(e)||i.delete(e);for(let[e,t]of r)o.get(e)?.fingerprint!==t.fingerprint&&(t.cancelPending?.(new DOMException(`Tool execution cancelled because its form changed`,`UnknownError`)),t.controller.abort(),r.delete(e));for(let[e,{definition:n,fingerprint:i}]of o){if(r.has(e))continue;let a=new AbortController,o={controller:a,fingerprint:i,form:e};r.set(e,o),t.registerTool({name:n.name,title:n.title,description:n.description,inputSchema:n.inputSchema,execute(t){let r=xe(e);if(!n.autosubmit&&!r)throw new DOMException(`A declarative form without toolautosubmit requires a submit button`,`UnknownError`);return be(e,t),Ce(o,n.name,n.autosubmit,r)}},{signal:a.signal}).catch(e=>{a.abort(),e?.name!==`AbortError`&&console.error(`[webmcp] declarative form tool "${n.name}" was not registered:`,e)})}}let d=()=>{},f=e.defaultView?.Element.prototype,p=f?Object.getOwnPropertyDescriptor(f,`attachShadow`):void 0;if(f&&p?.configurable){let t=f.attachShadow,r=function(r){let i=t.call(this,r);return n&&i.mode===`open`&&Reflect.get(Node.prototype,`ownerDocument`,this)===e&&Reflect.get(Node.prototype,`isConnected`,this)&&l(i),i};Object.defineProperty(f,"attachShadow",{...p,value:r}),d=()=>{f.attachShadow===r&&Object.defineProperty(f,"attachShadow",p)}}let m=()=>{},h=e.defaultView?.HTMLFormElement.prototype,g=h?Object.getOwnPropertyDescriptor(h,`submit`):void 0;if(h&&g?.configurable){let e=h.submit,t=function(){e.call(this),n&&y.get(this)?.direct()};Object.defineProperty(h,"submit",{...g,value:t}),m=()=>{h.submit===t&&Object.defineProperty(h,"submit",g)}}return u(),()=>{n=!1,m(),d();for(let e of a.keys())c(e);i.clear();for(let e of r.values())e.cancelPending?.(new DOMException(`Tool execution cancelled`,`UnknownError`)),e.controller.abort();r.clear()}}let V=Symbol(`registeredInputSchema`),H=Symbol(`registrationSignal`),U=Symbol(`registrationAbort`),W=[],G=null,K=null;function q(){return typeof globalThis.origin==`string`?globalThis.origin:globalThis.location?.origin??``}function J(e,t,n){let r=Object.getOwnPropertyDescriptor(e,t);try{Object.defineProperty(e,t,n)}catch(e){throw $(),e}W.push({target:e,key:t,previous:r})}var Y=class extends EventTarget{#e=new Map;#t=null;#n=null;#r=e=>{this.#n?.call(this,e)};#i;#a;constructor(e){super(),this.#a=e,this.#i=e?.defaultView?.DOMException??DOMException,Object.defineProperty(this,"__isWebMCPPolyfill",{value:!0,enumerable:!1,writable:!1,configurable:!1})}get ontoolchange(){return this.#n}set ontoolchange(e){let t=typeof e==`function`?e:null;if(t===null){this.#n=null,super.removeEventListener(`toolchange`,this.#r);return}this.#n===null&&super.addEventListener(`toolchange`,this.#r),this.#n=t}async registerTool(e,t={}){g(this.#a);let n=t?.signal,r=Ee(e,this.#e);if(n?.throwIfAborted(),h(t?.exposedTo),n?.throwIfAborted(),t?.exposedTo?.length)throw new this.#i(`Cross-document tool exposure requires native WebMCP`,`NotSupportedError`);if(this.#e.set(r.name,r),n){let e=()=>{this.#o(r.name,r)&&this.#c()};r[H]=n,r[U]=e,n.addEventListener(`abort`,e,{once:!0})}if(await this.#c(),n?.aborted)throw n.reason}async getTools(e={}){if(g(this.#a),h(e?.fromOrigins),e?.fromOrigins?.length)throw new this.#i(`Cross-document tool discovery requires native WebMCP`,`NotSupportedError`);let t=[...this.#e.values()].map(e=>{let t=e[V],n=t===void 0?void 0:JSON.parse(t);return{name:e.name,title:e.title??``,description:e.description,...r(n)?{inputSchema:n}:{},origin:q(),window:globalThis.window,...e.annotations?{annotations:u(e.annotations)}:{}}}).sort((e,t)=>e.name<t.name?-1:+(e.name>t.name));return await new Promise(e=>setTimeout(e,0)),t}async executeTool(e,t,n={}){if(g(this.#a),typeof e!=`object`||!e)throw TypeError(`RegisteredTool must be an object`);for(let t of[`name`,`description`,`window`,`origin`])if(!(t in e))throw TypeError(`RegisteredTool.${t} is required`);if(te(e.origin),e.window!==globalThis.window||e.origin!==q())throw o(`Tool not found: ${e.name}`);return this.#s(e.name,t,n)}static getTestingShim(e){return e.#t??=new Te(e),e.#t}static getToolInfos(e){return[...e.#e.values()].map(e=>({name:e.name,description:e.description,...e[V]===void 0?{}:{inputSchema:e[V]}}))}static executeToolForTesting(e,t,n,r){return g(e.#a),e.#s(t,n,r)}static dispose(e){for(let t of e.#e.keys())e.#o(t);e.ontoolchange=null,e.#t?.dispose()}#o(e,t){let n=this.#e.get(e);if(!n||t&&n!==t)return!1;let r=n[H],i=n[U];return r&&i&&r.removeEventListener(`abort`,i),this.#e.delete(e)}async#s(e,t,n){n?.signal?.throwIfAborted();let r=this.#e.get(e);if(!r)throw o(`Tool not found: ${e}`);let i=d(t);if(n?.signal?.throwIfAborted(),r[H]?.aborted)throw o(`Tool unregistered`);let a;try{let e=r[H];a=await p(p(Promise.resolve(r.execute(i)),e,()=>o(`Tool unregistered`)),n?.signal)}catch(e){throw n?.signal?.aborted&&e===n.signal.reason||r[H]?.aborted?e:s(e)}return f(a)}async#c(){await new Promise(e=>setTimeout(e,0)),this.dispatchEvent(new Event(`toolchange`)),this.#t?.dispatchToolChange()}};let X=function(){throw TypeError(`Illegal constructor`)};Object.defineProperty(X,"name",{value:`ModelContext`}),Object.defineProperty(X,"prototype",{value:Y.prototype,writable:!1}),Object.setPrototypeOf(X,EventTarget),Object.defineProperty(Y.prototype,"constructor",{configurable:!0,writable:!0,value:X}),Object.defineProperty(Y.prototype,Symbol.toStringTag,{configurable:!0,value:`ModelContext`});for(let e of[`registerTool`,`getTools`,`executeTool`,`ontoolchange`]){let t=Object.getOwnPropertyDescriptor(Y.prototype,e);t&&Object.defineProperty(Y.prototype,e,{...t,enumerable:!0})}var Te=class extends EventTarget{_ontoolchange=null;ontoolchangeListener=e=>{this._ontoolchange?.call(this,e)};#e;constructor(e){super(),this.#e=e}listTools(){return Y.getToolInfos(this.#e)}executeTool(e,t,n){return Y.executeToolForTesting(this.#e,e,t,n)}get ontoolchange(){return this._ontoolchange}set ontoolchange(e){let t=typeof e==`function`?e:null;if(t===null){this._ontoolchange=null,super.removeEventListener(`toolchange`,this.ontoolchangeListener);return}this._ontoolchange===null&&super.addEventListener(`toolchange`,this.ontoolchangeListener),this._ontoolchange=t}dispatchToolChange(){this.dispatchEvent(new Event(`toolchange`))}dispose(){this.ontoolchange=null}};function Ee(e,t){if(!e||typeof e!=`object`)throw TypeError(`registerTool(tool) requires a tool object`);let n=a(e);if(l(n),t.has(n.name))throw c(`Tool already registered: ${n.name}`);let r=n.inputSchema===void 0?void 0:ne(n.inputSchema);return{name:n.name,...n.title===void 0?{}:{title:n.title},description:n.description,...n.inputSchema===void 0?{}:{inputSchema:n.inputSchema},...n.annotations===void 0?{}:{annotations:n.annotations},execute:e=>Reflect.apply(n.execute,void 0,[e]),...r===void 0?{}:{[V]:r}}}let Z=!1,De=new WeakMap,{modelContext:Oe}={modelContext(){if(!(this instanceof Document))throw TypeError(`Illegal invocation`);return De.get(this)}};Object.defineProperty(Oe,"name",{value:`get modelContext`});function ke(e,t){De.set(e,t),!Object.hasOwn(Document.prototype,`modelContext`)&&J(Document.prototype,`modelContext`,{configurable:!0,enumerable:!0,get:Oe})}function Ae(e,t){J(e,`modelContext`,{configurable:!0,enumerable:!0,get(){return Z||(Z=!0,console.warn(`[WebMCPPolyfill] navigator.modelContext is deprecated. The May 27, 2026 WebMCP draft moved the modelContext getter from Navigator to Document — use document.modelContext instead. See https://github.com/webmachinelearning/webmcp/pull/184.`)),t}})}function je(){let e=SubmitEvent.prototype;`agentInvoked`in e||J(e,`agentInvoked`,{configurable:!0,enumerable:!0,get(){return b(this)}}),`respondWith`in e||J(e,`respondWith`,{configurable:!0,enumerable:!0,writable:!0,value(e){re(this,e)}})}function Q(e){if(globalThis.isSecureContext===!1)return;let t=typeof navigator>`u`?null:navigator,n=typeof document>`u`?null:document;if(!t||!n||typeof window>`u`||n.modelContext)return;let r=t.modelContext;if(W.length>0&&$(),r){ke(n,r);return}let i=Object.getOwnPropertyDescriptor(window,`ModelContext`);if(i&&!i.configurable){if(!Object.is(Reflect.get(window,`ModelContext`),X))throw TypeError(`Cannot install ModelContext over a non-configurable global`)}else J(window,`ModelContext`,{configurable:!0,enumerable:!1,writable:!0,value:X});let a=new Y(n);G=a,ke(n,a),Z=!1,Ae(t,a),je(),e?.installTestingShim&&!t.modelContextTesting&&J(t,`modelContextTesting`,{configurable:!0,enumerable:!0,writable:!1,value:Y.getTestingShim(a)}),K=we(n,a)}function $(){K?.(),K=null,G&&Y.dispose(G),G=null;for(let{target:e,key:t,previous:n}of[...W].reverse())n?Object.defineProperty(e,t,n):Reflect.deleteProperty(e,t);W.length=0,Z=!1}try{Q(window.__webMCPPolyfillOptions)}catch(e){console.error(`[WebMCPPolyfill] Auto-initialization failed:`,e)}return e.cleanupWebMCPPolyfill=$,e.initializeWebMCPPolyfill=Q,e})({});
|
|
1
|
+
var WebMCPPolyfill=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});let t=[`consequentialHint`,`debugging`,`readOnlyHint`,`untrustedContentHint`],n=`webmcp-polyfill`,r=globalThis.DOMException;var i=class{#e;#t;#n;#r=new Set;#i=new Set;#a=Promise.withResolvers();#o=new Map;#s=new Set;#c;#l=!1;constructor(e,t){this.#t=e,this.#e=e.document,this.#n=t,this.#t.addEventListener(`message`,e=>this.#d(e),!0),this.#t.addEventListener(`pagehide`,()=>{this.#l=!0;for(let e of this.#s)e.end()}),this.#t.addEventListener(`pageshow`,e=>{e.persisted&&(this.#l=!1,this.#x())});for(let e of this.#x())this.#i.add(e);this.#i.size===0?this.#a.resolve():setTimeout(()=>{this.#i.clear(),this.#a.resolve()},500)}async allowed(){return this.#l?!1:this.#h(this.#e)}async getTools(e){await this.#a.promise;let t=this.#t.origin,n=[t,...e];return(await Promise.all(this.#b().map(async e=>{if(e===this.#t)return this.#n.getTools(t).map(e=>d(e,this.#t,t));try{let t=await this.#u(e,n,{kind:`getTools`});if(!Array.isArray(t.value))throw TypeError(`Expected a tool list from the frame`);return t.value.map(n=>d(f(n),e,t.origin))}catch(e){return e instanceof r&&e.name===`UnknownError`||console.warn(`WebMCP: could not read tools from a frame.`,e),[]}}))).flat()}async execute(e,t,n,r,i){let a=await this.#u(e,[t],{kind:`execute`,name:n,input:r},i);if(typeof a.value!=`string`)throw g();return a.value}async notify(e){await this.#a.promise;let t=[this.#t.origin,...e];for(let e of this.#b()){if(e===this.#t){await this.#n.changed();continue}try{await this.#u(e,t,{kind:`changed`})}catch{}}}#u(e,t,r,i){return new Promise((a,o)=>{if(i?.throwIfAborted(),this.#l||!this.#v(e)){o(g());return}let s=crypto.randomUUID(),{port1:c,port2:l}=new MessageChannel,u,d=()=>{clearTimeout(v),y(),i?.removeEventListener(`abort`,p),this.#o.delete(s),c.close()},f=(e=g())=>{c.postMessage({kind:`cancel`}),d(),o(e)},p=()=>f(i?.reason),h=()=>{u===void 0&&this.#C(e),f()},_=n=>{if(n.source===e){if(this.#o.delete(s),t&&!t.includes(n.origin)){f();return}u=n.origin,clearTimeout(v),r.kind!==`execute`&&r.kind!==`changed`&&(v=setTimeout(h,500)),c.postMessage(r)}},v=setTimeout(h,500),y=this.#w(e,f);c.onmessage=e=>{let t=m(e.data);if(t?.kind===`error`){f();return}t?.kind!==`result`||u===void 0||(d(),a({value:t.value,origin:u}))},c.onmessageerror=()=>f(),i?.addEventListener(`abort`,p,{once:!0}),this.#o.set(s,_);try{e.postMessage(`${n}:connect:${s}`,`*`,[l])}catch{l.close(),f()}})}#d(e){let t=p(e.data);if(!t)return;e.stopImmediatePropagation();let r=e.source;if(!e.isTrusted||!r||!h(r)||!this.#v(r)||e.origin===`null`||this.#l)return;if(t.kind===`announce`){let t=!this.#r.has(r);if(this.#S(r),r.postMessage(`${n}:present`,e.origin),!t||this.#t!==this.#t.top)return;for(let e of this.#r)e!==r&&e.postMessage(`${n}:refresh`,`*`);return}if(t.kind===`present`){this.#S(r);return}if(t.kind===`refresh`){r===this.#t.top&&this.#x();return}if(t.kind===`ready`){this.#o.get(t.id)?.(e);return}let[i]=e.ports;t.kind!==`connect`||!t.id||!i||e.ports.length!==1||(this.#S(r),this.#f(r,e.origin,t.id,i))}#f(e,t,r,i){let a=new AbortController,o=!1,s=()=>{clearTimeout(u),d(),i.close()},c=()=>{a.abort(),s()},l=()=>{i.postMessage({kind:`error`}),c()},u=setTimeout(l,500),d=this.#w(e,l);i.onmessageerror=l,i.onmessage=async n=>{let r=m(n.data);if(r?.kind===`cancel`){c();return}if(!o){o=!0,clearTimeout(u);try{let n=await this.#p(e,t,r,a.signal);i.postMessage({kind:`result`,value:n}),s()}catch{l()}}},e.postMessage(`${n}:ready:${r}`,t)}async#p(e,t,n,r){if(!n||!this.#v(e))throw g();if(n.kind===`permission`){let{childIndex:e,childOrigin:t}=n;if(typeof e!=`number`||!Number.isInteger(e)||e<0||typeof t!=`string`)throw g();return this.#m(e,t)}if(!await this.allowed()||!await this.#g(e,t)||!this.#v(e))throw g();if(r.throwIfAborted(),n.kind===`getTools`)return this.#n.getTools(t);if(n.kind===`execute`&&typeof n.name==`string`&&typeof n.input==`string`)return this.#n.execute(t,n.name,n.input,r);if(n.kind===`changed`){await this.#n.changed();return}throw g()}async#m(e,t){let n=this.#t[e];return n!==void 0&&await this.allowed()&&a(this.#e,n,t)}async#h(e){let t=l(e);if(!t)return!1;let n=u(e);if(n!==void 0)return n;if(t===t.parent)return!0;let r=t.location.ancestorOrigins?.[0],i=o(t.parent,r===void 0||r===t.origin);return i?a(i,t,t.origin)&&await this.#h(i):this.#_(t,t.origin)}async#g(e,t){let n=o(e,t===this.#t.origin);return n?this.#h(n):this.#_(e,t)}async#_(e,t){let n=e.parent;if(n===e)return!0;let r=-1;for(let t=0;t<n.length;t++)if(n[t]===e){r=t;break}if(r<0)return!1;if(n===this.#t)return await this.allowed()&&a(this.#e,e,t);if(await this.#a.promise,!this.#r.has(n))return!1;try{let e=await this.#u(n,void 0,{kind:`permission`,childIndex:r,childOrigin:t});return e.value===!0&&await this.#g(n,e.origin)}catch{return!1}}#v(e){try{return!e.closed&&e!==this.#t&&e.top===this.#t.top}catch{return!1}}#y(){if(this.#t.closed)return[];for(let e of this.#r)this.#v(e)||this.#r.delete(e);let e=[this.#t,...this.#r];for(let t=this.#t.parent;t!==t.parent;t=t.parent)e.push(t);let t=new Set,n=[this.#t.top];for(;n.length;){let r=n.pop();if(t.has(r))continue;t.add(r);let i=[];for(let e=0;e<r.length;e++){let t=r[e];t&&i.push(t)}for(let t of e)t!==r&&t.parent===r&&!i.includes(t)&&i.push(t);n.push(...i.reverse())}return Array.from(t).filter(e=>e===this.#t||this.#v(e))}#b(){return this.#y().filter(e=>e===this.#t||this.#r.has(e))}#x(){let e=this.#y().filter(e=>e!==this.#t);for(let t of e)t.postMessage(`${n}:announce`,`*`);return e}#S(e){this.#r.add(e),this.#i.delete(e),this.#i.size===0&&this.#a.resolve()}#C(e){this.#r.delete(e),this.#v(e)&&e.postMessage(`${n}:announce`,`*`)}#w(e,t){let n={peer:e,end:t};return this.#s.add(n),this.#c===void 0&&(this.#c=this.#t.setInterval(()=>{for(let e of this.#s)this.#v(e.peer)||e.end()},100)),()=>{this.#s.delete(n),this.#s.size===0&&(this.#t.clearInterval(this.#c),this.#c=void 0)}}};function a(e,t,n){let r=e.defaultView?.origin,i=s(e,t,n===r);if(!i)return!1;let a=(i.getAttribute(`allow`)??``).split(`;`).map(e=>e.trim().split(/\s+/u)).find(([e])=>e===`tools`);if(!a)return n===r;let o=a.length===1?[`'src'`]:a.slice(1);if(o.includes(`'none'`))return!1;let c=i.hasAttribute(`srcdoc`)?null:i.getAttribute(`src`),l=c?URL.parse(c,e.baseURI):null,u=!c||l?.protocol===`about:`?r:l?.origin;return o.some(e=>e===`*`||e===`'self'`&&n===r||e===`'src'`&&n===u||e===n)}function o(e,t){if(t)try{return e.document}catch{return}}function s(e,t,n){if(n)try{let n=t.frameElement;if(n?.ownerDocument===e)return n}catch{}return c(e,t)}function c(e,t){let n=e.querySelectorAll(`iframe, frame`);for(let e of n)if(e.contentWindow===t)return e;for(let n of e.querySelectorAll(`*`)){if(!n.shadowRoot)continue;let e=c(n.shadowRoot,t);if(e)return e}}function l(e){let t=e.defaultView;return t&&!t.closed&&t.document===e?t:void 0}function u(e){let t=e,n=m(t.permissionsPolicy??t.featurePolicy);if(typeof n?.features!=`function`||typeof n.allowsFeature!=`function`)return;let r=n.features();return Array.isArray(r)&&r.includes(`tools`)?!!n.allowsFeature(`tools`):void 0}function d(e,t,n){let r=e.serializedSchema===void 0?void 0:JSON.parse(e.serializedSchema);return{...e.annotations!==void 0&&{annotations:{...e.annotations}},description:e.description,...r!==void 0&&{inputSchema:r},name:e.name,origin:n,title:e.title,window:t}}function f(e){let n=m(e);if(!n||typeof n.name!=`string`||typeof n.title!=`string`||typeof n.description!=`string`||n.serializedSchema!==void 0&&typeof n.serializedSchema!=`string`)throw TypeError(`Invalid tool metadata from the frame`);let r={name:n.name,title:n.title,description:n.description,annotations:void 0,serializedSchema:n.serializedSchema};if(n.annotations===void 0)return r;let i=m(n.annotations);if(!i)throw TypeError(`Invalid tool annotations from the frame`);let a={};for(let e of t){let t=i[e];if(t!==void 0){if(typeof t!=`boolean`)throw TypeError(`Invalid ${e} annotation from the frame`);a[e]=t}}return r.annotations=a,r}function p(e){if(typeof e!=`string`)return;let[t,r=``,i=``,a]=e.split(`:`);return t===n&&a===void 0?{kind:r,id:i}:void 0}function m(e){if(!(typeof e!=`object`||!e||Array.isArray(e)))return e}function h(e){try{return`postMessage`in e&&`window`in e}catch{return!1}}function g(){return new r(`Tool execution failed`,`UnknownError`)}let _=new WeakSet,v=new WeakMap,y=new WeakMap;function b(e){return e.isTrusted&&(_.has(e)||e.eventPhase!==Event.NONE&&e.target instanceof HTMLFormElement&&y.has(e.target))}function ee(e,t){if(!b(e))throw new DOMException(`respondWith() is only available during an agent-invoked submit event`,`InvalidStateError`);if(!e.defaultPrevented)throw new DOMException(`respondWith() requires preventDefault() during an agent-invoked submit event`,`InvalidStateError`);if(e.eventPhase===Event.NONE)throw new DOMException(`respondWith() is only available while the submit event is being dispatched`,`InvalidStateError`);_.add(e);let n=Promise.resolve(t);v.set(e,n),e.target instanceof HTMLFormElement&&y.get(e.target)?.respond(e)}let x=new Set([`email`,`password`,`search`,`tel`,`text`,`url`]),te=new Set([...x,`date`,`datetime-local`,`month`,`number`,`time`,`week`]);function ne(e){return e instanceof HTMLInputElement||e instanceof HTMLSelectElement||e instanceof HTMLTextAreaElement}function S(e){return Object.getOwnPropertyDescriptor(HTMLFormElement.prototype,`elements`)?.get?.call(e)}function C(e,t){return Element.prototype.getAttribute.call(e,t)}function w(e,t){return Element.prototype.hasAttribute.call(e,t)}function T(e){return Object.getOwnPropertyDescriptor(Node.prototype,`isConnected`)?.get?.call(e)}function re(e){return Object.getOwnPropertyDescriptor(Element.prototype,`shadowRoot`)?.get?.call(e)}function ie(e){return HTMLFormElement.prototype.checkValidity.call(e)}function ae(e,t){HTMLFormElement.prototype.requestSubmit.call(e,t)}function oe(e){return[...S(e)].filter(e=>ne(e)&&!e.matches(`:disabled`)&&!(`readOnly`in e&&e.readOnly&&(e instanceof HTMLTextAreaElement||te.has(e.type))))}function se(e){let t=new Map;for(let n of oe(e)){let e=n.name.trim(),r=t.get(e);r?r.push(n):t.set(e,[n])}return t}function ce(e){return[...e.labels??[]].map(e=>{let t=e.cloneNode(!0);return t instanceof HTMLElement?(t.querySelectorAll(`button, input, meter, output, progress, select, textarea`).forEach(e=>e.remove()),t.textContent?.trim()??``):``}).filter(Boolean).join(`; `)}function le(e,t){for(let n=t[0]?.parentElement;n&&n!==e;n=n.parentElement)if(n instanceof HTMLFieldSetElement&&t.every(e=>n.contains(e)))return n}function ue(e,t){if(t.length===1){let e=t[0];return e&&(e.getAttribute(`toolparamdescription`)||ce(e)||e.getAttribute(`aria-description`))||void 0}return le(e,t)?.getAttribute(`toolparamdescription`)||void 0}function de(e,t,n,r){let i=ue(t,n),a=i&&r?`${i} (${r})`:i||r;return a?{...e,description:a}:e}function fe(e,t){let n=e.getAttribute(t);if(n===null||n.trim()===``)return;let r=Number(n);return Number.isFinite(r)?r:void 0}function pe(e,t){let n=Number(e.getAttribute(`step`));return Number.isFinite(n)&&n>0?n:t}function me(e,t){let n=e/t;return Math.abs(n-Math.round(n))<2**-52*16}function E(e,t){let n=t.getAttribute(`pattern`);if(n===null)return e;try{new RegExp(n,`v`)}catch{return e}return{...e,pattern:n}}function D(e){let t={type:`number`},n=fe(e,`min`),r=fe(e,`max`);if(n!==void 0&&(t.minimum=n),r!==void 0&&(t.maximum=r),e.getAttribute(`step`)!==`any`){let r=pe(e,1),i=Number(e.getAttribute(`value`));me(n??(Number.isFinite(i)?i:0),r)&&(t.multipleOf=r)}return t}function O(e,t){let n=pe(e,60);return n<1?`${t}(:[0-5][0-9](\\.[0-9]{1,3})?)?$`:n<60?`${t}(:[0-5][0-9])?$`:`${t}$`}function he(e){return{anyOf:e.map(e=>({type:`string`,const:e.value,title:e.textContent??``})),enum:e.map(e=>e.value)}}function k(e){return{anyOf:e.map(e=>{let t=ce(e),n={type:`string`,const:e.value};return t&&(n.title=t),n}),enum:e.map(e=>e.value)}}function A(e,t){return e instanceof HTMLInputElement&&e.type===t}function ge(e){if(x.has(e.type))return E({type:`string`},e);switch(e.type){case`hidden`:return e.getAttribute(`toolparamdescription`)?{type:`string`}:void 0;case`number`:return E(D(e),e);case`range`:{let t=D(e);return t.minimum??=0,t.maximum??=100,t}case`checkbox`:return{type:`boolean`};case`date`:return{type:`string`,format:`date`};case`month`:return{type:`string`,format:`^[0-9]{4}-(0[1-9]|1[0-2])$`};case`week`:return{type:`string`,format:`^[0-9]{4}-W(0[1-9]|[1-4][0-9]|5[0-3])$`};case`time`:return{type:`string`,format:O(e,`^([01][0-9]|2[0-3]):[0-5][0-9]`)};case`datetime-local`:return{type:`string`,format:O(e,`^[0-9]{4}-(0[1-9]|1[0-2])-[0-9]{2}T([01][0-9]|2[0-3]):[0-5][0-9]`)};case`color`:return{type:`string`,format:`^#[0-9a-zA-Z]{6}$`};default:return}}function j(e,t){let[n]=t;if(!n)return;let r;if(t.every(e=>A(e,`radio`)))r={type:`string`,...k(t)};else if(t.length>1)t.every(e=>A(e,`checkbox`))&&(r={type:`array`,items:{type:`string`,...k(t)},uniqueItems:!0});else if(n instanceof HTMLTextAreaElement)r={type:`string`};else if(n instanceof HTMLSelectElement){let e=he([...n.options]);r=n.multiple?{type:`array`,items:{type:`string`,...e},uniqueItems:!0}:{type:`string`,...e}}else r=ge(n);let i=n.type===`date`?`Dates MUST be provided in 'YYYY-MM-DD' format.`:void 0;return r&&de(r,e,t,i)}function _e(e){let t={},n=[];for(let[r,i]of se(e)){if(!r)continue;let a=j(e,i);a&&(Object.defineProperty(t,r,{configurable:!0,enumerable:!0,value:a,writable:!0}),i.some(e=>e.required)&&n.push(r))}return{type:`object`,properties:t,required:n}}function ve(e){return{name:C(e,`toolname`)??``,title:C(e,`tooltitle`)??``,description:C(e,`tooldescription`)??``,inputSchema:_e(e),autosubmit:w(e,`toolautosubmit`)}}function M(e){if(typeof e==`string`||typeof e==`boolean`||typeof e==`number`&&Number.isFinite(e))return String(e)}function N(e){if(typeof e==`boolean`)return e;if(typeof e==`number`&&Number.isInteger(e))return e!==0;if(typeof e==`string`){if(e===`1`||e.toLowerCase()===`true`)return!0;if(e===`0`||e.toLowerCase()===`false`)return!1}}function P(e,t){if(!Array.isArray(e))return!1;let n=new Set(t);for(let t of e){let e=M(t);if(e===void 0||!n.delete(e))return!1}return!0}function ye(e,t){if(t===``)return e.type!==`number`&&e.type!==`range`;let n=e.ownerDocument.createElement(`input`);return n.type=e.type,n.value=t,n.value!==``}function be(e,t,n){let[r]=t;if(!r||!j(e,t))return!1;let i=M(n);if(t.every(e=>A(e,`radio`)))return t.some(e=>e.value===i);if(t.length>1)return P(n,new Set(t.map(e=>e.value)));if(r instanceof HTMLSelectElement){let e=new Set([...r.options].map(e=>e.value));return r.multiple?P(n,e):i!==void 0&&e.has(i)}return r instanceof HTMLTextAreaElement?i!==void 0:r.type===`checkbox`?N(n)!==void 0:i!==void 0&&ye(r,i)}function F(e){e.dispatchEvent(new Event(`input`,{bubbles:!0,composed:!0})),e.dispatchEvent(new Event(`change`,{bubbles:!0}))}function xe(e,t){if(e.value===t)return;let n=e instanceof HTMLInputElement?HTMLInputElement.prototype:HTMLTextAreaElement.prototype;Object.getOwnPropertyDescriptor(n,`value`)?.set?.call(e,t),F(e)}function I(e,t){e.checked!==t&&(Object.getOwnPropertyDescriptor(HTMLInputElement.prototype,`checked`)?.set?.call(e,t),F(e))}function Se(e,t){let[n]=e,r=M(t),i=new Set(Array.isArray(t)?t.map(M):[]);if(e.every(e=>A(e,`radio`))){let t=e.find(e=>e.value===r);t&&I(t,!0)}else if(e.length>1)for(let t of e)t instanceof HTMLInputElement&&I(t,i.has(t.value));else if(n instanceof HTMLSelectElement)if(n.multiple){let e=!1;for(let t of n.options){let n=i.has(t.value);t.selected!==n&&(t.selected=n,e=!0)}e&&F(n)}else r!==void 0&&n.value!==r&&(n.value=r,F(n));else if(n&&A(n,`checkbox`)){let e=N(t);e!==void 0&&I(n,e)}else n&&r!==void 0&&xe(n,r)}function Ce(e,t){if(Array.isArray(t))throw g();let n=se(e),r=[];for(let[i,a]of Object.entries(t)){let t=n.get(i);if(!t||!be(e,t,a))throw g();r.push({controls:t,value:a})}for(let{controls:e,value:t}of r)Se(e,t)}function we(e){return[...S(e)].find(e=>!e.matches(`:disabled`)&&(e instanceof HTMLButtonElement&&e.type===`submit`||e instanceof HTMLInputElement&&[`image`,`submit`].includes(e.type)))}function L(e,t){let n=new Event(e);return Object.defineProperty(n,"toolName",{enumerable:!0,value:t}),n}function Te(e,t,n,r,i){let{form:a}=t;return t.cancelPending?.(g()),new Promise((o,s)=>{let c=!1,l=()=>{EventTarget.prototype.removeEventListener.call(a,`invalid`,p,!0),i.removeEventListener(`abort`,m),y.delete(a),t.cancelPending===d&&delete t.cancelPending},u=e=>{c||(c=!0,l(),e())},d=e=>u(()=>s(e)),f=e=>{t.cancelPending===d&&delete t.cancelPending,e.then(e=>u(()=>o(e??null)),e=>u(()=>s(e)))},p=e=>{e.isTrusted&&queueMicrotask(()=>{ie(a)||d(g())})},m=()=>{u(()=>{e.dispatchEvent(L(`toolcancel`,n.name)),s(i.reason)})};if(y.set(a,{complete(e){setTimeout(()=>{let t=v.get(e);t?f(t):e.defaultPrevented?d(g()):u(()=>o(null))})},direct(){u(()=>o(null))},respond(e){queueMicrotask(()=>{let t=v.get(e);t&&f(t)})}}),t.cancelPending=d,EventTarget.prototype.addEventListener.call(a,`invalid`,p,!0),i.addEventListener(`abort`,m,{once:!0}),!n.autosubmit){r?.focus(),e.dispatchEvent(L(`toolactivated`,n.name));return}try{ae(a,r),e.dispatchEvent(L(`toolactivated`,n.name))}catch(e){d(e)}})}function Ee(e){let t=SubmitEvent.prototype;if(`agentInvoked`in t&&`respondWith`in t)return;`agentInvoked`in t||Object.defineProperty(t,"agentInvoked",{configurable:!0,enumerable:!0,get(){return b(this)}}),`respondWith`in t||Object.defineProperty(t,"respondWith",{configurable:!0,enumerable:!0,writable:!0,value(e){ee(this,e)}});let n=new Map,r=new Map,i=new Map,a=e=>{if(!(e instanceof SubmitEvent)||!e.isTrusted||!(e.target instanceof HTMLFormElement))return;let t=y.get(e.target);t&&(_.add(e),t.complete(e))},o=e=>{if(!e.isTrusted||!(e.target instanceof HTMLFormElement))return;let t=e.target;setTimeout(()=>{e.defaultPrevented||n.get(t)?.cancelPending?.(g())})};function s(e){i.get(e)?.disconnect(),i.delete(e),e.removeEventListener(`reset`,o,!0),e.removeEventListener(`submit`,a,!0)}function c(e){if(i.has(e))return;let t=new MutationObserver(l);i.set(e,t),t.observe(e,{attributes:!0,characterData:!0,childList:!0,subtree:!0}),e.addEventListener(`reset`,o,!0),e.addEventListener(`submit`,a,!0)}function l(){c(document);for(let e of i.keys())e instanceof ShadowRoot&&!e.host.isConnected&&s(e);let t=new Set,a=new Map,o=new Map;for(let e of i.keys())for(let n of e.querySelectorAll(`*`)){let e=re(n);if(e&&c(e),!(n instanceof HTMLFormElement)||!w(n,`toolname`)||!w(n,`tooldescription`)||!T(n))continue;let i=n;t.add(i);let s=ve(i),l=JSON.stringify(s),u=r.get(i);if(u===l)continue;r.delete(i);let d=o.get(s.name);if(d){if(u===void 0){r.set(i,l);continue}let e=a.get(d);e&&r.set(d,e.fingerprint),a.delete(d)}o.set(s.name,i),a.set(i,{definition:s,fingerprint:l})}for(let e of r.keys())t.has(e)||r.delete(e);for(let[e,t]of n)a.get(e)?.fingerprint!==t.fingerprint&&(t.cancelPending?.(g()),t.controller.abort(),n.delete(e));for(let[t,{definition:r,fingerprint:i}]of a){if(n.has(t))continue;let a=new AbortController,o={controller:a,fingerprint:i,form:t};n.set(t,o),e.registerTool({name:r.name,title:r.title,description:r.description,inputSchema:r.inputSchema,execute(n,i){let a=we(t);if(!r.autosubmit&&!a)throw g();return Ce(t,n),Te(e,o,r,a,i.signal)}},{signal:a.signal}).catch(e=>{a.abort(),!(e instanceof DOMException&&e.name===`AbortError`)&&console.error(`[webmcp] declarative form tool "${r.name}" was not registered:`,e)})}}let u=Object.getOwnPropertyDescriptor(Element.prototype,`attachShadow`);if(u?.configurable){let e=Element.prototype.attachShadow,t=function(t){let n=e.call(this,t);return n.mode===`open`&&Object.getOwnPropertyDescriptor(Node.prototype,`ownerDocument`)?.get?.call(this)===document&&T(this)&&c(n),n};Object.defineProperty(Element.prototype,"attachShadow",{...u,value:t})}let d=Object.getOwnPropertyDescriptor(HTMLFormElement.prototype,`submit`);if(d?.configurable){let e=HTMLFormElement.prototype.submit,t=function(){e.call(this),y.get(this)?.direct()};Object.defineProperty(HTMLFormElement.prototype,"submit",{...d,value:t})}l()}
|
|
2
|
+
/*!
|
|
3
|
+
* Copyright (c) 2026 WebMCP polyfill contributors
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
let R=globalThis.DOMException,De=Object.getOwnPropertyDescriptor(globalThis,`window`)?.get,z=new WeakMap;function Oe(){if(typeof document>`u`||!globalThis.isSecureContext||`modelContext`in document)return;let e=Document.prototype,t=Object.getOwnPropertyDescriptor(e,`defaultView`).get,n=Object.getOwnPropertyDescriptor(globalThis,`ModelContext`);if(!Object.isExtensible(e)||n&&!n.configurable||!n&&!Object.isExtensible(globalThis))throw TypeError(`Cannot install WebMCP on this realm`);Object.defineProperty(globalThis,"ModelContext",{value:H,configurable:!0,writable:!0});let{getModelContext:r}={getModelContext(){t.call(this);let e=z.get(this);return e||(e=new B(this),z.set(this,e)),e}};Object.defineProperty(r,"name",{value:`get modelContext`}),Object.defineProperty(e,"modelContext",{configurable:!0,enumerable:!0,get:r}),document.modelContext}var B=class extends EventTarget{#e;#t=new Map;#n;#r=null;#i=e=>{let t=this.#r;typeof t==`function`&&Reflect.apply(t,this,[e])===!1&&Event.prototype.preventDefault.call(e)};constructor(e){super(),this.#e=e;let t=l(e);t&&(this.#n=new i(t,{getTools:e=>this.#s(e),execute:(t,n,r,i)=>{let a=Z(e).origin;return this.#a(n,r,a,t,i)},changed:()=>this.#c()}))}get ontoolchange(){return this.#r}set ontoolchange(e){let t=W(e)?e:null;!this.#r&&t&&this.addEventListener(`toolchange`,this.#i),this.#r&&!t&&this.removeEventListener(`toolchange`,this.#i),this.#r=t}async registerTool(e,t={}){let n=this.#e,{name:r,title:i,description:a,annotations:o,inputSchema:s,execute:c}=ke(e),l=G(t),u=Ne(l.exposedTo),d=Me(l.signal);Z(n);let f=()=>{if(this.#t.has(r))throw new R(`A tool named ${r} is already registered`,`InvalidStateError`)};if(f(),!/^[A-Za-z0-9_.-]{1,128}$/u.test(r))throw new R(`Tool names are 1 to 128 characters of ASCII alphanumerics, "_", "-" or ".": ${r}`,`InvalidStateError`);if(!a)throw new R(`A tool description cannot be empty`,`InvalidStateError`);let p=s===void 0?void 0:Y(s);d?.throwIfAborted();let m=X(u),h={metadata:{name:r,title:i,description:a,annotations:o,serializedSchema:p},execute:c,exposedTo:m},g=await this.#o();return d?.throwIfAborted(),f(),new Promise((e,t)=>{d?.addEventListener(`abort`,()=>{this.#t.delete(r),g.notify(m),t(d.reason)},{once:!0}),this.#t.set(r,h),g.notify(m).then(e,t)})}async getTools(e={}){let t=this.#e,n=Ne(G(e).fromOrigins);Z(t);let r=await this.#o(),i=X(n),a=await r.getTools(i);return a.sort((e,t)=>e.name===t.name?0:e.name<t.name?-1:1),new Promise(e=>{$(()=>e(a))})}async executeTool(e,t={},n={}){let r=this.#e,i=Ae(e),a=Me(G(n).signal);Z(r);let o=URL.parse(i.origin)?.origin;if(!o||o===`null`)throw new R(`Invalid or opaque origin`,`NotSupportedError`);if(!W(t))throw TypeError(`inputObject must be an object`);let s=Y(t);a?.throwIfAborted();let c=await this.#o();a?.throwIfAborted();let l=Z(r);return i.window===l?this.#a(i.name,s,o,l.origin,a):c.execute(i.window,o,i.name,s,a)}#a(e,t,n,r,i){return new Promise((a,o)=>{i?.throwIfAborted();let s=new AbortController,c=!1,l=()=>{o(i.reason),$(()=>{c||s.abort()})},u=()=>{c=!0,$(()=>{i?.removeEventListener(`abort`,l),o(g())})},d=e=>{if(c=!0,!i?.aborted)try{let t=Y(e);$(()=>{i?.removeEventListener(`abort`,l),a(t)})}catch{u()}};i?.addEventListener(`abort`,l,{once:!0}),$(()=>{if(!i?.aborted)try{let i=Z(this.#e),a=this.#t.get(e);if(!a||n!==i.origin||!V(a,i.origin,r)){u();return}let o=JSON.parse(t);if(!W(o)){u();return}let c=a.execute,l=c(o,{signal:s.signal});Promise.resolve(l).then(d,u)}catch{u()}})})}async#o(){let e=this.#n;if(!e||!await e.allowed())throw new R(`WebMCP is disabled by Permissions Policy`,`NotAllowedError`);return Z(this.#e),e}#s(e){let t=Z(this.#e).origin,n=[];for(let r of this.#t.values())V(r,t,e)&&n.push(r.metadata);return n}#c(){return new Promise(e=>{$(()=>{this.dispatchEvent(new Event(`toolchange`)),e()})})}};function V(e,t,n){return t===n||e.exposedTo.includes(n)}let H=function(){throw TypeError(`Illegal constructor`)};Object.defineProperty(H,"name",{value:`ModelContext`}),Object.defineProperty(H,"prototype",{value:B.prototype,writable:!1}),Object.setPrototypeOf(H,EventTarget),Object.defineProperties(B.prototype,{constructor:{value:H,configurable:!0,writable:!0},[Symbol.toStringTag]:{value:`ModelContext`,configurable:!0},registerTool:{enumerable:!0},getTools:{enumerable:!0},executeTool:{enumerable:!0},ontoolchange:{enumerable:!0}});function ke(e){let t=G(e),n=je(t.annotations),r=K(J(t.description,`description`)),i=J(t.execute,`execute`);if(typeof i!=`function`)throw TypeError(`execute must be a function`);let a=i,o=U(t.inputSchema),s=K(J(t.name,`name`)),c=t.title;return{name:s,title:c===void 0?``:q(c),description:r,annotations:n,inputSchema:o,execute:a}}function Ae(e){let t=G(e);je(t.annotations),K(J(t.description,`description`)),U(t.inputSchema);let n=K(J(t.name,`name`)),r=q(J(t.origin,`origin`)),i=t.title;i!==void 0&&K(i);let a=J(t.window,`window`);if(!W(a))throw TypeError(`window must be a Window`);return De.call(a),{name:n,origin:r,window:a}}function U(e){if(e!==void 0&&!W(e))throw TypeError(`inputSchema must be an object`);return e}function W(e){return typeof e==`object`&&!!e||typeof e==`function`}function G(e){if(e==null)return{};if(!W(e))throw TypeError(`Expected a dictionary`);return e}function je(e){if(e===void 0)return;let n=G(e),r={};for(let e of t)r[e]=!!n[e];return r}function K(e){if(typeof e==`symbol`)throw TypeError(`Cannot convert a Symbol to a string`);return String(e)}function q(e){return K(e).toWellFormed()}function J(e,t){if(e===void 0)throw TypeError(`${t} is required`);return e}function Y(e){let t=JSON.stringify(e);if(t===void 0)throw TypeError(`Value is not JSON-serializable`);return t}function Me(e){if(e!==void 0)return AbortSignal.any([e])}function Ne(e){if(e===void 0)return[];if(!W(e))throw TypeError(`Origins must be a sequence`);let t=G(e)[Symbol.iterator];if(typeof t!=`function`)throw TypeError(`Origins must be a sequence`);let n={[Symbol.iterator](){let n=Reflect.apply(t,e,[]);if(!W(n))throw TypeError(`Iterator must be an object`);let r=G(n).next;if(typeof r!=`function`)throw TypeError(`Iterator next must be a function`);return{next(){return Reflect.apply(r,n,[])}}}};return Array.from(n,q)}function X(e){return e.map(e=>{let t=URL.parse(e)?.origin;if(t===void 0)throw new R(`Invalid origin`,`SecurityError`);let n=URL.parse(t);if(!n||!Pe(n))throw new R(`Origin is not potentially trustworthy`,`SecurityError`);return t})}function Pe({protocol:e,hostname:t}){if([`https:`,`wss:`].includes(e))return!0;let n=t===`[::1]`||/^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(t),r=t===`localhost`||t===`localhost.`||t.endsWith(`.localhost`)||t.endsWith(`.localhost.`);return[`http:`,`ws:`].includes(e)&&(n||r)}function Z(e){let t=l(e);if(!t)throw new R(`The document is not fully active`,`InvalidStateError`);if(u(e)===!1)throw new R(`WebMCP is disabled by Permissions Policy`,`NotAllowedError`);return t}let Q,Fe=[];function $(e){if(!Q){let e=new MessageChannel;e.port1.onmessage=()=>Fe.shift()?.(),Q=e.port2}Fe.push(e),Q.postMessage(void 0)}function Ie(){if(typeof document>`u`||!globalThis.isSecureContext||typeof Promise.withResolvers!=`function`||typeof AbortSignal.any!=`function`||typeof String.prototype.toWellFormed!=`function`||typeof URL.parse!=`function`)return;Oe();let e=document.modelContext;e&&Ee(e)}try{Ie()}catch(e){console.error(`[WebMCPPolyfill] Auto-initialization failed:`,e)}return e.installWebMCP=Ie,e})({});
|