@atlisp/agent 0.1.11 → 0.1.13

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/README.md CHANGED
@@ -100,23 +100,52 @@ mcp:
100
100
 
101
101
  ## 环境变量
102
102
 
103
- 配置可被环境变量覆盖(优先级最高):
103
+ 配置可被环境变量覆盖(优先级最高)。支持两种方式:
104
+
105
+ ### 方式1: 命令行环境变量
104
106
 
105
107
  ```bash
106
108
  # LLM
107
109
  export LLM_PROVIDER=deepseek
110
+ export LLM_BASE_URL=https://api.deepseek.com
108
111
  export LLM_MODEL=deepseek-v4-flash
109
- export DEEPSEEK_API_KEY=sk-xxxxx
112
+ export LLM_API_KEY=sk-xxxxx
110
113
  export LLM_TEMPERATURE=0.7
111
114
  export LLM_MAX_TOKENS=2048
112
115
 
113
116
  # MCP
114
117
  export MCP_MODE=stdio
118
+ export MCP_URL=http://localhost:8120
115
119
  export MCP_COMMAND=atlisp-mcp
116
- export MCP_ARGS="--stdio"
117
120
 
118
121
  # Agent
122
+ export AGENT_ENABLED=true
123
+ export AGENT_MAX_STEPS=500
119
124
  export AGENT_VERBOSE=true
125
+ ```
126
+
127
+ ### 方式2: .env 文件
128
+
129
+ 在 `~/.atlisp/.env` 文件中配置:
130
+
131
+ ```env
132
+ # LLM 配置
133
+ LLM_PROVIDER=deepseek
134
+ LLM_BASE_URL=https://api.deepseek.com
135
+ LLM_MODEL=deepseek-v4-flash
136
+ LLM_API_KEY=sk-xxxxx
137
+ LLM_TEMPERATURE=0.7
138
+ LLM_MAX_TOKENS=2048
139
+
140
+ # MCP 配置
141
+ MCP_MODE=stdio
142
+ MCP_URL=http://localhost:8120
143
+
144
+ # Agent 配置
145
+ AGENT_VERBOSE=true
146
+ ```
147
+
148
+ 优先级: 命令行环境变量 > .env 文件 > atlisp.json
120
149
  export AGENT_MAX_STEPS=20
