@yoooclaw/phone-notifications 1.11.1 → 1.11.2-beta.1
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 +432 -407
- package/dist/index.cjs.map +1 -1
- package/package.json +1 -1
- package/skills/notification-search/SKILL.md +3 -2
package/dist/index.cjs
CHANGED
|
@@ -270,14 +270,16 @@ var init_env = __esm({
|
|
|
270
270
|
relayTunnelUrl: "wss://openclaw-service-dev.yoooclaw.com/message/messages/ws/plugin",
|
|
271
271
|
appNameMapUrl: "https://openclaw-service-dev.yoooclaw.com/api/application-config/app-package/config-all",
|
|
272
272
|
modelProxyLongRecordingSubmitTaskUrl: "https://openclaw-service-dev.yoooclaw.com/api/model-proxy/long-recording/submit-task",
|
|
273
|
-
modelProxyLongRecordingQueryTaskResultBaseUrl: "https://openclaw-service-dev.yoooclaw.com/api/model-proxy/long-recording/query-task-result"
|
|
273
|
+
modelProxyLongRecordingQueryTaskResultBaseUrl: "https://openclaw-service-dev.yoooclaw.com/api/model-proxy/long-recording/query-task-result",
|
|
274
|
+
accountFileDeleteUrl: "https://openclaw-service-dev.yoooclaw.com/account/file/delete"
|
|
274
275
|
},
|
|
275
276
|
production: {
|
|
276
277
|
lightApiUrl: "https://openclaw-service.yoootek.com/api/message/tob/sendMessage",
|
|
277
278
|
relayTunnelUrl: "wss://openclaw-service.yoootek.com/message/messages/ws/plugin",
|
|
278
279
|
appNameMapUrl: "https://openclaw-service.yoootek.com/api/application-config/app-package/config-all",
|
|
279
280
|
modelProxyLongRecordingSubmitTaskUrl: "https://openclaw-service.yoootek.com/api/model-proxy/long-recording/submit-task",
|
|
280
|
-
modelProxyLongRecordingQueryTaskResultBaseUrl: "https://openclaw-service.yoootek.com/api/model-proxy/long-recording/query-task-result"
|
|
281
|
+
modelProxyLongRecordingQueryTaskResultBaseUrl: "https://openclaw-service.yoootek.com/api/model-proxy/long-recording/query-task-result",
|
|
282
|
+
accountFileDeleteUrl: "https://openclaw-service.yoootek.com/account/file/delete"
|
|
281
283
|
}
|
|
282
284
|
};
|
|
283
285
|
VALID_ENVS = new Set(Object.keys(ENV_CONFIG));
|
|
@@ -535,20 +537,20 @@ function selectModelByMemory(availableGB, isAppleSilicon = false) {
|
|
|
535
537
|
return "tiny";
|
|
536
538
|
}
|
|
537
539
|
function resolveModelsDir(dataDir) {
|
|
538
|
-
const dir = (0,
|
|
539
|
-
(0,
|
|
540
|
+
const dir = (0, import_node_path21.join)(dataDir, WHISPER_MODELS_DIR);
|
|
541
|
+
(0, import_node_fs25.mkdirSync)(dir, { recursive: true });
|
|
540
542
|
return dir;
|
|
541
543
|
}
|
|
542
544
|
function resolveBinDir(dataDir) {
|
|
543
|
-
const dir = (0,
|
|
544
|
-
(0,
|
|
545
|
+
const dir = (0, import_node_path21.join)(dataDir, WHISPER_BIN_DIR);
|
|
546
|
+
(0, import_node_fs25.mkdirSync)(dir, { recursive: true });
|
|
545
547
|
return dir;
|
|
546
548
|
}
|
|
547
549
|
function isModelDownloaded(modelsDir, modelSize) {
|
|
548
|
-
const modelPath = (0,
|
|
549
|
-
if (!(0,
|
|
550
|
+
const modelPath = (0, import_node_path21.join)(modelsDir, MODEL_FILENAMES[modelSize]);
|
|
551
|
+
if (!(0, import_node_fs25.existsSync)(modelPath)) return false;
|
|
550
552
|
try {
|
|
551
|
-
const stat = (0,
|
|
553
|
+
const stat = (0, import_node_fs25.statSync)(modelPath);
|
|
552
554
|
const expectedSize = MODEL_DISK_SIZES[modelSize];
|
|
553
555
|
return stat.size >= expectedSize * 0.8;
|
|
554
556
|
} catch {
|
|
@@ -557,7 +559,7 @@ function isModelDownloaded(modelsDir, modelSize) {
|
|
|
557
559
|
}
|
|
558
560
|
async function downloadModel(modelsDir, modelSize, logger, modelSource, mirrorUrl) {
|
|
559
561
|
const filename = MODEL_FILENAMES[modelSize];
|
|
560
|
-
const modelPath = (0,
|
|
562
|
+
const modelPath = (0, import_node_path21.join)(modelsDir, filename);
|
|
561
563
|
if (isModelDownloaded(modelsDir, modelSize)) {
|
|
562
564
|
logger.info(`[whisper-local] \u6A21\u578B\u5DF2\u5B58\u5728\uFF0C\u8DF3\u8FC7\u4E0B\u8F7D: ${filename}`);
|
|
563
565
|
return { ok: true, modelPath };
|
|
@@ -623,7 +625,7 @@ async function probeUrl(url, logger) {
|
|
|
623
625
|
async function downloadFromUrl(url, modelPath, logger) {
|
|
624
626
|
const tmpPath = `${modelPath}.downloading`;
|
|
625
627
|
try {
|
|
626
|
-
(0,
|
|
628
|
+
(0, import_node_fs25.mkdirSync)((0, import_node_path21.dirname)(modelPath), { recursive: true });
|
|
627
629
|
const controller = new AbortController();
|
|
628
630
|
const timer = setTimeout(() => controller.abort(), 30 * 60 * 1e3);
|
|
629
631
|
try {
|
|
@@ -639,7 +641,7 @@ async function downloadFromUrl(url, modelPath, logger) {
|
|
|
639
641
|
return { ok: false, modelPath, error: "\u6A21\u578B\u4E0B\u8F7D\u5931\u8D25: \u54CD\u5E94\u4F53\u4E3A\u7A7A" };
|
|
640
642
|
}
|
|
641
643
|
const contentLength = Number(res.headers.get("content-length") ?? 0);
|
|
642
|
-
const writeStream = (0,
|
|
644
|
+
const writeStream = (0, import_node_fs25.createWriteStream)(tmpPath);
|
|
643
645
|
const readable = import_node_stream2.Readable.fromWeb(res.body);
|
|
644
646
|
let downloaded = 0;
|
|
645
647
|
let lastLogPercent = 0;
|
|
@@ -661,14 +663,14 @@ async function downloadFromUrl(url, modelPath, logger) {
|
|
|
661
663
|
}
|
|
662
664
|
const { renameSync: renameSync2 } = await import("fs");
|
|
663
665
|
renameSync2(tmpPath, modelPath);
|
|
664
|
-
const fileSize = (0,
|
|
666
|
+
const fileSize = (0, import_node_fs25.statSync)(modelPath).size;
|
|
665
667
|
logger.info(
|
|
666
|
-
`[whisper-local] \u6A21\u578B\u4E0B\u8F7D\u5B8C\u6210: ${(0,
|
|
668
|
+
`[whisper-local] \u6A21\u578B\u4E0B\u8F7D\u5B8C\u6210: ${(0, import_node_path21.basename)(modelPath)} (${formatBytes2(fileSize)})`
|
|
667
669
|
);
|
|
668
670
|
return { ok: true, modelPath };
|
|
669
671
|
} catch (err2) {
|
|
670
672
|
try {
|
|
671
|
-
if ((0,
|
|
673
|
+
if ((0, import_node_fs25.existsSync)(tmpPath)) (0, import_node_fs25.unlinkSync)(tmpPath);
|
|
672
674
|
} catch {
|
|
673
675
|
}
|
|
674
676
|
const msg = err2?.name === "AbortError" ? "\u6A21\u578B\u4E0B\u8F7D\u8D85\u65F6\uFF0830 \u5206\u949F\uFF09" : err2?.message ?? String(err2);
|
|
@@ -680,8 +682,8 @@ function findWhisperBinary(dataDir, logger) {
|
|
|
680
682
|
const binDir = resolveBinDir(dataDir);
|
|
681
683
|
const binNames = (0, import_node_os4.platform)() === "win32" ? ["whisper-cli.exe", "whisper.exe", "main.exe"] : ["whisper-cli", "whisper", "main"];
|
|
682
684
|
for (const name of binNames) {
|
|
683
|
-
const binPath = (0,
|
|
684
|
-
if ((0,
|
|
685
|
+
const binPath = (0, import_node_path21.join)(binDir, name);
|
|
686
|
+
if ((0, import_node_fs25.existsSync)(binPath)) {
|
|
685
687
|
logger.info(`[whisper-local] \u627E\u5230\u672C\u5730\u4E8C\u8FDB\u5236: ${binPath}`);
|
|
686
688
|
return binPath;
|
|
687
689
|
}
|
|
@@ -732,7 +734,7 @@ async function transcribeWithWhisperLocal(audioFilePath, localConfig, dataDir, l
|
|
|
732
734
|
return { ok: false, error: `\u6A21\u578B\u4E0B\u8F7D\u5931\u8D25: ${downloadResult.error}` };
|
|
733
735
|
}
|
|
734
736
|
}
|
|
735
|
-
const modelPath = (0,
|
|
737
|
+
const modelPath = (0, import_node_path21.join)(modelsDir, MODEL_FILENAMES[modelSize]);
|
|
736
738
|
let inputPath = audioFilePath;
|
|
737
739
|
let tmpWavPath = null;
|
|
738
740
|
const actualFmt = detectAudioFormat(audioFilePath);
|
|
@@ -784,10 +786,10 @@ async function transcribeWithWhisperLocal(audioFilePath, localConfig, dataDir, l
|
|
|
784
786
|
logger.info(`[whisper-local] \u8F6C\u5199\u8017\u65F6: ${Math.round(elapsed / 1e3)}s`);
|
|
785
787
|
const jsonPath = inputPath + ".json";
|
|
786
788
|
let jsonContent;
|
|
787
|
-
if ((0,
|
|
788
|
-
jsonContent = (0,
|
|
789
|
+
if ((0, import_node_fs25.existsSync)(jsonPath)) {
|
|
790
|
+
jsonContent = (0, import_node_fs25.readFileSync)(jsonPath, "utf-8");
|
|
789
791
|
try {
|
|
790
|
-
(0,
|
|
792
|
+
(0, import_node_fs25.unlinkSync)(jsonPath);
|
|
791
793
|
} catch {
|
|
792
794
|
}
|
|
793
795
|
} else {
|
|
@@ -865,10 +867,10 @@ function getPhysicalCoreCount() {
|
|
|
865
867
|
}
|
|
866
868
|
function detectAudioFormat(filePath) {
|
|
867
869
|
try {
|
|
868
|
-
const fd = (0,
|
|
870
|
+
const fd = (0, import_node_fs25.openSync)(filePath, "r");
|
|
869
871
|
const buf = Buffer.alloc(12);
|
|
870
|
-
(0,
|
|
871
|
-
(0,
|
|
872
|
+
(0, import_node_fs25.readSync)(fd, buf, 0, 12, 0);
|
|
873
|
+
(0, import_node_fs25.closeSync)(fd);
|
|
872
874
|
const header = buf.toString("ascii", 0, 4);
|
|
873
875
|
const header8 = buf.toString("ascii", 0, 8);
|
|
874
876
|
if (header === "RIFF" && buf.toString("ascii", 8, 12) === "WAVE") return ".wav";
|
|
@@ -903,7 +905,7 @@ function convertToWav(inputPath, outputPath, actualFmt, logger) {
|
|
|
903
905
|
timeout: 12e4,
|
|
904
906
|
stdio: ["pipe", "pipe", "pipe"]
|
|
905
907
|
});
|
|
906
|
-
if (ffmpegResult.status === 0 && (0,
|
|
908
|
+
if (ffmpegResult.status === 0 && (0, import_node_fs25.existsSync)(outputPath)) {
|
|
907
909
|
logger.info(`[whisper-local] ffmpeg \u8F6C\u6362\u5B8C\u6210: ${outputPath}`);
|
|
908
910
|
return { ok: true };
|
|
909
911
|
}
|
|
@@ -916,7 +918,7 @@ function convertToWav(inputPath, outputPath, actualFmt, logger) {
|
|
|
916
918
|
["--rate", "16000", "--mono", inputPath, outputPath],
|
|
917
919
|
{ encoding: "utf-8", timeout: 12e4, stdio: ["pipe", "pipe", "pipe"] }
|
|
918
920
|
);
|
|
919
|
-
if (opusResult.status === 0 && (0,
|
|
921
|
+
if (opusResult.status === 0 && (0, import_node_fs25.existsSync)(outputPath)) {
|
|
920
922
|
logger.info(`[whisper-local] opusdec \u8F6C\u6362\u5B8C\u6210: ${outputPath}`);
|
|
921
923
|
return { ok: true };
|
|
922
924
|
}
|
|
@@ -930,7 +932,7 @@ function convertToWav(inputPath, outputPath, actualFmt, logger) {
|
|
|
930
932
|
if (detectedExt && !inputPath.endsWith(detectedExt)) {
|
|
931
933
|
tmpCopy = inputPath + ".detected" + detectedExt;
|
|
932
934
|
try {
|
|
933
|
-
(0,
|
|
935
|
+
(0, import_node_fs25.copyFileSync)(inputPath, tmpCopy);
|
|
934
936
|
actualInputPath = tmpCopy;
|
|
935
937
|
logger.info(
|
|
936
938
|
`[whisper-local] \u68C0\u6D4B\u5230\u5B9E\u9645\u683C\u5F0F ${detectedExt}\uFF0C\u4E34\u65F6\u91CD\u547D\u540D`
|
|
@@ -954,22 +956,22 @@ function convertToWav(inputPath, outputPath, actualFmt, logger) {
|
|
|
954
956
|
timeout: 12e4,
|
|
955
957
|
stdio: ["pipe", "pipe", "pipe"]
|
|
956
958
|
});
|
|
957
|
-
if (tmpCopy && (0,
|
|
959
|
+
if (tmpCopy && (0, import_node_fs25.existsSync)(tmpCopy)) {
|
|
958
960
|
try {
|
|
959
|
-
(0,
|
|
961
|
+
(0, import_node_fs25.unlinkSync)(tmpCopy);
|
|
960
962
|
} catch {
|
|
961
963
|
}
|
|
962
964
|
}
|
|
963
|
-
if (afResult.status === 0 && (0,
|
|
965
|
+
if (afResult.status === 0 && (0, import_node_fs25.existsSync)(outputPath)) {
|
|
964
966
|
logger.info(`[whisper-local] afconvert \u8F6C\u6362\u5B8C\u6210: ${outputPath}`);
|
|
965
967
|
return { ok: true };
|
|
966
968
|
}
|
|
967
969
|
const stderr = afResult.stderr?.slice(0, 200) ?? "";
|
|
968
970
|
return { ok: false, error: `afconvert \u8F6C\u6362\u5931\u8D25 (exit ${afResult.status}): ${stderr}` };
|
|
969
971
|
} catch (err2) {
|
|
970
|
-
if (tmpCopy && (0,
|
|
972
|
+
if (tmpCopy && (0, import_node_fs25.existsSync)(tmpCopy)) {
|
|
971
973
|
try {
|
|
972
|
-
(0,
|
|
974
|
+
(0, import_node_fs25.unlinkSync)(tmpCopy);
|
|
973
975
|
} catch {
|
|
974
976
|
}
|
|
975
977
|
}
|
|
@@ -980,9 +982,9 @@ function convertToWav(inputPath, outputPath, actualFmt, logger) {
|
|
|
980
982
|
return { ok: false, error: `\u65E0\u6CD5\u5C06\u97F3\u9891\u8F6C\u6362\u4E3A WAV \u683C\u5F0F\u3002${fmtHint}` };
|
|
981
983
|
}
|
|
982
984
|
function cleanupTmpWav(path2) {
|
|
983
|
-
if (path2 && (0,
|
|
985
|
+
if (path2 && (0, import_node_fs25.existsSync)(path2)) {
|
|
984
986
|
try {
|
|
985
|
-
(0,
|
|
987
|
+
(0, import_node_fs25.unlinkSync)(path2);
|
|
986
988
|
} catch {
|
|
987
989
|
}
|
|
988
990
|
}
|
|
@@ -1068,13 +1070,13 @@ function formatBytes2(bytes) {
|
|
|
1068
1070
|
if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
1069
1071
|
return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)}GB`;
|
|
1070
1072
|
}
|
|
1071
|
-
var import_node_child_process2,
|
|
1073
|
+
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;
|
|
1072
1074
|
var init_whisper_local = __esm({
|
|
1073
1075
|
"src/recording/whisper-local.ts"() {
|
|
1074
1076
|
"use strict";
|
|
1075
1077
|
import_node_child_process2 = require("child_process");
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
+
import_node_fs25 = require("fs");
|
|
1079
|
+
import_node_path21 = require("path");
|
|
1078
1080
|
import_promises3 = require("stream/promises");
|
|
1079
1081
|
import_node_stream2 = require("stream");
|
|
1080
1082
|
import_node_os4 = require("os");
|
|
@@ -1229,7 +1231,7 @@ async function initializeAsr(config, dataDir, logger) {
|
|
|
1229
1231
|
}
|
|
1230
1232
|
}
|
|
1231
1233
|
async function transcribeAudio(audioFilePath, config, logger, options = {}) {
|
|
1232
|
-
if (!(0,
|
|
1234
|
+
if (!(0, import_node_fs26.existsSync)(audioFilePath)) {
|
|
1233
1235
|
return { ok: false, error: `\u97F3\u9891\u6587\u4EF6\u4E0D\u5B58\u5728: ${audioFilePath}` };
|
|
1234
1236
|
}
|
|
1235
1237
|
logger.info(
|
|
@@ -1240,6 +1242,7 @@ async function transcribeAudio(audioFilePath, config, logger, options = {}) {
|
|
|
1240
1242
|
case "api":
|
|
1241
1243
|
return await transcribeWithModelProxy(
|
|
1242
1244
|
options.audioOssUrl,
|
|
1245
|
+
options.audioDurationMs,
|
|
1243
1246
|
config.api,
|
|
1244
1247
|
logger
|
|
1245
1248
|
);
|
|
@@ -1339,7 +1342,8 @@ async function runTranscriptionWorkflow(params) {
|
|
|
1339
1342
|
logger
|
|
1340
1343
|
} = params;
|
|
1341
1344
|
const result = await transcribeAudio(audioFilePath, config, logger, {
|
|
1342
|
-
audioOssUrl
|
|
1345
|
+
audioOssUrl,
|
|
1346
|
+
audioDurationMs: Math.max(0, Math.round(durationSec * 1e3))
|
|
1343
1347
|
});
|
|
1344
1348
|
if (!result.ok) {
|
|
1345
1349
|
return { ok: false, error: result.error };
|
|
@@ -1373,8 +1377,8 @@ async function runTranscriptionWorkflow(params) {
|
|
|
1373
1377
|
createdAt
|
|
1374
1378
|
);
|
|
1375
1379
|
const transcriptDataFilename = buildTranscriptDataFilename(recordingId);
|
|
1376
|
-
const transcriptDataPath = (0,
|
|
1377
|
-
(0,
|
|
1380
|
+
const transcriptDataPath = (0, import_node_path22.join)(transcriptDataDir, transcriptDataFilename);
|
|
1381
|
+
(0, import_node_fs26.writeFileSync)(
|
|
1378
1382
|
transcriptDataPath,
|
|
1379
1383
|
JSON.stringify(transcriptData, null, 2),
|
|
1380
1384
|
"utf-8"
|
|
@@ -1382,14 +1386,14 @@ async function runTranscriptionWorkflow(params) {
|
|
|
1382
1386
|
logger.info(`[asr] \u8F6C\u5199 JSON \u5DF2\u5199\u5165: ${transcriptDataPath}`);
|
|
1383
1387
|
const safeSummary = title.replace(/[/\\:*?"<>|]/g, "").trim().slice(0, 20);
|
|
1384
1388
|
const filename = safeSummary ? `${recordingId}_${safeSummary}.md` : `${recordingId}.md`;
|
|
1385
|
-
const filePath = (0,
|
|
1386
|
-
(0,
|
|
1389
|
+
const filePath = (0, import_node_path22.join)(transcriptsDir, filename);
|
|
1390
|
+
(0, import_node_fs26.writeFileSync)(filePath, markdown, "utf-8");
|
|
1387
1391
|
logger.info(`[asr] \u8F6C\u5199\u6587\u672C\u5DF2\u5199\u5165: ${filePath}`);
|
|
1388
1392
|
let summaryFilename;
|
|
1389
1393
|
if (summary) {
|
|
1390
1394
|
summaryFilename = `${recordingId}.md`;
|
|
1391
|
-
const summaryFilePath = (0,
|
|
1392
|
-
(0,
|
|
1395
|
+
const summaryFilePath = (0, import_node_path22.join)(summariesDir, summaryFilename);
|
|
1396
|
+
(0, import_node_fs26.writeFileSync)(summaryFilePath, summary, "utf-8");
|
|
1393
1397
|
logger.info(`[asr] \u6458\u8981\u6587\u672C\u5DF2\u5199\u5165: ${summaryFilePath}`);
|
|
1394
1398
|
}
|
|
1395
1399
|
return {
|
|
@@ -1402,7 +1406,7 @@ async function runTranscriptionWorkflow(params) {
|
|
|
1402
1406
|
title
|
|
1403
1407
|
};
|
|
1404
1408
|
}
|
|
1405
|
-
async function transcribeWithModelProxy(audioOssUrl, apiConfig, logger) {
|
|
1409
|
+
async function transcribeWithModelProxy(audioOssUrl, audioDurationMs, apiConfig, logger) {
|
|
1406
1410
|
const normalizedAudioOssUrl = normalizeOptionalText2(audioOssUrl);
|
|
1407
1411
|
if (!normalizedAudioOssUrl) {
|
|
1408
1412
|
return { ok: false, error: "API \u6A21\u5F0F\u7F3A\u5C11 audioOssUrl\uFF0C\u65E0\u6CD5\u8C03\u7528 model-proxy" };
|
|
@@ -1468,13 +1472,14 @@ async function transcribeWithModelProxy(audioOssUrl, apiConfig, logger) {
|
|
|
1468
1472
|
apiKey,
|
|
1469
1473
|
taskId,
|
|
1470
1474
|
initialRequestId: requestId,
|
|
1475
|
+
audioDurationMs,
|
|
1471
1476
|
apiConfig,
|
|
1472
1477
|
logger
|
|
1473
1478
|
});
|
|
1474
1479
|
}
|
|
1475
1480
|
async function transcribeWithWhisperLocal2(audioFilePath, config, logger) {
|
|
1476
1481
|
const { transcribeWithWhisperLocal: runLocal } = await Promise.resolve().then(() => (init_whisper_local(), whisper_local_exports));
|
|
1477
|
-
const dataDir = process.env.OPENCLAW_STATE_DIR ?? process.env.QCLAW_STATE_DIR ?? (0,
|
|
1482
|
+
const dataDir = process.env.OPENCLAW_STATE_DIR ?? process.env.QCLAW_STATE_DIR ?? (0, import_node_path22.join)(audioFilePath, "..", "..", "..");
|
|
1478
1483
|
const localConfig = config.local ?? {};
|
|
1479
1484
|
const result = await runLocal(
|
|
1480
1485
|
audioFilePath,
|
|
@@ -1530,6 +1535,7 @@ async function pollLongRecordingTaskResult(params) {
|
|
|
1530
1535
|
apiKey,
|
|
1531
1536
|
taskId,
|
|
1532
1537
|
initialRequestId,
|
|
1538
|
+
audioDurationMs,
|
|
1533
1539
|
apiConfig,
|
|
1534
1540
|
logger
|
|
1535
1541
|
} = params;
|
|
@@ -1577,7 +1583,13 @@ async function pollLongRecordingTaskResult(params) {
|
|
|
1577
1583
|
lastStatus = status;
|
|
1578
1584
|
}
|
|
1579
1585
|
if (status === "SUCCEEDED") {
|
|
1580
|
-
return buildLongRecordingSuccessResult(
|
|
1586
|
+
return buildLongRecordingSuccessResult(
|
|
1587
|
+
taskId,
|
|
1588
|
+
requestId,
|
|
1589
|
+
data,
|
|
1590
|
+
audioDurationMs,
|
|
1591
|
+
logger
|
|
1592
|
+
);
|
|
1581
1593
|
}
|
|
1582
1594
|
if (LONG_RECORDING_TERMINAL_FAILURE_STATUSES.has(status)) {
|
|
1583
1595
|
return {
|
|
@@ -1600,11 +1612,11 @@ async function pollLongRecordingTaskResult(params) {
|
|
|
1600
1612
|
error: `Model Proxy ASR \u8F6E\u8BE2\u8D85\u65F6: taskId=${taskId}, waited=${DEFAULT_LONG_RECORDING_MAX_POLL_ATTEMPTS * DEFAULT_LONG_RECORDING_POLL_INTERVAL_MS}ms`
|
|
1601
1613
|
};
|
|
1602
1614
|
}
|
|
1603
|
-
function buildLongRecordingSuccessResult(taskId, requestId, data, logger) {
|
|
1615
|
+
function buildLongRecordingSuccessResult(taskId, requestId, data, audioDurationMs, logger) {
|
|
1604
1616
|
const sourceTextList = normalizeLongRecordingSourceTextList(
|
|
1605
1617
|
data?.recordResult?.sourceTextList
|
|
1606
1618
|
);
|
|
1607
|
-
const listResult = extractLongRecordingTextFromList(sourceTextList);
|
|
1619
|
+
const listResult = extractLongRecordingTextFromList(sourceTextList, audioDurationMs);
|
|
1608
1620
|
const sourceText = normalizeOptionalText2(data?.recordResult?.sourceText);
|
|
1609
1621
|
const summaryText = normalizeOptionalText2(data?.recordResult?.summaryResult) ?? "";
|
|
1610
1622
|
const title = normalizeOptionalText2(data?.recordResult?.title);
|
|
@@ -1701,11 +1713,12 @@ function normalizeLongRecordingSourceTextList(value) {
|
|
|
1701
1713
|
return [{
|
|
1702
1714
|
content,
|
|
1703
1715
|
speakerId: normalizeOptionalInteger2(record.speakerId),
|
|
1704
|
-
startTime: normalizeOptionalNonNegativeNumber(record.startTime)
|
|
1716
|
+
startTime: normalizeOptionalNonNegativeNumber(record.startTime),
|
|
1717
|
+
endTime: normalizeOptionalNonNegativeNumber(record.endTime)
|
|
1705
1718
|
}];
|
|
1706
1719
|
});
|
|
1707
1720
|
}
|
|
1708
|
-
function extractLongRecordingTextFromList(items) {
|
|
1721
|
+
function extractLongRecordingTextFromList(items, finalFallbackEndMs) {
|
|
1709
1722
|
if (items.length === 0) {
|
|
1710
1723
|
return {
|
|
1711
1724
|
segments: []
|
|
@@ -1713,10 +1726,13 @@ function extractLongRecordingTextFromList(items) {
|
|
|
1713
1726
|
}
|
|
1714
1727
|
const segments = items.map((item, index) => {
|
|
1715
1728
|
const startMs = item.startTime ?? 0;
|
|
1729
|
+
const explicitEndMs = item.endTime;
|
|
1716
1730
|
const nextStart = items[index + 1]?.startTime;
|
|
1731
|
+
const fallbackEndMs = index === items.length - 1 ? normalizeOptionalNonNegativeNumber(finalFallbackEndMs) : void 0;
|
|
1732
|
+
const endMs = explicitEndMs ?? nextStart ?? fallbackEndMs ?? startMs;
|
|
1717
1733
|
return {
|
|
1718
1734
|
start_ms: startMs,
|
|
1719
|
-
end_ms:
|
|
1735
|
+
end_ms: Math.max(startMs, endMs),
|
|
1720
1736
|
text: item.content,
|
|
1721
1737
|
speaker_id: item.speakerId
|
|
1722
1738
|
};
|
|
@@ -1772,17 +1788,17 @@ function formatTranscriptSegmentText(segment) {
|
|
|
1772
1788
|
}
|
|
1773
1789
|
return text;
|
|
1774
1790
|
}
|
|
1775
|
-
var
|
|
1791
|
+
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;
|
|
1776
1792
|
var init_asr = __esm({
|
|
1777
1793
|
"src/recording/asr.ts"() {
|
|
1778
1794
|
"use strict";
|
|
1779
|
-
|
|
1780
|
-
|
|
1795
|
+
import_node_fs26 = require("fs");
|
|
1796
|
+
import_node_path22 = require("path");
|
|
1781
1797
|
init_credentials();
|
|
1782
1798
|
init_env();
|
|
1783
1799
|
init_transcript_document();
|
|
1784
1800
|
DEFAULT_LONG_RECORDING_POLL_INTERVAL_MS = 2e3;
|
|
1785
|
-
DEFAULT_LONG_RECORDING_MAX_POLL_ATTEMPTS =
|
|
1801
|
+
DEFAULT_LONG_RECORDING_MAX_POLL_ATTEMPTS = 3600;
|
|
1786
1802
|
LONG_RECORDING_RUNNING_STATUSES = /* @__PURE__ */ new Set(["PENDING", "RUNNING", "SUSPENDED"]);
|
|
1787
1803
|
LONG_RECORDING_TERMINAL_FAILURE_STATUSES = /* @__PURE__ */ new Set(["FAILED", "CANCELED", "UNKNOWN"]);
|
|
1788
1804
|
}
|
|
@@ -5422,7 +5438,7 @@ function readBuildInjectedVersion() {
|
|
|
5422
5438
|
if (false) {
|
|
5423
5439
|
return void 0;
|
|
5424
5440
|
}
|
|
5425
|
-
const version = "1.11.1".trim();
|
|
5441
|
+
const version = "1.11.2-beta.1".trim();
|
|
5426
5442
|
return version || void 0;
|
|
5427
5443
|
}
|
|
5428
5444
|
function readPluginVersionFromPackageJson() {
|
|
@@ -6035,20 +6051,17 @@ function readOptionalString(value) {
|
|
|
6035
6051
|
const trimmed = value.trim();
|
|
6036
6052
|
return trimmed || void 0;
|
|
6037
6053
|
}
|
|
6038
|
-
function isLegacyLightRuleWithoutType(raw) {
|
|
6039
|
-
return raw.type === void 0 && readOptionalString(raw.name) !== void 0 && readOptionalString(raw.description) !== void 0 && Array.isArray(raw.segments);
|
|
6040
|
-
}
|
|
6041
6054
|
function readMeta(taskDir) {
|
|
6042
6055
|
const metaPath = (0, import_node_path3.join)(taskDir, "meta.json");
|
|
6043
6056
|
if (!(0, import_node_fs4.existsSync)(metaPath)) return null;
|
|
6044
6057
|
try {
|
|
6045
6058
|
const raw = JSON.parse((0, import_node_fs4.readFileSync)(metaPath, "utf-8"));
|
|
6046
6059
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
|
|
6047
|
-
if (raw.type !== "light-rule"
|
|
6060
|
+
if (raw.type !== "light-rule") return null;
|
|
6048
6061
|
if (!Array.isArray(raw.segments)) return null;
|
|
6049
6062
|
const name = readOptionalString(raw.name) ?? (0, import_node_path3.basename)(taskDir);
|
|
6050
6063
|
const title = readOptionalString(raw.title) ?? name;
|
|
6051
|
-
const description = readOptionalString(raw.description) ??
|
|
6064
|
+
const description = readOptionalString(raw.description) ?? name;
|
|
6052
6065
|
const createdAt = readOptionalString(raw.createdAt) ?? (0, import_node_fs4.statSync)(metaPath).birthtime.toISOString();
|
|
6053
6066
|
const enabled = typeof raw.enabled === "boolean" ? raw.enabled : true;
|
|
6054
6067
|
const repeatTimes = normalizeRepeatTimes({
|
|
@@ -7075,115 +7088,6 @@ var InlineLightRuleEvaluator = class {
|
|
|
7075
7088
|
}
|
|
7076
7089
|
};
|
|
7077
7090
|
|
|
7078
|
-
// src/light-rules/migration.ts
|
|
7079
|
-
var import_node_fs8 = require("fs");
|
|
7080
|
-
var import_node_path7 = require("path");
|
|
7081
|
-
var NO_MATCH_FETCH_PY = `#!/usr/bin/env python3
|
|
7082
|
-
# \u6B64\u6587\u4EF6\u7531\u8FC1\u79FB\u5DE5\u5177\u751F\u6210\u3002
|
|
7083
|
-
# \u706F\u6548\u89C4\u5219\u5DF2\u8FC1\u79FB\u81F3\u4E8B\u4EF6\u9A71\u52A8\u67B6\u6784\uFF0C\u6B64 cron job \u4E0D\u518D\u6267\u884C\u5B9E\u9645\u5DE5\u4F5C\u3002
|
|
7084
|
-
print("NO_MATCH")
|
|
7085
|
-
`;
|
|
7086
|
-
function normalizeScriptText(text) {
|
|
7087
|
-
return text.replace(/\r\n/g, "\n").trim();
|
|
7088
|
-
}
|
|
7089
|
-
function resolveTasksDir(ctx) {
|
|
7090
|
-
if (ctx.workspaceDir) return (0, import_node_path7.join)(ctx.workspaceDir, "tasks");
|
|
7091
|
-
if (ctx.stateDir) {
|
|
7092
|
-
const inferredWorkspaceDir = (0, import_node_path7.join)(ctx.stateDir, "workspace");
|
|
7093
|
-
if ((0, import_node_fs8.existsSync)(inferredWorkspaceDir)) return (0, import_node_path7.join)(inferredWorkspaceDir, "tasks");
|
|
7094
|
-
return (0, import_node_path7.join)(ctx.stateDir, "tasks");
|
|
7095
|
-
}
|
|
7096
|
-
return null;
|
|
7097
|
-
}
|
|
7098
|
-
function migrateLegacyLightRuleTasks(ctx, logger) {
|
|
7099
|
-
const tasksDir3 = resolveTasksDir(ctx);
|
|
7100
|
-
if (!tasksDir3 || !(0, import_node_fs8.existsSync)(tasksDir3)) return;
|
|
7101
|
-
try {
|
|
7102
|
-
for (const entry of (0, import_node_fs8.readdirSync)(tasksDir3, { withFileTypes: true })) {
|
|
7103
|
-
if (!entry.isDirectory()) continue;
|
|
7104
|
-
migrateTaskDir((0, import_node_path7.join)(tasksDir3, String(entry.name)), logger);
|
|
7105
|
-
}
|
|
7106
|
-
} catch (err2) {
|
|
7107
|
-
logger.warn(`migration: failed to read tasks dir: ${err2?.message}`);
|
|
7108
|
-
}
|
|
7109
|
-
}
|
|
7110
|
-
function migrateTaskDir(taskDir, logger) {
|
|
7111
|
-
const metaPath = (0, import_node_path7.join)(taskDir, "meta.json");
|
|
7112
|
-
if (!(0, import_node_fs8.existsSync)(metaPath)) return;
|
|
7113
|
-
let meta;
|
|
7114
|
-
try {
|
|
7115
|
-
meta = JSON.parse((0, import_node_fs8.readFileSync)(metaPath, "utf-8"));
|
|
7116
|
-
} catch {
|
|
7117
|
-
return;
|
|
7118
|
-
}
|
|
7119
|
-
if (meta.type !== "light-rule") return;
|
|
7120
|
-
const name = typeof meta.name === "string" ? meta.name : taskDir;
|
|
7121
|
-
cleanupLegacyMetaFields(meta, name, metaPath, logger);
|
|
7122
|
-
replaceFetchPy(taskDir, name, logger);
|
|
7123
|
-
for (const filename of ["README.md", "checkpoint.json"]) {
|
|
7124
|
-
removeFile((0, import_node_path7.join)(taskDir, filename), name, filename, logger);
|
|
7125
|
-
}
|
|
7126
|
-
}
|
|
7127
|
-
function cleanupLegacyMetaFields(meta, name, metaPath, logger) {
|
|
7128
|
-
const cleaned = [];
|
|
7129
|
-
if (mergeMatchRulesIntoDescription(meta)) cleaned.push("matchRules");
|
|
7130
|
-
if (meta.cronSchedule !== void 0) {
|
|
7131
|
-
delete meta.cronSchedule;
|
|
7132
|
-
cleaned.push("cronSchedule");
|
|
7133
|
-
}
|
|
7134
|
-
if (cleaned.length === 0) return;
|
|
7135
|
-
try {
|
|
7136
|
-
(0, import_node_fs8.writeFileSync)(metaPath, JSON.stringify(meta, null, 2), "utf-8");
|
|
7137
|
-
logger.info(
|
|
7138
|
-
`migration: cleaned deprecated field(s) [${cleaned.join(", ")}] in meta.json for light rule: ${name}`
|
|
7139
|
-
);
|
|
7140
|
-
} catch (err2) {
|
|
7141
|
-
logger.warn(`migration: failed to update meta.json for ${name}: ${err2?.message}`);
|
|
7142
|
-
}
|
|
7143
|
-
}
|
|
7144
|
-
function mergeMatchRulesIntoDescription(meta) {
|
|
7145
|
-
const matchRules = meta.matchRules;
|
|
7146
|
-
if (!matchRules || typeof matchRules !== "object") return false;
|
|
7147
|
-
const rules = matchRules;
|
|
7148
|
-
const parts = [];
|
|
7149
|
-
if (rules.appName) parts.push(`app=${rules.appName}`);
|
|
7150
|
-
if (rules.senderKeywords?.length) {
|
|
7151
|
-
parts.push(`\u53D1\u4EF6\u4EBA\u5173\u952E\u8BCD=${rules.senderKeywords.join("\u3001")}`);
|
|
7152
|
-
}
|
|
7153
|
-
if (rules.contentKeywords?.length) {
|
|
7154
|
-
parts.push(`\u5185\u5BB9\u5173\u952E\u8BCD=${rules.contentKeywords.join("\u3001")}`);
|
|
7155
|
-
}
|
|
7156
|
-
if (parts.length > 0) {
|
|
7157
|
-
const existing = typeof meta.description === "string" ? meta.description.trim() : "";
|
|
7158
|
-
meta.description = existing ? `${existing}\u3002\u5339\u914D\u89C4\u5219\uFF1A${parts.join("\uFF0C")}` : `\u5339\u914D\u89C4\u5219\uFF1A${parts.join("\uFF0C")}`;
|
|
7159
|
-
}
|
|
7160
|
-
delete meta.matchRules;
|
|
7161
|
-
return true;
|
|
7162
|
-
}
|
|
7163
|
-
function replaceFetchPy(taskDir, name, logger) {
|
|
7164
|
-
const fetchPyPath = (0, import_node_path7.join)(taskDir, "fetch.py");
|
|
7165
|
-
if (!(0, import_node_fs8.existsSync)(fetchPyPath)) return;
|
|
7166
|
-
try {
|
|
7167
|
-
const existing = (0, import_node_fs8.readFileSync)(fetchPyPath, "utf-8");
|
|
7168
|
-
if (normalizeScriptText(existing) === normalizeScriptText(NO_MATCH_FETCH_PY)) {
|
|
7169
|
-
return;
|
|
7170
|
-
}
|
|
7171
|
-
(0, import_node_fs8.writeFileSync)(fetchPyPath, NO_MATCH_FETCH_PY, "utf-8");
|
|
7172
|
-
logger.info(`migration: replaced fetch.py with NO_MATCH placeholder for ${name}`);
|
|
7173
|
-
} catch (err2) {
|
|
7174
|
-
logger.warn(`migration: failed to replace fetch.py for ${name}: ${err2?.message}`);
|
|
7175
|
-
}
|
|
7176
|
-
}
|
|
7177
|
-
function removeFile(filePath, ruleName, filename, logger) {
|
|
7178
|
-
if (!(0, import_node_fs8.existsSync)(filePath)) return;
|
|
7179
|
-
try {
|
|
7180
|
-
(0, import_node_fs8.rmSync)(filePath);
|
|
7181
|
-
logger.info(`migration: removed ${filename} for light rule: ${ruleName}`);
|
|
7182
|
-
} catch (err2) {
|
|
7183
|
-
logger.warn(`migration: failed to remove ${filename} for ${ruleName}: ${err2?.message}`);
|
|
7184
|
-
}
|
|
7185
|
-
}
|
|
7186
|
-
|
|
7187
7091
|
// src/light-rules/pi-invoker.ts
|
|
7188
7092
|
var import_agent_runtime = require("openclaw/plugin-sdk/agent-runtime");
|
|
7189
7093
|
var DEFAULT_PROVIDER = "anthropic";
|
|
@@ -7365,7 +7269,7 @@ function resolveUpdateChannel(params) {
|
|
|
7365
7269
|
}
|
|
7366
7270
|
|
|
7367
7271
|
// src/update/index.ts
|
|
7368
|
-
var
|
|
7272
|
+
var import_node_path8 = require("path");
|
|
7369
7273
|
|
|
7370
7274
|
// src/update/checker.ts
|
|
7371
7275
|
function parseSemver(v) {
|
|
@@ -7467,8 +7371,8 @@ var UpdateChecker = class {
|
|
|
7467
7371
|
};
|
|
7468
7372
|
|
|
7469
7373
|
// src/update/executor.ts
|
|
7470
|
-
var
|
|
7471
|
-
var
|
|
7374
|
+
var import_node_fs8 = require("fs");
|
|
7375
|
+
var import_node_path7 = require("path");
|
|
7472
7376
|
var import_node_os = require("os");
|
|
7473
7377
|
var VERSION_PATTERN = /^\d+\.\d+\.\d+(-[\w.]+)?$/;
|
|
7474
7378
|
var BASE_URL = "https://artifact.yoooclaw.com/plugin";
|
|
@@ -7478,9 +7382,9 @@ async function executeUpdate(version, runCommand, logger, targetDir, updateConfi
|
|
|
7478
7382
|
}
|
|
7479
7383
|
const tgzUrl = `${BASE_URL}/v${version}/yoooclaw-phone-notifications-${version}.tgz`;
|
|
7480
7384
|
logger.info(`\u6267\u884C\u66F4\u65B0: ${tgzUrl} \u2192 ${targetDir}`);
|
|
7481
|
-
const workDir = (0,
|
|
7482
|
-
const tgzPath = (0,
|
|
7483
|
-
const stagingDir = (0,
|
|
7385
|
+
const workDir = (0, import_node_fs8.mkdtempSync)((0, import_node_path7.join)((0, import_node_os.tmpdir)(), ".openclaw-plugin-update-"));
|
|
7386
|
+
const tgzPath = (0, import_node_path7.join)(workDir, "plugin.tgz");
|
|
7387
|
+
const stagingDir = (0, import_node_path7.join)(workDir, "staged");
|
|
7484
7388
|
let backupDir = null;
|
|
7485
7389
|
try {
|
|
7486
7390
|
logger.info("\u4E0B\u8F7D\u63D2\u4EF6\u5305...");
|
|
@@ -7489,9 +7393,9 @@ async function executeUpdate(version, runCommand, logger, targetDir, updateConfi
|
|
|
7489
7393
|
return { success: false, message: `\u4E0B\u8F7D\u5931\u8D25 (HTTP ${response.status}): ${tgzUrl}` };
|
|
7490
7394
|
}
|
|
7491
7395
|
const buffer = Buffer.from(await response.arrayBuffer());
|
|
7492
|
-
(0,
|
|
7396
|
+
(0, import_node_fs8.writeFileSync)(tgzPath, buffer);
|
|
7493
7397
|
logger.info(`\u4E0B\u8F7D\u5B8C\u6210 (${buffer.length} bytes)`);
|
|
7494
|
-
(0,
|
|
7398
|
+
(0, import_node_fs8.mkdirSync)(stagingDir, { recursive: true });
|
|
7495
7399
|
const tarResult = await runCommand(
|
|
7496
7400
|
["tar", "-xzf", tgzPath, "-C", stagingDir, "--strip-components=1"],
|
|
7497
7401
|
{ timeoutMs: 3e4 }
|
|
@@ -7500,14 +7404,14 @@ async function executeUpdate(version, runCommand, logger, targetDir, updateConfi
|
|
|
7500
7404
|
const err2 = tarResult.stderr || tarResult.stdout || "unknown error";
|
|
7501
7405
|
return { success: false, message: `\u89E3\u538B\u5931\u8D25: ${err2}` };
|
|
7502
7406
|
}
|
|
7503
|
-
(0,
|
|
7407
|
+
(0, import_node_fs8.mkdirSync)((0, import_node_path7.dirname)(targetDir), { recursive: true });
|
|
7504
7408
|
try {
|
|
7505
7409
|
backupDir = `${targetDir}.bak.${Date.now()}`;
|
|
7506
|
-
(0,
|
|
7410
|
+
(0, import_node_fs8.renameSync)(targetDir, backupDir);
|
|
7507
7411
|
} catch {
|
|
7508
7412
|
backupDir = null;
|
|
7509
7413
|
}
|
|
7510
|
-
(0,
|
|
7414
|
+
(0, import_node_fs8.renameSync)(stagingDir, targetDir);
|
|
7511
7415
|
try {
|
|
7512
7416
|
await updateConfigRecord2(version, tgzUrl);
|
|
7513
7417
|
} catch (err2) {
|
|
@@ -7515,18 +7419,18 @@ async function executeUpdate(version, runCommand, logger, targetDir, updateConfi
|
|
|
7515
7419
|
}
|
|
7516
7420
|
if (backupDir) {
|
|
7517
7421
|
try {
|
|
7518
|
-
(0,
|
|
7422
|
+
(0, import_node_fs8.rmSync)(backupDir, { force: true, recursive: true });
|
|
7519
7423
|
} catch {
|
|
7520
7424
|
}
|
|
7521
7425
|
}
|
|
7522
|
-
const msg = `\u5DF2\u66F4\u65B0\u5230 ${version}
|
|
7426
|
+
const msg = `\u5DF2\u66F4\u65B0\u5230 ${version}`;
|
|
7523
7427
|
logger.info(msg);
|
|
7524
|
-
return { success: true, message: msg };
|
|
7428
|
+
return { success: true, message: msg, version };
|
|
7525
7429
|
} catch (err2) {
|
|
7526
7430
|
if (backupDir) {
|
|
7527
7431
|
try {
|
|
7528
|
-
(0,
|
|
7529
|
-
(0,
|
|
7432
|
+
(0, import_node_fs8.rmSync)(targetDir, { force: true, recursive: true });
|
|
7433
|
+
(0, import_node_fs8.renameSync)(backupDir, targetDir);
|
|
7530
7434
|
logger.info("\u5DF2\u56DE\u6EDA\u5230\u4E4B\u524D\u7248\u672C");
|
|
7531
7435
|
} catch (rollbackErr) {
|
|
7532
7436
|
logger.error(`\u56DE\u6EDA\u5931\u8D25: ${String(rollbackErr)}`);
|
|
@@ -7537,12 +7441,47 @@ async function executeUpdate(version, runCommand, logger, targetDir, updateConfi
|
|
|
7537
7441
|
return { success: false, message: errMsg };
|
|
7538
7442
|
} finally {
|
|
7539
7443
|
try {
|
|
7540
|
-
(0,
|
|
7444
|
+
(0, import_node_fs8.rmSync)(workDir, { force: true, recursive: true });
|
|
7541
7445
|
} catch {
|
|
7542
7446
|
}
|
|
7543
7447
|
}
|
|
7544
7448
|
}
|
|
7545
7449
|
|
|
7450
|
+
// src/update/restart.ts
|
|
7451
|
+
function scheduleGatewayRestart(logger, deps = {}) {
|
|
7452
|
+
try {
|
|
7453
|
+
const cfg = deps.loadConfig?.();
|
|
7454
|
+
if (cfg?.commands?.restart === false) {
|
|
7455
|
+
logger.warn("\u66F4\u65B0\u540E\u8DF3\u8FC7 gateway \u91CD\u542F: commands.restart=false");
|
|
7456
|
+
return { scheduled: false };
|
|
7457
|
+
}
|
|
7458
|
+
} catch (err2) {
|
|
7459
|
+
logger.warn(`\u66F4\u65B0\u540E\u68C0\u67E5 gateway \u91CD\u542F\u914D\u7F6E\u5931\u8D25: ${String(err2)}`);
|
|
7460
|
+
}
|
|
7461
|
+
const getListenerCount = deps.getListenerCount ?? ((signal) => process.listenerCount(signal));
|
|
7462
|
+
if (getListenerCount("SIGUSR1") < 1) {
|
|
7463
|
+
logger.warn("\u66F4\u65B0\u540E\u8DF3\u8FC7 gateway \u91CD\u542F: \u5F53\u524D\u8FDB\u7A0B\u672A\u6CE8\u518C SIGUSR1 \u76D1\u542C\u5668");
|
|
7464
|
+
return { scheduled: false };
|
|
7465
|
+
}
|
|
7466
|
+
const emitSignal = deps.emitSignal ?? ((signal) => process.emit(signal));
|
|
7467
|
+
const schedule = deps.schedule ?? ((task) => {
|
|
7468
|
+
setTimeout(task, 0);
|
|
7469
|
+
});
|
|
7470
|
+
schedule(() => {
|
|
7471
|
+
try {
|
|
7472
|
+
const accepted = emitSignal("SIGUSR1");
|
|
7473
|
+
if (accepted) {
|
|
7474
|
+
logger.info("\u66F4\u65B0\u5B8C\u6210\uFF0C\u5DF2\u89E6\u53D1 gateway SIGUSR1 \u91CD\u542F");
|
|
7475
|
+
} else {
|
|
7476
|
+
logger.warn("\u66F4\u65B0\u5B8C\u6210\uFF0C\u4F46 gateway SIGUSR1 \u4FE1\u53F7\u672A\u88AB\u5904\u7406");
|
|
7477
|
+
}
|
|
7478
|
+
} catch (err2) {
|
|
7479
|
+
logger.warn(`\u66F4\u65B0\u540E\u89E6\u53D1 gateway \u91CD\u542F\u5931\u8D25: ${String(err2)}`);
|
|
7480
|
+
}
|
|
7481
|
+
});
|
|
7482
|
+
return { scheduled: true };
|
|
7483
|
+
}
|
|
7484
|
+
|
|
7546
7485
|
// src/update/index.ts
|
|
7547
7486
|
var PLUGIN_ID = "phone-notifications";
|
|
7548
7487
|
function resolveTargetDir(api) {
|
|
@@ -7552,7 +7491,7 @@ function resolveTargetDir(api) {
|
|
|
7552
7491
|
if (installPath) return installPath;
|
|
7553
7492
|
} catch {
|
|
7554
7493
|
}
|
|
7555
|
-
return (0,
|
|
7494
|
+
return (0, import_node_path8.join)(api.runtime.state.resolveStateDir(), "extensions", PLUGIN_ID);
|
|
7556
7495
|
}
|
|
7557
7496
|
async function updateConfigRecord(api, version, targetDir, tgzUrl) {
|
|
7558
7497
|
const configApi = api.runtime.config;
|
|
@@ -7570,6 +7509,23 @@ async function updateConfigRecord(api, version, targetDir, tgzUrl) {
|
|
|
7570
7509
|
};
|
|
7571
7510
|
await configApi.writeConfigFile(cfg);
|
|
7572
7511
|
}
|
|
7512
|
+
function finalizeUpdateResult(api, logger, result) {
|
|
7513
|
+
if (!result.success) {
|
|
7514
|
+
return result;
|
|
7515
|
+
}
|
|
7516
|
+
const restart = scheduleGatewayRestart(logger, {
|
|
7517
|
+
loadConfig: () => {
|
|
7518
|
+
const configApi = api.runtime.config;
|
|
7519
|
+
return configApi?.loadConfig?.();
|
|
7520
|
+
}
|
|
7521
|
+
});
|
|
7522
|
+
const version = result.version ?? "\u76EE\u6807\u7248\u672C";
|
|
7523
|
+
return {
|
|
7524
|
+
...result,
|
|
7525
|
+
restartScheduled: restart.scheduled,
|
|
7526
|
+
message: restart.scheduled ? `\u5DF2\u66F4\u65B0\u5230 ${version}\uFF0C\u5DF2\u89E6\u53D1 gateway \u91CD\u542F` : `\u5DF2\u66F4\u65B0\u5230 ${version}\uFF0C\u8BF7\u624B\u52A8\u91CD\u542F gateway \u751F\u6548`
|
|
7527
|
+
};
|
|
7528
|
+
}
|
|
7573
7529
|
function registerAutoUpdate(api, logger, config, getBroadcast, rememberBroadcast, externalUpdateNotifier) {
|
|
7574
7530
|
if (config.enabled === false) {
|
|
7575
7531
|
logger.info("\u81EA\u52A8\u66F4\u65B0\u5DF2\u7981\u7528 (autoUpdate.enabled = false)");
|
|
@@ -7601,7 +7557,7 @@ function registerAutoUpdate(api, logger, config, getBroadcast, rememberBroadcast
|
|
|
7601
7557
|
api.registerTool({
|
|
7602
7558
|
name: "plugin-update",
|
|
7603
7559
|
label: "Plugin Update",
|
|
7604
|
-
description: "\u5C06 phone-notifications \u63D2\u4EF6\u66F4\u65B0\u5230\u6307\u5B9A\u7248\u672C\u3002\u4EC5\u5728\u7528\u6237\u660E\u786E\u540C\u610F\u66F4\u65B0\u540E\u8C03\u7528\u3002\u66F4\u65B0\u5B8C\u6210\u540E\
|
|
7560
|
+
description: "\u5C06 phone-notifications \u63D2\u4EF6\u66F4\u65B0\u5230\u6307\u5B9A\u7248\u672C\u3002\u4EC5\u5728\u7528\u6237\u660E\u786E\u540C\u610F\u66F4\u65B0\u540E\u8C03\u7528\u3002\u66F4\u65B0\u5B8C\u6210\u540E\u4F1A\u81EA\u52A8\u5C1D\u8BD5\u91CD\u542F gateway\uFF1B\u5982\u5BBF\u4E3B\u4E0D\u652F\u6301\uFF0C\u5219\u9700\u624B\u52A8\u91CD\u542F\u3002",
|
|
7605
7561
|
parameters: {
|
|
7606
7562
|
type: "object",
|
|
7607
7563
|
required: ["version"],
|
|
@@ -7623,13 +7579,14 @@ function registerAutoUpdate(api, logger, config, getBroadcast, rememberBroadcast
|
|
|
7623
7579
|
targetDir,
|
|
7624
7580
|
(v, url) => updateConfigRecord(api, v, targetDir, url)
|
|
7625
7581
|
);
|
|
7626
|
-
|
|
7582
|
+
const finalResult = finalizeUpdateResult(api, logger, result);
|
|
7583
|
+
if (finalResult.success) {
|
|
7627
7584
|
pendingUpdate = null;
|
|
7628
7585
|
externalUpdateNotifier?.clearPendingUpdate();
|
|
7629
7586
|
}
|
|
7630
7587
|
return {
|
|
7631
|
-
content: [{ type: "text", text:
|
|
7632
|
-
details:
|
|
7588
|
+
content: [{ type: "text", text: finalResult.message }],
|
|
7589
|
+
details: finalResult
|
|
7633
7590
|
};
|
|
7634
7591
|
}
|
|
7635
7592
|
});
|
|
@@ -7651,16 +7608,20 @@ function registerAutoUpdate(api, logger, config, getBroadcast, rememberBroadcast
|
|
|
7651
7608
|
targetDir,
|
|
7652
7609
|
(v, url) => updateConfigRecord(api, v, targetDir, url)
|
|
7653
7610
|
);
|
|
7654
|
-
|
|
7611
|
+
const finalResult = finalizeUpdateResult(api, logger, result);
|
|
7612
|
+
if (finalResult.success) {
|
|
7655
7613
|
pendingUpdate = null;
|
|
7656
7614
|
externalUpdateNotifier?.clearPendingUpdate();
|
|
7657
7615
|
}
|
|
7658
|
-
if (
|
|
7659
|
-
respond(true, {
|
|
7616
|
+
if (finalResult.success) {
|
|
7617
|
+
respond(true, {
|
|
7618
|
+
message: finalResult.message,
|
|
7619
|
+
restartScheduled: finalResult.restartScheduled === true
|
|
7620
|
+
});
|
|
7660
7621
|
} else {
|
|
7661
7622
|
respond(false, void 0, {
|
|
7662
7623
|
code: "UPDATE_FAILED",
|
|
7663
|
-
message:
|
|
7624
|
+
message: finalResult.message
|
|
7664
7625
|
});
|
|
7665
7626
|
}
|
|
7666
7627
|
});
|
|
@@ -7740,10 +7701,10 @@ function registerAutoUpdateLifecycle(deps) {
|
|
|
7740
7701
|
}
|
|
7741
7702
|
|
|
7742
7703
|
// src/plugin/cli.ts
|
|
7743
|
-
var
|
|
7704
|
+
var import_node_path16 = require("path");
|
|
7744
7705
|
|
|
7745
7706
|
// src/cli/auth.ts
|
|
7746
|
-
var
|
|
7707
|
+
var import_node_fs9 = require("fs");
|
|
7747
7708
|
init_credentials();
|
|
7748
7709
|
function registerAuthCli(program) {
|
|
7749
7710
|
const auth = program.command("auth").description("\u7528\u6237\u8BA4\u8BC1\u7BA1\u7406");
|
|
@@ -7779,12 +7740,12 @@ function registerAuthCli(program) {
|
|
|
7779
7740
|
});
|
|
7780
7741
|
auth.command("clear").description("\u6E05\u9664\u5DF2\u4FDD\u5B58\u7684\u8BA4\u8BC1\u4FE1\u606F").action(() => {
|
|
7781
7742
|
const path2 = credentialsPath();
|
|
7782
|
-
if ((0,
|
|
7743
|
+
if ((0, import_node_fs9.existsSync)(path2)) {
|
|
7783
7744
|
const creds = readCredentials();
|
|
7784
7745
|
delete creds.apiKey;
|
|
7785
7746
|
delete creds.token;
|
|
7786
7747
|
if (Object.keys(creds).length === 0) {
|
|
7787
|
-
(0,
|
|
7748
|
+
(0, import_node_fs9.rmSync)(path2, { force: true });
|
|
7788
7749
|
} else {
|
|
7789
7750
|
writeCredentials(creds);
|
|
7790
7751
|
}
|
|
@@ -7916,23 +7877,23 @@ function registerNtfStats(ntf, ctx) {
|
|
|
7916
7877
|
}
|
|
7917
7878
|
|
|
7918
7879
|
// src/cli/ntf-sync.ts
|
|
7919
|
-
var
|
|
7920
|
-
var
|
|
7880
|
+
var import_node_fs10 = require("fs");
|
|
7881
|
+
var import_node_path9 = require("path");
|
|
7921
7882
|
var SYNC_FETCH_LIMIT = 300;
|
|
7922
7883
|
function checkpointPath(dir) {
|
|
7923
|
-
return (0,
|
|
7884
|
+
return (0, import_node_path9.join)(dir, ".checkpoint.json");
|
|
7924
7885
|
}
|
|
7925
7886
|
function readCheckpoint(dir) {
|
|
7926
7887
|
const p = checkpointPath(dir);
|
|
7927
|
-
if (!(0,
|
|
7888
|
+
if (!(0, import_node_fs10.existsSync)(p)) return {};
|
|
7928
7889
|
try {
|
|
7929
|
-
return JSON.parse((0,
|
|
7890
|
+
return JSON.parse((0, import_node_fs10.readFileSync)(p, "utf-8"));
|
|
7930
7891
|
} catch {
|
|
7931
7892
|
return {};
|
|
7932
7893
|
}
|
|
7933
7894
|
}
|
|
7934
7895
|
function writeCheckpoint(dir, data) {
|
|
7935
|
-
(0,
|
|
7896
|
+
(0, import_node_fs10.writeFileSync)(checkpointPath(dir), JSON.stringify(data, null, 2), "utf-8");
|
|
7936
7897
|
}
|
|
7937
7898
|
function registerNtfSync(ntf, ctx) {
|
|
7938
7899
|
const sync = ntf.command("sync").description("\u540C\u6B65\u901A\u77E5\u5230\u8BB0\u5FC6\u7CFB\u7EDF");
|
|
@@ -8025,8 +7986,8 @@ function registerNtfSync(ntf, ctx) {
|
|
|
8025
7986
|
}
|
|
8026
7987
|
|
|
8027
7988
|
// src/cli/ntf-monitor.ts
|
|
8028
|
-
var
|
|
8029
|
-
var
|
|
7989
|
+
var import_node_fs11 = require("fs");
|
|
7990
|
+
var import_node_path10 = require("path");
|
|
8030
7991
|
|
|
8031
7992
|
// src/monitor/fetch-gen.ts
|
|
8032
7993
|
function generateFetchPy(name, matchRules) {
|
|
@@ -8111,19 +8072,19 @@ function pyLiteral(value) {
|
|
|
8111
8072
|
function tasksDir2(ctx) {
|
|
8112
8073
|
const base = ctx.workspaceDir || ctx.stateDir;
|
|
8113
8074
|
if (!base) throw new Error("workspaceDir and stateDir both unavailable");
|
|
8114
|
-
return (0,
|
|
8075
|
+
return (0, import_node_path10.join)(base, "tasks");
|
|
8115
8076
|
}
|
|
8116
8077
|
function readMeta2(taskDir) {
|
|
8117
|
-
const metaPath = (0,
|
|
8118
|
-
if (!(0,
|
|
8078
|
+
const metaPath = (0, import_node_path10.join)(taskDir, "meta.json");
|
|
8079
|
+
if (!(0, import_node_fs11.existsSync)(metaPath)) return null;
|
|
8119
8080
|
try {
|
|
8120
|
-
return JSON.parse((0,
|
|
8081
|
+
return JSON.parse((0, import_node_fs11.readFileSync)(metaPath, "utf-8"));
|
|
8121
8082
|
} catch {
|
|
8122
8083
|
return null;
|
|
8123
8084
|
}
|
|
8124
8085
|
}
|
|
8125
8086
|
function writeMeta2(taskDir, meta) {
|
|
8126
|
-
(0,
|
|
8087
|
+
(0, import_node_fs11.writeFileSync)((0, import_node_path10.join)(taskDir, "meta.json"), JSON.stringify(meta, null, 2), "utf-8");
|
|
8127
8088
|
}
|
|
8128
8089
|
function generateReadme(name, description) {
|
|
8129
8090
|
return `# Monitor Task: ${name}
|
|
@@ -8142,27 +8103,27 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
8142
8103
|
const monitor = ntf.command("monitor").description("\u901A\u77E5\u76D1\u63A7\u4EFB\u52A1\u7BA1\u7406");
|
|
8143
8104
|
monitor.command("list").description("\u5217\u51FA\u6240\u6709\u76D1\u63A7\u4EFB\u52A1").action(() => {
|
|
8144
8105
|
const dir = tasksDir2(ctx);
|
|
8145
|
-
if (!(0,
|
|
8106
|
+
if (!(0, import_node_fs11.existsSync)(dir)) {
|
|
8146
8107
|
output({ ok: true, tasks: [] });
|
|
8147
8108
|
return;
|
|
8148
8109
|
}
|
|
8149
8110
|
const tasks = [];
|
|
8150
|
-
for (const entry of (0,
|
|
8111
|
+
for (const entry of (0, import_node_fs11.readdirSync)(dir, { withFileTypes: true })) {
|
|
8151
8112
|
if (!entry.isDirectory()) continue;
|
|
8152
|
-
const meta = readMeta2((0,
|
|
8113
|
+
const meta = readMeta2((0, import_node_path10.join)(dir, entry.name));
|
|
8153
8114
|
if (meta) tasks.push(meta);
|
|
8154
8115
|
}
|
|
8155
8116
|
output({ ok: true, tasks });
|
|
8156
8117
|
});
|
|
8157
8118
|
monitor.command("show <name>").description("\u67E5\u770B\u76D1\u63A7\u4EFB\u52A1\u8BE6\u60C5").action((name) => {
|
|
8158
|
-
const taskDir = (0,
|
|
8119
|
+
const taskDir = (0, import_node_path10.join)(tasksDir2(ctx), name);
|
|
8159
8120
|
const meta = readMeta2(taskDir);
|
|
8160
8121
|
if (!meta) exitError("NOT_FOUND", `\u76D1\u63A7\u4EFB\u52A1 '${name}' \u4E0D\u5B58\u5728`);
|
|
8161
|
-
const checkpointPath2 = (0,
|
|
8122
|
+
const checkpointPath2 = (0, import_node_path10.join)(taskDir, "checkpoint.json");
|
|
8162
8123
|
let checkpoint = {};
|
|
8163
|
-
if ((0,
|
|
8124
|
+
if ((0, import_node_fs11.existsSync)(checkpointPath2)) {
|
|
8164
8125
|
try {
|
|
8165
|
-
checkpoint = JSON.parse((0,
|
|
8126
|
+
checkpoint = JSON.parse((0, import_node_fs11.readFileSync)(checkpointPath2, "utf-8"));
|
|
8166
8127
|
} catch {
|
|
8167
8128
|
}
|
|
8168
8129
|
}
|
|
@@ -8177,8 +8138,8 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
8177
8138
|
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(
|
|
8178
8139
|
(name, opts) => {
|
|
8179
8140
|
const dir = tasksDir2(ctx);
|
|
8180
|
-
const taskDir = (0,
|
|
8181
|
-
if ((0,
|
|
8141
|
+
const taskDir = (0, import_node_path10.join)(dir, name);
|
|
8142
|
+
if ((0, import_node_fs11.existsSync)(taskDir)) {
|
|
8182
8143
|
exitError("ALREADY_EXISTS", `\u76D1\u63A7\u4EFB\u52A1 '${name}' \u5DF2\u5B58\u5728`);
|
|
8183
8144
|
}
|
|
8184
8145
|
let matchRules;
|
|
@@ -8190,7 +8151,7 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
8190
8151
|
"match-rules \u5FC5\u987B\u662F\u5408\u6CD5\u7684 JSON"
|
|
8191
8152
|
);
|
|
8192
8153
|
}
|
|
8193
|
-
(0,
|
|
8154
|
+
(0, import_node_fs11.mkdirSync)(taskDir, { recursive: true });
|
|
8194
8155
|
const meta = {
|
|
8195
8156
|
name,
|
|
8196
8157
|
description: opts.description,
|
|
@@ -8200,13 +8161,13 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
8200
8161
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
8201
8162
|
};
|
|
8202
8163
|
writeMeta2(taskDir, meta);
|
|
8203
|
-
(0,
|
|
8204
|
-
(0,
|
|
8164
|
+
(0, import_node_fs11.writeFileSync)(
|
|
8165
|
+
(0, import_node_path10.join)(taskDir, "fetch.py"),
|
|
8205
8166
|
generateFetchPy(name, matchRules),
|
|
8206
8167
|
"utf-8"
|
|
8207
8168
|
);
|
|
8208
|
-
(0,
|
|
8209
|
-
(0,
|
|
8169
|
+
(0, import_node_fs11.writeFileSync)(
|
|
8170
|
+
(0, import_node_path10.join)(taskDir, "README.md"),
|
|
8210
8171
|
generateReadme(name, opts.description),
|
|
8211
8172
|
"utf-8"
|
|
8212
8173
|
);
|
|
@@ -8234,8 +8195,8 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
8234
8195
|
}
|
|
8235
8196
|
);
|
|
8236
8197
|
monitor.command("delete <name>").description("\u5220\u9664\u76D1\u63A7\u4EFB\u52A1").option("--yes", "\u8DF3\u8FC7\u786E\u8BA4").action((name, opts) => {
|
|
8237
|
-
const taskDir = (0,
|
|
8238
|
-
if (!(0,
|
|
8198
|
+
const taskDir = (0, import_node_path10.join)(tasksDir2(ctx), name);
|
|
8199
|
+
if (!(0, import_node_fs11.existsSync)(taskDir)) {
|
|
8239
8200
|
exitError("NOT_FOUND", `\u76D1\u63A7\u4EFB\u52A1 '${name}' \u4E0D\u5B58\u5728`);
|
|
8240
8201
|
}
|
|
8241
8202
|
if (!opts.yes) {
|
|
@@ -8248,7 +8209,7 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
8248
8209
|
});
|
|
8249
8210
|
process.exit(1);
|
|
8250
8211
|
}
|
|
8251
|
-
(0,
|
|
8212
|
+
(0, import_node_fs11.rmSync)(taskDir, { recursive: true, force: true });
|
|
8252
8213
|
output({
|
|
8253
8214
|
ok: true,
|
|
8254
8215
|
name,
|
|
@@ -8260,7 +8221,7 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
8260
8221
|
});
|
|
8261
8222
|
});
|
|
8262
8223
|
monitor.command("enable <name>").description("\u542F\u7528\u76D1\u63A7\u4EFB\u52A1").action((name) => {
|
|
8263
|
-
const taskDir = (0,
|
|
8224
|
+
const taskDir = (0, import_node_path10.join)(tasksDir2(ctx), name);
|
|
8264
8225
|
const meta = readMeta2(taskDir);
|
|
8265
8226
|
if (!meta) exitError("NOT_FOUND", `\u76D1\u63A7\u4EFB\u52A1 '${name}' \u4E0D\u5B58\u5728`);
|
|
8266
8227
|
meta.enabled = true;
|
|
@@ -8268,7 +8229,7 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
8268
8229
|
output({ ok: true, name, enabled: true });
|
|
8269
8230
|
});
|
|
8270
8231
|
monitor.command("disable <name>").description("\u6682\u505C\u76D1\u63A7\u4EFB\u52A1").action((name) => {
|
|
8271
|
-
const taskDir = (0,
|
|
8232
|
+
const taskDir = (0, import_node_path10.join)(tasksDir2(ctx), name);
|
|
8272
8233
|
const meta = readMeta2(taskDir);
|
|
8273
8234
|
if (!meta) exitError("NOT_FOUND", `\u76D1\u63A7\u4EFB\u52A1 '${name}' \u4E0D\u5B58\u5728`);
|
|
8274
8235
|
meta.enabled = false;
|
|
@@ -8312,9 +8273,9 @@ function registerLightSend(light) {
|
|
|
8312
8273
|
}
|
|
8313
8274
|
|
|
8314
8275
|
// src/cli/light-setup-tools.ts
|
|
8315
|
-
var
|
|
8276
|
+
var import_node_fs12 = require("fs");
|
|
8316
8277
|
var import_node_os2 = require("os");
|
|
8317
|
-
var
|
|
8278
|
+
var import_node_path11 = require("path");
|
|
8318
8279
|
function isObject(value) {
|
|
8319
8280
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
8320
8281
|
}
|
|
@@ -8328,7 +8289,7 @@ function ensureArray(obj, key) {
|
|
|
8328
8289
|
function resolveConfigPath2() {
|
|
8329
8290
|
const fromEnv = process.env.OPENCLAW_CONFIG_PATH?.trim();
|
|
8330
8291
|
if (fromEnv) return fromEnv;
|
|
8331
|
-
return (0,
|
|
8292
|
+
return (0, import_node_path11.join)((0, import_node_os2.homedir)(), ".openclaw", "openclaw.json");
|
|
8332
8293
|
}
|
|
8333
8294
|
var LIGHT_TOOLS = [
|
|
8334
8295
|
"light_control",
|
|
@@ -8375,12 +8336,12 @@ function upsertLightControlAlsoAllow(cfg) {
|
|
|
8375
8336
|
function registerLightSetupTools(light) {
|
|
8376
8337
|
light.command("setup").description("\u81EA\u52A8\u653E\u884C light_control\uFF08\u5199\u5165 tools.alsoAllow \u4E0E agents.main.tools.alsoAllow\uFF09").action(() => {
|
|
8377
8338
|
const configPath = resolveConfigPath2();
|
|
8378
|
-
if (!(0,
|
|
8339
|
+
if (!(0, import_node_fs12.existsSync)(configPath)) {
|
|
8379
8340
|
exitError("CONFIG_NOT_FOUND", `\u672A\u627E\u5230\u914D\u7F6E\u6587\u4EF6: ${configPath}`);
|
|
8380
8341
|
}
|
|
8381
8342
|
let cfg = {};
|
|
8382
8343
|
try {
|
|
8383
|
-
const raw = (0,
|
|
8344
|
+
const raw = (0, import_node_fs12.readFileSync)(configPath, "utf-8");
|
|
8384
8345
|
const parsed = JSON.parse(raw);
|
|
8385
8346
|
if (isObject(parsed)) cfg = parsed;
|
|
8386
8347
|
} catch (err2) {
|
|
@@ -8388,8 +8349,8 @@ function registerLightSetupTools(light) {
|
|
|
8388
8349
|
}
|
|
8389
8350
|
const result = upsertLightControlAlsoAllow(cfg);
|
|
8390
8351
|
try {
|
|
8391
|
-
(0,
|
|
8392
|
-
(0,
|
|
8352
|
+
(0, import_node_fs12.mkdirSync)((0, import_node_path11.dirname)(configPath), { recursive: true });
|
|
8353
|
+
(0, import_node_fs12.writeFileSync)(configPath, JSON.stringify(cfg, null, 2) + "\n", "utf-8");
|
|
8393
8354
|
} catch (err2) {
|
|
8394
8355
|
exitError("WRITE_FAILED", `\u5199\u5165\u914D\u7F6E\u5931\u8D25: ${err2?.message ?? String(err2)}`);
|
|
8395
8356
|
}
|
|
@@ -8407,17 +8368,17 @@ function registerLightSetupTools(light) {
|
|
|
8407
8368
|
}
|
|
8408
8369
|
|
|
8409
8370
|
// src/cli/tunnel-status.ts
|
|
8410
|
-
var
|
|
8411
|
-
var
|
|
8371
|
+
var import_node_fs13 = require("fs");
|
|
8372
|
+
var import_node_path12 = require("path");
|
|
8412
8373
|
init_credentials();
|
|
8413
8374
|
init_env();
|
|
8414
|
-
var STATUS_REL_PATH = (0,
|
|
8375
|
+
var STATUS_REL_PATH = (0, import_node_path12.join)("plugins", "phone-notifications", "tunnel-status.json");
|
|
8415
8376
|
function readTunnelStatus(ctx) {
|
|
8416
8377
|
if (!ctx.stateDir) return null;
|
|
8417
|
-
const filePath = (0,
|
|
8418
|
-
if (!(0,
|
|
8378
|
+
const filePath = (0, import_node_path12.join)(ctx.stateDir, STATUS_REL_PATH);
|
|
8379
|
+
if (!(0, import_node_fs13.existsSync)(filePath)) return null;
|
|
8419
8380
|
try {
|
|
8420
|
-
return JSON.parse((0,
|
|
8381
|
+
return JSON.parse((0, import_node_fs13.readFileSync)(filePath, "utf-8"));
|
|
8421
8382
|
} catch {
|
|
8422
8383
|
return null;
|
|
8423
8384
|
}
|
|
@@ -8485,24 +8446,24 @@ function registerNtfStoragePath(ntf, ctx) {
|
|
|
8485
8446
|
}
|
|
8486
8447
|
|
|
8487
8448
|
// src/cli/log-search.ts
|
|
8488
|
-
var
|
|
8489
|
-
var
|
|
8449
|
+
var import_node_fs14 = require("fs");
|
|
8450
|
+
var import_node_path13 = require("path");
|
|
8490
8451
|
function resolveLogsDir(ctx) {
|
|
8491
8452
|
if (ctx.stateDir) {
|
|
8492
|
-
const dir = (0,
|
|
8453
|
+
const dir = (0, import_node_path13.join)(
|
|
8493
8454
|
ctx.stateDir,
|
|
8494
8455
|
"plugins",
|
|
8495
8456
|
"phone-notifications",
|
|
8496
8457
|
"logs"
|
|
8497
8458
|
);
|
|
8498
|
-
if ((0,
|
|
8459
|
+
if ((0, import_node_fs14.existsSync)(dir)) return dir;
|
|
8499
8460
|
}
|
|
8500
8461
|
return null;
|
|
8501
8462
|
}
|
|
8502
8463
|
function listLogDateKeys(dir) {
|
|
8503
8464
|
const pattern = /^(\d{4}-\d{2}-\d{2})\.log$/;
|
|
8504
8465
|
const keys = [];
|
|
8505
|
-
for (const entry of (0,
|
|
8466
|
+
for (const entry of (0, import_node_fs14.readdirSync)(dir, { withFileTypes: true })) {
|
|
8506
8467
|
if (!entry.isFile()) continue;
|
|
8507
8468
|
const m = pattern.exec(entry.name);
|
|
8508
8469
|
if (m) keys.push(m[1]);
|
|
@@ -8510,9 +8471,9 @@ function listLogDateKeys(dir) {
|
|
|
8510
8471
|
return keys.sort().reverse();
|
|
8511
8472
|
}
|
|
8512
8473
|
function collectLogLines(dir, dateKey, keyword, limit, collected) {
|
|
8513
|
-
const filePath = (0,
|
|
8514
|
-
if (!(0,
|
|
8515
|
-
const content = (0,
|
|
8474
|
+
const filePath = (0, import_node_path13.join)(dir, `${dateKey}.log`);
|
|
8475
|
+
if (!(0, import_node_fs14.existsSync)(filePath)) return;
|
|
8476
|
+
const content = (0, import_node_fs14.readFileSync)(filePath, "utf-8");
|
|
8516
8477
|
const lowerKeyword = keyword?.toLowerCase();
|
|
8517
8478
|
for (const line of content.split("\n")) {
|
|
8518
8479
|
if (collected.length >= limit) return;
|
|
@@ -8579,12 +8540,12 @@ function registerEnvCli(ntf) {
|
|
|
8579
8540
|
}
|
|
8580
8541
|
|
|
8581
8542
|
// src/cli/doctor.ts
|
|
8582
|
-
var
|
|
8543
|
+
var import_node_fs18 = require("fs");
|
|
8583
8544
|
var import_node_readline = require("readline");
|
|
8584
8545
|
init_host();
|
|
8585
8546
|
|
|
8586
8547
|
// src/cli/doctor/check-dangerous-flags.ts
|
|
8587
|
-
var
|
|
8548
|
+
var import_node_fs15 = require("fs");
|
|
8588
8549
|
function isObject2(v) {
|
|
8589
8550
|
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
8590
8551
|
}
|
|
@@ -8601,13 +8562,13 @@ var checkDangerousFlags = ({ cfg, configPath }) => {
|
|
|
8601
8562
|
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",
|
|
8602
8563
|
fixDescription: "\u8BBE\u4E3A false",
|
|
8603
8564
|
fix: () => {
|
|
8604
|
-
const raw = (0,
|
|
8565
|
+
const raw = (0, import_node_fs15.readFileSync)(configPath, "utf-8");
|
|
8605
8566
|
const config = JSON.parse(raw);
|
|
8606
8567
|
const gw = config.gateway;
|
|
8607
8568
|
const cui = gw.controlUi;
|
|
8608
8569
|
cui.dangerouslyDisableDeviceAuth = false;
|
|
8609
|
-
(0,
|
|
8610
|
-
(0,
|
|
8570
|
+
(0, import_node_fs15.copyFileSync)(configPath, configPath + ".bak");
|
|
8571
|
+
(0, import_node_fs15.writeFileSync)(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
8611
8572
|
}
|
|
8612
8573
|
};
|
|
8613
8574
|
};
|
|
@@ -8655,11 +8616,11 @@ function warnEmpty() {
|
|
|
8655
8616
|
}
|
|
8656
8617
|
|
|
8657
8618
|
// src/cli/doctor/check-state-dir-perms.ts
|
|
8658
|
-
var
|
|
8619
|
+
var import_node_fs16 = require("fs");
|
|
8659
8620
|
var checkStateDirPerms = ({ stateDir }) => {
|
|
8660
8621
|
let mode;
|
|
8661
8622
|
try {
|
|
8662
|
-
mode = (0,
|
|
8623
|
+
mode = (0, import_node_fs16.statSync)(stateDir).mode;
|
|
8663
8624
|
} catch {
|
|
8664
8625
|
return null;
|
|
8665
8626
|
}
|
|
@@ -8673,7 +8634,7 @@ var checkStateDirPerms = ({ stateDir }) => {
|
|
|
8673
8634
|
detail: "\u5176\u4ED6\u7528\u6237\u53EF\u4EE5\u8BFB\u53D6\u8BE5\u76EE\u5F55\u4E0B\u7684\u51ED\u8BC1\u548C\u914D\u7F6E\u6587\u4EF6\u3002",
|
|
8674
8635
|
fixDescription: "chmod 700 " + stateDir,
|
|
8675
8636
|
fix: () => {
|
|
8676
|
-
(0,
|
|
8637
|
+
(0, import_node_fs16.chmodSync)(stateDir, 448);
|
|
8677
8638
|
}
|
|
8678
8639
|
};
|
|
8679
8640
|
};
|
|
@@ -8728,16 +8689,16 @@ var checkCredentials = () => {
|
|
|
8728
8689
|
};
|
|
8729
8690
|
|
|
8730
8691
|
// src/cli/doctor/check-tunnel.ts
|
|
8731
|
-
var
|
|
8732
|
-
var
|
|
8733
|
-
var STATUS_REL_PATH2 = (0,
|
|
8692
|
+
var import_node_fs17 = require("fs");
|
|
8693
|
+
var import_node_path14 = require("path");
|
|
8694
|
+
var STATUS_REL_PATH2 = (0, import_node_path14.join)(
|
|
8734
8695
|
"plugins",
|
|
8735
8696
|
"phone-notifications",
|
|
8736
8697
|
"tunnel-status.json"
|
|
8737
8698
|
);
|
|
8738
8699
|
var checkTunnel = ({ stateDir }) => {
|
|
8739
|
-
const filePath = (0,
|
|
8740
|
-
if (!(0,
|
|
8700
|
+
const filePath = (0, import_node_path14.join)(stateDir, STATUS_REL_PATH2);
|
|
8701
|
+
if (!(0, import_node_fs17.existsSync)(filePath)) {
|
|
8741
8702
|
return {
|
|
8742
8703
|
id: "tunnel",
|
|
8743
8704
|
severity: "warn",
|
|
@@ -8749,7 +8710,7 @@ var checkTunnel = ({ stateDir }) => {
|
|
|
8749
8710
|
}
|
|
8750
8711
|
let status;
|
|
8751
8712
|
try {
|
|
8752
|
-
status = JSON.parse((0,
|
|
8713
|
+
status = JSON.parse((0, import_node_fs17.readFileSync)(filePath, "utf-8"));
|
|
8753
8714
|
} catch {
|
|
8754
8715
|
return {
|
|
8755
8716
|
id: "tunnel",
|
|
@@ -8842,9 +8803,9 @@ function isObject5(v) {
|
|
|
8842
8803
|
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
8843
8804
|
}
|
|
8844
8805
|
function readConfig(configPath) {
|
|
8845
|
-
if (!(0,
|
|
8806
|
+
if (!(0, import_node_fs18.existsSync)(configPath)) return {};
|
|
8846
8807
|
try {
|
|
8847
|
-
const parsed = JSON.parse((0,
|
|
8808
|
+
const parsed = JSON.parse((0, import_node_fs18.readFileSync)(configPath, "utf-8"));
|
|
8848
8809
|
return isObject5(parsed) ? parsed : {};
|
|
8849
8810
|
} catch {
|
|
8850
8811
|
return {};
|
|
@@ -9045,7 +9006,7 @@ function registerRecStoragePath(rec, ctx) {
|
|
|
9045
9006
|
|
|
9046
9007
|
// src/cli/rec-setup.ts
|
|
9047
9008
|
var import_node_readline2 = require("readline");
|
|
9048
|
-
var
|
|
9009
|
+
var import_node_fs19 = require("fs");
|
|
9049
9010
|
function ask(rl, question) {
|
|
9050
9011
|
return new Promise((resolve) => rl.question(question, resolve));
|
|
9051
9012
|
}
|
|
@@ -9131,9 +9092,9 @@ async function setupLocal(rl) {
|
|
|
9131
9092
|
function registerRecSetup(rec, ctx) {
|
|
9132
9093
|
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 () => {
|
|
9133
9094
|
const configPath = resolveAsrConfigPath(ctx);
|
|
9134
|
-
if ((0,
|
|
9095
|
+
if ((0, import_node_fs19.existsSync)(configPath)) {
|
|
9135
9096
|
try {
|
|
9136
|
-
const existing = JSON.parse((0,
|
|
9097
|
+
const existing = JSON.parse((0, import_node_fs19.readFileSync)(configPath, "utf-8"));
|
|
9137
9098
|
process.stderr.write(`\u5F53\u524D\u5DF2\u6709\u914D\u7F6E\uFF1Amode = ${existing.mode}`);
|
|
9138
9099
|
if (existing.updatedAt) process.stderr.write(`\uFF0C\u66F4\u65B0\u4E8E ${existing.updatedAt}`);
|
|
9139
9100
|
process.stderr.write("\n");
|
|
@@ -9146,7 +9107,7 @@ function registerRecSetup(rec, ctx) {
|
|
|
9146
9107
|
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"]);
|
|
9147
9108
|
const config = modeIdx === 0 ? await setupApi(rl) : await setupLocal(rl);
|
|
9148
9109
|
const stored = { ...config, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
9149
|
-
(0,
|
|
9110
|
+
(0, import_node_fs19.writeFileSync)(configPath, JSON.stringify(stored, null, 2), "utf-8");
|
|
9150
9111
|
process.stderr.write(`
|
|
9151
9112
|
\u2713 \u914D\u7F6E\u5DF2\u4FDD\u5B58\u5230 ${configPath}
|
|
9152
9113
|
|
|
@@ -9160,8 +9121,8 @@ function registerRecSetup(rec, ctx) {
|
|
|
9160
9121
|
|
|
9161
9122
|
// src/cli/update.ts
|
|
9162
9123
|
var import_node_child_process = require("child_process");
|
|
9163
|
-
var
|
|
9164
|
-
var
|
|
9124
|
+
var import_node_fs20 = require("fs");
|
|
9125
|
+
var import_node_path15 = require("path");
|
|
9165
9126
|
var import_node_os3 = __toESM(require("os"), 1);
|
|
9166
9127
|
init_host();
|
|
9167
9128
|
var BASE_URL2 = "https://artifact.yoooclaw.com/plugin";
|
|
@@ -9220,9 +9181,9 @@ async function runUpdate(ctx, opts) {
|
|
|
9220
9181
|
`);
|
|
9221
9182
|
process.exit(1);
|
|
9222
9183
|
}
|
|
9223
|
-
const tmpScript = (0,
|
|
9184
|
+
const tmpScript = (0, import_node_path15.join)(import_node_os3.default.tmpdir(), `openclaw-install-${Date.now()}.mjs`);
|
|
9224
9185
|
try {
|
|
9225
|
-
(0,
|
|
9186
|
+
(0, import_node_fs20.writeFileSync)(tmpScript, installScript, "utf-8");
|
|
9226
9187
|
} catch (err2) {
|
|
9227
9188
|
const msg = `\u5199\u5165\u4E34\u65F6\u6587\u4EF6\u5931\u8D25: ${err2?.message ?? String(err2)}`;
|
|
9228
9189
|
if (json) {
|
|
@@ -9240,7 +9201,7 @@ async function runUpdate(ctx, opts) {
|
|
|
9240
9201
|
{ stdio: "inherit" }
|
|
9241
9202
|
);
|
|
9242
9203
|
try {
|
|
9243
|
-
(0,
|
|
9204
|
+
(0, import_node_fs20.unlinkSync)(tmpScript);
|
|
9244
9205
|
} catch {
|
|
9245
9206
|
}
|
|
9246
9207
|
if (result.error) {
|
|
@@ -9304,10 +9265,10 @@ function inferOpenClawRootDir(workspaceDir) {
|
|
|
9304
9265
|
if (!workspaceDir) {
|
|
9305
9266
|
return void 0;
|
|
9306
9267
|
}
|
|
9307
|
-
if ((0,
|
|
9268
|
+
if ((0, import_node_path16.basename)(workspaceDir) !== "workspace") {
|
|
9308
9269
|
return void 0;
|
|
9309
9270
|
}
|
|
9310
|
-
return (0,
|
|
9271
|
+
return (0, import_node_path16.dirname)(workspaceDir);
|
|
9311
9272
|
}
|
|
9312
9273
|
function registerPluginCli(api, params) {
|
|
9313
9274
|
const { logger, openclawDir } = params;
|
|
@@ -9558,12 +9519,12 @@ function registerLightControlTool(api, logger) {
|
|
|
9558
9519
|
}
|
|
9559
9520
|
|
|
9560
9521
|
// src/plugin/lifecycle.ts
|
|
9561
|
-
var
|
|
9522
|
+
var import_node_fs30 = require("fs");
|
|
9562
9523
|
init_host();
|
|
9563
9524
|
|
|
9564
9525
|
// src/notification/app-name-map.ts
|
|
9565
|
-
var
|
|
9566
|
-
var
|
|
9526
|
+
var import_node_fs21 = require("fs");
|
|
9527
|
+
var import_node_path17 = require("path");
|
|
9567
9528
|
init_credentials();
|
|
9568
9529
|
init_env();
|
|
9569
9530
|
var PLUGIN_STATE_DIR = "phone-notifications";
|
|
@@ -9584,7 +9545,7 @@ function isAppNameMapApiResponse(v) {
|
|
|
9584
9545
|
);
|
|
9585
9546
|
}
|
|
9586
9547
|
function getCachePath(stateDir) {
|
|
9587
|
-
return (0,
|
|
9548
|
+
return (0, import_node_path17.join)(stateDir, "plugins", PLUGIN_STATE_DIR, CACHE_FILE);
|
|
9588
9549
|
}
|
|
9589
9550
|
function createAppNameMapProvider(opts) {
|
|
9590
9551
|
const { stateDir, logger } = opts;
|
|
@@ -9596,9 +9557,9 @@ function createAppNameMapProvider(opts) {
|
|
|
9596
9557
|
let inFlightFetch = null;
|
|
9597
9558
|
function loadFromDisk() {
|
|
9598
9559
|
const path2 = getCachePath(stateDir);
|
|
9599
|
-
if (!(0,
|
|
9560
|
+
if (!(0, import_node_fs21.existsSync)(path2)) return;
|
|
9600
9561
|
try {
|
|
9601
|
-
const raw = JSON.parse((0,
|
|
9562
|
+
const raw = JSON.parse((0, import_node_fs21.readFileSync)(path2, "utf-8"));
|
|
9602
9563
|
if (!isRecordOfStrings(raw)) return;
|
|
9603
9564
|
map.clear();
|
|
9604
9565
|
for (const [k, v] of Object.entries(raw)) map.set(k, v);
|
|
@@ -9642,10 +9603,10 @@ function createAppNameMapProvider(opts) {
|
|
|
9642
9603
|
logger.warn("[app-name-map] refresh succeeded but got 0 entries");
|
|
9643
9604
|
return;
|
|
9644
9605
|
}
|
|
9645
|
-
const dir = (0,
|
|
9646
|
-
(0,
|
|
9606
|
+
const dir = (0, import_node_path17.join)(stateDir, "plugins", PLUGIN_STATE_DIR);
|
|
9607
|
+
(0, import_node_fs21.mkdirSync)(dir, { recursive: true });
|
|
9647
9608
|
const cachePath = getCachePath(stateDir);
|
|
9648
|
-
(0,
|
|
9609
|
+
(0, import_node_fs21.writeFileSync)(cachePath, JSON.stringify(Object.fromEntries(map), null, 2), "utf-8");
|
|
9649
9610
|
logger.info(`[app-name-map] refreshed ${map.size} entries from server and saved: ${cachePath}`);
|
|
9650
9611
|
} catch (e) {
|
|
9651
9612
|
const message = e instanceof Error ? e.message : String(e);
|
|
@@ -9689,19 +9650,19 @@ function createAppNameMapProvider(opts) {
|
|
|
9689
9650
|
}
|
|
9690
9651
|
|
|
9691
9652
|
// src/notification/storage.ts
|
|
9692
|
-
var
|
|
9653
|
+
var import_node_fs22 = require("fs");
|
|
9693
9654
|
var import_node_crypto2 = require("crypto");
|
|
9694
|
-
var
|
|
9655
|
+
var import_node_path18 = require("path");
|
|
9695
9656
|
var NOTIFICATION_DIR_NAME = "notifications";
|
|
9696
9657
|
var ID_INDEX_DIR_NAME = ".ids";
|
|
9697
9658
|
var CONTENT_KEY_INDEX_DIR_NAME = ".keys";
|
|
9698
9659
|
function getStateFallbackNotificationDir(stateDir) {
|
|
9699
|
-
return (0,
|
|
9660
|
+
return (0, import_node_path18.join)(stateDir, "plugins", "phone-notifications", NOTIFICATION_DIR_NAME);
|
|
9700
9661
|
}
|
|
9701
9662
|
function ensureWritableDirectory(dir) {
|
|
9702
9663
|
try {
|
|
9703
|
-
(0,
|
|
9704
|
-
(0,
|
|
9664
|
+
(0, import_node_fs22.mkdirSync)(dir, { recursive: true });
|
|
9665
|
+
(0, import_node_fs22.accessSync)(dir, import_node_fs22.constants.R_OK | import_node_fs22.constants.W_OK);
|
|
9705
9666
|
return true;
|
|
9706
9667
|
} catch {
|
|
9707
9668
|
return false;
|
|
@@ -9714,7 +9675,7 @@ function resolveNotificationStorageDir(ctx, logger) {
|
|
|
9714
9675
|
return stateNotifDir;
|
|
9715
9676
|
}
|
|
9716
9677
|
if (ctx.workspaceDir) {
|
|
9717
|
-
const workspaceDir = (0,
|
|
9678
|
+
const workspaceDir = (0, import_node_path18.join)(ctx.workspaceDir, NOTIFICATION_DIR_NAME);
|
|
9718
9679
|
if (ensureWritableDirectory(workspaceDir)) {
|
|
9719
9680
|
logger.warn(
|
|
9720
9681
|
`stateDir \u4E0D\u53EF\u7528\uFF0C\u901A\u77E5\u5DF2\u56DE\u9000\u5230 workspace \u8DEF\u5F84: ${workspaceDir}`
|
|
@@ -9729,8 +9690,8 @@ var NotificationStorage = class {
|
|
|
9729
9690
|
this.config = config;
|
|
9730
9691
|
this.logger = logger;
|
|
9731
9692
|
this.dir = dir;
|
|
9732
|
-
this.idIndexDir = (0,
|
|
9733
|
-
this.contentKeyIndexDir = (0,
|
|
9693
|
+
this.idIndexDir = (0, import_node_path18.join)(dir, ID_INDEX_DIR_NAME);
|
|
9694
|
+
this.contentKeyIndexDir = (0, import_node_path18.join)(dir, CONTENT_KEY_INDEX_DIR_NAME);
|
|
9734
9695
|
this.resolveDisplayName = resolveDisplayName;
|
|
9735
9696
|
}
|
|
9736
9697
|
dir;
|
|
@@ -9741,10 +9702,10 @@ var NotificationStorage = class {
|
|
|
9741
9702
|
dateWriteChains = /* @__PURE__ */ new Map();
|
|
9742
9703
|
resolveDisplayName;
|
|
9743
9704
|
async init() {
|
|
9744
|
-
(0,
|
|
9745
|
-
(0,
|
|
9746
|
-
(0,
|
|
9747
|
-
(0,
|
|
9705
|
+
(0, import_node_fs22.mkdirSync)(this.dir, { recursive: true });
|
|
9706
|
+
(0, import_node_fs22.mkdirSync)(this.idIndexDir, { recursive: true });
|
|
9707
|
+
(0, import_node_fs22.rmSync)(this.contentKeyIndexDir, { recursive: true, force: true });
|
|
9708
|
+
(0, import_node_fs22.mkdirSync)(this.contentKeyIndexDir, { recursive: true });
|
|
9748
9709
|
}
|
|
9749
9710
|
async ingest(items) {
|
|
9750
9711
|
const result = {
|
|
@@ -9783,7 +9744,7 @@ var NotificationStorage = class {
|
|
|
9783
9744
|
return { kind: "invalid" };
|
|
9784
9745
|
}
|
|
9785
9746
|
const dateKey = this.formatDate(ts);
|
|
9786
|
-
const filePath = (0,
|
|
9747
|
+
const filePath = (0, import_node_path18.join)(this.dir, `${dateKey}.json`);
|
|
9787
9748
|
const normalizedId = typeof n.id === "string" ? n.id.trim() : "";
|
|
9788
9749
|
const entry = this.buildStoredNotification(n);
|
|
9789
9750
|
return this.withDateWriteLock(dateKey, async () => {
|
|
@@ -9800,7 +9761,7 @@ var NotificationStorage = class {
|
|
|
9800
9761
|
};
|
|
9801
9762
|
const arr = this.readStoredNotifications(filePath);
|
|
9802
9763
|
arr.push(storedEntry);
|
|
9803
|
-
(0,
|
|
9764
|
+
(0, import_node_fs22.writeFileSync)(filePath, JSON.stringify(arr, null, 2), "utf-8");
|
|
9804
9765
|
if (normalizedId) {
|
|
9805
9766
|
this.recordNotificationId(dateKey, normalizedId);
|
|
9806
9767
|
}
|
|
@@ -9837,7 +9798,7 @@ var NotificationStorage = class {
|
|
|
9837
9798
|
return `${year}-${month}-${day}`;
|
|
9838
9799
|
}
|
|
9839
9800
|
getIdIndexPath(dateKey) {
|
|
9840
|
-
return (0,
|
|
9801
|
+
return (0, import_node_path18.join)(this.idIndexDir, `${dateKey}.ids`);
|
|
9841
9802
|
}
|
|
9842
9803
|
getIdSet(dateKey) {
|
|
9843
9804
|
const cached = this.idCache.get(dateKey);
|
|
@@ -9846,8 +9807,8 @@ var NotificationStorage = class {
|
|
|
9846
9807
|
}
|
|
9847
9808
|
const idPath = this.getIdIndexPath(dateKey);
|
|
9848
9809
|
const ids = /* @__PURE__ */ new Set();
|
|
9849
|
-
if ((0,
|
|
9850
|
-
const lines = (0,
|
|
9810
|
+
if ((0, import_node_fs22.existsSync)(idPath)) {
|
|
9811
|
+
const lines = (0, import_node_fs22.readFileSync)(idPath, "utf-8").split(/\r?\n/);
|
|
9851
9812
|
for (const line of lines) {
|
|
9852
9813
|
const id = line.trim();
|
|
9853
9814
|
if (id) {
|
|
@@ -9862,7 +9823,7 @@ var NotificationStorage = class {
|
|
|
9862
9823
|
return this.getIdSet(dateKey).has(id);
|
|
9863
9824
|
}
|
|
9864
9825
|
getContentKeyIndexPath(dateKey) {
|
|
9865
|
-
return (0,
|
|
9826
|
+
return (0, import_node_path18.join)(this.contentKeyIndexDir, `${dateKey}.keys`);
|
|
9866
9827
|
}
|
|
9867
9828
|
getContentKeySet(dateKey, filePath) {
|
|
9868
9829
|
const cached = this.contentKeyCache.get(dateKey);
|
|
@@ -9871,16 +9832,16 @@ var NotificationStorage = class {
|
|
|
9871
9832
|
}
|
|
9872
9833
|
const keyPath = this.getContentKeyIndexPath(dateKey);
|
|
9873
9834
|
const keys = /* @__PURE__ */ new Set();
|
|
9874
|
-
if ((0,
|
|
9835
|
+
if ((0, import_node_fs22.existsSync)(filePath)) {
|
|
9875
9836
|
for (const item of this.readStoredNotifications(filePath)) {
|
|
9876
9837
|
keys.add(this.buildNotificationContentKey(item));
|
|
9877
9838
|
}
|
|
9878
9839
|
}
|
|
9879
9840
|
if (keys.size > 0) {
|
|
9880
|
-
(0,
|
|
9841
|
+
(0, import_node_fs22.writeFileSync)(keyPath, `${Array.from(keys).join("\n")}
|
|
9881
9842
|
`, "utf-8");
|
|
9882
|
-
} else if ((0,
|
|
9883
|
-
(0,
|
|
9843
|
+
} else if ((0, import_node_fs22.existsSync)(keyPath)) {
|
|
9844
|
+
(0, import_node_fs22.rmSync)(keyPath, { force: true });
|
|
9884
9845
|
}
|
|
9885
9846
|
this.contentKeyCache.set(dateKey, keys);
|
|
9886
9847
|
return keys;
|
|
@@ -9895,7 +9856,7 @@ var NotificationStorage = class {
|
|
|
9895
9856
|
if (ids.has(id)) {
|
|
9896
9857
|
return;
|
|
9897
9858
|
}
|
|
9898
|
-
(0,
|
|
9859
|
+
(0, import_node_fs22.appendFileSync)(this.getIdIndexPath(dateKey), `${id}
|
|
9899
9860
|
`, "utf-8");
|
|
9900
9861
|
ids.add(id);
|
|
9901
9862
|
}
|
|
@@ -9905,7 +9866,7 @@ var NotificationStorage = class {
|
|
|
9905
9866
|
if (keys.has(key)) {
|
|
9906
9867
|
return;
|
|
9907
9868
|
}
|
|
9908
|
-
(0,
|
|
9869
|
+
(0, import_node_fs22.appendFileSync)(this.getContentKeyIndexPath(dateKey), `${key}
|
|
9909
9870
|
`, "utf-8");
|
|
9910
9871
|
keys.add(key);
|
|
9911
9872
|
}
|
|
@@ -9913,11 +9874,11 @@ var NotificationStorage = class {
|
|
|
9913
9874
|
return (0, import_node_crypto2.createHash)("sha256").update(entry.appName).update("").update(entry.title).update("").update(entry.content).update("").update(entry.timestamp).digest("hex");
|
|
9914
9875
|
}
|
|
9915
9876
|
readStoredNotifications(filePath) {
|
|
9916
|
-
if (!(0,
|
|
9877
|
+
if (!(0, import_node_fs22.existsSync)(filePath)) {
|
|
9917
9878
|
return [];
|
|
9918
9879
|
}
|
|
9919
9880
|
try {
|
|
9920
|
-
const parsed = JSON.parse((0,
|
|
9881
|
+
const parsed = JSON.parse((0, import_node_fs22.readFileSync)(filePath, "utf-8"));
|
|
9921
9882
|
return Array.isArray(parsed) ? parsed : [];
|
|
9922
9883
|
} catch {
|
|
9923
9884
|
return [];
|
|
@@ -9957,14 +9918,14 @@ var NotificationStorage = class {
|
|
|
9957
9918
|
const dateFilePattern = /^(\d{4}-\d{2}-\d{2})\.(json|md)$/;
|
|
9958
9919
|
const dateDirPattern = /^\d{4}-\d{2}-\d{2}$/;
|
|
9959
9920
|
try {
|
|
9960
|
-
for (const entry of (0,
|
|
9921
|
+
for (const entry of (0, import_node_fs22.readdirSync)(this.dir, { withFileTypes: true })) {
|
|
9961
9922
|
if (entry.isFile()) {
|
|
9962
9923
|
const match = dateFilePattern.exec(entry.name);
|
|
9963
9924
|
if (match && match[1] < cutoffDate) {
|
|
9964
|
-
(0,
|
|
9925
|
+
(0, import_node_fs22.rmSync)((0, import_node_path18.join)(this.dir, entry.name), { force: true });
|
|
9965
9926
|
}
|
|
9966
9927
|
} else if (entry.isDirectory() && dateDirPattern.test(entry.name) && entry.name < cutoffDate) {
|
|
9967
|
-
(0,
|
|
9928
|
+
(0, import_node_fs22.rmSync)((0, import_node_path18.join)(this.dir, entry.name), { recursive: true, force: true });
|
|
9968
9929
|
}
|
|
9969
9930
|
}
|
|
9970
9931
|
} catch {
|
|
@@ -9973,11 +9934,11 @@ var NotificationStorage = class {
|
|
|
9973
9934
|
/** Remove expired .ids index files */
|
|
9974
9935
|
pruneIdIndex(cutoffDate) {
|
|
9975
9936
|
try {
|
|
9976
|
-
for (const entry of (0,
|
|
9937
|
+
for (const entry of (0, import_node_fs22.readdirSync)(this.idIndexDir, { withFileTypes: true })) {
|
|
9977
9938
|
if (!entry.isFile()) continue;
|
|
9978
9939
|
const match = /^(\d{4}-\d{2}-\d{2})\.ids$/.exec(entry.name);
|
|
9979
9940
|
if (match && match[1] < cutoffDate) {
|
|
9980
|
-
(0,
|
|
9941
|
+
(0, import_node_fs22.rmSync)((0, import_node_path18.join)(this.idIndexDir, entry.name), { force: true });
|
|
9981
9942
|
this.idCache.delete(match[1]);
|
|
9982
9943
|
}
|
|
9983
9944
|
}
|
|
@@ -9986,11 +9947,11 @@ var NotificationStorage = class {
|
|
|
9986
9947
|
}
|
|
9987
9948
|
pruneContentKeyIndex(cutoffDate) {
|
|
9988
9949
|
try {
|
|
9989
|
-
for (const entry of (0,
|
|
9950
|
+
for (const entry of (0, import_node_fs22.readdirSync)(this.contentKeyIndexDir, { withFileTypes: true })) {
|
|
9990
9951
|
if (!entry.isFile()) continue;
|
|
9991
9952
|
const match = /^(\d{4}-\d{2}-\d{2})\.keys$/.exec(entry.name);
|
|
9992
9953
|
if (match && match[1] < cutoffDate) {
|
|
9993
|
-
(0,
|
|
9954
|
+
(0, import_node_fs22.rmSync)((0, import_node_path18.join)(this.contentKeyIndexDir, entry.name), { force: true });
|
|
9994
9955
|
this.contentKeyCache.delete(match[1]);
|
|
9995
9956
|
}
|
|
9996
9957
|
}
|
|
@@ -10005,8 +9966,8 @@ var NotificationStorage = class {
|
|
|
10005
9966
|
};
|
|
10006
9967
|
|
|
10007
9968
|
// src/recording/storage.ts
|
|
10008
|
-
var
|
|
10009
|
-
var
|
|
9969
|
+
var import_node_fs23 = require("fs");
|
|
9970
|
+
var import_node_path19 = require("path");
|
|
10010
9971
|
|
|
10011
9972
|
// src/recording/state-machine.ts
|
|
10012
9973
|
var VALID_TRANSITIONS = /* @__PURE__ */ new Map([
|
|
@@ -10067,7 +10028,7 @@ function stripMarkdownFence(markdown) {
|
|
|
10067
10028
|
}
|
|
10068
10029
|
function deriveTitleFromTranscriptPath(transcriptFile, recordingId) {
|
|
10069
10030
|
if (!transcriptFile) return void 0;
|
|
10070
|
-
const name = (0,
|
|
10031
|
+
const name = (0, import_node_path19.basename)(transcriptFile, ".md");
|
|
10071
10032
|
const prefix = `${recordingId}_`;
|
|
10072
10033
|
if (name.startsWith(prefix)) {
|
|
10073
10034
|
const derived = name.slice(prefix.length).trim();
|
|
@@ -10095,22 +10056,22 @@ function extractTranscriptContent(markdown) {
|
|
|
10095
10056
|
return lines.join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
10096
10057
|
}
|
|
10097
10058
|
function resolveRecordingStorageDir(ctx, logger) {
|
|
10098
|
-
const stateRecDir = (0,
|
|
10059
|
+
const stateRecDir = (0, import_node_path19.join)(
|
|
10099
10060
|
ctx.stateDir,
|
|
10100
10061
|
"plugins",
|
|
10101
10062
|
"phone-notifications",
|
|
10102
10063
|
RECORDINGS_DIR
|
|
10103
10064
|
);
|
|
10104
10065
|
try {
|
|
10105
|
-
(0,
|
|
10066
|
+
(0, import_node_fs23.mkdirSync)(stateRecDir, { recursive: true });
|
|
10106
10067
|
logger.info(`\u5F55\u97F3\u5C06\u5199\u5165 stateDir \u8DEF\u5F84: ${stateRecDir}`);
|
|
10107
10068
|
return stateRecDir;
|
|
10108
10069
|
} catch {
|
|
10109
10070
|
}
|
|
10110
10071
|
if (ctx.workspaceDir) {
|
|
10111
|
-
const wsRecDir = (0,
|
|
10072
|
+
const wsRecDir = (0, import_node_path19.join)(ctx.workspaceDir, RECORDINGS_DIR);
|
|
10112
10073
|
try {
|
|
10113
|
-
(0,
|
|
10074
|
+
(0, import_node_fs23.mkdirSync)(wsRecDir, { recursive: true });
|
|
10114
10075
|
logger.warn(`stateDir \u4E0D\u53EF\u7528\uFF0C\u5F55\u97F3\u5DF2\u56DE\u9000\u5230 workspace \u8DEF\u5F84: ${wsRecDir}`);
|
|
10115
10076
|
return wsRecDir;
|
|
10116
10077
|
} catch {
|
|
@@ -10122,11 +10083,11 @@ var RecordingStorage = class {
|
|
|
10122
10083
|
constructor(dir, logger) {
|
|
10123
10084
|
this.logger = logger;
|
|
10124
10085
|
this.dir = dir;
|
|
10125
|
-
this.audioDir = (0,
|
|
10126
|
-
this.transcriptDataDir = (0,
|
|
10127
|
-
this.transcriptsDir = (0,
|
|
10128
|
-
this.summariesDir = (0,
|
|
10129
|
-
this.indexPath = (0,
|
|
10086
|
+
this.audioDir = (0, import_node_path19.join)(dir, AUDIO_DIR);
|
|
10087
|
+
this.transcriptDataDir = (0, import_node_path19.join)(dir, TRANSCRIPT_DATA_DIR);
|
|
10088
|
+
this.transcriptsDir = (0, import_node_path19.join)(dir, TRANSCRIPTS_DIR);
|
|
10089
|
+
this.summariesDir = (0, import_node_path19.join)(dir, SUMMARIES_DIR);
|
|
10090
|
+
this.indexPath = (0, import_node_path19.join)(dir, INDEX_FILE);
|
|
10130
10091
|
}
|
|
10131
10092
|
dir;
|
|
10132
10093
|
audioDir;
|
|
@@ -10137,10 +10098,10 @@ var RecordingStorage = class {
|
|
|
10137
10098
|
index = { recordings: [] };
|
|
10138
10099
|
/** 初始化目录结构并加载索引 */
|
|
10139
10100
|
async init() {
|
|
10140
|
-
(0,
|
|
10141
|
-
(0,
|
|
10142
|
-
(0,
|
|
10143
|
-
(0,
|
|
10101
|
+
(0, import_node_fs23.mkdirSync)(this.audioDir, { recursive: true });
|
|
10102
|
+
(0, import_node_fs23.mkdirSync)(this.transcriptDataDir, { recursive: true });
|
|
10103
|
+
(0, import_node_fs23.mkdirSync)(this.transcriptsDir, { recursive: true });
|
|
10104
|
+
(0, import_node_fs23.mkdirSync)(this.summariesDir, { recursive: true });
|
|
10144
10105
|
this.loadIndex();
|
|
10145
10106
|
this.logger.info(
|
|
10146
10107
|
`\u5F55\u97F3\u5B58\u50A8\u5DF2\u521D\u59CB\u5316: ${this.dir}\uFF08\u5171 ${this.index.recordings.length} \u6761\u8BB0\u5F55\uFF09`
|
|
@@ -10184,13 +10145,13 @@ var RecordingStorage = class {
|
|
|
10184
10145
|
return id;
|
|
10185
10146
|
}
|
|
10186
10147
|
if (existing.transcriptDataFile) {
|
|
10187
|
-
(0,
|
|
10148
|
+
(0, import_node_fs23.rmSync)((0, import_node_path19.join)(this.dir, existing.transcriptDataFile), { force: true });
|
|
10188
10149
|
}
|
|
10189
10150
|
if (existing.transcriptFile) {
|
|
10190
|
-
(0,
|
|
10151
|
+
(0, import_node_fs23.rmSync)((0, import_node_path19.join)(this.dir, existing.transcriptFile), { force: true });
|
|
10191
10152
|
}
|
|
10192
10153
|
if (existing.summaryFile) {
|
|
10193
|
-
(0,
|
|
10154
|
+
(0, import_node_fs23.rmSync)((0, import_node_path19.join)(this.dir, existing.summaryFile), { force: true });
|
|
10194
10155
|
}
|
|
10195
10156
|
existing.metadata = metadata;
|
|
10196
10157
|
existing.status = "syncing_openclaw";
|
|
@@ -10258,7 +10219,7 @@ var RecordingStorage = class {
|
|
|
10258
10219
|
if (!entry) return;
|
|
10259
10220
|
const nextTranscriptDataFile = `${TRANSCRIPT_DATA_DIR}/${filename}`;
|
|
10260
10221
|
if (entry.transcriptDataFile && entry.transcriptDataFile !== nextTranscriptDataFile) {
|
|
10261
|
-
(0,
|
|
10222
|
+
(0, import_node_fs23.rmSync)((0, import_node_path19.join)(this.dir, entry.transcriptDataFile), { force: true });
|
|
10262
10223
|
}
|
|
10263
10224
|
entry.transcriptDataFile = nextTranscriptDataFile;
|
|
10264
10225
|
entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -10272,7 +10233,7 @@ var RecordingStorage = class {
|
|
|
10272
10233
|
if (!entry) return;
|
|
10273
10234
|
const nextTranscriptFile = `${TRANSCRIPTS_DIR}/${filename}`;
|
|
10274
10235
|
if (entry.transcriptFile && entry.transcriptFile !== nextTranscriptFile) {
|
|
10275
|
-
(0,
|
|
10236
|
+
(0, import_node_fs23.rmSync)((0, import_node_path19.join)(this.dir, entry.transcriptFile), { force: true });
|
|
10276
10237
|
}
|
|
10277
10238
|
entry.transcriptFile = nextTranscriptFile;
|
|
10278
10239
|
entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -10286,7 +10247,7 @@ var RecordingStorage = class {
|
|
|
10286
10247
|
if (!entry) return;
|
|
10287
10248
|
const nextSummaryFile = `${SUMMARIES_DIR}/${filename}`;
|
|
10288
10249
|
if (entry.summaryFile && entry.summaryFile !== nextSummaryFile) {
|
|
10289
|
-
(0,
|
|
10250
|
+
(0, import_node_fs23.rmSync)((0, import_node_path19.join)(this.dir, entry.summaryFile), { force: true });
|
|
10290
10251
|
}
|
|
10291
10252
|
entry.summaryFile = nextSummaryFile;
|
|
10292
10253
|
entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -10384,24 +10345,24 @@ var RecordingStorage = class {
|
|
|
10384
10345
|
const entry = this.findById(recordingId);
|
|
10385
10346
|
if (!entry) return false;
|
|
10386
10347
|
if (entry.audioFile) {
|
|
10387
|
-
const audioPath = (0,
|
|
10388
|
-
(0,
|
|
10348
|
+
const audioPath = (0, import_node_path19.join)(this.dir, entry.audioFile);
|
|
10349
|
+
(0, import_node_fs23.rmSync)(audioPath, { force: true });
|
|
10389
10350
|
}
|
|
10390
10351
|
if (entry.srtFile) {
|
|
10391
|
-
const srtPath = (0,
|
|
10392
|
-
(0,
|
|
10352
|
+
const srtPath = (0, import_node_path19.join)(this.dir, entry.srtFile);
|
|
10353
|
+
(0, import_node_fs23.rmSync)(srtPath, { force: true });
|
|
10393
10354
|
}
|
|
10394
10355
|
if (entry.transcriptDataFile) {
|
|
10395
|
-
const transcriptDataPath = (0,
|
|
10396
|
-
(0,
|
|
10356
|
+
const transcriptDataPath = (0, import_node_path19.join)(this.dir, entry.transcriptDataFile);
|
|
10357
|
+
(0, import_node_fs23.rmSync)(transcriptDataPath, { force: true });
|
|
10397
10358
|
}
|
|
10398
10359
|
if (entry.transcriptFile) {
|
|
10399
|
-
const transcriptPath = (0,
|
|
10400
|
-
(0,
|
|
10360
|
+
const transcriptPath = (0, import_node_path19.join)(this.dir, entry.transcriptFile);
|
|
10361
|
+
(0, import_node_fs23.rmSync)(transcriptPath, { force: true });
|
|
10401
10362
|
}
|
|
10402
10363
|
if (entry.summaryFile) {
|
|
10403
|
-
const summaryPath = (0,
|
|
10404
|
-
(0,
|
|
10364
|
+
const summaryPath = (0, import_node_path19.join)(this.dir, entry.summaryFile);
|
|
10365
|
+
(0, import_node_fs23.rmSync)(summaryPath, { force: true });
|
|
10405
10366
|
}
|
|
10406
10367
|
if (opts?.localOnly) {
|
|
10407
10368
|
entry.audioFile = void 0;
|
|
@@ -10459,34 +10420,34 @@ var RecordingStorage = class {
|
|
|
10459
10420
|
* 获取音频文件的绝对路径。ossUrl 用于推断文件扩展名
|
|
10460
10421
|
*/
|
|
10461
10422
|
getAudioFilePath(recordingId, ossUrl) {
|
|
10462
|
-
return (0,
|
|
10423
|
+
return (0, import_node_path19.join)(this.audioDir, this.buildAudioFilename(recordingId, ossUrl));
|
|
10463
10424
|
}
|
|
10464
10425
|
/**
|
|
10465
10426
|
* 获取打点文件的绝对路径
|
|
10466
10427
|
*/
|
|
10467
10428
|
getSrtFilePath(recordingId) {
|
|
10468
|
-
return (0,
|
|
10429
|
+
return (0, import_node_path19.join)(this.audioDir, this.buildSrtFilename(recordingId));
|
|
10469
10430
|
}
|
|
10470
10431
|
/**
|
|
10471
10432
|
* 获取转写 JSON 文件的绝对路径
|
|
10472
10433
|
*/
|
|
10473
10434
|
getTranscriptDataFilePath(recordingId) {
|
|
10474
|
-
return (0,
|
|
10435
|
+
return (0, import_node_path19.join)(this.transcriptDataDir, this.buildTranscriptDataFilename(recordingId));
|
|
10475
10436
|
}
|
|
10476
10437
|
/**
|
|
10477
10438
|
* 获取摘要文件的绝对路径
|
|
10478
10439
|
*/
|
|
10479
10440
|
getSummaryFilePath(recordingId) {
|
|
10480
|
-
return (0,
|
|
10441
|
+
return (0, import_node_path19.join)(this.summariesDir, this.buildSummaryFilename(recordingId));
|
|
10481
10442
|
}
|
|
10482
10443
|
// ─── Persistence ───
|
|
10483
10444
|
loadIndex() {
|
|
10484
|
-
if (!(0,
|
|
10445
|
+
if (!(0, import_node_fs23.existsSync)(this.indexPath)) {
|
|
10485
10446
|
this.index = { recordings: [] };
|
|
10486
10447
|
return;
|
|
10487
10448
|
}
|
|
10488
10449
|
try {
|
|
10489
|
-
const raw = JSON.parse((0,
|
|
10450
|
+
const raw = JSON.parse((0, import_node_fs23.readFileSync)(this.indexPath, "utf-8"));
|
|
10490
10451
|
if (raw && Array.isArray(raw.recordings)) {
|
|
10491
10452
|
let needsRewrite = false;
|
|
10492
10453
|
const normalized = raw.recordings.filter((entry) => entry && typeof entry === "object").map((entry) => {
|
|
@@ -10524,8 +10485,8 @@ var RecordingStorage = class {
|
|
|
10524
10485
|
segments: []
|
|
10525
10486
|
});
|
|
10526
10487
|
const transcriptDataFilename = this.buildTranscriptDataFilename(compacted.id);
|
|
10527
|
-
(0,
|
|
10528
|
-
(0,
|
|
10488
|
+
(0, import_node_fs23.writeFileSync)(
|
|
10489
|
+
(0, import_node_path19.join)(this.transcriptDataDir, transcriptDataFilename),
|
|
10529
10490
|
JSON.stringify(transcriptDoc, null, 2),
|
|
10530
10491
|
"utf-8"
|
|
10531
10492
|
);
|
|
@@ -10537,8 +10498,8 @@ var RecordingStorage = class {
|
|
|
10537
10498
|
compacted.summaryFile = entry.summaryFile;
|
|
10538
10499
|
} else if (typeof entry.summary === "string" && entry.summary.trim()) {
|
|
10539
10500
|
const summaryFilename = this.buildSummaryFilename(entry.id);
|
|
10540
|
-
(0,
|
|
10541
|
-
(0,
|
|
10501
|
+
(0, import_node_fs23.writeFileSync)(
|
|
10502
|
+
(0, import_node_path19.join)(this.summariesDir, summaryFilename),
|
|
10542
10503
|
entry.summary.trim(),
|
|
10543
10504
|
"utf-8"
|
|
10544
10505
|
);
|
|
@@ -10548,8 +10509,8 @@ var RecordingStorage = class {
|
|
|
10548
10509
|
const summaryFromDocument = extractTranscriptSummaryFromDocument(transcriptDoc);
|
|
10549
10510
|
if (summaryFromDocument) {
|
|
10550
10511
|
const summaryFilename = this.buildSummaryFilename(entry.id);
|
|
10551
|
-
(0,
|
|
10552
|
-
(0,
|
|
10512
|
+
(0, import_node_fs23.writeFileSync)(
|
|
10513
|
+
(0, import_node_path19.join)(this.summariesDir, summaryFilename),
|
|
10553
10514
|
summaryFromDocument,
|
|
10554
10515
|
"utf-8"
|
|
10555
10516
|
);
|
|
@@ -10589,7 +10550,7 @@ var RecordingStorage = class {
|
|
|
10589
10550
|
}
|
|
10590
10551
|
readRelativeTextFile(relativePath) {
|
|
10591
10552
|
try {
|
|
10592
|
-
return (0,
|
|
10553
|
+
return (0, import_node_fs23.readFileSync)((0, import_node_path19.join)(this.dir, relativePath), "utf-8");
|
|
10593
10554
|
} catch {
|
|
10594
10555
|
return void 0;
|
|
10595
10556
|
}
|
|
@@ -10602,7 +10563,7 @@ var RecordingStorage = class {
|
|
|
10602
10563
|
return parseTranscriptDocument(raw);
|
|
10603
10564
|
}
|
|
10604
10565
|
saveIndex() {
|
|
10605
|
-
(0,
|
|
10566
|
+
(0, import_node_fs23.writeFileSync)(
|
|
10606
10567
|
this.indexPath,
|
|
10607
10568
|
JSON.stringify(this.index, null, 2),
|
|
10608
10569
|
"utf-8"
|
|
@@ -10616,8 +10577,8 @@ var RecordingStorage = class {
|
|
|
10616
10577
|
init_transcript_document();
|
|
10617
10578
|
|
|
10618
10579
|
// src/recording/downloader.ts
|
|
10619
|
-
var
|
|
10620
|
-
var
|
|
10580
|
+
var import_node_fs24 = require("fs");
|
|
10581
|
+
var import_node_path20 = require("path");
|
|
10621
10582
|
var import_promises2 = require("stream/promises");
|
|
10622
10583
|
var import_node_stream = require("stream");
|
|
10623
10584
|
var DEFAULT_TIMEOUT_MS2 = 5 * 60 * 1e3;
|
|
@@ -10627,7 +10588,7 @@ async function downloadFile(url, destPath, logger, options) {
|
|
|
10627
10588
|
const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
|
|
10628
10589
|
const maxRetries = options?.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
10629
10590
|
const retryBackoffMs = options?.retryBackoffMs ?? DEFAULT_RETRY_BACKOFF_MS;
|
|
10630
|
-
(0,
|
|
10591
|
+
(0, import_node_fs24.mkdirSync)((0, import_node_path20.dirname)(destPath), { recursive: true });
|
|
10631
10592
|
let lastError;
|
|
10632
10593
|
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
10633
10594
|
const startMs = Date.now();
|
|
@@ -10645,11 +10606,11 @@ async function downloadFile(url, destPath, logger, options) {
|
|
|
10645
10606
|
if (!res.body) {
|
|
10646
10607
|
throw new Error("\u54CD\u5E94\u4F53\u4E3A\u7A7A");
|
|
10647
10608
|
}
|
|
10648
|
-
const writeStream = (0,
|
|
10609
|
+
const writeStream = (0, import_node_fs24.createWriteStream)(destPath);
|
|
10649
10610
|
const readable = import_node_stream.Readable.fromWeb(res.body);
|
|
10650
10611
|
await (0, import_promises2.pipeline)(readable, writeStream);
|
|
10651
10612
|
const elapsed = Date.now() - startMs;
|
|
10652
|
-
const fileSize = (0,
|
|
10613
|
+
const fileSize = (0, import_node_fs24.existsSync)(destPath) ? (0, import_node_fs24.statSync)(destPath).size : 0;
|
|
10653
10614
|
logger.info(
|
|
10654
10615
|
`[downloader] \u4E0B\u8F7D\u5B8C\u6210: ${destPath} (${formatBytes(fileSize)}, ${elapsed}ms)`
|
|
10655
10616
|
);
|
|
@@ -10660,7 +10621,7 @@ async function downloadFile(url, destPath, logger, options) {
|
|
|
10660
10621
|
} catch (err2) {
|
|
10661
10622
|
lastError = err2?.message ?? String(err2);
|
|
10662
10623
|
try {
|
|
10663
|
-
if ((0,
|
|
10624
|
+
if ((0, import_node_fs24.existsSync)(destPath)) (0, import_node_fs24.unlinkSync)(destPath);
|
|
10664
10625
|
} catch {
|
|
10665
10626
|
}
|
|
10666
10627
|
const isAbort = err2?.name === "AbortError";
|
|
@@ -10702,6 +10663,63 @@ init_whisper_local();
|
|
|
10702
10663
|
|
|
10703
10664
|
// src/recording/handler.ts
|
|
10704
10665
|
init_asr();
|
|
10666
|
+
|
|
10667
|
+
// src/recording/account-oss.ts
|
|
10668
|
+
init_credentials();
|
|
10669
|
+
init_env();
|
|
10670
|
+
async function deleteAccountOssFile(fileUrl, logger) {
|
|
10671
|
+
const trimmed = fileUrl?.trim();
|
|
10672
|
+
if (!trimmed) {
|
|
10673
|
+
return { ok: false, error: "fileUrl is empty" };
|
|
10674
|
+
}
|
|
10675
|
+
const apiKey = loadApiKey();
|
|
10676
|
+
if (!apiKey) {
|
|
10677
|
+
return { ok: false, error: "API Key \u672A\u8BBE\u7F6E\uFF0C\u8DF3\u8FC7 OSS \u6587\u4EF6\u5220\u9664" };
|
|
10678
|
+
}
|
|
10679
|
+
const endpoint = getEnvUrls().accountFileDeleteUrl;
|
|
10680
|
+
const headerKey = apiKey.startsWith("Bearer ") ? apiKey.slice("Bearer ".length) : apiKey;
|
|
10681
|
+
const body = new URLSearchParams({ fileUrl: trimmed }).toString();
|
|
10682
|
+
logger.info(`[account-oss-delete] \u63D0\u4EA4 OSS \u6587\u4EF6\u5220\u9664: endpoint=${endpoint}, fileUrl=${trimmed}`);
|
|
10683
|
+
let res;
|
|
10684
|
+
try {
|
|
10685
|
+
res = await fetch(endpoint, {
|
|
10686
|
+
method: "POST",
|
|
10687
|
+
headers: {
|
|
10688
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
10689
|
+
"X-Api-Key-Id": headerKey
|
|
10690
|
+
},
|
|
10691
|
+
body
|
|
10692
|
+
});
|
|
10693
|
+
} catch (err2) {
|
|
10694
|
+
const error = err2?.message ?? String(err2);
|
|
10695
|
+
logger.warn(`[account-oss-delete] \u7F51\u7EDC\u5F02\u5E38: ${error}`);
|
|
10696
|
+
return { ok: false, error };
|
|
10697
|
+
}
|
|
10698
|
+
const text = await res.text();
|
|
10699
|
+
if (!res.ok) {
|
|
10700
|
+
logger.warn(
|
|
10701
|
+
`[account-oss-delete] HTTP \u9519\u8BEF: status=${res.status}, body=${text.slice(0, 300)}`
|
|
10702
|
+
);
|
|
10703
|
+
return { ok: false, error: `HTTP ${res.status} ${text.slice(0, 200)}` };
|
|
10704
|
+
}
|
|
10705
|
+
let payload;
|
|
10706
|
+
try {
|
|
10707
|
+
payload = text ? JSON.parse(text) : void 0;
|
|
10708
|
+
} catch {
|
|
10709
|
+
logger.warn(`[account-oss-delete] \u54CD\u5E94\u975E JSON: body=${text.slice(0, 300)}`);
|
|
10710
|
+
return { ok: false, error: "response is not JSON" };
|
|
10711
|
+
}
|
|
10712
|
+
const code = typeof payload?.code === "number" ? String(payload.code) : payload?.code?.trim?.();
|
|
10713
|
+
if (code !== "000000") {
|
|
10714
|
+
const msg = payload?.msg?.trim?.() || text.slice(0, 200);
|
|
10715
|
+
logger.warn(`[account-oss-delete] \u4E1A\u52A1\u5931\u8D25: code=${code ?? "n/a"}, msg=${msg}`);
|
|
10716
|
+
return { ok: false, error: `${code ?? "unknown"} ${msg}`.trim() };
|
|
10717
|
+
}
|
|
10718
|
+
logger.info(`[account-oss-delete] OSS \u6587\u4EF6\u5DF2\u5220\u9664: fileUrl=${trimmed}`);
|
|
10719
|
+
return { ok: true };
|
|
10720
|
+
}
|
|
10721
|
+
|
|
10722
|
+
// src/recording/handler.ts
|
|
10705
10723
|
function emitRecordingStatus(recordingId, storage, logger, notifyStatus, error, extras) {
|
|
10706
10724
|
if (!notifyStatus) {
|
|
10707
10725
|
return;
|
|
@@ -10882,6 +10900,14 @@ async function triggerTranscription(recordingId, storage, asrConfig, logger, opt
|
|
|
10882
10900
|
logger.info(
|
|
10883
10901
|
`[asr-trigger] \u8F6C\u5199\u5B8C\u6210: ${recordingId}, summary="${result.summary}"`
|
|
10884
10902
|
);
|
|
10903
|
+
const ossAudioUrl = entry.metadata.oss_audio_url?.trim();
|
|
10904
|
+
if (ossAudioUrl) {
|
|
10905
|
+
void deleteAccountOssFile(ossAudioUrl, logger).catch((err2) => {
|
|
10906
|
+
logger.warn(
|
|
10907
|
+
`[asr-trigger] OSS \u97F3\u9891\u6E05\u7406\u5F02\u5E38 (\u975E\u81F4\u547D): ${recordingId}, ${err2?.message ?? err2}`
|
|
10908
|
+
);
|
|
10909
|
+
});
|
|
10910
|
+
}
|
|
10885
10911
|
} else {
|
|
10886
10912
|
storage.updateStatus(recordingId, "transcribe_failed");
|
|
10887
10913
|
emitRecordingStatus(
|
|
@@ -10898,13 +10924,13 @@ async function triggerTranscription(recordingId, storage, asrConfig, logger, opt
|
|
|
10898
10924
|
}
|
|
10899
10925
|
|
|
10900
10926
|
// src/tunnel/service.ts
|
|
10901
|
-
var
|
|
10902
|
-
var
|
|
10927
|
+
var import_node_fs29 = require("fs");
|
|
10928
|
+
var import_node_path25 = require("path");
|
|
10903
10929
|
init_credentials();
|
|
10904
10930
|
|
|
10905
10931
|
// src/tunnel/relay-client.ts
|
|
10906
|
-
var
|
|
10907
|
-
var
|
|
10932
|
+
var import_node_fs27 = require("fs");
|
|
10933
|
+
var import_node_path23 = require("path");
|
|
10908
10934
|
|
|
10909
10935
|
// node_modules/.pnpm/ws@8.19.0/node_modules/ws/wrapper.mjs
|
|
10910
10936
|
var import_stream = __toESM(require_stream(), 1);
|
|
@@ -10948,8 +10974,8 @@ var RelayClient = class {
|
|
|
10948
10974
|
lastDisconnectReason
|
|
10949
10975
|
};
|
|
10950
10976
|
try {
|
|
10951
|
-
(0,
|
|
10952
|
-
(0,
|
|
10977
|
+
(0, import_node_fs27.mkdirSync)((0, import_node_path23.dirname)(this.opts.statusFilePath), { recursive: true });
|
|
10978
|
+
(0, import_node_fs27.writeFileSync)(this.opts.statusFilePath, JSON.stringify(info, null, 2));
|
|
10953
10979
|
} catch {
|
|
10954
10980
|
}
|
|
10955
10981
|
}
|
|
@@ -11331,8 +11357,8 @@ init_host();
|
|
|
11331
11357
|
|
|
11332
11358
|
// src/tunnel/device-identity.ts
|
|
11333
11359
|
var import_node_crypto3 = __toESM(require("crypto"), 1);
|
|
11334
|
-
var
|
|
11335
|
-
var
|
|
11360
|
+
var import_node_fs28 = __toESM(require("fs"), 1);
|
|
11361
|
+
var import_node_path24 = __toESM(require("path"), 1);
|
|
11336
11362
|
init_host();
|
|
11337
11363
|
var ED25519_SPKI_PREFIX = Buffer.from("302a300506032b6570032100", "hex");
|
|
11338
11364
|
function base64UrlEncode(buf) {
|
|
@@ -11377,10 +11403,10 @@ function resolveClientStateDir(stateDir) {
|
|
|
11377
11403
|
return stateDir ?? resolveStateDir();
|
|
11378
11404
|
}
|
|
11379
11405
|
function ensureDir(filePath) {
|
|
11380
|
-
|
|
11406
|
+
import_node_fs28.default.mkdirSync(import_node_path24.default.dirname(filePath), { recursive: true });
|
|
11381
11407
|
}
|
|
11382
11408
|
function resolveIdentityPath(stateDir) {
|
|
11383
|
-
return
|
|
11409
|
+
return import_node_path24.default.join(stateDir, "identity", "device.json");
|
|
11384
11410
|
}
|
|
11385
11411
|
function normalizeDeviceAuthRole(role) {
|
|
11386
11412
|
return role.trim();
|
|
@@ -11396,12 +11422,12 @@ function normalizeDeviceAuthScopes(scopes) {
|
|
|
11396
11422
|
return [...out].sort();
|
|
11397
11423
|
}
|
|
11398
11424
|
function resolveDeviceAuthPath(stateDir) {
|
|
11399
|
-
return
|
|
11425
|
+
return import_node_path24.default.join(stateDir, "identity", "device-auth.json");
|
|
11400
11426
|
}
|
|
11401
11427
|
function readDeviceAuthStore(filePath) {
|
|
11402
11428
|
try {
|
|
11403
|
-
if (!
|
|
11404
|
-
const raw =
|
|
11429
|
+
if (!import_node_fs28.default.existsSync(filePath)) return null;
|
|
11430
|
+
const raw = import_node_fs28.default.readFileSync(filePath, "utf8");
|
|
11405
11431
|
const parsed = JSON.parse(raw);
|
|
11406
11432
|
if (parsed?.version !== 1 || typeof parsed.deviceId !== "string") return null;
|
|
11407
11433
|
if (!parsed.tokens || typeof parsed.tokens !== "object") return null;
|
|
@@ -11412,12 +11438,12 @@ function readDeviceAuthStore(filePath) {
|
|
|
11412
11438
|
}
|
|
11413
11439
|
function writeDeviceAuthStore(filePath, store) {
|
|
11414
11440
|
ensureDir(filePath);
|
|
11415
|
-
|
|
11441
|
+
import_node_fs28.default.writeFileSync(filePath, `${JSON.stringify(store, null, 2)}
|
|
11416
11442
|
`, {
|
|
11417
11443
|
mode: 384
|
|
11418
11444
|
});
|
|
11419
11445
|
try {
|
|
11420
|
-
|
|
11446
|
+
import_node_fs28.default.chmodSync(filePath, 384);
|
|
11421
11447
|
} catch {
|
|
11422
11448
|
}
|
|
11423
11449
|
}
|
|
@@ -11464,8 +11490,8 @@ function clearDeviceAuthToken(params) {
|
|
|
11464
11490
|
function loadOrCreateDeviceIdentity(stateDir) {
|
|
11465
11491
|
const filePath = resolveIdentityPath(stateDir);
|
|
11466
11492
|
try {
|
|
11467
|
-
if (
|
|
11468
|
-
const raw =
|
|
11493
|
+
if (import_node_fs28.default.existsSync(filePath)) {
|
|
11494
|
+
const raw = import_node_fs28.default.readFileSync(filePath, "utf8");
|
|
11469
11495
|
const parsed = JSON.parse(raw);
|
|
11470
11496
|
if (parsed?.version === 1 && typeof parsed.deviceId === "string" && typeof parsed.publicKeyPem === "string" && typeof parsed.privateKeyPem === "string") {
|
|
11471
11497
|
const derivedId = fingerprintPublicKey(parsed.publicKeyPem);
|
|
@@ -11486,14 +11512,14 @@ function loadOrCreateDeviceIdentity(stateDir) {
|
|
|
11486
11512
|
publicKeyPem,
|
|
11487
11513
|
privateKeyPem
|
|
11488
11514
|
};
|
|
11489
|
-
|
|
11515
|
+
import_node_fs28.default.mkdirSync(import_node_path24.default.dirname(filePath), { recursive: true });
|
|
11490
11516
|
const stored = {
|
|
11491
11517
|
version: 1,
|
|
11492
11518
|
...identity,
|
|
11493
11519
|
createdAtMs: Date.now()
|
|
11494
11520
|
};
|
|
11495
11521
|
ensureDir(filePath);
|
|
11496
|
-
|
|
11522
|
+
import_node_fs28.default.writeFileSync(filePath, `${JSON.stringify(stored, null, 2)}
|
|
11497
11523
|
`, {
|
|
11498
11524
|
mode: 384
|
|
11499
11525
|
});
|
|
@@ -12265,7 +12291,7 @@ function createTunnelService(opts) {
|
|
|
12265
12291
|
}
|
|
12266
12292
|
function readLockOwner(filePath) {
|
|
12267
12293
|
try {
|
|
12268
|
-
const parsed = JSON.parse((0,
|
|
12294
|
+
const parsed = JSON.parse((0, import_node_fs29.readFileSync)(filePath, "utf-8"));
|
|
12269
12295
|
return typeof parsed.pid === "number" ? parsed.pid : null;
|
|
12270
12296
|
} catch {
|
|
12271
12297
|
return null;
|
|
@@ -12278,23 +12304,23 @@ function createTunnelService(opts) {
|
|
|
12278
12304
|
lockFd = null;
|
|
12279
12305
|
if (fd !== null) {
|
|
12280
12306
|
try {
|
|
12281
|
-
(0,
|
|
12307
|
+
(0, import_node_fs29.closeSync)(fd);
|
|
12282
12308
|
} catch {
|
|
12283
12309
|
}
|
|
12284
12310
|
}
|
|
12285
12311
|
if (filePath) {
|
|
12286
12312
|
try {
|
|
12287
|
-
(0,
|
|
12313
|
+
(0, import_node_fs29.unlinkSync)(filePath);
|
|
12288
12314
|
} catch {
|
|
12289
12315
|
}
|
|
12290
12316
|
}
|
|
12291
12317
|
}
|
|
12292
12318
|
function acquireLock(filePath) {
|
|
12293
|
-
(0,
|
|
12319
|
+
(0, import_node_fs29.mkdirSync)((0, import_node_path25.dirname)(filePath), { recursive: true });
|
|
12294
12320
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
12295
12321
|
try {
|
|
12296
|
-
const fd = (0,
|
|
12297
|
-
(0,
|
|
12322
|
+
const fd = (0, import_node_fs29.openSync)(filePath, "wx", 384);
|
|
12323
|
+
(0, import_node_fs29.writeFileSync)(
|
|
12298
12324
|
fd,
|
|
12299
12325
|
JSON.stringify({
|
|
12300
12326
|
pid: process.pid,
|
|
@@ -12318,7 +12344,7 @@ function createTunnelService(opts) {
|
|
|
12318
12344
|
`Relay tunnel: removing stale local lock owned by dead pid=${ownerPid}`
|
|
12319
12345
|
);
|
|
12320
12346
|
try {
|
|
12321
|
-
(0,
|
|
12347
|
+
(0, import_node_fs29.unlinkSync)(filePath);
|
|
12322
12348
|
} catch {
|
|
12323
12349
|
}
|
|
12324
12350
|
continue;
|
|
@@ -12363,12 +12389,12 @@ function createTunnelService(opts) {
|
|
|
12363
12389
|
return;
|
|
12364
12390
|
}
|
|
12365
12391
|
const { logger } = opts;
|
|
12366
|
-
const baseStateDir = (0,
|
|
12392
|
+
const baseStateDir = (0, import_node_path25.join)(ctx.stateDir, "plugins", "phone-notifications");
|
|
12367
12393
|
logger.info(
|
|
12368
12394
|
`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})`
|
|
12369
12395
|
);
|
|
12370
|
-
const statusFilePath = (0,
|
|
12371
|
-
const lockPath = (0,
|
|
12396
|
+
const statusFilePath = (0, import_node_path25.join)(baseStateDir, "tunnel-status.json");
|
|
12397
|
+
const lockPath = (0, import_node_path25.join)(baseStateDir, "relay-tunnel.lock");
|
|
12372
12398
|
if (!acquireLock(lockPath)) {
|
|
12373
12399
|
return;
|
|
12374
12400
|
}
|
|
@@ -12508,7 +12534,7 @@ function readHostGatewayConfig(params) {
|
|
|
12508
12534
|
let configData;
|
|
12509
12535
|
if (configPath) {
|
|
12510
12536
|
try {
|
|
12511
|
-
configData = JSON.parse((0,
|
|
12537
|
+
configData = JSON.parse((0, import_node_fs30.readFileSync)(configPath, "utf-8"));
|
|
12512
12538
|
} catch (err2) {
|
|
12513
12539
|
if (err2?.code !== "ENOENT") {
|
|
12514
12540
|
params.logger.warn(
|
|
@@ -13270,7 +13296,6 @@ var index_default = {
|
|
|
13270
13296
|
recordingStorage = nextRecordingStorage;
|
|
13271
13297
|
},
|
|
13272
13298
|
onStorageReady() {
|
|
13273
|
-
migrateLegacyLightRuleTasks(lightRuleCtx, logger);
|
|
13274
13299
|
lightRuleRegistry.reload();
|
|
13275
13300
|
}
|
|
13276
13301
|
});
|