engine7 7.1.94 → 7.1.96
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/cli.mjs +93 -18
- package/dist/engine-startup.mjs +256 -33
- package/dist/main.mjs +261 -38
- package/package.json +85 -85
package/dist/cli.mjs
CHANGED
|
@@ -18320,7 +18320,8 @@ function buildLightHistory(history, opts) {
|
|
|
18320
18320
|
function buildLightStablePrompt(workspace, mode, opts) {
|
|
18321
18321
|
const lp = liveConfig.get(`channels.${mode}.liveSystemPrompt`);
|
|
18322
18322
|
const parts = [];
|
|
18323
|
-
|
|
18323
|
+
const files = lp?.files ?? (mode === "emotion" ? ["SOUL.md", "EMOTION.md"] : ["SOUL.md"]);
|
|
18324
|
+
for (const f of files) {
|
|
18324
18325
|
try {
|
|
18325
18326
|
parts.push(readFileSync22(join29(workspace, f), "utf-8").trim());
|
|
18326
18327
|
} catch {
|
|
@@ -18343,7 +18344,7 @@ function buildLightStablePrompt(workspace, mode, opts) {
|
|
|
18343
18344
|
].join("\n"));
|
|
18344
18345
|
}
|
|
18345
18346
|
const built = parts.join("\n\n");
|
|
18346
|
-
console.log(`[light-stable] mode=${mode} files=[${
|
|
18347
|
+
console.log(`[light-stable] mode=${mode} files=[${files.join(",")}] ~${Math.round(built.length / 3)} tokens`);
|
|
18347
18348
|
return built;
|
|
18348
18349
|
}
|
|
18349
18350
|
var init_light_mode = __esm({
|
|
@@ -27228,12 +27229,17 @@ var init_cli_doctor = __esm({
|
|
|
27228
27229
|
var provision_free_exports = {};
|
|
27229
27230
|
__export(provision_free_exports, {
|
|
27230
27231
|
loadOrCreateInstallIdentity: () => loadOrCreateInstallIdentity,
|
|
27231
|
-
provisionFreeToken: () => provisionFreeToken
|
|
27232
|
+
provisionFreeToken: () => provisionFreeToken,
|
|
27233
|
+
readInstallIdentity: () => readInstallIdentity,
|
|
27234
|
+
writeIdentityContactEmail: () => writeIdentityContactEmail
|
|
27232
27235
|
});
|
|
27233
27236
|
import { randomBytes as randomBytes6, randomUUID as randomUUID9 } from "node:crypto";
|
|
27234
27237
|
import { chmodSync as chmodSync2, existsSync as existsSync31, mkdirSync as mkdirSync19, readFileSync as readFileSync39, writeFileSync as writeFileSync20 } from "node:fs";
|
|
27235
27238
|
import { dirname as dirname12, join as join49 } from "node:path";
|
|
27236
27239
|
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
27240
|
+
function readContactEmailOf(parsed) {
|
|
27241
|
+
return typeof parsed?.contactEmail === "string" ? parsed.contactEmail.trim() : "";
|
|
27242
|
+
}
|
|
27237
27243
|
function loadOrCreateInstallIdentity(stateDir) {
|
|
27238
27244
|
const file2 = join49(stateDir, IDENTITY_FILE);
|
|
27239
27245
|
if (existsSync31(file2)) {
|
|
@@ -27248,7 +27254,12 @@ function loadOrCreateInstallIdentity(stateDir) {
|
|
|
27248
27254
|
if (typeof parsed?.installId !== "string" || typeof parsed?.installSecret !== "string") {
|
|
27249
27255
|
throw new Error(`${IDENTITY_FILE} \u7F3A installId / installSecret \u5B57\u6BB5`);
|
|
27250
27256
|
}
|
|
27251
|
-
|
|
27257
|
+
const email = readContactEmailOf(parsed);
|
|
27258
|
+
return {
|
|
27259
|
+
installId: parsed.installId,
|
|
27260
|
+
installSecret: parsed.installSecret,
|
|
27261
|
+
...email ? { contactEmail: email } : {}
|
|
27262
|
+
};
|
|
27252
27263
|
}
|
|
27253
27264
|
const identity = {
|
|
27254
27265
|
// 服务端校验 installId 长度为 8..36、只允许字母数字和连字符;uuid 正好符合
|
|
@@ -27264,6 +27275,32 @@ function loadOrCreateInstallIdentity(stateDir) {
|
|
|
27264
27275
|
}
|
|
27265
27276
|
return identity;
|
|
27266
27277
|
}
|
|
27278
|
+
function readInstallIdentity(stateDir) {
|
|
27279
|
+
try {
|
|
27280
|
+
const parsed = JSON.parse(readFileSync39(join49(stateDir, IDENTITY_FILE), "utf8"));
|
|
27281
|
+
if (typeof parsed?.installId !== "string" || typeof parsed?.installSecret !== "string") return null;
|
|
27282
|
+
const email = readContactEmailOf(parsed);
|
|
27283
|
+
return {
|
|
27284
|
+
installId: parsed.installId,
|
|
27285
|
+
installSecret: parsed.installSecret,
|
|
27286
|
+
...email ? { contactEmail: email } : {}
|
|
27287
|
+
};
|
|
27288
|
+
} catch {
|
|
27289
|
+
return null;
|
|
27290
|
+
}
|
|
27291
|
+
}
|
|
27292
|
+
function writeIdentityContactEmail(stateDir, email) {
|
|
27293
|
+
const identity = loadOrCreateInstallIdentity(stateDir);
|
|
27294
|
+
const trimmed = email.trim();
|
|
27295
|
+
const next = { ...identity, contactEmail: trimmed };
|
|
27296
|
+
const file2 = join49(stateDir, IDENTITY_FILE);
|
|
27297
|
+
mkdirSync19(stateDir, { recursive: true });
|
|
27298
|
+
writeFileSync20(file2, JSON.stringify(next, null, 2) + "\n", { mode: 384 });
|
|
27299
|
+
try {
|
|
27300
|
+
chmodSync2(file2, 384);
|
|
27301
|
+
} catch {
|
|
27302
|
+
}
|
|
27303
|
+
}
|
|
27267
27304
|
function readEngineVersion() {
|
|
27268
27305
|
try {
|
|
27269
27306
|
return JSON.parse(readFileSync39(join49(dirname12(__filename), "..", "package.json"), "utf8")).version || "unknown";
|
|
@@ -27278,7 +27315,14 @@ async function provisionFreeToken(opts) {
|
|
|
27278
27315
|
const res = await doFetch(url, {
|
|
27279
27316
|
method: "POST",
|
|
27280
27317
|
headers: { "Content-Type": "application/json" },
|
|
27281
|
-
|
|
27318
|
+
// 显式列字段,**不要用 `...identity` 展开**:InstallIdentity 加了 contactEmail
|
|
27319
|
+
// 之后,展开会把邮箱也发到发号端点——协议悄悄变了,而服务端只认这三个字段。
|
|
27320
|
+
// (provision-free.test.ts 里有一条断言守这个。)
|
|
27321
|
+
body: JSON.stringify({
|
|
27322
|
+
installId: identity.installId,
|
|
27323
|
+
installSecret: identity.installSecret,
|
|
27324
|
+
engineVersion: readEngineVersion()
|
|
27325
|
+
})
|
|
27282
27326
|
});
|
|
27283
27327
|
const text = await res.text();
|
|
27284
27328
|
let body;
|
|
@@ -28165,6 +28209,13 @@ import * as fs2 from "node:fs";
|
|
|
28165
28209
|
// src/cli-init-config.ts
|
|
28166
28210
|
import * as path2 from "node:path";
|
|
28167
28211
|
var SCHEMA_VERSION = 1;
|
|
28212
|
+
var FREE_TIER_RELAY_URL = "https://www.twinsun.top:8866";
|
|
28213
|
+
function isFreeTier(v) {
|
|
28214
|
+
return v.freeTier === true || v.primaryProvider === "7yi";
|
|
28215
|
+
}
|
|
28216
|
+
function resolveRelayUrl(relayArg, env = process.env) {
|
|
28217
|
+
return (relayArg || "").trim() || (env.E7_RELAY_URL || "").trim() || FREE_TIER_RELAY_URL;
|
|
28218
|
+
}
|
|
28168
28219
|
var DEFAULT_PRIMARY_MODEL = {
|
|
28169
28220
|
dashscope: "dashscope/qwen3.8-max",
|
|
28170
28221
|
minimax: "minimax/MiniMax-M3",
|
|
@@ -28245,7 +28296,13 @@ var PROVIDER_DEFS = {
|
|
|
28245
28296
|
// 引擎免费档的中转站。baseUrl 是兜底值——真正的权威值来自领号响应
|
|
28246
28297
|
// (服务端按请求 Host 自报地址),由安装器作为 customBaseUrl 下发。
|
|
28247
28298
|
// 这样挪机器、换域名只改服务端,不用重发安装包。
|
|
28248
|
-
|
|
28299
|
+
//
|
|
28300
|
+
// ⚠️ 0921 修:这里原本写的是 `https://www.twinsun.top/v1`(443),而 **443 上不是
|
|
28301
|
+
// 中转站**(实测回的是另一个服务的 FastAPI 404)。安装器那条路每次都会下发
|
|
28302
|
+
// customBaseUrl 把它盖掉,所以正式装机撞不到;但**终端向导选 7yi 时不问 baseUrl**,
|
|
28303
|
+
// 直接落到这个兜底值——于是命令行用户拿到的是「号领到了、引擎起来了、一发消息就废」。
|
|
28304
|
+
// 用常量拼,别再手写一遍(漏端口就是这个坑)。
|
|
28305
|
+
baseUrl: `${FREE_TIER_RELAY_URL}/v1`,
|
|
28249
28306
|
api: "anthropic",
|
|
28250
28307
|
models: [
|
|
28251
28308
|
// ⚠️ contextWindow **不能照抄 1000000**。
|
|
@@ -28365,9 +28422,9 @@ function generateConfig(v) {
|
|
|
28365
28422
|
// 自拍(§4.3):免费档必须显式写 provider:'relay'。不写的话 getProvider()
|
|
28366
28423
|
// 会落回默认值 'fal',而免费装机没有 fal key——第一次自拍就失败。
|
|
28367
28424
|
// 非免费档只在用户真给了形象时才写这个块,且不替他决定 provider。
|
|
28368
|
-
...v
|
|
28425
|
+
...isFreeTier(v) || v.selfiePhotoRelPath || v.selfiePortraitDesc ? {
|
|
28369
28426
|
my_selfie: {
|
|
28370
|
-
...v
|
|
28427
|
+
...isFreeTier(v) ? { provider: "relay" } : {},
|
|
28371
28428
|
...v.selfiePhotoRelPath ? { references: [{ name: "portrait", path: v.selfiePhotoRelPath }] } : {},
|
|
28372
28429
|
// 只在没有照片时才写描述——两个都给的话以照片为准,写进去会让人以为
|
|
28373
28430
|
// 描述也生效了(冷启读的就是这个键)
|
|
@@ -28415,7 +28472,7 @@ function generateConfig(v) {
|
|
|
28415
28472
|
debounceMs: 5e3,
|
|
28416
28473
|
// 免费档的装机目标是「能对话、能看图、能自拍」,这两个 flag 默认 false
|
|
28417
28474
|
// (src/config/features.ts)。显式打开,它们是声明这两件事的地方。
|
|
28418
|
-
...v
|
|
28475
|
+
...isFreeTier(v) ? { selfie: true, eyes: true } : {}
|
|
28419
28476
|
}
|
|
28420
28477
|
}
|
|
28421
28478
|
},
|
|
@@ -28581,6 +28638,13 @@ function validate(a) {
|
|
|
28581
28638
|
if (a.timezone !== void 0 && !isValidTimezone(a.timezone)) {
|
|
28582
28639
|
throw new Error(`timezone \u975E\u6CD5: ${a.timezone}\uFF08\u8981 IANA \u540D\uFF0C\u5982 Asia/Shanghai\u3001Europe/Malta\uFF09`);
|
|
28583
28640
|
}
|
|
28641
|
+
if (a.contactEmail !== void 0 && a.contactEmail !== null && a.contactEmail !== "") {
|
|
28642
|
+
if (typeof a.contactEmail !== "string") throw new Error("contactEmail \u5FC5\u987B\u662F\u5B57\u7B26\u4E32");
|
|
28643
|
+
const t = a.contactEmail.trim();
|
|
28644
|
+
if (t && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t)) {
|
|
28645
|
+
throw new Error(`contactEmail \u4E0D\u662F\u5408\u6CD5\u90AE\u7BB1: ${t}`);
|
|
28646
|
+
}
|
|
28647
|
+
}
|
|
28584
28648
|
if (a.feishu?.mode !== void 0 && !VALID_CHANNEL_MODES.includes(a.feishu.mode)) {
|
|
28585
28649
|
throw new Error(`feishu.mode \u975E\u6CD5: ${a.feishu.mode}\uFF08\u53EF\u9009: ${VALID_CHANNEL_MODES.join(" / ")}\uFF09`);
|
|
28586
28650
|
}
|
|
@@ -28609,6 +28673,11 @@ function loadInitAnswers(filePath) {
|
|
|
28609
28673
|
throw new Error(`answers \u6587\u4EF6\u4E0D\u662F\u5408\u6CD5 JSON: ${e.message}`);
|
|
28610
28674
|
}
|
|
28611
28675
|
validate(parsed);
|
|
28676
|
+
if (typeof parsed.contactEmail === "string") {
|
|
28677
|
+
const t = parsed.contactEmail.trim();
|
|
28678
|
+
if (t) parsed.contactEmail = t;
|
|
28679
|
+
else delete parsed.contactEmail;
|
|
28680
|
+
}
|
|
28612
28681
|
return parsed;
|
|
28613
28682
|
}
|
|
28614
28683
|
function buildConfigValuesFromAnswers(stateDir, a, existing = {}) {
|
|
@@ -29399,16 +29468,16 @@ async function main() {
|
|
|
29399
29468
|
}
|
|
29400
29469
|
if (subcommand === "provision-free") {
|
|
29401
29470
|
let relay = "";
|
|
29471
|
+
let relayFromArg = false;
|
|
29402
29472
|
let stateDir = "";
|
|
29403
29473
|
for (let i = 1; i < args.length; i++) {
|
|
29404
|
-
if (args[i] === "--relay" && args[i + 1])
|
|
29405
|
-
|
|
29406
|
-
|
|
29407
|
-
|
|
29408
|
-
console.error("\u7528\u6CD5\uFF1Aengine7 provision-free --relay <\u4E2D\u8F6C\u7AD9\u5730\u5740> --state-dir <\u76EE\u5F55>");
|
|
29409
|
-
console.error(" --relay \u662F\u5B89\u88C5\u5668\u4E0B\u53D1\u7684\u9886\u53F7\u5730\u5740\uFF0C\u4E0D\u662F\u6A21\u578B baseUrl\uFF08\u540E\u8005\u4EE5\u9886\u53F7\u54CD\u5E94\u4E3A\u51C6\uFF09");
|
|
29410
|
-
process.exit(1);
|
|
29474
|
+
if (args[i] === "--relay" && args[i + 1]) {
|
|
29475
|
+
relay = args[++i].trim();
|
|
29476
|
+
relayFromArg = true;
|
|
29477
|
+
} else if (args[i] === "--state-dir" && args[i + 1]) stateDir = args[++i].trim();
|
|
29411
29478
|
}
|
|
29479
|
+
relay = resolveRelayUrl(relay, process.env);
|
|
29480
|
+
if (!relayFromArg) console.error(` \u4E2D\u8F6C\u7AD9: ${relay}\uFF08\u8981\u6362\u5730\u5740\u7528 --relay <\u5730\u5740>\uFF09`);
|
|
29412
29481
|
const { resolveStateDirFromArgs: resolveStateDirFromArgs2 } = await Promise.resolve().then(() => (init_cli_doctor(), cli_doctor_exports));
|
|
29413
29482
|
stateDir = stateDir ? path33.resolve(stateDir) : resolveStateDirFromArgs2(args.slice(1));
|
|
29414
29483
|
try {
|
|
@@ -30225,11 +30294,17 @@ WantedBy=default.target`;
|
|
|
30225
30294
|
values = await interactiveConfig(rl, getDefaultValues(opts.stateDir));
|
|
30226
30295
|
rl.close();
|
|
30227
30296
|
}
|
|
30228
|
-
|
|
30297
|
+
{
|
|
30298
|
+
const { loadOrCreateInstallIdentity: loadOrCreateInstallIdentity2, writeIdentityContactEmail: writeIdentityContactEmail2 } = await Promise.resolve().then(() => (init_provision_free(), provision_free_exports));
|
|
30299
|
+
loadOrCreateInstallIdentity2(opts.stateDir);
|
|
30300
|
+
const contactEmail = (answers?.contactEmail || "").trim();
|
|
30301
|
+
if (contactEmail) writeIdentityContactEmail2(opts.stateDir, contactEmail);
|
|
30302
|
+
}
|
|
30303
|
+
if (isFreeTier(values)) {
|
|
30229
30304
|
const envName = values.primaryProvider.toUpperCase().replace(/[^A-Z0-9_]/g, "_") + "_API_KEY";
|
|
30230
30305
|
if (!readSecretsValue(opts.stateDir, envName)) {
|
|
30231
30306
|
throw new Error(
|
|
30232
|
-
`\u514D\u8D39\u6863\u7F3A\u5C11\u4EE4\u724C\uFF1Asecrets \u91CC\u6CA1\u6709 ${envName}\u3002\u8BF7\u5148\u6267\u884C engine7 provision-free --
|
|
30307
|
+
`\u514D\u8D39\u6863\u7F3A\u5C11\u4EE4\u724C\uFF1Asecrets \u91CC\u6CA1\u6709 ${envName}\u3002\u8BF7\u5148\u6267\u884C engine7 provision-free --state-dir ${opts.stateDir} \u9886\u53F7\uFF0C\u518D\u8DD1 init\u3002`
|
|
30233
30308
|
);
|
|
30234
30309
|
}
|
|
30235
30310
|
}
|