@yoooclaw/phone-notifications 1.10.2 → 1.10.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
CHANGED
|
@@ -206,9 +206,38 @@ var init_credentials = __esm({
|
|
|
206
206
|
});
|
|
207
207
|
|
|
208
208
|
// src/env.ts
|
|
209
|
+
function writeDotEnv(key, value) {
|
|
210
|
+
const path2 = resolveStateFile(".env");
|
|
211
|
+
(0, import_node_fs9.mkdirSync)((0, import_node_path8.dirname)(path2), { recursive: true });
|
|
212
|
+
const existing = (0, import_node_fs9.existsSync)(path2) ? (0, import_node_fs9.readFileSync)(path2, "utf-8") : "";
|
|
213
|
+
const lines = existing.split("\n");
|
|
214
|
+
const prefix = `${key}=`;
|
|
215
|
+
const idx = lines.findIndex((l) => l.startsWith(prefix));
|
|
216
|
+
const newLine = `${prefix}${value}`;
|
|
217
|
+
if (idx >= 0) {
|
|
218
|
+
lines[idx] = newLine;
|
|
219
|
+
} else {
|
|
220
|
+
if (existing && !existing.endsWith("\n")) lines.push("");
|
|
221
|
+
lines.push(newLine);
|
|
222
|
+
}
|
|
223
|
+
(0, import_node_fs9.writeFileSync)(path2, lines.join("\n"), "utf-8");
|
|
224
|
+
}
|
|
225
|
+
function readDotEnv() {
|
|
226
|
+
const path2 = resolveStateFile(".env");
|
|
227
|
+
if (!(0, import_node_fs9.existsSync)(path2)) return {};
|
|
228
|
+
return Object.fromEntries(
|
|
229
|
+
(0, import_node_fs9.readFileSync)(path2, "utf-8").split("\n").flatMap((line) => {
|
|
230
|
+
const eq = line.indexOf("=");
|
|
231
|
+
if (eq < 1) return [];
|
|
232
|
+
return [[line.slice(0, eq).trim(), line.slice(eq + 1).trim()]];
|
|
233
|
+
})
|
|
234
|
+
);
|
|
235
|
+
}
|
|
209
236
|
function loadEnvName() {
|
|
210
|
-
const fromEnvVar = process.env.
|
|
237
|
+
const fromEnvVar = process.env.PHONE_NOTIFICATIONS_ENV?.trim();
|
|
211
238
|
if (fromEnvVar && VALID_ENVS.has(fromEnvVar)) return fromEnvVar;
|
|
239
|
+
const fromDotEnv = readDotEnv()["PHONE_NOTIFICATIONS_ENV"]?.trim();
|
|
240
|
+
if (fromDotEnv && VALID_ENVS.has(fromDotEnv)) return fromDotEnv;
|
|
212
241
|
const { env } = readCredentials();
|
|
213
242
|
if (env && VALID_ENVS.has(env)) return env;
|
|
214
243
|
return "production";
|
|
@@ -219,7 +248,7 @@ function saveEnvName(env) {
|
|
|
219
248
|
`\u65E0\u6548\u7684\u73AF\u5883\u540D\u79F0: ${env}\uFF0C\u53EF\u9009\u503C: ${[...VALID_ENVS].join(", ")}`
|
|
220
249
|
);
|
|
221
250
|
}
|
|
222
|
-
|
|
251
|
+
writeDotEnv("PHONE_NOTIFICATIONS_ENV", env);
|
|
223
252
|
}
|
|
224
253
|
function getEnvUrls(env) {
|
|
225
254
|
return ENV_CONFIG[env ?? loadEnvName()];
|
|
@@ -227,11 +256,14 @@ function getEnvUrls(env) {
|
|
|
227
256
|
function getAvailableEnvs() {
|
|
228
257
|
return Object.keys(ENV_CONFIG);
|
|
229
258
|
}
|
|
230
|
-
var ENV_CONFIG, VALID_ENVS;
|
|
259
|
+
var import_node_fs9, import_node_path8, ENV_CONFIG, VALID_ENVS;
|
|
231
260
|
var init_env = __esm({
|
|
232
261
|
"src/env.ts"() {
|
|
233
262
|
"use strict";
|
|
263
|
+
import_node_fs9 = require("fs");
|
|
264
|
+
import_node_path8 = require("path");
|
|
234
265
|
init_credentials();
|
|
266
|
+
init_host();
|
|
235
267
|
ENV_CONFIG = {
|
|
236
268
|
development: {
|
|
237
269
|
lightApiUrl: "https://openclaw-service-dev.yoooclaw.com/api/message/tob/sendMessage",
|
|
@@ -461,8 +493,8 @@ __export(whisper_local_exports, {
|
|
|
461
493
|
transcribeWithWhisperLocal: () => transcribeWithWhisperLocal
|
|
462
494
|
});
|
|
463
495
|
function detectEnvironment(logger) {
|
|
464
|
-
const os2 = (0,
|
|
465
|
-
const cpuArch = (0,
|
|
496
|
+
const os2 = (0, import_node_os4.platform)();
|
|
497
|
+
const cpuArch = (0, import_node_os4.arch)();
|
|
466
498
|
const isAppleSilicon = os2 === "darwin" && cpuArch === "arm64";
|
|
467
499
|
const hasCuda = detectCuda(logger);
|
|
468
500
|
let recommendedBackend;
|
|
@@ -500,20 +532,20 @@ function selectModelByMemory(availableGB, isAppleSilicon = false) {
|
|
|
500
532
|
return "tiny";
|
|
501
533
|
}
|
|
502
534
|
function resolveModelsDir(dataDir) {
|
|
503
|
-
const dir = (0,
|
|
504
|
-
(0,
|
|
535
|
+
const dir = (0, import_node_path22.join)(dataDir, WHISPER_MODELS_DIR);
|
|
536
|
+
(0, import_node_fs26.mkdirSync)(dir, { recursive: true });
|
|
505
537
|
return dir;
|
|
506
538
|
}
|
|
507
539
|
function resolveBinDir(dataDir) {
|
|
508
|
-
const dir = (0,
|
|
509
|
-
(0,
|
|
540
|
+
const dir = (0, import_node_path22.join)(dataDir, WHISPER_BIN_DIR);
|
|
541
|
+
(0, import_node_fs26.mkdirSync)(dir, { recursive: true });
|
|
510
542
|
return dir;
|
|
511
543
|
}
|
|
512
544
|
function isModelDownloaded(modelsDir, modelSize) {
|
|
513
|
-
const modelPath = (0,
|
|
514
|
-
if (!(0,
|
|
545
|
+
const modelPath = (0, import_node_path22.join)(modelsDir, MODEL_FILENAMES[modelSize]);
|
|
546
|
+
if (!(0, import_node_fs26.existsSync)(modelPath)) return false;
|
|
515
547
|
try {
|
|
516
|
-
const stat = (0,
|
|
548
|
+
const stat = (0, import_node_fs26.statSync)(modelPath);
|
|
517
549
|
const expectedSize = MODEL_DISK_SIZES[modelSize];
|
|
518
550
|
return stat.size >= expectedSize * 0.8;
|
|
519
551
|
} catch {
|
|
@@ -522,7 +554,7 @@ function isModelDownloaded(modelsDir, modelSize) {
|
|
|
522
554
|
}
|
|
523
555
|
async function downloadModel(modelsDir, modelSize, logger, modelSource, mirrorUrl) {
|
|
524
556
|
const filename = MODEL_FILENAMES[modelSize];
|
|
525
|
-
const modelPath = (0,
|
|
557
|
+
const modelPath = (0, import_node_path22.join)(modelsDir, filename);
|
|
526
558
|
if (isModelDownloaded(modelsDir, modelSize)) {
|
|
527
559
|
logger.info(`[whisper-local] \u6A21\u578B\u5DF2\u5B58\u5728\uFF0C\u8DF3\u8FC7\u4E0B\u8F7D: ${filename}`);
|
|
528
560
|
return { ok: true, modelPath };
|
|
@@ -588,7 +620,7 @@ async function probeUrl(url, logger) {
|
|
|
588
620
|
async function downloadFromUrl(url, modelPath, logger) {
|
|
589
621
|
const tmpPath = `${modelPath}.downloading`;
|
|
590
622
|
try {
|
|
591
|
-
(0,
|
|
623
|
+
(0, import_node_fs26.mkdirSync)((0, import_node_path22.dirname)(modelPath), { recursive: true });
|
|
592
624
|
const controller = new AbortController();
|
|
593
625
|
const timer = setTimeout(() => controller.abort(), 30 * 60 * 1e3);
|
|
594
626
|
try {
|
|
@@ -604,7 +636,7 @@ async function downloadFromUrl(url, modelPath, logger) {
|
|
|
604
636
|
return { ok: false, modelPath, error: "\u6A21\u578B\u4E0B\u8F7D\u5931\u8D25: \u54CD\u5E94\u4F53\u4E3A\u7A7A" };
|
|
605
637
|
}
|
|
606
638
|
const contentLength = Number(res.headers.get("content-length") ?? 0);
|
|
607
|
-
const writeStream = (0,
|
|
639
|
+
const writeStream = (0, import_node_fs26.createWriteStream)(tmpPath);
|
|
608
640
|
const readable = import_node_stream2.Readable.fromWeb(res.body);
|
|
609
641
|
let downloaded = 0;
|
|
610
642
|
let lastLogPercent = 0;
|
|
@@ -624,16 +656,16 @@ async function downloadFromUrl(url, modelPath, logger) {
|
|
|
624
656
|
} finally {
|
|
625
657
|
clearTimeout(timer);
|
|
626
658
|
}
|
|
627
|
-
const { renameSync } = await import("fs");
|
|
628
|
-
|
|
629
|
-
const fileSize = (0,
|
|
659
|
+
const { renameSync: renameSync2 } = await import("fs");
|
|
660
|
+
renameSync2(tmpPath, modelPath);
|
|
661
|
+
const fileSize = (0, import_node_fs26.statSync)(modelPath).size;
|
|
630
662
|
logger.info(
|
|
631
|
-
`[whisper-local] \u6A21\u578B\u4E0B\u8F7D\u5B8C\u6210: ${(0,
|
|
663
|
+
`[whisper-local] \u6A21\u578B\u4E0B\u8F7D\u5B8C\u6210: ${(0, import_node_path22.basename)(modelPath)} (${formatBytes2(fileSize)})`
|
|
632
664
|
);
|
|
633
665
|
return { ok: true, modelPath };
|
|
634
666
|
} catch (err) {
|
|
635
667
|
try {
|
|
636
|
-
if ((0,
|
|
668
|
+
if ((0, import_node_fs26.existsSync)(tmpPath)) (0, import_node_fs26.unlinkSync)(tmpPath);
|
|
637
669
|
} catch {
|
|
638
670
|
}
|
|
639
671
|
const msg = err?.name === "AbortError" ? "\u6A21\u578B\u4E0B\u8F7D\u8D85\u65F6\uFF0830 \u5206\u949F\uFF09" : err?.message ?? String(err);
|
|
@@ -643,18 +675,18 @@ async function downloadFromUrl(url, modelPath, logger) {
|
|
|
643
675
|
}
|
|
644
676
|
function findWhisperBinary(dataDir, logger) {
|
|
645
677
|
const binDir = resolveBinDir(dataDir);
|
|
646
|
-
const binNames = (0,
|
|
678
|
+
const binNames = (0, import_node_os4.platform)() === "win32" ? ["whisper-cli.exe", "whisper.exe", "main.exe"] : ["whisper-cli", "whisper", "main"];
|
|
647
679
|
for (const name of binNames) {
|
|
648
|
-
const binPath = (0,
|
|
649
|
-
if ((0,
|
|
680
|
+
const binPath = (0, import_node_path22.join)(binDir, name);
|
|
681
|
+
if ((0, import_node_fs26.existsSync)(binPath)) {
|
|
650
682
|
logger.info(`[whisper-local] \u627E\u5230\u672C\u5730\u4E8C\u8FDB\u5236: ${binPath}`);
|
|
651
683
|
return binPath;
|
|
652
684
|
}
|
|
653
685
|
}
|
|
654
|
-
const pathNames = (0,
|
|
686
|
+
const pathNames = (0, import_node_os4.platform)() === "win32" ? ["whisper-cli", "whisper-cpp", "whisper"] : ["whisper-cli", "whisper-cpp", "whisper"];
|
|
655
687
|
for (const name of pathNames) {
|
|
656
688
|
try {
|
|
657
|
-
const cmd = (0,
|
|
689
|
+
const cmd = (0, import_node_os4.platform)() === "win32" ? "where" : "which";
|
|
658
690
|
const result = (0, import_node_child_process2.execSync)(`${cmd} ${name}`, { encoding: "utf-8", stdio: "pipe" }).trim();
|
|
659
691
|
if (result) {
|
|
660
692
|
logger.info(`[whisper-local] \u627E\u5230\u7CFB\u7EDF PATH \u4E8C\u8FDB\u5236: ${result}`);
|
|
@@ -697,7 +729,7 @@ async function transcribeWithWhisperLocal(audioFilePath, localConfig, dataDir, l
|
|
|
697
729
|
return { ok: false, error: `\u6A21\u578B\u4E0B\u8F7D\u5931\u8D25: ${downloadResult.error}` };
|
|
698
730
|
}
|
|
699
731
|
}
|
|
700
|
-
const modelPath = (0,
|
|
732
|
+
const modelPath = (0, import_node_path22.join)(modelsDir, MODEL_FILENAMES[modelSize]);
|
|
701
733
|
let inputPath = audioFilePath;
|
|
702
734
|
let tmpWavPath = null;
|
|
703
735
|
const actualFmt = detectAudioFormat(audioFilePath);
|
|
@@ -749,10 +781,10 @@ async function transcribeWithWhisperLocal(audioFilePath, localConfig, dataDir, l
|
|
|
749
781
|
logger.info(`[whisper-local] \u8F6C\u5199\u8017\u65F6: ${Math.round(elapsed / 1e3)}s`);
|
|
750
782
|
const jsonPath = inputPath + ".json";
|
|
751
783
|
let jsonContent;
|
|
752
|
-
if ((0,
|
|
753
|
-
jsonContent = (0,
|
|
784
|
+
if ((0, import_node_fs26.existsSync)(jsonPath)) {
|
|
785
|
+
jsonContent = (0, import_node_fs26.readFileSync)(jsonPath, "utf-8");
|
|
754
786
|
try {
|
|
755
|
-
(0,
|
|
787
|
+
(0, import_node_fs26.unlinkSync)(jsonPath);
|
|
756
788
|
} catch {
|
|
757
789
|
}
|
|
758
790
|
} else {
|
|
@@ -785,7 +817,7 @@ function detectCuda(logger) {
|
|
|
785
817
|
return true;
|
|
786
818
|
} catch {
|
|
787
819
|
}
|
|
788
|
-
if ((0,
|
|
820
|
+
if ((0, import_node_os4.platform)() === "linux") {
|
|
789
821
|
try {
|
|
790
822
|
const ldconfig = (0, import_node_child_process2.execSync)("ldconfig -p 2>/dev/null | grep libcudart", {
|
|
791
823
|
encoding: "utf-8",
|
|
@@ -816,24 +848,24 @@ function getAvailableMemoryGB(backend, logger) {
|
|
|
816
848
|
logger.warn("[whisper-local] \u65E0\u6CD5\u83B7\u53D6 GPU VRAM\uFF0C\u4F7F\u7528\u7CFB\u7EDF RAM \u4EE3\u66FF");
|
|
817
849
|
}
|
|
818
850
|
}
|
|
819
|
-
const totalGB = (0,
|
|
820
|
-
const freeGB = (0,
|
|
851
|
+
const totalGB = (0, import_node_os4.totalmem)() / (1024 * 1024 * 1024);
|
|
852
|
+
const freeGB = (0, import_node_os4.freemem)() / (1024 * 1024 * 1024);
|
|
821
853
|
return Math.max(freeGB, totalGB * 0.6);
|
|
822
854
|
}
|
|
823
855
|
function getPhysicalCoreCount() {
|
|
824
|
-
const cpuList = (0,
|
|
856
|
+
const cpuList = (0, import_node_os4.cpus)();
|
|
825
857
|
if (cpuList.length === 0) return 4;
|
|
826
|
-
if ((0,
|
|
858
|
+
if ((0, import_node_os4.platform)() === "darwin" && (0, import_node_os4.arch)() === "arm64") {
|
|
827
859
|
return cpuList.length;
|
|
828
860
|
}
|
|
829
861
|
return Math.max(1, Math.floor(cpuList.length / 2));
|
|
830
862
|
}
|
|
831
863
|
function detectAudioFormat(filePath) {
|
|
832
864
|
try {
|
|
833
|
-
const fd = (0,
|
|
865
|
+
const fd = (0, import_node_fs26.openSync)(filePath, "r");
|
|
834
866
|
const buf = Buffer.alloc(12);
|
|
835
|
-
(0,
|
|
836
|
-
(0,
|
|
867
|
+
(0, import_node_fs26.readSync)(fd, buf, 0, 12, 0);
|
|
868
|
+
(0, import_node_fs26.closeSync)(fd);
|
|
837
869
|
const header = buf.toString("ascii", 0, 4);
|
|
838
870
|
const header8 = buf.toString("ascii", 0, 8);
|
|
839
871
|
if (header === "RIFF" && buf.toString("ascii", 8, 12) === "WAVE") return ".wav";
|
|
@@ -868,7 +900,7 @@ function convertToWav(inputPath, outputPath, actualFmt, logger) {
|
|
|
868
900
|
timeout: 12e4,
|
|
869
901
|
stdio: ["pipe", "pipe", "pipe"]
|
|
870
902
|
});
|
|
871
|
-
if (ffmpegResult.status === 0 && (0,
|
|
903
|
+
if (ffmpegResult.status === 0 && (0, import_node_fs26.existsSync)(outputPath)) {
|
|
872
904
|
logger.info(`[whisper-local] ffmpeg \u8F6C\u6362\u5B8C\u6210: ${outputPath}`);
|
|
873
905
|
return { ok: true };
|
|
874
906
|
}
|
|
@@ -881,7 +913,7 @@ function convertToWav(inputPath, outputPath, actualFmt, logger) {
|
|
|
881
913
|
["--rate", "16000", "--mono", inputPath, outputPath],
|
|
882
914
|
{ encoding: "utf-8", timeout: 12e4, stdio: ["pipe", "pipe", "pipe"] }
|
|
883
915
|
);
|
|
884
|
-
if (opusResult.status === 0 && (0,
|
|
916
|
+
if (opusResult.status === 0 && (0, import_node_fs26.existsSync)(outputPath)) {
|
|
885
917
|
logger.info(`[whisper-local] opusdec \u8F6C\u6362\u5B8C\u6210: ${outputPath}`);
|
|
886
918
|
return { ok: true };
|
|
887
919
|
}
|
|
@@ -895,7 +927,7 @@ function convertToWav(inputPath, outputPath, actualFmt, logger) {
|
|
|
895
927
|
if (detectedExt && !inputPath.endsWith(detectedExt)) {
|
|
896
928
|
tmpCopy = inputPath + ".detected" + detectedExt;
|
|
897
929
|
try {
|
|
898
|
-
(0,
|
|
930
|
+
(0, import_node_fs26.copyFileSync)(inputPath, tmpCopy);
|
|
899
931
|
actualInputPath = tmpCopy;
|
|
900
932
|
logger.info(
|
|
901
933
|
`[whisper-local] \u68C0\u6D4B\u5230\u5B9E\u9645\u683C\u5F0F ${detectedExt}\uFF0C\u4E34\u65F6\u91CD\u547D\u540D`
|
|
@@ -919,22 +951,22 @@ function convertToWav(inputPath, outputPath, actualFmt, logger) {
|
|
|
919
951
|
timeout: 12e4,
|
|
920
952
|
stdio: ["pipe", "pipe", "pipe"]
|
|
921
953
|
});
|
|
922
|
-
if (tmpCopy && (0,
|
|
954
|
+
if (tmpCopy && (0, import_node_fs26.existsSync)(tmpCopy)) {
|
|
923
955
|
try {
|
|
924
|
-
(0,
|
|
956
|
+
(0, import_node_fs26.unlinkSync)(tmpCopy);
|
|
925
957
|
} catch {
|
|
926
958
|
}
|
|
927
959
|
}
|
|
928
|
-
if (afResult.status === 0 && (0,
|
|
960
|
+
if (afResult.status === 0 && (0, import_node_fs26.existsSync)(outputPath)) {
|
|
929
961
|
logger.info(`[whisper-local] afconvert \u8F6C\u6362\u5B8C\u6210: ${outputPath}`);
|
|
930
962
|
return { ok: true };
|
|
931
963
|
}
|
|
932
964
|
const stderr = afResult.stderr?.slice(0, 200) ?? "";
|
|
933
965
|
return { ok: false, error: `afconvert \u8F6C\u6362\u5931\u8D25 (exit ${afResult.status}): ${stderr}` };
|
|
934
966
|
} catch (err) {
|
|
935
|
-
if (tmpCopy && (0,
|
|
967
|
+
if (tmpCopy && (0, import_node_fs26.existsSync)(tmpCopy)) {
|
|
936
968
|
try {
|
|
937
|
-
(0,
|
|
969
|
+
(0, import_node_fs26.unlinkSync)(tmpCopy);
|
|
938
970
|
} catch {
|
|
939
971
|
}
|
|
940
972
|
}
|
|
@@ -945,9 +977,9 @@ function convertToWav(inputPath, outputPath, actualFmt, logger) {
|
|
|
945
977
|
return { ok: false, error: `\u65E0\u6CD5\u5C06\u97F3\u9891\u8F6C\u6362\u4E3A WAV \u683C\u5F0F\u3002${fmtHint}` };
|
|
946
978
|
}
|
|
947
979
|
function cleanupTmpWav(path2) {
|
|
948
|
-
if (path2 && (0,
|
|
980
|
+
if (path2 && (0, import_node_fs26.existsSync)(path2)) {
|
|
949
981
|
try {
|
|
950
|
-
(0,
|
|
982
|
+
(0, import_node_fs26.unlinkSync)(path2);
|
|
951
983
|
} catch {
|
|
952
984
|
}
|
|
953
985
|
}
|
|
@@ -1033,16 +1065,16 @@ function formatBytes2(bytes) {
|
|
|
1033
1065
|
if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
1034
1066
|
return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)}GB`;
|
|
1035
1067
|
}
|
|
1036
|
-
var import_node_child_process2,
|
|
1068
|
+
var import_node_child_process2, import_node_fs26, import_node_path22, 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
1069
|
var init_whisper_local = __esm({
|
|
1038
1070
|
"src/recording/whisper-local.ts"() {
|
|
1039
1071
|
"use strict";
|
|
1040
1072
|
import_node_child_process2 = require("child_process");
|
|
1041
|
-
|
|
1042
|
-
|
|
1073
|
+
import_node_fs26 = require("fs");
|
|
1074
|
+
import_node_path22 = require("path");
|
|
1043
1075
|
import_promises3 = require("stream/promises");
|
|
1044
1076
|
import_node_stream2 = require("stream");
|
|
1045
|
-
|
|
1077
|
+
import_node_os4 = require("os");
|
|
1046
1078
|
WHISPER_MODELS_DIR = "whisper-models";
|
|
1047
1079
|
WHISPER_BIN_DIR = "whisper-bin";
|
|
1048
1080
|
HF_MODEL_URL_TEMPLATE = "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-{model}.bin";
|
|
@@ -1194,7 +1226,7 @@ async function initializeAsr(config, dataDir, logger) {
|
|
|
1194
1226
|
}
|
|
1195
1227
|
}
|
|
1196
1228
|
async function transcribeAudio(audioFilePath, config, logger, options = {}) {
|
|
1197
|
-
if (!(0,
|
|
1229
|
+
if (!(0, import_node_fs27.existsSync)(audioFilePath)) {
|
|
1198
1230
|
return { ok: false, error: `\u97F3\u9891\u6587\u4EF6\u4E0D\u5B58\u5728: ${audioFilePath}` };
|
|
1199
1231
|
}
|
|
1200
1232
|
logger.info(
|
|
@@ -1310,7 +1342,7 @@ async function runTranscriptionWorkflow(params) {
|
|
|
1310
1342
|
return { ok: false, error: result.error };
|
|
1311
1343
|
}
|
|
1312
1344
|
const title = normalizeOptionalText2(result.summary) ? normalizeOptionalText2(result.summary) : extractSummary(result.text ?? "");
|
|
1313
|
-
const summary = normalizeOptionalText2(result.summaryText)
|
|
1345
|
+
const summary = normalizeOptionalText2(result.summaryText);
|
|
1314
1346
|
result.summary = title;
|
|
1315
1347
|
const transcriptData = buildTranscriptDocument({
|
|
1316
1348
|
recordingId,
|
|
@@ -1338,8 +1370,8 @@ async function runTranscriptionWorkflow(params) {
|
|
|
1338
1370
|
createdAt
|
|
1339
1371
|
);
|
|
1340
1372
|
const transcriptDataFilename = buildTranscriptDataFilename(recordingId);
|
|
1341
|
-
const transcriptDataPath = (0,
|
|
1342
|
-
(0,
|
|
1373
|
+
const transcriptDataPath = (0, import_node_path23.join)(transcriptDataDir, transcriptDataFilename);
|
|
1374
|
+
(0, import_node_fs27.writeFileSync)(
|
|
1343
1375
|
transcriptDataPath,
|
|
1344
1376
|
JSON.stringify(transcriptData, null, 2),
|
|
1345
1377
|
"utf-8"
|
|
@@ -1347,13 +1379,16 @@ async function runTranscriptionWorkflow(params) {
|
|
|
1347
1379
|
logger.info(`[asr] \u8F6C\u5199 JSON \u5DF2\u5199\u5165: ${transcriptDataPath}`);
|
|
1348
1380
|
const safeSummary = title.replace(/[/\\:*?"<>|]/g, "").trim().slice(0, 20);
|
|
1349
1381
|
const filename = safeSummary ? `${recordingId}_${safeSummary}.md` : `${recordingId}.md`;
|
|
1350
|
-
const filePath = (0,
|
|
1351
|
-
(0,
|
|
1382
|
+
const filePath = (0, import_node_path23.join)(transcriptsDir, filename);
|
|
1383
|
+
(0, import_node_fs27.writeFileSync)(filePath, markdown, "utf-8");
|
|
1352
1384
|
logger.info(`[asr] \u8F6C\u5199\u6587\u672C\u5DF2\u5199\u5165: ${filePath}`);
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1385
|
+
let summaryFilename;
|
|
1386
|
+
if (summary) {
|
|
1387
|
+
summaryFilename = `${recordingId}.md`;
|
|
1388
|
+
const summaryFilePath = (0, import_node_path23.join)(summariesDir, summaryFilename);
|
|
1389
|
+
(0, import_node_fs27.writeFileSync)(summaryFilePath, summary, "utf-8");
|
|
1390
|
+
logger.info(`[asr] \u6458\u8981\u6587\u672C\u5DF2\u5199\u5165: ${summaryFilePath}`);
|
|
1391
|
+
}
|
|
1357
1392
|
return {
|
|
1358
1393
|
ok: true,
|
|
1359
1394
|
transcriptFilename: filename,
|
|
@@ -1436,7 +1471,7 @@ async function transcribeWithModelProxy(audioOssUrl, apiConfig, logger) {
|
|
|
1436
1471
|
}
|
|
1437
1472
|
async function transcribeWithWhisperLocal2(audioFilePath, config, logger) {
|
|
1438
1473
|
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,
|
|
1474
|
+
const dataDir = process.env.OPENCLAW_STATE_DIR ?? process.env.QCLAW_STATE_DIR ?? (0, import_node_path23.join)(audioFilePath, "..", "..", "..");
|
|
1440
1475
|
const localConfig = config.local ?? {};
|
|
1441
1476
|
const result = await runLocal(
|
|
1442
1477
|
audioFilePath,
|
|
@@ -1590,8 +1625,8 @@ function buildLongRecordingSuccessResult(taskId, requestId, data, logger) {
|
|
|
1590
1625
|
ok: true,
|
|
1591
1626
|
text,
|
|
1592
1627
|
segments: listResult.segments,
|
|
1593
|
-
summary: title
|
|
1594
|
-
summaryText
|
|
1628
|
+
summary: title,
|
|
1629
|
+
summaryText,
|
|
1595
1630
|
category,
|
|
1596
1631
|
sourceInfo: {
|
|
1597
1632
|
provider: "model-proxy",
|
|
@@ -1711,15 +1746,6 @@ function stringifyForLog(value, maxLength = 500) {
|
|
|
1711
1746
|
async function sleep2(ms) {
|
|
1712
1747
|
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
1713
1748
|
}
|
|
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
1749
|
function formatTimestamp(ms) {
|
|
1724
1750
|
const totalSeconds = Math.floor(ms / 1e3);
|
|
1725
1751
|
const minutes = Math.floor(totalSeconds / 60);
|
|
@@ -1748,12 +1774,12 @@ function formatTranscriptSegmentText(segment) {
|
|
|
1748
1774
|
}
|
|
1749
1775
|
return text;
|
|
1750
1776
|
}
|
|
1751
|
-
var
|
|
1777
|
+
var import_node_fs27, import_node_path23, DEFAULT_LONG_RECORDING_POLL_INTERVAL_MS, DEFAULT_LONG_RECORDING_MAX_POLL_ATTEMPTS, LONG_RECORDING_RUNNING_STATUSES, LONG_RECORDING_TERMINAL_FAILURE_STATUSES;
|
|
1752
1778
|
var init_asr = __esm({
|
|
1753
1779
|
"src/recording/asr.ts"() {
|
|
1754
1780
|
"use strict";
|
|
1755
|
-
|
|
1756
|
-
|
|
1781
|
+
import_node_fs27 = require("fs");
|
|
1782
|
+
import_node_path23 = require("path");
|
|
1757
1783
|
init_credentials();
|
|
1758
1784
|
init_env();
|
|
1759
1785
|
init_transcript_document();
|
|
@@ -5398,7 +5424,7 @@ function readBuildInjectedVersion() {
|
|
|
5398
5424
|
if (false) {
|
|
5399
5425
|
return void 0;
|
|
5400
5426
|
}
|
|
5401
|
-
const version = "1.10.
|
|
5427
|
+
const version = "1.10.4".trim();
|
|
5402
5428
|
return version || void 0;
|
|
5403
5429
|
}
|
|
5404
5430
|
function readPluginVersionFromPackageJson() {
|
|
@@ -7201,8 +7227,48 @@ function resolveUpdateChannel(params) {
|
|
|
7201
7227
|
return params.envName === "development" ? "beta" : "latest";
|
|
7202
7228
|
}
|
|
7203
7229
|
|
|
7230
|
+
// src/update/index.ts
|
|
7231
|
+
var import_node_path10 = require("path");
|
|
7232
|
+
|
|
7204
7233
|
// src/update/checker.ts
|
|
7205
|
-
|
|
7234
|
+
function parseSemver(v) {
|
|
7235
|
+
const [main, pre = null] = v.split("-", 2);
|
|
7236
|
+
const [major = 0, minor = 0, patch = 0] = main.split(".").map(Number);
|
|
7237
|
+
return { major, minor, patch, pre: pre ?? null };
|
|
7238
|
+
}
|
|
7239
|
+
function comparePreRelease(a, b) {
|
|
7240
|
+
const aParts = a.split(".");
|
|
7241
|
+
const bParts = b.split(".");
|
|
7242
|
+
for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {
|
|
7243
|
+
const ap = aParts[i] ?? "";
|
|
7244
|
+
const bp = bParts[i] ?? "";
|
|
7245
|
+
const an = Number(ap);
|
|
7246
|
+
const bn = Number(bp);
|
|
7247
|
+
let diff;
|
|
7248
|
+
if (!Number.isNaN(an) && !Number.isNaN(bn)) {
|
|
7249
|
+
diff = an - bn;
|
|
7250
|
+
} else if (ap < bp) {
|
|
7251
|
+
diff = -1;
|
|
7252
|
+
} else if (ap > bp) {
|
|
7253
|
+
diff = 1;
|
|
7254
|
+
} else {
|
|
7255
|
+
diff = 0;
|
|
7256
|
+
}
|
|
7257
|
+
if (diff !== 0) return diff;
|
|
7258
|
+
}
|
|
7259
|
+
return 0;
|
|
7260
|
+
}
|
|
7261
|
+
function isNewerVersion(candidate, current) {
|
|
7262
|
+
const a = parseSemver(candidate);
|
|
7263
|
+
const b = parseSemver(current);
|
|
7264
|
+
if (a.major !== b.major) return a.major > b.major;
|
|
7265
|
+
if (a.minor !== b.minor) return a.minor > b.minor;
|
|
7266
|
+
if (a.patch !== b.patch) return a.patch > b.patch;
|
|
7267
|
+
if (a.pre === null) return b.pre !== null;
|
|
7268
|
+
if (b.pre === null) return false;
|
|
7269
|
+
return comparePreRelease(a.pre, b.pre) > 0;
|
|
7270
|
+
}
|
|
7271
|
+
var CDN_BASE_URL = "https://artifact.yoooclaw.com/plugin";
|
|
7206
7272
|
var NPM_BASE_URL = "https://registry.npmjs.org/@yoooclaw/phone-notifications";
|
|
7207
7273
|
var FETCH_TIMEOUT_MS = 5e3;
|
|
7208
7274
|
var UpdateChecker = class {
|
|
@@ -7231,6 +7297,7 @@ var UpdateChecker = class {
|
|
|
7231
7297
|
if (!latest || latest === PLUGIN_VERSION) return;
|
|
7232
7298
|
if (latest === this.notifiedVersion) return;
|
|
7233
7299
|
if (PLUGIN_VERSION.includes("-") && this.channel !== "beta") return;
|
|
7300
|
+
if (!isNewerVersion(latest, PLUGIN_VERSION)) return;
|
|
7234
7301
|
this.notifiedVersion = latest;
|
|
7235
7302
|
this.logger.info(`\u53D1\u73B0\u65B0\u7248\u672C: ${PLUGIN_VERSION} \u2192 ${latest}`);
|
|
7236
7303
|
this.onUpdateFound({ current: PLUGIN_VERSION, latest });
|
|
@@ -7263,36 +7330,109 @@ var UpdateChecker = class {
|
|
|
7263
7330
|
};
|
|
7264
7331
|
|
|
7265
7332
|
// src/update/executor.ts
|
|
7333
|
+
var import_node_fs10 = require("fs");
|
|
7334
|
+
var import_node_path9 = require("path");
|
|
7335
|
+
var import_node_os = require("os");
|
|
7266
7336
|
var VERSION_PATTERN = /^\d+\.\d+\.\d+(-[\w.]+)?$/;
|
|
7267
|
-
|
|
7337
|
+
var BASE_URL = "https://artifact.yoooclaw.com/plugin";
|
|
7338
|
+
async function executeUpdate(version, runCommand, logger, targetDir, updateConfigRecord2) {
|
|
7268
7339
|
if (!VERSION_PATTERN.test(version)) {
|
|
7269
7340
|
return { success: false, message: `\u975E\u6CD5\u7248\u672C\u53F7: ${version}` };
|
|
7270
7341
|
}
|
|
7271
|
-
const
|
|
7272
|
-
|
|
7273
|
-
|
|
7274
|
-
|
|
7275
|
-
|
|
7276
|
-
|
|
7277
|
-
logger.info(`\u6267\u884C\u66F4\u65B0: ${argv.join(" ")}`);
|
|
7342
|
+
const tgzUrl = `${BASE_URL}/v${version}/yoooclaw-phone-notifications-${version}.tgz`;
|
|
7343
|
+
logger.info(`\u6267\u884C\u66F4\u65B0: ${tgzUrl} \u2192 ${targetDir}`);
|
|
7344
|
+
const workDir = (0, import_node_fs10.mkdtempSync)((0, import_node_path9.join)((0, import_node_os.tmpdir)(), ".openclaw-plugin-update-"));
|
|
7345
|
+
const tgzPath = (0, import_node_path9.join)(workDir, "plugin.tgz");
|
|
7346
|
+
const stagingDir = (0, import_node_path9.join)(workDir, "staged");
|
|
7347
|
+
let backupDir = null;
|
|
7278
7348
|
try {
|
|
7279
|
-
|
|
7280
|
-
|
|
7281
|
-
|
|
7282
|
-
|
|
7283
|
-
|
|
7349
|
+
logger.info("\u4E0B\u8F7D\u63D2\u4EF6\u5305...");
|
|
7350
|
+
const response = await fetch(tgzUrl, { signal: AbortSignal.timeout(6e4) });
|
|
7351
|
+
if (!response.ok) {
|
|
7352
|
+
return { success: false, message: `\u4E0B\u8F7D\u5931\u8D25 (HTTP ${response.status}): ${tgzUrl}` };
|
|
7353
|
+
}
|
|
7354
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
7355
|
+
(0, import_node_fs10.writeFileSync)(tgzPath, buffer);
|
|
7356
|
+
logger.info(`\u4E0B\u8F7D\u5B8C\u6210 (${buffer.length} bytes)`);
|
|
7357
|
+
(0, import_node_fs10.mkdirSync)(stagingDir, { recursive: true });
|
|
7358
|
+
const tarResult = await runCommand(
|
|
7359
|
+
["tar", "-xzf", tgzPath, "-C", stagingDir, "--strip-components=1"],
|
|
7360
|
+
{ timeoutMs: 3e4 }
|
|
7361
|
+
);
|
|
7362
|
+
if (tarResult.code !== 0) {
|
|
7363
|
+
const err = tarResult.stderr || tarResult.stdout || "unknown error";
|
|
7364
|
+
return { success: false, message: `\u89E3\u538B\u5931\u8D25: ${err}` };
|
|
7284
7365
|
}
|
|
7285
|
-
|
|
7286
|
-
|
|
7287
|
-
|
|
7366
|
+
(0, import_node_fs10.mkdirSync)((0, import_node_path9.dirname)(targetDir), { recursive: true });
|
|
7367
|
+
try {
|
|
7368
|
+
backupDir = `${targetDir}.bak.${Date.now()}`;
|
|
7369
|
+
(0, import_node_fs10.renameSync)(targetDir, backupDir);
|
|
7370
|
+
} catch {
|
|
7371
|
+
backupDir = null;
|
|
7372
|
+
}
|
|
7373
|
+
(0, import_node_fs10.renameSync)(stagingDir, targetDir);
|
|
7374
|
+
try {
|
|
7375
|
+
await updateConfigRecord2(version, tgzUrl);
|
|
7376
|
+
} catch (err) {
|
|
7377
|
+
logger.warn(`\u914D\u7F6E\u8BB0\u5F55\u66F4\u65B0\u5931\u8D25\uFF08\u63D2\u4EF6\u6587\u4EF6\u5DF2\u5C31\u4F4D\uFF09: ${String(err)}`);
|
|
7378
|
+
}
|
|
7379
|
+
if (backupDir) {
|
|
7380
|
+
try {
|
|
7381
|
+
(0, import_node_fs10.rmSync)(backupDir, { force: true, recursive: true });
|
|
7382
|
+
} catch {
|
|
7383
|
+
}
|
|
7384
|
+
}
|
|
7385
|
+
const msg = `\u5DF2\u66F4\u65B0\u5230 ${version}\uFF0C\u8BF7\u91CD\u542F gateway \u751F\u6548`;
|
|
7386
|
+
logger.info(msg);
|
|
7387
|
+
return { success: true, message: msg };
|
|
7288
7388
|
} catch (err) {
|
|
7289
|
-
|
|
7389
|
+
if (backupDir) {
|
|
7390
|
+
try {
|
|
7391
|
+
(0, import_node_fs10.rmSync)(targetDir, { force: true, recursive: true });
|
|
7392
|
+
(0, import_node_fs10.renameSync)(backupDir, targetDir);
|
|
7393
|
+
logger.info("\u5DF2\u56DE\u6EDA\u5230\u4E4B\u524D\u7248\u672C");
|
|
7394
|
+
} catch (rollbackErr) {
|
|
7395
|
+
logger.error(`\u56DE\u6EDA\u5931\u8D25: ${String(rollbackErr)}`);
|
|
7396
|
+
}
|
|
7397
|
+
}
|
|
7398
|
+
const errMsg = `\u66F4\u65B0\u6267\u884C\u5F02\u5E38: ${String(err)}`;
|
|
7290
7399
|
logger.error(errMsg);
|
|
7291
7400
|
return { success: false, message: errMsg };
|
|
7401
|
+
} finally {
|
|
7402
|
+
try {
|
|
7403
|
+
(0, import_node_fs10.rmSync)(workDir, { force: true, recursive: true });
|
|
7404
|
+
} catch {
|
|
7405
|
+
}
|
|
7292
7406
|
}
|
|
7293
7407
|
}
|
|
7294
7408
|
|
|
7295
7409
|
// src/update/index.ts
|
|
7410
|
+
var PLUGIN_ID = "phone-notifications";
|
|
7411
|
+
function resolveTargetDir(api) {
|
|
7412
|
+
try {
|
|
7413
|
+
const cfg = api.runtime.config?.loadConfig?.();
|
|
7414
|
+
const installPath = cfg?.plugins?.installs?.[PLUGIN_ID]?.installPath;
|
|
7415
|
+
if (installPath) return installPath;
|
|
7416
|
+
} catch {
|
|
7417
|
+
}
|
|
7418
|
+
return (0, import_node_path10.join)(api.runtime.state.resolveStateDir(), "extensions", PLUGIN_ID);
|
|
7419
|
+
}
|
|
7420
|
+
async function updateConfigRecord(api, version, targetDir, tgzUrl) {
|
|
7421
|
+
const configApi = api.runtime.config;
|
|
7422
|
+
if (!configApi) return;
|
|
7423
|
+
const cfg = configApi.loadConfig();
|
|
7424
|
+
if (!cfg.plugins) cfg.plugins = {};
|
|
7425
|
+
if (!cfg.plugins.installs) cfg.plugins.installs = {};
|
|
7426
|
+
cfg.plugins.installs[PLUGIN_ID] = {
|
|
7427
|
+
...cfg.plugins.installs[PLUGIN_ID],
|
|
7428
|
+
source: "archive",
|
|
7429
|
+
sourcePath: tgzUrl,
|
|
7430
|
+
installPath: targetDir,
|
|
7431
|
+
version,
|
|
7432
|
+
installedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
7433
|
+
};
|
|
7434
|
+
await configApi.writeConfigFile(cfg);
|
|
7435
|
+
}
|
|
7296
7436
|
function registerAutoUpdate(api, logger, config, getBroadcast, rememberBroadcast, externalUpdateNotifier) {
|
|
7297
7437
|
if (config.enabled === false) {
|
|
7298
7438
|
logger.info("\u81EA\u52A8\u66F4\u65B0\u5DF2\u7981\u7528 (autoUpdate.enabled = false)");
|
|
@@ -7338,10 +7478,13 @@ function registerAutoUpdate(api, logger, config, getBroadcast, rememberBroadcast
|
|
|
7338
7478
|
},
|
|
7339
7479
|
async execute(_toolCallId, params) {
|
|
7340
7480
|
const { version } = params;
|
|
7481
|
+
const targetDir = resolveTargetDir(api);
|
|
7341
7482
|
const result = await executeUpdate(
|
|
7342
7483
|
version,
|
|
7343
7484
|
api.runtime.system.runCommandWithTimeout,
|
|
7344
|
-
logger
|
|
7485
|
+
logger,
|
|
7486
|
+
targetDir,
|
|
7487
|
+
(v, url) => updateConfigRecord(api, v, targetDir, url)
|
|
7345
7488
|
);
|
|
7346
7489
|
if (result.success) {
|
|
7347
7490
|
pendingUpdate = null;
|
|
@@ -7363,10 +7506,13 @@ function registerAutoUpdate(api, logger, config, getBroadcast, rememberBroadcast
|
|
|
7363
7506
|
});
|
|
7364
7507
|
return;
|
|
7365
7508
|
}
|
|
7509
|
+
const targetDir = resolveTargetDir(api);
|
|
7366
7510
|
const result = await executeUpdate(
|
|
7367
7511
|
version,
|
|
7368
7512
|
api.runtime.system.runCommandWithTimeout,
|
|
7369
|
-
logger
|
|
7513
|
+
logger,
|
|
7514
|
+
targetDir,
|
|
7515
|
+
(v, url) => updateConfigRecord(api, v, targetDir, url)
|
|
7370
7516
|
);
|
|
7371
7517
|
if (result.success) {
|
|
7372
7518
|
pendingUpdate = null;
|
|
@@ -7457,10 +7603,10 @@ function registerAutoUpdateLifecycle(deps) {
|
|
|
7457
7603
|
}
|
|
7458
7604
|
|
|
7459
7605
|
// src/plugin/cli.ts
|
|
7460
|
-
var
|
|
7606
|
+
var import_node_path18 = require("path");
|
|
7461
7607
|
|
|
7462
7608
|
// src/cli/auth.ts
|
|
7463
|
-
var
|
|
7609
|
+
var import_node_fs11 = require("fs");
|
|
7464
7610
|
init_credentials();
|
|
7465
7611
|
function registerAuthCli(program) {
|
|
7466
7612
|
const auth = program.command("auth").description("\u7528\u6237\u8BA4\u8BC1\u7BA1\u7406");
|
|
@@ -7496,12 +7642,12 @@ function registerAuthCli(program) {
|
|
|
7496
7642
|
});
|
|
7497
7643
|
auth.command("clear").description("\u6E05\u9664\u5DF2\u4FDD\u5B58\u7684\u8BA4\u8BC1\u4FE1\u606F").action(() => {
|
|
7498
7644
|
const path2 = credentialsPath();
|
|
7499
|
-
if ((0,
|
|
7645
|
+
if ((0, import_node_fs11.existsSync)(path2)) {
|
|
7500
7646
|
const creds = readCredentials();
|
|
7501
7647
|
delete creds.apiKey;
|
|
7502
7648
|
delete creds.token;
|
|
7503
7649
|
if (Object.keys(creds).length === 0) {
|
|
7504
|
-
(0,
|
|
7650
|
+
(0, import_node_fs11.rmSync)(path2, { force: true });
|
|
7505
7651
|
} else {
|
|
7506
7652
|
writeCredentials(creds);
|
|
7507
7653
|
}
|
|
@@ -7633,23 +7779,23 @@ function registerNtfStats(ntf, ctx) {
|
|
|
7633
7779
|
}
|
|
7634
7780
|
|
|
7635
7781
|
// src/cli/ntf-sync.ts
|
|
7636
|
-
var
|
|
7637
|
-
var
|
|
7782
|
+
var import_node_fs12 = require("fs");
|
|
7783
|
+
var import_node_path11 = require("path");
|
|
7638
7784
|
var SYNC_FETCH_LIMIT = 300;
|
|
7639
7785
|
function checkpointPath(dir) {
|
|
7640
|
-
return (0,
|
|
7786
|
+
return (0, import_node_path11.join)(dir, ".checkpoint.json");
|
|
7641
7787
|
}
|
|
7642
7788
|
function readCheckpoint(dir) {
|
|
7643
7789
|
const p = checkpointPath(dir);
|
|
7644
|
-
if (!(0,
|
|
7790
|
+
if (!(0, import_node_fs12.existsSync)(p)) return {};
|
|
7645
7791
|
try {
|
|
7646
|
-
return JSON.parse((0,
|
|
7792
|
+
return JSON.parse((0, import_node_fs12.readFileSync)(p, "utf-8"));
|
|
7647
7793
|
} catch {
|
|
7648
7794
|
return {};
|
|
7649
7795
|
}
|
|
7650
7796
|
}
|
|
7651
7797
|
function writeCheckpoint(dir, data) {
|
|
7652
|
-
(0,
|
|
7798
|
+
(0, import_node_fs12.writeFileSync)(checkpointPath(dir), JSON.stringify(data, null, 2), "utf-8");
|
|
7653
7799
|
}
|
|
7654
7800
|
function registerNtfSync(ntf, ctx) {
|
|
7655
7801
|
const sync = ntf.command("sync").description("\u540C\u6B65\u901A\u77E5\u5230\u8BB0\u5FC6\u7CFB\u7EDF");
|
|
@@ -7742,24 +7888,24 @@ function registerNtfSync(ntf, ctx) {
|
|
|
7742
7888
|
}
|
|
7743
7889
|
|
|
7744
7890
|
// src/cli/ntf-monitor.ts
|
|
7745
|
-
var
|
|
7746
|
-
var
|
|
7891
|
+
var import_node_fs13 = require("fs");
|
|
7892
|
+
var import_node_path12 = require("path");
|
|
7747
7893
|
function tasksDir2(ctx) {
|
|
7748
7894
|
const base = ctx.workspaceDir || ctx.stateDir;
|
|
7749
7895
|
if (!base) throw new Error("workspaceDir and stateDir both unavailable");
|
|
7750
|
-
return (0,
|
|
7896
|
+
return (0, import_node_path12.join)(base, "tasks");
|
|
7751
7897
|
}
|
|
7752
7898
|
function readMeta2(taskDir) {
|
|
7753
|
-
const metaPath = (0,
|
|
7754
|
-
if (!(0,
|
|
7899
|
+
const metaPath = (0, import_node_path12.join)(taskDir, "meta.json");
|
|
7900
|
+
if (!(0, import_node_fs13.existsSync)(metaPath)) return null;
|
|
7755
7901
|
try {
|
|
7756
|
-
return JSON.parse((0,
|
|
7902
|
+
return JSON.parse((0, import_node_fs13.readFileSync)(metaPath, "utf-8"));
|
|
7757
7903
|
} catch {
|
|
7758
7904
|
return null;
|
|
7759
7905
|
}
|
|
7760
7906
|
}
|
|
7761
7907
|
function writeMeta2(taskDir, meta) {
|
|
7762
|
-
(0,
|
|
7908
|
+
(0, import_node_fs13.writeFileSync)((0, import_node_path12.join)(taskDir, "meta.json"), JSON.stringify(meta, null, 2), "utf-8");
|
|
7763
7909
|
}
|
|
7764
7910
|
function generateReadme(name, description) {
|
|
7765
7911
|
return `# Monitor Task: ${name}
|
|
@@ -7778,27 +7924,27 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
7778
7924
|
const monitor = ntf.command("monitor").description("\u901A\u77E5\u76D1\u63A7\u4EFB\u52A1\u7BA1\u7406");
|
|
7779
7925
|
monitor.command("list").description("\u5217\u51FA\u6240\u6709\u76D1\u63A7\u4EFB\u52A1").action(() => {
|
|
7780
7926
|
const dir = tasksDir2(ctx);
|
|
7781
|
-
if (!(0,
|
|
7927
|
+
if (!(0, import_node_fs13.existsSync)(dir)) {
|
|
7782
7928
|
output({ ok: true, tasks: [] });
|
|
7783
7929
|
return;
|
|
7784
7930
|
}
|
|
7785
7931
|
const tasks = [];
|
|
7786
|
-
for (const entry of (0,
|
|
7932
|
+
for (const entry of (0, import_node_fs13.readdirSync)(dir, { withFileTypes: true })) {
|
|
7787
7933
|
if (!entry.isDirectory()) continue;
|
|
7788
|
-
const meta = readMeta2((0,
|
|
7934
|
+
const meta = readMeta2((0, import_node_path12.join)(dir, entry.name));
|
|
7789
7935
|
if (meta) tasks.push(meta);
|
|
7790
7936
|
}
|
|
7791
7937
|
output({ ok: true, tasks });
|
|
7792
7938
|
});
|
|
7793
7939
|
monitor.command("show <name>").description("\u67E5\u770B\u76D1\u63A7\u4EFB\u52A1\u8BE6\u60C5").action((name) => {
|
|
7794
|
-
const taskDir = (0,
|
|
7940
|
+
const taskDir = (0, import_node_path12.join)(tasksDir2(ctx), name);
|
|
7795
7941
|
const meta = readMeta2(taskDir);
|
|
7796
7942
|
if (!meta) exitError("NOT_FOUND", `\u76D1\u63A7\u4EFB\u52A1 '${name}' \u4E0D\u5B58\u5728`);
|
|
7797
|
-
const checkpointPath2 = (0,
|
|
7943
|
+
const checkpointPath2 = (0, import_node_path12.join)(taskDir, "checkpoint.json");
|
|
7798
7944
|
let checkpoint = {};
|
|
7799
|
-
if ((0,
|
|
7945
|
+
if ((0, import_node_fs13.existsSync)(checkpointPath2)) {
|
|
7800
7946
|
try {
|
|
7801
|
-
checkpoint = JSON.parse((0,
|
|
7947
|
+
checkpoint = JSON.parse((0, import_node_fs13.readFileSync)(checkpointPath2, "utf-8"));
|
|
7802
7948
|
} catch {
|
|
7803
7949
|
}
|
|
7804
7950
|
}
|
|
@@ -7813,8 +7959,8 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
7813
7959
|
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
7960
|
(name, opts) => {
|
|
7815
7961
|
const dir = tasksDir2(ctx);
|
|
7816
|
-
const taskDir = (0,
|
|
7817
|
-
if ((0,
|
|
7962
|
+
const taskDir = (0, import_node_path12.join)(dir, name);
|
|
7963
|
+
if ((0, import_node_fs13.existsSync)(taskDir)) {
|
|
7818
7964
|
exitError("ALREADY_EXISTS", `\u76D1\u63A7\u4EFB\u52A1 '${name}' \u5DF2\u5B58\u5728`);
|
|
7819
7965
|
}
|
|
7820
7966
|
let matchRules;
|
|
@@ -7826,7 +7972,7 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
7826
7972
|
"match-rules \u5FC5\u987B\u662F\u5408\u6CD5\u7684 JSON"
|
|
7827
7973
|
);
|
|
7828
7974
|
}
|
|
7829
|
-
(0,
|
|
7975
|
+
(0, import_node_fs13.mkdirSync)(taskDir, { recursive: true });
|
|
7830
7976
|
const meta = {
|
|
7831
7977
|
name,
|
|
7832
7978
|
description: opts.description,
|
|
@@ -7836,13 +7982,13 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
7836
7982
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
7837
7983
|
};
|
|
7838
7984
|
writeMeta2(taskDir, meta);
|
|
7839
|
-
(0,
|
|
7840
|
-
(0,
|
|
7985
|
+
(0, import_node_fs13.writeFileSync)(
|
|
7986
|
+
(0, import_node_path12.join)(taskDir, "fetch.py"),
|
|
7841
7987
|
generateFetchPy(name, matchRules),
|
|
7842
7988
|
"utf-8"
|
|
7843
7989
|
);
|
|
7844
|
-
(0,
|
|
7845
|
-
(0,
|
|
7990
|
+
(0, import_node_fs13.writeFileSync)(
|
|
7991
|
+
(0, import_node_path12.join)(taskDir, "README.md"),
|
|
7846
7992
|
generateReadme(name, opts.description),
|
|
7847
7993
|
"utf-8"
|
|
7848
7994
|
);
|
|
@@ -7870,8 +8016,8 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
7870
8016
|
}
|
|
7871
8017
|
);
|
|
7872
8018
|
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,
|
|
8019
|
+
const taskDir = (0, import_node_path12.join)(tasksDir2(ctx), name);
|
|
8020
|
+
if (!(0, import_node_fs13.existsSync)(taskDir)) {
|
|
7875
8021
|
exitError("NOT_FOUND", `\u76D1\u63A7\u4EFB\u52A1 '${name}' \u4E0D\u5B58\u5728`);
|
|
7876
8022
|
}
|
|
7877
8023
|
if (!opts.yes) {
|
|
@@ -7884,7 +8030,7 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
7884
8030
|
});
|
|
7885
8031
|
process.exit(1);
|
|
7886
8032
|
}
|
|
7887
|
-
(0,
|
|
8033
|
+
(0, import_node_fs13.rmSync)(taskDir, { recursive: true, force: true });
|
|
7888
8034
|
output({
|
|
7889
8035
|
ok: true,
|
|
7890
8036
|
name,
|
|
@@ -7896,7 +8042,7 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
7896
8042
|
});
|
|
7897
8043
|
});
|
|
7898
8044
|
monitor.command("enable <name>").description("\u542F\u7528\u76D1\u63A7\u4EFB\u52A1").action((name) => {
|
|
7899
|
-
const taskDir = (0,
|
|
8045
|
+
const taskDir = (0, import_node_path12.join)(tasksDir2(ctx), name);
|
|
7900
8046
|
const meta = readMeta2(taskDir);
|
|
7901
8047
|
if (!meta) exitError("NOT_FOUND", `\u76D1\u63A7\u4EFB\u52A1 '${name}' \u4E0D\u5B58\u5728`);
|
|
7902
8048
|
meta.enabled = true;
|
|
@@ -7904,7 +8050,7 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
7904
8050
|
output({ ok: true, name, enabled: true });
|
|
7905
8051
|
});
|
|
7906
8052
|
monitor.command("disable <name>").description("\u6682\u505C\u76D1\u63A7\u4EFB\u52A1").action((name) => {
|
|
7907
|
-
const taskDir = (0,
|
|
8053
|
+
const taskDir = (0, import_node_path12.join)(tasksDir2(ctx), name);
|
|
7908
8054
|
const meta = readMeta2(taskDir);
|
|
7909
8055
|
if (!meta) exitError("NOT_FOUND", `\u76D1\u63A7\u4EFB\u52A1 '${name}' \u4E0D\u5B58\u5728`);
|
|
7910
8056
|
meta.enabled = false;
|
|
@@ -8213,9 +8359,9 @@ function registerLightSend(light) {
|
|
|
8213
8359
|
}
|
|
8214
8360
|
|
|
8215
8361
|
// src/cli/light-setup-tools.ts
|
|
8216
|
-
var
|
|
8217
|
-
var
|
|
8218
|
-
var
|
|
8362
|
+
var import_node_fs14 = require("fs");
|
|
8363
|
+
var import_node_os2 = require("os");
|
|
8364
|
+
var import_node_path13 = require("path");
|
|
8219
8365
|
function isObject(value) {
|
|
8220
8366
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
8221
8367
|
}
|
|
@@ -8229,7 +8375,7 @@ function ensureArray(obj, key) {
|
|
|
8229
8375
|
function resolveConfigPath2() {
|
|
8230
8376
|
const fromEnv = process.env.OPENCLAW_CONFIG_PATH?.trim();
|
|
8231
8377
|
if (fromEnv) return fromEnv;
|
|
8232
|
-
return (0,
|
|
8378
|
+
return (0, import_node_path13.join)((0, import_node_os2.homedir)(), ".openclaw", "openclaw.json");
|
|
8233
8379
|
}
|
|
8234
8380
|
function upsertLightControlAlsoAllow(cfg) {
|
|
8235
8381
|
if (!isObject(cfg.tools)) cfg.tools = {};
|
|
@@ -8258,12 +8404,12 @@ function upsertLightControlAlsoAllow(cfg) {
|
|
|
8258
8404
|
function registerLightSetupTools(light) {
|
|
8259
8405
|
light.command("setup").description("\u81EA\u52A8\u653E\u884C light_control\uFF08\u5199\u5165 tools.alsoAllow \u4E0E agents.main.tools.alsoAllow\uFF09").action(() => {
|
|
8260
8406
|
const configPath = resolveConfigPath2();
|
|
8261
|
-
if (!(0,
|
|
8407
|
+
if (!(0, import_node_fs14.existsSync)(configPath)) {
|
|
8262
8408
|
exitError("CONFIG_NOT_FOUND", `\u672A\u627E\u5230\u914D\u7F6E\u6587\u4EF6: ${configPath}`);
|
|
8263
8409
|
}
|
|
8264
8410
|
let cfg = {};
|
|
8265
8411
|
try {
|
|
8266
|
-
const raw = (0,
|
|
8412
|
+
const raw = (0, import_node_fs14.readFileSync)(configPath, "utf-8");
|
|
8267
8413
|
const parsed = JSON.parse(raw);
|
|
8268
8414
|
if (isObject(parsed)) cfg = parsed;
|
|
8269
8415
|
} catch (err) {
|
|
@@ -8271,8 +8417,8 @@ function registerLightSetupTools(light) {
|
|
|
8271
8417
|
}
|
|
8272
8418
|
const result = upsertLightControlAlsoAllow(cfg);
|
|
8273
8419
|
try {
|
|
8274
|
-
(0,
|
|
8275
|
-
(0,
|
|
8420
|
+
(0, import_node_fs14.mkdirSync)((0, import_node_path13.dirname)(configPath), { recursive: true });
|
|
8421
|
+
(0, import_node_fs14.writeFileSync)(configPath, JSON.stringify(cfg, null, 2) + "\n", "utf-8");
|
|
8276
8422
|
} catch (err) {
|
|
8277
8423
|
exitError("WRITE_FAILED", `\u5199\u5165\u914D\u7F6E\u5931\u8D25: ${err?.message ?? String(err)}`);
|
|
8278
8424
|
}
|
|
@@ -8290,17 +8436,17 @@ function registerLightSetupTools(light) {
|
|
|
8290
8436
|
}
|
|
8291
8437
|
|
|
8292
8438
|
// src/cli/tunnel-status.ts
|
|
8293
|
-
var
|
|
8294
|
-
var
|
|
8439
|
+
var import_node_fs15 = require("fs");
|
|
8440
|
+
var import_node_path14 = require("path");
|
|
8295
8441
|
init_credentials();
|
|
8296
8442
|
init_env();
|
|
8297
|
-
var STATUS_REL_PATH = (0,
|
|
8443
|
+
var STATUS_REL_PATH = (0, import_node_path14.join)("plugins", "phone-notifications", "tunnel-status.json");
|
|
8298
8444
|
function readTunnelStatus(ctx) {
|
|
8299
8445
|
if (!ctx.stateDir) return null;
|
|
8300
|
-
const filePath = (0,
|
|
8301
|
-
if (!(0,
|
|
8446
|
+
const filePath = (0, import_node_path14.join)(ctx.stateDir, STATUS_REL_PATH);
|
|
8447
|
+
if (!(0, import_node_fs15.existsSync)(filePath)) return null;
|
|
8302
8448
|
try {
|
|
8303
|
-
return JSON.parse((0,
|
|
8449
|
+
return JSON.parse((0, import_node_fs15.readFileSync)(filePath, "utf-8"));
|
|
8304
8450
|
} catch {
|
|
8305
8451
|
return null;
|
|
8306
8452
|
}
|
|
@@ -8368,24 +8514,24 @@ function registerNtfStoragePath(ntf, ctx) {
|
|
|
8368
8514
|
}
|
|
8369
8515
|
|
|
8370
8516
|
// src/cli/log-search.ts
|
|
8371
|
-
var
|
|
8372
|
-
var
|
|
8517
|
+
var import_node_fs16 = require("fs");
|
|
8518
|
+
var import_node_path15 = require("path");
|
|
8373
8519
|
function resolveLogsDir(ctx) {
|
|
8374
8520
|
if (ctx.stateDir) {
|
|
8375
|
-
const dir = (0,
|
|
8521
|
+
const dir = (0, import_node_path15.join)(
|
|
8376
8522
|
ctx.stateDir,
|
|
8377
8523
|
"plugins",
|
|
8378
8524
|
"phone-notifications",
|
|
8379
8525
|
"logs"
|
|
8380
8526
|
);
|
|
8381
|
-
if ((0,
|
|
8527
|
+
if ((0, import_node_fs16.existsSync)(dir)) return dir;
|
|
8382
8528
|
}
|
|
8383
8529
|
return null;
|
|
8384
8530
|
}
|
|
8385
8531
|
function listLogDateKeys(dir) {
|
|
8386
8532
|
const pattern = /^(\d{4}-\d{2}-\d{2})\.log$/;
|
|
8387
8533
|
const keys = [];
|
|
8388
|
-
for (const entry of (0,
|
|
8534
|
+
for (const entry of (0, import_node_fs16.readdirSync)(dir, { withFileTypes: true })) {
|
|
8389
8535
|
if (!entry.isFile()) continue;
|
|
8390
8536
|
const m = pattern.exec(entry.name);
|
|
8391
8537
|
if (m) keys.push(m[1]);
|
|
@@ -8393,9 +8539,9 @@ function listLogDateKeys(dir) {
|
|
|
8393
8539
|
return keys.sort().reverse();
|
|
8394
8540
|
}
|
|
8395
8541
|
function collectLogLines(dir, dateKey, keyword, limit, collected) {
|
|
8396
|
-
const filePath = (0,
|
|
8397
|
-
if (!(0,
|
|
8398
|
-
const content = (0,
|
|
8542
|
+
const filePath = (0, import_node_path15.join)(dir, `${dateKey}.log`);
|
|
8543
|
+
if (!(0, import_node_fs16.existsSync)(filePath)) return;
|
|
8544
|
+
const content = (0, import_node_fs16.readFileSync)(filePath, "utf-8");
|
|
8399
8545
|
const lowerKeyword = keyword?.toLowerCase();
|
|
8400
8546
|
for (const line of content.split("\n")) {
|
|
8401
8547
|
if (collected.length >= limit) return;
|
|
@@ -8462,12 +8608,12 @@ function registerEnvCli(ntf) {
|
|
|
8462
8608
|
}
|
|
8463
8609
|
|
|
8464
8610
|
// src/cli/doctor.ts
|
|
8465
|
-
var
|
|
8611
|
+
var import_node_fs20 = require("fs");
|
|
8466
8612
|
var import_node_readline = require("readline");
|
|
8467
8613
|
init_host();
|
|
8468
8614
|
|
|
8469
8615
|
// src/cli/doctor/check-dangerous-flags.ts
|
|
8470
|
-
var
|
|
8616
|
+
var import_node_fs17 = require("fs");
|
|
8471
8617
|
function isObject2(v) {
|
|
8472
8618
|
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
8473
8619
|
}
|
|
@@ -8484,13 +8630,13 @@ var checkDangerousFlags = ({ cfg, configPath }) => {
|
|
|
8484
8630
|
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
8631
|
fixDescription: "\u8BBE\u4E3A false",
|
|
8486
8632
|
fix: () => {
|
|
8487
|
-
const raw = (0,
|
|
8633
|
+
const raw = (0, import_node_fs17.readFileSync)(configPath, "utf-8");
|
|
8488
8634
|
const config = JSON.parse(raw);
|
|
8489
8635
|
const gw = config.gateway;
|
|
8490
8636
|
const cui = gw.controlUi;
|
|
8491
8637
|
cui.dangerouslyDisableDeviceAuth = false;
|
|
8492
|
-
(0,
|
|
8493
|
-
(0,
|
|
8638
|
+
(0, import_node_fs17.copyFileSync)(configPath, configPath + ".bak");
|
|
8639
|
+
(0, import_node_fs17.writeFileSync)(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
8494
8640
|
}
|
|
8495
8641
|
};
|
|
8496
8642
|
};
|
|
@@ -8538,11 +8684,11 @@ function warnEmpty() {
|
|
|
8538
8684
|
}
|
|
8539
8685
|
|
|
8540
8686
|
// src/cli/doctor/check-state-dir-perms.ts
|
|
8541
|
-
var
|
|
8687
|
+
var import_node_fs18 = require("fs");
|
|
8542
8688
|
var checkStateDirPerms = ({ stateDir }) => {
|
|
8543
8689
|
let mode;
|
|
8544
8690
|
try {
|
|
8545
|
-
mode = (0,
|
|
8691
|
+
mode = (0, import_node_fs18.statSync)(stateDir).mode;
|
|
8546
8692
|
} catch {
|
|
8547
8693
|
return null;
|
|
8548
8694
|
}
|
|
@@ -8556,7 +8702,7 @@ var checkStateDirPerms = ({ stateDir }) => {
|
|
|
8556
8702
|
detail: "\u5176\u4ED6\u7528\u6237\u53EF\u4EE5\u8BFB\u53D6\u8BE5\u76EE\u5F55\u4E0B\u7684\u51ED\u8BC1\u548C\u914D\u7F6E\u6587\u4EF6\u3002",
|
|
8557
8703
|
fixDescription: "chmod 700 " + stateDir,
|
|
8558
8704
|
fix: () => {
|
|
8559
|
-
(0,
|
|
8705
|
+
(0, import_node_fs18.chmodSync)(stateDir, 448);
|
|
8560
8706
|
}
|
|
8561
8707
|
};
|
|
8562
8708
|
};
|
|
@@ -8611,16 +8757,16 @@ var checkCredentials = () => {
|
|
|
8611
8757
|
};
|
|
8612
8758
|
|
|
8613
8759
|
// src/cli/doctor/check-tunnel.ts
|
|
8614
|
-
var
|
|
8615
|
-
var
|
|
8616
|
-
var STATUS_REL_PATH2 = (0,
|
|
8760
|
+
var import_node_fs19 = require("fs");
|
|
8761
|
+
var import_node_path16 = require("path");
|
|
8762
|
+
var STATUS_REL_PATH2 = (0, import_node_path16.join)(
|
|
8617
8763
|
"plugins",
|
|
8618
8764
|
"phone-notifications",
|
|
8619
8765
|
"tunnel-status.json"
|
|
8620
8766
|
);
|
|
8621
8767
|
var checkTunnel = ({ stateDir }) => {
|
|
8622
|
-
const filePath = (0,
|
|
8623
|
-
if (!(0,
|
|
8768
|
+
const filePath = (0, import_node_path16.join)(stateDir, STATUS_REL_PATH2);
|
|
8769
|
+
if (!(0, import_node_fs19.existsSync)(filePath)) {
|
|
8624
8770
|
return {
|
|
8625
8771
|
id: "tunnel",
|
|
8626
8772
|
severity: "warn",
|
|
@@ -8632,7 +8778,7 @@ var checkTunnel = ({ stateDir }) => {
|
|
|
8632
8778
|
}
|
|
8633
8779
|
let status;
|
|
8634
8780
|
try {
|
|
8635
|
-
status = JSON.parse((0,
|
|
8781
|
+
status = JSON.parse((0, import_node_fs19.readFileSync)(filePath, "utf-8"));
|
|
8636
8782
|
} catch {
|
|
8637
8783
|
return {
|
|
8638
8784
|
id: "tunnel",
|
|
@@ -8725,9 +8871,9 @@ function isObject5(v) {
|
|
|
8725
8871
|
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
8726
8872
|
}
|
|
8727
8873
|
function readConfig(configPath) {
|
|
8728
|
-
if (!(0,
|
|
8874
|
+
if (!(0, import_node_fs20.existsSync)(configPath)) return {};
|
|
8729
8875
|
try {
|
|
8730
|
-
const parsed = JSON.parse((0,
|
|
8876
|
+
const parsed = JSON.parse((0, import_node_fs20.readFileSync)(configPath, "utf-8"));
|
|
8731
8877
|
return isObject5(parsed) ? parsed : {};
|
|
8732
8878
|
} catch {
|
|
8733
8879
|
return {};
|
|
@@ -8928,7 +9074,7 @@ function registerRecStoragePath(rec, ctx) {
|
|
|
8928
9074
|
|
|
8929
9075
|
// src/cli/rec-setup.ts
|
|
8930
9076
|
var import_node_readline2 = require("readline");
|
|
8931
|
-
var
|
|
9077
|
+
var import_node_fs21 = require("fs");
|
|
8932
9078
|
function ask(rl, question) {
|
|
8933
9079
|
return new Promise((resolve) => rl.question(question, resolve));
|
|
8934
9080
|
}
|
|
@@ -9014,9 +9160,9 @@ async function setupLocal(rl) {
|
|
|
9014
9160
|
function registerRecSetup(rec, ctx) {
|
|
9015
9161
|
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
9162
|
const configPath = resolveAsrConfigPath(ctx);
|
|
9017
|
-
if ((0,
|
|
9163
|
+
if ((0, import_node_fs21.existsSync)(configPath)) {
|
|
9018
9164
|
try {
|
|
9019
|
-
const existing = JSON.parse((0,
|
|
9165
|
+
const existing = JSON.parse((0, import_node_fs21.readFileSync)(configPath, "utf-8"));
|
|
9020
9166
|
process.stderr.write(`\u5F53\u524D\u5DF2\u6709\u914D\u7F6E\uFF1Amode = ${existing.mode}`);
|
|
9021
9167
|
if (existing.updatedAt) process.stderr.write(`\uFF0C\u66F4\u65B0\u4E8E ${existing.updatedAt}`);
|
|
9022
9168
|
process.stderr.write("\n");
|
|
@@ -9029,7 +9175,7 @@ function registerRecSetup(rec, ctx) {
|
|
|
9029
9175
|
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
9176
|
const config = modeIdx === 0 ? await setupApi(rl) : await setupLocal(rl);
|
|
9031
9177
|
const stored = { ...config, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
9032
|
-
(0,
|
|
9178
|
+
(0, import_node_fs21.writeFileSync)(configPath, JSON.stringify(stored, null, 2), "utf-8");
|
|
9033
9179
|
process.stderr.write(`
|
|
9034
9180
|
\u2713 \u914D\u7F6E\u5DF2\u4FDD\u5B58\u5230 ${configPath}
|
|
9035
9181
|
|
|
@@ -9043,11 +9189,11 @@ function registerRecSetup(rec, ctx) {
|
|
|
9043
9189
|
|
|
9044
9190
|
// src/cli/update.ts
|
|
9045
9191
|
var import_node_child_process = require("child_process");
|
|
9046
|
-
var
|
|
9047
|
-
var
|
|
9048
|
-
var
|
|
9192
|
+
var import_node_fs22 = require("fs");
|
|
9193
|
+
var import_node_path17 = require("path");
|
|
9194
|
+
var import_node_os3 = __toESM(require("os"), 1);
|
|
9049
9195
|
init_host();
|
|
9050
|
-
var
|
|
9196
|
+
var BASE_URL2 = "https://artifact.yoooclaw.com/plugin";
|
|
9051
9197
|
async function fetchText(url) {
|
|
9052
9198
|
const res = await fetch(url, { signal: AbortSignal.timeout(3e4) });
|
|
9053
9199
|
if (!res.ok) {
|
|
@@ -9067,7 +9213,7 @@ async function runUpdate(ctx, opts) {
|
|
|
9067
9213
|
log(`\u68C0\u67E5${beta ? " beta" : ""}\u6700\u65B0\u7248\u672C ...`);
|
|
9068
9214
|
let latest;
|
|
9069
9215
|
try {
|
|
9070
|
-
latest = (await fetchText(`${
|
|
9216
|
+
latest = (await fetchText(`${BASE_URL2}/${channel}`)).trim();
|
|
9071
9217
|
} catch (err) {
|
|
9072
9218
|
const msg = `\u65E0\u6CD5\u83B7\u53D6\u6700\u65B0\u7248\u672C: ${err?.message ?? String(err)}`;
|
|
9073
9219
|
if (json) {
|
|
@@ -9092,7 +9238,7 @@ async function runUpdate(ctx, opts) {
|
|
|
9092
9238
|
log("\u4E0B\u8F7D\u5B89\u88C5\u811A\u672C ...");
|
|
9093
9239
|
let installScript;
|
|
9094
9240
|
try {
|
|
9095
|
-
installScript = await fetchText(`${
|
|
9241
|
+
installScript = await fetchText(`${BASE_URL2}/install-core.mjs`);
|
|
9096
9242
|
} catch (err) {
|
|
9097
9243
|
const msg = `\u4E0B\u8F7D\u5B89\u88C5\u811A\u672C\u5931\u8D25: ${err?.message ?? String(err)}`;
|
|
9098
9244
|
if (json) {
|
|
@@ -9103,9 +9249,9 @@ async function runUpdate(ctx, opts) {
|
|
|
9103
9249
|
`);
|
|
9104
9250
|
process.exit(1);
|
|
9105
9251
|
}
|
|
9106
|
-
const tmpScript = (0,
|
|
9252
|
+
const tmpScript = (0, import_node_path17.join)(import_node_os3.default.tmpdir(), `openclaw-install-${Date.now()}.mjs`);
|
|
9107
9253
|
try {
|
|
9108
|
-
(0,
|
|
9254
|
+
(0, import_node_fs22.writeFileSync)(tmpScript, installScript, "utf-8");
|
|
9109
9255
|
} catch (err) {
|
|
9110
9256
|
const msg = `\u5199\u5165\u4E34\u65F6\u6587\u4EF6\u5931\u8D25: ${err?.message ?? String(err)}`;
|
|
9111
9257
|
if (json) {
|
|
@@ -9123,7 +9269,7 @@ async function runUpdate(ctx, opts) {
|
|
|
9123
9269
|
{ stdio: "inherit" }
|
|
9124
9270
|
);
|
|
9125
9271
|
try {
|
|
9126
|
-
(0,
|
|
9272
|
+
(0, import_node_fs22.unlinkSync)(tmpScript);
|
|
9127
9273
|
} catch {
|
|
9128
9274
|
}
|
|
9129
9275
|
if (result.error) {
|
|
@@ -9187,10 +9333,10 @@ function inferOpenClawRootDir(workspaceDir) {
|
|
|
9187
9333
|
if (!workspaceDir) {
|
|
9188
9334
|
return void 0;
|
|
9189
9335
|
}
|
|
9190
|
-
if ((0,
|
|
9336
|
+
if ((0, import_node_path18.basename)(workspaceDir) !== "workspace") {
|
|
9191
9337
|
return void 0;
|
|
9192
9338
|
}
|
|
9193
|
-
return (0,
|
|
9339
|
+
return (0, import_node_path18.dirname)(workspaceDir);
|
|
9194
9340
|
}
|
|
9195
9341
|
function registerPluginCli(api, params) {
|
|
9196
9342
|
const { logger, openclawDir } = params;
|
|
@@ -9436,12 +9582,12 @@ function registerLightControlTool(api, logger) {
|
|
|
9436
9582
|
}
|
|
9437
9583
|
|
|
9438
9584
|
// src/plugin/lifecycle.ts
|
|
9439
|
-
var
|
|
9585
|
+
var import_node_fs31 = require("fs");
|
|
9440
9586
|
init_host();
|
|
9441
9587
|
|
|
9442
9588
|
// src/notification/app-name-map.ts
|
|
9443
|
-
var
|
|
9444
|
-
var
|
|
9589
|
+
var import_node_fs23 = require("fs");
|
|
9590
|
+
var import_node_path19 = require("path");
|
|
9445
9591
|
init_credentials();
|
|
9446
9592
|
init_env();
|
|
9447
9593
|
var PLUGIN_STATE_DIR = "phone-notifications";
|
|
@@ -9462,7 +9608,7 @@ function isAppNameMapApiResponse(v) {
|
|
|
9462
9608
|
);
|
|
9463
9609
|
}
|
|
9464
9610
|
function getCachePath(stateDir) {
|
|
9465
|
-
return (0,
|
|
9611
|
+
return (0, import_node_path19.join)(stateDir, "plugins", PLUGIN_STATE_DIR, CACHE_FILE);
|
|
9466
9612
|
}
|
|
9467
9613
|
function createAppNameMapProvider(opts) {
|
|
9468
9614
|
const { stateDir, logger } = opts;
|
|
@@ -9474,9 +9620,9 @@ function createAppNameMapProvider(opts) {
|
|
|
9474
9620
|
let inFlightFetch = null;
|
|
9475
9621
|
function loadFromDisk() {
|
|
9476
9622
|
const path2 = getCachePath(stateDir);
|
|
9477
|
-
if (!(0,
|
|
9623
|
+
if (!(0, import_node_fs23.existsSync)(path2)) return;
|
|
9478
9624
|
try {
|
|
9479
|
-
const raw = JSON.parse((0,
|
|
9625
|
+
const raw = JSON.parse((0, import_node_fs23.readFileSync)(path2, "utf-8"));
|
|
9480
9626
|
if (!isRecordOfStrings(raw)) return;
|
|
9481
9627
|
map.clear();
|
|
9482
9628
|
for (const [k, v] of Object.entries(raw)) map.set(k, v);
|
|
@@ -9520,10 +9666,10 @@ function createAppNameMapProvider(opts) {
|
|
|
9520
9666
|
logger.warn("[app-name-map] refresh succeeded but got 0 entries");
|
|
9521
9667
|
return;
|
|
9522
9668
|
}
|
|
9523
|
-
const dir = (0,
|
|
9524
|
-
(0,
|
|
9669
|
+
const dir = (0, import_node_path19.join)(stateDir, "plugins", PLUGIN_STATE_DIR);
|
|
9670
|
+
(0, import_node_fs23.mkdirSync)(dir, { recursive: true });
|
|
9525
9671
|
const cachePath = getCachePath(stateDir);
|
|
9526
|
-
(0,
|
|
9672
|
+
(0, import_node_fs23.writeFileSync)(cachePath, JSON.stringify(Object.fromEntries(map), null, 2), "utf-8");
|
|
9527
9673
|
logger.info(`[app-name-map] refreshed ${map.size} entries from server and saved: ${cachePath}`);
|
|
9528
9674
|
} catch (e) {
|
|
9529
9675
|
const message = e instanceof Error ? e.message : String(e);
|
|
@@ -9567,8 +9713,8 @@ function createAppNameMapProvider(opts) {
|
|
|
9567
9713
|
}
|
|
9568
9714
|
|
|
9569
9715
|
// src/recording/storage.ts
|
|
9570
|
-
var
|
|
9571
|
-
var
|
|
9716
|
+
var import_node_fs24 = require("fs");
|
|
9717
|
+
var import_node_path20 = require("path");
|
|
9572
9718
|
|
|
9573
9719
|
// src/recording/state-machine.ts
|
|
9574
9720
|
var VALID_TRANSITIONS = /* @__PURE__ */ new Map([
|
|
@@ -9629,7 +9775,7 @@ function stripMarkdownFence(markdown) {
|
|
|
9629
9775
|
}
|
|
9630
9776
|
function deriveTitleFromTranscriptPath(transcriptFile, recordingId) {
|
|
9631
9777
|
if (!transcriptFile) return void 0;
|
|
9632
|
-
const name = (0,
|
|
9778
|
+
const name = (0, import_node_path20.basename)(transcriptFile, ".md");
|
|
9633
9779
|
const prefix = `${recordingId}_`;
|
|
9634
9780
|
if (name.startsWith(prefix)) {
|
|
9635
9781
|
const derived = name.slice(prefix.length).trim();
|
|
@@ -9657,22 +9803,22 @@ function extractTranscriptContent(markdown) {
|
|
|
9657
9803
|
return lines.join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
9658
9804
|
}
|
|
9659
9805
|
function resolveRecordingStorageDir(ctx, logger) {
|
|
9660
|
-
const stateRecDir = (0,
|
|
9806
|
+
const stateRecDir = (0, import_node_path20.join)(
|
|
9661
9807
|
ctx.stateDir,
|
|
9662
9808
|
"plugins",
|
|
9663
9809
|
"phone-notifications",
|
|
9664
9810
|
RECORDINGS_DIR
|
|
9665
9811
|
);
|
|
9666
9812
|
try {
|
|
9667
|
-
(0,
|
|
9813
|
+
(0, import_node_fs24.mkdirSync)(stateRecDir, { recursive: true });
|
|
9668
9814
|
logger.info(`\u5F55\u97F3\u5C06\u5199\u5165 stateDir \u8DEF\u5F84: ${stateRecDir}`);
|
|
9669
9815
|
return stateRecDir;
|
|
9670
9816
|
} catch {
|
|
9671
9817
|
}
|
|
9672
9818
|
if (ctx.workspaceDir) {
|
|
9673
|
-
const wsRecDir = (0,
|
|
9819
|
+
const wsRecDir = (0, import_node_path20.join)(ctx.workspaceDir, RECORDINGS_DIR);
|
|
9674
9820
|
try {
|
|
9675
|
-
(0,
|
|
9821
|
+
(0, import_node_fs24.mkdirSync)(wsRecDir, { recursive: true });
|
|
9676
9822
|
logger.warn(`stateDir \u4E0D\u53EF\u7528\uFF0C\u5F55\u97F3\u5DF2\u56DE\u9000\u5230 workspace \u8DEF\u5F84: ${wsRecDir}`);
|
|
9677
9823
|
return wsRecDir;
|
|
9678
9824
|
} catch {
|
|
@@ -9684,11 +9830,11 @@ var RecordingStorage = class {
|
|
|
9684
9830
|
constructor(dir, logger) {
|
|
9685
9831
|
this.logger = logger;
|
|
9686
9832
|
this.dir = dir;
|
|
9687
|
-
this.audioDir = (0,
|
|
9688
|
-
this.transcriptDataDir = (0,
|
|
9689
|
-
this.transcriptsDir = (0,
|
|
9690
|
-
this.summariesDir = (0,
|
|
9691
|
-
this.indexPath = (0,
|
|
9833
|
+
this.audioDir = (0, import_node_path20.join)(dir, AUDIO_DIR);
|
|
9834
|
+
this.transcriptDataDir = (0, import_node_path20.join)(dir, TRANSCRIPT_DATA_DIR);
|
|
9835
|
+
this.transcriptsDir = (0, import_node_path20.join)(dir, TRANSCRIPTS_DIR);
|
|
9836
|
+
this.summariesDir = (0, import_node_path20.join)(dir, SUMMARIES_DIR);
|
|
9837
|
+
this.indexPath = (0, import_node_path20.join)(dir, INDEX_FILE);
|
|
9692
9838
|
}
|
|
9693
9839
|
dir;
|
|
9694
9840
|
audioDir;
|
|
@@ -9699,10 +9845,10 @@ var RecordingStorage = class {
|
|
|
9699
9845
|
index = { recordings: [] };
|
|
9700
9846
|
/** 初始化目录结构并加载索引 */
|
|
9701
9847
|
async init() {
|
|
9702
|
-
(0,
|
|
9703
|
-
(0,
|
|
9704
|
-
(0,
|
|
9705
|
-
(0,
|
|
9848
|
+
(0, import_node_fs24.mkdirSync)(this.audioDir, { recursive: true });
|
|
9849
|
+
(0, import_node_fs24.mkdirSync)(this.transcriptDataDir, { recursive: true });
|
|
9850
|
+
(0, import_node_fs24.mkdirSync)(this.transcriptsDir, { recursive: true });
|
|
9851
|
+
(0, import_node_fs24.mkdirSync)(this.summariesDir, { recursive: true });
|
|
9706
9852
|
this.loadIndex();
|
|
9707
9853
|
this.logger.info(
|
|
9708
9854
|
`\u5F55\u97F3\u5B58\u50A8\u5DF2\u521D\u59CB\u5316: ${this.dir}\uFF08\u5171 ${this.index.recordings.length} \u6761\u8BB0\u5F55\uFF09`
|
|
@@ -9746,13 +9892,13 @@ var RecordingStorage = class {
|
|
|
9746
9892
|
return id;
|
|
9747
9893
|
}
|
|
9748
9894
|
if (existing.transcriptDataFile) {
|
|
9749
|
-
(0,
|
|
9895
|
+
(0, import_node_fs24.rmSync)((0, import_node_path20.join)(this.dir, existing.transcriptDataFile), { force: true });
|
|
9750
9896
|
}
|
|
9751
9897
|
if (existing.transcriptFile) {
|
|
9752
|
-
(0,
|
|
9898
|
+
(0, import_node_fs24.rmSync)((0, import_node_path20.join)(this.dir, existing.transcriptFile), { force: true });
|
|
9753
9899
|
}
|
|
9754
9900
|
if (existing.summaryFile) {
|
|
9755
|
-
(0,
|
|
9901
|
+
(0, import_node_fs24.rmSync)((0, import_node_path20.join)(this.dir, existing.summaryFile), { force: true });
|
|
9756
9902
|
}
|
|
9757
9903
|
existing.metadata = metadata;
|
|
9758
9904
|
existing.status = "syncing_openclaw";
|
|
@@ -9820,7 +9966,7 @@ var RecordingStorage = class {
|
|
|
9820
9966
|
if (!entry) return;
|
|
9821
9967
|
const nextTranscriptDataFile = `${TRANSCRIPT_DATA_DIR}/${filename}`;
|
|
9822
9968
|
if (entry.transcriptDataFile && entry.transcriptDataFile !== nextTranscriptDataFile) {
|
|
9823
|
-
(0,
|
|
9969
|
+
(0, import_node_fs24.rmSync)((0, import_node_path20.join)(this.dir, entry.transcriptDataFile), { force: true });
|
|
9824
9970
|
}
|
|
9825
9971
|
entry.transcriptDataFile = nextTranscriptDataFile;
|
|
9826
9972
|
entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -9834,7 +9980,7 @@ var RecordingStorage = class {
|
|
|
9834
9980
|
if (!entry) return;
|
|
9835
9981
|
const nextTranscriptFile = `${TRANSCRIPTS_DIR}/${filename}`;
|
|
9836
9982
|
if (entry.transcriptFile && entry.transcriptFile !== nextTranscriptFile) {
|
|
9837
|
-
(0,
|
|
9983
|
+
(0, import_node_fs24.rmSync)((0, import_node_path20.join)(this.dir, entry.transcriptFile), { force: true });
|
|
9838
9984
|
}
|
|
9839
9985
|
entry.transcriptFile = nextTranscriptFile;
|
|
9840
9986
|
entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -9848,7 +9994,7 @@ var RecordingStorage = class {
|
|
|
9848
9994
|
if (!entry) return;
|
|
9849
9995
|
const nextSummaryFile = `${SUMMARIES_DIR}/${filename}`;
|
|
9850
9996
|
if (entry.summaryFile && entry.summaryFile !== nextSummaryFile) {
|
|
9851
|
-
(0,
|
|
9997
|
+
(0, import_node_fs24.rmSync)((0, import_node_path20.join)(this.dir, entry.summaryFile), { force: true });
|
|
9852
9998
|
}
|
|
9853
9999
|
entry.summaryFile = nextSummaryFile;
|
|
9854
10000
|
entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -9946,24 +10092,24 @@ var RecordingStorage = class {
|
|
|
9946
10092
|
const entry = this.findById(recordingId);
|
|
9947
10093
|
if (!entry) return false;
|
|
9948
10094
|
if (entry.audioFile) {
|
|
9949
|
-
const audioPath = (0,
|
|
9950
|
-
(0,
|
|
10095
|
+
const audioPath = (0, import_node_path20.join)(this.dir, entry.audioFile);
|
|
10096
|
+
(0, import_node_fs24.rmSync)(audioPath, { force: true });
|
|
9951
10097
|
}
|
|
9952
10098
|
if (entry.srtFile) {
|
|
9953
|
-
const srtPath = (0,
|
|
9954
|
-
(0,
|
|
10099
|
+
const srtPath = (0, import_node_path20.join)(this.dir, entry.srtFile);
|
|
10100
|
+
(0, import_node_fs24.rmSync)(srtPath, { force: true });
|
|
9955
10101
|
}
|
|
9956
10102
|
if (entry.transcriptDataFile) {
|
|
9957
|
-
const transcriptDataPath = (0,
|
|
9958
|
-
(0,
|
|
10103
|
+
const transcriptDataPath = (0, import_node_path20.join)(this.dir, entry.transcriptDataFile);
|
|
10104
|
+
(0, import_node_fs24.rmSync)(transcriptDataPath, { force: true });
|
|
9959
10105
|
}
|
|
9960
10106
|
if (entry.transcriptFile) {
|
|
9961
|
-
const transcriptPath = (0,
|
|
9962
|
-
(0,
|
|
10107
|
+
const transcriptPath = (0, import_node_path20.join)(this.dir, entry.transcriptFile);
|
|
10108
|
+
(0, import_node_fs24.rmSync)(transcriptPath, { force: true });
|
|
9963
10109
|
}
|
|
9964
10110
|
if (entry.summaryFile) {
|
|
9965
|
-
const summaryPath = (0,
|
|
9966
|
-
(0,
|
|
10111
|
+
const summaryPath = (0, import_node_path20.join)(this.dir, entry.summaryFile);
|
|
10112
|
+
(0, import_node_fs24.rmSync)(summaryPath, { force: true });
|
|
9967
10113
|
}
|
|
9968
10114
|
if (opts?.localOnly) {
|
|
9969
10115
|
entry.audioFile = void 0;
|
|
@@ -10021,34 +10167,34 @@ var RecordingStorage = class {
|
|
|
10021
10167
|
* 获取音频文件的绝对路径。ossUrl 用于推断文件扩展名
|
|
10022
10168
|
*/
|
|
10023
10169
|
getAudioFilePath(recordingId, ossUrl) {
|
|
10024
|
-
return (0,
|
|
10170
|
+
return (0, import_node_path20.join)(this.audioDir, this.buildAudioFilename(recordingId, ossUrl));
|
|
10025
10171
|
}
|
|
10026
10172
|
/**
|
|
10027
10173
|
* 获取打点文件的绝对路径
|
|
10028
10174
|
*/
|
|
10029
10175
|
getSrtFilePath(recordingId) {
|
|
10030
|
-
return (0,
|
|
10176
|
+
return (0, import_node_path20.join)(this.audioDir, this.buildSrtFilename(recordingId));
|
|
10031
10177
|
}
|
|
10032
10178
|
/**
|
|
10033
10179
|
* 获取转写 JSON 文件的绝对路径
|
|
10034
10180
|
*/
|
|
10035
10181
|
getTranscriptDataFilePath(recordingId) {
|
|
10036
|
-
return (0,
|
|
10182
|
+
return (0, import_node_path20.join)(this.transcriptDataDir, this.buildTranscriptDataFilename(recordingId));
|
|
10037
10183
|
}
|
|
10038
10184
|
/**
|
|
10039
10185
|
* 获取摘要文件的绝对路径
|
|
10040
10186
|
*/
|
|
10041
10187
|
getSummaryFilePath(recordingId) {
|
|
10042
|
-
return (0,
|
|
10188
|
+
return (0, import_node_path20.join)(this.summariesDir, this.buildSummaryFilename(recordingId));
|
|
10043
10189
|
}
|
|
10044
10190
|
// ─── Persistence ───
|
|
10045
10191
|
loadIndex() {
|
|
10046
|
-
if (!(0,
|
|
10192
|
+
if (!(0, import_node_fs24.existsSync)(this.indexPath)) {
|
|
10047
10193
|
this.index = { recordings: [] };
|
|
10048
10194
|
return;
|
|
10049
10195
|
}
|
|
10050
10196
|
try {
|
|
10051
|
-
const raw = JSON.parse((0,
|
|
10197
|
+
const raw = JSON.parse((0, import_node_fs24.readFileSync)(this.indexPath, "utf-8"));
|
|
10052
10198
|
if (raw && Array.isArray(raw.recordings)) {
|
|
10053
10199
|
let needsRewrite = false;
|
|
10054
10200
|
const normalized = raw.recordings.filter((entry) => entry && typeof entry === "object").map((entry) => {
|
|
@@ -10086,8 +10232,8 @@ var RecordingStorage = class {
|
|
|
10086
10232
|
segments: []
|
|
10087
10233
|
});
|
|
10088
10234
|
const transcriptDataFilename = this.buildTranscriptDataFilename(compacted.id);
|
|
10089
|
-
(0,
|
|
10090
|
-
(0,
|
|
10235
|
+
(0, import_node_fs24.writeFileSync)(
|
|
10236
|
+
(0, import_node_path20.join)(this.transcriptDataDir, transcriptDataFilename),
|
|
10091
10237
|
JSON.stringify(transcriptDoc, null, 2),
|
|
10092
10238
|
"utf-8"
|
|
10093
10239
|
);
|
|
@@ -10099,8 +10245,8 @@ var RecordingStorage = class {
|
|
|
10099
10245
|
compacted.summaryFile = entry.summaryFile;
|
|
10100
10246
|
} else if (typeof entry.summary === "string" && entry.summary.trim()) {
|
|
10101
10247
|
const summaryFilename = this.buildSummaryFilename(entry.id);
|
|
10102
|
-
(0,
|
|
10103
|
-
(0,
|
|
10248
|
+
(0, import_node_fs24.writeFileSync)(
|
|
10249
|
+
(0, import_node_path20.join)(this.summariesDir, summaryFilename),
|
|
10104
10250
|
entry.summary.trim(),
|
|
10105
10251
|
"utf-8"
|
|
10106
10252
|
);
|
|
@@ -10110,8 +10256,8 @@ var RecordingStorage = class {
|
|
|
10110
10256
|
const summaryFromDocument = extractTranscriptSummaryFromDocument(transcriptDoc);
|
|
10111
10257
|
if (summaryFromDocument) {
|
|
10112
10258
|
const summaryFilename = this.buildSummaryFilename(entry.id);
|
|
10113
|
-
(0,
|
|
10114
|
-
(0,
|
|
10259
|
+
(0, import_node_fs24.writeFileSync)(
|
|
10260
|
+
(0, import_node_path20.join)(this.summariesDir, summaryFilename),
|
|
10115
10261
|
summaryFromDocument,
|
|
10116
10262
|
"utf-8"
|
|
10117
10263
|
);
|
|
@@ -10151,7 +10297,7 @@ var RecordingStorage = class {
|
|
|
10151
10297
|
}
|
|
10152
10298
|
readRelativeTextFile(relativePath) {
|
|
10153
10299
|
try {
|
|
10154
|
-
return (0,
|
|
10300
|
+
return (0, import_node_fs24.readFileSync)((0, import_node_path20.join)(this.dir, relativePath), "utf-8");
|
|
10155
10301
|
} catch {
|
|
10156
10302
|
return void 0;
|
|
10157
10303
|
}
|
|
@@ -10164,7 +10310,7 @@ var RecordingStorage = class {
|
|
|
10164
10310
|
return parseTranscriptDocument(raw);
|
|
10165
10311
|
}
|
|
10166
10312
|
saveIndex() {
|
|
10167
|
-
(0,
|
|
10313
|
+
(0, import_node_fs24.writeFileSync)(
|
|
10168
10314
|
this.indexPath,
|
|
10169
10315
|
JSON.stringify(this.index, null, 2),
|
|
10170
10316
|
"utf-8"
|
|
@@ -10178,8 +10324,8 @@ var RecordingStorage = class {
|
|
|
10178
10324
|
init_transcript_document();
|
|
10179
10325
|
|
|
10180
10326
|
// src/recording/downloader.ts
|
|
10181
|
-
var
|
|
10182
|
-
var
|
|
10327
|
+
var import_node_fs25 = require("fs");
|
|
10328
|
+
var import_node_path21 = require("path");
|
|
10183
10329
|
var import_promises2 = require("stream/promises");
|
|
10184
10330
|
var import_node_stream = require("stream");
|
|
10185
10331
|
var DEFAULT_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
@@ -10189,7 +10335,7 @@ async function downloadFile(url, destPath, logger, options) {
|
|
|
10189
10335
|
const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
10190
10336
|
const maxRetries = options?.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
10191
10337
|
const retryBackoffMs = options?.retryBackoffMs ?? DEFAULT_RETRY_BACKOFF_MS;
|
|
10192
|
-
(0,
|
|
10338
|
+
(0, import_node_fs25.mkdirSync)((0, import_node_path21.dirname)(destPath), { recursive: true });
|
|
10193
10339
|
let lastError;
|
|
10194
10340
|
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
10195
10341
|
const startMs = Date.now();
|
|
@@ -10207,11 +10353,11 @@ async function downloadFile(url, destPath, logger, options) {
|
|
|
10207
10353
|
if (!res.body) {
|
|
10208
10354
|
throw new Error("\u54CD\u5E94\u4F53\u4E3A\u7A7A");
|
|
10209
10355
|
}
|
|
10210
|
-
const writeStream = (0,
|
|
10356
|
+
const writeStream = (0, import_node_fs25.createWriteStream)(destPath);
|
|
10211
10357
|
const readable = import_node_stream.Readable.fromWeb(res.body);
|
|
10212
10358
|
await (0, import_promises2.pipeline)(readable, writeStream);
|
|
10213
10359
|
const elapsed = Date.now() - startMs;
|
|
10214
|
-
const fileSize = (0,
|
|
10360
|
+
const fileSize = (0, import_node_fs25.existsSync)(destPath) ? (0, import_node_fs25.statSync)(destPath).size : 0;
|
|
10215
10361
|
logger.info(
|
|
10216
10362
|
`[downloader] \u4E0B\u8F7D\u5B8C\u6210: ${destPath} (${formatBytes(fileSize)}, ${elapsed}ms)`
|
|
10217
10363
|
);
|
|
@@ -10222,7 +10368,7 @@ async function downloadFile(url, destPath, logger, options) {
|
|
|
10222
10368
|
} catch (err) {
|
|
10223
10369
|
lastError = err?.message ?? String(err);
|
|
10224
10370
|
try {
|
|
10225
|
-
if ((0,
|
|
10371
|
+
if ((0, import_node_fs25.existsSync)(destPath)) (0, import_node_fs25.unlinkSync)(destPath);
|
|
10226
10372
|
} catch {
|
|
10227
10373
|
}
|
|
10228
10374
|
const isAbort = err?.name === "AbortError";
|
|
@@ -10460,13 +10606,13 @@ async function triggerTranscription(recordingId, storage, asrConfig, logger, opt
|
|
|
10460
10606
|
}
|
|
10461
10607
|
|
|
10462
10608
|
// src/tunnel/service.ts
|
|
10463
|
-
var
|
|
10464
|
-
var
|
|
10609
|
+
var import_node_fs30 = require("fs");
|
|
10610
|
+
var import_node_path26 = require("path");
|
|
10465
10611
|
init_credentials();
|
|
10466
10612
|
|
|
10467
10613
|
// src/tunnel/relay-client.ts
|
|
10468
|
-
var
|
|
10469
|
-
var
|
|
10614
|
+
var import_node_fs28 = require("fs");
|
|
10615
|
+
var import_node_path24 = require("path");
|
|
10470
10616
|
|
|
10471
10617
|
// node_modules/.pnpm/ws@8.19.0/node_modules/ws/wrapper.mjs
|
|
10472
10618
|
var import_stream = __toESM(require_stream(), 1);
|
|
@@ -10510,8 +10656,8 @@ var RelayClient = class {
|
|
|
10510
10656
|
lastDisconnectReason
|
|
10511
10657
|
};
|
|
10512
10658
|
try {
|
|
10513
|
-
(0,
|
|
10514
|
-
(0,
|
|
10659
|
+
(0, import_node_fs28.mkdirSync)((0, import_node_path24.dirname)(this.opts.statusFilePath), { recursive: true });
|
|
10660
|
+
(0, import_node_fs28.writeFileSync)(this.opts.statusFilePath, JSON.stringify(info, null, 2));
|
|
10515
10661
|
} catch {
|
|
10516
10662
|
}
|
|
10517
10663
|
}
|
|
@@ -10893,8 +11039,8 @@ init_host();
|
|
|
10893
11039
|
|
|
10894
11040
|
// src/tunnel/device-identity.ts
|
|
10895
11041
|
var import_node_crypto3 = __toESM(require("crypto"), 1);
|
|
10896
|
-
var
|
|
10897
|
-
var
|
|
11042
|
+
var import_node_fs29 = __toESM(require("fs"), 1);
|
|
11043
|
+
var import_node_path25 = __toESM(require("path"), 1);
|
|
10898
11044
|
init_host();
|
|
10899
11045
|
var ED25519_SPKI_PREFIX = Buffer.from("302a300506032b6570032100", "hex");
|
|
10900
11046
|
function base64UrlEncode(buf) {
|
|
@@ -10939,10 +11085,10 @@ function resolveClientStateDir(stateDir) {
|
|
|
10939
11085
|
return stateDir ?? resolveStateDir();
|
|
10940
11086
|
}
|
|
10941
11087
|
function ensureDir(filePath) {
|
|
10942
|
-
|
|
11088
|
+
import_node_fs29.default.mkdirSync(import_node_path25.default.dirname(filePath), { recursive: true });
|
|
10943
11089
|
}
|
|
10944
11090
|
function resolveIdentityPath(stateDir) {
|
|
10945
|
-
return
|
|
11091
|
+
return import_node_path25.default.join(stateDir, "identity", "device.json");
|
|
10946
11092
|
}
|
|
10947
11093
|
function normalizeDeviceAuthRole(role) {
|
|
10948
11094
|
return role.trim();
|
|
@@ -10958,12 +11104,12 @@ function normalizeDeviceAuthScopes(scopes) {
|
|
|
10958
11104
|
return [...out].sort();
|
|
10959
11105
|
}
|
|
10960
11106
|
function resolveDeviceAuthPath(stateDir) {
|
|
10961
|
-
return
|
|
11107
|
+
return import_node_path25.default.join(stateDir, "identity", "device-auth.json");
|
|
10962
11108
|
}
|
|
10963
11109
|
function readDeviceAuthStore(filePath) {
|
|
10964
11110
|
try {
|
|
10965
|
-
if (!
|
|
10966
|
-
const raw =
|
|
11111
|
+
if (!import_node_fs29.default.existsSync(filePath)) return null;
|
|
11112
|
+
const raw = import_node_fs29.default.readFileSync(filePath, "utf8");
|
|
10967
11113
|
const parsed = JSON.parse(raw);
|
|
10968
11114
|
if (parsed?.version !== 1 || typeof parsed.deviceId !== "string") return null;
|
|
10969
11115
|
if (!parsed.tokens || typeof parsed.tokens !== "object") return null;
|
|
@@ -10974,12 +11120,12 @@ function readDeviceAuthStore(filePath) {
|
|
|
10974
11120
|
}
|
|
10975
11121
|
function writeDeviceAuthStore(filePath, store) {
|
|
10976
11122
|
ensureDir(filePath);
|
|
10977
|
-
|
|
11123
|
+
import_node_fs29.default.writeFileSync(filePath, `${JSON.stringify(store, null, 2)}
|
|
10978
11124
|
`, {
|
|
10979
11125
|
mode: 384
|
|
10980
11126
|
});
|
|
10981
11127
|
try {
|
|
10982
|
-
|
|
11128
|
+
import_node_fs29.default.chmodSync(filePath, 384);
|
|
10983
11129
|
} catch {
|
|
10984
11130
|
}
|
|
10985
11131
|
}
|
|
@@ -11026,8 +11172,8 @@ function clearDeviceAuthToken(params) {
|
|
|
11026
11172
|
function loadOrCreateDeviceIdentity(stateDir) {
|
|
11027
11173
|
const filePath = resolveIdentityPath(stateDir);
|
|
11028
11174
|
try {
|
|
11029
|
-
if (
|
|
11030
|
-
const raw =
|
|
11175
|
+
if (import_node_fs29.default.existsSync(filePath)) {
|
|
11176
|
+
const raw = import_node_fs29.default.readFileSync(filePath, "utf8");
|
|
11031
11177
|
const parsed = JSON.parse(raw);
|
|
11032
11178
|
if (parsed?.version === 1 && typeof parsed.deviceId === "string" && typeof parsed.publicKeyPem === "string" && typeof parsed.privateKeyPem === "string") {
|
|
11033
11179
|
const derivedId = fingerprintPublicKey(parsed.publicKeyPem);
|
|
@@ -11048,14 +11194,14 @@ function loadOrCreateDeviceIdentity(stateDir) {
|
|
|
11048
11194
|
publicKeyPem,
|
|
11049
11195
|
privateKeyPem
|
|
11050
11196
|
};
|
|
11051
|
-
|
|
11197
|
+
import_node_fs29.default.mkdirSync(import_node_path25.default.dirname(filePath), { recursive: true });
|
|
11052
11198
|
const stored = {
|
|
11053
11199
|
version: 1,
|
|
11054
11200
|
...identity,
|
|
11055
11201
|
createdAtMs: Date.now()
|
|
11056
11202
|
};
|
|
11057
11203
|
ensureDir(filePath);
|
|
11058
|
-
|
|
11204
|
+
import_node_fs29.default.writeFileSync(filePath, `${JSON.stringify(stored, null, 2)}
|
|
11059
11205
|
`, {
|
|
11060
11206
|
mode: 384
|
|
11061
11207
|
});
|
|
@@ -11825,7 +11971,7 @@ function createTunnelService(opts) {
|
|
|
11825
11971
|
}
|
|
11826
11972
|
function readLockOwner(filePath) {
|
|
11827
11973
|
try {
|
|
11828
|
-
const parsed = JSON.parse((0,
|
|
11974
|
+
const parsed = JSON.parse((0, import_node_fs30.readFileSync)(filePath, "utf-8"));
|
|
11829
11975
|
return typeof parsed.pid === "number" ? parsed.pid : null;
|
|
11830
11976
|
} catch {
|
|
11831
11977
|
return null;
|
|
@@ -11838,23 +11984,23 @@ function createTunnelService(opts) {
|
|
|
11838
11984
|
lockFd = null;
|
|
11839
11985
|
if (fd !== null) {
|
|
11840
11986
|
try {
|
|
11841
|
-
(0,
|
|
11987
|
+
(0, import_node_fs30.closeSync)(fd);
|
|
11842
11988
|
} catch {
|
|
11843
11989
|
}
|
|
11844
11990
|
}
|
|
11845
11991
|
if (filePath) {
|
|
11846
11992
|
try {
|
|
11847
|
-
(0,
|
|
11993
|
+
(0, import_node_fs30.unlinkSync)(filePath);
|
|
11848
11994
|
} catch {
|
|
11849
11995
|
}
|
|
11850
11996
|
}
|
|
11851
11997
|
}
|
|
11852
11998
|
function acquireLock(filePath) {
|
|
11853
|
-
(0,
|
|
11999
|
+
(0, import_node_fs30.mkdirSync)((0, import_node_path26.dirname)(filePath), { recursive: true });
|
|
11854
12000
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
11855
12001
|
try {
|
|
11856
|
-
const fd = (0,
|
|
11857
|
-
(0,
|
|
12002
|
+
const fd = (0, import_node_fs30.openSync)(filePath, "wx", 384);
|
|
12003
|
+
(0, import_node_fs30.writeFileSync)(
|
|
11858
12004
|
fd,
|
|
11859
12005
|
JSON.stringify({
|
|
11860
12006
|
pid: process.pid,
|
|
@@ -11878,7 +12024,7 @@ function createTunnelService(opts) {
|
|
|
11878
12024
|
`Relay tunnel: removing stale local lock owned by dead pid=${ownerPid}`
|
|
11879
12025
|
);
|
|
11880
12026
|
try {
|
|
11881
|
-
(0,
|
|
12027
|
+
(0, import_node_fs30.unlinkSync)(filePath);
|
|
11882
12028
|
} catch {
|
|
11883
12029
|
}
|
|
11884
12030
|
continue;
|
|
@@ -11923,12 +12069,12 @@ function createTunnelService(opts) {
|
|
|
11923
12069
|
return;
|
|
11924
12070
|
}
|
|
11925
12071
|
const { logger } = opts;
|
|
11926
|
-
const baseStateDir = (0,
|
|
12072
|
+
const baseStateDir = (0, import_node_path26.join)(ctx.stateDir, "plugins", "phone-notifications");
|
|
11927
12073
|
logger.info(
|
|
11928
12074
|
`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
12075
|
);
|
|
11930
|
-
const statusFilePath = (0,
|
|
11931
|
-
const lockPath = (0,
|
|
12076
|
+
const statusFilePath = (0, import_node_path26.join)(baseStateDir, "tunnel-status.json");
|
|
12077
|
+
const lockPath = (0, import_node_path26.join)(baseStateDir, "relay-tunnel.lock");
|
|
11932
12078
|
if (!acquireLock(lockPath)) {
|
|
11933
12079
|
return;
|
|
11934
12080
|
}
|
|
@@ -12068,7 +12214,7 @@ function readHostGatewayConfig(params) {
|
|
|
12068
12214
|
let configData;
|
|
12069
12215
|
if (configPath) {
|
|
12070
12216
|
try {
|
|
12071
|
-
configData = JSON.parse((0,
|
|
12217
|
+
configData = JSON.parse((0, import_node_fs31.readFileSync)(configPath, "utf-8"));
|
|
12072
12218
|
} catch (err) {
|
|
12073
12219
|
if (err?.code !== "ENOENT") {
|
|
12074
12220
|
params.logger.warn(
|