@hileeon/mcc 0.1.7 → 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.
Files changed (86) hide show
  1. package/README.md +226 -127
  2. package/dist/accounts/store.d.ts +1 -0
  3. package/dist/accounts/store.d.ts.map +1 -1
  4. package/dist/accounts/store.js.map +1 -1
  5. package/dist/commands/launch.d.ts +9 -0
  6. package/dist/commands/launch.d.ts.map +1 -0
  7. package/dist/commands/launch.js +158 -0
  8. package/dist/commands/launch.js.map +1 -0
  9. package/dist/commands/mcp.d.ts +9 -0
  10. package/dist/commands/mcp.d.ts.map +1 -0
  11. package/dist/commands/mcp.js +112 -0
  12. package/dist/commands/mcp.js.map +1 -0
  13. package/dist/commands/profile.d.ts +8 -0
  14. package/dist/commands/profile.d.ts.map +1 -0
  15. package/dist/commands/profile.js +125 -0
  16. package/dist/commands/profile.js.map +1 -0
  17. package/dist/core/model-router.d.ts.map +1 -1
  18. package/dist/core/model-router.js +5 -2
  19. package/dist/core/model-router.js.map +1 -1
  20. package/dist/{dashboard-server.d.ts → dashboard/server.d.ts} +1 -1
  21. package/dist/dashboard/server.d.ts.map +1 -0
  22. package/dist/{dashboard-server.js → dashboard/server.js} +169 -51
  23. package/dist/dashboard/server.js.map +1 -0
  24. package/dist/mcc.d.ts +4 -2
  25. package/dist/mcc.d.ts.map +1 -1
  26. package/dist/mcc.js +121 -408
  27. package/dist/mcc.js.map +1 -1
  28. package/dist/mcp/mcp-config.d.ts +17 -1
  29. package/dist/mcp/mcp-config.d.ts.map +1 -1
  30. package/dist/mcp/mcp-config.js +50 -17
  31. package/dist/mcp/mcp-config.js.map +1 -1
  32. package/dist/proxy/proxy-daemon.d.ts.map +1 -1
  33. package/dist/proxy/proxy-daemon.js +17 -2
  34. package/dist/proxy/proxy-daemon.js.map +1 -1
  35. package/dist/proxy/proxy-entry.js +5 -3
  36. package/dist/proxy/proxy-entry.js.map +1 -1
  37. package/dist/proxy/proxy-server.d.ts.map +1 -1
  38. package/dist/proxy/proxy-server.js +32 -6
  39. package/dist/proxy/proxy-server.js.map +1 -1
  40. package/dist/shared/config.d.ts +15 -0
  41. package/dist/shared/config.d.ts.map +1 -0
  42. package/dist/shared/config.js +79 -0
  43. package/dist/shared/config.js.map +1 -0
  44. package/dist/shared/logger.d.ts +23 -18
  45. package/dist/shared/logger.d.ts.map +1 -1
  46. package/dist/shared/logger.js +17 -178
  47. package/dist/shared/logger.js.map +1 -1
  48. package/dist/shared/provider-preset-catalog.d.ts +6 -2
  49. package/dist/shared/provider-preset-catalog.d.ts.map +1 -1
  50. package/dist/shared/provider-preset-catalog.js +47 -26
  51. package/dist/shared/provider-preset-catalog.js.map +1 -1
  52. package/dist/ui/assets/index-ClqmrjNk.js +40 -0
  53. package/dist/ui/assets/index-CwMwQ-Z4.css +1 -0
  54. package/dist/ui/index.html +21 -13
  55. package/dist/update.d.ts +31 -0
  56. package/dist/update.d.ts.map +1 -0
  57. package/dist/update.js +196 -0
  58. package/dist/update.js.map +1 -0
  59. package/lib/mcp/mcc-image-analysis-server.cjs +454 -454
  60. package/lib/mcp/mcc-websearch-server.cjs +339 -339
  61. package/lib/mcp-hooks/image-analysis-runtime.cjs +510 -510
  62. package/lib/mcp-hooks/image-analyzer-transformer.cjs +526 -526
  63. package/lib/mcp-hooks/websearch-transformer.cjs +1597 -1421
  64. package/lib/proxy/config/config-loader-facade.js +24 -24
  65. package/lib/proxy/glmt/delta-accumulator.js +362 -362
  66. package/lib/proxy/glmt/glmt-transformer.js +203 -203
  67. package/lib/proxy/glmt/index.js +40 -40
  68. package/lib/proxy/glmt/locale-enforcer.js +68 -68
  69. package/lib/proxy/glmt/pipeline/content-transformer.js +161 -161
  70. package/lib/proxy/glmt/pipeline/index.js +19 -19
  71. package/lib/proxy/glmt/pipeline/request-transformer.js +115 -115
  72. package/lib/proxy/glmt/pipeline/response-builder.js +204 -204
  73. package/lib/proxy/glmt/pipeline/stream-parser.js +233 -233
  74. package/lib/proxy/glmt/pipeline/tool-call-handler.js +77 -77
  75. package/lib/proxy/glmt/pipeline/types.js +5 -5
  76. package/lib/proxy/glmt/reasoning-enforcer.js +150 -150
  77. package/lib/proxy/glmt/sse-parser.js +101 -101
  78. package/lib/proxy/services/logging.js +13 -13
  79. package/lib/proxy/transformers/request-transformer.js +471 -451
  80. package/lib/proxy/transformers/sse-stream-transformer.js +198 -198
  81. package/lib/shared/logger.cjs +156 -138
  82. package/package.json +58 -41
  83. package/dist/dashboard-server.d.ts.map +0 -1
  84. package/dist/dashboard-server.js.map +0 -1
  85. package/dist/ui/assets/index-B16lhKZ6.js +0 -40
  86. package/dist/ui/assets/index-jEfiB6-h.css +0 -1
