ganesh-vilje commited on
Commit
6cb5907
·
1 Parent(s): 6f8bb0b

Fix: Update last_activity only for user messages

Browse files

- Remove automatic last_activity updates from get_session()
- Add update_activity parameter to update_session()
- Only update last_activity when user messages are added
- Viewing sessions/history no longer updates last_activity
- Ensures session list shows true last interaction time

API_CHANGES_REQUIRED.md ADDED
@@ -0,0 +1,555 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # API Response Changes Required
2
+
3
+ This document outlines **ALL** the changes that need to be made to the MasterLLM API responses based on the corrections defined in `API_RESPONSES_correction.md`.
4
+
5
+ ---
6
+
7
+ ## 1. Session Management APIs
8
+
9
+ ### 1.1 `GET /api/v2/sessions` (with `include_stats=True`)
10
+
11
+ #### Changes Required:
12
+
13
+ 1. **Sort sessions by `last_activity`** (most recent first)
14
+ - **Current:** No sorting specified
15
+ - **Required:** Sessions array must be sorted by `last_activity` in descending order
16
+
17
+ 2. **Update `state` field logic**
18
+ - **Current:** `"state": "initial"`
19
+ - **Required:** State should indicate pipeline/conversation status:
20
+ - `"in_progress"` - if pipeline is currently running
21
+ - `"completed"` - if pipeline completed successfully
22
+ - `"initial"` - if no pipeline has been run
23
+ - `"failed"` - if pipeline failed
24
+
25
+ 3. **Remove `current_file` field**
26
+ - **Current:** `"current_file": "s3://my-bucket/masterllm/550e8400-e29b-41d4-a716-446655440000/report.pdf"`
27
+ - **Required:** This field is not needed for session list
28
+
29
+ ---
30
+
31
+ ### 1.2 `GET /api/v2/sessions/{session_id}/history`
32
+
33
+ #### Changes Required:
34
+
35
+ 1. **Add `message_id` to each history item**
36
+ - **Current:** No `message_id` field
37
+ - **Required:** Each message in history array needs a unique `message_id`
38
+ ```json
39
+ {
40
+ "message_id": "msg_abc123",
41
+ "role": "user",
42
+ "content": "...",
43
+ ...
44
+ }
45
+ ```
46
+
47
+ 2. **Ensure `content` contains only conversation text**
48
+ - **Current:** Content field is correct
49
+ - **Required:** Content should NOT contain pipeline output (pipeline output goes in `pipelines_history`)
50
+
51
+ 3. **Standardize file attachment fields**
52
+ - **Current:** Has both `file_data` object AND separate `file`, `fileName`, `fileUrl` fields
53
+ - **Required:** Keep both structures for backward compatibility, but ensure consistency:
54
+ - If `file_data.has_file` is `true`, then `file` must be `true`
55
+ - `file_url` should be a presigned URL with 7-day validity
56
+ - If no file, all file-related fields should be `false`/`null`
57
+
58
+ 4. **Update pipeline history - rename `result_preview` to `result`**
59
+ - **Current:** `"result_preview": "The Q3 report indicates..."`
60
+ - **Required:**
61
+ ```json
62
+ "result": "The Q3 report indicates a 15% growth in revenue..."
63
+ ```
64
+ - **Note:** If pipeline completed successfully, populate with output. If failed/in-progress, set to `null`
65
+
66
+ 5. **Add error handling fields to pipeline history**
67
+ - **Current:** No error fields
68
+ - **Required:** Add to each pipeline in `pipelines_history`:
69
+ ```json
70
+ {
71
+ "pipeline_id": "pipe_987654321",
72
+ "hasError": false,
73
+ "error": null,
74
+ ...
75
+ }
76
+ ```
77
+ - If pipeline failed:
78
+ ```json
79
+ {
80
+ "pipeline_id": "pipe_987654321",
81
+ "hasError": true,
82
+ "error": {
83
+ "error_code": "EXTRACTION_FAILED",
84
+ "message": "Failed to extract text from PDF",
85
+ "details": "..."
86
+ },
87
+ ...
88
+ }
89
+ ```
90
+
91
+ 6. **Remove `pipeline_s3_key` from response**
92
+ - **Current:** `"pipeline_s3_key": "masterllm/pipelines/pipe_987654321.json"`
93
+ - **Required:** Store internally but don't include in API response
94
+
95
+ 7. **Add component-level details to each component**
96
+ - **Current:** Components only have basic info
97
+ - **Required:** Each component needs:
98
+ ```json
99
+ {
100
+ "component_id": "comp_001",
101
+ "step_id": 1,
102
+ "tool_name": "extract_text",
103
+ "description": "Extract text from the PDF",
104
+ "status": "success", // or "failed", "running"
105
+ "component_output": "Extracted text content here...",
106
+ "hasError": false,
107
+ "error": null,
108
+ "metadata": { // Optional
109
+ "duration_ms": 1500,
110
+ "tokens_consumed": 250,
111
+ "model_used": "claude-3-sonnet"
112
+ },
113
+ "parameters": {
114
+ "file_path": "s3://..."
115
+ }
116
+ }
117
+ ```
118
+
119
+ ---
120
+
121
+ ### 1.3 `GET /api/v2/sessions/{session_id}/pipelines`
122
+
123
+ #### Changes Required:
124
+
125
+ 1. **Add component details**
126
+ - **Current:** Only basic pipeline info
127
+ - **Required:** Include full component data as specified in `/history` endpoint
128
+ ```json
129
+ {
130
+ "pipeline_id": "pipe_987654321",
131
+ "pipeline_name": "Document Summarization",
132
+ "status": "completed",
133
+ "created_at": "2023-11-15T08:31:05Z",
134
+ "final_output_url": "s3://bucket/results/pipe_987654321_output.json",
135
+ "components": [
136
+ {
137
+ "component_id": "comp_001",
138
+ "step_id": 1,
139
+ "tool_name": "extract_text",
140
+ "status": "success",
141
+ "component_output": "...",
142
+ "hasError": false,
143
+ "error": null,
144
+ "metadata": { ... },
145
+ "parameters": { ... }
146
+ }
147
+ ]
148
+ }
149
+ ```
150
+
151
+ ---
152
+
153
+ ## 2. Unified Chat (Non-Streaming) - `POST /api/v2/chat/unified`
154
+
155
+ ### 2.1 All Scenarios - Add `message_id`
156
+
157
+ #### Changes Required:
158
+
159
+ 1. **Add `message_id` to assistant responses**
160
+ - **Current:** No `message_id` field
161
+ - **Required:** Every response needs a unique message ID
162
+ ```json
163
+ {
164
+ "message_id": "msg_xyz789",
165
+ "assistant_response": "...",
166
+ ...
167
+ }
168
+ ```
169
+
170
+ ---
171
+
172
+ ### 2.2 Scenario 4: Pipeline Generated (Proposal)
173
+
174
+ #### Changes Required:
175
+
176
+ 1. **Add `component_id` to each component**
177
+ - **Current:** Components don't have unique IDs
178
+ - **Required:**
179
+ ```json
180
+ "components": [
181
+ {
182
+ "component_id": "comp_001",
183
+ "tool_name": "extract_text",
184
+ "args": { "pages": "all" }
185
+ },
186
+ {
187
+ "component_id": "comp_002",
188
+ "tool_name": "summarize_text",
189
+ "args": { "style": "brief" }
190
+ }
191
+ ]
192
+ ```
193
+
194
+ ---
195
+
196
+ ### 2.3 Scenario 5: Pipeline Completed (Execution Success)
197
+
198
+ #### Changes Required:
199
+
200
+ 1. **Add error handling fields**
201
+ - **Current:** Only has `exception: null`
202
+ - **Required:** Add `hasError` field
203
+ ```json
204
+ {
205
+ "assistant_response": "🎉 Pipeline completed successfully!",
206
+ "hasError": false,
207
+ "exception": null,
208
+ ...
209
+ }
210
+ ```
211
+
212
+ 2. **Add output download capability to `final_output`**
213
+ - **Current:** Only has text and result
214
+ - **Required:**
215
+ ```json
216
+ "final_output": {
217
+ "output_id": "output_abc123",
218
+ "download_url": "https://s3.amazonaws.com/.../output.json?signature=...",
219
+ "text": "The Q3 financial report highlights...",
220
+ "result": {
221
+ "summary": "...",
222
+ "metadata": { ... }
223
+ }
224
+ }
225
+ ```
226
+ - **Note:** `download_url` is optional for now; `output_id` is required for separate download endpoint
227
+
228
+ 3. **Remove nested `result` object from `final_output`**
229
+ - **Current:** Has both `text` and `result` with duplicate data
230
+ - **Required:** Simplify structure - move result data to component level
231
+ ```json
232
+ "final_output": {
233
+ "output_id": "output_abc123",
234
+ "download_url": "https://s3.amazonaws.com/.../output.json?signature=...",
235
+ "text": "The Q3 financial report highlights a strong performance..."
236
+ }
237
+ ```
238
+
239
+ 4. **Add component-level details in `api_response.pipeline.components`**
240
+ - **Current:** Components only have tool names
241
+ - **Required:** Full component details with status, output, errors
242
+ ```json
243
+ "components": [
244
+ {
245
+ "component_id": "comp_001",
246
+ "tool_name": "extract_text",
247
+ "status": "success",
248
+ "component_output": "Full extracted text...",
249
+ "hasError": false,
250
+ "error": null,
251
+ "metadata": {
252
+ "duration_ms": 1200,
253
+ "tokens_consumed": 300
254
+ }
255
+ },
256
+ {
257
+ "component_id": "comp_002",
258
+ "tool_name": "summarize_text",
259
+ "status": "success",
260
+ "component_output": "The Q3 financial report highlights...",
261
+ "hasError": false,
262
+ "error": null,
263
+ "metadata": {
264
+ "duration_ms": 800,
265
+ "tokens_consumed": 150
266
+ }
267
+ }
268
+ ]
269
+ ```
270
+
271
+ ---
272
+
273
+ ### 2.4 Scenario 6: Error
274
+
275
+ #### Changes Required:
276
+
277
+ 1. **Add `hasError` field**
278
+ - **Current:** Only has `exception`
279
+ - **Required:**
280
+ ```json
281
+ {
282
+ "assistant_response": "❌ Pipeline execution failed: ValueError: Input file is empty.",
283
+ "hasError": true,
284
+ "exception": "ValueError: Input file is empty.",
285
+ ...
286
+ }
287
+ ```
288
+
289
+ 2. **Keep `api_response` format unchanged**
290
+ - **Note:** Don't change the error response format in `api_response`
291
+ - **Required:** If error is in a specific component, send error at component level (in component's `error` field)
292
+
293
+ 3. **Component-level error example:**
294
+ ```json
295
+ "api_response": {
296
+ "type": "error",
297
+ "error_code": "PIPELINE_EXECUTION_FAILED",
298
+ "message": "Component 'extract_text' failed",
299
+ "pipeline": {
300
+ "pipeline_id": "pipe_123abc",
301
+ "components": [
302
+ {
303
+ "component_id": "comp_001",
304
+ "tool_name": "extract_text",
305
+ "status": "failed",
306
+ "hasError": true,
307
+ "error": {
308
+ "error_code": "FILE_READ_ERROR",
309
+ "message": "ValueError: Input file is empty.",
310
+ "details": "The uploaded PDF file contains no readable content"
311
+ }
312
+ }
313
+ ]
314
+ }
315
+ }
316
+ ```
317
+
318
+ ---
319
+
320
+ ## 3. Workflows APIs
321
+
322
+ ### 3.1 `GET /api/v2/workflows/{workflow_id}`
323
+
324
+ #### Changes Required:
325
+
326
+ 1. **Add component details to workflow definition**
327
+ - **Current:** Components only have tool name and args
328
+ - **Required:** When workflow is executed, include full component details:
329
+ ```json
330
+ "definition": {
331
+ "pipeline_name": "Quarterly Report Analyzer",
332
+ "components": [
333
+ {
334
+ "component_id": "comp_001",
335
+ "tool_name": "extract_text",
336
+ "args": {},
337
+ "status": "success", // Only if workflow was executed
338
+ "component_output": "...", // Only if workflow was executed
339
+ "hasError": false,
340
+ "error": null,
341
+ "metadata": { // Optional
342
+ "duration_ms": 1500,
343
+ "tokens_consumed": 250
344
+ }
345
+ }
346
+ ]
347
+ }
348
+ ```
349
+
350
+ ---
351
+
352
+ ## 4. Summary of All Changes by Category
353
+
354
+ ### A. New Fields to Add
355
+
356
+ | Field | Location | Type | Description |
357
+ |-------|----------|------|-------------|
358
+ | `message_id` | All chat messages | string | Unique identifier for each message |
359
+ | `component_id` | All components | string | Unique identifier for each pipeline component |
360
+ | `hasError` | Pipeline/Component responses | boolean | Indicates if error occurred |
361
+ | `error` | Pipeline/Component responses | object/null | Error details if hasError is true |
362
+ | `status` | Components | string | Component execution status (success/failed/running) |
363
+ | `component_output` | Components | string/object | Output from component execution |
364
+ | `metadata` | Components (optional) | object | Execution metadata (duration, tokens, etc.) |
365
+ | `output_id` | final_output | string | ID for downloading output |
366
+ | `download_url` | final_output (optional) | string | Direct download URL for output |
367
+
368
+ ### B. Fields to Remove/Hide
369
+
370
+ | Field | Location | Reason |
371
+ |-------|----------|--------|
372
+ | `current_file` | Session list (include_stats=true) | Not needed for session list |
373
+ | `pipeline_s3_key` | Pipeline history | Internal use only, don't expose |
374
+ | Nested `result` in `final_output` | Chat responses | Redundant, move to component level |
375
+
376
+ ### C. Fields to Rename
377
+
378
+ | Old Name | New Name | Location |
379
+ |----------|----------|----------|
380
+ | `result_preview` | `result` | Pipeline history |
381
+
382
+ ### D. Behavioral Changes
383
+
384
+ | Change | Location | Description |
385
+ |--------|----------|-------------|
386
+ | Sort by `last_activity` | Session list | Most recent sessions first |
387
+ | Dynamic `state` values | Sessions & pipelines | Reflect actual pipeline status |
388
+ | 7-day presigned URLs | File attachments | Extend URL validity |
389
+ | Component-level errors | Error responses | Show which component failed |
390
+
391
+ ---
392
+
393
+ ## 5. Implementation Priority
394
+
395
+ ### High Priority (Critical for UI)
396
+
397
+ 1. ✅ Add `message_id` to all messages
398
+ 2. ✅ Add `component_id` to all components
399
+ 3. ✅ Add component `status`, `hasError`, and `error` fields
400
+ 4. ✅ Rename `result_preview` to `result`
401
+ 5. ✅ Sort sessions by `last_activity`
402
+ 6. ✅ Add `output_id` to `final_output`
403
+
404
+ ### Medium Priority (Important for UX)
405
+
406
+ 7. ✅ Add `component_output` to components
407
+ 8. ✅ Remove `current_file` from session list
408
+ 9. ✅ Remove `pipeline_s3_key` from responses
409
+ 10. ✅ Add `download_url` to `final_output`
410
+ 11. ✅ Update `state` field logic
411
+
412
+ ### Low Priority (Nice to Have)
413
+
414
+ 12. ✅ Add component `metadata` (duration, tokens, etc.)
415
+ 13. ✅ Extend presigned URL validity to 7 days
416
+
417
+ ---
418
+
419
+ ## 6. Code Files to Modify
420
+
421
+ Based on these changes, the following files will need modifications:
422
+
423
+ 1. **`api_routes_v2.py`** - Update all endpoint response structures
424
+ 2. **`session_manager.py`** - Add message_id generation, update session retrieval logic
425
+ 3. **`pipeline_executor.py`** - Add component_id, status tracking, error handling
426
+ 4. **`schemas.py`** (if exists) - Update Pydantic models for responses
427
+ 5. **Database models** - May need to add fields for message_id, component_id, etc.
428
+
429
+ ---
430
+
431
+ ## 7. Testing Checklist
432
+
433
+ After implementing changes, verify:
434
+
435
+ - [ ] All messages have unique `message_id`
436
+ - [ ] All components have unique `component_id`
437
+ - [ ] Sessions are sorted by `last_activity` (descending)
438
+ - [ ] `state` field reflects actual pipeline status
439
+ - [ ] `result` field (renamed from `result_preview`) shows correct data
440
+ - [ ] Component errors are properly captured and returned
441
+ - [ ] `hasError` flag is set correctly
442
+ - [ ] `output_id` is generated for completed pipelines
443
+ - [ ] File presigned URLs have 7-day validity
444
+ - [ ] `current_file` is removed from session list
445
+ - [ ] `pipeline_s3_key` is not exposed in responses
446
+ - [ ] Component-level output is captured and returned
447
+ - [ ] Error responses include component-level details
448
+
449
+ ---
450
+
451
+ ## 8. Example: Complete Corrected Response
452
+
453
+ ### `GET /api/v2/sessions/{session_id}/history` (Corrected)
454
+
455
+ ```json
456
+ {
457
+ "session_id": "550e8400-e29b-41d4-a716-446655440000",
458
+ "history": [
459
+ {
460
+ "message_id": "msg_001",
461
+ "role": "user",
462
+ "content": "Uploaded file: report.pdf",
463
+ "timestamp": "2023-11-15T08:30:00Z",
464
+ "file_data": {
465
+ "has_file": true,
466
+ "file_name": "report.pdf",
467
+ "file_url": "https://s3.amazonaws.com/bucket/key?signature=..."
468
+ },
469
+ "file": true,
470
+ "fileName": "report.pdf",
471
+ "fileUrl": "https://s3.amazonaws.com/bucket/key?signature=..."
472
+ },
473
+ {
474
+ "message_id": "msg_002",
475
+ "role": "assistant",
476
+ "content": "File uploaded successfully.",
477
+ "timestamp": "2023-11-15T08:30:05Z",
478
+ "file_data": {
479
+ "has_file": false
480
+ },
481
+ "file": false,
482
+ "fileName": null,
483
+ "fileUrl": null
484
+ }
485
+ ],
486
+ "count": 2,
487
+ "limit": 50,
488
+ "chat_name": "Q3 Financial Report Analysis",
489
+ "pipelines_history": [
490
+ {
491
+ "pipeline_id": "pipe_987654321",
492
+ "pipeline_name": "Document Summarization",
493
+ "status": "completed",
494
+ "created_at": "2023-11-15T08:31:05Z",
495
+ "created_from": "request",
496
+ "model_provider": "bedrock",
497
+ "model_name": "anthropic.claude-3-sonnet-20240229-v1:0",
498
+ "result": "The Q3 report indicates a 15% growth in revenue...",
499
+ "hasError": false,
500
+ "error": null,
501
+ "updated_at": "2023-11-15T08:32:00Z",
502
+ "tools": ["extract_text", "summarize_text"],
503
+ "component_count": 2,
504
+ "components": [
505
+ {
506
+ "component_id": "comp_001",
507
+ "step_id": 1,
508
+ "tool_name": "extract_text",
509
+ "description": "Extract text from the PDF",
510
+ "status": "success",
511
+ "component_output": "Full extracted text from the PDF document...",
512
+ "hasError": false,
513
+ "error": null,
514
+ "metadata": {
515
+ "duration_ms": 1200,
516
+ "tokens_consumed": 300
517
+ },
518
+ "parameters": {
519
+ "file_path": "s3://..."
520
+ }
521
+ },
522
+ {
523
+ "component_id": "comp_002",
524
+ "step_id": 2,
525
+ "tool_name": "summarize_text",
526
+ "description": "Summarize the extracted content",
527
+ "status": "success",
528
+ "component_output": "The Q3 report indicates a 15% growth in revenue...",
529
+ "hasError": false,
530
+ "error": null,
531
+ "metadata": {
532
+ "duration_ms": 800,
533
+ "tokens_consumed": 150
534
+ },
535
+ "parameters": {
536
+ "max_length": 500
537
+ }
538
+ }
539
+ ]
540
+ }
541
+ ]
542
+ }
543
+ ```
544
+
545
+ ---
546
+
547
+ ## 9. Next Steps
548
+
549
+ 1. Review this document with the development team
550
+ 2. Create implementation tasks for each change category
551
+ 3. Update API documentation
552
+ 4. Implement changes in backend code
553
+ 5. Update frontend to consume new response structure
554
+ 6. Test all endpoints thoroughly
555
+ 7. Deploy and monitor
API_RESPONSES.md ADDED
@@ -0,0 +1,750 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # MasterLLM API Response Schemas (Updated)
2
+
3
+ This document outlines the **ACTUAL** JSON response structures for the `api_routes_v2.py` endpoints after implementing all API response corrections. All fields shown reflect the current implementation.
4
+
5
+ **Last Updated:** January 3, 2026
6
+ **Implementation Status:** 100% Complete ✅
7
+
8
+ ---
9
+
10
+ ## 1. Session Management
11
+
12
+ ### `GET /api/v2/sessions`
13
+
14
+ **Description:** Returns a list of all chat sessions, sorted by `last_activity` (descending).
15
+
16
+ **Parameters:**
17
+ - `limit` (int, default=100) - Maximum sessions to return
18
+ - `skip` (int, default=0) - Pagination offset
19
+ - `include_stats` (bool, default=False) - Include detailed statistics
20
+
21
+ **Response (Default - `include_stats=False`):**
22
+
23
+ ```json
24
+ {
25
+ "sessions": [
26
+ {
27
+ "session_id": "550e8400-e29b-41d4-a716-446655440000",
28
+ "created_at": null,
29
+ "last_activity": null
30
+ },
31
+ {
32
+ "session_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
33
+ "created_at": null,
34
+ "last_activity": null
35
+ }
36
+ ],
37
+ "pagination": {
38
+ "total": 2,
39
+ "returned": 2,
40
+ "limit": 100,
41
+ "skip": 0,
42
+ "has_more": false
43
+ }
44
+ }
45
+ ```
46
+
47
+ **Response (with `include_stats=True`):**
48
+
49
+ ```json
50
+ {
51
+ "sessions": [
52
+ {
53
+ "session_id": "550e8400-e29b-41d4-a716-446655440000",
54
+ "user_id": "user_12345",
55
+ "created_at": "2023-11-15T08:30:00.000000Z",
56
+ "last_activity": "2023-11-15T09:45:00.000000Z",
57
+ "state": "completed",
58
+ "chat_name": "Q3 Financial Report Analysis",
59
+ "stats": {
60
+ "message_count": 12
61
+ },
62
+ "total_messages": 12,
63
+ "pipeline_executions_count": 3
64
+ }
65
+ ],
66
+ "pagination": {
67
+ "total": 1,
68
+ "returned": 1,
69
+ "limit": 100,
70
+ "skip": 0,
71
+ "has_more": false
72
+ }
73
+ }
74
+ ```
75
+
76
+ **Key Changes:**
77
+ - ✅ Sessions sorted by `last_activity` (descending)
78
+ - ✅ `current_file` field removed
79
+ - ✅ `state` reflects actual pipeline/conversation status
80
+
81
+ ---
82
+
83
+ ### `GET /api/v2/sessions/{session_id}/history`
84
+
85
+ **Description:** Returns the full message history and pipeline history for a specific session.
86
+
87
+ **Parameters:**
88
+ - `limit` (int, default=50) - Maximum messages to return
89
+
90
+ **Response:**
91
+
92
+ ```json
93
+ {
94
+ "session_id": "550e8400-e29b-41d4-a716-446655440000",
95
+ "history": [
96
+ {
97
+ "message_id": "msg_a1b2c3d4e5f6",
98
+ "role": "user",
99
+ "content": "Uploaded file: report.pdf",
100
+ "timestamp": "2023-11-15T08:30:00Z",
101
+ "file_data": {
102
+ "has_file": true,
103
+ "file_name": "report.pdf",
104
+ "file_url": "https://s3.amazonaws.com/bucket/key?signature=..."
105
+ },
106
+ "file": true,
107
+ "fileName": "report.pdf",
108
+ "fileUrl": "https://s3.amazonaws.com/bucket/key?signature=..."
109
+ },
110
+ {
111
+ "message_id": "msg_g7h8i9j0k1l2",
112
+ "role": "assistant",
113
+ "content": "File uploaded successfully.",
114
+ "timestamp": "2023-11-15T08:30:05Z",
115
+ "file_data": {
116
+ "has_file": false
117
+ },
118
+ "file": false,
119
+ "fileName": null,
120
+ "fileUrl": null
121
+ },
122
+ {
123
+ "message_id": "msg_m3n4o5p6q7r8",
124
+ "role": "user",
125
+ "content": "Summarize this document.",
126
+ "timestamp": "2023-11-15T08:31:00Z",
127
+ "file_data": {
128
+ "has_file": false
129
+ },
130
+ "file": false,
131
+ "fileName": null,
132
+ "fileUrl": null
133
+ }
134
+ ],
135
+ "count": 3,
136
+ "limit": 50,
137
+ "chat_name": "Q3 Financial Report Analysis",
138
+ "pipelines_history": [
139
+ {
140
+ "pipeline_id": "pipe_987654321",
141
+ "pipeline_name": "Document Summarization",
142
+ "status": "completed",
143
+ "created_at": "2023-11-15T08:31:05Z",
144
+ "created_from": "request",
145
+ "model_provider": "bedrock",
146
+ "model_name": "anthropic.claude-3-sonnet-20240229-v1:0",
147
+ "result": "The Q3 report indicates a 15% growth in revenue...",
148
+ "hasError": false,
149
+ "error": null,
150
+ "updated_at": "2023-11-15T08:32:00Z",
151
+ "tools": ["extract_text", "summarize_text"],
152
+ "component_count": 2,
153
+ "components": [
154
+ {
155
+ "component_id": "comp_abc123def456",
156
+ "component_name": "extract_text",
157
+ "order": 1,
158
+ "status": "completed",
159
+ "started_at": "2023-11-15T08:31:10Z",
160
+ "completed_at": "2023-11-15T08:31:25Z",
161
+ "component_output": {
162
+ "text": "Full extracted text from the PDF...",
163
+ "pages_processed": 15
164
+ },
165
+ "hasError": false,
166
+ "error": null,
167
+ "success_message": "Text extraction completed",
168
+ "metadata": {
169
+ "duration_ms": 15000,
170
+ "pages_count": 15
171
+ }
172
+ },
173
+ {
174
+ "component_id": "comp_ghi789jkl012",
175
+ "component_name": "summarize_text",
176
+ "order": 2,
177
+ "status": "completed",
178
+ "started_at": "2023-11-15T08:31:26Z",
179
+ "completed_at": "2023-11-15T08:32:00Z",
180
+ "component_output": {
181
+ "summary": "The Q3 report indicates a 15% growth in revenue...",
182
+ "word_count": 150
183
+ },
184
+ "hasError": false,
185
+ "error": null,
186
+ "success_message": "Summarization completed",
187
+ "metadata": {
188
+ "duration_ms": 34000,
189
+ "tokens_used": 250
190
+ }
191
+ }
192
+ ]
193
+ }
194
+ ]
195
+ }
196
+ ```
197
+
198
+ **Key Changes:**
199
+ - ✅ All messages include `message_id`
200
+ - ✅ Pipelines use `result` instead of `result_preview`
201
+ - ✅ `pipeline_s3_key` removed from response
202
+ - ✅ Added `hasError` and structured `error` fields
203
+ - ✅ Components include `component_id`, `status`, `component_output`, `hasError`, `error`, `metadata`
204
+ - ✅ Presigned URLs valid for 7 days
205
+
206
+ ---
207
+
208
+ ### `GET /api/v2/sessions/{session_id}/pipelines`
209
+
210
+ **Description:** Get all pipeline executions for a session with full component details.
211
+
212
+ **NEW ENDPOINT** ✨
213
+
214
+ **Response:**
215
+
216
+ ```json
217
+ {
218
+ "session_id": "550e8400-e29b-41d4-a716-446655440000",
219
+ "pipelines": [
220
+ {
221
+ "execution_id": "exec_abc123",
222
+ "pipeline_id": "pipe_987654321",
223
+ "pipeline_name": "Document Summarization",
224
+ "status": "completed",
225
+ "created_at": "2023-11-15T08:31:05Z",
226
+ "completed_at": "2023-11-15T08:32:00Z",
227
+ "created_from": "request",
228
+ "executor": "bedrock",
229
+ "result": "The Q3 report indicates a 15% growth in revenue...",
230
+ "hasError": false,
231
+ "error": null,
232
+ "output_id": "output_xyz789abc123",
233
+ "final_output_url": "https://s3.amazonaws.com/bucket/outputs/exec_abc123/final_output.json?signature=...",
234
+ "final_output_presigned_expires_at": "2023-11-22T08:32:00Z",
235
+ "components": [
236
+ {
237
+ "component_id": "comp_abc123def456",
238
+ "component_name": "extract_text",
239
+ "order": 1,
240
+ "status": "completed",
241
+ "component_output": {
242
+ "text": "Full extracted text...",
243
+ "pages_processed": 15
244
+ },
245
+ "hasError": false,
246
+ "error": null,
247
+ "metadata": {
248
+ "duration_ms": 15000
249
+ }
250
+ },
251
+ {
252
+ "component_id": "comp_ghi789jkl012",
253
+ "component_name": "summarize_text",
254
+ "order": 2,
255
+ "status": "completed",
256
+ "component_output": {
257
+ "summary": "The Q3 report indicates...",
258
+ "word_count": 150
259
+ },
260
+ "hasError": false,
261
+ "error": null,
262
+ "metadata": {
263
+ "duration_ms": 34000,
264
+ "tokens_used": 250
265
+ }
266
+ }
267
+ ]
268
+ }
269
+ ]
270
+ }
271
+ ```
272
+
273
+ **Key Features:**
274
+ - ✅ Full component details with IDs and outputs
275
+ - ✅ `output_id` for download tracking
276
+ - ✅ `final_output_url` with 7-day validity
277
+ - ✅ Internal S3 keys removed
278
+ - ✅ Component-level error tracking
279
+
280
+ ---
281
+
282
+ ### `DELETE /api/v2/sessions/{session_id}`
283
+
284
+ **Description:** Deletes a session and its S3 conversation history.
285
+
286
+ **Response:**
287
+
288
+ ```json
289
+ {
290
+ "status": "deleted",
291
+ "session_id": "550e8400-e29b-41d4-a716-446655440000"
292
+ }
293
+ ```
294
+
295
+ ---
296
+
297
+ ### `PUT /api/v2/sessions/{session_id}/rename`
298
+
299
+ **Description:** Renames a session.
300
+
301
+ **Response:**
302
+
303
+ ```json
304
+ {
305
+ "success": true,
306
+ "session_id": "550e8400-e29b-41d4-a716-446655440000",
307
+ "new_name": "New Chat Title"
308
+ }
309
+ ```
310
+
311
+ ---
312
+
313
+ ## 2. Unified Chat (Non-Streaming)
314
+
315
+ ### `POST /api/v2/chat/unified`
316
+
317
+ **Description:** Main interaction endpoint for chat, pipeline generation, and execution.
318
+
319
+ #### **Scenario 1: Casual Chat / Question**
320
+
321
+ **Response:**
322
+
323
+ ```json
324
+ {
325
+ "message_id": "msg_s9t0u1v2w3x4",
326
+ "assistant_response": "I am MasterLLM, an advanced AI agent designed to help you process documents.",
327
+ "output": {},
328
+ "final_output": null,
329
+ "hasError": false,
330
+ "exception": null,
331
+ "api_response": {
332
+ "type": "informational_response",
333
+ "message": "I am MasterLLM, an advanced AI agent designed to help you process documents.",
334
+ "intent_classification": {
335
+ "intent": "question",
336
+ "confidence": 0.98,
337
+ "requires_pipeline": false
338
+ }
339
+ },
340
+ "intent": {
341
+ "intent": "question",
342
+ "confidence": 0.98,
343
+ "requires_pipeline": false
344
+ },
345
+ "chat_id": "550e8400-e29b-41d4-a716-446655440000",
346
+ "state": "initial",
347
+ "file": false,
348
+ "fileName": null,
349
+ "fileUrl": null
350
+ }
351
+ ```
352
+
353
+ #### **Scenario 2: File Uploaded (Only)**
354
+
355
+ **Response:**
356
+
357
+ ```json
358
+ {
359
+ "message_id": "msg_y5z6a7b8c9d0",
360
+ "assistant_response": "📁 File uploaded successfully. Tell me what you'd like to do with it (e.g., extract text, get tables, summarize).",
361
+ "output": {},
362
+ "final_output": null,
363
+ "hasError": false,
364
+ "exception": null,
365
+ "api_response": {
366
+ "type": "file_uploaded",
367
+ "file": {
368
+ "bucket": "my-s3-bucket",
369
+ "key": "masterllm/550e8400-e29b-41d4-a716-446655440000/report.pdf",
370
+ "s3_uri": "s3://my-s3-bucket/masterllm/550e8400-e29b-41d4-a716-446655440000/report.pdf",
371
+ "presigned_url": "https://s3.amazonaws.com/my-s3-bucket/masterllm/550e8400-e29b-41d4-a716-446655440000/report.pdf?signature=...",
372
+ "presigned_expires_at": "2023-11-22T08:30:00.000000Z"
373
+ },
374
+ "next_action": "send_instruction"
375
+ },
376
+ "intent": {
377
+ "intent": "file_uploaded"
378
+ },
379
+ "chat_id": "550e8400-e29b-41d4-a716-446655440000",
380
+ "state": "initial",
381
+ "file": true,
382
+ "fileName": "report.pdf",
383
+ "fileUrl": "https://s3.amazonaws.com/my-s3-bucket/..."
384
+ }
385
+ ```
386
+
387
+ #### **Scenario 3: Pipeline Generated (Proposal)**
388
+
389
+ **Response:**
390
+
391
+ ```json
392
+ {
393
+ "message_id": "msg_e1f2g3h4i5j6",
394
+ "assistant_response": "🎯 **Pipeline Created: Document Summarization**\nHere's what I'll do:\n 1. extract_text\n 2. summarize_text\n**Ready to proceed?**\n- Type 'approve' or 'yes' to execute\n- Type 'reject' or 'no' to cancel\n- Describe changes to modify the plan",
395
+ "output": {
396
+ "pipeline_id": "pipe_123abc",
397
+ "pipeline_name": "Document Summarization",
398
+ "steps_count": 2,
399
+ "tools": ["extract_text", "summarize_text"]
400
+ },
401
+ "final_output": null,
402
+ "hasError": false,
403
+ "exception": null,
404
+ "api_response": {
405
+ "type": "pipeline_generated",
406
+ "message": "Pipeline successfully created",
407
+ "pipeline": {
408
+ "pipeline_id": "pipe_123abc",
409
+ "pipeline_name": "Document Summarization",
410
+ "session_id": "550e8400-e29b-41d4-a716-446655440000",
411
+ "created_at": "2023-11-15T08:35:00Z",
412
+ "_generator": "Claude 3.5 Sonnet",
413
+ "_model": "claude-3-5-sonnet-20240620",
414
+ "components": [
415
+ {
416
+ "component_id": "comp_k7l8m9n0o1p2",
417
+ "tool_name": "extract_text",
418
+ "args": { "pages": "all" }
419
+ },
420
+ {
421
+ "component_id": "comp_q3r4s5t6u7v8",
422
+ "tool_name": "summarize_text",
423
+ "args": { "style": "brief" }
424
+ }
425
+ ]
426
+ },
427
+ "required_action": "approval"
428
+ },
429
+ "intent": {
430
+ "intent": "pipeline_request",
431
+ "requires_pipeline": true,
432
+ "confidence": 0.99
433
+ },
434
+ "chat_id": "550e8400-e29b-41d4-a716-446655440000",
435
+ "state": "pipeline_proposed",
436
+ "file": true,
437
+ "fileName": "report.pdf",
438
+ "fileUrl": "https://s3.amazonaws.com/..."
439
+ }
440
+ ```
441
+
442
+ #### **Scenario 4: Pipeline Completed (Execution Success)**
443
+
444
+ **Response:**
445
+
446
+ ```json
447
+ {
448
+ "message_id": "msg_w9x0y1z2a3b4",
449
+ "assistant_response": "🎉 Pipeline completed successfully!",
450
+ "output": {
451
+ "component_summary": "Pipeline executed successfully",
452
+ "steps": 2
453
+ },
454
+ "final_output": {
455
+ "text": "The Q3 financial report highlights a strong performance with a 15% revenue increase driven by the new product line launch. Operating expenses were reduced by 5% due to efficiency improvements. The outlook for Q4 is positive with projected growth of 10%.",
456
+ "output_id": "output_c5d6e7f8g9h0",
457
+ "download_url": "https://s3.amazonaws.com/bucket/outputs/exec_abc123/final_output.json?signature=..."
458
+ },
459
+ "hasError": false,
460
+ "exception": null,
461
+ "api_response": {
462
+ "type": "pipeline_completed",
463
+ "result": {
464
+ "pipeline_id": "pipe_123abc",
465
+ "status": "completed",
466
+ "components_executed": [
467
+ {
468
+ "component_id": "comp_k7l8m9n0o1p2",
469
+ "tool_name": "extract_text",
470
+ "status": "completed",
471
+ "component_output": {
472
+ "text": "Full extracted text...",
473
+ "pages_processed": 15
474
+ }
475
+ },
476
+ {
477
+ "component_id": "comp_q3r4s5t6u7v8",
478
+ "tool_name": "summarize_text",
479
+ "status": "completed",
480
+ "component_output": {
481
+ "summary": "The Q3 financial report highlights..."
482
+ }
483
+ }
484
+ ]
485
+ },
486
+ "pipeline": {
487
+ "pipeline_id": "pipe_123abc",
488
+ "pipeline_name": "Document Summarization",
489
+ "components": [
490
+ { "component_id": "comp_k7l8m9n0o1p2", "tool_name": "extract_text" },
491
+ { "component_id": "comp_q3r4s5t6u7v8", "tool_name": "summarize_text" }
492
+ ]
493
+ }
494
+ },
495
+ "intent": {
496
+ "intent": "pipeline_execute"
497
+ },
498
+ "chat_id": "550e8400-e29b-41d4-a716-446655440000",
499
+ "state": "initial",
500
+ "file": true,
501
+ "fileName": "report.pdf",
502
+ "fileUrl": "https://s3.amazonaws.com/..."
503
+ }
504
+ ```
505
+
506
+ **Key Changes:**
507
+ - ✅ `message_id` in all responses
508
+ - ✅ `hasError` flag
509
+ - ✅ `output_id` and `download_url` in `final_output`
510
+ - ✅ Component IDs in pipeline proposals
511
+ - ✅ Removed nested `result` object from `final_output`
512
+
513
+ #### **Scenario 5: Error**
514
+
515
+ **Response:**
516
+
517
+ ```json
518
+ {
519
+ "message_id": "msg_i1j2k3l4m5n6",
520
+ "assistant_response": "❌ Pipeline execution failed: ValueError: Input file is empty.",
521
+ "output": {},
522
+ "final_output": null,
523
+ "hasError": true,
524
+ "exception": "ValueError: Input file is empty.",
525
+ "api_response": {
526
+ "type": "error",
527
+ "error_code": "PIPELINE_EXECUTION_FAILED",
528
+ "message": "ValueError: Input file is empty.",
529
+ "failed_component": {
530
+ "component_id": "comp_k7l8m9n0o1p2",
531
+ "tool_name": "extract_text",
532
+ "error": {
533
+ "message": "ValueError: Input file is empty.",
534
+ "error_code": "FILE_READ_ERROR"
535
+ }
536
+ }
537
+ },
538
+ "intent": {
539
+ "intent": "pipeline_execute"
540
+ },
541
+ "chat_id": "550e8400-e29b-41d4-a716-446655440000",
542
+ "state": "initial",
543
+ "file": true,
544
+ "fileName": "report.pdf",
545
+ "fileUrl": "https://s3.amazonaws.com/..."
546
+ }
547
+ ```
548
+
549
+ **Key Changes:**
550
+ - ✅ `hasError` set to `true`
551
+ - ✅ Component-level error details in `failed_component`
552
+ - ✅ Structured error with `error_code` and `message`
553
+
554
+ ---
555
+
556
+ ## 3. Unified Chat (Streaming)
557
+
558
+ ### `POST /api/v2/chat/unified/stream`
559
+
560
+ **Description:** Streaming version of the unified chat. Returns **NDJSON** (Newlines Delimited JSON).
561
+
562
+ **Event Type: `status`**
563
+
564
+ ```json
565
+ {
566
+ "type": "status",
567
+ "message": "Analyzing request and creating a pipeline...",
568
+ "chat_id": "550e8400-e29b-41d4-a716-446655440000",
569
+ "state": "initial"
570
+ }
571
+ ```
572
+
573
+ **Event Type: `assistant_final` (Typical Chat Response)**
574
+
575
+ ```json
576
+ {
577
+ "type": "assistant_final",
578
+ "content": "Hello! How can I help you today?",
579
+ "intent": {
580
+ "intent": "casual_chat",
581
+ "confidence": 0.99
582
+ },
583
+ "chat_id": "550e8400-e29b-41d4-a716-446655440000",
584
+ "state": "initial"
585
+ }
586
+ ```
587
+
588
+ **Event Type: `assistant_final` (Execution Completed)**
589
+
590
+ ```json
591
+ {
592
+ "type": "assistant_final",
593
+ "content": "🎉 Pipeline Completed Successfully!\n- Pipeline: Document Summarization\n- Total Steps: 2\n- Successful: 2\n- Executor: Bedrock Agent\n\nThe Q3 financial report highlights...",
594
+ "result": {
595
+ "summary": "The Q3 financial report highlights...",
596
+ "full_text": "..."
597
+ },
598
+ "output": {
599
+ "component_summary": "Executed 2 steps successfully",
600
+ "steps_completed": 2,
601
+ "total_steps": 2
602
+ },
603
+ "final_output": {
604
+ "text": "The Q3 financial report highlights...",
605
+ "output_id": "output_o9p0q1r2s3t4",
606
+ "download_url": "https://s3.amazonaws.com/..."
607
+ },
608
+ "chat_id": "550e8400-e29b-41d4-a716-446655440000",
609
+ "state": "initial"
610
+ }
611
+ ```
612
+
613
+ ---
614
+
615
+ ## 4. File Management
616
+
617
+ ### `POST /api/v2/chats/{chat_id}/upload`
618
+
619
+ **Description:** Direct file upload endpoint.
620
+
621
+ **Response:**
622
+
623
+ ```json
624
+ {
625
+ "status": "success",
626
+ "message": "File uploaded to S3",
627
+ "file": {
628
+ "bucket": "my-s3-bucket",
629
+ "key": "masterllm/550e8400-e29b-41d4-a716-446655440000/report.pdf",
630
+ "s3_uri": "s3://my-s3-bucket/masterllm/550e8400-e29b-41d4-a716-446655440000/report.pdf",
631
+ "presigned_url": "https://s3.amazonaws.com/my-s3-bucket/masterllm/550e8400-e29b-41d4-a716-446655440000/report.pdf?signature=...",
632
+ "presigned_expires_at": "2023-11-22T08:30:00.000000Z"
633
+ },
634
+ "chat_id": "550e8400-e29b-41d4-a716-446655440000",
635
+ "next_action": "💬 Now tell me what you'd like to do with this document"
636
+ }
637
+ ```
638
+
639
+ **Key Changes:**
640
+ - ✅ Presigned URLs valid for 7 days
641
+
642
+ ---
643
+
644
+ ## 5. System
645
+
646
+ ### `POST /api/v2/chats`
647
+
648
+ **Description:** Create a new empty chat session.
649
+
650
+ **Response:**
651
+
652
+ ```json
653
+ {
654
+ "chat_id": "550e8400-e29b-41d4-a716-446655440000"
655
+ }
656
+ ```
657
+
658
+ ### `GET /api/v2/health`
659
+
660
+ **Description:** Health check.
661
+
662
+ **Response:**
663
+
664
+ ```json
665
+ {
666
+ "status": "ok",
667
+ "service": "MasterLLM v2.0",
668
+ "time": "2023-11-15T08:30:00.000000Z"
669
+ }
670
+ ```
671
+
672
+ ---
673
+
674
+ ## Summary of Changes
675
+
676
+ ### ✅ New Fields Added
677
+ - `message_id` - Unique identifier for all messages (format: `msg_xxxxxxxxxxxx`)
678
+ - `component_id` - Unique identifier for pipeline components (format: `comp_xxxxxxxxxxxx`)
679
+ - `output_id` - Unique identifier for pipeline outputs (format: `output_xxxxxxxxxxxx`)
680
+ - `hasError` - Boolean flag for error detection
681
+ - `error` - Structured error object with `message`, `error_code`, `details`
682
+ - `component_output` - Actual output from component execution
683
+ - `download_url` - Direct download URL for pipeline results
684
+ - `failed_component` - Component-level error details in error responses
685
+ - `metadata` - Component execution metadata (duration, tokens, etc.)
686
+
687
+ ### ✅ Fields Renamed
688
+ - `result_preview` → `result`
689
+
690
+ ### ✅ Fields Removed
691
+ - `current_file` (from session list response)
692
+ - `pipeline_s3_key` (internal field, not exposed in API)
693
+ - Nested `result` object in `final_output` (simplified structure)
694
+
695
+ ### ✅ New Endpoints
696
+ - `GET /api/v2/sessions/{session_id}/pipelines` - Get all pipelines for a session
697
+
698
+ ### ✅ Behavioral Changes
699
+ - Sessions sorted by `last_activity` (descending)
700
+ - Presigned URLs valid for 7 days (604800 seconds)
701
+ - Component-level error tracking and reporting
702
+ - State field dynamically reflects pipeline/conversation status
703
+
704
+ ---
705
+
706
+ ## ID Formats
707
+
708
+ All IDs follow consistent formats for easy identification:
709
+
710
+ - **Message IDs:** `msg_xxxxxxxxxxxx` (12 hex characters)
711
+ - **Component IDs:** `comp_xxxxxxxxxxxx` (12 hex characters)
712
+ - **Output IDs:** `output_xxxxxxxxxxxx` (12 hex characters)
713
+ - **Session IDs:** Standard UUID v4 format
714
+ - **Pipeline IDs:** `pipe_` prefix or UUID format
715
+
716
+ ---
717
+
718
+ ## Error Handling
719
+
720
+ All error responses now include:
721
+
722
+ 1. **Top-level `hasError` flag** - Quick error detection
723
+ 2. **Structured `error` object** - Detailed error information
724
+ 3. **Component-level errors** - Identify which component failed
725
+ 4. **Error codes** - Machine-readable error classification
726
+
727
+ Example error structure:
728
+ ```json
729
+ {
730
+ "hasError": true,
731
+ "error": {
732
+ "message": "Detailed error message",
733
+ "error_code": "ERROR_TYPE",
734
+ "details": {
735
+ "additional": "context"
736
+ }
737
+ },
738
+ "failed_component": {
739
+ "component_id": "comp_xxxxxxxxxxxx",
740
+ "tool_name": "tool_name",
741
+ "error": {...}
742
+ }
743
+ }
744
+ ```
745
+
746
+ ---
747
+
748
+ **Document Version:** 2.0
749
+ **Implementation Date:** January 3, 2026
750
+ **Status:** Production Ready ✅
API_RESPONSES_correction.md ADDED
@@ -0,0 +1,763 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # MasterLLM API Response Schemas
2
+
3
+ This document outlines the COMPLETE JSON response structures for the `api_routes_v2.py` endpoints. All fields are shown with example data.
4
+
5
+ ## 1. **Session Management**
6
+
7
+ ### `GET /api/v2/sessions`
8
+
9
+ **Description:** Returns a list of all chat sessions.
10
+ **Parameters:** `limit` (int, default=100), `skip` (int, default=0), `include_stats` (bool, default=False)
11
+
12
+ **Response (Default - `include_stats=False`):**
13
+
14
+ ```json
15
+ {
16
+ "sessions": [
17
+ {
18
+ "session_id": "550e8400-e29b-41d4-a716-446655440000",
19
+ "created_at": null,
20
+ "last_activity": null
21
+ },
22
+ {
23
+ "session_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
24
+ "created_at": null,
25
+ "last_activity": null
26
+ }
27
+ ],
28
+ "pagination": {
29
+ "total": 2,
30
+ "returned": 2,
31
+ "limit": 100,
32
+ "skip": 0,
33
+ "has_more": false
34
+ }
35
+ }
36
+ ```
37
+
38
+ **Response (with `include_stats=True`):**
39
+
40
+ ```json
41
+ {
42
+ // The sessions needs to be sorted according to the last activity. The latest should come first key is last_activity
43
+ "sessions": [
44
+ {
45
+ "session_id": "550e8400-e29b-41d4-a716-446655440000",
46
+ "user_id": "user_12345",
47
+ "created_at": "2023-11-15T08:30:00.000000Z",
48
+ "last_activity": "2023-11-15T09:45:00.000000Z",
49
+ // state should indicate the status of the pipeline or the conversation. If the pipeline is in pogress it should be in pogress if not then completed, initial, or failed
50
+ "state": "initial",
51
+ // current_file is not needed for session list
52
+ "current_file": "s3://my-bucket/masterllm/550e8400-e29b-41d4-a716-446655440000/report.pdf",
53
+ "chat_name": "Q3 Financial Report Analysis",
54
+ "stats": {
55
+ "tokens_used": 1500,
56
+ "cost_estimate": 0.045
57
+ },
58
+ "total_messages": 12,
59
+ "pipeline_executions_count": 3
60
+ }
61
+ ],
62
+ "pagination": {
63
+ "total": 1,
64
+ "returned": 1,
65
+ "limit": 100,
66
+ "skip": 0,
67
+ "has_more": false
68
+ }
69
+ }
70
+ ```
71
+
72
+ ### `GET /api/v2/sessions/{session_id}/history`
73
+
74
+ **Description:** Returns the full message history and pipeline history for a specific session.
75
+ **Parameters:** `limit` (int, default=50)
76
+
77
+ **Response:**
78
+
79
+ ```json
80
+ {
81
+ "session_id": "550e8400-e29b-41d4-a716-446655440000",
82
+ // This is the history of msg and chats
83
+ "history": [
84
+ {
85
+ // Need message_id
86
+ "role": "user",
87
+ // content should always have basic conversation content, it should not have the output of the pipeline
88
+ "content": "Uploaded file: report.pdf",
89
+ "timestamp": "2023-11-15T08:30:00Z",
90
+ "file_data": {
91
+ "has_file": true,
92
+ "file_name": "report.pdf",
93
+ "file_url": "https://s3.amazonaws.com/bucket/key?signature=..."
94
+ },
95
+ // This should be proper, like if file was attached to this particular msg then true with file details like a presigned url with a validity of 7 days.
96
+ // If Not then file should be false
97
+ "file": true,
98
+ "fileName": "report.pdf",
99
+ "fileUrl": "https://s3.amazonaws.com/bucket/key?signature=..."
100
+ },
101
+ {
102
+ "role": "assistant",
103
+ "content": "File uploaded successfully.",
104
+ "timestamp": "2023-11-15T08:30:05Z",
105
+ "file_data": {
106
+ "has_file": false
107
+ },
108
+ "file": false,
109
+ "fileName": null,
110
+ "fileUrl": null
111
+ },
112
+ {
113
+ "role": "user",
114
+ "content": "Summarize this document.",
115
+ "timestamp": "2023-11-15T08:31:00Z",
116
+ "file_data": {
117
+ "has_file": false
118
+ },
119
+ "file": false,
120
+ "fileName": null,
121
+ "fileUrl": null
122
+ }
123
+ ],
124
+ "count": 3,
125
+ "limit": 50,
126
+ "chat_name": "Q3 Financial Report Analysis",
127
+ "pipelines_history": [
128
+ {
129
+ "pipeline_id": "pipe_987654321",
130
+ "pipeline_name": "Document Summarization",
131
+ // status should indicate the state of the pipeline, if success then completed, if not failed or in pogress.
132
+ "status": "completed",
133
+ "created_at": "2023-11-15T08:31:05Z",
134
+ "created_from": "request",
135
+ "model_provider": "bedrock",
136
+ "model_name": "anthropic.claude-3-sonnet-20240229-v1:0",
137
+ // No need for pipeline_s3_key store it but dont need in the output,
138
+ "pipeline_s3_key": "masterllm/pipelines/pipe_987654321.json",
139
+ // result_preview should be named as result. And in here if the pipeline has completed with success the output should be provided, if not or failed this should be null.
140
+ "result_preview": "The Q3 report indicates a 15% growth in revenue...",
141
+ // Please add another key called hasError, and error details where if the pipeline is failed or has error the error should be provided. If the pipeline is passed then this will be null and hasError false.
142
+ "updated_at": "2023-11-15T08:32:00Z",
143
+ "tools": ["extract_text", "summarize_text"],
144
+ "component_count": 2,
145
+ "components": [
146
+ {
147
+ // Please provide a component ID to unique identify each
148
+ // Please provide the status of each component, like status: success, failed, or running
149
+ // If success send the result of this component run. like component_output: This will have the output of the component
150
+ // Please send hasError, and error details where if the component is failed or has error the error should be provided. If the component is passed then this will be null and hasError false
151
+ // Send the component meta data if present like the duration run, token consumed, etc (This is optional)
152
+ "step_id": 1,
153
+ "tool_name": "extract_text",
154
+ "description": "Extract text from the PDF",
155
+ "parameters": {
156
+ "file_path": "s3://..."
157
+ }
158
+ },
159
+ {
160
+ "step_id": 2,
161
+ "tool_name": "summarize_text",
162
+ "description": "Summarize the extracted content",
163
+ "parameters": {
164
+ "max_length": 500
165
+ }
166
+ }
167
+ ]
168
+ }
169
+ ]
170
+ }
171
+ ```
172
+
173
+ ### `DELETE /api/v2/sessions/{session_id}`
174
+
175
+ **Description:** Deletes a session and its S3 conversation history.
176
+
177
+ **Response:**
178
+
179
+ ```json
180
+ {
181
+ "status": "deleted",
182
+ "session_id": "550e8400-e29b-41d4-a716-446655440000"
183
+ }
184
+ ```
185
+
186
+ ### `PUT /api/v2/sessions/{session_id}/rename`
187
+
188
+ **Description:** Renames a session.
189
+
190
+ **Response:**
191
+
192
+ ```json
193
+ {
194
+ "success": true,
195
+ "session_id": "550e8400-e29b-41d4-a716-446655440000",
196
+ "new_name": "New Chat Title"
197
+ }
198
+ ```
199
+
200
+ ### `GET /api/v2/sessions/{session_id}/pipelines`
201
+
202
+ **Description:** Get all pipeline executions for a session.
203
+
204
+ **Response:**
205
+
206
+ ```json
207
+ {
208
+ "session_id": "550e8400-e29b-41d4-a716-446655440000",
209
+ "pipelines": [
210
+ {
211
+ "pipeline_id": "pipe_987654321",
212
+ "pipeline_name": "Document Summarization",
213
+ "status": "completed",
214
+ "created_at": "2023-11-15T08:31:05Z",
215
+ "final_output_url": "s3://bucket/results/pipe_987654321_output.json"
216
+ // Please also send the components and its data as you are / will be sending in the `GET /api/v2/sessions/{session_id}/history`
217
+ }
218
+ ]
219
+ }
220
+ ```
221
+
222
+ ---
223
+
224
+ ## 2. **Unified Chat (Non-Streaming)**
225
+
226
+ ### `POST /api/v2/chat/unified`
227
+
228
+ **Description:** Main interaction endpoint.
229
+
230
+ #### **Scenario 1: Casual Chat / Question**
231
+
232
+ **Response:**
233
+
234
+ ```json
235
+ {
236
+ // This should also have the message id, as this is a msg from the LLM
237
+ "assistant_response": "I am MasterLLM, an advanced AI agent designed to help you process documents.",
238
+ "output": {},
239
+ "final_output": null,
240
+ "exception": null,
241
+ "api_response": {
242
+ "type": "informational_response",
243
+ "message": "I am MasterLLM, an advanced AI agent designed to help you process documents.",
244
+ "intent_classification": {
245
+ "intent": "question",
246
+ "confidence": 0.98,
247
+ "requires_pipeline": false
248
+ }
249
+ },
250
+ "intent": {
251
+ "intent": "question",
252
+ "confidence": 0.98,
253
+ "requires_pipeline": false
254
+ },
255
+ "chat_id": "550e8400-e29b-41d4-a716-446655440000",
256
+ "state": "initial",
257
+ "file": false,
258
+ "fileName": null,
259
+ "fileUrl": null
260
+ }
261
+ ```
262
+
263
+ #### **Scenario 2: Clarification Needed**
264
+
265
+ **Response:**
266
+
267
+ ```json
268
+ {
269
+ // This should also have the message id, as this is a msg from the LLM
270
+ "assistant_response": "I'm not sure what you mean by 'do it'. Could you please specify if you want to summarize, extract text, or translate the document?",
271
+ "output": {},
272
+ "final_output": null,
273
+ "exception": null,
274
+ "api_response": {
275
+ "type": "clarification_needed",
276
+ "message": "I'm not sure what you mean by 'do it'. Could you please specify if you want to summarize, extract text, or translate the document?",
277
+ "intent_classification": {
278
+ "intent": "unclear",
279
+ "confidence": 0.45,
280
+ "requires_pipeline": false
281
+ },
282
+ "suggestions": [
283
+ "Be more specific about what you want to do",
284
+ "Use keywords like: extract, summarize, translate, etc.",
285
+ "Type 'help' for examples"
286
+ ]
287
+ },
288
+ "intent": {
289
+ "intent": "unclear",
290
+ "confidence": 0.45,
291
+ "requires_pipeline": false
292
+ },
293
+ "chat_id": "550e8400-e29b-41d4-a716-446655440000",
294
+ "state": "initial",
295
+ "file": true,
296
+ "fileName": "report.pdf",
297
+ "fileUrl": "https://s3.amazonaws.com/..."
298
+ }
299
+ ```
300
+
301
+ #### **Scenario 3: File Uploaded (Only)**
302
+
303
+ **Response:**
304
+
305
+ ```json
306
+ {
307
+ // This should also have the message id, as this is a msg from the LLM
308
+ "assistant_response": "📁 File uploaded successfully. Tell me what you'd like to do with it (e.g., extract text, get tables, summarize).",
309
+ "output": {},
310
+ "final_output": null,
311
+ "exception": null,
312
+ "api_response": {
313
+ "type": "file_uploaded",
314
+ "file": {
315
+ "bucket": "my-s3-bucket",
316
+ "key": "masterllm/550e8400-e29b-41d4-a716-446655440000/report.pdf",
317
+ "s3_uri": "s3://my-s3-bucket/masterllm/550e8400-e29b-41d4-a716-446655440000/report.pdf",
318
+ "presigned_url": "https://s3.amazonaws.com/my-s3-bucket/masterllm/550e8400-e29b-41d4-a716-446655440000/report.pdf?AMAZONPARAMS...",
319
+ "presigned_expires_at": "2023-11-22T08:30:00.000000Z"
320
+ },
321
+ "next_action": "send_instruction"
322
+ },
323
+ "intent": {
324
+ "intent": "file_uploaded"
325
+ },
326
+ "chat_id": "550e8400-e29b-41d4-a716-446655440000",
327
+ "state": "initial",
328
+ "file": true,
329
+ "fileName": "report.pdf",
330
+ "fileUrl": "https://s3.amazonaws.com/my-s3-bucket/..."
331
+ }
332
+ ```
333
+
334
+ #### **Scenario 4: Pipeline Generated (Proposal)**
335
+
336
+ **Response:**
337
+
338
+ ```json
339
+ {
340
+ // This should also have the message id, as this is a msg from the LLM
341
+ "assistant_response": "🎯 **Pipeline Created: Document Summarization**\nHere's what I'll do:\n 1. extract_text\n 2. summarize_text\n**Ready to proceed?**\n- Type 'approve' or 'yes' to execute\n- Type 'reject' or 'no' to cancel\n- Describe changes to modify the plan",
342
+ "output": {
343
+ "pipeline_id": "pipe_123abc",
344
+ "pipeline_name": "Document Summarization",
345
+ "steps_count": 2,
346
+ "tools": ["extract_text", "summarize_text"]
347
+ },
348
+ "final_output": null,
349
+ "exception": null,
350
+ "api_response": {
351
+ "type": "pipeline_generated",
352
+ "message": "Pipeline successfully created",
353
+ "pipeline": {
354
+ "pipeline_id": "pipe_123abc",
355
+ "pipeline_name": "Document Summarization",
356
+ "session_id": "550e8400-e29b-41d4-a716-446655440000",
357
+ "created_at": "2023-11-15T08:35:00Z",
358
+ "_generator": "Claude 3.5 Sonnet",
359
+ "_model": "claude-3-5-sonnet-20240620",
360
+ // Please provide a component ID to unique identify each
361
+ "components": [
362
+ {
363
+ "tool_name": "extract_text",
364
+ "args": { "pages": "all" }
365
+ },
366
+ {
367
+ "tool_name": "summarize_text",
368
+ "args": { "style": "brief" }
369
+ }
370
+ ],
371
+ "pipeline_steps": [
372
+ {
373
+ "tool_name": "extract_text",
374
+ "args": { "pages": "all" }
375
+ },
376
+ {
377
+ "tool_name": "summarize_text",
378
+ "args": { "style": "brief" }
379
+ }
380
+ ]
381
+ },
382
+ "pipeline_summary": {
383
+ "name": "Document Summarization",
384
+ "total_steps": 2,
385
+ "steps": [
386
+ {
387
+ "tool_name": "extract_text",
388
+ "args": { "pages": "all" }
389
+ },
390
+ {
391
+ "tool_name": "summarize_text",
392
+ "args": { "style": "brief" }
393
+ }
394
+ ],
395
+ "generator": "Claude 3.5 Sonnet",
396
+ "model": "claude-3-5-sonnet-20240620"
397
+ },
398
+ "required_action": "approval",
399
+ "next_steps": {
400
+ "approve": "Type 'approve' or 'yes'",
401
+ "reject": "Type 'reject' or 'no'",
402
+ "modify": "Describe your changes"
403
+ }
404
+ },
405
+ "intent": {
406
+ "intent": "pipeline_request",
407
+ "requires_pipeline": true,
408
+ "confidence": 0.99
409
+ },
410
+ "chat_id": "550e8400-e29b-41d4-a716-446655440000",
411
+ "state": "pipeline_proposed",
412
+ "file": true,
413
+ "fileName": "report.pdf",
414
+ "fileUrl": "https://s3.amazonaws.com/..."
415
+ }
416
+ ```
417
+
418
+ #### **Scenario 5: Pipeline Completed (Execution Success)**
419
+
420
+ **Response:**
421
+
422
+ ```json
423
+ {
424
+ // This should also have the message id, as this is a msg from the LLM
425
+ "assistant_response": "🎉 Pipeline completed successfully!",
426
+ // send hasError, if it has then the error should be provide in the exception if not this will be null and hasError will be false
427
+ "output": {
428
+ "component_summary": "Pipeline executed successfully",
429
+ "steps": 2
430
+ },
431
+ // final_output should have data only if the LLM has run the pipeline and completed with success. Then populate the final output here
432
+ "final_output": {
433
+ // Please add output id for which the user can download the output if he wants. The output id will be used to downalod using a separate endpoint.
434
+ // Optional: check if you can send the download url in here as well for downalod output. if not the output id will work as of now.
435
+ "text": "The Q3 financial report highlights a strong performance with a 15% revenue increase driven by the new product line launch. Operating expenses were reduced by 5% due to efficiency improvements. The outlook for Q4 is positive with projected growth of 10%.",
436
+
437
+ // This result is not needed as this should be in the component level
438
+ "result": {
439
+ "summary": "The Q3 financial report highlights a strong performance with a 15% revenue increase driven by the new product line launch. Operating expenses were reduced by 5% due to efficiency improvements. The outlook for Q4 is positive with projected growth of 10%.",
440
+ "metadata": {
441
+ "source_file": "report.pdf",
442
+ "processed_at": "2023-11-15T08:36:00Z"
443
+ }
444
+ }
445
+ },
446
+ "exception": null,
447
+ "api_response": {
448
+ "type": "pipeline_completed",
449
+ "result": {
450
+ "summary": "The Q3 financial report highlights a strong performance with a 15% revenue increase driven by the new product line launch. Operating expenses were reduced by 5% due to efficiency improvements. The outlook for Q4 is positive with projected growth of 10%.",
451
+ "metadata": {
452
+ "source_file": "report.pdf",
453
+ "processed_at": "2023-11-15T08:36:00Z"
454
+ }
455
+ },
456
+ "pipeline": {
457
+ "pipeline_id": "pipe_123abc",
458
+ "pipeline_name": "Document Summarization",
459
+ // Please provide a component ID to unique identify each
460
+ // Please provide the status of each component, like status: success, failed, or running
461
+ // If success send the result of this component run. like component_output: This will have the output of the component
462
+ // Please send hasError, and error details where if the component is failed or has error the error should be provided. If the component is passed then this will be null and hasError false
463
+ // Send the component meta data if present like the duration run, token consumed, etc (This is optional)
464
+ "components": [
465
+ { "tool_name": "extract_text" },
466
+ { "tool_name": "summarize_text" }
467
+ ]
468
+ }
469
+ },
470
+ "intent": {
471
+ "intent": "pipeline_execute"
472
+ },
473
+ "chat_id": "550e8400-e29b-41d4-a716-446655440000",
474
+ "state": "initial",
475
+ "file": true,
476
+ "fileName": "report.pdf",
477
+ "fileUrl": "https://s3.amazonaws.com/..."
478
+ }
479
+ ```
480
+
481
+ #### **Scenario 6: Error**
482
+
483
+ **Response:**
484
+
485
+ ```json
486
+ {
487
+ // This should also have the message id, as this is a msg from the LLM
488
+ "assistant_response": "❌ Pipeline execution failed: ValueError: Input file is empty.",
489
+ "output": {},
490
+ "final_output": null,
491
+ // send hasError, if it has then the error should be provide in the exception if not this will be null and hasError will be false
492
+ "exception": "ValueError: Input file is empty.",
493
+ "api_response": {
494
+ // Dont change the api_response format, keep it same
495
+ // If the error is in a particular component then send error in the component level
496
+ "type": "error",
497
+ "error_code": "PIPELINE_EXECUTION_FAILED",
498
+ "message": "ValueError: Input file is empty."
499
+ },
500
+ "intent": {
501
+ "intent": "pipeline_execute"
502
+ },
503
+ "chat_id": "550e8400-e29b-41d4-a716-446655440000",
504
+ "state": "initial",
505
+ "file": true,
506
+ "fileName": "report.pdf",
507
+ "fileUrl": "https://s3.amazonaws.com/..."
508
+ }
509
+ ```
510
+
511
+ ---
512
+
513
+ ## 3. **Unified Chat (Streaming)**
514
+
515
+ ### `POST /api/v2/chat/unified/stream`
516
+
517
+ **Description:** Streaming version of the unified chat. Returns **NDJSON** (Newlines Delimited JSON). Each line is a JSON object.
518
+
519
+ **Event Type: `status`**
520
+
521
+ ```json
522
+ {
523
+ "type": "status",
524
+ "message": "Analyzing request and creating a pipeline...",
525
+ "chat_id": "550e8400-e29b-41d4-a716-446655440000",
526
+ "state": "initial"
527
+ }
528
+ ```
529
+
530
+ **Event Type: `assistant_final` (Typical Chat Response)**
531
+
532
+ ```json
533
+ {
534
+ "type": "assistant_final",
535
+ "content": "Hello! How can I help you today?",
536
+ "intent": {
537
+ "intent": "casual_chat",
538
+ "confidence": 0.99
539
+ },
540
+ "chat_id": "550e8400-e29b-41d4-a716-446655440000",
541
+ "state": "initial"
542
+ }
543
+ ```
544
+
545
+ **Event Type: `assistant_final` (Pipeline Proposed)**
546
+
547
+ ```json
548
+ {
549
+ "type": "assistant_final",
550
+ "content": "🎯 **Pipeline Created: Document Summarization**\nHere's what I'll do:\n 1. extract_text\n 2. summarize_text\n...",
551
+ "pipeline": {
552
+ "pipeline_id": "pipe_123abc",
553
+ "pipeline_name": "Document Summarization",
554
+ "components": [
555
+ { "tool_name": "extract_text" },
556
+ { "tool_name": "summarize_text" }
557
+ ]
558
+ },
559
+ "output": {
560
+ "pipeline_id": "pipe_123abc",
561
+ "pipeline_name": "Document Summarization",
562
+ "steps_count": 2,
563
+ "tools": ["extract_text", "summarize_text"]
564
+ },
565
+ "chat_id": "550e8400-e29b-41d4-a716-446655440000",
566
+ "state": "pipeline_proposed"
567
+ }
568
+ ```
569
+
570
+ **Event Type: `assistant_delta` (Streaming Execution Output)**
571
+
572
+ ```json
573
+ {
574
+ "type": "assistant_delta",
575
+ "content": "✅ Approved! Starting execution of: **Document Summarization**\n\n🚀 Processing, please wait...\n\n⏳ Step 1: extract_text - Processing...",
576
+ "chat_id": "550e8400-e29b-41d4-a716-446655440000",
577
+ "state": "executing"
578
+ }
579
+ ```
580
+
581
+ **Event Type: `assistant_final` (Execution Completed)**
582
+
583
+ ```json
584
+ {
585
+ "type": "assistant_final",
586
+ "content": "🎉 Pipeline Completed Successfully!\n- Pipeline: Document Summarization\n- Total Steps: 2\n- Successful: 2\n- Executor: Bedrock Agent\n\nThe Q3 financial report highlights...",
587
+ "result": {
588
+ "summary": "The Q3 financial report highlights...",
589
+ "full_text": "..."
590
+ },
591
+ "output": {
592
+ "component_summary": "Executed 2 steps successfully",
593
+ "steps_completed": 2,
594
+ "total_steps": 2
595
+ },
596
+ "final_output": {
597
+ "text": "The Q3 financial report highlights...",
598
+ "result": {
599
+ "summary": "The Q3 financial report highlights...",
600
+ "full_text": "..."
601
+ }
602
+ },
603
+ "chat_id": "550e8400-e29b-41d4-a716-446655440000",
604
+ "state": "initial"
605
+ }
606
+ ```
607
+
608
+ **Event Type: `assistant_final` (Error)**
609
+
610
+ ```json
611
+ {
612
+ "type": "assistant_final",
613
+ "content": "❌ Pipeline Execution Failed\n\nError: Service Unavailable",
614
+ "error": "Service Unavailable",
615
+ "exception": "Service Unavailable",
616
+ "chat_id": "550e8400-e29b-41d4-a716-446655440000",
617
+ "state": "initial"
618
+ }
619
+ ```
620
+
621
+ ---
622
+
623
+ ## 4. **File Management**
624
+
625
+ ### `POST /api/v2/chats/{chat_id}/upload`
626
+
627
+ **Description:** Direct file upload endpoint.
628
+
629
+ **Response:**
630
+
631
+ ```json
632
+ {
633
+ "status": "success",
634
+ "message": "File uploaded to S3",
635
+ "file": {
636
+ "bucket": "my-s3-bucket",
637
+ "key": "masterllm/550e8400-e29b-41d4-a716-446655440000/report.pdf",
638
+ "s3_uri": "s3://my-s3-bucket/masterllm/550e8400-e29b-41d4-a716-446655440000/report.pdf",
639
+ "presigned_url": "https://s3.amazonaws.com/my-s3-bucket/masterllm/550e8400-e29b-41d4-a716-446655440000/report.pdf?AMAZONPARAMS...",
640
+ "presigned_expires_at": "2023-11-22T08:30:00.000000Z"
641
+ },
642
+ "chat_id": "550e8400-e29b-41d4-a716-446655440000",
643
+ "next_action": "💬 Now tell me what you'd like to do with this document"
644
+ }
645
+ ```
646
+
647
+ ### `GET /api/v2/files/{file_id}/url`
648
+
649
+ **Description:** Regenerate a temporary presigned URL for a file.
650
+
651
+ **Response:**
652
+
653
+ ```json
654
+ {
655
+ "file_id": "masterllm/550e8400-e29b-41d4-a716-446655440000/report.pdf",
656
+ "presigned_url": "https://s3.amazonaws.com/my-s3-bucket/masterllm/550e8400-e29b-41d4-a716-446655440000/report.pdf?AMAZONPARAMS...",
657
+ "expires_at": "2023-11-23T08:30:00.000000Z"
658
+ }
659
+ ```
660
+
661
+ ---
662
+
663
+ ## 5. **Workflows**
664
+
665
+ ### `GET /api/v2/workflows`
666
+
667
+ **Description:** List saved workflows.
668
+
669
+ **Response:**
670
+
671
+ ```json
672
+ {
673
+ "workflows": [
674
+ {
675
+ "workflow_id": "flow_888",
676
+ "name": "Quarterly Report Analyzer",
677
+ "created_at": "2023-10-01T12:00:00Z",
678
+ "last_used": "2023-11-01T10:00:00Z",
679
+ "steps_count": 3
680
+ }
681
+ ],
682
+ "count": 1,
683
+ "total": 1
684
+ }
685
+ ```
686
+
687
+ ### `GET /api/v2/workflows/{workflow_id}`
688
+
689
+ **Description:** Get a single workflow definition.
690
+
691
+ **Response:**
692
+
693
+ ```json
694
+ {
695
+ "workflow_id": "flow_888",
696
+ "name": "Quarterly Report Analyzer",
697
+ "description": "Extracts text, summarizes key points, and extracts financial tables.",
698
+ "created_at": "2023-10-01T12:00:00Z",
699
+ "updated_at": "2023-10-05T09:00:00Z",
700
+ "definition": {
701
+ "pipeline_name": "Quarterly Report Analyzer",
702
+ // Please provide a component ID to unique identify each
703
+ // Please provide the status of each component, like status: success, failed, or running
704
+ // If success send the result of this component run. like component_output: This will have the output of the component
705
+ // Please send hasError, and error details where if the component is failed or has error the error should be provided. If the component is passed then this will be null and hasError false
706
+ // Send the component meta data if present like the duration run, token consumed, etc (This is optional)
707
+ "components": [
708
+ { "tool_name": "extract_text", "args": {} },
709
+ { "tool_name": "summarize", "args": { "focus": "financials" } },
710
+ { "tool_name": "extract_tables", "args": {} }
711
+ ]
712
+ },
713
+ "source_pipeline_id": "pipe_old_123",
714
+ "usage_count": 15
715
+ }
716
+ ```
717
+
718
+ ### `POST /api/v2/workflows/save`
719
+
720
+ **Description:** Save an existing pipeline as a reusable workflow.
721
+ **Parameters:** `pipeline_id` (form), `workflow_name` (form, optional)
722
+
723
+ **Response:**
724
+
725
+ ```json
726
+ {
727
+ "workflow_id": "flow_999",
728
+ "pipeline_name": "New Saved Workflow",
729
+ "source_pipeline_id": "pipe_123abc",
730
+ "pipeline_status": "completed",
731
+ "message": "Workflow saved successfully"
732
+ }
733
+ ```
734
+
735
+ ---
736
+
737
+ ## 6. **System**
738
+
739
+ ### `POST /api/v2/chats`
740
+
741
+ **Description:** Create a new empty chat session.
742
+
743
+ **Response:**
744
+
745
+ ```json
746
+ {
747
+ "chat_id": "550e8400-e29b-41d4-a716-446655440000"
748
+ }
749
+ ```
750
+
751
+ ### `GET /api/v2/health`
752
+
753
+ **Description:** Health check.
754
+
755
+ **Response:**
756
+
757
+ ```json
758
+ {
759
+ "status": "ok",
760
+ "service": "MasterLLM v2.0",
761
+ "time": "2023-11-15T08:30:00.000000Z"
762
+ }
763
+ ```
api_routes_v2.py CHANGED
@@ -72,11 +72,16 @@ def _get_conversation_s3_key(session_id: str) -> str:
72
  """Return the canonical S3 key for a session's conversation."""
73
  return f"{S3_PREFIX}/conversations/{session_id}.json"
74
 
75
- def _save_conversation_to_s3(session_id: str, messages: List[Dict[str, Any]]):
76
  """
77
  V3 RULE: Persist full conversation history to S3.
78
  MongoDB stores metadata only.
79
  This overwrites the existing file on every new message (simple append architecture).
 
 
 
 
 
80
  """
81
  key = _get_conversation_s3_key(session_id)
82
  try:
@@ -86,14 +91,19 @@ def _save_conversation_to_s3(session_id: str, messages: List[Dict[str, Any]]):
86
  Body=json.dumps(messages, ensure_ascii=False),
87
  ContentType="application/json"
88
  )
