@easynet/agent-model 1.0.61 → 1.0.62

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 (42) hide show
  1. package/README.md +4 -4
  2. package/dist/api/create-agent-llm.d.ts +1 -1
  3. package/dist/api/create-embed-fn.d.ts +2 -2
  4. package/dist/api/get-default-llm-config.d.ts +3 -3
  5. package/dist/api/get-default-llm-config.d.ts.map +1 -1
  6. package/dist/api/get-default-vlm-config.d.ts +3 -3
  7. package/dist/api/get-default-vlm-config.d.ts.map +1 -1
  8. package/dist/{chunk-CCGNXMFC.js → chunk-4OLU43SH.js} +4 -4
  9. package/dist/{chunk-XSR4TAZ7.js → chunk-HSU6XZOI.js} +8 -8
  10. package/dist/{chunk-JVLYAGWR.js → chunk-NIFNTD6P.js} +6 -6
  11. package/dist/chunk-NIFNTD6P.js.map +1 -0
  12. package/dist/{chunk-VBXTOU4S.js → chunk-WKUSX6VQ.js} +16 -2
  13. package/dist/chunk-WKUSX6VQ.js.map +1 -0
  14. package/dist/{chunk-FZKECZUY.js → chunk-Y7POI745.js} +7 -6
  15. package/dist/chunk-Y7POI745.js.map +1 -0
  16. package/dist/{chunk-V5QTINFH.js → chunk-YOOYQBGK.js} +2 -2
  17. package/dist/{chunk-5YPJ43HW.js → chunk-Z4E7LN4P.js} +1 -1
  18. package/dist/chunk-Z4E7LN4P.js.map +1 -0
  19. package/dist/cli/index.js +6 -6
  20. package/dist/config/index.d.ts +2 -0
  21. package/dist/config/index.d.ts.map +1 -1
  22. package/dist/config/index.js +5 -3
  23. package/dist/config/loader.d.ts +1 -1
  24. package/dist/config/loader.d.ts.map +1 -1
  25. package/dist/config/ref.d.ts +7 -0
  26. package/dist/config/ref.d.ts.map +1 -0
  27. package/dist/extensions/index.js +5 -5
  28. package/dist/index.d.ts +3 -1
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +21 -19
  31. package/dist/index.js.map +1 -1
  32. package/dist/langchain/index.js +2 -2
  33. package/dist/model/embed-parser.d.ts +2 -2
  34. package/dist/model/index.js +1 -1
  35. package/package.json +1 -1
  36. package/dist/chunk-5YPJ43HW.js.map +0 -1
  37. package/dist/chunk-FZKECZUY.js.map +0 -1
  38. package/dist/chunk-JVLYAGWR.js.map +0 -1
  39. package/dist/chunk-VBXTOU4S.js.map +0 -1
  40. /package/dist/{chunk-CCGNXMFC.js.map → chunk-4OLU43SH.js.map} +0 -0
  41. /package/dist/{chunk-XSR4TAZ7.js.map → chunk-HSU6XZOI.js.map} +0 -0
  42. /package/dist/{chunk-V5QTINFH.js.map → chunk-YOOYQBGK.js.map} +0 -0
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @easynet/agent-model
2
2
 
3
- 统一的 Model Hub:从 `models.yaml` 创建 LangChain ChatModel、Embedding 等模型。
3
+ 统一的 Model Hub:从 `model.yaml` 创建 LangChain ChatModel、Embedding 等模型。
4
4
 
5
5
  ## 最小接口
6
6
 
@@ -14,7 +14,7 @@ console.log(result.content);
14
14
 
15
15
  ## 最小 YAML(推荐先用这个)
16
16
 
17
- `models.yaml`
17
+ `model.yaml`
18
18
 
