easyrouter-config 1.0.2 → 1.0.3

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.
Files changed (2) hide show
  1. package/dist/index.js +83 -20
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -16,7 +16,7 @@ import {
16
16
  import { execa } from "execa";
17
17
  import pc from "picocolors";
18
18
  import { parseArgs } from "util";
19
- var VERSION = "0.1.0";
19
+ var VERSION = "0.1.1";
20
20
  var CLAUDE_BASE_URL = "https://easyrouter.io";
21
21
  var CODEX_BASE_URL = "https://easyrouter.io/v1";
22
22
  function parseCliArgs() {
@@ -75,6 +75,8 @@ ${pc.bold("\u539F\u7406:")}
75
75
  \u2022 Codex \u2192 ~/.codex/config.toml + ~/.codex/auth.json
76
76
  `);
77
77
  }
78
+ var IDLE_TIMEOUT_MS = 6e4;
79
+ var HARD_TIMEOUT_MS = 3e5;
78
80
  async function runZcf(opts) {
79
81
  const args = [
80
82
  "-y",
@@ -109,27 +111,86 @@ async function runZcf(opts) {
109
111
  "false"
110
112
  // 不装状态栏
111
113
  ];
114
+ const isWin = process.platform === "win32";
115
+ const cmd = isWin ? "npx.cmd" : "npx";
112
116
  let capturedOut = "";
113
117
  let capturedErr = "";
114
- try {
115
- const child = execa("npx", args, {
116
- stdio: opts.verbose ? "inherit" : "pipe",
117
- env: { ...process.env, FORCE_COLOR: opts.verbose ? "1" : "0" },
118
- reject: true
119
- });
120
- if (!opts.verbose) {
121
- child.stdout?.on("data", (chunk) => {
122
- capturedOut += chunk.toString();
123
- });
124
- child.stderr?.on("data", (chunk) => {
125
- capturedErr += chunk.toString();
126
- });
118
+ let lastDataAt = Date.now();
119
+ let killedReason = null;
120
+ const child = execa(cmd, args, {
121
+ stdio: ["ignore", "pipe", "pipe"],
122
+ env: {
123
+ ...process.env,
124
+ FORCE_COLOR: "0",
125
+ // 强制无颜色,免得 ANSI 干扰我们的检测
126
+ CI: "1",
127
+ // 让某些库自动进入"非交互模式"
128
+ npm_config_yes: "true"
129
+ // npx 自动 yes
130
+ },
131
+ reject: false,
132
+ // 我们自己处理退出码,避免 throw 时丢失输出
133
+ windowsHide: true
134
+ });
135
+ const handleChunk = (chunk, target) => {
136
+ const text2 = typeof chunk === "string" ? chunk : chunk.toString("utf8");
137
+ if (target === "out") capturedOut += text2;
138
+ else capturedErr += text2;
139
+ lastDataAt = Date.now();
140
+ if (opts.onProgress) {
141
+ const lines = text2.split(/\r?\n/).map((l) => l.trim()).filter(Boolean);
142
+ const last = lines[lines.length - 1];
143
+ if (last) opts.onProgress(last.slice(0, 80));
127
144
  }
128
- await child;
129
- } catch (err) {
130
- const detail = err?.stderr || err?.stdout || err?.message || String(err);
145
+ if (opts.verbose) {
146
+ process.stderr.write(text2);
147
+ }
148
+ };
149
+ child.stdout?.on("data", (c) => handleChunk(c, "out"));
150
+ child.stderr?.on("data", (c) => handleChunk(c, "err"));
151
+ const idleTimer = setInterval(() => {
152
+ if (Date.now() - lastDataAt > IDLE_TIMEOUT_MS) {
153
+ killedReason = `\u5B50\u8FDB\u7A0B\u5DF2 ${Math.floor(IDLE_TIMEOUT_MS / 1e3)} \u79D2\u65E0\u8F93\u51FA\uFF08\u7591\u4F3C\u5361\u5728\u4EA4\u4E92\u5F0F\u63D0\u95EE\u6216\u7F51\u7EDC\u95EE\u9898\uFF09`;
154
+ child.kill("SIGTERM");
155
+ setTimeout(() => {
156
+ try {
157
+ child.kill("SIGKILL");
158
+ } catch {
159
+ }
160
+ }, 5e3);
161
+ }
162
+ }, 5e3);
163
+ const hardTimer = setTimeout(() => {
164
+ killedReason = `\u5B50\u8FDB\u7A0B\u8D85\u8FC7 ${Math.floor(HARD_TIMEOUT_MS / 1e3)} \u79D2\u672A\u7ED3\u675F\uFF08\u5F3A\u5236\u8D85\u65F6\uFF09`;
165
+ child.kill("SIGTERM");
166
+ setTimeout(() => {
167
+ try {
168
+ child.kill("SIGKILL");
169
+ } catch {
170
+ }
171
+ }, 5e3);
172
+ }, HARD_TIMEOUT_MS);
173
+ const result = await child.catch((e) => e);
174
+ clearInterval(idleTimer);
175
+ clearTimeout(hardTimer);
176
+ const exitCode = result?.exitCode ?? null;
177
+ const signal = result?.signal ?? null;
178
+ if (killedReason) {
179
+ throw new Error(
180
+ `zcf \u8C03\u7528\u5931\u8D25\uFF1A${killedReason}
181
+
182
+ \u5E38\u89C1\u539F\u56E0\uFF1A
183
+ \u2022 \u6CA1\u88C5\u76EE\u6807\u5BA2\u6237\u7AEF\uFF08zcf \u8BD5\u56FE\u8BE2\u95EE\u662F\u5426\u5B89\u88C5\uFF09
184
+ \u2022 npm \u955C\u50CF/\u7F51\u7EDC\u6162\uFF0Cnpx \u4E0B\u8F7D zcf \u5305\u5361\u4F4F
185
+ \u2022 \u9632\u706B\u5899\u62E6\u622A\u4E86 registry.npmjs.org
186
+
187
+ \u5EFA\u8BAE\uFF1A\u7528 ${pc.green("--verbose")} \u91CD\u65B0\u8FD0\u884C\u67E5\u770B\u8BE6\u7EC6\u65E5\u5FD7`
188
+ );
189
+ }
190
+ if (exitCode !== 0 || signal) {
191
+ const detail = (capturedErr || capturedOut || "").slice(-2e3) || `exit ${exitCode}, signal ${signal}`;
131
192
  throw new Error(
132
- `zcf \u6267\u884C\u5931\u8D25 (code-type=${opts.codeType}):
193
+ `zcf \u5F02\u5E38\u9000\u51FA\uFF08code-type=${opts.codeType}, exit=${exitCode}\uFF09:
133
194
  ${detail}
134
195
 
135
196
  \u{1F4A1} \u7528 ${pc.green("--verbose")} \u91CD\u65B0\u8FD0\u884C\u53EF\u770B\u5230\u5B8C\u6574\u65E5\u5FD7`
@@ -263,7 +324,8 @@ async function main() {
263
324
  codeType: "cc",
264
325
  baseUrl: CLAUDE_BASE_URL,
265
326
  apiKey,
266
- verbose
327
+ verbose,
328
+ onProgress: (line) => s?.message(`\u914D\u7F6E Claude Code \xB7 ${pc.dim(line)}`)
267
329
  });
268
330
  s?.stop(pc.green("\u2713 Claude Code \u914D\u7F6E\u5B8C\u6210 ") + pc.dim("\u2192 ~/.claude/settings.json"));
269
331
  if (!s) log.success(pc.green("\u2713 Claude Code \u914D\u7F6E\u5B8C\u6210 \u2192 ~/.claude/settings.json"));
@@ -285,7 +347,8 @@ async function main() {
285
347
  codeType: "cx",
286
348
  baseUrl: CODEX_BASE_URL,
287
349
  apiKey,
288
- verbose
350
+ verbose,
351
+ onProgress: (line) => s?.message(`\u914D\u7F6E Codex \xB7 ${pc.dim(line)}`)
289
352
  });
290
353
  s?.stop(pc.green("\u2713 Codex \u914D\u7F6E\u5B8C\u6210 ") + pc.dim("\u2192 ~/.codex/config.toml"));
291
354
  if (!s) log.success(pc.green("\u2713 Codex \u914D\u7F6E\u5B8C\u6210 \u2192 ~/.codex/config.toml"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "easyrouter-config",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "🚀 一键把 EasyRouter 接入 Claude Code & Codex —— 粘贴 Key 即用",
5
5
  "type": "module",
6
6
  "bin": {