@particle-academy/agent-integrations 0.29.0 → 0.30.0
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/README.md +30 -1
- package/dist/bridges/files.d.cts +20 -1
- package/dist/bridges/files.d.ts +20 -1
- package/dist/bridges/forms.d.cts +22 -1
- package/dist/bridges/forms.d.ts +22 -1
- package/dist/bridges/terminal.d.cts +21 -1
- package/dist/bridges/terminal.d.ts +21 -1
- package/dist/bridges-artboard.cjs +1 -1
- package/dist/bridges-artboard.cjs.map +1 -1
- package/dist/bridges-artboard.js +1 -1
- package/dist/bridges-catalog.cjs +1 -1
- package/dist/bridges-catalog.cjs.map +1 -1
- package/dist/bridges-catalog.js +2 -2
- package/dist/bridges-charts.cjs +1 -1
- package/dist/bridges-charts.cjs.map +1 -1
- package/dist/bridges-charts.js +2 -2
- package/dist/bridges-cms.cjs +1 -1
- package/dist/bridges-cms.cjs.map +1 -1
- package/dist/bridges-cms.js +3 -3
- package/dist/bridges-code.cjs +38 -3
- package/dist/bridges-code.cjs.map +1 -1
- package/dist/bridges-code.js +2 -2
- package/dist/bridges-doc.cjs +1 -1
- package/dist/bridges-doc.cjs.map +1 -1
- package/dist/bridges-doc.js +2 -2
- package/dist/bridges-features.cjs +1 -1
- package/dist/bridges-features.cjs.map +1 -1
- package/dist/bridges-features.js +2 -2
- package/dist/bridges-files.cjs +29 -8
- package/dist/bridges-files.cjs.map +1 -1
- package/dist/bridges-files.js +2 -2
- package/dist/bridges-flow.cjs +1 -1
- package/dist/bridges-flow.cjs.map +1 -1
- package/dist/bridges-flow.js +1 -1
- package/dist/bridges-forms.cjs +12 -2
- package/dist/bridges-forms.cjs.map +1 -1
- package/dist/bridges-forms.js +2 -2
- package/dist/bridges-map.cjs +1 -1
- package/dist/bridges-map.cjs.map +1 -1
- package/dist/bridges-map.js +2 -2
- package/dist/bridges-scene.cjs +1 -1
- package/dist/bridges-scene.cjs.map +1 -1
- package/dist/bridges-scene.js +2 -2
- package/dist/bridges-screens.cjs +1 -1
- package/dist/bridges-screens.cjs.map +1 -1
- package/dist/bridges-screens.js +2 -2
- package/dist/bridges-sheets.cjs +1 -1
- package/dist/bridges-sheets.cjs.map +1 -1
- package/dist/bridges-sheets.js +2 -2
- package/dist/bridges-slides.cjs +1 -1
- package/dist/bridges-slides.cjs.map +1 -1
- package/dist/bridges-slides.js +2 -2
- package/dist/bridges-terminal.cjs +70 -45
- package/dist/bridges-terminal.cjs.map +1 -1
- package/dist/bridges-terminal.js +2 -2
- package/dist/bridges-tui.js +1 -1
- package/dist/bridges-whiteboard.cjs +1 -1
- package/dist/bridges-whiteboard.cjs.map +1 -1
- package/dist/bridges-whiteboard.js +2 -2
- package/dist/{chunk-OFCR6JY3.js → chunk-2U5JB6ZA.js} +3 -3
- package/dist/{chunk-OFCR6JY3.js.map → chunk-2U5JB6ZA.js.map} +1 -1
- package/dist/{chunk-ULJL53DL.js → chunk-2VENWGLZ.js} +3 -3
- package/dist/chunk-2VENWGLZ.js.map +1 -0
- package/dist/{chunk-BE2XS577.js → chunk-6YUBWQTS.js} +3 -3
- package/dist/{chunk-BE2XS577.js.map → chunk-6YUBWQTS.js.map} +1 -1
- package/dist/{chunk-OHUDEA6R.js → chunk-BHQJJ2YG.js} +3 -3
- package/dist/{chunk-OHUDEA6R.js.map → chunk-BHQJJ2YG.js.map} +1 -1
- package/dist/{chunk-LZJI7EKQ.js → chunk-CA7GIJJC.js} +3 -3
- package/dist/{chunk-LZJI7EKQ.js.map → chunk-CA7GIJJC.js.map} +1 -1
- package/dist/{chunk-7VBB2FJB.js → chunk-DKSR4R4O.js} +3 -3
- package/dist/{chunk-7VBB2FJB.js.map → chunk-DKSR4R4O.js.map} +1 -1
- package/dist/{chunk-2Y7Y5PTR.js → chunk-G5EZNWXJ.js} +3 -3
- package/dist/{chunk-2Y7Y5PTR.js.map → chunk-G5EZNWXJ.js.map} +1 -1
- package/dist/{chunk-OIX2ANFS.js → chunk-GRHPEK6M.js} +45 -9
- package/dist/chunk-GRHPEK6M.js.map +1 -0
- package/dist/{chunk-VMCG3PJD.js → chunk-HRHC5GM5.js} +31 -11
- package/dist/chunk-HRHC5GM5.js.map +1 -0
- package/dist/{chunk-5KLUYF4D.js → chunk-HSI5RVF4.js} +3 -3
- package/dist/{chunk-5KLUYF4D.js.map → chunk-HSI5RVF4.js.map} +1 -1
- package/dist/{chunk-AF454WRD.js → chunk-LQZKRBWR.js} +3 -3
- package/dist/{chunk-AF454WRD.js.map → chunk-LQZKRBWR.js.map} +1 -1
- package/dist/{chunk-KMSRG5KH.js → chunk-N6RLSLOF.js} +7 -7
- package/dist/chunk-N6RLSLOF.js.map +1 -0
- package/dist/{chunk-NSPL5TVF.js → chunk-OAFJ53X3.js} +3 -3
- package/dist/{chunk-NSPL5TVF.js.map → chunk-OAFJ53X3.js.map} +1 -1
- package/dist/{chunk-3PKHJ4IV.js → chunk-PR4SXFZH.js} +3 -3
- package/dist/{chunk-3PKHJ4IV.js.map → chunk-PR4SXFZH.js.map} +1 -1
- package/dist/{chunk-KYMEDV6E.js → chunk-RIXYCFDO.js} +41 -6
- package/dist/chunk-RIXYCFDO.js.map +1 -0
- package/dist/{chunk-TNU6AWUO.js → chunk-USQGA672.js} +14 -4
- package/dist/chunk-USQGA672.js.map +1 -0
- package/dist/{chunk-KKGC4ERF.js → chunk-UZHNKUER.js} +72 -47
- package/dist/chunk-UZHNKUER.js.map +1 -0
- package/dist/{chunk-UTUVN6HQ.js → chunk-WCKSDFTM.js} +3 -3
- package/dist/{chunk-UTUVN6HQ.js.map → chunk-WCKSDFTM.js.map} +1 -1
- package/dist/{chunk-HFLHLS2N.js → chunk-ZNGTC4CO.js} +3 -3
- package/dist/{chunk-HFLHLS2N.js.map → chunk-ZNGTC4CO.js.map} +1 -1
- package/dist/components/SharedWhiteboard/index.d.cts +1 -1
- package/dist/components/SharedWhiteboard/index.d.ts +1 -1
- package/dist/components-shared-whiteboard.cjs +2 -3
- package/dist/components-shared-whiteboard.cjs.map +1 -1
- package/dist/components-shared-whiteboard.js +4 -4
- package/dist/heuristics.js +1 -1
- package/dist/index.cjs +156 -60
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +27 -21
- package/dist/index.js.map +1 -1
- package/dist/presence/index.d.cts +7 -0
- package/dist/presence/index.d.ts +7 -0
- package/dist/presence.cjs +1 -1
- package/dist/presence.cjs.map +1 -1
- package/dist/presence.js +1 -1
- package/dist/relay-server/index.d.cts +20 -0
- package/dist/relay-server/index.d.ts +20 -0
- package/dist/relay-server-cli.cjs +53 -9
- package/dist/relay-server-cli.cjs.map +1 -1
- package/dist/relay-server-cli.js +11 -3
- package/dist/relay-server-cli.js.map +1 -1
- package/dist/relay-server.cjs +43 -7
- package/dist/relay-server.cjs.map +1 -1
- package/dist/relay-server.js +1 -1
- package/dist/sharing/index.d.cts +1 -1
- package/dist/sharing/index.d.ts +1 -1
- package/dist/sharing.cjs +5 -5
- package/dist/sharing.cjs.map +1 -1
- package/dist/sharing.js +1 -1
- package/dist/{token-CrJF76oH.d.ts → token-BZ8doMam.d.cts} +15 -2
- package/dist/{token-CrJF76oH.d.cts → token-BZ8doMam.d.ts} +15 -2
- package/package.json +1 -1
- package/dist/chunk-KKGC4ERF.js.map +0 -1
- package/dist/chunk-KMSRG5KH.js.map +0 -1
- package/dist/chunk-KYMEDV6E.js.map +0 -1
- package/dist/chunk-OIX2ANFS.js.map +0 -1
- package/dist/chunk-TNU6AWUO.js.map +0 -1
- package/dist/chunk-ULJL53DL.js.map +0 -1
- package/dist/chunk-VMCG3PJD.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -26,8 +26,8 @@ export { DocAdapter, DocBridgeOptions, DocOpTool, registerDocBridge } from './br
|
|
|
26
26
|
export { CmsBridgeOptions, CmsOp, cmsReducer, registerCmsBridge } from './bridges/cms.cjs';
|
|
27
27
|
import { RelayState } from './sharing/index.cjs';
|
|
28
28
|
export { SseRelayOptions, SseRelayTransport, attachSseRelay } from './sharing/index.cjs';
|
|
29
|
-
import { S as SessionDescriptor } from './token-
|
|
30
|
-
export { b as buildShareConfig, a as buildShareUrl, c as createSessionDescriptor, d as describeSession, r as readSessionFromUrl } from './token-
|
|
29
|
+
import { S as SessionDescriptor } from './token-BZ8doMam.cjs';
|
|
30
|
+
export { b as buildShareConfig, a as buildShareUrl, c as createSessionDescriptor, d as describeSession, r as readSessionFromUrl } from './token-BZ8doMam.cjs';
|
|
31
31
|
import * as react from 'react';
|
|
32
32
|
import { ReactNode, CSSProperties } from 'react';
|
|
33
33
|
export { ActivityFilter, AutoActivityEvent as AgentActivityEvent, AutoActivityListener as AgentActivityListener, AutoTarget as AgentTarget, AutoTargetKind as AgentTargetKind, UndoEntry, clearStack as clearUndoStack, emitActivity, onActivity, pushUndoEntry, readActivityHistory, readHistory as readUndoHistory, redoOne, resetActivityRegistry, resetAllUndoStacks, undoOne } from '@particle-academy/fancy-auto-common';
|
package/dist/index.d.ts
CHANGED
|
@@ -26,8 +26,8 @@ export { DocAdapter, DocBridgeOptions, DocOpTool, registerDocBridge } from './br
|
|
|
26
26
|
export { CmsBridgeOptions, CmsOp, cmsReducer, registerCmsBridge } from './bridges/cms.js';
|
|
27
27
|
import { RelayState } from './sharing/index.js';
|
|
28
28
|
export { SseRelayOptions, SseRelayTransport, attachSseRelay } from './sharing/index.js';
|
|
29
|
-
import { S as SessionDescriptor } from './token-
|
|
30
|
-
export { b as buildShareConfig, a as buildShareUrl, c as createSessionDescriptor, d as describeSession, r as readSessionFromUrl } from './token-
|
|
29
|
+
import { S as SessionDescriptor } from './token-BZ8doMam.js';
|
|
30
|
+
export { b as buildShareConfig, a as buildShareUrl, c as createSessionDescriptor, d as describeSession, r as readSessionFromUrl } from './token-BZ8doMam.js';
|
|
31
31
|
import * as react from 'react';
|
|
32
32
|
import { ReactNode, CSSProperties } from 'react';
|
|
33
33
|
export { ActivityFilter, AutoActivityEvent as AgentActivityEvent, AutoActivityListener as AgentActivityListener, AutoTarget as AgentTarget, AutoTargetKind as AgentTargetKind, UndoEntry, clearStack as clearUndoStack, emitActivity, onActivity, pushUndoEntry, readActivityHistory, readHistory as readUndoHistory, redoOne, resetActivityRegistry, resetAllUndoStacks, undoOne } from '@particle-academy/fancy-auto-common';
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { ShareControls, AgentActivityHighlight, AgentCursor } from './chunk-
|
|
2
|
-
export { AgentActivityHighlight, AgentCursor, AgentPanel, ShareControls, buildAgentPrompt } from './chunk-
|
|
1
|
+
import { ShareControls, AgentActivityHighlight, AgentCursor } from './chunk-HSI5RVF4.js';
|
|
2
|
+
export { AgentActivityHighlight, AgentCursor, AgentPanel, ShareControls, buildAgentPrompt } from './chunk-HSI5RVF4.js';
|
|
3
3
|
import './chunk-IJ6JX5VC.js';
|
|
4
|
-
import { createSessionDescriptor, attachSseRelay } from './chunk-
|
|
5
|
-
export { SseRelayTransport, attachSseRelay, buildShareConfig, buildShareUrl, createSessionDescriptor, describeSession, readSessionFromUrl } from './chunk-
|
|
4
|
+
import { createSessionDescriptor, attachSseRelay } from './chunk-N6RLSLOF.js';
|
|
5
|
+
export { SseRelayTransport, attachSseRelay, buildShareConfig, buildShareUrl, createSessionDescriptor, describeSession, readSessionFromUrl } from './chunk-N6RLSLOF.js';
|
|
6
6
|
export { attachHeuristicsSink, mapActivityToEvent as mapActivityToHeuristicsEvent } from './chunk-7R6RMROL.js';
|
|
7
7
|
export { useUndoStack } from './chunk-BT7HM5I6.js';
|
|
8
|
-
export { registerFeaturesBridge } from './chunk-
|
|
9
|
-
export { cmsReducer, registerCmsBridge } from './chunk-
|
|
10
|
-
export { registerDocBridge } from './chunk-
|
|
8
|
+
export { registerFeaturesBridge } from './chunk-ZNGTC4CO.js';
|
|
9
|
+
export { cmsReducer, registerCmsBridge } from './chunk-DKSR4R4O.js';
|
|
10
|
+
export { registerDocBridge } from './chunk-LQZKRBWR.js';
|
|
11
11
|
export { registerTuiBridge } from './chunk-MFMBR6LN.js';
|
|
12
12
|
import { useAgentActivity } from './chunk-UCKJAUBY.js';
|
|
13
13
|
export { useAgentActivity, useAgentActivityForScreen } from './chunk-UCKJAUBY.js';
|
|
@@ -16,25 +16,25 @@ export { useSheetsActivityHighlights, useSheetsAdapter } from './chunk-KHKSQEMC.
|
|
|
16
16
|
import { ConnectorButtons } from './chunk-5HNTNIWY.js';
|
|
17
17
|
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';
|
|
18
18
|
export { DEFAULT_MCPB_ENTRY_POINT, MCPB_MANIFEST_VERSION, MCPB_MIN_NODE, buildMcpbManifest, buildMcpbProxyStub } from './chunk-GO2Y6H6U.js';
|
|
19
|
-
export { registerChartsBridge } from './chunk-
|
|
20
|
-
export { registerSceneBridge } from './chunk-
|
|
21
|
-
export { registerScreensBridge } from './chunk-
|
|
22
|
-
export { registerSlidesBridge } from './chunk-
|
|
23
|
-
export { registerMapBridge } from './chunk-
|
|
24
|
-
export { registerFilesBridge } from './chunk-
|
|
25
|
-
export { registerTerminalBridge } from './chunk-
|
|
26
|
-
export { registerCatalogBridge } from './chunk-
|
|
19
|
+
export { registerChartsBridge } from './chunk-G5EZNWXJ.js';
|
|
20
|
+
export { registerSceneBridge } from './chunk-CA7GIJJC.js';
|
|
21
|
+
export { registerScreensBridge } from './chunk-6YUBWQTS.js';
|
|
22
|
+
export { registerSlidesBridge } from './chunk-PR4SXFZH.js';
|
|
23
|
+
export { registerMapBridge } from './chunk-BHQJJ2YG.js';
|
|
24
|
+
export { registerFilesBridge } from './chunk-HRHC5GM5.js';
|
|
25
|
+
export { registerTerminalBridge } from './chunk-UZHNKUER.js';
|
|
26
|
+
export { registerCatalogBridge } from './chunk-OAFJ53X3.js';
|
|
27
27
|
export { RelayTransport, attachRelay } from './chunk-G6N2TQVO.js';
|
|
28
28
|
import { attachInProcess } from './chunk-AFUULW5E.js';
|
|
29
29
|
export { InProcessTransport, attachInProcess } from './chunk-AFUULW5E.js';
|
|
30
|
-
import { registerFormBridge } from './chunk-
|
|
31
|
-
export { registerFormBridge } from './chunk-
|
|
32
|
-
export { registerSheetsBridge } from './chunk-
|
|
33
|
-
export { registerCodeBridge } from './chunk-
|
|
30
|
+
import { registerFormBridge } from './chunk-USQGA672.js';
|
|
31
|
+
export { registerFormBridge } from './chunk-USQGA672.js';
|
|
32
|
+
export { registerSheetsBridge } from './chunk-WCKSDFTM.js';
|
|
33
|
+
export { registerCodeBridge } from './chunk-RIXYCFDO.js';
|
|
34
34
|
import { ensureUndoToolsRegistered, pushUndoEntry } from './chunk-CT3LRNH7.js';
|
|
35
35
|
export { clearStack as clearUndoStack, ensureUndoToolsRegistered, pushUndoEntry, readHistory as readUndoHistory, redoOne, registerUndoTools, resetAllUndoStacks, undoOne } from './chunk-CT3LRNH7.js';
|
|
36
|
-
import { wrapToolWithActivity } from './chunk-
|
|
37
|
-
export { wrapToolWithActivity } from './chunk-
|
|
36
|
+
import { wrapToolWithActivity } from './chunk-2VENWGLZ.js';
|
|
37
|
+
export { wrapToolWithActivity } from './chunk-2VENWGLZ.js';
|
|
38
38
|
import { emitActivity, onActivity } from './chunk-C3TYI5TJ.js';
|
|
39
39
|
export { emitActivity, onActivity, readActivityHistory, resetActivityRegistry } from './chunk-C3TYI5TJ.js';
|
|
40
40
|
import { MicroMcpServer, textResult, errorResult } from './chunk-DF3PLL2E.js';
|
|
@@ -152,6 +152,12 @@ function registerNavigationBridge(host, options) {
|
|
|
152
152
|
if (stale) return stale;
|
|
153
153
|
const url = String(args.url ?? "");
|
|
154
154
|
if (!url) return errorResult("url is required");
|
|
155
|
+
const scheme = /^([a-zA-Z][a-zA-Z0-9+.-]*):/.exec(url)?.[1]?.toLowerCase();
|
|
156
|
+
if (scheme && scheme !== "http" && scheme !== "https") {
|
|
157
|
+
return errorResult(
|
|
158
|
+
`Refusing to navigate to a '${scheme}:' URL. Only http(s) URLs or same-site paths are allowed.`
|
|
159
|
+
);
|
|
160
|
+
}
|
|
155
161
|
const from = adapter.getLocation().url;
|
|
156
162
|
await adapter.visit(url);
|
|
157
163
|
pushUndoEntry(agent.id, {
|
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":"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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\nconst CURSOR_EDGE_INSET = 24;\nconst FLUID_CURSOR_SPEED_PX_PER_SECOND = 1_050;\nconst MIN_GLIDE_MS = 240;\nconst MAX_GLIDE_MS = 1_200;\n\nexport function visibleCursorPoint(rect: Rect, viewport: { width: number; height: number }) {\n const x = rect.x + rect.width / 2;\n const y = rect.y + rect.height / 2;\n return {\n x: Math.min(Math.max(x, CURSOR_EDGE_INSET), Math.max(CURSOR_EDGE_INSET, viewport.width - CURSOR_EDGE_INSET)),\n y: Math.min(Math.max(y, CURSOR_EDGE_INSET), Math.max(CURSOR_EDGE_INSET, viewport.height - CURSOR_EDGE_INSET)),\n };\n}\n\nexport function fluidGlideDuration(from: { x: number; y: number } | null, to: { x: number; y: number }) {\n if (!from) return 0;\n const distance = Math.hypot(to.x - from.x, to.y - from.y);\n return Math.round(Math.min(MAX_GLIDE_MS, Math.max(MIN_GLIDE_MS, (distance / FLUID_CURSOR_SPEED_PX_PER_SECOND) * 1_000)));\n}\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; glideMs: number } | 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 // Relay clients may be intentionally short-lived (one process per MCP\n // call). The shared session is the presence boundary, not an individual\n // transport connection, so leave the agent's cursor in place between\n // calls. `active=false` still removes it when sharing actually ends.\n setCursor((prev) => (prev ? { ...prev, status: \"Standing by\", glideMs: 0 } : prev));\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 // Keep off-screen targets represented at the nearest viewport edge, then\n // glide at a distance-aware pace that a watching human can comfortably\n // follow. This is presence, not a teleport animation.\n const target = visibleCursorPoint(rect, { width: window.innerWidth, height: window.innerHeight });\n const reduceMotion = window.matchMedia?.(\"(prefers-reduced-motion: reduce)\").matches ?? false;\n setCursor((prev) => ({\n ...target,\n name,\n color,\n status,\n glideMs: reduceMotion ? 0 : fluidGlideDuration(prev, target),\n }));\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, glideMs: 0 },\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={{\n transition: cursor.glideMs\n ? `left ${cursor.glideMs}ms cubic-bezier(.22,.61,.36,1), top ${cursor.glideMs}ms cubic-bezier(.22,.61,.36,1)`\n : \"none\",\n }}\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 // Scheme allow-list: permit only same-site/relative paths and http(s)\n // absolutes. A `javascript:` / `data:` / `file:` / `vbscript:` URL handed\n // to a host that wires visit() to window.location would execute as the\n // human — a semi-trusted agent (steerable via page_read prompt injection)\n // must not reach those.\n const scheme = /^([a-zA-Z][a-zA-Z0-9+.-]*):/.exec(url)?.[1]?.toLowerCase();\n if (scheme && scheme !== \"http\" && scheme !== \"https\") {\n return errorResult(\n `Refusing to navigate to a '${scheme}:' URL. Only http(s) URLs or same-site paths are allowed.`,\n );\n }\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\nconst CURSOR_EDGE_INSET = 24;\nconst FLUID_CURSOR_SPEED_PX_PER_SECOND = 1_050;\nconst MIN_GLIDE_MS = 240;\nconst MAX_GLIDE_MS = 1_200;\n\nexport function visibleCursorPoint(rect: Rect, viewport: { width: number; height: number }) {\n const x = rect.x + rect.width / 2;\n const y = rect.y + rect.height / 2;\n return {\n x: Math.min(Math.max(x, CURSOR_EDGE_INSET), Math.max(CURSOR_EDGE_INSET, viewport.width - CURSOR_EDGE_INSET)),\n y: Math.min(Math.max(y, CURSOR_EDGE_INSET), Math.max(CURSOR_EDGE_INSET, viewport.height - CURSOR_EDGE_INSET)),\n };\n}\n\nexport function fluidGlideDuration(from: { x: number; y: number } | null, to: { x: number; y: number }) {\n if (!from) return 0;\n const distance = Math.hypot(to.x - from.x, to.y - from.y);\n return Math.round(Math.min(MAX_GLIDE_MS, Math.max(MIN_GLIDE_MS, (distance / FLUID_CURSOR_SPEED_PX_PER_SECOND) * 1_000)));\n}\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; glideMs: number } | 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 // Relay clients may be intentionally short-lived (one process per MCP\n // call). The shared session is the presence boundary, not an individual\n // transport connection, so leave the agent's cursor in place between\n // calls. `active=false` still removes it when sharing actually ends.\n setCursor((prev) => (prev ? { ...prev, status: \"Standing by\", glideMs: 0 } : prev));\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 // Keep off-screen targets represented at the nearest viewport edge, then\n // glide at a distance-aware pace that a watching human can comfortably\n // follow. This is presence, not a teleport animation.\n const target = visibleCursorPoint(rect, { width: window.innerWidth, height: window.innerHeight });\n const reduceMotion = window.matchMedia?.(\"(prefers-reduced-motion: reduce)\").matches ?? false;\n setCursor((prev) => ({\n ...target,\n name,\n color,\n status,\n glideMs: reduceMotion ? 0 : fluidGlideDuration(prev, target),\n }));\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, glideMs: 0 },\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={{\n transition: cursor.glideMs\n ? `left ${cursor.glideMs}ms cubic-bezier(.22,.61,.36,1), top ${cursor.glideMs}ms cubic-bezier(.22,.61,.36,1)`\n : \"none\",\n }}\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"]}
|
|
@@ -52,6 +52,13 @@ declare function wrapToolWithActivity<TArgs = Record<string, unknown>>(handler:
|
|
|
52
52
|
resolveTarget?: ActivityTargetResolver<TArgs>;
|
|
53
53
|
/** Optional ttl override. */
|
|
54
54
|
ttlMs?: number;
|
|
55
|
+
/**
|
|
56
|
+
* Build the `meta` broadcast to all relay peers. Defaults to the tool's full
|
|
57
|
+
* `structuredContent`. Override to REDACT sensitive fields before fan-out —
|
|
58
|
+
* e.g. the terminal bridge strips raw command/keystroke bytes so a command
|
|
59
|
+
* line (or its secrets) is never broadcast verbatim to every peer.
|
|
60
|
+
*/
|
|
61
|
+
buildMeta?: (result: CallToolResult) => Record<string, unknown> | undefined;
|
|
55
62
|
}): ToolHandler<TArgs>;
|
|
56
63
|
|
|
57
64
|
/**
|
package/dist/presence/index.d.ts
CHANGED
|
@@ -52,6 +52,13 @@ declare function wrapToolWithActivity<TArgs = Record<string, unknown>>(handler:
|
|
|
52
52
|
resolveTarget?: ActivityTargetResolver<TArgs>;
|
|
53
53
|
/** Optional ttl override. */
|
|
54
54
|
ttlMs?: number;
|
|
55
|
+
/**
|
|
56
|
+
* Build the `meta` broadcast to all relay peers. Defaults to the tool's full
|
|
57
|
+
* `structuredContent`. Override to REDACT sensitive fields before fan-out —
|
|
58
|
+
* e.g. the terminal bridge strips raw command/keystroke bytes so a command
|
|
59
|
+
* line (or its secrets) is never broadcast verbatim to every peer.
|
|
60
|
+
*/
|
|
61
|
+
buildMeta?: (result: CallToolResult) => Record<string, unknown> | undefined;
|
|
55
62
|
}): ToolHandler<TArgs>;
|
|
56
63
|
|
|
57
64
|
/**
|
package/dist/presence.cjs
CHANGED
|
@@ -24,7 +24,7 @@ function wrapToolWithActivity(handler, options) {
|
|
|
24
24
|
target: { ...target, kind: target.kind ?? options.kind, screenId: target.screenId ?? options.screenId },
|
|
25
25
|
action: options.toolName,
|
|
26
26
|
timestamp: Date.now(),
|
|
27
|
-
meta: extractMeta(result),
|
|
27
|
+
meta: options.buildMeta ? options.buildMeta(result) : extractMeta(result),
|
|
28
28
|
ttlMs: options.ttlMs
|
|
29
29
|
});
|
|
30
30
|
return result;
|
package/dist/presence.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/presence/wrap-tool-with-activity.ts","../src/presence/use-agent-activity.ts"],"names":["emitActivity","useState","readActivityHistory","useEffect","onActivity"],"mappings":";;;;;;;;AA+CO,SAAS,oBAAA,CACd,SACA,OAAA,
|
|
1
|
+
{"version":3,"sources":["../src/presence/wrap-tool-with-activity.ts","../src/presence/use-agent-activity.ts"],"names":["emitActivity","useState","readActivityHistory","useEffect","onActivity"],"mappings":"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","file":"presence.cjs","sourcesContent":["import type { CallToolResult } from \"../mcp/types\";\nimport { emitActivity } from \"./registry\";\nimport type { AgentTarget } from \"./types\";\n\nexport type ActivityAgent = { id: string; name?: string; color?: string };\n\nexport type ActivityResolverContext<TArgs = Record<string, unknown>> = {\n /** Tool name as registered. */\n toolName: string;\n /** Arguments the tool was called with. */\n args: TArgs;\n /** The CallToolResult the underlying handler produced. */\n result: CallToolResult;\n};\n\n/**\n * Resolves an `AgentTarget` for an executed tool. Bridges declare one of\n * these per registration so the wrapper knows which surface / element /\n * screen the activity belongs to.\n *\n * The resolver runs AFTER the tool handler so it can inspect the result\n * (e.g. read a newly-created item id from `structuredContent`).\n */\nexport type ActivityTargetResolver<TArgs = Record<string, unknown>> = (\n ctx: ActivityResolverContext<TArgs>,\n) => AgentTarget | null;\n\nexport type ToolHandler<TArgs = Record<string, unknown>> = (\n args: TArgs,\n) => Promise<CallToolResult> | CallToolResult;\n\n/**\n * wrapToolWithActivity — decorate a bridge tool handler so every successful\n * call emits an `AgentActivityEvent`. Returns a new handler with the same shape.\n *\n * Usage in a bridge:\n *\n * server.registerTool(\n * definition,\n * wrapToolWithActivity(\n * handler,\n * { agent, kind: \"whiteboard\", resolveTarget: ({ args }) => ({\n * kind: \"whiteboard\", elementId: args.id as string,\n * }) },\n * ),\n * );\n */\nexport function wrapToolWithActivity<TArgs = Record<string, unknown>>(\n handler: ToolHandler<TArgs>,\n options: {\n toolName: string;\n agent: ActivityAgent;\n /** Optional fancy-screens screen id this bridge is scoped to. */\n screenId?: string;\n /** Default target kind if the resolver returns one without `kind`. */\n kind: AgentTarget[\"kind\"];\n /** Per-call resolver. Return `null` to skip emitting (e.g. for read-only tools). */\n resolveTarget?: ActivityTargetResolver<TArgs>;\n /** Optional ttl override. */\n ttlMs?: number;\n /**\n * Build the `meta` broadcast to all relay peers. Defaults to the tool's full\n * `structuredContent`. Override to REDACT sensitive fields before fan-out —\n * e.g. the terminal bridge strips raw command/keystroke bytes so a command\n * line (or its secrets) is never broadcast verbatim to every peer.\n */\n buildMeta?: (result: CallToolResult) => Record<string, unknown> | undefined;\n },\n): ToolHandler<TArgs> {\n return async (args) => {\n const result = await handler(args);\n if (result.isError) return result;\n\n let target: AgentTarget | null;\n if (options.resolveTarget) {\n target = options.resolveTarget({ toolName: options.toolName, args, result });\n } else {\n target = { kind: options.kind, screenId: options.screenId };\n }\n if (!target) return result;\n\n emitActivity({\n agentId: options.agent.id,\n agentName: options.agent.name,\n agentColor: options.agent.color,\n target: { ...target, kind: target.kind ?? options.kind, screenId: target.screenId ?? options.screenId },\n action: options.toolName,\n timestamp: Date.now(),\n meta: options.buildMeta ? options.buildMeta(result) : extractMeta(result),\n ttlMs: options.ttlMs,\n });\n return result;\n };\n}\n\nfunction extractMeta(result: CallToolResult): Record<string, unknown> | undefined {\n const sc = result.structuredContent;\n if (sc && typeof sc === \"object\" && !Array.isArray(sc)) {\n return sc as Record<string, unknown>;\n }\n return undefined;\n}\n","import { useEffect, useState } from \"react\";\nimport { onActivity, readActivityHistory } from \"./registry\";\nimport type { ActivityFilter, AgentActivityEvent } from \"./types\";\n\n/**\n * useAgentActivity — React subscription to the in-process activity stream.\n *\n * Returns:\n * - `events`: capped scrollback of recent events matching the filter\n * - `latest`: the most recent event (handy for transient highlights)\n */\nexport function useAgentActivity(\n filter?: ActivityFilter,\n options: { capacity?: number } = {},\n): { events: AgentActivityEvent[]; latest: AgentActivityEvent | null } {\n const cap = options.capacity ?? 50;\n const [events, setEvents] = useState<AgentActivityEvent[]>(() => readActivityHistory(filter).slice(-cap));\n\n useEffect(() => {\n setEvents(readActivityHistory(filter).slice(-cap));\n return onActivity((event) => {\n setEvents((prev) => {\n const next = prev.length >= cap ? prev.slice(prev.length - cap + 1) : prev.slice();\n next.push(event);\n return next;\n });\n }, filter);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [filter?.agentId, filter?.screenId, filter?.kind, cap]);\n\n return { events, latest: events.length > 0 ? events[events.length - 1] : null };\n}\n\n/**\n * useAgentActivityForScreen — convenience wrapper that filters by screen id.\n * Drives \"agent is here\" badges in fancy-screens-based shells.\n */\nexport function useAgentActivityForScreen(\n screenId: string,\n options: { capacity?: number } = {},\n): { events: AgentActivityEvent[]; latest: AgentActivityEvent | null; isAgentActive: boolean } {\n const { events, latest } = useAgentActivity({ screenId }, options);\n const fadeAfter = latest?.ttlMs ?? 1500;\n const [isAgentActive, setActive] = useState(false);\n\n useEffect(() => {\n if (!latest) {\n setActive(false);\n return;\n }\n setActive(true);\n const timer = setTimeout(() => setActive(false), fadeAfter);\n return () => clearTimeout(timer);\n }, [latest, fadeAfter]);\n\n return { events, latest, isAgentActive };\n}\n"]}
|
package/dist/presence.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { useAgentActivity, useAgentActivityForScreen } from './chunk-UCKJAUBY.js';
|
|
2
|
-
export { wrapToolWithActivity } from './chunk-
|
|
2
|
+
export { wrapToolWithActivity } from './chunk-2VENWGLZ.js';
|
|
3
3
|
export { emitActivity, onActivity, readActivityHistory, resetActivityRegistry } from './chunk-C3TYI5TJ.js';
|
|
4
4
|
//# sourceMappingURL=presence.js.map
|
|
5
5
|
//# sourceMappingURL=presence.js.map
|
|
@@ -77,7 +77,18 @@ declare class RelayBroker {
|
|
|
77
77
|
subscribe(id: string, token: string, direction: Direction): SubscribeResult;
|
|
78
78
|
private getDirSubs;
|
|
79
79
|
private fanOut;
|
|
80
|
+
/**
|
|
81
|
+
* Validate that a peer-supplied payload is a well-formed JSON-RPC 2.0 frame
|
|
82
|
+
* (or batch) before it is fanned out. Previously this was a substring match on
|
|
83
|
+
* `"jsonrpc"`, which let any token holder inject spoofed frames — a forged
|
|
84
|
+
* `notifications/peer_joined` / `peer_left` (broker-reserved presence control),
|
|
85
|
+
* a fake `notifications/agent_activity {source:"user"}` ("human took control"),
|
|
86
|
+
* or a forged response with a matching id. We now parse + shape-check, and
|
|
87
|
+
* reject the broker-reserved control methods (the broker emits those itself,
|
|
88
|
+
* never a peer).
|
|
89
|
+
*/
|
|
80
90
|
private isFrame;
|
|
91
|
+
private isValidFrame;
|
|
81
92
|
private reap;
|
|
82
93
|
}
|
|
83
94
|
type SubscribeResult = {
|
|
@@ -114,6 +125,15 @@ type NodeRelayOptions = RelayBrokerOptions & {
|
|
|
114
125
|
/** Comma-separated origins (or `*`) for CORS. Default `*` — relays
|
|
115
126
|
* are typically called cross-origin from the demo host. */
|
|
116
127
|
corsAllowOrigin?: string;
|
|
128
|
+
/**
|
|
129
|
+
* Strict browser-origin allow-list. When set, only these Origins get a
|
|
130
|
+
* matching `Access-Control-Allow-Origin` (the request's own Origin is
|
|
131
|
+
* reflected, never `*`), which blunts DNS-rebinding + hostile cross-origin
|
|
132
|
+
* pages from reading relay responses. Recommended for any browser-facing
|
|
133
|
+
* deployment. When unset, `corsAllowOrigin` (default `*`) is used and the
|
|
134
|
+
* session token is the only auth — pair that with a loopback bind.
|
|
135
|
+
*/
|
|
136
|
+
allowedOrigins?: string[];
|
|
117
137
|
};
|
|
118
138
|
type NodeHandler = (req: IncomingMessage, res: ServerResponse) => unknown | Promise<unknown>;
|
|
119
139
|
type NodeRelay = {
|
|
@@ -77,7 +77,18 @@ declare class RelayBroker {
|
|
|
77
77
|
subscribe(id: string, token: string, direction: Direction): SubscribeResult;
|
|
78
78
|
private getDirSubs;
|
|
79
79
|
private fanOut;
|
|
80
|
+
/**
|
|
81
|
+
* Validate that a peer-supplied payload is a well-formed JSON-RPC 2.0 frame
|
|
82
|
+
* (or batch) before it is fanned out. Previously this was a substring match on
|
|
83
|
+
* `"jsonrpc"`, which let any token holder inject spoofed frames — a forged
|
|
84
|
+
* `notifications/peer_joined` / `peer_left` (broker-reserved presence control),
|
|
85
|
+
* a fake `notifications/agent_activity {source:"user"}` ("human took control"),
|
|
86
|
+
* or a forged response with a matching id. We now parse + shape-check, and
|
|
87
|
+
* reject the broker-reserved control methods (the broker emits those itself,
|
|
88
|
+
* never a peer).
|
|
89
|
+
*/
|
|
80
90
|
private isFrame;
|
|
91
|
+
private isValidFrame;
|
|
81
92
|
private reap;
|
|
82
93
|
}
|
|
83
94
|
type SubscribeResult = {
|
|
@@ -114,6 +125,15 @@ type NodeRelayOptions = RelayBrokerOptions & {
|
|
|
114
125
|
/** Comma-separated origins (or `*`) for CORS. Default `*` — relays
|
|
115
126
|
* are typically called cross-origin from the demo host. */
|
|
116
127
|
corsAllowOrigin?: string;
|
|
128
|
+
/**
|
|
129
|
+
* Strict browser-origin allow-list. When set, only these Origins get a
|
|
130
|
+
* matching `Access-Control-Allow-Origin` (the request's own Origin is
|
|
131
|
+
* reflected, never `*`), which blunts DNS-rebinding + hostile cross-origin
|
|
132
|
+
* pages from reading relay responses. Recommended for any browser-facing
|
|
133
|
+
* deployment. When unset, `corsAllowOrigin` (default `*`) is used and the
|
|
134
|
+
* session token is the only auth — pair that with a loopback bind.
|
|
135
|
+
*/
|
|
136
|
+
allowedOrigins?: string[];
|
|
117
137
|
};
|
|
118
138
|
type NodeHandler = (req: IncomingMessage, res: ServerResponse) => unknown | Promise<unknown>;
|
|
119
139
|
type NodeRelay = {
|