@schuttdev/gigai 0.1.0-beta.16 → 0.1.0-beta.18

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,16 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- AuthStore
4
- } from "./chunk-OWDYY3IG.js";
5
- import {
6
- generatePairingCode,
7
- validateAndPair
8
- } from "./chunk-HN7WQY7K.js";
9
2
  import {
10
3
  ErrorCode,
11
4
  GigaiConfigSchema,
12
5
  GigaiError,
13
6
  decrypt,
7
+ encrypt,
14
8
  generateEncryptionKey
15
9
  } from "./chunk-HIKBVSBK.js";
16
10
 
@@ -21,7 +15,9 @@ import cors from "@fastify/cors";
21
15
  import rateLimit from "@fastify/rate-limit";
22
16
  import multipart from "@fastify/multipart";
23
17
  import fp from "fastify-plugin";
18
+ import { nanoid } from "nanoid";
24
19
  import { randomBytes } from "crypto";
20
+ import { nanoid as nanoid2 } from "nanoid";
25
21
  import fp2 from "fastify-plugin";
26
22
  import fp3 from "fastify-plugin";
27
23
  import { spawn } from "child_process";
@@ -37,7 +33,7 @@ import { spawn as spawn2 } from "child_process";
37
33
  import { writeFile, readFile as readFile2, unlink, mkdir } from "fs/promises";
38
34
  import { join as join2 } from "path";
39
35
  import { tmpdir } from "os";
40
- import { nanoid } from "nanoid";
36
+ import { nanoid as nanoid3 } from "nanoid";
41
37
  import { readFile as readFile3 } from "fs/promises";
42
38
  import { resolve as resolve3 } from "path";
43
39
  import { spawn as spawn3 } from "child_process";
@@ -55,6 +51,71 @@ import { resolve as resolve6, join as join3 } from "path";
55
51
  import { homedir, platform } from "os";
56
52
  import { execFile as execFile2 } from "child_process";
57
53
  import { promisify as promisify2 } from "util";
