@paymanai/payman-typescript-ask-sdk 4.0.24 → 4.0.26
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 +27 -1
- package/dist/index.d.ts +27 -1
- package/dist/index.js +104 -22
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +102 -23
- package/dist/index.mjs.map +1 -1
- package/dist/index.native.js +104 -22
- package/dist/index.native.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -124,6 +124,8 @@ type UserActionRequest = {
|
|
|
124
124
|
subAction?: UserActionSubAction | (string & {});
|
|
125
125
|
verificationType?: VerificationType;
|
|
126
126
|
expirySeconds?: number;
|
|
127
|
+
/** Wall-clock expiry (epoch ms). Set when the prompt is first received. */
|
|
128
|
+
expiresAt?: number;
|
|
127
129
|
message?: string;
|
|
128
130
|
requestedSchema?: RequestedSchema;
|
|
129
131
|
metadata?: Record<string, string>;
|
|
@@ -199,6 +201,14 @@ type MessageDisplay = {
|
|
|
199
201
|
isStreaming?: boolean;
|
|
200
202
|
streamingContent?: string;
|
|
201
203
|
currentMessage?: string;
|
|
204
|
+
/**
|
|
205
|
+
* True while work events (tool calls, LLM-call boundaries, keep-alive
|
|
206
|
+
* heartbeats) are arriving AFTER answer text already started streaming —
|
|
207
|
+
* e.g. the agent-builder streams an instant acknowledgment and then does
|
|
208
|
+
* its real work. Tells the UI to keep a live status line below the
|
|
209
|
+
* already-rendered text instead of showing just a frozen cursor.
|
|
210
|
+
*/
|
|
211
|
+
hasTrailingActivity?: boolean;
|
|
202
212
|
streamProgress?: StreamProgress;
|
|
203
213
|
steps?: StreamingStep[];
|
|
204
214
|
isCancelled?: boolean;
|
|
@@ -556,6 +566,16 @@ type V2EventProcessorState = {
|
|
|
556
566
|
currentExecutingStepId?: string;
|
|
557
567
|
/** Server-computed wall-clock duration captured from RUN_COMPLETED's `totalTimeMs`. */
|
|
558
568
|
totalElapsedMs?: number;
|
|
569
|
+
/**
|
|
570
|
+
* True once work events (tool calls, LLM-call boundaries, keep-alive
|
|
571
|
+
* heartbeats) arrive AFTER answer text has started streaming. The
|
|
572
|
+
* agent-builder streams an instant acknowledgment first and then does
|
|
573
|
+
* its real work — this tells the UI to keep a live status line below
|
|
574
|
+
* the already-rendered text. Plain answer streaming (formatter deltas
|
|
575
|
+
* with no trailing work) never sets it. Sticky until the run ends so
|
|
576
|
+
* the status line doesn't flicker during think-gaps between tools.
|
|
577
|
+
*/
|
|
578
|
+
trailingActivity: boolean;
|
|
559
579
|
};
|
|
560
580
|
declare function createInitialV2State(): V2EventProcessorState;
|
|
561
581
|
declare function processStreamEventV2(rawEvent: StreamEvent, state: V2EventProcessorState): V2EventProcessorState;
|
|
@@ -639,6 +659,12 @@ declare function cancelUserAction(config: ChatConfig, userActionId: string): Pro
|
|
|
639
659
|
declare function resendUserAction(config: ChatConfig, userActionId: string): Promise<UserActionResponse>;
|
|
640
660
|
declare function expireUserAction(config: ChatConfig, userActionId: string): Promise<UserActionResponse>;
|
|
641
661
|
|
|
662
|
+
/** Wall-clock deadline (epoch ms) for a prompt with a positive TTL. */
|
|
663
|
+
declare function resolveUserActionExpiresAt(req: UserActionRequest, existing?: ActiveUserAction): number | undefined;
|
|
664
|
+
/** Seconds remaining before expiry, or undefined when the prompt has no TTL. */
|
|
665
|
+
declare function getUserActionSecondsLeft(prompt: ActiveUserAction): number | undefined;
|
|
666
|
+
declare function isUserActionExpired(prompt: ActiveUserAction): boolean;
|
|
667
|
+
|
|
642
668
|
declare function migrateActiveStream(oldUserId: string, newUserId: string): void;
|
|
643
669
|
|
|
644
|
-
export { type APIConfig, type ActiveUserAction, type AgentStage, type AnalysisMode, type ChatCallbacks, type ChatConfig, type ChunkDisplay, type FieldWidget, type JsonSchemaField, type JsonSchemaOption, type MessageDisplay, type MessageFeedbackState, type MessageRole, type RequestedSchema, type SendMessageOptions, type SessionParams, type StreamEvent, type StreamOptions, type StreamProgress, type StreamingStep, type UseChatV2Return, type UseVoiceReturn, type UserActionKind, type UserActionRequest, UserActionStaleError, type UserActionState, type UserActionStatus, type UserActionSubAction, type UserNotification, type V2EventProcessorState, type VerificationType, type VoiceCallbacks, type VoiceConfig, type VoicePermissions, type VoiceResult, type VoiceState, buildContent, cancelUserAction, classifyField, classifyUserActionKind, coerceValue, createInitialV2State, defaultValueFor, expireUserAction, generateId, getOptions, isNestedOrUnsupported, isRequired, migrateActiveStream, processStreamEventV2, renderableFields, resendUserAction, streamWorkflowEvents, submitUserAction, useChatV2, useVoice, validateField, validateForm };
|
|
670
|
+
export { type APIConfig, type ActiveUserAction, type AgentStage, type AnalysisMode, type ChatCallbacks, type ChatConfig, type ChunkDisplay, type FieldWidget, type JsonSchemaField, type JsonSchemaOption, type MessageDisplay, type MessageFeedbackState, type MessageRole, type RequestedSchema, type SendMessageOptions, type SessionParams, type StreamEvent, type StreamOptions, type StreamProgress, type StreamingStep, type UseChatV2Return, type UseVoiceReturn, type UserActionKind, type UserActionRequest, UserActionStaleError, type UserActionState, type UserActionStatus, type UserActionSubAction, type UserNotification, type V2EventProcessorState, type VerificationType, type VoiceCallbacks, type VoiceConfig, type VoicePermissions, type VoiceResult, type VoiceState, buildContent, cancelUserAction, classifyField, classifyUserActionKind, coerceValue, createInitialV2State, defaultValueFor, expireUserAction, generateId, getOptions, getUserActionSecondsLeft, isNestedOrUnsupported, isRequired, isUserActionExpired, migrateActiveStream, processStreamEventV2, renderableFields, resendUserAction, resolveUserActionExpiresAt, streamWorkflowEvents, submitUserAction, useChatV2, useVoice, validateField, validateForm };
|
package/dist/index.d.ts
CHANGED
|
@@ -124,6 +124,8 @@ type UserActionRequest = {
|
|
|
124
124
|
subAction?: UserActionSubAction | (string & {});
|
|
125
125
|
verificationType?: VerificationType;
|
|
126
126
|
expirySeconds?: number;
|
|
127
|
+
/** Wall-clock expiry (epoch ms). Set when the prompt is first received. */
|
|
128
|
+
expiresAt?: number;
|
|
127
129
|
message?: string;
|
|
128
130
|
requestedSchema?: RequestedSchema;
|
|
129
131
|
metadata?: Record<string, string>;
|
|
@@ -199,6 +201,14 @@ type MessageDisplay = {
|
|
|
199
201
|
isStreaming?: boolean;
|
|
200
202
|
streamingContent?: string;
|
|
201
203
|
currentMessage?: string;
|
|
204
|
+
/**
|
|
205
|
+
* True while work events (tool calls, LLM-call boundaries, keep-alive
|
|
206
|
+
* heartbeats) are arriving AFTER answer text already started streaming —
|
|
207
|
+
* e.g. the agent-builder streams an instant acknowledgment and then does
|
|
208
|
+
* its real work. Tells the UI to keep a live status line below the
|
|
209
|
+
* already-rendered text instead of showing just a frozen cursor.
|
|
210
|
+
*/
|
|
211
|
+
hasTrailingActivity?: boolean;
|
|
202
212
|
streamProgress?: StreamProgress;
|
|
203
213
|
steps?: StreamingStep[];
|
|
204
214
|
isCancelled?: boolean;
|
|
@@ -556,6 +566,16 @@ type V2EventProcessorState = {
|
|
|
556
566
|
currentExecutingStepId?: string;
|
|
557
567
|
/** Server-computed wall-clock duration captured from RUN_COMPLETED's `totalTimeMs`. */
|
|
558
568
|
totalElapsedMs?: number;
|
|
569
|
+
/**
|
|
570
|
+
* True once work events (tool calls, LLM-call boundaries, keep-alive
|
|
571
|
+
* heartbeats) arrive AFTER answer text has started streaming. The
|
|
572
|
+
* agent-builder streams an instant acknowledgment first and then does
|
|
573
|
+
* its real work — this tells the UI to keep a live status line below
|
|
574
|
+
* the already-rendered text. Plain answer streaming (formatter deltas
|
|
575
|
+
* with no trailing work) never sets it. Sticky until the run ends so
|
|
576
|
+
* the status line doesn't flicker during think-gaps between tools.
|
|
577
|
+
*/
|
|
578
|
+
trailingActivity: boolean;
|
|
559
579
|
};
|
|
560
580
|
declare function createInitialV2State(): V2EventProcessorState;
|
|
561
581
|
declare function processStreamEventV2(rawEvent: StreamEvent, state: V2EventProcessorState): V2EventProcessorState;
|
|
@@ -639,6 +659,12 @@ declare function cancelUserAction(config: ChatConfig, userActionId: string): Pro
|
|
|
639
659
|
declare function resendUserAction(config: ChatConfig, userActionId: string): Promise<UserActionResponse>;
|
|
640
660
|
declare function expireUserAction(config: ChatConfig, userActionId: string): Promise<UserActionResponse>;
|
|
641
661
|
|
|
662
|
+
/** Wall-clock deadline (epoch ms) for a prompt with a positive TTL. */
|
|
663
|
+
declare function resolveUserActionExpiresAt(req: UserActionRequest, existing?: ActiveUserAction): number | undefined;
|
|
664
|
+
/** Seconds remaining before expiry, or undefined when the prompt has no TTL. */
|
|
665
|
+
declare function getUserActionSecondsLeft(prompt: ActiveUserAction): number | undefined;
|
|
666
|
+
declare function isUserActionExpired(prompt: ActiveUserAction): boolean;
|
|
667
|
+
|
|
642
668
|
declare function migrateActiveStream(oldUserId: string, newUserId: string): void;
|
|
643
669
|
|
|
644
|
-
export { type APIConfig, type ActiveUserAction, type AgentStage, type AnalysisMode, type ChatCallbacks, type ChatConfig, type ChunkDisplay, type FieldWidget, type JsonSchemaField, type JsonSchemaOption, type MessageDisplay, type MessageFeedbackState, type MessageRole, type RequestedSchema, type SendMessageOptions, type SessionParams, type StreamEvent, type StreamOptions, type StreamProgress, type StreamingStep, type UseChatV2Return, type UseVoiceReturn, type UserActionKind, type UserActionRequest, UserActionStaleError, type UserActionState, type UserActionStatus, type UserActionSubAction, type UserNotification, type V2EventProcessorState, type VerificationType, type VoiceCallbacks, type VoiceConfig, type VoicePermissions, type VoiceResult, type VoiceState, buildContent, cancelUserAction, classifyField, classifyUserActionKind, coerceValue, createInitialV2State, defaultValueFor, expireUserAction, generateId, getOptions, isNestedOrUnsupported, isRequired, migrateActiveStream, processStreamEventV2, renderableFields, resendUserAction, streamWorkflowEvents, submitUserAction, useChatV2, useVoice, validateField, validateForm };
|
|
670
|
+
export { type APIConfig, type ActiveUserAction, type AgentStage, type AnalysisMode, type ChatCallbacks, type ChatConfig, type ChunkDisplay, type FieldWidget, type JsonSchemaField, type JsonSchemaOption, type MessageDisplay, type MessageFeedbackState, type MessageRole, type RequestedSchema, type SendMessageOptions, type SessionParams, type StreamEvent, type StreamOptions, type StreamProgress, type StreamingStep, type UseChatV2Return, type UseVoiceReturn, type UserActionKind, type UserActionRequest, UserActionStaleError, type UserActionState, type UserActionStatus, type UserActionSubAction, type UserNotification, type V2EventProcessorState, type VerificationType, type VoiceCallbacks, type VoiceConfig, type VoicePermissions, type VoiceResult, type VoiceState, buildContent, cancelUserAction, classifyField, classifyUserActionKind, coerceValue, createInitialV2State, defaultValueFor, expireUserAction, generateId, getOptions, getUserActionSecondsLeft, isNestedOrUnsupported, isRequired, isUserActionExpired, migrateActiveStream, processStreamEventV2, renderableFields, resendUserAction, resolveUserActionExpiresAt, streamWorkflowEvents, submitUserAction, useChatV2, useVoice, validateField, validateForm };
|
package/dist/index.js
CHANGED
|
@@ -30,6 +30,7 @@ var chatStore = {
|
|
|
30
30
|
};
|
|
31
31
|
|
|
32
32
|
// src/utils/activeStreamStore.ts
|
|
33
|
+
var EMPTY_USER_ACTION_STATE = { prompts: [], notifications: [] };
|
|
33
34
|
var streams = /* @__PURE__ */ new Map();
|
|
34
35
|
var activeStreamStore = {
|
|
35
36
|
has(key) {
|
|
@@ -38,7 +39,11 @@ var activeStreamStore = {
|
|
|
38
39
|
get(key) {
|
|
39
40
|
const entry = streams.get(key);
|
|
40
41
|
if (!entry) return null;
|
|
41
|
-
return {
|
|
42
|
+
return {
|
|
43
|
+
messages: entry.messages,
|
|
44
|
+
isWaiting: entry.isWaiting,
|
|
45
|
+
userActionState: entry.userActionState
|
|
46
|
+
};
|
|
42
47
|
},
|
|
43
48
|
// Called before startStream — registers the controller and initial messages
|
|
44
49
|
start(key, abortController, initialMessages) {
|
|
@@ -46,6 +51,7 @@ var activeStreamStore = {
|
|
|
46
51
|
streams.set(key, {
|
|
47
52
|
messages: initialMessages,
|
|
48
53
|
isWaiting: true,
|
|
54
|
+
userActionState: EMPTY_USER_ACTION_STATE,
|
|
49
55
|
abortController,
|
|
50
56
|
listeners: existing?.listeners ?? /* @__PURE__ */ new Set()
|
|
51
57
|
});
|
|
@@ -56,20 +62,27 @@ var activeStreamStore = {
|
|
|
56
62
|
if (!entry) return;
|
|
57
63
|
const next = typeof updater === "function" ? updater(entry.messages) : updater;
|
|
58
64
|
entry.messages = next;
|
|
59
|
-
entry.listeners.forEach((l) => l(next, entry.isWaiting));
|
|
65
|
+
entry.listeners.forEach((l) => l(next, entry.isWaiting, entry.userActionState));
|
|
60
66
|
},
|
|
61
67
|
setWaiting(key, waiting) {
|
|
62
68
|
const entry = streams.get(key);
|
|
63
69
|
if (!entry) return;
|
|
64
70
|
entry.isWaiting = waiting;
|
|
65
|
-
entry.listeners.forEach((l) => l(entry.messages, waiting));
|
|
71
|
+
entry.listeners.forEach((l) => l(entry.messages, waiting, entry.userActionState));
|
|
72
|
+
},
|
|
73
|
+
applyUserActionState(key, updater) {
|
|
74
|
+
const entry = streams.get(key);
|
|
75
|
+
if (!entry) return;
|
|
76
|
+
const next = typeof updater === "function" ? updater(entry.userActionState) : updater;
|
|
77
|
+
entry.userActionState = next;
|
|
78
|
+
entry.listeners.forEach((l) => l(entry.messages, entry.isWaiting, next));
|
|
66
79
|
},
|
|
67
80
|
// Called when stream completes — persists to chatStore and cleans up
|
|
68
81
|
complete(key) {
|
|
69
82
|
const entry = streams.get(key);
|
|
70
83
|
if (!entry) return;
|
|
71
84
|
entry.isWaiting = false;
|
|
72
|
-
entry.listeners.forEach((l) => l(entry.messages, false));
|
|
85
|
+
entry.listeners.forEach((l) => l(entry.messages, false, entry.userActionState));
|
|
73
86
|
const toSave = entry.messages.filter((m) => !m.isStreaming);
|
|
74
87
|
if (toSave.length > 0) chatStore.set(key, toSave);
|
|
75
88
|
streams.delete(key);
|
|
@@ -263,6 +276,8 @@ function getEventMessage(event) {
|
|
|
263
276
|
}
|
|
264
277
|
case "RUN_IN_PROGRESS":
|
|
265
278
|
return event.partialText || "Thinking...";
|
|
279
|
+
case "LLM_CALL_STARTED":
|
|
280
|
+
return event.description || "";
|
|
266
281
|
case "RUN_COMPLETED":
|
|
267
282
|
return "Agent run completed";
|
|
268
283
|
case "RUN_FAILED":
|
|
@@ -400,7 +415,8 @@ function createInitialV2State() {
|
|
|
400
415
|
finalData: void 0,
|
|
401
416
|
steps: [],
|
|
402
417
|
stepCounter: 0,
|
|
403
|
-
currentExecutingStepId: void 0
|
|
418
|
+
currentExecutingStepId: void 0,
|
|
419
|
+
trailingActivity: false
|
|
404
420
|
};
|
|
405
421
|
}
|
|
406
422
|
function upsertUserAction(state, req) {
|
|
@@ -422,6 +438,7 @@ function processStreamEventV2(rawEvent, state) {
|
|
|
422
438
|
if (typeof eventType === "string" && eventType.toUpperCase() === "KEEP_ALIVE") {
|
|
423
439
|
if (event.executionId) state.executionId = event.executionId;
|
|
424
440
|
if (event.sessionId) state.sessionId = event.sessionId;
|
|
441
|
+
if (state.finalResponse) state.trailingActivity = true;
|
|
425
442
|
const description = typeof event.description === "string" ? event.description : "";
|
|
426
443
|
if (description) {
|
|
427
444
|
for (let i = state.steps.length - 1; i >= 0; i--) {
|
|
@@ -456,7 +473,12 @@ function processStreamEventV2(rawEvent, state) {
|
|
|
456
473
|
state.lastEventType = eventType;
|
|
457
474
|
break;
|
|
458
475
|
}
|
|
476
|
+
case "LLM_CALL_STARTED":
|
|
477
|
+
if (state.finalResponse) state.trailingActivity = true;
|
|
478
|
+
state.lastEventType = eventType;
|
|
479
|
+
break;
|
|
459
480
|
case "INTENT_STARTED": {
|
|
481
|
+
if (state.finalResponse) state.trailingActivity = true;
|
|
460
482
|
const stepId = `step-${state.stepCounter++}`;
|
|
461
483
|
state.steps.push({
|
|
462
484
|
id: stepId,
|
|
@@ -472,6 +494,7 @@ function processStreamEventV2(rawEvent, state) {
|
|
|
472
494
|
break;
|
|
473
495
|
}
|
|
474
496
|
case "INTENT_COMPLETED": {
|
|
497
|
+
if (state.finalResponse) state.trailingActivity = true;
|
|
475
498
|
const intentStep = state.steps.find((s) => s.eventType === "INTENT_STARTED" && s.status === "in_progress");
|
|
476
499
|
if (intentStep) {
|
|
477
500
|
intentStep.status = "completed";
|
|
@@ -503,6 +526,7 @@ function processStreamEventV2(rawEvent, state) {
|
|
|
503
526
|
step.status = "completed";
|
|
504
527
|
}
|
|
505
528
|
});
|
|
529
|
+
state.trailingActivity = false;
|
|
506
530
|
state.lastEventType = eventType;
|
|
507
531
|
break;
|
|
508
532
|
}
|
|
@@ -574,6 +598,7 @@ function processStreamEventV2(rawEvent, state) {
|
|
|
574
598
|
case "WORKFLOW_ERROR":
|
|
575
599
|
state.hasError = true;
|
|
576
600
|
state.errorMessage = event.errorMessage || event.message || "Workflow error";
|
|
601
|
+
state.trailingActivity = false;
|
|
577
602
|
state.lastEventType = eventType;
|
|
578
603
|
break;
|
|
579
604
|
// ---- K2 pipeline stage lifecycle events ----
|
|
@@ -868,7 +893,9 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
868
893
|
const latestUsefulStep = [...state.steps].reverse().find(
|
|
869
894
|
(s) => s.message && !isBlandStatus(s.message)
|
|
870
895
|
);
|
|
871
|
-
const
|
|
896
|
+
const eventTypeUpper = typeof event.eventType === "string" ? event.eventType.toUpperCase() : "";
|
|
897
|
+
const liveEventLabel = eventTypeUpper === "KEEP_ALIVE" || eventTypeUpper === "LLM_CALL_STARTED" ? useful(getEventMessage(event)) : void 0;
|
|
898
|
+
const currentMessage = useful(activeStep?.message) ?? useful(lastInProgressStep?.message) ?? liveEventLabel ?? latestUsefulStep?.message ?? useful(getEventMessage(event)) ?? // Last-resort: every candidate is bland (very first event,
|
|
872
899
|
// nothing useful seen yet). Render the bland label so the
|
|
873
900
|
// bubble isn't blank.
|
|
874
901
|
activeStep?.message ?? lastInProgressStep?.message ?? getEventMessage(event);
|
|
@@ -893,6 +920,7 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
893
920
|
streamingContent: state.finalResponse,
|
|
894
921
|
content: "",
|
|
895
922
|
currentMessage,
|
|
923
|
+
hasTrailingActivity: state.trailingActivity,
|
|
896
924
|
streamProgress: "processing",
|
|
897
925
|
isError: false,
|
|
898
926
|
steps: [...state.steps],
|
|
@@ -1094,13 +1122,38 @@ async function expireUserAction(config, userActionId) {
|
|
|
1094
1122
|
return sendUserActionRequest(config, userActionId, "expired");
|
|
1095
1123
|
}
|
|
1096
1124
|
|
|
1125
|
+
// src/utils/userActionExpiry.ts
|
|
1126
|
+
function resolveUserActionExpiresAt(req, existing) {
|
|
1127
|
+
if (typeof req.expirySeconds !== "number" || req.expirySeconds <= 0) {
|
|
1128
|
+
return void 0;
|
|
1129
|
+
}
|
|
1130
|
+
if (existing?.expiresAt && existing.userActionId === req.userActionId) {
|
|
1131
|
+
return existing.expiresAt;
|
|
1132
|
+
}
|
|
1133
|
+
return Date.now() + Math.floor(req.expirySeconds) * 1e3;
|
|
1134
|
+
}
|
|
1135
|
+
function getUserActionSecondsLeft(prompt) {
|
|
1136
|
+
if (typeof prompt.expiresAt === "number" && prompt.expiresAt > 0) {
|
|
1137
|
+
return Math.max(0, Math.ceil((prompt.expiresAt - Date.now()) / 1e3));
|
|
1138
|
+
}
|
|
1139
|
+
if (typeof prompt.expirySeconds === "number" && prompt.expirySeconds > 0) {
|
|
1140
|
+
return Math.floor(prompt.expirySeconds);
|
|
1141
|
+
}
|
|
1142
|
+
return void 0;
|
|
1143
|
+
}
|
|
1144
|
+
function isUserActionExpired(prompt) {
|
|
1145
|
+
const left = getUserActionSecondsLeft(prompt);
|
|
1146
|
+
return left !== void 0 && left <= 0;
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1097
1149
|
// src/hooks/useChatV2.ts
|
|
1098
|
-
var
|
|
1150
|
+
var EMPTY_USER_ACTION_STATE2 = { prompts: [], notifications: [] };
|
|
1099
1151
|
function upsertPrompt(prompts, req) {
|
|
1100
|
-
const active = { ...req, status: "pending" };
|
|
1101
1152
|
const idx = prompts.findIndex(
|
|
1102
1153
|
(p) => req.toolCallId ? p.toolCallId === req.toolCallId : p.userActionId === req.userActionId
|
|
1103
1154
|
);
|
|
1155
|
+
const expiresAt = resolveUserActionExpiresAt(req, idx >= 0 ? prompts[idx] : void 0);
|
|
1156
|
+
const active = { ...req, status: "pending", expiresAt };
|
|
1104
1157
|
if (idx >= 0) {
|
|
1105
1158
|
const next = prompts.slice();
|
|
1106
1159
|
next[idx] = active;
|
|
@@ -1171,7 +1224,28 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1171
1224
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1172
1225
|
[]
|
|
1173
1226
|
);
|
|
1174
|
-
const [userActionState, setUserActionState] = react.useState(
|
|
1227
|
+
const [userActionState, setUserActionState] = react.useState(() => {
|
|
1228
|
+
if (!config.userId) return EMPTY_USER_ACTION_STATE2;
|
|
1229
|
+
return activeStreamStore.get(config.userId)?.userActionState ?? EMPTY_USER_ACTION_STATE2;
|
|
1230
|
+
});
|
|
1231
|
+
const storeAwareSetUserActionState = react.useCallback(
|
|
1232
|
+
(updater) => {
|
|
1233
|
+
const streamUserId = streamUserIdRef.current;
|
|
1234
|
+
const currentUserId = configRef.current.userId;
|
|
1235
|
+
const storeKey = streamUserId ?? currentUserId;
|
|
1236
|
+
if (storeKey && activeStreamStore.has(storeKey)) {
|
|
1237
|
+
activeStreamStore.applyUserActionState(
|
|
1238
|
+
storeKey,
|
|
1239
|
+
updater
|
|
1240
|
+
);
|
|
1241
|
+
}
|
|
1242
|
+
if (!streamUserId || streamUserId === currentUserId) {
|
|
1243
|
+
setUserActionState(updater);
|
|
1244
|
+
}
|
|
1245
|
+
},
|
|
1246
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1247
|
+
[]
|
|
1248
|
+
);
|
|
1175
1249
|
const wrappedCallbacks = react.useMemo(() => ({
|
|
1176
1250
|
...callbacksRef.current,
|
|
1177
1251
|
onMessageSent: (message) => callbacksRef.current.onMessageSent?.(message),
|
|
@@ -1181,14 +1255,14 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1181
1255
|
onExecutionTraceClick: (data) => callbacksRef.current.onExecutionTraceClick?.(data),
|
|
1182
1256
|
onSessionIdChange: (sessionId) => callbacksRef.current.onSessionIdChange?.(sessionId),
|
|
1183
1257
|
onUserActionRequired: (request) => {
|
|
1184
|
-
|
|
1258
|
+
storeAwareSetUserActionState((prev) => ({
|
|
1185
1259
|
...prev,
|
|
1186
1260
|
prompts: upsertPrompt(prev.prompts, request)
|
|
1187
1261
|
}));
|
|
1188
1262
|
callbacksRef.current.onUserActionRequired?.(request);
|
|
1189
1263
|
},
|
|
1190
1264
|
onUserNotification: (notification) => {
|
|
1191
|
-
|
|
1265
|
+
storeAwareSetUserActionState(
|
|
1192
1266
|
(prev) => prev.notifications.some((n) => n.id === notification.id) ? prev : { ...prev, notifications: [...prev.notifications, notification] }
|
|
1193
1267
|
);
|
|
1194
1268
|
callbacksRef.current.onUserNotification?.(notification);
|
|
@@ -1278,7 +1352,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1278
1352
|
streamUserIdRef.current = void 0;
|
|
1279
1353
|
cancelStreamManager();
|
|
1280
1354
|
setIsWaitingForResponse(false);
|
|
1281
|
-
|
|
1355
|
+
storeAwareSetUserActionState((prev) => ({ ...prev, prompts: [] }));
|
|
1282
1356
|
setMessages(
|
|
1283
1357
|
(prev) => prev.map((msg) => {
|
|
1284
1358
|
if (msg.isStreaming) {
|
|
@@ -1293,7 +1367,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1293
1367
|
return msg;
|
|
1294
1368
|
})
|
|
1295
1369
|
);
|
|
1296
|
-
}, [cancelStreamManager]);
|
|
1370
|
+
}, [cancelStreamManager, storeAwareSetUserActionState]);
|
|
1297
1371
|
const resetSession = react.useCallback(() => {
|
|
1298
1372
|
const streamUserId = streamUserIdRef.current ?? configRef.current.userId;
|
|
1299
1373
|
if (streamUserId) {
|
|
@@ -1307,7 +1381,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1307
1381
|
sessionIdRef.current = void 0;
|
|
1308
1382
|
abortControllerRef.current?.abort();
|
|
1309
1383
|
setIsWaitingForResponse(false);
|
|
1310
|
-
|
|
1384
|
+
storeAwareSetUserActionState(EMPTY_USER_ACTION_STATE2);
|
|
1311
1385
|
}, []);
|
|
1312
1386
|
const getSessionId = react.useCallback(() => {
|
|
1313
1387
|
return sessionIdRef.current;
|
|
@@ -1317,21 +1391,21 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1317
1391
|
}, [messages]);
|
|
1318
1392
|
const setPromptStatus = react.useCallback(
|
|
1319
1393
|
(userActionId, status) => {
|
|
1320
|
-
|
|
1394
|
+
storeAwareSetUserActionState((prev) => ({
|
|
1321
1395
|
...prev,
|
|
1322
1396
|
prompts: prev.prompts.map(
|
|
1323
1397
|
(p) => p.userActionId === userActionId ? { ...p, status } : p
|
|
1324
1398
|
)
|
|
1325
1399
|
}));
|
|
1326
1400
|
},
|
|
1327
|
-
[]
|
|
1401
|
+
[storeAwareSetUserActionState]
|
|
1328
1402
|
);
|
|
1329
1403
|
const removePrompt = react.useCallback((userActionId) => {
|
|
1330
|
-
|
|
1404
|
+
storeAwareSetUserActionState((prev) => ({
|
|
1331
1405
|
...prev,
|
|
1332
1406
|
prompts: prev.prompts.filter((p) => p.userActionId !== userActionId)
|
|
1333
1407
|
}));
|
|
1334
|
-
}, []);
|
|
1408
|
+
}, [storeAwareSetUserActionState]);
|
|
1335
1409
|
const submitUserAction2 = react.useCallback(
|
|
1336
1410
|
async (userActionId, content) => {
|
|
1337
1411
|
setPromptStatus(userActionId, "submitting");
|
|
@@ -1400,11 +1474,11 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1400
1474
|
[setPromptStatus]
|
|
1401
1475
|
);
|
|
1402
1476
|
const dismissNotification = react.useCallback((id) => {
|
|
1403
|
-
|
|
1477
|
+
storeAwareSetUserActionState((prev) => ({
|
|
1404
1478
|
...prev,
|
|
1405
1479
|
notifications: prev.notifications.filter((n) => n.id !== id)
|
|
1406
1480
|
}));
|
|
1407
|
-
}, []);
|
|
1481
|
+
}, [storeAwareSetUserActionState]);
|
|
1408
1482
|
react.useEffect(() => {
|
|
1409
1483
|
const prevSubscriptionUserId = subscriptionPrevUserIdRef.current;
|
|
1410
1484
|
subscriptionPrevUserIdRef.current = config.userId;
|
|
@@ -1413,14 +1487,17 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1413
1487
|
if (prevSubscriptionUserId && prevSubscriptionUserId !== userId && streamUserIdRef.current === prevSubscriptionUserId && !activeStreamStore.has(prevSubscriptionUserId) && activeStreamStore.has(userId)) {
|
|
1414
1488
|
streamUserIdRef.current = userId;
|
|
1415
1489
|
}
|
|
1416
|
-
const unsubscribe = activeStreamStore.subscribe(userId, (msgs, isWaiting) => {
|
|
1490
|
+
const unsubscribe = activeStreamStore.subscribe(userId, (msgs, isWaiting, actions) => {
|
|
1417
1491
|
setMessages(msgs);
|
|
1418
1492
|
setIsWaitingForResponse(isWaiting);
|
|
1493
|
+
setUserActionState(actions);
|
|
1419
1494
|
});
|
|
1420
1495
|
const active = activeStreamStore.get(userId);
|
|
1421
1496
|
if (active) {
|
|
1497
|
+
streamUserIdRef.current = userId;
|
|
1422
1498
|
setMessages(active.messages);
|
|
1423
1499
|
setIsWaitingForResponse(active.isWaiting);
|
|
1500
|
+
setUserActionState(active.userActionState);
|
|
1424
1501
|
}
|
|
1425
1502
|
return unsubscribe;
|
|
1426
1503
|
}, [config.userId]);
|
|
@@ -1448,12 +1525,14 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1448
1525
|
setMessages([]);
|
|
1449
1526
|
sessionIdRef.current = void 0;
|
|
1450
1527
|
setIsWaitingForResponse(false);
|
|
1451
|
-
setUserActionState(
|
|
1528
|
+
setUserActionState(EMPTY_USER_ACTION_STATE2);
|
|
1452
1529
|
} else if (config.userId) {
|
|
1453
1530
|
const active = activeStreamStore.get(config.userId);
|
|
1454
1531
|
if (active) {
|
|
1532
|
+
streamUserIdRef.current = config.userId;
|
|
1455
1533
|
setMessages(active.messages);
|
|
1456
1534
|
setIsWaitingForResponse(active.isWaiting);
|
|
1535
|
+
setUserActionState(active.userActionState);
|
|
1457
1536
|
sessionIdRef.current = getSessionIdFromMessages(active.messages) ?? config.initialSessionId;
|
|
1458
1537
|
return;
|
|
1459
1538
|
}
|
|
@@ -1832,12 +1911,15 @@ exports.defaultValueFor = defaultValueFor;
|
|
|
1832
1911
|
exports.expireUserAction = expireUserAction;
|
|
1833
1912
|
exports.generateId = generateId;
|
|
1834
1913
|
exports.getOptions = getOptions;
|
|
1914
|
+
exports.getUserActionSecondsLeft = getUserActionSecondsLeft;
|
|
1835
1915
|
exports.isNestedOrUnsupported = isNestedOrUnsupported;
|
|
1836
1916
|
exports.isRequired = isRequired;
|
|
1917
|
+
exports.isUserActionExpired = isUserActionExpired;
|
|
1837
1918
|
exports.migrateActiveStream = migrateActiveStream;
|
|
1838
1919
|
exports.processStreamEventV2 = processStreamEventV2;
|
|
1839
1920
|
exports.renderableFields = renderableFields;
|
|
1840
1921
|
exports.resendUserAction = resendUserAction;
|
|
1922
|
+
exports.resolveUserActionExpiresAt = resolveUserActionExpiresAt;
|
|
1841
1923
|
exports.streamWorkflowEvents = streamWorkflowEvents;
|
|
1842
1924
|
exports.submitUserAction = submitUserAction;
|
|
1843
1925
|
exports.useChatV2 = useChatV2;
|