@aigne/afs-cli 1.11.0-beta.11 → 1.11.0-beta.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/dist/cli.cjs +3 -2
  2. package/dist/cli.mjs +3 -2
  3. package/dist/cli.mjs.map +1 -1
  4. package/dist/config/afs-loader.cjs +36 -315
  5. package/dist/config/afs-loader.d.cts.map +1 -1
  6. package/dist/config/afs-loader.d.mts +2 -1
  7. package/dist/config/afs-loader.d.mts.map +1 -1
  8. package/dist/config/afs-loader.mjs +28 -307
  9. package/dist/config/afs-loader.mjs.map +1 -1
  10. package/dist/config/credential-helpers.cjs +303 -0
  11. package/dist/config/credential-helpers.d.mts +2 -0
  12. package/dist/config/credential-helpers.mjs +300 -0
  13. package/dist/config/credential-helpers.mjs.map +1 -0
  14. package/dist/config/loader.cjs +3 -1
  15. package/dist/config/loader.mjs +3 -2
  16. package/dist/config/loader.mjs.map +1 -1
  17. package/dist/config/program-install.cjs +450 -0
  18. package/dist/config/program-install.d.mts +1 -0
  19. package/dist/config/program-install.mjs +444 -0
  20. package/dist/config/program-install.mjs.map +1 -0
  21. package/dist/core/commands/connect.cjs +53 -0
  22. package/dist/core/commands/connect.d.mts +2 -0
  23. package/dist/core/commands/connect.mjs +55 -0
  24. package/dist/core/commands/connect.mjs.map +1 -0
  25. package/dist/core/commands/daemon.cjs +211 -0
  26. package/dist/core/commands/daemon.d.mts +2 -0
  27. package/dist/core/commands/daemon.mjs +212 -0
  28. package/dist/core/commands/daemon.mjs.map +1 -0
  29. package/dist/core/commands/explain.cjs +3 -1
  30. package/dist/core/commands/explain.mjs +3 -1
  31. package/dist/core/commands/explain.mjs.map +1 -1
  32. package/dist/core/commands/explore.cjs +47 -12
  33. package/dist/core/commands/explore.mjs +47 -12
  34. package/dist/core/commands/explore.mjs.map +1 -1
  35. package/dist/core/commands/gen-agent-md.cjs +126 -0
  36. package/dist/core/commands/gen-agent-md.d.mts +2 -0
  37. package/dist/core/commands/gen-agent-md.mjs +125 -0
  38. package/dist/core/commands/gen-agent-md.mjs.map +1 -0
  39. package/dist/core/commands/index.cjs +13 -1
  40. package/dist/core/commands/index.d.cts.map +1 -1
  41. package/dist/core/commands/index.d.mts +6 -0
  42. package/dist/core/commands/index.d.mts.map +1 -1
  43. package/dist/core/commands/index.mjs +13 -1
  44. package/dist/core/commands/index.mjs.map +1 -1
  45. package/dist/core/commands/install.cjs +139 -0
  46. package/dist/core/commands/install.d.mts +2 -0
  47. package/dist/core/commands/install.mjs +140 -0
  48. package/dist/core/commands/install.mjs.map +1 -0
  49. package/dist/core/commands/ls.cjs +14 -2
  50. package/dist/core/commands/ls.d.cts +2 -0
  51. package/dist/core/commands/ls.d.cts.map +1 -1
  52. package/dist/core/commands/ls.d.mts +2 -0
  53. package/dist/core/commands/ls.d.mts.map +1 -1
  54. package/dist/core/commands/ls.mjs +14 -2
  55. package/dist/core/commands/ls.mjs.map +1 -1
  56. package/dist/core/commands/mcp-bridge.cjs +201 -0
  57. package/dist/core/commands/mcp-bridge.d.mts +2 -0
  58. package/dist/core/commands/mcp-bridge.mjs +201 -0
  59. package/dist/core/commands/mcp-bridge.mjs.map +1 -0
  60. package/dist/core/commands/read.cjs +20 -7
  61. package/dist/core/commands/read.d.cts +2 -0
  62. package/dist/core/commands/read.d.cts.map +1 -1
  63. package/dist/core/commands/read.d.mts +2 -0
  64. package/dist/core/commands/read.d.mts.map +1 -1
  65. package/dist/core/commands/read.mjs +20 -7
  66. package/dist/core/commands/read.mjs.map +1 -1
  67. package/dist/core/commands/search.cjs +5 -1
  68. package/dist/core/commands/search.mjs +5 -1
  69. package/dist/core/commands/search.mjs.map +1 -1
  70. package/dist/core/commands/stat.mjs.map +1 -1
  71. package/dist/core/commands/types.d.cts +2 -0
  72. package/dist/core/commands/types.d.cts.map +1 -1
  73. package/dist/core/commands/types.d.mts +2 -0
  74. package/dist/core/commands/types.d.mts.map +1 -1
  75. package/dist/core/commands/types.mjs.map +1 -1
  76. package/dist/core/commands/vault.cjs +289 -0
  77. package/dist/core/commands/vault.d.mts +2 -0
  78. package/dist/core/commands/vault.mjs +289 -0
  79. package/dist/core/commands/vault.mjs.map +1 -0
  80. package/dist/core/commands/write.cjs +19 -6
  81. package/dist/core/commands/write.d.cts +2 -1
  82. package/dist/core/commands/write.d.cts.map +1 -1
  83. package/dist/core/commands/write.d.mts +2 -1
  84. package/dist/core/commands/write.d.mts.map +1 -1
  85. package/dist/core/commands/write.mjs +19 -6
  86. package/dist/core/commands/write.mjs.map +1 -1
  87. package/dist/core/executor/index.cjs +95 -19
  88. package/dist/core/executor/index.d.cts +4 -0
  89. package/dist/core/executor/index.d.cts.map +1 -1
  90. package/dist/core/executor/index.d.mts +4 -0
  91. package/dist/core/executor/index.d.mts.map +1 -1
  92. package/dist/core/executor/index.mjs +95 -19
  93. package/dist/core/executor/index.mjs.map +1 -1
  94. package/dist/core/formatters/index.d.mts +1 -0
  95. package/dist/core/formatters/install.cjs +40 -0
  96. package/dist/core/formatters/install.d.mts +1 -0
  97. package/dist/core/formatters/install.mjs +36 -0
  98. package/dist/core/formatters/install.mjs.map +1 -0
  99. package/dist/core/formatters/vault.cjs +36 -0
  100. package/dist/core/formatters/vault.mjs +32 -0
  101. package/dist/core/formatters/vault.mjs.map +1 -0
  102. package/dist/credential/auth-server.cjs +22 -4
  103. package/dist/credential/auth-server.mjs +22 -4
  104. package/dist/credential/auth-server.mjs.map +1 -1
  105. package/dist/credential/index.d.mts +2 -1
  106. package/dist/credential/mcp-auth-context.cjs +21 -5
  107. package/dist/credential/mcp-auth-context.mjs +21 -5
  108. package/dist/credential/mcp-auth-context.mjs.map +1 -1
  109. package/dist/credential/resolver.cjs +11 -3
  110. package/dist/credential/resolver.mjs +11 -3
  111. package/dist/credential/resolver.mjs.map +1 -1
  112. package/dist/credential/vault-store.d.mts +1 -0
  113. package/dist/daemon/config-manager.cjs +279 -0
  114. package/dist/daemon/config-manager.mjs +279 -0
  115. package/dist/daemon/config-manager.mjs.map +1 -0
  116. package/dist/daemon/manager.cjs +164 -0
  117. package/dist/daemon/manager.mjs +157 -0
  118. package/dist/daemon/manager.mjs.map +1 -0
  119. package/dist/daemon/server.cjs +220 -0
  120. package/dist/daemon/server.mjs +220 -0
  121. package/dist/daemon/server.mjs.map +1 -0
  122. package/dist/mcp/http-transport.cjs +14 -1
  123. package/dist/mcp/http-transport.mjs +14 -1
  124. package/dist/mcp/http-transport.mjs.map +1 -1
  125. package/dist/mcp/server.cjs +4 -2
  126. package/dist/mcp/server.mjs +4 -2
  127. package/dist/mcp/server.mjs.map +1 -1
  128. package/dist/mcp/tools.cjs +62 -12
  129. package/dist/mcp/tools.mjs +62 -12
  130. package/dist/mcp/tools.mjs.map +1 -1
  131. package/dist/program/daemon-integration.cjs +46 -0
  132. package/dist/program/daemon-integration.mjs +45 -0
  133. package/dist/program/daemon-integration.mjs.map +1 -0
  134. package/dist/program/program-manager.cjs +166 -0
  135. package/dist/program/program-manager.mjs +166 -0
  136. package/dist/program/program-manager.mjs.map +1 -0
  137. package/dist/program/trigger-scanner.cjs +148 -0
  138. package/dist/program/trigger-scanner.mjs +148 -0
  139. package/dist/program/trigger-scanner.mjs.map +1 -0
  140. package/dist/providers/vault/dist/_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.cjs +11 -0
  141. package/dist/providers/vault/dist/_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.mjs +11 -0
  142. package/dist/providers/vault/dist/_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.mjs.map +1 -0
  143. package/dist/providers/vault/dist/encrypted-file.cjs +158 -0
  144. package/dist/providers/vault/dist/encrypted-file.mjs +153 -0
  145. package/dist/providers/vault/dist/encrypted-file.mjs.map +1 -0
  146. package/dist/providers/vault/dist/index.cjs +405 -0
  147. package/dist/providers/vault/dist/index.mjs +400 -0
  148. package/dist/providers/vault/dist/index.mjs.map +1 -0
  149. package/dist/providers/vault/dist/key-resolver.cjs +181 -0
  150. package/dist/providers/vault/dist/key-resolver.mjs +180 -0
  151. package/dist/providers/vault/dist/key-resolver.mjs.map +1 -0
  152. package/dist/repl.cjs +109 -14
  153. package/dist/repl.d.cts.map +1 -1
  154. package/dist/repl.d.mts.map +1 -1
  155. package/dist/repl.mjs +109 -14
  156. package/dist/repl.mjs.map +1 -1
  157. package/package.json +27 -20
