@particle-academy/agent-integrations 0.27.0 → 0.28.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -61,6 +61,8 @@ type PageSnapshot = {
61
61
  url: string;
62
62
  title: string;
63
63
  actions: PageAction[];
64
+ /** Monotonic host revision. Human input advances it and invalidates stale agent intent. */
65
+ revision?: number;
64
66
  };
65
67
  /** A write the host may want the human to confirm (trust-but-verify). */
66
68
  type NavigationConfirmRequest = {
@@ -81,6 +83,8 @@ type NavigationBridgeAdapter = {
81
83
  url: string;
82
84
  title: string;
83
85
  };
86
+ /** Current human-control revision. Omit to disable stale-intent protection. */
87
+ getRevision?: () => number;
84
88
  /** Snapshot of the page's actionable elements (stable handles + labels). */
85
89
  describe: () => PageSnapshot;
86
90
  /** Visible text / heading outline for grounding (optional). */
@@ -156,14 +160,22 @@ type CoBrowseUserEvent = {
156
160
  kind: "navigation";
157
161
  url: string;
158
162
  title?: string;
163
+ revision?: number;
159
164
  } | {
160
165
  kind: "scroll";
161
166
  y: number;
167
+ revision?: number;
162
168
  } | {
163
169
  kind: "form";
164
170
  handle: string;
165
171
  value?: unknown;
166
172
  masked?: boolean;
173
+ revision?: number;
174
+ } | {
175
+ kind: "click";
176
+ handle: string;
177
+ label?: string;
178
+ revision?: number;
167
179
  };
168
180
  type UseCoBrowseSessionOptions = {
169
181
  /**
package/dist/index.d.ts CHANGED
@@ -61,6 +61,8 @@ type PageSnapshot = {
61
61
  url: string;
62
62
  title: string;
63
63
  actions: PageAction[];
64
+ /** Monotonic host revision. Human input advances it and invalidates stale agent intent. */
65
+ revision?: number;
64
66
  };
65
67
  /** A write the host may want the human to confirm (trust-but-verify). */
66
68
  type NavigationConfirmRequest = {
@@ -81,6 +83,8 @@ type NavigationBridgeAdapter = {
81
83
  url: string;
82
84
  title: string;
83
85
  };
86
+ /** Current human-control revision. Omit to disable stale-intent protection. */
87
+ getRevision?: () => number;
84
88
  /** Snapshot of the page's actionable elements (stable handles + labels). */
85
89
  describe: () => PageSnapshot;
86
90
  /** Visible text / heading outline for grounding (optional). */
@@ -156,14 +160,22 @@ type CoBrowseUserEvent = {
156
160
  kind: "navigation";
157
161
  url: string;
158
162
  title?: string;
163
+ revision?: number;
159
164
  } | {
160
165
  kind: "scroll";
161
166
  y: number;
167
+ revision?: number;
162
168
  } | {
163
169
  kind: "form";
164
170
  handle: string;
165
171
  value?: unknown;
166
172
  masked?: boolean;
173
+ revision?: number;
174
+ } | {
175
+ kind: "click";
176
+ handle: string;
177
+ label?: string;
178
+ revision?: number;
167
179
  };
168
180
  type UseCoBrowseSessionOptions = {
169
181
  /**
package/dist/index.js CHANGED
@@ -9,11 +9,11 @@ export { useSheetsActivityHighlights, useSheetsAdapter } from './chunk-KHKSQEMC.
9
9
  import { ConnectorButtons } from './chunk-5HNTNIWY.js';
10
10
  export { CLAUDE_CONNECTORS_URL, CONNECTOR_GLYPHS, CONNECTOR_TARGETS, ClaudeMark, ConnectorButtons, CursorMark, DesktopMark, VscodeMark, WrenchMark, buildCursorDeeplink, buildManualConfig, buildManualConfigSnippet, buildVscodeDeeplink, connectorHref, encodeBase64Json, slugifyServerName } from './chunk-5HNTNIWY.js';
11
11
  export { DEFAULT_MCPB_ENTRY_POINT, MCPB_MANIFEST_VERSION, MCPB_MIN_NODE, buildMcpbManifest, buildMcpbProxyStub } from './chunk-GO2Y6H6U.js';
12
- import { ShareControls, AgentActivityHighlight, AgentCursor } from './chunk-HKQBG2HZ.js';
13
- export { AgentActivityHighlight, AgentCursor, AgentPanel, ShareControls, buildAgentPrompt } from './chunk-HKQBG2HZ.js';
12
+ import { ShareControls, AgentActivityHighlight, AgentCursor } from './chunk-5KLUYF4D.js';
13
+ export { AgentActivityHighlight, AgentCursor, AgentPanel, ShareControls, buildAgentPrompt } from './chunk-5KLUYF4D.js';
14
14
  import './chunk-IJ6JX5VC.js';
15
- import { createSessionDescriptor, attachSseRelay } from './chunk-FUI7KXE7.js';
16
- export { SseRelayTransport, attachSseRelay, buildShareConfig, buildShareUrl, createSessionDescriptor, describeSession, readSessionFromUrl } from './chunk-FUI7KXE7.js';
15
+ import { createSessionDescriptor, attachSseRelay } from './chunk-KMSRG5KH.js';
16
+ export { SseRelayTransport, attachSseRelay, buildShareConfig, buildShareUrl, createSessionDescriptor, describeSession, readSessionFromUrl } from './chunk-KMSRG5KH.js';
17
17
  export { registerChartsBridge } from './chunk-AROVENCE.js';
18
18
  export { registerSceneBridge } from './chunk-YGD2VTUM.js';
19
19
  export { registerScreensBridge } from './chunk-66WOHZZJ.js';
@@ -48,6 +48,17 @@ function registerNavigationBridge(host, options) {
48
48
  const agent = { ...DEFAULT_AGENT, ...options.agent ?? {} };
49
49
  const pendingMode = options.pendingMode ?? true;
50
50
  const disposers = [];
51
+ let groundedRevision = null;
52
+ const staleIntent = () => {
53
+ const current = adapter.getRevision?.();
54
+ if (current === void 0) return null;
55
+ if (groundedRevision === null || groundedRevision !== current) {
56
+ return errorResult(
57
+ `Human took control at page revision ${current}. This agent action was cancelled; call page_describe before acting again.`
58
+ );
59
+ }
60
+ return null;
61
+ };
51
62
  ensureUndoToolsRegistered(host, { defaultAgentId: agent.id });
52
63
  const target = (label, elementId) => ({
53
64
  kind: "navigation",
@@ -88,6 +99,11 @@ function registerNavigationBridge(host, options) {
88
99
  [],
89
100
  () => {
90
101
  const snap = adapter.describe();
102
+ const revision = adapter.getRevision?.();
103
+ if (revision !== void 0) {
104
+ snap.revision = revision;
105
+ groundedRevision = revision;
106
+ }
91
107
  const text = [
92
108
  `URL: ${snap.url}`,
93
109
  `Title: ${snap.title}`,
@@ -96,7 +112,7 @@ function registerNavigationBridge(host, options) {
96
112
  ].join("\n");
97
113
  return textResult(text, snap);
98
114
  },
99
- false
115
+ () => target("Inspect page")
100
116
  );
101
117
  reg(
102
118
  "page_read",
@@ -104,7 +120,25 @@ function registerNavigationBridge(host, options) {
104
120
  {},
105
121
  [],
106
122
  () => textResult(adapter.read ? adapter.read() : "(host did not provide page text)"),
107
- false
123
+ () => target("Read page")
124
+ );
125
+ reg(
126
+ "page_focus",
127
+ "Move the agent's visible focus to an interactive element by stable handle without activating it.",
128
+ { handle: { type: "string" } },
129
+ ["handle"],
130
+ (args) => {
131
+ const stale = staleIntent();
132
+ if (stale) return stale;
133
+ const handle = String(args.handle ?? "");
134
+ const action = adapter.describe().actions.find((candidate) => candidate.handle === handle);
135
+ if (!action) return errorResult(`No element for handle "${handle}"`);
136
+ return textResult(`Focused ${handle}`, {
137
+ handle,
138
+ rect: adapter.rectFor?.(handle) ?? void 0
139
+ });
140
+ },
141
+ (args) => target(`Focus ${String(args.handle ?? "")}`, String(args.handle ?? ""))
108
142
  );
109
143
  reg(
110
144
  "nav_visit",
@@ -112,6 +146,8 @@ function registerNavigationBridge(host, options) {
112
146
  { url: { type: "string", description: "Path like /packages or an absolute URL." } },
113
147
  ["url"],
114
148
  async (args) => {
149
+ const stale = staleIntent();
150
+ if (stale) return stale;
115
151
  const url = String(args.url ?? "");
116
152
  if (!url) return errorResult("url is required");
117
153
  const from = adapter.getLocation().url;
@@ -138,6 +174,8 @@ function registerNavigationBridge(host, options) {
138
174
  {},
139
175
  [],
140
176
  async () => {
177
+ const stale = staleIntent();
178
+ if (stale) return stale;
141
179
  if (!adapter.back) return errorResult("Host did not provide back navigation.");
142
180
  await adapter.back();
143
181
  return textResult("Went back");
@@ -150,6 +188,8 @@ function registerNavigationBridge(host, options) {
150
188
  {},
151
189
  [],
152
190
  async () => {
191
+ const stale = staleIntent();
192
+ if (stale) return stale;
153
193
  if (!adapter.forward) return errorResult("Host did not provide forward navigation.");
154
194
  await adapter.forward();
155
195
  return textResult("Went forward");
@@ -166,6 +206,8 @@ function registerNavigationBridge(host, options) {
166
206
  },
167
207
  [],
168
208
  (args) => {
209
+ const stale = staleIntent();
210
+ if (stale) return stale;
169
211
  const handle = typeof args.handle === "string" ? args.handle : void 0;
170
212
  adapter.scrollTo({
171
213
  handle,
@@ -182,6 +224,8 @@ function registerNavigationBridge(host, options) {
182
224
  { dy: { type: "number" } },
183
225
  ["dy"],
184
226
  (args) => {
227
+ const stale = staleIntent();
228
+ if (stale) return stale;
185
229
  adapter.scrollBy(Number(args.dy ?? 0));
186
230
  return textResult(`Scrolled by ${Number(args.dy ?? 0)}px`);
187
231
  },
@@ -196,6 +240,8 @@ function registerNavigationBridge(host, options) {
196
240
  },
197
241
  ["handle", "value"],
198
242
  (args) => {
243
+ const stale = staleIntent();
244
+ if (stale) return stale;
199
245
  const handle = String(args.handle ?? "");
200
246
  const res = adapter.setField(handle, args.value);
201
247
  if (!res.ok) return errorResult(res.error ?? `Could not set ${handle}`);
@@ -209,6 +255,8 @@ function registerNavigationBridge(host, options) {
209
255
  { handle: { type: "string" } },
210
256
  ["handle"],
211
257
  async (args) => {
258
+ const stale = staleIntent();
259
+ if (stale) return stale;
212
260
  const handle = String(args.handle ?? "");
213
261
  const action = adapter.describe().actions.find((a) => a.handle === handle);
214
262
  const rect = adapter.rectFor?.(handle) ?? void 0;
@@ -228,6 +276,8 @@ function registerNavigationBridge(host, options) {
228
276
  { handle: { type: "string" } },
229
277
  ["handle"],
230
278
  async (args) => {
279
+ const stale = staleIntent();
280
+ if (stale) return stale;
231
281
  const handle = String(args.handle ?? "");
232
282
  const rect = adapter.rectFor?.(handle) ?? void 0;
233
283
  if (pendingMode && adapter.confirm) {
@@ -284,11 +334,14 @@ function useCoBrowseSession(options) {
284
334
  if (!server || relayRef.current) return;
285
335
  const descriptor = createSessionDescriptor();
286
336
  const csrf = options.csrfToken?.() ?? "";
287
- await fetch(`${relayBaseUrl}/register`, {
337
+ const response = await fetch(`${relayBaseUrl}/register`, {
288
338
  method: "POST",
289
339
  headers: { "content-type": "application/json", "x-csrf-token": csrf },
290
340
  body: JSON.stringify({ session: descriptor.id, token: descriptor.token })
291
341
  });
342
+ if (!response.ok) {
343
+ throw new Error(`Relay registration failed (${response.status})`);
344
+ }
292
345
  const relay = attachSseRelay(server, { baseUrl: relayBaseUrl, sessionId: descriptor.id, token: descriptor.token });
293
346
  relay.onStateChange(setRelayState);
294
347
  relayRef.current = relay;
@@ -302,16 +355,15 @@ function useCoBrowseSession(options) {
302
355
  setSession(null);
303
356
  if (current) {
304
357
  const csrf = options.csrfToken?.() ?? "";
305
- void fetch(`${relayBaseUrl}/${current.id}/unregister`, {
358
+ void fetch(`${relayBaseUrl}/${current.id}/unregister?token=${encodeURIComponent(current.token)}`, {
306
359
  method: "POST",
307
- headers: { "content-type": "application/json", "x-csrf-token": csrf },
308
- body: JSON.stringify({ token: current.token })
360
+ headers: { "content-type": "application/json", "x-csrf-token": csrf }
309
361
  }).catch(() => {
310
362
  });
311
363
  }
312
364
  }, [relayBaseUrl, options, session]);
313
365
  const observeUser = useCallback((event) => {
314
- const label = event.kind === "navigation" ? `You navigated to ${event.url}` : event.kind === "scroll" ? "You scrolled" : `You edited ${event.handle}${event.masked ? " (hidden)" : ""}`;
366
+ const label = event.kind === "navigation" ? `You navigated to ${event.url}` : event.kind === "scroll" ? "You scrolled" : event.kind === "click" ? `You clicked ${event.label ?? event.handle}` : `You edited ${event.handle}${event.masked ? " (hidden)" : ""}`;
315
367
  emitActivity({
316
368
  agentId: USER.id,
317
369
  agentName: USER.name,
@@ -452,6 +504,11 @@ function CoBrowseCursorLayer({ active = true, zIndex = 2147483e3 }) {
452
504
  const [pulse, setPulse] = useState(null);
453
505
  useEffect(() => {
454
506
  if (!latest || (latest.source ?? "agent") === "user") return;
507
+ if (latest.action === "agent_disconnected") {
508
+ setCursor(null);
509
+ setPulse(null);
510
+ return;
511
+ }
455
512
  const color = latest.agentColor ?? "#a855f7";
456
513
  const name = latest.agentName ?? "Agent";
457
514
  const status = latest.target?.label ?? latest.action;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/bridges/navigation.ts","../src/sharing/use-co-browse-session.ts","../src/components/BridgedForm/BridgedForm.tsx","../src/components/ScreensActivityBridge/ScreensActivityBridge.tsx","../src/components/CoBrowsePresence/CoBrowsePresence.tsx","../src/components/CoBrowseCursorLayer/CoBrowseCursorLayer.tsx","../src/components/SimulateUsersButton/SimulateUsersButton.tsx"],"names":["DEFAULT_AGENT","useRef","useEffect","jsx","useState","jsxs"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2FA,IAAM,gBAAgB,EAAE,EAAA,EAAI,SAAS,IAAA,EAAM,OAAA,EAAS,OAAO,SAAA,EAAU;AAQ9D,SAAS,wBAAA,CACd,MACA,OAAA,EACQ;AACR,EAAA,MAAM,EAAE,SAAQ,GAAI,OAAA;AACpB,EAAA,MAAM,KAAA,GAAQ,EAAE,GAAG,aAAA,EAAe,GAAI,OAAA,CAAQ,KAAA,IAAS,EAAC,EAAG;AAC3D,EAAA,MAAM,WAAA,GAAc,QAAQ,WAAA,IAAe,IAAA;AAC3C,EAAA,MAAM,YAA+B,EAAC;AAEtC,EAAA,yBAAA,CAA0B,IAAA,EAAM,EAAE,cAAA,EAAgB,KAAA,CAAM,IAAI,CAAA;AAE5D,EAAA,MAAM,MAAA,GAAS,CAAC,KAAA,EAAe,SAAA,MAAqC;AAAA,IAClE,IAAA,EAAM,YAAA;AAAA,IACN,UAAU,OAAA,CAAQ,QAAA;AAAA,IAClB,SAAA;AAAA,IACA;AAAA,GACF,CAAA;AAEA,EAAA,MAAM,MAAM,CACV,IAAA,EACA,aACA,UAAA,EACA,QAAA,EACA,SACA,QAAA,KACG;AACH,IAAA,MAAM,OAAA,GAAU,OAAO,IAAA,KAAqB;AAC1C,MAAA,IAAI;AACF,QAAA,OAAO,MAAM,QAAQ,IAAI,CAAA;AAAA,MAC3B,SAAS,CAAA,EAAG;AACV,QAAA,OAAO,YAAY,CAAA,YAAa,KAAA,GAAQ,EAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,MAC/D;AAAA,IACF,CAAA;AACA,IAAA,MAAM,KAAA,GAAQ,QAAA,GACV,oBAAA,CAAqB,OAAA,EAAS;AAAA,MAC5B,QAAA,EAAU,IAAA;AAAA,MACV,KAAA,EAAO,EAAE,EAAA,EAAI,KAAA,CAAM,EAAA,EAAI,MAAM,KAAA,CAAM,IAAA,EAAM,KAAA,EAAO,KAAA,CAAM,KAAA,EAAM;AAAA,MAC5D,IAAA,EAAM,YAAA;AAAA,MACN,UAAU,OAAA,CAAQ,QAAA;AAAA,MAClB,eAAe,CAAC,EAAE,IAAA,EAAK,KAAM,SAAS,IAAI;AAAA,KAC3C,CAAA,GACD,OAAA;AACJ,IAAA,SAAA,CAAU,IAAA;AAAA,MACR,IAAA,CAAK,YAAA;AAAA,QACH;AAAA,UACE,IAAA;AAAA,UACA,WAAA;AAAA,UACA,aAAa,EAAE,IAAA,EAAM,UAAU,UAAA,EAA+B,QAAA,EAAU,sBAAsB,KAAA;AAAM,SACtG;AAAA,QACA;AAAA;AACF,KACF;AAAA,EACF,CAAA;AAIA,EAAA,GAAA;AAAA,IACE,eAAA;AAAA,IACA,qLAAA;AAAA,IACA,EAAC;AAAA,IACD,EAAC;AAAA,IACD,MAAM;AACJ,MAAA,MAAM,IAAA,GAAO,QAAQ,QAAA,EAAS;AAC9B,MAAA,MAAM,IAAA,GAAO;AAAA,QACX,CAAA,KAAA,EAAQ,KAAK,GAAG,CAAA,CAAA;AAAA,QAChB,CAAA,OAAA,EAAU,KAAK,KAAK,CAAA,CAAA;AAAA,QACpB,EAAA;AAAA,QACA,GAAG,KAAK,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAA,EAAI,EAAE,MAAM,CAAA,EAAA,EAAK,EAAE,IAAI,CAAA,EAAA,EAAK,EAAE,KAAK,CAAA,EAAG,EAAE,WAAA,GAAc,gBAAA,GAAmB,EAAE,CAAA,CAAE;AAAA,OAC1G,CAAE,KAAK,IAAI,CAAA;AACX,MAAA,OAAO,UAAA,CAAW,MAAM,IAAI,CAAA;AAAA,IAC9B,CAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,GAAA;AAAA,IACE,WAAA;AAAA,IACA,+DAAA;AAAA,IACA,EAAC;AAAA,IACD,EAAC;AAAA,IACD,MAAM,UAAA,CAAW,OAAA,CAAQ,OAAO,OAAA,CAAQ,IAAA,KAAS,kCAAkC,CAAA;AAAA,IACnF;AAAA,GACF;AAIA,EAAA,GAAA;AAAA,IACE,WAAA;AAAA,IACA,oFAAA;AAAA,IACA,EAAE,GAAA,EAAK,EAAE,MAAM,QAAA,EAAU,WAAA,EAAa,2CAA0C,EAAE;AAAA,IAClF,CAAC,KAAK,CAAA;AAAA,IACN,OAAO,IAAA,KAAS;AACd,MAAA,MAAM,GAAA,GAAM,MAAA,CAAO,IAAA,CAAK,GAAA,IAAO,EAAE,CAAA;AACjC,MAAA,IAAI,CAAC,GAAA,EAAK,OAAO,WAAA,CAAY,iBAAiB,CAAA;AAC9C,MAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,WAAA,EAAY,CAAE,GAAA;AACnC,MAAA,MAAM,OAAA,CAAQ,MAAM,GAAG,CAAA;AACvB,MAAA,aAAA,CAAc,MAAM,EAAA,EAAI;AAAA,QACtB,SAAA,EAAW,KAAK,GAAA,EAAI;AAAA,QACpB,QAAA,EAAU,YAAA;AAAA,QACV,MAAA,EAAQ,WAAA;AAAA,QACR,KAAA,EAAO,eAAe,GAAG,CAAA,CAAA;AAAA,QACzB,MAAM,MAAM;AACV,UAAA,OAAA,CAAQ,MAAM,IAAI,CAAA;AAAA,QACpB,CAAA;AAAA,QACA,MAAM,MAAM;AACV,UAAA,OAAA,CAAQ,MAAM,GAAG,CAAA;AAAA,QACnB;AAAA,OACD,CAAA;AACD,MAAA,OAAO,WAAW,CAAA,aAAA,EAAgB,GAAG,CAAA,CAAA,EAAI,EAAE,KAAK,CAAA;AAAA,IAClD,CAAA;AAAA,IACA,CAAC,SAAS,MAAA,CAAO,CAAA,gBAAA,EAAc,OAAO,IAAA,CAAK,GAAA,IAAO,EAAE,CAAC,CAAA,CAAE;AAAA,GACzD;AAEA,EAAA,GAAA;AAAA,IACE,UAAA;AAAA,IACA,+BAAA;AAAA,IACA,EAAC;AAAA,IACD,EAAC;AAAA,IACD,YAAY;AACV,MAAA,IAAI,CAAC,OAAA,CAAQ,IAAA,EAAM,OAAO,YAAY,uCAAuC,CAAA;AAC7E,MAAA,MAAM,QAAQ,IAAA,EAAK;AACnB,MAAA,OAAO,WAAW,WAAW,CAAA;AAAA,IAC/B,CAAA;AAAA,IACA,MAAM,OAAO,MAAM;AAAA,GACrB;AAEA,EAAA,GAAA;AAAA,IACE,aAAA;AAAA,IACA,8BAAA;AAAA,IACA,EAAC;AAAA,IACD,EAAC;AAAA,IACD,YAAY;AACV,MAAA,IAAI,CAAC,OAAA,CAAQ,OAAA,EAAS,OAAO,YAAY,0CAA0C,CAAA;AACnF,MAAA,MAAM,QAAQ,OAAA,EAAQ;AACtB,MAAA,OAAO,WAAW,cAAc,CAAA;AAAA,IAClC,CAAA;AAAA,IACA,MAAM,OAAO,SAAS;AAAA,GACxB;AAEA,EAAA,GAAA;AAAA,IACE,eAAA;AAAA,IACA,kFAAA;AAAA,IACA;AAAA,MACE,MAAA,EAAQ,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,gCAAA,EAAiC;AAAA,MACxE,CAAA,EAAG,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MACpB,CAAA,EAAG,EAAE,IAAA,EAAM,QAAA;AAAS,KACtB;AAAA,IACA,EAAC;AAAA,IACD,CAAC,IAAA,KAAS;AACR,MAAA,MAAM,SAAS,OAAO,IAAA,CAAK,MAAA,KAAW,QAAA,GAAW,KAAK,MAAA,GAAS,MAAA;AAC/D,MAAA,OAAA,CAAQ,QAAA,CAAS;AAAA,QACf,MAAA;AAAA,QACA,GAAG,OAAO,IAAA,CAAK,CAAA,KAAM,QAAA,GAAW,KAAK,CAAA,GAAI,MAAA;AAAA,QACzC,GAAG,OAAO,IAAA,CAAK,CAAA,KAAM,QAAA,GAAW,KAAK,CAAA,GAAI;AAAA,OAC1C,CAAA;AACD,MAAA,OAAO,UAAA,CAAW,UAAA,EAAY,MAAA,GAAS,EAAE,MAAA,EAAQ,IAAA,EAAM,OAAA,CAAQ,OAAA,GAAU,MAAM,CAAA,IAAK,MAAA,EAAU,GAAI,MAAS,CAAA;AAAA,IAC7G,CAAA;AAAA,IACA,MAAM,OAAO,QAAQ;AAAA,GACvB;AAEA,EAAA,GAAA;AAAA,IACE,eAAA;AAAA,IACA,sEAAA;AAAA,IACA,EAAE,EAAA,EAAI,EAAE,IAAA,EAAM,UAAS,EAAE;AAAA,IACzB,CAAC,IAAI,CAAA;AAAA,IACL,CAAC,IAAA,KAAS;AACR,MAAA,OAAA,CAAQ,QAAA,CAAS,MAAA,CAAO,IAAA,CAAK,EAAA,IAAM,CAAC,CAAC,CAAA;AACrC,MAAA,OAAO,WAAW,CAAA,YAAA,EAAe,MAAA,CAAO,KAAK,EAAA,IAAM,CAAC,CAAC,CAAA,EAAA,CAAI,CAAA;AAAA,IAC3D,CAAA;AAAA,IACA,MAAM,OAAO,QAAQ;AAAA,GACvB;AAIA,EAAA,GAAA;AAAA,IACE,gBAAA;AAAA,IACA,yGAAA;AAAA,IACA;AAAA,MACE,MAAA,EAAQ,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,MACzB,KAAA,EAAO,EAAE,WAAA,EAAa,uCAAA;AAAwC,KAChE;AAAA,IACA,CAAC,UAAU,OAAO,CAAA;AAAA,IAClB,CAAC,IAAA,KAAS;AACR,MAAA,MAAM,MAAA,GAAS,MAAA,CAAO,IAAA,CAAK,MAAA,IAAU,EAAE,CAAA;AACvC,MAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,QAAA,CAAS,MAAA,EAAQ,KAAK,KAAK,CAAA;AAC/C,MAAA,IAAI,CAAC,IAAI,EAAA,EAAI,OAAO,YAAY,GAAA,CAAI,KAAA,IAAS,CAAA,cAAA,EAAiB,MAAM,CAAA,CAAE,CAAA;AACtE,MAAA,OAAO,UAAA,CAAW,GAAG,MAAM,CAAA,QAAA,EAAM,KAAK,SAAA,CAAU,IAAA,CAAK,KAAK,CAAC,CAAA,CAAA,EAAI,EAAE,MAAA,EAAQ,KAAA,EAAO,KAAK,KAAA,EAAO,IAAA,EAAM,QAAQ,OAAA,GAAU,MAAM,CAAA,IAAK,MAAA,EAAW,CAAA;AAAA,IAC5I,CAAA;AAAA,IACA,CAAC,IAAA,KAAS,MAAA,CAAO,CAAA,IAAA,EAAO,OAAO,IAAA,CAAK,MAAA,IAAU,EAAE,CAAC,CAAA,CAAA,EAAI,MAAA,CAAO,IAAA,CAAK,MAAA,IAAU,EAAE,CAAC;AAAA,GAChF;AAEA,EAAA,GAAA;AAAA,IACE,YAAA;AAAA,IACA,yHAAA;AAAA,IACA,EAAE,MAAA,EAAQ,EAAE,IAAA,EAAM,UAAS,EAAE;AAAA,IAC7B,CAAC,QAAQ,CAAA;AAAA,IACT,OAAO,IAAA,KAAS;AACd,MAAA,MAAM,MAAA,GAAS,MAAA,CAAO,IAAA,CAAK,MAAA,IAAU,EAAE,CAAA;AACvC,MAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,QAAA,EAAS,CAAE,OAAA,CAAQ,KAAK,CAAC,CAAA,KAAM,CAAA,CAAE,MAAA,KAAW,MAAM,CAAA;AACzE,MAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,OAAA,GAAU,MAAM,CAAA,IAAK,MAAA;AAC1C,MAAA,IAAI,WAAA,IAAe,MAAA,EAAQ,WAAA,IAAe,OAAA,CAAQ,OAAA,EAAS;AACzD,QAAA,MAAM,EAAA,GAAK,MAAM,OAAA,CAAQ,OAAA,CAAQ,EAAE,MAAA,EAAQ,OAAA,EAAS,MAAA,EAAQ,KAAA,EAAO,MAAA,CAAO,KAAA,EAAO,CAAA;AACjF,QAAA,IAAI,CAAC,EAAA,EAAI,OAAO,WAAA,CAAY,kBAAkB,CAAA;AAAA,MAChD;AACA,MAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,KAAA,CAAM,MAAM,CAAA;AAChC,MAAA,IAAI,CAAC,IAAI,EAAA,EAAI,OAAO,YAAY,GAAA,CAAI,KAAA,IAAS,CAAA,gBAAA,EAAmB,MAAM,CAAA,CAAE,CAAA;AACxE,MAAA,OAAO,WAAW,CAAA,QAAA,EAAW,MAAM,IAAI,EAAE,MAAA,EAAQ,MAAM,CAAA;AAAA,IACzD,CAAA;AAAA,IACA,CAAC,IAAA,KAAS,MAAA,CAAO,CAAA,MAAA,EAAS,OAAO,IAAA,CAAK,MAAA,IAAU,EAAE,CAAC,CAAA,CAAA,EAAI,MAAA,CAAO,IAAA,CAAK,MAAA,IAAU,EAAE,CAAC;AAAA,GAClF;AAEA,EAAA,GAAA;AAAA,IACE,aAAA;AAAA,IACA,yFAAA;AAAA,IACA,EAAE,MAAA,EAAQ,EAAE,IAAA,EAAM,UAAS,EAAE;AAAA,IAC7B,CAAC,QAAQ,CAAA;AAAA,IACT,OAAO,IAAA,KAAS;AACd,MAAA,MAAM,MAAA,GAAS,MAAA,CAAO,IAAA,CAAK,MAAA,IAAU,EAAE,CAAA;AACvC,MAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,OAAA,GAAU,MAAM,CAAA,IAAK,MAAA;AAC1C,MAAA,IAAI,WAAA,IAAe,QAAQ,OAAA,EAAS;AAClC,QAAA,MAAM,EAAA,GAAK,MAAM,OAAA,CAAQ,OAAA,CAAQ,EAAE,QAAQ,QAAA,EAAU,MAAA,EAAQ,KAAA,EAAO,MAAA,EAAQ,CAAA;AAC5E,QAAA,IAAI,CAAC,EAAA,EAAI,OAAO,WAAA,CAAY,kBAAkB,CAAA;AAAA,MAChD;AACA,MAAA,MAAM,GAAA,GAAM,MAAM,OAAA,CAAQ,MAAA,CAAO,MAAM,CAAA;AACvC,MAAA,IAAI,CAAC,GAAA,CAAI,EAAA,SAAW,WAAA,CAAY,GAAA,CAAI,SAAS,eAAe,CAAA;AAC5D,MAAA,OAAO,WAAW,CAAA,UAAA,EAAa,MAAM,IAAI,EAAE,MAAA,EAAQ,MAAM,CAAA;AAAA,IAC3D,CAAA;AAAA,IACA,CAAC,IAAA,KAAS,MAAA,CAAO,CAAA,OAAA,EAAU,OAAO,IAAA,CAAK,MAAA,IAAU,EAAE,CAAC,CAAA,CAAA,EAAI,MAAA,CAAO,IAAA,CAAK,MAAA,IAAU,EAAE,CAAC;AAAA,GACnF;AAEA,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,YAAA;AAAA,IACJ,KAAA,EAAO,aAAA;AAAA,IACP,SAAS,MAAM;AACb,MAAA,KAAA,MAAW,CAAA,IAAK,WAAW,CAAA,EAAE;AAAA,IAC/B;AAAA,GACF;AACF;AC9RA,IAAMA,iBAAgB,EAAE,EAAA,EAAI,SAAS,IAAA,EAAM,OAAA,EAAS,OAAO,SAAA,EAAU;AACrE,IAAM,IAAA,GAAO,EAAE,EAAA,EAAI,OAAA,EAAS,MAAM,KAAA,EAAM;AASjC,SAAS,mBAAmB,OAAA,EAAqD;AACtF,EAAA,MAAM,EAAE,OAAA,EAAS,YAAA,EAAa,GAAI,OAAA;AAClC,EAAA,MAAM,KAAA,GAAQ,EAAE,GAAGA,cAAAA,EAAe,GAAI,OAAA,CAAQ,KAAA,IAAS,EAAC,EAAG;AAC3D,EAAA,MAAM,YAAA,GAAe,QAAQ,YAAA,IAAgB,cAAA;AAE7C,EAAA,MAAM,SAAA,GAAY,OAA8B,IAAI,CAAA;AACpD,EAAA,MAAM,QAAA,GAAW,OAAiC,IAAI,CAAA;AACtD,EAAA,MAAM,YAAA,GAAe,OAA4B,IAAI,CAAA;AACrD,EAAA,MAAM,aAAA,GAAgB,OAA4B,IAAI,CAAA;AAEtD,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAmC,IAAI,CAAA;AACrE,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAI,SAAqB,MAAM,CAAA;AAI/D,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,MAAA,GAAS,IAAI,cAAA,CAAe;AAAA,MAChC,MAAM,OAAA,CAAQ,IAAA,IAAQ,EAAE,IAAA,EAAM,iBAAA,EAAmB,SAAS,OAAA,EAAQ;AAAA,MAClE,YAAA,EACE,OAAA,CAAQ,IAAA,EAAM,YAAA,IACd,CAAA,gNAAA;AAAA,KACH,CAAA;AACD,IAAA,MAAM,MAAA,GAAS,yBAAyB,MAAA,EAAQ,EAAE,SAAS,KAAA,EAAO,WAAA,EAAa,OAAA,CAAQ,WAAA,EAAa,CAAA;AACpG,IAAA,YAAA,GAAe,MAAM,CAAA;AACrB,IAAA,MAAM,MAAA,GAAS,gBAAgB,MAAM,CAAA;AACrC,IAAA,YAAA,CAAa,OAAA,GAAU,MAAM,MAAA,CAAO,KAAA,EAAM;AAC1C,IAAA,aAAA,CAAc,UAAU,MAAA,CAAO,OAAA;AAC/B,IAAA,SAAA,CAAU,OAAA,GAAU,MAAA;AAEpB,IAAA,OAAO,MAAM;AACX,MAAA,QAAA,CAAS,SAAS,KAAA,EAAM;AACxB,MAAA,QAAA,CAAS,OAAA,GAAU,IAAA;AACnB,MAAA,aAAA,CAAc,OAAA,IAAU;AACxB,MAAA,YAAA,CAAa,OAAA,IAAU;AACvB,MAAA,SAAA,CAAU,OAAA,GAAU,IAAA;AAAA,IACtB,CAAA;AAAA,EAEF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,UAAA,GAAa,YAAY,YAAY;AACzC,IAAA,MAAM,SAAS,SAAA,CAAU,OAAA;AACzB,IAAA,IAAI,CAAC,MAAA,IAAU,QAAA,CAAS,OAAA,EAAS;AACjC,IAAA,MAAM,aAAa,uBAAA,EAAwB;AAC3C,IAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,SAAA,IAAY,IAAK,EAAA;AACtC,IAAA,MAAM,KAAA,CAAM,CAAA,EAAG,YAAY,CAAA,SAAA,CAAA,EAAa;AAAA,MACtC,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAoB,gBAAgB,IAAA,EAAK;AAAA,MACpE,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,EAAE,OAAA,EAAS,WAAW,EAAA,EAAI,KAAA,EAAO,UAAA,CAAW,KAAA,EAAO;AAAA,KACzE,CAAA;AACD,IAAA,MAAM,KAAA,GAAQ,cAAA,CAAe,MAAA,EAAQ,EAAE,OAAA,EAAS,YAAA,EAAc,SAAA,EAAW,UAAA,CAAW,EAAA,EAAI,KAAA,EAAO,UAAA,CAAW,KAAA,EAAO,CAAA;AACjH,IAAA,KAAA,CAAM,cAAc,aAAa,CAAA;AACjC,IAAA,QAAA,CAAS,OAAA,GAAU,KAAA;AACnB,IAAA,UAAA,CAAW,UAAU,CAAA;AAAA,EACvB,CAAA,EAAG,CAAC,YAAA,EAAc,OAAO,CAAC,CAAA;AAE1B,EAAA,MAAM,SAAA,GAAY,YAAY,MAAM;AAClC,IAAA,MAAM,OAAA,GAAU,OAAA;AAChB,IAAA,QAAA,CAAS,SAAS,KAAA,EAAM;AACxB,IAAA,QAAA,CAAS,OAAA,GAAU,IAAA;AACnB,IAAA,aAAA,CAAc,MAAM,CAAA;AACpB,IAAA,UAAA,CAAW,IAAI,CAAA;AACf,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,SAAA,IAAY,IAAK,EAAA;AACtC,MAAA,KAAK,MAAM,CAAA,EAAG,YAAY,CAAA,CAAA,EAAI,OAAA,CAAQ,EAAE,CAAA,WAAA,CAAA,EAAe;AAAA,QACrD,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAoB,gBAAgB,IAAA,EAAK;AAAA,QACpE,MAAM,IAAA,CAAK,SAAA,CAAU,EAAE,KAAA,EAAO,OAAA,CAAQ,OAAO;AAAA,OAC9C,CAAA,CAAE,KAAA,CAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AAAA,IACnB;AAAA,EACF,CAAA,EAAG,CAAC,YAAA,EAAc,OAAA,EAAS,OAAO,CAAC,CAAA;AAEnC,EAAA,MAAM,WAAA,GAAc,WAAA,CAAY,CAAC,KAAA,KAA6B;AAC5D,IAAA,MAAM,QACJ,KAAA,CAAM,IAAA,KAAS,eACX,CAAA,iBAAA,EAAoB,KAAA,CAAM,GAAG,CAAA,CAAA,GAC7B,KAAA,CAAM,SAAS,QAAA,GACb,cAAA,GACA,cAAc,KAAA,CAAM,MAAM,GAAG,KAAA,CAAM,MAAA,GAAS,cAAc,EAAE,CAAA,CAAA;AACpE,IAAA,YAAA,CAAa;AAAA,MACX,SAAS,IAAA,CAAK,EAAA;AAAA,MACd,WAAW,IAAA,CAAK,IAAA;AAAA,MAChB,MAAA,EAAQ,MAAA;AAAA,MACR,MAAA,EAAQ,EAAE,IAAA,EAAM,YAAA,EAAc,KAAA,EAAM;AAAA,MACpC,MAAA,EAAQ,CAAA,KAAA,EAAQ,KAAA,CAAM,IAAI,CAAA,CAAA;AAAA,MAC1B,SAAA,EAAW,KAAK,GAAA,EAAI;AAAA,MACpB,IAAA,EAAM;AAAA,KACP,CAAA;AAAA,EACH,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,OAAO,EAAE,QAAQ,SAAA,CAAU,OAAA,EAAS,SAAS,UAAA,EAAY,UAAA,EAAY,WAAW,WAAA,EAAY;AAC9F;AC5GO,SAAS,WAAA,CAAY;AAAA,EAC1B,EAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA;AACF,CAAA,EAAqB;AAEnB,EAAA,MAAM,SAAA,GAAYC,OAAO,MAAM,CAAA;AAC/B,EAAA,MAAM,WAAA,GAAcA,OAAO,QAAQ,CAAA;AACnC,EAAA,MAAM,SAAA,GAAYA,OAAO,MAAM,CAAA;AAC/B,EAAA,MAAM,SAAA,GAAYA,OAAO,QAAQ,CAAA;AACjC,EAAAC,UAAU,MAAM;AAAE,IAAA,SAAA,CAAU,OAAA,GAAU,MAAA;AAAA,EAAQ,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AACzD,EAAAA,UAAU,MAAM;AAAE,IAAA,WAAA,CAAY,OAAA,GAAU,QAAA;AAAA,EAAU,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AAC/D,EAAAA,UAAU,MAAM;AAAE,IAAA,SAAA,CAAU,OAAA,GAAU,MAAA;AAAA,EAAQ,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AACzD,EAAAA,UAAU,MAAM;AAAE,IAAA,SAAA,CAAU,OAAA,GAAU,QAAA;AAAA,EAAU,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AAE7D,EAAA,MAAM,YAAA,GAAe,CAAC,IAAA,KAAiB;AACrC,IAAA,IAAI,OAAO,aAAa,WAAA,EAAa;AACrC,IAAA,MAAM,KAAK,QAAA,CAAS,aAAA,CAAc,kBAAkB,EAAE,CAAA,UAAA,EAAa,IAAI,CAAA,EAAA,CAAI,CAAA;AAC3E,IAAA,EAAA,EAAI,KAAA,EAAM;AAAA,EACZ,CAAA;AAEA,EAAA,MAAM,OAAA,GAAU,QAA2B,OAAO;AAAA,IAChD,EAAA;AAAA,IACA,KAAA;AAAA,IACA,QAAA;AAAA,IACA,SAAA,EAAW,MAAM,SAAA,CAAU,OAAA;AAAA,IAC3B,QAAA,EAAU,CAAC,IAAA,KAAS,SAAA,CAAU,QAAQ,IAAI,CAAA;AAAA,IAC1C,SAAA,EAAW,OAAO,EAAE,GAAG,UAAU,OAAA,EAAQ,CAAA;AAAA,IACzC,QAAA,EAAU,CAAC,IAAA,EAAM,CAAA,KAAM,YAAY,OAAA,CAAQ,EAAE,GAAG,SAAA,CAAU,OAAA,EAAS,CAAC,IAAI,GAAG,GAAG,CAAA;AAAA,IAC9E,SAAA,EAAW,CAAC,IAAA,KAAS,WAAA,CAAY,OAAA,CAAQ,EAAE,GAAG,SAAA,CAAU,OAAA,EAAS,GAAG,IAAA,EAAM,CAAA;AAAA,IAC1E,KAAA,EAAO,YAAA;AAAA,IACP,QAAQ,YAAY;AAClB,MAAA,IAAI,CAAC,UAAU,OAAA,EAAS;AACtB,QAAA,OAAO,EAAE,IAAI,IAAA,EAAM,MAAA,EAAQ,EAAE,GAAG,SAAA,CAAU,SAAQ,EAAE;AAAA,MACtD;AACA,MAAA,OAAO,UAAU,OAAA,EAAQ;AAAA,IAC3B;AAAA;AAAA,GAEF,CAAA,EAAI,CAAC,EAAA,EAAI,KAAA,EAAO,QAAQ,CAAC,CAAA;AAEzB,EAAAA,UAAU,MAAM;AACd,IAAA,IAAI,CAAC,MAAA,EAAQ;AACb,IAAA,MAAM,SAAS,kBAAA,CAAmB,MAAA,EAAQ,EAAE,OAAA,EAAS,OAAO,CAAA;AAC5D,IAAA,OAAO,MAAM,OAAO,OAAA,EAAQ;AAAA,EAC9B,CAAA,EAAG,CAAC,MAAA,EAAQ,OAAA,EAAS,KAAK,CAAC,CAAA;AAE3B,EAAA,uBAAO,GAAA,CAAC,KAAA,EAAA,EAAI,cAAA,EAAc,EAAA,EAAK,QAAA,EAAS,CAAA;AAC1C;AC5DO,SAAS,qBAAA,CAAsB,EAAE,MAAA,EAAQ,MAAA,GAAS,MAAK,EAA+B;AAC3F,EAAAA,UAAU,MAAM;AACd,IAAA,MAAM,UAAA,uBAAiB,GAAA,EAA2C;AAClE,IAAA,MAAM,GAAA,GAAM,UAAA,CAAW,CAAC,KAAA,KAAU;AAChC,MAAA,MAAM,QAAA,GAAW,MAAM,MAAA,CAAO,QAAA;AAC9B,MAAA,IAAI,CAAC,QAAA,EAAU;AAEf,MAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,GAAA,CAAI,QAAQ,CAAA,EAAG;AACpC,MAAA,MAAM,QAAA,GAAW;AAAA,QACf,SAAS,KAAA,CAAM,OAAA;AAAA,QACf,WAAW,KAAA,CAAM,SAAA;AAAA,QACjB,YAAY,KAAA,CAAM,UAAA;AAAA,QAClB,QAAQ,KAAA,CAAM,MAAA;AAAA,QACd,WAAW,KAAA,CAAM,SAAA;AAAA,QACjB,SAAA,EAAW,MAAM,MAAA,CAAO,SAAA;AAAA,QACxB,KAAA,EAAO,MAAM,MAAA,CAAO;AAAA,OACtB;AACA,MAAA,MAAA,CAAO,YAAA,CAAa,QAAA,EAAU,EAAE,aAAA,EAAe,UAAU,CAAA;AACzD,MAAA,MAAM,IAAA,GAAO,UAAA,CAAW,GAAA,CAAI,QAAQ,CAAA;AACpC,MAAA,IAAI,IAAA,eAAmB,IAAI,CAAA;AAC3B,MAAA,UAAA,CAAW,GAAA;AAAA,QACT,QAAA;AAAA,QACA,WAAW,MAAM;AACf,UAAA,MAAA,CAAO,YAAA,CAAa,QAAA,EAAU,EAAE,aAAA,EAAe,MAAM,CAAA;AACrD,UAAA,UAAA,CAAW,OAAO,QAAQ,CAAA;AAAA,QAC5B,CAAA,EAAG,KAAA,CAAM,KAAA,IAAS,MAAM;AAAA,OAC1B;AAAA,IACF,CAAC,CAAA;AACD,IAAA,OAAO,MAAM;AACX,MAAA,GAAA,EAAI;AACJ,MAAA,KAAA,MAAW,CAAA,IAAK,UAAA,CAAW,MAAA,EAAO,eAAgB,CAAC,CAAA;AAAA,IACrD,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,MAAA,EAAQ,MAAM,CAAC,CAAA;AACnB,EAAA,OAAO,IAAA;AACT;AC9CO,SAAS,iBAAiB,EAAE,OAAA,EAAS,UAAA,EAAY,YAAA,EAAc,WAAU,EAA0B;AACxG,EAAA,MAAM,EAAE,QAAO,GAAI,gBAAA,CAAiB,QAAW,EAAE,QAAA,EAAU,IAAI,CAAA;AAC/D,EAAA,MAAM,eAAA,GAAkB,CAAC,GAAG,MAAM,CAAA,CAAE,OAAA,EAAQ,CAAE,IAAA,CAAK,CAAC,CAAA,KAAA,CAAO,CAAA,CAAE,MAAA,IAAU,aAAa,MAAM,CAAA;AAC1F,EAAA,MAAM,SAAA,GAAY,QAAQ,UAAA,KAAe,MAAA;AAEzC,EAAA,IAAI,CAAC,QAAQ,OAAA,EAAS;AACpB,IAAA,uBACEC,IAAC,KAAA,EAAA,EAAI,SAAA,EAAsB,2BAAwB,MAAA,EACjD,QAAA,kBAAAA,IAAC,QAAA,EAAA,EAAO,IAAA,EAAK,UAAS,OAAA,EAAS,MAAM,KAAK,OAAA,CAAQ,UAAA,IAAc,sBAAA,EAAoB,IAAA,EAAC,gCAErF,CAAA,EACF,CAAA;AAAA,EAEJ;AAEA,EAAA,4BACG,KAAA,EAAA,EAAI,SAAA,EAAsB,yBAAA,EAAyB,SAAA,GAAY,cAAc,SAAA,EAC5E,QAAA,EAAA;AAAA,oBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,sBAAkB,IAAA,EACrB,QAAA,EAAA;AAAA,sBAAAA,IAAC,MAAA,EAAA,EAAK,oBAAA,EAAkB,IAAA,EAAC,YAAA,EAAY,QAAQ,UAAA,EAAY,CAAA;AAAA,sBACzDA,GAAAA,CAAC,MAAA,EAAA,EAAK,uBAAA,EAAqB,IAAA,EACxB,sBAAY,kBAAA,GAAqB,CAAA,4BAAA,EAA0B,OAAA,CAAQ,UAAU,CAAA,CAAA,CAAA,EAChF,CAAA;AAAA,MACC,eAAA,oBAAmBA,GAAAA,CAAC,MAAA,EAAA,EAAK,qBAAA,EAAmB,MAAE,QAAA,EAAA,eAAA,CAAgB,MAAA,EAAQ,KAAA,IAAS,eAAA,CAAgB,MAAA,EAAO,CAAA;AAAA,sBACvGA,GAAAA,CAAC,QAAA,EAAA,EAAO,IAAA,EAAK,QAAA,EAAS,SAAS,OAAA,CAAQ,SAAA,EAAW,qBAAA,EAAmB,IAAA,EAAC,QAAA,EAAA,MAAA,EAEtE;AAAA,KAAA,EACF,CAAA;AAAA,oBAEAA,GAAAA;AAAA,MAAC,aAAA;AAAA,MAAA;AAAA,QACC,SAAS,OAAA,CAAQ,OAAA;AAAA,QACjB,OAAA,EAAS,MAAM,KAAK,OAAA,CAAQ,UAAA,EAAW;AAAA,QACvC,QAAQ,OAAA,CAAQ,SAAA;AAAA,QAChB,QAAQ,OAAA,CAAQ,UAAA;AAAA,QAChB;AAAA;AAAA,KACF;AAAA,IAEC,8BAAcA,GAAAA,CAAC,oBAAiB,UAAA,EAAW,oBAAA,EAAqB,QAAQ,UAAA,EAAY;AAAA,GAAA,EACvF,CAAA;AAEJ;AAEA,gBAAA,CAAiB,WAAA,GAAc,kBAAA;ACrCxB,SAAS,oBAAoB,EAAE,MAAA,GAAS,IAAA,EAAM,MAAA,GAAS,WAAW,EAA6B;AACpG,EAAA,MAAM,EAAE,QAAO,GAAI,gBAAA,CAAiB,QAAW,EAAE,QAAA,EAAU,IAAI,CAAA;AAC/D,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAIC,QAAAA;AAAA,IAC1B;AAAA,GACF;AACA,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIA,SAA4D,IAAI,CAAA;AAE1F,EAAAF,UAAU,MAAM;AACd,IAAA,IAAI,CAAC,MAAA,IAAA,CAAW,MAAA,CAAO,MAAA,IAAU,aAAa,MAAA,EAAQ;AACtD,IAAA,MAAM,KAAA,GAAQ,OAAO,UAAA,IAAc,SAAA;AACnC,IAAA,MAAM,IAAA,GAAO,OAAO,SAAA,IAAa,OAAA;AACjC,IAAA,MAAM,MAAA,GAAS,MAAA,CAAO,MAAA,EAAQ,KAAA,IAAS,MAAA,CAAO,MAAA;AAC9C,IAAA,MAAM,IAAA,GAAQ,OAAO,IAAA,EAAsC,IAAA;AAC3D,IAAA,IAAI,IAAA,EAAM;AAER,MAAA,SAAA,CAAU,EAAE,CAAA,EAAG,IAAA,CAAK,CAAA,GAAI,IAAA,CAAK,QAAQ,CAAA,EAAG,CAAA,EAAG,IAAA,CAAK,CAAA,GAAI,KAAK,MAAA,GAAS,CAAA,EAAG,IAAA,EAAM,KAAA,EAAO,QAAQ,CAAA;AAC1F,MAAA,QAAA,CAAS,EAAE,IAAA,EAAM,KAAA,EAAO,GAAA,EAAK,MAAA,CAAO,WAAW,CAAA;AAAA,IACjD,CAAA,MAAO;AAGL,MAAA,SAAA;AAAA,QAAU,CAAC,SACT,IAAA,GACI,EAAE,GAAG,IAAA,EAAM,MAAA,EAAQ,MAAM,KAAA,EAAM,GAC/B,EAAE,CAAA,EAAG,MAAA,CAAO,aAAa,CAAA,EAAG,CAAA,EAAG,OAAO,WAAA,GAAc,CAAA,EAAG,IAAA,EAAM,KAAA,EAAO,MAAA;AAAO,OACjF;AAAA,IACF;AAAA,EACF,CAAA,EAAG,CAAC,MAAA,EAAQ,SAAS,CAAC,CAAA;AAEtB,EAAA,IAAI,CAAC,MAAA,IAAU,CAAC,UAAU,OAAO,QAAA,KAAa,aAAa,OAAO,IAAA;AAElE,EAAA,OAAO,YAAA;AAAA,oBACLG,IAAAA,CAAC,KAAA,EAAA,EAAI,6BAAA,EAA4B,IAAG,KAAA,EAAO,EAAE,QAAA,EAAU,OAAA,EAAS,KAAA,EAAO,CAAA,EAAG,aAAA,EAAe,MAAA,EAAQ,QAAO,EACrG,QAAA,EAAA;AAAA,MAAA,KAAA,oBACCF,GAAAA;AAAA,QAAC,sBAAA;AAAA,QAAA;AAAA,UACC,CAAA,EAAG,MAAM,IAAA,CAAK,CAAA;AAAA,UACd,CAAA,EAAG,MAAM,IAAA,CAAK,CAAA;AAAA,UACd,KAAA,EAAO,MAAM,IAAA,CAAK,KAAA;AAAA,UAClB,MAAA,EAAQ,MAAM,IAAA,CAAK,MAAA;AAAA,UACnB,OAAO,KAAA,CAAM,KAAA;AAAA,UACb,UAAU,KAAA,CAAM;AAAA;AAAA,OAClB;AAAA,sBAEFA,GAAAA;AAAA,QAAC,WAAA;AAAA,QAAA;AAAA,UACC,GAAG,MAAA,CAAO,CAAA;AAAA,UACV,GAAG,MAAA,CAAO,CAAA;AAAA,UACV,MAAM,MAAA,CAAO,IAAA;AAAA,UACb,OAAO,MAAA,CAAO,KAAA;AAAA,UACd,QAAQ,MAAA,CAAO,MAAA;AAAA,UACf,KAAA,EAAO,EAAE,UAAA,EAAY,6EAAA;AAA8E;AAAA;AACrG,KAAA,EACF,CAAA;AAAA,IACA,QAAA,CAAS;AAAA,GACX;AACF;AAEA,mBAAA,CAAoB,WAAA,GAAc,qBAAA;AC5DlC,SAAS,YAAY,QAAA,EAAuC;AAC1D,EAAA,IAAI,UAAU,OAAO,QAAA;AACrB,EAAA,IAAI,OAAO,QAAA,KAAa,WAAA,EAAa,OAAO,MAAA;AAC5C,EAAA,OAAO,QAAA,CAAS,aAAA,CAA+B,yBAAyB,CAAA,EAAG,OAAA;AAC7E;AAWO,SAAS,mBAAA,CAAoB;AAAA,EAClC,QAAA,GAAW,wBAAA;AAAA,EACX,KAAA,GAAQ,EAAA;AAAA,EACR,KAAA;AAAA,EACA,SAAA;AAAA,EACA,WAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAA,EAA6B;AAC3B,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAIC,SAAS,KAAK,CAAA;AAEtC,EAAA,eAAe,OAAA,GAAU;AACvB,IAAA,IAAI,IAAA,EAAM;AACV,IAAA,OAAA,CAAQ,IAAI,CAAA;AACZ,IAAA,IAAI;AACF,MAAA,MAAM,KAAA,GAAQ,YAAY,SAAS,CAAA;AACnC,MAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,QAAA,EAAU;AAAA,QAChC,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA,EAAS;AAAA,UACP,cAAA,EAAgB,kBAAA;AAAA,UAChB,kBAAA,EAAoB,gBAAA;AAAA,UACpB,GAAI,KAAA,GAAQ,EAAE,cAAA,EAAgB,KAAA,KAAU;AAAC,SAC3C;AAAA,QACA,WAAA,EAAa,aAAA;AAAA,QACb,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,EAAE,OAAO;AAAA,OAC/B,CAAA;AACD,MAAA,IAAI,CAAC,IAAI,EAAA,EAAI,MAAM,IAAI,KAAA,CAAM,CAAA,yBAAA,EAA4B,GAAA,CAAI,MAAM,CAAA,CAAE,CAAA;AACrE,MAAA,WAAA,IAAc;AAAA,IAChB,SAAS,GAAA,EAAK;AACZ,MAAA,OAAA,GAAU,GAAG,CAAA;AAAA,IACf,CAAA,SAAE;AACA,MAAA,OAAA,CAAQ,KAAK,CAAA;AAAA,IACf;AAAA,EACF;AAEA,EAAA,uBACEC,IAAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAK,QAAA;AAAA,MACL,yBAAA,EAAwB,EAAA;AAAA,MACxB,SAAA,EAAW,CAAC,oBAAA,EAAsB,SAAA,IAAa,EAAE,EAAE,MAAA,CAAO,OAAO,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA;AAAA,MAC3E,OAAA,EAAS,OAAA;AAAA,MACT,QAAA,EAAU,IAAA;AAAA,MACV,KAAA,EAAO;AAAA,QACL,OAAA,EAAS,aAAA;AAAA,QACT,UAAA,EAAY,QAAA;AAAA,QACZ,GAAA,EAAK,CAAA;AAAA,QACL,OAAA,EAAS,UAAA;AAAA,QACT,YAAA,EAAc,CAAA;AAAA,QACd,MAAA,EAAQ,gCAAA;AAAA,QACR,UAAA,EAAY,OAAO,uBAAA,GAA0B,sBAAA;AAAA,QAC7C,KAAA,EAAO,SAAA;AAAA,QACP,IAAA,EAAM,SAAA;AAAA,QACN,QAAA,EAAU,EAAA;AAAA,QACV,UAAA,EAAY,GAAA;AAAA,QACZ,MAAA,EAAQ,OAAO,UAAA,GAAa,SAAA;AAAA,QAC5B,OAAA,EAAS,OAAO,GAAA,GAAM,CAAA;AAAA,QACtB,GAAG;AAAA,OACL;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAAF,IAAC,MAAA,EAAA,EAAK,aAAA,EAAW,IAAA,EAAE,QAAA,EAAA,IAAA,GAAO,WAAM,QAAA,EAAI,CAAA;AAAA,QACnC,KAAA,IAAS,YAAY,KAAK,CAAA,aAAA;AAAA;AAAA;AAAA,GAC7B;AAEJ","file":"index.js","sourcesContent":["import { textResult, errorResult } from \"../mcp/server\";\nimport type { ToolHost } from \"../mcp/tool-host\";\nimport type { JsonObject } from \"../mcp/types\";\nimport type { Bridge } from \"./types\";\nimport { wrapToolWithActivity } from \"../presence/wrap-tool-with-activity\";\nimport type { AgentTarget } from \"../presence/types\";\nimport { pushUndoEntry } from \"../undo/undo-stack\";\nimport { ensureUndoToolsRegistered } from \"../undo/undo-tools\";\n\n/**\n * One interactive element the agent can act on, addressed by a STABLE handle\n * (not a CSS selector) so the agent drives the page the Human+ way — never DOM\n * scraping. The host builds these in `describe()` (data-co-handle → name/id →\n * ARIA role + accessible name).\n */\nexport type PageAction = {\n /** Stable, opaque handle the agent passes back to act on this element. */\n handle: string;\n /** ARIA-ish role: \"link\" | \"button\" | \"textbox\" | \"checkbox\" | \"select\" | … */\n role: string;\n /** Accessible name / label. */\n label: string;\n /** Current value for inputs (omitted/masked for sensitive fields). */\n value?: unknown;\n /** True when activating this is destructive / submits (agent should stage). */\n destructive?: boolean;\n};\n\n/** The page as the agent sees it: where it is + what it can do. */\nexport type PageSnapshot = {\n url: string;\n title: string;\n actions: PageAction[];\n};\n\n/** A write the host may want the human to confirm (trust-but-verify). */\nexport type NavigationConfirmRequest = {\n action: \"submit\" | \"click\";\n handle: string;\n label: string;\n};\n\n/**\n * Host-provided adapter. In the sandbox this is backed by Inertia's `router` +\n * a DOM walker (see resources/js/agent/CoBrowseProvider.tsx). Every method\n * works on stable handles, never raw selectors.\n */\nexport type NavigationBridgeAdapter = {\n /** Optional fancy-screens screen id for presence targeting. */\n screenId?: string;\n /** Current location. */\n getLocation: () => { url: string; title: string };\n /** Snapshot of the page's actionable elements (stable handles + labels). */\n describe: () => PageSnapshot;\n /** Visible text / heading outline for grounding (optional). */\n read?: () => string;\n /** Navigate to a URL (host wires to router.visit). */\n visit: (url: string) => void | Promise<void>;\n back?: () => void | Promise<void>;\n forward?: () => void | Promise<void>;\n /** Scroll to coords or to a handle's element. */\n scrollTo: (opts: { x?: number; y?: number; handle?: string }) => void;\n scrollBy: (dy: number) => void;\n /** Set a field's value by handle (host dispatches input/change for React). */\n setField: (handle: string, value: unknown) => { ok: boolean; error?: string };\n /** Activate an element by handle. */\n click: (handle: string) => { ok: boolean; error?: string };\n /** Submit a form by handle. */\n submit: (handle: string) => Promise<{ ok: boolean; error?: string }> | { ok: boolean; error?: string };\n /**\n * Viewport rect of a handle's element, for agent-presence rendering (cursor +\n * highlight). Returned in tool `meta.rect` so `<CoBrowseCursorLayer>` can show\n * the agent acting on the page. Optional — omit and there's just no cursor.\n */\n rectFor?: (handle: string) => { x: number; y: number; width: number; height: number } | null;\n /**\n * Trust-but-verify hook. When `pendingMode` is on, `page_submit` and\n * destructive `page_click` route through this; the host shows a prompt and\n * resolves true (proceed) / false (declined).\n */\n confirm?: (req: NavigationConfirmRequest) => Promise<boolean>;\n};\n\nexport type NavigationBridgeOptions = {\n adapter: NavigationBridgeAdapter;\n /** Identity tagged into activity events (so the human sees who's driving). */\n agent?: { id: string; name?: string; color?: string };\n /** Route submit + destructive clicks through `adapter.confirm`. Default true. */\n pendingMode?: boolean;\n};\n\nconst DEFAULT_AGENT = { id: \"agent\", name: \"Agent\", color: \"#a855f7\" };\n\n/**\n * registerNavigationBridge — site-wide co-browsing. Lets a connected agent\n * navigate, scroll, and (with staged confirm) fill + click any page, addressed\n * by stable handles. Pairs with `useCoBrowseSession` (server + relay) and\n * `<CoBrowsePresence>` (the human's view of the agent). The 12th Fancy bridge.\n */\nexport function registerNavigationBridge(\n host: ToolHost,\n options: NavigationBridgeOptions,\n): Bridge {\n const { adapter } = options;\n const agent = { ...DEFAULT_AGENT, ...(options.agent ?? {}) };\n const pendingMode = options.pendingMode ?? true;\n const disposers: Array<() => void> = [];\n\n ensureUndoToolsRegistered(host, { defaultAgentId: agent.id });\n\n const target = (label: string, elementId?: string): AgentTarget => ({\n kind: \"navigation\",\n screenId: adapter.screenId,\n elementId,\n label,\n });\n\n const reg = (\n name: string,\n description: string,\n properties: Record<string, unknown>,\n required: string[],\n handler: (args: JsonObject) => Promise<any> | any,\n activity: false | ((args: JsonObject) => AgentTarget),\n ) => {\n const wrapped = async (args: JsonObject) => {\n try {\n return await handler(args);\n } catch (e) {\n return errorResult(e instanceof Error ? e.message : String(e));\n }\n };\n const final = activity\n ? wrapToolWithActivity(wrapped, {\n toolName: name,\n agent: { id: agent.id, name: agent.name, color: agent.color },\n kind: \"navigation\",\n screenId: adapter.screenId,\n resolveTarget: ({ args }) => activity(args),\n })\n : wrapped;\n disposers.push(\n host.registerTool(\n {\n name,\n description,\n inputSchema: { type: \"object\", properties: properties as any, required, additionalProperties: false },\n },\n final as any,\n ),\n );\n };\n\n // ───────────── Read ─────────────\n\n reg(\n \"page_describe\",\n \"Describe the current page: its URL, title, and the interactive elements you can act on (each with a stable `handle`, role, and label). Call this first, and again after navigating.\",\n {},\n [],\n () => {\n const snap = adapter.describe();\n const text = [\n `URL: ${snap.url}`,\n `Title: ${snap.title}`,\n \"\",\n ...snap.actions.map((a) => `[${a.handle}] ${a.role}: ${a.label}${a.destructive ? \" (destructive)\" : \"\"}`),\n ].join(\"\\n\");\n return textResult(text, snap);\n },\n false,\n );\n\n reg(\n \"page_read\",\n \"Read the page's visible text / heading outline for grounding.\",\n {},\n [],\n () => textResult(adapter.read ? adapter.read() : \"(host did not provide page text)\"),\n false,\n );\n\n // ───────────── Navigate / scroll ─────────────\n\n reg(\n \"nav_visit\",\n \"Navigate to a URL (same-site path or absolute). The human watches the page change.\",\n { url: { type: \"string\", description: \"Path like /packages or an absolute URL.\" } },\n [\"url\"],\n async (args) => {\n const url = String(args.url ?? \"\");\n if (!url) return errorResult(\"url is required\");\n const from = adapter.getLocation().url;\n await adapter.visit(url);\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: \"navigation\",\n action: \"nav_visit\",\n label: `Navigate to ${url}`,\n undo: () => {\n adapter.visit(from);\n },\n redo: () => {\n adapter.visit(url);\n },\n });\n return textResult(`Navigated to ${url}`, { url });\n },\n (args) => target(`Navigate → ${String(args.url ?? \"\")}`),\n );\n\n reg(\n \"nav_back\",\n \"Go back to the previous page.\",\n {},\n [],\n async () => {\n if (!adapter.back) return errorResult(\"Host did not provide back navigation.\");\n await adapter.back();\n return textResult(\"Went back\");\n },\n () => target(\"Back\"),\n );\n\n reg(\n \"nav_forward\",\n \"Go forward to the next page.\",\n {},\n [],\n async () => {\n if (!adapter.forward) return errorResult(\"Host did not provide forward navigation.\");\n await adapter.forward();\n return textResult(\"Went forward\");\n },\n () => target(\"Forward\"),\n );\n\n reg(\n \"nav_scroll_to\",\n \"Scroll the page to absolute coordinates, or to a specific element by its handle.\",\n {\n handle: { type: \"string\", description: \"Scroll this element into view.\" },\n x: { type: \"number\" },\n y: { type: \"number\" },\n },\n [],\n (args) => {\n const handle = typeof args.handle === \"string\" ? args.handle : undefined;\n adapter.scrollTo({\n handle,\n x: typeof args.x === \"number\" ? args.x : undefined,\n y: typeof args.y === \"number\" ? args.y : undefined,\n });\n return textResult(\"Scrolled\", handle ? { handle, rect: adapter.rectFor?.(handle) ?? undefined } : undefined);\n },\n () => target(\"Scroll\"),\n );\n\n reg(\n \"nav_scroll_by\",\n \"Scroll the page by a vertical delta in pixels (negative scrolls up).\",\n { dy: { type: \"number\" } },\n [\"dy\"],\n (args) => {\n adapter.scrollBy(Number(args.dy ?? 0));\n return textResult(`Scrolled by ${Number(args.dy ?? 0)}px`);\n },\n () => target(\"Scroll\"),\n );\n\n // ───────────── Co-drive (fill / click / submit) ─────────────\n\n reg(\n \"page_set_field\",\n \"Set a form field's value by handle. The host updates the controlled input and the human sees it change.\",\n {\n handle: { type: \"string\" },\n value: { description: \"Value to set; type matches the field.\" },\n },\n [\"handle\", \"value\"],\n (args) => {\n const handle = String(args.handle ?? \"\");\n const res = adapter.setField(handle, args.value);\n if (!res.ok) return errorResult(res.error ?? `Could not set ${handle}`);\n return textResult(`${handle} ← ${JSON.stringify(args.value)}`, { handle, value: args.value, rect: adapter.rectFor?.(handle) ?? undefined });\n },\n (args) => target(`Set ${String(args.handle ?? \"\")}`, String(args.handle ?? \"\")),\n );\n\n reg(\n \"page_click\",\n \"Activate an element by handle (link, button, checkbox…). Destructive elements are staged for the human to confirm.\",\n { handle: { type: \"string\" } },\n [\"handle\"],\n async (args) => {\n const handle = String(args.handle ?? \"\");\n const action = adapter.describe().actions.find((a) => a.handle === handle);\n const rect = adapter.rectFor?.(handle) ?? undefined; // capture before the click may navigate away\n if (pendingMode && action?.destructive && adapter.confirm) {\n const ok = await adapter.confirm({ action: \"click\", handle, label: action.label });\n if (!ok) return errorResult(\"Declined by user\");\n }\n const res = adapter.click(handle);\n if (!res.ok) return errorResult(res.error ?? `Could not click ${handle}`);\n return textResult(`Clicked ${handle}`, { handle, rect });\n },\n (args) => target(`Click ${String(args.handle ?? \"\")}`, String(args.handle ?? \"\")),\n );\n\n reg(\n \"page_submit\",\n \"Submit a form by handle. Always staged for the human to confirm when pendingMode is on.\",\n { handle: { type: \"string\" } },\n [\"handle\"],\n async (args) => {\n const handle = String(args.handle ?? \"\");\n const rect = adapter.rectFor?.(handle) ?? undefined; // capture before the submit navigates\n if (pendingMode && adapter.confirm) {\n const ok = await adapter.confirm({ action: \"submit\", handle, label: handle });\n if (!ok) return errorResult(\"Declined by user\");\n }\n const res = await adapter.submit(handle);\n if (!res.ok) return errorResult(res.error ?? \"Submit failed\");\n return textResult(`Submitted ${handle}`, { handle, rect });\n },\n (args) => target(`Submit ${String(args.handle ?? \"\")}`, String(args.handle ?? \"\")),\n );\n\n return {\n id: \"navigation\",\n title: \"Co-browsing\",\n dispose: () => {\n for (const d of disposers) d();\n },\n };\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { MicroMcpServer } from \"../mcp/server\";\nimport { attachInProcess } from \"../mcp/transports\";\nimport { attachSseRelay, type RelayState, type SseRelayTransport } from \"./sse-relay\";\nimport { createSessionDescriptor, type SessionDescriptor } from \"./token\";\nimport { emitActivity } from \"../presence/registry\";\nimport { registerNavigationBridge, type NavigationBridgeAdapter } from \"../bridges/navigation\";\n\n/** A thing the human did, surfaced so the connected agent stays aware. */\nexport type CoBrowseUserEvent =\n | { kind: \"navigation\"; url: string; title?: string }\n | { kind: \"scroll\"; y: number }\n | { kind: \"form\"; handle: string; value?: unknown; masked?: boolean };\n\nexport type UseCoBrowseSessionOptions = {\n /**\n * The navigation adapter (Inertia + DOM in the sandbox). MUST be stable —\n * its methods should read live state via refs, since the bridge captures it\n * once on mount. Memoize it.\n */\n adapter: NavigationBridgeAdapter;\n /** Identity for the agent's presence (cursor/log color + name). */\n agent?: { id: string; name?: string; color?: string };\n /** Relay base path. Default \"/agent-relay\" (the generic frame broker). */\n relayBaseUrl?: string;\n /** MCP server info advertised to the agent. */\n info?: { name: string; version: string; instructions?: string };\n /** Register extra bridges (forms/screens/…) on the same server. */\n extraBridges?: (server: MicroMcpServer) => void;\n /** CSRF token for the relay register/unregister POSTs. */\n csrfToken?: () => string | null | undefined;\n /** Stage submit + destructive clicks for human confirm. Default true. */\n pendingMode?: boolean;\n};\n\nexport type CoBrowseSession = {\n server: MicroMcpServer | null;\n session: SessionDescriptor | null;\n relayState: RelayState;\n startShare: () => Promise<void>;\n stopShare: () => void;\n /**\n * Report a human action so the connected agent is notified. Emits a\n * `source:\"user\"` activity event, which the SSE relay forwards to the agent\n * as a `notifications/agent_activity` frame.\n */\n observeUser: (event: CoBrowseUserEvent) => void;\n};\n\nconst DEFAULT_AGENT = { id: \"agent\", name: \"Agent\", color: \"#a855f7\" };\nconst USER = { id: \"human\", name: \"You\" };\n\n/**\n * Site-wide co-browsing session: one persistent in-page `MicroMcpServer` running\n * the navigation bridge, joinable by an external agent over the relay. Mount it\n * once at the app root; render `<CoBrowsePresence>` to show the agent + a Stop\n * control. The host wires `observeUser(...)` to navigation/scroll/form listeners\n * so the agent sees what the human does.\n */\nexport function useCoBrowseSession(options: UseCoBrowseSessionOptions): CoBrowseSession {\n const { adapter, extraBridges } = options;\n const agent = { ...DEFAULT_AGENT, ...(options.agent ?? {}) };\n const relayBaseUrl = options.relayBaseUrl ?? \"/agent-relay\";\n\n const serverRef = useRef<MicroMcpServer | null>(null);\n const relayRef = useRef<SseRelayTransport | null>(null);\n const detachInProc = useRef<(() => void) | null>(null);\n const disposeBridge = useRef<(() => void) | null>(null);\n\n const [session, setSession] = useState<SessionDescriptor | null>(null);\n const [relayState, setRelayState] = useState<RelayState>(\"idle\");\n\n // Build the server + bridges once. The adapter is captured here, so it must\n // be stable (its methods read live state).\n useEffect(() => {\n const server = new MicroMcpServer({\n info: options.info ?? { name: \"fancy-co-browse\", version: \"0.1.0\" },\n instructions:\n options.info?.instructions ??\n \"Co-browse with a watching human. Call page_describe first; navigate, scroll, and (with confirm) fill/click via stable handles. You receive notifications/agent_activity for the human's actions (source:\\\"user\\\").\",\n });\n const bridge = registerNavigationBridge(server, { adapter, agent, pendingMode: options.pendingMode });\n extraBridges?.(server);\n const inProc = attachInProcess(server);\n detachInProc.current = () => inProc.close();\n disposeBridge.current = bridge.dispose;\n serverRef.current = server;\n\n return () => {\n relayRef.current?.close();\n relayRef.current = null;\n disposeBridge.current?.();\n detachInProc.current?.();\n serverRef.current = null;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const startShare = useCallback(async () => {\n const server = serverRef.current;\n if (!server || relayRef.current) return;\n const descriptor = createSessionDescriptor();\n const csrf = options.csrfToken?.() ?? \"\";\n await fetch(`${relayBaseUrl}/register`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", \"x-csrf-token\": csrf },\n body: JSON.stringify({ session: descriptor.id, token: descriptor.token }),\n });\n const relay = attachSseRelay(server, { baseUrl: relayBaseUrl, sessionId: descriptor.id, token: descriptor.token });\n relay.onStateChange(setRelayState);\n relayRef.current = relay;\n setSession(descriptor);\n }, [relayBaseUrl, options]);\n\n const stopShare = useCallback(() => {\n const current = session;\n relayRef.current?.close();\n relayRef.current = null;\n setRelayState(\"idle\");\n setSession(null);\n if (current) {\n const csrf = options.csrfToken?.() ?? \"\";\n void fetch(`${relayBaseUrl}/${current.id}/unregister`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", \"x-csrf-token\": csrf },\n body: JSON.stringify({ token: current.token }),\n }).catch(() => {});\n }\n }, [relayBaseUrl, options, session]);\n\n const observeUser = useCallback((event: CoBrowseUserEvent) => {\n const label =\n event.kind === \"navigation\"\n ? `You navigated to ${event.url}`\n : event.kind === \"scroll\"\n ? \"You scrolled\"\n : `You edited ${event.handle}${event.masked ? \" (hidden)\" : \"\"}`;\n emitActivity({\n agentId: USER.id,\n agentName: USER.name,\n source: \"user\",\n target: { kind: \"navigation\", label },\n action: `user_${event.kind}`,\n timestamp: Date.now(),\n meta: event as Record<string, unknown>,\n });\n }, []);\n\n return { server: serverRef.current, session, relayState, startShare, stopShare, observeUser };\n}\n","import { type ReactNode, useEffect, useMemo, useRef } from \"react\";\nimport type { MicroMcpServer } from \"../../mcp/server\";\nimport { registerFormBridge, type FormBridgeAdapter, type FormFieldDescriptor } from \"../../bridges/forms\";\n\nexport type BridgedFormProps = {\n /** Stable id for this form. Used by agents in `form_*` tool calls. */\n id: string;\n /** Human title (also surfaced as the bridge title). */\n title?: string;\n /** Optional fancy-screens screen id this form lives in. */\n screenId?: string;\n /** Field descriptors — drives the agent-facing schema. */\n fields: FormFieldDescriptor[];\n /** Controlled values. */\n values: Record<string, unknown>;\n /** Setter — hosts pass their setState. */\n onChange: (next: Record<string, unknown>) => void;\n /** Optional submit handler. */\n onSubmit?: () => Promise<{ ok: boolean; values?: Record<string, unknown>; error?: string }>;\n /** The MicroMcpServer the bridge registers against. Pass null/undefined\n * to render without a bridge (useful for stories / non-shared use). */\n server?: MicroMcpServer | null;\n /** Identity used in activity events. */\n agent?: { id: string; name?: string; color?: string };\n children: ReactNode;\n};\n\n/**\n * BridgedForm — wraps a react-fancy form (or any controlled inputs)\n * with a `registerFormBridge` lifecycle. Children render the actual form\n * using `values` + `onChange`; this component only manages the bridge.\n *\n * Hosts use it like:\n *\n * <BridgedForm id=\"signup\" fields={...} values={values} onChange={setValues} server={server}>\n * <Field><Input value={values.email} onValueChange={(v) => onChange({ ...values, email: v })} /></Field>\n * ...\n * </BridgedForm>\n *\n * Agents can then call form_describe, form_set_value, form_submit, etc.\n */\nexport function BridgedForm({\n id,\n title,\n screenId,\n fields,\n values,\n onChange,\n onSubmit,\n server,\n agent,\n children,\n}: BridgedFormProps) {\n // Refs so the adapter sees fresh values without re-installing the bridge.\n const valuesRef = useRef(values);\n const onChangeRef = useRef(onChange);\n const fieldsRef = useRef(fields);\n const submitRef = useRef(onSubmit);\n useEffect(() => { valuesRef.current = values; }, [values]);\n useEffect(() => { onChangeRef.current = onChange; }, [onChange]);\n useEffect(() => { fieldsRef.current = fields; }, [fields]);\n useEffect(() => { submitRef.current = onSubmit; }, [onSubmit]);\n\n const focusElement = (name: string) => {\n if (typeof document === \"undefined\") return;\n const el = document.querySelector(`[data-form-id=\"${id}\"] [name=\"${name}\"]`) as HTMLElement | null;\n el?.focus();\n };\n\n const adapter = useMemo<FormBridgeAdapter>(() => ({\n id,\n title,\n screenId,\n getFields: () => fieldsRef.current,\n getValue: (name) => valuesRef.current[name],\n getValues: () => ({ ...valuesRef.current }),\n setValue: (name, v) => onChangeRef.current({ ...valuesRef.current, [name]: v }),\n setValues: (next) => onChangeRef.current({ ...valuesRef.current, ...next }),\n focus: focusElement,\n submit: async () => {\n if (!submitRef.current) {\n return { ok: true, values: { ...valuesRef.current } };\n }\n return submitRef.current();\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }), [id, title, screenId]);\n\n useEffect(() => {\n if (!server) return;\n const bridge = registerFormBridge(server, { adapter, agent });\n return () => bridge.dispose();\n }, [server, adapter, agent]);\n\n return <div data-form-id={id}>{children}</div>;\n}\n","import { useEffect } from \"react\";\nimport { onActivity } from \"../../presence/registry\";\n\n/**\n * Loose shape of the fancy-screens system context — kept here so this\n * component doesn't hard-import `@particle-academy/fancy-screens`.\n */\ntype ScreenSystemLike = {\n registry: Map<string, { id: string; agentActivity?: unknown }>;\n updateScreen: (id: string, patch: { agentActivity?: unknown }) => void;\n};\n\nexport type ScreensActivityBridgeProps = {\n /** The value returned by `useScreenSystem()` from fancy-screens. */\n system: ScreenSystemLike;\n /** ms to wait after the last activity before clearing the screen's badge. Default 1500. */\n fadeMs?: number;\n};\n\n/**\n * ScreensActivityBridge — subscribe to the in-process activity registry\n * and patch each event into the matching screen's `agentActivity` field.\n * Fade-out clears the badge after `fadeMs`.\n *\n * Use it once near the root of your app, ABOVE every <Screen>:\n *\n * const system = useScreenSystem();\n * <>\n * <ScreensActivityBridge system={system} />\n * <Screen id=\"dashboard\">…</Screen>\n * <Screen id=\"form\">…</Screen>\n * </>\n *\n * Renders nothing; pure side-effect component.\n */\nexport function ScreensActivityBridge({ system, fadeMs = 1500 }: ScreensActivityBridgeProps) {\n useEffect(() => {\n const fadeTimers = new Map<string, ReturnType<typeof setTimeout>>();\n const off = onActivity((event) => {\n const screenId = event.target.screenId;\n if (!screenId) return;\n // Only patch screens that are currently registered.\n if (!system.registry.has(screenId)) return;\n const activity = {\n agentId: event.agentId,\n agentName: event.agentName,\n agentColor: event.agentColor,\n action: event.action,\n timestamp: event.timestamp,\n elementId: event.target.elementId,\n label: event.target.label,\n };\n system.updateScreen(screenId, { agentActivity: activity });\n const prev = fadeTimers.get(screenId);\n if (prev) clearTimeout(prev);\n fadeTimers.set(\n screenId,\n setTimeout(() => {\n system.updateScreen(screenId, { agentActivity: null });\n fadeTimers.delete(screenId);\n }, event.ttlMs ?? fadeMs),\n );\n });\n return () => {\n off();\n for (const t of fadeTimers.values()) clearTimeout(t);\n };\n }, [system, fadeMs]);\n return null;\n}\n","import { useAgentActivity } from \"../../presence/use-agent-activity\";\nimport { ShareControls } from \"../ShareControls/ShareControls\";\nimport { ConnectorButtons } from \"../../connectors/ConnectorButtons\";\nimport type { CoBrowseSession } from \"../../sharing/use-co-browse-session\";\n\nexport type CoBrowsePresenceProps = {\n /** The session from `useCoBrowseSession`. */\n session: CoBrowseSession;\n /** Public MCP/connect URL shown to the user (for ConnectorButtons), optional. */\n connectUrl?: string;\n /** Base URL used to build the shareable session link. */\n shareBaseUrl?: string;\n className?: string;\n};\n\n/**\n * The human's view of a site-wide co-browsing session: a \"Let an agent drive\"\n * starter, the share/connect surface once started, a live \"agent is driving\"\n * status with the latest action, and a Stop / take-back-control button.\n *\n * Staged-action confirms are rendered by the HOST (via the navigation adapter's\n * `confirm`), so this component stays presentation-only.\n */\nexport function CoBrowsePresence({ session, connectUrl, shareBaseUrl, className }: CoBrowsePresenceProps) {\n const { events } = useAgentActivity(undefined, { capacity: 40 });\n const lastAgentAction = [...events].reverse().find((e) => (e.source ?? \"agent\") !== \"user\");\n const connected = session.relayState === \"open\";\n\n if (!session.session) {\n return (\n <div className={className} data-co-browse-presence=\"idle\">\n <button type=\"button\" onClick={() => void session.startShare()} data-co-browse-start>\n Let an agent drive\n </button>\n </div>\n );\n }\n\n return (\n <div className={className} data-co-browse-presence={connected ? \"connected\" : \"waiting\"}>\n <div data-co-browse-bar>\n <span data-co-browse-dot data-state={session.relayState} />\n <span data-co-browse-status>\n {connected ? \"Agent is driving\" : `Waiting for an agent… (${session.relayState})`}\n </span>\n {lastAgentAction && <span data-co-browse-last>{lastAgentAction.target?.label ?? lastAgentAction.action}</span>}\n <button type=\"button\" onClick={session.stopShare} data-co-browse-stop>\n Stop\n </button>\n </div>\n\n <ShareControls\n session={session.session}\n onStart={() => void session.startShare()}\n onStop={session.stopShare}\n status={session.relayState}\n shareBaseUrl={shareBaseUrl}\n />\n\n {connectUrl && <ConnectorButtons serverName=\"Fancy UI co-browse\" mcpUrl={connectUrl} />}\n </div>\n );\n}\n\nCoBrowsePresence.displayName = \"CoBrowsePresence\";\n","import { useEffect, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useAgentActivity } from \"../../presence/use-agent-activity\";\nimport { AgentCursor } from \"../AgentCursor/AgentCursor\";\nimport { AgentActivityHighlight } from \"../AgentActivityHighlight/AgentActivityHighlight\";\n\ntype Rect = { x: number; y: number; width: number; height: number };\n\nexport type CoBrowseCursorLayerProps = {\n /** Render the overlay only while a session is live. Default true. */\n active?: boolean;\n /** Stacking order of the overlay. Default just under the max. */\n zIndex?: number;\n};\n\n/**\n * Page-wide agent presence for co-browsing — the missing \"all actors present\"\n * half of Human+ UX. A fixed, click-through overlay (portaled to <body>) that\n * shows the connected agent as a live cursor + pings/highlights the element it\n * just acted on, gliding between targets. Same visual language as the whiteboard\n * demo's agent cursor, but mapped from the navigation bridge's STABLE HANDLES\n * (the agent has no real mouse) — each tool reports the acted element's viewport\n * rect in `meta.rect` (see `NavigationBridgeAdapter.rectFor`).\n *\n * Mount it once near the app root (e.g. in your CoBrowseProvider), gated on an\n * active session. SSR-safe: renders null on the server / until the first action.\n */\nexport function CoBrowseCursorLayer({ active = true, zIndex = 2147483000 }: CoBrowseCursorLayerProps) {\n const { latest } = useAgentActivity(undefined, { capacity: 12 });\n const [cursor, setCursor] = useState<{ x: number; y: number; name: string; color: string; status?: string } | null>(\n null,\n );\n const [pulse, setPulse] = useState<{ rect: Rect; color: string; key: number } | null>(null);\n\n useEffect(() => {\n if (!latest || (latest.source ?? \"agent\") === \"user\") return;\n const color = latest.agentColor ?? \"#a855f7\";\n const name = latest.agentName ?? \"Agent\";\n const status = latest.target?.label ?? latest.action;\n const rect = (latest.meta as { rect?: Rect } | undefined)?.rect;\n if (rect) {\n // Acted on a concrete element — glide the cursor to it + pulse a highlight.\n setCursor({ x: rect.x + rect.width / 2, y: rect.y + rect.height / 2, name, color, status });\n setPulse({ rect, color, key: latest.timestamp });\n } else {\n // nav / scroll — no element. Keep (or first-show, at viewport center) the\n // cursor so the agent stays visibly present; just refresh its caption.\n setCursor((prev) =>\n prev\n ? { ...prev, status, name, color }\n : { x: window.innerWidth / 2, y: window.innerHeight / 2, name, color, status },\n );\n }\n }, [latest?.timestamp]);\n\n if (!active || !cursor || typeof document === \"undefined\") return null;\n\n return createPortal(\n <div data-co-browse-cursor-layer=\"\" style={{ position: \"fixed\", inset: 0, pointerEvents: \"none\", zIndex }}>\n {pulse && (\n <AgentActivityHighlight\n x={pulse.rect.x}\n y={pulse.rect.y}\n width={pulse.rect.width}\n height={pulse.rect.height}\n color={pulse.color}\n pulseKey={pulse.key}\n />\n )}\n <AgentCursor\n x={cursor.x}\n y={cursor.y}\n name={cursor.name}\n color={cursor.color}\n status={cursor.status}\n style={{ transition: \"left .35s cubic-bezier(.22,.61,.36,1), top .35s cubic-bezier(.22,.61,.36,1)\" }}\n />\n </div>,\n document.body,\n );\n}\n\nCoBrowseCursorLayer.displayName = \"CoBrowseCursorLayer\";\n","import { type CSSProperties, useState } from \"react\";\n\nexport type SimulateUsersButtonProps = {\n /** Endpoint that injects the fake active users. Default `/active-users/simulate`. */\n endpoint?: string;\n /** How many fake users to simulate (sent as `count`). Default `10`. */\n count?: number;\n /** Button label. Default `Simulate {count} active users`. */\n label?: string;\n /**\n * CSRF token sent as `X-CSRF-TOKEN`. If omitted, falls back to a\n * `<meta name=\"csrf-token\">` on the page (the Laravel default).\n */\n csrfToken?: string;\n /** Called after a successful trigger. */\n onTriggered?: () => void;\n /** Called if the request fails. */\n onError?: (error: unknown) => void;\n className?: string;\n style?: CSSProperties;\n};\n\nfunction resolveCsrf(explicit?: string): string | undefined {\n if (explicit) return explicit;\n if (typeof document === \"undefined\") return undefined;\n return document.querySelector<HTMLMetaElement>('meta[name=\"csrf-token\"]')?.content;\n}\n\n/**\n * A button that asks the host to inject N **fake** active users (injected\n * dummies, not real accounts) so the live ActiveUser stream / presence overlay\n * has something to animate in a demo. POSTs `{ count }` to `endpoint`.\n *\n * Self-contained (inline styles, no react-fancy dependency) so it drops into any\n * host. The fakes + their staggered activity are produced server-side; this\n * button only triggers them.\n */\nexport function SimulateUsersButton({\n endpoint = \"/active-users/simulate\",\n count = 10,\n label,\n csrfToken,\n onTriggered,\n onError,\n className,\n style,\n}: SimulateUsersButtonProps) {\n const [busy, setBusy] = useState(false);\n\n async function trigger() {\n if (busy) return;\n setBusy(true);\n try {\n const token = resolveCsrf(csrfToken);\n const res = await fetch(endpoint, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Requested-With\": \"XMLHttpRequest\",\n ...(token ? { \"X-CSRF-TOKEN\": token } : {}),\n },\n credentials: \"same-origin\",\n body: JSON.stringify({ count }),\n });\n if (!res.ok) throw new Error(`Simulate request failed: ${res.status}`);\n onTriggered?.();\n } catch (err) {\n onError?.(err);\n } finally {\n setBusy(false);\n }\n }\n\n return (\n <button\n type=\"button\"\n data-fai-simulate-users=\"\"\n className={[\"fai-simulate-users\", className ?? \"\"].filter(Boolean).join(\" \")}\n onClick={trigger}\n disabled={busy}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 8,\n padding: \"8px 14px\",\n borderRadius: 8,\n border: \"1px solid rgba(139,92,246,0.4)\",\n background: busy ? \"rgba(139,92,246,0.15)\" : \"rgba(139,92,246,0.1)\",\n color: \"#7c3aed\",\n font: \"inherit\",\n fontSize: 13,\n fontWeight: 500,\n cursor: busy ? \"progress\" : \"pointer\",\n opacity: busy ? 0.7 : 1,\n ...style,\n }}\n >\n <span aria-hidden>{busy ? \"⏳\" : \"✨\"}</span>\n {label ?? `Simulate ${count} active users`}\n </button>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/bridges/navigation.ts","../src/sharing/use-co-browse-session.ts","../src/components/BridgedForm/BridgedForm.tsx","../src/components/ScreensActivityBridge/ScreensActivityBridge.tsx","../src/components/CoBrowsePresence/CoBrowsePresence.tsx","../src/components/CoBrowseCursorLayer/CoBrowseCursorLayer.tsx","../src/components/SimulateUsersButton/SimulateUsersButton.tsx"],"names":["DEFAULT_AGENT","useRef","useEffect","jsx","useState","jsxs"],"mappings":"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","file":"index.js","sourcesContent":["import { textResult, errorResult } from \"../mcp/server\";\nimport type { ToolHost } from \"../mcp/tool-host\";\nimport type { JsonObject } from \"../mcp/types\";\nimport type { Bridge } from \"./types\";\nimport { wrapToolWithActivity } from \"../presence/wrap-tool-with-activity\";\nimport type { AgentTarget } from \"../presence/types\";\nimport { pushUndoEntry } from \"../undo/undo-stack\";\nimport { ensureUndoToolsRegistered } from \"../undo/undo-tools\";\n\n/**\n * One interactive element the agent can act on, addressed by a STABLE handle\n * (not a CSS selector) so the agent drives the page the Human+ way — never DOM\n * scraping. The host builds these in `describe()` (data-co-handle → name/id →\n * ARIA role + accessible name).\n */\nexport type PageAction = {\n /** Stable, opaque handle the agent passes back to act on this element. */\n handle: string;\n /** ARIA-ish role: \"link\" | \"button\" | \"textbox\" | \"checkbox\" | \"select\" | … */\n role: string;\n /** Accessible name / label. */\n label: string;\n /** Current value for inputs (omitted/masked for sensitive fields). */\n value?: unknown;\n /** True when activating this is destructive / submits (agent should stage). */\n destructive?: boolean;\n};\n\n/** The page as the agent sees it: where it is + what it can do. */\nexport type PageSnapshot = {\n url: string;\n title: string;\n actions: PageAction[];\n /** Monotonic host revision. Human input advances it and invalidates stale agent intent. */\n revision?: number;\n};\n\n/** A write the host may want the human to confirm (trust-but-verify). */\nexport type NavigationConfirmRequest = {\n action: \"submit\" | \"click\";\n handle: string;\n label: string;\n};\n\n/**\n * Host-provided adapter. In the sandbox this is backed by Inertia's `router` +\n * a DOM walker (see resources/js/agent/CoBrowseProvider.tsx). Every method\n * works on stable handles, never raw selectors.\n */\nexport type NavigationBridgeAdapter = {\n /** Optional fancy-screens screen id for presence targeting. */\n screenId?: string;\n /** Current location. */\n getLocation: () => { url: string; title: string };\n /** Current human-control revision. Omit to disable stale-intent protection. */\n getRevision?: () => number;\n /** Snapshot of the page's actionable elements (stable handles + labels). */\n describe: () => PageSnapshot;\n /** Visible text / heading outline for grounding (optional). */\n read?: () => string;\n /** Navigate to a URL (host wires to router.visit). */\n visit: (url: string) => void | Promise<void>;\n back?: () => void | Promise<void>;\n forward?: () => void | Promise<void>;\n /** Scroll to coords or to a handle's element. */\n scrollTo: (opts: { x?: number; y?: number; handle?: string }) => void;\n scrollBy: (dy: number) => void;\n /** Set a field's value by handle (host dispatches input/change for React). */\n setField: (handle: string, value: unknown) => { ok: boolean; error?: string };\n /** Activate an element by handle. */\n click: (handle: string) => { ok: boolean; error?: string };\n /** Submit a form by handle. */\n submit: (handle: string) => Promise<{ ok: boolean; error?: string }> | { ok: boolean; error?: string };\n /**\n * Viewport rect of a handle's element, for agent-presence rendering (cursor +\n * highlight). Returned in tool `meta.rect` so `<CoBrowseCursorLayer>` can show\n * the agent acting on the page. Optional — omit and there's just no cursor.\n */\n rectFor?: (handle: string) => { x: number; y: number; width: number; height: number } | null;\n /**\n * Trust-but-verify hook. When `pendingMode` is on, `page_submit` and\n * destructive `page_click` route through this; the host shows a prompt and\n * resolves true (proceed) / false (declined).\n */\n confirm?: (req: NavigationConfirmRequest) => Promise<boolean>;\n};\n\nexport type NavigationBridgeOptions = {\n adapter: NavigationBridgeAdapter;\n /** Identity tagged into activity events (so the human sees who's driving). */\n agent?: { id: string; name?: string; color?: string };\n /** Route submit + destructive clicks through `adapter.confirm`. Default true. */\n pendingMode?: boolean;\n};\n\nconst DEFAULT_AGENT = { id: \"agent\", name: \"Agent\", color: \"#a855f7\" };\n\n/**\n * registerNavigationBridge — site-wide co-browsing. Lets a connected agent\n * navigate, scroll, and (with staged confirm) fill + click any page, addressed\n * by stable handles. Pairs with `useCoBrowseSession` (server + relay) and\n * `<CoBrowsePresence>` (the human's view of the agent). The 12th Fancy bridge.\n */\nexport function registerNavigationBridge(\n host: ToolHost,\n options: NavigationBridgeOptions,\n): Bridge {\n const { adapter } = options;\n const agent = { ...DEFAULT_AGENT, ...(options.agent ?? {}) };\n const pendingMode = options.pendingMode ?? true;\n const disposers: Array<() => void> = [];\n let groundedRevision: number | null = null;\n\n const staleIntent = () => {\n const current = adapter.getRevision?.();\n if (current === undefined) return null;\n if (groundedRevision === null || groundedRevision !== current) {\n return errorResult(\n `Human took control at page revision ${current}. This agent action was cancelled; call page_describe before acting again.`,\n );\n }\n return null;\n };\n\n ensureUndoToolsRegistered(host, { defaultAgentId: agent.id });\n\n const target = (label: string, elementId?: string): AgentTarget => ({\n kind: \"navigation\",\n screenId: adapter.screenId,\n elementId,\n label,\n });\n\n const reg = (\n name: string,\n description: string,\n properties: Record<string, unknown>,\n required: string[],\n handler: (args: JsonObject) => Promise<any> | any,\n activity: false | ((args: JsonObject) => AgentTarget),\n ) => {\n const wrapped = async (args: JsonObject) => {\n try {\n return await handler(args);\n } catch (e) {\n return errorResult(e instanceof Error ? e.message : String(e));\n }\n };\n const final = activity\n ? wrapToolWithActivity(wrapped, {\n toolName: name,\n agent: { id: agent.id, name: agent.name, color: agent.color },\n kind: \"navigation\",\n screenId: adapter.screenId,\n resolveTarget: ({ args }) => activity(args),\n })\n : wrapped;\n disposers.push(\n host.registerTool(\n {\n name,\n description,\n inputSchema: { type: \"object\", properties: properties as any, required, additionalProperties: false },\n },\n final as any,\n ),\n );\n };\n\n // ───────────── Read ─────────────\n\n reg(\n \"page_describe\",\n \"Describe the current page: its URL, title, and the interactive elements you can act on (each with a stable `handle`, role, and label). Call this first, and again after navigating.\",\n {},\n [],\n () => {\n const snap = adapter.describe();\n const revision = adapter.getRevision?.();\n if (revision !== undefined) {\n snap.revision = revision;\n groundedRevision = revision;\n }\n const text = [\n `URL: ${snap.url}`,\n `Title: ${snap.title}`,\n \"\",\n ...snap.actions.map((a) => `[${a.handle}] ${a.role}: ${a.label}${a.destructive ? \" (destructive)\" : \"\"}`),\n ].join(\"\\n\");\n return textResult(text, snap);\n },\n () => target(\"Inspect page\"),\n );\n\n reg(\n \"page_read\",\n \"Read the page's visible text / heading outline for grounding.\",\n {},\n [],\n () => textResult(adapter.read ? adapter.read() : \"(host did not provide page text)\"),\n () => target(\"Read page\"),\n );\n\n reg(\n \"page_focus\",\n \"Move the agent's visible focus to an interactive element by stable handle without activating it.\",\n { handle: { type: \"string\" } },\n [\"handle\"],\n (args) => {\n const stale = staleIntent();\n if (stale) return stale;\n const handle = String(args.handle ?? \"\");\n const action = adapter.describe().actions.find((candidate) => candidate.handle === handle);\n if (!action) return errorResult(`No element for handle \"${handle}\"`);\n return textResult(`Focused ${handle}`, {\n handle,\n rect: adapter.rectFor?.(handle) ?? undefined,\n });\n },\n (args) => target(`Focus ${String(args.handle ?? \"\")}`, String(args.handle ?? \"\")),\n );\n\n // ───────────── Navigate / scroll ─────────────\n\n reg(\n \"nav_visit\",\n \"Navigate to a URL (same-site path or absolute). The human watches the page change.\",\n { url: { type: \"string\", description: \"Path like /packages or an absolute URL.\" } },\n [\"url\"],\n async (args) => {\n const stale = staleIntent();\n if (stale) return stale;\n const url = String(args.url ?? \"\");\n if (!url) return errorResult(\"url is required\");\n const from = adapter.getLocation().url;\n await adapter.visit(url);\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: \"navigation\",\n action: \"nav_visit\",\n label: `Navigate to ${url}`,\n undo: () => {\n adapter.visit(from);\n },\n redo: () => {\n adapter.visit(url);\n },\n });\n return textResult(`Navigated to ${url}`, { url });\n },\n (args) => target(`Navigate → ${String(args.url ?? \"\")}`),\n );\n\n reg(\n \"nav_back\",\n \"Go back to the previous page.\",\n {},\n [],\n async () => {\n const stale = staleIntent();\n if (stale) return stale;\n if (!adapter.back) return errorResult(\"Host did not provide back navigation.\");\n await adapter.back();\n return textResult(\"Went back\");\n },\n () => target(\"Back\"),\n );\n\n reg(\n \"nav_forward\",\n \"Go forward to the next page.\",\n {},\n [],\n async () => {\n const stale = staleIntent();\n if (stale) return stale;\n if (!adapter.forward) return errorResult(\"Host did not provide forward navigation.\");\n await adapter.forward();\n return textResult(\"Went forward\");\n },\n () => target(\"Forward\"),\n );\n\n reg(\n \"nav_scroll_to\",\n \"Scroll the page to absolute coordinates, or to a specific element by its handle.\",\n {\n handle: { type: \"string\", description: \"Scroll this element into view.\" },\n x: { type: \"number\" },\n y: { type: \"number\" },\n },\n [],\n (args) => {\n const stale = staleIntent();\n if (stale) return stale;\n const handle = typeof args.handle === \"string\" ? args.handle : undefined;\n adapter.scrollTo({\n handle,\n x: typeof args.x === \"number\" ? args.x : undefined,\n y: typeof args.y === \"number\" ? args.y : undefined,\n });\n return textResult(\"Scrolled\", handle ? { handle, rect: adapter.rectFor?.(handle) ?? undefined } : undefined);\n },\n () => target(\"Scroll\"),\n );\n\n reg(\n \"nav_scroll_by\",\n \"Scroll the page by a vertical delta in pixels (negative scrolls up).\",\n { dy: { type: \"number\" } },\n [\"dy\"],\n (args) => {\n const stale = staleIntent();\n if (stale) return stale;\n adapter.scrollBy(Number(args.dy ?? 0));\n return textResult(`Scrolled by ${Number(args.dy ?? 0)}px`);\n },\n () => target(\"Scroll\"),\n );\n\n // ───────────── Co-drive (fill / click / submit) ─────────────\n\n reg(\n \"page_set_field\",\n \"Set a form field's value by handle. The host updates the controlled input and the human sees it change.\",\n {\n handle: { type: \"string\" },\n value: { description: \"Value to set; type matches the field.\" },\n },\n [\"handle\", \"value\"],\n (args) => {\n const stale = staleIntent();\n if (stale) return stale;\n const handle = String(args.handle ?? \"\");\n const res = adapter.setField(handle, args.value);\n if (!res.ok) return errorResult(res.error ?? `Could not set ${handle}`);\n return textResult(`${handle} ← ${JSON.stringify(args.value)}`, { handle, value: args.value, rect: adapter.rectFor?.(handle) ?? undefined });\n },\n (args) => target(`Set ${String(args.handle ?? \"\")}`, String(args.handle ?? \"\")),\n );\n\n reg(\n \"page_click\",\n \"Activate an element by handle (link, button, checkbox…). Destructive elements are staged for the human to confirm.\",\n { handle: { type: \"string\" } },\n [\"handle\"],\n async (args) => {\n const stale = staleIntent();\n if (stale) return stale;\n const handle = String(args.handle ?? \"\");\n const action = adapter.describe().actions.find((a) => a.handle === handle);\n const rect = adapter.rectFor?.(handle) ?? undefined; // capture before the click may navigate away\n if (pendingMode && action?.destructive && adapter.confirm) {\n const ok = await adapter.confirm({ action: \"click\", handle, label: action.label });\n if (!ok) return errorResult(\"Declined by user\");\n }\n const res = adapter.click(handle);\n if (!res.ok) return errorResult(res.error ?? `Could not click ${handle}`);\n return textResult(`Clicked ${handle}`, { handle, rect });\n },\n (args) => target(`Click ${String(args.handle ?? \"\")}`, String(args.handle ?? \"\")),\n );\n\n reg(\n \"page_submit\",\n \"Submit a form by handle. Always staged for the human to confirm when pendingMode is on.\",\n { handle: { type: \"string\" } },\n [\"handle\"],\n async (args) => {\n const stale = staleIntent();\n if (stale) return stale;\n const handle = String(args.handle ?? \"\");\n const rect = adapter.rectFor?.(handle) ?? undefined; // capture before the submit navigates\n if (pendingMode && adapter.confirm) {\n const ok = await adapter.confirm({ action: \"submit\", handle, label: handle });\n if (!ok) return errorResult(\"Declined by user\");\n }\n const res = await adapter.submit(handle);\n if (!res.ok) return errorResult(res.error ?? \"Submit failed\");\n return textResult(`Submitted ${handle}`, { handle, rect });\n },\n (args) => target(`Submit ${String(args.handle ?? \"\")}`, String(args.handle ?? \"\")),\n );\n\n return {\n id: \"navigation\",\n title: \"Co-browsing\",\n dispose: () => {\n for (const d of disposers) d();\n },\n };\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { MicroMcpServer } from \"../mcp/server\";\nimport { attachInProcess } from \"../mcp/transports\";\nimport { attachSseRelay, type RelayState, type SseRelayTransport } from \"./sse-relay\";\nimport { createSessionDescriptor, type SessionDescriptor } from \"./token\";\nimport { emitActivity } from \"../presence/registry\";\nimport { registerNavigationBridge, type NavigationBridgeAdapter } from \"../bridges/navigation\";\n\n/** A thing the human did, surfaced so the connected agent stays aware. */\nexport type CoBrowseUserEvent =\n | { kind: \"navigation\"; url: string; title?: string; revision?: number }\n | { kind: \"scroll\"; y: number; revision?: number }\n | { kind: \"form\"; handle: string; value?: unknown; masked?: boolean; revision?: number }\n | { kind: \"click\"; handle: string; label?: string; revision?: number };\n\nexport type UseCoBrowseSessionOptions = {\n /**\n * The navigation adapter (Inertia + DOM in the sandbox). MUST be stable —\n * its methods should read live state via refs, since the bridge captures it\n * once on mount. Memoize it.\n */\n adapter: NavigationBridgeAdapter;\n /** Identity for the agent's presence (cursor/log color + name). */\n agent?: { id: string; name?: string; color?: string };\n /** Relay base path. Default \"/agent-relay\" (the generic frame broker). */\n relayBaseUrl?: string;\n /** MCP server info advertised to the agent. */\n info?: { name: string; version: string; instructions?: string };\n /** Register extra bridges (forms/screens/…) on the same server. */\n extraBridges?: (server: MicroMcpServer) => void;\n /** CSRF token for the relay register/unregister POSTs. */\n csrfToken?: () => string | null | undefined;\n /** Stage submit + destructive clicks for human confirm. Default true. */\n pendingMode?: boolean;\n};\n\nexport type CoBrowseSession = {\n server: MicroMcpServer | null;\n session: SessionDescriptor | null;\n relayState: RelayState;\n startShare: () => Promise<void>;\n stopShare: () => void;\n /**\n * Report a human action so the connected agent is notified. Emits a\n * `source:\"user\"` activity event, which the SSE relay forwards to the agent\n * as a `notifications/agent_activity` frame.\n */\n observeUser: (event: CoBrowseUserEvent) => void;\n};\n\nconst DEFAULT_AGENT = { id: \"agent\", name: \"Agent\", color: \"#a855f7\" };\nconst USER = { id: \"human\", name: \"You\" };\n\n/**\n * Site-wide co-browsing session: one persistent in-page `MicroMcpServer` running\n * the navigation bridge, joinable by an external agent over the relay. Mount it\n * once at the app root; render `<CoBrowsePresence>` to show the agent + a Stop\n * control. The host wires `observeUser(...)` to navigation/scroll/form listeners\n * so the agent sees what the human does.\n */\nexport function useCoBrowseSession(options: UseCoBrowseSessionOptions): CoBrowseSession {\n const { adapter, extraBridges } = options;\n const agent = { ...DEFAULT_AGENT, ...(options.agent ?? {}) };\n const relayBaseUrl = options.relayBaseUrl ?? \"/agent-relay\";\n\n const serverRef = useRef<MicroMcpServer | null>(null);\n const relayRef = useRef<SseRelayTransport | null>(null);\n const detachInProc = useRef<(() => void) | null>(null);\n const disposeBridge = useRef<(() => void) | null>(null);\n\n const [session, setSession] = useState<SessionDescriptor | null>(null);\n const [relayState, setRelayState] = useState<RelayState>(\"idle\");\n\n // Build the server + bridges once. The adapter is captured here, so it must\n // be stable (its methods read live state).\n useEffect(() => {\n const server = new MicroMcpServer({\n info: options.info ?? { name: \"fancy-co-browse\", version: \"0.1.0\" },\n instructions:\n options.info?.instructions ??\n \"Co-browse with a watching human. Call page_describe first; navigate, scroll, and (with confirm) fill/click via stable handles. You receive notifications/agent_activity for the human's actions (source:\\\"user\\\").\",\n });\n const bridge = registerNavigationBridge(server, { adapter, agent, pendingMode: options.pendingMode });\n extraBridges?.(server);\n const inProc = attachInProcess(server);\n detachInProc.current = () => inProc.close();\n disposeBridge.current = bridge.dispose;\n serverRef.current = server;\n\n return () => {\n relayRef.current?.close();\n relayRef.current = null;\n disposeBridge.current?.();\n detachInProc.current?.();\n serverRef.current = null;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const startShare = useCallback(async () => {\n const server = serverRef.current;\n if (!server || relayRef.current) return;\n const descriptor = createSessionDescriptor();\n const csrf = options.csrfToken?.() ?? \"\";\n const response = await fetch(`${relayBaseUrl}/register`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", \"x-csrf-token\": csrf },\n body: JSON.stringify({ session: descriptor.id, token: descriptor.token }),\n });\n if (!response.ok) {\n throw new Error(`Relay registration failed (${response.status})`);\n }\n const relay = attachSseRelay(server, { baseUrl: relayBaseUrl, sessionId: descriptor.id, token: descriptor.token });\n relay.onStateChange(setRelayState);\n relayRef.current = relay;\n setSession(descriptor);\n }, [relayBaseUrl, options]);\n\n const stopShare = useCallback(() => {\n const current = session;\n relayRef.current?.close();\n relayRef.current = null;\n setRelayState(\"idle\");\n setSession(null);\n if (current) {\n const csrf = options.csrfToken?.() ?? \"\";\n void fetch(`${relayBaseUrl}/${current.id}/unregister?token=${encodeURIComponent(current.token)}`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", \"x-csrf-token\": csrf },\n }).catch(() => {});\n }\n }, [relayBaseUrl, options, session]);\n\n const observeUser = useCallback((event: CoBrowseUserEvent) => {\n const label =\n event.kind === \"navigation\"\n ? `You navigated to ${event.url}`\n : event.kind === \"scroll\"\n ? \"You scrolled\"\n : event.kind === \"click\"\n ? `You clicked ${event.label ?? event.handle}`\n : `You edited ${event.handle}${event.masked ? \" (hidden)\" : \"\"}`;\n emitActivity({\n agentId: USER.id,\n agentName: USER.name,\n source: \"user\",\n target: { kind: \"navigation\", label },\n action: `user_${event.kind}`,\n timestamp: Date.now(),\n meta: event as Record<string, unknown>,\n });\n }, []);\n\n return { server: serverRef.current, session, relayState, startShare, stopShare, observeUser };\n}\n","import { type ReactNode, useEffect, useMemo, useRef } from \"react\";\nimport type { MicroMcpServer } from \"../../mcp/server\";\nimport { registerFormBridge, type FormBridgeAdapter, type FormFieldDescriptor } from \"../../bridges/forms\";\n\nexport type BridgedFormProps = {\n /** Stable id for this form. Used by agents in `form_*` tool calls. */\n id: string;\n /** Human title (also surfaced as the bridge title). */\n title?: string;\n /** Optional fancy-screens screen id this form lives in. */\n screenId?: string;\n /** Field descriptors — drives the agent-facing schema. */\n fields: FormFieldDescriptor[];\n /** Controlled values. */\n values: Record<string, unknown>;\n /** Setter — hosts pass their setState. */\n onChange: (next: Record<string, unknown>) => void;\n /** Optional submit handler. */\n onSubmit?: () => Promise<{ ok: boolean; values?: Record<string, unknown>; error?: string }>;\n /** The MicroMcpServer the bridge registers against. Pass null/undefined\n * to render without a bridge (useful for stories / non-shared use). */\n server?: MicroMcpServer | null;\n /** Identity used in activity events. */\n agent?: { id: string; name?: string; color?: string };\n children: ReactNode;\n};\n\n/**\n * BridgedForm — wraps a react-fancy form (or any controlled inputs)\n * with a `registerFormBridge` lifecycle. Children render the actual form\n * using `values` + `onChange`; this component only manages the bridge.\n *\n * Hosts use it like:\n *\n * <BridgedForm id=\"signup\" fields={...} values={values} onChange={setValues} server={server}>\n * <Field><Input value={values.email} onValueChange={(v) => onChange({ ...values, email: v })} /></Field>\n * ...\n * </BridgedForm>\n *\n * Agents can then call form_describe, form_set_value, form_submit, etc.\n */\nexport function BridgedForm({\n id,\n title,\n screenId,\n fields,\n values,\n onChange,\n onSubmit,\n server,\n agent,\n children,\n}: BridgedFormProps) {\n // Refs so the adapter sees fresh values without re-installing the bridge.\n const valuesRef = useRef(values);\n const onChangeRef = useRef(onChange);\n const fieldsRef = useRef(fields);\n const submitRef = useRef(onSubmit);\n useEffect(() => { valuesRef.current = values; }, [values]);\n useEffect(() => { onChangeRef.current = onChange; }, [onChange]);\n useEffect(() => { fieldsRef.current = fields; }, [fields]);\n useEffect(() => { submitRef.current = onSubmit; }, [onSubmit]);\n\n const focusElement = (name: string) => {\n if (typeof document === \"undefined\") return;\n const el = document.querySelector(`[data-form-id=\"${id}\"] [name=\"${name}\"]`) as HTMLElement | null;\n el?.focus();\n };\n\n const adapter = useMemo<FormBridgeAdapter>(() => ({\n id,\n title,\n screenId,\n getFields: () => fieldsRef.current,\n getValue: (name) => valuesRef.current[name],\n getValues: () => ({ ...valuesRef.current }),\n setValue: (name, v) => onChangeRef.current({ ...valuesRef.current, [name]: v }),\n setValues: (next) => onChangeRef.current({ ...valuesRef.current, ...next }),\n focus: focusElement,\n submit: async () => {\n if (!submitRef.current) {\n return { ok: true, values: { ...valuesRef.current } };\n }\n return submitRef.current();\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }), [id, title, screenId]);\n\n useEffect(() => {\n if (!server) return;\n const bridge = registerFormBridge(server, { adapter, agent });\n return () => bridge.dispose();\n }, [server, adapter, agent]);\n\n return <div data-form-id={id}>{children}</div>;\n}\n","import { useEffect } from \"react\";\nimport { onActivity } from \"../../presence/registry\";\n\n/**\n * Loose shape of the fancy-screens system context — kept here so this\n * component doesn't hard-import `@particle-academy/fancy-screens`.\n */\ntype ScreenSystemLike = {\n registry: Map<string, { id: string; agentActivity?: unknown }>;\n updateScreen: (id: string, patch: { agentActivity?: unknown }) => void;\n};\n\nexport type ScreensActivityBridgeProps = {\n /** The value returned by `useScreenSystem()` from fancy-screens. */\n system: ScreenSystemLike;\n /** ms to wait after the last activity before clearing the screen's badge. Default 1500. */\n fadeMs?: number;\n};\n\n/**\n * ScreensActivityBridge — subscribe to the in-process activity registry\n * and patch each event into the matching screen's `agentActivity` field.\n * Fade-out clears the badge after `fadeMs`.\n *\n * Use it once near the root of your app, ABOVE every <Screen>:\n *\n * const system = useScreenSystem();\n * <>\n * <ScreensActivityBridge system={system} />\n * <Screen id=\"dashboard\">…</Screen>\n * <Screen id=\"form\">…</Screen>\n * </>\n *\n * Renders nothing; pure side-effect component.\n */\nexport function ScreensActivityBridge({ system, fadeMs = 1500 }: ScreensActivityBridgeProps) {\n useEffect(() => {\n const fadeTimers = new Map<string, ReturnType<typeof setTimeout>>();\n const off = onActivity((event) => {\n const screenId = event.target.screenId;\n if (!screenId) return;\n // Only patch screens that are currently registered.\n if (!system.registry.has(screenId)) return;\n const activity = {\n agentId: event.agentId,\n agentName: event.agentName,\n agentColor: event.agentColor,\n action: event.action,\n timestamp: event.timestamp,\n elementId: event.target.elementId,\n label: event.target.label,\n };\n system.updateScreen(screenId, { agentActivity: activity });\n const prev = fadeTimers.get(screenId);\n if (prev) clearTimeout(prev);\n fadeTimers.set(\n screenId,\n setTimeout(() => {\n system.updateScreen(screenId, { agentActivity: null });\n fadeTimers.delete(screenId);\n }, event.ttlMs ?? fadeMs),\n );\n });\n return () => {\n off();\n for (const t of fadeTimers.values()) clearTimeout(t);\n };\n }, [system, fadeMs]);\n return null;\n}\n","import { useAgentActivity } from \"../../presence/use-agent-activity\";\nimport { ShareControls } from \"../ShareControls/ShareControls\";\nimport { ConnectorButtons } from \"../../connectors/ConnectorButtons\";\nimport type { CoBrowseSession } from \"../../sharing/use-co-browse-session\";\n\nexport type CoBrowsePresenceProps = {\n /** The session from `useCoBrowseSession`. */\n session: CoBrowseSession;\n /** Public MCP/connect URL shown to the user (for ConnectorButtons), optional. */\n connectUrl?: string;\n /** Base URL used to build the shareable session link. */\n shareBaseUrl?: string;\n className?: string;\n};\n\n/**\n * The human's view of a site-wide co-browsing session: a \"Let an agent drive\"\n * starter, the share/connect surface once started, a live \"agent is driving\"\n * status with the latest action, and a Stop / take-back-control button.\n *\n * Staged-action confirms are rendered by the HOST (via the navigation adapter's\n * `confirm`), so this component stays presentation-only.\n */\nexport function CoBrowsePresence({ session, connectUrl, shareBaseUrl, className }: CoBrowsePresenceProps) {\n const { events } = useAgentActivity(undefined, { capacity: 40 });\n const lastAgentAction = [...events].reverse().find((e) => (e.source ?? \"agent\") !== \"user\");\n const connected = session.relayState === \"open\";\n\n if (!session.session) {\n return (\n <div className={className} data-co-browse-presence=\"idle\">\n <button type=\"button\" onClick={() => void session.startShare()} data-co-browse-start>\n Let an agent drive\n </button>\n </div>\n );\n }\n\n return (\n <div className={className} data-co-browse-presence={connected ? \"connected\" : \"waiting\"}>\n <div data-co-browse-bar>\n <span data-co-browse-dot data-state={session.relayState} />\n <span data-co-browse-status>\n {connected ? \"Agent is driving\" : `Waiting for an agent… (${session.relayState})`}\n </span>\n {lastAgentAction && <span data-co-browse-last>{lastAgentAction.target?.label ?? lastAgentAction.action}</span>}\n <button type=\"button\" onClick={session.stopShare} data-co-browse-stop>\n Stop\n </button>\n </div>\n\n <ShareControls\n session={session.session}\n onStart={() => void session.startShare()}\n onStop={session.stopShare}\n status={session.relayState}\n shareBaseUrl={shareBaseUrl}\n />\n\n {connectUrl && <ConnectorButtons serverName=\"Fancy UI co-browse\" mcpUrl={connectUrl} />}\n </div>\n );\n}\n\nCoBrowsePresence.displayName = \"CoBrowsePresence\";\n","import { useEffect, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { useAgentActivity } from \"../../presence/use-agent-activity\";\nimport { AgentCursor } from \"../AgentCursor/AgentCursor\";\nimport { AgentActivityHighlight } from \"../AgentActivityHighlight/AgentActivityHighlight\";\n\ntype Rect = { x: number; y: number; width: number; height: number };\n\nexport type CoBrowseCursorLayerProps = {\n /** Render the overlay only while a session is live. Default true. */\n active?: boolean;\n /** Stacking order of the overlay. Default just under the max. */\n zIndex?: number;\n};\n\n/**\n * Page-wide agent presence for co-browsing — the missing \"all actors present\"\n * half of Human+ UX. A fixed, click-through overlay (portaled to <body>) that\n * shows the connected agent as a live cursor + pings/highlights the element it\n * just acted on, gliding between targets. Same visual language as the whiteboard\n * demo's agent cursor, but mapped from the navigation bridge's STABLE HANDLES\n * (the agent has no real mouse) — each tool reports the acted element's viewport\n * rect in `meta.rect` (see `NavigationBridgeAdapter.rectFor`).\n *\n * Mount it once near the app root (e.g. in your CoBrowseProvider), gated on an\n * active session. SSR-safe: renders null on the server / until the first action.\n */\nexport function CoBrowseCursorLayer({ active = true, zIndex = 2147483000 }: CoBrowseCursorLayerProps) {\n const { latest } = useAgentActivity(undefined, { capacity: 12 });\n const [cursor, setCursor] = useState<{ x: number; y: number; name: string; color: string; status?: string } | null>(\n null,\n );\n const [pulse, setPulse] = useState<{ rect: Rect; color: string; key: number } | null>(null);\n\n useEffect(() => {\n if (!latest || (latest.source ?? \"agent\") === \"user\") return;\n if (latest.action === \"agent_disconnected\") {\n setCursor(null);\n setPulse(null);\n return;\n }\n const color = latest.agentColor ?? \"#a855f7\";\n const name = latest.agentName ?? \"Agent\";\n const status = latest.target?.label ?? latest.action;\n const rect = (latest.meta as { rect?: Rect } | undefined)?.rect;\n if (rect) {\n // Acted on a concrete element — glide the cursor to it + pulse a highlight.\n setCursor({ x: rect.x + rect.width / 2, y: rect.y + rect.height / 2, name, color, status });\n setPulse({ rect, color, key: latest.timestamp });\n } else {\n // nav / scroll — no element. Keep (or first-show, at viewport center) the\n // cursor so the agent stays visibly present; just refresh its caption.\n setCursor((prev) =>\n prev\n ? { ...prev, status, name, color }\n : { x: window.innerWidth / 2, y: window.innerHeight / 2, name, color, status },\n );\n }\n }, [latest?.timestamp]);\n\n if (!active || !cursor || typeof document === \"undefined\") return null;\n\n return createPortal(\n <div data-co-browse-cursor-layer=\"\" style={{ position: \"fixed\", inset: 0, pointerEvents: \"none\", zIndex }}>\n {pulse && (\n <AgentActivityHighlight\n x={pulse.rect.x}\n y={pulse.rect.y}\n width={pulse.rect.width}\n height={pulse.rect.height}\n color={pulse.color}\n pulseKey={pulse.key}\n />\n )}\n <AgentCursor\n x={cursor.x}\n y={cursor.y}\n name={cursor.name}\n color={cursor.color}\n status={cursor.status}\n style={{ transition: \"left .35s cubic-bezier(.22,.61,.36,1), top .35s cubic-bezier(.22,.61,.36,1)\" }}\n />\n </div>,\n document.body,\n );\n}\n\nCoBrowseCursorLayer.displayName = \"CoBrowseCursorLayer\";\n","import { type CSSProperties, useState } from \"react\";\n\nexport type SimulateUsersButtonProps = {\n /** Endpoint that injects the fake active users. Default `/active-users/simulate`. */\n endpoint?: string;\n /** How many fake users to simulate (sent as `count`). Default `10`. */\n count?: number;\n /** Button label. Default `Simulate {count} active users`. */\n label?: string;\n /**\n * CSRF token sent as `X-CSRF-TOKEN`. If omitted, falls back to a\n * `<meta name=\"csrf-token\">` on the page (the Laravel default).\n */\n csrfToken?: string;\n /** Called after a successful trigger. */\n onTriggered?: () => void;\n /** Called if the request fails. */\n onError?: (error: unknown) => void;\n className?: string;\n style?: CSSProperties;\n};\n\nfunction resolveCsrf(explicit?: string): string | undefined {\n if (explicit) return explicit;\n if (typeof document === \"undefined\") return undefined;\n return document.querySelector<HTMLMetaElement>('meta[name=\"csrf-token\"]')?.content;\n}\n\n/**\n * A button that asks the host to inject N **fake** active users (injected\n * dummies, not real accounts) so the live ActiveUser stream / presence overlay\n * has something to animate in a demo. POSTs `{ count }` to `endpoint`.\n *\n * Self-contained (inline styles, no react-fancy dependency) so it drops into any\n * host. The fakes + their staggered activity are produced server-side; this\n * button only triggers them.\n */\nexport function SimulateUsersButton({\n endpoint = \"/active-users/simulate\",\n count = 10,\n label,\n csrfToken,\n onTriggered,\n onError,\n className,\n style,\n}: SimulateUsersButtonProps) {\n const [busy, setBusy] = useState(false);\n\n async function trigger() {\n if (busy) return;\n setBusy(true);\n try {\n const token = resolveCsrf(csrfToken);\n const res = await fetch(endpoint, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Requested-With\": \"XMLHttpRequest\",\n ...(token ? { \"X-CSRF-TOKEN\": token } : {}),\n },\n credentials: \"same-origin\",\n body: JSON.stringify({ count }),\n });\n if (!res.ok) throw new Error(`Simulate request failed: ${res.status}`);\n onTriggered?.();\n } catch (err) {\n onError?.(err);\n } finally {\n setBusy(false);\n }\n }\n\n return (\n <button\n type=\"button\"\n data-fai-simulate-users=\"\"\n className={[\"fai-simulate-users\", className ?? \"\"].filter(Boolean).join(\" \")}\n onClick={trigger}\n disabled={busy}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 8,\n padding: \"8px 14px\",\n borderRadius: 8,\n border: \"1px solid rgba(139,92,246,0.4)\",\n background: busy ? \"rgba(139,92,246,0.15)\" : \"rgba(139,92,246,0.1)\",\n color: \"#7c3aed\",\n font: \"inherit\",\n fontSize: 13,\n fontWeight: 500,\n cursor: busy ? \"progress\" : \"pointer\",\n opacity: busy ? 0.7 : 1,\n ...style,\n }}\n >\n <span aria-hidden>{busy ? \"⏳\" : \"✨\"}</span>\n {label ?? `Simulate ${count} active users`}\n </button>\n );\n}\n"]}
@@ -38,6 +38,7 @@ declare class SseRelayTransport implements Transport {
38
38
  private listeners;
39
39
  private state;
40
40
  private expectedToken;
41
+ private peers;
41
42
  constructor(options: SseRelayOptions);
42
43
  bindServer(server: MicroMcpServer): void;
43
44
  /** Open the receive channel. Idempotent. */
@@ -38,6 +38,7 @@ declare class SseRelayTransport implements Transport {
38
38
  private listeners;
39
39
  private state;
40
40
  private expectedToken;
41
+ private peers;
41
42
  constructor(options: SseRelayOptions);
42
43
  bindServer(server: MicroMcpServer): void;
43
44
  /** Open the receive channel. Idempotent. */
package/dist/sharing.cjs CHANGED
@@ -87,6 +87,7 @@ function constantTimeEqual(a, b) {
87
87
  }
88
88
 
89
89
  // src/sharing/sse-relay.ts
90
+ init_registry();
90
91
  var SseRelayTransport = class {
91
92
  constructor(options) {
92
93
  this.disposed = false;
@@ -94,6 +95,7 @@ var SseRelayTransport = class {
94
95
  this.connected = false;
95
96
  this.listeners = /* @__PURE__ */ new Set();
96
97
  this.state = "idle";
98
+ this.peers = /* @__PURE__ */ new Set();
97
99
  this.opts = options;
98
100
  this.expectedToken = options.token;
99
101
  }
@@ -192,6 +194,36 @@ var SseRelayTransport = class {
192
194
  } catch {
193
195
  return;
194
196
  }
197
+ if ("method" in message && message.method === "notifications/peer_joined") {
198
+ const subscriberId = String(message.params?.subscriberId ?? "peer");
199
+ this.peers.add(subscriberId);
200
+ fancyAutoCommon.emitActivity({
201
+ agentId: "agent",
202
+ agentName: "Agent",
203
+ agentColor: "#a855f7",
204
+ action: "agent_connected",
205
+ timestamp: Date.now(),
206
+ target: { kind: "navigation", label: "Agent connected" },
207
+ meta: { subscriberId }
208
+ });
209
+ return;
210
+ }
211
+ if ("method" in message && message.method === "notifications/peer_left") {
212
+ const subscriberId = String(message.params?.subscriberId ?? "peer");
213
+ this.peers.delete(subscriberId);
214
+ if (this.peers.size === 0) {
215
+ fancyAutoCommon.emitActivity({
216
+ agentId: "agent",
217
+ agentName: "Agent",
218
+ agentColor: "#a855f7",
219
+ action: "agent_disconnected",
220
+ timestamp: Date.now(),
221
+ target: { kind: "navigation", label: "Agent disconnected" },
222
+ meta: { subscriberId }
223
+ });
224
+ }
225
+ return;
226
+ }
195
227
  await this.server.receive(this, message);
196
228
  }
197
229
  setState(state) {