@schuttdev/gigai 0.2.5 → 0.2.7

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.
@@ -1,12 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- ErrorCode,
4
- GigaiConfigSchema,
5
- GigaiError,
6
- decrypt,
7
- encrypt,
8
- generateEncryptionKey
9
- } from "./chunk-7C3UYEKE.js";
10
2
 
11
3
  // ../server/dist/index.mjs
12
4
  import { parseArgs } from "util";
@@ -14,9 +6,270 @@ import Fastify from "fastify";
14
6
  import cors from "@fastify/cors";
15
7
  import rateLimit from "@fastify/rate-limit";
16
8
  import multipart from "@fastify/multipart";
9
+
10
+ // ../shared/dist/index.mjs
11
+ import { randomBytes, createCipheriv, createDecipheriv } from "crypto";
12
+ import { z } from "zod";
13
+ var ALGORITHM = "aes-256-gcm";
14
+ var IV_LENGTH = 12;
15
+ var TAG_LENGTH = 16;
16
+ function encrypt(payload, key) {
17
+ const keyBuffer = Buffer.from(key, "hex");
18
+ if (keyBuffer.length !== 32) {
19
+ throw new Error("Encryption key must be 32 bytes (64 hex chars)");
20
+ }
21
+ const iv = randomBytes(IV_LENGTH);
22
+ const cipher = createCipheriv(ALGORITHM, keyBuffer, iv, {
23
+ authTagLength: TAG_LENGTH
24
+ });
25
+ const plaintext = JSON.stringify(payload);
26
+ const encrypted = Buffer.concat([
27
+ cipher.update(plaintext, "utf8"),
28
+ cipher.final()
29
+ ]);
30
+ const tag = cipher.getAuthTag();
31
+ return {
32
+ iv: iv.toString("base64"),
33
+ ciphertext: encrypted.toString("base64"),
34
+ tag: tag.toString("base64")
35
+ };
36
+ }
37
+ function decrypt(encrypted, key) {
38
+ const keyBuffer = Buffer.from(key, "hex");
39
+ if (keyBuffer.length !== 32) {
40
+ throw new Error("Encryption key must be 32 bytes (64 hex chars)");
41
+ }
42
+ const iv = Buffer.from(encrypted.iv, "base64");
43
+ const ciphertext = Buffer.from(encrypted.ciphertext, "base64");
44
+ const tag = Buffer.from(encrypted.tag, "base64");
45
+ const decipher = createDecipheriv(ALGORITHM, keyBuffer, iv, {
46
+ authTagLength: TAG_LENGTH
47
+ });
48
+ decipher.setAuthTag(tag);
49
+ const decrypted = Buffer.concat([
50
+ decipher.update(ciphertext),
51
+ decipher.final()
52
+ ]);
53
+ return JSON.parse(decrypted.toString("utf8"));
54
+ }
55
+ function generateEncryptionKey() {
56
+ return randomBytes(32).toString("hex");
57
+ }
58
+ var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => {
59
+ ErrorCode2["PAIRING_EXPIRED"] = "PAIRING_EXPIRED";
60
+ ErrorCode2["PAIRING_INVALID"] = "PAIRING_INVALID";
61
+ ErrorCode2["PAIRING_USED"] = "PAIRING_USED";
62
+ ErrorCode2["TOKEN_INVALID"] = "TOKEN_INVALID";
63
+ ErrorCode2["TOKEN_DECRYPT_FAILED"] = "TOKEN_DECRYPT_FAILED";
64
+ ErrorCode2["ORG_MISMATCH"] = "ORG_MISMATCH";
65
+ ErrorCode2["SESSION_EXPIRED"] = "SESSION_EXPIRED";
66
+ ErrorCode2["SESSION_INVALID"] = "SESSION_INVALID";
67
+ ErrorCode2["AUTH_REQUIRED"] = "AUTH_REQUIRED";
68
+ ErrorCode2["TOOL_NOT_FOUND"] = "TOOL_NOT_FOUND";
69
+ ErrorCode2["EXEC_TIMEOUT"] = "EXEC_TIMEOUT";
70
+ ErrorCode2["EXEC_FAILED"] = "EXEC_FAILED";
71
+ ErrorCode2["HTTPS_REQUIRED"] = "HTTPS_REQUIRED";
72
+ ErrorCode2["RATE_LIMITED"] = "RATE_LIMITED";
73
+ ErrorCode2["VALIDATION_ERROR"] = "VALIDATION_ERROR";
74
+ ErrorCode2["INTERNAL_ERROR"] = "INTERNAL_ERROR";
75
+ ErrorCode2["MCP_ERROR"] = "MCP_ERROR";
76
+ ErrorCode2["MCP_NOT_CONNECTED"] = "MCP_NOT_CONNECTED";
77
+ ErrorCode2["TRANSFER_NOT_FOUND"] = "TRANSFER_NOT_FOUND";
78
+ ErrorCode2["TRANSFER_EXPIRED"] = "TRANSFER_EXPIRED";
79
+ ErrorCode2["PATH_NOT_ALLOWED"] = "PATH_NOT_ALLOWED";
80
+ ErrorCode2["COMMAND_NOT_ALLOWED"] = "COMMAND_NOT_ALLOWED";
81
+ return ErrorCode2;
82
+ })(ErrorCode || {});
83
+ var STATUS_CODES = {
84
+ [
85
+ "PAIRING_EXPIRED"
86
+ /* PAIRING_EXPIRED */
87
+ ]: 410,
88
+ [
89
+ "PAIRING_INVALID"
90
+ /* PAIRING_INVALID */
91
+ ]: 400,
92
+ [
93
+ "PAIRING_USED"
94
+ /* PAIRING_USED */
95
+ ]: 409,
96
+ [
97
+ "TOKEN_INVALID"
98
+ /* TOKEN_INVALID */
99
+ ]: 401,
100
+ [
101
+ "TOKEN_DECRYPT_FAILED"
102
+ /* TOKEN_DECRYPT_FAILED */
103
+ ]: 401,
104
+ [
105
+ "ORG_MISMATCH"
106
+ /* ORG_MISMATCH */
107
+ ]: 403,
108
+ [
109
+ "SESSION_EXPIRED"
110
+ /* SESSION_EXPIRED */
111
+ ]: 401,
112
+ [
113
+ "SESSION_INVALID"
114
+ /* SESSION_INVALID */
115
+ ]: 401,
116
+ [
117
+ "AUTH_REQUIRED"
118
+ /* AUTH_REQUIRED */
119
+ ]: 401,
120
+ [
121
+ "TOOL_NOT_FOUND"
122
+ /* TOOL_NOT_FOUND */
123
+ ]: 404,
124
+ [
125
+ "EXEC_TIMEOUT"
126
+ /* EXEC_TIMEOUT */
127
+ ]: 408,
128
+ [
129
+ "EXEC_FAILED"
130
+ /* EXEC_FAILED */
131
+ ]: 500,
132
+ [
133
+ "HTTPS_REQUIRED"
134
+ /* HTTPS_REQUIRED */
135
+ ]: 403,
136
+ [
137
+ "RATE_LIMITED"
138
+ /* RATE_LIMITED */
139
+ ]: 429,
140
+ [
141
+ "VALIDATION_ERROR"
142
+ /* VALIDATION_ERROR */
143
+ ]: 400,
144
+ [
145
+ "INTERNAL_ERROR"
146
+ /* INTERNAL_ERROR */
147
+ ]: 500,
148
+ [
149
+ "MCP_ERROR"
150
+ /* MCP_ERROR */
151
+ ]: 502,
152
+ [
153
+ "MCP_NOT_CONNECTED"
154
+ /* MCP_NOT_CONNECTED */
155
+ ]: 503,
156
+ [
157
+ "TRANSFER_NOT_FOUND"
158
+ /* TRANSFER_NOT_FOUND */
159
+ ]: 404,
160
+ [
161
+ "TRANSFER_EXPIRED"
162
+ /* TRANSFER_EXPIRED */
163
+ ]: 410,
164
+ [
165
+ "PATH_NOT_ALLOWED"
166
+ /* PATH_NOT_ALLOWED */
167
+ ]: 403,
168
+ [
169
+ "COMMAND_NOT_ALLOWED"
170
+ /* COMMAND_NOT_ALLOWED */
171
+ ]: 403
172
+ };
173
+ var GigaiError = class extends Error {
174
+ code;
175
+ statusCode;
176
+ details;
177
+ constructor(code, message, details) {
178
+ super(message);
179
+ this.name = "GigaiError";
180
+ this.code = code;
181
+ this.statusCode = STATUS_CODES[code];
182
+ this.details = details;
183
+ }
184
+ toJSON() {
185
+ return {
186
+ error: {
187
+ code: this.code,
188
+ message: this.message,
189
+ ...this.details !== void 0 && { details: this.details }
190
+ }
191
+ };
192
+ }
193
+ };
194
+ var TailscaleHttpsConfigSchema = z.object({
195
+ provider: z.literal("tailscale"),
196
+ funnelPort: z.number().optional()
197
+ });
198
+ var CloudflareHttpsConfigSchema = z.object({
199
+ provider: z.literal("cloudflare"),
200
+ tunnelName: z.string(),
201
+ domain: z.string().optional()
202
+ });
203
+ var ManualHttpsConfigSchema = z.object({
204
+ provider: z.literal("manual"),
205
+ certPath: z.string(),
206
+ keyPath: z.string()
207
+ });
208
+ var HttpsConfigSchema = z.discriminatedUnion("provider", [
209
+ TailscaleHttpsConfigSchema,
210
+ CloudflareHttpsConfigSchema,
211
+ ManualHttpsConfigSchema
212
+ ]);
213
+ var CliToolConfigSchema = z.object({
214
+ type: z.literal("cli"),
215
+ name: z.string(),
216
+ command: z.string(),
217
+ args: z.array(z.string()).optional(),
218
+ description: z.string(),
219
+ timeout: z.number().optional(),
220
+ cwd: z.string().optional(),
221
+ env: z.record(z.string()).optional()
222
+ });
223
+ var McpToolConfigSchema = z.object({
224
+ type: z.literal("mcp"),
225
+ name: z.string(),
226
+ command: z.string(),
227
+ args: z.array(z.string()).optional(),
228
+ description: z.string(),
229
+ env: z.record(z.string()).optional()
230
+ });
231
+ var ScriptToolConfigSchema = z.object({
232
+ type: z.literal("script"),
233
+ name: z.string(),
234
+ path: z.string(),
235
+ description: z.string(),
236
+ timeout: z.number().optional(),
237
+ interpreter: z.string().optional()
238
+ });
239
+ var BuiltinToolConfigSchema = z.object({
240
+ type: z.literal("builtin"),
241
+ name: z.string(),
242
+ builtin: z.enum(["filesystem", "shell"]),
243
+ description: z.string(),
244
+ config: z.record(z.unknown()).optional()
245
+ });
246
+ var ToolConfigSchema = z.discriminatedUnion("type", [
247
+ CliToolConfigSchema,
248
+ McpToolConfigSchema,
249
+ ScriptToolConfigSchema,
250
+ BuiltinToolConfigSchema
251
+ ]);
252
+ var AuthConfigSchema = z.object({
253
+ encryptionKey: z.string().length(64),
254
+ pairingTtlSeconds: z.number().default(300),
255
+ sessionTtlSeconds: z.number().default(14400)
256
+ });
257
+ var ServerConfigSchema = z.object({
258
+ port: z.number().default(7443),
259
+ host: z.string().default("0.0.0.0"),
260
+ https: HttpsConfigSchema.optional()
261
+ });
262
+ var GigaiConfigSchema = z.object({
263
+ serverName: z.string().optional(),
264
+ server: ServerConfigSchema,
265
+ auth: AuthConfigSchema,
266
+ tools: z.array(ToolConfigSchema).default([])
267
+ });
268
+
269
+ // ../server/dist/index.mjs
17
270
  import fp from "fastify-plugin";
