@yoooclaw/phone-notifications 1.11.1 → 1.11.2-beta.0
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 +362 -404
- package/dist/index.cjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -535,20 +535,20 @@ function selectModelByMemory(availableGB, isAppleSilicon = false) {
|
|
|
535
535
|
return "tiny";
|
|
536
536
|
}
|
|
537
537
|
function resolveModelsDir(dataDir) {
|
|
538
|
-
const dir = (0,
|
|
539
|
-
(0,
|
|
538
|
+
const dir = (0, import_node_path21.join)(dataDir, WHISPER_MODELS_DIR);
|
|
539
|
+
(0, import_node_fs25.mkdirSync)(dir, { recursive: true });
|
|
540
540
|
return dir;
|
|
541
541
|
}
|
|
542
542
|
function resolveBinDir(dataDir) {
|
|
543
|
-
const dir = (0,
|
|
544
|
-
(0,
|
|
543
|
+
const dir = (0, import_node_path21.join)(dataDir, WHISPER_BIN_DIR);
|
|
544
|
+
(0, import_node_fs25.mkdirSync)(dir, { recursive: true });
|
|
545
545
|
return dir;
|
|
546
546
|
}
|
|
547
547
|
function isModelDownloaded(modelsDir, modelSize) {
|
|
548
|
-
const modelPath = (0,
|
|
549
|
-
if (!(0,
|
|
548
|
+
const modelPath = (0, import_node_path21.join)(modelsDir, MODEL_FILENAMES[modelSize]);
|
|
549
|
+
if (!(0, import_node_fs25.existsSync)(modelPath)) return false;
|
|
550
550
|
try {
|
|
551
|
-
const stat = (0,
|
|
551
|
+
const stat = (0, import_node_fs25.statSync)(modelPath);
|
|
552
552
|
const expectedSize = MODEL_DISK_SIZES[modelSize];
|
|
553
553
|
return stat.size >= expectedSize * 0.8;
|
|
554
554
|
} catch {
|
|
@@ -557,7 +557,7 @@ function isModelDownloaded(modelsDir, modelSize) {
|
|
|
557
557
|
}
|
|
558
558
|
async function downloadModel(modelsDir, modelSize, logger, modelSource, mirrorUrl) {
|
|
559
559
|
const filename = MODEL_FILENAMES[modelSize];
|
|
560
|
-
const modelPath = (0,
|
|
560
|
+
const modelPath = (0, import_node_path21.join)(modelsDir, filename);
|
|
561
561
|
if (isModelDownloaded(modelsDir, modelSize)) {
|
|
562
562
|
logger.info(`[whisper-local] \u6A21\u578B\u5DF2\u5B58\u5728\uFF0C\u8DF3\u8FC7\u4E0B\u8F7D: ${filename}`);
|
|
563
563
|
return { ok: true, modelPath };
|
|
@@ -623,7 +623,7 @@ async function probeUrl(url, logger) {
|
|
|
623
623
|
async function downloadFromUrl(url, modelPath, logger) {
|
|
624
624
|
const tmpPath = `${modelPath}.downloading`;
|
|
625
625
|
try {
|
|
626
|
-
(0,
|
|
626
|
+
(0, import_node_fs25.mkdirSync)((0, import_node_path21.dirname)(modelPath), { recursive: true });
|
|
627
627
|
const controller = new AbortController();
|
|
628
628
|
const timer = setTimeout(() => controller.abort(), 30 * 60 * 1e3);
|
|
629
629
|
try {
|
|
@@ -639,7 +639,7 @@ async function downloadFromUrl(url, modelPath, logger) {
|
|
|
639
639
|
return { ok: false, modelPath, error: "\u6A21\u578B\u4E0B\u8F7D\u5931\u8D25: \u54CD\u5E94\u4F53\u4E3A\u7A7A" };
|
|
640
640
|
}
|
|
641
641
|
const contentLength = Number(res.headers.get("content-length") ?? 0);
|
|
642
|
-
const writeStream = (0,
|
|
642
|
+
const writeStream = (0, import_node_fs25.createWriteStream)(tmpPath);
|
|
643
643
|
const readable = import_node_stream2.Readable.fromWeb(res.body);
|
|
644
644
|
let downloaded = 0;
|
|
645
645
|
let lastLogPercent = 0;
|
|
@@ -661,14 +661,14 @@ async function downloadFromUrl(url, modelPath, logger) {
|
|
|
661
661
|
}
|
|
662
662
|
const { renameSync: renameSync2 } = await import("fs");
|
|
663
663
|
renameSync2(tmpPath, modelPath);
|
|
664
|
-
const fileSize = (0,
|
|
664
|
+
const fileSize = (0, import_node_fs25.statSync)(modelPath).size;
|
|
665
665
|
logger.info(
|
|
666
|
-
`[whisper-local] \u6A21\u578B\u4E0B\u8F7D\u5B8C\u6210: ${(0,
|
|
666
|
+
`[whisper-local] \u6A21\u578B\u4E0B\u8F7D\u5B8C\u6210: ${(0, import_node_path21.basename)(modelPath)} (${formatBytes2(fileSize)})`
|
|
667
667
|
);
|
|
668
668
|
return { ok: true, modelPath };
|
|
669
669
|
} catch (err2) {
|
|
670
670
|
try {
|
|
671
|
-
if ((0,
|
|
671
|
+
if ((0, import_node_fs25.existsSync)(tmpPath)) (0, import_node_fs25.unlinkSync)(tmpPath);
|
|
672
672
|
} catch {
|
|
673
673
|
}
|
|
674
674
|
const msg = err2?.name === "AbortError" ? "\u6A21\u578B\u4E0B\u8F7D\u8D85\u65F6\uFF0830 \u5206\u949F\uFF09" : err2?.message ?? String(err2);
|
|
@@ -680,8 +680,8 @@ function findWhisperBinary(dataDir, logger) {
|
|
|
680
680
|
const binDir = resolveBinDir(dataDir);
|
|
681
681
|
const binNames = (0, import_node_os4.platform)() === "win32" ? ["whisper-cli.exe", "whisper.exe", "main.exe"] : ["whisper-cli", "whisper", "main"];
|
|
682
682
|
for (const name of binNames) {
|
|
683
|
-
const binPath = (0,
|
|
684
|
-
if ((0,
|
|
683
|
+
const binPath = (0, import_node_path21.join)(binDir, name);
|
|
684
|
+
if ((0, import_node_fs25.existsSync)(binPath)) {
|
|
685
685
|
logger.info(`[whisper-local] \u627E\u5230\u672C\u5730\u4E8C\u8FDB\u5236: ${binPath}`);
|
|
686
686
|
return binPath;
|
|
687
687
|
}
|
|
@@ -732,7 +732,7 @@ async function transcribeWithWhisperLocal(audioFilePath, localConfig, dataDir, l
|
|
|
732
732
|
return { ok: false, error: `\u6A21\u578B\u4E0B\u8F7D\u5931\u8D25: ${downloadResult.error}` };
|
|
733
733
|
}
|
|
734
734
|
}
|
|
735
|
-
const modelPath = (0,
|
|
735
|
+
const modelPath = (0, import_node_path21.join)(modelsDir, MODEL_FILENAMES[modelSize]);
|
|
736
736
|
let inputPath = audioFilePath;
|
|
737
737
|
let tmpWavPath = null;
|
|
738
738
|
const actualFmt = detectAudioFormat(audioFilePath);
|
|
@@ -784,10 +784,10 @@ async function transcribeWithWhisperLocal(audioFilePath, localConfig, dataDir, l
|
|
|
784
784
|
logger.info(`[whisper-local] \u8F6C\u5199\u8017\u65F6: ${Math.round(elapsed / 1e3)}s`);
|
|
785
785
|
const jsonPath = inputPath + ".json";
|
|
786
786
|
let jsonContent;
|
|
787
|
-
if ((0,
|
|
788
|
-
jsonContent = (0,
|
|
787
|
+
if ((0, import_node_fs25.existsSync)(jsonPath)) {
|
|
788
|
+
jsonContent = (0, import_node_fs25.readFileSync)(jsonPath, "utf-8");
|
|
789
789
|
try {
|
|
790
|
-
(0,
|
|
790
|
+
(0, import_node_fs25.unlinkSync)(jsonPath);
|
|
791
791
|
} catch {
|
|
792
792
|
}
|
|
793
793
|
} else {
|
|
@@ -865,10 +865,10 @@ function getPhysicalCoreCount() {
|
|
|
865
865
|
}
|
|
866
866
|
function detectAudioFormat(filePath) {
|
|
867
867
|
try {
|
|
868
|
-
const fd = (0,
|
|
868
|
+
const fd = (0, import_node_fs25.openSync)(filePath, "r");
|
|
869
869
|
const buf = Buffer.alloc(12);
|
|
870
|
-
(0,
|
|
871
|
-
(0,
|
|
870
|
+
(0, import_node_fs25.readSync)(fd, buf, 0, 12, 0);
|
|
871
|
+
(0, import_node_fs25.closeSync)(fd);
|
|
872
872
|
const header = buf.toString("ascii", 0, 4);
|
|
873
873
|
const header8 = buf.toString("ascii", 0, 8);
|
|
874
874
|
if (header === "RIFF" && buf.toString("ascii", 8, 12) === "WAVE") return ".wav";
|
|
@@ -903,7 +903,7 @@ function convertToWav(inputPath, outputPath, actualFmt, logger) {
|
|
|
903
903
|
timeout: 12e4,
|
|
904
904
|
stdio: ["pipe", "pipe", "pipe"]
|
|
905
905
|
});
|
|
906
|
-
if (ffmpegResult.status === 0 && (0,
|
|
906
|
+
if (ffmpegResult.status === 0 && (0, import_node_fs25.existsSync)(outputPath)) {
|
|
907
907
|
logger.info(`[whisper-local] ffmpeg \u8F6C\u6362\u5B8C\u6210: ${outputPath}`);
|
|
908
908
|
return { ok: true };
|
|
909
909
|
}
|
|
@@ -916,7 +916,7 @@ function convertToWav(inputPath, outputPath, actualFmt, logger) {
|
|
|
916
916
|
["--rate", "16000", "--mono", inputPath, outputPath],
|
|
917
917
|
{ encoding: "utf-8", timeout: 12e4, stdio: ["pipe", "pipe", "pipe"] }
|
|
918
918
|
);
|
|
919
|
-
if (opusResult.status === 0 && (0,
|
|
919
|
+
if (opusResult.status === 0 && (0, import_node_fs25.existsSync)(outputPath)) {
|
|
920
920
|
logger.info(`[whisper-local] opusdec \u8F6C\u6362\u5B8C\u6210: ${outputPath}`);
|
|
921
921
|
return { ok: true };
|
|
922
922
|
}
|
|
@@ -930,7 +930,7 @@ function convertToWav(inputPath, outputPath, actualFmt, logger) {
|
|
|
930
930
|
if (detectedExt && !inputPath.endsWith(detectedExt)) {
|
|
931
931
|
tmpCopy = inputPath + ".detected" + detectedExt;
|
|
932
932
|
try {
|
|
933
|
-
(0,
|
|
933
|
+
(0, import_node_fs25.copyFileSync)(inputPath, tmpCopy);
|
|
934
934
|
actualInputPath = tmpCopy;
|
|
935
935
|
logger.info(
|
|
936
936
|
`[whisper-local] \u68C0\u6D4B\u5230\u5B9E\u9645\u683C\u5F0F ${detectedExt}\uFF0C\u4E34\u65F6\u91CD\u547D\u540D`
|
|
@@ -954,22 +954,22 @@ function convertToWav(inputPath, outputPath, actualFmt, logger) {
|
|
|
954
954
|
timeout: 12e4,
|
|
955
955
|
stdio: ["pipe", "pipe", "pipe"]
|
|
956
956
|
});
|
|
957
|
-
if (tmpCopy && (0,
|
|
957
|
+
if (tmpCopy && (0, import_node_fs25.existsSync)(tmpCopy)) {
|
|
958
958
|
try {
|
|
959
|
-
(0,
|
|
959
|
+
(0, import_node_fs25.unlinkSync)(tmpCopy);
|
|
960
960
|
} catch {
|
|
961
961
|
}
|
|
962
962
|
}
|
|
963
|
-
if (afResult.status === 0 && (0,
|
|
963
|
+
if (afResult.status === 0 && (0, import_node_fs25.existsSync)(outputPath)) {
|
|
964
964
|
logger.info(`[whisper-local] afconvert \u8F6C\u6362\u5B8C\u6210: ${outputPath}`);
|
|
965
965
|
return { ok: true };
|
|
966
966
|
}
|
|
967
967
|
const stderr = afResult.stderr?.slice(0, 200) ?? "";
|
|
968
968
|
return { ok: false, error: `afconvert \u8F6C\u6362\u5931\u8D25 (exit ${afResult.status}): ${stderr}` };
|
|
969
969
|
} catch (err2) {
|
|
970
|
-
if (tmpCopy && (0,
|
|
970
|
+
if (tmpCopy && (0, import_node_fs25.existsSync)(tmpCopy)) {
|
|
971
971
|
try {
|
|
972
|
-
(0,
|
|
972
|
+
(0, import_node_fs25.unlinkSync)(tmpCopy);
|
|
973
973
|
} catch {
|
|
974
974
|
}
|
|
975
975
|
}
|
|
@@ -980,9 +980,9 @@ function convertToWav(inputPath, outputPath, actualFmt, logger) {
|
|
|
980
980
|
return { ok: false, error: `\u65E0\u6CD5\u5C06\u97F3\u9891\u8F6C\u6362\u4E3A WAV \u683C\u5F0F\u3002${fmtHint}` };
|
|
981
981
|
}
|
|
982
982
|
function cleanupTmpWav(path2) {
|
|
983
|
-
if (path2 && (0,
|
|
983
|
+
if (path2 && (0, import_node_fs25.existsSync)(path2)) {
|
|
984
984
|
try {
|
|
985
|
-
(0,
|
|
985
|
+
(0, import_node_fs25.unlinkSync)(path2);
|
|
986
986
|
} catch {
|
|
987
987
|
}
|
|
988
988
|
}
|
|
@@ -1068,13 +1068,13 @@ function formatBytes2(bytes) {
|
|
|
1068
1068
|
if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
1069
1069
|
return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)}GB`;
|
|
1070
1070
|
}
|
|
1071
|
-
var import_node_child_process2,
|
|
1071
|
+
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
1072
|
var init_whisper_local = __esm({
|
|
1073
1073
|
"src/recording/whisper-local.ts"() {
|
|
1074
1074
|
"use strict";
|
|
1075
1075
|
import_node_child_process2 = require("child_process");
|
|
1076
|
-
|
|
1077
|
-
|
|
1076
|
+
import_node_fs25 = require("fs");
|
|
1077
|
+
import_node_path21 = require("path");
|
|
1078
1078
|
import_promises3 = require("stream/promises");
|
|
1079
1079
|
import_node_stream2 = require("stream");
|
|
1080
1080
|
import_node_os4 = require("os");
|
|
@@ -1229,7 +1229,7 @@ async function initializeAsr(config, dataDir, logger) {
|
|
|
1229
1229
|
}
|
|
1230
1230
|
}
|
|
1231
1231
|
async function transcribeAudio(audioFilePath, config, logger, options = {}) {
|
|
1232
|
-
if (!(0,
|
|
1232
|
+
if (!(0, import_node_fs26.existsSync)(audioFilePath)) {
|
|
1233
1233
|
return { ok: false, error: `\u97F3\u9891\u6587\u4EF6\u4E0D\u5B58\u5728: ${audioFilePath}` };
|
|
1234
1234
|
}
|
|
1235
1235
|
logger.info(
|
|
@@ -1240,6 +1240,7 @@ async function transcribeAudio(audioFilePath, config, logger, options = {}) {
|
|
|
1240
1240
|
case "api":
|
|
1241
1241
|
return await transcribeWithModelProxy(
|
|
1242
1242
|
options.audioOssUrl,
|
|
1243
|
+
options.audioDurationMs,
|
|
1243
1244
|
config.api,
|
|
1244
1245
|
logger
|
|
1245
1246
|
);
|
|
@@ -1339,7 +1340,8 @@ async function runTranscriptionWorkflow(params) {
|
|
|
1339
1340
|
logger
|
|
1340
1341
|
} = params;
|
|
1341
1342
|
const result = await transcribeAudio(audioFilePath, config, logger, {
|
|
1342
|
-
audioOssUrl
|
|
1343
|
+
audioOssUrl,
|
|
1344
|
+
audioDurationMs: Math.max(0, Math.round(durationSec * 1e3))
|
|
1343
1345
|
});
|
|
1344
1346
|
if (!result.ok) {
|
|
1345
1347
|
return { ok: false, error: result.error };
|
|
@@ -1373,8 +1375,8 @@ async function runTranscriptionWorkflow(params) {
|
|
|
1373
1375
|
createdAt
|
|
1374
1376
|
);
|
|
1375
1377
|
const transcriptDataFilename = buildTranscriptDataFilename(recordingId);
|
|
1376
|
-
const transcriptDataPath = (0,
|
|
1377
|
-
(0,
|
|
1378
|
+
const transcriptDataPath = (0, import_node_path22.join)(transcriptDataDir, transcriptDataFilename);
|
|
1379
|
+
(0, import_node_fs26.writeFileSync)(
|
|
1378
1380
|
transcriptDataPath,
|
|
1379
1381
|
JSON.stringify(transcriptData, null, 2),
|
|
1380
1382
|
"utf-8"
|
|
@@ -1382,14 +1384,14 @@ async function runTranscriptionWorkflow(params) {
|
|
|
1382
1384
|
logger.info(`[asr] \u8F6C\u5199 JSON \u5DF2\u5199\u5165: ${transcriptDataPath}`);
|
|
1383
1385
|
const safeSummary = title.replace(/[/\\:*?"<>|]/g, "").trim().slice(0, 20);
|
|
1384
1386
|
const filename = safeSummary ? `${recordingId}_${safeSummary}.md` : `${recordingId}.md`;
|
|
1385
|
-
const filePath = (0,
|
|
1386
|
-
(0,
|
|
1387
|
+
const filePath = (0, import_node_path22.join)(transcriptsDir, filename);
|
|
1388
|
+
(0, import_node_fs26.writeFileSync)(filePath, markdown, "utf-8");
|
|
1387
1389
|
logger.info(`[asr] \u8F6C\u5199\u6587\u672C\u5DF2\u5199\u5165: ${filePath}`);
|
|
1388
1390
|
let summaryFilename;
|
|
1389
1391
|
if (summary) {
|
|
1390
1392
|
summaryFilename = `${recordingId}.md`;
|
|
1391
|
-
const summaryFilePath = (0,
|
|
1392
|
-
(0,
|
|
1393
|
+
const summaryFilePath = (0, import_node_path22.join)(summariesDir, summaryFilename);
|
|
1394
|
+
(0, import_node_fs26.writeFileSync)(summaryFilePath, summary, "utf-8");
|
|
1393
1395
|
logger.info(`[asr] \u6458\u8981\u6587\u672C\u5DF2\u5199\u5165: ${summaryFilePath}`);
|
|
1394
1396
|
}
|
|
1395
1397
|
return {
|
|
@@ -1402,7 +1404,7 @@ async function runTranscriptionWorkflow(params) {
|
|
|
1402
1404
|
title
|
|
1403
1405
|
};
|
|
1404
1406
|
}
|
|
1405
|
-
async function transcribeWithModelProxy(audioOssUrl, apiConfig, logger) {
|
|
1407
|
+
async function transcribeWithModelProxy(audioOssUrl, audioDurationMs, apiConfig, logger) {
|
|
1406
1408
|
const normalizedAudioOssUrl = normalizeOptionalText2(audioOssUrl);
|
|
1407
1409
|
if (!normalizedAudioOssUrl) {
|
|
1408
1410
|
return { ok: false, error: "API \u6A21\u5F0F\u7F3A\u5C11 audioOssUrl\uFF0C\u65E0\u6CD5\u8C03\u7528 model-proxy" };
|
|
@@ -1468,13 +1470,14 @@ async function transcribeWithModelProxy(audioOssUrl, apiConfig, logger) {
|
|
|
1468
1470
|
apiKey,
|
|
1469
1471
|
taskId,
|
|
1470
1472
|
initialRequestId: requestId,
|
|
1473
|
+
audioDurationMs,
|
|
1471
1474
|
apiConfig,
|
|
1472
1475
|
logger
|
|
1473
1476
|
});
|
|
1474
1477
|
}
|
|
1475
1478
|
async function transcribeWithWhisperLocal2(audioFilePath, config, logger) {
|
|
1476
1479
|
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,
|
|
1480
|
+
const dataDir = process.env.OPENCLAW_STATE_DIR ?? process.env.QCLAW_STATE_DIR ?? (0, import_node_path22.join)(audioFilePath, "..", "..", "..");
|
|
1478
1481
|
const localConfig = config.local ?? {};
|
|
1479
1482
|
const result = await runLocal(
|
|
1480
1483
|
audioFilePath,
|
|
@@ -1530,6 +1533,7 @@ async function pollLongRecordingTaskResult(params) {
|
|
|
1530
1533
|
apiKey,
|
|
1531
1534
|
taskId,
|
|
1532
1535
|
initialRequestId,
|
|
1536
|
+
audioDurationMs,
|
|
1533
1537
|
apiConfig,
|
|
1534
1538
|
logger
|
|
1535
1539
|
} = params;
|
|
@@ -1577,7 +1581,13 @@ async function pollLongRecordingTaskResult(params) {
|
|
|
1577
1581
|
lastStatus = status;
|
|
1578
1582
|
}
|
|
1579
1583
|
if (status === "SUCCEEDED") {
|
|
1580
|
-
return buildLongRecordingSuccessResult(
|
|
1584
|
+
return buildLongRecordingSuccessResult(
|
|
1585
|
+
taskId,
|
|
1586
|
+
requestId,
|
|
1587
|
+
data,
|
|
1588
|
+
audioDurationMs,
|
|
1589
|
+
logger
|
|
1590
|
+
);
|
|
1581
1591
|
}
|
|
1582
1592
|
if (LONG_RECORDING_TERMINAL_FAILURE_STATUSES.has(status)) {
|
|
1583
1593
|
return {
|
|
@@ -1600,11 +1610,11 @@ async function pollLongRecordingTaskResult(params) {
|
|
|
1600
1610
|
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
1611
|
};
|
|
1602
1612
|
}
|
|
1603
|
-
function buildLongRecordingSuccessResult(taskId, requestId, data, logger) {
|
|
1613
|
+
function buildLongRecordingSuccessResult(taskId, requestId, data, audioDurationMs, logger) {
|
|
1604
1614
|
const sourceTextList = normalizeLongRecordingSourceTextList(
|
|
1605
1615
|
data?.recordResult?.sourceTextList
|
|
1606
1616
|
);
|
|
1607
|
-
const listResult = extractLongRecordingTextFromList(sourceTextList);
|
|
1617
|
+
const listResult = extractLongRecordingTextFromList(sourceTextList, audioDurationMs);
|
|
1608
1618
|
const sourceText = normalizeOptionalText2(data?.recordResult?.sourceText);
|
|
1609
1619
|
const summaryText = normalizeOptionalText2(data?.recordResult?.summaryResult) ?? "";
|
|
1610
1620
|
const title = normalizeOptionalText2(data?.recordResult?.title);
|
|
@@ -1701,11 +1711,12 @@ function normalizeLongRecordingSourceTextList(value) {
|
|
|
1701
1711
|
return [{
|
|
1702
1712
|
content,
|
|
1703
1713
|
speakerId: normalizeOptionalInteger2(record.speakerId),
|
|
1704
|
-
startTime: normalizeOptionalNonNegativeNumber(record.startTime)
|
|
1714
|
+
startTime: normalizeOptionalNonNegativeNumber(record.startTime),
|
|
1715
|
+
endTime: normalizeOptionalNonNegativeNumber(record.endTime)
|
|
1705
1716
|
}];
|
|
1706
1717
|
});
|
|
1707
1718
|
}
|
|
1708
|
-
function extractLongRecordingTextFromList(items) {
|
|
1719
|
+
function extractLongRecordingTextFromList(items, finalFallbackEndMs) {
|
|
1709
1720
|
if (items.length === 0) {
|
|
1710
1721
|
return {
|
|
1711
1722
|
segments: []
|
|
@@ -1713,10 +1724,13 @@ function extractLongRecordingTextFromList(items) {
|
|
|
1713
1724
|
}
|
|
1714
1725
|
const segments = items.map((item, index) => {
|
|
1715
1726
|
const startMs = item.startTime ?? 0;
|
|
1727
|
+
const explicitEndMs = item.endTime;
|
|
1716
1728
|
const nextStart = items[index + 1]?.startTime;
|
|
1729
|
+
const fallbackEndMs = index === items.length - 1 ? normalizeOptionalNonNegativeNumber(finalFallbackEndMs) : void 0;
|
|
1730
|
+
const endMs = explicitEndMs ?? nextStart ?? fallbackEndMs ?? startMs;
|
|
1717
1731
|
return {
|
|
1718
1732
|
start_ms: startMs,
|
|
1719
|
-
end_ms:
|
|
1733
|
+
end_ms: Math.max(startMs, endMs),
|
|
1720
1734
|
text: item.content,
|
|
1721
1735
|
speaker_id: item.speakerId
|
|
1722
1736
|
};
|
|
@@ -1772,12 +1786,12 @@ function formatTranscriptSegmentText(segment) {
|
|
|
1772
1786
|
}
|
|
1773
1787
|
return text;
|
|
1774
1788
|
}
|
|
1775
|
-
var
|
|
1789
|
+
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
1790
|
var init_asr = __esm({
|
|
1777
1791
|
"src/recording/asr.ts"() {
|
|
1778
1792
|
"use strict";
|
|
1779
|
-
|
|
1780
|
-
|
|
1793
|
+
import_node_fs26 = require("fs");
|
|
1794
|
+
import_node_path22 = require("path");
|
|
1781
1795
|
init_credentials();
|
|
1782
1796
|
init_env();
|
|
1783
1797
|
init_transcript_document();
|
|
@@ -5422,7 +5436,7 @@ function readBuildInjectedVersion() {
|
|
|
5422
5436
|
if (false) {
|
|
5423
5437
|
return void 0;
|
|
5424
5438
|
}
|
|
5425
|
-
const version = "1.11.
|
|
5439
|
+
const version = "1.11.2-beta.0".trim();
|
|
5426
5440
|
return version || void 0;
|
|
5427
5441
|
}
|
|
5428
5442
|
function readPluginVersionFromPackageJson() {
|
|
@@ -6035,20 +6049,17 @@ function readOptionalString(value) {
|
|
|
6035
6049
|
const trimmed = value.trim();
|
|
6036
6050
|
return trimmed || void 0;
|
|
6037
6051
|
}
|
|
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
6052
|
function readMeta(taskDir) {
|
|
6042
6053
|
const metaPath = (0, import_node_path3.join)(taskDir, "meta.json");
|
|
6043
6054
|
if (!(0, import_node_fs4.existsSync)(metaPath)) return null;
|
|
6044
6055
|
try {
|
|
6045
6056
|
const raw = JSON.parse((0, import_node_fs4.readFileSync)(metaPath, "utf-8"));
|
|
6046
6057
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
|
|
6047
|
-
if (raw.type !== "light-rule"
|
|
6058
|
+
if (raw.type !== "light-rule") return null;
|
|
6048
6059
|
if (!Array.isArray(raw.segments)) return null;
|
|
6049
6060
|
const name = readOptionalString(raw.name) ?? (0, import_node_path3.basename)(taskDir);
|
|
6050
6061
|
const title = readOptionalString(raw.title) ?? name;
|
|
6051
|
-
const description = readOptionalString(raw.description) ??
|
|
6062
|
+
const description = readOptionalString(raw.description) ?? name;
|
|
6052
6063
|
const createdAt = readOptionalString(raw.createdAt) ?? (0, import_node_fs4.statSync)(metaPath).birthtime.toISOString();
|
|
6053
6064
|
const enabled = typeof raw.enabled === "boolean" ? raw.enabled : true;
|
|
6054
6065
|
const repeatTimes = normalizeRepeatTimes({
|
|
@@ -7075,115 +7086,6 @@ var InlineLightRuleEvaluator = class {
|
|
|
7075
7086
|
}
|
|
7076
7087
|
};
|
|
7077
7088
|
|
|
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
7089
|
// src/light-rules/pi-invoker.ts
|
|
7188
7090
|
var import_agent_runtime = require("openclaw/plugin-sdk/agent-runtime");
|
|
7189
7091
|
var DEFAULT_PROVIDER = "anthropic";
|
|
@@ -7365,7 +7267,7 @@ function resolveUpdateChannel(params) {
|
|
|
7365
7267
|
}
|
|
7366
7268
|
|
|
7367
7269
|
// src/update/index.ts
|
|
7368
|
-
var
|
|
7270
|
+
var import_node_path8 = require("path");
|
|
7369
7271
|
|
|
7370
7272
|
// src/update/checker.ts
|
|
7371
7273
|
function parseSemver(v) {
|
|
@@ -7467,8 +7369,8 @@ var UpdateChecker = class {
|
|
|
7467
7369
|
};
|
|
7468
7370
|
|
|
7469
7371
|
// src/update/executor.ts
|
|
7470
|
-
var
|
|
7471
|
-
var
|
|
7372
|
+
var import_node_fs8 = require("fs");
|
|
7373
|
+
var import_node_path7 = require("path");
|
|
7472
7374
|
var import_node_os = require("os");
|
|
7473
7375
|
var VERSION_PATTERN = /^\d+\.\d+\.\d+(-[\w.]+)?$/;
|
|
7474
7376
|
var BASE_URL = "https://artifact.yoooclaw.com/plugin";
|
|
@@ -7478,9 +7380,9 @@ async function executeUpdate(version, runCommand, logger, targetDir, updateConfi
|
|
|
7478
7380
|
}
|
|
7479
7381
|
const tgzUrl = `${BASE_URL}/v${version}/yoooclaw-phone-notifications-${version}.tgz`;
|
|
7480
7382
|
logger.info(`\u6267\u884C\u66F4\u65B0: ${tgzUrl} \u2192 ${targetDir}`);
|
|
7481
|
-
const workDir = (0,
|
|
7482
|
-
const tgzPath = (0,
|
|
7483
|
-
const stagingDir = (0,
|
|
7383
|
+
const workDir = (0, import_node_fs8.mkdtempSync)((0, import_node_path7.join)((0, import_node_os.tmpdir)(), ".openclaw-plugin-update-"));
|
|
7384
|
+
const tgzPath = (0, import_node_path7.join)(workDir, "plugin.tgz");
|
|
7385
|
+
const stagingDir = (0, import_node_path7.join)(workDir, "staged");
|
|
7484
7386
|
let backupDir = null;
|
|
7485
7387
|
try {
|
|
7486
7388
|
logger.info("\u4E0B\u8F7D\u63D2\u4EF6\u5305...");
|
|
@@ -7489,9 +7391,9 @@ async function executeUpdate(version, runCommand, logger, targetDir, updateConfi
|
|
|
7489
7391
|
return { success: false, message: `\u4E0B\u8F7D\u5931\u8D25 (HTTP ${response.status}): ${tgzUrl}` };
|
|
7490
7392
|
}
|
|
7491
7393
|
const buffer = Buffer.from(await response.arrayBuffer());
|
|
7492
|
-
(0,
|
|
7394
|
+
(0, import_node_fs8.writeFileSync)(tgzPath, buffer);
|
|
7493
7395
|
logger.info(`\u4E0B\u8F7D\u5B8C\u6210 (${buffer.length} bytes)`);
|
|
7494
|
-
(0,
|
|
7396
|
+
(0, import_node_fs8.mkdirSync)(stagingDir, { recursive: true });
|
|
7495
7397
|
const tarResult = await runCommand(
|
|
7496
7398
|
["tar", "-xzf", tgzPath, "-C", stagingDir, "--strip-components=1"],
|
|
7497
7399
|
{ timeoutMs: 3e4 }
|
|
@@ -7500,14 +7402,14 @@ async function executeUpdate(version, runCommand, logger, targetDir, updateConfi
|
|
|
7500
7402
|
const err2 = tarResult.stderr || tarResult.stdout || "unknown error";
|
|
7501
7403
|
return { success: false, message: `\u89E3\u538B\u5931\u8D25: ${err2}` };
|
|
7502
7404
|
}
|
|
7503
|
-
(0,
|
|
7405
|
+
(0, import_node_fs8.mkdirSync)((0, import_node_path7.dirname)(targetDir), { recursive: true });
|
|
7504
7406
|
try {
|
|
7505
7407
|
backupDir = `${targetDir}.bak.${Date.now()}`;
|
|
7506
|
-
(0,
|
|
7408
|
+
(0, import_node_fs8.renameSync)(targetDir, backupDir);
|
|
7507
7409
|
} catch {
|
|
7508
7410
|
backupDir = null;
|
|
7509
7411
|
}
|
|
7510
|
-
(0,
|
|
7412
|
+
(0, import_node_fs8.renameSync)(stagingDir, targetDir);
|
|
7511
7413
|
try {
|
|
7512
7414
|
await updateConfigRecord2(version, tgzUrl);
|
|
7513
7415
|
} catch (err2) {
|
|
@@ -7515,18 +7417,18 @@ async function executeUpdate(version, runCommand, logger, targetDir, updateConfi
|
|
|
7515
7417
|
}
|
|
7516
7418
|
if (backupDir) {
|
|
7517
7419
|
try {
|
|
7518
|
-
(0,
|
|
7420
|
+
(0, import_node_fs8.rmSync)(backupDir, { force: true, recursive: true });
|
|
7519
7421
|
} catch {
|
|
7520
7422
|
}
|
|
7521
7423
|
}
|
|
7522
|
-
const msg = `\u5DF2\u66F4\u65B0\u5230 ${version}
|
|
7424
|
+
const msg = `\u5DF2\u66F4\u65B0\u5230 ${version}`;
|
|
7523
7425
|
logger.info(msg);
|
|
7524
|
-
return { success: true, message: msg };
|
|
7426
|
+
return { success: true, message: msg, version };
|
|
7525
7427
|
} catch (err2) {
|
|
7526
7428
|
if (backupDir) {
|
|
7527
7429
|
try {
|
|
7528
|
-
(0,
|
|
7529
|
-
(0,
|
|
7430
|
+
(0, import_node_fs8.rmSync)(targetDir, { force: true, recursive: true });
|
|
7431
|
+
(0, import_node_fs8.renameSync)(backupDir, targetDir);
|
|
7530
7432
|
logger.info("\u5DF2\u56DE\u6EDA\u5230\u4E4B\u524D\u7248\u672C");
|
|
7531
7433
|
} catch (rollbackErr) {
|
|
7532
7434
|
logger.error(`\u56DE\u6EDA\u5931\u8D25: ${String(rollbackErr)}`);
|
|
@@ -7537,12 +7439,47 @@ async function executeUpdate(version, runCommand, logger, targetDir, updateConfi
|
|
|
7537
7439
|
return { success: false, message: errMsg };
|
|
7538
7440
|
} finally {
|
|
7539
7441
|
try {
|
|
7540
|
-
(0,
|
|
7442
|
+
(0, import_node_fs8.rmSync)(workDir, { force: true, recursive: true });
|
|
7541
7443
|
} catch {
|
|
7542
7444
|
}
|
|
7543
7445
|
}
|
|
7544
7446
|
}
|
|
7545
7447
|
|
|
7448
|
+
// src/update/restart.ts
|
|
7449
|
+
function scheduleGatewayRestart(logger, deps = {}) {
|
|
7450
|
+
try {
|
|
7451
|
+
const cfg = deps.loadConfig?.();
|
|
7452
|
+
if (cfg?.commands?.restart === false) {
|
|
7453
|
+
logger.warn("\u66F4\u65B0\u540E\u8DF3\u8FC7 gateway \u91CD\u542F: commands.restart=false");
|
|
7454
|
+
return { scheduled: false };
|
|
7455
|
+
}
|
|
7456
|
+
} catch (err2) {
|
|
7457
|
+
logger.warn(`\u66F4\u65B0\u540E\u68C0\u67E5 gateway \u91CD\u542F\u914D\u7F6E\u5931\u8D25: ${String(err2)}`);
|
|
7458
|
+
}
|
|
7459
|
+
const getListenerCount = deps.getListenerCount ?? ((signal) => process.listenerCount(signal));
|
|
7460
|
+
if (getListenerCount("SIGUSR1") < 1) {
|
|
7461
|
+
logger.warn("\u66F4\u65B0\u540E\u8DF3\u8FC7 gateway \u91CD\u542F: \u5F53\u524D\u8FDB\u7A0B\u672A\u6CE8\u518C SIGUSR1 \u76D1\u542C\u5668");
|
|
7462
|
+
return { scheduled: false };
|
|
7463
|
+
}
|
|
7464
|
+
const emitSignal = deps.emitSignal ?? ((signal) => process.emit(signal));
|
|
7465
|
+
const schedule = deps.schedule ?? ((task) => {
|
|
7466
|
+
setTimeout(task, 0);
|
|
7467
|
+
});
|
|
7468
|
+
schedule(() => {
|
|
7469
|
+
try {
|
|
7470
|
+
const accepted = emitSignal("SIGUSR1");
|
|
7471
|
+
if (accepted) {
|
|
7472
|
+
logger.info("\u66F4\u65B0\u5B8C\u6210\uFF0C\u5DF2\u89E6\u53D1 gateway SIGUSR1 \u91CD\u542F");
|
|
7473
|
+
} else {
|
|
7474
|
+
logger.warn("\u66F4\u65B0\u5B8C\u6210\uFF0C\u4F46 gateway SIGUSR1 \u4FE1\u53F7\u672A\u88AB\u5904\u7406");
|
|
7475
|
+
}
|
|
7476
|
+
} catch (err2) {
|
|
7477
|
+
logger.warn(`\u66F4\u65B0\u540E\u89E6\u53D1 gateway \u91CD\u542F\u5931\u8D25: ${String(err2)}`);
|
|
7478
|
+
}
|
|
7479
|
+
});
|
|
7480
|
+
return { scheduled: true };
|
|
7481
|
+
}
|
|
7482
|
+
|
|
7546
7483
|
// src/update/index.ts
|
|
7547
7484
|
var PLUGIN_ID = "phone-notifications";
|
|
7548
7485
|
function resolveTargetDir(api) {
|
|
@@ -7552,7 +7489,7 @@ function resolveTargetDir(api) {
|
|
|
7552
7489
|
if (installPath) return installPath;
|
|
7553
7490
|
} catch {
|
|
7554
7491
|
}
|
|
7555
|
-
return (0,
|
|
7492
|
+
return (0, import_node_path8.join)(api.runtime.state.resolveStateDir(), "extensions", PLUGIN_ID);
|
|
7556
7493
|
}
|
|
7557
7494
|
async function updateConfigRecord(api, version, targetDir, tgzUrl) {
|
|
7558
7495
|
const configApi = api.runtime.config;
|
|
@@ -7570,6 +7507,23 @@ async function updateConfigRecord(api, version, targetDir, tgzUrl) {
|
|
|
7570
7507
|
};
|
|
7571
7508
|
await configApi.writeConfigFile(cfg);
|
|
7572
7509
|
}
|
|
7510
|
+
function finalizeUpdateResult(api, logger, result) {
|
|
7511
|
+
if (!result.success) {
|
|
7512
|
+
return result;
|
|
7513
|
+
}
|
|
7514
|
+
const restart = scheduleGatewayRestart(logger, {
|
|
7515
|
+
loadConfig: () => {
|
|
7516
|
+
const configApi = api.runtime.config;
|
|
7517
|
+
return configApi?.loadConfig?.();
|
|
7518
|
+
}
|
|
7519
|
+
});
|
|
7520
|
+
const version = result.version ?? "\u76EE\u6807\u7248\u672C";
|
|
7521
|
+
return {
|
|
7522
|
+
...result,
|
|
7523
|
+
restartScheduled: restart.scheduled,
|
|
7524
|
+
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`
|
|
7525
|
+
};
|
|
7526
|
+
}
|
|
7573
7527
|
function registerAutoUpdate(api, logger, config, getBroadcast, rememberBroadcast, externalUpdateNotifier) {
|
|
7574
7528
|
if (config.enabled === false) {
|
|
7575
7529
|
logger.info("\u81EA\u52A8\u66F4\u65B0\u5DF2\u7981\u7528 (autoUpdate.enabled = false)");
|
|
@@ -7601,7 +7555,7 @@ function registerAutoUpdate(api, logger, config, getBroadcast, rememberBroadcast
|
|
|
7601
7555
|
api.registerTool({
|
|
7602
7556
|
name: "plugin-update",
|
|
7603
7557
|
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\
|
|
7558
|
+
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
7559
|
parameters: {
|
|
7606
7560
|
type: "object",
|
|
7607
7561
|
required: ["version"],
|
|
@@ -7623,13 +7577,14 @@ function registerAutoUpdate(api, logger, config, getBroadcast, rememberBroadcast
|
|
|
7623
7577
|
targetDir,
|
|
7624
7578
|
(v, url) => updateConfigRecord(api, v, targetDir, url)
|
|
7625
7579
|
);
|
|
7626
|
-
|
|
7580
|
+
const finalResult = finalizeUpdateResult(api, logger, result);
|
|
7581
|
+
if (finalResult.success) {
|
|
7627
7582
|
pendingUpdate = null;
|
|
7628
7583
|
externalUpdateNotifier?.clearPendingUpdate();
|
|
7629
7584
|
}
|
|
7630
7585
|
return {
|
|
7631
|
-
content: [{ type: "text", text:
|
|
7632
|
-
details:
|
|
7586
|
+
content: [{ type: "text", text: finalResult.message }],
|
|
7587
|
+
details: finalResult
|
|
7633
7588
|
};
|
|
7634
7589
|
}
|
|
7635
7590
|
});
|
|
@@ -7651,16 +7606,20 @@ function registerAutoUpdate(api, logger, config, getBroadcast, rememberBroadcast
|
|
|
7651
7606
|
targetDir,
|
|
7652
7607
|
(v, url) => updateConfigRecord(api, v, targetDir, url)
|
|
7653
7608
|
);
|
|
7654
|
-
|
|
7609
|
+
const finalResult = finalizeUpdateResult(api, logger, result);
|
|
7610
|
+
if (finalResult.success) {
|
|
7655
7611
|
pendingUpdate = null;
|
|
7656
7612
|
externalUpdateNotifier?.clearPendingUpdate();
|
|
7657
7613
|
}
|
|
7658
|
-
if (
|
|
7659
|
-
respond(true, {
|
|
7614
|
+
if (finalResult.success) {
|
|
7615
|
+
respond(true, {
|
|
7616
|
+
message: finalResult.message,
|
|
7617
|
+
restartScheduled: finalResult.restartScheduled === true
|
|
7618
|
+
});
|
|
7660
7619
|
} else {
|
|
7661
7620
|
respond(false, void 0, {
|
|
7662
7621
|
code: "UPDATE_FAILED",
|
|
7663
|
-
message:
|
|
7622
|
+
message: finalResult.message
|
|
7664
7623
|
});
|
|
7665
7624
|
}
|
|
7666
7625
|
});
|
|
@@ -7740,10 +7699,10 @@ function registerAutoUpdateLifecycle(deps) {
|
|
|
7740
7699
|
}
|
|
7741
7700
|
|
|
7742
7701
|
// src/plugin/cli.ts
|
|
7743
|
-
var
|
|
7702
|
+
var import_node_path16 = require("path");
|
|
7744
7703
|
|
|
7745
7704
|
// src/cli/auth.ts
|
|
7746
|
-
var
|
|
7705
|
+
var import_node_fs9 = require("fs");
|
|
7747
7706
|
init_credentials();
|
|
7748
7707
|
function registerAuthCli(program) {
|
|
7749
7708
|
const auth = program.command("auth").description("\u7528\u6237\u8BA4\u8BC1\u7BA1\u7406");
|
|
@@ -7779,12 +7738,12 @@ function registerAuthCli(program) {
|
|
|
7779
7738
|
});
|
|
7780
7739
|
auth.command("clear").description("\u6E05\u9664\u5DF2\u4FDD\u5B58\u7684\u8BA4\u8BC1\u4FE1\u606F").action(() => {
|
|
7781
7740
|
const path2 = credentialsPath();
|
|
7782
|
-
if ((0,
|
|
7741
|
+
if ((0, import_node_fs9.existsSync)(path2)) {
|
|
7783
7742
|
const creds = readCredentials();
|
|
7784
7743
|
delete creds.apiKey;
|
|
7785
7744
|
delete creds.token;
|
|
7786
7745
|
if (Object.keys(creds).length === 0) {
|
|
7787
|
-
(0,
|
|
7746
|
+
(0, import_node_fs9.rmSync)(path2, { force: true });
|
|
7788
7747
|
} else {
|
|
7789
7748
|
writeCredentials(creds);
|
|
7790
7749
|
}
|
|
@@ -7916,23 +7875,23 @@ function registerNtfStats(ntf, ctx) {
|
|
|
7916
7875
|
}
|
|
7917
7876
|
|
|
7918
7877
|
// src/cli/ntf-sync.ts
|
|
7919
|
-
var
|
|
7920
|
-
var
|
|
7878
|
+
var import_node_fs10 = require("fs");
|
|
7879
|
+
var import_node_path9 = require("path");
|
|
7921
7880
|
var SYNC_FETCH_LIMIT = 300;
|
|
7922
7881
|
function checkpointPath(dir) {
|
|
7923
|
-
return (0,
|
|
7882
|
+
return (0, import_node_path9.join)(dir, ".checkpoint.json");
|
|
7924
7883
|
}
|
|
7925
7884
|
function readCheckpoint(dir) {
|
|
7926
7885
|
const p = checkpointPath(dir);
|
|
7927
|
-
if (!(0,
|
|
7886
|
+
if (!(0, import_node_fs10.existsSync)(p)) return {};
|
|
7928
7887
|
try {
|
|
7929
|
-
return JSON.parse((0,
|
|
7888
|
+
return JSON.parse((0, import_node_fs10.readFileSync)(p, "utf-8"));
|
|
7930
7889
|
} catch {
|
|
7931
7890
|
return {};
|
|
7932
7891
|
}
|
|
7933
7892
|
}
|
|
7934
7893
|
function writeCheckpoint(dir, data) {
|
|
7935
|
-
(0,
|
|
7894
|
+
(0, import_node_fs10.writeFileSync)(checkpointPath(dir), JSON.stringify(data, null, 2), "utf-8");
|
|
7936
7895
|
}
|
|
7937
7896
|
function registerNtfSync(ntf, ctx) {
|
|
7938
7897
|
const sync = ntf.command("sync").description("\u540C\u6B65\u901A\u77E5\u5230\u8BB0\u5FC6\u7CFB\u7EDF");
|
|
@@ -8025,8 +7984,8 @@ function registerNtfSync(ntf, ctx) {
|
|
|
8025
7984
|
}
|
|
8026
7985
|
|
|
8027
7986
|
// src/cli/ntf-monitor.ts
|
|
8028
|
-
var
|
|
8029
|
-
var
|
|
7987
|
+
var import_node_fs11 = require("fs");
|
|
7988
|
+
var import_node_path10 = require("path");
|
|
8030
7989
|
|
|
8031
7990
|
// src/monitor/fetch-gen.ts
|
|
8032
7991
|
function generateFetchPy(name, matchRules) {
|
|
@@ -8111,19 +8070,19 @@ function pyLiteral(value) {
|
|
|
8111
8070
|
function tasksDir2(ctx) {
|
|
8112
8071
|
const base = ctx.workspaceDir || ctx.stateDir;
|
|
8113
8072
|
if (!base) throw new Error("workspaceDir and stateDir both unavailable");
|
|
8114
|
-
return (0,
|
|
8073
|
+
return (0, import_node_path10.join)(base, "tasks");
|
|
8115
8074
|
}
|
|
8116
8075
|
function readMeta2(taskDir) {
|
|
8117
|
-
const metaPath = (0,
|
|
8118
|
-
if (!(0,
|
|
8076
|
+
const metaPath = (0, import_node_path10.join)(taskDir, "meta.json");
|
|
8077
|
+
if (!(0, import_node_fs11.existsSync)(metaPath)) return null;
|
|
8119
8078
|
try {
|
|
8120
|
-
return JSON.parse((0,
|
|
8079
|
+
return JSON.parse((0, import_node_fs11.readFileSync)(metaPath, "utf-8"));
|
|
8121
8080
|
} catch {
|
|
8122
8081
|
return null;
|
|
8123
8082
|
}
|
|
8124
8083
|
}
|
|
8125
8084
|
function writeMeta2(taskDir, meta) {
|
|
8126
|
-
(0,
|
|
8085
|
+
(0, import_node_fs11.writeFileSync)((0, import_node_path10.join)(taskDir, "meta.json"), JSON.stringify(meta, null, 2), "utf-8");
|
|
8127
8086
|
}
|
|
8128
8087
|
function generateReadme(name, description) {
|
|
8129
8088
|
return `# Monitor Task: ${name}
|
|
@@ -8142,27 +8101,27 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
8142
8101
|
const monitor = ntf.command("monitor").description("\u901A\u77E5\u76D1\u63A7\u4EFB\u52A1\u7BA1\u7406");
|
|
8143
8102
|
monitor.command("list").description("\u5217\u51FA\u6240\u6709\u76D1\u63A7\u4EFB\u52A1").action(() => {
|
|
8144
8103
|
const dir = tasksDir2(ctx);
|
|
8145
|
-
if (!(0,
|
|
8104
|
+
if (!(0, import_node_fs11.existsSync)(dir)) {
|
|
8146
8105
|
output({ ok: true, tasks: [] });
|
|
8147
8106
|
return;
|
|
8148
8107
|
}
|
|
8149
8108
|
const tasks = [];
|
|
8150
|
-
for (const entry of (0,
|
|
8109
|
+
for (const entry of (0, import_node_fs11.readdirSync)(dir, { withFileTypes: true })) {
|
|
8151
8110
|
if (!entry.isDirectory()) continue;
|
|
8152
|
-
const meta = readMeta2((0,
|
|
8111
|
+
const meta = readMeta2((0, import_node_path10.join)(dir, entry.name));
|
|
8153
8112
|
if (meta) tasks.push(meta);
|
|
8154
8113
|
}
|
|
8155
8114
|
output({ ok: true, tasks });
|
|
8156
8115
|
});
|
|
8157
8116
|
monitor.command("show <name>").description("\u67E5\u770B\u76D1\u63A7\u4EFB\u52A1\u8BE6\u60C5").action((name) => {
|
|
8158
|
-
const taskDir = (0,
|
|
8117
|
+
const taskDir = (0, import_node_path10.join)(tasksDir2(ctx), name);
|
|
8159
8118
|
const meta = readMeta2(taskDir);
|
|
8160
8119
|
if (!meta) exitError("NOT_FOUND", `\u76D1\u63A7\u4EFB\u52A1 '${name}' \u4E0D\u5B58\u5728`);
|
|
8161
|
-
const checkpointPath2 = (0,
|
|
8120
|
+
const checkpointPath2 = (0, import_node_path10.join)(taskDir, "checkpoint.json");
|
|
8162
8121
|
let checkpoint = {};
|
|
8163
|
-
if ((0,
|
|
8122
|
+
if ((0, import_node_fs11.existsSync)(checkpointPath2)) {
|
|
8164
8123
|
try {
|
|
8165
|
-
checkpoint = JSON.parse((0,
|
|
8124
|
+
checkpoint = JSON.parse((0, import_node_fs11.readFileSync)(checkpointPath2, "utf-8"));
|
|
8166
8125
|
} catch {
|
|
8167
8126
|
}
|
|
8168
8127
|
}
|
|
@@ -8177,8 +8136,8 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
8177
8136
|
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
8137
|
(name, opts) => {
|
|
8179
8138
|
const dir = tasksDir2(ctx);
|
|
8180
|
-
const taskDir = (0,
|
|
8181
|
-
if ((0,
|
|
8139
|
+
const taskDir = (0, import_node_path10.join)(dir, name);
|
|
8140
|
+
if ((0, import_node_fs11.existsSync)(taskDir)) {
|
|
8182
8141
|
exitError("ALREADY_EXISTS", `\u76D1\u63A7\u4EFB\u52A1 '${name}' \u5DF2\u5B58\u5728`);
|
|
8183
8142
|
}
|
|
8184
8143
|
let matchRules;
|
|
@@ -8190,7 +8149,7 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
8190
8149
|
"match-rules \u5FC5\u987B\u662F\u5408\u6CD5\u7684 JSON"
|
|
8191
8150
|
);
|
|
8192
8151
|
}
|
|
8193
|
-
(0,
|
|
8152
|
+
(0, import_node_fs11.mkdirSync)(taskDir, { recursive: true });
|
|
8194
8153
|
const meta = {
|
|
8195
8154
|
name,
|
|
8196
8155
|
description: opts.description,
|
|
@@ -8200,13 +8159,13 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
8200
8159
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
8201
8160
|
};
|
|
8202
8161
|
writeMeta2(taskDir, meta);
|
|
8203
|
-
(0,
|
|
8204
|
-
(0,
|
|
8162
|
+
(0, import_node_fs11.writeFileSync)(
|
|
8163
|
+
(0, import_node_path10.join)(taskDir, "fetch.py"),
|
|
8205
8164
|
generateFetchPy(name, matchRules),
|
|
8206
8165
|
"utf-8"
|
|
8207
8166
|
);
|
|
8208
|
-
(0,
|
|
8209
|
-
(0,
|
|
8167
|
+
(0, import_node_fs11.writeFileSync)(
|
|
8168
|
+
(0, import_node_path10.join)(taskDir, "README.md"),
|
|
8210
8169
|
generateReadme(name, opts.description),
|
|
8211
8170
|
"utf-8"
|
|
8212
8171
|
);
|
|
@@ -8234,8 +8193,8 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
8234
8193
|
}
|
|
8235
8194
|
);
|
|
8236
8195
|
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,
|
|
8196
|
+
const taskDir = (0, import_node_path10.join)(tasksDir2(ctx), name);
|
|
8197
|
+
if (!(0, import_node_fs11.existsSync)(taskDir)) {
|
|
8239
8198
|
exitError("NOT_FOUND", `\u76D1\u63A7\u4EFB\u52A1 '${name}' \u4E0D\u5B58\u5728`);
|
|
8240
8199
|
}
|
|
8241
8200
|
if (!opts.yes) {
|
|
@@ -8248,7 +8207,7 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
8248
8207
|
});
|
|
8249
8208
|
process.exit(1);
|
|
8250
8209
|
}
|
|
8251
|
-
(0,
|
|
8210
|
+
(0, import_node_fs11.rmSync)(taskDir, { recursive: true, force: true });
|
|
8252
8211
|
output({
|
|
8253
8212
|
ok: true,
|
|
8254
8213
|
name,
|
|
@@ -8260,7 +8219,7 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
8260
8219
|
});
|
|
8261
8220
|
});
|
|
8262
8221
|
monitor.command("enable <name>").description("\u542F\u7528\u76D1\u63A7\u4EFB\u52A1").action((name) => {
|
|
8263
|
-
const taskDir = (0,
|
|
8222
|
+
const taskDir = (0, import_node_path10.join)(tasksDir2(ctx), name);
|
|
8264
8223
|
const meta = readMeta2(taskDir);
|
|
8265
8224
|
if (!meta) exitError("NOT_FOUND", `\u76D1\u63A7\u4EFB\u52A1 '${name}' \u4E0D\u5B58\u5728`);
|
|
8266
8225
|
meta.enabled = true;
|
|
@@ -8268,7 +8227,7 @@ function registerNtfMonitor(ntf, ctx) {
|
|
|
8268
8227
|
output({ ok: true, name, enabled: true });
|
|
8269
8228
|
});
|
|
8270
8229
|
monitor.command("disable <name>").description("\u6682\u505C\u76D1\u63A7\u4EFB\u52A1").action((name) => {
|
|
8271
|
-
const taskDir = (0,
|
|
8230
|
+
const taskDir = (0, import_node_path10.join)(tasksDir2(ctx), name);
|
|
8272
8231
|
const meta = readMeta2(taskDir);
|
|
8273
8232
|
if (!meta) exitError("NOT_FOUND", `\u76D1\u63A7\u4EFB\u52A1 '${name}' \u4E0D\u5B58\u5728`);
|
|
8274
8233
|
meta.enabled = false;
|
|
@@ -8312,9 +8271,9 @@ function registerLightSend(light) {
|
|
|
8312
8271
|
}
|
|
8313
8272
|
|
|
8314
8273
|
// src/cli/light-setup-tools.ts
|
|
8315
|
-
var
|
|
8274
|
+
var import_node_fs12 = require("fs");
|
|
8316
8275
|
var import_node_os2 = require("os");
|
|
8317
|
-
var
|
|
8276
|
+
var import_node_path11 = require("path");
|
|
8318
8277
|
function isObject(value) {
|
|
8319
8278
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
8320
8279
|
}
|
|
@@ -8328,7 +8287,7 @@ function ensureArray(obj, key) {
|
|
|
8328
8287
|
function resolveConfigPath2() {
|
|
8329
8288
|
const fromEnv = process.env.OPENCLAW_CONFIG_PATH?.trim();
|
|
8330
8289
|
if (fromEnv) return fromEnv;
|
|
8331
|
-
return (0,
|
|
8290
|
+
return (0, import_node_path11.join)((0, import_node_os2.homedir)(), ".openclaw", "openclaw.json");
|
|
8332
8291
|
}
|
|
8333
8292
|
var LIGHT_TOOLS = [
|
|
8334
8293
|
"light_control",
|
|
@@ -8375,12 +8334,12 @@ function upsertLightControlAlsoAllow(cfg) {
|
|
|
8375
8334
|
function registerLightSetupTools(light) {
|
|
8376
8335
|
light.command("setup").description("\u81EA\u52A8\u653E\u884C light_control\uFF08\u5199\u5165 tools.alsoAllow \u4E0E agents.main.tools.alsoAllow\uFF09").action(() => {
|
|
8377
8336
|
const configPath = resolveConfigPath2();
|
|
8378
|
-
if (!(0,
|
|
8337
|
+
if (!(0, import_node_fs12.existsSync)(configPath)) {
|
|
8379
8338
|
exitError("CONFIG_NOT_FOUND", `\u672A\u627E\u5230\u914D\u7F6E\u6587\u4EF6: ${configPath}`);
|
|
8380
8339
|
}
|
|
8381
8340
|
let cfg = {};
|
|
8382
8341
|
try {
|
|
8383
|
-
const raw = (0,
|
|
8342
|
+
const raw = (0, import_node_fs12.readFileSync)(configPath, "utf-8");
|
|
8384
8343
|
const parsed = JSON.parse(raw);
|
|
8385
8344
|
if (isObject(parsed)) cfg = parsed;
|
|
8386
8345
|
} catch (err2) {
|
|
@@ -8388,8 +8347,8 @@ function registerLightSetupTools(light) {
|
|
|
8388
8347
|
}
|
|
8389
8348
|
const result = upsertLightControlAlsoAllow(cfg);
|
|
8390
8349
|
try {
|
|
8391
|
-
(0,
|
|
8392
|
-
(0,
|
|
8350
|
+
(0, import_node_fs12.mkdirSync)((0, import_node_path11.dirname)(configPath), { recursive: true });
|
|
8351
|
+
(0, import_node_fs12.writeFileSync)(configPath, JSON.stringify(cfg, null, 2) + "\n", "utf-8");
|
|
8393
8352
|
} catch (err2) {
|
|
8394
8353
|
exitError("WRITE_FAILED", `\u5199\u5165\u914D\u7F6E\u5931\u8D25: ${err2?.message ?? String(err2)}`);
|
|
8395
8354
|
}
|
|
@@ -8407,17 +8366,17 @@ function registerLightSetupTools(light) {
|
|
|
8407
8366
|
}
|
|
8408
8367
|
|
|
8409
8368
|
// src/cli/tunnel-status.ts
|
|
8410
|
-
var
|
|
8411
|
-
var
|
|
8369
|
+
var import_node_fs13 = require("fs");
|
|
8370
|
+
var import_node_path12 = require("path");
|
|
8412
8371
|
init_credentials();
|
|
8413
8372
|
init_env();
|
|
8414
|
-
var STATUS_REL_PATH = (0,
|
|
8373
|
+
var STATUS_REL_PATH = (0, import_node_path12.join)("plugins", "phone-notifications", "tunnel-status.json");
|
|
8415
8374
|
function readTunnelStatus(ctx) {
|
|
8416
8375
|
if (!ctx.stateDir) return null;
|
|
8417
|
-
const filePath = (0,
|
|
8418
|
-
if (!(0,
|
|
8376
|
+
const filePath = (0, import_node_path12.join)(ctx.stateDir, STATUS_REL_PATH);
|
|
8377
|
+
if (!(0, import_node_fs13.existsSync)(filePath)) return null;
|
|
8419
8378
|
try {
|
|
8420
|
-
return JSON.parse((0,
|
|
8379
|
+
return JSON.parse((0, import_node_fs13.readFileSync)(filePath, "utf-8"));
|
|
8421
8380
|
} catch {
|
|
8422
8381
|
return null;
|
|
8423
8382
|
}
|
|
@@ -8485,24 +8444,24 @@ function registerNtfStoragePath(ntf, ctx) {
|
|
|
8485
8444
|
}
|
|
8486
8445
|
|
|
8487
8446
|
// src/cli/log-search.ts
|
|
8488
|
-
var
|
|
8489
|
-
var
|
|
8447
|
+
var import_node_fs14 = require("fs");
|
|
8448
|
+
var import_node_path13 = require("path");
|
|
8490
8449
|
function resolveLogsDir(ctx) {
|
|
8491
8450
|
if (ctx.stateDir) {
|
|
8492
|
-
const dir = (0,
|
|
8451
|
+
const dir = (0, import_node_path13.join)(
|
|
8493
8452
|
ctx.stateDir,
|
|
8494
8453
|
"plugins",
|
|
8495
8454
|
"phone-notifications",
|
|
8496
8455
|
"logs"
|
|
8497
8456
|
);
|
|
8498
|
-
if ((0,
|
|
8457
|
+
if ((0, import_node_fs14.existsSync)(dir)) return dir;
|
|
8499
8458
|
}
|
|
8500
8459
|
return null;
|
|
8501
8460
|
}
|
|
8502
8461
|
function listLogDateKeys(dir) {
|
|
8503
8462
|
const pattern = /^(\d{4}-\d{2}-\d{2})\.log$/;
|
|
8504
8463
|
const keys = [];
|
|
8505
|
-
for (const entry of (0,
|
|
8464
|
+
for (const entry of (0, import_node_fs14.readdirSync)(dir, { withFileTypes: true })) {
|
|
8506
8465
|
if (!entry.isFile()) continue;
|
|
8507
8466
|
const m = pattern.exec(entry.name);
|
|
8508
8467
|
if (m) keys.push(m[1]);
|
|
@@ -8510,9 +8469,9 @@ function listLogDateKeys(dir) {
|
|
|
8510
8469
|
return keys.sort().reverse();
|
|
8511
8470
|
}
|
|
8512
8471
|
function collectLogLines(dir, dateKey, keyword, limit, collected) {
|
|
8513
|
-
const filePath = (0,
|
|
8514
|
-
if (!(0,
|
|
8515
|
-
const content = (0,
|
|
8472
|
+
const filePath = (0, import_node_path13.join)(dir, `${dateKey}.log`);
|
|
8473
|
+
if (!(0, import_node_fs14.existsSync)(filePath)) return;
|
|
8474
|
+
const content = (0, import_node_fs14.readFileSync)(filePath, "utf-8");
|
|
8516
8475
|
const lowerKeyword = keyword?.toLowerCase();
|
|
8517
8476
|
for (const line of content.split("\n")) {
|
|
8518
8477
|
if (collected.length >= limit) return;
|
|
@@ -8579,12 +8538,12 @@ function registerEnvCli(ntf) {
|
|
|
8579
8538
|
}
|
|
8580
8539
|
|
|
8581
8540
|
// src/cli/doctor.ts
|
|
8582
|
-
var
|
|
8541
|
+
var import_node_fs18 = require("fs");
|
|
8583
8542
|
var import_node_readline = require("readline");
|
|
8584
8543
|
init_host();
|
|
8585
8544
|
|
|
8586
8545
|
// src/cli/doctor/check-dangerous-flags.ts
|
|
8587
|
-
var
|
|
8546
|
+
var import_node_fs15 = require("fs");
|
|
8588
8547
|
function isObject2(v) {
|
|
8589
8548
|
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
8590
8549
|
}
|
|
@@ -8601,13 +8560,13 @@ var checkDangerousFlags = ({ cfg, configPath }) => {
|
|
|
8601
8560
|
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
8561
|
fixDescription: "\u8BBE\u4E3A false",
|
|
8603
8562
|
fix: () => {
|
|
8604
|
-
const raw = (0,
|
|
8563
|
+
const raw = (0, import_node_fs15.readFileSync)(configPath, "utf-8");
|
|
8605
8564
|
const config = JSON.parse(raw);
|
|
8606
8565
|
const gw = config.gateway;
|
|
8607
8566
|
const cui = gw.controlUi;
|
|
8608
8567
|
cui.dangerouslyDisableDeviceAuth = false;
|
|
8609
|
-
(0,
|
|
8610
|
-
(0,
|
|
8568
|
+
(0, import_node_fs15.copyFileSync)(configPath, configPath + ".bak");
|
|
8569
|
+
(0, import_node_fs15.writeFileSync)(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
8611
8570
|
}
|
|
8612
8571
|
};
|
|
8613
8572
|
};
|
|
@@ -8655,11 +8614,11 @@ function warnEmpty() {
|
|
|
8655
8614
|
}
|
|
8656
8615
|
|
|
8657
8616
|
// src/cli/doctor/check-state-dir-perms.ts
|
|
8658
|
-
var
|
|
8617
|
+
var import_node_fs16 = require("fs");
|
|
8659
8618
|
var checkStateDirPerms = ({ stateDir }) => {
|
|
8660
8619
|
let mode;
|
|
8661
8620
|
try {
|
|
8662
|
-
mode = (0,
|
|
8621
|
+
mode = (0, import_node_fs16.statSync)(stateDir).mode;
|
|
8663
8622
|
} catch {
|
|
8664
8623
|
return null;
|
|
8665
8624
|
}
|
|
@@ -8673,7 +8632,7 @@ var checkStateDirPerms = ({ stateDir }) => {
|
|
|
8673
8632
|
detail: "\u5176\u4ED6\u7528\u6237\u53EF\u4EE5\u8BFB\u53D6\u8BE5\u76EE\u5F55\u4E0B\u7684\u51ED\u8BC1\u548C\u914D\u7F6E\u6587\u4EF6\u3002",
|
|
8674
8633
|
fixDescription: "chmod 700 " + stateDir,
|
|
8675
8634
|
fix: () => {
|
|
8676
|
-
(0,
|
|
8635
|
+
(0, import_node_fs16.chmodSync)(stateDir, 448);
|
|
8677
8636
|
}
|
|
8678
8637
|
};
|
|
8679
8638
|
};
|
|
@@ -8728,16 +8687,16 @@ var checkCredentials = () => {
|
|
|
8728
8687
|
};
|
|
8729
8688
|
|
|
8730
8689
|
// src/cli/doctor/check-tunnel.ts
|
|
8731
|
-
var
|
|
8732
|
-
var
|
|
8733
|
-
var STATUS_REL_PATH2 = (0,
|
|
8690
|
+
var import_node_fs17 = require("fs");
|
|
8691
|
+
var import_node_path14 = require("path");
|
|
8692
|
+
var STATUS_REL_PATH2 = (0, import_node_path14.join)(
|
|
8734
8693
|
"plugins",
|
|
8735
8694
|
"phone-notifications",
|
|
8736
8695
|
"tunnel-status.json"
|
|
8737
8696
|
);
|
|
8738
8697
|
var checkTunnel = ({ stateDir }) => {
|
|
8739
|
-
const filePath = (0,
|
|
8740
|
-
if (!(0,
|
|
8698
|
+
const filePath = (0, import_node_path14.join)(stateDir, STATUS_REL_PATH2);
|
|
8699
|
+
if (!(0, import_node_fs17.existsSync)(filePath)) {
|
|
8741
8700
|
return {
|
|
8742
8701
|
id: "tunnel",
|
|
8743
8702
|
severity: "warn",
|
|
@@ -8749,7 +8708,7 @@ var checkTunnel = ({ stateDir }) => {
|
|
|
8749
8708
|
}
|
|
8750
8709
|
let status;
|
|
8751
8710
|
try {
|
|
8752
|
-
status = JSON.parse((0,
|
|
8711
|
+
status = JSON.parse((0, import_node_fs17.readFileSync)(filePath, "utf-8"));
|
|
8753
8712
|
} catch {
|
|
8754
8713
|
return {
|
|
8755
8714
|
id: "tunnel",
|
|
@@ -8842,9 +8801,9 @@ function isObject5(v) {
|
|
|
8842
8801
|
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
8843
8802
|
}
|
|
8844
8803
|
function readConfig(configPath) {
|
|
8845
|
-
if (!(0,
|
|
8804
|
+
if (!(0, import_node_fs18.existsSync)(configPath)) return {};
|
|
8846
8805
|
try {
|
|
8847
|
-
const parsed = JSON.parse((0,
|
|
8806
|
+
const parsed = JSON.parse((0, import_node_fs18.readFileSync)(configPath, "utf-8"));
|
|
8848
8807
|
return isObject5(parsed) ? parsed : {};
|
|
8849
8808
|
} catch {
|
|
8850
8809
|
return {};
|
|
@@ -9045,7 +9004,7 @@ function registerRecStoragePath(rec, ctx) {
|
|
|
9045
9004
|
|
|
9046
9005
|
// src/cli/rec-setup.ts
|
|
9047
9006
|
var import_node_readline2 = require("readline");
|
|
9048
|
-
var
|
|
9007
|
+
var import_node_fs19 = require("fs");
|
|
9049
9008
|
function ask(rl, question) {
|
|
9050
9009
|
return new Promise((resolve) => rl.question(question, resolve));
|
|
9051
9010
|
}
|
|
@@ -9131,9 +9090,9 @@ async function setupLocal(rl) {
|
|
|
9131
9090
|
function registerRecSetup(rec, ctx) {
|
|
9132
9091
|
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
9092
|
const configPath = resolveAsrConfigPath(ctx);
|
|
9134
|
-
if ((0,
|
|
9093
|
+
if ((0, import_node_fs19.existsSync)(configPath)) {
|
|
9135
9094
|
try {
|
|
9136
|
-
const existing = JSON.parse((0,
|
|
9095
|
+
const existing = JSON.parse((0, import_node_fs19.readFileSync)(configPath, "utf-8"));
|
|
9137
9096
|
process.stderr.write(`\u5F53\u524D\u5DF2\u6709\u914D\u7F6E\uFF1Amode = ${existing.mode}`);
|
|
9138
9097
|
if (existing.updatedAt) process.stderr.write(`\uFF0C\u66F4\u65B0\u4E8E ${existing.updatedAt}`);
|
|
9139
9098
|
process.stderr.write("\n");
|
|
@@ -9146,7 +9105,7 @@ function registerRecSetup(rec, ctx) {
|
|
|
9146
9105
|
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
9106
|
const config = modeIdx === 0 ? await setupApi(rl) : await setupLocal(rl);
|
|
9148
9107
|
const stored = { ...config, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
9149
|
-
(0,
|
|
9108
|
+
(0, import_node_fs19.writeFileSync)(configPath, JSON.stringify(stored, null, 2), "utf-8");
|
|
9150
9109
|
process.stderr.write(`
|
|
9151
9110
|
\u2713 \u914D\u7F6E\u5DF2\u4FDD\u5B58\u5230 ${configPath}
|
|
9152
9111
|
|
|
@@ -9160,8 +9119,8 @@ function registerRecSetup(rec, ctx) {
|
|
|
9160
9119
|
|
|
9161
9120
|
// src/cli/update.ts
|
|
9162
9121
|
var import_node_child_process = require("child_process");
|
|
9163
|
-
var
|
|
9164
|
-
var
|
|
9122
|
+
var import_node_fs20 = require("fs");
|
|
9123
|
+
var import_node_path15 = require("path");
|
|
9165
9124
|
var import_node_os3 = __toESM(require("os"), 1);
|
|
9166
9125
|
init_host();
|
|
9167
9126
|
var BASE_URL2 = "https://artifact.yoooclaw.com/plugin";
|
|
@@ -9220,9 +9179,9 @@ async function runUpdate(ctx, opts) {
|
|
|
9220
9179
|
`);
|
|
9221
9180
|
process.exit(1);
|
|
9222
9181
|
}
|
|
9223
|
-
const tmpScript = (0,
|
|
9182
|
+
const tmpScript = (0, import_node_path15.join)(import_node_os3.default.tmpdir(), `openclaw-install-${Date.now()}.mjs`);
|
|
9224
9183
|
try {
|
|
9225
|
-
(0,
|
|
9184
|
+
(0, import_node_fs20.writeFileSync)(tmpScript, installScript, "utf-8");
|
|
9226
9185
|
} catch (err2) {
|
|
9227
9186
|
const msg = `\u5199\u5165\u4E34\u65F6\u6587\u4EF6\u5931\u8D25: ${err2?.message ?? String(err2)}`;
|
|
9228
9187
|
if (json) {
|
|
@@ -9240,7 +9199,7 @@ async function runUpdate(ctx, opts) {
|
|
|
9240
9199
|
{ stdio: "inherit" }
|
|
9241
9200
|
);
|
|
9242
9201
|
try {
|
|
9243
|
-
(0,
|
|
9202
|
+
(0, import_node_fs20.unlinkSync)(tmpScript);
|
|
9244
9203
|
} catch {
|
|
9245
9204
|
}
|
|
9246
9205
|
if (result.error) {
|
|
@@ -9304,10 +9263,10 @@ function inferOpenClawRootDir(workspaceDir) {
|
|
|
9304
9263
|
if (!workspaceDir) {
|
|
9305
9264
|
return void 0;
|
|
9306
9265
|
}
|
|
9307
|
-
if ((0,
|
|
9266
|
+
if ((0, import_node_path16.basename)(workspaceDir) !== "workspace") {
|
|
9308
9267
|
return void 0;
|
|
9309
9268
|
}
|
|
9310
|
-
return (0,
|
|
9269
|
+
return (0, import_node_path16.dirname)(workspaceDir);
|
|
9311
9270
|
}
|
|
9312
9271
|
function registerPluginCli(api, params) {
|
|
9313
9272
|
const { logger, openclawDir } = params;
|
|
@@ -9558,12 +9517,12 @@ function registerLightControlTool(api, logger) {
|
|
|
9558
9517
|
}
|
|
9559
9518
|
|
|
9560
9519
|
// src/plugin/lifecycle.ts
|
|
9561
|
-
var
|
|
9520
|
+
var import_node_fs30 = require("fs");
|
|
9562
9521
|
init_host();
|
|
9563
9522
|
|
|
9564
9523
|
// src/notification/app-name-map.ts
|
|
9565
|
-
var
|
|
9566
|
-
var
|
|
9524
|
+
var import_node_fs21 = require("fs");
|
|
9525
|
+
var import_node_path17 = require("path");
|
|
9567
9526
|
init_credentials();
|
|
9568
9527
|
init_env();
|
|
9569
9528
|
var PLUGIN_STATE_DIR = "phone-notifications";
|
|
@@ -9584,7 +9543,7 @@ function isAppNameMapApiResponse(v) {
|
|
|
9584
9543
|
);
|
|
9585
9544
|
}
|
|
9586
9545
|
function getCachePath(stateDir) {
|
|
9587
|
-
return (0,
|
|
9546
|
+
return (0, import_node_path17.join)(stateDir, "plugins", PLUGIN_STATE_DIR, CACHE_FILE);
|
|
9588
9547
|
}
|
|
9589
9548
|
function createAppNameMapProvider(opts) {
|
|
9590
9549
|
const { stateDir, logger } = opts;
|
|
@@ -9596,9 +9555,9 @@ function createAppNameMapProvider(opts) {
|
|
|
9596
9555
|
let inFlightFetch = null;
|
|
9597
9556
|
function loadFromDisk() {
|
|
9598
9557
|
const path2 = getCachePath(stateDir);
|
|
9599
|
-
if (!(0,
|
|
9558
|
+
if (!(0, import_node_fs21.existsSync)(path2)) return;
|
|
9600
9559
|
try {
|
|
9601
|
-
const raw = JSON.parse((0,
|
|
9560
|
+
const raw = JSON.parse((0, import_node_fs21.readFileSync)(path2, "utf-8"));
|
|
9602
9561
|
if (!isRecordOfStrings(raw)) return;
|
|
9603
9562
|
map.clear();
|
|
9604
9563
|
for (const [k, v] of Object.entries(raw)) map.set(k, v);
|
|
@@ -9642,10 +9601,10 @@ function createAppNameMapProvider(opts) {
|
|
|
9642
9601
|
logger.warn("[app-name-map] refresh succeeded but got 0 entries");
|
|
9643
9602
|
return;
|
|
9644
9603
|
}
|
|
9645
|
-
const dir = (0,
|
|
9646
|
-
(0,
|
|
9604
|
+
const dir = (0, import_node_path17.join)(stateDir, "plugins", PLUGIN_STATE_DIR);
|
|
9605
|
+
(0, import_node_fs21.mkdirSync)(dir, { recursive: true });
|
|
9647
9606
|
const cachePath = getCachePath(stateDir);
|
|
9648
|
-
(0,
|
|
9607
|
+
(0, import_node_fs21.writeFileSync)(cachePath, JSON.stringify(Object.fromEntries(map), null, 2), "utf-8");
|
|
9649
9608
|
logger.info(`[app-name-map] refreshed ${map.size} entries from server and saved: ${cachePath}`);
|
|
9650
9609
|
} catch (e) {
|
|
9651
9610
|
const message = e instanceof Error ? e.message : String(e);
|
|
@@ -9689,19 +9648,19 @@ function createAppNameMapProvider(opts) {
|
|
|
9689
9648
|
}
|
|
9690
9649
|
|
|
9691
9650
|
// src/notification/storage.ts
|
|
9692
|
-
var
|
|
9651
|
+
var import_node_fs22 = require("fs");
|
|
9693
9652
|
var import_node_crypto2 = require("crypto");
|
|
9694
|
-
var
|
|
9653
|
+
var import_node_path18 = require("path");
|
|
9695
9654
|
var NOTIFICATION_DIR_NAME = "notifications";
|
|
9696
9655
|
var ID_INDEX_DIR_NAME = ".ids";
|
|
9697
9656
|
var CONTENT_KEY_INDEX_DIR_NAME = ".keys";
|
|
9698
9657
|
function getStateFallbackNotificationDir(stateDir) {
|
|
9699
|
-
return (0,
|
|
9658
|
+
return (0, import_node_path18.join)(stateDir, "plugins", "phone-notifications", NOTIFICATION_DIR_NAME);
|
|
9700
9659
|
}
|
|
9701
9660
|
function ensureWritableDirectory(dir) {
|
|
9702
9661
|
try {
|
|
9703
|
-
(0,
|
|
9704
|
-
(0,
|
|
9662
|
+
(0, import_node_fs22.mkdirSync)(dir, { recursive: true });
|
|
9663
|
+
(0, import_node_fs22.accessSync)(dir, import_node_fs22.constants.R_OK | import_node_fs22.constants.W_OK);
|
|
9705
9664
|
return true;
|
|
9706
9665
|
} catch {
|
|
9707
9666
|
return false;
|
|
@@ -9714,7 +9673,7 @@ function resolveNotificationStorageDir(ctx, logger) {
|
|
|
9714
9673
|
return stateNotifDir;
|
|
9715
9674
|
}
|
|
9716
9675
|
if (ctx.workspaceDir) {
|
|
9717
|
-
const workspaceDir = (0,
|
|
9676
|
+
const workspaceDir = (0, import_node_path18.join)(ctx.workspaceDir, NOTIFICATION_DIR_NAME);
|
|
9718
9677
|
if (ensureWritableDirectory(workspaceDir)) {
|
|
9719
9678
|
logger.warn(
|
|
9720
9679
|
`stateDir \u4E0D\u53EF\u7528\uFF0C\u901A\u77E5\u5DF2\u56DE\u9000\u5230 workspace \u8DEF\u5F84: ${workspaceDir}`
|
|
@@ -9729,8 +9688,8 @@ var NotificationStorage = class {
|
|
|
9729
9688
|
this.config = config;
|
|
9730
9689
|
this.logger = logger;
|
|
9731
9690
|
this.dir = dir;
|
|
9732
|
-
this.idIndexDir = (0,
|
|
9733
|
-
this.contentKeyIndexDir = (0,
|
|
9691
|
+
this.idIndexDir = (0, import_node_path18.join)(dir, ID_INDEX_DIR_NAME);
|
|
9692
|
+
this.contentKeyIndexDir = (0, import_node_path18.join)(dir, CONTENT_KEY_INDEX_DIR_NAME);
|
|
9734
9693
|
this.resolveDisplayName = resolveDisplayName;
|
|
9735
9694
|
}
|
|
9736
9695
|
dir;
|
|
@@ -9741,10 +9700,10 @@ var NotificationStorage = class {
|
|
|
9741
9700
|
dateWriteChains = /* @__PURE__ */ new Map();
|
|
9742
9701
|
resolveDisplayName;
|
|
9743
9702
|
async init() {
|
|
9744
|
-
(0,
|
|
9745
|
-
(0,
|
|
9746
|
-
(0,
|
|
9747
|
-
(0,
|
|
9703
|
+
(0, import_node_fs22.mkdirSync)(this.dir, { recursive: true });
|
|
9704
|
+
(0, import_node_fs22.mkdirSync)(this.idIndexDir, { recursive: true });
|
|
9705
|
+
(0, import_node_fs22.rmSync)(this.contentKeyIndexDir, { recursive: true, force: true });
|
|
9706
|
+
(0, import_node_fs22.mkdirSync)(this.contentKeyIndexDir, { recursive: true });
|
|
9748
9707
|
}
|
|
9749
9708
|
async ingest(items) {
|
|
9750
9709
|
const result = {
|
|
@@ -9783,7 +9742,7 @@ var NotificationStorage = class {
|
|
|
9783
9742
|
return { kind: "invalid" };
|
|
9784
9743
|
}
|
|
9785
9744
|
const dateKey = this.formatDate(ts);
|
|
9786
|
-
const filePath = (0,
|
|
9745
|
+
const filePath = (0, import_node_path18.join)(this.dir, `${dateKey}.json`);
|
|
9787
9746
|
const normalizedId = typeof n.id === "string" ? n.id.trim() : "";
|
|
9788
9747
|
const entry = this.buildStoredNotification(n);
|
|
9789
9748
|
return this.withDateWriteLock(dateKey, async () => {
|
|
@@ -9800,7 +9759,7 @@ var NotificationStorage = class {
|
|
|
9800
9759
|
};
|
|
9801
9760
|
const arr = this.readStoredNotifications(filePath);
|
|
9802
9761
|
arr.push(storedEntry);
|
|
9803
|
-
(0,
|
|
9762
|
+
(0, import_node_fs22.writeFileSync)(filePath, JSON.stringify(arr, null, 2), "utf-8");
|
|
9804
9763
|
if (normalizedId) {
|
|
9805
9764
|
this.recordNotificationId(dateKey, normalizedId);
|
|
9806
9765
|
}
|
|
@@ -9837,7 +9796,7 @@ var NotificationStorage = class {
|
|
|
9837
9796
|
return `${year}-${month}-${day}`;
|
|
9838
9797
|
}
|
|
9839
9798
|
getIdIndexPath(dateKey) {
|
|
9840
|
-
return (0,
|
|
9799
|
+
return (0, import_node_path18.join)(this.idIndexDir, `${dateKey}.ids`);
|
|
9841
9800
|
}
|
|
9842
9801
|
getIdSet(dateKey) {
|
|
9843
9802
|
const cached = this.idCache.get(dateKey);
|
|
@@ -9846,8 +9805,8 @@ var NotificationStorage = class {
|
|
|
9846
9805
|
}
|
|
9847
9806
|
const idPath = this.getIdIndexPath(dateKey);
|
|
9848
9807
|
const ids = /* @__PURE__ */ new Set();
|
|
9849
|
-
if ((0,
|
|
9850
|
-
const lines = (0,
|
|
9808
|
+
if ((0, import_node_fs22.existsSync)(idPath)) {
|
|
9809
|
+
const lines = (0, import_node_fs22.readFileSync)(idPath, "utf-8").split(/\r?\n/);
|
|
9851
9810
|
for (const line of lines) {
|
|
9852
9811
|
const id = line.trim();
|
|
9853
9812
|
if (id) {
|
|
@@ -9862,7 +9821,7 @@ var NotificationStorage = class {
|
|
|
9862
9821
|
return this.getIdSet(dateKey).has(id);
|
|
9863
9822
|
}
|
|
9864
9823
|
getContentKeyIndexPath(dateKey) {
|
|
9865
|
-
return (0,
|
|
9824
|
+
return (0, import_node_path18.join)(this.contentKeyIndexDir, `${dateKey}.keys`);
|
|
9866
9825
|
}
|
|
9867
9826
|
getContentKeySet(dateKey, filePath) {
|
|
9868
9827
|
const cached = this.contentKeyCache.get(dateKey);
|
|
@@ -9871,16 +9830,16 @@ var NotificationStorage = class {
|
|
|
9871
9830
|
}
|
|
9872
9831
|
const keyPath = this.getContentKeyIndexPath(dateKey);
|
|
9873
9832
|
const keys = /* @__PURE__ */ new Set();
|
|
9874
|
-
if ((0,
|
|
9833
|
+
if ((0, import_node_fs22.existsSync)(filePath)) {
|
|
9875
9834
|
for (const item of this.readStoredNotifications(filePath)) {
|
|
9876
9835
|
keys.add(this.buildNotificationContentKey(item));
|
|
9877
9836
|
}
|
|
9878
9837
|
}
|
|
9879
9838
|
if (keys.size > 0) {
|
|
9880
|
-
(0,
|
|
9839
|
+
(0, import_node_fs22.writeFileSync)(keyPath, `${Array.from(keys).join("\n")}
|
|
9881
9840
|
`, "utf-8");
|
|
9882
|
-
} else if ((0,
|
|
9883
|
-
(0,
|
|
9841
|
+
} else if ((0, import_node_fs22.existsSync)(keyPath)) {
|
|
9842
|
+
(0, import_node_fs22.rmSync)(keyPath, { force: true });
|
|
9884
9843
|
}
|
|
9885
9844
|
this.contentKeyCache.set(dateKey, keys);
|
|
9886
9845
|
return keys;
|
|
@@ -9895,7 +9854,7 @@ var NotificationStorage = class {
|
|
|
9895
9854
|
if (ids.has(id)) {
|
|
9896
9855
|
return;
|
|
9897
9856
|
}
|
|
9898
|
-
(0,
|
|
9857
|
+
(0, import_node_fs22.appendFileSync)(this.getIdIndexPath(dateKey), `${id}
|
|
9899
9858
|
`, "utf-8");
|
|
9900
9859
|
ids.add(id);
|
|
9901
9860
|
}
|
|
@@ -9905,7 +9864,7 @@ var NotificationStorage = class {
|
|
|
9905
9864
|
if (keys.has(key)) {
|
|
9906
9865
|
return;
|
|
9907
9866
|
}
|
|
9908
|
-
(0,
|
|
9867
|
+
(0, import_node_fs22.appendFileSync)(this.getContentKeyIndexPath(dateKey), `${key}
|
|
9909
9868
|
`, "utf-8");
|
|
9910
9869
|
keys.add(key);
|
|
9911
9870
|
}
|
|
@@ -9913,11 +9872,11 @@ var NotificationStorage = class {
|
|
|
9913
9872
|
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
9873
|
}
|
|
9915
9874
|
readStoredNotifications(filePath) {
|
|
9916
|
-
if (!(0,
|
|
9875
|
+
if (!(0, import_node_fs22.existsSync)(filePath)) {
|
|
9917
9876
|
return [];
|
|
9918
9877
|
}
|
|
9919
9878
|
try {
|
|
9920
|
-
const parsed = JSON.parse((0,
|
|
9879
|
+
const parsed = JSON.parse((0, import_node_fs22.readFileSync)(filePath, "utf-8"));
|
|
9921
9880
|
return Array.isArray(parsed) ? parsed : [];
|
|
9922
9881
|
} catch {
|
|
9923
9882
|
return [];
|
|
@@ -9957,14 +9916,14 @@ var NotificationStorage = class {
|
|
|
9957
9916
|
const dateFilePattern = /^(\d{4}-\d{2}-\d{2})\.(json|md)$/;
|
|
9958
9917
|
const dateDirPattern = /^\d{4}-\d{2}-\d{2}$/;
|
|
9959
9918
|
try {
|
|
9960
|
-
for (const entry of (0,
|
|
9919
|
+
for (const entry of (0, import_node_fs22.readdirSync)(this.dir, { withFileTypes: true })) {
|
|
9961
9920
|
if (entry.isFile()) {
|
|
9962
9921
|
const match = dateFilePattern.exec(entry.name);
|
|
9963
9922
|
if (match && match[1] < cutoffDate) {
|
|
9964
|
-
(0,
|
|
9923
|
+
(0, import_node_fs22.rmSync)((0, import_node_path18.join)(this.dir, entry.name), { force: true });
|
|
9965
9924
|
}
|
|
9966
9925
|
} else if (entry.isDirectory() && dateDirPattern.test(entry.name) && entry.name < cutoffDate) {
|
|
9967
|
-
(0,
|
|
9926
|
+
(0, import_node_fs22.rmSync)((0, import_node_path18.join)(this.dir, entry.name), { recursive: true, force: true });
|
|
9968
9927
|
}
|
|
9969
9928
|
}
|
|
9970
9929
|
} catch {
|
|
@@ -9973,11 +9932,11 @@ var NotificationStorage = class {
|
|
|
9973
9932
|
/** Remove expired .ids index files */
|
|
9974
9933
|
pruneIdIndex(cutoffDate) {
|
|
9975
9934
|
try {
|
|
9976
|
-
for (const entry of (0,
|
|
9935
|
+
for (const entry of (0, import_node_fs22.readdirSync)(this.idIndexDir, { withFileTypes: true })) {
|
|
9977
9936
|
if (!entry.isFile()) continue;
|
|
9978
9937
|
const match = /^(\d{4}-\d{2}-\d{2})\.ids$/.exec(entry.name);
|
|
9979
9938
|
if (match && match[1] < cutoffDate) {
|
|
9980
|
-
(0,
|
|
9939
|
+
(0, import_node_fs22.rmSync)((0, import_node_path18.join)(this.idIndexDir, entry.name), { force: true });
|
|
9981
9940
|
this.idCache.delete(match[1]);
|
|
9982
9941
|
}
|
|
9983
9942
|
}
|
|
@@ -9986,11 +9945,11 @@ var NotificationStorage = class {
|
|
|
9986
9945
|
}
|
|
9987
9946
|
pruneContentKeyIndex(cutoffDate) {
|
|
9988
9947
|
try {
|
|
9989
|
-
for (const entry of (0,
|
|
9948
|
+
for (const entry of (0, import_node_fs22.readdirSync)(this.contentKeyIndexDir, { withFileTypes: true })) {
|
|
9990
9949
|
if (!entry.isFile()) continue;
|
|
9991
9950
|
const match = /^(\d{4}-\d{2}-\d{2})\.keys$/.exec(entry.name);
|
|
9992
9951
|
if (match && match[1] < cutoffDate) {
|
|
9993
|
-
(0,
|
|
9952
|
+
(0, import_node_fs22.rmSync)((0, import_node_path18.join)(this.contentKeyIndexDir, entry.name), { force: true });
|
|
9994
9953
|
this.contentKeyCache.delete(match[1]);
|
|
9995
9954
|
}
|
|
9996
9955
|
}
|
|
@@ -10005,8 +9964,8 @@ var NotificationStorage = class {
|
|
|
10005
9964
|
};
|
|
10006
9965
|
|
|
10007
9966
|
// src/recording/storage.ts
|
|
10008
|
-
var
|
|
10009
|
-
var
|
|
9967
|
+
var import_node_fs23 = require("fs");
|
|
9968
|
+
var import_node_path19 = require("path");
|
|
10010
9969
|
|
|
10011
9970
|
// src/recording/state-machine.ts
|
|
10012
9971
|
var VALID_TRANSITIONS = /* @__PURE__ */ new Map([
|
|
@@ -10067,7 +10026,7 @@ function stripMarkdownFence(markdown) {
|
|
|
10067
10026
|
}
|
|
10068
10027
|
function deriveTitleFromTranscriptPath(transcriptFile, recordingId) {
|
|
10069
10028
|
if (!transcriptFile) return void 0;
|
|
10070
|
-
const name = (0,
|
|
10029
|
+
const name = (0, import_node_path19.basename)(transcriptFile, ".md");
|
|
10071
10030
|
const prefix = `${recordingId}_`;
|
|
10072
10031
|
if (name.startsWith(prefix)) {
|
|
10073
10032
|
const derived = name.slice(prefix.length).trim();
|
|
@@ -10095,22 +10054,22 @@ function extractTranscriptContent(markdown) {
|
|
|
10095
10054
|
return lines.join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
10096
10055
|
}
|
|
10097
10056
|
function resolveRecordingStorageDir(ctx, logger) {
|
|
10098
|
-
const stateRecDir = (0,
|
|
10057
|
+
const stateRecDir = (0, import_node_path19.join)(
|
|
10099
10058
|
ctx.stateDir,
|
|
10100
10059
|
"plugins",
|
|
10101
10060
|
"phone-notifications",
|
|
10102
10061
|
RECORDINGS_DIR
|
|
10103
10062
|
);
|
|
10104
10063
|
try {
|
|
10105
|
-
(0,
|
|
10064
|
+
(0, import_node_fs23.mkdirSync)(stateRecDir, { recursive: true });
|
|
10106
10065
|
logger.info(`\u5F55\u97F3\u5C06\u5199\u5165 stateDir \u8DEF\u5F84: ${stateRecDir}`);
|
|
10107
10066
|
return stateRecDir;
|
|
10108
10067
|
} catch {
|
|
10109
10068
|
}
|
|
10110
10069
|
if (ctx.workspaceDir) {
|
|
10111
|
-
const wsRecDir = (0,
|
|
10070
|
+
const wsRecDir = (0, import_node_path19.join)(ctx.workspaceDir, RECORDINGS_DIR);
|
|
10112
10071
|
try {
|
|
10113
|
-
(0,
|
|
10072
|
+
(0, import_node_fs23.mkdirSync)(wsRecDir, { recursive: true });
|
|
10114
10073
|
logger.warn(`stateDir \u4E0D\u53EF\u7528\uFF0C\u5F55\u97F3\u5DF2\u56DE\u9000\u5230 workspace \u8DEF\u5F84: ${wsRecDir}`);
|
|
10115
10074
|
return wsRecDir;
|
|
10116
10075
|
} catch {
|
|
@@ -10122,11 +10081,11 @@ var RecordingStorage = class {
|
|
|
10122
10081
|
constructor(dir, logger) {
|
|
10123
10082
|
this.logger = logger;
|
|
10124
10083
|
this.dir = dir;
|
|
10125
|
-
this.audioDir = (0,
|
|
10126
|
-
this.transcriptDataDir = (0,
|
|
10127
|
-
this.transcriptsDir = (0,
|
|
10128
|
-
this.summariesDir = (0,
|
|
10129
|
-
this.indexPath = (0,
|
|
10084
|
+
this.audioDir = (0, import_node_path19.join)(dir, AUDIO_DIR);
|
|
10085
|
+
this.transcriptDataDir = (0, import_node_path19.join)(dir, TRANSCRIPT_DATA_DIR);
|
|
10086
|
+
this.transcriptsDir = (0, import_node_path19.join)(dir, TRANSCRIPTS_DIR);
|
|
10087
|
+
this.summariesDir = (0, import_node_path19.join)(dir, SUMMARIES_DIR);
|
|
10088
|
+
this.indexPath = (0, import_node_path19.join)(dir, INDEX_FILE);
|
|
10130
10089
|
}
|
|
10131
10090
|
dir;
|
|
10132
10091
|
audioDir;
|
|
@@ -10137,10 +10096,10 @@ var RecordingStorage = class {
|
|
|
10137
10096
|
index = { recordings: [] };
|
|
10138
10097
|
/** 初始化目录结构并加载索引 */
|
|
10139
10098
|
async init() {
|
|
10140
|
-
(0,
|
|
10141
|
-
(0,
|
|
10142
|
-
(0,
|
|
10143
|
-
(0,
|
|
10099
|
+
(0, import_node_fs23.mkdirSync)(this.audioDir, { recursive: true });
|
|
10100
|
+
(0, import_node_fs23.mkdirSync)(this.transcriptDataDir, { recursive: true });
|
|
10101
|
+
(0, import_node_fs23.mkdirSync)(this.transcriptsDir, { recursive: true });
|
|
10102
|
+
(0, import_node_fs23.mkdirSync)(this.summariesDir, { recursive: true });
|
|
10144
10103
|
this.loadIndex();
|
|
10145
10104
|
this.logger.info(
|
|
10146
10105
|
`\u5F55\u97F3\u5B58\u50A8\u5DF2\u521D\u59CB\u5316: ${this.dir}\uFF08\u5171 ${this.index.recordings.length} \u6761\u8BB0\u5F55\uFF09`
|
|
@@ -10184,13 +10143,13 @@ var RecordingStorage = class {
|
|
|
10184
10143
|
return id;
|
|
10185
10144
|
}
|
|
10186
10145
|
if (existing.transcriptDataFile) {
|
|
10187
|
-
(0,
|
|
10146
|
+
(0, import_node_fs23.rmSync)((0, import_node_path19.join)(this.dir, existing.transcriptDataFile), { force: true });
|
|
10188
10147
|
}
|
|
10189
10148
|
if (existing.transcriptFile) {
|
|
10190
|
-
(0,
|
|
10149
|
+
(0, import_node_fs23.rmSync)((0, import_node_path19.join)(this.dir, existing.transcriptFile), { force: true });
|
|
10191
10150
|
}
|
|
10192
10151
|
if (existing.summaryFile) {
|
|
10193
|
-
(0,
|
|
10152
|
+
(0, import_node_fs23.rmSync)((0, import_node_path19.join)(this.dir, existing.summaryFile), { force: true });
|
|
10194
10153
|
}
|
|
10195
10154
|
existing.metadata = metadata;
|
|
10196
10155
|
existing.status = "syncing_openclaw";
|
|
@@ -10258,7 +10217,7 @@ var RecordingStorage = class {
|
|
|
10258
10217
|
if (!entry) return;
|
|
10259
10218
|
const nextTranscriptDataFile = `${TRANSCRIPT_DATA_DIR}/${filename}`;
|
|
10260
10219
|
if (entry.transcriptDataFile && entry.transcriptDataFile !== nextTranscriptDataFile) {
|
|
10261
|
-
(0,
|
|
10220
|
+
(0, import_node_fs23.rmSync)((0, import_node_path19.join)(this.dir, entry.transcriptDataFile), { force: true });
|
|
10262
10221
|
}
|
|
10263
10222
|
entry.transcriptDataFile = nextTranscriptDataFile;
|
|
10264
10223
|
entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -10272,7 +10231,7 @@ var RecordingStorage = class {
|
|
|
10272
10231
|
if (!entry) return;
|
|
10273
10232
|
const nextTranscriptFile = `${TRANSCRIPTS_DIR}/${filename}`;
|
|
10274
10233
|
if (entry.transcriptFile && entry.transcriptFile !== nextTranscriptFile) {
|
|
10275
|
-
(0,
|
|
10234
|
+
(0, import_node_fs23.rmSync)((0, import_node_path19.join)(this.dir, entry.transcriptFile), { force: true });
|
|
10276
10235
|
}
|
|
10277
10236
|
entry.transcriptFile = nextTranscriptFile;
|
|
10278
10237
|
entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -10286,7 +10245,7 @@ var RecordingStorage = class {
|
|
|
10286
10245
|
if (!entry) return;
|
|
10287
10246
|
const nextSummaryFile = `${SUMMARIES_DIR}/${filename}`;
|
|
10288
10247
|
if (entry.summaryFile && entry.summaryFile !== nextSummaryFile) {
|
|
10289
|
-
(0,
|
|
10248
|
+
(0, import_node_fs23.rmSync)((0, import_node_path19.join)(this.dir, entry.summaryFile), { force: true });
|
|
10290
10249
|
}
|
|
10291
10250
|
entry.summaryFile = nextSummaryFile;
|
|
10292
10251
|
entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -10384,24 +10343,24 @@ var RecordingStorage = class {
|
|
|
10384
10343
|
const entry = this.findById(recordingId);
|
|
10385
10344
|
if (!entry) return false;
|
|
10386
10345
|
if (entry.audioFile) {
|
|
10387
|
-
const audioPath = (0,
|
|
10388
|
-
(0,
|
|
10346
|
+
const audioPath = (0, import_node_path19.join)(this.dir, entry.audioFile);
|
|
10347
|
+
(0, import_node_fs23.rmSync)(audioPath, { force: true });
|
|
10389
10348
|
}
|
|
10390
10349
|
if (entry.srtFile) {
|
|
10391
|
-
const srtPath = (0,
|
|
10392
|
-
(0,
|
|
10350
|
+
const srtPath = (0, import_node_path19.join)(this.dir, entry.srtFile);
|
|
10351
|
+
(0, import_node_fs23.rmSync)(srtPath, { force: true });
|
|
10393
10352
|
}
|
|
10394
10353
|
if (entry.transcriptDataFile) {
|
|
10395
|
-
const transcriptDataPath = (0,
|
|
10396
|
-
(0,
|
|
10354
|
+
const transcriptDataPath = (0, import_node_path19.join)(this.dir, entry.transcriptDataFile);
|
|
10355
|
+
(0, import_node_fs23.rmSync)(transcriptDataPath, { force: true });
|
|
10397
10356
|
}
|
|
10398
10357
|
if (entry.transcriptFile) {
|
|
10399
|
-
const transcriptPath = (0,
|
|
10400
|
-
(0,
|
|
10358
|
+
const transcriptPath = (0, import_node_path19.join)(this.dir, entry.transcriptFile);
|
|
10359
|
+
(0, import_node_fs23.rmSync)(transcriptPath, { force: true });
|
|
10401
10360
|
}
|
|
10402
10361
|
if (entry.summaryFile) {
|
|
10403
|
-
const summaryPath = (0,
|
|
10404
|
-
(0,
|
|
10362
|
+
const summaryPath = (0, import_node_path19.join)(this.dir, entry.summaryFile);
|
|
10363
|
+
(0, import_node_fs23.rmSync)(summaryPath, { force: true });
|
|
10405
10364
|
}
|
|
10406
10365
|
if (opts?.localOnly) {
|
|
10407
10366
|
entry.audioFile = void 0;
|
|
@@ -10459,34 +10418,34 @@ var RecordingStorage = class {
|
|
|
10459
10418
|
* 获取音频文件的绝对路径。ossUrl 用于推断文件扩展名
|
|
10460
10419
|
*/
|
|
10461
10420
|
getAudioFilePath(recordingId, ossUrl) {
|
|
10462
|
-
return (0,
|
|
10421
|
+
return (0, import_node_path19.join)(this.audioDir, this.buildAudioFilename(recordingId, ossUrl));
|
|
10463
10422
|
}
|
|
10464
10423
|
/**
|
|
10465
10424
|
* 获取打点文件的绝对路径
|
|
10466
10425
|
*/
|
|
10467
10426
|
getSrtFilePath(recordingId) {
|
|
10468
|
-
return (0,
|
|
10427
|
+
return (0, import_node_path19.join)(this.audioDir, this.buildSrtFilename(recordingId));
|
|
10469
10428
|
}
|
|
10470
10429
|
/**
|
|
10471
10430
|
* 获取转写 JSON 文件的绝对路径
|
|
10472
10431
|
*/
|
|
10473
10432
|
getTranscriptDataFilePath(recordingId) {
|
|
10474
|
-
return (0,
|
|
10433
|
+
return (0, import_node_path19.join)(this.transcriptDataDir, this.buildTranscriptDataFilename(recordingId));
|
|
10475
10434
|
}
|
|
10476
10435
|
/**
|
|
10477
10436
|
* 获取摘要文件的绝对路径
|
|
10478
10437
|
*/
|
|
10479
10438
|
getSummaryFilePath(recordingId) {
|
|
10480
|
-
return (0,
|
|
10439
|
+
return (0, import_node_path19.join)(this.summariesDir, this.buildSummaryFilename(recordingId));
|
|
10481
10440
|
}
|
|
10482
10441
|
// ─── Persistence ───
|
|
10483
10442
|
loadIndex() {
|
|
10484
|
-
if (!(0,
|
|
10443
|
+
if (!(0, import_node_fs23.existsSync)(this.indexPath)) {
|
|
10485
10444
|
this.index = { recordings: [] };
|
|
10486
10445
|
return;
|
|
10487
10446
|
}
|
|
10488
10447
|
try {
|
|
10489
|
-
const raw = JSON.parse((0,
|
|
10448
|
+
const raw = JSON.parse((0, import_node_fs23.readFileSync)(this.indexPath, "utf-8"));
|
|
10490
10449
|
if (raw && Array.isArray(raw.recordings)) {
|
|
10491
10450
|
let needsRewrite = false;
|
|
10492
10451
|
const normalized = raw.recordings.filter((entry) => entry && typeof entry === "object").map((entry) => {
|
|
@@ -10524,8 +10483,8 @@ var RecordingStorage = class {
|
|
|
10524
10483
|
segments: []
|
|
10525
10484
|
});
|
|
10526
10485
|
const transcriptDataFilename = this.buildTranscriptDataFilename(compacted.id);
|
|
10527
|
-
(0,
|
|
10528
|
-
(0,
|
|
10486
|
+
(0, import_node_fs23.writeFileSync)(
|
|
10487
|
+
(0, import_node_path19.join)(this.transcriptDataDir, transcriptDataFilename),
|
|
10529
10488
|
JSON.stringify(transcriptDoc, null, 2),
|
|
10530
10489
|
"utf-8"
|
|
10531
10490
|
);
|
|
@@ -10537,8 +10496,8 @@ var RecordingStorage = class {
|
|
|
10537
10496
|
compacted.summaryFile = entry.summaryFile;
|
|
10538
10497
|
} else if (typeof entry.summary === "string" && entry.summary.trim()) {
|
|
10539
10498
|
const summaryFilename = this.buildSummaryFilename(entry.id);
|
|
10540
|
-
(0,
|
|
10541
|
-
(0,
|
|
10499
|
+
(0, import_node_fs23.writeFileSync)(
|
|
10500
|
+
(0, import_node_path19.join)(this.summariesDir, summaryFilename),
|
|
10542
10501
|
entry.summary.trim(),
|
|
10543
10502
|
"utf-8"
|
|
10544
10503
|
);
|
|
@@ -10548,8 +10507,8 @@ var RecordingStorage = class {
|
|
|
10548
10507
|
const summaryFromDocument = extractTranscriptSummaryFromDocument(transcriptDoc);
|
|
10549
10508
|
if (summaryFromDocument) {
|
|
10550
10509
|
const summaryFilename = this.buildSummaryFilename(entry.id);
|
|
10551
|
-
(0,
|
|
10552
|
-
(0,
|
|
10510
|
+
(0, import_node_fs23.writeFileSync)(
|
|
10511
|
+
(0, import_node_path19.join)(this.summariesDir, summaryFilename),
|
|
10553
10512
|
summaryFromDocument,
|
|
10554
10513
|
"utf-8"
|
|
10555
10514
|
);
|
|
@@ -10589,7 +10548,7 @@ var RecordingStorage = class {
|
|
|
10589
10548
|
}
|
|
10590
10549
|
readRelativeTextFile(relativePath) {
|
|
10591
10550
|
try {
|
|
10592
|
-
return (0,
|
|
10551
|
+
return (0, import_node_fs23.readFileSync)((0, import_node_path19.join)(this.dir, relativePath), "utf-8");
|
|
10593
10552
|
} catch {
|
|
10594
10553
|
return void 0;
|
|
10595
10554
|
}
|
|
@@ -10602,7 +10561,7 @@ var RecordingStorage = class {
|
|
|
10602
10561
|
return parseTranscriptDocument(raw);
|
|
10603
10562
|
}
|
|
10604
10563
|
saveIndex() {
|
|
10605
|
-
(0,
|
|
10564
|
+
(0, import_node_fs23.writeFileSync)(
|
|
10606
10565
|
this.indexPath,
|
|
10607
10566
|
JSON.stringify(this.index, null, 2),
|
|
10608
10567
|
"utf-8"
|
|
@@ -10616,8 +10575,8 @@ var RecordingStorage = class {
|
|
|
10616
10575
|
init_transcript_document();
|
|
10617
10576
|
|
|
10618
10577
|
// src/recording/downloader.ts
|
|
10619
|
-
var
|
|
10620
|
-
var
|
|
10578
|
+
var import_node_fs24 = require("fs");
|
|
10579
|
+
var import_node_path20 = require("path");
|
|
10621
10580
|
var import_promises2 = require("stream/promises");
|
|
10622
10581
|
var import_node_stream = require("stream");
|
|
10623
10582
|
var DEFAULT_TIMEOUT_MS2 = 5 * 60 * 1e3;
|
|
@@ -10627,7 +10586,7 @@ async function downloadFile(url, destPath, logger, options) {
|
|
|
10627
10586
|
const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
|
|
10628
10587
|
const maxRetries = options?.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
10629
10588
|
const retryBackoffMs = options?.retryBackoffMs ?? DEFAULT_RETRY_BACKOFF_MS;
|
|
10630
|
-
(0,
|
|
10589
|
+
(0, import_node_fs24.mkdirSync)((0, import_node_path20.dirname)(destPath), { recursive: true });
|
|
10631
10590
|
let lastError;
|
|
10632
10591
|
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
10633
10592
|
const startMs = Date.now();
|
|
@@ -10645,11 +10604,11 @@ async function downloadFile(url, destPath, logger, options) {
|
|
|
10645
10604
|
if (!res.body) {
|
|
10646
10605
|
throw new Error("\u54CD\u5E94\u4F53\u4E3A\u7A7A");
|
|
10647
10606
|
}
|
|
10648
|
-
const writeStream = (0,
|
|
10607
|
+
const writeStream = (0, import_node_fs24.createWriteStream)(destPath);
|
|
10649
10608
|
const readable = import_node_stream.Readable.fromWeb(res.body);
|
|
10650
10609
|
await (0, import_promises2.pipeline)(readable, writeStream);
|
|
10651
10610
|
const elapsed = Date.now() - startMs;
|
|
10652
|
-
const fileSize = (0,
|
|
10611
|
+
const fileSize = (0, import_node_fs24.existsSync)(destPath) ? (0, import_node_fs24.statSync)(destPath).size : 0;
|
|
10653
10612
|
logger.info(
|
|
10654
10613
|
`[downloader] \u4E0B\u8F7D\u5B8C\u6210: ${destPath} (${formatBytes(fileSize)}, ${elapsed}ms)`
|
|
10655
10614
|
);
|
|
@@ -10660,7 +10619,7 @@ async function downloadFile(url, destPath, logger, options) {
|
|
|
10660
10619
|
} catch (err2) {
|
|
10661
10620
|
lastError = err2?.message ?? String(err2);
|
|
10662
10621
|
try {
|
|
10663
|
-
if ((0,
|
|
10622
|
+
if ((0, import_node_fs24.existsSync)(destPath)) (0, import_node_fs24.unlinkSync)(destPath);
|
|
10664
10623
|
} catch {
|
|
10665
10624
|
}
|
|
10666
10625
|
const isAbort = err2?.name === "AbortError";
|
|
@@ -10898,13 +10857,13 @@ async function triggerTranscription(recordingId, storage, asrConfig, logger, opt
|
|
|
10898
10857
|
}
|
|
10899
10858
|
|
|
10900
10859
|
// src/tunnel/service.ts
|
|
10901
|
-
var
|
|
10902
|
-
var
|
|
10860
|
+
var import_node_fs29 = require("fs");
|
|
10861
|
+
var import_node_path25 = require("path");
|
|
10903
10862
|
init_credentials();
|
|
10904
10863
|
|
|
10905
10864
|
// src/tunnel/relay-client.ts
|
|
10906
|
-
var
|
|
10907
|
-
var
|
|
10865
|
+
var import_node_fs27 = require("fs");
|
|
10866
|
+
var import_node_path23 = require("path");
|
|
10908
10867
|
|
|
10909
10868
|
// node_modules/.pnpm/ws@8.19.0/node_modules/ws/wrapper.mjs
|
|
10910
10869
|
var import_stream = __toESM(require_stream(), 1);
|
|
@@ -10948,8 +10907,8 @@ var RelayClient = class {
|
|
|
10948
10907
|
lastDisconnectReason
|
|
10949
10908
|
};
|
|
10950
10909
|
try {
|
|
10951
|
-
(0,
|
|
10952
|
-
(0,
|
|
10910
|
+
(0, import_node_fs27.mkdirSync)((0, import_node_path23.dirname)(this.opts.statusFilePath), { recursive: true });
|
|
10911
|
+
(0, import_node_fs27.writeFileSync)(this.opts.statusFilePath, JSON.stringify(info, null, 2));
|
|
10953
10912
|
} catch {
|
|
10954
10913
|
}
|
|
10955
10914
|
}
|
|
@@ -11331,8 +11290,8 @@ init_host();
|
|
|
11331
11290
|
|
|
11332
11291
|
// src/tunnel/device-identity.ts
|
|
11333
11292
|
var import_node_crypto3 = __toESM(require("crypto"), 1);
|
|
11334
|
-
var
|
|
11335
|
-
var
|
|
11293
|
+
var import_node_fs28 = __toESM(require("fs"), 1);
|
|
11294
|
+
var import_node_path24 = __toESM(require("path"), 1);
|
|
11336
11295
|
init_host();
|
|
11337
11296
|
var ED25519_SPKI_PREFIX = Buffer.from("302a300506032b6570032100", "hex");
|
|
11338
11297
|
function base64UrlEncode(buf) {
|
|
@@ -11377,10 +11336,10 @@ function resolveClientStateDir(stateDir) {
|
|
|
11377
11336
|
return stateDir ?? resolveStateDir();
|
|
11378
11337
|
}
|
|
11379
11338
|
function ensureDir(filePath) {
|
|
11380
|
-
|
|
11339
|
+
import_node_fs28.default.mkdirSync(import_node_path24.default.dirname(filePath), { recursive: true });
|
|
11381
11340
|
}
|
|
11382
11341
|
function resolveIdentityPath(stateDir) {
|
|
11383
|
-
return
|
|
11342
|
+
return import_node_path24.default.join(stateDir, "identity", "device.json");
|
|
11384
11343
|
}
|
|
11385
11344
|
function normalizeDeviceAuthRole(role) {
|
|
11386
11345
|
return role.trim();
|
|
@@ -11396,12 +11355,12 @@ function normalizeDeviceAuthScopes(scopes) {
|
|
|
11396
11355
|
return [...out].sort();
|
|
11397
11356
|
}
|
|
11398
11357
|
function resolveDeviceAuthPath(stateDir) {
|
|
11399
|
-
return
|
|
11358
|
+
return import_node_path24.default.join(stateDir, "identity", "device-auth.json");
|
|
11400
11359
|
}
|
|
11401
11360
|
function readDeviceAuthStore(filePath) {
|
|
11402
11361
|
try {
|
|
11403
|
-
if (!
|
|
11404
|
-
const raw =
|
|
11362
|
+
if (!import_node_fs28.default.existsSync(filePath)) return null;
|
|
11363
|
+
const raw = import_node_fs28.default.readFileSync(filePath, "utf8");
|
|
11405
11364
|
const parsed = JSON.parse(raw);
|
|
11406
11365
|
if (parsed?.version !== 1 || typeof parsed.deviceId !== "string") return null;
|
|
11407
11366
|
if (!parsed.tokens || typeof parsed.tokens !== "object") return null;
|
|
@@ -11412,12 +11371,12 @@ function readDeviceAuthStore(filePath) {
|
|
|
11412
11371
|
}
|
|
11413
11372
|
function writeDeviceAuthStore(filePath, store) {
|
|
11414
11373
|
ensureDir(filePath);
|
|
11415
|
-
|
|
11374
|
+
import_node_fs28.default.writeFileSync(filePath, `${JSON.stringify(store, null, 2)}
|
|
11416
11375
|
`, {
|
|
11417
11376
|
mode: 384
|
|
11418
11377
|
});
|
|
11419
11378
|
try {
|
|
11420
|
-
|
|
11379
|
+
import_node_fs28.default.chmodSync(filePath, 384);
|
|
11421
11380
|
} catch {
|
|
11422
11381
|
}
|
|
11423
11382
|
}
|
|
@@ -11464,8 +11423,8 @@ function clearDeviceAuthToken(params) {
|
|
|
11464
11423
|
function loadOrCreateDeviceIdentity(stateDir) {
|
|
11465
11424
|
const filePath = resolveIdentityPath(stateDir);
|
|
11466
11425
|
try {
|
|
11467
|
-
if (
|
|
11468
|
-
const raw =
|
|
11426
|
+
if (import_node_fs28.default.existsSync(filePath)) {
|
|
11427
|
+
const raw = import_node_fs28.default.readFileSync(filePath, "utf8");
|
|
11469
11428
|
const parsed = JSON.parse(raw);
|
|
11470
11429
|
if (parsed?.version === 1 && typeof parsed.deviceId === "string" && typeof parsed.publicKeyPem === "string" && typeof parsed.privateKeyPem === "string") {
|
|
11471
11430
|
const derivedId = fingerprintPublicKey(parsed.publicKeyPem);
|
|
@@ -11486,14 +11445,14 @@ function loadOrCreateDeviceIdentity(stateDir) {
|
|
|
11486
11445
|
publicKeyPem,
|
|
11487
11446
|
privateKeyPem
|
|
11488
11447
|
};
|
|
11489
|
-
|
|
11448
|
+
import_node_fs28.default.mkdirSync(import_node_path24.default.dirname(filePath), { recursive: true });
|
|
11490
11449
|
const stored = {
|
|
11491
11450
|
version: 1,
|
|
11492
11451
|
...identity,
|
|
11493
11452
|
createdAtMs: Date.now()
|
|
11494
11453
|
};
|
|
11495
11454
|
ensureDir(filePath);
|
|
11496
|
-
|
|
11455
|
+
import_node_fs28.default.writeFileSync(filePath, `${JSON.stringify(stored, null, 2)}
|
|
11497
11456
|
`, {
|
|
11498
11457
|
mode: 384
|
|
11499
11458
|
});
|
|
@@ -12265,7 +12224,7 @@ function createTunnelService(opts) {
|
|
|
12265
12224
|
}
|
|
12266
12225
|
function readLockOwner(filePath) {
|
|
12267
12226
|
try {
|
|
12268
|
-
const parsed = JSON.parse((0,
|
|
12227
|
+
const parsed = JSON.parse((0, import_node_fs29.readFileSync)(filePath, "utf-8"));
|
|
12269
12228
|
return typeof parsed.pid === "number" ? parsed.pid : null;
|
|
12270
12229
|
} catch {
|
|
12271
12230
|
return null;
|
|
@@ -12278,23 +12237,23 @@ function createTunnelService(opts) {
|
|
|
12278
12237
|
lockFd = null;
|
|
12279
12238
|
if (fd !== null) {
|
|
12280
12239
|
try {
|
|
12281
|
-
(0,
|
|
12240
|
+
(0, import_node_fs29.closeSync)(fd);
|
|
12282
12241
|
} catch {
|
|
12283
12242
|
}
|
|
12284
12243
|
}
|
|
12285
12244
|
if (filePath) {
|
|
12286
12245
|
try {
|
|
12287
|
-
(0,
|
|
12246
|
+
(0, import_node_fs29.unlinkSync)(filePath);
|
|
12288
12247
|
} catch {
|
|
12289
12248
|
}
|
|
12290
12249
|
}
|
|
12291
12250
|
}
|
|
12292
12251
|
function acquireLock(filePath) {
|
|
12293
|
-
(0,
|
|
12252
|
+
(0, import_node_fs29.mkdirSync)((0, import_node_path25.dirname)(filePath), { recursive: true });
|
|
12294
12253
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
12295
12254
|
try {
|
|
12296
|
-
const fd = (0,
|
|
12297
|
-
(0,
|
|
12255
|
+
const fd = (0, import_node_fs29.openSync)(filePath, "wx", 384);
|
|
12256
|
+
(0, import_node_fs29.writeFileSync)(
|
|
12298
12257
|
fd,
|
|
12299
12258
|
JSON.stringify({
|
|
12300
12259
|
pid: process.pid,
|
|
@@ -12318,7 +12277,7 @@ function createTunnelService(opts) {
|
|
|
12318
12277
|
`Relay tunnel: removing stale local lock owned by dead pid=${ownerPid}`
|
|
12319
12278
|
);
|
|
12320
12279
|
try {
|
|
12321
|
-
(0,
|
|
12280
|
+
(0, import_node_fs29.unlinkSync)(filePath);
|
|
12322
12281
|
} catch {
|
|
12323
12282
|
}
|
|
12324
12283
|
continue;
|
|
@@ -12363,12 +12322,12 @@ function createTunnelService(opts) {
|
|
|
12363
12322
|
return;
|
|
12364
12323
|
}
|
|
12365
12324
|
const { logger } = opts;
|
|
12366
|
-
const baseStateDir = (0,
|
|
12325
|
+
const baseStateDir = (0, import_node_path25.join)(ctx.stateDir, "plugins", "phone-notifications");
|
|
12367
12326
|
logger.info(
|
|
12368
12327
|
`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
12328
|
);
|
|
12370
|
-
const statusFilePath = (0,
|
|
12371
|
-
const lockPath = (0,
|
|
12329
|
+
const statusFilePath = (0, import_node_path25.join)(baseStateDir, "tunnel-status.json");
|
|
12330
|
+
const lockPath = (0, import_node_path25.join)(baseStateDir, "relay-tunnel.lock");
|
|
12372
12331
|
if (!acquireLock(lockPath)) {
|
|
12373
12332
|
return;
|
|
12374
12333
|
}
|
|
@@ -12508,7 +12467,7 @@ function readHostGatewayConfig(params) {
|
|
|
12508
12467
|
let configData;
|
|
12509
12468
|
if (configPath) {
|
|
12510
12469
|
try {
|
|
12511
|
-
configData = JSON.parse((0,
|
|
12470
|
+
configData = JSON.parse((0, import_node_fs30.readFileSync)(configPath, "utf-8"));
|
|
12512
12471
|
} catch (err2) {
|
|
12513
12472
|
if (err2?.code !== "ENOENT") {
|
|
12514
12473
|
params.logger.warn(
|
|
@@ -13270,7 +13229,6 @@ var index_default = {
|
|
|
13270
13229
|
recordingStorage = nextRecordingStorage;
|
|
13271
13230
|
},
|
|
13272
13231
|
onStorageReady() {
|
|
13273
|
-
migrateLegacyLightRuleTasks(lightRuleCtx, logger);
|
|
13274
13232
|
lightRuleRegistry.reload();
|
|
13275
13233
|
}
|
|
13276
13234
|
});
|