apex-dev 3.10.18 → 3.10.20
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/cli.js +98 -26
- package/dist/index.js +14 -4
- package/package.json +1 -1
package/cli.js
CHANGED
|
@@ -145,6 +145,8 @@ function getDownloadUrl() {
|
|
|
145
145
|
return `https://github.com/Marcus-Mok-GH/apex-dev/releases/download/v${VERSION}/apex-dev-${platform}-${arch}`;
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
+
const DOWNLOAD_TIMEOUT = 10 * 1000;
|
|
149
|
+
|
|
148
150
|
function downloadBinary(destPath) {
|
|
149
151
|
const url = getDownloadUrl();
|
|
150
152
|
console.error(`Downloading apex-dev v${VERSION} for ${detectPlatform().platform}-${detectPlatform().arch}...`);
|
|
@@ -152,33 +154,80 @@ function downloadBinary(destPath) {
|
|
|
152
154
|
|
|
153
155
|
return new Promise((resolve, reject) => {
|
|
154
156
|
const file = fs.createWriteStream(destPath, { mode: 0o755 });
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
157
|
+
let settled = false;
|
|
158
|
+
|
|
159
|
+
function cleanupAndReject(err) {
|
|
160
|
+
if (settled) return;
|
|
161
|
+
settled = true;
|
|
162
|
+
file.destroy();
|
|
163
|
+
try { fs.unlinkSync(destPath); } catch {}
|
|
164
|
+
reject(err);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function onFileError(err) {
|
|
168
|
+
cleanupAndReject(new Error(`Write stream error: ${err.message}`));
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
file.on("error", onFileError);
|
|
172
|
+
|
|
173
|
+
const req = https.get(url, (response) => {
|
|
174
|
+
if (response.statusCode === 302 || response.statusCode === 301) {
|
|
175
|
+
const redirectReq = https.get(response.headers.location, (redirectRes) => {
|
|
176
|
+
if (redirectRes.statusCode !== 200) {
|
|
177
|
+
cleanupAndReject(new Error(`Download failed with status ${redirectRes.statusCode}`));
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function onFinish() {
|
|
182
|
+
file.removeListener("error", onFileError);
|
|
183
|
+
redirectReq.removeListener("error", onRedirectError);
|
|
184
|
+
redirectReq.removeListener("timeout", onRedirectTimeout);
|
|
185
|
+
file.close();
|
|
186
|
+
resolve();
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
file.on("finish", onFinish);
|
|
190
|
+
redirectRes.pipe(file);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
function onRedirectError(err) {
|
|
194
|
+
cleanupAndReject(new Error(`Redirect request error: ${err.message}`));
|
|
170
195
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
return;
|
|
196
|
+
function onRedirectTimeout() {
|
|
197
|
+
cleanupAndReject(new Error("Download redirect timed out"));
|
|
174
198
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
.
|
|
199
|
+
|
|
200
|
+
redirectReq.on("error", onRedirectError);
|
|
201
|
+
redirectReq.setTimeout(DOWNLOAD_TIMEOUT, onRedirectTimeout);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (response.statusCode !== 200) {
|
|
206
|
+
cleanupAndReject(new Error(`Download failed with status ${response.statusCode}`));
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function onFinish() {
|
|
211
|
+
file.removeListener("error", onFileError);
|
|
212
|
+
req.removeListener("error", onReqError);
|
|
213
|
+
req.removeListener("timeout", onReqTimeout);
|
|
214
|
+
file.close();
|
|
215
|
+
resolve();
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
file.on("finish", onFinish);
|
|
219
|
+
response.pipe(file);
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
function onReqError(err) {
|
|
223
|
+
cleanupAndReject(new Error(`Download request error: ${err.message}`));
|
|
224
|
+
}
|
|
225
|
+
function onReqTimeout() {
|
|
226
|
+
cleanupAndReject(new Error("Download timed out"));
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
req.on("error", onReqError);
|
|
230
|
+
req.setTimeout(DOWNLOAD_TIMEOUT, onReqTimeout);
|
|
182
231
|
});
|
|
183
232
|
}
|
|
184
233
|
|
|
@@ -186,7 +235,17 @@ async function ensureBinary() {
|
|
|
186
235
|
const localPath = getLocalBinaryPath();
|
|
187
236
|
|
|
188
237
|
if (fs.existsSync(localPath)) {
|
|
189
|
-
|
|
238
|
+
// Check for empty/partial downloads and remove them
|
|
239
|
+
try {
|
|
240
|
+
const stat = fs.statSync(localPath);
|
|
241
|
+
if (stat.size === 0) {
|
|
242
|
+
fs.unlinkSync(localPath);
|
|
243
|
+
} else {
|
|
244
|
+
return localPath;
|
|
245
|
+
}
|
|
246
|
+
} catch {
|
|
247
|
+
try { fs.unlinkSync(localPath); } catch {}
|
|
248
|
+
}
|
|
190
249
|
}
|
|
191
250
|
|
|
192
251
|
try {
|
|
@@ -195,6 +254,7 @@ async function ensureBinary() {
|
|
|
195
254
|
return localPath;
|
|
196
255
|
} catch (err) {
|
|
197
256
|
console.error(`Failed to download binary: ${err.message}`);
|
|
257
|
+
try { fs.unlinkSync(localPath); } catch {}
|
|
198
258
|
return null;
|
|
199
259
|
}
|
|
200
260
|
}
|
|
@@ -221,6 +281,10 @@ function runWithBun() {
|
|
|
221
281
|
const child = spawn(bunPath, [distPath, ...process.argv.slice(2)], {
|
|
222
282
|
stdio: "inherit",
|
|
223
283
|
});
|
|
284
|
+
child.on("error", (err) => {
|
|
285
|
+
console.error(`Failed to launch bun: ${err.message}`);
|
|
286
|
+
process.exit(1);
|
|
287
|
+
});
|
|
224
288
|
child.on("exit", (code) => {
|
|
225
289
|
process.exit(code || 0);
|
|
226
290
|
});
|
|
@@ -229,6 +293,10 @@ function runWithBun() {
|
|
|
229
293
|
const child = spawn(bunPath, [scriptPath, ...process.argv.slice(2)], {
|
|
230
294
|
stdio: "inherit",
|
|
231
295
|
});
|
|
296
|
+
child.on("error", (err) => {
|
|
297
|
+
console.error(`Failed to launch bun: ${err.message}`);
|
|
298
|
+
process.exit(1);
|
|
299
|
+
});
|
|
232
300
|
child.on("exit", (code) => {
|
|
233
301
|
process.exit(code || 0);
|
|
234
302
|
});
|
|
@@ -329,6 +397,10 @@ async function main() {
|
|
|
329
397
|
const child = spawn(binaryPath, args, {
|
|
330
398
|
stdio: "inherit",
|
|
331
399
|
});
|
|
400
|
+
child.on("error", (err) => {
|
|
401
|
+
console.error(`Failed to launch binary: ${err.message}`);
|
|
402
|
+
process.exit(1);
|
|
403
|
+
});
|
|
332
404
|
child.on("exit", (code) => {
|
|
333
405
|
process.exit(code || 0);
|
|
334
406
|
});
|
package/dist/index.js
CHANGED
|
@@ -867,16 +867,26 @@ The user asks you to implement a new feature. You respond in multiple steps:
|
|
|
867
867
|
deepseek: { model: "deepseek/deepseek-chat-v3", temperature: 0.1, maxTokens: 8192 },
|
|
868
868
|
minimax: { model: "minimax/minimax-01", temperature: 0.1, maxTokens: 8192 }
|
|
869
869
|
};
|
|
870
|
-
const
|
|
870
|
+
const os = __require("os");
|
|
871
|
+
let savedProvider = null;
|
|
871
872
|
try {
|
|
872
|
-
const configPath = path.join(
|
|
873
|
+
const configPath = path.join(os.homedir(), ".apex-dev", "config.json");
|
|
873
874
|
if (fs.existsSync(configPath)) {
|
|
874
875
|
const savedConfig = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
875
|
-
|
|
876
|
-
|
|
876
|
+
const hasEnvKey = Object.values(PROVIDERS).some((p) => process.env[p.envKey]);
|
|
877
|
+
if (!hasEnvKey) {
|
|
878
|
+
for (const [providerKey, provider] of Object.entries(PROVIDERS)) {
|
|
879
|
+
if (savedConfig[providerKey]) {
|
|
880
|
+
currentProvider = providerKey;
|
|
881
|
+
process.env[provider.envKey] = savedConfig[providerKey];
|
|
882
|
+
savedProvider = providerKey;
|
|
883
|
+
break;
|
|
884
|
+
}
|
|
885
|
+
}
|
|
877
886
|
}
|
|
878
887
|
}
|
|
879
888
|
} catch (e) {}
|
|
889
|
+
const _initialProvider = PROVIDERS[currentProvider];
|
|
880
890
|
const _initialKey = process.env[_initialProvider.envKey] || "no-key";
|
|
881
891
|
let _internalClient = new OpenAI({
|
|
882
892
|
apiKey: _initialKey,
|