@particle-academy/agent-integrations 0.28.0 → 0.28.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +65 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +65 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2772,6 +2772,17 @@ function registerNavigationBridge(host, options) {
|
|
|
2772
2772
|
const agent = { ...DEFAULT_AGENT11, ...options.agent ?? {} };
|
|
2773
2773
|
const pendingMode = options.pendingMode ?? true;
|
|
2774
2774
|
const disposers = [];
|
|
2775
|
+
let groundedRevision = null;
|
|
2776
|
+
const staleIntent = () => {
|
|
2777
|
+
const current = adapter.getRevision?.();
|
|
2778
|
+
if (current === void 0) return null;
|
|
2779
|
+
if (groundedRevision === null || groundedRevision !== current) {
|
|
2780
|
+
return errorResult(
|
|
2781
|
+
`Human took control at page revision ${current}. This agent action was cancelled; call page_describe before acting again.`
|
|
2782
|
+
);
|
|
2783
|
+
}
|
|
2784
|
+
return null;
|
|
2785
|
+
};
|
|
2775
2786
|
ensureUndoToolsRegistered(host, { defaultAgentId: agent.id });
|
|
2776
2787
|
const target = (label, elementId) => ({
|
|
2777
2788
|
kind: "navigation",
|
|
@@ -2812,6 +2823,11 @@ function registerNavigationBridge(host, options) {
|
|
|
2812
2823
|
[],
|
|
2813
2824
|
() => {
|
|
2814
2825
|
const snap = adapter.describe();
|
|
2826
|
+
const revision = adapter.getRevision?.();
|
|
2827
|
+
if (revision !== void 0) {
|
|
2828
|
+
snap.revision = revision;
|
|
2829
|
+
groundedRevision = revision;
|
|
2830
|
+
}
|
|
2815
2831
|
const text = [
|
|
2816
2832
|
`URL: ${snap.url}`,
|
|
2817
2833
|
`Title: ${snap.title}`,
|
|
@@ -2836,6 +2852,8 @@ function registerNavigationBridge(host, options) {
|
|
|
2836
2852
|
{ handle: { type: "string" } },
|
|
2837
2853
|
["handle"],
|
|
2838
2854
|
(args) => {
|
|
2855
|
+
const stale = staleIntent();
|
|
2856
|
+
if (stale) return stale;
|
|
2839
2857
|
const handle = String(args.handle ?? "");
|
|
2840
2858
|
const action = adapter.describe().actions.find((candidate) => candidate.handle === handle);
|
|
2841
2859
|
if (!action) return errorResult(`No element for handle "${handle}"`);
|
|
@@ -2852,6 +2870,8 @@ function registerNavigationBridge(host, options) {
|
|
|
2852
2870
|
{ url: { type: "string", description: "Path like /packages or an absolute URL." } },
|
|
2853
2871
|
["url"],
|
|
2854
2872
|
async (args) => {
|
|
2873
|
+
const stale = staleIntent();
|
|
2874
|
+
if (stale) return stale;
|
|
2855
2875
|
const url = String(args.url ?? "");
|
|
2856
2876
|
if (!url) return errorResult("url is required");
|
|
2857
2877
|
const from = adapter.getLocation().url;
|
|
@@ -2878,6 +2898,8 @@ function registerNavigationBridge(host, options) {
|
|
|
2878
2898
|
{},
|
|
2879
2899
|
[],
|
|
2880
2900
|
async () => {
|
|
2901
|
+
const stale = staleIntent();
|
|
2902
|
+
if (stale) return stale;
|
|
2881
2903
|
if (!adapter.back) return errorResult("Host did not provide back navigation.");
|
|
2882
2904
|
await adapter.back();
|
|
2883
2905
|
return textResult("Went back");
|
|
@@ -2890,6 +2912,8 @@ function registerNavigationBridge(host, options) {
|
|
|
2890
2912
|
{},
|
|
2891
2913
|
[],
|
|
2892
2914
|
async () => {
|
|
2915
|
+
const stale = staleIntent();
|
|
2916
|
+
if (stale) return stale;
|
|
2893
2917
|
if (!adapter.forward) return errorResult("Host did not provide forward navigation.");
|
|
2894
2918
|
await adapter.forward();
|
|
2895
2919
|
return textResult("Went forward");
|
|
@@ -2906,6 +2930,8 @@ function registerNavigationBridge(host, options) {
|
|
|
2906
2930
|
},
|
|
2907
2931
|
[],
|
|
2908
2932
|
(args) => {
|
|
2933
|
+
const stale = staleIntent();
|
|
2934
|
+
if (stale) return stale;
|
|
2909
2935
|
const handle = typeof args.handle === "string" ? args.handle : void 0;
|
|
2910
2936
|
adapter.scrollTo({
|
|
2911
2937
|
handle,
|
|
@@ -2922,6 +2948,8 @@ function registerNavigationBridge(host, options) {
|
|
|
2922
2948
|
{ dy: { type: "number" } },
|
|
2923
2949
|
["dy"],
|
|
2924
2950
|
(args) => {
|
|
2951
|
+
const stale = staleIntent();
|
|
2952
|
+
if (stale) return stale;
|
|
2925
2953
|
adapter.scrollBy(Number(args.dy ?? 0));
|
|
2926
2954
|
return textResult(`Scrolled by ${Number(args.dy ?? 0)}px`);
|
|
2927
2955
|
},
|
|
@@ -2936,6 +2964,8 @@ function registerNavigationBridge(host, options) {
|
|
|
2936
2964
|
},
|
|
2937
2965
|
["handle", "value"],
|
|
2938
2966
|
(args) => {
|
|
2967
|
+
const stale = staleIntent();
|
|
2968
|
+
if (stale) return stale;
|
|
2939
2969
|
const handle = String(args.handle ?? "");
|
|
2940
2970
|
const res = adapter.setField(handle, args.value);
|
|
2941
2971
|
if (!res.ok) return errorResult(res.error ?? `Could not set ${handle}`);
|
|
@@ -2949,6 +2979,8 @@ function registerNavigationBridge(host, options) {
|
|
|
2949
2979
|
{ handle: { type: "string" } },
|
|
2950
2980
|
["handle"],
|
|
2951
2981
|
async (args) => {
|
|
2982
|
+
const stale = staleIntent();
|
|
2983
|
+
if (stale) return stale;
|
|
2952
2984
|
const handle = String(args.handle ?? "");
|
|
2953
2985
|
const action = adapter.describe().actions.find((a) => a.handle === handle);
|
|
2954
2986
|
const rect = adapter.rectFor?.(handle) ?? void 0;
|
|
@@ -2968,6 +3000,8 @@ function registerNavigationBridge(host, options) {
|
|
|
2968
3000
|
{ handle: { type: "string" } },
|
|
2969
3001
|
["handle"],
|
|
2970
3002
|
async (args) => {
|
|
3003
|
+
const stale = staleIntent();
|
|
3004
|
+
if (stale) return stale;
|
|
2971
3005
|
const handle = String(args.handle ?? "");
|
|
2972
3006
|
const rect = adapter.rectFor?.(handle) ?? void 0;
|
|
2973
3007
|
if (pendingMode && adapter.confirm) {
|
|
@@ -4871,6 +4905,23 @@ function CoBrowsePresence({ session, connectUrl, shareBaseUrl, className }) {
|
|
|
4871
4905
|
] });
|
|
4872
4906
|
}
|
|
4873
4907
|
CoBrowsePresence.displayName = "CoBrowsePresence";
|
|
4908
|
+
var CURSOR_EDGE_INSET = 24;
|
|
4909
|
+
var FLUID_CURSOR_SPEED_PX_PER_SECOND = 1050;
|
|
4910
|
+
var MIN_GLIDE_MS = 240;
|
|
4911
|
+
var MAX_GLIDE_MS = 1200;
|
|
4912
|
+
function visibleCursorPoint(rect, viewport) {
|
|
4913
|
+
const x = rect.x + rect.width / 2;
|
|
4914
|
+
const y = rect.y + rect.height / 2;
|
|
4915
|
+
return {
|
|
4916
|
+
x: Math.min(Math.max(x, CURSOR_EDGE_INSET), Math.max(CURSOR_EDGE_INSET, viewport.width - CURSOR_EDGE_INSET)),
|
|
4917
|
+
y: Math.min(Math.max(y, CURSOR_EDGE_INSET), Math.max(CURSOR_EDGE_INSET, viewport.height - CURSOR_EDGE_INSET))
|
|
4918
|
+
};
|
|
4919
|
+
}
|
|
4920
|
+
function fluidGlideDuration(from, to) {
|
|
4921
|
+
if (!from) return 0;
|
|
4922
|
+
const distance = Math.hypot(to.x - from.x, to.y - from.y);
|
|
4923
|
+
return Math.round(Math.min(MAX_GLIDE_MS, Math.max(MIN_GLIDE_MS, distance / FLUID_CURSOR_SPEED_PX_PER_SECOND * 1e3)));
|
|
4924
|
+
}
|
|
4874
4925
|
function CoBrowseCursorLayer({ active = true, zIndex = 2147483e3 }) {
|
|
4875
4926
|
const { latest } = useAgentActivity(void 0, { capacity: 12 });
|
|
4876
4927
|
const [cursor, setCursor] = react.useState(
|
|
@@ -4880,7 +4931,7 @@ function CoBrowseCursorLayer({ active = true, zIndex = 2147483e3 }) {
|
|
|
4880
4931
|
react.useEffect(() => {
|
|
4881
4932
|
if (!latest || (latest.source ?? "agent") === "user") return;
|
|
4882
4933
|
if (latest.action === "agent_disconnected") {
|
|
4883
|
-
setCursor(
|
|
4934
|
+
setCursor((prev) => prev ? { ...prev, status: "Standing by", glideMs: 0 } : prev);
|
|
4884
4935
|
setPulse(null);
|
|
4885
4936
|
return;
|
|
4886
4937
|
}
|
|
@@ -4889,11 +4940,19 @@ function CoBrowseCursorLayer({ active = true, zIndex = 2147483e3 }) {
|
|
|
4889
4940
|
const status = latest.target?.label ?? latest.action;
|
|
4890
4941
|
const rect = latest.meta?.rect;
|
|
4891
4942
|
if (rect) {
|
|
4892
|
-
|
|
4943
|
+
const target = visibleCursorPoint(rect, { width: window.innerWidth, height: window.innerHeight });
|
|
4944
|
+
const reduceMotion = window.matchMedia?.("(prefers-reduced-motion: reduce)").matches ?? false;
|
|
4945
|
+
setCursor((prev) => ({
|
|
4946
|
+
...target,
|
|
4947
|
+
name,
|
|
4948
|
+
color,
|
|
4949
|
+
status,
|
|
4950
|
+
glideMs: reduceMotion ? 0 : fluidGlideDuration(prev, target)
|
|
4951
|
+
}));
|
|
4893
4952
|
setPulse({ rect, color, key: latest.timestamp });
|
|
4894
4953
|
} else {
|
|
4895
4954
|
setCursor(
|
|
4896
|
-
(prev) => prev ? { ...prev, status, name, color } : { x: window.innerWidth / 2, y: window.innerHeight / 2, name, color, status }
|
|
4955
|
+
(prev) => prev ? { ...prev, status, name, color } : { x: window.innerWidth / 2, y: window.innerHeight / 2, name, color, status, glideMs: 0 }
|
|
4897
4956
|
);
|
|
4898
4957
|
}
|
|
4899
4958
|
}, [latest?.timestamp]);
|
|
@@ -4919,7 +4978,9 @@ function CoBrowseCursorLayer({ active = true, zIndex = 2147483e3 }) {
|
|
|
4919
4978
|
name: cursor.name,
|
|
4920
4979
|
color: cursor.color,
|
|
4921
4980
|
status: cursor.status,
|
|
4922
|
-
style: {
|
|
4981
|
+
style: {
|
|
4982
|
+
transition: cursor.glideMs ? `left ${cursor.glideMs}ms cubic-bezier(.22,.61,.36,1), top ${cursor.glideMs}ms cubic-bezier(.22,.61,.36,1)` : "none"
|
|
4983
|
+
}
|
|
4923
4984
|
}
|
|
4924
4985
|
)
|
|
4925
4986
|
] }),
|