@particle-academy/agent-integrations 0.15.0 → 0.17.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/dist/{chunk-GJSKBUOH.js → chunk-YEEOTIGY.js} +46 -5
- package/dist/chunk-YEEOTIGY.js.map +1 -0
- package/dist/components-shared-whiteboard.cjs +43 -2
- package/dist/components-shared-whiteboard.cjs.map +1 -1
- package/dist/components-shared-whiteboard.js +1 -1
- package/dist/index.cjs +105 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +42 -1
- package/dist/index.d.ts +42 -1
- package/dist/index.js +63 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-GJSKBUOH.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ShareControls, AgentCursor, AgentActivityHighlight, AgentPanel } from './chunk-
|
|
1
|
+
import { ShareControls, AgentCursor, AgentActivityHighlight, AgentPanel } from './chunk-YEEOTIGY.js';
|
|
2
2
|
import { createSessionDescriptor, attachSseRelay } from './chunk-CPNOF4HI.js';
|
|
3
3
|
import { attachInProcess } from './chunk-AFUULW5E.js';
|
|
4
4
|
import { registerWhiteboardBridge } from './chunk-3QJSOS7G.js';
|
package/dist/index.cjs
CHANGED
|
@@ -4,6 +4,7 @@ var fancyAutoCommon = require('@particle-academy/fancy-auto-common');
|
|
|
4
4
|
var react = require('react');
|
|
5
5
|
var fancySlides = require('@particle-academy/fancy-slides');
|
|
6
6
|
var jsxRuntime = require('react/jsx-runtime');
|
|
7
|
+
var reactDom = require('react-dom');
|
|
7
8
|
|
|
8
9
|
var __defProp = Object.defineProperty;
|
|
9
10
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -2342,12 +2343,13 @@ function registerNavigationBridge(host, options) {
|
|
|
2342
2343
|
},
|
|
2343
2344
|
[],
|
|
2344
2345
|
(args) => {
|
|
2346
|
+
const handle = typeof args.handle === "string" ? args.handle : void 0;
|
|
2345
2347
|
adapter.scrollTo({
|
|
2346
|
-
handle
|
|
2348
|
+
handle,
|
|
2347
2349
|
x: typeof args.x === "number" ? args.x : void 0,
|
|
2348
2350
|
y: typeof args.y === "number" ? args.y : void 0
|
|
2349
2351
|
});
|
|
2350
|
-
return textResult("Scrolled");
|
|
2352
|
+
return textResult("Scrolled", handle ? { handle, rect: adapter.rectFor?.(handle) ?? void 0 } : void 0);
|
|
2351
2353
|
},
|
|
2352
2354
|
() => target("Scroll")
|
|
2353
2355
|
);
|
|
@@ -2374,7 +2376,7 @@ function registerNavigationBridge(host, options) {
|
|
|
2374
2376
|
const handle = String(args.handle ?? "");
|
|
2375
2377
|
const res = adapter.setField(handle, args.value);
|
|
2376
2378
|
if (!res.ok) return errorResult(res.error ?? `Could not set ${handle}`);
|
|
2377
|
-
return textResult(`${handle} \u2190 ${JSON.stringify(args.value)}`, { handle, value: args.value });
|
|
2379
|
+
return textResult(`${handle} \u2190 ${JSON.stringify(args.value)}`, { handle, value: args.value, rect: adapter.rectFor?.(handle) ?? void 0 });
|
|
2378
2380
|
},
|
|
2379
2381
|
(args) => target(`Set ${String(args.handle ?? "")}`, String(args.handle ?? ""))
|
|
2380
2382
|
);
|
|
@@ -2386,13 +2388,14 @@ function registerNavigationBridge(host, options) {
|
|
|
2386
2388
|
async (args) => {
|
|
2387
2389
|
const handle = String(args.handle ?? "");
|
|
2388
2390
|
const action = adapter.describe().actions.find((a) => a.handle === handle);
|
|
2391
|
+
const rect = adapter.rectFor?.(handle) ?? void 0;
|
|
2389
2392
|
if (pendingMode && action?.destructive && adapter.confirm) {
|
|
2390
2393
|
const ok = await adapter.confirm({ action: "click", handle, label: action.label });
|
|
2391
2394
|
if (!ok) return errorResult("Declined by user");
|
|
2392
2395
|
}
|
|
2393
2396
|
const res = adapter.click(handle);
|
|
2394
2397
|
if (!res.ok) return errorResult(res.error ?? `Could not click ${handle}`);
|
|
2395
|
-
return textResult(`Clicked ${handle}`, { handle });
|
|
2398
|
+
return textResult(`Clicked ${handle}`, { handle, rect });
|
|
2396
2399
|
},
|
|
2397
2400
|
(args) => target(`Click ${String(args.handle ?? "")}`, String(args.handle ?? ""))
|
|
2398
2401
|
);
|
|
@@ -2403,13 +2406,14 @@ function registerNavigationBridge(host, options) {
|
|
|
2403
2406
|
["handle"],
|
|
2404
2407
|
async (args) => {
|
|
2405
2408
|
const handle = String(args.handle ?? "");
|
|
2409
|
+
const rect = adapter.rectFor?.(handle) ?? void 0;
|
|
2406
2410
|
if (pendingMode && adapter.confirm) {
|
|
2407
2411
|
const ok = await adapter.confirm({ action: "submit", handle, label: handle });
|
|
2408
2412
|
if (!ok) return errorResult("Declined by user");
|
|
2409
2413
|
}
|
|
2410
2414
|
const res = await adapter.submit(handle);
|
|
2411
2415
|
if (!res.ok) return errorResult(res.error ?? "Submit failed");
|
|
2412
|
-
return textResult(`Submitted ${handle}`, { handle });
|
|
2416
|
+
return textResult(`Submitted ${handle}`, { handle, rect });
|
|
2413
2417
|
},
|
|
2414
2418
|
(args) => target(`Submit ${String(args.handle ?? "")}`, String(args.handle ?? ""))
|
|
2415
2419
|
);
|
|
@@ -2936,16 +2940,21 @@ function ShareControls({
|
|
|
2936
2940
|
className,
|
|
2937
2941
|
style
|
|
2938
2942
|
}) {
|
|
2939
|
-
const [tab, setTab] = react.useState("
|
|
2943
|
+
const [tab, setTab] = react.useState("prompt");
|
|
2940
2944
|
if (!session) {
|
|
2941
2945
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ["fai-share fai-share--idle", className ?? ""].filter(Boolean).join(" "), style, children: [
|
|
2942
2946
|
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "fai-share__start", onClick: onStart, children: "Start shared session" }),
|
|
2943
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2947
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "fai-share__hint", children: [
|
|
2948
|
+
"Generates a session id + secret token. Hand the ",
|
|
2949
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Agent prompt" }),
|
|
2950
|
+
" to an AI agent, share the URL with humans, or give the JSON config to an MCP-capable client."
|
|
2951
|
+
] })
|
|
2944
2952
|
] });
|
|
2945
2953
|
}
|
|
2946
2954
|
const url = buildShareUrl(session, shareBaseUrl);
|
|
2947
2955
|
const config = buildShareConfig(session);
|
|
2948
2956
|
const curl = buildCurlRecipe(session);
|
|
2957
|
+
const prompt = buildAgentPrompt(url);
|
|
2949
2958
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ["fai-share fai-share--active", className ?? ""].filter(Boolean).join(" "), style, children: [
|
|
2950
2959
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fai-share__header", children: [
|
|
2951
2960
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
@@ -2966,11 +2975,20 @@ function ShareControls({
|
|
|
2966
2975
|
] })
|
|
2967
2976
|
] }),
|
|
2968
2977
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fai-share__tabs", role: "tablist", children: [
|
|
2978
|
+
/* @__PURE__ */ jsxRuntime.jsx(TabButton, { tab: "prompt", active: tab, setTab, children: "Agent prompt" }),
|
|
2969
2979
|
/* @__PURE__ */ jsxRuntime.jsx(TabButton, { tab: "url", active: tab, setTab, children: "URL" }),
|
|
2970
2980
|
/* @__PURE__ */ jsxRuntime.jsx(TabButton, { tab: "json", active: tab, setTab, children: "JSON" }),
|
|
2971
2981
|
/* @__PURE__ */ jsxRuntime.jsx(TabButton, { tab: "curl", active: tab, setTab, children: "cURL recipe" })
|
|
2972
2982
|
] }),
|
|
2973
2983
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fai-share__panel", children: [
|
|
2984
|
+
tab === "prompt" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2985
|
+
CopyBox,
|
|
2986
|
+
{
|
|
2987
|
+
label: "Paste this straight into an AI agent \u2014 it connects over MCP, no browser",
|
|
2988
|
+
value: prompt,
|
|
2989
|
+
multiline: true
|
|
2990
|
+
}
|
|
2991
|
+
),
|
|
2974
2992
|
tab === "url" && /* @__PURE__ */ jsxRuntime.jsx(CopyBox, { label: "Open this URL in another tab to join the session", value: url }),
|
|
2975
2993
|
tab === "json" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2976
2994
|
CopyBox,
|
|
@@ -3021,6 +3039,33 @@ function CopyBox({ label, value, multiline }) {
|
|
|
3021
3039
|
] })
|
|
3022
3040
|
] });
|
|
3023
3041
|
}
|
|
3042
|
+
function buildAgentPrompt(url) {
|
|
3043
|
+
return [
|
|
3044
|
+
`You're joining a live Human+ co-browsing session on a web app. This is an MCP`,
|
|
3045
|
+
`(Model Context Protocol) session \u2014 NOT a website to visit. Do NOT open the URL`,
|
|
3046
|
+
`in a browser and do NOT use any browser/Playwright tool. You drive the real,`,
|
|
3047
|
+
`running app through MCP tools while a human watches and can take over.`,
|
|
3048
|
+
``,
|
|
3049
|
+
`Session link (carries the session id + token \u2014 treat it as a secret):`,
|
|
3050
|
+
` ${url}`,
|
|
3051
|
+
``,
|
|
3052
|
+
`Connect by running the relay client as an MCP server (zero install):`,
|
|
3053
|
+
` npx -y mcp-relay-client "${url}"`,
|
|
3054
|
+
``,
|
|
3055
|
+
`That exposes the app's own tools (e.g. page_describe, page_read, nav_visit,`,
|
|
3056
|
+
`page_click, page_set_field, page_submit, plus surface tools like whiteboard_*).`,
|
|
3057
|
+
`Then:`,
|
|
3058
|
+
` 1. Call page_describe first to see the current page and its interactive handles.`,
|
|
3059
|
+
` 2. Act only on the STABLE HANDLES the tools return \u2014 never guess DOM selectors.`,
|
|
3060
|
+
` 3. Navigate with nav_visit, type with page_set_field, click with page_click.`,
|
|
3061
|
+
` Submits and destructive clicks are staged for the human to confirm.`,
|
|
3062
|
+
``,
|
|
3063
|
+
`If you can't register an MCP server but can run a shell, drive it directly:`,
|
|
3064
|
+
` curl -O https://raw.githubusercontent.com/Particle-Academy/mcp-relay-client/main/connect.sh`,
|
|
3065
|
+
` bash connect.sh "${url}" tools`,
|
|
3066
|
+
` bash connect.sh "${url}" call page_describe '{}'`
|
|
3067
|
+
].join("\n");
|
|
3068
|
+
}
|
|
3024
3069
|
function buildCurlRecipe(session) {
|
|
3025
3070
|
const base = typeof window !== "undefined" ? `${window.location.protocol}//${window.location.host}` : "http://localhost";
|
|
3026
3071
|
const inbox = `${base}/agent-relay/${session.id}/inbox?token=${session.token}`;
|
|
@@ -3383,6 +3428,57 @@ function CoBrowsePresence({ session, connectUrl, shareBaseUrl, className }) {
|
|
|
3383
3428
|
] });
|
|
3384
3429
|
}
|
|
3385
3430
|
CoBrowsePresence.displayName = "CoBrowsePresence";
|
|
3431
|
+
function CoBrowseCursorLayer({ active = true, zIndex = 2147483e3 }) {
|
|
3432
|
+
const { latest } = useAgentActivity(void 0, { capacity: 12 });
|
|
3433
|
+
const [cursor, setCursor] = react.useState(
|
|
3434
|
+
null
|
|
3435
|
+
);
|
|
3436
|
+
const [pulse, setPulse] = react.useState(null);
|
|
3437
|
+
react.useEffect(() => {
|
|
3438
|
+
if (!latest || (latest.source ?? "agent") === "user") return;
|
|
3439
|
+
const color = latest.agentColor ?? "#a855f7";
|
|
3440
|
+
const name = latest.agentName ?? "Agent";
|
|
3441
|
+
const status = latest.target?.label ?? latest.action;
|
|
3442
|
+
const rect = latest.meta?.rect;
|
|
3443
|
+
if (rect) {
|
|
3444
|
+
setCursor({ x: rect.x + rect.width / 2, y: rect.y + rect.height / 2, name, color, status });
|
|
3445
|
+
setPulse({ rect, color, key: latest.timestamp });
|
|
3446
|
+
} else {
|
|
3447
|
+
setCursor(
|
|
3448
|
+
(prev) => prev ? { ...prev, status, name, color } : { x: window.innerWidth / 2, y: window.innerHeight / 2, name, color, status }
|
|
3449
|
+
);
|
|
3450
|
+
}
|
|
3451
|
+
}, [latest?.timestamp]);
|
|
3452
|
+
if (!active || !cursor || typeof document === "undefined") return null;
|
|
3453
|
+
return reactDom.createPortal(
|
|
3454
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { "data-co-browse-cursor-layer": "", style: { position: "fixed", inset: 0, pointerEvents: "none", zIndex }, children: [
|
|
3455
|
+
pulse && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3456
|
+
AgentActivityHighlight,
|
|
3457
|
+
{
|
|
3458
|
+
x: pulse.rect.x,
|
|
3459
|
+
y: pulse.rect.y,
|
|
3460
|
+
width: pulse.rect.width,
|
|
3461
|
+
height: pulse.rect.height,
|
|
3462
|
+
color: pulse.color,
|
|
3463
|
+
pulseKey: pulse.key
|
|
3464
|
+
}
|
|
3465
|
+
),
|
|
3466
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3467
|
+
AgentCursor,
|
|
3468
|
+
{
|
|
3469
|
+
x: cursor.x,
|
|
3470
|
+
y: cursor.y,
|
|
3471
|
+
name: cursor.name,
|
|
3472
|
+
color: cursor.color,
|
|
3473
|
+
status: cursor.status,
|
|
3474
|
+
style: { transition: "left .35s cubic-bezier(.22,.61,.36,1), top .35s cubic-bezier(.22,.61,.36,1)" }
|
|
3475
|
+
}
|
|
3476
|
+
)
|
|
3477
|
+
] }),
|
|
3478
|
+
document.body
|
|
3479
|
+
);
|
|
3480
|
+
}
|
|
3481
|
+
CoBrowseCursorLayer.displayName = "CoBrowseCursorLayer";
|
|
3386
3482
|
|
|
3387
3483
|
// src/presence/index.ts
|
|
3388
3484
|
init_registry();
|
|
@@ -3512,6 +3608,7 @@ exports.CLAUDE_CONNECTORS_URL = CLAUDE_CONNECTORS_URL;
|
|
|
3512
3608
|
exports.CONNECTOR_GLYPHS = CONNECTOR_GLYPHS;
|
|
3513
3609
|
exports.CONNECTOR_TARGETS = CONNECTOR_TARGETS;
|
|
3514
3610
|
exports.ClaudeMark = ClaudeMark;
|
|
3611
|
+
exports.CoBrowseCursorLayer = CoBrowseCursorLayer;
|
|
3515
3612
|
exports.CoBrowsePresence = CoBrowsePresence;
|
|
3516
3613
|
exports.ConnectorButtons = ConnectorButtons;
|
|
3517
3614
|
exports.CursorMark = CursorMark;
|
|
@@ -3532,6 +3629,7 @@ exports.WrenchMark = WrenchMark;
|
|
|
3532
3629
|
exports.attachInProcess = attachInProcess;
|
|
3533
3630
|
exports.attachRelay = attachRelay;
|
|
3534
3631
|
exports.attachSseRelay = attachSseRelay;
|
|
3632
|
+
exports.buildAgentPrompt = buildAgentPrompt;
|
|
3535
3633
|
exports.buildCursorDeeplink = buildCursorDeeplink;
|
|
3536
3634
|
exports.buildManualConfig = buildManualConfig;
|
|
3537
3635
|
exports.buildManualConfigSnippet = buildManualConfigSnippet;
|