@hileeon/mcc 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/.claude/CLAUDE.md +204 -0
  2. package/.claude/agents/.gitkeep +0 -0
  3. package/.claude/settings.json +9 -0
  4. package/.claude/skills/.gitkeep +0 -0
  5. package/README.md +127 -0
  6. package/dist/accounts/instance-manager.d.ts +11 -0
  7. package/dist/accounts/instance-manager.d.ts.map +1 -0
  8. package/dist/accounts/instance-manager.js +89 -0
  9. package/dist/accounts/instance-manager.js.map +1 -0
  10. package/dist/accounts/shared-manager.d.ts +25 -0
  11. package/dist/accounts/shared-manager.d.ts.map +1 -0
  12. package/dist/accounts/shared-manager.js +186 -0
  13. package/dist/accounts/shared-manager.js.map +1 -0
  14. package/dist/accounts/store.d.ts +30 -0
  15. package/dist/accounts/store.d.ts.map +1 -0
  16. package/dist/accounts/store.js +128 -0
  17. package/dist/accounts/store.js.map +1 -0
  18. package/dist/core/model-router.d.ts +30 -0
  19. package/dist/core/model-router.d.ts.map +1 -0
  20. package/dist/core/model-router.js +64 -0
  21. package/dist/core/model-router.js.map +1 -0
  22. package/dist/dashboard-server.d.ts +5 -0
  23. package/dist/dashboard-server.d.ts.map +1 -0
  24. package/dist/dashboard-server.js +387 -0
  25. package/dist/dashboard-server.js.map +1 -0
  26. package/dist/mcc.d.ts +8 -0
  27. package/dist/mcc.d.ts.map +1 -0
  28. package/dist/mcc.js +474 -0
  29. package/dist/mcc.js.map +1 -0
  30. package/dist/mcp/external-registry.d.ts +24 -0
  31. package/dist/mcp/external-registry.d.ts.map +1 -0
  32. package/dist/mcp/external-registry.js +99 -0
  33. package/dist/mcp/external-registry.js.map +1 -0
  34. package/dist/mcp/installer.d.ts +31 -0
  35. package/dist/mcp/installer.d.ts.map +1 -0
  36. package/dist/mcp/installer.js +273 -0
  37. package/dist/mcp/installer.js.map +1 -0
  38. package/dist/mcp/mcp-config.d.ts +86 -0
  39. package/dist/mcp/mcp-config.d.ts.map +1 -0
  40. package/dist/mcp/mcp-config.js +178 -0
  41. package/dist/mcp/mcp-config.js.map +1 -0
  42. package/dist/mcp/registry.d.ts +23 -0
  43. package/dist/mcp/registry.d.ts.map +1 -0
  44. package/dist/mcp/registry.js +100 -0
  45. package/dist/mcp/registry.js.map +1 -0
  46. package/dist/proxy/proxy-daemon.d.ts +27 -0
  47. package/dist/proxy/proxy-daemon.d.ts.map +1 -0
  48. package/dist/proxy/proxy-daemon.js +192 -0
  49. package/dist/proxy/proxy-daemon.js.map +1 -0
  50. package/dist/proxy/proxy-entry.d.ts +11 -0
  51. package/dist/proxy/proxy-entry.d.ts.map +1 -0
  52. package/dist/proxy/proxy-entry.js +74 -0
  53. package/dist/proxy/proxy-entry.js.map +1 -0
  54. package/dist/proxy/proxy-paths.d.ts +27 -0
  55. package/dist/proxy/proxy-paths.d.ts.map +1 -0
  56. package/dist/proxy/proxy-paths.js +125 -0
  57. package/dist/proxy/proxy-paths.js.map +1 -0
  58. package/dist/proxy/proxy-server.d.ts +20 -0
  59. package/dist/proxy/proxy-server.d.ts.map +1 -0
  60. package/dist/proxy/proxy-server.js +280 -0
  61. package/dist/proxy/proxy-server.js.map +1 -0
  62. package/dist/proxy/upstream-url.d.ts +7 -0
  63. package/dist/proxy/upstream-url.d.ts.map +1 -0
  64. package/dist/proxy/upstream-url.js +38 -0
  65. package/dist/proxy/upstream-url.js.map +1 -0
  66. package/dist/shared/logger.d.ts +23 -0
  67. package/dist/shared/logger.d.ts.map +1 -0
  68. package/dist/shared/logger.js +184 -0
  69. package/dist/shared/logger.js.map +1 -0
  70. package/dist/shared/provider-preset-catalog.d.ts +41 -0
  71. package/dist/shared/provider-preset-catalog.d.ts.map +1 -0
  72. package/dist/shared/provider-preset-catalog.js +299 -0
  73. package/dist/shared/provider-preset-catalog.js.map +1 -0
  74. package/docs/decisions.md +33 -0
  75. package/docs/lessons.md +8 -0
  76. package/docs/product.md +37 -0
  77. package/lib/mcp/mcc-image-analysis-server.cjs +454 -0
  78. package/lib/mcp/mcc-websearch-server.cjs +339 -0
  79. package/lib/mcp-hooks/image-analysis-runtime.cjs +510 -0
  80. package/lib/mcp-hooks/image-analyzer-transformer.cjs +526 -0
  81. package/lib/mcp-hooks/websearch-transformer.cjs +1421 -0
  82. package/lib/proxy/config/config-loader-facade.js +24 -0
  83. package/lib/proxy/glmt/delta-accumulator.js +363 -0
  84. package/lib/proxy/glmt/glmt-transformer.js +204 -0
  85. package/lib/proxy/glmt/index.js +41 -0
  86. package/lib/proxy/glmt/locale-enforcer.js +69 -0
  87. package/lib/proxy/glmt/pipeline/content-transformer.js +162 -0
  88. package/lib/proxy/glmt/pipeline/index.js +20 -0
  89. package/lib/proxy/glmt/pipeline/request-transformer.js +116 -0
  90. package/lib/proxy/glmt/pipeline/response-builder.js +205 -0
  91. package/lib/proxy/glmt/pipeline/stream-parser.js +234 -0
  92. package/lib/proxy/glmt/pipeline/tool-call-handler.js +78 -0
  93. package/lib/proxy/glmt/pipeline/types.js +6 -0
  94. package/lib/proxy/glmt/reasoning-enforcer.js +151 -0
  95. package/lib/proxy/glmt/sse-parser.js +102 -0
  96. package/lib/proxy/services/logging.js +13 -0
  97. package/lib/proxy/transformers/request-transformer.js +452 -0
  98. package/lib/proxy/transformers/sse-stream-transformer.js +199 -0
  99. package/lib/shared/logger.cjs +138 -0
  100. package/package.json +35 -0
  101. package/src/accounts/instance-manager.ts +58 -0
  102. package/src/accounts/shared-manager.ts +154 -0
  103. package/src/accounts/store.ts +111 -0
  104. package/src/core/model-router.ts +82 -0
  105. package/src/dashboard-server.ts +407 -0
  106. package/src/mcc.ts +474 -0
  107. package/src/mcp/external-registry.ts +73 -0
  108. package/src/mcp/installer.ts +258 -0
  109. package/src/mcp/mcp-config.ts +168 -0
  110. package/src/mcp/registry.ts +89 -0
  111. package/src/proxy/proxy-daemon.ts +184 -0
  112. package/src/proxy/proxy-entry.ts +63 -0
  113. package/src/proxy/proxy-paths.ts +97 -0
  114. package/src/proxy/proxy-server.ts +278 -0
  115. package/src/proxy/upstream-url.ts +38 -0
  116. package/src/shared/logger.ts +140 -0
  117. package/src/shared/provider-preset-catalog.ts +340 -0
  118. package/tsconfig.json +33 -0
  119. package/ui/.prettierrc +9 -0
  120. package/ui/index.html +12 -0
  121. package/ui/package.json +33 -0
  122. package/ui/postcss.config.js +6 -0
  123. package/ui/src/App.tsx +753 -0
  124. package/ui/src/components/ui/button.tsx +48 -0
  125. package/ui/src/components/ui/card.tsx +50 -0
  126. package/ui/src/components/ui/input.tsx +21 -0
  127. package/ui/src/components/ui/label.tsx +20 -0
  128. package/ui/src/components/ui/select.tsx +80 -0
  129. package/ui/src/components/ui/switch.tsx +26 -0
  130. package/ui/src/components/ui/tabs.tsx +52 -0
  131. package/ui/src/index.css +33 -0
  132. package/ui/src/lib/api.ts +185 -0
  133. package/ui/src/lib/utils.ts +6 -0
  134. package/ui/src/main.tsx +10 -0
  135. package/ui/src/vite-env.d.ts +1 -0
  136. package/ui/tailwind.config.js +49 -0
  137. package/ui/tsconfig.json +25 -0
  138. package/ui/vite.config.ts +20 -0
