@paymanai/payman-typescript-ask-sdk 4.0.10 → 4.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +1 -21
- package/dist/index.d.ts +1 -21
- package/dist/index.js +143 -391
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +144 -391
- package/dist/index.mjs.map +1 -1
- package/dist/index.native.js +146 -394
- package/dist/index.native.js.map +1 -1
- package/package.json +1 -1
package/dist/index.native.js
CHANGED
|
@@ -16,6 +16,95 @@ function generateId() {
|
|
|
16
16
|
return v.toString(16);
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
|
+
var storage = reactNativeMmkv.createMMKV({ id: "payman-chat-store" });
|
|
20
|
+
var chatStore = {
|
|
21
|
+
get(key) {
|
|
22
|
+
const raw = storage.getString(key);
|
|
23
|
+
if (!raw) return [];
|
|
24
|
+
try {
|
|
25
|
+
return JSON.parse(raw);
|
|
26
|
+
} catch {
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
set(key, messages) {
|
|
31
|
+
storage.set(key, JSON.stringify(messages));
|
|
32
|
+
},
|
|
33
|
+
delete(key) {
|
|
34
|
+
storage.delete(key);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// src/utils/activeStreamStore.ts
|
|
39
|
+
var streams = /* @__PURE__ */ new Map();
|
|
40
|
+
var activeStreamStore = {
|
|
41
|
+
has(key) {
|
|
42
|
+
return streams.has(key);
|
|
43
|
+
},
|
|
44
|
+
get(key) {
|
|
45
|
+
const entry = streams.get(key);
|
|
46
|
+
if (!entry) return null;
|
|
47
|
+
return { messages: entry.messages, isWaiting: entry.isWaiting };
|
|
48
|
+
},
|
|
49
|
+
// Called before startStream — registers the controller and initial messages
|
|
50
|
+
start(key, abortController, initialMessages) {
|
|
51
|
+
const existing = streams.get(key);
|
|
52
|
+
streams.set(key, {
|
|
53
|
+
messages: initialMessages,
|
|
54
|
+
isWaiting: true,
|
|
55
|
+
abortController,
|
|
56
|
+
listeners: existing?.listeners ?? /* @__PURE__ */ new Set()
|
|
57
|
+
});
|
|
58
|
+
},
|
|
59
|
+
// Called by the stream on every event — applies the same updater pattern React uses
|
|
60
|
+
applyMessages(key, updater) {
|
|
61
|
+
const entry = streams.get(key);
|
|
62
|
+
if (!entry) return;
|
|
63
|
+
const next = typeof updater === "function" ? updater(entry.messages) : updater;
|
|
64
|
+
entry.messages = next;
|
|
65
|
+
entry.listeners.forEach((l) => l(next, entry.isWaiting));
|
|
66
|
+
},
|
|
67
|
+
setWaiting(key, waiting) {
|
|
68
|
+
const entry = streams.get(key);
|
|
69
|
+
if (!entry) return;
|
|
70
|
+
entry.isWaiting = waiting;
|
|
71
|
+
entry.listeners.forEach((l) => l(entry.messages, waiting));
|
|
72
|
+
},
|
|
73
|
+
// Called when stream completes — persists to chatStore and cleans up
|
|
74
|
+
complete(key) {
|
|
75
|
+
const entry = streams.get(key);
|
|
76
|
+
if (!entry) return;
|
|
77
|
+
entry.isWaiting = false;
|
|
78
|
+
entry.listeners.forEach((l) => l(entry.messages, false));
|
|
79
|
+
const toSave = entry.messages.filter((m) => !m.isStreaming);
|
|
80
|
+
if (toSave.length > 0) chatStore.set(key, toSave);
|
|
81
|
+
streams.delete(key);
|
|
82
|
+
},
|
|
83
|
+
// Subscribe — returns unsubscribe fn. Component calls this on mount, cleanup on unmount.
|
|
84
|
+
subscribe(key, listener) {
|
|
85
|
+
const entry = streams.get(key);
|
|
86
|
+
if (!entry) return () => {
|
|
87
|
+
};
|
|
88
|
+
entry.listeners.add(listener);
|
|
89
|
+
return () => {
|
|
90
|
+
streams.get(key)?.listeners.delete(listener);
|
|
91
|
+
};
|
|
92
|
+
},
|
|
93
|
+
// Rename an entry — used when the server assigns a new session ID mid-stream
|
|
94
|
+
rename(oldKey, newKey) {
|
|
95
|
+
const entry = streams.get(oldKey);
|
|
96
|
+
if (!entry) return;
|
|
97
|
+
streams.set(newKey, entry);
|
|
98
|
+
streams.delete(oldKey);
|
|
99
|
+
},
|
|
100
|
+
// Explicit user cancel — aborts the controller and removes the entry
|
|
101
|
+
abort(key) {
|
|
102
|
+
const entry = streams.get(key);
|
|
103
|
+
if (!entry) return;
|
|
104
|
+
entry.abortController.abort();
|
|
105
|
+
streams.delete(key);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
19
108
|
|
|
20
109
|
// src/utils/streamingClient.native.ts
|
|
21
110
|
function parseJSONBuffer(buffer) {
|
|
@@ -295,40 +384,10 @@ function classifyUserActionKind(action, schema) {
|
|
|
295
384
|
return isVerificationSchema(schema) ? "verification" : "form";
|
|
296
385
|
}
|
|
297
386
|
}
|
|
298
|
-
function userActionHeader(kind) {
|
|
299
|
-
return kind === "verification" ? "**Verification required**" : "**Action required**";
|
|
300
|
-
}
|
|
301
|
-
function workingPhaseDetailForDisplay(raw) {
|
|
302
|
-
const t = raw.trim();
|
|
303
|
-
if (!t) return "";
|
|
304
|
-
if (/^Identified\s+\d+\s+tasks?\s+to\s+execute\.?$/i.test(t)) {
|
|
305
|
-
return "";
|
|
306
|
-
}
|
|
307
|
-
return t;
|
|
308
|
-
}
|
|
309
387
|
function getEventText(event, field) {
|
|
310
388
|
const value = event[field];
|
|
311
389
|
return typeof value === "string" ? value.trim() : "";
|
|
312
390
|
}
|
|
313
|
-
function shouldShowIntentHeader(event) {
|
|
314
|
-
const workerName = getEventText(event, "workerName");
|
|
315
|
-
const intentId = getEventText(event, "intentId");
|
|
316
|
-
return Boolean(workerName && intentId && workerName === intentId);
|
|
317
|
-
}
|
|
318
|
-
function addThinkingHeader(state, header) {
|
|
319
|
-
state.formattedThinkingText += (state.formattedThinkingText ? "\n" : "") + header;
|
|
320
|
-
}
|
|
321
|
-
function addThinkingDetail(state, detail) {
|
|
322
|
-
const trimmed = detail.trim();
|
|
323
|
-
if (!trimmed) return;
|
|
324
|
-
state.formattedThinkingText += (state.formattedThinkingText ? "\n" : "") + trimmed;
|
|
325
|
-
}
|
|
326
|
-
function addThinkingLine(state, header, detail) {
|
|
327
|
-
state.formattedThinkingText += (state.formattedThinkingText ? "\n" : "") + header + "\n" + detail;
|
|
328
|
-
}
|
|
329
|
-
function appendThinkingText(state, text) {
|
|
330
|
-
state.formattedThinkingText += text;
|
|
331
|
-
}
|
|
332
391
|
function updateExecutionStageMessage(state, msg) {
|
|
333
392
|
if (!msg) return;
|
|
334
393
|
for (let i = state.steps.length - 1; i >= 0; i--) {
|
|
@@ -349,9 +408,7 @@ function completeLastInProgressStep(steps) {
|
|
|
349
408
|
}
|
|
350
409
|
function createInitialV2State() {
|
|
351
410
|
return {
|
|
352
|
-
formattedThinkingText: "",
|
|
353
411
|
finalResponse: "",
|
|
354
|
-
currentWorker: "",
|
|
355
412
|
lastEventType: "",
|
|
356
413
|
sessionId: void 0,
|
|
357
414
|
executionId: void 0,
|
|
@@ -398,10 +455,6 @@ function processStreamEventV2(rawEvent, state) {
|
|
|
398
455
|
return state;
|
|
399
456
|
}
|
|
400
457
|
if (typeof eventType === "string" && eventType.toUpperCase() === "THINKING_DELTA") {
|
|
401
|
-
const text = typeof event.text === "string" ? event.text : "";
|
|
402
|
-
if (text) {
|
|
403
|
-
appendThinkingText(state, text);
|
|
404
|
-
}
|
|
405
458
|
if (event.executionId) state.executionId = event.executionId;
|
|
406
459
|
if (event.sessionId) state.sessionId = event.sessionId;
|
|
407
460
|
state.lastEventType = "THINKING_DELTA";
|
|
@@ -412,7 +465,6 @@ function processStreamEventV2(rawEvent, state) {
|
|
|
412
465
|
const message = getEventMessage(event);
|
|
413
466
|
switch (eventType) {
|
|
414
467
|
case "WORKFLOW_STARTED":
|
|
415
|
-
case "STARTED":
|
|
416
468
|
state.lastEventType = eventType;
|
|
417
469
|
break;
|
|
418
470
|
case "INTENT_PROGRESS": {
|
|
@@ -425,97 +477,7 @@ function processStreamEventV2(rawEvent, state) {
|
|
|
425
477
|
state.lastEventType = eventType;
|
|
426
478
|
break;
|
|
427
479
|
}
|
|
428
|
-
case "INTENT_THINKING": {
|
|
429
|
-
const worker = getEventText(event, "workerName") || "Worker";
|
|
430
|
-
const msg = getEventText(event, "message") || "Thinking...";
|
|
431
|
-
const showHeader = shouldShowIntentHeader(event);
|
|
432
|
-
if (worker !== state.currentWorker) {
|
|
433
|
-
state.currentWorker = worker;
|
|
434
|
-
if (showHeader && msg && msg !== worker) {
|
|
435
|
-
addThinkingLine(state, `**${worker}**`, msg);
|
|
436
|
-
} else if (showHeader) {
|
|
437
|
-
addThinkingHeader(state, `**${worker}**`);
|
|
438
|
-
} else if (msg !== "Thinking...") {
|
|
439
|
-
addThinkingDetail(state, msg);
|
|
440
|
-
}
|
|
441
|
-
} else if ((showHeader || msg !== "Thinking...")) {
|
|
442
|
-
appendThinkingText(state, "\n" + msg);
|
|
443
|
-
}
|
|
444
|
-
const lastInProgress = [...state.steps].reverse().find((s) => s.status === "in_progress");
|
|
445
|
-
if (lastInProgress) {
|
|
446
|
-
lastInProgress.thinkingText = "";
|
|
447
|
-
lastInProgress.isThinking = true;
|
|
448
|
-
}
|
|
449
|
-
state.lastEventType = "INTENT_THINKING";
|
|
450
|
-
break;
|
|
451
|
-
}
|
|
452
|
-
case "INTENT_THINKING_CONT": {
|
|
453
|
-
const msg = event.message || "";
|
|
454
|
-
if (!msg) break;
|
|
455
|
-
if (state.lastEventType === "INTENT_THINKING") {
|
|
456
|
-
appendThinkingText(state, "\n" + msg);
|
|
457
|
-
} else {
|
|
458
|
-
appendThinkingText(state, msg);
|
|
459
|
-
}
|
|
460
|
-
const thinkingStep = [...state.steps].reverse().find((s) => s.isThinking);
|
|
461
|
-
if (thinkingStep) {
|
|
462
|
-
thinkingStep.thinkingText = (thinkingStep.thinkingText || "") + msg;
|
|
463
|
-
}
|
|
464
|
-
state.lastEventType = "INTENT_THINKING_CONT";
|
|
465
|
-
break;
|
|
466
|
-
}
|
|
467
|
-
case "ORCHESTRATOR_THINKING": {
|
|
468
|
-
addThinkingLine(state, "**Planning**", event.message || "Understanding your request...");
|
|
469
|
-
const stepId = `step-${state.stepCounter++}`;
|
|
470
|
-
state.steps.push({
|
|
471
|
-
id: stepId,
|
|
472
|
-
eventType,
|
|
473
|
-
message,
|
|
474
|
-
status: "in_progress",
|
|
475
|
-
timestamp: Date.now(),
|
|
476
|
-
elapsedMs: event.elapsedMs
|
|
477
|
-
});
|
|
478
|
-
state.currentExecutingStepId = stepId;
|
|
479
|
-
state.lastEventType = eventType;
|
|
480
|
-
break;
|
|
481
|
-
}
|
|
482
|
-
case "ORCHESTRATOR_COMPLETED": {
|
|
483
|
-
const workingDetail = workingPhaseDetailForDisplay(message);
|
|
484
|
-
if (workingDetail) {
|
|
485
|
-
addThinkingLine(state, "**Working**", workingDetail);
|
|
486
|
-
} else {
|
|
487
|
-
addThinkingHeader(state, "**Working**");
|
|
488
|
-
}
|
|
489
|
-
state.steps.push({
|
|
490
|
-
id: `step-${state.stepCounter++}`,
|
|
491
|
-
eventType: "WORKING",
|
|
492
|
-
message: workingDetail,
|
|
493
|
-
status: "completed",
|
|
494
|
-
timestamp: Date.now()
|
|
495
|
-
});
|
|
496
|
-
const step = state.steps.find((s) => s.eventType === "ORCHESTRATOR_THINKING" && s.status === "in_progress");
|
|
497
|
-
if (step) {
|
|
498
|
-
step.status = "completed";
|
|
499
|
-
if (event.elapsedMs) step.elapsedMs = event.elapsedMs;
|
|
500
|
-
if (step.id === state.currentExecutingStepId) state.currentExecutingStepId = void 0;
|
|
501
|
-
}
|
|
502
|
-
state.lastEventType = eventType;
|
|
503
|
-
break;
|
|
504
|
-
}
|
|
505
480
|
case "INTENT_STARTED": {
|
|
506
|
-
const worker = getEventText(event, "workerName") || "Worker";
|
|
507
|
-
const msg = getEventText(event, "message") || "Starting...";
|
|
508
|
-
const showHeader = shouldShowIntentHeader(event);
|
|
509
|
-
state.currentWorker = worker;
|
|
510
|
-
if (showHeader && msg !== worker) {
|
|
511
|
-
addThinkingLine(state, `**${worker}**`, msg);
|
|
512
|
-
} else if (showHeader) {
|
|
513
|
-
addThinkingHeader(state, `**${worker}**`);
|
|
514
|
-
} else {
|
|
515
|
-
addThinkingDetail(state, msg);
|
|
516
|
-
}
|
|
517
|
-
const thinkingStep = state.steps.find((s) => s.isThinking);
|
|
518
|
-
if (thinkingStep) thinkingStep.isThinking = false;
|
|
519
481
|
const stepId = `step-${state.stepCounter++}`;
|
|
520
482
|
state.steps.push({
|
|
521
483
|
id: stepId,
|
|
@@ -534,55 +496,18 @@ function processStreamEventV2(rawEvent, state) {
|
|
|
534
496
|
const intentStep = state.steps.find((s) => s.eventType === "INTENT_STARTED" && s.status === "in_progress");
|
|
535
497
|
if (intentStep) {
|
|
536
498
|
intentStep.status = "completed";
|
|
537
|
-
intentStep.isThinking = false;
|
|
538
499
|
if (event.elapsedMs) intentStep.elapsedMs = event.elapsedMs;
|
|
539
500
|
if (intentStep.id === state.currentExecutingStepId) state.currentExecutingStepId = void 0;
|
|
540
501
|
}
|
|
541
502
|
state.lastEventType = eventType;
|
|
542
503
|
break;
|
|
543
504
|
}
|
|
544
|
-
case "
|
|
545
|
-
addThinkingLine(state, "**Finalizing**", event.message || "Preparing response...");
|
|
546
|
-
const stepId = `step-${state.stepCounter++}`;
|
|
547
|
-
state.steps.push({
|
|
548
|
-
id: stepId,
|
|
549
|
-
eventType,
|
|
550
|
-
message,
|
|
551
|
-
status: "in_progress",
|
|
552
|
-
timestamp: Date.now(),
|
|
553
|
-
elapsedMs: event.elapsedMs
|
|
554
|
-
});
|
|
555
|
-
state.currentExecutingStepId = stepId;
|
|
556
|
-
state.lastEventType = eventType;
|
|
557
|
-
break;
|
|
558
|
-
}
|
|
559
|
-
case "AGGREGATOR_COMPLETED": {
|
|
560
|
-
appendThinkingText(state, "\n" + (event.message || "Response ready"));
|
|
561
|
-
const step = state.steps.find((s) => s.eventType === "AGGREGATOR_THINKING" && s.status === "in_progress");
|
|
562
|
-
if (step) {
|
|
563
|
-
step.status = "completed";
|
|
564
|
-
if (event.elapsedMs) step.elapsedMs = event.elapsedMs;
|
|
565
|
-
if (step.id === state.currentExecutingStepId) state.currentExecutingStepId = void 0;
|
|
566
|
-
}
|
|
567
|
-
state.lastEventType = eventType;
|
|
568
|
-
break;
|
|
569
|
-
}
|
|
570
|
-
case "WORKFLOW_COMPLETED":
|
|
571
|
-
case "COMPLETED": {
|
|
505
|
+
case "WORKFLOW_COMPLETED": {
|
|
572
506
|
const totalTime = Number(event.totalTimeMs);
|
|
573
507
|
if (Number.isFinite(totalTime) && totalTime > 0) {
|
|
574
508
|
state.totalElapsedMs = totalTime;
|
|
575
509
|
}
|
|
576
|
-
|
|
577
|
-
const trace = event.trace && typeof event.trace === "object" ? event.trace : null;
|
|
578
|
-
if (!content && trace?.workflowMsg && typeof trace.workflowMsg === "string") {
|
|
579
|
-
content = trace.workflowMsg;
|
|
580
|
-
}
|
|
581
|
-
if (!content && trace?.aggregator && typeof trace.aggregator === "object") {
|
|
582
|
-
const agg = trace.aggregator;
|
|
583
|
-
if (typeof agg.response === "string") content = agg.response;
|
|
584
|
-
else content = extractResponseContent(agg.response);
|
|
585
|
-
}
|
|
510
|
+
const content = extractResponseContent(event.response);
|
|
586
511
|
if (content) {
|
|
587
512
|
state.finalResponse = content;
|
|
588
513
|
if (event.trace && typeof event.trace === "object") {
|
|
@@ -597,7 +522,6 @@ function processStreamEventV2(rawEvent, state) {
|
|
|
597
522
|
state.steps.forEach((step) => {
|
|
598
523
|
if (step.status === "in_progress") {
|
|
599
524
|
step.status = "completed";
|
|
600
|
-
step.isThinking = false;
|
|
601
525
|
}
|
|
602
526
|
});
|
|
603
527
|
state.lastEventType = eventType;
|
|
@@ -616,7 +540,6 @@ function processStreamEventV2(rawEvent, state) {
|
|
|
616
540
|
};
|
|
617
541
|
state.notifications.push(notification);
|
|
618
542
|
state.lastNotification = notification;
|
|
619
|
-
if (promptMessage) addThinkingDetail(state, promptMessage);
|
|
620
543
|
state.lastEventType = eventType;
|
|
621
544
|
break;
|
|
622
545
|
}
|
|
@@ -642,9 +565,6 @@ function processStreamEventV2(rawEvent, state) {
|
|
|
642
565
|
};
|
|
643
566
|
upsertUserAction(state, request);
|
|
644
567
|
state.lastUserAction = request;
|
|
645
|
-
const header = userActionHeader(kind);
|
|
646
|
-
if (promptMessage) addThinkingLine(state, header, promptMessage);
|
|
647
|
-
else addThinkingHeader(state, header);
|
|
648
568
|
const stepId = `step-${state.stepCounter++}`;
|
|
649
569
|
state.steps.push({
|
|
650
570
|
id: stepId,
|
|
@@ -668,27 +588,15 @@ function processStreamEventV2(rawEvent, state) {
|
|
|
668
588
|
};
|
|
669
589
|
state.notifications.push(notification);
|
|
670
590
|
state.lastNotification = notification;
|
|
671
|
-
if (noteMessage) addThinkingDetail(state, noteMessage);
|
|
672
591
|
}
|
|
673
592
|
state.lastEventType = eventType;
|
|
674
593
|
break;
|
|
675
594
|
}
|
|
676
595
|
case "WORKFLOW_ERROR":
|
|
677
|
-
case "ERROR":
|
|
678
596
|
state.hasError = true;
|
|
679
597
|
state.errorMessage = event.errorMessage || event.message || "Workflow error";
|
|
680
598
|
state.lastEventType = eventType;
|
|
681
599
|
break;
|
|
682
|
-
case "INTENT_ERROR": {
|
|
683
|
-
state.errorMessage = message || event.errorMessage || "An error occurred";
|
|
684
|
-
const intentStep = state.steps.find((s) => s.eventType === "INTENT_STARTED" && s.status === "in_progress");
|
|
685
|
-
if (intentStep) {
|
|
686
|
-
intentStep.status = "error";
|
|
687
|
-
intentStep.isThinking = false;
|
|
688
|
-
}
|
|
689
|
-
state.lastEventType = eventType;
|
|
690
|
-
break;
|
|
691
|
-
}
|
|
692
600
|
// ---- K2 pipeline stage lifecycle events ----
|
|
693
601
|
//
|
|
694
602
|
// The k2-server playground streaming API emits
|
|
@@ -809,84 +717,6 @@ function processStreamEventV2(rawEvent, state) {
|
|
|
809
717
|
return state;
|
|
810
718
|
}
|
|
811
719
|
|
|
812
|
-
// src/utils/messageStateManager.ts
|
|
813
|
-
function buildFormattedThinking(steps, allThinkingText) {
|
|
814
|
-
const parts = [];
|
|
815
|
-
const safeSteps = steps ?? [];
|
|
816
|
-
const cleanAll = allThinkingText.replace(/^\s+/, "");
|
|
817
|
-
if (cleanAll) {
|
|
818
|
-
const firstStepWithThinking = safeSteps.find(
|
|
819
|
-
(s) => s.thinkingText && s.thinkingText.trim()
|
|
820
|
-
);
|
|
821
|
-
if (!firstStepWithThinking) {
|
|
822
|
-
parts.push("**Preflight**");
|
|
823
|
-
parts.push(cleanAll);
|
|
824
|
-
} else {
|
|
825
|
-
const stepText = firstStepWithThinking.thinkingText.trim();
|
|
826
|
-
const idx = cleanAll.indexOf(stepText);
|
|
827
|
-
if (idx > 0) {
|
|
828
|
-
const orphaned = cleanAll.substring(0, idx).replace(/\s+$/, "");
|
|
829
|
-
if (orphaned) {
|
|
830
|
-
parts.push("**Preflight**");
|
|
831
|
-
parts.push(orphaned);
|
|
832
|
-
}
|
|
833
|
-
}
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
for (const step of safeSteps) {
|
|
837
|
-
switch (step.eventType) {
|
|
838
|
-
case "STAGE_STARTED": {
|
|
839
|
-
if (step.message) parts.push(`**${step.message}**`);
|
|
840
|
-
break;
|
|
841
|
-
}
|
|
842
|
-
case "ORCHESTRATOR_THINKING":
|
|
843
|
-
parts.push("**Planning**");
|
|
844
|
-
if (step.message) parts.push(step.message);
|
|
845
|
-
break;
|
|
846
|
-
case "INTENT_STARTED": {
|
|
847
|
-
let label = step.message || "Processing";
|
|
848
|
-
const started = label.match(/^(.+?)\s+started$/i);
|
|
849
|
-
const progress = label.match(/^(.+?)\s+in progress$/i);
|
|
850
|
-
if (started) label = started[1];
|
|
851
|
-
else if (progress) label = progress[1];
|
|
852
|
-
parts.push(`**${label}**`);
|
|
853
|
-
if (step.thinkingText) parts.push(step.thinkingText);
|
|
854
|
-
break;
|
|
855
|
-
}
|
|
856
|
-
case "INTENT_PROGRESS": {
|
|
857
|
-
if (step.thinkingText) parts.push(step.thinkingText);
|
|
858
|
-
else if (step.message) parts.push(step.message);
|
|
859
|
-
break;
|
|
860
|
-
}
|
|
861
|
-
case "AGGREGATOR_THINKING":
|
|
862
|
-
parts.push("**Finalizing**");
|
|
863
|
-
if (step.message) parts.push(step.message);
|
|
864
|
-
break;
|
|
865
|
-
case "USER_ACTION_REQUIRED":
|
|
866
|
-
parts.push("**Action required**");
|
|
867
|
-
if (step.message) parts.push(step.message);
|
|
868
|
-
break;
|
|
869
|
-
}
|
|
870
|
-
}
|
|
871
|
-
return parts.length > 0 ? parts.join("\n") : allThinkingText;
|
|
872
|
-
}
|
|
873
|
-
function createCancelledMessageUpdate(steps, currentMessage) {
|
|
874
|
-
const updatedSteps = steps.map((step) => {
|
|
875
|
-
if (step.status === "in_progress") {
|
|
876
|
-
return { ...step, status: "pending" };
|
|
877
|
-
}
|
|
878
|
-
return step;
|
|
879
|
-
});
|
|
880
|
-
return {
|
|
881
|
-
isStreaming: false,
|
|
882
|
-
isCancelled: true,
|
|
883
|
-
steps: updatedSteps,
|
|
884
|
-
currentExecutingStepId: void 0,
|
|
885
|
-
// Preserve currentMessage so UI can show it with X icon
|
|
886
|
-
currentMessage: currentMessage || "Thinking..."
|
|
887
|
-
};
|
|
888
|
-
}
|
|
889
|
-
|
|
890
720
|
// src/utils/requestBuilder.ts
|
|
891
721
|
var DEFAULT_STREAM_ENDPOINT = "/api/playground/ask/stream";
|
|
892
722
|
function buildRequestBody(config, userMessage, sessionId, options) {
|
|
@@ -960,133 +790,6 @@ function buildRequestHeaders(config) {
|
|
|
960
790
|
return headers;
|
|
961
791
|
}
|
|
962
792
|
|
|
963
|
-
// src/utils/userActionClient.ts
|
|
964
|
-
var UserActionStaleError = class extends Error {
|
|
965
|
-
constructor(userActionId, message = "User action is no longer actionable") {
|
|
966
|
-
super(message);
|
|
967
|
-
__publicField(this, "userActionId");
|
|
968
|
-
this.name = "UserActionStaleError";
|
|
969
|
-
this.userActionId = userActionId;
|
|
970
|
-
}
|
|
971
|
-
};
|
|
972
|
-
async function sendUserActionRequest(config, userActionId, action, data) {
|
|
973
|
-
const url = buildUserActionUrl(config, userActionId, action);
|
|
974
|
-
const baseHeaders = buildRequestHeaders(config);
|
|
975
|
-
const hasBody = data !== void 0;
|
|
976
|
-
const headers = hasBody ? { "Content-Type": "application/json", ...baseHeaders } : baseHeaders;
|
|
977
|
-
const response = await fetch(url, {
|
|
978
|
-
method: "POST",
|
|
979
|
-
headers,
|
|
980
|
-
body: hasBody ? JSON.stringify(data) : void 0
|
|
981
|
-
});
|
|
982
|
-
if (response.status === 404) {
|
|
983
|
-
throw new UserActionStaleError(userActionId);
|
|
984
|
-
}
|
|
985
|
-
if (!response.ok) {
|
|
986
|
-
const errorText = await response.text();
|
|
987
|
-
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
|
988
|
-
}
|
|
989
|
-
return await response.json();
|
|
990
|
-
}
|
|
991
|
-
async function submitUserAction(config, userActionId, content) {
|
|
992
|
-
return sendUserActionRequest(config, userActionId, "submit", content ?? {});
|
|
993
|
-
}
|
|
994
|
-
async function cancelUserAction(config, userActionId) {
|
|
995
|
-
return sendUserActionRequest(config, userActionId, "cancel");
|
|
996
|
-
}
|
|
997
|
-
async function resendUserAction(config, userActionId) {
|
|
998
|
-
return sendUserActionRequest(config, userActionId, "resend");
|
|
999
|
-
}
|
|
1000
|
-
var storage = reactNativeMmkv.createMMKV({ id: "payman-chat-store" });
|
|
1001
|
-
var chatStore = {
|
|
1002
|
-
get(key) {
|
|
1003
|
-
const raw = storage.getString(key);
|
|
1004
|
-
if (!raw) return [];
|
|
1005
|
-
try {
|
|
1006
|
-
return JSON.parse(raw);
|
|
1007
|
-
} catch {
|
|
1008
|
-
return [];
|
|
1009
|
-
}
|
|
1010
|
-
},
|
|
1011
|
-
set(key, messages) {
|
|
1012
|
-
storage.set(key, JSON.stringify(messages));
|
|
1013
|
-
},
|
|
1014
|
-
delete(key) {
|
|
1015
|
-
storage.delete(key);
|
|
1016
|
-
}
|
|
1017
|
-
};
|
|
1018
|
-
|
|
1019
|
-
// src/utils/activeStreamStore.ts
|
|
1020
|
-
var streams = /* @__PURE__ */ new Map();
|
|
1021
|
-
var activeStreamStore = {
|
|
1022
|
-
has(key) {
|
|
1023
|
-
return streams.has(key);
|
|
1024
|
-
},
|
|
1025
|
-
get(key) {
|
|
1026
|
-
const entry = streams.get(key);
|
|
1027
|
-
if (!entry) return null;
|
|
1028
|
-
return { messages: entry.messages, isWaiting: entry.isWaiting };
|
|
1029
|
-
},
|
|
1030
|
-
// Called before startStream — registers the controller and initial messages
|
|
1031
|
-
start(key, abortController, initialMessages) {
|
|
1032
|
-
const existing = streams.get(key);
|
|
1033
|
-
streams.set(key, {
|
|
1034
|
-
messages: initialMessages,
|
|
1035
|
-
isWaiting: true,
|
|
1036
|
-
abortController,
|
|
1037
|
-
listeners: existing?.listeners ?? /* @__PURE__ */ new Set()
|
|
1038
|
-
});
|
|
1039
|
-
},
|
|
1040
|
-
// Called by the stream on every event — applies the same updater pattern React uses
|
|
1041
|
-
applyMessages(key, updater) {
|
|
1042
|
-
const entry = streams.get(key);
|
|
1043
|
-
if (!entry) return;
|
|
1044
|
-
const next = typeof updater === "function" ? updater(entry.messages) : updater;
|
|
1045
|
-
entry.messages = next;
|
|
1046
|
-
entry.listeners.forEach((l) => l(next, entry.isWaiting));
|
|
1047
|
-
},
|
|
1048
|
-
setWaiting(key, waiting) {
|
|
1049
|
-
const entry = streams.get(key);
|
|
1050
|
-
if (!entry) return;
|
|
1051
|
-
entry.isWaiting = waiting;
|
|
1052
|
-
entry.listeners.forEach((l) => l(entry.messages, waiting));
|
|
1053
|
-
},
|
|
1054
|
-
// Called when stream completes — persists to chatStore and cleans up
|
|
1055
|
-
complete(key) {
|
|
1056
|
-
const entry = streams.get(key);
|
|
1057
|
-
if (!entry) return;
|
|
1058
|
-
entry.isWaiting = false;
|
|
1059
|
-
entry.listeners.forEach((l) => l(entry.messages, false));
|
|
1060
|
-
const toSave = entry.messages.filter((m) => !m.isStreaming);
|
|
1061
|
-
if (toSave.length > 0) chatStore.set(key, toSave);
|
|
1062
|
-
streams.delete(key);
|
|
1063
|
-
},
|
|
1064
|
-
// Subscribe — returns unsubscribe fn. Component calls this on mount, cleanup on unmount.
|
|
1065
|
-
subscribe(key, listener) {
|
|
1066
|
-
const entry = streams.get(key);
|
|
1067
|
-
if (!entry) return () => {
|
|
1068
|
-
};
|
|
1069
|
-
entry.listeners.add(listener);
|
|
1070
|
-
return () => {
|
|
1071
|
-
streams.get(key)?.listeners.delete(listener);
|
|
1072
|
-
};
|
|
1073
|
-
},
|
|
1074
|
-
// Rename an entry — used when the server assigns a new session ID mid-stream
|
|
1075
|
-
rename(oldKey, newKey) {
|
|
1076
|
-
const entry = streams.get(oldKey);
|
|
1077
|
-
if (!entry) return;
|
|
1078
|
-
streams.set(newKey, entry);
|
|
1079
|
-
streams.delete(oldKey);
|
|
1080
|
-
},
|
|
1081
|
-
// Explicit user cancel — aborts the controller and removes the entry
|
|
1082
|
-
abort(key) {
|
|
1083
|
-
const entry = streams.get(key);
|
|
1084
|
-
if (!entry) return;
|
|
1085
|
-
entry.abortController.abort();
|
|
1086
|
-
streams.delete(key);
|
|
1087
|
-
}
|
|
1088
|
-
};
|
|
1089
|
-
|
|
1090
793
|
// src/utils/ragImageResolver.ts
|
|
1091
794
|
var RAG_IMAGE_REGEX = /\/api\/rag\/chunks\/[^"'\s]+\/image/;
|
|
1092
795
|
function hasRagImages(content) {
|
|
@@ -1201,7 +904,6 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
1201
904
|
streamProgress: "error",
|
|
1202
905
|
isError: true,
|
|
1203
906
|
errorDetails: state.errorMessage,
|
|
1204
|
-
formattedThinkingText: state.formattedThinkingText || void 0,
|
|
1205
907
|
steps: [...state.steps],
|
|
1206
908
|
currentExecutingStepId: void 0,
|
|
1207
909
|
executionId: state.executionId,
|
|
@@ -1214,7 +916,6 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
1214
916
|
currentMessage,
|
|
1215
917
|
streamProgress: "processing",
|
|
1216
918
|
isError: false,
|
|
1217
|
-
formattedThinkingText: state.formattedThinkingText || void 0,
|
|
1218
919
|
steps: [...state.steps],
|
|
1219
920
|
currentExecutingStepId: state.currentExecutingStepId,
|
|
1220
921
|
executionId: state.executionId,
|
|
@@ -1241,7 +942,6 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
1241
942
|
errorDetails: isAborted ? void 0 : error.message,
|
|
1242
943
|
content: isAborted ? state.finalResponse || "" : state.finalResponse || FRIENDLY_ERROR_MESSAGE,
|
|
1243
944
|
currentMessage: isAborted ? "Thinking..." : void 0,
|
|
1244
|
-
formattedThinkingText: state.formattedThinkingText || void 0,
|
|
1245
945
|
steps: [...state.steps].map((step) => {
|
|
1246
946
|
if (step.status === "in_progress" && isAborted) {
|
|
1247
947
|
return { ...step, status: "pending" };
|
|
@@ -1280,7 +980,6 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
1280
980
|
steps: state.hasError ? [] : [...state.steps],
|
|
1281
981
|
isCancelled: false,
|
|
1282
982
|
currentExecutingStepId: void 0,
|
|
1283
|
-
formattedThinkingText: state.hasError ? void 0 : state.formattedThinkingText || void 0,
|
|
1284
983
|
isResolvingImages: needsImageResolve,
|
|
1285
984
|
totalElapsedMs: state.hasError ? void 0 : state.totalElapsedMs
|
|
1286
985
|
};
|
|
@@ -1333,7 +1032,6 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
1333
1032
|
isCancelled: isAborted,
|
|
1334
1033
|
errorDetails: isAborted ? void 0 : error.message,
|
|
1335
1034
|
content: isAborted ? state.finalResponse || "" : state.finalResponse || FRIENDLY_ERROR_MESSAGE,
|
|
1336
|
-
formattedThinkingText: state.formattedThinkingText || void 0,
|
|
1337
1035
|
steps: [...state.steps].map((step) => {
|
|
1338
1036
|
if (step.status === "in_progress" && isAborted) {
|
|
1339
1037
|
return { ...step, status: "pending" };
|
|
@@ -1359,6 +1057,61 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
1359
1057
|
};
|
|
1360
1058
|
}
|
|
1361
1059
|
|
|
1060
|
+
// src/utils/messageStateManager.ts
|
|
1061
|
+
function createCancelledMessageUpdate(steps, currentMessage) {
|
|
1062
|
+
const updatedSteps = steps.map((step) => {
|
|
1063
|
+
if (step.status === "in_progress") {
|
|
1064
|
+
return { ...step, status: "pending" };
|
|
1065
|
+
}
|
|
1066
|
+
return step;
|
|
1067
|
+
});
|
|
1068
|
+
return {
|
|
1069
|
+
isStreaming: false,
|
|
1070
|
+
isCancelled: true,
|
|
1071
|
+
steps: updatedSteps,
|
|
1072
|
+
currentExecutingStepId: void 0,
|
|
1073
|
+
currentMessage: currentMessage || "Thinking..."
|
|
1074
|
+
};
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
// src/utils/userActionClient.ts
|
|
1078
|
+
var UserActionStaleError = class extends Error {
|
|
1079
|
+
constructor(userActionId, message = "User action is no longer actionable") {
|
|
1080
|
+
super(message);
|
|
1081
|
+
__publicField(this, "userActionId");
|
|
1082
|
+
this.name = "UserActionStaleError";
|
|
1083
|
+
this.userActionId = userActionId;
|
|
1084
|
+
}
|
|
1085
|
+
};
|
|
1086
|
+
async function sendUserActionRequest(config, userActionId, action, data) {
|
|
1087
|
+
const url = buildUserActionUrl(config, userActionId, action);
|
|
1088
|
+
const baseHeaders = buildRequestHeaders(config);
|
|
1089
|
+
const hasBody = data !== void 0;
|
|
1090
|
+
const headers = hasBody ? { "Content-Type": "application/json", ...baseHeaders } : baseHeaders;
|
|
1091
|
+
const response = await fetch(url, {
|
|
1092
|
+
method: "POST",
|
|
1093
|
+
headers,
|
|
1094
|
+
body: hasBody ? JSON.stringify(data) : void 0
|
|
1095
|
+
});
|
|
1096
|
+
if (response.status === 404) {
|
|
1097
|
+
throw new UserActionStaleError(userActionId);
|
|
1098
|
+
}
|
|
1099
|
+
if (!response.ok) {
|
|
1100
|
+
const errorText = await response.text();
|
|
1101
|
+
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
|
1102
|
+
}
|
|
1103
|
+
return await response.json();
|
|
1104
|
+
}
|
|
1105
|
+
async function submitUserAction(config, userActionId, content) {
|
|
1106
|
+
return sendUserActionRequest(config, userActionId, "submit", content ?? {});
|
|
1107
|
+
}
|
|
1108
|
+
async function cancelUserAction(config, userActionId) {
|
|
1109
|
+
return sendUserActionRequest(config, userActionId, "cancel");
|
|
1110
|
+
}
|
|
1111
|
+
async function resendUserAction(config, userActionId) {
|
|
1112
|
+
return sendUserActionRequest(config, userActionId, "resend");
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1362
1115
|
// src/hooks/useChatV2.ts
|
|
1363
1116
|
var EMPTY_USER_ACTION_STATE = { prompts: [], notifications: [] };
|
|
1364
1117
|
function upsertPrompt(prompts, req) {
|
|
@@ -1974,7 +1727,6 @@ function migrateActiveStream(oldUserId, newUserId) {
|
|
|
1974
1727
|
|
|
1975
1728
|
exports.UserActionStaleError = UserActionStaleError;
|
|
1976
1729
|
exports.buildContent = buildContent;
|
|
1977
|
-
exports.buildFormattedThinking = buildFormattedThinking;
|
|
1978
1730
|
exports.cancelUserAction = cancelUserAction;
|
|
1979
1731
|
exports.classifyField = classifyField;
|
|
1980
1732
|
exports.classifyUserActionKind = classifyUserActionKind;
|