package/dist/cli.cjs CHANGED
@@ -25,12 +25,13 @@ async function main() {
25
25
  version: require_version.VERSION
26
26
  }).execute(args);
27
27
  if (result.success) {
28
+ process.exitCode = require_errors.ExitCode.OK;
28
29
  console.log(result.formatted);
29
- process.exit(require_errors.ExitCode.OK);
30
30
  } else {
31
+ process.exitCode = result.error?.code ?? require_errors.ExitCode.RUNTIME_ERROR;
31
32
  console.error(result.formatted);
32
- process.exit(result.error?.code ?? require_errors.ExitCode.RUNTIME_ERROR);
33
33
  }
34
+ process.exit(process.exitCode);
34
35
  }
35
36
  main().catch((error) => {
36
37
  console.error(error instanceof Error ? error.message : String(error));
package/dist/cli.mjs CHANGED
@@ -24,12 +24,13 @@ async function main() {
24
24
  version: VERSION
25
25
  }).execute(args);
26
26
  if (result.success) {
27
+ process.exitCode = ExitCode.OK;
27
28
  console.log(result.formatted);
28
- process.exit(ExitCode.OK);
29
29
  } else {
30
+ process.exitCode = result.error?.code ?? ExitCode.RUNTIME_ERROR;
30
31
  console.error(result.formatted);
31
- process.exit(result.error?.code ?? ExitCode.RUNTIME_ERROR);
32
32
  }
33
+ process.exit(process.exitCode);
33
34
  }