@@ -1,162 +1,162 @@
1
- "use strict";
2
- /**
3
- * ContentTransformer - Handle message sanitization and content transformations
4
- *
5
- * Responsibilities:
6
- * - Sanitize messages for OpenAI API compatibility
7
- * - Extract thinking control tags from messages
8
- * - Detect think keywords in user prompts
9
- * - Transform tools between Anthropic and OpenAI formats
10
- */
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.ContentTransformer = void 0;
13
- class ContentTransformer {
14
- constructor(defaultThinking = true) {
15
- this.defaultThinking = defaultThinking;
16
- }
17
- /**
18
- * Sanitize messages for OpenAI API compatibility
19
- */
20
- sanitizeMessages(messages) {
21
- const result = [];
22
- for (const msg of messages) {
23
- // If content is a string, add as-is
24
- if (typeof msg.content === 'string') {
25
- result.push(msg);
26
- continue;
27
- }
28
- // If content is an array, process blocks
29
- if (Array.isArray(msg.content)) {
30
- // Separate tool_result blocks from other content
31
- const toolResults = msg.content.filter((block) => block.type === 'tool_result');
32
- const textBlocks = msg.content.filter((block) => block.type === 'text');
33
- // CRITICAL: Tool messages must come BEFORE user text in OpenAI API
34
- for (const toolResult of toolResults) {
35
- result.push({
36
- role: 'tool',
37
- content: typeof toolResult.content === 'string'
38
- ? toolResult.content
39
- : JSON.stringify(toolResult.content),
40
- });
41
- }
42
- // Add text content as user/assistant message AFTER tool messages
43
- if (textBlocks.length > 0) {
44
- const textContent = textBlocks.length === 1
45
- ? textBlocks[0].text || ''
46
- : textBlocks.map((b) => b.text || '').join('\n');
47
- result.push({
48
- role: msg.role,
49
- content: textContent,
50
- });
51
- }
52
- // If no content at all, add empty message
53
- if (textBlocks.length === 0 && toolResults.length === 0) {
54
- result.push({
55
- role: msg.role,
56
- content: '',
57
- });
58
- }
59
- continue;
60
- }
61
- // Fallback: return message as-is
62
- result.push(msg);
63
- }
64
- return result;
65
- }
66
- /**
67
- * Transform Anthropic tools to OpenAI tools format
68
- */
69
- transformTools(anthropicTools) {
70
- return anthropicTools.map((tool) => ({
71
- type: 'function',
72
- function: {
73
- name: tool.name,
74
- description: tool.description,
75
- parameters: tool.input_schema || {},
76
- },
77
- }));
78
- }
79
- /**
80
- * Check if messages contain thinking control tags
81
- */
82
- hasThinkingTags(messages) {
83
- for (const msg of messages) {
84
- if (msg.role !== 'user')
85
- continue;
86
- const content = msg.content;
87
- if (typeof content !== 'string')
88
- continue;
89
- // Check for control tags
90
- if (/<Thinking:(On|Off)>/i.test(content) || /<Effort:(Low|Medium|High)>/i.test(content)) {
91
- return true;
92
- }
93
- }
94
- return false;
95
- }
96
- /**
97
- * Extract thinking control tags from user messages
98
- */
99
- extractThinkingControl(messages) {
100
- const config = {
101
- thinking: this.defaultThinking,
102
- effort: 'medium',
103
- };
104
- // Scan user messages for control tags
105
- for (const msg of messages) {
106
- if (msg.role !== 'user')
107
- continue;
108
- const content = msg.content;
109
- if (typeof content !== 'string')
110
- continue;
111
- // Check for <Thinking:On|Off>
112
- const thinkingMatch = content.match(/<Thinking:(On|Off)>/i);
113
- if (thinkingMatch) {
114
- config.thinking = thinkingMatch[1].toLowerCase() === 'on';
115
- }
116
- // Check for <Effort:Low|Medium|High>
117
- const effortMatch = content.match(/<Effort:(Low|Medium|High)>/i);
118
- if (effortMatch) {
119
- config.effort = effortMatch[1].toLowerCase();
120
- }
121
- }
122
- return config;
123
- }
124
- /**
125
- * Detect Anthropic-style "think" keywords in user prompts
126
- */
127
- detectThinkKeywords(messages) {
128
- if (!messages || messages.length === 0)
129
- return null;
130
- // Extract text from user messages
131
- const text = messages
132
- .filter((m) => m.role === 'user')
133
- .map((m) => {
134
- if (typeof m.content === 'string')
135
- return m.content;
136
- if (Array.isArray(m.content)) {
137
- return m.content
138
- .filter((block) => block.type === 'text')
139
- .map((block) => block.text || '')
140
- .join(' ');
141
- }
142
- return '';
143
- })
144
- .join(' ');
145
- // Priority: ultrathink > think harder > think hard > think
146
- if (/\bultrathink\b/i.test(text)) {
147
- return { thinking: true, effort: 'max', keyword: 'ultrathink' };
148
- }
149
- if (/\bthink\s+harder\b/i.test(text)) {
150
- return { thinking: true, effort: 'high', keyword: 'think harder' };
151
- }
152
- if (/\bthink\s+hard\b/i.test(text)) {
153
- return { thinking: true, effort: 'medium', keyword: 'think hard' };
154
- }
155
- if (/\bthink\b/i.test(text)) {
156
- return { thinking: true, effort: 'low', keyword: 'think' };
157
- }
158
- return null; // No keywords detected
159
- }
160
- }
161
- exports.ContentTransformer = ContentTransformer;
1
+ "use strict";
2
+ /**
3
+ * ContentTransformer - Handle message sanitization and content transformations
4
+ *
5
+ * Responsibilities:
6
+ * - Sanitize messages for OpenAI API compatibility
7
+ * - Extract thinking control tags from messages
8
+ * - Detect think keywords in user prompts
9
+ * - Transform tools between Anthropic and OpenAI formats
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.ContentTransformer = void 0;
13
+ class ContentTransformer {
14
+ constructor(defaultThinking = true) {
15
+ this.defaultThinking = defaultThinking;
16
+ }
17
+ /**
18
+ * Sanitize messages for OpenAI API compatibility
19
+ */
20
+ sanitizeMessages(messages) {
21
+ const result = [];
22
+ for (const msg of messages) {
23
+ // If content is a string, add as-is
24
+ if (typeof msg.content === 'string') {
25
+ result.push(msg);
26
+ continue;
27
+ }
28
+ // If content is an array, process blocks
29
+ if (Array.isArray(msg.content)) {
30
+ // Separate tool_result blocks from other content
31
+ const toolResults = msg.content.filter((block) => block.type === 'tool_result');
32
+ const textBlocks = msg.content.filter((block) => block.type === 'text');
33
+ // CRITICAL: Tool messages must come BEFORE user text in OpenAI API
34
+ for (const toolResult of toolResults) {
35
+ result.push({
36
+ role: 'tool',
37
+ content: typeof toolResult.content === 'string'
38
+ ? toolResult.content
39
+ : JSON.stringify(toolResult.content),
40
+ });
41
+ }
42
+ // Add text content as user/assistant message AFTER tool messages
43
+ if (textBlocks.length > 0) {
44
+ const textContent = textBlocks.length === 1
45
+ ? textBlocks[0].text || ''
46
+ : textBlocks.map((b) => b.text || '').join('\n');
47
+ result.push({
48
+ role: msg.role,
49
+ content: textContent,
50
+ });
51
+ }
52
+ // If no content at all, add empty message
53
+ if (textBlocks.length === 0 && toolResults.length === 0) {
54
+ result.push({
55
+ role: msg.role,
56
+ content: '',
57
+ });
58
+ }
59
+ continue;
60
+ }
61
+ // Fallback: return message as-is
62
+ result.push(msg);
63
+ }
64
+ return result;
65
+ }
66
+ /**
67
+ * Transform Anthropic tools to OpenAI tools format
68
+ */
69
+ transformTools(anthropicTools) {
70
+ return anthropicTools.map((tool) => ({
71
+ type: 'function',
72
+ function: {
73
+ name: tool.name,
74
+ description: tool.description,
75
+ parameters: tool.input_schema || {},
76
+ },
77
+ }));
78
+ }
79
+ /**
80
+ * Check if messages contain thinking control tags
81
+ */
82
+ hasThinkingTags(messages) {
83
+ for (const msg of messages) {
84
+ if (msg.role !== 'user')
85
+ continue;
86
+ const content = msg.content;
87
+ if (typeof content !== 'string')
88
+ continue;
89
+ // Check for control tags
90
+ if (/<Thinking:(On|Off)>/i.test(content) || /<Effort:(Low|Medium|High)>/i.test(content)) {
91
+ return true;
92
+ }
93
+ }
94
+ return false;
95
+ }
96
+ /**
97
+ * Extract thinking control tags from user messages
98
+ */
99
+ extractThinkingControl(messages) {
100
+ const config = {
101
+ thinking: this.defaultThinking,
102
+ effort: 'medium',
103
+ };
104
+ // Scan user messages for control tags
105
+ for (const msg of messages) {
106
+ if (msg.role !== 'user')
107
+ continue;
108
+ const content = msg.content;
109
+ if (typeof content !== 'string')
110
+ continue;
111
+ // Check for <Thinking:On|Off>
112
+ const thinkingMatch = content.match(/<Thinking:(On|Off)>/i);
113
+ if (thinkingMatch) {
114
+ config.thinking = thinkingMatch[1].toLowerCase() === 'on';
115
+ }
116
+ // Check for <Effort:Low|Medium|High>
117
+ const effortMatch = content.match(/<Effort:(Low|Medium|High)>/i);
118
+ if (effortMatch) {
119
+ config.effort = effortMatch[1].toLowerCase();
120
+ }
121
+ }
122
+ return config;
123
+ }
124
+ /**
125
+ * Detect Anthropic-style "think" keywords in user prompts
126
+ */
127
+ detectThinkKeywords(messages) {
128
+ if (!messages || messages.length === 0)
129
+ return null;
130
+ // Extract text from user messages
131
+ const text = messages
132
+ .filter((m) => m.role === 'user')
133
+ .map((m) => {
134
+ if (typeof m.content === 'string')
135
+ return m.content;
136
+ if (Array.isArray(m.content)) {
137
+ return m.content
138
+ .filter((block) => block.type === 'text')
139
+ .map((block) => block.text || '')
140
+ .join(' ');
141
+ }
142
+ return '';
143
+ })
144
+ .join(' ');
145
+ // Priority: ultrathink > think harder > think hard > think
146
+ if (/\bultrathink\b/i.test(text)) {
147
+ return { thinking: true, effort: 'max', keyword: 'ultrathink' };
148
+ }
149
+ if (/\bthink\s+harder\b/i.test(text)) {
150
+ return { thinking: true, effort: 'high', keyword: 'think harder' };
151
+ }
152
+ if (/\bthink\s+hard\b/i.test(text)) {
153
+ return { thinking: true, effort: 'medium', keyword: 'think hard' };
154
+ }
155
+ if (/\bthink\b/i.test(text)) {
156
+ return { thinking: true, effort: 'low', keyword: 'think' };
157
+ }
158
+ return null; // No keywords detected
159
+ }
160
+ }
161
+ exports.ContentTransformer = ContentTransformer;
162
162
  //# sourceMappingURL=content-transformer.js.map
