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/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 };