34
35
  main().catch((error) => {
35
36
  console.error(error instanceof Error ? error.message : String(error));
package/dist/cli.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.mjs","names":[],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * AFS CLI - Command Line Interface\n *\n * Simple CLI that delegates to executor. AFS is lazy-loaded on demand\n * by individual commands, so mount failures don't block config commands.\n */\n\nimport \"urlpattern-polyfill\";\nimport { hideBin } from \"yargs/helpers\";\nimport { AFSCommandExecutor } from \"./core/index.js\";\nimport { ExitCode } from \"./errors.js\";\nimport { VERSION } from \"./version.js\";\n\nasync function main() {\n const args = hideBin(process.argv);\n const cwd = process.cwd();\n\n // Check for -i / --interactive before yargs parsing\n if (args.includes(\"-i\") || args.includes(\"--interactive\")) {\n const { startRepl } = await import(\"./repl.js\");\n await startRepl({ cwd, version: VERSION });\n process.exit(ExitCode.OK);\n }\n\n const executor = new AFSCommandExecutor(undefined, {\n cwd,\n tty: process.stdout.isTTY ?? false,\n version: VERSION,\n });\n\n const result = await executor.execute(args);\n\n if (result.success) {\n console.log(result.formatted);\n process.exit(ExitCode.OK);\n } else {\n console.error(result.formatted);\n process.exit(result.error?.code ?? ExitCode.RUNTIME_ERROR);\n }\n}\n\nmain().catch((error) => {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(ExitCode.RUNTIME_ERROR);\n});\n"],"mappings":";;;;;;;;;AAeA,eAAe,OAAO;CACpB,MAAM,OAAO,QAAQ,QAAQ,KAAK;CAClC,MAAM,MAAM,QAAQ,KAAK;AAGzB,KAAI,KAAK,SAAS,KAAK,IAAI,KAAK,SAAS,gBAAgB,EAAE;EACzD,MAAM,EAAE,cAAc,MAAM,OAAO;AACnC,QAAM,UAAU;GAAE;GAAK,SAAS;GAAS,CAAC;AAC1C,UAAQ,KAAK,SAAS,GAAG;;CAS3B,MAAM,SAAS,MANE,IAAI,mBAAmB,QAAW;EACjD;EACA,KAAK,QAAQ,OAAO,SAAS;EAC7B,SAAS;EACV,CAAC,CAE4B,QAAQ,KAAK;AAE3C,KAAI,OAAO,SAAS;AAClB,UAAQ,IAAI,OAAO,UAAU;AAC7B,UAAQ,KAAK,SAAS,GAAG;QACpB;AACL,UAAQ,MAAM,OAAO,UAAU;AAC/B,UAAQ,KAAK,OAAO,OAAO,QAAQ,SAAS,cAAc;;;AAI9D,MAAM,CAAC,OAAO,UAAU;AACtB,SAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CAAC;AACrE,SAAQ,KAAK,SAAS,cAAc;EACpC"}
1
+ {"version":3,"file":"cli.mjs","names":[],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * AFS CLI - Command Line Interface\n *\n * Simple CLI that delegates to executor. AFS is lazy-loaded on demand\n * by individual commands, so mount failures don't block config commands.\n */\n\nimport \"urlpattern-polyfill\";\nimport { hideBin } from \"yargs/helpers\";\nimport { AFSCommandExecutor } from \"./core/index.js\";\nimport { ExitCode } from \"./errors.js\";\nimport { VERSION } from \"./version.js\";\n\nasync function main() {\n const args = hideBin(process.argv);\n const cwd = process.cwd();\n\n // Check for -i / --interactive before yargs parsing\n if (args.includes(\"-i\") || args.includes(\"--interactive\")) {\n const { startRepl } = await import(\"./repl.js\");\n await startRepl({ cwd, version: VERSION });\n process.exit(ExitCode.OK);\n }\n\n const executor = new AFSCommandExecutor(undefined, {\n cwd,\n tty: process.stdout.isTTY ?? false,\n version: VERSION,\n });\n\n const result = await executor.execute(args);\n\n if (result.success) {\n process.exitCode = ExitCode.OK;\n console.log(result.formatted);\n } else {\n process.exitCode = result.error?.code ?? ExitCode.RUNTIME_ERROR;\n console.error(result.formatted);\n }\n\n // Force exit — providers may hold background resources (MCP child processes,\n // Telegram long-polling, open HTTP connections) that keep the event loop alive.\n // stdout/stderr are flushed synchronously above via console.log/console.error.\n process.exit(process.exitCode);\n}\n\nmain().catch((error) => {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(ExitCode.RUNTIME_ERROR);\n});\n"],"mappings":";;;;;;;;;AAeA,eAAe,OAAO;CACpB,MAAM,OAAO,QAAQ,QAAQ,KAAK;CAClC,MAAM,MAAM,QAAQ,KAAK;AAGzB,KAAI,KAAK,SAAS,KAAK,IAAI,KAAK,SAAS,gBAAgB,EAAE;EACzD,MAAM,EAAE,cAAc,MAAM,OAAO;AACnC,QAAM,UAAU;GAAE;GAAK,SAAS;GAAS,CAAC;AAC1C,UAAQ,KAAK,SAAS,GAAG;;CAS3B,MAAM,SAAS,MANE,IAAI,mBAAmB,QAAW;EACjD;EACA,KAAK,QAAQ,OAAO,SAAS;EAC7B,SAAS;EACV,CAAC,CAE4B,QAAQ,KAAK;AAE3C,KAAI,OAAO,SAAS;AAClB,UAAQ,WAAW,SAAS;AAC5B,UAAQ,IAAI,OAAO,UAAU;QACxB;AACL,UAAQ,WAAW,OAAO,OAAO,QAAQ,SAAS;AAClD,UAAQ,MAAM,OAAO,UAAU;;AAMjC,SAAQ,KAAK,QAAQ,SAAS;;AAGhC,MAAM,CAAC,OAAO,UAAU;AACtB,SAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CAAC;AACrE,SAAQ,KAAK,SAAS,cAAc;EACpC"}
@@ -1,4 +1,5 @@
1
1
  const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
2
+ const require_credential_helpers = require('./credential-helpers.cjs');
2
3
  const require_loader = require('./loader.cjs');
3
4
  const require_mount_commands = require('./mount-commands.cjs');
4
5
  let _aigne_afs = require("@aigne/afs");
@@ -27,17 +28,26 @@ function registerWorkspaceFactory(registry) {
27
28
  });
