@aigne/afs-cli 1.11.0-beta.11 → 1.11.0-beta.12
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/cli.cjs +3 -2
- package/dist/cli.mjs +3 -2
- package/dist/cli.mjs.map +1 -1
- package/dist/config/afs-loader.cjs +64 -315
- package/dist/config/afs-loader.d.cts.map +1 -1
- package/dist/config/afs-loader.d.mts +2 -1
- package/dist/config/afs-loader.d.mts.map +1 -1
- package/dist/config/afs-loader.mjs +59 -310
- package/dist/config/afs-loader.mjs.map +1 -1
- package/dist/config/credential-helpers.cjs +291 -0
- package/dist/config/credential-helpers.d.mts +2 -0
- package/dist/config/credential-helpers.mjs +288 -0
- package/dist/config/credential-helpers.mjs.map +1 -0
- package/dist/config/loader.cjs +3 -1
- package/dist/config/loader.mjs +3 -2
- package/dist/config/loader.mjs.map +1 -1
- package/dist/config/program-install.cjs +276 -0
- package/dist/config/program-install.d.mts +1 -0
- package/dist/config/program-install.mjs +273 -0
- package/dist/config/program-install.mjs.map +1 -0
- package/dist/core/commands/connect.cjs +53 -0
- package/dist/core/commands/connect.d.mts +2 -0
- package/dist/core/commands/connect.mjs +55 -0
- package/dist/core/commands/connect.mjs.map +1 -0
- package/dist/core/commands/daemon.cjs +207 -0
- package/dist/core/commands/daemon.d.mts +2 -0
- package/dist/core/commands/daemon.mjs +208 -0
- package/dist/core/commands/daemon.mjs.map +1 -0
- package/dist/core/commands/explain.cjs +3 -1
- package/dist/core/commands/explain.mjs +3 -1
- package/dist/core/commands/explain.mjs.map +1 -1
- package/dist/core/commands/explore.cjs +47 -12
- package/dist/core/commands/explore.mjs +47 -12
- package/dist/core/commands/explore.mjs.map +1 -1
- package/dist/core/commands/gen-agent-md.cjs +126 -0
- package/dist/core/commands/gen-agent-md.d.mts +2 -0
- package/dist/core/commands/gen-agent-md.mjs +125 -0
- package/dist/core/commands/gen-agent-md.mjs.map +1 -0
- package/dist/core/commands/index.cjs +13 -1
- package/dist/core/commands/index.d.cts.map +1 -1
- package/dist/core/commands/index.d.mts +6 -0
- package/dist/core/commands/index.d.mts.map +1 -1
- package/dist/core/commands/index.mjs +13 -1
- package/dist/core/commands/index.mjs.map +1 -1
- package/dist/core/commands/install.cjs +91 -0
- package/dist/core/commands/install.d.mts +2 -0
- package/dist/core/commands/install.mjs +92 -0
- package/dist/core/commands/install.mjs.map +1 -0
- package/dist/core/commands/ls.cjs +14 -2
- package/dist/core/commands/ls.d.cts +2 -0
- package/dist/core/commands/ls.d.cts.map +1 -1
- package/dist/core/commands/ls.d.mts +2 -0
- package/dist/core/commands/ls.d.mts.map +1 -1
- package/dist/core/commands/ls.mjs +14 -2
- package/dist/core/commands/ls.mjs.map +1 -1
- package/dist/core/commands/mcp-bridge.cjs +201 -0
- package/dist/core/commands/mcp-bridge.d.mts +2 -0
- package/dist/core/commands/mcp-bridge.mjs +201 -0
- package/dist/core/commands/mcp-bridge.mjs.map +1 -0
- package/dist/core/commands/read.cjs +20 -7
- package/dist/core/commands/read.d.cts +2 -0
- package/dist/core/commands/read.d.cts.map +1 -1
- package/dist/core/commands/read.d.mts +2 -0
- package/dist/core/commands/read.d.mts.map +1 -1
- package/dist/core/commands/read.mjs +20 -7
- package/dist/core/commands/read.mjs.map +1 -1
- package/dist/core/commands/search.cjs +5 -1
- package/dist/core/commands/search.mjs +5 -1
- package/dist/core/commands/search.mjs.map +1 -1
- package/dist/core/commands/stat.mjs.map +1 -1
- package/dist/core/commands/types.d.cts +2 -0
- package/dist/core/commands/types.d.cts.map +1 -1
- package/dist/core/commands/types.d.mts +2 -0
- package/dist/core/commands/types.d.mts.map +1 -1
- package/dist/core/commands/types.mjs.map +1 -1
- package/dist/core/commands/vault.cjs +289 -0
- package/dist/core/commands/vault.d.mts +2 -0
- package/dist/core/commands/vault.mjs +289 -0
- package/dist/core/commands/vault.mjs.map +1 -0
- package/dist/core/commands/write.cjs +19 -6
- package/dist/core/commands/write.d.cts +2 -1
- package/dist/core/commands/write.d.cts.map +1 -1
- package/dist/core/commands/write.d.mts +2 -1
- package/dist/core/commands/write.d.mts.map +1 -1
- package/dist/core/commands/write.mjs +19 -6
- package/dist/core/commands/write.mjs.map +1 -1
- package/dist/core/executor/index.cjs +95 -19
- package/dist/core/executor/index.d.cts +4 -0
- package/dist/core/executor/index.d.cts.map +1 -1
- package/dist/core/executor/index.d.mts +4 -0
- package/dist/core/executor/index.d.mts.map +1 -1
- package/dist/core/executor/index.mjs +95 -19
- package/dist/core/executor/index.mjs.map +1 -1
- package/dist/core/formatters/index.d.mts +1 -0
- package/dist/core/formatters/install.cjs +21 -0
- package/dist/core/formatters/install.d.mts +1 -0
- package/dist/core/formatters/install.mjs +19 -0
- package/dist/core/formatters/install.mjs.map +1 -0
- package/dist/core/formatters/vault.cjs +36 -0
- package/dist/core/formatters/vault.mjs +32 -0
- package/dist/core/formatters/vault.mjs.map +1 -0
- package/dist/credential/index.d.mts +2 -1
- package/dist/credential/mcp-auth-context.cjs +21 -5
- package/dist/credential/mcp-auth-context.mjs +21 -5
- package/dist/credential/mcp-auth-context.mjs.map +1 -1
- package/dist/credential/resolver.cjs +7 -2
- package/dist/credential/resolver.mjs +7 -2
- package/dist/credential/resolver.mjs.map +1 -1
- package/dist/credential/vault-store.d.mts +1 -0
- package/dist/daemon/config-manager.cjs +279 -0
- package/dist/daemon/config-manager.mjs +279 -0
- package/dist/daemon/config-manager.mjs.map +1 -0
- package/dist/daemon/manager.cjs +164 -0
- package/dist/daemon/manager.mjs +157 -0
- package/dist/daemon/manager.mjs.map +1 -0
- package/dist/daemon/server.cjs +220 -0
- package/dist/daemon/server.mjs +220 -0
- package/dist/daemon/server.mjs.map +1 -0
- package/dist/mcp/http-transport.cjs +14 -1
- package/dist/mcp/http-transport.mjs +14 -1
- package/dist/mcp/http-transport.mjs.map +1 -1
- package/dist/mcp/server.cjs +4 -2
- package/dist/mcp/server.mjs +4 -2
- package/dist/mcp/server.mjs.map +1 -1
- package/dist/mcp/tools.cjs +62 -12
- package/dist/mcp/tools.mjs +62 -12
- package/dist/mcp/tools.mjs.map +1 -1
- package/dist/program/daemon-integration.cjs +46 -0
- package/dist/program/daemon-integration.mjs +45 -0
- package/dist/program/daemon-integration.mjs.map +1 -0
- package/dist/program/program-manager.cjs +162 -0
- package/dist/program/program-manager.mjs +162 -0
- package/dist/program/program-manager.mjs.map +1 -0
- package/dist/program/trigger-scanner.cjs +148 -0
- package/dist/program/trigger-scanner.mjs +148 -0
- package/dist/program/trigger-scanner.mjs.map +1 -0
- package/dist/providers/vault/dist/_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.cjs +11 -0
- package/dist/providers/vault/dist/_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.mjs +11 -0
- package/dist/providers/vault/dist/_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.mjs.map +1 -0
- package/dist/providers/vault/dist/encrypted-file.cjs +158 -0
- package/dist/providers/vault/dist/encrypted-file.mjs +153 -0
- package/dist/providers/vault/dist/encrypted-file.mjs.map +1 -0
- package/dist/providers/vault/dist/index.cjs +405 -0
- package/dist/providers/vault/dist/index.mjs +400 -0
- package/dist/providers/vault/dist/index.mjs.map +1 -0
- package/dist/providers/vault/dist/key-resolver.cjs +181 -0
- package/dist/providers/vault/dist/key-resolver.mjs +180 -0
- package/dist/providers/vault/dist/key-resolver.mjs.map +1 -0
- package/dist/repl.cjs +105 -14
- package/dist/repl.d.cts.map +1 -1
- package/dist/repl.d.mts.map +1 -1
- package/dist/repl.mjs +105 -14
- package/dist/repl.mjs.map +1 -1
- package/package.json +29 -22
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
let _aigne_afs = require("@aigne/afs");
|
|
3
|
+
let _aigne_afs_utils_uri = require("@aigne/afs/utils/uri");
|
|
4
|
+
|
|
5
|
+
//#region src/config/credential-helpers.ts
|
|
6
|
+
/**
|
|
7
|
+
* Extract env query params from MCP URIs for secure credential storage.
|
|
8
|
+
*
|
|
9
|
+
* MCP servers receive secrets via env vars (e.g., `mcp+stdio://npx?env=API_KEY=sk-xxx`).
|
|
10
|
+
* This function extracts env params from the URI so they can be stored in credentials.toml
|
|
11
|
+
* instead of being persisted in plaintext in config.toml.
|
|
12
|
+
*
|
|
13
|
+
* Only applies to MCP schemes (mcp://, mcp+stdio://, mcp+sse://).
|
|
14
|
+
* Non-MCP URIs are returned unchanged.
|
|
15
|
+
*/
|
|
16
|
+
function extractEnvFromURI(uri) {
|
|
17
|
+
const parsed = (0, _aigne_afs_utils_uri.parseURI)(uri);
|
|
18
|
+
const envRecord = {};
|
|
19
|
+
if (!parsed.scheme.startsWith("mcp")) return {
|
|
20
|
+
cleanUri: uri,
|
|
21
|
+
envRecord
|
|
22
|
+
};
|
|
23
|
+
const envValues = parsed.query.env;
|
|
24
|
+
if (!envValues) return {
|
|
25
|
+
cleanUri: uri,
|
|
26
|
+
envRecord
|
|
27
|
+
};
|
|
28
|
+
const envList = Array.isArray(envValues) ? envValues : [envValues];
|
|
29
|
+
for (const entry of envList) {
|
|
30
|
+
const eqIdx = entry.indexOf("=");
|
|
31
|
+
if (eqIdx > 0) envRecord[entry.slice(0, eqIdx)] = entry.slice(eqIdx + 1);
|
|
32
|
+
}
|
|
33
|
+
const queryIndex = uri.indexOf("?");
|
|
34
|
+
if (queryIndex < 0) return {
|
|
35
|
+
cleanUri: uri,
|
|
36
|
+
envRecord
|
|
37
|
+
};
|
|
38
|
+
const rawQuery = uri.slice(queryIndex + 1);
|
|
39
|
+
const params = new URLSearchParams(rawQuery);
|
|
40
|
+
params.delete("env");
|
|
41
|
+
const newQuery = params.toString();
|
|
42
|
+
const base = uri.slice(0, queryIndex);
|
|
43
|
+
return {
|
|
44
|
+
cleanUri: newQuery ? `${base}?${newQuery}` : base,
|
|
45
|
+
envRecord
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Extract template variables from mount.uri using the manifest's uriTemplate
|
|
50
|
+
* and merge them into mount.options so the credential resolver sees them as "known".
|
|
51
|
+
*/
|
|
52
|
+
function mergeTemplateVarsIntoMount(mount, manifest) {
|
|
53
|
+
if (!manifest?.uriTemplate) return;
|
|
54
|
+
const { parseTemplate } = require("@aigne/afs/utils/uri-template");
|
|
55
|
+
const parsed = (0, _aigne_afs_utils_uri.parseURI)(mount.uri);
|
|
56
|
+
let templateVars;
|
|
57
|
+
try {
|
|
58
|
+
templateVars = parseTemplate(manifest.uriTemplate, parsed.body);
|
|
59
|
+
} catch {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
for (const [key, value] of Object.entries(templateVars)) if (value !== void 0) {
|
|
63
|
+
if (!mount.options) mount.options = {};
|
|
64
|
+
if (mount.options[key] === void 0) mount.options[key] = value;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* After credential resolution, rebuild mount.uri from the template if the
|
|
69
|
+
* current URI body is empty/incomplete and resolved options can fill template vars.
|
|
70
|
+
*/
|
|
71
|
+
function rebuildURIFromTemplate(mount, manifest) {
|
|
72
|
+
if (!manifest?.uriTemplate) return;
|
|
73
|
+
const { buildURI, getTemplateVariableNames } = require("@aigne/afs/utils/uri-template");
|
|
74
|
+
const varNames = getTemplateVariableNames(manifest.uriTemplate);
|
|
75
|
+
if (varNames.length === 0) return;
|
|
76
|
+
const parsed = (0, _aigne_afs_utils_uri.parseURI)(mount.uri);
|
|
77
|
+
const { parseTemplate } = require("@aigne/afs/utils/uri-template");
|
|
78
|
+
let existingVars;
|
|
79
|
+
try {
|
|
80
|
+
existingVars = parseTemplate(manifest.uriTemplate, parsed.body);
|
|
81
|
+
} catch {
|
|
82
|
+
existingVars = {};
|
|
83
|
+
}
|
|
84
|
+
const allVars = { ...existingVars };
|
|
85
|
+
for (const name of varNames) if (!allVars[name] && mount.options?.[name] != null) allVars[name] = String(mount.options[name]);
|
|
86
|
+
try {
|
|
87
|
+
const newURI = buildURI(manifest.uriTemplate, allVars);
|
|
88
|
+
if (newURI !== mount.uri) mount.uri = newURI;
|
|
89
|
+
} catch {}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Attempt credential resolution for a mount, merging resolved values into mount.options.
|
|
93
|
+
*
|
|
94
|
+
* Returns the credential result if any fields were collected interactively,
|
|
95
|
+
* or null if no interactive collection was needed (or no schema/authContext).
|
|
96
|
+
*
|
|
97
|
+
* This function mutates mount.options and mount.auth/mount.token when credentials
|
|
98
|
+
* are resolved, so the subsequent registry.createProvider(mount) receives complete values.
|
|
99
|
+
*/
|
|
100
|
+
async function resolveAndMergeCredentials(mount, authContext, credentialStore, registry, opts) {
|
|
101
|
+
const info = await registry.getProviderInfo(mount.uri);
|
|
102
|
+
const schema = info?.schema ?? null;
|
|
103
|
+
const providerAuth = info?.auth;
|
|
104
|
+
if (!schema) return null;
|
|
105
|
+
mergeTemplateVarsIntoMount(mount, info?.manifest);
|
|
106
|
+
const { getSensitiveFields } = await import("@aigne/afs/utils/schema");
|
|
107
|
+
const sensitiveFieldsInSchema = getSensitiveFields(schema);
|
|
108
|
+
const schemaProps = schema.properties ?? {};
|
|
109
|
+
const hasEnvFields = Object.values(schemaProps).some((p) => Array.isArray(p?.env));
|
|
110
|
+
if (sensitiveFieldsInSchema.length === 0 && !hasEnvFields && !providerAuth) return null;
|
|
111
|
+
const { resolveCredentials } = await Promise.resolve().then(() => require("../credential/resolver.cjs"));
|
|
112
|
+
const result = await resolveCredentials({
|
|
113
|
+
mount,
|
|
114
|
+
schema,
|
|
115
|
+
authContext,
|
|
116
|
+
credentialStore,
|
|
117
|
+
providerAuth,
|
|
118
|
+
forceCollect: opts?.forceCollect
|
|
119
|
+
});
|
|
120
|
+
if (!result) {
|
|
121
|
+
const fieldNames = Object.keys(schema.properties ?? {});
|
|
122
|
+
const known = /* @__PURE__ */ new Set();
|
|
123
|
+
if (mount.auth !== void 0) known.add("auth");
|
|
124
|
+
if (mount.token !== void 0) known.add("token");
|
|
125
|
+
if (mount.options) for (const k of Object.keys(mount.options)) known.add(k);
|
|
126
|
+
const missing = fieldNames.filter((f) => !known.has(f));
|
|
127
|
+
const fieldList = missing.length > 0 ? missing.join(", ") : fieldNames.join(", ");
|
|
128
|
+
throw new Error(`Missing credentials: ${fieldList}. Retry with them as args, e.g. { "uri": "${mount.uri}", "path": "${mount.path}", ${missing.map((f) => `"${f}": "..."`).join(", ")} }`);
|
|
129
|
+
}
|
|
130
|
+
if (Object.keys(result.values).length > 0) {
|
|
131
|
+
if (result.values.token !== void 0 && mount.token === void 0) mount.token = String(result.values.token);
|
|
132
|
+
if (result.values.auth !== void 0 && mount.auth === void 0) mount.auth = String(result.values.auth);
|
|
133
|
+
const mergedOpts = mount.options ?? {};
|
|
134
|
+
for (const [key, value] of Object.entries(result.values)) if (key !== "token" && key !== "auth" && mergedOpts[key] === void 0) mergedOpts[key] = value;
|
|
135
|
+
if (Object.keys(mergedOpts).length > 0) mount.options = mergedOpts;
|
|
136
|
+
}
|
|
137
|
+
rebuildURIFromTemplate(mount, info?.manifest);
|
|
138
|
+
return result.collected ? result : null;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Persist credential resolution result (sensitive → credentials.toml).
|
|
142
|
+
*/
|
|
143
|
+
async function persistCredentialResult(mount, result) {
|
|
144
|
+
if (Object.keys(result.sensitive).length > 0) try {
|
|
145
|
+
const { createCredentialStore } = await Promise.resolve().then(() => require("../credential/store.cjs"));
|
|
146
|
+
await createCredentialStore().set(mount.uri, result.sensitive);
|
|
147
|
+
} catch (err) {
|
|
148
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
149
|
+
console.warn(`[mount] credential persistence failed: ${msg}`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Load stored credentials and merge into mount options during startup.
|
|
154
|
+
*/
|
|
155
|
+
async function mergeStoredCredentials(mounts, _mountSources, store) {
|
|
156
|
+
for (const mount of mounts) try {
|
|
157
|
+
const stored = await store.get(mount.uri);
|
|
158
|
+
if (stored) {
|
|
159
|
+
const opts = mount.options ?? {};
|
|
160
|
+
for (const [key, value] of Object.entries(stored)) if (key.startsWith("env:")) {
|
|
161
|
+
if (!opts.env) opts.env = {};
|
|
162
|
+
opts.env[key.slice(4)] = value;
|
|
163
|
+
} else if (opts[key] === void 0) opts[key] = value;
|
|
164
|
+
if (Object.keys(opts).length > 0) mount.options = opts;
|
|
165
|
+
}
|
|
166
|
+
} catch {}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Resolve and persist credentials for a mount configuration.
|
|
170
|
+
*
|
|
171
|
+
* Used by `mount add` CLI command to trigger credential collection
|
|
172
|
+
* at add-time rather than deferring to AFS creation.
|
|
173
|
+
*/
|
|
174
|
+
async function resolveCredentialsForMount(options) {
|
|
175
|
+
const { uri, mountPath, authContext, credentialStore, extraOptions, sensitiveArgs } = options;
|
|
176
|
+
const { cleanUri: configUri, envRecord } = extractEnvFromURI(uri);
|
|
177
|
+
const hasExtractedEnv = Object.keys(envRecord).length > 0;
|
|
178
|
+
const info = await (options.registry ?? new _aigne_afs.ProviderRegistry()).getProviderInfo(uri);
|
|
179
|
+
let schema = info?.schema ?? null;
|
|
180
|
+
const providerAuth = info?.auth;
|
|
181
|
+
if (!schema && extraOptions && Object.keys(extraOptions).length > 0) {
|
|
182
|
+
const { buildAdHocSchema } = await import("@aigne/afs/utils/schema");
|
|
183
|
+
schema = buildAdHocSchema(extraOptions, sensitiveArgs ?? []);
|
|
184
|
+
}
|
|
185
|
+
const envOnlyResult = () => {
|
|
186
|
+
if (!hasExtractedEnv) return null;
|
|
187
|
+
return {
|
|
188
|
+
collected: false,
|
|
189
|
+
nonSensitive: {},
|
|
190
|
+
allValues: {},
|
|
191
|
+
persistCredentials: async () => {
|
|
192
|
+
const toStore = {};
|
|
193
|
+
for (const [key, val] of Object.entries(envRecord)) toStore[`env:${key}`] = val;
|
|
194
|
+
if (credentialStore) try {
|
|
195
|
+
await credentialStore.set(configUri, toStore);
|
|
196
|
+
} catch (err) {
|
|
197
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
198
|
+
console.warn(`[mount add] credential persistence failed: ${msg}`);
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
sensitiveFields: [],
|
|
202
|
+
configUri
|
|
203
|
+
};
|
|
204
|
+
};
|
|
205
|
+
if (!schema) return envOnlyResult();
|
|
206
|
+
const properties = schema.properties;
|
|
207
|
+
if (!properties || Object.keys(properties).length === 0) return envOnlyResult();
|
|
208
|
+
if (sensitiveArgs && sensitiveArgs.length > 0) {
|
|
209
|
+
const mergedProps = { ...properties };
|
|
210
|
+
let changed = false;
|
|
211
|
+
for (const field of sensitiveArgs) if (mergedProps[field]) {
|
|
212
|
+
mergedProps[field] = {
|
|
213
|
+
...mergedProps[field],
|
|
214
|
+
sensitive: true
|
|
215
|
+
};
|
|
216
|
+
changed = true;
|
|
217
|
+
} else if (extraOptions?.[field] !== void 0) {
|
|
218
|
+
const value = extraOptions[field];
|
|
219
|
+
mergedProps[field] = {
|
|
220
|
+
type: typeof value === "number" ? "number" : typeof value === "boolean" ? "boolean" : "string",
|
|
221
|
+
sensitive: true
|
|
222
|
+
};
|
|
223
|
+
changed = true;
|
|
224
|
+
}
|
|
225
|
+
if (changed) schema = {
|
|
226
|
+
...schema,
|
|
227
|
+
properties: mergedProps
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
const { getSensitiveFields } = await import("@aigne/afs/utils/schema");
|
|
231
|
+
const sensitiveFieldsInSchema = getSensitiveFields(schema);
|
|
232
|
+
const schemaProps = schema.properties;
|
|
233
|
+
const hasEnvFields = Object.values(schemaProps).some((p) => Array.isArray(p?.env));
|
|
234
|
+
if (sensitiveFieldsInSchema.length === 0 && !hasEnvFields && !extraOptions) return envOnlyResult();
|
|
235
|
+
const mount = {
|
|
236
|
+
uri,
|
|
237
|
+
path: mountPath
|
|
238
|
+
};
|
|
239
|
+
if (extraOptions && Object.keys(extraOptions).length > 0) mount.options = {
|
|
240
|
+
...mount.options ?? {},
|
|
241
|
+
...extraOptions
|
|
242
|
+
};
|
|
243
|
+
mergeTemplateVarsIntoMount(mount, info?.manifest);
|
|
244
|
+
const { resolveCredentials } = await Promise.resolve().then(() => require("../credential/resolver.cjs"));
|
|
245
|
+
const result = await resolveCredentials({
|
|
246
|
+
mount,
|
|
247
|
+
schema,
|
|
248
|
+
authContext,
|
|
249
|
+
credentialStore,
|
|
250
|
+
providerAuth,
|
|
251
|
+
forceCollect: options.forceCollect
|
|
252
|
+
});
|
|
253
|
+
if (!result) {
|
|
254
|
+
const fieldNames = Object.keys(properties);
|
|
255
|
+
throw new Error(`Missing credentials: ${fieldNames.join(", ")}. Retry with them as args, e.g. { "uri": "${uri}", "path": "${mountPath}", ${fieldNames.map((f) => `"${f}": "..."`).join(", ")} }`);
|
|
256
|
+
}
|
|
257
|
+
const sensitiveFieldSet = new Set(sensitiveFieldsInSchema);
|
|
258
|
+
const flatSensitive = {};
|
|
259
|
+
for (const field of sensitiveFieldsInSchema) {
|
|
260
|
+
const val = result.values[field];
|
|
261
|
+
if (val === void 0) continue;
|
|
262
|
+
if (field === "env" && typeof val === "object" && val !== null) for (const [envKey, envVal] of Object.entries(val)) flatSensitive[`env:${envKey}`] = String(envVal);
|
|
263
|
+
else flatSensitive[field] = String(val);
|
|
264
|
+
}
|
|
265
|
+
const nonSensitive = result.collected ? result.nonSensitive : extraOptions ? Object.fromEntries(Object.entries(extraOptions).filter(([k]) => !sensitiveFieldSet.has(k))) : {};
|
|
266
|
+
const persistCredentials = async () => {
|
|
267
|
+
const toStore = { ...flatSensitive };
|
|
268
|
+
for (const [key, val] of Object.entries(envRecord)) toStore[`env:${key}`] = val;
|
|
269
|
+
if (Object.keys(toStore).length > 0 && credentialStore) try {
|
|
270
|
+
await credentialStore.set(configUri, toStore);
|
|
271
|
+
} catch (err) {
|
|
272
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
273
|
+
console.warn(`[mount add] credential persistence failed: ${msg}`);
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
return {
|
|
277
|
+
collected: result.collected,
|
|
278
|
+
nonSensitive,
|
|
279
|
+
allValues: result.values,
|
|
280
|
+
persistCredentials,
|
|
281
|
+
sensitiveFields: sensitiveFieldsInSchema,
|
|
282
|
+
configUri: hasExtractedEnv ? configUri : void 0
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
//#endregion
|
|
287
|
+
exports.extractEnvFromURI = extractEnvFromURI;
|
|
288
|
+
exports.mergeStoredCredentials = mergeStoredCredentials;
|
|
289
|
+
exports.persistCredentialResult = persistCredentialResult;
|
|
290
|
+
exports.resolveAndMergeCredentials = resolveAndMergeCredentials;
|
|
291
|
+
exports.resolveCredentialsForMount = resolveCredentialsForMount;
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import { __require } from "../_virtual/rolldown_runtime.mjs";
|
|
2
|
+
import { ProviderRegistry } from "@aigne/afs";
|
|
3
|
+
import { parseURI } from "@aigne/afs/utils/uri";
|
|
4
|
+
|
|
5
|
+
//#region src/config/credential-helpers.ts
|
|
6
|
+
/**
|
|
7
|
+
* Extract env query params from MCP URIs for secure credential storage.
|
|
8
|
+
*
|
|
9
|
+
* MCP servers receive secrets via env vars (e.g., `mcp+stdio://npx?env=API_KEY=sk-xxx`).
|
|
10
|
+
* This function extracts env params from the URI so they can be stored in credentials.toml
|
|
11
|
+
* instead of being persisted in plaintext in config.toml.
|
|
12
|
+
*
|
|
13
|
+
* Only applies to MCP schemes (mcp://, mcp+stdio://, mcp+sse://).
|
|
14
|
+
* Non-MCP URIs are returned unchanged.
|
|
15
|
+
*/
|
|
16
|
+
function extractEnvFromURI(uri) {
|
|
17
|
+
const parsed = parseURI(uri);
|
|
18
|
+
const envRecord = {};
|
|
19
|
+
if (!parsed.scheme.startsWith("mcp")) return {
|
|
20
|
+
cleanUri: uri,
|
|
21
|
+
envRecord
|
|
22
|
+
};
|
|
23
|
+
const envValues = parsed.query.env;
|
|
24
|
+
if (!envValues) return {
|
|
25
|
+
cleanUri: uri,
|
|
26
|
+
envRecord
|
|
27
|
+
};
|
|
28
|
+
const envList = Array.isArray(envValues) ? envValues : [envValues];
|
|
29
|
+
for (const entry of envList) {
|
|
30
|
+
const eqIdx = entry.indexOf("=");
|
|
31
|
+
if (eqIdx > 0) envRecord[entry.slice(0, eqIdx)] = entry.slice(eqIdx + 1);
|
|
32
|
+
}
|
|
33
|
+
const queryIndex = uri.indexOf("?");
|
|
34
|
+
if (queryIndex < 0) return {
|
|
35
|
+
cleanUri: uri,
|
|
36
|
+
envRecord
|
|
37
|
+
};
|
|
38
|
+
const rawQuery = uri.slice(queryIndex + 1);
|
|
39
|
+
const params = new URLSearchParams(rawQuery);
|
|
40
|
+
params.delete("env");
|
|
41
|
+
const newQuery = params.toString();
|
|
42
|
+
const base = uri.slice(0, queryIndex);
|
|
43
|
+
return {
|
|
44
|
+
cleanUri: newQuery ? `${base}?${newQuery}` : base,
|
|
45
|
+
envRecord
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Extract template variables from mount.uri using the manifest's uriTemplate
|
|
50
|
+
* and merge them into mount.options so the credential resolver sees them as "known".
|
|
51
|
+
*/
|
|
52
|
+
function mergeTemplateVarsIntoMount(mount, manifest) {
|
|
53
|
+
if (!manifest?.uriTemplate) return;
|
|
54
|
+
const { parseTemplate } = __require("@aigne/afs/utils/uri-template");
|
|
55
|
+
const parsed = parseURI(mount.uri);
|
|
56
|
+
let templateVars;
|
|
57
|
+
try {
|
|
58
|
+
templateVars = parseTemplate(manifest.uriTemplate, parsed.body);
|
|
59
|
+
} catch {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
for (const [key, value] of Object.entries(templateVars)) if (value !== void 0) {
|
|
63
|
+
if (!mount.options) mount.options = {};
|
|
64
|
+
if (mount.options[key] === void 0) mount.options[key] = value;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* After credential resolution, rebuild mount.uri from the template if the
|
|
69
|
+
* current URI body is empty/incomplete and resolved options can fill template vars.
|
|
70
|
+
*/
|
|
71
|
+
function rebuildURIFromTemplate(mount, manifest) {
|
|
72
|
+
if (!manifest?.uriTemplate) return;
|
|
73
|
+
const { buildURI, getTemplateVariableNames } = __require("@aigne/afs/utils/uri-template");
|
|
74
|
+
const varNames = getTemplateVariableNames(manifest.uriTemplate);
|
|
75
|
+
if (varNames.length === 0) return;
|
|
76
|
+
const parsed = parseURI(mount.uri);
|
|
77
|
+
const { parseTemplate } = __require("@aigne/afs/utils/uri-template");
|
|
78
|
+
let existingVars;
|
|
79
|
+
try {
|
|
80
|
+
existingVars = parseTemplate(manifest.uriTemplate, parsed.body);
|
|
81
|
+
} catch {
|
|
82
|
+
existingVars = {};
|
|
83
|
+
}
|
|
84
|
+
const allVars = { ...existingVars };
|
|
85
|
+
for (const name of varNames) if (!allVars[name] && mount.options?.[name] != null) allVars[name] = String(mount.options[name]);
|
|
86
|
+
try {
|
|
87
|
+
const newURI = buildURI(manifest.uriTemplate, allVars);
|
|
88
|
+
if (newURI !== mount.uri) mount.uri = newURI;
|
|
89
|
+
} catch {}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Attempt credential resolution for a mount, merging resolved values into mount.options.
|
|
93
|
+
*
|
|
94
|
+
* Returns the credential result if any fields were collected interactively,
|
|
95
|
+
* or null if no interactive collection was needed (or no schema/authContext).
|
|
96
|
+
*
|
|
97
|
+
* This function mutates mount.options and mount.auth/mount.token when credentials
|
|
98
|
+
* are resolved, so the subsequent registry.createProvider(mount) receives complete values.
|
|
99
|
+
*/
|
|
100
|
+
async function resolveAndMergeCredentials(mount, authContext, credentialStore, registry, opts) {
|
|
101
|
+
const info = await registry.getProviderInfo(mount.uri);
|
|
102
|
+
const schema = info?.schema ?? null;
|
|
103
|
+
const providerAuth = info?.auth;
|
|
104
|
+
if (!schema) return null;
|
|
105
|
+
mergeTemplateVarsIntoMount(mount, info?.manifest);
|
|
106
|
+
const { getSensitiveFields } = await import("@aigne/afs/utils/schema");
|
|
107
|
+
const sensitiveFieldsInSchema = getSensitiveFields(schema);
|
|
108
|
+
const schemaProps = schema.properties ?? {};
|
|
109
|
+
const hasEnvFields = Object.values(schemaProps).some((p) => Array.isArray(p?.env));
|
|
110
|
+
if (sensitiveFieldsInSchema.length === 0 && !hasEnvFields && !providerAuth) return null;
|
|
111
|
+
const { resolveCredentials } = await import("../credential/resolver.mjs");
|
|
112
|
+
const result = await resolveCredentials({
|
|
113
|
+
mount,
|
|
114
|
+
schema,
|
|
115
|
+
authContext,
|
|
116
|
+
credentialStore,
|
|
117
|
+
providerAuth,
|
|
118
|
+
forceCollect: opts?.forceCollect
|
|
119
|
+
});
|
|
120
|
+
if (!result) {
|
|
121
|
+
const fieldNames = Object.keys(schema.properties ?? {});
|
|
122
|
+
const known = /* @__PURE__ */ new Set();
|
|
123
|
+
if (mount.auth !== void 0) known.add("auth");
|
|
124
|
+
if (mount.token !== void 0) known.add("token");
|
|
125
|
+
if (mount.options) for (const k of Object.keys(mount.options)) known.add(k);
|
|
126
|
+
const missing = fieldNames.filter((f) => !known.has(f));
|
|
127
|
+
const fieldList = missing.length > 0 ? missing.join(", ") : fieldNames.join(", ");
|
|
128
|
+
throw new Error(`Missing credentials: ${fieldList}. Retry with them as args, e.g. { "uri": "${mount.uri}", "path": "${mount.path}", ${missing.map((f) => `"${f}": "..."`).join(", ")} }`);
|
|
129
|
+
}
|
|
130
|
+
if (Object.keys(result.values).length > 0) {
|
|
131
|
+
if (result.values.token !== void 0 && mount.token === void 0) mount.token = String(result.values.token);
|
|
132
|
+
if (result.values.auth !== void 0 && mount.auth === void 0) mount.auth = String(result.values.auth);
|
|
133
|
+
const mergedOpts = mount.options ?? {};
|
|
134
|
+
for (const [key, value] of Object.entries(result.values)) if (key !== "token" && key !== "auth" && mergedOpts[key] === void 0) mergedOpts[key] = value;
|
|
135
|
+
if (Object.keys(mergedOpts).length > 0) mount.options = mergedOpts;
|
|
136
|
+
}
|
|
137
|
+
rebuildURIFromTemplate(mount, info?.manifest);
|
|
138
|
+
return result.collected ? result : null;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Persist credential resolution result (sensitive → credentials.toml).
|
|
142
|
+
*/
|
|
143
|
+
async function persistCredentialResult(mount, result) {
|
|
144
|
+
if (Object.keys(result.sensitive).length > 0) try {
|
|
145
|
+
const { createCredentialStore } = await import("../credential/store.mjs");
|
|
146
|
+
await createCredentialStore().set(mount.uri, result.sensitive);
|
|
147
|
+
} catch (err) {
|
|
148
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
149
|
+
console.warn(`[mount] credential persistence failed: ${msg}`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Load stored credentials and merge into mount options during startup.
|
|
154
|
+
*/
|
|
155
|
+
async function mergeStoredCredentials(mounts, _mountSources, store) {
|
|
156
|
+
for (const mount of mounts) try {
|
|
157
|
+
const stored = await store.get(mount.uri);
|
|
158
|
+
if (stored) {
|
|
159
|
+
const opts = mount.options ?? {};
|
|
160
|
+
for (const [key, value] of Object.entries(stored)) if (key.startsWith("env:")) {
|
|
161
|
+
if (!opts.env) opts.env = {};
|
|
162
|
+
opts.env[key.slice(4)] = value;
|
|
163
|
+
} else if (opts[key] === void 0) opts[key] = value;
|
|
164
|
+
if (Object.keys(opts).length > 0) mount.options = opts;
|
|
165
|
+
}
|
|
166
|
+
} catch {}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Resolve and persist credentials for a mount configuration.
|
|
170
|
+
*
|
|
171
|
+
* Used by `mount add` CLI command to trigger credential collection
|
|
172
|
+
* at add-time rather than deferring to AFS creation.
|
|
173
|
+
*/
|
|
174
|
+
async function resolveCredentialsForMount(options) {
|
|
175
|
+
const { uri, mountPath, authContext, credentialStore, extraOptions, sensitiveArgs } = options;
|
|
176
|
+
const { cleanUri: configUri, envRecord } = extractEnvFromURI(uri);
|
|
177
|
+
const hasExtractedEnv = Object.keys(envRecord).length > 0;
|
|
178
|
+
const info = await (options.registry ?? new ProviderRegistry()).getProviderInfo(uri);
|
|
179
|
+
let schema = info?.schema ?? null;
|
|
180
|
+
const providerAuth = info?.auth;
|
|
181
|
+
if (!schema && extraOptions && Object.keys(extraOptions).length > 0) {
|
|
182
|
+
const { buildAdHocSchema } = await import("@aigne/afs/utils/schema");
|
|
183
|
+
schema = buildAdHocSchema(extraOptions, sensitiveArgs ?? []);
|
|
184
|
+
}
|
|
185
|
+
const envOnlyResult = () => {
|
|
186
|
+
if (!hasExtractedEnv) return null;
|
|
187
|
+
return {
|
|
188
|
+
collected: false,
|
|
189
|
+
nonSensitive: {},
|
|
190
|
+
allValues: {},
|
|
191
|
+
persistCredentials: async () => {
|
|
192
|
+
const toStore = {};
|
|
193
|
+
for (const [key, val] of Object.entries(envRecord)) toStore[`env:${key}`] = val;
|
|
194
|
+
if (credentialStore) try {
|
|
195
|
+
await credentialStore.set(configUri, toStore);
|
|
196
|
+
} catch (err) {
|
|
197
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
198
|
+
console.warn(`[mount add] credential persistence failed: ${msg}`);
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
sensitiveFields: [],
|
|
202
|
+
configUri
|
|
203
|
+
};
|
|
204
|
+
};
|
|
205
|
+
if (!schema) return envOnlyResult();
|
|
206
|
+
const properties = schema.properties;
|
|
207
|
+
if (!properties || Object.keys(properties).length === 0) return envOnlyResult();
|
|
208
|
+
if (sensitiveArgs && sensitiveArgs.length > 0) {
|
|
209
|
+
const mergedProps = { ...properties };
|
|
210
|
+
let changed = false;
|
|
211
|
+
for (const field of sensitiveArgs) if (mergedProps[field]) {
|
|
212
|
+
mergedProps[field] = {
|
|
213
|
+
...mergedProps[field],
|
|
214
|
+
sensitive: true
|
|
215
|
+
};
|
|
216
|
+
changed = true;
|
|
217
|
+
} else if (extraOptions?.[field] !== void 0) {
|
|
218
|
+
const value = extraOptions[field];
|
|
219
|
+
mergedProps[field] = {
|
|
220
|
+
type: typeof value === "number" ? "number" : typeof value === "boolean" ? "boolean" : "string",
|
|
221
|
+
sensitive: true
|
|
222
|
+
};
|
|
223
|
+
changed = true;
|
|
224
|
+
}
|
|
225
|
+
if (changed) schema = {
|
|
226
|
+
...schema,
|
|
227
|
+
properties: mergedProps
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
const { getSensitiveFields } = await import("@aigne/afs/utils/schema");
|
|
231
|
+
const sensitiveFieldsInSchema = getSensitiveFields(schema);
|
|
232
|
+
const schemaProps = schema.properties;
|
|
233
|
+
const hasEnvFields = Object.values(schemaProps).some((p) => Array.isArray(p?.env));
|
|
234
|
+
if (sensitiveFieldsInSchema.length === 0 && !hasEnvFields && !extraOptions) return envOnlyResult();
|
|
235
|
+
const mount = {
|
|
236
|
+
uri,
|
|
237
|
+
path: mountPath
|
|
238
|
+
};
|
|
239
|
+
if (extraOptions && Object.keys(extraOptions).length > 0) mount.options = {
|
|
240
|
+
...mount.options ?? {},
|
|
241
|
+
...extraOptions
|
|
242
|
+
};
|
|
243
|
+
mergeTemplateVarsIntoMount(mount, info?.manifest);
|
|
244
|
+
const { resolveCredentials } = await import("../credential/resolver.mjs");
|
|
245
|
+
const result = await resolveCredentials({
|
|
246
|
+
mount,
|
|
247
|
+
schema,
|
|
248
|
+
authContext,
|
|
249
|
+
credentialStore,
|
|
250
|
+
providerAuth,
|
|
251
|
+
forceCollect: options.forceCollect
|
|
252
|
+
});
|
|
253
|
+
if (!result) {
|
|
254
|
+
const fieldNames = Object.keys(properties);
|
|
255
|
+
throw new Error(`Missing credentials: ${fieldNames.join(", ")}. Retry with them as args, e.g. { "uri": "${uri}", "path": "${mountPath}", ${fieldNames.map((f) => `"${f}": "..."`).join(", ")} }`);
|
|
256
|
+
}
|
|
257
|
+
const sensitiveFieldSet = new Set(sensitiveFieldsInSchema);
|
|
258
|
+
const flatSensitive = {};
|
|
259
|
+
for (const field of sensitiveFieldsInSchema) {
|
|
260
|
+
const val = result.values[field];
|
|
261
|
+
if (val === void 0) continue;
|
|
262
|
+
if (field === "env" && typeof val === "object" && val !== null) for (const [envKey, envVal] of Object.entries(val)) flatSensitive[`env:${envKey}`] = String(envVal);
|
|
263
|
+
else flatSensitive[field] = String(val);
|
|
264
|
+
}
|
|
265
|
+
const nonSensitive = result.collected ? result.nonSensitive : extraOptions ? Object.fromEntries(Object.entries(extraOptions).filter(([k]) => !sensitiveFieldSet.has(k))) : {};
|
|
266
|
+
const persistCredentials = async () => {
|
|
267
|
+
const toStore = { ...flatSensitive };
|
|
268
|
+
for (const [key, val] of Object.entries(envRecord)) toStore[`env:${key}`] = val;
|
|
269
|
+
if (Object.keys(toStore).length > 0 && credentialStore) try {
|
|
270
|
+
await credentialStore.set(configUri, toStore);
|
|
271
|
+
} catch (err) {
|
|
272
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
273
|
+
console.warn(`[mount add] credential persistence failed: ${msg}`);
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
return {
|
|
277
|
+
collected: result.collected,
|
|
278
|
+
nonSensitive,
|
|
279
|
+
allValues: result.values,
|
|
280
|
+
persistCredentials,
|
|
281
|
+
sensitiveFields: sensitiveFieldsInSchema,
|
|
282
|
+
configUri: hasExtractedEnv ? configUri : void 0
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
//#endregion
|
|
287
|
+
export { extractEnvFromURI, mergeStoredCredentials, persistCredentialResult, resolveAndMergeCredentials, resolveCredentialsForMount };
|
|
288
|
+
//# sourceMappingURL=credential-helpers.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credential-helpers.mjs","names":[],"sources":["../../src/config/credential-helpers.ts"],"sourcesContent":["/**\n * Credential Resolution Helpers\n *\n * Extracted from afs-loader.ts to separate credential resolution concerns\n * from AFS lifecycle management. All credential-related logic lives here:\n * - URI env extraction (MCP schemes)\n * - URI template variable merging\n * - Credential resolution + merge into mount config\n * - Credential persistence\n * - CLI mount add credential resolution\n */\n\nimport type { AuthContext, MountConfig } from \"@aigne/afs\";\nimport { ProviderRegistry } from \"@aigne/afs\";\nimport { parseURI } from \"@aigne/afs/utils/uri\";\nimport type { CredentialStore } from \"../credential/store.js\";\n\n// ─── URI & Template Manipulation ─────────────────────────────────────────\n\n/**\n * Extract env query params from MCP URIs for secure credential storage.\n *\n * MCP servers receive secrets via env vars (e.g., `mcp+stdio://npx?env=API_KEY=sk-xxx`).\n * This function extracts env params from the URI so they can be stored in credentials.toml\n * instead of being persisted in plaintext in config.toml.\n *\n * Only applies to MCP schemes (mcp://, mcp+stdio://, mcp+sse://).\n * Non-MCP URIs are returned unchanged.\n */\nexport function extractEnvFromURI(uri: string): {\n cleanUri: string;\n envRecord: Record<string, string>;\n} {\n const parsed = parseURI(uri);\n const envRecord: Record<string, string> = {};\n\n // Only extract env for MCP schemes\n if (!parsed.scheme.startsWith(\"mcp\")) {\n return { cleanUri: uri, envRecord };\n }\n\n const envValues = parsed.query.env;\n if (!envValues) return { cleanUri: uri, envRecord };\n\n // Parse env=KEY=VALUE format (split on first = only)\n const envList = Array.isArray(envValues) ? envValues : [envValues];\n for (const entry of envList) {\n const eqIdx = entry.indexOf(\"=\");\n if (eqIdx > 0) {\n envRecord[entry.slice(0, eqIdx)] = entry.slice(eqIdx + 1);\n }\n }\n\n // Rebuild URI without env params, preserving other query params\n const queryIndex = uri.indexOf(\"?\");\n if (queryIndex < 0) return { cleanUri: uri, envRecord };\n\n const rawQuery = uri.slice(queryIndex + 1);\n const params = new URLSearchParams(rawQuery);\n params.delete(\"env\");\n const newQuery = params.toString();\n const base = uri.slice(0, queryIndex);\n const cleanUri = newQuery ? `${base}?${newQuery}` : base;\n\n return { cleanUri, envRecord };\n}\n\n/**\n * Extract template variables from mount.uri using the manifest's uriTemplate\n * and merge them into mount.options so the credential resolver sees them as \"known\".\n */\nexport function mergeTemplateVarsIntoMount(\n mount: MountConfig,\n manifest: import(\"@aigne/afs\").ProviderManifest | null | undefined,\n): void {\n if (!manifest?.uriTemplate) return;\n const { parseTemplate } =\n require(\"@aigne/afs/utils/uri-template\") as typeof import(\"@aigne/afs/utils/uri-template\");\n const parsed = parseURI(mount.uri);\n let templateVars: Record<string, string | undefined>;\n try {\n templateVars = parseTemplate(manifest.uriTemplate, parsed.body);\n } catch {\n return; // Body doesn't match template yet — nothing to merge\n }\n for (const [key, value] of Object.entries(templateVars)) {\n if (value !== undefined) {\n if (!mount.options) mount.options = {};\n if (mount.options[key] === undefined) {\n mount.options[key] = value;\n }\n }\n }\n}\n\n/**\n * After credential resolution, rebuild mount.uri from the template if the\n * current URI body is empty/incomplete and resolved options can fill template vars.\n */\nexport function rebuildURIFromTemplate(\n mount: MountConfig,\n manifest: import(\"@aigne/afs\").ProviderManifest | null | undefined,\n): void {\n if (!manifest?.uriTemplate) return;\n const { buildURI, getTemplateVariableNames } =\n require(\"@aigne/afs/utils/uri-template\") as typeof import(\"@aigne/afs/utils/uri-template\");\n const varNames = getTemplateVariableNames(manifest.uriTemplate);\n if (varNames.length === 0) return;\n\n const parsed = parseURI(mount.uri);\n const { parseTemplate } =\n require(\"@aigne/afs/utils/uri-template\") as typeof import(\"@aigne/afs/utils/uri-template\");\n let existingVars: Record<string, string | undefined>;\n try {\n existingVars = parseTemplate(manifest.uriTemplate, parsed.body);\n } catch {\n existingVars = {};\n }\n\n const allVars: Record<string, string | undefined> = { ...existingVars };\n for (const name of varNames) {\n if (!allVars[name] && mount.options?.[name] != null) {\n allVars[name] = String(mount.options[name]);\n }\n }\n\n try {\n const newURI = buildURI(manifest.uriTemplate, allVars);\n if (newURI !== mount.uri) {\n mount.uri = newURI;\n }\n } catch {\n // Still can't build a complete URI — that's OK, createProvider will handle it\n }\n}\n\n// ─── Credential Resolution Core ─────────────────────────────────────────\n\n/**\n * Attempt credential resolution for a mount, merging resolved values into mount.options.\n *\n * Returns the credential result if any fields were collected interactively,\n * or null if no interactive collection was needed (or no schema/authContext).\n *\n * This function mutates mount.options and mount.auth/mount.token when credentials\n * are resolved, so the subsequent registry.createProvider(mount) receives complete values.\n */\nexport async function resolveAndMergeCredentials(\n mount: MountConfig,\n authContext: AuthContext | undefined,\n credentialStore: CredentialStore | undefined,\n registry: ProviderRegistry,\n opts?: { forceCollect?: boolean },\n): Promise<import(\"../credential/resolver.js\").ResolveCredentialsResult | null> {\n const info = await registry.getProviderInfo(mount.uri);\n const schema = info?.schema ?? null;\n const providerAuth = info?.auth;\n\n if (!schema) return null;\n\n mergeTemplateVarsIntoMount(mount, info?.manifest);\n\n const { getSensitiveFields } = await import(\"@aigne/afs/utils/schema\");\n const sensitiveFieldsInSchema = getSensitiveFields(schema);\n const schemaProps = (schema as any).properties ?? {};\n const hasEnvFields = Object.values(schemaProps).some((p: any) => Array.isArray(p?.env));\n if (sensitiveFieldsInSchema.length === 0 && !hasEnvFields && !providerAuth) return null;\n\n const { resolveCredentials } = await import(\"../credential/resolver.js\");\n\n const result = await resolveCredentials({\n mount,\n schema,\n authContext,\n credentialStore,\n providerAuth,\n forceCollect: opts?.forceCollect,\n });\n\n if (!result) {\n const fieldNames = Object.keys((schema as any).properties ?? {});\n const known = new Set<string>();\n if (mount.auth !== undefined) known.add(\"auth\");\n if (mount.token !== undefined) known.add(\"token\");\n if (mount.options) {\n for (const k of Object.keys(mount.options)) known.add(k);\n }\n const missing = fieldNames.filter((f) => !known.has(f));\n const fieldList = missing.length > 0 ? missing.join(\", \") : fieldNames.join(\", \");\n throw new Error(\n `Missing credentials: ${fieldList}. ` +\n `Retry with them as args, e.g. { \"uri\": \"${mount.uri}\", \"path\": \"${mount.path}\", ${missing.map((f) => `\"${f}\": \"...\"`).join(\", \")} }`,\n );\n }\n\n if (Object.keys(result.values).length > 0) {\n if (result.values.token !== undefined && mount.token === undefined) {\n mount.token = String(result.values.token);\n }\n if (result.values.auth !== undefined && mount.auth === undefined) {\n mount.auth = String(result.values.auth);\n }\n\n const mergedOpts = mount.options ?? {};\n for (const [key, value] of Object.entries(result.values)) {\n if (key !== \"token\" && key !== \"auth\" && mergedOpts[key] === undefined) {\n mergedOpts[key] = value;\n }\n }\n if (Object.keys(mergedOpts).length > 0) {\n mount.options = mergedOpts;\n }\n }\n\n rebuildURIFromTemplate(mount, info?.manifest);\n\n return result.collected ? result : null;\n}\n\n/**\n * Persist credential resolution result (sensitive → credentials.toml).\n */\nexport async function persistCredentialResult(\n mount: MountConfig,\n result: import(\"../credential/resolver.js\").ResolveCredentialsResult,\n): Promise<void> {\n if (Object.keys(result.sensitive).length > 0) {\n try {\n const { createCredentialStore } = await import(\"../credential/store.js\");\n const store = createCredentialStore();\n await store.set(mount.uri, result.sensitive);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.warn(`[mount] credential persistence failed: ${msg}`);\n }\n }\n}\n\n/**\n * Load stored credentials and merge into mount options during startup.\n */\nexport async function mergeStoredCredentials(\n mounts: MountConfig[],\n _mountSources: Map<string, string>,\n store: CredentialStore,\n): Promise<void> {\n for (const mount of mounts) {\n try {\n const stored = await store.get(mount.uri);\n if (stored) {\n const opts = mount.options ?? {};\n for (const [key, value] of Object.entries(stored)) {\n if (key.startsWith(\"env:\")) {\n if (!opts.env) opts.env = {};\n (opts.env as Record<string, string>)[key.slice(4)] = value;\n } else if (opts[key] === undefined) {\n opts[key] = value;\n }\n }\n if (Object.keys(opts).length > 0) {\n mount.options = opts;\n }\n }\n } catch {\n // Credential lookup failure is non-fatal\n }\n }\n}\n\n// ─── Exported Credential Resolution for CLI mount add ───────────────────────\n\nexport interface ResolveCredentialsForMountOptions {\n cwd: string;\n uri: string;\n mountPath: string;\n authContext?: AuthContext;\n credentialStore?: CredentialStore;\n extraOptions?: Record<string, unknown>;\n sensitiveArgs?: string[];\n registry?: ProviderRegistry;\n forceCollect?: boolean;\n}\n\nexport interface ResolveCredentialsForMountResult {\n collected: boolean;\n nonSensitive: Record<string, unknown>;\n allValues: Record<string, unknown>;\n persistCredentials: () => Promise<void>;\n sensitiveFields: string[];\n configUri?: string;\n}\n\n/**\n * Resolve and persist credentials for a mount configuration.\n *\n * Used by `mount add` CLI command to trigger credential collection\n * at add-time rather than deferring to AFS creation.\n */\nexport async function resolveCredentialsForMount(\n options: ResolveCredentialsForMountOptions,\n): Promise<ResolveCredentialsForMountResult | null> {\n const { uri, mountPath, authContext, credentialStore, extraOptions, sensitiveArgs } = options;\n\n const { cleanUri: configUri, envRecord } = extractEnvFromURI(uri);\n const hasExtractedEnv = Object.keys(envRecord).length > 0;\n\n const registry = options.registry ?? new ProviderRegistry();\n const info = await registry.getProviderInfo(uri);\n let schema = info?.schema ?? null;\n const providerAuth = info?.auth;\n\n if (!schema && extraOptions && Object.keys(extraOptions).length > 0) {\n const { buildAdHocSchema } = await import(\"@aigne/afs/utils/schema\");\n schema = buildAdHocSchema(extraOptions, sensitiveArgs ?? []);\n }\n\n const envOnlyResult = (): ResolveCredentialsForMountResult | null => {\n if (!hasExtractedEnv) return null;\n return {\n collected: false,\n nonSensitive: {},\n allValues: {},\n persistCredentials: async () => {\n const toStore: Record<string, string> = {};\n for (const [key, val] of Object.entries(envRecord)) {\n toStore[`env:${key}`] = val;\n }\n if (credentialStore) {\n try {\n await credentialStore.set(configUri, toStore);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.warn(`[mount add] credential persistence failed: ${msg}`);\n }\n }\n },\n sensitiveFields: [],\n configUri,\n };\n };\n\n if (!schema) return envOnlyResult();\n\n const properties = (schema as any).properties;\n if (!properties || Object.keys(properties).length === 0) return envOnlyResult();\n\n if (sensitiveArgs && sensitiveArgs.length > 0) {\n const mergedProps = { ...properties };\n let changed = false;\n for (const field of sensitiveArgs) {\n if (mergedProps[field]) {\n mergedProps[field] = { ...mergedProps[field], sensitive: true };\n changed = true;\n } else if (extraOptions?.[field] !== undefined) {\n const value = extraOptions[field];\n mergedProps[field] = {\n type:\n typeof value === \"number\"\n ? \"number\"\n : typeof value === \"boolean\"\n ? \"boolean\"\n : \"string\",\n sensitive: true,\n };\n changed = true;\n }\n }\n if (changed) {\n schema = { ...schema, properties: mergedProps } as typeof schema;\n }\n }\n\n const { getSensitiveFields } = await import(\"@aigne/afs/utils/schema\");\n const sensitiveFieldsInSchema = getSensitiveFields(schema);\n const schemaProps = (schema as any).properties;\n const hasEnvFields = Object.values(schemaProps).some((p: any) => Array.isArray(p?.env));\n if (sensitiveFieldsInSchema.length === 0 && !hasEnvFields && !extraOptions)\n return envOnlyResult();\n\n const mount: MountConfig = { uri, path: mountPath };\n\n if (extraOptions && Object.keys(extraOptions).length > 0) {\n mount.options = { ...(mount.options ?? {}), ...extraOptions };\n }\n\n mergeTemplateVarsIntoMount(mount, info?.manifest);\n\n const { resolveCredentials } = await import(\"../credential/resolver.js\");\n\n const result = await resolveCredentials({\n mount,\n schema,\n authContext,\n credentialStore,\n providerAuth,\n forceCollect: options.forceCollect,\n });\n\n if (!result) {\n const fieldNames = Object.keys(properties);\n throw new Error(\n `Missing credentials: ${fieldNames.join(\", \")}. ` +\n `Retry with them as args, e.g. { \"uri\": \"${uri}\", \"path\": \"${mountPath}\", ${fieldNames.map((f) => `\"${f}\": \"...\"`).join(\", \")} }`,\n );\n }\n\n const sensitiveFieldSet = new Set(sensitiveFieldsInSchema);\n\n const flatSensitive: Record<string, string> = {};\n for (const field of sensitiveFieldsInSchema) {\n const val = result.values[field];\n if (val === undefined) continue;\n if (field === \"env\" && typeof val === \"object\" && val !== null) {\n for (const [envKey, envVal] of Object.entries(val as Record<string, string>)) {\n flatSensitive[`env:${envKey}`] = String(envVal);\n }\n } else {\n flatSensitive[field] = String(val);\n }\n }\n\n const nonSensitive: Record<string, unknown> = result.collected\n ? result.nonSensitive\n : extraOptions\n ? Object.fromEntries(Object.entries(extraOptions).filter(([k]) => !sensitiveFieldSet.has(k)))\n : {};\n\n const persistCredentials = async () => {\n const toStore = { ...flatSensitive };\n for (const [key, val] of Object.entries(envRecord)) {\n toStore[`env:${key}`] = val;\n }\n if (Object.keys(toStore).length > 0 && credentialStore) {\n try {\n await credentialStore.set(configUri, toStore);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.warn(`[mount add] credential persistence failed: ${msg}`);\n }\n }\n };\n\n return {\n collected: result.collected,\n nonSensitive,\n allValues: result.values,\n persistCredentials,\n sensitiveFields: sensitiveFieldsInSchema,\n configUri: hasExtractedEnv ? configUri : undefined,\n };\n}\n"],"mappings":"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"}
|
package/dist/config/loader.cjs
CHANGED
|
@@ -182,7 +182,8 @@ var ConfigLoader = class {
|
|
|
182
182
|
mounts: allMounts,
|
|
183
183
|
serve: mergedServe
|
|
184
184
|
},
|
|
185
|
-
mountSources
|
|
185
|
+
mountSources,
|
|
186
|
+
configDirs: entries.map((e) => e.configDir)
|
|
186
187
|
};
|
|
187
188
|
}
|
|
188
189
|
/**
|
|
@@ -214,6 +215,7 @@ var ConfigLoader = class {
|
|
|
214
215
|
const configLoader = new ConfigLoader();
|
|
215
216
|
|
|
216
217
|
//#endregion
|
|
218
|
+
exports.AFS_USER_CONFIG_DIR_ENV = AFS_USER_CONFIG_DIR_ENV;
|
|
217
219
|
exports.CONFIG_DIR_NAME = CONFIG_DIR_NAME;
|
|
218
220
|
exports.CONFIG_FILE_NAME = CONFIG_FILE_NAME;
|
|
219
221
|
exports.ConfigLoader = ConfigLoader;
|
package/dist/config/loader.mjs
CHANGED
|
@@ -181,7 +181,8 @@ var ConfigLoader = class {
|
|
|
181
181
|
mounts: allMounts,
|
|
182
182
|
serve: mergedServe
|
|
183
183
|
},
|
|
184
|
-
mountSources
|
|
184
|
+
mountSources,
|
|
185
|
+
configDirs: entries.map((e) => e.configDir)
|
|
185
186
|
};
|
|
186
187
|
}
|
|
187
188
|
/**
|
|
@@ -213,5 +214,5 @@ var ConfigLoader = class {
|
|
|
213
214
|
const configLoader = new ConfigLoader();
|
|
214
215
|
|
|
215
216
|
//#endregion
|
|
216
|
-
export { CONFIG_DIR_NAME, CONFIG_FILE_NAME, ConfigLoader };
|
|
217
|
+
export { AFS_USER_CONFIG_DIR_ENV, CONFIG_DIR_NAME, CONFIG_FILE_NAME, ConfigLoader };
|
|
217
218
|
//# sourceMappingURL=loader.mjs.map
|