repoburg 1.3.30 → 1.3.31
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/.plan/llm-generation-status-implementation.md +1 -0
- package/backend/dist/src/events/websocket.events.d.ts +19 -0
- package/backend/dist/src/events/websocket.events.js +9 -0
- package/backend/dist/src/events/websocket.events.js.map +1 -1
- package/backend/dist/src/interactive-chat/chat.service.js +20 -1
- package/backend/dist/src/interactive-chat/chat.service.js.map +1 -1
- package/backend/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[{"event": "llm-generation-started", "data": {"sessionInputId": "string; sessionId: string; isStreaming: boolean"}}, {"event": "llm-generation-in-progress", "data": {"sessionInputId": "string"}}, {"event": "llm-generation-ended", "data": {"sessionInputId": "string; sessionId: string; error?: string"}}, {"BROADCAST": "Generation started\n this.eventsGateway.sendToAll('llm-generation-started'", "sessionInputId": "pendingInput.id", "pendingInputId": "pendingInput.id"}, {"BROADCAST": "In progress (only for streaming mode)\n if (isFirst) {\n this.eventsGateway.sendToAll('llm-generation-in-progress'", "sessionInputId": "pendingInput.id"}, {"sessionInputId": "pendingInput?.id || 'unknown'", "BROADCAST": "Generation ended (error)\n this.eventsGateway.sendToAll('llm-generation-ended'", "error": "error.message"}, {"sessionInputId": "pendingInput.id"}, {"event": "llm-generation-started", "data": {"sessionInputId": "string; sessionId: string; isStreaming: boolean"}}, {"event": "llm-generation-in-progress", "data": {"sessionInputId": "string"}}, {"event": "llm-generation-ended", "data": {"sessionInputId": "string; sessionId: string; error?: string"}}, {"llmGenerationStatus": {"sessionInputId": "string | null;\n status: 'idle' | 'started' | 'in-progress' | 'ended';\n isStreaming: boolean;\n error: string | null;"}, "initialState": "SessionState = {\n // ... existing initial state ...\n \n llmGenerationStatus: {\n sessionInputId: null", "status": "idle", "isStreaming": false, "error": null}, {"sessionInputId": "string; sessionId: string; isStreaming: boolean"}, {"sessionInputId": "action.payload.sessionInputId", "status": "started", "isStreaming": "action.payload.isStreaming", "error": null}, {"sessionInputId": "string"}, {"in-progress": ""}, {"sessionInputId": "string; error?: string"}, {"ended": "state.llmGenerationStatus.error = action.payload.error || null;\n \n // Reset to idle after a short delay\n // (This will be handled by the UI component)"}, {"sessionInputId": null, "status": "idle", "isStreaming": false, "error": null}, {"event": "MessageEvent) => {\n try {\n const parsed = JSON.parse(event.data);\n \n if (isWebSocketEvent(parsed)) {\n switch (parsed.event) {\n // ... existing cases ...\n \n case 'llm-generation-started':\n dispatch(setLlmGenerationStarted({\n sessionInputId: parsed.data.sessionInputId", "sessionId": "parsed.data.sessionId", "isStreaming": "parsed.data.isStreaming"}, {"sessionInputId": "parsed.data.sessionInputId"}, {"sessionInputId": "parsed.data.sessionInputId", "error": "parsed.data.error"}, {"message": ", error);\n }\n };\n\n // ... existing WebSocket setup ...\n}, [dispatch, /* ... */]);\n```\n\n---\n\n### Phase 6: Frontend - UI Components\n\n**File: `frontend/src/app/components/session/LLMGenerationStatus.tsx` (NEW)**\n\nCreate a new component for displaying generation status:\n\n```typescript\n\"use client\";\n\nimport React, { useEffect } from 'react", "@/store/sessionStore": "import { Loader2", "lucide-react": "import { Badge"}, {"@/lib/utils": "const LLMGenerationStatus: React.FC = () => {\n const { llmGenerationStatus", "ended": "tatus\n useEffect(() => {\n if (status === 'ended') {\n const timer = setTimeout(() => {\n resetLlmGenerationStatus();"}, ["status, resetLlmGenerationStatus]);\n \n // Don't render anything if idle\n if (status === 'idle' || !llmGenerationStatus.sessionInputId) {\n return null;\n }\n \n const getStatusContent = () => {\n switch (status) {\n case 'started':\n return (\n <div className=\"flex items-center gap-2 text-xs text-slate-600 dark:text-slate-400\">\n <Sparkles className=\"h-3 w-3 animate-pulse\" />\n <span>AI generation {isStreaming ? 'started (streaming)' : 'started'}</span>\n </div>\n );\n \n case 'in-progress':\n return (\n <div className=\"flex items-center gap-2 text-xs text-slate-600 dark:text-slate-400\">\n <Loader2 className=\"h-3 w-3 animate-spin\" />\n <span>AI generating{isStreaming ? '...' : ' response...'}</span>\n </div>\n );\n \n case 'ended':\n if (error) {\n return (\n <div className=\"flex items-center gap-2 text-xs text-red-600 dark:text-red-400\">\n <XCircle className=\"h-3 w-3\" />\n <span>Generation failed: {error}</span>\n </div>\n );\n }\n return (\n <div className=\"flex items-center gap-2 text-xs text-emerald-600 dark:text-emerald-400\">\n <CheckCircle2 className=\"h-3 w-3\" />\n <span>Generation complete</span>\n </div>\n );\n \n default:\n return null;\n }\n };\n \n return (\n <div className=\"px-2 py-1\">\n {getStatusContent()}\n </div>\n );\n};\n\nexport default LLMGenerationStatus;\n```\n\n---\n\n**File: `frontend/src/app/components/session/SessionControls.tsx`**\n\nIntegrate the status component:\n\n```typescript\nimport LLMGenerationStatus from './LLMGenerationStatus';\n\nconst SessionControls: React.FC = () => {\n // ... existing code ...\n \n return (\n <div className=\"space-y-1\">\n {/* Add status indicator */}\n <LLMGenerationStatus />\n \n <SessionActions\n onNewSession={handleNewSession}\n onFollowUp={handleFollowUp}\n isLoading={isLoading}\n currentSessionId={currentSessionId}\n currentSessionStatus={currentSessionStatus}\n />\n\n {error && <p className=\"text-red-500 text-xs p-2 bg-red-100 dark:bg-red-900/30 rounded-md\">Error: {error}</p>}\n\n <SessionInfo />\n <SessionSettings />\n </div>\n );\n};\n```\n\n---\n\n### Phase 7: Testing & Validation\n\n**Test Scenarios:**\n\n1. **Streaming Mode**\n - Submit prompt \u2192 See \"AI generation started (streaming)\"\n - Tokens arrive \u2192 See \"AI generating...\"\n - Completion \u2192 See \"Generation complete\" \u2192 Auto-hide after 3s\n\n2. **Non-Streaming Mode**\n - Submit prompt \u2192 See \"AI generation started\"\n - Immediately see \"AI generating response...\"\n - Completion \u2192 See \"Generation complete\" \u2192 Auto-hide after 3s\n\n3. **Error Cases**\n - Generation fails \u2192 See", "Generation failed: [error message]\"\n - User stops generation \u2192 Status should update appropriately\n\n4. **Manual Mode**\n - Should not show generation status (llm-input-generated event already handles this)\n\n---\n\n## Dependencies & Order of Implementation\n\n1. **Phase 1** - Backend: Add WebSocket event types (Foundational)\n2. **Phase 2** - Backend: ChatService integration (Depends on Phase 1)\n3. **Phase 3** - Frontend: Update WebSocket types (Must sync with Phase 1)\n4. **Phase 4** - Frontend: State management (Depends on Phase 3)\n5. **Phase 5** - Frontend: WebSocket handling (Depends on Phase 4)\n6. **Phase 6** - Frontend: UI components (Depends on Phase 5)\n7. **Phase 7** - Testing (Depends on all phases)\n\n---\n\n## Edge Cases to Handle\n\n1. **Rapid consecutive submissions** - Ensure status updates correctly for latest request\n2. **Stopped generation** - Broadcast \"ended", "with appropriate error or cancellation message\n3. **Session switching** - Reset status when switching sessions\n4. **WebSocket disconnection** - Handle gracefully with timeout/fallback\n5. **Multiple browser tabs** - Each tab receives events, should sync correctly\n\n---\n\n## Success Criteria\n\n- \u2705 User sees explicit \"generation started\" indicator when LLM begins\n- \u2705 User sees \"generating...\" indicator while LLM is working (both streaming and non-streaming)\n- \u2705 User sees \"generation complete", "or error when finished\n- \u2705 Status auto-hides after completion to avoid clutter\n- \u2705 Status works correctly with existing streaming display\n- \u2705 No regression in existing functionality\n\n---\n\n## Notes\n\n- The existing `StreamingResponseDisplay` component shows character count during streaming; this new component provides lifecycle-level status\n- For non-streaming mode, the \"in-progress\" status provides feedback that was previously missing\n- The 3-second auto-hide duration for \"ended", "status gives users confirmation without permanent UI clutter\n- Error messages should be user-friendly, not exposing technical stack traces"]]
|
|
@@ -51,6 +51,25 @@ export type WebSocketEvent = {
|
|
|
51
51
|
chunk: string;
|
|
52
52
|
isFirst: boolean;
|
|
53
53
|
};
|
|
54
|
+
} | {
|
|
55
|
+
event: 'llm-generation-started';
|
|
56
|
+
data: {
|
|
57
|
+
sessionInputId: string;
|
|
58
|
+
sessionId: string;
|
|
59
|
+
isStreaming: boolean;
|
|
60
|
+
};
|
|
61
|
+
} | {
|
|
62
|
+
event: 'llm-generation-in-progress';
|
|
63
|
+
data: {
|
|
64
|
+
sessionInputId: string;
|
|
65
|
+
};
|
|
66
|
+
} | {
|
|
67
|
+
event: 'llm-generation-ended';
|
|
68
|
+
data: {
|
|
69
|
+
sessionInputId: string;
|
|
70
|
+
sessionId: string;
|
|
71
|
+
error?: string;
|
|
72
|
+
};
|
|
54
73
|
};
|
|
55
74
|
export type WebSocketEventName = WebSocketEvent['event'];
|
|
56
75
|
export declare function isWebSocketEvent(obj: unknown): obj is WebSocketEvent;
|
|
@@ -29,6 +29,15 @@ function isWebSocketEvent(obj) {
|
|
|
29
29
|
'sessionInputId' in data &&
|
|
30
30
|
'chunk' in data &&
|
|
31
31
|
'isFirst' in data);
|
|
32
|
+
case 'llm-generation-started':
|
|
33
|
+
return (data !== null &&
|
|
34
|
+
'sessionInputId' in data &&
|
|
35
|
+
'sessionId' in data &&
|
|
36
|
+
'isStreaming' in data);
|
|
37
|
+
case 'llm-generation-in-progress':
|
|
38
|
+
return data !== null && 'sessionInputId' in data;
|
|
39
|
+
case 'llm-generation-ended':
|
|
40
|
+
return data !== null && 'sessionInputId' in data && 'sessionId' in data;
|
|
32
41
|
default:
|
|
33
42
|
return false;
|
|
34
43
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"websocket.events.js","sourceRoot":"","sources":["../../../src/events/websocket.events.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"websocket.events.js","sourceRoot":"","sources":["../../../src/events/websocket.events.ts"],"names":[],"mappings":";;AAqDA,4CA6CC;AA7CD,SAAgB,gBAAgB,CAAC,GAAY;IAC3C,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QAC5C,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,GAAuC,CAAC;IAChE,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC1D,OAAO,KAAK,CAAC;IACf,CAAC;IAED,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,YAAY;YACf,OAAO,IAAI,CAAC;QACd,KAAK,aAAa;YAChB,OAAO,IAAI,KAAK,IAAI,IAAI,aAAa,IAAI,IAAI,CAAC;QAChD,KAAK,YAAY;YACf,OAAO,IAAI,KAAK,IAAI,IAAI,WAAW,IAAI,IAAI,IAAI,gBAAgB,IAAI,IAAI,CAAC;QAC1E,KAAK,sBAAsB;YACzB,OAAO,IAAI,CAAC;QACd,KAAK,sBAAsB;YACzB,OAAO,IAAI,KAAK,IAAI,IAAI,cAAc,IAAI,IAAI,CAAC;QACjD,KAAK,iBAAiB;YACpB,OAAO,IAAI,KAAK,IAAI,IAAI,WAAW,IAAI,IAAI,CAAC;QAC9C,KAAK,qBAAqB;YACxB,OAAO,IAAI,KAAK,IAAI,IAAI,QAAQ,IAAI,IAAI,CAAC;QAC3C,KAAK,kBAAkB;YACrB,OAAO,CACL,IAAI,KAAK,IAAI;gBACb,gBAAgB,IAAI,IAAI;gBACxB,OAAO,IAAI,IAAI;gBACf,SAAS,IAAI,IAAI,CAClB,CAAC;QACJ,KAAK,wBAAwB;YAC3B,OAAO,CACL,IAAI,KAAK,IAAI;gBACb,gBAAgB,IAAI,IAAI;gBACxB,WAAW,IAAI,IAAI;gBACnB,aAAa,IAAI,IAAI,CACtB,CAAC;QACJ,KAAK,4BAA4B;YAC/B,OAAO,IAAI,KAAK,IAAI,IAAI,gBAAgB,IAAI,IAAI,CAAC;QACnD,KAAK,sBAAsB;YACzB,OAAO,IAAI,KAAK,IAAI,IAAI,gBAAgB,IAAI,IAAI,IAAI,WAAW,IAAI,IAAI,CAAC;QAC1E;YACE,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC"}
|
|
@@ -86,6 +86,7 @@ let ChatService = ChatService_1 = class ChatService {
|
|
|
86
86
|
}
|
|
87
87
|
try {
|
|
88
88
|
const session = await this.sessionsService.findOne(sessionId);
|
|
89
|
+
const isStreaming = await this.applicationStateService.getStreamingEnabled();
|
|
89
90
|
let finalSystemInstruction = '';
|
|
90
91
|
const promptIdToRender = session.systemPrompt?.id;
|
|
91
92
|
if (promptIdToRender) {
|
|
@@ -104,8 +105,12 @@ let ChatService = ChatService_1 = class ChatService {
|
|
|
104
105
|
const tools = isToolCapable && toolsEnabled
|
|
105
106
|
? this.toolSchemaService.generateToolDefinitions(this.handlerRegistry)
|
|
106
107
|
: undefined;
|
|
107
|
-
const isStreaming = await this.applicationStateService.getStreamingEnabled();
|
|
108
108
|
const pendingInput = await this.llmResponsesService.createPendingAiInput(sessionId, executionStrategy);
|
|
109
|
+
this.eventsGateway.sendToAll('llm-generation-started', {
|
|
110
|
+
sessionInputId: pendingInput.id,
|
|
111
|
+
sessionId: session.id,
|
|
112
|
+
isStreaming: isStreaming,
|
|
113
|
+
});
|
|
109
114
|
const abortController = new AbortController();
|
|
110
115
|
this.activeRequests.set(sessionId, {
|
|
111
116
|
abortController,
|
|
@@ -113,6 +118,11 @@ let ChatService = ChatService_1 = class ChatService {
|
|
|
113
118
|
});
|
|
114
119
|
const onToken = isStreaming
|
|
115
120
|
? (chunk, isFirst) => {
|
|
121
|
+
if (isFirst) {
|
|
122
|
+
this.eventsGateway.sendToAll('llm-generation-in-progress', {
|
|
123
|
+
sessionInputId: pendingInput.id,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
116
126
|
this.eventsGateway.sendToAll('llm-stream-chunk', {
|
|
117
127
|
sessionInputId: pendingInput.id,
|
|
118
128
|
chunk,
|
|
@@ -142,11 +152,20 @@ let ChatService = ChatService_1 = class ChatService {
|
|
|
142
152
|
cached_token_count: llm_response.usage?.cachedTokens,
|
|
143
153
|
tool_calls: llm_response.tool_calls,
|
|
144
154
|
});
|
|
155
|
+
this.eventsGateway.sendToAll('llm-generation-ended', {
|
|
156
|
+
sessionInputId: pendingInput.id,
|
|
157
|
+
sessionId: session.id,
|
|
158
|
+
});
|
|
145
159
|
this.activeRequests.delete(sessionId);
|
|
146
160
|
this.eventsGateway.sendToAll('refresh-ui', {});
|
|
147
161
|
}
|
|
148
162
|
catch (error) {
|
|
149
163
|
this.activeRequests.delete(sessionId);
|
|
164
|
+
this.eventsGateway.sendToAll('llm-generation-ended', {
|
|
165
|
+
sessionInputId: this.activeRequests.get(sessionId)?.pendingInputId || 'unknown',
|
|
166
|
+
sessionId: sessionId,
|
|
167
|
+
error: error.message,
|
|
168
|
+
});
|
|
150
169
|
this.logger.error(`Error in sendMessage for session ${sessionId}: ${error.message}`, error.stack);
|
|
151
170
|
throw error;
|
|
152
171
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat.service.js","sourceRoot":"","sources":["../../../src/interactive-chat/chat.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAwE;AACxE,mFAKgD;AAChD,6DAAyD;AACzD,kFAA6E;AAC7E,8FAAyF;AACzF,4EAAuE;AACvE,mEAA+D;AAC/D,qFAAgF;AAChF,kFAA6E;AAC7E,6CAAmD;AACnD,qCAAqC;AACrC,gFAAqE;AAQ9D,IAAM,WAAW,mBAAjB,MAAM,WAAW;IAItB,YAEE,WAAyC,EACxB,aAA4B,EAE7C,mBAAyD,EACxC,uBAAgD,EAChD,iBAAoC,EAErD,eAAiD,EAEjD,oBAA2D,EAC1C,iBAAoC,EAErD,eAAkD,EAElD,uBAAkE;QAdjD,gBAAW,GAAX,WAAW,CAAa;QACxB,kBAAa,GAAb,aAAa,CAAe;QAE5B,wBAAmB,GAAnB,mBAAmB,CAAqB;QACxC,4BAAuB,GAAvB,uBAAuB,CAAyB;QAChD,sBAAiB,GAAjB,iBAAiB,CAAmB;QAEpC,oBAAe,GAAf,eAAe,CAAiB;QAEhC,yBAAoB,GAApB,oBAAoB,CAAsB;QAC1C,sBAAiB,GAAjB,iBAAiB,CAAmB;QAEpC,oBAAe,GAAf,eAAe,CAAkB;QAEjC,4BAAuB,GAAvB,uBAAuB,CAA0B;QAnBnD,WAAM,GAAG,IAAI,eAAM,CAAC,aAAW,CAAC,IAAI,CAAC,CAAC;QAC/C,mBAAc,GAAG,IAAI,GAAG,EAA8B,CAAC;IAmB5D,CAAC;
|
|
1
|
+
{"version":3,"file":"chat.service.js","sourceRoot":"","sources":["../../../src/interactive-chat/chat.service.ts"],"names":[],"mappings":"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"}
|