ai-fly 0.4.0-alpha.4 → 0.4.0-alpha.6

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.
Files changed (48) hide show
  1. package/dist/ai-fly.js +6 -6
  2. package/dist/app/main.js +161 -0
  3. package/dist/{common-DGktbuQT.mjs → common-B6U1vLFw.mjs} +2 -2
  4. package/dist/{common-BerjPDN0.mjs → common-CwlJNk3L.mjs} +1 -1
  5. package/dist/{daemon-z7hZDf5X.mjs → daemon-iqO29D7K.mjs} +3 -3
  6. package/dist/{forget-zXXMWRPE.mjs → forget-BIorc8Rx.mjs} +2 -2
  7. package/dist/{group-DxTSU3w2.mjs → group-C13I2bCR.mjs} +1 -1
  8. package/dist/{hooks-Da7bL31j.mjs → hooks-BeBzkBL-.mjs} +2 -2
  9. package/dist/{import-DVD6ODYu.mjs → import-BhasJTGS.mjs} +4 -4
  10. package/dist/{join-BvMm1-Qz.mjs → join-BHhCLh9B.mjs} +3 -3
  11. package/dist/{join-BjpRt0Tj.mjs → join-DiVTFi59.mjs} +2 -2
  12. package/dist/{key-BvFO4hCw.mjs → key-DYeTZ7MI.mjs} +1 -1
  13. package/dist/{key-DHyfw_xd.mjs → key-DdZsNmo_.mjs} +3 -3
  14. package/dist/{local-test-CPOZODTW.mjs → local-test-B1ys1pNo.mjs} +1 -1
  15. package/dist/{models-dev-DhEP4LJH.mjs → models-dev-DPT_BK_V.mjs} +1 -1
  16. package/dist/{mux-BQ1w82tz.mjs → mux-DlwEK4Tt.mjs} +1 -1
  17. package/dist/{ports-Bs8NpX1c.mjs → ports-DDM5bbJg.mjs} +2 -2
  18. package/dist/{presets-B339R3JU.mjs → presets-Do5DWXfQ.mjs} +2 -2
  19. package/dist/{revoke-CA4VYdTU.mjs → revoke-6lrZkjN4.mjs} +2 -2
  20. package/dist/{rewrite-zdPePt_u.mjs → rewrite-vGrkDZx8.mjs} +2 -2
  21. package/dist/{route-test-D8se2bKr.mjs → route-test-DfGzFjKw.mjs} +3 -3
  22. package/dist/{rpc-contract-eOK7IGzh.mjs → rpc-contract-BXviZUtF.mjs} +26 -0
  23. package/dist/{run-Ckodfe9X.mjs → run-BLxeLngt.mjs} +3 -3
  24. package/dist/{runtime-CJWL72hJ.mjs → runtime-D8P29hIl.mjs} +2 -2
  25. package/dist/{secret-BTq8J0Oj.mjs → secret-Ds6pIoLP.mjs} +2 -2
  26. package/dist/secrets-G2HTT66T.mjs +2 -0
  27. package/dist/{secrets-BkwvIX0M.mjs → secrets-bHJBznMX.mjs} +2 -2
  28. package/dist/{serve-CEmNAhX5.mjs → serve-B4f79Eqq.mjs} +2 -2
  29. package/dist/{serve-CvGVQszo.mjs → serve-C8VRRJrt.mjs} +4 -4
  30. package/dist/{service-CBURGJU1.mjs → service-CYkpuJuc.mjs} +4 -4
  31. package/dist/{settings-BwDXTwUJ.mjs → settings-CSran7QD.mjs} +1 -1
  32. package/dist/{settings-D1Ukj8bF.mjs → settings-CY-bC0MJ.mjs} +2 -2
  33. package/dist/{share-CNYqhoFY.mjs → share-B94HhX_b.mjs} +4 -4
  34. package/dist/{status-bV9YPNmT.mjs → status-BFpr-LHB.mjs} +3 -3
  35. package/dist/{status-DlB1AHty.mjs → status-C_EI8-b9.mjs} +3 -3
  36. package/dist/{store-DUMRSQVn.mjs → store-DCLn0Df-.mjs} +1 -1
  37. package/dist/{store-z7qZO_5S.mjs → store-DxU0bd_u.mjs} +1 -1
  38. package/dist/{test-DtOSl9gb.mjs → test-BERWIlFb.mjs} +2 -2
  39. package/package.json +1 -1
  40. package/webui/dist/assets/index-YFHT6NZO.js +77 -0
  41. package/webui/dist/assets/{index-BGzZMfCg.css → index-tP1nMXNW.css} +1 -1
  42. package/webui/dist/icons/presets/anthropic.svg +5 -0
  43. package/webui/dist/icons/presets/codex.svg +5 -0
  44. package/webui/dist/icons/presets/deepseek.svg +5 -0
  45. package/webui/dist/icons/presets/openai.svg +5 -0
  46. package/webui/dist/index.html +2 -2
  47. package/dist/secrets-DtqxPHvY.mjs +0 -2
  48. package/webui/dist/assets/index-B52MRIjg.js +0 -74
