@kaitranntt/ccs 7.31.0 → 7.31.1-dev.2
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/dist/cliproxy/auth/gemini-token-refresh.d.ts +4 -0
- package/dist/cliproxy/auth/gemini-token-refresh.d.ts.map +1 -1
- package/dist/cliproxy/auth/gemini-token-refresh.js +153 -18
- package/dist/cliproxy/auth/gemini-token-refresh.js.map +1 -1
- package/dist/cliproxy/cliproxy-executor.d.ts.map +1 -1
- package/dist/cliproxy/cliproxy-executor.js +60 -12
- package/dist/cliproxy/cliproxy-executor.js.map +1 -1
- package/dist/cliproxy/index.d.ts +6 -0
- package/dist/cliproxy/index.d.ts.map +1 -1
- package/dist/cliproxy/index.js +11 -1
- package/dist/cliproxy/index.js.map +1 -1
- package/dist/cliproxy/tool-name-mapper.d.ts +103 -0
- package/dist/cliproxy/tool-name-mapper.d.ts.map +1 -0
- package/dist/cliproxy/tool-name-mapper.js +149 -0
- package/dist/cliproxy/tool-name-mapper.js.map +1 -0
- package/dist/cliproxy/tool-name-sanitizer.d.ts +65 -0
- package/dist/cliproxy/tool-name-sanitizer.d.ts.map +1 -0
- package/dist/cliproxy/tool-name-sanitizer.js +118 -0
- package/dist/cliproxy/tool-name-sanitizer.js.map +1 -0
- package/dist/cliproxy/tool-sanitization-proxy.d.ts +70 -0
- package/dist/cliproxy/tool-sanitization-proxy.d.ts.map +1 -0
- package/dist/cliproxy/tool-sanitization-proxy.js +453 -0
- package/dist/cliproxy/tool-sanitization-proxy.js.map +1 -0
- package/package.json +1 -1
package/dist/cliproxy/index.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
exports.configureProviderModel = exports.getCurrentModel = exports.hasUserSettings = exports.findModel = exports.getProviderCatalog = exports.supportsModelConfig = exports.MODEL_CATALOG = exports.clearConfigCache = exports.getEnvVarsFromConfig = exports.getModelMappingFromConfig = exports.loadBaseConfig = exports.CLIPROXY_CONFIG_VERSION = exports.CLIPROXY_DEFAULT_PORT = exports.deleteConfig = exports.configExists = exports.getBinDir = exports.getCliproxyConfigPath = exports.getAuthDir = exports.getProviderAuthDir = exports.getCliproxyDir = exports.getModelMapping = exports.getProviderConfig = exports.ensureProviderSettings = exports.getProviderSettingsPath = exports.getEffectiveEnvVars = exports.getClaudeEnvVars = exports.parseUserApiKeys = exports.configNeedsRegeneration = exports.regenerateConfig = exports.generateConfig = exports.getVersionPinPath = exports.isVersionPinned = exports.clearPinnedVersion = exports.savePinnedVersion = exports.getPinnedVersion = exports.fetchLatestCliproxyVersion = exports.installCliproxyVersion = exports.getInstalledCliproxyVersion = exports.getCLIProxyPath = exports.isCLIProxyInstalled = exports.ensureCLIProxyBinary = exports.BinaryManager = exports.CLIPROXY_VERSION = exports.getPlatformDescription = exports.isPlatformSupported = exports.getArchiveBinaryName = exports.getExecutableName = exports.getChecksumsUrl = exports.getDownloadUrl = exports.detectPlatform = void 0;
|
|
8
8
|
exports.ManagementApiClient = exports.THINKING_BUDGET_DEFAULT_MIN = exports.THINKING_BUDGET_MAX = exports.THINKING_BUDGET_MIN = exports.THINKING_AUTO_VALUE = exports.THINKING_OFF_VALUES = exports.VALID_THINKING_TIERS = exports.VALID_THINKING_LEVELS = exports.THINKING_LEVEL_BUDGETS = exports.validateThinking = exports.getAuthSummary = exports.resetAuthToDefaults = exports.setVariantApiKey = exports.setGlobalManagementSecret = exports.setGlobalApiKey = exports.getEffectiveManagementSecret = exports.getEffectiveApiKey = exports.maskToken = exports.generateSecureToken = exports.withStartupLock = exports.acquireStartupLock = exports.reclaimOrphanedProxy = exports.waitForProxyHealthy = exports.detectRunningProxy = exports.getServiceStatus = exports.stopCliproxyService = exports.ensureCliproxyService = exports.TOGETHER_TEMPLATE = exports.OPENROUTER_TEMPLATE = exports.removeOpenAICompatProvider = exports.updateOpenAICompatProvider = exports.addOpenAICompatProvider = exports.getOpenAICompatProvider = exports.listOpenAICompatProviders = exports.fetchAccountQuota = exports.isCliproxyRunning = exports.fetchCliproxyStats = exports.displayAuthStatus = exports.getProviderTokenDir = exports.getOAuthConfig = exports.ensureAuth = exports.triggerOAuth = exports.clearAuth = exports.getAllAuthStatus = exports.getAuthStatus = exports.isAuthenticated = exports.findAvailablePort = exports.isPortAvailable = exports.execClaudeWithCLIProxy = exports.showCurrentConfig = void 0;
|
|
9
|
-
exports.isProfileSyncable = exports.getSyncableProfileCount = exports.generateSyncPreview = exports.generateSyncPayload = exports.mapProfileToClaudeKey = exports.loadSyncableProfiles = exports.createManagementClient = void 0;
|
|
9
|
+
exports.ToolSanitizationProxy = exports.ToolNameMapper = exports.GEMINI_MAX_TOOL_NAME_LENGTH = exports.smartTruncate = exports.removeDuplicateSegments = exports.isValidToolName = exports.sanitizeToolName = exports.isProfileSyncable = exports.getSyncableProfileCount = exports.generateSyncPreview = exports.generateSyncPayload = exports.mapProfileToClaudeKey = exports.loadSyncableProfiles = exports.createManagementClient = void 0;
|
|
10
10
|
// Platform detection
|
|
11
11
|
var platform_detector_1 = require("./platform-detector");
|
|
12
12
|
Object.defineProperty(exports, "detectPlatform", { enumerable: true, get: function () { return platform_detector_1.detectPlatform; } });
|
|
@@ -138,4 +138,14 @@ Object.defineProperty(exports, "generateSyncPayload", { enumerable: true, get: f
|
|
|
138
138
|
Object.defineProperty(exports, "generateSyncPreview", { enumerable: true, get: function () { return sync_1.generateSyncPreview; } });
|
|
139
139
|
Object.defineProperty(exports, "getSyncableProfileCount", { enumerable: true, get: function () { return sync_1.getSyncableProfileCount; } });
|
|
140
140
|
Object.defineProperty(exports, "isProfileSyncable", { enumerable: true, get: function () { return sync_1.isProfileSyncable; } });
|
|
141
|
+
var tool_name_sanitizer_1 = require("./tool-name-sanitizer");
|
|
142
|
+
Object.defineProperty(exports, "sanitizeToolName", { enumerable: true, get: function () { return tool_name_sanitizer_1.sanitizeToolName; } });
|
|
143
|
+
Object.defineProperty(exports, "isValidToolName", { enumerable: true, get: function () { return tool_name_sanitizer_1.isValidToolName; } });
|
|
144
|
+
Object.defineProperty(exports, "removeDuplicateSegments", { enumerable: true, get: function () { return tool_name_sanitizer_1.removeDuplicateSegments; } });
|
|
145
|
+
Object.defineProperty(exports, "smartTruncate", { enumerable: true, get: function () { return tool_name_sanitizer_1.smartTruncate; } });
|
|
146
|
+
Object.defineProperty(exports, "GEMINI_MAX_TOOL_NAME_LENGTH", { enumerable: true, get: function () { return tool_name_sanitizer_1.GEMINI_MAX_TOOL_NAME_LENGTH; } });
|
|
147
|
+
var tool_name_mapper_1 = require("./tool-name-mapper");
|
|
148
|
+
Object.defineProperty(exports, "ToolNameMapper", { enumerable: true, get: function () { return tool_name_mapper_1.ToolNameMapper; } });
|
|
149
|
+
var tool_sanitization_proxy_1 = require("./tool-sanitization-proxy");
|
|
150
|
+
Object.defineProperty(exports, "ToolSanitizationProxy", { enumerable: true, get: function () { return tool_sanitization_proxy_1.ToolSanitizationProxy; } });
|
|
141
151
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cliproxy/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cliproxy/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Name Mapper
|
|
3
|
+
*
|
|
4
|
+
* Bidirectional mapping class to track original ↔ sanitized tool names.
|
|
5
|
+
* Used to restore original names in API responses after sanitization.
|
|
6
|
+
*
|
|
7
|
+
* Flow:
|
|
8
|
+
* 1. Request: registerTools() sanitizes names and stores mapping
|
|
9
|
+
* 2. Response: restoreToolUse() restores original names using mapping
|
|
10
|
+
*/
|
|
11
|
+
/** MCP tool definition from Claude API */
|
|
12
|
+
export interface Tool {
|
|
13
|
+
name: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
input_schema?: Record<string, unknown>;
|
|
16
|
+
[key: string]: unknown;
|
|
17
|
+
}
|
|
18
|
+
/** Tool use content block from Claude API response */
|
|
19
|
+
export interface ToolUseBlock {
|
|
20
|
+
type: 'tool_use';
|
|
21
|
+
id: string;
|
|
22
|
+
name: string;
|
|
23
|
+
input: Record<string, unknown>;
|
|
24
|
+
}
|
|
25
|
+
/** Content block from Claude API response (union type) */
|
|
26
|
+
export interface ContentBlock {
|
|
27
|
+
type: string;
|
|
28
|
+
[key: string]: unknown;
|
|
29
|
+
}
|
|
30
|
+
/** Record of a sanitization change */
|
|
31
|
+
export interface SanitizationChange {
|
|
32
|
+
original: string;
|
|
33
|
+
sanitized: string;
|
|
34
|
+
}
|
|
35
|
+
/** Record of a hash collision */
|
|
36
|
+
export interface HashCollision {
|
|
37
|
+
sanitized: string;
|
|
38
|
+
originals: string[];
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Bidirectional mapper for tool name sanitization.
|
|
42
|
+
*
|
|
43
|
+
* Maintains a per-request mapping between sanitized and original tool names.
|
|
44
|
+
* Must be cleared between requests to avoid memory leaks.
|
|
45
|
+
*/
|
|
46
|
+
export declare class ToolNameMapper {
|
|
47
|
+
/** Map from sanitized name → original name */
|
|
48
|
+
private mapping;
|
|
49
|
+
/** List of all changes made during registration */
|
|
50
|
+
private changes;
|
|
51
|
+
/** List of detected hash collisions */
|
|
52
|
+
private collisions;
|
|
53
|
+
/**
|
|
54
|
+
* Register tools and sanitize their names.
|
|
55
|
+
* Stores mapping for later restoration.
|
|
56
|
+
*
|
|
57
|
+
* @param tools Array of tool definitions
|
|
58
|
+
* @returns Array of tools with sanitized names
|
|
59
|
+
*/
|
|
60
|
+
registerTools(tools: Tool[]): Tool[];
|
|
61
|
+
/**
|
|
62
|
+
* Restore original tool names in content blocks.
|
|
63
|
+
* Looks for tool_use blocks and restores their names.
|
|
64
|
+
*
|
|
65
|
+
* @param content Array of content blocks from API response
|
|
66
|
+
* @returns Array with restored tool names
|
|
67
|
+
*/
|
|
68
|
+
restoreToolUse(content: ContentBlock[]): ContentBlock[];
|
|
69
|
+
/**
|
|
70
|
+
* Restore tool name in a single tool_use block.
|
|
71
|
+
* Useful for streaming responses.
|
|
72
|
+
*
|
|
73
|
+
* @param name The sanitized tool name
|
|
74
|
+
* @returns Original name if mapped, otherwise the input name
|
|
75
|
+
*/
|
|
76
|
+
restoreName(name: string): string;
|
|
77
|
+
/**
|
|
78
|
+
* Check if any sanitization occurred during registration.
|
|
79
|
+
*/
|
|
80
|
+
hasChanges(): boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Get all sanitization changes for logging.
|
|
83
|
+
*/
|
|
84
|
+
getChanges(): SanitizationChange[];
|
|
85
|
+
/**
|
|
86
|
+
* Get the number of tools that were sanitized.
|
|
87
|
+
*/
|
|
88
|
+
getChangeCount(): number;
|
|
89
|
+
/**
|
|
90
|
+
* Check if any hash collisions were detected.
|
|
91
|
+
* Collisions occur when multiple original names map to the same sanitized name.
|
|
92
|
+
*/
|
|
93
|
+
hasCollisions(): boolean;
|
|
94
|
+
/**
|
|
95
|
+
* Get all detected hash collisions for logging/warning.
|
|
96
|
+
*/
|
|
97
|
+
getCollisions(): HashCollision[];
|
|
98
|
+
/**
|
|
99
|
+
* Clear all mappings. Call between requests.
|
|
100
|
+
*/
|
|
101
|
+
clear(): void;
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=tool-name-mapper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-name-mapper.d.ts","sourceRoot":"","sources":["../../src/cliproxy/tool-name-mapper.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,0CAA0C;AAC1C,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,sDAAsD;AACtD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,UAAU,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,0DAA0D;AAC1D,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,sCAAsC;AACtC,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,iCAAiC;AACjC,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;;;;GAKG;AACH,qBAAa,cAAc;IACzB,8CAA8C;IAC9C,OAAO,CAAC,OAAO,CAAkC;IAEjD,mDAAmD;IACnD,OAAO,CAAC,OAAO,CAA4B;IAE3C,uCAAuC;IACvC,OAAO,CAAC,UAAU,CAAuB;IAEzC;;;;;;OAMG;IACH,aAAa,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE;IAqCpC;;;;;;OAMG;IACH,cAAc,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,YAAY,EAAE;IAyBvD;;;;;;OAMG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAIjC;;OAEG;IACH,UAAU,IAAI,OAAO;IAIrB;;OAEG;IACH,UAAU,IAAI,kBAAkB,EAAE;IAIlC;;OAEG;IACH,cAAc,IAAI,MAAM;IAIxB;;;OAGG;IACH,aAAa,IAAI,OAAO;IAIxB;;OAEG;IACH,aAAa,IAAI,aAAa,EAAE;IAIhC;;OAEG;IACH,KAAK,IAAI,IAAI;CAKd"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Tool Name Mapper
|
|
4
|
+
*
|
|
5
|
+
* Bidirectional mapping class to track original ↔ sanitized tool names.
|
|
6
|
+
* Used to restore original names in API responses after sanitization.
|
|
7
|
+
*
|
|
8
|
+
* Flow:
|
|
9
|
+
* 1. Request: registerTools() sanitizes names and stores mapping
|
|
10
|
+
* 2. Response: restoreToolUse() restores original names using mapping
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.ToolNameMapper = void 0;
|
|
14
|
+
const tool_name_sanitizer_1 = require("./tool-name-sanitizer");
|
|
15
|
+
/**
|
|
16
|
+
* Bidirectional mapper for tool name sanitization.
|
|
17
|
+
*
|
|
18
|
+
* Maintains a per-request mapping between sanitized and original tool names.
|
|
19
|
+
* Must be cleared between requests to avoid memory leaks.
|
|
20
|
+
*/
|
|
21
|
+
class ToolNameMapper {
|
|
22
|
+
constructor() {
|
|
23
|
+
/** Map from sanitized name → original name */
|
|
24
|
+
this.mapping = new Map();
|
|
25
|
+
/** List of all changes made during registration */
|
|
26
|
+
this.changes = [];
|
|
27
|
+
/** List of detected hash collisions */
|
|
28
|
+
this.collisions = [];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Register tools and sanitize their names.
|
|
32
|
+
* Stores mapping for later restoration.
|
|
33
|
+
*
|
|
34
|
+
* @param tools Array of tool definitions
|
|
35
|
+
* @returns Array of tools with sanitized names
|
|
36
|
+
*/
|
|
37
|
+
registerTools(tools) {
|
|
38
|
+
return tools.map((tool) => {
|
|
39
|
+
const result = (0, tool_name_sanitizer_1.sanitizeToolName)(tool.name);
|
|
40
|
+
if (result.changed) {
|
|
41
|
+
// Check for collision: sanitized name already maps to different original
|
|
42
|
+
const existingOriginal = this.mapping.get(result.sanitized);
|
|
43
|
+
if (existingOriginal && existingOriginal !== tool.name) {
|
|
44
|
+
// Record collision
|
|
45
|
+
const existing = this.collisions.find((c) => c.sanitized === result.sanitized);
|
|
46
|
+
if (existing) {
|
|
47
|
+
if (!existing.originals.includes(tool.name)) {
|
|
48
|
+
existing.originals.push(tool.name);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
this.collisions.push({
|
|
53
|
+
sanitized: result.sanitized,
|
|
54
|
+
originals: [existingOriginal, tool.name],
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Store mapping: sanitized → original
|
|
59
|
+
this.mapping.set(result.sanitized, tool.name);
|
|
60
|
+
this.changes.push({
|
|
61
|
+
original: tool.name,
|
|
62
|
+
sanitized: result.sanitized,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
...tool,
|
|
67
|
+
name: result.sanitized,
|
|
68
|
+
};
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Restore original tool names in content blocks.
|
|
73
|
+
* Looks for tool_use blocks and restores their names.
|
|
74
|
+
*
|
|
75
|
+
* @param content Array of content blocks from API response
|
|
76
|
+
* @returns Array with restored tool names
|
|
77
|
+
*/
|
|
78
|
+
restoreToolUse(content) {
|
|
79
|
+
return content.map((block) => {
|
|
80
|
+
if (block.type !== 'tool_use') {
|
|
81
|
+
return block;
|
|
82
|
+
}
|
|
83
|
+
// Type guard: we know this is a tool_use block
|
|
84
|
+
const toolUseName = block.name;
|
|
85
|
+
if (!toolUseName) {
|
|
86
|
+
return block;
|
|
87
|
+
}
|
|
88
|
+
const originalName = this.mapping.get(toolUseName);
|
|
89
|
+
if (originalName) {
|
|
90
|
+
return {
|
|
91
|
+
...block,
|
|
92
|
+
name: originalName,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
return block;
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Restore tool name in a single tool_use block.
|
|
100
|
+
* Useful for streaming responses.
|
|
101
|
+
*
|
|
102
|
+
* @param name The sanitized tool name
|
|
103
|
+
* @returns Original name if mapped, otherwise the input name
|
|
104
|
+
*/
|
|
105
|
+
restoreName(name) {
|
|
106
|
+
return this.mapping.get(name) ?? name;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Check if any sanitization occurred during registration.
|
|
110
|
+
*/
|
|
111
|
+
hasChanges() {
|
|
112
|
+
return this.changes.length > 0;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Get all sanitization changes for logging.
|
|
116
|
+
*/
|
|
117
|
+
getChanges() {
|
|
118
|
+
return [...this.changes];
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Get the number of tools that were sanitized.
|
|
122
|
+
*/
|
|
123
|
+
getChangeCount() {
|
|
124
|
+
return this.changes.length;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Check if any hash collisions were detected.
|
|
128
|
+
* Collisions occur when multiple original names map to the same sanitized name.
|
|
129
|
+
*/
|
|
130
|
+
hasCollisions() {
|
|
131
|
+
return this.collisions.length > 0;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Get all detected hash collisions for logging/warning.
|
|
135
|
+
*/
|
|
136
|
+
getCollisions() {
|
|
137
|
+
return [...this.collisions];
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Clear all mappings. Call between requests.
|
|
141
|
+
*/
|
|
142
|
+
clear() {
|
|
143
|
+
this.mapping.clear();
|
|
144
|
+
this.changes = [];
|
|
145
|
+
this.collisions = [];
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
exports.ToolNameMapper = ToolNameMapper;
|
|
149
|
+
//# sourceMappingURL=tool-name-mapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-name-mapper.js","sourceRoot":"","sources":["../../src/cliproxy/tool-name-mapper.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Name Sanitizer
|
|
3
|
+
*
|
|
4
|
+
* Sanitizes MCP tool names to comply with Gemini API constraints:
|
|
5
|
+
* - Max 64 characters
|
|
6
|
+
* - Must start with letter or underscore
|
|
7
|
+
* - Only a-z A-Z 0-9 _ . : - / allowed
|
|
8
|
+
*
|
|
9
|
+
* Strategies:
|
|
10
|
+
* 1. Remove duplicate segments (e.g., gitmcp__foo__foo → gitmcp__foo)
|
|
11
|
+
* 2. Smart truncate with hash suffix if still >64 chars
|
|
12
|
+
*
|
|
13
|
+
* Note: Hash collision risk is ~1 in 16M with 6-char MD5 prefix.
|
|
14
|
+
* Acceptable for typical MCP tool counts (<1000 tools).
|
|
15
|
+
*/
|
|
16
|
+
/** Maximum tool name length allowed by Gemini API */
|
|
17
|
+
export declare const GEMINI_MAX_TOOL_NAME_LENGTH = 64;
|
|
18
|
+
/** Result of sanitization operation */
|
|
19
|
+
export interface SanitizeResult {
|
|
20
|
+
/** The sanitized tool name */
|
|
21
|
+
sanitized: string;
|
|
22
|
+
/** Whether the name was changed */
|
|
23
|
+
changed: boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Check if a tool name is valid for Gemini API.
|
|
27
|
+
*
|
|
28
|
+
* Requirements:
|
|
29
|
+
* - Length <= 64 characters
|
|
30
|
+
* - Starts with letter or underscore
|
|
31
|
+
* - Contains only valid characters: a-z A-Z 0-9 _ . : -
|
|
32
|
+
*/
|
|
33
|
+
export declare function isValidToolName(name: string): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Remove consecutive duplicate segments separated by '__'.
|
|
36
|
+
*
|
|
37
|
+
* Examples:
|
|
38
|
+
* - 'gitmcp__foo__foo' → 'gitmcp__foo'
|
|
39
|
+
* - 'a__b__c__b__c' → 'a__b__c'
|
|
40
|
+
* - 'no_dupes' → 'no_dupes'
|
|
41
|
+
*/
|
|
42
|
+
export declare function removeDuplicateSegments(name: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* Smart truncate a name to fit within maxLen.
|
|
45
|
+
* Preserves start of name and appends hash suffix for uniqueness.
|
|
46
|
+
*
|
|
47
|
+
* Format: <prefix>_<6-char-hash>
|
|
48
|
+
*
|
|
49
|
+
* @param name The name to truncate
|
|
50
|
+
* @param maxLen Maximum allowed length (default: 64)
|
|
51
|
+
*/
|
|
52
|
+
export declare function smartTruncate(name: string, maxLen?: number): string;
|
|
53
|
+
/**
|
|
54
|
+
* Sanitize a tool name to comply with Gemini API constraints.
|
|
55
|
+
*
|
|
56
|
+
* Process:
|
|
57
|
+
* 1. Remove duplicate segments (always, as duplicates are likely unintentional)
|
|
58
|
+
* 2. Truncate with hash if >64 chars
|
|
59
|
+
* 3. Return result with changed flag
|
|
60
|
+
*
|
|
61
|
+
* @param name The original tool name
|
|
62
|
+
* @returns Sanitization result with sanitized name and changed flag
|
|
63
|
+
*/
|
|
64
|
+
export declare function sanitizeToolName(name: string): SanitizeResult;
|
|
65
|
+
//# sourceMappingURL=tool-name-sanitizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-name-sanitizer.d.ts","sourceRoot":"","sources":["../../src/cliproxy/tool-name-sanitizer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,qDAAqD;AACrD,eAAO,MAAM,2BAA2B,KAAK,CAAC;AAK9C,uCAAuC;AACvC,MAAM,WAAW,cAAc;IAC7B,8BAA8B;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAQrD;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAY5D;AAUD;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAoC,GAAG,MAAM,CAWhG;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAmB7D"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Tool Name Sanitizer
|
|
4
|
+
*
|
|
5
|
+
* Sanitizes MCP tool names to comply with Gemini API constraints:
|
|
6
|
+
* - Max 64 characters
|
|
7
|
+
* - Must start with letter or underscore
|
|
8
|
+
* - Only a-z A-Z 0-9 _ . : - / allowed
|
|
9
|
+
*
|
|
10
|
+
* Strategies:
|
|
11
|
+
* 1. Remove duplicate segments (e.g., gitmcp__foo__foo → gitmcp__foo)
|
|
12
|
+
* 2. Smart truncate with hash suffix if still >64 chars
|
|
13
|
+
*
|
|
14
|
+
* Note: Hash collision risk is ~1 in 16M with 6-char MD5 prefix.
|
|
15
|
+
* Acceptable for typical MCP tool counts (<1000 tools).
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.sanitizeToolName = exports.smartTruncate = exports.removeDuplicateSegments = exports.isValidToolName = exports.GEMINI_MAX_TOOL_NAME_LENGTH = void 0;
|
|
19
|
+
const crypto_1 = require("crypto");
|
|
20
|
+
/** Maximum tool name length allowed by Gemini API */
|
|
21
|
+
exports.GEMINI_MAX_TOOL_NAME_LENGTH = 64;
|
|
22
|
+
/** Valid characters pattern for Gemini tool names */
|
|
23
|
+
const VALID_CHARS_REGEX = /^[a-zA-Z_][a-zA-Z0-9_.:/-]*$/;
|
|
24
|
+
/**
|
|
25
|
+
* Check if a tool name is valid for Gemini API.
|
|
26
|
+
*
|
|
27
|
+
* Requirements:
|
|
28
|
+
* - Length <= 64 characters
|
|
29
|
+
* - Starts with letter or underscore
|
|
30
|
+
* - Contains only valid characters: a-z A-Z 0-9 _ . : -
|
|
31
|
+
*/
|
|
32
|
+
function isValidToolName(name) {
|
|
33
|
+
if (!name || name.length === 0) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
if (name.length > exports.GEMINI_MAX_TOOL_NAME_LENGTH) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
return VALID_CHARS_REGEX.test(name);
|
|
40
|
+
}
|
|
41
|
+
exports.isValidToolName = isValidToolName;
|
|
42
|
+
/**
|
|
43
|
+
* Remove consecutive duplicate segments separated by '__'.
|
|
44
|
+
*
|
|
45
|
+
* Examples:
|
|
46
|
+
* - 'gitmcp__foo__foo' → 'gitmcp__foo'
|
|
47
|
+
* - 'a__b__c__b__c' → 'a__b__c'
|
|
48
|
+
* - 'no_dupes' → 'no_dupes'
|
|
49
|
+
*/
|
|
50
|
+
function removeDuplicateSegments(name) {
|
|
51
|
+
const segments = name.split('__');
|
|
52
|
+
const deduped = [];
|
|
53
|
+
for (const segment of segments) {
|
|
54
|
+
// Only add if different from previous segment
|
|
55
|
+
if (deduped.length === 0 || deduped[deduped.length - 1] !== segment) {
|
|
56
|
+
deduped.push(segment);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return deduped.join('__');
|
|
60
|
+
}
|
|
61
|
+
exports.removeDuplicateSegments = removeDuplicateSegments;
|
|
62
|
+
/**
|
|
63
|
+
* Generate a short hash from a string for truncation suffix.
|
|
64
|
+
* Uses first 6 characters of MD5 hash (16M combinations).
|
|
65
|
+
*/
|
|
66
|
+
function generateShortHash(input) {
|
|
67
|
+
return (0, crypto_1.createHash)('md5').update(input).digest('hex').slice(0, 6);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Smart truncate a name to fit within maxLen.
|
|
71
|
+
* Preserves start of name and appends hash suffix for uniqueness.
|
|
72
|
+
*
|
|
73
|
+
* Format: <prefix>_<6-char-hash>
|
|
74
|
+
*
|
|
75
|
+
* @param name The name to truncate
|
|
76
|
+
* @param maxLen Maximum allowed length (default: 64)
|
|
77
|
+
*/
|
|
78
|
+
function smartTruncate(name, maxLen = exports.GEMINI_MAX_TOOL_NAME_LENGTH) {
|
|
79
|
+
if (name.length <= maxLen) {
|
|
80
|
+
return name;
|
|
81
|
+
}
|
|
82
|
+
// Format: prefix + '_' + 6-char hash = 7 chars for suffix
|
|
83
|
+
const hash = generateShortHash(name);
|
|
84
|
+
const prefixLen = maxLen - 7; // 7 = '_' (1) + hash (6)
|
|
85
|
+
const prefix = name.slice(0, prefixLen);
|
|
86
|
+
return `${prefix}_${hash}`;
|
|
87
|
+
}
|
|
88
|
+
exports.smartTruncate = smartTruncate;
|
|
89
|
+
/**
|
|
90
|
+
* Sanitize a tool name to comply with Gemini API constraints.
|
|
91
|
+
*
|
|
92
|
+
* Process:
|
|
93
|
+
* 1. Remove duplicate segments (always, as duplicates are likely unintentional)
|
|
94
|
+
* 2. Truncate with hash if >64 chars
|
|
95
|
+
* 3. Return result with changed flag
|
|
96
|
+
*
|
|
97
|
+
* @param name The original tool name
|
|
98
|
+
* @returns Sanitization result with sanitized name and changed flag
|
|
99
|
+
*/
|
|
100
|
+
function sanitizeToolName(name) {
|
|
101
|
+
// Step 1: Always try to remove duplicate segments
|
|
102
|
+
// Duplicates like gitmcp__foo__foo are likely unintentional from MCP naming
|
|
103
|
+
let sanitized = removeDuplicateSegments(name);
|
|
104
|
+
// Step 2: Truncate if still too long
|
|
105
|
+
if (sanitized.length > exports.GEMINI_MAX_TOOL_NAME_LENGTH) {
|
|
106
|
+
sanitized = smartTruncate(sanitized);
|
|
107
|
+
}
|
|
108
|
+
// Step 3: If still invalid after sanitization, apply truncation to original
|
|
109
|
+
if (!isValidToolName(sanitized)) {
|
|
110
|
+
sanitized = smartTruncate(name);
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
sanitized,
|
|
114
|
+
changed: sanitized !== name,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
exports.sanitizeToolName = sanitizeToolName;
|
|
118
|
+
//# sourceMappingURL=tool-name-sanitizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-name-sanitizer.js","sourceRoot":"","sources":["../../src/cliproxy/tool-name-sanitizer.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;;AAEH,mCAAoC;AAEpC,qDAAqD;AACxC,QAAA,2BAA2B,GAAG,EAAE,CAAC;AAE9C,qDAAqD;AACrD,MAAM,iBAAiB,GAAG,8BAA8B,CAAC;AAUzD;;;;;;;GAOG;AACH,SAAgB,eAAe,CAAC,IAAY;IAC1C,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,GAAG,mCAA2B,EAAE,CAAC;QAC9C,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACtC,CAAC;AARD,0CAQC;AAED;;;;;;;GAOG;AACH,SAAgB,uBAAuB,CAAC,IAAY;IAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,8CAA8C;QAC9C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,OAAO,EAAE,CAAC;YACpE,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC;AAZD,0DAYC;AAED;;;GAGG;AACH,SAAS,iBAAiB,CAAC,KAAa;IACtC,OAAO,IAAA,mBAAU,EAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACnE,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,aAAa,CAAC,IAAY,EAAE,SAAiB,mCAA2B;IACtF,IAAI,IAAI,CAAC,MAAM,IAAI,MAAM,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,0DAA0D;IAC1D,MAAM,IAAI,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC,yBAAyB;IACvD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IAExC,OAAO,GAAG,MAAM,IAAI,IAAI,EAAE,CAAC;AAC7B,CAAC;AAXD,sCAWC;AAED;;;;;;;;;;GAUG;AACH,SAAgB,gBAAgB,CAAC,IAAY;IAC3C,kDAAkD;IAClD,4EAA4E;IAC5E,IAAI,SAAS,GAAG,uBAAuB,CAAC,IAAI,CAAC,CAAC;IAE9C,qCAAqC;IACrC,IAAI,SAAS,CAAC,MAAM,GAAG,mCAA2B,EAAE,CAAC;QACnD,SAAS,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;IACvC,CAAC;IAED,4EAA4E;IAC5E,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,EAAE,CAAC;QAChC,SAAS,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAED,OAAO;QACL,SAAS;QACT,OAAO,EAAE,SAAS,KAAK,IAAI;KAC5B,CAAC;AACJ,CAAC;AAnBD,4CAmBC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Sanitization Proxy
|
|
3
|
+
*
|
|
4
|
+
* HTTP proxy that intercepts Claude CLI → CLIProxy requests to:
|
|
5
|
+
* 1. Sanitize MCP tool names exceeding Gemini's 64-char limit
|
|
6
|
+
* 2. Forward sanitized requests to upstream
|
|
7
|
+
* 3. Restore original names in responses
|
|
8
|
+
*
|
|
9
|
+
* Follows CodexReasoningProxy pattern for consistency.
|
|
10
|
+
*/
|
|
11
|
+
export interface ToolSanitizationProxyConfig {
|
|
12
|
+
/** Upstream CLIProxy URL */
|
|
13
|
+
upstreamBaseUrl: string;
|
|
14
|
+
/** Enable verbose logging */
|
|
15
|
+
verbose?: boolean;
|
|
16
|
+
/** Log warnings when sanitization occurs */
|
|
17
|
+
warnOnSanitize?: boolean;
|
|
18
|
+
/** Request timeout in milliseconds */
|
|
19
|
+
timeoutMs?: number;
|
|
20
|
+
}
|
|
21
|
+
export declare class ToolSanitizationProxy {
|
|
22
|
+
private server;
|
|
23
|
+
private port;
|
|
24
|
+
private readonly config;
|
|
25
|
+
private readonly logFilePath;
|
|
26
|
+
private readonly debugMode;
|
|
27
|
+
constructor(config: ToolSanitizationProxyConfig);
|
|
28
|
+
/**
|
|
29
|
+
* Initialize log file path and ensure directory exists.
|
|
30
|
+
*/
|
|
31
|
+
private initLogFile;
|
|
32
|
+
/**
|
|
33
|
+
* Write log entry to file (always) and console (if CCS_DEBUG=1).
|
|
34
|
+
*/
|
|
35
|
+
private writeLog;
|
|
36
|
+
private log;
|
|
37
|
+
private warn;
|
|
38
|
+
/**
|
|
39
|
+
* Start the proxy server on an ephemeral port.
|
|
40
|
+
* @returns The assigned port number
|
|
41
|
+
*/
|
|
42
|
+
start(): Promise<number>;
|
|
43
|
+
/**
|
|
44
|
+
* Stop the proxy server.
|
|
45
|
+
*/
|
|
46
|
+
stop(): void;
|
|
47
|
+
/**
|
|
48
|
+
* Get the port the proxy is listening on.
|
|
49
|
+
*/
|
|
50
|
+
getPort(): number | null;
|
|
51
|
+
private readBody;
|
|
52
|
+
private handleRequest;
|
|
53
|
+
private buildForwardHeaders;
|
|
54
|
+
private getRequestFn;
|
|
55
|
+
private forwardRaw;
|
|
56
|
+
/**
|
|
57
|
+
* Forward JSON request and buffer response for tool name restoration.
|
|
58
|
+
*/
|
|
59
|
+
private forwardJsonBuffered;
|
|
60
|
+
/**
|
|
61
|
+
* Forward JSON request and stream response with tool name restoration.
|
|
62
|
+
* Handles SSE (Server-Sent Events) format.
|
|
63
|
+
*/
|
|
64
|
+
private forwardJsonStreaming;
|
|
65
|
+
/**
|
|
66
|
+
* Process a single SSE event, restoring tool names if present.
|
|
67
|
+
*/
|
|
68
|
+
private processSSEEvent;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=tool-sanitization-proxy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-sanitization-proxy.d.ts","sourceRoot":"","sources":["../../src/cliproxy/tool-sanitization-proxy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAWH,MAAM,WAAW,2BAA2B;IAC1C,4BAA4B;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,6BAA6B;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,4CAA4C;IAC5C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,sCAAsC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAUD,qBAAa,qBAAqB;IAChC,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,IAAI,CAAuB;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwC;IAC/D,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAU;gBAExB,MAAM,EAAE,2BAA2B;IAW/C;;OAEG;IACH,OAAO,CAAC,WAAW;IAoBnB;;OAEG;IACH,OAAO,CAAC,QAAQ;IAkBhB,OAAO,CAAC,GAAG;IAMX,OAAO,CAAC,IAAI;IAMZ;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAmB9B;;OAEG;IACH,IAAI,IAAI,IAAI;IAOZ;;OAEG;IACH,OAAO,IAAI,MAAM,GAAG,IAAI;IAIxB,OAAO,CAAC,QAAQ;YAqBF,aAAa;IA6E3B,OAAO,CAAC,mBAAmB;IAmC3B,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,UAAU;IA+BlB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAsE3B;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAsE5B;;OAEG;IACH,OAAO,CAAC,eAAe;CAqDxB"}
|