54
+ var AuthStore = class {
55
+ pairingCodes = /* @__PURE__ */ new Map();
56
+ sessions = /* @__PURE__ */ new Map();
57
+ cleanupInterval;
58
+ constructor() {
59
+ this.cleanupInterval = setInterval(() => this.cleanup(), 6e4);
60
+ }
61
+ // Pairing codes
62
+ addPairingCode(code, ttlSeconds) {
63
+ const entry = {
64
+ code,
65
+ expiresAt: Date.now() + ttlSeconds * 1e3,
66
+ used: false
67
+ };
68
+ this.pairingCodes.set(code, entry);
69
+ return entry;
70
+ }
71
+ getPairingCode(code) {
72
+ return this.pairingCodes.get(code);
73
+ }
74
+ markPairingCodeUsed(code) {
75
+ const entry = this.pairingCodes.get(code);
76
+ if (entry) {
77
+ entry.used = true;
78
+ }
79
+ }
80
+ // Sessions
81
+ createSession(orgUuid, ttlSeconds) {
82
+ const session = {
83
+ id: nanoid(32),
84
+ orgUuid,
85
+ token: nanoid(48),
86
+ expiresAt: Date.now() + ttlSeconds * 1e3,
87
+ lastActivity: Date.now()
88
+ };
89
+ this.sessions.set(session.token, session);
90
+ return session;
91
+ }
92
+ getSession(token) {
93
+ const session = this.sessions.get(token);
94
+ if (session) {
95
+ session.lastActivity = Date.now();
96
+ }
97
+ return session;
98
+ }
99
+ // Cleanup
100
+ cleanup() {
101
+ const now = Date.now();
102
+ for (const [key, code] of this.pairingCodes) {
103
+ if (code.expiresAt < now) {
104
+ this.pairingCodes.delete(key);
105
+ }
106
+ }
107
+ for (const [key, session] of this.sessions) {
108
+ if (session.expiresAt < now) {
109
+ this.sessions.delete(key);
110
+ }
111
+ }
112
+ }
113
+ destroy() {
114
+ clearInterval(this.cleanupInterval);
115
+ this.pairingCodes.clear();
116
+ this.sessions.clear();
117
+ }
118
+ };
58
119
  function connectWithToken(store, encryptedToken, orgUuid, encryptionKey, sessionTtlSeconds) {
59
120
  let payload;
60
121
  try {
@@ -94,6 +155,34 @@ function createAuthMiddleware(store) {
94
155
  request.session = session;
95
156
  };
96
157
  }
158
+ var PAIRING_CODE_LENGTH = 8;
159
+ var PAIRING_CODE_CHARS = "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ";
160
+ function generatePairingCode(store, ttlSeconds) {
161
+ let code = "";
162
+ const bytes = nanoid2(PAIRING_CODE_LENGTH);
163
+ for (let i = 0; i < PAIRING_CODE_LENGTH; i++) {
164
+ code += PAIRING_CODE_CHARS[bytes.charCodeAt(i) % PAIRING_CODE_CHARS.length];
165
+ }
166
+ store.addPairingCode(code, ttlSeconds);
167
+ return code;
168
+ }
169
+ function validateAndPair(store, code, orgUuid, encryptionKey, serverFingerprint) {
170
+ const entry = store.getPairingCode(code.toUpperCase());
171
+ if (!entry) {
172
+ throw new GigaiError(ErrorCode.PAIRING_INVALID, "Invalid pairing code");
173
+ }
174
+ if (entry.used) {
175
+ throw new GigaiError(ErrorCode.PAIRING_USED, "Pairing code already used");
176
+ }
177
+ if (entry.expiresAt < Date.now()) {
178
+ throw new GigaiError(ErrorCode.PAIRING_EXPIRED, "Pairing code expired");
179
+ }
180
+ store.markPairingCodeUsed(code.toUpperCase());
181
+ return encrypt(
182
+ { orgUuid, serverFingerprint, createdAt: Date.now() },
183
+ encryptionKey
184
+ );
185
+ }
97
186
  function registerAuthRoutes(server, store, config) {
98
187
  const serverFingerprint = randomBytes(16).toString("hex");
99
188
  server.post("/auth/pair", {
@@ -752,7 +841,7 @@ async function transferRoutes(server) {
752
841
  if (!data) {
753
842
  throw new GigaiError(ErrorCode.VALIDATION_ERROR, "No file uploaded");
754
843
  }
755
- const id = nanoid(16);
844
+ const id = nanoid3(16);
756
845
  const buffer = await data.toBuffer();
757
846
  const filePath = join2(TRANSFER_DIR, id);
758
847
  await writeFile(filePath, buffer);
@@ -1096,9 +1185,25 @@ async function runInit() {
1096
1185
  } catch {
1097
1186
  console.log(` Server starting in background (PID ${child.pid})`);
1098
1187
  }
1099
- const store = new AuthStore();
1100
- const code = generatePairingCode(store, config.auth.pairingTtlSeconds);
1101
- store.destroy();
1188
+ let code;
1189
+ const maxRetries = 5;
1190
+ for (let i = 0; i < maxRetries; i++) {
1191
+ try {
1192
+ const res = await fetch(`http://localhost:${port}/auth/pair/generate`);
1193
+ if (res.ok) {
1194
+ const data = await res.json();
1195
+ code = data.code;
1196
+ break;
1197
+ }
1198
+ } catch {
1199
+ await new Promise((r) => setTimeout(r, 1e3));
1200
+ }
1201
+ }
1202
+ if (!code) {
1203
+ console.log("\n Server is starting but not ready yet.");
1204
+ console.log(" Run 'gigai server pair' once it's up to get a pairing code.\n");
1205
+ return;
1206
+ }
1102
1207
  console.log(`
1103
1208
  Paste this into Claude to pair:
1104
1209
  `);
@@ -1228,17 +1333,25 @@ async function unwrapTool(name) {
1228
1333
  }
1229
1334
  async function generateServerPairingCode(configPath) {
1230
1335
  const { config } = await loadConfigFile(configPath);
1231
- const { AuthStore: AuthStore2 } = await import("./store-Y4V3TOYJ-GKOB6ANA.js");
1232
- const { generatePairingCode: generatePairingCode2 } = await import("./pairing-IGMDVOIZ-SZYYTKV3.js");
1233
- const store = new AuthStore2();
1234
- const code = generatePairingCode2(store, config.auth.pairingTtlSeconds);
1235
- console.log(`
1236
- Pairing code: ${code}`);
1237
- console.log(`Expires in ${config.auth.pairingTtlSeconds / 60} minutes.`);
1238
- console.log(`
1239
- Note: The server must be running for the client to use this code.`);
1240
- console.log(`For a live pairing code, use the server's /auth/pair/generate endpoint.`);
1241
- store.destroy();
1336
+ const port = config.server.port;
1337
+ try {
1338
+ const res = await fetch(`http://localhost:${port}/auth/pair/generate`);
1339
+ if (!res.ok) {
1340
+ const body = await res.text();
1341
+ throw new Error(`Server returned ${res.status}: ${body}`);
1342
+ }
1343
+ const data = await res.json();
1344
+ console.log(`
1345
+ Pairing code: ${data.code}`);
1346
+ console.log(`Expires in ${data.expiresIn / 60} minutes.`);
1347
+ } catch (e) {
1348
+ if (e.message.includes("fetch failed") || e.message.includes("ECONNREFUSED")) {
1349
+ console.error("Server is not running. Start it with: gigai server start");
1350
+ } else {
1351
+ console.error(`Error: ${e.message}`);
1352
+ }
1353
+ process.exitCode = 1;
1354
+ }
1242
1355
  }
1243
1356
  var execFileAsync2 = promisify2(execFile2);
1244
1357
  function getGigaiBin() {
package/dist/index.js CHANGED
@@ -577,7 +577,7 @@ function runCitty() {
577
577
  dev: { type: "boolean", description: "Development mode (no HTTPS)" }
578
578
  },
579
579
  async run({ args }) {
580
- const { startServer } = await import("./dist-GANOIL6Z.js");
580
+ const { startServer } = await import("./dist-4DHEQIOT.js");
581
581
  const extraArgs = [];
582
582
  if (args.config) extraArgs.push("--config", args.config);
583
583
  if (args.dev) extraArgs.push("--dev");
@@ -588,7 +588,7 @@ function runCitty() {
588
588
  init: defineCommand({
589
589
  meta: { name: "init", description: "Interactive setup wizard" },
590
590
  async run() {
591
- const { runInit } = await import("./dist-GANOIL6Z.js");
591
+ const { runInit } = await import("./dist-4DHEQIOT.js");
592
592
  await runInit();
593
593
  }
594
594
  }),
@@ -598,7 +598,7 @@ function runCitty() {
598
598
  config: { type: "string", alias: "c", description: "Config file path" }
599
599
  },
600
600
  async run({ args }) {
601
- const { generateServerPairingCode } = await import("./dist-GANOIL6Z.js");
601
+ const { generateServerPairingCode } = await import("./dist-4DHEQIOT.js");
602
602
  await generateServerPairingCode(args.config);
603
603
  }
604
604
  }),
@@ -608,14 +608,14 @@ function runCitty() {
608
608
  config: { type: "string", alias: "c", description: "Config file path" }
609
609
  },
610
610
  async run({ args }) {
611
- const { installDaemon } = await import("./dist-GANOIL6Z.js");
611
+ const { installDaemon } = await import("./dist-4DHEQIOT.js");
612
612
  await installDaemon(args.config);
613
613
  }
614
614
  }),
615
615
  uninstall: defineCommand({
616
616
  meta: { name: "uninstall", description: "Remove background service" },
617
617
  async run() {
618
- const { uninstallDaemon } = await import("./dist-GANOIL6Z.js");
618
+ const { uninstallDaemon } = await import("./dist-4DHEQIOT.js");
619
619
  await uninstallDaemon();
620
620
  }
621
621
  }),
@@ -642,21 +642,21 @@ function runCitty() {
642
642
  cli: defineCommand({
643
643
  meta: { name: "cli", description: "Wrap a CLI command" },
644
644
  async run() {
645
- const { wrapCli } = await import("./dist-GANOIL6Z.js");
645
+ const { wrapCli } = await import("./dist-4DHEQIOT.js");
646
646
  await wrapCli();
647
647
  }
648
648
  }),
649
649
  mcp: defineCommand({
650
650
  meta: { name: "mcp", description: "Wrap an MCP server" },
651
651
  async run() {
652
- const { wrapMcp } = await import("./dist-GANOIL6Z.js");
652
+ const { wrapMcp } = await import("./dist-4DHEQIOT.js");
653
653
  await wrapMcp();
654
654
  }
655
655
  }),
656
656
  script: defineCommand({
657
657
  meta: { name: "script", description: "Wrap a script" },
658
658
  async run() {
659
- const { wrapScript } = await import("./dist-GANOIL6Z.js");
659
+ const { wrapScript } = await import("./dist-4DHEQIOT.js");
660
660
  await wrapScript();
661
661
  }
662
662
  }),
@@ -666,7 +666,7 @@ function runCitty() {
666
666
  path: { type: "positional", description: "Path to config file", required: true }
667
667
  },
668
668
  async run({ args }) {
669
- const { wrapImport } = await import("./dist-GANOIL6Z.js");
669
+ const { wrapImport } = await import("./dist-4DHEQIOT.js");
670
670
  await wrapImport(args.path);
671
671
  }
672
672
  })
@@ -678,7 +678,7 @@ function runCitty() {
678
678
  name: { type: "positional", description: "Tool name", required: true }
679
679
  },
680
680
  async run({ args }) {
681
- const { unwrapTool } = await import("./dist-GANOIL6Z.js");
681
+ const { unwrapTool } = await import("./dist-4DHEQIOT.js");
682
682
  await unwrapTool(args.name);
683
683
  }
684
684
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schuttdev/gigai",
3
- "version": "0.1.0-beta.16",
3
+ "version": "0.1.0-beta.18",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "gigai": "dist/index.js"
@@ -30,7 +30,8 @@
30
30
  "@modelcontextprotocol/sdk": "^1.0.0",
31
31
  "@inquirer/prompts": "^7.0.0",
32
32
  "nanoid": "^5.0.0",
33
- "zod": "^3.22.0"
33
+ "zod": "^3.22.0",
34
+ "undici": "^6.0.0"
34
35
  },
35
36
  "devDependencies": {
36
37
  "@gigai/shared": "*",
@@ -1,42 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- ErrorCode,
4
- GigaiError,
5
- encrypt
6
- } from "./chunk-HIKBVSBK.js";
7
-
8
- // ../server/dist/chunk-54TEF6CS.mjs
9
- import { nanoid } from "nanoid";
10
- var PAIRING_CODE_LENGTH = 8;
11
- var PAIRING_CODE_CHARS = "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ";
12
- function generatePairingCode(store, ttlSeconds) {
13
- let code = "";
14
- const bytes = nanoid(PAIRING_CODE_LENGTH);
15
- for (let i = 0; i < PAIRING_CODE_LENGTH; i++) {
16
- code += PAIRING_CODE_CHARS[bytes.charCodeAt(i) % PAIRING_CODE_CHARS.length];
17
- }
18
- store.addPairingCode(code, ttlSeconds);
19
- return code;
20
- }
21
- function validateAndPair(store, code, orgUuid, encryptionKey, serverFingerprint) {
22
- const entry = store.getPairingCode(code.toUpperCase());
23
- if (!entry) {
24
- throw new GigaiError(ErrorCode.PAIRING_INVALID, "Invalid pairing code");
25
- }
26
- if (entry.used) {
27
- throw new GigaiError(ErrorCode.PAIRING_USED, "Pairing code already used");
28
- }
29
- if (entry.expiresAt < Date.now()) {
30
- throw new GigaiError(ErrorCode.PAIRING_EXPIRED, "Pairing code expired");
31
- }
32
- store.markPairingCodeUsed(code.toUpperCase());
33
- return encrypt(
34
- { orgUuid, serverFingerprint, createdAt: Date.now() },
35
- encryptionKey
36
- );
37
- }
38
-
39
- export {
40
- generatePairingCode,
41
- validateAndPair
42
- };
@@ -1,73 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // ../server/dist/chunk-RZTCSUFS.mjs
4
- import { nanoid } from "nanoid";
5
- var AuthStore = class {
6
- pairingCodes = /* @__PURE__ */ new Map();
7
- sessions = /* @__PURE__ */ new Map();
8
- cleanupInterval;
9
- constructor() {
10
- this.cleanupInterval = setInterval(() => this.cleanup(), 6e4);
11
- }
12
- // Pairing codes
13
- addPairingCode(code, ttlSeconds) {
14
- const entry = {
15
- code,
16
- expiresAt: Date.now() + ttlSeconds * 1e3,
17
- used: false
18
- };
19
- this.pairingCodes.set(code, entry);
20
- return entry;
21
- }
22
- getPairingCode(code) {
23
- return this.pairingCodes.get(code);
24
- }
25
- markPairingCodeUsed(code) {
26
- const entry = this.pairingCodes.get(code);
27
- if (entry) {
28
- entry.used = true;
29
- }
30
- }
31
- // Sessions
32
- createSession(orgUuid, ttlSeconds) {
33
- const session = {
34
- id: nanoid(32),
35
- orgUuid,
36
- token: nanoid(48),
37
- expiresAt: Date.now() + ttlSeconds * 1e3,
38
- lastActivity: Date.now()
39
- };
40
- this.sessions.set(session.token, session);
41
- return session;
42
- }
43
- getSession(token) {
44
- const session = this.sessions.get(token);
45
- if (session) {
46
- session.lastActivity = Date.now();
47
- }
48
- return session;
49
- }
50
- // Cleanup
51
- cleanup() {
52
- const now = Date.now();
53
- for (const [key, code] of this.pairingCodes) {
54
- if (code.expiresAt < now) {
55
- this.pairingCodes.delete(key);
56
- }
57
- }
58
- for (const [key, session] of this.sessions) {
59
- if (session.expiresAt < now) {
60
- this.sessions.delete(key);
61
- }
62
- }
63
- }
64
- destroy() {
65
- clearInterval(this.cleanupInterval);
66
- this.pairingCodes.clear();
67
- this.sessions.clear();
68
- }
69
- };
70
-
71
- export {
72
- AuthStore
73
- };
@@ -1,10 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- generatePairingCode,
4
- validateAndPair
5
- } from "./chunk-HN7WQY7K.js";
6
- import "./chunk-HIKBVSBK.js";
7
- export {
8
- generatePairingCode,
9
- validateAndPair
10
- };
@@ -1,7 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- AuthStore
4
- } from "./chunk-OWDYY3IG.js";
5
- export {
6
- AuthStore
7
- };