@nexface/tools 0.1.13-alpha.1 → 0.1.13-alpha.3

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 (77) hide show
  1. package/dist/browser/actions.js +0 -1
  2. package/dist/browser/controller.js +0 -1
  3. package/dist/browser/diagnostics.js +0 -1
  4. package/dist/browser/dom.js +0 -1
  5. package/dist/browser/feedback.js +0 -1
  6. package/dist/browser/focus.js +0 -1
  7. package/dist/browser/locator.js +0 -1
  8. package/dist/browser/prompt.generated.js +0 -1
  9. package/dist/browser/prompt.js +0 -1
  10. package/dist/browser/snapshot.js +0 -1
  11. package/dist/browser/toolset.js +0 -1
  12. package/dist/browser/types.js +0 -1
  13. package/dist/browser/worker-runner.js +0 -1
  14. package/dist/definition.js +0 -1
  15. package/dist/index.browser.js +0 -1
  16. package/dist/index.js +0 -1
  17. package/dist/internal-react.js +0 -1
  18. package/dist/internal-types.js +0 -1
  19. package/dist/navigation.js +0 -1
  20. package/dist/operation-lock.js +0 -1
  21. package/dist/operation-runtime.js +0 -1
  22. package/dist/operation-surface.js +0 -1
  23. package/dist/operation-types.js +0 -1
  24. package/dist/operation-view.js +0 -1
  25. package/dist/react.js +0 -1
  26. package/dist/registration.js +0 -1
  27. package/dist/runtime.d.ts +3 -1
  28. package/dist/runtime.js +40 -3
  29. package/dist/shared/definition.js +0 -1
  30. package/dist/shared/errors.js +0 -1
  31. package/dist/shared/page-protocol.js +0 -1
  32. package/dist/shared/page-tools.js +0 -1
  33. package/dist/shared/runtime-controller.d.ts +1 -0
  34. package/dist/shared/runtime-controller.js +0 -1
  35. package/dist/shared/runtime-execution.js +0 -1
  36. package/dist/shared/schema.js +0 -1
  37. package/dist/tool-search.d.ts +11 -0
  38. package/dist/tool-search.js +91 -0
  39. package/dist/types.js +0 -1
  40. package/dist/webmcp.js +0 -1
  41. package/package.json +6 -2
  42. package/dist/browser/actions.js.map +0 -1
  43. package/dist/browser/controller.js.map +0 -1
  44. package/dist/browser/diagnostics.js.map +0 -1
  45. package/dist/browser/dom.js.map +0 -1
  46. package/dist/browser/feedback.js.map +0 -1
  47. package/dist/browser/focus.js.map +0 -1
  48. package/dist/browser/locator.js.map +0 -1
  49. package/dist/browser/prompt.generated.js.map +0 -1
  50. package/dist/browser/prompt.js.map +0 -1
  51. package/dist/browser/snapshot.js.map +0 -1
  52. package/dist/browser/toolset.js.map +0 -1
  53. package/dist/browser/types.js.map +0 -1
  54. package/dist/browser/worker-runner.js.map +0 -1
  55. package/dist/definition.js.map +0 -1
  56. package/dist/index.browser.js.map +0 -1
  57. package/dist/index.js.map +0 -1
  58. package/dist/internal-react.js.map +0 -1
  59. package/dist/internal-types.js.map +0 -1
  60. package/dist/navigation.js.map +0 -1
  61. package/dist/operation-lock.js.map +0 -1
  62. package/dist/operation-runtime.js.map +0 -1
  63. package/dist/operation-surface.js.map +0 -1
  64. package/dist/operation-types.js.map +0 -1
  65. package/dist/operation-view.js.map +0 -1
  66. package/dist/react.js.map +0 -1
  67. package/dist/registration.js.map +0 -1
  68. package/dist/runtime.js.map +0 -1
  69. package/dist/shared/definition.js.map +0 -1
  70. package/dist/shared/errors.js.map +0 -1
  71. package/dist/shared/page-protocol.js.map +0 -1
  72. package/dist/shared/page-tools.js.map +0 -1
  73. package/dist/shared/runtime-controller.js.map +0 -1
  74. package/dist/shared/runtime-execution.js.map +0 -1
  75. package/dist/shared/schema.js.map +0 -1
  76. package/dist/types.js.map +0 -1
  77. package/dist/webmcp.js.map +0 -1