@@ -1,20 +1,20 @@
1
- "use strict";
2
- /**
3
- * Pipeline Module Exports
4
- *
5
- * Barrel file for the GLMT transformation pipeline
6
- */
7
- Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.RequestTransformer = exports.StreamParser = exports.ResponseBuilder = exports.ToolCallHandler = exports.ContentTransformer = void 0;
9
- // Pipeline components
10
- var content_transformer_1 = require("./content-transformer");
11
- Object.defineProperty(exports, "ContentTransformer", { enumerable: true, get: function () { return content_transformer_1.ContentTransformer; } });
12
- var tool_call_handler_1 = require("./tool-call-handler");
13
- Object.defineProperty(exports, "ToolCallHandler", { enumerable: true, get: function () { return tool_call_handler_1.ToolCallHandler; } });
14
- var response_builder_1 = require("./response-builder");
15
- Object.defineProperty(exports, "ResponseBuilder", { enumerable: true, get: function () { return response_builder_1.ResponseBuilder; } });
16
- var stream_parser_1 = require("./stream-parser");
17
- Object.defineProperty(exports, "StreamParser", { enumerable: true, get: function () { return stream_parser_1.StreamParser; } });
18
- var request_transformer_1 = require("./request-transformer");
19
- Object.defineProperty(exports, "RequestTransformer", { enumerable: true, get: function () { return request_transformer_1.RequestTransformer; } });
1
+ "use strict";
2
+ /**
3
+ * Pipeline Module Exports
4
+ *
5
+ * Barrel file for the GLMT transformation pipeline
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.RequestTransformer = exports.StreamParser = exports.ResponseBuilder = exports.ToolCallHandler = exports.ContentTransformer = void 0;
9
+ // Pipeline components
10
+ var content_transformer_1 = require("./content-transformer");
11
+ Object.defineProperty(exports, "ContentTransformer", { enumerable: true, get: function () { return content_transformer_1.ContentTransformer; } });
12
+ var tool_call_handler_1 = require("./tool-call-handler");
13
+ Object.defineProperty(exports, "ToolCallHandler", { enumerable: true, get: function () { return tool_call_handler_1.ToolCallHandler; } });
14
+ var response_builder_1 = require("./response-builder");
15
+ Object.defineProperty(exports, "ResponseBuilder", { enumerable: true, get: function () { return response_builder_1.ResponseBuilder; } });
16
+ var stream_parser_1 = require("./stream-parser");
17
+ Object.defineProperty(exports, "StreamParser", { enumerable: true, get: function () { return stream_parser_1.StreamParser; } });
18
+ var request_transformer_1 = require("./request-transformer");
19
+ Object.defineProperty(exports, "RequestTransformer", { enumerable: true, get: function () { return request_transformer_1.RequestTransformer; } });
20
20
  //# sourceMappingURL=index.js.map
@@ -1,116 +1,116 @@
1
- "use strict";
2
- /**
3
- * RequestTransformer - Handle Anthropic → OpenAI request transformation
4
- *
5
- * Responsibilities:
6
- * - Transform Anthropic request format to OpenAI format
7
- * - Inject locale and reasoning instructions
8
- * - Map models and configure parameters
9
- */
10
- Object.defineProperty(exports, "__esModule", { value: true });
11
- exports.RequestTransformer = void 0;
12
- const locale_enforcer_1 = require("../locale-enforcer");
13
- const reasoning_enforcer_1 = require("../reasoning-enforcer");
14
- const content_transformer_1 = require("./content-transformer");
15
- class RequestTransformer {
16
- constructor(config = {}) {
17
- const defaultThinking = config.defaultThinking ?? true;
18
- this.log = config.log || (() => { });
19
- this.localeEnforcer = new locale_enforcer_1.LocaleEnforcer();
20
- this.reasoningEnforcer = new reasoning_enforcer_1.ReasoningEnforcer({
21
- enabled: config.explicitReasoning ?? true,
22
- });
23
- this.contentTransformer = new content_transformer_1.ContentTransformer(defaultThinking);
24
- this.modelMaxTokens = {
25
- 'GLM-4.6': 128000,
26
- 'GLM-4.5': 96000,
27
- 'GLM-4.5-air': 16000,
28
- };
29
- }
30
- /**
31
- * Transform Anthropic request to OpenAI format
32
- */
33
- transform(anthropicRequest) {
34
- try {
35
- const messages = anthropicRequest.messages || [];
36
- // 1. Extract thinking control from messages
37
- const thinkingConfig = this.contentTransformer.extractThinkingControl(messages);
38
- const hasControlTags = this.contentTransformer.hasThinkingTags(messages);
39
- // 2. Detect "think" keywords in user prompts
40
- const keywordConfig = this.contentTransformer.detectThinkKeywords(messages);
41
- if (keywordConfig && !anthropicRequest.thinking && !hasControlTags) {
42
- thinkingConfig.thinking = keywordConfig.thinking;
43
- thinkingConfig.effort = keywordConfig.effort;
44
- this.log(`Detected think keyword: ${keywordConfig.keyword}, effort=${keywordConfig.effort}`);
45
- }
46
- // 3. Check anthropicRequest.thinking parameter (takes precedence)
47
- if (anthropicRequest.thinking) {
48
- if (anthropicRequest.thinking.type === 'enabled') {
49
- thinkingConfig.thinking = true;
50
- this.log('Claude CLI explicitly enabled thinking');
51
- }
52
- else if (anthropicRequest.thinking.type === 'disabled') {
53
- thinkingConfig.thinking = false;
54
- this.log('Claude CLI explicitly disabled thinking');
55
- }
56
- }
57
- this.log(`Final thinking control: ${JSON.stringify(thinkingConfig)}`);
58
- // 4. Map model
59
- const glmModel = this.mapModel(anthropicRequest.model);
60
- // 5. Inject locale instruction
61
- const messagesWithLocale = this.localeEnforcer.injectInstruction(messages);
62
- // 6. Inject reasoning instruction
63
- const messagesWithReasoning = this.reasoningEnforcer.injectInstruction(messagesWithLocale, thinkingConfig);
64
- // 7. Build OpenAI request
65
- const openaiRequest = {
66
- model: glmModel,
67
- messages: this.contentTransformer.sanitizeMessages(messagesWithReasoning),
68
- max_tokens: this.getMaxTokens(glmModel),
69
- stream: anthropicRequest.stream ?? false,
70
- };
71
- // 8. Transform tools if present
72
- if (anthropicRequest.tools && anthropicRequest.tools.length > 0) {
73
- openaiRequest.tools = this.contentTransformer.transformTools(anthropicRequest.tools);
74
- openaiRequest.tool_choice = 'auto';
75
- this.log(`Transformed ${anthropicRequest.tools.length} tools for OpenAI format`);
76
- }
77
- // 9. Preserve optional parameters
78
- if (anthropicRequest.temperature !== undefined) {
79
- openaiRequest.temperature = anthropicRequest.temperature;
80
- }
81
- if (anthropicRequest.top_p !== undefined) {
82
- openaiRequest.top_p = anthropicRequest.top_p;
83
- }
84
- if (anthropicRequest.stream !== undefined) {
85
- openaiRequest.stream = anthropicRequest.stream;
86
- }
87
- // 10. Inject reasoning parameters
88
- this.injectReasoningParams(openaiRequest, thinkingConfig);
89
- return { openaiRequest, thinkingConfig };
90
- }
91
- catch (error) {
92
- const err = error;
93
- console.error('[RequestTransformer] Transformation error:', err);
94
- return {
95
- openaiRequest: anthropicRequest,
96
- thinkingConfig: { thinking: false, effort: 'medium' },
97
- error: err.message,
98
- };
99
- }
100
- }
101
- injectReasoningParams(openaiRequest, thinkingConfig) {
102
- openaiRequest.do_sample = true;
103
- if (thinkingConfig.thinking) {
104
- openaiRequest.reasoning = true;
105
- openaiRequest.reasoning_effort = thinkingConfig.effort;
106
- }
107
- }
108
- mapModel(_anthropicModel) {
109
- return 'GLM-4.6';
110
- }
111
- getMaxTokens(model) {
112
- return this.modelMaxTokens[model] || 128000;
113
- }
114
- }
115
- exports.RequestTransformer = RequestTransformer;
1
+ "use strict";
2
+ /**
3
+ * RequestTransformer - Handle Anthropic → OpenAI request transformation
4
+ *
5
+ * Responsibilities:
6
+ * - Transform Anthropic request format to OpenAI format
7
+ * - Inject locale and reasoning instructions
8
+ * - Map models and configure parameters
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.RequestTransformer = void 0;
12
+ const locale_enforcer_1 = require("../locale-enforcer");
13
+ const reasoning_enforcer_1 = require("../reasoning-enforcer");
14
+ const content_transformer_1 = require("./content-transformer");
15
+ class RequestTransformer {
16
+ constructor(config = {}) {
17
+ const defaultThinking = config.defaultThinking ?? true;
18
+ this.log = config.log || (() => { });
19
+ this.localeEnforcer = new locale_enforcer_1.LocaleEnforcer();
20
+ this.reasoningEnforcer = new reasoning_enforcer_1.ReasoningEnforcer({
21
+ enabled: config.explicitReasoning ?? true,
22
+ });
23
+ this.contentTransformer = new content_transformer_1.ContentTransformer(defaultThinking);
24
+ this.modelMaxTokens = {
25
+ 'GLM-4.6': 128000,
26
+ 'GLM-4.5': 96000,
27
+ 'GLM-4.5-air': 16000,
28
+ };
29
+ }
30
+ /**
31
+ * Transform Anthropic request to OpenAI format
32
+ */
33
+ transform(anthropicRequest) {
34
+ try {
35
+ const messages = anthropicRequest.messages || [];
36
+ // 1. Extract thinking control from messages
37
+ const thinkingConfig = this.contentTransformer.extractThinkingControl(messages);
38
+ const hasControlTags = this.contentTransformer.hasThinkingTags(messages);
39
+ // 2. Detect "think" keywords in user prompts
40
+ const keywordConfig = this.contentTransformer.detectThinkKeywords(messages);
41
+ if (keywordConfig && !anthropicRequest.thinking && !hasControlTags) {
42
+ thinkingConfig.thinking = keywordConfig.thinking;
43
+ thinkingConfig.effort = keywordConfig.effort;
44
+ this.log(`Detected think keyword: ${keywordConfig.keyword}, effort=${keywordConfig.effort}`);
45
+ }
46
+ // 3. Check anthropicRequest.thinking parameter (takes precedence)
47
+ if (anthropicRequest.thinking) {
48
+ if (anthropicRequest.thinking.type === 'enabled') {
49
+ thinkingConfig.thinking = true;
50
+ this.log('Claude CLI explicitly enabled thinking');
51
+ }
52
+ else if (anthropicRequest.thinking.type === 'disabled') {
53
+ thinkingConfig.thinking = false;
54
+ this.log('Claude CLI explicitly disabled thinking');
55
+ }
56
+ }
57
+ this.log(`Final thinking control: ${JSON.stringify(thinkingConfig)}`);
58
+ // 4. Map model
59
+ const glmModel = this.mapModel(anthropicRequest.model);
60
+ // 5. Inject locale instruction
61
+ const messagesWithLocale = this.localeEnforcer.injectInstruction(messages);
62
+ // 6. Inject reasoning instruction
63
+ const messagesWithReasoning = this.reasoningEnforcer.injectInstruction(messagesWithLocale, thinkingConfig);
64
+ // 7. Build OpenAI request
65
+ const openaiRequest = {
66
+ model: glmModel,
67
+ messages: this.contentTransformer.sanitizeMessages(messagesWithReasoning),
68
+ max_tokens: this.getMaxTokens(glmModel),
69
+ stream: anthropicRequest.stream ?? false,
70
+ };
71
+ // 8. Transform tools if present
72
+ if (anthropicRequest.tools && anthropicRequest.tools.length > 0) {
73
+ openaiRequest.tools = this.contentTransformer.transformTools(anthropicRequest.tools);
74
+ openaiRequest.tool_choice = 'auto';
75
+ this.log(`Transformed ${anthropicRequest.tools.length} tools for OpenAI format`);
76
+ }
77
+ // 9. Preserve optional parameters
78
+ if (anthropicRequest.temperature !== undefined) {
79
+ openaiRequest.temperature = anthropicRequest.temperature;
80
+ }
81
+ if (anthropicRequest.top_p !== undefined) {
82
+ openaiRequest.top_p = anthropicRequest.top_p;
83
+ }
84
+ if (anthropicRequest.stream !== undefined) {
85
+ openaiRequest.stream = anthropicRequest.stream;
86
+ }
87
+ // 10. Inject reasoning parameters
88
+ this.injectReasoningParams(openaiRequest, thinkingConfig);
89
+ return { openaiRequest, thinkingConfig };
90
+ }
91
+ catch (error) {
92
+ const err = error;
93
+ console.error('[RequestTransformer] Transformation error:', err);
94
+ return {
95
+ openaiRequest: anthropicRequest,
96
+ thinkingConfig: { thinking: false, effort: 'medium' },
97
+ error: err.message,
98
+ };
99
+ }
100
+ }
101
+ injectReasoningParams(openaiRequest, thinkingConfig) {
102
+ openaiRequest.do_sample = true;
103
+ if (thinkingConfig.thinking) {
104
+ openaiRequest.reasoning = true;
105
+ openaiRequest.reasoning_effort = thinkingConfig.effort;
106
+ }
107
+ }
108
+ mapModel(_anthropicModel) {
109
+ return 'GLM-4.6';
110
+ }
111
+ getMaxTokens(model) {
112
+ return this.modelMaxTokens[model] || 128000;
113
+ }
114
+ }
115
+ exports.RequestTransformer = RequestTransformer;
116
116
  //# sourceMappingURL=request-transformer.js.map