@syntrologie/adapt-chatbot 2.8.0-canary.583 → 2.8.0-canary.585

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.
@@ -1 +1 @@
1
- {"version":3,"file":"hostAgentController.d.ts","sourceRoot":"","sources":["../src/hostAgentController.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAEpD,uFAAuF;AACvF,MAAM,WAAW,eAAe;IAC9B,oBAAoB,CAClB,QAAQ,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,EACnC,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GACjC,MAAM,IAAI,CAAC;IACd;;;;;;OAMG;IACH,cAAc,CAAC,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACjG;;;;OAIG;IACH,qBAAqB,CAAC,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;CAC1D;AAeD,MAAM,WAAW,0BAA0B;IACzC,wEAAwE;IACxE,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AA2ED,UAAU,oBAAoB;IAC5B,cAAc,CAAC,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CAAC;CAC7C;AA4ID,oFAAoF;AACpF,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,oBAAoB,EAC7B,MAAM,EAAE,eAAe,EACvB,MAAM,CAAC,EAAE,oBAAoB,EAC7B,OAAO,GAAE,0BAA+B;4BA8TT,OAAO,KAAG,IAAI;gCA0FJ,OAAO,KAAG,OAAO,CAAC,IAAI,CAAC;;;EA+CjE;AAED,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CA4D5E;AAED,qFAAqF;AACrF,wBAAgB,YAAY,CAC1B,OAAO,EAAE;IAAE,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;CAAE,EACtD,OAAO,EAAE,OAAO,GACf,IAAI,CAEN"}
1
+ {"version":3,"file":"hostAgentController.d.ts","sourceRoot":"","sources":["../src/hostAgentController.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAEpD,uFAAuF;AACvF,MAAM,WAAW,eAAe;IAC9B,oBAAoB,CAClB,QAAQ,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,EACnC,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GACjC,MAAM,IAAI,CAAC;IACd;;;;;;OAMG;IACH,cAAc,CAAC,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACjG;;;;OAIG;IACH,qBAAqB,CAAC,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;CAC1D;AAeD,MAAM,WAAW,0BAA0B;IACzC,wEAAwE;IACxE,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAkGD,UAAU,oBAAoB;IAC5B,cAAc,CAAC,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CAAC;CAC7C;AAgJD,oFAAoF;AACpF,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,oBAAoB,EAC7B,MAAM,EAAE,eAAe,EACvB,MAAM,CAAC,EAAE,oBAAoB,EAC7B,OAAO,GAAE,0BAA+B;4BAuZT,OAAO,KAAG,IAAI;gCAgGJ,OAAO,KAAG,OAAO,CAAC,IAAI,CAAC;;;EAmDjE;AA0BD,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CA4D5E;AAED,qFAAqF;AACrF,wBAAgB,YAAY,CAC1B,OAAO,EAAE;IAAE,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;CAAE,EACtD,OAAO,EAAE,OAAO,GACf,IAAI,CAEN"}
package/dist/runtime.js CHANGED
@@ -3487,6 +3487,16 @@ var heartbeatPrefix = (sessionRef) => `${CARD_HEARTBEAT_PREFIX}${sessionRef}:`;
3487
3487
  var CARD_HEARTBEAT_INTERVAL_MS = 2e3;
3488
3488
  var CARD_SIBLING_WINDOW_MS = 6e3;
3489
3489
  var CARD_HEARTBEAT_STALE_MS = 6e4;
3490
+ var CARD_SUPERSEDED = "canvas:superseded";
3491
+ var DOCKED_PREFIX = "syntro:mcp-docked:";
3492
+ var DOCKED_FOR_MS = 24 * 60 * 60 * 1e3;
3493
+ function coarsePointer() {
3494
+ try {
3495
+ return typeof matchMedia === "function" && matchMedia("(pointer: coarse)").matches;
3496
+ } catch {
3497
+ return false;
3498
+ }
3499
+ }
3490
3500
  function cardStorage() {
3491
3501
  try {
3492
3502
  return globalThis.localStorage ?? void 0;
@@ -3552,7 +3562,8 @@ function decodeAgentTurn(result) {
3552
3562
  session_expires_at: snapshot.session_expires_at,
3553
3563
  mounted_elements: snapshot.mounted_elements
3554
3564
  };
3555
- return { session, frame };
3565
+ const issuedAt = typeof payload.issuedAt === "number" && Number.isFinite(payload.issuedAt) ? payload.issuedAt : void 0;
3566
+ return { session, frame, ...issuedAt !== void 0 ? { issuedAt } : {} };
3556
3567
  }
3557
3568
  function activateHostAgentController(runtime2, bridge, hostUi, options = {}) {
3558
3569
  let controller = createElementSessionController(runtime2);
@@ -3568,6 +3579,10 @@ function activateHostAgentController(runtime2, bridge, hostUi, options = {}) {
3568
3579
  let heartbeatKey;
3569
3580
  let heartbeatTimer;
3570
3581
  let popOutDecided = false;
3582
+ let born;
3583
+ let answerIssuedAt;
3584
+ let heartbeatSession;
3585
+ let folded = false;
3571
3586
  function hostSurface() {
3572
3587
  try {
3573
3588
  return runtime2.context?.get().surface ?? {};
@@ -3584,7 +3599,8 @@ function activateHostAgentController(runtime2, bridge, hostUi, options = {}) {
3584
3599
  return {
3585
3600
  id: parsed.id,
3586
3601
  ts: parsed.ts,
3587
- mode: typeof parsed.mode === "string" ? parsed.mode : void 0
3602
+ mode: typeof parsed.mode === "string" ? parsed.mode : void 0,
3603
+ born: typeof parsed.born === "number" ? parsed.born : void 0
3588
3604
  };
3589
3605
  } catch {
3590
3606
  return;
@@ -3595,10 +3611,21 @@ function activateHostAgentController(runtime2, bridge, hostUi, options = {}) {
3595
3611
  try {
3596
3612
  cardStorage()?.setItem(
3597
3613
  heartbeatKey,
3598
- JSON.stringify({ id: cardId, ts: Date.now(), mode: hostSurface().displayMode })
3614
+ JSON.stringify({ id: cardId, ts: Date.now(), mode: hostSurface().displayMode, born })
3599
3615
  );
3600
3616
  } catch {
3601
3617
  }
3618
+ considerFold();
3619
+ }
3620
+ function considerFold() {
3621
+ if (folded || disposed || !heartbeatSession || born === void 0) return;
3622
+ const surface = hostSurface();
3623
+ if (surface.type !== "mcp-app" || surface.displayMode !== "inline") return;
3624
+ if (!surface.availableDisplayModes || popsOut(surface, heartbeatSession)) return;
3625
+ const mine = born;
3626
+ if (!freshSiblings(heartbeatSession).some((beat) => (beat.born ?? 0) > mine)) return;
3627
+ folded = true;
3628
+ runtime2.events.publish(CARD_SUPERSEDED, { superseded: true });
3602
3629
  }
3603
3630
  function pruneHeartbeats() {
3604
3631
  try {
@@ -3629,14 +3656,28 @@ function activateHostAgentController(runtime2, bridge, hostUi, options = {}) {
3629
3656
  writeHeartbeat();
3630
3657
  heartbeatTimer = setInterval(writeHeartbeat, CARD_HEARTBEAT_INTERVAL_MS);
3631
3658
  };
3659
+ let unsubscribeModeWatch;
3632
3660
  function startHeartbeat(sessionRef) {
3633
3661
  const key = heartbeatPrefix(sessionRef) + cardId;
3634
3662
  if (heartbeatKey === key) return;
3635
3663
  if (heartbeatKey) stopHeartbeat();
3636
3664
  heartbeatKey = key;
3665
+ heartbeatSession = sessionRef;
3637
3666
  pruneHeartbeats();
3638
3667
  writeHeartbeat();
3639
3668
  heartbeatTimer = setInterval(writeHeartbeat, CARD_HEARTBEAT_INTERVAL_MS);
3669
+ let heartbeatMode = hostSurface().displayMode;
3670
+ try {
3671
+ unsubscribeModeWatch = runtime2.context?.subscribe?.(() => {
3672
+ const mode = hostSurface().displayMode;
3673
+ if (mode === heartbeatMode) return;
3674
+ if (heartbeatMode === "pip" && mode === "inline" && heartbeatSession)
3675
+ rememberDocked(heartbeatSession);
3676
+ heartbeatMode = mode;
3677
+ writeHeartbeat();
3678
+ });
3679
+ } catch {
3680
+ }
3640
3681
  if (typeof window !== "undefined") {
3641
3682
  window.addEventListener("pagehide", releaseHeartbeat);
3642
3683
  window.addEventListener("beforeunload", releaseHeartbeat);
@@ -3649,6 +3690,8 @@ function activateHostAgentController(runtime2, bridge, hostUi, options = {}) {
3649
3690
  clearInterval(heartbeatTimer);
3650
3691
  heartbeatTimer = void 0;
3651
3692
  }
3693
+ unsubscribeModeWatch?.();
3694
+ unsubscribeModeWatch = void 0;
3652
3695
  const key = heartbeatKey;
3653
3696
  heartbeatKey = void 0;
3654
3697
  if (typeof window !== "undefined") {
@@ -3686,13 +3729,32 @@ function activateHostAgentController(runtime2, bridge, hostUi, options = {}) {
3686
3729
  if (popOutDecided) return;
3687
3730
  popOutDecided = true;
3688
3731
  const siblings = freshSiblings(sessionRef);
3689
- if (siblings.length === 0) return;
3690
3732
  if (siblings.some((beat) => beat.mode !== "inline")) return;
3691
3733
  const surface = hostSurface();
3692
3734
  if (surface.type !== "mcp-app" || surface.displayMode !== "inline") return;
3693
- if (!surface.availableDisplayModes?.includes("pip")) return;
3735
+ if (!popsOut(surface, sessionRef)) return;
3694
3736
  runtime2.events.publish("canvas:request-display-mode", { mode: "pip" });
3695
3737
  }
3738
+ function popsOut(surface, sessionRef) {
3739
+ if (!surface.availableDisplayModes?.includes("pip")) return false;
3740
+ if (coarsePointer()) return false;
3741
+ return !shopperDocked(sessionRef);
3742
+ }
3743
+ function shopperDocked(sessionRef) {
3744
+ try {
3745
+ const raw = cardStorage()?.getItem(DOCKED_PREFIX + sessionRef);
3746
+ const at = raw ? Number(raw) : Number.NaN;
3747
+ return Number.isFinite(at) && Date.now() - at < DOCKED_FOR_MS;
3748
+ } catch {
3749
+ return false;
3750
+ }
3751
+ }
3752
+ function rememberDocked(sessionRef) {
3753
+ try {
3754
+ cardStorage()?.setItem(DOCKED_PREFIX + sessionRef, String(Date.now()));
3755
+ } catch {
3756
+ }
3757
+ }
3696
3758
  let interactiveState;
3697
3759
  function interactive(value) {
3698
3760
  if (disposed || interactiveState === value) return;
@@ -3729,11 +3791,14 @@ function activateHostAgentController(runtime2, bridge, hostUi, options = {}) {
3729
3791
  return;
3730
3792
  }
3731
3793
  return consumeToolResult(result);
3732
- }).catch(() => {
3794
+ }).catch((error) => {
3733
3795
  reportCardStage("read_brand_view_answered", {
3734
3796
  why: "reload",
3735
3797
  ok: false,
3736
- withAgentTurn: false
3798
+ withAgentTurn: false,
3799
+ // The host's own words for the refusal: a read that never
3800
+ // reaches the connector leaves no other record of why.
3801
+ reason: readFailureReason(error instanceof Error ? error.message : String(error))
3737
3802
  });
3738
3803
  if (!disposed && expected === generation)
3739
3804
  runtime2.events.publish("host.ui_error", { reason: "refresh_required" });
@@ -3742,10 +3807,13 @@ function activateHostAgentController(runtime2, bridge, hostUi, options = {}) {
3742
3807
  });
3743
3808
  }
3744
3809
  function reportReadAnswer(why, result) {
3810
+ const failed = record(result) && result.isError === true;
3811
+ const text = failed ? firstText(result) : void 0;
3745
3812
  reportCardStage("read_brand_view_answered", {
3746
3813
  why,
3747
- ok: !(record(result) && result.isError === true),
3748
- withAgentTurn: decodeAgentTurn(result) !== void 0
3814
+ ok: !failed,
3815
+ withAgentTurn: decodeAgentTurn(result) !== void 0,
3816
+ ...text ? { reason: readFailureReason(text) } : {}
3749
3817
  });
3750
3818
  }
3751
3819
  const missingAfterMs = options.missingResultMs ?? MISSING_RESULT_MS;
@@ -3824,6 +3892,10 @@ function activateHostAgentController(runtime2, bridge, hostUi, options = {}) {
3824
3892
  result_id: outcome.resultId,
3825
3893
  tiles: tiles.length
3826
3894
  });
3895
+ if (born === void 0 && tiles.length > 0) {
3896
+ born = answerIssuedAt ?? Date.now();
3897
+ writeHeartbeat();
3898
+ }
3827
3899
  interactive(true);
3828
3900
  }
3829
3901
  });
@@ -3836,6 +3908,7 @@ function activateHostAgentController(runtime2, bridge, hostUi, options = {}) {
3836
3908
  reportCardStage("tool_result_rejected", { reason: "decode_failed" });
3837
3909
  return;
3838
3910
  }
3911
+ answerIssuedAt ?? (answerIssuedAt = turn.issuedAt ?? Date.now());
3839
3912
  considerPopOut(turn.session.session_ref);
3840
3913
  acceptHostUi2({ kind: "session", session: turn.session });
3841
3914
  acceptHostUi2({ kind: "frame", frame: turn.frame });
@@ -3871,6 +3944,18 @@ function activateHostAgentController(runtime2, bridge, hostUi, options = {}) {
3871
3944
  }
3872
3945
  };
3873
3946
  }
3947
+ var READ_REASON_MAX = 120;
3948
+ function readFailureReason(text) {
3949
+ const flat = text.replace(/\s+/g, " ").replace(/[A-Za-z0-9_\-+/=]{24,}/g, "[id]").trim();
3950
+ return flat.length > READ_REASON_MAX ? `${flat.slice(0, READ_REASON_MAX - 1)}~` : flat || "unknown";
3951
+ }
3952
+ function firstText(result) {
3953
+ if (!Array.isArray(result.content)) return void 0;
3954
+ for (const block of result.content) {
3955
+ if (record(block) && block.type === "text" && typeof block.text === "string") return block.text;
3956
+ }
3957
+ return void 0;
3958
+ }
3874
3959
  function activateHostAgent(runtime2) {
3875
3960
  if (!record(runtime2) || !record(runtime2.context) || typeof runtime2.context.get !== "function")
3876
3961
  return;