chatablex-web-sdk 1.0.32 → 1.0.34

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,48 @@ 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 in ms (default: 30000). 0 disables. */
283
+ timeout?: number;
284
+ /** Delay before actually removing the overlay after unlock, to avoid flicker between consecutive tools (default: 200ms). */
285
+ debounceUnlock?: number;
286
+ }
287
+ type AgentLockEventType = 'lock' | 'unlock' | 'cancel' | 'timeout';
288
+ interface AgentLockEventData {
289
+ requestId?: string;
290
+ timestamp: number;
291
+ }
292
+ type AgentLockEventHandler = (data: AgentLockEventData) => void;
293
+ interface ChatableXAgentLock {
294
+ /** Manually lock user interaction with an optional custom message / timeout. */
295
+ lock(opts?: {
296
+ message?: string;
297
+ timeout?: number;
298
+ }): void;
299
+ /** Manually unlock. Safe to call when already unlocked. */
300
+ unlock(): void;
301
+ /** Whether the overlay is currently active. */
302
+ isLocked(): boolean;
303
+ /** Subscribe to lock lifecycle events. Returns an unsubscribe function. */
304
+ on(event: AgentLockEventType, handler: AgentLockEventHandler): () => void;
305
+ /** Remove a previously registered handler. */
306
+ off(event: AgentLockEventType, handler: AgentLockEventHandler): void;
307
+ }
264
308
  interface ChatableXSDK {
265
309
  ai: ChatableXAI;
266
310
  tools: ChatableXTools;
@@ -271,6 +315,7 @@ interface ChatableXSDK {
271
315
  platform: ChatableXPlatform;
272
316
  auth: ChatableXAuth;
273
317
  cloud: ChatableXCloud;
318
+ agentLock: ChatableXAgentLock;
274
319
  }
275
320
  declare global {
276
321
  interface Window {
@@ -386,4 +431,4 @@ declare const ChatableX: {
386
431
  version: string;
387
432
  };
388
433
 
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 };
434
+ 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,48 @@ 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 in ms (default: 30000). 0 disables. */
283
+ timeout?: number;
284
+ /** Delay before actually removing the overlay after unlock, to avoid flicker between consecutive tools (default: 200ms). */
285
+ debounceUnlock?: number;
286
+ }
287
+ type AgentLockEventType = 'lock' | 'unlock' | 'cancel' | 'timeout';
288
+ interface AgentLockEventData {
289
+ requestId?: string;
290
+ timestamp: number;
291
+ }
292
+ type AgentLockEventHandler = (data: AgentLockEventData) => void;
293
+ interface ChatableXAgentLock {
294
+ /** Manually lock user interaction with an optional custom message / timeout. */
295
+ lock(opts?: {
296
+ message?: string;
297
+ timeout?: number;
298
+ }): void;
299
+ /** Manually unlock. Safe to call when already unlocked. */
300
+ unlock(): void;
301
+ /** Whether the overlay is currently active. */
302
+ isLocked(): boolean;
303
+ /** Subscribe to lock lifecycle events. Returns an unsubscribe function. */
304
+ on(event: AgentLockEventType, handler: AgentLockEventHandler): () => void;
305
+ /** Remove a previously registered handler. */
306
+ off(event: AgentLockEventType, handler: AgentLockEventHandler): void;
307
+ }
264
308
  interface ChatableXSDK {
265
309
  ai: ChatableXAI;
266
310
  tools: ChatableXTools;
@@ -271,6 +315,7 @@ interface ChatableXSDK {
271
315
  platform: ChatableXPlatform;
272
316
  auth: ChatableXAuth;
273
317
  cloud: ChatableXCloud;
318
+ agentLock: ChatableXAgentLock;
274
319
  }
275
320
  declare global {
276
321
  interface Window {
@@ -386,4 +431,4 @@ declare const ChatableX: {
386
431
  version: string;
387
432
  };
388
433
 
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 };
434
+ 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,225 @@ 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
+ debounceUnlock: 200
557
+ };
558
+ var OVERLAY_ID = "__chatablex_agent_lock_overlay__";
559
+ var BLOCKED_EVENTS = [
560
+ "mousedown",
561
+ "mouseup",
562
+ "click",
563
+ "dblclick",
564
+ "contextmenu",
565
+ "keydown",
566
+ "keyup",
567
+ "keypress",
568
+ "touchstart",
569
+ "touchmove",
570
+ "touchend",
571
+ "wheel",
572
+ "scroll",
573
+ "pointerdown",
574
+ "pointerup"
575
+ ];
576
+ var CANCEL_BTN_ID = "__ctx_agent_lock_cancel__";
577
+ function blockEvent(e) {
578
+ const target = e.target;
579
+ if (target?.id === CANCEL_BTN_ID) return;
580
+ e.stopPropagation();
581
+ e.preventDefault();
582
+ }
583
+ function createAgentLockModule(_bridge, userConfig = {}) {
584
+ const cfg = { ...DEFAULT_CONFIG, ...userConfig };
585
+ const logoSrc = cfg.logoUrl || bee_default;
586
+ const listeners = /* @__PURE__ */ new Map();
587
+ let overlayEl = null;
588
+ let locked = false;
589
+ let lockCount = 0;
590
+ let timeoutTimer = null;
591
+ let debounceTimer = null;
592
+ let currentMessage = cfg.message;
593
+ function emit(event, data = {}) {
594
+ const payload = { timestamp: Date.now(), ...data };
595
+ const handlers = listeners.get(event);
596
+ if (handlers) {
597
+ for (const fn of handlers) {
598
+ try {
599
+ fn(payload);
600
+ } catch (e) {
601
+ console.error("[ChatableX AgentLock] event handler error:", e);
602
+ }
603
+ }
604
+ }
605
+ }
606
+ function injectOverlay(message) {
607
+ if (typeof document === "undefined") return;
608
+ if (document.getElementById(OVERLAY_ID)) return;
609
+ const el = document.createElement("div");
610
+ el.id = OVERLAY_ID;
611
+ el.setAttribute("aria-hidden", "true");
612
+ el.style.cssText = [
613
+ "position:fixed",
614
+ "inset:0",
615
+ `z-index:2147483646`,
616
+ `background:rgba(255,255,255,${cfg.opacity})`,
617
+ "display:flex",
618
+ "flex-direction:column",
619
+ "align-items:center",
620
+ "justify-content:center",
621
+ "pointer-events:all",
622
+ "user-select:none",
623
+ "backdrop-filter:blur(1px)",
624
+ "-webkit-backdrop-filter:blur(1px)"
625
+ ].join(";");
626
+ el.innerHTML = `
627
+ <img src="${logoSrc}" alt="" style="width:48px;height:48px;animation:__ctx_spin 1.5s linear infinite;" />
628
+ <p style="margin:12px 0 0;font:14px/1.4 -apple-system,BlinkMacSystemFont,sans-serif;color:#666;">${message}</p>
629
+ ${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>' : ""}
630
+ `;
631
+ if (!document.getElementById("__ctx_agent_lock_style__")) {
632
+ const style = document.createElement("style");
633
+ style.id = "__ctx_agent_lock_style__";
634
+ style.textContent = "@keyframes __ctx_spin{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}";
635
+ document.head.appendChild(style);
636
+ }
637
+ for (const evt of BLOCKED_EVENTS) {
638
+ el.addEventListener(evt, blockEvent, { capture: true, passive: false });
639
+ }
640
+ if (cfg.allowCancel) {
641
+ queueMicrotask(() => {
642
+ const btn = el.querySelector("#__ctx_agent_lock_cancel__");
643
+ if (btn) {
644
+ btn.addEventListener("click", (e) => {
645
+ e.stopPropagation();
646
+ handleCancel();
647
+ });
648
+ }
649
+ });
650
+ }
651
+ document.body.appendChild(el);
652
+ overlayEl = el;
653
+ }
654
+ function removeOverlay() {
655
+ if (overlayEl) {
656
+ for (const evt of BLOCKED_EVENTS) {
657
+ overlayEl.removeEventListener(evt, blockEvent, { capture: true });
658
+ }
659
+ overlayEl.remove();
660
+ overlayEl = null;
661
+ }
662
+ const style = typeof document !== "undefined" ? document.getElementById("__ctx_agent_lock_style__") : null;
663
+ if (style) style.remove();
664
+ }
665
+ function startTimeout(ms, requestId) {
666
+ clearTimeoutTimer();
667
+ if (ms <= 0) return;
668
+ timeoutTimer = setTimeout(() => {
669
+ console.warn("[ChatableX] Agent lock timeout \u2014 auto-unlocking");
670
+ forceUnlock();
671
+ emit("timeout", { requestId });
672
+ }, ms);
673
+ }
674
+ function clearTimeoutTimer() {
675
+ if (timeoutTimer !== null) {
676
+ clearTimeout(timeoutTimer);
677
+ timeoutTimer = null;
678
+ }
679
+ }
680
+ function clearDebounceTimer() {
681
+ if (debounceTimer !== null) {
682
+ clearTimeout(debounceTimer);
683
+ debounceTimer = null;
684
+ }
685
+ }
686
+ function doLock(message, timeout, requestId) {
687
+ if (locked) return;
688
+ locked = true;
689
+ currentMessage = message;
690
+ if (cfg.mode === "overlay") {
691
+ injectOverlay(currentMessage);
692
+ }
693
+ startTimeout(timeout, requestId);
694
+ emit("lock", { requestId });
695
+ }
696
+ function forceUnlock(requestId) {
697
+ if (!locked) return;
698
+ locked = false;
699
+ lockCount = 0;
700
+ clearTimeoutTimer();
701
+ clearDebounceTimer();
702
+ if (cfg.mode === "overlay") {
703
+ removeOverlay();
704
+ }
705
+ emit("unlock", { requestId });
706
+ }
707
+ function handleCancel() {
708
+ const rid = void 0;
709
+ forceUnlock(rid);
710
+ emit("cancel", { requestId: rid });
711
+ }
712
+ function lock(opts) {
713
+ if (!cfg.enabled) return;
714
+ const msg = opts?.message ?? cfg.message;
715
+ const timeout = opts?.timeout ?? cfg.timeout;
716
+ doLock(msg, timeout);
717
+ }
718
+ function unlock() {
719
+ forceUnlock();
720
+ }
721
+ function isLocked() {
722
+ return locked;
723
+ }
724
+ function on(event, handler) {
725
+ if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());
726
+ listeners.get(event).add(handler);
727
+ return () => off(event, handler);
728
+ }
729
+ function off(event, handler) {
730
+ listeners.get(event)?.delete(handler);
731
+ }
732
+ function _autoLock(requestId) {
733
+ if (!cfg.enabled) return;
734
+ clearDebounceTimer();
735
+ lockCount++;
736
+ if (!locked) {
737
+ doLock(cfg.message, cfg.timeout, requestId);
738
+ }
739
+ }
740
+ function _autoUnlock(requestId) {
741
+ if (!cfg.enabled) return;
742
+ lockCount = Math.max(0, lockCount - 1);
743
+ if (lockCount === 0) {
744
+ clearDebounceTimer();
745
+ debounceTimer = setTimeout(() => {
746
+ if (lockCount === 0) {
747
+ forceUnlock(requestId);
748
+ }
749
+ }, cfg.debounceUnlock);
750
+ }
751
+ }
752
+ function _destroy() {
753
+ forceUnlock();
754
+ listeners.clear();
755
+ }
756
+ return { lock, unlock, isLocked, on, off, _autoLock, _autoUnlock, _destroy };
757
+ }
758
+
542
759
  // package.json
543
760
  var package_default = {
544
761
  name: "chatablex-web-sdk",
545
- version: "1.0.32",
762
+ version: "1.0.34",
546
763
  description: "ChatableX Web SDK for AI App WebUI development. Provides bridge communication with the ChatableX Flutter client.",
547
764
  main: "dist/index.js",
548
765
  module: "dist/index.mjs",
@@ -561,8 +778,8 @@ var package_default = {
561
778
  "README.zh-CN.md"
562
779
  ],
563
780
  scripts: {
564
- build: "tsup src/index.ts --format cjs,esm --dts --clean",
565
- dev: "tsup src/index.ts --format cjs,esm --dts --watch",
781
+ build: "tsup",
782
+ dev: "tsup --watch",
566
783
  typecheck: "tsc --noEmit",
567
784
  test: "vitest run",
568
785
  "test:watch": "vitest",
@@ -632,7 +849,8 @@ var ChatableX = {
632
849
  } catch {
633
850
  if (debug) console.warn("[ChatableX] sdk_init handshake failed, continuing with defaults");
634
851
  }
635
- const toolModule = createToolModule(bridge, config.appId);
852
+ const agentLockModule = createAgentLockModule(bridge, config.agentLock);
853
+ const toolModule = createToolModule(bridge, config.appId, agentLockModule);
636
854
  if (toolConfig) toolModule._setInfo(toolConfig);
637
855
  const authModule = createAuthModule(bridge);
638
856
  const sdk = {
@@ -648,7 +866,8 @@ var ChatableX = {
648
866
  appId: config.appId,
649
867
  auth: authModule,
650
868
  apiBaseUrl: config.apiBaseUrl
651
- })
869
+ }),
870
+ agentLock: agentLockModule
652
871
  };