18
271
  import { nanoid } from "nanoid";
19
- import { randomBytes } from "crypto";
272
+ import { randomBytes as randomBytes2 } from "crypto";
20
273
  import { hostname } from "os";
21
274
  import { nanoid as nanoid2 } from "nanoid";
22
275
  import fp2 from "fastify-plugin";
@@ -25,19 +278,19 @@ import { spawn } from "child_process";
25
278
  import fp4 from "fastify-plugin";
26
279
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
27
280
  import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
28
- import { readFile } from "fs/promises";
281
+ import { readFileSync } from "fs";
29
282
  import { resolve } from "path";
30
283
  import { readFile as fsReadFile, readdir } from "fs/promises";
31
284
  import { resolve as resolve2, relative, join } from "path";
32
285
  import { realpath } from "fs/promises";
33
286
  import { spawn as spawn2 } from "child_process";
34
- import { writeFile, readFile as readFile2, unlink, mkdir } from "fs/promises";
287
+ import { writeFile, readFile, unlink, mkdir } from "fs/promises";
35
288
  import { join as join2 } from "path";
36
289
  import { tmpdir } from "os";
37
290
  import { nanoid as nanoid3 } from "nanoid";
38
291
  import { execFile, spawn as spawn3 } from "child_process";
39
292
  import { promisify } from "util";
