@particle-academy/agent-integrations 0.47.0 → 0.47.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -3416,6 +3416,22 @@ function registerTerminalBridge(host, options) {
3416
3416
 
3417
3417
  // src/bridges/navigation.ts
3418
3418
  var DEFAULT_AGENT12 = { id: "agent", name: "Agent", color: "#a855f7" };
3419
+ var isControl = (code) => code < 32 || code >= 127 && code <= 159 || code === 8232 || code === 8233;
3420
+ function oneLine(value, max) {
3421
+ const raw = typeof value === "string" ? value : value == null ? "" : String(value);
3422
+ const bounded = raw.length > max * 4 ? raw.slice(0, max * 4) : raw;
3423
+ let out = "";
3424
+ for (const c of bounded) out += isControl(c.charCodeAt(0)) ? " " : c;
3425
+ out = out.replace(/\s+/g, " ").trim();
3426
+ return out.length > max ? out.slice(0, max - 3) + "..." : out;
3427
+ }
3428
+ var SAFE_HANDLE = /^[A-Za-z0-9_.:#@/-]{1,80}$/;
3429
+ var CAP = { url: 500, title: 200, role: 40, label: 200, heading: 200, text: 4e3, error: 300, headings: 50 };
3430
+ function formatReadout(r) {
3431
+ if (typeof r === "string") return oneLine(r, CAP.text);
3432
+ const headings = (Array.isArray(r.headings) ? r.headings : []).slice(0, CAP.headings).map((h) => `H${Math.min(6, Math.max(1, Math.trunc(Number(h?.level)) || 1))}: ${oneLine(h?.text, CAP.heading)}`);
3433
+ return [oneLine(r.title, CAP.title), ...headings, "", oneLine(r.text, CAP.text)].join("\n");
3434
+ }
3419
3435
  function registerNavigationBridge(host, options) {
3420
3436
  const { adapter } = options;
3421
3437
  const agent = { ...DEFAULT_AGENT12, ...options.agent ?? {} };
@@ -3432,6 +3448,9 @@ function registerNavigationBridge(host, options) {
3432
3448
  }
3433
3449
  return null;
3434
3450
  };
3451
+ let aliases = /* @__PURE__ */ new Map();
3452
+ const pageHandle = (handle) => aliases.get(handle) ?? handle;
3453
+ const failure = (message, fallback) => errorResult(oneLine(message ?? fallback, CAP.error) || fallback);
3435
3454
  ensureUndoToolsRegistered(host, { defaultAgentId: agent.id });
3436
3455
  const target = (label, elementId) => ({
3437
3456
  kind: "navigation",
@@ -3444,7 +3463,7 @@ function registerNavigationBridge(host, options) {
3444
3463
  try {
3445
3464
  return await handler(args);
3446
3465
  } catch (e) {
3447
- return errorResult(e instanceof Error ? e.message : String(e));
3466
+ return failure(e instanceof Error ? e.message : String(e), `${name} failed`);
3448
3467
  }
3449
3468
  };
3450
3469
  const final = activity ? wrapToolWithActivity(wrapped, {
@@ -3471,17 +3490,29 @@ function registerNavigationBridge(host, options) {
3471
3490
  {},
3472
3491
  [],
3473
3492
  async () => {
3474
- const snap = await adapter.describe();
3493
+ const raw = await adapter.describe();
3494
+ const next = /* @__PURE__ */ new Map();
3495
+ const actions = (Array.isArray(raw.actions) ? raw.actions : []).map((a) => {
3496
+ const handle = String(a.handle ?? "");
3497
+ if (SAFE_HANDLE.test(handle)) return a;
3498
+ const alias = `~${next.size}`;
3499
+ next.set(alias, handle);
3500
+ return { ...a, handle: alias };
3501
+ });
3502
+ aliases = next;
3503
+ const snap = { ...raw, actions };
3475
3504
  const revision = await adapter.getRevision?.();
3476
3505
  if (revision !== void 0) {
3477
3506
  snap.revision = revision;
3478
3507
  groundedRevision = revision;
3479
3508
  }
3480
3509
  const text = [
3481
- `URL: ${snap.url}`,
3482
- `Title: ${snap.title}`,
3510
+ `URL: ${oneLine(snap.url, CAP.url)}`,
3511
+ `Title: ${oneLine(snap.title, CAP.title)}`,
3483
3512
  "",
3484
- ...snap.actions.map((a) => `[${a.handle}] ${a.role}: ${a.label}${a.destructive ? " (destructive)" : ""}`)
3513
+ ...actions.map(
3514
+ (a) => `[${a.handle}] ${oneLine(a.role, CAP.role)}: ${oneLine(a.label, CAP.label)}${a.destructive ? " (destructive)" : ""}`
3515
+ )
3485
3516
  ].join("\n");
3486
3517
  return textResult(text, snap);
3487
3518
  },
@@ -3492,7 +3523,10 @@ function registerNavigationBridge(host, options) {
3492
3523
  "Read the page's visible text / heading outline for grounding.",
3493
3524
  {},
3494
3525
  [],
3495
- async () => textResult(adapter.read ? await adapter.read() : "(host did not provide page text)"),
3526
+ async () => {
3527
+ const r = adapter.read ? await adapter.read() : void 0;
3528
+ return textResult(r == null ? "(host did not provide page text)" : formatReadout(r));
3529
+ },
3496
3530
  () => target("Read page")
3497
3531
  );
3498
3532
  reg(
@@ -3503,11 +3537,12 @@ function registerNavigationBridge(host, options) {
3503
3537
  async (args) => {
3504
3538
  const stale = await staleIntent();
3505
3539
  if (stale) return stale;
3506
- const handle = String(args.handle ?? "");
3540
+ const shown = String(args.handle ?? "");
3541
+ const handle = pageHandle(shown);
3507
3542
  const action = (await adapter.describe()).actions.find((candidate) => candidate.handle === handle);
3508
- if (!action) return errorResult(`No element for handle "${handle}"`);
3509
- return textResult(`Focused ${handle}`, {
3510
- handle,
3543
+ if (!action) return failure(`No element for handle "${shown}"`, "No element for that handle");
3544
+ return textResult(`Focused ${oneLine(shown, CAP.label)}`, {
3545
+ handle: shown,
3511
3546
  rect: await adapter.rectFor?.(handle) ?? void 0
3512
3547
  });
3513
3548
  },
@@ -3587,13 +3622,17 @@ function registerNavigationBridge(host, options) {
3587
3622
  async (args) => {
3588
3623
  const stale = await staleIntent();
3589
3624
  if (stale) return stale;
3590
- const handle = typeof args.handle === "string" ? args.handle : void 0;
3625
+ const shown = typeof args.handle === "string" ? args.handle : void 0;
3626
+ const handle = shown === void 0 ? void 0 : pageHandle(shown);
3591
3627
  await adapter.scrollTo({
3592
3628
  handle,
3593
3629
  x: typeof args.x === "number" ? args.x : void 0,
3594
3630
  y: typeof args.y === "number" ? args.y : void 0
3595
3631
  });
3596
- return textResult("Scrolled", handle ? { handle, rect: await adapter.rectFor?.(handle) ?? void 0 } : void 0);
3632
+ return textResult(
3633
+ "Scrolled",
3634
+ handle ? { handle: shown, rect: await adapter.rectFor?.(handle) ?? void 0 } : void 0
3635
+ );
3597
3636
  },
3598
3637
  () => target("Scroll")
3599
3638
  );
@@ -3621,10 +3660,15 @@ function registerNavigationBridge(host, options) {
3621
3660
  async (args) => {
3622
3661
  const stale = await staleIntent();
3623
3662
  if (stale) return stale;
3624
- const handle = String(args.handle ?? "");
3663
+ const shown = String(args.handle ?? "");
3664
+ const handle = pageHandle(shown);
3625
3665
  const res = await adapter.setField(handle, args.value);
3626
- if (!res.ok) return errorResult(res.error ?? `Could not set ${handle}`);
3627
- return textResult(`${handle} \u2190 ${JSON.stringify(args.value)}`, { handle, value: args.value, rect: await adapter.rectFor?.(handle) ?? void 0 });
3666
+ if (!res.ok) return failure(res.error, `Could not set ${oneLine(shown, CAP.label)}`);
3667
+ return textResult(`${oneLine(shown, CAP.label)} \u2190 ${JSON.stringify(args.value)}`, {
3668
+ handle: shown,
3669
+ value: args.value,
3670
+ rect: await adapter.rectFor?.(handle) ?? void 0
3671
+ });
3628
3672
  },
3629
3673
  (args) => target(`Set ${String(args.handle ?? "")}`, String(args.handle ?? ""))
3630
3674
  );
@@ -3636,7 +3680,8 @@ function registerNavigationBridge(host, options) {
3636
3680
  async (args) => {
3637
3681
  const stale = await staleIntent();
3638
3682
  if (stale) return stale;
3639
- const handle = String(args.handle ?? "");
3683
+ const shown = String(args.handle ?? "");
3684
+ const handle = pageHandle(shown);
3640
3685
  const action = (await adapter.describe()).actions.find((a) => a.handle === handle);
3641
3686
  const rect = await adapter.rectFor?.(handle) ?? void 0;
3642
3687
  if (pendingMode && action?.destructive && adapter.confirm) {
@@ -3644,8 +3689,8 @@ function registerNavigationBridge(host, options) {
3644
3689
  if (!ok) return errorResult("Declined by user");
3645
3690
  }
3646
3691
  const res = await adapter.click(handle);
3647
- if (!res.ok) return errorResult(res.error ?? `Could not click ${handle}`);
3648
- return textResult(`Clicked ${handle}`, { handle, rect });
3692
+ if (!res.ok) return failure(res.error, `Could not click ${oneLine(shown, CAP.label)}`);
3693
+ return textResult(`Clicked ${oneLine(shown, CAP.label)}`, { handle: shown, rect });
3649
3694
  },
3650
3695
  (args) => target(`Click ${String(args.handle ?? "")}`, String(args.handle ?? ""))
3651
3696
  );
@@ -3657,15 +3702,16 @@ function registerNavigationBridge(host, options) {
3657
3702
  async (args) => {
3658
3703
  const stale = await staleIntent();
3659
3704
  if (stale) return stale;
3660
- const handle = String(args.handle ?? "");
3705
+ const shown = String(args.handle ?? "");
3706
+ const handle = pageHandle(shown);
3661
3707
  const rect = await adapter.rectFor?.(handle) ?? void 0;
3662
3708
  if (pendingMode && adapter.confirm) {
3663
3709
  const ok = await adapter.confirm({ action: "submit", handle, label: handle });
3664
3710
  if (!ok) return errorResult("Declined by user");
3665
3711
  }
3666
3712
  const res = await adapter.submit(handle);
3667
- if (!res.ok) return errorResult(res.error ?? "Submit failed");
3668
- return textResult(`Submitted ${handle}`, { handle, rect });
3713
+ if (!res.ok) return failure(res.error, "Submit failed");
3714
+ return textResult(`Submitted ${oneLine(shown, CAP.label)}`, { handle: shown, rect });
3669
3715
  },
3670
3716
  (args) => target(`Submit ${String(args.handle ?? "")}`, String(args.handle ?? ""))
3671
3717
  );