28
29
  });
29
30
  }
30
- let cached;
31
+ const cacheMap = /* @__PURE__ */ new Map();
32
+ function cacheKey(cwd) {
33
+ const { resolve } = require("node:path");
34
+ return resolve(cwd);
35
+ }
31
36
  /**
32
- * Load AFS with caching - first call creates, subsequent calls return cached instance
37
+ * Load AFS with per-cwd caching same cwd returns same instance,
38
+ * different cwd creates a separate instance.
33
39
  */
34
40
  async function loadAFS(cwd, options) {
41
+ const key = cacheKey(cwd);
42
+ const cached = cacheMap.get(key);
35
43
  if (cached) return {
36
44
  afs: cached,
37
- failures: []
45
+ failures: [],
46
+ configMountPaths: [],
47
+ registry: new _aigne_afs.ProviderRegistry()
38
48
  };
39
49
  const result = await createAFS(cwd, options);
40
- cached = result.afs;
50
+ cacheMap.set(key, result.afs);
41
51
  return result;
42
52
  }
43
53
  /**
@@ -64,10 +74,10 @@ async function createAFS(cwd, options) {
64
74
  workspacePath: parsed.body,
65
75
  registry,
66
76
  createProvider: async (subMount) => {
67
- const credResult = await resolveAndMergeCredentials(subMount, authContext, credentialStore, registry);
77
+ const credResult = await require_credential_helpers.resolveAndMergeCredentials(subMount, authContext, credentialStore, registry);
68
78
  const provider = await registry.createProvider(subMount);
69
79
  if (credResult) {
70
- await persistCredentialResult(subMount, credResult);
80
+ await require_credential_helpers.persistCredentialResult(subMount, credResult);
71
81
  const opts = subMount.options ?? {};
72
82
  for (const key of Object.keys(credResult.sensitive)) delete opts[key];
73
83
  subMount.options = Object.keys(opts).length > 0 ? opts : void 0;
@@ -84,9 +94,13 @@ async function createAFS(cwd, options) {
84
94
  ...mount.options
85
95
  });
86
96
  });
97
+ afs.createProviderFromMount = async (mount) => {
98
+ await require_credential_helpers.resolveAndMergeCredentials(mount, authContext, credentialStore, registry);
99
+ return registry.createProvider(mount);
100
+ };
87
101
  afs.loadProvider = async (uri, mountPath, options$1) => {
88
102
  (0, _aigne_afs_utils_uri.parseURI)(uri);
89
- const { cleanUri: loadConfigUri, envRecord: loadEnvRecord } = extractEnvFromURI(uri);
103
+ const { cleanUri: loadConfigUri, envRecord: loadEnvRecord } = require_credential_helpers.extractEnvFromURI(uri);
90
104
  const hasLoadEnv = Object.keys(loadEnvRecord).length > 0;
91
105
  const { accessMode, auth, description, scope, ...providerOptions } = options$1 ?? {};
92
106
  if (hasLoadEnv) providerOptions.env = {
@@ -102,7 +116,7 @@ async function createAFS(cwd, options) {
102
116
  options: Object.keys(providerOptions).length > 0 ? providerOptions : void 0
103
117
  };
104
118
  const persistScope = scope || "cwd";
105
- let credResult = await resolveAndMergeCredentials(mount, authContext, credentialStore, registry);
119
+ let credResult = await require_credential_helpers.resolveAndMergeCredentials(mount, authContext, credentialStore, registry);
106
120
  try {
107
121
  const provider = await registry.createProvider(mount);
108
122
  await afs.mount(provider, mountPath);
@@ -117,13 +131,13 @@ async function createAFS(cwd, options) {
117
131
  description: description ?? void 0,
118
132
  options: Object.keys(retryProviderOptions).length > 0 ? retryProviderOptions : void 0
119
133
  };
120
- credResult = await resolveAndMergeCredentials(retryMount, authContext, credentialStore, registry, { forceCollect: true });
134
+ credResult = await require_credential_helpers.resolveAndMergeCredentials(retryMount, authContext, credentialStore, registry, { forceCollect: true });
121
135
  const retryProvider = await registry.createProvider(retryMount);
122
136
  await afs.mount(retryProvider, mountPath);
123
137
  Object.assign(mount, retryMount);
124
138
  } else throw mountError;
125
139
  }
126
- if (credResult) await persistCredentialResult(mount, credResult);
140
+ if (credResult) await require_credential_helpers.persistCredentialResult(mount, credResult);
127
141
  if (hasLoadEnv && credentialStore) try {
128
142
  const envCreds = {};
129
143
  for (const [k, v] of Object.entries(loadEnvRecord)) envCreds[`env:${k}`] = v;
@@ -177,14 +191,14 @@ async function createAFS(cwd, options) {
177
191
  };
178
192
  if (config.registry?.enabled !== false) try {
179
193
  const { AFSRegistry } = await import("@aigne/afs-registry");
180
- const officialRegistry = new AFSRegistry(config.registry?.providers?.length ? { providers: config.registry.providers } : { url: "https://raw.githubusercontent.com/ArcBlock/afs-registry/refs/heads/main/providers.json" });
181
- await afs.mount(officialRegistry, "/registry/official");
182
- const internalRegistry = new AFSRegistry();
183
- await afs.mount(internalRegistry, "/registry/internal");
194
+ const registry$1 = new AFSRegistry(config.registry?.providers?.length ? { providers: config.registry.providers } : void 0);
195
+ await afs.mount(registry$1, "/registry");
184
196
  } catch {}
185
197
  if (config.mounts.length === 0) return {
186
198
  afs,
187
- failures: []
199
+ failures: [],
200
+ configMountPaths: [],
201
+ registry
188
202
  };
189
203
  const total = config.mounts.length;
190
204
  let completed = 0;
@@ -194,7 +208,7 @@ async function createAFS(cwd, options) {
194
208
  completed: 0,
195
209
  failed: 0
196
210
  });
197
- if (credentialStore && mountSources.size > 0) await mergeStoredCredentials(config.mounts, mountSources, credentialStore);
211
+ if (credentialStore && mountSources.size > 0) await require_credential_helpers.mergeStoredCredentials(config.mounts, mountSources, credentialStore);
198
212
  const results = await Promise.allSettled(config.mounts.map(async (mount) => {
199
213
  const provider = await registry.createProvider(mount);
200
214
  await afs.mount(provider, mount.path, { namespace: mount.namespace ?? null });
@@ -234,302 +248,9 @@ async function createAFS(cwd, options) {
234
248
  if (succeeded.length === 0 && config.mounts.length > 0) throw new Error("All providers failed to mount");
235
249
  return {
236
250
  afs,
237
- failures
238
- };
239
- }
240
- /**
241
- * Extract env query params from MCP URIs for secure credential storage.
242
- *
243
- * MCP servers receive secrets via env vars (e.g., `mcp+stdio://npx?env=API_KEY=sk-xxx`).
244
- * This function extracts env params from the URI so they can be stored in credentials.toml
245
- * instead of being persisted in plaintext in config.toml.
246
- *
247
- * Only applies to MCP schemes (mcp://, mcp+stdio://, mcp+sse://).
248
- * Non-MCP URIs are returned unchanged.
249
- */
250
- function extractEnvFromURI(uri) {
251
- const parsed = (0, _aigne_afs_utils_uri.parseURI)(uri);
252
- const envRecord = {};
253
- if (!parsed.scheme.startsWith("mcp")) return {
254
- cleanUri: uri,
255
- envRecord
256
- };
257
- const envValues = parsed.query.env;
258
- if (!envValues) return {
259
- cleanUri: uri,
260
- envRecord
261
- };
262
- const envList = Array.isArray(envValues) ? envValues : [envValues];
263
- for (const entry of envList) {
264
- const eqIdx = entry.indexOf("=");
265
- if (eqIdx > 0) envRecord[entry.slice(0, eqIdx)] = entry.slice(eqIdx + 1);
266
- }
267
- const queryIndex = uri.indexOf("?");
268
- if (queryIndex < 0) return {
269
- cleanUri: uri,
270
- envRecord
271
- };
272
- const rawQuery = uri.slice(queryIndex + 1);
273
- const params = new URLSearchParams(rawQuery);
274
- params.delete("env");
275
- const newQuery = params.toString();
276
- const base = uri.slice(0, queryIndex);
277
- return {
278
- cleanUri: newQuery ? `${base}?${newQuery}` : base,
279
- envRecord
280
- };
281
- }
282
- /**
283
- * Extract template variables from mount.uri using the manifest's uriTemplate
284
- * and merge them into mount.options so the credential resolver sees them as "known".
285
- *
286
- * Example: cloudflare://d9e5fca3... + template "cloudflare://{accountId}"
287
- * → mount.options.accountId = "d9e5fca3..."
288
- */
289
- function mergeTemplateVarsIntoMount(mount, manifest) {
290
- if (!manifest?.uriTemplate) return;
291
- const { parseTemplate } = require("@aigne/afs/utils/uri-template");
292
- const parsed = (0, _aigne_afs_utils_uri.parseURI)(mount.uri);
293
- let templateVars;
294
- try {
295
- templateVars = parseTemplate(manifest.uriTemplate, parsed.body);
296
- } catch {
297
- return;
298
- }
299
- for (const [key, value] of Object.entries(templateVars)) if (value !== void 0) {
300
- if (!mount.options) mount.options = {};
301
- if (mount.options[key] === void 0) mount.options[key] = value;
302
- }
303
- }
304
- /**
305
- * After credential resolution, rebuild mount.uri from the template if the
306
- * current URI body is empty/incomplete and resolved options can fill template vars.
307
- *
308
- * Example: mount.uri = "cloudflare://" (empty body), mount.options.accountId = "abc"
309
- * → mount.uri = "cloudflare://abc"
310
- */
311
- function rebuildURIFromTemplate(mount, manifest) {
312
- if (!manifest?.uriTemplate) return;
313
- const { buildURI, getTemplateVariableNames } = require("@aigne/afs/utils/uri-template");
314
- const varNames = getTemplateVariableNames(manifest.uriTemplate);
315
- if (varNames.length === 0) return;
316
- const parsed = (0, _aigne_afs_utils_uri.parseURI)(mount.uri);
317
- const { parseTemplate } = require("@aigne/afs/utils/uri-template");
318
- let existingVars;
319
- try {
320
- existingVars = parseTemplate(manifest.uriTemplate, parsed.body);
321
- } catch {
322
- existingVars = {};
323
- }
324
- const allVars = { ...existingVars };
325
- for (const name of varNames) if (!allVars[name] && mount.options?.[name] != null) allVars[name] = String(mount.options[name]);
326
- try {
327
- const newURI = buildURI(manifest.uriTemplate, allVars);
328
- if (newURI !== mount.uri) mount.uri = newURI;
329
- } catch {}
330
- }
331
- /**
332
- * Attempt credential resolution for a mount, merging resolved values into mount.options.
333
- *
334
- * Returns the credential result if any fields were collected interactively,
335
- * or null if no interactive collection was needed (or no schema/authContext).
336
- *
337
- * This function mutates mount.options and mount.auth/mount.token when credentials
338
- * are resolved, so the subsequent registry.createProvider(mount) receives complete values.
339
- */
340
- async function resolveAndMergeCredentials(mount, authContext, credentialStore, registry, opts) {
341
- const info = await registry.getProviderInfo(mount.uri);
342
- const schema = info?.schema ?? null;
343
- const providerAuth = info?.auth;
344
- if (!schema) return null;
345
- mergeTemplateVarsIntoMount(mount, info?.manifest);
346
- const { getSensitiveFields } = await import("@aigne/afs/utils/schema");
347
- const sensitiveFieldsInSchema = getSensitiveFields(schema);
348
- const schemaProps = schema.properties ?? {};
349
- const hasEnvFields = Object.values(schemaProps).some((p) => Array.isArray(p?.env));
350
- if (sensitiveFieldsInSchema.length === 0 && !hasEnvFields && !providerAuth) return null;
351
- const { resolveCredentials } = await Promise.resolve().then(() => require("../credential/resolver.cjs"));
352
- const result = await resolveCredentials({
353
- mount,
354
- schema,
355
- authContext,
356
- credentialStore,
357
- providerAuth,
358
- forceCollect: opts?.forceCollect
359
- });
360
- if (!result) {
361
- const fieldNames = Object.keys(schema.properties ?? {});
362
- const known = /* @__PURE__ */ new Set();
363
- if (mount.auth !== void 0) known.add("auth");
364
- if (mount.token !== void 0) known.add("token");
365
- if (mount.options) for (const k of Object.keys(mount.options)) known.add(k);
366
- const missing = fieldNames.filter((f) => !known.has(f));
367
- const fieldList = missing.length > 0 ? missing.join(", ") : fieldNames.join(", ");
368
- throw new Error(`Missing credentials: ${fieldList}. Retry with them as args, e.g. { "uri": "${mount.uri}", "path": "${mount.path}", ${missing.map((f) => `"${f}": "..."`).join(", ")} }`);
369
- }
370
- if (Object.keys(result.values).length > 0) {
371
- if (result.values.token !== void 0 && mount.token === void 0) mount.token = String(result.values.token);
372
- if (result.values.auth !== void 0 && mount.auth === void 0) mount.auth = String(result.values.auth);
373
- const opts$1 = mount.options ?? {};
374
- for (const [key, value] of Object.entries(result.values)) if (key !== "token" && key !== "auth" && opts$1[key] === void 0) opts$1[key] = value;
375
- if (Object.keys(opts$1).length > 0) mount.options = opts$1;
376
- }
377
- rebuildURIFromTemplate(mount, info?.manifest);
378
- return result.collected ? result : null;
379
- }
380
- /**
381
- * Persist credential resolution result (sensitive → credentials.toml, non-sensitive → config).
382
- */
383
- async function persistCredentialResult(mount, result) {
384
- if (Object.keys(result.sensitive).length > 0) try {
385
- const { createCredentialStore } = await Promise.resolve().then(() => require("../credential/store.cjs"));
386
- await createCredentialStore().set(mount.uri, result.sensitive);
387
- } catch (err) {
388
- const msg = err instanceof Error ? err.message : String(err);
389
- console.warn(`[mount] credential persistence failed: ${msg}`);
390
- }
391
- }
392
- /**
393
- * Load stored credentials and merge into mount options during startup.
394
- *
395
- * Credentials are keyed by URI (the resource identity), not mount path.
396
- */
397
- async function mergeStoredCredentials(mounts, _mountSources, store) {
398
- for (const mount of mounts) try {
399
- const stored = await store.get(mount.uri);
400
- if (stored) {
401
- const opts = mount.options ?? {};
402
- for (const [key, value] of Object.entries(stored)) if (key.startsWith("env:")) {
403
- if (!opts.env) opts.env = {};
404
- opts.env[key.slice(4)] = value;
405
- } else if (opts[key] === void 0) opts[key] = value;
406
- if (Object.keys(opts).length > 0) mount.options = opts;
407
- }
408
- } catch {}
409
- }
410
- /**
411
- * Resolve and persist credentials for a mount configuration.
412
- *
413
- * Used by `mount add` CLI command to trigger credential collection
414
- * at add-time rather than deferring to AFS creation.
415
- *
416
- * - Gets provider schema via registry
417
- * - Runs 4-step credential resolution
418
- * - Persists sensitive values to credentials.toml
419
- * - Returns non-sensitive values for caller to update config
420
- *
421
- * Returns null if no schema found or no credentials needed.
422
- * Throws if user cancels collection when credentials are required.
423
- */
424
- async function resolveCredentialsForMount(options) {
425
- const { uri, mountPath, authContext, credentialStore, extraOptions, sensitiveArgs } = options;
426
- const { cleanUri: configUri, envRecord } = extractEnvFromURI(uri);
427
- const hasExtractedEnv = Object.keys(envRecord).length > 0;
428
- const info = await (options.registry ?? new _aigne_afs.ProviderRegistry()).getProviderInfo(uri);
429
- let schema = info?.schema ?? null;
430
- const providerAuth = info?.auth;
431
- if (!schema && extraOptions && Object.keys(extraOptions).length > 0) {
432
- const { buildAdHocSchema } = await import("@aigne/afs/utils/schema");
433
- schema = buildAdHocSchema(extraOptions, sensitiveArgs ?? []);
434
- }
435
- const envOnlyResult = () => {
436
- if (!hasExtractedEnv) return null;
437
- return {
438
- collected: false,
439
- nonSensitive: {},
440
- allValues: {},
441
- persistCredentials: async () => {
442
- const toStore = {};
443
- for (const [key, val] of Object.entries(envRecord)) toStore[`env:${key}`] = val;
444
- if (credentialStore) try {
445
- await credentialStore.set(configUri, toStore);
446
- } catch (err) {
447
- const msg = err instanceof Error ? err.message : String(err);
448
- console.warn(`[mount add] credential persistence failed: ${msg}`);
449
- }
450
- },
451
- sensitiveFields: [],
452
- configUri
453
- };
454
- };
455
- if (!schema) return envOnlyResult();
456
- const properties = schema.properties;
457
- if (!properties || Object.keys(properties).length === 0) return envOnlyResult();
458
- if (sensitiveArgs && sensitiveArgs.length > 0) {
459
- const mergedProps = { ...properties };
460
- let changed = false;
461
- for (const field of sensitiveArgs) if (mergedProps[field]) {
462
- mergedProps[field] = {
463
- ...mergedProps[field],
464
- sensitive: true
465
- };
466
- changed = true;
467
- } else if (extraOptions?.[field] !== void 0) {
468
- const value = extraOptions[field];
469
- mergedProps[field] = {
470
- type: typeof value === "number" ? "number" : typeof value === "boolean" ? "boolean" : "string",
471
- sensitive: true
472
- };
473
- changed = true;
474
- }
475
- if (changed) schema = {
476
- ...schema,
477
- properties: mergedProps
478
- };
479
- }
480
- const { getSensitiveFields } = await import("@aigne/afs/utils/schema");
481
- const sensitiveFieldsInSchema = getSensitiveFields(schema);
482
- const schemaProps = schema.properties;
483
- const hasEnvFields = Object.values(schemaProps).some((p) => Array.isArray(p?.env));
484
- if (sensitiveFieldsInSchema.length === 0 && !hasEnvFields && !extraOptions) return envOnlyResult();
485
- const mount = {
486
- uri,
487
- path: mountPath
488
- };
489
- if (extraOptions && Object.keys(extraOptions).length > 0) mount.options = {
490
- ...mount.options ?? {},
491
- ...extraOptions
492
- };
493
- mergeTemplateVarsIntoMount(mount, info?.manifest);
494
- const { resolveCredentials } = await Promise.resolve().then(() => require("../credential/resolver.cjs"));
495
- const result = await resolveCredentials({
496
- mount,
497
- schema,
498
- authContext,
499
- credentialStore,
500
- providerAuth,
501
- forceCollect: options.forceCollect
502
- });
503
- if (!result) {
504
- const fieldNames = Object.keys(properties);
505
- throw new Error(`Missing credentials: ${fieldNames.join(", ")}. Retry with them as args, e.g. { "uri": "${uri}", "path": "${mountPath}", ${fieldNames.map((f) => `"${f}": "..."`).join(", ")} }`);
506
- }
507
- const sensitiveFieldSet = new Set(sensitiveFieldsInSchema);
508
- const flatSensitive = {};
509
- for (const field of sensitiveFieldsInSchema) {
510
- const val = result.values[field];
511
- if (val === void 0) continue;
512
- if (field === "env" && typeof val === "object" && val !== null) for (const [envKey, envVal] of Object.entries(val)) flatSensitive[`env:${envKey}`] = String(envVal);
513
- else flatSensitive[field] = String(val);
514
- }
515
- const nonSensitive = result.collected ? result.nonSensitive : extraOptions ? Object.fromEntries(Object.entries(extraOptions).filter(([k]) => !sensitiveFieldSet.has(k))) : {};
516
- const persistCredentials = async () => {
517
- const toStore = { ...flatSensitive };
518
- for (const [key, val] of Object.entries(envRecord)) toStore[`env:${key}`] = val;
519
- if (Object.keys(toStore).length > 0 && credentialStore) try {
520
- await credentialStore.set(configUri, toStore);
521
- } catch (err) {
522
- const msg = err instanceof Error ? err.message : String(err);
523
- console.warn(`[mount add] credential persistence failed: ${msg}`);
524
- }
525
- };
526
- return {
527
- collected: result.collected,
528
- nonSensitive,
529
- allValues: result.values,
530
- persistCredentials,
531
- sensitiveFields: sensitiveFieldsInSchema,
532
- configUri: hasExtractedEnv ? configUri : void 0
251
+ failures,
252
+ configMountPaths: succeeded,
253
+ registry
533
254
  };
534
255
  }
