@kaitranntt/ccs 4.4.0 → 5.0.1
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 +98 -7
- package/VERSION +1 -1
- package/config/base-agy.settings.json +10 -0
- package/config/base-codex.settings.json +10 -0
- package/config/base-gemini.settings.json +10 -0
- package/dist/auth/auth-commands.d.ts +52 -0
- package/dist/auth/auth-commands.d.ts.map +1 -0
- package/dist/auth/auth-commands.js +479 -0
- package/dist/auth/auth-commands.js.map +1 -0
- package/dist/auth/profile-detector.d.ts +68 -0
- package/dist/auth/profile-detector.d.ts.map +1 -0
- package/dist/auth/profile-detector.js +209 -0
- package/dist/auth/profile-detector.js.map +1 -0
- package/dist/auth/profile-registry.d.ts +60 -0
- package/dist/auth/profile-registry.d.ts.map +1 -0
- package/dist/auth/profile-registry.js +188 -0
- package/dist/auth/profile-registry.js.map +1 -0
- package/dist/ccs.d.ts +10 -0
- package/dist/ccs.d.ts.map +1 -0
- package/dist/ccs.js +320 -0
- package/dist/ccs.js.map +1 -0
- package/dist/cliproxy/auth-handler.d.ts +95 -0
- package/dist/cliproxy/auth-handler.d.ts.map +1 -0
- package/dist/cliproxy/auth-handler.js +443 -0
- package/dist/cliproxy/auth-handler.js.map +1 -0
- package/dist/cliproxy/base-config-loader.d.ts +42 -0
- package/dist/cliproxy/base-config-loader.d.ts.map +1 -0
- package/dist/cliproxy/base-config-loader.js +123 -0
- package/dist/cliproxy/base-config-loader.js.map +1 -0
- package/dist/cliproxy/binary-manager.d.ts +104 -0
- package/dist/cliproxy/binary-manager.d.ts.map +1 -0
- package/dist/cliproxy/binary-manager.js +567 -0
- package/dist/cliproxy/binary-manager.js.map +1 -0
- package/dist/cliproxy/cliproxy-executor.d.ts +33 -0
- package/dist/cliproxy/cliproxy-executor.d.ts.map +1 -0
- package/dist/cliproxy/cliproxy-executor.js +297 -0
- package/dist/cliproxy/cliproxy-executor.js.map +1 -0
- package/dist/cliproxy/config-generator.d.ts +89 -0
- package/dist/cliproxy/config-generator.d.ts.map +1 -0
- package/dist/cliproxy/config-generator.js +263 -0
- package/dist/cliproxy/config-generator.js.map +1 -0
- package/dist/cliproxy/index.d.ts +13 -0
- package/dist/cliproxy/index.d.ts.map +1 -0
- package/dist/cliproxy/index.js +62 -0
- package/dist/cliproxy/index.js.map +1 -0
- package/dist/cliproxy/platform-detector.d.ts +48 -0
- package/dist/cliproxy/platform-detector.d.ts.map +1 -0
- package/dist/cliproxy/platform-detector.js +118 -0
- package/dist/cliproxy/platform-detector.js.map +1 -0
- package/dist/cliproxy/types.d.ts +169 -0
- package/dist/cliproxy/types.d.ts.map +1 -0
- package/dist/cliproxy/types.js +7 -0
- package/dist/cliproxy/types.js.map +1 -0
- package/dist/commands/doctor-command.d.ts +10 -0
- package/dist/commands/doctor-command.d.ts.map +1 -0
- package/dist/commands/doctor-command.js +44 -0
- package/dist/commands/doctor-command.js.map +1 -0
- package/dist/commands/help-command.d.ts +5 -0
- package/dist/commands/help-command.d.ts.map +1 -0
- package/dist/commands/help-command.js +104 -0
- package/dist/commands/help-command.js.map +1 -0
- package/dist/commands/install-command.d.ts +14 -0
- package/dist/commands/install-command.d.ts.map +1 -0
- package/dist/commands/install-command.js +39 -0
- package/dist/commands/install-command.js.map +1 -0
- package/dist/commands/shell-completion-command.d.ts +10 -0
- package/dist/commands/shell-completion-command.d.ts.map +1 -0
- package/dist/commands/shell-completion-command.js +85 -0
- package/dist/commands/shell-completion-command.js.map +1 -0
- package/dist/commands/sync-command.d.ts +10 -0
- package/dist/commands/sync-command.d.ts.map +1 -0
- package/dist/commands/sync-command.js +59 -0
- package/dist/commands/sync-command.js.map +1 -0
- package/dist/commands/update-command.d.ts +12 -0
- package/dist/commands/update-command.d.ts.map +1 -0
- package/dist/commands/update-command.js +295 -0
- package/dist/commands/update-command.js.map +1 -0
- package/dist/commands/version-command.d.ts +10 -0
- package/dist/commands/version-command.d.ts.map +1 -0
- package/dist/commands/version-command.js +100 -0
- package/dist/commands/version-command.js.map +1 -0
- package/dist/delegation/delegation-handler.d.ts +60 -0
- package/dist/delegation/delegation-handler.d.ts.map +1 -0
- package/dist/delegation/delegation-handler.js +174 -0
- package/dist/delegation/delegation-handler.js.map +1 -0
- package/dist/delegation/headless-executor.d.ts +114 -0
- package/dist/delegation/headless-executor.d.ts.map +1 -0
- package/dist/delegation/headless-executor.js +562 -0
- package/dist/delegation/headless-executor.js.map +1 -0
- package/dist/delegation/result-formatter.d.ts +108 -0
- package/dist/delegation/result-formatter.d.ts.map +1 -0
- package/dist/delegation/result-formatter.js +391 -0
- package/dist/delegation/result-formatter.js.map +1 -0
- package/dist/delegation/session-manager.d.ts +58 -0
- package/dist/delegation/session-manager.d.ts.map +1 -0
- package/dist/delegation/session-manager.js +153 -0
- package/dist/delegation/session-manager.js.map +1 -0
- package/dist/delegation/settings-parser.d.ts +31 -0
- package/dist/delegation/settings-parser.d.ts.map +1 -0
- package/dist/delegation/settings-parser.js +107 -0
- package/dist/delegation/settings-parser.js.map +1 -0
- package/dist/glmt/delta-accumulator.d.ts +210 -0
- package/dist/glmt/delta-accumulator.d.ts.map +1 -0
- package/dist/glmt/delta-accumulator.js +351 -0
- package/dist/glmt/delta-accumulator.js.map +1 -0
- package/dist/glmt/glmt-proxy.d.ts +72 -0
- package/dist/glmt/glmt-proxy.d.ts.map +1 -0
- package/dist/glmt/glmt-proxy.js +427 -0
- package/dist/glmt/glmt-proxy.js.map +1 -0
- package/dist/glmt/glmt-transformer.d.ts +265 -0
- package/dist/glmt/glmt-transformer.d.ts.map +1 -0
- package/dist/glmt/glmt-transformer.js +832 -0
- package/dist/glmt/glmt-transformer.js.map +1 -0
- package/dist/glmt/locale-enforcer.d.ts +38 -0
- package/dist/glmt/locale-enforcer.d.ts.map +1 -0
- package/dist/glmt/locale-enforcer.js +69 -0
- package/dist/glmt/locale-enforcer.js.map +1 -0
- package/dist/glmt/reasoning-enforcer.d.ts +52 -0
- package/dist/glmt/reasoning-enforcer.d.ts.map +1 -0
- package/dist/glmt/reasoning-enforcer.js +151 -0
- package/dist/glmt/reasoning-enforcer.js.map +1 -0
- package/dist/glmt/sse-parser.d.ts +47 -0
- package/dist/glmt/sse-parser.d.ts.map +1 -0
- package/dist/glmt/sse-parser.js +93 -0
- package/dist/glmt/sse-parser.js.map +1 -0
- package/dist/management/doctor.d.ts +104 -0
- package/dist/management/doctor.d.ts.map +1 -0
- package/dist/management/doctor.js +673 -0
- package/dist/management/doctor.js.map +1 -0
- package/dist/management/instance-manager.d.ts +57 -0
- package/dist/management/instance-manager.d.ts.map +1 -0
- package/dist/management/instance-manager.js +195 -0
- package/dist/management/instance-manager.js.map +1 -0
- package/dist/management/recovery-manager.d.ts +39 -0
- package/dist/management/recovery-manager.d.ts.map +1 -0
- package/dist/management/recovery-manager.js +141 -0
- package/dist/management/recovery-manager.js.map +1 -0
- package/dist/management/shared-manager.d.ts +47 -0
- package/dist/management/shared-manager.d.ts.map +1 -0
- package/dist/management/shared-manager.js +388 -0
- package/dist/management/shared-manager.js.map +1 -0
- package/dist/types/cli.d.ts +50 -0
- package/dist/types/cli.d.ts.map +1 -0
- package/dist/types/cli.js +16 -0
- package/dist/types/cli.js.map +1 -0
- package/dist/types/config.d.ts +51 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +26 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/delegation.d.ts +61 -0
- package/dist/types/delegation.d.ts.map +1 -0
- package/dist/types/delegation.js +6 -0
- package/dist/types/delegation.js.map +1 -0
- package/dist/types/glmt.d.ts +95 -0
- package/dist/types/glmt.d.ts.map +1 -0
- package/dist/types/glmt.js +7 -0
- package/dist/types/glmt.js.map +1 -0
- package/dist/types/index.d.ts +13 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +16 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/utils.d.ts +36 -0
- package/dist/types/utils.d.ts.map +1 -0
- package/dist/types/utils.js +22 -0
- package/dist/types/utils.js.map +1 -0
- package/dist/utils/claude-detector.d.ts +14 -0
- package/dist/utils/claude-detector.d.ts.map +1 -0
- package/dist/utils/claude-detector.js +112 -0
- package/dist/utils/claude-detector.js.map +1 -0
- package/dist/utils/claude-dir-installer.d.ts +46 -0
- package/dist/utils/claude-dir-installer.d.ts.map +1 -0
- package/dist/utils/claude-dir-installer.js +289 -0
- package/dist/utils/claude-dir-installer.js.map +1 -0
- package/dist/utils/claude-symlink-manager.d.ts +61 -0
- package/dist/utils/claude-symlink-manager.d.ts.map +1 -0
- package/dist/utils/claude-symlink-manager.js +291 -0
- package/dist/utils/claude-symlink-manager.js.map +1 -0
- package/dist/utils/config-manager.d.ts +32 -0
- package/dist/utils/config-manager.d.ts.map +1 -0
- package/dist/utils/config-manager.js +143 -0
- package/dist/utils/config-manager.js.map +1 -0
- package/dist/utils/delegation-validator.d.ts +39 -0
- package/dist/utils/delegation-validator.d.ts.map +1 -0
- package/dist/utils/delegation-validator.js +161 -0
- package/dist/utils/delegation-validator.js.map +1 -0
- package/dist/utils/error-codes.d.ts +36 -0
- package/dist/utils/error-codes.d.ts.map +1 -0
- package/dist/utils/error-codes.js +63 -0
- package/dist/utils/error-codes.js.map +1 -0
- package/dist/utils/error-manager.d.ts +59 -0
- package/dist/utils/error-manager.d.ts.map +1 -0
- package/dist/utils/error-manager.js +228 -0
- package/dist/utils/error-manager.js.map +1 -0
- package/dist/utils/helpers.d.ts +27 -0
- package/dist/utils/helpers.d.ts.map +1 -0
- package/dist/utils/helpers.js +150 -0
- package/dist/utils/helpers.js.map +1 -0
- package/dist/utils/package-manager-detector.d.ts +14 -0
- package/dist/utils/package-manager-detector.d.ts.map +1 -0
- package/dist/utils/package-manager-detector.js +162 -0
- package/dist/utils/package-manager-detector.js.map +1 -0
- package/dist/utils/progress-indicator.d.ts +52 -0
- package/dist/utils/progress-indicator.d.ts.map +1 -0
- package/dist/utils/progress-indicator.js +102 -0
- package/dist/utils/progress-indicator.js.map +1 -0
- package/dist/utils/prompt.d.ts +29 -0
- package/dist/utils/prompt.d.ts.map +1 -0
- package/dist/utils/prompt.js +116 -0
- package/dist/utils/prompt.js.map +1 -0
- package/dist/utils/shell-completion.d.ts +52 -0
- package/dist/utils/shell-completion.d.ts.map +1 -0
- package/dist/utils/shell-completion.js +231 -0
- package/dist/utils/shell-completion.js.map +1 -0
- package/dist/utils/shell-executor.d.ts +15 -0
- package/dist/utils/shell-executor.d.ts.map +1 -0
- package/dist/utils/shell-executor.js +57 -0
- package/dist/utils/shell-executor.js.map +1 -0
- package/dist/utils/update-checker.d.ts +48 -0
- package/dist/utils/update-checker.d.ts.map +1 -0
- package/dist/utils/update-checker.js +241 -0
- package/dist/utils/update-checker.js.map +1 -0
- package/lib/ccs +21 -1907
- package/lib/ccs.ps1 +26 -1800
- package/lib/error-codes.ps1 +2 -1
- package/lib/prompt.ps1 +2 -2
- package/package.json +31 -11
- package/scripts/add-shebang.js +39 -0
- package/scripts/bump-version.sh +25 -37
- package/scripts/dev-install.sh +32 -11
- package/scripts/postinstall.js +29 -29
- package/bin/auth/auth-commands.js +0 -499
- package/bin/auth/profile-detector.js +0 -204
- package/bin/auth/profile-registry.js +0 -225
- package/bin/ccs.js +0 -1034
- package/bin/delegation/README.md +0 -191
- package/bin/delegation/delegation-handler.js +0 -212
- package/bin/delegation/headless-executor.js +0 -618
- package/bin/delegation/result-formatter.js +0 -485
- package/bin/delegation/session-manager.js +0 -157
- package/bin/delegation/settings-parser.js +0 -109
- package/bin/glmt/delta-accumulator.js +0 -276
- package/bin/glmt/glmt-proxy.js +0 -495
- package/bin/glmt/glmt-transformer.js +0 -999
- package/bin/glmt/locale-enforcer.js +0 -72
- package/bin/glmt/reasoning-enforcer.js +0 -173
- package/bin/glmt/sse-parser.js +0 -96
- package/bin/management/doctor.js +0 -721
- package/bin/management/instance-manager.js +0 -202
- package/bin/management/recovery-manager.js +0 -135
- package/bin/management/shared-manager.js +0 -402
- package/bin/utils/claude-detector.js +0 -73
- package/bin/utils/claude-dir-installer.js +0 -283
- package/bin/utils/claude-symlink-manager.js +0 -289
- package/bin/utils/config-manager.js +0 -103
- package/bin/utils/delegation-validator.js +0 -154
- package/bin/utils/error-codes.js +0 -59
- package/bin/utils/error-manager.js +0 -165
- package/bin/utils/helpers.js +0 -136
- package/bin/utils/progress-indicator.js +0 -111
- package/bin/utils/prompt.js +0 -134
- package/bin/utils/shell-completion.js +0 -256
- package/bin/utils/update-checker.js +0 -243
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Binary Manager for CLIProxyAPI
|
|
3
|
+
*
|
|
4
|
+
* Download-on-demand binary manager:
|
|
5
|
+
* - Downloads platform-specific binary from GitHub releases
|
|
6
|
+
* - Verifies SHA256 checksum
|
|
7
|
+
* - Extracts and caches binary locally
|
|
8
|
+
* - Supports retry logic with exponential backoff
|
|
9
|
+
*
|
|
10
|
+
* Pattern: Mirrors npm install behavior (fast check, download only when needed)
|
|
11
|
+
*/
|
|
12
|
+
import { BinaryInfo, BinaryManagerConfig } from './types';
|
|
13
|
+
/**
|
|
14
|
+
* Binary Manager class for CLIProxyAPI binary lifecycle
|
|
15
|
+
*/
|
|
16
|
+
export declare class BinaryManager {
|
|
17
|
+
private config;
|
|
18
|
+
private verbose;
|
|
19
|
+
constructor(config?: Partial<BinaryManagerConfig>);
|
|
20
|
+
/**
|
|
21
|
+
* Ensure binary is available (download if missing)
|
|
22
|
+
* @returns Path to executable binary
|
|
23
|
+
*/
|
|
24
|
+
ensureBinary(): Promise<string>;
|
|
25
|
+
/**
|
|
26
|
+
* Get full path to binary executable
|
|
27
|
+
*/
|
|
28
|
+
getBinaryPath(): string;
|
|
29
|
+
/**
|
|
30
|
+
* Check if binary exists
|
|
31
|
+
*/
|
|
32
|
+
isBinaryInstalled(): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Get binary info if installed
|
|
35
|
+
*/
|
|
36
|
+
getBinaryInfo(): Promise<BinaryInfo | null>;
|
|
37
|
+
/**
|
|
38
|
+
* Download and install binary
|
|
39
|
+
*/
|
|
40
|
+
private downloadAndInstall;
|
|
41
|
+
/**
|
|
42
|
+
* Download file with retry logic and exponential backoff
|
|
43
|
+
*/
|
|
44
|
+
private downloadWithRetry;
|
|
45
|
+
/**
|
|
46
|
+
* Download file from URL with progress tracking
|
|
47
|
+
*/
|
|
48
|
+
private downloadFile;
|
|
49
|
+
/**
|
|
50
|
+
* Verify file checksum against checksums.txt
|
|
51
|
+
*/
|
|
52
|
+
private verifyChecksum;
|
|
53
|
+
/**
|
|
54
|
+
* Parse checksum from checksums.txt content
|
|
55
|
+
*/
|
|
56
|
+
private parseChecksum;
|
|
57
|
+
/**
|
|
58
|
+
* Compute SHA256 checksum of file
|
|
59
|
+
*/
|
|
60
|
+
private computeChecksum;
|
|
61
|
+
/**
|
|
62
|
+
* Fetch text content from URL
|
|
63
|
+
*/
|
|
64
|
+
private fetchText;
|
|
65
|
+
/**
|
|
66
|
+
* Extract archive (tar.gz or zip)
|
|
67
|
+
*/
|
|
68
|
+
private extractArchive;
|
|
69
|
+
/**
|
|
70
|
+
* Extract tar.gz archive using Node.js built-in modules
|
|
71
|
+
*/
|
|
72
|
+
private extractTarGz;
|
|
73
|
+
/**
|
|
74
|
+
* Extract zip archive using Node.js (simple implementation)
|
|
75
|
+
*/
|
|
76
|
+
private extractZip;
|
|
77
|
+
/**
|
|
78
|
+
* Delete binary (for cleanup or reinstall)
|
|
79
|
+
*/
|
|
80
|
+
deleteBinary(): void;
|
|
81
|
+
/**
|
|
82
|
+
* Sleep helper
|
|
83
|
+
*/
|
|
84
|
+
private sleep;
|
|
85
|
+
/**
|
|
86
|
+
* Log message if verbose
|
|
87
|
+
*/
|
|
88
|
+
private log;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Convenience function to ensure binary is available
|
|
92
|
+
* @returns Path to CLIProxyAPI executable
|
|
93
|
+
*/
|
|
94
|
+
export declare function ensureCLIProxyBinary(verbose?: boolean): Promise<string>;
|
|
95
|
+
/**
|
|
96
|
+
* Check if CLIProxyAPI binary is installed
|
|
97
|
+
*/
|
|
98
|
+
export declare function isCLIProxyInstalled(): boolean;
|
|
99
|
+
/**
|
|
100
|
+
* Get CLIProxyAPI binary path (may not exist)
|
|
101
|
+
*/
|
|
102
|
+
export declare function getCLIProxyPath(): string;
|
|
103
|
+
export default BinaryManager;
|
|
104
|
+
//# sourceMappingURL=binary-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"binary-manager.d.ts","sourceRoot":"","sources":["../../src/cliproxy/binary-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAUH,OAAO,EACL,UAAU,EACV,mBAAmB,EAIpB,MAAM,SAAS,CAAC;AAmBjB;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,OAAO,CAAU;gBAEb,MAAM,GAAE,OAAO,CAAC,mBAAmB,CAAM;IAKrD;;;OAGG;IACG,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAgBrC;;OAEG;IACH,aAAa,IAAI,MAAM;IAKvB;;OAEG;IACH,iBAAiB,IAAI,OAAO;IAI5B;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAiBjD;;OAEG;YACW,kBAAkB;IAwEhC;;OAEG;YACW,iBAAiB;IA6B/B;;OAEG;IACH,OAAO,CAAC,YAAY;IAqEpB;;OAEG;YACW,cAAc;IAwB5B;;OAEG;IACH,OAAO,CAAC,aAAa;IAYrB;;OAEG;IACH,OAAO,CAAC,eAAe;IAWvB;;OAEG;IACH,OAAO,CAAC,SAAS;IAmCjB;;OAEG;YACW,cAAc;IAQ5B;;OAEG;IACH,OAAO,CAAC,YAAY;IA0GpB;;OAEG;IACH,OAAO,CAAC,UAAU;IA2FlB;;OAEG;IACH,YAAY,IAAI,IAAI;IAQpB;;OAEG;IACH,OAAO,CAAC,KAAK;IAIb;;OAEG;IACH,OAAO,CAAC,GAAG;CAKZ;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,UAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAG3E;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAG7C;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAGxC;AAED,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1,567 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Binary Manager for CLIProxyAPI
|
|
4
|
+
*
|
|
5
|
+
* Download-on-demand binary manager:
|
|
6
|
+
* - Downloads platform-specific binary from GitHub releases
|
|
7
|
+
* - Verifies SHA256 checksum
|
|
8
|
+
* - Extracts and caches binary locally
|
|
9
|
+
* - Supports retry logic with exponential backoff
|
|
10
|
+
*
|
|
11
|
+
* Pattern: Mirrors npm install behavior (fast check, download only when needed)
|
|
12
|
+
*/
|
|
13
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
16
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
17
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
18
|
+
}
|
|
19
|
+
Object.defineProperty(o, k2, desc);
|
|
20
|
+
}) : (function(o, m, k, k2) {
|
|
21
|
+
if (k2 === undefined) k2 = k;
|
|
22
|
+
o[k2] = m[k];
|
|
23
|
+
}));
|
|
24
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
25
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
26
|
+
}) : function(o, v) {
|
|
27
|
+
o["default"] = v;
|
|
28
|
+
});
|
|
29
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
30
|
+
if (mod && mod.__esModule) return mod;
|
|
31
|
+
var result = {};
|
|
32
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
33
|
+
__setModuleDefault(result, mod);
|
|
34
|
+
return result;
|
|
35
|
+
};
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
exports.getCLIProxyPath = exports.isCLIProxyInstalled = exports.ensureCLIProxyBinary = exports.BinaryManager = void 0;
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const https = __importStar(require("https"));
|
|
41
|
+
const http = __importStar(require("http"));
|
|
42
|
+
const crypto = __importStar(require("crypto"));
|
|
43
|
+
const zlib = __importStar(require("zlib"));
|
|
44
|
+
const progress_indicator_1 = require("../utils/progress-indicator");
|
|
45
|
+
const config_generator_1 = require("./config-generator");
|
|
46
|
+
const platform_detector_1 = require("./platform-detector");
|
|
47
|
+
/** Default configuration */
|
|
48
|
+
const DEFAULT_CONFIG = {
|
|
49
|
+
version: platform_detector_1.CLIPROXY_VERSION,
|
|
50
|
+
releaseUrl: 'https://github.com/router-for-me/CLIProxyAPI/releases/download',
|
|
51
|
+
binPath: (0, config_generator_1.getBinDir)(),
|
|
52
|
+
maxRetries: 3,
|
|
53
|
+
verbose: false,
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Binary Manager class for CLIProxyAPI binary lifecycle
|
|
57
|
+
*/
|
|
58
|
+
class BinaryManager {
|
|
59
|
+
constructor(config = {}) {
|
|
60
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
61
|
+
this.verbose = this.config.verbose;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Ensure binary is available (download if missing)
|
|
65
|
+
* @returns Path to executable binary
|
|
66
|
+
*/
|
|
67
|
+
async ensureBinary() {
|
|
68
|
+
const binaryPath = this.getBinaryPath();
|
|
69
|
+
// Check if binary already exists
|
|
70
|
+
if (fs.existsSync(binaryPath)) {
|
|
71
|
+
this.log(`Binary exists: ${binaryPath}`);
|
|
72
|
+
return binaryPath;
|
|
73
|
+
}
|
|
74
|
+
// Download, verify, extract
|
|
75
|
+
this.log('Binary not found, downloading...');
|
|
76
|
+
await this.downloadAndInstall();
|
|
77
|
+
return binaryPath;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Get full path to binary executable
|
|
81
|
+
*/
|
|
82
|
+
getBinaryPath() {
|
|
83
|
+
const execName = (0, platform_detector_1.getExecutableName)();
|
|
84
|
+
return path.join(this.config.binPath, execName);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Check if binary exists
|
|
88
|
+
*/
|
|
89
|
+
isBinaryInstalled() {
|
|
90
|
+
return fs.existsSync(this.getBinaryPath());
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Get binary info if installed
|
|
94
|
+
*/
|
|
95
|
+
async getBinaryInfo() {
|
|
96
|
+
const binaryPath = this.getBinaryPath();
|
|
97
|
+
if (!fs.existsSync(binaryPath)) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
const platform = (0, platform_detector_1.detectPlatform)();
|
|
101
|
+
const checksum = await this.computeChecksum(binaryPath);
|
|
102
|
+
return {
|
|
103
|
+
path: binaryPath,
|
|
104
|
+
version: this.config.version,
|
|
105
|
+
platform,
|
|
106
|
+
checksum,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Download and install binary
|
|
111
|
+
*/
|
|
112
|
+
async downloadAndInstall() {
|
|
113
|
+
const platform = (0, platform_detector_1.detectPlatform)();
|
|
114
|
+
const downloadUrl = (0, platform_detector_1.getDownloadUrl)(this.config.version);
|
|
115
|
+
const checksumsUrl = (0, platform_detector_1.getChecksumsUrl)(this.config.version);
|
|
116
|
+
// Ensure bin directory exists
|
|
117
|
+
fs.mkdirSync(this.config.binPath, { recursive: true });
|
|
118
|
+
// Download archive
|
|
119
|
+
const archivePath = path.join(this.config.binPath, `cliproxy-archive.${platform.extension}`);
|
|
120
|
+
const spinner = new progress_indicator_1.ProgressIndicator(`Downloading CLIProxyAPI v${this.config.version}`);
|
|
121
|
+
spinner.start();
|
|
122
|
+
try {
|
|
123
|
+
// Download with retry
|
|
124
|
+
const result = await this.downloadWithRetry(downloadUrl, archivePath);
|
|
125
|
+
if (!result.success) {
|
|
126
|
+
spinner.fail('Download failed');
|
|
127
|
+
throw new Error(result.error || 'Download failed after retries');
|
|
128
|
+
}
|
|
129
|
+
spinner.succeed('Download complete');
|
|
130
|
+
// Verify checksum
|
|
131
|
+
const verifySpinner = new progress_indicator_1.ProgressIndicator('Verifying checksum');
|
|
132
|
+
verifySpinner.start();
|
|
133
|
+
const checksumResult = await this.verifyChecksum(archivePath, platform.binaryName, checksumsUrl);
|
|
134
|
+
if (!checksumResult.valid) {
|
|
135
|
+
verifySpinner.fail('Checksum mismatch');
|
|
136
|
+
fs.unlinkSync(archivePath);
|
|
137
|
+
throw new Error(`Checksum mismatch for ${platform.binaryName}\n` +
|
|
138
|
+
`Expected: ${checksumResult.expected}\n` +
|
|
139
|
+
`Actual: ${checksumResult.actual}\n\n` +
|
|
140
|
+
`Manual download: ${downloadUrl}`);
|
|
141
|
+
}
|
|
142
|
+
verifySpinner.succeed('Checksum verified');
|
|
143
|
+
// Extract archive
|
|
144
|
+
const extractSpinner = new progress_indicator_1.ProgressIndicator('Extracting binary');
|
|
145
|
+
extractSpinner.start();
|
|
146
|
+
await this.extractArchive(archivePath, platform.extension);
|
|
147
|
+
extractSpinner.succeed('Extraction complete');
|
|
148
|
+
// Cleanup archive
|
|
149
|
+
fs.unlinkSync(archivePath);
|
|
150
|
+
// Make executable (Unix only)
|
|
151
|
+
const binaryPath = this.getBinaryPath();
|
|
152
|
+
if (platform.os !== 'windows' && fs.existsSync(binaryPath)) {
|
|
153
|
+
fs.chmodSync(binaryPath, 0o755);
|
|
154
|
+
this.log(`Set executable permissions: ${binaryPath}`);
|
|
155
|
+
}
|
|
156
|
+
console.log(`[OK] CLIProxyAPI v${this.config.version} installed successfully`);
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
spinner.fail('Installation failed');
|
|
160
|
+
throw error;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Download file with retry logic and exponential backoff
|
|
165
|
+
*/
|
|
166
|
+
async downloadWithRetry(url, destPath) {
|
|
167
|
+
let lastError = '';
|
|
168
|
+
let retries = 0;
|
|
169
|
+
while (retries < this.config.maxRetries) {
|
|
170
|
+
try {
|
|
171
|
+
await this.downloadFile(url, destPath);
|
|
172
|
+
return { success: true, filePath: destPath, retries };
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
const err = error;
|
|
176
|
+
lastError = err.message;
|
|
177
|
+
retries++;
|
|
178
|
+
if (retries < this.config.maxRetries) {
|
|
179
|
+
// Exponential backoff: 1s, 2s, 4s
|
|
180
|
+
const delay = Math.pow(2, retries - 1) * 1000;
|
|
181
|
+
this.log(`Retry ${retries}/${this.config.maxRetries} after ${delay}ms: ${lastError}`);
|
|
182
|
+
await this.sleep(delay);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return {
|
|
187
|
+
success: false,
|
|
188
|
+
error: `Download failed after ${retries} attempts: ${lastError}`,
|
|
189
|
+
retries,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Download file from URL with progress tracking
|
|
194
|
+
*/
|
|
195
|
+
downloadFile(url, destPath, onProgress) {
|
|
196
|
+
return new Promise((resolve, reject) => {
|
|
197
|
+
const handleResponse = (res) => {
|
|
198
|
+
// Handle redirects (GitHub releases use 302)
|
|
199
|
+
if (res.statusCode === 301 || res.statusCode === 302) {
|
|
200
|
+
const redirectUrl = res.headers.location;
|
|
201
|
+
if (!redirectUrl) {
|
|
202
|
+
reject(new Error('Redirect without location header'));
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
this.log(`Following redirect: ${redirectUrl}`);
|
|
206
|
+
this.downloadFile(redirectUrl, destPath, onProgress).then(resolve).catch(reject);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
if (res.statusCode !== 200) {
|
|
210
|
+
reject(new Error(`HTTP ${res.statusCode}: ${res.statusMessage}`));
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
const totalBytes = parseInt(res.headers['content-length'] || '0', 10);
|
|
214
|
+
let downloadedBytes = 0;
|
|
215
|
+
const fileStream = fs.createWriteStream(destPath);
|
|
216
|
+
res.on('data', (chunk) => {
|
|
217
|
+
downloadedBytes += chunk.length;
|
|
218
|
+
if (onProgress && totalBytes > 0) {
|
|
219
|
+
onProgress({
|
|
220
|
+
total: totalBytes,
|
|
221
|
+
downloaded: downloadedBytes,
|
|
222
|
+
percentage: Math.round((downloadedBytes / totalBytes) * 100),
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
res.pipe(fileStream);
|
|
227
|
+
fileStream.on('finish', () => {
|
|
228
|
+
fileStream.close();
|
|
229
|
+
resolve();
|
|
230
|
+
});
|
|
231
|
+
fileStream.on('error', (err) => {
|
|
232
|
+
fs.unlink(destPath, () => { }); // Cleanup partial file
|
|
233
|
+
reject(err);
|
|
234
|
+
});
|
|
235
|
+
res.on('error', (err) => {
|
|
236
|
+
fs.unlink(destPath, () => { });
|
|
237
|
+
reject(err);
|
|
238
|
+
});
|
|
239
|
+
};
|
|
240
|
+
const protocol = url.startsWith('https') ? https : http;
|
|
241
|
+
const req = protocol.get(url, handleResponse);
|
|
242
|
+
req.on('error', reject);
|
|
243
|
+
req.setTimeout(60000, () => {
|
|
244
|
+
req.destroy();
|
|
245
|
+
reject(new Error('Download timeout (60s)'));
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Verify file checksum against checksums.txt
|
|
251
|
+
*/
|
|
252
|
+
async verifyChecksum(filePath, binaryName, checksumsUrl) {
|
|
253
|
+
// Download checksums.txt
|
|
254
|
+
const checksumsContent = await this.fetchText(checksumsUrl);
|
|
255
|
+
// Parse expected checksum
|
|
256
|
+
const expectedHash = this.parseChecksum(checksumsContent, binaryName);
|
|
257
|
+
if (!expectedHash) {
|
|
258
|
+
throw new Error(`Checksum not found for ${binaryName} in checksums.txt`);
|
|
259
|
+
}
|
|
260
|
+
// Compute actual checksum
|
|
261
|
+
const actualHash = await this.computeChecksum(filePath);
|
|
262
|
+
return {
|
|
263
|
+
valid: actualHash === expectedHash,
|
|
264
|
+
expected: expectedHash,
|
|
265
|
+
actual: actualHash,
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Parse checksum from checksums.txt content
|
|
270
|
+
*/
|
|
271
|
+
parseChecksum(content, binaryName) {
|
|
272
|
+
const lines = content.split('\n');
|
|
273
|
+
for (const line of lines) {
|
|
274
|
+
// Format: "hash filename" or "hash filename"
|
|
275
|
+
const parts = line.trim().split(/\s+/);
|
|
276
|
+
if (parts.length >= 2 && parts[1] === binaryName) {
|
|
277
|
+
return parts[0].toLowerCase();
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return null;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Compute SHA256 checksum of file
|
|
284
|
+
*/
|
|
285
|
+
computeChecksum(filePath) {
|
|
286
|
+
return new Promise((resolve, reject) => {
|
|
287
|
+
const hash = crypto.createHash('sha256');
|
|
288
|
+
const stream = fs.createReadStream(filePath);
|
|
289
|
+
stream.on('data', (data) => hash.update(data));
|
|
290
|
+
stream.on('end', () => resolve(hash.digest('hex')));
|
|
291
|
+
stream.on('error', reject);
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Fetch text content from URL
|
|
296
|
+
*/
|
|
297
|
+
fetchText(url) {
|
|
298
|
+
return new Promise((resolve, reject) => {
|
|
299
|
+
const handleResponse = (res) => {
|
|
300
|
+
// Handle redirects
|
|
301
|
+
if (res.statusCode === 301 || res.statusCode === 302) {
|
|
302
|
+
const redirectUrl = res.headers.location;
|
|
303
|
+
if (!redirectUrl) {
|
|
304
|
+
reject(new Error('Redirect without location header'));
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
this.fetchText(redirectUrl).then(resolve).catch(reject);
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
if (res.statusCode !== 200) {
|
|
311
|
+
reject(new Error(`HTTP ${res.statusCode}: ${res.statusMessage}`));
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
let data = '';
|
|
315
|
+
res.on('data', (chunk) => (data += chunk));
|
|
316
|
+
res.on('end', () => resolve(data));
|
|
317
|
+
res.on('error', reject);
|
|
318
|
+
};
|
|
319
|
+
const protocol = url.startsWith('https') ? https : http;
|
|
320
|
+
const req = protocol.get(url, handleResponse);
|
|
321
|
+
req.on('error', reject);
|
|
322
|
+
req.setTimeout(30000, () => {
|
|
323
|
+
req.destroy();
|
|
324
|
+
reject(new Error('Request timeout (30s)'));
|
|
325
|
+
});
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Extract archive (tar.gz or zip)
|
|
330
|
+
*/
|
|
331
|
+
async extractArchive(archivePath, extension) {
|
|
332
|
+
if (extension === 'tar.gz') {
|
|
333
|
+
await this.extractTarGz(archivePath);
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
await this.extractZip(archivePath);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Extract tar.gz archive using Node.js built-in modules
|
|
341
|
+
*/
|
|
342
|
+
extractTarGz(archivePath) {
|
|
343
|
+
return new Promise((resolve, reject) => {
|
|
344
|
+
const destDir = this.config.binPath;
|
|
345
|
+
const execName = (0, platform_detector_1.getExecutableName)();
|
|
346
|
+
const archiveBinaryName = (0, platform_detector_1.getArchiveBinaryName)();
|
|
347
|
+
// Read and decompress
|
|
348
|
+
const gunzip = zlib.createGunzip();
|
|
349
|
+
const input = fs.createReadStream(archivePath);
|
|
350
|
+
let headerBuffer = Buffer.alloc(0);
|
|
351
|
+
let currentFile = null;
|
|
352
|
+
let bytesRead = 0;
|
|
353
|
+
let fileBuffer = Buffer.alloc(0);
|
|
354
|
+
const processData = (data) => {
|
|
355
|
+
headerBuffer = Buffer.concat([headerBuffer, data]);
|
|
356
|
+
while (headerBuffer.length >= 512) {
|
|
357
|
+
if (!currentFile) {
|
|
358
|
+
// Parse tar header
|
|
359
|
+
const header = headerBuffer.subarray(0, 512);
|
|
360
|
+
headerBuffer = headerBuffer.subarray(512);
|
|
361
|
+
// Check for empty header (end of archive)
|
|
362
|
+
if (header.every((b) => b === 0)) {
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
// Extract filename (bytes 0-99)
|
|
366
|
+
let name = '';
|
|
367
|
+
for (let i = 0; i < 100 && header[i] !== 0; i++) {
|
|
368
|
+
name += String.fromCharCode(header[i]);
|
|
369
|
+
}
|
|
370
|
+
// Extract size (bytes 124-135, octal)
|
|
371
|
+
let sizeStr = '';
|
|
372
|
+
for (let i = 124; i < 136 && header[i] !== 0; i++) {
|
|
373
|
+
sizeStr += String.fromCharCode(header[i]);
|
|
374
|
+
}
|
|
375
|
+
const size = parseInt(sizeStr.trim(), 8) || 0;
|
|
376
|
+
if (name && size > 0) {
|
|
377
|
+
// Extract just the filename (handle directories)
|
|
378
|
+
const baseName = path.basename(name);
|
|
379
|
+
if (baseName === execName ||
|
|
380
|
+
baseName === archiveBinaryName ||
|
|
381
|
+
baseName === 'cli-proxy-api') {
|
|
382
|
+
currentFile = { name: baseName, size };
|
|
383
|
+
fileBuffer = Buffer.alloc(0);
|
|
384
|
+
bytesRead = 0;
|
|
385
|
+
}
|
|
386
|
+
else {
|
|
387
|
+
// Skip this file's data
|
|
388
|
+
const paddedSize = Math.ceil(size / 512) * 512;
|
|
389
|
+
if (headerBuffer.length >= paddedSize) {
|
|
390
|
+
headerBuffer = headerBuffer.subarray(paddedSize);
|
|
391
|
+
}
|
|
392
|
+
else {
|
|
393
|
+
// Need to skip data in chunks
|
|
394
|
+
currentFile = { name: '', size: paddedSize };
|
|
395
|
+
bytesRead = 0;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
else {
|
|
401
|
+
// Read file data
|
|
402
|
+
const remaining = currentFile.size - bytesRead;
|
|
403
|
+
const chunk = headerBuffer.subarray(0, Math.min(remaining, headerBuffer.length));
|
|
404
|
+
headerBuffer = headerBuffer.subarray(chunk.length);
|
|
405
|
+
if (currentFile.name) {
|
|
406
|
+
fileBuffer = Buffer.concat([fileBuffer, chunk]);
|
|
407
|
+
}
|
|
408
|
+
bytesRead += chunk.length;
|
|
409
|
+
if (bytesRead >= currentFile.size) {
|
|
410
|
+
// File complete
|
|
411
|
+
if (currentFile.name) {
|
|
412
|
+
const destPath = path.join(destDir, execName);
|
|
413
|
+
fs.writeFileSync(destPath, fileBuffer);
|
|
414
|
+
this.log(`Extracted: ${currentFile.name} -> ${destPath}`);
|
|
415
|
+
}
|
|
416
|
+
// Skip padding to 512-byte boundary
|
|
417
|
+
const paddedSize = Math.ceil(currentFile.size / 512) * 512;
|
|
418
|
+
const padding = paddedSize - currentFile.size;
|
|
419
|
+
if (headerBuffer.length >= padding) {
|
|
420
|
+
headerBuffer = headerBuffer.subarray(padding);
|
|
421
|
+
}
|
|
422
|
+
currentFile = null;
|
|
423
|
+
fileBuffer = Buffer.alloc(0);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
};
|
|
428
|
+
input.pipe(gunzip);
|
|
429
|
+
gunzip.on('data', processData);
|
|
430
|
+
gunzip.on('end', resolve);
|
|
431
|
+
gunzip.on('error', reject);
|
|
432
|
+
input.on('error', reject);
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Extract zip archive using Node.js (simple implementation)
|
|
437
|
+
*/
|
|
438
|
+
extractZip(archivePath) {
|
|
439
|
+
return new Promise((resolve, reject) => {
|
|
440
|
+
const destDir = this.config.binPath;
|
|
441
|
+
const execName = (0, platform_detector_1.getExecutableName)();
|
|
442
|
+
const archiveBinaryName = (0, platform_detector_1.getArchiveBinaryName)();
|
|
443
|
+
const buffer = fs.readFileSync(archivePath);
|
|
444
|
+
// Find End of Central Directory record (EOCD)
|
|
445
|
+
let eocdOffset = buffer.length - 22;
|
|
446
|
+
while (eocdOffset >= 0) {
|
|
447
|
+
if (buffer.readUInt32LE(eocdOffset) === 0x06054b50) {
|
|
448
|
+
break;
|
|
449
|
+
}
|
|
450
|
+
eocdOffset--;
|
|
451
|
+
}
|
|
452
|
+
if (eocdOffset < 0) {
|
|
453
|
+
reject(new Error('Invalid ZIP file: EOCD not found'));
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
const centralDirOffset = buffer.readUInt32LE(eocdOffset + 16);
|
|
457
|
+
let offset = centralDirOffset;
|
|
458
|
+
// Parse central directory
|
|
459
|
+
while (offset < eocdOffset) {
|
|
460
|
+
const sig = buffer.readUInt32LE(offset);
|
|
461
|
+
if (sig !== 0x02014b50)
|
|
462
|
+
break;
|
|
463
|
+
const compressionMethod = buffer.readUInt16LE(offset + 10);
|
|
464
|
+
const compressedSize = buffer.readUInt32LE(offset + 20);
|
|
465
|
+
const uncompressedSize = buffer.readUInt32LE(offset + 24);
|
|
466
|
+
const fileNameLength = buffer.readUInt16LE(offset + 28);
|
|
467
|
+
const extraFieldLength = buffer.readUInt16LE(offset + 30);
|
|
468
|
+
const commentLength = buffer.readUInt16LE(offset + 32);
|
|
469
|
+
const localHeaderOffset = buffer.readUInt32LE(offset + 42);
|
|
470
|
+
const fileName = buffer.toString('utf8', offset + 46, offset + 46 + fileNameLength);
|
|
471
|
+
const baseName = path.basename(fileName);
|
|
472
|
+
// Check if this is the executable we want
|
|
473
|
+
if (baseName === execName ||
|
|
474
|
+
baseName === archiveBinaryName ||
|
|
475
|
+
baseName === 'cli-proxy-api.exe') {
|
|
476
|
+
// Read from local file header
|
|
477
|
+
const localOffset = localHeaderOffset;
|
|
478
|
+
const localSig = buffer.readUInt32LE(localOffset);
|
|
479
|
+
if (localSig !== 0x04034b50) {
|
|
480
|
+
reject(new Error('Invalid local file header'));
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
const localFileNameLength = buffer.readUInt16LE(localOffset + 26);
|
|
484
|
+
const localExtraLength = buffer.readUInt16LE(localOffset + 28);
|
|
485
|
+
const dataOffset = localOffset + 30 + localFileNameLength + localExtraLength;
|
|
486
|
+
let fileData;
|
|
487
|
+
if (compressionMethod === 0) {
|
|
488
|
+
// Stored (no compression)
|
|
489
|
+
fileData = buffer.subarray(dataOffset, dataOffset + compressedSize);
|
|
490
|
+
}
|
|
491
|
+
else if (compressionMethod === 8) {
|
|
492
|
+
// Deflate
|
|
493
|
+
const compressed = buffer.subarray(dataOffset, dataOffset + compressedSize);
|
|
494
|
+
fileData = zlib.inflateRawSync(compressed);
|
|
495
|
+
}
|
|
496
|
+
else {
|
|
497
|
+
reject(new Error(`Unsupported compression method: ${compressionMethod}`));
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
if (fileData.length !== uncompressedSize) {
|
|
501
|
+
reject(new Error('Decompression size mismatch'));
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
504
|
+
const destPath = path.join(destDir, execName);
|
|
505
|
+
fs.writeFileSync(destPath, fileData);
|
|
506
|
+
this.log(`Extracted: ${fileName} -> ${destPath}`);
|
|
507
|
+
resolve();
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
510
|
+
offset += 46 + fileNameLength + extraFieldLength + commentLength;
|
|
511
|
+
}
|
|
512
|
+
reject(new Error(`Executable not found in archive: ${execName}`));
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
/**
|
|
516
|
+
* Delete binary (for cleanup or reinstall)
|
|
517
|
+
*/
|
|
518
|
+
deleteBinary() {
|
|
519
|
+
const binaryPath = this.getBinaryPath();
|
|
520
|
+
if (fs.existsSync(binaryPath)) {
|
|
521
|
+
fs.unlinkSync(binaryPath);
|
|
522
|
+
this.log(`Deleted: ${binaryPath}`);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* Sleep helper
|
|
527
|
+
*/
|
|
528
|
+
sleep(ms) {
|
|
529
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
530
|
+
}
|
|
531
|
+
/**
|
|
532
|
+
* Log message if verbose
|
|
533
|
+
*/
|
|
534
|
+
log(message) {
|
|
535
|
+
if (this.verbose) {
|
|
536
|
+
console.error(`[cliproxy] ${message}`);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
exports.BinaryManager = BinaryManager;
|
|
541
|
+
/**
|
|
542
|
+
* Convenience function to ensure binary is available
|
|
543
|
+
* @returns Path to CLIProxyAPI executable
|
|
544
|
+
*/
|
|
545
|
+
async function ensureCLIProxyBinary(verbose = false) {
|
|
546
|
+
const manager = new BinaryManager({ verbose });
|
|
547
|
+
return manager.ensureBinary();
|
|
548
|
+
}
|
|
549
|
+
exports.ensureCLIProxyBinary = ensureCLIProxyBinary;
|
|
550
|
+
/**
|
|
551
|
+
* Check if CLIProxyAPI binary is installed
|
|
552
|
+
*/
|
|
553
|
+
function isCLIProxyInstalled() {
|
|
554
|
+
const manager = new BinaryManager();
|
|
555
|
+
return manager.isBinaryInstalled();
|
|
556
|
+
}
|
|
557
|
+
exports.isCLIProxyInstalled = isCLIProxyInstalled;
|
|
558
|
+
/**
|
|
559
|
+
* Get CLIProxyAPI binary path (may not exist)
|
|
560
|
+
*/
|
|
561
|
+
function getCLIProxyPath() {
|
|
562
|
+
const manager = new BinaryManager();
|
|
563
|
+
return manager.getBinaryPath();
|
|
564
|
+
}
|
|
565
|
+
exports.getCLIProxyPath = getCLIProxyPath;
|
|
566
|
+
exports.default = BinaryManager;
|
|
567
|
+
//# sourceMappingURL=binary-manager.js.map
|