@hileeon/mcc 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/CLAUDE.md +204 -0
- package/.claude/agents/.gitkeep +0 -0
- package/.claude/settings.json +9 -0
- package/.claude/skills/.gitkeep +0 -0
- package/README.md +127 -0
- package/dist/accounts/instance-manager.d.ts +11 -0
- package/dist/accounts/instance-manager.d.ts.map +1 -0
- package/dist/accounts/instance-manager.js +89 -0
- package/dist/accounts/instance-manager.js.map +1 -0
- package/dist/accounts/shared-manager.d.ts +25 -0
- package/dist/accounts/shared-manager.d.ts.map +1 -0
- package/dist/accounts/shared-manager.js +186 -0
- package/dist/accounts/shared-manager.js.map +1 -0
- package/dist/accounts/store.d.ts +30 -0
- package/dist/accounts/store.d.ts.map +1 -0
- package/dist/accounts/store.js +128 -0
- package/dist/accounts/store.js.map +1 -0
- package/dist/core/model-router.d.ts +30 -0
- package/dist/core/model-router.d.ts.map +1 -0
- package/dist/core/model-router.js +64 -0
- package/dist/core/model-router.js.map +1 -0
- package/dist/dashboard-server.d.ts +5 -0
- package/dist/dashboard-server.d.ts.map +1 -0
- package/dist/dashboard-server.js +387 -0
- package/dist/dashboard-server.js.map +1 -0
- package/dist/mcc.d.ts +8 -0
- package/dist/mcc.d.ts.map +1 -0
- package/dist/mcc.js +474 -0
- package/dist/mcc.js.map +1 -0
- package/dist/mcp/external-registry.d.ts +24 -0
- package/dist/mcp/external-registry.d.ts.map +1 -0
- package/dist/mcp/external-registry.js +99 -0
- package/dist/mcp/external-registry.js.map +1 -0
- package/dist/mcp/installer.d.ts +31 -0
- package/dist/mcp/installer.d.ts.map +1 -0
- package/dist/mcp/installer.js +273 -0
- package/dist/mcp/installer.js.map +1 -0
- package/dist/mcp/mcp-config.d.ts +86 -0
- package/dist/mcp/mcp-config.d.ts.map +1 -0
- package/dist/mcp/mcp-config.js +178 -0
- package/dist/mcp/mcp-config.js.map +1 -0
- package/dist/mcp/registry.d.ts +23 -0
- package/dist/mcp/registry.d.ts.map +1 -0
- package/dist/mcp/registry.js +100 -0
- package/dist/mcp/registry.js.map +1 -0
- package/dist/proxy/proxy-daemon.d.ts +27 -0
- package/dist/proxy/proxy-daemon.d.ts.map +1 -0
- package/dist/proxy/proxy-daemon.js +192 -0
- package/dist/proxy/proxy-daemon.js.map +1 -0
- package/dist/proxy/proxy-entry.d.ts +11 -0
- package/dist/proxy/proxy-entry.d.ts.map +1 -0
- package/dist/proxy/proxy-entry.js +74 -0
- package/dist/proxy/proxy-entry.js.map +1 -0
- package/dist/proxy/proxy-paths.d.ts +27 -0
- package/dist/proxy/proxy-paths.d.ts.map +1 -0
- package/dist/proxy/proxy-paths.js +125 -0
- package/dist/proxy/proxy-paths.js.map +1 -0
- package/dist/proxy/proxy-server.d.ts +20 -0
- package/dist/proxy/proxy-server.d.ts.map +1 -0
- package/dist/proxy/proxy-server.js +280 -0
- package/dist/proxy/proxy-server.js.map +1 -0
- package/dist/proxy/upstream-url.d.ts +7 -0
- package/dist/proxy/upstream-url.d.ts.map +1 -0
- package/dist/proxy/upstream-url.js +38 -0
- package/dist/proxy/upstream-url.js.map +1 -0
- package/dist/shared/logger.d.ts +23 -0
- package/dist/shared/logger.d.ts.map +1 -0
- package/dist/shared/logger.js +184 -0
- package/dist/shared/logger.js.map +1 -0
- package/dist/shared/provider-preset-catalog.d.ts +41 -0
- package/dist/shared/provider-preset-catalog.d.ts.map +1 -0
- package/dist/shared/provider-preset-catalog.js +299 -0
- package/dist/shared/provider-preset-catalog.js.map +1 -0
- package/docs/decisions.md +33 -0
- package/docs/lessons.md +8 -0
- package/docs/product.md +37 -0
- package/lib/mcp/mcc-image-analysis-server.cjs +454 -0
- package/lib/mcp/mcc-websearch-server.cjs +339 -0
- package/lib/mcp-hooks/image-analysis-runtime.cjs +510 -0
- package/lib/mcp-hooks/image-analyzer-transformer.cjs +526 -0
- package/lib/mcp-hooks/websearch-transformer.cjs +1421 -0
- package/lib/proxy/config/config-loader-facade.js +24 -0
- package/lib/proxy/glmt/delta-accumulator.js +363 -0
- package/lib/proxy/glmt/glmt-transformer.js +204 -0
- package/lib/proxy/glmt/index.js +41 -0
- package/lib/proxy/glmt/locale-enforcer.js +69 -0
- package/lib/proxy/glmt/pipeline/content-transformer.js +162 -0
- package/lib/proxy/glmt/pipeline/index.js +20 -0
- package/lib/proxy/glmt/pipeline/request-transformer.js +116 -0
- package/lib/proxy/glmt/pipeline/response-builder.js +205 -0
- package/lib/proxy/glmt/pipeline/stream-parser.js +234 -0
- package/lib/proxy/glmt/pipeline/tool-call-handler.js +78 -0
- package/lib/proxy/glmt/pipeline/types.js +6 -0
- package/lib/proxy/glmt/reasoning-enforcer.js +151 -0
- package/lib/proxy/glmt/sse-parser.js +102 -0
- package/lib/proxy/services/logging.js +13 -0
- package/lib/proxy/transformers/request-transformer.js +452 -0
- package/lib/proxy/transformers/sse-stream-transformer.js +199 -0
- package/lib/shared/logger.cjs +138 -0
- package/package.json +35 -0
- package/src/accounts/instance-manager.ts +58 -0
- package/src/accounts/shared-manager.ts +154 -0
- package/src/accounts/store.ts +111 -0
- package/src/core/model-router.ts +82 -0
- package/src/dashboard-server.ts +407 -0
- package/src/mcc.ts +474 -0
- package/src/mcp/external-registry.ts +73 -0
- package/src/mcp/installer.ts +258 -0
- package/src/mcp/mcp-config.ts +168 -0
- package/src/mcp/registry.ts +89 -0
- package/src/proxy/proxy-daemon.ts +184 -0
- package/src/proxy/proxy-entry.ts +63 -0
- package/src/proxy/proxy-paths.ts +97 -0
- package/src/proxy/proxy-server.ts +278 -0
- package/src/proxy/upstream-url.ts +38 -0
- package/src/shared/logger.ts +140 -0
- package/src/shared/provider-preset-catalog.ts +340 -0
- package/tsconfig.json +33 -0
- package/ui/.prettierrc +9 -0
- package/ui/index.html +12 -0
- package/ui/package.json +33 -0
- package/ui/postcss.config.js +6 -0
- package/ui/src/App.tsx +753 -0
- package/ui/src/components/ui/button.tsx +48 -0
- package/ui/src/components/ui/card.tsx +50 -0
- package/ui/src/components/ui/input.tsx +21 -0
- package/ui/src/components/ui/label.tsx +20 -0
- package/ui/src/components/ui/select.tsx +80 -0
- package/ui/src/components/ui/switch.tsx +26 -0
- package/ui/src/components/ui/tabs.tsx +52 -0
- package/ui/src/index.css +33 -0
- package/ui/src/lib/api.ts +185 -0
- package/ui/src/lib/utils.ts +6 -0
- package/ui/src/main.tsx +10 -0
- package/ui/src/vite-env.d.ts +1 -0
- package/ui/tailwind.config.js +49 -0
- package/ui/tsconfig.json +25 -0
- package/ui/vite.config.ts +20 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* MCP Server Registry
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
+
}) : function(o, v) {
|
|
19
|
+
o["default"] = v;
|
|
20
|
+
});
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.BUILTIN_MCP_SERVERS = void 0;
|
|
40
|
+
exports.getBuiltinServerPath = getBuiltinServerPath;
|
|
41
|
+
exports.getServerByName = getServerByName;
|
|
42
|
+
exports.getAllServers = getAllServers;
|
|
43
|
+
const fs = __importStar(require("fs"));
|
|
44
|
+
const path = __importStar(require("path"));
|
|
45
|
+
function getMccHome() {
|
|
46
|
+
return process.env.MCC_HOME ?? path.join(process.env.HOME ?? process.env.USERPROFILE ?? '~', '.mcc');
|
|
47
|
+
}
|
|
48
|
+
exports.BUILTIN_MCP_SERVERS = [
|
|
49
|
+
{
|
|
50
|
+
name: 'mcc-websearch',
|
|
51
|
+
displayName: 'WebSearch',
|
|
52
|
+
description: 'Multi-provider web search (Exa, Tavily, Brave Search, DuckDuckGo).',
|
|
53
|
+
config: {
|
|
54
|
+
type: 'stdio',
|
|
55
|
+
command: 'node',
|
|
56
|
+
args: [path.join(getMccHome(), 'mcp', 'mcc-websearch-server.cjs')],
|
|
57
|
+
env: {},
|
|
58
|
+
builtin: true,
|
|
59
|
+
},
|
|
60
|
+
enabledByDefault: true,
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: 'mcc-image-analysis',
|
|
64
|
+
displayName: 'Image Analysis',
|
|
65
|
+
description: 'Image and PDF analysis via vision models.',
|
|
66
|
+
config: {
|
|
67
|
+
type: 'stdio',
|
|
68
|
+
command: 'node',
|
|
69
|
+
args: [path.join(getMccHome(), 'mcp', 'mcc-image-analysis-server.cjs')],
|
|
70
|
+
env: {},
|
|
71
|
+
builtin: true,
|
|
72
|
+
},
|
|
73
|
+
enabledByDefault: true,
|
|
74
|
+
},
|
|
75
|
+
];
|
|
76
|
+
function getBuiltinServerPath(serverName) {
|
|
77
|
+
const libDir = path.join(__dirname, '..', '..', 'lib', 'mcp');
|
|
78
|
+
const fileName = serverName === 'mcc-websearch'
|
|
79
|
+
? 'mcc-websearch-server.cjs'
|
|
80
|
+
: serverName === 'mcc-image-analysis'
|
|
81
|
+
? 'mcc-image-analysis-server.cjs'
|
|
82
|
+
: null;
|
|
83
|
+
if (!fileName)
|
|
84
|
+
return null;
|
|
85
|
+
const candidate = path.join(libDir, fileName);
|
|
86
|
+
return fs.existsSync(candidate) ? candidate : null;
|
|
87
|
+
}
|
|
88
|
+
function getServerByName(name) {
|
|
89
|
+
const builtin = exports.BUILTIN_MCP_SERVERS.find((s) => s.name === name);
|
|
90
|
+
if (builtin)
|
|
91
|
+
return builtin;
|
|
92
|
+
// Avoid circular import at module level — require at runtime
|
|
93
|
+
const { readExternalMcpRegistry } = require('./external-registry');
|
|
94
|
+
return readExternalMcpRegistry().find((s) => s.name === name);
|
|
95
|
+
}
|
|
96
|
+
function getAllServers() {
|
|
97
|
+
const { readExternalMcpRegistry } = require('./external-registry');
|
|
98
|
+
return [...exports.BUILTIN_MCP_SERVERS, ...readExternalMcpRegistry()];
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/mcp/registry.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwDH,oDAWC;AAED,0CAUC;AAED,sCAKC;AApFD,uCAAyB;AACzB,2CAA6B;AAmB7B,SAAS,UAAU;IACjB,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,GAAG,EAAE,MAAM,CAAC,CAAC;AACvG,CAAC;AAEY,QAAA,mBAAmB,GAAgC;IAC9D;QACE,IAAI,EAAE,eAAe;QACrB,WAAW,EAAE,WAAW;QACxB,WAAW,EACT,oEAAoE;QACtE,MAAM,EAAE;YACN,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,MAAM;YACf,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,0BAA0B,CAAC,CAAC;YAClE,GAAG,EAAE,EAAE;YACP,OAAO,EAAE,IAAI;SACd;QACD,gBAAgB,EAAE,IAAI;KACvB;IACD;QACE,IAAI,EAAE,oBAAoB;QAC1B,WAAW,EAAE,gBAAgB;QAC7B,WAAW,EAAE,2CAA2C;QACxD,MAAM,EAAE;YACN,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,MAAM;YACf,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,+BAA+B,CAAC,CAAC;YACvE,GAAG,EAAE,EAAE;YACP,OAAO,EAAE,IAAI;SACd;QACD,gBAAgB,EAAE,IAAI;KACvB;CACF,CAAC;AAEF,SAAgB,oBAAoB,CAAC,UAAkB;IACrD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAC9D,MAAM,QAAQ,GACZ,UAAU,KAAK,eAAe;QAC5B,CAAC,CAAC,0BAA0B;QAC5B,CAAC,CAAC,UAAU,KAAK,oBAAoB;YACnC,CAAC,CAAC,+BAA+B;YACjC,CAAC,CAAC,IAAI,CAAC;IACb,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC9C,OAAO,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;AACrD,CAAC;AAED,SAAgB,eAAe,CAC7B,IAAY;IAEZ,MAAM,OAAO,GAAG,2BAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IACjE,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAC5B,6DAA6D;IAC7D,MAAM,EAAE,uBAAuB,EAAE,GAAG,OAAO,CAAC,qBAAqB,CAEhE,CAAC;IACF,OAAO,uBAAuB,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AAChE,CAAC;AAED,SAAgB,aAAa;IAC3B,MAAM,EAAE,uBAAuB,EAAE,GAAG,OAAO,CAAC,qBAAqB,CAEhE,CAAC;IACF,OAAO,CAAC,GAAG,2BAAmB,EAAE,GAAG,uBAAuB,EAAE,CAAC,CAAC;AAChE,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Proxy Daemon - Lifecycle management for the translation proxy
|
|
3
|
+
*
|
|
4
|
+
* Manages starting/stopping the proxy as a detached child process.
|
|
5
|
+
* Ported from CCS proxy/proxy-daemon.js (simplified for single-profile MCC).
|
|
6
|
+
*/
|
|
7
|
+
export interface ProxyStartResult {
|
|
8
|
+
port: number;
|
|
9
|
+
authToken: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Start the translation proxy for a profile.
|
|
13
|
+
* If a proxy is already running for this profile, returns its existing session.
|
|
14
|
+
*/
|
|
15
|
+
export declare function startProxy(profileName: string, baseUrl: string, apiKey: string, model?: string): Promise<ProxyStartResult>;
|
|
16
|
+
/**
|
|
17
|
+
* Stop the translation proxy for a profile.
|
|
18
|
+
*/
|
|
19
|
+
export declare function stopProxy(profileName: string): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Check if a proxy is running for a profile.
|
|
22
|
+
*/
|
|
23
|
+
export declare function getProxyStatus(profileName: string): Promise<{
|
|
24
|
+
running: boolean;
|
|
25
|
+
port?: number;
|
|
26
|
+
}>;
|
|
27
|
+
//# sourceMappingURL=proxy-daemon.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy-daemon.d.ts","sourceRoot":"","sources":["../../src/proxy/proxy-daemon.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAuEH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,gBAAgB,CAAC,CAuE3B;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAOlE;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAKtG"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Proxy Daemon - Lifecycle management for the translation proxy
|
|
4
|
+
*
|
|
5
|
+
* Manages starting/stopping the proxy as a detached child process.
|
|
6
|
+
* Ported from CCS proxy/proxy-daemon.js (simplified for single-profile MCC).
|
|
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.startProxy = startProxy;
|
|
43
|
+
exports.stopProxy = stopProxy;
|
|
44
|
+
exports.getProxyStatus = getProxyStatus;
|
|
45
|
+
const crypto = __importStar(require("crypto"));
|
|
46
|
+
const http = __importStar(require("http"));
|
|
47
|
+
const child_process_1 = require("child_process");
|
|
48
|
+
const path = __importStar(require("path"));
|
|
49
|
+
const proxy_paths_1 = require("./proxy-paths");
|
|
50
|
+
const PROXY_ENTRY_CANDIDATES = [
|
|
51
|
+
path.join(__dirname, 'proxy-entry.js'),
|
|
52
|
+
path.join(__dirname, 'proxy-entry.cjs'),
|
|
53
|
+
];
|
|
54
|
+
function generateAuthToken() {
|
|
55
|
+
return crypto.randomBytes(24).toString('hex');
|
|
56
|
+
}
|
|
57
|
+
async function isProxyRunning(port) {
|
|
58
|
+
return new Promise((resolve) => {
|
|
59
|
+
const req = http.request({ hostname: '127.0.0.1', port, path: '/health', method: 'GET', timeout: 3000 }, (res) => {
|
|
60
|
+
let body = '';
|
|
61
|
+
res.setEncoding('utf8');
|
|
62
|
+
res.on('data', (chunk) => (body += chunk));
|
|
63
|
+
res.on('end', () => {
|
|
64
|
+
if (res.statusCode !== 200) {
|
|
65
|
+
resolve(false);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
const payload = JSON.parse(body);
|
|
70
|
+
resolve(payload.service === proxy_paths_1.PROXY_SERVICE_NAME);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
resolve(false);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
req.on('error', () => resolve(false));
|
|
78
|
+
req.on('timeout', () => { req.destroy(); resolve(false); });
|
|
79
|
+
req.end();
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
async function terminateProcess(pid) {
|
|
83
|
+
try {
|
|
84
|
+
process.kill(pid, 'SIGTERM');
|
|
85
|
+
let attempts = 0;
|
|
86
|
+
while (attempts < 10) {
|
|
87
|
+
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
88
|
+
try {
|
|
89
|
+
process.kill(pid, 0);
|
|
90
|
+
attempts++;
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return; // Process exited
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
process.kill(pid, 'SIGKILL');
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// Best-effort
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Start the translation proxy for a profile.
|
|
104
|
+
* If a proxy is already running for this profile, returns its existing session.
|
|
105
|
+
*/
|
|
106
|
+
async function startProxy(profileName, baseUrl, apiKey, model) {
|
|
107
|
+
// Check if already running
|
|
108
|
+
const existingSession = (0, proxy_paths_1.readProxySession)(profileName);
|
|
109
|
+
if (existingSession && await isProxyRunning(existingSession.port)) {
|
|
110
|
+
return { port: existingSession.port, authToken: existingSession.authToken };
|
|
111
|
+
}
|
|
112
|
+
// Clean up stale state
|
|
113
|
+
stopProxy(profileName).catch(() => { });
|
|
114
|
+
const port = (0, proxy_paths_1.resolveAdaptivePort)(profileName);
|
|
115
|
+
const authToken = generateAuthToken();
|
|
116
|
+
// Find the entry script
|
|
117
|
+
let entryScript = null;
|
|
118
|
+
for (const candidate of PROXY_ENTRY_CANDIDATES) {
|
|
119
|
+
try {
|
|
120
|
+
const fs = await Promise.resolve().then(() => __importStar(require('fs')));
|
|
121
|
+
fs.accessSync(candidate, fs.constants.R_OK);
|
|
122
|
+
entryScript = candidate;
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
// Try next
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (!entryScript) {
|
|
130
|
+
throw new Error('Proxy entry script not found. Run: npm run build');
|
|
131
|
+
}
|
|
132
|
+
// Spawn the proxy as a detached child process
|
|
133
|
+
const child = (0, child_process_1.spawn)(process.execPath, [
|
|
134
|
+
entryScript,
|
|
135
|
+
'--port', String(port),
|
|
136
|
+
'--host', '127.0.0.1',
|
|
137
|
+
'--base-url', baseUrl,
|
|
138
|
+
'--api-key', apiKey,
|
|
139
|
+
'--auth-token', authToken,
|
|
140
|
+
...(model ? ['--model', model] : []),
|
|
141
|
+
], {
|
|
142
|
+
detached: true,
|
|
143
|
+
stdio: 'ignore',
|
|
144
|
+
env: { ...process.env },
|
|
145
|
+
});
|
|
146
|
+
child.unref();
|
|
147
|
+
const pid = child.pid;
|
|
148
|
+
if (!pid) {
|
|
149
|
+
throw new Error('Failed to spawn proxy process');
|
|
150
|
+
}
|
|
151
|
+
// Write PID and session files
|
|
152
|
+
(0, proxy_paths_1.writeProxyPid)(profileName, pid);
|
|
153
|
+
const session = {
|
|
154
|
+
profileName,
|
|
155
|
+
port,
|
|
156
|
+
host: '127.0.0.1',
|
|
157
|
+
authToken,
|
|
158
|
+
baseUrl,
|
|
159
|
+
startedAt: new Date().toISOString(),
|
|
160
|
+
};
|
|
161
|
+
(0, proxy_paths_1.writeProxySession)(session);
|
|
162
|
+
// Wait for the proxy to be ready (up to 5 seconds)
|
|
163
|
+
for (let i = 0; i < 25; i++) {
|
|
164
|
+
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
165
|
+
if (await isProxyRunning(port)) {
|
|
166
|
+
return { port, authToken };
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
throw new Error(`Proxy failed to start within 5 seconds (PID: ${pid}, port: ${port})`);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Stop the translation proxy for a profile.
|
|
173
|
+
*/
|
|
174
|
+
async function stopProxy(profileName) {
|
|
175
|
+
const pid = (0, proxy_paths_1.readProxyPid)(profileName);
|
|
176
|
+
if (pid) {
|
|
177
|
+
await terminateProcess(pid);
|
|
178
|
+
}
|
|
179
|
+
(0, proxy_paths_1.removeProxyPid)(profileName);
|
|
180
|
+
(0, proxy_paths_1.removeProxySession)(profileName);
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Check if a proxy is running for a profile.
|
|
184
|
+
*/
|
|
185
|
+
async function getProxyStatus(profileName) {
|
|
186
|
+
const session = (0, proxy_paths_1.readProxySession)(profileName);
|
|
187
|
+
if (!session)
|
|
188
|
+
return { running: false };
|
|
189
|
+
const running = await isProxyRunning(session.port);
|
|
190
|
+
return { running, port: running ? session.port : undefined };
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=proxy-daemon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy-daemon.js","sourceRoot":"","sources":["../../src/proxy/proxy-daemon.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgFH,gCA4EC;AAKD,8BAOC;AAKD,wCAKC;AAhLD,+CAAiC;AACjC,2CAA6B;AAC7B,iDAAsC;AACtC,2CAA6B;AAC7B,+CAUuB;AAEvB,MAAM,sBAAsB,GAAG;IAC7B,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC;IACtC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC;CACxC,CAAC;AAEF,SAAS,iBAAiB;IACxB,OAAO,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAChD,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,IAAY;IACxC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CACtB,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,EAC9E,CAAC,GAAG,EAAE,EAAE;YACN,IAAI,IAAI,GAAG,EAAE,CAAC;YACd,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;YACxB,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC;YAC3C,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;gBACjB,IAAI,GAAG,CAAC,UAAU,KAAK,GAAG,EAAE,CAAC;oBAAC,OAAO,CAAC,KAAK,CAAC,CAAC;oBAAC,OAAO;gBAAC,CAAC;gBACvD,IAAI,CAAC;oBACH,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBACjC,OAAO,CAAC,OAAO,CAAC,OAAO,KAAK,gCAAkB,CAAC,CAAC;gBAClD,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,CAAC,KAAK,CAAC,CAAC;gBACjB,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CACF,CAAC;QACF,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QACtC,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5D,GAAG,CAAC,GAAG,EAAE,CAAC;IACZ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,gBAAgB,CAAC,GAAW;IACzC,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC7B,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,OAAO,QAAQ,GAAG,EAAE,EAAE,CAAC;YACrB,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;YACzD,IAAI,CAAC;gBACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;gBACrB,QAAQ,EAAE,CAAC;YACb,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,CAAC,iBAAiB;YAC3B,CAAC;QACH,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,cAAc;IAChB,CAAC;AACH,CAAC;AAOD;;;GAGG;AACI,KAAK,UAAU,UAAU,CAC9B,WAAmB,EACnB,OAAe,EACf,MAAc,EACd,KAAc;IAEd,2BAA2B;IAC3B,MAAM,eAAe,GAAG,IAAA,8BAAgB,EAAC,WAAW,CAAC,CAAC;IACtD,IAAI,eAAe,IAAI,MAAM,cAAc,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;QAClE,OAAO,EAAE,IAAI,EAAE,eAAe,CAAC,IAAI,EAAE,SAAS,EAAE,eAAe,CAAC,SAAS,EAAE,CAAC;IAC9E,CAAC;IAED,uBAAuB;IACvB,SAAS,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAEvC,MAAM,IAAI,GAAG,IAAA,iCAAmB,EAAC,WAAW,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,iBAAiB,EAAE,CAAC;IAEtC,wBAAwB;IACxB,IAAI,WAAW,GAAkB,IAAI,CAAC;IACtC,KAAK,MAAM,SAAS,IAAI,sBAAsB,EAAE,CAAC;QAC/C,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,wDAAa,IAAI,GAAC,CAAC;YAC9B,EAAE,CAAC,UAAU,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAC5C,WAAW,GAAG,SAAS,CAAC;YACxB,MAAM;QACR,CAAC;QAAC,MAAM,CAAC;YACP,WAAW;QACb,CAAC;IACH,CAAC;IACD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACtE,CAAC;IAED,8CAA8C;IAC9C,MAAM,KAAK,GAAG,IAAA,qBAAK,EAAC,OAAO,CAAC,QAAQ,EAAE;QACpC,WAAW;QACX,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC;QACtB,QAAQ,EAAE,WAAW;QACrB,YAAY,EAAE,OAAO;QACrB,WAAW,EAAE,MAAM;QACnB,cAAc,EAAE,SAAS;QACzB,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;KACrC,EAAE;QACD,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,QAAQ;QACf,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE;KACxB,CAAC,CAAC;IACH,KAAK,CAAC,KAAK,EAAE,CAAC;IAEd,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;IACtB,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnD,CAAC;IAED,8BAA8B;IAC9B,IAAA,2BAAa,EAAC,WAAW,EAAE,GAAG,CAAC,CAAC;IAChC,MAAM,OAAO,GAAiB;QAC5B,WAAW;QACX,IAAI;QACJ,IAAI,EAAE,WAAW;QACjB,SAAS;QACT,OAAO;QACP,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC;IACF,IAAA,+BAAiB,EAAC,OAAO,CAAC,CAAC;IAE3B,mDAAmD;IACnD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;QACzD,IAAI,MAAM,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,gDAAgD,GAAG,WAAW,IAAI,GAAG,CAAC,CAAC;AACzF,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,SAAS,CAAC,WAAmB;IACjD,MAAM,GAAG,GAAG,IAAA,0BAAY,EAAC,WAAW,CAAC,CAAC;IACtC,IAAI,GAAG,EAAE,CAAC;QACR,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IACD,IAAA,4BAAc,EAAC,WAAW,CAAC,CAAC;IAC5B,IAAA,gCAAkB,EAAC,WAAW,CAAC,CAAC;AAClC,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,cAAc,CAAC,WAAmB;IACtD,MAAM,OAAO,GAAG,IAAA,8BAAgB,EAAC,WAAW,CAAC,CAAC;IAC9C,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IACxC,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;AAC/D,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Proxy Daemon Entrypoint
|
|
4
|
+
*
|
|
5
|
+
* This file is spawned as a detached child process by proxy-daemon.ts.
|
|
6
|
+
* It parses CLI args and starts the proxy server.
|
|
7
|
+
*
|
|
8
|
+
* Ported from CCS proxy/proxy-daemon-entry.js (simplified for single-profile MCC).
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=proxy-entry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy-entry.d.ts","sourceRoot":"","sources":["../../src/proxy/proxy-entry.ts"],"names":[],"mappings":";AACA;;;;;;;GAOG"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* Proxy Daemon Entrypoint
|
|
5
|
+
*
|
|
6
|
+
* This file is spawned as a detached child process by proxy-daemon.ts.
|
|
7
|
+
* It parses CLI args and starts the proxy server.
|
|
8
|
+
*
|
|
9
|
+
* Ported from CCS proxy/proxy-daemon-entry.js (simplified for single-profile MCC).
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const proxy_server_1 = require("./proxy-server");
|
|
13
|
+
function parseArgs(argv) {
|
|
14
|
+
let port = 43456;
|
|
15
|
+
let host = '127.0.0.1';
|
|
16
|
+
let baseUrl = '';
|
|
17
|
+
let apiKey = '';
|
|
18
|
+
let model = '';
|
|
19
|
+
let authToken = '';
|
|
20
|
+
for (let i = 0; i < argv.length; i++) {
|
|
21
|
+
const arg = argv[i];
|
|
22
|
+
if (arg === '--port' && argv[i + 1]) {
|
|
23
|
+
port = Number.parseInt(argv[++i] || '', 10) || port;
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
if (arg === '--host' && argv[i + 1]) {
|
|
27
|
+
host = argv[++i] || host;
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
if (arg === '--base-url' && argv[i + 1]) {
|
|
31
|
+
baseUrl = argv[++i] || '';
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (arg === '--api-key' && argv[i + 1]) {
|
|
35
|
+
apiKey = argv[++i] || '';
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (arg === '--model' && argv[i + 1]) {
|
|
39
|
+
model = argv[++i] || '';
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if (arg === '--auth-token' && argv[i + 1]) {
|
|
43
|
+
authToken = argv[++i] || '';
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (!authToken.trim()) {
|
|
48
|
+
throw new Error('Missing local proxy auth token');
|
|
49
|
+
}
|
|
50
|
+
if (!baseUrl.trim()) {
|
|
51
|
+
throw new Error('Missing upstream base URL');
|
|
52
|
+
}
|
|
53
|
+
if (!apiKey.trim()) {
|
|
54
|
+
throw new Error('Missing upstream API key');
|
|
55
|
+
}
|
|
56
|
+
return { port, host, baseUrl, apiKey, model: model || undefined, authToken };
|
|
57
|
+
}
|
|
58
|
+
function main() {
|
|
59
|
+
const options = parseArgs(process.argv.slice(2));
|
|
60
|
+
const server = (0, proxy_server_1.startProxyServer)(options);
|
|
61
|
+
server.once('error', (error) => {
|
|
62
|
+
console.error(`[MCC Proxy] Server error: ${error.message}`);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
});
|
|
65
|
+
console.log(`[MCC Proxy] Listening on http://${options.host}:${options.port}`);
|
|
66
|
+
const shutdown = () => {
|
|
67
|
+
console.log('[MCC Proxy] Shutting down...');
|
|
68
|
+
server.close();
|
|
69
|
+
};
|
|
70
|
+
process.on('SIGTERM', shutdown);
|
|
71
|
+
process.on('SIGINT', shutdown);
|
|
72
|
+
}
|
|
73
|
+
main();
|
|
74
|
+
//# sourceMappingURL=proxy-entry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy-entry.js","sourceRoot":"","sources":["../../src/proxy/proxy-entry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Proxy path constants and session/PID file management
|
|
3
|
+
* Ported from CCS proxy-daemon-paths.js + proxy-daemon-state.js
|
|
4
|
+
*/
|
|
5
|
+
export declare const PROXY_PORT_START = 43456;
|
|
6
|
+
export declare const PROXY_PORT_END = 43555;
|
|
7
|
+
export declare const PROXY_SERVICE_NAME = "mcc-openai-compat-proxy";
|
|
8
|
+
export declare function getProxyDir(): string;
|
|
9
|
+
export declare function getProxyPidPath(profileName: string): string;
|
|
10
|
+
export declare function getProxySessionPath(profileName: string): string;
|
|
11
|
+
export interface ProxySession {
|
|
12
|
+
profileName: string;
|
|
13
|
+
port: number;
|
|
14
|
+
host: string;
|
|
15
|
+
authToken: string;
|
|
16
|
+
baseUrl: string;
|
|
17
|
+
startedAt: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function readProxyPid(profileName: string): number | null;
|
|
20
|
+
export declare function writeProxyPid(profileName: string, pid: number): void;
|
|
21
|
+
export declare function removeProxyPid(profileName: string): void;
|
|
22
|
+
export declare function readProxySession(profileName: string): ProxySession | null;
|
|
23
|
+
export declare function writeProxySession(session: ProxySession): void;
|
|
24
|
+
export declare function removeProxySession(profileName: string): void;
|
|
25
|
+
export declare function hashProfileName(profileName: string): number;
|
|
26
|
+
export declare function resolveAdaptivePort(profileName: string): number;
|
|
27
|
+
//# sourceMappingURL=proxy-paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy-paths.d.ts","sourceRoot":"","sources":["../../src/proxy/proxy-paths.ts"],"names":[],"mappings":"AAAA;;;GAGG;AASH,eAAO,MAAM,gBAAgB,QAAQ,CAAC;AACtC,eAAO,MAAM,cAAc,QAAQ,CAAC;AACpC,eAAO,MAAM,kBAAkB,4BAA4B,CAAC;AAE5D,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ/D;AAED,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAGpE;AAED,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAMxD;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAMzE;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAG7D;AAED,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAM5D;AAED,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAM3D;AAED,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAG/D"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Proxy path constants and session/PID file management
|
|
4
|
+
* Ported from CCS proxy-daemon-paths.js + proxy-daemon-state.js
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.PROXY_SERVICE_NAME = exports.PROXY_PORT_END = exports.PROXY_PORT_START = void 0;
|
|
41
|
+
exports.getProxyDir = getProxyDir;
|
|
42
|
+
exports.getProxyPidPath = getProxyPidPath;
|
|
43
|
+
exports.getProxySessionPath = getProxySessionPath;
|
|
44
|
+
exports.readProxyPid = readProxyPid;
|
|
45
|
+
exports.writeProxyPid = writeProxyPid;
|
|
46
|
+
exports.removeProxyPid = removeProxyPid;
|
|
47
|
+
exports.readProxySession = readProxySession;
|
|
48
|
+
exports.writeProxySession = writeProxySession;
|
|
49
|
+
exports.removeProxySession = removeProxySession;
|
|
50
|
+
exports.hashProfileName = hashProfileName;
|
|
51
|
+
exports.resolveAdaptivePort = resolveAdaptivePort;
|
|
52
|
+
const fs = __importStar(require("fs"));
|
|
53
|
+
const path = __importStar(require("path"));
|
|
54
|
+
function getMccHome() {
|
|
55
|
+
return process.env.MCC_HOME ?? path.join(process.env.HOME ?? process.env.USERPROFILE ?? '~', '.mcc');
|
|
56
|
+
}
|
|
57
|
+
exports.PROXY_PORT_START = 43456;
|
|
58
|
+
exports.PROXY_PORT_END = 43555;
|
|
59
|
+
exports.PROXY_SERVICE_NAME = 'mcc-openai-compat-proxy';
|
|
60
|
+
function getProxyDir() {
|
|
61
|
+
return path.join(getMccHome(), 'proxy');
|
|
62
|
+
}
|
|
63
|
+
function getProxyPidPath(profileName) {
|
|
64
|
+
return path.join(getProxyDir(), `${encodeURIComponent(profileName)}.daemon.pid`);
|
|
65
|
+
}
|
|
66
|
+
function getProxySessionPath(profileName) {
|
|
67
|
+
return path.join(getProxyDir(), `${encodeURIComponent(profileName)}.session.json`);
|
|
68
|
+
}
|
|
69
|
+
function ensureProxyDir() {
|
|
70
|
+
fs.mkdirSync(getProxyDir(), { recursive: true, mode: 0o700 });
|
|
71
|
+
}
|
|
72
|
+
function readProxyPid(profileName) {
|
|
73
|
+
try {
|
|
74
|
+
const raw = fs.readFileSync(getProxyPidPath(profileName), 'utf8').trim();
|
|
75
|
+
const pid = Number.parseInt(raw, 10);
|
|
76
|
+
return Number.isInteger(pid) ? pid : null;
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function writeProxyPid(profileName, pid) {
|
|
83
|
+
ensureProxyDir();
|
|
84
|
+
fs.writeFileSync(getProxyPidPath(profileName), String(pid), 'utf8');
|
|
85
|
+
}
|
|
86
|
+
function removeProxyPid(profileName) {
|
|
87
|
+
try {
|
|
88
|
+
fs.unlinkSync(getProxyPidPath(profileName));
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
// Best-effort cleanup
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function readProxySession(profileName) {
|
|
95
|
+
try {
|
|
96
|
+
return JSON.parse(fs.readFileSync(getProxySessionPath(profileName), 'utf8'));
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function writeProxySession(session) {
|
|
103
|
+
ensureProxyDir();
|
|
104
|
+
fs.writeFileSync(getProxySessionPath(session.profileName), JSON.stringify(session, null, 2) + '\n', 'utf8');
|
|
105
|
+
}
|
|
106
|
+
function removeProxySession(profileName) {
|
|
107
|
+
try {
|
|
108
|
+
fs.unlinkSync(getProxySessionPath(profileName));
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
// Best-effort cleanup
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function hashProfileName(profileName) {
|
|
115
|
+
let hash = 0;
|
|
116
|
+
for (const char of profileName.trim()) {
|
|
117
|
+
hash = (hash * 31 + char.charCodeAt(0)) >>> 0;
|
|
118
|
+
}
|
|
119
|
+
return hash;
|
|
120
|
+
}
|
|
121
|
+
function resolveAdaptivePort(profileName) {
|
|
122
|
+
const rangeSize = exports.PROXY_PORT_END - exports.PROXY_PORT_START + 1;
|
|
123
|
+
return exports.PROXY_PORT_START + (hashProfileName(profileName) % rangeSize);
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=proxy-paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy-paths.js","sourceRoot":"","sources":["../../src/proxy/proxy-paths.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAaH,kCAEC;AAED,0CAEC;AAED,kDAEC;AAeD,oCAQC;AAED,sCAGC;AAED,wCAMC;AAED,4CAMC;AAED,8CAGC;AAED,gDAMC;AAED,0CAMC;AAED,kDAGC;AA3FD,uCAAyB;AACzB,2CAA6B;AAE7B,SAAS,UAAU;IACjB,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,GAAG,EAAE,MAAM,CAAC,CAAC;AACvG,CAAC;AAEY,QAAA,gBAAgB,GAAG,KAAK,CAAC;AACzB,QAAA,cAAc,GAAG,KAAK,CAAC;AACvB,QAAA,kBAAkB,GAAG,yBAAyB,CAAC;AAE5D,SAAgB,WAAW;IACzB,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,OAAO,CAAC,CAAC;AAC1C,CAAC;AAED,SAAgB,eAAe,CAAC,WAAmB;IACjD,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,GAAG,kBAAkB,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;AACnF,CAAC;AAED,SAAgB,mBAAmB,CAAC,WAAmB;IACrD,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,GAAG,kBAAkB,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC;AACrF,CAAC;AAWD,SAAS,cAAc;IACrB,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAChE,CAAC;AAED,SAAgB,YAAY,CAAC,WAAmB;IAC9C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,eAAe,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QACzE,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACrC,OAAO,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAgB,aAAa,CAAC,WAAmB,EAAE,GAAW;IAC5D,cAAc,EAAE,CAAC;IACjB,EAAE,CAAC,aAAa,CAAC,eAAe,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;AACtE,CAAC;AAED,SAAgB,cAAc,CAAC,WAAmB;IAChD,IAAI,CAAC;QACH,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,sBAAsB;IACxB,CAAC;AACH,CAAC;AAED,SAAgB,gBAAgB,CAAC,WAAmB;IAClD,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,mBAAmB,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IAC/E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAgB,iBAAiB,CAAC,OAAqB;IACrD,cAAc,EAAE,CAAC;IACjB,EAAE,CAAC,aAAa,CAAC,mBAAmB,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;AAC9G,CAAC;AAED,SAAgB,kBAAkB,CAAC,WAAmB;IACpD,IAAI,CAAC;QACH,EAAE,CAAC,UAAU,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAC,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,sBAAsB;IACxB,CAAC;AACH,CAAC;AAED,SAAgB,eAAe,CAAC,WAAmB;IACjD,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,IAAI,EAAE,EAAE,CAAC;QACtC,IAAI,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAChD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAgB,mBAAmB,CAAC,WAAmB;IACrD,MAAM,SAAS,GAAG,sBAAc,GAAG,wBAAgB,GAAG,CAAC,CAAC;IACxD,OAAO,wBAAgB,GAAG,CAAC,eAAe,CAAC,WAAW,CAAC,GAAG,SAAS,CAAC,CAAC;AACvE,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Proxy Server - Simplified translation proxy for MCC
|
|
3
|
+
*
|
|
4
|
+
* Accepts Anthropic /v1/messages requests, translates to OpenAI chat/completions,
|
|
5
|
+
* forwards to upstream provider, translates response back.
|
|
6
|
+
*
|
|
7
|
+
* Ported from CCS proxy/server/proxy-server.js + messages-route.js + http-helpers.js
|
|
8
|
+
* Simplified: single-profile, no multi-profile routing, no CCS logging, native fetch.
|
|
9
|
+
*/
|
|
10
|
+
import * as http from 'http';
|
|
11
|
+
export interface ProxyServerOptions {
|
|
12
|
+
host: string;
|
|
13
|
+
port: number;
|
|
14
|
+
authToken: string;
|
|
15
|
+
baseUrl: string;
|
|
16
|
+
apiKey: string;
|
|
17
|
+
model?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function startProxyServer(options: ProxyServerOptions): http.Server;
|
|
20
|
+
//# sourceMappingURL=proxy-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy-server.d.ts","sourceRoot":"","sources":["../../src/proxy/proxy-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAe7B,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA8FD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAAC,MAAM,CAqBzE"}
|