653
872
  window.ChatableX = sdk;
654
873
  _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,225 @@ 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
+ debounceUnlock: 200
525
+ };
526
+ var OVERLAY_ID = "__chatablex_agent_lock_overlay__";
527
+ var BLOCKED_EVENTS = [
528
+ "mousedown",
529
+ "mouseup",
530
+ "click",
531
+ "dblclick",
532
+ "contextmenu",
533
+ "keydown",
534
+ "keyup",
535
+ "keypress",
536
+ "touchstart",
537
+ "touchmove",
538
+ "touchend",
539
+ "wheel",
540
+ "scroll",
541
+ "pointerdown",
542
+ "pointerup"
543
+ ];
544
+ var CANCEL_BTN_ID = "__ctx_agent_lock_cancel__";
545
+ function blockEvent(e) {
546
+ const target = e.target;
547
+ if (target?.id === CANCEL_BTN_ID) return;
548
+ e.stopPropagation();
549
+ e.preventDefault();
550
+ }
551
+ function createAgentLockModule(_bridge, userConfig = {}) {
552
+ const cfg = { ...DEFAULT_CONFIG, ...userConfig };
553
+ const logoSrc = cfg.logoUrl || bee_default;
554
+ const listeners = /* @__PURE__ */ new Map();
555
+ let overlayEl = null;
556
+ let locked = false;
557
+ let lockCount = 0;
558
+ let timeoutTimer = null;
559
+ let debounceTimer = null;
560
+ let currentMessage = cfg.message;
561
+ function emit(event, data = {}) {
562
+ const payload = { timestamp: Date.now(), ...data };
563
+ const handlers = listeners.get(event);
564
+ if (handlers) {
565
+ for (const fn of handlers) {
566
+ try {
567
+ fn(payload);
568
+ } catch (e) {
569
+ console.error("[ChatableX AgentLock] event handler error:", e);
570
+ }
571
+ }
572
+ }
573
+ }
574
+ function injectOverlay(message) {
575
+ if (typeof document === "undefined") return;
576
+ if (document.getElementById(OVERLAY_ID)) return;
577
+ const el = document.createElement("div");
578
+ el.id = OVERLAY_ID;
579
+ el.setAttribute("aria-hidden", "true");
580
+ el.style.cssText = [
581
+ "position:fixed",
582
+ "inset:0",
583
+ `z-index:2147483646`,
584
+ `background:rgba(255,255,255,${cfg.opacity})`,
585
+ "display:flex",
586
+ "flex-direction:column",
587
+ "align-items:center",
588
+ "justify-content:center",
589
+ "pointer-events:all",
590
+ "user-select:none",
591
+ "backdrop-filter:blur(1px)",
592
+ "-webkit-backdrop-filter:blur(1px)"
593
+ ].join(";");
594
+ el.innerHTML = `
595
+ <img src="${logoSrc}" alt="" style="width:48px;height:48px;animation:__ctx_spin 1.5s linear infinite;" />
596
+ <p style="margin:12px 0 0;font:14px/1.4 -apple-system,BlinkMacSystemFont,sans-serif;color:#666;">${message}</p>
597
+ ${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>' : ""}
598
+ `;
599
+ if (!document.getElementById("__ctx_agent_lock_style__")) {
600
+ const style = document.createElement("style");
601
+ style.id = "__ctx_agent_lock_style__";
602
+ style.textContent = "@keyframes __ctx_spin{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}";
603
+ document.head.appendChild(style);
604
+ }
605
+ for (const evt of BLOCKED_EVENTS) {
606
+ el.addEventListener(evt, blockEvent, { capture: true, passive: false });
607
+ }
608
+ if (cfg.allowCancel) {
609
+ queueMicrotask(() => {
610
+ const btn = el.querySelector("#__ctx_agent_lock_cancel__");
611
+ if (btn) {
612
+ btn.addEventListener("click", (e) => {
613
+ e.stopPropagation();
614
+ handleCancel();
615
+ });
616
+ }
617
+ });
618
+ }
619
+ document.body.appendChild(el);
620
+ overlayEl = el;
621
+ }
622
+ function removeOverlay() {
623
+ if (overlayEl) {
624
+ for (const evt of BLOCKED_EVENTS) {
625
+ overlayEl.removeEventListener(evt, blockEvent, { capture: true });
626
+ }
627
+ overlayEl.remove();
628
+ overlayEl = null;
629
+ }
630
+ const style = typeof document !== "undefined" ? document.getElementById("__ctx_agent_lock_style__") : null;
631
+ if (style) style.remove();
632
+ }
633
+ function startTimeout(ms, requestId) {
634
+ clearTimeoutTimer();
635
+ if (ms <= 0) return;
636
+ timeoutTimer = setTimeout(() => {
637
+ console.warn("[ChatableX] Agent lock timeout \u2014 auto-unlocking");
638
+ forceUnlock();
639
+ emit("timeout", { requestId });
640
+ }, ms);
641
+ }
642
+ function clearTimeoutTimer() {
643
+ if (timeoutTimer !== null) {
644
+ clearTimeout(timeoutTimer);
645
+ timeoutTimer = null;
646
+ }
647
+ }
648
+ function clearDebounceTimer() {
649
+ if (debounceTimer !== null) {
650
+ clearTimeout(debounceTimer);
651
+ debounceTimer = null;
652
+ }
653
+ }
654
+ function doLock(message, timeout, requestId) {
655
+ if (locked) return;
656
+ locked = true;
657
+ currentMessage = message;
658
+ if (cfg.mode === "overlay") {
659
+ injectOverlay(currentMessage);
660
+ }
661
+ startTimeout(timeout, requestId);
662
+ emit("lock", { requestId });
663
+ }
664
+ function forceUnlock(requestId) {
665
+ if (!locked) return;
666
+ locked = false;
667
+ lockCount = 0;
668
+ clearTimeoutTimer();
669
+ clearDebounceTimer();
670
+ if (cfg.mode === "overlay") {
671
+ removeOverlay();
672
+ }
673
+ emit("unlock", { requestId });
674
+ }
675
+ function handleCancel() {
676
+ const rid = void 0;
677
+ forceUnlock(rid);
678
+ emit("cancel", { requestId: rid });
679
+ }
680
+ function lock(opts) {
681
+ if (!cfg.enabled) return;
682
+ const msg = opts?.message ?? cfg.message;
683
+ const timeout = opts?.timeout ?? cfg.timeout;
684
+ doLock(msg, timeout);
685
+ }
686
+ function unlock() {
687
+ forceUnlock();
688
+ }
689
+ function isLocked() {
690
+ return locked;
691
+ }
692
+ function on(event, handler) {
693
+ if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());
694
+ listeners.get(event).add(handler);
695
+ return () => off(event, handler);
696
+ }
697
+ function off(event, handler) {
698
+ listeners.get(event)?.delete(handler);
699
+ }
700
+ function _autoLock(requestId) {
701
+ if (!cfg.enabled) return;
702
+ clearDebounceTimer();
703
+ lockCount++;
704
+ if (!locked) {
705
+ doLock(cfg.message, cfg.timeout, requestId);
706
+ }
707
+ }
708
+ function _autoUnlock(requestId) {
709
+ if (!cfg.enabled) return;
710
+ lockCount = Math.max(0, lockCount - 1);
711
+ if (lockCount === 0) {
712
+ clearDebounceTimer();
713
+ debounceTimer = setTimeout(() => {
714
+ if (lockCount === 0) {
715
+ forceUnlock(requestId);
716
+ }
717
+ }, cfg.debounceUnlock);
718
+ }
719
+ }
720
+ function _destroy() {
721
+ forceUnlock();
722
+ listeners.clear();
723
+ }
724
+ return { lock, unlock, isLocked, on, off, _autoLock, _autoUnlock, _destroy };
725
+ }
726
+
510
727
  // package.json
