@cadraos/sdk 0.1.10 → 0.1.12

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.
@@ -65,7 +65,7 @@ var BaseResourceAPI = class {
65
65
  };
66
66
 
67
67
  // src/errors/sdk-errors.ts
68
- var AISaaSError = class extends Error {
68
+ var CadraError = class extends Error {
69
69
  /** Error code */
70
70
  code;
71
71
  /** HTTP status code */
@@ -76,7 +76,7 @@ var AISaaSError = class extends Error {
76
76
  requestId;
77
77
  constructor(message, code, status, details, requestId) {
78
78
  super(message);
79
- this.name = "AISaaSError";
79
+ this.name = "CadraError";
80
80
  this.code = code;
81
81
  this.status = status;
82
82
  this.details = details;
@@ -86,25 +86,25 @@ var AISaaSError = class extends Error {
86
86
  }
87
87
  }
88
88
  };
89
- var AuthenticationError = class extends AISaaSError {
89
+ var AuthenticationError = class extends CadraError {
90
90
  constructor(message = "Authentication failed", code = "authentication_error", details, requestId) {
91
91
  super(message, code, 401, details, requestId);
92
92
  this.name = "AuthenticationError";
93
93
  }
94
94
  };
95
- var AuthorizationError = class extends AISaaSError {
95
+ var AuthorizationError = class extends CadraError {
96
96
  constructor(message = "Access denied", code = "authorization_error", details, requestId) {
97
97
  super(message, code, 403, details, requestId);
98
98
  this.name = "AuthorizationError";
99
99
  }
100
100
  };
101
- var NotFoundError = class extends AISaaSError {
101
+ var NotFoundError = class extends CadraError {
102
102
  constructor(message = "Resource not found", code = "not_found", details, requestId) {
103
103
  super(message, code, 404, details, requestId);
104
104
  this.name = "NotFoundError";
105
105
  }
106
106
  };
107
- var ValidationError = class extends AISaaSError {
107
+ var ValidationError = class extends CadraError {
108
108
  /** Field-level validation errors */
109
109
  errors;
110
110
  constructor(message = "Validation failed", errors = [], details, requestId) {
@@ -113,7 +113,7 @@ var ValidationError = class extends AISaaSError {
113
113
  this.errors = errors;
114
114
  }
115
115
  };
116
- var RateLimitError = class extends AISaaSError {
116
+ var RateLimitError = class extends CadraError {
117
117
  /** Seconds until rate limit resets */
118
118
  retryAfter;
119
119
  constructor(message = "Rate limit exceeded", retryAfter, details, requestId) {
@@ -122,25 +122,25 @@ var RateLimitError = class extends AISaaSError {
122
122
  this.retryAfter = retryAfter;
123
123
  }
124
124
  };
125
- var ServerError = class extends AISaaSError {
125
+ var ServerError = class extends CadraError {
126
126
  constructor(message = "Server error", status = 500, details, requestId) {
127
127
  super(message, "server_error", status, details, requestId);
128
128
  this.name = "ServerError";
129
129
  }
130
130
  };
131
- var ConflictError = class extends AISaaSError {
131
+ var ConflictError = class extends CadraError {
132
132
  constructor(message = "Resource conflict", details, requestId) {
133
133
  super(message, "conflict", 409, details, requestId);
134
134
  this.name = "ConflictError";
135
135
  }
136
136
  };
137
- var TimeoutError = class extends AISaaSError {
137
+ var TimeoutError = class extends CadraError {
138
138
  constructor(message = "Request timed out", details, requestId) {
139
139
  super(message, "timeout", 408, details, requestId);
140
140
  this.name = "TimeoutError";
141
141
  }
142
142
  };
143
- var NetworkError = class extends AISaaSError {
143
+ var NetworkError = class extends CadraError {
144
144
  constructor(message = "Network error", details) {
145
145
  super(message, "network_error", 0, details);
146
146
  this.name = "NetworkError";
@@ -182,7 +182,7 @@ function parseApiError(status, body, requestId) {
182
182
  if (status >= 500) {
183
183
  return new ServerError(message, status, details, requestId);
184
184
  }
185
- return new AISaaSError(message, code, status, details, requestId);
185
+ return new CadraError(message, code, status, details, requestId);
186
186
  }
187
187
  }
188
188
 
@@ -270,15 +270,21 @@ var HttpClient = class {
270
270
  * Build full URL with query parameters
271
271
  */
272
272
  buildUrl(path, query) {
273
- const url = new URL(path, this.config.baseUrl);
273
+ const base = this.config.baseUrl.replace(/\/+$/, "");
274
+ let url = `${base}${path}`;
274
275
  if (query) {
276
+ const params = new URLSearchParams();
275
277
  for (const [key, value] of Object.entries(query)) {
276
278
  if (value !== void 0) {
277
- url.searchParams.set(key, String(value));
279
+ params.set(key, String(value));
278
280
  }
279
281
  }
282
+ const qs = params.toString();
283
+ if (qs) {
284
+ url += `?${qs}`;
285
+ }
280
286
  }
281
- return url.toString();
287
+ return url;
282
288
  }
283
289
  /**
284
290
  * Make an HTTP request
@@ -582,9 +588,11 @@ var DEFAULT_STREAMING_CONFIG = {
582
588
  activityTimeoutMs: 3e4,
583
589
  pollingIntervalMs: 2e3
584
590
  };
591
+ var DEFAULT_POLLING_ENABLED = true;
585
592
  var ExecutionStreamControllerImpl = class {
586
593
  options;
587
594
  config;
595
+ pollingEnabled;
588
596
  sseClient = null;
589
597
  status = "connecting";
590
598
  reconnectAttempts = 0;
@@ -618,6 +626,7 @@ var ExecutionStreamControllerImpl = class {
618
626
  constructor(options) {
619
627
  this.options = options;
620
628
  this.config = { ...DEFAULT_STREAMING_CONFIG, ...options.config };
629
+ this.pollingEnabled = options.pollingEnabled ?? DEFAULT_POLLING_ENABLED;
621
630
  }
622
631
  /**
623
632
  * Get the last event ID (for resume support)
@@ -678,7 +687,7 @@ var ExecutionStreamControllerImpl = class {
678
687
  return Promise.resolve(this.finalExecution);
679
688
  }
680
689
  if (this.finalError) {
681
- return Promise.reject(new AISaaSError(
690
+ return Promise.reject(new CadraError(
682
691
  this.finalError.error,
683
692
  this.finalError.errorCode ?? "execution_error",
684
693
  500
@@ -697,7 +706,8 @@ var ExecutionStreamControllerImpl = class {
697
706
  * Connect to SSE endpoint
698
707
  */
699
708
  async connectSSE() {
700
- const url = `${this.options.baseUrl}/agents/runs/${this.options.executionId}/stream`;
709
+ const base = this.options.baseUrl.replace(/\/+$/, "");
710
+ const url = `${base}/api/v1/agents/runs/${this.options.executionId}/stream`;
701
711
  let authToken = this.options.apiKey;
702
712
  if (!authToken && this.options.tokenProvider) {
703
713
  authToken = await this.options.tokenProvider();
@@ -932,7 +942,7 @@ var ExecutionStreamControllerImpl = class {
932
942
  this.finalError = error;
933
943
  this.emit("error", error);
934
944
  if (this.waitReject) {
935
- this.waitReject(new AISaaSError(
945
+ this.waitReject(new CadraError(
936
946
  error.error,
937
947
  error.errorCode ?? "execution_error",
938
948
  500
@@ -957,15 +967,61 @@ var ExecutionStreamControllerImpl = class {
957
967
  if (this.status === "closed") {
958
968
  return;
959
969
  }
970
+ await this.recoverState();
971
+ if (this.status === "closed") {
972
+ return;
973
+ }
960
974
  try {
961
975
  await this.connectSSE();
962
976
  } catch {
963
977
  await this.handleConnectionError(error);
964
978
  }
965
979
  } else {
966
- this.status = "fallback_polling";
967
- this.emit("connectionChange", { connected: false, usingFallback: true });
968
- this.startPolling();
980
+ if (this.pollingEnabled) {
981
+ this.status = "fallback_polling";
982
+ this.emit("connectionChange", { connected: false, usingFallback: true });
983
+ this.startPolling();
984
+ } else {
985
+ this.handleError({
986
+ error: "SSE connection failed and polling is disabled",
987
+ errorCode: "connection_failed"
988
+ });
989
+ }
990
+ }
991
+ }
992
+ /**
993
+ * Recover state by checking execution status.
994
+ *
995
+ * Called during reconnection to catch any events missed while SSE was down.
996
+ * If the execution completed while disconnected, emits completion immediately.
997
+ * Otherwise, emits any new logs that weren't seen via SSE.
998
+ */
999
+ async recoverState() {
1000
+ try {
1001
+ const execution = await this.options.getExecution(this.options.executionId);
1002
+ if (execution.logs) {
1003
+ for (const log of execution.logs) {
1004
+ if (!this.seenEventIds.has(log.uuid)) {
1005
+ this.seenEventIds.add(log.uuid);
1006
+ this.emit("log", log);
1007
+ }
1008
+ }
1009
+ }
1010
+ if (execution.status === "completed") {
1011
+ this.stopPolling();
1012
+ this.handleComplete(execution);
1013
+ return;
1014
+ }
1015
+ if (execution.status === "failed" || execution.status === "cancelled") {
1016
+ this.stopPolling();
1017
+ this.handleError({
1018
+ error: execution.error ?? `Execution ${execution.status}`,
1019
+ errorCode: execution.status
1020
+ });
1021
+ return;
1022
+ }
1023
+ } catch (err) {
1024
+ console.warn("[SDK:StreamController] State recovery failed (non-fatal):", err);
969
1025
  }
970
1026
  }
971
1027
  /**
@@ -1050,7 +1106,7 @@ function createExecutionStreamController(options) {
1050
1106
  // src/resources/agents.ts
1051
1107
  var AgentsAPI = class extends BaseResourceAPI {
1052
1108
  constructor(http, getStreamConfig) {
1053
- super(http, "/agents");
1109
+ super(http, "/api/v1/agents");
1054
1110
  this.getStreamConfig = getStreamConfig;
1055
1111
  }
1056
1112
  // ===== LIST Operations =====
@@ -1326,7 +1382,7 @@ var AgentsAPI = class extends BaseResourceAPI {
1326
1382
  // src/resources/skills.ts
1327
1383
  var SkillsAPI = class extends BaseResourceAPI {
1328
1384
  constructor(http) {
1329
- super(http, "/skills");
1385
+ super(http, "/api/v1/skills");
1330
1386
  }
1331
1387
  // ===== LIST Operations =====
1332
1388
  /**
@@ -1470,7 +1526,7 @@ var SkillsAPI = class extends BaseResourceAPI {
1470
1526
  // src/resources/tools.ts
1471
1527
  var ToolsAPI = class extends BaseResourceAPI {
1472
1528
  constructor(http) {
1473
- super(http, "/tools");
1529
+ super(http, "/api/v1/tools");
1474
1530
  }
1475
1531
  // ===== LIST Operations =====
1476
1532
  /**
@@ -1633,7 +1689,7 @@ var ToolsAPI = class extends BaseResourceAPI {
1633
1689
  // src/resources/artifacts.ts
1634
1690
  var ArtifactsAPI = class extends BaseResourceAPI {
1635
1691
  constructor(http) {
1636
- super(http, "/artifacts");
1692
+ super(http, "/api/v1/artifacts");
1637
1693
  }
1638
1694
  // ===== LIST Operations =====
1639
1695
  /**
@@ -1829,7 +1885,7 @@ var ArtifactsAPI = class extends BaseResourceAPI {
1829
1885
  // src/resources/sessions.ts
1830
1886
  var SessionsAPI = class extends BaseResourceAPI {
1831
1887
  constructor(http, getStreamConfig) {
1832
- super(http, "/sessions");
1888
+ super(http, "/api/v1/sessions");
1833
1889
  this.getStreamConfig = getStreamConfig;
1834
1890
  }
1835
1891
  // ===== LIST Operations =====
@@ -2060,9 +2116,9 @@ var SessionsAPI = class extends BaseResourceAPI {
2060
2116
  };
2061
2117
 
2062
2118
  // src/client.ts
2063
- var DEFAULT_BASE_URL = "https://api.aisaas.com/v1";
2119
+ var DEFAULT_BASE_URL = "https://api.cadraos.com";
2064
2120
  var DEFAULT_TIMEOUT = 3e4;
2065
- var AISaaSClient = class {
2121
+ var CadraClient = class {
2066
2122
  httpClient;
2067
2123
  config;
2068
2124
  /**
@@ -2093,19 +2149,19 @@ var AISaaSClient = class {
2093
2149
  * @example
2094
2150
  * ```typescript
2095
2151
  * // API key authentication
2096
- * const client = new AISaaSClient({
2152
+ * const client = new CadraClient({
2097
2153
  * apiKey: 'sk_...',
2098
2154
  * orgId: 123,
2099
2155
  * });
2100
2156
  *
2101
2157
  * // OAuth token authentication
2102
- * const client = new AISaaSClient({
2158
+ * const client = new CadraClient({
2103
2159
  * token: 'eyJ...',
2104
2160
  * orgId: 123,
2105
2161
  * });
2106
2162
  *
2107
2163
  * // Token provider (for automatic refresh)
2108
- * const client = new AISaaSClient({
2164
+ * const client = new CadraClient({
2109
2165
  * tokenProvider: async () => myAuth.getAccessToken(),
2110
2166
  * orgId: 123,
2111
2167
  * });
@@ -2113,6 +2169,19 @@ var AISaaSClient = class {
2113
2169
  */
2114
2170
  constructor(options) {
2115
2171
  this.validateOptions(options);
2172
+ if (options.baseUrl) {
2173
+ try {
2174
+ const parsed = new URL(options.baseUrl);
2175
+ if (/\/(api|v\d)/.test(parsed.pathname)) {
2176
+ if (typeof process !== "undefined" && process.env?.NODE_ENV !== "production") {
2177
+ console.warn(
2178
+ `[CadraOS SDK] baseUrl should be the origin only (e.g., "https://api.cadraos.com" or "http://localhost:3000"). The SDK automatically prepends "/api/v1/" to all requests. Received: "${options.baseUrl}"`
2179
+ );
2180
+ }
2181
+ }
2182
+ } catch {
2183
+ }
2184
+ }
2116
2185
  this.config = {
2117
2186
  baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,
2118
2187
  orgId: options.orgId,
@@ -2185,21 +2254,21 @@ function resolveClient(config) {
2185
2254
  throw new Error("DefaultAdapterConfig requires 'orgId' when 'client' is not provided");
2186
2255
  }
2187
2256
  if (config.apiKey) {
2188
- return new AISaaSClient({
2257
+ return new CadraClient({
2189
2258
  apiKey: config.apiKey,
2190
2259
  orgId: config.orgId,
2191
2260
  baseUrl: config.baseUrl
2192
2261
  });
2193
2262
  }
2194
2263
  if (config.token) {
2195
- return new AISaaSClient({
2264
+ return new CadraClient({
2196
2265
  token: config.token,
2197
2266
  orgId: config.orgId,
2198
2267
  baseUrl: config.baseUrl
2199
2268
  });
2200
2269
  }
2201
2270
  if (config.tokenProvider) {
2202
- return new AISaaSClient({
2271
+ return new CadraClient({
2203
2272
  tokenProvider: config.tokenProvider,
2204
2273
  orgId: config.orgId,
2205
2274
  baseUrl: config.baseUrl
@@ -2211,7 +2280,7 @@ function resolveClient(config) {
2211
2280
  }
2212
2281
  function resolveBaseUrl(config) {
2213
2282
  if (config.baseUrl) return config.baseUrl;
2214
- return "https://api.cadra.io/v1";
2283
+ return "https://api.cadraos.com";
2215
2284
  }
2216
2285
  async function getAuthHeaders(config) {
2217
2286
  const headers = {
@@ -2320,7 +2389,7 @@ function createDefaultAdapter(config) {
2320
2389
  // Attachment Methods (raw fetch — CadraClient has no AttachmentsAPI yet)
2321
2390
  // -------------------------------------------------------------------------
2322
2391
  async getUploadUrl(input) {
2323
- return rawRequest(config, "POST", "/attachments/upload-url", {
2392
+ return rawRequest(config, "POST", "/api/v1/attachments/upload-url", {
2324
2393
  sessionId: input.sessionId,
2325
2394
  filename: input.filename,
2326
2395
  mimeType: input.mimeType,
@@ -2328,10 +2397,10 @@ function createDefaultAdapter(config) {
2328
2397
  });
2329
2398
  },
2330
2399
  async confirmUpload(uuid) {
2331
- await rawRequest(config, "POST", `/attachments/${uuid}/confirm`);
2400
+ await rawRequest(config, "POST", `/api/v1/attachments/${uuid}/confirm`);
2332
2401
  },
2333
2402
  async getDownloadUrl(uuid) {
2334
- const result = await rawRequest(config, "GET", `/attachments/${uuid}/download-url`);
2403
+ const result = await rawRequest(config, "GET", `/api/v1/attachments/${uuid}/download-url`);
2335
2404
  return result.url;
2336
2405
  },
2337
2406
  // -------------------------------------------------------------------------
@@ -2412,7 +2481,7 @@ function createDefaultAdapter(config) {
2412
2481
  );
2413
2482
  }
2414
2483
  }
2415
- return `${baseUrl}/agents/runs/${executionId}/stream`;
2484
+ return `${baseUrl}/api/v1/agents/runs/${executionId}/stream`;
2416
2485
  },
2417
2486
  // -------------------------------------------------------------------------
2418
2487
  // Secure SSE Streaming (Recommended)
@@ -2804,12 +2873,54 @@ function useExecutionStream(options) {
2804
2873
  }
2805
2874
 
2806
2875
  // src/chat/hooks/useAgentChat.ts
2876
+ var __DEV__ = typeof process !== "undefined" && process.env?.NODE_ENV !== "production";
2807
2877
  var SILENT_TOOL_NAMES = /* @__PURE__ */ new Set([
2808
2878
  "check_delegations"
2809
2879
  ]);
2810
2880
  function generateId() {
2811
2881
  return `msg-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
2812
2882
  }
2883
+ function extractImagesFromResult(result, sourceToolCallId) {
2884
+ if (!result) return [];
2885
+ let data = result;
2886
+ if (typeof result === "string") {
2887
+ try {
2888
+ data = JSON.parse(result);
2889
+ } catch {
2890
+ if (/\.(png|jpg|jpeg|gif|webp|svg|bmp)(\?.*)?$/i.test(result) || result.startsWith("data:image/")) {
2891
+ return [{ url: result, sourceToolCallId }];
2892
+ }
2893
+ return [];
2894
+ }
2895
+ }
2896
+ if (typeof data !== "object" || data === null) return [];
2897
+ const obj = data;
2898
+ if (Array.isArray(obj.images)) {
2899
+ return obj.images.filter((img) => typeof img.url === "string").map((img) => ({
2900
+ url: img.url,
2901
+ alt: img.alt || img.prompt || void 0,
2902
+ filename: img.filename,
2903
+ sourceToolCallId
2904
+ }));
2905
+ }
2906
+ if (typeof obj.url === "string" && /\.(png|jpg|jpeg|gif|webp|svg|bmp)(\?.*)?$/i.test(obj.url)) {
2907
+ return [{ url: obj.url, alt: obj.alt, sourceToolCallId }];
2908
+ }
2909
+ if (typeof obj.imageUrl === "string") {
2910
+ return [{ url: obj.imageUrl, alt: obj.alt, sourceToolCallId }];
2911
+ }
2912
+ return [];
2913
+ }
2914
+ function deriveImagesFromToolCalls(toolCalls) {
2915
+ if (!toolCalls) return [];
2916
+ const images = [];
2917
+ for (const tc of toolCalls) {
2918
+ if (tc.status === "completed" && tc.result) {
2919
+ images.push(...extractImagesFromResult(tc.result, tc.id));
2920
+ }
2921
+ }
2922
+ return images;
2923
+ }
2813
2924
  function historyToMessage(historyMsg) {
2814
2925
  return {
2815
2926
  id: historyMsg.uuid,
@@ -2850,7 +2961,9 @@ function useAgentChat(options) {
2850
2961
  // Deprecated, but still supported
2851
2962
  onToolCall,
2852
2963
  onToolResult,
2853
- onClarification
2964
+ onClarification,
2965
+ pollingInterval,
2966
+ pollingEnabled
2854
2967
  } = options;
2855
2968
  const contextConfig = useChatConfigOptional();
2856
2969
  const adapter = propsAdapter ?? contextConfig?.adapter;
@@ -2882,8 +2995,14 @@ function useAgentChat(options) {
2882
2995
  const streamingMessageIdRef = react.useRef(null);
2883
2996
  const pendingToolCallsRef = react.useRef(/* @__PURE__ */ new Map());
2884
2997
  const lastMessageContentRef = react.useRef("");
2998
+ const finalizedRef = react.useRef(false);
2885
2999
  const firedToolResultsRef = react.useRef(/* @__PURE__ */ new Set());
2886
3000
  const streamControllerRef = react.useRef(null);
3001
+ const pendingDelegationsRef = react.useRef(/* @__PURE__ */ new Map());
3002
+ const onDelegationRef = react.useRef(options.onDelegation);
3003
+ react.useEffect(() => {
3004
+ onDelegationRef.current = options.onDelegation;
3005
+ }, [options.onDelegation]);
2887
3006
  const updateStreamingMessage = react.useCallback((content) => {
2888
3007
  if (!streamingMessageIdRef.current) return;
2889
3008
  setMessages(
@@ -2912,21 +3031,72 @@ function useAgentChat(options) {
2912
3031
  });
2913
3032
  });
2914
3033
  }, []);
2915
- const finalizeStreamingMessage = react.useCallback(() => {
3034
+ const addDelegationEvent = react.useCallback((delegation) => {
3035
+ setMessages((prev) => {
3036
+ const targetId = streamingMessageIdRef.current ?? [...prev].reverse().find((m) => m.role === "assistant")?.id;
3037
+ if (!targetId) return prev;
3038
+ return prev.map((msg) => {
3039
+ if (msg.id !== targetId) return msg;
3040
+ const existing = msg.delegationEvents ?? [];
3041
+ if (delegation.type === "delegation_completed" && delegation.handoffId) {
3042
+ const updatedEvents = existing.map(
3043
+ (de) => de.handoffId === delegation.handoffId ? { ...de, ...delegation, status: delegation.status ?? "completed" } : de
3044
+ );
3045
+ const hasMatch = existing.some((de) => de.handoffId === delegation.handoffId);
3046
+ return {
3047
+ ...msg,
3048
+ delegationEvents: hasMatch ? updatedEvents : [...existing, delegation]
3049
+ };
3050
+ }
3051
+ return { ...msg, delegationEvents: [...existing, delegation] };
3052
+ });
3053
+ });
3054
+ }, []);
3055
+ const updateMessageImages = react.useCallback(() => {
3056
+ setMessages((prev) => {
3057
+ const targetId = streamingMessageIdRef.current ?? [...prev].reverse().find((m) => m.role === "assistant")?.id;
3058
+ if (!targetId) return prev;
3059
+ return prev.map((msg) => {
3060
+ if (msg.id !== targetId) return msg;
3061
+ const images = deriveImagesFromToolCalls(msg.toolCalls);
3062
+ return images.length > 0 ? { ...msg, images } : msg;
3063
+ });
3064
+ });
3065
+ }, []);
3066
+ const finalizeStreamingMessage = react.useCallback((finalOutput) => {
2916
3067
  if (!streamingMessageIdRef.current) return;
2917
- setMessages(
2918
- (prev) => prev.map(
2919
- (msg) => msg.id === streamingMessageIdRef.current ? { ...msg, isStreaming: false } : msg
2920
- )
2921
- );
3068
+ finalizedRef.current = true;
3069
+ const streamMsgId = streamingMessageIdRef.current;
3070
+ setMessages((prev) => {
3071
+ const resolvedContent = finalOutput || streamingContentRef.current || "";
3072
+ const duplicateExists = resolvedContent && prev.some(
3073
+ (msg) => msg.id !== streamMsgId && msg.role === "assistant" && !msg.isStreaming && msg.content === resolvedContent
3074
+ );
3075
+ if (duplicateExists) {
3076
+ return prev.filter((msg) => msg.id !== streamMsgId);
3077
+ }
3078
+ return prev.map((msg) => {
3079
+ if (msg.id !== streamMsgId) return msg;
3080
+ const updatedToolCalls = msg.toolCalls?.map(
3081
+ (tc) => tc.status === "running" || tc.status === "pending" ? { ...tc, status: "completed" } : tc
3082
+ );
3083
+ return {
3084
+ ...msg,
3085
+ content: resolvedContent || msg.content,
3086
+ isStreaming: false,
3087
+ toolCalls: updatedToolCalls
3088
+ };
3089
+ });
3090
+ });
2922
3091
  streamingMessageIdRef.current = null;
2923
3092
  streamingContentRef.current = "";
2924
3093
  pendingToolCallsRef.current.clear();
2925
3094
  firedToolResultsRef.current.clear();
3095
+ pendingDelegationsRef.current.clear();
2926
3096
  }, []);
2927
3097
  const handleExecutionLog = react.useCallback(
2928
3098
  (log) => {
2929
- console.log("[useAgentChat] handleExecutionLog:", log.type, log.metadata);
3099
+ if (__DEV__) console.log("[useAgentChat] handleExecutionLog:", log.type, log.metadata);
2930
3100
  switch (log.type) {
2931
3101
  // Primary handlers for ai-saas-api worker log types
2932
3102
  case "llm_response": {
@@ -2946,11 +3116,46 @@ function useAgentChat(options) {
2946
3116
  }
2947
3117
  break;
2948
3118
  }
3119
+ case "delegation": {
3120
+ const delegationType = log.metadata?.delegationType;
3121
+ if (delegationType === "started" || delegationType === "delegation_started") {
3122
+ const delegation = {
3123
+ type: "delegation_started",
3124
+ handoffId: log.metadata?.handoffId,
3125
+ toAgent: log.metadata?.targetAgentName || log.metadata?.targetAgentUuid,
3126
+ targetAgentUuid: log.metadata?.targetAgentUuid,
3127
+ taskPreview: log.metadata?.taskPreview,
3128
+ timestamp: new Date(log.timestamp || Date.now()),
3129
+ status: "active"
3130
+ };
3131
+ if (delegation.handoffId) {
3132
+ pendingDelegationsRef.current.set(delegation.handoffId, delegation);
3133
+ }
3134
+ addDelegationEvent(delegation);
3135
+ onDelegationRef.current?.(delegation);
3136
+ } else if (delegationType === "completed" || delegationType === "delegation_completed") {
3137
+ const delegation = {
3138
+ type: "delegation_completed",
3139
+ handoffId: log.metadata?.handoffId,
3140
+ resultPreview: log.metadata?.resultPreview,
3141
+ timestamp: new Date(log.timestamp || Date.now()),
3142
+ status: log.metadata?.status === "failed" ? "failed" : "completed",
3143
+ durationMs: log.durationMs
3144
+ };
3145
+ if (delegation.handoffId) {
3146
+ pendingDelegationsRef.current.delete(delegation.handoffId);
3147
+ }
3148
+ addDelegationEvent(delegation);
3149
+ onDelegationRef.current?.(delegation);
3150
+ }
3151
+ break;
3152
+ }
2949
3153
  case "info":
2950
3154
  case "system":
2951
- console.log("[useAgentChat] Status:", log.type, log.title);
3155
+ if (__DEV__) console.log("[useAgentChat] Status:", log.type, log.title);
2952
3156
  break;
2953
3157
  case "tool_call": {
3158
+ if (finalizedRef.current) break;
2954
3159
  const toolName = log.metadata?.toolName;
2955
3160
  if (SILENT_TOOL_NAMES.has(toolName)) break;
2956
3161
  const toolCallId = log.metadata?.toolCallId || `tool-${Date.now()}`;
@@ -3005,17 +3210,18 @@ function useAgentChat(options) {
3005
3210
  firedToolResultsRef.current.add(resultToolCallId);
3006
3211
  }
3007
3212
  onToolResultRef.current?.(resultToolName, result, durationMs);
3213
+ updateMessageImages();
3008
3214
  break;
3009
3215
  }
3010
3216
  default:
3011
- console.log("[useAgentChat] Unhandled log type:", log.type, log);
3217
+ if (__DEV__) console.log("[useAgentChat] Unhandled log type:", log.type, log);
3012
3218
  }
3013
3219
  },
3014
- [updateStreamingMessage, updateToolCall]
3220
+ [updateStreamingMessage, updateToolCall, updateMessageImages, addDelegationEvent]
3015
3221
  );
3016
3222
  const handleStreamLog = react.useCallback(
3017
3223
  (log) => {
3018
- console.log("[useAgentChat] handleStreamLog:", log.logType, log.metadata);
3224
+ if (__DEV__) console.log("[useAgentChat] handleStreamLog:", log.logType, log.metadata);
3019
3225
  switch (log.logType) {
3020
3226
  case "llm_response": {
3021
3227
  const llmText = log.metadata?.text || "";
@@ -3034,9 +3240,42 @@ function useAgentChat(options) {
3034
3240
  }
3035
3241
  break;
3036
3242
  }
3243
+ case "delegation_started": {
3244
+ const delegation = {
3245
+ type: "delegation_started",
3246
+ handoffId: log.metadata?.handoffId,
3247
+ toAgent: log.metadata?.targetAgentName || log.metadata?.targetAgentUuid,
3248
+ targetAgentUuid: log.metadata?.targetAgentUuid,
3249
+ taskPreview: log.metadata?.taskPreview,
3250
+ timestamp: new Date(log.timestamp || Date.now()),
3251
+ status: "active"
3252
+ };
3253
+ if (delegation.handoffId) {
3254
+ pendingDelegationsRef.current.set(delegation.handoffId, delegation);
3255
+ }
3256
+ addDelegationEvent(delegation);
3257
+ onDelegationRef.current?.(delegation);
3258
+ break;
3259
+ }
3260
+ case "delegation_completed": {
3261
+ const delegation = {
3262
+ type: "delegation_completed",
3263
+ handoffId: log.metadata?.handoffId,
3264
+ resultPreview: log.metadata?.resultPreview,
3265
+ timestamp: new Date(log.timestamp || Date.now()),
3266
+ status: log.metadata?.status === "failed" ? "failed" : "completed",
3267
+ durationMs: log.durationMs
3268
+ };
3269
+ if (delegation.handoffId) {
3270
+ pendingDelegationsRef.current.delete(delegation.handoffId);
3271
+ }
3272
+ addDelegationEvent(delegation);
3273
+ onDelegationRef.current?.(delegation);
3274
+ break;
3275
+ }
3037
3276
  case "info":
3038
3277
  case "system":
3039
- console.log("[useAgentChat] Status:", log.logType, log.message);
3278
+ if (__DEV__) console.log("[useAgentChat] Status:", log.logType, log.message);
3040
3279
  break;
3041
3280
  case "response_text":
3042
3281
  case "text_chunk": {
@@ -3046,6 +3285,7 @@ function useAgentChat(options) {
3046
3285
  break;
3047
3286
  }
3048
3287
  case "tool_call": {
3288
+ if (finalizedRef.current) break;
3049
3289
  const toolName = log.metadata?.toolName;
3050
3290
  if (SILENT_TOOL_NAMES.has(toolName)) break;
3051
3291
  const toolCallId = log.metadata?.toolCallId || `tool-${Date.now()}`;
@@ -3100,6 +3340,7 @@ function useAgentChat(options) {
3100
3340
  firedToolResultsRef.current.add(resultToolCallId);
3101
3341
  }
3102
3342
  onToolResultRef.current?.(resultToolName, result, durationMs);
3343
+ updateMessageImages();
3103
3344
  break;
3104
3345
  }
3105
3346
  case "final_response": {
@@ -3111,10 +3352,10 @@ function useAgentChat(options) {
3111
3352
  break;
3112
3353
  }
3113
3354
  default:
3114
- console.log("[useAgentChat] Unknown log type:", log.logType, log);
3355
+ if (__DEV__) console.log("[useAgentChat] Unknown log type:", log.logType, log);
3115
3356
  }
3116
3357
  },
3117
- [updateStreamingMessage, updateToolCall]
3358
+ [updateStreamingMessage, updateToolCall, updateMessageImages, addDelegationEvent]
3118
3359
  );
3119
3360
  const handleClarification = react.useCallback(
3120
3361
  (data) => {
@@ -3123,17 +3364,23 @@ function useAgentChat(options) {
3123
3364
  },
3124
3365
  [onClarification]
3125
3366
  );
3126
- const handleComplete = react.useCallback(() => {
3127
- console.log("[useAgentChat] handleComplete called");
3367
+ const completedRef = react.useRef(false);
3368
+ const handleComplete = react.useCallback((finalOutput) => {
3369
+ if (completedRef.current) {
3370
+ if (__DEV__) console.log("[useAgentChat] handleComplete: skipping duplicate complete");
3371
+ return;
3372
+ }
3373
+ completedRef.current = true;
3374
+ if (__DEV__) console.log("[useAgentChat] handleComplete called");
3128
3375
  setIsLoading(false);
3129
3376
  setIsStreamControllerConnected(false);
3130
- finalizeStreamingMessage();
3377
+ finalizeStreamingMessage(finalOutput);
3131
3378
  setCurrentExecutionId(null);
3132
3379
  streamControllerRef.current = null;
3133
3380
  }, [finalizeStreamingMessage]);
3134
3381
  const handleError = react.useCallback(
3135
3382
  (errorMsg) => {
3136
- console.log("[useAgentChat] handleError called:", errorMsg);
3383
+ if (__DEV__) console.log("[useAgentChat] handleError called:", errorMsg);
3137
3384
  const chatError = {
3138
3385
  code: "EXECUTION_ERROR",
3139
3386
  message: errorMsg,
@@ -3172,43 +3419,39 @@ function useAgentChat(options) {
3172
3419
  if (pollingExecutionIdRef.current === executionId) return;
3173
3420
  stopPolling();
3174
3421
  pollingExecutionIdRef.current = executionId;
3175
- console.log("[useAgentChat] Starting polling fallback for:", executionId);
3422
+ if (__DEV__) console.log("[useAgentChat] Starting polling fallback for:", executionId);
3176
3423
  const poll = async () => {
3177
3424
  if (pollingExecutionIdRef.current !== executionId) return;
3178
3425
  try {
3179
3426
  const execution = await adapter.getExecution(executionId);
3180
3427
  if (execution.status === "completed") {
3181
- console.log("[useAgentChat] Polling: execution completed");
3182
- if (execution.result) {
3183
- streamingContentRef.current = execution.result;
3184
- updateStreamingMessage(execution.result);
3185
- }
3428
+ if (__DEV__) console.log("[useAgentChat] Polling: execution completed");
3186
3429
  stopPolling();
3187
- handleComplete();
3430
+ handleComplete(execution.result || void 0);
3188
3431
  } else if (execution.status === "failed") {
3189
- console.log("[useAgentChat] Polling: execution failed");
3432
+ if (__DEV__) console.log("[useAgentChat] Polling: execution failed");
3190
3433
  stopPolling();
3191
3434
  handleError(execution.error || "Execution failed");
3192
3435
  }
3193
3436
  } catch (err) {
3194
- console.warn("[useAgentChat] Polling error (will retry):", err);
3437
+ if (__DEV__) console.warn("[useAgentChat] Polling error (will retry):", err);
3195
3438
  }
3196
3439
  };
3197
3440
  poll();
3198
- pollingIntervalRef.current = setInterval(poll, 2e3);
3199
- }, [adapter, stopPolling, updateStreamingMessage, handleComplete, handleError]);
3441
+ pollingIntervalRef.current = setInterval(poll, pollingInterval ?? 2e3);
3442
+ }, [adapter, stopPolling, handleComplete, handleError, pollingInterval]);
3200
3443
  react.useEffect(() => {
3201
- if (!useStreamController && isUsingFallback && currentExecutionId && isLoading) {
3202
- console.log("[useAgentChat] SSE fallback detected, activating polling");
3444
+ if (!useStreamController && isUsingFallback && currentExecutionId && isLoading && pollingEnabled !== false) {
3445
+ if (__DEV__) console.log("[useAgentChat] SSE fallback detected, activating polling");
3203
3446
  startPolling(currentExecutionId);
3204
3447
  }
3205
- }, [useStreamController, isUsingFallback, currentExecutionId, isLoading, startPolling]);
3448
+ }, [useStreamController, isUsingFallback, currentExecutionId, isLoading, startPolling, pollingEnabled]);
3206
3449
  const sseTimeoutRef = react.useRef(null);
3207
3450
  react.useEffect(() => {
3208
- if (!useStreamController && currentExecutionId && isLoading && !legacyIsConnected && !isUsingFallback) {
3451
+ if (!useStreamController && currentExecutionId && isLoading && !legacyIsConnected && !isUsingFallback && pollingEnabled !== false) {
3209
3452
  sseTimeoutRef.current = setTimeout(() => {
3210
3453
  if (!legacyIsConnected && currentExecutionId && isLoading) {
3211
- console.log("[useAgentChat] SSE connection timeout, activating polling fallback");
3454
+ if (__DEV__) console.log("[useAgentChat] SSE connection timeout, activating polling fallback");
3212
3455
  startPolling(currentExecutionId);
3213
3456
  }
3214
3457
  }, 1e4);
@@ -3219,7 +3462,7 @@ function useAgentChat(options) {
3219
3462
  sseTimeoutRef.current = null;
3220
3463
  }
3221
3464
  };
3222
- }, [useStreamController, currentExecutionId, isLoading, legacyIsConnected, isUsingFallback, startPolling]);
3465
+ }, [useStreamController, currentExecutionId, isLoading, legacyIsConnected, isUsingFallback, startPolling, pollingEnabled]);
3223
3466
  react.useEffect(() => {
3224
3467
  if (!currentExecutionId) {
3225
3468
  stopPolling();
@@ -3235,7 +3478,7 @@ function useAgentChat(options) {
3235
3478
  streamControllerRef.current.cancel();
3236
3479
  streamControllerRef.current = null;
3237
3480
  }
3238
- console.log("[useAgentChat] Creating stream controller for:", executionId);
3481
+ if (__DEV__) console.log("[useAgentChat] Creating stream controller for:", executionId);
3239
3482
  const controller = adapter.createStream(executionId, sessionId);
3240
3483
  streamControllerRef.current = controller;
3241
3484
  controller.on("log", (log) => {
@@ -3286,6 +3529,34 @@ function useAgentChat(options) {
3286
3529
  }
3287
3530
  firedToolResultsRef.current.add(toolCallId);
3288
3531
  onToolResultRef.current?.(toolName, data.result, data.durationMs);
3532
+ updateMessageImages();
3533
+ });
3534
+ controller.on("delegationStarted", (data) => {
3535
+ const delegation = {
3536
+ type: "delegation_started",
3537
+ handoffId: data.handoffId,
3538
+ toAgent: data.targetAgentName || data.targetAgentUuid,
3539
+ targetAgentUuid: data.targetAgentUuid,
3540
+ taskPreview: data.taskPreview,
3541
+ timestamp: new Date(data.timestamp),
3542
+ status: "active"
3543
+ };
3544
+ pendingDelegationsRef.current.set(data.handoffId, delegation);
3545
+ addDelegationEvent(delegation);
3546
+ onDelegationRef.current?.(delegation);
3547
+ });
3548
+ controller.on("delegationCompleted", (data) => {
3549
+ const delegation = {
3550
+ type: "delegation_completed",
3551
+ handoffId: data.handoffId,
3552
+ resultPreview: data.resultPreview,
3553
+ timestamp: new Date(data.timestamp),
3554
+ status: data.status === "failed" ? "failed" : "completed",
3555
+ durationMs: data.durationMs
3556
+ };
3557
+ pendingDelegationsRef.current.delete(data.handoffId);
3558
+ addDelegationEvent(delegation);
3559
+ onDelegationRef.current?.(delegation);
3289
3560
  });
3290
3561
  controller.on("textDelta", (data) => {
3291
3562
  streamingContentRef.current += data.delta;
@@ -3299,11 +3570,8 @@ function useAgentChat(options) {
3299
3570
  });
3300
3571
  });
3301
3572
  controller.on("complete", ({ execution }) => {
3302
- if (execution?.output && !streamingContentRef.current) {
3303
- streamingContentRef.current = execution.output;
3304
- updateStreamingMessage(execution.output);
3305
- }
3306
- handleComplete();
3573
+ const output = execution?.output || void 0;
3574
+ handleComplete(output);
3307
3575
  });
3308
3576
  controller.on("error", (errorEvent) => {
3309
3577
  handleError(errorEvent.error);
@@ -3317,7 +3585,7 @@ function useAgentChat(options) {
3317
3585
  });
3318
3586
  setIsStreamControllerConnected(true);
3319
3587
  },
3320
- [adapter, handleExecutionLog, updateStreamingMessage, updateToolCall, handleClarification, handleComplete, handleError]
3588
+ [adapter, handleExecutionLog, updateStreamingMessage, updateToolCall, updateMessageImages, addDelegationEvent, handleClarification, handleComplete, handleError]
3321
3589
  );
3322
3590
  const sendMessage = react.useCallback(
3323
3591
  async (content, options2) => {
@@ -3347,8 +3615,10 @@ function useAgentChat(options) {
3347
3615
  setMessages((prev) => [...prev, assistantMessage]);
3348
3616
  streamingMessageIdRef.current = assistantMessageId;
3349
3617
  streamingContentRef.current = "";
3618
+ completedRef.current = false;
3619
+ finalizedRef.current = false;
3350
3620
  try {
3351
- console.log("[useAgentChat] Starting execution...", { agentId, sessionId: currentSessionId });
3621
+ if (__DEV__) console.log("[useAgentChat] Starting execution...", { agentId, sessionId: currentSessionId });
3352
3622
  const result = await adapter.startExecution({
3353
3623
  agentId,
3354
3624
  teamId,
@@ -3356,7 +3626,7 @@ function useAgentChat(options) {
3356
3626
  content: content.trim(),
3357
3627
  attachmentUuids
3358
3628
  });
3359
- console.log("[useAgentChat] Execution started:", result);
3629
+ if (__DEV__) console.log("[useAgentChat] Execution started:", result);
3360
3630
  if (!currentSessionId && result.sessionId) {
3361
3631
  internallyCreatedSessionRef.current = result.sessionId;
3362
3632
  setCurrentSessionId(result.sessionId);
@@ -3367,7 +3637,7 @@ function useAgentChat(options) {
3367
3637
  connectStreamController(result.executionId, result.sessionId || currentSessionId || void 0);
3368
3638
  setCurrentExecutionId(result.executionId);
3369
3639
  } else {
3370
- console.log("[useAgentChat] Setting executionId:", result.executionId);
3640
+ if (__DEV__) console.log("[useAgentChat] Setting executionId:", result.executionId);
3371
3641
  setCurrentExecutionId(result.executionId);
3372
3642
  }
3373
3643
  } catch (err) {
@@ -3427,6 +3697,7 @@ function useAgentChat(options) {
3427
3697
  setMessages([]);
3428
3698
  setCurrentSessionId(null);
3429
3699
  hasLoadedInitialSession.current = false;
3700
+ lastLoadedSessionRef.current = null;
3430
3701
  internallyCreatedSessionRef.current = null;
3431
3702
  }, []);
3432
3703
  const loadSession = react.useCallback(
@@ -3522,15 +3793,20 @@ function useAgentChat(options) {
3522
3793
  },
3523
3794
  [adapter, onError]
3524
3795
  );
3796
+ const lastLoadedSessionRef = react.useRef(null);
3525
3797
  react.useEffect(() => {
3526
- if (initialSessionId && !hasLoadedInitialSession.current) {
3527
- if (internallyCreatedSessionRef.current === initialSessionId) {
3528
- hasLoadedInitialSession.current = true;
3529
- return;
3530
- }
3798
+ if (!initialSessionId) return;
3799
+ if (internallyCreatedSessionRef.current === initialSessionId) {
3800
+ lastLoadedSessionRef.current = initialSessionId;
3531
3801
  hasLoadedInitialSession.current = true;
3532
- loadSession(initialSessionId);
3802
+ return;
3803
+ }
3804
+ if (lastLoadedSessionRef.current === initialSessionId && hasLoadedInitialSession.current) {
3805
+ return;
3533
3806
  }
3807
+ lastLoadedSessionRef.current = initialSessionId;
3808
+ hasLoadedInitialSession.current = true;
3809
+ loadSession(initialSessionId);
3534
3810
  }, [initialSessionId, loadSession]);
3535
3811
  react.useEffect(() => {
3536
3812
  return () => {
@@ -3546,6 +3822,16 @@ function useAgentChat(options) {
3546
3822
  }
3547
3823
  return !!currentExecutionId && legacyIsConnected;
3548
3824
  }, [useStreamController, currentExecutionId, isStreamControllerConnected, legacyIsConnected]);
3825
+ const activeDelegation = react.useMemo(() => {
3826
+ for (let i = messages.length - 1; i >= 0; i--) {
3827
+ const msg = messages[i];
3828
+ if (msg.delegationEvents) {
3829
+ const active = msg.delegationEvents.find((de) => de.status === "active");
3830
+ if (active) return active;
3831
+ }
3832
+ }
3833
+ return null;
3834
+ }, [messages]);
3549
3835
  return {
3550
3836
  messages,
3551
3837
  isLoading,
@@ -3554,6 +3840,7 @@ function useAgentChat(options) {
3554
3840
  error,
3555
3841
  sessionId: currentSessionId,
3556
3842
  clarification,
3843
+ activeDelegation,
3557
3844
  sendMessage,
3558
3845
  respondToClarification,
3559
3846
  cancel,
@@ -4409,18 +4696,30 @@ function ChatContainer({
4409
4696
  children,
4410
4697
  maxHeight = "600px",
4411
4698
  className,
4412
- theme = "system"
4699
+ theme = "system",
4700
+ layout = "fixed"
4413
4701
  }) {
4414
4702
  const maxHeightValue = typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight;
4703
+ const isFill = layout === "fill";
4415
4704
  return /* @__PURE__ */ jsxRuntime.jsx(
4416
4705
  "div",
4417
4706
  {
4418
4707
  className: cn2(
4419
- "flex flex-col bg-white dark:bg-gray-900 rounded-lg border border-gray-200 dark:border-gray-700 overflow-hidden",
4708
+ "cadra-chat-container flex flex-col overflow-hidden",
4709
+ // Default colors use CSS custom properties with Tailwind fallbacks.
4710
+ // Consumers can override via CSS: --chat-bg, --chat-border, --chat-border-radius
4711
+ !isFill && "rounded-lg border",
4712
+ isFill && "flex-1 min-h-0",
4420
4713
  className
4421
4714
  ),
4422
- style: { maxHeight: maxHeightValue },
4715
+ style: {
4716
+ ...!isFill ? { maxHeight: maxHeightValue } : void 0,
4717
+ // CSS custom properties for theming — consumers set these to override
4718
+ backgroundColor: "var(--chat-bg, var(--background, #fff))",
4719
+ borderColor: !isFill ? "var(--chat-border, var(--border, #e5e7eb))" : void 0
4720
+ },
4423
4721
  "data-theme": theme,
4722
+ "data-layout": layout,
4424
4723
  children
4425
4724
  }
4426
4725
  );
@@ -5107,7 +5406,7 @@ var FileDropZone = react.forwardRef(
5107
5406
  {
5108
5407
  ref: dropZoneRef,
5109
5408
  "data-dropzone": "wrapper",
5110
- className: cn4("relative w-full h-full", className),
5409
+ className: cn4("relative flex flex-col flex-1 min-h-0", className),
5111
5410
  style: { minHeight: "inherit" },
5112
5411
  children: [
5113
5412
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -5392,6 +5691,312 @@ function AskUserPrompt({
5392
5691
  function cn6(...classes) {
5393
5692
  return classes.filter(Boolean).join(" ");
5394
5693
  }
5694
+ function formatDuration(ms) {
5695
+ if (ms < 1e3) return `${ms}ms`;
5696
+ return `${(ms / 1e3).toFixed(1)}s`;
5697
+ }
5698
+ function DelegationProgress({
5699
+ event,
5700
+ className
5701
+ }) {
5702
+ const statusIcon = react.useMemo(() => {
5703
+ switch (event.status) {
5704
+ case "active":
5705
+ return /* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner, { className: "h-4 w-4 text-blue-500" });
5706
+ case "completed":
5707
+ return /* @__PURE__ */ jsxRuntime.jsx(CheckCircleIcon, { className: "h-4 w-4 text-green-500" });
5708
+ case "failed":
5709
+ return /* @__PURE__ */ jsxRuntime.jsx(AlertCircleIcon, { className: "h-4 w-4 text-red-500" });
5710
+ default:
5711
+ return /* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner, { className: "h-4 w-4 text-gray-400" });
5712
+ }
5713
+ }, [event.status]);
5714
+ const statusColor = react.useMemo(() => {
5715
+ switch (event.status) {
5716
+ case "active":
5717
+ return "border-blue-200 dark:border-blue-800 bg-blue-50/50 dark:bg-blue-950/20";
5718
+ case "completed":
5719
+ return "border-green-200 dark:border-green-800 bg-green-50/50 dark:bg-green-950/20";
5720
+ case "failed":
5721
+ return "border-red-200 dark:border-red-800 bg-red-50/50 dark:bg-red-950/20";
5722
+ default:
5723
+ return "border-gray-200 dark:border-gray-700";
5724
+ }
5725
+ }, [event.status]);
5726
+ return /* @__PURE__ */ jsxRuntime.jsx(
5727
+ "div",
5728
+ {
5729
+ className: cn6(
5730
+ "rounded-lg border text-sm px-3 py-2",
5731
+ statusColor,
5732
+ className
5733
+ ),
5734
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
5735
+ statusIcon,
5736
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
5737
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
5738
+ event.fromAgent && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5739
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-gray-700 dark:text-gray-300 truncate", children: event.fromAgent }),
5740
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-400 dark:text-gray-500 flex-shrink-0", children: "\u2192" })
5741
+ ] }),
5742
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-gray-900 dark:text-gray-100 truncate", children: event.toAgent || event.targetAgentUuid || "Specialist" })
5743
+ ] }),
5744
+ event.taskPreview && event.status === "active" && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400 truncate mt-0.5", children: event.taskPreview }),
5745
+ event.resultPreview && event.status === "completed" && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-green-600 dark:text-green-400 truncate mt-0.5", children: event.resultPreview })
5746
+ ] }),
5747
+ event.durationMs !== void 0 && event.status !== "active" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-gray-500 dark:text-gray-400 flex-shrink-0", children: formatDuration(event.durationMs) })
5748
+ ] })
5749
+ }
5750
+ );
5751
+ }
5752
+ function DelegationProgressList({
5753
+ events,
5754
+ className
5755
+ }) {
5756
+ if (!events || events.length === 0) return null;
5757
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn6("space-y-2", className), children: events.map((event, index) => /* @__PURE__ */ jsxRuntime.jsx(
5758
+ DelegationProgress,
5759
+ {
5760
+ event
5761
+ },
5762
+ event.handoffId || `delegation-${index}`
5763
+ )) });
5764
+ }
5765
+ function ImageLightbox({
5766
+ images,
5767
+ currentIndex,
5768
+ onClose,
5769
+ onPrev,
5770
+ onNext,
5771
+ className
5772
+ }) {
5773
+ const currentImage = images[currentIndex];
5774
+ const hasMultiple = images.length > 1;
5775
+ react.useEffect(() => {
5776
+ function handleKeyDown(e) {
5777
+ switch (e.key) {
5778
+ case "Escape":
5779
+ onClose();
5780
+ break;
5781
+ case "ArrowLeft":
5782
+ if (hasMultiple) onPrev();
5783
+ break;
5784
+ case "ArrowRight":
5785
+ if (hasMultiple) onNext();
5786
+ break;
5787
+ }
5788
+ }
5789
+ document.addEventListener("keydown", handleKeyDown);
5790
+ return () => document.removeEventListener("keydown", handleKeyDown);
5791
+ }, [onClose, onPrev, onNext, hasMultiple]);
5792
+ react.useEffect(() => {
5793
+ const originalOverflow = document.body.style.overflow;
5794
+ document.body.style.overflow = "hidden";
5795
+ return () => {
5796
+ document.body.style.overflow = originalOverflow;
5797
+ };
5798
+ }, []);
5799
+ const handleDownload = react.useCallback(() => {
5800
+ if (!currentImage) return;
5801
+ const link = document.createElement("a");
5802
+ link.href = currentImage.url;
5803
+ link.download = currentImage.filename || `image-${currentIndex + 1}`;
5804
+ link.target = "_blank";
5805
+ link.rel = "noopener noreferrer";
5806
+ document.body.appendChild(link);
5807
+ link.click();
5808
+ document.body.removeChild(link);
5809
+ }, [currentImage, currentIndex]);
5810
+ if (!currentImage) return null;
5811
+ return /* @__PURE__ */ jsxRuntime.jsxs(
5812
+ "div",
5813
+ {
5814
+ className: `fixed inset-0 z-50 flex items-center justify-center bg-black/80 ${className || ""}`,
5815
+ onClick: onClose,
5816
+ children: [
5817
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute top-0 left-0 right-0 flex items-center justify-between p-4 z-10", children: [
5818
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-white text-sm", children: hasMultiple && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
5819
+ currentIndex + 1,
5820
+ " / ",
5821
+ images.length
5822
+ ] }) }),
5823
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
5824
+ /* @__PURE__ */ jsxRuntime.jsx(
5825
+ "button",
5826
+ {
5827
+ type: "button",
5828
+ onClick: (e) => {
5829
+ e.stopPropagation();
5830
+ handleDownload();
5831
+ },
5832
+ className: "p-2 rounded-full bg-black/50 hover:bg-black/70 text-white transition-colors",
5833
+ "aria-label": "Download image",
5834
+ children: /* @__PURE__ */ jsxRuntime.jsx(DownloadIcon, { className: "h-5 w-5" })
5835
+ }
5836
+ ),
5837
+ /* @__PURE__ */ jsxRuntime.jsx(
5838
+ "button",
5839
+ {
5840
+ type: "button",
5841
+ onClick: (e) => {
5842
+ e.stopPropagation();
5843
+ onClose();
5844
+ },
5845
+ className: "p-2 rounded-full bg-black/50 hover:bg-black/70 text-white transition-colors",
5846
+ "aria-label": "Close lightbox",
5847
+ children: /* @__PURE__ */ jsxRuntime.jsx(XIcon, { className: "h-5 w-5" })
5848
+ }
5849
+ )
5850
+ ] })
5851
+ ] }),
5852
+ hasMultiple && /* @__PURE__ */ jsxRuntime.jsx(
5853
+ "button",
5854
+ {
5855
+ type: "button",
5856
+ onClick: (e) => {
5857
+ e.stopPropagation();
5858
+ onPrev();
5859
+ },
5860
+ className: "absolute left-4 top-1/2 -translate-y-1/2 p-2 rounded-full bg-black/50 hover:bg-black/70 text-white transition-colors z-10",
5861
+ "aria-label": "Previous image",
5862
+ children: /* @__PURE__ */ jsxRuntime.jsx(ChevronLeftIcon, { className: "h-6 w-6" })
5863
+ }
5864
+ ),
5865
+ /* @__PURE__ */ jsxRuntime.jsx(
5866
+ "img",
5867
+ {
5868
+ src: currentImage.url,
5869
+ alt: currentImage.alt || `Image ${currentIndex + 1}`,
5870
+ className: "max-w-[90vw] max-h-[85vh] object-contain",
5871
+ onClick: (e) => e.stopPropagation()
5872
+ }
5873
+ ),
5874
+ hasMultiple && /* @__PURE__ */ jsxRuntime.jsx(
5875
+ "button",
5876
+ {
5877
+ type: "button",
5878
+ onClick: (e) => {
5879
+ e.stopPropagation();
5880
+ onNext();
5881
+ },
5882
+ className: "absolute right-4 top-1/2 -translate-y-1/2 p-2 rounded-full bg-black/50 hover:bg-black/70 text-white transition-colors z-10",
5883
+ "aria-label": "Next image",
5884
+ children: /* @__PURE__ */ jsxRuntime.jsx(ChevronRightIcon, { className: "h-6 w-6" })
5885
+ }
5886
+ ),
5887
+ currentImage.alt && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute bottom-0 left-0 right-0 p-4 text-center z-10", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-white text-sm bg-black/50 inline-block px-3 py-1 rounded-full", children: currentImage.alt }) })
5888
+ ]
5889
+ }
5890
+ );
5891
+ }
5892
+ function cn7(...classes) {
5893
+ return classes.filter(Boolean).join(" ");
5894
+ }
5895
+ function ImageWithLoading({ src, alt, className, onClick }) {
5896
+ const [isLoaded, setIsLoaded] = react.useState(false);
5897
+ const [hasError, setHasError] = react.useState(false);
5898
+ return /* @__PURE__ */ jsxRuntime.jsxs(
5899
+ "div",
5900
+ {
5901
+ className: cn7(
5902
+ "relative overflow-hidden bg-gray-100 dark:bg-gray-800",
5903
+ className
5904
+ ),
5905
+ children: [
5906
+ !isLoaded && !hasError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 animate-pulse bg-gray-200 dark:bg-gray-700" }),
5907
+ hasError && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex items-center justify-center text-gray-400 dark:text-gray-500 text-sm", children: "Failed to load" }),
5908
+ /* @__PURE__ */ jsxRuntime.jsx(
5909
+ "img",
5910
+ {
5911
+ src,
5912
+ alt,
5913
+ loading: "lazy",
5914
+ className: cn7(
5915
+ "w-full h-auto max-h-[300px] object-contain transition-opacity duration-200",
5916
+ isLoaded ? "opacity-100" : "opacity-0"
5917
+ ),
5918
+ onLoad: () => setIsLoaded(true),
5919
+ onError: () => setHasError(true),
5920
+ onClick,
5921
+ style: onClick ? { cursor: "pointer" } : void 0
5922
+ }
5923
+ )
5924
+ ]
5925
+ }
5926
+ );
5927
+ }
5928
+ function ImageGallery({
5929
+ images,
5930
+ onImageClick,
5931
+ className
5932
+ }) {
5933
+ const [lightboxIndex, setLightboxIndex] = react.useState(null);
5934
+ const handleImageClick = react.useCallback(
5935
+ (image, index) => {
5936
+ if (onImageClick) {
5937
+ onImageClick(image);
5938
+ } else {
5939
+ setLightboxIndex(index);
5940
+ }
5941
+ },
5942
+ [onImageClick]
5943
+ );
5944
+ const handleLightboxClose = react.useCallback(() => {
5945
+ setLightboxIndex(null);
5946
+ }, []);
5947
+ const handleLightboxPrev = react.useCallback(() => {
5948
+ setLightboxIndex(
5949
+ (prev) => prev !== null ? (prev - 1 + images.length) % images.length : null
5950
+ );
5951
+ }, [images.length]);
5952
+ const handleLightboxNext = react.useCallback(() => {
5953
+ setLightboxIndex(
5954
+ (prev) => prev !== null ? (prev + 1) % images.length : null
5955
+ );
5956
+ }, [images.length]);
5957
+ if (!images || images.length === 0) return null;
5958
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5959
+ /* @__PURE__ */ jsxRuntime.jsx(
5960
+ "div",
5961
+ {
5962
+ className: cn7(
5963
+ "grid gap-2",
5964
+ images.length === 1 ? "grid-cols-1" : images.length === 2 ? "grid-cols-2" : "grid-cols-2 sm:grid-cols-3",
5965
+ className
5966
+ ),
5967
+ children: images.map((image, index) => /* @__PURE__ */ jsxRuntime.jsx(
5968
+ "button",
5969
+ {
5970
+ type: "button",
5971
+ onClick: () => handleImageClick(image, index),
5972
+ className: "block rounded-lg overflow-hidden border border-gray-200 dark:border-gray-700 hover:border-blue-400 dark:hover:border-blue-600 transition-colors text-left",
5973
+ children: /* @__PURE__ */ jsxRuntime.jsx(
5974
+ ImageWithLoading,
5975
+ {
5976
+ src: image.url,
5977
+ alt: image.alt || `Image ${index + 1}`
5978
+ }
5979
+ )
5980
+ },
5981
+ `${image.url}-${index}`
5982
+ ))
5983
+ }
5984
+ ),
5985
+ lightboxIndex !== null && !onImageClick && /* @__PURE__ */ jsxRuntime.jsx(
5986
+ ImageLightbox,
5987
+ {
5988
+ images,
5989
+ currentIndex: lightboxIndex,
5990
+ onClose: handleLightboxClose,
5991
+ onPrev: handleLightboxPrev,
5992
+ onNext: handleLightboxNext
5993
+ }
5994
+ )
5995
+ ] });
5996
+ }
5997
+ function cn8(...classes) {
5998
+ return classes.filter(Boolean).join(" ");
5999
+ }
5395
6000
  function MarkdownContent({
5396
6001
  content,
5397
6002
  className,
@@ -5411,11 +6016,11 @@ function MarkdownContent({
5411
6016
  h3: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold mt-3 mb-1 first:mt-0", children }),
5412
6017
  h4: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "text-base font-semibold mt-2 mb-1 first:mt-0", children }),
5413
6018
  // Paragraphs
5414
- p: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 last:mb-0 leading-relaxed", children }),
6019
+ p: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-1.5 last:mb-0", children }),
5415
6020
  // Lists
5416
- ul: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "list-disc list-inside mb-2 space-y-1", children }),
5417
- ol: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("ol", { className: "list-decimal list-inside mb-2 space-y-1", children }),
5418
- li: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("li", { className: "leading-relaxed", children }),
6021
+ ul: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "list-disc list-inside mb-1.5 last:mb-0", children }),
6022
+ ol: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("ol", { className: "list-decimal list-inside mb-1.5 last:mb-0", children }),
6023
+ li: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("li", { className: "", children }),
5419
6024
  // Links
5420
6025
  a: ({ href, children }) => /* @__PURE__ */ jsxRuntime.jsx(
5421
6026
  "a",
@@ -5450,7 +6055,7 @@ function MarkdownContent({
5450
6055
  if (isCodeBlock) {
5451
6056
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative my-2", children: [
5452
6057
  language && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-0 right-0 px-2 py-1 text-xs font-mono text-gray-500 dark:text-gray-400 bg-gray-100 dark:bg-gray-800 rounded-bl rounded-tr border-b border-l border-gray-200 dark:border-gray-700", children: language }),
5453
- /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "bg-gray-100 dark:bg-gray-800 rounded-lg p-4 overflow-x-auto text-sm", children: /* @__PURE__ */ jsxRuntime.jsx("code", { className: cn6("font-mono", codeClassName), ...props, children }) })
6058
+ /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "bg-gray-100 dark:bg-gray-800 rounded-lg p-4 overflow-x-auto text-sm", children: /* @__PURE__ */ jsxRuntime.jsx("code", { className: cn8("font-mono", codeClassName), ...props, children }) })
5454
6059
  ] });
5455
6060
  }
5456
6061
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -5497,7 +6102,7 @@ function MarkdownContent({
5497
6102
  () => customComponents ? { ...defaultComponents, ...customComponents } : defaultComponents,
5498
6103
  [defaultComponents, customComponents]
5499
6104
  );
5500
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn6("prose prose-sm dark:prose-invert max-w-none", className), children: /* @__PURE__ */ jsxRuntime.jsx(
6105
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn8("max-w-none text-sm leading-relaxed", className), children: /* @__PURE__ */ jsxRuntime.jsx(
5501
6106
  ReactMarkdown__default.default,
5502
6107
  {
5503
6108
  remarkPlugins: [remarkGfm__default.default],
@@ -5507,7 +6112,89 @@ function MarkdownContent({
5507
6112
  }
5508
6113
  ) });
5509
6114
  }
5510
- function cn7(...classes) {
6115
+ function cn9(...classes) {
6116
+ return classes.filter(Boolean).join(" ");
6117
+ }
6118
+ function ThinkingBlock({
6119
+ block,
6120
+ defaultExpanded = false,
6121
+ className
6122
+ }) {
6123
+ const [isExpanded, setIsExpanded] = react.useState(defaultExpanded);
6124
+ return /* @__PURE__ */ jsxRuntime.jsxs(
6125
+ "div",
6126
+ {
6127
+ className: cn9(
6128
+ "rounded-lg border",
6129
+ "border-purple-200 dark:border-purple-800",
6130
+ "bg-purple-50/50 dark:bg-purple-950/20",
6131
+ className
6132
+ ),
6133
+ children: [
6134
+ /* @__PURE__ */ jsxRuntime.jsxs(
6135
+ "button",
6136
+ {
6137
+ type: "button",
6138
+ onClick: () => setIsExpanded(!isExpanded),
6139
+ className: "w-full flex items-center gap-2 px-3 py-2 text-sm hover:bg-purple-100/50 dark:hover:bg-purple-900/30 transition-colors rounded-lg",
6140
+ children: [
6141
+ isExpanded ? /* @__PURE__ */ jsxRuntime.jsx(ChevronDownIcon, { className: "h-4 w-4 text-purple-400 flex-shrink-0" }) : /* @__PURE__ */ jsxRuntime.jsx(ChevronRightIcon, { className: "h-4 w-4 text-purple-400 flex-shrink-0" }),
6142
+ /* @__PURE__ */ jsxRuntime.jsx(SparklesIcon, { className: "h-4 w-4 text-purple-500 flex-shrink-0" }),
6143
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-purple-700 dark:text-purple-300", children: "Thinking" })
6144
+ ]
6145
+ }
6146
+ ),
6147
+ isExpanded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 pb-3 border-t border-purple-200 dark:border-purple-800", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 text-sm text-purple-800 dark:text-purple-200 whitespace-pre-wrap font-mono leading-relaxed", children: block.content }) })
6148
+ ]
6149
+ }
6150
+ );
6151
+ }
6152
+ function ThinkingBlockList({
6153
+ blocks,
6154
+ defaultExpanded = false,
6155
+ className
6156
+ }) {
6157
+ if (!blocks || blocks.length === 0) return null;
6158
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn9("space-y-2", className), children: blocks.map((block) => /* @__PURE__ */ jsxRuntime.jsx(
6159
+ ThinkingBlock,
6160
+ {
6161
+ block,
6162
+ defaultExpanded
6163
+ },
6164
+ block.id
6165
+ )) });
6166
+ }
6167
+ var INTERNAL_TOOL_NAMES = /* @__PURE__ */ new Set([
6168
+ "update_task_list",
6169
+ "create_task",
6170
+ "mark_task_complete",
6171
+ "handoff_to_agent",
6172
+ "delegate_to_agent",
6173
+ "delegate_task",
6174
+ "get_tool_info",
6175
+ "get_tools",
6176
+ "list_tools",
6177
+ "call_tool",
6178
+ "invoke_tool",
6179
+ "execute_tool",
6180
+ "check_task_status",
6181
+ "assign_task",
6182
+ "update_plan",
6183
+ "check_delegations"
6184
+ ]);
6185
+ function isInternalTool(toolName) {
6186
+ if (!toolName) return false;
6187
+ const lower = toolName.toLowerCase();
6188
+ if (INTERNAL_TOOL_NAMES.has(lower)) return true;
6189
+ for (const internal of INTERNAL_TOOL_NAMES) {
6190
+ if (lower.endsWith(internal) && lower.length > internal.length) {
6191
+ const charBefore = lower[lower.length - internal.length - 1];
6192
+ if (charBefore === "_" || charBefore === ".") return true;
6193
+ }
6194
+ }
6195
+ return false;
6196
+ }
6197
+ function cn10(...classes) {
5511
6198
  return classes.filter(Boolean).join(" ");
5512
6199
  }
5513
6200
  function formatToolName(toolName) {
@@ -5556,7 +6243,7 @@ function formatToolName(toolName) {
5556
6243
  }
5557
6244
  return uniqueWords.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
5558
6245
  }
5559
- function formatDuration(ms) {
6246
+ function formatDuration2(ms) {
5560
6247
  if (ms < 1e3) {
5561
6248
  return `${ms}ms`;
5562
6249
  }
@@ -5577,7 +6264,7 @@ function formatJsonPreview(data, maxLength = 100) {
5577
6264
  return String(data);
5578
6265
  }
5579
6266
  }
5580
- function extractImagesFromResult(result) {
6267
+ function extractImagesFromResult2(result) {
5581
6268
  if (!result) return [];
5582
6269
  let data = result;
5583
6270
  if (typeof result === "string") {
@@ -5612,7 +6299,8 @@ function ToolCallEntry({
5612
6299
  toolCall,
5613
6300
  className,
5614
6301
  showFullJson = true,
5615
- onImageClick
6302
+ onImageClick,
6303
+ compact = false
5616
6304
  }) {
5617
6305
  const [isExpanded, setIsExpanded] = react.useState(false);
5618
6306
  const formattedName = react.useMemo(
@@ -5620,7 +6308,7 @@ function ToolCallEntry({
5620
6308
  [toolCall.name]
5621
6309
  );
5622
6310
  const resultImages = react.useMemo(
5623
- () => toolCall.status === "completed" && toolCall.result ? extractImagesFromResult(toolCall.result) : [],
6311
+ () => toolCall.status === "completed" && toolCall.result ? extractImagesFromResult2(toolCall.result) : [],
5624
6312
  [toolCall.status, toolCall.result]
5625
6313
  );
5626
6314
  const hasImages = resultImages.length > 0;
@@ -5652,10 +6340,26 @@ function ToolCallEntry({
5652
6340
  return "border-gray-200 dark:border-gray-700";
5653
6341
  }
5654
6342
  }, [toolCall.status]);
6343
+ if (compact && (toolCall.status === "completed" || toolCall.status === "failed")) {
6344
+ return /* @__PURE__ */ jsxRuntime.jsxs(
6345
+ "div",
6346
+ {
6347
+ className: cn10(
6348
+ "inline-flex items-center gap-1.5 text-xs text-gray-500 dark:text-gray-400",
6349
+ className
6350
+ ),
6351
+ children: [
6352
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0", children: statusIcon }),
6353
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: formattedName }),
6354
+ toolCall.durationMs !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-400 dark:text-gray-500", children: formatDuration2(toolCall.durationMs) })
6355
+ ]
6356
+ }
6357
+ );
6358
+ }
5655
6359
  return /* @__PURE__ */ jsxRuntime.jsxs(
5656
6360
  "div",
5657
6361
  {
5658
- className: cn7(
6362
+ className: cn10(
5659
6363
  "rounded-lg border text-sm",
5660
6364
  statusColor,
5661
6365
  className
@@ -5671,12 +6375,12 @@ function ToolCallEntry({
5671
6375
  isExpanded ? /* @__PURE__ */ jsxRuntime.jsx(ChevronDownIcon, { className: "h-4 w-4 text-gray-400 flex-shrink-0" }) : /* @__PURE__ */ jsxRuntime.jsx(ChevronRightIcon, { className: "h-4 w-4 text-gray-400 flex-shrink-0" }),
5672
6376
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0", children: statusIcon }),
5673
6377
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-gray-900 dark:text-gray-100 truncate", children: formattedName }),
5674
- toolCall.status === "completed" && toolCall.durationMs !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-auto text-xs text-gray-500 dark:text-gray-400 flex-shrink-0", children: formatDuration(toolCall.durationMs) }),
6378
+ toolCall.status === "completed" && toolCall.durationMs !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-auto text-xs text-gray-500 dark:text-gray-400 flex-shrink-0", children: formatDuration2(toolCall.durationMs) }),
5675
6379
  toolCall.status === "failed" && toolCall.error && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-auto text-xs text-red-600 dark:text-red-400 truncate max-w-[150px]", children: toolCall.error })
5676
6380
  ]
5677
6381
  }
5678
6382
  ),
5679
- hasImages && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 pb-2", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn7(
6383
+ hasImages && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 pb-2", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn10(
5680
6384
  "grid gap-2",
5681
6385
  resultImages.length === 1 ? "grid-cols-1" : "grid-cols-2"
5682
6386
  ), children: resultImages.map((img, idx) => {
@@ -5735,21 +6439,28 @@ function ToolCallEntry({
5735
6439
  }
5736
6440
  );
5737
6441
  }
5738
- function cn8(...classes) {
6442
+ function cn11(...classes) {
5739
6443
  return classes.filter(Boolean).join(" ");
5740
6444
  }
5741
6445
  function ChatMessage({
5742
6446
  message,
5743
6447
  enableMarkdown = true,
5744
6448
  showToolCalls = true,
6449
+ toolCallVerbosity: _toolCallVerbosity,
5745
6450
  className,
5746
6451
  markdownComponents,
5747
6452
  markdownUrlTransform,
5748
6453
  markdownContentTransform,
5749
- onImageClick
6454
+ onImageClick,
6455
+ showThinking = true,
6456
+ showDelegation = true,
6457
+ showImages = true,
6458
+ renderToolCall,
6459
+ variant = "bubble"
5750
6460
  }) {
5751
6461
  const isUser = message.role === "user";
5752
6462
  const isAssistant = message.role === "assistant";
6463
+ const isFlat = variant === "flat";
5753
6464
  const formattedTime = react.useMemo(() => {
5754
6465
  const date = message.timestamp instanceof Date ? message.timestamp : new Date(message.timestamp);
5755
6466
  return date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
@@ -5757,85 +6468,124 @@ function ChatMessage({
5757
6468
  return /* @__PURE__ */ jsxRuntime.jsxs(
5758
6469
  "div",
5759
6470
  {
5760
- className: cn8(
5761
- "flex gap-3 p-4",
5762
- isUser ? "flex-row-reverse" : "flex-row",
6471
+ className: cn11(
6472
+ "cadra-chat-message flex gap-3",
6473
+ isFlat ? "py-5 px-4" : "p-4",
6474
+ // Bubble: user messages right-aligned. Flat: always left-aligned.
6475
+ !isFlat && isUser ? "flex-row-reverse" : "flex-row",
6476
+ // Flat variant: subtle row background for user messages
6477
+ isFlat && isUser && "chat-message-user-row",
5763
6478
  className
5764
6479
  ),
6480
+ style: isFlat && isUser ? {
6481
+ backgroundColor: "var(--chat-user-row-bg, rgba(128, 128, 128, 0.08))"
6482
+ } : void 0,
6483
+ "data-role": message.role,
5765
6484
  children: [
5766
6485
  /* @__PURE__ */ jsxRuntime.jsx(
5767
6486
  "div",
5768
6487
  {
5769
- className: cn8(
5770
- "flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center",
5771
- isUser ? "bg-blue-500 text-white" : "bg-gray-200 dark:bg-gray-700 text-gray-600 dark:text-gray-300"
5772
- ),
6488
+ className: "flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center shadow-sm",
6489
+ style: {
6490
+ backgroundColor: isUser ? "var(--chat-user-avatar-bg, #3b82f6)" : "var(--chat-assistant-avatar-bg, #e5e7eb)",
6491
+ color: isUser ? "var(--chat-user-avatar-text, #fff)" : "var(--chat-assistant-avatar-text, #4b5563)"
6492
+ },
5773
6493
  children: isUser ? /* @__PURE__ */ jsxRuntime.jsx(UserIcon, { className: "h-4 w-4" }) : /* @__PURE__ */ jsxRuntime.jsx(BotIcon, { className: "h-4 w-4" })
5774
6494
  }
5775
6495
  ),
5776
6496
  /* @__PURE__ */ jsxRuntime.jsxs(
5777
6497
  "div",
5778
6498
  {
5779
- className: cn8(
5780
- "flex-1 min-w-0 space-y-2",
5781
- isUser ? "text-right" : "text-left"
6499
+ className: cn11(
6500
+ "flex-1 min-w-0",
6501
+ isFlat ? "pt-0.5" : "space-y-2",
6502
+ !isFlat && isUser ? "text-right" : "text-left"
5782
6503
  ),
5783
6504
  children: [
5784
6505
  /* @__PURE__ */ jsxRuntime.jsxs(
5785
6506
  "div",
5786
6507
  {
5787
- className: cn8(
5788
- "flex items-center gap-2 text-xs text-gray-500 dark:text-gray-400",
5789
- isUser ? "justify-end" : "justify-start"
6508
+ className: cn11(
6509
+ "flex items-center gap-2 text-xs",
6510
+ isFlat ? "mb-1.5" : "",
6511
+ !isFlat && isUser ? "justify-end" : "justify-start"
5790
6512
  ),
6513
+ style: { color: "var(--chat-meta-text, #6b7280)" },
5791
6514
  children: [
5792
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: isUser ? "You" : "Assistant" }),
6515
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", style: { color: "var(--chat-label-text, inherit)" }, children: isUser ? "You" : "Assistant" }),
5793
6516
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: formattedTime }),
5794
6517
  message.isStreaming && /* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner, { className: "h-3 w-3" })
5795
6518
  ]
5796
6519
  }
5797
6520
  ),
5798
- message.thinkingBlocks && message.thinkingBlocks.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: message.thinkingBlocks.map((block) => /* @__PURE__ */ jsxRuntime.jsxs(
5799
- "div",
5800
- {
5801
- className: "bg-purple-50 dark:bg-purple-950/30 border border-purple-200 dark:border-purple-800 rounded-lg p-3 text-sm text-purple-800 dark:text-purple-200",
5802
- children: [
5803
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs font-medium text-purple-600 dark:text-purple-400 mb-1", children: "Thinking..." }),
5804
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "whitespace-pre-wrap", children: block.content })
5805
- ]
5806
- },
5807
- block.id
5808
- )) }),
5809
- showToolCalls && message.toolCalls && message.toolCalls.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: message.toolCalls.map((toolCall) => /* @__PURE__ */ jsxRuntime.jsx(
5810
- ToolCallEntry,
5811
- {
5812
- toolCall,
5813
- onImageClick
5814
- },
5815
- toolCall.id
5816
- )) }),
5817
- message.content && /* @__PURE__ */ jsxRuntime.jsx(
5818
- "div",
6521
+ showThinking && message.thinkingBlocks && message.thinkingBlocks.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(ThinkingBlockList, { blocks: message.thinkingBlocks }),
6522
+ showDelegation && message.delegationEvents && message.delegationEvents.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(DelegationProgressList, { events: message.delegationEvents }),
6523
+ showToolCalls && message.toolCalls && message.toolCalls.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: message.toolCalls.map((toolCall) => {
6524
+ const defaultRender = () => /* @__PURE__ */ jsxRuntime.jsx(
6525
+ ToolCallEntry,
6526
+ {
6527
+ toolCall,
6528
+ onImageClick
6529
+ },
6530
+ toolCall.id
6531
+ );
6532
+ if (renderToolCall) {
6533
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { children: renderToolCall(toolCall, defaultRender) }, toolCall.id);
6534
+ }
6535
+ return defaultRender();
6536
+ }) }),
6537
+ showImages && message.images && message.images.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
6538
+ ImageGallery,
5819
6539
  {
5820
- className: cn8(
5821
- "rounded-lg p-3",
5822
- isUser ? "bg-blue-500 text-white" : "bg-gray-100 dark:bg-gray-800 text-gray-900 dark:text-gray-100"
5823
- ),
5824
- children: isAssistant && enableMarkdown ? /* @__PURE__ */ jsxRuntime.jsx(
5825
- MarkdownContent,
5826
- {
5827
- content: message.content,
5828
- components: markdownComponents,
5829
- urlTransform: markdownUrlTransform,
5830
- contentTransform: markdownContentTransform
5831
- }
5832
- ) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "whitespace-pre-wrap", children: message.content })
6540
+ images: message.images,
6541
+ onImageClick: onImageClick ? (img) => onImageClick({ url: img.url, alt: img.alt, filename: img.filename }) : void 0
5833
6542
  }
5834
6543
  ),
6544
+ message.content && (isFlat ? (
6545
+ // Flat variant: no bubble, just text with theme-aware color
6546
+ /* @__PURE__ */ jsxRuntime.jsx(
6547
+ "div",
6548
+ {
6549
+ className: cn11("text-sm break-words", !(isAssistant && enableMarkdown) && "whitespace-pre-wrap"),
6550
+ style: { color: "var(--chat-content-text, inherit)" },
6551
+ children: isAssistant && enableMarkdown ? /* @__PURE__ */ jsxRuntime.jsx(
6552
+ MarkdownContent,
6553
+ {
6554
+ content: message.content,
6555
+ components: markdownComponents,
6556
+ urlTransform: markdownUrlTransform,
6557
+ contentTransform: markdownContentTransform
6558
+ }
6559
+ ) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "whitespace-pre-wrap", children: message.content })
6560
+ }
6561
+ )
6562
+ ) : (
6563
+ // Bubble variant: colored bubble backgrounds
6564
+ /* @__PURE__ */ jsxRuntime.jsx(
6565
+ "div",
6566
+ {
6567
+ className: "rounded-lg p-3",
6568
+ style: {
6569
+ backgroundColor: isUser ? "var(--chat-user-bg, #3b82f6)" : "var(--chat-assistant-bg, #f3f4f6)",
6570
+ color: isUser ? "var(--chat-user-text, #fff)" : "var(--chat-assistant-text, #111827)"
6571
+ },
6572
+ children: isAssistant && enableMarkdown ? /* @__PURE__ */ jsxRuntime.jsx(
6573
+ MarkdownContent,
6574
+ {
6575
+ content: message.content,
6576
+ components: markdownComponents,
6577
+ urlTransform: markdownUrlTransform,
6578
+ contentTransform: markdownContentTransform
6579
+ }
6580
+ ) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "whitespace-pre-wrap", children: message.content })
6581
+ }
6582
+ )
6583
+ )),
5835
6584
  message.attachments && message.attachments.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: message.attachments.map((attachment) => /* @__PURE__ */ jsxRuntime.jsx(
5836
6585
  "div",
5837
6586
  {
5838
- className: "flex items-center gap-2 bg-gray-100 dark:bg-gray-800 rounded-lg px-3 py-2 text-sm",
6587
+ className: "flex items-center gap-2 rounded-lg px-3 py-2 text-sm",
6588
+ style: { backgroundColor: "var(--chat-assistant-bg, #f3f4f6)" },
5839
6589
  children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate max-w-[150px]", children: attachment.filename })
5840
6590
  },
5841
6591
  attachment.uuid
@@ -5847,7 +6597,7 @@ function ChatMessage({
5847
6597
  }
5848
6598
  );
5849
6599
  }
5850
- function cn9(...classes) {
6600
+ function cn12(...classes) {
5851
6601
  return classes.filter(Boolean).join(" ");
5852
6602
  }
5853
6603
  function MessageList({
@@ -5859,11 +6609,18 @@ function MessageList({
5859
6609
  isLoadingHistory = false,
5860
6610
  enableMarkdown = true,
5861
6611
  showToolCalls = true,
6612
+ toolCallVerbosity,
5862
6613
  className,
5863
6614
  markdownComponents,
5864
6615
  markdownUrlTransform,
5865
6616
  markdownContentTransform,
5866
6617
  onImageClick,
6618
+ showThinking = true,
6619
+ showDelegation = true,
6620
+ showImages = true,
6621
+ renderMessage,
6622
+ renderToolCall,
6623
+ messageVariant = "bubble",
5867
6624
  sendMessage
5868
6625
  }) {
5869
6626
  const scrollRef = react.useRef(null);
@@ -5877,7 +6634,7 @@ function MessageList({
5877
6634
  "div",
5878
6635
  {
5879
6636
  ref: scrollRef,
5880
- className: cn9(
6637
+ className: cn12(
5881
6638
  "flex-1 overflow-y-auto",
5882
6639
  className
5883
6640
  ),
@@ -5888,19 +6645,31 @@ function MessageList({
5888
6645
  ] }) }),
5889
6646
  messages.length === 0 && !isLoading && !isLoadingHistory && (renderWelcome ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: typeof renderWelcome === "function" ? renderWelcome({ sendMessage: sendMessage || (() => {
5890
6647
  }) }) : renderWelcome }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-full p-8", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-center text-gray-500 dark:text-gray-400", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-lg", children: welcomeMessage }) }) })),
5891
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y divide-gray-100 dark:divide-gray-800", children: messages.map((message) => /* @__PURE__ */ jsxRuntime.jsx(
5892
- ChatMessage,
5893
- {
5894
- message,
5895
- enableMarkdown,
5896
- showToolCalls,
5897
- markdownComponents,
5898
- markdownUrlTransform,
5899
- markdownContentTransform,
5900
- onImageClick
5901
- },
5902
- message.id
5903
- )) }),
6648
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y divide-gray-100 dark:divide-gray-800", children: messages.map((message) => {
6649
+ const defaultRender = () => /* @__PURE__ */ jsxRuntime.jsx(
6650
+ ChatMessage,
6651
+ {
6652
+ message,
6653
+ enableMarkdown,
6654
+ showToolCalls,
6655
+ toolCallVerbosity,
6656
+ markdownComponents,
6657
+ markdownUrlTransform,
6658
+ markdownContentTransform,
6659
+ onImageClick,
6660
+ showThinking,
6661
+ showDelegation,
6662
+ showImages,
6663
+ renderToolCall,
6664
+ variant: messageVariant
6665
+ },
6666
+ message.id
6667
+ );
6668
+ if (renderMessage) {
6669
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { children: renderMessage(message, defaultRender) }, message.id);
6670
+ }
6671
+ return defaultRender();
6672
+ }) }),
5904
6673
  isLoading && !isStreaming && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 p-4", children: [
5905
6674
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0 w-8 h-8 rounded-full bg-gray-200 dark:bg-gray-700 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner, { className: "h-4 w-4 text-gray-600 dark:text-gray-300" }) }),
5906
6675
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-gray-500 dark:text-gray-400", children: "Thinking..." })
@@ -5956,13 +6725,28 @@ function AgentChat({
5956
6725
  maxHeight = "600px",
5957
6726
  className,
5958
6727
  theme = "system",
6728
+ layout = "fixed",
5959
6729
  enableAttachments = false,
5960
6730
  enableMarkdown = true,
5961
6731
  showToolCalls = true,
6732
+ toolCallVerbosity,
5962
6733
  markdownComponents,
5963
6734
  markdownUrlTransform,
5964
6735
  markdownContentTransform,
5965
- onImageClick
6736
+ onImageClick,
6737
+ // Extension props
6738
+ hideHeader,
6739
+ renderAboveInput,
6740
+ renderBelowMessages,
6741
+ renderMessage,
6742
+ renderToolCall,
6743
+ messageVariant = "bubble",
6744
+ showThinking = true,
6745
+ showDelegation = true,
6746
+ showImages = true,
6747
+ pollingInterval,
6748
+ pollingEnabled,
6749
+ onDelegation
5966
6750
  }) {
5967
6751
  const {
5968
6752
  messages,
@@ -5989,8 +6773,12 @@ function AgentChat({
5989
6773
  onSessionStart,
5990
6774
  onToolCall,
5991
6775
  onToolResult,
5992
- onClarification
6776
+ onClarification,
6777
+ onDelegation,
6778
+ pollingInterval,
6779
+ pollingEnabled
5993
6780
  });
6781
+ const effectiveVerbosity = showToolCalls === false ? "hidden" : toolCallVerbosity ?? "compact";
5994
6782
  const dropZoneRef = react.useRef(null);
5995
6783
  const attachments = useFileAttachments({
5996
6784
  onUpload: enableAttachments && adapter ? async (_file, meta) => {
@@ -6017,50 +6805,31 @@ function AgentChat({
6017
6805
  },
6018
6806
  [enableAttachments, attachments, sendMessage]
6019
6807
  );
6020
- return /* @__PURE__ */ jsxRuntime.jsxs(ChatContainer, { maxHeight, className, theme, children: [
6021
- enableAttachments ? /* @__PURE__ */ jsxRuntime.jsx(
6022
- FileDropZone,
6023
- {
6024
- ref: dropZoneRef,
6025
- ...attachments.dropZoneProps,
6026
- disabled: isLoading || !!clarification || isLoadingHistory,
6027
- children: /* @__PURE__ */ jsxRuntime.jsx(
6028
- MessageList,
6029
- {
6030
- messages,
6031
- welcomeMessage,
6032
- renderWelcome,
6033
- isLoading,
6034
- isStreaming,
6035
- isLoadingHistory,
6036
- enableMarkdown,
6037
- showToolCalls,
6038
- markdownComponents,
6039
- markdownUrlTransform,
6040
- markdownContentTransform,
6041
- onImageClick,
6042
- sendMessage: handleSend
6043
- }
6044
- )
6045
- }
6046
- ) : /* @__PURE__ */ jsxRuntime.jsx(
6047
- MessageList,
6048
- {
6049
- messages,
6050
- welcomeMessage,
6051
- renderWelcome,
6052
- isLoading,
6053
- isStreaming,
6054
- isLoadingHistory,
6055
- enableMarkdown,
6056
- showToolCalls,
6057
- markdownComponents,
6058
- markdownUrlTransform,
6059
- markdownContentTransform,
6060
- onImageClick,
6061
- sendMessage: handleSend
6062
- }
6063
- ),
6808
+ const messageListProps = {
6809
+ messages,
6810
+ welcomeMessage: hideHeader ? void 0 : welcomeMessage,
6811
+ renderWelcome: hideHeader ? void 0 : renderWelcome,
6812
+ isLoading,
6813
+ isStreaming,
6814
+ isLoadingHistory,
6815
+ enableMarkdown,
6816
+ showToolCalls,
6817
+ toolCallVerbosity: effectiveVerbosity,
6818
+ markdownComponents,
6819
+ markdownUrlTransform,
6820
+ markdownContentTransform,
6821
+ onImageClick,
6822
+ showThinking,
6823
+ showDelegation,
6824
+ showImages,
6825
+ renderMessage,
6826
+ renderToolCall,
6827
+ messageVariant,
6828
+ sendMessage: handleSend
6829
+ };
6830
+ const chatContent = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6831
+ /* @__PURE__ */ jsxRuntime.jsx(MessageList, { ...messageListProps }),
6832
+ renderBelowMessages?.(),
6064
6833
  clarification && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-gray-200 dark:border-gray-700 p-4", children: /* @__PURE__ */ jsxRuntime.jsx(
6065
6834
  AskUserPrompt,
6066
6835
  {
@@ -6070,6 +6839,7 @@ function AgentChat({
6070
6839
  }
6071
6840
  ) }),
6072
6841
  error && /* @__PURE__ */ jsxRuntime.jsx(ErrorBanner, { error, onRetry: retry, onDismiss: clearError }),
6842
+ renderAboveInput?.(),
6073
6843
  /* @__PURE__ */ jsxRuntime.jsx(
6074
6844
  ChatInput,
6075
6845
  {
@@ -6086,8 +6856,17 @@ function AgentChat({
6086
6856
  }
6087
6857
  )
6088
6858
  ] });
6859
+ return /* @__PURE__ */ jsxRuntime.jsx(ChatContainer, { maxHeight, className, theme, layout, children: enableAttachments ? /* @__PURE__ */ jsxRuntime.jsx(
6860
+ FileDropZone,
6861
+ {
6862
+ ref: dropZoneRef,
6863
+ ...attachments.dropZoneProps,
6864
+ disabled: isLoading || !!clarification || isLoadingHistory,
6865
+ children: chatContent
6866
+ }
6867
+ ) : chatContent });
6089
6868
  }
6090
- function cn10(...classes) {
6869
+ function cn13(...classes) {
6091
6870
  return classes.filter(Boolean).join(" ");
6092
6871
  }
6093
6872
  function TodoList({
@@ -6116,7 +6895,7 @@ function TodoList({
6116
6895
  return /* @__PURE__ */ jsxRuntime.jsxs(
6117
6896
  "div",
6118
6897
  {
6119
- className: cn10(
6898
+ className: cn13(
6120
6899
  "rounded-lg border border-gray-200 dark:border-gray-700 overflow-hidden",
6121
6900
  className
6122
6901
  ),
@@ -6124,7 +6903,7 @@ function TodoList({
6124
6903
  /* @__PURE__ */ jsxRuntime.jsxs(
6125
6904
  "div",
6126
6905
  {
6127
- className: cn10(
6906
+ className: cn13(
6128
6907
  "flex items-center gap-2 px-3 py-2 bg-gray-50 dark:bg-gray-800/50",
6129
6908
  collapsible && "cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800"
6130
6909
  ),
@@ -6155,7 +6934,7 @@ function TodoList({
6155
6934
  !isCollapsed && /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "divide-y divide-gray-100 dark:divide-gray-700", children: todos.map((todo, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
6156
6935
  "li",
6157
6936
  {
6158
- className: cn10(
6937
+ className: cn13(
6159
6938
  "px-3 py-2 flex items-start gap-2 text-sm",
6160
6939
  todo.status === "in_progress" && "bg-blue-50/50 dark:bg-blue-950/20",
6161
6940
  todo.status === "completed" && "opacity-60"
@@ -6165,7 +6944,7 @@ function TodoList({
6165
6944
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx(
6166
6945
  "p",
6167
6946
  {
6168
- className: cn10(
6947
+ className: cn13(
6169
6948
  "text-gray-700 dark:text-gray-300",
6170
6949
  todo.status === "completed" && "line-through"
6171
6950
  ),
@@ -6182,39 +6961,6 @@ function TodoList({
6182
6961
  );
6183
6962
  }
6184
6963
 
6185
- // src/chat/index.ts
6186
- var DEPRECATION_WARNING = `
6187
- [@cadraos/sdk/chat] DEPRECATION WARNING
6188
-
6189
- This module is deprecated and will be removed in a future version.
6190
- Please migrate to @cadraos/react for:
6191
- - Simpler setup with CadraCopilot
6192
- - Better security (header-based SSE auth)
6193
- - Scoped CSS that won't conflict with your app
6194
-
6195
- Migration steps:
6196
- 1. npm install @cadraos/react
6197
- 2. import '@cadraos/react/styles.css'
6198
- 3. Replace <AgentChat> with <CadraCopilot> or <CadraChat>
6199
-
6200
- See: https://github.com/cadraos/cadra-sdk/blob/main/packages/react/MIGRATION.md
6201
- `;
6202
- var hasWarned = false;
6203
- function showDeprecationWarning() {
6204
- if (hasWarned) return;
6205
- hasWarned = true;
6206
- if (typeof process !== "undefined" && process.env?.NODE_ENV === "production") {
6207
- return;
6208
- }
6209
- if (typeof window === "undefined") {
6210
- return;
6211
- }
6212
- console.warn(DEPRECATION_WARNING);
6213
- }
6214
- if (typeof window !== "undefined") {
6215
- setTimeout(showDeprecationWarning, 0);
6216
- }
6217
-
6218
6964
  exports.AgentChat = AgentChat;
6219
6965
  exports.AlertCircleIcon = AlertCircleIcon;
6220
6966
  exports.AskUserPrompt = AskUserPrompt;
@@ -6233,13 +6979,18 @@ exports.ClockIcon = ClockIcon;
6233
6979
  exports.CodeIcon = CodeIcon;
6234
6980
  exports.CopyIcon = CopyIcon;
6235
6981
  exports.DatabaseIcon = DatabaseIcon;
6982
+ exports.DelegationProgress = DelegationProgress;
6983
+ exports.DelegationProgressList = DelegationProgressList;
6236
6984
  exports.DownloadIcon = DownloadIcon;
6237
6985
  exports.ExternalLinkIcon = ExternalLinkIcon;
6238
6986
  exports.FileDropZone = FileDropZone;
6239
6987
  exports.FileIcon = FileIcon;
6240
6988
  exports.FileTextIcon = FileTextIcon;
6241
6989
  exports.HelpCircleIcon = HelpCircleIcon;
6990
+ exports.INTERNAL_TOOL_NAMES = INTERNAL_TOOL_NAMES;
6991
+ exports.ImageGallery = ImageGallery;
6242
6992
  exports.ImageIcon = ImageIcon;
6993
+ exports.ImageLightbox = ImageLightbox;
6243
6994
  exports.ImagesIcon = ImagesIcon;
6244
6995
  exports.ListTodoIcon = ListTodoIcon;
6245
6996
  exports.LoadingSpinner = LoadingSpinner;
@@ -6252,6 +7003,8 @@ exports.PaperclipIcon = PaperclipIcon;
6252
7003
  exports.SendIcon = SendIcon;
6253
7004
  exports.SparklesIcon = SparklesIcon;
6254
7005
  exports.StopCircleIcon = StopCircleIcon;
7006
+ exports.ThinkingBlock = ThinkingBlock;
7007
+ exports.ThinkingBlockList = ThinkingBlockList;
6255
7008
  exports.TodoList = TodoList;
6256
7009
  exports.ToolCallEntry = ToolCallEntry;
6257
7010
  exports.UserIcon = UserIcon;
@@ -6260,6 +7013,7 @@ exports.ZoomInIcon = ZoomInIcon;
6260
7013
  exports.ZoomOutIcon = ZoomOutIcon;
6261
7014
  exports.compressImage = compressImage;
6262
7015
  exports.createDefaultAdapter = createDefaultAdapter;
7016
+ exports.isInternalTool = isInternalTool;
6263
7017
  exports.useAgentChat = useAgentChat;
6264
7018
  exports.useChatConfig = useChatConfig;
6265
7019
  exports.useChatConfigOptional = useChatConfigOptional;