@nexface/tools 0.1.15-alpha.1 → 0.1.15-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 (83) hide show
  1. package/dist/browser/actions.js +34 -10
  2. package/dist/browser/controller.js +53 -74
  3. package/dist/browser/diagnostics.js +8 -3
  4. package/dist/browser/dom.js +12 -28
  5. package/dist/browser/feedback.js +6 -5
  6. package/dist/browser/focus.js +0 -1
  7. package/dist/browser/locator.js +3 -9
  8. package/dist/browser/prompt.generated.js +0 -1
  9. package/dist/browser/prompt.js +0 -1
  10. package/dist/browser/snapshot.js +10 -22
  11. package/dist/browser/toolset.js +42 -36
  12. package/dist/browser/types.d.ts +1 -1
  13. package/dist/browser/types.js +0 -1
  14. package/dist/browser/worker-runner.js +0 -1
  15. package/dist/definition.d.ts +1 -3
  16. package/dist/definition.js +2 -2
  17. package/dist/index.browser.js +0 -1
  18. package/dist/index.js +0 -1
  19. package/dist/internal-react.d.ts +1 -1
  20. package/dist/internal-react.js +3 -4
  21. package/dist/internal-types.js +0 -1
  22. package/dist/navigation.js +0 -1
  23. package/dist/operation-lock.js +36 -2
  24. package/dist/operation-runtime.js +41 -13
  25. package/dist/operation-surface.js +118 -41
  26. package/dist/operation-types.js +0 -1
  27. package/dist/operation-view.d.ts +1 -1
  28. package/dist/operation-view.js +120 -60
  29. package/dist/react.js +9 -14
  30. package/dist/registration.js +4 -3
  31. package/dist/runtime.d.ts +4 -2
  32. package/dist/runtime.js +112 -47
  33. package/dist/shared/definition.js +2 -3
  34. package/dist/shared/errors.d.ts +1 -1
  35. package/dist/shared/errors.js +0 -1
  36. package/dist/shared/page-protocol.js +0 -1
  37. package/dist/shared/page-tools.js +0 -1
  38. package/dist/shared/runtime-controller.d.ts +1 -0
  39. package/dist/shared/runtime-controller.js +0 -1
  40. package/dist/shared/runtime-execution.js +0 -1
  41. package/dist/shared/schema.js +45 -19
  42. package/dist/styles.css +879 -109
  43. package/dist/tool-search.d.ts +11 -0
  44. package/dist/tool-search.js +117 -0
  45. package/dist/types.js +0 -1
  46. package/dist/webmcp.js +39 -13
  47. package/package.json +6 -2
  48. package/dist/browser/actions.js.map +0 -1
  49. package/dist/browser/controller.js.map +0 -1
  50. package/dist/browser/diagnostics.js.map +0 -1
  51. package/dist/browser/dom.js.map +0 -1
  52. package/dist/browser/feedback.js.map +0 -1
  53. package/dist/browser/focus.js.map +0 -1
  54. package/dist/browser/locator.js.map +0 -1
  55. package/dist/browser/prompt.generated.js.map +0 -1
  56. package/dist/browser/prompt.js.map +0 -1
  57. package/dist/browser/snapshot.js.map +0 -1
  58. package/dist/browser/toolset.js.map +0 -1
  59. package/dist/browser/types.js.map +0 -1
  60. package/dist/browser/worker-runner.js.map +0 -1
  61. package/dist/definition.js.map +0 -1
  62. package/dist/index.browser.js.map +0 -1
  63. package/dist/index.js.map +0 -1
  64. package/dist/internal-react.js.map +0 -1
  65. package/dist/internal-types.js.map +0 -1
  66. package/dist/navigation.js.map +0 -1
  67. package/dist/operation-lock.js.map +0 -1
  68. package/dist/operation-runtime.js.map +0 -1
  69. package/dist/operation-surface.js.map +0 -1
  70. package/dist/operation-types.js.map +0 -1
  71. package/dist/operation-view.js.map +0 -1
  72. package/dist/react.js.map +0 -1
  73. package/dist/registration.js.map +0 -1
  74. package/dist/runtime.js.map +0 -1
  75. package/dist/shared/definition.js.map +0 -1
  76. package/dist/shared/errors.js.map +0 -1
  77. package/dist/shared/page-protocol.js.map +0 -1
  78. package/dist/shared/page-tools.js.map +0 -1
  79. package/dist/shared/runtime-controller.js.map +0 -1
  80. package/dist/shared/runtime-execution.js.map +0 -1
  81. package/dist/shared/schema.js.map +0 -1
  82. package/dist/types.js.map +0 -1
  83. package/dist/webmcp.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
  import { flushSync } from "react-dom";
3
- import { useCallback, useLayoutEffect, useRef, useState } from "react";
3
+ import { useCallback, useLayoutEffect, useRef, useState, } from "react";
4
4
  import { useSyncExternalStore } from "use-sync-external-store/shim";
5
5
  import { PageCommandError } from "./browser/locator.js";
6
6
  import { getInternalToolRuntime } from "./runtime.js";
@@ -9,7 +9,8 @@ import { isAgentActivation } from "./browser/focus.js";
9
9
  import { OperationOverlayView } from "./operation-view.js";
10
10
  const BROWSER_TOOL_NAMES = new Set(["nxf_getSnapshot", "nxf_executeAction", "nxf_applyAction"]);
11
11
  const belongsToOperation = (event, operation) => !operation || event.operationId === operation.id;
12
- const canPresentInOperation = (event, operation) => belongsToOperation(event, operation) && (!operation || operation.status === "running" || operation.status === "ending");
12
+ const canPresentInOperation = (event, operation) => belongsToOperation(event, operation) &&
13
+ (!operation || operation.status === "running" || operation.status === "ending");
13
14
  const surfaces = new WeakSet();
