chatablex-web-sdk 1.0.32 → 1.0.36

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.d.mts CHANGED
@@ -127,6 +127,8 @@ interface ChatableXInitConfig {
127
127
  * calls reject with a clear error.
128
128
  */
129
129
  apiBaseUrl?: string;
130
+ /** Agent lock configuration — blocks user input during tool execution. */
131
+ agentLock?: AgentLockConfig;
130
132
  }
131
133
  interface ChatableXAI {
132
134
  chat(message: string, options?: ChatOptions): Promise<ChatResponse>;
@@ -261,6 +263,55 @@ interface ChatableXCloud {
261
263
  /** Read the account's storage usage / quota. */
262
264
  usage(): Promise<CloudUsage>;
263
265
  }
266
+ interface AgentLockConfig {
267
+ /** Enable the agent lock feature (default: true). */
268
+ enabled?: boolean;
269
+ /**
270
+ * `"overlay"` — SDK renders a built-in transparent overlay (default).
271
+ * `"events-only"` — SDK only emits lock/unlock events; no overlay injected.
272
+ */
273
+ mode?: 'overlay' | 'events-only';
274
+ /** URL of the logo displayed in the overlay centre. Defaults to built-in Chatablex SVG. */
275
+ logoUrl?: string;
276
+ /** Message shown below the logo (default: "Agent 正在操作,请稍候…"). */
277
+ message?: string;
278
+ /** Show a cancel button on the overlay (default: true). */
279
+ allowCancel?: boolean;
280
+ /** Overlay background opacity, 0–1 (default: 0.3). */
281
+ opacity?: number;
282
+ /** Auto-unlock timeout for a single tool execution, in ms (default: 30000). 0 disables. */
283
+ timeout?: number;
284
+ /**
285
+ * Safety auto-unlock timeout for a whole agent turn, in ms (default: 0 =
286
+ * disabled, rely on the host's turn-end signal). When the host drives a
287
+ * turn-level lock (the lock spans the entire agent response, not just one
288
+ * tool), this acts purely as a fallback in case the turn-end signal is lost.
289
+ */
290
+ turnTimeout?: number;
291
+ /** Delay before actually removing the overlay after unlock, to avoid flicker between consecutive tools (default: 200ms). */
292
+ debounceUnlock?: number;
293
+ }
294
+ type AgentLockEventType = 'lock' | 'unlock' | 'cancel' | 'timeout';
295
+ interface AgentLockEventData {
296
+ requestId?: string;
297
+ timestamp: number;
298
+ }
299
+ type AgentLockEventHandler = (data: AgentLockEventData) => void;
300
+ interface ChatableXAgentLock {
301
+ /** Manually lock user interaction with an optional custom message / timeout. */
302
+ lock(opts?: {
303
+ message?: string;
304
+ timeout?: number;
305
+ }): void;
306
+ /** Manually unlock. Safe to call when already unlocked. */
307
+ unlock(): void;
308
+ /** Whether the overlay is currently active. */
309
+ isLocked(): boolean;
310
+ /** Subscribe to lock lifecycle events. Returns an unsubscribe function. */
311
+ on(event: AgentLockEventType, handler: AgentLockEventHandler): () => void;
312
+ /** Remove a previously registered handler. */
313
+ off(event: AgentLockEventType, handler: AgentLockEventHandler): void;
314
+ }
264
315
  interface ChatableXSDK {
265
316
  ai: ChatableXAI;
266
317
  tools: ChatableXTools;
@@ -271,6 +322,7 @@ interface ChatableXSDK {
271
322
  platform: ChatableXPlatform;
272
323
  auth: ChatableXAuth;
273
324
  cloud: ChatableXCloud;
325
+ agentLock: ChatableXAgentLock;
274
326
  }
275
327
  declare global {
276
328
  interface Window {
@@ -386,4 +438,4 @@ declare const ChatableX: {
386
438
  version: string;
387
439
  };
388
440
 
389
- export { type AiResponseEventData, type AuthTokenData, Bridge, type ChatOptions, type ChatResponse, ChatableX, type ChatableXAI, type ChatableXAuth, type ChatableXCloud, type ChatableXEvents, type ChatableXInitConfig, type ChatableXPlatform, type ChatableXSDK, type ChatableXStorage, type ChatableXToolModule, type ChatableXTools, type ChatableXUI, type CloseEventData, CloudAuthRequiredError, CloudError, type CloudFileInfo, type CloudListOptions, CloudQuotaExceededError, CloudSubscriptionRequiredError, type CloudUploadData, type CloudUploadOptions, type CloudUploadResult, type CloudUsage, type EventCallbackMap, type EventType, type FilePickerOptions, type Message, type NotificationType, SDK_VERSION, type SessionContext, type StateUpdate, type StreamingContentEventData, type TabConfig, type ToolCall, type ToolExecuteHandler, type ToolExecutionEventData, type ToolInfo, type ToolParameter, type ToolResult, type Unsubscribe, type UserMessageEventData };
441
+ export { type AgentLockConfig, type AgentLockEventData, type AgentLockEventHandler, type AgentLockEventType, type AiResponseEventData, type AuthTokenData, Bridge, type ChatOptions, type ChatResponse, ChatableX, type ChatableXAI, type ChatableXAgentLock, type ChatableXAuth, type ChatableXCloud, type ChatableXEvents, type ChatableXInitConfig, type ChatableXPlatform, type ChatableXSDK, type ChatableXStorage, type ChatableXToolModule, type ChatableXTools, type ChatableXUI, type CloseEventData, CloudAuthRequiredError, CloudError, type CloudFileInfo, type CloudListOptions, CloudQuotaExceededError, CloudSubscriptionRequiredError, type CloudUploadData, type CloudUploadOptions, type CloudUploadResult, type CloudUsage, type EventCallbackMap, type EventType, type FilePickerOptions, type Message, type NotificationType, SDK_VERSION, type SessionContext, type StateUpdate, type StreamingContentEventData, type TabConfig, type ToolCall, type ToolExecuteHandler, type ToolExecutionEventData, type ToolInfo, type ToolParameter, type ToolResult, type Unsubscribe, type UserMessageEventData };
package/dist/index.d.ts CHANGED
@@ -127,6 +127,8 @@ interface ChatableXInitConfig {
127
127
  * calls reject with a clear error.
128
128
  */
129
129
  apiBaseUrl?: string;
130
+ /** Agent lock configuration — blocks user input during tool execution. */
131
+ agentLock?: AgentLockConfig;
130
132
  }
131
133
  interface ChatableXAI {
132
134
  chat(message: string, options?: ChatOptions): Promise<ChatResponse>;
@@ -261,6 +263,55 @@ interface ChatableXCloud {
261
263
  /** Read the account's storage usage / quota. */
262
264
  usage(): Promise<CloudUsage>;
263
265
  }
266
+ interface AgentLockConfig {
267
+ /** Enable the agent lock feature (default: true). */
268
+ enabled?: boolean;
269
+ /**
270
+ * `"overlay"` — SDK renders a built-in transparent overlay (default).
271
+ * `"events-only"` — SDK only emits lock/unlock events; no overlay injected.
272
+ */
273
+ mode?: 'overlay' | 'events-only';
274
+ /** URL of the logo displayed in the overlay centre. Defaults to built-in Chatablex SVG. */
275
+ logoUrl?: string;
276
+ /** Message shown below the logo (default: "Agent 正在操作,请稍候…"). */
277
+ message?: string;
278
+ /** Show a cancel button on the overlay (default: true). */
279
+ allowCancel?: boolean;
280
+ /** Overlay background opacity, 0–1 (default: 0.3). */
281
+ opacity?: number;
282
+ /** Auto-unlock timeout for a single tool execution, in ms (default: 30000). 0 disables. */
283
+ timeout?: number;
284
+ /**
285
+ * Safety auto-unlock timeout for a whole agent turn, in ms (default: 0 =
286
+ * disabled, rely on the host's turn-end signal). When the host drives a
287
+ * turn-level lock (the lock spans the entire agent response, not just one
288
+ * tool), this acts purely as a fallback in case the turn-end signal is lost.
289
+ */
290
+ turnTimeout?: number;
291
+ /** Delay before actually removing the overlay after unlock, to avoid flicker between consecutive tools (default: 200ms). */
292
+ debounceUnlock?: number;
293
+ }
294
+ type AgentLockEventType = 'lock' | 'unlock' | 'cancel' | 'timeout';
295
+ interface AgentLockEventData {
296
+ requestId?: string;
297
+ timestamp: number;
298
+ }
299
+ type AgentLockEventHandler = (data: AgentLockEventData) => void;
300
+ interface ChatableXAgentLock {
301
+ /** Manually lock user interaction with an optional custom message / timeout. */
302
+ lock(opts?: {
303
+ message?: string;
304
+ timeout?: number;
305
+ }): void;
306
+ /** Manually unlock. Safe to call when already unlocked. */
307
+ unlock(): void;
308
+ /** Whether the overlay is currently active. */
309
+ isLocked(): boolean;
310
+ /** Subscribe to lock lifecycle events. Returns an unsubscribe function. */
311
+ on(event: AgentLockEventType, handler: AgentLockEventHandler): () => void;
312
+ /** Remove a previously registered handler. */
313
+ off(event: AgentLockEventType, handler: AgentLockEventHandler): void;
314
+ }
264
315
  interface ChatableXSDK {
265
316
  ai: ChatableXAI;
266
317
  tools: ChatableXTools;
@@ -271,6 +322,7 @@ interface ChatableXSDK {
271
322
  platform: ChatableXPlatform;
272
323
  auth: ChatableXAuth;
273
324
  cloud: ChatableXCloud;
325
+ agentLock: ChatableXAgentLock;
274
326
  }
275
327
  declare global {
276
328
  interface Window {
@@ -386,4 +438,4 @@ declare const ChatableX: {
386
438
  version: string;
387
439
  };
388
440
 
389
- export { type AiResponseEventData, type AuthTokenData, Bridge, type ChatOptions, type ChatResponse, ChatableX, type ChatableXAI, type ChatableXAuth, type ChatableXCloud, type ChatableXEvents, type ChatableXInitConfig, type ChatableXPlatform, type ChatableXSDK, type ChatableXStorage, type ChatableXToolModule, type ChatableXTools, type ChatableXUI, type CloseEventData, CloudAuthRequiredError, CloudError, type CloudFileInfo, type CloudListOptions, CloudQuotaExceededError, CloudSubscriptionRequiredError, type CloudUploadData, type CloudUploadOptions, type CloudUploadResult, type CloudUsage, type EventCallbackMap, type EventType, type FilePickerOptions, type Message, type NotificationType, SDK_VERSION, type SessionContext, type StateUpdate, type StreamingContentEventData, type TabConfig, type ToolCall, type ToolExecuteHandler, type ToolExecutionEventData, type ToolInfo, type ToolParameter, type ToolResult, type Unsubscribe, type UserMessageEventData };
441
+ export { type AgentLockConfig, type AgentLockEventData, type AgentLockEventHandler, type AgentLockEventType, type AiResponseEventData, type AuthTokenData, Bridge, type ChatOptions, type ChatResponse, ChatableX, type ChatableXAI, type ChatableXAgentLock, type ChatableXAuth, type ChatableXCloud, type ChatableXEvents, type ChatableXInitConfig, type ChatableXPlatform, type ChatableXSDK, type ChatableXStorage, type ChatableXToolModule, type ChatableXTools, type ChatableXUI, type CloseEventData, CloudAuthRequiredError, CloudError, type CloudFileInfo, type CloudListOptions, CloudQuotaExceededError, CloudSubscriptionRequiredError, type CloudUploadData, type CloudUploadOptions, type CloudUploadResult, type CloudUsage, type EventCallbackMap, type EventType, type FilePickerOptions, type Message, type NotificationType, SDK_VERSION, type SessionContext, type StateUpdate, type StreamingContentEventData, type TabConfig, type ToolCall, type ToolExecuteHandler, type ToolExecutionEventData, type ToolInfo, type ToolParameter, type ToolResult, type Unsubscribe, type UserMessageEventData };
package/dist/index.js CHANGED
@@ -164,7 +164,7 @@ var Bridge = class {
164
164
  };
165
165
 
166
166
  // src/modules/tool.ts
167
- function createToolModule(bridge, appId) {
167
+ function createToolModule(bridge, appId, agentLock) {
168
168
  let _info = { id: appId, name: appId, version: "1.0.0", description: "" };
169
169
  let _handler = null;
170
170
  const dispatch = async (params) => {
@@ -182,6 +182,7 @@ function createToolModule(bridge, appId) {
182
182
  bridge.addEventListener("toolExecution", async (data) => {
183
183
  const params = data;
184
184
  const requestId = params._requestId;
185
+ if (requestId && agentLock) agentLock._autoLock(requestId);
185
186
  const result = await dispatch(params);
186
187
  if (requestId && window.ChatableXBridge) {
187
188
  window.ChatableXBridge.postMessage(JSON.stringify({
@@ -189,6 +190,7 @@ function createToolModule(bridge, appId) {
189
190
  params: { _requestId: requestId, ...result }
190
191
  }));
191
192
  }
193
+ if (requestId && agentLock) agentLock._autoUnlock(requestId);
192
194
  });
193
195
  return {
194
196
  getInfo() {
@@ -539,10 +541,252 @@ function createCloudModule(bridge, deps) {
539
541
  };
540
542
  }
541
543
 
544
+ // src/assets/bee.png
545
+ var bee_default = "data:image/png;base64,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";
546
+
547
+ // src/modules/agentLock.ts
548
+ var DEFAULT_CONFIG = {
549
+ enabled: true,
550
+ mode: "overlay",
551
+ logoUrl: "",
552
+ message: "Agent \u6B63\u5728\u64CD\u4F5C\uFF0C\u8BF7\u7A0D\u5019\u2026",
553
+ allowCancel: true,
554
+ opacity: 0.3,
555
+ timeout: 3e4,
556
+ turnTimeout: 0,
557
+ debounceUnlock: 200
558
+ };
559
+ var TURN_EVENT = "agentLock";
560
+ var OVERLAY_ID = "__chatablex_agent_lock_overlay__";
561
+ var BLOCKED_EVENTS = [
562
+ "mousedown",
563
+ "mouseup",
564
+ "click",
565
+ "dblclick",
566
+ "contextmenu",
567
+ "keydown",
568
+ "keyup",
569
+ "keypress",
570
+ "touchstart",
571
+ "touchmove",
572
+ "touchend",
573
+ "wheel",
574
+ "scroll",
575
+ "pointerdown",
576
+ "pointerup"
577
+ ];
578
+ var CANCEL_BTN_ID = "__ctx_agent_lock_cancel__";
579
+ function blockEvent(e) {
580
+ const target = e.target;
581
+ if (target?.id === CANCEL_BTN_ID) return;
582
+ e.stopPropagation();
583
+ e.preventDefault();
584
+ }
585
+ function createAgentLockModule(bridge, userConfig = {}) {
586
+ const cfg = { ...DEFAULT_CONFIG, ...userConfig };
587
+ const logoSrc = cfg.logoUrl || bee_default;
588
+ const listeners = /* @__PURE__ */ new Map();
589
+ let overlayEl = null;
590
+ let locked = false;
591
+ let lockCount = 0;
592
+ let turnActive = false;
593
+ let timeoutTimer = null;
594
+ let debounceTimer = null;
595
+ let currentMessage = cfg.message;
596
+ function emit(event, data = {}) {
597
+ const payload = { timestamp: Date.now(), ...data };
598
+ const handlers = listeners.get(event);
599
+ if (handlers) {
600
+ for (const fn of handlers) {
601
+ try {
602
+ fn(payload);
603
+ } catch (e) {
604
+ console.error("[ChatableX AgentLock] event handler error:", e);
605
+ }
606
+ }
607
+ }
608
+ }
609
+ function injectOverlay(message) {
610
+ if (typeof document === "undefined") return;
611
+ if (document.getElementById(OVERLAY_ID)) return;
612
+ const el = document.createElement("div");
613
+ el.id = OVERLAY_ID;
614
+ el.setAttribute("aria-hidden", "true");
615
+ el.style.cssText = [
616
+ "position:fixed",
617
+ "inset:0",
618
+ `z-index:2147483646`,
619
+ `background:rgba(255,255,255,${cfg.opacity})`,
620
+ "display:flex",
621
+ "flex-direction:column",
622
+ "align-items:center",
623
+ "justify-content:center",
624
+ "pointer-events:all",
625
+ "user-select:none",
626
+ "backdrop-filter:blur(1px)",
627
+ "-webkit-backdrop-filter:blur(1px)"
628
+ ].join(";");
629
+ el.innerHTML = `
630
+ <img src="${logoSrc}" alt="" style="width:48px;height:48px;animation:__ctx_spin 1.5s linear infinite;" />
631
+ <p style="margin:12px 0 0;font:14px/1.4 -apple-system,BlinkMacSystemFont,sans-serif;color:#666;">${message}</p>
632
+ ${cfg.allowCancel ? '<button id="__ctx_agent_lock_cancel__" style="margin-top:16px;background:none;border:none;color:#6366f1;font:13px -apple-system,BlinkMacSystemFont,sans-serif;cursor:pointer;text-decoration:underline;padding:4px 8px;">\u53D6\u6D88</button>' : ""}
633
+ `;
634
+ if (!document.getElementById("__ctx_agent_lock_style__")) {
635
+ const style = document.createElement("style");
636
+ style.id = "__ctx_agent_lock_style__";
637
+ style.textContent = "@keyframes __ctx_spin{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}";
638
+ document.head.appendChild(style);
639
+ }
640
+ for (const evt of BLOCKED_EVENTS) {
641
+ el.addEventListener(evt, blockEvent, { capture: true, passive: false });
642
+ }
643
+ if (cfg.allowCancel) {
644
+ queueMicrotask(() => {
645
+ const btn = el.querySelector("#__ctx_agent_lock_cancel__");
646
+ if (btn) {
647
+ btn.addEventListener("click", (e) => {
648
+ e.stopPropagation();
649
+ handleCancel();
650
+ });
651
+ }
652
+ });
653
+ }
654
+ document.body.appendChild(el);
655
+ overlayEl = el;
656
+ }
657
+ function removeOverlay() {
658
+ if (overlayEl) {
659
+ for (const evt of BLOCKED_EVENTS) {
660
+ overlayEl.removeEventListener(evt, blockEvent, { capture: true });
661
+ }
662
+ overlayEl.remove();
663
+ overlayEl = null;
664
+ }
665
+ const style = typeof document !== "undefined" ? document.getElementById("__ctx_agent_lock_style__") : null;
666
+ if (style) style.remove();
667
+ }
668
+ function startTimeout(ms, requestId) {
669
+ clearTimeoutTimer();
670
+ if (ms <= 0) return;
671
+ timeoutTimer = setTimeout(() => {
672
+ console.warn("[ChatableX] Agent lock timeout \u2014 auto-unlocking");
673
+ forceUnlock();
674
+ emit("timeout", { requestId });
675
+ }, ms);
676
+ }
677
+ function clearTimeoutTimer() {
678
+ if (timeoutTimer !== null) {
679
+ clearTimeout(timeoutTimer);
680
+ timeoutTimer = null;
681
+ }
682
+ }
683
+ function clearDebounceTimer() {
684
+ if (debounceTimer !== null) {
685
+ clearTimeout(debounceTimer);
686
+ debounceTimer = null;
687
+ }
688
+ }
689
+ function doLock(message, timeout, requestId) {
690
+ if (locked) return;
691
+ locked = true;
692
+ currentMessage = message;
693
+ if (cfg.mode === "overlay") {
694
+ injectOverlay(currentMessage);
695
+ }
696
+ startTimeout(timeout, requestId);
697
+ emit("lock", { requestId });
698
+ }
699
+ function forceUnlock(requestId) {
700
+ if (!locked) return;
701
+ locked = false;
702
+ lockCount = 0;
703
+ turnActive = false;
704
+ clearTimeoutTimer();
705
+ clearDebounceTimer();
706
+ if (cfg.mode === "overlay") {
707
+ removeOverlay();
708
+ }
709
+ emit("unlock", { requestId });
710
+ }
711
+ function maybeUnlock(requestId) {
712
+ if (turnActive || lockCount > 0) return;
713
+ forceUnlock(requestId);
714
+ }
715
+ function scheduleDebouncedUnlock(requestId) {
716
+ clearDebounceTimer();
717
+ debounceTimer = setTimeout(() => maybeUnlock(requestId), cfg.debounceUnlock);
718
+ }
719
+ function handleCancel() {
720
+ const rid = void 0;
721
+ forceUnlock(rid);
722
+ emit("cancel", { requestId: rid });
723
+ }
724
+ function setTurn(active) {
725
+ if (!cfg.enabled) return;
726
+ if (active) {
727
+ turnActive = true;
728
+ clearDebounceTimer();
729
+ if (!locked) {
730
+ doLock(cfg.message, cfg.turnTimeout);
731
+ } else {
732
+ startTimeout(cfg.turnTimeout);
733
+ }
734
+ } else {
735
+ turnActive = false;
736
+ if (lockCount === 0) scheduleDebouncedUnlock();
737
+ }
738
+ }
739
+ function lock(opts) {
740
+ if (!cfg.enabled) return;
741
+ const msg = opts?.message ?? cfg.message;
742
+ const timeout = opts?.timeout ?? cfg.timeout;
743
+ doLock(msg, timeout);
744
+ }
745
+ function unlock() {
746
+ forceUnlock();
747
+ }
748
+ function isLocked() {
749
+ return locked;
750
+ }
751
+ function on(event, handler) {
752
+ if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());
753
+ listeners.get(event).add(handler);
754
+ return () => off(event, handler);
755
+ }
756
+ function off(event, handler) {
757
+ listeners.get(event)?.delete(handler);
758
+ }
759
+ function _autoLock(requestId) {
760
+ if (!cfg.enabled) return;
761
+ clearDebounceTimer();
762
+ lockCount++;
763
+ if (!locked) {
764
+ doLock(cfg.message, turnActive ? cfg.turnTimeout : cfg.timeout, requestId);
765
+ }
766
+ }
767
+ function _autoUnlock(requestId) {
768
+ if (!cfg.enabled) return;
769
+ lockCount = Math.max(0, lockCount - 1);
770
+ if (lockCount === 0) {
771
+ scheduleDebouncedUnlock(requestId);
772
+ }
773
+ }
774
+ function _destroy() {
775
+ if (removeTurnListener) removeTurnListener();
776
+ forceUnlock();
777
+ listeners.clear();
778
+ }
779
+ const removeTurnListener = bridge.addEventListener(TURN_EVENT, (data) => {
780
+ const active = !!data?.active;
781
+ setTurn(active);
782
+ });
783
+ return { lock, unlock, isLocked, on, off, _autoLock, _autoUnlock, _destroy };
784
+ }
785
+
542
786
  // package.json
543
787
  var package_default = {
544
788
  name: "chatablex-web-sdk",
545
- version: "1.0.32",
789
+ version: "1.0.36",
546
790
  description: "ChatableX Web SDK for AI App WebUI development. Provides bridge communication with the ChatableX Flutter client.",
547
791
  main: "dist/index.js",
548
792
  module: "dist/index.mjs",
@@ -561,8 +805,8 @@ var package_default = {
561
805
  "README.zh-CN.md"
562
806
  ],
563
807
  scripts: {
564
- build: "tsup src/index.ts --format cjs,esm --dts --clean",
565
- dev: "tsup src/index.ts --format cjs,esm --dts --watch",
808
+ build: "tsup",
809
+ dev: "tsup --watch",
566
810
  typecheck: "tsc --noEmit",
567
811
  test: "vitest run",
568
812
  "test:watch": "vitest",
@@ -632,7 +876,8 @@ var ChatableX = {
632
876
  } catch {
633
877
  if (debug) console.warn("[ChatableX] sdk_init handshake failed, continuing with defaults");
634
878
  }
635
- const toolModule = createToolModule(bridge, config.appId);
879
+ const agentLockModule = createAgentLockModule(bridge, config.agentLock);
880
+ const toolModule = createToolModule(bridge, config.appId, agentLockModule);
636
881
  if (toolConfig) toolModule._setInfo(toolConfig);
637
882
  const authModule = createAuthModule(bridge);
638
883
  const sdk = {
@@ -648,7 +893,8 @@ var ChatableX = {
648
893
  appId: config.appId,
649
894
  auth: authModule,
650
895
  apiBaseUrl: config.apiBaseUrl
651
- })
896
+ }),
897
+ agentLock: agentLockModule
652
898
  };
653
899
  window.ChatableX = sdk;
654
900
  _instance = sdk;
package/dist/index.mjs CHANGED
@@ -132,7 +132,7 @@ var Bridge = class {
132
132
  };
133
133
 
134
134
  // src/modules/tool.ts
135
- function createToolModule(bridge, appId) {
135
+ function createToolModule(bridge, appId, agentLock) {
136
136
  let _info = { id: appId, name: appId, version: "1.0.0", description: "" };
137
137
  let _handler = null;
138
138
  const dispatch = async (params) => {
@@ -150,6 +150,7 @@ function createToolModule(bridge, appId) {
150
150
  bridge.addEventListener("toolExecution", async (data) => {
151
151
  const params = data;
152
152
  const requestId = params._requestId;
153
+ if (requestId && agentLock) agentLock._autoLock(requestId);
153
154
  const result = await dispatch(params);
154
155
  if (requestId && window.ChatableXBridge) {
155
156
  window.ChatableXBridge.postMessage(JSON.stringify({
@@ -157,6 +158,7 @@ function createToolModule(bridge, appId) {
157
158
  params: { _requestId: requestId, ...result }
158
159
  }));
159
160
  }
161
+ if (requestId && agentLock) agentLock._autoUnlock(requestId);
160
162
  });
161
163
  return {
162
164
  getInfo() {
@@ -507,10 +509,252 @@ function createCloudModule(bridge, deps) {
507
509
  };
508
510
  }
509
511
 
512
+ // src/assets/bee.png
513
+ var bee_default = "data:image/png;base64,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";
514
+
515
+ // src/modules/agentLock.ts
516
+ var DEFAULT_CONFIG = {
517
+ enabled: true,
518
+ mode: "overlay",
519
+ logoUrl: "",
520
+ message: "Agent \u6B63\u5728\u64CD\u4F5C\uFF0C\u8BF7\u7A0D\u5019\u2026",
521
+ allowCancel: true,
522
+ opacity: 0.3,
523
+ timeout: 3e4,
524
+ turnTimeout: 0,
525
+ debounceUnlock: 200
526
+ };
527
+ var TURN_EVENT = "agentLock";
528
+ var OVERLAY_ID = "__chatablex_agent_lock_overlay__";
529
+ var BLOCKED_EVENTS = [
530
+ "mousedown",
531
+ "mouseup",
532
+ "click",
533
+ "dblclick",
534
+ "contextmenu",
535
+ "keydown",
536
+ "keyup",
537
+ "keypress",
538
+ "touchstart",
539
+ "touchmove",
540
+ "touchend",
541
+ "wheel",
542
+ "scroll",
543
+ "pointerdown",
544
+ "pointerup"
545
+ ];
546
+ var CANCEL_BTN_ID = "__ctx_agent_lock_cancel__";
547
+ function blockEvent(e) {
548
+ const target = e.target;
549
+ if (target?.id === CANCEL_BTN_ID) return;
550
+ e.stopPropagation();
551
+ e.preventDefault();
552
+ }
553
+ function createAgentLockModule(bridge, userConfig = {}) {
554
+ const cfg = { ...DEFAULT_CONFIG, ...userConfig };
555
+ const logoSrc = cfg.logoUrl || bee_default;
556
+ const listeners = /* @__PURE__ */ new Map();
557
+ let overlayEl = null;
558
+ let locked = false;
559
+ let lockCount = 0;
560
+ let turnActive = false;
561
+ let timeoutTimer = null;
562
+ let debounceTimer = null;
563
+ let currentMessage = cfg.message;
564
+ function emit(event, data = {}) {
565
+ const payload = { timestamp: Date.now(), ...data };
566
+ const handlers = listeners.get(event);
567
+ if (handlers) {
568
+ for (const fn of handlers) {
569
+ try {
570
+ fn(payload);
571
+ } catch (e) {
572
+ console.error("[ChatableX AgentLock] event handler error:", e);
573
+ }
574
+ }
575
+ }
576
+ }
577
+ function injectOverlay(message) {
578
+ if (typeof document === "undefined") return;
579
+ if (document.getElementById(OVERLAY_ID)) return;
580
+ const el = document.createElement("div");
581
+ el.id = OVERLAY_ID;
582
+ el.setAttribute("aria-hidden", "true");
583
+ el.style.cssText = [
584
+ "position:fixed",
585
+ "inset:0",
586
+ `z-index:2147483646`,
587
+ `background:rgba(255,255,255,${cfg.opacity})`,
588
+ "display:flex",
589
+ "flex-direction:column",
590
+ "align-items:center",
591
+ "justify-content:center",
592
+ "pointer-events:all",
593
+ "user-select:none",
594
+ "backdrop-filter:blur(1px)",
595
+ "-webkit-backdrop-filter:blur(1px)"
596
+ ].join(";");
597
+ el.innerHTML = `
598
+ <img src="${logoSrc}" alt="" style="width:48px;height:48px;animation:__ctx_spin 1.5s linear infinite;" />
599
+ <p style="margin:12px 0 0;font:14px/1.4 -apple-system,BlinkMacSystemFont,sans-serif;color:#666;">${message}</p>
600
+ ${cfg.allowCancel ? '<button id="__ctx_agent_lock_cancel__" style="margin-top:16px;background:none;border:none;color:#6366f1;font:13px -apple-system,BlinkMacSystemFont,sans-serif;cursor:pointer;text-decoration:underline;padding:4px 8px;">\u53D6\u6D88</button>' : ""}
601
+ `;
602
+ if (!document.getElementById("__ctx_agent_lock_style__")) {
603
+ const style = document.createElement("style");
604
+ style.id = "__ctx_agent_lock_style__";
605
+ style.textContent = "@keyframes __ctx_spin{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}";
606
+ document.head.appendChild(style);
607
+ }
608
+ for (const evt of BLOCKED_EVENTS) {
609
+ el.addEventListener(evt, blockEvent, { capture: true, passive: false });
610
+ }
611
+ if (cfg.allowCancel) {
612
+ queueMicrotask(() => {
613
+ const btn = el.querySelector("#__ctx_agent_lock_cancel__");
614
+ if (btn) {
615
+ btn.addEventListener("click", (e) => {
616
+ e.stopPropagation();
617
+ handleCancel();
618
+ });
619
+ }
620
+ });
621
+ }
622
+ document.body.appendChild(el);
623
+ overlayEl = el;
624
+ }
625
+ function removeOverlay() {
626
+ if (overlayEl) {
627
+ for (const evt of BLOCKED_EVENTS) {
628
+ overlayEl.removeEventListener(evt, blockEvent, { capture: true });
629
+ }
630
+ overlayEl.remove();
631
+ overlayEl = null;
632
+ }
633
+ const style = typeof document !== "undefined" ? document.getElementById("__ctx_agent_lock_style__") : null;
634
+ if (style) style.remove();
635
+ }
636
+ function startTimeout(ms, requestId) {
637
+ clearTimeoutTimer();
638
+ if (ms <= 0) return;
639
+ timeoutTimer = setTimeout(() => {
640
+ console.warn("[ChatableX] Agent lock timeout \u2014 auto-unlocking");
641
+ forceUnlock();
642
+ emit("timeout", { requestId });
643
+ }, ms);
644
+ }
645
+ function clearTimeoutTimer() {
646
+ if (timeoutTimer !== null) {
647
+ clearTimeout(timeoutTimer);
648
+ timeoutTimer = null;
649
+ }
650
+ }
651
+ function clearDebounceTimer() {
652
+ if (debounceTimer !== null) {
653
+ clearTimeout(debounceTimer);
654
+ debounceTimer = null;
655
+ }
656
+ }
657
+ function doLock(message, timeout, requestId) {
658
+ if (locked) return;
659
+ locked = true;
660
+ currentMessage = message;
661
+ if (cfg.mode === "overlay") {
662
+ injectOverlay(currentMessage);
663
+ }
664
+ startTimeout(timeout, requestId);
665
+ emit("lock", { requestId });
666
+ }
667
+ function forceUnlock(requestId) {
668
+ if (!locked) return;
669
+ locked = false;
670
+ lockCount = 0;
671
+ turnActive = false;
672
+ clearTimeoutTimer();
673
+ clearDebounceTimer();
674
+ if (cfg.mode === "overlay") {
675
+ removeOverlay();
676
+ }
677
+ emit("unlock", { requestId });
678
+ }
679
+ function maybeUnlock(requestId) {
680
+ if (turnActive || lockCount > 0) return;
681
+ forceUnlock(requestId);
682
+ }
683
+ function scheduleDebouncedUnlock(requestId) {
684
+ clearDebounceTimer();
685
+ debounceTimer = setTimeout(() => maybeUnlock(requestId), cfg.debounceUnlock);
686
+ }
687
+ function handleCancel() {
688
+ const rid = void 0;
689
+ forceUnlock(rid);
690
+ emit("cancel", { requestId: rid });
691
+ }
692
+ function setTurn(active) {
693
+ if (!cfg.enabled) return;
694
+ if (active) {
695
+ turnActive = true;
696
+ clearDebounceTimer();
697
+ if (!locked) {
698
+ doLock(cfg.message, cfg.turnTimeout);
699
+ } else {
700
+ startTimeout(cfg.turnTimeout);
701
+ }
702
+ } else {
703
+ turnActive = false;
704
+ if (lockCount === 0) scheduleDebouncedUnlock();
705
+ }
706
+ }
707
+ function lock(opts) {
708
+ if (!cfg.enabled) return;
709
+ const msg = opts?.message ?? cfg.message;
710
+ const timeout = opts?.timeout ?? cfg.timeout;
711
+ doLock(msg, timeout);
712
+ }
713
+ function unlock() {
714
+ forceUnlock();
715
+ }
716
+ function isLocked() {
717
+ return locked;
718
+ }
719
+ function on(event, handler) {
720
+ if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());
721
+ listeners.get(event).add(handler);
722
+ return () => off(event, handler);
723
+ }
724
+ function off(event, handler) {
725
+ listeners.get(event)?.delete(handler);
726
+ }
727
+ function _autoLock(requestId) {
728
+ if (!cfg.enabled) return;
729
+ clearDebounceTimer();
730
+ lockCount++;
731
+ if (!locked) {
732
+ doLock(cfg.message, turnActive ? cfg.turnTimeout : cfg.timeout, requestId);
733
+ }
734
+ }
735
+ function _autoUnlock(requestId) {
736
+ if (!cfg.enabled) return;
737
+ lockCount = Math.max(0, lockCount - 1);
738
+ if (lockCount === 0) {
739
+ scheduleDebouncedUnlock(requestId);
740
+ }
741
+ }
742
+ function _destroy() {
743
+ if (removeTurnListener) removeTurnListener();
744
+ forceUnlock();
745
+ listeners.clear();
746
+ }
747
+ const removeTurnListener = bridge.addEventListener(TURN_EVENT, (data) => {
748
+ const active = !!data?.active;
749
+ setTurn(active);
750
+ });
751
+ return { lock, unlock, isLocked, on, off, _autoLock, _autoUnlock, _destroy };
752
+ }
753
+
510
754
  // package.json
511
755
  var package_default = {
512
756
  name: "chatablex-web-sdk",
513
- version: "1.0.32",
757
+ version: "1.0.36",
514
758
  description: "ChatableX Web SDK for AI App WebUI development. Provides bridge communication with the ChatableX Flutter client.",
515
759
  main: "dist/index.js",
516
760
  module: "dist/index.mjs",
@@ -529,8 +773,8 @@ var package_default = {
529
773
  "README.zh-CN.md"
530
774
  ],
531
775
  scripts: {
532
- build: "tsup src/index.ts --format cjs,esm --dts --clean",
533
- dev: "tsup src/index.ts --format cjs,esm --dts --watch",
776
+ build: "tsup",
777
+ dev: "tsup --watch",
534
778
  typecheck: "tsc --noEmit",
535
779
  test: "vitest run",
536
780
  "test:watch": "vitest",
@@ -600,7 +844,8 @@ var ChatableX = {
600
844
  } catch {
601
845
  if (debug) console.warn("[ChatableX] sdk_init handshake failed, continuing with defaults");
602
846
  }
603
- const toolModule = createToolModule(bridge, config.appId);
847
+ const agentLockModule = createAgentLockModule(bridge, config.agentLock);
848
+ const toolModule = createToolModule(bridge, config.appId, agentLockModule);
604
849
  if (toolConfig) toolModule._setInfo(toolConfig);
605
850
  const authModule = createAuthModule(bridge);
606
851
  const sdk = {
@@ -616,7 +861,8 @@ var ChatableX = {
616
861
  appId: config.appId,
617
862
  auth: authModule,
618
863
  apiBaseUrl: config.apiBaseUrl
619
- })
864
+ }),
865
+ agentLock: agentLockModule
620
866
  };
621
867
  window.ChatableX = sdk;
622
868
  _instance = sdk;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chatablex-web-sdk",
3
- "version": "1.0.32",
3
+ "version": "1.0.36",
4
4
  "description": "ChatableX Web SDK for AI App WebUI development. Provides bridge communication with the ChatableX Flutter client.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -19,8 +19,8 @@
19
19
  "README.zh-CN.md"
20
20
  ],
21
21
  "scripts": {
22
- "build": "tsup src/index.ts --format cjs,esm --dts --clean",
23
- "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
22
+ "build": "tsup",
23
+ "dev": "tsup --watch",
24
24
  "typecheck": "tsc --noEmit",
25
25
  "test": "vitest run",
26
26
  "test:watch": "vitest",
Binary file
@@ -0,0 +1,4 @@
1
+ declare module '*.png' {
2
+ const dataUrl: string;
3
+ export default dataUrl;
4
+ }
package/src/index.ts CHANGED
@@ -28,6 +28,7 @@ import { createToolsModule } from './modules/tools';
28
28
  import { createPlatformModule } from './modules/platform';
29
29
  import { createAuthModule } from './modules/auth';
30
30
  import { createCloudModule } from './modules/cloud';
31
+ import { createAgentLockModule } from './modules/agentLock';
31
32
  import type { ChatableXSDK, ChatableXInitConfig, ToolInfo } from './types';
32
33
  import pkg from '../package.json';
33
34
 
@@ -77,7 +78,9 @@ export const ChatableX = {
77
78
  }
78
79
 
79
80
  // 4. Create modules
80
- const toolModule = createToolModule(bridge, config.appId);
81
+ const agentLockModule = createAgentLockModule(bridge, config.agentLock);
82
+
83
+ const toolModule = createToolModule(bridge, config.appId, agentLockModule);
81
84
  if (toolConfig) toolModule._setInfo(toolConfig);
82
85
 
83
86
  const authModule = createAuthModule(bridge);
@@ -96,6 +99,7 @@ export const ChatableX = {
96
99
  auth: authModule,
97
100
  apiBaseUrl: config.apiBaseUrl,
98
101
  }),
102
+ agentLock: agentLockModule,
99
103
  };
100
104
 
101
105
  // Expose on window for debugging / Flutter interop
@@ -0,0 +1,313 @@
1
+ import type { Bridge } from '../bridge';
2
+ import type {
3
+ AgentLockConfig,
4
+ AgentLockEventType,
5
+ AgentLockEventData,
6
+ AgentLockEventHandler,
7
+ ChatableXAgentLock,
8
+ } from '../types';
9
+ import beeLogo from '../assets/bee.png';
10
+
11
+ const DEFAULT_CONFIG: Required<AgentLockConfig> = {
12
+ enabled: true,
13
+ mode: 'overlay',
14
+ logoUrl: '',
15
+ message: 'Agent 正在操作,请稍候…',
16
+ allowCancel: true,
17
+ opacity: 0.3,
18
+ timeout: 30_000,
19
+ turnTimeout: 0,
20
+ debounceUnlock: 200,
21
+ };
22
+
23
+ /**
24
+ * Bridge event pushed by the Flutter host to lock the UI for the *entire* agent
25
+ * turn (from the moment the agent starts responding until the turn ends),
26
+ * rather than only during each individual tool execution. Payload: `{ active }`.
27
+ */
28
+ const TURN_EVENT = 'agentLock';
29
+
30
+ const OVERLAY_ID = '__chatablex_agent_lock_overlay__';
31
+
32
+ /**
33
+ * Blocked event types — we intercept these on the overlay to prevent user
34
+ * interaction from reaching the app underneath.
35
+ */
36
+ const BLOCKED_EVENTS: string[] = [
37
+ 'mousedown', 'mouseup', 'click', 'dblclick', 'contextmenu',
38
+ 'keydown', 'keyup', 'keypress',
39
+ 'touchstart', 'touchmove', 'touchend',
40
+ 'wheel', 'scroll',
41
+ 'pointerdown', 'pointerup',
42
+ ];
43
+
44
+ const CANCEL_BTN_ID = '__ctx_agent_lock_cancel__';
45
+
46
+ function blockEvent(e: Event): void {
47
+ const target = e.target as HTMLElement | null;
48
+ if (target?.id === CANCEL_BTN_ID) return;
49
+ e.stopPropagation();
50
+ e.preventDefault();
51
+ }
52
+
53
+ export interface AgentLockModule extends ChatableXAgentLock {
54
+ /**
55
+ * @internal — called by tool module to lock before dispatch and schedule
56
+ * unlock after result. Uses ref-counting to support consecutive tools.
57
+ */
58
+ _autoLock(requestId: string): void;
59
+ /** @internal */
60
+ _autoUnlock(requestId: string): void;
61
+ /** @internal */
62
+ _destroy(): void;
63
+ }
64
+
65
+ export function createAgentLockModule(
66
+ bridge: Bridge,
67
+ userConfig: AgentLockConfig = {},
68
+ ): AgentLockModule {
69
+ const cfg: Required<AgentLockConfig> = { ...DEFAULT_CONFIG, ...userConfig };
70
+ const logoSrc = cfg.logoUrl || beeLogo;
71
+
72
+ const listeners = new Map<AgentLockEventType, Set<AgentLockEventHandler>>();
73
+ let overlayEl: HTMLDivElement | null = null;
74
+ let locked = false;
75
+ let lockCount = 0;
76
+ /**
77
+ * True while an agent *turn* is in progress (driven by the host's
78
+ * {@link TURN_EVENT}). Keeps the overlay up across the whole response — and
79
+ * across the gaps between individual tool calls — until the turn ends.
80
+ */
81
+ let turnActive = false;
82
+ let timeoutTimer: ReturnType<typeof setTimeout> | null = null;
83
+ let debounceTimer: ReturnType<typeof setTimeout> | null = null;
84
+ let currentMessage = cfg.message;
85
+
86
+ function emit(event: AgentLockEventType, data: Partial<AgentLockEventData> = {}): void {
87
+ const payload: AgentLockEventData = { timestamp: Date.now(), ...data };
88
+ const handlers = listeners.get(event);
89
+ if (handlers) {
90
+ for (const fn of handlers) {
91
+ try { fn(payload); } catch (e) { console.error('[ChatableX AgentLock] event handler error:', e); }
92
+ }
93
+ }
94
+ }
95
+
96
+ function injectOverlay(message: string): void {
97
+ if (typeof document === 'undefined') return;
98
+ if (document.getElementById(OVERLAY_ID)) return;
99
+
100
+ const el = document.createElement('div');
101
+ el.id = OVERLAY_ID;
102
+ el.setAttribute('aria-hidden', 'true');
103
+ el.style.cssText = [
104
+ 'position:fixed', 'inset:0', `z-index:2147483646`,
105
+ `background:rgba(255,255,255,${cfg.opacity})`,
106
+ 'display:flex', 'flex-direction:column',
107
+ 'align-items:center', 'justify-content:center',
108
+ 'pointer-events:all', 'user-select:none',
109
+ 'backdrop-filter:blur(1px)', '-webkit-backdrop-filter:blur(1px)',
110
+ ].join(';');
111
+
112
+ el.innerHTML = `
113
+ <img src="${logoSrc}" alt="" style="width:48px;height:48px;animation:__ctx_spin 1.5s linear infinite;" />
114
+ <p style="margin:12px 0 0;font:14px/1.4 -apple-system,BlinkMacSystemFont,sans-serif;color:#666;">${message}</p>
115
+ ${cfg.allowCancel ? '<button id="__ctx_agent_lock_cancel__" style="margin-top:16px;background:none;border:none;color:#6366f1;font:13px -apple-system,BlinkMacSystemFont,sans-serif;cursor:pointer;text-decoration:underline;padding:4px 8px;">取消</button>' : ''}
116
+ `;
117
+
118
+ if (!document.getElementById('__ctx_agent_lock_style__')) {
119
+ const style = document.createElement('style');
120
+ style.id = '__ctx_agent_lock_style__';
121
+ style.textContent = '@keyframes __ctx_spin{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}';
122
+ document.head.appendChild(style);
123
+ }
124
+
125
+ for (const evt of BLOCKED_EVENTS) {
126
+ el.addEventListener(evt, blockEvent, { capture: true, passive: false });
127
+ }
128
+
129
+ if (cfg.allowCancel) {
130
+ // Defer binding so the DOM is ready
131
+ queueMicrotask(() => {
132
+ const btn = el.querySelector('#__ctx_agent_lock_cancel__');
133
+ if (btn) {
134
+ btn.addEventListener('click', (e) => {
135
+ e.stopPropagation();
136
+ handleCancel();
137
+ });
138
+ }
139
+ });
140
+ }
141
+
142
+ document.body.appendChild(el);
143
+ overlayEl = el;
144
+ }
145
+
146
+ function removeOverlay(): void {
147
+ if (overlayEl) {
148
+ for (const evt of BLOCKED_EVENTS) {
149
+ overlayEl.removeEventListener(evt, blockEvent, { capture: true } as EventListenerOptions);
150
+ }
151
+ overlayEl.remove();
152
+ overlayEl = null;
153
+ }
154
+ const style = typeof document !== 'undefined' ? document.getElementById('__ctx_agent_lock_style__') : null;
155
+ if (style) style.remove();
156
+ }
157
+
158
+ function startTimeout(ms: number, requestId?: string): void {
159
+ clearTimeoutTimer();
160
+ if (ms <= 0) return;
161
+ timeoutTimer = setTimeout(() => {
162
+ console.warn('[ChatableX] Agent lock timeout — auto-unlocking');
163
+ forceUnlock();
164
+ emit('timeout', { requestId });
165
+ }, ms);
166
+ }
167
+
168
+ function clearTimeoutTimer(): void {
169
+ if (timeoutTimer !== null) {
170
+ clearTimeout(timeoutTimer);
171
+ timeoutTimer = null;
172
+ }
173
+ }
174
+
175
+ function clearDebounceTimer(): void {
176
+ if (debounceTimer !== null) {
177
+ clearTimeout(debounceTimer);
178
+ debounceTimer = null;
179
+ }
180
+ }
181
+
182
+ function doLock(message: string, timeout: number, requestId?: string): void {
183
+ if (locked) return;
184
+ locked = true;
185
+ currentMessage = message;
186
+
187
+ if (cfg.mode === 'overlay') {
188
+ injectOverlay(currentMessage);
189
+ }
190
+ startTimeout(timeout, requestId);
191
+ emit('lock', { requestId });
192
+ }
193
+
194
+ function forceUnlock(requestId?: string): void {
195
+ if (!locked) return;
196
+ locked = false;
197
+ lockCount = 0;
198
+ turnActive = false;
199
+ clearTimeoutTimer();
200
+ clearDebounceTimer();
201
+ if (cfg.mode === 'overlay') {
202
+ removeOverlay();
203
+ }
204
+ emit('unlock', { requestId });
205
+ }
206
+
207
+ /**
208
+ * Release the lock only when nothing is still holding it — i.e. no agent turn
209
+ * is in progress and no tool execution is outstanding. This is what keeps the
210
+ * overlay from flickering off between tools or mid-turn.
211
+ */
212
+ function maybeUnlock(requestId?: string): void {
213
+ if (turnActive || lockCount > 0) return;
214
+ forceUnlock(requestId);
215
+ }
216
+
217
+ function scheduleDebouncedUnlock(requestId?: string): void {
218
+ clearDebounceTimer();
219
+ debounceTimer = setTimeout(() => maybeUnlock(requestId), cfg.debounceUnlock);
220
+ }
221
+
222
+ function handleCancel(): void {
223
+ const rid = undefined; // auto mode tracks this externally
224
+ // Explicit user cancel wins over any in-progress turn/tool tracking.
225
+ forceUnlock(rid);
226
+ emit('cancel', { requestId: rid });
227
+ }
228
+
229
+ /**
230
+ * Turn-level lock driven by the host (see {@link TURN_EVENT}). Holds the
231
+ * overlay for the entire agent response; tool-level auto lock/unlock nests
232
+ * inside without tearing the overlay down.
233
+ */
234
+ function setTurn(active: boolean): void {
235
+ if (!cfg.enabled) return;
236
+ if (active) {
237
+ turnActive = true;
238
+ clearDebounceTimer();
239
+ if (!locked) {
240
+ doLock(cfg.message, cfg.turnTimeout);
241
+ } else {
242
+ // Already locked by a tool — extend its timeout to the (longer) turn
243
+ // budget so a 30s tool timeout can't drop the overlay mid-turn.
244
+ startTimeout(cfg.turnTimeout);
245
+ }
246
+ } else {
247
+ turnActive = false;
248
+ if (lockCount === 0) scheduleDebouncedUnlock();
249
+ }
250
+ }
251
+
252
+ // Public API -----------------------------------------------------------------
253
+
254
+ function lock(opts?: { message?: string; timeout?: number }): void {
255
+ if (!cfg.enabled) return;
256
+ const msg = opts?.message ?? cfg.message;
257
+ const timeout = opts?.timeout ?? cfg.timeout;
258
+ doLock(msg, timeout);
259
+ }
260
+
261
+ function unlock(): void {
262
+ forceUnlock();
263
+ }
264
+
265
+ function isLocked(): boolean {
266
+ return locked;
267
+ }
268
+
269
+ function on(event: AgentLockEventType, handler: AgentLockEventHandler): () => void {
270
+ if (!listeners.has(event)) listeners.set(event, new Set());
271
+ listeners.get(event)!.add(handler);
272
+ return () => off(event, handler);
273
+ }
274
+
275
+ function off(event: AgentLockEventType, handler: AgentLockEventHandler): void {
276
+ listeners.get(event)?.delete(handler);
277
+ }
278
+
279
+ // Internal auto-mode API (called by tool module) ----------------------------
280
+
281
+ function _autoLock(requestId: string): void {
282
+ if (!cfg.enabled) return;
283
+ clearDebounceTimer();
284
+ lockCount++;
285
+ if (!locked) {
286
+ // Inside a turn the (longer) turn budget governs; standalone tool calls
287
+ // keep the per-tool timeout.
288
+ doLock(cfg.message, turnActive ? cfg.turnTimeout : cfg.timeout, requestId);
289
+ }
290
+ }
291
+
292
+ function _autoUnlock(requestId: string): void {
293
+ if (!cfg.enabled) return;
294
+ lockCount = Math.max(0, lockCount - 1);
295
+ if (lockCount === 0) {
296
+ scheduleDebouncedUnlock(requestId);
297
+ }
298
+ }
299
+
300
+ function _destroy(): void {
301
+ if (removeTurnListener) removeTurnListener();
302
+ forceUnlock();
303
+ listeners.clear();
304
+ }
305
+
306
+ // Listen for host-driven turn lock/unlock. Payload shape: `{ active: boolean }`.
307
+ const removeTurnListener = bridge.addEventListener(TURN_EVENT, (data) => {
308
+ const active = !!(data as { active?: unknown } | undefined)?.active;
309
+ setTurn(active);
310
+ });
311
+
312
+ return { lock, unlock, isLocked, on, off, _autoLock, _autoUnlock, _destroy };
313
+ }
@@ -1,11 +1,16 @@
1
1
  import type { Bridge } from '../bridge';
2
2
  import type { ToolInfo, ToolExecuteHandler, ChatableXToolModule } from '../types';
3
+ import type { AgentLockModule } from './agentLock';
3
4
 
4
5
  /**
5
6
  * Creates the `sdk.tool` module — the primary interface for LLM-driven
6
7
  * tool execution in a ChatableX WebUI app.
7
8
  */
8
- export function createToolModule(bridge: Bridge, appId: string): ChatableXToolModule & { _setInfo(info: Partial<ToolInfo>): void } {
9
+ export function createToolModule(
10
+ bridge: Bridge,
11
+ appId: string,
12
+ agentLock?: AgentLockModule,
13
+ ): ChatableXToolModule & { _setInfo(info: Partial<ToolInfo>): void } {
9
14
  let _info: ToolInfo = { id: appId, name: appId, version: '1.0.0', description: '' };
10
15
  let _handler: ToolExecuteHandler | null = null;
11
16
 
@@ -30,13 +35,19 @@ export function createToolModule(bridge: Bridge, appId: string): ChatableXToolMo
30
35
  bridge.addEventListener('toolExecution', async (data) => {
31
36
  const params = data as Record<string, unknown>;
32
37
  const requestId = params._requestId as string | undefined;
38
+
39
+ if (requestId && agentLock) agentLock._autoLock(requestId);
40
+
33
41
  const result = await dispatch(params);
42
+
34
43
  if (requestId && window.ChatableXBridge) {
35
44
  window.ChatableXBridge.postMessage(JSON.stringify({
36
45
  method: 'tool.executeResult',
37
46
  params: { _requestId: requestId, ...result },
38
47
  }));
39
48
  }
49
+
50
+ if (requestId && agentLock) agentLock._autoUnlock(requestId);
40
51
  });
41
52
 
42
53
  return {
package/src/types.ts CHANGED
@@ -169,6 +169,8 @@ export interface ChatableXInitConfig {
169
169
  * calls reject with a clear error.
170
170
  */
171
171
  apiBaseUrl?: string;
172
+ /** Agent lock configuration — blocks user input during tool execution. */
173
+ agentLock?: AgentLockConfig;
172
174
  }
173
175
 
174
176
  // ---------------------------------------------------------------------------
@@ -332,6 +334,61 @@ export interface ChatableXCloud {
332
334
  usage(): Promise<CloudUsage>;
333
335
  }
334
336
 
337
+ // ---------------------------------------------------------------------------
338
+ // Agent Lock
339
+ // ---------------------------------------------------------------------------
340
+
341
+ export interface AgentLockConfig {
342
+ /** Enable the agent lock feature (default: true). */
343
+ enabled?: boolean;
344
+ /**
345
+ * `"overlay"` — SDK renders a built-in transparent overlay (default).
346
+ * `"events-only"` — SDK only emits lock/unlock events; no overlay injected.
347
+ */
348
+ mode?: 'overlay' | 'events-only';
349
+ /** URL of the logo displayed in the overlay centre. Defaults to built-in Chatablex SVG. */
350
+ logoUrl?: string;
351
+ /** Message shown below the logo (default: "Agent 正在操作,请稍候…"). */
352
+ message?: string;
353
+ /** Show a cancel button on the overlay (default: true). */
354
+ allowCancel?: boolean;
355
+ /** Overlay background opacity, 0–1 (default: 0.3). */
356
+ opacity?: number;
357
+ /** Auto-unlock timeout for a single tool execution, in ms (default: 30000). 0 disables. */
358
+ timeout?: number;
359
+ /**
360
+ * Safety auto-unlock timeout for a whole agent turn, in ms (default: 0 =
361
+ * disabled, rely on the host's turn-end signal). When the host drives a
362
+ * turn-level lock (the lock spans the entire agent response, not just one
363
+ * tool), this acts purely as a fallback in case the turn-end signal is lost.
364
+ */
365
+ turnTimeout?: number;
366
+ /** Delay before actually removing the overlay after unlock, to avoid flicker between consecutive tools (default: 200ms). */
367
+ debounceUnlock?: number;
368
+ }
369
+
370
+ export type AgentLockEventType = 'lock' | 'unlock' | 'cancel' | 'timeout';
371
+
372
+ export interface AgentLockEventData {
373
+ requestId?: string;
374
+ timestamp: number;
375
+ }
376
+
377
+ export type AgentLockEventHandler = (data: AgentLockEventData) => void;
378
+
379
+ export interface ChatableXAgentLock {
380
+ /** Manually lock user interaction with an optional custom message / timeout. */
381
+ lock(opts?: { message?: string; timeout?: number }): void;
382
+ /** Manually unlock. Safe to call when already unlocked. */
383
+ unlock(): void;
384
+ /** Whether the overlay is currently active. */
385
+ isLocked(): boolean;
386
+ /** Subscribe to lock lifecycle events. Returns an unsubscribe function. */
387
+ on(event: AgentLockEventType, handler: AgentLockEventHandler): () => void;
388
+ /** Remove a previously registered handler. */
389
+ off(event: AgentLockEventType, handler: AgentLockEventHandler): void;
390
+ }
391
+
335
392
  export interface ChatableXSDK {
336
393
  ai: ChatableXAI;
337
394
  tools: ChatableXTools;
@@ -342,6 +399,7 @@ export interface ChatableXSDK {
342
399
  platform: ChatableXPlatform;
343
400
  auth: ChatableXAuth;
344
401
  cloud: ChatableXCloud;
402
+ agentLock: ChatableXAgentLock;
345
403
  }
346
404
 
347
405
  // ---------------------------------------------------------------------------