@easynet/agent-llm 1.0.7 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -57,8 +57,12 @@ var toolsByName = new Map(tools.map((t) => [t.name, t]));
57
57
  var MAX_TURNS = 10;
58
58
  async function runAgent(model, query) {
59
59
  const withTools = model.bindTools?.(tools, { tool_choice: "auto" });
60
- if (!withTools) throw new Error("Model does not support bindTools");
61
60
  const messages = [new HumanMessage(query)];
61
+ if (!withTools) {
62
+ const response = await model.invoke(messages);
63
+ const content = typeof response.content === "string" ? response.content : Array.isArray(response.content) ? response.content.map((c) => "text" in c ? c.text : "").join("") : String(response.content ?? "");
64
+ return content;
65
+ }
62
66
  for (let turn = 0; turn < MAX_TURNS; turn++) {
63
67
  const response = await withTools.invoke(messages);
64
68
  const aiMessage = response;
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * CLI for @easynet/agent-llm: run the LangChain agent with a query.\n * Usage: agent-llm \"your question\"\n * or: agent-llm --config ./config/llm.yaml \"hi\"\n * or: npx @easynet/agent-llm \"hi\"\n */\n\nimport { createAgentLlM } from \"./createAgentLlM.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; query: string } {\n const args = process.argv.slice(2);\n let configPath: string | undefined;\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 {\n rest.push(args[i]);\n }\n }\n const query = rest.join(\" \").trim() || \"hi\";\n return { configPath, query };\n}\n\nconst getWeather = tool(\n (input: { location: string }) => {\n const loc = input.location.toLowerCase();\n if ([\"sf\", \"san francisco\"].includes(loc)) {\n return \"It's 60°F and foggy in San Francisco.\";\n }\n if ([\"ny\", \"new york\"].includes(loc)) {\n return \"It's 72°F and partly cloudy in New York.\";\n }\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]));\n\nconst MAX_TURNS = 10;\n\nasync function runAgent(\n model: BaseChatModel,\n query: string\n): Promise<string> {\n const withTools = model.bindTools?.(tools, { tool_choice: \"auto\" });\n if (!withTools) throw new Error(\"Model does not support bindTools\");\n const messages: BaseMessage[] = [new HumanMessage(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 const content =\n typeof aiMessage.content === \"string\"\n ? aiMessage.content\n : Array.isArray(aiMessage.content)\n ? (aiMessage.content as { type?: string; text?: string }[])\n .map((c) => (\"text\" in c ? c.text : \"\"))\n .join(\"\")\n : String(aiMessage.content ?? \"\");\n return content;\n }\n\n messages.push(aiMessage);\n\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\n return \"Agent reached max turns without a final answer.\";\n}\n\nasync function main() {\n const { configPath, query } = parseArgv();\n // createAgentLlM resolves npm: providers (e.g. npm:wallee-llm#cis) and loads packages\n const model = await createAgentLlM(configPath ? { configPath } : undefined);\n\n console.log(\"Query:\", query);\n console.log(\"---\");\n\n const answer = await runAgent(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"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * CLI for @easynet/agent-llm: run the LangChain agent with a query.\n * Usage: agent-llm \"your question\"\n * or: agent-llm --config ./config/llm.yaml \"hi\"\n * or: npx @easynet/agent-llm \"hi\"\n */\n\nimport { createAgentLlM } from \"./createAgentLlM.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; query: string } {\n const args = process.argv.slice(2);\n let configPath: string | undefined;\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 {\n rest.push(args[i]);\n }\n }\n const query = rest.join(\" \").trim() || \"hi\";\n return { configPath, query };\n}\n\nconst getWeather = tool(\n (input: { location: string }) => {\n const loc = input.location.toLowerCase();\n if ([\"sf\", \"san francisco\"].includes(loc)) {\n return \"It's 60°F and foggy in San Francisco.\";\n }\n if ([\"ny\", \"new york\"].includes(loc)) {\n return \"It's 72°F and partly cloudy in New York.\";\n }\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]));\n\nconst MAX_TURNS = 10;\n\nasync function runAgent(\n model: BaseChatModel,\n query: string\n): Promise<string> {\n const withTools = model.bindTools?.(tools, { tool_choice: \"auto\" });\n const messages: BaseMessage[] = [new HumanMessage(query)];\n\n // If model doesn't support tools, do a single invoke and return content\n if (!withTools) {\n const response = await model.invoke(messages);\n const content =\n typeof response.content === \"string\"\n ? response.content\n : Array.isArray(response.content)\n ? (response.content as { type?: string; text?: string }[])\n .map((c) => (\"text\" in c ? c.text : \"\"))\n .join(\"\")\n : String(response.content ?? \"\");\n return content;\n }\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 const content =\n typeof aiMessage.content === \"string\"\n ? aiMessage.content\n : Array.isArray(aiMessage.content)\n ? (aiMessage.content as { type?: string; text?: string }[])\n .map((c) => (\"text\" in c ? c.text : \"\"))\n .join(\"\")\n : String(aiMessage.content ?? \"\");\n return content;\n }\n\n messages.push(aiMessage);\n\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\n return \"Agent reached max turns without a final answer.\";\n}\n\nasync function main() {\n const { configPath, query } = parseArgv();\n // createAgentLlM resolves npm: providers (e.g. npm:wallee-llm#cis) and loads packages\n const model = await createAgentLlM(configPath ? { configPath } : undefined);\n\n console.log(\"Query:\", query);\n console.log(\"---\");\n\n const answer = await runAgent(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"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@easynet/agent-llm",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
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": {