package/dist/ai-fly.js CHANGED
@@ -63,7 +63,7 @@ async function dispatch(command, rest) {
63
63
  const lazy = (load) => {
64
64
  return (argv, ctx) => load().then((m) => m.run([...argv], ctx));
65
65
  };
66
- return match(command).with("serve", () => lazy(() => import("./serve-CEmNAhX5.mjs"))(rest)).with("app", async () => {
66
+ return match(command).with("serve", () => lazy(() => import("./serve-B4f79Eqq.mjs"))(rest)).with("app", async () => {
67
67
  const { join, dirname } = await import("node:path");
68
68
  const { fileURLToPath } = await import("node:url");
69
69
  const { spawn } = await import("node:child_process");
@@ -78,17 +78,17 @@ async function dispatch(command, rest) {
78
78
  return await new Promise((resolve) => {
79
79
  child.once("exit", (c) => resolve(c ?? 0));
80
80
  });
81
- }).with("daemon", () => lazy(() => import("./daemon-z7hZDf5X.mjs"))(rest)).with("presets", () => lazy(() => import("./presets-B339R3JU.mjs"))(rest)).with("hooks", () => lazy(() => import("./hooks-Da7bL31j.mjs"))(rest)).with("secret", () => lazy(() => import("./secret-BTq8J0Oj.mjs"))(rest)).with("settings", async () => (await import("./settings-BwDXTwUJ.mjs")).runAsSettings(rest, {})).with("relay", async () => (await import("./settings-BwDXTwUJ.mjs")).runAsRelay(rest, {})).with("test", () => lazy(() => import("./test-DtOSl9gb.mjs"))(rest)).with("service", () => lazy(() => import("./service-CBURGJU1.mjs"))(rest)).with("group", () => lazy(() => import("./group-DxTSU3w2.mjs"))(rest)).with("share", () => lazy(() => import("./share-CNYqhoFY.mjs"))(rest)).with("revoke", () => lazy(() => import("./revoke-CA4VYdTU.mjs"))(rest)).with("join", () => lazy(() => import("./join-BvMm1-Qz.mjs"))(rest)).with("import", () => lazy(() => import("./import-DVD6ODYu.mjs"))(rest)).with("run", () => lazy(() => import("./run-Ckodfe9X.mjs"))(rest)).with("ports", () => lazy(() => import("./ports-Bs8NpX1c.mjs"))(rest)).with("forget", () => lazy(() => import("./forget-zXXMWRPE.mjs"))(rest)).with("key", () => {
82
- if (rest[0] === "add") return lazy(() => import("./key-DHyfw_xd.mjs"))(rest);
83
- return lazy(() => import("./key-BvFO4hCw.mjs"))(rest);
81
+ }).with("daemon", () => lazy(() => import("./daemon-iqO29D7K.mjs"))(rest)).with("presets", () => lazy(() => import("./presets-Do5DWXfQ.mjs"))(rest)).with("hooks", () => lazy(() => import("./hooks-BeBzkBL-.mjs"))(rest)).with("secret", () => lazy(() => import("./secret-Ds6pIoLP.mjs"))(rest)).with("settings", async () => (await import("./settings-CSran7QD.mjs")).runAsSettings(rest, {})).with("relay", async () => (await import("./settings-CSran7QD.mjs")).runAsRelay(rest, {})).with("test", () => lazy(() => import("./test-BERWIlFb.mjs"))(rest)).with("service", () => lazy(() => import("./service-CYkpuJuc.mjs"))(rest)).with("group", () => lazy(() => import("./group-C13I2bCR.mjs"))(rest)).with("share", () => lazy(() => import("./share-B94HhX_b.mjs"))(rest)).with("revoke", () => lazy(() => import("./revoke-6lrZkjN4.mjs"))(rest)).with("join", () => lazy(() => import("./join-BHhCLh9B.mjs"))(rest)).with("import", () => lazy(() => import("./import-BhasJTGS.mjs"))(rest)).with("run", () => lazy(() => import("./run-BLxeLngt.mjs"))(rest)).with("ports", () => lazy(() => import("./ports-DDM5bbJg.mjs"))(rest)).with("forget", () => lazy(() => import("./forget-BIorc8Rx.mjs"))(rest)).with("key", () => {
82
+ if (rest[0] === "add") return lazy(() => import("./key-DdZsNmo_.mjs"))(rest);
83
+ return lazy(() => import("./key-DYeTZ7MI.mjs"))(rest);
84
84
  }).with("status", async () => {
85
85
  const [scope, ...tail] = rest;
86
86
  const wantProvider = scope === "provider" || scope !== "consumer" && providerDirExists();
87
87
  const wantConsumer = scope === "consumer" || scope !== "provider" && consumersRootExists();
88
88
  const argv = scope === "provider" || scope === "consumer" ? tail : rest;
89
89
  let code = 0;
90
- if (wantProvider) code = Math.max(code, await lazy(() => import("./status-bV9YPNmT.mjs"))(argv));
91
- if (wantConsumer) code = Math.max(code, await lazy(() => import("./status-DlB1AHty.mjs"))(argv));
90
+ if (wantProvider) code = Math.max(code, await lazy(() => import("./status-BFpr-LHB.mjs"))(argv));
91
+ if (wantConsumer) code = Math.max(code, await lazy(() => import("./status-C_EI8-b9.mjs"))(argv));
92
92
  if (!wantProvider && !wantConsumer) process.stdout.write("nothing to report: no provider storage and no imported consumers\n");
93
93
  return code;
94
94
  }).otherwise(() => {
package/dist/app/main.js CHANGED
@@ -378,6 +378,32 @@ const rpcContract = oc.errors(RpcErrorDefinitions).router({
378
378
  localPrefix: z.string().min(1).max(2048).optional()
379
379
  })).output(SERVICE_TEST_RESULT_SCHEMA)
380
380
  },
381
+ hooks: {
382
+ /** hooks 脚本清单(内建 + 用户库;fns = 命名规范发现的钩子函数)。 */
383
+ list: oc.input(z.object({})).output(z.object({ hooks: z.array(z.strictObject({
384
+ name: z.string(),
385
+ source: z.enum(["user", "builtin"]),
386
+ fns: z.array(z.string())
387
+ })) })),
388
+ /** 脚本内容查看(含 path)。 */
389
+ get: oc.input(z.strictObject({ name: z.string().min(1).max(64) })).output(z.strictObject({
390
+ name: z.string(),
391
+ source: z.enum(["user", "builtin"]),
392
+ path: z.string(),
393
+ content: z.string()
394
+ })),
395
+ /** 安装用户脚本(校验:可加载 + 至少一个导出函数;失败回滚)。 */
396
+ add: oc.input(z.strictObject({
397
+ name: z.string().min(1).max(64),
398
+ content: z.string().min(1).max(65536)
399
+ })).output(z.strictObject({
400
+ name: z.string(),
401
+ path: z.string(),
402
+ fns: z.array(z.string())
403
+ })),
404
+ /** 删除(仅用户库;内建拒绝)。 */
405
+ remove: oc.input(z.strictObject({ name: z.string().min(1).max(64) })).output(z.object({ removed: z.boolean() }))
406
+ },
381
407
  secrets: {
382
408
  /** 密钥库清单(仅名称与时间戳;值由设计不跨 RPC)。 */
383
409
  list: oc.input(z.object({})).output(z.object({ secrets: z.array(SECRET_ENTRY_SCHEMA) })),
@@ -2624,6 +2650,42 @@ function loadHookScript(name, home = homedir()) {
2624
2650
  } catch {}
2625
2651
  }
2626
2652
  }
2653
+ function dirScriptNames(dir) {
2654
+ try {
2655
+ return readdirSync(dir).filter((f) => f.endsWith(".cjs")).map((f) => f.slice(0, -4));
2656
+ } catch {
2657
+ return [];
2658
+ }
2659
+ }
2660
+ /** 枚举可用 hooks 脚本及其钩子清单(用户库优先;内建同名被覆盖不重复列出)。 */
2661
+ function discoverHooks(home = homedir()) {
2662
+ const paths = hookScriptPaths(home);
2663
+ const seen = /* @__PURE__ */ new Map();
2664
+ for (const name of dirScriptNames(paths.userDir)) {
2665
+ const mod = loadHookScript(name, home);
2666
+ if (mod === void 0) continue;
2667
+ seen.set(name, {
2668
+ name,
2669
+ source: "user",
2670
+ fns: exportedHookFns(mod)
2671
+ });
2672
+ }
2673
+ for (const name of dirScriptNames(paths.builtinDir)) {
2674
+ if (seen.has(name)) continue;
2675
+ const mod = loadHookScript(name, home);
2676
+ if (mod === void 0) continue;
2677
+ seen.set(name, {
2678
+ name,
2679
+ source: "builtin",
2680
+ fns: exportedHookFns(mod)
2681
+ });
2682
+ }
2683
+ return [...seen.values()].sort((a, b) => a.name.localeCompare(b.name));
2684
+ }
2685
+ /** 模块导出面的钩子函数名(typeof function 且非下划线开头)。 */
2686
+ function exportedHookFns(mod) {
2687
+ return Object.keys(mod).filter((k) => !k.startsWith("_") && typeof mod[k] === "function").sort();
2688
+ }
2627
2689
  function isAsyncIterable(v) {
2628
2690
  return v !== null && typeof v === "object" && Symbol.asyncIterator in v;
2629
2691
  }
@@ -2693,6 +2755,65 @@ async function resolveHookValue(fnName, opts) {
2693
2755
  if (typeof awaited !== "string" || awaited === "") throw new HookMissingError();
2694
2756
  return awaited;
2695
2757
  }
2758
+ /** 脚本名合法性(资源标识符;防路径逃逸)。 */
2759
+ function validHookName(name) {
2760
+ return /^[a-z][a-z0-9_-]{0,63}$/.test(name);
2761
+ }
2762
+ function userHookPath(name, home = homedir()) {
2763
+ return join(hookScriptPaths(home).userDir, `${name}.cjs`);
2764
+ }
2765
+ /**
2766
+ * 安装用户 hooks 脚本(写入 ~/.aifly/hooks/<name>.cjs 并校验可加载、
2767
+ * 至少导出一个钩子函数)。内建同名允许覆盖(用户库优先语义)。
2768
+ */
2769
+ function installUserHook(name, content, home = homedir()) {
2770
+ if (!validHookName(name)) throw new Error(`invalid hook script name '${name}' (lowercase identifier, 1-64 chars)`);
2771
+ const paths = hookScriptPaths(home);
2772
+ mkdirSync(paths.userDir, { recursive: true });
2773
+ const path = userHookPath(name, home);
2774
+ writeFileSync(path, content, { mode: 384 });
2775
+ const mod = loadHookScript(name, home);
2776
+ if (mod === void 0) {
2777
+ rmSync(path, { force: true });
2778
+ throw new Error("hook script failed to load (syntax error or non-object export)");
2779
+ }
2780
+ const fns = exportedHookFns(mod);
2781
+ if (fns.length === 0) {
2782
+ rmSync(path, { force: true });
2783
+ throw new Error("hook script exports no hook functions (named function exports required)");
2784
+ }
2785
+ return {
2786
+ name,
2787
+ path,
2788
+ fns
2789
+ };
2790
+ }
2791
+ /** 删除用户脚本(内建库不可删;未命中报错)。 */
2792
+ function removeUserHook(name, home = homedir()) {
2793
+ const path = userHookPath(name, home);
2794
+ if (!existsSync(path)) {
2795
+ const builtin = join(hookScriptPaths(home).builtinDir, `${name}.cjs`);
2796
+ if (existsSync(builtin)) throw new Error(`'${name}' is a builtin hook script (cannot be removed)`);
2797
+ throw new Error(`hook script '${name}' not found`);
2798
+ }
2799
+ rmSync(path, { force: true });
2800
+ return { path };
2801
+ }
2802
+ /** 读取用户脚本内容(get/show;内建脚本返回包内内容)。 */
2803
+ function readHookScript(name, home = homedir()) {
2804
+ const user = userHookPath(name, home);
2805
+ if (existsSync(user)) return {
2806
+ path: user,
2807
+ source: "user",
2808
+ content: readFileSync(user, "utf8")
2809
+ };
2810
+ const builtin = join(hookScriptPaths(home).builtinDir, `${name}.cjs`);
2811
+ if (existsSync(builtin)) return {
2812
+ path: builtin,
2813
+ source: "builtin",
2814
+ content: readFileSync(builtin, "utf8")
2815
+ };
2816
+ }
2696
2817
  //#endregion
2697
2818
  //#region src/provider/rewrite.ts
2698
2819
  /** 拼接/断言失败(protocol_error 语义)。 */
@@ -7696,6 +7817,44 @@ function createRpcRouter(deps) {
7696
7817
  list: rpc.provider.keys.list.handler(() => ({ keys: host.providerStore().listKeys().map(keyView) })),
7697
7818
  revoke: rpc.provider.keys.revoke.handler(({ input }) => ({ key: keyView(host.providerStore().revokeKey(input.keyId)) }))
7698
7819
  },
7820
+ hooks: {
7821
+ list: rpc.provider.hooks.list.handler(() => ({ hooks: discoverHooks(home()).map((h) => ({
7822
+ name: h.name,
7823
+ source: h.source,
7824
+ fns: h.fns
7825
+ })) })),
7826
+ get: rpc.provider.hooks.get.handler(({ input }) => {
7827
+ const found = readHookScript(input.name, home());
7828
+ if (found === void 0) throw new DomainError("NOT_FOUND", `error: hook script '${input.name}' not found`);
7829
+ return {
7830
+ name: input.name,
7831
+ source: found.source,
7832
+ path: found.path,
7833
+ content: found.content
7834
+ };
7835
+ }),
7836
+ add: rpc.provider.hooks.add.handler(({ input }) => {
7837
+ try {
7838
+ const installed = installUserHook(input.name, input.content, home());
7839
+ return {
7840
+ name: installed.name,
7841
+ path: installed.path,
7842
+ fns: installed.fns
7843
+ };
7844
+ } catch (err) {
7845
+ throw new DomainError("INVALID_INPUT", err.message);
7846
+ }
7847
+ }),
7848
+ remove: rpc.provider.hooks.remove.handler(({ input }) => {
7849
+ try {
7850
+ removeUserHook(input.name, home());
7851
+ return { removed: true };
7852
+ } catch (err) {
7853
+ const msg = err.message;
7854
+ throw new DomainError(msg.includes("not found") || msg.includes("builtin") ? "NOT_FOUND" : "INVALID_INPUT", msg);
7855
+ }
7856
+ })
7857
+ },
7699
7858
  secrets: {
7700
7859
  list: rpc.provider.secrets.list.handler(() => ({ secrets: SecretsStore.open(host.providerDataDir).list() })),
7701
7860
  set: rpc.provider.secrets.set.handler(({ input }) => ({ secret: SecretsStore.open(host.providerDataDir).set(input.name, input.value, { ...input.bearerPrefix !== void 0 ? { bearerPrefix: input.bearerPrefix } : {} }) })),
@@ -8690,6 +8849,8 @@ async function assembleApp(deps) {
8690
8849
  else {
8691
8850
  log.info(`tray + app window ready (v${readPackageVersion(root)})`);
8692
8851
  log.info(`ui entry (one-time token): ${uiUrl}`);
8852
+ const extraTokens = Number.parseInt(process.env.AIFLY_EXTRA_UI_TOKEN ?? "0", 10) || 0;
8853
+ for (let i = 0; i < extraTokens && i < 16; i += 1) log.info(`ui entry (extra one-time token): ${webServer.uiUrl(port)}`);
8693
8854
  }
8694
8855
  return {
8695
8856
  host,
@@ -1,7 +1,7 @@
1
1
  import { n as UsageError } from "./errors-BGtxPkM7.mjs";
2
2
  import { n as resolveRelayUrls, t as loadConfig } from "./config-BlZnFqx7.mjs";
3
- import { t as ProviderStore } from "./store-z7qZO_5S.mjs";
4
- import { t as loadSettings } from "./settings-D1Ukj8bF.mjs";
3
+ import { t as ProviderStore } from "./store-DxU0bd_u.mjs";
4
+ import { t as loadSettings } from "./settings-CY-bC0MJ.mjs";
5
5
  import { homedir } from "node:os";
6
6
  import { join } from "node:path";
7
7
  //#region src/cli/commands/provider/common.ts
@@ -1,6 +1,6 @@
1
1
  import { n as resolveRelayUrls, t as loadConfig } from "./config-BlZnFqx7.mjs";
2
2
  import { n as loadSdk, t as resolveHttpProxy } from "./proxy-D7VMUVEg.mjs";
3
- import { t as loadSettings } from "./settings-D1Ukj8bF.mjs";
3
+ import { t as loadSettings } from "./settings-CY-bC0MJ.mjs";
4
4
  import { homedir } from "node:os";
5
5
  //#region src/cli/commands/consumer/common.ts
6
6
  function ctxOut(ctx) {
@@ -1,8 +1,8 @@
1
1
  import { n as UsageError, r as reportCliError, t as CliError } from "./errors-BGtxPkM7.mjs";
2
2
  import { n as parseArgv } from "./args-CSxXW9eD.mjs";
3
- import { r as settingsPath, t as loadSettings } from "./settings-D1Ukj8bF.mjs";
3
+ import { r as settingsPath, t as loadSettings } from "./settings-CY-bC0MJ.mjs";
4
4
  import { a as killHard, c as terminateGracefully, i as isAlive, l as writeLastStart, n as daemonDir, o as readLastStart, r as ensureDaemonDir, s as readPid, t as clearPid, u as writePid } from "./daemon-state-CYkiW3SA.mjs";
5
- import { r as openStore } from "./common-DGktbuQT.mjs";
5
+ import { r as openStore } from "./common-B6U1vLFw.mjs";
6
6
  import { openSync, readFileSync } from "node:fs";
7
7
  import { homedir } from "node:os";
8
8
  import { isAbsolute, resolve } from "node:path";
@@ -99,7 +99,7 @@ async function start(startArgv, home) {
99
99
  process.on("exit", () => {
100
100
  clearPid(home);
101
101
  });
102
- const { run: serveRun } = await import("./serve-CEmNAhX5.mjs");
102
+ const { run: serveRun } = await import("./serve-B4f79Eqq.mjs");
103
103
  return serveRun([...startArgv], { homedir: home });
104
104
  }
105
105
  /** 后台 pid(活性核验;陈旧 pidfile 就地清理返回 null)。 */
@@ -1,7 +1,7 @@
1
1
  import { n as UsageError } from "./errors-BGtxPkM7.mjs";
2
2
  import { n as parseArgv } from "./args-CSxXW9eD.mjs";
3
- import { d as removeKeyring, n as consumersRoot } from "./store-DUMRSQVn.mjs";
4
- import { n as ctxHomedir, r as ctxOut } from "./common-BerjPDN0.mjs";
3
+ import { d as removeKeyring, n as consumersRoot } from "./store-DCLn0Df-.mjs";
4
+ import { n as ctxHomedir, r as ctxOut } from "./common-CwlJNk3L.mjs";
5
5
  import { homedir } from "node:os";
6
6
  //#region src/cli/commands/consumer/forget.ts
7
7
  async function run(argv, ctx = {}) {
@@ -1,6 +1,6 @@
1
1
  import { n as UsageError, r as reportCliError } from "./errors-BGtxPkM7.mjs";
2
2
  import { n as parseArgv } from "./args-CSxXW9eD.mjs";
3
- import { d as str, l as resolveDataDir, n as multi, r as openStore, s as parsePositiveInt } from "./common-DGktbuQT.mjs";
3
+ import { d as str, l as resolveDataDir, n as multi, r as openStore, s as parsePositiveInt } from "./common-B6U1vLFw.mjs";
4
4
  import { homedir } from "node:os";
5
5
  //#region src/cli/commands/provider/group.ts
6
6
  const SPEC = {
@@ -1,8 +1,8 @@
1
1
  import { n as UsageError, r as reportCliError } from "./errors-BGtxPkM7.mjs";
2
2
  import { n as parseArgv } from "./args-CSxXW9eD.mjs";
3
- import { d as str, l as resolveDataDir } from "./common-DGktbuQT.mjs";
3
+ import { d as str, l as resolveDataDir } from "./common-B6U1vLFw.mjs";
4
4
  import { a as removeUserHook, i as readHookScript, n as disposeHookSubscriptions, o as resolveHookValue, r as installUserHook, t as discoverHooks } from "./hook-CvAMGts4.mjs";
5
- import { t as SecretsStore } from "./secrets-BkwvIX0M.mjs";
5
+ import { t as SecretsStore } from "./secrets-bHJBznMX.mjs";
6
6
  import { readFileSync } from "node:fs";
7
7
  import { homedir } from "node:os";
8
8
  //#region src/cli/commands/provider/hooks.ts
@@ -1,9 +1,9 @@
1
1
  import { n as UsageError } from "./errors-BGtxPkM7.mjs";
2
2
  import { n as parseArgv } from "./args-CSxXW9eD.mjs";
3
- import { n as consumersRoot, s as listKeyrings } from "./store-DUMRSQVn.mjs";
4
- import { a as ringsForRun, i as printListeners, n as ctxHomedir, o as waitForSignals, r as ctxOut, t as createSdkFabricFactory } from "./common-BerjPDN0.mjs";
5
- import { a as importLink, i as formatLinkPreview, n as decodeShareLink, r as formatKeyringSummary } from "./join-BjpRt0Tj.mjs";
6
- import { n as createFabricProviderTransport, t as startEngine } from "./runtime-CJWL72hJ.mjs";
3
+ import { n as consumersRoot, s as listKeyrings } from "./store-DCLn0Df-.mjs";
4
+ import { a as ringsForRun, i as printListeners, n as ctxHomedir, o as waitForSignals, r as ctxOut, t as createSdkFabricFactory } from "./common-CwlJNk3L.mjs";
5
+ import { a as importLink, i as formatLinkPreview, n as decodeShareLink, r as formatKeyringSummary } from "./join-DiVTFi59.mjs";
6
+ import { n as createFabricProviderTransport, t as startEngine } from "./runtime-D8P29hIl.mjs";
7
7
  import { homedir } from "node:os";
8
8
  //#region src/cli/commands/consumer/import.ts
9
9
  async function run(argv, ctx = {}) {
@@ -1,8 +1,8 @@
1
1
  import { n as UsageError } from "./errors-BGtxPkM7.mjs";
2
2
  import { n as parseArgv } from "./args-CSxXW9eD.mjs";
3
- import { n as consumersRoot } from "./store-DUMRSQVn.mjs";
4
- import { n as ctxHomedir, r as ctxOut, t as createSdkFabricFactory } from "./common-BerjPDN0.mjs";
5
- import { o as joinDevice } from "./join-BjpRt0Tj.mjs";
3
+ import { n as consumersRoot } from "./store-DCLn0Df-.mjs";
4
+ import { n as ctxHomedir, r as ctxOut, t as createSdkFabricFactory } from "./common-CwlJNk3L.mjs";
5
+ import { o as joinDevice } from "./join-DiVTFi59.mjs";
6
6
  import { homedir } from "node:os";
7
7
  //#region src/cli/commands/consumer/join.ts
8
8
  async function run(argv, ctx = {}) {
@@ -1,7 +1,7 @@
1
1
  import { t as CliError } from "./errors-BGtxPkM7.mjs";
2
- import { o as decodeZ32, s as randomZ32 } from "./rpc-contract-eOK7IGzh.mjs";
2
+ import { o as decodeZ32, s as randomZ32 } from "./rpc-contract-BXviZUtF.mjs";
3
3
  import { l as SERVICE_ENTRY_SCHEMA } from "./frames-BDz8buix.mjs";
4
- import { a as hasFabricIdentity, c as loadKeyring, f as saveKeyring, h as upsertKey, i as findKeyringDir, l as mergeImportView, o as keyringDir, r as fabricDir } from "./store-DUMRSQVn.mjs";
4
+ import { a as hasFabricIdentity, c as loadKeyring, f as saveKeyring, h as upsertKey, i as findKeyringDir, l as mergeImportView, o as keyringDir, r as fabricDir } from "./store-DCLn0Df-.mjs";
5
5
  import { existsSync, mkdirSync, renameSync, rmSync } from "node:fs";
6
6
  import { join } from "node:path";
7
7
  import { z } from "zod";
@@ -1,6 +1,6 @@
1
1
  import { n as UsageError, r as reportCliError } from "./errors-BGtxPkM7.mjs";
2
2
  import { n as parseArgv } from "./args-CSxXW9eD.mjs";
3
- import { c as requireString, d as str, l as resolveDataDir, r as openStore } from "./common-DGktbuQT.mjs";
3
+ import { c as requireString, d as str, l as resolveDataDir, r as openStore } from "./common-B6U1vLFw.mjs";
4
4
  import { homedir } from "node:os";
5
5
  //#region src/cli/commands/provider/key.ts
6
6
  const SPEC = {
@@ -1,8 +1,8 @@
1
1
  import { n as UsageError } from "./errors-BGtxPkM7.mjs";
2
2
  import { n as parseArgv } from "./args-CSxXW9eD.mjs";
3
- import { n as consumersRoot } from "./store-DUMRSQVn.mjs";
4
- import { n as ctxHomedir, r as ctxOut } from "./common-BerjPDN0.mjs";
5
- import { r as formatKeyringSummary, t as addKey } from "./join-BjpRt0Tj.mjs";
3
+ import { n as consumersRoot } from "./store-DCLn0Df-.mjs";
4
+ import { n as ctxHomedir, r as ctxOut } from "./common-CwlJNk3L.mjs";
5
+ import { r as formatKeyringSummary, t as addKey } from "./join-DiVTFi59.mjs";
6
6
  import { homedir } from "node:os";
7
7
  //#region src/cli/commands/consumer/key.ts
8
8
  async function run(argv, ctx = {}) {
@@ -1,4 +1,4 @@
1
- import { n as ROUTE_LOCAL_PREFIX } from "./rpc-contract-eOK7IGzh.mjs";
1
+ import { n as ROUTE_LOCAL_PREFIX } from "./rpc-contract-BXviZUtF.mjs";
2
2
  //#region src/consumer/local-test.ts
3
3
  const DEFAULT_TIMEOUT_MS = 2e4;
4
4
  const BODY_EXCERPT_MAX = 2e3;
@@ -1,4 +1,4 @@
1
- import { t as PRESET_SCHEMA } from "./rpc-contract-eOK7IGzh.mjs";
1
+ import { t as PRESET_SCHEMA } from "./rpc-contract-BXviZUtF.mjs";
2
2
  import { mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
3
3
  import { homedir } from "node:os";
4
4
  import { dirname, join } from "node:path";
@@ -1,4 +1,4 @@
1
- import { s as randomZ32 } from "./rpc-contract-eOK7IGzh.mjs";
1
+ import { s as randomZ32 } from "./rpc-contract-BXviZUtF.mjs";
2
2
  import { a as FRAME_TYPE_NAME, d as isKnownFrameType, i as FRAME_TYPE, r as FRAME_HEADER_SCHEMAS, t as ERROR_CODE, u as classifySchemaFailure } from "./frames-BDz8buix.mjs";
3
3
  //#region src/wire/codec.ts
4
4
  const WIRE_MAGIC_PREFIX = "aifly";
@@ -1,7 +1,7 @@
1
1
  import { n as UsageError } from "./errors-BGtxPkM7.mjs";
2
2
  import { n as parseArgv } from "./args-CSxXW9eD.mjs";
3
- import { m as setPort, n as consumersRoot, s as listKeyrings } from "./store-DUMRSQVn.mjs";
4
- import { n as ctxHomedir, r as ctxOut } from "./common-BerjPDN0.mjs";
3
+ import { m as setPort, n as consumersRoot, s as listKeyrings } from "./store-DCLn0Df-.mjs";
4
+ import { n as ctxHomedir, r as ctxOut } from "./common-CwlJNk3L.mjs";
5
5
  import { i as validatePortArg, n as desiredPortFor } from "./ports-pI59MtmI.mjs";
6
6
  import { homedir } from "node:os";
7
7
  //#region src/cli/commands/consumer/ports.ts
@@ -1,7 +1,7 @@
1
1
  import { n as UsageError, r as reportCliError } from "./errors-BGtxPkM7.mjs";
2
2
  import { n as parseArgv } from "./args-CSxXW9eD.mjs";
3
- import { t as loadSettings } from "./settings-D1Ukj8bF.mjs";
4
- import { n as loadCuratedPresets, r as modelsDevCachePath, t as fetchModelsDevPresets } from "./models-dev-DhEP4LJH.mjs";
3
+ import { t as loadSettings } from "./settings-CY-bC0MJ.mjs";
4
+ import { n as loadCuratedPresets, r as modelsDevCachePath, t as fetchModelsDevPresets } from "./models-dev-DPT_BK_V.mjs";
5
5
  import { homedir } from "node:os";
6
6
  //#region src/cli/commands/provider/presets.ts
7
7
  const SPEC = { json: { type: "boolean" } };
@@ -1,8 +1,8 @@
1
1
  import { n as UsageError, r as reportCliError } from "./errors-BGtxPkM7.mjs";
2
2
  import { n as parseArgv } from "./args-CSxXW9eD.mjs";
3
3
  import { t as resolveHttpProxy } from "./proxy-D7VMUVEg.mjs";
4
- import { d as str, l as resolveDataDir, u as resolvedRelayUrls } from "./common-DGktbuQT.mjs";
5
- import { t as openExistingFabric } from "./serve-CvGVQszo.mjs";
4
+ import { d as str, l as resolveDataDir, u as resolvedRelayUrls } from "./common-B6U1vLFw.mjs";
5
+ import { t as openExistingFabric } from "./serve-C8VRRJrt.mjs";
6
6
  import { homedir } from "node:os";
7
7
  //#region src/cli/commands/provider/revoke.ts
8
8
  const SPEC = {
@@ -1,6 +1,6 @@
1
- import { a as routeLocalPrefix } from "./rpc-contract-eOK7IGzh.mjs";
1
+ import { a as routeLocalPrefix } from "./rpc-contract-BXviZUtF.mjs";
2
2
  import { n as FORBIDDEN_REQ_HEADER_NAMES } from "./frames-BDz8buix.mjs";
3
- import { a as parseUpstreamUrl, c as matchRequestPath, o as expandUriTemplate, s as compileMatchPattern } from "./store-z7qZO_5S.mjs";
3
+ import { a as parseUpstreamUrl, c as matchRequestPath, o as expandUriTemplate, s as compileMatchPattern } from "./store-DxU0bd_u.mjs";
4
4
  import { o as resolveHookValue } from "./hook-CvAMGts4.mjs";
5
5
  import "node:module";
6
6
  import "node:fs";
@@ -1,6 +1,6 @@
1
- import { n as ROUTE_LOCAL_PREFIX } from "./rpc-contract-eOK7IGzh.mjs";
2
- import { t as formProbe } from "./local-test-CPOZODTW.mjs";
3
- import { i as buildUpstreamRequest, t as PathNotOfferedError } from "./rewrite-zdPePt_u.mjs";
1
+ import { n as ROUTE_LOCAL_PREFIX } from "./rpc-contract-BXviZUtF.mjs";
2
+ import { t as formProbe } from "./local-test-B1ys1pNo.mjs";
3
+ import { i as buildUpstreamRequest, t as PathNotOfferedError } from "./rewrite-vGrkDZx8.mjs";
4
4
  //#region src/provider/route-test.ts
5
5
  const DEFAULT_TIMEOUT_MS = 2e4;
6
6
  const BODY_EXCERPT_MAX = 2e3;
@@ -412,6 +412,32 @@ oc.errors(RpcErrorDefinitions).router({
412
412
  localPrefix: z.string().min(1).max(2048).optional()
413
413
  })).output(SERVICE_TEST_RESULT_SCHEMA)
414
414
  },
415
+ hooks: {
416
+ /** hooks 脚本清单(内建 + 用户库;fns = 命名规范发现的钩子函数)。 */
417
+ list: oc.input(z.object({})).output(z.object({ hooks: z.array(z.strictObject({
418
+ name: z.string(),
419
+ source: z.enum(["user", "builtin"]),
420
+ fns: z.array(z.string())
421
+ })) })),
422
+ /** 脚本内容查看(含 path)。 */
423
+ get: oc.input(z.strictObject({ name: z.string().min(1).max(64) })).output(z.strictObject({
424
+ name: z.string(),
425
+ source: z.enum(["user", "builtin"]),
426
+ path: z.string(),
427
+ content: z.string()
428
+ })),
429
+ /** 安装用户脚本(校验:可加载 + 至少一个导出函数;失败回滚)。 */
430
+ add: oc.input(z.strictObject({
431
+ name: z.string().min(1).max(64),
432
+ content: z.string().min(1).max(65536)
433
+ })).output(z.strictObject({
434
+ name: z.string(),
435
+ path: z.string(),
436
+ fns: z.array(z.string())
437
+ })),
438
+ /** 删除(仅用户库;内建拒绝)。 */
439
+ remove: oc.input(z.strictObject({ name: z.string().min(1).max(64) })).output(z.object({ removed: z.boolean() }))
440
+ },
415
441
  secrets: {
416
442
  /** 密钥库清单(仅名称与时间戳;值由设计不跨 RPC)。 */
417
443
  list: oc.input(z.object({})).output(z.object({ secrets: z.array(SECRET_ENTRY_SCHEMA) })),
@@ -1,8 +1,8 @@
1
1
  import { n as UsageError, r as reportCliError, t as CliError } from "./errors-BGtxPkM7.mjs";
2
2
  import { n as parseArgv } from "./args-CSxXW9eD.mjs";
3
- import { n as consumersRoot, s as listKeyrings } from "./store-DUMRSQVn.mjs";
4
- import { a as ringsForRun, i as printListeners, n as ctxHomedir, o as waitForSignals, r as ctxOut, t as createSdkFabricFactory } from "./common-BerjPDN0.mjs";
5
- import { n as createFabricProviderTransport, t as startEngine } from "./runtime-CJWL72hJ.mjs";
3
+ import { n as consumersRoot, s as listKeyrings } from "./store-DCLn0Df-.mjs";
4
+ import { a as ringsForRun, i as printListeners, n as ctxHomedir, o as waitForSignals, r as ctxOut, t as createSdkFabricFactory } from "./common-CwlJNk3L.mjs";
5
+ import { n as createFabricProviderTransport, t as startEngine } from "./runtime-D8P29hIl.mjs";
6
6
  import { a as killHard, c as terminateGracefully, i as isAlive, l as writeLastStart, n as daemonDir, o as readLastStart, r as ensureDaemonDir, s as readPid, t as clearPid, u as writePid } from "./daemon-state-CYkiW3SA.mjs";
7
7
  import { openSync, readFileSync } from "node:fs";
8
8
  import { resolve } from "node:path";
@@ -1,6 +1,6 @@
1
1
  import { i as FRAME_TYPE, o as HTTP_METHODS } from "./frames-BDz8buix.mjs";
2
- import { c as loadKeyring, f as saveKeyring, p as setActualPorts, t as applyCatalog, u as reconcileKeyMetadata } from "./store-DUMRSQVn.mjs";
3
- import { i as splitBody, n as FabricWireAdapter, t as WireSession } from "./mux-BQ1w82tz.mjs";
2
+ import { c as loadKeyring, f as saveKeyring, p as setActualPorts, t as applyCatalog, u as reconcileKeyMetadata } from "./store-DCLn0Df-.mjs";
3
+ import { i as splitBody, n as FabricWireAdapter, t as WireSession } from "./mux-DlwEK4Tt.mjs";
4
4
  import { n as desiredPortFor, r as listenWithFallback, t as LOOPBACK_HOST } from "./ports-pI59MtmI.mjs";
5
5
  import { Hono } from "hono";
6
6
  import { createAdaptorServer } from "@hono/node-server";
@@ -1,7 +1,7 @@
1
1
  import { n as UsageError, r as reportCliError } from "./errors-BGtxPkM7.mjs";
2
2
  import { n as parseArgv } from "./args-CSxXW9eD.mjs";
3
- import { d as str, l as resolveDataDir } from "./common-DGktbuQT.mjs";
4
- import { t as SecretsStore } from "./secrets-BkwvIX0M.mjs";
3
+ import { d as str, l as resolveDataDir } from "./common-B6U1vLFw.mjs";
4
+ import { t as SecretsStore } from "./secrets-bHJBznMX.mjs";
5
5
  import { homedir } from "node:os";
6
6
  import process from "node:process";
7
7
  import { createInterface } from "node:readline";
@@ -0,0 +1,2 @@
1
+ import { t as SecretsStore } from "./secrets-bHJBznMX.mjs";
2
+ export { SecretsStore };
@@ -1,5 +1,5 @@
1
- import { r as SECRET_NAME_SCHEMA } from "./rpc-contract-eOK7IGzh.mjs";
2
- import { i as ensurePrivateDir, n as StoreError, r as atomicWriteFileSync } from "./store-z7qZO_5S.mjs";
1
+ import { r as SECRET_NAME_SCHEMA } from "./rpc-contract-BXviZUtF.mjs";
2
+ import { i as ensurePrivateDir, n as StoreError, r as atomicWriteFileSync } from "./store-DxU0bd_u.mjs";
3
3
  import { existsSync, readFileSync } from "node:fs";
4
4
  import { join } from "node:path";
5
5
  import { z } from "zod";
@@ -1,8 +1,8 @@
1
1
  import { n as UsageError, r as reportCliError } from "./errors-BGtxPkM7.mjs";
2
2
  import { n as parseArgv } from "./args-CSxXW9eD.mjs";
3
3
  import { t as resolveHttpProxy } from "./proxy-D7VMUVEg.mjs";
4
- import { d as str, l as resolveDataDir, u as resolvedRelayUrls } from "./common-DGktbuQT.mjs";
5
- import { n as startProviderDaemon } from "./serve-CvGVQszo.mjs";
4
+ import { d as str, l as resolveDataDir, u as resolvedRelayUrls } from "./common-B6U1vLFw.mjs";
5
+ import { n as startProviderDaemon } from "./serve-C8VRRJrt.mjs";
6
6
  import { homedir } from "node:os";
7
7
  //#region src/cli/commands/provider/serve.ts
8
8
  const SPEC = {
@@ -1,9 +1,9 @@
1
1
  import { c as RESP_META_HEADER_WHITELIST, i as FRAME_TYPE, s as REJECTED_CODE, t as ERROR_CODE } from "./frames-BDz8buix.mjs";
2
2
  import { n as loadSdk } from "./proxy-D7VMUVEg.mjs";
3
- import { i as ensurePrivateDir, r as atomicWriteFileSync, t as ProviderStore } from "./store-z7qZO_5S.mjs";
4
- import { n as FabricWireAdapter, r as DEFAULT_BODY_CHUNK_BYTES, t as WireSession } from "./mux-BQ1w82tz.mjs";
5
- import { t as SecretsStore } from "./secrets-BkwvIX0M.mjs";
6
- import { a as collectEnvVarNames, i as buildUpstreamRequest, n as RewriteError, r as SecretMissingError, s as buildServiceEntry, t as PathNotOfferedError } from "./rewrite-zdPePt_u.mjs";
3
+ import { i as ensurePrivateDir, r as atomicWriteFileSync, t as ProviderStore } from "./store-DxU0bd_u.mjs";
4
+ import { n as FabricWireAdapter, r as DEFAULT_BODY_CHUNK_BYTES, t as WireSession } from "./mux-DlwEK4Tt.mjs";
5
+ import { t as SecretsStore } from "./secrets-bHJBznMX.mjs";
6
+ import { a as collectEnvVarNames, i as buildUpstreamRequest, n as RewriteError, r as SecretMissingError, s as buildServiceEntry, t as PathNotOfferedError } from "./rewrite-vGrkDZx8.mjs";
7
7
  import { appendFileSync, existsSync, readFileSync, readdirSync, watch } from "node:fs";
8
8
  import "node:os";
9
9
  import { dirname, join } from "node:path";
@@ -1,7 +1,7 @@
1
1
  import { n as UsageError, r as reportCliError } from "./errors-BGtxPkM7.mjs";
2
2
  import { n as parseArgv } from "./args-CSxXW9eD.mjs";
3
- import { a as parseMatchSpec, d as str, i as parseHeaderSetSpec, l as resolveDataDir, n as multi, o as parsePortNumber, r as openStore, t as buildRewrite } from "./common-DGktbuQT.mjs";
4
- import { n as loadCuratedPresets } from "./models-dev-DhEP4LJH.mjs";
3
+ import { a as parseMatchSpec, d as str, i as parseHeaderSetSpec, l as resolveDataDir, n as multi, o as parsePortNumber, r as openStore, t as buildRewrite } from "./common-B6U1vLFw.mjs";
4
+ import { n as loadCuratedPresets } from "./models-dev-DPT_BK_V.mjs";
5
5
  import { homedir } from "node:os";
6
6
  //#region src/cli/commands/provider/service.ts
7
7
  const SPEC = {
@@ -225,8 +225,8 @@ async function test(options, positionals, home) {
225
225
  formRaw = (localPrefix !== void 0 ? routes.find((r) => r.localPrefix === localPrefix) : routes.length === 1 ? routes[0] : void 0)?.forms[0] ?? "openai-chat";
226
226
  }
227
227
  if (!ROUTE_FORMS.includes(formRaw)) throw new UsageError(`error: --form must be one of ${ROUTE_FORMS.join(", ")}`);
228
- const { testServiceRoute } = await import("./route-test-D8se2bKr.mjs");
229
- const { SecretsStore } = await import("./secrets-DtqxPHvY.mjs");
228
+ const { testServiceRoute } = await import("./route-test-DfGzFjKw.mjs");
229
+ const { SecretsStore } = await import("./secrets-G2HTT66T.mjs");
230
230
  const secretsStore = SecretsStore.open(dataDir);
231
231
  const hitLocalPrefix = options["local-prefix"] !== void 0 ? str(options["local-prefix"]) : (() => {
232
232
  const routes = (service.routes ?? []).filter((r) => r.mode !== "pattern");
@@ -1,6 +1,6 @@
1
1
  import { n as UsageError, r as reportCliError } from "./errors-BGtxPkM7.mjs";
2
2
  import { n as parseArgv } from "./args-CSxXW9eD.mjs";
3
- import { n as saveSettings, r as settingsPath, t as loadSettings } from "./settings-D1Ukj8bF.mjs";
3
+ import { n as saveSettings, r as settingsPath, t as loadSettings } from "./settings-CY-bC0MJ.mjs";
4
4
  import { homedir } from "node:os";
5
5
  //#region src/cli/commands/settings.ts
6
6
  const SPEC = { default: { type: "boolean" } };
@@ -1,5 +1,5 @@
1
- import { i as SETTINGS_SCHEMA } from "./rpc-contract-eOK7IGzh.mjs";
2
- import { i as ensurePrivateDir, r as atomicWriteFileSync } from "./store-z7qZO_5S.mjs";
1
+ import { i as SETTINGS_SCHEMA } from "./rpc-contract-BXviZUtF.mjs";
2
+ import { i as ensurePrivateDir, r as atomicWriteFileSync } from "./store-DxU0bd_u.mjs";
3
3
  import { readFileSync } from "node:fs";
4
4
  import { homedir } from "node:os";
5
5
  import { join } from "node:path";
@@ -2,10 +2,10 @@ import { r as reportCliError, t as CliError } from "./errors-BGtxPkM7.mjs";
2
2
  import { n as parseArgv, r as parseDurationMs, t as assertDurationRange } from "./args-CSxXW9eD.mjs";
3
3
  import { l as SERVICE_ENTRY_SCHEMA } from "./frames-BDz8buix.mjs";
4
4
  import { t as resolveHttpProxy } from "./proxy-D7VMUVEg.mjs";
5
- import { n as StoreError } from "./store-z7qZO_5S.mjs";
6
- import { c as requireString, d as str, l as resolveDataDir, r as openStore, u as resolvedRelayUrls } from "./common-DGktbuQT.mjs";
7
- import { t as openExistingFabric } from "./serve-CvGVQszo.mjs";
8
- import { s as buildServiceEntry } from "./rewrite-zdPePt_u.mjs";
5
+ import { n as StoreError } from "./store-DxU0bd_u.mjs";
6
+ import { c as requireString, d as str, l as resolveDataDir, r as openStore, u as resolvedRelayUrls } from "./common-B6U1vLFw.mjs";
7
+ import { t as openExistingFabric } from "./serve-C8VRRJrt.mjs";
8
+ import { s as buildServiceEntry } from "./rewrite-vGrkDZx8.mjs";
9
9
  import { homedir } from "node:os";
10
10
  import { z } from "zod";
11
11
  //#region src/provider/link.ts