@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,204 +1,204 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* GlmtTransformer - Orchestrator for Anthropic ↔ OpenAI format transformation
|
|
4
|
-
*
|
|
5
|
-
* Pipeline Architecture:
|
|
6
|
-
* - RequestTransformer: Anthropic → OpenAI request conversion
|
|
7
|
-
* - StreamParser: Delta processing for streaming responses
|
|
8
|
-
* - ResponseBuilder: SSE event generation
|
|
9
|
-
* - ToolCallHandler: Tool call processing
|
|
10
|
-
*/
|
|
11
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
-
if (k2 === undefined) k2 = k;
|
|
13
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
-
}
|
|
17
|
-
Object.defineProperty(o, k2, desc);
|
|
18
|
-
}) : (function(o, m, k, k2) {
|
|
19
|
-
if (k2 === undefined) k2 = k;
|
|
20
|
-
o[k2] = m[k];
|
|
21
|
-
}));
|
|
22
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
-
}) : function(o, v) {
|
|
25
|
-
o["default"] = v;
|
|
26
|
-
});
|
|
27
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
|
-
exports.GlmtTransformer = void 0;
|
|
36
|
-
const fs = __importStar(require("fs"));
|
|
37
|
-
const path = __importStar(require("path"));
|
|
38
|
-
const logging_1 = require("../services/logging");
|
|
39
|
-
const pipeline_1 = require("./pipeline");
|
|
40
|
-
const config_loader_facade_1 = require("../config/config-loader-facade");
|
|
41
|
-
class GlmtTransformer {
|
|
42
|
-
constructor(config = {}) {
|
|
43
|
-
this.logger = (0, logging_1.createLogger)('glmt:transformer');
|
|
44
|
-
this.verbose = config.verbose || false;
|
|
45
|
-
const debugEnabled = process.env.CCS_DEBUG === '1';
|
|
46
|
-
this.debugLog = config.debugLog ?? debugEnabled;
|
|
47
|
-
this.debugLogDir = config.debugLogDir || path.join((0, config_loader_facade_1.getCcsDir)(), 'logs');
|
|
48
|
-
// Initialize pipeline components
|
|
49
|
-
this.requestTransformer = new pipeline_1.RequestTransformer({
|
|
50
|
-
defaultThinking: config.defaultThinking ?? true,
|
|
51
|
-
verbose: this.verbose,
|
|
52
|
-
explicitReasoning: config.explicitReasoning ?? true,
|
|
53
|
-
log: (msg) => this.log(msg),
|
|
54
|
-
});
|
|
55
|
-
this.responseBuilder = new pipeline_1.ResponseBuilder(this.verbose);
|
|
56
|
-
this.toolCallHandler = new pipeline_1.ToolCallHandler();
|
|
57
|
-
this.contentTransformer = new pipeline_1.ContentTransformer(config.defaultThinking ?? true);
|
|
58
|
-
this.streamParser = new pipeline_1.StreamParser({
|
|
59
|
-
verbose: this.verbose,
|
|
60
|
-
debugMode: config.debugMode ?? debugEnabled,
|
|
61
|
-
debugLog: this.debugLog,
|
|
62
|
-
writeDebugLog: (type, data) => this.writeDebugLog(type, data),
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
/** Transform Anthropic request to OpenAI format */
|
|
66
|
-
transformRequest(anthropicRequest) {
|
|
67
|
-
this.writeDebugLog('request-anthropic', anthropicRequest);
|
|
68
|
-
const result = this.requestTransformer.transform(anthropicRequest);
|
|
69
|
-
this.writeDebugLog('request-openai', result.openaiRequest);
|
|
70
|
-
return result;
|
|
71
|
-
}
|
|
72
|
-
/** Transform OpenAI response to Anthropic format */
|
|
73
|
-
transformResponse(openaiResponse, _thinkingConfig = { thinking: false, effort: 'medium' }) {
|
|
74
|
-
this.writeDebugLog('response-openai', openaiResponse);
|
|
75
|
-
try {
|
|
76
|
-
const choice = openaiResponse.choices?.[0];
|
|
77
|
-
if (!choice)
|
|
78
|
-
throw new Error('No choices in OpenAI response');
|
|
79
|
-
const message = choice.message;
|
|
80
|
-
const content = [];
|
|
81
|
-
if (message.reasoning_content) {
|
|
82
|
-
this.log(`Detected reasoning_content: ${message.reasoning_content.length} chars`);
|
|
83
|
-
content.push({
|
|
84
|
-
type: 'thinking',
|
|
85
|
-
thinking: message.reasoning_content,
|
|
86
|
-
signature: this.responseBuilder.generateThinkingSignature(message.reasoning_content),
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
if (message.content) {
|
|
90
|
-
content.push({ type: 'text', text: message.content });
|
|
91
|
-
}
|
|
92
|
-
if (message.tool_calls?.length) {
|
|
93
|
-
content.push(...this.toolCallHandler.processToolCalls(message.tool_calls));
|
|
94
|
-
}
|
|
95
|
-
const anthropicResponse = {
|
|
96
|
-
id: openaiResponse.id || 'msg_' + Date.now(),
|
|
97
|
-
type: 'message',
|
|
98
|
-
role: 'assistant',
|
|
99
|
-
content,
|
|
100
|
-
model: openaiResponse.model || 'glm-5',
|
|
101
|
-
stop_reason: this.responseBuilder.mapStopReason(choice.finish_reason || 'stop'),
|
|
102
|
-
usage: {
|
|
103
|
-
input_tokens: openaiResponse.usage?.prompt_tokens || 0,
|
|
104
|
-
output_tokens: openaiResponse.usage?.completion_tokens || 0,
|
|
105
|
-
},
|
|
106
|
-
};
|
|
107
|
-
this.writeDebugLog('response-anthropic', anthropicResponse);
|
|
108
|
-
return anthropicResponse;
|
|
109
|
-
}
|
|
110
|
-
catch (error) {
|
|
111
|
-
const err = error;
|
|
112
|
-
this.logger.stage('cleanup', 'response.transform_failed', 'GLMT response transformation failed', undefined, { level: 'error', error: { name: err.name, message: err.message } });
|
|
113
|
-
console.error('[glmt-transformer] Response transformation error:', err);
|
|
114
|
-
return {
|
|
115
|
-
id: 'msg_error_' + Date.now(),
|
|
116
|
-
type: 'message',
|
|
117
|
-
role: 'assistant',
|
|
118
|
-
content: [{ type: 'text', text: '[Transformation Error] ' + err.message }],
|
|
119
|
-
model: 'glm-5',
|
|
120
|
-
stop_reason: 'end_turn',
|
|
121
|
-
usage: { input_tokens: 0, output_tokens: 0 },
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
/** Transform streaming delta (delegates to StreamParser) */
|
|
126
|
-
transformDelta(openaiEvent, accumulator) {
|
|
127
|
-
return this.streamParser.transformDelta(openaiEvent, accumulator);
|
|
128
|
-
}
|
|
129
|
-
/** Finalize streaming (delegates to StreamParser) */
|
|
130
|
-
finalizeDelta(accumulator) {
|
|
131
|
-
return this.streamParser.finalizeDelta(accumulator);
|
|
132
|
-
}
|
|
133
|
-
redactSensitiveData(data) {
|
|
134
|
-
if (data === null || data === undefined)
|
|
135
|
-
return data;
|
|
136
|
-
if (typeof data !== 'object')
|
|
137
|
-
return data;
|
|
138
|
-
if (Array.isArray(data))
|
|
139
|
-
return data.map((item) => this.redactSensitiveData(item));
|
|
140
|
-
const SENSITIVE_KEYS = /^(authorization|auth[_-]?token|api[_-]?key|apikey|token|secret|password|credential|x-api-key|anthropic-api-key|cookie)$/i;
|
|
141
|
-
const result = {};
|
|
142
|
-
for (const [key, value] of Object.entries(data)) {
|
|
143
|
-
if (SENSITIVE_KEYS.test(key)) {
|
|
144
|
-
result[key] = '[REDACTED]';
|
|
145
|
-
}
|
|
146
|
-
else {
|
|
147
|
-
result[key] = this.redactSensitiveData(value);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
return result;
|
|
151
|
-
}
|
|
152
|
-
writeDebugLog(type, data) {
|
|
153
|
-
if (!this.debugLog)
|
|
154
|
-
return;
|
|
155
|
-
try {
|
|
156
|
-
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').split('.')[0];
|
|
157
|
-
const filepath = path.join(this.debugLogDir, `${timestamp}-${type}.json`);
|
|
158
|
-
fs.mkdirSync(this.debugLogDir, { recursive: true });
|
|
159
|
-
const redacted = this.redactSensitiveData(data);
|
|
160
|
-
fs.writeFileSync(filepath, JSON.stringify(redacted, null, 2) + '\n', 'utf8');
|
|
161
|
-
}
|
|
162
|
-
catch (error) {
|
|
163
|
-
this.logger.warn('debug-log.write_failed', 'GLMT debug log write failed', {
|
|
164
|
-
message: error.message,
|
|
165
|
-
});
|
|
166
|
-
console.error(`[glmt-transformer] Debug log error: ${error.message}`);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
log(message) {
|
|
170
|
-
if (this.verbose) {
|
|
171
|
-
this.logger.debug('transformer.verbose', message);
|
|
172
|
-
console.error(`[glmt-transformer] [${new Date().toTimeString().split(' ')[0]}] ${message}`);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
// ========== Backwards-compatible public methods ==========
|
|
176
|
-
/** Generate thinking signature (delegates to ResponseBuilder) */
|
|
177
|
-
generateThinkingSignature(thinking) {
|
|
178
|
-
return this.responseBuilder.generateThinkingSignature(thinking);
|
|
179
|
-
}
|
|
180
|
-
/** Map stop reason (delegates to ResponseBuilder) */
|
|
181
|
-
mapStopReason(openaiReason) {
|
|
182
|
-
return this.responseBuilder.mapStopReason(openaiReason);
|
|
183
|
-
}
|
|
184
|
-
/** Detect think keywords (delegates to ContentTransformer) */
|
|
185
|
-
detectThinkKeywords(messages) {
|
|
186
|
-
return this.contentTransformer.detectThinkKeywords(messages);
|
|
187
|
-
}
|
|
188
|
-
/** Validate transformation result */
|
|
189
|
-
validateTransformation(anthropicResponse) {
|
|
190
|
-
const checks = {
|
|
191
|
-
hasContent: Boolean(anthropicResponse.content && anthropicResponse.content.length > 0),
|
|
192
|
-
hasThinking: anthropicResponse.content?.some((block) => block.type === 'thinking') || false,
|
|
193
|
-
hasText: anthropicResponse.content?.some((block) => block.type === 'text') || false,
|
|
194
|
-
validStructure: anthropicResponse.type === 'message' && anthropicResponse.role === 'assistant',
|
|
195
|
-
hasUsage: Boolean(anthropicResponse.usage),
|
|
196
|
-
};
|
|
197
|
-
const passed = Object.values(checks).filter(Boolean).length;
|
|
198
|
-
const total = Object.keys(checks).length;
|
|
199
|
-
return { checks, passed, total, valid: passed === total };
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
exports.GlmtTransformer = GlmtTransformer;
|
|
203
|
-
exports.default = GlmtTransformer;
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* GlmtTransformer - Orchestrator for Anthropic ↔ OpenAI format transformation
|
|
4
|
+
*
|
|
5
|
+
* Pipeline Architecture:
|
|
6
|
+
* - RequestTransformer: Anthropic → OpenAI request conversion
|
|
7
|
+
* - StreamParser: Delta processing for streaming responses
|
|
8
|
+
* - ResponseBuilder: SSE event generation
|
|
9
|
+
* - ToolCallHandler: Tool call processing
|
|
10
|
+
*/
|
|
11
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
+
}
|
|
17
|
+
Object.defineProperty(o, k2, desc);
|
|
18
|
+
}) : (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
}));
|
|
22
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
+
}) : function(o, v) {
|
|
25
|
+
o["default"] = v;
|
|
26
|
+
});
|
|
27
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
|
+
exports.GlmtTransformer = void 0;
|
|
36
|
+
const fs = __importStar(require("fs"));
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const logging_1 = require("../services/logging");
|
|
39
|
+
const pipeline_1 = require("./pipeline");
|
|
40
|
+
const config_loader_facade_1 = require("../config/config-loader-facade");
|
|
41
|
+
class GlmtTransformer {
|
|
42
|
+
constructor(config = {}) {
|
|
43
|
+
this.logger = (0, logging_1.createLogger)('glmt:transformer');
|
|
44
|
+
this.verbose = config.verbose || false;
|
|
45
|
+
const debugEnabled = process.env.CCS_DEBUG === '1';
|
|
46
|
+
this.debugLog = config.debugLog ?? debugEnabled;
|
|
47
|
+
this.debugLogDir = config.debugLogDir || path.join((0, config_loader_facade_1.getCcsDir)(), 'logs');
|
|
48
|
+
// Initialize pipeline components
|
|
49
|
+
this.requestTransformer = new pipeline_1.RequestTransformer({
|
|
50
|
+
defaultThinking: config.defaultThinking ?? true,
|
|
51
|
+
verbose: this.verbose,
|
|
52
|
+
explicitReasoning: config.explicitReasoning ?? true,
|
|
53
|
+
log: (msg) => this.log(msg),
|
|
54
|
+
});
|
|
55
|
+
this.responseBuilder = new pipeline_1.ResponseBuilder(this.verbose);
|
|
56
|
+
this.toolCallHandler = new pipeline_1.ToolCallHandler();
|
|
57
|
+
this.contentTransformer = new pipeline_1.ContentTransformer(config.defaultThinking ?? true);
|
|
58
|
+
this.streamParser = new pipeline_1.StreamParser({
|
|
59
|
+
verbose: this.verbose,
|
|
60
|
+
debugMode: config.debugMode ?? debugEnabled,
|
|
61
|
+
debugLog: this.debugLog,
|
|
62
|
+
writeDebugLog: (type, data) => this.writeDebugLog(type, data),
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
/** Transform Anthropic request to OpenAI format */
|
|
66
|
+
transformRequest(anthropicRequest) {
|
|
67
|
+
this.writeDebugLog('request-anthropic', anthropicRequest);
|
|
68
|
+
const result = this.requestTransformer.transform(anthropicRequest);
|
|
69
|
+
this.writeDebugLog('request-openai', result.openaiRequest);
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
/** Transform OpenAI response to Anthropic format */
|
|
73
|
+
transformResponse(openaiResponse, _thinkingConfig = { thinking: false, effort: 'medium' }) {
|
|
74
|
+
this.writeDebugLog('response-openai', openaiResponse);
|
|
75
|
+
try {
|
|
76
|
+
const choice = openaiResponse.choices?.[0];
|
|
77
|
+
if (!choice)
|
|
78
|
+
throw new Error('No choices in OpenAI response');
|
|
79
|
+
const message = choice.message;
|
|
80
|
+
const content = [];
|
|
81
|
+
if (message.reasoning_content) {
|
|
82
|
+
this.log(`Detected reasoning_content: ${message.reasoning_content.length} chars`);
|
|
83
|
+
content.push({
|
|
84
|
+
type: 'thinking',
|
|
85
|
+
thinking: message.reasoning_content,
|
|
86
|
+
signature: this.responseBuilder.generateThinkingSignature(message.reasoning_content),
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
if (message.content) {
|
|
90
|
+
content.push({ type: 'text', text: message.content });
|
|
91
|
+
}
|
|
92
|
+
if (message.tool_calls?.length) {
|
|
93
|
+
content.push(...this.toolCallHandler.processToolCalls(message.tool_calls));
|
|
94
|
+
}
|
|
95
|
+
const anthropicResponse = {
|
|
96
|
+
id: openaiResponse.id || 'msg_' + Date.now(),
|
|
97
|
+
type: 'message',
|
|
98
|
+
role: 'assistant',
|
|
99
|
+
content,
|
|
100
|
+
model: openaiResponse.model || 'glm-5',
|
|
101
|
+
stop_reason: this.responseBuilder.mapStopReason(choice.finish_reason || 'stop'),
|
|
102
|
+
usage: {
|
|
103
|
+
input_tokens: openaiResponse.usage?.prompt_tokens || 0,
|
|
104
|
+
output_tokens: openaiResponse.usage?.completion_tokens || 0,
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
this.writeDebugLog('response-anthropic', anthropicResponse);
|
|
108
|
+
return anthropicResponse;
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
const err = error;
|
|
112
|
+
this.logger.stage('cleanup', 'response.transform_failed', 'GLMT response transformation failed', undefined, { level: 'error', error: { name: err.name, message: err.message } });
|
|
113
|
+
console.error('[glmt-transformer] Response transformation error:', err);
|
|
114
|
+
return {
|
|
115
|
+
id: 'msg_error_' + Date.now(),
|
|
116
|
+
type: 'message',
|
|
117
|
+
role: 'assistant',
|
|
118
|
+
content: [{ type: 'text', text: '[Transformation Error] ' + err.message }],
|
|
119
|
+
model: 'glm-5',
|
|
120
|
+
stop_reason: 'end_turn',
|
|
121
|
+
usage: { input_tokens: 0, output_tokens: 0 },
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/** Transform streaming delta (delegates to StreamParser) */
|
|
126
|
+
transformDelta(openaiEvent, accumulator) {
|
|
127
|
+
return this.streamParser.transformDelta(openaiEvent, accumulator);
|
|
128
|
+
}
|
|
129
|
+
/** Finalize streaming (delegates to StreamParser) */
|
|
130
|
+
finalizeDelta(accumulator) {
|
|
131
|
+
return this.streamParser.finalizeDelta(accumulator);
|
|
132
|
+
}
|
|
133
|
+
redactSensitiveData(data) {
|
|
134
|
+
if (data === null || data === undefined)
|
|
135
|
+
return data;
|
|
136
|
+
if (typeof data !== 'object')
|
|
137
|
+
return data;
|
|
138
|
+
if (Array.isArray(data))
|
|
139
|
+
return data.map((item) => this.redactSensitiveData(item));
|
|
140
|
+
const SENSITIVE_KEYS = /^(authorization|auth[_-]?token|api[_-]?key|apikey|token|secret|password|credential|x-api-key|anthropic-api-key|cookie)$/i;
|
|
141
|
+
const result = {};
|
|
142
|
+
for (const [key, value] of Object.entries(data)) {
|
|
143
|
+
if (SENSITIVE_KEYS.test(key)) {
|
|
144
|
+
result[key] = '[REDACTED]';
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
result[key] = this.redactSensitiveData(value);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return result;
|
|
151
|
+
}
|
|
152
|
+
writeDebugLog(type, data) {
|
|
153
|
+
if (!this.debugLog)
|
|
154
|
+
return;
|
|
155
|
+
try {
|
|
156
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').split('.')[0];
|
|
157
|
+
const filepath = path.join(this.debugLogDir, `${timestamp}-${type}.json`);
|
|
158
|
+
fs.mkdirSync(this.debugLogDir, { recursive: true });
|
|
159
|
+
const redacted = this.redactSensitiveData(data);
|
|
160
|
+
fs.writeFileSync(filepath, JSON.stringify(redacted, null, 2) + '\n', 'utf8');
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
this.logger.warn('debug-log.write_failed', 'GLMT debug log write failed', {
|
|
164
|
+
message: error.message,
|
|
165
|
+
});
|
|
166
|
+
console.error(`[glmt-transformer] Debug log error: ${error.message}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
log(message) {
|
|
170
|
+
if (this.verbose) {
|
|
171
|
+
this.logger.debug('transformer.verbose', message);
|
|
172
|
+
console.error(`[glmt-transformer] [${new Date().toTimeString().split(' ')[0]}] ${message}`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
// ========== Backwards-compatible public methods ==========
|
|
176
|
+
/** Generate thinking signature (delegates to ResponseBuilder) */
|
|
177
|
+
generateThinkingSignature(thinking) {
|
|
178
|
+
return this.responseBuilder.generateThinkingSignature(thinking);
|
|
179
|
+
}
|
|
180
|
+
/** Map stop reason (delegates to ResponseBuilder) */
|
|
181
|
+
mapStopReason(openaiReason) {
|
|
182
|
+
return this.responseBuilder.mapStopReason(openaiReason);
|
|
183
|
+
}
|
|
184
|
+
/** Detect think keywords (delegates to ContentTransformer) */
|
|
185
|
+
detectThinkKeywords(messages) {
|
|
186
|
+
return this.contentTransformer.detectThinkKeywords(messages);
|
|
187
|
+
}
|
|
188
|
+
/** Validate transformation result */
|
|
189
|
+
validateTransformation(anthropicResponse) {
|
|
190
|
+
const checks = {
|
|
191
|
+
hasContent: Boolean(anthropicResponse.content && anthropicResponse.content.length > 0),
|
|
192
|
+
hasThinking: anthropicResponse.content?.some((block) => block.type === 'thinking') || false,
|
|
193
|
+
hasText: anthropicResponse.content?.some((block) => block.type === 'text') || false,
|
|
194
|
+
validStructure: anthropicResponse.type === 'message' && anthropicResponse.role === 'assistant',
|
|
195
|
+
hasUsage: Boolean(anthropicResponse.usage),
|
|
196
|
+
};
|
|
197
|
+
const passed = Object.values(checks).filter(Boolean).length;
|
|
198
|
+
const total = Object.keys(checks).length;
|
|
199
|
+
return { checks, passed, total, valid: passed === total };
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
exports.GlmtTransformer = GlmtTransformer;
|
|
203
|
+
exports.default = GlmtTransformer;
|
|
204
204
|
//# sourceMappingURL=glmt-transformer.js.map
|
package/lib/proxy/glmt/index.js
CHANGED
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* GLMT (GLM Thinking) Module Barrel Export
|
|
4
|
-
*
|
|
5
|
-
* Provides OpenAI-to-Anthropic protocol translation for GLM models with
|
|
6
|
-
* extended thinking support.
|
|
7
|
-
*/
|
|
8
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
-
if (k2 === undefined) k2 = k;
|
|
10
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
-
}
|
|
14
|
-
Object.defineProperty(o, k2, desc);
|
|
15
|
-
}) : (function(o, m, k, k2) {
|
|
16
|
-
if (k2 === undefined) k2 = k;
|
|
17
|
-
o[k2] = m[k];
|
|
18
|
-
}));
|
|
19
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
20
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
21
|
-
};
|
|
22
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
-
exports.ReasoningEnforcer = exports.LocaleEnforcer = exports.DeltaAccumulator = exports.SSEParser = exports.GlmtTransformer = exports.GlmtProxy = void 0;
|
|
24
|
-
// Core proxy and transformer
|
|
25
|
-
var glmt_proxy_1 = require("./glmt-proxy");
|
|
26
|
-
Object.defineProperty(exports, "GlmtProxy", { enumerable: true, get: function () { return glmt_proxy_1.GlmtProxy; } });
|
|
27
|
-
var glmt_transformer_1 = require("./glmt-transformer");
|
|
28
|
-
Object.defineProperty(exports, "GlmtTransformer", { enumerable: true, get: function () { return glmt_transformer_1.GlmtTransformer; } });
|
|
29
|
-
// Streaming utilities
|
|
30
|
-
var sse_parser_1 = require("./sse-parser");
|
|
31
|
-
Object.defineProperty(exports, "SSEParser", { enumerable: true, get: function () { return sse_parser_1.SSEParser; } });
|
|
32
|
-
var delta_accumulator_1 = require("./delta-accumulator");
|
|
33
|
-
Object.defineProperty(exports, "DeltaAccumulator", { enumerable: true, get: function () { return delta_accumulator_1.DeltaAccumulator; } });
|
|
34
|
-
// Content enforcers
|
|
35
|
-
var locale_enforcer_1 = require("./locale-enforcer");
|
|
36
|
-
Object.defineProperty(exports, "LocaleEnforcer", { enumerable: true, get: function () { return locale_enforcer_1.LocaleEnforcer; } });
|
|
37
|
-
var reasoning_enforcer_1 = require("./reasoning-enforcer");
|
|
38
|
-
Object.defineProperty(exports, "ReasoningEnforcer", { enumerable: true, get: function () { return reasoning_enforcer_1.ReasoningEnforcer; } });
|
|
39
|
-
// Pipeline components and types
|
|
40
|
-
__exportStar(require("./pipeline"), exports);
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* GLMT (GLM Thinking) Module Barrel Export
|
|
4
|
+
*
|
|
5
|
+
* Provides OpenAI-to-Anthropic protocol translation for GLM models with
|
|
6
|
+
* extended thinking support.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
20
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
21
|
+
};
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.ReasoningEnforcer = exports.LocaleEnforcer = exports.DeltaAccumulator = exports.SSEParser = exports.GlmtTransformer = exports.GlmtProxy = void 0;
|
|
24
|
+
// Core proxy and transformer
|
|
25
|
+
var glmt_proxy_1 = require("./glmt-proxy");
|
|
26
|
+
Object.defineProperty(exports, "GlmtProxy", { enumerable: true, get: function () { return glmt_proxy_1.GlmtProxy; } });
|
|
27
|
+
var glmt_transformer_1 = require("./glmt-transformer");
|
|
28
|
+
Object.defineProperty(exports, "GlmtTransformer", { enumerable: true, get: function () { return glmt_transformer_1.GlmtTransformer; } });
|
|
29
|
+
// Streaming utilities
|
|
30
|
+
var sse_parser_1 = require("./sse-parser");
|
|
31
|
+
Object.defineProperty(exports, "SSEParser", { enumerable: true, get: function () { return sse_parser_1.SSEParser; } });
|
|
32
|
+
var delta_accumulator_1 = require("./delta-accumulator");
|
|
33
|
+
Object.defineProperty(exports, "DeltaAccumulator", { enumerable: true, get: function () { return delta_accumulator_1.DeltaAccumulator; } });
|
|
34
|
+
// Content enforcers
|
|
35
|
+
var locale_enforcer_1 = require("./locale-enforcer");
|
|
36
|
+
Object.defineProperty(exports, "LocaleEnforcer", { enumerable: true, get: function () { return locale_enforcer_1.LocaleEnforcer; } });
|
|
37
|
+
var reasoning_enforcer_1 = require("./reasoning-enforcer");
|
|
38
|
+
Object.defineProperty(exports, "ReasoningEnforcer", { enumerable: true, get: function () { return reasoning_enforcer_1.ReasoningEnforcer; } });
|
|
39
|
+
// Pipeline components and types
|
|
40
|
+
__exportStar(require("./pipeline"), exports);
|
|
41
41
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,69 +1,69 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
/**
|
|
4
|
-
* LocaleEnforcer - Force English output from GLM models
|
|
5
|
-
*
|
|
6
|
-
* Purpose: GLM models default to Chinese when prompts are ambiguous or contain Chinese context.
|
|
7
|
-
* This module always injects "MUST respond in English" instruction into system prompt or first user message.
|
|
8
|
-
*
|
|
9
|
-
* Usage:
|
|
10
|
-
* const enforcer = new LocaleEnforcer();
|
|
11
|
-
* const modifiedMessages = enforcer.injectInstruction(messages);
|
|
12
|
-
*
|
|
13
|
-
* Strategy:
|
|
14
|
-
* 1. If system prompt exists: Prepend instruction
|
|
15
|
-
* 2. If no system prompt: Prepend to first user message
|
|
16
|
-
* 3. Preserve message structure (string vs array content)
|
|
17
|
-
*/
|
|
18
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
-
exports.LocaleEnforcer = void 0;
|
|
20
|
-
class LocaleEnforcer {
|
|
21
|
-
constructor(options = {}) {
|
|
22
|
-
this.instruction =
|
|
23
|
-
options.instruction ||
|
|
24
|
-
'CRITICAL: You MUST respond in English only, regardless of the input language or context. This is a strict requirement.';
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Inject English instruction into messages
|
|
28
|
-
* @param messages - Messages array to modify
|
|
29
|
-
* @returns Modified messages array
|
|
30
|
-
*/
|
|
31
|
-
injectInstruction(messages) {
|
|
32
|
-
// Clone messages to avoid mutation
|
|
33
|
-
const modifiedMessages = JSON.parse(JSON.stringify(messages));
|
|
34
|
-
// Strategy 1: Inject into system prompt (preferred)
|
|
35
|
-
const systemIndex = modifiedMessages.findIndex((m) => m.role === 'system');
|
|
36
|
-
if (systemIndex >= 0) {
|
|
37
|
-
const systemMsg = modifiedMessages[systemIndex];
|
|
38
|
-
if (typeof systemMsg.content === 'string') {
|
|
39
|
-
systemMsg.content = `${this.instruction}\n\n${systemMsg.content}`;
|
|
40
|
-
}
|
|
41
|
-
else if (Array.isArray(systemMsg.content)) {
|
|
42
|
-
systemMsg.content.unshift({
|
|
43
|
-
type: 'text',
|
|
44
|
-
text: this.instruction,
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
return modifiedMessages;
|
|
48
|
-
}
|
|
49
|
-
// Strategy 2: Prepend to first user message
|
|
50
|
-
const userIndex = modifiedMessages.findIndex((m) => m.role === 'user');
|
|
51
|
-
if (userIndex >= 0) {
|
|
52
|
-
const userMsg = modifiedMessages[userIndex];
|
|
53
|
-
if (typeof userMsg.content === 'string') {
|
|
54
|
-
userMsg.content = `${this.instruction}\n\n${userMsg.content}`;
|
|
55
|
-
}
|
|
56
|
-
else if (Array.isArray(userMsg.content)) {
|
|
57
|
-
userMsg.content.unshift({
|
|
58
|
-
type: 'text',
|
|
59
|
-
text: this.instruction,
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
return modifiedMessages;
|
|
63
|
-
}
|
|
64
|
-
// No system or user messages found (edge case)
|
|
65
|
-
return modifiedMessages;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
exports.LocaleEnforcer = LocaleEnforcer;
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* LocaleEnforcer - Force English output from GLM models
|
|
5
|
+
*
|
|
6
|
+
* Purpose: GLM models default to Chinese when prompts are ambiguous or contain Chinese context.
|
|
7
|
+
* This module always injects "MUST respond in English" instruction into system prompt or first user message.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* const enforcer = new LocaleEnforcer();
|
|
11
|
+
* const modifiedMessages = enforcer.injectInstruction(messages);
|
|
12
|
+
*
|
|
13
|
+
* Strategy:
|
|
14
|
+
* 1. If system prompt exists: Prepend instruction
|
|
15
|
+
* 2. If no system prompt: Prepend to first user message
|
|
16
|
+
* 3. Preserve message structure (string vs array content)
|
|
17
|
+
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.LocaleEnforcer = void 0;
|
|
20
|
+
class LocaleEnforcer {
|
|
21
|
+
constructor(options = {}) {
|
|
22
|
+
this.instruction =
|
|
23
|
+
options.instruction ||
|
|
24
|
+
'CRITICAL: You MUST respond in English only, regardless of the input language or context. This is a strict requirement.';
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Inject English instruction into messages
|
|
28
|
+
* @param messages - Messages array to modify
|
|
29
|
+
* @returns Modified messages array
|
|
30
|
+
*/
|
|
31
|
+
injectInstruction(messages) {
|
|
32
|
+
// Clone messages to avoid mutation
|
|
33
|
+
const modifiedMessages = JSON.parse(JSON.stringify(messages));
|
|
34
|
+
// Strategy 1: Inject into system prompt (preferred)
|
|
35
|
+
const systemIndex = modifiedMessages.findIndex((m) => m.role === 'system');
|
|
36
|
+
if (systemIndex >= 0) {
|
|
37
|
+
const systemMsg = modifiedMessages[systemIndex];
|
|
38
|
+
if (typeof systemMsg.content === 'string') {
|
|
39
|
+
systemMsg.content = `${this.instruction}\n\n${systemMsg.content}`;
|
|
40
|
+
}
|
|
41
|
+
else if (Array.isArray(systemMsg.content)) {
|
|
42
|
+
systemMsg.content.unshift({
|
|
43
|
+
type: 'text',
|
|
44
|
+
text: this.instruction,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
return modifiedMessages;
|
|
48
|
+
}
|
|
49
|
+
// Strategy 2: Prepend to first user message
|
|
50
|
+
const userIndex = modifiedMessages.findIndex((m) => m.role === 'user');
|
|
51
|
+
if (userIndex >= 0) {
|
|
52
|
+
const userMsg = modifiedMessages[userIndex];
|
|
53
|
+
if (typeof userMsg.content === 'string') {
|
|
54
|
+
userMsg.content = `${this.instruction}\n\n${userMsg.content}`;
|
|
55
|
+
}
|
|
56
|
+
else if (Array.isArray(userMsg.content)) {
|
|
57
|
+
userMsg.content.unshift({
|
|
58
|
+
type: 'text',
|
|
59
|
+
text: this.instruction,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
return modifiedMessages;
|
|
63
|
+
}
|
|
64
|
+
// No system or user messages found (edge case)
|
|
65
|
+
return modifiedMessages;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.LocaleEnforcer = LocaleEnforcer;
|
|
69
69
|
//# sourceMappingURL=locale-enforcer.js.map
|