@easynet/agent-model 1.0.67 → 1.0.69

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 (43) hide show
  1. package/dist/api/create-agent-model-registry.d.ts +19 -0
  2. package/dist/api/create-agent-model-registry.d.ts.map +1 -0
  3. package/dist/{chunk-EPVJLBGC.js → chunk-AUQEXHUP.js} +2 -15
  4. package/dist/chunk-AUQEXHUP.js.map +1 -0
  5. package/dist/{chunk-K3JR2N4E.js → chunk-KE7IMUSA.js} +2 -29
  6. package/dist/chunk-KE7IMUSA.js.map +1 -0
  7. package/dist/chunk-MFLWZSWI.js +17 -0
  8. package/dist/chunk-MFLWZSWI.js.map +1 -0
  9. package/dist/{chunk-CCGNXMFC.js → chunk-UVIUQUYJ.js} +2 -13
  10. package/dist/chunk-UVIUQUYJ.js.map +1 -0
  11. package/dist/{chunk-XSR4TAZ7.js → chunk-UZ6B6BF4.js} +5 -5
  12. package/dist/cli/index.js +252 -8
  13. package/dist/cli/index.js.map +1 -1
  14. package/dist/config/index.js +44 -7
  15. package/dist/config/index.js.map +1 -1
  16. package/dist/connectivity/index.js +1 -2
  17. package/dist/extensions/index.js +4 -6
  18. package/dist/index.d.ts +3 -57
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +191 -109
  21. package/dist/index.js.map +1 -1
  22. package/dist/langchain/index.js +1 -2
  23. package/dist/model/index.js +172 -5
  24. package/dist/model/index.js.map +1 -1
  25. package/dist/npm/index.js +1 -2
  26. package/dist/registry/index.js +0 -2
  27. package/package.json +1 -33
  28. package/dist/chunk-5QOKZ2JF.js +0 -83
  29. package/dist/chunk-5QOKZ2JF.js.map +0 -1
  30. package/dist/chunk-CCGNXMFC.js.map +0 -1
  31. package/dist/chunk-CJK5NAOX.js +0 -260
  32. package/dist/chunk-CJK5NAOX.js.map +0 -1
  33. package/dist/chunk-EPVJLBGC.js.map +0 -1
  34. package/dist/chunk-HCU4AWIV.js +0 -19
  35. package/dist/chunk-HCU4AWIV.js.map +0 -1
  36. package/dist/chunk-K3JR2N4E.js.map +0 -1
  37. package/dist/chunk-PZ5AY32C.js +0 -10
  38. package/dist/chunk-PZ5AY32C.js.map +0 -1
  39. package/dist/chunk-V5QTINFH.js +0 -43
  40. package/dist/chunk-V5QTINFH.js.map +0 -1
  41. package/dist/chunk-Z4E7LN4P.js +0 -205
  42. package/dist/chunk-Z4E7LN4P.js.map +0 -1
  43. /package/dist/{chunk-XSR4TAZ7.js.map → chunk-UZ6B6BF4.js.map} +0 -0
@@ -1,13 +1,180 @@
1
1
  import {
2
- chatCompletionViaOpenAICompatibleApi,
3
- createModelHub,
4
- embedViaOpenAICompatibleApi,
5
2
  parseEmbedSection
6
- } from "../chunk-Z4E7LN4P.js";
3
+ } from "../chunk-MFLWZSWI.js";
7
4
  import {
8
5
  parseLlmSection
9
6
  } from "../chunk-SPDXNDDD.js";
