@yoooclaw/phone-notifications 1.11.4-beta.3 → 1.11.4-beta.4
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/index.cjs +406 -238
- package/dist/index.cjs.map +1 -1
- package/openclaw.plugin.json +3 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -579,20 +579,20 @@ function selectModelByMemory(availableGB, isAppleSilicon = false) {
|
|
|
579
579
|
return "tiny";
|
|
580
580
|
}
|
|
581
581
|
function resolveModelsDir(dataDir) {
|
|
582
|
-
const dir = (0,
|
|
583
|
-
(0,
|
|
582
|
+
const dir = (0, import_node_path20.join)(dataDir, WHISPER_MODELS_DIR);
|
|
583
|
+
(0, import_node_fs24.mkdirSync)(dir, { recursive: true });
|
|
584
584
|
return dir;
|
|
585
585
|
}
|
|
586
586
|
function resolveBinDir(dataDir) {
|
|
587
|
-
const dir = (0,
|
|
588
|
-
(0,
|
|
587
|
+
const dir = (0, import_node_path20.join)(dataDir, WHISPER_BIN_DIR);
|
|
588
|
+
(0, import_node_fs24.mkdirSync)(dir, { recursive: true });
|
|
589
589
|
return dir;
|
|
590
590
|
}
|
|
591
591
|
function isModelDownloaded(modelsDir, modelSize) {
|
|
592
|
-
const modelPath = (0,
|
|
593
|
-
if (!(0,
|
|
592
|
+
const modelPath = (0, import_node_path20.join)(modelsDir, MODEL_FILENAMES[modelSize]);
|
|
593
|
+
if (!(0, import_node_fs24.existsSync)(modelPath)) return false;
|
|
594
594
|
try {
|
|
595
|
-
const stat = (0,
|
|
595
|
+
const stat = (0, import_node_fs24.statSync)(modelPath);
|
|
596
596
|
const expectedSize = MODEL_DISK_SIZES[modelSize];
|
|
597
597
|
return stat.size >= expectedSize * 0.8;
|
|
598
598
|
} catch {
|
|
@@ -601,7 +601,7 @@ function isModelDownloaded(modelsDir, modelSize) {
|
|
|
601
601
|
}
|
|
602
602
|
async function downloadModel(modelsDir, modelSize, logger, modelSource, mirrorUrl) {
|
|
603
603
|
const filename = MODEL_FILENAMES[modelSize];
|
|
604
|
-
const modelPath = (0,
|
|
604
|
+
const modelPath = (0, import_node_path20.join)(modelsDir, filename);
|
|
605
605
|
if (isModelDownloaded(modelsDir, modelSize)) {
|
|
606
606
|
logger.info(`[whisper-local] \u6A21\u578B\u5DF2\u5B58\u5728\uFF0C\u8DF3\u8FC7\u4E0B\u8F7D: ${filename}`);
|
|
607
607
|
return { ok: true, modelPath };
|
|
@@ -667,7 +667,7 @@ async function probeUrl(url, logger) {
|
|
|
667
667
|
async function downloadFromUrl(url, modelPath, logger) {
|
|
668
668
|
const tmpPath = `${modelPath}.downloading`;
|
|
669
669
|
try {
|
|
670
|
-
(0,
|
|
670
|
+
(0, import_node_fs24.mkdirSync)((0, import_node_path20.dirname)(modelPath), { recursive: true });
|
|
671
671
|
const controller = new AbortController();
|
|
672
672
|
const timer = setTimeout(() => controller.abort(), 30 * 60 * 1e3);
|
|
673
673
|
try {
|
|
@@ -683,7 +683,7 @@ async function downloadFromUrl(url, modelPath, logger) {
|
|
|
683
683
|
return { ok: false, modelPath, error: "\u6A21\u578B\u4E0B\u8F7D\u5931\u8D25: \u54CD\u5E94\u4F53\u4E3A\u7A7A" };
|
|
684
684
|
}
|
|
685
685
|
const contentLength = Number(res.headers.get("content-length") ?? 0);
|
|
686
|
-
const writeStream = (0,
|
|
686
|
+
const writeStream = (0, import_node_fs24.createWriteStream)(tmpPath);
|
|
687
687
|
const readable = import_node_stream2.Readable.fromWeb(res.body);
|
|
688
688
|
let downloaded = 0;
|
|
689
689
|
let lastLogPercent = 0;
|
|
@@ -705,14 +705,14 @@ async function downloadFromUrl(url, modelPath, logger) {
|
|
|
705
705
|
}
|
|
706
706
|
const { renameSync: renameSync2 } = await import("fs");
|
|
707
707
|
renameSync2(tmpPath, modelPath);
|
|
708
|
-
const fileSize = (0,
|
|
708
|
+
const fileSize = (0, import_node_fs24.statSync)(modelPath).size;
|
|
709
709
|
logger.info(
|
|
710
|
-
`[whisper-local] \u6A21\u578B\u4E0B\u8F7D\u5B8C\u6210: ${(0,
|
|
710
|
+
`[whisper-local] \u6A21\u578B\u4E0B\u8F7D\u5B8C\u6210: ${(0, import_node_path20.basename)(modelPath)} (${formatBytes2(fileSize)})`
|
|
711
711
|
);
|
|
712
712
|
return { ok: true, modelPath };
|
|
713
713
|
} catch (err2) {
|
|
714
714
|
try {
|
|
715
|
-
if ((0,
|
|
715
|
+
if ((0, import_node_fs24.existsSync)(tmpPath)) (0, import_node_fs24.unlinkSync)(tmpPath);
|
|
716
716
|
} catch {
|
|
717
717
|
}
|
|
718
718
|
const msg = err2?.name === "AbortError" ? "\u6A21\u578B\u4E0B\u8F7D\u8D85\u65F6\uFF0830 \u5206\u949F\uFF09" : err2?.message ?? String(err2);
|
|
@@ -724,8 +724,8 @@ function findWhisperBinary(dataDir, logger) {
|
|
|
724
724
|
const binDir = resolveBinDir(dataDir);
|
|
725
725
|
const binNames = (0, import_node_os4.platform)() === "win32" ? ["whisper-cli.exe", "whisper.exe", "main.exe"] : ["whisper-cli", "whisper", "main"];
|
|
726
726
|
for (const name of binNames) {
|
|
727
|
-
const binPath = (0,
|
|
728
|
-
if ((0,
|
|
727
|
+
const binPath = (0, import_node_path20.join)(binDir, name);
|
|
728
|
+
if ((0, import_node_fs24.existsSync)(binPath)) {
|
|
729
729
|
logger.info(`[whisper-local] \u627E\u5230\u672C\u5730\u4E8C\u8FDB\u5236: ${binPath}`);
|
|
730
730
|
return binPath;
|
|
731
731
|
}
|
|
@@ -776,7 +776,7 @@ async function transcribeWithWhisperLocal(audioFilePath, localConfig, dataDir, l
|
|
|
776
776
|
return { ok: false, error: `\u6A21\u578B\u4E0B\u8F7D\u5931\u8D25: ${downloadResult.error}` };
|
|
777
777
|
}
|
|
778
778
|
}
|
|
779
|
-
const modelPath = (0,
|
|
779
|
+
const modelPath = (0, import_node_path20.join)(modelsDir, MODEL_FILENAMES[modelSize]);
|
|
780
780
|
let inputPath = audioFilePath;
|
|
781
781
|
let tmpWavPath = null;
|
|
782
782
|
const actualFmt = detectAudioFormat(audioFilePath);
|
|
@@ -828,10 +828,10 @@ async function transcribeWithWhisperLocal(audioFilePath, localConfig, dataDir, l
|
|
|
828
828
|
logger.info(`[whisper-local] \u8F6C\u5199\u8017\u65F6: ${Math.round(elapsed / 1e3)}s`);
|
|
829
829
|
const jsonPath = inputPath + ".json";
|
|
830
830
|
let jsonContent;
|
|
831
|
-
if ((0,
|
|
832
|
-
jsonContent = (0,
|
|
831
|
+
if ((0, import_node_fs24.existsSync)(jsonPath)) {
|
|
832
|
+
jsonContent = (0, import_node_fs24.readFileSync)(jsonPath, "utf-8");
|
|
833
833
|
try {
|
|
834
|
-
(0,
|
|
834
|
+
(0, import_node_fs24.unlinkSync)(jsonPath);
|
|
835
835
|
} catch {
|
|
836
836
|
}
|
|
837
837
|
} else {
|
|
@@ -909,10 +909,10 @@ function getPhysicalCoreCount() {
|
|
|
909
909
|
}
|
|
910
910
|
function detectAudioFormat(filePath) {
|
|
911
911
|
try {
|
|
912
|
-
const fd = (0,
|
|
912
|
+
const fd = (0, import_node_fs24.openSync)(filePath, "r");
|
|
913
913
|
const buf = Buffer.alloc(12);
|
|
914
|
-
(0,
|
|
915
|
-
(0,
|
|
914
|
+
(0, import_node_fs24.readSync)(fd, buf, 0, 12, 0);
|
|
915
|
+
(0, import_node_fs24.closeSync)(fd);
|
|
916
916
|
const header = buf.toString("ascii", 0, 4);
|
|
917
917
|
const header8 = buf.toString("ascii", 0, 8);
|
|
918
918
|
if (header === "RIFF" && buf.toString("ascii", 8, 12) === "WAVE") return ".wav";
|
|
@@ -947,7 +947,7 @@ function convertToWav(inputPath, outputPath, actualFmt, logger) {
|
|
|
947
947
|
timeout: 12e4,
|
|
948
948
|
stdio: ["pipe", "pipe", "pipe"]
|
|
949
949
|
});
|
|
950
|
-
if (ffmpegResult.status === 0 && (0,
|
|
950
|
+
if (ffmpegResult.status === 0 && (0, import_node_fs24.existsSync)(outputPath)) {
|
|
951
951
|
logger.info(`[whisper-local] ffmpeg \u8F6C\u6362\u5B8C\u6210: ${outputPath}`);
|
|
952
952
|
return { ok: true };
|
|
953
953
|
}
|
|
@@ -960,7 +960,7 @@ function convertToWav(inputPath, outputPath, actualFmt, logger) {
|
|
|
960
960
|
["--rate", "16000", "--mono", inputPath, outputPath],
|
|
961
961
|
{ encoding: "utf-8", timeout: 12e4, stdio: ["pipe", "pipe", "pipe"] }
|
|
962
962
|
);
|
|
963
|
-
if (opusResult.status === 0 && (0,
|
|
963
|
+
if (opusResult.status === 0 && (0, import_node_fs24.existsSync)(outputPath)) {
|
|
964
964
|
logger.info(`[whisper-local] opusdec \u8F6C\u6362\u5B8C\u6210: ${outputPath}`);
|
|
965
965
|
return { ok: true };
|
|
966
966
|
}
|
|
@@ -974,7 +974,7 @@ function convertToWav(inputPath, outputPath, actualFmt, logger) {
|
|
|
974
974
|
if (detectedExt && !inputPath.endsWith(detectedExt)) {
|
|
975
975
|
tmpCopy = inputPath + ".detected" + detectedExt;
|
|
976
976
|
try {
|
|
977
|
-
(0,
|
|
977
|
+
(0, import_node_fs24.copyFileSync)(inputPath, tmpCopy);
|
|
978
978
|
actualInputPath = tmpCopy;
|
|
979
979
|
logger.info(
|
|
980
980
|
`[whisper-local] \u68C0\u6D4B\u5230\u5B9E\u9645\u683C\u5F0F ${detectedExt}\uFF0C\u4E34\u65F6\u91CD\u547D\u540D`
|
|
@@ -998,22 +998,22 @@ function convertToWav(inputPath, outputPath, actualFmt, logger) {
|
|
|
998
998
|
timeout: 12e4,
|
|
999
999
|
stdio: ["pipe", "pipe", "pipe"]
|
|
1000
1000
|
});
|
|
1001
|
-
if (tmpCopy && (0,
|
|
1001
|
+
if (tmpCopy && (0, import_node_fs24.existsSync)(tmpCopy)) {
|
|
1002
1002
|
try {
|
|
1003
|
-
(0,
|
|
1003
|
+
(0, import_node_fs24.unlinkSync)(tmpCopy);
|
|
1004
1004
|
} catch {
|
|
1005
1005
|
}
|
|
1006
1006
|
}
|
|
1007
|
-
if (afResult.status === 0 && (0,
|
|
1007
|
+
if (afResult.status === 0 && (0, import_node_fs24.existsSync)(outputPath)) {
|
|
1008
1008
|
logger.info(`[whisper-local] afconvert \u8F6C\u6362\u5B8C\u6210: ${outputPath}`);
|
|
1009
1009
|
return { ok: true };
|
|
1010
1010
|
}
|
|
1011
1011
|
const stderr = afResult.stderr?.slice(0, 200) ?? "";
|
|
1012
1012
|
return { ok: false, error: `afconvert \u8F6C\u6362\u5931\u8D25 (exit ${afResult.status}): ${stderr}` };
|
|
1013
1013
|
} catch (err2) {
|
|
1014
|
-
if (tmpCopy && (0,
|
|
1014
|
+
if (tmpCopy && (0, import_node_fs24.existsSync)(tmpCopy)) {
|
|
1015
1015
|
try {
|
|
1016
|
-
(0,
|
|
1016
|
+
(0, import_node_fs24.unlinkSync)(tmpCopy);
|
|
1017
1017
|
} catch {
|
|
1018
1018
|
}
|
|
1019
1019
|
}
|
|
@@ -1024,9 +1024,9 @@ function convertToWav(inputPath, outputPath, actualFmt, logger) {
|
|
|
1024
1024
|
return { ok: false, error: `\u65E0\u6CD5\u5C06\u97F3\u9891\u8F6C\u6362\u4E3A WAV \u683C\u5F0F\u3002${fmtHint}` };
|
|
1025
1025
|
}
|
|
1026
1026
|
function cleanupTmpWav(path2) {
|
|
1027
|
-
if (path2 && (0,
|
|
1027
|
+
if (path2 && (0, import_node_fs24.existsSync)(path2)) {
|
|
1028
1028
|
try {
|
|
1029
|
-
(0,
|
|
1029
|
+
(0, import_node_fs24.unlinkSync)(path2);
|
|
1030
1030
|
} catch {
|
|
1031
1031
|
}
|
|
1032
1032
|
}
|
|
@@ -1112,13 +1112,13 @@ function formatBytes2(bytes) {
|
|
|
1112
1112
|
if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
1113
1113
|
return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)}GB`;
|
|
1114
1114
|
}
|
|
1115
|
-
var import_node_child_process3,
|
|
1115
|
+
var import_node_child_process3, import_node_fs24, import_node_path20, import_promises3, import_node_stream2, import_node_os4, WHISPER_MODELS_DIR, WHISPER_BIN_DIR, HF_MODEL_URL_TEMPLATE, MODELSCOPE_MODEL_URL_TEMPLATE, PROBE_TIMEOUT_MS, MODEL_FILENAMES, MODEL_DISK_SIZES;
|
|
1116
1116
|
var init_whisper_local = __esm({
|
|
1117
1117
|
"src/recording/whisper-local.ts"() {
|
|
1118
1118
|
"use strict";
|
|
1119
1119
|
import_node_child_process3 = require("child_process");
|
|
1120
|
-
|
|
1121
|
-
|
|
1120
|
+
import_node_fs24 = require("fs");
|
|
1121
|
+
import_node_path20 = require("path");
|
|
1122
1122
|
import_promises3 = require("stream/promises");
|
|
1123
1123
|
import_node_stream2 = require("stream");
|
|
1124
1124
|
import_node_os4 = require("os");
|
|
@@ -1273,7 +1273,7 @@ async function initializeAsr(config, dataDir, logger) {
|
|
|
1273
1273
|
}
|
|
1274
1274
|
}
|
|
1275
1275
|
async function transcribeAudio(audioFilePath, config, logger, options = {}) {
|
|
1276
|
-
if (!(0,
|
|
1276
|
+
if (!(0, import_node_fs25.existsSync)(audioFilePath)) {
|
|
1277
1277
|
return { ok: false, error: `\u97F3\u9891\u6587\u4EF6\u4E0D\u5B58\u5728: ${audioFilePath}` };
|
|
1278
1278
|
}
|
|
1279
1279
|
logger.info(
|
|
@@ -1419,8 +1419,8 @@ async function runTranscriptionWorkflow(params) {
|
|
|
1419
1419
|
createdAt
|
|
1420
1420
|
);
|
|
1421
1421
|
const transcriptDataFilename = buildTranscriptDataFilename(recordingId);
|
|
1422
|
-
const transcriptDataPath = (0,
|
|
1423
|
-
(0,
|
|
1422
|
+
const transcriptDataPath = (0, import_node_path21.join)(transcriptDataDir, transcriptDataFilename);
|
|
1423
|
+
(0, import_node_fs25.writeFileSync)(
|
|
1424
1424
|
transcriptDataPath,
|
|
1425
1425
|
JSON.stringify(transcriptData, null, 2),
|
|
1426
1426
|
"utf-8"
|
|
@@ -1428,14 +1428,14 @@ async function runTranscriptionWorkflow(params) {
|
|
|
1428
1428
|
logger.info(`[asr] \u8F6C\u5199 JSON \u5DF2\u5199\u5165: ${transcriptDataPath}`);
|
|
1429
1429
|
const safeSummary = title.replace(/[/\\:*?"<>|]/g, "").trim().slice(0, 20);
|
|
1430
1430
|
const filename = safeSummary ? `${recordingId}_${safeSummary}.md` : `${recordingId}.md`;
|
|
1431
|
-
const filePath = (0,
|
|
1432
|
-
(0,
|
|
1431
|
+
const filePath = (0, import_node_path21.join)(transcriptsDir, filename);
|
|
1432
|
+
(0, import_node_fs25.writeFileSync)(filePath, markdown, "utf-8");
|
|
1433
1433
|
logger.info(`[asr] \u8F6C\u5199\u6587\u672C\u5DF2\u5199\u5165: ${filePath}`);
|
|
1434
1434
|
let summaryFilename;
|
|
1435
1435
|
if (summary) {
|
|
1436
1436
|
summaryFilename = `${recordingId}.md`;
|
|
1437
|
-
const summaryFilePath = (0,
|
|
1438
|
-
(0,
|
|
1437
|
+
const summaryFilePath = (0, import_node_path21.join)(summariesDir, summaryFilename);
|
|
1438
|
+
(0, import_node_fs25.writeFileSync)(summaryFilePath, summary, "utf-8");
|
|
1439
1439
|
logger.info(`[asr] \u6458\u8981\u6587\u672C\u5DF2\u5199\u5165: ${summaryFilePath}`);
|
|
1440
1440
|
}
|
|
1441
1441
|
return {
|
|
@@ -1521,7 +1521,7 @@ async function transcribeWithModelProxy(audioOssUrl, audioDurationMs, apiConfig,
|
|
|
1521
1521
|
}
|
|
1522
1522
|
async function transcribeWithWhisperLocal2(audioFilePath, config, logger) {
|
|
1523
1523
|
const { transcribeWithWhisperLocal: runLocal } = await Promise.resolve().then(() => (init_whisper_local(), whisper_local_exports));
|
|
1524
|
-
const dataDir = process.env.OPENCLAW_STATE_DIR ?? process.env.QCLAW_STATE_DIR ?? (0,
|
|
1524
|
+
const dataDir = process.env.OPENCLAW_STATE_DIR ?? process.env.QCLAW_STATE_DIR ?? (0, import_node_path21.join)(audioFilePath, "..", "..", "..");
|
|
1525
1525
|
const localConfig = config.local ?? {};
|
|
1526
1526
|
const result = await runLocal(
|
|
1527
1527
|
audioFilePath,
|
|
@@ -1830,12 +1830,12 @@ function formatTranscriptSegmentText(segment) {
|
|
|
1830
1830
|
}
|
|
1831
1831
|
return text;
|
|
1832
1832
|
}
|
|
1833
|
-
var
|
|
1833
|
+
var import_node_fs25, import_node_path21, DEFAULT_LONG_RECORDING_POLL_INTERVAL_MS, DEFAULT_LONG_RECORDING_MAX_POLL_ATTEMPTS, LONG_RECORDING_RUNNING_STATUSES, LONG_RECORDING_TERMINAL_FAILURE_STATUSES;
|
|
1834
1834
|
var init_asr = __esm({
|
|
1835
1835
|
"src/recording/asr.ts"() {
|
|
1836
1836
|
"use strict";
|
|
1837
|
-
|
|
1838
|
-
|
|
1837
|
+
import_node_fs25 = require("fs");
|
|
1838
|
+
import_node_path21 = require("path");
|
|
1839
1839
|
init_credentials();
|
|
1840
1840
|
init_env();
|
|
1841
1841
|
init_transcript_document();
|
|
@@ -5480,7 +5480,7 @@ function readBuildInjectedVersion() {
|
|
|
5480
5480
|
if (false) {
|
|
5481
5481
|
return void 0;
|
|
5482
5482
|
}
|
|
5483
|
-
const version = "1.11.4-beta.
|
|
5483
|
+
const version = "1.11.4-beta.4".trim();
|
|
5484
5484
|
return version || void 0;
|
|
5485
5485
|
}
|
|
5486
5486
|
function readPluginVersionFromPackageJson() {
|
|
@@ -7427,6 +7427,43 @@ function resolveUpdateChannel(params) {
|
|
|
7427
7427
|
// src/update/index.ts
|
|
7428
7428
|
var import_node_path8 = require("path");
|
|
7429
7429
|
|
|
7430
|
+
// src/plugin/runtime-state.ts
|
|
7431
|
+
init_host();
|
|
7432
|
+
|
|
7433
|
+
// src/plugin/shared.ts
|
|
7434
|
+
function readBody(req) {
|
|
7435
|
+
return new Promise((resolve, reject) => {
|
|
7436
|
+
const chunks = [];
|
|
7437
|
+
req.on("data", (chunk) => chunks.push(chunk));
|
|
7438
|
+
req.on("end", () => resolve(Buffer.concat(chunks).toString()));
|
|
7439
|
+
req.on("error", reject);
|
|
7440
|
+
});
|
|
7441
|
+
}
|
|
7442
|
+
function trimToUndefined2(value) {
|
|
7443
|
+
if (typeof value !== "string") {
|
|
7444
|
+
return void 0;
|
|
7445
|
+
}
|
|
7446
|
+
const trimmed = value.trim();
|
|
7447
|
+
return trimmed || void 0;
|
|
7448
|
+
}
|
|
7449
|
+
|
|
7450
|
+
// src/plugin/runtime-state.ts
|
|
7451
|
+
function tryResolveRuntimeStateDir(api) {
|
|
7452
|
+
const runtimeState = api?.runtime?.state;
|
|
7453
|
+
const resolveStateDir2 = runtimeState?.resolveStateDir;
|
|
7454
|
+
if (typeof resolveStateDir2 !== "function") {
|
|
7455
|
+
return void 0;
|
|
7456
|
+
}
|
|
7457
|
+
try {
|
|
7458
|
+
return trimToUndefined2(resolveStateDir2.call(runtimeState));
|
|
7459
|
+
} catch {
|
|
7460
|
+
return void 0;
|
|
7461
|
+
}
|
|
7462
|
+
}
|
|
7463
|
+
function resolvePluginStateDir(api) {
|
|
7464
|
+
return tryResolveRuntimeStateDir(api) ?? resolveStateDir();
|
|
7465
|
+
}
|
|
7466
|
+
|
|
7430
7467
|
// src/update/checker.ts
|
|
7431
7468
|
function parseSemver(v) {
|
|
7432
7469
|
const [main, pre = null] = v.split("-", 2);
|
|
@@ -7647,7 +7684,7 @@ function resolveTargetDir(api) {
|
|
|
7647
7684
|
if (installPath) return installPath;
|
|
7648
7685
|
} catch {
|
|
7649
7686
|
}
|
|
7650
|
-
return (0, import_node_path8.join)(api
|
|
7687
|
+
return (0, import_node_path8.join)(resolvePluginStateDir(api), "extensions", PLUGIN_ID);
|
|
7651
7688
|
}
|
|
7652
7689
|
async function updateConfigRecord(api, version, targetDir, tgzUrl) {
|
|
7653
7690
|
const configApi = api.runtime.config;
|
|
@@ -7857,7 +7894,7 @@ function registerAutoUpdateLifecycle(deps) {
|
|
|
7857
7894
|
}
|
|
7858
7895
|
|
|
7859
7896
|
// src/plugin/cli.ts
|
|
7860
|
-
var
|
|
7897
|
+
var import_node_path15 = require("path");
|
|
7861
7898
|
|
|
7862
7899
|
// src/cli/auth.ts
|
|
7863
7900
|
var import_node_fs9 = require("fs");
|
|
@@ -8532,21 +8569,155 @@ function registerLightSetupTools(light) {
|
|
|
8532
8569
|
}
|
|
8533
8570
|
|
|
8534
8571
|
// src/cli/tunnel-status.ts
|
|
8535
|
-
var import_node_fs13 = require("fs");
|
|
8536
|
-
var import_node_path12 = require("path");
|
|
8537
8572
|
init_credentials();
|
|
8538
8573
|
init_env();
|
|
8539
|
-
|
|
8540
|
-
|
|
8541
|
-
|
|
8542
|
-
|
|
8543
|
-
|
|
8574
|
+
|
|
8575
|
+
// src/tunnel/status.ts
|
|
8576
|
+
var import_node_fs13 = require("fs");
|
|
8577
|
+
var import_node_path12 = require("path");
|
|
8578
|
+
var TUNNEL_STATUS_REL_PATH = (0, import_node_path12.join)(
|
|
8579
|
+
"plugins",
|
|
8580
|
+
"phone-notifications",
|
|
8581
|
+
"tunnel-status.json"
|
|
8582
|
+
);
|
|
8583
|
+
var TUNNEL_LOCK_REL_PATH = (0, import_node_path12.join)(
|
|
8584
|
+
"plugins",
|
|
8585
|
+
"phone-notifications",
|
|
8586
|
+
"relay-tunnel.lock"
|
|
8587
|
+
);
|
|
8588
|
+
function isTunnelState(value) {
|
|
8589
|
+
return value === "connected" || value === "connecting" || value === "disconnected" || value === "stopped";
|
|
8590
|
+
}
|
|
8591
|
+
function isTunnelStatusInfo(value) {
|
|
8592
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
8593
|
+
const obj = value;
|
|
8594
|
+
return isTunnelState(obj.state) && typeof obj.since === "string" && typeof obj.reconnectAttempt === "number" && (obj.lastDisconnectReason === void 0 || typeof obj.lastDisconnectReason === "string");
|
|
8595
|
+
}
|
|
8596
|
+
function parseTunnelLockInfo(value) {
|
|
8597
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
8598
|
+
const obj = value;
|
|
8599
|
+
return typeof obj.pid === "number" && typeof obj.startedAt === "string" ? { pid: obj.pid, startedAt: obj.startedAt } : null;
|
|
8600
|
+
}
|
|
8601
|
+
function isProcessAlive(pid) {
|
|
8602
|
+
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
8603
|
+
if (pid === process.pid) return true;
|
|
8604
|
+
try {
|
|
8605
|
+
process.kill(pid, 0);
|
|
8606
|
+
return true;
|
|
8607
|
+
} catch (err2) {
|
|
8608
|
+
return err2?.code === "EPERM";
|
|
8609
|
+
}
|
|
8610
|
+
}
|
|
8611
|
+
function isStatusOlderThanLock(statusSince, lockStartedAt) {
|
|
8612
|
+
const statusTs = Date.parse(statusSince);
|
|
8613
|
+
const lockTs = Date.parse(lockStartedAt);
|
|
8614
|
+
if (Number.isNaN(statusTs) || Number.isNaN(lockTs)) return false;
|
|
8615
|
+
return statusTs + 1e3 < lockTs;
|
|
8616
|
+
}
|
|
8617
|
+
function staleStatusMessage(status, lock) {
|
|
8618
|
+
const prefix = `\u96A7\u9053\u72B6\u6001\u6587\u4EF6\u663E\u793A\u5DF2\u8FDE\u63A5\uFF08\u81EA ${status.since}\uFF09`;
|
|
8619
|
+
if (!lock.exists) {
|
|
8620
|
+
return `${prefix}\uFF0C\u4F46\u672A\u627E\u5230\u672C\u5730\u8FD0\u884C\u9501\uFF0C\u72B6\u6001\u53EF\u80FD\u5DF2\u8FC7\u671F\u3002\u8BF7\u91CD\u542F openclaw \u4E3B\u8FDB\u7A0B\u3002`;
|
|
8621
|
+
}
|
|
8622
|
+
if (lock.pid === null || lock.startedAt === null) {
|
|
8623
|
+
return `${prefix}\uFF0C\u4F46\u672C\u5730\u8FD0\u884C\u9501\u5185\u5BB9\u4E0D\u5B8C\u6574\uFF0C\u65E0\u6CD5\u786E\u8BA4\u5F53\u524D\u8FDE\u63A5\u662F\u5426\u4ECD\u7136\u6709\u6548\u3002\u8BF7\u91CD\u542F openclaw \u4E3B\u8FDB\u7A0B\u3002`;
|
|
8624
|
+
}
|
|
8625
|
+
if (lock.active === false) {
|
|
8626
|
+
return `${prefix}\uFF0C\u4F46\u672C\u5730\u8FD0\u884C\u9501\u4ECD\u6307\u5411\u5DF2\u9000\u51FA\u7684\u8FDB\u7A0B pid=${lock.pid}\uFF0C\u72B6\u6001\u53EF\u80FD\u5DF2\u8FC7\u671F\u3002\u8BF7\u91CD\u542F openclaw \u4E3B\u8FDB\u7A0B\u3002`;
|
|
8627
|
+
}
|
|
8628
|
+
return `${prefix}\uFF0C\u4F46\u5F53\u524D\u8FD0\u884C\u9501\u542F\u52A8\u4E8E ${lock.startedAt}\uFF0C\u665A\u4E8E\u72B6\u6001\u65F6\u95F4\uFF0C\u8BF4\u660E\u72B6\u6001\u672A\u968F\u65B0\u8FDB\u7A0B\u5237\u65B0\u3002\u8BF7\u91CD\u542F openclaw \u4E3B\u8FDB\u7A0B\u3002`;
|
|
8629
|
+
}
|
|
8630
|
+
function assessTunnelStatus(stateDir) {
|
|
8631
|
+
const statusFilePath = (0, import_node_path12.join)(stateDir, TUNNEL_STATUS_REL_PATH);
|
|
8632
|
+
const lockFilePath = (0, import_node_path12.join)(stateDir, TUNNEL_LOCK_REL_PATH);
|
|
8633
|
+
if (!(0, import_node_fs13.existsSync)(statusFilePath)) {
|
|
8634
|
+
return {
|
|
8635
|
+
status: null,
|
|
8636
|
+
issueCode: "STATUS_NOT_FOUND",
|
|
8637
|
+
issueMessage: "\u672A\u627E\u5230\u96A7\u9053\u72B6\u6001\u6587\u4EF6\uFF0C\u96A7\u9053\u670D\u52A1\u53EF\u80FD\u5C1A\u672A\u542F\u52A8\u8FC7\u3002\u8BF7\u786E\u8BA4 openclaw \u4E3B\u8FDB\u7A0B\u6B63\u5728\u8FD0\u884C\u3002",
|
|
8638
|
+
statusFilePath,
|
|
8639
|
+
lockFilePath,
|
|
8640
|
+
lock: {
|
|
8641
|
+
exists: (0, import_node_fs13.existsSync)(lockFilePath),
|
|
8642
|
+
pid: null,
|
|
8643
|
+
startedAt: null,
|
|
8644
|
+
active: null
|
|
8645
|
+
}
|
|
8646
|
+
};
|
|
8647
|
+
}
|
|
8648
|
+
let rawStatus;
|
|
8544
8649
|
try {
|
|
8545
|
-
|
|
8650
|
+
rawStatus = JSON.parse((0, import_node_fs13.readFileSync)(statusFilePath, "utf-8"));
|
|
8546
8651
|
} catch {
|
|
8547
|
-
return
|
|
8652
|
+
return {
|
|
8653
|
+
status: null,
|
|
8654
|
+
issueCode: "STATUS_INVALID",
|
|
8655
|
+
issueMessage: "\u96A7\u9053\u72B6\u6001\u6587\u4EF6\u89E3\u6790\u5931\u8D25\uFF0C\u6587\u4EF6\u5185\u5BB9\u635F\u574F\u6216\u683C\u5F0F\u4E0D\u6B63\u786E\u3002\u8BF7\u91CD\u542F openclaw \u4E3B\u8FDB\u7A0B\u3002",
|
|
8656
|
+
statusFilePath,
|
|
8657
|
+
lockFilePath,
|
|
8658
|
+
lock: {
|
|
8659
|
+
exists: (0, import_node_fs13.existsSync)(lockFilePath),
|
|
8660
|
+
pid: null,
|
|
8661
|
+
startedAt: null,
|
|
8662
|
+
active: null
|
|
8663
|
+
}
|
|
8664
|
+
};
|
|
8665
|
+
}
|
|
8666
|
+
if (!isTunnelStatusInfo(rawStatus)) {
|
|
8667
|
+
return {
|
|
8668
|
+
status: null,
|
|
8669
|
+
issueCode: "STATUS_INVALID",
|
|
8670
|
+
issueMessage: "\u96A7\u9053\u72B6\u6001\u6587\u4EF6\u7F3A\u5C11\u5FC5\u8981\u5B57\u6BB5\u6216\u5B57\u6BB5\u7C7B\u578B\u4E0D\u6B63\u786E\u3002\u8BF7\u91CD\u542F openclaw \u4E3B\u8FDB\u7A0B\u3002",
|
|
8671
|
+
statusFilePath,
|
|
8672
|
+
lockFilePath,
|
|
8673
|
+
lock: {
|
|
8674
|
+
exists: (0, import_node_fs13.existsSync)(lockFilePath),
|
|
8675
|
+
pid: null,
|
|
8676
|
+
startedAt: null,
|
|
8677
|
+
active: null
|
|
8678
|
+
}
|
|
8679
|
+
};
|
|
8680
|
+
}
|
|
8681
|
+
const status = rawStatus;
|
|
8682
|
+
const lockExists = (0, import_node_fs13.existsSync)(lockFilePath);
|
|
8683
|
+
let lockInfo = null;
|
|
8684
|
+
if (lockExists) {
|
|
8685
|
+
try {
|
|
8686
|
+
lockInfo = parseTunnelLockInfo(JSON.parse((0, import_node_fs13.readFileSync)(lockFilePath, "utf-8")));
|
|
8687
|
+
} catch {
|
|
8688
|
+
lockInfo = null;
|
|
8689
|
+
}
|
|
8548
8690
|
}
|
|
8691
|
+
const lock = {
|
|
8692
|
+
exists: lockExists,
|
|
8693
|
+
pid: lockInfo?.pid ?? null,
|
|
8694
|
+
startedAt: lockInfo?.startedAt ?? null,
|
|
8695
|
+
active: lockInfo ? isProcessAlive(lockInfo.pid) : null
|
|
8696
|
+
};
|
|
8697
|
+
if (status.state === "connected") {
|
|
8698
|
+
const isStale = !lock.exists || lock.pid === null || lock.startedAt === null || lock.active === false || isStatusOlderThanLock(status.since, lock.startedAt);
|
|
8699
|
+
if (isStale) {
|
|
8700
|
+
return {
|
|
8701
|
+
status,
|
|
8702
|
+
issueCode: "STATUS_STALE",
|
|
8703
|
+
issueMessage: staleStatusMessage(status, lock),
|
|
8704
|
+
statusFilePath,
|
|
8705
|
+
lockFilePath,
|
|
8706
|
+
lock
|
|
8707
|
+
};
|
|
8708
|
+
}
|
|
8709
|
+
}
|
|
8710
|
+
return {
|
|
8711
|
+
status,
|
|
8712
|
+
issueCode: null,
|
|
8713
|
+
issueMessage: null,
|
|
8714
|
+
statusFilePath,
|
|
8715
|
+
lockFilePath,
|
|
8716
|
+
lock
|
|
8717
|
+
};
|
|
8549
8718
|
}
|
|
8719
|
+
|
|
8720
|
+
// src/cli/tunnel-status.ts
|
|
8550
8721
|
function formatMessage(status) {
|
|
8551
8722
|
switch (status.state) {
|
|
8552
8723
|
case "connected":
|
|
@@ -8577,13 +8748,23 @@ function registerTunnelStatus(ntf, ctx) {
|
|
|
8577
8748
|
"API Key \u672A\u8BBE\u7F6E\uFF0C\u96A7\u9053\u65E0\u6CD5\u8FDE\u63A5\u3002\u8BF7\u6267\u884C openclaw ntf auth set-api-key <apiKey>"
|
|
8578
8749
|
);
|
|
8579
8750
|
}
|
|
8580
|
-
|
|
8751
|
+
if (!ctx.stateDir) {
|
|
8752
|
+
exitError(
|
|
8753
|
+
"STATE_DIR_UNAVAILABLE",
|
|
8754
|
+
"\u65E0\u6CD5\u786E\u5B9A\u72B6\u6001\u76EE\u5F55\uFF0C\u65E0\u6CD5\u68C0\u67E5\u96A7\u9053\u72B6\u6001\u3002\u8BF7\u5728 openclaw \u4E3B\u73AF\u5883\u4E2D\u6267\u884C\u8BE5\u547D\u4EE4\u3002"
|
|
8755
|
+
);
|
|
8756
|
+
}
|
|
8757
|
+
const assessment = assessTunnelStatus(ctx.stateDir);
|
|
8758
|
+
const status = assessment.status;
|
|
8581
8759
|
if (!status) {
|
|
8582
8760
|
exitError(
|
|
8583
|
-
"STATUS_NOT_FOUND",
|
|
8584
|
-
"\u672A\u627E\u5230\u96A7\u9053\u72B6\u6001\u6587\u4EF6\uFF0C\u96A7\u9053\u670D\u52A1\u53EF\u80FD\u5C1A\u672A\u542F\u52A8\u8FC7\u3002\u8BF7\u786E\u8BA4 openclaw \u4E3B\u8FDB\u7A0B\u6B63\u5728\u8FD0\u884C\u3002"
|
|
8761
|
+
assessment.issueCode ?? "STATUS_NOT_FOUND",
|
|
8762
|
+
assessment.issueMessage ?? "\u672A\u627E\u5230\u96A7\u9053\u72B6\u6001\u6587\u4EF6\uFF0C\u96A7\u9053\u670D\u52A1\u53EF\u80FD\u5C1A\u672A\u542F\u52A8\u8FC7\u3002\u8BF7\u786E\u8BA4 openclaw \u4E3B\u8FDB\u7A0B\u6B63\u5728\u8FD0\u884C\u3002"
|
|
8585
8763
|
);
|
|
8586
8764
|
}
|
|
8765
|
+
if (assessment.issueCode) {
|
|
8766
|
+
exitError(assessment.issueCode, assessment.issueMessage ?? formatMessage(status));
|
|
8767
|
+
}
|
|
8587
8768
|
const ok2 = status.state === "connected";
|
|
8588
8769
|
output({
|
|
8589
8770
|
ok: ok2,
|
|
@@ -8594,6 +8775,11 @@ function registerTunnelStatus(ntf, ctx) {
|
|
|
8594
8775
|
reconnectAttempt: status.reconnectAttempt,
|
|
8595
8776
|
lastDisconnectReason: status.lastDisconnectReason
|
|
8596
8777
|
},
|
|
8778
|
+
runtime: {
|
|
8779
|
+
lockOwnerPid: assessment.lock.pid,
|
|
8780
|
+
lockOwnerStartedAt: assessment.lock.startedAt,
|
|
8781
|
+
lockOwnerActive: assessment.lock.active
|
|
8782
|
+
},
|
|
8597
8783
|
message: formatMessage(status)
|
|
8598
8784
|
});
|
|
8599
8785
|
if (!ok2) process.exit(1);
|
|
@@ -8773,7 +8959,7 @@ function registerEnvCli(ntf, deps = {}) {
|
|
|
8773
8959
|
}
|
|
8774
8960
|
|
|
8775
8961
|
// src/cli/doctor.ts
|
|
8776
|
-
var
|
|
8962
|
+
var import_node_fs17 = require("fs");
|
|
8777
8963
|
var import_node_readline = require("readline");
|
|
8778
8964
|
init_host();
|
|
8779
8965
|
|
|
@@ -8922,39 +9108,40 @@ var checkCredentials = () => {
|
|
|
8922
9108
|
};
|
|
8923
9109
|
|
|
8924
9110
|
// src/cli/doctor/check-tunnel.ts
|
|
8925
|
-
var import_node_fs17 = require("fs");
|
|
8926
|
-
var import_node_path14 = require("path");
|
|
8927
|
-
var STATUS_REL_PATH2 = (0, import_node_path14.join)(
|
|
8928
|
-
"plugins",
|
|
8929
|
-
"phone-notifications",
|
|
8930
|
-
"tunnel-status.json"
|
|
8931
|
-
);
|
|
8932
9111
|
var checkTunnel = ({ stateDir }) => {
|
|
8933
|
-
const
|
|
8934
|
-
|
|
9112
|
+
const assessment = assessTunnelStatus(stateDir);
|
|
9113
|
+
const status = assessment.status;
|
|
9114
|
+
if (assessment.issueCode === "STATUS_NOT_FOUND") {
|
|
8935
9115
|
return {
|
|
8936
9116
|
id: "tunnel",
|
|
8937
9117
|
severity: "warn",
|
|
8938
9118
|
title: "\u96A7\u9053\u72B6\u6001\u6587\u4EF6\u4E0D\u5B58\u5728",
|
|
8939
|
-
detail: "\u96A7\u9053\u670D\u52A1\u53EF\u80FD\u5C1A\u672A\u542F\u52A8\u8FC7\uFF0C\u6216\u72B6\u6001\u6587\u4EF6\u5DF2\u88AB\u5220\u9664\u3002",
|
|
9119
|
+
detail: assessment.issueMessage ?? "\u96A7\u9053\u670D\u52A1\u53EF\u80FD\u5C1A\u672A\u542F\u52A8\u8FC7\uFF0C\u6216\u72B6\u6001\u6587\u4EF6\u5DF2\u88AB\u5220\u9664\u3002",
|
|
8940
9120
|
fixDescription: "\u8BF7\u786E\u8BA4 openclaw \u4E3B\u8FDB\u7A0B\u6B63\u5728\u8FD0\u884C",
|
|
8941
9121
|
fix: null
|
|
8942
9122
|
};
|
|
8943
9123
|
}
|
|
8944
|
-
|
|
8945
|
-
try {
|
|
8946
|
-
status = JSON.parse((0, import_node_fs17.readFileSync)(filePath, "utf-8"));
|
|
8947
|
-
} catch {
|
|
9124
|
+
if (assessment.issueCode === "STATUS_INVALID") {
|
|
8948
9125
|
return {
|
|
8949
9126
|
id: "tunnel",
|
|
8950
9127
|
severity: "warn",
|
|
8951
9128
|
title: "\u96A7\u9053\u72B6\u6001\u6587\u4EF6\u89E3\u6790\u5931\u8D25",
|
|
8952
|
-
detail: "\u6587\u4EF6\u5185\u5BB9\u635F\u574F\u6216\u683C\u5F0F\u4E0D\u6B63\u786E\u3002",
|
|
9129
|
+
detail: assessment.issueMessage ?? "\u6587\u4EF6\u5185\u5BB9\u635F\u574F\u6216\u683C\u5F0F\u4E0D\u6B63\u786E\u3002",
|
|
9130
|
+
fixDescription: "\u8BF7\u91CD\u542F openclaw \u4E3B\u8FDB\u7A0B",
|
|
9131
|
+
fix: null
|
|
9132
|
+
};
|
|
9133
|
+
}
|
|
9134
|
+
if (assessment.issueCode === "STATUS_STALE") {
|
|
9135
|
+
return {
|
|
9136
|
+
id: "tunnel",
|
|
9137
|
+
severity: "warn",
|
|
9138
|
+
title: "\u96A7\u9053\u72B6\u6001\u5DF2\u8FC7\u671F",
|
|
9139
|
+
detail: assessment.issueMessage ?? "\u96A7\u9053\u72B6\u6001\u6587\u4EF6\u4ECD\u663E\u793A\u5DF2\u8FDE\u63A5\uFF0C\u4F46\u8FD0\u884C\u65F6\u72B6\u6001\u5DF2\u5931\u6548\u3002",
|
|
8953
9140
|
fixDescription: "\u8BF7\u91CD\u542F openclaw \u4E3B\u8FDB\u7A0B",
|
|
8954
9141
|
fix: null
|
|
8955
9142
|
};
|
|
8956
9143
|
}
|
|
8957
|
-
if (status.state === "connected") return null;
|
|
9144
|
+
if (!status || status.state === "connected") return null;
|
|
8958
9145
|
const reasonSuffix = status.lastDisconnectReason ? `\uFF0C\u539F\u56E0: ${status.lastDisconnectReason}` : "";
|
|
8959
9146
|
return {
|
|
8960
9147
|
id: "tunnel",
|
|
@@ -9036,9 +9223,9 @@ function isObject5(v) {
|
|
|
9036
9223
|
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
9037
9224
|
}
|
|
9038
9225
|
function readConfig(configPath) {
|
|
9039
|
-
if (!(0,
|
|
9226
|
+
if (!(0, import_node_fs17.existsSync)(configPath)) return {};
|
|
9040
9227
|
try {
|
|
9041
|
-
const parsed = JSON.parse((0,
|
|
9228
|
+
const parsed = JSON.parse((0, import_node_fs17.readFileSync)(configPath, "utf-8"));
|
|
9042
9229
|
return isObject5(parsed) ? parsed : {};
|
|
9043
9230
|
} catch {
|
|
9044
9231
|
return {};
|
|
@@ -9241,7 +9428,7 @@ function registerRecStoragePath(rec, ctx) {
|
|
|
9241
9428
|
|
|
9242
9429
|
// src/cli/rec-setup.ts
|
|
9243
9430
|
var import_node_readline2 = require("readline");
|
|
9244
|
-
var
|
|
9431
|
+
var import_node_fs18 = require("fs");
|
|
9245
9432
|
function ask(rl, question) {
|
|
9246
9433
|
return new Promise((resolve) => rl.question(question, resolve));
|
|
9247
9434
|
}
|
|
@@ -9327,9 +9514,9 @@ async function setupLocal(rl) {
|
|
|
9327
9514
|
function registerRecSetup(rec, ctx) {
|
|
9328
9515
|
rec.command("setup").description("\u4EA4\u4E92\u5F0F\u914D\u7F6E ASR \u8F6C\u5199\u53C2\u6570\uFF0C\u4FDD\u5B58\u5230\u672C\u5730\u914D\u7F6E\u6587\u4EF6").action(async () => {
|
|
9329
9516
|
const configPath = resolveAsrConfigPath(ctx);
|
|
9330
|
-
if ((0,
|
|
9517
|
+
if ((0, import_node_fs18.existsSync)(configPath)) {
|
|
9331
9518
|
try {
|
|
9332
|
-
const existing = JSON.parse((0,
|
|
9519
|
+
const existing = JSON.parse((0, import_node_fs18.readFileSync)(configPath, "utf-8"));
|
|
9333
9520
|
process.stderr.write(`\u5F53\u524D\u5DF2\u6709\u914D\u7F6E\uFF1Amode = ${existing.mode}`);
|
|
9334
9521
|
if (existing.updatedAt) process.stderr.write(`\uFF0C\u66F4\u65B0\u4E8E ${existing.updatedAt}`);
|
|
9335
9522
|
process.stderr.write("\n");
|
|
@@ -9342,7 +9529,7 @@ function registerRecSetup(rec, ctx) {
|
|
|
9342
9529
|
const modeIdx = await askChoice(rl, "\u9009\u62E9\u6A21\u5F0F", ["api\uFF08\u4E91\u7AEF model-proxy \u957F\u5F55\u97F3\uFF09", "local\uFF08\u672C\u5730 Whisper\uFF09"]);
|
|
9343
9530
|
const config = modeIdx === 0 ? await setupApi(rl) : await setupLocal(rl);
|
|
9344
9531
|
const stored = { ...config, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
9345
|
-
(0,
|
|
9532
|
+
(0, import_node_fs18.writeFileSync)(configPath, JSON.stringify(stored, null, 2), "utf-8");
|
|
9346
9533
|
process.stderr.write(`
|
|
9347
9534
|
\u2713 \u914D\u7F6E\u5DF2\u4FDD\u5B58\u5230 ${configPath}
|
|
9348
9535
|
|
|
@@ -9356,8 +9543,8 @@ function registerRecSetup(rec, ctx) {
|
|
|
9356
9543
|
|
|
9357
9544
|
// src/cli/update.ts
|
|
9358
9545
|
var import_node_child_process2 = require("child_process");
|
|
9359
|
-
var
|
|
9360
|
-
var
|
|
9546
|
+
var import_node_fs19 = require("fs");
|
|
9547
|
+
var import_node_path14 = require("path");
|
|
9361
9548
|
var import_node_os3 = __toESM(require("os"), 1);
|
|
9362
9549
|
init_host();
|
|
9363
9550
|
var BASE_URL2 = "https://artifact.yoooclaw.com/plugin";
|
|
@@ -9416,9 +9603,9 @@ async function runUpdate(ctx, opts) {
|
|
|
9416
9603
|
`);
|
|
9417
9604
|
process.exit(1);
|
|
9418
9605
|
}
|
|
9419
|
-
const tmpScript = (0,
|
|
9606
|
+
const tmpScript = (0, import_node_path14.join)(import_node_os3.default.tmpdir(), `openclaw-install-${Date.now()}.mjs`);
|
|
9420
9607
|
try {
|
|
9421
|
-
(0,
|
|
9608
|
+
(0, import_node_fs19.writeFileSync)(tmpScript, installScript, "utf-8");
|
|
9422
9609
|
} catch (err2) {
|
|
9423
9610
|
const msg = `\u5199\u5165\u4E34\u65F6\u6587\u4EF6\u5931\u8D25: ${err2?.message ?? String(err2)}`;
|
|
9424
9611
|
if (json) {
|
|
@@ -9436,7 +9623,7 @@ async function runUpdate(ctx, opts) {
|
|
|
9436
9623
|
{ stdio: "inherit" }
|
|
9437
9624
|
);
|
|
9438
9625
|
try {
|
|
9439
|
-
(0,
|
|
9626
|
+
(0, import_node_fs19.unlinkSync)(tmpScript);
|
|
9440
9627
|
} catch {
|
|
9441
9628
|
}
|
|
9442
9629
|
if (result.error) {
|
|
@@ -9500,17 +9687,17 @@ function inferOpenClawRootDir(workspaceDir) {
|
|
|
9500
9687
|
if (!workspaceDir) {
|
|
9501
9688
|
return void 0;
|
|
9502
9689
|
}
|
|
9503
|
-
if ((0,
|
|
9690
|
+
if ((0, import_node_path15.basename)(workspaceDir) !== "workspace") {
|
|
9504
9691
|
return void 0;
|
|
9505
9692
|
}
|
|
9506
|
-
return (0,
|
|
9693
|
+
return (0, import_node_path15.dirname)(workspaceDir);
|
|
9507
9694
|
}
|
|
9508
9695
|
function registerPluginCli(api, params) {
|
|
9509
9696
|
const { logger, openclawDir } = params;
|
|
9510
9697
|
const registerAlias = (command) => {
|
|
9511
9698
|
api.registerCli(
|
|
9512
9699
|
(ctx) => {
|
|
9513
|
-
const effectiveStateDir = openclawDir ?? inferOpenClawRootDir(ctx.workspaceDir);
|
|
9700
|
+
const effectiveStateDir = openclawDir ?? ctx.stateDir ?? inferOpenClawRootDir(ctx.workspaceDir);
|
|
9514
9701
|
registerAllCli(
|
|
9515
9702
|
ctx.program,
|
|
9516
9703
|
{
|
|
@@ -9754,12 +9941,12 @@ function registerLightControlTool(api, logger) {
|
|
|
9754
9941
|
}
|
|
9755
9942
|
|
|
9756
9943
|
// src/plugin/lifecycle.ts
|
|
9757
|
-
var
|
|
9944
|
+
var import_node_fs29 = require("fs");
|
|
9758
9945
|
init_host();
|
|
9759
9946
|
|
|
9760
9947
|
// src/notification/app-name-map.ts
|
|
9761
|
-
var
|
|
9762
|
-
var
|
|
9948
|
+
var import_node_fs20 = require("fs");
|
|
9949
|
+
var import_node_path16 = require("path");
|
|
9763
9950
|
init_credentials();
|
|
9764
9951
|
init_env();
|
|
9765
9952
|
var PLUGIN_STATE_DIR = "phone-notifications";
|
|
@@ -9780,7 +9967,7 @@ function isAppNameMapApiResponse(v) {
|
|
|
9780
9967
|
);
|
|
9781
9968
|
}
|
|
9782
9969
|
function getCachePath(stateDir) {
|
|
9783
|
-
return (0,
|
|
9970
|
+
return (0, import_node_path16.join)(stateDir, "plugins", PLUGIN_STATE_DIR, CACHE_FILE);
|
|
9784
9971
|
}
|
|
9785
9972
|
function createAppNameMapProvider(opts) {
|
|
9786
9973
|
const { stateDir, logger } = opts;
|
|
@@ -9792,9 +9979,9 @@ function createAppNameMapProvider(opts) {
|
|
|
9792
9979
|
let inFlightFetch = null;
|
|
9793
9980
|
function loadFromDisk() {
|
|
9794
9981
|
const path2 = getCachePath(stateDir);
|
|
9795
|
-
if (!(0,
|
|
9982
|
+
if (!(0, import_node_fs20.existsSync)(path2)) return;
|
|
9796
9983
|
try {
|
|
9797
|
-
const raw = JSON.parse((0,
|
|
9984
|
+
const raw = JSON.parse((0, import_node_fs20.readFileSync)(path2, "utf-8"));
|
|
9798
9985
|
if (!isRecordOfStrings(raw)) return;
|
|
9799
9986
|
map.clear();
|
|
9800
9987
|
for (const [k, v] of Object.entries(raw)) map.set(k, v);
|
|
@@ -9838,10 +10025,10 @@ function createAppNameMapProvider(opts) {
|
|
|
9838
10025
|
logger.warn("[app-name-map] refresh succeeded but got 0 entries");
|
|
9839
10026
|
return;
|
|
9840
10027
|
}
|
|
9841
|
-
const dir = (0,
|
|
9842
|
-
(0,
|
|
10028
|
+
const dir = (0, import_node_path16.join)(stateDir, "plugins", PLUGIN_STATE_DIR);
|
|
10029
|
+
(0, import_node_fs20.mkdirSync)(dir, { recursive: true });
|
|
9843
10030
|
const cachePath = getCachePath(stateDir);
|
|
9844
|
-
(0,
|
|
10031
|
+
(0, import_node_fs20.writeFileSync)(cachePath, JSON.stringify(Object.fromEntries(map), null, 2), "utf-8");
|
|
9845
10032
|
logger.info(`[app-name-map] refreshed ${map.size} entries from server and saved: ${cachePath}`);
|
|
9846
10033
|
} catch (e) {
|
|
9847
10034
|
const message = e instanceof Error ? e.message : String(e);
|
|
@@ -9885,9 +10072,9 @@ function createAppNameMapProvider(opts) {
|
|
|
9885
10072
|
}
|
|
9886
10073
|
|
|
9887
10074
|
// src/notification/storage.ts
|
|
9888
|
-
var
|
|
10075
|
+
var import_node_fs21 = require("fs");
|
|
9889
10076
|
var import_node_crypto2 = require("crypto");
|
|
9890
|
-
var
|
|
10077
|
+
var import_node_path17 = require("path");
|
|
9891
10078
|
|
|
9892
10079
|
// src/notification/feishu-normalize.ts
|
|
9893
10080
|
function normalizeOptionalText(value) {
|
|
@@ -10015,7 +10202,7 @@ var NOTIFICATION_DIR_NAME = "notifications";
|
|
|
10015
10202
|
var ID_INDEX_DIR_NAME = ".ids";
|
|
10016
10203
|
var CONTENT_KEY_INDEX_DIR_NAME = ".keys";
|
|
10017
10204
|
function getStateFallbackNotificationDir(stateDir) {
|
|
10018
|
-
return (0,
|
|
10205
|
+
return (0, import_node_path17.join)(stateDir, "plugins", "phone-notifications", NOTIFICATION_DIR_NAME);
|
|
10019
10206
|
}
|
|
10020
10207
|
function buildFallbackContent(n) {
|
|
10021
10208
|
const body = n.body?.trim();
|
|
@@ -10033,8 +10220,8 @@ function buildFallbackContent(n) {
|
|
|
10033
10220
|
}
|
|
10034
10221
|
function ensureWritableDirectory(dir) {
|
|
10035
10222
|
try {
|
|
10036
|
-
(0,
|
|
10037
|
-
(0,
|
|
10223
|
+
(0, import_node_fs21.mkdirSync)(dir, { recursive: true });
|
|
10224
|
+
(0, import_node_fs21.accessSync)(dir, import_node_fs21.constants.R_OK | import_node_fs21.constants.W_OK);
|
|
10038
10225
|
return true;
|
|
10039
10226
|
} catch {
|
|
10040
10227
|
return false;
|
|
@@ -10047,7 +10234,7 @@ function resolveNotificationStorageDir(ctx, logger) {
|
|
|
10047
10234
|
return stateNotifDir;
|
|
10048
10235
|
}
|
|
10049
10236
|
if (ctx.workspaceDir) {
|
|
10050
|
-
const workspaceDir = (0,
|
|
10237
|
+
const workspaceDir = (0, import_node_path17.join)(ctx.workspaceDir, NOTIFICATION_DIR_NAME);
|
|
10051
10238
|
if (ensureWritableDirectory(workspaceDir)) {
|
|
10052
10239
|
logger.warn(
|
|
10053
10240
|
`stateDir \u4E0D\u53EF\u7528\uFF0C\u901A\u77E5\u5DF2\u56DE\u9000\u5230 workspace \u8DEF\u5F84: ${workspaceDir}`
|
|
@@ -10062,8 +10249,8 @@ var NotificationStorage = class {
|
|
|
10062
10249
|
this.config = config;
|
|
10063
10250
|
this.logger = logger;
|
|
10064
10251
|
this.dir = dir;
|
|
10065
|
-
this.idIndexDir = (0,
|
|
10066
|
-
this.contentKeyIndexDir = (0,
|
|
10252
|
+
this.idIndexDir = (0, import_node_path17.join)(dir, ID_INDEX_DIR_NAME);
|
|
10253
|
+
this.contentKeyIndexDir = (0, import_node_path17.join)(dir, CONTENT_KEY_INDEX_DIR_NAME);
|
|
10067
10254
|
this.resolveDisplayName = resolveDisplayName;
|
|
10068
10255
|
}
|
|
10069
10256
|
dir;
|
|
@@ -10074,10 +10261,10 @@ var NotificationStorage = class {
|
|
|
10074
10261
|
dateWriteChains = /* @__PURE__ */ new Map();
|
|
10075
10262
|
resolveDisplayName;
|
|
10076
10263
|
async init() {
|
|
10077
|
-
(0,
|
|
10078
|
-
(0,
|
|
10079
|
-
(0,
|
|
10080
|
-
(0,
|
|
10264
|
+
(0, import_node_fs21.mkdirSync)(this.dir, { recursive: true });
|
|
10265
|
+
(0, import_node_fs21.mkdirSync)(this.idIndexDir, { recursive: true });
|
|
10266
|
+
(0, import_node_fs21.rmSync)(this.contentKeyIndexDir, { recursive: true, force: true });
|
|
10267
|
+
(0, import_node_fs21.mkdirSync)(this.contentKeyIndexDir, { recursive: true });
|
|
10081
10268
|
}
|
|
10082
10269
|
async ingest(items) {
|
|
10083
10270
|
const result = {
|
|
@@ -10116,7 +10303,7 @@ var NotificationStorage = class {
|
|
|
10116
10303
|
return { kind: "invalid" };
|
|
10117
10304
|
}
|
|
10118
10305
|
const dateKey = this.formatDate(ts);
|
|
10119
|
-
const filePath = (0,
|
|
10306
|
+
const filePath = (0, import_node_path17.join)(this.dir, `${dateKey}.json`);
|
|
10120
10307
|
const normalizedId = typeof n.id === "string" ? n.id.trim() : "";
|
|
10121
10308
|
const entry = this.buildStoredNotification(n);
|
|
10122
10309
|
return this.withDateWriteLock(dateKey, async () => {
|
|
@@ -10133,7 +10320,7 @@ var NotificationStorage = class {
|
|
|
10133
10320
|
};
|
|
10134
10321
|
const arr = this.readStoredNotifications(filePath);
|
|
10135
10322
|
arr.push(storedEntry);
|
|
10136
|
-
(0,
|
|
10323
|
+
(0, import_node_fs21.writeFileSync)(filePath, JSON.stringify(arr, null, 2), "utf-8");
|
|
10137
10324
|
if (normalizedId) {
|
|
10138
10325
|
this.recordNotificationId(dateKey, normalizedId);
|
|
10139
10326
|
}
|
|
@@ -10167,7 +10354,7 @@ var NotificationStorage = class {
|
|
|
10167
10354
|
return `${year}-${month}-${day}`;
|
|
10168
10355
|
}
|
|
10169
10356
|
getIdIndexPath(dateKey) {
|
|
10170
|
-
return (0,
|
|
10357
|
+
return (0, import_node_path17.join)(this.idIndexDir, `${dateKey}.ids`);
|
|
10171
10358
|
}
|
|
10172
10359
|
getIdSet(dateKey) {
|
|
10173
10360
|
const cached = this.idCache.get(dateKey);
|
|
@@ -10176,8 +10363,8 @@ var NotificationStorage = class {
|
|
|
10176
10363
|
}
|
|
10177
10364
|
const idPath = this.getIdIndexPath(dateKey);
|
|
10178
10365
|
const ids = /* @__PURE__ */ new Set();
|
|
10179
|
-
if ((0,
|
|
10180
|
-
const lines = (0,
|
|
10366
|
+
if ((0, import_node_fs21.existsSync)(idPath)) {
|
|
10367
|
+
const lines = (0, import_node_fs21.readFileSync)(idPath, "utf-8").split(/\r?\n/);
|
|
10181
10368
|
for (const line of lines) {
|
|
10182
10369
|
const id = line.trim();
|
|
10183
10370
|
if (id) {
|
|
@@ -10192,7 +10379,7 @@ var NotificationStorage = class {
|
|
|
10192
10379
|
return this.getIdSet(dateKey).has(id);
|
|
10193
10380
|
}
|
|
10194
10381
|
getContentKeyIndexPath(dateKey) {
|
|
10195
|
-
return (0,
|
|
10382
|
+
return (0, import_node_path17.join)(this.contentKeyIndexDir, `${dateKey}.keys`);
|
|
10196
10383
|
}
|
|
10197
10384
|
getContentKeySet(dateKey, filePath) {
|
|
10198
10385
|
const cached = this.contentKeyCache.get(dateKey);
|
|
@@ -10201,16 +10388,16 @@ var NotificationStorage = class {
|
|
|
10201
10388
|
}
|
|
10202
10389
|
const keyPath = this.getContentKeyIndexPath(dateKey);
|
|
10203
10390
|
const keys = /* @__PURE__ */ new Set();
|
|
10204
|
-
if ((0,
|
|
10391
|
+
if ((0, import_node_fs21.existsSync)(filePath)) {
|
|
10205
10392
|
for (const item of this.readStoredNotifications(filePath)) {
|
|
10206
10393
|
keys.add(this.buildNotificationContentKey(item));
|
|
10207
10394
|
}
|
|
10208
10395
|
}
|
|
10209
10396
|
if (keys.size > 0) {
|
|
10210
|
-
(0,
|
|
10397
|
+
(0, import_node_fs21.writeFileSync)(keyPath, `${Array.from(keys).join("\n")}
|
|
10211
10398
|
`, "utf-8");
|
|
10212
|
-
} else if ((0,
|
|
10213
|
-
(0,
|
|
10399
|
+
} else if ((0, import_node_fs21.existsSync)(keyPath)) {
|
|
10400
|
+
(0, import_node_fs21.rmSync)(keyPath, { force: true });
|
|
10214
10401
|
}
|
|
10215
10402
|
this.contentKeyCache.set(dateKey, keys);
|
|
10216
10403
|
return keys;
|
|
@@ -10225,7 +10412,7 @@ var NotificationStorage = class {
|
|
|
10225
10412
|
if (ids.has(id)) {
|
|
10226
10413
|
return;
|
|
10227
10414
|
}
|
|
10228
|
-
(0,
|
|
10415
|
+
(0, import_node_fs21.appendFileSync)(this.getIdIndexPath(dateKey), `${id}
|
|
10229
10416
|
`, "utf-8");
|
|
10230
10417
|
ids.add(id);
|
|
10231
10418
|
}
|
|
@@ -10235,7 +10422,7 @@ var NotificationStorage = class {
|
|
|
10235
10422
|
if (keys.has(key)) {
|
|
10236
10423
|
return;
|
|
10237
10424
|
}
|
|
10238
|
-
(0,
|
|
10425
|
+
(0, import_node_fs21.appendFileSync)(this.getContentKeyIndexPath(dateKey), `${key}
|
|
10239
10426
|
`, "utf-8");
|
|
10240
10427
|
keys.add(key);
|
|
10241
10428
|
}
|
|
@@ -10243,11 +10430,11 @@ var NotificationStorage = class {
|
|
|
10243
10430
|
return (0, import_node_crypto2.createHash)("sha256").update(entry.appName).update("").update(entry.title).update("").update(entry.content).update("").update(entry.timestamp).digest("hex");
|
|
10244
10431
|
}
|
|
10245
10432
|
readStoredNotifications(filePath) {
|
|
10246
|
-
if (!(0,
|
|
10433
|
+
if (!(0, import_node_fs21.existsSync)(filePath)) {
|
|
10247
10434
|
return [];
|
|
10248
10435
|
}
|
|
10249
10436
|
try {
|
|
10250
|
-
const parsed = JSON.parse((0,
|
|
10437
|
+
const parsed = JSON.parse((0, import_node_fs21.readFileSync)(filePath, "utf-8"));
|
|
10251
10438
|
return Array.isArray(parsed) ? parsed : [];
|
|
10252
10439
|
} catch {
|
|
10253
10440
|
return [];
|
|
@@ -10287,14 +10474,14 @@ var NotificationStorage = class {
|
|
|
10287
10474
|
const dateFilePattern = /^(\d{4}-\d{2}-\d{2})\.(json|md)$/;
|
|
10288
10475
|
const dateDirPattern = /^\d{4}-\d{2}-\d{2}$/;
|
|
10289
10476
|
try {
|
|
10290
|
-
for (const entry of (0,
|
|
10477
|
+
for (const entry of (0, import_node_fs21.readdirSync)(this.dir, { withFileTypes: true })) {
|
|
10291
10478
|
if (entry.isFile()) {
|
|
10292
10479
|
const match = dateFilePattern.exec(entry.name);
|
|
10293
10480
|
if (match && match[1] < cutoffDate) {
|
|
10294
|
-
(0,
|
|
10481
|
+
(0, import_node_fs21.rmSync)((0, import_node_path17.join)(this.dir, entry.name), { force: true });
|
|
10295
10482
|
}
|
|
10296
10483
|
} else if (entry.isDirectory() && dateDirPattern.test(entry.name) && entry.name < cutoffDate) {
|
|
10297
|
-
(0,
|
|
10484
|
+
(0, import_node_fs21.rmSync)((0, import_node_path17.join)(this.dir, entry.name), { recursive: true, force: true });
|
|
10298
10485
|
}
|
|
10299
10486
|
}
|
|
10300
10487
|
} catch {
|
|
@@ -10303,11 +10490,11 @@ var NotificationStorage = class {
|
|
|
10303
10490
|
/** Remove expired .ids index files */
|
|
10304
10491
|
pruneIdIndex(cutoffDate) {
|
|
10305
10492
|
try {
|
|
10306
|
-
for (const entry of (0,
|
|
10493
|
+
for (const entry of (0, import_node_fs21.readdirSync)(this.idIndexDir, { withFileTypes: true })) {
|
|
10307
10494
|
if (!entry.isFile()) continue;
|
|
10308
10495
|
const match = /^(\d{4}-\d{2}-\d{2})\.ids$/.exec(entry.name);
|
|
10309
10496
|
if (match && match[1] < cutoffDate) {
|
|
10310
|
-
(0,
|
|
10497
|
+
(0, import_node_fs21.rmSync)((0, import_node_path17.join)(this.idIndexDir, entry.name), { force: true });
|
|
10311
10498
|
this.idCache.delete(match[1]);
|
|
10312
10499
|
}
|
|
10313
10500
|
}
|
|
@@ -10316,11 +10503,11 @@ var NotificationStorage = class {
|
|
|
10316
10503
|
}
|
|
10317
10504
|
pruneContentKeyIndex(cutoffDate) {
|
|
10318
10505
|
try {
|
|
10319
|
-
for (const entry of (0,
|
|
10506
|
+
for (const entry of (0, import_node_fs21.readdirSync)(this.contentKeyIndexDir, { withFileTypes: true })) {
|
|
10320
10507
|
if (!entry.isFile()) continue;
|
|
10321
10508
|
const match = /^(\d{4}-\d{2}-\d{2})\.keys$/.exec(entry.name);
|
|
10322
10509
|
if (match && match[1] < cutoffDate) {
|
|
10323
|
-
(0,
|
|
10510
|
+
(0, import_node_fs21.rmSync)((0, import_node_path17.join)(this.contentKeyIndexDir, entry.name), { force: true });
|
|
10324
10511
|
this.contentKeyCache.delete(match[1]);
|
|
10325
10512
|
}
|
|
10326
10513
|
}
|
|
@@ -10335,8 +10522,8 @@ var NotificationStorage = class {
|
|
|
10335
10522
|
};
|
|
10336
10523
|
|
|
10337
10524
|
// src/recording/storage.ts
|
|
10338
|
-
var
|
|
10339
|
-
var
|
|
10525
|
+
var import_node_fs22 = require("fs");
|
|
10526
|
+
var import_node_path18 = require("path");
|
|
10340
10527
|
|
|
10341
10528
|
// src/recording/state-machine.ts
|
|
10342
10529
|
var VALID_TRANSITIONS = /* @__PURE__ */ new Map([
|
|
@@ -10398,7 +10585,7 @@ function stripMarkdownFence(markdown) {
|
|
|
10398
10585
|
}
|
|
10399
10586
|
function deriveTitleFromTranscriptPath(transcriptFile, recordingId) {
|
|
10400
10587
|
if (!transcriptFile) return void 0;
|
|
10401
|
-
const name = (0,
|
|
10588
|
+
const name = (0, import_node_path18.basename)(transcriptFile, ".md");
|
|
10402
10589
|
const prefix = `${recordingId}_`;
|
|
10403
10590
|
if (name.startsWith(prefix)) {
|
|
10404
10591
|
const derived = name.slice(prefix.length).trim();
|
|
@@ -10426,22 +10613,22 @@ function extractTranscriptContent(markdown) {
|
|
|
10426
10613
|
return lines.join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
10427
10614
|
}
|
|
10428
10615
|
function resolveRecordingStorageDir(ctx, logger) {
|
|
10429
|
-
const stateRecDir = (0,
|
|
10616
|
+
const stateRecDir = (0, import_node_path18.join)(
|
|
10430
10617
|
ctx.stateDir,
|
|
10431
10618
|
"plugins",
|
|
10432
10619
|
"phone-notifications",
|
|
10433
10620
|
RECORDINGS_DIR
|
|
10434
10621
|
);
|
|
10435
10622
|
try {
|
|
10436
|
-
(0,
|
|
10623
|
+
(0, import_node_fs22.mkdirSync)(stateRecDir, { recursive: true });
|
|
10437
10624
|
logger.info(`\u5F55\u97F3\u5C06\u5199\u5165 stateDir \u8DEF\u5F84: ${stateRecDir}`);
|
|
10438
10625
|
return stateRecDir;
|
|
10439
10626
|
} catch {
|
|
10440
10627
|
}
|
|
10441
10628
|
if (ctx.workspaceDir) {
|
|
10442
|
-
const wsRecDir = (0,
|
|
10629
|
+
const wsRecDir = (0, import_node_path18.join)(ctx.workspaceDir, RECORDINGS_DIR);
|
|
10443
10630
|
try {
|
|
10444
|
-
(0,
|
|
10631
|
+
(0, import_node_fs22.mkdirSync)(wsRecDir, { recursive: true });
|
|
10445
10632
|
logger.warn(`stateDir \u4E0D\u53EF\u7528\uFF0C\u5F55\u97F3\u5DF2\u56DE\u9000\u5230 workspace \u8DEF\u5F84: ${wsRecDir}`);
|
|
10446
10633
|
return wsRecDir;
|
|
10447
10634
|
} catch {
|
|
@@ -10453,11 +10640,11 @@ var RecordingStorage = class {
|
|
|
10453
10640
|
constructor(dir, logger) {
|
|
10454
10641
|
this.logger = logger;
|
|
10455
10642
|
this.dir = dir;
|
|
10456
|
-
this.audioDir = (0,
|
|
10457
|
-
this.transcriptDataDir = (0,
|
|
10458
|
-
this.transcriptsDir = (0,
|
|
10459
|
-
this.summariesDir = (0,
|
|
10460
|
-
this.indexPath = (0,
|
|
10643
|
+
this.audioDir = (0, import_node_path18.join)(dir, AUDIO_DIR);
|
|
10644
|
+
this.transcriptDataDir = (0, import_node_path18.join)(dir, TRANSCRIPT_DATA_DIR);
|
|
10645
|
+
this.transcriptsDir = (0, import_node_path18.join)(dir, TRANSCRIPTS_DIR);
|
|
10646
|
+
this.summariesDir = (0, import_node_path18.join)(dir, SUMMARIES_DIR);
|
|
10647
|
+
this.indexPath = (0, import_node_path18.join)(dir, INDEX_FILE);
|
|
10461
10648
|
}
|
|
10462
10649
|
dir;
|
|
10463
10650
|
audioDir;
|
|
@@ -10468,10 +10655,10 @@ var RecordingStorage = class {
|
|
|
10468
10655
|
index = { recordings: [] };
|
|
10469
10656
|
/** 初始化目录结构并加载索引 */
|
|
10470
10657
|
async init() {
|
|
10471
|
-
(0,
|
|
10472
|
-
(0,
|
|
10473
|
-
(0,
|
|
10474
|
-
(0,
|
|
10658
|
+
(0, import_node_fs22.mkdirSync)(this.audioDir, { recursive: true });
|
|
10659
|
+
(0, import_node_fs22.mkdirSync)(this.transcriptDataDir, { recursive: true });
|
|
10660
|
+
(0, import_node_fs22.mkdirSync)(this.transcriptsDir, { recursive: true });
|
|
10661
|
+
(0, import_node_fs22.mkdirSync)(this.summariesDir, { recursive: true });
|
|
10475
10662
|
this.loadIndex();
|
|
10476
10663
|
this.logger.info(
|
|
10477
10664
|
`\u5F55\u97F3\u5B58\u50A8\u5DF2\u521D\u59CB\u5316: ${this.dir}\uFF08\u5171 ${this.index.recordings.length} \u6761\u8BB0\u5F55\uFF09`
|
|
@@ -10515,13 +10702,13 @@ var RecordingStorage = class {
|
|
|
10515
10702
|
return id;
|
|
10516
10703
|
}
|
|
10517
10704
|
if (existing.transcriptDataFile) {
|
|
10518
|
-
(0,
|
|
10705
|
+
(0, import_node_fs22.rmSync)((0, import_node_path18.join)(this.dir, existing.transcriptDataFile), { force: true });
|
|
10519
10706
|
}
|
|
10520
10707
|
if (existing.transcriptFile) {
|
|
10521
|
-
(0,
|
|
10708
|
+
(0, import_node_fs22.rmSync)((0, import_node_path18.join)(this.dir, existing.transcriptFile), { force: true });
|
|
10522
10709
|
}
|
|
10523
10710
|
if (existing.summaryFile) {
|
|
10524
|
-
(0,
|
|
10711
|
+
(0, import_node_fs22.rmSync)((0, import_node_path18.join)(this.dir, existing.summaryFile), { force: true });
|
|
10525
10712
|
}
|
|
10526
10713
|
existing.metadata = metadata;
|
|
10527
10714
|
existing.status = "syncing_openclaw";
|
|
@@ -10590,7 +10777,7 @@ var RecordingStorage = class {
|
|
|
10590
10777
|
if (!entry) return;
|
|
10591
10778
|
const nextTranscriptDataFile = `${TRANSCRIPT_DATA_DIR}/${filename}`;
|
|
10592
10779
|
if (entry.transcriptDataFile && entry.transcriptDataFile !== nextTranscriptDataFile) {
|
|
10593
|
-
(0,
|
|
10780
|
+
(0, import_node_fs22.rmSync)((0, import_node_path18.join)(this.dir, entry.transcriptDataFile), { force: true });
|
|
10594
10781
|
}
|
|
10595
10782
|
entry.transcriptDataFile = nextTranscriptDataFile;
|
|
10596
10783
|
entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -10604,7 +10791,7 @@ var RecordingStorage = class {
|
|
|
10604
10791
|
if (!entry) return;
|
|
10605
10792
|
const nextTranscriptFile = `${TRANSCRIPTS_DIR}/${filename}`;
|
|
10606
10793
|
if (entry.transcriptFile && entry.transcriptFile !== nextTranscriptFile) {
|
|
10607
|
-
(0,
|
|
10794
|
+
(0, import_node_fs22.rmSync)((0, import_node_path18.join)(this.dir, entry.transcriptFile), { force: true });
|
|
10608
10795
|
}
|
|
10609
10796
|
entry.transcriptFile = nextTranscriptFile;
|
|
10610
10797
|
entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -10618,7 +10805,7 @@ var RecordingStorage = class {
|
|
|
10618
10805
|
if (!entry) return;
|
|
10619
10806
|
const nextSummaryFile = `${SUMMARIES_DIR}/${filename}`;
|
|
10620
10807
|
if (entry.summaryFile && entry.summaryFile !== nextSummaryFile) {
|
|
10621
|
-
(0,
|
|
10808
|
+
(0, import_node_fs22.rmSync)((0, import_node_path18.join)(this.dir, entry.summaryFile), { force: true });
|
|
10622
10809
|
}
|
|
10623
10810
|
entry.summaryFile = nextSummaryFile;
|
|
10624
10811
|
entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -10726,24 +10913,24 @@ var RecordingStorage = class {
|
|
|
10726
10913
|
const entry = this.findById(recordingId);
|
|
10727
10914
|
if (!entry) return false;
|
|
10728
10915
|
if (entry.audioFile) {
|
|
10729
|
-
const audioPath = (0,
|
|
10730
|
-
(0,
|
|
10916
|
+
const audioPath = (0, import_node_path18.join)(this.dir, entry.audioFile);
|
|
10917
|
+
(0, import_node_fs22.rmSync)(audioPath, { force: true });
|
|
10731
10918
|
}
|
|
10732
10919
|
if (entry.srtFile) {
|
|
10733
|
-
const srtPath = (0,
|
|
10734
|
-
(0,
|
|
10920
|
+
const srtPath = (0, import_node_path18.join)(this.dir, entry.srtFile);
|
|
10921
|
+
(0, import_node_fs22.rmSync)(srtPath, { force: true });
|
|
10735
10922
|
}
|
|
10736
10923
|
if (entry.transcriptDataFile) {
|
|
10737
|
-
const transcriptDataPath = (0,
|
|
10738
|
-
(0,
|
|
10924
|
+
const transcriptDataPath = (0, import_node_path18.join)(this.dir, entry.transcriptDataFile);
|
|
10925
|
+
(0, import_node_fs22.rmSync)(transcriptDataPath, { force: true });
|
|
10739
10926
|
}
|
|
10740
10927
|
if (entry.transcriptFile) {
|
|
10741
|
-
const transcriptPath = (0,
|
|
10742
|
-
(0,
|
|
10928
|
+
const transcriptPath = (0, import_node_path18.join)(this.dir, entry.transcriptFile);
|
|
10929
|
+
(0, import_node_fs22.rmSync)(transcriptPath, { force: true });
|
|
10743
10930
|
}
|
|
10744
10931
|
if (entry.summaryFile) {
|
|
10745
|
-
const summaryPath = (0,
|
|
10746
|
-
(0,
|
|
10932
|
+
const summaryPath = (0, import_node_path18.join)(this.dir, entry.summaryFile);
|
|
10933
|
+
(0, import_node_fs22.rmSync)(summaryPath, { force: true });
|
|
10747
10934
|
}
|
|
10748
10935
|
if (opts?.localOnly) {
|
|
10749
10936
|
entry.audioFile = void 0;
|
|
@@ -10801,34 +10988,34 @@ var RecordingStorage = class {
|
|
|
10801
10988
|
* 获取音频文件的绝对路径。ossUrl 用于推断文件扩展名
|
|
10802
10989
|
*/
|
|
10803
10990
|
getAudioFilePath(recordingId, ossUrl) {
|
|
10804
|
-
return (0,
|
|
10991
|
+
return (0, import_node_path18.join)(this.audioDir, this.buildAudioFilename(recordingId, ossUrl));
|
|
10805
10992
|
}
|
|
10806
10993
|
/**
|
|
10807
10994
|
* 获取打点文件的绝对路径
|
|
10808
10995
|
*/
|
|
10809
10996
|
getSrtFilePath(recordingId) {
|
|
10810
|
-
return (0,
|
|
10997
|
+
return (0, import_node_path18.join)(this.audioDir, this.buildSrtFilename(recordingId));
|
|
10811
10998
|
}
|
|
10812
10999
|
/**
|
|
10813
11000
|
* 获取转写 JSON 文件的绝对路径
|
|
10814
11001
|
*/
|
|
10815
11002
|
getTranscriptDataFilePath(recordingId) {
|
|
10816
|
-
return (0,
|
|
11003
|
+
return (0, import_node_path18.join)(this.transcriptDataDir, this.buildTranscriptDataFilename(recordingId));
|
|
10817
11004
|
}
|
|
10818
11005
|
/**
|
|
10819
11006
|
* 获取摘要文件的绝对路径
|
|
10820
11007
|
*/
|
|
10821
11008
|
getSummaryFilePath(recordingId) {
|
|
10822
|
-
return (0,
|
|
11009
|
+
return (0, import_node_path18.join)(this.summariesDir, this.buildSummaryFilename(recordingId));
|
|
10823
11010
|
}
|
|
10824
11011
|
// ─── Persistence ───
|
|
10825
11012
|
loadIndex() {
|
|
10826
|
-
if (!(0,
|
|
11013
|
+
if (!(0, import_node_fs22.existsSync)(this.indexPath)) {
|
|
10827
11014
|
this.index = { recordings: [] };
|
|
10828
11015
|
return;
|
|
10829
11016
|
}
|
|
10830
11017
|
try {
|
|
10831
|
-
const raw = JSON.parse((0,
|
|
11018
|
+
const raw = JSON.parse((0, import_node_fs22.readFileSync)(this.indexPath, "utf-8"));
|
|
10832
11019
|
if (raw && Array.isArray(raw.recordings)) {
|
|
10833
11020
|
let needsRewrite = false;
|
|
10834
11021
|
const normalized = raw.recordings.filter((entry) => entry && typeof entry === "object").map((entry) => {
|
|
@@ -10866,8 +11053,8 @@ var RecordingStorage = class {
|
|
|
10866
11053
|
segments: []
|
|
10867
11054
|
});
|
|
10868
11055
|
const transcriptDataFilename = this.buildTranscriptDataFilename(compacted.id);
|
|
10869
|
-
(0,
|
|
10870
|
-
(0,
|
|
11056
|
+
(0, import_node_fs22.writeFileSync)(
|
|
11057
|
+
(0, import_node_path18.join)(this.transcriptDataDir, transcriptDataFilename),
|
|
10871
11058
|
JSON.stringify(transcriptDoc, null, 2),
|
|
10872
11059
|
"utf-8"
|
|
10873
11060
|
);
|
|
@@ -10879,8 +11066,8 @@ var RecordingStorage = class {
|
|
|
10879
11066
|
compacted.summaryFile = entry.summaryFile;
|
|
10880
11067
|
} else if (typeof entry.summary === "string" && entry.summary.trim()) {
|
|
10881
11068
|
const summaryFilename = this.buildSummaryFilename(entry.id);
|
|
10882
|
-
(0,
|
|
10883
|
-
(0,
|
|
11069
|
+
(0, import_node_fs22.writeFileSync)(
|
|
11070
|
+
(0, import_node_path18.join)(this.summariesDir, summaryFilename),
|
|
10884
11071
|
entry.summary.trim(),
|
|
10885
11072
|
"utf-8"
|
|
10886
11073
|
);
|
|
@@ -10890,8 +11077,8 @@ var RecordingStorage = class {
|
|
|
10890
11077
|
const summaryFromDocument = extractTranscriptSummaryFromDocument(transcriptDoc);
|
|
10891
11078
|
if (summaryFromDocument) {
|
|
10892
11079
|
const summaryFilename = this.buildSummaryFilename(entry.id);
|
|
10893
|
-
(0,
|
|
10894
|
-
(0,
|
|
11080
|
+
(0, import_node_fs22.writeFileSync)(
|
|
11081
|
+
(0, import_node_path18.join)(this.summariesDir, summaryFilename),
|
|
10895
11082
|
summaryFromDocument,
|
|
10896
11083
|
"utf-8"
|
|
10897
11084
|
);
|
|
@@ -10934,7 +11121,7 @@ var RecordingStorage = class {
|
|
|
10934
11121
|
}
|
|
10935
11122
|
readRelativeTextFile(relativePath) {
|
|
10936
11123
|
try {
|
|
10937
|
-
return (0,
|
|
11124
|
+
return (0, import_node_fs22.readFileSync)((0, import_node_path18.join)(this.dir, relativePath), "utf-8");
|
|
10938
11125
|
} catch {
|
|
10939
11126
|
return void 0;
|
|
10940
11127
|
}
|
|
@@ -10947,7 +11134,7 @@ var RecordingStorage = class {
|
|
|
10947
11134
|
return parseTranscriptDocument(raw);
|
|
10948
11135
|
}
|
|
10949
11136
|
saveIndex() {
|
|
10950
|
-
(0,
|
|
11137
|
+
(0, import_node_fs22.writeFileSync)(
|
|
10951
11138
|
this.indexPath,
|
|
10952
11139
|
JSON.stringify(this.index, null, 2),
|
|
10953
11140
|
"utf-8"
|
|
@@ -10961,8 +11148,8 @@ var RecordingStorage = class {
|
|
|
10961
11148
|
init_transcript_document();
|
|
10962
11149
|
|
|
10963
11150
|
// src/recording/downloader.ts
|
|
10964
|
-
var
|
|
10965
|
-
var
|
|
11151
|
+
var import_node_fs23 = require("fs");
|
|
11152
|
+
var import_node_path19 = require("path");
|
|
10966
11153
|
var import_promises2 = require("stream/promises");
|
|
10967
11154
|
var import_node_stream = require("stream");
|
|
10968
11155
|
var DEFAULT_TIMEOUT_MS2 = 5 * 60 * 1e3;
|
|
@@ -10972,7 +11159,7 @@ async function downloadFile(url, destPath, logger, options) {
|
|
|
10972
11159
|
const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
|
|
10973
11160
|
const maxRetries = options?.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
10974
11161
|
const retryBackoffMs = options?.retryBackoffMs ?? DEFAULT_RETRY_BACKOFF_MS;
|
|
10975
|
-
(0,
|
|
11162
|
+
(0, import_node_fs23.mkdirSync)((0, import_node_path19.dirname)(destPath), { recursive: true });
|
|
10976
11163
|
let lastError;
|
|
10977
11164
|
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
10978
11165
|
const startMs = Date.now();
|
|
@@ -10990,11 +11177,11 @@ async function downloadFile(url, destPath, logger, options) {
|
|
|
10990
11177
|
if (!res.body) {
|
|
10991
11178
|
throw new Error("\u54CD\u5E94\u4F53\u4E3A\u7A7A");
|
|
10992
11179
|
}
|
|
10993
|
-
const writeStream = (0,
|
|
11180
|
+
const writeStream = (0, import_node_fs23.createWriteStream)(destPath);
|
|
10994
11181
|
const readable = import_node_stream.Readable.fromWeb(res.body);
|
|
10995
11182
|
await (0, import_promises2.pipeline)(readable, writeStream);
|
|
10996
11183
|
const elapsed = Date.now() - startMs;
|
|
10997
|
-
const fileSize = (0,
|
|
11184
|
+
const fileSize = (0, import_node_fs23.existsSync)(destPath) ? (0, import_node_fs23.statSync)(destPath).size : 0;
|
|
10998
11185
|
logger.info(
|
|
10999
11186
|
`[downloader] \u4E0B\u8F7D\u5B8C\u6210: ${destPath} (${formatBytes(fileSize)}, ${elapsed}ms)`
|
|
11000
11187
|
);
|
|
@@ -11005,7 +11192,7 @@ async function downloadFile(url, destPath, logger, options) {
|
|
|
11005
11192
|
} catch (err2) {
|
|
11006
11193
|
lastError = err2?.message ?? String(err2);
|
|
11007
11194
|
try {
|
|
11008
|
-
if ((0,
|
|
11195
|
+
if ((0, import_node_fs23.existsSync)(destPath)) (0, import_node_fs23.unlinkSync)(destPath);
|
|
11009
11196
|
} catch {
|
|
11010
11197
|
}
|
|
11011
11198
|
const isAbort = err2?.name === "AbortError";
|
|
@@ -11321,13 +11508,13 @@ async function triggerTranscription(recordingId, storage, asrConfig, logger, opt
|
|
|
11321
11508
|
}
|
|
11322
11509
|
|
|
11323
11510
|
// src/tunnel/service.ts
|
|
11324
|
-
var
|
|
11325
|
-
var
|
|
11511
|
+
var import_node_fs28 = require("fs");
|
|
11512
|
+
var import_node_path24 = require("path");
|
|
11326
11513
|
init_credentials();
|
|
11327
11514
|
|
|
11328
11515
|
// src/tunnel/relay-client.ts
|
|
11329
|
-
var
|
|
11330
|
-
var
|
|
11516
|
+
var import_node_fs26 = require("fs");
|
|
11517
|
+
var import_node_path22 = require("path");
|
|
11331
11518
|
|
|
11332
11519
|
// node_modules/.pnpm/ws@8.19.0/node_modules/ws/wrapper.mjs
|
|
11333
11520
|
var import_stream = __toESM(require_stream(), 1);
|
|
@@ -11371,8 +11558,8 @@ var RelayClient = class {
|
|
|
11371
11558
|
lastDisconnectReason
|
|
11372
11559
|
};
|
|
11373
11560
|
try {
|
|
11374
|
-
(0,
|
|
11375
|
-
(0,
|
|
11561
|
+
(0, import_node_fs26.mkdirSync)((0, import_node_path22.dirname)(this.opts.statusFilePath), { recursive: true });
|
|
11562
|
+
(0, import_node_fs26.writeFileSync)(this.opts.statusFilePath, JSON.stringify(info, null, 2));
|
|
11376
11563
|
} catch {
|
|
11377
11564
|
}
|
|
11378
11565
|
}
|
|
@@ -11754,8 +11941,8 @@ init_host();
|
|
|
11754
11941
|
|
|
11755
11942
|
// src/tunnel/device-identity.ts
|
|
11756
11943
|
var import_node_crypto3 = __toESM(require("crypto"), 1);
|
|
11757
|
-
var
|
|
11758
|
-
var
|
|
11944
|
+
var import_node_fs27 = __toESM(require("fs"), 1);
|
|
11945
|
+
var import_node_path23 = __toESM(require("path"), 1);
|
|
11759
11946
|
init_host();
|
|
11760
11947
|
var ED25519_SPKI_PREFIX = Buffer.from("302a300506032b6570032100", "hex");
|
|
11761
11948
|
function base64UrlEncode(buf) {
|
|
@@ -11800,10 +11987,10 @@ function resolveClientStateDir(stateDir) {
|
|
|
11800
11987
|
return stateDir ?? resolveStateDir();
|
|
11801
11988
|
}
|
|
11802
11989
|
function ensureDir(filePath) {
|
|
11803
|
-
|
|
11990
|
+
import_node_fs27.default.mkdirSync(import_node_path23.default.dirname(filePath), { recursive: true });
|
|
11804
11991
|
}
|
|
11805
11992
|
function resolveIdentityPath(stateDir) {
|
|
11806
|
-
return
|
|
11993
|
+
return import_node_path23.default.join(stateDir, "identity", "device.json");
|
|
11807
11994
|
}
|
|
11808
11995
|
function normalizeDeviceAuthRole(role) {
|
|
11809
11996
|
return role.trim();
|
|
@@ -11819,12 +12006,12 @@ function normalizeDeviceAuthScopes(scopes) {
|
|
|
11819
12006
|
return [...out].sort();
|
|
11820
12007
|
}
|
|
11821
12008
|
function resolveDeviceAuthPath(stateDir) {
|
|
11822
|
-
return
|
|
12009
|
+
return import_node_path23.default.join(stateDir, "identity", "device-auth.json");
|
|
11823
12010
|
}
|
|
11824
12011
|
function readDeviceAuthStore(filePath) {
|
|
11825
12012
|
try {
|
|
11826
|
-
if (!
|
|
11827
|
-
const raw =
|
|
12013
|
+
if (!import_node_fs27.default.existsSync(filePath)) return null;
|
|
12014
|
+
const raw = import_node_fs27.default.readFileSync(filePath, "utf8");
|
|
11828
12015
|
const parsed = JSON.parse(raw);
|
|
11829
12016
|
if (parsed?.version !== 1 || typeof parsed.deviceId !== "string") return null;
|
|
11830
12017
|
if (!parsed.tokens || typeof parsed.tokens !== "object") return null;
|
|
@@ -11835,12 +12022,12 @@ function readDeviceAuthStore(filePath) {
|
|
|
11835
12022
|
}
|
|
11836
12023
|
function writeDeviceAuthStore(filePath, store) {
|
|
11837
12024
|
ensureDir(filePath);
|
|
11838
|
-
|
|
12025
|
+
import_node_fs27.default.writeFileSync(filePath, `${JSON.stringify(store, null, 2)}
|
|
11839
12026
|
`, {
|
|
11840
12027
|
mode: 384
|
|
11841
12028
|
});
|
|
11842
12029
|
try {
|
|
11843
|
-
|
|
12030
|
+
import_node_fs27.default.chmodSync(filePath, 384);
|
|
11844
12031
|
} catch {
|
|
11845
12032
|
}
|
|
11846
12033
|
}
|
|
@@ -11887,8 +12074,8 @@ function clearDeviceAuthToken(params) {
|
|
|
11887
12074
|
function loadOrCreateDeviceIdentity(stateDir) {
|
|
11888
12075
|
const filePath = resolveIdentityPath(stateDir);
|
|
11889
12076
|
try {
|
|
11890
|
-
if (
|
|
11891
|
-
const raw =
|
|
12077
|
+
if (import_node_fs27.default.existsSync(filePath)) {
|
|
12078
|
+
const raw = import_node_fs27.default.readFileSync(filePath, "utf8");
|
|
11892
12079
|
const parsed = JSON.parse(raw);
|
|
11893
12080
|
if (parsed?.version === 1 && typeof parsed.deviceId === "string" && typeof parsed.publicKeyPem === "string" && typeof parsed.privateKeyPem === "string") {
|
|
11894
12081
|
const derivedId = fingerprintPublicKey(parsed.publicKeyPem);
|
|
@@ -11909,14 +12096,14 @@ function loadOrCreateDeviceIdentity(stateDir) {
|
|
|
11909
12096
|
publicKeyPem,
|
|
11910
12097
|
privateKeyPem
|
|
11911
12098
|
};
|
|
11912
|
-
|
|
12099
|
+
import_node_fs27.default.mkdirSync(import_node_path23.default.dirname(filePath), { recursive: true });
|
|
11913
12100
|
const stored = {
|
|
11914
12101
|
version: 1,
|
|
11915
12102
|
...identity,
|
|
11916
12103
|
createdAtMs: Date.now()
|
|
11917
12104
|
};
|
|
11918
12105
|
ensureDir(filePath);
|
|
11919
|
-
|
|
12106
|
+
import_node_fs27.default.writeFileSync(filePath, `${JSON.stringify(stored, null, 2)}
|
|
11920
12107
|
`, {
|
|
11921
12108
|
mode: 384
|
|
11922
12109
|
});
|
|
@@ -12800,7 +12987,7 @@ function createTunnelService(opts) {
|
|
|
12800
12987
|
);
|
|
12801
12988
|
client.sendRaw(frame);
|
|
12802
12989
|
}
|
|
12803
|
-
function
|
|
12990
|
+
function isProcessAlive2(pid) {
|
|
12804
12991
|
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
12805
12992
|
if (pid === process.pid) return true;
|
|
12806
12993
|
try {
|
|
@@ -12812,7 +12999,7 @@ function createTunnelService(opts) {
|
|
|
12812
12999
|
}
|
|
12813
13000
|
function readLockOwner(filePath) {
|
|
12814
13001
|
try {
|
|
12815
|
-
const parsed = JSON.parse((0,
|
|
13002
|
+
const parsed = JSON.parse((0, import_node_fs28.readFileSync)(filePath, "utf-8"));
|
|
12816
13003
|
return typeof parsed.pid === "number" ? parsed.pid : null;
|
|
12817
13004
|
} catch {
|
|
12818
13005
|
return null;
|
|
@@ -12825,23 +13012,23 @@ function createTunnelService(opts) {
|
|
|
12825
13012
|
lockFd = null;
|
|
12826
13013
|
if (fd !== null) {
|
|
12827
13014
|
try {
|
|
12828
|
-
(0,
|
|
13015
|
+
(0, import_node_fs28.closeSync)(fd);
|
|
12829
13016
|
} catch {
|
|
12830
13017
|
}
|
|
12831
13018
|
}
|
|
12832
13019
|
if (filePath) {
|
|
12833
13020
|
try {
|
|
12834
|
-
(0,
|
|
13021
|
+
(0, import_node_fs28.unlinkSync)(filePath);
|
|
12835
13022
|
} catch {
|
|
12836
13023
|
}
|
|
12837
13024
|
}
|
|
12838
13025
|
}
|
|
12839
13026
|
function acquireLock(filePath) {
|
|
12840
|
-
(0,
|
|
13027
|
+
(0, import_node_fs28.mkdirSync)((0, import_node_path24.dirname)(filePath), { recursive: true });
|
|
12841
13028
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
12842
13029
|
try {
|
|
12843
|
-
const fd = (0,
|
|
12844
|
-
(0,
|
|
13030
|
+
const fd = (0, import_node_fs28.openSync)(filePath, "wx", 384);
|
|
13031
|
+
(0, import_node_fs28.writeFileSync)(
|
|
12845
13032
|
fd,
|
|
12846
13033
|
JSON.stringify({
|
|
12847
13034
|
pid: process.pid,
|
|
@@ -12860,12 +13047,12 @@ function createTunnelService(opts) {
|
|
|
12860
13047
|
return false;
|
|
12861
13048
|
}
|
|
12862
13049
|
const ownerPid = readLockOwner(filePath);
|
|
12863
|
-
if (ownerPid && !
|
|
13050
|
+
if (ownerPid && !isProcessAlive2(ownerPid)) {
|
|
12864
13051
|
opts.logger.warn(
|
|
12865
13052
|
`Relay tunnel: removing stale local lock owned by dead pid=${ownerPid}`
|
|
12866
13053
|
);
|
|
12867
13054
|
try {
|
|
12868
|
-
(0,
|
|
13055
|
+
(0, import_node_fs28.unlinkSync)(filePath);
|
|
12869
13056
|
} catch {
|
|
12870
13057
|
}
|
|
12871
13058
|
continue;
|
|
@@ -12910,12 +13097,12 @@ function createTunnelService(opts) {
|
|
|
12910
13097
|
return;
|
|
12911
13098
|
}
|
|
12912
13099
|
const { logger } = opts;
|
|
12913
|
-
const baseStateDir = (0,
|
|
13100
|
+
const baseStateDir = (0, import_node_path24.join)(ctx.stateDir, "plugins", "phone-notifications");
|
|
12914
13101
|
logger.info(
|
|
12915
13102
|
`Relay tunnel: starting (pid=${process.pid}, url=${opts.tunnelUrl}, heartbeat=${opts.heartbeatSec ?? DEFAULT_HEARTBEAT_SEC}s, backoff=${opts.reconnectBackoffMs ?? DEFAULT_RECONNECT_BACKOFF_MS}ms, gateway=${opts.gatewayBaseUrl}, hasGatewayToken=${!!opts.gatewayToken}, hasGatewayPwd=${!!opts.gatewayPassword})`
|
|
12916
13103
|
);
|
|
12917
|
-
const statusFilePath = (0,
|
|
12918
|
-
const lockPath = (0,
|
|
13104
|
+
const statusFilePath = (0, import_node_path24.join)(baseStateDir, "tunnel-status.json");
|
|
13105
|
+
const lockPath = (0, import_node_path24.join)(baseStateDir, "relay-tunnel.lock");
|
|
12919
13106
|
if (!acquireLock(lockPath)) {
|
|
12920
13107
|
return;
|
|
12921
13108
|
}
|
|
@@ -12980,25 +13167,6 @@ function createTunnelService(opts) {
|
|
|
12980
13167
|
|
|
12981
13168
|
// src/plugin/lifecycle.ts
|
|
12982
13169
|
init_env();
|
|
12983
|
-
|
|
12984
|
-
// src/plugin/shared.ts
|
|
12985
|
-
function readBody(req) {
|
|
12986
|
-
return new Promise((resolve, reject) => {
|
|
12987
|
-
const chunks = [];
|
|
12988
|
-
req.on("data", (chunk) => chunks.push(chunk));
|
|
12989
|
-
req.on("end", () => resolve(Buffer.concat(chunks).toString()));
|
|
12990
|
-
req.on("error", reject);
|
|
12991
|
-
});
|
|
12992
|
-
}
|
|
12993
|
-
function trimToUndefined2(value) {
|
|
12994
|
-
if (typeof value !== "string") {
|
|
12995
|
-
return void 0;
|
|
12996
|
-
}
|
|
12997
|
-
const trimmed = value.trim();
|
|
12998
|
-
return trimmed || void 0;
|
|
12999
|
-
}
|
|
13000
|
-
|
|
13001
|
-
// src/plugin/lifecycle.ts
|
|
13002
13170
|
function registerStorageLifecycle(deps) {
|
|
13003
13171
|
const {
|
|
13004
13172
|
api,
|
|
@@ -13055,7 +13223,7 @@ function readHostGatewayConfig(params) {
|
|
|
13055
13223
|
let configData;
|
|
13056
13224
|
if (configPath) {
|
|
13057
13225
|
try {
|
|
13058
|
-
configData = JSON.parse((0,
|
|
13226
|
+
configData = JSON.parse((0, import_node_fs29.readFileSync)(configPath, "utf-8"));
|
|
13059
13227
|
} catch (err2) {
|
|
13060
13228
|
if (err2?.code !== "ENOENT") {
|
|
13061
13229
|
params.logger.warn(
|
|
@@ -13732,7 +13900,7 @@ var index_default = {
|
|
|
13732
13900
|
let broadcastFn = null;
|
|
13733
13901
|
let autoUpdateLifecycle = null;
|
|
13734
13902
|
let tunnelService = null;
|
|
13735
|
-
const openclawDir = api
|
|
13903
|
+
const openclawDir = resolvePluginStateDir(api);
|
|
13736
13904
|
const logger = openclawDir ? new PluginFileLogger(api.logger, openclawDir) : createVersionAwareLogger(api.logger);
|
|
13737
13905
|
const lightRuleCtx = {
|
|
13738
13906
|
stateDir: openclawDir
|