echopai 2.6.0 → 2.6.1
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/bin.js +147 -151
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/bin.ts
|
|
4
4
|
import { spawn } from "node:child_process";
|
|
5
|
-
import {
|
|
6
|
-
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
7
6
|
import { Command as Command31, Option as Option23 } from "commander";
|
|
8
7
|
|
|
9
8
|
// src/_generated/commands.ts
|
|
@@ -3057,6 +3056,137 @@ function buildCommandTree(program, dispatch) {
|
|
|
3057
3056
|
}
|
|
3058
3057
|
}
|
|
3059
3058
|
|
|
3059
|
+
// src/runtime/dist.ts
|
|
3060
|
+
import { spawnSync } from "node:child_process";
|
|
3061
|
+
import { createHash } from "node:crypto";
|
|
3062
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
3063
|
+
var RELEASE_BASE = process.env.ECHOPAI_RELEASE_BASE?.replace(/\/+$/, "") || "https://downloads.echopai.com/echopai-cli-releases";
|
|
3064
|
+
var VERSION_RE = /^[0-9]+\.[0-9]+\.[0-9]+(-\S+)?$/;
|
|
3065
|
+
var SHA256_RE = /^[a-f0-9]{64}$/;
|
|
3066
|
+
var FETCH_TIMEOUT_MS = 8000;
|
|
3067
|
+
function isStandaloneFromUrl(url) {
|
|
3068
|
+
return url.includes("$bunfs") || url.includes("~BUN");
|
|
3069
|
+
}
|
|
3070
|
+
function isStandaloneBinary() {
|
|
3071
|
+
return isStandaloneFromUrl(import.meta.url);
|
|
3072
|
+
}
|
|
3073
|
+
function computePlatformKey(i) {
|
|
3074
|
+
let arch = i.arch === "x64" || i.arch === "amd64" ? "x64" : i.arch === "arm64" ? "arm64" : null;
|
|
3075
|
+
if (!arch)
|
|
3076
|
+
return null;
|
|
3077
|
+
if (i.platform === "darwin") {
|
|
3078
|
+
if (arch === "x64" && i.isRosetta)
|
|
3079
|
+
arch = "arm64";
|
|
3080
|
+
return `darwin-${arch}`;
|
|
3081
|
+
}
|
|
3082
|
+
if (i.platform === "win32") {
|
|
3083
|
+
return arch === "x64" ? "windows-x64" : null;
|
|
3084
|
+
}
|
|
3085
|
+
if (i.platform === "linux") {
|
|
3086
|
+
if (arch === "x64") {
|
|
3087
|
+
if (i.isMusl)
|
|
3088
|
+
return "linux-x64-musl";
|
|
3089
|
+
return i.hasAvx2 ? "linux-x64" : "linux-x64-baseline";
|
|
3090
|
+
}
|
|
3091
|
+
return i.isMusl ? "linux-arm64-musl" : "linux-arm64";
|
|
3092
|
+
}
|
|
3093
|
+
return null;
|
|
3094
|
+
}
|
|
3095
|
+
function detectMusl() {
|
|
3096
|
+
return existsSync("/lib/libc.musl-x86_64.so.1") || existsSync("/lib/libc.musl-aarch64.so.1");
|
|
3097
|
+
}
|
|
3098
|
+
function detectAvx2() {
|
|
3099
|
+
try {
|
|
3100
|
+
return /\bavx2\b/.test(readFileSync("/proc/cpuinfo", "utf8"));
|
|
3101
|
+
} catch {
|
|
3102
|
+
return false;
|
|
3103
|
+
}
|
|
3104
|
+
}
|
|
3105
|
+
function detectRosetta() {
|
|
3106
|
+
try {
|
|
3107
|
+
const r = spawnSync("sysctl", ["-n", "sysctl.proc_translated"], {
|
|
3108
|
+
encoding: "utf8",
|
|
3109
|
+
timeout: 1000
|
|
3110
|
+
});
|
|
3111
|
+
return r.stdout.trim() === "1";
|
|
3112
|
+
} catch {
|
|
3113
|
+
return false;
|
|
3114
|
+
}
|
|
3115
|
+
}
|
|
3116
|
+
function detectPlatformKey() {
|
|
3117
|
+
return computePlatformKey({
|
|
3118
|
+
platform: process.platform,
|
|
3119
|
+
arch: process.arch,
|
|
3120
|
+
isMusl: process.platform === "linux" ? detectMusl() : false,
|
|
3121
|
+
hasAvx2: process.platform === "linux" && process.arch === "x64" ? detectAvx2() : true,
|
|
3122
|
+
isRosetta: process.platform === "darwin" && process.arch === "x64" ? detectRosetta() : false
|
|
3123
|
+
});
|
|
3124
|
+
}
|
|
3125
|
+
function parseManifestChecksum(manifest, platform) {
|
|
3126
|
+
if (!manifest || typeof manifest !== "object")
|
|
3127
|
+
return null;
|
|
3128
|
+
const platforms = manifest.platforms;
|
|
3129
|
+
if (!platforms || typeof platforms !== "object")
|
|
3130
|
+
return null;
|
|
3131
|
+
const entry = platforms[platform];
|
|
3132
|
+
if (!entry || typeof entry !== "object")
|
|
3133
|
+
return null;
|
|
3134
|
+
const cs = entry.checksum;
|
|
3135
|
+
return typeof cs === "string" && SHA256_RE.test(cs) ? cs : null;
|
|
3136
|
+
}
|
|
3137
|
+
async function fetchText(url) {
|
|
3138
|
+
const ac = new AbortController;
|
|
3139
|
+
const timer = setTimeout(() => ac.abort(), FETCH_TIMEOUT_MS);
|
|
3140
|
+
try {
|
|
3141
|
+
const res = await fetch(url, { signal: ac.signal });
|
|
3142
|
+
if (!res.ok)
|
|
3143
|
+
return null;
|
|
3144
|
+
return await res.text();
|
|
3145
|
+
} catch {
|
|
3146
|
+
return null;
|
|
3147
|
+
} finally {
|
|
3148
|
+
clearTimeout(timer);
|
|
3149
|
+
}
|
|
3150
|
+
}
|
|
3151
|
+
async function resolveLatestFromCdn() {
|
|
3152
|
+
const txt = await fetchText(`${RELEASE_BASE}/latest`);
|
|
3153
|
+
if (txt == null)
|
|
3154
|
+
return null;
|
|
3155
|
+
const v = txt.trim();
|
|
3156
|
+
return VERSION_RE.test(v) ? v : null;
|
|
3157
|
+
}
|
|
3158
|
+
async function fetchManifest(version) {
|
|
3159
|
+
const txt = await fetchText(`${RELEASE_BASE}/${version}/manifest.json`);
|
|
3160
|
+
if (txt == null)
|
|
3161
|
+
return null;
|
|
3162
|
+
try {
|
|
3163
|
+
return JSON.parse(txt);
|
|
3164
|
+
} catch {
|
|
3165
|
+
return null;
|
|
3166
|
+
}
|
|
3167
|
+
}
|
|
3168
|
+
function binaryUrl(version, platform) {
|
|
3169
|
+
const name = platform.startsWith("windows-") ? "echopai.exe" : "echopai";
|
|
3170
|
+
return `${RELEASE_BASE}/${version}/${platform}/${name}`;
|
|
3171
|
+
}
|
|
3172
|
+
async function downloadAndVerify(url, expectedSha) {
|
|
3173
|
+
const ac = new AbortController;
|
|
3174
|
+
const timer = setTimeout(() => ac.abort(), FETCH_TIMEOUT_MS * 4);
|
|
3175
|
+
try {
|
|
3176
|
+
const res = await fetch(url, { signal: ac.signal });
|
|
3177
|
+
if (!res.ok)
|
|
3178
|
+
throw new Error(`下载失败 HTTP ${res.status}: ${url}`);
|
|
3179
|
+
const buf = Buffer.from(await res.arrayBuffer());
|
|
3180
|
+
const actual = createHash("sha256").update(buf).digest("hex");
|
|
3181
|
+
if (actual !== expectedSha) {
|
|
3182
|
+
throw new Error(`校验和不匹配(期望 ${expectedSha},实际 ${actual})`);
|
|
3183
|
+
}
|
|
3184
|
+
return buf;
|
|
3185
|
+
} finally {
|
|
3186
|
+
clearTimeout(timer);
|
|
3187
|
+
}
|
|
3188
|
+
}
|
|
3189
|
+
|
|
3060
3190
|
// src/runtime/invoker.ts
|
|
3061
3191
|
import AjvPkg from "ajv";
|
|
3062
3192
|
import addFormatsPkg from "ajv-formats";
|
|
@@ -3563,9 +3693,9 @@ function resolveRequestId(serverHeader, clientGenerated) {
|
|
|
3563
3693
|
// src/runtime/trace.ts
|
|
3564
3694
|
import {
|
|
3565
3695
|
appendFileSync,
|
|
3566
|
-
existsSync as
|
|
3696
|
+
existsSync as existsSync3,
|
|
3567
3697
|
mkdirSync as mkdirSync2,
|
|
3568
|
-
readFileSync as
|
|
3698
|
+
readFileSync as readFileSync3,
|
|
3569
3699
|
renameSync,
|
|
3570
3700
|
statSync
|
|
3571
3701
|
} from "node:fs";
|
|
@@ -3586,7 +3716,7 @@ function appendTrace(record, opts) {
|
|
|
3586
3716
|
const maxBytes = opts?.ringMaxBytes ?? RING_MAX_BYTES;
|
|
3587
3717
|
try {
|
|
3588
3718
|
mkdirSync2(dirname(file), { recursive: true });
|
|
3589
|
-
if (
|
|
3719
|
+
if (existsSync3(file)) {
|
|
3590
3720
|
const size = statSync(file).size;
|
|
3591
3721
|
if (size >= maxBytes) {
|
|
3592
3722
|
renameSync(file, file + ".1");
|
|
@@ -3598,9 +3728,9 @@ function appendTrace(record, opts) {
|
|
|
3598
3728
|
}
|
|
3599
3729
|
function readNdjsonLines(file) {
|
|
3600
3730
|
try {
|
|
3601
|
-
if (!
|
|
3731
|
+
if (!existsSync3(file))
|
|
3602
3732
|
return [];
|
|
3603
|
-
const raw =
|
|
3733
|
+
const raw = readFileSync3(file, "utf-8");
|
|
3604
3734
|
const out = [];
|
|
3605
3735
|
for (const line of raw.split(`
|
|
3606
3736
|
`)) {
|
|
@@ -3824,12 +3954,12 @@ function renderError(env) {
|
|
|
3824
3954
|
}
|
|
3825
3955
|
|
|
3826
3956
|
// src/runtime/update_check.ts
|
|
3827
|
-
import { readFileSync as
|
|
3957
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3, renameSync as renameSync2 } from "node:fs";
|
|
3828
3958
|
import os2 from "node:os";
|
|
3829
3959
|
import path2 from "node:path";
|
|
3830
3960
|
|
|
3831
3961
|
// src/version.ts
|
|
3832
|
-
var CLI_VERSION = "2.
|
|
3962
|
+
var CLI_VERSION = "2.6.1";
|
|
3833
3963
|
|
|
3834
3964
|
// src/runtime/update_check.ts
|
|
3835
3965
|
var UPDATE_CACHE_PATH = path2.join(os2.homedir(), ".config", "echopai", "update_cache.json");
|
|
@@ -3864,7 +3994,7 @@ function isNewer(latest, current) {
|
|
|
3864
3994
|
}
|
|
3865
3995
|
function readCachedUpdate() {
|
|
3866
3996
|
try {
|
|
3867
|
-
const raw =
|
|
3997
|
+
const raw = readFileSync4(UPDATE_CACHE_PATH, "utf-8");
|
|
3868
3998
|
const obj = JSON.parse(raw);
|
|
3869
3999
|
if (typeof obj.checked_at === "string" && typeof obj.current === "string" && typeof obj.latest === "string") {
|
|
3870
4000
|
return obj;
|
|
@@ -4279,139 +4409,6 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
4279
4409
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4280
4410
|
import { Command as Command20, Option as Option18 } from "commander";
|
|
4281
4411
|
|
|
4282
|
-
// src/runtime/dist.ts
|
|
4283
|
-
import { spawnSync } from "node:child_process";
|
|
4284
|
-
import { createHash } from "node:crypto";
|
|
4285
|
-
import { existsSync as existsSync3, readFileSync as readFileSync4 } from "node:fs";
|
|
4286
|
-
import { fileURLToPath } from "node:url";
|
|
4287
|
-
var RELEASE_BASE = process.env.ECHOPAI_RELEASE_BASE?.replace(/\/+$/, "") || "https://downloads.echopai.com/echopai-cli-releases";
|
|
4288
|
-
var VERSION_RE = /^[0-9]+\.[0-9]+\.[0-9]+(-\S+)?$/;
|
|
4289
|
-
var SHA256_RE = /^[a-f0-9]{64}$/;
|
|
4290
|
-
var FETCH_TIMEOUT_MS = 8000;
|
|
4291
|
-
function isStandaloneBinary() {
|
|
4292
|
-
try {
|
|
4293
|
-
return !existsSync3(fileURLToPath(import.meta.url));
|
|
4294
|
-
} catch {
|
|
4295
|
-
return true;
|
|
4296
|
-
}
|
|
4297
|
-
}
|
|
4298
|
-
function computePlatformKey(i) {
|
|
4299
|
-
let arch = i.arch === "x64" || i.arch === "amd64" ? "x64" : i.arch === "arm64" ? "arm64" : null;
|
|
4300
|
-
if (!arch)
|
|
4301
|
-
return null;
|
|
4302
|
-
if (i.platform === "darwin") {
|
|
4303
|
-
if (arch === "x64" && i.isRosetta)
|
|
4304
|
-
arch = "arm64";
|
|
4305
|
-
return `darwin-${arch}`;
|
|
4306
|
-
}
|
|
4307
|
-
if (i.platform === "win32") {
|
|
4308
|
-
return arch === "x64" ? "windows-x64" : null;
|
|
4309
|
-
}
|
|
4310
|
-
if (i.platform === "linux") {
|
|
4311
|
-
if (arch === "x64") {
|
|
4312
|
-
if (i.isMusl)
|
|
4313
|
-
return "linux-x64-musl";
|
|
4314
|
-
return i.hasAvx2 ? "linux-x64" : "linux-x64-baseline";
|
|
4315
|
-
}
|
|
4316
|
-
return i.isMusl ? "linux-arm64-musl" : "linux-arm64";
|
|
4317
|
-
}
|
|
4318
|
-
return null;
|
|
4319
|
-
}
|
|
4320
|
-
function detectMusl() {
|
|
4321
|
-
return existsSync3("/lib/libc.musl-x86_64.so.1") || existsSync3("/lib/libc.musl-aarch64.so.1");
|
|
4322
|
-
}
|
|
4323
|
-
function detectAvx2() {
|
|
4324
|
-
try {
|
|
4325
|
-
return /\bavx2\b/.test(readFileSync4("/proc/cpuinfo", "utf8"));
|
|
4326
|
-
} catch {
|
|
4327
|
-
return false;
|
|
4328
|
-
}
|
|
4329
|
-
}
|
|
4330
|
-
function detectRosetta() {
|
|
4331
|
-
try {
|
|
4332
|
-
const r = spawnSync("sysctl", ["-n", "sysctl.proc_translated"], {
|
|
4333
|
-
encoding: "utf8",
|
|
4334
|
-
timeout: 1000
|
|
4335
|
-
});
|
|
4336
|
-
return r.stdout.trim() === "1";
|
|
4337
|
-
} catch {
|
|
4338
|
-
return false;
|
|
4339
|
-
}
|
|
4340
|
-
}
|
|
4341
|
-
function detectPlatformKey() {
|
|
4342
|
-
return computePlatformKey({
|
|
4343
|
-
platform: process.platform,
|
|
4344
|
-
arch: process.arch,
|
|
4345
|
-
isMusl: process.platform === "linux" ? detectMusl() : false,
|
|
4346
|
-
hasAvx2: process.platform === "linux" && process.arch === "x64" ? detectAvx2() : true,
|
|
4347
|
-
isRosetta: process.platform === "darwin" && process.arch === "x64" ? detectRosetta() : false
|
|
4348
|
-
});
|
|
4349
|
-
}
|
|
4350
|
-
function parseManifestChecksum(manifest, platform) {
|
|
4351
|
-
if (!manifest || typeof manifest !== "object")
|
|
4352
|
-
return null;
|
|
4353
|
-
const platforms = manifest.platforms;
|
|
4354
|
-
if (!platforms || typeof platforms !== "object")
|
|
4355
|
-
return null;
|
|
4356
|
-
const entry = platforms[platform];
|
|
4357
|
-
if (!entry || typeof entry !== "object")
|
|
4358
|
-
return null;
|
|
4359
|
-
const cs = entry.checksum;
|
|
4360
|
-
return typeof cs === "string" && SHA256_RE.test(cs) ? cs : null;
|
|
4361
|
-
}
|
|
4362
|
-
async function fetchText(url) {
|
|
4363
|
-
const ac = new AbortController;
|
|
4364
|
-
const timer = setTimeout(() => ac.abort(), FETCH_TIMEOUT_MS);
|
|
4365
|
-
try {
|
|
4366
|
-
const res = await fetch(url, { signal: ac.signal });
|
|
4367
|
-
if (!res.ok)
|
|
4368
|
-
return null;
|
|
4369
|
-
return await res.text();
|
|
4370
|
-
} catch {
|
|
4371
|
-
return null;
|
|
4372
|
-
} finally {
|
|
4373
|
-
clearTimeout(timer);
|
|
4374
|
-
}
|
|
4375
|
-
}
|
|
4376
|
-
async function resolveLatestFromCdn() {
|
|
4377
|
-
const txt = await fetchText(`${RELEASE_BASE}/latest`);
|
|
4378
|
-
if (txt == null)
|
|
4379
|
-
return null;
|
|
4380
|
-
const v = txt.trim();
|
|
4381
|
-
return VERSION_RE.test(v) ? v : null;
|
|
4382
|
-
}
|
|
4383
|
-
async function fetchManifest(version) {
|
|
4384
|
-
const txt = await fetchText(`${RELEASE_BASE}/${version}/manifest.json`);
|
|
4385
|
-
if (txt == null)
|
|
4386
|
-
return null;
|
|
4387
|
-
try {
|
|
4388
|
-
return JSON.parse(txt);
|
|
4389
|
-
} catch {
|
|
4390
|
-
return null;
|
|
4391
|
-
}
|
|
4392
|
-
}
|
|
4393
|
-
function binaryUrl(version, platform) {
|
|
4394
|
-
const name = platform.startsWith("windows-") ? "echopai.exe" : "echopai";
|
|
4395
|
-
return `${RELEASE_BASE}/${version}/${platform}/${name}`;
|
|
4396
|
-
}
|
|
4397
|
-
async function downloadAndVerify(url, expectedSha) {
|
|
4398
|
-
const ac = new AbortController;
|
|
4399
|
-
const timer = setTimeout(() => ac.abort(), FETCH_TIMEOUT_MS * 4);
|
|
4400
|
-
try {
|
|
4401
|
-
const res = await fetch(url, { signal: ac.signal });
|
|
4402
|
-
if (!res.ok)
|
|
4403
|
-
throw new Error(`下载失败 HTTP ${res.status}: ${url}`);
|
|
4404
|
-
const buf = Buffer.from(await res.arrayBuffer());
|
|
4405
|
-
const actual = createHash("sha256").update(buf).digest("hex");
|
|
4406
|
-
if (actual !== expectedSha) {
|
|
4407
|
-
throw new Error(`校验和不匹配(期望 ${expectedSha},实际 ${actual})`);
|
|
4408
|
-
}
|
|
4409
|
-
return buf;
|
|
4410
|
-
} finally {
|
|
4411
|
-
clearTimeout(timer);
|
|
4412
|
-
}
|
|
4413
|
-
}
|
|
4414
|
-
|
|
4415
4412
|
// src/runtime/whoami_cache.ts
|
|
4416
4413
|
var DEFAULT_TTL_MS = 5 * 60 * 1000;
|
|
4417
4414
|
var cache = null;
|
|
@@ -8395,15 +8392,14 @@ if (process.env._ECHOPAI_UPDATE_WORKER === "1") {
|
|
|
8395
8392
|
try {
|
|
8396
8393
|
const optedOut = process.env.CI || process.env.ECHOPAI_DISABLE_UPDATE_CHECK || !process.stderr.isTTY;
|
|
8397
8394
|
if (!optedOut && !process.env._ECHOPAI_UPDATE_WORKER) {
|
|
8398
|
-
let
|
|
8399
|
-
|
|
8400
|
-
|
|
8401
|
-
|
|
8402
|
-
|
|
8403
|
-
|
|
8404
|
-
|
|
8395
|
+
let reexecArgs = [];
|
|
8396
|
+
if (!isStandaloneBinary()) {
|
|
8397
|
+
try {
|
|
8398
|
+
reexecArgs = [fileURLToPath(import.meta.url)];
|
|
8399
|
+
} catch {
|
|
8400
|
+
reexecArgs = [];
|
|
8401
|
+
}
|
|
8405
8402
|
}
|
|
8406
|
-
const reexecArgs = scriptPath ? [scriptPath] : [];
|
|
8407
8403
|
const child = spawn(process.execPath, reexecArgs, {
|
|
8408
8404
|
detached: true,
|
|
8409
8405
|
stdio: "ignore",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "echopai",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.1",
|
|
4
4
|
"description": "Command-line interface for the EchoPai Open Platform: stock-market data, news, analyst views, sentiment, signals, backtests.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://echopai.com",
|