ai-fly 0.4.0-alpha.8 → 0.4.0
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/ai-fly.js +6 -6
- package/dist/app/main.js +60 -17
- package/dist/{common-B6U1vLFw.mjs → common-C51SAE5f.mjs} +2 -2
- package/dist/{common-CwlJNk3L.mjs → common-CanLn0Qt.mjs} +1 -1
- package/dist/{daemon-iqO29D7K.mjs → daemon-BWgyJMyB.mjs} +3 -3
- package/dist/{forget-BIorc8Rx.mjs → forget-B3KRkHho.mjs} +2 -2
- package/dist/{group-C13I2bCR.mjs → group-BdnvRD2t.mjs} +1 -1
- package/dist/{hooks-BeBzkBL-.mjs → hooks-DUrXA7PL.mjs} +2 -2
- package/dist/{import-BhasJTGS.mjs → import-CTkKGPsa.mjs} +4 -4
- package/dist/{join-DiVTFi59.mjs → join-BRow9_3-.mjs} +2 -2
- package/dist/{join-BHhCLh9B.mjs → join-d-pqyf8e.mjs} +3 -3
- package/dist/{key-DYeTZ7MI.mjs → key-CTL_AXOh.mjs} +24 -8
- package/dist/{key-DdZsNmo_.mjs → key-D_66hrWW.mjs} +3 -3
- package/dist/{local-test-B1ys1pNo.mjs → local-test-BZHGo22F.mjs} +1 -1
- package/dist/{models-dev-DPT_BK_V.mjs → models-dev-CDEyd2k3.mjs} +1 -1
- package/dist/{mux-DlwEK4Tt.mjs → mux-BaIDugDq.mjs} +1 -1
- package/dist/{ports-DDM5bbJg.mjs → ports-TQ4tWmiJ.mjs} +2 -2
- package/dist/{presets-Do5DWXfQ.mjs → presets-DleOUQiT.mjs} +2 -2
- package/dist/{revoke-6lrZkjN4.mjs → revoke-DTFW_EF1.mjs} +2 -2
- package/dist/{rewrite-vGrkDZx8.mjs → rewrite-CEzfYH9n.mjs} +2 -2
- package/dist/{route-test-DfGzFjKw.mjs → route-test-D2LQyX7c.mjs} +3 -3
- package/dist/{rpc-contract-BXviZUtF.mjs → rpc-contract-cB5SuyQ_.mjs} +16 -6
- package/dist/{run-BLxeLngt.mjs → run-D8kgXdId.mjs} +3 -3
- package/dist/{runtime-D8P29hIl.mjs → runtime-C_pLA5F0.mjs} +2 -2
- package/dist/{secret-Ds6pIoLP.mjs → secret-P2RgHy2h.mjs} +2 -2
- package/dist/{secrets-bHJBznMX.mjs → secrets-1Hmddmwy.mjs} +2 -2
- package/dist/secrets-C9IYp93v.mjs +2 -0
- package/dist/{serve-B4f79Eqq.mjs → serve-B51lmr9M.mjs} +2 -2
- package/dist/{serve-C8VRRJrt.mjs → serve-CY7ZFOFM.mjs} +4 -4
- package/dist/{service-CYkpuJuc.mjs → service-D6TNolyh.mjs} +4 -4
- package/dist/{settings-CSran7QD.mjs → settings-Rq1zLoxY.mjs} +1 -1
- package/dist/{settings-CY-bC0MJ.mjs → settings-XCvAzDK8.mjs} +2 -2
- package/dist/{share-B94HhX_b.mjs → share-DdtbAylA.mjs} +27 -12
- package/dist/{status-BFpr-LHB.mjs → status-DSVQ3YHm.mjs} +3 -3
- package/dist/{status-C_EI8-b9.mjs → status-uE2-kOyK.mjs} +3 -3
- package/dist/{store-DCLn0Df-.mjs → store-DOFDy1rY.mjs} +1 -1
- package/dist/{store-DxU0bd_u.mjs → store-EGzVd-dn.mjs} +21 -3
- package/dist/{test-BERWIlFb.mjs → test-DW4BF7xJ.mjs} +2 -2
- package/hooks/codex.cjs +12 -0
- package/hooks/env.cjs +10 -0
- package/hooks/file.cjs +27 -0
- package/hooks/secret.cjs +11 -0
- package/package.json +2 -1
- package/webui/dist/assets/index-B5lnC-QV.js +71 -0
- package/webui/dist/assets/{index-CufH1z8j.css → index-DqLIOzIY.css} +1 -1
- package/webui/dist/index.html +2 -2
- package/dist/secrets-G2HTT66T.mjs +0 -2
- package/webui/dist/assets/index-B-lLxXvx.js +0 -77
|
@@ -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-
|
|
4
|
-
import { n as FabricWireAdapter, r as DEFAULT_BODY_CHUNK_BYTES, t as WireSession } from "./mux-
|
|
5
|
-
import { t as SecretsStore } from "./secrets-
|
|
6
|
-
import { a as collectEnvVarNames, i as buildUpstreamRequest, n as RewriteError, r as SecretMissingError, s as buildServiceEntry, t as PathNotOfferedError } from "./rewrite-
|
|
3
|
+
import { i as ensurePrivateDir, r as atomicWriteFileSync, t as ProviderStore } from "./store-EGzVd-dn.mjs";
|
|
4
|
+
import { n as FabricWireAdapter, r as DEFAULT_BODY_CHUNK_BYTES, t as WireSession } from "./mux-BaIDugDq.mjs";
|
|
5
|
+
import { t as SecretsStore } from "./secrets-1Hmddmwy.mjs";
|
|
6
|
+
import { a as collectEnvVarNames, i as buildUpstreamRequest, n as RewriteError, r as SecretMissingError, s as buildServiceEntry, t as PathNotOfferedError } from "./rewrite-CEzfYH9n.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-
|
|
4
|
-
import { n as loadCuratedPresets } from "./models-dev-
|
|
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-C51SAE5f.mjs";
|
|
4
|
+
import { n as loadCuratedPresets } from "./models-dev-CDEyd2k3.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-
|
|
229
|
-
const { SecretsStore } = await import("./secrets-
|
|
228
|
+
const { testServiceRoute } = await import("./route-test-D2LQyX7c.mjs");
|
|
229
|
+
const { SecretsStore } = await import("./secrets-C9IYp93v.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-
|
|
3
|
+
import { n as saveSettings, r as settingsPath, t as loadSettings } from "./settings-XCvAzDK8.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-
|
|
2
|
-
import { i as ensurePrivateDir, r as atomicWriteFileSync } from "./store-
|
|
1
|
+
import { i as SETTINGS_SCHEMA } from "./rpc-contract-cB5SuyQ_.mjs";
|
|
2
|
+
import { i as ensurePrivateDir, r as atomicWriteFileSync } from "./store-EGzVd-dn.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-
|
|
6
|
-
import { c as requireString, d as str, l as resolveDataDir, r as openStore, u as resolvedRelayUrls } from "./common-
|
|
7
|
-
import { t as openExistingFabric } from "./serve-
|
|
8
|
-
import { s as buildServiceEntry } from "./rewrite-
|
|
5
|
+
import { n as StoreError } from "./store-EGzVd-dn.mjs";
|
|
6
|
+
import { c as requireString, d as str, l as resolveDataDir, r as openStore, u as resolvedRelayUrls } from "./common-C51SAE5f.mjs";
|
|
7
|
+
import { t as openExistingFabric } from "./serve-CY7ZFOFM.mjs";
|
|
8
|
+
import { s as buildServiceEntry } from "./rewrite-CEzfYH9n.mjs";
|
|
9
9
|
import { homedir } from "node:os";
|
|
10
10
|
import { z } from "zod";
|
|
11
11
|
//#region src/provider/link.ts
|
|
@@ -33,21 +33,32 @@ function encodeShareLink(payload) {
|
|
|
33
33
|
return SHARE_LINK_PREFIX + Buffer.from(JSON.stringify(payload), "utf8").toString("base64url");
|
|
34
34
|
}
|
|
35
35
|
/**
|
|
36
|
-
* 构造分享链接:前置检查(组存在且非空)->
|
|
37
|
-
*
|
|
36
|
+
* 构造分享链接:前置检查(组存在且非空)-> key(复用 keyId 指定的已存
|
|
37
|
+
* 原文;缺省签发新钥)-> 组内服务脱敏视图 -> payload + link + 警告。
|
|
38
38
|
*/
|
|
39
39
|
function buildShareLink(input) {
|
|
40
40
|
if (input.store.getGroup(input.group) === void 0) throw new StoreError("not-found", `error: group '${input.group}' not found`);
|
|
41
41
|
const services = input.store.groupServices(input.group);
|
|
42
42
|
if (services.length === 0) throw new StoreError("invalid", `error: group '${input.group}' has no services; a share link would be meaningless`);
|
|
43
|
-
|
|
43
|
+
let key;
|
|
44
|
+
let keyId;
|
|
45
|
+
if (input.keyId !== void 0) {
|
|
46
|
+
const material = input.store.getKeyMaterial(input.keyId);
|
|
47
|
+
if (material === void 0) throw new StoreError("invalid", `error: key '${input.keyId}' cannot be shared (missing, revoked, or raw material not stored)`);
|
|
48
|
+
key = material;
|
|
49
|
+
keyId = input.keyId;
|
|
50
|
+
} else {
|
|
51
|
+
const issued = input.store.issueKey(input.group, input.keyName);
|
|
52
|
+
key = issued.key;
|
|
53
|
+
keyId = issued.keyId;
|
|
54
|
+
}
|
|
44
55
|
const serviceEntries = services.map(buildServiceEntry);
|
|
45
56
|
const relayUrls = input.relayUrls === void 0 ? [] : [...input.relayUrls];
|
|
46
57
|
const payload = {
|
|
47
58
|
v: 1,
|
|
48
59
|
invite: input.invite,
|
|
49
|
-
key
|
|
50
|
-
keyId
|
|
60
|
+
key,
|
|
61
|
+
keyId,
|
|
51
62
|
provider: {
|
|
52
63
|
alias: input.alias ?? input.store.alias ?? "provider",
|
|
53
64
|
endpointId: input.endpointId,
|
|
@@ -62,7 +73,7 @@ function buildShareLink(input) {
|
|
|
62
73
|
payload,
|
|
63
74
|
link: encodeShareLink(payload),
|
|
64
75
|
warnings,
|
|
65
|
-
keyId
|
|
76
|
+
keyId
|
|
66
77
|
};
|
|
67
78
|
}
|
|
68
79
|
//#endregion
|
|
@@ -75,7 +86,9 @@ const SPEC = {
|
|
|
75
86
|
group: { type: "string" },
|
|
76
87
|
ttl: { type: "string" },
|
|
77
88
|
relay: { type: "multi" },
|
|
78
|
-
"allow-relayless": { type: "boolean" }
|
|
89
|
+
"allow-relayless": { type: "boolean" },
|
|
90
|
+
"key-id": { type: "string" },
|
|
91
|
+
"key-name": { type: "string" }
|
|
79
92
|
};
|
|
80
93
|
async function run(argv, ctx = {}) {
|
|
81
94
|
let fabric;
|
|
@@ -97,7 +110,9 @@ async function run(argv, ctx = {}) {
|
|
|
97
110
|
group,
|
|
98
111
|
invite,
|
|
99
112
|
endpointId: fabric.endpointId,
|
|
100
|
-
relayUrls: relayStatus.urls
|
|
113
|
+
relayUrls: relayStatus.urls,
|
|
114
|
+
keyId: str(options["key-id"]),
|
|
115
|
+
keyName: str(options["key-name"])
|
|
101
116
|
});
|
|
102
117
|
process.stdout.write([
|
|
103
118
|
`share link for group '${group}' (keyId ${result.keyId}, ttl ${describeTtl(ttlMs)}):`,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { 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, r as openStore, u as resolvedRelayUrls } from "./common-
|
|
5
|
-
import { t as openExistingFabric } from "./serve-
|
|
6
|
-
import { c as detailDisplayLines, o as buildServiceDetail } from "./rewrite-
|
|
4
|
+
import { d as str, l as resolveDataDir, r as openStore, u as resolvedRelayUrls } from "./common-C51SAE5f.mjs";
|
|
5
|
+
import { t as openExistingFabric } from "./serve-CY7ZFOFM.mjs";
|
|
6
|
+
import { c as detailDisplayLines, o as buildServiceDetail } from "./rewrite-CEzfYH9n.mjs";
|
|
7
7
|
import { homedir } from "node:os";
|
|
8
8
|
//#region src/cli/commands/provider/status.ts
|
|
9
9
|
const SPEC = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { n as parseArgv } from "./args-CSxXW9eD.mjs";
|
|
2
|
-
import { n as consumersRoot, s as listKeyrings } from "./store-
|
|
3
|
-
import { a as ringsForRun, n as ctxHomedir, r as ctxOut, t as createSdkFabricFactory } from "./common-
|
|
4
|
-
import { n as createFabricProviderTransport, t as startEngine } from "./runtime-
|
|
2
|
+
import { n as consumersRoot, s as listKeyrings } from "./store-DOFDy1rY.mjs";
|
|
3
|
+
import { a as ringsForRun, n as ctxHomedir, r as ctxOut, t as createSdkFabricFactory } from "./common-CanLn0Qt.mjs";
|
|
4
|
+
import { n as createFabricProviderTransport, t as startEngine } from "./runtime-C_pLA5F0.mjs";
|
|
5
5
|
import { homedir } from "node:os";
|
|
6
6
|
//#region src/cli/commands/consumer/status.ts
|
|
7
7
|
/** 状态显示名(spec 六态)。 */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as CliError } from "./errors-BGtxPkM7.mjs";
|
|
2
|
-
import { s as randomZ32 } from "./rpc-contract-
|
|
2
|
+
import { s as randomZ32 } from "./rpc-contract-cB5SuyQ_.mjs";
|
|
3
3
|
import { l as SERVICE_ENTRY_SCHEMA } from "./frames-BDz8buix.mjs";
|
|
4
4
|
import { chmodSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { homedir } from "node:os";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as ROUTE_LOCAL_PREFIX, s as randomZ32 } from "./rpc-contract-
|
|
1
|
+
import { n as ROUTE_LOCAL_PREFIX, s as randomZ32 } from "./rpc-contract-cB5SuyQ_.mjs";
|
|
2
2
|
import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { z } from "zod";
|
|
@@ -235,9 +235,17 @@ const KEY_STORE_SCHEMA = z.strictObject({
|
|
|
235
235
|
keyId: z.string().min(1).max(128),
|
|
236
236
|
group: z.string().min(1).max(256),
|
|
237
237
|
hash: z.string().regex(/^[0-9a-f]{64}$/, "key hash must be 64 hex chars"),
|
|
238
|
+
/** key 名(Owner 裁决 2026-09-13:签发时必填,GUI 分组视图按名展示;
|
|
239
|
+
* 旧记录无此字段——迁移容忍,GUI 显示为未命名)。 */
|
|
240
|
+
name: z.string().min(1).max(128).optional(),
|
|
241
|
+
/** key 原文(Owner 裁决 2026-09-13:可随时复制取代仅签发时可见——本机
|
|
242
|
+
* 个人工具与密钥库明文同一威胁模型;旧记录只存哈希,无法补录)。 */
|
|
243
|
+
key: z.string().min(8).max(256).optional(),
|
|
238
244
|
createdAt: z.number().int().min(0),
|
|
239
245
|
revokedAt: z.number().int().min(0).optional()
|
|
240
246
|
});
|
|
247
|
+
/** key 名规则(同 SECRET_NAME_SCHEMA 词汇:小写开头,点横杠下划线)。 */
|
|
248
|
+
const KEY_NAME_SCHEMA = /^[a-z0-9][a-z0-9._-]*$/;
|
|
241
249
|
const STORE_FILE_SCHEMA = z.strictObject({
|
|
242
250
|
revision: z.number().int().min(0),
|
|
243
251
|
meta: z.strictObject({ alias: z.string().min(1).max(256).optional() }).optional(),
|
|
@@ -473,9 +481,11 @@ var ProviderStore = class ProviderStore {
|
|
|
473
481
|
listKeys() {
|
|
474
482
|
return this.data.keys.map((k) => ({ ...k }));
|
|
475
483
|
}
|
|
476
|
-
/**
|
|
477
|
-
|
|
484
|
+
/** 签发:name 缺省 "default";原文随记录落库(Owner 2026-09-13:随时
|
|
485
|
+
* 可复制)。name 是展示标签非身份(keyId 唯一),同组可重名。 */
|
|
486
|
+
issueKey(groupName, name = "default") {
|
|
478
487
|
if (this.getGroup(groupName) === void 0) throw new StoreError("not-found", `error: group '${groupName}' not found`);
|
|
488
|
+
if (!KEY_NAME_SCHEMA.test(name)) throw new StoreError("invalid", "error: key name must match /^[a-z0-9][a-z0-9._-]*$/");
|
|
479
489
|
let keyId;
|
|
480
490
|
do
|
|
481
491
|
keyId = randomZ32(8);
|
|
@@ -486,6 +496,8 @@ var ProviderStore = class ProviderStore {
|
|
|
486
496
|
keyId,
|
|
487
497
|
group: groupName,
|
|
488
498
|
hash: hashKeyMaterial(key),
|
|
499
|
+
name,
|
|
500
|
+
key,
|
|
489
501
|
createdAt
|
|
490
502
|
});
|
|
491
503
|
this.save();
|
|
@@ -495,6 +507,12 @@ var ProviderStore = class ProviderStore {
|
|
|
495
507
|
createdAt
|
|
496
508
|
};
|
|
497
509
|
}
|
|
510
|
+
/** key 原文取回(旧记录只存哈希 → undefined;撤销/不存在 → undefined)。 */
|
|
511
|
+
getKeyMaterial(keyId) {
|
|
512
|
+
const found = this.data.keys.find((k) => k.keyId === keyId);
|
|
513
|
+
if (found === void 0 || found.revokedAt !== void 0) return void 0;
|
|
514
|
+
return found.key;
|
|
515
|
+
}
|
|
498
516
|
/** 撤销(幂等:已撤销为 no-op)。 */
|
|
499
517
|
revokeKey(keyId) {
|
|
500
518
|
const found = this.data.keys.find((k) => k.keyId === keyId);
|
|
@@ -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 { n as consumersRoot, s as listKeyrings } from "./store-
|
|
3
|
+
import { n as consumersRoot, s as listKeyrings } from "./store-DOFDy1rY.mjs";
|
|
4
4
|
import { n as desiredPortFor } from "./ports-pI59MtmI.mjs";
|
|
5
|
-
import { n as testLocalService } from "./local-test-
|
|
5
|
+
import { n as testLocalService } from "./local-test-BZHGo22F.mjs";
|
|
6
6
|
import { homedir } from "node:os";
|
|
7
7
|
//#region src/cli/commands/consumer/test.ts
|
|
8
8
|
const SPEC = {
|
package/hooks/codex.cjs
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// 内建 hooks 脚本:codex —— 读 codex CLI 登录态(~/.codex/auth.json)。
|
|
2
|
+
// 钩子清单(按函数名命名规范被发现):
|
|
3
|
+
// - authHeader(ctx) -> string:ChatGPT Codex backend 的 Bearer 认证头(去前缀裸值,
|
|
4
|
+
// 框架按需拼 "Bearer " 由 headerSet 配置的 bearer 决定——本脚本返回裸 token)。
|
|
5
|
+
module.exports.authHeader = function authHeader({ homedir }) {
|
|
6
|
+
const { readFileSync } = require("node:fs");
|
|
7
|
+
const { join } = require("node:path");
|
|
8
|
+
const auth = JSON.parse(readFileSync(join(homedir, ".codex", "auth.json"), "utf8"));
|
|
9
|
+
const token = auth && auth.tokens && auth.tokens.access_token;
|
|
10
|
+
if (typeof token !== "string" || token === "") throw new Error("codex auth.json missing access_token");
|
|
11
|
+
return token;
|
|
12
|
+
};
|
package/hooks/env.cjs
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// 内建 hooks 脚本:env —— 环境变量桥。
|
|
2
|
+
// 钩子清单:
|
|
3
|
+
// - authHeader(ctx) -> string:读 args.var 指定的环境变量(OPENAI_API_KEY 等)。
|
|
4
|
+
module.exports.authHeader = function authHeader({ args, env: ctxEnv }) {
|
|
5
|
+
const name = args && args.var;
|
|
6
|
+
if (typeof name !== "string" || name === "") throw new Error("env hook requires args.var");
|
|
7
|
+
const value = (ctxEnv && ctxEnv(name)) || process.env[name];
|
|
8
|
+
if (value === undefined || value === "") throw new Error(`env '${name}' unset`);
|
|
9
|
+
return value;
|
|
10
|
+
};
|
package/hooks/file.cjs
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// 内建 hooks 脚本:file —— JSON 文件取值(点径)。
|
|
2
|
+
// 钩子清单:
|
|
3
|
+
// - authHeader(ctx) -> string:读 args.path(支持 ~)+ args.jsonPath(.a.b 风格);
|
|
4
|
+
// args.bearer 为 "true"/"1" 时返回值拼 "Bearer " 前缀。
|
|
5
|
+
// watch 模式示例(返回 AsyncIterable):unwatchOnClose 实现见文档。
|
|
6
|
+
module.exports.authHeader = function authHeader({ homedir, args }) {
|
|
7
|
+
const { readFileSync } = require("node:fs");
|
|
8
|
+
const { join } = require("node:path");
|
|
9
|
+
const path = args && args.path;
|
|
10
|
+
const jsonPath = (args && args.jsonPath) || ".";
|
|
11
|
+
if (typeof path !== "string" || path === "") throw new Error("file hook requires args.path");
|
|
12
|
+
const abs = path.startsWith("~/") ? join(homedir, path.slice(1)) : path;
|
|
13
|
+
let doc;
|
|
14
|
+
try {
|
|
15
|
+
doc = JSON.parse(readFileSync(abs, "utf8"));
|
|
16
|
+
} catch {
|
|
17
|
+
throw new Error("file unreadable or invalid JSON");
|
|
18
|
+
}
|
|
19
|
+
let cur = doc;
|
|
20
|
+
for (const seg of jsonPath.split(".").filter(Boolean)) {
|
|
21
|
+
if (cur === null || cur === undefined) throw new Error("json path miss");
|
|
22
|
+
cur = cur[seg];
|
|
23
|
+
}
|
|
24
|
+
if (typeof cur !== "string" || cur === "") throw new Error("json path value missing");
|
|
25
|
+
const bearer = args && (args.bearer === "true" || args.bearer === "1");
|
|
26
|
+
return bearer ? `Bearer ${cur}` : cur;
|
|
27
|
+
};
|
package/hooks/secret.cjs
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// 内建 hooks 脚本:secret —— 密钥库(SecretsStore)桥。
|
|
2
|
+
// 钩子清单:
|
|
3
|
+
// - authHeader(ctx) -> string:读 args.name 指定的密钥(ctx.secrets 访问器;
|
|
4
|
+
// 值只进头不回显——$secret 法则不变)。
|
|
5
|
+
module.exports.authHeader = function authHeader({ args, secrets }) {
|
|
6
|
+
const name = args && args.name;
|
|
7
|
+
if (typeof name !== "string" || name === "") throw new Error("secret hook requires args.name");
|
|
8
|
+
const value = secrets && secrets(name);
|
|
9
|
+
if (value === undefined || value === "") throw new Error(`secret '${name}' not found`);
|
|
10
|
+
return value;
|
|
11
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-fly",
|
|
3
|
-
"version": "0.4.0
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "ai-fly — peer-to-peer HTTP/WebSocket bridge with AI-ready presets, over OpenDWeb fabric",
|
|
5
5
|
"license": "MIT OR Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -60,6 +60,7 @@
|
|
|
60
60
|
"dist/*.mjs",
|
|
61
61
|
"dist/*.d.ts",
|
|
62
62
|
"dist/app/**",
|
|
63
|
+
"hooks",
|
|
63
64
|
"webui/dist",
|
|
64
65
|
"resources/app-icons"
|
|
65
66
|
],
|