89
- # Update MongoDB with reference and stats (idempotent)
90
- session_manager.update_session(session_id, {
91
  "conversation_s3_key": key,
92
  "last_message_count": len(messages),
93
- "last_activity": datetime.utcnow().isoformat() + "Z",
94
  "last_updated": datetime.utcnow().isoformat() + "Z",
95
  "stats.message_count": len(messages)
96
- })
 
 
 
 
 
 
97
  except Exception as e:
98
  print(f"CRITICAL ERROR saving conversation to S3: {e}")
99
  # In a real system, we might want to retry or circuit break
@@ -141,14 +151,14 @@ def _validate_conversation_integrity(session_id: str) -> Dict[str, Any]:
141
  if msgs:
142
  # Auto-migrate old session to V3
143
  try:
144
- _save_conversation_to_s3(session_id, msgs)
145
  # Clear old MongoDB messages after successful migration
146
  session_manager.update_session(session_id, {"messages": []})
147
  return {"valid": True, "note": "Migrated old MongoDB messages to S3"}
148
  except Exception as e:
149
  return {"valid": False, "error": f"Migration failed: {str(e)}"}
150
  # New empty session - initialize S3
151
- _save_conversation_to_s3(session_id, [])
152
  return {"valid": True, "note": "Initialized new session"}