@@ -70,4 +70,3 @@ export function collectPageActions(actions) {
70
70
  add("pageDown", "scrollDown", "scrollBy", [{ y: 560 }]);
71
71
  add("wait", "wait", "waitForTimeout", [100]);
72
72
  }
73
- //# sourceMappingURL=actions.js.map
@@ -841,4 +841,3 @@ export class PageController {
841
841
  throw invalidCommand(`Unsupported locator method: ${command.method}`);
842
842
  }
843
843
  }
844
- //# sourceMappingURL=controller.js.map
@@ -17,4 +17,3 @@ export async function measurePagePhase(phase, execute) {
17
17
  catch { /* Diagnostics must never interrupt execution. */ }
18
18
  }
19
19
  }
20
- //# sourceMappingURL=diagnostics.js.map
@@ -442,4 +442,3 @@ export function matchesText(value, matcher, exact = false) {
442
442
  const expected = normalizeText(matcher);
443
443
  return exact ? normalized === expected : normalized.includes(expected);
444
444
  }
445
- //# sourceMappingURL=dom.js.map
@@ -11,4 +11,3 @@ export class ActionFeedback {
11
11
  });
12
12
  }
13
13
  }
14
- //# sourceMappingURL=feedback.js.map
@@ -26,4 +26,3 @@ export function focusForAgent(element) {
26
26
  focusingForAgent = previous;
27
27
  }
28
28
  }
29
- //# sourceMappingURL=focus.js.map
@@ -274,4 +274,3 @@ export function requireValidRef(target) {
274
274
  validateIdentity(target);
275
275
  return target.element;
276
276
  }
277
- //# sourceMappingURL=locator.js.map
@@ -54,4 +54,3 @@ Execution policy:
54
54
  - Return JSON-serializable data when reading information from the page.
55
55
  - A successful Page action receipt proves only that the action ran. Confirm business success through visible feedback, field readback, or an application tool result.
