@schuttdev/gigai 0.1.0-beta.11 → 0.1.0-beta.13
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/{chunk-4XUWD3DZ.js → chunk-HIKBVSBK.js} +0 -8
- package/dist/{chunk-FN4LCKUA.js → chunk-HN7WQY7K.js} +1 -1
- package/dist/{dist-66IDK7VT.js → dist-SIS4UF2D.js} +102 -21
- package/dist/index.js +43 -10
- package/dist/{pairing-IGMDVOIZ-RA7GNFU7.js → pairing-IGMDVOIZ-SZYYTKV3.js} +2 -2
- package/package.json +1 -1
|
@@ -193,13 +193,6 @@ var CloudflareHttpsConfigSchema = z.object({
|
|
|
193
193
|
tunnelName: z.string(),
|
|
194
194
|
domain: z.string().optional()
|
|
195
195
|
});
|
|
196
|
-
var LetsEncryptHttpsConfigSchema = z.object({
|
|
197
|
-
provider: z.literal("letsencrypt"),
|
|
198
|
-
domain: z.string(),
|
|
199
|
-
email: z.string().email(),
|
|
200
|
-
certPath: z.string().optional(),
|
|
201
|
-
keyPath: z.string().optional()
|
|
202
|
-
});
|
|
203
196
|
var ManualHttpsConfigSchema = z.object({
|
|
204
197
|
provider: z.literal("manual"),
|
|
205
198
|
certPath: z.string(),
|
|
@@ -208,7 +201,6 @@ var ManualHttpsConfigSchema = z.object({
|
|
|
208
201
|
var HttpsConfigSchema = z.discriminatedUnion("provider", [
|
|
209
202
|
TailscaleHttpsConfigSchema,
|
|
210
203
|
CloudflareHttpsConfigSchema,
|
|
211
|
-
LetsEncryptHttpsConfigSchema,
|
|
212
204
|
ManualHttpsConfigSchema
|
|
213
205
|
]);
|
|
214
206
|
var CliToolConfigSchema = z.object({
|
|
@@ -5,14 +5,14 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
generatePairingCode,
|
|
7
7
|
validateAndPair
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-HN7WQY7K.js";
|
|
9
9
|
import {
|
|
10
10
|
ErrorCode,
|
|
11
11
|
GigaiConfigSchema,
|
|
12
12
|
GigaiError,
|
|
13
13
|
decrypt,
|
|
14
14
|
generateEncryptionKey
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-HIKBVSBK.js";
|
|
16
16
|
|
|
17
17
|
// ../server/dist/index.mjs
|
|
18
18
|
import { parseArgs } from "util";
|
|
@@ -40,6 +40,8 @@ import { tmpdir } from "os";
|
|
|
40
40
|
import { nanoid } from "nanoid";
|
|
41
41
|
import { readFile as readFile3 } from "fs/promises";
|
|
42
42
|
import { resolve as resolve3 } from "path";
|
|
43
|
+
import { spawn as spawn3 } from "child_process";
|
|
44
|
+
import { spawn as spawn4 } from "child_process";
|
|
43
45
|
import { input, select, checkbox, confirm } from "@inquirer/prompts";
|
|
44
46
|
import { writeFile as writeFile2 } from "fs/promises";
|
|
45
47
|
import { resolve as resolve4 } from "path";
|
|
@@ -828,6 +830,63 @@ async function loadConfig(path) {
|
|
|
828
830
|
const json = JSON.parse(raw);
|
|
829
831
|
return GigaiConfigSchema.parse(json);
|
|
830
832
|
}
|
|
833
|
+
function runCommand(command, args) {
|
|
834
|
+
return new Promise((resolve6, reject) => {
|
|
835
|
+
const child = spawn3(command, args, { shell: false, stdio: ["ignore", "pipe", "pipe"] });
|
|
836
|
+
const chunks = [];
|
|
837
|
+
child.stdout.on("data", (chunk) => chunks.push(chunk));
|
|
838
|
+
child.on("error", reject);
|
|
839
|
+
child.on("close", (exitCode) => {
|
|
840
|
+
resolve6({ stdout: Buffer.concat(chunks).toString("utf8").trim(), exitCode: exitCode ?? 1 });
|
|
841
|
+
});
|
|
842
|
+
});
|
|
843
|
+
}
|
|
844
|
+
async function getTailscaleStatus() {
|
|
845
|
+
try {
|
|
846
|
+
const { stdout, exitCode } = await runCommand("tailscale", ["status", "--json"]);
|
|
847
|
+
if (exitCode !== 0) return { online: false };
|
|
848
|
+
const status = JSON.parse(stdout);
|
|
849
|
+
return {
|
|
850
|
+
online: status.BackendState === "Running",
|
|
851
|
+
hostname: status.Self?.DNSName?.replace(/\.$/, "")
|
|
852
|
+
};
|
|
853
|
+
} catch {
|
|
854
|
+
return { online: false };
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
async function enableFunnel(port) {
|
|
858
|
+
const status = await getTailscaleStatus();
|
|
859
|
+
if (!status.online || !status.hostname) {
|
|
860
|
+
throw new Error("Tailscale is not running or not connected");
|
|
861
|
+
}
|
|
862
|
+
const { exitCode, stdout } = await runCommand("tailscale", [
|
|
863
|
+
"funnel",
|
|
864
|
+
"--bg",
|
|
865
|
+
`${port}`
|
|
866
|
+
]);
|
|
867
|
+
if (exitCode !== 0) {
|
|
868
|
+
throw new Error(`Failed to enable Tailscale Funnel: ${stdout}`);
|
|
869
|
+
}
|
|
870
|
+
return `https://${status.hostname}:${port}`;
|
|
871
|
+
}
|
|
872
|
+
async function disableFunnel(port) {
|
|
873
|
+
await runCommand("tailscale", ["funnel", "--bg", "off", `${port}`]);
|
|
874
|
+
}
|
|
875
|
+
function runTunnel(tunnelName, localPort) {
|
|
876
|
+
const child = spawn4("cloudflared", [
|
|
877
|
+
"tunnel",
|
|
878
|
+
"--url",
|
|
879
|
+
`http://localhost:${localPort}`,
|
|
880
|
+
"run",
|
|
881
|
+
tunnelName
|
|
882
|
+
], {
|
|
883
|
+
shell: false,
|
|
884
|
+
stdio: "ignore",
|
|
885
|
+
detached: true
|
|
886
|
+
});
|
|
887
|
+
child.unref();
|
|
888
|
+
return child;
|
|
889
|
+
}
|
|
831
890
|
var execFileAsync = promisify(execFile);
|
|
832
891
|
async function getTailscaleDnsName() {
|
|
833
892
|
try {
|
|
@@ -847,7 +906,6 @@ async function runInit() {
|
|
|
847
906
|
choices: [
|
|
848
907
|
{ name: "Tailscale Funnel (recommended)", value: "tailscale" },
|
|
849
908
|
{ name: "Cloudflare Tunnel", value: "cloudflare" },
|
|
850
|
-
{ name: "Let's Encrypt", value: "letsencrypt" },
|
|
851
909
|
{ name: "Manual (provide certs)", value: "manual" },
|
|
852
910
|
{ name: "None (dev mode only)", value: "none" }
|
|
853
911
|
]
|
|
@@ -876,22 +934,6 @@ async function runInit() {
|
|
|
876
934
|
};
|
|
877
935
|
break;
|
|
878
936
|
}
|
|
879
|
-
case "letsencrypt": {
|
|
880
|
-
const domain = await input({
|
|
881
|
-
message: "Domain name:",
|
|
882
|
-
required: true
|
|
883
|
-
});
|
|
884
|
-
const email = await input({
|
|
885
|
-
message: "Email for Let's Encrypt:",
|
|
886
|
-
required: true
|
|
887
|
-
});
|
|
888
|
-
httpsConfig = {
|
|
889
|
-
provider: "letsencrypt",
|
|
890
|
-
domain,
|
|
891
|
-
email
|
|
892
|
-
};
|
|
893
|
-
break;
|
|
894
|
-
}
|
|
895
937
|
case "manual": {
|
|
896
938
|
const certPath = await input({
|
|
897
939
|
message: "Path to TLS certificate:",
|
|
@@ -977,13 +1019,22 @@ async function runInit() {
|
|
|
977
1019
|
await writeFile2(configPath, JSON.stringify(config, null, 2) + "\n", { mode: 384 });
|
|
978
1020
|
console.log(`
|
|
979
1021
|
Config written to: ${configPath}`);
|
|
980
|
-
let serverUrl
|
|
1022
|
+
let serverUrl;
|
|
981
1023
|
if (httpsProvider === "tailscale") {
|
|
982
1024
|
const dnsName = await getTailscaleDnsName();
|
|
983
1025
|
if (dnsName) {
|
|
984
1026
|
serverUrl = `https://${dnsName}:${port}`;
|
|
985
1027
|
console.log(` Detected Tailscale URL: ${serverUrl}`);
|
|
986
1028
|
}
|
|
1029
|
+
} else if (httpsProvider === "cloudflare" && httpsConfig && "domain" in httpsConfig && httpsConfig.domain) {
|
|
1030
|
+
serverUrl = `https://${httpsConfig.domain}`;
|
|
1031
|
+
console.log(` Cloudflare URL: ${serverUrl}`);
|
|
1032
|
+
}
|
|
1033
|
+
if (!serverUrl) {
|
|
1034
|
+
serverUrl = await input({
|
|
1035
|
+
message: "Server URL (how clients will reach this server):",
|
|
1036
|
+
required: true
|
|
1037
|
+
});
|
|
987
1038
|
}
|
|
988
1039
|
const store = new AuthStore();
|
|
989
1040
|
const code = generatePairingCode(store, config.auth.pairingTtlSeconds);
|
|
@@ -1119,7 +1170,7 @@ async function unwrapTool(name) {
|
|
|
1119
1170
|
async function generateServerPairingCode(configPath) {
|
|
1120
1171
|
const { config } = await loadConfigFile(configPath);
|
|
1121
1172
|
const { AuthStore: AuthStore2 } = await import("./store-Y4V3TOYJ-GKOB6ANA.js");
|
|
1122
|
-
const { generatePairingCode: generatePairingCode2 } = await import("./pairing-IGMDVOIZ-
|
|
1173
|
+
const { generatePairingCode: generatePairingCode2 } = await import("./pairing-IGMDVOIZ-SZYYTKV3.js");
|
|
1123
1174
|
const store = new AuthStore2();
|
|
1124
1175
|
const code = generatePairingCode2(store, config.auth.pairingTtlSeconds);
|
|
1125
1176
|
console.log(`
|
|
@@ -1144,8 +1195,38 @@ async function startServer() {
|
|
|
1144
1195
|
const host = config.server.host;
|
|
1145
1196
|
await server.listen({ port, host });
|
|
1146
1197
|
server.log.info(`gigai server listening on ${host}:${port}`);
|
|
1198
|
+
let cfTunnel;
|
|
1199
|
+
const httpsProvider = config.server.https?.provider;
|
|
1200
|
+
if (httpsProvider === "tailscale") {
|
|
1201
|
+
try {
|
|
1202
|
+
const funnelUrl = await enableFunnel(port);
|
|
1203
|
+
server.log.info(`Tailscale Funnel enabled: ${funnelUrl}`);
|
|
1204
|
+
} catch (e) {
|
|
1205
|
+
server.log.error(`Failed to enable Tailscale Funnel: ${e.message}`);
|
|
1206
|
+
}
|
|
1207
|
+
} else if (httpsProvider === "cloudflare") {
|
|
1208
|
+
try {
|
|
1209
|
+
const tunnelName = config.server.https.tunnelName;
|
|
1210
|
+
cfTunnel = runTunnel(tunnelName, port);
|
|
1211
|
+
server.log.info(`Cloudflare Tunnel started: ${tunnelName}`);
|
|
1212
|
+
} catch (e) {
|
|
1213
|
+
server.log.error(`Failed to start Cloudflare Tunnel: ${e.message}`);
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1147
1216
|
const shutdown = async () => {
|
|
1148
1217
|
server.log.info("Shutting down...");
|
|
1218
|
+
if (httpsProvider === "tailscale") {
|
|
1219
|
+
try {
|
|
1220
|
+
await disableFunnel(port);
|
|
1221
|
+
} catch {
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
if (cfTunnel) {
|
|
1225
|
+
try {
|
|
1226
|
+
cfTunnel.kill();
|
|
1227
|
+
} catch {
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1149
1230
|
await server.close();
|
|
1150
1231
|
process.exit(0);
|
|
1151
1232
|
};
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
decodeJWTPayload
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-HIKBVSBK.js";
|
|
5
5
|
|
|
6
6
|
// src/index.ts
|
|
7
7
|
import { defineCommand, runMain } from "citty";
|
|
@@ -307,6 +307,25 @@ async function execTool(http, name, args, timeout) {
|
|
|
307
307
|
if (res.stderr) process.stderr.write(res.stderr);
|
|
308
308
|
process.exitCode = res.exitCode;
|
|
309
309
|
}
|
|
310
|
+
async function execMcpTool(http, tool, mcpTool, args) {
|
|
311
|
+
const res = await http.post("/exec/mcp", {
|
|
312
|
+
tool,
|
|
313
|
+
mcpTool,
|
|
314
|
+
args
|
|
315
|
+
});
|
|
316
|
+
for (const content of res.content) {
|
|
317
|
+
if (content.type === "text" && content.text) {
|
|
318
|
+
process.stdout.write(content.text + "\n");
|
|
319
|
+
} else if (content.type === "image") {
|
|
320
|
+
console.log(`[Image: ${content.mimeType}]`);
|
|
321
|
+
} else if (content.type === "resource") {
|
|
322
|
+
console.log(`[Resource: ${content.mimeType}]`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
if (res.isError) {
|
|
326
|
+
process.exitCode = 1;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
310
329
|
|
|
311
330
|
// src/transfer.ts
|
|
312
331
|
import { readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
|
|
@@ -408,7 +427,21 @@ if (mode === "client") {
|
|
|
408
427
|
try {
|
|
409
428
|
const { serverUrl, sessionToken } = await connect();
|
|
410
429
|
const http = createHttpClient(serverUrl, sessionToken);
|
|
411
|
-
await
|
|
430
|
+
const { tool: detail } = await fetchToolDetail(http, toolName);
|
|
431
|
+
if (detail.type === "mcp") {
|
|
432
|
+
const mcpToolName = toolArgs[0];
|
|
433
|
+
if (!mcpToolName) {
|
|
434
|
+
const toolNames = (detail.mcpTools ?? []).map((t) => ` ${t.name} \u2014 ${t.description}`);
|
|
435
|
+
console.log(`MCP tools for ${toolName}:
|
|
436
|
+
${toolNames.join("\n")}`);
|
|
437
|
+
} else {
|
|
438
|
+
const jsonArg = toolArgs.slice(1).join(" ");
|
|
439
|
+
const args = jsonArg ? JSON.parse(jsonArg) : {};
|
|
440
|
+
await execMcpTool(http, toolName, mcpToolName, args);
|
|
441
|
+
}
|
|
442
|
+
} else {
|
|
443
|
+
await execTool(http, toolName, toolArgs);
|
|
444
|
+
}
|
|
412
445
|
} catch (e) {
|
|
413
446
|
console.error(`Error: ${e.message}`);
|
|
414
447
|
process.exitCode = 1;
|
|
@@ -505,7 +538,7 @@ function runCitty() {
|
|
|
505
538
|
dev: { type: "boolean", description: "Development mode (no HTTPS)" }
|
|
506
539
|
},
|
|
507
540
|
async run({ args }) {
|
|
508
|
-
const { startServer } = await import("./dist-
|
|
541
|
+
const { startServer } = await import("./dist-SIS4UF2D.js");
|
|
509
542
|
const extraArgs = [];
|
|
510
543
|
if (args.config) extraArgs.push("--config", args.config);
|
|
511
544
|
if (args.dev) extraArgs.push("--dev");
|
|
@@ -516,7 +549,7 @@ function runCitty() {
|
|
|
516
549
|
init: defineCommand({
|
|
517
550
|
meta: { name: "init", description: "Interactive setup wizard" },
|
|
518
551
|
async run() {
|
|
519
|
-
const { runInit } = await import("./dist-
|
|
552
|
+
const { runInit } = await import("./dist-SIS4UF2D.js");
|
|
520
553
|
await runInit();
|
|
521
554
|
}
|
|
522
555
|
}),
|
|
@@ -526,7 +559,7 @@ function runCitty() {
|
|
|
526
559
|
config: { type: "string", alias: "c", description: "Config file path" }
|
|
527
560
|
},
|
|
528
561
|
async run({ args }) {
|
|
529
|
-
const { generateServerPairingCode } = await import("./dist-
|
|
562
|
+
const { generateServerPairingCode } = await import("./dist-SIS4UF2D.js");
|
|
530
563
|
await generateServerPairingCode(args.config);
|
|
531
564
|
}
|
|
532
565
|
}),
|
|
@@ -553,21 +586,21 @@ function runCitty() {
|
|
|
553
586
|
cli: defineCommand({
|
|
554
587
|
meta: { name: "cli", description: "Wrap a CLI command" },
|
|
555
588
|
async run() {
|
|
556
|
-
const { wrapCli } = await import("./dist-
|
|
589
|
+
const { wrapCli } = await import("./dist-SIS4UF2D.js");
|
|
557
590
|
await wrapCli();
|
|
558
591
|
}
|
|
559
592
|
}),
|
|
560
593
|
mcp: defineCommand({
|
|
561
594
|
meta: { name: "mcp", description: "Wrap an MCP server" },
|
|
562
595
|
async run() {
|
|
563
|
-
const { wrapMcp } = await import("./dist-
|
|
596
|
+
const { wrapMcp } = await import("./dist-SIS4UF2D.js");
|
|
564
597
|
await wrapMcp();
|
|
565
598
|
}
|
|
566
599
|
}),
|
|
567
600
|
script: defineCommand({
|
|
568
601
|
meta: { name: "script", description: "Wrap a script" },
|
|
569
602
|
async run() {
|
|
570
|
-
const { wrapScript } = await import("./dist-
|
|
603
|
+
const { wrapScript } = await import("./dist-SIS4UF2D.js");
|
|
571
604
|
await wrapScript();
|
|
572
605
|
}
|
|
573
606
|
}),
|
|
@@ -577,7 +610,7 @@ function runCitty() {
|
|
|
577
610
|
path: { type: "positional", description: "Path to config file", required: true }
|
|
578
611
|
},
|
|
579
612
|
async run({ args }) {
|
|
580
|
-
const { wrapImport } = await import("./dist-
|
|
613
|
+
const { wrapImport } = await import("./dist-SIS4UF2D.js");
|
|
581
614
|
await wrapImport(args.path);
|
|
582
615
|
}
|
|
583
616
|
})
|
|
@@ -589,7 +622,7 @@ function runCitty() {
|
|
|
589
622
|
name: { type: "positional", description: "Tool name", required: true }
|
|
590
623
|
},
|
|
591
624
|
async run({ args }) {
|
|
592
|
-
const { unwrapTool } = await import("./dist-
|
|
625
|
+
const { unwrapTool } = await import("./dist-SIS4UF2D.js");
|
|
593
626
|
await unwrapTool(args.name);
|
|
594
627
|
}
|
|
595
628
|
});
|