121
150
  ```
122
151
 
package/config.js CHANGED
@@ -15,6 +15,45 @@ function getConfigDir() {
15
15
  return path.join(os.homedir(), '.atlisp');
16
16
  }
17
17
 
18
+ function getEnvPath() {
19
+ return path.join(os.homedir(), '.atlisp', '.env');
20
+ }
21
+
22
+ function loadEnvFile() {
23
+ const envPath = getEnvPath();
24
+ const envVars = {};
25
+
26
+ if (fs.existsSync(envPath)) {
27
+ try {
28
+ const content = fs.readFileSync(envPath, 'utf-8');
29
+ const lines = content.split('\n');
30
+ for (const line of lines) {
31
+ const trimmed = line.trim();
32
+ if (!trimmed || trimmed.startsWith('#')) continue;
33
+ const idx = trimmed.indexOf('=');
34
+ if (idx > 0) {
35
+ const key = trimmed.substring(0, idx).trim();
36
+ let val = trimmed.substring(idx + 1).trim();
37
+ if ((val.startsWith('"') && val.endsWith('"')) || (val.startsWith("'") && val.endsWith("'"))) {
38
+ val = val.slice(1, -1);
39
+ }
40
+ envVars[key] = val;
41
+ }
42
+ }
43
+ } catch (e) {
44
+ console.error(`[Config] .env 文件加载失败: ${e.message}`);
45
+ }
46
+ }
47
+
48
+ for (const [key, val] of Object.entries(process.env)) {
49
+ if (val !== undefined && val !== '') {
50
+ envVars[key] = val;
51
+ }
52
+ }
53
+
54
+ return envVars;
55
+ }
56
+
18
57
  function getDefaultConfig() {
19
58
  return {
20
59
  agent: {
@@ -71,8 +110,7 @@ function loadConfigFile() {
71
110
  }
72
111
  }
73
112
 
74
- saveDefaultConfig(jsonPath);
75
- return {};
113
+ return null;
76
114
  }
77
115
 
78
116
  function deepMerge(target, source) {
@@ -91,8 +129,13 @@ let config = null;
91
129
 
92
130
  function loadConfig() {
93
131
  const fileConfig = loadConfigFile();
94
- let merged = deepMerge(getDefaultConfig(), fileConfig);
95
132
 
133
+ if (fileConfig === null) {
134
+ const jsonPath = getConfigPath();
135
+ saveDefaultConfig(jsonPath);
136
+ }
137
+
138
+ let merged = deepMerge(getDefaultConfig(), fileConfig);
96
139
  return merged;
97
140
  }
98
141
 
@@ -104,15 +147,42 @@ function getConfig() {
104
147
  }
105
148
 
106
149
  export function getAgentConfig() {
107
- return getConfig().agent;
150
+ const config = getConfig().agent;
151
+ const envVars = loadEnvFile();
152
+
153
+ const envOverrides = {};
154
+ if (envVars.AGENT_ENABLED) envOverrides.enabled = envVars.AGENT_ENABLED === 'true';
155
+ if (envVars.AGENT_MAX_STEPS) envOverrides.maxSteps = parseInt(envVars.AGENT_MAX_STEPS);
156
+ if (envVars.AGENT_VERBOSE) envOverrides.verbose = envVars.AGENT_VERBOSE === 'true';
157
+
158
+ return { ...config, ...envOverrides };
108
159
  }
109
160
 
110
161
  export function getLlmConfig() {
111
- return getConfig().llm;
162
+ const config = getConfig().llm;
163
+ const envVars = loadEnvFile();
164
+
165
+ const envOverrides = {};
166
+ if (envVars.LLM_PROVIDER) envOverrides.provider = envVars.LLM_PROVIDER;
167
+ if (envVars.LLM_BASE_URL) envOverrides.baseURL = envVars.LLM_BASE_URL;
168
+ if (envVars.LLM_MODEL) envOverrides.model = envVars.LLM_MODEL;
169
+ if (envVars.LLM_API_KEY) envOverrides.apiKey = envVars.LLM_API_KEY;
170
+ if (envVars.LLM_TEMPERATURE) envOverrides.temperature = parseFloat(envVars.LLM_TEMPERATURE);
171
+ if (envVars.LLM_MAX_TOKENS) envOverrides.maxTokens = parseInt(envVars.LLM_MAX_TOKENS);
172
+
173
+ return { ...config, ...envOverrides };
112
174
  }
113
175
 
114
176
  export function getMcpConfig() {
115
- return getConfig().mcp;
177
+ const config = getConfig().mcp;
178
+ const envVars = loadEnvFile();
179
+
180
+ const envOverrides = {};
181
+ if (envVars.MCP_MODE) envOverrides.mode = envVars.MCP_MODE;
182
+ if (envVars.MCP_URL) envOverrides.url = envVars.MCP_URL;
183
+ if (envVars.MCP_COMMAND) envOverrides.command = envVars.MCP_COMMAND;
184
+
185
+ return { ...config, ...envOverrides };
116
186
  }
117
187
 
118
188
  export { getConfig };
@@ -16,8 +16,10 @@ export class StdioMcpClient {
16
16
  async connect() {
17
17
  return new Promise((resolve, reject) => {
18
18
  try {
19
- this.proc = spawn(this.command, this.args, {
19
+ const npxPath = process.platform === 'win32' ? 'npx.cmd' : 'npx';
20
+ this.proc = spawn(npxPath, ['-y', this.command, ...this.args], {
20
21
  stdio: ['pipe', 'pipe', 'pipe'],
22
+ shell: true,
21
23
  });
22
24
 
23
25
  this.proc.stdout.on('data', (data) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlisp/agent",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "description": "AI Agent for @lisp - Connects to MCP Server for CAD operations",
5
5
  "type": "module",
6
6
  "main": "index.js",