@yoooclaw/phone-notifications 1.10.2 → 1.10.3
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
CHANGED
|
@@ -461,8 +461,8 @@ __export(whisper_local_exports, {
|
|
|
461
461
|
transcribeWithWhisperLocal: () => transcribeWithWhisperLocal
|
|
462
462
|
});
|
|
463
463
|
function detectEnvironment(logger) {
|
|
464
|
-
const os2 = (0,
|
|
465
|
-
const cpuArch = (0,
|
|
464
|
+
const os2 = (0, import_node_os4.platform)();
|
|
465
|
+
const cpuArch = (0, import_node_os4.arch)();
|
|
466
466
|
const isAppleSilicon = os2 === "darwin" && cpuArch === "arm64";
|
|
467
467
|
const hasCuda = detectCuda(logger);
|
|
468
468
|
let recommendedBackend;
|
|
@@ -500,20 +500,20 @@ function selectModelByMemory(availableGB, isAppleSilicon = false) {
|
|
|
500
500
|
return "tiny";
|
|
501
501
|
}
|
|
502
502
|
function resolveModelsDir(dataDir) {
|
|
503
|
-
const dir = (0,
|
|
504
|
-
(0,
|
|
503
|
+
const dir = (0, import_node_path21.join)(dataDir, WHISPER_MODELS_DIR);
|
|
504
|
+
(0, import_node_fs25.mkdirSync)(dir, { recursive: true });
|
|
505
505
|
return dir;
|
|
506
506
|
}
|
|
507
507
|
function resolveBinDir(dataDir) {
|
|
508
|
-
const dir = (0,
|
|
509
|
-
(0,
|
|
508
|
+
const dir = (0, import_node_path21.join)(dataDir, WHISPER_BIN_DIR);
|
|
509
|
+
(0, import_node_fs25.mkdirSync)(dir, { recursive: true });
|
|
510
510
|
return dir;
|
|
511
511
|
}
|
|
512
512
|
function isModelDownloaded(modelsDir, modelSize) {
|
|
513
|
-
const modelPath = (0,
|
|
514
|
-
if (!(0,
|
|
513
|
+
const modelPath = (0, import_node_path21.join)(modelsDir, MODEL_FILENAMES[modelSize]);
|
|
514
|
+
if (!(0, import_node_fs25.existsSync)(modelPath)) return false;
|
|
515
515
|
try {
|
|
516
|
-
const stat = (0,
|
|
516
|
+
const stat = (0, import_node_fs25.statSync)(modelPath);
|
|
517
517
|
const expectedSize = MODEL_DISK_SIZES[modelSize];
|
|
518
518
|
return stat.size >= expectedSize * 0.8;
|
|
519
519
|
} catch {
|
|
@@ -522,7 +522,7 @@ function isModelDownloaded(modelsDir, modelSize) {
|
|
|
522
522
|
}
|
|
523
523
|
async function downloadModel(modelsDir, modelSize, logger, modelSource, mirrorUrl) {
|
|
524
524
|
const filename = MODEL_FILENAMES[modelSize];
|
|
525
|
-
const modelPath = (0,
|
|
525
|
+
const modelPath = (0, import_node_path21.join)(modelsDir, filename);
|
|
526
526
|
if (isModelDownloaded(modelsDir, modelSize)) {
|
|
527
527
|
logger.info(`[whisper-local] \u6A21\u578B\u5DF2\u5B58\u5728\uFF0C\u8DF3\u8FC7\u4E0B\u8F7D: ${filename}`);
|
|
528
528
|
return { ok: true, modelPath };
|
|
@@ -588,7 +588,7 @@ async function probeUrl(url, logger) {
|
|
|
588
588
|
async function downloadFromUrl(url, modelPath, logger) {
|
|
589
589
|
const tmpPath = `${modelPath}.downloading`;
|
|
590
590
|
try {
|
|
591
|
-
(0,
|
|
591
|
+
(0, import_node_fs25.mkdirSync)((0, import_node_path21.dirname)(modelPath), { recursive: true });
|
|
592
592
|
const controller = new AbortController();
|
|
593
593
|
const timer = setTimeout(() => controller.abort(), 30 * 60 * 1e3);
|
|
594
594
|
try {
|
|
@@ -604,7 +604,7 @@ async function downloadFromUrl(url, modelPath, logger) {
|
|
|
604
604
|
return { ok: false, modelPath, error: "\u6A21\u578B\u4E0B\u8F7D\u5931\u8D25: \u54CD\u5E94\u4F53\u4E3A\u7A7A" };
|
|
605
605
|
}
|
|
606
606
|
const contentLength = Number(res.headers.get("content-length") ?? 0);
|
|
607
|
-
const writeStream = (0,
|
|
607
|
+
const writeStream = (0, import_node_fs25.createWriteStream)(tmpPath);
|
|
608
608
|
const readable = import_node_stream2.Readable.fromWeb(res.body);
|
|
609
609
|
let downloaded = 0;
|
|
610
610
|
let lastLogPercent = 0;
|
|
@@ -624,16 +624,16 @@ async function downloadFromUrl(url, modelPath, logger) {
|
|
|
624
624
|
} finally {
|
|
625
625
|
clearTimeout(timer);
|
|
626
626
|
}
|
|
627
|
-
const { renameSync } = await import("fs");
|
|
628
|
-
|
|
629
|
-
const fileSize = (0,
|
|
627
|
+
const { renameSync: renameSync2 } = await import("fs");
|
|
628
|
+
renameSync2(tmpPath, modelPath);
|
|
629
|
+
const fileSize = (0, import_node_fs25.statSync)(modelPath).size;
|
|
630
630
|
logger.info(
|
|
631
|
-
`[whisper-local] \u6A21\u578B\u4E0B\u8F7D\u5B8C\u6210: ${(0,
|
|
631
|
+
`[whisper-local] \u6A21\u578B\u4E0B\u8F7D\u5B8C\u6210: ${(0, import_node_path21.basename)(modelPath)} (${formatBytes2(fileSize)})`
|
|
632
632
|
);
|
|
633
633
|
return { ok: true, modelPath };
|
|
634
634
|
} catch (err) {
|
|
635
635
|
try {
|
|
636
|
-
if ((0,
|
|
636
|
+
if ((0, import_node_fs25.existsSync)(tmpPath)) (0, import_node_fs25.unlinkSync)(tmpPath);
|
|
637
637
|
} catch {
|
|
638
638
|
}
|
|
639
639
|
const msg = err?.name === "AbortError" ? "\u6A21\u578B\u4E0B\u8F7D\u8D85\u65F6\uFF0830 \u5206\u949F\uFF09" : err?.message ?? String(err);
|
|
@@ -643,18 +643,18 @@ async function downloadFromUrl(url, modelPath, logger) {
|
|
|
643
643
|
}
|
|
644
644
|
function findWhisperBinary(dataDir, logger) {
|
|
645
645
|
const binDir = resolveBinDir(dataDir);
|
|
646
|
-
const binNames = (0,
|
|
646
|
+
const binNames = (0, import_node_os4.platform)() === "win32" ? ["whisper-cli.exe", "whisper.exe", "main.exe"] : ["whisper-cli", "whisper", "main"];
|
|
647
647
|
for (const name of binNames) {
|
|
648
|
-
const binPath = (0,
|
|
649
|
-
if ((0,
|
|
648
|
+
const binPath = (0, import_node_path21.join)(binDir, name);
|
|
649
|
+
if ((0, import_node_fs25.existsSync)(binPath)) {
|
|
650
650
|
logger.info(`[whisper-local] \u627E\u5230\u672C\u5730\u4E8C\u8FDB\u5236: ${binPath}`);
|
|
651
651
|
return binPath;
|
|
652
652
|
}
|
|
653
653
|
}
|
|
654
|
-
const pathNames = (0,
|
|
654
|
+
const pathNames = (0, import_node_os4.platform)() === "win32" ? ["whisper-cli", "whisper-cpp", "whisper"] : ["whisper-cli", "whisper-cpp", "whisper"];
|
|
655
655
|
for (const name of pathNames) {
|
|
656
656
|
try {
|
|
657
|
-
const cmd = (0,
|
|
657
|
+
const cmd = (0, import_node_os4.platform)() === "win32" ? "where" : "which";
|
|
658
658
|
const result = (0, import_node_child_process2.execSync)(`${cmd} ${name}`, { encoding: "utf-8", stdio: "pipe" }).trim();
|
|
659
659
|
if (result) {
|
|
660
660
|
logger.info(`[whisper-local] \u627E\u5230\u7CFB\u7EDF PATH \u4E8C\u8FDB\u5236: ${result}`);
|
|
@@ -697,7 +697,7 @@ async function transcribeWithWhisperLocal(audioFilePath, localConfig, dataDir, l
|
|
|
697
697
|
return { ok: false, error: `\u6A21\u578B\u4E0B\u8F7D\u5931\u8D25: ${downloadResult.error}` };
|
|
698
698
|
}
|
|
699
699
|
}
|
|
700
|
-
const modelPath = (0,
|
|
700
|
+
const modelPath = (0, import_node_path21.join)(modelsDir, MODEL_FILENAMES[modelSize]);
|
|
701
701
|
let inputPath = audioFilePath;
|
|
702
702
|
let tmpWavPath = null;
|
|
703
703
|
const actualFmt = detectAudioFormat(audioFilePath);
|
|
@@ -749,10 +749,10 @@ async function transcribeWithWhisperLocal(audioFilePath, localConfig, dataDir, l
|
|
|
749
749
|
logger.info(`[whisper-local] \u8F6C\u5199\u8017\u65F6: ${Math.round(elapsed / 1e3)}s`);
|
|
750
750
|
const jsonPath = inputPath + ".json";
|
|
751
751
|
let jsonContent;
|
|
752
|
-
if ((0,
|
|
753
|
-
jsonContent = (0,
|
|
752
|
+
if ((0, import_node_fs25.existsSync)(jsonPath)) {
|
|
753
|
+
jsonContent = (0, import_node_fs25.readFileSync)(jsonPath, "utf-8");
|
|
754
754
|
try {
|
|
755
|
-
(0,
|
|
755
|
+
(0, import_node_fs25.unlinkSync)(jsonPath);
|
|
756
756
|
} catch {
|
|
757
757
|
}
|
|
758
758
|
} else {
|
|
@@ -785,7 +785,7 @@ function detectCuda(logger) {
|
|
|
785
785
|
return true;
|
|
786
786
|
} catch {
|
|
787
787
|
}
|
|
788
|
-
if ((0,
|
|
788
|
+
if ((0, import_node_os4.platform)() === "linux") {
|
|
789
789
|
try {
|
|
790
790
|
const ldconfig = (0, import_node_child_process2.execSync)("ldconfig -p 2>/dev/null | grep libcudart", {
|
|
791
791
|
encoding: "utf-8",
|
|
@@ -816,24 +816,24 @@ function getAvailableMemoryGB(backend, logger) {
|
|
|
816
816
|
logger.warn("[whisper-local] \u65E0\u6CD5\u83B7\u53D6 GPU VRAM\uFF0C\u4F7F\u7528\u7CFB\u7EDF RAM \u4EE3\u66FF");
|
|
817
817
|
}
|
|
818
818
|
}
|
|
819
|
-
const totalGB = (0,
|
|
820
|
-
const freeGB = (0,
|
|
819
|
+
const totalGB = (0, import_node_os4.totalmem)() / (1024 * 1024 * 1024);
|
|
820
|
+
const freeGB = (0, import_node_os4.freemem)() / (1024 * 1024 * 1024);
|
|
821
821
|
return Math.max(freeGB, totalGB * 0.6);
|
|
822
822
|
}
|
|
823
823
|
function getPhysicalCoreCount() {
|
|
824
|
-
const cpuList = (0,
|
|
824
|
+
const cpuList = (0, import_node_os4.cpus)();
|
|
825
825
|
if (cpuList.length === 0) return 4;
|
|
826
|
-
if ((0,
|
|
826
|
+
if ((0, import_node_os4.platform)() === "darwin" && (0, import_node_os4.arch)() === "arm64") {
|
|
827
827
|
return cpuList.length;
|
|
828
828
|
}
|
|
829
829
|
return Math.max(1, Math.floor(cpuList.length / 2));
|
|
830
830
|
}
|
|
831
831
|
function detectAudioFormat(filePath) {
|
|
832
832
|
try {
|
|
833
|
-
const fd = (0,
|
|
833
|
+
const fd = (0, import_node_fs25.openSync)(filePath, "r");
|
|
834
834
|
const buf = Buffer.alloc(12);
|
|
835
|
-
(0,
|
|
836
|
-
(0,
|
|
835
|
+
(0, import_node_fs25.readSync)(fd, buf, 0, 12, 0);
|
|
836
|
+
(0, import_node_fs25.closeSync)(fd);
|
|
837
837
|
const header = buf.toString("ascii", 0, 4);
|
|
838
838
|
const header8 = buf.toString("ascii", 0, 8);
|
|
839
839
|
if (header === "RIFF" && buf.toString("ascii", 8, 12) === "WAVE") return ".wav";
|
|
@@ -868,7 +868,7 @@ function convertToWav(inputPath, outputPath, actualFmt, logger) {
|
|
|
868
868
|
timeout: 12e4,
|
|
869
869
|
stdio: ["pipe", "pipe", "pipe"]
|
|
870
870
|
});
|
|
871
|
-
if (ffmpegResult.status === 0 && (0,
|
|
871
|
+
if (ffmpegResult.status === 0 && (0, import_node_fs25.existsSync)(outputPath)) {
|
|
872
872
|
logger.info(`[whisper-local] ffmpeg \u8F6C\u6362\u5B8C\u6210: ${outputPath}`);
|
|
873
873
|
return { ok: true };
|
|
874
874
|
}
|
|
@@ -881,7 +881,7 @@ function convertToWav(inputPath, outputPath, actualFmt, logger) {
|
|
|
881
881
|
["--rate", "16000", "--mono", inputPath, outputPath],
|
|
882
882
|
{ encoding: "utf-8", timeout: 12e4, stdio: ["pipe", "pipe", "pipe"] }
|
|
883
883
|
);
|
|
884
|
-
if (opusResult.status === 0 && (0,
|
|
884
|
+
if (opusResult.status === 0 && (0, import_node_fs25.existsSync)(outputPath)) {
|
|
885
885
|
logger.info(`[whisper-local] opusdec \u8F6C\u6362\u5B8C\u6210: ${outputPath}`);
|
|
886
886
|
return { ok: true };
|
|
887
887
|
}
|
|
@@ -895,7 +895,7 @@ function convertToWav(inputPath, outputPath, actualFmt, logger) {
|
|
|
895
895
|
if (detectedExt && !inputPath.endsWith(detectedExt)) {
|
|
896
896
|
tmpCopy = inputPath + ".detected" + detectedExt;
|
|
897
897
|
try {
|
|
898
|
-
(0,
|
|
898
|
+
(0, import_node_fs25.copyFileSync)(inputPath, tmpCopy);
|
|
899
899
|
actualInputPath = tmpCopy;
|
|
900
900
|
logger.info(
|
|
901
901
|
`[whisper-local] \u68C0\u6D4B\u5230\u5B9E\u9645\u683C\u5F0F ${detectedExt}\uFF0C\u4E34\u65F6\u91CD\u547D\u540D`
|
|
@@ -919,22 +919,22 @@ function convertToWav(inputPath, outputPath, actualFmt, logger) {
|
|
|
919
919
|
timeout: 12e4,
|
|
920
920
|
stdio: ["pipe", "pipe", "pipe"]
|
|
921
921
|
});
|
|
922
|
-
if (tmpCopy && (0,
|
|
922
|
+
if (tmpCopy && (0, import_node_fs25.existsSync)(tmpCopy)) {
|
|
923
923
|
try {
|
|
924
|
-
(0,
|
|
924
|
+
(0, import_node_fs25.unlinkSync)(tmpCopy);
|
|
925
925
|
} catch {
|
|
926
926
|
}
|
|
927
927
|
}
|
|
928
|
-
if (afResult.status === 0 && (0,
|
|
928
|
+
if (afResult.status === 0 && (0, import_node_fs25.existsSync)(outputPath)) {
|
|
929
929
|
logger.info(`[whisper-local] afconvert \u8F6C\u6362\u5B8C\u6210: ${outputPath}`);
|
|
930
930
|
return { ok: true };
|
|
931
931
|
}
|
|
932
932
|
const stderr = afResult.stderr?.slice(0, 200) ?? "";
|
|
933
933
|
return { ok: false, error: `afconvert \u8F6C\u6362\u5931\u8D25 (exit ${afResult.status}): ${stderr}` };
|
|
934
934
|
} catch (err) {
|
|
935
|
-
if (tmpCopy && (0,
|
|
935
|
+
if (tmpCopy && (0, import_node_fs25.existsSync)(tmpCopy)) {
|
|
936
936
|
try {
|
|
937
|
-
(0,
|
|
937
|
+
(0, import_node_fs25.unlinkSync)(tmpCopy);
|
|
938
938
|
} catch {
|
|
939
939
|
}
|
|
940
940
|
}
|
|
@@ -945,9 +945,9 @@ function convertToWav(inputPath, outputPath, actualFmt, logger) {
|
|
|
945
945
|
return { ok: false, error: `\u65E0\u6CD5\u5C06\u97F3\u9891\u8F6C\u6362\u4E3A WAV \u683C\u5F0F\u3002${fmtHint}` };
|
|
946
946
|
}
|
|
947
947
|
function cleanupTmpWav(path2) {
|
|
948
|
-
if (path2 && (0,
|
|
948
|
+
if (path2 && (0, import_node_fs25.existsSync)(path2)) {
|
|
949
949
|
try {
|
|
950
|
-
(0,
|
|
950
|
+
(0, import_node_fs25.unlinkSync)(path2);
|
|
951
951
|
} catch {
|
|
952
952
|
}
|
|
953
953
|
}
|
|
@@ -1033,16 +1033,16 @@ function formatBytes2(bytes) {
|
|
|
1033
1033
|
if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
1034
1034
|
return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)}GB`;
|
|
1035
1035
|
}
|
|
1036
|
-
var import_node_child_process2,
|
|
1036
|
+
var import_node_child_process2, import_node_fs25, import_node_path21, 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;
|
|
1037
1037
|
var init_whisper_local = __esm({
|
|
1038
1038
|
"src/recording/whisper-local.ts"() {
|
|
1039
1039
|
"use strict";
|
|
1040
1040
|
import_node_child_process2 = require("child_process");
|
|
1041
|
-
|
|
1042
|
-
|
|
1041
|
+
import_node_fs25 = require("fs");
|
|
1042
|
+
import_node_path21 = require("path");
|
|
1043
1043
|
import_promises3 = require("stream/promises");
|
|
1044
1044
|
import_node_stream2 = require("stream");
|
|
1045
|
-
|
|
1045
|
+
import_node_os4 = require("os");
|
|
1046
1046
|
WHISPER_MODELS_DIR = "whisper-models";
|
|
1047
1047
|
WHISPER_BIN_DIR = "whisper-bin";
|
|
1048
1048
|
HF_MODEL_URL_TEMPLATE = "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-{model}.bin";
|
|
@@ -1194,7 +1194,7 @@ async function initializeAsr(config, dataDir, logger) {
|
|
|
1194
1194
|
}
|
|
1195
1195
|
}
|
|
1196
1196
|
async function transcribeAudio(audioFilePath, config, logger, options = {}) {
|
|
1197
|
-
if (!(0,
|
|
1197
|
+
if (!(0, import_node_fs26.existsSync)(audioFilePath)) {
|
|
1198
1198
|
return { ok: false, error: `\u97F3\u9891\u6587\u4EF6\u4E0D\u5B58\u5728: ${audioFilePath}` };
|
|
1199
1199
|
}
|
|
1200
1200
|
logger.info(
|
|
@@ -1310,7 +1310,7 @@ async function runTranscriptionWorkflow(params) {
|
|
|
1310
1310
|
return { ok: false, error: result.error };
|
|
1311
1311
|
}
|
|
1312
1312
|
const title = normalizeOptionalText2(result.summary) ? normalizeOptionalText2(result.summary) : extractSummary(result.text ?? "");
|
|
1313
|
-
const summary = normalizeOptionalText2(result.summaryText)
|
|
1313
|
+
const summary = normalizeOptionalText2(result.summaryText);
|
|
1314
1314
|
result.summary = title;
|
|
1315
1315
|
const transcriptData = buildTranscriptDocument({
|
|
1316
1316
|
recordingId,
|
|
@@ -1338,8 +1338,8 @@ async function runTranscriptionWorkflow(params) {
|
|
|
1338
1338
|
createdAt
|
|
1339
1339
|
);
|
|
1340
1340
|
const transcriptDataFilename = buildTranscriptDataFilename(recordingId);
|
|
1341
|
-
const transcriptDataPath = (0,
|
|
1342
|
-
(0,
|
|
1341
|
+
const transcriptDataPath = (0, import_node_path22.join)(transcriptDataDir, transcriptDataFilename);
|
|
1342
|
+
(0, import_node_fs26.writeFileSync)(
|
|
1343
1343
|
transcriptDataPath,
|
|
1344
1344
|
JSON.stringify(transcriptData, null, 2),
|
|
1345
1345
|
"utf-8"
|
|
@@ -1347,13 +1347,16 @@ async function runTranscriptionWorkflow(params) {
|
|
|
1347
1347
|
logger.info(`[asr] \u8F6C\u5199 JSON \u5DF2\u5199\u5165: ${transcriptDataPath}`);
|
|
1348
1348
|
const safeSummary = title.replace(/[/\\:*?"<>|]/g, "").trim().slice(0, 20);
|
|
1349
1349
|
const filename = safeSummary ? `${recordingId}_${safeSummary}.md` : `${recordingId}.md`;
|
|
1350
|
-
const filePath = (0,
|
|
1351
|
-
(0,
|
|
1350
|
+
const filePath = (0, import_node_path22.join)(transcriptsDir, filename);
|
|
1351
|
+
(0, import_node_fs26.writeFileSync)(filePath, markdown, "utf-8");
|
|
1352
1352
|
logger.info(`[asr] \u8F6C\u5199\u6587\u672C\u5DF2\u5199\u5165: ${filePath}`);
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1353
|
+
let summaryFilename;
|
|
1354
|
+
if (summary) {
|
|
1355
|
+
summaryFilename = `${recordingId}.md`;
|
|
1356
|
+
const summaryFilePath = (0, import_node_path22.join)(summariesDir, summaryFilename);
|
|
1357
|
+
(0, import_node_fs26.writeFileSync)(summaryFilePath, summary, "utf-8");
|
|
1358
|
+
logger.info(`[asr] \u6458\u8981\u6587\u672C\u5DF2\u5199\u5165: ${summaryFilePath}`);
|
|
1359
|
+
}
|
|
1357
1360
|
return {
|
|
1358
1361
|
ok: true,
|
|
1359
1362
|
transcriptFilename: filename,
|
|
@@ -1436,7 +1439,7 @@ async function transcribeWithModelProxy(audioOssUrl, apiConfig, logger) {
|
|
|
1436
1439
|
}
|
|
1437
1440
|
async function transcribeWithWhisperLocal2(audioFilePath, config, logger) {
|
|
1438
1441
|
const { transcribeWithWhisperLocal: runLocal } = await Promise.resolve().then(() => (init_whisper_local(), whisper_local_exports));
|
|
1439
|
-
const dataDir = process.env.OPENCLAW_STATE_DIR ?? process.env.QCLAW_STATE_DIR ?? (0,
|
|
1442
|
+
const dataDir = process.env.OPENCLAW_STATE_DIR ?? process.env.QCLAW_STATE_DIR ?? (0, import_node_path22.join)(audioFilePath, "..", "..", "..");
|
|
1440
1443
|
const localConfig = config.local ?? {};
|
|
1441
1444
|
const result = await runLocal(
|
|
1442
1445
|
audioFilePath,
|
|
@@ -1590,8 +1593,8 @@ function buildLongRecordingSuccessResult(taskId, requestId, data, logger) {
|
|
|
1590
1593
|
ok: true,
|
|
1591
1594
|
text,
|
|
1592
1595
|
segments: listResult.segments,
|
|
1593
|
-
summary: title
|
|
1594
|
-
summaryText
|
|
1596
|
+
summary: title,
|
|
1597
|
+
summaryText,
|
|
1595
1598
|
category,
|
|
1596
1599
|
sourceInfo: {
|
|
1597
1600
|
provider: "model-proxy",
|
|
@@ -1711,15 +1714,6 @@ function stringifyForLog(value, maxLength = 500) {
|
|
|
1711
1714
|
async function sleep2(ms) {
|
|
1712
1715
|
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
1713
1716
|
}
|
|
1714
|
-
function extractTranscriptSummary(text) {
|
|
1715
|
-
const normalized = text.replace(/\s+/g, " ").trim();
|
|
1716
|
-
if (!normalized) {
|
|
1717
|
-
return "";
|
|
1718
|
-
}
|
|
1719
|
-
const sentence = normalized.split(/[。!?!?]/).map((part) => part.trim()).find((part) => part.length > 0);
|
|
1720
|
-
const candidate = sentence || normalized;
|
|
1721
|
-
return candidate.length <= 120 ? candidate : `${candidate.slice(0, 117).trimEnd()}...`;
|
|
1722
|
-
}
|
|
1723
1717
|
function formatTimestamp(ms) {
|
|
1724
1718
|
const totalSeconds = Math.floor(ms / 1e3);
|
|
1725
1719
|
const minutes = Math.floor(totalSeconds / 60);
|
|
@@ -1748,12 +1742,12 @@ function formatTranscriptSegmentText(segment) {
|
|
|
1748
1742
|
}
|
|
1749
1743
|
return text;
|
|
1750
1744
|
}
|
|
1751
|
-
var
|
|
1745
|
+
var import_node_fs26, import_node_path22, DEFAULT_LONG_RECORDING_POLL_INTERVAL_MS, DEFAULT_LONG_RECORDING_MAX_POLL_ATTEMPTS, LONG_RECORDING_RUNNING_STATUSES, LONG_RECORDING_TERMINAL_FAILURE_STATUSES;
|
|
1752
1746
|
var init_asr = __esm({
|
|
1753
1747
|
"src/recording/asr.ts"() {
|
|
1754
1748
|
"use strict";
|
|
1755
|
-
|
|
1756
|
-
|
|
1749
|
+
import_node_fs26 = require("fs");
|
|
1750
|
+
import_node_path22 = require("path");
|
|
1757
1751
|
init_credentials();
|
|
1758
1752
|
init_env();
|
|
1759
1753
|
init_transcript_document();
|
|
@@ -5398,7 +5392,7 @@ function readBuildInjectedVersion() {
|
|
|
5398
5392
|
if (false) {
|
|
5399
5393
|
return void 0;
|
|
5400
5394
|
}
|
|
5401
|
-
const version = "1.10.
|
|
5395
|
+
const version = "1.10.3".trim();
|
|
5402
5396
|
return version || void 0;
|
|
5403
5397
|
}
|
|
5404
5398
|
function readPluginVersionFromPackageJson() {
|
|
@@ -7201,8 +7195,48 @@ function resolveUpdateChannel(params) {
|
|
|
7201
7195
|
return params.envName === "development" ? "beta" : "latest";
|
|
7202
7196
|
}
|
|
7203
7197
|
|
|
7198
|
+
// src/update/index.ts
|
|
7199
|
+
var import_node_path9 = require("path");
|
|
7200
|
+
|
|
7204
7201
|
// src/update/checker.ts
|
|
7205
|
-
|
|
7202
|
+
function parseSemver(v) {
|
|
7203
|
+
const [main, pre = null] = v.split("-", 2);
|
|
7204
|
+
const [major = 0, minor = 0, patch = 0] = main.split(".").map(Number);
|
|
7205
|
+
return { major, minor, patch, pre: pre ?? null };
|
|
7206
|
+
}
|
|
7207
|
+
function comparePreRelease(a, b) {
|
|
7208
|
+
const aParts = a.split(".");
|
|
7209
|
+
const bParts = b.split(".");
|
|
7210
|
+
for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {
|
|
7211
|
+
const ap = aParts[i] ?? "";
|
|
7212
|
+
const bp = bParts[i] ?? "";
|
|
7213
|
+
const an = Number(ap);
|
|
7214
|
+
const bn = Number(bp);
|
|
7215
|
+
let diff;
|
|
7216
|
+
if (!Number.isNaN(an) && !Number.isNaN(bn)) {
|
|
7217
|
+
diff = an - bn;
|
|
7218
|
+
} else if (ap < bp) {
|
|
7219
|
+
diff = -1;
|
|
7220
|
+
} else if (ap > bp) {
|
|
7221
|
+
diff = 1;
|
|
7222
|
+
} else {
|
|
7223
|
+
diff = 0;
|
|
7224
|
+
}
|
|
7225
|
+
if (diff !== 0) return diff;
|
|
7226
|
+
}
|
|
7227
|
+
return 0;
|
|
7228
|
+
}
|
|
7229
|
+
function isNewerVersion(candidate, current) {
|
|
7230
|
+
const a = parseSemver(candidate);
|
|
7231
|
+
const b = parseSemver(current);
|
|
7232
|
+
if (a.major !== b.major) return a.major > b.major;
|
|
7233
|
+
if (a.minor !== b.minor) return a.minor > b.minor;
|
|
7234
|
+
if (a.patch !== b.patch) return a.patch > b.patch;
|
|
7235
|
+
if (a.pre === null) return b.pre !== null;
|
|
7236
|
+
if (b.pre === null) return false;
|
|
7237
|
+
return comparePreRelease(a.pre, b.pre) > 0;
|
|
7238
|
+
}
|
|
7239
|
+
var CDN_BASE_URL = "https://artifact.yoooclaw.com/plugin";
|
|
7206
7240
|
var NPM_BASE_URL = "https://registry.npmjs.org/@yoooclaw/phone-notifications";
|
|
7207
7241
|
var FETCH_TIMEOUT_MS = 5e3;
|
|
7208
7242
|
var UpdateChecker = class {
|
|
@@ -7231,6 +7265,7 @@ var UpdateChecker = class {
|
|
|
7231
7265
|
if (!latest || latest === PLUGIN_VERSION) return;
|
|
7232
7266
|
if (latest === this.notifiedVersion) return;
|
|
7233
7267
|
if (PLUGIN_VERSION.includes("-") && this.channel !== "beta") return;
|
|
7268
|
+
if (!isNewerVersion(latest, PLUGIN_VERSION)) return;
|
|
7234
7269
|
this.notifiedVersion = latest;
|
|
7235
7270
|
this.logger.info(`\u53D1\u73B0\u65B0\u7248\u672C: ${PLUGIN_VERSION} \u2192 ${latest}`);
|
|
7236
7271
|
this.onUpdateFound({ current: PLUGIN_VERSION, latest });
|
|
@@ -7263,36 +7298,109 @@ var UpdateChecker = class {
|
|
|
7263
7298
|
};
|
|
7264
7299
|
|
|
7265
7300
|
// src/update/executor.ts
|
|
7301
|
+
var import_node_fs9 = require("fs");
|
|
7302
|
+
var import_node_path8 = require("path");
|
|
7303
|
+
var import_node_os = require("os");
|
|
7266
7304
|
var VERSION_PATTERN = /^\d+\.\d+\.\d+(-[\w.]+)?$/;
|
|
7267
|
-
|
|
7305
|
+
var BASE_URL = "https://artifact.yoooclaw.com/plugin";
|
|
7306
|
+
async function executeUpdate(version, runCommand, logger, targetDir, updateConfigRecord2) {
|
|
7268
7307
|
if (!VERSION_PATTERN.test(version)) {
|
|
7269
7308
|
return { success: false, message: `\u975E\u6CD5\u7248\u672C\u53F7: ${version}` };
|
|
7270
7309
|
}
|
|
7271
|
-
const
|
|
7272
|
-
|
|
7273
|
-
|
|
7274
|
-
|
|
7275
|
-
|
|
7276
|
-
|
|
7277
|
-
logger.info(`\u6267\u884C\u66F4\u65B0: ${argv.join(" ")}`);
|
|
7310
|
+
const tgzUrl = `${BASE_URL}/v${version}/yoooclaw-phone-notifications-${version}.tgz`;
|
|
7311
|
+
logger.info(`\u6267\u884C\u66F4\u65B0: ${tgzUrl} \u2192 ${targetDir}`);
|
|
7312
|
+
const workDir = (0, import_node_fs9.mkdtempSync)((0, import_node_path8.join)((0, import_node_os.tmpdir)(), ".openclaw-plugin-update-"));
|
|
7313
|
+
const tgzPath = (0, import_node_path8.join)(workDir, "plugin.tgz");
|
|
7314
|
+
const stagingDir = (0, import_node_path8.join)(workDir, "staged");
|
|
7315
|
+
let backupDir = null;
|
|
7278
7316
|
try {
|
|
7279
|
-
|
|
7280
|
-
|
|
7281
|
-
|
|
7282
|
-
|
|
7283
|
-
|
|
7317
|
+
logger.info("\u4E0B\u8F7D\u63D2\u4EF6\u5305...");
|
|
7318
|
+
const response = await fetch(tgzUrl, { signal: AbortSignal.timeout(6e4) });
|
|
7319
|
+
if (!response.ok) {
|
|
7320
|
+
return { success: false, message: `\u4E0B\u8F7D\u5931\u8D25 (HTTP ${response.status}): ${tgzUrl}` };
|
|
7321
|
+
}
|
|
7322
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
7323
|
+
(0, import_node_fs9.writeFileSync)(tgzPath, buffer);
|
|
7324
|
+
logger.info(`\u4E0B\u8F7D\u5B8C\u6210 (${buffer.length} bytes)`);
|
|
7325
|
+
(0, import_node_fs9.mkdirSync)(stagingDir, { recursive: true });
|
|
7326
|
+
const tarResult = await runCommand(
|
|
7327
|
+
["tar", "-xzf", tgzPath, "-C", stagingDir, "--strip-components=1"],
|
|
7328
|
+
{ timeoutMs: 3e4 }
|
|
7329
|
+
);
|
|
7330
|
+
if (tarResult.code !== 0) {
|
|
7331
|
+
const err = tarResult.stderr || tarResult.stdout || "unknown error";
|
|
7332
|
+
return { success: false, message: `\u89E3\u538B\u5931\u8D25: ${err}` };
|
|
7284
7333
|
}
|
|
7285
|
-
|
|
7286
|
-
|
|
7287
|
-
|
|
7334
|
+
(0, import_node_fs9.mkdirSync)((0, import_node_path8.dirname)(targetDir), { recursive: true });
|
|
7335
|
+
try {
|
|
7336
|
+
backupDir = `${targetDir}.bak.${Date.now()}`;
|
|
7337
|
+
(0, import_node_fs9.renameSync)(targetDir, backupDir);
|
|
7338
|
+
} catch {
|
|
7339
|
+
backupDir = null;
|
|
7340
|
+
}
|
|
7341
|
+
(0, import_node_fs9.renameSync)(stagingDir, targetDir);
|
|
7342
|
+
try {
|
|
7343
|
+
await updateConfigRecord2(version, tgzUrl);
|
|
7344
|
+
} catch (err) {
|
|
7345
|
+
logger.warn(`\u914D\u7F6E\u8BB0\u5F55\u66F4\u65B0\u5931\u8D25\uFF08\u63D2\u4EF6\u6587\u4EF6\u5DF2\u5C31\u4F4D\uFF09: ${String(err)}`);
|
|
7346
|
+
}
|
|
7347
|
+
if (backupDir) {
|
|
7348
|
+
try {
|
|
7349
|
+
(0, import_node_fs9.rmSync)(backupDir, { force: true, recursive: true });
|
|
7350
|
+
} catch {
|
|
7351
|
+
}
|
|
7352
|
+
}
|
|
7353
|
+
const msg = `\u5DF2\u66F4\u65B0\u5230 ${version}\uFF0C\u8BF7\u91CD\u542F gateway \u751F\u6548`;
|
|
7354
|
+
logger.info(msg);
|
|
7355
|
+
return { success: true, message: msg };
|
|
7288
7356
|
} catch (err) {
|
|
7289
|
-
|
|
7357
|
+
if (backupDir) {
|
|
7358
|
+
try {
|
|
7359
|
+
(0, import_node_fs9.rmSync)(targetDir, { force: true, recursive: true });
|
|
7360
|
+
(0, import_node_fs9.renameSync)(backupDir, targetDir);
|
|
7361
|
+
logger.info("\u5DF2\u56DE\u6EDA\u5230\u4E4B\u524D\u7248\u672C");
|
|
7362
|
+
} catch (rollbackErr) {
|
|
7363
|
+
logger.error(`\u56DE\u6EDA\u5931\u8D25: ${String(rollbackErr)}`);
|
|
7364
|
+
}
|
|
7365
|
+
}
|
|
7366
|
+
const errMsg = `\u66F4\u65B0\u6267\u884C\u5F02\u5E38: ${String(err)}`;
|
|
7290
7367
|
logger.error(errMsg);
|
|
7291
7368
|
return { success: false, message: errMsg };
|
|
7369
|
+
} finally {
|
|
7370
|
+
try {
|
|
7371
|
+
(0, import_node_fs9.rmSync)(workDir, { force: true, recursive: true });
|
|
7372
|
+
} catch {
|
|
7373
|
+
}
|
|
7292
7374
|
}
|
|
7293
7375
|
}
|
|
7294
7376
|
|
|
7295
7377
|
// src/update/index.ts
|
|
7378
|
+
var PLUGIN_ID = "phone-notifications";
|
|
7379
|
+
function resolveTargetDir(api) {
|
|
7380
|
+
try {
|
|
7381
|
+
const cfg = api.runtime.config?.loadConfig?.();
|
|
7382
|
+
const installPath = cfg?.plugins?.installs?.[PLUGIN_ID]?.installPath;
|
|
7383
|
+
if (installPath) return installPath;
|
|
7384
|
+
} catch {
|
|
7385
|
+
}
|
|
7386
|
+
return (0, import_node_path9.join)(api.runtime.state.resolveStateDir(), "extensions", PLUGIN_ID);
|
|
7387
|
+
}
|
|
7388
|
+
async function updateConfigRecord(api, version, targetDir, tgzUrl) {
|
|
7389
|
+
const configApi = api.runtime.config;
|
|
7390
|
+
if (!configApi) return;
|
|
7391
|
+
const cfg = configApi.loadConfig();
|
|
7392
|
+
if (!cfg.plugins) cfg.plugins = {};
|
|
7393
|
+
if (!cfg.plugins.installs) cfg.plugins.installs = {};
|
|
7394
|
+
cfg.plugins.installs[PLUGIN_ID] = {
|
|
7395
|
+
...cfg.plugins.installs[PLUGIN_ID],
|
|
7396
|
+
source: "archive",
|
|
7397
|
+
sourcePath: tgzUrl,
|
|
7398
|
+
installPath: targetDir,
|
|
7399
|
+
version,
|
|
7400
|
+
installedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
7401
|
+
};
|
|
7402
|
+
await configApi.writeConfigFile(cfg);
|
|
7403
|
+
}
|
|
7296
7404
|
function registerAutoUpdate(api, logger, config, getBroadcast, rememberBroadcast, externalUpdateNotifier) {
|
|
7297
7405
|
if (config.enabled === false) {
|
|
7298
7406
|
logger.info("\u81EA\u52A8\u66F4\u65B0\u5DF2\u7981\u7528 (autoUpdate.enabled = false)");
|
|
@@ -7338,10 +7446,13 @@ function registerAutoUpdate(api, logger, config, getBroadcast, rememberBroadcast
|
|
|
7338
7446
|
},
|
|
7339
7447
|
async execute(_toolCallId, params) {
|
|
7340
7448
|
const { version } = params;
|
|
7449
|
+
const targetDir = resolveTargetDir(api);
|
|
7341
7450
|
const result = await executeUpdate(
|
|
7342
7451
|
version,
|
|
7343
7452
|
api.runtime.system.runCommandWithTimeout,
|
|
7344
|
-
logger
|
|
7453
|
+
logger,
|
|
7454
|
+
targetDir,
|
|
7455
|
+
(v, url) => updateConfigRecord(api, v, targetDir, url)
|
|
7345
7456
|
);
|
|
7346
7457
|
if (result.success) {
|
|
7347
7458
|
pendingUpdate = null;
|
|
@@ -7363,10 +7474,13 @@ function registerAutoUpdate(api, logger, config, getBroadcast, rememberBroadcast
|
|
|
7363
7474
|
});
|
|
7364
7475
|
return;
|
|
7365
7476
|
}
|
|
7477
|
+
const targetDir = resolveTargetDir(api);
|
|
7366
7478
|
const result = await executeUpdate(
|
|
7367
7479
|
version,
|
|
7368
7480
|
api.runtime.system.runCommandWithTimeout,
|
|
7369
|
-
logger
|
|
7481
|
+
logger,
|
|
7482
|
+
targetDir,
|
|
7483
|
+
(v, url) => updateConfigRecord(api, v, targetDir, url)
|
|
7370
7484
|
);
|
|
7371
7485
|
if (result.success) {
|
|
7372
7486
|
pendingUpdate = null;
|
|
@@ -7457,10 +7571,10 @@ function registerAutoUpdateLifecycle(deps) {
|
|
|
7457
7571
|
}
|
|
7458
7572
|
|
|
7459
7573
|
// src/plugin/cli.ts
|
|
7460
|
-
var
|
|
7574
|
+
var import_node_path17 = require("path");
|
|
7461
7575
|
|
|
7462
7576
|
// src/cli/auth.ts
|
|
7463
|
-
var
|
|
7577
|
+
var import_node_fs10 = require("fs");
|
|
7464
7578
|
init_credentials();
|
|
7465
7579
|
function registerAuthCli(program) {
|
|
7466
7580
|
const auth = program.command("auth").description("\u7528\u6237\u8BA4\u8BC1\u7BA1\u7406");
|
|
@@ -7496,12 +7610,12 @@ function registerAuthCli(program) {
|
|
|
7496
7610
|
});
|
|
7497
7611
|
auth.command("clear").description("\u6E05\u9664\u5DF2\u4FDD\u5B58\u7684\u8BA4\u8BC1\u4FE1\u606F").action(() => {
|
|
7498
7612
|
const path2 = credentialsPath();
|
|
7499
|
-
if ((0,
|
|
7613
|
+
if ((0, import_node_fs10.existsSync)(path2)) {
|
|
7500
7614
|
const creds = readCredentials();
|
|
7501
7615
|
delete creds.apiKey;
|
|
7502
7616
|
delete creds.token;
|
|
7503
7617
|
if (Object.keys(creds).length === 0) {
|
|
7504
|
-
(0,
|
|
7618
|
+
(0, import_node_fs10.rmSync)(path2, { force: true });
|
|
7505
7619
|
} else {
|
|
7506
7620
|
writeCredentials(creds);
|
|
7507
7621
|
}
|
|
@@ -7633,23 +7747,23 @@ function registerNtfStats(ntf, ctx) {
|
|
|
7633
7747
|
}
|
|
7634
7748
|
|
|
7635
7749
|
// src/cli/ntf-sync.ts
|
|
7636
|
-
var
|
|
7637
|
-
var
|
|
7750
|
+
var import_node_fs11 = require("fs");
|
|
7751
|
+
var import_node_path10 = require("path");
|
|
7638
7752
|
var SYNC_FETCH_LIMIT = 300;
|
|
7639
7753
|
function checkpointPath(dir) {
|
|
7640
|
-
return (0,
|
|
7754
|
+
return (0, import_node_path10.join)(dir, ".checkpoint.json");
|
|
7641
7755
|
}
|
|
7642
7756
|
function readCheckpoint(dir) {
|
|
7643
7757
|
const p = checkpointPath(dir);
|
|
7644
|
-
if (!(0,
|
|
7758
|
+
if (!(0, import_node_fs11.existsSync)(p)) return {};
|
|
7645
7759
|
try {
|
|
7646
|
-
return JSON.parse((0,
|
|
7760
|
+
return JSON.parse((0, import_node_fs11.readFileSync)(p, "utf-8"));
|
|
7647
7761
|
} catch {
|
|
7648
7762
|
return {};
|
|
7649
7763
|
}
|
|
7650
7764
|
}
|
|
7651
7765
|
function writeCheckpoint(dir, data) {
|
|
7652
|
-
(0,
|
|
7766
|
+
(0, import_node_fs11.writeFileSync)(checkpointPath(dir), JSON.stringify(data, null, 2), "utf-8");
|
|
7653
7767
|
}
|
|
7654
7768
|
function registerNtfSync(ntf, ctx) {
|
|
7655
7769
|
const sync = ntf.command("sync").description("\u540C\u6B65\u901A\u77E5\u5230\u8BB0\u5FC6\u7CFB\u7EDF");
|
|
@@ -7742,24 +7856,24 @@ function registerNtfSync(ntf, ctx) {
|
|
|
7742
7856
|
}
|
|
7743
7857
|
|
|
7744
7858
|
// src/cli/ntf-monitor.ts
|
|
7745
|
-
var
|
|
7746
|
-
var
|
|
7859
|
+
var import_node_fs12 = require("fs");
|
|
7860
|
+
var import_node_path11 = require("path");
|
|
7747
7861
|
function tasksDir2(ctx) {
|
|
7748
7862
|
const base = ctx.workspaceDir || ctx.stateDir;
|
|
7749
7863
|
if (!base) throw new Error("workspaceDir and stateDir both unavailable");
|
|
7750
|
-
return (0,
|
|
7864
|
+
return (0, import_node_path11.join)(base, "tasks");
|
|
7751
7865
|
}
|
|
7752
7866
|
function readMeta2(taskDir) {
|
|
7753
|
-
const metaPath = (0,
|
|
7754
|
-
if (!(0,
|
|
7867
|
+
const metaPath = (0, import_node_path11.join)(taskDir, "meta.json");
|
|
7868
|
+
if (!(0, import_node_fs12.existsSync)(metaPath)) return null;
|
|
7755
7869
|
try {
|
|
7756
|
-
return JSON.parse((0,
|
|
7870
|
+
return JSON.parse((0, import_node_fs12.readFileSync)(metaPath, "utf-8"));
|
|
7757
7871
|
} catch {
|
|
7758
7872
|
return null;
|
|
7759
7873
|
}
|
|
7760
7874
|
}
|
|
7761
7875
|
function writeMeta2(taskDir, meta) {
|
|
7762
|
-
(0,
|
|
7876
|
+
(0, import_node_fs12.writeFileSync)((0, import_node_path11.join)(taskDir, "meta.json"), JSON.stringify(meta, null, 2), "utf-8");
|
|
7763
7877
|
}
|
|
7764
7878
|
function generateReadme(name, description) {
|
|
7765
7879
|
return `# Monitor Task: ${name}
|
|
@@ -7778,27 +7892,27 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
7778
7892
|
const monitor = ntf.command("monitor").description("\u901A\u77E5\u76D1\u63A7\u4EFB\u52A1\u7BA1\u7406");
|
|
7779
7893
|
monitor.command("list").description("\u5217\u51FA\u6240\u6709\u76D1\u63A7\u4EFB\u52A1").action(() => {
|
|
7780
7894
|
const dir = tasksDir2(ctx);
|
|
7781
|
-
if (!(0,
|
|
7895
|
+
if (!(0, import_node_fs12.existsSync)(dir)) {
|
|
7782
7896
|
output({ ok: true, tasks: [] });
|
|
7783
7897
|
return;
|
|
7784
7898
|
}
|
|
7785
7899
|
const tasks = [];
|
|
7786
|
-
for (const entry of (0,
|
|
7900
|
+
for (const entry of (0, import_node_fs12.readdirSync)(dir, { withFileTypes: true })) {
|
|
7787
7901
|
if (!entry.isDirectory()) continue;
|
|
7788
|
-
const meta = readMeta2((0,
|
|
7902
|
+
const meta = readMeta2((0, import_node_path11.join)(dir, entry.name));
|
|
7789
7903
|
if (meta) tasks.push(meta);
|
|
7790
7904
|
}
|
|
7791
7905
|
output({ ok: true, tasks });
|
|
7792
7906
|
});
|
|
7793
7907
|
monitor.command("show <name>").description("\u67E5\u770B\u76D1\u63A7\u4EFB\u52A1\u8BE6\u60C5").action((name) => {
|
|
7794
|
-
const taskDir = (0,
|
|
7908
|
+
const taskDir = (0, import_node_path11.join)(tasksDir2(ctx), name);
|
|
7795
7909
|
const meta = readMeta2(taskDir);
|
|
7796
7910
|
if (!meta) exitError("NOT_FOUND", `\u76D1\u63A7\u4EFB\u52A1 '${name}' \u4E0D\u5B58\u5728`);
|
|
7797
|
-
const checkpointPath2 = (0,
|
|
7911
|
+
const checkpointPath2 = (0, import_node_path11.join)(taskDir, "checkpoint.json");
|
|
7798
7912
|
let checkpoint = {};
|
|
7799
|
-
if ((0,
|
|
7913
|
+
if ((0, import_node_fs12.existsSync)(checkpointPath2)) {
|
|
7800
7914
|
try {
|
|
7801
|
-
checkpoint = JSON.parse((0,
|
|
7915
|
+
checkpoint = JSON.parse((0, import_node_fs12.readFileSync)(checkpointPath2, "utf-8"));
|
|
7802
7916
|
} catch {
|
|
7803
7917
|
}
|
|
7804
7918
|
}
|
|
@@ -7813,8 +7927,8 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
7813
7927
|
monitor.command("create <name>").description("\u521B\u5EFA\u76D1\u63A7\u4EFB\u52A1").requiredOption("--description <text>", "\u4EFB\u52A1\u63CF\u8FF0").requiredOption("--match-rules <json>", "\u5339\u914D\u89C4\u5219 JSON").requiredOption("--schedule <cron>", "cron \u8868\u8FBE\u5F0F").action(
|
|
7814
7928
|
(name, opts) => {
|
|
7815
7929
|
const dir = tasksDir2(ctx);
|
|
7816
|
-
const taskDir = (0,
|
|
7817
|
-
if ((0,
|
|
7930
|
+
const taskDir = (0, import_node_path11.join)(dir, name);
|
|
7931
|
+
if ((0, import_node_fs12.existsSync)(taskDir)) {
|
|
7818
7932
|
exitError("ALREADY_EXISTS", `\u76D1\u63A7\u4EFB\u52A1 '${name}' \u5DF2\u5B58\u5728`);
|
|
7819
7933
|
}
|
|
7820
7934
|
let matchRules;
|
|
@@ -7826,7 +7940,7 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
7826
7940
|
"match-rules \u5FC5\u987B\u662F\u5408\u6CD5\u7684 JSON"
|
|
7827
7941
|
);
|
|
7828
7942
|
}
|
|
7829
|
-
(0,
|
|
7943
|
+
(0, import_node_fs12.mkdirSync)(taskDir, { recursive: true });
|
|
7830
7944
|
const meta = {
|
|
7831
7945
|
name,
|
|
7832
7946
|
description: opts.description,
|
|
@@ -7836,13 +7950,13 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
7836
7950
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
7837
7951
|
};
|
|
7838
7952
|
writeMeta2(taskDir, meta);
|
|
7839
|
-
(0,
|
|
7840
|
-
(0,
|
|
7953
|
+
(0, import_node_fs12.writeFileSync)(
|
|
7954
|
+
(0, import_node_path11.join)(taskDir, "fetch.py"),
|
|
7841
7955
|
generateFetchPy(name, matchRules),
|
|
7842
7956
|
"utf-8"
|
|
7843
7957
|
);
|
|
7844
|
-
(0,
|
|
7845
|
-
(0,
|
|
7958
|
+
(0, import_node_fs12.writeFileSync)(
|
|
7959
|
+
(0, import_node_path11.join)(taskDir, "README.md"),
|
|
7846
7960
|
generateReadme(name, opts.description),
|
|
7847
7961
|
"utf-8"
|
|
7848
7962
|
);
|
|
@@ -7870,8 +7984,8 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
7870
7984
|
}
|
|
7871
7985
|
);
|
|
7872
7986
|
monitor.command("delete <name>").description("\u5220\u9664\u76D1\u63A7\u4EFB\u52A1").option("--yes", "\u8DF3\u8FC7\u786E\u8BA4").action((name, opts) => {
|
|
7873
|
-
const taskDir = (0,
|
|
7874
|
-
if (!(0,
|
|
7987
|
+
const taskDir = (0, import_node_path11.join)(tasksDir2(ctx), name);
|
|
7988
|
+
if (!(0, import_node_fs12.existsSync)(taskDir)) {
|
|
7875
7989
|
exitError("NOT_FOUND", `\u76D1\u63A7\u4EFB\u52A1 '${name}' \u4E0D\u5B58\u5728`);
|
|
7876
7990
|
}
|
|
7877
7991
|
if (!opts.yes) {
|
|
@@ -7884,7 +7998,7 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
7884
7998
|
});
|
|
7885
7999
|
process.exit(1);
|
|
7886
8000
|
}
|
|
7887
|
-
(0,
|
|
8001
|
+
(0, import_node_fs12.rmSync)(taskDir, { recursive: true, force: true });
|
|
7888
8002
|
output({
|
|
7889
8003
|
ok: true,
|
|
7890
8004
|
name,
|
|
@@ -7896,7 +8010,7 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
7896
8010
|
});
|
|
7897
8011
|
});
|
|
7898
8012
|
monitor.command("enable <name>").description("\u542F\u7528\u76D1\u63A7\u4EFB\u52A1").action((name) => {
|
|
7899
|
-
const taskDir = (0,
|
|
8013
|
+
const taskDir = (0, import_node_path11.join)(tasksDir2(ctx), name);
|
|
7900
8014
|
const meta = readMeta2(taskDir);
|
|
7901
8015
|
if (!meta) exitError("NOT_FOUND", `\u76D1\u63A7\u4EFB\u52A1 '${name}' \u4E0D\u5B58\u5728`);
|
|
7902
8016
|
meta.enabled = true;
|
|
@@ -7904,7 +8018,7 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
7904
8018
|
output({ ok: true, name, enabled: true });
|
|
7905
8019
|
});
|
|
7906
8020
|
monitor.command("disable <name>").description("\u6682\u505C\u76D1\u63A7\u4EFB\u52A1").action((name) => {
|
|
7907
|
-
const taskDir = (0,
|
|
8021
|
+
const taskDir = (0, import_node_path11.join)(tasksDir2(ctx), name);
|
|
7908
8022
|
const meta = readMeta2(taskDir);
|
|
7909
8023
|
if (!meta) exitError("NOT_FOUND", `\u76D1\u63A7\u4EFB\u52A1 '${name}' \u4E0D\u5B58\u5728`);
|
|
7910
8024
|
meta.enabled = false;
|
|
@@ -8213,9 +8327,9 @@ function registerLightSend(light) {
|
|
|
8213
8327
|
}
|
|
8214
8328
|
|
|
8215
8329
|
// src/cli/light-setup-tools.ts
|
|
8216
|
-
var
|
|
8217
|
-
var
|
|
8218
|
-
var
|
|
8330
|
+
var import_node_fs13 = require("fs");
|
|
8331
|
+
var import_node_os2 = require("os");
|
|
8332
|
+
var import_node_path12 = require("path");
|
|
8219
8333
|
function isObject(value) {
|
|
8220
8334
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
8221
8335
|
}
|
|
@@ -8229,7 +8343,7 @@ function ensureArray(obj, key) {
|
|
|
8229
8343
|
function resolveConfigPath2() {
|
|
8230
8344
|
const fromEnv = process.env.OPENCLAW_CONFIG_PATH?.trim();
|
|
8231
8345
|
if (fromEnv) return fromEnv;
|
|
8232
|
-
return (0,
|
|
8346
|
+
return (0, import_node_path12.join)((0, import_node_os2.homedir)(), ".openclaw", "openclaw.json");
|
|
8233
8347
|
}
|
|
8234
8348
|
function upsertLightControlAlsoAllow(cfg) {
|
|
8235
8349
|
if (!isObject(cfg.tools)) cfg.tools = {};
|
|
@@ -8258,12 +8372,12 @@ function upsertLightControlAlsoAllow(cfg) {
|
|
|
8258
8372
|
function registerLightSetupTools(light) {
|
|
8259
8373
|
light.command("setup").description("\u81EA\u52A8\u653E\u884C light_control\uFF08\u5199\u5165 tools.alsoAllow \u4E0E agents.main.tools.alsoAllow\uFF09").action(() => {
|
|
8260
8374
|
const configPath = resolveConfigPath2();
|
|
8261
|
-
if (!(0,
|
|
8375
|
+
if (!(0, import_node_fs13.existsSync)(configPath)) {
|
|
8262
8376
|
exitError("CONFIG_NOT_FOUND", `\u672A\u627E\u5230\u914D\u7F6E\u6587\u4EF6: ${configPath}`);
|
|
8263
8377
|
}
|
|
8264
8378
|
let cfg = {};
|
|
8265
8379
|
try {
|
|
8266
|
-
const raw = (0,
|
|
8380
|
+
const raw = (0, import_node_fs13.readFileSync)(configPath, "utf-8");
|
|
8267
8381
|
const parsed = JSON.parse(raw);
|
|
8268
8382
|
if (isObject(parsed)) cfg = parsed;
|
|
8269
8383
|
} catch (err) {
|
|
@@ -8271,8 +8385,8 @@ function registerLightSetupTools(light) {
|
|
|
8271
8385
|
}
|
|
8272
8386
|
const result = upsertLightControlAlsoAllow(cfg);
|
|
8273
8387
|
try {
|
|
8274
|
-
(0,
|
|
8275
|
-
(0,
|
|
8388
|
+
(0, import_node_fs13.mkdirSync)((0, import_node_path12.dirname)(configPath), { recursive: true });
|
|
8389
|
+
(0, import_node_fs13.writeFileSync)(configPath, JSON.stringify(cfg, null, 2) + "\n", "utf-8");
|
|
8276
8390
|
} catch (err) {
|
|
8277
8391
|
exitError("WRITE_FAILED", `\u5199\u5165\u914D\u7F6E\u5931\u8D25: ${err?.message ?? String(err)}`);
|
|
8278
8392
|
}
|
|
@@ -8290,17 +8404,17 @@ function registerLightSetupTools(light) {
|
|
|
8290
8404
|
}
|
|
8291
8405
|
|
|
8292
8406
|
// src/cli/tunnel-status.ts
|
|
8293
|
-
var
|
|
8294
|
-
var
|
|
8407
|
+
var import_node_fs14 = require("fs");
|
|
8408
|
+
var import_node_path13 = require("path");
|
|
8295
8409
|
init_credentials();
|
|
8296
8410
|
init_env();
|
|
8297
|
-
var STATUS_REL_PATH = (0,
|
|
8411
|
+
var STATUS_REL_PATH = (0, import_node_path13.join)("plugins", "phone-notifications", "tunnel-status.json");
|
|
8298
8412
|
function readTunnelStatus(ctx) {
|
|
8299
8413
|
if (!ctx.stateDir) return null;
|
|
8300
|
-
const filePath = (0,
|
|
8301
|
-
if (!(0,
|
|
8414
|
+
const filePath = (0, import_node_path13.join)(ctx.stateDir, STATUS_REL_PATH);
|
|
8415
|
+
if (!(0, import_node_fs14.existsSync)(filePath)) return null;
|
|
8302
8416
|
try {
|
|
8303
|
-
return JSON.parse((0,
|
|
8417
|
+
return JSON.parse((0, import_node_fs14.readFileSync)(filePath, "utf-8"));
|
|
8304
8418
|
} catch {
|
|
8305
8419
|
return null;
|
|
8306
8420
|
}
|
|
@@ -8368,24 +8482,24 @@ function registerNtfStoragePath(ntf, ctx) {
|
|
|
8368
8482
|
}
|
|
8369
8483
|
|
|
8370
8484
|
// src/cli/log-search.ts
|
|
8371
|
-
var
|
|
8372
|
-
var
|
|
8485
|
+
var import_node_fs15 = require("fs");
|
|
8486
|
+
var import_node_path14 = require("path");
|
|
8373
8487
|
function resolveLogsDir(ctx) {
|
|
8374
8488
|
if (ctx.stateDir) {
|
|
8375
|
-
const dir = (0,
|
|
8489
|
+
const dir = (0, import_node_path14.join)(
|
|
8376
8490
|
ctx.stateDir,
|
|
8377
8491
|
"plugins",
|
|
8378
8492
|
"phone-notifications",
|
|
8379
8493
|
"logs"
|
|
8380
8494
|
);
|
|
8381
|
-
if ((0,
|
|
8495
|
+
if ((0, import_node_fs15.existsSync)(dir)) return dir;
|
|
8382
8496
|
}
|
|
8383
8497
|
return null;
|
|
8384
8498
|
}
|
|
8385
8499
|
function listLogDateKeys(dir) {
|
|
8386
8500
|
const pattern = /^(\d{4}-\d{2}-\d{2})\.log$/;
|
|
8387
8501
|
const keys = [];
|
|
8388
|
-
for (const entry of (0,
|
|
8502
|
+
for (const entry of (0, import_node_fs15.readdirSync)(dir, { withFileTypes: true })) {
|
|
8389
8503
|
if (!entry.isFile()) continue;
|
|
8390
8504
|
const m = pattern.exec(entry.name);
|
|
8391
8505
|
if (m) keys.push(m[1]);
|
|
@@ -8393,9 +8507,9 @@ function listLogDateKeys(dir) {
|
|
|
8393
8507
|
return keys.sort().reverse();
|
|
8394
8508
|
}
|
|
8395
8509
|
function collectLogLines(dir, dateKey, keyword, limit, collected) {
|
|
8396
|
-
const filePath = (0,
|
|
8397
|
-
if (!(0,
|
|
8398
|
-
const content = (0,
|
|
8510
|
+
const filePath = (0, import_node_path14.join)(dir, `${dateKey}.log`);
|
|
8511
|
+
if (!(0, import_node_fs15.existsSync)(filePath)) return;
|
|
8512
|
+
const content = (0, import_node_fs15.readFileSync)(filePath, "utf-8");
|
|
8399
8513
|
const lowerKeyword = keyword?.toLowerCase();
|
|
8400
8514
|
for (const line of content.split("\n")) {
|
|
8401
8515
|
if (collected.length >= limit) return;
|
|
@@ -8462,12 +8576,12 @@ function registerEnvCli(ntf) {
|
|
|
8462
8576
|
}
|
|
8463
8577
|
|
|
8464
8578
|
// src/cli/doctor.ts
|
|
8465
|
-
var
|
|
8579
|
+
var import_node_fs19 = require("fs");
|
|
8466
8580
|
var import_node_readline = require("readline");
|
|
8467
8581
|
init_host();
|
|
8468
8582
|
|
|
8469
8583
|
// src/cli/doctor/check-dangerous-flags.ts
|
|
8470
|
-
var
|
|
8584
|
+
var import_node_fs16 = require("fs");
|
|
8471
8585
|
function isObject2(v) {
|
|
8472
8586
|
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
8473
8587
|
}
|
|
@@ -8484,13 +8598,13 @@ var checkDangerousFlags = ({ cfg, configPath }) => {
|
|
|
8484
8598
|
detail: "\u8FD9\u4F1A\u5173\u95ED Control UI \u7684\u8BBE\u5907\u8EAB\u4EFD\u9A8C\u8BC1\uFF0C\u4EFB\u4F55\u4EBA\u90FD\u53EF\u4EE5\u8BBF\u95EE\u63A7\u5236\u9762\u677F\u3002",
|
|
8485
8599
|
fixDescription: "\u8BBE\u4E3A false",
|
|
8486
8600
|
fix: () => {
|
|
8487
|
-
const raw = (0,
|
|
8601
|
+
const raw = (0, import_node_fs16.readFileSync)(configPath, "utf-8");
|
|
8488
8602
|
const config = JSON.parse(raw);
|
|
8489
8603
|
const gw = config.gateway;
|
|
8490
8604
|
const cui = gw.controlUi;
|
|
8491
8605
|
cui.dangerouslyDisableDeviceAuth = false;
|
|
8492
|
-
(0,
|
|
8493
|
-
(0,
|
|
8606
|
+
(0, import_node_fs16.copyFileSync)(configPath, configPath + ".bak");
|
|
8607
|
+
(0, import_node_fs16.writeFileSync)(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
8494
8608
|
}
|
|
8495
8609
|
};
|
|
8496
8610
|
};
|
|
@@ -8538,11 +8652,11 @@ function warnEmpty() {
|
|
|
8538
8652
|
}
|
|
8539
8653
|
|
|
8540
8654
|
// src/cli/doctor/check-state-dir-perms.ts
|
|
8541
|
-
var
|
|
8655
|
+
var import_node_fs17 = require("fs");
|
|
8542
8656
|
var checkStateDirPerms = ({ stateDir }) => {
|
|
8543
8657
|
let mode;
|
|
8544
8658
|
try {
|
|
8545
|
-
mode = (0,
|
|
8659
|
+
mode = (0, import_node_fs17.statSync)(stateDir).mode;
|
|
8546
8660
|
} catch {
|
|
8547
8661
|
return null;
|
|
8548
8662
|
}
|
|
@@ -8556,7 +8670,7 @@ var checkStateDirPerms = ({ stateDir }) => {
|
|
|
8556
8670
|
detail: "\u5176\u4ED6\u7528\u6237\u53EF\u4EE5\u8BFB\u53D6\u8BE5\u76EE\u5F55\u4E0B\u7684\u51ED\u8BC1\u548C\u914D\u7F6E\u6587\u4EF6\u3002",
|
|
8557
8671
|
fixDescription: "chmod 700 " + stateDir,
|
|
8558
8672
|
fix: () => {
|
|
8559
|
-
(0,
|
|
8673
|
+
(0, import_node_fs17.chmodSync)(stateDir, 448);
|
|
8560
8674
|
}
|
|
8561
8675
|
};
|
|
8562
8676
|
};
|
|
@@ -8611,16 +8725,16 @@ var checkCredentials = () => {
|
|
|
8611
8725
|
};
|
|
8612
8726
|
|
|
8613
8727
|
// src/cli/doctor/check-tunnel.ts
|
|
8614
|
-
var
|
|
8615
|
-
var
|
|
8616
|
-
var STATUS_REL_PATH2 = (0,
|
|
8728
|
+
var import_node_fs18 = require("fs");
|
|
8729
|
+
var import_node_path15 = require("path");
|
|
8730
|
+
var STATUS_REL_PATH2 = (0, import_node_path15.join)(
|
|
8617
8731
|
"plugins",
|
|
8618
8732
|
"phone-notifications",
|
|
8619
8733
|
"tunnel-status.json"
|
|
8620
8734
|
);
|
|
8621
8735
|
var checkTunnel = ({ stateDir }) => {
|
|
8622
|
-
const filePath = (0,
|
|
8623
|
-
if (!(0,
|
|
8736
|
+
const filePath = (0, import_node_path15.join)(stateDir, STATUS_REL_PATH2);
|
|
8737
|
+
if (!(0, import_node_fs18.existsSync)(filePath)) {
|
|
8624
8738
|
return {
|
|
8625
8739
|
id: "tunnel",
|
|
8626
8740
|
severity: "warn",
|
|
@@ -8632,7 +8746,7 @@ var checkTunnel = ({ stateDir }) => {
|
|
|
8632
8746
|
}
|
|
8633
8747
|
let status;
|
|
8634
8748
|
try {
|
|
8635
|
-
status = JSON.parse((0,
|
|
8749
|
+
status = JSON.parse((0, import_node_fs18.readFileSync)(filePath, "utf-8"));
|
|
8636
8750
|
} catch {
|
|
8637
8751
|
return {
|
|
8638
8752
|
id: "tunnel",
|
|
@@ -8725,9 +8839,9 @@ function isObject5(v) {
|
|
|
8725
8839
|
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
8726
8840
|
}
|
|
8727
8841
|
function readConfig(configPath) {
|
|
8728
|
-
if (!(0,
|
|
8842
|
+
if (!(0, import_node_fs19.existsSync)(configPath)) return {};
|
|
8729
8843
|
try {
|
|
8730
|
-
const parsed = JSON.parse((0,
|
|
8844
|
+
const parsed = JSON.parse((0, import_node_fs19.readFileSync)(configPath, "utf-8"));
|
|
8731
8845
|
return isObject5(parsed) ? parsed : {};
|
|
8732
8846
|
} catch {
|
|
8733
8847
|
return {};
|
|
@@ -8928,7 +9042,7 @@ function registerRecStoragePath(rec, ctx) {
|
|
|
8928
9042
|
|
|
8929
9043
|
// src/cli/rec-setup.ts
|
|
8930
9044
|
var import_node_readline2 = require("readline");
|
|
8931
|
-
var
|
|
9045
|
+
var import_node_fs20 = require("fs");
|
|
8932
9046
|
function ask(rl, question) {
|
|
8933
9047
|
return new Promise((resolve) => rl.question(question, resolve));
|
|
8934
9048
|
}
|
|
@@ -9014,9 +9128,9 @@ async function setupLocal(rl) {
|
|
|
9014
9128
|
function registerRecSetup(rec, ctx) {
|
|
9015
9129
|
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 () => {
|
|
9016
9130
|
const configPath = resolveAsrConfigPath(ctx);
|
|
9017
|
-
if ((0,
|
|
9131
|
+
if ((0, import_node_fs20.existsSync)(configPath)) {
|
|
9018
9132
|
try {
|
|
9019
|
-
const existing = JSON.parse((0,
|
|
9133
|
+
const existing = JSON.parse((0, import_node_fs20.readFileSync)(configPath, "utf-8"));
|
|
9020
9134
|
process.stderr.write(`\u5F53\u524D\u5DF2\u6709\u914D\u7F6E\uFF1Amode = ${existing.mode}`);
|
|
9021
9135
|
if (existing.updatedAt) process.stderr.write(`\uFF0C\u66F4\u65B0\u4E8E ${existing.updatedAt}`);
|
|
9022
9136
|
process.stderr.write("\n");
|
|
@@ -9029,7 +9143,7 @@ function registerRecSetup(rec, ctx) {
|
|
|
9029
9143
|
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"]);
|
|
9030
9144
|
const config = modeIdx === 0 ? await setupApi(rl) : await setupLocal(rl);
|
|
9031
9145
|
const stored = { ...config, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
9032
|
-
(0,
|
|
9146
|
+
(0, import_node_fs20.writeFileSync)(configPath, JSON.stringify(stored, null, 2), "utf-8");
|
|
9033
9147
|
process.stderr.write(`
|
|
9034
9148
|
\u2713 \u914D\u7F6E\u5DF2\u4FDD\u5B58\u5230 ${configPath}
|
|
9035
9149
|
|
|
@@ -9043,11 +9157,11 @@ function registerRecSetup(rec, ctx) {
|
|
|
9043
9157
|
|
|
9044
9158
|
// src/cli/update.ts
|
|
9045
9159
|
var import_node_child_process = require("child_process");
|
|
9046
|
-
var
|
|
9047
|
-
var
|
|
9048
|
-
var
|
|
9160
|
+
var import_node_fs21 = require("fs");
|
|
9161
|
+
var import_node_path16 = require("path");
|
|
9162
|
+
var import_node_os3 = __toESM(require("os"), 1);
|
|
9049
9163
|
init_host();
|
|
9050
|
-
var
|
|
9164
|
+
var BASE_URL2 = "https://artifact.yoooclaw.com/plugin";
|
|
9051
9165
|
async function fetchText(url) {
|
|
9052
9166
|
const res = await fetch(url, { signal: AbortSignal.timeout(3e4) });
|
|
9053
9167
|
if (!res.ok) {
|
|
@@ -9067,7 +9181,7 @@ async function runUpdate(ctx, opts) {
|
|
|
9067
9181
|
log(`\u68C0\u67E5${beta ? " beta" : ""}\u6700\u65B0\u7248\u672C ...`);
|
|
9068
9182
|
let latest;
|
|
9069
9183
|
try {
|
|
9070
|
-
latest = (await fetchText(`${
|
|
9184
|
+
latest = (await fetchText(`${BASE_URL2}/${channel}`)).trim();
|
|
9071
9185
|
} catch (err) {
|
|
9072
9186
|
const msg = `\u65E0\u6CD5\u83B7\u53D6\u6700\u65B0\u7248\u672C: ${err?.message ?? String(err)}`;
|
|
9073
9187
|
if (json) {
|
|
@@ -9092,7 +9206,7 @@ async function runUpdate(ctx, opts) {
|
|
|
9092
9206
|
log("\u4E0B\u8F7D\u5B89\u88C5\u811A\u672C ...");
|
|
9093
9207
|
let installScript;
|
|
9094
9208
|
try {
|
|
9095
|
-
installScript = await fetchText(`${
|
|
9209
|
+
installScript = await fetchText(`${BASE_URL2}/install-core.mjs`);
|
|
9096
9210
|
} catch (err) {
|
|
9097
9211
|
const msg = `\u4E0B\u8F7D\u5B89\u88C5\u811A\u672C\u5931\u8D25: ${err?.message ?? String(err)}`;
|
|
9098
9212
|
if (json) {
|
|
@@ -9103,9 +9217,9 @@ async function runUpdate(ctx, opts) {
|
|
|
9103
9217
|
`);
|
|
9104
9218
|
process.exit(1);
|
|
9105
9219
|
}
|
|
9106
|
-
const tmpScript = (0,
|
|
9220
|
+
const tmpScript = (0, import_node_path16.join)(import_node_os3.default.tmpdir(), `openclaw-install-${Date.now()}.mjs`);
|
|
9107
9221
|
try {
|
|
9108
|
-
(0,
|
|
9222
|
+
(0, import_node_fs21.writeFileSync)(tmpScript, installScript, "utf-8");
|
|
9109
9223
|
} catch (err) {
|
|
9110
9224
|
const msg = `\u5199\u5165\u4E34\u65F6\u6587\u4EF6\u5931\u8D25: ${err?.message ?? String(err)}`;
|
|
9111
9225
|
if (json) {
|
|
@@ -9123,7 +9237,7 @@ async function runUpdate(ctx, opts) {
|
|
|
9123
9237
|
{ stdio: "inherit" }
|
|
9124
9238
|
);
|
|
9125
9239
|
try {
|
|
9126
|
-
(0,
|
|
9240
|
+
(0, import_node_fs21.unlinkSync)(tmpScript);
|
|
9127
9241
|
} catch {
|
|
9128
9242
|
}
|
|
9129
9243
|
if (result.error) {
|
|
@@ -9187,10 +9301,10 @@ function inferOpenClawRootDir(workspaceDir) {
|
|
|
9187
9301
|
if (!workspaceDir) {
|
|
9188
9302
|
return void 0;
|
|
9189
9303
|
}
|
|
9190
|
-
if ((0,
|
|
9304
|
+
if ((0, import_node_path17.basename)(workspaceDir) !== "workspace") {
|
|
9191
9305
|
return void 0;
|
|
9192
9306
|
}
|
|
9193
|
-
return (0,
|
|
9307
|
+
return (0, import_node_path17.dirname)(workspaceDir);
|
|
9194
9308
|
}
|
|
9195
9309
|
function registerPluginCli(api, params) {
|
|
9196
9310
|
const { logger, openclawDir } = params;
|
|
@@ -9436,12 +9550,12 @@ function registerLightControlTool(api, logger) {
|
|
|
9436
9550
|
}
|
|
9437
9551
|
|
|
9438
9552
|
// src/plugin/lifecycle.ts
|
|
9439
|
-
var
|
|
9553
|
+
var import_node_fs30 = require("fs");
|
|
9440
9554
|
init_host();
|
|
9441
9555
|
|
|
9442
9556
|
// src/notification/app-name-map.ts
|
|
9443
|
-
var
|
|
9444
|
-
var
|
|
9557
|
+
var import_node_fs22 = require("fs");
|
|
9558
|
+
var import_node_path18 = require("path");
|
|
9445
9559
|
init_credentials();
|
|
9446
9560
|
init_env();
|
|
9447
9561
|
var PLUGIN_STATE_DIR = "phone-notifications";
|
|
@@ -9462,7 +9576,7 @@ function isAppNameMapApiResponse(v) {
|
|
|
9462
9576
|
);
|
|
9463
9577
|
}
|
|
9464
9578
|
function getCachePath(stateDir) {
|
|
9465
|
-
return (0,
|
|
9579
|
+
return (0, import_node_path18.join)(stateDir, "plugins", PLUGIN_STATE_DIR, CACHE_FILE);
|
|
9466
9580
|
}
|
|
9467
9581
|
function createAppNameMapProvider(opts) {
|
|
9468
9582
|
const { stateDir, logger } = opts;
|
|
@@ -9474,9 +9588,9 @@ function createAppNameMapProvider(opts) {
|
|
|
9474
9588
|
let inFlightFetch = null;
|
|
9475
9589
|
function loadFromDisk() {
|
|
9476
9590
|
const path2 = getCachePath(stateDir);
|
|
9477
|
-
if (!(0,
|
|
9591
|
+
if (!(0, import_node_fs22.existsSync)(path2)) return;
|
|
9478
9592
|
try {
|
|
9479
|
-
const raw = JSON.parse((0,
|
|
9593
|
+
const raw = JSON.parse((0, import_node_fs22.readFileSync)(path2, "utf-8"));
|
|
9480
9594
|
if (!isRecordOfStrings(raw)) return;
|
|
9481
9595
|
map.clear();
|
|
9482
9596
|
for (const [k, v] of Object.entries(raw)) map.set(k, v);
|
|
@@ -9520,10 +9634,10 @@ function createAppNameMapProvider(opts) {
|
|
|
9520
9634
|
logger.warn("[app-name-map] refresh succeeded but got 0 entries");
|
|
9521
9635
|
return;
|
|
9522
9636
|
}
|
|
9523
|
-
const dir = (0,
|
|
9524
|
-
(0,
|
|
9637
|
+
const dir = (0, import_node_path18.join)(stateDir, "plugins", PLUGIN_STATE_DIR);
|
|
9638
|
+
(0, import_node_fs22.mkdirSync)(dir, { recursive: true });
|
|
9525
9639
|
const cachePath = getCachePath(stateDir);
|
|
9526
|
-
(0,
|
|
9640
|
+
(0, import_node_fs22.writeFileSync)(cachePath, JSON.stringify(Object.fromEntries(map), null, 2), "utf-8");
|
|
9527
9641
|
logger.info(`[app-name-map] refreshed ${map.size} entries from server and saved: ${cachePath}`);
|
|
9528
9642
|
} catch (e) {
|
|
9529
9643
|
const message = e instanceof Error ? e.message : String(e);
|
|
@@ -9567,8 +9681,8 @@ function createAppNameMapProvider(opts) {
|
|
|
9567
9681
|
}
|
|
9568
9682
|
|
|
9569
9683
|
// src/recording/storage.ts
|
|
9570
|
-
var
|
|
9571
|
-
var
|
|
9684
|
+
var import_node_fs23 = require("fs");
|
|
9685
|
+
var import_node_path19 = require("path");
|
|
9572
9686
|
|
|
9573
9687
|
// src/recording/state-machine.ts
|
|
9574
9688
|
var VALID_TRANSITIONS = /* @__PURE__ */ new Map([
|
|
@@ -9629,7 +9743,7 @@ function stripMarkdownFence(markdown) {
|
|
|
9629
9743
|
}
|
|
9630
9744
|
function deriveTitleFromTranscriptPath(transcriptFile, recordingId) {
|
|
9631
9745
|
if (!transcriptFile) return void 0;
|
|
9632
|
-
const name = (0,
|
|
9746
|
+
const name = (0, import_node_path19.basename)(transcriptFile, ".md");
|
|
9633
9747
|
const prefix = `${recordingId}_`;
|
|
9634
9748
|
if (name.startsWith(prefix)) {
|
|
9635
9749
|
const derived = name.slice(prefix.length).trim();
|
|
@@ -9657,22 +9771,22 @@ function extractTranscriptContent(markdown) {
|
|
|
9657
9771
|
return lines.join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
9658
9772
|
}
|
|
9659
9773
|
function resolveRecordingStorageDir(ctx, logger) {
|
|
9660
|
-
const stateRecDir = (0,
|
|
9774
|
+
const stateRecDir = (0, import_node_path19.join)(
|
|
9661
9775
|
ctx.stateDir,
|
|
9662
9776
|
"plugins",
|
|
9663
9777
|
"phone-notifications",
|
|
9664
9778
|
RECORDINGS_DIR
|
|
9665
9779
|
);
|
|
9666
9780
|
try {
|
|
9667
|
-
(0,
|
|
9781
|
+
(0, import_node_fs23.mkdirSync)(stateRecDir, { recursive: true });
|
|
9668
9782
|
logger.info(`\u5F55\u97F3\u5C06\u5199\u5165 stateDir \u8DEF\u5F84: ${stateRecDir}`);
|
|
9669
9783
|
return stateRecDir;
|
|
9670
9784
|
} catch {
|
|
9671
9785
|
}
|
|
9672
9786
|
if (ctx.workspaceDir) {
|
|
9673
|
-
const wsRecDir = (0,
|
|
9787
|
+
const wsRecDir = (0, import_node_path19.join)(ctx.workspaceDir, RECORDINGS_DIR);
|
|
9674
9788
|
try {
|
|
9675
|
-
(0,
|
|
9789
|
+
(0, import_node_fs23.mkdirSync)(wsRecDir, { recursive: true });
|
|
9676
9790
|
logger.warn(`stateDir \u4E0D\u53EF\u7528\uFF0C\u5F55\u97F3\u5DF2\u56DE\u9000\u5230 workspace \u8DEF\u5F84: ${wsRecDir}`);
|
|
9677
9791
|
return wsRecDir;
|
|
9678
9792
|
} catch {
|
|
@@ -9684,11 +9798,11 @@ var RecordingStorage = class {
|
|
|
9684
9798
|
constructor(dir, logger) {
|
|
9685
9799
|
this.logger = logger;
|
|
9686
9800
|
this.dir = dir;
|
|
9687
|
-
this.audioDir = (0,
|
|
9688
|
-
this.transcriptDataDir = (0,
|
|
9689
|
-
this.transcriptsDir = (0,
|
|
9690
|
-
this.summariesDir = (0,
|
|
9691
|
-
this.indexPath = (0,
|
|
9801
|
+
this.audioDir = (0, import_node_path19.join)(dir, AUDIO_DIR);
|
|
9802
|
+
this.transcriptDataDir = (0, import_node_path19.join)(dir, TRANSCRIPT_DATA_DIR);
|
|
9803
|
+
this.transcriptsDir = (0, import_node_path19.join)(dir, TRANSCRIPTS_DIR);
|
|
9804
|
+
this.summariesDir = (0, import_node_path19.join)(dir, SUMMARIES_DIR);
|
|
9805
|
+
this.indexPath = (0, import_node_path19.join)(dir, INDEX_FILE);
|
|
9692
9806
|
}
|
|
9693
9807
|
dir;
|
|
9694
9808
|
audioDir;
|
|
@@ -9699,10 +9813,10 @@ var RecordingStorage = class {
|
|
|
9699
9813
|
index = { recordings: [] };
|
|
9700
9814
|
/** 初始化目录结构并加载索引 */
|
|
9701
9815
|
async init() {
|
|
9702
|
-
(0,
|
|
9703
|
-
(0,
|
|
9704
|
-
(0,
|
|
9705
|
-
(0,
|
|
9816
|
+
(0, import_node_fs23.mkdirSync)(this.audioDir, { recursive: true });
|
|
9817
|
+
(0, import_node_fs23.mkdirSync)(this.transcriptDataDir, { recursive: true });
|
|
9818
|
+
(0, import_node_fs23.mkdirSync)(this.transcriptsDir, { recursive: true });
|
|
9819
|
+
(0, import_node_fs23.mkdirSync)(this.summariesDir, { recursive: true });
|
|
9706
9820
|
this.loadIndex();
|
|
9707
9821
|
this.logger.info(
|
|
9708
9822
|
`\u5F55\u97F3\u5B58\u50A8\u5DF2\u521D\u59CB\u5316: ${this.dir}\uFF08\u5171 ${this.index.recordings.length} \u6761\u8BB0\u5F55\uFF09`
|
|
@@ -9746,13 +9860,13 @@ var RecordingStorage = class {
|
|
|
9746
9860
|
return id;
|
|
9747
9861
|
}
|
|
9748
9862
|
if (existing.transcriptDataFile) {
|
|
9749
|
-
(0,
|
|
9863
|
+
(0, import_node_fs23.rmSync)((0, import_node_path19.join)(this.dir, existing.transcriptDataFile), { force: true });
|
|
9750
9864
|
}
|
|
9751
9865
|
if (existing.transcriptFile) {
|
|
9752
|
-
(0,
|
|
9866
|
+
(0, import_node_fs23.rmSync)((0, import_node_path19.join)(this.dir, existing.transcriptFile), { force: true });
|
|
9753
9867
|
}
|
|
9754
9868
|
if (existing.summaryFile) {
|
|
9755
|
-
(0,
|
|
9869
|
+
(0, import_node_fs23.rmSync)((0, import_node_path19.join)(this.dir, existing.summaryFile), { force: true });
|
|
9756
9870
|
}
|
|
9757
9871
|
existing.metadata = metadata;
|
|
9758
9872
|
existing.status = "syncing_openclaw";
|
|
@@ -9820,7 +9934,7 @@ var RecordingStorage = class {
|
|
|
9820
9934
|
if (!entry) return;
|
|
9821
9935
|
const nextTranscriptDataFile = `${TRANSCRIPT_DATA_DIR}/${filename}`;
|
|
9822
9936
|
if (entry.transcriptDataFile && entry.transcriptDataFile !== nextTranscriptDataFile) {
|
|
9823
|
-
(0,
|
|
9937
|
+
(0, import_node_fs23.rmSync)((0, import_node_path19.join)(this.dir, entry.transcriptDataFile), { force: true });
|
|
9824
9938
|
}
|
|
9825
9939
|
entry.transcriptDataFile = nextTranscriptDataFile;
|
|
9826
9940
|
entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -9834,7 +9948,7 @@ var RecordingStorage = class {
|
|
|
9834
9948
|
if (!entry) return;
|
|
9835
9949
|
const nextTranscriptFile = `${TRANSCRIPTS_DIR}/${filename}`;
|
|
9836
9950
|
if (entry.transcriptFile && entry.transcriptFile !== nextTranscriptFile) {
|
|
9837
|
-
(0,
|
|
9951
|
+
(0, import_node_fs23.rmSync)((0, import_node_path19.join)(this.dir, entry.transcriptFile), { force: true });
|
|
9838
9952
|
}
|
|
9839
9953
|
entry.transcriptFile = nextTranscriptFile;
|
|
9840
9954
|
entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -9848,7 +9962,7 @@ var RecordingStorage = class {
|
|
|
9848
9962
|
if (!entry) return;
|
|
9849
9963
|
const nextSummaryFile = `${SUMMARIES_DIR}/${filename}`;
|
|
9850
9964
|
if (entry.summaryFile && entry.summaryFile !== nextSummaryFile) {
|
|
9851
|
-
(0,
|
|
9965
|
+
(0, import_node_fs23.rmSync)((0, import_node_path19.join)(this.dir, entry.summaryFile), { force: true });
|
|
9852
9966
|
}
|
|
9853
9967
|
entry.summaryFile = nextSummaryFile;
|
|
9854
9968
|
entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -9946,24 +10060,24 @@ var RecordingStorage = class {
|
|
|
9946
10060
|
const entry = this.findById(recordingId);
|
|
9947
10061
|
if (!entry) return false;
|
|
9948
10062
|
if (entry.audioFile) {
|
|
9949
|
-
const audioPath = (0,
|
|
9950
|
-
(0,
|
|
10063
|
+
const audioPath = (0, import_node_path19.join)(this.dir, entry.audioFile);
|
|
10064
|
+
(0, import_node_fs23.rmSync)(audioPath, { force: true });
|
|
9951
10065
|
}
|
|
9952
10066
|
if (entry.srtFile) {
|
|
9953
|
-
const srtPath = (0,
|
|
9954
|
-
(0,
|
|
10067
|
+
const srtPath = (0, import_node_path19.join)(this.dir, entry.srtFile);
|
|
10068
|
+
(0, import_node_fs23.rmSync)(srtPath, { force: true });
|
|
9955
10069
|
}
|
|
9956
10070
|
if (entry.transcriptDataFile) {
|
|
9957
|
-
const transcriptDataPath = (0,
|
|
9958
|
-
(0,
|
|
10071
|
+
const transcriptDataPath = (0, import_node_path19.join)(this.dir, entry.transcriptDataFile);
|
|
10072
|
+
(0, import_node_fs23.rmSync)(transcriptDataPath, { force: true });
|
|
9959
10073
|
}
|
|
9960
10074
|
if (entry.transcriptFile) {
|
|
9961
|
-
const transcriptPath = (0,
|
|
9962
|
-
(0,
|
|
10075
|
+
const transcriptPath = (0, import_node_path19.join)(this.dir, entry.transcriptFile);
|
|
10076
|
+
(0, import_node_fs23.rmSync)(transcriptPath, { force: true });
|
|
9963
10077
|
}
|
|
9964
10078
|
if (entry.summaryFile) {
|
|
9965
|
-
const summaryPath = (0,
|
|
9966
|
-
(0,
|
|
10079
|
+
const summaryPath = (0, import_node_path19.join)(this.dir, entry.summaryFile);
|
|
10080
|
+
(0, import_node_fs23.rmSync)(summaryPath, { force: true });
|
|
9967
10081
|
}
|
|
9968
10082
|
if (opts?.localOnly) {
|
|
9969
10083
|
entry.audioFile = void 0;
|
|
@@ -10021,34 +10135,34 @@ var RecordingStorage = class {
|
|
|
10021
10135
|
* 获取音频文件的绝对路径。ossUrl 用于推断文件扩展名
|
|
10022
10136
|
*/
|
|
10023
10137
|
getAudioFilePath(recordingId, ossUrl) {
|
|
10024
|
-
return (0,
|
|
10138
|
+
return (0, import_node_path19.join)(this.audioDir, this.buildAudioFilename(recordingId, ossUrl));
|
|
10025
10139
|
}
|
|
10026
10140
|
/**
|
|
10027
10141
|
* 获取打点文件的绝对路径
|
|
10028
10142
|
*/
|
|
10029
10143
|
getSrtFilePath(recordingId) {
|
|
10030
|
-
return (0,
|
|
10144
|
+
return (0, import_node_path19.join)(this.audioDir, this.buildSrtFilename(recordingId));
|
|
10031
10145
|
}
|
|
10032
10146
|
/**
|
|
10033
10147
|
* 获取转写 JSON 文件的绝对路径
|
|
10034
10148
|
*/
|
|
10035
10149
|
getTranscriptDataFilePath(recordingId) {
|
|
10036
|
-
return (0,
|
|
10150
|
+
return (0, import_node_path19.join)(this.transcriptDataDir, this.buildTranscriptDataFilename(recordingId));
|
|
10037
10151
|
}
|
|
10038
10152
|
/**
|
|
10039
10153
|
* 获取摘要文件的绝对路径
|
|
10040
10154
|
*/
|
|
10041
10155
|
getSummaryFilePath(recordingId) {
|
|
10042
|
-
return (0,
|
|
10156
|
+
return (0, import_node_path19.join)(this.summariesDir, this.buildSummaryFilename(recordingId));
|
|
10043
10157
|
}
|
|
10044
10158
|
// ─── Persistence ───
|
|
10045
10159
|
loadIndex() {
|
|
10046
|
-
if (!(0,
|
|
10160
|
+
if (!(0, import_node_fs23.existsSync)(this.indexPath)) {
|
|
10047
10161
|
this.index = { recordings: [] };
|
|
10048
10162
|
return;
|
|
10049
10163
|
}
|
|
10050
10164
|
try {
|
|
10051
|
-
const raw = JSON.parse((0,
|
|
10165
|
+
const raw = JSON.parse((0, import_node_fs23.readFileSync)(this.indexPath, "utf-8"));
|
|
10052
10166
|
if (raw && Array.isArray(raw.recordings)) {
|
|
10053
10167
|
let needsRewrite = false;
|
|
10054
10168
|
const normalized = raw.recordings.filter((entry) => entry && typeof entry === "object").map((entry) => {
|
|
@@ -10086,8 +10200,8 @@ var RecordingStorage = class {
|
|
|
10086
10200
|
segments: []
|
|
10087
10201
|
});
|
|
10088
10202
|
const transcriptDataFilename = this.buildTranscriptDataFilename(compacted.id);
|
|
10089
|
-
(0,
|
|
10090
|
-
(0,
|
|
10203
|
+
(0, import_node_fs23.writeFileSync)(
|
|
10204
|
+
(0, import_node_path19.join)(this.transcriptDataDir, transcriptDataFilename),
|
|
10091
10205
|
JSON.stringify(transcriptDoc, null, 2),
|
|
10092
10206
|
"utf-8"
|
|
10093
10207
|
);
|
|
@@ -10099,8 +10213,8 @@ var RecordingStorage = class {
|
|
|
10099
10213
|
compacted.summaryFile = entry.summaryFile;
|
|
10100
10214
|
} else if (typeof entry.summary === "string" && entry.summary.trim()) {
|
|
10101
10215
|
const summaryFilename = this.buildSummaryFilename(entry.id);
|
|
10102
|
-
(0,
|
|
10103
|
-
(0,
|
|
10216
|
+
(0, import_node_fs23.writeFileSync)(
|
|
10217
|
+
(0, import_node_path19.join)(this.summariesDir, summaryFilename),
|
|
10104
10218
|
entry.summary.trim(),
|
|
10105
10219
|
"utf-8"
|
|
10106
10220
|
);
|
|
@@ -10110,8 +10224,8 @@ var RecordingStorage = class {
|
|
|
10110
10224
|
const summaryFromDocument = extractTranscriptSummaryFromDocument(transcriptDoc);
|
|
10111
10225
|
if (summaryFromDocument) {
|
|
10112
10226
|
const summaryFilename = this.buildSummaryFilename(entry.id);
|
|
10113
|
-
(0,
|
|
10114
|
-
(0,
|
|
10227
|
+
(0, import_node_fs23.writeFileSync)(
|
|
10228
|
+
(0, import_node_path19.join)(this.summariesDir, summaryFilename),
|
|
10115
10229
|
summaryFromDocument,
|
|
10116
10230
|
"utf-8"
|
|
10117
10231
|
);
|
|
@@ -10151,7 +10265,7 @@ var RecordingStorage = class {
|
|
|
10151
10265
|
}
|
|
10152
10266
|
readRelativeTextFile(relativePath) {
|
|
10153
10267
|
try {
|
|
10154
|
-
return (0,
|
|
10268
|
+
return (0, import_node_fs23.readFileSync)((0, import_node_path19.join)(this.dir, relativePath), "utf-8");
|
|
10155
10269
|
} catch {
|
|
10156
10270
|
return void 0;
|
|
10157
10271
|
}
|
|
@@ -10164,7 +10278,7 @@ var RecordingStorage = class {
|
|
|
10164
10278
|
return parseTranscriptDocument(raw);
|
|
10165
10279
|
}
|
|
10166
10280
|
saveIndex() {
|
|
10167
|
-
(0,
|
|
10281
|
+
(0, import_node_fs23.writeFileSync)(
|
|
10168
10282
|
this.indexPath,
|
|
10169
10283
|
JSON.stringify(this.index, null, 2),
|
|
10170
10284
|
"utf-8"
|
|
@@ -10178,8 +10292,8 @@ var RecordingStorage = class {
|
|
|
10178
10292
|
init_transcript_document();
|
|
10179
10293
|
|
|
10180
10294
|
// src/recording/downloader.ts
|
|
10181
|
-
var
|
|
10182
|
-
var
|
|
10295
|
+
var import_node_fs24 = require("fs");
|
|
10296
|
+
var import_node_path20 = require("path");
|
|
10183
10297
|
var import_promises2 = require("stream/promises");
|
|
10184
10298
|
var import_node_stream = require("stream");
|
|
10185
10299
|
var DEFAULT_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
@@ -10189,7 +10303,7 @@ async function downloadFile(url, destPath, logger, options) {
|
|
|
10189
10303
|
const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
10190
10304
|
const maxRetries = options?.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
10191
10305
|
const retryBackoffMs = options?.retryBackoffMs ?? DEFAULT_RETRY_BACKOFF_MS;
|
|
10192
|
-
(0,
|
|
10306
|
+
(0, import_node_fs24.mkdirSync)((0, import_node_path20.dirname)(destPath), { recursive: true });
|
|
10193
10307
|
let lastError;
|
|
10194
10308
|
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
10195
10309
|
const startMs = Date.now();
|
|
@@ -10207,11 +10321,11 @@ async function downloadFile(url, destPath, logger, options) {
|
|
|
10207
10321
|
if (!res.body) {
|
|
10208
10322
|
throw new Error("\u54CD\u5E94\u4F53\u4E3A\u7A7A");
|
|
10209
10323
|
}
|
|
10210
|
-
const writeStream = (0,
|
|
10324
|
+
const writeStream = (0, import_node_fs24.createWriteStream)(destPath);
|
|
10211
10325
|
const readable = import_node_stream.Readable.fromWeb(res.body);
|
|
10212
10326
|
await (0, import_promises2.pipeline)(readable, writeStream);
|
|
10213
10327
|
const elapsed = Date.now() - startMs;
|
|
10214
|
-
const fileSize = (0,
|
|
10328
|
+
const fileSize = (0, import_node_fs24.existsSync)(destPath) ? (0, import_node_fs24.statSync)(destPath).size : 0;
|
|
10215
10329
|
logger.info(
|
|
10216
10330
|
`[downloader] \u4E0B\u8F7D\u5B8C\u6210: ${destPath} (${formatBytes(fileSize)}, ${elapsed}ms)`
|
|
10217
10331
|
);
|
|
@@ -10222,7 +10336,7 @@ async function downloadFile(url, destPath, logger, options) {
|
|
|
10222
10336
|
} catch (err) {
|
|
10223
10337
|
lastError = err?.message ?? String(err);
|
|
10224
10338
|
try {
|
|
10225
|
-
if ((0,
|
|
10339
|
+
if ((0, import_node_fs24.existsSync)(destPath)) (0, import_node_fs24.unlinkSync)(destPath);
|
|
10226
10340
|
} catch {
|
|
10227
10341
|
}
|
|
10228
10342
|
const isAbort = err?.name === "AbortError";
|
|
@@ -10460,13 +10574,13 @@ async function triggerTranscription(recordingId, storage, asrConfig, logger, opt
|
|
|
10460
10574
|
}
|
|
10461
10575
|
|
|
10462
10576
|
// src/tunnel/service.ts
|
|
10463
|
-
var
|
|
10464
|
-
var
|
|
10577
|
+
var import_node_fs29 = require("fs");
|
|
10578
|
+
var import_node_path25 = require("path");
|
|
10465
10579
|
init_credentials();
|
|
10466
10580
|
|
|
10467
10581
|
// src/tunnel/relay-client.ts
|
|
10468
|
-
var
|
|
10469
|
-
var
|
|
10582
|
+
var import_node_fs27 = require("fs");
|
|
10583
|
+
var import_node_path23 = require("path");
|
|
10470
10584
|
|
|
10471
10585
|
// node_modules/.pnpm/ws@8.19.0/node_modules/ws/wrapper.mjs
|
|
10472
10586
|
var import_stream = __toESM(require_stream(), 1);
|
|
@@ -10510,8 +10624,8 @@ var RelayClient = class {
|
|
|
10510
10624
|
lastDisconnectReason
|
|
10511
10625
|
};
|
|
10512
10626
|
try {
|
|
10513
|
-
(0,
|
|
10514
|
-
(0,
|
|
10627
|
+
(0, import_node_fs27.mkdirSync)((0, import_node_path23.dirname)(this.opts.statusFilePath), { recursive: true });
|
|
10628
|
+
(0, import_node_fs27.writeFileSync)(this.opts.statusFilePath, JSON.stringify(info, null, 2));
|
|
10515
10629
|
} catch {
|
|
10516
10630
|
}
|
|
10517
10631
|
}
|
|
@@ -10893,8 +11007,8 @@ init_host();
|
|
|
10893
11007
|
|
|
10894
11008
|
// src/tunnel/device-identity.ts
|
|
10895
11009
|
var import_node_crypto3 = __toESM(require("crypto"), 1);
|
|
10896
|
-
var
|
|
10897
|
-
var
|
|
11010
|
+
var import_node_fs28 = __toESM(require("fs"), 1);
|
|
11011
|
+
var import_node_path24 = __toESM(require("path"), 1);
|
|
10898
11012
|
init_host();
|
|
10899
11013
|
var ED25519_SPKI_PREFIX = Buffer.from("302a300506032b6570032100", "hex");
|
|
10900
11014
|
function base64UrlEncode(buf) {
|
|
@@ -10939,10 +11053,10 @@ function resolveClientStateDir(stateDir) {
|
|
|
10939
11053
|
return stateDir ?? resolveStateDir();
|
|
10940
11054
|
}
|
|
10941
11055
|
function ensureDir(filePath) {
|
|
10942
|
-
|
|
11056
|
+
import_node_fs28.default.mkdirSync(import_node_path24.default.dirname(filePath), { recursive: true });
|
|
10943
11057
|
}
|
|
10944
11058
|
function resolveIdentityPath(stateDir) {
|
|
10945
|
-
return
|
|
11059
|
+
return import_node_path24.default.join(stateDir, "identity", "device.json");
|
|
10946
11060
|
}
|
|
10947
11061
|
function normalizeDeviceAuthRole(role) {
|
|
10948
11062
|
return role.trim();
|
|
@@ -10958,12 +11072,12 @@ function normalizeDeviceAuthScopes(scopes) {
|
|
|
10958
11072
|
return [...out].sort();
|
|
10959
11073
|
}
|
|
10960
11074
|
function resolveDeviceAuthPath(stateDir) {
|
|
10961
|
-
return
|
|
11075
|
+
return import_node_path24.default.join(stateDir, "identity", "device-auth.json");
|
|
10962
11076
|
}
|
|
10963
11077
|
function readDeviceAuthStore(filePath) {
|
|
10964
11078
|
try {
|
|
10965
|
-
if (!
|
|
10966
|
-
const raw =
|
|
11079
|
+
if (!import_node_fs28.default.existsSync(filePath)) return null;
|
|
11080
|
+
const raw = import_node_fs28.default.readFileSync(filePath, "utf8");
|
|
10967
11081
|
const parsed = JSON.parse(raw);
|
|
10968
11082
|
if (parsed?.version !== 1 || typeof parsed.deviceId !== "string") return null;
|
|
10969
11083
|
if (!parsed.tokens || typeof parsed.tokens !== "object") return null;
|
|
@@ -10974,12 +11088,12 @@ function readDeviceAuthStore(filePath) {
|
|
|
10974
11088
|
}
|
|
10975
11089
|
function writeDeviceAuthStore(filePath, store) {
|
|
10976
11090
|
ensureDir(filePath);
|
|
10977
|
-
|
|
11091
|
+
import_node_fs28.default.writeFileSync(filePath, `${JSON.stringify(store, null, 2)}
|
|
10978
11092
|
`, {
|
|
10979
11093
|
mode: 384
|
|
10980
11094
|
});
|
|
10981
11095
|
try {
|
|
10982
|
-
|
|
11096
|
+
import_node_fs28.default.chmodSync(filePath, 384);
|
|
10983
11097
|
} catch {
|
|
10984
11098
|
}
|
|
10985
11099
|
}
|
|
@@ -11026,8 +11140,8 @@ function clearDeviceAuthToken(params) {
|
|
|
11026
11140
|
function loadOrCreateDeviceIdentity(stateDir) {
|
|
11027
11141
|
const filePath = resolveIdentityPath(stateDir);
|
|
11028
11142
|
try {
|
|
11029
|
-
if (
|
|
11030
|
-
const raw =
|
|
11143
|
+
if (import_node_fs28.default.existsSync(filePath)) {
|
|
11144
|
+
const raw = import_node_fs28.default.readFileSync(filePath, "utf8");
|
|
11031
11145
|
const parsed = JSON.parse(raw);
|
|
11032
11146
|
if (parsed?.version === 1 && typeof parsed.deviceId === "string" && typeof parsed.publicKeyPem === "string" && typeof parsed.privateKeyPem === "string") {
|
|
11033
11147
|
const derivedId = fingerprintPublicKey(parsed.publicKeyPem);
|
|
@@ -11048,14 +11162,14 @@ function loadOrCreateDeviceIdentity(stateDir) {
|
|
|
11048
11162
|
publicKeyPem,
|
|
11049
11163
|
privateKeyPem
|
|
11050
11164
|
};
|
|
11051
|
-
|
|
11165
|
+
import_node_fs28.default.mkdirSync(import_node_path24.default.dirname(filePath), { recursive: true });
|
|
11052
11166
|
const stored = {
|
|
11053
11167
|
version: 1,
|
|
11054
11168
|
...identity,
|
|
11055
11169
|
createdAtMs: Date.now()
|
|
11056
11170
|
};
|
|
11057
11171
|
ensureDir(filePath);
|
|
11058
|
-
|
|
11172
|
+
import_node_fs28.default.writeFileSync(filePath, `${JSON.stringify(stored, null, 2)}
|
|
11059
11173
|
`, {
|
|
11060
11174
|
mode: 384
|
|
11061
11175
|
});
|
|
@@ -11825,7 +11939,7 @@ function createTunnelService(opts) {
|
|
|
11825
11939
|
}
|
|
11826
11940
|
function readLockOwner(filePath) {
|
|
11827
11941
|
try {
|
|
11828
|
-
const parsed = JSON.parse((0,
|
|
11942
|
+
const parsed = JSON.parse((0, import_node_fs29.readFileSync)(filePath, "utf-8"));
|
|
11829
11943
|
return typeof parsed.pid === "number" ? parsed.pid : null;
|
|
11830
11944
|
} catch {
|
|
11831
11945
|
return null;
|
|
@@ -11838,23 +11952,23 @@ function createTunnelService(opts) {
|
|
|
11838
11952
|
lockFd = null;
|
|
11839
11953
|
if (fd !== null) {
|
|
11840
11954
|
try {
|
|
11841
|
-
(0,
|
|
11955
|
+
(0, import_node_fs29.closeSync)(fd);
|
|
11842
11956
|
} catch {
|
|
11843
11957
|
}
|
|
11844
11958
|
}
|
|
11845
11959
|
if (filePath) {
|
|
11846
11960
|
try {
|
|
11847
|
-
(0,
|
|
11961
|
+
(0, import_node_fs29.unlinkSync)(filePath);
|
|
11848
11962
|
} catch {
|
|
11849
11963
|
}
|
|
11850
11964
|
}
|
|
11851
11965
|
}
|
|
11852
11966
|
function acquireLock(filePath) {
|
|
11853
|
-
(0,
|
|
11967
|
+
(0, import_node_fs29.mkdirSync)((0, import_node_path25.dirname)(filePath), { recursive: true });
|
|
11854
11968
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
11855
11969
|
try {
|
|
11856
|
-
const fd = (0,
|
|
11857
|
-
(0,
|
|
11970
|
+
const fd = (0, import_node_fs29.openSync)(filePath, "wx", 384);
|
|
11971
|
+
(0, import_node_fs29.writeFileSync)(
|
|
11858
11972
|
fd,
|
|
11859
11973
|
JSON.stringify({
|
|
11860
11974
|
pid: process.pid,
|
|
@@ -11878,7 +11992,7 @@ function createTunnelService(opts) {
|
|
|
11878
11992
|
`Relay tunnel: removing stale local lock owned by dead pid=${ownerPid}`
|
|
11879
11993
|
);
|
|
11880
11994
|
try {
|
|
11881
|
-
(0,
|
|
11995
|
+
(0, import_node_fs29.unlinkSync)(filePath);
|
|
11882
11996
|
} catch {
|
|
11883
11997
|
}
|
|
11884
11998
|
continue;
|
|
@@ -11923,12 +12037,12 @@ function createTunnelService(opts) {
|
|
|
11923
12037
|
return;
|
|
11924
12038
|
}
|
|
11925
12039
|
const { logger } = opts;
|
|
11926
|
-
const baseStateDir = (0,
|
|
12040
|
+
const baseStateDir = (0, import_node_path25.join)(ctx.stateDir, "plugins", "phone-notifications");
|
|
11927
12041
|
logger.info(
|
|
11928
12042
|
`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})`
|
|
11929
12043
|
);
|
|
11930
|
-
const statusFilePath = (0,
|
|
11931
|
-
const lockPath = (0,
|
|
12044
|
+
const statusFilePath = (0, import_node_path25.join)(baseStateDir, "tunnel-status.json");
|
|
12045
|
+
const lockPath = (0, import_node_path25.join)(baseStateDir, "relay-tunnel.lock");
|
|
11932
12046
|
if (!acquireLock(lockPath)) {
|
|
11933
12047
|
return;
|
|
11934
12048
|
}
|
|
@@ -12068,7 +12182,7 @@ function readHostGatewayConfig(params) {
|
|
|
12068
12182
|
let configData;
|
|
12069
12183
|
if (configPath) {
|
|
12070
12184
|
try {
|
|
12071
|
-
configData = JSON.parse((0,
|
|
12185
|
+
configData = JSON.parse((0, import_node_fs30.readFileSync)(configPath, "utf-8"));
|
|
12072
12186
|
} catch (err) {
|
|
12073
12187
|
if (err?.code !== "ENOENT") {
|
|
12074
12188
|
params.logger.warn(
|