@easynet/agent-llm 1.0.49 → 1.0.50

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 (94) hide show
  1. package/README.md +18 -6
  2. package/dist/api/create-agent-llm.d.ts +2 -2
  3. package/dist/api/create-agent-llm.d.ts.map +1 -1
  4. package/dist/api/create-embed-fn.d.ts +10 -0
  5. package/dist/api/create-embed-fn.d.ts.map +1 -0
  6. package/dist/api/get-default-llm-config.d.ts +3 -3
  7. package/dist/api/get-default-llm-config.d.ts.map +1 -1
  8. package/dist/chunk-36PPGV4O.js +1 -0
  9. package/dist/chunk-36PPGV4O.js.map +1 -0
  10. package/dist/chunk-6EQCGQTV.js +154 -0
  11. package/dist/chunk-6EQCGQTV.js.map +1 -0
  12. package/dist/chunk-7VIJ4MFU.js +139 -0
  13. package/dist/chunk-7VIJ4MFU.js.map +1 -0
  14. package/dist/chunk-AUQEXHUP.js +105 -0
  15. package/dist/chunk-AUQEXHUP.js.map +1 -0
  16. package/dist/chunk-FVQ3PKER.js +354 -0
  17. package/dist/chunk-FVQ3PKER.js.map +1 -0
  18. package/dist/chunk-FZWXYGR6.js +191 -0
  19. package/dist/chunk-FZWXYGR6.js.map +1 -0
  20. package/dist/chunk-G7MKWPEI.js +14 -0
  21. package/dist/chunk-G7MKWPEI.js.map +1 -0
  22. package/dist/chunk-KE7IMUSA.js +223 -0
  23. package/dist/chunk-KE7IMUSA.js.map +1 -0
  24. package/dist/chunk-SPDXNDDD.js +114 -0
  25. package/dist/chunk-SPDXNDDD.js.map +1 -0
  26. package/dist/chunk-WK6P4EOC.js +147 -0
  27. package/dist/chunk-WK6P4EOC.js.map +1 -0
  28. package/dist/cli/index.js +18 -3
  29. package/dist/cli/index.js.map +1 -1
  30. package/dist/config/index.d.ts +1 -0
  31. package/dist/config/index.d.ts.map +1 -1
  32. package/dist/config/index.js +40 -0
  33. package/dist/config/index.js.map +1 -0
  34. package/dist/config/loader.d.ts +15 -0
  35. package/dist/config/loader.d.ts.map +1 -1
  36. package/dist/config/parser.d.ts +2 -2
  37. package/dist/config/parser.d.ts.map +1 -1
  38. package/dist/config/yaml-utils.d.ts +13 -0
  39. package/dist/config/yaml-utils.d.ts.map +1 -0
  40. package/dist/connectivity/check.d.ts +18 -0
  41. package/dist/connectivity/check.d.ts.map +1 -0
  42. package/dist/connectivity/index.d.ts +3 -0
  43. package/dist/connectivity/index.d.ts.map +1 -0
  44. package/dist/connectivity/index.js +11 -0
  45. package/dist/connectivity/index.js.map +1 -0
  46. package/dist/connectivity/types.d.ts +13 -0
  47. package/dist/connectivity/types.d.ts.map +1 -0
  48. package/dist/extensions/index.js +36 -0
  49. package/dist/extensions/index.js.map +1 -0
  50. package/dist/extensions/npm-protocol.d.ts +1 -1
  51. package/dist/extensions/npm-protocol.d.ts.map +1 -1
  52. package/dist/index.d.ts +4 -11
  53. package/dist/index.d.ts.map +1 -1
  54. package/dist/index.js +46 -26
  55. package/dist/index.js.map +1 -1
  56. package/dist/langchain/index.js +11 -0
  57. package/dist/langchain/index.js.map +1 -0
  58. package/dist/model/chat.d.ts +30 -0
  59. package/dist/model/chat.d.ts.map +1 -0
  60. package/dist/model/embed-parser.d.ts +25 -0
  61. package/dist/model/embed-parser.d.ts.map +1 -0
  62. package/dist/model/embedding.d.ts +25 -0
  63. package/dist/model/embedding.d.ts.map +1 -0
  64. package/dist/model/hub.d.ts +26 -3
  65. package/dist/model/hub.d.ts.map +1 -1
  66. package/dist/model/index.d.ts +13 -0
  67. package/dist/model/index.d.ts.map +1 -0
  68. package/dist/model/index.js +17 -0
  69. package/dist/model/index.js.map +1 -0
  70. package/dist/model/llm-parser.d.ts +10 -0
  71. package/dist/model/llm-parser.d.ts.map +1 -0
  72. package/dist/model/types.d.ts +31 -0
  73. package/dist/model/types.d.ts.map +1 -0
  74. package/dist/npm/command.d.ts +37 -0
  75. package/dist/npm/command.d.ts.map +1 -0
  76. package/dist/npm/index.d.ts +5 -0
  77. package/dist/npm/index.d.ts.map +1 -0
  78. package/dist/npm/index.js +39 -0
  79. package/dist/npm/index.js.map +1 -0
  80. package/dist/npm/install.d.ts +9 -0
  81. package/dist/npm/install.d.ts.map +1 -0
  82. package/dist/npm/provider.d.ts +15 -0
  83. package/dist/npm/provider.d.ts.map +1 -0
  84. package/dist/npm/version.d.ts +12 -0
  85. package/dist/npm/version.d.ts.map +1 -0
  86. package/dist/registry/chat-model.d.ts +1 -1
  87. package/dist/registry/chat-model.d.ts.map +1 -1
  88. package/dist/registry/index.js +9 -0
  89. package/dist/registry/index.js.map +1 -0
  90. package/dist/types.d.ts +2 -2
  91. package/dist/types.d.ts.map +1 -1
  92. package/package.json +39 -1
  93. package/dist/chunk-YK4EBPJ3.js +0 -578
  94. package/dist/chunk-YK4EBPJ3.js.map +0 -1
