gopher-orch 0.1.0-20260131-081911
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/LICENSE +201 -0
- package/README.md +415 -0
- package/dist/agent.d.ts +118 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +236 -0
- package/dist/agent.js.map +1 -0
- package/dist/config.d.ts +63 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +101 -0
- package/dist/config.js.map +1 -0
- package/dist/errors.d.ts +29 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +53 -0
- package/dist/errors.js.map +1 -0
- package/dist/ffi/index.d.ts +6 -0
- package/dist/ffi/index.d.ts.map +1 -0
- package/dist/ffi/index.js +9 -0
- package/dist/ffi/index.js.map +1 -0
- package/dist/ffi/library.d.ts +80 -0
- package/dist/ffi/library.d.ts.map +1 -0
- package/dist/ffi/library.js +357 -0
- package/dist/ffi/library.js.map +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -0
- package/dist/result.d.ts +81 -0
- package/dist/result.d.ts.map +1 -0
- package/dist/result.js +129 -0
- package/dist/result.js.map +1 -0
- package/dist/serverConfig.d.ts +18 -0
- package/dist/serverConfig.d.ts.map +1 -0
- package/dist/serverConfig.js +48 -0
- package/dist/serverConfig.js.map +1 -0
- package/package.json +67 -0
- package/scripts/download-native.js +328 -0
package/dist/result.js
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AgentResultBuilder = exports.AgentResult = exports.AgentResultStatus = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Status of agent query execution.
|
|
6
|
+
*/
|
|
7
|
+
var AgentResultStatus;
|
|
8
|
+
(function (AgentResultStatus) {
|
|
9
|
+
AgentResultStatus["SUCCESS"] = "success";
|
|
10
|
+
AgentResultStatus["ERROR"] = "error";
|
|
11
|
+
AgentResultStatus["TIMEOUT"] = "timeout";
|
|
12
|
+
})(AgentResultStatus || (exports.AgentResultStatus = AgentResultStatus = {}));
|
|
13
|
+
/**
|
|
14
|
+
* Result from agent query execution.
|
|
15
|
+
*/
|
|
16
|
+
class AgentResult {
|
|
17
|
+
response;
|
|
18
|
+
status;
|
|
19
|
+
iterationCount;
|
|
20
|
+
tokensUsed;
|
|
21
|
+
constructor(options) {
|
|
22
|
+
this.response = options.response;
|
|
23
|
+
this.status = options.status;
|
|
24
|
+
this.iterationCount = options.iterationCount;
|
|
25
|
+
this.tokensUsed = options.tokensUsed;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Check if the result is a success.
|
|
29
|
+
*/
|
|
30
|
+
isSuccess() {
|
|
31
|
+
return this.status === AgentResultStatus.SUCCESS;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Create a new builder for AgentResult.
|
|
35
|
+
*/
|
|
36
|
+
static builder() {
|
|
37
|
+
return new AgentResultBuilder();
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Create a success result.
|
|
41
|
+
*/
|
|
42
|
+
static success(response) {
|
|
43
|
+
return AgentResult.builder()
|
|
44
|
+
.response(response)
|
|
45
|
+
.status(AgentResultStatus.SUCCESS)
|
|
46
|
+
.build();
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Create an error result.
|
|
50
|
+
*/
|
|
51
|
+
static error(message) {
|
|
52
|
+
return AgentResult.builder()
|
|
53
|
+
.response(message)
|
|
54
|
+
.status(AgentResultStatus.ERROR)
|
|
55
|
+
.build();
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Create a timeout result.
|
|
59
|
+
*/
|
|
60
|
+
static timeout(message) {
|
|
61
|
+
return AgentResult.builder()
|
|
62
|
+
.response(message)
|
|
63
|
+
.status(AgentResultStatus.TIMEOUT)
|
|
64
|
+
.build();
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* String representation of the result.
|
|
68
|
+
*/
|
|
69
|
+
toString() {
|
|
70
|
+
return `AgentResult{response='${this.response}', status=${this.status}, iterationCount=${this.iterationCount}, tokensUsed=${this.tokensUsed}}`;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
exports.AgentResult = AgentResult;
|
|
74
|
+
/**
|
|
75
|
+
* Builder for AgentResult.
|
|
76
|
+
*/
|
|
77
|
+
class AgentResultBuilder {
|
|
78
|
+
_response;
|
|
79
|
+
_status;
|
|
80
|
+
_iterationCount;
|
|
81
|
+
_tokensUsed;
|
|
82
|
+
/**
|
|
83
|
+
* Set the response.
|
|
84
|
+
*/
|
|
85
|
+
response(response) {
|
|
86
|
+
this._response = response;
|
|
87
|
+
return this;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Set the status.
|
|
91
|
+
*/
|
|
92
|
+
status(status) {
|
|
93
|
+
this._status = status;
|
|
94
|
+
return this;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Set the iteration count.
|
|
98
|
+
*/
|
|
99
|
+
iterationCount(iterationCount) {
|
|
100
|
+
this._iterationCount = iterationCount;
|
|
101
|
+
return this;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Set the tokens used.
|
|
105
|
+
*/
|
|
106
|
+
tokensUsed(tokensUsed) {
|
|
107
|
+
this._tokensUsed = tokensUsed;
|
|
108
|
+
return this;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Build the AgentResult.
|
|
112
|
+
*/
|
|
113
|
+
build() {
|
|
114
|
+
if (this._response === undefined) {
|
|
115
|
+
throw new Error('Response is required');
|
|
116
|
+
}
|
|
117
|
+
if (this._status === undefined) {
|
|
118
|
+
throw new Error('Status is required');
|
|
119
|
+
}
|
|
120
|
+
return new AgentResult({
|
|
121
|
+
response: this._response,
|
|
122
|
+
status: this._status,
|
|
123
|
+
iterationCount: this._iterationCount,
|
|
124
|
+
tokensUsed: this._tokensUsed,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
exports.AgentResultBuilder = AgentResultBuilder;
|
|
129
|
+
//# sourceMappingURL=result.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result.js","sourceRoot":"","sources":["../src/result.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility class for fetching server configurations.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Utility functions for fetching server configurations.
|
|
6
|
+
*/
|
|
7
|
+
export declare const ServerConfig: {
|
|
8
|
+
/**
|
|
9
|
+
* Fetch MCP server configurations from remote API.
|
|
10
|
+
*
|
|
11
|
+
* @param apiKey API key for authentication
|
|
12
|
+
* @returns Server configuration JSON string
|
|
13
|
+
* @throws {ApiKeyError} if API key is invalid or missing
|
|
14
|
+
* @throws {AgentError} if fetch fails
|
|
15
|
+
*/
|
|
16
|
+
fetch(apiKey: string): string;
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=serverConfig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serverConfig.d.ts","sourceRoot":"","sources":["../src/serverConfig.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH;;GAEG;AACH,eAAO,MAAM,YAAY;IACvB;;;;;;;OAOG;kBACW,MAAM,GAAG,MAAM;CA2B9B,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Utility class for fetching server configurations.
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ServerConfig = void 0;
|
|
7
|
+
const agent_1 = require("./agent");
|
|
8
|
+
const errors_1 = require("./errors");
|
|
9
|
+
const ffi_1 = require("./ffi");
|
|
10
|
+
/**
|
|
11
|
+
* Utility functions for fetching server configurations.
|
|
12
|
+
*/
|
|
13
|
+
exports.ServerConfig = {
|
|
14
|
+
/**
|
|
15
|
+
* Fetch MCP server configurations from remote API.
|
|
16
|
+
*
|
|
17
|
+
* @param apiKey API key for authentication
|
|
18
|
+
* @returns Server configuration JSON string
|
|
19
|
+
* @throws {ApiKeyError} if API key is invalid or missing
|
|
20
|
+
* @throws {AgentError} if fetch fails
|
|
21
|
+
*/
|
|
22
|
+
fetch(apiKey) {
|
|
23
|
+
if (!agent_1.GopherAgent.isInitialized()) {
|
|
24
|
+
agent_1.GopherAgent.init();
|
|
25
|
+
}
|
|
26
|
+
if (!apiKey || apiKey.trim() === '') {
|
|
27
|
+
throw new errors_1.ApiKeyError('Invalid or missing API key');
|
|
28
|
+
}
|
|
29
|
+
const lib = ffi_1.GopherOrchLibrary.getInstance();
|
|
30
|
+
if (lib === null) {
|
|
31
|
+
throw new errors_1.AgentError('Native library not available');
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
const result = lib.apiFetchServers(apiKey);
|
|
35
|
+
if (result === null) {
|
|
36
|
+
throw new errors_1.AgentError('Failed to fetch servers: no response');
|
|
37
|
+
}
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
if (e instanceof errors_1.ApiKeyError) {
|
|
42
|
+
throw e;
|
|
43
|
+
}
|
|
44
|
+
throw new errors_1.AgentError(`Failed to fetch servers: ${e.message}`);
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=serverConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serverConfig.js","sourceRoot":"","sources":["../src/serverConfig.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,mCAAsC;AACtC,qCAAmD;AACnD,+BAA0C;AAE1C;;GAEG;AACU,QAAA,YAAY,GAAG;IAC1B;;;;;;;OAOG;IACH,KAAK,CAAC,MAAc;QAClB,IAAI,CAAC,mBAAW,CAAC,aAAa,EAAE,EAAE,CAAC;YACjC,mBAAW,CAAC,IAAI,EAAE,CAAC;QACrB,CAAC;QAED,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACpC,MAAM,IAAI,oBAAW,CAAC,4BAA4B,CAAC,CAAC;QACtD,CAAC;QAED,MAAM,GAAG,GAAG,uBAAiB,CAAC,WAAW,EAAE,CAAC;QAC5C,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACjB,MAAM,IAAI,mBAAU,CAAC,8BAA8B,CAAC,CAAC;QACvD,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,GAAG,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;YAC3C,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;gBACpB,MAAM,IAAI,mBAAU,CAAC,sCAAsC,CAAC,CAAC;YAC/D,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,YAAY,oBAAW,EAAE,CAAC;gBAC7B,MAAM,CAAC,CAAC;YACV,CAAC;YACD,MAAM,IAAI,mBAAU,CAAC,4BAA6B,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;QAC3E,CAAC;IACH,CAAC;CACF,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "gopher-orch",
|
|
3
|
+
"version": "0.1.0-20260131-081911",
|
|
4
|
+
"description": "TypeScript SDK for Gopher Orch - AI Agent orchestration framework with native performance",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"author": "Gopher Security <dev@gophersecurity.com>",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/GopherSecurity/gopher-mcp-js.git"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"gopher",
|
|
15
|
+
"mcp",
|
|
16
|
+
"ai",
|
|
17
|
+
"agent",
|
|
18
|
+
"orchestration",
|
|
19
|
+
"llm",
|
|
20
|
+
"ffi"
|
|
21
|
+
],
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=18.0.0"
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "tsc",
|
|
27
|
+
"clean": "rm -rf dist",
|
|
28
|
+
"test": "jest",
|
|
29
|
+
"test:watch": "jest --watch",
|
|
30
|
+
"example": "tsx examples/client_example_json.ts",
|
|
31
|
+
"lint": "eslint src --ext .ts",
|
|
32
|
+
"lint:fix": "eslint src --ext .ts --fix",
|
|
33
|
+
"format": "prettier --write 'src/**/*.ts' 'tests/**/*.ts' 'examples/**/*.ts'",
|
|
34
|
+
"format:check": "prettier --check 'src/**/*.ts' 'tests/**/*.ts' 'examples/**/*.ts'",
|
|
35
|
+
"prepublishOnly": "npm run build",
|
|
36
|
+
"postinstall": "node scripts/download-native.js || true"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"koffi": "^2.9.0"
|
|
40
|
+
},
|
|
41
|
+
"optionalDependencies": {
|
|
42
|
+
"@gopher-test/gopher-orch-darwin-arm64": "0.1.0",
|
|
43
|
+
"@gopher-test/gopher-orch-darwin-x64": "0.1.0",
|
|
44
|
+
"@gopher-test/gopher-orch-linux-arm64": "0.1.0",
|
|
45
|
+
"@gopher-test/gopher-orch-linux-x64": "0.1.0",
|
|
46
|
+
"@gopher-test/gopher-orch-win32-arm64": "0.1.0",
|
|
47
|
+
"@gopher-test/gopher-orch-win32-x64": "0.1.0"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@types/jest": "^29.5.11",
|
|
51
|
+
"@types/node": "^20.10.6",
|
|
52
|
+
"@typescript-eslint/eslint-plugin": "^6.16.0",
|
|
53
|
+
"@typescript-eslint/parser": "^6.16.0",
|
|
54
|
+
"eslint": "^8.56.0",
|
|
55
|
+
"eslint-config-prettier": "^9.1.0",
|
|
56
|
+
"jest": "^29.7.0",
|
|
57
|
+
"prettier": "^3.1.1",
|
|
58
|
+
"ts-jest": "^29.1.1",
|
|
59
|
+
"tsx": "^4.7.0",
|
|
60
|
+
"typescript": "^5.3.3"
|
|
61
|
+
},
|
|
62
|
+
"files": [
|
|
63
|
+
"dist",
|
|
64
|
+
"native/lib",
|
|
65
|
+
"scripts"
|
|
66
|
+
]
|
|
67
|
+
}
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Download native gopher-orch library as a fallback when optional
|
|
5
|
+
* dependency packages aren't available.
|
|
6
|
+
*
|
|
7
|
+
* This script is run during postinstall to ensure the native library
|
|
8
|
+
* is available even if:
|
|
9
|
+
* - The user's platform package wasn't installed
|
|
10
|
+
* - The user ran npm install with --ignore-scripts initially
|
|
11
|
+
* - The optional dependencies failed to install
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* node scripts/download-native.js [--version <version>] [--force]
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const https = require('https');
|
|
18
|
+
const http = require('http');
|
|
19
|
+
const fs = require('fs');
|
|
20
|
+
const path = require('path');
|
|
21
|
+
const os = require('os');
|
|
22
|
+
const { execSync } = require('child_process');
|
|
23
|
+
|
|
24
|
+
// Configuration
|
|
25
|
+
const GITHUB_REPO = 'GopherSecurity/gopher-orch';
|
|
26
|
+
const DEFAULT_VERSION = 'latest';
|
|
27
|
+
|
|
28
|
+
// Platform mappings
|
|
29
|
+
const PLATFORM_MAP = {
|
|
30
|
+
darwin: { name: 'macos', ext: 'tar.gz', lib: 'libgopher-orch.dylib' },
|
|
31
|
+
linux: { name: 'linux', ext: 'tar.gz', lib: 'libgopher-orch.so' },
|
|
32
|
+
win32: { name: 'windows', ext: 'zip', lib: 'gopher-orch.dll' },
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const ARCH_MAP = {
|
|
36
|
+
arm64: 'arm64',
|
|
37
|
+
x64: 'x64',
|
|
38
|
+
x86_64: 'x64',
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Get the platform-specific package name
|
|
43
|
+
*/
|
|
44
|
+
function getPlatformPackageName() {
|
|
45
|
+
const platform = os.platform();
|
|
46
|
+
const arch = os.arch();
|
|
47
|
+
const archName = ARCH_MAP[arch] || arch;
|
|
48
|
+
|
|
49
|
+
const platformName =
|
|
50
|
+
platform === 'darwin' ? 'darwin' : platform === 'win32' ? 'win32' : 'linux';
|
|
51
|
+
|
|
52
|
+
return `gopher-orch-${platformName}-${archName}`;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Check if the platform package is already installed
|
|
57
|
+
*/
|
|
58
|
+
function isPlatformPackageInstalled() {
|
|
59
|
+
const packageName = getPlatformPackageName();
|
|
60
|
+
try {
|
|
61
|
+
require.resolve(`${packageName}/package.json`);
|
|
62
|
+
return true;
|
|
63
|
+
} catch {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Check if the native library already exists locally
|
|
70
|
+
*/
|
|
71
|
+
function isLibraryInstalled() {
|
|
72
|
+
const platform = os.platform();
|
|
73
|
+
const platformInfo = PLATFORM_MAP[platform];
|
|
74
|
+
if (!platformInfo) return false;
|
|
75
|
+
|
|
76
|
+
const libPath = path.join(__dirname, '..', 'native', 'lib', platformInfo.lib);
|
|
77
|
+
return fs.existsSync(libPath);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Get the download URL for the current platform
|
|
82
|
+
*/
|
|
83
|
+
function getDownloadUrl(version) {
|
|
84
|
+
const platform = os.platform();
|
|
85
|
+
const arch = os.arch();
|
|
86
|
+
|
|
87
|
+
const platformInfo = PLATFORM_MAP[platform];
|
|
88
|
+
const archName = ARCH_MAP[arch] || arch;
|
|
89
|
+
|
|
90
|
+
if (!platformInfo) {
|
|
91
|
+
throw new Error(`Unsupported platform: ${platform}`);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const filename = `libgopher-orch-${platformInfo.name}-${archName}.${platformInfo.ext}`;
|
|
95
|
+
|
|
96
|
+
if (version === 'latest') {
|
|
97
|
+
return `https://github.com/${GITHUB_REPO}/releases/latest/download/${filename}`;
|
|
98
|
+
}
|
|
99
|
+
return `https://github.com/${GITHUB_REPO}/releases/download/${version}/${filename}`;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Follow redirects and download a file
|
|
104
|
+
*/
|
|
105
|
+
function downloadFile(url, destPath) {
|
|
106
|
+
return new Promise((resolve, reject) => {
|
|
107
|
+
const file = fs.createWriteStream(destPath);
|
|
108
|
+
const protocol = url.startsWith('https') ? https : http;
|
|
109
|
+
|
|
110
|
+
const request = protocol.get(url, (response) => {
|
|
111
|
+
// Handle redirects
|
|
112
|
+
if (response.statusCode === 301 || response.statusCode === 302) {
|
|
113
|
+
file.close();
|
|
114
|
+
fs.unlinkSync(destPath);
|
|
115
|
+
return downloadFile(response.headers.location, destPath)
|
|
116
|
+
.then(resolve)
|
|
117
|
+
.catch(reject);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (response.statusCode !== 200) {
|
|
121
|
+
file.close();
|
|
122
|
+
fs.unlinkSync(destPath);
|
|
123
|
+
reject(new Error(`Download failed with status ${response.statusCode}`));
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
response.pipe(file);
|
|
128
|
+
|
|
129
|
+
file.on('finish', () => {
|
|
130
|
+
file.close();
|
|
131
|
+
resolve();
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
request.on('error', (err) => {
|
|
136
|
+
file.close();
|
|
137
|
+
fs.unlink(destPath, () => {});
|
|
138
|
+
reject(err);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
file.on('error', (err) => {
|
|
142
|
+
file.close();
|
|
143
|
+
fs.unlink(destPath, () => {});
|
|
144
|
+
reject(err);
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Extract the archive based on extension
|
|
151
|
+
*/
|
|
152
|
+
function extractArchive(archivePath, destDir) {
|
|
153
|
+
const ext = path.extname(archivePath);
|
|
154
|
+
|
|
155
|
+
if (ext === '.gz' && archivePath.endsWith('.tar.gz')) {
|
|
156
|
+
// tar.gz
|
|
157
|
+
execSync(`tar -xzf "${archivePath}" -C "${destDir}"`, { stdio: 'inherit' });
|
|
158
|
+
} else if (ext === '.zip') {
|
|
159
|
+
// zip
|
|
160
|
+
execSync(`unzip -o "${archivePath}" -d "${destDir}"`, { stdio: 'inherit' });
|
|
161
|
+
} else {
|
|
162
|
+
throw new Error(`Unknown archive format: ${ext}`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Main download function
|
|
168
|
+
*/
|
|
169
|
+
async function downloadNative(options = {}) {
|
|
170
|
+
const { version = DEFAULT_VERSION, force = false } = options;
|
|
171
|
+
|
|
172
|
+
console.log('gopher-orch native library installer');
|
|
173
|
+
console.log('====================================');
|
|
174
|
+
console.log(`Platform: ${os.platform()} ${os.arch()}`);
|
|
175
|
+
console.log(`Version: ${version}`);
|
|
176
|
+
console.log();
|
|
177
|
+
|
|
178
|
+
// Check if platform package is already installed
|
|
179
|
+
if (!force && isPlatformPackageInstalled()) {
|
|
180
|
+
console.log(
|
|
181
|
+
'✓ Platform-specific package is already installed via npm optional dependencies'
|
|
182
|
+
);
|
|
183
|
+
console.log(' No download needed.');
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Check if library already exists
|
|
188
|
+
if (!force && isLibraryInstalled()) {
|
|
189
|
+
console.log('✓ Native library already exists in native/lib/');
|
|
190
|
+
console.log(' Use --force to re-download.');
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const platform = os.platform();
|
|
195
|
+
const platformInfo = PLATFORM_MAP[platform];
|
|
196
|
+
|
|
197
|
+
if (!platformInfo) {
|
|
198
|
+
console.error(`✗ Unsupported platform: ${platform}`);
|
|
199
|
+
console.error(
|
|
200
|
+
' Supported platforms: darwin (macOS), linux, win32 (Windows)'
|
|
201
|
+
);
|
|
202
|
+
process.exit(1);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Create directories
|
|
206
|
+
const nativeLibDir = path.join(__dirname, '..', 'native', 'lib');
|
|
207
|
+
const tempDir = path.join(os.tmpdir(), 'gopher-orch-download');
|
|
208
|
+
|
|
209
|
+
fs.mkdirSync(nativeLibDir, { recursive: true });
|
|
210
|
+
fs.mkdirSync(tempDir, { recursive: true });
|
|
211
|
+
|
|
212
|
+
try {
|
|
213
|
+
// Download
|
|
214
|
+
const url = getDownloadUrl(version);
|
|
215
|
+
const archiveName = `gopher-orch.${platformInfo.ext}`;
|
|
216
|
+
const archivePath = path.join(tempDir, archiveName);
|
|
217
|
+
|
|
218
|
+
console.log(`Downloading from: ${url}`);
|
|
219
|
+
await downloadFile(url, archivePath);
|
|
220
|
+
console.log('✓ Download complete');
|
|
221
|
+
|
|
222
|
+
// Extract
|
|
223
|
+
console.log('Extracting archive...');
|
|
224
|
+
const extractDir = path.join(tempDir, 'extracted');
|
|
225
|
+
fs.mkdirSync(extractDir, { recursive: true });
|
|
226
|
+
extractArchive(archivePath, extractDir);
|
|
227
|
+
console.log('✓ Extraction complete');
|
|
228
|
+
|
|
229
|
+
// Find and copy library file
|
|
230
|
+
const libName = platformInfo.lib;
|
|
231
|
+
let libFound = false;
|
|
232
|
+
|
|
233
|
+
// Look for the library in various locations
|
|
234
|
+
const searchPaths = [
|
|
235
|
+
path.join(extractDir, libName),
|
|
236
|
+
path.join(extractDir, 'lib', libName),
|
|
237
|
+
];
|
|
238
|
+
|
|
239
|
+
// Also search for versioned libraries (e.g., libgopher-orch.so.0.1.0)
|
|
240
|
+
const files = fs.readdirSync(extractDir);
|
|
241
|
+
for (const file of files) {
|
|
242
|
+
if (file.startsWith(libName.replace(/\.[^.]+$/, ''))) {
|
|
243
|
+
searchPaths.push(path.join(extractDir, file));
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Check lib subdirectory too
|
|
248
|
+
const libDir = path.join(extractDir, 'lib');
|
|
249
|
+
if (fs.existsSync(libDir)) {
|
|
250
|
+
const libFiles = fs.readdirSync(libDir);
|
|
251
|
+
for (const file of libFiles) {
|
|
252
|
+
if (file.startsWith(libName.replace(/\.[^.]+$/, ''))) {
|
|
253
|
+
searchPaths.push(path.join(libDir, file));
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
for (const srcPath of searchPaths) {
|
|
259
|
+
if (fs.existsSync(srcPath) && fs.statSync(srcPath).isFile()) {
|
|
260
|
+
const destPath = path.join(nativeLibDir, path.basename(srcPath));
|
|
261
|
+
fs.copyFileSync(srcPath, destPath);
|
|
262
|
+
console.log(`✓ Installed: ${path.basename(srcPath)}`);
|
|
263
|
+
libFound = true;
|
|
264
|
+
|
|
265
|
+
// Create symlink for versioned libraries
|
|
266
|
+
if (platform !== 'win32' && srcPath !== path.join(extractDir, libName)) {
|
|
267
|
+
const symlinkPath = path.join(nativeLibDir, libName);
|
|
268
|
+
if (fs.existsSync(symlinkPath)) {
|
|
269
|
+
fs.unlinkSync(symlinkPath);
|
|
270
|
+
}
|
|
271
|
+
fs.symlinkSync(path.basename(srcPath), symlinkPath);
|
|
272
|
+
console.log(`✓ Created symlink: ${libName}`);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (!libFound) {
|
|
278
|
+
throw new Error(`Library file not found in archive: ${libName}`);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
console.log();
|
|
282
|
+
console.log('✓ Installation complete!');
|
|
283
|
+
console.log(` Library installed to: ${nativeLibDir}`);
|
|
284
|
+
} finally {
|
|
285
|
+
// Cleanup temp directory
|
|
286
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Parse command line arguments
|
|
291
|
+
function parseArgs() {
|
|
292
|
+
const args = process.argv.slice(2);
|
|
293
|
+
const options = {
|
|
294
|
+
version: DEFAULT_VERSION,
|
|
295
|
+
force: false,
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
for (let i = 0; i < args.length; i++) {
|
|
299
|
+
if (args[i] === '--version' || args[i] === '-v') {
|
|
300
|
+
options.version = args[++i];
|
|
301
|
+
} else if (args[i] === '--force' || args[i] === '-f') {
|
|
302
|
+
options.force = true;
|
|
303
|
+
} else if (args[i] === '--help' || args[i] === '-h') {
|
|
304
|
+
console.log('Usage: download-native.js [options]');
|
|
305
|
+
console.log();
|
|
306
|
+
console.log('Options:');
|
|
307
|
+
console.log(
|
|
308
|
+
' --version, -v <version> gopher-orch version (default: latest)'
|
|
309
|
+
);
|
|
310
|
+
console.log(' --force, -f Force re-download');
|
|
311
|
+
console.log(' --help, -h Show this help');
|
|
312
|
+
process.exit(0);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
return options;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// Run if called directly
|
|
320
|
+
if (require.main === module) {
|
|
321
|
+
const options = parseArgs();
|
|
322
|
+
downloadNative(options).catch((err) => {
|
|
323
|
+
console.error('Error:', err.message);
|
|
324
|
+
process.exit(1);
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
module.exports = { downloadNative };
|