511
728
  var package_default = {
512
729
  name: "chatablex-web-sdk",
513
- version: "1.0.32",
730
+ version: "1.0.34",
514
731
  description: "ChatableX Web SDK for AI App WebUI development. Provides bridge communication with the ChatableX Flutter client.",
515
732
  main: "dist/index.js",
516
733
  module: "dist/index.mjs",
@@ -529,8 +746,8 @@ var package_default = {
529
746
  "README.zh-CN.md"
530
747
  ],
531
748
  scripts: {
532
- build: "tsup src/index.ts --format cjs,esm --dts --clean",
533
- dev: "tsup src/index.ts --format cjs,esm --dts --watch",
749
+ build: "tsup",
750
+ dev: "tsup --watch",
534
751
  typecheck: "tsc --noEmit",
535
752
  test: "vitest run",
536
753
  "test:watch": "vitest",
@@ -600,7 +817,8 @@ var ChatableX = {
600
817
  } catch {
601
818
  if (debug) console.warn("[ChatableX] sdk_init handshake failed, continuing with defaults");
602
819
  }
603
- const toolModule = createToolModule(bridge, config.appId);
820
+ const agentLockModule = createAgentLockModule(bridge, config.agentLock);
821
+ const toolModule = createToolModule(bridge, config.appId, agentLockModule);
604
822
  if (toolConfig) toolModule._setInfo(toolConfig);
605
823
  const authModule = createAuthModule(bridge);
606
824
  const sdk = {
@@ -616,7 +834,8 @@ var ChatableX = {
616
834
  appId: config.appId,
617
835
  auth: authModule,
618
836
  apiBaseUrl: config.apiBaseUrl
619
- })
837
+ }),
838
+ agentLock: agentLockModule
620
839
  };
