@hileeon/mcc 0.1.8 → 0.1.9
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/README.md +226 -127
- package/dist/accounts/store.d.ts +1 -0
- package/dist/accounts/store.d.ts.map +1 -1
- package/dist/accounts/store.js.map +1 -1
- package/dist/commands/launch.d.ts +9 -0
- package/dist/commands/launch.d.ts.map +1 -0
- package/dist/commands/launch.js +158 -0
- package/dist/commands/launch.js.map +1 -0
- package/dist/commands/mcp.d.ts +9 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +112 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/profile.d.ts +8 -0
- package/dist/commands/profile.d.ts.map +1 -0
- package/dist/commands/profile.js +125 -0
- package/dist/commands/profile.js.map +1 -0
- package/dist/core/model-router.d.ts.map +1 -1
- package/dist/core/model-router.js +5 -2
- package/dist/core/model-router.js.map +1 -1
- package/dist/{dashboard-server.d.ts → dashboard/server.d.ts} +1 -1
- package/dist/dashboard/server.d.ts.map +1 -0
- package/dist/{dashboard-server.js → dashboard/server.js} +169 -51
- package/dist/dashboard/server.js.map +1 -0
- package/dist/mcc.d.ts +4 -2
- package/dist/mcc.d.ts.map +1 -1
- package/dist/mcc.js +121 -408
- package/dist/mcc.js.map +1 -1
- package/dist/mcp/mcp-config.d.ts +17 -1
- package/dist/mcp/mcp-config.d.ts.map +1 -1
- package/dist/mcp/mcp-config.js +50 -17
- package/dist/mcp/mcp-config.js.map +1 -1
- package/dist/proxy/proxy-daemon.d.ts.map +1 -1
- package/dist/proxy/proxy-daemon.js +17 -2
- package/dist/proxy/proxy-daemon.js.map +1 -1
- package/dist/proxy/proxy-entry.js +5 -3
- package/dist/proxy/proxy-entry.js.map +1 -1
- package/dist/proxy/proxy-server.d.ts.map +1 -1
- package/dist/proxy/proxy-server.js +32 -6
- package/dist/proxy/proxy-server.js.map +1 -1
- package/dist/shared/config.d.ts +15 -0
- package/dist/shared/config.d.ts.map +1 -0
- package/dist/shared/config.js +79 -0
- package/dist/shared/config.js.map +1 -0
- package/dist/shared/logger.d.ts +23 -18
- package/dist/shared/logger.d.ts.map +1 -1
- package/dist/shared/logger.js +17 -178
- package/dist/shared/logger.js.map +1 -1
- package/dist/shared/provider-preset-catalog.d.ts +6 -2
- package/dist/shared/provider-preset-catalog.d.ts.map +1 -1
- package/dist/shared/provider-preset-catalog.js +47 -26
- package/dist/shared/provider-preset-catalog.js.map +1 -1
- package/dist/ui/assets/index-ClqmrjNk.js +40 -0
- package/dist/ui/assets/index-CwMwQ-Z4.css +1 -0
- package/dist/ui/index.html +21 -13
- package/dist/update.d.ts +31 -0
- package/dist/update.d.ts.map +1 -0
- package/dist/update.js +196 -0
- package/dist/update.js.map +1 -0
- package/lib/mcp/mcc-image-analysis-server.cjs +454 -454
- package/lib/mcp/mcc-websearch-server.cjs +339 -339
- package/lib/mcp-hooks/image-analysis-runtime.cjs +510 -510
- package/lib/mcp-hooks/image-analyzer-transformer.cjs +526 -526
- package/lib/mcp-hooks/websearch-transformer.cjs +1597 -1421
- package/lib/proxy/config/config-loader-facade.js +24 -24
- package/lib/proxy/glmt/delta-accumulator.js +362 -362
- package/lib/proxy/glmt/glmt-transformer.js +203 -203
- package/lib/proxy/glmt/index.js +40 -40
- package/lib/proxy/glmt/locale-enforcer.js +68 -68
- package/lib/proxy/glmt/pipeline/content-transformer.js +161 -161
- package/lib/proxy/glmt/pipeline/index.js +19 -19
- package/lib/proxy/glmt/pipeline/request-transformer.js +115 -115
- package/lib/proxy/glmt/pipeline/response-builder.js +204 -204
- package/lib/proxy/glmt/pipeline/stream-parser.js +233 -233
- package/lib/proxy/glmt/pipeline/tool-call-handler.js +77 -77
- package/lib/proxy/glmt/pipeline/types.js +5 -5
- package/lib/proxy/glmt/reasoning-enforcer.js +150 -150
- package/lib/proxy/glmt/sse-parser.js +101 -101
- package/lib/proxy/services/logging.js +13 -13
- package/lib/proxy/transformers/request-transformer.js +471 -471
- package/lib/proxy/transformers/sse-stream-transformer.js +198 -198
- package/lib/shared/logger.cjs +156 -138
- package/package.json +58 -41
- package/dist/dashboard-server.d.ts.map +0 -1
- package/dist/dashboard-server.js.map +0 -1
- package/dist/ui/assets/index-B16lhKZ6.js +0 -40
- package/dist/ui/assets/index-jEfiB6-h.css +0 -1
|
@@ -1,234 +1,234 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* StreamParser - Transform OpenAI streaming deltas to Anthropic SSE events
|
|
4
|
-
*
|
|
5
|
-
* Responsibilities:
|
|
6
|
-
* - Process streaming deltas (reasoning_content, content, tool_calls)
|
|
7
|
-
* - Coordinate with accumulator for state tracking
|
|
8
|
-
* - Detect and handle planning loops
|
|
9
|
-
* - Generate appropriate Anthropic SSE events
|
|
10
|
-
*/
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.StreamParser = void 0;
|
|
13
|
-
const response_builder_1 = require("./response-builder");
|
|
14
|
-
const tool_call_handler_1 = require("./tool-call-handler");
|
|
15
|
-
class StreamParser {
|
|
16
|
-
constructor(config = {}) {
|
|
17
|
-
this.verbose = config.verbose || false;
|
|
18
|
-
this.debugMode = config.debugMode || false;
|
|
19
|
-
this.debugLog = config.debugLog || false;
|
|
20
|
-
this.responseBuilder = new response_builder_1.ResponseBuilder(this.verbose);
|
|
21
|
-
this.toolCallHandler = new tool_call_handler_1.ToolCallHandler();
|
|
22
|
-
this.writeDebugLog = config.writeDebugLog || (() => { });
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Transform OpenAI streaming delta to Anthropic events
|
|
26
|
-
*/
|
|
27
|
-
transformDelta(openaiEvent, accumulator) {
|
|
28
|
-
const events = [];
|
|
29
|
-
// Debug logging for streaming deltas
|
|
30
|
-
if (this.debugLog && openaiEvent.data) {
|
|
31
|
-
this.writeDebugLog('delta-openai', openaiEvent.data);
|
|
32
|
-
}
|
|
33
|
-
// Handle [DONE] marker
|
|
34
|
-
if (openaiEvent.event === 'done') {
|
|
35
|
-
if (!accumulator.isFinalized()) {
|
|
36
|
-
return this.finalizeDelta(accumulator);
|
|
37
|
-
}
|
|
38
|
-
return []; // Already finalized
|
|
39
|
-
}
|
|
40
|
-
// Usage update (appears in final chunk, may be before choice data)
|
|
41
|
-
if (openaiEvent.data?.usage) {
|
|
42
|
-
accumulator.updateUsage(openaiEvent.data.usage);
|
|
43
|
-
// If we have both usage AND finish_reason, finalize immediately
|
|
44
|
-
if (accumulator.getFinishReason()) {
|
|
45
|
-
events.push(...this.finalizeDelta(accumulator));
|
|
46
|
-
return events;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
const choice = openaiEvent.data?.choices?.[0];
|
|
50
|
-
if (!choice)
|
|
51
|
-
return events;
|
|
52
|
-
const delta = choice.delta;
|
|
53
|
-
if (!delta)
|
|
54
|
-
return events;
|
|
55
|
-
// Message start
|
|
56
|
-
if (!accumulator.isMessageStarted()) {
|
|
57
|
-
if (openaiEvent.data?.model) {
|
|
58
|
-
accumulator.setModel(openaiEvent.data.model);
|
|
59
|
-
}
|
|
60
|
-
events.push(this.responseBuilder.createMessageStartEvent(accumulator));
|
|
61
|
-
accumulator.setMessageStarted(true);
|
|
62
|
-
}
|
|
63
|
-
// Role
|
|
64
|
-
if (delta.role) {
|
|
65
|
-
accumulator.setRole(delta.role);
|
|
66
|
-
}
|
|
67
|
-
// Reasoning content delta
|
|
68
|
-
if (delta.reasoning_content) {
|
|
69
|
-
events.push(...this.handleReasoningDelta(delta.reasoning_content, accumulator));
|
|
70
|
-
}
|
|
71
|
-
// Text content delta
|
|
72
|
-
if (delta.content) {
|
|
73
|
-
events.push(...this.handleContentDelta(delta.content, accumulator));
|
|
74
|
-
}
|
|
75
|
-
// Check for planning loop
|
|
76
|
-
if (accumulator.checkForLoop()) {
|
|
77
|
-
this.log('WARNING: Planning loop detected - 3 consecutive thinking blocks with no tool calls');
|
|
78
|
-
this.log('Forcing early finalization to prevent unbounded planning');
|
|
79
|
-
events.push(...this.forceFinalization(accumulator));
|
|
80
|
-
return events;
|
|
81
|
-
}
|
|
82
|
-
// Tool calls deltas
|
|
83
|
-
if (delta.tool_calls && delta.tool_calls.length > 0) {
|
|
84
|
-
events.push(...this.handleToolCallDeltas(delta.tool_calls, accumulator));
|
|
85
|
-
}
|
|
86
|
-
// Finish reason
|
|
87
|
-
if (choice.finish_reason) {
|
|
88
|
-
accumulator.setFinishReason(choice.finish_reason);
|
|
89
|
-
// If we have both finish_reason AND usage, finalize immediately
|
|
90
|
-
if (accumulator.hasUsageReceived()) {
|
|
91
|
-
events.push(...this.finalizeDelta(accumulator));
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
// Debug logging for generated events
|
|
95
|
-
if (this.debugLog && events.length > 0) {
|
|
96
|
-
this.writeDebugLog('delta-anthropic-events', {
|
|
97
|
-
events,
|
|
98
|
-
accumulator: accumulator.getSummary(),
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
return events;
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Handle reasoning content delta
|
|
105
|
-
*/
|
|
106
|
-
handleReasoningDelta(reasoningContent, accumulator) {
|
|
107
|
-
const events = [];
|
|
108
|
-
const currentBlock = accumulator.getCurrentBlock();
|
|
109
|
-
if (this.debugMode) {
|
|
110
|
-
console.error(`[StreamParser] Reasoning delta: ${reasoningContent.length} chars`);
|
|
111
|
-
console.error(`[StreamParser] Current block: ${currentBlock?.type || 'none'}, index: ${currentBlock?.index ?? 'N/A'}`);
|
|
112
|
-
}
|
|
113
|
-
if (!currentBlock || currentBlock.type !== 'thinking') {
|
|
114
|
-
// Start thinking block
|
|
115
|
-
const block = accumulator.startBlock('thinking');
|
|
116
|
-
events.push(this.responseBuilder.createContentBlockStartEvent(block));
|
|
117
|
-
if (this.debugMode) {
|
|
118
|
-
console.error(`[StreamParser] Started new thinking block ${block.index}`);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
accumulator.addDelta(reasoningContent);
|
|
122
|
-
const currentThinkingBlock = accumulator.getCurrentBlock();
|
|
123
|
-
if (currentThinkingBlock) {
|
|
124
|
-
events.push(this.responseBuilder.createThinkingDeltaEvent(currentThinkingBlock, reasoningContent));
|
|
125
|
-
}
|
|
126
|
-
return events;
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Handle content delta
|
|
130
|
-
*/
|
|
131
|
-
handleContentDelta(content, accumulator) {
|
|
132
|
-
const events = [];
|
|
133
|
-
const currentBlock = accumulator.getCurrentBlock();
|
|
134
|
-
// Close thinking block if transitioning from thinking to text
|
|
135
|
-
if (currentBlock && currentBlock.type === 'thinking' && !currentBlock.stopped) {
|
|
136
|
-
events.push(...this.closeThinkingBlock(currentBlock, accumulator));
|
|
137
|
-
}
|
|
138
|
-
if (!accumulator.getCurrentBlock() || accumulator.getCurrentBlock()?.type !== 'text') {
|
|
139
|
-
// Start text block
|
|
140
|
-
const block = accumulator.startBlock('text');
|
|
141
|
-
events.push(this.responseBuilder.createContentBlockStartEvent(block));
|
|
142
|
-
}
|
|
143
|
-
accumulator.addDelta(content);
|
|
144
|
-
const currentTextBlock = accumulator.getCurrentBlock();
|
|
145
|
-
if (currentTextBlock) {
|
|
146
|
-
events.push(this.responseBuilder.createTextDeltaEvent(currentTextBlock, content));
|
|
147
|
-
}
|
|
148
|
-
return events;
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* Handle tool call deltas
|
|
152
|
-
*/
|
|
153
|
-
handleToolCallDeltas(toolCallDeltas, accumulator) {
|
|
154
|
-
const events = [];
|
|
155
|
-
if (!toolCallDeltas)
|
|
156
|
-
return events;
|
|
157
|
-
const currentBlock = accumulator.getCurrentBlock();
|
|
158
|
-
if (currentBlock && !currentBlock.stopped && currentBlock.type !== 'tool_use') {
|
|
159
|
-
if (currentBlock.type === 'thinking') {
|
|
160
|
-
events.push(...this.closeThinkingBlock(currentBlock, accumulator));
|
|
161
|
-
}
|
|
162
|
-
else {
|
|
163
|
-
events.push(this.responseBuilder.createContentBlockStopEvent(currentBlock));
|
|
164
|
-
accumulator.stopCurrentBlock();
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
events.push(...this.toolCallHandler.processToolCallDeltas(toolCallDeltas, accumulator));
|
|
168
|
-
return events;
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Close thinking block with signature
|
|
172
|
-
*/
|
|
173
|
-
closeThinkingBlock(block, accumulator) {
|
|
174
|
-
const events = [];
|
|
175
|
-
const signatureEvent = this.responseBuilder.createSignatureDeltaEvent(block);
|
|
176
|
-
if (signatureEvent) {
|
|
177
|
-
events.push(signatureEvent);
|
|
178
|
-
}
|
|
179
|
-
events.push(this.responseBuilder.createContentBlockStopEvent(block));
|
|
180
|
-
accumulator.stopCurrentBlock();
|
|
181
|
-
return events;
|
|
182
|
-
}
|
|
183
|
-
/**
|
|
184
|
-
* Force finalization due to loop detection
|
|
185
|
-
*/
|
|
186
|
-
forceFinalization(accumulator) {
|
|
187
|
-
const events = [];
|
|
188
|
-
const unstoppedBlocks = accumulator.getUnstoppedBlocks();
|
|
189
|
-
for (const block of unstoppedBlocks) {
|
|
190
|
-
if (block.type === 'thinking') {
|
|
191
|
-
const signatureEvent = this.responseBuilder.createSignatureDeltaEvent(block);
|
|
192
|
-
if (signatureEvent) {
|
|
193
|
-
events.push(signatureEvent);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
events.push(this.responseBuilder.createContentBlockStopEvent(block));
|
|
197
|
-
block.stopped = true;
|
|
198
|
-
}
|
|
199
|
-
events.push(...this.finalizeDelta(accumulator));
|
|
200
|
-
return events;
|
|
201
|
-
}
|
|
202
|
-
finalizeDelta(accumulator) {
|
|
203
|
-
if (accumulator.isFinalized()) {
|
|
204
|
-
return [];
|
|
205
|
-
}
|
|
206
|
-
const events = [];
|
|
207
|
-
const unstoppedBlocks = accumulator.getUnstoppedBlocks();
|
|
208
|
-
for (const block of unstoppedBlocks) {
|
|
209
|
-
if (block.type === 'thinking') {
|
|
210
|
-
const signatureEvent = this.responseBuilder.createSignatureDeltaEvent(block);
|
|
211
|
-
if (signatureEvent) {
|
|
212
|
-
events.push(signatureEvent);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
events.push(this.responseBuilder.createContentBlockStopEvent(block));
|
|
216
|
-
block.stopped = true;
|
|
217
|
-
}
|
|
218
|
-
const stopReason = this.responseBuilder.mapStopReason(accumulator.getFinishReason() || 'stop');
|
|
219
|
-
events.push(...this.responseBuilder.createFinalizationEvents(accumulator, stopReason));
|
|
220
|
-
accumulator.setFinalized(true);
|
|
221
|
-
return events;
|
|
222
|
-
}
|
|
223
|
-
/**
|
|
224
|
-
* Log message if verbose
|
|
225
|
-
*/
|
|
226
|
-
log(message) {
|
|
227
|
-
if (this.verbose) {
|
|
228
|
-
const timestamp = new Date().toTimeString().split(' ')[0]; // HH:MM:SS
|
|
229
|
-
console.error(`[StreamParser] [${timestamp}] ${message}`);
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
exports.StreamParser = StreamParser;
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* StreamParser - Transform OpenAI streaming deltas to Anthropic SSE events
|
|
4
|
+
*
|
|
5
|
+
* Responsibilities:
|
|
6
|
+
* - Process streaming deltas (reasoning_content, content, tool_calls)
|
|
7
|
+
* - Coordinate with accumulator for state tracking
|
|
8
|
+
* - Detect and handle planning loops
|
|
9
|
+
* - Generate appropriate Anthropic SSE events
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.StreamParser = void 0;
|
|
13
|
+
const response_builder_1 = require("./response-builder");
|
|
14
|
+
const tool_call_handler_1 = require("./tool-call-handler");
|
|
15
|
+
class StreamParser {
|
|
16
|
+
constructor(config = {}) {
|
|
17
|
+
this.verbose = config.verbose || false;
|
|
18
|
+
this.debugMode = config.debugMode || false;
|
|
19
|
+
this.debugLog = config.debugLog || false;
|
|
20
|
+
this.responseBuilder = new response_builder_1.ResponseBuilder(this.verbose);
|
|
21
|
+
this.toolCallHandler = new tool_call_handler_1.ToolCallHandler();
|
|
22
|
+
this.writeDebugLog = config.writeDebugLog || (() => { });
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Transform OpenAI streaming delta to Anthropic events
|
|
26
|
+
*/
|
|
27
|
+
transformDelta(openaiEvent, accumulator) {
|
|
28
|
+
const events = [];
|
|
29
|
+
// Debug logging for streaming deltas
|
|
30
|
+
if (this.debugLog && openaiEvent.data) {
|
|
31
|
+
this.writeDebugLog('delta-openai', openaiEvent.data);
|
|
32
|
+
}
|
|
33
|
+
// Handle [DONE] marker
|
|
34
|
+
if (openaiEvent.event === 'done') {
|
|
35
|
+
if (!accumulator.isFinalized()) {
|
|
36
|
+
return this.finalizeDelta(accumulator);
|
|
37
|
+
}
|
|
38
|
+
return []; // Already finalized
|
|
39
|
+
}
|
|
40
|
+
// Usage update (appears in final chunk, may be before choice data)
|
|
41
|
+
if (openaiEvent.data?.usage) {
|
|
42
|
+
accumulator.updateUsage(openaiEvent.data.usage);
|
|
43
|
+
// If we have both usage AND finish_reason, finalize immediately
|
|
44
|
+
if (accumulator.getFinishReason()) {
|
|
45
|
+
events.push(...this.finalizeDelta(accumulator));
|
|
46
|
+
return events;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
const choice = openaiEvent.data?.choices?.[0];
|
|
50
|
+
if (!choice)
|
|
51
|
+
return events;
|
|
52
|
+
const delta = choice.delta;
|
|
53
|
+
if (!delta)
|
|
54
|
+
return events;
|
|
55
|
+
// Message start
|
|
56
|
+
if (!accumulator.isMessageStarted()) {
|
|
57
|
+
if (openaiEvent.data?.model) {
|
|
58
|
+
accumulator.setModel(openaiEvent.data.model);
|
|
59
|
+
}
|
|
60
|
+
events.push(this.responseBuilder.createMessageStartEvent(accumulator));
|
|
61
|
+
accumulator.setMessageStarted(true);
|
|
62
|
+
}
|
|
63
|
+
// Role
|
|
64
|
+
if (delta.role) {
|
|
65
|
+
accumulator.setRole(delta.role);
|
|
66
|
+
}
|
|
67
|
+
// Reasoning content delta
|
|
68
|
+
if (delta.reasoning_content) {
|
|
69
|
+
events.push(...this.handleReasoningDelta(delta.reasoning_content, accumulator));
|
|
70
|
+
}
|
|
71
|
+
// Text content delta
|
|
72
|
+
if (delta.content) {
|
|
73
|
+
events.push(...this.handleContentDelta(delta.content, accumulator));
|
|
74
|
+
}
|
|
75
|
+
// Check for planning loop
|
|
76
|
+
if (accumulator.checkForLoop()) {
|
|
77
|
+
this.log('WARNING: Planning loop detected - 3 consecutive thinking blocks with no tool calls');
|
|
78
|
+
this.log('Forcing early finalization to prevent unbounded planning');
|
|
79
|
+
events.push(...this.forceFinalization(accumulator));
|
|
80
|
+
return events;
|
|
81
|
+
}
|
|
82
|
+
// Tool calls deltas
|
|
83
|
+
if (delta.tool_calls && delta.tool_calls.length > 0) {
|
|
84
|
+
events.push(...this.handleToolCallDeltas(delta.tool_calls, accumulator));
|
|
85
|
+
}
|
|
86
|
+
// Finish reason
|
|
87
|
+
if (choice.finish_reason) {
|
|
88
|
+
accumulator.setFinishReason(choice.finish_reason);
|
|
89
|
+
// If we have both finish_reason AND usage, finalize immediately
|
|
90
|
+
if (accumulator.hasUsageReceived()) {
|
|
91
|
+
events.push(...this.finalizeDelta(accumulator));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// Debug logging for generated events
|
|
95
|
+
if (this.debugLog && events.length > 0) {
|
|
96
|
+
this.writeDebugLog('delta-anthropic-events', {
|
|
97
|
+
events,
|
|
98
|
+
accumulator: accumulator.getSummary(),
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
return events;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Handle reasoning content delta
|
|
105
|
+
*/
|
|
106
|
+
handleReasoningDelta(reasoningContent, accumulator) {
|
|
107
|
+
const events = [];
|
|
108
|
+
const currentBlock = accumulator.getCurrentBlock();
|
|
109
|
+
if (this.debugMode) {
|
|
110
|
+
console.error(`[StreamParser] Reasoning delta: ${reasoningContent.length} chars`);
|
|
111
|
+
console.error(`[StreamParser] Current block: ${currentBlock?.type || 'none'}, index: ${currentBlock?.index ?? 'N/A'}`);
|
|
112
|
+
}
|
|
113
|
+
if (!currentBlock || currentBlock.type !== 'thinking') {
|
|
114
|
+
// Start thinking block
|
|
115
|
+
const block = accumulator.startBlock('thinking');
|
|
116
|
+
events.push(this.responseBuilder.createContentBlockStartEvent(block));
|
|
117
|
+
if (this.debugMode) {
|
|
118
|
+
console.error(`[StreamParser] Started new thinking block ${block.index}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
accumulator.addDelta(reasoningContent);
|
|
122
|
+
const currentThinkingBlock = accumulator.getCurrentBlock();
|
|
123
|
+
if (currentThinkingBlock) {
|
|
124
|
+
events.push(this.responseBuilder.createThinkingDeltaEvent(currentThinkingBlock, reasoningContent));
|
|
125
|
+
}
|
|
126
|
+
return events;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Handle content delta
|
|
130
|
+
*/
|
|
131
|
+
handleContentDelta(content, accumulator) {
|
|
132
|
+
const events = [];
|
|
133
|
+
const currentBlock = accumulator.getCurrentBlock();
|
|
134
|
+
// Close thinking block if transitioning from thinking to text
|
|
135
|
+
if (currentBlock && currentBlock.type === 'thinking' && !currentBlock.stopped) {
|
|
136
|
+
events.push(...this.closeThinkingBlock(currentBlock, accumulator));
|
|
137
|
+
}
|
|
138
|
+
if (!accumulator.getCurrentBlock() || accumulator.getCurrentBlock()?.type !== 'text') {
|
|
139
|
+
// Start text block
|
|
140
|
+
const block = accumulator.startBlock('text');
|
|
141
|
+
events.push(this.responseBuilder.createContentBlockStartEvent(block));
|
|
142
|
+
}
|
|
143
|
+
accumulator.addDelta(content);
|
|
144
|
+
const currentTextBlock = accumulator.getCurrentBlock();
|
|
145
|
+
if (currentTextBlock) {
|
|
146
|
+
events.push(this.responseBuilder.createTextDeltaEvent(currentTextBlock, content));
|
|
147
|
+
}
|
|
148
|
+
return events;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Handle tool call deltas
|
|
152
|
+
*/
|
|
153
|
+
handleToolCallDeltas(toolCallDeltas, accumulator) {
|
|
154
|
+
const events = [];
|
|
155
|
+
if (!toolCallDeltas)
|
|
156
|
+
return events;
|
|
157
|
+
const currentBlock = accumulator.getCurrentBlock();
|
|
158
|
+
if (currentBlock && !currentBlock.stopped && currentBlock.type !== 'tool_use') {
|
|
159
|
+
if (currentBlock.type === 'thinking') {
|
|
160
|
+
events.push(...this.closeThinkingBlock(currentBlock, accumulator));
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
events.push(this.responseBuilder.createContentBlockStopEvent(currentBlock));
|
|
164
|
+
accumulator.stopCurrentBlock();
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
events.push(...this.toolCallHandler.processToolCallDeltas(toolCallDeltas, accumulator));
|
|
168
|
+
return events;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Close thinking block with signature
|
|
172
|
+
*/
|
|
173
|
+
closeThinkingBlock(block, accumulator) {
|
|
174
|
+
const events = [];
|
|
175
|
+
const signatureEvent = this.responseBuilder.createSignatureDeltaEvent(block);
|
|
176
|
+
if (signatureEvent) {
|
|
177
|
+
events.push(signatureEvent);
|
|
178
|
+
}
|
|
179
|
+
events.push(this.responseBuilder.createContentBlockStopEvent(block));
|
|
180
|
+
accumulator.stopCurrentBlock();
|
|
181
|
+
return events;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Force finalization due to loop detection
|
|
185
|
+
*/
|
|
186
|
+
forceFinalization(accumulator) {
|
|
187
|
+
const events = [];
|
|
188
|
+
const unstoppedBlocks = accumulator.getUnstoppedBlocks();
|
|
189
|
+
for (const block of unstoppedBlocks) {
|
|
190
|
+
if (block.type === 'thinking') {
|
|
191
|
+
const signatureEvent = this.responseBuilder.createSignatureDeltaEvent(block);
|
|
192
|
+
if (signatureEvent) {
|
|
193
|
+
events.push(signatureEvent);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
events.push(this.responseBuilder.createContentBlockStopEvent(block));
|
|
197
|
+
block.stopped = true;
|
|
198
|
+
}
|
|
199
|
+
events.push(...this.finalizeDelta(accumulator));
|
|
200
|
+
return events;
|
|
201
|
+
}
|
|
202
|
+
finalizeDelta(accumulator) {
|
|
203
|
+
if (accumulator.isFinalized()) {
|
|
204
|
+
return [];
|
|
205
|
+
}
|
|
206
|
+
const events = [];
|
|
207
|
+
const unstoppedBlocks = accumulator.getUnstoppedBlocks();
|
|
208
|
+
for (const block of unstoppedBlocks) {
|
|
209
|
+
if (block.type === 'thinking') {
|
|
210
|
+
const signatureEvent = this.responseBuilder.createSignatureDeltaEvent(block);
|
|
211
|
+
if (signatureEvent) {
|
|
212
|
+
events.push(signatureEvent);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
events.push(this.responseBuilder.createContentBlockStopEvent(block));
|
|
216
|
+
block.stopped = true;
|
|
217
|
+
}
|
|
218
|
+
const stopReason = this.responseBuilder.mapStopReason(accumulator.getFinishReason() || 'stop');
|
|
219
|
+
events.push(...this.responseBuilder.createFinalizationEvents(accumulator, stopReason));
|
|
220
|
+
accumulator.setFinalized(true);
|
|
221
|
+
return events;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Log message if verbose
|
|
225
|
+
*/
|
|
226
|
+
log(message) {
|
|
227
|
+
if (this.verbose) {
|
|
228
|
+
const timestamp = new Date().toTimeString().split(' ')[0]; // HH:MM:SS
|
|
229
|
+
console.error(`[StreamParser] [${timestamp}] ${message}`);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
exports.StreamParser = StreamParser;
|
|
234
234
|
//# sourceMappingURL=stream-parser.js.map
|
|
@@ -1,78 +1,78 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* ToolCallHandler - Handle tool call processing for streaming responses
|
|
4
|
-
*
|
|
5
|
-
* Responsibilities:
|
|
6
|
-
* - Process tool call deltas from OpenAI
|
|
7
|
-
* - Generate tool_use content blocks for Anthropic format
|
|
8
|
-
* - Handle input_json_delta events
|
|
9
|
-
*/
|
|
10
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
-
exports.ToolCallHandler = void 0;
|
|
12
|
-
class ToolCallHandler {
|
|
13
|
-
processToolCalls(toolCalls) {
|
|
14
|
-
const content = [];
|
|
15
|
-
for (const toolCall of toolCalls) {
|
|
16
|
-
let parsedInput;
|
|
17
|
-
try {
|
|
18
|
-
parsedInput = JSON.parse(toolCall.function.arguments || '{}');
|
|
19
|
-
}
|
|
20
|
-
catch (parseError) {
|
|
21
|
-
const err = parseError;
|
|
22
|
-
console.error(`[ToolCallHandler] Invalid JSON in tool arguments: ${err.message}`);
|
|
23
|
-
parsedInput = { _error: 'Invalid JSON', _raw: toolCall.function.arguments };
|
|
24
|
-
}
|
|
25
|
-
content.push({
|
|
26
|
-
type: 'tool_use',
|
|
27
|
-
id: toolCall.id,
|
|
28
|
-
name: toolCall.function.name,
|
|
29
|
-
input: parsedInput,
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
return content;
|
|
33
|
-
}
|
|
34
|
-
processToolCallDeltas(toolCallDeltas, accumulator) {
|
|
35
|
-
const events = [];
|
|
36
|
-
for (const toolCallDelta of toolCallDeltas) {
|
|
37
|
-
const isNewToolCall = !accumulator.hasToolCall(toolCallDelta.index);
|
|
38
|
-
accumulator.addToolCallDelta(toolCallDelta);
|
|
39
|
-
if (isNewToolCall) {
|
|
40
|
-
// OpenAI may interleave tool_call fragments across chunks, so blocks must stay open
|
|
41
|
-
// until the stream finalizes. Closing on a later index truncates earlier tool input.
|
|
42
|
-
const block = accumulator.startBlock('tool_use');
|
|
43
|
-
const toolCall = accumulator.getToolCall(toolCallDelta.index);
|
|
44
|
-
accumulator.setToolCallBlockIndex(toolCallDelta.index, block.index);
|
|
45
|
-
events.push({
|
|
46
|
-
event: 'content_block_start',
|
|
47
|
-
data: {
|
|
48
|
-
type: 'content_block_start',
|
|
49
|
-
index: block.index,
|
|
50
|
-
content_block: {
|
|
51
|
-
type: 'tool_use',
|
|
52
|
-
id: toolCall?.id || `tool_${toolCallDelta.index}`,
|
|
53
|
-
name: toolCall?.function?.name || '',
|
|
54
|
-
input: {},
|
|
55
|
-
},
|
|
56
|
-
},
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
if (toolCallDelta.function?.arguments) {
|
|
60
|
-
const toolCallBlockIndex = accumulator.getToolCallBlockIndex(toolCallDelta.index);
|
|
61
|
-
events.push({
|
|
62
|
-
event: 'content_block_delta',
|
|
63
|
-
data: {
|
|
64
|
-
type: 'content_block_delta',
|
|
65
|
-
index: toolCallBlockIndex,
|
|
66
|
-
delta: {
|
|
67
|
-
type: 'input_json_delta',
|
|
68
|
-
partial_json: toolCallDelta.function.arguments,
|
|
69
|
-
},
|
|
70
|
-
},
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
return events;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
exports.ToolCallHandler = ToolCallHandler;
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ToolCallHandler - Handle tool call processing for streaming responses
|
|
4
|
+
*
|
|
5
|
+
* Responsibilities:
|
|
6
|
+
* - Process tool call deltas from OpenAI
|
|
7
|
+
* - Generate tool_use content blocks for Anthropic format
|
|
8
|
+
* - Handle input_json_delta events
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.ToolCallHandler = void 0;
|
|
12
|
+
class ToolCallHandler {
|
|
13
|
+
processToolCalls(toolCalls) {
|
|
14
|
+
const content = [];
|
|
15
|
+
for (const toolCall of toolCalls) {
|
|
16
|
+
let parsedInput;
|
|
17
|
+
try {
|
|
18
|
+
parsedInput = JSON.parse(toolCall.function.arguments || '{}');
|
|
19
|
+
}
|
|
20
|
+
catch (parseError) {
|
|
21
|
+
const err = parseError;
|
|
22
|
+
console.error(`[ToolCallHandler] Invalid JSON in tool arguments: ${err.message}`);
|
|
23
|
+
parsedInput = { _error: 'Invalid JSON', _raw: toolCall.function.arguments };
|
|
24
|
+
}
|
|
25
|
+
content.push({
|
|
26
|
+
type: 'tool_use',
|
|
27
|
+
id: toolCall.id,
|
|
28
|
+
name: toolCall.function.name,
|
|
29
|
+
input: parsedInput,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
return content;
|
|
33
|
+
}
|
|
34
|
+
processToolCallDeltas(toolCallDeltas, accumulator) {
|
|
35
|
+
const events = [];
|
|
36
|
+
for (const toolCallDelta of toolCallDeltas) {
|
|
37
|
+
const isNewToolCall = !accumulator.hasToolCall(toolCallDelta.index);
|
|
38
|
+
accumulator.addToolCallDelta(toolCallDelta);
|
|
39
|
+
if (isNewToolCall) {
|
|
40
|
+
// OpenAI may interleave tool_call fragments across chunks, so blocks must stay open
|
|
41
|
+
// until the stream finalizes. Closing on a later index truncates earlier tool input.
|
|
42
|
+
const block = accumulator.startBlock('tool_use');
|
|
43
|
+
const toolCall = accumulator.getToolCall(toolCallDelta.index);
|
|
44
|
+
accumulator.setToolCallBlockIndex(toolCallDelta.index, block.index);
|
|
45
|
+
events.push({
|
|
46
|
+
event: 'content_block_start',
|
|
47
|
+
data: {
|
|
48
|
+
type: 'content_block_start',
|
|
49
|
+
index: block.index,
|
|
50
|
+
content_block: {
|
|
51
|
+
type: 'tool_use',
|
|
52
|
+
id: toolCall?.id || `tool_${toolCallDelta.index}`,
|
|
53
|
+
name: toolCall?.function?.name || '',
|
|
54
|
+
input: {},
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
if (toolCallDelta.function?.arguments) {
|
|
60
|
+
const toolCallBlockIndex = accumulator.getToolCallBlockIndex(toolCallDelta.index);
|
|
61
|
+
events.push({
|
|
62
|
+
event: 'content_block_delta',
|
|
63
|
+
data: {
|
|
64
|
+
type: 'content_block_delta',
|
|
65
|
+
index: toolCallBlockIndex,
|
|
66
|
+
delta: {
|
|
67
|
+
type: 'input_json_delta',
|
|
68
|
+
partial_json: toolCallDelta.function.arguments,
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return events;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.ToolCallHandler = ToolCallHandler;
|
|
78
78
|
//# sourceMappingURL=tool-call-handler.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Pipeline Types - Shared types for GLMT transformation pipeline
|
|
4
|
-
*/
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Pipeline Types - Shared types for GLMT transformation pipeline
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
//# sourceMappingURL=types.js.map
|