@syntrologie/adapt-chatbot 2.8.0-canary.593 → 2.8.0-canary.595

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.
@@ -21,7 +21,24 @@ export interface HostToolResults {
21
21
  * already has. What the missing-result check stands down on.
22
22
  */
23
23
  subscribeToolActivity?(listener: () => void): () => void;
24
+ /**
25
+ * Where the tool call this card was drawn for stands, the latest replayed
26
+ * on subscribe. Its input names the session the conversation is in.
27
+ */
28
+ subscribeToolCall?(listener: (call: {
29
+ phase: 'input';
30
+ arguments: Record<string, unknown>;
31
+ } | {
32
+ phase: 'result';
33
+ } | {
34
+ phase: 'cancelled';
35
+ }) => void): () => void;
24
36
  }
37
+ /**
38
+ * How long a card says its answer is on its way when neither the answer nor a
39
+ * cancellation ever comes (a host that stops a turn without saying so).
40
+ */
41
+ export declare const PENDING_MAX_MS = 120000;
25
42
  export interface HostAgentControllerOptions {
26
43
  /** How long a card that has heard nothing waits before reporting it. */
27
44
  missingResultMs?: number;
@@ -32,7 +49,9 @@ interface HostUiInitialization {
32
49
  /** One host conversation owns one store; host delivery may synchronously replay. */
33
50
  export declare function activateHostAgentController(runtime: ChatbotWidgetRuntime, bridge: HostToolResults, hostUi?: HostUiInitialization, options?: HostAgentControllerOptions): {
34
51
  acceptHostUi: (payload: unknown) => void;
35
- consumeToolResult: (result: unknown) => Promise<void>;
52
+ consumeToolResult: (result: unknown, { earlyRead }?: {
53
+ earlyRead?: boolean;
54
+ }) => Promise<void>;
36
55
  whenIdle: () => Promise<void>;
37
56
  dispose(): void;
38
57
  };
@@ -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;AAwJD,UAAU,oBAAoB;IAC5B,cAAc,CAAC,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CAAC;CAC7C;AAsJD,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;;;EAoHjE;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"}
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;IACzD;;;OAGG;IACH,iBAAiB,CAAC,CAChB,QAAQ,EAAE,CACR,IAAI,EACA;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GACtD;QAAE,KAAK,EAAE,QAAQ,CAAA;KAAE,GACnB;QAAE,KAAK,EAAE,WAAW,CAAA;KAAE,KACvB,IAAI,GACR,MAAM,IAAI,CAAC;CACf;AAYD;;;GAGG;AACH,eAAO,MAAM,cAAc,SAAU,CAAC;AAKtC,MAAM,WAAW,0BAA0B;IACzC,wEAAwE;IACxE,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAwJD,UAAU,oBAAoB;IAC5B,cAAc,CAAC,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CAAC;CAC7C;AAsJD,oFAAoF;AACpF,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,oBAAoB,EAC7B,MAAM,EAAE,eAAe,EACvB,MAAM,CAAC,EAAE,oBAAoB,EAC7B,OAAO,GAAE,0BAA+B;4BAwaT,OAAO,KAAG,IAAI;gCAiGnC,OAAO,kBACQ;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,KAC7C,OAAO,CAAC,IAAI,CAAC;;;EAkKjB;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
@@ -3481,6 +3481,7 @@ var AdaptiveChipsStripMountable = {
3481
3481
  // src/hostAgentController.ts
3482
3482
  var READ_TOOL = "read_brand_view";
3483
3483
  var MISSING_RESULT_MS = 8e3;
3484
+ var PENDING_MAX_MS = 12e4;
3484
3485
  var AGENT_TURN_KEY = "syntro/agent-turn";
3485
3486
  var CARD_HEARTBEAT_PREFIX = "syntro:mcp-card:";
3486
3487
  var heartbeatPrefix = (sessionRef) => `${CARD_HEARTBEAT_PREFIX}${sessionRef}:`;
@@ -3609,6 +3610,7 @@ function activateHostAgentController(runtime2, bridge, hostUi, options = {}) {
3609
3610
  let heartbeatTimer;
3610
3611
  let popOutDecided = false;
3611
3612
  let born;
3613
+ let showingEarlyRead = false;
3612
3614
  let answerIssuedAt;
3613
3615
  let heartbeatSession;
3614
3616
  let folded = false;
@@ -3802,33 +3804,41 @@ function activateHostAgentController(runtime2, bridge, hostUi, options = {}) {
3802
3804
  }
3803
3805
  });
3804
3806
  }
3805
- function scheduleHostRead(sessionRef) {
3807
+ function scheduleHostRead(sessionRef, why = "reload") {
3806
3808
  if (disposed || readRequested || typeof bridge.callServerTool !== "function") return;
3807
3809
  const call = bridge.callServerTool.bind(bridge);
3808
3810
  readRequested = true;
3809
3811
  const expected = generation;
3812
+ const readAgain = () => {
3813
+ if (disposed || why !== "turn_started") return;
3814
+ readRequested = false;
3815
+ if (session) scheduleHostRead(session.session_ref);
3816
+ };
3810
3817
  void Promise.resolve().then(() => {
3811
- if (disposed || expected !== generation) return;
3818
+ if (disposed) return;
3819
+ if (expected !== generation) return readAgain();
3812
3820
  queue(async () => {
3813
3821
  const appliedAtIssue = applied;
3814
- reportCardStage("read_brand_view_called", { why: "reload" });
3822
+ reportCardStage("read_brand_view_called", { why });
3815
3823
  void call({ name: READ_TOOL, arguments: { sessionRef } }).then((result) => {
3816
- reportReadAnswer("reload", result);
3817
- if (disposed || expected !== generation) return;
3824
+ reportReadAnswer(why, result);
3825
+ if (disposed) return;
3826
+ if (expected !== generation) return readAgain();
3818
3827
  if (applied !== appliedAtIssue) {
3819
3828
  reportCardStage("tool_result_rejected", { reason: "stale" });
3820
3829
  return;
3821
3830
  }
3822
- return consumeToolResult(result);
3831
+ return consumeToolResult(result, { earlyRead: why === "turn_started" });
3823
3832
  }).catch((error) => {
3824
3833
  reportCardStage("read_brand_view_answered", {
3825
- why: "reload",
3834
+ why,
3826
3835
  ok: false,
3827
3836
  withAgentTurn: false,
3828
3837
  // The host's own words for the refusal: a read that never
3829
3838
  // reaches the connector leaves no other record of why.
3830
3839
  reason: readFailureReason(error instanceof Error ? error.message : String(error))
3831
3840
  });
3841
+ if (why === "turn_started") return readAgain();
3832
3842
  if (!disposed && expected === generation)
3833
3843
  runtime2.events.publish("host.ui_error", { reason: "refresh_required" });
3834
3844
  });
@@ -3921,7 +3931,7 @@ function activateHostAgentController(runtime2, bridge, hostUi, options = {}) {
3921
3931
  result_id: outcome.resultId,
3922
3932
  tiles: tiles.length
3923
3933
  });
3924
- if (born === void 0 && tiles.length > 0) {
3934
+ if (born === void 0 && tiles.length > 0 && !showingEarlyRead) {
3925
3935
  born = answerIssuedAt ?? Date.now();
3926
3936
  writeHeartbeat();
3927
3937
  }
@@ -3929,7 +3939,7 @@ function activateHostAgentController(runtime2, bridge, hostUi, options = {}) {
3929
3939
  }
3930
3940
  });
3931
3941
  }
3932
- async function consumeToolResult(result) {
3942
+ async function consumeToolResult(result, { earlyRead = false } = {}) {
3933
3943
  if (disposed) return;
3934
3944
  const turn = decodeAgentTurn(result);
3935
3945
  if (!turn) {
@@ -3937,8 +3947,11 @@ function activateHostAgentController(runtime2, bridge, hostUi, options = {}) {
3937
3947
  reportCardStage("tool_result_rejected", { reason: "decode_failed" });
3938
3948
  return;
3939
3949
  }
3940
- answerIssuedAt ?? (answerIssuedAt = turn.issuedAt ?? Date.now());
3941
- considerPopOut(turn.session.session_ref);
3950
+ showingEarlyRead = earlyRead;
3951
+ if (!earlyRead) {
3952
+ answerIssuedAt ?? (answerIssuedAt = turn.issuedAt ?? Date.now());
3953
+ considerPopOut(turn.session.session_ref);
3954
+ }
3942
3955
  acceptHostUi2({ kind: "session", session: turn.session });
3943
3956
  acceptHostUi2({ kind: "frame", frame: turn.frame });
3944
3957
  startHeartbeat(turn.session.session_ref);
@@ -3996,6 +4009,32 @@ function activateHostAgentController(runtime2, bridge, hostUi, options = {}) {
3996
4009
  void consumeToolResult(result);
3997
4010
  };
3998
4011
  const stopActivity = bridge.subscribeToolActivity?.(standDown);
4012
+ let turnPending;
4013
+ let pendingTimer;
4014
+ function publishTurnPending(value) {
4015
+ if (disposed || turnPending === value) return;
4016
+ turnPending = value;
4017
+ if (pendingTimer !== void 0) clearTimeout(pendingTimer);
4018
+ pendingTimer = value ? setTimeout(() => publishTurnPending(false), PENDING_MAX_MS) : void 0;
4019
+ runtime2.events.publish("host.turn_pending", { pending: value });
4020
+ }
4021
+ const stopPendingRequests = runtime2.events.subscribe?.(
4022
+ { names: ["canvas:turn-pending-request"] },
4023
+ () => {
4024
+ if (!disposed && turnPending !== void 0)
4025
+ runtime2.events.publish("host.turn_pending", { pending: turnPending });
4026
+ }
4027
+ );
4028
+ const stopToolCall = bridge.subscribeToolCall?.((call) => {
4029
+ if (disposed) return;
4030
+ if (call.phase === "input") {
4031
+ publishTurnPending(true);
4032
+ const sessionRef = call.arguments.sessionRef;
4033
+ if (nonempty(sessionRef) && !session) scheduleHostRead(sessionRef, "turn_started");
4034
+ return;
4035
+ }
4036
+ void Promise.resolve().then(() => queue(async () => publishTurnPending(false)));
4037
+ });
3999
4038
  const unsubscribe = bridge.subscribeToolResults(deliver, {
4000
4039
  metadataKey: AGENT_TURN_KEY
4001
4040
  });
@@ -4013,6 +4052,9 @@ function activateHostAgentController(runtime2, bridge, hostUi, options = {}) {
4013
4052
  if (missingTimer !== void 0) clearTimeout(missingTimer);
4014
4053
  missingTimer = void 0;
4015
4054
  stopActivity?.();
4055
+ stopToolCall?.();
4056
+ stopPendingRequests?.();
4057
+ if (pendingTimer !== void 0) clearTimeout(pendingTimer);
4016
4058
  stopStarRequests?.();
4017
4059
  stopHeartbeat();
4018
4060
  stopObserver?.();