@@ -0,0 +1,354 @@
1
+ import {
2
+ createChatModelFromLlmConfig
3
+ } from "./chunk-6EQCGQTV.js";
4
+ import {
5
+ getChatModelFactory,
6
+ registerChatModelProvider
7
+ } from "./chunk-G7MKWPEI.js";
8
+ import {
9
+ ensureNpmPackageInstalled,
10
+ getInstalledVersion,
11
+ isNpmProviderSpec,
12
+ parseNpmProviderSpec,
13
+ resolveLatestVersionFromRegistry
14
+ } from "./chunk-KE7IMUSA.js";
15
+
16
+ // src/extensions/loader.ts
17
+ import { readdirSync, readFileSync, existsSync } from "fs";
18
+ import { createRequire } from "module";
19
+ import { join } from "path";
20
+ import { pathToFileURL } from "url";
21
+
22
+ // src/types.ts
23
+ var AGENT_LLM_PROVIDER_FIELD = "agentLlmProvider";
24
+
25
+ // src/extensions/loader.ts
26
+ var loadedPackages = /* @__PURE__ */ new Set();
27
+ function isLLMExtension(m) {
28
+ if (m == null || typeof m !== "object") return false;
29
+ const e = m;
30
+ if (typeof e.providerName !== "string") return false;
31
+ const hasRegister = typeof e.register === "function";
32
+ const hasChatModel = typeof e.createChatModel === "function";
33
+ return hasRegister || hasChatModel;
34
+ }
35
+ function registerExtension(ext) {
36
+ if (typeof ext.createChatModel === "function") {
37
+ registerChatModelProvider(ext.providerName, ext.createChatModel);
38
+ return;
39
+ }
40
+ if (typeof ext.register === "function") {
41
+ ext.register();
42
+ }
43
+ }
44
+ function getExtensionFromModule(m) {
45
+ if (isLLMExtension(m)) return m;
46
+ if (typeof m.getLLMExtension === "function") {
47
+ const ext = m.getLLMExtension();
48
+ return isLLMExtension(ext) ? ext : null;
49
+ }
50
+ if (isLLMExtension(m.default)) return m.default;
51
+ return null;
52
+ }
53
+ function resolveLLMExtensionPackages(types) {
54
+ if (types == null) return [];
55
+ const typeList = Array.isArray(types) ? types : [types];
56
+ return typeList.filter(
57
+ (t) => typeof t === "string" && String(t).trim().length > 0
58
+ );
59
+ }
60
+ function readPackageProviderName(pkgPath) {
61
+ if (!existsSync(pkgPath)) return null;
62
+ try {
63
+ const raw = readFileSync(pkgPath, "utf-8");
64
+ const pkg = JSON.parse(raw);
65
+ const declared = pkg[AGENT_LLM_PROVIDER_FIELD] === true || Array.isArray(pkg.keywords) && pkg.keywords.includes("agent-llm-provider");
66
+ return declared && typeof pkg.name === "string" ? pkg.name : null;
67
+ } catch {
68
+ return null;
69
+ }
70
+ }
71
+ function discoverLLMExtensions(cwd = process.cwd()) {
72
+ const dir = typeof cwd === "string" && cwd.trim().length > 0 ? cwd : process.cwd();
73
+ const nodeModules = join(dir, "node_modules");
74
+ if (!existsSync(nodeModules)) return [];
75
+ const names = [];
76
+ const seen = /* @__PURE__ */ new Set();
77
+ try {
78
+ const entries = readdirSync(nodeModules, { withFileTypes: true });
79
+ for (const e of entries) {
80
+ if (e.name.startsWith(".") || e.name === "node") continue;
81
+ if (e.name.startsWith("@") && e.isDirectory()) {
82
+ const scopePath = join(nodeModules, e.name);
83
+ const scopeEntries = readdirSync(scopePath, { withFileTypes: true });
84
+ for (const se of scopeEntries) {
85
+ if (!se.isDirectory()) continue;
86
+ const name2 = readPackageProviderName(join(scopePath, se.name, "package.json"));
87
+ if (name2 && !seen.has(name2)) {
88
+ seen.add(name2);
89
+ names.push(name2);
90
+ }
91
+ }
92
+ continue;
93
+ }
94
+ const name = readPackageProviderName(join(nodeModules, e.name, "package.json"));
95
+ if (name && !seen.has(name)) {
96
+ seen.add(name);
97
+ names.push(name);
98
+ }
99
+ }
100
+ } catch {
101
+ }
102
+ return names;
103
+ }
104
+ async function loadModuleFromPath(pkgDir) {
105
+ const pkgJsonPath = join(pkgDir, "package.json");
106
+ if (!existsSync(pkgJsonPath)) {
107
+ throw new Error(`package.json not found in ${pkgDir}`);
108
+ }
109
+ const pkgJson = JSON.parse(readFileSync(pkgJsonPath, "utf-8"));
110
+ const main = pkgJson?.main ?? "index.js";
111
+ const entryPath = join(pkgDir, main);
112
+ if (!existsSync(entryPath)) {
113
+ throw new Error(`Entry ${main} not found in ${pkgDir}`);
114
+ }
115
+ const entryUrl = pathToFileURL(entryPath).href;
116
+ return await import(
117
+ /* @vite-ignore */
118
+ entryUrl
119
+ );
120
+ }
121
+ function resolvePackageEntryFromCwd(pkg, cwd) {
122
+ const pkgDir = join(cwd, "node_modules", pkg);
123
+ const pkgJsonPath = join(pkgDir, "package.json");
124
+ if (!existsSync(pkgJsonPath)) return null;
125
+ try {
126
+ const req = createRequire(pkgJsonPath);
127
+ return req.resolve(pkg);
128
+ } catch {
129
+ return null;
130
+ }
131
+ }
132
+ async function loadLLMExtensions(extensionPackages, options) {
133
+ const packages = Array.isArray(extensionPackages) ? extensionPackages.filter((p) => typeof p === "string" && String(p).trim().length > 0) : [];
134
+ const cwd = options?.cwd ?? process.cwd();
135
+ for (const pkg of packages) {
136
+ if (loadedPackages.has(pkg)) continue;
137
+ loadedPackages.add(pkg);
138
+ let loaded = false;
139
+ const cwdPkgDir = join(cwd, "node_modules", pkg);
140
+ const cwdIsProject = existsSync(join(cwd, "package.json")) && (() => {
141
+ try {
142
+ const name = JSON.parse(readFileSync(join(cwd, "package.json"), "utf-8")).name;
143
+ return name === pkg;
144
+ } catch {
145
+ return false;
146
+ }
147
+ })();
148
+ const dirsToTry = [cwdPkgDir, ...cwdIsProject ? [cwd] : []];
149
+ for (const pkgDir of dirsToTry) {
150
+ if (!existsSync(join(pkgDir, "package.json"))) continue;
151
+ try {
152
+ const m = await loadModuleFromPath(pkgDir);
153
+ const ext = getExtensionFromModule(m);
154
+ if (ext) {
155
+ registerExtension(ext);
156
+ loaded = true;
157
+ break;
158
+ }
159
+ if (typeof m.registerLLMExtension === "function") {
160
+ m.registerLLMExtension();
161
+ loaded = true;
162
+ break;
163
+ }
164
+ } catch {
165
+ }
166
+ }
167
+ if (loaded) continue;
168
+ const resolvedEntry = resolvePackageEntryFromCwd(pkg, cwd);
169
+ if (resolvedEntry) {
170
+ try {
171
+ const entryUrl = pathToFileURL(resolvedEntry).href;
172
+ const m = await import(
173
+ /* @vite-ignore */
174
+ entryUrl
175
+ );
176
+ const ext = getExtensionFromModule(m);
177
+ if (ext) {
178
+ registerExtension(ext);
179
+ continue;
180
+ }
181
+ if (typeof m.registerLLMExtension === "function") {
182
+ m.registerLLMExtension();
183
+ continue;
184
+ }
185
+ } catch {
186
+ }
187
+ }
188
+ try {
189
+ const m = await import(
190
+ /* @vite-ignore */
191
+ pkg
192
+ );
193
+ const ext = getExtensionFromModule(m);
194
+ if (ext) {
195
+ registerExtension(ext);
196
+ continue;
197
+ }
198
+ if (typeof m.registerLLMExtension === "function") {
199
+ m.registerLLMExtension();
200
+ }
201
+ } catch (e) {
202
+ const msg = e instanceof Error ? e.message : String(e);
203
+ if (typeof process !== "undefined" && process.emitWarning) {
204
+ process.emitWarning(`[agent-llm] Failed to load extension "${pkg}": ${msg}`, { code: "AGENT_LLM_EXTENSION_LOAD" });
205
+ }
206
+ }
207
+ }
208
+ }
209
+ async function loadDiscoveredExtensions(cwd = process.cwd()) {
210
+ const dir = typeof cwd === "string" && cwd.trim().length > 0 ? cwd : process.cwd();
211
+ const names = discoverLLMExtensions(dir);
212
+ await loadLLMExtensions(names);
213
+ return names;
214
+ }
215
+
216
+ // src/extensions/npm-protocol.ts
217
+ async function getLatestVersion(packageName, options = {}) {
218
+ return resolveLatestVersionFromRegistry(packageName, { cwd: options.cwd ?? process.cwd() });
219
+ }
220
+ function getInstalledVersion2(packageName, options = {}) {
221
+ return getInstalledVersion(packageName, options);
222
+ }
223
+ function isModuleNotFoundError(err) {
224
+ const msg = err instanceof Error ? err.message : String(err);
225
+ return msg.includes("Cannot find module") || msg.includes("Cannot find package") || msg.includes("MODULE_NOT_FOUND") || msg.includes("ERR_MODULE_NOT_FOUND") || msg.includes("Failed to load url") || msg.includes("Does the file exist");
226
+ }
227
+ async function ensureNpmPackageInstalled2(packageName, options = {}) {
228
+ await ensureNpmPackageInstalled(packageName, {
229
+ version: options.version,
230
+ cwd: options.cwd,
231
+ stdio: "inherit",
232
+ noPackageLock: true,
233
+ logPrefix: "[agent-llm]"
234
+ });
235
+ }
236
+ function normalizeError(e, context) {
237
+ if (e instanceof Error) return new Error(`${context}: ${e.message}`, { cause: e });
238
+ return new Error(`${context}: ${String(e)}`);
239
+ }
240
+ async function resolveNpmProvider(spec, options = {}) {
241
+ if (typeof spec !== "string" || spec.trim().length === 0) return null;
242
+ const parsed = parseNpmProviderSpec(spec);
243
+ if (!parsed) return null;
244
+ const { packageName, version, provider: fragmentProvider } = parsed;
245
+ const installNpmIfMissing = options.installNpmIfMissing !== false;
246
+ const cwd = options.cwd ?? process.cwd();
247
+ const load = async () => {
248
+ await loadLLMExtensions([packageName], { cwd });
249
+ };
250
+ if (installNpmIfMissing) {
251
+ await ensureNpmPackageInstalled2(packageName, { version, cwd });
252
+ }
253
+ try {
254
+ await load();
255
+ } catch (err) {
256
+ if (installNpmIfMissing && isModuleNotFoundError(err)) {
257
+ try {
258
+ await ensureNpmPackageInstalled2(packageName, { version, cwd });
259
+ await load();
260
+ } catch (installErr) {
261
+ throw normalizeError(installErr, `Failed to install or load npm provider "${packageName}"`);
262
+ }
263
+ } else {
264
+ throw normalizeError(err, `Failed to load npm provider "${packageName}"`);
265
+ }
266
+ }
267
+ if (fragmentProvider && !getChatModelFactory(fragmentProvider)) {
268
+ if (installNpmIfMissing) {
269
+ await ensureNpmPackageInstalled2(packageName, { version, cwd });
270
+ await load();
271
+ }
272
+ if (!getChatModelFactory(fragmentProvider)) {
273
+ throw new Error(`Package "${packageName}" was installed but did not register provider "${fragmentProvider}". Check that the package exports getLLMExtension() or registerLLMExtension().`);
274
+ }
275
+ }
276
+ if (fragmentProvider) return fragmentProvider;
277
+ try {
278
+ const m = await import(
279
+ /* @vite-ignore */
280
+ packageName
281
+ );
282
+ if (typeof m.getDefaultProviderName === "function") {
283
+ return m.getDefaultProviderName();
284
+ }
285
+ } catch {
286
+ }
287
+ throw new Error(
288
+ `Provider spec ${spec} has no #provider fragment and the package does not export getDefaultProviderName(). Use e.g. npm:${packageName}#<provider-name>.`
289
+ );
290
+ }
291
+ async function resolveLlmSectionWithNpm(llmSection, options = {}) {
292
+ if (llmSection == null) return llmSection;
293
+ if (Array.isArray(llmSection)) {
294
+ const out = [];
295
+ for (let i = 0; i < llmSection.length; i++) {
296
+ try {
297
+ out.push(await resolveLlmSectionWithNpm(llmSection[i], options));
298
+ } catch (e) {
299
+ throw normalizeError(e, `Failed to resolve llm section at index ${i}`);
300
+ }
301
+ }
302
+ return out;
303
+ }
304
+ if (typeof llmSection === "object") {
305
+ const out = {};
306
+ for (const [k, v] of Object.entries(llmSection)) {
307
+ if (k === "provider" && isNpmProviderSpec(v)) {
308
+ try {
309
+ const resolved = await resolveNpmProvider(v, options);
310
+ out[k] = resolved ?? v;
311
+ } catch (e) {
312
+ throw normalizeError(e, `Failed to resolve provider "${String(v)}"`);
313
+ }
314
+ continue;
315
+ }
316
+ try {
317
+ out[k] = await resolveLlmSectionWithNpm(v, options);
318
+ } catch (e) {
319
+ throw normalizeError(e, `Failed to resolve llm section key "${k}"`);
320
+ }
321
+ }
322
+ return out;
323
+ }
324
+ return llmSection;
325
+ }
326
+ async function createChatModelWithNpm(options = {}) {
327
+ try {
328
+ const { installNpmIfMissing, cwd, ...rest } = options;
329
+ const resolvedSection = await resolveLlmSectionWithNpm(options.llmSection ?? null, {
330
+ installNpmIfMissing,
331
+ cwd
332
+ });
333
+ return createChatModelFromLlmConfig({
334
+ ...rest,
335
+ llmSection: resolvedSection
336
+ });
337
+ } catch (e) {
338
+ throw normalizeError(e, "createChatModelWithNpm failed");
339
+ }
340
+ }
341
+
342
+ export {
343
+ resolveLLMExtensionPackages,
344
+ discoverLLMExtensions,
345
+ loadLLMExtensions,
346
+ loadDiscoveredExtensions,
347
+ getLatestVersion,
348
+ getInstalledVersion2 as getInstalledVersion,
349
+ ensureNpmPackageInstalled2 as ensureNpmPackageInstalled,
350
+ resolveNpmProvider,
351
+ resolveLlmSectionWithNpm,
352
+ createChatModelWithNpm
353
+ };
354
+ //# sourceMappingURL=chunk-FVQ3PKER.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/extensions/loader.ts","../src/types.ts","../src/extensions/npm-protocol.ts"],"sourcesContent":["/**\n * Load LLM extensions by npm package name or by dynamic discovery.\n * Extensions register a ChatModel factory via registerChatModelProvider.\n */\n\nimport { readdirSync, readFileSync, existsSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { join } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport type { ILLMExtension } from \"../types.js\";\nimport { AGENT_LLM_PROVIDER_FIELD } from \"../types.js\";\nimport { registerChatModelProvider, type ChatModelFactory } from \"../registry/chat-model.js\";\n\nconst loadedPackages = new Set<string>();\n\nfunction isLLMExtension(m: unknown): m is ILLMExtension {\n if (m == null || typeof m !== \"object\") return false;\n const e = m as ILLMExtension;\n if (typeof e.providerName !== \"string\") return false;\n const hasRegister = typeof e.register === \"function\";\n const hasChatModel = typeof e.createChatModel === \"function\";\n return hasRegister || hasChatModel;\n}\n\nfunction registerExtension(ext: ILLMExtension): void {\n if (typeof ext.createChatModel === \"function\") {\n registerChatModelProvider(ext.providerName, ext.createChatModel as ChatModelFactory);\n return;\n }\n if (typeof ext.register === \"function\") {\n ext.register();\n }\n}\n\nfunction getExtensionFromModule(m: Record<string, unknown>): ILLMExtension | null {\n if (isLLMExtension(m)) return m;\n if (typeof m.getLLMExtension === \"function\") {\n const ext = m.getLLMExtension();\n return isLLMExtension(ext) ? ext : null;\n }\n if (isLLMExtension(m.default)) return m.default;\n return null;\n}\n\nexport function resolveLLMExtensionPackages(types?: string | string[]): string[] {\n if (types == null) return [];\n const typeList = Array.isArray(types) ? types : [types];\n return typeList.filter(\n (t): t is string => typeof t === \"string\" && String(t).trim().length > 0\n );\n}\n\nfunction readPackageProviderName(pkgPath: string): string | null {\n if (!existsSync(pkgPath)) return null;\n try {\n const raw = readFileSync(pkgPath, \"utf-8\");\n const pkg = JSON.parse(raw) as { agentLlmProvider?: boolean; keywords?: string[]; name?: string };\n const declared =\n pkg[AGENT_LLM_PROVIDER_FIELD] === true ||\n (Array.isArray(pkg.keywords) && pkg.keywords.includes(\"agent-llm-provider\"));\n return declared && typeof pkg.name === \"string\" ? pkg.name : null;\n } catch {\n return null;\n }\n}\n\nexport function discoverLLMExtensions(cwd: string = process.cwd()): string[] {\n const dir = typeof cwd === \"string\" && cwd.trim().length > 0 ? cwd : process.cwd();\n const nodeModules = join(dir, \"node_modules\");\n if (!existsSync(nodeModules)) return [];\n const names: string[] = [];\n const seen = new Set<string>();\n try {\n const entries = readdirSync(nodeModules, { withFileTypes: true });\n for (const e of entries) {\n if (e.name.startsWith(\".\") || e.name === \"node\") continue;\n if (e.name.startsWith(\"@\") && e.isDirectory()) {\n const scopePath = join(nodeModules, e.name);\n const scopeEntries = readdirSync(scopePath, { withFileTypes: true });\n for (const se of scopeEntries) {\n if (!se.isDirectory()) continue;\n const name = readPackageProviderName(join(scopePath, se.name, \"package.json\"));\n if (name && !seen.has(name)) {\n seen.add(name);\n names.push(name);\n }\n }\n continue;\n }\n const name = readPackageProviderName(join(nodeModules, e.name, \"package.json\"));\n if (name && !seen.has(name)) {\n seen.add(name);\n names.push(name);\n }\n }\n } catch {\n // no node_modules or not readable\n }\n return names;\n}\n\nasync function loadModuleFromPath(pkgDir: string): Promise<Record<string, unknown>> {\n const pkgJsonPath = join(pkgDir, \"package.json\");\n if (!existsSync(pkgJsonPath)) {\n throw new Error(`package.json not found in ${pkgDir}`);\n }\n const pkgJson = JSON.parse(readFileSync(pkgJsonPath, \"utf-8\")) as { main?: string };\n const main = pkgJson?.main ?? \"index.js\";\n const entryPath = join(pkgDir, main);\n if (!existsSync(entryPath)) {\n throw new Error(`Entry ${main} not found in ${pkgDir}`);\n }\n const entryUrl = pathToFileURL(entryPath).href;\n return (await import(/* @vite-ignore */ entryUrl)) as Record<string, unknown>;\n}\n\n/**\n * Resolve package main entry from cwd so we load the copy in cwd's node_modules,\n * not a different copy from bare import (e.g. under @wallee/agent).\n */\nfunction resolvePackageEntryFromCwd(pkg: string, cwd: string): string | null {\n const pkgDir = join(cwd, \"node_modules\", pkg);\n const pkgJsonPath = join(pkgDir, \"package.json\");\n if (!existsSync(pkgJsonPath)) return null;\n try {\n const req = createRequire(pkgJsonPath);\n return req.resolve(pkg);\n } catch {\n return null;\n }\n}\n\nexport interface LoadLLMExtensionsOptions {\n cwd?: string;\n}\n\nexport async function loadLLMExtensions(\n extensionPackages?: string[],\n options?: LoadLLMExtensionsOptions\n): Promise<void> {\n const packages = Array.isArray(extensionPackages)\n ? extensionPackages.filter((p): p is string => typeof p === \"string\" && String(p).trim().length > 0)\n : [];\n const cwd = options?.cwd ?? process.cwd();\n for (const pkg of packages) {\n if (loadedPackages.has(pkg)) continue;\n loadedPackages.add(pkg);\n let loaded = false;\n const cwdPkgDir = join(cwd, \"node_modules\", pkg);\n const cwdIsProject =\n existsSync(join(cwd, \"package.json\")) &&\n (() => {\n try {\n const name = (JSON.parse(readFileSync(join(cwd, \"package.json\"), \"utf-8\")) as { name?: string }).name;\n return name === pkg;\n } catch {\n return false;\n }\n })();\n const dirsToTry = [cwdPkgDir, ...(cwdIsProject ? [cwd] : [])];\n for (const pkgDir of dirsToTry) {\n if (!existsSync(join(pkgDir, \"package.json\"))) continue;\n try {\n const m = await loadModuleFromPath(pkgDir);\n const ext = getExtensionFromModule(m);\n if (ext) {\n registerExtension(ext);\n loaded = true;\n break;\n }\n if (typeof (m as { registerLLMExtension?: () => void }).registerLLMExtension === \"function\") {\n (m as { registerLLMExtension: () => void }).registerLLMExtension();\n loaded = true;\n break;\n }\n } catch {\n // try next path\n }\n }\n if (loaded) continue;\n // Prefer cwd-resolved entry so we load the copy just installed, not another copy from bare import\n const resolvedEntry = resolvePackageEntryFromCwd(pkg, cwd);\n if (resolvedEntry) {\n try {\n const entryUrl = pathToFileURL(resolvedEntry).href;\n const m = (await import(/* @vite-ignore */ entryUrl)) as Record<string, unknown>;\n const ext = getExtensionFromModule(m);\n if (ext) {\n registerExtension(ext);\n continue;\n }\n if (typeof (m as { registerLLMExtension?: () => void }).registerLLMExtension === \"function\") {\n (m as { registerLLMExtension: () => void }).registerLLMExtension();\n continue;\n }\n } catch {\n // fall through to bare import\n }\n }\n try {\n const m = await import(/* @vite-ignore */ pkg) as Record<string, unknown>;\n const ext = getExtensionFromModule(m);\n if (ext) {\n registerExtension(ext);\n continue;\n }\n if (typeof (m as { registerLLMExtension?: () => void }).registerLLMExtension === \"function\") {\n (m as { registerLLMExtension: () => void }).registerLLMExtension();\n }\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n if (typeof process !== \"undefined\" && process.emitWarning) {\n process.emitWarning(`[agent-llm] Failed to load extension \"${pkg}\": ${msg}`, { code: \"AGENT_LLM_EXTENSION_LOAD\" });\n }\n }\n }\n}\n\nexport async function loadDiscoveredExtensions(cwd: string = process.cwd()): Promise<string[]> {\n const dir = typeof cwd === \"string\" && cwd.trim().length > 0 ? cwd : process.cwd();\n const names = discoverLLMExtensions(dir);\n await loadLLMExtensions(names);\n return names;\n}\n","/**\n * Agent LLM: OpenAI-compatible config.\n * Returns LangChain BaseChatModel instances.\n */\n\nimport type { BaseChatModel } from \"@langchain/core/language_models/chat_models\";\n\n// LLM types now live locally in agent-model\nexport type { LLMType, LLMConfig, AgentConfigLlmSection } from \"./model/types.js\";\n\n/** package.json field: when true, the package is an agent-llm provider (for discovery). */\nexport const AGENT_LLM_PROVIDER_FIELD = \"agentLlmProvider\";\n\n/**\n * Extension interface: register a ChatModel factory by provider name.\n * Extensions implement getLLMExtension(); framework registers the factory when loading.\n */\nexport interface ILLMExtension {\n readonly providerName: string;\n /** ChatModel factory. Framework calls registerChatModelProvider(providerName, createChatModel). */\n readonly createChatModel?: (config: import(\"./model/types.js\").LLMConfig) => BaseChatModel;\n /** Legacy: if extension provides register(), framework calls it. */\n register?(): void;\n}\n","/**\n * npm: protocol in provider — specify an npm package name (and optional version) in config's provider.\n * When installNpmIfMissing is true, the framework will run npm install <package>[@version] if the package is not found.\n */\n\nimport type { BaseChatModel } from \"@langchain/core/language_models/chat_models\";\nimport { loadLLMExtensions } from \"./loader.js\";\nimport { getChatModelFactory } from \"../registry/chat-model.js\";\nimport { createChatModelFromLlmConfig } from \"../langchain/index.js\";\nimport type { CreateChatModelOptions } from \"../langchain/index.js\";\nimport {\n NPM_PROTOCOL_PREFIX,\n parseNpmProviderSpec,\n isNpmProviderSpec,\n resolveLatestVersionFromRegistry,\n getInstalledVersion as getInstalledVersionFromCommon,\n ensureNpmPackageInstalled as ensureNpmPackageInstalledFromCommon,\n} from \"../npm/index.js\";\n\nexport { NPM_PROTOCOL_PREFIX, parseNpmProviderSpec, isNpmProviderSpec };\n\nexport async function getLatestVersion(\n packageName: string,\n options: { cwd?: string } = {}\n): Promise<string> {\n return resolveLatestVersionFromRegistry(packageName, { cwd: options.cwd ?? process.cwd() });\n}\n\nexport function getInstalledVersion(packageName: string, options: { cwd?: string } = {}): string | null {\n return getInstalledVersionFromCommon(packageName, options);\n}\n\nexport interface EnsureNpmPackageInstalledOptions {\n version?: string;\n cwd?: string;\n}\n\nfunction isModuleNotFoundError(err: unknown): boolean {\n const msg = err instanceof Error ? err.message : String(err);\n return (\n msg.includes(\"Cannot find module\") ||\n msg.includes(\"Cannot find package\") ||\n msg.includes(\"MODULE_NOT_FOUND\") ||\n msg.includes(\"ERR_MODULE_NOT_FOUND\") ||\n msg.includes(\"Failed to load url\") ||\n msg.includes(\"Does the file exist\")\n );\n}\n\n/**\n * Ensure the npm package is installed at the required version.\n * We only use version numbers for management; \"latest\" is always resolved to the actual\n * version from the registry, then we install that version if missing or different.\n */\nexport async function ensureNpmPackageInstalled(\n packageName: string,\n options: EnsureNpmPackageInstalledOptions = {}\n): Promise<void> {\n await ensureNpmPackageInstalledFromCommon(packageName, {\n version: options.version,\n cwd: options.cwd,\n stdio: \"inherit\",\n noPackageLock: true,\n logPrefix: \"[agent-llm]\",\n });\n}\n\nexport interface ResolveNpmProviderOptions {\n installNpmIfMissing?: boolean;\n cwd?: string;\n}\n\nfunction normalizeError(e: unknown, context: string): Error {\n if (e instanceof Error) return new Error(`${context}: ${e.message}`, { cause: e });\n return new Error(`${context}: ${String(e)}`);\n}\n\nexport async function resolveNpmProvider(\n spec: string,\n options: ResolveNpmProviderOptions = {}\n): Promise<string | null> {\n if (typeof spec !== \"string\" || spec.trim().length === 0) return null;\n const parsed = parseNpmProviderSpec(spec);\n if (!parsed) return null;\n const { packageName, version, provider: fragmentProvider } = parsed;\n const installNpmIfMissing = options.installNpmIfMissing !== false;\n const cwd = options.cwd ?? process.cwd();\n\n const load = async (): Promise<void> => {\n await loadLLMExtensions([packageName], { cwd });\n };\n\n if (installNpmIfMissing) {\n await ensureNpmPackageInstalled(packageName, { version, cwd });\n }\n\n try {\n await load();\n } catch (err) {\n if (installNpmIfMissing && isModuleNotFoundError(err)) {\n try {\n await ensureNpmPackageInstalled(packageName, { version, cwd });\n await load();\n } catch (installErr) {\n throw normalizeError(installErr, `Failed to install or load npm provider \"${packageName}\"`);\n }\n } else {\n throw normalizeError(err, `Failed to load npm provider \"${packageName}\"`);\n }\n }\n\n if (fragmentProvider && !getChatModelFactory(fragmentProvider)) {\n if (installNpmIfMissing) {\n await ensureNpmPackageInstalled(packageName, { version, cwd });\n await load();\n }\n if (!getChatModelFactory(fragmentProvider)) {\n throw new Error(`Package \"${packageName}\" was installed but did not register provider \"${fragmentProvider}\". Check that the package exports getLLMExtension() or registerLLMExtension().`);\n }\n }\n\n if (fragmentProvider) return fragmentProvider;\n\n try {\n const m = await import(/* @vite-ignore */ packageName);\n if (typeof (m as { getDefaultProviderName?: () => string }).getDefaultProviderName === \"function\") {\n return (m as { getDefaultProviderName: () => string }).getDefaultProviderName();\n }\n } catch {\n // ignore\n }\n throw new Error(\n `Provider spec ${spec} has no #provider fragment and the package does not export getDefaultProviderName(). Use e.g. npm:${packageName}#<provider-name>.`\n );\n}\n\nexport interface ResolveLlmSectionWithNpmOptions extends ResolveNpmProviderOptions {}\n\nexport async function resolveLlmSectionWithNpm(\n llmSection: unknown,\n options: ResolveLlmSectionWithNpmOptions = {}\n): Promise<unknown> {\n if (llmSection == null) return llmSection;\n if (Array.isArray(llmSection)) {\n const out: unknown[] = [];\n for (let i = 0; i < llmSection.length; i++) {\n try {\n out.push(await resolveLlmSectionWithNpm(llmSection[i], options));\n } catch (e) {\n throw normalizeError(e, `Failed to resolve llm section at index ${i}`);\n }\n }\n return out;\n }\n if (typeof llmSection === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(llmSection)) {\n if (k === \"provider\" && isNpmProviderSpec(v)) {\n try {\n const resolved = await resolveNpmProvider(v as string, options);\n out[k] = resolved ?? v;\n } catch (e) {\n throw normalizeError(e, `Failed to resolve provider \"${String(v)}\"`);\n }\n continue;\n }\n try {\n out[k] = await resolveLlmSectionWithNpm(v, options);\n } catch (e) {\n throw normalizeError(e, `Failed to resolve llm section key \"${k}\"`);\n }\n }\n return out;\n }\n return llmSection;\n}\n\nexport interface CreateChatModelWithNpmOptions\n extends CreateChatModelOptions,\n ResolveNpmProviderOptions {}\n\nexport async function createChatModelWithNpm(\n options: CreateChatModelWithNpmOptions = {}\n): Promise<BaseChatModel> {\n try {\n const { installNpmIfMissing, cwd, ...rest } = options;\n const resolvedSection = await resolveLlmSectionWithNpm(options.llmSection ?? null, {\n installNpmIfMissing,\n cwd,\n });\n return createChatModelFromLlmConfig({\n ...rest,\n llmSection: resolvedSection,\n });\n } catch (e) {\n throw normalizeError(e, \"createChatModelWithNpm failed\");\n }\n}\n"],"mappings":"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","names":["name","getInstalledVersion","ensureNpmPackageInstalled"]}
@@ -0,0 +1,191 @@
1
+ import {
2
+ parseLlmSection
3
+ } from "./chunk-SPDXNDDD.js";
4
+
5
+ // src/model/chat.ts
6
+ var DEFAULT_CHAT_TIMEOUT_MS = 6e4;
7
+ function isLocalBaseUrl(url) {
8
+ try {
9
+ const u = new URL(url);
10
+ const host = u.hostname.toLowerCase();
11
+ return host === "localhost" || host === "127.0.0.1" || host === "::1";
12
+ } catch {
13
+ return false;
14
+ }
15
+ }
16
+ function normalizeContent(content) {
17
+ if (typeof content === "string") return content;
18
+ if (!Array.isArray(content)) return String(content ?? "");
19
+ const parts = [];
20
+ for (const p of content) {
21
+ if (typeof p === "string") parts.push(p);
22
+ else if (p && typeof p === "object" && typeof p.text === "string")
23
+ parts.push(p.text);
24
+ }
25
+ return parts.join("\n").trim();
26
+ }
27
+ async function chatCompletionViaOpenAICompatibleApi(options, request) {
28
+ const baseUrl = options.baseURL.replace(/\/$/, "");
29
+ const apiKey = options.apiKey?.trim();
30
+ const timeoutMs = options.timeoutMs ?? DEFAULT_CHAT_TIMEOUT_MS;
31
+ const modelName = typeof request.model === "string" && request.model.trim() !== "" ? request.model.trim() : options.model ?? "gpt-4o-mini";
32
+ if (!apiKey && !isLocalBaseUrl(baseUrl)) {
33
+ throw new Error("Chat completion API key is required for non-local baseURL");
34
+ }
35
+ const body = {
36
+ model: modelName,
37
+ messages: request.messages.map((m) => ({ role: m.role, content: m.content })),
38
+ temperature: typeof request.temperature === "number" ? request.temperature : 0
39
+ };
40
+ if (typeof request.maxTokens === "number") body.max_tokens = request.maxTokens;
41
+ const controller = new AbortController();
42
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
43
+ try {
44
+ const response = await fetch(`${baseUrl}/chat/completions`, {
45
+ method: "POST",
46
+ headers: {
47
+ "Content-Type": "application/json",
48
+ ...apiKey ? { Authorization: `Bearer ${apiKey}` } : {}
49
+ },
50
+ body: JSON.stringify(body),
51
+ signal: controller.signal
52
+ });
53
+ if (!response.ok) {
54
+ const text = await response.text();
55
+ throw new Error(`Chat completion API error ${response.status}: ${text.slice(0, 500)}`);
56
+ }
57
+ const data = await response.json();
58
+ const raw = data.choices?.[0]?.message?.content ?? data.choices?.[0]?.text ?? "";
59
+ return {
60
+ text: normalizeContent(raw),
61
+ model: data.model ?? modelName
62
+ };
63
+ } finally {
64
+ clearTimeout(timer);
65
+ }
66
+ }
67
+
68
+ // src/model/embedding.ts
69
+ var DEFAULT_EMBEDDING_TIMEOUT_MS = 3e4;
70
+ function isLocalBaseUrl2(url) {
71
+ try {
72
+ const u = new URL(url);
73
+ const host = u.hostname.toLowerCase();
74
+ return host === "localhost" || host === "127.0.0.1" || host === "::1";
75
+ } catch {
76
+ return false;
77
+ }
78
+ }
79
+ async function embedViaOpenAICompatibleApi(options, input) {
80
+ const baseUrl = options.baseURL.replace(/\/$/, "");
81
+ const apiKey = options.apiKey?.trim();
82
+ const timeoutMs = options.timeoutMs ?? DEFAULT_EMBEDDING_TIMEOUT_MS;
83
+ const modelName = typeof input.model === "string" && input.model.trim() !== "" ? input.model.trim() : options.model ?? "text-embedding-3-small";
84
+ if (!apiKey && !isLocalBaseUrl2(baseUrl)) {
85
+ throw new Error("Embedding API key is required for non-local baseURL");
86
+ }
87
+ const controller = new AbortController();
88
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
89
+ try {
90
+ const response = await fetch(`${baseUrl}/embeddings`, {
91
+ method: "POST",
92
+ headers: {
93
+ "Content-Type": "application/json",
94
+ ...apiKey ? { Authorization: `Bearer ${apiKey}` } : {}
95
+ },
96
+ body: JSON.stringify({ model: modelName, input: input.input }),
97
+ signal: controller.signal
98
+ });
99
+ if (!response.ok) {
100
+ const body = await response.text();
101
+ throw new Error(`Embedding API error ${response.status}: ${body.slice(0, 500)}`);
102
+ }
103
+ const data = await response.json();
104
+ const vectors = (data.data ?? []).slice().sort((a, b) => (a.index ?? 0) - (b.index ?? 0)).map((v) => v.embedding).filter((v) => Array.isArray(v));
105
+ return {
106
+ vectors,
107
+ dimensions: vectors[0]?.length,
108
+ model: data.model ?? modelName
109
+ };
110
+ } finally {
111
+ clearTimeout(timer);
112
+ }
113
+ }
114
+
115
+ // src/model/hub.ts
116
+ var DEFAULT_EMBEDDING_MODEL = "text-embedding-3-small";
117
+ var DEFAULT_CHAT_MODEL = "gpt-4o-mini";
118
+ var DEFAULT_BASE_URL = "https://api.openai.com/v1";
119
+ function getDefaultLlmConfig(llmSection) {
120
+ const parsed = parseLlmSection(llmSection ?? null);
121
+ const config = parsed.configs.find((c) => c.id === parsed.defaultId) ?? parsed.configs[0] ?? null;
122
+ return config;
123
+ }
124
+ function createModelHub(options = {}) {
125
+ const baseCfg = getDefaultLlmConfig(options.llmSection);
126
+ const defaultBaseUrl = (options.embeddingBaseURL ?? baseCfg?.baseURL ?? DEFAULT_BASE_URL).replace(/\/$/, "");
127
+ const defaultApiKey = options.embeddingApiKey ?? baseCfg?.apiKey ?? process.env.OPENAI_API_KEY;
128
+ const defaultEmbeddingModel = options.embeddingModel ?? (baseCfg?.options && typeof baseCfg.options.embeddingModel === "string" ? baseCfg.options.embeddingModel : void 0) ?? baseCfg?.model ?? process.env.OPENAI_EMBEDDING_MODEL ?? DEFAULT_EMBEDDING_MODEL;
129
+ const defaultChatModel = baseCfg?.model ?? process.env.OPENAI_MODEL ?? DEFAULT_CHAT_MODEL;
130
+ const embeddingTimeoutMs = options.embeddingTimeoutMs;
131
+ const chatTimeoutMs = options.chatTimeoutMs;
132
+ return {
133
+ async generate(input) {
134
+ const messages = [];
135
+ if (typeof input.systemPrompt === "string" && input.systemPrompt.trim() !== "") {
136
+ messages.push({ role: "system", content: input.systemPrompt.trim() });
137
+ }
138
+ messages.push({ role: "user", content: input.input });
139
+ const result = await chatCompletionViaOpenAICompatibleApi(
140
+ {
141
+ baseURL: defaultBaseUrl,
142
+ apiKey: defaultApiKey,
143
+ model: defaultChatModel,
144
+ timeoutMs: chatTimeoutMs
145
+ },
146
+ {
147
+ messages,
148
+ model: input.model,
149
+ temperature: input.temperature
150
+ }
151
+ );
152
+ return {
153
+ text: result.text,
154
+ model: typeof input.model === "string" && input.model.trim() !== "" ? input.model : result.model ?? baseCfg?.model
155
+ };
156
+ },
157
+ async embed(input) {
158
+ const result = await embedViaOpenAICompatibleApi(
159
+ {
160
+ baseURL: defaultBaseUrl,
161
+ apiKey: defaultApiKey,
162
+ model: defaultEmbeddingModel,
163
+ timeoutMs: embeddingTimeoutMs
164
+ },
165
+ { input: input.input, model: input.model }
166
+ );
167
+ return {
168
+ vectors: result.vectors,
169
+ dimensions: result.dimensions,
170
+ model: result.model
171
+ };
172
+ }
173
+ };
174
+ }
175
+
176
+ // src/model/embed-parser.ts
177
+ function parseEmbedSection(section) {
178
+ const result = parseLlmSection(section);
179
+ for (const config of result.configs) {
180
+ config.type = "embed";
181
+ }
182
+ return result;
183
+ }
184
+
185
+ export {
186
+ chatCompletionViaOpenAICompatibleApi,
187
+ embedViaOpenAICompatibleApi,
188
+ createModelHub,
189
+ parseEmbedSection
190
+ };
191
+ //# sourceMappingURL=chunk-FZWXYGR6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/model/chat.ts","../src/model/embedding.ts","../src/model/hub.ts","../src/model/embed-parser.ts"],"sourcesContent":["/**\n * OpenAI-compatible chat completion API: POST /chat/completions.\n * No LangChain dependency; for use by any module that needs LLM text generation.\n */\n\nconst DEFAULT_CHAT_TIMEOUT_MS = 60_000;\n\nexport interface ChatCompletionOptions {\n baseURL: string;\n apiKey?: string;\n model?: string;\n timeoutMs?: number;\n}\n\nexport interface ChatCompletionMessage {\n role: \"system\" | \"user\" | \"assistant\";\n content: string;\n}\n\nexport interface ChatCompletionRequest {\n messages: ChatCompletionMessage[];\n model?: string;\n temperature?: number;\n maxTokens?: number;\n}\n\nexport interface ChatCompletionResult {\n text: string;\n model?: string;\n}\n\nfunction isLocalBaseUrl(url: string): boolean {\n try {\n const u = new URL(url);\n const host = u.hostname.toLowerCase();\n return host === \"localhost\" || host === \"127.0.0.1\" || host === \"::1\";\n } catch {\n return false;\n }\n}\n\nfunction normalizeContent(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return String(content ?? \"\");\n const parts: string[] = [];\n for (const p of content) {\n if (typeof p === \"string\") parts.push(p);\n else if (p && typeof p === \"object\" && typeof (p as { text?: unknown }).text === \"string\")\n parts.push((p as { text: string }).text);\n }\n return parts.join(\"\\n\").trim();\n}\n\n/**\n * Call OpenAI-compatible /chat/completions endpoint.\n * baseURL should be the API root (e.g. https://api.openai.com/v1); trailing slash is stripped.\n */\nexport async function chatCompletionViaOpenAICompatibleApi(\n options: ChatCompletionOptions,\n request: ChatCompletionRequest\n): Promise<ChatCompletionResult> {\n const baseUrl = options.baseURL.replace(/\\/$/, \"\");\n const apiKey = options.apiKey?.trim();\n const timeoutMs = options.timeoutMs ?? DEFAULT_CHAT_TIMEOUT_MS;\n const modelName =\n typeof request.model === \"string\" && request.model.trim() !== \"\"\n ? request.model.trim()\n : options.model ?? \"gpt-4o-mini\";\n\n if (!apiKey && !isLocalBaseUrl(baseUrl)) {\n throw new Error(\"Chat completion API key is required for non-local baseURL\");\n }\n\n const body: Record<string, unknown> = {\n model: modelName,\n messages: request.messages.map((m) => ({ role: m.role, content: m.content })),\n temperature: typeof request.temperature === \"number\" ? request.temperature : 0,\n };\n if (typeof request.maxTokens === \"number\") body.max_tokens = request.maxTokens;\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const response = await fetch(`${baseUrl}/chat/completions`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {}),\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n if (!response.ok) {\n const text = await response.text();\n throw new Error(`Chat completion API error ${response.status}: ${text.slice(0, 500)}`);\n }\n const data = (await response.json()) as {\n choices?: Array<{ message?: { content?: unknown }; text?: unknown }>;\n model?: string;\n };\n const raw =\n data.choices?.[0]?.message?.content ?? data.choices?.[0]?.text ?? \"\";\n return {\n text: normalizeContent(raw),\n model: data.model ?? modelName,\n };\n } finally {\n clearTimeout(timer);\n }\n}\n","/**\n * OpenAI-compatible embedding API: POST /embeddings.\n * No LangChain dependency; for use by any module that needs embeddings.\n */\n\nconst DEFAULT_EMBEDDING_TIMEOUT_MS = 30_000;\n\nexport interface EmbeddingOptions {\n baseURL: string;\n apiKey?: string;\n model?: string;\n timeoutMs?: number;\n}\n\nexport interface EmbedRequest {\n input: string | string[];\n model?: string;\n}\n\nexport interface EmbedResult {\n vectors: number[][];\n dimensions?: number;\n model?: string;\n}\n\nfunction isLocalBaseUrl(url: string): boolean {\n try {\n const u = new URL(url);\n const host = u.hostname.toLowerCase();\n return host === \"localhost\" || host === \"127.0.0.1\" || host === \"::1\";\n } catch {\n return false;\n }\n}\n\n/**\n * Call OpenAI-compatible /embeddings endpoint.\n * baseURL should be the API root (e.g. https://api.openai.com/v1); trailing slash is stripped.\n */\nexport async function embedViaOpenAICompatibleApi(\n options: EmbeddingOptions,\n input: EmbedRequest\n): Promise<EmbedResult> {\n const baseUrl = options.baseURL.replace(/\\/$/, \"\");\n const apiKey = options.apiKey?.trim();\n const timeoutMs = options.timeoutMs ?? DEFAULT_EMBEDDING_TIMEOUT_MS;\n const modelName =\n typeof input.model === \"string\" && input.model.trim() !== \"\"\n ? input.model.trim()\n : options.model ?? \"text-embedding-3-small\";\n\n if (!apiKey && !isLocalBaseUrl(baseUrl)) {\n throw new Error(\"Embedding API key is required for non-local baseURL\");\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const response = await fetch(`${baseUrl}/embeddings`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {}),\n },\n body: JSON.stringify({ model: modelName, input: input.input }),\n signal: controller.signal,\n });\n if (!response.ok) {\n const body = await response.text();\n throw new Error(`Embedding API error ${response.status}: ${body.slice(0, 500)}`);\n }\n const data = (await response.json()) as {\n data?: Array<{ embedding?: number[]; index?: number }>;\n model?: string;\n };\n const vectors = (data.data ?? [])\n .slice()\n .sort((a, b) => (a.index ?? 0) - (b.index ?? 0))\n .map((v) => v.embedding)\n .filter((v): v is number[] => Array.isArray(v));\n return {\n vectors,\n dimensions: vectors[0]?.length,\n model: data.model ?? modelName,\n };\n } finally {\n clearTimeout(timer);\n }\n}\n","/**\n * Model hub: generate (chat completion) + embed, driven by llm section config.\n * No LangChain; uses OpenAI-compatible HTTP APIs so any package can use it via agent-model.\n */\n\nimport { parseLlmSection } from \"./llm-parser.js\";\nimport type { LLMConfig } from \"./types.js\";\nimport { chatCompletionViaOpenAICompatibleApi } from \"./chat.js\";\nimport { embedViaOpenAICompatibleApi } from \"./embedding.js\";\nimport type { EmbedRequest, EmbedResult } from \"./embedding.js\";\n\nconst DEFAULT_EMBEDDING_MODEL = \"text-embedding-3-small\";\nconst DEFAULT_CHAT_MODEL = \"gpt-4o-mini\";\nconst DEFAULT_BASE_URL = \"https://api.openai.com/v1\";\n\nexport interface CreateModelHubOptions {\n llmSection?: unknown;\n embeddingBaseURL?: string;\n embeddingApiKey?: string;\n embeddingModel?: string;\n embeddingTimeoutMs?: number;\n chatTimeoutMs?: number;\n}\n\nexport interface ChatGenerateRequest {\n input: string;\n systemPrompt?: string;\n model?: string;\n temperature?: number;\n}\n\nexport interface ChatGenerateResult {\n text: string;\n model?: string;\n}\n\nexport interface ModelHub {\n generate(input: ChatGenerateRequest): Promise<ChatGenerateResult>;\n embed(input: EmbedRequest): Promise<EmbedResult>;\n}\n\nfunction getDefaultLlmConfig(llmSection: unknown): LLMConfig | null {\n const parsed = parseLlmSection(llmSection ?? null);\n const config =\n parsed.configs.find((c: LLMConfig) => c.id === parsed.defaultId) ??\n parsed.configs[0] ??\n null;\n return config;\n}\n\nexport function createModelHub(options: CreateModelHubOptions = {}): ModelHub {\n const baseCfg = getDefaultLlmConfig(options.llmSection);\n const defaultBaseUrl = (\n options.embeddingBaseURL ??\n baseCfg?.baseURL ??\n DEFAULT_BASE_URL\n ).replace(/\\/$/, \"\");\n const defaultApiKey =\n options.embeddingApiKey ??\n baseCfg?.apiKey ??\n process.env.OPENAI_API_KEY;\n const defaultEmbeddingModel =\n options.embeddingModel ??\n (baseCfg?.options && typeof baseCfg.options.embeddingModel === \"string\"\n ? baseCfg.options.embeddingModel\n : undefined) ??\n baseCfg?.model ??\n process.env.OPENAI_EMBEDDING_MODEL ??\n DEFAULT_EMBEDDING_MODEL;\n const defaultChatModel =\n baseCfg?.model ??\n process.env.OPENAI_MODEL ??\n DEFAULT_CHAT_MODEL;\n const embeddingTimeoutMs = options.embeddingTimeoutMs;\n const chatTimeoutMs = options.chatTimeoutMs;\n\n return {\n async generate(input: ChatGenerateRequest): Promise<ChatGenerateResult> {\n const messages: Array<{ role: \"system\" | \"user\" | \"assistant\"; content: string }> = [];\n if (typeof input.systemPrompt === \"string\" && input.systemPrompt.trim() !== \"\") {\n messages.push({ role: \"system\", content: input.systemPrompt.trim() });\n }\n messages.push({ role: \"user\", content: input.input });\n const result = await chatCompletionViaOpenAICompatibleApi(\n {\n baseURL: defaultBaseUrl,\n apiKey: defaultApiKey,\n model: defaultChatModel,\n timeoutMs: chatTimeoutMs,\n },\n {\n messages,\n model: input.model,\n temperature: input.temperature,\n }\n );\n return {\n text: result.text,\n model:\n typeof input.model === \"string\" && input.model.trim() !== \"\"\n ? input.model\n : result.model ?? baseCfg?.model,\n };\n },\n async embed(input: EmbedRequest): Promise<EmbedResult> {\n const result = await embedViaOpenAICompatibleApi(\n {\n baseURL: defaultBaseUrl,\n apiKey: defaultApiKey,\n model: defaultEmbeddingModel,\n timeoutMs: embeddingTimeoutMs,\n },\n { input: input.input, model: input.model }\n );\n return {\n vectors: result.vectors,\n dimensions: result.dimensions,\n model: result.model,\n };\n },\n };\n}\n","/**\n * Parse embed section from models.yaml into normalized LLMConfig[] with type \"embed\".\n * Reuses parseLlmSection internally since the config shape is identical.\n */\n\nimport { parseLlmSection } from \"./llm-parser.js\";\nimport type { LLMConfig } from \"./types.js\";\n\n/**\n * Parse an `embed:` section from models.yaml.\n * Accepts the same flat-entry, instances[], or single-object formats as the llm section.\n *\n * @example\n * ```yaml\n * embed:\n * default: gemma\n * gemma:\n * provider: openai\n * base_url: https://ollama.example.com/v1\n * model: embeddinggemma:latest\n * apiKey: ollama\n * ```\n */\nexport function parseEmbedSection(\n section: unknown,\n): { defaultId: string; configs: LLMConfig[] } {\n const result = parseLlmSection(section);\n // Override type to \"embed\" for all parsed configs\n for (const config of result.configs) {\n config.type = \"embed\";\n }\n return result;\n}\n"],"mappings":"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","names":["isLocalBaseUrl"]}
@@ -0,0 +1,14 @@
1
+ // src/registry/chat-model.ts
2
+ var CHAT_MODEL_FACTORIES = /* @__PURE__ */ new Map();
3
+ function registerChatModelProvider(providerName, factory) {
4
+ CHAT_MODEL_FACTORIES.set(providerName.toLowerCase(), factory);
5
+ }
6
+ function getChatModelFactory(providerName) {
7
+ return CHAT_MODEL_FACTORIES.get(providerName.toLowerCase());
8
+ }
9
+
10
+ export {
11
+ registerChatModelProvider,
12
+ getChatModelFactory
13
+ };
14
+ //# sourceMappingURL=chunk-G7MKWPEI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/registry/chat-model.ts"],"sourcesContent":["/**\n * Registry for LangChain ChatModel by provider name.\n * Extensions register via registerChatModelProvider.\n */\n\nimport type { BaseChatModel } from \"@langchain/core/language_models/chat_models\";\nimport type { LLMConfig } from \"../model/types.js\";\n\nexport type ChatModelFactory = (config: LLMConfig) => BaseChatModel;\n\nconst CHAT_MODEL_FACTORIES = new Map<string, ChatModelFactory>();\n\nexport function registerChatModelProvider(providerName: string, factory: ChatModelFactory): void {\n CHAT_MODEL_FACTORIES.set(providerName.toLowerCase(), factory);\n}\n\nexport function getChatModelFactory(providerName: string): ChatModelFactory | undefined {\n return CHAT_MODEL_FACTORIES.get(providerName.toLowerCase());\n}\n"],"mappings":";AAUA,IAAM,uBAAuB,oBAAI,IAA8B;AAExD,SAAS,0BAA0B,cAAsB,SAAiC;AAC/F,uBAAqB,IAAI,aAAa,YAAY,GAAG,OAAO;AAC9D;AAEO,SAAS,oBAAoB,cAAoD;AACtF,SAAO,qBAAqB,IAAI,aAAa,YAAY,CAAC;AAC5D;","names":[]}