@agent-spaces/server 0.3.65 → 0.4.0
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/adapters/agent-runtime.js +8 -0
- package/dist/adapters/codex-function-tool-bridge.js +152 -0
- package/dist/adapters/codex-runtime.js +23 -4
- package/dist/adapters/git.js +25 -3
- package/dist/adapters/hermes-runtime.js +813 -0
- package/dist/adapters/langchain-runtime.js +384 -21
- package/dist/adapters/oh-my-pi-runtime.js +858 -0
- package/dist/adapters/open-agent-sdk-runtime.js +202 -5
- package/dist/adapters/open-agent-sdk-runtime.test.js +35 -0
- package/dist/agents/agent-message-parts.js +52 -2
- package/dist/agents/issue-task-controller.js +71 -2
- package/dist/agents/pull-request-agent.js +115 -0
- package/dist/agents/scheduler-agent.js +1 -1
- package/dist/agents/title-generator-agent.js +120 -0
- package/dist/app.js +61 -4
- package/dist/middleware/auth.js +1 -1
- package/dist/package.json +2 -1
- package/dist/routes/agent-sse.js +70 -6
- package/dist/routes/channel.js +23 -2
- package/dist/routes/chat-run.js +191 -0
- package/dist/routes/chat.js +142 -0
- package/dist/routes/command.js +16 -0
- package/dist/routes/data.js +189 -0
- package/dist/routes/git.js +10 -1
- package/dist/routes/import.js +199 -0
- package/dist/routes/issue.js +17 -5
- package/dist/routes/notification.js +10 -0
- package/dist/routes/plugin.js +69 -0
- package/dist/routes/version.js +95 -0
- package/dist/routes/workflow-hook.js +71 -0
- package/dist/routes/workflow.js +282 -7
- package/dist/routes/workspace.js +13 -4
- package/dist/routes/worktree.js +93 -0
- package/dist/services/agent.js +123 -36
- package/dist/services/ai-text.js +185 -0
- package/dist/services/builtin-tools/index.js +1 -0
- package/dist/services/builtin-tools/workflow-editor-tools.js +509 -0
- package/dist/services/builtin-tools/workflow-exec-tools.js +320 -0
- package/dist/services/chat.js +134 -0
- package/dist/services/command-process-manager.js +16 -0
- package/dist/services/execution-manager.js +1346 -0
- package/dist/services/generated-title.js +59 -0
- package/dist/services/gitignore.js +22 -18
- package/dist/services/interaction-manager.js +114 -0
- package/dist/services/issue-retry.js +25 -0
- package/dist/services/notification-center.js +9 -0
- package/dist/services/output-style.js +8 -1
- package/dist/services/plugin.js +257 -0
- package/dist/services/prompt-template.js +8 -1
- package/dist/services/pty.js +20 -0
- package/dist/services/search.js +16 -6
- package/dist/services/skill.js +2 -0
- package/dist/services/version.js +69 -0
- package/dist/services/workflow-command-runner.js +24 -0
- package/dist/services/workflow-trigger-service.js +137 -0
- package/dist/services/workflow.js +219 -39
- package/dist/services/workspace.js +23 -1
- package/dist/services/worktree.js +207 -0
- package/dist/storage/agent-store.js +8 -0
- package/dist/storage/chat-store.js +151 -0
- package/dist/storage/database-store.js +6 -0
- package/dist/storage/json-store.js +2 -1
- package/dist/storage/kanban-store.js +6 -0
- package/dist/storage/workflow-store.js +386 -22
- package/dist/storage/worktree-store.js +33 -0
- package/dist/web/404.html +1 -1
- package/dist/web/__next.__PAGE__.txt +4 -4
- package/dist/web/__next._full.txt +21 -21
- package/dist/web/__next._head.txt +4 -4
- package/dist/web/__next._index.txt +13 -13
- package/dist/web/__next._tree.txt +2 -2
- package/dist/web/_next/static/chunks/{08x85faoz58i7.js → 0-92u-tiuy40a.js} +4 -4
- package/dist/web/_next/static/chunks/{0db14450oqzhg.js → 0-yizd8osmas2.js} +1 -1
- package/dist/web/_next/static/chunks/0.ln~3mnv8.69.js +1 -0
- package/dist/web/_next/static/chunks/{11cchuwoupmbf.js → 01y3e9pemva7b.js} +10 -10
- package/dist/web/_next/static/chunks/02l~tmzrgny.~.js +1 -0
- package/dist/web/_next/static/chunks/03f1bwuynjdmk.js +1 -0
- package/dist/web/_next/static/chunks/04cb4kc9r2pd1.js +1 -0
- package/dist/web/_next/static/chunks/04de6ha5_e3pp.js +1 -0
- package/dist/web/_next/static/chunks/09he0p79ov1rn.js +1 -0
- package/dist/web/_next/static/chunks/09vpocs4zuc8h.js +1 -0
- package/dist/web/_next/static/chunks/0_o2exgr0e_nh.js +1 -0
- package/dist/web/_next/static/chunks/{0xbaakj0dfc0..js → 0_y9nskc-xt2k.js} +1 -1
- package/dist/web/_next/static/chunks/0clnj-1fi6u8j.js +3 -0
- package/dist/web/_next/static/chunks/0gv40by0zzxs_.js +1 -0
- package/dist/web/_next/static/chunks/0iusr8y88.kjg.js +1 -0
- package/dist/web/_next/static/chunks/{0-a.-hl3wv99k.js → 0j-8418fxvkd1.js} +1 -1
- package/dist/web/_next/static/chunks/0j.wxxyoclma5.js +1 -0
- package/dist/web/_next/static/chunks/{0.6b64sy0g5.3.js → 0jq.16sozqik..js} +1 -1
- package/dist/web/_next/static/chunks/0jw8xdk_fpnp0.css +1 -0
- package/dist/web/_next/static/chunks/0l1lkd-wcotma.js +1 -0
- package/dist/web/_next/static/chunks/{0u6h-hqc_i52e.js → 0ncxf_zr4n839.js} +1 -1
- package/dist/web/_next/static/chunks/0ndo7um~v7vco.js +1 -0
- package/dist/web/_next/static/chunks/0ngk.~kan8wq_.js +1 -0
- package/dist/web/_next/static/chunks/0ppr271hz0xoq.js +1 -0
- package/dist/web/_next/static/chunks/0rt9bofnn6qvn.js +1 -0
- package/dist/web/_next/static/chunks/0t64.9jd00hio.js +3 -0
- package/dist/web/_next/static/chunks/0taui9--5n6-5.js +1 -0
- package/dist/web/_next/static/chunks/0ty39169lh~z3.js +1 -0
- package/dist/web/_next/static/chunks/0v8nof~waedlu.js +1 -0
- package/dist/web/_next/static/chunks/{0-pi.67w.ymsr.js → 0vcfoagnpf.aw.js} +1 -1
- package/dist/web/_next/static/chunks/{0vis~lx0nxgn-.js → 0wwwq.gyyz0vg.js} +3 -3
- package/dist/web/_next/static/chunks/0x5lak8yz7pm7.js +1 -0
- package/dist/web/_next/static/chunks/0xon_.4-o0_zq.js +7 -0
- package/dist/web/_next/static/chunks/0zjnrbt7inime.js +1 -0
- package/dist/web/_next/static/chunks/0zwebpitvpuv1.js +1 -0
- package/dist/web/_next/static/chunks/0~02o4g-o6n~m.js +1 -0
- package/dist/web/_next/static/chunks/{0w7.tb29958zj.js → 0~fjezp.k4qk3.js} +1 -1
- package/dist/web/_next/static/chunks/0~sh93re1-_rp.js +1 -0
- package/dist/web/_next/static/chunks/10_niiq0k6o-p.js +5 -0
- package/dist/web/_next/static/chunks/12tjr0_2ccrtq.js +2 -0
- package/dist/web/_next/static/chunks/12x5.go_x9mfk.js +1 -0
- package/dist/web/_next/static/chunks/{0l2w0qz1ea7ql.js → 12~5dk9i9d16t.js} +2 -2
- package/dist/web/_next/static/chunks/13iye4rv5p31b.js +1 -0
- package/dist/web/_next/static/chunks/{01~quun6sefgl.js → 13~y-b.b9rrw4.js} +1 -1
- package/dist/web/_next/static/chunks/151wzhb5q0lo5.js +1 -0
- package/dist/web/_not-found/__next._full.txt +19 -19
- package/dist/web/_not-found/__next._head.txt +4 -4
- package/dist/web/_not-found/__next._index.txt +13 -13
- package/dist/web/_not-found/__next._not-found.__PAGE__.txt +2 -2
- package/dist/web/_not-found/__next._not-found.txt +3 -3
- package/dist/web/_not-found/__next._tree.txt +2 -2
- package/dist/web/_not-found.html +1 -1
- package/dist/web/_not-found.txt +19 -19
- package/dist/web/index.html +1 -1
- package/dist/web/index.txt +21 -21
- package/dist/web/login/__next._full.txt +21 -21
- package/dist/web/login/__next._head.txt +4 -4
- package/dist/web/login/__next._index.txt +13 -13
- package/dist/web/login/__next._tree.txt +2 -2
- package/dist/web/login/__next.login.__PAGE__.txt +4 -4
- package/dist/web/login/__next.login.txt +3 -3
- package/dist/web/login.html +1 -1
- package/dist/web/login.txt +21 -21
- package/dist/web/settings/__next._full.txt +23 -23
- package/dist/web/settings/__next._head.txt +4 -4
- package/dist/web/settings/__next._index.txt +13 -13
- package/dist/web/settings/__next._tree.txt +2 -2
- package/dist/web/settings/__next.settings.__PAGE__.txt +4 -4
- package/dist/web/settings/__next.settings.txt +5 -5
- package/dist/web/settings/agents/__next._full.txt +23 -23
- package/dist/web/settings/agents/__next._head.txt +4 -4
- package/dist/web/settings/agents/__next._index.txt +13 -13
- package/dist/web/settings/agents/__next._tree.txt +2 -2
- package/dist/web/settings/agents/__next.settings.agents.__PAGE__.txt +4 -4
- package/dist/web/settings/agents/__next.settings.agents.txt +3 -3
- package/dist/web/settings/agents/__next.settings.txt +5 -5
- package/dist/web/settings/agents.html +1 -1
- package/dist/web/settings/agents.txt +23 -23
- package/dist/web/settings/mcps/__next._full.txt +23 -23
- package/dist/web/settings/mcps/__next._head.txt +4 -4
- package/dist/web/settings/mcps/__next._index.txt +13 -13
- package/dist/web/settings/mcps/__next._tree.txt +2 -2
- package/dist/web/settings/mcps/__next.settings.mcps.__PAGE__.txt +4 -4
- package/dist/web/settings/mcps/__next.settings.mcps.txt +3 -3
- package/dist/web/settings/mcps/__next.settings.txt +5 -5
- package/dist/web/settings/mcps.html +1 -1
- package/dist/web/settings/mcps.txt +23 -23
- package/dist/web/settings/models/__next._full.txt +23 -23
- package/dist/web/settings/models/__next._head.txt +4 -4
- package/dist/web/settings/models/__next._index.txt +13 -13
- package/dist/web/settings/models/__next._tree.txt +2 -2
- package/dist/web/settings/models/__next.settings.models.__PAGE__.txt +4 -4
- package/dist/web/settings/models/__next.settings.models.txt +3 -3
- package/dist/web/settings/models/__next.settings.txt +5 -5
- package/dist/web/settings/models.html +1 -1
- package/dist/web/settings/models.txt +23 -23
- package/dist/web/settings/output-styles/__next._full.txt +23 -23
- package/dist/web/settings/output-styles/__next._head.txt +4 -4
- package/dist/web/settings/output-styles/__next._index.txt +13 -13
- package/dist/web/settings/output-styles/__next._tree.txt +2 -2
- package/dist/web/settings/output-styles/__next.settings.output-styles.__PAGE__.txt +4 -4
- package/dist/web/settings/output-styles/__next.settings.output-styles.txt +3 -3
- package/dist/web/settings/output-styles/__next.settings.txt +5 -5
- package/dist/web/settings/output-styles.html +1 -1
- package/dist/web/settings/output-styles.txt +23 -23
- package/dist/web/settings/prompts/__next._full.txt +23 -23
- package/dist/web/settings/prompts/__next._head.txt +4 -4
- package/dist/web/settings/prompts/__next._index.txt +13 -13
- package/dist/web/settings/prompts/__next._tree.txt +2 -2
- package/dist/web/settings/prompts/__next.settings.prompts.__PAGE__.txt +4 -4
- package/dist/web/settings/prompts/__next.settings.prompts.txt +3 -3
- package/dist/web/settings/prompts/__next.settings.txt +5 -5
- package/dist/web/settings/prompts.html +1 -1
- package/dist/web/settings/prompts.txt +23 -23
- package/dist/web/settings/providers/__next._full.txt +23 -23
- package/dist/web/settings/providers/__next._head.txt +4 -4
- package/dist/web/settings/providers/__next._index.txt +13 -13
- package/dist/web/settings/providers/__next._tree.txt +2 -2
- package/dist/web/settings/providers/__next.settings.providers.__PAGE__.txt +4 -4
- package/dist/web/settings/providers/__next.settings.providers.txt +3 -3
- package/dist/web/settings/providers/__next.settings.txt +5 -5
- package/dist/web/settings/providers.html +1 -1
- package/dist/web/settings/providers.txt +23 -23
- package/dist/web/settings/skills/__next._full.txt +23 -23
- package/dist/web/settings/skills/__next._head.txt +4 -4
- package/dist/web/settings/skills/__next._index.txt +13 -13
- package/dist/web/settings/skills/__next._tree.txt +2 -2
- package/dist/web/settings/skills/__next.settings.skills.__PAGE__.txt +4 -4
- package/dist/web/settings/skills/__next.settings.skills.txt +3 -3
- package/dist/web/settings/skills/__next.settings.txt +5 -5
- package/dist/web/settings/skills.html +1 -1
- package/dist/web/settings/skills.txt +23 -23
- package/dist/web/settings/tools/__next._full.txt +23 -23
- package/dist/web/settings/tools/__next._head.txt +4 -4
- package/dist/web/settings/tools/__next._index.txt +13 -13
- package/dist/web/settings/tools/__next._tree.txt +2 -2
- package/dist/web/settings/tools/__next.settings.tools.__PAGE__.txt +4 -4
- package/dist/web/settings/tools/__next.settings.tools.txt +3 -3
- package/dist/web/settings/tools/__next.settings.txt +5 -5
- package/dist/web/settings/tools.html +1 -1
- package/dist/web/settings/tools.txt +23 -23
- package/dist/web/settings.html +1 -1
- package/dist/web/settings.txt +23 -23
- package/dist/web/workflows/__next._full.txt +22 -22
- package/dist/web/workflows/__next._head.txt +4 -4
- package/dist/web/workflows/__next._index.txt +13 -13
- package/dist/web/workflows/__next._tree.txt +2 -2
- package/dist/web/workflows/__next.workflows.__PAGE__.txt +4 -4
- package/dist/web/workflows/__next.workflows.txt +3 -3
- package/dist/web/workflows.html +1 -1
- package/dist/web/workflows.txt +22 -22
- package/dist/web/workspace/_/__next._full.txt +20 -20
- package/dist/web/workspace/_/__next._head.txt +4 -4
- package/dist/web/workspace/_/__next._index.txt +13 -13
- package/dist/web/workspace/_/__next._tree.txt +2 -2
- package/dist/web/workspace/_/__next.workspace.$d$id.__PAGE__.txt +3 -3
- package/dist/web/workspace/_/__next.workspace.$d$id.txt +3 -3
- package/dist/web/workspace/_/__next.workspace.txt +3 -3
- package/dist/web/workspace/_.html +1 -1
- package/dist/web/workspace/_.txt +20 -20
- package/dist/web/workspaces/__next._full.txt +21 -21
- package/dist/web/workspaces/__next._head.txt +4 -4
- package/dist/web/workspaces/__next._index.txt +13 -13
- package/dist/web/workspaces/__next._tree.txt +2 -2
- package/dist/web/workspaces/__next.workspaces.__PAGE__.txt +4 -4
- package/dist/web/workspaces/__next.workspaces.txt +3 -3
- package/dist/web/workspaces.html +1 -1
- package/dist/web/workspaces.txt +21 -21
- package/dist/ws/agent-prompt.js +36 -3
- package/dist/ws/agent-runner.js +30 -18
- package/dist/ws/chat-handler.js +89 -0
- package/dist/ws/connection-manager.js +49 -2
- package/dist/ws/execution-channels.js +88 -0
- package/dist/ws/handler.js +32 -5
- package/dist/ws/message-parts.js +130 -12
- package/dist/ws/terminal-handler.js +26 -0
- package/package.json +13 -1
- package/public/avatars/user.jpg +0 -0
- package/dist/web/_next/static/chunks/0-v_p6j5u3_9l.js +0 -1
- package/dist/web/_next/static/chunks/0.-x29t-8gk0r.js +0 -1
- package/dist/web/_next/static/chunks/0.l5e8~r7_0~p.js +0 -1
- package/dist/web/_next/static/chunks/0.n~yfwf4~6w-.js +0 -1
- package/dist/web/_next/static/chunks/00-syqzi-6zxr.js +0 -1
- package/dist/web/_next/static/chunks/02j4sr9psucf-.js +0 -1
- package/dist/web/_next/static/chunks/06si8l0doqe8p.js +0 -1
- package/dist/web/_next/static/chunks/08kfx8on9oty~.js +0 -1
- package/dist/web/_next/static/chunks/08ugbvzr20drp.js +0 -2
- package/dist/web/_next/static/chunks/0_cqojbge48kq.js +0 -5
- package/dist/web/_next/static/chunks/0d6~~lv0-6kex.js +0 -3
- package/dist/web/_next/static/chunks/0gdwop9cnpmtu.js +0 -1
- package/dist/web/_next/static/chunks/0ghx3j_.-gdyd.js +0 -1
- package/dist/web/_next/static/chunks/0kbvoxla7f751.js +0 -1
- package/dist/web/_next/static/chunks/0paaat8y96ayc.js +0 -7
- package/dist/web/_next/static/chunks/0pq318f8xgafg.js +0 -1
- package/dist/web/_next/static/chunks/0t6s8of0qr6nc.js +0 -1
- package/dist/web/_next/static/chunks/0xt-8wk21gs7g.js +0 -1
- package/dist/web/_next/static/chunks/0yd.m1afqg.2t.js +0 -3
- package/dist/web/_next/static/chunks/0yhbr8hl09b-5.js +0 -1
- package/dist/web/_next/static/chunks/0z~vqzbm_q371.js +0 -1
- package/dist/web/_next/static/chunks/0~~_ltu6dx_ch.js +0 -1
- package/dist/web/_next/static/chunks/12oxcgyhpaxw~.js +0 -1
- package/dist/web/_next/static/chunks/1452eibz62gs6.css +0 -1
- package/dist/web/_next/static/chunks/16zlreiems5cn.js +0 -1
- package/dist/web/_next/static/chunks/18awqjk9-o5m0.js +0 -1
- /package/dist/web/_next/static/{x4-CsKe6qUQyFDWVtfvUg → rGXyAK8rgod1NjF3bLZAY}/_buildManifest.js +0 -0
- /package/dist/web/_next/static/{x4-CsKe6qUQyFDWVtfvUg → rGXyAK8rgod1NjF3bLZAY}/_clientMiddlewareManifest.js +0 -0
- /package/dist/web/_next/static/{x4-CsKe6qUQyFDWVtfvUg → rGXyAK8rgod1NjF3bLZAY}/_ssgManifest.js +0 -0
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
2
|
+
import { basename, join } from 'node:path';
|
|
3
|
+
import { MultiServerMCPClient } from '@langchain/mcp-adapters';
|
|
1
4
|
import { createAgent, initChatModel, tool } from 'langchain';
|
|
2
5
|
import { z } from 'zod';
|
|
3
6
|
import { appendOutputStyleToPrompt, summarizeResult } from './agent-runtime-types.js';
|
|
7
|
+
const DEFAULT_DATA_DIR = join(process.env.HOME || '~', '.agent-spaces-data');
|
|
4
8
|
/**
|
|
5
9
|
* Runtime backed by LangChain.js.
|
|
6
10
|
* Uses LangChain's provider-neutral createAgent API and adapts Agent Spaces tools.
|
|
@@ -8,6 +12,7 @@ import { appendOutputStyleToPrompt, summarizeResult } from './agent-runtime-type
|
|
|
8
12
|
export class LangChainRuntime {
|
|
9
13
|
config;
|
|
10
14
|
abortController = null;
|
|
15
|
+
static nextRunId = 1;
|
|
11
16
|
constructor(config = {}) {
|
|
12
17
|
this.config = config;
|
|
13
18
|
}
|
|
@@ -16,23 +21,58 @@ export class LangChainRuntime {
|
|
|
16
21
|
const output = [];
|
|
17
22
|
const cwd = workingDir || process.cwd();
|
|
18
23
|
const startTime = Date.now();
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
24
|
+
const runId = LangChainRuntime.nextRunId++;
|
|
25
|
+
const d = (msg) => console.log(`[langchain:${runId}] ${msg}`);
|
|
26
|
+
const modelSettings = resolveLangChainModelSettings(this.config);
|
|
27
|
+
const model = modelSettings.modelIdentifier;
|
|
28
|
+
let mcpClient;
|
|
29
|
+
const skillPrompts = loadConfiguredSkillPrompts(options?.configDir, options?.skills);
|
|
30
|
+
d(`starting | cwd=${cwd} provider=${this.config.provider ?? 'auto'} langchainProvider=${modelSettings.provider ?? 'auto'} model=${model} baseURL=${this.config.baseURL ?? 'default'} apiKey=${this.config.apiKey ? 'set' : 'unset'} maxTurns=${options?.maxTurns ?? '∞'} tools=${options?.functionTools?.map((runtimeTool) => runtimeTool.name).join(',') || '-'} mcpServers=${Object.keys(options?.mcpServers ?? {}).join(',') || '-'} skills=${skillPrompts.map((skill) => skill.name).join(',') || '-'} sandboxDirs=${options?.sandboxDirs?.join(',') ?? '-'}`);
|
|
31
|
+
d(`options | ${summarizeOptionsForLog(options)}`);
|
|
32
|
+
d(`model config | ${summarizeForLog(maskSensitiveConfig(buildModelConfig(this.config)), 1000)}`);
|
|
33
|
+
d(`provider env | ${summarizeEnvForLog(buildProviderEnv(this.config, modelSettings.provider))}`);
|
|
34
|
+
if (modelSettings.providerCorrectionReason)
|
|
35
|
+
d(`provider adjusted | ${modelSettings.providerCorrectionReason}`);
|
|
36
|
+
d(`prompt | chars=${prompt.length} preview=${truncateForLog(prompt, 1000)}`);
|
|
37
|
+
if (skillPrompts.length) {
|
|
38
|
+
d(`skills loaded | ${skillPrompts.map((skill) => `${skill.name}:${skill.content.length}chars`).join(',')}`);
|
|
39
|
+
}
|
|
40
|
+
else if (options?.skills?.length) {
|
|
41
|
+
d(`skills requested but not loaded | requested=${options.skills.join(',')}`);
|
|
42
|
+
}
|
|
23
43
|
try {
|
|
24
|
-
|
|
44
|
+
d('initializing chat model');
|
|
45
|
+
const chatModel = await withTemporaryEnv(buildProviderEnv(this.config, modelSettings.provider), () => initChatModel(model, buildModelConfig(this.config)));
|
|
46
|
+
d(`chat model initialized | type=${getObjectTypeName(chatModel)}`);
|
|
47
|
+
mcpClient = createLangChainMcpClient(options?.mcpServers, output, options, d);
|
|
48
|
+
d(`MCP client ${mcpClient ? 'created' : 'not created'}`);
|
|
49
|
+
const mcpTools = mcpClient ? await mcpClient.getTools() : [];
|
|
50
|
+
if (mcpClient)
|
|
51
|
+
d(`resolved MCP tools | servers=${Object.keys(options?.mcpServers ?? {}).join(',') || '-'} count=${mcpTools.length} tools=${mcpTools.map((mcpTool) => mcpTool.name).join(',') || '-'}`);
|
|
52
|
+
const runtimeTools = buildLangChainTools(options?.functionTools, output, options, d);
|
|
53
|
+
d(`creating agent | runtimeTools=${runtimeTools.length} mcpTools=${mcpTools.length} systemPrompt=${options?.systemPrompt ? `${options.systemPrompt.length}chars` : '-'} outputStyle=${options?.outputStyle ?? '-'}`);
|
|
25
54
|
const agent = createAgent({
|
|
26
55
|
model: chatModel,
|
|
27
|
-
tools:
|
|
56
|
+
tools: [
|
|
57
|
+
...runtimeTools,
|
|
58
|
+
...mcpTools,
|
|
59
|
+
],
|
|
28
60
|
systemPrompt: options?.systemPrompt,
|
|
29
61
|
});
|
|
30
|
-
|
|
62
|
+
d(`agent created | type=${getObjectTypeName(agent)}`);
|
|
63
|
+
const finalPrompt = appendOutputStyleToPrompt(injectSkillPrompts(prompt, skillPrompts), options?.outputStyle);
|
|
64
|
+
d(`final prompt | chars=${finalPrompt.length} skillCount=${skillPrompts.length} outputStyle=${options?.outputStyle ?? '-'} preview=${truncateForLog(finalPrompt, 1200)}`);
|
|
65
|
+
const recursionLimit = options?.maxTurns ? Math.max(2, options.maxTurns * 2 + 1) : undefined;
|
|
66
|
+
d(`invoking agent | recursionLimit=${recursionLimit ?? '-'} aborted=${this.abortController?.signal.aborted ? 'yes' : 'no'}`);
|
|
67
|
+
const result = await agent.invoke({ messages: [{ role: 'user', content: finalPrompt }] }, {
|
|
31
68
|
signal: this.abortController?.signal,
|
|
32
|
-
recursionLimit
|
|
69
|
+
recursionLimit,
|
|
33
70
|
});
|
|
71
|
+
d(`agent result | ${summarizeAgentResultForLog(result)}`);
|
|
34
72
|
const text = extractFinalText(result);
|
|
35
73
|
const usage = extractUsage(result);
|
|
74
|
+
d(`final text | chars=${text.length} preview=${truncateForLog(text, 1200) || '-'}`);
|
|
75
|
+
d(`usage | ${usage ? summarizeForLog(usage, 500) : '-'}`);
|
|
36
76
|
if (text) {
|
|
37
77
|
output.push(text);
|
|
38
78
|
options?.onEvent?.({ type: 'output', line: text });
|
|
@@ -43,7 +83,7 @@ export class LangChainRuntime {
|
|
|
43
83
|
options?.onEvent?.({ type: 'output', line: usageLine });
|
|
44
84
|
}
|
|
45
85
|
const elapsed = Date.now() - startTime;
|
|
46
|
-
d(`done ${elapsed}ms | tokens=${usage?.totalTokens ?? 'unknown'}`);
|
|
86
|
+
d(`done ${elapsed}ms | outputLines=${output.length} tokens=${usage?.totalTokens ?? 'unknown'}`);
|
|
47
87
|
return {
|
|
48
88
|
success: true,
|
|
49
89
|
summary: summarizeResult(text),
|
|
@@ -55,41 +95,146 @@ export class LangChainRuntime {
|
|
|
55
95
|
catch (err) {
|
|
56
96
|
const elapsed = Date.now() - startTime;
|
|
57
97
|
const message = err instanceof Error ? err.message : String(err);
|
|
58
|
-
d(`failed ${elapsed}ms |
|
|
98
|
+
d(`failed ${elapsed}ms | name=${err instanceof Error ? err.name : typeof err} message=${truncateForLog(message, 1000)} outputLines=${output.length}`);
|
|
59
99
|
if (err instanceof Error && err.stack)
|
|
60
100
|
console.error(err.stack);
|
|
61
101
|
return { success: false, summary: 'LangChain execution failed', artifacts: [], error: message, output };
|
|
62
102
|
}
|
|
63
103
|
finally {
|
|
104
|
+
if (mcpClient) {
|
|
105
|
+
d('closing MCP client');
|
|
106
|
+
try {
|
|
107
|
+
await mcpClient.close();
|
|
108
|
+
d('MCP client closed');
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
d(`MCP client close failed | ${err instanceof Error ? err.message : String(err)}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
64
114
|
this.abortController = null;
|
|
115
|
+
d('runtime reset');
|
|
65
116
|
}
|
|
66
117
|
}
|
|
67
118
|
stop() {
|
|
68
119
|
this.abortController?.abort();
|
|
69
120
|
}
|
|
70
121
|
}
|
|
71
|
-
function
|
|
122
|
+
export function buildLangChainPromptWithSkills(prompt, agentDir, skills, outputStyle) {
|
|
123
|
+
return appendOutputStyleToPrompt(injectSkillPrompts(prompt, loadConfiguredSkillPrompts(agentDir, skills)), outputStyle);
|
|
124
|
+
}
|
|
125
|
+
function injectSkillPrompts(prompt, skills) {
|
|
126
|
+
if (!skills.length)
|
|
127
|
+
return prompt;
|
|
128
|
+
return [
|
|
129
|
+
prompt.trimEnd(),
|
|
130
|
+
'',
|
|
131
|
+
'Configured skill instructions:',
|
|
132
|
+
`Enabled skill names: ${skills.map((skill) => skill.name).join(', ')}`,
|
|
133
|
+
'These are configured skills for this run, even if a skill body looks like a design note, plan, or reference document.',
|
|
134
|
+
'If the user asks what skills are available, answer from the enabled skill names above. Do not say that no skills are available when this list is non-empty.',
|
|
135
|
+
'Follow the skill contents below when they are relevant to the user request.',
|
|
136
|
+
'',
|
|
137
|
+
...skills.flatMap((skill) => [
|
|
138
|
+
`## Skill: ${skill.name}`,
|
|
139
|
+
'',
|
|
140
|
+
skill.content,
|
|
141
|
+
'',
|
|
142
|
+
]),
|
|
143
|
+
].join('\n').trimEnd();
|
|
144
|
+
}
|
|
145
|
+
function loadConfiguredSkillPrompts(agentDir, skills) {
|
|
146
|
+
if (!Array.isArray(skills))
|
|
147
|
+
return [];
|
|
148
|
+
return skills.flatMap((rawSkill) => {
|
|
149
|
+
const skillName = sanitizeSkillName(rawSkill);
|
|
150
|
+
if (!skillName)
|
|
151
|
+
return [];
|
|
152
|
+
const skillFile = resolveSkillFile(agentDir, skillName);
|
|
153
|
+
if (!skillFile)
|
|
154
|
+
return [];
|
|
155
|
+
const source = readFileSync(skillFile, 'utf-8');
|
|
156
|
+
const parsed = parseSkillMarkdown(source);
|
|
157
|
+
const content = parsed.body || source.trim();
|
|
158
|
+
if (!content)
|
|
159
|
+
return [];
|
|
160
|
+
return [{ name: sanitizeSkillName(parsed.meta.name) || skillName, content }];
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
function resolveSkillFile(agentDir, skillName) {
|
|
164
|
+
const candidates = [
|
|
165
|
+
...(agentDir ? [
|
|
166
|
+
join(agentDir, 'skills', skillName, 'SKILL.md'),
|
|
167
|
+
join(agentDir, 'skills', `${skillName}.md`),
|
|
168
|
+
] : []),
|
|
169
|
+
join(getDataDir(), 'skills', skillName, 'SKILL.md'),
|
|
170
|
+
join(getDataDir(), 'skills', `${skillName}.md`),
|
|
171
|
+
];
|
|
172
|
+
return candidates.find((file) => existsSync(file) && statSync(file).size > 0);
|
|
173
|
+
}
|
|
174
|
+
function getDataDir() {
|
|
175
|
+
return process.env.AGENT_SPACES_DATA_DIR || DEFAULT_DATA_DIR;
|
|
176
|
+
}
|
|
177
|
+
function parseSkillMarkdown(source) {
|
|
178
|
+
const match = source.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?/);
|
|
179
|
+
if (!match)
|
|
180
|
+
return { meta: {}, body: source.trim() };
|
|
181
|
+
const meta = {};
|
|
182
|
+
for (const line of match[1].split(/\r?\n/)) {
|
|
183
|
+
const parsed = line.match(/^([A-Za-z0-9_-]+):\s*(.*)$/);
|
|
184
|
+
if (!parsed)
|
|
185
|
+
continue;
|
|
186
|
+
meta[parsed[1]] = parsed[2].trim().replace(/^['"]|['"]$/g, '');
|
|
187
|
+
}
|
|
188
|
+
return { meta, body: source.slice(match[0].length).trim() };
|
|
189
|
+
}
|
|
190
|
+
function sanitizeSkillName(name) {
|
|
191
|
+
const raw = basename(name ?? '').replace(/\.md$/i, '').trim();
|
|
192
|
+
return raw.replace(/[^a-zA-Z0-9._-]+/g, '-').replace(/^-+|-+$/g, '');
|
|
193
|
+
}
|
|
194
|
+
function buildLangChainTools(functionTools, output, options, log) {
|
|
72
195
|
if (!functionTools?.length)
|
|
73
196
|
return [];
|
|
74
197
|
return functionTools.map((runtimeTool) => tool(async (input) => {
|
|
198
|
+
const startedAt = Date.now();
|
|
75
199
|
const line = `Tool: ${runtimeTool.name} input=${JSON.stringify(input)}`;
|
|
200
|
+
log(`tool use | source=function name=${runtimeTool.name} descriptionChars=${runtimeTool.description.length} input=${summarizeForLog(input, 800)}`);
|
|
76
201
|
output.push(line);
|
|
77
202
|
options?.onEvent?.({ type: 'tool_use', id: runtimeTool.name, name: runtimeTool.name, input, line });
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
203
|
+
try {
|
|
204
|
+
const result = await runtimeTool.execute(input);
|
|
205
|
+
log(`tool result | source=function name=${runtimeTool.name} elapsedMs=${Date.now() - startedAt} output=${summarizeForLog(result, 1000)}`);
|
|
206
|
+
options?.onEvent?.({ type: 'tool_result', toolUseId: runtimeTool.name, result });
|
|
207
|
+
return stringifyToolResult(result);
|
|
208
|
+
}
|
|
209
|
+
catch (err) {
|
|
210
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
211
|
+
log(`tool error | source=function name=${runtimeTool.name} elapsedMs=${Date.now() - startedAt} error=${truncateForLog(message, 1000)}`);
|
|
212
|
+
if (err instanceof Error && err.stack)
|
|
213
|
+
console.error(err.stack);
|
|
214
|
+
throw err;
|
|
215
|
+
}
|
|
81
216
|
}, {
|
|
82
217
|
name: runtimeTool.name,
|
|
83
218
|
description: runtimeTool.description,
|
|
84
219
|
schema: z.object({}).passthrough(),
|
|
85
220
|
}));
|
|
86
221
|
}
|
|
87
|
-
function
|
|
222
|
+
export function resolveLangChainModelSettings(config) {
|
|
88
223
|
const model = config.model || 'gpt-4o-mini';
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
224
|
+
const configuredProvider = normalizeLangChainProvider(config.provider);
|
|
225
|
+
const inferredProvider = inferLangChainProviderFromBaseURL(config.baseURL);
|
|
226
|
+
const provider = configuredProvider === 'anthropic' && inferredProvider === 'openai'
|
|
227
|
+
? inferredProvider
|
|
228
|
+
: configuredProvider;
|
|
229
|
+
const plainModel = provider ? stripLangChainProviderPrefix(model) : model;
|
|
230
|
+
const providerCorrectionReason = provider !== configuredProvider
|
|
231
|
+
? `baseURL=${config.baseURL} is OpenAI-compatible, using ${provider} instead of ${configuredProvider}`
|
|
232
|
+
: undefined;
|
|
233
|
+
return {
|
|
234
|
+
provider,
|
|
235
|
+
modelIdentifier: provider ? `${provider}:${plainModel}` : plainModel,
|
|
236
|
+
providerCorrectionReason,
|
|
237
|
+
};
|
|
93
238
|
}
|
|
94
239
|
function normalizeLangChainProvider(provider) {
|
|
95
240
|
switch (provider) {
|
|
@@ -113,8 +258,223 @@ function buildModelConfig(config) {
|
|
|
113
258
|
configuration: config.baseURL ? { baseURL: config.baseURL } : undefined,
|
|
114
259
|
});
|
|
115
260
|
}
|
|
116
|
-
function
|
|
117
|
-
|
|
261
|
+
function inferLangChainProviderFromBaseURL(baseURL) {
|
|
262
|
+
if (!baseURL)
|
|
263
|
+
return undefined;
|
|
264
|
+
try {
|
|
265
|
+
const hostname = new URL(baseURL).hostname.toLowerCase();
|
|
266
|
+
if (hostname === 'open.bigmodel.cn' || hostname.endsWith('.bigmodel.cn'))
|
|
267
|
+
return 'openai';
|
|
268
|
+
}
|
|
269
|
+
catch {
|
|
270
|
+
return undefined;
|
|
271
|
+
}
|
|
272
|
+
return undefined;
|
|
273
|
+
}
|
|
274
|
+
function stripLangChainProviderPrefix(model) {
|
|
275
|
+
const match = /^(anthropic|openai|google-genai):(.+)$/i.exec(model);
|
|
276
|
+
return match?.[2] || model;
|
|
277
|
+
}
|
|
278
|
+
export function stringifyToolResult(result) {
|
|
279
|
+
if (result === undefined)
|
|
280
|
+
return 'null';
|
|
281
|
+
if (typeof result === 'string')
|
|
282
|
+
return result;
|
|
283
|
+
try {
|
|
284
|
+
return JSON.stringify(result, null, 2) ?? String(result);
|
|
285
|
+
}
|
|
286
|
+
catch {
|
|
287
|
+
return String(result);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
function createLangChainMcpClient(mcpServers, output, options, log) {
|
|
291
|
+
log(`normalizing MCP servers | requested=${Object.keys(mcpServers ?? {}).join(',') || '-'}`);
|
|
292
|
+
const normalizedMcpServers = normalizeLangChainMcpServers(mcpServers);
|
|
293
|
+
if (!normalizedMcpServers) {
|
|
294
|
+
log('normalizing MCP servers | none');
|
|
295
|
+
return undefined;
|
|
296
|
+
}
|
|
297
|
+
log(`normalized MCP servers | ${summarizeMcpServersForLog(normalizedMcpServers)}`);
|
|
298
|
+
return new MultiServerMCPClient({
|
|
299
|
+
throwOnLoadError: true,
|
|
300
|
+
prefixToolNameWithServerName: true,
|
|
301
|
+
additionalToolNamePrefix: 'mcp',
|
|
302
|
+
useStandardContentBlocks: false,
|
|
303
|
+
outputHandling: 'content',
|
|
304
|
+
mcpServers: normalizedMcpServers,
|
|
305
|
+
beforeToolCall: (request) => {
|
|
306
|
+
const name = formatMcpToolName(request.serverName, request.name);
|
|
307
|
+
const line = `Tool: ${name} input=${JSON.stringify(request.args ?? {})}`;
|
|
308
|
+
log(`tool use | source=mcp server=${request.serverName} name=${name} input=${summarizeForLog(request.args ?? {}, 800)}`);
|
|
309
|
+
output.push(line);
|
|
310
|
+
options?.onEvent?.({ type: 'tool_use', id: name, name, input: request.args ?? {}, line });
|
|
311
|
+
},
|
|
312
|
+
afterToolCall: (result) => {
|
|
313
|
+
const name = formatMcpToolName(result.serverName, result.name);
|
|
314
|
+
const outputText = stringifyToolResult(result.result);
|
|
315
|
+
log(`tool result | source=mcp server=${result.serverName} name=${name} chars=${outputText.length} output=${truncateForLog(outputText, 1000)}`);
|
|
316
|
+
options?.onEvent?.({ type: 'tool_result', toolUseId: name, result: outputText });
|
|
317
|
+
return { result: outputText };
|
|
318
|
+
},
|
|
319
|
+
onProgress: (progress, source) => {
|
|
320
|
+
if (source.type !== 'tool')
|
|
321
|
+
return;
|
|
322
|
+
const name = formatMcpToolName(source.server, source.name);
|
|
323
|
+
const progressText = progress.total
|
|
324
|
+
? `${progress.progress}/${progress.total}`
|
|
325
|
+
: String(progress.progress);
|
|
326
|
+
log(`tool progress | source=mcp server=${source.server} name=${name} progress=${progressText}${progress.message ? ` message=${truncateForLog(progress.message, 300)}` : ''}`);
|
|
327
|
+
},
|
|
328
|
+
onMessage: (message, source) => {
|
|
329
|
+
log(`mcp message | server=${source.server} level=${message.level ?? '-'} data=${summarizeForLog(message.data, 500)}`);
|
|
330
|
+
},
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
export function normalizeLangChainMcpServers(mcpServers) {
|
|
334
|
+
if (!mcpServers || Object.keys(mcpServers).length === 0)
|
|
335
|
+
return undefined;
|
|
336
|
+
return Object.fromEntries(Object.entries(mcpServers).map(([name, server]) => [name, normalizeLangChainMcpServer(server)]));
|
|
337
|
+
}
|
|
338
|
+
function normalizeLangChainMcpServer(server) {
|
|
339
|
+
if (!isRecord(server)) {
|
|
340
|
+
throw new Error('MCP server config must be an object.');
|
|
341
|
+
}
|
|
342
|
+
const normalized = normalizeOpenAgentCompatibleFetchMcpServer(server);
|
|
343
|
+
if (typeof normalized.url === 'string') {
|
|
344
|
+
return removeUndefined({
|
|
345
|
+
...normalized,
|
|
346
|
+
transport: normalized.transport === 'sse' || normalized.type === 'sse' ? 'sse' : 'http',
|
|
347
|
+
url: normalized.url,
|
|
348
|
+
headers: isStringRecord(normalized.headers) ? normalized.headers : undefined,
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
if (typeof normalized.command === 'string') {
|
|
352
|
+
return removeUndefined({
|
|
353
|
+
...normalized,
|
|
354
|
+
transport: 'stdio',
|
|
355
|
+
command: normalized.command,
|
|
356
|
+
args: Array.isArray(normalized.args) ? normalized.args.map(String) : [],
|
|
357
|
+
env: isStringRecord(normalized.env) ? normalized.env : undefined,
|
|
358
|
+
cwd: typeof normalized.cwd === 'string' ? normalized.cwd : undefined,
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
throw new Error('MCP server config requires either url or command.');
|
|
362
|
+
}
|
|
363
|
+
function normalizeOpenAgentCompatibleFetchMcpServer(server) {
|
|
364
|
+
const args = Array.isArray(server.args) ? server.args.map(String) : undefined;
|
|
365
|
+
const badFetchPackageIndex = args?.indexOf('@modelcontextprotocol/server-fetch') ?? -1;
|
|
366
|
+
if (String(server.command) !== 'npx' || !args || badFetchPackageIndex < 0)
|
|
367
|
+
return server;
|
|
368
|
+
return {
|
|
369
|
+
...server,
|
|
370
|
+
command: 'uvx',
|
|
371
|
+
args: ['mcp-server-fetch', ...args.slice(badFetchPackageIndex + 1)],
|
|
372
|
+
env: {
|
|
373
|
+
PYTHONIOENCODING: 'utf-8',
|
|
374
|
+
...(isStringRecord(server.env) ? server.env : {}),
|
|
375
|
+
},
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
function formatMcpToolName(serverName, toolName) {
|
|
379
|
+
return `mcp__${serverName}__${toolName}`;
|
|
380
|
+
}
|
|
381
|
+
function summarizeOptionsForLog(options) {
|
|
382
|
+
if (!options)
|
|
383
|
+
return '-';
|
|
384
|
+
return summarizeForLog({
|
|
385
|
+
maxTurns: options.maxTurns,
|
|
386
|
+
tools: options.tools,
|
|
387
|
+
functionTools: options.functionTools?.map((runtimeTool) => ({
|
|
388
|
+
name: runtimeTool.name,
|
|
389
|
+
descriptionChars: runtimeTool.description.length,
|
|
390
|
+
annotations: runtimeTool.annotations,
|
|
391
|
+
inputSchema: runtimeTool.inputSchema,
|
|
392
|
+
})),
|
|
393
|
+
mcpServers: Object.keys(options.mcpServers ?? {}),
|
|
394
|
+
skills: options.skills,
|
|
395
|
+
configDir: options.configDir,
|
|
396
|
+
sandboxDirs: options.sandboxDirs,
|
|
397
|
+
systemPromptChars: options.systemPrompt?.length,
|
|
398
|
+
userPromptChars: options.userPrompt?.length,
|
|
399
|
+
outputStyle: options.outputStyle,
|
|
400
|
+
resumeSessionId: options.resumeSessionId,
|
|
401
|
+
onEvent: options.onEvent ? 'set' : undefined,
|
|
402
|
+
}, 2000);
|
|
403
|
+
}
|
|
404
|
+
function summarizeAgentResultForLog(result) {
|
|
405
|
+
if (!isRecord(result))
|
|
406
|
+
return summarizeForLog(result, 1200);
|
|
407
|
+
const messages = Array.isArray(result.messages) ? result.messages : [];
|
|
408
|
+
return summarizeForLog({
|
|
409
|
+
keys: Object.keys(result),
|
|
410
|
+
messageCount: messages.length,
|
|
411
|
+
messages: messages.map((message, index) => summarizeMessageForLog(message, index)),
|
|
412
|
+
}, 2000);
|
|
413
|
+
}
|
|
414
|
+
function summarizeMessageForLog(message, index) {
|
|
415
|
+
if (!isRecord(message))
|
|
416
|
+
return { index, type: typeof message };
|
|
417
|
+
const content = stringifyMessageContent(message.content);
|
|
418
|
+
return removeUndefined({
|
|
419
|
+
index,
|
|
420
|
+
type: getMessageType(message) ?? message.type,
|
|
421
|
+
role: message.role,
|
|
422
|
+
name: message.name,
|
|
423
|
+
id: message.id,
|
|
424
|
+
contentChars: content.length,
|
|
425
|
+
contentPreview: truncateForLog(content, 300),
|
|
426
|
+
usage: message.usage_metadata,
|
|
427
|
+
responseMetadataKeys: isRecord(message.response_metadata) ? Object.keys(message.response_metadata) : undefined,
|
|
428
|
+
additionalKwargsKeys: isRecord(message.additional_kwargs) ? Object.keys(message.additional_kwargs) : undefined,
|
|
429
|
+
toolCallCount: Array.isArray(message.tool_calls) ? message.tool_calls.length : undefined,
|
|
430
|
+
invalidToolCallCount: Array.isArray(message.invalid_tool_calls) ? message.invalid_tool_calls.length : undefined,
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
function summarizeMcpServersForLog(mcpServers) {
|
|
434
|
+
return summarizeForLog(Object.fromEntries(Object.entries(mcpServers).map(([name, server]) => [name, summarizeMcpServerForLog(server)])), 2000);
|
|
435
|
+
}
|
|
436
|
+
function summarizeMcpServerForLog(server) {
|
|
437
|
+
const record = server;
|
|
438
|
+
return removeUndefined({
|
|
439
|
+
transport: record.transport,
|
|
440
|
+
url: typeof record.url === 'string' ? record.url : undefined,
|
|
441
|
+
command: typeof record.command === 'string' ? record.command : undefined,
|
|
442
|
+
args: Array.isArray(record.args) ? record.args : undefined,
|
|
443
|
+
cwd: typeof record.cwd === 'string' ? record.cwd : undefined,
|
|
444
|
+
headers: isStringRecord(record.headers) ? Object.keys(record.headers) : undefined,
|
|
445
|
+
env: isStringRecord(record.env) ? Object.keys(record.env) : undefined,
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
function summarizeEnvForLog(env) {
|
|
449
|
+
const configured = Object.entries(env)
|
|
450
|
+
.filter(([, value]) => Boolean(value))
|
|
451
|
+
.map(([key]) => key);
|
|
452
|
+
return configured.length ? configured.join(',') : '-';
|
|
453
|
+
}
|
|
454
|
+
function maskSensitiveConfig(config) {
|
|
455
|
+
return Object.fromEntries(Object.entries(config).map(([key, value]) => {
|
|
456
|
+
if (/api[_-]?key/i.test(key))
|
|
457
|
+
return [key, value ? 'set' : value];
|
|
458
|
+
if (key === 'configuration' && isRecord(value))
|
|
459
|
+
return [key, maskSensitiveConfig(value)];
|
|
460
|
+
return [key, value];
|
|
461
|
+
}));
|
|
462
|
+
}
|
|
463
|
+
function getObjectTypeName(value) {
|
|
464
|
+
return isRecord(value) && typeof value.constructor === 'function'
|
|
465
|
+
? value.constructor.name
|
|
466
|
+
: typeof value;
|
|
467
|
+
}
|
|
468
|
+
function summarizeForLog(value, maxLength = 300) {
|
|
469
|
+
if (typeof value === 'string')
|
|
470
|
+
return truncateForLog(value, maxLength);
|
|
471
|
+
return truncateForLog(stringifyToolResult(value), maxLength);
|
|
472
|
+
}
|
|
473
|
+
function truncateForLog(value, maxLength = 300) {
|
|
474
|
+
return value.length > maxLength ? `${value.slice(0, maxLength)}...` : value;
|
|
475
|
+
}
|
|
476
|
+
function buildProviderEnv(config, resolvedProvider) {
|
|
477
|
+
const provider = resolvedProvider ?? normalizeLangChainProvider(config.provider);
|
|
118
478
|
return {
|
|
119
479
|
OPENAI_API_KEY: provider === 'openai' ? config.apiKey : undefined,
|
|
120
480
|
OPENAI_BASE_URL: provider === 'openai' ? config.baseURL : undefined,
|
|
@@ -201,6 +561,9 @@ function numberFrom(value) {
|
|
|
201
561
|
function isRecord(value) {
|
|
202
562
|
return Boolean(value && typeof value === 'object');
|
|
203
563
|
}
|
|
564
|
+
function isStringRecord(value) {
|
|
565
|
+
return isRecord(value) && Object.values(value).every((entry) => typeof entry === 'string');
|
|
566
|
+
}
|
|
204
567
|
function removeUndefined(value) {
|
|
205
568
|
return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined));
|
|
206
569
|
}
|