56
56
  - nxf_executeAction automatically returns a best-effort viewport snapshot. If refsExpired, postSnapshotTimedOut, or snapshotUnavailable is true, or the expected page state is absent, call nxf_getSnapshot before another write or nxf_finish.`;
57
- //# sourceMappingURL=prompt.generated.js.map
@@ -6,4 +6,3 @@ export const BROWSER_TOOLS_SKILL = {
6
6
  export function serializeBrowserToolsSkill() {
7
7
  return `[NEXFACE_SKILL_V1 name="${BROWSER_TOOLS_SKILL.name}"]\n${BROWSER_TOOLS_SKILL.content}\n[/NEXFACE_SKILL_V1]`;
8
8
  }
9
- //# sourceMappingURL=prompt.js.map
@@ -429,4 +429,3 @@ export async function createSnapshot(scope = "viewport", limits = {}, execution,
429
429
  export async function getSnapshot(scope = "viewport", limits = {}) {
430
430
  return (await createSnapshot(scope, limits)).snapshot;
431
431
  }
432
- //# sourceMappingURL=snapshot.js.map
@@ -449,4 +449,3 @@ export function createBrowserToolset(options = {}) {
449
449
  handlers: new Map(toolHandlers.map((tool) => [tool.definition.name, tool])),
450
450
  };
451
451
  }
452
- //# sourceMappingURL=toolset.js.map
@@ -1,2 +1 @@
1
1
  export {};
2
- //# sourceMappingURL=types.js.map
@@ -397,4 +397,3 @@ export class WorkerRunner {
397
397
  active.cancel();
398
398
  }
399
399
  }
400
- //# sourceMappingURL=worker-runner.js.map
@@ -33,4 +33,3 @@ export function defineAgentTool(metadata) {
33
33
  inputSchema: metadata.inputSchema === undefined ? emptyInputSchema : metadata.inputSchema,
34
34
  });
35
35
  }
36
- //# sourceMappingURL=definition.js.map
@@ -1,4 +1,3 @@
1
1
  import "./styles.css";
2
2
  export * from "./index.js";
3
3
  export { registerAgentTool } from "./registration.js";
4
- //# sourceMappingURL=index.browser.js.map
package/dist/index.js CHANGED
@@ -4,4 +4,3 @@ export { AgentOperationSurface } from "./operation-surface.js";
4
4
  export { createToolRuntime, isToolRuntimeError, } from "./runtime.js";
5
5
  export { AgentContext, ToolsProvider, AgentUIAction, useAgentContext, useAgentNavigation, useAgentTool, } from "./react.js";
6
6
  export { registerAgentTool } from "./registration.js";
7
- //# sourceMappingURL=index.js.map
@@ -20,4 +20,3 @@ export function useInternalToolRuntime() {
20
20
  export function useOptionalInternalToolRuntime() {
21
21
  return useContext(InternalToolRuntimeContext);
22
22
  }
23
- //# sourceMappingURL=internal-react.js.map
@@ -1,2 +1 @@
1
1
  export {};
2
- //# sourceMappingURL=internal-types.js.map
@@ -37,4 +37,3 @@ export function getAgentNavigationEntries(navigation) {
37
37
  }
38
38
  return entries;
39
39
  }
40
- //# sourceMappingURL=navigation.js.map
@@ -45,4 +45,3 @@ export function lockOperationSurface(surface, redirectFocus) {
45
45
  surface.setAttribute("aria-busy", previousBusy);
46
46
  };
47
47
  }
48
- //# sourceMappingURL=operation-lock.js.map
@@ -151,4 +151,3 @@ export class OperationTracker {
151
151
  listener();
152
152
  }
153
153
  }
154
- //# sourceMappingURL=operation-runtime.js.map
@@ -157,4 +157,3 @@ function OperationSurfaceContent({ toolRuntime, element }) {
157
157
  const entries = !cycle || history.scope === cycle.id ? history.entries : [];
158
158
  return activated || executing || entries.length ? React.createElement(OperationOverlayView, { key: cycle?.id ?? history.scope, operation: operation, progressHistory: entries, running: running, humanHasControl: waiting, cancelling: stopping, ...(feedback ? { feedback } : {}), ...(cycle?.canCancel ? { onCancel: () => runtime.requestOperationCancel(cycle.id) } : {}), resolveSurface: resolveSurface }) : null;
159
159
  }
160
- //# sourceMappingURL=operation-surface.js.map
@@ -1,2 +1 @@
1
1
  export {};
2
- //# sourceMappingURL=operation-types.js.map
@@ -209,4 +209,3 @@ export function OperationOverlayView({ operation, feedback, progressHistory = []
209
209
  (running || humanHasControl) && operation.status !== "cancelled" ? React.createElement("span", { className: "agent-operation__compact-status", title: compactStatusLabel }, compactStatusLabel) : null,
210
210
  cancel && (running || humanHasControl) && operation.status !== "cancelled" ? React.createElement("button", { ref: cancelButtonRef, className: "agent-operation__stop", type: "button", disabled: cancelling, onClick: cancel }, cancelling ? "正在终止" : "终止任务") : null) : null), document.body);
211
211
  }
212
- //# sourceMappingURL=operation-view.js.map
package/dist/react.js CHANGED
@@ -365,4 +365,3 @@ export function AgentUIAction({ name, description, event = "click", children, })
365
365
  ref: mergedRef,
366
366
  });
367
367
  }
368
- //# sourceMappingURL=react.js.map
@@ -9,4 +9,3 @@ export function registerAgentTool(definition, options) {
9
9
  assertAgentToolInputSchema(definition.inputSchema, `Tool "${definition.name}".inputSchema`);
10
10
  return Object.freeze({ definition, execute: options.execute });
11
11
  }
12
- //# sourceMappingURL=registration.js.map
package/dist/runtime.d.ts CHANGED
@@ -7,10 +7,11 @@ import type { AgentContextEntry, AgentContextInput, AgentContextRegistration, Ag
7
7
  import type { AgentToolExecutionEvent } from "./internal-types.js";
8
8
  export interface ToolRuntimeOptions {
9
9
  readonly pageAutomation?: boolean;
10
+ readonly routeSearch?: boolean;
10
11
  }
11
12
  export interface ToolRuntimeToolChangeEvent {
12
13
  readonly toolName: string;
13
- readonly change: "registered" | "unregistered";
14
+ readonly change: "registered" | "unregistered" | "visibility";
14
15
  }
15
16
  declare const CONTEXT_ERROR_CODES: readonly ["CONTEXT_DISPOSED", "CONTEXT_NAME_MISMATCH", "DUPLICATE_CONTEXT", "INVALID_CONTEXT"];
16
17
  type AgentContextErrorCode = typeof CONTEXT_ERROR_CODES[number];
@@ -170,6 +171,7 @@ export declare class ToolRuntimeImplementation extends EventTarget implements To
170
171
  getContexts(options?: {
171
172
  signal?: AbortSignal;
172
173
  }): Promise<readonly AgentContextEntry[]>;
174
+ getRegisteredTools(): readonly RuntimeAgentTool[];
173
175
  getWebMcpTools(): readonly RuntimeAgentTool[];
174
176
  isRegistered(name: string): boolean;
175
177
  getTools(): readonly RuntimeAgentTool[];
package/dist/runtime.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { searchNavigationTools, searchToolDefinition } from "./tool-search.js";
1
2
  import { pageDecisionSymbol } from "./shared/runtime-execution.js";
2
3
  import { PageCommandError } from "./browser/locator.js";
3
4
  import { measurePagePhase } from "./browser/diagnostics.js";
@@ -123,6 +124,8 @@ export function getInternalToolRuntime(runtime) {
123
124
  export class ToolRuntimeImplementation extends EventTarget {
124
125
  [toolRuntimeBrand] = true;
125
126
  #bindings = new Map();
127
+ #routeSearch;
128
+ #visibleNavigation = new Set();
126
129
  #contexts = new Map();
127
130
  #contextRevision = 0;
128
131
  #browserToolset;
@@ -157,6 +160,33 @@ export class ToolRuntimeImplementation extends EventTarget {
157
160
  typeof options.pageAutomation !== "boolean") {
158
161
  throw new AgentToolError("INVALID_INPUT", "pageAutomation must be a boolean.");
159
162
  }
163
+ if (options.routeSearch !== undefined && typeof options.routeSearch !== "boolean") {
164
+ throw new AgentToolError("INVALID_INPUT", "routeSearch must be a boolean.");
165
+ }
166
+ this.#routeSearch = options.routeSearch ?? false;
167
+ if (this.#routeSearch)
168
+ this.register(searchToolDefinition, ({ query, queries }) => {
169
+ if (query !== undefined && queries !== undefined)
170
+ throw new AgentToolError("INVALID_INPUT", "Use either query or queries, not both.");
171
+ const searchQueries = queries === undefined ? (query === undefined ? undefined : [query]) : [...queries];
172
+ if (searchQueries?.some((phrase) => typeof phrase !== "string" || !phrase.trim()))
173
+ throw new AgentToolError("INVALID_INPUT", "Search queries must contain nonblank strings.");
174
+ const navigation = this.getRegisteredTools().filter(({ definition }) => definition.effect === "navigate");
175
+ const candidates = searchQueries === undefined ? navigation : searchNavigationTools(navigation, searchQueries.map((phrase) => phrase.trim()));
176
+ if (searchQueries !== undefined) {
177
+ const previous = this.#visibleNavigation;
178
+ this.#visibleNavigation = new Set(candidates);
179
+ for (const tool of new Set([...previous, ...candidates])) {
180
+ if (previous.has(tool) === this.#visibleNavigation.has(tool))
181
+ continue;
182
+ this.dispatchEvent(new DetailEvent("toolchange", Object.freeze({
183
+ toolName: tool.definition.name,
184
+ change: "visibility",
185
+ })));
186
+ }
187
+ }
188
+ return { tools: candidates.map(({ definition: { name, description } }) => ({ name, description })) };
189
+ });
160
190
  this.#browserToolset = options.pageAutomation ? createBrowserToolset() : undefined;
161
191
  runtimeInternals.set(this, this);
162
192
  const controller = Object.freeze({
@@ -165,6 +195,7 @@ export class ToolRuntimeImplementation extends EventTarget {
165
195
  setTaskProgress: this.setTaskProgress,
166
196
  getOperationSnapshot: () => this.getActivitySnapshot().operation,
167
197
  subscribeOperation: this.subscribeActivity,
198
+ getRegisteredTools: () => this.getRegisteredTools(),
168
199
  });
169
200
  Object.defineProperty(this, runtimeControllerSymbol, { value: controller });
170
201
  }
@@ -224,6 +255,7 @@ export class ToolRuntimeImplementation extends EventTarget {
224
255
  disposed = true;
225
256
  options.signal?.removeEventListener("abort", dispose);
226
257
  this.#bindings.delete(definition.name);
258
+ this.#visibleNavigation.delete(runtimeTool);
227
259
  lifecycleController.abort();
228
260
  this.dispatchEvent(new DetailEvent("toolchange", Object.freeze({
229
261
  toolName: definition.name,
@@ -337,17 +369,23 @@ export class ToolRuntimeImplementation extends EventTarget {
337
369
  revision: this.#contextRevision,
338
370
  }));
339
371
  }
372
+ getRegisteredTools() {
373
+ return [...this.#bindings.values()]
374
+ .map(({ runtimeTool }) => runtimeTool)
375
+ .filter(({ definition }) => !this.#routeSearch || definition !== searchToolDefinition)
376
+ .sort((left, right) => compareStrings(left.definition.name, right.definition.name));
377
+ }
340
378
  getWebMcpTools() {
341
379
  return [...this.#bindings.values()]
342
380
  .map(({ runtimeTool }) => runtimeTool)
381
+ .filter((tool) => !this.#routeSearch || tool.definition.effect !== "navigate" || this.#visibleNavigation.has(tool))
343
382
  .sort((left, right) => compareStrings(left.definition.name, right.definition.name));
344
383
  }
345
384
  isRegistered(name) {
346
385
  return this.#bindings.has(name);
347
386
  }
348
387
  getTools() {
349
- const applicationTools = [...this.#bindings.values()]
350
- .map(({ runtimeTool }) => runtimeTool);
388
+ const applicationTools = this.getWebMcpTools();
351
389
  const browserTools = (this.#browserToolset?.definitions ?? [])
352
390
  .map((definition) => this.#getBrowserRuntimeTool(definition));
353
391
  return [...applicationTools, ...browserTools]
@@ -599,4 +637,3 @@ export class ToolRuntimeImplementation extends EventTarget {
599
637
  return runtimeTool;
600
638
  }
601
639
  }
602
- //# sourceMappingURL=runtime.js.map
@@ -30,4 +30,3 @@ function cloneAndFreeze(value) {
30
30
  }
31
31
  return value;
32
32
  }
33
- //# sourceMappingURL=definition.js.map
@@ -33,4 +33,3 @@ export class AgentToolError extends Error {
33
33
  this.name = "ToolRuntimeError";
34
34
  }
35
35
  }
36
- //# sourceMappingURL=errors.js.map
@@ -1,3 +1,2 @@
1
1
  // Generated from shared/page-protocol.ts. Do not edit manually.
2
2
  export {};
3
- //# sourceMappingURL=page-protocol.js.map
@@ -40,4 +40,3 @@ export const applyActionTool = createAgentToolDefinition({
40
40
  additionalProperties: false,
41
41
  },
42
42
  });
43
- //# sourceMappingURL=page-tools.js.map
@@ -12,6 +12,7 @@ interface OperationSnapshot {
12
12
  readonly taskProgress?: TaskProgress;
13
13
  }
14
14
  export interface RuntimeController {
15
+ getRegisteredTools(): ReturnType<ToolRuntime["getTools"]>;
15
16
  beginInternalOperation(options?: {
16
17
  signal?: AbortSignal;
17
18
  onCancel?: () => void;
@@ -8,4 +8,3 @@ export function getRuntimeController(runtime) {
8
8
  }
9
9
  return controller;
10
10
  }
11
- //# sourceMappingURL=runtime-controller.js.map
@@ -1,3 +1,2 @@
1
1
  // Generated from shared/runtime-execution.ts. Do not edit manually.
2
2
  export const pageDecisionSymbol = Symbol.for("@nexface/tools/page-decision");
3
- //# sourceMappingURL=runtime-execution.js.map
@@ -197,4 +197,3 @@ export function validateAgentToolInput(schema, value, path = "input") {
197
197
  }
198
198
  return errors;
199
199
  }
200
- //# sourceMappingURL=schema.js.map
@@ -0,0 +1,11 @@
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[];
@@ -0,0 +1,91 @@
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: { type: "array", description: "Alternative search phrases for the same navigation task. Use instead of query.", minItems: 1, maxItems: 3, items: { type: "string", minLength: 1 } },
11
+ },
12
+ additionalProperties: false,
13
+ },
14
+ });
15
+ function tokenize(text, segmenter) {
16
+ const normalized = text.normalize("NFKC").replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").toLowerCase();
17
+ if (segmenter) {
18
+ return [...segmenter.segment(normalized)].filter((part) => part.isWordLike).map((part) => part.segment);
19
+ }
20
+ return (normalized.match(/\p{Script=Han}+|[\p{L}\p{N}]+/gu) ?? []).flatMap((word) => {
21
+ if (!/^\p{Script=Han}+$/u.test(word))
22
+ return [word];
23
+ const characters = [...word];
24
+ return characters.length < 2 ? characters : characters.slice(1).map((character, index) => characters[index] + character);
25
+ });
26
+ }
27
+ function schemaText(value) {
28
+ if (!value || typeof value !== "object")
29
+ return [];
30
+ if (Array.isArray(value))
31
+ return value.flatMap(schemaText);
32
+ const schema = value;
33
+ return Object.entries(schema).flatMap(([key, child]) => {
34
+ if (key === "description" && typeof child === "string")
35
+ return [child];
36
+ if (key === "properties" && child && typeof child === "object") {
37
+ return Object.entries(child).flatMap(([name, property]) => [name, ...schemaText(property)]);
38
+ }
39
+ return child && typeof child === "object" ? schemaText(child) : [];
40
+ });
41
+ }
42
+ export function searchNavigationTools(tools, query) {
43
+ if (typeof query !== "string") {
44
+ const queries = [...new Set(query)];
45
+ if (queries.length === 1)
46
+ return searchNavigationTools(tools, queries[0]);
47
+ // Fuse ranks rather than comparing BM25 scores across different queries.
48
+ const scores = new Map();
49
+ for (const phrase of queries) {
50
+ searchNavigationTools(tools, phrase).forEach((tool, index) => {
51
+ scores.set(tool, (scores.get(tool) ?? 0) + 1 / (60 + index + 1));
52
+ });
53
+ }
54
+ return [...scores].sort(([left, a], [right, b]) => {
55
+ const x = left.definition.name;
56
+ const y = right.definition.name;
57
+ return b - a || (x < y ? -1 : x > y ? 1 : 0);
58
+ }).slice(0, 5).map(([tool]) => tool);
59
+ }
60
+ const exact = tools.find((tool) => tool.definition.name === query);
61
+ if (exact)
62
+ return [exact];
63
+ const segmenter = typeof Intl.Segmenter === "function" ? new Intl.Segmenter("zh", { granularity: "word" }) : undefined;
64
+ const terms = [...new Set(tokenize(query, segmenter))];
65
+ if (!terms.length || !tools.length)
66
+ return [];
67
+ const documents = tools.map((tool) => {
68
+ const { name, description, inputSchema } = tool.definition;
69
+ const tokens = tokenize([name, description, ...schemaText(inputSchema)].join(" "), segmenter);
70
+ const frequencies = new Map();
71
+ for (const token of tokens)
72
+ frequencies.set(token, (frequencies.get(token) ?? 0) + 1);
73
+ return { tool, length: tokens.length, frequencies };
74
+ });
75
+ const averageLength = documents.reduce((sum, document) => sum + document.length, 0) / documents.length || 1;
76
+ const idf = new Map(terms.map((term) => {
77
+ const count = documents.filter((document) => document.frequencies.has(term)).length;
78
+ return [term, Math.log(1 + (documents.length - count + 0.5) / (count + 0.5))];
79
+ }));
80
+ return documents.map((document) => {
81
+ const score = terms.reduce((sum, term) => {
82
+ const frequency = document.frequencies.get(term) ?? 0;
83
+ return sum + idf.get(term) * frequency * 2.2 / (frequency + 1.2 * (0.25 + 0.75 * document.length / averageLength));
84
+ }, 0);
85
+ return { tool: document.tool, score };
86
+ }).filter(({ score }) => score > 0).sort((left, right) => {
87
+ const a = left.tool.definition.name;
88
+ const b = right.tool.definition.name;
89
+ return right.score - left.score || (a < b ? -1 : a > b ? 1 : 0);
90
+ }).slice(0, 5).map(({ tool }) => tool);
91
+ }
package/dist/types.js CHANGED
@@ -1,2 +1 @@
1
1
  export {};
2
- //# sourceMappingURL=types.js.map
package/dist/webmcp.js CHANGED
@@ -225,4 +225,3 @@ function createConnection(runtime, modelContext) {
225
225
  registrations.clear();
226
226
  };
227
227
  }
228
- //# sourceMappingURL=webmcp.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nexface/tools",
3
- "version": "0.1.13-alpha.1",
3
+ "version": "0.1.13-alpha.3",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -27,5 +27,9 @@
27
27
  },
28
28
  "files": [
29
29
  "dist"
30
- ]
30
+ ],
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "git+https://github.com/fishear/nexface.git"
34
+ }
31
35
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"actions.js","sourceRoot":"","sources":["../../src/browser/actions.ts"],"names":[],"mappings":"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","sourcesContent":["import type { PageActionCandidate, PageCommand, SemanticState } from \"./types.js\";\nimport { computeName } from \"./dom.js\";\n\nexport interface ObservedAction {\n candidate: PageActionCandidate;\n command: Pick<PageCommand, \"target\" | \"method\" | \"args\">;\n optionElement?: HTMLOptionElement;\n}\n\nexport function collectElementActions(\n actions: Map<string, ObservedAction>,\n ref: string,\n element: Element,\n role: string,\n label: string,\n state: SemanticState,\n scrollable: boolean,\n): void {\n const target = { type: \"ref\", ref } as const;\n const add = (operation: PageActionCandidate[\"operation\"], method: PageCommand[\"method\"], args: unknown[], option?: string, optionElement?: HTMLOptionElement): void => {\n if (actions.size >= 240) return;\n const id = `a${actions.size + 1}`;\n actions.set(id, {\n candidate: { id, operation, ref, role, label: (optionElement ? `${label} / ${option}` : label).slice(0, 500), state, ...(option === undefined ? {} : { option: option.slice(0, 500) }) },\n command: { target, method, args },\n ...(optionElement ? { optionElement } : {}),\n });\n };\n if (state.disabled || element.closest('[inert],[aria-disabled=\"true\"]') || element.matches(\":disabled\")) return;\n if (scrollable) {\n if (element.scrollTop > 0) add(\"scrollUp\", \"scrollBy\", [{ y: -560 }]);\n if (element.scrollTop + element.clientHeight < element.scrollHeight - 1) add(\"scrollDown\", \"scrollBy\", [{ y: 560 }]);\n return;\n }\n if (element instanceof HTMLInputElement && [\"password\", \"file\", \"hidden\"].includes(element.type)) return;\n if (element instanceof HTMLOptionElement) return;\n if (element instanceof HTMLSelectElement) {\n const counts = new Map<string, number>();\n for (const option of element.options) counts.set(option.value, (counts.get(option.value) ?? 0) + 1);\n for (const option of element.options) {\n if (element.multiple) {\n if (counts.get(option.value) === 1 && !option.disabled && !option.closest(\"optgroup[disabled]\")) {\n add(option.selected ? \"uncheck\" : \"check\", \"setOptionSelected\", [option.value, !option.selected, option.label], option.label, option);\n }\n continue;\n }\n if (counts.get(option.value) === 1 && !(element.required && option.value === \"\") && !option.disabled && !option.selected && !option.closest(\"optgroup[disabled]\")) add(\"select\", \"selectOption\", [option.value], option.label);\n }\n return;\n }\n if (role === \"option\" && element.closest('[role=\"listbox\"]')?.getAttribute(\"aria-multiselectable\") === \"true\"\n && [\"true\", \"false\"].includes(element.getAttribute(\"aria-selected\") ?? \"\")) {\n const field = computeName(element.closest('[role=\"listbox\"]')!);\n label = field ? `${field} / ${label}` : label;\n add(state.selected ? \"uncheck\" : \"check\", state.selected ? \"uncheck\" : \"check\", []);\n return;\n }\n if (role === \"checkbox\" || role === \"switch\" || role === \"radio\") {\n if (state.checked !== true) add(\"check\", \"check\", []);\n else if (role !== \"radio\") add(\"uncheck\", \"uncheck\", []);\n return;\n }\n const editable = element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || (element instanceof HTMLElement && element.isContentEditable);\n if (editable && !(\"readOnly\" in element && element.readOnly) && element.getAttribute(\"aria-readonly\") !== \"true\" && [\"textbox\", \"searchbox\", \"combobox\", \"spinbutton\"].includes(role)) {\n add(\"fill\", \"fill\", []);\n }\n add(\"click\", \"click\", []);\n}\n\nexport function collectPageActions(actions: Map<string, ObservedAction>): void {\n const add = (id: string, operation: PageActionCandidate[\"operation\"], method: PageCommand[\"method\"], args: unknown[]): void => {\n actions.set(id, { candidate: { id, operation, label: operation, role: \"page\", state: {} }, command: { target: { type: \"page\" }, method, args } });\n };\n if (window.scrollY > 0) add(\"pageUp\", \"scrollUp\", \"scrollBy\", [{ y: -560 }]);\n if (window.scrollY + window.innerHeight < document.documentElement.scrollHeight - 1) add(\"pageDown\", \"scrollDown\", \"scrollBy\", [{ y: 560 }]);\n add(\"wait\", \"wait\", \"waitForTimeout\", [100]);\n}\n"]}