ai-fly 0.0.0 → 0.1.1

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.
@@ -0,0 +1,46 @@
1
+ import { n as UsageError } from "./errors-BGtxPkM7.mjs";
2
+ import { o as parseArgv } from "./config-CO3WyW2H.mjs";
3
+ import { c as consumersRoot, n as ctxHomedir, p as listKeyrings, r as ctxOut, y as setPort } from "./common-4VeA_3wo.mjs";
4
+ import { i as validatePortArg, n as desiredPortFor } from "./ports-pI59MtmI.mjs";
5
+ import { homedir } from "node:os";
6
+ //#region src/cli/commands/consumer/ports.ts
7
+ async function run(argv, ctx = {}) {
8
+ const { options, positionals } = parseArgv(argv, {
9
+ data: {
10
+ type: "string",
11
+ tilde: true
12
+ },
13
+ port: { type: "string" }
14
+ }, { homedir: ctx.homedir ?? homedir() });
15
+ const out = ctxOut(ctx);
16
+ const root = consumersRoot(options.data, ctxHomedir(ctx));
17
+ const { rings, warnings } = listKeyrings(root);
18
+ for (const w of warnings) out(`warning: ${w}`);
19
+ const serviceId = positionals[0];
20
+ if (serviceId === void 0) {
21
+ if (rings.length === 0) {
22
+ out("no providers imported yet");
23
+ return 0;
24
+ }
25
+ for (const ring of rings) {
26
+ out(`provider ${ring.alias} (${ring.endpointId}):`);
27
+ if (ring.services.length === 0) out(" (no services known yet - run the gateway to fetch the catalog)");
28
+ for (const s of ring.services) {
29
+ const pinned = ring.ports[s.serviceId] !== void 0;
30
+ out(` ${s.serviceId} ${s.name} port ${desiredPortFor(s, ring.ports)} [${pinned ? "pinned" : `default ${s.defaultPort}`}]`);
31
+ }
32
+ }
33
+ return 0;
34
+ }
35
+ const rawPort = options.port;
36
+ if (rawPort === void 0) throw new UsageError(`error: --port is required when a serviceId is given\nusage: ai-fly ports <serviceId> --port <n>`);
37
+ const port = validatePortArg(rawPort);
38
+ const owner = rings.find((r) => r.services.some((s) => s.serviceId === serviceId));
39
+ if (owner === void 0) throw new UsageError(`error: unknown service '${serviceId}' (see 'ai-fly ports' for the list)`);
40
+ setPort(root, owner.endpointId, serviceId, port);
41
+ out(`service ${serviceId} (${owner.alias}) pinned to port ${port}`);
42
+ out("note: a running gateway picks this up on next start");
43
+ return 0;
44
+ }
45
+ //#endregion
46
+ export { run };
@@ -0,0 +1,68 @@
1
+ import { n as UsageError } from "./errors-BGtxPkM7.mjs";
2
+ //#region src/consumer/ports.ts
3
+ const LOOPBACK_HOST = "127.0.0.1";
4
+ /** 解析服务期望端口:显式偏好(keyring.ports)优先,缺省取服务 defaultPort。 */
5
+ function desiredPortFor(service, ports) {
6
+ const pinned = ports[service.serviceId];
7
+ if (pinned !== void 0) return pinned;
8
+ return service.defaultPort;
9
+ }
10
+ function listenOnce(server, port) {
11
+ return new Promise((resolve, reject) => {
12
+ const onErr = (err) => {
13
+ server.off("listening", onOk);
14
+ reject(err);
15
+ };
16
+ const onOk = () => {
17
+ server.off("error", onErr);
18
+ const addr = server.address();
19
+ resolve(typeof addr === "object" && addr !== null ? addr.port : port);
20
+ };
21
+ server.once("error", onErr);
22
+ server.once("listening", onOk);
23
+ server.listen({
24
+ host: LOOPBACK_HOST,
25
+ port
26
+ });
27
+ });
28
+ }
29
+ function isPortUnavailable(err) {
30
+ const e = err;
31
+ return e?.code === "EADDRINUSE" || e?.code === "EACCES" || e?.code === "EADDRNOTAVAIL";
32
+ }
33
+ /**
34
+ * 在 127.0.0.1 上监听:冲突(占用/特权)时 strict 即报错;否则错开为系统分配端口,
35
+ * 返回 autoAssigned=true 与原因(调用方显著标注)。desired=0 直接请求系统分配。
36
+ */
37
+ async function listenWithFallback(server, opts) {
38
+ try {
39
+ const port = await listenOnce(server, opts.desired);
40
+ if (opts.desired === 0) return {
41
+ port,
42
+ requested: 0,
43
+ autoAssigned: true,
44
+ reason: "requested system-assigned port (0)"
45
+ };
46
+ return {
47
+ port,
48
+ requested: opts.desired,
49
+ autoAssigned: false
50
+ };
51
+ } catch (err) {
52
+ if (!isPortUnavailable(err) || opts.strict) throw err;
53
+ return {
54
+ port: await listenOnce(server, 0),
55
+ requested: opts.desired,
56
+ autoAssigned: true,
57
+ reason: `port ${opts.desired} unavailable (${err.code ?? "in use"})`
58
+ };
59
+ }
60
+ }
61
+ /** ports 命令 --port 值校验:整数 1..65535(0 仅运行期分配语义,不可持久化)。 */
62
+ function validatePortArg(raw) {
63
+ const n = Number(raw);
64
+ if (!Number.isInteger(n) || n < 1 || n > 65535) throw new UsageError(`error: invalid port '${raw}' (expected integer 1..65535)`);
65
+ return n;
66
+ }
67
+ //#endregion
68
+ export { validatePortArg as i, desiredPortFor as n, listenWithFallback as r, LOOPBACK_HOST as t };
@@ -0,0 +1,34 @@
1
+ import { n as UsageError, r as reportCliError } from "./errors-BGtxPkM7.mjs";
2
+ import { o as parseArgv } from "./config-CO3WyW2H.mjs";
3
+ import { d as str, l as resolveDataDir, u as resolvedRelayUrls } from "./common-BULbPtYn.mjs";
4
+ import { t as openExistingFabric } from "./serve-DuyQMeJh.mjs";
5
+ import { homedir } from "node:os";
6
+ //#region src/cli/commands/provider/revoke.ts
7
+ const SPEC = {
8
+ data: {
9
+ type: "string",
10
+ tilde: true
11
+ },
12
+ relay: { type: "multi" }
13
+ };
14
+ async function run(argv, ctx = {}) {
15
+ let fabric;
16
+ try {
17
+ const home = ctx.homedir ?? homedir();
18
+ const { options, positionals } = parseArgv(argv, SPEC, { homedir: home });
19
+ const endpointId = positionals[0];
20
+ if (endpointId === void 0 || endpointId === "") throw new UsageError("error: revoke requires an <endpointId> argument");
21
+ if (positionals.length > 1) throw new UsageError(`error: unexpected argument '${positionals[1]}'`);
22
+ const dataDir = resolveDataDir(str(options.data), home);
23
+ fabric = await openExistingFabric(dataDir, resolvedRelayUrls(options, home));
24
+ await fabric.revoke(endpointId);
25
+ process.stdout.write(`member revoked: ${endpointId}\n`);
26
+ return 0;
27
+ } catch (err) {
28
+ return reportCliError(err);
29
+ } finally {
30
+ await fabric?.shutdown().catch(() => void 0);
31
+ }
32
+ }
33
+ //#endregion
34
+ export { run };
@@ -0,0 +1,42 @@
1
+ import { t as CliError } from "./errors-BGtxPkM7.mjs";
2
+ import { o as parseArgv } from "./config-CO3WyW2H.mjs";
3
+ import { a as ringsForRun, c as consumersRoot, i as printListeners, n as ctxHomedir, o as waitForSignals, p as listKeyrings, r as ctxOut, t as createSdkFabricFactory } from "./common-4VeA_3wo.mjs";
4
+ import { n as createFabricProviderTransport, t as startEngine } from "./runtime-Dg4en1D8.mjs";
5
+ import { homedir } from "node:os";
6
+ //#region src/cli/commands/consumer/run.ts
7
+ async function run(argv, ctx = {}) {
8
+ const { options } = parseArgv(argv, {
9
+ data: {
10
+ type: "string",
11
+ tilde: true
12
+ },
13
+ "strict-ports": { type: "boolean" },
14
+ relay: { type: "multi" }
15
+ }, { homedir: ctx.homedir ?? homedir() });
16
+ const out = ctxOut(ctx);
17
+ const root = consumersRoot(options.data, ctxHomedir(ctx));
18
+ const { rings, warnings } = listKeyrings(root);
19
+ for (const w of warnings) out(`warning: ${w}`);
20
+ const engineRings = ringsForRun(rings);
21
+ if (engineRings.length === 0) throw new CliError("error: no imported providers - run 'ai-fly import <aifly1-link>' or 'ai-fly join <token>' first");
22
+ const factory = await createSdkFabricFactory(options.relay, ctx);
23
+ const engine = await startEngine({
24
+ rings: engineRings,
25
+ consumersRoot: root,
26
+ sessionFactoryFor: (ring) => createFabricProviderTransport(factory, {
27
+ dataDir: `${root}/${ring.endpointId.slice(0, 8)}/fabric`,
28
+ providerEndpointId: ring.endpointId,
29
+ ...ring.relayUrls.length > 0 ? { relayUrls: ring.relayUrls } : {}
30
+ }),
31
+ strictPorts: options["strict-ports"] === true,
32
+ onNotice: out
33
+ });
34
+ printListeners(out, engine.gateway.listenerInfo());
35
+ out("gateway running - press Ctrl-C to stop");
36
+ await waitForSignals();
37
+ await engine.stop();
38
+ out("gateway stopped");
39
+ return 0;
40
+ }
41
+ //#endregion
42
+ export { run };