40
- import { readFile as readFile3 } from "fs/promises";
293
+ import { readFile as readFile2 } from "fs/promises";
41
294
  import { resolve as resolve3 } from "path";
42
295
  import { spawn as spawn4 } from "child_process";
43
296
  import { spawn as spawn5 } from "child_process";
@@ -47,7 +300,7 @@ import { resolve as resolve4 } from "path";
47
300
  import { execFile as execFile2, spawn as spawn6 } from "child_process";
48
301
  import { promisify as promisify2 } from "util";
49
302
  import { input as input2 } from "@inquirer/prompts";
50
- import { readFile as readFile4, writeFile as writeFile3 } from "fs/promises";
303
+ import { readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
51
304
  import { resolve as resolve5 } from "path";
52
305
  import { writeFile as writeFile4 } from "fs/promises";
53
306
  import { resolve as resolve6, join as join3 } from "path";
@@ -187,7 +440,7 @@ function validateAndPair(store, code, orgUuid, encryptionKey, serverFingerprint)
187
440
  );
188
441
  }
189
442
  function registerAuthRoutes(server, store, config) {
190
- const serverFingerprint = randomBytes(16).toString("hex");
443
+ const serverFingerprint = randomBytes2(16).toString("hex");
191
444
  const serverName = config.serverName ?? hostname();
192
445
  server.post("/auth/pair", {
193
446
  config: {
@@ -565,21 +818,21 @@ var mcpPlugin = fp4(async (server, opts) => {
565
818
  });
566
819
  }, { name: "mcp" });
567
820
  var startTime = Date.now();
821
+ var startupVersion = "0.0.0";
822
+ try {
823
+ const pkg = JSON.parse(
824
+ readFileSync(resolve(import.meta.dirname ?? ".", "../package.json"), "utf8")
825
+ );
826
+ startupVersion = pkg.version;
827
+ } catch {
828
+ }
568
829
  async function healthRoutes(server) {
569
830
  server.get("/health", {
570
831
  config: { skipAuth: true }
571
832
  }, async () => {
572
- let version = "0.1.0";
573
- try {
574
- const pkg = JSON.parse(
575
- await readFile(resolve(import.meta.dirname ?? ".", "../package.json"), "utf8")
576
- );
577
- version = pkg.version;
578
- } catch {
579
- }
580
833
  return {
581
834
  status: "ok",
582
- version,
835
+ version: startupVersion,
583
836
  uptime: Date.now() - startTime
584
837
  };
585
838
  });
@@ -872,7 +1125,7 @@ async function transferRoutes(server) {
872
1125
  transfers.delete(id);
873
1126
  throw new GigaiError(ErrorCode.TRANSFER_EXPIRED, "Transfer expired");
874
1127
  }
875
- const content = await readFile2(entry.path);
1128
+ const content = await readFile(entry.path);
876
1129
  reply.type(entry.mimeType).send(content);
877
1130
  });
878
1131
  }
