@yoooclaw/phone-notifications 1.12.1 → 1.12.2
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/ntf.cjs +2 -2
- package/dist/bin/ntf.cjs.map +1 -1
- package/dist/index.cjs +188 -162
- package/dist/index.cjs.map +4 -4
- package/dist/update/checker.d.ts +2 -1
- package/dist/update/checker.d.ts.map +1 -1
- package/dist/update/index.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2959,7 +2959,7 @@ var import_node_path = require("node:path");
|
|
|
2959
2959
|
var import_node_fs = require("node:fs");
|
|
2960
2960
|
function readBuildInjectedVersion() {
|
|
2961
2961
|
if (false) {}
|
|
2962
|
-
const version = "1.12.
|
|
2962
|
+
const version = "1.12.2".trim();
|
|
2963
2963
|
return version || undefined;
|
|
2964
2964
|
}
|
|
2965
2965
|
function readPluginVersionFromPackageJson() {
|
|
@@ -6588,6 +6588,7 @@ function resolveUpdateBaseUrl(params) {
|
|
|
6588
6588
|
}
|
|
6589
6589
|
|
|
6590
6590
|
// src/update/index.ts
|
|
6591
|
+
var import_node_fs11 = require("node:fs");
|
|
6591
6592
|
var import_node_path11 = require("node:path");
|
|
6592
6593
|
|
|
6593
6594
|
// src/plugin/shared.ts
|
|
@@ -6693,15 +6694,17 @@ class UpdateChecker {
|
|
|
6693
6694
|
intervalMs;
|
|
6694
6695
|
channel;
|
|
6695
6696
|
baseUrl;
|
|
6697
|
+
getCurrentVersion;
|
|
6696
6698
|
timer = null;
|
|
6697
6699
|
notifiedVersion = null;
|
|
6698
6700
|
inflightCheck = null;
|
|
6699
|
-
constructor(logger, onUpdateFound, intervalMs, channel, baseUrl = PRODUCTION_UPDATE_BASE_URL) {
|
|
6701
|
+
constructor(logger, onUpdateFound, intervalMs, channel, baseUrl = PRODUCTION_UPDATE_BASE_URL, getCurrentVersion = () => PLUGIN_VERSION) {
|
|
6700
6702
|
this.logger = logger;
|
|
6701
6703
|
this.onUpdateFound = onUpdateFound;
|
|
6702
6704
|
this.intervalMs = intervalMs;
|
|
6703
6705
|
this.channel = channel;
|
|
6704
6706
|
this.baseUrl = baseUrl;
|
|
6707
|
+
this.getCurrentVersion = getCurrentVersion;
|
|
6705
6708
|
}
|
|
6706
6709
|
start() {
|
|
6707
6710
|
this.timer = setTimeout(() => {
|
|
@@ -6724,17 +6727,18 @@ class UpdateChecker {
|
|
|
6724
6727
|
return this.inflightCheck;
|
|
6725
6728
|
}
|
|
6726
6729
|
async runCheck() {
|
|
6730
|
+
const current = this.getCurrentVersion();
|
|
6727
6731
|
const latest = await this.fetchLatestVersion();
|
|
6728
|
-
if (!latest || latest ===
|
|
6732
|
+
if (!latest || latest === current)
|
|
6729
6733
|
return null;
|
|
6730
6734
|
if (this.channel !== "beta" && latest.includes("-"))
|
|
6731
6735
|
return null;
|
|
6732
|
-
if (!isNewerVersion(latest,
|
|
6736
|
+
if (!isNewerVersion(latest, current))
|
|
6733
6737
|
return null;
|
|
6734
|
-
const info = { current
|
|
6738
|
+
const info = { current, latest };
|
|
6735
6739
|
if (latest !== this.notifiedVersion) {
|
|
6736
6740
|
this.notifiedVersion = latest;
|
|
6737
|
-
this.logger.info(`发现新版本: ${
|
|
6741
|
+
this.logger.info(`发现新版本: ${current} → ${latest}`);
|
|
6738
6742
|
this.onUpdateFound(info);
|
|
6739
6743
|
}
|
|
6740
6744
|
return info;
|
|
@@ -7398,6 +7402,7 @@ function scheduleGatewayRestart(logger, deps = {}) {
|
|
|
7398
7402
|
|
|
7399
7403
|
// src/update/index.ts
|
|
7400
7404
|
var PLUGIN_ID2 = "phone-notifications";
|
|
7405
|
+
var VERSION_PATTERN2 = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
|
|
7401
7406
|
function shouldSkipAutoRestart() {
|
|
7402
7407
|
return process.platform === "win32";
|
|
7403
7408
|
}
|
|
@@ -7538,6 +7543,26 @@ async function reconcileSucceededUpdateRecord(api, logger, targetDir) {
|
|
|
7538
7543
|
logger.warn(`更新已应用,但配置记录补写失败: ${String(err2)}`);
|
|
7539
7544
|
}
|
|
7540
7545
|
}
|
|
7546
|
+
function resolveEffectiveCurrentVersion(targetDir) {
|
|
7547
|
+
const installedVersion = readInstalledPackageVersion(targetDir);
|
|
7548
|
+
if (installedVersion && isNewerVersion(installedVersion, PLUGIN_VERSION)) {
|
|
7549
|
+
return installedVersion;
|
|
7550
|
+
}
|
|
7551
|
+
const status = readLastUpdateStatus(targetDir);
|
|
7552
|
+
if (status?.status === "succeeded" && status.version && isNewerVersion(status.version, PLUGIN_VERSION)) {
|
|
7553
|
+
return status.version;
|
|
7554
|
+
}
|
|
7555
|
+
return PLUGIN_VERSION;
|
|
7556
|
+
}
|
|
7557
|
+
function readInstalledPackageVersion(targetDir) {
|
|
7558
|
+
try {
|
|
7559
|
+
const parsed = JSON.parse(import_node_fs11.readFileSync(import_node_path11.join(targetDir, "package.json"), "utf-8"));
|
|
7560
|
+
const version = typeof parsed.version === "string" ? parsed.version.trim() : "";
|
|
7561
|
+
return VERSION_PATTERN2.test(version) ? version : undefined;
|
|
7562
|
+
} catch {
|
|
7563
|
+
return;
|
|
7564
|
+
}
|
|
7565
|
+
}
|
|
7541
7566
|
function registerAutoUpdate(api, logger, config, getBroadcast, rememberBroadcast, externalUpdateNotifier) {
|
|
7542
7567
|
if (config.enabled === false) {
|
|
7543
7568
|
logger.info("自动更新已禁用 (autoUpdate.enabled = false)");
|
|
@@ -7631,7 +7656,7 @@ function registerAutoUpdate(api, logger, config, getBroadcast, rememberBroadcast
|
|
|
7631
7656
|
externalUpdateNotifier?.notifyUpdateAvailable(update);
|
|
7632
7657
|
}
|
|
7633
7658
|
logger.info(`已通知更新 ${update.current} → ${update.latest}` + (broadcasted ? "(对话 + 网关)" : "(对话通道已生效,等待下次 gateway 请求时补发客户端事件)"));
|
|
7634
|
-
}, intervalMs, channel, baseUrl);
|
|
7659
|
+
}, intervalMs, channel, baseUrl, () => resolveEffectiveCurrentVersion(resolveTargetDir(api)));
|
|
7635
7660
|
api.registerGatewayMethod("plugin.update", async ({ params, respond, context }) => {
|
|
7636
7661
|
const version = params.version;
|
|
7637
7662
|
if (!version) {
|
|
@@ -7754,6 +7779,7 @@ function registerAutoUpdate(api, logger, config, getBroadcast, rememberBroadcast
|
|
|
7754
7779
|
try {
|
|
7755
7780
|
const targetDir = resolveTargetDir(api);
|
|
7756
7781
|
const info = await checker.check();
|
|
7782
|
+
const current = resolveEffectiveCurrentVersion(targetDir);
|
|
7757
7783
|
const lastUpdateStatus = readLastUpdateStatus(targetDir);
|
|
7758
7784
|
const lastUpdateNotice = lastUpdateStatus ? buildLastUpdateNotice(lastUpdateStatus) : undefined;
|
|
7759
7785
|
if (!info) {
|
|
@@ -7762,7 +7788,7 @@ function registerAutoUpdate(api, logger, config, getBroadcast, rememberBroadcast
|
|
|
7762
7788
|
respond(true, {
|
|
7763
7789
|
pluginId: PLUGIN_ID2,
|
|
7764
7790
|
pluginName: "消息通知",
|
|
7765
|
-
current
|
|
7791
|
+
current,
|
|
7766
7792
|
latest: info?.latest ?? null,
|
|
7767
7793
|
hasUpdate: !!info,
|
|
7768
7794
|
...lastUpdateNotice ? { lastUpdateNotice } : {}
|
|
@@ -7837,7 +7863,7 @@ function registerAutoUpdateLifecycle(deps) {
|
|
|
7837
7863
|
var import_node_path19 = require("node:path");
|
|
7838
7864
|
|
|
7839
7865
|
// src/cli/auth.ts
|
|
7840
|
-
var
|
|
7866
|
+
var import_node_fs12 = require("node:fs");
|
|
7841
7867
|
function registerAuthCli(program) {
|
|
7842
7868
|
const auth = program.command("auth").description("用户认证管理");
|
|
7843
7869
|
auth.command("set-api-key <apiKey>").description("设置用户 API Key(持久化到本地配置)").action((apiKey) => {
|
|
@@ -7871,13 +7897,13 @@ function registerAuthCli(program) {
|
|
|
7871
7897
|
});
|
|
7872
7898
|
auth.command("clear").description("清除已保存的认证信息").action(() => {
|
|
7873
7899
|
const path = credentialsPath();
|
|
7874
|
-
if (
|
|
7900
|
+
if (import_node_fs12.existsSync(path)) {
|
|
7875
7901
|
const creds = readCredentials();
|
|
7876
7902
|
delete creds.apiKey;
|
|
7877
7903
|
delete creds.apiKeys;
|
|
7878
7904
|
delete creds.token;
|
|
7879
7905
|
if (Object.keys(creds).length === 0) {
|
|
7880
|
-
|
|
7906
|
+
import_node_fs12.rmSync(path, { force: true });
|
|
7881
7907
|
} else {
|
|
7882
7908
|
writeCredentials(creds);
|
|
7883
7909
|
}
|
|
@@ -8023,7 +8049,7 @@ function registerNtfSummary(ntf, ctx) {
|
|
|
8023
8049
|
|
|
8024
8050
|
// src/cli/ntf-summary-job.ts
|
|
8025
8051
|
var import_node_crypto3 = require("node:crypto");
|
|
8026
|
-
var
|
|
8052
|
+
var import_node_fs13 = require("node:fs");
|
|
8027
8053
|
var import_node_path12 = require("node:path");
|
|
8028
8054
|
var SUMMARY_ROOT = ".summaries";
|
|
8029
8055
|
var JOBS_DIR = "jobs";
|
|
@@ -8165,11 +8191,11 @@ function chunkPath(jobDir, chunkId) {
|
|
|
8165
8191
|
return import_node_path12.join(jobDir, CHUNKS_DIR, `${chunkId}.json`);
|
|
8166
8192
|
}
|
|
8167
8193
|
function writeJson(path, value) {
|
|
8168
|
-
|
|
8194
|
+
import_node_fs13.writeFileSync(path, JSON.stringify(value, null, 2), "utf-8");
|
|
8169
8195
|
}
|
|
8170
8196
|
function readJson(path) {
|
|
8171
8197
|
try {
|
|
8172
|
-
return JSON.parse(
|
|
8198
|
+
return JSON.parse(import_node_fs13.readFileSync(path, "utf-8"));
|
|
8173
8199
|
} catch {
|
|
8174
8200
|
exitError("READ_FAILED", `无法读取 JSON: ${path}`);
|
|
8175
8201
|
}
|
|
@@ -8177,7 +8203,7 @@ function readJson(path) {
|
|
|
8177
8203
|
function readMeta2(notificationsDir, id) {
|
|
8178
8204
|
const dir = summaryJobDir(notificationsDir, id);
|
|
8179
8205
|
const path = metaPath(dir);
|
|
8180
|
-
if (!
|
|
8206
|
+
if (!import_node_fs13.existsSync(path)) {
|
|
8181
8207
|
exitError("JOB_NOT_FOUND", `summary job 不存在: ${id}`);
|
|
8182
8208
|
}
|
|
8183
8209
|
const meta = readJson(path);
|
|
@@ -8265,7 +8291,7 @@ function resolveSummaryText(opts) {
|
|
|
8265
8291
|
if (!hasSummary && !hasSummaryFile) {
|
|
8266
8292
|
exitError("INVALID_COMMIT", "必须提供 --summary 或 --summary-file");
|
|
8267
8293
|
}
|
|
8268
|
-
const text = hasSummary ? opts.summary :
|
|
8294
|
+
const text = hasSummary ? opts.summary : import_node_fs13.readFileSync(import_node_path12.resolve(opts.summaryFile), "utf-8");
|
|
8269
8295
|
if (!text.trim()) {
|
|
8270
8296
|
exitError("INVALID_COMMIT", "分片摘要不能为空");
|
|
8271
8297
|
}
|
|
@@ -8289,7 +8315,7 @@ function buildResultMarkdown(meta, jobDir) {
|
|
|
8289
8315
|
lines.push("(未提交摘要)", "");
|
|
8290
8316
|
continue;
|
|
8291
8317
|
}
|
|
8292
|
-
lines.push(
|
|
8318
|
+
lines.push(import_node_fs13.readFileSync(import_node_path12.join(jobDir, chunk.summaryFile), "utf-8").trim(), "");
|
|
8293
8319
|
}
|
|
8294
8320
|
return lines.join(`
|
|
8295
8321
|
`).trimEnd() + `
|
|
@@ -8298,7 +8324,7 @@ function buildResultMarkdown(meta, jobDir) {
|
|
|
8298
8324
|
function writeChunkSummary(notificationsDir, meta, chunk, text) {
|
|
8299
8325
|
const jobDir = summaryJobDir(notificationsDir, meta.id);
|
|
8300
8326
|
const relativeSummaryFile = import_node_path12.join(SUMMARIES_DIR, `${chunk.id}.md`);
|
|
8301
|
-
|
|
8327
|
+
import_node_fs13.writeFileSync(import_node_path12.join(jobDir, relativeSummaryFile), text, "utf-8");
|
|
8302
8328
|
chunk.status = "done";
|
|
8303
8329
|
chunk.completedAt = nowIso2();
|
|
8304
8330
|
chunk.summaryFile = relativeSummaryFile;
|
|
@@ -8310,7 +8336,7 @@ function finalizeResultIfReady(notificationsDir, meta) {
|
|
|
8310
8336
|
}
|
|
8311
8337
|
const jobDir = summaryJobDir(notificationsDir, meta.id);
|
|
8312
8338
|
const markdown = buildResultMarkdown(meta, jobDir);
|
|
8313
|
-
|
|
8339
|
+
import_node_fs13.writeFileSync(import_node_path12.join(jobDir, RESULT_FILE), markdown, "utf-8");
|
|
8314
8340
|
meta.status = "complete";
|
|
8315
8341
|
meta.resultFile = RESULT_FILE;
|
|
8316
8342
|
return markdown;
|
|
@@ -8332,8 +8358,8 @@ function registerNtfSummaryJob(ntf, ctx) {
|
|
|
8332
8358
|
const id = createJobId();
|
|
8333
8359
|
const createdAt = nowIso2();
|
|
8334
8360
|
const jobDir = summaryJobDir(dir, id);
|
|
8335
|
-
|
|
8336
|
-
|
|
8361
|
+
import_node_fs13.mkdirSync(import_node_path12.join(jobDir, CHUNKS_DIR), { recursive: true });
|
|
8362
|
+
import_node_fs13.mkdirSync(import_node_path12.join(jobDir, SUMMARIES_DIR), { recursive: true });
|
|
8337
8363
|
const chunks = [];
|
|
8338
8364
|
for (let start = 0;start < notifications.length; start += chunkSize) {
|
|
8339
8365
|
const rawChunk = notifications.slice(start, start + chunkSize);
|
|
@@ -8628,7 +8654,7 @@ function registerNtfStats(ntf, ctx) {
|
|
|
8628
8654
|
|
|
8629
8655
|
// src/cli/ntf-sync.ts
|
|
8630
8656
|
var import_node_child_process2 = require("node:child_process");
|
|
8631
|
-
var
|
|
8657
|
+
var import_node_fs14 = require("node:fs");
|
|
8632
8658
|
var import_node_path13 = require("node:path");
|
|
8633
8659
|
var SYNC_FETCH_LIMIT = 100;
|
|
8634
8660
|
function checkpointPath(dir) {
|
|
@@ -8636,16 +8662,16 @@ function checkpointPath(dir) {
|
|
|
8636
8662
|
}
|
|
8637
8663
|
function readCheckpoint(dir) {
|
|
8638
8664
|
const p = checkpointPath(dir);
|
|
8639
|
-
if (!
|
|
8665
|
+
if (!import_node_fs14.existsSync(p))
|
|
8640
8666
|
return {};
|
|
8641
8667
|
try {
|
|
8642
|
-
return JSON.parse(
|
|
8668
|
+
return JSON.parse(import_node_fs14.readFileSync(p, "utf-8"));
|
|
8643
8669
|
} catch {
|
|
8644
8670
|
return {};
|
|
8645
8671
|
}
|
|
8646
8672
|
}
|
|
8647
8673
|
function writeCheckpoint(dir, data) {
|
|
8648
|
-
|
|
8674
|
+
import_node_fs14.writeFileSync(checkpointPath(dir), JSON.stringify(data, null, 2), "utf-8");
|
|
8649
8675
|
}
|
|
8650
8676
|
function validateDateKey(value, optionName) {
|
|
8651
8677
|
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);
|
|
@@ -8916,7 +8942,7 @@ function registerNtfSync(ntf, ctx) {
|
|
|
8916
8942
|
}
|
|
8917
8943
|
|
|
8918
8944
|
// src/cli/ntf-monitor.ts
|
|
8919
|
-
var
|
|
8945
|
+
var import_node_fs15 = require("node:fs");
|
|
8920
8946
|
var import_node_path14 = require("node:path");
|
|
8921
8947
|
|
|
8922
8948
|
// src/monitor/fetch-gen.ts
|
|
@@ -9008,16 +9034,16 @@ function tasksDir(ctx) {
|
|
|
9008
9034
|
}
|
|
9009
9035
|
function readMeta3(taskDir) {
|
|
9010
9036
|
const metaPath2 = import_node_path14.join(taskDir, "meta.json");
|
|
9011
|
-
if (!
|
|
9037
|
+
if (!import_node_fs15.existsSync(metaPath2))
|
|
9012
9038
|
return null;
|
|
9013
9039
|
try {
|
|
9014
|
-
return JSON.parse(
|
|
9040
|
+
return JSON.parse(import_node_fs15.readFileSync(metaPath2, "utf-8"));
|
|
9015
9041
|
} catch {
|
|
9016
9042
|
return null;
|
|
9017
9043
|
}
|
|
9018
9044
|
}
|
|
9019
9045
|
function writeMeta2(taskDir, meta) {
|
|
9020
|
-
|
|
9046
|
+
import_node_fs15.writeFileSync(import_node_path14.join(taskDir, "meta.json"), JSON.stringify(meta, null, 2), "utf-8");
|
|
9021
9047
|
}
|
|
9022
9048
|
function generateReadme(name, description) {
|
|
9023
9049
|
return `# Monitor Task: ${name}
|
|
@@ -9036,12 +9062,12 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
9036
9062
|
const monitor = ntf.command("monitor").description("通知监控任务管理");
|
|
9037
9063
|
monitor.command("list").description("列出所有监控任务").action(() => {
|
|
9038
9064
|
const dir = tasksDir(ctx);
|
|
9039
|
-
if (!
|
|
9065
|
+
if (!import_node_fs15.existsSync(dir)) {
|
|
9040
9066
|
output({ ok: true, tasks: [] });
|
|
9041
9067
|
return;
|
|
9042
9068
|
}
|
|
9043
9069
|
const tasks = [];
|
|
9044
|
-
for (const entry of
|
|
9070
|
+
for (const entry of import_node_fs15.readdirSync(dir, { withFileTypes: true })) {
|
|
9045
9071
|
if (!entry.isDirectory())
|
|
9046
9072
|
continue;
|
|
9047
9073
|
const meta = readMeta3(import_node_path14.join(dir, entry.name));
|
|
@@ -9057,9 +9083,9 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
9057
9083
|
exitError("NOT_FOUND", `监控任务 '${name}' 不存在`);
|
|
9058
9084
|
const checkpointPath2 = import_node_path14.join(taskDir, "checkpoint.json");
|
|
9059
9085
|
let checkpoint = {};
|
|
9060
|
-
if (
|
|
9086
|
+
if (import_node_fs15.existsSync(checkpointPath2)) {
|
|
9061
9087
|
try {
|
|
9062
|
-
checkpoint = JSON.parse(
|
|
9088
|
+
checkpoint = JSON.parse(import_node_fs15.readFileSync(checkpointPath2, "utf-8"));
|
|
9063
9089
|
} catch {}
|
|
9064
9090
|
}
|
|
9065
9091
|
output({
|
|
@@ -9073,7 +9099,7 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
9073
9099
|
monitor.command("create <name>").description("创建监控任务").requiredOption("--description <text>", "任务描述").requiredOption("--match-rules <json>", "匹配规则 JSON").requiredOption("--schedule <cron>", "cron 表达式").action((name, opts) => {
|
|
9074
9100
|
const dir = tasksDir(ctx);
|
|
9075
9101
|
const taskDir = import_node_path14.join(dir, name);
|
|
9076
|
-
if (
|
|
9102
|
+
if (import_node_fs15.existsSync(taskDir)) {
|
|
9077
9103
|
exitError("ALREADY_EXISTS", `监控任务 '${name}' 已存在`);
|
|
9078
9104
|
}
|
|
9079
9105
|
let matchRules;
|
|
@@ -9082,7 +9108,7 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
9082
9108
|
} catch {
|
|
9083
9109
|
exitError("VALIDATION_FAILED", "match-rules 必须是合法的 JSON");
|
|
9084
9110
|
}
|
|
9085
|
-
|
|
9111
|
+
import_node_fs15.mkdirSync(taskDir, { recursive: true });
|
|
9086
9112
|
const meta = {
|
|
9087
9113
|
name,
|
|
9088
9114
|
description: opts.description,
|
|
@@ -9092,8 +9118,8 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
9092
9118
|
createdAt: new Date().toISOString()
|
|
9093
9119
|
};
|
|
9094
9120
|
writeMeta2(taskDir, meta);
|
|
9095
|
-
|
|
9096
|
-
|
|
9121
|
+
import_node_fs15.writeFileSync(import_node_path14.join(taskDir, "fetch.py"), generateFetchPy(name, matchRules), "utf-8");
|
|
9122
|
+
import_node_fs15.writeFileSync(import_node_path14.join(taskDir, "README.md"), generateReadme(name, opts.description), "utf-8");
|
|
9097
9123
|
output({
|
|
9098
9124
|
ok: true,
|
|
9099
9125
|
name,
|
|
@@ -9118,7 +9144,7 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
9118
9144
|
});
|
|
9119
9145
|
monitor.command("delete <name>").description("删除监控任务").option("--yes", "跳过确认").action((name, opts) => {
|
|
9120
9146
|
const taskDir = import_node_path14.join(tasksDir(ctx), name);
|
|
9121
|
-
if (!
|
|
9147
|
+
if (!import_node_fs15.existsSync(taskDir)) {
|
|
9122
9148
|
exitError("NOT_FOUND", `监控任务 '${name}' 不存在`);
|
|
9123
9149
|
}
|
|
9124
9150
|
if (!opts.yes) {
|
|
@@ -9131,7 +9157,7 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
9131
9157
|
});
|
|
9132
9158
|
process.exit(1);
|
|
9133
9159
|
}
|
|
9134
|
-
|
|
9160
|
+
import_node_fs15.rmSync(taskDir, { recursive: true, force: true });
|
|
9135
9161
|
output({
|
|
9136
9162
|
ok: true,
|
|
9137
9163
|
name,
|
|
@@ -9248,7 +9274,7 @@ function registerLightSend(light) {
|
|
|
9248
9274
|
}
|
|
9249
9275
|
|
|
9250
9276
|
// src/cli/light-setup-tools.ts
|
|
9251
|
-
var
|
|
9277
|
+
var import_node_fs16 = require("node:fs");
|
|
9252
9278
|
var import_node_path15 = require("node:path");
|
|
9253
9279
|
function isObject(value) {
|
|
9254
9280
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
@@ -9317,12 +9343,12 @@ function upsertLightRuleToolsAlsoAllow(cfg) {
|
|
|
9317
9343
|
function registerLightSetupTools(light) {
|
|
9318
9344
|
light.command("setup").description("自动放行云端灯效规则工具(兼容 tools.allow / tools.alsoAllow)").action(() => {
|
|
9319
9345
|
const configPath = resolveConfigPath2();
|
|
9320
|
-
if (!
|
|
9346
|
+
if (!import_node_fs16.existsSync(configPath)) {
|
|
9321
9347
|
exitError("CONFIG_NOT_FOUND", `未找到配置文件: ${configPath}`);
|
|
9322
9348
|
}
|
|
9323
9349
|
let cfg = {};
|
|
9324
9350
|
try {
|
|
9325
|
-
const raw =
|
|
9351
|
+
const raw = import_node_fs16.readFileSync(configPath, "utf-8");
|
|
9326
9352
|
const parsed = JSON.parse(raw);
|
|
9327
9353
|
if (isObject(parsed))
|
|
9328
9354
|
cfg = parsed;
|
|
@@ -9331,8 +9357,8 @@ function registerLightSetupTools(light) {
|
|
|
9331
9357
|
}
|
|
9332
9358
|
const result = upsertLightRuleToolsAlsoAllow(cfg);
|
|
9333
9359
|
try {
|
|
9334
|
-
|
|
9335
|
-
|
|
9360
|
+
import_node_fs16.mkdirSync(import_node_path15.dirname(configPath), { recursive: true });
|
|
9361
|
+
import_node_fs16.writeFileSync(configPath, JSON.stringify(cfg, null, 2) + `
|
|
9336
9362
|
`, "utf-8");
|
|
9337
9363
|
} catch (err2) {
|
|
9338
9364
|
exitError("WRITE_FAILED", `写入配置失败: ${err2?.message ?? String(err2)}`);
|
|
@@ -9351,7 +9377,7 @@ function registerLightSetupTools(light) {
|
|
|
9351
9377
|
}
|
|
9352
9378
|
|
|
9353
9379
|
// src/tunnel/status.ts
|
|
9354
|
-
var
|
|
9380
|
+
var import_node_fs17 = require("node:fs");
|
|
9355
9381
|
var import_node_path16 = require("node:path");
|
|
9356
9382
|
var TUNNEL_STATUS_REL_PATH = import_node_path16.join("plugins", "phone-notifications", "tunnel-status.json");
|
|
9357
9383
|
var TUNNEL_LOCK_REL_PATH = import_node_path16.join("plugins", "phone-notifications", "relay-tunnel.lock");
|
|
@@ -9405,7 +9431,7 @@ function staleStatusMessage(status, lock) {
|
|
|
9405
9431
|
function assessTunnelStatus(stateDir) {
|
|
9406
9432
|
const statusFilePath = import_node_path16.join(stateDir, TUNNEL_STATUS_REL_PATH);
|
|
9407
9433
|
const lockFilePath = import_node_path16.join(stateDir, TUNNEL_LOCK_REL_PATH);
|
|
9408
|
-
if (!
|
|
9434
|
+
if (!import_node_fs17.existsSync(statusFilePath)) {
|
|
9409
9435
|
return {
|
|
9410
9436
|
status: null,
|
|
9411
9437
|
issueCode: "STATUS_NOT_FOUND",
|
|
@@ -9413,7 +9439,7 @@ function assessTunnelStatus(stateDir) {
|
|
|
9413
9439
|
statusFilePath,
|
|
9414
9440
|
lockFilePath,
|
|
9415
9441
|
lock: {
|
|
9416
|
-
exists:
|
|
9442
|
+
exists: import_node_fs17.existsSync(lockFilePath),
|
|
9417
9443
|
pid: null,
|
|
9418
9444
|
startedAt: null,
|
|
9419
9445
|
active: null
|
|
@@ -9422,7 +9448,7 @@ function assessTunnelStatus(stateDir) {
|
|
|
9422
9448
|
}
|
|
9423
9449
|
let rawStatus;
|
|
9424
9450
|
try {
|
|
9425
|
-
rawStatus = JSON.parse(
|
|
9451
|
+
rawStatus = JSON.parse(import_node_fs17.readFileSync(statusFilePath, "utf-8"));
|
|
9426
9452
|
} catch {
|
|
9427
9453
|
return {
|
|
9428
9454
|
status: null,
|
|
@@ -9431,7 +9457,7 @@ function assessTunnelStatus(stateDir) {
|
|
|
9431
9457
|
statusFilePath,
|
|
9432
9458
|
lockFilePath,
|
|
9433
9459
|
lock: {
|
|
9434
|
-
exists:
|
|
9460
|
+
exists: import_node_fs17.existsSync(lockFilePath),
|
|
9435
9461
|
pid: null,
|
|
9436
9462
|
startedAt: null,
|
|
9437
9463
|
active: null
|
|
@@ -9446,7 +9472,7 @@ function assessTunnelStatus(stateDir) {
|
|
|
9446
9472
|
statusFilePath,
|
|
9447
9473
|
lockFilePath,
|
|
9448
9474
|
lock: {
|
|
9449
|
-
exists:
|
|
9475
|
+
exists: import_node_fs17.existsSync(lockFilePath),
|
|
9450
9476
|
pid: null,
|
|
9451
9477
|
startedAt: null,
|
|
9452
9478
|
active: null
|
|
@@ -9454,11 +9480,11 @@ function assessTunnelStatus(stateDir) {
|
|
|
9454
9480
|
};
|
|
9455
9481
|
}
|
|
9456
9482
|
const status = rawStatus;
|
|
9457
|
-
const lockExists =
|
|
9483
|
+
const lockExists = import_node_fs17.existsSync(lockFilePath);
|
|
9458
9484
|
let lockInfo = null;
|
|
9459
9485
|
if (lockExists) {
|
|
9460
9486
|
try {
|
|
9461
|
-
lockInfo = parseTunnelLockInfo(JSON.parse(
|
|
9487
|
+
lockInfo = parseTunnelLockInfo(JSON.parse(import_node_fs17.readFileSync(lockFilePath, "utf-8")));
|
|
9462
9488
|
} catch {
|
|
9463
9489
|
lockInfo = null;
|
|
9464
9490
|
}
|
|
@@ -9561,12 +9587,12 @@ function registerNtfStoragePath(ntf, ctx) {
|
|
|
9561
9587
|
}
|
|
9562
9588
|
|
|
9563
9589
|
// src/cli/log-search.ts
|
|
9564
|
-
var
|
|
9590
|
+
var import_node_fs18 = require("node:fs");
|
|
9565
9591
|
var import_node_path17 = require("node:path");
|
|
9566
9592
|
function resolveLogsDir(ctx) {
|
|
9567
9593
|
if (ctx.stateDir) {
|
|
9568
9594
|
const dir = import_node_path17.join(ctx.stateDir, "plugins", "phone-notifications", "logs");
|
|
9569
|
-
if (
|
|
9595
|
+
if (import_node_fs18.existsSync(dir))
|
|
9570
9596
|
return dir;
|
|
9571
9597
|
}
|
|
9572
9598
|
return null;
|
|
@@ -9574,7 +9600,7 @@ function resolveLogsDir(ctx) {
|
|
|
9574
9600
|
function listLogDateKeys(dir) {
|
|
9575
9601
|
const pattern = /^(\d{4}-\d{2}-\d{2})\.log$/;
|
|
9576
9602
|
const keys = [];
|
|
9577
|
-
for (const entry of
|
|
9603
|
+
for (const entry of import_node_fs18.readdirSync(dir, { withFileTypes: true })) {
|
|
9578
9604
|
if (!entry.isFile())
|
|
9579
9605
|
continue;
|
|
9580
9606
|
const m = pattern.exec(entry.name);
|
|
@@ -9585,9 +9611,9 @@ function listLogDateKeys(dir) {
|
|
|
9585
9611
|
}
|
|
9586
9612
|
function collectLogLines(dir, dateKey, keyword, limit, collected) {
|
|
9587
9613
|
const filePath = import_node_path17.join(dir, `${dateKey}.log`);
|
|
9588
|
-
if (!
|
|
9614
|
+
if (!import_node_fs18.existsSync(filePath))
|
|
9589
9615
|
return;
|
|
9590
|
-
const content =
|
|
9616
|
+
const content = import_node_fs18.readFileSync(filePath, "utf-8");
|
|
9591
9617
|
const lowerKeyword = keyword?.toLowerCase();
|
|
9592
9618
|
for (const line of content.split(`
|
|
9593
9619
|
`)) {
|
|
@@ -9728,11 +9754,11 @@ function registerEnvCli(ntf, deps = {}) {
|
|
|
9728
9754
|
}
|
|
9729
9755
|
|
|
9730
9756
|
// src/cli/doctor.ts
|
|
9731
|
-
var
|
|
9757
|
+
var import_node_fs21 = require("node:fs");
|
|
9732
9758
|
var import_node_readline = require("node:readline");
|
|
9733
9759
|
|
|
9734
9760
|
// src/cli/doctor/check-dangerous-flags.ts
|
|
9735
|
-
var
|
|
9761
|
+
var import_node_fs19 = require("node:fs");
|
|
9736
9762
|
function isObject2(v) {
|
|
9737
9763
|
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
9738
9764
|
}
|
|
@@ -9752,13 +9778,13 @@ var checkDangerousFlags = ({ cfg, configPath }) => {
|
|
|
9752
9778
|
detail: "这会关闭 Control UI 的设备身份验证,任何人都可以访问控制面板。",
|
|
9753
9779
|
fixDescription: "设为 false",
|
|
9754
9780
|
fix: () => {
|
|
9755
|
-
const raw =
|
|
9781
|
+
const raw = import_node_fs19.readFileSync(configPath, "utf-8");
|
|
9756
9782
|
const config = JSON.parse(raw);
|
|
9757
9783
|
const gw = config.gateway;
|
|
9758
9784
|
const cui = gw.controlUi;
|
|
9759
9785
|
cui.dangerouslyDisableDeviceAuth = false;
|
|
9760
|
-
|
|
9761
|
-
|
|
9786
|
+
import_node_fs19.copyFileSync(configPath, configPath + ".bak");
|
|
9787
|
+
import_node_fs19.writeFileSync(configPath, JSON.stringify(config, null, 2) + `
|
|
9762
9788
|
`, "utf-8");
|
|
9763
9789
|
}
|
|
9764
9790
|
};
|
|
@@ -9815,11 +9841,11 @@ function warnEmpty() {
|
|
|
9815
9841
|
}
|
|
9816
9842
|
|
|
9817
9843
|
// src/cli/doctor/check-state-dir-perms.ts
|
|
9818
|
-
var
|
|
9844
|
+
var import_node_fs20 = require("node:fs");
|
|
9819
9845
|
var checkStateDirPerms = ({ stateDir }) => {
|
|
9820
9846
|
let mode;
|
|
9821
9847
|
try {
|
|
9822
|
-
mode =
|
|
9848
|
+
mode = import_node_fs20.statSync(stateDir).mode;
|
|
9823
9849
|
} catch {
|
|
9824
9850
|
return null;
|
|
9825
9851
|
}
|
|
@@ -9834,7 +9860,7 @@ var checkStateDirPerms = ({ stateDir }) => {
|
|
|
9834
9860
|
detail: "其他用户可以读取该目录下的凭证和配置文件。",
|
|
9835
9861
|
fixDescription: "chmod 700 " + stateDir,
|
|
9836
9862
|
fix: () => {
|
|
9837
|
-
|
|
9863
|
+
import_node_fs20.chmodSync(stateDir, 448);
|
|
9838
9864
|
}
|
|
9839
9865
|
};
|
|
9840
9866
|
};
|
|
@@ -10007,10 +10033,10 @@ function isObject5(v) {
|
|
|
10007
10033
|
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
10008
10034
|
}
|
|
10009
10035
|
function readConfig(configPath) {
|
|
10010
|
-
if (!
|
|
10036
|
+
if (!import_node_fs21.existsSync(configPath))
|
|
10011
10037
|
return {};
|
|
10012
10038
|
try {
|
|
10013
|
-
const parsed = JSON.parse(
|
|
10039
|
+
const parsed = JSON.parse(import_node_fs21.readFileSync(configPath, "utf-8"));
|
|
10014
10040
|
return isObject5(parsed) ? parsed : {};
|
|
10015
10041
|
} catch {
|
|
10016
10042
|
return {};
|
|
@@ -10221,7 +10247,7 @@ function registerRecStoragePath(rec, ctx) {
|
|
|
10221
10247
|
|
|
10222
10248
|
// src/cli/rec-setup.ts
|
|
10223
10249
|
var import_node_readline2 = require("node:readline");
|
|
10224
|
-
var
|
|
10250
|
+
var import_node_fs22 = require("node:fs");
|
|
10225
10251
|
function ask(rl, question) {
|
|
10226
10252
|
return new Promise((resolve3) => rl.question(question, resolve3));
|
|
10227
10253
|
}
|
|
@@ -10322,9 +10348,9 @@ async function setupLocal(rl) {
|
|
|
10322
10348
|
function registerRecSetup(rec, ctx) {
|
|
10323
10349
|
rec.command("setup").description("交互式配置 ASR 转写参数,保存到本地配置文件").action(async () => {
|
|
10324
10350
|
const configPath = resolveAsrConfigPath(ctx);
|
|
10325
|
-
if (
|
|
10351
|
+
if (import_node_fs22.existsSync(configPath)) {
|
|
10326
10352
|
try {
|
|
10327
|
-
const existing = JSON.parse(
|
|
10353
|
+
const existing = JSON.parse(import_node_fs22.readFileSync(configPath, "utf-8"));
|
|
10328
10354
|
process.stderr.write(`当前已有配置:mode = ${existing.mode}`);
|
|
10329
10355
|
if (existing.updatedAt)
|
|
10330
10356
|
process.stderr.write(`,更新于 ${existing.updatedAt}`);
|
|
@@ -10340,7 +10366,7 @@ function registerRecSetup(rec, ctx) {
|
|
|
10340
10366
|
const modeIdx = await askChoice(rl, "选择模式", ["api(云端 model-proxy 长录音)", "local(本地 Whisper)"]);
|
|
10341
10367
|
const config = modeIdx === 0 ? await setupApi(rl) : await setupLocal(rl);
|
|
10342
10368
|
const stored = { ...config, updatedAt: new Date().toISOString() };
|
|
10343
|
-
|
|
10369
|
+
import_node_fs22.writeFileSync(configPath, JSON.stringify(stored, null, 2), "utf-8");
|
|
10344
10370
|
process.stderr.write(`
|
|
10345
10371
|
✓ 配置已保存到 ${configPath}
|
|
10346
10372
|
|
|
@@ -10437,7 +10463,7 @@ function registerImageStoragePath(image, ctx) {
|
|
|
10437
10463
|
|
|
10438
10464
|
// src/cli/update.ts
|
|
10439
10465
|
var import_node_child_process4 = require("node:child_process");
|
|
10440
|
-
var
|
|
10466
|
+
var import_node_fs23 = require("node:fs");
|
|
10441
10467
|
var import_node_path18 = require("node:path");
|
|
10442
10468
|
var import_node_os2 = __toESM(require("node:os"));
|
|
10443
10469
|
async function fetchText(url) {
|
|
@@ -10513,7 +10539,7 @@ async function runUpdate(ctx, opts) {
|
|
|
10513
10539
|
}
|
|
10514
10540
|
const tmpScript = import_node_path18.join(import_node_os2.default.tmpdir(), `openclaw-install-${Date.now()}.mjs`);
|
|
10515
10541
|
try {
|
|
10516
|
-
|
|
10542
|
+
import_node_fs23.writeFileSync(tmpScript, installScript, "utf-8");
|
|
10517
10543
|
} catch (err2) {
|
|
10518
10544
|
const msg = `写入临时文件失败: ${err2?.message ?? String(err2)}`;
|
|
10519
10545
|
if (json) {
|
|
@@ -10527,7 +10553,7 @@ async function runUpdate(ctx, opts) {
|
|
|
10527
10553
|
const stateDir = resolveStateDir(ctx.stateDir);
|
|
10528
10554
|
const result = import_node_child_process4.spawnSync(process.execPath, [tmpScript, "--version", latest, "--state-dir", stateDir], { stdio: "inherit" });
|
|
10529
10555
|
try {
|
|
10530
|
-
|
|
10556
|
+
import_node_fs23.unlinkSync(tmpScript);
|
|
10531
10557
|
} catch {}
|
|
10532
10558
|
if (result.error) {
|
|
10533
10559
|
const msg = `安装脚本执行失败: ${result.error.message}`;
|
|
@@ -10624,12 +10650,12 @@ function registerPluginCli(api, params) {
|
|
|
10624
10650
|
}
|
|
10625
10651
|
|
|
10626
10652
|
// src/plugin/ntf-bin.ts
|
|
10627
|
-
var
|
|
10653
|
+
var import_node_fs24 = require("node:fs");
|
|
10628
10654
|
var import_node_path20 = require("node:path");
|
|
10629
10655
|
var import_node_process = __toESM(require("node:process"));
|
|
10630
10656
|
function ensureNtfBinInstalled(opts) {
|
|
10631
10657
|
const { ntfCjsPath, stateDir, logger } = opts;
|
|
10632
|
-
if (!
|
|
10658
|
+
if (!import_node_fs24.existsSync(ntfCjsPath)) {
|
|
10633
10659
|
logger.warn(`ntf wrapper: 目标不存在 ${ntfCjsPath},跳过`);
|
|
10634
10660
|
return;
|
|
10635
10661
|
}
|
|
@@ -10674,7 +10700,7 @@ function resolveNtfBinInstallDirs(opts) {
|
|
|
10674
10700
|
}
|
|
10675
10701
|
function tryInstallWrapper(dir, target) {
|
|
10676
10702
|
try {
|
|
10677
|
-
|
|
10703
|
+
import_node_fs24.mkdirSync(dir, { recursive: true });
|
|
10678
10704
|
} catch (err2) {
|
|
10679
10705
|
return { ok: false, reason: `mkdir ${dir} 失败: ${describeError(err2)}` };
|
|
10680
10706
|
}
|
|
@@ -10688,13 +10714,13 @@ function tryInstallWrapper(dir, target) {
|
|
|
10688
10714
|
}
|
|
10689
10715
|
try {
|
|
10690
10716
|
if (import_node_process.default.platform === "win32") {
|
|
10691
|
-
|
|
10717
|
+
import_node_fs24.writeFileSync(wrapperPath, `@echo off\r
|
|
10692
10718
|
node "${target}" %*\r
|
|
10693
10719
|
`, "utf-8");
|
|
10694
10720
|
} else {
|
|
10695
|
-
|
|
10721
|
+
import_node_fs24.symlinkSync(target, wrapperPath);
|
|
10696
10722
|
try {
|
|
10697
|
-
|
|
10723
|
+
import_node_fs24.chmodSync(target, 493);
|
|
10698
10724
|
} catch {}
|
|
10699
10725
|
}
|
|
10700
10726
|
return { ok: true, path: wrapperPath, created: true };
|
|
@@ -10704,7 +10730,7 @@ node "${target}" %*\r
|
|
|
10704
10730
|
}
|
|
10705
10731
|
function pathExists(path) {
|
|
10706
10732
|
try {
|
|
10707
|
-
|
|
10733
|
+
import_node_fs24.lstatSync(path);
|
|
10708
10734
|
return true;
|
|
10709
10735
|
} catch {
|
|
10710
10736
|
return false;
|
|
@@ -10713,16 +10739,16 @@ function pathExists(path) {
|
|
|
10713
10739
|
function isExistingWrapperForTarget(wrapperPath, target) {
|
|
10714
10740
|
if (import_node_process.default.platform === "win32") {
|
|
10715
10741
|
try {
|
|
10716
|
-
return
|
|
10742
|
+
return import_node_fs24.readFileSync(wrapperPath, "utf-8").includes(`"${target}"`);
|
|
10717
10743
|
} catch {
|
|
10718
10744
|
return false;
|
|
10719
10745
|
}
|
|
10720
10746
|
}
|
|
10721
10747
|
try {
|
|
10722
|
-
if (!
|
|
10748
|
+
if (!import_node_fs24.lstatSync(wrapperPath).isSymbolicLink()) {
|
|
10723
10749
|
return false;
|
|
10724
10750
|
}
|
|
10725
|
-
return
|
|
10751
|
+
return import_node_fs24.realpathSync(wrapperPath) === import_node_fs24.realpathSync(target);
|
|
10726
10752
|
} catch {
|
|
10727
10753
|
return false;
|
|
10728
10754
|
}
|
|
@@ -10748,7 +10774,7 @@ function findCommandOnPath(command, pathDirs) {
|
|
|
10748
10774
|
for (const dir of pathDirs) {
|
|
10749
10775
|
for (const name of names) {
|
|
10750
10776
|
const candidate = import_node_path20.join(dir, name);
|
|
10751
|
-
if (
|
|
10777
|
+
if (import_node_fs24.existsSync(candidate)) {
|
|
10752
10778
|
return candidate;
|
|
10753
10779
|
}
|
|
10754
10780
|
}
|
|
@@ -10763,10 +10789,10 @@ function pushCandidate(candidates, dir, label, onPath) {
|
|
|
10763
10789
|
}
|
|
10764
10790
|
|
|
10765
10791
|
// src/plugin/lifecycle.ts
|
|
10766
|
-
var
|
|
10792
|
+
var import_node_fs35 = require("node:fs");
|
|
10767
10793
|
|
|
10768
10794
|
// src/notification/app-name-map.ts
|
|
10769
|
-
var
|
|
10795
|
+
var import_node_fs25 = require("node:fs");
|
|
10770
10796
|
var import_node_path21 = require("node:path");
|
|
10771
10797
|
var PLUGIN_STATE_DIR = "phone-notifications";
|
|
10772
10798
|
var CACHE_FILE = "app-name-map.json";
|
|
@@ -10800,10 +10826,10 @@ function createAppNameMapProvider(opts) {
|
|
|
10800
10826
|
let inFlightFetch = null;
|
|
10801
10827
|
function loadFromDisk() {
|
|
10802
10828
|
const path = getCachePath(stateDir);
|
|
10803
|
-
if (!
|
|
10829
|
+
if (!import_node_fs25.existsSync(path))
|
|
10804
10830
|
return;
|
|
10805
10831
|
try {
|
|
10806
|
-
const raw = JSON.parse(
|
|
10832
|
+
const raw = JSON.parse(import_node_fs25.readFileSync(path, "utf-8"));
|
|
10807
10833
|
if (!isRecordOfStrings(raw))
|
|
10808
10834
|
return;
|
|
10809
10835
|
map.clear();
|
|
@@ -10850,9 +10876,9 @@ function createAppNameMapProvider(opts) {
|
|
|
10850
10876
|
return;
|
|
10851
10877
|
}
|
|
10852
10878
|
const dir = import_node_path21.join(stateDir, "plugins", PLUGIN_STATE_DIR);
|
|
10853
|
-
|
|
10879
|
+
import_node_fs25.mkdirSync(dir, { recursive: true });
|
|
10854
10880
|
const cachePath = getCachePath(stateDir);
|
|
10855
|
-
|
|
10881
|
+
import_node_fs25.writeFileSync(cachePath, JSON.stringify(Object.fromEntries(map), null, 2), "utf-8");
|
|
10856
10882
|
logger.info(`[app-name-map] refreshed ${map.size} entries from server and saved: ${cachePath}`);
|
|
10857
10883
|
} catch (e) {
|
|
10858
10884
|
const message = e instanceof Error ? e.message : String(e);
|
|
@@ -10903,7 +10929,7 @@ function createAppNameMapProvider(opts) {
|
|
|
10903
10929
|
}
|
|
10904
10930
|
|
|
10905
10931
|
// src/recording/storage.ts
|
|
10906
|
-
var
|
|
10932
|
+
var import_node_fs26 = require("node:fs");
|
|
10907
10933
|
var import_node_path22 = require("node:path");
|
|
10908
10934
|
|
|
10909
10935
|
// src/recording/state-machine.ts
|
|
@@ -11215,14 +11241,14 @@ function extractTranscriptContent(markdown) {
|
|
|
11215
11241
|
function resolveRecordingStorageDir(ctx, logger) {
|
|
11216
11242
|
const stateRecDir = import_node_path22.join(ctx.stateDir, "plugins", "phone-notifications", RECORDINGS_DIR);
|
|
11217
11243
|
try {
|
|
11218
|
-
|
|
11244
|
+
import_node_fs26.mkdirSync(stateRecDir, { recursive: true });
|
|
11219
11245
|
logger.info(`录音将写入 stateDir 路径: ${stateRecDir}`);
|
|
11220
11246
|
return stateRecDir;
|
|
11221
11247
|
} catch {}
|
|
11222
11248
|
if (ctx.workspaceDir) {
|
|
11223
11249
|
const wsRecDir = import_node_path22.join(ctx.workspaceDir, RECORDINGS_DIR);
|
|
11224
11250
|
try {
|
|
11225
|
-
|
|
11251
|
+
import_node_fs26.mkdirSync(wsRecDir, { recursive: true });
|
|
11226
11252
|
logger.warn(`stateDir 不可用,录音已回退到 workspace 路径: ${wsRecDir}`);
|
|
11227
11253
|
return wsRecDir;
|
|
11228
11254
|
} catch {}
|
|
@@ -11249,10 +11275,10 @@ class RecordingStorage {
|
|
|
11249
11275
|
this.indexPath = import_node_path22.join(dir, INDEX_FILE);
|
|
11250
11276
|
}
|
|
11251
11277
|
async init() {
|
|
11252
|
-
|
|
11253
|
-
|
|
11254
|
-
|
|
11255
|
-
|
|
11278
|
+
import_node_fs26.mkdirSync(this.audioDir, { recursive: true });
|
|
11279
|
+
import_node_fs26.mkdirSync(this.transcriptDataDir, { recursive: true });
|
|
11280
|
+
import_node_fs26.mkdirSync(this.transcriptsDir, { recursive: true });
|
|
11281
|
+
import_node_fs26.mkdirSync(this.summariesDir, { recursive: true });
|
|
11256
11282
|
this.loadIndex();
|
|
11257
11283
|
this.logger.info(`录音存储已初始化: ${this.dir}(共 ${this.index.recordings.length} 条记录)`);
|
|
11258
11284
|
}
|
|
@@ -11284,13 +11310,13 @@ class RecordingStorage {
|
|
|
11284
11310
|
return id;
|
|
11285
11311
|
}
|
|
11286
11312
|
if (existing.transcriptDataFile) {
|
|
11287
|
-
|
|
11313
|
+
import_node_fs26.rmSync(import_node_path22.join(this.dir, existing.transcriptDataFile), { force: true });
|
|
11288
11314
|
}
|
|
11289
11315
|
if (existing.transcriptFile) {
|
|
11290
|
-
|
|
11316
|
+
import_node_fs26.rmSync(import_node_path22.join(this.dir, existing.transcriptFile), { force: true });
|
|
11291
11317
|
}
|
|
11292
11318
|
if (existing.summaryFile) {
|
|
11293
|
-
|
|
11319
|
+
import_node_fs26.rmSync(import_node_path22.join(this.dir, existing.summaryFile), { force: true });
|
|
11294
11320
|
}
|
|
11295
11321
|
existing.metadata = metadata;
|
|
11296
11322
|
existing.clientLabel = clientLabel;
|
|
@@ -11347,7 +11373,7 @@ class RecordingStorage {
|
|
|
11347
11373
|
return;
|
|
11348
11374
|
const nextAudioFile = `${AUDIO_DIR}/${filename}`;
|
|
11349
11375
|
if (entry.audioFile && entry.audioFile !== nextAudioFile) {
|
|
11350
|
-
|
|
11376
|
+
import_node_fs26.rmSync(import_node_path22.join(this.dir, entry.audioFile), { force: true });
|
|
11351
11377
|
}
|
|
11352
11378
|
entry.audioFile = nextAudioFile;
|
|
11353
11379
|
entry.updatedAt = new Date().toISOString();
|
|
@@ -11367,7 +11393,7 @@ class RecordingStorage {
|
|
|
11367
11393
|
return;
|
|
11368
11394
|
const nextTranscriptDataFile = `${TRANSCRIPT_DATA_DIR}/${filename}`;
|
|
11369
11395
|
if (entry.transcriptDataFile && entry.transcriptDataFile !== nextTranscriptDataFile) {
|
|
11370
|
-
|
|
11396
|
+
import_node_fs26.rmSync(import_node_path22.join(this.dir, entry.transcriptDataFile), { force: true });
|
|
11371
11397
|
}
|
|
11372
11398
|
entry.transcriptDataFile = nextTranscriptDataFile;
|
|
11373
11399
|
entry.updatedAt = new Date().toISOString();
|
|
@@ -11379,7 +11405,7 @@ class RecordingStorage {
|
|
|
11379
11405
|
return;
|
|
11380
11406
|
const nextTranscriptFile = `${TRANSCRIPTS_DIR}/${filename}`;
|
|
11381
11407
|
if (entry.transcriptFile && entry.transcriptFile !== nextTranscriptFile) {
|
|
11382
|
-
|
|
11408
|
+
import_node_fs26.rmSync(import_node_path22.join(this.dir, entry.transcriptFile), { force: true });
|
|
11383
11409
|
}
|
|
11384
11410
|
entry.transcriptFile = nextTranscriptFile;
|
|
11385
11411
|
entry.updatedAt = new Date().toISOString();
|
|
@@ -11391,7 +11417,7 @@ class RecordingStorage {
|
|
|
11391
11417
|
return;
|
|
11392
11418
|
const nextSummaryFile = `${SUMMARIES_DIR2}/${filename}`;
|
|
11393
11419
|
if (entry.summaryFile && entry.summaryFile !== nextSummaryFile) {
|
|
11394
|
-
|
|
11420
|
+
import_node_fs26.rmSync(import_node_path22.join(this.dir, entry.summaryFile), { force: true });
|
|
11395
11421
|
}
|
|
11396
11422
|
entry.summaryFile = nextSummaryFile;
|
|
11397
11423
|
entry.updatedAt = new Date().toISOString();
|
|
@@ -11481,23 +11507,23 @@ class RecordingStorage {
|
|
|
11481
11507
|
return false;
|
|
11482
11508
|
if (entry.audioFile) {
|
|
11483
11509
|
const audioPath = import_node_path22.join(this.dir, entry.audioFile);
|
|
11484
|
-
|
|
11510
|
+
import_node_fs26.rmSync(audioPath, { force: true });
|
|
11485
11511
|
}
|
|
11486
11512
|
if (entry.srtFile) {
|
|
11487
11513
|
const srtPath = import_node_path22.join(this.dir, entry.srtFile);
|
|
11488
|
-
|
|
11514
|
+
import_node_fs26.rmSync(srtPath, { force: true });
|
|
11489
11515
|
}
|
|
11490
11516
|
if (entry.transcriptDataFile) {
|
|
11491
11517
|
const transcriptDataPath = import_node_path22.join(this.dir, entry.transcriptDataFile);
|
|
11492
|
-
|
|
11518
|
+
import_node_fs26.rmSync(transcriptDataPath, { force: true });
|
|
11493
11519
|
}
|
|
11494
11520
|
if (entry.transcriptFile) {
|
|
11495
11521
|
const transcriptPath = import_node_path22.join(this.dir, entry.transcriptFile);
|
|
11496
|
-
|
|
11522
|
+
import_node_fs26.rmSync(transcriptPath, { force: true });
|
|
11497
11523
|
}
|
|
11498
11524
|
if (entry.summaryFile) {
|
|
11499
11525
|
const summaryPath = import_node_path22.join(this.dir, entry.summaryFile);
|
|
11500
|
-
|
|
11526
|
+
import_node_fs26.rmSync(summaryPath, { force: true });
|
|
11501
11527
|
}
|
|
11502
11528
|
if (opts?.localOnly) {
|
|
11503
11529
|
entry.audioFile = undefined;
|
|
@@ -11545,12 +11571,12 @@ class RecordingStorage {
|
|
|
11545
11571
|
return import_node_path22.join(this.summariesDir, this.buildSummaryFilename(recordingId));
|
|
11546
11572
|
}
|
|
11547
11573
|
loadIndex() {
|
|
11548
|
-
if (!
|
|
11574
|
+
if (!import_node_fs26.existsSync(this.indexPath)) {
|
|
11549
11575
|
this.index = { recordings: [] };
|
|
11550
11576
|
return;
|
|
11551
11577
|
}
|
|
11552
11578
|
try {
|
|
11553
|
-
const raw = JSON.parse(
|
|
11579
|
+
const raw = JSON.parse(import_node_fs26.readFileSync(this.indexPath, "utf-8"));
|
|
11554
11580
|
if (raw && Array.isArray(raw.recordings)) {
|
|
11555
11581
|
let needsRewrite = false;
|
|
11556
11582
|
const normalized = raw.recordings.filter((entry) => entry && typeof entry === "object").map((entry) => {
|
|
@@ -11591,7 +11617,7 @@ class RecordingStorage {
|
|
|
11591
11617
|
segments: []
|
|
11592
11618
|
});
|
|
11593
11619
|
const transcriptDataFilename = this.buildTranscriptDataFilename(compacted.id);
|
|
11594
|
-
|
|
11620
|
+
import_node_fs26.writeFileSync(import_node_path22.join(this.transcriptDataDir, transcriptDataFilename), JSON.stringify(transcriptDoc, null, 2), "utf-8");
|
|
11595
11621
|
compacted.transcriptDataFile = `${TRANSCRIPT_DATA_DIR}/${transcriptDataFilename}`;
|
|
11596
11622
|
needsRewrite = true;
|
|
11597
11623
|
}
|
|
@@ -11600,14 +11626,14 @@ class RecordingStorage {
|
|
|
11600
11626
|
compacted.summaryFile = entry.summaryFile;
|
|
11601
11627
|
} else if (typeof entry.summary === "string" && entry.summary.trim()) {
|
|
11602
11628
|
const summaryFilename = this.buildSummaryFilename(entry.id);
|
|
11603
|
-
|
|
11629
|
+
import_node_fs26.writeFileSync(import_node_path22.join(this.summariesDir, summaryFilename), entry.summary.trim(), "utf-8");
|
|
11604
11630
|
compacted.summaryFile = `${SUMMARIES_DIR2}/${summaryFilename}`;
|
|
11605
11631
|
needsRewrite = true;
|
|
11606
11632
|
} else {
|
|
11607
11633
|
const summaryFromDocument = extractTranscriptSummaryFromDocument(transcriptDoc);
|
|
11608
11634
|
if (summaryFromDocument) {
|
|
11609
11635
|
const summaryFilename = this.buildSummaryFilename(entry.id);
|
|
11610
|
-
|
|
11636
|
+
import_node_fs26.writeFileSync(import_node_path22.join(this.summariesDir, summaryFilename), summaryFromDocument, "utf-8");
|
|
11611
11637
|
compacted.summaryFile = `${SUMMARIES_DIR2}/${summaryFilename}`;
|
|
11612
11638
|
needsRewrite = true;
|
|
11613
11639
|
}
|
|
@@ -11648,7 +11674,7 @@ class RecordingStorage {
|
|
|
11648
11674
|
}
|
|
11649
11675
|
readRelativeTextFile(relativePath) {
|
|
11650
11676
|
try {
|
|
11651
|
-
return
|
|
11677
|
+
return import_node_fs26.readFileSync(import_node_path22.join(this.dir, relativePath), "utf-8");
|
|
11652
11678
|
} catch {
|
|
11653
11679
|
return;
|
|
11654
11680
|
}
|
|
@@ -11661,12 +11687,12 @@ class RecordingStorage {
|
|
|
11661
11687
|
return parseTranscriptDocument(raw);
|
|
11662
11688
|
}
|
|
11663
11689
|
saveIndex() {
|
|
11664
|
-
|
|
11690
|
+
import_node_fs26.writeFileSync(this.indexPath, JSON.stringify(this.index, null, 2), "utf-8");
|
|
11665
11691
|
}
|
|
11666
11692
|
async close() {}
|
|
11667
11693
|
}
|
|
11668
11694
|
// src/recording/downloader.ts
|
|
11669
|
-
var
|
|
11695
|
+
var import_node_fs27 = require("node:fs");
|
|
11670
11696
|
var import_node_path23 = require("node:path");
|
|
11671
11697
|
var import_promises2 = require("node:stream/promises");
|
|
11672
11698
|
var import_node_stream = require("node:stream");
|
|
@@ -11677,7 +11703,7 @@ async function downloadFile(url, destPath, logger, options) {
|
|
|
11677
11703
|
const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
11678
11704
|
const maxRetries = options?.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
11679
11705
|
const retryBackoffMs = options?.retryBackoffMs ?? DEFAULT_RETRY_BACKOFF_MS;
|
|
11680
|
-
|
|
11706
|
+
import_node_fs27.mkdirSync(import_node_path23.dirname(destPath), { recursive: true });
|
|
11681
11707
|
let lastError;
|
|
11682
11708
|
for (let attempt = 1;attempt <= maxRetries; attempt++) {
|
|
11683
11709
|
const startMs = Date.now();
|
|
@@ -11693,11 +11719,11 @@ async function downloadFile(url, destPath, logger, options) {
|
|
|
11693
11719
|
if (!res.body) {
|
|
11694
11720
|
throw new Error("响应体为空");
|
|
11695
11721
|
}
|
|
11696
|
-
const writeStream =
|
|
11722
|
+
const writeStream = import_node_fs27.createWriteStream(destPath);
|
|
11697
11723
|
const readable = import_node_stream.Readable.fromWeb(res.body);
|
|
11698
11724
|
await import_promises2.pipeline(readable, writeStream);
|
|
11699
11725
|
const elapsed = Date.now() - startMs;
|
|
11700
|
-
const fileSize =
|
|
11726
|
+
const fileSize = import_node_fs27.existsSync(destPath) ? import_node_fs27.statSync(destPath).size : 0;
|
|
11701
11727
|
logger.info(`[downloader] 下载完成: ${destPath} (${formatBytes(fileSize)}, ${elapsed}ms)`);
|
|
11702
11728
|
return { ok: true, sizeBytes: fileSize, elapsedMs: elapsed };
|
|
11703
11729
|
} finally {
|
|
@@ -11706,8 +11732,8 @@ async function downloadFile(url, destPath, logger, options) {
|
|
|
11706
11732
|
} catch (err2) {
|
|
11707
11733
|
lastError = err2?.message ?? String(err2);
|
|
11708
11734
|
try {
|
|
11709
|
-
if (
|
|
11710
|
-
|
|
11735
|
+
if (import_node_fs27.existsSync(destPath))
|
|
11736
|
+
import_node_fs27.unlinkSync(destPath);
|
|
11711
11737
|
} catch {}
|
|
11712
11738
|
const isAbort = err2?.name === "AbortError";
|
|
11713
11739
|
logger.warn(`[downloader] 下载失败 (attempt ${attempt}/${maxRetries}): ${isAbort ? "超时" : lastError}`);
|
|
@@ -11742,7 +11768,7 @@ function sleep(ms) {
|
|
|
11742
11768
|
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
11743
11769
|
}
|
|
11744
11770
|
// src/recording/asr.ts
|
|
11745
|
-
var
|
|
11771
|
+
var import_node_fs28 = require("node:fs");
|
|
11746
11772
|
var import_node_path24 = require("node:path");
|
|
11747
11773
|
var DEFAULT_LONG_RECORDING_POLL_INTERVAL_MS = 2000;
|
|
11748
11774
|
var DEFAULT_LONG_RECORDING_MAX_POLL_ATTEMPTS = 3600;
|
|
@@ -11822,7 +11848,7 @@ async function initializeAsr(config, dataDir, logger) {
|
|
|
11822
11848
|
}
|
|
11823
11849
|
}
|
|
11824
11850
|
async function transcribeAudio(audioFilePath, config, logger, options = {}) {
|
|
11825
|
-
if (!
|
|
11851
|
+
if (!import_node_fs28.existsSync(audioFilePath)) {
|
|
11826
11852
|
return { ok: false, error: `音频文件不存在: ${audioFilePath}` };
|
|
11827
11853
|
}
|
|
11828
11854
|
logger.info(`[asr] 开始转写: mode=${config.mode}, file=${audioFilePath}`);
|
|
@@ -11955,18 +11981,18 @@ async function runTranscriptionWorkflow(params) {
|
|
|
11955
11981
|
const markdown = buildTranscriptMarkdown(result, markers, recordingName, durationSec, createdAt);
|
|
11956
11982
|
const transcriptDataFilename = buildTranscriptDataFilename(recordingId);
|
|
11957
11983
|
const transcriptDataPath = import_node_path24.join(transcriptDataDir, transcriptDataFilename);
|
|
11958
|
-
|
|
11984
|
+
import_node_fs28.writeFileSync(transcriptDataPath, JSON.stringify(transcriptData, null, 2), "utf-8");
|
|
11959
11985
|
logger.info(`[asr] 转写 JSON 已写入: ${transcriptDataPath}`);
|
|
11960
11986
|
const safeSummary = title.replace(/[/\\:*?"<>|]/g, "").trim().slice(0, 20);
|
|
11961
11987
|
const filename = safeSummary ? `${recordingId}_${safeSummary}.md` : `${recordingId}.md`;
|
|
11962
11988
|
const filePath = import_node_path24.join(transcriptsDir, filename);
|
|
11963
|
-
|
|
11989
|
+
import_node_fs28.writeFileSync(filePath, markdown, "utf-8");
|
|
11964
11990
|
logger.info(`[asr] 转写文本已写入: ${filePath}`);
|
|
11965
11991
|
let summaryFilename;
|
|
11966
11992
|
if (summary) {
|
|
11967
11993
|
summaryFilename = `${recordingId}.md`;
|
|
11968
11994
|
const summaryFilePath = import_node_path24.join(summariesDir, summaryFilename);
|
|
11969
|
-
|
|
11995
|
+
import_node_fs28.writeFileSync(summaryFilePath, summary, "utf-8");
|
|
11970
11996
|
logger.info(`[asr] 摘要文本已写入: ${summaryFilePath}`);
|
|
11971
11997
|
}
|
|
11972
11998
|
return {
|
|
@@ -12558,7 +12584,7 @@ async function triggerTranscription(recordingId, storage2, asrConfig, logger, op
|
|
|
12558
12584
|
}
|
|
12559
12585
|
}
|
|
12560
12586
|
// src/recording/result-writer.ts
|
|
12561
|
-
var
|
|
12587
|
+
var import_node_fs29 = require("node:fs");
|
|
12562
12588
|
var import_node_path25 = require("node:path");
|
|
12563
12589
|
function handleRecordingResultWrite(params, storage2, logger, options = {}) {
|
|
12564
12590
|
const recordingId = normalizeRequiredText(params.recordingId, "recordingId");
|
|
@@ -12639,11 +12665,11 @@ function writeTranscript(recordingId, recording, transcript, storage2, logger) {
|
|
|
12639
12665
|
raw: transcript
|
|
12640
12666
|
});
|
|
12641
12667
|
const transcriptDataFilename = storage2.buildTranscriptDataFilename(recordingId);
|
|
12642
|
-
|
|
12668
|
+
import_node_fs29.writeFileSync(storage2.getTranscriptDataFilePath(recordingId), JSON.stringify(transcriptDocument, null, 2), "utf-8");
|
|
12643
12669
|
storage2.setTranscriptDataFile(recordingId, transcriptDataFilename);
|
|
12644
12670
|
const transcriptFilename = storage2.buildTranscriptFilename(recordingId, title);
|
|
12645
12671
|
const markdown = normalizePossiblyEmptyText2(transcript.markdown) ?? buildTranscriptMarkdown2(recording, title, text, segments);
|
|
12646
|
-
|
|
12672
|
+
import_node_fs29.writeFileSync(import_node_path25.join(storage2.getTranscriptsDir(), transcriptFilename), ensureTrailingNewline(markdown), "utf-8");
|
|
12647
12673
|
storage2.setTranscriptFile(recordingId, transcriptFilename);
|
|
12648
12674
|
storage2.setTitle(recordingId, title);
|
|
12649
12675
|
logger.info(`[recording-result] 转录文本已写入: ${recordingId}`);
|
|
@@ -12658,7 +12684,7 @@ function writeSummary(recordingId, summary, storage2, logger) {
|
|
|
12658
12684
|
return;
|
|
12659
12685
|
}
|
|
12660
12686
|
const summaryFilename = storage2.buildSummaryFilename(recordingId);
|
|
12661
|
-
|
|
12687
|
+
import_node_fs29.writeFileSync(storage2.getSummaryFilePath(recordingId), ensureTrailingNewline(markdown), "utf-8");
|
|
12662
12688
|
storage2.setSummaryFile(recordingId, summaryFilename);
|
|
12663
12689
|
logger.info(`[recording-result] 总结已写入: ${recordingId}`);
|
|
12664
12690
|
return markdown.trim();
|
|
@@ -12831,7 +12857,7 @@ function formatTimestamp2(ms) {
|
|
|
12831
12857
|
return `${String(minutes).padStart(2, "0")}:${String(seconds).padStart(2, "0")}`;
|
|
12832
12858
|
}
|
|
12833
12859
|
// src/image/store.ts
|
|
12834
|
-
var
|
|
12860
|
+
var import_node_fs30 = require("node:fs");
|
|
12835
12861
|
var import_node_path26 = require("node:path");
|
|
12836
12862
|
var IMAGES_DIR = "images";
|
|
12837
12863
|
var FILES_DIR = "files";
|
|
@@ -12849,14 +12875,14 @@ function extFromMime(mime) {
|
|
|
12849
12875
|
function resolveImageStorageDir(ctx, logger) {
|
|
12850
12876
|
const stateImagesDir = import_node_path26.join(ctx.stateDir, "plugins", "phone-notifications", IMAGES_DIR);
|
|
12851
12877
|
try {
|
|
12852
|
-
|
|
12878
|
+
import_node_fs30.mkdirSync(stateImagesDir, { recursive: true });
|
|
12853
12879
|
logger.info(`图片将写入 stateDir 路径: ${stateImagesDir}`);
|
|
12854
12880
|
return stateImagesDir;
|
|
12855
12881
|
} catch {}
|
|
12856
12882
|
if (ctx.workspaceDir) {
|
|
12857
12883
|
const wsImagesDir = import_node_path26.join(ctx.workspaceDir, IMAGES_DIR);
|
|
12858
12884
|
try {
|
|
12859
|
-
|
|
12885
|
+
import_node_fs30.mkdirSync(wsImagesDir, { recursive: true });
|
|
12860
12886
|
logger.warn(`stateDir 不可用,图片已回退到 workspace 路径: ${wsImagesDir}`);
|
|
12861
12887
|
return wsImagesDir;
|
|
12862
12888
|
} catch {}
|
|
@@ -12877,7 +12903,7 @@ class ImageStorage {
|
|
|
12877
12903
|
this.indexPath = import_node_path26.join(dir, INDEX_FILE2);
|
|
12878
12904
|
}
|
|
12879
12905
|
async init() {
|
|
12880
|
-
|
|
12906
|
+
import_node_fs30.mkdirSync(this.filesDir, { recursive: true });
|
|
12881
12907
|
this.loadIndex();
|
|
12882
12908
|
this.logger.info(`图片存储已初始化: ${this.dir}(共 ${this.index.images.length} 条记录)`);
|
|
12883
12909
|
}
|
|
@@ -12895,7 +12921,7 @@ class ImageStorage {
|
|
|
12895
12921
|
return existing;
|
|
12896
12922
|
}
|
|
12897
12923
|
if (existing.localFile) {
|
|
12898
|
-
|
|
12924
|
+
import_node_fs30.rmSync(import_node_path26.join(this.dir, existing.localFile), { force: true });
|
|
12899
12925
|
}
|
|
12900
12926
|
existing.metadata = metadata;
|
|
12901
12927
|
existing.clientLabel = clientLabel;
|
|
@@ -12956,12 +12982,12 @@ class ImageStorage {
|
|
|
12956
12982
|
return [...this.index.images].sort((a, b) => b.metadata.created_at.localeCompare(a.metadata.created_at));
|
|
12957
12983
|
}
|
|
12958
12984
|
loadIndex() {
|
|
12959
|
-
if (!
|
|
12985
|
+
if (!import_node_fs30.existsSync(this.indexPath)) {
|
|
12960
12986
|
this.index = { images: [] };
|
|
12961
12987
|
return;
|
|
12962
12988
|
}
|
|
12963
12989
|
try {
|
|
12964
|
-
const raw = JSON.parse(
|
|
12990
|
+
const raw = JSON.parse(import_node_fs30.readFileSync(this.indexPath, "utf-8"));
|
|
12965
12991
|
this.index = raw && Array.isArray(raw.images) ? { images: raw.images } : { images: [] };
|
|
12966
12992
|
} catch {
|
|
12967
12993
|
this.logger.warn(`图片索引文件损坏,已重建: ${this.indexPath}`);
|
|
@@ -12969,12 +12995,12 @@ class ImageStorage {
|
|
|
12969
12995
|
}
|
|
12970
12996
|
}
|
|
12971
12997
|
saveIndex() {
|
|
12972
|
-
|
|
12998
|
+
import_node_fs30.writeFileSync(this.indexPath, JSON.stringify(this.index, null, 2), "utf-8");
|
|
12973
12999
|
}
|
|
12974
13000
|
async close() {}
|
|
12975
13001
|
}
|
|
12976
13002
|
// src/image/handler.ts
|
|
12977
|
-
var
|
|
13003
|
+
var import_node_fs31 = require("node:fs");
|
|
12978
13004
|
var import_node_path27 = require("node:path");
|
|
12979
13005
|
var DEFAULT_IMAGE_MAX_BYTES = 20 * 1024 * 1024;
|
|
12980
13006
|
var DOWNLOAD_TIMEOUT_MS = 5 * 60 * 1000;
|
|
@@ -13008,13 +13034,13 @@ async function runImageDownloadInBackground(imageId, metadata, storage2, maxByte
|
|
|
13008
13034
|
logger.info(`[image-sync] 图片已同步: ${imageId} (${result.sizeBytes} bytes)`);
|
|
13009
13035
|
}
|
|
13010
13036
|
async function downloadImage(url, destPath, maxBytes, logger) {
|
|
13011
|
-
|
|
13037
|
+
import_node_fs31.mkdirSync(import_node_path27.dirname(destPath), { recursive: true });
|
|
13012
13038
|
const controller = new AbortController;
|
|
13013
13039
|
const timer = setTimeout(() => controller.abort(), DOWNLOAD_TIMEOUT_MS);
|
|
13014
13040
|
const cleanup = () => {
|
|
13015
13041
|
try {
|
|
13016
|
-
if (
|
|
13017
|
-
|
|
13042
|
+
if (import_node_fs31.existsSync(destPath))
|
|
13043
|
+
import_node_fs31.unlinkSync(destPath);
|
|
13018
13044
|
} catch {}
|
|
13019
13045
|
};
|
|
13020
13046
|
try {
|
|
@@ -13029,7 +13055,7 @@ async function downloadImage(url, destPath, maxBytes, logger) {
|
|
|
13029
13055
|
if (contentLength > 0 && contentLength > maxBytes) {
|
|
13030
13056
|
return { ok: false, error: `图片超过上限 ${maxBytes} 字节` };
|
|
13031
13057
|
}
|
|
13032
|
-
const writeStream =
|
|
13058
|
+
const writeStream = import_node_fs31.createWriteStream(destPath);
|
|
13033
13059
|
let total = 0;
|
|
13034
13060
|
try {
|
|
13035
13061
|
for await (const chunk of res.body) {
|
|
@@ -13063,11 +13089,11 @@ async function downloadImage(url, destPath, maxBytes, logger) {
|
|
|
13063
13089
|
}
|
|
13064
13090
|
}
|
|
13065
13091
|
// src/tunnel/service.ts
|
|
13066
|
-
var
|
|
13092
|
+
var import_node_fs33 = require("node:fs");
|
|
13067
13093
|
var import_node_path30 = require("node:path");
|
|
13068
13094
|
|
|
13069
13095
|
// src/tunnel/relay-client.ts
|
|
13070
|
-
var
|
|
13096
|
+
var import_node_fs32 = require("node:fs");
|
|
13071
13097
|
var import_node_path28 = require("node:path");
|
|
13072
13098
|
|
|
13073
13099
|
// node_modules/ws/wrapper.mjs
|
|
@@ -13184,8 +13210,8 @@ class RelayClient {
|
|
|
13184
13210
|
lastDisconnectReason
|
|
13185
13211
|
};
|
|
13186
13212
|
try {
|
|
13187
|
-
|
|
13188
|
-
|
|
13213
|
+
import_node_fs32.mkdirSync(import_node_path28.dirname(this.opts.statusFilePath), { recursive: true });
|
|
13214
|
+
import_node_fs32.writeFileSync(this.opts.statusFilePath, JSON.stringify(info, null, 2));
|
|
13189
13215
|
} catch {}
|
|
13190
13216
|
}
|
|
13191
13217
|
onInbound(handler) {
|
|
@@ -15047,7 +15073,7 @@ function createTunnelService(opts) {
|
|
|
15047
15073
|
}
|
|
15048
15074
|
function readLockInfo(filePath) {
|
|
15049
15075
|
try {
|
|
15050
|
-
const parsed = JSON.parse(
|
|
15076
|
+
const parsed = JSON.parse(import_node_fs33.readFileSync(filePath, "utf-8"));
|
|
15051
15077
|
const pid = typeof parsed.pid === "number" ? parsed.pid : null;
|
|
15052
15078
|
const updatedAtMs = typeof parsed.updatedAt === "string" ? Date.parse(parsed.updatedAt) : Number.NaN;
|
|
15053
15079
|
return {
|
|
@@ -15080,7 +15106,7 @@ function createTunnelService(opts) {
|
|
|
15080
15106
|
if (!filePath)
|
|
15081
15107
|
return;
|
|
15082
15108
|
try {
|
|
15083
|
-
|
|
15109
|
+
import_node_fs33.writeFileSync(filePath, buildLockPayload(), { mode: 384 });
|
|
15084
15110
|
} catch {}
|
|
15085
15111
|
}, intervalMs);
|
|
15086
15112
|
lockRefreshTimer.unref?.();
|
|
@@ -15094,25 +15120,25 @@ function createTunnelService(opts) {
|
|
|
15094
15120
|
lockStartedAt = null;
|
|
15095
15121
|
if (fd !== null) {
|
|
15096
15122
|
try {
|
|
15097
|
-
|
|
15123
|
+
import_node_fs33.closeSync(fd);
|
|
15098
15124
|
} catch {}
|
|
15099
15125
|
}
|
|
15100
15126
|
if (filePath) {
|
|
15101
15127
|
try {
|
|
15102
|
-
|
|
15128
|
+
import_node_fs33.unlinkSync(filePath);
|
|
15103
15129
|
} catch {}
|
|
15104
15130
|
}
|
|
15105
15131
|
}
|
|
15106
15132
|
function acquireLock(filePath) {
|
|
15107
|
-
|
|
15133
|
+
import_node_fs33.mkdirSync(import_node_path30.dirname(filePath), { recursive: true });
|
|
15108
15134
|
const heartbeatSec = opts.heartbeatSec ?? DEFAULT_HEARTBEAT_SEC;
|
|
15109
15135
|
const refreshMs = heartbeatSec * 1000 * LOCK_REFRESH_HEARTBEAT_MULTIPLIER;
|
|
15110
15136
|
const staleMs = heartbeatSec * 1000 * LOCK_STALE_HEARTBEAT_MULTIPLIER;
|
|
15111
15137
|
for (let attempt = 0;attempt < 2; attempt++) {
|
|
15112
15138
|
try {
|
|
15113
15139
|
lockStartedAt = new Date().toISOString();
|
|
15114
|
-
const fd =
|
|
15115
|
-
|
|
15140
|
+
const fd = import_node_fs33.openSync(filePath, "wx", 384);
|
|
15141
|
+
import_node_fs33.writeFileSync(fd, buildLockPayload());
|
|
15116
15142
|
lockFilePath = filePath;
|
|
15117
15143
|
lockFd = fd;
|
|
15118
15144
|
startLockRefresh(refreshMs);
|
|
@@ -15130,7 +15156,7 @@ function createTunnelService(opts) {
|
|
|
15130
15156
|
const staleReason = describeStaleLock(ownerPid, updatedAt, staleMs);
|
|
15131
15157
|
opts.logger.warn(`Relay tunnel: removing stale local lock (${staleReason})`);
|
|
15132
15158
|
try {
|
|
15133
|
-
|
|
15159
|
+
import_node_fs33.unlinkSync(filePath);
|
|
15134
15160
|
} catch {}
|
|
15135
15161
|
continue;
|
|
15136
15162
|
}
|
|
@@ -15379,7 +15405,7 @@ class ArkclawAuthProvider extends BaseApiKeyAuthProvider {
|
|
|
15379
15405
|
// src/profile/auth/jvsclaw.ts
|
|
15380
15406
|
var import_node_crypto6 = require("node:crypto");
|
|
15381
15407
|
var import_node_os3 = __toESM(require("node:os"));
|
|
15382
|
-
var
|
|
15408
|
+
var import_node_fs34 = require("node:fs");
|
|
15383
15409
|
var import_node_path31 = require("node:path");
|
|
15384
15410
|
var CLAW_CODE = "JvsClaw";
|
|
15385
15411
|
var RETRY_BASE_MS = 2000;
|
|
@@ -15517,7 +15543,7 @@ class JvsclawAuthProvider extends BaseApiKeyAuthProvider {
|
|
|
15517
15543
|
debounceTimer.unref?.();
|
|
15518
15544
|
};
|
|
15519
15545
|
try {
|
|
15520
|
-
configWatcher =
|
|
15546
|
+
configWatcher = import_node_fs34.watch(configDir, { persistent: false }, (_event, changedName) => {
|
|
15521
15547
|
if (!changedName)
|
|
15522
15548
|
return;
|
|
15523
15549
|
const name = String(changedName);
|
|
@@ -15542,7 +15568,7 @@ function hashLinkSecret(value) {
|
|
|
15542
15568
|
function readJvsclawLinkSecretFromConfigFile(configPath = resolveConfigPath()) {
|
|
15543
15569
|
let config;
|
|
15544
15570
|
try {
|
|
15545
|
-
config = JSON.parse(
|
|
15571
|
+
config = JSON.parse(import_node_fs34.readFileSync(configPath, "utf-8"));
|
|
15546
15572
|
} catch {
|
|
15547
15573
|
return;
|
|
15548
15574
|
}
|
|
@@ -15656,7 +15682,7 @@ function readHostGatewayConfig(params) {
|
|
|
15656
15682
|
let configData;
|
|
15657
15683
|
if (configPath) {
|
|
15658
15684
|
try {
|
|
15659
|
-
configData = JSON.parse(
|
|
15685
|
+
configData = JSON.parse(import_node_fs35.readFileSync(configPath, "utf-8"));
|
|
15660
15686
|
} catch (err2) {
|
|
15661
15687
|
if (err2?.code !== "ENOENT") {
|
|
15662
15688
|
params.logger.warn(`Relay tunnel: 无法读取 gateway 鉴权配置 (${configPath})`);
|
|
@@ -16997,5 +17023,5 @@ var src_default = {
|
|
|
16997
17023
|
}
|
|
16998
17024
|
};
|
|
16999
17025
|
|
|
17000
|
-
//# debugId=
|
|
17026
|
+
//# debugId=3838A06742EC9ED664756E2164756E21
|
|
17001
17027
|
//# sourceMappingURL=index.cjs.map
|