@nexface/tools 0.1.1-alpha.1 → 0.1.1-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/controller.js +5 -4
- package/dist/browser/controller.js.map +1 -1
- package/dist/browser/dom.js +1 -2
- package/dist/browser/dom.js.map +1 -1
- package/dist/browser/feedback.js.map +1 -1
- package/dist/browser/focus.d.ts +2 -0
- package/dist/browser/focus.js +15 -0
- package/dist/browser/focus.js.map +1 -0
- package/dist/browser/locator.js.map +1 -1
- package/dist/browser/prompt.d.ts +1 -1
- package/dist/browser/prompt.generated.d.ts +1 -1
- package/dist/browser/prompt.generated.js +2 -2
- package/dist/browser/prompt.generated.js.map +1 -1
- package/dist/browser/prompt.js.map +1 -1
- package/dist/browser/snapshot.js.map +1 -1
- package/dist/browser/toolset.d.ts +12 -6
- package/dist/browser/toolset.js +18 -7
- package/dist/browser/toolset.js.map +1 -1
- package/dist/browser/types.js.map +1 -1
- package/dist/browser/worker-runner.js.map +1 -1
- package/dist/definition.js +10 -5
- package/dist/definition.js.map +1 -1
- package/dist/errors.d.ts +10 -0
- package/dist/errors.js +34 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.browser.d.ts +3 -0
- package/dist/index.browser.js +4 -0
- package/dist/index.browser.js.map +1 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/internal-react.d.ts +1 -1
- package/dist/internal-react.js +0 -1
- package/dist/internal-react.js.map +1 -1
- package/dist/internal-types.d.ts +1 -0
- package/dist/internal-types.js.map +1 -1
- package/dist/internal.d.ts +3 -2
- package/dist/internal.js +1 -0
- package/dist/internal.js.map +1 -1
- package/dist/navigation.js.map +1 -1
- package/dist/operation-lock.d.ts +3 -0
- package/dist/operation-lock.js +46 -0
- package/dist/operation-lock.js.map +1 -0
- package/dist/operation-runtime.d.ts +44 -0
- package/dist/operation-runtime.js +153 -0
- package/dist/operation-runtime.js.map +1 -0
- package/dist/operation-surface.d.ts +1 -1
- package/dist/operation-surface.js +109 -65
- package/dist/operation-surface.js.map +1 -1
- package/dist/operation-types.d.ts +1 -1
- package/dist/operation-types.js.map +1 -1
- package/dist/operation-view.d.ts +8 -2
- package/dist/operation-view.js +30 -61
- package/dist/operation-view.js.map +1 -1
- package/dist/react.js.map +1 -1
- package/dist/registration.d.ts +11 -0
- package/dist/registration.js +12 -0
- package/dist/registration.js.map +1 -0
- package/dist/runtime.d.ts +45 -12
- package/dist/runtime.js +73 -81
- package/dist/runtime.js.map +1 -1
- package/dist/schema.d.ts +1 -0
- package/dist/schema.js +185 -32
- package/dist/schema.js.map +1 -1
- package/dist/styles.css +11 -7
- package/dist/types.d.ts +11 -1
- package/dist/types.js.map +1 -1
- package/dist/webmcp.js +163 -9
- package/dist/webmcp.js.map +1 -1
- package/package.json +7 -12
- package/dist/operation-host.d.ts +0 -17
- package/dist/operation-host.js +0 -9
- package/dist/operation-host.js.map +0 -1
- package/dist/react-entry.d.ts +0 -2
- package/dist/react-entry.js +0 -3
- package/dist/react-entry.js.map +0 -1
package/dist/schema.js
CHANGED
|
@@ -1,44 +1,197 @@
|
|
|
1
|
+
const types = new Set(["object", "array", "string", "number", "integer", "boolean", "null"]);
|
|
2
|
+
const counts = ["minLength", "maxLength", "minItems", "maxItems"];
|
|
3
|
+
const bounds = ["minimum", "maximum", "exclusiveMinimum", "exclusiveMaximum"];
|
|
4
|
+
const keywords = new Set([
|
|
5
|
+
"type", "description", "properties", "required", "items", "enum", "additionalProperties",
|
|
6
|
+
...counts, ...bounds, "pattern", "uniqueItems",
|
|
7
|
+
]);
|
|
8
|
+
const checkedSchemas = new WeakSet();
|
|
9
|
+
const patterns = new WeakMap();
|
|
10
|
+
function invalid(path, message) {
|
|
11
|
+
throw new TypeError(`${path} ${message}`);
|
|
12
|
+
}
|
|
13
|
+
function isRecord(value) {
|
|
14
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
15
|
+
}
|
|
16
|
+
// Only deeply frozen, JSON-compatible values can safely share validation results.
|
|
17
|
+
function assertJson(value, path, ancestors = new Set()) {
|
|
18
|
+
if (value === null || typeof value === "string" || typeof value === "boolean")
|
|
19
|
+
return true;
|
|
20
|
+
if (typeof value === "number" && Number.isFinite(value))
|
|
21
|
+
return true;
|
|
22
|
+
if (typeof value !== "object" || value === null)
|
|
23
|
+
invalid(path, "must be JSON-compatible.");
|
|
24
|
+
if (ancestors.has(value))
|
|
25
|
+
invalid(path, "must not contain circular references.");
|
|
26
|
+
if (!Array.isArray(value) && Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) {
|
|
27
|
+
invalid(path, "must be a plain JSON object.");
|
|
28
|
+
}
|
|
29
|
+
if (Object.getOwnPropertySymbols(value).length)
|
|
30
|
+
invalid(path, "must not contain symbol properties.");
|
|
31
|
+
for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(value))) {
|
|
32
|
+
if (!descriptor.enumerable && !(Array.isArray(value) && key === "length"))
|
|
33
|
+
invalid(`${path}.${key}`, "must be enumerable.");
|
|
34
|
+
if (descriptor.get || descriptor.set)
|
|
35
|
+
invalid(`${path}.${key}`, "must be a data property.");
|
|
36
|
+
}
|
|
37
|
+
if (Array.isArray(value)) {
|
|
38
|
+
for (let index = 0; index < value.length; index++) {
|
|
39
|
+
if (!Object.hasOwn(value, index))
|
|
40
|
+
invalid(`${path}[${index}]`, "must not be a sparse array slot.");
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
ancestors.add(value);
|
|
44
|
+
let frozen = Object.isFrozen(value);
|
|
45
|
+
for (const [key, child] of Object.entries(value)) {
|
|
46
|
+
const childFrozen = assertJson(child, `${path}.${key}`, ancestors);
|
|
47
|
+
frozen = frozen && childFrozen;
|
|
48
|
+
}
|
|
49
|
+
ancestors.delete(value);
|
|
50
|
+
return frozen;
|
|
51
|
+
}
|
|
52
|
+
function patternFor(schema, path) {
|
|
53
|
+
const source = schema.pattern;
|
|
54
|
+
const cached = patterns.get(schema);
|
|
55
|
+
if (cached?.source === source)
|
|
56
|
+
return cached.regex;
|
|
57
|
+
let regex;
|
|
58
|
+
try {
|
|
59
|
+
regex = new RegExp(source, "u");
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
invalid(`${path}.pattern`, "must be a valid Unicode regular expression.");
|
|
63
|
+
}
|
|
64
|
+
patterns.set(schema, { source, regex });
|
|
65
|
+
return regex;
|
|
66
|
+
}
|
|
67
|
+
function assertSchema(value, path) {
|
|
68
|
+
if (!isRecord(value))
|
|
69
|
+
invalid(path, "must be an object.");
|
|
70
|
+
const unexpected = Object.keys(value).filter((key) => !keywords.has(key));
|
|
71
|
+
if (unexpected.length)
|
|
72
|
+
invalid(path, `has unsupported fields: ${unexpected.join(", ")}.`);
|
|
73
|
+
if (value.type !== undefined && (typeof value.type !== "string" || !types.has(value.type)))
|
|
74
|
+
invalid(`${path}.type`, "is not supported.");
|
|
75
|
+
if (value.description !== undefined && typeof value.description !== "string")
|
|
76
|
+
invalid(`${path}.description`, "must be a string.");
|
|
77
|
+
for (const key of ["additionalProperties", "uniqueItems"]) {
|
|
78
|
+
if (value[key] !== undefined && typeof value[key] !== "boolean")
|
|
79
|
+
invalid(`${path}.${key}`, "must be a boolean.");
|
|
80
|
+
}
|
|
81
|
+
for (const key of counts) {
|
|
82
|
+
const count = value[key];
|
|
83
|
+
if (count !== undefined && (typeof count !== "number" || !Number.isInteger(count) || count < 0))
|
|
84
|
+
invalid(`${path}.${key}`, "must be a non-negative integer.");
|
|
85
|
+
}
|
|
86
|
+
for (const key of bounds) {
|
|
87
|
+
if (value[key] !== undefined && (typeof value[key] !== "number" || !Number.isFinite(value[key])))
|
|
88
|
+
invalid(`${path}.${key}`, "must be a finite number.");
|
|
89
|
+
}
|
|
90
|
+
if (value.pattern !== undefined) {
|
|
91
|
+
if (typeof value.pattern !== "string")
|
|
92
|
+
invalid(`${path}.pattern`, "must be a string.");
|
|
93
|
+
patternFor(value, path);
|
|
94
|
+
}
|
|
95
|
+
if (value.enum !== undefined && (!Array.isArray(value.enum) || value.enum.length === 0))
|
|
96
|
+
invalid(`${path}.enum`, "must be a non-empty array.");
|
|
97
|
+
if (Array.isArray(value.enum) && value.enum.some((item, index, entries) => entries.slice(0, index).some((other) => jsonEqual(item, other))))
|
|
98
|
+
invalid(`${path}.enum`, "must contain unique values.");
|
|
99
|
+
if (value.properties !== undefined) {
|
|
100
|
+
if (value.type !== "object" || !isRecord(value.properties))
|
|
101
|
+
invalid(`${path}.properties`, "requires an object schema.");
|
|
102
|
+
for (const [name, property] of Object.entries(value.properties))
|
|
103
|
+
assertSchema(property, `${path}.properties.${name}`);
|
|
104
|
+
}
|
|
105
|
+
if (value.required !== undefined) {
|
|
106
|
+
if (value.type !== "object" || !Array.isArray(value.required) || value.required.some((name) => typeof name !== "string") || new Set(value.required).size !== value.required.length)
|
|
107
|
+
invalid(`${path}.required`, "must contain unique property names.");
|
|
108
|
+
const properties = value.properties;
|
|
109
|
+
if (value.required.some((name) => !properties || !Object.hasOwn(properties, name)))
|
|
110
|
+
invalid(`${path}.required`, "must reference declared properties.");
|
|
111
|
+
}
|
|
112
|
+
if (value.items !== undefined) {
|
|
113
|
+
if (value.type !== "array")
|
|
114
|
+
invalid(`${path}.items`, "requires an array schema.");
|
|
115
|
+
assertSchema(value.items, `${path}.items`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
export function assertAgentToolInputSchema(value, path = "inputSchema") {
|
|
119
|
+
if (!isRecord(value) || value.type !== "object")
|
|
120
|
+
invalid(path, 'root type must be object.');
|
|
121
|
+
if (checkedSchemas.has(value))
|
|
122
|
+
return;
|
|
123
|
+
const frozen = assertJson(value, path);
|
|
124
|
+
assertSchema(value, path);
|
|
125
|
+
if (frozen)
|
|
126
|
+
checkedSchemas.add(value);
|
|
127
|
+
}
|
|
128
|
+
function jsonEqual(left, right) {
|
|
129
|
+
if (left === right)
|
|
130
|
+
return true;
|
|
131
|
+
if (Array.isArray(left) && Array.isArray(right))
|
|
132
|
+
return left.length === right.length && left.every((item, index) => jsonEqual(item, right[index]));
|
|
133
|
+
if (!isRecord(left) || !isRecord(right))
|
|
134
|
+
return false;
|
|
135
|
+
const keys = Object.keys(left);
|
|
136
|
+
return keys.length === Object.keys(right).length && keys.every((key) => Object.hasOwn(right, key) && jsonEqual(left[key], right[key]));
|
|
137
|
+
}
|
|
1
138
|
function typeMatches(schema, value) {
|
|
2
139
|
switch (schema.type) {
|
|
3
|
-
case undefined:
|
|
4
|
-
|
|
5
|
-
case "
|
|
6
|
-
|
|
7
|
-
case "
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
11
|
-
case "integer":
|
|
12
|
-
return typeof value === "number" && Number.isInteger(value);
|
|
13
|
-
default:
|
|
14
|
-
return typeof value === schema.type;
|
|
140
|
+
case undefined: return true;
|
|
141
|
+
case "null": return value === null;
|
|
142
|
+
case "array": return Array.isArray(value);
|
|
143
|
+
case "object": return isRecord(value);
|
|
144
|
+
case "integer": return typeof value === "number" && Number.isInteger(value);
|
|
145
|
+
case "number": return typeof value === "number" && Number.isFinite(value);
|
|
146
|
+
default: return typeof value === schema.type;
|
|
15
147
|
}
|
|
16
148
|
}
|
|
17
149
|
export function validateAgentToolInput(schema, value, path = "input") {
|
|
18
|
-
if (!typeMatches(schema, value))
|
|
150
|
+
if (!typeMatches(schema, value))
|
|
19
151
|
return [`${path} must be ${schema.type}.`];
|
|
152
|
+
const errors = [];
|
|
153
|
+
if (schema.enum && !schema.enum.some((item) => jsonEqual(item, value)))
|
|
154
|
+
errors.push(`${path} must be one of the declared enum values.`);
|
|
155
|
+
if (typeof value === "string") {
|
|
156
|
+
const length = Array.from(value).length;
|
|
157
|
+
if (schema.minLength !== undefined && length < schema.minLength)
|
|
158
|
+
errors.push(`${path} must have at least ${schema.minLength} characters.`);
|
|
159
|
+
if (schema.maxLength !== undefined && length > schema.maxLength)
|
|
160
|
+
errors.push(`${path} must have at most ${schema.maxLength} characters.`);
|
|
161
|
+
if (schema.pattern !== undefined && !patternFor(schema, path).test(value))
|
|
162
|
+
errors.push(`${path} must match pattern ${schema.pattern}.`);
|
|
20
163
|
}
|
|
21
|
-
if (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
164
|
+
if (typeof value === "number") {
|
|
165
|
+
if (schema.minimum !== undefined && value < schema.minimum)
|
|
166
|
+
errors.push(`${path} must be >= ${schema.minimum}.`);
|
|
167
|
+
if (schema.maximum !== undefined && value > schema.maximum)
|
|
168
|
+
errors.push(`${path} must be <= ${schema.maximum}.`);
|
|
169
|
+
if (schema.exclusiveMinimum !== undefined && value <= schema.exclusiveMinimum)
|
|
170
|
+
errors.push(`${path} must be > ${schema.exclusiveMinimum}.`);
|
|
171
|
+
if (schema.exclusiveMaximum !== undefined && value >= schema.exclusiveMaximum)
|
|
172
|
+
errors.push(`${path} must be < ${schema.exclusiveMaximum}.`);
|
|
26
173
|
}
|
|
27
|
-
if (
|
|
28
|
-
|
|
174
|
+
if (Array.isArray(value)) {
|
|
175
|
+
if (schema.minItems !== undefined && value.length < schema.minItems)
|
|
176
|
+
errors.push(`${path} must have at least ${schema.minItems} items.`);
|
|
177
|
+
if (schema.maxItems !== undefined && value.length > schema.maxItems)
|
|
178
|
+
errors.push(`${path} must have at most ${schema.maxItems} items.`);
|
|
179
|
+
if (schema.uniqueItems && value.some((item, index) => value.slice(0, index).some((other) => jsonEqual(item, other))))
|
|
180
|
+
errors.push(`${path} must contain unique items.`);
|
|
181
|
+
if (schema.items)
|
|
182
|
+
value.forEach((item, index) => errors.push(...validateAgentToolInput(schema.items, item, `${path}[${index}]`)));
|
|
29
183
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
errors.push(`${path}.${key} is not allowed.`);
|
|
184
|
+
if (isRecord(value)) {
|
|
185
|
+
for (const key of schema.required ?? []) {
|
|
186
|
+
if (!Object.hasOwn(value, key))
|
|
187
|
+
errors.push(`${path}.${key} is required.`);
|
|
188
|
+
}
|
|
189
|
+
for (const [key, item] of Object.entries(value)) {
|
|
190
|
+
const property = schema.properties && Object.hasOwn(schema.properties, key) ? schema.properties[key] : undefined;
|
|
191
|
+
if (property)
|
|
192
|
+
errors.push(...validateAgentToolInput(property, item, `${path}.${key}`));
|
|
193
|
+
else if (schema.additionalProperties === false)
|
|
194
|
+
errors.push(`${path}.${key} is not allowed.`);
|
|
42
195
|
}
|
|
43
196
|
}
|
|
44
197
|
return errors;
|
package/dist/schema.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAEA,SAAS,WAAW,CAAC,MAAkB,EAAE,KAAc;IACrD,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,SAAS;YACZ,OAAO,IAAI,CAAC;QACd,KAAK,MAAM;YACT,OAAO,KAAK,KAAK,IAAI,CAAC;QACxB,KAAK,OAAO;YACV,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC9B,KAAK,QAAQ;YACX,OAAO,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC9E,KAAK,SAAS;YACZ,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC9D;YACE,OAAO,OAAO,KAAK,KAAK,MAAM,CAAC,IAAI,CAAC;IACxC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,MAAkB,EAClB,KAAc,EACd,IAAI,GAAG,OAAO;IAEd,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC;QAChC,OAAO,CAAC,GAAG,IAAI,YAAY,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;IAC7C,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC;QACvE,OAAO,CAAC,GAAG,IAAI,2CAA2C,CAAC,CAAC;IAC9D,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACpE,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CACnC,sBAAsB,CAAC,MAAM,CAAC,KAAM,EAAE,IAAI,EAAE,GAAG,IAAI,IAAI,KAAK,GAAG,CAAC,CACjE,CAAC;IACJ,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC5E,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,MAAM,GAAG,KAAgC,CAAC;IAChD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;QACxC,IAAI,CAAC,CAAC,GAAG,IAAI,MAAM,CAAC;YAAE,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,GAAG,eAAe,CAAC,CAAC;IACnE,CAAC;IACD,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACjD,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,CAAC;QAC1C,IAAI,QAAQ;YAAE,MAAM,CAAC,IAAI,CAAC,GAAG,sBAAsB,CAAC,QAAQ,EAAE,IAAI,EAAE,GAAG,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC;aAClF,IAAI,MAAM,CAAC,oBAAoB,KAAK,KAAK,EAAE,CAAC;YAC/C,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,GAAG,kBAAkB,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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","sourcesContent":["import type { JsonSchema } from \"./types.js\";\n\nconst types = new Set([\"object\", \"array\", \"string\", \"number\", \"integer\", \"boolean\", \"null\"]);\nconst counts = [\"minLength\", \"maxLength\", \"minItems\", \"maxItems\"] as const;\nconst bounds = [\"minimum\", \"maximum\", \"exclusiveMinimum\", \"exclusiveMaximum\"] as const;\nconst keywords = new Set([\n \"type\", \"description\", \"properties\", \"required\", \"items\", \"enum\", \"additionalProperties\",\n ...counts, ...bounds, \"pattern\", \"uniqueItems\",\n]);\nconst checkedSchemas = new WeakSet<object>();\nconst patterns = new WeakMap<object, { source: string; regex: RegExp }>();\n\nfunction invalid(path: string, message: string): never {\n throw new TypeError(`${path} ${message}`);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\n// Only deeply frozen, JSON-compatible values can safely share validation results.\nfunction assertJson(value: unknown, path: string, ancestors = new Set<object>()): boolean {\n if (value === null || typeof value === \"string\" || typeof value === \"boolean\") return true;\n if (typeof value === \"number\" && Number.isFinite(value)) return true;\n if (typeof value !== \"object\" || value === null) invalid(path, \"must be JSON-compatible.\");\n if (ancestors.has(value)) invalid(path, \"must not contain circular references.\");\n if (!Array.isArray(value) && Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) {\n invalid(path, \"must be a plain JSON object.\");\n }\n if (Object.getOwnPropertySymbols(value).length) invalid(path, \"must not contain symbol properties.\");\n for (const [key, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(value))) {\n if (!descriptor.enumerable && !(Array.isArray(value) && key === \"length\")) invalid(`${path}.${key}`, \"must be enumerable.\");\n if (descriptor.get || descriptor.set) invalid(`${path}.${key}`, \"must be a data property.\");\n }\n if (Array.isArray(value)) {\n for (let index = 0; index < value.length; index++) {\n if (!Object.hasOwn(value, index)) invalid(`${path}[${index}]`, \"must not be a sparse array slot.\");\n }\n }\n ancestors.add(value);\n let frozen = Object.isFrozen(value);\n for (const [key, child] of Object.entries(value)) {\n const childFrozen = assertJson(child, `${path}.${key}`, ancestors);\n frozen = frozen && childFrozen;\n }\n ancestors.delete(value);\n return frozen;\n}\n\nfunction patternFor(schema: JsonSchema, path: string): RegExp {\n const source = schema.pattern!;\n const cached = patterns.get(schema);\n if (cached?.source === source) return cached.regex;\n let regex: RegExp;\n try {\n regex = new RegExp(source, \"u\");\n } catch {\n invalid(`${path}.pattern`, \"must be a valid Unicode regular expression.\");\n }\n patterns.set(schema, { source, regex });\n return regex;\n}\n\nfunction assertSchema(value: unknown, path: string): void {\n if (!isRecord(value)) invalid(path, \"must be an object.\");\n const unexpected = Object.keys(value).filter((key) => !keywords.has(key));\n if (unexpected.length) invalid(path, `has unsupported fields: ${unexpected.join(\", \")}.`);\n if (value.type !== undefined && (typeof value.type !== \"string\" || !types.has(value.type))) invalid(`${path}.type`, \"is not supported.\");\n if (value.description !== undefined && typeof value.description !== \"string\") invalid(`${path}.description`, \"must be a string.\");\n for (const key of [\"additionalProperties\", \"uniqueItems\"] as const) {\n if (value[key] !== undefined && typeof value[key] !== \"boolean\") invalid(`${path}.${key}`, \"must be a boolean.\");\n }\n for (const key of counts) {\n const count = value[key];\n if (count !== undefined && (typeof count !== \"number\" || !Number.isInteger(count) || count < 0)) invalid(`${path}.${key}`, \"must be a non-negative integer.\");\n }\n for (const key of bounds) {\n if (value[key] !== undefined && (typeof value[key] !== \"number\" || !Number.isFinite(value[key]))) invalid(`${path}.${key}`, \"must be a finite number.\");\n }\n if (value.pattern !== undefined) {\n if (typeof value.pattern !== \"string\") invalid(`${path}.pattern`, \"must be a string.\");\n patternFor(value as JsonSchema, path);\n }\n if (value.enum !== undefined && (!Array.isArray(value.enum) || value.enum.length === 0)) invalid(`${path}.enum`, \"must be a non-empty array.\");\n if (Array.isArray(value.enum) && value.enum.some((item, index, entries) => entries.slice(0, index).some((other) => jsonEqual(item, other)))) invalid(`${path}.enum`, \"must contain unique values.\");\n if (value.properties !== undefined) {\n if (value.type !== \"object\" || !isRecord(value.properties)) invalid(`${path}.properties`, \"requires an object schema.\");\n for (const [name, property] of Object.entries(value.properties)) assertSchema(property, `${path}.properties.${name}`);\n }\n if (value.required !== undefined) {\n if (value.type !== \"object\" || !Array.isArray(value.required) || value.required.some((name) => typeof name !== \"string\") || new Set(value.required).size !== value.required.length) invalid(`${path}.required`, \"must contain unique property names.\");\n const properties = value.properties as Record<string, unknown> | undefined;\n if (value.required.some((name) => !properties || !Object.hasOwn(properties, name))) invalid(`${path}.required`, \"must reference declared properties.\");\n }\n if (value.items !== undefined) {\n if (value.type !== \"array\") invalid(`${path}.items`, \"requires an array schema.\");\n assertSchema(value.items, `${path}.items`);\n }\n}\n\nexport function assertAgentToolInputSchema(value: unknown, path = \"inputSchema\"): void {\n if (!isRecord(value) || value.type !== \"object\") invalid(path, 'root type must be object.');\n if (checkedSchemas.has(value)) return;\n const frozen = assertJson(value, path);\n assertSchema(value, path);\n if (frozen) checkedSchemas.add(value);\n}\n\nfunction jsonEqual(left: unknown, right: unknown): boolean {\n if (left === right) return true;\n if (Array.isArray(left) && Array.isArray(right)) return left.length === right.length && left.every((item, index) => jsonEqual(item, right[index]));\n if (!isRecord(left) || !isRecord(right)) return false;\n const keys = Object.keys(left);\n return keys.length === Object.keys(right).length && keys.every((key) => Object.hasOwn(right, key) && jsonEqual(left[key], right[key]));\n}\n\nfunction typeMatches(schema: JsonSchema, value: unknown): boolean {\n switch (schema.type) {\n case undefined: return true;\n case \"null\": return value === null;\n case \"array\": return Array.isArray(value);\n case \"object\": return isRecord(value);\n case \"integer\": return typeof value === \"number\" && Number.isInteger(value);\n case \"number\": return typeof value === \"number\" && Number.isFinite(value);\n default: return typeof value === schema.type;\n }\n}\n\nexport function validateAgentToolInput(schema: JsonSchema, value: unknown, path = \"input\"): string[] {\n if (!typeMatches(schema, value)) return [`${path} must be ${schema.type}.`];\n const errors: string[] = [];\n if (schema.enum && !schema.enum.some((item) => jsonEqual(item, value))) errors.push(`${path} must be one of the declared enum values.`);\n if (typeof value === \"string\") {\n const length = Array.from(value).length;\n if (schema.minLength !== undefined && length < schema.minLength) errors.push(`${path} must have at least ${schema.minLength} characters.`);\n if (schema.maxLength !== undefined && length > schema.maxLength) errors.push(`${path} must have at most ${schema.maxLength} characters.`);\n if (schema.pattern !== undefined && !patternFor(schema, path).test(value)) errors.push(`${path} must match pattern ${schema.pattern}.`);\n }\n if (typeof value === \"number\") {\n if (schema.minimum !== undefined && value < schema.minimum) errors.push(`${path} must be >= ${schema.minimum}.`);\n if (schema.maximum !== undefined && value > schema.maximum) errors.push(`${path} must be <= ${schema.maximum}.`);\n if (schema.exclusiveMinimum !== undefined && value <= schema.exclusiveMinimum) errors.push(`${path} must be > ${schema.exclusiveMinimum}.`);\n if (schema.exclusiveMaximum !== undefined && value >= schema.exclusiveMaximum) errors.push(`${path} must be < ${schema.exclusiveMaximum}.`);\n }\n if (Array.isArray(value)) {\n if (schema.minItems !== undefined && value.length < schema.minItems) errors.push(`${path} must have at least ${schema.minItems} items.`);\n if (schema.maxItems !== undefined && value.length > schema.maxItems) errors.push(`${path} must have at most ${schema.maxItems} items.`);\n if (schema.uniqueItems && value.some((item, index) => value.slice(0, index).some((other) => jsonEqual(item, other)))) errors.push(`${path} must contain unique items.`);\n if (schema.items) value.forEach((item, index) => errors.push(...validateAgentToolInput(schema.items!, item, `${path}[${index}]`)));\n }\n if (isRecord(value)) {\n for (const key of schema.required ?? []) {\n if (!Object.hasOwn(value, key)) errors.push(`${path}.${key} is required.`);\n }\n for (const [key, item] of Object.entries(value)) {\n const property = schema.properties && Object.hasOwn(schema.properties, key) ? schema.properties[key] : undefined;\n if (property) errors.push(...validateAgentToolInput(property, item, `${path}.${key}`));\n else if (schema.additionalProperties === false) errors.push(`${path}.${key} is not allowed.`);\n }\n }\n return errors;\n}\n"]}
|
package/dist/styles.css
CHANGED
|
@@ -8,11 +8,9 @@
|
|
|
8
8
|
.agent-operation__pointer-effect { position: fixed; z-index: 2; top: 0; left: 0; width: 0; height: 0; opacity: 1; pointer-events: none; transform: translate3d(var(--agent-operation-pointer-x),var(--agent-operation-pointer-y),0); transition: transform var(--agent-operation-pointer-duration) cubic-bezier(.22,1,.36,1),opacity .12s ease-out; will-change: transform,opacity; }
|
|
9
9
|
.agent-operation__pointer-effect[data-phase="hidden"] { opacity: 0; }
|
|
10
10
|
.agent-operation__pointer-cursor { position: absolute; z-index: 1; top: -4px; left: -3px; display: block; width: 24px; height: 24px; transform-origin: 4px 4px; }
|
|
11
|
-
.agent-operation__pointer-effect[data-active="true"][data-phase="resting"] .agent-operation__pointer-cursor { animation: agent-operation-pointer-float 1.6s ease-in-out infinite; }
|
|
12
|
-
.agent-operation__pointer-effect[data-phase="arrived"] .agent-operation__pointer-cursor { animation: agent-operation-pointer-press .11s ease-out both; }
|
|
13
|
-
.agent-operation__pointer-ripple { position: absolute; top: 0; left: 0; width: 64px; height: 64px; border: 2px solid rgba(79,124,255,.78); border-radius: 50%; opacity: 0; transform: translate(-50%,-50%) scale(.35); box-shadow: 0 0 18px rgba(96,156,245,.34); }
|
|
14
|
-
.agent-operation__pointer-ripple--primary { animation: agent-operation-pointer-ripple var(--agent-operation-ripple-duration) ease-out both; }
|
|
15
11
|
.agent-operation__pointer { position: relative; z-index: 2; display: block; color: #111827; filter: drop-shadow(0 0 1px #fff) drop-shadow(0 1px 2px rgba(15,23,42,.32)); }
|
|
12
|
+
.agent-operation__pointer-ripple { position: absolute; top: 0; left: 0; width: 64px; height: 64px; border: 2px solid rgba(79,124,255,.78); border-radius: 50%; opacity: 0; transform: translate(-50%,-50%) scale(.35); box-shadow: 0 0 18px rgba(96,156,245,.34); }
|
|
13
|
+
.agent-operation__pointer-ripple--primary { animation: agent-operation-pointer-ripple var(--agent-operation-ripple-duration) ease-out infinite; }
|
|
16
14
|
.agent-operation__pointer-label { position: absolute; z-index: 2; top: 27px; left: 19px; display: flex; max-width: min(300px,48vw); overflow: hidden; align-items: center; gap: 9px; border: 1px solid rgba(24,24,27,.1); border-radius: 11px; padding: 7px 11px; color: #27272a; background: rgba(255,255,255,.97); box-shadow: 0 6px 20px rgba(15,23,42,.13); font: 500 13px/1.35 Inter,ui-sans-serif,system-ui,sans-serif; white-space: nowrap; }
|
|
17
15
|
.agent-operation__pointer-label:is([data-operation-effect="read"],[data-operation-effect="navigate"]) { top: 12px; left: 10px; overflow: visible; gap: 5px; border: 0; padding: 0; background: transparent; box-shadow: none; }
|
|
18
16
|
.agent-operation__pointer-label-text { overflow: hidden; text-overflow: ellipsis; }
|
|
@@ -66,8 +64,6 @@
|
|
|
66
64
|
@keyframes agent-operation-edge-flow-reverse { 0% { right: -20%; opacity: 0; } 18%,76% { opacity: .8; } 100% { right: 100%; opacity: 0; } }
|
|
67
65
|
@keyframes agent-operation-edge-breathe { 50% { border-color: rgba(103,232,249,.42); } }
|
|
68
66
|
@keyframes agent-operation-pulse { 50% { border-color: #38bdf8; box-shadow: 0 0 0 6px rgba(99,102,241,.12),0 0 28px rgba(34,211,238,.4),0 0 58px rgba(79,70,229,.24); } }
|
|
69
|
-
@keyframes agent-operation-pointer-float { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-3px); } }
|
|
70
|
-
@keyframes agent-operation-pointer-press { 0%,100% { transform: translate(0) scale(1); } 48% { transform: translate(1px,1px) scale(.94); } }
|
|
71
67
|
@property --agent-operation-edge-primary-angle { syntax: "<angle>"; inherits: false; initial-value: 0deg; }
|
|
72
68
|
@property --agent-operation-edge-secondary-angle { syntax: "<angle>"; inherits: false; initial-value: 0deg; }
|
|
73
69
|
@keyframes agent-operation-surface-edge-primary { 0% { --agent-operation-edge-primary-angle: 0deg; animation-timing-function: cubic-bezier(.4,.25,.6,.75); } 100% { --agent-operation-edge-primary-angle: 360deg; } }
|
|
@@ -77,7 +73,7 @@
|
|
|
77
73
|
@keyframes agent-operation-pointer-ripple { 0% { opacity: .82; transform: translate(-50%,-50%) scale(.35); } 100% { opacity: 0; transform: translate(-50%,-50%) scale(1.45); } }
|
|
78
74
|
@keyframes agent-operation-pointer-read-bar { 0%,18%,100% { opacity: .34; transform: scaleY(.58); box-shadow: none; } 42% { opacity: 1; transform: scaleY(1.27); box-shadow: 0 0 6px rgba(96,156,245,.52); } 68% { opacity: .58; transform: scaleY(.78); box-shadow: none; } }
|
|
79
75
|
@keyframes agent-operation-pointer-navigation-chevron { 0%,100% { opacity: .24; transform: translateX(-3px) rotate(45deg); } 48% { opacity: 1; transform: translateX(2px) rotate(45deg); } 72% { opacity: .62; transform: translateX(4px) rotate(45deg); } }
|
|
80
|
-
@media (prefers-reduced-motion: reduce) { .agent-operation__surface,.agent-operation__target,.agent-operation__controller,.agent-operation__activity i,.agent-operation__edge-flow::before,.agent-operation__edge-flow::after,.agent-operation__pointer-
|
|
76
|
+
@media (prefers-reduced-motion: reduce) { .agent-operation__surface,.agent-operation__target,.agent-operation__controller,.agent-operation__activity i,.agent-operation__edge-flow::before,.agent-operation__edge-flow::after,.agent-operation__pointer-read-scan i,.agent-operation__pointer-navigation-trail::before,.agent-operation__pointer-navigation-trail::after { animation: none; } .agent-operation__pointer-effect { transition: none; } .agent-operation__surface::before,.agent-operation__surface::after { display: none; } }
|
|
81
77
|
@media (max-width:520px) { .agent-operation__controller { --agent-operation-controller-x: 0%; right: 12px; bottom: 12px; left: 12px; width: auto; min-width: 0; } .agent-operation__controller>.agent-operation__history { width: 100%; } }
|
|
82
78
|
|
|
83
79
|
.nexface-operation-surface { width: 100%; height: 100%; min-width: 0; min-height: 0; overflow: auto; }
|
|
@@ -187,3 +183,11 @@
|
|
|
187
183
|
.agent-operation, .agent-operation *, .agent-operation::before, .agent-operation::after, .agent-operation *::before, .agent-operation *::after { box-sizing: border-box; }
|
|
188
184
|
.agent-operation__pointer-navigation-trail::before,.agent-operation__pointer-navigation-trail::after { box-sizing: content-box; }
|
|
189
185
|
.agent-operation__pointer-indicator { position: absolute; top: 12px; left: 10px; display: flex; align-items: center; gap: 5px; }
|
|
186
|
+
|
|
187
|
+
.agent-operation__pointer-processing { display: inline-block; flex: none; width: 16px; height: 16px; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: agent-operation-processing-spin .8s linear infinite; }
|
|
188
|
+
@keyframes agent-operation-processing-spin { to { transform: rotate(360deg); } }
|
|
189
|
+
@media (prefers-reduced-motion: reduce) { .agent-operation__pointer-processing { animation: none; } }
|
|
190
|
+
|
|
191
|
+
@media (prefers-reduced-motion: reduce) {
|
|
192
|
+
.agent-operation__pointer-ripple--primary { animation: none; opacity: .6; transform: translate(-50%,-50%) scale(1); }
|
|
193
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
export type JsonSchema = {
|
|
2
2
|
type?: "object" | "array" | "string" | "number" | "integer" | "boolean" | "null";
|
|
3
3
|
description?: string;
|
|
4
|
+
minLength?: number;
|
|
5
|
+
maxLength?: number;
|
|
6
|
+
pattern?: string;
|
|
7
|
+
minimum?: number;
|
|
8
|
+
maximum?: number;
|
|
9
|
+
exclusiveMinimum?: number;
|
|
10
|
+
exclusiveMaximum?: number;
|
|
11
|
+
minItems?: number;
|
|
12
|
+
maxItems?: number;
|
|
13
|
+
uniqueItems?: boolean;
|
|
4
14
|
properties?: Record<string, JsonSchema>;
|
|
5
15
|
required?: readonly string[];
|
|
6
16
|
items?: JsonSchema;
|
|
@@ -53,7 +63,7 @@ export type AgentContextValue = string | number | boolean | null | readonly Agen
|
|
|
53
63
|
};
|
|
54
64
|
export interface AgentContextEntry {
|
|
55
65
|
name: string;
|
|
56
|
-
description
|
|
66
|
+
description?: string;
|
|
57
67
|
value: AgentContextValue;
|
|
58
68
|
}
|
|
59
69
|
export type AgentContextInput = AgentContextEntry;
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["export type JsonSchema = {\n type?: \"object\" | \"array\" | \"string\" | \"number\" | \"integer\" | \"boolean\" | \"null\";\n description?: string;\n minLength?: number;\n maxLength?: number;\n pattern?: string;\n minimum?: number;\n maximum?: number;\n exclusiveMinimum?: number;\n exclusiveMaximum?: number;\n minItems?: number;\n maxItems?: number;\n uniqueItems?: boolean;\n properties?: Record<string, JsonSchema>;\n required?: readonly string[];\n items?: JsonSchema;\n enum?: readonly unknown[];\n additionalProperties?: boolean;\n};\n\nexport type AgentToolInputSchema = JsonSchema & {\n type: \"object\";\n};\n\ntype Simplify<TValue> = { [TKey in keyof TValue]: TValue[TKey] };\n\ntype RequiredPropertyKeys<\n TSchema extends JsonSchema,\n TProperties extends Record<string, JsonSchema>,\n> = TSchema extends { readonly required: readonly (infer TKey)[] }\n ? Extract<TKey, keyof TProperties>\n : never;\n\ntype InferObjectSchema<\n TSchema extends JsonSchema,\n TProperties extends Record<string, JsonSchema>,\n> = keyof TProperties extends never\n ? TSchema extends { readonly additionalProperties: false }\n ? Record<string, never>\n : Record<string, unknown>\n : Simplify<{\n [TKey in RequiredPropertyKeys<TSchema, TProperties>]-?: InferJsonSchema<\n TProperties[TKey]\n >;\n } & {\n [TKey in Exclude<\n keyof TProperties,\n RequiredPropertyKeys<TSchema, TProperties>\n >]?: InferJsonSchema<TProperties[TKey]>;\n }> & (TSchema extends { readonly additionalProperties: false }\n ? unknown\n : Record<string, unknown>);\n\nexport type InferJsonSchema<TSchema extends JsonSchema> =\n TSchema extends { readonly enum: readonly (infer TValue)[] }\n ? TValue\n : TSchema extends { readonly type: \"string\" }\n ? string\n : TSchema extends { readonly type: \"number\" | \"integer\" }\n ? number\n : TSchema extends { readonly type: \"boolean\" }\n ? boolean\n : TSchema extends { readonly type: \"null\" }\n ? null\n : TSchema extends {\n readonly type: \"array\";\n readonly items: infer TItem extends JsonSchema;\n }\n ? InferJsonSchema<TItem>[]\n : TSchema extends { readonly type: \"array\" }\n ? unknown[]\n : TSchema extends {\n readonly type: \"object\";\n readonly properties: infer TProperties extends Record<\n string,\n JsonSchema\n >;\n }\n ? InferObjectSchema<TSchema, TProperties>\n : TSchema extends { readonly type: \"object\" }\n ? TSchema extends { readonly additionalProperties: false }\n ? Record<string, never>\n : Record<string, unknown>\n : unknown;\n\nexport type AgentContextValue =\n | string\n | number\n | boolean\n | null\n | readonly AgentContextValue[]\n | { readonly [key: string]: AgentContextValue };\n\nexport interface AgentContextEntry {\n name: string;\n description?: string;\n value: AgentContextValue;\n}\n\nexport type AgentContextInput = AgentContextEntry;\n\nexport interface AgentContextRegistration {\n update(context: AgentContextInput): void;\n dispose(): void;\n}\n\nexport interface AgentToolMetadata {\n name: string;\n description: string;\n inputSchema: AgentToolInputSchema;\n effect: AgentToolEffect;\n}\n\nexport type AgentToolEffect = \"read\" | \"action\" | \"navigate\";\n\nexport interface AgentToolDefinition<\n TInput = Record<string, unknown>,\n TResult = unknown,\n>\n extends AgentToolMetadata {\n readonly __input?: TInput;\n readonly __result?: TResult;\n}\n\nexport interface AgentToolExecutionContext {\n signal: AbortSignal;\n waitForTool(\n definition: AgentToolDefinition<any, any>,\n options?: { timeoutMs?: number },\n ): Promise<void>;\n}\n\nexport type AgentToolExecutor<TInput, TResult> = (\n input: TInput,\n context: AgentToolExecutionContext,\n) => TResult | Promise<TResult>;\n"]}
|
package/dist/webmcp.js
CHANGED
|
@@ -2,19 +2,145 @@ function getWebMcpModelContext() {
|
|
|
2
2
|
if (typeof document === "undefined")
|
|
3
3
|
return undefined;
|
|
4
4
|
const modelContext = document.modelContext;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
if (typeof modelContext?.registerTool === "function")
|
|
6
|
+
return modelContext;
|
|
7
|
+
if (typeof navigator === "undefined")
|
|
8
|
+
return undefined;
|
|
9
|
+
const legacy = navigator.modelContext;
|
|
10
|
+
if (typeof legacy?.registerTool !== "function" || typeof legacy.unregisterTool !== "function")
|
|
11
|
+
return undefined;
|
|
12
|
+
return adaptLegacyModelContext(legacy);
|
|
13
|
+
}
|
|
14
|
+
function adaptLegacyModelContext(legacy) {
|
|
15
|
+
return {
|
|
16
|
+
registerTool(tool, options = {}) {
|
|
17
|
+
const { signal } = options;
|
|
18
|
+
signal?.throwIfAborted();
|
|
19
|
+
// The legacy callback receives an agent, not execution cancellation options.
|
|
20
|
+
legacy.registerTool({ ...tool, execute: (input) => tool.execute(input) });
|
|
21
|
+
const unregister = () => {
|
|
22
|
+
try {
|
|
23
|
+
legacy.unregisterTool(tool.name);
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
console.warn(`Unable to unregister WebMCP Tool "${tool.name}".`, error);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
// Only a successful registration owns the name and may unregister it.
|
|
30
|
+
if (signal?.aborted)
|
|
31
|
+
unregister();
|
|
32
|
+
else
|
|
33
|
+
signal?.addEventListener("abort", unregister, { once: true });
|
|
34
|
+
return Promise.resolve();
|
|
35
|
+
},
|
|
36
|
+
};
|
|
8
37
|
}
|
|
9
38
|
function warnWebMcpRegistration(name, error) {
|
|
10
39
|
console.warn(`Unable to register WebMCP Tool "${name}".`, error);
|
|
11
40
|
}
|
|
41
|
+
const connections = new WeakMap();
|
|
42
|
+
const pendingDisposals = new Map();
|
|
43
|
+
function disposeUnusedConnection(runtime, connection) {
|
|
44
|
+
if (connection.refs || connections.get(runtime) !== connection)
|
|
45
|
+
return;
|
|
46
|
+
pendingDisposals.delete(runtime);
|
|
47
|
+
connections.delete(runtime);
|
|
48
|
+
connection.dispose();
|
|
49
|
+
}
|
|
12
50
|
export function connectToolRuntimeToWebMcp(runtime) {
|
|
13
|
-
|
|
14
|
-
if (!
|
|
15
|
-
|
|
51
|
+
let connection = connections.get(runtime);
|
|
52
|
+
if (!connection) {
|
|
53
|
+
const modelContext = getWebMcpModelContext();
|
|
54
|
+
if (!modelContext)
|
|
55
|
+
return () => undefined;
|
|
56
|
+
// Release names before a replacement Runtime starts publishing its tools.
|
|
57
|
+
for (const [previousRuntime, previous] of pendingDisposals) {
|
|
58
|
+
disposeUnusedConnection(previousRuntime, previous);
|
|
59
|
+
}
|
|
60
|
+
// Install the shared connection before registration can synchronously notify listeners.
|
|
61
|
+
connection = { refs: 0, dispose: () => { } };
|
|
62
|
+
connections.set(runtime, connection);
|
|
63
|
+
connection.dispose = createConnection(runtime, modelContext);
|
|
64
|
+
}
|
|
65
|
+
pendingDisposals.delete(runtime);
|
|
66
|
+
connection.refs += 1;
|
|
67
|
+
const current = connection;
|
|
68
|
+
let released = false;
|
|
69
|
+
return () => {
|
|
70
|
+
if (released)
|
|
71
|
+
return;
|
|
72
|
+
released = true;
|
|
73
|
+
current.refs -= 1;
|
|
74
|
+
if (current.refs)
|
|
75
|
+
return;
|
|
76
|
+
// A same-Runtime reconnect can still reuse this connection in Strict Mode.
|
|
77
|
+
pendingDisposals.set(runtime, current);
|
|
78
|
+
queueMicrotask(() => disposeUnusedConnection(runtime, current));
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function createConnection(runtime, modelContext) {
|
|
16
82
|
const registrations = new Map();
|
|
17
83
|
let disposed = false;
|
|
84
|
+
let operation;
|
|
85
|
+
const controls = new AbortController();
|
|
86
|
+
const begin = {
|
|
87
|
+
name: "beginOperation",
|
|
88
|
+
description: "Begin a continuous page operation before using page tools. Call endOperation with the returned operationId when all page work is done, before your final response. Repeated begin returns the same active operation. Omitting begin shows feedback only while each tool executes.",
|
|
89
|
+
inputSchema: { type: "object", properties: {}, additionalProperties: false },
|
|
90
|
+
execute: async (input, options = {}) => {
|
|
91
|
+
options.signal?.throwIfAborted();
|
|
92
|
+
controls.signal.throwIfAborted();
|
|
93
|
+
if (!input || typeof input !== "object" || Array.isArray(input) || Object.keys(input).length)
|
|
94
|
+
throw new TypeError("beginOperation requires {}.");
|
|
95
|
+
const current = runtime.getActivitySnapshot().operation;
|
|
96
|
+
if (operation && current?.id === operation.id) {
|
|
97
|
+
return { status: current.status === "ending" ? "ending" : "active", operationId: operation.id };
|
|
98
|
+
}
|
|
99
|
+
operation = undefined;
|
|
100
|
+
try {
|
|
101
|
+
operation = runtime.beginInternalOperation({ source: "webmcp" });
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
if (error.code === "OPERATION_BUSY")
|
|
105
|
+
return { status: "busy" };
|
|
106
|
+
throw error;
|
|
107
|
+
}
|
|
108
|
+
return { status: "active", operationId: operation.id };
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
const end = {
|
|
112
|
+
name: "endOperation",
|
|
113
|
+
description: "End the page operation identified by operationId after all page work. Waits for its admitted tools to settle. Does not stop an external agent or undo changes.",
|
|
114
|
+
inputSchema: { type: "object", properties: { operationId: { type: "string" } }, required: ["operationId"], additionalProperties: false },
|
|
115
|
+
execute: async (input, options = {}) => {
|
|
116
|
+
options.signal?.throwIfAborted();
|
|
117
|
+
controls.signal.throwIfAborted();
|
|
118
|
+
const args = input;
|
|
119
|
+
if (!args || typeof args !== "object" || Array.isArray(args) || typeof args.operationId !== "string" || Object.keys(args).some((key) => key !== "operationId"))
|
|
120
|
+
throw new TypeError("endOperation requires { operationId: string }.");
|
|
121
|
+
const operationId = args.operationId;
|
|
122
|
+
const owned = operation;
|
|
123
|
+
if (!owned || owned.id !== operationId || runtime.getActivitySnapshot().operation?.id !== operationId)
|
|
124
|
+
return { status: "not_active", operationId };
|
|
125
|
+
await owned.end();
|
|
126
|
+
if (operation === owned)
|
|
127
|
+
operation = undefined;
|
|
128
|
+
return { status: "ended", operationId };
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
const registerControls = async () => {
|
|
132
|
+
try {
|
|
133
|
+
await modelContext.registerTool(end, { signal: controls.signal });
|
|
134
|
+
controls.signal.throwIfAborted();
|
|
135
|
+
await modelContext.registerTool(begin, { signal: controls.signal });
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
const aborted = controls.signal.aborted;
|
|
139
|
+
controls.abort();
|
|
140
|
+
if (!disposed && !aborted)
|
|
141
|
+
warnWebMcpRegistration("beginOperation/endOperation", error);
|
|
142
|
+
}
|
|
143
|
+
};
|
|
18
144
|
const register = (tool) => {
|
|
19
145
|
const { definition } = tool;
|
|
20
146
|
const controller = new AbortController();
|
|
@@ -25,8 +151,31 @@ export function connectToolRuntimeToWebMcp(runtime) {
|
|
|
25
151
|
result = modelContext.registerTool({
|
|
26
152
|
name: definition.name,
|
|
27
153
|
description: definition.description,
|
|
28
|
-
inputSchema:
|
|
29
|
-
|
|
154
|
+
inputSchema: {
|
|
155
|
+
type: "object",
|
|
156
|
+
properties: {
|
|
157
|
+
input: definition.inputSchema ?? { type: "object", properties: {}, additionalProperties: false },
|
|
158
|
+
progressLabel: {
|
|
159
|
+
type: "string",
|
|
160
|
+
description: "Briefly describe this tool action in the user’s language. Do not expose internal identifiers or claim success before completion.",
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
required: ["input"],
|
|
164
|
+
additionalProperties: false,
|
|
165
|
+
},
|
|
166
|
+
execute: async (parameters, options = {}) => {
|
|
167
|
+
const args = parameters;
|
|
168
|
+
if (!args || typeof args !== "object" || Array.isArray(args)
|
|
169
|
+
|| !args.input || typeof args.input !== "object" || Array.isArray(args.input)
|
|
170
|
+
|| Object.keys(args).some((key) => key !== "input" && key !== "progressLabel")
|
|
171
|
+
|| (args.progressLabel !== undefined && typeof args.progressLabel !== "string")) {
|
|
172
|
+
throw new TypeError("WebMCP tools require { input: object, progressLabel?: string }.");
|
|
173
|
+
}
|
|
174
|
+
return runtime.executeWithProgress(tool, args.input, {
|
|
175
|
+
...(options.signal ? { signal: options.signal } : {}),
|
|
176
|
+
...(typeof args.progressLabel === "string" ? { progressLabel: args.progressLabel } : {}),
|
|
177
|
+
});
|
|
178
|
+
},
|
|
30
179
|
}, { signal: controller.signal });
|
|
31
180
|
}
|
|
32
181
|
catch (error) {
|
|
@@ -44,7 +193,7 @@ export function connectToolRuntimeToWebMcp(runtime) {
|
|
|
44
193
|
});
|
|
45
194
|
};
|
|
46
195
|
const reconcile = () => {
|
|
47
|
-
const tools = new Map(runtime.getWebMcpTools().map((tool) => [tool.definition.name, tool]));
|
|
196
|
+
const tools = new Map(runtime.getWebMcpTools().filter((tool) => !["beginOperation", "endOperation"].includes(tool.definition.name)).map((tool) => [tool.definition.name, tool]));
|
|
48
197
|
for (const [name, registration] of registrations) {
|
|
49
198
|
if (tools.get(name) === registration.tool)
|
|
50
199
|
continue;
|
|
@@ -59,10 +208,15 @@ export function connectToolRuntimeToWebMcp(runtime) {
|
|
|
59
208
|
const unsubscribeRuntime = runtime.on("toolchange", reconcile);
|
|
60
209
|
modelContext.addEventListener?.("toolchange", reconcile);
|
|
61
210
|
reconcile();
|
|
211
|
+
void registerControls();
|
|
62
212
|
return () => {
|
|
63
213
|
if (disposed)
|
|
64
214
|
return;
|
|
65
215
|
disposed = true;
|
|
216
|
+
controls.abort();
|
|
217
|
+
if (operation)
|
|
218
|
+
void runtime.endBridgeOperation(operation);
|
|
219
|
+
operation = undefined;
|
|
66
220
|
unsubscribeRuntime();
|
|
67
221
|
modelContext.removeEventListener?.("toolchange", reconcile);
|
|
68
222
|
for (const registration of registrations.values()) {
|