@@ -969,7 +1222,7 @@ async function createServer(opts) {
969
1222
  var DEFAULT_CONFIG_PATH = "gigai.config.json";
970
1223
  async function loadConfig(path) {
971
1224
  const configPath = resolve3(path ?? DEFAULT_CONFIG_PATH);
972
- const raw = await readFile3(configPath, "utf8");
1225
+ const raw = await readFile2(configPath, "utf8");
973
1226
  const json = JSON.parse(raw);
974
1227
  return GigaiConfigSchema.parse(json);
975
1228
  }
@@ -1272,11 +1525,11 @@ async function runInit() {
1272
1525
  Paste this into Claude to pair:
1273
1526
  `);
1274
1527
  console.log(` \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`);
1275
- console.log(` Install the gigai CLI and pair with my server:
1528
+ console.log(` Install kon and pair with my server:
1276
1529
  `);
1277
1530
  console.log(` \`\`\`bash`);
1278
- console.log(` npm install -g @schuttdev/gigai`);
1279
- console.log(` gigai pair ${code} ${serverUrl}`);
1531
+ console.log(` npm install -g @schuttdev/kon`);
1532
+ console.log(` kon pair ${code} ${serverUrl}`);
1280
1533
  console.log(` \`\`\`
1281
1534
  `);
1282
1535
  console.log(` Then show me the skill file output so I can save it.`);
@@ -1288,7 +1541,7 @@ async function runInit() {
1288
1541
  }
1289
1542
  async function loadConfigFile(path) {
1290
1543
  const configPath = resolve5(path ?? "gigai.config.json");
1291
- const raw = await readFile4(configPath, "utf8");
1544
+ const raw = await readFile3(configPath, "utf8");
1292
1545
  const config = GigaiConfigSchema.parse(JSON.parse(raw));
1293
1546
  return { config, path: configPath };
1294
1547
  }
@@ -1363,7 +1616,7 @@ async function wrapScript() {
1363
1616
  }
1364
1617
  async function wrapImport(configFilePath) {
1365
1618
  const { config, path } = await loadConfigFile();
1366
- const raw = await readFile4(resolve5(configFilePath), "utf8");
1619
+ const raw = await readFile3(resolve5(configFilePath), "utf8");
1367
1620
  const desktopConfig = JSON.parse(raw);
1368
1621
  const mcpServers = desktopConfig.mcpServers ?? {};
1369
1622
  for (const [serverName, serverConfig] of Object.entries(mcpServers)) {