chatlab-cli 0.33.0 → 0.34.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chat-command-IHRNO7J4.mjs → chat-command-OWKJJ736.mjs} +9 -9
- package/dist/{chunk-C3B7RXES.mjs → chunk-3RWYALUP.mjs} +629 -319
- package/dist/chunk-3RWYALUP.mjs.map +1 -0
- package/dist/{chunk-4V6UP7EW.mjs → chunk-GHZFNAMF.mjs} +2 -2
- package/dist/{chunk-NHTOSDYI.mjs → chunk-J7HAIT3T.mjs} +15 -9
- package/dist/chunk-J7HAIT3T.mjs.map +1 -0
- package/dist/{chunk-HGV4MUIW.mjs → chunk-MPHFZYB7.mjs} +15 -62
- package/dist/chunk-MPHFZYB7.mjs.map +1 -0
- package/dist/{chunk-U4F6BNGZ.mjs → chunk-OHFVX2HH.mjs} +2 -2
- package/dist/{chunk-YAQLYL52.mjs → chunk-QZCNVAH6.mjs} +2 -2
- package/dist/{chunk-YAQLYL52.mjs.map → chunk-QZCNVAH6.mjs.map} +1 -1
- package/dist/{chunk-ZTMZ7S7T.mjs → chunk-RMW3524R.mjs} +46 -66
- package/dist/chunk-RMW3524R.mjs.map +1 -0
- package/dist/{chunk-KWJ5FZ74.mjs → chunk-RRC6U56Y.mjs} +640 -296
- package/dist/chunk-RRC6U56Y.mjs.map +1 -0
- package/dist/{chunk-NSWFHMBZ.mjs → chunk-VTCZM2JS.mjs} +11 -11
- package/dist/{chunk-S7YPBKQ3.mjs → chunk-XEGEOU2D.mjs} +2 -2
- package/dist/{chunk-RHA534GU.mjs → chunk-YRCFDZ5Q.mjs} +3 -3
- package/dist/{chunk-ZERQIKI4.mjs → chunk-ZM5DSHFF.mjs} +95 -5
- package/dist/chunk-ZM5DSHFF.mjs.map +1 -0
- package/dist/cli.mjs +9 -9
- package/dist/contacts-worker.mjs +2 -2
- package/dist/global-insight-worker.mjs +2 -2
- package/dist/{http-Y2WC2UK4.mjs → http-X55S6MTO.mjs} +12 -12
- package/dist/{import-4HF2UNQI.mjs → import-4AX6IX57.mjs} +8 -8
- package/dist/index.mjs +12 -12
- package/dist/{mcp-DJPDRFTW.mjs → mcp-GWC52AWE.mjs} +9 -9
- package/dist/people-relationships-worker.mjs +2 -2
- package/dist/semantic-index-worker.mjs +1 -1
- package/dist/{src-R7MZLKXQ.mjs → src-DLLM4SEO.mjs} +11 -7
- package/dist/{stream-import-DX57ANUL.mjs → stream-import-K24HWAAZ.mjs} +8 -8
- package/dist/{worker-runtime-QMN7OKOZ.mjs → worker-runtime-6KKR55TD.mjs} +6 -6
- package/dist-cli-web/assets/{ActionToolsPanel.vue_vue_type_script_setup_true_lang-hwRVh048.js → ActionToolsPanel.vue_vue_type_script_setup_true_lang-D1BiZuQL.js} +5 -5
- package/dist-cli-web/assets/{BufferResource-DwfMBlAa.js → BufferResource-IPkSmPao.js} +1 -1
- package/dist-cli-web/assets/{CanvasRenderer-q312LRsp.js → CanvasRenderer-OAQy65em.js} +1 -1
- package/dist-cli-web/assets/{DataDirCleanupNotice--ee1dY0d.js → DataDirCleanupNotice-jEI-YjFp.js} +1 -1
- package/dist-cli-web/assets/{EChartWordcloud-BaMgUl0Y.js → EChartWordcloud-Pi48JdN2.js} +1 -1
- package/dist-cli-web/assets/{Filter-BOb5cLBx.js → Filter-FQD30cRE.js} +1 -1
- package/dist-cli-web/assets/LoadingState.vue_vue_type_script_setup_true_lang-CCK5yTju.js +1 -0
- package/dist-cli-web/assets/{MessageExportModal-CFbovWh1.js → MessageExportModal-CZn3LbeY.js} +1 -1
- package/dist-cli-web/assets/{PageHeader-B3-W9mvh.js → PageHeader-B9B9K9by.js} +1 -1
- package/dist-cli-web/assets/{RelationshipGalaxyCanvas-GEpsKHxV.js → RelationshipGalaxyCanvas-CbTmpnZ6.js} +14 -14
- package/dist-cli-web/assets/{RelationshipGalaxyThreeCanvas-BluPHjCR.css → RelationshipGalaxyThreeCanvas-CeYJABxI.css} +1 -1
- package/dist-cli-web/assets/{RelationshipGalaxyThreeCanvas-DHOU66Gj.js → RelationshipGalaxyThreeCanvas-Cu6NmKOq.js} +14 -14
- package/dist-cli-web/assets/{RenderTargetSystem-PEnnW2yb.js → RenderTargetSystem-DnptJCQ0.js} +1 -1
- package/dist-cli-web/assets/{ThemeCard.vue_vue_type_script_setup_true_lang-sNw3hP4c.js → ThemeCard.vue_vue_type_script_setup_true_lang-JXMFY6aD.js} +1 -1
- package/dist-cli-web/assets/{TimeSelect.vue_vue_type_script_setup_true_lang-BtUvMehe.js → TimeSelect.vue_vue_type_script_setup_true_lang-QAZFwx5S.js} +1 -1
- package/dist-cli-web/assets/{WebGLRenderer-BjP_1do7.js → WebGLRenderer-BmjIF5se.js} +1 -1
- package/dist-cli-web/assets/{WebGPURenderer-ldVv92u7.js → WebGPURenderer-DkNcKkqj.js} +1 -1
- package/dist-cli-web/assets/{annual-summary-time-range-BHClzNvd.js → annual-summary-time-range-DJ0HWI_t.js} +1 -1
- package/dist-cli-web/assets/{base-DBJ95yXf.js → base-CnuE0ss0.js} +1 -1
- package/dist-cli-web/assets/{browserAll-CPoMOLKh.js → browserAll-C_NnyNBz.js} +1 -1
- package/dist-cli-web/assets/{cli-web-B5VYO-Dh.js → cli-web-t1gabACJ.js} +1 -1
- package/dist-cli-web/assets/{dateFormat-Cf2xuaE-.js → dateFormat-p6nibkgt.js} +1 -1
- package/dist-cli-web/assets/{fetch-J67jyI2k.js → fetch-BBUvWvOM.js} +1 -1
- package/dist-cli-web/assets/{fetch-BuWxo6oK.js → fetch-BfYranz7.js} +1 -1
- package/dist-cli-web/assets/{fetch-CXIdj2-_.js → fetch-Bsm5YQ_7.js} +1 -1
- package/dist-cli-web/assets/{fetch-Dr41uuXL.js → fetch-C4KJ7tGz.js} +1 -1
- package/dist-cli-web/assets/fetch-CMhV3TYQ.js +1 -0
- package/dist-cli-web/assets/{fetch-C0HHT1Yn.js → fetch-Ch4IMKin.js} +1 -1
- package/dist-cli-web/assets/{fetch-B1km2u3N.js → fetch-DajjPQtq.js} +1 -1
- package/dist-cli-web/assets/{fetch-BFDKzf1P.js → fetch-WElo3Vix.js} +1 -1
- package/dist-cli-web/assets/{fetch-DGi_9my2.js → fetch-WIOgRPd9.js} +1 -1
- package/dist-cli-web/assets/{fetch-CtyVktRW.js → fetch-_Hb-KRSr.js} +3 -3
- package/dist-cli-web/assets/index-B8I5Pax_.js +2 -0
- package/dist-cli-web/assets/index-BE4nd1aX.js +1 -0
- package/dist-cli-web/assets/{index-B7R74Yp7.js → index-Bb6EtLMB.js} +1 -1
- package/dist-cli-web/assets/{index-DzQT-qXF.js → index-BcWaPFz7.js} +1 -1
- package/dist-cli-web/assets/index-CKkIHbie.js +64 -0
- package/dist-cli-web/assets/index-CbacXZN3.js +2 -0
- package/dist-cli-web/assets/{index-DtlTo3nt.js → index-CjoTcSEc.js} +1 -1
- package/dist-cli-web/assets/index-CsX1Wt8l.js +173 -0
- package/dist-cli-web/assets/{index-BGiTw98l.js → index-CsyURmWU.js} +1 -1
- package/dist-cli-web/assets/{index-5UdyJtVU.js → index-DLnlRLCx.js} +1 -1
- package/dist-cli-web/assets/index-DrjoMv9s.css +1 -0
- package/dist-cli-web/assets/index-Jhwca9kg.css +1 -0
- package/dist-cli-web/assets/index-YzfjPohq.js +53 -0
- package/dist-cli-web/assets/{index-Bf3gFaid.js → index-dObiAHg6.js} +1 -1
- package/dist-cli-web/assets/index-vtF05fh7.css +1 -0
- package/dist-cli-web/assets/{index-Ba21yU86.js → index-x74lBtei.js} +1 -1
- package/dist-cli-web/assets/{people-page-header-BvQy1GQj.js → people-page-header-BW5cNPl7.js} +1 -1
- package/dist-cli-web/assets/{webworkerAll-DgKQKbNn.js → webworkerAll-8AFsQkH1.js} +1 -1
- package/dist-cli-web/index.html +2 -2
- package/package.json +1 -1
- package/dist/chunk-C3B7RXES.mjs.map +0 -1
- package/dist/chunk-HGV4MUIW.mjs.map +0 -1
- package/dist/chunk-KWJ5FZ74.mjs.map +0 -1
- package/dist/chunk-NHTOSDYI.mjs.map +0 -1
- package/dist/chunk-ZERQIKI4.mjs.map +0 -1
- package/dist/chunk-ZTMZ7S7T.mjs.map +0 -1
- package/dist-cli-web/assets/LoadingState.vue_vue_type_script_setup_true_lang-DK2z0Jrh.js +0 -1
- package/dist-cli-web/assets/fetch-80O3EH4a.js +0 -1
- package/dist-cli-web/assets/index-7jm3YI9u.js +0 -53
- package/dist-cli-web/assets/index-ByQSR8Bj.js +0 -2
- package/dist-cli-web/assets/index-CPZYydbc.js +0 -2
- package/dist-cli-web/assets/index-D8Q3U-6e.js +0 -1
- package/dist-cli-web/assets/index-DGtDxRCd.js +0 -173
- package/dist-cli-web/assets/index-DTxnpQiv.css +0 -1
- package/dist-cli-web/assets/index-gpTDI3sq.js +0 -64
- package/dist-cli-web/assets/index-lwhCMqhd.css +0 -1
- package/dist-cli-web/assets/index-qsbWn8VP.css +0 -1
- /package/dist/{chat-command-IHRNO7J4.mjs.map → chat-command-OWKJJ736.mjs.map} +0 -0
- /package/dist/{chunk-4V6UP7EW.mjs.map → chunk-GHZFNAMF.mjs.map} +0 -0
- /package/dist/{chunk-U4F6BNGZ.mjs.map → chunk-OHFVX2HH.mjs.map} +0 -0
- /package/dist/{chunk-NSWFHMBZ.mjs.map → chunk-VTCZM2JS.mjs.map} +0 -0
- /package/dist/{chunk-S7YPBKQ3.mjs.map → chunk-XEGEOU2D.mjs.map} +0 -0
- /package/dist/{chunk-RHA534GU.mjs.map → chunk-YRCFDZ5Q.mjs.map} +0 -0
- /package/dist/{http-Y2WC2UK4.mjs.map → http-X55S6MTO.mjs.map} +0 -0
- /package/dist/{import-4HF2UNQI.mjs.map → import-4AX6IX57.mjs.map} +0 -0
- /package/dist/{mcp-DJPDRFTW.mjs.map → mcp-GWC52AWE.mjs.map} +0 -0
- /package/dist/{src-R7MZLKXQ.mjs.map → src-DLLM4SEO.mjs.map} +0 -0
- /package/dist/{stream-import-DX57ANUL.mjs.map → stream-import-K24HWAAZ.mjs.map} +0 -0
- /package/dist/{worker-runtime-QMN7OKOZ.mjs.map → worker-runtime-6KKR55TD.mjs.map} +0 -0
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
createEmptyContactsDiagnostics,
|
|
10
10
|
normalizeContactsTimeRangePreset,
|
|
11
11
|
resolveContactsTimeRange
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-GHZFNAMF.mjs";
|
|
13
13
|
import {
|
|
14
14
|
PEOPLE_RELATIONSHIPS_ALGORITHM_VERSION,
|
|
15
15
|
buildPeopleRelationshipsNeighborhoodGraph,
|
|
@@ -18,10 +18,10 @@ import {
|
|
|
18
18
|
computePeopleRelationshipsSnapshot,
|
|
19
19
|
normalizePeopleRelationshipsTimeRangePreset,
|
|
20
20
|
resolvePeopleRelationshipsTimeRange
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-XEGEOU2D.mjs";
|
|
22
22
|
import {
|
|
23
23
|
ANNUAL_SUMMARY_ALGORITHM_VERSION
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-QZCNVAH6.mjs";
|
|
25
25
|
import {
|
|
26
26
|
BUILTIN_MODELS,
|
|
27
27
|
BUILTIN_PROVIDERS,
|
|
@@ -51,11 +51,14 @@ import {
|
|
|
51
51
|
deleteAuthProfile,
|
|
52
52
|
deleteMember,
|
|
53
53
|
deleteMembers,
|
|
54
|
+
deriveAuthProfileName,
|
|
54
55
|
generateIncrementalSessionIndex,
|
|
55
56
|
generateMessageKey,
|
|
56
57
|
generateSessionIndex,
|
|
57
58
|
getAnnualSummarySnapshotPath,
|
|
59
|
+
getBuiltinModelById,
|
|
58
60
|
getBuiltinModelsByProvider,
|
|
61
|
+
getBuiltinProviderById,
|
|
59
62
|
getChatSessionList,
|
|
60
63
|
getContactsDir,
|
|
61
64
|
getContactsFactsCacheDir,
|
|
@@ -80,6 +83,7 @@ import {
|
|
|
80
83
|
isNameMatchPlatform,
|
|
81
84
|
isReasoningModel,
|
|
82
85
|
isSupportedChatLabFormatVersion,
|
|
86
|
+
loadAuthProfiles,
|
|
83
87
|
matchOwnerProfile,
|
|
84
88
|
mergeConfirmedNames,
|
|
85
89
|
mergeMembers,
|
|
@@ -88,6 +92,7 @@ import {
|
|
|
88
92
|
normalizeBuiltinToolNames,
|
|
89
93
|
openBetterSqliteDatabase,
|
|
90
94
|
readAnnualSummarySnapshot,
|
|
95
|
+
readJsonFile,
|
|
91
96
|
renameSession,
|
|
92
97
|
resolveApiKey,
|
|
93
98
|
saveSegmentSummary,
|
|
@@ -100,10 +105,12 @@ import {
|
|
|
100
105
|
truncateToolResultText,
|
|
101
106
|
updateMemberAliases,
|
|
102
107
|
updateSessionOwnerId,
|
|
108
|
+
withFileLock,
|
|
103
109
|
writeAnnualSummarySnapshot,
|
|
104
110
|
writeAuthProfile,
|
|
111
|
+
writeJsonFileAtomically,
|
|
105
112
|
writeParseResultToDb
|
|
106
|
-
} from "./chunk-
|
|
113
|
+
} from "./chunk-3RWYALUP.mjs";
|
|
107
114
|
import {
|
|
108
115
|
__commonJS,
|
|
109
116
|
__export,
|
|
@@ -1461,7 +1468,7 @@ var require_pend = __commonJS({
|
|
|
1461
1468
|
var require_fd_slicer = __commonJS({
|
|
1462
1469
|
"../../packages/node-runtime/node_modules/yauzl/fd-slicer.js"(exports) {
|
|
1463
1470
|
"use strict";
|
|
1464
|
-
var
|
|
1471
|
+
var fs36 = __require("fs");
|
|
1465
1472
|
var util = __require("util");
|
|
1466
1473
|
var stream = __require("stream");
|
|
1467
1474
|
var Readable = stream.Readable;
|
|
@@ -1481,7 +1488,7 @@ var require_fd_slicer = __commonJS({
|
|
|
1481
1488
|
FdSlicer.prototype.read = function(buffer, offset, length, position, callback) {
|
|
1482
1489
|
var self = this;
|
|
1483
1490
|
self.pend.go(function(cb) {
|
|
1484
|
-
|
|
1491
|
+
fs36.read(self.fd, buffer, offset, length, position, function(err, bytesRead, buffer2) {
|
|
1485
1492
|
cb();
|
|
1486
1493
|
callback(err, bytesRead, buffer2);
|
|
1487
1494
|
});
|
|
@@ -1498,7 +1505,7 @@ var require_fd_slicer = __commonJS({
|
|
|
1498
1505
|
self.refCount -= 1;
|
|
1499
1506
|
if (self.refCount < 0) throw new Error("invalid unref");
|
|
1500
1507
|
if (self.refCount > 0) return;
|
|
1501
|
-
|
|
1508
|
+
fs36.close(self.fd, onCloseDone);
|
|
1502
1509
|
function onCloseDone(err) {
|
|
1503
1510
|
if (err) {
|
|
1504
1511
|
self.emit("error", err);
|
|
@@ -1530,7 +1537,7 @@ var require_fd_slicer = __commonJS({
|
|
|
1530
1537
|
}
|
|
1531
1538
|
self.context.pend.go(function(cb) {
|
|
1532
1539
|
var buffer = Buffer.allocUnsafe(toRead);
|
|
1533
|
-
|
|
1540
|
+
fs36.read(self.context.fd, buffer, 0, toRead, self.pos, function(err, bytesRead) {
|
|
1534
1541
|
if (err) {
|
|
1535
1542
|
self.destroy(err);
|
|
1536
1543
|
} else if (bytesRead === 0) {
|
|
@@ -1892,7 +1899,7 @@ var require_crc32 = __commonJS({
|
|
|
1892
1899
|
var require_yauzl = __commonJS({
|
|
1893
1900
|
"../../packages/node-runtime/node_modules/yauzl/index.js"(exports) {
|
|
1894
1901
|
"use strict";
|
|
1895
|
-
var
|
|
1902
|
+
var fs36 = __require("fs");
|
|
1896
1903
|
var zlib = __require("zlib");
|
|
1897
1904
|
var fd_slicer = require_fd_slicer();
|
|
1898
1905
|
var util = __require("util");
|
|
@@ -1961,10 +1968,10 @@ var require_yauzl = __commonJS({
|
|
|
1961
1968
|
if (options2.validateEntrySizes == null) options2.validateEntrySizes = true;
|
|
1962
1969
|
if (options2.strictFileNames == null) options2.strictFileNames = false;
|
|
1963
1970
|
if (callback == null) callback = defaultCallback;
|
|
1964
|
-
|
|
1971
|
+
fs36.open(path30, "r", function(err, fd) {
|
|
1965
1972
|
if (err) return callback(err);
|
|
1966
1973
|
fromFd(fd, options2, function(err2, zipfile) {
|
|
1967
|
-
if (err2)
|
|
1974
|
+
if (err2) fs36.close(fd, defaultCallback);
|
|
1968
1975
|
callback(err2, zipfile);
|
|
1969
1976
|
});
|
|
1970
1977
|
});
|
|
@@ -1981,7 +1988,7 @@ var require_yauzl = __commonJS({
|
|
|
1981
1988
|
if (options2.validateEntrySizes == null) options2.validateEntrySizes = true;
|
|
1982
1989
|
if (options2.strictFileNames == null) options2.strictFileNames = false;
|
|
1983
1990
|
if (callback == null) callback = defaultCallback;
|
|
1984
|
-
|
|
1991
|
+
fs36.fstat(fd, function(err, stats) {
|
|
1985
1992
|
if (err) return callback(err);
|
|
1986
1993
|
var reader = new fd_slicer.FdSlicer(fd);
|
|
1987
1994
|
fromRandomAccessReader(reader, stats.size, options2, callback);
|
|
@@ -2840,6 +2847,14 @@ function matchFilenameSignatures(filePath, patterns) {
|
|
|
2840
2847
|
const filename = path2.basename(filePath);
|
|
2841
2848
|
return patterns.some((pattern) => pattern.test(filename));
|
|
2842
2849
|
}
|
|
2850
|
+
function matchFilenameFallbackPatterns(filePath, patterns) {
|
|
2851
|
+
try {
|
|
2852
|
+
const content = fs2.readFileSync(filePath, "utf-8");
|
|
2853
|
+
return patterns.every((pattern) => pattern.test(content));
|
|
2854
|
+
} catch {
|
|
2855
|
+
return false;
|
|
2856
|
+
}
|
|
2857
|
+
}
|
|
2843
2858
|
function matchRequiredFields(headContent, fields) {
|
|
2844
2859
|
return fields.every((field) => {
|
|
2845
2860
|
const pattern = new RegExp(`"${field.replace(".", '"\\s*:\\s*.*"')}"\\s*:`);
|
|
@@ -2961,6 +2976,11 @@ var FormatSniffer = class {
|
|
|
2961
2976
|
return false;
|
|
2962
2977
|
}
|
|
2963
2978
|
}
|
|
2979
|
+
if (!headMatch && filenameMatch && signatures.filenameFallbackPatterns) {
|
|
2980
|
+
if (!filePath || !matchFilenameFallbackPatterns(filePath, signatures.filenameFallbackPatterns)) {
|
|
2981
|
+
return false;
|
|
2982
|
+
}
|
|
2983
|
+
}
|
|
2964
2984
|
if (signatures.requiredFields && signatures.requiredFields.length > 0) {
|
|
2965
2985
|
if (!matchRequiredFields(headContent, signatures.requiredFields)) {
|
|
2966
2986
|
return false;
|
|
@@ -4082,8 +4102,10 @@ var feature4 = {
|
|
|
4082
4102
|
// 比单文件版本优先级更高
|
|
4083
4103
|
extensions: [".json"],
|
|
4084
4104
|
signatures: {
|
|
4085
|
-
// 使用
|
|
4086
|
-
head: [/"format"\s*:\s*"chunked-jsonl"/],
|
|
4105
|
+
// V5 使用 metadata.format,0.1.x 将格式标识移至 chunked.format。
|
|
4106
|
+
head: [/"format"\s*:\s*"chunked-jsonl"/, /"chunked"\s*:\s*\{[^{}]*"format"\s*:\s*"jsonl"/],
|
|
4107
|
+
filename: [/^manifest\.json$/i],
|
|
4108
|
+
filenameFallbackPatterns: [/"chunked"\s*:\s*\{[\s\S]*?"format"\s*:\s*"jsonl"/],
|
|
4087
4109
|
requiredFields: ["metadata", "chatInfo"]
|
|
4088
4110
|
}
|
|
4089
4111
|
};
|
|
@@ -4214,9 +4236,10 @@ async function* parseChunkedJsonl(options2) {
|
|
|
4214
4236
|
yield { type: "error", data: new Error(`\u65E0\u6CD5\u8BFB\u53D6 manifest.json: ${errorMsg}`) };
|
|
4215
4237
|
return;
|
|
4216
4238
|
}
|
|
4217
|
-
if (manifest.metadata.format !== "chunked-jsonl") {
|
|
4218
|
-
|
|
4219
|
-
|
|
4239
|
+
if (manifest.metadata.format !== "chunked-jsonl" && manifest.chunked.format !== "jsonl") {
|
|
4240
|
+
const format = manifest.metadata.format ?? manifest.chunked.format ?? "unknown";
|
|
4241
|
+
onLog?.("error", `\u4E0D\u652F\u6301\u7684\u683C\u5F0F: ${format}`);
|
|
4242
|
+
yield { type: "error", data: new Error(`\u4E0D\u652F\u6301\u7684\u683C\u5F0F: ${format}`) };
|
|
4220
4243
|
return;
|
|
4221
4244
|
}
|
|
4222
4245
|
const totalBytes = calculateTotalBytes(manifest, baseDir);
|
|
@@ -6736,6 +6759,8 @@ var MAX_UNIX_SECONDS = 1e11;
|
|
|
6736
6759
|
var KNOWN_MESSAGE_TYPES = new Set(
|
|
6737
6760
|
Object.values(MessageType).filter((value) => typeof value === "number")
|
|
6738
6761
|
);
|
|
6762
|
+
var SYSTEM_SENDER_ID = "SYSTEM";
|
|
6763
|
+
var SYSTEM_SENDER_MESSAGE_TYPES = /* @__PURE__ */ new Set([80 /* SYSTEM */, 81 /* RECALL */]);
|
|
6739
6764
|
function createState(format, fileSize) {
|
|
6740
6765
|
return {
|
|
6741
6766
|
format,
|
|
@@ -6910,8 +6935,9 @@ function validateMessage(state, value, path30, location) {
|
|
|
6910
6935
|
addIssue(state, "error", "INVALID_MESSAGE", "Expected a message object.", childLocation(location, path30));
|
|
6911
6936
|
return;
|
|
6912
6937
|
}
|
|
6913
|
-
|
|
6914
|
-
|
|
6938
|
+
const sender = validateRequiredString(state, value.sender, `${path30}.sender`, location) ? value.sender : void 0;
|
|
6939
|
+
if (sender !== void 0) {
|
|
6940
|
+
state.senderIds.add(sender);
|
|
6915
6941
|
}
|
|
6916
6942
|
validateRequiredString(state, value.accountName, `${path30}.accountName`, location);
|
|
6917
6943
|
if (validateUnixSeconds(state, value.timestamp, `${path30}.timestamp`, location)) {
|
|
@@ -6926,11 +6952,20 @@ function validateMessage(state, value, path30, location) {
|
|
|
6926
6952
|
}
|
|
6927
6953
|
state.lastTimestamp = value.timestamp;
|
|
6928
6954
|
}
|
|
6929
|
-
|
|
6955
|
+
const messageType = typeof value.type === "number" && Number.isInteger(value.type) && KNOWN_MESSAGE_TYPES.has(value.type) ? value.type : void 0;
|
|
6956
|
+
if (messageType === void 0) {
|
|
6930
6957
|
addIssue(state, "error", "INVALID_MESSAGE_TYPE", "Expected a supported numeric ChatLab message type.", {
|
|
6931
6958
|
...location,
|
|
6932
6959
|
path: `${path30}.type`
|
|
6933
6960
|
});
|
|
6961
|
+
} else if (sender === SYSTEM_SENDER_ID && !SYSTEM_SENDER_MESSAGE_TYPES.has(messageType)) {
|
|
6962
|
+
addIssue(
|
|
6963
|
+
state,
|
|
6964
|
+
"error",
|
|
6965
|
+
"INVALID_SYSTEM_SENDER_TYPE",
|
|
6966
|
+
"The reserved SYSTEM sender is only valid for system and recall messages.",
|
|
6967
|
+
childLocation(location, `${path30}.sender`)
|
|
6968
|
+
);
|
|
6934
6969
|
}
|
|
6935
6970
|
if (!hasOwn(value, "content") || typeof value.content !== "string" && value.content !== null) {
|
|
6936
6971
|
addIssue(state, "error", "INVALID_MESSAGE_CONTENT", "Expected content to be a string or null.", {
|
|
@@ -6979,7 +7014,7 @@ function finalizeState(state, requireExplicitMembers, enforceRequiredSections =
|
|
|
6979
7014
|
}
|
|
6980
7015
|
if (state.memberIds.size > 0) {
|
|
6981
7016
|
for (const senderId of state.senderIds) {
|
|
6982
|
-
if (!state.memberIds.has(senderId)) {
|
|
7017
|
+
if (senderId !== SYSTEM_SENDER_ID && !state.memberIds.has(senderId)) {
|
|
6983
7018
|
addIssue(
|
|
6984
7019
|
state,
|
|
6985
7020
|
"error",
|
|
@@ -7118,6 +7153,154 @@ async function validateChatLabFile(filePath) {
|
|
|
7118
7153
|
return finalizeState(state, false, false);
|
|
7119
7154
|
}
|
|
7120
7155
|
|
|
7156
|
+
// ../../packages/parser/src/chatlab-demo-timeline.ts
|
|
7157
|
+
var SECONDS_PER_MINUTE = 60;
|
|
7158
|
+
var DEFAULT_DEMO_TIME_ZONE_OFFSET_MINUTES = 8 * 60;
|
|
7159
|
+
var MAX_TIME_ZONE_OFFSET_MINUTES = 14 * 60;
|
|
7160
|
+
function rebaseChatLabDemoDocuments(jsonDocuments, now = /* @__PURE__ */ new Date(), targetTimeZone) {
|
|
7161
|
+
if (jsonDocuments.length === 0) throw new Error("Demo timeline requires at least one document");
|
|
7162
|
+
if (!Number.isFinite(now.getTime())) throw new Error("Demo timeline requires a valid import time");
|
|
7163
|
+
const documents = jsonDocuments.map((json, index) => parseDemoDocument(json, index));
|
|
7164
|
+
const timeZoneOffsetMinutes = resolveTimeZoneOffsetMinutes(documents);
|
|
7165
|
+
const sourceLatestTimestamp = Math.max(
|
|
7166
|
+
...documents.flatMap((document) => document.messages.map((message) => message.timestamp))
|
|
7167
|
+
);
|
|
7168
|
+
const sourceLatestWallTime = new Date((sourceLatestTimestamp + timeZoneOffsetMinutes * SECONDS_PER_MINUTE) * 1e3);
|
|
7169
|
+
const latestTimestamp = resolveTargetLatestTimestamp(now, sourceLatestWallTime, targetTimeZone);
|
|
7170
|
+
const offsetSeconds = latestTimestamp - sourceLatestTimestamp;
|
|
7171
|
+
const exportedAt = Math.floor(now.getTime() / 1e3);
|
|
7172
|
+
for (const document of documents) {
|
|
7173
|
+
document.chatlab.exportedAt = exportedAt;
|
|
7174
|
+
for (const message of document.messages) {
|
|
7175
|
+
message.timestamp += offsetSeconds;
|
|
7176
|
+
}
|
|
7177
|
+
}
|
|
7178
|
+
return {
|
|
7179
|
+
documents: documents.map((document) => JSON.stringify(document)),
|
|
7180
|
+
offsetSeconds,
|
|
7181
|
+
latestTimestamp
|
|
7182
|
+
};
|
|
7183
|
+
}
|
|
7184
|
+
function resolveTargetLatestTimestamp(now, sourceWallTime, targetTimeZone) {
|
|
7185
|
+
if (!targetTimeZone) {
|
|
7186
|
+
const targetLatestTime = new Date(now);
|
|
7187
|
+
targetLatestTime.setDate(targetLatestTime.getDate() - 1);
|
|
7188
|
+
targetLatestTime.setHours(
|
|
7189
|
+
sourceWallTime.getUTCHours(),
|
|
7190
|
+
sourceWallTime.getUTCMinutes(),
|
|
7191
|
+
sourceWallTime.getUTCSeconds(),
|
|
7192
|
+
0
|
|
7193
|
+
);
|
|
7194
|
+
return Math.floor(targetLatestTime.getTime() / 1e3);
|
|
7195
|
+
}
|
|
7196
|
+
let formatter;
|
|
7197
|
+
try {
|
|
7198
|
+
formatter = new Intl.DateTimeFormat("en-US-u-ca-gregory-nu-latn", {
|
|
7199
|
+
timeZone: targetTimeZone,
|
|
7200
|
+
year: "numeric",
|
|
7201
|
+
month: "2-digit",
|
|
7202
|
+
day: "2-digit",
|
|
7203
|
+
hour: "2-digit",
|
|
7204
|
+
minute: "2-digit",
|
|
7205
|
+
second: "2-digit",
|
|
7206
|
+
hourCycle: "h23"
|
|
7207
|
+
});
|
|
7208
|
+
} catch {
|
|
7209
|
+
throw new Error("Demo timeline has an invalid target time zone");
|
|
7210
|
+
}
|
|
7211
|
+
const currentDate = getZonedDateTimeParts(now, formatter);
|
|
7212
|
+
const yesterday = new Date(Date.UTC(currentDate.year, currentDate.month - 1, currentDate.day - 1));
|
|
7213
|
+
const targetParts = {
|
|
7214
|
+
year: yesterday.getUTCFullYear(),
|
|
7215
|
+
month: yesterday.getUTCMonth() + 1,
|
|
7216
|
+
day: yesterday.getUTCDate(),
|
|
7217
|
+
hour: sourceWallTime.getUTCHours(),
|
|
7218
|
+
minute: sourceWallTime.getUTCMinutes(),
|
|
7219
|
+
second: sourceWallTime.getUTCSeconds()
|
|
7220
|
+
};
|
|
7221
|
+
return Math.floor(zonedWallTimeToUnixMillis(targetParts, formatter) / 1e3);
|
|
7222
|
+
}
|
|
7223
|
+
function getZonedDateTimeParts(date, formatter) {
|
|
7224
|
+
const values = new Map(formatter.formatToParts(date).map((part) => [part.type, part.value]));
|
|
7225
|
+
const read = (type) => Number(values.get(type));
|
|
7226
|
+
const parts = {
|
|
7227
|
+
year: read("year"),
|
|
7228
|
+
month: read("month"),
|
|
7229
|
+
day: read("day"),
|
|
7230
|
+
hour: read("hour"),
|
|
7231
|
+
minute: read("minute"),
|
|
7232
|
+
second: read("second")
|
|
7233
|
+
};
|
|
7234
|
+
if (Object.values(parts).some((value) => !Number.isInteger(value))) {
|
|
7235
|
+
throw new Error("Demo timeline could not resolve the target time zone");
|
|
7236
|
+
}
|
|
7237
|
+
return parts;
|
|
7238
|
+
}
|
|
7239
|
+
function zonedWallTimeToUnixMillis(target, formatter) {
|
|
7240
|
+
const targetAsUtc = dateTimePartsToUtcMillis(target);
|
|
7241
|
+
let candidate = targetAsUtc;
|
|
7242
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
7243
|
+
const actual2 = getZonedDateTimeParts(new Date(candidate), formatter);
|
|
7244
|
+
const correction = targetAsUtc - dateTimePartsToUtcMillis(actual2);
|
|
7245
|
+
candidate += correction;
|
|
7246
|
+
if (correction === 0) return candidate;
|
|
7247
|
+
}
|
|
7248
|
+
const actual = getZonedDateTimeParts(new Date(candidate), formatter);
|
|
7249
|
+
if (dateTimePartsToUtcMillis(actual) !== targetAsUtc) {
|
|
7250
|
+
throw new Error("Demo timeline target wall time does not exist in the selected time zone");
|
|
7251
|
+
}
|
|
7252
|
+
return candidate;
|
|
7253
|
+
}
|
|
7254
|
+
function dateTimePartsToUtcMillis(parts) {
|
|
7255
|
+
return Date.UTC(parts.year, parts.month - 1, parts.day, parts.hour, parts.minute, parts.second);
|
|
7256
|
+
}
|
|
7257
|
+
function parseDemoDocument(json, index) {
|
|
7258
|
+
let value;
|
|
7259
|
+
try {
|
|
7260
|
+
value = JSON.parse(json);
|
|
7261
|
+
} catch {
|
|
7262
|
+
throw new Error(`Demo document ${index + 1} is not valid JSON`);
|
|
7263
|
+
}
|
|
7264
|
+
if (!isRecord2(value) || !isRecord2(value.chatlab) || !Array.isArray(value.messages)) {
|
|
7265
|
+
throw new Error(`Demo document ${index + 1} is not a ChatLab JSON document`);
|
|
7266
|
+
}
|
|
7267
|
+
if (value.messages.length === 0) {
|
|
7268
|
+
throw new Error(`Demo document ${index + 1} has no messages`);
|
|
7269
|
+
}
|
|
7270
|
+
const messages = value.messages.map((message, messageIndex) => {
|
|
7271
|
+
if (!isRecord2(message) || !isUnixSeconds(message.timestamp)) {
|
|
7272
|
+
throw new Error(`Demo document ${index + 1} has an invalid timestamp at message ${messageIndex + 1}`);
|
|
7273
|
+
}
|
|
7274
|
+
return message;
|
|
7275
|
+
});
|
|
7276
|
+
return {
|
|
7277
|
+
...value,
|
|
7278
|
+
chatlab: value.chatlab,
|
|
7279
|
+
messages
|
|
7280
|
+
};
|
|
7281
|
+
}
|
|
7282
|
+
function resolveTimeZoneOffsetMinutes(documents) {
|
|
7283
|
+
const offsets = /* @__PURE__ */ new Set();
|
|
7284
|
+
for (const document of documents) {
|
|
7285
|
+
const configured = document.chatlab.demoTimeline?.timeZoneOffsetMinutes;
|
|
7286
|
+
const offset = configured ?? DEFAULT_DEMO_TIME_ZONE_OFFSET_MINUTES;
|
|
7287
|
+
if (typeof offset !== "number" || !Number.isInteger(offset) || Math.abs(offset) > MAX_TIME_ZONE_OFFSET_MINUTES) {
|
|
7288
|
+
throw new Error("Demo timeline has an invalid time zone offset");
|
|
7289
|
+
}
|
|
7290
|
+
offsets.add(offset);
|
|
7291
|
+
}
|
|
7292
|
+
if (offsets.size !== 1) {
|
|
7293
|
+
throw new Error("Demo documents must use the same time zone offset");
|
|
7294
|
+
}
|
|
7295
|
+
return offsets.values().next().value;
|
|
7296
|
+
}
|
|
7297
|
+
function isUnixSeconds(value) {
|
|
7298
|
+
return typeof value === "number" && Number.isInteger(value) && value >= 0;
|
|
7299
|
+
}
|
|
7300
|
+
function isRecord2(value) {
|
|
7301
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7302
|
+
}
|
|
7303
|
+
|
|
7121
7304
|
// ../../packages/parser/src/index.ts
|
|
7122
7305
|
var sniffer = createSniffer();
|
|
7123
7306
|
sniffer.registerAll(formats);
|
|
@@ -7681,15 +7864,21 @@ function registerMessageAndCheckDuplicate(message, state) {
|
|
|
7681
7864
|
// ../../packages/node-runtime/src/import/streaming-importer.ts
|
|
7682
7865
|
var BATCH_COMMIT_SIZE = 5e4;
|
|
7683
7866
|
var CHECKPOINT_INTERVAL = 2e5;
|
|
7867
|
+
var SYSTEM_SENDER_ID2 = "SYSTEM";
|
|
7868
|
+
var SYSTEM_MEMBER_NAME = "\u7CFB\u7EDF\u6D88\u606F";
|
|
7869
|
+
var RESERVED_SYSTEM_SENDER_FORMATS = /* @__PURE__ */ new Set(["chatlab", "chatlab-jsonl"]);
|
|
7684
7870
|
var yieldToEventLoop = () => new Promise((resolve4) => setImmediate(resolve4));
|
|
7685
7871
|
function defaultGenerateSessionId() {
|
|
7686
7872
|
const ts = Date.now();
|
|
7687
7873
|
const rand = Math.random().toString(36).substring(2, 8);
|
|
7688
7874
|
return `chat_${ts}_${rand}`;
|
|
7689
7875
|
}
|
|
7690
|
-
function
|
|
7876
|
+
function normalizeSystemMemberName(formatId, platformId, name) {
|
|
7877
|
+
return RESERVED_SYSTEM_SENDER_FORMATS.has(formatId) && platformId === SYSTEM_SENDER_ID2 ? SYSTEM_MEMBER_NAME : name;
|
|
7878
|
+
}
|
|
7879
|
+
function prepareMessageForCreate(message, senderAccountName = message.senderAccountName) {
|
|
7691
7880
|
if (!message.senderPlatformId) return { skipCounter: "skippedNoSenderId" };
|
|
7692
|
-
if (!
|
|
7881
|
+
if (!senderAccountName) return { skipCounter: "skippedNoAccountName" };
|
|
7693
7882
|
if (message.timestamp === void 0 || message.timestamp === null || isNaN(message.timestamp)) {
|
|
7694
7883
|
return { skipCounter: "skippedInvalidTimestamp" };
|
|
7695
7884
|
}
|
|
@@ -7903,10 +8092,12 @@ async function streamImportSingle(filePath, deps, formatFeature, formatOptions,
|
|
|
7903
8092
|
callbackStats.totalMembersReceived += members.length;
|
|
7904
8093
|
logger?.info(`Received member batch: ${members.length} members`);
|
|
7905
8094
|
for (const member of members) {
|
|
8095
|
+
const accountName = normalizeSystemMemberName(formatFeature.id, member.platformId, member.accountName);
|
|
8096
|
+
const groupNickname = normalizeSystemMemberName(formatFeature.id, member.platformId, member.groupNickname);
|
|
7906
8097
|
insertMember.run(
|
|
7907
8098
|
member.platformId,
|
|
7908
|
-
|
|
7909
|
-
|
|
8099
|
+
accountName || null,
|
|
8100
|
+
groupNickname || null,
|
|
7910
8101
|
member.aliases ? JSON.stringify(member.aliases) : "[]",
|
|
7911
8102
|
member.avatar || null,
|
|
7912
8103
|
member.roles ? JSON.stringify(member.roles) : "[]"
|
|
@@ -7929,7 +8120,17 @@ async function streamImportSingle(filePath, deps, formatFeature, formatOptions,
|
|
|
7929
8120
|
let memberInsertCount = 0;
|
|
7930
8121
|
let nicknameChangeCount = 0;
|
|
7931
8122
|
for (const msg of messages) {
|
|
7932
|
-
const
|
|
8123
|
+
const senderAccountName = normalizeSystemMemberName(
|
|
8124
|
+
formatFeature.id,
|
|
8125
|
+
msg.senderPlatformId,
|
|
8126
|
+
msg.senderAccountName
|
|
8127
|
+
);
|
|
8128
|
+
const senderGroupNickname = normalizeSystemMemberName(
|
|
8129
|
+
formatFeature.id,
|
|
8130
|
+
msg.senderPlatformId,
|
|
8131
|
+
msg.senderGroupNickname
|
|
8132
|
+
);
|
|
8133
|
+
const prepared = prepareMessageForCreate(msg, senderAccountName);
|
|
7933
8134
|
if ("skipCounter" in prepared) {
|
|
7934
8135
|
callbackStats[prepared.skipCounter]++;
|
|
7935
8136
|
continue;
|
|
@@ -7943,8 +8144,8 @@ async function streamImportSingle(filePath, deps, formatFeature, formatOptions,
|
|
|
7943
8144
|
if (!memberIdMap.has(msg.senderPlatformId)) {
|
|
7944
8145
|
insertMember.run(
|
|
7945
8146
|
msg.senderPlatformId,
|
|
7946
|
-
|
|
7947
|
-
|
|
8147
|
+
senderAccountName || null,
|
|
8148
|
+
senderGroupNickname || null,
|
|
7948
8149
|
"[]",
|
|
7949
8150
|
null,
|
|
7950
8151
|
"[]"
|
|
@@ -7962,8 +8163,8 @@ async function streamImportSingle(filePath, deps, formatFeature, formatOptions,
|
|
|
7962
8163
|
t0 = Date.now();
|
|
7963
8164
|
insertMessage.run(
|
|
7964
8165
|
senderId,
|
|
7965
|
-
|
|
7966
|
-
|
|
8166
|
+
senderAccountName || null,
|
|
8167
|
+
senderGroupNickname || null,
|
|
7967
8168
|
dedupMessage.timestamp,
|
|
7968
8169
|
dedupMessage.type,
|
|
7969
8170
|
dedupMessage.content,
|
|
@@ -7974,8 +8175,8 @@ async function streamImportSingle(filePath, deps, formatFeature, formatOptions,
|
|
|
7974
8175
|
messageCountInBatch++;
|
|
7975
8176
|
totalMessageCount++;
|
|
7976
8177
|
t0 = Date.now();
|
|
7977
|
-
trackNickname(accountNameTracker, msg.senderPlatformId,
|
|
7978
|
-
trackNickname(groupNicknameTracker, msg.senderPlatformId,
|
|
8178
|
+
trackNickname(accountNameTracker, msg.senderPlatformId, senderAccountName, msg.timestamp);
|
|
8179
|
+
trackNickname(groupNicknameTracker, msg.senderPlatformId, senderGroupNickname, msg.timestamp);
|
|
7979
8180
|
nicknameTrackTime += Date.now() - t0;
|
|
7980
8181
|
nicknameChangeCount += accountNameTracker.get(msg.senderPlatformId)?.history.length === 1 ? 0 : 0;
|
|
7981
8182
|
if (messageCountInBatch >= BATCH_COMMIT_SIZE) {
|
|
@@ -8506,10 +8707,12 @@ async function incrementalImport(sessionId, filePath, deps, options2) {
|
|
|
8506
8707
|
if (memberUpdateMode === "none") return;
|
|
8507
8708
|
for (const m of members) {
|
|
8508
8709
|
const existed = memberIdMap.has(m.platformId);
|
|
8710
|
+
const accountName = normalizeSystemMemberName(formatFeature.id, m.platformId, m.accountName);
|
|
8711
|
+
const groupNickname = normalizeSystemMemberName(formatFeature.id, m.platformId, m.groupNickname);
|
|
8509
8712
|
upsertMember.run(
|
|
8510
8713
|
m.platformId,
|
|
8511
|
-
|
|
8512
|
-
|
|
8714
|
+
accountName || null,
|
|
8715
|
+
groupNickname || null,
|
|
8513
8716
|
m.aliases ? JSON.stringify(m.aliases) : "[]",
|
|
8514
8717
|
m.avatar || null,
|
|
8515
8718
|
m.roles ? JSON.stringify(m.roles) : "[]"
|
|
@@ -8546,12 +8749,22 @@ async function incrementalImport(sessionId, filePath, deps, options2) {
|
|
|
8546
8749
|
duplicateCount++;
|
|
8547
8750
|
continue;
|
|
8548
8751
|
}
|
|
8752
|
+
const senderAccountName = normalizeSystemMemberName(
|
|
8753
|
+
formatFeature.id,
|
|
8754
|
+
msg.senderPlatformId,
|
|
8755
|
+
msg.senderAccountName
|
|
8756
|
+
);
|
|
8757
|
+
const senderGroupNickname = normalizeSystemMemberName(
|
|
8758
|
+
formatFeature.id,
|
|
8759
|
+
msg.senderPlatformId,
|
|
8760
|
+
msg.senderGroupNickname
|
|
8761
|
+
);
|
|
8549
8762
|
let memberId = memberIdMap.get(msg.senderPlatformId);
|
|
8550
8763
|
if (!memberId) {
|
|
8551
8764
|
insertMemberMinimal.run(
|
|
8552
8765
|
msg.senderPlatformId,
|
|
8553
|
-
|
|
8554
|
-
|
|
8766
|
+
senderAccountName || null,
|
|
8767
|
+
senderGroupNickname || null,
|
|
8555
8768
|
null
|
|
8556
8769
|
);
|
|
8557
8770
|
const row = getMemberId.get(msg.senderPlatformId);
|
|
@@ -8564,8 +8777,8 @@ async function incrementalImport(sessionId, filePath, deps, options2) {
|
|
|
8564
8777
|
if (!memberId) continue;
|
|
8565
8778
|
const msgResult = insertMessage.run(
|
|
8566
8779
|
memberId,
|
|
8567
|
-
|
|
8568
|
-
|
|
8780
|
+
senderAccountName || null,
|
|
8781
|
+
senderGroupNickname || null,
|
|
8569
8782
|
timestamp,
|
|
8570
8783
|
msg.type,
|
|
8571
8784
|
msg.content || null,
|
|
@@ -8620,7 +8833,7 @@ async function incrementalImport(sessionId, filePath, deps, options2) {
|
|
|
8620
8833
|
MAX(ts) as lastTimestamp
|
|
8621
8834
|
FROM message`
|
|
8622
8835
|
).get();
|
|
8623
|
-
const memberCountRow = db.prepare(
|
|
8836
|
+
const memberCountRow = db.prepare(`SELECT COUNT(*) as count FROM member WHERE COALESCE(account_name, '') != ?`).get(SYSTEM_MEMBER_NAME);
|
|
8624
8837
|
try {
|
|
8625
8838
|
await deps.postImportHook?.(db, sessionId);
|
|
8626
8839
|
} catch {
|
|
@@ -9751,8 +9964,8 @@ var AssistantManager = class {
|
|
|
9751
9964
|
}
|
|
9752
9965
|
// ==================== Init ====================
|
|
9753
9966
|
init() {
|
|
9754
|
-
const { fs:
|
|
9755
|
-
|
|
9967
|
+
const { fs: fs36, assistantsDir } = this.deps;
|
|
9968
|
+
fs36.ensureDir(assistantsDir);
|
|
9756
9969
|
const { generalCreated, generalUpdated } = this.syncGeneralAssistants();
|
|
9757
9970
|
this.loadAll();
|
|
9758
9971
|
this.initialized = true;
|
|
@@ -9764,25 +9977,25 @@ var AssistantManager = class {
|
|
|
9764
9977
|
return { total: this.cache.size, generalCreated, generalUpdated };
|
|
9765
9978
|
}
|
|
9766
9979
|
syncGeneralAssistants() {
|
|
9767
|
-
const { fs:
|
|
9980
|
+
const { fs: fs36, assistantsDir } = this.deps;
|
|
9768
9981
|
let generalCreated = false;
|
|
9769
9982
|
let generalUpdated = false;
|
|
9770
9983
|
for (const id of this.generalIds) {
|
|
9771
9984
|
const config = this.getBuiltinConfig(id);
|
|
9772
9985
|
if (!config) continue;
|
|
9773
|
-
const filePath =
|
|
9774
|
-
if (!
|
|
9775
|
-
|
|
9986
|
+
const filePath = fs36.joinPath(assistantsDir, `${id}.md`);
|
|
9987
|
+
if (!fs36.fileExists(filePath)) {
|
|
9988
|
+
fs36.writeFile(filePath, serializeAssistant(this.withBuiltinTracking(config)));
|
|
9776
9989
|
generalCreated = true;
|
|
9777
9990
|
continue;
|
|
9778
9991
|
}
|
|
9779
9992
|
try {
|
|
9780
|
-
const existing = parseAssistantFile(
|
|
9993
|
+
const existing = parseAssistantFile(fs36.readFile(filePath), filePath);
|
|
9781
9994
|
if (!existing) continue;
|
|
9782
9995
|
if (existing.builtinId !== id) {
|
|
9783
9996
|
try {
|
|
9784
9997
|
const backupId = this.backupAssistantOccupyingReservedId(existing);
|
|
9785
|
-
|
|
9998
|
+
fs36.writeFile(filePath, serializeAssistant(this.withBuiltinTracking(config)));
|
|
9786
9999
|
generalCreated = true;
|
|
9787
10000
|
this.deps.logger?.info("AssistantManager", "Backed up assistant occupying reserved default ID", {
|
|
9788
10001
|
reservedId: id,
|
|
@@ -9798,7 +10011,7 @@ var AssistantManager = class {
|
|
|
9798
10011
|
continue;
|
|
9799
10012
|
}
|
|
9800
10013
|
if (!this.shouldUpgradeBuiltin(existing, config)) continue;
|
|
9801
|
-
|
|
10014
|
+
fs36.writeFile(filePath, serializeAssistant(this.withBuiltinTracking(config, existing.id)));
|
|
9802
10015
|
generalUpdated = true;
|
|
9803
10016
|
this.deps.logger?.info("AssistantManager", "Updated unmodified default assistant template", {
|
|
9804
10017
|
id,
|
|
@@ -9814,14 +10027,14 @@ var AssistantManager = class {
|
|
|
9814
10027
|
return { generalCreated, generalUpdated };
|
|
9815
10028
|
}
|
|
9816
10029
|
backupAssistantOccupyingReservedId(config) {
|
|
9817
|
-
const { fs:
|
|
10030
|
+
const { fs: fs36, assistantsDir } = this.deps;
|
|
9818
10031
|
const baseId = this.deps.generateId?.() || `custom_${Date.now().toString(36)}`;
|
|
9819
10032
|
let backupId = baseId;
|
|
9820
10033
|
let suffix = 2;
|
|
9821
|
-
while (this.generalIds.includes(backupId) ||
|
|
10034
|
+
while (this.generalIds.includes(backupId) || fs36.fileExists(fs36.joinPath(assistantsDir, `${backupId}.md`))) {
|
|
9822
10035
|
backupId = `${baseId}_${suffix++}`;
|
|
9823
10036
|
}
|
|
9824
|
-
|
|
10037
|
+
fs36.writeFile(fs36.joinPath(assistantsDir, `${backupId}.md`), serializeAssistant({ ...config, id: backupId }));
|
|
9825
10038
|
return backupId;
|
|
9826
10039
|
}
|
|
9827
10040
|
getConfigDigest(config) {
|
|
@@ -9858,13 +10071,13 @@ var AssistantManager = class {
|
|
|
9858
10071
|
return { isUnmodified, isOutdated };
|
|
9859
10072
|
}
|
|
9860
10073
|
loadAll() {
|
|
9861
|
-
const { fs:
|
|
10074
|
+
const { fs: fs36, assistantsDir } = this.deps;
|
|
9862
10075
|
this.cache.clear();
|
|
9863
|
-
const files =
|
|
10076
|
+
const files = fs36.listFiles(assistantsDir, ".md");
|
|
9864
10077
|
for (const file of files) {
|
|
9865
10078
|
try {
|
|
9866
|
-
const filePath =
|
|
9867
|
-
const content =
|
|
10079
|
+
const filePath = fs36.joinPath(assistantsDir, file);
|
|
10080
|
+
const content = fs36.readFile(filePath);
|
|
9868
10081
|
const config = parseAssistantFile(content, filePath);
|
|
9869
10082
|
if (config) {
|
|
9870
10083
|
this.cache.set(config.id, config);
|
|
@@ -10933,21 +11146,21 @@ var SkillManagerCore = class {
|
|
|
10933
11146
|
}
|
|
10934
11147
|
// ==================== Init ====================
|
|
10935
11148
|
init() {
|
|
10936
|
-
const { fs:
|
|
10937
|
-
|
|
11149
|
+
const { fs: fs36, skillsDir } = this.deps;
|
|
11150
|
+
fs36.ensureDir(skillsDir);
|
|
10938
11151
|
this.loadAll();
|
|
10939
11152
|
this.initialized = true;
|
|
10940
11153
|
this.deps.logger?.info("SkillManager", "Initialized", { total: this.cache.size });
|
|
10941
11154
|
return { total: this.cache.size };
|
|
10942
11155
|
}
|
|
10943
11156
|
loadAll() {
|
|
10944
|
-
const { fs:
|
|
11157
|
+
const { fs: fs36, skillsDir } = this.deps;
|
|
10945
11158
|
this.cache.clear();
|
|
10946
|
-
const files =
|
|
11159
|
+
const files = fs36.listFiles(skillsDir, ".md");
|
|
10947
11160
|
for (const file of files) {
|
|
10948
11161
|
try {
|
|
10949
|
-
const filePath =
|
|
10950
|
-
const content =
|
|
11162
|
+
const filePath = fs36.joinPath(skillsDir, file);
|
|
11163
|
+
const content = fs36.readFile(filePath);
|
|
10951
11164
|
const def = parseSkillFile(content, filePath);
|
|
10952
11165
|
if (def) {
|
|
10953
11166
|
this.cache.set(def.id, def);
|
|
@@ -13001,7 +13214,7 @@ var PLAN_INTENTS = [
|
|
|
13001
13214
|
"mixed"
|
|
13002
13215
|
];
|
|
13003
13216
|
var STREAM_MARKER_HOLDBACK_CHARS = Math.max("</draft>".length, "</plan>".length, "<json>".length) - 1;
|
|
13004
|
-
function
|
|
13217
|
+
function isRecord3(value) {
|
|
13005
13218
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
13006
13219
|
}
|
|
13007
13220
|
function isIntent(value) {
|
|
@@ -13023,10 +13236,10 @@ function extractJsonObject4(text) {
|
|
|
13023
13236
|
function parsePlanJson(rawText, availableTools) {
|
|
13024
13237
|
try {
|
|
13025
13238
|
const parsed = JSON.parse(extractJsonObject4(rawText));
|
|
13026
|
-
if (!
|
|
13239
|
+
if (!isRecord3(parsed)) return null;
|
|
13027
13240
|
const title = normalizeString(parsed.title);
|
|
13028
13241
|
if (!title || !isIntent(parsed.intent) || !Array.isArray(parsed.steps)) return null;
|
|
13029
|
-
const steps = parsed.steps.filter(
|
|
13242
|
+
const steps = parsed.steps.filter(isRecord3).map((step) => {
|
|
13030
13243
|
const goal = normalizeString(step.goal);
|
|
13031
13244
|
const evidenceNeeded = normalizeString(step.evidenceNeeded);
|
|
13032
13245
|
if (!goal || !evidenceNeeded) return null;
|
|
@@ -15353,19 +15566,26 @@ var LLMConfigStore = class {
|
|
|
15353
15566
|
this.resolveApiKey = deps.resolveApiKey;
|
|
15354
15567
|
this.onStoreLoaded = deps.onStoreLoaded;
|
|
15355
15568
|
}
|
|
15569
|
+
withStoreLock(action) {
|
|
15570
|
+
return this.storage.withLock ? this.storage.withLock("llm-config", action) : action();
|
|
15571
|
+
}
|
|
15356
15572
|
loadStore() {
|
|
15357
15573
|
const store = this.storage.readJson("llm-config");
|
|
15358
15574
|
if (!store) {
|
|
15359
15575
|
return { configs: [], defaultAssistant: null, fastModel: null };
|
|
15360
15576
|
}
|
|
15361
15577
|
this.onStoreLoaded?.(store.configs);
|
|
15362
|
-
const
|
|
15578
|
+
const sanitizedConfigs = store.configs.map((config) => ({
|
|
15579
|
+
...config,
|
|
15580
|
+
apiKey: config.apiKey?.startsWith("enc:") ? "" : config.apiKey || ""
|
|
15581
|
+
}));
|
|
15582
|
+
const resolvedConfigs = this.resolveApiKey ? sanitizedConfigs.map((config) => {
|
|
15363
15583
|
const profileKey = this.resolveApiKey(
|
|
15364
15584
|
config.provider,
|
|
15365
15585
|
config.authProfile
|
|
15366
15586
|
);
|
|
15367
|
-
return { ...config, apiKey: profileKey || config.apiKey
|
|
15368
|
-
}) :
|
|
15587
|
+
return { ...config, apiKey: profileKey || config.apiKey };
|
|
15588
|
+
}) : sanitizedConfigs;
|
|
15369
15589
|
return {
|
|
15370
15590
|
...store,
|
|
15371
15591
|
configs: resolvedConfigs,
|
|
@@ -15417,103 +15637,113 @@ var LLMConfigStore = class {
|
|
|
15417
15637
|
return store.configs.find((c) => c.id === id) || null;
|
|
15418
15638
|
}
|
|
15419
15639
|
addConfig(config) {
|
|
15420
|
-
|
|
15421
|
-
|
|
15422
|
-
|
|
15423
|
-
|
|
15424
|
-
const now = Date.now();
|
|
15425
|
-
const newConfig = {
|
|
15426
|
-
...config,
|
|
15427
|
-
id: this.generateId(),
|
|
15428
|
-
createdAt: now,
|
|
15429
|
-
updatedAt: now
|
|
15430
|
-
};
|
|
15431
|
-
store.configs.push(newConfig);
|
|
15432
|
-
if (store.configs.length === 1) {
|
|
15433
|
-
store.defaultAssistant = { configId: newConfig.id, modelId: newConfig.model || "" };
|
|
15434
|
-
}
|
|
15435
|
-
if (newConfig.apiKey && this.onApiKeyCreated) {
|
|
15436
|
-
const profileName = this.onApiKeyCreated(newConfig, newConfig.apiKey);
|
|
15437
|
-
if (profileName) {
|
|
15438
|
-
;
|
|
15439
|
-
newConfig.authProfile = profileName;
|
|
15640
|
+
return this.withStoreLock(() => {
|
|
15641
|
+
const store = this.loadStore();
|
|
15642
|
+
if (store.configs.length >= MAX_CONFIG_COUNT) {
|
|
15643
|
+
return { success: false, error: this.t("llm.maxConfigs", { count: MAX_CONFIG_COUNT }) };
|
|
15440
15644
|
}
|
|
15441
|
-
|
|
15442
|
-
|
|
15443
|
-
|
|
15645
|
+
const now = Date.now();
|
|
15646
|
+
const newConfig = {
|
|
15647
|
+
...config,
|
|
15648
|
+
id: this.generateId(),
|
|
15649
|
+
createdAt: now,
|
|
15650
|
+
updatedAt: now
|
|
15651
|
+
};
|
|
15652
|
+
store.configs.push(newConfig);
|
|
15653
|
+
if (store.configs.length === 1) {
|
|
15654
|
+
store.defaultAssistant = { configId: newConfig.id, modelId: newConfig.model || "" };
|
|
15655
|
+
}
|
|
15656
|
+
if (newConfig.apiKey && this.onApiKeyCreated) {
|
|
15657
|
+
const profileName = this.onApiKeyCreated(newConfig, newConfig.apiKey);
|
|
15658
|
+
if (profileName) {
|
|
15659
|
+
;
|
|
15660
|
+
newConfig.authProfile = profileName;
|
|
15661
|
+
}
|
|
15662
|
+
}
|
|
15663
|
+
this.saveStore(store);
|
|
15664
|
+
return { success: true, config: { ...newConfig, apiKey: "" } };
|
|
15665
|
+
});
|
|
15444
15666
|
}
|
|
15445
15667
|
updateConfig(id, updates) {
|
|
15446
|
-
|
|
15447
|
-
|
|
15448
|
-
|
|
15449
|
-
|
|
15450
|
-
|
|
15451
|
-
|
|
15452
|
-
|
|
15453
|
-
|
|
15454
|
-
|
|
15455
|
-
|
|
15456
|
-
|
|
15457
|
-
|
|
15458
|
-
|
|
15459
|
-
|
|
15460
|
-
|
|
15461
|
-
|
|
15462
|
-
|
|
15463
|
-
|
|
15464
|
-
|
|
15465
|
-
|
|
15466
|
-
|
|
15668
|
+
return this.withStoreLock(() => {
|
|
15669
|
+
const store = this.loadStore();
|
|
15670
|
+
const index = store.configs.findIndex((c) => c.id === id);
|
|
15671
|
+
if (index === -1) {
|
|
15672
|
+
return { success: false, error: this.t("llm.configNotFound") };
|
|
15673
|
+
}
|
|
15674
|
+
const oldConfig = store.configs[index];
|
|
15675
|
+
const oldProfileName = oldConfig.authProfile;
|
|
15676
|
+
const updated = {
|
|
15677
|
+
...oldConfig,
|
|
15678
|
+
...updates,
|
|
15679
|
+
updatedAt: Date.now()
|
|
15680
|
+
};
|
|
15681
|
+
store.configs[index] = updated;
|
|
15682
|
+
let oldProfileToDelete = null;
|
|
15683
|
+
if (updates.apiKey && this.onApiKeyCreated) {
|
|
15684
|
+
const profileName = this.onApiKeyCreated(updated, updates.apiKey);
|
|
15685
|
+
if (profileName) {
|
|
15686
|
+
;
|
|
15687
|
+
store.configs[index].authProfile = profileName;
|
|
15688
|
+
if (oldProfileName && oldProfileName !== profileName && !isAuthProfileUsed(store.configs, oldProfileName, oldConfig.provider)) {
|
|
15689
|
+
oldProfileToDelete = oldConfig;
|
|
15690
|
+
}
|
|
15467
15691
|
}
|
|
15468
15692
|
}
|
|
15469
|
-
|
|
15470
|
-
|
|
15471
|
-
|
|
15472
|
-
|
|
15693
|
+
this.saveStore(store);
|
|
15694
|
+
if (oldProfileToDelete) this.onApiKeyDeleted?.(oldProfileToDelete);
|
|
15695
|
+
return { success: true };
|
|
15696
|
+
});
|
|
15473
15697
|
}
|
|
15474
15698
|
deleteConfig(id) {
|
|
15475
|
-
|
|
15476
|
-
|
|
15477
|
-
|
|
15478
|
-
|
|
15479
|
-
|
|
15480
|
-
|
|
15481
|
-
|
|
15482
|
-
|
|
15483
|
-
|
|
15484
|
-
store.defaultAssistant
|
|
15485
|
-
|
|
15486
|
-
|
|
15487
|
-
store.fastModel
|
|
15488
|
-
|
|
15489
|
-
|
|
15490
|
-
|
|
15491
|
-
|
|
15492
|
-
|
|
15493
|
-
|
|
15494
|
-
|
|
15699
|
+
return this.withStoreLock(() => {
|
|
15700
|
+
const store = this.loadStore();
|
|
15701
|
+
const index = store.configs.findIndex((c) => c.id === id);
|
|
15702
|
+
if (index === -1) {
|
|
15703
|
+
return { success: false, error: this.t("llm.configNotFound") };
|
|
15704
|
+
}
|
|
15705
|
+
const deleted = store.configs[index];
|
|
15706
|
+
store.configs.splice(index, 1);
|
|
15707
|
+
const fallback = store.configs[0];
|
|
15708
|
+
if (store.defaultAssistant?.configId === id) {
|
|
15709
|
+
store.defaultAssistant = fallback ? { configId: fallback.id, modelId: fallback.model || "" } : null;
|
|
15710
|
+
}
|
|
15711
|
+
if (store.fastModel?.configId === id) {
|
|
15712
|
+
store.fastModel = fallback ? { configId: fallback.id, modelId: fallback.model || "" } : null;
|
|
15713
|
+
}
|
|
15714
|
+
this.saveStore(store);
|
|
15715
|
+
const deletedProfileName = getAuthProfile(deleted);
|
|
15716
|
+
if (!deletedProfileName || !isAuthProfileUsed(store.configs, deletedProfileName, deleted.provider)) {
|
|
15717
|
+
this.onApiKeyDeleted?.(deleted);
|
|
15718
|
+
}
|
|
15719
|
+
return { success: true };
|
|
15720
|
+
});
|
|
15495
15721
|
}
|
|
15496
15722
|
setDefaultAssistantModel(configId, modelId) {
|
|
15497
|
-
|
|
15498
|
-
|
|
15499
|
-
|
|
15500
|
-
return { success: false, error: this.t("llm.configNotFound") };
|
|
15501
|
-
}
|
|
15502
|
-
store.defaultAssistant = { configId, modelId };
|
|
15503
|
-
this.saveStore(store);
|
|
15504
|
-
return { success: true };
|
|
15505
|
-
}
|
|
15506
|
-
setFastModel(slot) {
|
|
15507
|
-
const store = this.loadStore();
|
|
15508
|
-
if (slot !== null) {
|
|
15509
|
-
const config = store.configs.find((c) => c.id === slot.configId);
|
|
15723
|
+
return this.withStoreLock(() => {
|
|
15724
|
+
const store = this.loadStore();
|
|
15725
|
+
const config = store.configs.find((c) => c.id === configId);
|
|
15510
15726
|
if (!config) {
|
|
15511
15727
|
return { success: false, error: this.t("llm.configNotFound") };
|
|
15512
15728
|
}
|
|
15513
|
-
|
|
15514
|
-
|
|
15515
|
-
|
|
15516
|
-
|
|
15729
|
+
store.defaultAssistant = { configId, modelId };
|
|
15730
|
+
this.saveStore(store);
|
|
15731
|
+
return { success: true };
|
|
15732
|
+
});
|
|
15733
|
+
}
|
|
15734
|
+
setFastModel(slot) {
|
|
15735
|
+
return this.withStoreLock(() => {
|
|
15736
|
+
const store = this.loadStore();
|
|
15737
|
+
if (slot !== null) {
|
|
15738
|
+
const config = store.configs.find((c) => c.id === slot.configId);
|
|
15739
|
+
if (!config) {
|
|
15740
|
+
return { success: false, error: this.t("llm.configNotFound") };
|
|
15741
|
+
}
|
|
15742
|
+
}
|
|
15743
|
+
store.fastModel = slot;
|
|
15744
|
+
this.saveStore(store);
|
|
15745
|
+
return { success: true };
|
|
15746
|
+
});
|
|
15517
15747
|
}
|
|
15518
15748
|
hasActiveConfig() {
|
|
15519
15749
|
return this.getDefaultAssistantConfig() !== null;
|
|
@@ -15521,20 +15751,30 @@ var LLMConfigStore = class {
|
|
|
15521
15751
|
};
|
|
15522
15752
|
|
|
15523
15753
|
// ../../packages/node-runtime/src/ai/file-config-storage.ts
|
|
15524
|
-
import * as fs28 from "fs";
|
|
15525
15754
|
import * as path22 from "path";
|
|
15526
15755
|
function createFileConfigStorage(baseDir) {
|
|
15756
|
+
const heldLocks = /* @__PURE__ */ new Set();
|
|
15757
|
+
const getFilePath = (key) => path22.join(baseDir, `${key}.json`);
|
|
15527
15758
|
return {
|
|
15528
15759
|
readJson(key) {
|
|
15529
|
-
|
|
15530
|
-
return JSON.parse(fs28.readFileSync(path22.join(baseDir, `${key}.json`), "utf-8"));
|
|
15531
|
-
} catch {
|
|
15532
|
-
return null;
|
|
15533
|
-
}
|
|
15760
|
+
return readJsonFile(getFilePath(key));
|
|
15534
15761
|
},
|
|
15535
15762
|
writeJson(key, data) {
|
|
15536
|
-
|
|
15537
|
-
|
|
15763
|
+
const filePath = getFilePath(key);
|
|
15764
|
+
const write = () => writeJsonFileAtomically(filePath, data);
|
|
15765
|
+
if (heldLocks.has(key)) write();
|
|
15766
|
+
else withFileLock(filePath, write);
|
|
15767
|
+
},
|
|
15768
|
+
withLock(key, action) {
|
|
15769
|
+
if (heldLocks.has(key)) return action();
|
|
15770
|
+
return withFileLock(getFilePath(key), () => {
|
|
15771
|
+
heldLocks.add(key);
|
|
15772
|
+
try {
|
|
15773
|
+
return action();
|
|
15774
|
+
} finally {
|
|
15775
|
+
heldLocks.delete(key);
|
|
15776
|
+
}
|
|
15777
|
+
});
|
|
15538
15778
|
}
|
|
15539
15779
|
};
|
|
15540
15780
|
}
|
|
@@ -15542,23 +15782,57 @@ function createFileConfigStorage(baseDir) {
|
|
|
15542
15782
|
// ../../packages/node-runtime/src/ai/auth-profile-llm-config-store.ts
|
|
15543
15783
|
var defaultDeps = {
|
|
15544
15784
|
resolveApiKey: (provider, authProfile) => resolveApiKey(provider, authProfile) || void 0,
|
|
15785
|
+
loadAuthProfiles,
|
|
15545
15786
|
writeAuthProfile,
|
|
15546
15787
|
deleteAuthProfile
|
|
15547
15788
|
};
|
|
15548
15789
|
function getAuthProfile2(config) {
|
|
15549
15790
|
return config.authProfile;
|
|
15550
15791
|
}
|
|
15551
|
-
function
|
|
15792
|
+
function getNamedAuthProfile(config) {
|
|
15793
|
+
return config.name?.toLowerCase().replace(/\s+/g, "-") || config.provider;
|
|
15794
|
+
}
|
|
15795
|
+
function restoreLegacyAuthProfileReferences(configs, authProfiles) {
|
|
15796
|
+
const usedProfiles = new Set(configs.map(getAuthProfile2).filter((name) => Boolean(name)));
|
|
15797
|
+
for (const config of configs) {
|
|
15798
|
+
if (getAuthProfile2(config)) continue;
|
|
15799
|
+
const namedProfile = getNamedAuthProfile(config);
|
|
15800
|
+
const namedProfileValue = authProfiles.profiles[namedProfile];
|
|
15801
|
+
if (namedProfileValue?.provider === config.provider && !usedProfiles.has(namedProfile)) {
|
|
15802
|
+
;
|
|
15803
|
+
config.authProfile = namedProfile;
|
|
15804
|
+
usedProfiles.add(namedProfile);
|
|
15805
|
+
continue;
|
|
15806
|
+
}
|
|
15807
|
+
const baseName = deriveAuthProfileName(config.provider, config);
|
|
15808
|
+
for (let index = 1; index <= Object.keys(authProfiles.profiles).length; index++) {
|
|
15809
|
+
const candidate = index === 1 ? baseName : `${baseName}-${index}`;
|
|
15810
|
+
const profile = authProfiles.profiles[candidate];
|
|
15811
|
+
if (!profile || profile.provider !== config.provider || usedProfiles.has(candidate)) continue;
|
|
15812
|
+
config.authProfile = candidate;
|
|
15813
|
+
usedProfiles.add(candidate);
|
|
15814
|
+
break;
|
|
15815
|
+
}
|
|
15816
|
+
}
|
|
15817
|
+
}
|
|
15818
|
+
function createAuthProfileLlmConfigStore(storage, deps = {}) {
|
|
15819
|
+
const resolvedDeps = { ...defaultDeps, ...deps };
|
|
15552
15820
|
return new LLMConfigStore(storage, {
|
|
15553
|
-
|
|
15821
|
+
t: deps.t,
|
|
15822
|
+
generateId: deps.generateId,
|
|
15823
|
+
onStoreLoaded: (configs) => {
|
|
15824
|
+
restoreLegacyAuthProfileReferences(configs, resolvedDeps.loadAuthProfiles());
|
|
15825
|
+
deps.onStoreLoaded?.(configs);
|
|
15826
|
+
},
|
|
15827
|
+
resolveApiKey: resolvedDeps.resolveApiKey,
|
|
15554
15828
|
onApiKeyCreated: (config, apiKey) => {
|
|
15555
|
-
const profileName = config
|
|
15556
|
-
|
|
15829
|
+
const profileName = getNamedAuthProfile(config);
|
|
15830
|
+
resolvedDeps.writeAuthProfile(profileName, { type: "api_key", provider: config.provider, key: apiKey });
|
|
15557
15831
|
return profileName;
|
|
15558
15832
|
},
|
|
15559
15833
|
onApiKeyDeleted: (config) => {
|
|
15560
15834
|
const profileName = getAuthProfile2(config);
|
|
15561
|
-
if (profileName)
|
|
15835
|
+
if (profileName) resolvedDeps.deleteAuthProfile(profileName);
|
|
15562
15836
|
}
|
|
15563
15837
|
});
|
|
15564
15838
|
}
|
|
@@ -15572,43 +15846,52 @@ var CustomProviderStore = class {
|
|
|
15572
15846
|
this.storage = storage;
|
|
15573
15847
|
}
|
|
15574
15848
|
storage;
|
|
15849
|
+
withLock(action) {
|
|
15850
|
+
return this.storage.withLock ? this.storage.withLock("custom-providers", action) : action();
|
|
15851
|
+
}
|
|
15575
15852
|
getAll() {
|
|
15576
15853
|
return this.storage.readJson("custom-providers") ?? [];
|
|
15577
15854
|
}
|
|
15578
15855
|
add(input) {
|
|
15579
|
-
|
|
15580
|
-
|
|
15581
|
-
|
|
15582
|
-
|
|
15583
|
-
|
|
15584
|
-
|
|
15585
|
-
|
|
15586
|
-
|
|
15587
|
-
|
|
15588
|
-
|
|
15589
|
-
|
|
15590
|
-
|
|
15591
|
-
|
|
15592
|
-
|
|
15593
|
-
|
|
15594
|
-
|
|
15595
|
-
|
|
15856
|
+
return this.withLock(() => {
|
|
15857
|
+
const providers = this.getAll();
|
|
15858
|
+
const newProvider = {
|
|
15859
|
+
id: generateCustomId(),
|
|
15860
|
+
name: input.name,
|
|
15861
|
+
kind: input.kind || "openai-compatible",
|
|
15862
|
+
defaultBaseUrl: input.defaultBaseUrl,
|
|
15863
|
+
authMode: "api-key",
|
|
15864
|
+
supportsCustomModels: input.supportsCustomModels ?? true,
|
|
15865
|
+
modelIds: input.modelIds ?? [],
|
|
15866
|
+
builtin: false,
|
|
15867
|
+
enabledByDefault: false,
|
|
15868
|
+
website: input.website,
|
|
15869
|
+
consoleUrl: input.consoleUrl
|
|
15870
|
+
};
|
|
15871
|
+
providers.push(newProvider);
|
|
15872
|
+
this.storage.writeJson("custom-providers", providers);
|
|
15873
|
+
return newProvider;
|
|
15874
|
+
});
|
|
15596
15875
|
}
|
|
15597
15876
|
update(id, updates) {
|
|
15598
|
-
|
|
15599
|
-
|
|
15600
|
-
|
|
15601
|
-
|
|
15602
|
-
|
|
15603
|
-
|
|
15877
|
+
return this.withLock(() => {
|
|
15878
|
+
const providers = this.getAll();
|
|
15879
|
+
const index = providers.findIndex((p) => p.id === id);
|
|
15880
|
+
if (index === -1) return { success: false, error: "Custom provider not found" };
|
|
15881
|
+
providers[index] = { ...providers[index], ...updates };
|
|
15882
|
+
this.storage.writeJson("custom-providers", providers);
|
|
15883
|
+
return { success: true };
|
|
15884
|
+
});
|
|
15604
15885
|
}
|
|
15605
15886
|
delete(id) {
|
|
15606
|
-
|
|
15607
|
-
|
|
15608
|
-
|
|
15609
|
-
|
|
15610
|
-
|
|
15611
|
-
|
|
15887
|
+
return this.withLock(() => {
|
|
15888
|
+
const providers = this.getAll();
|
|
15889
|
+
const index = providers.findIndex((p) => p.id === id);
|
|
15890
|
+
if (index === -1) return { success: false, error: "Custom provider not found" };
|
|
15891
|
+
providers.splice(index, 1);
|
|
15892
|
+
this.storage.writeJson("custom-providers", providers);
|
|
15893
|
+
return { success: true };
|
|
15894
|
+
});
|
|
15612
15895
|
}
|
|
15613
15896
|
};
|
|
15614
15897
|
var CustomModelStore = class {
|
|
@@ -15616,51 +15899,96 @@ var CustomModelStore = class {
|
|
|
15616
15899
|
this.storage = storage;
|
|
15617
15900
|
}
|
|
15618
15901
|
storage;
|
|
15902
|
+
withLock(action) {
|
|
15903
|
+
return this.storage.withLock ? this.storage.withLock("custom-models", action) : action();
|
|
15904
|
+
}
|
|
15619
15905
|
getAll() {
|
|
15620
15906
|
return this.storage.readJson("custom-models") ?? [];
|
|
15621
15907
|
}
|
|
15622
15908
|
add(input) {
|
|
15623
|
-
|
|
15624
|
-
|
|
15625
|
-
|
|
15626
|
-
|
|
15627
|
-
|
|
15909
|
+
return this.withLock(() => {
|
|
15910
|
+
const models = this.getAll();
|
|
15911
|
+
if (models.find((m) => m.id === input.id && m.providerId === input.providerId)) {
|
|
15912
|
+
return {
|
|
15913
|
+
success: false,
|
|
15914
|
+
error: `Model "${input.id}" already exists under provider "${input.providerId}"`
|
|
15915
|
+
};
|
|
15916
|
+
}
|
|
15917
|
+
const newModel = {
|
|
15918
|
+
id: input.id,
|
|
15919
|
+
providerId: input.providerId,
|
|
15920
|
+
name: input.name,
|
|
15921
|
+
description: input.description,
|
|
15922
|
+
contextWindow: input.contextWindow,
|
|
15923
|
+
capabilities: input.capabilities ?? ["chat"],
|
|
15924
|
+
recommendedFor: input.recommendedFor ?? ["chat"],
|
|
15925
|
+
status: input.status ?? "stable",
|
|
15926
|
+
builtin: false,
|
|
15927
|
+
editable: true
|
|
15628
15928
|
};
|
|
15629
|
-
|
|
15630
|
-
|
|
15631
|
-
|
|
15632
|
-
|
|
15633
|
-
name: input.name,
|
|
15634
|
-
description: input.description,
|
|
15635
|
-
contextWindow: input.contextWindow,
|
|
15636
|
-
capabilities: input.capabilities ?? ["chat"],
|
|
15637
|
-
recommendedFor: input.recommendedFor ?? ["chat"],
|
|
15638
|
-
status: input.status ?? "stable",
|
|
15639
|
-
builtin: false,
|
|
15640
|
-
editable: true
|
|
15641
|
-
};
|
|
15642
|
-
models.push(newModel);
|
|
15643
|
-
this.storage.writeJson("custom-models", models);
|
|
15644
|
-
return { success: true, model: newModel };
|
|
15929
|
+
models.push(newModel);
|
|
15930
|
+
this.storage.writeJson("custom-models", models);
|
|
15931
|
+
return { success: true, model: newModel };
|
|
15932
|
+
});
|
|
15645
15933
|
}
|
|
15646
15934
|
update(providerId, modelId, updates) {
|
|
15647
|
-
|
|
15648
|
-
|
|
15649
|
-
|
|
15650
|
-
|
|
15651
|
-
|
|
15652
|
-
|
|
15935
|
+
return this.withLock(() => {
|
|
15936
|
+
const models = this.getAll();
|
|
15937
|
+
const index = models.findIndex((m) => m.id === modelId && m.providerId === providerId);
|
|
15938
|
+
if (index === -1) return { success: false, error: "Custom model not found" };
|
|
15939
|
+
models[index] = { ...models[index], ...updates };
|
|
15940
|
+
this.storage.writeJson("custom-models", models);
|
|
15941
|
+
return { success: true };
|
|
15942
|
+
});
|
|
15653
15943
|
}
|
|
15654
15944
|
delete(providerId, modelId) {
|
|
15655
|
-
|
|
15656
|
-
|
|
15657
|
-
|
|
15658
|
-
|
|
15659
|
-
|
|
15660
|
-
|
|
15945
|
+
return this.withLock(() => {
|
|
15946
|
+
const models = this.getAll();
|
|
15947
|
+
const index = models.findIndex((m) => m.id === modelId && m.providerId === providerId);
|
|
15948
|
+
if (index === -1) return { success: false, error: "Custom model not found" };
|
|
15949
|
+
models.splice(index, 1);
|
|
15950
|
+
this.storage.writeJson("custom-models", models);
|
|
15951
|
+
return { success: true };
|
|
15952
|
+
});
|
|
15661
15953
|
}
|
|
15662
15954
|
};
|
|
15663
15955
|
|
|
15956
|
+
// ../../packages/node-runtime/src/ai/llm-runtime-stores.ts
|
|
15957
|
+
function ensureLegacyCustomModels(configs, customModelStore) {
|
|
15958
|
+
for (const config of configs) {
|
|
15959
|
+
const providerId = config.provider;
|
|
15960
|
+
if (config.model && getBuiltinProviderById(providerId) && !getBuiltinModelById(providerId, config.model)) {
|
|
15961
|
+
customModelStore.add({
|
|
15962
|
+
id: config.model,
|
|
15963
|
+
providerId,
|
|
15964
|
+
name: config.model,
|
|
15965
|
+
capabilities: ["chat"],
|
|
15966
|
+
recommendedFor: ["chat"],
|
|
15967
|
+
status: "stable"
|
|
15968
|
+
});
|
|
15969
|
+
}
|
|
15970
|
+
}
|
|
15971
|
+
}
|
|
15972
|
+
function createLlmRuntimeStores(aiDataDir, options2 = {}) {
|
|
15973
|
+
const storage = createFileConfigStorage(aiDataDir);
|
|
15974
|
+
const customProviderStore = new CustomProviderStore(storage);
|
|
15975
|
+
const customModelStore = new CustomModelStore(storage);
|
|
15976
|
+
const llmConfigStore = createAuthProfileLlmConfigStore(storage, {
|
|
15977
|
+
...options2.authProfileDeps,
|
|
15978
|
+
t: options2.t,
|
|
15979
|
+
generateId: options2.generateId,
|
|
15980
|
+
onStoreLoaded: (configs) => {
|
|
15981
|
+
ensureLegacyCustomModels(configs, customModelStore);
|
|
15982
|
+
options2.onStoreLoaded?.(configs);
|
|
15983
|
+
}
|
|
15984
|
+
});
|
|
15985
|
+
return {
|
|
15986
|
+
llmConfigStore,
|
|
15987
|
+
customProviderStore,
|
|
15988
|
+
customModelStore
|
|
15989
|
+
};
|
|
15990
|
+
}
|
|
15991
|
+
|
|
15664
15992
|
// ../../packages/node-runtime/src/ai/llm-builder.ts
|
|
15665
15993
|
function normalizeAnthropicBaseUrl(url) {
|
|
15666
15994
|
return url.replace(/\/v1\/?$/, "");
|
|
@@ -16382,7 +16710,7 @@ function exportWithFormat(params, openDatabase) {
|
|
|
16382
16710
|
}
|
|
16383
16711
|
|
|
16384
16712
|
// ../../packages/node-runtime/src/merger/temp-db.ts
|
|
16385
|
-
import * as
|
|
16713
|
+
import * as fs28 from "fs";
|
|
16386
16714
|
import * as path23 from "path";
|
|
16387
16715
|
var TEMP_DB_SCHEMA = `
|
|
16388
16716
|
CREATE TABLE IF NOT EXISTS meta (
|
|
@@ -16628,18 +16956,18 @@ function exportSessionToJson(db) {
|
|
|
16628
16956
|
}
|
|
16629
16957
|
function deleteTempDatabase(dbPath) {
|
|
16630
16958
|
try {
|
|
16631
|
-
if (
|
|
16959
|
+
if (fs28.existsSync(dbPath)) fs28.unlinkSync(dbPath);
|
|
16632
16960
|
const walPath = dbPath + "-wal";
|
|
16633
16961
|
const shmPath = dbPath + "-shm";
|
|
16634
|
-
if (
|
|
16635
|
-
if (
|
|
16962
|
+
if (fs28.existsSync(walPath)) fs28.unlinkSync(walPath);
|
|
16963
|
+
if (fs28.existsSync(shmPath)) fs28.unlinkSync(shmPath);
|
|
16636
16964
|
} catch {
|
|
16637
16965
|
}
|
|
16638
16966
|
}
|
|
16639
16967
|
function cleanupTempDatabases(tempDir) {
|
|
16640
16968
|
try {
|
|
16641
|
-
if (!
|
|
16642
|
-
const files =
|
|
16969
|
+
if (!fs28.existsSync(tempDir)) return;
|
|
16970
|
+
const files = fs28.readdirSync(tempDir);
|
|
16643
16971
|
for (const file of files) {
|
|
16644
16972
|
if (file.startsWith("merge_") && file.endsWith(".db")) {
|
|
16645
16973
|
deleteTempDatabase(path23.join(tempDir, file));
|
|
@@ -17027,7 +17355,7 @@ function clearSessionOwner(adapter, sessionId) {
|
|
|
17027
17355
|
}
|
|
17028
17356
|
|
|
17029
17357
|
// ../../packages/node-runtime/src/services/contacts/overrides.ts
|
|
17030
|
-
import
|
|
17358
|
+
import fs29 from "fs";
|
|
17031
17359
|
import path24 from "path";
|
|
17032
17360
|
var CONTACT_OVERRIDES_FILE_NAME = "contact-overrides.json";
|
|
17033
17361
|
var CONTACT_OVERRIDES_TMP_PREFIX = "contact-overrides.tmp-";
|
|
@@ -17043,26 +17371,26 @@ function getContactOverridesPath(snapshotDir) {
|
|
|
17043
17371
|
}
|
|
17044
17372
|
function readContactOverrides(snapshotDir) {
|
|
17045
17373
|
const filePath = getContactOverridesPath(snapshotDir);
|
|
17046
|
-
if (!
|
|
17374
|
+
if (!fs29.existsSync(filePath)) return createEmptyContactOverridesFile();
|
|
17047
17375
|
try {
|
|
17048
|
-
return normalizeContactOverrides(JSON.parse(
|
|
17376
|
+
return normalizeContactOverrides(JSON.parse(fs29.readFileSync(filePath, "utf-8")));
|
|
17049
17377
|
} catch (error) {
|
|
17050
17378
|
appLogger.warn("contacts", "contact overrides file is unreadable", error);
|
|
17051
17379
|
return createEmptyContactOverridesFile();
|
|
17052
17380
|
}
|
|
17053
17381
|
}
|
|
17054
17382
|
function writeContactOverrides(snapshotDir, overrides) {
|
|
17055
|
-
if (!
|
|
17383
|
+
if (!fs29.existsSync(snapshotDir)) fs29.mkdirSync(snapshotDir, { recursive: true });
|
|
17056
17384
|
const tmpPath = path24.join(snapshotDir, `${CONTACT_OVERRIDES_TMP_PREFIX}${process.pid}-${Date.now()}`);
|
|
17057
|
-
|
|
17058
|
-
|
|
17385
|
+
fs29.writeFileSync(tmpPath, JSON.stringify(normalizeContactOverrides(overrides), null, 2), "utf-8");
|
|
17386
|
+
fs29.renameSync(tmpPath, getContactOverridesPath(snapshotDir));
|
|
17059
17387
|
}
|
|
17060
17388
|
function normalizeContactOverrides(value) {
|
|
17061
|
-
const input =
|
|
17062
|
-
const manualFriendsInput =
|
|
17389
|
+
const input = isRecord4(value) ? value : {};
|
|
17390
|
+
const manualFriendsInput = isRecord4(input.manualFriends) ? input.manualFriends : {};
|
|
17063
17391
|
const manualFriends = {};
|
|
17064
17392
|
for (const [key, entry] of Object.entries(manualFriendsInput)) {
|
|
17065
|
-
if (!key || !
|
|
17393
|
+
if (!key || !isRecord4(entry)) continue;
|
|
17066
17394
|
const createdAt = Number.isFinite(entry.createdAt) ? Number(entry.createdAt) : Date.now();
|
|
17067
17395
|
const updatedAt = Number.isFinite(entry.updatedAt) ? Number(entry.updatedAt) : createdAt;
|
|
17068
17396
|
manualFriends[key] = { key, createdAt, updatedAt };
|
|
@@ -17072,7 +17400,7 @@ function normalizeContactOverrides(value) {
|
|
|
17072
17400
|
manualFriends
|
|
17073
17401
|
};
|
|
17074
17402
|
}
|
|
17075
|
-
function
|
|
17403
|
+
function isRecord4(value) {
|
|
17076
17404
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17077
17405
|
}
|
|
17078
17406
|
|
|
@@ -17090,7 +17418,7 @@ function buildContactsSignature(adapter, timeRangePreset) {
|
|
|
17090
17418
|
}
|
|
17091
17419
|
|
|
17092
17420
|
// ../../packages/node-runtime/src/services/contacts/snapshot.ts
|
|
17093
|
-
import
|
|
17421
|
+
import fs30 from "fs";
|
|
17094
17422
|
import path25 from "path";
|
|
17095
17423
|
var CONTACTS_SNAPSHOT_TMP_PREFIX = "contacts-snapshot.tmp-";
|
|
17096
17424
|
function getContactsSnapshotPath(snapshotDir, timeRangePreset) {
|
|
@@ -17099,14 +17427,14 @@ function getContactsSnapshotPath(snapshotDir, timeRangePreset) {
|
|
|
17099
17427
|
}
|
|
17100
17428
|
function readContactsSnapshot(snapshotDir, timeRangePreset, options2 = {}) {
|
|
17101
17429
|
const snapshotPath = getContactsSnapshotPath(snapshotDir, timeRangePreset);
|
|
17102
|
-
if (!
|
|
17430
|
+
if (!fs30.existsSync(snapshotPath)) return null;
|
|
17103
17431
|
try {
|
|
17104
|
-
return JSON.parse(
|
|
17432
|
+
return JSON.parse(fs30.readFileSync(snapshotPath, "utf-8"));
|
|
17105
17433
|
} catch (error) {
|
|
17106
17434
|
const ts = options2.now?.() ?? Date.now();
|
|
17107
17435
|
const backupPath = path25.join(snapshotDir, `contacts-snapshot.corrupt-${ts}.json`);
|
|
17108
17436
|
try {
|
|
17109
|
-
|
|
17437
|
+
fs30.renameSync(snapshotPath, backupPath);
|
|
17110
17438
|
} catch (renameError) {
|
|
17111
17439
|
appLogger.warn("contacts", "failed to backup corrupt contacts snapshot", renameError);
|
|
17112
17440
|
}
|
|
@@ -17115,17 +17443,17 @@ function readContactsSnapshot(snapshotDir, timeRangePreset, options2 = {}) {
|
|
|
17115
17443
|
}
|
|
17116
17444
|
}
|
|
17117
17445
|
function writeContactsSnapshot(snapshotDir, snapshot) {
|
|
17118
|
-
if (!
|
|
17446
|
+
if (!fs30.existsSync(snapshotDir)) fs30.mkdirSync(snapshotDir, { recursive: true });
|
|
17119
17447
|
const tmpPath = path25.join(snapshotDir, `${CONTACTS_SNAPSHOT_TMP_PREFIX}${process.pid}-${Date.now()}`);
|
|
17120
|
-
|
|
17121
|
-
|
|
17448
|
+
fs30.writeFileSync(tmpPath, JSON.stringify(snapshot, null, 2), "utf-8");
|
|
17449
|
+
fs30.renameSync(tmpPath, getContactsSnapshotPath(snapshotDir, snapshot.timeRange.preset));
|
|
17122
17450
|
}
|
|
17123
17451
|
function cleanupContactsSnapshotTempFiles(snapshotDir) {
|
|
17124
|
-
if (!
|
|
17125
|
-
for (const name of
|
|
17452
|
+
if (!fs30.existsSync(snapshotDir)) return;
|
|
17453
|
+
for (const name of fs30.readdirSync(snapshotDir)) {
|
|
17126
17454
|
if (!name.startsWith(CONTACTS_SNAPSHOT_TMP_PREFIX)) continue;
|
|
17127
17455
|
try {
|
|
17128
|
-
|
|
17456
|
+
fs30.rmSync(path25.join(snapshotDir, name), { force: true });
|
|
17129
17457
|
} catch (error) {
|
|
17130
17458
|
appLogger.warn("contacts", "failed to remove contacts snapshot temp file", error);
|
|
17131
17459
|
}
|
|
@@ -17623,7 +17951,7 @@ function buildPeopleRelationshipsSignature(adapter, timeRangePreset) {
|
|
|
17623
17951
|
}
|
|
17624
17952
|
|
|
17625
17953
|
// ../../packages/node-runtime/src/services/people/relationships/snapshot.ts
|
|
17626
|
-
import
|
|
17954
|
+
import fs31 from "fs";
|
|
17627
17955
|
import path26 from "path";
|
|
17628
17956
|
var PEOPLE_RELATIONSHIPS_SNAPSHOT_TMP_PREFIX = "people-relationships-snapshot.tmp-";
|
|
17629
17957
|
function getPeopleRelationshipsSnapshotPath(snapshotDir, timeRangePreset) {
|
|
@@ -17632,14 +17960,14 @@ function getPeopleRelationshipsSnapshotPath(snapshotDir, timeRangePreset) {
|
|
|
17632
17960
|
}
|
|
17633
17961
|
function readPeopleRelationshipsSnapshot(snapshotDir, timeRangePreset, options2 = {}) {
|
|
17634
17962
|
const snapshotPath = getPeopleRelationshipsSnapshotPath(snapshotDir, timeRangePreset);
|
|
17635
|
-
if (!
|
|
17963
|
+
if (!fs31.existsSync(snapshotPath)) return null;
|
|
17636
17964
|
try {
|
|
17637
|
-
return JSON.parse(
|
|
17965
|
+
return JSON.parse(fs31.readFileSync(snapshotPath, "utf-8"));
|
|
17638
17966
|
} catch (error) {
|
|
17639
17967
|
const ts = options2.now?.() ?? Date.now();
|
|
17640
17968
|
const backupPath = path26.join(snapshotDir, `graph-snapshot.corrupt-${ts}.json`);
|
|
17641
17969
|
try {
|
|
17642
|
-
|
|
17970
|
+
fs31.renameSync(snapshotPath, backupPath);
|
|
17643
17971
|
} catch (renameError) {
|
|
17644
17972
|
appLogger.warn("people-relationships", "failed to backup corrupt people relationships snapshot", renameError);
|
|
17645
17973
|
}
|
|
@@ -17648,17 +17976,17 @@ function readPeopleRelationshipsSnapshot(snapshotDir, timeRangePreset, options2
|
|
|
17648
17976
|
}
|
|
17649
17977
|
}
|
|
17650
17978
|
function writePeopleRelationshipsSnapshot(snapshotDir, snapshot) {
|
|
17651
|
-
if (!
|
|
17979
|
+
if (!fs31.existsSync(snapshotDir)) fs31.mkdirSync(snapshotDir, { recursive: true });
|
|
17652
17980
|
const tmpPath = path26.join(snapshotDir, `${PEOPLE_RELATIONSHIPS_SNAPSHOT_TMP_PREFIX}${process.pid}-${Date.now()}`);
|
|
17653
|
-
|
|
17654
|
-
|
|
17981
|
+
fs31.writeFileSync(tmpPath, JSON.stringify(snapshot, null, 2), "utf-8");
|
|
17982
|
+
fs31.renameSync(tmpPath, getPeopleRelationshipsSnapshotPath(snapshotDir, snapshot.timeRange.preset));
|
|
17655
17983
|
}
|
|
17656
17984
|
function cleanupPeopleRelationshipsSnapshotTempFiles(snapshotDir) {
|
|
17657
|
-
if (!
|
|
17658
|
-
for (const name of
|
|
17985
|
+
if (!fs31.existsSync(snapshotDir)) return;
|
|
17986
|
+
for (const name of fs31.readdirSync(snapshotDir)) {
|
|
17659
17987
|
if (!name.startsWith(PEOPLE_RELATIONSHIPS_SNAPSHOT_TMP_PREFIX)) continue;
|
|
17660
17988
|
try {
|
|
17661
|
-
|
|
17989
|
+
fs31.rmSync(path26.join(snapshotDir, name), { force: true });
|
|
17662
17990
|
} catch (error) {
|
|
17663
17991
|
appLogger.warn("people-relationships", "failed to remove people relationships snapshot temp file", error);
|
|
17664
17992
|
}
|
|
@@ -17794,8 +18122,10 @@ var DefaultPeopleRelationshipsService = class {
|
|
|
17794
18122
|
const snapshot = this.getSnapshotForResponse(timeRangePreset);
|
|
17795
18123
|
const status = this.getCacheStatus(signature, timeRangePreset);
|
|
17796
18124
|
const includeSnapshot = shouldIncludeSnapshot(status, options2.acceptStale);
|
|
17797
|
-
const
|
|
17798
|
-
const
|
|
18125
|
+
const graphScope = normalizePeopleRelationshipsGraphScope(options2.graphScope);
|
|
18126
|
+
const scopedSnapshot = snapshot ? buildNeighborhoodSnapshotForScope(snapshot, graphScope) : null;
|
|
18127
|
+
const graph = includeSnapshot && scopedSnapshot ? buildPeopleRelationshipsNeighborhoodGraph(scopedSnapshot, key) : emptyGraph();
|
|
18128
|
+
const contact = includeSnapshot ? scopedSnapshot?.nodes.find((node) => node.key === key) ?? null : null;
|
|
17799
18129
|
return {
|
|
17800
18130
|
contact,
|
|
17801
18131
|
graph,
|
|
@@ -17927,7 +18257,7 @@ var DefaultPeopleRelationshipsService = class {
|
|
|
17927
18257
|
const graph = includeSnapshot && snapshot ? buildGraphForScope(snapshot, graphScope) : emptyGraph();
|
|
17928
18258
|
return {
|
|
17929
18259
|
graph,
|
|
17930
|
-
searchResults: includeSnapshot && snapshot ? buildSearchResults(snapshot, options2.query, graph) : [],
|
|
18260
|
+
searchResults: includeSnapshot && snapshot ? buildSearchResults(snapshot, options2.query, graph, graphScope) : [],
|
|
17931
18261
|
diagnostics: includeSnapshot ? sanitizePeopleRelationshipsDiagnostics(snapshot?.diagnostics ?? createEmptyDiagnostics()) : createEmptyDiagnostics(),
|
|
17932
18262
|
algorithmVersion: includeSnapshot ? snapshot?.algorithmVersion ?? PEOPLE_RELATIONSHIPS_ALGORITHM_VERSION : PEOPLE_RELATIONSHIPS_ALGORITHM_VERSION,
|
|
17933
18263
|
timeRange: snapshot?.timeRange ?? resolvePeopleRelationshipsTimeRange(timeRangePreset, null),
|
|
@@ -17985,6 +18315,16 @@ function buildFriendsRelationshipsGraph(snapshot) {
|
|
|
17985
18315
|
communities: filterCommunitiesForNodes(snapshot.communities, nodes)
|
|
17986
18316
|
};
|
|
17987
18317
|
}
|
|
18318
|
+
function buildNeighborhoodSnapshotForScope(snapshot, scope) {
|
|
18319
|
+
if (scope !== "friends") return snapshot;
|
|
18320
|
+
const graph = buildFriendsRelationshipsGraph(snapshot);
|
|
18321
|
+
return {
|
|
18322
|
+
...snapshot,
|
|
18323
|
+
nodes: graph.nodes,
|
|
18324
|
+
edges: graph.edges,
|
|
18325
|
+
communities: graph.communities
|
|
18326
|
+
};
|
|
18327
|
+
}
|
|
17988
18328
|
function buildCloseRelationshipsGraph(snapshot) {
|
|
17989
18329
|
const selectedKeys = /* @__PURE__ */ new Set();
|
|
17990
18330
|
for (const node of snapshot.nodes) {
|
|
@@ -18025,11 +18365,12 @@ function filterCommunitiesForNodes(communities, nodes) {
|
|
|
18025
18365
|
size: communitySizes.get(community.id) ?? community.size
|
|
18026
18366
|
}));
|
|
18027
18367
|
}
|
|
18028
|
-
function buildSearchResults(snapshot, queryInput, graph) {
|
|
18368
|
+
function buildSearchResults(snapshot, queryInput, graph, graphScope) {
|
|
18029
18369
|
const query = queryInput?.trim().toLowerCase() ?? "";
|
|
18030
18370
|
if (!query) return [];
|
|
18031
18371
|
const visibleKeys = new Set(graph.nodes.map((node) => node.key));
|
|
18032
|
-
|
|
18372
|
+
const searchableNodes = graphScope === "friends" ? graph.nodes : snapshot.nodes;
|
|
18373
|
+
return searchableNodes.filter((node) => node.searchText.includes(query)).sort(compareNodes).slice(0, snapshot.limits.searchResultLimit).map((node) => ({
|
|
18033
18374
|
key: node.key,
|
|
18034
18375
|
kind: node.kind,
|
|
18035
18376
|
displayName: node.displayName,
|
|
@@ -18180,7 +18521,7 @@ __export(relationships_exports, {
|
|
|
18180
18521
|
});
|
|
18181
18522
|
|
|
18182
18523
|
// ../../packages/node-runtime/src/services/global-insight/service.ts
|
|
18183
|
-
import
|
|
18524
|
+
import fs32 from "fs";
|
|
18184
18525
|
|
|
18185
18526
|
// ../../packages/node-runtime/src/services/global-insight/signature.ts
|
|
18186
18527
|
function buildAnnualSummarySignature(adapter, range) {
|
|
@@ -18413,6 +18754,7 @@ var DefaultGlobalInsightService = class {
|
|
|
18413
18754
|
latestDataYear: includeSnapshot ? snapshot?.latestDataYear ?? null : null,
|
|
18414
18755
|
metrics: includeSnapshot ? snapshot?.metrics ?? null : null,
|
|
18415
18756
|
monthlyActivity: includeSnapshot ? snapshot?.monthlyActivity ?? [] : [],
|
|
18757
|
+
monthlyDirectContacts: includeSnapshot ? snapshot?.monthlyDirectContacts ?? [] : [],
|
|
18416
18758
|
dailyActivity: includeSnapshot ? snapshot?.dailyActivity ?? [] : [],
|
|
18417
18759
|
messageTypes: includeSnapshot ? snapshot?.messageTypes ?? [] : [],
|
|
18418
18760
|
textLength: includeSnapshot ? snapshot?.textLength ?? null : null,
|
|
@@ -18433,7 +18775,7 @@ var DefaultGlobalInsightService = class {
|
|
|
18433
18775
|
}
|
|
18434
18776
|
getSnapshot(range) {
|
|
18435
18777
|
const key = toAnnualSummaryRangeKey(range);
|
|
18436
|
-
if (this.snapshots.has(key) && !
|
|
18778
|
+
if (this.snapshots.has(key) && !fs32.existsSync(getAnnualSummarySnapshotPath(this.snapshotDir, range))) {
|
|
18437
18779
|
this.snapshots.delete(key);
|
|
18438
18780
|
}
|
|
18439
18781
|
if (!this.snapshots.has(key)) {
|
|
@@ -18481,7 +18823,7 @@ __export(global_insight_exports, {
|
|
|
18481
18823
|
});
|
|
18482
18824
|
|
|
18483
18825
|
// ../../packages/node-runtime/src/semantic-index/config.ts
|
|
18484
|
-
import
|
|
18826
|
+
import fs33 from "fs";
|
|
18485
18827
|
import path27 from "path";
|
|
18486
18828
|
var DEFAULT_SEMANTIC_INDEX_MODEL_DOWNLOAD_SOURCE = "huggingface";
|
|
18487
18829
|
var SEMANTIC_INDEX_CONFIG_VERSION = 1;
|
|
@@ -18571,9 +18913,9 @@ var SemanticIndexConfigStore = class {
|
|
|
18571
18913
|
return this.set({ ...this.get(), enabled });
|
|
18572
18914
|
}
|
|
18573
18915
|
get() {
|
|
18574
|
-
if (!
|
|
18916
|
+
if (!fs33.existsSync(this.filePath)) return defaultSemanticIndexConfig();
|
|
18575
18917
|
try {
|
|
18576
|
-
const raw = JSON.parse(
|
|
18918
|
+
const raw = JSON.parse(fs33.readFileSync(this.filePath, "utf-8"));
|
|
18577
18919
|
return normalizeConfig(raw);
|
|
18578
18920
|
} catch {
|
|
18579
18921
|
return defaultSemanticIndexConfig();
|
|
@@ -18582,8 +18924,8 @@ var SemanticIndexConfigStore = class {
|
|
|
18582
18924
|
set(config) {
|
|
18583
18925
|
const normalized = normalizeConfig(config);
|
|
18584
18926
|
const dir = path27.dirname(this.filePath);
|
|
18585
|
-
if (!
|
|
18586
|
-
|
|
18927
|
+
if (!fs33.existsSync(dir)) fs33.mkdirSync(dir, { recursive: true });
|
|
18928
|
+
fs33.writeFileSync(this.filePath, JSON.stringify(normalized, null, 2), "utf-8");
|
|
18587
18929
|
return normalized;
|
|
18588
18930
|
}
|
|
18589
18931
|
resolveModelId() {
|
|
@@ -20682,7 +21024,7 @@ ${text}`;
|
|
|
20682
21024
|
};
|
|
20683
21025
|
|
|
20684
21026
|
// ../../packages/node-runtime/src/services/merge-cache.ts
|
|
20685
|
-
import * as
|
|
21027
|
+
import * as fs34 from "fs";
|
|
20686
21028
|
import * as path29 from "path";
|
|
20687
21029
|
import * as crypto from "crypto";
|
|
20688
21030
|
var MergeSessionCache = class {
|
|
@@ -20692,8 +21034,8 @@ var MergeSessionCache = class {
|
|
|
20692
21034
|
constructor(pathProvider, options2) {
|
|
20693
21035
|
this.tempDir = pathProvider.getTempDir();
|
|
20694
21036
|
this.nativeBinding = options2?.nativeBinding;
|
|
20695
|
-
if (!
|
|
20696
|
-
|
|
21037
|
+
if (!fs34.existsSync(this.tempDir)) {
|
|
21038
|
+
fs34.mkdirSync(this.tempDir, { recursive: true });
|
|
20697
21039
|
}
|
|
20698
21040
|
}
|
|
20699
21041
|
generateTempDbPath(filename) {
|
|
@@ -20711,7 +21053,7 @@ var MergeSessionCache = class {
|
|
|
20711
21053
|
/** Open a TempDbReader for a given handle. Caller must close the reader. */
|
|
20712
21054
|
openReader(handle) {
|
|
20713
21055
|
const entry = this.cache.get(handle);
|
|
20714
|
-
if (!entry || !
|
|
21056
|
+
if (!entry || !fs34.existsSync(entry.tempDbPath)) return null;
|
|
20715
21057
|
const adapter = openBetterSqliteDatabase(entry.tempDbPath, {
|
|
20716
21058
|
readonly: true,
|
|
20717
21059
|
nativeBinding: this.nativeBinding
|
|
@@ -20756,21 +21098,21 @@ var MergeSessionCache = class {
|
|
|
20756
21098
|
};
|
|
20757
21099
|
|
|
20758
21100
|
// ../../packages/node-runtime/src/services/push-importer.ts
|
|
20759
|
-
import * as
|
|
20760
|
-
var
|
|
20761
|
-
var
|
|
20762
|
-
function
|
|
21101
|
+
import * as fs35 from "fs";
|
|
21102
|
+
var SYSTEM_SENDER_ID3 = "SYSTEM";
|
|
21103
|
+
var SYSTEM_MEMBER_NAME2 = "\u7CFB\u7EDF\u6D88\u606F";
|
|
21104
|
+
function isRecord5(value) {
|
|
20763
21105
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20764
21106
|
}
|
|
20765
21107
|
function validateOptionalString2(value, field) {
|
|
20766
21108
|
return value !== void 0 && typeof value !== "string" ? `${field} must be a string` : null;
|
|
20767
21109
|
}
|
|
20768
21110
|
function validatePayload(payload, isNew) {
|
|
20769
|
-
if (!
|
|
21111
|
+
if (!isRecord5(payload)) return "payload must be an object";
|
|
20770
21112
|
const messages = payload.messages;
|
|
20771
21113
|
if (!Array.isArray(messages) || messages.length === 0) return "messages is required and must be a non-empty array";
|
|
20772
21114
|
if (payload.chatlab !== void 0) {
|
|
20773
|
-
if (!
|
|
21115
|
+
if (!isRecord5(payload.chatlab)) return "chatlab must be an object";
|
|
20774
21116
|
if (typeof payload.chatlab.version !== "string" || payload.chatlab.version.length === 0)
|
|
20775
21117
|
return "chatlab.version must be a string";
|
|
20776
21118
|
if (typeof payload.chatlab.exportedAt !== "number" || !Number.isFinite(payload.chatlab.exportedAt))
|
|
@@ -20783,7 +21125,7 @@ function validatePayload(payload, isNew) {
|
|
|
20783
21125
|
if (!payload.meta) return "meta is required for new sessions";
|
|
20784
21126
|
}
|
|
20785
21127
|
if (payload.meta !== void 0) {
|
|
20786
|
-
if (!
|
|
21128
|
+
if (!isRecord5(payload.meta)) return "meta must be an object";
|
|
20787
21129
|
const metaFields = ["name", "platform", "type", "groupId", "groupAvatar", "ownerId"];
|
|
20788
21130
|
for (const field of metaFields) {
|
|
20789
21131
|
const error = validateOptionalString2(payload.meta[field], `meta.${field}`);
|
|
@@ -20793,7 +21135,7 @@ function validatePayload(payload, isNew) {
|
|
|
20793
21135
|
if (isNew && !payload.meta.platform) return "meta.platform is required";
|
|
20794
21136
|
if (isNew && !payload.meta.type) return "meta.type is required";
|
|
20795
21137
|
}
|
|
20796
|
-
if (payload.options !== void 0 && !
|
|
21138
|
+
if (payload.options !== void 0 && !isRecord5(payload.options)) return "options must be an object";
|
|
20797
21139
|
const { metaUpdateMode, memberUpdateMode } = payload.options ?? {};
|
|
20798
21140
|
if (metaUpdateMode !== void 0 && metaUpdateMode !== "patch" && metaUpdateMode !== "none") {
|
|
20799
21141
|
return `options.metaUpdateMode must be 'patch' or 'none'`;
|
|
@@ -20805,7 +21147,7 @@ function validatePayload(payload, isNew) {
|
|
|
20805
21147
|
if (payload.members) {
|
|
20806
21148
|
for (let i = 0; i < payload.members.length; i++) {
|
|
20807
21149
|
const member = payload.members[i];
|
|
20808
|
-
if (!
|
|
21150
|
+
if (!isRecord5(member)) return `members[${i}] must be an object`;
|
|
20809
21151
|
if (typeof member.platformId !== "string" || member.platformId.length === 0)
|
|
20810
21152
|
return `members[${i}].platformId must be a string`;
|
|
20811
21153
|
for (const field of ["accountName", "groupNickname", "avatar"]) {
|
|
@@ -20816,7 +21158,7 @@ function validatePayload(payload, isNew) {
|
|
|
20816
21158
|
if (!Array.isArray(member.roles)) return `members[${i}].roles must be an array`;
|
|
20817
21159
|
for (let j = 0; j < member.roles.length; j++) {
|
|
20818
21160
|
const role = member.roles[j];
|
|
20819
|
-
if (!
|
|
21161
|
+
if (!isRecord5(role) || typeof role.id !== "string" || role.id.length === 0)
|
|
20820
21162
|
return `members[${i}].roles[${j}].id must be a string`;
|
|
20821
21163
|
}
|
|
20822
21164
|
}
|
|
@@ -20824,7 +21166,7 @@ function validatePayload(payload, isNew) {
|
|
|
20824
21166
|
}
|
|
20825
21167
|
for (let i = 0; i < messages.length; i++) {
|
|
20826
21168
|
const msg = messages[i];
|
|
20827
|
-
if (!
|
|
21169
|
+
if (!isRecord5(msg)) return `messages[${i}] must be an object`;
|
|
20828
21170
|
if (typeof msg.sender !== "string" || msg.sender.length === 0) return `messages[${i}].sender must be a string`;
|
|
20829
21171
|
if (typeof msg.timestamp !== "number" || !Number.isFinite(msg.timestamp) || msg.timestamp <= 0)
|
|
20830
21172
|
return `messages[${i}].timestamp must be a positive number`;
|
|
@@ -20844,17 +21186,17 @@ function validatePayload(payload, isNew) {
|
|
|
20844
21186
|
}
|
|
20845
21187
|
function queryStats(db) {
|
|
20846
21188
|
const row = db.prepare("SELECT COUNT(*) as total, MIN(ts) as first, MAX(ts) as last FROM message").get();
|
|
20847
|
-
const memberRow = db.prepare(`SELECT COUNT(*) as cnt FROM member WHERE COALESCE(account_name, '') != ?`).get(
|
|
21189
|
+
const memberRow = db.prepare(`SELECT COUNT(*) as cnt FROM member WHERE COALESCE(account_name, '') != ?`).get(SYSTEM_MEMBER_NAME2);
|
|
20848
21190
|
return { totalCount: row.total, memberCount: memberRow.cnt, firstTimestamp: row.first, lastTimestamp: row.last };
|
|
20849
21191
|
}
|
|
20850
21192
|
function normalizeSenderAccountName(sender, accountName) {
|
|
20851
|
-
return sender ===
|
|
21193
|
+
return sender === SYSTEM_SENDER_ID3 ? SYSTEM_MEMBER_NAME2 : accountName;
|
|
20852
21194
|
}
|
|
20853
21195
|
function normalizeSenderGroupNickname(sender, groupNickname) {
|
|
20854
|
-
return sender ===
|
|
21196
|
+
return sender === SYSTEM_SENDER_ID3 ? SYSTEM_MEMBER_NAME2 : groupNickname;
|
|
20855
21197
|
}
|
|
20856
21198
|
function isCountedMember(platformId) {
|
|
20857
|
-
return platformId !==
|
|
21199
|
+
return platformId !== SYSTEM_SENDER_ID3;
|
|
20858
21200
|
}
|
|
20859
21201
|
function registerPushMessageAndCheckDuplicate(message, dedupState) {
|
|
20860
21202
|
return registerMessageAndCheckDuplicate(
|
|
@@ -21123,7 +21465,7 @@ async function executePushImportUnlocked(deps, sessionId, payload) {
|
|
|
21123
21465
|
return { ok: false, reason: "invalid_payload", message: "sessionId contains invalid characters" };
|
|
21124
21466
|
}
|
|
21125
21467
|
const dbPath = deps.getDbPath(sessionId);
|
|
21126
|
-
const isNew = !
|
|
21468
|
+
const isNew = !fs35.existsSync(dbPath);
|
|
21127
21469
|
const validationError = validatePayload(payload, isNew);
|
|
21128
21470
|
if (validationError) {
|
|
21129
21471
|
return { ok: false, reason: "invalid_payload", message: validationError };
|
|
@@ -21230,6 +21572,7 @@ export {
|
|
|
21230
21572
|
createChatLabTempDir,
|
|
21231
21573
|
removeChatLabTempDir,
|
|
21232
21574
|
validateChatLabFile,
|
|
21575
|
+
rebaseChatLabDemoDocuments,
|
|
21233
21576
|
detectFormat,
|
|
21234
21577
|
detectAllFormats,
|
|
21235
21578
|
getSupportedFormats,
|
|
@@ -21357,6 +21700,7 @@ export {
|
|
|
21357
21700
|
createAuthProfileLlmConfigStore,
|
|
21358
21701
|
CustomProviderStore,
|
|
21359
21702
|
CustomModelStore,
|
|
21703
|
+
createLlmRuntimeStores,
|
|
21360
21704
|
normalizeAnthropicBaseUrl,
|
|
21361
21705
|
normalizeOpenAICompatibleBaseUrl,
|
|
21362
21706
|
buildPiModel,
|
|
@@ -21449,4 +21793,4 @@ export {
|
|
|
21449
21793
|
hashImportBody,
|
|
21450
21794
|
ImportIdempotencyCache
|
|
21451
21795
|
};
|
|
21452
|
-
//# sourceMappingURL=chunk-
|
|
21796
|
+
//# sourceMappingURL=chunk-RRC6U56Y.mjs.map
|