19
19
  ```yaml
20
20
  llm:
@@ -51,7 +51,7 @@ runtime:
51
51
  import { createAgentLlm } from "@easynet/agent-model";
52
52
 
53
53
  async function main() {
54
- // 1) 从当前目录 models.yaml 读取配置并创建模型
54
+ // 1) 从当前目录 model.yaml 读取配置并创建模型
55
55
  const llm = await createAgentLlm();
56
56
 
57
57
  // 2) 直接调用模型
@@ -69,4 +69,4 @@ main().catch(console.error);
69
69
  - 自定义 provider:`registerChatModelProvider(...)`
70
70
  - 只取默认模型配置:`getDefaultLlmConfig(...)`
71
71
  - 直接从对象构建模型:`createChatModelFromLlmConfig(...)`
72
- - 从 models.yaml 创建 EmbedFn:`createEmbedFnFromModelsConfig(...)`
72
+ - 从 model.yaml 创建 EmbedFn:`createEmbedFnFromModelsConfig(...)`
@@ -8,7 +8,7 @@ export interface CreateAgentLlmOptions {
8
8
  connectivityTimeoutMs?: number;
9
9
  }
10
10
  /**
11
- * Create a LangChain ChatModel from models.yaml config.
11
+ * Create a LangChain ChatModel from model.yaml config.
12
12
  * Returns BaseChatModel compatible with LangChain's createAgent and other tools.
13
13
  */
14
14
  export declare function createAgentLlm(configPathOrOptions?: string | CreateAgentLlmOptions): Promise<BaseChatModel>;
@@ -1,9 +1,9 @@
1
1
  export type EmbedFn = (input: string | string[]) => Promise<number[][]>;
2
2
  /**
3
- * Load models.yaml and build an EmbedFn from the `embed:` section.
3
+ * Load model.yaml and build an EmbedFn from the `embed:` section.
4
4
  * Returns undefined if no embed section is configured.
5
5
  *
6
- * @param configPath - Path to models.yaml
6
+ * @param configPath - Path to model.yaml
7
7
  * @param embedId - Which embed instance to use (defaults to the `default:` key)
8
8
  */
9
9
  export declare function createEmbedFnFromModelsConfig(configPath: string, embedId?: string): EmbedFn | undefined;
@@ -1,16 +1,16 @@
1
1
  /**
2
- * Load models.yaml, resolve npm providers, and return the default LLMConfig.
2
+ * Load model.yaml, resolve npm providers, and return the default LLMConfig.
3
3
  * For use by CLIs (e.g. wallee-llm) that need config without creating a model.
4
4
  */
5
5
  import type { LLMConfig } from "../types.js";
6
6
  export interface GetDefaultLlmConfigOptions {
7
- /** Path to models.yaml. Default: process.cwd() + "/models.yaml" */
7
+ /** Path to model.yaml. Default: process.cwd() + "/model.yaml" */
8
8
  configPath?: string;
9
9
  /** Install npm provider packages if missing. Default true. */
10
10
  installNpmIfMissing?: boolean;
11
11
  }
12
12
  /**
13
- * Returns the default LLM config from models.yaml (after resolving npm: providers), or null if no config file.
13
+ * Returns the default LLM config from model.yaml (after resolving npm: providers), or null if no config file.
14
14
  */
15
15
  export declare function getDefaultLlmConfig(options?: GetDefaultLlmConfigOptions): Promise<LLMConfig | null>;
16
16
  //# sourceMappingURL=get-default-llm-config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"get-default-llm-config.d.ts","sourceRoot":"","sources":["../../src/api/get-default-llm-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,0BAA0B;IACzC,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,GAAE,0BAA+B,GACvC,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAa3B"}
1
+ {"version":3,"file":"get-default-llm-config.d.ts","sourceRoot":"","sources":["../../src/api/get-default-llm-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,0BAA0B;IACzC,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,GAAE,0BAA+B,GACvC,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAa3B"}
@@ -1,15 +1,15 @@
1
1
  /**
2
- * Load models.yaml, resolve npm providers, and return a default VLM (type=image) config.
2
+ * Load model.yaml, resolve npm providers, and return a default VLM (type=image) config.
3
3
  */
4
4
  import type { LLMConfig } from "../types.js";
5
5
  export interface GetDefaultVlmConfigOptions {
6
- /** Path to models.yaml. Default: process.cwd() + "/models.yaml" */
6
+ /** Path to model.yaml. Default: process.cwd() + "/model.yaml" */
7
7
  configPath?: string;
8
8
  /** Install npm provider packages if missing. Default true. */
9
9
  installNpmIfMissing?: boolean;
10
10
  }
11
11
  /**
12
- * Returns the default VLM config (type=image) from models.yaml, or null if not configured.
12
+ * Returns the default VLM config (type=image) from model.yaml, or null if not configured.
13
13
  */
14
14
  export declare function getDefaultVlmConfig(options?: GetDefaultVlmConfigOptions): Promise<LLMConfig | null>;
15
15
  //# sourceMappingURL=get-default-vlm-config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"get-default-vlm-config.d.ts","sourceRoot":"","sources":["../../src/api/get-default-vlm-config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,0BAA0B;IACzC,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,GAAE,0BAA+B,GACvC,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAuB3B"}
1
+ {"version":3,"file":"get-default-vlm-config.d.ts","sourceRoot":"","sources":["../../src/api/get-default-vlm-config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,0BAA0B;IACzC,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,GAAE,0BAA+B,GACvC,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAuB3B"}
@@ -1,9 +1,9 @@
1
- import {
2
- parseLlmSection
3
- } from "./chunk-SPDXNDDD.js";
4
1
  import {
5
2
  getChatModelFactory
6
3
  } from "./chunk-G7MKWPEI.js";
4
+ import {
5
+ parseLlmSection
6
+ } from "./chunk-SPDXNDDD.js";
7
7
  import {
8
8
  __export
9
9
  } from "./chunk-PZ5AY32C.js";
@@ -162,4 +162,4 @@ export {
162
162
  createChatModelFromLlmConfig,
163
163
  langchain_exports
164
164
  };
165
- //# sourceMappingURL=chunk-CCGNXMFC.js.map
165
+ //# sourceMappingURL=chunk-4OLU43SH.js.map
@@ -1,3 +1,10 @@
1
+ import {
2
+ createChatModelFromLlmConfig
3
+ } from "./chunk-4OLU43SH.js";
4
+ import {
5
+ getChatModelFactory,
6
+ registerChatModelProvider
7
+ } from "./chunk-G7MKWPEI.js";
1
8
  import {
2
9
  ensureNpmPackageInstalled,
3
10
  getInstalledVersion,
@@ -5,13 +12,6 @@ import {
5
12
  parseNpmProviderSpec,
6
13
  resolveLatestVersionFromRegistry
7
14
  } from "./chunk-K3JR2N4E.js";
8
- import {
9
- createChatModelFromLlmConfig
10
- } from "./chunk-CCGNXMFC.js";
11
- import {
12
- getChatModelFactory,
13
- registerChatModelProvider
14
- } from "./chunk-G7MKWPEI.js";
15
15
 
16
16
  // src/extensions/loader.ts
17
17
  import { readdirSync, readFileSync, existsSync } from "fs";
@@ -351,4 +351,4 @@ export {
351
351
  resolveLlmSectionWithNpm,
352
352
  createChatModelWithNpm
353
353
  };
354
- //# sourceMappingURL=chunk-XSR4TAZ7.js.map
354
+ //# sourceMappingURL=chunk-HSU6XZOI.js.map
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  loadModelsConfig
3
- } from "./chunk-FZKECZUY.js";
3
+ } from "./chunk-Y7POI745.js";
4
4
  import {
5
5
  buildUnreachableError,
6
6
  checkEndpointConnectivity
7
7
  } from "./chunk-EPVJLBGC.js";
8
8
  import {
9
9
  resolveLlmSectionWithNpm
10
- } from "./chunk-XSR4TAZ7.js";
10
+ } from "./chunk-HSU6XZOI.js";
11
11
  import {
12
12
  createChatModelFromLlmConfig
13
- } from "./chunk-CCGNXMFC.js";
13
+ } from "./chunk-4OLU43SH.js";
14
14
  import {
15
15
  parseLlmSection
16
16
  } from "./chunk-SPDXNDDD.js";
@@ -50,7 +50,7 @@ function buildEndpointConnectivityOptions(config) {
50
50
  };
51
51
  }
52
52
  function resolveDefaultConfigPath() {
53
- return join(process.cwd(), "models.yaml");
53
+ return join(process.cwd(), "model.yaml");
54
54
  }
55
55
  function normalizeOptions(configPathOrOptions) {
56
56
  if (configPathOrOptions == null) return {};
@@ -113,7 +113,7 @@ async function createAgentLlm(configPathOrOptions) {
113
113
  const modelsConfig = loadModelsConfig(configPath);
114
114
  if (modelsConfig?.llm == null) {
115
115
  throw new Error(
116
- `No LLM config at ${configPath}. Add models.yaml in the current directory, or pass configPath.`
116
+ `No LLM config at ${configPath}. Add model.yaml in the current directory, or pass configPath.`
117
117
  );
118
118
  }
119
119
  const resolvedSection = await resolveLlmSectionWithNpm(modelsConfig.llm, {
@@ -257,4 +257,4 @@ export {
257
257
  createAgentLlm,
258
258
  cli_exports
259
259
  };
260
- //# sourceMappingURL=chunk-JVLYAGWR.js.map
260
+ //# sourceMappingURL=chunk-NIFNTD6P.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/index.ts","../src/api/create-agent-llm.ts","../src/cli/utils.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * CLI for @easynet/agent-model: chat with the configured LLM (LangChain ChatOpenAI).\n * Usage: agent-model \"your question\"\n * or: agent-model --config ./model.yaml \"hi\"\n * or: agent-model --tools \"what is the weather in SF?\"\n */\nimport { createAgentLlm } from \"../api/create-agent-llm.js\";\nimport { messageContentToString } from \"./utils.js\";\nimport type { BaseChatModel } from \"@langchain/core/language_models/chat_models\";\nimport { tool } from \"@langchain/core/tools\";\nimport { z } from \"zod\";\nimport { HumanMessage, AIMessage, ToolMessage } from \"@langchain/core/messages\";\nimport type { BaseMessage } from \"@langchain/core/messages\";\nimport { fileURLToPath } from \"node:url\";\n\nfunction parseArgv(): { configPath: string | undefined; useTools: boolean; query: string } {\n const args = process.argv.slice(2);\n let configPath: string | undefined;\n let useTools = false;\n const rest: string[] = [];\n for (let i = 0; i < args.length; i++) {\n if (args[i] === \"--config\" && args[i + 1]) {\n configPath = args[i + 1];\n i++;\n } else if (args[i] === \"--tools\") {\n useTools = true;\n } else {\n rest.push(args[i]);\n }\n }\n const query = rest.join(\" \").trim() || \"hi\";\n return { configPath, useTools, query };\n}\n\nconst getWeather = tool(\n (input: { location: string }) => {\n const loc = input.location.toLowerCase();\n if ([\"sf\", \"sf bay\"].includes(loc)) return \"It's 60°F and foggy in the Bay Area.\";\n if ([\"ny\", \"new york\"].includes(loc)) return \"It's 72°F and partly cloudy in New York.\";\n return `Weather for ${input.location}: 70°F and sunny.`;\n },\n {\n name: \"get_weather\",\n description: \"Get the current weather for a location.\",\n schema: z.object({\n location: z.string().describe(\"City or place name (e.g. SF, New York)\"),\n }),\n }\n);\n\nconst addNumbers = tool(\n (input: { a: number; b: number }) => String(input.a + input.b),\n {\n name: \"add_numbers\",\n description: \"Add two numbers.\",\n schema: z.object({\n a: z.number().describe(\"First number\"),\n b: z.number().describe(\"Second number\"),\n }),\n }\n);\n\nconst tools = [getWeather, addNumbers];\nconst toolsByName = new Map(tools.map((t) => [t.name, t]));\nconst MAX_TURNS = 10;\n\nasync function runSimpleChat(model: BaseChatModel, query: string): Promise<string> {\n const messages: BaseMessage[] = [new HumanMessage(query)];\n const response = await model.invoke(messages);\n return messageContentToString(response.content);\n}\n\nasync function runAgentWithTools(model: BaseChatModel, query: string): Promise<string> {\n const withTools = model.bindTools?.(tools, { tool_choice: \"auto\" });\n const messages: BaseMessage[] = [new HumanMessage(query)];\n if (!withTools) return runSimpleChat(model, query);\n\n for (let turn = 0; turn < MAX_TURNS; turn++) {\n const response = await withTools.invoke(messages);\n const aiMessage = response as AIMessage;\n\n if (!aiMessage.tool_calls?.length) {\n return messageContentToString(aiMessage.content);\n }\n\n messages.push(aiMessage);\n for (const tc of aiMessage.tool_calls) {\n const id = tc.id ?? `call_${turn}_${tc.name}`;\n const toolFn = toolsByName.get(tc.name as \"get_weather\" | \"add_numbers\");\n let result: string;\n if (toolFn) {\n try {\n const out = await (toolFn as { invoke: (args: Record<string, unknown>) => Promise<unknown> }).invoke(\n tc.args as Record<string, unknown>\n );\n result = typeof out === \"string\" ? out : JSON.stringify(out);\n } catch (err) {\n result = `Error: ${err instanceof Error ? err.message : String(err)}`;\n }\n } else {\n result = `Unknown tool: ${tc.name}`;\n }\n messages.push(new ToolMessage({ content: result, tool_call_id: id }));\n }\n }\n return \"Agent reached max turns without a final answer.\";\n}\n\nasync function main() {\n const { configPath, useTools, query } = parseArgv();\n const model = await createAgentLlm(configPath ? { configPath } : undefined);\n\n console.log(\"Query:\", query);\n console.log(\"---\");\n const answer = useTools\n ? await runAgentWithTools(model, query)\n : await runSimpleChat(model, query);\n console.log(\"Answer:\", answer);\n console.log(\"---\");\n console.log(\"Done.\");\n}\n\nconst entryArg = process.argv[1];\nconst isDirectRun =\n typeof entryArg === \"string\" && entryArg.length > 0 && fileURLToPath(import.meta.url) === entryArg;\n\nif (isDirectRun) {\n main().catch((err) => {\n console.error(err);\n process.exit(1);\n });\n}\n","/**\n * Simple API: create LangChain ChatModel from model.yaml config.\n * Supports OpenAI-compatible providers with optional connectivity check and npm: provider resolution.\n */\nimport { join } from \"node:path\";\nimport type { BaseChatModel } from \"@langchain/core/language_models/chat_models\";\nimport {\n checkEndpointConnectivity,\n buildUnreachableError,\n type EndpointConnectivityOptions,\n type ConnectionStatus,\n} from \"../connectivity/index.js\";\nimport { parseLlmSection } from \"../model/llm-parser.js\";\nimport type { LLMConfig } from \"../model/types.js\";\nimport { createChatModelFromLlmConfig } from \"../langchain/index.js\";\nimport { resolveLlmSectionWithNpm } from \"../extensions/npm-protocol.js\";\nimport { loadModelsConfig } from \"../config/loader.js\";\n\n/**\n * Ensure bindTools always receives tool_choice: \"auto\" when tools are bound.\n * Fixes \"Tool choice is none, but model called a tool\" when using this model\n * with LangChain createAgent (AgentNode leaves tool_choice undefined for non-structured tools).\n * Mutates the model in place so it still passes isBaseChatModel / bindTools checks.\n */\nfunction applyDefaultToolChoice(model: BaseChatModel): void {\n const m = model as {\n bindTools?: (tools: unknown, opts?: Record<string, unknown>) => unknown;\n };\n const orig = m.bindTools?.bind(model);\n if (!orig) return;\n m.bindTools = function (tools: unknown, opts?: Record<string, unknown>) {\n return orig(tools, { ...opts, tool_choice: \"auto\" });\n };\n}\n\nconst CIS_DEFAULT_RESOLVE_HOST = \"s0010-ml-https.s0010.us-west-2.awswd\";\nconst CIS_DEFAULT_RESOLVE_IP = \"10.210.98.124\";\n\nfunction buildEndpointConnectivityOptions(\n config: LLMConfig & { baseURL: string }\n): EndpointConnectivityOptions | undefined {\n const opts = (config.options as Record<string, unknown> | undefined) ?? config;\n const provider = typeof config.provider === \"string\" ? config.provider : \"\";\n const baseURL = config.baseURL;\n const isCis = provider === \"cis\" || provider.includes(\"cis\");\n const useCisDefault =\n isCis &&\n baseURL.includes(CIS_DEFAULT_RESOLVE_HOST) &&\n opts?.resolveHost == null;\n\n const resolveHost =\n opts?.resolveHost != null && typeof (opts.resolveHost as { from?: string; to?: string }).from === \"string\"\n ? (opts.resolveHost as { from: string; to: string })\n : useCisDefault\n ? { from: CIS_DEFAULT_RESOLVE_HOST, to: CIS_DEFAULT_RESOLVE_IP }\n : undefined;\n const host = typeof opts?.host === \"string\" ? opts.host : (resolveHost ? resolveHost.from : undefined);\n if (resolveHost == null && host == null) return undefined;\n\n const verifySSL = opts?.verifySSL === true;\n const bypassAuth = opts?.bypassAuth !== false;\n\n return {\n resolveHost,\n host,\n verifySSL: resolveHost != null ? false : (verifySSL ? true : undefined),\n bypassAuth: bypassAuth ? true : undefined,\n featureKey: typeof opts?.featureKey === \"string\" ? opts.featureKey : undefined,\n };\n}\n\nexport interface CreateAgentLlmOptions {\n configPath?: string;\n installNpmIfMissing?: boolean;\n checkConnectivity?: boolean;\n onConnectionStatus?: (status: ConnectionStatus) => void;\n connectivityTimeoutMs?: number;\n}\n\nfunction resolveDefaultConfigPath(): string {\n return join(process.cwd(), \"model.yaml\");\n}\n\nfunction normalizeOptions(\n configPathOrOptions?: string | CreateAgentLlmOptions\n): CreateAgentLlmOptions {\n if (configPathOrOptions == null) return {};\n if (typeof configPathOrOptions === \"string\") return { configPath: configPathOrOptions };\n return configPathOrOptions;\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\nasync function ensureConnectivity(\n resolvedLlmSection: unknown,\n options: {\n checkConnectivity?: boolean;\n onConnectionStatus?: (status: ConnectionStatus) => void;\n connectivityTimeoutMs?: number;\n }\n): Promise<void> {\n let configs: Array<LLMConfig & { baseURL: string }>;\n try {\n const parsed = parseLlmSection(resolvedLlmSection ?? null);\n configs = parsed.configs.filter(\n (c: LLMConfig): c is LLMConfig & { baseURL: string } =>\n typeof c.baseURL === \"string\" &&\n c.baseURL.length > 0 &&\n (c.baseURL.startsWith(\"http://\") || c.baseURL.startsWith(\"https://\")) &&\n !c.baseURL.includes(\"${\")\n );\n } catch {\n return;\n }\n const shouldCheck = options.checkConnectivity !== false && configs.length > 0;\n if (!shouldCheck) return;\n\n const report = (status: ConnectionStatus) => options.onConnectionStatus?.(status);\n const timeoutMs = options.connectivityTimeoutMs ?? 8000;\n\n for (const config of configs) {\n const { id, baseURL } = config;\n report({\n phase: \"checking\",\n endpointId: id,\n baseURL,\n message: \"Checking connection...\",\n });\n\n const endpointOpts = buildEndpointConnectivityOptions(config);\n const result = await checkEndpointConnectivity(baseURL, {\n timeoutMs,\n ...endpointOpts,\n });\n\n if (result.reachable) {\n report({\n phase: \"reachable\",\n endpointId: id,\n baseURL,\n message: result.message ?? \"Connected\",\n });\n } else {\n report({\n phase: \"unreachable\",\n endpointId: id,\n baseURL,\n message: result.message ?? \"Unreachable\",\n });\n throw new Error(buildUnreachableError(id, baseURL, result.message));\n }\n }\n}\n\n/**\n * Create a LangChain ChatModel from model.yaml config.\n * Returns BaseChatModel compatible with LangChain's createAgent and other tools.\n */\nexport async function createAgentLlm(\n configPathOrOptions?: string | CreateAgentLlmOptions\n): Promise<BaseChatModel> {\n try {\n const options = normalizeOptions(configPathOrOptions);\n const configPath = options.configPath ?? resolveDefaultConfigPath();\n const modelsConfig = loadModelsConfig(configPath);\n\n if (modelsConfig?.llm == null) {\n throw new Error(\n `No LLM config at ${configPath}. Add model.yaml in the current directory, or pass configPath.`\n );\n }\n\n const resolvedSection = await resolveLlmSectionWithNpm(modelsConfig.llm, {\n installNpmIfMissing: options.installNpmIfMissing !== false,\n cwd: process.cwd(),\n });\n\n // Priority: caller option > YAML runtime > default (true)\n const checkConnectivity =\n options.checkConnectivity ?? modelsConfig.runtime.check_connectivity;\n\n await ensureConnectivity(resolvedSection, {\n checkConnectivity,\n onConnectionStatus: options.onConnectionStatus,\n connectivityTimeoutMs: options.connectivityTimeoutMs,\n });\n\n const model = createChatModelFromLlmConfig({ llmSection: resolvedSection });\n applyDefaultToolChoice(model);\n return model;\n } catch (e) {\n if (e instanceof Error && e.message.includes(\"No LLM config\")) throw e;\n if (e instanceof Error && e.message.includes(\"Cannot connect to\")) throw e;\n throw normalizeError(e, \"createAgentLlm failed\");\n }\n}\n","/**\n * Shared CLI helpers for agent-model and provider CLIs.\n */\n\n/**\n * Turn LangChain message content (string | array of parts) into a single string.\n */\nexport function messageContentToString(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (Array.isArray(content)) {\n return (content as { type?: string; text?: string }[])\n .map((c) => (\"text\" in c && c.text ? c.text : \"\"))\n .join(\"\");\n }\n return String(content ?? \"\");\n}\n\n/**\n * Log error and exit. Use in CLIs for consistent error handling.\n */\nexport function exitWithError(err: unknown, code = 1): never {\n console.error(\"Error:\", err instanceof Error ? err.message : String(err));\n process.exit(code);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;;;ACIA,SAAS,YAAY;AAoBrB,SAAS,uBAAuB,OAA4B;AAC1D,QAAM,IAAI;AAGV,QAAM,OAAO,EAAE,WAAW,KAAK,KAAK;AACpC,MAAI,CAAC,KAAM;AACX,IAAE,YAAY,SAAUA,QAAgB,MAAgC;AACtE,WAAO,KAAKA,QAAO,EAAE,GAAG,MAAM,aAAa,OAAO,CAAC;AAAA,EACrD;AACF;AAEA,IAAM,2BAA2B;AACjC,IAAM,yBAAyB;AAE/B,SAAS,iCACP,QACyC;AACzC,QAAM,OAAQ,OAAO,WAAmD;AACxE,QAAM,WAAW,OAAO,OAAO,aAAa,WAAW,OAAO,WAAW;AACzE,QAAM,UAAU,OAAO;AACvB,QAAM,QAAQ,aAAa,SAAS,SAAS,SAAS,KAAK;AAC3D,QAAM,gBACJ,SACA,QAAQ,SAAS,wBAAwB,KACzC,MAAM,eAAe;AAEvB,QAAM,cACJ,MAAM,eAAe,QAAQ,OAAQ,KAAK,YAA+C,SAAS,WAC7F,KAAK,cACN,gBACE,EAAE,MAAM,0BAA0B,IAAI,uBAAuB,IAC7D;AACR,QAAM,OAAO,OAAO,MAAM,SAAS,WAAW,KAAK,OAAQ,cAAc,YAAY,OAAO;AAC5F,MAAI,eAAe,QAAQ,QAAQ,KAAM,QAAO;AAEhD,QAAM,YAAY,MAAM,cAAc;AACtC,QAAM,aAAa,MAAM,eAAe;AAExC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,WAAW,eAAe,OAAO,QAAS,YAAY,OAAO;AAAA,IAC7D,YAAY,aAAa,OAAO;AAAA,IAChC,YAAY,OAAO,MAAM,eAAe,WAAW,KAAK,aAAa;AAAA,EACvE;AACF;AAUA,SAAS,2BAAmC;AAC1C,SAAO,KAAK,QAAQ,IAAI,GAAG,YAAY;AACzC;AAEA,SAAS,iBACP,qBACuB;AACvB,MAAI,uBAAuB,KAAM,QAAO,CAAC;AACzC,MAAI,OAAO,wBAAwB,SAAU,QAAO,EAAE,YAAY,oBAAoB;AACtF,SAAO;AACT;AAEA,SAAS,eAAe,GAAY,SAAwB;AAC1D,MAAI,aAAa,MAAO,QAAO,IAAI,MAAM,GAAG,OAAO,KAAK,EAAE,OAAO,IAAI,EAAE,OAAO,EAAE,CAAC;AACjF,SAAO,IAAI,MAAM,GAAG,OAAO,KAAK,OAAO,CAAC,CAAC,EAAE;AAC7C;AAEA,eAAe,mBACb,oBACA,SAKe;AACf,MAAI;AACJ,MAAI;AACF,UAAM,SAAS,gBAAgB,sBAAsB,IAAI;AACzD,cAAU,OAAO,QAAQ;AAAA,MACvB,CAAC,MACC,OAAO,EAAE,YAAY,YACrB,EAAE,QAAQ,SAAS,MAClB,EAAE,QAAQ,WAAW,SAAS,KAAK,EAAE,QAAQ,WAAW,UAAU,MACnE,CAAC,EAAE,QAAQ,SAAS,IAAI;AAAA,IAC5B;AAAA,EACF,QAAQ;AACN;AAAA,EACF;AACA,QAAM,cAAc,QAAQ,sBAAsB,SAAS,QAAQ,SAAS;AAC5E,MAAI,CAAC,YAAa;AAElB,QAAM,SAAS,CAAC,WAA6B,QAAQ,qBAAqB,MAAM;AAChF,QAAM,YAAY,QAAQ,yBAAyB;AAEnD,aAAW,UAAU,SAAS;AAC5B,UAAM,EAAE,IAAI,QAAQ,IAAI;AACxB,WAAO;AAAA,MACL,OAAO;AAAA,MACP,YAAY;AAAA,MACZ;AAAA,MACA,SAAS;AAAA,IACX,CAAC;AAED,UAAM,eAAe,iCAAiC,MAAM;AAC5D,UAAM,SAAS,MAAM,0BAA0B,SAAS;AAAA,MACtD;AAAA,MACA,GAAG;AAAA,IACL,CAAC;AAED,QAAI,OAAO,WAAW;AACpB,aAAO;AAAA,QACL,OAAO;AAAA,QACP,YAAY;AAAA,QACZ;AAAA,QACA,SAAS,OAAO,WAAW;AAAA,MAC7B,CAAC;AAAA,IACH,OAAO;AACL,aAAO;AAAA,QACL,OAAO;AAAA,QACP,YAAY;AAAA,QACZ;AAAA,QACA,SAAS,OAAO,WAAW;AAAA,MAC7B,CAAC;AACD,YAAM,IAAI,MAAM,sBAAsB,IAAI,SAAS,OAAO,OAAO,CAAC;AAAA,IACpE;AAAA,EACF;AACF;AAMA,eAAsB,eACpB,qBACwB;AACxB,MAAI;AACF,UAAM,UAAU,iBAAiB,mBAAmB;AACpD,UAAM,aAAa,QAAQ,cAAc,yBAAyB;AAClE,UAAM,eAAe,iBAAiB,UAAU;AAEhD,QAAI,cAAc,OAAO,MAAM;AAC7B,YAAM,IAAI;AAAA,QACR,oBAAoB,UAAU;AAAA,MAChC;AAAA,IACF;AAEA,UAAM,kBAAkB,MAAM,yBAAyB,aAAa,KAAK;AAAA,MACvE,qBAAqB,QAAQ,wBAAwB;AAAA,MACrD,KAAK,QAAQ,IAAI;AAAA,IACnB,CAAC;AAGD,UAAM,oBACJ,QAAQ,qBAAqB,aAAa,QAAQ;AAEpD,UAAM,mBAAmB,iBAAiB;AAAA,MACxC;AAAA,MACA,oBAAoB,QAAQ;AAAA,MAC5B,uBAAuB,QAAQ;AAAA,IACjC,CAAC;AAED,UAAM,QAAQ,6BAA6B,EAAE,YAAY,gBAAgB,CAAC;AAC1E,2BAAuB,KAAK;AAC5B,WAAO;AAAA,EACT,SAAS,GAAG;AACV,QAAI,aAAa,SAAS,EAAE,QAAQ,SAAS,eAAe,EAAG,OAAM;AACrE,QAAI,aAAa,SAAS,EAAE,QAAQ,SAAS,mBAAmB,EAAG,OAAM;AACzE,UAAM,eAAe,GAAG,uBAAuB;AAAA,EACjD;AACF;;;AC/LO,SAAS,uBAAuB,SAA0B;AAC/D,MAAI,OAAO,YAAY,SAAU,QAAO;AACxC,MAAI,MAAM,QAAQ,OAAO,GAAG;AAC1B,WAAQ,QACL,IAAI,CAAC,MAAO,UAAU,KAAK,EAAE,OAAO,EAAE,OAAO,EAAG,EAChD,KAAK,EAAE;AAAA,EACZ;AACA,SAAO,OAAO,WAAW,EAAE;AAC7B;;;AFLA,SAAS,YAAY;AACrB,SAAS,SAAS;AAClB,SAAS,cAAyB,mBAAmB;AAErD,SAAS,qBAAqB;AAE9B,SAAS,YAAkF;AACzF,QAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AACjC,MAAI;AACJ,MAAI,WAAW;AACf,QAAM,OAAiB,CAAC;AACxB,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,QAAI,KAAK,CAAC,MAAM,cAAc,KAAK,IAAI,CAAC,GAAG;AACzC,mBAAa,KAAK,IAAI,CAAC;AACvB;AAAA,IACF,WAAW,KAAK,CAAC,MAAM,WAAW;AAChC,iBAAW;AAAA,IACb,OAAO;AACL,WAAK,KAAK,KAAK,CAAC,CAAC;AAAA,IACnB;AAAA,EACF;AACA,QAAM,QAAQ,KAAK,KAAK,GAAG,EAAE,KAAK,KAAK;AACvC,SAAO,EAAE,YAAY,UAAU,MAAM;AACvC;AAEA,IAAM,aAAa;AAAA,EACjB,CAAC,UAAgC;AAC/B,UAAM,MAAM,MAAM,SAAS,YAAY;AACvC,QAAI,CAAC,MAAM,QAAQ,EAAE,SAAS,GAAG,EAAG,QAAO;AAC3C,QAAI,CAAC,MAAM,UAAU,EAAE,SAAS,GAAG,EAAG,QAAO;AAC7C,WAAO,eAAe,MAAM,QAAQ;AAAA,EACtC;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,QAAQ,EAAE,OAAO;AAAA,MACf,UAAU,EAAE,OAAO,EAAE,SAAS,wCAAwC;AAAA,IACxE,CAAC;AAAA,EACH;AACF;AAEA,IAAM,aAAa;AAAA,EACjB,CAAC,UAAoC,OAAO,MAAM,IAAI,MAAM,CAAC;AAAA,EAC7D;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,QAAQ,EAAE,OAAO;AAAA,MACf,GAAG,EAAE,OAAO,EAAE,SAAS,cAAc;AAAA,MACrC,GAAG,EAAE,OAAO,EAAE,SAAS,eAAe;AAAA,IACxC,CAAC;AAAA,EACH;AACF;AAEA,IAAM,QAAQ,CAAC,YAAY,UAAU;AACrC,IAAM,cAAc,IAAI,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AACzD,IAAM,YAAY;AAElB,eAAe,cAAc,OAAsB,OAAgC;AACjF,QAAM,WAA0B,CAAC,IAAI,aAAa,KAAK,CAAC;AACxD,QAAM,WAAW,MAAM,MAAM,OAAO,QAAQ;AAC5C,SAAO,uBAAuB,SAAS,OAAO;AAChD;AAEA,eAAe,kBAAkB,OAAsB,OAAgC;AACrF,QAAM,YAAY,MAAM,YAAY,OAAO,EAAE,aAAa,OAAO,CAAC;AAClE,QAAM,WAA0B,CAAC,IAAI,aAAa,KAAK,CAAC;AACxD,MAAI,CAAC,UAAW,QAAO,cAAc,OAAO,KAAK;AAEjD,WAAS,OAAO,GAAG,OAAO,WAAW,QAAQ;AAC3C,UAAM,WAAW,MAAM,UAAU,OAAO,QAAQ;AAChD,UAAM,YAAY;AAElB,QAAI,CAAC,UAAU,YAAY,QAAQ;AACjC,aAAO,uBAAuB,UAAU,OAAO;AAAA,IACjD;AAEA,aAAS,KAAK,SAAS;AACvB,eAAW,MAAM,UAAU,YAAY;AACrC,YAAM,KAAK,GAAG,MAAM,QAAQ,IAAI,IAAI,GAAG,IAAI;AAC3C,YAAM,SAAS,YAAY,IAAI,GAAG,IAAqC;AACvE,UAAI;AACJ,UAAI,QAAQ;AACV,YAAI;AACF,gBAAM,MAAM,MAAO,OAA2E;AAAA,YAC5F,GAAG;AAAA,UACL;AACA,mBAAS,OAAO,QAAQ,WAAW,MAAM,KAAK,UAAU,GAAG;AAAA,QAC7D,SAAS,KAAK;AACZ,mBAAS,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,QACrE;AAAA,MACF,OAAO;AACL,iBAAS,iBAAiB,GAAG,IAAI;AAAA,MACnC;AACA,eAAS,KAAK,IAAI,YAAY,EAAE,SAAS,QAAQ,cAAc,GAAG,CAAC,CAAC;AAAA,IACtE;AAAA,EACF;AACA,SAAO;AACT;AAEA,eAAe,OAAO;AACpB,QAAM,EAAE,YAAY,UAAU,MAAM,IAAI,UAAU;AAClD,QAAM,QAAQ,MAAM,eAAe,aAAa,EAAE,WAAW,IAAI,MAAS;AAE1E,UAAQ,IAAI,UAAU,KAAK;AAC3B,UAAQ,IAAI,KAAK;AACjB,QAAM,SAAS,WACX,MAAM,kBAAkB,OAAO,KAAK,IACpC,MAAM,cAAc,OAAO,KAAK;AACpC,UAAQ,IAAI,WAAW,MAAM;AAC7B,UAAQ,IAAI,KAAK;AACjB,UAAQ,IAAI,OAAO;AACrB;AAEA,IAAM,WAAW,QAAQ,KAAK,CAAC;AAC/B,IAAM,cACJ,OAAO,aAAa,YAAY,SAAS,SAAS,KAAK,cAAc,YAAY,GAAG,MAAM;AAE5F,IAAI,aAAa;AACf,OAAK,EAAE,MAAM,CAAC,QAAQ;AACpB,YAAQ,MAAM,GAAG;AACjB,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACH;","names":["tools"]}
@@ -6,7 +6,7 @@ import {
6
6
  parseLlmYaml,
7
7
  parseYamlContent,
8
8
  substituteEnv
9
- } from "./chunk-FZKECZUY.js";
9
+ } from "./chunk-Y7POI745.js";
10
10
  import {
11
11
  parseLlmSection
12
12
  } from "./chunk-SPDXNDDD.js";
@@ -22,6 +22,7 @@ __export(config_exports, {
22
22
  loadYamlConfig: () => loadYamlConfig,
23
23
  loadYamlFile: () => loadYamlFile,
24
24
  loadYamlFileSync: () => loadYamlFileSync,
25
+ normalizeAgentModelConfigRef: () => normalizeAgentModelConfigRef,
25
26
  parseLlmSection: () => parseLlmSection,
26
27
  parseLlmYaml: () => parseLlmYaml,
27
28
  parseYamlContent: () => parseYamlContent,
@@ -43,8 +44,21 @@ function loadYamlConfig(filePath) {
43
44
  }
44
45
  }
45
46
 
47
+ // src/config/ref.ts
48
+ function asObject(input) {
49
+ return typeof input === "object" && input !== null ? input : void 0;
50
+ }
51
+ function normalizeAgentModelConfigRef(raw) {
52
+ if (typeof raw === "string" && raw.trim().length > 0) return { ref: raw.trim() };
53
+ const obj = asObject(raw);
54
+ if (!obj) return {};
55
+ if (typeof obj.ref === "string" && obj.ref.trim().length > 0) return { ref: obj.ref.trim() };
56
+ return {};
57
+ }
58
+
46
59
  export {
47
60
  loadYamlConfig,
61
+ normalizeAgentModelConfigRef,
48
62
  config_exports
49
63
  };
50
- //# sourceMappingURL=chunk-VBXTOU4S.js.map
64
+ //# sourceMappingURL=chunk-WKUSX6VQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config/index.ts","../src/config/yaml.ts","../src/config/ref.ts"],"sourcesContent":["export { parseLlmSection } from \"./parser.js\";\nexport { loadLlmConfig, parseLlmYaml, substituteEnv } from \"./loader.js\";\nexport { loadYamlConfig } from \"./yaml.js\";\nexport { normalizeAgentModelConfigRef } from \"./ref.js\";\nexport {\n loadYamlFile,\n loadYamlFileSync,\n parseYamlContent,\n clearYamlFileCache,\n type LoadYamlOptions,\n type YamlEnvOptions,\n} from \"./yaml-utils.js\";\nexport type { LoadLlmConfigOptions } from \"./loader.js\";\nexport type { AgentModelConfigRef } from \"./ref.js\";\n","/**\n * Generic YAML file loader utility.\n */\n\nimport { loadYamlFileSync } from \"./yaml-utils.js\";\n\n/**\n * Load and parse a YAML file into a typed object.\n * Returns empty object if file doesn't exist.\n */\nexport function loadYamlConfig<T = Record<string, unknown>>(filePath: string): T {\n try {\n const parsed = loadYamlFileSync<T>(filePath, {\n substituteEnv: true,\n missingEnv: \"keep\",\n cache: true,\n });\n return (parsed ?? ({} as T)) as T;\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n throw new Error(`Failed to load YAML config from ${filePath}: ${msg}`, { cause: e });\n }\n}\n","/** Agent-level reference to models config file. */\nexport interface AgentModelConfigRef {\n ref?: string;\n}\n\nfunction asObject(input: unknown): Record<string, unknown> | undefined {\n return typeof input === \"object\" && input !== null ? (input as Record<string, unknown>) : undefined;\n}\n\n/** Normalize unknown value to AgentModelConfigRef. */\nexport function normalizeAgentModelConfigRef(raw: unknown): Partial<AgentModelConfigRef> {\n if (typeof raw === \"string\" && raw.trim().length > 0) return { ref: raw.trim() };\n const obj = asObject(raw);\n if (!obj) return {};\n if (typeof obj.ref === \"string\" && obj.ref.trim().length > 0) return { ref: obj.ref.trim() };\n return {};\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACUO,SAAS,eAA4C,UAAqB;AAC/E,MAAI;AACF,UAAM,SAAS,iBAAoB,UAAU;AAAA,MAC3C,eAAe;AAAA,MACf,YAAY;AAAA,MACZ,OAAO;AAAA,IACT,CAAC;AACD,WAAQ,UAAW,CAAC;AAAA,EACtB,SAAS,GAAG;AACV,UAAM,MAAM,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;AACrD,UAAM,IAAI,MAAM,mCAAmC,QAAQ,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,CAAC;AAAA,EACrF;AACF;;;ACjBA,SAAS,SAAS,OAAqD;AACrE,SAAO,OAAO,UAAU,YAAY,UAAU,OAAQ,QAAoC;AAC5F;AAGO,SAAS,6BAA6B,KAA4C;AACvF,MAAI,OAAO,QAAQ,YAAY,IAAI,KAAK,EAAE,SAAS,EAAG,QAAO,EAAE,KAAK,IAAI,KAAK,EAAE;AAC/E,QAAM,MAAM,SAAS,GAAG;AACxB,MAAI,CAAC,IAAK,QAAO,CAAC;AAClB,MAAI,OAAO,IAAI,QAAQ,YAAY,IAAI,IAAI,KAAK,EAAE,SAAS,EAAG,QAAO,EAAE,KAAK,IAAI,IAAI,KAAK,EAAE;AAC3F,SAAO,CAAC;AACV;","names":[]}
@@ -102,7 +102,7 @@ function parseLlmYaml(content, options = {}) {
102
102
  substituteEnv: doSub,
103
103
  missingEnv: "keep"
104
104
  });
105
- const llm = parsed?.llm;
105
+ const llm = parsed?.spec?.llm ?? parsed?.llm;
106
106
  if (llm == null) return void 0;
107
107
  return llm;
108
108
  }
@@ -117,12 +117,13 @@ function loadModelsConfig(filePath, options = {}) {
117
117
  cache: true
118
118
  });
119
119
  if (parsed == null) return null;
120
+ const source = parsed.spec ?? parsed;
120
121
  return {
121
- llm: parsed.llm ?? null,
122
- vlm: parsed.vlm ?? null,
123
- embed: parsed.embed ?? null,
122
+ llm: source.llm ?? null,
123
+ vlm: source.vlm ?? null,
124
+ embed: source.embed ?? null,
124
125
  runtime: {
125
- check_connectivity: typeof parsed.runtime?.check_connectivity === "boolean" ? parsed.runtime.check_connectivity : void 0
126
+ check_connectivity: typeof source.runtime?.check_connectivity === "boolean" ? source.runtime.check_connectivity : void 0
126
127
  }
127
128
  };
128
129
  } catch (e) {
@@ -145,4 +146,4 @@ export {
145
146
  loadModelsConfig,
146
147
  loadLlmConfig
147
148
  };
148
- //# sourceMappingURL=chunk-FZKECZUY.js.map
149
+ //# sourceMappingURL=chunk-Y7POI745.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config/yaml-utils.ts","../src/config/loader.ts"],"sourcesContent":["import { existsSync, readFileSync, statSync } from \"node:fs\";\nimport { readFile, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { parse as parseYaml } from \"yaml\";\n\nexport interface YamlEnvOptions {\n substituteEnv?: boolean;\n missingEnv?: \"keep\" | \"empty\";\n env?: NodeJS.ProcessEnv;\n}\n\nexport interface LoadYamlOptions extends YamlEnvOptions {\n cache?: boolean;\n}\n\ninterface CacheEntry {\n mtimeMs: number;\n value: unknown;\n}\n\nconst YAML_CACHE = new Map<string, CacheEntry>();\n\nexport function clearYamlFileCache(): void {\n YAML_CACHE.clear();\n}\n\nfunction substituteEnvInString(\n input: string,\n env: NodeJS.ProcessEnv,\n missingEnv: \"keep\" | \"empty\",\n): string {\n return input.replace(/\\$\\{(\\w+)\\}/g, (_, name: string) => {\n const value = env[name];\n if (value !== undefined) return value;\n return missingEnv === \"empty\" ? \"\" : `\\${${name}}`;\n });\n}\n\nfunction substituteEnvInValue(\n input: unknown,\n options: { env: NodeJS.ProcessEnv; missingEnv: \"keep\" | \"empty\" },\n): unknown {\n if (typeof input === \"string\") {\n return substituteEnvInString(input, options.env, options.missingEnv);\n }\n if (Array.isArray(input)) {\n return input.map((item) => substituteEnvInValue(item, options));\n }\n if (input && typeof input === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(input)) {\n out[k] = substituteEnvInValue(v, options);\n }\n return out;\n }\n return input;\n}\n\nexport function parseYamlContent<T = unknown>(\n content: string,\n options: YamlEnvOptions = {},\n): T {\n const parsed = parseYaml(content) as unknown;\n if (options.substituteEnv === false) return parsed as T;\n return substituteEnvInValue(parsed, {\n env: options.env ?? process.env,\n missingEnv: options.missingEnv ?? \"keep\",\n }) as T;\n}\n\nfunction readFromCache(filePath: string, mtimeMs: number): unknown | undefined {\n const cached = YAML_CACHE.get(filePath);\n if (!cached) return undefined;\n if (cached.mtimeMs !== mtimeMs) return undefined;\n return cached.value;\n}\n\nfunction writeCache(filePath: string, mtimeMs: number, value: unknown): void {\n YAML_CACHE.set(filePath, { mtimeMs, value });\n}\n\nexport function loadYamlFileSync<T = unknown>(\n filePath: string,\n options: LoadYamlOptions = {},\n): T | undefined {\n const absPath = path.resolve(filePath);\n if (!existsSync(absPath)) return undefined;\n const useCache = options.cache === true;\n const fileStat = statSync(absPath);\n if (useCache) {\n const cached = readFromCache(absPath, fileStat.mtimeMs);\n if (cached !== undefined) return cached as T;\n }\n const content = readFileSync(absPath, \"utf-8\");\n const parsed = parseYamlContent<T>(content, options);\n if (useCache) writeCache(absPath, fileStat.mtimeMs, parsed);\n return parsed;\n}\n\nexport async function loadYamlFile<T = unknown>(\n filePath: string,\n options: LoadYamlOptions = {},\n): Promise<T | undefined> {\n const absPath = path.resolve(filePath);\n let fileStat;\n try {\n fileStat = await stat(absPath);\n } catch (err) {\n if ((err as NodeJS.ErrnoException)?.code === \"ENOENT\") return undefined;\n throw err;\n }\n const useCache = options.cache === true;\n if (useCache) {\n const cached = readFromCache(absPath, fileStat.mtimeMs);\n if (cached !== undefined) return cached as T;\n }\n const content = await readFile(absPath, \"utf-8\");\n const parsed = parseYamlContent<T>(content, options);\n if (useCache) writeCache(absPath, fileStat.mtimeMs, parsed);\n return parsed;\n}\n","/**\n * Load and parse LLM config from YAML (e.g. model.yaml).\n * Supports ${VAR} substitution from process.env.\n */\nimport { loadYamlFileSync, parseYamlContent } from \"./yaml-utils.js\";\n\nexport interface LoadLlmConfigOptions {\n substituteEnv?: boolean;\n}\n\nexport function substituteEnv(obj: unknown): unknown {\n if (obj === null || obj === undefined) return obj;\n if (typeof obj === \"string\") {\n const m = obj.match(/^\\$\\{(\\w+)\\}$/);\n return m ? (process.env[m[1]] ?? obj) : obj;\n }\n if (Array.isArray(obj)) return obj.map(substituteEnv);\n if (typeof obj === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(obj)) out[k] = substituteEnv(v);\n return out;\n }\n return obj;\n}\n\nexport function parseLlmYaml(\n content: string,\n options: LoadLlmConfigOptions = {}\n): unknown {\n const { substituteEnv: doSub = true } = options;\n const parsed = parseYamlContent<{ llm?: unknown; spec?: { llm?: unknown } }>(content, {\n substituteEnv: doSub,\n missingEnv: \"keep\",\n });\n const llm = parsed?.spec?.llm ?? parsed?.llm;\n if (llm == null) return undefined;\n return llm;\n}\n\nexport interface ModelsConfigResult {\n llm: unknown;\n vlm: unknown;\n embed: unknown;\n runtime: { check_connectivity?: boolean };\n}\n\n/**\n * Load the full model.yaml config, returning llm, vlm, embed, and runtime sections.\n */\nexport function loadModelsConfig(\n filePath: string,\n options: LoadLlmConfigOptions = {},\n): ModelsConfigResult | null {\n if (typeof filePath !== \"string\" || filePath.trim().length === 0) {\n throw new Error(\"agent-model: loadModelsConfig requires a non-empty file path\");\n }\n try {\n const parsed = loadYamlFileSync<{\n llm?: unknown;\n vlm?: unknown;\n embed?: unknown;\n runtime?: Record<string, unknown>;\n spec?: {\n llm?: unknown;\n vlm?: unknown;\n embed?: unknown;\n runtime?: Record<string, unknown>;\n };\n }>(filePath, {\n substituteEnv: options.substituteEnv !== false,\n missingEnv: \"keep\",\n cache: true,\n });\n if (parsed == null) return null;\n const source = parsed.spec ?? parsed;\n return {\n llm: source.llm ?? null,\n vlm: source.vlm ?? null,\n embed: source.embed ?? null,\n runtime: {\n check_connectivity:\n typeof source.runtime?.check_connectivity === \"boolean\"\n ? source.runtime.check_connectivity\n : undefined,\n },\n };\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n throw new Error(`agent-model: failed to parse config file ${filePath}: ${msg}`, { cause: e });\n }\n}\n\n/**\n * Load only the llm section from a YAML config file.\n * @deprecated Use loadModelsConfig() instead.\n */\nexport function loadLlmConfig(\n filePath: string,\n options: LoadLlmConfigOptions = {}\n): unknown | null {\n const result = loadModelsConfig(filePath, options);\n return result?.llm ?? null;\n}\n"],"mappings":"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","names":[]}
@@ -9,7 +9,7 @@ import {
9
9
  resolveLLMExtensionPackages,
10
10
  resolveLlmSectionWithNpm,
11
11
  resolveNpmProvider
12
- } from "./chunk-XSR4TAZ7.js";
12
+ } from "./chunk-HSU6XZOI.js";
13
13
  import {
14
14
  NPM_PROTOCOL_PREFIX,
15
15
  isNpmProviderSpec,
@@ -40,4 +40,4 @@ __export(extensions_exports, {
40
40
  export {
41
41
  extensions_exports
42
42
  };
43
- //# sourceMappingURL=chunk-V5QTINFH.js.map
43
+ //# sourceMappingURL=chunk-YOOYQBGK.js.map
@@ -202,4 +202,4 @@ export {
202
202
  parseEmbedSection,
203
203
  model_exports
204
204
  };
205
- //# sourceMappingURL=chunk-5YPJ43HW.js.map
205
+ //# sourceMappingURL=chunk-Z4E7LN4P.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/model/index.ts","../src/model/embed-parser.ts","../src/model/chat.ts","../src/model/embedding.ts","../src/model/hub.ts"],"sourcesContent":["/**\n * Model APIs (no LangChain dependency):\n * - LLM types and config parsing\n * - Chat completion and embedding HTTP APIs\n * - ModelHub (generate + embed)\n */\n\nexport type { LLMType, LLMConfig, AgentConfigLlmSection } from \"./types.js\";\nexport { parseLlmSection } from \"./llm-parser.js\";\nexport { parseEmbedSection } from \"./embed-parser.js\";\nexport {\n chatCompletionViaOpenAICompatibleApi,\n type ChatCompletionOptions,\n type ChatCompletionMessage,\n type ChatCompletionRequest,\n type ChatCompletionResult,\n} from \"./chat.js\";\nexport {\n embedViaOpenAICompatibleApi,\n type EmbeddingOptions,\n type EmbedRequest,\n type EmbedResult,\n} from \"./embedding.js\";\nexport {\n createModelHub,\n type CreateModelHubOptions,\n type ModelHub,\n type ChatGenerateRequest,\n type ChatGenerateResult,\n} from \"./hub.js\";\n","/**\n * Parse embed section from model.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 model.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","/**\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"],"mappings":";;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACuBO,SAAS,kBACd,SAC6C;AAC7C,QAAM,SAAS,gBAAgB,OAAO;AAEtC,aAAW,UAAU,OAAO,SAAS;AACnC,WAAO,OAAO;AAAA,EAChB;AACA,SAAO;AACT;;;AC3BA,IAAM,0BAA0B;AA0BhC,SAAS,eAAe,KAAsB;AAC5C,MAAI;AACF,UAAM,IAAI,IAAI,IAAI,GAAG;AACrB,UAAM,OAAO,EAAE,SAAS,YAAY;AACpC,WAAO,SAAS,eAAe,SAAS,eAAe,SAAS;AAAA,EAClE,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,iBAAiB,SAA0B;AAClD,MAAI,OAAO,YAAY,SAAU,QAAO;AACxC,MAAI,CAAC,MAAM,QAAQ,OAAO,EAAG,QAAO,OAAO,WAAW,EAAE;AACxD,QAAM,QAAkB,CAAC;AACzB,aAAW,KAAK,SAAS;AACvB,QAAI,OAAO,MAAM,SAAU,OAAM,KAAK,CAAC;AAAA,aAC9B,KAAK,OAAO,MAAM,YAAY,OAAQ,EAAyB,SAAS;AAC/E,YAAM,KAAM,EAAuB,IAAI;AAAA,EAC3C;AACA,SAAO,MAAM,KAAK,IAAI,EAAE,KAAK;AAC/B;AAMA,eAAsB,qCACpB,SACA,SAC+B;AAC/B,QAAM,UAAU,QAAQ,QAAQ,QAAQ,OAAO,EAAE;AACjD,QAAM,SAAS,QAAQ,QAAQ,KAAK;AACpC,QAAM,YAAY,QAAQ,aAAa;AACvC,QAAM,YACJ,OAAO,QAAQ,UAAU,YAAY,QAAQ,MAAM,KAAK,MAAM,KAC1D,QAAQ,MAAM,KAAK,IACnB,QAAQ,SAAS;AAEvB,MAAI,CAAC,UAAU,CAAC,eAAe,OAAO,GAAG;AACvC,UAAM,IAAI,MAAM,2DAA2D;AAAA,EAC7E;AAEA,QAAM,OAAgC;AAAA,IACpC,OAAO;AAAA,IACP,UAAU,QAAQ,SAAS,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,EAAE,QAAQ,EAAE;AAAA,IAC5E,aAAa,OAAO,QAAQ,gBAAgB,WAAW,QAAQ,cAAc;AAAA,EAC/E;AACA,MAAI,OAAO,QAAQ,cAAc,SAAU,MAAK,aAAa,QAAQ;AAErE,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,QAAQ,WAAW,MAAM,WAAW,MAAM,GAAG,SAAS;AAC5D,MAAI;AACF,UAAM,WAAW,MAAM,MAAM,GAAG,OAAO,qBAAqB;AAAA,MAC1D,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,GAAI,SAAS,EAAE,eAAe,UAAU,MAAM,GAAG,IAAI,CAAC;AAAA,MACxD;AAAA,MACA,MAAM,KAAK,UAAU,IAAI;AAAA,MACzB,QAAQ,WAAW;AAAA,IACrB,CAAC;AACD,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,OAAO,MAAM,SAAS,KAAK;AACjC,YAAM,IAAI,MAAM,6BAA6B,SAAS,MAAM,KAAK,KAAK,MAAM,GAAG,GAAG,CAAC,EAAE;AAAA,IACvF;AACA,UAAM,OAAQ,MAAM,SAAS,KAAK;AAIlC,UAAM,MACJ,KAAK,UAAU,CAAC,GAAG,SAAS,WAAW,KAAK,UAAU,CAAC,GAAG,QAAQ;AACpE,WAAO;AAAA,MACL,MAAM,iBAAiB,GAAG;AAAA,MAC1B,OAAO,KAAK,SAAS;AAAA,IACvB;AAAA,EACF,UAAE;AACA,iBAAa,KAAK;AAAA,EACpB;AACF;;;ACxGA,IAAM,+BAA+B;AAoBrC,SAASA,gBAAe,KAAsB;AAC5C,MAAI;AACF,UAAM,IAAI,IAAI,IAAI,GAAG;AACrB,UAAM,OAAO,EAAE,SAAS,YAAY;AACpC,WAAO,SAAS,eAAe,SAAS,eAAe,SAAS;AAAA,EAClE,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMA,eAAsB,4BACpB,SACA,OACsB;AACtB,QAAM,UAAU,QAAQ,QAAQ,QAAQ,OAAO,EAAE;AACjD,QAAM,SAAS,QAAQ,QAAQ,KAAK;AACpC,QAAM,YAAY,QAAQ,aAAa;AACvC,QAAM,YACJ,OAAO,MAAM,UAAU,YAAY,MAAM,MAAM,KAAK,MAAM,KACtD,MAAM,MAAM,KAAK,IACjB,QAAQ,SAAS;AAEvB,MAAI,CAAC,UAAU,CAACA,gBAAe,OAAO,GAAG;AACvC,UAAM,IAAI,MAAM,qDAAqD;AAAA,EACvE;AAEA,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,QAAQ,WAAW,MAAM,WAAW,MAAM,GAAG,SAAS;AAC5D,MAAI;AACF,UAAM,WAAW,MAAM,MAAM,GAAG,OAAO,eAAe;AAAA,MACpD,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,GAAI,SAAS,EAAE,eAAe,UAAU,MAAM,GAAG,IAAI,CAAC;AAAA,MACxD;AAAA,MACA,MAAM,KAAK,UAAU,EAAE,OAAO,WAAW,OAAO,MAAM,MAAM,CAAC;AAAA,MAC7D,QAAQ,WAAW;AAAA,IACrB,CAAC;AACD,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,OAAO,MAAM,SAAS,KAAK;AACjC,YAAM,IAAI,MAAM,uBAAuB,SAAS,MAAM,KAAK,KAAK,MAAM,GAAG,GAAG,CAAC,EAAE;AAAA,IACjF;AACA,UAAM,OAAQ,MAAM,SAAS,KAAK;AAIlC,UAAM,WAAW,KAAK,QAAQ,CAAC,GAC5B,MAAM,EACN,KAAK,CAAC,GAAG,OAAO,EAAE,SAAS,MAAM,EAAE,SAAS,EAAE,EAC9C,IAAI,CAAC,MAAM,EAAE,SAAS,EACtB,OAAO,CAAC,MAAqB,MAAM,QAAQ,CAAC,CAAC;AAChD,WAAO;AAAA,MACL;AAAA,MACA,YAAY,QAAQ,CAAC,GAAG;AAAA,MACxB,OAAO,KAAK,SAAS;AAAA,IACvB;AAAA,EACF,UAAE;AACA,iBAAa,KAAK;AAAA,EACpB;AACF;;;AC7EA,IAAM,0BAA0B;AAChC,IAAM,qBAAqB;AAC3B,IAAM,mBAAmB;AA4BzB,SAAS,oBAAoB,YAAuC;AAClE,QAAM,SAAS,gBAAgB,cAAc,IAAI;AACjD,QAAM,SACJ,OAAO,QAAQ,KAAK,CAAC,MAAiB,EAAE,OAAO,OAAO,SAAS,KAC/D,OAAO,QAAQ,CAAC,KAChB;AACF,SAAO;AACT;AAEO,SAAS,eAAe,UAAiC,CAAC,GAAa;AAC5E,QAAM,UAAU,oBAAoB,QAAQ,UAAU;AACtD,QAAM,kBACJ,QAAQ,oBACR,SAAS,WACT,kBACA,QAAQ,OAAO,EAAE;AACnB,QAAM,gBACJ,QAAQ,mBACR,SAAS,UACT,QAAQ,IAAI;AACd,QAAM,wBACJ,QAAQ,mBACP,SAAS,WAAW,OAAO,QAAQ,QAAQ,mBAAmB,WAC3D,QAAQ,QAAQ,iBAChB,WACJ,SAAS,SACT,QAAQ,IAAI,0BACZ;AACF,QAAM,mBACJ,SAAS,SACT,QAAQ,IAAI,gBACZ;AACF,QAAM,qBAAqB,QAAQ;AACnC,QAAM,gBAAgB,QAAQ;AAE9B,SAAO;AAAA,IACL,MAAM,SAAS,OAAyD;AACtE,YAAM,WAA8E,CAAC;AACrF,UAAI,OAAO,MAAM,iBAAiB,YAAY,MAAM,aAAa,KAAK,MAAM,IAAI;AAC9E,iBAAS,KAAK,EAAE,MAAM,UAAU,SAAS,MAAM,aAAa,KAAK,EAAE,CAAC;AAAA,MACtE;AACA,eAAS,KAAK,EAAE,MAAM,QAAQ,SAAS,MAAM,MAAM,CAAC;AACpD,YAAM,SAAS,MAAM;AAAA,QACnB;AAAA,UACE,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,WAAW;AAAA,QACb;AAAA,QACA;AAAA,UACE;AAAA,UACA,OAAO,MAAM;AAAA,UACb,aAAa,MAAM;AAAA,QACrB;AAAA,MACF;AACA,aAAO;AAAA,QACL,MAAM,OAAO;AAAA,QACb,OACE,OAAO,MAAM,UAAU,YAAY,MAAM,MAAM,KAAK,MAAM,KACtD,MAAM,QACN,OAAO,SAAS,SAAS;AAAA,MACjC;AAAA,IACF;AAAA,IACA,MAAM,MAAM,OAA2C;AACrD,YAAM,SAAS,MAAM;AAAA,QACnB;AAAA,UACE,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,WAAW;AAAA,QACb;AAAA,QACA,EAAE,OAAO,MAAM,OAAO,OAAO,MAAM,MAAM;AAAA,MAC3C;AACA,aAAO;AAAA,QACL,SAAS,OAAO;AAAA,QAChB,YAAY,OAAO;AAAA,QACnB,OAAO,OAAO;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AACF;","names":["isLocalBaseUrl"]}
package/dist/cli/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
- import "../chunk-JVLYAGWR.js";
3
- import "../chunk-FZKECZUY.js";
2
+ import "../chunk-NIFNTD6P.js";
3
+ import "../chunk-Y7POI745.js";
4
4
  import "../chunk-EPVJLBGC.js";
5
- import "../chunk-XSR4TAZ7.js";
6
- import "../chunk-K3JR2N4E.js";
7
- import "../chunk-CCGNXMFC.js";
8
- import "../chunk-SPDXNDDD.js";
5
+ import "../chunk-HSU6XZOI.js";
6
+ import "../chunk-4OLU43SH.js";
9
7
  import "../chunk-G7MKWPEI.js";
8
+ import "../chunk-SPDXNDDD.js";
9
+ import "../chunk-K3JR2N4E.js";
10
10
  import "../chunk-PZ5AY32C.js";
11
11
  //# sourceMappingURL=index.js.map
@@ -1,6 +1,8 @@
1
1
  export { parseLlmSection } from "./parser.js";
2
2
  export { loadLlmConfig, parseLlmYaml, substituteEnv } from "./loader.js";
3
3
  export { loadYamlConfig } from "./yaml.js";
4
+ export { normalizeAgentModelConfigRef } from "./ref.js";
4
5
  export { loadYamlFile, loadYamlFileSync, parseYamlContent, clearYamlFileCache, type LoadYamlOptions, type YamlEnvOptions, } from "./yaml-utils.js";
5
6
  export type { LoadLlmConfigOptions } from "./loader.js";
7
+ export type { AgentModelConfigRef } from "./ref.js";
6
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EAClB,KAAK,eAAe,EACpB,KAAK,cAAc,GACpB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,4BAA4B,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EAClB,KAAK,eAAe,EACpB,KAAK,cAAc,GACpB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import {
2
- loadYamlConfig
3
- } from "../chunk-VBXTOU4S.js";
2
+ loadYamlConfig,
3
+ normalizeAgentModelConfigRef
4
+ } from "../chunk-WKUSX6VQ.js";
4
5
  import {
5
6
  clearYamlFileCache,
6
7
  loadLlmConfig,
@@ -9,7 +10,7 @@ import {
9
10
  parseLlmYaml,
10
11
  parseYamlContent,
11
12
  substituteEnv
12
- } from "../chunk-FZKECZUY.js";
13
+ } from "../chunk-Y7POI745.js";
13
14
  import {
14
15
  parseLlmSection
15
16
  } from "../chunk-SPDXNDDD.js";
@@ -20,6 +21,7 @@ export {
20
21
  loadYamlConfig,
21
22
  loadYamlFile,
22
23
  loadYamlFileSync,
24
+ normalizeAgentModelConfigRef,
23
25
  parseLlmSection,
24
26
  parseLlmYaml,
25
27
  parseYamlContent,
@@ -12,7 +12,7 @@ export interface ModelsConfigResult {
12
12
  };
13
13
  }
14
14
  /**
15
- * Load the full models.yaml config, returning llm, vlm, embed, and runtime sections.
15
+ * Load the full model.yaml config, returning llm, vlm, embed, and runtime sections.
16
16
  */
17
17
  export declare function loadModelsConfig(filePath: string, options?: LoadLlmConfigOptions): ModelsConfigResult | null;
18
18
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,oBAAoB;IACnC,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAanD;AAED,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAST;AAED,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE;QAAE,kBAAkB,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAC3C;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,oBAAyB,GACjC,kBAAkB,GAAG,IAAI,CA+B3B;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,oBAAyB,GACjC,OAAO,GAAG,IAAI,CAGhB"}
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,oBAAoB;IACnC,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAanD;AAED,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAST;AAED,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE;QAAE,kBAAkB,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAC3C;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,oBAAyB,GACjC,kBAAkB,GAAG,IAAI,CAsC3B;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,oBAAyB,GACjC,OAAO,GAAG,IAAI,CAGhB"}
@@ -0,0 +1,7 @@
1
+ /** Agent-level reference to models config file. */
2
+ export interface AgentModelConfigRef {
3
+ ref?: string;
4
+ }
5
+ /** Normalize unknown value to AgentModelConfigRef. */
6
+ export declare function normalizeAgentModelConfigRef(raw: unknown): Partial<AgentModelConfigRef>;
7
+ //# sourceMappingURL=ref.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ref.d.ts","sourceRoot":"","sources":["../../src/config/ref.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,MAAM,WAAW,mBAAmB;IAClC,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAMD,sDAAsD;AACtD,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAMvF"}
@@ -1,4 +1,4 @@
1
- import "../chunk-V5QTINFH.js";
1
+ import "../chunk-YOOYQBGK.js";
2
2
  import {
3
3
  createChatModelWithNpm,
4
4
  discoverLLMExtensions,
@@ -10,15 +10,15 @@ import {
10
10
  resolveLLMExtensionPackages,
11
11
  resolveLlmSectionWithNpm,
12
12
  resolveNpmProvider
13
- } from "../chunk-XSR4TAZ7.js";
13
+ } from "../chunk-HSU6XZOI.js";
14
+ import "../chunk-4OLU43SH.js";
15
+ import "../chunk-G7MKWPEI.js";
16
+ import "../chunk-SPDXNDDD.js";
14
17
  import {
15
18
  NPM_PROTOCOL_PREFIX,
16
19
  isNpmProviderSpec,
17
20
  parseNpmProviderSpec
18
21
  } from "../chunk-K3JR2N4E.js";
19
- import "../chunk-CCGNXMFC.js";
20
- import "../chunk-SPDXNDDD.js";
21
- import "../chunk-G7MKWPEI.js";
22
22
  import "../chunk-PZ5AY32C.js";
23
23
  export {
24
24
  NPM_PROTOCOL_PREFIX,
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Minimal public API for @easynet/agent-model.
3
- * Goal: create a chat model from `models.yaml` with the smallest possible surface.
3
+ * Goal: create a chat model from `model.yaml` with the smallest possible surface.
4
4
  */
5
5
  export { createAgentLlm } from "./api/create-agent-llm.js";
6
6
  export type { CreateAgentLlmOptions } from "./api/create-agent-llm.js";
@@ -10,6 +10,8 @@ export { getDefaultVlmConfig } from "./api/get-default-vlm-config.js";
10
10
  export type { GetDefaultVlmConfigOptions } from "./api/get-default-vlm-config.js";
11
11
  export { createEmbedFnFromModelsConfig } from "./api/create-embed-fn.js";
12
12
  export type { EmbedFn } from "./api/create-embed-fn.js";
13
+ export type { AgentModelConfigRef } from "./config/index.js";
14
+ export { normalizeAgentModelConfigRef } from "./config/index.js";
13
15
  export { createChatModelFromLlmConfig } from "./langchain/index.js";
14
16
  export type { CreateChatModelOptions } from "./langchain/index.js";
15
17
  export { applyToolChoiceAuto } from "./langchain/index.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,YAAY,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,YAAY,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAClF,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,YAAY,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAClF,OAAO,EAAE,6BAA6B,EAAE,MAAM,0BAA0B,CAAC;AACzE,YAAY,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAGxD,OAAO,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AACpE,YAAY,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAG3D,OAAO,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC1F,YAAY,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAEjE,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,6BAA6B,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,4BAA4B,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AACzF,OAAO,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC1F,OAAO,KAAK,SAAS,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,YAAY,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,WAAW,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,aAAa,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,eAAe,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,MAAM,MAAM,gBAAgB,CAAC;AACzC,OAAO,KAAK,MAAM,MAAM,gBAAgB,CAAC;AAEzC;;GAEG;AACH,eAAO,MAAM,QAAQ;;;;;;;;;CASX,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,WAAW;;;;;;;;;CASd,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,YAAY,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,YAAY,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAClF,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,YAAY,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAClF,OAAO,EAAE,6BAA6B,EAAE,MAAM,0BAA0B,CAAC;AACzE,YAAY,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACxD,YAAY,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,4BAA4B,EAAE,MAAM,mBAAmB,CAAC;AAGjE,OAAO,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AACpE,YAAY,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAG3D,OAAO,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC1F,YAAY,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAEjE,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,6BAA6B,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,4BAA4B,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AACzF,OAAO,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC1F,OAAO,KAAK,SAAS,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,YAAY,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,WAAW,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,aAAa,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,eAAe,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,MAAM,MAAM,gBAAgB,CAAC;AACzC,OAAO,KAAK,MAAM,MAAM,gBAAgB,CAAC;AAEzC;;GAEG;AACH,eAAO,MAAM,QAAQ;;;;;;;;;CASX,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,WAAW;;;;;;;;;CASd,CAAC"}
package/dist/index.js CHANGED
@@ -1,52 +1,53 @@
1
+ import {
2
+ registry_exports
3
+ } from "./chunk-HCU4AWIV.js";
1
4
  import {
2
5
  cli_exports,
3
6
  createAgentLlm
4
- } from "./chunk-JVLYAGWR.js";
7
+ } from "./chunk-NIFNTD6P.js";
5
8
  import {
6
- config_exports
7
- } from "./chunk-VBXTOU4S.js";
9
+ config_exports,
10
+ normalizeAgentModelConfigRef
11
+ } from "./chunk-WKUSX6VQ.js";
8
12
  import {
9
13
  loadLlmConfig,
10
14
  loadModelsConfig
11
- } from "./chunk-FZKECZUY.js";
15
+ } from "./chunk-Y7POI745.js";
12
16
  import {
13
17
  connectivity_exports
14
18
  } from "./chunk-EPVJLBGC.js";
15
19
  import {
16
20
  extensions_exports
17
- } from "./chunk-V5QTINFH.js";
21
+ } from "./chunk-YOOYQBGK.js";
18
22
  import {
19
23
  resolveLlmSectionWithNpm
20
- } from "./chunk-XSR4TAZ7.js";
21
- import {
22
- npm_exports
23
- } from "./chunk-K3JR2N4E.js";
24
+ } from "./chunk-HSU6XZOI.js";
24
25
  import {
25
26
  applyToolChoiceAuto,
26
27
  createChatModelFromLlmConfig,
27
28
  langchain_exports
28
- } from "./chunk-CCGNXMFC.js";
29
+ } from "./chunk-4OLU43SH.js";
30
+ import {
31
+ getChatModelFactory,
32
+ registerChatModelProvider
33
+ } from "./chunk-G7MKWPEI.js";
29
34
  import {
30
35
  createModelHub,
31
36
  model_exports,
32
37
  parseEmbedSection
33
- } from "./chunk-5YPJ43HW.js";
38
+ } from "./chunk-Z4E7LN4P.js";
34
39
  import {
35
40
  parseLlmSection
36
41
  } from "./chunk-SPDXNDDD.js";
37
42
  import {
38
- registry_exports
39
- } from "./chunk-HCU4AWIV.js";
40
- import {
41
- getChatModelFactory,
42
- registerChatModelProvider
43
- } from "./chunk-G7MKWPEI.js";
43
+ npm_exports
44
+ } from "./chunk-K3JR2N4E.js";
44
45
  import "./chunk-PZ5AY32C.js";
45
46
 
46
47
  // src/api/get-default-llm-config.ts
47
48
  import { join } from "path";
48
49
  async function getDefaultLlmConfig(options = {}) {
49
- const configPath = options.configPath ?? join(process.cwd(), "models.yaml");
50
+ const configPath = options.configPath ?? join(process.cwd(), "model.yaml");
50
51
  const llmSection = loadLlmConfig(configPath);
51
52
  if (llmSection == null) return null;
52
53
  const resolved = await resolveLlmSectionWithNpm(llmSection, {
@@ -61,7 +62,7 @@ async function getDefaultLlmConfig(options = {}) {
61
62
  // src/api/get-default-vlm-config.ts
62
63
  import { join as join2 } from "path";
63
64
  async function getDefaultVlmConfig(options = {}) {
64
- const configPath = options.configPath ?? join2(process.cwd(), "models.yaml");
65
+ const configPath = options.configPath ?? join2(process.cwd(), "model.yaml");
65
66
  const modelsConfig = loadModelsConfig(configPath);
66
67
  if (modelsConfig == null) return null;
67
68
  const sourceSection = modelsConfig.vlm ?? modelsConfig.llm;
@@ -127,6 +128,7 @@ export {
127
128
  getDefaultLlmConfig,
128
129
  getDefaultVlmConfig,
129
130
  modelApi,
131
+ normalizeAgentModelConfigRef,
130
132
  platformApi,
131
133
  registerChatModelProvider
132
134
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/api/get-default-llm-config.ts","../src/api/get-default-vlm-config.ts","../src/api/create-embed-fn.ts","../src/index.ts"],"sourcesContent":["/**\n * Load models.yaml, resolve npm providers, and return the default LLMConfig.\n * For use by CLIs (e.g. wallee-llm) that need config without creating a model.\n */\n\nimport { join } from \"node:path\";\nimport { loadLlmConfig } from \"../config/loader.js\";\nimport { parseLlmSection } from \"../config/parser.js\";\nimport { resolveLlmSectionWithNpm } from \"../extensions/npm-protocol.js\";\nimport type { LLMConfig } from \"../types.js\";\n\nexport interface GetDefaultLlmConfigOptions {\n /** Path to models.yaml. Default: process.cwd() + \"/models.yaml\" */\n configPath?: string;\n /** Install npm provider packages if missing. Default true. */\n installNpmIfMissing?: boolean;\n}\n\n/**\n * Returns the default LLM config from models.yaml (after resolving npm: providers), or null if no config file.\n */\nexport async function getDefaultLlmConfig(\n options: GetDefaultLlmConfigOptions = {}\n): Promise<LLMConfig | null> {\n const configPath = options.configPath ?? join(process.cwd(), \"models.yaml\");\n const llmSection = loadLlmConfig(configPath);\n if (llmSection == null) return null;\n\n const resolved = await resolveLlmSectionWithNpm(llmSection, {\n installNpmIfMissing: options.installNpmIfMissing !== false,\n cwd: process.cwd(),\n });\n\n const { defaultId, configs } = parseLlmSection(resolved);\n const defaultConfig = configs.find((c: LLMConfig) => c.id === defaultId) ?? configs[0] ?? null;\n return defaultConfig;\n}\n","/**\n * Load models.yaml, resolve npm providers, and return a default VLM (type=image) config.\n */\n\nimport { join } from \"node:path\";\nimport { loadModelsConfig } from \"../config/loader.js\";\nimport { parseLlmSection } from \"../config/parser.js\";\nimport { resolveLlmSectionWithNpm } from \"../extensions/npm-protocol.js\";\nimport type { LLMConfig } from \"../types.js\";\n\nexport interface GetDefaultVlmConfigOptions {\n /** Path to models.yaml. Default: process.cwd() + \"/models.yaml\" */\n configPath?: string;\n /** Install npm provider packages if missing. Default true. */\n installNpmIfMissing?: boolean;\n}\n\n/**\n * Returns the default VLM config (type=image) from models.yaml, or null if not configured.\n */\nexport async function getDefaultVlmConfig(\n options: GetDefaultVlmConfigOptions = {},\n): Promise<LLMConfig | null> {\n const configPath = options.configPath ?? join(process.cwd(), \"models.yaml\");\n const modelsConfig = loadModelsConfig(configPath);\n if (modelsConfig == null) return null;\n\n // Prefer top-level `vlm:`. Fallback to `llm:` section with type=image entries.\n const sourceSection = modelsConfig.vlm ?? modelsConfig.llm;\n if (sourceSection == null) return null;\n\n const resolved = await resolveLlmSectionWithNpm(sourceSection, {\n installNpmIfMissing: options.installNpmIfMissing !== false,\n cwd: process.cwd(),\n });\n\n const { defaultId, configs } = parseLlmSection(resolved);\n const imageConfigs = configs.filter((c: LLMConfig) => c.type === \"image\");\n if (imageConfigs.length === 0) return null;\n\n const defaultConfig =\n imageConfigs.find((c: LLMConfig) => c.id === defaultId) ??\n imageConfigs[0] ??\n null;\n return defaultConfig;\n}\n","/**\n * Create an EmbedFn from the embed section of models.yaml.\n */\nimport { createModelHub } from \"../model/hub.js\";\nimport { parseEmbedSection } from \"../model/embed-parser.js\";\nimport { loadModelsConfig } from \"../config/loader.js\";\n\nexport type EmbedFn = (input: string | string[]) => Promise<number[][]>;\n\n/**\n * Load models.yaml and build an EmbedFn from the `embed:` section.\n * Returns undefined if no embed section is configured.\n *\n * @param configPath - Path to models.yaml\n * @param embedId - Which embed instance to use (defaults to the `default:` key)\n */\nexport function createEmbedFnFromModelsConfig(\n configPath: string,\n embedId?: string,\n): EmbedFn | undefined {\n const config = loadModelsConfig(configPath);\n if (!config?.embed) return undefined;\n\n const parsed = parseEmbedSection(config.embed);\n if (parsed.configs.length === 0) return undefined;\n\n const id = embedId ?? parsed.defaultId;\n const embedConfig =\n parsed.configs.find((c) => c.id === id) ?? parsed.configs[0];\n if (!embedConfig) return undefined;\n\n const hub = createModelHub({\n embeddingBaseURL: embedConfig.baseURL,\n embeddingModel: embedConfig.model,\n embeddingApiKey: embedConfig.apiKey,\n });\n\n return async (input: string | string[]) => {\n const result = await hub.embed({ input });\n return result.vectors;\n };\n}\n","/**\n * Minimal public API for @easynet/agent-model.\n * Goal: create a chat model from `models.yaml` with the smallest possible surface.\n */\n\n// Main high-level APIs\nexport { createAgentLlm } from \"./api/create-agent-llm.js\";\nexport type { CreateAgentLlmOptions } from \"./api/create-agent-llm.js\";\nexport { getDefaultLlmConfig } from \"./api/get-default-llm-config.js\";\nexport type { GetDefaultLlmConfigOptions } from \"./api/get-default-llm-config.js\";\nexport { getDefaultVlmConfig } from \"./api/get-default-vlm-config.js\";\nexport type { GetDefaultVlmConfigOptions } from \"./api/get-default-vlm-config.js\";\nexport { createEmbedFnFromModelsConfig } from \"./api/create-embed-fn.js\";\nexport type { EmbedFn } from \"./api/create-embed-fn.js\";\n\n// Common runtime helper (used by agent-runtime)\nexport { createChatModelFromLlmConfig } from \"./langchain/index.js\";\nexport type { CreateChatModelOptions } from \"./langchain/index.js\";\nexport { applyToolChoiceAuto } from \"./langchain/index.js\";\n\n// Provider extension registration\nexport { registerChatModelProvider, getChatModelFactory } from \"./registry/chat-model.js\";\nexport type { ChatModelFactory } from \"./registry/chat-model.js\";\n\nimport { createAgentLlm } from \"./api/create-agent-llm.js\";\nimport { getDefaultLlmConfig } from \"./api/get-default-llm-config.js\";\nimport { getDefaultVlmConfig } from \"./api/get-default-vlm-config.js\";\nimport { createEmbedFnFromModelsConfig } from \"./api/create-embed-fn.js\";\nimport { createChatModelFromLlmConfig, applyToolChoiceAuto } from \"./langchain/index.js\";\nimport { registerChatModelProvider, getChatModelFactory } from \"./registry/chat-model.js\";\nimport * as ConfigApi from \"./config/index.js\";\nimport * as LangChainApi from \"./langchain/index.js\";\nimport * as ModelApi from \"./model/index.js\";\nimport * as RegistryApi from \"./registry/index.js\";\nimport * as ExtensionsApi from \"./extensions/index.js\";\nimport * as ConnectivityApi from \"./connectivity/index.js\";\nimport * as NpmApi from \"./npm/index.js\";\nimport * as CliApi from \"./cli/index.js\";\n\n/**\n * Facade: high-frequency model APIs with a single import.\n */\nexport const modelApi = {\n createAgentLlm,\n getDefaultLlmConfig,\n getDefaultVlmConfig,\n createEmbedFnFromModelsConfig,\n createChatModelFromLlmConfig,\n applyToolChoiceAuto,\n registerChatModelProvider,\n getChatModelFactory,\n} as const;\n\n/**\n * Facade: grouped subpath modules (config/langchain/model/registry/extensions/connectivity/npm/cli).\n */\nexport const platformApi = {\n config: ConfigApi,\n langchain: LangChainApi,\n model: ModelApi,\n registry: RegistryApi,\n extensions: ExtensionsApi,\n connectivity: ConnectivityApi,\n npm: NpmApi,\n cli: CliApi,\n} as const;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,SAAS,YAAY;AAgBrB,eAAsB,oBACpB,UAAsC,CAAC,GACZ;AAC3B,QAAM,aAAa,QAAQ,cAAc,KAAK,QAAQ,IAAI,GAAG,aAAa;AAC1E,QAAM,aAAa,cAAc,UAAU;AAC3C,MAAI,cAAc,KAAM,QAAO;AAE/B,QAAM,WAAW,MAAM,yBAAyB,YAAY;AAAA,IAC1D,qBAAqB,QAAQ,wBAAwB;AAAA,IACrD,KAAK,QAAQ,IAAI;AAAA,EACnB,CAAC;AAED,QAAM,EAAE,WAAW,QAAQ,IAAI,gBAAgB,QAAQ;AACvD,QAAM,gBAAgB,QAAQ,KAAK,CAAC,MAAiB,EAAE,OAAO,SAAS,KAAK,QAAQ,CAAC,KAAK;AAC1F,SAAO;AACT;;;AChCA,SAAS,QAAAA,aAAY;AAgBrB,eAAsB,oBACpB,UAAsC,CAAC,GACZ;AAC3B,QAAM,aAAa,QAAQ,cAAcC,MAAK,QAAQ,IAAI,GAAG,aAAa;AAC1E,QAAM,eAAe,iBAAiB,UAAU;AAChD,MAAI,gBAAgB,KAAM,QAAO;AAGjC,QAAM,gBAAgB,aAAa,OAAO,aAAa;AACvD,MAAI,iBAAiB,KAAM,QAAO;AAElC,QAAM,WAAW,MAAM,yBAAyB,eAAe;AAAA,IAC7D,qBAAqB,QAAQ,wBAAwB;AAAA,IACrD,KAAK,QAAQ,IAAI;AAAA,EACnB,CAAC;AAED,QAAM,EAAE,WAAW,QAAQ,IAAI,gBAAgB,QAAQ;AACvD,QAAM,eAAe,QAAQ,OAAO,CAAC,MAAiB,EAAE,SAAS,OAAO;AACxE,MAAI,aAAa,WAAW,EAAG,QAAO;AAEtC,QAAM,gBACJ,aAAa,KAAK,CAAC,MAAiB,EAAE,OAAO,SAAS,KACtD,aAAa,CAAC,KACd;AACF,SAAO;AACT;;;AC7BO,SAAS,8BACd,YACA,SACqB;AACrB,QAAM,SAAS,iBAAiB,UAAU;AAC1C,MAAI,CAAC,QAAQ,MAAO,QAAO;AAE3B,QAAM,SAAS,kBAAkB,OAAO,KAAK;AAC7C,MAAI,OAAO,QAAQ,WAAW,EAAG,QAAO;AAExC,QAAM,KAAK,WAAW,OAAO;AAC7B,QAAM,cACJ,OAAO,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,OAAO,QAAQ,CAAC;AAC7D,MAAI,CAAC,YAAa,QAAO;AAEzB,QAAM,MAAM,eAAe;AAAA,IACzB,kBAAkB,YAAY;AAAA,IAC9B,gBAAgB,YAAY;AAAA,IAC5B,iBAAiB,YAAY;AAAA,EAC/B,CAAC;AAED,SAAO,OAAO,UAA6B;AACzC,UAAM,SAAS,MAAM,IAAI,MAAM,EAAE,MAAM,CAAC;AACxC,WAAO,OAAO;AAAA,EAChB;AACF;;;ACCO,IAAM,WAAW;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAKO,IAAM,cAAc;AAAA,EACzB,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,OAAO;AAAA,EACP,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,KAAK;AAAA,EACL,KAAK;AACP;","names":["join","join"]}
1
+ {"version":3,"sources":["../src/api/get-default-llm-config.ts","../src/api/get-default-vlm-config.ts","../src/api/create-embed-fn.ts","../src/index.ts"],"sourcesContent":["/**\n * Load model.yaml, resolve npm providers, and return the default LLMConfig.\n * For use by CLIs (e.g. wallee-llm) that need config without creating a model.\n */\n\nimport { join } from \"node:path\";\nimport { loadLlmConfig } from \"../config/loader.js\";\nimport { parseLlmSection } from \"../config/parser.js\";\nimport { resolveLlmSectionWithNpm } from \"../extensions/npm-protocol.js\";\nimport type { LLMConfig } from \"../types.js\";\n\nexport interface GetDefaultLlmConfigOptions {\n /** Path to model.yaml. Default: process.cwd() + \"/model.yaml\" */\n configPath?: string;\n /** Install npm provider packages if missing. Default true. */\n installNpmIfMissing?: boolean;\n}\n\n/**\n * Returns the default LLM config from model.yaml (after resolving npm: providers), or null if no config file.\n */\nexport async function getDefaultLlmConfig(\n options: GetDefaultLlmConfigOptions = {}\n): Promise<LLMConfig | null> {\n const configPath = options.configPath ?? join(process.cwd(), \"model.yaml\");\n const llmSection = loadLlmConfig(configPath);\n if (llmSection == null) return null;\n\n const resolved = await resolveLlmSectionWithNpm(llmSection, {\n installNpmIfMissing: options.installNpmIfMissing !== false,\n cwd: process.cwd(),\n });\n\n const { defaultId, configs } = parseLlmSection(resolved);\n const defaultConfig = configs.find((c: LLMConfig) => c.id === defaultId) ?? configs[0] ?? null;\n return defaultConfig;\n}\n","/**\n * Load model.yaml, resolve npm providers, and return a default VLM (type=image) config.\n */\n\nimport { join } from \"node:path\";\nimport { loadModelsConfig } from \"../config/loader.js\";\nimport { parseLlmSection } from \"../config/parser.js\";\nimport { resolveLlmSectionWithNpm } from \"../extensions/npm-protocol.js\";\nimport type { LLMConfig } from \"../types.js\";\n\nexport interface GetDefaultVlmConfigOptions {\n /** Path to model.yaml. Default: process.cwd() + \"/model.yaml\" */\n configPath?: string;\n /** Install npm provider packages if missing. Default true. */\n installNpmIfMissing?: boolean;\n}\n\n/**\n * Returns the default VLM config (type=image) from model.yaml, or null if not configured.\n */\nexport async function getDefaultVlmConfig(\n options: GetDefaultVlmConfigOptions = {},\n): Promise<LLMConfig | null> {\n const configPath = options.configPath ?? join(process.cwd(), \"model.yaml\");\n const modelsConfig = loadModelsConfig(configPath);\n if (modelsConfig == null) return null;\n\n // Prefer top-level `vlm:`. Fallback to `llm:` section with type=image entries.\n const sourceSection = modelsConfig.vlm ?? modelsConfig.llm;\n if (sourceSection == null) return null;\n\n const resolved = await resolveLlmSectionWithNpm(sourceSection, {\n installNpmIfMissing: options.installNpmIfMissing !== false,\n cwd: process.cwd(),\n });\n\n const { defaultId, configs } = parseLlmSection(resolved);\n const imageConfigs = configs.filter((c: LLMConfig) => c.type === \"image\");\n if (imageConfigs.length === 0) return null;\n\n const defaultConfig =\n imageConfigs.find((c: LLMConfig) => c.id === defaultId) ??\n imageConfigs[0] ??\n null;\n return defaultConfig;\n}\n","/**\n * Create an EmbedFn from the embed section of model.yaml.\n */\nimport { createModelHub } from \"../model/hub.js\";\nimport { parseEmbedSection } from \"../model/embed-parser.js\";\nimport { loadModelsConfig } from \"../config/loader.js\";\n\nexport type EmbedFn = (input: string | string[]) => Promise<number[][]>;\n\n/**\n * Load model.yaml and build an EmbedFn from the `embed:` section.\n * Returns undefined if no embed section is configured.\n *\n * @param configPath - Path to model.yaml\n * @param embedId - Which embed instance to use (defaults to the `default:` key)\n */\nexport function createEmbedFnFromModelsConfig(\n configPath: string,\n embedId?: string,\n): EmbedFn | undefined {\n const config = loadModelsConfig(configPath);\n if (!config?.embed) return undefined;\n\n const parsed = parseEmbedSection(config.embed);\n if (parsed.configs.length === 0) return undefined;\n\n const id = embedId ?? parsed.defaultId;\n const embedConfig =\n parsed.configs.find((c) => c.id === id) ?? parsed.configs[0];\n if (!embedConfig) return undefined;\n\n const hub = createModelHub({\n embeddingBaseURL: embedConfig.baseURL,\n embeddingModel: embedConfig.model,\n embeddingApiKey: embedConfig.apiKey,\n });\n\n return async (input: string | string[]) => {\n const result = await hub.embed({ input });\n return result.vectors;\n };\n}\n","/**\n * Minimal public API for @easynet/agent-model.\n * Goal: create a chat model from `model.yaml` with the smallest possible surface.\n */\n\n// Main high-level APIs\nexport { createAgentLlm } from \"./api/create-agent-llm.js\";\nexport type { CreateAgentLlmOptions } from \"./api/create-agent-llm.js\";\nexport { getDefaultLlmConfig } from \"./api/get-default-llm-config.js\";\nexport type { GetDefaultLlmConfigOptions } from \"./api/get-default-llm-config.js\";\nexport { getDefaultVlmConfig } from \"./api/get-default-vlm-config.js\";\nexport type { GetDefaultVlmConfigOptions } from \"./api/get-default-vlm-config.js\";\nexport { createEmbedFnFromModelsConfig } from \"./api/create-embed-fn.js\";\nexport type { EmbedFn } from \"./api/create-embed-fn.js\";\nexport type { AgentModelConfigRef } from \"./config/index.js\";\nexport { normalizeAgentModelConfigRef } from \"./config/index.js\";\n\n// Common runtime helper (used by agent-runtime)\nexport { createChatModelFromLlmConfig } from \"./langchain/index.js\";\nexport type { CreateChatModelOptions } from \"./langchain/index.js\";\nexport { applyToolChoiceAuto } from \"./langchain/index.js\";\n\n// Provider extension registration\nexport { registerChatModelProvider, getChatModelFactory } from \"./registry/chat-model.js\";\nexport type { ChatModelFactory } from \"./registry/chat-model.js\";\n\nimport { createAgentLlm } from \"./api/create-agent-llm.js\";\nimport { getDefaultLlmConfig } from \"./api/get-default-llm-config.js\";\nimport { getDefaultVlmConfig } from \"./api/get-default-vlm-config.js\";\nimport { createEmbedFnFromModelsConfig } from \"./api/create-embed-fn.js\";\nimport { createChatModelFromLlmConfig, applyToolChoiceAuto } from \"./langchain/index.js\";\nimport { registerChatModelProvider, getChatModelFactory } from \"./registry/chat-model.js\";\nimport * as ConfigApi from \"./config/index.js\";\nimport * as LangChainApi from \"./langchain/index.js\";\nimport * as ModelApi from \"./model/index.js\";\nimport * as RegistryApi from \"./registry/index.js\";\nimport * as ExtensionsApi from \"./extensions/index.js\";\nimport * as ConnectivityApi from \"./connectivity/index.js\";\nimport * as NpmApi from \"./npm/index.js\";\nimport * as CliApi from \"./cli/index.js\";\n\n/**\n * Facade: high-frequency model APIs with a single import.\n */\nexport const modelApi = {\n createAgentLlm,\n getDefaultLlmConfig,\n getDefaultVlmConfig,\n createEmbedFnFromModelsConfig,\n createChatModelFromLlmConfig,\n applyToolChoiceAuto,\n registerChatModelProvider,\n getChatModelFactory,\n} as const;\n\n/**\n * Facade: grouped subpath modules (config/langchain/model/registry/extensions/connectivity/npm/cli).\n */\nexport const platformApi = {\n config: ConfigApi,\n langchain: LangChainApi,\n model: ModelApi,\n registry: RegistryApi,\n extensions: ExtensionsApi,\n connectivity: ConnectivityApi,\n npm: NpmApi,\n cli: CliApi,\n} as const;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,SAAS,YAAY;AAgBrB,eAAsB,oBACpB,UAAsC,CAAC,GACZ;AAC3B,QAAM,aAAa,QAAQ,cAAc,KAAK,QAAQ,IAAI,GAAG,YAAY;AACzE,QAAM,aAAa,cAAc,UAAU;AAC3C,MAAI,cAAc,KAAM,QAAO;AAE/B,QAAM,WAAW,MAAM,yBAAyB,YAAY;AAAA,IAC1D,qBAAqB,QAAQ,wBAAwB;AAAA,IACrD,KAAK,QAAQ,IAAI;AAAA,EACnB,CAAC;AAED,QAAM,EAAE,WAAW,QAAQ,IAAI,gBAAgB,QAAQ;AACvD,QAAM,gBAAgB,QAAQ,KAAK,CAAC,MAAiB,EAAE,OAAO,SAAS,KAAK,QAAQ,CAAC,KAAK;AAC1F,SAAO;AACT;;;AChCA,SAAS,QAAAA,aAAY;AAgBrB,eAAsB,oBACpB,UAAsC,CAAC,GACZ;AAC3B,QAAM,aAAa,QAAQ,cAAcC,MAAK,QAAQ,IAAI,GAAG,YAAY;AACzE,QAAM,eAAe,iBAAiB,UAAU;AAChD,MAAI,gBAAgB,KAAM,QAAO;AAGjC,QAAM,gBAAgB,aAAa,OAAO,aAAa;AACvD,MAAI,iBAAiB,KAAM,QAAO;AAElC,QAAM,WAAW,MAAM,yBAAyB,eAAe;AAAA,IAC7D,qBAAqB,QAAQ,wBAAwB;AAAA,IACrD,KAAK,QAAQ,IAAI;AAAA,EACnB,CAAC;AAED,QAAM,EAAE,WAAW,QAAQ,IAAI,gBAAgB,QAAQ;AACvD,QAAM,eAAe,QAAQ,OAAO,CAAC,MAAiB,EAAE,SAAS,OAAO;AACxE,MAAI,aAAa,WAAW,EAAG,QAAO;AAEtC,QAAM,gBACJ,aAAa,KAAK,CAAC,MAAiB,EAAE,OAAO,SAAS,KACtD,aAAa,CAAC,KACd;AACF,SAAO;AACT;;;AC7BO,SAAS,8BACd,YACA,SACqB;AACrB,QAAM,SAAS,iBAAiB,UAAU;AAC1C,MAAI,CAAC,QAAQ,MAAO,QAAO;AAE3B,QAAM,SAAS,kBAAkB,OAAO,KAAK;AAC7C,MAAI,OAAO,QAAQ,WAAW,EAAG,QAAO;AAExC,QAAM,KAAK,WAAW,OAAO;AAC7B,QAAM,cACJ,OAAO,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,OAAO,QAAQ,CAAC;AAC7D,MAAI,CAAC,YAAa,QAAO;AAEzB,QAAM,MAAM,eAAe;AAAA,IACzB,kBAAkB,YAAY;AAAA,IAC9B,gBAAgB,YAAY;AAAA,IAC5B,iBAAiB,YAAY;AAAA,EAC/B,CAAC;AAED,SAAO,OAAO,UAA6B;AACzC,UAAM,SAAS,MAAM,IAAI,MAAM,EAAE,MAAM,CAAC;AACxC,WAAO,OAAO;AAAA,EAChB;AACF;;;ACGO,IAAM,WAAW;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAKO,IAAM,cAAc;AAAA,EACzB,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,OAAO;AAAA,EACP,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,KAAK;AAAA,EACL,KAAK;AACP;","names":["join","join"]}
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  applyToolChoiceAuto,
3
3
  createChatModelFromLlmConfig
4
- } from "../chunk-CCGNXMFC.js";
5
- import "../chunk-SPDXNDDD.js";
4
+ } from "../chunk-4OLU43SH.js";
6
5
  import "../chunk-G7MKWPEI.js";
6
+ import "../chunk-SPDXNDDD.js";
7
7
  import "../chunk-PZ5AY32C.js";
8
8
  export {
9
9
  applyToolChoiceAuto,
@@ -1,10 +1,10 @@
1
1
  /**
2
- * Parse embed section from models.yaml into normalized LLMConfig[] with type "embed".
2
+ * Parse embed section from model.yaml into normalized LLMConfig[] with type "embed".
3
3
  * Reuses parseLlmSection internally since the config shape is identical.
4
4
  */
5
5
  import type { LLMConfig } from "./types.js";
6
6
  /**
7
- * Parse an `embed:` section from models.yaml.
7
+ * Parse an `embed:` section from model.yaml.
8
8
  * Accepts the same flat-entry, instances[], or single-object formats as the llm section.
9
9
  *
10
10
  * @example
@@ -3,7 +3,7 @@ import {
3
3
  createModelHub,
4
4
  embedViaOpenAICompatibleApi,
5
5
  parseEmbedSection
6
- } from "../chunk-5YPJ43HW.js";
6
+ } from "../chunk-Z4E7LN4P.js";
7
7
  import {
8
8
  parseLlmSection
9
9
  } from "../chunk-SPDXNDDD.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@easynet/agent-model",
3
- "version": "1.0.61",
3
+ "version": "1.0.62",
4
4
  "description": "Agent LLM: multi-provider, multi-model, simple chat/image API. Consumes agent.yaml llm section.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/model/index.ts","../src/model/embed-parser.ts","../src/model/chat.ts","../src/model/embedding.ts","../src/model/hub.ts"],"sourcesContent":["/**\n * Model APIs (no LangChain dependency):\n * - LLM types and config parsing\n * - Chat completion and embedding HTTP APIs\n * - ModelHub (generate + embed)\n */\n\nexport type { LLMType, LLMConfig, AgentConfigLlmSection } from \"./types.js\";\nexport { parseLlmSection } from \"./llm-parser.js\";\nexport { parseEmbedSection } from \"./embed-parser.js\";\nexport {\n chatCompletionViaOpenAICompatibleApi,\n type ChatCompletionOptions,\n type ChatCompletionMessage,\n type ChatCompletionRequest,\n type ChatCompletionResult,\n} from \"./chat.js\";\nexport {\n embedViaOpenAICompatibleApi,\n type EmbeddingOptions,\n type EmbedRequest,\n type EmbedResult,\n} from \"./embedding.js\";\nexport {\n createModelHub,\n type CreateModelHubOptions,\n type ModelHub,\n type ChatGenerateRequest,\n type ChatGenerateResult,\n} from \"./hub.js\";\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","/**\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"],"mappings":"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","names":["isLocalBaseUrl"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/config/yaml-utils.ts","../src/config/loader.ts"],"sourcesContent":["import { existsSync, readFileSync, statSync } from \"node:fs\";\nimport { readFile, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { parse as parseYaml } from \"yaml\";\n\nexport interface YamlEnvOptions {\n substituteEnv?: boolean;\n missingEnv?: \"keep\" | \"empty\";\n env?: NodeJS.ProcessEnv;\n}\n\nexport interface LoadYamlOptions extends YamlEnvOptions {\n cache?: boolean;\n}\n\ninterface CacheEntry {\n mtimeMs: number;\n value: unknown;\n}\n\nconst YAML_CACHE = new Map<string, CacheEntry>();\n\nexport function clearYamlFileCache(): void {\n YAML_CACHE.clear();\n}\n\nfunction substituteEnvInString(\n input: string,\n env: NodeJS.ProcessEnv,\n missingEnv: \"keep\" | \"empty\",\n): string {\n return input.replace(/\\$\\{(\\w+)\\}/g, (_, name: string) => {\n const value = env[name];\n if (value !== undefined) return value;\n return missingEnv === \"empty\" ? \"\" : `\\${${name}}`;\n });\n}\n\nfunction substituteEnvInValue(\n input: unknown,\n options: { env: NodeJS.ProcessEnv; missingEnv: \"keep\" | \"empty\" },\n): unknown {\n if (typeof input === \"string\") {\n return substituteEnvInString(input, options.env, options.missingEnv);\n }\n if (Array.isArray(input)) {\n return input.map((item) => substituteEnvInValue(item, options));\n }\n if (input && typeof input === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(input)) {\n out[k] = substituteEnvInValue(v, options);\n }\n return out;\n }\n return input;\n}\n\nexport function parseYamlContent<T = unknown>(\n content: string,\n options: YamlEnvOptions = {},\n): T {\n const parsed = parseYaml(content) as unknown;\n if (options.substituteEnv === false) return parsed as T;\n return substituteEnvInValue(parsed, {\n env: options.env ?? process.env,\n missingEnv: options.missingEnv ?? \"keep\",\n }) as T;\n}\n\nfunction readFromCache(filePath: string, mtimeMs: number): unknown | undefined {\n const cached = YAML_CACHE.get(filePath);\n if (!cached) return undefined;\n if (cached.mtimeMs !== mtimeMs) return undefined;\n return cached.value;\n}\n\nfunction writeCache(filePath: string, mtimeMs: number, value: unknown): void {\n YAML_CACHE.set(filePath, { mtimeMs, value });\n}\n\nexport function loadYamlFileSync<T = unknown>(\n filePath: string,\n options: LoadYamlOptions = {},\n): T | undefined {\n const absPath = path.resolve(filePath);\n if (!existsSync(absPath)) return undefined;\n const useCache = options.cache === true;\n const fileStat = statSync(absPath);\n if (useCache) {\n const cached = readFromCache(absPath, fileStat.mtimeMs);\n if (cached !== undefined) return cached as T;\n }\n const content = readFileSync(absPath, \"utf-8\");\n const parsed = parseYamlContent<T>(content, options);\n if (useCache) writeCache(absPath, fileStat.mtimeMs, parsed);\n return parsed;\n}\n\nexport async function loadYamlFile<T = unknown>(\n filePath: string,\n options: LoadYamlOptions = {},\n): Promise<T | undefined> {\n const absPath = path.resolve(filePath);\n let fileStat;\n try {\n fileStat = await stat(absPath);\n } catch (err) {\n if ((err as NodeJS.ErrnoException)?.code === \"ENOENT\") return undefined;\n throw err;\n }\n const useCache = options.cache === true;\n if (useCache) {\n const cached = readFromCache(absPath, fileStat.mtimeMs);\n if (cached !== undefined) return cached as T;\n }\n const content = await readFile(absPath, \"utf-8\");\n const parsed = parseYamlContent<T>(content, options);\n if (useCache) writeCache(absPath, fileStat.mtimeMs, parsed);\n return parsed;\n}\n","/**\n * Load and parse LLM config from YAML (e.g. models.yaml).\n * Supports ${VAR} substitution from process.env.\n */\nimport { loadYamlFileSync, parseYamlContent } from \"./yaml-utils.js\";\n\nexport interface LoadLlmConfigOptions {\n substituteEnv?: boolean;\n}\n\nexport function substituteEnv(obj: unknown): unknown {\n if (obj === null || obj === undefined) return obj;\n if (typeof obj === \"string\") {\n const m = obj.match(/^\\$\\{(\\w+)\\}$/);\n return m ? (process.env[m[1]] ?? obj) : obj;\n }\n if (Array.isArray(obj)) return obj.map(substituteEnv);\n if (typeof obj === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(obj)) out[k] = substituteEnv(v);\n return out;\n }\n return obj;\n}\n\nexport function parseLlmYaml(\n content: string,\n options: LoadLlmConfigOptions = {}\n): unknown {\n const { substituteEnv: doSub = true } = options;\n const parsed = parseYamlContent<{ llm?: unknown }>(content, {\n substituteEnv: doSub,\n missingEnv: \"keep\",\n });\n const llm = parsed?.llm;\n if (llm == null) return undefined;\n return llm;\n}\n\nexport interface ModelsConfigResult {\n llm: unknown;\n vlm: unknown;\n embed: unknown;\n runtime: { check_connectivity?: boolean };\n}\n\n/**\n * Load the full models.yaml config, returning llm, vlm, embed, and runtime sections.\n */\nexport function loadModelsConfig(\n filePath: string,\n options: LoadLlmConfigOptions = {},\n): ModelsConfigResult | null {\n if (typeof filePath !== \"string\" || filePath.trim().length === 0) {\n throw new Error(\"agent-model: loadModelsConfig requires a non-empty file path\");\n }\n try {\n const parsed = loadYamlFileSync<{\n llm?: unknown;\n vlm?: unknown;\n embed?: unknown;\n runtime?: Record<string, unknown>;\n }>(filePath, {\n substituteEnv: options.substituteEnv !== false,\n missingEnv: \"keep\",\n cache: true,\n });\n if (parsed == null) return null;\n return {\n llm: parsed.llm ?? null,\n vlm: parsed.vlm ?? null,\n embed: parsed.embed ?? null,\n runtime: {\n check_connectivity:\n typeof parsed.runtime?.check_connectivity === \"boolean\"\n ? parsed.runtime.check_connectivity\n : undefined,\n },\n };\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n throw new Error(`agent-model: failed to parse config file ${filePath}: ${msg}`, { cause: e });\n }\n}\n\n/**\n * Load only the llm section from a YAML config file.\n * @deprecated Use loadModelsConfig() instead.\n */\nexport function loadLlmConfig(\n filePath: string,\n options: LoadLlmConfigOptions = {}\n): unknown | null {\n const result = loadModelsConfig(filePath, options);\n return result?.llm ?? null;\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/cli/index.ts","../src/api/create-agent-llm.ts","../src/cli/utils.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * CLI for @easynet/agent-model: chat with the configured LLM (LangChain ChatOpenAI).\n * Usage: agent-model \"your question\"\n * or: agent-model --config ./models.yaml \"hi\"\n * or: agent-model --tools \"what is the weather in SF?\"\n */\nimport { createAgentLlm } from \"../api/create-agent-llm.js\";\nimport { messageContentToString } from \"./utils.js\";\nimport type { BaseChatModel } from \"@langchain/core/language_models/chat_models\";\nimport { tool } from \"@langchain/core/tools\";\nimport { z } from \"zod\";\nimport { HumanMessage, AIMessage, ToolMessage } from \"@langchain/core/messages\";\nimport type { BaseMessage } from \"@langchain/core/messages\";\nimport { fileURLToPath } from \"node:url\";\n\nfunction parseArgv(): { configPath: string | undefined; useTools: boolean; query: string } {\n const args = process.argv.slice(2);\n let configPath: string | undefined;\n let useTools = false;\n const rest: string[] = [];\n for (let i = 0; i < args.length; i++) {\n if (args[i] === \"--config\" && args[i + 1]) {\n configPath = args[i + 1];\n i++;\n } else if (args[i] === \"--tools\") {\n useTools = true;\n } else {\n rest.push(args[i]);\n }\n }\n const query = rest.join(\" \").trim() || \"hi\";\n return { configPath, useTools, query };\n}\n\nconst getWeather = tool(\n (input: { location: string }) => {\n const loc = input.location.toLowerCase();\n if ([\"sf\", \"sf bay\"].includes(loc)) return \"It's 60°F and foggy in the Bay Area.\";\n if ([\"ny\", \"new york\"].includes(loc)) return \"It's 72°F and partly cloudy in New York.\";\n return `Weather for ${input.location}: 70°F and sunny.`;\n },\n {\n name: \"get_weather\",\n description: \"Get the current weather for a location.\",\n schema: z.object({\n location: z.string().describe(\"City or place name (e.g. SF, New York)\"),\n }),\n }\n);\n\nconst addNumbers = tool(\n (input: { a: number; b: number }) => String(input.a + input.b),\n {\n name: \"add_numbers\",\n description: \"Add two numbers.\",\n schema: z.object({\n a: z.number().describe(\"First number\"),\n b: z.number().describe(\"Second number\"),\n }),\n }\n);\n\nconst tools = [getWeather, addNumbers];\nconst toolsByName = new Map(tools.map((t) => [t.name, t]));\nconst MAX_TURNS = 10;\n\nasync function runSimpleChat(model: BaseChatModel, query: string): Promise<string> {\n const messages: BaseMessage[] = [new HumanMessage(query)];\n const response = await model.invoke(messages);\n return messageContentToString(response.content);\n}\n\nasync function runAgentWithTools(model: BaseChatModel, query: string): Promise<string> {\n const withTools = model.bindTools?.(tools, { tool_choice: \"auto\" });\n const messages: BaseMessage[] = [new HumanMessage(query)];\n if (!withTools) return runSimpleChat(model, query);\n\n for (let turn = 0; turn < MAX_TURNS; turn++) {\n const response = await withTools.invoke(messages);\n const aiMessage = response as AIMessage;\n\n if (!aiMessage.tool_calls?.length) {\n return messageContentToString(aiMessage.content);\n }\n\n messages.push(aiMessage);\n for (const tc of aiMessage.tool_calls) {\n const id = tc.id ?? `call_${turn}_${tc.name}`;\n const toolFn = toolsByName.get(tc.name as \"get_weather\" | \"add_numbers\");\n let result: string;\n if (toolFn) {\n try {\n const out = await (toolFn as { invoke: (args: Record<string, unknown>) => Promise<unknown> }).invoke(\n tc.args as Record<string, unknown>\n );\n result = typeof out === \"string\" ? out : JSON.stringify(out);\n } catch (err) {\n result = `Error: ${err instanceof Error ? err.message : String(err)}`;\n }\n } else {\n result = `Unknown tool: ${tc.name}`;\n }\n messages.push(new ToolMessage({ content: result, tool_call_id: id }));\n }\n }\n return \"Agent reached max turns without a final answer.\";\n}\n\nasync function main() {\n const { configPath, useTools, query } = parseArgv();\n const model = await createAgentLlm(configPath ? { configPath } : undefined);\n\n console.log(\"Query:\", query);\n console.log(\"---\");\n const answer = useTools\n ? await runAgentWithTools(model, query)\n : await runSimpleChat(model, query);\n console.log(\"Answer:\", answer);\n console.log(\"---\");\n console.log(\"Done.\");\n}\n\nconst entryArg = process.argv[1];\nconst isDirectRun =\n typeof entryArg === \"string\" && entryArg.length > 0 && fileURLToPath(import.meta.url) === entryArg;\n\nif (isDirectRun) {\n main().catch((err) => {\n console.error(err);\n process.exit(1);\n });\n}\n","/**\n * Simple API: create LangChain ChatModel from models.yaml config.\n * Supports OpenAI-compatible providers with optional connectivity check and npm: provider resolution.\n */\nimport { join } from \"node:path\";\nimport type { BaseChatModel } from \"@langchain/core/language_models/chat_models\";\nimport {\n checkEndpointConnectivity,\n buildUnreachableError,\n type EndpointConnectivityOptions,\n type ConnectionStatus,\n} from \"../connectivity/index.js\";\nimport { parseLlmSection } from \"../model/llm-parser.js\";\nimport type { LLMConfig } from \"../model/types.js\";\nimport { createChatModelFromLlmConfig } from \"../langchain/index.js\";\nimport { resolveLlmSectionWithNpm } from \"../extensions/npm-protocol.js\";\nimport { loadModelsConfig } from \"../config/loader.js\";\n\n/**\n * Ensure bindTools always receives tool_choice: \"auto\" when tools are bound.\n * Fixes \"Tool choice is none, but model called a tool\" when using this model\n * with LangChain createAgent (AgentNode leaves tool_choice undefined for non-structured tools).\n * Mutates the model in place so it still passes isBaseChatModel / bindTools checks.\n */\nfunction applyDefaultToolChoice(model: BaseChatModel): void {\n const m = model as {\n bindTools?: (tools: unknown, opts?: Record<string, unknown>) => unknown;\n };\n const orig = m.bindTools?.bind(model);\n if (!orig) return;\n m.bindTools = function (tools: unknown, opts?: Record<string, unknown>) {\n return orig(tools, { ...opts, tool_choice: \"auto\" });\n };\n}\n\nconst CIS_DEFAULT_RESOLVE_HOST = \"s0010-ml-https.s0010.us-west-2.awswd\";\nconst CIS_DEFAULT_RESOLVE_IP = \"10.210.98.124\";\n\nfunction buildEndpointConnectivityOptions(\n config: LLMConfig & { baseURL: string }\n): EndpointConnectivityOptions | undefined {\n const opts = (config.options as Record<string, unknown> | undefined) ?? config;\n const provider = typeof config.provider === \"string\" ? config.provider : \"\";\n const baseURL = config.baseURL;\n const isCis = provider === \"cis\" || provider.includes(\"cis\");\n const useCisDefault =\n isCis &&\n baseURL.includes(CIS_DEFAULT_RESOLVE_HOST) &&\n opts?.resolveHost == null;\n\n const resolveHost =\n opts?.resolveHost != null && typeof (opts.resolveHost as { from?: string; to?: string }).from === \"string\"\n ? (opts.resolveHost as { from: string; to: string })\n : useCisDefault\n ? { from: CIS_DEFAULT_RESOLVE_HOST, to: CIS_DEFAULT_RESOLVE_IP }\n : undefined;\n const host = typeof opts?.host === \"string\" ? opts.host : (resolveHost ? resolveHost.from : undefined);\n if (resolveHost == null && host == null) return undefined;\n\n const verifySSL = opts?.verifySSL === true;\n const bypassAuth = opts?.bypassAuth !== false;\n\n return {\n resolveHost,\n host,\n verifySSL: resolveHost != null ? false : (verifySSL ? true : undefined),\n bypassAuth: bypassAuth ? true : undefined,\n featureKey: typeof opts?.featureKey === \"string\" ? opts.featureKey : undefined,\n };\n}\n\nexport interface CreateAgentLlmOptions {\n configPath?: string;\n installNpmIfMissing?: boolean;\n checkConnectivity?: boolean;\n onConnectionStatus?: (status: ConnectionStatus) => void;\n connectivityTimeoutMs?: number;\n}\n\nfunction resolveDefaultConfigPath(): string {\n return join(process.cwd(), \"models.yaml\");\n}\n\nfunction normalizeOptions(\n configPathOrOptions?: string | CreateAgentLlmOptions\n): CreateAgentLlmOptions {\n if (configPathOrOptions == null) return {};\n if (typeof configPathOrOptions === \"string\") return { configPath: configPathOrOptions };\n return configPathOrOptions;\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\nasync function ensureConnectivity(\n resolvedLlmSection: unknown,\n options: {\n checkConnectivity?: boolean;\n onConnectionStatus?: (status: ConnectionStatus) => void;\n connectivityTimeoutMs?: number;\n }\n): Promise<void> {\n let configs: Array<LLMConfig & { baseURL: string }>;\n try {\n const parsed = parseLlmSection(resolvedLlmSection ?? null);\n configs = parsed.configs.filter(\n (c: LLMConfig): c is LLMConfig & { baseURL: string } =>\n typeof c.baseURL === \"string\" &&\n c.baseURL.length > 0 &&\n (c.baseURL.startsWith(\"http://\") || c.baseURL.startsWith(\"https://\")) &&\n !c.baseURL.includes(\"${\")\n );\n } catch {\n return;\n }\n const shouldCheck = options.checkConnectivity !== false && configs.length > 0;\n if (!shouldCheck) return;\n\n const report = (status: ConnectionStatus) => options.onConnectionStatus?.(status);\n const timeoutMs = options.connectivityTimeoutMs ?? 8000;\n\n for (const config of configs) {\n const { id, baseURL } = config;\n report({\n phase: \"checking\",\n endpointId: id,\n baseURL,\n message: \"Checking connection...\",\n });\n\n const endpointOpts = buildEndpointConnectivityOptions(config);\n const result = await checkEndpointConnectivity(baseURL, {\n timeoutMs,\n ...endpointOpts,\n });\n\n if (result.reachable) {\n report({\n phase: \"reachable\",\n endpointId: id,\n baseURL,\n message: result.message ?? \"Connected\",\n });\n } else {\n report({\n phase: \"unreachable\",\n endpointId: id,\n baseURL,\n message: result.message ?? \"Unreachable\",\n });\n throw new Error(buildUnreachableError(id, baseURL, result.message));\n }\n }\n}\n\n/**\n * Create a LangChain ChatModel from models.yaml config.\n * Returns BaseChatModel compatible with LangChain's createAgent and other tools.\n */\nexport async function createAgentLlm(\n configPathOrOptions?: string | CreateAgentLlmOptions\n): Promise<BaseChatModel> {\n try {\n const options = normalizeOptions(configPathOrOptions);\n const configPath = options.configPath ?? resolveDefaultConfigPath();\n const modelsConfig = loadModelsConfig(configPath);\n\n if (modelsConfig?.llm == null) {\n throw new Error(\n `No LLM config at ${configPath}. Add models.yaml in the current directory, or pass configPath.`\n );\n }\n\n const resolvedSection = await resolveLlmSectionWithNpm(modelsConfig.llm, {\n installNpmIfMissing: options.installNpmIfMissing !== false,\n cwd: process.cwd(),\n });\n\n // Priority: caller option > YAML runtime > default (true)\n const checkConnectivity =\n options.checkConnectivity ?? modelsConfig.runtime.check_connectivity;\n\n await ensureConnectivity(resolvedSection, {\n checkConnectivity,\n onConnectionStatus: options.onConnectionStatus,\n connectivityTimeoutMs: options.connectivityTimeoutMs,\n });\n\n const model = createChatModelFromLlmConfig({ llmSection: resolvedSection });\n applyDefaultToolChoice(model);\n return model;\n } catch (e) {\n if (e instanceof Error && e.message.includes(\"No LLM config\")) throw e;\n if (e instanceof Error && e.message.includes(\"Cannot connect to\")) throw e;\n throw normalizeError(e, \"createAgentLlm failed\");\n }\n}\n","/**\n * Shared CLI helpers for agent-model and provider CLIs.\n */\n\n/**\n * Turn LangChain message content (string | array of parts) into a single string.\n */\nexport function messageContentToString(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (Array.isArray(content)) {\n return (content as { type?: string; text?: string }[])\n .map((c) => (\"text\" in c && c.text ? c.text : \"\"))\n .join(\"\");\n }\n return String(content ?? \"\");\n}\n\n/**\n * Log error and exit. Use in CLIs for consistent error handling.\n */\nexport function exitWithError(err: unknown, code = 1): never {\n console.error(\"Error:\", err instanceof Error ? err.message : String(err));\n process.exit(code);\n}\n"],"mappings":"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","names":["tools"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/config/index.ts","../src/config/yaml.ts"],"sourcesContent":["export { parseLlmSection } from \"./parser.js\";\nexport { loadLlmConfig, parseLlmYaml, substituteEnv } from \"./loader.js\";\nexport { loadYamlConfig } from \"./yaml.js\";\nexport {\n loadYamlFile,\n loadYamlFileSync,\n parseYamlContent,\n clearYamlFileCache,\n type LoadYamlOptions,\n type YamlEnvOptions,\n} from \"./yaml-utils.js\";\nexport type { LoadLlmConfigOptions } from \"./loader.js\";\n","/**\n * Generic YAML file loader utility.\n */\n\nimport { loadYamlFileSync } from \"./yaml-utils.js\";\n\n/**\n * Load and parse a YAML file into a typed object.\n * Returns empty object if file doesn't exist.\n */\nexport function loadYamlConfig<T = Record<string, unknown>>(filePath: string): T {\n try {\n const parsed = loadYamlFileSync<T>(filePath, {\n substituteEnv: true,\n missingEnv: \"keep\",\n cache: true,\n });\n return (parsed ?? ({} as T)) as T;\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n throw new Error(`Failed to load YAML config from ${filePath}: ${msg}`, { cause: e });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACUO,SAAS,eAA4C,UAAqB;AAC/E,MAAI;AACF,UAAM,SAAS,iBAAoB,UAAU;AAAA,MAC3C,eAAe;AAAA,MACf,YAAY;AAAA,MACZ,OAAO;AAAA,IACT,CAAC;AACD,WAAQ,UAAW,CAAC;AAAA,EACtB,SAAS,GAAG;AACV,UAAM,MAAM,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;AACrD,UAAM,IAAI,MAAM,mCAAmC,QAAQ,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,CAAC;AAAA,EACrF;AACF;","names":[]}