14
15
  export function AgentOperationSurface(props) {
15
16
  const element = useRef(null);
@@ -21,28 +22,34 @@ export function AgentOperationSurface(props) {
21
22
  if (surfaces.has(props.toolRuntime))
22
23
  throw new Error("Only one AgentOperationSurface is supported per Runtime.");
23
24
  surfaces.add(props.toolRuntime);
24
- return () => { surfaces.delete(props.toolRuntime); };
25
+ return () => {
26
+ surfaces.delete(props.toolRuntime);
27
+ };
25
28
  }, [props.toolRuntime]);
26
29
  const blockUserInput = useCallback((event) => {
27
30
  if ((event.type === "submit" || event.type === "reset") && isAgentActivation())
28
31
  return;
29
- if (!element.current || !isOperationSurfaceLocked(element.current) || !event.nativeEvent.isTrusted)
32
+ if (!element.current ||
33
+ !isOperationSurfaceLocked(element.current) ||
34
+ !event.nativeEvent.isTrusted)
30
35
  return;
31
36
  event.preventDefault();
32
37
  event.stopPropagation();
33
38
  }, []);
34
39
  const blockPassiveUserInput = useCallback((event) => {
35
- if (!element.current || !isOperationSurfaceLocked(element.current) || !event.nativeEvent.isTrusted)
40
+ if (!element.current ||
41
+ !isOperationSurfaceLocked(element.current) ||
42
+ !event.nativeEvent.isTrusted)
36
43
  return;
37
44
  // Stop React's capture dispatch, but let the native event reach our non-passive
38
45
  // surface listener. React's passive root listener cannot prevent scrolling.
39
46
  event.isPropagationStopped = () => true;
40
47
  }, []);
41
- return React.createElement(React.Fragment, null,
48
+ return (React.createElement(React.Fragment, null,
42
49
  React.createElement("div", { ref: element, className: "nexface-operation-surface", onClickCapture: blockUserInput, onDoubleClickCapture: blockUserInput, onAuxClickCapture: blockUserInput, onPointerDownCapture: blockUserInput, onPointerUpCapture: blockUserInput, onPointerMoveCapture: blockUserInput, onPointerOverCapture: blockUserInput, onPointerOutCapture: blockUserInput, onMouseDownCapture: blockUserInput, onMouseUpCapture: blockUserInput, onContextMenuCapture: blockUserInput, onMouseMoveCapture: blockUserInput, onMouseOverCapture: blockUserInput, onMouseOutCapture: blockUserInput, onWheelCapture: blockPassiveUserInput, onTouchStartCapture: blockPassiveUserInput, onTouchMoveCapture: blockPassiveUserInput, onTouchEndCapture: blockUserInput, onTouchCancelCapture: blockUserInput, onKeyDownCapture: blockUserInput, onKeyUpCapture: blockUserInput, onKeyPressCapture: blockUserInput, onBeforeInputCapture: blockUserInput, onPasteCapture: blockUserInput, onCutCapture: blockUserInput, onDropCapture: blockUserInput, onDragStartCapture: blockUserInput, onSubmitCapture: blockUserInput, onResetCapture: blockUserInput }, props.children),
43
- React.createElement(OperationSurfaceContent, { ...props, element: element }));
50
+ React.createElement(OperationSurfaceContent, { ...props, element: element })));
44
51
  }
