flare-chat-core 0.1.1 → 0.2.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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "flare-chat-core",
3
3
  "private": false,
4
- "version": "0.1.1",
4
+ "version": "0.2.0",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
7
7
  "module": "./src/index.js",
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env sh
2
+ set -eu
3
+
4
+ SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
5
+ PKG_DIR=$(CDPATH= cd -- "$SCRIPT_DIR/.." && pwd)
6
+
7
+ level="${1:-quick}"
8
+ case "$level" in
9
+ quick|full) ;;
10
+ *) echo "Unsupported level: $level" >&2; exit 2 ;;
11
+ esac
12
+
13
+ find "$PKG_DIR/src" -type f -name '*.js' | while IFS= read -r file; do
14
+ node --check "$file"
15
+ done
@@ -1,5 +1,18 @@
1
1
  import { useState, useCallback } from 'react';
2
2
 
3
+ function buildAttachmentFile(file, index = 0, status = 'ready') {
4
+ return {
5
+ uid: file?.uid || `${Date.now()}-${index}`,
6
+ name: file?.name || `附件-${index + 1}`,
7
+ size: Number.isFinite(file?.size) ? file.size : null,
8
+ type: file?.type || '',
9
+ originFileObj: file?.originFileObj || file || null,
10
+ status: file?.status || status,
11
+ error_message: file?.error_message || '',
12
+ created_at: file?.created_at || new Date().toISOString(),
13
+ };
14
+ }
15
+
3
16
  export function useChatInput() {
4
17
  const [inputValue, setInputValue] = useState('');
5
18
  const [fileList, setFileList] = useState([]);
@@ -23,18 +36,37 @@ export function useChatInput() {
23
36
  setIsDragging(false);
24
37
 
25
38
  const files = Array.from(e.dataTransfer.files);
26
- const newFiles = files.map((file, index) => ({
27
- uid: `${Date.now()}-${index}`,
28
- name: file.name,
29
- size: file.size,
30
- type: file.type,
31
- originFileObj: file,
32
- }));
39
+ const newFiles = files.map((file, index) => buildAttachmentFile(file, index));
33
40
 
34
41
  setFileList((prev) => [...prev, ...newFiles]);
35
42
  return files.length;
36
43
  }, []);
37
44
 
