zen-code 4.0.0 → 4.1.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.
@@ -0,0 +1,237 @@
1
+ import "micromatch";
2
+ import "./index-DFARkGOA.mjs";
3
+ import { Low as n } from "lowdb";
4
+ import { JSONFile as d } from "lowdb/node";
5
+ import "yaml";
6
+ import r from "node:path";
7
+ class h {
8
+ db;
9
+ dbPath;
10
+ constructor(t) {
11
+ this.dbPath = r.join(t, ".claude", "task.json");
12
+ const a = new d(this.dbPath);
13
+ this.db = new n(a, this.getDefaultData());
14
+ }
15
+ getDefaultData() {
16
+ return {
17
+ version: "1.0",
18
+ lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
19
+ tasks: {},
20
+ history: [],
21
+ config: {
22
+ maxConcurrentAgents: 3,
23
+ retryLimit: 3,
24
+ autoResume: !1
25
+ }
26
+ };
27
+ }
28
+ /**
29
+ * 初始化数据库
30
+ */
31
+ async initialize() {
32
+ const t = await import("node:fs"), a = r.dirname(this.dbPath);
33
+ t.existsSync(a) || t.mkdirSync(a, { recursive: !0 }), await this.db.read(), this.db.data || (this.db.data = this.getDefaultData(), await this.db.write());
34
+ }
35
+ /**
36
+ * 获取单个任务
37
+ */
38
+ async getTask(t) {
39
+ return await this.db.read(), this.db.data.tasks[t];
40
+ }
41
+ /**
42
+ * 更新任务
43
+ */
44
+ async updateTask(t, a) {
45
+ await this.db.read();
46
+ const i = this.db.data.tasks[t];
47
+ return i ? (this.db.data.tasks[t] = {
48
+ ...i,
49
+ ...a
50
+ }, a.status && (a.status === "running" && !i.startedAt ? this.db.data.tasks[t].startedAt = (/* @__PURE__ */ new Date()).toISOString() : ["complete", "error", "review"].includes(a.status) && !i.completedAt && (this.db.data.tasks[t].completedAt = (/* @__PURE__ */ new Date()).toISOString())), this.db.data.lastUpdated = (/* @__PURE__ */ new Date()).toISOString(), await this.db.write(), !0) : !1;
51
+ }
52
+ /**
53
+ * 批量添加任务(用于 Plan 初始化)
54
+ */
55
+ async addTasks(t) {
56
+ await this.db.read();
57
+ for (const a of t)
58
+ this.db.data.tasks[a.id] = a;
59
+ this.db.data.lastUpdated = (/* @__PURE__ */ new Date()).toISOString(), await this.db.write();
60
+ }
61
+ /**
62
+ * 根据 status 获取任务列表
63
+ */
64
+ async getTasksByStatus(t) {
65
+ return await this.db.read(), Object.values(this.db.data.tasks).filter((a) => a.status === t);
66
+ }
67
+ /**
68
+ * 获取所有任务
69
+ */
70
+ async getAllTasks() {
71
+ return await this.db.read(), Object.values(this.db.data.tasks);
72
+ }
73
+ /**
74
+ * 添加执行记录
75
+ */
76
+ async addHistory(t) {
77
+ await this.db.read(), this.db.data.history.push(t), await this.db.write();
78
+ }
79
+ /**
80
+ * 获取执行历史
81
+ */
82
+ async getHistory(t) {
83
+ return await this.db.read(), t ? this.db.data.history.filter((a) => a.planId === t) : this.db.data.history;
84
+ }
85
+ /**
86
+ * 设置活跃 Plan ID
87
+ */
88
+ async setActivePlan(t) {
89
+ await this.db.read(), this.db.data.activePlanId = t, this.db.data.lastUpdated = (/* @__PURE__ */ new Date()).toISOString(), await this.db.write();
90
+ }
91
+ /**
92
+ * 获取活跃 Plan ID
93
+ */
94
+ async getActivePlan() {
95
+ return await this.db.read(), this.db.data.activePlanId;
96
+ }
97
+ /**
98
+ * 更新配置
99
+ */
100
+ async updateConfig(t) {
101
+ await this.db.read(), this.db.data.config = {
102
+ ...this.db.data.config,
103
+ ...t
104
+ }, this.db.data.lastUpdated = (/* @__PURE__ */ new Date()).toISOString(), await this.db.write();
105
+ }
106
+ /**
107
+ * 获取配置
108
+ */
109
+ async getConfig() {
110
+ return await this.db.read(), this.db.data.config;
111
+ }
112
+ /**
113
+ * 清空所有任务(慎用)
114
+ */
115
+ async clearAllTasks() {
116
+ await this.db.read(), this.db.data.tasks = {}, this.db.data.activePlanId = void 0, this.db.data.lastUpdated = (/* @__PURE__ */ new Date()).toISOString(), await this.db.write();
117
+ }
118
+ /**
119
+ * 删除单个任务
120
+ */
121
+ async deleteTask(t) {
122
+ return await this.db.read(), this.db.data.tasks[t] ? (delete this.db.data.tasks[t], this.db.data.lastUpdated = (/* @__PURE__ */ new Date()).toISOString(), await this.db.write(), !0) : !1;
123
+ }
124
+ /**
125
+ * 获取数据库路径(用于测试)
126
+ */
127
+ getDbPath() {
128
+ return this.dbPath;
129
+ }
130
+ }
131
+ class o {
132
+ store = null;
133
+ projectRoot;
134
+ constructor(t) {
135
+ this.projectRoot = t;
136
+ }
137
+ /**
138
+ * 初始化 Store
139
+ */
140
+ async initialize() {
141
+ this.store || (this.store = new h(this.projectRoot), await this.store.initialize());
142
+ }
143
+ /**
144
+ * 确保 Store 已初始化
145
+ */
146
+ ensureInitialized() {
147
+ if (!this.store)
148
+ throw new Error("TasksStore not initialized. Call initialize() first.");
149
+ }
150
+ /**
151
+ * 获取所有任务
152
+ */
153
+ async getAllTasks() {
154
+ return this.ensureInitialized(), await this.store.getAllTasks();
155
+ }
156
+ /**
157
+ * 根据 status 获取任务
158
+ */
159
+ async getTasksByStatus(t) {
160
+ return this.ensureInitialized(), await this.store.getTasksByStatus(t);
161
+ }
162
+ /**
163
+ * 获取单个任务
164
+ */
165
+ async getTask(t) {
166
+ return this.ensureInitialized(), await this.store.getTask(t);
167
+ }
168
+ /**
169
+ * 更新任务状态
170
+ */
171
+ async updateTaskStatus(t, a) {
172
+ return this.ensureInitialized(), await this.store.updateTask(t, { status: a });
173
+ }
174
+ /**
175
+ * 删除任务
176
+ */
177
+ async deleteTask(t) {
178
+ return this.ensureInitialized(), await this.store.deleteTask(t);
179
+ }
180
+ /**
181
+ * 批量添加任务
182
+ */
183
+ async addTasks(t) {
184
+ this.ensureInitialized(), await this.store.addTasks(t);
185
+ }
186
+ /**
187
+ * 获取活跃 Plan ID
188
+ */
189
+ async getActivePlan() {
190
+ return this.ensureInitialized(), await this.store.getActivePlan();
191
+ }
192
+ /**
193
+ * 设置活跃 Plan ID
194
+ */
195
+ async setActivePlan(t) {
196
+ this.ensureInitialized(), await this.store.setActivePlan(t);
197
+ }
198
+ /**
199
+ * 获取任务统计
200
+ */
201
+ async getTaskStats() {
202
+ const t = await this.getAllTasks();
203
+ return {
204
+ total: t.length,
205
+ pickup: t.filter((a) => a.status === "pickup").length,
206
+ running: t.filter((a) => a.status === "running").length,
207
+ complete: t.filter((a) => a.status === "complete").length,
208
+ error: t.filter((a) => a.status === "error").length,
209
+ review: t.filter((a) => a.status === "review").length,
210
+ feedback: t.filter((a) => a.status === "feedback").length
211
+ };
212
+ }
213
+ /**
214
+ * 获取执行历史
215
+ */
216
+ async getHistory(t) {
217
+ return this.ensureInitialized(), await this.store.getHistory(t);
218
+ }
219
+ /**
220
+ * 清空所有任务(慎用)
221
+ */
222
+ async clearAllTasks() {
223
+ this.ensureInitialized(), await this.store.clearAllTasks();
224
+ }
225
+ }
226
+ let e = null;
227
+ function k(s) {
228
+ if (!e) {
229
+ if (!s)
230
+ throw new Error("projectRoot is required for first initialization");
231
+ e = new o(s);
232
+ }
233
+ return e;
234
+ }
235
+ export {
236
+ k as getTasksStore
237
+ };
package/dist/zen-code.mjs CHANGED
@@ -1,3 +1,3 @@
1
1
  import "./MultiLineTextInput-DjNvaZzA.mjs";