10
- import "../chunk-PZ5AY32C.js";
7
+
8
+ // src/model/chat.ts
9
+ var DEFAULT_CHAT_TIMEOUT_MS = 6e4;
10
+ function isLocalBaseUrl(url) {
11
+ try {
12
+ const u = new URL(url);
13
+ const host = u.hostname.toLowerCase();
14
+ return host === "localhost" || host === "127.0.0.1" || host === "::1";
15
+ } catch {
16
+ return false;
17
+ }
18
+ }
19
+ function normalizeContent(content) {
20
+ if (typeof content === "string") return content;
21
+ if (!Array.isArray(content)) return String(content ?? "");
22
+ const parts = [];
23
+ for (const p of content) {
24
+ if (typeof p === "string") parts.push(p);
25
+ else if (p && typeof p === "object" && typeof p.text === "string")
26
+ parts.push(p.text);
27
+ }
28
+ return parts.join("\n").trim();
29
+ }
30
+ async function chatCompletionViaOpenAICompatibleApi(options, request) {
31
+ const baseUrl = options.baseURL.replace(/\/$/, "");
32
+ const apiKey = options.apiKey?.trim();
33
+ const timeoutMs = options.timeoutMs ?? DEFAULT_CHAT_TIMEOUT_MS;
34
+ const modelName = typeof request.model === "string" && request.model.trim() !== "" ? request.model.trim() : options.model ?? "gpt-4o-mini";
35
+ if (!apiKey && !isLocalBaseUrl(baseUrl)) {
36
+ throw new Error("Chat completion API key is required for non-local baseURL");
37
+ }
38
+ const body = {
39
+ model: modelName,
40
+ messages: request.messages.map((m) => ({ role: m.role, content: m.content })),
41
+ temperature: typeof request.temperature === "number" ? request.temperature : 0
42
+ };
43
+ if (typeof request.maxTokens === "number") body.max_tokens = request.maxTokens;
44
+ const controller = new AbortController();
45
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
46
+ try {
47
+ const response = await fetch(`${baseUrl}/chat/completions`, {
48
+ method: "POST",
49
+ headers: {
50
+ "Content-Type": "application/json",
51
+ ...apiKey ? { Authorization: `Bearer ${apiKey}` } : {}
52
+ },
53
+ body: JSON.stringify(body),
54
+ signal: controller.signal
55
+ });
56
+ if (!response.ok) {
57
+ const text = await response.text();
58
+ throw new Error(`Chat completion API error ${response.status}: ${text.slice(0, 500)}`);
59
+ }
60
+ const data = await response.json();
61
+ const raw = data.choices?.[0]?.message?.content ?? data.choices?.[0]?.text ?? "";
62
+ return {
63
+ text: normalizeContent(raw),
64
+ model: data.model ?? modelName
65
+ };
66
+ } finally {
67
+ clearTimeout(timer);
68
+ }
69
+ }
70
+
71
+ // src/model/embedding.ts
72
+ var DEFAULT_EMBEDDING_TIMEOUT_MS = 3e4;
73
+ function isLocalBaseUrl2(url) {
74
+ try {
75
+ const u = new URL(url);
76
+ const host = u.hostname.toLowerCase();
77
+ return host === "localhost" || host === "127.0.0.1" || host === "::1";
78
+ } catch {
79
+ return false;
80
+ }
81
+ }
82
+ async function embedViaOpenAICompatibleApi(options, input) {
83
+ const baseUrl = options.baseURL.replace(/\/$/, "");
84
+ const apiKey = options.apiKey?.trim();
85
+ const timeoutMs = options.timeoutMs ?? DEFAULT_EMBEDDING_TIMEOUT_MS;
86
+ const modelName = typeof input.model === "string" && input.model.trim() !== "" ? input.model.trim() : options.model ?? "text-embedding-3-small";
87
+ if (!apiKey && !isLocalBaseUrl2(baseUrl)) {
88
+ throw new Error("Embedding API key is required for non-local baseURL");
89
+ }
90
+ const controller = new AbortController();
91
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
92
+ try {
93
+ const response = await fetch(`${baseUrl}/embeddings`, {
94
+ method: "POST",
95
+ headers: {
96
+ "Content-Type": "application/json",
97
+ ...apiKey ? { Authorization: `Bearer ${apiKey}` } : {}
98
+ },
99
+ body: JSON.stringify({ model: modelName, input: input.input }),
100
+ signal: controller.signal
101
+ });
102
+ if (!response.ok) {
103
+ const body = await response.text();
104
+ throw new Error(`Embedding API error ${response.status}: ${body.slice(0, 500)}`);
105
+ }
106
+ const data = await response.json();
107
+ const vectors = (data.data ?? []).slice().sort((a, b) => (a.index ?? 0) - (b.index ?? 0)).map((v) => v.embedding).filter((v) => Array.isArray(v));
108
+ return {
109
+ vectors,
110
+ dimensions: vectors[0]?.length,
111
+ model: data.model ?? modelName
112
+ };
113
+ } finally {
114
+ clearTimeout(timer);
115
+ }
116
+ }
117
+
118
+ // src/model/hub.ts
119
+ var DEFAULT_EMBEDDING_MODEL = "text-embedding-3-small";
120
+ var DEFAULT_CHAT_MODEL = "gpt-4o-mini";
121
+ var DEFAULT_BASE_URL = "https://api.openai.com/v1";
122
+ function getDefaultLlmConfig(llmSection) {
123
+ const parsed = parseLlmSection(llmSection ?? null);
124
+ const config = parsed.configs.find((c) => c.id === parsed.defaultId) ?? parsed.configs[0] ?? null;
125
+ return config;
126
+ }
127
+ function createModelHub(options = {}) {
128
+ const baseCfg = getDefaultLlmConfig(options.llmSection);
129
+ const defaultBaseUrl = (options.embeddingBaseURL ?? baseCfg?.baseURL ?? DEFAULT_BASE_URL).replace(/\/$/, "");
130
+ const defaultApiKey = options.embeddingApiKey ?? baseCfg?.apiKey ?? process.env.OPENAI_API_KEY;
131
+ const defaultEmbeddingModel = options.embeddingModel ?? (baseCfg?.options && typeof baseCfg.options.embeddingModel === "string" ? baseCfg.options.embeddingModel : void 0) ?? baseCfg?.model ?? process.env.OPENAI_EMBEDDING_MODEL ?? DEFAULT_EMBEDDING_MODEL;
132
+ const defaultChatModel = baseCfg?.model ?? process.env.OPENAI_MODEL ?? DEFAULT_CHAT_MODEL;
133
+ const embeddingTimeoutMs = options.embeddingTimeoutMs;
134
+ const chatTimeoutMs = options.chatTimeoutMs;
135
+ return {
136
+ async generate(input) {
137
+ const messages = [];
138
+ if (typeof input.systemPrompt === "string" && input.systemPrompt.trim() !== "") {
139
+ messages.push({ role: "system", content: input.systemPrompt.trim() });
140
+ }
141
+ messages.push({ role: "user", content: input.input });
142
+ const result = await chatCompletionViaOpenAICompatibleApi(
143
+ {
144
+ baseURL: defaultBaseUrl,
145
+ apiKey: defaultApiKey,
146
+ model: defaultChatModel,
147
+ timeoutMs: chatTimeoutMs
148
+ },
149
+ {
150
+ messages,
151
+ model: input.model,
152
+ temperature: input.temperature
153
+ }
154
+ );
155
+ return {
156
+ text: result.text,
157
+ model: typeof input.model === "string" && input.model.trim() !== "" ? input.model : result.model ?? baseCfg?.model
158
+ };
159
+ },
160
+ async embed(input) {
161
+ const result = await embedViaOpenAICompatibleApi(
162
+ {
163
+ baseURL: defaultBaseUrl,
164
+ apiKey: defaultApiKey,
165
+ model: defaultEmbeddingModel,
166
+ timeoutMs: embeddingTimeoutMs
167
+ },
168
+ { input: input.input, model: input.model }
169
+ );
170
+ return {
171
+ vectors: result.vectors,
172
+ dimensions: result.dimensions,
173
+ model: result.model
174
+ };
175
+ }
176
+ };
177
+ }
11
178
  export {
12
179
  chatCompletionViaOpenAICompatibleApi,
13
180
  createModelHub,
@@ -1 +1 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
1
+ {"version":3,"sources":["../../src/model/chat.ts","../../src/model/embedding.ts","../../src/model/hub.ts"],"sourcesContent":["/**\n * OpenAI-compatible chat completion API: POST /chat/completions.\n * No LangChain dependency; for use by any module that needs LLM text generation.\n */\n\nconst DEFAULT_CHAT_TIMEOUT_MS = 60_000;\n\nexport interface ChatCompletionOptions {\n baseURL: string;\n apiKey?: string;\n model?: string;\n timeoutMs?: number;\n}\n\nexport interface ChatCompletionMessage {\n role: \"system\" | \"user\" | \"assistant\";\n content: string;\n}\n\nexport interface ChatCompletionRequest {\n messages: ChatCompletionMessage[];\n model?: string;\n temperature?: number;\n maxTokens?: number;\n}\n\nexport interface ChatCompletionResult {\n text: string;\n model?: string;\n}\n\nfunction isLocalBaseUrl(url: string): boolean {\n try {\n const u = new URL(url);\n const host = u.hostname.toLowerCase();\n return host === \"localhost\" || host === \"127.0.0.1\" || host === \"::1\";\n } catch {\n return false;\n }\n}\n\nfunction normalizeContent(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return String(content ?? \"\");\n const parts: string[] = [];\n for (const p of content) {\n if (typeof p === \"string\") parts.push(p);\n else if (p && typeof p === \"object\" && typeof (p as { text?: unknown }).text === \"string\")\n parts.push((p as { text: string }).text);\n }\n return parts.join(\"\\n\").trim();\n}\n\n/**\n * Call OpenAI-compatible /chat/completions endpoint.\n * baseURL should be the API root (e.g. https://api.openai.com/v1); trailing slash is stripped.\n */\nexport async function chatCompletionViaOpenAICompatibleApi(\n options: ChatCompletionOptions,\n request: ChatCompletionRequest\n): Promise<ChatCompletionResult> {\n const baseUrl = options.baseURL.replace(/\\/$/, \"\");\n const apiKey = options.apiKey?.trim();\n const timeoutMs = options.timeoutMs ?? DEFAULT_CHAT_TIMEOUT_MS;\n const modelName =\n typeof request.model === \"string\" && request.model.trim() !== \"\"\n ? request.model.trim()\n : options.model ?? \"gpt-4o-mini\";\n\n if (!apiKey && !isLocalBaseUrl(baseUrl)) {\n throw new Error(\"Chat completion API key is required for non-local baseURL\");\n }\n\n const body: Record<string, unknown> = {\n model: modelName,\n messages: request.messages.map((m) => ({ role: m.role, content: m.content })),\n temperature: typeof request.temperature === \"number\" ? request.temperature : 0,\n };\n if (typeof request.maxTokens === \"number\") body.max_tokens = request.maxTokens;\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const response = await fetch(`${baseUrl}/chat/completions`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {}),\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n if (!response.ok) {\n const text = await response.text();\n throw new Error(`Chat completion API error ${response.status}: ${text.slice(0, 500)}`);\n }\n const data = (await response.json()) as {\n choices?: Array<{ message?: { content?: unknown }; text?: unknown }>;\n model?: string;\n };\n const raw =\n data.choices?.[0]?.message?.content ?? data.choices?.[0]?.text ?? \"\";\n return {\n text: normalizeContent(raw),\n model: data.model ?? modelName,\n };\n } finally {\n clearTimeout(timer);\n }\n}\n","/**\n * OpenAI-compatible embedding API: POST /embeddings.\n * No LangChain dependency; for use by any module that needs embeddings.\n */\n\nconst DEFAULT_EMBEDDING_TIMEOUT_MS = 30_000;\n\nexport interface EmbeddingOptions {\n baseURL: string;\n apiKey?: string;\n model?: string;\n timeoutMs?: number;\n}\n\nexport interface EmbedRequest {\n input: string | string[];\n model?: string;\n}\n\nexport interface EmbedResult {\n vectors: number[][];\n dimensions?: number;\n model?: string;\n}\n\nfunction isLocalBaseUrl(url: string): boolean {\n try {\n const u = new URL(url);\n const host = u.hostname.toLowerCase();\n return host === \"localhost\" || host === \"127.0.0.1\" || host === \"::1\";\n } catch {\n return false;\n }\n}\n\n/**\n * Call OpenAI-compatible /embeddings endpoint.\n * baseURL should be the API root (e.g. https://api.openai.com/v1); trailing slash is stripped.\n */\nexport async function embedViaOpenAICompatibleApi(\n options: EmbeddingOptions,\n input: EmbedRequest\n): Promise<EmbedResult> {\n const baseUrl = options.baseURL.replace(/\\/$/, \"\");\n const apiKey = options.apiKey?.trim();\n const timeoutMs = options.timeoutMs ?? DEFAULT_EMBEDDING_TIMEOUT_MS;\n const modelName =\n typeof input.model === \"string\" && input.model.trim() !== \"\"\n ? input.model.trim()\n : options.model ?? \"text-embedding-3-small\";\n\n if (!apiKey && !isLocalBaseUrl(baseUrl)) {\n throw new Error(\"Embedding API key is required for non-local baseURL\");\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const response = await fetch(`${baseUrl}/embeddings`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {}),\n },\n body: JSON.stringify({ model: modelName, input: input.input }),\n signal: controller.signal,\n });\n if (!response.ok) {\n const body = await response.text();\n throw new Error(`Embedding API error ${response.status}: ${body.slice(0, 500)}`);\n }\n const data = (await response.json()) as {\n data?: Array<{ embedding?: number[]; index?: number }>;\n model?: string;\n };\n const vectors = (data.data ?? [])\n .slice()\n .sort((a, b) => (a.index ?? 0) - (b.index ?? 0))\n .map((v) => v.embedding)\n .filter((v): v is number[] => Array.isArray(v));\n return {\n vectors,\n dimensions: vectors[0]?.length,\n model: data.model ?? modelName,\n };\n } finally {\n clearTimeout(timer);\n }\n}\n","/**\n * Model hub: generate (chat completion) + embed, driven by llm section config.\n * No LangChain; uses OpenAI-compatible HTTP APIs so any package can use it via agent-model.\n */\n\nimport { parseLlmSection } from \"./llm-parser.js\";\nimport type { LLMConfig } from \"./types.js\";\nimport { chatCompletionViaOpenAICompatibleApi } from \"./chat.js\";\nimport { embedViaOpenAICompatibleApi } from \"./embedding.js\";\nimport type { EmbedRequest, EmbedResult } from \"./embedding.js\";\n\nconst DEFAULT_EMBEDDING_MODEL = \"text-embedding-3-small\";\nconst DEFAULT_CHAT_MODEL = \"gpt-4o-mini\";\nconst DEFAULT_BASE_URL = \"https://api.openai.com/v1\";\n\nexport interface CreateModelHubOptions {\n llmSection?: unknown;\n embeddingBaseURL?: string;\n embeddingApiKey?: string;\n embeddingModel?: string;\n embeddingTimeoutMs?: number;\n chatTimeoutMs?: number;\n}\n\nexport interface ChatGenerateRequest {\n input: string;\n systemPrompt?: string;\n model?: string;\n temperature?: number;\n}\n\nexport interface ChatGenerateResult {\n text: string;\n model?: string;\n}\n\nexport interface ModelHub {\n generate(input: ChatGenerateRequest): Promise<ChatGenerateResult>;\n embed(input: EmbedRequest): Promise<EmbedResult>;\n}\n\nfunction getDefaultLlmConfig(llmSection: unknown): LLMConfig | null {\n const parsed = parseLlmSection(llmSection ?? null);\n const config =\n parsed.configs.find((c: LLMConfig) => c.id === parsed.defaultId) ??\n parsed.configs[0] ??\n null;\n return config;\n}\n\nexport function createModelHub(options: CreateModelHubOptions = {}): ModelHub {\n const baseCfg = getDefaultLlmConfig(options.llmSection);\n const defaultBaseUrl = (\n options.embeddingBaseURL ??\n baseCfg?.baseURL ??\n DEFAULT_BASE_URL\n ).replace(/\\/$/, \"\");\n const defaultApiKey =\n options.embeddingApiKey ??\n baseCfg?.apiKey ??\n process.env.OPENAI_API_KEY;\n const defaultEmbeddingModel =\n options.embeddingModel ??\n (baseCfg?.options && typeof baseCfg.options.embeddingModel === \"string\"\n ? baseCfg.options.embeddingModel\n : undefined) ??\n baseCfg?.model ??\n process.env.OPENAI_EMBEDDING_MODEL ??\n DEFAULT_EMBEDDING_MODEL;\n const defaultChatModel =\n baseCfg?.model ??\n process.env.OPENAI_MODEL ??\n DEFAULT_CHAT_MODEL;\n const embeddingTimeoutMs = options.embeddingTimeoutMs;\n const chatTimeoutMs = options.chatTimeoutMs;\n\n return {\n async generate(input: ChatGenerateRequest): Promise<ChatGenerateResult> {\n const messages: Array<{ role: \"system\" | \"user\" | \"assistant\"; content: string }> = [];\n if (typeof input.systemPrompt === \"string\" && input.systemPrompt.trim() !== \"\") {\n messages.push({ role: \"system\", content: input.systemPrompt.trim() });\n }\n messages.push({ role: \"user\", content: input.input });\n const result = await chatCompletionViaOpenAICompatibleApi(\n {\n baseURL: defaultBaseUrl,\n apiKey: defaultApiKey,\n model: defaultChatModel,\n timeoutMs: chatTimeoutMs,\n },\n {\n messages,\n model: input.model,\n temperature: input.temperature,\n }\n );\n return {\n text: result.text,\n model:\n typeof input.model === \"string\" && input.model.trim() !== \"\"\n ? input.model\n : result.model ?? baseCfg?.model,\n };\n },\n async embed(input: EmbedRequest): Promise<EmbedResult> {\n const result = await embedViaOpenAICompatibleApi(\n {\n baseURL: defaultBaseUrl,\n apiKey: defaultApiKey,\n model: defaultEmbeddingModel,\n timeoutMs: embeddingTimeoutMs,\n },\n { input: input.input, model: input.model }\n );\n return {\n vectors: result.vectors,\n dimensions: result.dimensions,\n model: result.model,\n };\n },\n };\n}\n"],"mappings":"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","names":["isLocalBaseUrl"]}
package/dist/npm/index.js CHANGED
@@ -16,8 +16,7 @@ import {
16
16
  resolveLatestVersionFromRegistry,
17
17
  resolveNpmPackageVersion,
18
18
  runNpmCommand
19
- } from "../chunk-K3JR2N4E.js";
20
- import "../chunk-PZ5AY32C.js";
19
+ } from "../chunk-KE7IMUSA.js";
21
20
  export {
22
21
  NPM_PROTOCOL_PREFIX,
23
22
  assertNpmCommandSuccess,
@@ -1,9 +1,7 @@
1
- import "../chunk-HCU4AWIV.js";
2
1
  import {
3
2
  getChatModelFactory,
4
3
  registerChatModelProvider
5
4
  } from "../chunk-G7MKWPEI.js";
6
- import "../chunk-PZ5AY32C.js";
7
5
  export {
8
6
  getChatModelFactory,
9
7
  registerChatModelProvider
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@easynet/agent-model",
3
- "version": "1.0.67",
3
+ "version": "1.0.69",
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": {
@@ -12,38 +12,6 @@
12
12
  ".": {
13
13
  "types": "./dist/index.d.ts",
14
14
  "import": "./dist/index.js"
15
- },
16
- "./config": {
17
- "types": "./dist/config/index.d.ts",
18
- "import": "./dist/config/index.js"
19
- },
20
- "./langchain": {
21
- "types": "./dist/langchain/index.d.ts",
22
- "import": "./dist/langchain/index.js"
23
- },
24
- "./model": {
25
- "types": "./dist/model/index.d.ts",
26
- "import": "./dist/model/index.js"
27
- },
28
- "./registry": {
29
- "types": "./dist/registry/index.d.ts",
30
- "import": "./dist/registry/index.js"
31
- },
32
- "./extensions": {
33
- "types": "./dist/extensions/index.d.ts",
34
- "import": "./dist/extensions/index.js"
35
- },
36
- "./connectivity": {
37
- "types": "./dist/connectivity/index.d.ts",
38
- "import": "./dist/connectivity/index.js"
39
- },
40
- "./npm": {
41
- "types": "./dist/npm/index.d.ts",
42
- "import": "./dist/npm/index.js"
43
- },
44
- "./cli": {
45
- "types": "./dist/cli/index.d.ts",
46
- "import": "./dist/cli/index.js"
47
15
  }
48
16
  },
49
17
  "scripts": {
@@ -1,83 +0,0 @@
1
- import {
2
- clearYamlFileCache,
3
- loadLlmConfig,
4
- loadModelConfig,
5
- loadYamlFile,
6
- loadYamlFileSync,
7
- parseLlmYaml,
8
- parseYamlContent,
9
- substituteEnv
10
- } from "./chunk-3HA2CHZN.js";
11
- import {
12
- parseLlmSection
13
- } from "./chunk-SPDXNDDD.js";
14
- import {
15
- __export
16
- } from "./chunk-PZ5AY32C.js";
17
-
18
- // src/config/index.ts
19
- var config_exports = {};
20
- __export(config_exports, {
21
- clearYamlFileCache: () => clearYamlFileCache,
22
- createModelConfig: () => createModelConfig,
23
- loadLlmConfig: () => loadLlmConfig,
24
- loadModelRuntimeConfig: () => loadModelRuntimeConfig,
25
- loadYamlConfig: () => loadYamlConfig,
26
- loadYamlFile: () => loadYamlFile,
27
- loadYamlFileSync: () => loadYamlFileSync,
28
- normalizeAgentModelConfigRef: () => normalizeAgentModelConfigRef,
29
- parseLlmSection: () => parseLlmSection,
30
- parseLlmYaml: () => parseLlmYaml,
31
- parseYamlContent: () => parseYamlContent,
32
- substituteEnv: () => substituteEnv
33
- });
34
- import { join } from "path";
35
- import { deepMerge } from "@easynet/agent-common";
36
-
37
- // src/config/yaml.ts
38
- function loadYamlConfig(filePath) {
39
- try {
40
- const parsed = loadYamlFileSync(filePath, {
41
- substituteEnv: true,
42
- missingEnv: "keep",
43
- cache: true
44
- });
45
- return parsed ?? {};
46
- } catch (e) {
47
- const msg = e instanceof Error ? e.message : String(e);
48
- throw new Error(`Failed to load YAML config from ${filePath}: ${msg}`, { cause: e });
49
- }
50
- }
51
-
52
- // src/config/ref.ts
53
- function asObject(input) {
54
- return typeof input === "object" && input !== null ? input : void 0;
55
- }
56
- function normalizeAgentModelConfigRef(raw) {
57
- if (typeof raw === "string" && raw.trim().length > 0) return { ref: raw.trim() };
58
- const obj = asObject(raw);
59
- if (!obj) return {};
60
- if (typeof obj.ref === "string" && obj.ref.trim().length > 0) return { ref: obj.ref.trim() };
61
- return {};
62
- }
63
-
64
- // src/config/index.ts
65
- function loadModelRuntimeConfig(options = {}) {
66
- const configPath = options.configPath ?? join(process.cwd(), "model.yaml");
67
- return loadModelConfig(configPath, options.loadOptions);
68
- }
69
- function createModelConfig(options = {}) {
70
- const base = loadModelRuntimeConfig(options);
71
- if (!base) return base;
72
- if (!options.overrides) return base;
73
- return deepMerge({}, base, options.overrides);
74
- }
75
-
76
- export {
77
- loadYamlConfig,
78
- normalizeAgentModelConfigRef,
79
- loadModelRuntimeConfig,
80
- createModelConfig,
81
- config_exports
82
- };
83
- //# sourceMappingURL=chunk-5QOKZ2JF.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/config/index.ts","../src/config/yaml.ts","../src/config/ref.ts"],"sourcesContent":["import { join } from \"node:path\";\nimport { deepMerge } from \"@easynet/agent-common\";\nimport { loadModelConfig, type LoadLlmConfigOptions, type ModelConfigResult } from \"./loader.js\";\n\nexport { 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, ModelConfigResult } from \"./loader.js\";\nexport type { AgentModelConfigRef } from \"./ref.js\";\n\nexport interface LoadModelConfigOptions {\n configPath?: string;\n loadOptions?: LoadLlmConfigOptions;\n}\n\nexport interface CreateModelConfigOptions extends LoadModelConfigOptions {\n overrides?: Partial<ModelConfigResult>;\n}\n\nexport function loadModelRuntimeConfig(options: LoadModelConfigOptions = {}): ModelConfigResult | null {\n const configPath = options.configPath ?? join(process.cwd(), \"model.yaml\");\n return loadModelConfig(configPath, options.loadOptions);\n}\n\nexport function createModelConfig(options: CreateModelConfigOptions = {}): ModelConfigResult | null {\n const base = loadModelRuntimeConfig(options);\n if (!base) return base;\n if (!options.overrides) return base;\n return deepMerge({} as ModelConfigResult, base, options.overrides);\n}\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;AAAA;AAAA;AAAA,SAAS,YAAY;AACrB,SAAS,iBAAiB;;;ACSnB,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;;;AFYO,SAAS,uBAAuB,UAAkC,CAAC,GAA6B;AACrG,QAAM,aAAa,QAAQ,cAAc,KAAK,QAAQ,IAAI,GAAG,YAAY;AACzE,SAAO,gBAAgB,YAAY,QAAQ,WAAW;AACxD;AAEO,SAAS,kBAAkB,UAAoC,CAAC,GAA6B;AAClG,QAAM,OAAO,uBAAuB,OAAO;AAC3C,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,CAAC,QAAQ,UAAW,QAAO;AAC/B,SAAO,UAAU,CAAC,GAAwB,MAAM,QAAQ,SAAS;AACnE;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/langchain/index.ts","../src/langchain/openai-compatible.ts","../src/langchain/tool-choice.ts"],"sourcesContent":["/**\n * Simple LangChain module: create ChatOpenAI from llm config.\n * Extensions can register custom ChatModel factories via the registry.\n */\n\nimport type { BaseChatModel } from \"@langchain/core/language_models/chat_models\";\nimport { parseLlmSection } from \"../model/llm-parser.js\";\nimport type { LLMConfig } from \"../model/types.js\";\nimport { getChatModelFactory } from \"../registry/chat-model.js\";\nimport { createChatOpenAI } from \"./openai-compatible.js\";\nimport type { Agent } from \"node:http\";\n\nconst DEFAULT_MODEL = \"gpt-4o-mini\";\n\nexport interface CreateChatModelOptions {\n llmSection?: unknown;\n modelEnv?: string;\n apiKeyEnv?: string;\n}\n\nexport { applyToolChoiceAuto } from \"./tool-choice.js\";\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\n/**\n * Create a LangChain ChatModel from agent config llm section.\n * Uses extension-registered factory when available; otherwise creates ChatOpenAI.\n */\nexport function createChatModelFromLlmConfig(\n options: CreateChatModelOptions = {}\n): BaseChatModel {\n const { llmSection, modelEnv, apiKeyEnv } = options;\n\n let defaultId: string;\n let configs: LLMConfig[];\n\n try {\n const parsed = parseLlmSection(llmSection ?? null);\n defaultId = parsed.defaultId;\n configs = parsed.configs;\n } catch (e) {\n throw normalizeError(e, \"Failed to parse llm section\");\n }\n\n const config = configs.find((c) => c.id === defaultId) ?? configs[0];\n\n // No config? Use default OpenAI\n if (!config) {\n const model = modelEnv ?? process.env.OPENAI_MODEL ?? DEFAULT_MODEL;\n const apiKey = apiKeyEnv ?? process.env.OPENAI_API_KEY;\n\n return createChatOpenAI({\n model,\n temperature: 0,\n ...(apiKey ? { apiKey } : {}),\n });\n }\n\n // Check for registered custom factory\n const provider = config.provider ?? \"openai\";\n const factory = getChatModelFactory(provider);\n\n if (factory) {\n try {\n return factory({\n ...config,\n model: modelEnv ?? config.model ?? DEFAULT_MODEL,\n temperature: typeof config.temperature === \"number\" ? config.temperature : 0,\n });\n } catch (e) {\n throw normalizeError(e, `Failed to create ChatModel for provider \"${provider}\"`);\n }\n }\n\n // Create standard ChatOpenAI for OpenAI-compatible provider\n const model = modelEnv ?? config.model ?? process.env.OPENAI_MODEL ?? DEFAULT_MODEL;\n let apiKey = apiKeyEnv ?? config.apiKey ?? process.env.OPENAI_API_KEY;\n let baseURL = config.baseURL;\n\n // Ensure baseURL ends with /v1\n if (baseURL && !baseURL.replace(/\\/$/, \"\").endsWith(\"/v1\")) {\n baseURL = baseURL.replace(/\\/$/, \"\") + \"/v1\";\n }\n\n // For local providers without API keys, use a placeholder\n if (baseURL && !apiKey) {\n apiKey = \"not-needed\";\n }\n\n const temperature = typeof config.temperature === \"number\" ? config.temperature : 0;\n\n // Extract options\n const opts = config.options as Record<string, unknown> | undefined;\n const defaultHeaders = opts?.defaultHeaders as Record<string, string> | undefined;\n const defaultQuery = opts?.defaultQuery as Record<string, string> | undefined;\n const httpAgent = opts?.httpAgent as Agent | undefined;\n\n return createChatOpenAI({\n model,\n temperature,\n baseURL,\n apiKey,\n defaultHeaders,\n defaultQuery,\n httpAgent,\n });\n}\n","/**\n * Create ChatOpenAI from config - works with any OpenAI-compatible provider.\n * This is the ONLY place we create ChatOpenAI instances.\n */\n\nimport { ChatOpenAI } from \"@langchain/openai\";\nimport type { BaseChatModel } from \"@langchain/core/language_models/chat_models\";\nimport type { Agent } from \"node:http\";\n\nexport interface CreateChatOpenAIOptions {\n baseURL?: string;\n model: string;\n temperature?: number;\n apiKey?: string;\n defaultHeaders?: Record<string, string>;\n defaultQuery?: Record<string, string>;\n httpAgent?: Agent;\n}\n\n/**\n * Create ChatOpenAI from options.\n * Works with OpenAI and any OpenAI-compatible endpoint (CIS, Ollama, etc.).\n */\nexport function createChatOpenAI(options: CreateChatOpenAIOptions): BaseChatModel {\n const {\n baseURL,\n model,\n temperature = 0,\n apiKey,\n defaultHeaders,\n defaultQuery,\n httpAgent,\n } = options;\n\n const config: {\n baseURL?: string;\n defaultHeaders?: Record<string, string>;\n defaultQuery?: Record<string, string>;\n httpAgent?: Agent;\n } = {};\n\n if (baseURL) config.baseURL = baseURL;\n if (defaultHeaders) config.defaultHeaders = defaultHeaders;\n if (defaultQuery) config.defaultQuery = defaultQuery;\n if (httpAgent) config.httpAgent = httpAgent;\n\n return new ChatOpenAI({\n model,\n temperature,\n ...(apiKey ? { apiKey } : {}),\n ...(Object.keys(config).length > 0 ? { configuration: config } : {}),\n });\n}\n","interface ToolChoicePatchTarget {\n __agentLlmToolChoicePatched?: boolean;\n defaultOptions?: { tools?: unknown[] };\n bindTools?: (tools: unknown, opts?: Record<string, unknown>) => unknown;\n withConfig?: (config: Record<string, unknown>) => unknown;\n invoke?: (input: unknown, options?: Record<string, unknown>) => unknown;\n stream?: (input: unknown, options?: Record<string, unknown>) => unknown;\n}\n\nfunction hasTools(model: ToolChoicePatchTarget, options?: Record<string, unknown>): boolean {\n const optTools = options?.tools;\n if (Array.isArray(optTools) && optTools.length > 0) return true;\n const defaultTools = model.defaultOptions?.tools;\n return Array.isArray(defaultTools) && defaultTools.length > 0;\n}\n\nfunction sanitizeOptions(\n model: ToolChoicePatchTarget,\n options?: Record<string, unknown>\n): Record<string, unknown> | undefined {\n if (!options) return options;\n if (options.tool_choice !== \"none\") return options;\n if (!hasTools(model, options)) return options;\n return { ...options, tool_choice: \"auto\" };\n}\n\n/**\n * Force tool_choice to \"auto\" when tools are present.\n * Patches bindTools/withConfig/invoke/stream in-place for compatibility with providers\n * that default to tool_choice: \"none\".\n */\nexport function applyToolChoiceAuto(\n model: { bindTools?: (tools: unknown, opts?: Record<string, unknown>) => unknown }\n): void {\n const m = model as ToolChoicePatchTarget;\n if (m.__agentLlmToolChoicePatched) return;\n m.__agentLlmToolChoicePatched = true;\n\n const origBindTools = m.bindTools?.bind(model);\n if (origBindTools) {\n m.bindTools = function (tools: unknown, opts?: Record<string, unknown>) {\n const bound = origBindTools(tools, { ...opts, tool_choice: \"auto\" });\n applyToolChoiceAuto(\n bound as { bindTools?: (tools: unknown, opts?: Record<string, unknown>) => unknown }\n );\n return bound;\n };\n }\n\n const origWithConfig = m.withConfig?.bind(model);\n if (origWithConfig) {\n m.withConfig = function (config: Record<string, unknown>) {\n const sanitized = sanitizeOptions(this as ToolChoicePatchTarget, config) ?? config;\n const next = origWithConfig(sanitized);\n applyToolChoiceAuto(\n next as { bindTools?: (tools: unknown, opts?: Record<string, unknown>) => unknown }\n );\n return next;\n };\n }\n\n const origInvoke = m.invoke?.bind(model);\n if (origInvoke) {\n m.invoke = function (input: unknown, options?: Record<string, unknown>) {\n return origInvoke(input, sanitizeOptions(this as ToolChoicePatchTarget, options));\n };\n }\n\n const origStream = m.stream?.bind(model);\n if (origStream) {\n m.stream = function (input: unknown, options?: Record<string, unknown>) {\n return origStream(input, sanitizeOptions(this as ToolChoicePatchTarget, options));\n };\n }\n}\n"],"mappings":"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","names":["model","apiKey"]}
@@ -1,260 +0,0 @@
1
- import {
2
- loadModelConfig
3
- } from "./chunk-3HA2CHZN.js";
4
- import {
5
- buildUnreachableError,
6
- checkEndpointConnectivity
7
- } from "./chunk-EPVJLBGC.js";
8
- import {
9
- resolveLlmSectionWithNpm
10
- } from "./chunk-XSR4TAZ7.js";
11
- import {
12
- createChatModelFromLlmConfig
13
- } from "./chunk-CCGNXMFC.js";
14
- import {
15
- parseLlmSection
16
- } from "./chunk-SPDXNDDD.js";
17
-
18
- // src/cli/index.ts
19
- var cli_exports = {};
20
-
21
- // src/api/create-agent-llm.ts
22
- import { join } from "path";
23
- function applyDefaultToolChoice(model) {
24
- const m = model;
25
- const orig = m.bindTools?.bind(model);
26
- if (!orig) return;
27
- m.bindTools = function(tools2, opts) {
28
- return orig(tools2, { ...opts, tool_choice: "auto" });
29
- };
30
- }
31
- var CIS_DEFAULT_RESOLVE_HOST = "s0010-ml-https.s0010.us-west-2.awswd";
32
- var CIS_DEFAULT_RESOLVE_IP = "10.210.98.124";
33
- function buildEndpointConnectivityOptions(config) {
34
- const opts = config.options ?? config;
35
- const provider = typeof config.provider === "string" ? config.provider : "";
36
- const baseURL = config.baseURL;
37
- const isCis = provider === "cis" || provider.includes("cis");
38
- const useCisDefault = isCis && baseURL.includes(CIS_DEFAULT_RESOLVE_HOST) && opts?.resolveHost == null;
39
- const resolveHost = opts?.resolveHost != null && typeof opts.resolveHost.from === "string" ? opts.resolveHost : useCisDefault ? { from: CIS_DEFAULT_RESOLVE_HOST, to: CIS_DEFAULT_RESOLVE_IP } : void 0;
40
- const host = typeof opts?.host === "string" ? opts.host : resolveHost ? resolveHost.from : void 0;
41
- if (resolveHost == null && host == null) return void 0;
42
- const verifySSL = opts?.verifySSL === true;
43
- const bypassAuth = opts?.bypassAuth !== false;
44
- return {
45
- resolveHost,
46
- host,
47
- verifySSL: resolveHost != null ? false : verifySSL ? true : void 0,
48
- bypassAuth: bypassAuth ? true : void 0,
49
- featureKey: typeof opts?.featureKey === "string" ? opts.featureKey : void 0
50
- };
51
- }
52
- function resolveDefaultConfigPath() {
53
- return join(process.cwd(), "model.yaml");
54
- }
55
- function normalizeOptions(configPathOrOptions) {
56
- if (configPathOrOptions == null) return {};
57
- if (typeof configPathOrOptions === "string") return { configPath: configPathOrOptions };
58
- return configPathOrOptions;
59
- }
60
- function normalizeError(e, context) {
61
- if (e instanceof Error) return new Error(`${context}: ${e.message}`, { cause: e });
62
- return new Error(`${context}: ${String(e)}`);
63
- }
64
- async function ensureConnectivity(resolvedLlmSection, options) {
65
- let configs;
66
- try {
67
- const parsed = parseLlmSection(resolvedLlmSection ?? null);
68
- configs = parsed.configs.filter(
69
- (c) => typeof c.baseURL === "string" && c.baseURL.length > 0 && (c.baseURL.startsWith("http://") || c.baseURL.startsWith("https://")) && !c.baseURL.includes("${")
70
- );
71
- } catch {
72
- return;
73
- }
74
- const shouldCheck = options.checkConnectivity !== false && configs.length > 0;
75
- if (!shouldCheck) return;
76
- const report = (status) => options.onConnectionStatus?.(status);
77
- const timeoutMs = options.connectivityTimeoutMs ?? 8e3;
78
- for (const config of configs) {
79
- const { id, baseURL } = config;
80
- report({
81
- phase: "checking",
82
- endpointId: id,
83
- baseURL,
84
- message: "Checking connection..."
85
- });
86
- const endpointOpts = buildEndpointConnectivityOptions(config);
87
- const result = await checkEndpointConnectivity(baseURL, {
88
- timeoutMs,
89
- ...endpointOpts
90
- });
91
- if (result.reachable) {
92
- report({
93
- phase: "reachable",
94
- endpointId: id,
95
- baseURL,
96
- message: result.message ?? "Connected"
97
- });
98
- } else {
99
- report({
100
- phase: "unreachable",
101
- endpointId: id,
102
- baseURL,
103
- message: result.message ?? "Unreachable"
104
- });
105
- throw new Error(buildUnreachableError(id, baseURL, result.message));
106
- }
107
- }
108
- }
109
- async function createAgentLlm(configPathOrOptions) {
110
- try {
111
- const options = normalizeOptions(configPathOrOptions);
112
- const configPath = options.configPath ?? resolveDefaultConfigPath();
113
- const modelConfig = loadModelConfig(configPath);
114
- if (modelConfig?.llm == null) {
115
- throw new Error(
116
- `No LLM config at ${configPath}. Add model.yaml in the current directory, or pass configPath.`
117
- );
118
- }
119
- const resolvedSection = await resolveLlmSectionWithNpm(modelConfig.llm, {
120
- installNpmIfMissing: options.installNpmIfMissing !== false,
121
- cwd: process.cwd()
122
- });
123
- const checkConnectivity = options.checkConnectivity ?? modelConfig.runtime.check_connectivity;
124
- await ensureConnectivity(resolvedSection, {
125
- checkConnectivity,
126
- onConnectionStatus: options.onConnectionStatus,
127
- connectivityTimeoutMs: options.connectivityTimeoutMs
128
- });
129
- const model = createChatModelFromLlmConfig({ llmSection: resolvedSection });
130
- applyDefaultToolChoice(model);
131
- return model;
132
- } catch (e) {
133
- if (e instanceof Error && e.message.includes("No LLM config")) throw e;
134
- if (e instanceof Error && e.message.includes("Cannot connect to")) throw e;
135
- throw normalizeError(e, "createAgentLlm failed");
136
- }
137
- }
138
-
139
- // src/cli/utils.ts
140
- function messageContentToString(content) {
141
- if (typeof content === "string") return content;
142
- if (Array.isArray(content)) {
143
- return content.map((c) => "text" in c && c.text ? c.text : "").join("");
144
- }
145
- return String(content ?? "");
146
- }
147
-
148
- // src/cli/index.ts
149
- import { tool } from "@langchain/core/tools";
150
- import { z } from "zod";
151
- import { HumanMessage, ToolMessage } from "@langchain/core/messages";
152
- import { fileURLToPath } from "url";
153
- function parseArgv() {
154
- const args = process.argv.slice(2);
155
- let configPath;
156
- let useTools = false;
157
- const rest = [];
158
- for (let i = 0; i < args.length; i++) {
159
- if (args[i] === "--config" && args[i + 1]) {
160
- configPath = args[i + 1];
161
- i++;
162
- } else if (args[i] === "--tools") {
163
- useTools = true;
164
- } else {
165
- rest.push(args[i]);
166
- }
167
- }
168
- const query = rest.join(" ").trim() || "hi";
169
- return { configPath, useTools, query };
170
- }
171
- var getWeather = tool(
172
- (input) => {
173
- const loc = input.location.toLowerCase();
174
- if (["sf", "sf bay"].includes(loc)) return "It's 60\xB0F and foggy in the Bay Area.";
175
- if (["ny", "new york"].includes(loc)) return "It's 72\xB0F and partly cloudy in New York.";
176
- return `Weather for ${input.location}: 70\xB0F and sunny.`;
177
- },
178
- {
179
- name: "get_weather",
180
- description: "Get the current weather for a location.",
181
- schema: z.object({
182
- location: z.string().describe("City or place name (e.g. SF, New York)")
183
- })
184
- }
185
- );
186
- var addNumbers = tool(
187
- (input) => String(input.a + input.b),
188
- {
189
- name: "add_numbers",
190
- description: "Add two numbers.",
191
- schema: z.object({
192
- a: z.number().describe("First number"),
193
- b: z.number().describe("Second number")
194
- })
195
- }
196
- );
197
- var tools = [getWeather, addNumbers];
198
- var toolsByName = new Map(tools.map((t) => [t.name, t]));
199
- var MAX_TURNS = 10;
200
- async function runSimpleChat(model, query) {
201
- const messages = [new HumanMessage(query)];
202
- const response = await model.invoke(messages);
203
- return messageContentToString(response.content);
204
- }
205
- async function runAgentWithTools(model, query) {
206
- const withTools = model.bindTools?.(tools, { tool_choice: "auto" });
207
- const messages = [new HumanMessage(query)];
208
- if (!withTools) return runSimpleChat(model, query);
209
- for (let turn = 0; turn < MAX_TURNS; turn++) {
210
- const response = await withTools.invoke(messages);
211
- const aiMessage = response;
212
- if (!aiMessage.tool_calls?.length) {
213
- return messageContentToString(aiMessage.content);
214
- }
215
- messages.push(aiMessage);
216
- for (const tc of aiMessage.tool_calls) {
217
- const id = tc.id ?? `call_${turn}_${tc.name}`;
218
- const toolFn = toolsByName.get(tc.name);
219
- let result;
220
- if (toolFn) {
221
- try {
222
- const out = await toolFn.invoke(
223
- tc.args
224
- );
225
- result = typeof out === "string" ? out : JSON.stringify(out);
226
- } catch (err) {
227
- result = `Error: ${err instanceof Error ? err.message : String(err)}`;
228
- }
229
- } else {
230
- result = `Unknown tool: ${tc.name}`;
231
- }
232
- messages.push(new ToolMessage({ content: result, tool_call_id: id }));
233
- }
234
- }
235
- return "Agent reached max turns without a final answer.";
236
- }
237
- async function main() {
238
- const { configPath, useTools, query } = parseArgv();
239
- const model = await createAgentLlm(configPath ? { configPath } : void 0);
240
- console.log("Query:", query);
241
- console.log("---");
242
- const answer = useTools ? await runAgentWithTools(model, query) : await runSimpleChat(model, query);
243
- console.log("Answer:", answer);
244
- console.log("---");
245
- console.log("Done.");
246
- }
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
- }
255
-
256
- export {
257
- createAgentLlm,
258
- cli_exports
259
- };
260
- //# sourceMappingURL=chunk-CJK5NAOX.js.map