@nexface/tools 0.1.14 → 0.1.15-alpha.1
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/actions.js +10 -34
- package/dist/browser/actions.js.map +1 -0
- package/dist/browser/controller.js +74 -53
- package/dist/browser/controller.js.map +1 -0
- package/dist/browser/diagnostics.js +3 -8
- package/dist/browser/diagnostics.js.map +1 -0
- package/dist/browser/dom.js +28 -12
- package/dist/browser/dom.js.map +1 -0
- package/dist/browser/feedback.js +5 -6
- package/dist/browser/feedback.js.map +1 -0
- package/dist/browser/focus.js +1 -0
- package/dist/browser/focus.js.map +1 -0
- package/dist/browser/locator.js +9 -3
- package/dist/browser/locator.js.map +1 -0
- package/dist/browser/prompt.generated.js +1 -0
- package/dist/browser/prompt.generated.js.map +1 -0
- package/dist/browser/prompt.js +1 -0
- package/dist/browser/prompt.js.map +1 -0
- package/dist/browser/snapshot.js +22 -10
- package/dist/browser/snapshot.js.map +1 -0
- package/dist/browser/toolset.js +36 -42
- package/dist/browser/toolset.js.map +1 -0
- package/dist/browser/types.d.ts +1 -1
- package/dist/browser/types.js +1 -0
- package/dist/browser/types.js.map +1 -0
- package/dist/browser/worker-runner.js +1 -0
- package/dist/browser/worker-runner.js.map +1 -0
- package/dist/definition.d.ts +3 -1
- package/dist/definition.js +2 -2
- package/dist/definition.js.map +1 -0
- package/dist/index.browser.js +1 -0
- package/dist/index.browser.js.map +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -0
- package/dist/internal-react.d.ts +1 -1
- package/dist/internal-react.js +4 -3
- package/dist/internal-react.js.map +1 -0
- package/dist/internal-types.js +1 -0
- package/dist/internal-types.js.map +1 -0
- package/dist/navigation.js +1 -0
- package/dist/navigation.js.map +1 -0
- package/dist/operation-lock.js +2 -36
- package/dist/operation-lock.js.map +1 -0
- package/dist/operation-runtime.js +13 -41
- package/dist/operation-runtime.js.map +1 -0
- package/dist/operation-surface.js +41 -118
- package/dist/operation-surface.js.map +1 -0
- package/dist/operation-types.js +1 -0
- package/dist/operation-types.js.map +1 -0
- package/dist/operation-view.d.ts +1 -1
- package/dist/operation-view.js +60 -120
- package/dist/operation-view.js.map +1 -0
- package/dist/react.js +12 -9
- package/dist/react.js.map +1 -0
- package/dist/registration.d.ts +3 -0
- package/dist/registration.js +7 -5
- package/dist/registration.js.map +1 -0
- package/dist/runtime.d.ts +17 -6
- package/dist/runtime.js +59 -105
- package/dist/runtime.js.map +1 -0
- package/dist/shared/definition.js +1 -0
- package/dist/shared/definition.js.map +1 -0
- package/dist/shared/errors.d.ts +1 -1
- package/dist/shared/errors.js +1 -0
- package/dist/shared/errors.js.map +1 -0
- package/dist/shared/page-protocol.js +1 -0
- package/dist/shared/page-protocol.js.map +1 -0
- package/dist/shared/page-tools.js +1 -0
- package/dist/shared/page-tools.js.map +1 -0
- package/dist/shared/runtime-controller.d.ts +0 -1
- package/dist/shared/runtime-controller.js +1 -0
- package/dist/shared/runtime-controller.js.map +1 -0
- package/dist/shared/runtime-execution.js +1 -0
- package/dist/shared/runtime-execution.js.map +1 -0
- package/dist/shared/schema.js +19 -45
- package/dist/shared/schema.js.map +1 -0
- package/dist/styles.css +109 -879
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -0
- package/dist/webmcp.js +12 -38
- package/dist/webmcp.js.map +1 -0
- package/package.json +2 -6
- package/dist/tool-search.d.ts +0 -11
- package/dist/tool-search.js +0 -117
package/dist/types.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
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
|
@@ -94,10 +94,7 @@ function createConnection(runtime, modelContext) {
|
|
|
94
94
|
throw new TypeError("nxf_beginOperation requires {}.");
|
|
95
95
|
const current = runtime.getActivitySnapshot().operation;
|
|
96
96
|
if (operation && current?.id === operation.id) {
|
|
97
|
-
return {
|
|
98
|
-
status: current.status === "ending" ? "ending" : "active",
|
|
99
|
-
operationId: operation.id,
|
|
100
|
-
};
|
|
97
|
+
return { status: current.status === "ending" ? "ending" : "active", operationId: operation.id };
|
|
101
98
|
}
|
|
102
99
|
operation = undefined;
|
|
103
100
|
try {
|
|
@@ -114,27 +111,16 @@ function createConnection(runtime, modelContext) {
|
|
|
114
111
|
const end = {
|
|
115
112
|
name: "nxf_endOperation",
|
|
116
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.",
|
|
117
|
-
inputSchema: {
|
|
118
|
-
type: "object",
|
|
119
|
-
properties: { operationId: { type: "string" } },
|
|
120
|
-
required: ["operationId"],
|
|
121
|
-
additionalProperties: false,
|
|
122
|
-
},
|
|
114
|
+
inputSchema: { type: "object", properties: { operationId: { type: "string" } }, required: ["operationId"], additionalProperties: false },
|
|
123
115
|
execute: async (input, options = {}) => {
|
|
124
116
|
options.signal?.throwIfAborted();
|
|
125
117
|
controls.signal.throwIfAborted();
|
|
126
118
|
const args = input;
|
|
127
|
-
if (!args ||
|
|
128
|
-
typeof args !== "object" ||
|
|
129
|
-
Array.isArray(args) ||
|
|
130
|
-
typeof args.operationId !== "string" ||
|
|
131
|
-
Object.keys(args).some((key) => key !== "operationId"))
|
|
119
|
+
if (!args || typeof args !== "object" || Array.isArray(args) || typeof args.operationId !== "string" || Object.keys(args).some((key) => key !== "operationId"))
|
|
132
120
|
throw new TypeError("nxf_endOperation requires { operationId: string }.");
|
|
133
121
|
const operationId = args.operationId;
|
|
134
122
|
const owned = operation;
|
|
135
|
-
if (!owned ||
|
|
136
|
-
owned.id !== operationId ||
|
|
137
|
-
runtime.getActivitySnapshot().operation?.id !== operationId)
|
|
123
|
+
if (!owned || owned.id !== operationId || runtime.getActivitySnapshot().operation?.id !== operationId)
|
|
138
124
|
return { status: "not_active", operationId };
|
|
139
125
|
await owned.end();
|
|
140
126
|
if (operation === owned)
|
|
@@ -168,11 +154,7 @@ function createConnection(runtime, modelContext) {
|
|
|
168
154
|
inputSchema: {
|
|
169
155
|
type: "object",
|
|
170
156
|
properties: {
|
|
171
|
-
input: definition.inputSchema ?? {
|
|
172
|
-
type: "object",
|
|
173
|
-
properties: {},
|
|
174
|
-
additionalProperties: false,
|
|
175
|
-
},
|
|
157
|
+
input: definition.inputSchema ?? { type: "object", properties: {}, additionalProperties: false },
|
|
176
158
|
progressLabel: {
|
|
177
159
|
type: "string",
|
|
178
160
|
description: "Briefly describe this tool action in the user’s language. Do not expose internal identifiers or claim success before completion.",
|
|
@@ -183,21 +165,15 @@ function createConnection(runtime, modelContext) {
|
|
|
183
165
|
},
|
|
184
166
|
execute: async (parameters, options = {}) => {
|
|
185
167
|
const args = parameters;
|
|
186
|
-
if (!args ||
|
|
187
|
-
typeof args !== "object" ||
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
typeof args.input !== "object" ||
|
|
191
|
-
Array.isArray(args.input) ||
|
|
192
|
-
Object.keys(args).some((key) => key !== "input" && key !== "progressLabel") ||
|
|
193
|
-
(args.progressLabel !== undefined && typeof args.progressLabel !== "string")) {
|
|
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")) {
|
|
194
172
|
throw new TypeError("WebMCP tools require { input: object, progressLabel?: string }.");
|
|
195
173
|
}
|
|
196
174
|
return runtime.execute(tool, args.input, {
|
|
197
175
|
...(options.signal ? { signal: options.signal } : {}),
|
|
198
|
-
...(typeof args.progressLabel === "string"
|
|
199
|
-
? { progressLabel: args.progressLabel }
|
|
200
|
-
: {}),
|
|
176
|
+
...(typeof args.progressLabel === "string" ? { progressLabel: args.progressLabel } : {}),
|
|
201
177
|
});
|
|
202
178
|
},
|
|
203
179
|
}, { signal: controller.signal });
|
|
@@ -217,10 +193,7 @@ function createConnection(runtime, modelContext) {
|
|
|
217
193
|
});
|
|
218
194
|
};
|
|
219
195
|
const reconcile = () => {
|
|
220
|
-
const tools = new Map(runtime
|
|
221
|
-
.getWebMcpTools()
|
|
222
|
-
.filter((tool) => !["nxf_beginOperation", "nxf_endOperation"].includes(tool.definition.name))
|
|
223
|
-
.map((tool) => [tool.definition.name, tool]));
|
|
196
|
+
const tools = new Map(runtime.getWebMcpTools().filter((tool) => !["nxf_beginOperation", "nxf_endOperation"].includes(tool.definition.name)).map((tool) => [tool.definition.name, tool]));
|
|
224
197
|
for (const [name, registration] of registrations) {
|
|
225
198
|
if (tools.get(name) === registration.tool)
|
|
226
199
|
continue;
|
|
@@ -252,3 +225,4 @@ function createConnection(runtime, modelContext) {
|
|
|
252
225
|
registrations.clear();
|
|
253
226
|
};
|
|
254
227
|
}
|
|
228
|
+
//# sourceMappingURL=webmcp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webmcp.js","sourceRoot":"","sources":["../src/webmcp.ts"],"names":[],"mappings":"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","sourcesContent":["import type { InternalToolRuntime, RuntimeAgentTool, ToolOperation } from \"./runtime.js\";\n\ninterface WebMcpTool {\n name: string;\n description: string;\n inputSchema: object;\n execute(input: object, options?: { signal?: AbortSignal }): Promise<unknown>;\n}\n\ninterface WebMcpModelContext {\n addEventListener?(type: \"toolchange\", listener: EventListener): void;\n removeEventListener?(type: \"toolchange\", listener: EventListener): void;\n registerTool(\n tool: WebMcpTool,\n options?: { signal?: AbortSignal },\n ): Promise<void>;\n}\n\ninterface LegacyWebMcpModelContext {\n registerTool(tool: Omit<WebMcpTool, \"execute\"> & {\n execute(input: object, agent?: unknown): Promise<unknown>;\n }): void;\n unregisterTool(name: string): void;\n}\n\ntype WebMcpRegistration = {\n controller: AbortController;\n tool: RuntimeAgentTool;\n};\n\nfunction getWebMcpModelContext(): WebMcpModelContext | undefined {\n if (typeof document === \"undefined\") return undefined;\n const modelContext = (document as Document & {\n modelContext?: Partial<WebMcpModelContext>;\n }).modelContext;\n if (typeof modelContext?.registerTool === \"function\") return modelContext as WebMcpModelContext;\n if (typeof navigator === \"undefined\") return undefined;\n const legacy = (navigator as Navigator & {\n modelContext?: Partial<LegacyWebMcpModelContext>;\n }).modelContext;\n if (typeof legacy?.registerTool !== \"function\" || typeof legacy.unregisterTool !== \"function\") return undefined;\n return adaptLegacyModelContext(legacy as LegacyWebMcpModelContext);\n}\n\nfunction adaptLegacyModelContext(legacy: LegacyWebMcpModelContext): WebMcpModelContext {\n return {\n registerTool(tool, options = {}) {\n const { signal } = options;\n signal?.throwIfAborted();\n // The legacy callback receives an agent, not execution cancellation options.\n legacy.registerTool({ ...tool, execute: (input) => tool.execute(input) });\n const unregister = () => {\n try { legacy.unregisterTool(tool.name); }\n catch (error) { console.warn(`Unable to unregister WebMCP Tool \"${tool.name}\".`, error); }\n };\n // Only a successful registration owns the name and may unregister it.\n if (signal?.aborted) unregister();\n else signal?.addEventListener(\"abort\", unregister, { once: true });\n return Promise.resolve();\n },\n };\n}\n\nfunction warnWebMcpRegistration(name: string, error: unknown): void {\n console.warn(`Unable to register WebMCP Tool \"${name}\".`, error);\n}\n\ntype WebMcpConnection = { refs: number; dispose(): void };\n\nconst connections = new WeakMap<InternalToolRuntime, WebMcpConnection>();\nconst pendingDisposals = new Map<InternalToolRuntime, WebMcpConnection>();\n\nfunction disposeUnusedConnection(runtime: InternalToolRuntime, connection: WebMcpConnection): void {\n if (connection.refs || connections.get(runtime) !== connection) return;\n pendingDisposals.delete(runtime);\n connections.delete(runtime);\n connection.dispose();\n}\n\nexport function connectToolRuntimeToWebMcp(runtime: InternalToolRuntime): () => void {\n let connection = connections.get(runtime);\n if (!connection) {\n const modelContext = getWebMcpModelContext();\n if (!modelContext) return () => undefined;\n // Release names before a replacement Runtime starts publishing its tools.\n for (const [previousRuntime, previous] of pendingDisposals) {\n disposeUnusedConnection(previousRuntime, previous);\n }\n // Install the shared connection before registration can synchronously notify listeners.\n connection = { refs: 0, dispose: () => {} };\n connections.set(runtime, connection);\n connection.dispose = createConnection(runtime, modelContext);\n }\n pendingDisposals.delete(runtime);\n connection.refs += 1;\n const current = connection;\n let released = false;\n return () => {\n if (released) return;\n released = true;\n current.refs -= 1;\n if (current.refs) return;\n // A same-Runtime reconnect can still reuse this connection in Strict Mode.\n pendingDisposals.set(runtime, current);\n queueMicrotask(() => disposeUnusedConnection(runtime, current));\n };\n}\n\nfunction createConnection(runtime: InternalToolRuntime, modelContext: WebMcpModelContext): () => void {\n\n const registrations = new Map<string, WebMcpRegistration>();\n let disposed = false;\n let operation: ToolOperation | undefined;\n const controls = new AbortController();\n const begin: WebMcpTool = {\n name: \"nxf_beginOperation\",\n description: \"Begin a continuous page operation before using page tools. Call nxf_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.\",\n inputSchema: { type: \"object\", properties: {}, additionalProperties: false },\n execute: async (input, options = {}) => {\n options.signal?.throwIfAborted();\n controls.signal.throwIfAborted();\n if (!input || typeof input !== \"object\" || Array.isArray(input) || Object.keys(input).length) throw new TypeError(\"nxf_beginOperation requires {}.\");\n const current = runtime.getActivitySnapshot().operation;\n if (operation && current?.id === operation.id) {\n return { status: current.status === \"ending\" ? \"ending\" : \"active\", operationId: operation.id };\n }\n operation = undefined;\n try { operation = runtime.beginInternalOperation({ source: \"webmcp\" }); }\n catch (error) {\n if ((error as { code?: string }).code === \"OPERATION_BUSY\") return { status: \"busy\" };\n throw error;\n }\n return { status: \"active\", operationId: operation.id };\n },\n };\n const end: WebMcpTool = {\n name: \"nxf_endOperation\",\n 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.\",\n inputSchema: { type: \"object\", properties: { operationId: { type: \"string\" } }, required: [\"operationId\"], additionalProperties: false },\n execute: async (input, options = {}) => {\n options.signal?.throwIfAborted();\n controls.signal.throwIfAborted();\n const args = input as { operationId?: unknown };\n if (!args || typeof args !== \"object\" || Array.isArray(args) || typeof args.operationId !== \"string\" || Object.keys(args).some((key) => key !== \"operationId\")) throw new TypeError(\"nxf_endOperation requires { operationId: string }.\");\n const operationId = args.operationId;\n const owned = operation;\n if (!owned || owned.id !== operationId || runtime.getActivitySnapshot().operation?.id !== operationId) return { status: \"not_active\", operationId };\n await owned.end();\n if (operation === owned) operation = undefined;\n return { status: \"ended\", operationId };\n },\n };\n const registerControls = async () => {\n try {\n await modelContext.registerTool(end, { signal: controls.signal });\n controls.signal.throwIfAborted();\n await modelContext.registerTool(begin, { signal: controls.signal });\n } catch (error) {\n const aborted = controls.signal.aborted;\n controls.abort();\n if (!disposed && !aborted) warnWebMcpRegistration(\"nxf_beginOperation/nxf_endOperation\", error);\n }\n };\n\n const register = (tool: RuntimeAgentTool) => {\n const { definition } = tool;\n const controller = new AbortController();\n const registration = { controller, tool };\n registrations.set(definition.name, registration);\n let result: Promise<void>;\n try {\n result = modelContext.registerTool({\n name: definition.name,\n description: definition.description,\n inputSchema: {\n type: \"object\",\n properties: {\n input: definition.inputSchema ?? { type: \"object\", properties: {}, additionalProperties: false },\n progressLabel: {\n type: \"string\",\n description: \"Briefly describe this tool action in the user’s language. Do not expose internal identifiers or claim success before completion.\",\n },\n },\n required: [\"input\"],\n additionalProperties: false,\n },\n execute: async (parameters, options = {}) => {\n const args = parameters as { input?: unknown; progressLabel?: unknown };\n if (!args || typeof args !== \"object\" || Array.isArray(args)\n || !args.input || typeof args.input !== \"object\" || Array.isArray(args.input)\n || Object.keys(args).some((key) => key !== \"input\" && key !== \"progressLabel\")\n || (args.progressLabel !== undefined && typeof args.progressLabel !== \"string\")) {\n throw new TypeError(\"WebMCP tools require { input: object, progressLabel?: string }.\");\n }\n return runtime.execute(tool, args.input, {\n ...(options.signal ? { signal: options.signal } : {}),\n ...(typeof args.progressLabel === \"string\" ? { progressLabel: args.progressLabel } : {}),\n });\n },\n }, { signal: controller.signal });\n } catch (error) {\n registrations.delete(definition.name);\n warnWebMcpRegistration(definition.name, error);\n return;\n }\n Promise.resolve(result).catch((error: unknown) => {\n if (controller.signal.aborted || disposed) return;\n if (registrations.get(definition.name) === registration) {\n registrations.delete(definition.name);\n }\n warnWebMcpRegistration(definition.name, error);\n });\n };\n\n const reconcile = () => {\n const tools = new Map(\n runtime.getWebMcpTools().filter((tool) => ![\"nxf_beginOperation\", \"nxf_endOperation\"].includes(tool.definition.name)).map((tool) => [tool.definition.name, tool]),\n );\n for (const [name, registration] of registrations) {\n if (tools.get(name) === registration.tool) continue;\n registration.controller.abort();\n registrations.delete(name);\n }\n for (const tool of tools.values()) {\n if (!registrations.has(tool.definition.name)) register(tool);\n }\n };\n\n const unsubscribeRuntime = runtime.on(\"toolchange\", reconcile);\n modelContext.addEventListener?.(\"toolchange\", reconcile);\n reconcile();\n void registerControls();\n\n return () => {\n if (disposed) return;\n disposed = true;\n controls.abort();\n if (operation) void runtime.endBridgeOperation(operation);\n operation = undefined;\n unsubscribeRuntime();\n modelContext.removeEventListener?.(\"toolchange\", reconcile);\n for (const registration of registrations.values()) {\n registration.controller.abort();\n }\n registrations.clear();\n };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nexface/tools",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.15-alpha.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -27,9 +27,5 @@
|
|
|
27
27
|
},
|
|
28
28
|
"files": [
|
|
29
29
|
"dist"
|
|
30
|
-
]
|
|
31
|
-
"repository": {
|
|
32
|
-
"type": "git",
|
|
33
|
-
"url": "git+https://github.com/fishear/nexface.git"
|
|
34
|
-
}
|
|
30
|
+
]
|
|
35
31
|
}
|
package/dist/tool-search.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { RuntimeAgentTool } from "./runtime.js";
|
|
2
|
-
export declare const searchToolDefinition: import("./types.js").AgentToolDefinition<{
|
|
3
|
-
query?: string;
|
|
4
|
-
queries?: string[];
|
|
5
|
-
}, {
|
|
6
|
-
tools: Array<{
|
|
7
|
-
name: string;
|
|
8
|
-
description: string;
|
|
9
|
-
}>;
|
|
10
|
-
}>;
|
|
11
|
-
export declare function searchNavigationTools(tools: readonly RuntimeAgentTool[], query: string | readonly string[]): RuntimeAgentTool[];
|
package/dist/tool-search.js
DELETED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import { createAgentToolDefinition } from "./shared/definition.js";
|
|
2
|
-
export const searchToolDefinition = createAgentToolDefinition({
|
|
3
|
-
name: "nxf_searchTool",
|
|
4
|
-
description: "Search registered navigation tools when opening a page with no suitable callable navigation tool. Use query for one phrase or queries for alternative phrasings of the same task. Results replace visible candidates (max 5). Call a match from the refreshed catalog, then use the page's tools. If none fits, call {} for the directory, then query an exact name.",
|
|
5
|
-
effect: "read",
|
|
6
|
-
inputSchema: {
|
|
7
|
-
type: "object",
|
|
8
|
-
properties: {
|
|
9
|
-
query: { type: "string", description: "Page name, purpose, or exact navigation tool name." },
|
|
10
|
-
queries: {
|
|
11
|
-
type: "array",
|
|
12
|
-
description: "Alternative search phrases for the same navigation task. Use instead of query.",
|
|
13
|
-
minItems: 1,
|
|
14
|
-
maxItems: 3,
|
|
15
|
-
items: { type: "string", minLength: 1 },
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
additionalProperties: false,
|
|
19
|
-
},
|
|
20
|
-
});
|
|
21
|
-
function tokenize(text, segmenter) {
|
|
22
|
-
const normalized = text
|
|
23
|
-
.normalize("NFKC")
|
|
24
|
-
.replace(/([a-z0-9])([A-Z])/g, "$1 $2")
|
|
25
|
-
.replace(/[_-]+/g, " ")
|
|
26
|
-
.toLowerCase();
|
|
27
|
-
if (segmenter) {
|
|
28
|
-
return [...segmenter.segment(normalized)]
|
|
29
|
-
.filter((part) => part.isWordLike)
|
|
30
|
-
.map((part) => part.segment);
|
|
31
|
-
}
|
|
32
|
-
return (normalized.match(/\p{Script=Han}+|[\p{L}\p{N}]+/gu) ?? []).flatMap((word) => {
|
|
33
|
-
if (!/^\p{Script=Han}+$/u.test(word))
|
|
34
|
-
return [word];
|
|
35
|
-
const characters = [...word];
|
|
36
|
-
return characters.length < 2
|
|
37
|
-
? characters
|
|
38
|
-
: characters.slice(1).map((character, index) => characters[index] + character);
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
function schemaText(value) {
|
|
42
|
-
if (!value || typeof value !== "object")
|
|
43
|
-
return [];
|
|
44
|
-
if (Array.isArray(value))
|
|
45
|
-
return value.flatMap(schemaText);
|
|
46
|
-
const schema = value;
|
|
47
|
-
return Object.entries(schema).flatMap(([key, child]) => {
|
|
48
|
-
if (key === "description" && typeof child === "string")
|
|
49
|
-
return [child];
|
|
50
|
-
if (key === "properties" && child && typeof child === "object") {
|
|
51
|
-
return Object.entries(child).flatMap(([name, property]) => [name, ...schemaText(property)]);
|
|
52
|
-
}
|
|
53
|
-
return child && typeof child === "object" ? schemaText(child) : [];
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
export function searchNavigationTools(tools, query) {
|
|
57
|
-
if (typeof query !== "string") {
|
|
58
|
-
const queries = [...new Set(query)];
|
|
59
|
-
if (queries.length === 1)
|
|
60
|
-
return searchNavigationTools(tools, queries[0]);
|
|
61
|
-
// Fuse ranks rather than comparing BM25 scores across different queries.
|
|
62
|
-
const scores = new Map();
|
|
63
|
-
for (const phrase of queries) {
|
|
64
|
-
searchNavigationTools(tools, phrase).forEach((tool, index) => {
|
|
65
|
-
scores.set(tool, (scores.get(tool) ?? 0) + 1 / (60 + index + 1));
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
return [...scores]
|
|
69
|
-
.sort(([left, a], [right, b]) => {
|
|
70
|
-
const x = left.definition.name;
|
|
71
|
-
const y = right.definition.name;
|
|
72
|
-
return b - a || (x < y ? -1 : x > y ? 1 : 0);
|
|
73
|
-
})
|
|
74
|
-
.slice(0, 5)
|
|
75
|
-
.map(([tool]) => tool);
|
|
76
|
-
}
|
|
77
|
-
const exact = tools.find((tool) => tool.definition.name === query);
|
|
78
|
-
if (exact)
|
|
79
|
-
return [exact];
|
|
80
|
-
const segmenter = typeof Intl.Segmenter === "function"
|
|
81
|
-
? new Intl.Segmenter("zh", { granularity: "word" })
|
|
82
|
-
: undefined;
|
|
83
|
-
const terms = [...new Set(tokenize(query, segmenter))];
|
|
84
|
-
if (!terms.length || !tools.length)
|
|
85
|
-
return [];
|
|
86
|
-
const documents = tools.map((tool) => {
|
|
87
|
-
const { name, description, inputSchema } = tool.definition;
|
|
88
|
-
const tokens = tokenize([name, description, ...schemaText(inputSchema)].join(" "), segmenter);
|
|
89
|
-
const frequencies = new Map();
|
|
90
|
-
for (const token of tokens)
|
|
91
|
-
frequencies.set(token, (frequencies.get(token) ?? 0) + 1);
|
|
92
|
-
return { tool, length: tokens.length, frequencies };
|
|
93
|
-
});
|
|
94
|
-
const averageLength = documents.reduce((sum, document) => sum + document.length, 0) / documents.length || 1;
|
|
95
|
-
const idf = new Map(terms.map((term) => {
|
|
96
|
-
const count = documents.filter((document) => document.frequencies.has(term)).length;
|
|
97
|
-
return [term, Math.log(1 + (documents.length - count + 0.5) / (count + 0.5))];
|
|
98
|
-
}));
|
|
99
|
-
return documents
|
|
100
|
-
.map((document) => {
|
|
101
|
-
const score = terms.reduce((sum, term) => {
|
|
102
|
-
const frequency = document.frequencies.get(term) ?? 0;
|
|
103
|
-
return (sum +
|
|
104
|
-
(idf.get(term) * frequency * 2.2) /
|
|
105
|
-
(frequency + 1.2 * (0.25 + (0.75 * document.length) / averageLength)));
|
|
106
|
-
}, 0);
|
|
107
|
-
return { tool: document.tool, score };
|
|
108
|
-
})
|
|
109
|
-
.filter(({ score }) => score > 0)
|
|
110
|
-
.sort((left, right) => {
|
|
111
|
-
const a = left.tool.definition.name;
|
|
112
|
-
const b = right.tool.definition.name;
|
|
113
|
-
return right.score - left.score || (a < b ? -1 : a > b ? 1 : 0);
|
|
114
|
-
})
|
|
115
|
-
.slice(0, 5)
|
|
116
|
-
.map(({ tool }) => tool);
|
|
117
|
-
}
|