153
 
154
  try:
@@ -547,7 +557,7 @@ def _get_session_or_init(chat_id: str):
547
  # Create new session (metadata in Mongo)
548
  session_manager.update_session(chat_id, {"state": "initial"})
549
  # Initialize S3 conversation file (Source of Truth)
550
- _save_conversation_to_s3(chat_id, [])
551
  return session_manager.get_session(chat_id) or {"state": "initial"}
552
 
553
  # Validate integrity of existing session
@@ -586,6 +596,7 @@ def _add_and_mirror_message(chat_id: str, role: str, content: str, file_metadata
586
  """
587
  V3 RULE: Append message to S3 conversation.
588
  MongoDB metadata updated via _save_conversation_to_s3.
 
589
  """
590
  # 1. Load existing
591
  current_messages = _load_conversation_from_s3(chat_id)
@@ -609,8 +620,8 @@ def _add_and_mirror_message(chat_id: str, role: str, content: str, file_metadata
609
 
610
  current_messages.append(new_msg)
611
 
612
- # 3. Save to S3 (this updates MongoDB metadata too)
613
- _save_conversation_to_s3(chat_id, current_messages)
614
 
615
  # 4. Auto-generate chat name after first user message
616
  if role == "user":
 
72
  """Return the canonical S3 key for a session's conversation."""
73
  return f"{S3_PREFIX}/conversations/{session_id}.json"
74
 
75
+ def _save_conversation_to_s3(session_id: str, messages: List[Dict[str, Any]], update_activity: bool = False):
76
  """
77
  V3 RULE: Persist full conversation history to S3.
78
  MongoDB stores metadata only.
79
  This overwrites the existing file on every new message (simple append architecture).
80
+
81
+ Args:
82
+ session_id: Session ID
83
+ messages: List of messages to save
84
+ update_activity: If True, update last_activity timestamp (only for user messages)
85
  """
86
  key = _get_conversation_s3_key(session_id)
87
  try:
 
91
  Body=json.dumps(messages, ensure_ascii=False),
92
  ContentType="application/json"
93
  )
94
+ # Update MongoDB with reference and stats
95
+ updates = {
96
  "conversation_s3_key": key,
97
  "last_message_count": len(messages),
 
98
  "last_updated": datetime.utcnow().isoformat() + "Z",
99
  "stats.message_count": len(messages)
100
+ }
101
+
102
+ # Only update last_activity if explicitly requested (for user messages)
103
+ if update_activity:
104
+ updates["last_activity"] = datetime.utcnow().isoformat() + "Z"
105
+
106
+ session_manager.update_session(session_id, updates, update_activity=False)
107
  except Exception as e:
108
  print(f"CRITICAL ERROR saving conversation to S3: {e}")
109
  # In a real system, we might want to retry or circuit break
 
151
  if msgs:
152
  # Auto-migrate old session to V3
153
  try:
154
+ _save_conversation_to_s3(session_id, msgs, update_activity=False)
155
  # Clear old MongoDB messages after successful migration
156
  session_manager.update_session(session_id, {"messages": []})
157
  return {"valid": True, "note": "Migrated old MongoDB messages to S3"}
158
  except Exception as e:
159
  return {"valid": False, "error": f"Migration failed: {str(e)}"}
160
  # New empty session - initialize S3
161
+ _save_conversation_to_s3(session_id, [], update_activity=False)
162
  return {"valid": True, "note": "Initialized new session"}
163
 
164
  try:
 
557
  # Create new session (metadata in Mongo)
558
  session_manager.update_session(chat_id, {"state": "initial"})
559
  # Initialize S3 conversation file (Source of Truth)
560
+ _save_conversation_to_s3(chat_id, [], update_activity=False)
561
  return session_manager.get_session(chat_id) or {"state": "initial"}
562
 
563
  # Validate integrity of existing session
 
596
  """
597
  V3 RULE: Append message to S3 conversation.
598
  MongoDB metadata updated via _save_conversation_to_s3.
599
+ Only updates last_activity for user messages.
600
  """
601
  # 1. Load existing
602
  current_messages = _load_conversation_from_s3(chat_id)
 
620
 
621
  current_messages.append(new_msg)
622
 
623
+ # 3. Save to S3 - only update last_activity for user messages
624
+ _save_conversation_to_s3(chat_id, current_messages, update_activity=(role == "user"))
625
 
626
  # 4. Auto-generate chat name after first user message
627
  if role == "user":
services/session_manager.py CHANGED
@@ -244,20 +244,11 @@ class SessionManager:
244
  return messages
245
 
246
  def get_session(self, session_id: str) -> Optional[Dict[str, Any]]:
247
- """Get session metadata by ID"""
248
  session = self.sessions_collection.find_one(
249
  {"session_id": session_id},
250
  {"_id": 0}
251
  )
252
-
253
- if session:
254
- # Update last_activity timestamp
255
- now = datetime.utcnow()
256
- self.sessions_collection.update_one(
257
- {"session_id": session_id},
258
- {"$set": {"last_activity": now.isoformat() + "Z"}}
259
- )
260
-
261
  return session
262
 
263
  def get_all_sessions(
@@ -285,7 +276,8 @@ class SessionManager:
285
  def update_session(
286
  self,
287
  session_id: str,
288
- updates: Dict[str, Any]
 
289
  ) -> bool:
290
  """
291
  Update session metadata
@@ -293,12 +285,14 @@ class SessionManager:
293
  Args:
294
  session_id: Session ID
295
  updates: Fields to update
 
296
 
297
  Returns:
298
  True if successful
299
  """
300
- # Always update last_activity
301
- updates["last_activity"] = datetime.utcnow().isoformat() + "Z"
 
302
 
303
  result = self.sessions_collection.update_one(
304
  {"session_id": session_id},
 
244
  return messages
245
 
246
  def get_session(self, session_id: str) -> Optional[Dict[str, Any]]:
247
+ """Get session metadata by ID (read-only, does not update last_activity)"""
248
  session = self.sessions_collection.find_one(
249
  {"session_id": session_id},
250
  {"_id": 0}
251
  )
 
 
 
 
 
 
 
 
 
252
  return session
253
 
254
  def get_all_sessions(
 
276
  def update_session(
277
  self,
278
  session_id: str,
279
+ updates: Dict[str, Any],
280
+ update_activity: bool = False
281
  ) -> bool:
282
  """
283
  Update session metadata
 
285
  Args:
286
  session_id: Session ID
287
  updates: Fields to update
288
+ update_activity: If True, also update last_activity timestamp
289
 
290
  Returns:
291
  True if successful
292
  """
293
+ # Only update last_activity if explicitly requested
294
+ if update_activity and "last_activity" not in updates:
295
+ updates["last_activity"] = datetime.utcnow().isoformat() + "Z"
296
 
297
  result = self.sessions_collection.update_one(
298
  {"session_id": session_id},