45
- function OperationSurfaceContent({ toolRuntime, element }) {
52
+ function OperationSurfaceContent({ toolRuntime, element, }) {
46
53
  const runtime = getInternalToolRuntime(toolRuntime);
47
54
  const activity = useSyncExternalStore(runtime.subscribeActivity, runtime.getActivitySnapshot, runtime.getActivitySnapshot);
48
55
  const cycle = activity.operation;
@@ -58,15 +65,24 @@ function OperationSurfaceContent({ toolRuntime, element }) {
58
65
  useLayoutEffect(() => runtime.setPageActionFeedback((event, feedback, signal) => {
59
66
  const operation = runtime.getActivitySnapshot().operation;
60
67
  if (signal?.aborted || !canPresentInOperation(event, operation))
61
- throw new PageCommandError({ code: "EXECUTION_CANCELLED", message: "Page action presentation was interrupted." });
68
+ throw new PageCommandError({
69
+ code: "EXECUTION_CANCELLED",
70
+ message: "Page action presentation was interrupted.",
71
+ });
62
72
  const target = feedback.target;
63
- if (!feedback.effect || (feedback.effect === "action" && (!target?.isConnected || !element.current?.contains(target)))) {
73
+ if (!feedback.effect ||
74
+ (feedback.effect === "action" &&
75
+ (!target?.isConnected || !element.current?.contains(target)))) {
64
76
  setVisual(undefined);
65
77
  return;
66
78
  }
67
79
  const next = {
68
- id: crypto.randomUUID(), effect: feedback.effect, label: label(event),
69
- centered: feedback.effect === "read", persistentCursor: true, requiresTarget: feedback.effect === "action",
80
+ id: crypto.randomUUID(),
81
+ effect: feedback.effect,
82
+ label: label(event),
83
+ centered: feedback.effect === "read",
84
+ persistentCursor: true,
85
+ requiresTarget: feedback.effect === "action",
70
86
  ...(target ? { target } : {}),
71
87
  };
72
88
  if (feedback.effect !== "action") {
@@ -98,32 +114,61 @@ function OperationSurfaceContent({ toolRuntime, element }) {
98
114
  const page = BROWSER_TOOL_NAMES.has(event.name);
99
115
  if (canDisplay && event.status === "running") {
100
116
  if (page)
101
- setVisual(event.name === "nxf_getSnapshot" ? { event, feedback: {
102
- id: event.id, effect: "read", label: label(event), centered: true,
103
- } } : undefined);
117
+ setVisual(event.name === "nxf_getSnapshot"
118
+ ? {
119
+ event,
120
+ feedback: {
121
+ id: event.id,
122
+ effect: "read",
123
+ label: label(event),
124
+ centered: true,
125
+ },
126
+ }
127
+ : undefined);
104
128
  else {
105
- const target = event.tool.definition.effect === "navigate" ? element.current : runtime.resolveTarget(event.tool, event.input);
129
+ const target = event.tool.definition.effect === "navigate"
130
+ ? element.current
131
+ : runtime.resolveTarget(event.tool, event.input);
106
132
  if (target?.isConnected && element.current?.contains(target)) {
107
133
  const rect = target.getBoundingClientRect();
108
- setVisual({ event, feedback: { id: event.id, effect: event.tool.definition.effect ?? "action", label: label(event),
109
- resolveTarget: () => event.tool.definition.effect === "navigate" ? element.current ?? undefined : runtime.resolveTarget(event.tool, event.input),
110
- position: { left: rect.left + rect.width / 2, top: rect.top + rect.height / 2 } } });
134
+ setVisual({
135
+ event,
136
+ feedback: {
137
+ id: event.id,
138
+ effect: event.tool.definition.effect ?? "action",
139
+ label: label(event),
140
+ resolveTarget: () => event.tool.definition.effect === "navigate"
141
+ ? (element.current ?? undefined)
142
+ : runtime.resolveTarget(event.tool, event.input),
143
+ position: { left: rect.left + rect.width / 2, top: rect.top + rect.height / 2 },
144
+ },
145
+ });
111
146
  }
112
147
  }
113
148
  }
114
149
  else if (canDisplay)
115
150
  setVisual((current) => current?.event.id === event.id && current.event.operationId === event.operationId
116
- ? page ? undefined : { ...current, event } : current);
151
+ ? page
152
+ ? undefined
153
+ : { ...current, event }
154
+ : current);
117
155
  if (page && !operation && event.status === "error")
118
156
  setOutcome({ id: scope, status: event.cancelled ? "cancelled" : "failed" });
119
157
  setHistory((current) => {
120
- if (!belongsToOperation(event, operation) || (event.status !== "running" && current.scope !== scope))
158
+ if (!belongsToOperation(event, operation) ||
159
+ (event.status !== "running" && current.scope !== scope))
121
160
  return current;
122
161
  const entries = current.scope === scope ? current.entries : [];
123
- const entry = { toolCallId: event.id,
124
- progressLabel: `${event.progressLabel || "正在处理你的请求"} · ${event.cancelled ? "已取消" : event.status === "running" ? "执行中" : event.status === "success" ? "已完成" : "失败"}` };
125
- return { scope, entries: entries.some((item) => item.toolCallId === event.id)
126
- ? entries.map((item) => item.toolCallId === event.id ? entry : item) : [...entries, entry] };
162
+ const entry = {
163
+ toolCallId: event.id,
164
+ progressLabel: `${event.progressLabel || "正在处理你的请求"} · ${event.cancelled ? "已取消" : event.status === "running" ? "执行中" : event.status === "success" ? "已完成" : "失败"}`,
165
+ };
166
+ return {
167
+ scope,
168
+ entries: entries.some((item) => item.toolCallId === event.id)
169
+ ? entries.map((item) => (item.toolCallId === event.id ? entry : item))
170
+ : [...entries, entry],
171
+ };
127
172
  });
128
173
  };
129
174
  const unsubscribe = toolRuntime.on("toolexecution", onExecution);
@@ -136,25 +181,57 @@ function OperationSurfaceContent({ toolRuntime, element }) {
136
181
  const waiting = cycle?.status === "waiting" && !executing;
137
182
  const running = executing || (activated && cycle?.status !== "waiting");
138
183
  const stopping = cycle?.status === "cancelling";
139
- useLayoutEffect(() => { if (!running || waiting)
140
- setVisual(undefined); }, [running, waiting]);
184
+ useLayoutEffect(() => {
185
+ if (!running || waiting)
186
+ setVisual(undefined);
187
+ }, [running, waiting]);
141
188
  const serverExecuting = cycle?.taskProgress?.phase === "tool";
142
189
  const visualExecuting = Boolean(visual && activity.executions.some((event) => event.id === visual.event.id));
143
- const currentVisual = !stopping && !waiting && visual
144
- && (!serverExecuting || (BROWSER_TOOL_NAMES.has(visual.event.name) && visualExecuting))
145
- && canPresentInOperation(visual.event, cycle) && (cycle || visualExecuting) ? visual : undefined;
190
+ const currentVisual = !stopping &&
191
+ !waiting &&
192
+ visual &&
193
+ (!serverExecuting || (BROWSER_TOOL_NAMES.has(visual.event.name) && visualExecuting)) &&
194
+ canPresentInOperation(visual.event, cycle) &&
195
+ (cycle || visualExecuting)
196
+ ? visual
197
+ : undefined;
146
198
  const browserExecution = activity.executions.find((event) => BROWSER_TOOL_NAMES.has(event.name));
147
- const progressLabel = currentVisual?.feedback.label ?? (waiting ? "等待你完成操作" : stopping ? "正在终止"
148
- : browserExecution ? browserExecution.progressLabel || "正在浏览网页"
149
- : cycle?.taskProgress?.phase === "tool" ? cycle.taskProgress.progressLabel || "正在执行工具"
150
- : cycle?.taskProgress ? "正在处理" : "正在处理你的请求");
151
- const operation = { progressLabel, status: currentVisual
152
- ? currentVisual.event.status === "running" ? "running" : currentVisual.event.status === "success" ? "completed" : "failed"
153
- : running || waiting ? "running" : outcome?.id === history.scope ? outcome.status : "completed" };
154
- const feedback = currentVisual?.feedback ?? (serverExecuting && running && !waiting && !stopping
155
- ? { id: cycle.taskProgress.toolCallId, effect: "read", label: progressLabel, centered: true } : undefined);
199
+ const progressLabel = currentVisual?.feedback.label ??
200
+ (waiting
201
+ ? "等待你完成操作"
202
+ : stopping
203
+ ? "正在终止"
204
+ : browserExecution
205
+ ? browserExecution.progressLabel || "正在浏览网页"
206
+ : cycle?.taskProgress?.phase === "tool"
207
+ ? cycle.taskProgress.progressLabel || "正在执行工具"
208
+ : cycle?.taskProgress
209
+ ? "正在处理"
210
+ : "正在处理你的请求");
211
+ const operation = {
212
+ progressLabel,
213
+ status: currentVisual
214
+ ? currentVisual.event.status === "running"
215
+ ? "running"
216
+ : currentVisual.event.status === "success"
217
+ ? "completed"
218
+ : "failed"
219
+ : running || waiting
220
+ ? "running"
221
+ : outcome?.id === history.scope
222
+ ? outcome.status
223
+ : "completed",
224
+ };
225
+ const feedback = currentVisual?.feedback ??
226
+ (serverExecuting && running && !waiting && !stopping
227
+ ? {
228
+ id: cycle.taskProgress.toolCallId,
229
+ effect: "read",
230
+ label: progressLabel,
231
+ centered: true,
232
+ }
233
+ : undefined);
156
234
  const resolveSurface = useCallback(() => element.current ?? undefined, [element]);
157
235
  const entries = !cycle || history.scope === cycle.id ? history.entries : [];
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;
236
+ 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
237
  }
160
- //# sourceMappingURL=operation-surface.js.map
@@ -1,2 +1 @@
1
1
  export {};
2
- //# sourceMappingURL=operation-types.js.map
@@ -10,4 +10,4 @@ export interface OperationOverlayViewProps {
10
10
  onCancel?(): void;
11
11
  resolveSurface?(): HTMLElement | undefined;
12
12
  }
13
- export declare function OperationOverlayView({ operation, feedback, progressHistory, running, humanHasControl, cancelling, onCancel: cancel, resolveSurface }: OperationOverlayViewProps): React.ReactPortal | null;
13
+ export declare function OperationOverlayView({ operation, feedback, progressHistory, running, humanHasControl, cancelling, onCancel: cancel, resolveSurface, }: OperationOverlayViewProps): React.ReactPortal | null;
@@ -1,13 +1,19 @@
1
1
  import { CursorIcon as Cursor } from "@phosphor-icons/react/Cursor";
2
2
  import { SparkleIcon as Sparkle } from "@phosphor-icons/react/Sparkle";
3
3
  import * as React from "react";
4
- import { useCallback, useLayoutEffect, useEffect, useRef, useState } from "react";
4
+ import { useCallback, useLayoutEffect, useEffect, useRef, useState, } from "react";
5
5
  import { createPortal } from "react-dom";
6
6
  import { PageCommandError } from "./browser/locator.js";
7
7
  import { lockOperationSurface } from "./operation-lock.js";
8
- const center = (rect) => ({ left: rect.left + rect.width / 2, top: rect.top + rect.height / 2 });
8
+ const center = (rect) => ({
9
+ left: rect.left + rect.width / 2,
10
+ top: rect.top + rect.height / 2,
11
+ });
9
12
  const distance = (a, b) => Math.hypot(a.left - b.left, a.top - b.top);
10
- const interrupted = () => new PageCommandError({ code: "EXECUTION_CANCELLED", message: "Page action presentation was interrupted." });
13
+ const interrupted = () => new PageCommandError({
14
+ code: "EXECUTION_CANCELLED",
15
+ message: "Page action presentation was interrupted.",
16
+ });
11
17
  function presentPointer(pointer, target, presentation) {
12
18
  let finished = false;
13
19
  const finish = (error) => {
@@ -19,45 +25,57 @@ function presentPointer(pointer, target, presentation) {
19
25
  presentation.signal?.removeEventListener("abort", onAbort);
20
26
  presentation.finish(error);
21
27
  };
22
- const reached = () => pointer.isConnected && target.isConnected && distance(pointer.getBoundingClientRect(), center(target.getBoundingClientRect())) < 2;
28
+ const reached = () => pointer.isConnected &&
29
+ target.isConnected &&
30
+ distance(pointer.getBoundingClientRect(), center(target.getBoundingClientRect())) < 2;
23
31
  const onTransition = (event) => {
24
32
  if (event.target === pointer && event.propertyName === "transform" && reached())
25
33
  finish();
26
34
  };
27
35
  const onAbort = () => finish(interrupted());
28
- const timer = setTimeout(() => reached() ? finish() : finish(new PageCommandError({
29
- code: "ACTION_TIMEOUT", message: "Page action pointer did not reach its target in time.",
30
- })), 750);
36
+ const timer = setTimeout(() => reached()
37
+ ? finish()
38
+ : finish(new PageCommandError({
39
+ code: "ACTION_TIMEOUT",
40
+ message: "Page action pointer did not reach its target in time.",
41
+ })), 750);
31
42
  pointer.addEventListener("transitionend", onTransition);
32
43
  presentation.signal?.addEventListener("abort", onAbort, { once: true });
33
- queueMicrotask(() => { if (presentation.signal?.aborted)
34
- onAbort();
35
- else if (reached())
36
- finish(); });
44
+ queueMicrotask(() => {
45
+ if (presentation.signal?.aborted)
46
+ onAbort();
47
+ else if (reached())
48
+ finish();
49
+ });
37
50
  return () => finish(interrupted());
38
51
  }
39
52
  function FeedbackLabel({ feedback }) {
40
- return React.createElement("span", { className: "agent-operation__pointer-label", "data-browser-tool": feedback.centered ? "true" : undefined, "data-operation-effect": feedback.effect, title: feedback.label },
41
- feedback.effect === "processing" ? React.createElement("span", { className: "agent-operation__pointer-processing" }) : null,
42
- feedback.effect === "read" ? React.createElement("span", { className: "agent-operation__pointer-read-scan" },
53
+ return (React.createElement("span", { className: "agent-operation__pointer-label", "data-browser-tool": feedback.centered ? "true" : undefined, "data-operation-effect": feedback.effect, title: feedback.label },
54
+ feedback.effect === "processing" ? (React.createElement("span", { className: "agent-operation__pointer-processing" })) : null,
55
+ feedback.effect === "read" ? (React.createElement("span", { className: "agent-operation__pointer-read-scan" },
43
56
  React.createElement("i", null),
44
57
  React.createElement("i", null),
45
58
  React.createElement("i", null),
46
59
  React.createElement("i", null),
47
- React.createElement("i", null)) : null,
48
- feedback.effect === "navigate" ? React.createElement("span", { className: "agent-operation__pointer-navigation-trail" }) : null,
49
- React.createElement("span", { className: "agent-operation__pointer-label-text" }, feedback.label));
60
+ React.createElement("i", null))) : null,
61
+ feedback.effect === "navigate" ? (React.createElement("span", { className: "agent-operation__pointer-navigation-trail" })) : null,
62
+ React.createElement("span", { className: "agent-operation__pointer-label-text" }, feedback.label)));
50
63
  }
51
- function FeedbackIndicator({ feedback, position }) {
64
+ function FeedbackIndicator({ feedback, position, }) {
52
65
  const [lastPosition, setLastPosition] = useState(position ?? feedback.position);
53
- useLayoutEffect(() => { if (position)
54
- setLastPosition(position); }, [position?.left, position?.top]);
66
+ useLayoutEffect(() => {
67
+ if (position)
68
+ setLastPosition(position);
69
+ }, [position?.left, position?.top]);
55
70
  const current = position ?? lastPosition;
56
- return current ? React.createElement("div", { "aria-hidden": true, className: "agent-operation__pointer-effect", "data-active": "true", "data-operation-effect": feedback.effect, style: { "--agent-operation-pointer-duration": "0ms", "--agent-operation-pointer-x": `${current.left}px`,
57
- "--agent-operation-pointer-y": `${current.top}px` } },
58
- React.createElement(FeedbackLabel, { feedback: feedback })) : null;
71
+ return current ? (React.createElement("div", { "aria-hidden": true, className: "agent-operation__pointer-effect", "data-active": "true", "data-operation-effect": feedback.effect, style: {
72
+ "--agent-operation-pointer-duration": "0ms",
73
+ "--agent-operation-pointer-x": `${current.left}px`,
74
+ "--agent-operation-pointer-y": `${current.top}px`,
75
+ } },
76
+ React.createElement(FeedbackLabel, { feedback: feedback }))) : null;
59
77
  }
60
- function AgentPointer({ active, feedback, targetPosition, surfaceCenter }) {
78
+ function AgentPointer({ active, feedback, targetPosition, surfaceCenter, }) {
61
79
  const pointer = useRef(null);
62
80
  const [motion, setMotion] = useState();
63
81
  const action = feedback?.effect === "action" && (!feedback.requiresTarget || Boolean(targetPosition));
@@ -75,8 +93,11 @@ function AgentPointer({ active, feedback, targetPosition, surfaceCenter }) {
75
93
  return;
76
94
  }
77
95
  if (!motion) {
78
- setMotion({ position: feedback?.persistentCursor && surfaceCenter ? surfaceCenter : targetPosition,
79
- durationMs: 0, persistent: Boolean(feedback?.persistentCursor) });
96
+ setMotion({
97
+ position: feedback?.persistentCursor && surfaceCenter ? surfaceCenter : targetPosition,
98
+ durationMs: 0,
99
+ persistent: Boolean(feedback?.persistentCursor),
100
+ });
80
101
  return;
81
102
  }
82
103
  if (distance(motion.position, targetPosition) < 1) {
@@ -85,9 +106,14 @@ function AgentPointer({ active, feedback, targetPosition, surfaceCenter }) {
85
106
  return;
86
107
  }
87
108
  const from = pointer.current?.getBoundingClientRect() ?? motion.position;
88
- const durationMs = window.matchMedia?.("(prefers-reduced-motion: reduce)").matches ? 0
109
+ const durationMs = window.matchMedia?.("(prefers-reduced-motion: reduce)").matches
110
+ ? 0
89
111
  : Math.round(Math.min(360, Math.max(180, 180 + distance(from, targetPosition) * 0.18)));
90
- setMotion({ position: targetPosition, durationMs, persistent: motion.persistent || Boolean(feedback?.persistentCursor) });
112
+ setMotion({
113
+ position: targetPosition,
114
+ durationMs,
115
+ persistent: motion.persistent || Boolean(feedback?.persistentCursor),
116
+ });
91
117
  }, [active, action, feedback?.id, targetPosition?.left, targetPosition?.top, motion]);
92
118
  const show = Boolean(active && motion && (motion.persistent || action));
93
119
  useLayoutEffect(() => {
@@ -100,18 +126,22 @@ function AgentPointer({ active, feedback, targetPosition, surfaceCenter }) {
100
126
  if (show && pointer.current)
101
127
  return presentPointer(pointer.current, feedback.target, feedback.presentation);
102
128
  }, [active, show, feedback?.presentation, feedback?.target, Boolean(targetPosition)]);
103
- return show && motion ? React.createElement("div", { "aria-hidden": true, ref: pointer, className: "agent-operation__pointer-effect", "data-active": action, "data-operation-effect": action ? "action" : undefined, style: { "--agent-operation-pointer-duration": `${motion.durationMs}ms`,
104
- "--agent-operation-pointer-x": `${motion.position.left}px`, "--agent-operation-pointer-y": `${motion.position.top}px` } },
129
+ return show && motion ? (React.createElement("div", { "aria-hidden": true, ref: pointer, className: "agent-operation__pointer-effect", "data-active": action, "data-operation-effect": action ? "action" : undefined, style: {
130
+ "--agent-operation-pointer-duration": `${motion.durationMs}ms`,
131
+ "--agent-operation-pointer-x": `${motion.position.left}px`,
132
+ "--agent-operation-pointer-y": `${motion.position.top}px`,
133
+ } },
105
134
  React.createElement("span", { className: "agent-operation__pointer-cursor" },
106
135
  React.createElement(Cursor, { className: "agent-operation__pointer", size: 24, weight: "fill" })),
107
- action && feedback ? React.createElement(FeedbackLabel, { feedback: feedback }) : null) : null;
136
+ action && feedback ? React.createElement(FeedbackLabel, { feedback: feedback }) : null)) : null;
108
137
  }
109
- export function OperationOverlayView({ operation, feedback, progressHistory = [], running, humanHasControl = false, cancelling = false, onCancel: cancel, resolveSurface }) {
138
+ export function OperationOverlayView({ operation, feedback, progressHistory = [], running, humanHasControl = false, cancelling = false, onCancel: cancel, resolveSurface, }) {
110
139
  const [, setGeometry] = useState("");
111
140
  const [historyOpen, setHistoryOpen] = useState(false);
112
141
  const [historyId] = useState(() => `nexface-operation-history-${globalThis.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random()}`}`);
113
142
  const cancelButtonRef = useRef(null);
114
- const controllerShouldBeVisible = operation.status !== "cancelled" && (running || humanHasControl || operation.status === "failed");
143
+ const controllerShouldBeVisible = operation.status !== "cancelled" &&
144
+ (running || humanHasControl || operation.status === "failed");
115
145
  const [controllerVisibility, setControllerVisibility] = useState(controllerShouldBeVisible ? "visible" : undefined);
116
146
  useEffect(() => {
117
147
  if (controllerShouldBeVisible) {
@@ -119,12 +149,14 @@ export function OperationOverlayView({ operation, feedback, progressHistory = []
119
149
  return;
120
150
  }
121
151
  setHistoryOpen(false);
122
- setControllerVisibility((current) => current ? "exiting" : undefined);
152
+ setControllerVisibility((current) => (current ? "exiting" : undefined));
123
153
  const timer = setTimeout(() => setControllerVisibility(undefined), 300);
124
154
  return () => clearTimeout(timer);
125
155
  }, [controllerShouldBeVisible]);
126
- useEffect(() => { if (!progressHistory.length)
127
- setHistoryOpen(false); }, [progressHistory.length]);
156
+ useEffect(() => {
157
+ if (!progressHistory.length)
158
+ setHistoryOpen(false);
159
+ }, [progressHistory.length]);
128
160
  useLayoutEffect(() => {
129
161
  const surface = resolveSurface?.();
130
162
  if (!surface || !running || humanHasControl)
@@ -144,17 +176,22 @@ export function OperationOverlayView({ operation, feedback, progressHistory = []
144
176
  useLayoutEffect(() => {
145
177
  const update = () => {
146
178
  const { surfaceRect, targetRect } = readGeometry();
147
- const geometry = [surfaceRect, targetRect].map((rect) => {
179
+ const geometry = [surfaceRect, targetRect]
180
+ .map((rect) => {
148
181
  if (!rect)
149
182
  return "";
150
183
  return [rect.left, rect.top, rect.width, rect.height].join(",");
151
- }).join(";");
184
+ })
185
+ .join(";");
152
186
  setGeometry(geometry);
153
187
  };
154
188
  update();
155
189
  if (!running && !humanHasControl)
156
190
  return;
157
- let frame = requestAnimationFrame(function track() { update(); frame = requestAnimationFrame(track); });
191
+ let frame = requestAnimationFrame(function track() {
192
+ update();
193
+ frame = requestAnimationFrame(track);
194
+ });
158
195
  return () => cancelAnimationFrame(frame);
159
196
  }, [readGeometry, operation, running, humanHasControl]);
160
197
  if (typeof document === "undefined")
@@ -170,29 +207,53 @@ export function OperationOverlayView({ operation, feedback, progressHistory = []
170
207
  const controllerExiting = controllerVisibility === "exiting";
171
208
  const controllerLabel = humanHasControl ? undefined : operation.progressLabel;
172
209
  const compactStatusLabel = humanHasControl ? "等待你完成操作" : operation.progressLabel;
173
- const statusLabel = humanHasControl ? "等待你完成操作" : {
174
- running: "Agent 正在控制", completed: running ? "工具已完成,任务继续中" : "操作已完成",
175
- failed: running ? "Agent 正在处理错误" : "操作失败", cancelled: "任务已终止",
176
- }[operation.status];
210
+ const statusLabel = humanHasControl
211
+ ? "等待你完成操作"
212
+ : {
213
+ running: "Agent 正在控制",
214
+ completed: running ? "工具已完成,任务继续中" : "操作已完成",
215
+ failed: running ? "Agent 正在处理错误" : "操作失败",
216
+ cancelled: "任务已终止",
217
+ }[operation.status];
177
218
  const targetPosition = rect ? center(rect) : undefined;
178
219
  return createPortal(React.createElement("div", { className: "agent-operation", "data-nexface-ignore": true, "data-feedback-active": operationFeedbackActive, "data-structured-target-lost": structuredTargetLost, "data-human-control": humanHasControl, "data-operation-effect": effect ?? "action", "data-run-active": running, "data-status": operation.status },
179
- agentControlsSurface && surfaceRect ? React.createElement("div", { "aria-hidden": true, className: "agent-operation__surface", style: {
180
- ...(highlightedRect ? { "--agent-operation-cutout-height": `${highlightedRect.height}px`,
181
- "--agent-operation-cutout-left": `${highlightedRect.left - surfaceRect.left}px`,
182
- "--agent-operation-cutout-top": `${highlightedRect.top - surfaceRect.top}px`, "--agent-operation-cutout-width": `${highlightedRect.width}px` } : {}),
183
- height: surfaceRect.height, left: surfaceRect.left, top: surfaceRect.top, width: surfaceRect.width,
184
- } }) : null,
185
- activeFeedback && highlightedRect ? React.createElement("div", { "aria-hidden": true, className: "agent-operation__target", "data-operation-effect": effect, style: { height: highlightedRect.height, left: highlightedRect.left, top: highlightedRect.top, width: highlightedRect.width } }) : null,
220
+ agentControlsSurface && surfaceRect ? (React.createElement("div", { "aria-hidden": true, className: "agent-operation__surface", style: {
221
+ ...(highlightedRect
222
+ ? {
223
+ "--agent-operation-cutout-height": `${highlightedRect.height}px`,
224
+ "--agent-operation-cutout-left": `${highlightedRect.left - surfaceRect.left}px`,
225
+ "--agent-operation-cutout-top": `${highlightedRect.top - surfaceRect.top}px`,
226
+ "--agent-operation-cutout-width": `${highlightedRect.width}px`,
227
+ }
228
+ : {}),
229
+ height: surfaceRect.height,
230
+ left: surfaceRect.left,
231
+ top: surfaceRect.top,
232
+ width: surfaceRect.width,
233
+ } })) : null,
234
+ activeFeedback && highlightedRect ? (React.createElement("div", { "aria-hidden": true, className: "agent-operation__target", "data-operation-effect": effect, style: {
235
+ height: highlightedRect.height,
236
+ left: highlightedRect.left,
237
+ top: highlightedRect.top,
238
+ width: highlightedRect.width,
239
+ } })) : null,
186
240
  React.createElement(AgentPointer, { active: agentControlsSurface && !cancelling, feedback: feedback?.presentation ? feedback : activeFeedback, targetPosition: targetPosition, surfaceCenter: surfaceRect ? center(surfaceRect) : undefined }),
187
- activeFeedback && effect !== "action" && surfaceRect ? React.createElement(FeedbackIndicator, { key: activeFeedback.id, feedback: activeFeedback, position: activeFeedback.centered ? center(surfaceRect) : targetPosition }) : null,
188
- controllerMounted ? React.createElement("section", { "aria-live": "polite", className: "agent-operation__controller", "data-visibility": controllerExiting ? "exiting" : "visible", style: surfaceRect ? { left: surfaceRect.left + surfaceRect.width / 2, right: "auto", "--agent-operation-controller-x": "-50%", maxWidth: Math.max(0, surfaceRect.width - 32) } : undefined },
189
- historyOpen ? React.createElement("aside", { "aria-label": "\u672C\u6B21\u8FD0\u884C\u7684\u64CD\u4F5C\u8BB0\u5F55", className: "agent-operation__history", id: historyId },
241
+ activeFeedback && effect !== "action" && surfaceRect ? (React.createElement(FeedbackIndicator, { key: activeFeedback.id, feedback: activeFeedback, position: activeFeedback.centered ? center(surfaceRect) : targetPosition })) : null,
242
+ controllerMounted ? (React.createElement("section", { "aria-live": "polite", className: "agent-operation__controller", "data-visibility": controllerExiting ? "exiting" : "visible", style: surfaceRect
243
+ ? {
244
+ left: surfaceRect.left + surfaceRect.width / 2,
245
+ right: "auto",
246
+ "--agent-operation-controller-x": "-50%",
247
+ maxWidth: Math.max(0, surfaceRect.width - 32),
248
+ }
249
+ : undefined },
250
+ historyOpen ? (React.createElement("aside", { "aria-label": "\u672C\u6B21\u8FD0\u884C\u7684\u64CD\u4F5C\u8BB0\u5F55", className: "agent-operation__history", id: historyId },
190
251
  React.createElement("header", null,
191
252
  React.createElement("strong", null, "\u64CD\u4F5C\u8BB0\u5F55"),
192
253
  React.createElement("span", null, progressHistory.length)),
193
- React.createElement("ol", null, progressHistory.map(({ progressLabel: label, toolCallId }, index) => React.createElement("li", { key: toolCallId },
254
+ React.createElement("ol", null, progressHistory.map(({ progressLabel: label, toolCallId }, index) => (React.createElement("li", { key: toolCallId },
194
255
  React.createElement("span", { "aria-hidden": true }, index + 1),
195
- React.createElement("p", null, label))))) : null,
256
+ React.createElement("p", null, label))))))) : null,
196
257
  React.createElement("span", { "aria-hidden": true, className: "agent-operation__edge-flow" }),
197
258
  React.createElement("span", { "aria-hidden": true, className: "agent-operation__pause-mark" },
198
259
  React.createElement("i", null),
@@ -204,9 +265,8 @@ export function OperationOverlayView({ operation, feedback, progressHistory = []
204
265
  React.createElement("div", null,
205
266
  React.createElement("span", { className: "agent-operation__heading" },
206
267
  React.createElement("strong", null, controllerLabel)),
207
- statusLabel ? React.createElement("small", { className: "agent-operation__description" },
208
- React.createElement("span", { className: "agent-operation__status" }, statusLabel)) : null),
209
- (running || humanHasControl) && operation.status !== "cancelled" ? React.createElement("span", { className: "agent-operation__compact-status", title: compactStatusLabel }, compactStatusLabel) : null,
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);
268
+ statusLabel ? (React.createElement("small", { className: "agent-operation__description" },
269
+ React.createElement("span", { className: "agent-operation__status" }, statusLabel))) : null),
270
+ (running || humanHasControl) && operation.status !== "cancelled" ? (React.createElement("span", { className: "agent-operation__compact-status", title: compactStatusLabel }, compactStatusLabel)) : null,
271
+ 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
272
  }
212
- //# sourceMappingURL=operation-view.js.map
package/dist/react.js CHANGED
@@ -3,7 +3,7 @@ import { Children, Fragment, cloneElement, useCallback, useEffect, useLayoutEffe
3
3
  import { defineAgentTool } from "./definition.js";
4
4
  import { getAgentNavigationEntries, } from "./navigation.js";
5
5
  import { AgentToolError, getInternalToolRuntime } from "./runtime.js";
6
- import { InternalToolRuntimeScope, useInternalToolRuntime, } from "./internal-react.js";
6
+ import { InternalToolRuntimeScope, useInternalToolRuntime } from "./internal-react.js";
7
7
  import { connectToolRuntimeToWebMcp } from "./webmcp.js";
8
8
  const bindingInternals = new WeakMap();
9
9
  export function getAgentToolBindingInternals(binding) {
@@ -55,10 +55,10 @@ function createAgentToolBinding(toolName) {
55
55
  function useAgentBinding(definition, execute, options) {
56
56
  const runtime = useInternalToolRuntime();
57
57
  const confirmation = options.requiresConfirmation;
58
- if (confirmation !== undefined
59
- && (!confirmation
60
- || typeof confirmation !== "object"
61
- || (confirmation.mode !== "chat" && confirmation.mode !== "page"))) {
58
+ if (confirmation !== undefined &&
59
+ (!confirmation ||
60
+ typeof confirmation !== "object" ||
61
+ (confirmation.mode !== "chat" && confirmation.mode !== "page"))) {
62
62
  throw new Error("requiresConfirmation must explicitly use chat or page mode.");
63
63
  }
64
64
  const executeRef = useRef(execute);
@@ -82,9 +82,7 @@ export function useAgentTool(definition, execute, options = {}) {
82
82
  return useAgentBinding(definition, execute, options);
83
83
  }
84
84
  function getAgentNavigationExecutor(executors, key) {
85
- if (!executors
86
- || typeof executors !== "object"
87
- || !Object.hasOwn(executors, key)) {
85
+ if (!executors || typeof executors !== "object" || !Object.hasOwn(executors, key)) {
88
86
  throw new Error(`Missing navigation executor: ${key}.`);
89
87
  }
90
88
  const executor = executors[key];
@@ -203,9 +201,7 @@ function isHTMLElement(value) {
203
201
  return ElementConstructor !== undefined && value instanceof ElementConstructor;
204
202
  }
205
203
  function warnAgentUIAction(message) {
206
- if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
207
- console.warn(message);
208
- }
204
+ console.warn(message);
209
205
  }
210
206
  const eventAdapters = {
211
207
  click: {
@@ -286,8 +282,8 @@ export function AgentUIAction({ name, description, event = "click", children, })
286
282
  if (warnedChildRef.current !== warningType) {
287
283
  warnedChildRef.current = warningType;
288
284
  warnAgentUIAction(isFragment
289
- ? `AgentUIAction "${name}" does not support React.Fragment children.`
290
- : `AgentUIAction "${name}" needs a child with onClick.`);
285
+ ? `AgentUIAction "${name}" does not support React.Fragment children; the Tool is not registered.`
286
+ : `AgentUIAction "${name}" needs a child with onClick; the Tool is not registered.`);
291
287
  }
292
288
  return;
293
289
  }
@@ -365,4 +361,3 @@ export function AgentUIAction({ name, description, event = "click", children, })
365
361
  ref: mergedRef,
366
362
  });
367
363
  }
368
- //# sourceMappingURL=react.js.map
@@ -1,15 +1,16 @@
1
1
  import { assertAgentToolInputSchema } from "./shared/schema.js";
2
2
  export function registerAgentTool(definition, options) {
3
3
  assertAgentToolRegistration(definition, options);
4
- assertAgentToolInputSchema(definition.inputSchema, `Tool "${definition.name}".inputSchema`);
4
+ assertAgentToolInputSchema(definition.inputSchema, `Tool "${definition.name}" was not registered: inputSchema`);
5
5
  return Object.freeze({ definition, execute: options.execute });
6
6
  }
7
7
  export function assertAgentToolRegistration(definition, options) {
8
- if (!definition || typeof definition.name !== "string" || typeof options?.execute !== "function") {
8
+ if (!definition ||
9
+ typeof definition.name !== "string" ||
10
+ typeof options?.execute !== "function") {
9
11
  throw new TypeError("registerAgentTool requires a definition and execute function.");
10
12
  }
11
13
  if ("requiresConfirmation" in options) {
12
14
  throw new TypeError("Registered Agent tools do not support requiresConfirmation.");
13
15
  }
14
16
  }
15
- //# sourceMappingURL=registration.js.map