@easynet/agent-llm 1.0.15 → 1.0.25
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/api/create-agent-llm.d.ts +4 -18
- package/dist/api/create-agent-llm.d.ts.map +1 -1
- package/dist/api/get-default-llm-config.d.ts +16 -0
- package/dist/api/get-default-llm-config.d.ts.map +1 -0
- package/dist/{chunk-AZDHRCIM.js → chunk-H4UQIDGT.js} +171 -338
- package/dist/chunk-H4UQIDGT.js.map +1 -0
- package/dist/cli/index.d.ts +0 -7
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +7 -12
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/utils.d.ts +12 -0
- package/dist/cli/utils.d.ts.map +1 -0
- package/dist/config/index.d.ts +1 -3
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/loader.d.ts +0 -14
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/parser.d.ts +0 -3
- package/dist/config/parser.d.ts.map +1 -1
- package/dist/config/yaml.d.ts +9 -0
- package/dist/config/yaml.d.ts.map +1 -0
- package/dist/connectivity/check.d.ts +0 -23
- package/dist/connectivity/check.d.ts.map +1 -1
- package/dist/connectivity/index.d.ts +2 -4
- package/dist/connectivity/index.d.ts.map +1 -1
- package/dist/connectivity/types.d.ts +0 -11
- package/dist/connectivity/types.d.ts.map +1 -1
- package/dist/extensions/index.d.ts +3 -3
- package/dist/extensions/index.d.ts.map +1 -1
- package/dist/extensions/loader.d.ts +1 -17
- package/dist/extensions/loader.d.ts.map +1 -1
- package/dist/extensions/npm-protocol.d.ts +7 -33
- package/dist/extensions/npm-protocol.d.ts.map +1 -1
- package/dist/index.d.ts +18 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +56 -38
- package/dist/index.js.map +1 -1
- package/dist/langchain/index.d.ts +13 -3
- package/dist/langchain/index.d.ts.map +1 -1
- package/dist/langchain/openai-compatible.d.ts +21 -0
- package/dist/langchain/openai-compatible.d.ts.map +1 -0
- package/dist/registry/chat-model.d.ts +1 -8
- package/dist/registry/chat-model.d.ts.map +1 -1
- package/dist/registry/index.d.ts +0 -5
- package/dist/registry/index.d.ts.map +1 -1
- package/dist/types.d.ts +12 -166
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/deep-merge.d.ts +5 -0
- package/dist/utils/deep-merge.d.ts.map +1 -0
- package/package.json +11 -9
- package/dist/chunk-AZDHRCIM.js.map +0 -1
- package/dist/langchain/adapter.d.ts +0 -21
- package/dist/langchain/adapter.d.ts.map +0 -1
- package/dist/providers/index.d.ts +0 -7
- package/dist/providers/index.d.ts.map +0 -1
- package/dist/providers/openai.d.ts +0 -9
- package/dist/providers/openai.d.ts.map +0 -1
- package/dist/registry/client.d.ts +0 -13
- package/dist/registry/client.d.ts.map +0 -1
|
@@ -153,205 +153,29 @@ function loadLlmConfig(filePath, options = {}) {
|
|
|
153
153
|
}
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
-
// src/
|
|
157
|
-
import
|
|
158
|
-
function
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
if (
|
|
170
|
-
|
|
171
|
-
if (
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
}))
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
return { role: m.role, content: m.content };
|
|
183
|
-
}
|
|
184
|
-
function createOpenAIChatClient(config) {
|
|
185
|
-
const client = new OpenAI(createOpenAIClientOptions(config));
|
|
186
|
-
const model = config.model ?? process.env.OPENAI_MODEL ?? "gpt-4o-mini";
|
|
187
|
-
const temperature = config.temperature ?? 0;
|
|
188
|
-
return {
|
|
189
|
-
id: config.id,
|
|
190
|
-
type: "chat",
|
|
191
|
-
async chat(messages) {
|
|
192
|
-
const resp = await client.chat.completions.create({
|
|
193
|
-
model,
|
|
194
|
-
temperature,
|
|
195
|
-
messages: messages.map((m) => ({ role: m.role, content: m.content }))
|
|
196
|
-
});
|
|
197
|
-
const content = resp.choices[0]?.message?.content ?? "";
|
|
198
|
-
const usage = resp.usage ? { promptTokens: resp.usage.prompt_tokens, completionTokens: resp.usage.completion_tokens } : void 0;
|
|
199
|
-
return { content, usage };
|
|
200
|
-
},
|
|
201
|
-
async *chatStream(messages) {
|
|
202
|
-
const stream = await client.chat.completions.create({
|
|
203
|
-
model,
|
|
204
|
-
temperature,
|
|
205
|
-
messages: messages.map((m) => ({ role: m.role, content: m.content })),
|
|
206
|
-
stream: true
|
|
207
|
-
});
|
|
208
|
-
let usage;
|
|
209
|
-
for await (const chunk of stream) {
|
|
210
|
-
const delta = chunk.choices[0]?.delta;
|
|
211
|
-
const content = delta?.content ?? "";
|
|
212
|
-
const finishReason = chunk.choices[0]?.finish_reason;
|
|
213
|
-
if (chunk.usage) {
|
|
214
|
-
usage = {
|
|
215
|
-
promptTokens: chunk.usage.prompt_tokens,
|
|
216
|
-
completionTokens: chunk.usage.completion_tokens
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
yield {
|
|
220
|
-
content,
|
|
221
|
-
done: finishReason !== null && finishReason !== void 0,
|
|
222
|
-
usage
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
|
-
},
|
|
226
|
-
async chatWithTools(messages, tools, _options) {
|
|
227
|
-
const resp = await client.chat.completions.create({
|
|
228
|
-
model,
|
|
229
|
-
temperature,
|
|
230
|
-
messages: messages.map(serializeMessage),
|
|
231
|
-
tools: tools.map((t) => ({
|
|
232
|
-
type: "function",
|
|
233
|
-
function: {
|
|
234
|
-
name: t.function.name,
|
|
235
|
-
description: t.function.description,
|
|
236
|
-
parameters: t.function.parameters ?? void 0
|
|
237
|
-
}
|
|
238
|
-
}))
|
|
239
|
-
});
|
|
240
|
-
const msg = resp.choices[0]?.message;
|
|
241
|
-
const usage = resp.usage ? { promptTokens: resp.usage.prompt_tokens, completionTokens: resp.usage.completion_tokens } : void 0;
|
|
242
|
-
return {
|
|
243
|
-
message: {
|
|
244
|
-
role: "assistant",
|
|
245
|
-
content: msg?.content ?? null,
|
|
246
|
-
tool_calls: msg?.tool_calls?.map((tc) => ({
|
|
247
|
-
id: tc.id,
|
|
248
|
-
type: "function",
|
|
249
|
-
function: {
|
|
250
|
-
name: tc.function?.name ?? "",
|
|
251
|
-
arguments: tc.function?.arguments ?? ""
|
|
252
|
-
}
|
|
253
|
-
}))
|
|
254
|
-
},
|
|
255
|
-
usage
|
|
256
|
-
};
|
|
257
|
-
},
|
|
258
|
-
async *chatWithToolsStream(messages, tools, _options) {
|
|
259
|
-
const stream = await client.chat.completions.create({
|
|
260
|
-
model,
|
|
261
|
-
temperature,
|
|
262
|
-
messages: messages.map(serializeMessage),
|
|
263
|
-
tools: tools.map((t) => ({
|
|
264
|
-
type: "function",
|
|
265
|
-
function: {
|
|
266
|
-
name: t.function.name,
|
|
267
|
-
description: t.function.description,
|
|
268
|
-
parameters: t.function.parameters ?? void 0
|
|
269
|
-
}
|
|
270
|
-
})),
|
|
271
|
-
stream: true,
|
|
272
|
-
stream_options: { include_usage: true }
|
|
273
|
-
});
|
|
274
|
-
let usage;
|
|
275
|
-
for await (const chunk of stream) {
|
|
276
|
-
const delta = chunk.choices[0]?.delta;
|
|
277
|
-
const finishReason = chunk.choices[0]?.finish_reason;
|
|
278
|
-
if (chunk.usage) {
|
|
279
|
-
usage = {
|
|
280
|
-
promptTokens: chunk.usage.prompt_tokens,
|
|
281
|
-
completionTokens: chunk.usage.completion_tokens
|
|
282
|
-
};
|
|
283
|
-
}
|
|
284
|
-
const toolCalls = delta?.tool_calls?.map((tc) => ({
|
|
285
|
-
index: tc.index,
|
|
286
|
-
id: tc.id,
|
|
287
|
-
type: tc.type,
|
|
288
|
-
function: tc.function ? {
|
|
289
|
-
name: tc.function.name,
|
|
290
|
-
arguments: tc.function.arguments
|
|
291
|
-
} : void 0
|
|
292
|
-
}));
|
|
293
|
-
yield {
|
|
294
|
-
delta: {
|
|
295
|
-
role: delta?.role,
|
|
296
|
-
content: delta?.content ?? null,
|
|
297
|
-
tool_calls: toolCalls
|
|
298
|
-
},
|
|
299
|
-
done: finishReason !== null && finishReason !== void 0,
|
|
300
|
-
usage
|
|
301
|
-
};
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
};
|
|
305
|
-
}
|
|
306
|
-
function createOpenAIImageClient(config) {
|
|
307
|
-
const client = new OpenAI(createOpenAIClientOptions(config));
|
|
308
|
-
const model = config.model ?? "dall-e-3";
|
|
309
|
-
return {
|
|
310
|
-
id: config.id,
|
|
311
|
-
type: "image",
|
|
312
|
-
async chat() {
|
|
313
|
-
throw new Error("OpenAI image model does not support chat; use generateImage()");
|
|
314
|
-
},
|
|
315
|
-
async generateImage(options) {
|
|
316
|
-
const resp = await client.images.generate({
|
|
317
|
-
model,
|
|
318
|
-
prompt: options.prompt,
|
|
319
|
-
size: options.size ?? "1024x1024",
|
|
320
|
-
n: options.n ?? 1,
|
|
321
|
-
response_format: "url"
|
|
322
|
-
});
|
|
323
|
-
const url = resp.data?.[0]?.url ?? void 0;
|
|
324
|
-
return { url };
|
|
325
|
-
}
|
|
326
|
-
};
|
|
327
|
-
}
|
|
328
|
-
function createOpenAIClient(config) {
|
|
329
|
-
if (config.type === "image") return createOpenAIImageClient(config);
|
|
330
|
-
return createOpenAIChatClient(config);
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
// src/providers/index.ts
|
|
334
|
-
var OPENAI_COMPATIBLE = "openai-compatible";
|
|
335
|
-
function createOpenAICompat(config) {
|
|
336
|
-
return createOpenAIClient(config);
|
|
337
|
-
}
|
|
338
|
-
var PROVIDERS = {
|
|
339
|
-
openai: createOpenAICompat,
|
|
340
|
-
[OPENAI_COMPATIBLE]: createOpenAICompat
|
|
341
|
-
};
|
|
342
|
-
function createClient(config) {
|
|
343
|
-
const p = (config.provider ?? "").toLowerCase();
|
|
344
|
-
const fn = PROVIDERS[p];
|
|
345
|
-
if (!fn) {
|
|
346
|
-
const supported = [.../* @__PURE__ */ new Set([...Object.keys(PROVIDERS), "extension providers"])].sort().join(", ");
|
|
347
|
-
throw new Error(
|
|
348
|
-
`Unsupported LLM provider: ${config.provider}. Supported: ${supported}.`
|
|
349
|
-
);
|
|
350
|
-
}
|
|
351
|
-
return fn(config);
|
|
352
|
-
}
|
|
353
|
-
function registerProvider(name, factory) {
|
|
354
|
-
PROVIDERS[name.toLowerCase()] = factory;
|
|
156
|
+
// src/langchain/openai-compatible.ts
|
|
157
|
+
import { ChatOpenAI } from "@langchain/openai";
|
|
158
|
+
function createChatOpenAI(options) {
|
|
159
|
+
const {
|
|
160
|
+
baseURL,
|
|
161
|
+
model,
|
|
162
|
+
temperature = 0,
|
|
163
|
+
apiKey,
|
|
164
|
+
defaultHeaders,
|
|
165
|
+
defaultQuery,
|
|
166
|
+
httpAgent
|
|
167
|
+
} = options;
|
|
168
|
+
const config = {};
|
|
169
|
+
if (baseURL) config.baseURL = baseURL;
|
|
170
|
+
if (defaultHeaders) config.defaultHeaders = defaultHeaders;
|
|
171
|
+
if (defaultQuery) config.defaultQuery = defaultQuery;
|
|
172
|
+
if (httpAgent) config.httpAgent = httpAgent;
|
|
173
|
+
return new ChatOpenAI({
|
|
174
|
+
model,
|
|
175
|
+
temperature,
|
|
176
|
+
...apiKey ? { apiKey } : {},
|
|
177
|
+
...Object.keys(config).length > 0 ? { configuration: config } : {}
|
|
178
|
+
});
|
|
355
179
|
}
|
|
356
180
|
|
|
357
181
|
// src/registry/chat-model.ts
|
|
@@ -363,14 +187,13 @@ function getChatModelFactory(providerName) {
|
|
|
363
187
|
return CHAT_MODEL_FACTORIES.get(providerName.toLowerCase());
|
|
364
188
|
}
|
|
365
189
|
|
|
366
|
-
// src/langchain/
|
|
367
|
-
import { ChatOpenAI } from "@langchain/openai";
|
|
190
|
+
// src/langchain/index.ts
|
|
368
191
|
var DEFAULT_MODEL = "gpt-4o-mini";
|
|
369
|
-
function
|
|
192
|
+
function normalizeError(e, context) {
|
|
370
193
|
if (e instanceof Error) return new Error(`${context}: ${e.message}`, { cause: e });
|
|
371
194
|
return new Error(`${context}: ${String(e)}`);
|
|
372
195
|
}
|
|
373
|
-
function createChatModelFromLlmConfig(options) {
|
|
196
|
+
function createChatModelFromLlmConfig(options = {}) {
|
|
374
197
|
const { llmSection, modelEnv, apiKeyEnv } = options;
|
|
375
198
|
let defaultId;
|
|
376
199
|
let configs;
|
|
@@ -379,61 +202,62 @@ function createChatModelFromLlmConfig(options) {
|
|
|
379
202
|
defaultId = parsed.defaultId;
|
|
380
203
|
configs = parsed.configs;
|
|
381
204
|
} catch (e) {
|
|
382
|
-
throw
|
|
205
|
+
throw normalizeError(e, "Failed to parse llm section");
|
|
383
206
|
}
|
|
384
|
-
const
|
|
385
|
-
if (!
|
|
207
|
+
const config = configs.find((c) => c.id === defaultId) ?? configs[0];
|
|
208
|
+
if (!config) {
|
|
386
209
|
const model2 = modelEnv ?? process.env.OPENAI_MODEL ?? DEFAULT_MODEL;
|
|
387
210
|
const apiKey2 = apiKeyEnv ?? process.env.OPENAI_API_KEY;
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
});
|
|
394
|
-
} catch (e) {
|
|
395
|
-
throw normalizeAgentLlMError(e, "agent-llm: failed to create default ChatOpenAI");
|
|
396
|
-
}
|
|
211
|
+
return createChatOpenAI({
|
|
212
|
+
model: model2,
|
|
213
|
+
temperature: 0,
|
|
214
|
+
...apiKey2 ? { apiKey: apiKey2 } : {}
|
|
215
|
+
});
|
|
397
216
|
}
|
|
398
|
-
const provider =
|
|
399
|
-
const
|
|
400
|
-
if (
|
|
401
|
-
const config = {
|
|
402
|
-
...defaultConfig,
|
|
403
|
-
model: modelEnv ?? defaultConfig.model,
|
|
404
|
-
temperature: typeof defaultConfig.temperature === "number" ? defaultConfig.temperature : 0
|
|
405
|
-
};
|
|
217
|
+
const provider = config.provider ?? "openai";
|
|
218
|
+
const factory = getChatModelFactory(provider);
|
|
219
|
+
if (factory) {
|
|
406
220
|
try {
|
|
407
|
-
return
|
|
221
|
+
return factory({
|
|
222
|
+
...config,
|
|
223
|
+
model: modelEnv ?? config.model ?? DEFAULT_MODEL,
|
|
224
|
+
temperature: typeof config.temperature === "number" ? config.temperature : 0
|
|
225
|
+
});
|
|
408
226
|
} catch (e) {
|
|
409
|
-
throw
|
|
227
|
+
throw normalizeError(e, `Failed to create ChatModel for provider "${provider}"`);
|
|
410
228
|
}
|
|
411
229
|
}
|
|
412
|
-
const model = modelEnv ??
|
|
413
|
-
let apiKey = apiKeyEnv ??
|
|
414
|
-
let baseURL =
|
|
230
|
+
const model = modelEnv ?? config.model ?? process.env.OPENAI_MODEL ?? DEFAULT_MODEL;
|
|
231
|
+
let apiKey = apiKeyEnv ?? config.apiKey ?? process.env.OPENAI_API_KEY;
|
|
232
|
+
let baseURL = config.baseURL;
|
|
415
233
|
if (baseURL && !baseURL.replace(/\/$/, "").endsWith("/v1")) {
|
|
416
234
|
baseURL = baseURL.replace(/\/$/, "") + "/v1";
|
|
417
235
|
}
|
|
418
|
-
if (baseURL && apiKey
|
|
419
|
-
apiKey = "
|
|
236
|
+
if (baseURL && !apiKey) {
|
|
237
|
+
apiKey = "not-needed";
|
|
420
238
|
}
|
|
421
|
-
const temperature = typeof
|
|
422
|
-
const
|
|
239
|
+
const temperature = typeof config.temperature === "number" ? config.temperature : 0;
|
|
240
|
+
const opts = config.options;
|
|
241
|
+
const defaultHeaders = opts?.defaultHeaders;
|
|
242
|
+
const defaultQuery = opts?.defaultQuery;
|
|
243
|
+
const httpAgent = opts?.httpAgent;
|
|
244
|
+
return createChatOpenAI({
|
|
423
245
|
model,
|
|
424
246
|
temperature,
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
}
|
|
431
|
-
throw normalizeAgentLlMError(e, "agent-llm: failed to create ChatOpenAI from config");
|
|
432
|
-
}
|
|
247
|
+
baseURL,
|
|
248
|
+
apiKey,
|
|
249
|
+
defaultHeaders,
|
|
250
|
+
defaultQuery,
|
|
251
|
+
httpAgent
|
|
252
|
+
});
|
|
433
253
|
}
|
|
434
254
|
|
|
255
|
+
// src/types.ts
|
|
256
|
+
var AGENT_LLM_PROVIDER_FIELD = "agentLlmProvider";
|
|
257
|
+
|
|
435
258
|
// src/extensions/loader.ts
|
|
436
259
|
import { readdirSync, readFileSync as readFileSync2, existsSync as existsSync2 } from "fs";
|
|
260
|
+
import { createRequire } from "module";
|
|
437
261
|
import { join } from "path";
|
|
438
262
|
import { pathToFileURL } from "url";
|
|
439
263
|
var loadedPackages = /* @__PURE__ */ new Set();
|
|
@@ -442,12 +266,11 @@ function isLLMExtension(m) {
|
|
|
442
266
|
const e = m;
|
|
443
267
|
if (typeof e.providerName !== "string") return false;
|
|
444
268
|
const hasRegister = typeof e.register === "function";
|
|
445
|
-
const
|
|
446
|
-
return hasRegister ||
|
|
269
|
+
const hasChatModel = typeof e.createChatModel === "function";
|
|
270
|
+
return hasRegister || hasChatModel;
|
|
447
271
|
}
|
|
448
272
|
function registerExtension(ext) {
|
|
449
|
-
if (typeof ext.
|
|
450
|
-
registerProvider(ext.providerName, ext.createClient);
|
|
273
|
+
if (typeof ext.createChatModel === "function") {
|
|
451
274
|
registerChatModelProvider(ext.providerName, ext.createChatModel);
|
|
452
275
|
return;
|
|
453
276
|
}
|
|
@@ -476,7 +299,7 @@ function readPackageProviderName(pkgPath) {
|
|
|
476
299
|
try {
|
|
477
300
|
const raw = readFileSync2(pkgPath, "utf-8");
|
|
478
301
|
const pkg = JSON.parse(raw);
|
|
479
|
-
const declared = pkg
|
|
302
|
+
const declared = pkg[AGENT_LLM_PROVIDER_FIELD] === true || Array.isArray(pkg.keywords) && pkg.keywords.includes("agent-llm-provider");
|
|
480
303
|
return declared && typeof pkg.name === "string" ? pkg.name : null;
|
|
481
304
|
} catch {
|
|
482
305
|
return null;
|
|
@@ -532,6 +355,17 @@ async function loadModuleFromPath(pkgDir) {
|
|
|
532
355
|
entryUrl
|
|
533
356
|
);
|
|
534
357
|
}
|
|
358
|
+
function resolvePackageEntryFromCwd(pkg, cwd) {
|
|
359
|
+
const pkgDir = join(cwd, "node_modules", pkg);
|
|
360
|
+
const pkgJsonPath = join(pkgDir, "package.json");
|
|
361
|
+
if (!existsSync2(pkgJsonPath)) return null;
|
|
362
|
+
try {
|
|
363
|
+
const req = createRequire(pkgJsonPath);
|
|
364
|
+
return req.resolve(pkg);
|
|
365
|
+
} catch {
|
|
366
|
+
return null;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
535
369
|
async function loadLLMExtensions(extensionPackages, options) {
|
|
536
370
|
const packages = Array.isArray(extensionPackages) ? extensionPackages.filter((p) => typeof p === "string" && String(p).trim().length > 0) : [];
|
|
537
371
|
const cwd = options?.cwd ?? process.cwd();
|
|
@@ -568,6 +402,26 @@ async function loadLLMExtensions(extensionPackages, options) {
|
|
|
568
402
|
}
|
|
569
403
|
}
|
|
570
404
|
if (loaded) continue;
|
|
405
|
+
const resolvedEntry = resolvePackageEntryFromCwd(pkg, cwd);
|
|
406
|
+
if (resolvedEntry) {
|
|
407
|
+
try {
|
|
408
|
+
const entryUrl = pathToFileURL(resolvedEntry).href;
|
|
409
|
+
const m = await import(
|
|
410
|
+
/* @vite-ignore */
|
|
411
|
+
entryUrl
|
|
412
|
+
);
|
|
413
|
+
const ext = getExtensionFromModule(m);
|
|
414
|
+
if (ext) {
|
|
415
|
+
registerExtension(ext);
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
if (typeof m.registerLLMExtension === "function") {
|
|
419
|
+
m.registerLLMExtension();
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
422
|
+
} catch {
|
|
423
|
+
}
|
|
424
|
+
}
|
|
571
425
|
try {
|
|
572
426
|
const m = await import(
|
|
573
427
|
/* @vite-ignore */
|
|
@@ -599,7 +453,7 @@ async function loadDiscoveredExtensions(cwd = process.cwd()) {
|
|
|
599
453
|
// src/extensions/npm-protocol.ts
|
|
600
454
|
import { execFileSync } from "child_process";
|
|
601
455
|
import { readFileSync as readFileSync3 } from "fs";
|
|
602
|
-
import { createRequire } from "module";
|
|
456
|
+
import { createRequire as createRequire2 } from "module";
|
|
603
457
|
var NPM_PROTOCOL_PREFIX = "npm:";
|
|
604
458
|
var VERSION_LATEST = "latest";
|
|
605
459
|
async function getLatestVersion(packageName, options = {}) {
|
|
@@ -615,12 +469,12 @@ async function getLatestVersion(packageName, options = {}) {
|
|
|
615
469
|
return version;
|
|
616
470
|
} catch (e) {
|
|
617
471
|
const msg = e instanceof Error ? e.message : String(e);
|
|
618
|
-
throw new Error(`
|
|
472
|
+
throw new Error(`Failed to get latest version for "${packageName}": ${msg}`, { cause: e });
|
|
619
473
|
}
|
|
620
474
|
}
|
|
621
475
|
function getInstalledVersion(packageName, options = {}) {
|
|
622
476
|
const cwd = options.cwd ?? process.cwd();
|
|
623
|
-
const require2 =
|
|
477
|
+
const require2 = createRequire2(import.meta.url);
|
|
624
478
|
try {
|
|
625
479
|
const p = require2.resolve(`${packageName}/package.json`, { paths: [cwd] });
|
|
626
480
|
const j = JSON.parse(readFileSync3(p, "utf-8"));
|
|
@@ -649,60 +503,36 @@ function isModuleNotFoundError(err) {
|
|
|
649
503
|
return msg.includes("Cannot find module") || msg.includes("Cannot find package") || msg.includes("MODULE_NOT_FOUND") || msg.includes("ERR_MODULE_NOT_FOUND") || msg.includes("Failed to load url") || msg.includes("Does the file exist");
|
|
650
504
|
}
|
|
651
505
|
async function resolveInstallVersion(packageName, version, cwd) {
|
|
652
|
-
|
|
506
|
+
const isLatestOrEmpty = version === void 0 || version === "" || typeof version === "string" && version.toLowerCase() === VERSION_LATEST;
|
|
507
|
+
if (isLatestOrEmpty) {
|
|
653
508
|
return getLatestVersion(packageName, { cwd });
|
|
654
509
|
}
|
|
655
510
|
return version;
|
|
656
511
|
}
|
|
657
512
|
async function ensureNpmPackageInstalled(packageName, options = {}) {
|
|
658
513
|
if (typeof packageName !== "string" || packageName.trim().length === 0) {
|
|
659
|
-
throw new Error("
|
|
514
|
+
throw new Error("ensureNpmPackageInstalled requires a non-empty package name");
|
|
660
515
|
}
|
|
661
516
|
const cwd = options.cwd ?? process.cwd();
|
|
662
|
-
const
|
|
663
|
-
const
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
cwd,
|
|
677
|
-
stdio: "inherit",
|
|
678
|
-
encoding: "utf-8"
|
|
679
|
-
});
|
|
680
|
-
} catch (e) {
|
|
681
|
-
const msg = e instanceof Error ? e.message : String(e);
|
|
682
|
-
throw new Error(`agent-llm: npm install failed for ${installSpec2}: ${msg}`, { cause: e });
|
|
683
|
-
}
|
|
684
|
-
}
|
|
517
|
+
const resolvedVersion = await resolveInstallVersion(packageName, options.version, cwd);
|
|
518
|
+
const installedVersion = getInstalledVersion(packageName, { cwd });
|
|
519
|
+
if (installedVersion !== resolvedVersion) {
|
|
520
|
+
const installSpec = `${packageName}@${resolvedVersion}`;
|
|
521
|
+
if (installedVersion === null) {
|
|
522
|
+
console.info(`[agent-llm] Installing provider: ${installSpec}`);
|
|
523
|
+
} else {
|
|
524
|
+
console.info(`[agent-llm] Updating provider: ${packageName} ${installedVersion} \u2192 ${resolvedVersion}`);
|
|
525
|
+
}
|
|
526
|
+
try {
|
|
527
|
+
execFileSync("npm", ["install", installSpec], { cwd, stdio: "inherit", encoding: "utf-8" });
|
|
528
|
+
} catch (e) {
|
|
529
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
530
|
+
throw new Error(`npm install failed for ${installSpec}: ${msg}`, { cause: e });
|
|
685
531
|
}
|
|
686
|
-
return;
|
|
687
|
-
} catch (err) {
|
|
688
|
-
if (!isModuleNotFoundError(err)) throw err;
|
|
689
|
-
}
|
|
690
|
-
const installSpec = resolvedVersion ? `${packageName}@${resolvedVersion}` : packageName;
|
|
691
|
-
try {
|
|
692
|
-
execFileSync("npm", ["install", installSpec], {
|
|
693
|
-
cwd,
|
|
694
|
-
stdio: "inherit",
|
|
695
|
-
encoding: "utf-8"
|
|
696
|
-
});
|
|
697
|
-
} catch (e) {
|
|
698
|
-
const msg = e instanceof Error ? e.message : String(e);
|
|
699
|
-
throw new Error(`agent-llm: npm install failed for ${installSpec}: ${msg}`, { cause: e });
|
|
700
532
|
}
|
|
701
533
|
}
|
|
702
|
-
function
|
|
703
|
-
if (e instanceof Error) {
|
|
704
|
-
return new Error(`${context}: ${e.message}`, { cause: e });
|
|
705
|
-
}
|
|
534
|
+
function normalizeError2(e, context) {
|
|
535
|
+
if (e instanceof Error) return new Error(`${context}: ${e.message}`, { cause: e });
|
|
706
536
|
return new Error(`${context}: ${String(e)}`);
|
|
707
537
|
}
|
|
708
538
|
async function resolveNpmProvider(spec, options = {}) {
|
|
@@ -715,6 +545,9 @@ async function resolveNpmProvider(spec, options = {}) {
|
|
|
715
545
|
const load = async () => {
|
|
716
546
|
await loadLLMExtensions([packageName], { cwd });
|
|
717
547
|
};
|
|
548
|
+
if (installNpmIfMissing) {
|
|
549
|
+
await ensureNpmPackageInstalled(packageName, { version, cwd });
|
|
550
|
+
}
|
|
718
551
|
try {
|
|
719
552
|
await load();
|
|
720
553
|
} catch (err) {
|
|
@@ -723,21 +556,19 @@ async function resolveNpmProvider(spec, options = {}) {
|
|
|
723
556
|
await ensureNpmPackageInstalled(packageName, { version, cwd });
|
|
724
557
|
await load();
|
|
725
558
|
} catch (installErr) {
|
|
726
|
-
throw
|
|
559
|
+
throw normalizeError2(installErr, `Failed to install or load npm provider "${packageName}"`);
|
|
727
560
|
}
|
|
728
561
|
} else {
|
|
729
|
-
throw
|
|
562
|
+
throw normalizeError2(err, `Failed to load npm provider "${packageName}"`);
|
|
730
563
|
}
|
|
731
564
|
}
|
|
732
|
-
if (fragmentProvider &&
|
|
733
|
-
|
|
565
|
+
if (fragmentProvider && !getChatModelFactory(fragmentProvider)) {
|
|
566
|
+
if (installNpmIfMissing) {
|
|
734
567
|
await ensureNpmPackageInstalled(packageName, { version, cwd });
|
|
735
568
|
await load();
|
|
736
|
-
} catch (installErr) {
|
|
737
|
-
throw normalizeAgentLlMError2(installErr, `agent-llm: failed to install or load npm provider "${packageName}" (provider "${fragmentProvider}" not registered)`);
|
|
738
569
|
}
|
|
739
570
|
if (!getChatModelFactory(fragmentProvider)) {
|
|
740
|
-
throw new Error(`
|
|
571
|
+
throw new Error(`Package "${packageName}" was installed but did not register provider "${fragmentProvider}". Check that the package exports getLLMExtension() or registerLLMExtension().`);
|
|
741
572
|
}
|
|
742
573
|
}
|
|
743
574
|
if (fragmentProvider) return fragmentProvider;
|
|
@@ -763,7 +594,7 @@ async function resolveLlmSectionWithNpm(llmSection, options = {}) {
|
|
|
763
594
|
try {
|
|
764
595
|
out.push(await resolveLlmSectionWithNpm(llmSection[i], options));
|
|
765
596
|
} catch (e) {
|
|
766
|
-
throw
|
|
597
|
+
throw normalizeError2(e, `Failed to resolve llm section at index ${i}`);
|
|
767
598
|
}
|
|
768
599
|
}
|
|
769
600
|
return out;
|
|
@@ -776,21 +607,21 @@ async function resolveLlmSectionWithNpm(llmSection, options = {}) {
|
|
|
776
607
|
const resolved = await resolveNpmProvider(v, options);
|
|
777
608
|
out[k] = resolved ?? v;
|
|
778
609
|
} catch (e) {
|
|
779
|
-
throw
|
|
610
|
+
throw normalizeError2(e, `Failed to resolve provider "${String(v)}"`);
|
|
780
611
|
}
|
|
781
612
|
continue;
|
|
782
613
|
}
|
|
783
614
|
try {
|
|
784
615
|
out[k] = await resolveLlmSectionWithNpm(v, options);
|
|
785
616
|
} catch (e) {
|
|
786
|
-
throw
|
|
617
|
+
throw normalizeError2(e, `Failed to resolve llm section key "${k}"`);
|
|
787
618
|
}
|
|
788
619
|
}
|
|
789
620
|
return out;
|
|
790
621
|
}
|
|
791
622
|
return llmSection;
|
|
792
623
|
}
|
|
793
|
-
async function
|
|
624
|
+
async function createChatModelWithNpm(options = {}) {
|
|
794
625
|
try {
|
|
795
626
|
const { installNpmIfMissing, cwd, ...rest } = options;
|
|
796
627
|
const resolvedSection = await resolveLlmSectionWithNpm(options.llmSection ?? null, {
|
|
@@ -802,7 +633,7 @@ async function createChatModelFromLlmConfigWithNpm(options) {
|
|
|
802
633
|
llmSection: resolvedSection
|
|
803
634
|
});
|
|
804
635
|
} catch (e) {
|
|
805
|
-
throw
|
|
636
|
+
throw normalizeError2(e, "createChatModelWithNpm failed");
|
|
806
637
|
}
|
|
807
638
|
}
|
|
808
639
|
|
|
@@ -827,7 +658,7 @@ function resolveProbeRequest(baseURL, endpointOptions) {
|
|
|
827
658
|
const searchParams = new URLSearchParams(urlObj.search);
|
|
828
659
|
if (endpointOptions?.bypassAuth === true) searchParams.set("bypass_auth", "true");
|
|
829
660
|
urlObj.search = searchParams.toString();
|
|
830
|
-
return { url: urlObj.toString(), hostHeader
|
|
661
|
+
return { url: urlObj.toString(), hostHeader };
|
|
831
662
|
}
|
|
832
663
|
function checkWithHttps(url, hostHeader, options) {
|
|
833
664
|
return new Promise((resolve) => {
|
|
@@ -843,10 +674,7 @@ function checkWithHttps(url, hostHeader, options) {
|
|
|
843
674
|
if (hostHeader) reqOpts.headers = { ...reqOpts.headers, Host: hostHeader };
|
|
844
675
|
const timeoutId = setTimeout(() => {
|
|
845
676
|
req.destroy();
|
|
846
|
-
resolve({
|
|
847
|
-
reachable: false,
|
|
848
|
-
message: "Connection timed out"
|
|
849
|
-
});
|
|
677
|
+
resolve({ reachable: false, message: "Connection timed out" });
|
|
850
678
|
}, options.timeoutMs);
|
|
851
679
|
const req = https.request(reqOpts, (res) => {
|
|
852
680
|
clearTimeout(timeoutId);
|
|
@@ -858,10 +686,7 @@ function checkWithHttps(url, hostHeader, options) {
|
|
|
858
686
|
});
|
|
859
687
|
req.on("error", (err) => {
|
|
860
688
|
clearTimeout(timeoutId);
|
|
861
|
-
resolve({
|
|
862
|
-
reachable: false,
|
|
863
|
-
message: err.message || "Connection failed"
|
|
864
|
-
});
|
|
689
|
+
resolve({ reachable: false, message: err.message || "Connection failed" });
|
|
865
690
|
});
|
|
866
691
|
req.end();
|
|
867
692
|
});
|
|
@@ -926,25 +751,23 @@ function buildEndpointConnectivityOptions(config) {
|
|
|
926
751
|
if (resolveHost == null && host == null) return void 0;
|
|
927
752
|
const verifySSL = opts?.verifySSL === true;
|
|
928
753
|
const bypassAuth = opts?.bypassAuth !== false;
|
|
929
|
-
const featureKey = typeof opts?.featureKey === "string" ? opts.featureKey : void 0;
|
|
930
754
|
return {
|
|
931
755
|
resolveHost,
|
|
932
756
|
host,
|
|
933
757
|
verifySSL: resolveHost != null ? false : verifySSL ? true : void 0,
|
|
934
758
|
bypassAuth: bypassAuth ? true : void 0,
|
|
935
|
-
featureKey
|
|
759
|
+
featureKey: typeof opts?.featureKey === "string" ? opts.featureKey : void 0
|
|
936
760
|
};
|
|
937
761
|
}
|
|
938
762
|
function resolveDefaultConfigPath() {
|
|
939
|
-
|
|
940
|
-
return join2(cwd, "llm.yaml");
|
|
763
|
+
return join2(process.cwd(), "llm.yaml");
|
|
941
764
|
}
|
|
942
|
-
function
|
|
765
|
+
function normalizeOptions(configPathOrOptions) {
|
|
943
766
|
if (configPathOrOptions == null) return {};
|
|
944
767
|
if (typeof configPathOrOptions === "string") return { configPath: configPathOrOptions };
|
|
945
768
|
return configPathOrOptions;
|
|
946
769
|
}
|
|
947
|
-
function
|
|
770
|
+
function normalizeError3(e, context) {
|
|
948
771
|
if (e instanceof Error) return new Error(`${context}: ${e.message}`, { cause: e });
|
|
949
772
|
return new Error(`${context}: ${String(e)}`);
|
|
950
773
|
}
|
|
@@ -953,16 +776,14 @@ async function ensureConnectivity(resolvedLlmSection, options) {
|
|
|
953
776
|
try {
|
|
954
777
|
const parsed = parseLlmSection(resolvedLlmSection ?? null);
|
|
955
778
|
configs = parsed.configs.filter(
|
|
956
|
-
(c) => typeof c.baseURL === "string" && c.baseURL.length > 0
|
|
779
|
+
(c) => typeof c.baseURL === "string" && c.baseURL.length > 0 && (c.baseURL.startsWith("http://") || c.baseURL.startsWith("https://")) && !c.baseURL.includes("${")
|
|
957
780
|
);
|
|
958
781
|
} catch {
|
|
959
782
|
return;
|
|
960
783
|
}
|
|
961
784
|
const shouldCheck = options.checkConnectivity !== false && configs.length > 0;
|
|
962
785
|
if (!shouldCheck) return;
|
|
963
|
-
const report = (status) =>
|
|
964
|
-
options.onConnectionStatus?.(status);
|
|
965
|
-
};
|
|
786
|
+
const report = (status) => options.onConnectionStatus?.(status);
|
|
966
787
|
const timeoutMs = options.connectivityTimeoutMs ?? 8e3;
|
|
967
788
|
for (const config of configs) {
|
|
968
789
|
const { id, baseURL } = config;
|
|
@@ -970,7 +791,7 @@ async function ensureConnectivity(resolvedLlmSection, options) {
|
|
|
970
791
|
phase: "checking",
|
|
971
792
|
endpointId: id,
|
|
972
793
|
baseURL,
|
|
973
|
-
message: "Checking
|
|
794
|
+
message: "Checking connection..."
|
|
974
795
|
});
|
|
975
796
|
const endpointOpts = buildEndpointConnectivityOptions(config);
|
|
976
797
|
const result = await checkEndpointConnectivity(baseURL, {
|
|
@@ -991,19 +812,19 @@ async function ensureConnectivity(resolvedLlmSection, options) {
|
|
|
991
812
|
baseURL,
|
|
992
813
|
message: result.message ?? "Unreachable"
|
|
993
814
|
});
|
|
994
|
-
throw new Error(
|
|
995
|
-
buildUnreachableError(id, baseURL, result.message)
|
|
996
|
-
);
|
|
815
|
+
throw new Error(buildUnreachableError(id, baseURL, result.message));
|
|
997
816
|
}
|
|
998
817
|
}
|
|
999
818
|
}
|
|
1000
819
|
async function createAgentLlM(configPathOrOptions) {
|
|
1001
820
|
try {
|
|
1002
|
-
const options =
|
|
821
|
+
const options = normalizeOptions(configPathOrOptions);
|
|
1003
822
|
const configPath = options.configPath ?? resolveDefaultConfigPath();
|
|
1004
823
|
const llmSection = loadLlmConfig(configPath);
|
|
1005
824
|
if (llmSection == null) {
|
|
1006
|
-
throw new Error(
|
|
825
|
+
throw new Error(
|
|
826
|
+
`No LLM config at ${configPath}. Add llm.yaml in the current directory, or pass configPath.`
|
|
827
|
+
);
|
|
1007
828
|
}
|
|
1008
829
|
const resolvedSection = await resolveLlmSectionWithNpm(llmSection, {
|
|
1009
830
|
installNpmIfMissing: options.installNpmIfMissing !== false,
|
|
@@ -1017,9 +838,22 @@ async function createAgentLlM(configPathOrOptions) {
|
|
|
1017
838
|
return createChatModelFromLlmConfig({ llmSection: resolvedSection });
|
|
1018
839
|
} catch (e) {
|
|
1019
840
|
if (e instanceof Error && e.message.includes("No LLM config")) throw e;
|
|
1020
|
-
if (e instanceof Error && e.message.includes("Cannot connect to
|
|
1021
|
-
throw
|
|
841
|
+
if (e instanceof Error && e.message.includes("Cannot connect to")) throw e;
|
|
842
|
+
throw normalizeError3(e, "createAgentLlM failed");
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
// src/cli/utils.ts
|
|
847
|
+
function messageContentToString(content) {
|
|
848
|
+
if (typeof content === "string") return content;
|
|
849
|
+
if (Array.isArray(content)) {
|
|
850
|
+
return content.map((c) => "text" in c && c.text ? c.text : "").join("");
|
|
1022
851
|
}
|
|
852
|
+
return String(content ?? "");
|
|
853
|
+
}
|
|
854
|
+
function exitWithError(err, code = 1) {
|
|
855
|
+
console.error("Error:", err instanceof Error ? err.message : String(err));
|
|
856
|
+
process.exit(code);
|
|
1023
857
|
}
|
|
1024
858
|
|
|
1025
859
|
export {
|
|
@@ -1027,14 +861,11 @@ export {
|
|
|
1027
861
|
substituteEnv,
|
|
1028
862
|
parseLlmYaml,
|
|
1029
863
|
loadLlmConfig,
|
|
1030
|
-
|
|
1031
|
-
createOpenAIImageClient,
|
|
1032
|
-
createOpenAIClient,
|
|
1033
|
-
createClient,
|
|
1034
|
-
registerProvider,
|
|
864
|
+
createChatOpenAI,
|
|
1035
865
|
registerChatModelProvider,
|
|
1036
866
|
getChatModelFactory,
|
|
1037
867
|
createChatModelFromLlmConfig,
|
|
868
|
+
AGENT_LLM_PROVIDER_FIELD,
|
|
1038
869
|
resolveLLMExtensionPackages,
|
|
1039
870
|
discoverLLMExtensions,
|
|
1040
871
|
loadLLMExtensions,
|
|
@@ -1047,10 +878,12 @@ export {
|
|
|
1047
878
|
ensureNpmPackageInstalled,
|
|
1048
879
|
resolveNpmProvider,
|
|
1049
880
|
resolveLlmSectionWithNpm,
|
|
1050
|
-
|
|
881
|
+
createChatModelWithNpm,
|
|
1051
882
|
checkEndpointConnectivity,
|
|
1052
883
|
CIS_UNREACHABLE_REMINDER,
|
|
1053
884
|
buildUnreachableError,
|
|
1054
|
-
createAgentLlM
|
|
885
|
+
createAgentLlM,
|
|
886
|
+
messageContentToString,
|
|
887
|
+
exitWithError
|
|
1055
888
|
};
|
|
1056
|
-
//# sourceMappingURL=chunk-
|
|
889
|
+
//# sourceMappingURL=chunk-H4UQIDGT.js.map
|