2
2
  import "chalk";
3
- import "./app-QzdcE86p.mjs";
3
+ import "./app-C-NaCZSh.mjs";
package/dist/zen-init.mjs CHANGED
@@ -1,13 +1,13 @@
1
- import { a as c, j as e, T as r, B as o, M as B, r as U } from "./MultiLineTextInput-DjNvaZzA.mjs";
1
+ import { a as c, j as e, T as r, B as o, M as B, r as R } from "./MultiLineTextInput-DjNvaZzA.mjs";
2
2
  import "chalk";
3
- import { u as D, M as T, S as O, g as R } from "./get_allowed_models-DWso18Ri.mjs";
4
- import { c as K, u as M, i as v } from "./index-BG-c4_r3.mjs";
5
- const L = (s, t, x) => {
6
- const d = parseInt(s.slice(1, 3), 16), l = parseInt(s.slice(3, 5), 16), a = parseInt(s.slice(5, 7), 16), C = parseInt(t.slice(1, 3), 16), I = parseInt(t.slice(3, 5), 16), p = parseInt(t.slice(5, 7), 16), j = Math.round(d + x * (C - d)), m = Math.round(l + x * (I - l)), g = Math.round(a + x * (p - a));
3
+ import { u as D, M as T, S as U, g as _ } from "./get_allowed_models-DWso18Ri.mjs";
4
+ import { configStore as K, updateConfig as M, initDb as v } from "./index-DFARkGOA.mjs";
5
+ const L = (t, s, x) => {
6
+ const d = parseInt(t.slice(1, 3), 16), l = parseInt(t.slice(3, 5), 16), a = parseInt(t.slice(5, 7), 16), C = parseInt(s.slice(1, 3), 16), I = parseInt(s.slice(3, 5), 16), p = parseInt(s.slice(5, 7), 16), j = Math.round(d + x * (C - d)), m = Math.round(l + x * (I - l)), g = Math.round(a + x * (p - a));
7
7
  return `#${((1 << 24) + (j << 16) + (m << 8) + g).toString(16).slice(1).toUpperCase()}`;
8
8
  }, N = ({
9
- text: s,
10
- highlightColor: t = "#00FFFF",
9
+ text: t,
10
+ highlightColor: s = "#00FFFF",
11
11
  // Cyan
12
12
  baseColor: x = "#003333",
13
13
  // Dark Cyan
@@ -19,21 +19,21 @@ const L = (s, t, x) => {
19
19
  return c.useEffect(() => {
20
20
  if (a !== void 0) return;
21
21
  const j = setInterval(() => {
22
- I((m) => (m + 1) % (s.length + l * 2));
22
+ I((m) => (m + 1) % (t.length + l * 2));
23
23
  }, d);
24
24
  return () => clearInterval(j);
25
- }, [s.length, l, d, a]), /* @__PURE__ */ e.jsx(r, { children: s.split("").map((j, m) => {
26
- const g = p - l, y = Math.abs(m - g);
27
- let h = x, b = !1;
28
- if (y < l) {
29
- const w = Math.cos(y / l * (Math.PI / 2)), n = Math.pow(w, 2);
30
- h = L(x, t, n), b = y < 1;
25
+ }, [t.length, l, d, a]), /* @__PURE__ */ e.jsx(r, { children: t.split("").map((j, m) => {
26
+ const g = p - l, b = Math.abs(m - g);
27
+ let h = x, y = !1;
28
+ if (b < l) {
29
+ const w = Math.cos(b / l * (Math.PI / 2)), n = Math.pow(w, 2);
30
+ h = L(x, s, n), y = b < 1;
31
31
  }
32
- return /* @__PURE__ */ e.jsx(r, { color: h, bold: b, children: j }, m);
32
+ return /* @__PURE__ */ e.jsx(r, { color: h, bold: y, children: j }, m);
33
33
  }) });
34
- }, k = ({ onNext: s, onExit: t }) => {
34
+ }, k = ({ onNext: t, onExit: s }) => {
35
35
  D((l, a) => {
36
- a.return ? s() : a.ctrl && l === "c" && t();
36
+ a.return ? t() : a.ctrl && l === "c" && s();
37
37
  });
38
38
  const [x, d] = c.useState(0);
39
39
  return c.useEffect(() => {
@@ -133,8 +133,8 @@ const L = (s, t, x) => {
133
133
  }, F = [
134
134
  { label: "OpenAI (GPT-4, o1 等)", value: "openai" },
135
135
  { label: "Anthropic (Claude)", value: "anthropic" }
136
- ], V = ({ provider: s, onSelect: t, onNext: x }) => {
137
- const d = c.useMemo(() => s ? [s] : [], [s]);
136
+ ], V = ({ provider: t, onSelect: s, onNext: x }) => {
137
+ const d = c.useMemo(() => t ? [t] : [], [t]);
138
138
  return /* @__PURE__ */ e.jsxs(o, { flexDirection: "column", flexGrow: 1, justifyContent: "center", paddingX: 2, children: [
139
139
  /* @__PURE__ */ e.jsxs(o, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, marginBottom: 1, children: [
140
140
  /* @__PURE__ */ e.jsxs(o, { flexDirection: "row", justifyContent: "space-between", borderBottom: !1, children: [
@@ -157,7 +157,7 @@ const L = (s, t, x) => {
157
157
  options: F,
158
158
  values: d,
159
159
  onChange: (l) => {
160
- l.length > 0 && t(l[0]);
160
+ l.length > 0 && s(l[0]);
161
161
  },
162
162
  onSubmit: x,
163
163
  singleSelect: !0,
@@ -185,8 +185,8 @@ const L = (s, t, x) => {
185
185
  openai: "https://platform.openai.com/api-keys",
186
186
  anthropic: "https://console.anthropic.com/settings/keys"
187
187
  }, X = ({
188
- provider: s,
189
- apiKey: t,
188
+ provider: t,
189
+ apiKey: s,
190
190
  baseUrl: x,
191
191
  onApiKeyChange: d,
192
192
  onBaseUrlChange: l,
@@ -195,10 +195,10 @@ const L = (s, t, x) => {
195
195
  onExit: I,
196
196
  error: p
197
197
  }) => {
198
- const [j, m] = c.useState("apiKey"), [g, y] = c.useState(t), [h, b] = c.useState(x), w = A[s], n = (u) => {
199
- y(u), d(u);
198
+ const [j, m] = c.useState("apiKey"), [g, b] = c.useState(s), [h, y] = c.useState(x), w = A[t], n = (u) => {
199
+ b(u), d(u);
200
200
  }, i = (u) => {
201
- b(u), l(u);
201
+ y(u), l(u);
202
202
  }, f = (u) => {
203
203
  u = u.trim(), n(u), a();
204
204
  }, E = (u) => {
@@ -218,7 +218,7 @@ const L = (s, t, x) => {
218
218
  /* @__PURE__ */ e.jsxs(o, { flexDirection: "column", marginTop: 1, children: [
219
219
  /* @__PURE__ */ e.jsxs(o, { marginBottom: 1, children: [
220
220
  /* @__PURE__ */ e.jsx(r, { color: "blue", children: "PROVIDER::" }),
221
- /* @__PURE__ */ e.jsx(r, { color: "white", children: s.toUpperCase() })
221
+ /* @__PURE__ */ e.jsx(r, { color: "white", children: t.toUpperCase() })
222
222
  ] }),
223
223
  /* @__PURE__ */ e.jsx(o, { marginBottom: 1, children: /* @__PURE__ */ e.jsx(r, { bold: !0, children: "Base URL (可选)" }) }),
224
224
  /* @__PURE__ */ e.jsx(o, { marginBottom: 1, children: /* @__PURE__ */ e.jsxs(r, { color: "gray", children: [
@@ -237,7 +237,7 @@ const L = (s, t, x) => {
237
237
  /* @__PURE__ */ e.jsx(o, { marginBottom: 1, children: /* @__PURE__ */ e.jsx(r, { bold: !0, children: "API 密钥" }) }),
238
238
  /* @__PURE__ */ e.jsx(o, { marginBottom: 1, children: /* @__PURE__ */ e.jsxs(r, { color: "gray", children: [
239
239
  "获取地址: ",
240
- G[s]
240
+ G[t]
241
241
  ] }) }),
242
242
  /* @__PURE__ */ e.jsx(o, { marginBottom: j === "apiKey" && p ? 0 : 1, children: /* @__PURE__ */ e.jsx(
243
243
  B,
@@ -269,8 +269,8 @@ const L = (s, t, x) => {
269
269
  /* @__PURE__ */ e.jsx(o, { flexDirection: "row", justifyContent: "center", children: /* @__PURE__ */ e.jsx(r, { color: "gray", dimColor: !0, children: "[Ctrl+C 退出]" }) })
270
270
  ] });
271
271
  }, Y = ({
272
- provider: s,
273
- models: t,
272
+ provider: t,
273
+ models: s,
274
274
  selectedModel: x,
275
275
  onSelect: d,
276
276
  onRefresh: l,
@@ -280,17 +280,17 @@ const L = (s, t, x) => {
280
280
  isLoading: p,
281
281
  error: j
282
282
  }) => {
283
- const m = t.map((h) => ({
283
+ const m = s.map((h) => ({
284
284
  label: h.name,
285
285
  value: h.id
286
- })), g = x ? [x] : [], y = c.useCallback(
286
+ })), g = x ? [x] : [], b = c.useCallback(
287
287
  (h) => {
288
288
  h.length > 0 && (d(h[0]), a());
289
289
  },
290
290
  [d, a]
291
291
  );
292
- return D((h, b) => {
293
- (h === "r" || h === "R") && !p && l(), b.escape && C();
292
+ return D((h, y) => {
293
+ (h === "r" || h === "R") && !p && l(), y.escape && C();
294
294
  }), /* @__PURE__ */ e.jsxs(o, { flexDirection: "column", flexGrow: 1, justifyContent: "center", paddingX: 2, children: [
295
295
  /* @__PURE__ */ e.jsxs(o, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, marginBottom: 1, children: [
296
296
  /* @__PURE__ */ e.jsxs(o, { flexDirection: "row", justifyContent: "space-between", borderBottom: !1, children: [
@@ -300,15 +300,15 @@ const L = (s, t, x) => {
300
300
  /* @__PURE__ */ e.jsxs(o, { flexDirection: "column", marginTop: 1, children: [
301
301
  /* @__PURE__ */ e.jsxs(o, { marginBottom: 1, children: [
302
302
  /* @__PURE__ */ e.jsx(r, { color: "blue", children: "提供商 ::" }),
303
- /* @__PURE__ */ e.jsx(r, { color: "white", children: s.toUpperCase() })
303
+ /* @__PURE__ */ e.jsx(r, { color: "white", children: t.toUpperCase() })
304
304
  ] }),
305
- p && t.length === 0 && /* @__PURE__ */ e.jsx(o, { marginBottom: 1, children: /* @__PURE__ */ e.jsxs(r, { children: [
306
- /* @__PURE__ */ e.jsx(O, { type: "dots" }),
305
+ p && s.length === 0 && /* @__PURE__ */ e.jsx(o, { marginBottom: 1, children: /* @__PURE__ */ e.jsxs(r, { children: [
306
+ /* @__PURE__ */ e.jsx(U, { type: "dots" }),
307
307
  " 检测可用模型中..."
308
308
  ] }) }),
309
- !p && t.length === 0 && /* @__PURE__ */ e.jsx(o, { marginBottom: 1, children: /* @__PURE__ */ e.jsx(r, { color: "yellow", children: "未找到可用模型,请按 R 刷新" }) }),
310
- !p && t.length > 0 && /* @__PURE__ */ e.jsx(o, { marginBottom: 1, children: /* @__PURE__ */ e.jsx(r, { color: "gray", children: "选择您偏好的模型:" }) }),
311
- !p && t.length > 0 && /* @__PURE__ */ e.jsx(
309
+ !p && s.length === 0 && /* @__PURE__ */ e.jsx(o, { marginBottom: 1, children: /* @__PURE__ */ e.jsx(r, { color: "yellow", children: "未找到可用模型,请按 R 刷新" }) }),
310
+ !p && s.length > 0 && /* @__PURE__ */ e.jsx(o, { marginBottom: 1, children: /* @__PURE__ */ e.jsx(r, { color: "gray", children: "选择您偏好的模型:" }) }),
311
+ !p && s.length > 0 && /* @__PURE__ */ e.jsx(
312
312
  T,
313
313
  {
314
314
  options: m,
@@ -316,7 +316,7 @@ const L = (s, t, x) => {
316
316
  onChange: (h) => {
317
317
  h.length > 0 && d(h[0]);
318
318
  },
319
- onSubmit: y,
319
+ onSubmit: b,
320
320
  singleSelect: !0,
321
321
  autoFocus: !0
322
322
  }
@@ -342,7 +342,7 @@ const L = (s, t, x) => {
342
342
  }, H = {
343
343
  openai: "OpenAI",
344
344
  anthropic: "Anthropic"
345
- }, $ = ({ provider: s, model: t, onExit: x }) => (D((d, l) => {
345
+ }, $ = ({ provider: t, model: s, onExit: x }) => (D((d, l) => {
346
346
  (d || l.return) && x();
347
347
  }), /* @__PURE__ */ e.jsx(o, { flexDirection: "column", flexGrow: 1, justifyContent: "center", paddingX: 2, children: /* @__PURE__ */ e.jsxs(o, { flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 1, marginBottom: 1, children: [
348
348
  /* @__PURE__ */ e.jsxs(o, { flexDirection: "row", justifyContent: "space-between", borderBottom: !1, children: [
@@ -357,11 +357,11 @@ const L = (s, t, x) => {
357
357
  /* @__PURE__ */ e.jsxs(o, { flexDirection: "column", marginBottom: 2, gap: 1, children: [
358
358
  /* @__PURE__ */ e.jsxs(o, { children: [
359
359
  /* @__PURE__ */ e.jsx(r, { color: "blue", children: "提供商 ::" }),
360
- /* @__PURE__ */ e.jsx(r, { color: "white", children: H[s] })
360
+ /* @__PURE__ */ e.jsx(r, { color: "white", children: H[t] })
361
361
  ] }),
362
362
  /* @__PURE__ */ e.jsxs(o, { children: [
363
363
  /* @__PURE__ */ e.jsx(r, { color: "blue", children: "模型 ::" }),
364
- /* @__PURE__ */ e.jsx(r, { color: "white", children: t })
364
+ /* @__PURE__ */ e.jsx(r, { color: "white", children: s })
365
365
  ] }),
366
366
  /* @__PURE__ */ e.jsxs(o, { children: [
367
367
  /* @__PURE__ */ e.jsx(r, { color: "blue", children: "配置路径 ::" }),
@@ -395,8 +395,8 @@ const L = (s, t, x) => {
395
395
  isLoading: !1,
396
396
  error: null
397
397
  }, W = () => {
398
- const [s, t] = c.useState(z), [x, d] = c.useState([]), l = c.useCallback(() => {
399
- t((n) => {
398
+ const [t, s] = c.useState(z), [x, d] = c.useState([]), l = c.useCallback(() => {
399
+ s((n) => {
400
400
  if (n.step === "model" && !n.selectedModel)
401
401
  return { ...n, error: "请选择一个模型" };
402
402
  if (n.step === "apiAndBaseUrl") {
@@ -408,12 +408,12 @@ const L = (s, t, x) => {
408
408
  return f < i.length - 1 ? { ...n, step: i[f + 1], error: null } : n;
409
409
  });
410
410
  }, []), a = c.useCallback(() => {
411
- t((n) => {
411
+ s((n) => {
412
412
  const i = ["welcome", "provider", "apiAndBaseUrl", "model", "complete"], f = i.indexOf(n.step);
413
413
  return f > 0 ? { ...n, step: i[f - 1], error: null } : n;
414
414
  });
415
415
  }, []), C = c.useCallback((n) => {
416
- process.env.MODEL_PROVIDER = n, t((i) => ({
416
+ process.env.MODEL_PROVIDER = n, s((i) => ({
417
417
  ...i,
418
418
  provider: n,
419
419
  baseUrl: A[n],
@@ -421,106 +421,114 @@ const L = (s, t, x) => {
421
421
  selectedModel: ""
422
422
  }));
423
423
  }, []), I = c.useCallback((n) => {
424
- t((i) => ({ ...i, apiKey: n, error: null }));
424
+ s((i) => ({ ...i, apiKey: n, error: null }));
425
425
  }, []), p = c.useCallback((n) => {
426
- t((i) => ({ ...i, baseUrl: n, error: null }));
426
+ s((i) => ({ ...i, baseUrl: n, error: null }));
427
427
  }, []), j = c.useCallback((n) => {
428
- t((i) => ({ ...i, selectedModel: n, error: null }));
428
+ s((i) => ({ ...i, selectedModel: n, error: null }));
429
429
  }, []), m = c.useCallback((n) => {
430
- t((i) => ({ ...i, error: n }));
430
+ s((i) => ({ ...i, error: n }));
431
431
  }, []), g = c.useCallback((n) => {
432
- t((i) => ({ ...i, isLoading: n }));
433
- }, []), y = c.useCallback(async (n, i) => {
432
+ s((i) => ({ ...i, isLoading: n }));
433
+ }, []), b = c.useCallback(async (n, i) => {
434
434
  g(!0), m(null);
435
435
  try {
436
436
  const f = process.env.MODEL_PROVIDER, E = process.env.OPENAI_API_KEY, u = process.env.ANTHROPIC_API_KEY;
437
437
  process.env.MODEL_PROVIDER = n, n === "openai" ? process.env.OPENAI_API_KEY = i || "temp" : process.env.ANTHROPIC_API_KEY = i || "temp";
438
- const _ = (await R()).filter((P) => P.provider === n);
439
- d(_), f && (process.env.MODEL_PROVIDER = f), E && (process.env.OPENAI_API_KEY = E), u && (process.env.ANTHROPIC_API_KEY = u);
438
+ const P = (await _()).filter((O) => O.provider === n);
439
+ d(P), f && (process.env.MODEL_PROVIDER = f), E && (process.env.OPENAI_API_KEY = E), u && (process.env.ANTHROPIC_API_KEY = u);
440
440
  } catch (f) {
441
441
  m(`加载模型失败: ${f instanceof Error ? f.message : String(f)}`), d([]);
442
442
  } finally {
443
443
  g(!1);
444
444
  }
445
445
  }, []), h = c.useCallback(async () => {
446
- if (!s.provider || !s.apiKey || !s.selectedModel)
446
+ if (!t.provider || !t.apiKey || !t.selectedModel)
447
447
  return m("配置不完整"), !1;
448
448
  g(!0), m(null);
449
449
  try {
450
450
  const n = {
451
- main_model: s.selectedModel,
452
- model_provider: s.provider
451
+ provider_id: t.provider,
452
+ model_id: t.selectedModel,
453
+ providers: [
454
+ {
455
+ id: t.provider,
456
+ type: t.provider,
457
+ apiKey: t.apiKey,
458
+ baseUrl: t.baseUrl || A[t.provider]
459
+ }
460
+ ]
453
461
  };
454
- return s.provider === "openai" ? (n.openai_api_key = s.apiKey, s.baseUrl && s.baseUrl !== A.openai && (n.openai_base_url = s.baseUrl)) : (n.anthropic_api_key = s.apiKey, s.baseUrl && s.baseUrl !== A.anthropic && (n.anthropic_base_url = s.baseUrl)), await M(n), !0;
462
+ return await M(n), !0;
455
463
  } catch (n) {
456
464
  return m(`保存配置失败: ${n instanceof Error ? n.message : String(n)}`), !1;
457
465
  } finally {
458
466
  g(!1);
459
467
  }
460
- }, [s]), b = c.useCallback(() => {
468
+ }, [t]), y = c.useCallback(() => {
461
469
  process.exit(0);
462
470
  }, []);
463
471
  c.useEffect(() => {
464
- s.step === "model" && s.provider && s.apiKey && y(s.provider, s.apiKey);
465
- }, [s.step, s.provider, s.apiKey, y]), D((n, i) => {
472
+ t.step === "model" && t.provider && t.apiKey && b(t.provider, t.apiKey);
473
+ }, [t.step, t.provider, t.apiKey, b]), D((n, i) => {
466
474
  i.ctrl && n === "c" ? process.exit(0) : i.escape && a();
467
475
  });
468
476
  const w = () => {
469
- switch (s.step) {
477
+ switch (t.step) {
470
478
  case "welcome":
471
- return /* @__PURE__ */ e.jsx(k, { onNext: l, onExit: b });
479
+ return /* @__PURE__ */ e.jsx(k, { onNext: l, onExit: y });
472
480
  case "provider":
473
481
  return /* @__PURE__ */ e.jsx(
474
482
  V,
475
483
  {
476
- provider: s.provider,
484
+ provider: t.provider,
477
485
  onSelect: (n) => {
478
486
  C(n);
479
487
  },
480
488
  onNext: l,
481
- onExit: b
489
+ onExit: y
482
490
  }
483
491
  );
484
492
  case "apiAndBaseUrl":
485
493
  return /* @__PURE__ */ e.jsx(
486
494
  X,
487
495
  {
488
- provider: s.provider,
489
- apiKey: s.apiKey,
490
- baseUrl: s.baseUrl,
496
+ provider: t.provider,
497
+ apiKey: t.apiKey,
498
+ baseUrl: t.baseUrl,
491
499
  onApiKeyChange: I,
492
500
  onBaseUrlChange: p,
493
501
  onNext: l,
494
502
  onBack: a,
495
- onExit: b,
496
- error: s.error
503
+ onExit: y,
504
+ error: t.error
497
505
  }
498
506
  );
499
507
  case "model":
500
508
  return /* @__PURE__ */ e.jsx(
501
509
  Y,
502
510
  {
503
- provider: s.provider,
511
+ provider: t.provider,
504
512
  models: x,
505
- selectedModel: s.selectedModel,
513
+ selectedModel: t.selectedModel,
506
514
  onSelect: j,
507
- onRefresh: () => y(s.provider, s.apiKey),
515
+ onRefresh: () => b(t.provider, t.apiKey),
508
516
  onNext: async () => {
509
517
  await h() && l();
510
518
  },
511
519
  onBack: a,
512
- onExit: b,
513
- isLoading: s.isLoading,
514
- error: s.error
520
+ onExit: y,
521
+ isLoading: t.isLoading,
522
+ error: t.error
515
523
  }
516
524
  );
517
525
  case "complete":
518
- return /* @__PURE__ */ e.jsx($, { provider: s.provider, model: s.selectedModel, onExit: b });
526
+ return /* @__PURE__ */ e.jsx($, { provider: t.provider, model: t.selectedModel, onExit: y });
519
527
  }
520
528
  };
521
529
  return /* @__PURE__ */ e.jsx(o, { flexDirection: "column", height: "100%", width: "100%", children: w() });
522
530
  };
523
531
  async function Z() {
524
- await v(), U(/* @__PURE__ */ e.jsx(W, {}));
532
+ await v(), R(/* @__PURE__ */ e.jsx(W, {}));
525
533
  }
526
534
  Z();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zen-code",
3
- "version": "4.0.0",
3
+ "version": "4.1.0",
4
4
  "description": "",
5
5
  "main": "./dist/cli.mjs",
6
6
  "bin": "./dist/cli.mjs",
@@ -65,8 +65,8 @@
65
65
  "vitest": "^4.0.18",
66
66
  "@codegraph/agent": "1.0.0",
67
67
  "@codegraph/config": "1.0.0",
68
- "ink-pro": "1.0.0",
69
- "@codegraph/union-client": "1.0.0"
68
+ "@codegraph/union-client": "1.0.0",
69
+ "ink-pro": "1.0.0"
70
70
  },
71
71
  "babel": {
72
72
  "presets": [