@easynet/agent-model 1.0.53 → 1.0.54

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.
@@ -149,6 +149,7 @@ function messageContentToString(content) {
149
149
  import { tool } from "@langchain/core/tools";
150
150
  import { z } from "zod";
151
151
  import { HumanMessage, ToolMessage } from "@langchain/core/messages";
152
+ import { fileURLToPath } from "url";
152
153
  function parseArgv() {
153
154
  const args = process.argv.slice(2);
154
155
  let configPath;
@@ -243,13 +244,17 @@ async function main() {
243
244
  console.log("---");
244
245
  console.log("Done.");
245
246
  }
246
- main().catch((err) => {
247
- console.error(err);
248
- process.exit(1);
249
- });
247
+ var entryArg = process.argv[1];
248
+ var isDirectRun = typeof entryArg === "string" && entryArg.length > 0 && fileURLToPath(import.meta.url) === entryArg;
249
+ if (isDirectRun) {
250
+ main().catch((err) => {
251
+ console.error(err);
252
+ process.exit(1);
253
+ });
254
+ }
250
255
 
251
256
  export {
252
257
  createAgentLlm,
253
258
  cli_exports
254
259
  };
255
- //# sourceMappingURL=chunk-TKIZELZQ.js.map
260
+ //# sourceMappingURL=chunk-YCV6JBJZ.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 ./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":";;;;;;;;;;;;;;;;;;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,aAAa;AAC1C;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"]}
package/dist/cli/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import "../chunk-TKIZELZQ.js";
2
+ import "../chunk-YCV6JBJZ.js";
3
3
  import "../chunk-FZKECZUY.js";
4
4
  import "../chunk-EPVJLBGC.js";
5
5
  import "../chunk-HSU6XZOI.js";
package/dist/index.js CHANGED
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  registry_exports
3
3
  } from "./chunk-HCU4AWIV.js";
4
- import {
5
- cli_exports,
6
- createAgentLlm
7
- } from "./chunk-TKIZELZQ.js";
8
4
  import {
9
5
  config_exports
10
6
  } from "./chunk-VBXTOU4S.js";
7
+ import {
8
+ cli_exports,
9
+ createAgentLlm
10
+ } from "./chunk-YCV6JBJZ.js";
11
11
  import {
12
12
  loadLlmConfig,
13
13
  loadModelsConfig
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@easynet/agent-model",
3
- "version": "1.0.53",
3
+ "version": "1.0.54",
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/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\";\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\nmain().catch((err) => {\n console.error(err);\n process.exit(1);\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"]}