@@ -0,0 +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;
234
+ //# sourceMappingURL=stream-parser.js.map
@@ -0,0 +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;
78
+ //# sourceMappingURL=tool-call-handler.js.map
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ /**
3
+ * Pipeline Types - Shared types for GLMT transformation pipeline
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,151 @@
1
+ "use strict";
2
+ /**
3
+ * ReasoningEnforcer - Inject explicit reasoning instructions into prompts
4
+ *
5
+ * Purpose: Force GLM models to use structured reasoning output format (<reasoning_content>)
6
+ * This complements API parameters (reasoning: true) with explicit prompt instructions.
7
+ *
8
+ * Strategy:
9
+ * 1. If system prompt exists: Prepend reasoning instruction
10
+ * 2. If no system prompt: Prepend to first user message
11
+ * 3. Select prompt template based on effort level (low/medium/high/max)
12
+ * 4. Preserve message structure (string vs array content)
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.ReasoningEnforcer = void 0;
16
+ class ReasoningEnforcer {
17
+ constructor(options = {}) {
18
+ this.enabled = options.enabled ?? false; // Opt-in by default
19
+ this.prompts = options.prompts || this.getDefaultPrompts();
20
+ }
21
+ /**
22
+ * Inject reasoning instruction into messages
23
+ * @param messages - Messages array to modify
24
+ * @param thinkingConfig - { thinking: boolean, effort: string }
25
+ * @returns Modified messages array
26
+ */
27
+ injectInstruction(messages, thinkingConfig = {}) {
28
+ // Only inject if enabled or thinking explicitly requested
29
+ if (!this.enabled && !thinkingConfig.thinking) {
30
+ return messages;
31
+ }
32
+ // Clone messages to avoid mutation
33
+ const modifiedMessages = JSON.parse(JSON.stringify(messages));
34
+ // Select prompt based on effort level
35
+ const effort = (thinkingConfig.effort?.toLowerCase() || 'medium');
36
+ const prompt = this.selectPrompt(effort);
37
+ // Strategy 1: Inject into system prompt (preferred)
38
+ const systemIndex = modifiedMessages.findIndex((m) => m.role === 'system');
39
+ if (systemIndex >= 0) {
40
+ const systemMsg = modifiedMessages[systemIndex];
41
+ if (typeof systemMsg.content === 'string') {
42
+ systemMsg.content = `${prompt}\n\n${systemMsg.content}`;
43
+ }
44
+ else if (Array.isArray(systemMsg.content)) {
45
+ systemMsg.content.unshift({
46
+ type: 'text',
47
+ text: prompt,
48
+ });
49
+ }
50
+ return modifiedMessages;
51
+ }
52
+ // Strategy 2: Prepend to first user message
53
+ const userIndex = modifiedMessages.findIndex((m) => m.role === 'user');
54
+ if (userIndex >= 0) {
55
+ const userMsg = modifiedMessages[userIndex];
56
+ if (typeof userMsg.content === 'string') {
57
+ userMsg.content = `${prompt}\n\n${userMsg.content}`;
58
+ }
59
+ else if (Array.isArray(userMsg.content)) {
60
+ userMsg.content.unshift({
61
+ type: 'text',
62
+ text: prompt,
63
+ });
64
+ }
65
+ return modifiedMessages;
66
+ }
67
+ // No system or user messages found (edge case)
68
+ return modifiedMessages;
69
+ }
70
+ /**
71
+ * Select prompt template based on effort level
72
+ */
73
+ selectPrompt(effort) {
74
+ return this.prompts[effort] || this.prompts.medium;
75
+ }
76
+ /**
77
+ * Get default prompt templates
78
+ */
79
+ getDefaultPrompts() {
80
+ return {
81
+ low: `You are an expert reasoning model using GLM-4.6 architecture.
82
+
83
+ CRITICAL: Before answering, write 2-3 sentences of reasoning in <reasoning_content> tags.
84
+
85
+ OUTPUT FORMAT:
86
+ <reasoning_content>
87
+ (Brief analysis: what is the problem? what's the approach?)
88
+ </reasoning_content>
89
+
90
+ (Write your final answer here)`,
91
+ medium: `You are an expert reasoning model using GLM-4.6 architecture.
92
+
93
+ CRITICAL REQUIREMENTS:
94
+ 1. Always think step-by-step before answering
95
+ 2. Write your reasoning process explicitly in <reasoning_content> tags
96
+ 3. Never skip your chain of thought, even for simple problems
97
+
98
+ OUTPUT FORMAT:
99
+ <reasoning_content>
100
+ (Write your detailed thinking here: analyze the problem, explore approaches,
101
+ evaluate trade-offs, and arrive at a conclusion)
102
+ </reasoning_content>
103
+
104
+ (Write your final answer here based on your reasoning above)`,
105
+ high: `You are an expert reasoning model using GLM-4.6 architecture.
106
+
107
+ CRITICAL REQUIREMENTS:
108
+ 1. Think deeply and systematically before answering
109
+ 2. Write comprehensive reasoning in <reasoning_content> tags
110
+ 3. Explore multiple approaches and evaluate trade-offs
111
+ 4. Show all steps in your problem-solving process
112
+
113
+ OUTPUT FORMAT:
114
+ <reasoning_content>
115
+ (Write exhaustive analysis here:
116
+ - Problem decomposition
117
+ - Multiple approach exploration
118
+ - Trade-off analysis for each approach
119
+ - Edge case consideration
120
+ - Final conclusion with justification)
121
+ </reasoning_content>
122
+
123
+ (Write your final answer here based on your systematic reasoning above)`,
124
+ max: `You are an expert reasoning model using GLM-4.6 architecture.
125
+
126
+ CRITICAL REQUIREMENTS:
127
+ 1. Think exhaustively from first principles
128
+ 2. Write extremely detailed reasoning in <reasoning_content> tags
129
+ 3. Analyze ALL possible angles, approaches, and edge cases
130
+ 4. Challenge your own assumptions and explore alternatives
131
+ 5. Provide rigorous justification for every claim
132
+
133
+ OUTPUT FORMAT:
134
+ <reasoning_content>
135
+ (Write comprehensive analysis here:
136
+ - First principles breakdown
137
+ - Exhaustive approach enumeration
138
+ - Comparative analysis of all approaches
139
+ - Edge case and failure mode analysis
140
+ - Assumption validation
141
+ - Counter-argument consideration
142
+ - Final conclusion with rigorous justification)
143
+ </reasoning_content>
144
+
145
+ (Write your final answer here based on your exhaustive reasoning above)`,
146
+ };
147
+ }
148
+ }
149
+ exports.ReasoningEnforcer = ReasoningEnforcer;
150
+ exports.default = ReasoningEnforcer;
151
+ //# sourceMappingURL=reasoning-enforcer.js.map
@@ -0,0 +1,102 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * SSEParser - Parse Server-Sent Events (SSE) stream
5
+ *
6
+ * Handles:
7
+ * - Incomplete events across chunks
8
+ * - Multiple events in single chunk
9
+ * - Malformed data (skip gracefully)
10
+ * - [DONE] marker
11
+ *
12
+ * Usage:
13
+ * const parser = new SSEParser();
14
+ * stream.on('data', chunk => {
15
+ * const events = parser.parse(chunk);
16
+ * events.forEach(event => { ... });
17
+ * });
18
+ */
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.SSEParser = void 0;
21
+ class SSEParser {
22
+ constructor(options = {}) {
23
+ this.buffer = '';
24
+ this.eventCount = 0;
25
+ this.maxBufferSize = options.maxBufferSize || 1024 * 1024; // 1MB default
26
+ this.throwOnMalformedJson = options.throwOnMalformedJson === true;
27
+ }
28
+ /**
29
+ * Parse chunk and extract SSE events
30
+ * @param chunk - Data chunk from stream
31
+ * @returns Array of parsed events
32
+ */
33
+ parse(chunk) {
34
+ this.buffer += chunk.toString().replace(/\r\n?/g, '\n');
35
+ // C-01 Fix: Prevent unbounded buffer growth (DoS protection)
36
+ if (this.buffer.length > this.maxBufferSize) {
37
+ throw new Error(`SSE buffer exceeded ${this.maxBufferSize} bytes (DoS protection)`);
38
+ }
39
+ const events = [];
40
+ const segments = this.buffer.split('\n\n');
41
+ this.buffer = segments.pop() || '';
42
+ for (const segment of segments) {
43
+ const lines = segment.split('\n');
44
+ const currentEvent = { event: 'message', data: '' };
45
+ const dataLines = [];
46
+ for (const rawLine of lines) {
47
+ const line = rawLine.trimEnd();
48
+ if (!line || line.startsWith(':')) {
49
+ continue;
50
+ }
51
+ if (line.startsWith('event: ')) {
52
+ currentEvent.event = line.substring(7).trim();
53
+ continue;
54
+ }
55
+ if (line.startsWith('data:')) {
56
+ dataLines.push(line.substring(5).trimStart());
57
+ continue;
58
+ }
59
+ if (line.startsWith('id: ')) {
60
+ currentEvent.id = line.substring(4).trim();
61
+ continue;
62
+ }
63
+ if (line.startsWith('retry: ')) {
64
+ currentEvent.retry = parseInt(line.substring(7), 10);
65
+ }
66
+ }
67
+ const data = dataLines.join('\n');
68
+ if (!data) {
69
+ continue;
70
+ }
71
+ if (data === '[DONE]') {
72
+ this.eventCount++;
73
+ events.push({ event: 'done', data: null, index: this.eventCount });
74
+ continue;
75
+ }
76
+ try {
77
+ currentEvent.data = JSON.parse(data);
78
+ this.eventCount++;
79
+ currentEvent.index = this.eventCount;
80
+ events.push({ ...currentEvent });
81
+ }
82
+ catch (e) {
83
+ if (typeof console !== 'undefined' && console.error) {
84
+ console.error('[SSEParser] Malformed JSON event:', e.message, 'Data:', data.substring(0, 100));
85
+ }
86
+ if (this.throwOnMalformedJson) {
87
+ throw new Error(`Malformed SSE JSON event: ${e.message}`);
88
+ }
89
+ }
90
+ }
91
+ return events;
92
+ }
93
+ /**
94
+ * Reset parser state (for reuse)
95
+ */
96
+ reset() {
97
+ this.buffer = '';
98
+ this.eventCount = 0;
99
+ }
100
+ }
101
+ exports.SSEParser = SSEParser;
102
+ //# sourceMappingURL=sse-parser.js.map
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Stub for CCS services/logging - provides no-op logger
3
+ */
4
+ function createLogger(_name) {
5
+ return {
6
+ info: () => {},
7
+ warn: () => {},
8
+ error: () => {},
9
+ debug: () => {},
10
+ stage: () => {},
11
+ };
12
+ }
13
+ module.exports = { createLogger };