45
+ const appendFiles = useCallback((files = [], options = {}) => {
46
+ const normalized = Array.isArray(files)
47
+ ? files.map((file, index) => buildAttachmentFile(file, index, options.status || 'ready'))
48
+ : [];
49
+ if (normalized.length === 0) {
50
+ return;
51
+ }
52
+ setFileList((prev) => [...prev, ...normalized]);
53
+ }, []);
54
+
55
+ const updateFileStatus = useCallback((uid, status, errorMessage = '') => {
56
+ if (!uid) {
57
+ return;
58
+ }
59
+ setFileList((prev) => prev.map((file) => (
60
+ file.uid === uid
61
+ ? {
62
+ ...file,
63
+ status: status || file.status,
64
+ error_message: errorMessage || '',
65
+ }
66
+ : file
67
+ )));
68
+ }, []);
69
+
38
70
  const handleDragOver = useCallback((e) => {
39
71
  e.preventDefault();
40
72
  e.stopPropagation();
@@ -59,6 +91,8 @@ export function useChatInput() {
59
91
  handleInputChange,
60
92
  handleFileChange,
61
93
  handleRemoveFile,
94
+ appendFiles,
95
+ updateFileStatus,
62
96
  handleDrop,
63
97
  handleDragOver,
64
98
  handleDragLeave,
@@ -67,4 +101,3 @@ export function useChatInput() {
67
101
  }
68
102
 
69
103
  export default useChatInput;
70
-
@@ -1,8 +1,8 @@
1
- export function buildTimelineItems(state = {}) {
1
+ export function buildTimelineItems(state = {}, options = {}) {
2
2
  const messages = Array.isArray(state.messages) ? state.messages : [];
3
- const executionCards = Array.isArray(state.executionCards) ? state.executionCards : [];
4
3
  const uiCards = Array.isArray(state.uiCards) ? state.uiCards : [];
5
4
  const streaming = state.streaming || {};
5
+ const loading = Boolean(options?.loading);
6
6
 
7
7
  const items = [];
8
8
 
@@ -23,21 +23,10 @@ export function buildTimelineItems(state = {}) {
23
23
  createdAt: msg.created_at,
24
24
  highlights: msg.highlights ?? [],
25
25
  sourceTypes: msg.sourceTypes ?? [],
26
+ attachments: Array.isArray(msg.attachments) ? msg.attachments : [],
26
27
  });
27
28
  });
28
29
 
29
- executionCards
30
- .filter(Boolean)
31
- .filter((card) => card.step_id !== streaming.executionTrace?.step_id)
32
- .forEach((card, index) => {
33
- const executionId = card.step_id || `execution-fallback-${index}`;
34
- items.push({
35
- id: executionId,
36
- type: 'execution',
37
- executionTrace: card,
38
- });
39
- });
40
-
41
30
  if (uiCards.length > 0) {
42
31
  items.push({
43
32
  id: 'conversation-ui-cards',
@@ -54,7 +43,8 @@ export function buildTimelineItems(state = {}) {
54
43
  });
55
44
  }
56
45
 
57
- if (streaming.agentStatus || streaming.thinkingTrace || streaming.executionTrace) {
46
+ const hasThinkingSignal = Boolean(streaming.agentStatus || streaming.thinkingTrace || streaming.executionTrace);
47
+ if (hasThinkingSignal) {
58
48
  items.push({
59
49
  id: 'thinking-bubble',
60
50
  type: 'thinking',
@@ -62,6 +52,15 @@ export function buildTimelineItems(state = {}) {
62
52
  thinkingTrace: streaming.thinkingTrace,
63
53
  executionTrace: streaming.executionTrace,
64
54
  });
55
+ } else if (loading && !streaming.content) {
56
+ items.push({
57
+ id: 'thinking-bubble-loading',
58
+ type: 'thinking',
59
+ agentStatus: {
60
+ status: 'running',
61
+ agent: '助手',
62
+ },
63
+ });
65
64
  }
66
65
 
67
66
  return {
@@ -71,4 +70,3 @@ export function buildTimelineItems(state = {}) {
71
70
  }
72
71
 
73
72
  export default buildTimelineItems;
74
-
@@ -321,7 +321,14 @@ export default function useChatSessionReducer(deps = {}) {
321
321
  dispatch({ type: MESSAGES_REFRESHED, payload: messagesWithIds });
322
322
  }, [messageAPI]);
323
323
 
324
- const appendUserMessage = useCallback((content) => {
324
+ const appendUserMessage = useCallback((content, metadata = {}) => {
325
+ const payloadMeta = (
326
+ metadata
327
+ && typeof metadata === 'object'
328
+ && !Array.isArray(metadata)
329
+ )
330
+ ? metadata
331
+ : {};
325
332
  dispatch({
326
333
  type: MESSAGE_APPENDED,
327
334
  payload: {
@@ -329,6 +336,7 @@ export default function useChatSessionReducer(deps = {}) {
329
336
  role: 'user',
330
337
  content,
331
338
  created_at: new Date().toISOString(),
339
+ ...payloadMeta,
332
340
  },
333
341
  });
334
342
  }, []);
@@ -33,6 +33,16 @@ export class SSEClient {
33
33
  const sessionId = params.sessionId;
34
34
  const content = params.content;
35
35
  const enabledCapabilities = Array.isArray(params.enabledCapabilities) ? params.enabledCapabilities : [];
36
+ const modeKey = typeof params.modeKey === 'string' ? params.modeKey.trim() : '';
37
+ const manualModeKey = typeof params.manualModeKey === 'string' ? params.manualModeKey.trim() : '';
38
+ const currentModeKey = typeof params.currentModeKey === 'string' ? params.currentModeKey.trim() : '';
39
+ const payloadExtra = (
40
+ params.payloadExtra
41
+ && typeof params.payloadExtra === 'object'
42
+ && !Array.isArray(params.payloadExtra)
43
+ )
44
+ ? params.payloadExtra
45
+ : {};
36
46
  const onEvent = isObjectCall ? contentArg : onEventArg;
37
47
  const onComplete = isObjectCall ? onEventArg : onCompleteArg;
38
48
  const onError = isObjectCall ? onCompleteArg : onErrorArg;
@@ -50,6 +60,16 @@ export class SSEClient {
50
60
  message: content,
51
61
  session_id: sessionId,
52
62
  enabled_capabilities: enabledCapabilities,
63
+ ...(modeKey ? { mode: modeKey } : {}),
64
+ ...(manualModeKey ? { manual_mode: manualModeKey } : {}),
65
+ ...(currentModeKey ? { current_mode: currentModeKey } : {}),
66
+ payload: {
67
+ message: content,
68
+ ...(modeKey ? { mode: modeKey } : {}),
69
+ ...(manualModeKey ? { manual_mode: manualModeKey } : {}),
70
+ ...(currentModeKey ? { current_mode: currentModeKey } : {}),
71
+ ...payloadExtra,
72
+ },
53
73
  }),
54
74
  signal: this.abortController.signal,
55
75
  });
@@ -120,4 +140,3 @@ export class SSEClient {
120
140
  }
121
141
  }
122
142
  }
123
-
@@ -172,6 +172,7 @@ function pickFirstArray(payload, keys) {
172
172
  export const parseFieldProgress = (raw) => {
173
173
  const payload = resolveModeEventPayload(raw);
174
174
  return {
175
+ flow_state: payload?.flow_state ?? payload?.collection_phase ?? '',
175
176
  fields: payload?.fields ?? {},
176
177
  sources: payload?.sources ?? {},
177
178
  field_entries: Array.isArray(payload?.field_entries) ? payload.field_entries : [],
@@ -197,9 +198,20 @@ export const parseFieldProgress = (raw) => {
197
198
  required_fields: Array.isArray(payload?.required_fields) ? payload.required_fields : [],
198
199
  recommended_fields: Array.isArray(payload?.recommended_fields) ? payload.recommended_fields : [],
199
200
  optional_fields: Array.isArray(payload?.optional_fields) ? payload.optional_fields : [],
201
+ intake_core_fields: Array.isArray(payload?.intake_core_fields) ? payload.intake_core_fields : [],
202
+ intake_supplementary_fields: Array.isArray(payload?.intake_supplementary_fields) ? payload.intake_supplementary_fields : [],
203
+ analysis_enrichment_fields: Array.isArray(payload?.analysis_enrichment_fields) ? payload.analysis_enrichment_fields : [],
200
204
  field_priorities: payload?.field_priorities && typeof payload.field_priorities === 'object' && !Array.isArray(payload.field_priorities)
201
205
  ? payload.field_priorities
202
206
  : {},
207
+ current_question: payload?.current_question && typeof payload.current_question === 'object' && !Array.isArray(payload.current_question)
208
+ ? payload.current_question
209
+ : null,
210
+ question_progress: payload?.question_progress && typeof payload.question_progress === 'object' && !Array.isArray(payload.question_progress)
211
+ ? payload.question_progress
212
+ : { current: 0, total: 0 },
213
+ collection_phase: payload?.collection_phase ?? '',
214
+ required_missing_count: Number.isFinite(payload?.required_missing_count) ? payload.required_missing_count : null,
203
215
  };
204
216
  };
205
217
 
@@ -240,6 +252,7 @@ export const parseNextActions = (raw) => {
240
252
  : (Array.isArray(payload?.next_actions) ? payload.next_actions : []);
241
253
  return {
242
254
  mode_key: payload?.mode_key ?? '',
255
+ flow_state: payload?.flow_state ?? payload?.collection_phase ?? '',
243
256
  project_id: payload?.project_id ?? null,
244
257
  message_excerpt: payload?.message_excerpt ?? '',
245
258
  actions,
@@ -247,9 +260,27 @@ export const parseNextActions = (raw) => {
247
260
  required_missing: Array.isArray(payload?.required_missing) ? payload.required_missing : [],
248
261
  recommended_missing: Array.isArray(payload?.recommended_missing) ? payload.recommended_missing : [],
249
262
  optional_missing: Array.isArray(payload?.optional_missing) ? payload.optional_missing : [],
263
+ intake_core_fields: Array.isArray(payload?.intake_core_fields) ? payload.intake_core_fields : [],
264
+ intake_supplementary_fields: Array.isArray(payload?.intake_supplementary_fields) ? payload.intake_supplementary_fields : [],
265
+ analysis_enrichment_fields: Array.isArray(payload?.analysis_enrichment_fields) ? payload.analysis_enrichment_fields : [],
250
266
  ready_for_sourcing: payload?.ready_for_sourcing ?? null,
251
267
  status: payload?.status ?? '',
252
268
  reason: payload?.reason ?? '',
269
+ chooser_required: payload?.chooser_required === true,
270
+ blocking_reason: payload?.blocking_reason ?? '',
271
+ blocking: payload?.blocking && typeof payload.blocking === 'object' && !Array.isArray(payload.blocking)
272
+ ? payload.blocking
273
+ : null,
274
+ target_field: payload?.target_field ?? '',
275
+ degrade_reason: Array.isArray(payload?.degrade_reason) ? payload.degrade_reason : [],
276
+ current_question: payload?.current_question && typeof payload.current_question === 'object' && !Array.isArray(payload.current_question)
277
+ ? payload.current_question
278
+ : null,
279
+ question_progress: payload?.question_progress && typeof payload.question_progress === 'object' && !Array.isArray(payload.question_progress)
280
+ ? payload.question_progress
281
+ : { current: 0, total: 0 },
282
+ collection_phase: payload?.collection_phase ?? '',
283
+ required_missing_count: Number.isFinite(payload?.required_missing_count) ? payload.required_missing_count : null,
253
284
  render_hint: payload?.render_hint ?? 'next_actions',
254
285
  };
255
286
  };
@@ -378,6 +409,110 @@ export const parseEvaluationReportReady = (raw) => {
378
409
  };
379
410
  };
380
411
 
412
+ export const parsePlanBlock = (raw) => {
413
+ const payload = resolveModeEventPayload(raw);
414
+ return {
415
+ ...payload,
416
+ constraints: Array.isArray(payload?.constraints) ? payload.constraints : [],
417
+ plan: Array.isArray(payload?.plan) ? payload.plan : [],
418
+ acceptance: Array.isArray(payload?.acceptance) ? payload.acceptance : [],
419
+ actions: Array.isArray(payload?.actions) ? payload.actions : [],
420
+ };
421
+ };
422
+
423
+ export const parseCanvasState = (raw) => {
424
+ const payload = resolveModeEventPayload(raw);
425
+ const canvasState = payload?.canvas_state && typeof payload.canvas_state === 'object' && !Array.isArray(payload.canvas_state)
426
+ ? payload.canvas_state
427
+ : {};
428
+ return {
429
+ ...payload,
430
+ canvas_state: {
431
+ ...canvasState,
432
+ versions: Array.isArray(canvasState.versions) ? canvasState.versions : [],
433
+ },
434
+ };
435
+ };
436
+
437
+ export const parseCanvasRevision = (raw) => {
438
+ const payload = resolveModeEventPayload(raw);
439
+ return {
440
+ ...payload,
441
+ actions: Array.isArray(payload?.actions) ? payload.actions : [],
442
+ };
443
+ };
444
+
445
+ export const parseKnowledgeSearch = (raw) => {
446
+ const payload = resolveModeEventPayload(raw);
447
+ const sourceBreakdown = payload?.source_breakdown && typeof payload.source_breakdown === 'object'
448
+ && !Array.isArray(payload.source_breakdown)
449
+ ? payload.source_breakdown
450
+ : {};
451
+ return {
452
+ ...payload,
453
+ run_id: payload?.run_id ?? '',
454
+ query: payload?.query ?? '',
455
+ result_count: Number.isFinite(payload?.result_count) ? payload.result_count : null,
456
+ source_breakdown: {
457
+ local: Number.isFinite(sourceBreakdown.local) ? sourceBreakdown.local : 0,
458
+ mcp: Number.isFinite(sourceBreakdown.mcp) ? sourceBreakdown.mcp : 0,
459
+ web: Number.isFinite(sourceBreakdown.web) ? sourceBreakdown.web : 0,
460
+ },
461
+ results: Array.isArray(payload?.results) ? payload.results : [],
462
+ };
463
+ };
464
+
465
+ export const parseKnowledgeCitation = (raw) => {
466
+ const payload = resolveModeEventPayload(raw);
467
+ return {
468
+ ...payload,
469
+ run_id: payload?.run_id ?? '',
470
+ citations: Array.isArray(payload?.citations) ? payload.citations : [],
471
+ };
472
+ };
473
+
474
+ export const parseOrchestrationStatus = (raw) => {
475
+ const payload = resolveModeEventPayload(raw);
476
+ return {
477
+ trace_id: payload?.trace_id ?? '',
478
+ current_stage: payload?.current_stage ?? '',
479
+ detected_intent: payload?.detected_intent && typeof payload.detected_intent === 'object' && !Array.isArray(payload.detected_intent)
480
+ ? payload.detected_intent
481
+ : {},
482
+ confirmed_updates: Array.isArray(payload?.confirmed_updates) ? payload.confirmed_updates : [],
483
+ open_fields: Array.isArray(payload?.open_fields) ? payload.open_fields : [],
484
+ search_actions: Array.isArray(payload?.search_actions) ? payload.search_actions : [],
485
+ workspace_updates: payload?.workspace_updates && typeof payload.workspace_updates === 'object' && !Array.isArray(payload.workspace_updates)
486
+ ? payload.workspace_updates
487
+ : {},
488
+ next_action: payload?.next_action && typeof payload.next_action === 'object' && !Array.isArray(payload.next_action)
489
+ ? payload.next_action
490
+ : {},
491
+ next_actions: Array.isArray(payload?.next_actions) ? payload.next_actions : [],
492
+ chooser: payload?.chooser && typeof payload.chooser === 'object' && !Array.isArray(payload.chooser)
493
+ ? payload.chooser
494
+ : null,
495
+ stage_transition: payload?.stage_transition && typeof payload.stage_transition === 'object' && !Array.isArray(payload.stage_transition)
496
+ ? payload.stage_transition
497
+ : {},
498
+ decision_basis: Array.isArray(payload?.decision_basis) ? payload.decision_basis : [],
499
+ blocking: payload?.blocking && typeof payload.blocking === 'object' && !Array.isArray(payload.blocking)
500
+ ? payload.blocking
501
+ : {},
502
+ node: payload?.node && typeof payload.node === 'object' && !Array.isArray(payload.node)
503
+ ? payload.node
504
+ : {},
505
+ node_id: payload?.node_id ?? '',
506
+ node_state: payload?.node_state ?? '',
507
+ node_reason: payload?.node_reason ?? '',
508
+ needs_user_choice: payload?.needs_user_choice === true,
509
+ degrade_reason: Array.isArray(payload?.degrade_reason) ? payload.degrade_reason : [],
510
+ content_policy: payload?.content_policy && typeof payload.content_policy === 'object' && !Array.isArray(payload.content_policy)
511
+ ? payload.content_policy
512
+ : {},
513
+ };
514
+ };
515
+
381
516
  export const parseWorkspaceActivation = (raw) => ({
382
517
  function_type: raw?.function_type ?? '',
383
518
  mode: raw?.mode ?? '',
@@ -420,6 +555,44 @@ export const parseInstanceProfile = (raw) => ({
420
555
  ui_labels: raw?.instance_profile?.ui_labels ?? raw?.ui_labels ?? {},
421
556
  });
422
557
 
558
+ export const parseModeRuntime = (raw) => ({
559
+ mode_key: raw?.mode_key ?? '',
560
+ mode_state: raw?.mode_state ?? '',
561
+ });
562
+
563
+ export const parseAgentRuntime = (raw) => ({
564
+ trace_id: raw?.trace_id ?? '',
565
+ session_id: raw?.session_id ?? '',
566
+ intent: raw?.intent ?? '',
567
+ function_type: raw?.function_type ?? '',
568
+ mode_key: raw?.mode_key ?? '',
569
+ mode_state: raw?.mode_state ?? '',
570
+ agent_step_count: Number.isFinite(raw?.agent_step_count) ? raw.agent_step_count : 0,
571
+ agent_step: Array.isArray(raw?.agent_step) ? raw.agent_step : [],
572
+ });
573
+
574
+ export const parseSkillRuntime = (raw) => ({
575
+ trace_id: raw?.trace_id ?? '',
576
+ session_id: raw?.session_id ?? '',
577
+ intent: raw?.intent ?? '',
578
+ function_type: raw?.function_type ?? '',
579
+ mode_key: raw?.mode_key ?? '',
580
+ mode_state: raw?.mode_state ?? '',
581
+ skill_call_count: Number.isFinite(raw?.skill_call_count) ? raw.skill_call_count : 0,
582
+ skill_call: Array.isArray(raw?.skill_call) ? raw.skill_call : [],
583
+ });
584
+
585
+ export const parseModeSwitchReason = (raw) => ({
586
+ mode_key: raw?.mode_key ?? '',
587
+ intent: raw?.intent ?? '',
588
+ source: raw?.source ?? '',
589
+ previous_mode: raw?.previous_mode ?? '',
590
+ manual_mode: raw?.manual_mode ?? '',
591
+ current_mode: raw?.current_mode ?? '',
592
+ intent_override: raw?.intent_override ?? '',
593
+ summary: raw?.summary ?? '',
594
+ });
595
+
423
596
  export const parseSSEError = (raw) => ({
424
597
  message: raw?.message ?? '发生错误',
425
598
  });
@@ -21,6 +21,16 @@ import {
21
21
  parseCapabilitySuggestion,
22
22
  parseFieldsUpdated,
23
23
  parseInstanceProfile,
24
+ parseModeRuntime,
25
+ parseAgentRuntime,
26
+ parseSkillRuntime,
27
+ parseModeSwitchReason,
28
+ parseKnowledgeSearch,
29
+ parseKnowledgeCitation,
30
+ parseOrchestrationStatus,
31
+ parseCanvasState,
32
+ parseCanvasRevision,
33
+ parsePlanBlock,
24
34
  parseSSEError,
25
35
  } from './sse-events.js';
26
36
 
@@ -69,6 +79,16 @@ export function useSSEStream(sessionId) {
69
79
  onCategoryIdentified,
70
80
  onFieldsUpdated,
71
81
  onInstanceProfile,
82
+ onModeRuntime,
83
+ onAgentRuntime,
84
+ onSkillRuntime,
85
+ onModeSwitchReason,
86
+ onKnowledgeSearch,
87
+ onKnowledgeCitation,
88
+ onOrchestrationStatus,
89
+ onCanvasState,
90
+ onCanvasRevision,
91
+ onPlanBlock,
72
92
  onDoc,
73
93
  onCapabilitySuggestion,
74
94
  onError,
@@ -138,6 +158,36 @@ export function useSSEStream(sessionId) {
138
158
  case 'instance_profile':
139
159
  onInstanceProfile?.(parseInstanceProfile(event.data));
140
160
  break;
161
+ case 'mode_runtime':
162
+ onModeRuntime?.(parseModeRuntime(event.data));
163
+ break;
164
+ case 'agent_runtime':
165
+ onAgentRuntime?.(parseAgentRuntime(event.data));
166
+ break;
167
+ case 'skill_runtime':
168
+ onSkillRuntime?.(parseSkillRuntime(event.data));
169
+ break;
170
+ case 'mode_switch_reason':
171
+ onModeSwitchReason?.(parseModeSwitchReason(event.data));
172
+ break;
173
+ case 'knowledge_search':
174
+ onKnowledgeSearch?.(parseKnowledgeSearch(event.data));
175
+ break;
176
+ case 'knowledge_citation':
177
+ onKnowledgeCitation?.(parseKnowledgeCitation(event.data));
178
+ break;
179
+ case 'orchestration_status':
180
+ onOrchestrationStatus?.(parseOrchestrationStatus(event.data));
181
+ break;
182
+ case 'canvas_state':
183
+ onCanvasState?.(parseCanvasState(event.data));
184
+ break;
185
+ case 'canvas_revision':
186
+ onCanvasRevision?.(parseCanvasRevision(event.data));
187
+ break;
188
+ case 'plan_block':
189
+ onPlanBlock?.(parsePlanBlock(event.data));
190
+ break;
141
191
  case 'doc':
142
192
  onDoc?.(parseDoc(event.data));
143
193
  break;
@@ -170,6 +220,16 @@ export function useSSEStream(sessionId) {
170
220
  sessionId: resolvedSessionId,
171
221
  content,
172
222
  enabledCapabilities: Array.isArray(options.enabledCapabilities) ? options.enabledCapabilities : [],
223
+ modeKey: typeof options.modeKey === 'string' ? options.modeKey : '',
224
+ manualModeKey: typeof options.manualModeKey === 'string' ? options.manualModeKey : '',
225
+ currentModeKey: typeof options.currentModeKey === 'string' ? options.currentModeKey : '',
226
+ payloadExtra: (
227
+ options.payloadExtra
228
+ && typeof options.payloadExtra === 'object'
229
+ && !Array.isArray(options.payloadExtra)
230
+ )
231
+ ? options.payloadExtra
232
+ : {},
173
233
  endpoint: options.endpoint,
174
234
  baseUrl: options.baseUrl,
175
235
  url: options.url,
@@ -178,6 +238,10 @@ export function useSSEStream(sessionId) {
178
238
  if (!requestOptions.enabledCapabilities.length) {
179
239
  delete requestOptions.enabledCapabilities;
180
240
  }
241
+ if (!requestOptions.modeKey) delete requestOptions.modeKey;
242
+ if (!requestOptions.manualModeKey) delete requestOptions.manualModeKey;
243
+ if (!requestOptions.currentModeKey) delete requestOptions.currentModeKey;
244
+ if (!Object.keys(requestOptions.payloadExtra || {}).length) delete requestOptions.payloadExtra;
181
245
 
182
246
  if (!requestOptions.endpoint) delete requestOptions.endpoint;
183
247
  if (!requestOptions.baseUrl) delete requestOptions.baseUrl;