@paymanai/payman-typescript-ask-sdk 2.0.3 → 4.0.0

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.js CHANGED
@@ -14,6 +14,13 @@ function generateId() {
14
14
  }
15
15
 
16
16
  // src/utils/streamingClient.ts
17
+ function yieldAfterProgressEvent(event) {
18
+ const t = event.eventType;
19
+ if (t === "RUN_IN_PROGRESS" || t === "INTENT_PROGRESS" || t === "AGGREGATOR_THINKING_CONT" || t === "INTENT_THINKING_CONT" || t === "THINKING_DELTA") {
20
+ return new Promise((resolve) => setTimeout(resolve, 0));
21
+ }
22
+ return Promise.resolve();
23
+ }
17
24
  function parseJSONBuffer(buffer) {
18
25
  const events = [];
19
26
  let braceCount = 0;
@@ -90,6 +97,7 @@ async function streamWorkflowEvents(url, body, headers, options = {}) {
90
97
  const { events: events2 } = parseJSONBuffer(buffer);
91
98
  for (const event of events2) {
92
99
  onEvent?.(event);
100
+ await yieldAfterProgressEvent(event);
93
101
  }
94
102
  }
95
103
  break;
@@ -98,6 +106,7 @@ async function streamWorkflowEvents(url, body, headers, options = {}) {
98
106
  const { events, remaining } = parseJSONBuffer(buffer);
99
107
  for (const event of events) {
100
108
  onEvent?.(event);
109
+ await yieldAfterProgressEvent(event);
101
110
  }
102
111
  buffer = remaining;
103
112
  }
@@ -110,7 +119,38 @@ async function streamWorkflowEvents(url, body, headers, options = {}) {
110
119
  }
111
120
  }
112
121
 
113
- // src/utils/eventProcessor.ts
122
+ // src/utils/stageLabels.ts
123
+ var STAGE_LABELS = {
124
+ sanitizer: "Checking your request",
125
+ analyzer: "Understanding what you're asking",
126
+ prefetcher: "Gathering context",
127
+ planner: "Planning how to handle this",
128
+ execution: "Working on it",
129
+ formatter: "Writing the response"
130
+ };
131
+ function stageLabel(stage) {
132
+ const label = STAGE_LABELS[stage];
133
+ if (label) return label;
134
+ const pretty = stage.replace(/[_-]/g, " ");
135
+ return `Running ${pretty}`;
136
+ }
137
+
138
+ // src/utils/v2EventProcessor.ts
139
+ function isBlandStatus(message) {
140
+ if (!message) return true;
141
+ const normalized = message.trim().toLowerCase().replace(/[…\.]+$/, "").trim();
142
+ return BLAND_STATUS_LABELS.has(normalized);
143
+ }
144
+ var BLAND_STATUS_LABELS = /* @__PURE__ */ new Set([
145
+ "executing",
146
+ "working on it",
147
+ "thinking",
148
+ "processing",
149
+ "reviewing your request",
150
+ "composing response",
151
+ "checking your request",
152
+ "polishing the response"
153
+ ]);
114
154
  function getEventMessage(event) {
115
155
  if (event.message?.trim()) {
116
156
  return event.message.trim();
@@ -120,54 +160,104 @@ function getEventMessage(event) {
120
160
  }
121
161
  const eventType = event.eventType;
122
162
  switch (eventType) {
123
- case "STARTED":
124
- case "WORKFLOW_STARTED":
125
- return "Starting workflow...";
126
- case "ORCHESTRATOR_THINKING":
127
- return "Planning execution strategy...";
128
- case "ORCHESTRATOR_COMPLETED":
129
- return "Planning complete";
130
- case "INTENT_STARTED":
131
- return event.workerName ? `${event.workerName} started` : "Processing intent...";
132
- case "INTENT_PROGRESS":
133
- return event.workerName ? `${event.workerName} in progress` : "Thinking...";
134
- case "INTENT_COMPLETED":
135
- return event.workerName ? `${event.workerName} completed` : "Intent completed";
136
- case "AGGREGATOR_THINKING":
137
- return "Combining results...";
138
- case "AGGREGATOR_COMPLETED":
139
- return "Results combined";
140
- case "COMPLETED":
141
- case "WORKFLOW_COMPLETED":
142
- return "Workflow completed successfully";
143
- case "ERROR":
144
- case "WORKFLOW_ERROR":
145
- case "INTENT_ERROR":
146
- return event.errorMessage || "An error occurred";
147
- case "USER_ACTION_REQUIRED":
148
- return "Waiting for verification...";
149
- case "USER_ACTION_SUCCESS":
150
- return "Verification approved";
151
- case "USER_ACTION_EXPIRED":
152
- return "Verification expired";
153
- case "USER_ACTION_INVALID":
154
- return "Invalid code. Please try again.";
155
- case "USER_ACTION_REJECTED":
156
- return "Verification cancelled";
157
- case "USER_ACTION_RESENT":
158
- return "Verification code resent";
159
- case "USER_ACTION_FAILED":
160
- return "Verification failed";
161
- case "INTENT_THINKING":
162
- return event.workerName ? `${event.workerName} thinking...` : "Thinking...";
163
- case "INTENT_THINKING_CONT":
164
- return event.message || "";
163
+ case "RUN_STARTED":
164
+ return "Starting agent run...";
165
+ case "TOOL_CALL_STARTED": {
166
+ const description = typeof event.description === "string" ? event.description.trim() : "";
167
+ if (description) return description;
168
+ const toolName = typeof event.toolName === "string" ? event.toolName : "";
169
+ return toolName ? `Calling ${toolName}...` : "Calling tool...";
170
+ }
171
+ case "TOOL_CALL_COMPLETED": {
172
+ const description = typeof event.description === "string" ? event.description.trim() : "";
173
+ if (description) return description;
174
+ const toolName = typeof event.toolName === "string" ? event.toolName : "";
175
+ return toolName ? `${toolName} completed` : "Tool call completed";
176
+ }
177
+ case "RUN_IN_PROGRESS":
178
+ return event.partialText || "Thinking...";
179
+ case "RUN_COMPLETED":
180
+ return "Agent run completed";
181
+ case "RUN_FAILED":
182
+ return event.errorMessage || "Agent run failed";
165
183
  case "KEEP_ALIVE":
166
- return "";
184
+ return event.description || "";
185
+ case "THINKING_DELTA":
186
+ return event.text || "";
167
187
  default:
168
188
  return eventType;
169
189
  }
170
190
  }
191
+ function extractResponseContent(response) {
192
+ if (typeof response === "string") {
193
+ return response;
194
+ }
195
+ if (typeof response === "object" && response !== null) {
196
+ const resp = response;
197
+ if ("text" in resp && typeof resp.text === "string") {
198
+ return resp.text;
199
+ }
200
+ if ("content" in resp && typeof resp.content === "string") {
201
+ return resp.content;
202
+ }
203
+ if ("message" in resp && typeof resp.message === "string") {
204
+ return resp.message;
205
+ }
206
+ if ("answer" in resp && typeof resp.answer === "string") {
207
+ return resp.answer;
208
+ }
209
+ return JSON.stringify(response);
210
+ }
211
+ return "";
212
+ }
213
+ function normalizeEvent(event) {
214
+ const type = event.eventType;
215
+ switch (type) {
216
+ case "RUN_STARTED":
217
+ return { ...event, eventType: "WORKFLOW_STARTED" };
218
+ case "TOOL_CALL_STARTED": {
219
+ const toolName = typeof event.toolName === "string" ? event.toolName : void 0;
220
+ const description = typeof event.description === "string" ? event.description.trim() : "";
221
+ return {
222
+ ...event,
223
+ eventType: "INTENT_STARTED",
224
+ workerName: toolName ?? event.workerName,
225
+ message: description || event.message
226
+ };
227
+ }
228
+ case "TOOL_CALL_COMPLETED": {
229
+ const toolName = typeof event.toolName === "string" ? event.toolName : void 0;
230
+ const description = typeof event.description === "string" ? event.description.trim() : "";
231
+ return {
232
+ ...event,
233
+ eventType: "INTENT_COMPLETED",
234
+ workerName: toolName ?? event.workerName,
235
+ message: description || event.message
236
+ };
237
+ }
238
+ case "RUN_IN_PROGRESS":
239
+ return {
240
+ ...event,
241
+ eventType: "INTENT_PROGRESS",
242
+ message: event.partialText ?? event.message
243
+ };
244
+ case "RUN_COMPLETED":
245
+ return {
246
+ ...event,
247
+ eventType: "WORKFLOW_COMPLETED",
248
+ // state machine reads event.response for the final content
249
+ response: event.response ?? event.message
250
+ };
251
+ case "RUN_FAILED":
252
+ return {
253
+ ...event,
254
+ eventType: "WORKFLOW_ERROR",
255
+ errorMessage: event.errorMessage ?? event.message
256
+ };
257
+ default:
258
+ return event;
259
+ }
260
+ }
171
261
  function isUserActionPrompt(text) {
172
262
  return /\benter\b.+\b(code|otp)\b/i.test(text) || /\b(authorization|verification)\s+code\b/i.test(text) || /\bsent\s+to\s+your\b/i.test(text);
173
263
  }
@@ -201,300 +291,6 @@ function workingPhaseDetailForDisplay(raw) {
201
291
  }
202
292
  return t;
203
293
  }