621
840
  window.ChatableX = sdk;
622
841
  _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.34",
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,255 @@
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
+ debounceUnlock: 200,
20
+ };
21
+
22
+ const OVERLAY_ID = '__chatablex_agent_lock_overlay__';
23
+
24
+ /**
25
+ * Blocked event types — we intercept these on the overlay to prevent user
26
+ * interaction from reaching the app underneath.
27
+ */
28
+ const BLOCKED_EVENTS: string[] = [
29
+ 'mousedown', 'mouseup', 'click', 'dblclick', 'contextmenu',
30
+ 'keydown', 'keyup', 'keypress',
31
+ 'touchstart', 'touchmove', 'touchend',
32
+ 'wheel', 'scroll',
33
+ 'pointerdown', 'pointerup',
34
+ ];
35
+
36
+ const CANCEL_BTN_ID = '__ctx_agent_lock_cancel__';
37
+
38
+ function blockEvent(e: Event): void {
39
+ const target = e.target as HTMLElement | null;
40
+ if (target?.id === CANCEL_BTN_ID) return;
41
+ e.stopPropagation();
42
+ e.preventDefault();
43
+ }
44
+
45
+ export interface AgentLockModule extends ChatableXAgentLock {
46
+ /**
47
+ * @internal — called by tool module to lock before dispatch and schedule
48
+ * unlock after result. Uses ref-counting to support consecutive tools.
49
+ */
50
+ _autoLock(requestId: string): void;
51
+ /** @internal */
52
+ _autoUnlock(requestId: string): void;
53
+ /** @internal */
54
+ _destroy(): void;
55
+ }
56
+
57
+ export function createAgentLockModule(
58
+ _bridge: Bridge,
59
+ userConfig: AgentLockConfig = {},
60
+ ): AgentLockModule {
61
+ const cfg: Required<AgentLockConfig> = { ...DEFAULT_CONFIG, ...userConfig };
62
+ const logoSrc = cfg.logoUrl || beeLogo;
63
+
64
+ const listeners = new Map<AgentLockEventType, Set<AgentLockEventHandler>>();
65
+ let overlayEl: HTMLDivElement | null = null;
66
+ let locked = false;
67
+ let lockCount = 0;
68
+ let timeoutTimer: ReturnType<typeof setTimeout> | null = null;
69
+ let debounceTimer: ReturnType<typeof setTimeout> | null = null;
70
+ let currentMessage = cfg.message;
71
+
72
+ function emit(event: AgentLockEventType, data: Partial<AgentLockEventData> = {}): void {
73
+ const payload: AgentLockEventData = { timestamp: Date.now(), ...data };
74
+ const handlers = listeners.get(event);
75
+ if (handlers) {
76
+ for (const fn of handlers) {
77
+ try { fn(payload); } catch (e) { console.error('[ChatableX AgentLock] event handler error:', e); }
78
+ }
79
+ }
80
+ }
81
+
82
+ function injectOverlay(message: string): void {
83
+ if (typeof document === 'undefined') return;
84
+ if (document.getElementById(OVERLAY_ID)) return;
85
+
86
+ const el = document.createElement('div');
87
+ el.id = OVERLAY_ID;
88
+ el.setAttribute('aria-hidden', 'true');
89
+ el.style.cssText = [
90
+ 'position:fixed', 'inset:0', `z-index:2147483646`,
91
+ `background:rgba(255,255,255,${cfg.opacity})`,
92
+ 'display:flex', 'flex-direction:column',
93
+ 'align-items:center', 'justify-content:center',
94
+ 'pointer-events:all', 'user-select:none',
95
+ 'backdrop-filter:blur(1px)', '-webkit-backdrop-filter:blur(1px)',
96
+ ].join(';');
97
+
98
+ el.innerHTML = `
99
+ <img src="${logoSrc}" alt="" style="width:48px;height:48px;animation:__ctx_spin 1.5s linear infinite;" />
100
+ <p style="margin:12px 0 0;font:14px/1.4 -apple-system,BlinkMacSystemFont,sans-serif;color:#666;">${message}</p>
101
+ ${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>' : ''}
102
+ `;
103
+
104
+ if (!document.getElementById('__ctx_agent_lock_style__')) {
105
+ const style = document.createElement('style');
106
+ style.id = '__ctx_agent_lock_style__';
107
+ style.textContent = '@keyframes __ctx_spin{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}';
108
+ document.head.appendChild(style);
109
+ }
110
+
111
+ for (const evt of BLOCKED_EVENTS) {
112
+ el.addEventListener(evt, blockEvent, { capture: true, passive: false });
113
+ }
114
+
115
+ if (cfg.allowCancel) {
116
+ // Defer binding so the DOM is ready
117
+ queueMicrotask(() => {
118
+ const btn = el.querySelector('#__ctx_agent_lock_cancel__');
119
+ if (btn) {
120
+ btn.addEventListener('click', (e) => {
121
+ e.stopPropagation();
122
+ handleCancel();
123
+ });
124
+ }
125
+ });
126
+ }
127
+
128
+ document.body.appendChild(el);
129
+ overlayEl = el;
130
+ }
131
+
132
+ function removeOverlay(): void {
133
+ if (overlayEl) {
134
+ for (const evt of BLOCKED_EVENTS) {
135
+ overlayEl.removeEventListener(evt, blockEvent, { capture: true } as EventListenerOptions);
136
+ }
137
+ overlayEl.remove();
138
+ overlayEl = null;
139
+ }
140
+ const style = typeof document !== 'undefined' ? document.getElementById('__ctx_agent_lock_style__') : null;
141
+ if (style) style.remove();
142
+ }
143
+
144
+ function startTimeout(ms: number, requestId?: string): void {
145
+ clearTimeoutTimer();
146
+ if (ms <= 0) return;
147
+ timeoutTimer = setTimeout(() => {
148
+ console.warn('[ChatableX] Agent lock timeout — auto-unlocking');
149
+ forceUnlock();
150
+ emit('timeout', { requestId });
151
+ }, ms);
152
+ }
153
+
154
+ function clearTimeoutTimer(): void {
155
+ if (timeoutTimer !== null) {
156
+ clearTimeout(timeoutTimer);
157
+ timeoutTimer = null;
158
+ }
159
+ }
160
+
161
+ function clearDebounceTimer(): void {
162
+ if (debounceTimer !== null) {
163
+ clearTimeout(debounceTimer);
164
+ debounceTimer = null;
165
+ }
166
+ }
167
+
168
+ function doLock(message: string, timeout: number, requestId?: string): void {
169
+ if (locked) return;
170
+ locked = true;
171
+ currentMessage = message;
172
+
173
+ if (cfg.mode === 'overlay') {
174
+ injectOverlay(currentMessage);
175
+ }
176
+ startTimeout(timeout, requestId);
177
+ emit('lock', { requestId });
178
+ }
179
+
180
+ function forceUnlock(requestId?: string): void {
181
+ if (!locked) return;
182
+ locked = false;
183
+ lockCount = 0;
184
+ clearTimeoutTimer();
185
+ clearDebounceTimer();
186
+ if (cfg.mode === 'overlay') {
187
+ removeOverlay();
188
+ }
189
+ emit('unlock', { requestId });
190
+ }
191
+
192
+ function handleCancel(): void {
193
+ const rid = undefined; // auto mode tracks this externally
194
+ forceUnlock(rid);
195
+ emit('cancel', { requestId: rid });
196
+ }
197
+
198
+ // Public API -----------------------------------------------------------------
199
+
200
+ function lock(opts?: { message?: string; timeout?: number }): void {
201
+ if (!cfg.enabled) return;
202
+ const msg = opts?.message ?? cfg.message;
203
+ const timeout = opts?.timeout ?? cfg.timeout;
204
+ doLock(msg, timeout);
205
+ }
206
+
207
+ function unlock(): void {
208
+ forceUnlock();
209
+ }
210
+
211
+ function isLocked(): boolean {
212
+ return locked;
213
+ }
214
+
215
+ function on(event: AgentLockEventType, handler: AgentLockEventHandler): () => void {
216
+ if (!listeners.has(event)) listeners.set(event, new Set());
217
+ listeners.get(event)!.add(handler);
218
+ return () => off(event, handler);
219
+ }
220
+
221
+ function off(event: AgentLockEventType, handler: AgentLockEventHandler): void {
222
+ listeners.get(event)?.delete(handler);
223
+ }
224
+
225
+ // Internal auto-mode API (called by tool module) ----------------------------
226
+
227
+ function _autoLock(requestId: string): void {
228
+ if (!cfg.enabled) return;
229
+ clearDebounceTimer();
230
+ lockCount++;
231
+ if (!locked) {
232
+ doLock(cfg.message, cfg.timeout, requestId);
233
+ }
234
+ }
235
+
236
+ function _autoUnlock(requestId: string): void {
237
+ if (!cfg.enabled) return;
238
+ lockCount = Math.max(0, lockCount - 1);
239
+ if (lockCount === 0) {
240
+ clearDebounceTimer();
241
+ debounceTimer = setTimeout(() => {
242
+ if (lockCount === 0) {
243
+ forceUnlock(requestId);
244
+ }
245
+ }, cfg.debounceUnlock);
246
+ }
247
+ }
248
+
249
+ function _destroy(): void {
250
+ forceUnlock();
251
+ listeners.clear();
252
+ }
253
+
254
+ return { lock, unlock, isLocked, on, off, _autoLock, _autoUnlock, _destroy };
255
+ }
@@ -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,54 @@ 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 in ms (default: 30000). 0 disables. */
358
+ timeout?: number;
359
+ /** Delay before actually removing the overlay after unlock, to avoid flicker between consecutive tools (default: 200ms). */
360
+ debounceUnlock?: number;
361
+ }
362
+
363
+ export type AgentLockEventType = 'lock' | 'unlock' | 'cancel' | 'timeout';
364
+
365
+ export interface AgentLockEventData {
366
+ requestId?: string;
367
+ timestamp: number;
368
+ }
369
+
370
+ export type AgentLockEventHandler = (data: AgentLockEventData) => void;
371
+
372
+ export interface ChatableXAgentLock {
373
+ /** Manually lock user interaction with an optional custom message / timeout. */
374
+ lock(opts?: { message?: string; timeout?: number }): void;
375
+ /** Manually unlock. Safe to call when already unlocked. */
376
+ unlock(): void;
377
+ /** Whether the overlay is currently active. */
378
+ isLocked(): boolean;
379
+ /** Subscribe to lock lifecycle events. Returns an unsubscribe function. */
380
+ on(event: AgentLockEventType, handler: AgentLockEventHandler): () => void;
381
+ /** Remove a previously registered handler. */
382
+ off(event: AgentLockEventType, handler: AgentLockEventHandler): void;
383
+ }
384
+
335
385
  export interface ChatableXSDK {
336
386
  ai: ChatableXAI;
337
387
  tools: ChatableXTools;
@@ -342,6 +392,7 @@ export interface ChatableXSDK {
342
392
  platform: ChatableXPlatform;
343
393
  auth: ChatableXAuth;
344
394
  cloud: ChatableXCloud;
395
+ agentLock: ChatableXAgentLock;
345
396
  }
346
397
 
347
398
  // ---------------------------------------------------------------------------