535
256
  /**
@@ -565,8 +286,8 @@ async function verifyMount(uri, mountPath, options) {
565
286
  const msg = err instanceof Error ? err.message : String(err);
566
287
  throw new Error(`Mount verification failed: could not reach provider at ${uri}. Error: ${msg}. Check your URI and credentials.`);
567
288
  } finally {
568
- if (typeof provider.close === "function") try {
569
- await provider.close();
289
+ try {
290
+ await provider.close?.();
570
291
  } catch {}
571
292
  }
572
293
  }
@@ -574,5 +295,5 @@ async function verifyMount(uri, mountPath, options) {
574
295
  //#endregion
575
296
  exports.createAFS = createAFS;
576
297
  exports.loadAFS = loadAFS;
577
- exports.resolveCredentialsForMount = resolveCredentialsForMount;
298
+ exports.resolveCredentialsForMount = require_credential_helpers.resolveCredentialsForMount;
578
299
  exports.verifyMount = verifyMount;
@@ -1 +1 @@
1
- {"version":3,"file":"afs-loader.d.cts","names":[],"sources":["../../src/config/afs-loader.ts"],"mappings":";;;;UA0DiB,kBAAA;EACf,KAAA;EACA,SAAA;EACA,MAAA;AAAA;AAAA,UAae,gBAAA;EACf,UAAA,IAAc,KAAA,EAAO,kBAAA;;EAErB,WAAA,GAAc,WAAA;;EAEd,eAAA,GAAkB,eAAA;AAAA"}
1
+ {"version":3,"file":"afs-loader.d.cts","names":[],"sources":["../../src/config/afs-loader.ts"],"mappings":";;;;UA2EiB,kBAAA;EACf,KAAA;EACA,SAAA;EACA,MAAA;AAAA;AAAA,UAiBe,gBAAA;EACf,UAAA,IAAc,KAAA,EAAO,kBAAA;;EAErB,WAAA,GAAc,WAAA;;EAEd,eAAA,GAAkB,eAAA;AAAA"}
@@ -1,5 +1,6 @@
1
1
  import { CredentialStore } from "../credential/store.mjs";
2
- import { AFS, AuthContext, ProviderRegistry } from "@aigne/afs";
2
+ import "./credential-helpers.mjs";
3
+ import { AFS, AuthContext } from "@aigne/afs";
3
4
 
4
5
  //#region src/config/afs-loader.d.ts
5
6
  interface MountProgressEvent {
@@ -1 +1 @@
1
- {"version":3,"file":"afs-loader.d.mts","names":[],"sources":["../../src/config/afs-loader.ts"],"mappings":";;;;UA0DiB,kBAAA;EACf,KAAA;EACA,SAAA;EACA,MAAA;AAAA;AAAA,UAae,gBAAA;EACf,UAAA,IAAc,KAAA,EAAO,kBAAA;;EAErB,WAAA,GAAc,WAAA;;EAEd,eAAA,GAAkB,eAAA;AAAA"}
1
+ {"version":3,"file":"afs-loader.d.mts","names":[],"sources":["../../src/config/afs-loader.ts"],"mappings":";;;;;UA2EiB,kBAAA;EACf,KAAA;EACA,SAAA;EACA,MAAA;AAAA;AAAA,UAiBe,gBAAA;EACf,UAAA,IAAc,KAAA,EAAO,kBAAA;;EAErB,WAAA,GAAc,WAAA;;EAEd,eAAA,GAAkB,eAAA;AAAA"}