@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.
Files changed (84) hide show
  1. package/dist/browser/actions.js +10 -34
  2. package/dist/browser/actions.js.map +1 -0
  3. package/dist/browser/controller.js +74 -53
  4. package/dist/browser/controller.js.map +1 -0
  5. package/dist/browser/diagnostics.js +3 -8
  6. package/dist/browser/diagnostics.js.map +1 -0
  7. package/dist/browser/dom.js +28 -12
  8. package/dist/browser/dom.js.map +1 -0
  9. package/dist/browser/feedback.js +5 -6
  10. package/dist/browser/feedback.js.map +1 -0
  11. package/dist/browser/focus.js +1 -0
  12. package/dist/browser/focus.js.map +1 -0
  13. package/dist/browser/locator.js +9 -3
  14. package/dist/browser/locator.js.map +1 -0
  15. package/dist/browser/prompt.generated.js +1 -0
  16. package/dist/browser/prompt.generated.js.map +1 -0
  17. package/dist/browser/prompt.js +1 -0
  18. package/dist/browser/prompt.js.map +1 -0
  19. package/dist/browser/snapshot.js +22 -10
  20. package/dist/browser/snapshot.js.map +1 -0
  21. package/dist/browser/toolset.js +36 -42
  22. package/dist/browser/toolset.js.map +1 -0
  23. package/dist/browser/types.d.ts +1 -1
  24. package/dist/browser/types.js +1 -0
  25. package/dist/browser/types.js.map +1 -0
  26. package/dist/browser/worker-runner.js +1 -0
  27. package/dist/browser/worker-runner.js.map +1 -0
  28. package/dist/definition.d.ts +3 -1
  29. package/dist/definition.js +2 -2
  30. package/dist/definition.js.map +1 -0
  31. package/dist/index.browser.js +1 -0
  32. package/dist/index.browser.js.map +1 -0
  33. package/dist/index.js +1 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/internal-react.d.ts +1 -1
  36. package/dist/internal-react.js +4 -3
  37. package/dist/internal-react.js.map +1 -0
  38. package/dist/internal-types.js +1 -0
  39. package/dist/internal-types.js.map +1 -0
  40. package/dist/navigation.js +1 -0
  41. package/dist/navigation.js.map +1 -0
  42. package/dist/operation-lock.js +2 -36
  43. package/dist/operation-lock.js.map +1 -0
  44. package/dist/operation-runtime.js +13 -41
  45. package/dist/operation-runtime.js.map +1 -0
  46. package/dist/operation-surface.js +41 -118
  47. package/dist/operation-surface.js.map +1 -0
  48. package/dist/operation-types.js +1 -0
  49. package/dist/operation-types.js.map +1 -0
  50. package/dist/operation-view.d.ts +1 -1
  51. package/dist/operation-view.js +60 -120
  52. package/dist/operation-view.js.map +1 -0
  53. package/dist/react.js +12 -9
  54. package/dist/react.js.map +1 -0
  55. package/dist/registration.d.ts +3 -0
  56. package/dist/registration.js +7 -5
  57. package/dist/registration.js.map +1 -0
  58. package/dist/runtime.d.ts +17 -6
  59. package/dist/runtime.js +59 -105
  60. package/dist/runtime.js.map +1 -0
  61. package/dist/shared/definition.js +1 -0
  62. package/dist/shared/definition.js.map +1 -0
  63. package/dist/shared/errors.d.ts +1 -1
  64. package/dist/shared/errors.js +1 -0
  65. package/dist/shared/errors.js.map +1 -0
  66. package/dist/shared/page-protocol.js +1 -0
  67. package/dist/shared/page-protocol.js.map +1 -0
  68. package/dist/shared/page-tools.js +1 -0
  69. package/dist/shared/page-tools.js.map +1 -0
  70. package/dist/shared/runtime-controller.d.ts +0 -1
  71. package/dist/shared/runtime-controller.js +1 -0
  72. package/dist/shared/runtime-controller.js.map +1 -0
  73. package/dist/shared/runtime-execution.js +1 -0
  74. package/dist/shared/runtime-execution.js.map +1 -0
  75. package/dist/shared/schema.js +19 -45
  76. package/dist/shared/schema.js.map +1 -0
  77. package/dist/styles.css +109 -879
  78. package/dist/types.js +1 -0
  79. package/dist/types.js.map +1 -0
  80. package/dist/webmcp.js +12 -38
  81. package/dist/webmcp.js.map +1 -0
  82. package/package.json +2 -6
  83. package/dist/tool-search.d.ts +0 -11
  84. package/dist/tool-search.js +0 -117
package/dist/types.js CHANGED
@@ -1 +1,2 @@
1
1
  export {};
2
+ //# sourceMappingURL=types.js.map
@@ -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
- Array.isArray(args) ||
189
- !args.input ||
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.14",
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
  }
@@ -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[];
@@ -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
- }