@zhongqian97-code/ecode 0.3.3 → 0.3.5
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/index.js +55 -8
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -94,7 +94,14 @@ function loadConfig() {
|
|
|
94
94
|
logDir: process.env.ECODE_LOG_DIR ?? fileConfig.logDir ?? DEFAULTS.logDir,
|
|
95
95
|
// contextLimit 仅支持配置文件配置:数值类型在文件中更直观,
|
|
96
96
|
// 环境变量还需要 parseInt 转换,增加出错风险
|
|
97
|
-
contextLimit: fileConfig.contextLimit
|
|
97
|
+
contextLimit: fileConfig.contextLimit,
|
|
98
|
+
// ECODE_SYSTEM_PROMPT 环境变量优先;未设时从配置文件读取;
|
|
99
|
+
// 两者均未设时保持 undefined(由 resolveSystemPrompt 决定使用内置默认值)。
|
|
100
|
+
// 注意:空字符串 "" 是有效值(表示禁用),?? 不会跳过空字符串。
|
|
101
|
+
systemPrompt: process.env.ECODE_SYSTEM_PROMPT ?? fileConfig.systemPrompt,
|
|
102
|
+
// providers/defaultProvider 仅支持配置文件配置,不支持环境变量注入
|
|
103
|
+
providers: fileConfig.providers,
|
|
104
|
+
defaultProvider: fileConfig.defaultProvider
|
|
98
105
|
};
|
|
99
106
|
}
|
|
100
107
|
|
|
@@ -102,14 +109,23 @@ function loadConfig() {
|
|
|
102
109
|
import { useState as useState3, useCallback, useRef as useRef2, useEffect as useEffect3, useMemo } from "react";
|
|
103
110
|
import { Box as Box6, useInput as useInput2, useStdout, useStdin } from "ink";
|
|
104
111
|
|
|
105
|
-
// src/
|
|
112
|
+
// src/providers/openai.ts
|
|
106
113
|
import OpenAI from "openai";
|
|
107
|
-
function
|
|
114
|
+
function createOpenAIProvider(profile) {
|
|
108
115
|
const openai = new OpenAI({
|
|
109
|
-
baseURL:
|
|
110
|
-
apiKey:
|
|
116
|
+
baseURL: profile.baseUrl,
|
|
117
|
+
apiKey: profile.apiKey
|
|
111
118
|
});
|
|
119
|
+
const capabilities = Object.freeze(
|
|
120
|
+
Object.defineProperties({}, {
|
|
121
|
+
supportsTools: { value: true, writable: false, enumerable: true, configurable: false },
|
|
122
|
+
supportsReasoningStream: { value: true, writable: false, enumerable: true, configurable: false },
|
|
123
|
+
supportsImages: { value: false, writable: false, enumerable: true, configurable: false },
|
|
124
|
+
supportsJsonSchema: { value: true, writable: false, enumerable: true, configurable: false }
|
|
125
|
+
})
|
|
126
|
+
);
|
|
112
127
|
return {
|
|
128
|
+
capabilities,
|
|
113
129
|
/**
|
|
114
130
|
* stream 方法向 LLM 发起一次流式对话请求,返回异步可迭代的 chunk 序列。
|
|
115
131
|
*
|
|
@@ -123,12 +139,13 @@ function createLLMClient(config2) {
|
|
|
123
139
|
*
|
|
124
140
|
* @param messages 完整的对话历史,包含 user/assistant/tool 所有轮次
|
|
125
141
|
* @param tools 可选的工具列表,不传或传空数组时不附加 tools 字段
|
|
142
|
+
* @param signal 可选的 AbortSignal,用于取消请求
|
|
126
143
|
*/
|
|
127
144
|
stream(messages, tools, signal) {
|
|
128
145
|
return {
|
|
129
146
|
[Symbol.asyncIterator]: async function* () {
|
|
130
147
|
const requestParams = {
|
|
131
|
-
model:
|
|
148
|
+
model: profile.model,
|
|
132
149
|
messages,
|
|
133
150
|
stream: true,
|
|
134
151
|
stream_options: { include_usage: true }
|
|
@@ -196,6 +213,36 @@ function createLLMClient(config2) {
|
|
|
196
213
|
};
|
|
197
214
|
}
|
|
198
215
|
|
|
216
|
+
// src/providers/index.ts
|
|
217
|
+
function createProvider(profile) {
|
|
218
|
+
return createOpenAIProvider(profile);
|
|
219
|
+
}
|
|
220
|
+
function resolveActiveProfile(config2, providerName) {
|
|
221
|
+
if (providerName !== void 0) {
|
|
222
|
+
const profile = config2.providers?.[providerName];
|
|
223
|
+
if (!profile) {
|
|
224
|
+
throw new Error(`Provider '${providerName}' not found`);
|
|
225
|
+
}
|
|
226
|
+
return profile;
|
|
227
|
+
}
|
|
228
|
+
if (config2.defaultProvider) {
|
|
229
|
+
const profile = config2.providers?.[config2.defaultProvider];
|
|
230
|
+
if (profile) return profile;
|
|
231
|
+
}
|
|
232
|
+
if (config2.providers) {
|
|
233
|
+
if (config2.providers["default"]) {
|
|
234
|
+
return config2.providers["default"];
|
|
235
|
+
}
|
|
236
|
+
const first = Object.values(config2.providers)[0];
|
|
237
|
+
if (first) return first;
|
|
238
|
+
}
|
|
239
|
+
return {
|
|
240
|
+
baseUrl: config2.baseUrl,
|
|
241
|
+
apiKey: config2.apiKey,
|
|
242
|
+
model: config2.model
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
|
|
199
246
|
// src/repl.ts
|
|
200
247
|
import * as readline from "readline/promises";
|
|
201
248
|
|
|
@@ -1993,7 +2040,7 @@ function App({ config: config2, version: version2, autoMode: autoMode2 = false,
|
|
|
1993
2040
|
totalLinesRef.current = totalLines;
|
|
1994
2041
|
const pendingConfirmRef = useRef2(null);
|
|
1995
2042
|
const abortControllerRef = useRef2(null);
|
|
1996
|
-
const llmRef = useRef2(llmClient ??
|
|
2043
|
+
const llmRef = useRef2(llmClient ?? createProvider(resolveActiveProfile(config2)));
|
|
1997
2044
|
const inputRef = useRef2(null);
|
|
1998
2045
|
const [skillTools, setSkillTools] = useState3([]);
|
|
1999
2046
|
const skillToolsRef = useRef2([]);
|
|
@@ -2677,7 +2724,7 @@ for (const dir of [builtinSkillsDir, userSkillsDir, projectSkillsDir]) {
|
|
|
2677
2724
|
var trustedSkillDirs = [builtinSkillsDir, userSkillsDir, projectSkillsDir];
|
|
2678
2725
|
if (pipeMode) {
|
|
2679
2726
|
const prompt = await readStdin();
|
|
2680
|
-
const llm =
|
|
2727
|
+
const llm = createProvider(resolveActiveProfile(finalConfig));
|
|
2681
2728
|
await runPipe(prompt, llm);
|
|
2682
2729
|
process.exit(0);
|
|
2683
2730
|
}
|