flare-chat-core 0.2.3 → 0.2.5
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 +6372 -0
- package/package.json +19 -22
- package/docs/CAPABILITY-INVENTORY.md +0 -42
- package/docs/CHAT-CORE-BOUNDARY.md +0 -47
- package/docs/CORE-APP-REALIGNMENT-WORKLOAD-2026-04-18.md +0 -86
- package/docs/SSOT-CHAT-CORE-BOUNDARY.md +0 -73
- package/docs/SSOT-CHAT-CORE-DATAFLOW.md +0 -97
- package/index.html +0 -12
- package/scripts/check.sh +0 -15
- package/src/adapters/index.js +0 -6
- package/src/adapters/message-api.adapter.js +0 -59
- package/src/adapters/session-api.adapter.js +0 -133
- package/src/adapters/session-message-api.http.js +0 -161
- package/src/adapters/session-message-api.js +0 -34
- package/src/adapters/session-message-api.normalize-source-record.test.mjs +0 -180
- package/src/adapters/session-message-api.normalizers.js +0 -153
- package/src/adapters/source-api.adapter.js +0 -135
- package/src/adapters/sse-client.js +0 -244
- package/src/adapters/sse-event-dispatcher.js +0 -121
- package/src/app/App.jsx +0 -11
- package/src/app/AppProviders.jsx +0 -12
- package/src/app/ChatWorkspaceScreen.jsx +0 -33
- package/src/app/WorkspaceLayout.jsx +0 -190
- package/src/app/components/AppCanvasPanel.jsx +0 -64
- package/src/app/components/TriggerThresholdPopoverContent.jsx +0 -122
- package/src/app/components/WorkspaceBodySection.jsx +0 -156
- package/src/app/components/WorkspaceMainPane.jsx +0 -121
- package/src/app/components/WorkspaceSessionPane.jsx +0 -70
- package/src/app/components/WorkspaceTopBarSection.jsx +0 -71
- package/src/app/core-chat-entry/ComposerSectionNode.jsx +0 -241
- package/src/app/core-chat-entry/attachmentSendRefs.js +0 -154
- package/src/app/core-chat-entry/attachmentSendRefs.test.mjs +0 -101
- package/src/app/core-chat-entry/composerActionRouter.js +0 -26
- package/src/app/core-chat-entry/constants.js +0 -108
- package/src/app/core-chat-entry/selectors.js +0 -28
- package/src/app/core-chat-entry/useAppActionErrorGuards.js +0 -68
- package/src/app/core-chat-entry/useChatCorePipelines.js +0 -110
- package/src/app/core-chat-entry/useComposerModeSuggestion.js +0 -89
- package/src/app/core-chat-entry/useDevCapabilityStatusNote.js +0 -22
- package/src/app/core-chat-entry/useProjectNameEditing.js +0 -41
- package/src/app/core-chat-entry/useProjectSourceUpload.js +0 -341
- package/src/app/core-chat-entry/useRealApiReadinessGate.js +0 -103
- package/src/app/core-chat-entry/useUnavailableActionError.js +0 -29
- package/src/app/core-chat-entry/useWorkspaceCanvasController.jsx +0 -177
- package/src/app/core-chat-entry/useWorkspaceCanvasProjection.jsx +0 -171
- package/src/app/core-chat-entry/useWorkspaceComposerController.jsx +0 -199
- package/src/app/core-chat-entry/useWorkspaceController.jsx +0 -226
- package/src/app/core-chat-entry/useWorkspacePanels.js +0 -55
- package/src/app/hooks/useComposerAttachmentSync.js +0 -223
- package/src/app/hooks/useComposerChooserHandlers.js +0 -52
- package/src/app/hooks/useSendWithContextRefs.js +0 -140
- package/src/app/hooks/useSendWithContextRefs.test.mjs +0 -29
- package/src/app/hooks/useUserThresholdProfile.js +0 -121
- package/src/app/index.js +0 -1
- package/src/app/selectors/assistantTextSelector.js +0 -73
- package/src/app/selectors/canvasEvidenceSummarySelector.js +0 -28
- package/src/app/selectors/canvasReportTemplateSelector.js +0 -28
- package/src/app/selectors/canvasTabsSelector.js +0 -58
- package/src/app/selectors/evidenceProjectionSelector.js +0 -175
- package/src/app/selectors/evidenceProjectionSelector.test.mjs +0 -107
- package/src/app/selectors/modeSuggestionSelector.js +0 -50
- package/src/chat-core/app/mockRuntime.js +0 -291
- package/src/chat-core/app/useAppStream.js +0 -187
- package/src/chat-core/app/useAppStream.refs.test.mjs +0 -44
- package/src/chat-core/app/useAppStream.request-body.test.mjs +0 -116
- package/src/chat-core/app/useCoreChatApp.js +0 -115
- package/src/chat-core/facade/useBasicConversationFacade.js +0 -280
- package/src/chat-core/index.js +0 -14
- package/src/chat-core/input/useChatInput.js +0 -103
- package/src/chat-core/messages/buildTimelineItems.analysis-route.test.mjs +0 -36
- package/src/chat-core/messages/buildTimelineItems.js +0 -201
- package/src/chat-core/messages/buildTimelineItems.knowledge-citation.test.mjs +0 -182
- package/src/chat-core/messages/contextUsageDefaults.js +0 -3
- package/src/chat-core/messages/contextUsageViewModel.js +0 -147
- package/src/chat-core/messages/contextUsageViewModel.test.mjs +0 -74
- package/src/chat-core/messages/useContextUsageViewModel.js +0 -41
- package/src/chat-core/orchestration/useBasicSendHandler.js +0 -55
- package/src/chat-core/pipelines/build-action-request.js +0 -46
- package/src/chat-core/pipelines/build-stream-request.js +0 -74
- package/src/chat-core/pipelines/entity-extraction.js +0 -159
- package/src/chat-core/pipelines/preprocess-message.js +0 -16
- package/src/chat-core/pipelines/stream-persist-utils.js +0 -32
- package/src/chat-core/pipelines/transport/send-mock-stream.js +0 -86
- package/src/chat-core/pipelines/transport/send-real-stream.js +0 -330
- package/src/chat-core/pipelines/transport/send-real-stream.test.mjs +0 -27
- package/src/chat-core/pipelines/transport/send-sourcing-search.js +0 -86
- package/src/chat-core/pipelines/transport/send-sourcing-search.test.mjs +0 -14
- package/src/chat-core/pipelines/transport/sourcing-response-templates.js +0 -55
- package/src/chat-core/pipelines/transport/sourcing-search-api.js +0 -155
- package/src/chat-core/runtime/runtimeMode.js +0 -69
- package/src/chat-core/session/chatSessionActionTypes.js +0 -24
- package/src/chat-core/session/chatSessionReducer.js +0 -352
- package/src/chat-core/session/chatSessionReducer.streaming-done.test.mjs +0 -39
- package/src/chat-core/session/index.js +0 -2
- package/src/chat-core/session/sessionActionsMessages.js +0 -44
- package/src/chat-core/session/sessionActionsSessionCrud.js +0 -131
- package/src/chat-core/session/sessionActionsStreaming.js +0 -80
- package/src/chat-core/session/sessionActionsUiState.js +0 -51
- package/src/chat-core/session/useChatSessionReducer.js +0 -131
- package/src/chat-core/session/useSessionListController.js +0 -67
- package/src/chat-core/stream/sse-client.js +0 -1
- package/src/chat-core/stream/sse-event-dispatcher.js +0 -1
- package/src/chat-core/stream/sse-events.js +0 -1
- package/src/chat-core/stream/useSSEStream.js +0 -1
- package/src/chat-core/stream/useStreamSendController.js +0 -46
- package/src/contracts/context-ssot.js +0 -47
- package/src/contracts/index.js +0 -1
- package/src/contracts/sse-events/base-parsers.js +0 -79
- package/src/contracts/sse-events/domain-parsers.js +0 -3
- package/src/contracts/sse-events/internal-normalizers.js +0 -143
- package/src/contracts/sse-events/parsers-intake.js +0 -235
- package/src/contracts/sse-events/parsers-runtime.js +0 -37
- package/src/contracts/sse-events/parsers-sourcing.js +0 -179
- package/src/contracts/sse-events/patch-event-parser.js +0 -121
- package/src/contracts/sse-events/runtime-parsers.js +0 -79
- package/src/contracts/sse-events.js +0 -4
- package/src/index.js +0 -6
- package/src/main.jsx +0 -28
- package/src/orchestration/index.js +0 -6
- package/src/orchestration/useSSEStream.js +0 -221
- package/src/state/index.js +0 -4
- package/vite.config.js +0 -36
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Core runtime mode + debug gating.
|
|
3
|
-
*
|
|
4
|
-
* Env contract:
|
|
5
|
-
* - VITE_FLARE_CHAT_RUNTIME_MODE: optional override, "development" | "production"
|
|
6
|
-
* - VITE_FLARE_CHAT_DEBUG: optional debug switch, "1" | "true" enables debug logs
|
|
7
|
-
*
|
|
8
|
-
* Safety rule:
|
|
9
|
-
* - Debug logs are allowed only when runtime mode is non-production.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
function toBooleanFlag(value) {
|
|
13
|
-
const normalized = String(value ?? '').trim().toLowerCase();
|
|
14
|
-
return normalized === '1' || normalized === 'true' || normalized === 'yes' || normalized === 'on';
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function normalizeMode(value) {
|
|
18
|
-
const normalized = String(value ?? '').trim().toLowerCase();
|
|
19
|
-
if (normalized === 'production' || normalized === 'prod') {
|
|
20
|
-
return 'production';
|
|
21
|
-
}
|
|
22
|
-
if (normalized === 'development' || normalized === 'dev') {
|
|
23
|
-
return 'development';
|
|
24
|
-
}
|
|
25
|
-
return '';
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export function resolveRuntimeMode(envInput) {
|
|
29
|
-
const env = (
|
|
30
|
-
envInput
|
|
31
|
-
&& typeof envInput === 'object'
|
|
32
|
-
&& !Array.isArray(envInput)
|
|
33
|
-
) ? envInput : (import.meta?.env || {});
|
|
34
|
-
|
|
35
|
-
const overrideMode = normalizeMode(env.VITE_FLARE_CHAT_RUNTIME_MODE);
|
|
36
|
-
const modeFromVite = normalizeMode(env.MODE);
|
|
37
|
-
const fallbackMode = env.PROD === true ? 'production' : 'development';
|
|
38
|
-
const mode = overrideMode || modeFromVite || fallbackMode;
|
|
39
|
-
const isProduction = mode === 'production';
|
|
40
|
-
const isDevelopment = !isProduction;
|
|
41
|
-
const debugRequested = toBooleanFlag(env.VITE_FLARE_CHAT_DEBUG);
|
|
42
|
-
const debugEnabled = isDevelopment && debugRequested;
|
|
43
|
-
|
|
44
|
-
return {
|
|
45
|
-
mode,
|
|
46
|
-
isProduction,
|
|
47
|
-
isDevelopment,
|
|
48
|
-
debugEnabled,
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const runtimeMode = resolveRuntimeMode();
|
|
53
|
-
|
|
54
|
-
export function getCoreRuntimeMode() {
|
|
55
|
-
return runtimeMode;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export function isCoreDebugEnabled() {
|
|
59
|
-
return runtimeMode.debugEnabled;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export function debugCoreLog(...args) {
|
|
63
|
-
if (!runtimeMode.debugEnabled) {
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
console.debug('[flare-chat-core:debug]', ...args);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export default getCoreRuntimeMode;
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
export const SESSION_LOADED = 'SESSION_LOADED';
|
|
2
|
-
export const SESSION_RESET = 'SESSION_RESET';
|
|
3
|
-
export const SESSION_ERROR = 'SESSION_ERROR';
|
|
4
|
-
export const TITLE_UPDATED = 'TITLE_UPDATED';
|
|
5
|
-
export const MESSAGES_REFRESHED = 'MESSAGES_REFRESHED';
|
|
6
|
-
export const MESSAGE_APPENDED = 'MESSAGE_APPENDED';
|
|
7
|
-
export const STREAMING_RESET = 'STREAMING_RESET';
|
|
8
|
-
export const STREAMING_CHUNK = 'STREAMING_CHUNK';
|
|
9
|
-
export const STREAMING_REPLACE = 'STREAMING_REPLACE';
|
|
10
|
-
export const AGENT_STATUS_SET = 'AGENT_STATUS_SET';
|
|
11
|
-
export const THINKING_TRACE_SET = 'THINKING_TRACE_SET';
|
|
12
|
-
export const EXECUTION_TRACE_SET = 'EXECUTION_TRACE_SET';
|
|
13
|
-
export const STREAM_KNOWLEDGE_SEARCH_SET = 'STREAM_KNOWLEDGE_SEARCH_SET';
|
|
14
|
-
export const STREAM_SOURCING_CANDIDATES_SET = 'STREAM_SOURCING_CANDIDATES_SET';
|
|
15
|
-
export const STREAM_KNOWLEDGE_CITATION_SET = 'STREAM_KNOWLEDGE_CITATION_SET';
|
|
16
|
-
export const STREAMING_DONE = 'STREAMING_DONE';
|
|
17
|
-
export const DOC_GENERATED = 'DOC_GENERATED';
|
|
18
|
-
export const LEGEND_HINT_SHOWN = 'LEGEND_HINT_SHOWN';
|
|
19
|
-
export const EXECUTION_CARD_UPSERTED = 'EXECUTION_CARD_UPSERTED';
|
|
20
|
-
export const UI_CARDS_SET = 'UI_CARDS_SET';
|
|
21
|
-
export const LAST_USER_MESSAGE_SET = 'LAST_USER_MESSAGE_SET';
|
|
22
|
-
export const UI_CARD_UPDATED = 'UI_CARD_UPDATED';
|
|
23
|
-
export const INSTANCE_PROFILE_SET = 'INSTANCE_PROFILE_SET';
|
|
24
|
-
export const SESSION_PROMOTED = 'SESSION_PROMOTED';
|
|
@@ -1,352 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
SESSION_LOADED,
|
|
3
|
-
SESSION_RESET,
|
|
4
|
-
SESSION_ERROR,
|
|
5
|
-
TITLE_UPDATED,
|
|
6
|
-
MESSAGES_REFRESHED,
|
|
7
|
-
MESSAGE_APPENDED,
|
|
8
|
-
STREAMING_RESET,
|
|
9
|
-
STREAMING_CHUNK,
|
|
10
|
-
STREAMING_REPLACE,
|
|
11
|
-
AGENT_STATUS_SET,
|
|
12
|
-
THINKING_TRACE_SET,
|
|
13
|
-
EXECUTION_TRACE_SET,
|
|
14
|
-
STREAM_KNOWLEDGE_SEARCH_SET,
|
|
15
|
-
STREAM_SOURCING_CANDIDATES_SET,
|
|
16
|
-
STREAM_KNOWLEDGE_CITATION_SET,
|
|
17
|
-
STREAMING_DONE,
|
|
18
|
-
DOC_GENERATED,
|
|
19
|
-
LEGEND_HINT_SHOWN,
|
|
20
|
-
EXECUTION_CARD_UPSERTED,
|
|
21
|
-
UI_CARDS_SET,
|
|
22
|
-
LAST_USER_MESSAGE_SET,
|
|
23
|
-
UI_CARD_UPDATED,
|
|
24
|
-
INSTANCE_PROFILE_SET,
|
|
25
|
-
SESSION_PROMOTED,
|
|
26
|
-
} from './chatSessionActionTypes.js';
|
|
27
|
-
|
|
28
|
-
export const initialStreaming = {
|
|
29
|
-
content: '',
|
|
30
|
-
agentStatus: null,
|
|
31
|
-
thinkingTrace: '',
|
|
32
|
-
executionTrace: null,
|
|
33
|
-
knowledgeSearch: null,
|
|
34
|
-
sourcingCandidates: null,
|
|
35
|
-
knowledgeCitation: null,
|
|
36
|
-
roundKey: '',
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
export const initialState = {
|
|
40
|
-
sessionId: null,
|
|
41
|
-
sessionTitle: '',
|
|
42
|
-
sessionStatus: 'active',
|
|
43
|
-
sessionDetail: null,
|
|
44
|
-
instanceProfile: null,
|
|
45
|
-
messages: [],
|
|
46
|
-
executionCards: [],
|
|
47
|
-
uiCards: [],
|
|
48
|
-
lastUserMessage: '',
|
|
49
|
-
generatedDoc: null,
|
|
50
|
-
streaming: initialStreaming,
|
|
51
|
-
sessionError: null,
|
|
52
|
-
legendHintsShown: {
|
|
53
|
-
knowledge_base: false,
|
|
54
|
-
ai: false,
|
|
55
|
-
},
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
export function reducer(state, { type, payload }) {
|
|
59
|
-
switch (type) {
|
|
60
|
-
case SESSION_LOADED: {
|
|
61
|
-
const {
|
|
62
|
-
sessionId,
|
|
63
|
-
title,
|
|
64
|
-
status,
|
|
65
|
-
messages,
|
|
66
|
-
detail,
|
|
67
|
-
} = payload;
|
|
68
|
-
return {
|
|
69
|
-
...state,
|
|
70
|
-
sessionId,
|
|
71
|
-
sessionTitle: title,
|
|
72
|
-
sessionStatus: status || 'active',
|
|
73
|
-
sessionDetail: (detail && typeof detail === 'object' && !Array.isArray(detail)) ? detail : null,
|
|
74
|
-
instanceProfile: state.instanceProfile,
|
|
75
|
-
messages,
|
|
76
|
-
executionCards: [],
|
|
77
|
-
uiCards: [],
|
|
78
|
-
lastUserMessage: '',
|
|
79
|
-
generatedDoc: null,
|
|
80
|
-
streaming: initialStreaming,
|
|
81
|
-
legendHintsShown: initialState.legendHintsShown,
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
case SESSION_RESET:
|
|
86
|
-
return { ...initialState, instanceProfile: state.instanceProfile };
|
|
87
|
-
|
|
88
|
-
case SESSION_ERROR:
|
|
89
|
-
return { ...state, sessionError: payload };
|
|
90
|
-
|
|
91
|
-
case TITLE_UPDATED:
|
|
92
|
-
return { ...state, sessionTitle: payload };
|
|
93
|
-
|
|
94
|
-
case MESSAGES_REFRESHED:
|
|
95
|
-
return { ...state, messages: payload };
|
|
96
|
-
|
|
97
|
-
case MESSAGE_APPENDED:
|
|
98
|
-
return {
|
|
99
|
-
...state,
|
|
100
|
-
messages: [...state.messages, payload],
|
|
101
|
-
lastUserMessage: payload.role === 'user' ? payload.content : state.lastUserMessage,
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
case LAST_USER_MESSAGE_SET:
|
|
105
|
-
return { ...state, lastUserMessage: payload };
|
|
106
|
-
|
|
107
|
-
case UI_CARDS_SET:
|
|
108
|
-
return { ...state, uiCards: payload };
|
|
109
|
-
|
|
110
|
-
case UI_CARD_UPDATED: {
|
|
111
|
-
const nextCard = payload;
|
|
112
|
-
return {
|
|
113
|
-
...state,
|
|
114
|
-
uiCards: state.uiCards.map((card) =>
|
|
115
|
-
card.id === nextCard.id ? { ...card, ...nextCard } : card
|
|
116
|
-
),
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
case INSTANCE_PROFILE_SET:
|
|
121
|
-
return { ...state, instanceProfile: payload };
|
|
122
|
-
|
|
123
|
-
case SESSION_PROMOTED: {
|
|
124
|
-
const sessionId = String(payload?.sessionId || '').trim();
|
|
125
|
-
if (!sessionId) {
|
|
126
|
-
return state;
|
|
127
|
-
}
|
|
128
|
-
const title = String(payload?.title || '').trim();
|
|
129
|
-
const detailPayload = (
|
|
130
|
-
payload?.detail
|
|
131
|
-
&& typeof payload.detail === 'object'
|
|
132
|
-
&& !Array.isArray(payload.detail)
|
|
133
|
-
) ? payload.detail : null;
|
|
134
|
-
const nextDetail = detailPayload
|
|
135
|
-
? {
|
|
136
|
-
...(state.sessionDetail && typeof state.sessionDetail === 'object' ? state.sessionDetail : {}),
|
|
137
|
-
...detailPayload,
|
|
138
|
-
sessionId,
|
|
139
|
-
}
|
|
140
|
-
: (
|
|
141
|
-
state.sessionDetail && typeof state.sessionDetail === 'object'
|
|
142
|
-
? {
|
|
143
|
-
...state.sessionDetail,
|
|
144
|
-
sessionId,
|
|
145
|
-
}
|
|
146
|
-
: null
|
|
147
|
-
);
|
|
148
|
-
return {
|
|
149
|
-
...state,
|
|
150
|
-
sessionId,
|
|
151
|
-
sessionTitle: title || state.sessionTitle,
|
|
152
|
-
sessionStatus: String(payload?.status || state.sessionStatus || 'active'),
|
|
153
|
-
sessionDetail: nextDetail,
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
case EXECUTION_CARD_UPSERTED: {
|
|
158
|
-
const nextCard = payload;
|
|
159
|
-
const cardKey = nextCard.step_id || `${nextCard.agent}-${nextCard.label}-${nextCard.stage}`;
|
|
160
|
-
const existingIndex = state.executionCards.findIndex((card) => {
|
|
161
|
-
const existingKey = card.step_id || `${card.agent}-${card.label}-${card.stage}`;
|
|
162
|
-
return existingKey === cardKey;
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
const updatedCards = existingIndex >= 0
|
|
166
|
-
? state.executionCards.map((card, index) =>
|
|
167
|
-
index === existingIndex ? { ...card, ...nextCard } : card
|
|
168
|
-
)
|
|
169
|
-
: [...state.executionCards, nextCard];
|
|
170
|
-
|
|
171
|
-
return {
|
|
172
|
-
...state,
|
|
173
|
-
executionCards: updatedCards.slice(-6),
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
case STREAMING_RESET:
|
|
178
|
-
return { ...state, streaming: initialStreaming };
|
|
179
|
-
|
|
180
|
-
case STREAMING_CHUNK:
|
|
181
|
-
return {
|
|
182
|
-
...state,
|
|
183
|
-
streaming: {
|
|
184
|
-
...state.streaming,
|
|
185
|
-
content: state.streaming.content + payload,
|
|
186
|
-
},
|
|
187
|
-
};
|
|
188
|
-
|
|
189
|
-
case STREAMING_REPLACE:
|
|
190
|
-
return {
|
|
191
|
-
...state,
|
|
192
|
-
streaming: {
|
|
193
|
-
...state.streaming,
|
|
194
|
-
content: String(payload || ''),
|
|
195
|
-
},
|
|
196
|
-
};
|
|
197
|
-
|
|
198
|
-
case AGENT_STATUS_SET:
|
|
199
|
-
return {
|
|
200
|
-
...state,
|
|
201
|
-
streaming: { ...state.streaming, agentStatus: payload },
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
case THINKING_TRACE_SET:
|
|
205
|
-
return {
|
|
206
|
-
...state,
|
|
207
|
-
streaming: { ...state.streaming, thinkingTrace: payload },
|
|
208
|
-
};
|
|
209
|
-
|
|
210
|
-
case EXECUTION_TRACE_SET:
|
|
211
|
-
return {
|
|
212
|
-
...state,
|
|
213
|
-
streaming: {
|
|
214
|
-
...state.streaming,
|
|
215
|
-
executionTrace: {
|
|
216
|
-
...state.streaming.executionTrace,
|
|
217
|
-
...payload,
|
|
218
|
-
},
|
|
219
|
-
},
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
case STREAM_KNOWLEDGE_SEARCH_SET:
|
|
223
|
-
return {
|
|
224
|
-
...state,
|
|
225
|
-
streaming: {
|
|
226
|
-
...state.streaming,
|
|
227
|
-
knowledgeSearch: (
|
|
228
|
-
payload
|
|
229
|
-
&& typeof payload === 'object'
|
|
230
|
-
&& !Array.isArray(payload)
|
|
231
|
-
) ? payload : null,
|
|
232
|
-
},
|
|
233
|
-
};
|
|
234
|
-
|
|
235
|
-
case STREAM_SOURCING_CANDIDATES_SET:
|
|
236
|
-
return {
|
|
237
|
-
...state,
|
|
238
|
-
streaming: {
|
|
239
|
-
...state.streaming,
|
|
240
|
-
sourcingCandidates: (
|
|
241
|
-
payload
|
|
242
|
-
&& typeof payload === 'object'
|
|
243
|
-
&& !Array.isArray(payload)
|
|
244
|
-
) ? payload : null,
|
|
245
|
-
},
|
|
246
|
-
};
|
|
247
|
-
|
|
248
|
-
case STREAM_KNOWLEDGE_CITATION_SET:
|
|
249
|
-
return {
|
|
250
|
-
...state,
|
|
251
|
-
streaming: {
|
|
252
|
-
...state.streaming,
|
|
253
|
-
knowledgeCitation: (
|
|
254
|
-
payload
|
|
255
|
-
&& typeof payload === 'object'
|
|
256
|
-
&& !Array.isArray(payload)
|
|
257
|
-
) ? payload : null,
|
|
258
|
-
},
|
|
259
|
-
};
|
|
260
|
-
|
|
261
|
-
case STREAMING_DONE: {
|
|
262
|
-
const donePayload = (
|
|
263
|
-
payload
|
|
264
|
-
&& typeof payload === 'object'
|
|
265
|
-
&& !Array.isArray(payload)
|
|
266
|
-
) ? payload : { content: payload };
|
|
267
|
-
const doneContent = String(donePayload.content || '');
|
|
268
|
-
const doneMeta = (
|
|
269
|
-
donePayload.meta
|
|
270
|
-
&& typeof donePayload.meta === 'object'
|
|
271
|
-
&& !Array.isArray(donePayload.meta)
|
|
272
|
-
) ? donePayload.meta : {};
|
|
273
|
-
const newMessages = doneContent
|
|
274
|
-
? [
|
|
275
|
-
...state.messages,
|
|
276
|
-
{
|
|
277
|
-
message_id: `temp-assistant-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
278
|
-
role: 'assistant',
|
|
279
|
-
content: doneContent,
|
|
280
|
-
created_at: new Date().toISOString(),
|
|
281
|
-
round_key: String(doneMeta.round_key || doneMeta.roundKey || '').trim(),
|
|
282
|
-
round_state: String(doneMeta.round_state || doneMeta.roundState || '').trim(),
|
|
283
|
-
chooser_state: (
|
|
284
|
-
doneMeta.chooser_state
|
|
285
|
-
&& typeof doneMeta.chooser_state === 'object'
|
|
286
|
-
&& !Array.isArray(doneMeta.chooser_state)
|
|
287
|
-
) ? doneMeta.chooser_state : null,
|
|
288
|
-
knowledge_search: (
|
|
289
|
-
state.streaming.knowledgeSearch
|
|
290
|
-
&& typeof state.streaming.knowledgeSearch === 'object'
|
|
291
|
-
&& !Array.isArray(state.streaming.knowledgeSearch)
|
|
292
|
-
) ? state.streaming.knowledgeSearch : null,
|
|
293
|
-
sourcing_candidates: (
|
|
294
|
-
state.streaming.sourcingCandidates
|
|
295
|
-
&& typeof state.streaming.sourcingCandidates === 'object'
|
|
296
|
-
&& !Array.isArray(state.streaming.sourcingCandidates)
|
|
297
|
-
) ? state.streaming.sourcingCandidates : null,
|
|
298
|
-
knowledge_citation: (
|
|
299
|
-
state.streaming.knowledgeCitation
|
|
300
|
-
&& typeof state.streaming.knowledgeCitation === 'object'
|
|
301
|
-
&& !Array.isArray(state.streaming.knowledgeCitation)
|
|
302
|
-
) ? state.streaming.knowledgeCitation : null,
|
|
303
|
-
agent_status: (
|
|
304
|
-
state.streaming.agentStatus
|
|
305
|
-
&& typeof state.streaming.agentStatus === 'object'
|
|
306
|
-
&& !Array.isArray(state.streaming.agentStatus)
|
|
307
|
-
) ? state.streaming.agentStatus : null,
|
|
308
|
-
thinking_trace: String(state.streaming.thinkingTrace || ''),
|
|
309
|
-
execution_trace: (
|
|
310
|
-
state.streaming.executionTrace
|
|
311
|
-
&& typeof state.streaming.executionTrace === 'object'
|
|
312
|
-
&& !Array.isArray(state.streaming.executionTrace)
|
|
313
|
-
) ? state.streaming.executionTrace : null,
|
|
314
|
-
context_usage: (
|
|
315
|
-
doneMeta.context_usage
|
|
316
|
-
&& typeof doneMeta.context_usage === 'object'
|
|
317
|
-
&& !Array.isArray(doneMeta.context_usage)
|
|
318
|
-
) ? doneMeta.context_usage : null,
|
|
319
|
-
},
|
|
320
|
-
]
|
|
321
|
-
: state.messages;
|
|
322
|
-
|
|
323
|
-
return {
|
|
324
|
-
...state,
|
|
325
|
-
messages: newMessages,
|
|
326
|
-
streaming: initialStreaming,
|
|
327
|
-
};
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
case DOC_GENERATED:
|
|
331
|
-
return { ...state, generatedDoc: payload };
|
|
332
|
-
|
|
333
|
-
case LEGEND_HINT_SHOWN:
|
|
334
|
-
return {
|
|
335
|
-
...state,
|
|
336
|
-
legendHintsShown: {
|
|
337
|
-
...state.legendHintsShown,
|
|
338
|
-
[payload]: true,
|
|
339
|
-
},
|
|
340
|
-
};
|
|
341
|
-
|
|
342
|
-
default:
|
|
343
|
-
return state;
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
export function requireAPI(api, name) {
|
|
348
|
-
if (!api) {
|
|
349
|
-
throw new Error(`${name} is required`);
|
|
350
|
-
}
|
|
351
|
-
return api;
|
|
352
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import test from 'node:test';
|
|
2
|
-
import assert from 'node:assert/strict';
|
|
3
|
-
import { reducer, initialState } from './chatSessionReducer.js';
|
|
4
|
-
import {
|
|
5
|
-
AGENT_STATUS_SET,
|
|
6
|
-
THINKING_TRACE_SET,
|
|
7
|
-
EXECUTION_TRACE_SET,
|
|
8
|
-
STREAM_KNOWLEDGE_SEARCH_SET,
|
|
9
|
-
STREAM_KNOWLEDGE_CITATION_SET,
|
|
10
|
-
STREAMING_DONE,
|
|
11
|
-
} from './chatSessionActionTypes.js';
|
|
12
|
-
|
|
13
|
-
test('STREAMING_DONE snapshots thinking/search/citation metadata into assistant message', () => {
|
|
14
|
-
let state = { ...initialState };
|
|
15
|
-
state = reducer(state, { type: AGENT_STATUS_SET, payload: { status: 'completed', stage: 'analysis' } });
|
|
16
|
-
state = reducer(state, { type: THINKING_TRACE_SET, payload: '阶段:上下文处理' });
|
|
17
|
-
state = reducer(state, { type: EXECUTION_TRACE_SET, payload: { step_id: 'knowledge_search', status: 'completed' } });
|
|
18
|
-
state = reducer(state, { type: STREAM_KNOWLEDGE_SEARCH_SET, payload: { run_id: 'retrieval-1', results: [{ id: 'r1' }] } });
|
|
19
|
-
state = reducer(state, { type: STREAM_KNOWLEDGE_CITATION_SET, payload: { run_id: 'retrieval-1', citations: [{ citation_id: 'cite_1' }] } });
|
|
20
|
-
|
|
21
|
-
state = reducer(state, {
|
|
22
|
-
type: STREAMING_DONE,
|
|
23
|
-
payload: {
|
|
24
|
-
content: '总结完成',
|
|
25
|
-
meta: {
|
|
26
|
-
context_usage: { token_budget: 1200 },
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
const lastMessage = state.messages[state.messages.length - 1];
|
|
32
|
-
assert.equal(lastMessage.role, 'assistant');
|
|
33
|
-
assert.equal(lastMessage.content, '总结完成');
|
|
34
|
-
assert.equal(lastMessage.thinking_trace, '阶段:上下文处理');
|
|
35
|
-
assert.equal(lastMessage.execution_trace?.step_id, 'knowledge_search');
|
|
36
|
-
assert.equal(lastMessage.knowledge_search?.run_id, 'retrieval-1');
|
|
37
|
-
assert.equal(lastMessage.knowledge_citation?.run_id, 'retrieval-1');
|
|
38
|
-
assert.equal(lastMessage.context_usage?.token_budget, 1200);
|
|
39
|
-
});
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { useCallback } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
MESSAGES_REFRESHED,
|
|
4
|
-
MESSAGE_APPENDED,
|
|
5
|
-
} from './chatSessionActionTypes.js';
|
|
6
|
-
import { requireAPI } from './chatSessionReducer.js';
|
|
7
|
-
|
|
8
|
-
export function useMessageActions({ dispatch, messageAPI }) {
|
|
9
|
-
const refreshMessages = useCallback(async (sessionId) => {
|
|
10
|
-
const messageApi = requireAPI(messageAPI, 'messageAPI');
|
|
11
|
-
const response = await messageApi.list(sessionId);
|
|
12
|
-
const messagesWithIds = response.messages.map((msg, index) => ({
|
|
13
|
-
...msg,
|
|
14
|
-
message_id: msg.message_id || `fallback-${Date.now()}-${index}`,
|
|
15
|
-
}));
|
|
16
|
-
dispatch({ type: MESSAGES_REFRESHED, payload: messagesWithIds });
|
|
17
|
-
}, [dispatch, messageAPI]);
|
|
18
|
-
|
|
19
|
-
const appendUserMessage = useCallback((content, metadata = {}) => {
|
|
20
|
-
const payloadMeta = (
|
|
21
|
-
metadata
|
|
22
|
-
&& typeof metadata === 'object'
|
|
23
|
-
&& !Array.isArray(metadata)
|
|
24
|
-
)
|
|
25
|
-
? metadata
|
|
26
|
-
: {};
|
|
27
|
-
dispatch({
|
|
28
|
-
type: MESSAGE_APPENDED,
|
|
29
|
-
payload: {
|
|
30
|
-
message_id: `temp-user-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
31
|
-
role: 'user',
|
|
32
|
-
content,
|
|
33
|
-
created_at: new Date().toISOString(),
|
|
34
|
-
...payloadMeta,
|
|
35
|
-
},
|
|
36
|
-
});
|
|
37
|
-
}, [dispatch]);
|
|
38
|
-
|
|
39
|
-
return {
|
|
40
|
-
refreshMessages,
|
|
41
|
-
appendUserMessage,
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import { useCallback } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
SESSION_LOADED,
|
|
4
|
-
SESSION_RESET,
|
|
5
|
-
TITLE_UPDATED,
|
|
6
|
-
SESSION_PROMOTED,
|
|
7
|
-
} from './chatSessionActionTypes.js';
|
|
8
|
-
import { requireAPI } from './chatSessionReducer.js';
|
|
9
|
-
|
|
10
|
-
export function useSessionCrudActions({ dispatch, sessionAPI, messageAPI }) {
|
|
11
|
-
const loadSession = useCallback(async (sessionId) => {
|
|
12
|
-
const sessionApi = requireAPI(sessionAPI, 'sessionAPI');
|
|
13
|
-
const messageApi = requireAPI(messageAPI, 'messageAPI');
|
|
14
|
-
|
|
15
|
-
const [detail, msgs] = await Promise.all([
|
|
16
|
-
sessionApi.get(sessionId),
|
|
17
|
-
messageApi.list(sessionId),
|
|
18
|
-
]);
|
|
19
|
-
|
|
20
|
-
dispatch({
|
|
21
|
-
type: SESSION_LOADED,
|
|
22
|
-
payload: {
|
|
23
|
-
sessionId,
|
|
24
|
-
title: detail.title,
|
|
25
|
-
status: detail.status || 'active',
|
|
26
|
-
messages: msgs.messages,
|
|
27
|
-
detail,
|
|
28
|
-
},
|
|
29
|
-
});
|
|
30
|
-
return detail;
|
|
31
|
-
}, [dispatch, messageAPI, sessionAPI]);
|
|
32
|
-
|
|
33
|
-
const createSession = useCallback(async ({
|
|
34
|
-
function_type,
|
|
35
|
-
title,
|
|
36
|
-
...extraPayload
|
|
37
|
-
} = {}) => {
|
|
38
|
-
const sessionApi = requireAPI(sessionAPI, 'sessionAPI');
|
|
39
|
-
const response = await sessionApi.create({ function_type, title, ...extraPayload });
|
|
40
|
-
|
|
41
|
-
dispatch({
|
|
42
|
-
type: SESSION_LOADED,
|
|
43
|
-
payload: {
|
|
44
|
-
sessionId: response.sessionId,
|
|
45
|
-
title: String(response.title || title || '').trim(),
|
|
46
|
-
status: response.status || 'active',
|
|
47
|
-
messages: [],
|
|
48
|
-
detail: response,
|
|
49
|
-
},
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
return response.sessionId;
|
|
53
|
-
}, [dispatch, sessionAPI]);
|
|
54
|
-
|
|
55
|
-
const createOrLoadSession = useCallback(async ({
|
|
56
|
-
function_type,
|
|
57
|
-
defaultTitle,
|
|
58
|
-
forceNew = false,
|
|
59
|
-
...extraPayload
|
|
60
|
-
} = {}) => {
|
|
61
|
-
const sessionApi = requireAPI(sessionAPI, 'sessionAPI');
|
|
62
|
-
const messageApi = requireAPI(messageAPI, 'messageAPI');
|
|
63
|
-
|
|
64
|
-
let sessionId;
|
|
65
|
-
let title;
|
|
66
|
-
|
|
67
|
-
if (forceNew) {
|
|
68
|
-
title = defaultTitle;
|
|
69
|
-
const response = await sessionApi.create({ function_type, title, ...extraPayload });
|
|
70
|
-
sessionId = response.sessionId;
|
|
71
|
-
} else {
|
|
72
|
-
const sessionList = await sessionApi.list({
|
|
73
|
-
function_type,
|
|
74
|
-
status: 'active',
|
|
75
|
-
page: 1,
|
|
76
|
-
page_size: 1,
|
|
77
|
-
...extraPayload,
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
if (sessionList.sessions.length > 0) {
|
|
81
|
-
sessionId = sessionList.sessions[0].sessionId;
|
|
82
|
-
title = sessionList.sessions[0].title;
|
|
83
|
-
} else {
|
|
84
|
-
title = defaultTitle;
|
|
85
|
-
const response = await sessionApi.create({ function_type, title, ...extraPayload });
|
|
86
|
-
sessionId = response.sessionId;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const [msgs, detail] = await Promise.all([
|
|
91
|
-
messageApi.list(sessionId),
|
|
92
|
-
sessionApi.get(sessionId),
|
|
93
|
-
]);
|
|
94
|
-
|
|
95
|
-
dispatch({
|
|
96
|
-
type: SESSION_LOADED,
|
|
97
|
-
payload: {
|
|
98
|
-
sessionId,
|
|
99
|
-
title,
|
|
100
|
-
status: detail.status || 'active',
|
|
101
|
-
messages: msgs.messages,
|
|
102
|
-
detail,
|
|
103
|
-
},
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
return sessionId;
|
|
107
|
-
}, [dispatch, messageAPI, sessionAPI]);
|
|
108
|
-
|
|
109
|
-
const resetSession = useCallback(() => {
|
|
110
|
-
dispatch({ type: SESSION_RESET });
|
|
111
|
-
}, [dispatch]);
|
|
112
|
-
|
|
113
|
-
const updateTitle = useCallback(async (sessionId, title) => {
|
|
114
|
-
const sessionApi = requireAPI(sessionAPI, 'sessionAPI');
|
|
115
|
-
await sessionApi.update(sessionId, { title });
|
|
116
|
-
dispatch({ type: TITLE_UPDATED, payload: title });
|
|
117
|
-
}, [dispatch, sessionAPI]);
|
|
118
|
-
|
|
119
|
-
const promoteSession = useCallback((payload = {}) => {
|
|
120
|
-
dispatch({ type: SESSION_PROMOTED, payload });
|
|
121
|
-
}, [dispatch]);
|
|
122
|
-
|
|
123
|
-
return {
|
|
124
|
-
loadSession,
|
|
125
|
-
createSession,
|
|
126
|
-
createOrLoadSession,
|
|
127
|
-
resetSession,
|
|
128
|
-
updateTitle,
|
|
129
|
-
promoteSession,
|
|
130
|
-
};
|
|
131
|
-
}
|