204
- function extractResponseContent(response) {
205
- if (typeof response === "string") {
206
- return response;
207
- }
208
- if (typeof response === "object" && response !== null) {
209
- const resp = response;
210
- if ("text" in resp && typeof resp.text === "string") {
211
- return resp.text;
212
- }
213
- if ("content" in resp && typeof resp.content === "string") {
214
- return resp.content;
215
- }
216
- if ("message" in resp && typeof resp.message === "string") {
217
- return resp.message;
218
- }
219
- if ("answer" in resp && typeof resp.answer === "string") {
220
- return resp.answer;
221
- }
222
- return JSON.stringify(response);
223
- }
224
- return "";
225
- }
226
-
227
- // src/utils/messageStateManager.ts
228
- function buildFormattedThinking(steps, allThinkingText) {
229
- const parts = [];
230
- const safeSteps = steps ?? [];
231
- const cleanAll = allThinkingText.replace(/^\s+/, "");
232
- if (cleanAll) {
233
- const firstStepWithThinking = safeSteps.find(
234
- (s) => s.thinkingText && s.thinkingText.trim()
235
- );
236
- if (!firstStepWithThinking) {
237
- parts.push("**Preflight**");
238
- parts.push(cleanAll);
239
- } else {
240
- const stepText = firstStepWithThinking.thinkingText.trim();
241
- const idx = cleanAll.indexOf(stepText);
242
- if (idx > 0) {
243
- const orphaned = cleanAll.substring(0, idx).replace(/\s+$/, "");
244
- if (orphaned) {
245
- parts.push("**Preflight**");
246
- parts.push(orphaned);
247
- }
248
- }
249
- }
250
- }
251
- for (const step of safeSteps) {
252
- switch (step.eventType) {
253
- case "ORCHESTRATOR_THINKING":
254
- parts.push("**Planning**");
255
- if (step.message) parts.push(step.message);
256
- break;
257
- case "WORKING": {
258
- const detail = workingPhaseDetailForDisplay(step.message || "");
259
- parts.push("**Working**");
260
- if (detail) parts.push(detail);
261
- break;
262
- }
263
- case "INTENT_STARTED": {
264
- let label = step.message || "Processing";
265
- const started = label.match(/^(.+?)\s+started$/i);
266
- const progress = label.match(/^(.+?)\s+in progress$/i);
267
- if (started) label = started[1];
268
- else if (progress) label = progress[1];
269
- parts.push(`**${label}**`);
270
- if (step.thinkingText) parts.push(step.thinkingText);
271
- break;
272
- }
273
- case "INTENT_PROGRESS": {
274
- if (step.thinkingText) parts.push(step.thinkingText);
275
- else if (step.message) parts.push(step.message);
276
- break;
277
- }
278
- case "AGGREGATOR_THINKING":
279
- parts.push("**Finalizing**");
280
- if (step.message) parts.push(step.message);
281
- break;
282
- case "USER_ACTION_REQUIRED":
283
- parts.push("**Verification Required**");
284
- if (step.message) {
285
- parts.push(getUserActionDisplayMessage(step.eventType, step.message));
286
- }
287
- break;
288
- case "USER_ACTION_SUCCESS":
289
- parts.push(`\u2713 ${getUserActionDisplayMessage(step.eventType, step.message)}`);
290
- break;
291
- case "USER_ACTION_REJECTED":
292
- parts.push(getUserActionDisplayMessage(step.eventType, step.message));
293
- break;
294
- case "USER_ACTION_EXPIRED":
295
- parts.push(`\u2717 ${getUserActionDisplayMessage(step.eventType, step.message)}`);
296
- break;
297
- case "USER_ACTION_INVALID":
298
- parts.push(`\u2717 ${getUserActionDisplayMessage(step.eventType, step.message)}`);
299
- break;
300
- case "USER_ACTION_RESENT":
301
- parts.push(getUserActionDisplayMessage(step.eventType, step.message));
302
- break;
303
- case "USER_ACTION_FAILED":
304
- parts.push(`\u2717 ${getUserActionDisplayMessage(step.eventType, step.message)}`);
305
- break;
306
- }
307
- }
308
- return parts.length > 0 ? parts.join("\n") : allThinkingText;
309
- }
310
- function createCancelledMessageUpdate(steps, currentMessage) {
311
- const updatedSteps = steps.map((step) => {
312
- if (step.status === "in_progress") {
313
- return { ...step, status: "pending" };
314
- }
315
- return step;
316
- });
317
- return {
318
- isStreaming: false,
319
- isCancelled: true,
320
- steps: updatedSteps,
321
- currentExecutingStepId: void 0,
322
- // Preserve currentMessage so UI can show it with X icon
323
- currentMessage: currentMessage || "Thinking..."
324
- };
325
- }
326
-
327
- // src/utils/requestBuilder.ts
328
- function buildRequestBody(config, userMessage, sessionId) {
329
- const owner = config.session?.owner;
330
- const sessionAttributes = owner?.attributes && Object.keys(owner.attributes).length > 0 ? owner.attributes : void 0;
331
- return {
332
- workflowName: config.workflow.name,
333
- userInput: userMessage,
334
- sessionId,
335
- sessionOwnerId: owner?.id || "",
336
- sessionOwnerLabel: owner?.name || "",
337
- sessionAttributes,
338
- options: {
339
- clientTimezone: Intl.DateTimeFormat().resolvedOptions().timeZone
340
- }
341
- };
342
- }
343
- function getStageParamName(config) {
344
- return config.api.stageQueryParam ?? "stage";
345
- }
346
- function getStage(config) {
347
- return config.workflow.stage ?? "DEV";
348
- }
349
- function buildStreamingUrl(config) {
350
- const endpoint = config.api.streamEndpoint || "/api/workflows/ask/stream";
351
- const queryParams = new URLSearchParams({
352
- [getStageParamName(config)]: getStage(config)
353
- });
354
- if (config.workflow.version !== void 0) {
355
- queryParams.append("workflowVersion", String(config.workflow.version));
356
- }
357
- return `${config.api.baseUrl}${endpoint}?${queryParams.toString()}`;
358
- }
359
- function deriveBasePath(config) {
360
- const endpoint = config.api.streamEndpoint || "/api/workflows/ask/stream";
361
- const [endpointPath] = endpoint.split("?");
362
- const normalized = endpointPath.replace(/\/+$/, "");
363
- return normalized.endsWith("/stream") ? normalized.slice(0, -"/stream".length) : normalized;
364
- }
365
- function buildUserActionUrl(config, userActionId, action) {
366
- const basePath = deriveBasePath(config);
367
- const encodedUserActionId = encodeURIComponent(userActionId);
368
- return `${config.api.baseUrl}${basePath}/user-action/${encodedUserActionId}/${action}`;
369
- }
370
- function buildResolveImagesUrl(config) {
371
- if (config.api.resolveImagesEndpoint) {
372
- return `${config.api.baseUrl}${config.api.resolveImagesEndpoint}`;
373
- }
374
- return `${config.api.baseUrl}${deriveBasePath(config)}/resolve-image-urls`;
375
- }
376
- function buildRequestHeaders(config) {
377
- const headers = { ...config.api.headers };
378
- if (config.api.authToken) {
379
- headers.Authorization = `Bearer ${config.api.authToken}`;
380
- }
381
- return headers;
382
- }
383
- function buildScopeKey(config) {
384
- return [
385
- config.session?.userId ?? "",
386
- config.workflow.id ?? "",
387
- config.workflow.version ?? "",
388
- config.workflow.stage ?? ""
389
- ].join("|");
390
- }
391
-
392
- // src/utils/userActionClient.ts
393
- async function sendUserActionRequest(config, userActionId, action, data) {
394
- const url = buildUserActionUrl(config, userActionId, action);
395
- const baseHeaders = buildRequestHeaders(config);
396
- const hasBody = data !== void 0;
397
- const headers = hasBody ? { "Content-Type": "application/json", ...baseHeaders } : baseHeaders;
398
- const response = await fetch(url, {
399
- method: "POST",
400
- headers,
401
- body: hasBody ? JSON.stringify(data) : void 0
402
- });
403
- if (!response.ok) {
404
- const errorText = await response.text();
405
- throw new Error(`HTTP ${response.status}: ${errorText}`);
406
- }
407
- return await response.json();
408
- }
409
- async function submitUserAction(config, userActionId, data) {
410
- return sendUserActionRequest(config, userActionId, "submit", data);
411
- }
412
- async function cancelUserAction(config, userActionId) {
413
- return sendUserActionRequest(config, userActionId, "cancel");
414
- }
415
- async function resendUserAction(config, userActionId) {
416
- return sendUserActionRequest(config, userActionId, "resend");
417
- }
418
-
419
- // src/utils/chatStore.ts
420
- var memoryStore = /* @__PURE__ */ new Map();
421
- var chatStore = {
422
- get(key) {
423
- return memoryStore.get(key) ?? [];
424
- },
425
- set(key, messages) {
426
- memoryStore.set(key, messages);
427
- },
428
- delete(key) {
429
- memoryStore.delete(key);
430
- }
431
- };
432
-
433
- // src/utils/activeStreamStore.ts
434
- var streams = /* @__PURE__ */ new Map();
435
- var activeStreamStore = {
436
- has(key) {
437
- return streams.has(key);
438
- },
439
- get(key) {
440
- const entry = streams.get(key);
441
- if (!entry) return null;
442
- return { messages: entry.messages, isWaiting: entry.isWaiting };
443
- },
444
- // Called before startStream — registers the controller and initial messages
445
- start(key, abortController, initialMessages) {
446
- const existing = streams.get(key);
447
- streams.set(key, {
448
- messages: initialMessages,
449
- isWaiting: true,
450
- abortController,
451
- listeners: existing?.listeners ?? /* @__PURE__ */ new Set()
452
- });
453
- },
454
- // Called by the stream on every event — applies the same updater pattern React uses
455
- applyMessages(key, updater) {
456
- const entry = streams.get(key);
457
- if (!entry) return;
458
- const next = typeof updater === "function" ? updater(entry.messages) : updater;
459
- entry.messages = next;
460
- entry.listeners.forEach((l) => l(next, entry.isWaiting));
461
- },
462
- setWaiting(key, waiting) {
463
- const entry = streams.get(key);
464
- if (!entry) return;
465
- entry.isWaiting = waiting;
466
- entry.listeners.forEach((l) => l(entry.messages, waiting));
467
- },
468
- // Called when stream completes — persists to chatStore and cleans up
469
- complete(key) {
470
- const entry = streams.get(key);
471
- if (!entry) return;
472
- entry.isWaiting = false;
473
- entry.listeners.forEach((l) => l(entry.messages, false));
474
- const toSave = entry.messages.filter((m) => !m.isStreaming);
475
- if (toSave.length > 0) chatStore.set(key, toSave);
476
- streams.delete(key);
477
- },
478
- // Subscribe — returns unsubscribe fn. Component calls this on mount, cleanup on unmount.
479
- subscribe(key, listener) {
480
- const entry = streams.get(key);
481
- if (!entry) return () => {
482
- };
483
- entry.listeners.add(listener);
484
- return () => {
485
- streams.get(key)?.listeners.delete(listener);
486
- };
487
- },
488
- // Explicit user cancel — aborts the controller and removes the entry
489
- abort(key) {
490
- const entry = streams.get(key);
491
- if (!entry) return;
492
- entry.abortController.abort();
493
- streams.delete(key);
494
- }
495
- };
496
-
497
- // src/utils/v2EventProcessor.ts
498
294
  function getEventText(event, field) {
499
295
  const value = event[field];
500
296
  return typeof value === "string" ? value.trim() : "";
@@ -518,6 +314,16 @@ function addThinkingLine(state, header, detail) {
518
314
  function appendThinkingText(state, text) {
519
315
  state.formattedThinkingText += text;
520
316
  }
317
+ function updateExecutionStageMessage(state, msg) {
318
+ if (!msg) return;
319
+ for (let i = state.steps.length - 1; i >= 0; i--) {
320
+ const s = state.steps[i];
321
+ if (s.eventType === "STAGE_STARTED" && (s.stage === "executor" || s.stage === "execution") && s.status === "in_progress") {
322
+ s.message = msg;
323
+ return;
324
+ }
325
+ }
326
+ }
521
327
  function completeLastInProgressStep(steps) {
522
328
  for (let i = steps.length - 1; i >= 0; i--) {
523
329
  if (steps[i].status === "in_progress") {
@@ -545,11 +351,31 @@ function createInitialV2State() {
545
351
  currentExecutingStepId: void 0
546
352
  };
547
353
  }
548
- function processStreamEventV2(event, state) {
354
+ function processStreamEventV2(rawEvent, state) {
355
+ const event = normalizeEvent(rawEvent);
549
356
  const eventType = event.eventType;
550
357
  if (typeof eventType === "string" && eventType.toUpperCase() === "KEEP_ALIVE") {
551
358
  if (event.executionId) state.executionId = event.executionId;
552
359
  if (event.sessionId) state.sessionId = event.sessionId;
360
+ const description = typeof event.description === "string" ? event.description : "";
361
+ if (description) {
362
+ for (let i = state.steps.length - 1; i >= 0; i--) {
363
+ if (state.steps[i].status === "in_progress") {
364
+ state.steps[i].message = description;
365
+ break;
366
+ }
367
+ }
368
+ }
369
+ return state;
370
+ }
371
+ if (typeof eventType === "string" && eventType.toUpperCase() === "THINKING_DELTA") {
372
+ const text = typeof event.text === "string" ? event.text : "";
373
+ if (text) {
374
+ appendThinkingText(state, text);
375
+ }
376
+ if (event.executionId) state.executionId = event.executionId;
377
+ if (event.sessionId) state.sessionId = event.sessionId;
378
+ state.lastEventType = "THINKING_DELTA";
553
379
  return state;
554
380
  }
555
381
  if (event.executionId) state.executionId = event.executionId;
@@ -560,6 +386,16 @@ function processStreamEventV2(event, state) {
560
386
  case "STARTED":
561
387
  state.lastEventType = eventType;
562
388
  break;
389
+ case "INTENT_PROGRESS": {
390
+ const rawMessage = typeof event.message === "string" ? event.message : "";
391
+ const rawPartial = typeof event.partialText === "string" ? event.partialText : "";
392
+ const delta = rawMessage || rawPartial;
393
+ if (delta.length > 0) {
394
+ state.finalResponse += delta;
395
+ }
396
+ state.lastEventType = eventType;
397
+ break;
398
+ }
563
399
  case "INTENT_THINKING": {
564
400
  const worker = getEventText(event, "workerName") || "Worker";
565
401
  const msg = getEventText(event, "message") || "Thinking...";
@@ -661,6 +497,7 @@ function processStreamEventV2(event, state) {
661
497
  elapsedMs: event.elapsedMs
662
498
  });
663
499
  state.currentExecutingStepId = stepId;
500
+ updateExecutionStageMessage(state, message);
664
501
  state.lastEventType = eventType;
665
502
  break;
666
503
  }
@@ -703,6 +540,10 @@ function processStreamEventV2(event, state) {
703
540
  }
704
541
  case "WORKFLOW_COMPLETED":
705
542
  case "COMPLETED": {
543
+ const totalTime = Number(event.totalTimeMs);
544
+ if (Number.isFinite(totalTime) && totalTime > 0) {
545
+ state.totalElapsedMs = totalTime;
546
+ }
706
547
  let content = extractResponseContent(event.response);
707
548
  const trace = event.trace && typeof event.trace === "object" ? event.trace : null;
708
549
  if (!content && trace?.workflowMsg && typeof trace.workflowMsg === "string") {
@@ -715,7 +556,9 @@ function processStreamEventV2(event, state) {
715
556
  }
716
557
  if (content) {
717
558
  state.finalResponse = content;
718
- state.finalData = event.response ?? event.trace;
559
+ if (event.trace && typeof event.trace === "object") {
560
+ state.finalData = event.trace;
561
+ }
719
562
  state.hasError = false;
720
563
  state.errorMessage = "";
721
564
  } else {
@@ -897,12 +740,369 @@ function processStreamEventV2(event, state) {
897
740
  state.lastEventType = eventType;
898
741
  break;
899
742
  }
900
- default:
901
- state.lastEventType = eventType;
902
- break;
743
+ // ---- K2 pipeline stage lifecycle events ----
744
+ //
745
+ // The k2-server playground streaming API emits
746
+ // STAGE_STARTED / STAGE_COMPLETED / STAGE_FAILED /
747
+ // STAGE_SKIPPED around each pipeline stage so the UI can
748
+ // show real progress (sanitizer → analyzer → planner → …)
749
+ // instead of a static placeholder. Each STAGE_STARTED
750
+ // pushes an in-progress step with a user-facing label; the
751
+ // matching STAGE_COMPLETED/FAILED closes it WITHOUT
752
+ // rewriting the label — a terse "completed" flash between
753
+ // stages was more noise than signal. STAGE_SKIPPED removes
754
+ // the just-opened step entirely (skipping is expected on
755
+ // DIRECT_RESPONSE short-circuits).
756
+ //
757
+ // Finding the matching step uses `stepId` directly rather
758
+ // than comparing labels — the processor remembers which id
759
+ // it minted for the latest open STAGE_STARTED and the
760
+ // closing events look it up from state.currentExecutingStepId.
761
+ case "STAGE_STARTED": {
762
+ const stage = getEventText(event, "stage");
763
+ if (!stage) {
764
+ state.lastEventType = eventType;
765
+ break;
766
+ }
767
+ const serverMessage = getEventText(event, "message");
768
+ let initialMessage = serverMessage || stageLabel(stage);
769
+ if (stage === "executor" || stage === "execution") {
770
+ for (let i = state.steps.length - 1; i >= 0; i--) {
771
+ const s = state.steps[i];
772
+ if (s.eventType === "STAGE_STARTED" && s.stage === "analyzer" && s.status === "completed" && s.message) {
773
+ initialMessage = s.message;
774
+ break;
775
+ }
776
+ }
777
+ }
778
+ const stepId = `stage-${stage}-${state.stepCounter++}`;
779
+ state.steps.push({
780
+ id: stepId,
781
+ eventType,
782
+ message: initialMessage,
783
+ status: "in_progress",
784
+ timestamp: Date.now(),
785
+ stage
786
+ });
787
+ state.currentExecutingStepId = stepId;
788
+ state.lastEventType = eventType;
789
+ break;
790
+ }
791
+ case "STAGE_COMPLETED": {
792
+ const stage = getEventText(event, "stage");
793
+ if (!stage) {
794
+ state.lastEventType = eventType;
795
+ break;
796
+ }
797
+ const serverMessage = getEventText(event, "message");
798
+ for (let i = state.steps.length - 1; i >= 0; i--) {
799
+ const s = state.steps[i];
800
+ if (s.eventType === "STAGE_STARTED" && s.stage === stage && s.status === "in_progress") {
801
+ if (serverMessage) s.message = serverMessage;
802
+ s.status = "completed";
803
+ const durationMs = Number(event.durationMs);
804
+ if (Number.isFinite(durationMs)) s.elapsedMs = durationMs;
805
+ if (s.id === state.currentExecutingStepId) {
806
+ state.currentExecutingStepId = void 0;
807
+ }
808
+ break;
809
+ }
810
+ }
811
+ state.lastEventType = eventType;
812
+ break;
813
+ }
814
+ case "STAGE_FAILED": {
815
+ const stage = getEventText(event, "stage");
816
+ if (!stage) {
817
+ state.lastEventType = eventType;
818
+ break;
819
+ }
820
+ const serverMessage = getEventText(event, "message");
821
+ for (let i = state.steps.length - 1; i >= 0; i--) {
822
+ const s = state.steps[i];
823
+ if (s.eventType === "STAGE_STARTED" && s.stage === stage && s.status === "in_progress") {
824
+ if (serverMessage) s.message = serverMessage;
825
+ s.status = "error";
826
+ const durationMs = Number(event.durationMs);
827
+ if (Number.isFinite(durationMs)) s.elapsedMs = durationMs;
828
+ if (s.id === state.currentExecutingStepId) {
829
+ state.currentExecutingStepId = void 0;
830
+ }
831
+ break;
832
+ }
833
+ }
834
+ state.lastEventType = eventType;
835
+ break;
836
+ }
837
+ case "STAGE_SKIPPED": {
838
+ const stage = getEventText(event, "stage");
839
+ if (!stage) {
840
+ state.lastEventType = eventType;
841
+ break;
842
+ }
843
+ for (let i = state.steps.length - 1; i >= 0; i--) {
844
+ const s = state.steps[i];
845
+ if (s.eventType === "STAGE_STARTED" && s.stage === stage && s.status === "in_progress") {
846
+ if (s.id === state.currentExecutingStepId) {
847
+ state.currentExecutingStepId = void 0;
848
+ }
849
+ s.status = "skipped";
850
+ break;
851
+ }
852
+ }
853
+ state.lastEventType = eventType;
854
+ break;
855
+ }
856
+ default:
857
+ state.lastEventType = eventType;
858
+ break;
859
+ }
860
+ return state;
861
+ }
862
+
863
+ // src/utils/messageStateManager.ts
864
+ function buildFormattedThinking(steps, allThinkingText) {
865
+ const parts = [];
866
+ const safeSteps = steps ?? [];
867
+ const cleanAll = allThinkingText.replace(/^\s+/, "");
868
+ if (cleanAll) {
869
+ const firstStepWithThinking = safeSteps.find(
870
+ (s) => s.thinkingText && s.thinkingText.trim()
871
+ );
872
+ if (!firstStepWithThinking) {
873
+ parts.push("**Preflight**");
874
+ parts.push(cleanAll);
875
+ } else {
876
+ const stepText = firstStepWithThinking.thinkingText.trim();
877
+ const idx = cleanAll.indexOf(stepText);
878
+ if (idx > 0) {
879
+ const orphaned = cleanAll.substring(0, idx).replace(/\s+$/, "");
880
+ if (orphaned) {
881
+ parts.push("**Preflight**");
882
+ parts.push(orphaned);
883
+ }
884
+ }
885
+ }
886
+ }
887
+ for (const step of safeSteps) {
888
+ switch (step.eventType) {
889
+ case "STAGE_STARTED": {
890
+ if (step.message) parts.push(`**${step.message}**`);
891
+ break;
892
+ }
893
+ case "ORCHESTRATOR_THINKING":
894
+ parts.push("**Planning**");
895
+ if (step.message) parts.push(step.message);
896
+ break;
897
+ case "INTENT_STARTED": {
898
+ let label = step.message || "Processing";
899
+ const started = label.match(/^(.+?)\s+started$/i);
900
+ const progress = label.match(/^(.+?)\s+in progress$/i);
901
+ if (started) label = started[1];
902
+ else if (progress) label = progress[1];
903
+ parts.push(`**${label}**`);
904
+ if (step.thinkingText) parts.push(step.thinkingText);
905
+ break;
906
+ }
907
+ case "INTENT_PROGRESS": {
908
+ if (step.thinkingText) parts.push(step.thinkingText);
909
+ else if (step.message) parts.push(step.message);
910
+ break;
911
+ }
912
+ case "AGGREGATOR_THINKING":
913
+ parts.push("**Finalizing**");
914
+ if (step.message) parts.push(step.message);
915
+ break;
916
+ case "USER_ACTION_REQUIRED":
917
+ parts.push("**Verification Required**");
918
+ if (step.message) parts.push(step.message);
919
+ break;
920
+ case "USER_ACTION_SUCCESS":
921
+ parts.push(`\u2713 ${step.message || "Verification successful"}`);
922
+ break;
923
+ case "USER_ACTION_REJECTED":
924
+ parts.push(`\u2717 ${step.message || "Verification rejected"}`);
925
+ break;
926
+ case "USER_ACTION_EXPIRED":
927
+ parts.push(`\u2717 ${step.message || "Verification expired"}`);
928
+ break;
929
+ case "USER_ACTION_FAILED":
930
+ parts.push(`\u2717 ${step.message || "Verification failed"}`);
931
+ break;
932
+ }
933
+ }
934
+ return parts.length > 0 ? parts.join("\n") : allThinkingText;
935
+ }
936
+ function createCancelledMessageUpdate(steps, currentMessage) {
937
+ const updatedSteps = steps.map((step) => {
938
+ if (step.status === "in_progress") {
939
+ return { ...step, status: "pending" };
940
+ }
941
+ return step;
942
+ });
943
+ return {
944
+ isStreaming: false,
945
+ isCancelled: true,
946
+ steps: updatedSteps,
947
+ currentExecutingStepId: void 0,
948
+ // Preserve currentMessage so UI can show it with X icon
949
+ currentMessage: currentMessage || "Thinking..."
950
+ };
951
+ }
952
+
953
+ // src/utils/requestBuilder.ts
954
+ var DEFAULT_STREAM_ENDPOINT = "/api/playground/ask/stream";
955
+ function buildRequestBody(config, userMessage, sessionId, options) {
956
+ const sessionOwner = config.sessionParams;
957
+ const sessionAttributes = sessionOwner?.attributes && Object.keys(sessionOwner.attributes).length > 0 ? sessionOwner.attributes : void 0;
958
+ return {
959
+ agentId: config.agentId,
960
+ userInput: userMessage,
961
+ sessionId,
962
+ sessionOwnerLabel: sessionOwner?.name || void 0,
963
+ sessionAttributes,
964
+ analysisMode: options?.analysisMode
965
+ };
966
+ }
967
+ function buildStreamingUrl(config) {
968
+ const endpoint = config.api.streamEndpoint || DEFAULT_STREAM_ENDPOINT;
969
+ const stage = config.stage || "DEV";
970
+ const stageParamName = config.stageQueryParam ?? "stage";
971
+ const queryParams = new URLSearchParams({ [stageParamName]: stage });
972
+ return `${config.api.baseUrl}${endpoint}?${queryParams.toString()}`;
973
+ }
974
+ function buildUserActionUrl(config, userActionId, action) {
975
+ const endpoint = config.api.streamEndpoint || DEFAULT_STREAM_ENDPOINT;
976
+ const [endpointPath] = endpoint.split("?");
977
+ const normalizedEndpointPath = endpointPath.replace(/\/+$/, "");
978
+ const basePath = normalizedEndpointPath.endsWith("/stream") ? normalizedEndpointPath.slice(0, -"/stream".length) : normalizedEndpointPath;
979
+ const encodedUserActionId = encodeURIComponent(userActionId);
980
+ return `${config.api.baseUrl}${basePath}/user-action/${encodedUserActionId}/${action}`;
981
+ }
982
+ function buildResolveImagesUrl(config) {
983
+ if (config.api.resolveImagesEndpoint) {
984
+ return `${config.api.baseUrl}${config.api.resolveImagesEndpoint}`;
903
985
  }
904
- return state;
986
+ const streamEndpoint = config.api.streamEndpoint || DEFAULT_STREAM_ENDPOINT;
987
+ const [endpointPath] = streamEndpoint.split("?");
988
+ const normalizedEndpointPath = endpointPath.replace(/\/+$/, "");
989
+ const basePath = normalizedEndpointPath.endsWith("/stream") ? normalizedEndpointPath.slice(0, -"/stream".length) : normalizedEndpointPath;
990
+ return `${config.api.baseUrl}${basePath}/resolve-image-urls`;
991
+ }
992
+ function buildRequestHeaders(config) {
993
+ const headers = {
994
+ ...config.api.headers
995
+ };
996
+ if (config.api.authToken) {
997
+ headers.Authorization = `Bearer ${config.api.authToken}`;
998
+ }
999
+ return headers;
1000
+ }
1001
+
1002
+ // src/utils/userActionClient.ts
1003
+ async function sendUserActionRequest(config, userActionId, action, data) {
1004
+ const url = buildUserActionUrl(config, userActionId, action);
1005
+ const baseHeaders = buildRequestHeaders(config);
1006
+ const hasBody = data !== void 0;
1007
+ const headers = hasBody ? { "Content-Type": "application/json", ...baseHeaders } : baseHeaders;
1008
+ const response = await fetch(url, {
1009
+ method: "POST",
1010
+ headers,
1011
+ body: hasBody ? JSON.stringify(data) : void 0
1012
+ });
1013
+ if (!response.ok) {
1014
+ const errorText = await response.text();
1015
+ throw new Error(`HTTP ${response.status}: ${errorText}`);
1016
+ }
1017
+ return await response.json();
1018
+ }
1019
+ async function submitUserAction(config, userActionId, data) {
1020
+ return sendUserActionRequest(config, userActionId, "submit", data);
1021
+ }
1022
+ async function cancelUserAction(config, userActionId) {
1023
+ return sendUserActionRequest(config, userActionId, "cancel");
905
1024
  }
1025
+ async function resendUserAction(config, userActionId) {
1026
+ return sendUserActionRequest(config, userActionId, "resend");
1027
+ }
1028
+
1029
+ // src/utils/chatStore.ts
1030
+ var memoryStore = /* @__PURE__ */ new Map();
1031
+ var chatStore = {
1032
+ get(key) {
1033
+ return memoryStore.get(key) ?? [];
1034
+ },
1035
+ set(key, messages) {
1036
+ memoryStore.set(key, messages);
1037
+ },
1038
+ delete(key) {
1039
+ memoryStore.delete(key);
1040
+ }
1041
+ };
1042
+
1043
+ // src/utils/activeStreamStore.ts
1044
+ var streams = /* @__PURE__ */ new Map();
1045
+ var activeStreamStore = {
1046
+ has(key) {
1047
+ return streams.has(key);
1048
+ },
1049
+ get(key) {
1050
+ const entry = streams.get(key);
1051
+ if (!entry) return null;
1052
+ return { messages: entry.messages, isWaiting: entry.isWaiting };
1053
+ },
1054
+ // Called before startStream — registers the controller and initial messages
1055
+ start(key, abortController, initialMessages) {
1056
+ const existing = streams.get(key);
1057
+ streams.set(key, {
1058
+ messages: initialMessages,
1059
+ isWaiting: true,
1060
+ abortController,
1061
+ listeners: existing?.listeners ?? /* @__PURE__ */ new Set()
1062
+ });
1063
+ },
1064
+ // Called by the stream on every event — applies the same updater pattern React uses
1065
+ applyMessages(key, updater) {
1066
+ const entry = streams.get(key);
1067
+ if (!entry) return;
1068
+ const next = typeof updater === "function" ? updater(entry.messages) : updater;
1069
+ entry.messages = next;
1070
+ entry.listeners.forEach((l) => l(next, entry.isWaiting));
1071
+ },
1072
+ setWaiting(key, waiting) {
1073
+ const entry = streams.get(key);
1074
+ if (!entry) return;
1075
+ entry.isWaiting = waiting;
1076
+ entry.listeners.forEach((l) => l(entry.messages, waiting));
1077
+ },
1078
+ // Called when stream completes — persists to chatStore and cleans up
1079
+ complete(key) {
1080
+ const entry = streams.get(key);
1081
+ if (!entry) return;
1082
+ entry.isWaiting = false;
1083
+ entry.listeners.forEach((l) => l(entry.messages, false));
1084
+ const toSave = entry.messages.filter((m) => !m.isStreaming);
1085
+ if (toSave.length > 0) chatStore.set(key, toSave);
1086
+ streams.delete(key);
1087
+ },
1088
+ // Subscribe — returns unsubscribe fn. Component calls this on mount, cleanup on unmount.
1089
+ subscribe(key, listener) {
1090
+ const entry = streams.get(key);
1091
+ if (!entry) return () => {
1092
+ };
1093
+ entry.listeners.add(listener);
1094
+ return () => {
1095
+ streams.get(key)?.listeners.delete(listener);
1096
+ };
1097
+ },
1098
+ // Explicit user cancel — aborts the controller and removes the entry
1099
+ abort(key) {
1100
+ const entry = streams.get(key);
1101
+ if (!entry) return;
1102
+ entry.abortController.abort();
1103
+ streams.delete(key);
1104
+ }
1105
+ };
906
1106
 
907
1107
  // src/utils/ragImageResolver.ts
908
1108
  var RAG_IMAGE_REGEX = /\/api\/rag\/chunks\/[^"'\s]+\/image/;
@@ -963,12 +1163,11 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
963
1163
  const callbacksRef = react.useRef(callbacks);
964
1164
  callbacksRef.current = callbacks;
965
1165
  const startStream = react.useCallback(
966
- async (userMessage, streamingId, sessionId, externalAbortController) => {
1166
+ async (userMessage, streamingId, sessionId, externalAbortController, options) => {
967
1167
  abortControllerRef.current?.abort();
968
1168
  const abortController = externalAbortController ?? new AbortController();
969
1169
  abortControllerRef.current = abortController;
970
1170
  const state = createInitialV2State();
971
- const streamStartedAt = Date.now();
972
1171
  const updateMessage = (update) => {
973
1172
  if (abortController.signal.aborted) return;
974
1173
  setMessages(
@@ -978,7 +1177,12 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
978
1177
  );
979
1178
  };
980
1179
  const currentConfig = configRef.current;
981
- const requestBody = buildRequestBody(currentConfig, userMessage, sessionId);
1180
+ const requestBody = buildRequestBody(
1181
+ currentConfig,
1182
+ userMessage,
1183
+ sessionId,
1184
+ options
1185
+ );
982
1186
  const url = buildStreamingUrl(currentConfig);
983
1187
  const headers = buildRequestHeaders(currentConfig);
984
1188
  try {
@@ -986,11 +1190,6 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
986
1190
  signal: abortController.signal,
987
1191
  onEvent: (event) => {
988
1192
  if (abortController.signal.aborted) return;
989
- if (typeof event.eventType === "string" && event.eventType.toUpperCase() === "KEEP_ALIVE") {
990
- if (event.executionId) state.executionId = event.executionId;
991
- if (event.sessionId) state.sessionId = event.sessionId;
992
- return;
993
- }
994
1193
  processStreamEventV2(event, state);
995
1194
  const eventType = event.eventType;
996
1195
  if (eventType === "USER_ACTION_REQUIRED" && state.userActionRequest) {
@@ -1004,7 +1203,18 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
1004
1203
  }
1005
1204
  const activeStep = state.steps.find((s) => s.id === state.currentExecutingStepId);
1006
1205
  const lastInProgressStep = [...state.steps].reverse().find((s) => s.status === "in_progress");
1007
- const currentMessage = activeStep?.message || lastInProgressStep?.message || getEventMessage(event);
1206
+ const useful = (m) => m && !isBlandStatus(m) ? m : void 0;
1207
+ const latestUsefulStep = [...state.steps].reverse().find(
1208
+ (s) => s.message && !isBlandStatus(s.message)
1209
+ );
1210
+ const currentMessage = useful(activeStep?.message) ?? useful(lastInProgressStep?.message) ?? latestUsefulStep?.message ?? useful(getEventMessage(event)) ?? // Last-resort: every candidate is bland (very first event,
1211
+ // nothing useful seen yet). Render the bland label so the
1212
+ // bubble isn't blank.
1213
+ activeStep?.message ?? lastInProgressStep?.message ?? getEventMessage(event);
1214
+ if (currentMessage) {
1215
+ callbacksRef.current.onStatusMessage?.(currentMessage);
1216
+ }
1217
+ callbacksRef.current.onStepsUpdate?.([...state.steps]);
1008
1218
  if (state.hasError) {
1009
1219
  updateMessage({
1010
1220
  streamingContent: FRIENDLY_ERROR_MESSAGE,
@@ -1020,7 +1230,7 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
1020
1230
  });
1021
1231
  } else {
1022
1232
  updateMessage({
1023
- streamingContent: "",
1233
+ streamingContent: state.finalResponse,
1024
1234
  content: "",
1025
1235
  currentMessage,
1026
1236
  streamProgress: "processing",
@@ -1037,6 +1247,7 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
1037
1247
  },
1038
1248
  onError: (error) => {
1039
1249
  setIsWaitingForResponse(false);
1250
+ callbacksRef.current.onStatusMessage?.(null);
1040
1251
  if (error.name !== "AbortError") {
1041
1252
  callbacksRef.current.onError?.(error);
1042
1253
  }
@@ -1074,6 +1285,8 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
1074
1285
  },
1075
1286
  onComplete: () => {
1076
1287
  setIsWaitingForResponse(false);
1288
+ callbacksRef.current.onStatusMessage?.(null);
1289
+ callbacksRef.current.onStepsUpdate?.([]);
1077
1290
  if (state.userActionPending) {
1078
1291
  state.userActionPending = false;
1079
1292
  state.userActionRequest = void 0;
@@ -1097,14 +1310,18 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
1097
1310
  isError: state.hasError,
1098
1311
  errorDetails: state.hasError ? state.errorMessage : void 0,
1099
1312
  executionId: state.executionId,
1100
- tracingData: state.finalData,
1313
+ // Defensive: tracingData must be an object (or undefined)
1314
+ // so the JSON viewer doesn't char-iterate a string. The
1315
+ // event processor already drops bare strings; this is
1316
+ // the last stop before the message leaves the SDK.
1317
+ tracingData: state.finalData != null && typeof state.finalData === "object" ? state.finalData : void 0,
1101
1318
  steps: state.hasError ? [] : [...state.steps],
1102
1319
  isCancelled: false,
1103
1320
  currentExecutingStepId: void 0,
1104
1321
  userActionResult: state.userActionResult,
1105
1322
  formattedThinkingText: state.hasError ? void 0 : state.formattedThinkingText || void 0,
1106
1323
  isResolvingImages: needsImageResolve,
1107
- thinkingDurationSec: state.hasError ? void 0 : Math.max(0, Math.round((Date.now() - streamStartedAt) / 1e3))
1324
+ totalElapsedMs: state.hasError ? void 0 : state.totalElapsedMs
1108
1325
  };
1109
1326
  setMessages(
1110
1327
  (prev) => prev.map(
@@ -1189,199 +1406,45 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
1189
1406
  };
1190
1407
  }
1191
1408
 
1192
- // src/utils/workflowUsersClient.ts
1193
- var DEFAULT_SESSION_PAGE_SIZE = 20;
1194
- var DEFAULT_CONVERSATION_PAGE_SIZE = 50;
1195
- function getStageParamName2(config) {
1196
- return config.api.stageQueryParam ?? "stage";
1197
- }
1198
- function requireOwnerId(config) {
1199
- const ownerId = config.session?.owner?.id;
1200
- if (!ownerId) {
1201
- throw new Error(
1202
- "workflowUsersClient: session.owner.id is required to call this endpoint."
1203
- );
1204
- }
1205
- return ownerId;
1206
- }
1207
- function requireWorkflowName(config) {
1208
- const workflowName = config.workflow.name;
1209
- if (!workflowName) {
1210
- throw new Error(
1211
- "workflowUsersClient: workflow.name is required to call this endpoint."
1212
- );
1213
- }
1214
- return workflowName;
1215
- }
1216
- function requireWorkflowId(config) {
1217
- const workflowId = config.workflow.id;
1218
- if (!workflowId) {
1219
- throw new Error(
1220
- "workflowUsersClient: workflow.id is required to call this endpoint."
1221
- );
1222
- }
1223
- return workflowId;
1224
- }
1225
- function isPlaygroundYaakAuth(config) {
1226
- if (config.api.authToken) return false;
1227
- const headers = config.api.headers;
1228
- if (!headers) return false;
1229
- for (const key of Object.keys(headers)) {
1230
- const lower = key.toLowerCase();
1231
- if (lower === "yaak-api-key" || lower === "x-yaak-api-key") return true;
1232
- }
1233
- return false;
1234
- }
1235
- async function fetchJson(url, headers, signal) {
1236
- const response = await fetch(url, {
1237
- method: "GET",
1238
- headers,
1239
- signal
1240
- });
1241
- if (!response.ok) {
1242
- const errorText = await response.text();
1243
- throw new Error(`HTTP ${response.status}: ${errorText}`);
1244
- }
1245
- return await response.json();
1246
- }
1247
- async function listSessions(config, opts = {}) {
1248
- const ownerId = requireOwnerId(config);
1249
- const useYaakEndpoint = isPlaygroundYaakAuth(config);
1250
- const params = new URLSearchParams({
1251
- page: String(opts.page ?? 0),
1252
- size: String(opts.size ?? DEFAULT_SESSION_PAGE_SIZE)
1253
- });
1254
- if (useYaakEndpoint) {
1255
- params.set("workflowUserId", ownerId);
1256
- params.set("workflowName", requireWorkflowName(config));
1257
- } else {
1258
- params.set("workflowId", requireWorkflowId(config));
1259
- }
1260
- if (config.workflow.stage) {
1261
- params.set(getStageParamName2(config), config.workflow.stage);
1262
- }
1263
- const url = useYaakEndpoint ? `${config.api.baseUrl}/api/workflows/ask/sessions?${params.toString()}` : `${config.api.baseUrl}/api/workflow-users/${encodeURIComponent(
1264
- ownerId
1265
- )}/sessions?${params.toString()}`;
1266
- return fetchJson(
1267
- url,
1268
- buildRequestHeaders(config),
1269
- opts.signal
1270
- );
1271
- }
1272
- async function listConversations(config, opts) {
1273
- const ownerId = requireOwnerId(config);
1274
- const useYaakEndpoint = isPlaygroundYaakAuth(config);
1275
- const params = new URLSearchParams({
1276
- sessionId: opts.sessionId,
1277
- page: String(opts.page ?? 0),
1278
- size: String(opts.size ?? DEFAULT_CONVERSATION_PAGE_SIZE)
1279
- });
1280
- if (useYaakEndpoint) {
1281
- params.set("workflowUserId", ownerId);
1282
- params.set("workflowName", requireWorkflowName(config));
1283
- }
1284
- if (config.workflow.stage) {
1285
- params.set(getStageParamName2(config), config.workflow.stage);
1286
- }
1287
- const url = useYaakEndpoint ? `${config.api.baseUrl}/api/workflows/ask/conversations?${params.toString()}` : `${config.api.baseUrl}/api/workflow-users/${encodeURIComponent(
1288
- ownerId
1289
- )}/conversations?${params.toString()}`;
1290
- return fetchJson(
1291
- url,
1292
- buildRequestHeaders(config),
1293
- opts.signal
1294
- );
1295
- }
1296
-
1297
1409
  // src/hooks/useChatV2.ts
1298
- function conversationEntryToMessages(entry, sessionId) {
1299
- return [
1300
- {
1301
- id: `history-user-${entry.executionId}`,
1302
- sessionId,
1303
- role: "user",
1304
- content: entry.query,
1305
- timestamp: entry.createdAt,
1306
- isHistorical: true
1307
- },
1308
- {
1309
- id: `history-assistant-${entry.executionId}`,
1310
- sessionId,
1311
- role: "assistant",
1312
- content: entry.response,
1313
- timestamp: entry.createdAt,
1314
- executionId: entry.executionId,
1315
- isHistorical: true
1316
- }
1317
- ];
1318
- }
1319
- function streamKeyFor(scopeKey, sessionId) {
1320
- return `${scopeKey}|sid:${sessionId ?? ""}`;
1321
- }
1322
1410
  function useChatV2(config, callbacks = {}) {
1323
- const scopeKey = react.useMemo(() => buildScopeKey(config), [
1324
- config.session?.userId,
1325
- config.workflow?.id,
1326
- config.workflow?.version,
1327
- config.workflow?.stage
1328
- ]);
1329
- const initialSessionId = chatStore.get(scopeKey).find((m) => m.sessionId)?.sessionId ?? config.session?.initialId ?? void 0;
1330
1411
  const [messages, setMessages] = react.useState(() => {
1331
- const stored = chatStore.get(scopeKey);
1332
- if (stored.length > 0) return stored;
1333
- return config.session?.initialMessages ?? [];
1412
+ if (config.userId) return chatStore.get(config.userId);
1413
+ return config.initialMessages ?? [];
1334
1414
  });
1335
1415
  const [isWaitingForResponse, setIsWaitingForResponse] = react.useState(false);
1336
- const [loadingSessionId, setLoadingSessionId] = react.useState(void 0);
1337
- const [currentSessionId, setCurrentSessionId] = react.useState(initialSessionId);
1338
- const sessionIdRef = react.useRef(initialSessionId);
1339
- const prevScopeKeyRef = react.useRef(scopeKey);
1340
- const activeStreamSessionRef = react.useRef(void 0);
1416
+ const sessionIdRef = react.useRef(
1417
+ config.userId ? chatStore.get(config.userId).find((m) => m.sessionId)?.sessionId ?? config.initialSessionId ?? void 0 : config.initialSessionId ?? void 0
1418
+ );
1419
+ const prevUserIdRef = react.useRef(config.userId);
1341
1420
  const callbacksRef = react.useRef(callbacks);
1342
1421
  callbacksRef.current = callbacks;
1343
1422
  const configRef = react.useRef(config);
1344
1423
  configRef.current = config;
1345
- const scopeKeyRef = react.useRef(scopeKey);
1346
- scopeKeyRef.current = scopeKey;
1347
1424
  const messagesRef = react.useRef(messages);
1348
1425
  messagesRef.current = messages;
1349
1426
  const storeAwareSetMessages = react.useCallback(
1350
1427
  (updater) => {
1351
- const scope = scopeKeyRef.current;
1352
- const streamSid = activeStreamSessionRef.current;
1353
- if (streamSid !== void 0) {
1354
- const streamKey = streamKeyFor(scope, streamSid);
1355
- if (activeStreamStore.has(streamKey)) {
1356
- activeStreamStore.applyMessages(
1357
- streamKey,
1358
- updater
1359
- );
1360
- }
1361
- if (sessionIdRef.current === streamSid) {
1362
- setMessages(updater);
1363
- }
1364
- return;
1428
+ const { userId } = configRef.current;
1429
+ if (userId && activeStreamStore.has(userId)) {
1430
+ activeStreamStore.applyMessages(userId, updater);
1365
1431
  }
1366
1432
  setMessages(updater);
1367
1433
  },
1434
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1368
1435
  []
1369
1436
  );
1370
- const storeAwareSetIsWaiting = react.useCallback((waiting) => {
1371
- const scope = scopeKeyRef.current;
1372
- const streamSid = activeStreamSessionRef.current;
1373
- if (streamSid !== void 0) {
1374
- const streamKey = streamKeyFor(scope, streamSid);
1375
- if (activeStreamStore.has(streamKey)) {
1376
- activeStreamStore.setWaiting(streamKey, waiting);
1437
+ const storeAwareSetIsWaiting = react.useCallback(
1438
+ (waiting) => {
1439
+ const { userId } = configRef.current;
1440
+ if (userId && activeStreamStore.has(userId)) {
1441
+ activeStreamStore.setWaiting(userId, waiting);
1377
1442
  }
1378
- if (sessionIdRef.current === streamSid) {
1379
- setIsWaitingForResponse(waiting);
1380
- }
1381
- return;
1382
- }
1383
- setIsWaitingForResponse(waiting);
1384
- }, []);
1443
+ setIsWaitingForResponse(waiting);
1444
+ },
1445
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1446
+ []
1447
+ );
1385
1448
  const [userActionState, setUserActionState] = react.useState({
1386
1449
  request: null,
1387
1450
  result: null,
@@ -1389,43 +1452,38 @@ function useChatV2(config, callbacks = {}) {
1389
1452
  });
1390
1453
  const userActionStateRef = react.useRef(userActionState);
1391
1454
  userActionStateRef.current = userActionState;
1392
- const wrappedCallbacks = react.useMemo(
1393
- () => ({
1394
- ...callbacksRef.current,
1395
- onMessageSent: (message) => callbacksRef.current.onMessageSent?.(message),
1396
- onStreamStart: () => callbacksRef.current.onStreamStart?.(),
1397
- onStreamComplete: (message) => callbacksRef.current.onStreamComplete?.(message),
1398
- onError: (error) => callbacksRef.current.onError?.(error),
1399
- onExecutionTraceClick: (data) => callbacksRef.current.onExecutionTraceClick?.(data),
1400
- onSessionIdChange: (sessionId) => callbacksRef.current.onSessionIdChange?.(sessionId),
1401
- onUserActionRequired: (request) => {
1402
- setUserActionState((prev) => ({ ...prev, request, result: null }));
1403
- callbacksRef.current.onUserActionRequired?.(request);
1404
- },
1405
- onUserActionEvent: (eventType, message) => {
1406
- switch (eventType) {
1407
- case "USER_ACTION_SUCCESS":
1408
- setUserActionState((prev) => ({ ...prev, request: null, result: "approved" }));
1409
- break;
1410
- case "USER_ACTION_REJECTED":
1411
- setUserActionState((prev) => ({ ...prev, request: null, result: "rejected" }));
1412
- break;
1413
- case "USER_ACTION_EXPIRED":
1414
- case "USER_ACTION_FAILED":
1415
- setUserActionState((prev) => ({ ...prev, request: null }));
1416
- break;
1417
- case "USER_ACTION_INVALID":
1418
- setUserActionState((prev) => ({
1419
- ...prev,
1420
- clearOtpTrigger: prev.clearOtpTrigger + 1
1421
- }));
1422
- break;
1423
- }
1424
- callbacksRef.current.onUserActionEvent?.(eventType, message);
1455
+ const wrappedCallbacks = react.useMemo(() => ({
1456
+ ...callbacksRef.current,
1457
+ onMessageSent: (message) => callbacksRef.current.onMessageSent?.(message),
1458
+ onStreamStart: () => callbacksRef.current.onStreamStart?.(),
1459
+ onStreamComplete: (message) => callbacksRef.current.onStreamComplete?.(message),
1460
+ onError: (error) => callbacksRef.current.onError?.(error),
1461
+ onExecutionTraceClick: (data) => callbacksRef.current.onExecutionTraceClick?.(data),
1462
+ onSessionIdChange: (sessionId) => callbacksRef.current.onSessionIdChange?.(sessionId),
1463
+ onUserActionRequired: (request) => {
1464
+ setUserActionState((prev) => ({ ...prev, request, result: null }));
1465
+ callbacksRef.current.onUserActionRequired?.(request);
1466
+ },
1467
+ onUserActionEvent: (eventType, message) => {
1468
+ switch (eventType) {
1469
+ case "USER_ACTION_SUCCESS":
1470
+ setUserActionState((prev) => ({ ...prev, request: null, result: "approved" }));
1471
+ break;
1472
+ case "USER_ACTION_REJECTED":
1473
+ setUserActionState((prev) => ({ ...prev, request: null, result: "rejected" }));
1474
+ break;
1475
+ case "USER_ACTION_EXPIRED":
1476
+ case "USER_ACTION_FAILED":
1477
+ setUserActionState((prev) => ({ ...prev, request: null }));
1478
+ break;
1479
+ case "USER_ACTION_INVALID":
1480
+ setUserActionState((prev) => ({ ...prev, clearOtpTrigger: prev.clearOtpTrigger + 1 }));
1481
+ break;
1425
1482
  }
1426
- }),
1427
- []
1428
- );
1483
+ callbacksRef.current.onUserActionEvent?.(eventType, message);
1484
+ }
1485
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1486
+ }), []);
1429
1487
  const { startStream, cancelStream: cancelStreamManager, abortControllerRef } = useStreamManagerV2(
1430
1488
  config,
1431
1489
  wrappedCallbacks,
@@ -1433,12 +1491,10 @@ function useChatV2(config, callbacks = {}) {
1433
1491
  storeAwareSetIsWaiting
1434
1492
  );
1435
1493
  const sendMessage = react.useCallback(
1436
- async (userMessage) => {
1494
+ async (userMessage, options) => {
1437
1495
  if (!userMessage.trim()) return;
1438
- const autoGen = configRef.current.session?.autoGenerateId;
1439
- if (!sessionIdRef.current && autoGen !== false) {
1496
+ if (!sessionIdRef.current && configRef.current.autoGenerateSessionId !== false) {
1440
1497
  sessionIdRef.current = generateId();
1441
- setCurrentSessionId(sessionIdRef.current);
1442
1498
  callbacksRef.current.onSessionIdChange?.(sessionIdRef.current);
1443
1499
  }
1444
1500
  const userMessageId = `user-${Date.now()}`;
@@ -1470,40 +1526,39 @@ function useChatV2(config, callbacks = {}) {
1470
1526
  };
1471
1527
  setMessages((prev) => [...prev, streamingMsg]);
1472
1528
  const abortController = new AbortController();
1473
- const scope = scopeKeyRef.current;
1474
- const streamSessionId = sessionIdRef.current;
1475
- const streamKey = streamKeyFor(scope, streamSessionId);
1476
- activeStreamSessionRef.current = streamSessionId;
1477
- const initialMessages = [...messagesRef.current, userMsg, streamingMsg];
1478
- activeStreamStore.start(streamKey, abortController, initialMessages);
1529
+ const { userId } = configRef.current;
1530
+ if (userId) {
1531
+ const initialMessages = [...messagesRef.current, userMsg, streamingMsg];
1532
+ activeStreamStore.start(userId, abortController, initialMessages);
1533
+ }
1479
1534
  const newSessionId = await startStream(
1480
1535
  userMessage,
1481
1536
  streamingId,
1482
- streamSessionId,
1483
- abortController
1537
+ sessionIdRef.current,
1538
+ abortController,
1539
+ options
1484
1540
  );
1485
- activeStreamStore.complete(streamKey);
1486
- activeStreamSessionRef.current = void 0;
1487
- if (!abortController.signal.aborted && newSessionId && newSessionId !== streamSessionId && sessionIdRef.current === streamSessionId) {
1541
+ if (userId) {
1542
+ activeStreamStore.complete(userId);
1543
+ }
1544
+ if (!abortController.signal.aborted && newSessionId && newSessionId !== sessionIdRef.current) {
1488
1545
  sessionIdRef.current = newSessionId;
1489
- setCurrentSessionId(newSessionId);
1490
1546
  }
1491
1547
  },
1492
1548
  [startStream]
1493
1549
  );
1494
1550
  const clearMessages = react.useCallback(() => {
1495
- chatStore.delete(scopeKeyRef.current);
1551
+ if (configRef.current.userId) {
1552
+ chatStore.delete(configRef.current.userId);
1553
+ }
1496
1554
  setMessages([]);
1497
1555
  }, []);
1498
1556
  const prependMessages = react.useCallback((msgs) => {
1499
1557
  setMessages((prev) => [...msgs, ...prev]);
1500
1558
  }, []);
1501
1559
  const cancelStream = react.useCallback(() => {
1502
- const scope = scopeKeyRef.current;
1503
- const viewSid = sessionIdRef.current;
1504
- const viewStreamKey = streamKeyFor(scope, viewSid);
1505
- if (activeStreamStore.has(viewStreamKey)) {
1506
- activeStreamStore.abort(viewStreamKey);
1560
+ if (configRef.current.userId) {
1561
+ activeStreamStore.abort(configRef.current.userId);
1507
1562
  }
1508
1563
  cancelStreamManager();
1509
1564
  setIsWaitingForResponse(false);
@@ -1513,7 +1568,10 @@ function useChatV2(config, callbacks = {}) {
1513
1568
  if (msg.isStreaming) {
1514
1569
  return {
1515
1570
  ...msg,
1516
- ...createCancelledMessageUpdate(msg.steps || [], msg.currentMessage)
1571
+ ...createCancelledMessageUpdate(
1572
+ msg.steps || [],
1573
+ msg.currentMessage
1574
+ )
1517
1575
  };
1518
1576
  }
1519
1577
  return msg;
@@ -1521,37 +1579,39 @@ function useChatV2(config, callbacks = {}) {
1521
1579
  );
1522
1580
  }, [cancelStreamManager]);
1523
1581
  const resetSession = react.useCallback(() => {
1524
- const scope = scopeKeyRef.current;
1525
- const viewSid = sessionIdRef.current;
1526
- const viewStreamKey = streamKeyFor(scope, viewSid);
1527
- if (activeStreamStore.has(viewStreamKey)) {
1528
- activeStreamStore.abort(viewStreamKey);
1582
+ if (configRef.current.userId) {
1583
+ activeStreamStore.abort(configRef.current.userId);
1584
+ chatStore.delete(configRef.current.userId);
1529
1585
  }
1530
- chatStore.delete(scope);
1531
1586
  setMessages([]);
1532
1587
  sessionIdRef.current = void 0;
1533
- setCurrentSessionId(void 0);
1534
- activeStreamSessionRef.current = void 0;
1535
1588
  abortControllerRef.current?.abort();
1536
1589
  setIsWaitingForResponse(false);
1537
1590
  setUserActionState({ request: null, result: null, clearOtpTrigger: 0 });
1538
1591
  }, []);
1539
- const getSessionId = react.useCallback(() => sessionIdRef.current, []);
1540
- const getMessages = react.useCallback(() => messages, [messages]);
1541
- const approveUserAction = react.useCallback(async (otp) => {
1542
- const request = userActionStateRef.current.request;
1543
- if (!request) return;
1544
- try {
1545
- await submitUserAction(configRef.current, request.userActionId, { otp });
1546
- } catch (error) {
1547
- setUserActionState((prev) => ({
1548
- ...prev,
1549
- clearOtpTrigger: prev.clearOtpTrigger + 1
1550
- }));
1551
- callbacksRef.current.onError?.(error);
1552
- throw error;
1553
- }
1592
+ const getSessionId = react.useCallback(() => {
1593
+ return sessionIdRef.current;
1554
1594
  }, []);
1595
+ const getMessages = react.useCallback(() => {
1596
+ return messages;
1597
+ }, [messages]);
1598
+ const approveUserAction = react.useCallback(
1599
+ async (otp) => {
1600
+ const request = userActionStateRef.current.request;
1601
+ if (!request) return;
1602
+ try {
1603
+ await submitUserAction(configRef.current, request.userActionId, { otp });
1604
+ } catch (error) {
1605
+ setUserActionState((prev) => ({
1606
+ ...prev,
1607
+ clearOtpTrigger: prev.clearOtpTrigger + 1
1608
+ }));
1609
+ callbacksRef.current.onError?.(error);
1610
+ throw error;
1611
+ }
1612
+ },
1613
+ []
1614
+ );
1555
1615
  const rejectUserAction = react.useCallback(async () => {
1556
1616
  const request = userActionStateRef.current.request;
1557
1617
  if (!request) return;
@@ -1585,91 +1645,43 @@ function useChatV2(config, callbacks = {}) {
1585
1645
  throw error;
1586
1646
  }
1587
1647
  }, []);
1588
- const inFlightLoadRef = react.useRef(null);
1589
- const loadingSessionIdRef = react.useRef(void 0);
1590
- loadingSessionIdRef.current = loadingSessionId;
1591
- const loadSession = react.useCallback(async (sessionId) => {
1592
- const inFlight = inFlightLoadRef.current;
1593
- if (inFlight && inFlight.sessionId === sessionId) {
1594
- return inFlight.promise;
1595
- }
1596
- if (sessionIdRef.current === sessionId && loadingSessionIdRef.current !== sessionId) {
1597
- return;
1598
- }
1599
- const run = async () => {
1600
- const scope = scopeKeyRef.current;
1601
- setUserActionState({ request: null, result: null, clearOtpTrigger: 0 });
1602
- sessionIdRef.current = sessionId;
1603
- setCurrentSessionId(sessionId);
1604
- callbacksRef.current.onSessionIdChange?.(sessionId);
1605
- const streamKey = streamKeyFor(scope, sessionId);
1606
- const active = activeStreamStore.get(streamKey);
1607
- if (active) {
1608
- setMessages(active.messages);
1609
- setIsWaitingForResponse(active.isWaiting);
1610
- setLoadingSessionId(void 0);
1611
- return;
1612
- }
1613
- setIsWaitingForResponse(false);
1614
- setMessages([]);
1615
- chatStore.delete(scope);
1616
- setLoadingSessionId(sessionId);
1617
- try {
1618
- const response = await listConversations(configRef.current, { sessionId });
1619
- const entries = response.data ?? [];
1620
- const historical = entries.flatMap((entry) => conversationEntryToMessages(entry, sessionId));
1621
- if (sessionIdRef.current === sessionId) {
1622
- setMessages(historical);
1623
- }
1624
- if (historical.length > 0) {
1625
- chatStore.set(scope, historical);
1626
- }
1627
- } catch (error) {
1628
- callbacksRef.current.onError?.(error);
1629
- throw error;
1630
- } finally {
1631
- setLoadingSessionId((current) => current === sessionId ? void 0 : current);
1632
- }
1633
- };
1634
- const promise = run().finally(() => {
1635
- if (inFlightLoadRef.current?.sessionId === sessionId) {
1636
- inFlightLoadRef.current = null;
1637
- }
1638
- });
1639
- inFlightLoadRef.current = { sessionId, promise };
1640
- return promise;
1641
- }, []);
1642
1648
  react.useEffect(() => {
1643
- const key = streamKeyFor(scopeKey, currentSessionId);
1644
- const unsubscribe = activeStreamStore.subscribe(key, (msgs, isWaiting) => {
1649
+ const { userId } = config;
1650
+ if (!userId) return;
1651
+ const unsubscribe = activeStreamStore.subscribe(userId, (msgs, isWaiting) => {
1645
1652
  setMessages(msgs);
1646
1653
  setIsWaitingForResponse(isWaiting);
1647
1654
  });
1648
- const active = activeStreamStore.get(key);
1655
+ const active = activeStreamStore.get(userId);
1649
1656
  if (active) {
1650
1657
  setMessages(active.messages);
1651
1658
  setIsWaitingForResponse(active.isWaiting);
1652
1659
  }
1653
1660
  return unsubscribe;
1654
- }, [scopeKey, currentSessionId]);
1661
+ }, []);
1655
1662
  react.useEffect(() => {
1663
+ if (!config.userId) return;
1656
1664
  const toSave = messages.filter((m) => !m.isStreaming);
1657
1665
  if (toSave.length > 0) {
1658
- chatStore.set(scopeKey, toSave);
1666
+ chatStore.set(config.userId, toSave);
1659
1667
  }
1660
- }, [messages, scopeKey]);
1668
+ }, [messages, config.userId]);
1661
1669
  react.useEffect(() => {
1662
- const prevKey = prevScopeKeyRef.current;
1663
- prevScopeKeyRef.current = scopeKey;
1664
- if (prevKey === scopeKey) return;
1665
- const stored = chatStore.get(scopeKey);
1666
- setMessages(stored);
1667
- const restoredSessionId = stored.find((m) => m.sessionId)?.sessionId ?? configRef.current.session?.initialId ?? void 0;
1668
- sessionIdRef.current = restoredSessionId;
1669
- setCurrentSessionId(restoredSessionId);
1670
- setIsWaitingForResponse(false);
1671
- setUserActionState({ request: null, result: null, clearOtpTrigger: 0 });
1672
- }, [scopeKey]);
1670
+ const prevUserId = prevUserIdRef.current;
1671
+ prevUserIdRef.current = config.userId;
1672
+ if (prevUserId === config.userId) return;
1673
+ if (prevUserId && !config.userId) {
1674
+ chatStore.delete(prevUserId);
1675
+ setMessages([]);
1676
+ sessionIdRef.current = void 0;
1677
+ setIsWaitingForResponse(false);
1678
+ setUserActionState({ request: null, result: null, clearOtpTrigger: 0 });
1679
+ } else if (config.userId) {
1680
+ const stored = chatStore.get(config.userId);
1681
+ setMessages(stored);
1682
+ sessionIdRef.current = stored.find((m) => m.sessionId)?.sessionId;
1683
+ }
1684
+ }, [config.userId]);
1673
1685
  return {
1674
1686
  messages,
1675
1687
  sendMessage,
@@ -1680,13 +1692,11 @@ function useChatV2(config, callbacks = {}) {
1680
1692
  getSessionId,
1681
1693
  getMessages,
1682
1694
  isWaitingForResponse,
1683
- sessionId: currentSessionId,
1695
+ sessionId: sessionIdRef.current,
1684
1696
  userActionState,
1685
1697
  approveUserAction,
1686
1698
  rejectUserAction,
1687
- resendOtp,
1688
- loadSession,
1689
- loadingSessionId
1699
+ resendOtp
1690
1700
  };
1691
1701
  }
1692
1702
  function getSpeechRecognition() {
@@ -1906,18 +1916,14 @@ function useVoice(config = {}, callbacks = {}) {
1906
1916
  }
1907
1917
 
1908
1918
  exports.buildFormattedThinking = buildFormattedThinking;
1909
- exports.buildScopeKey = buildScopeKey;
1910
1919
  exports.cancelUserAction = cancelUserAction;
1911
1920
  exports.createInitialV2State = createInitialV2State;
1912
1921
  exports.generateId = generateId;
1913
- exports.listConversations = listConversations;
1914
- exports.listSessions = listSessions;
1915
1922
  exports.processStreamEventV2 = processStreamEventV2;
1916
1923
  exports.resendUserAction = resendUserAction;
1917
1924
  exports.streamWorkflowEvents = streamWorkflowEvents;
1918
1925
  exports.submitUserAction = submitUserAction;
1919
1926
  exports.useChatV2 = useChatV2;
1920
1927
  exports.useVoice = useVoice;
1921
- exports.workingPhaseDetailForDisplay = workingPhaseDetailForDisplay;
1922
1928
  //# sourceMappingURL=index.js.map
1923
1929
  //# sourceMappingURL=index.js.map