chatlab-cli 0.21.1 → 0.22.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/README.md +5 -5
- package/dist/{chunk-2AIOU3PW.mjs → chunk-6NB475AA.mjs} +12 -3
- package/dist/chunk-6NB475AA.mjs.map +1 -0
- package/dist/{chunk-OZWXLRJL.mjs → chunk-LZ3W6NS5.mjs} +24 -15
- package/dist/chunk-LZ3W6NS5.mjs.map +1 -0
- package/dist/{chunk-OQVKZTVD.mjs → chunk-OC2W5Q5T.mjs} +2 -2
- package/dist/{chunk-AIR7EAF4.mjs → chunk-QRC3RSER.mjs} +2 -2
- package/dist/{chunk-7HQWGLX6.mjs → chunk-SQKT45MM.mjs} +174 -120
- package/dist/chunk-SQKT45MM.mjs.map +1 -0
- package/dist/chunk-VSOWNKPA.mjs +49 -0
- package/dist/{chunk-LI4X52E7.mjs → chunk-XPBPKH6B.mjs} +350 -100
- package/dist/chunk-XPBPKH6B.mjs.map +1 -0
- package/dist/{chunk-4GI2UPCS.mjs → chunk-Z2LYMKCC.mjs} +2 -2
- package/dist/cli.mjs +4 -3
- package/dist/{http-DHQI4G5J.mjs → http-O5P4BYXU.mjs} +8 -7
- package/dist/{import-CQWGIMZQ.mjs → import-BDLL3DG7.mjs} +5 -4
- package/dist/index.mjs +8 -7
- package/dist/{mcp-7Q3FEI3Z.mjs → mcp-L2TPZFE7.mjs} +8 -7
- package/dist/mcp-L2TPZFE7.mjs.map +1 -0
- package/dist/{src-QBT5SYW5.mjs → src-FVJL5ENA.mjs} +3 -2
- package/dist/{stream-import-VG7RP6KJ.mjs → stream-import-ZTEW3YVL.mjs} +4 -3
- package/dist/stream-import-ZTEW3YVL.mjs.map +1 -0
- package/dist/update-checker-MQMQ6A4B.mjs +191 -0
- package/dist/update-checker-MQMQ6A4B.mjs.map +1 -0
- package/dist-web/assets/{DebugToolsPanel-CoBtqb--.css → DebugToolsPanel-DkbsB6lr.css} +1 -1
- package/dist-web/assets/{DebugToolsPanel.vue_vue_type_script_setup_true_lang-CpFGhsl5.js → DebugToolsPanel.vue_vue_type_script_setup_true_lang-CqacsKDU.js} +5 -5
- package/dist-web/assets/{EChartWordcloud-BYLFxPAX.js → EChartWordcloud-Ubal_aYg.js} +1 -1
- package/dist-web/assets/{MessageExportModal-DTgxz1eQ.js → MessageExportModal-D1GY6WSV.js} +1 -1
- package/dist-web/assets/{electron-CTK4NJag.js → electron-CRSL7qPM.js} +1 -1
- package/dist-web/assets/{electron-H65bUnhW.js → electron-CsUM2O_Y.js} +1 -1
- package/dist-web/assets/{fetch-CTZXLLcn.js → fetch-BOogCPfg.js} +1 -1
- package/dist-web/assets/{fetch-C2vUkdnA.js → fetch-CxwnEEqk.js} +1 -1
- package/dist-web/assets/index-CM29Kc4p.js +173 -0
- package/dist-web/assets/index-D183wYuz.js +7 -0
- package/dist-web/assets/{index-DeG0EHOT.js → index-DOwQB7In.js} +1 -1
- package/dist-web/assets/index-DSpvXged.css +1 -0
- package/dist-web/assets/{index-C4B0hv6C.js → index-DTxRy2FH.js} +4 -4
- package/dist-web/assets/{index-DuhN8jAf.js → index-grds3iG-.js} +2 -2
- package/dist-web/assets/logo-DXIuG_WE.svg +17 -0
- package/dist-web/assets/{vendor-echarts-C13vDgZW.js → vendor-echarts-C5u62NnM.js} +1 -1
- package/dist-web/assets/{vendor-echarts-wordcloud-uVdwYsYa.js → vendor-echarts-wordcloud-CZ9gsX8l.js} +1 -1
- package/dist-web/assets/{vendor-nuxt-ui-CYMNNdeD.js → vendor-nuxt-ui-7OAuiz_i.js} +1 -1
- package/dist-web/assets/{vendor-zrender-5DcYjSZk.js → vendor-zrender-DFl4U2Oe.js} +1 -1
- package/dist-web/assets/{web-DImo6Kjz.js → web-Cx5APyCN.js} +1 -1
- package/dist-web/index.html +3 -3
- package/package.json +4 -3
- package/dist/chunk-2AIOU3PW.mjs.map +0 -1
- package/dist/chunk-7HQWGLX6.mjs.map +0 -1
- package/dist/chunk-LI4X52E7.mjs.map +0 -1
- package/dist/chunk-OZWXLRJL.mjs.map +0 -1
- package/dist/mcp-7Q3FEI3Z.mjs.map +0 -1
- package/dist-web/assets/index-B8867dX7.css +0 -1
- package/dist-web/assets/index-DUXf21MT.js +0 -173
- package/dist-web/assets/index-DZiH2cC1.js +0 -7
- /package/dist/{chunk-OQVKZTVD.mjs.map → chunk-OC2W5Q5T.mjs.map} +0 -0
- /package/dist/{chunk-AIR7EAF4.mjs.map → chunk-QRC3RSER.mjs.map} +0 -0
- /package/dist/{http-DHQI4G5J.mjs.map → chunk-VSOWNKPA.mjs.map} +0 -0
- /package/dist/{chunk-4GI2UPCS.mjs.map → chunk-Z2LYMKCC.mjs.map} +0 -0
- /package/dist/{import-CQWGIMZQ.mjs.map → http-O5P4BYXU.mjs.map} +0 -0
- /package/dist/{src-QBT5SYW5.mjs.map → import-BDLL3DG7.mjs.map} +0 -0
- /package/dist/{stream-import-VG7RP6KJ.mjs.map → src-FVJL5ENA.mjs.map} +0 -0
|
@@ -7,20 +7,21 @@ const __dirname = __pathDirname(__filename);
|
|
|
7
7
|
import {
|
|
8
8
|
importData,
|
|
9
9
|
parseFile
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-OC2W5Q5T.mjs";
|
|
11
11
|
import {
|
|
12
12
|
analyzeIncrementalImport,
|
|
13
13
|
analyzeNewImport,
|
|
14
14
|
incrementalImport,
|
|
15
15
|
streamImport
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-QRC3RSER.mjs";
|
|
17
17
|
import {
|
|
18
18
|
AGENT_TOOL_REGISTRY,
|
|
19
19
|
CoreDataProvider
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-Z2LYMKCC.mjs";
|
|
21
21
|
import {
|
|
22
|
-
getVersion
|
|
23
|
-
|
|
22
|
+
getVersion,
|
|
23
|
+
resolveCliPath
|
|
24
|
+
} from "./chunk-6NB475AA.mjs";
|
|
24
25
|
import {
|
|
25
26
|
AIConversationManager,
|
|
26
27
|
ALL_MIGRATIONS,
|
|
@@ -114,11 +115,10 @@ import {
|
|
|
114
115
|
verifyCliDataPath,
|
|
115
116
|
writeAuthProfile,
|
|
116
117
|
writeConfigField
|
|
117
|
-
} from "./chunk-
|
|
118
|
+
} from "./chunk-SQKT45MM.mjs";
|
|
118
119
|
|
|
119
120
|
// src/http/index.ts
|
|
120
121
|
import * as fs14 from "fs";
|
|
121
|
-
import * as path15 from "path";
|
|
122
122
|
import * as crypto5 from "crypto";
|
|
123
123
|
|
|
124
124
|
// src/http/server.ts
|
|
@@ -207,6 +207,10 @@ async function authHook(request, reply) {
|
|
|
207
207
|
if (!cachedToken) return;
|
|
208
208
|
if (request.url.startsWith("/_web/")) return;
|
|
209
209
|
if (webModeEnabled && !request.url.startsWith("/api/")) return;
|
|
210
|
+
return requireBearerToken(request, reply);
|
|
211
|
+
}
|
|
212
|
+
function requireBearerToken(request, reply) {
|
|
213
|
+
if (!cachedToken) return;
|
|
210
214
|
const authHeader = request.headers.authorization;
|
|
211
215
|
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
|
212
216
|
const err = unauthorized();
|
|
@@ -492,7 +496,7 @@ function registerSessionRoutes(server2, dbManager2) {
|
|
|
492
496
|
|
|
493
497
|
// src/http/routes/web/index.ts
|
|
494
498
|
import * as os3 from "os";
|
|
495
|
-
import * as
|
|
499
|
+
import * as path6 from "path";
|
|
496
500
|
|
|
497
501
|
// src/merger/merge-cache.ts
|
|
498
502
|
import * as fs from "fs";
|
|
@@ -653,7 +657,6 @@ function registerMemberRoutes(server2, adapter) {
|
|
|
653
657
|
|
|
654
658
|
// src/http/routes/web/helpers.ts
|
|
655
659
|
import * as fs2 from "fs";
|
|
656
|
-
import * as path2 from "path";
|
|
657
660
|
function parseTimeFilter(query) {
|
|
658
661
|
const { startTs, endTs, memberId } = query;
|
|
659
662
|
if (!startTs && !endTs && !memberId) return void 0;
|
|
@@ -665,7 +668,7 @@ function parseTimeFilter(query) {
|
|
|
665
668
|
}
|
|
666
669
|
function resolveNativeBinding() {
|
|
667
670
|
if (process.versions.electron) return void 0;
|
|
668
|
-
const nativePath =
|
|
671
|
+
const nativePath = resolveCliPath("native/better_sqlite3.node");
|
|
669
672
|
if (fs2.existsSync(nativePath)) return nativePath;
|
|
670
673
|
return void 0;
|
|
671
674
|
}
|
|
@@ -879,10 +882,10 @@ function registerSessionIndexRoutes(server2, adapter) {
|
|
|
879
882
|
|
|
880
883
|
// src/ai/llm-config.ts
|
|
881
884
|
import * as fs3 from "fs";
|
|
882
|
-
import * as
|
|
885
|
+
import * as path2 from "path";
|
|
883
886
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
884
887
|
function loadLlmConfig(aiDataDir) {
|
|
885
|
-
const configPath =
|
|
888
|
+
const configPath = path2.join(aiDataDir, "llm-config.json");
|
|
886
889
|
if (!fs3.existsSync(configPath)) {
|
|
887
890
|
return { configs: [], defaultAssistant: null, fastModel: null };
|
|
888
891
|
}
|
|
@@ -924,7 +927,7 @@ function getDefaultAssistantConfig(aiDataDir) {
|
|
|
924
927
|
}
|
|
925
928
|
var MAX_CONFIG_COUNT = 99;
|
|
926
929
|
function saveLlmConfig(aiDataDir, store) {
|
|
927
|
-
const configPath =
|
|
930
|
+
const configPath = path2.join(aiDataDir, "llm-config.json");
|
|
928
931
|
const toSave = {
|
|
929
932
|
...store,
|
|
930
933
|
configs: store.configs.map((c) => {
|
|
@@ -1028,7 +1031,7 @@ function setFastModelSlot(aiDataDir, slot) {
|
|
|
1028
1031
|
return { success: true };
|
|
1029
1032
|
}
|
|
1030
1033
|
function loadRawConfigStore(aiDataDir) {
|
|
1031
|
-
const configPath =
|
|
1034
|
+
const configPath = path2.join(aiDataDir, "llm-config.json");
|
|
1032
1035
|
if (!fs3.existsSync(configPath)) {
|
|
1033
1036
|
return { configs: [], defaultAssistant: null, fastModel: null };
|
|
1034
1037
|
}
|
|
@@ -1062,10 +1065,11 @@ function createSummaryDeps(dbManager2) {
|
|
|
1062
1065
|
function registerSummaryRoutes(server2, dbManager2, adapter) {
|
|
1063
1066
|
const deps = createSummaryDeps(dbManager2);
|
|
1064
1067
|
server2.post("/_web/sessions/:id/summaries/generate", async (request, reply) => {
|
|
1065
|
-
const { chatSessionId, locale, forceRegenerate } = request.body;
|
|
1068
|
+
const { chatSessionId, locale, forceRegenerate, strategy } = request.body;
|
|
1066
1069
|
const result = await summary_service_exports.generateSummary(adapter, request.params.id, chatSessionId, deps, {
|
|
1067
1070
|
locale,
|
|
1068
|
-
forceRegenerate
|
|
1071
|
+
forceRegenerate,
|
|
1072
|
+
strategy
|
|
1069
1073
|
});
|
|
1070
1074
|
if ("error" in result && !result.success) {
|
|
1071
1075
|
return reply.code(400).send({ error: result.error });
|
|
@@ -1083,18 +1087,22 @@ function registerSummaryRoutes(server2, dbManager2, adapter) {
|
|
|
1083
1087
|
}
|
|
1084
1088
|
return result;
|
|
1085
1089
|
});
|
|
1090
|
+
server2.post("/_web/sessions/:id/summaries/check-can-generate", async (request) => {
|
|
1091
|
+
const { chatSessionIds } = request.body;
|
|
1092
|
+
return summary_service_exports.checkCanGenerate(adapter, request.params.id, chatSessionIds);
|
|
1093
|
+
});
|
|
1086
1094
|
}
|
|
1087
1095
|
|
|
1088
1096
|
// src/http/routes/web/import.ts
|
|
1089
1097
|
import * as fs4 from "fs";
|
|
1090
1098
|
import * as os from "os";
|
|
1091
|
-
import * as
|
|
1099
|
+
import * as path3 from "path";
|
|
1092
1100
|
var DEMO_BASE_URL = "https://chatlab.fun/assets/demo";
|
|
1093
1101
|
function cleanupTemp(...paths) {
|
|
1094
1102
|
for (const p of paths) {
|
|
1095
1103
|
try {
|
|
1096
|
-
const
|
|
1097
|
-
if (
|
|
1104
|
+
const stat2 = fs4.statSync(p);
|
|
1105
|
+
if (stat2.isDirectory()) {
|
|
1098
1106
|
fs4.rmSync(p, { recursive: true, force: true });
|
|
1099
1107
|
} else {
|
|
1100
1108
|
fs4.unlinkSync(p);
|
|
@@ -1110,8 +1118,8 @@ function registerImportRoutes(server2, dbManager2) {
|
|
|
1110
1118
|
server2.post("/_web/detect-format", async (request, reply) => {
|
|
1111
1119
|
const data = await request.file();
|
|
1112
1120
|
if (!data) return reply.code(400).send({ error: "No file uploaded" });
|
|
1113
|
-
const tmpDir = fs4.mkdtempSync(
|
|
1114
|
-
const tmpPath =
|
|
1121
|
+
const tmpDir = fs4.mkdtempSync(path3.join(os.tmpdir(), "chatlab-detect-"));
|
|
1122
|
+
const tmpPath = path3.join(tmpDir, data.filename || "upload");
|
|
1115
1123
|
try {
|
|
1116
1124
|
const chunks = [];
|
|
1117
1125
|
for await (const chunk of data.file) {
|
|
@@ -1128,8 +1136,8 @@ function registerImportRoutes(server2, dbManager2) {
|
|
|
1128
1136
|
server2.post("/_web/scan-multi-chat", async (request, reply) => {
|
|
1129
1137
|
const data = await request.file();
|
|
1130
1138
|
if (!data) return reply.code(400).send({ error: "No file uploaded" });
|
|
1131
|
-
const tmpDir = fs4.mkdtempSync(
|
|
1132
|
-
const tmpPath =
|
|
1139
|
+
const tmpDir = fs4.mkdtempSync(path3.join(os.tmpdir(), "chatlab-scan-"));
|
|
1140
|
+
const tmpPath = path3.join(tmpDir, data.filename || "upload");
|
|
1133
1141
|
try {
|
|
1134
1142
|
const chunks = [];
|
|
1135
1143
|
for await (const chunk of data.file) {
|
|
@@ -1145,8 +1153,8 @@ function registerImportRoutes(server2, dbManager2) {
|
|
|
1145
1153
|
server2.post("/_web/import", async (request, reply) => {
|
|
1146
1154
|
const data = await request.file();
|
|
1147
1155
|
if (!data) return reply.code(400).send({ error: "No file uploaded" });
|
|
1148
|
-
const tmpDir = fs4.mkdtempSync(
|
|
1149
|
-
const tmpPath =
|
|
1156
|
+
const tmpDir = fs4.mkdtempSync(path3.join(os.tmpdir(), "chatlab-import-"));
|
|
1157
|
+
const tmpPath = path3.join(tmpDir, data.filename || "upload");
|
|
1150
1158
|
const chunks = [];
|
|
1151
1159
|
for await (const chunk of data.file) {
|
|
1152
1160
|
chunks.push(chunk);
|
|
@@ -1194,7 +1202,7 @@ data: ${JSON.stringify(eventData)}
|
|
|
1194
1202
|
server2.post("/_web/import-directory", async (request, reply) => {
|
|
1195
1203
|
const parts = request.parts();
|
|
1196
1204
|
if (!parts) return reply.code(400).send({ error: "No files uploaded" });
|
|
1197
|
-
const tmpDir = fs4.mkdtempSync(
|
|
1205
|
+
const tmpDir = fs4.mkdtempSync(path3.join(os.tmpdir(), "chatlab-dir-import-"));
|
|
1198
1206
|
const relativePaths = [];
|
|
1199
1207
|
const fileBuffers = [];
|
|
1200
1208
|
try {
|
|
@@ -1222,9 +1230,9 @@ data: ${JSON.stringify(eventData)}
|
|
|
1222
1230
|
if (segments.length > 1) {
|
|
1223
1231
|
relPath = segments.slice(1).join("/");
|
|
1224
1232
|
}
|
|
1225
|
-
const targetPath =
|
|
1226
|
-
if (!targetPath.startsWith(tmpDir +
|
|
1227
|
-
fs4.mkdirSync(
|
|
1233
|
+
const targetPath = path3.resolve(tmpDir, relPath);
|
|
1234
|
+
if (!targetPath.startsWith(tmpDir + path3.sep)) continue;
|
|
1235
|
+
fs4.mkdirSync(path3.dirname(targetPath), { recursive: true });
|
|
1228
1236
|
fs4.writeFileSync(targetPath, fileBuffers[i].data);
|
|
1229
1237
|
}
|
|
1230
1238
|
const entryPath = findEntryFileInDirectory(tmpDir);
|
|
@@ -1270,8 +1278,8 @@ data: ${JSON.stringify({ success: false, error: err instanceof Error ? err.messa
|
|
|
1270
1278
|
const sessionId = request.params.id;
|
|
1271
1279
|
const data = await request.file();
|
|
1272
1280
|
if (!data) return reply.code(400).send({ error: "No file uploaded" });
|
|
1273
|
-
const tmpDir = fs4.mkdtempSync(
|
|
1274
|
-
const tmpPath =
|
|
1281
|
+
const tmpDir = fs4.mkdtempSync(path3.join(os.tmpdir(), "chatlab-inc-"));
|
|
1282
|
+
const tmpPath = path3.join(tmpDir, data.filename || "upload");
|
|
1275
1283
|
const chunks = [];
|
|
1276
1284
|
for await (const chunk of data.file) {
|
|
1277
1285
|
chunks.push(chunk);
|
|
@@ -1308,8 +1316,8 @@ data: ${JSON.stringify(eventData)}
|
|
|
1308
1316
|
const sessionId = request.params.id;
|
|
1309
1317
|
const data = await request.file();
|
|
1310
1318
|
if (!data) return reply.code(400).send({ error: "No file uploaded" });
|
|
1311
|
-
const tmpDir = fs4.mkdtempSync(
|
|
1312
|
-
const tmpPath =
|
|
1319
|
+
const tmpDir = fs4.mkdtempSync(path3.join(os.tmpdir(), "chatlab-analyze-"));
|
|
1320
|
+
const tmpPath = path3.join(tmpDir, data.filename || "upload");
|
|
1313
1321
|
const chunks = [];
|
|
1314
1322
|
for await (const chunk of data.file) {
|
|
1315
1323
|
chunks.push(chunk);
|
|
@@ -1326,8 +1334,8 @@ data: ${JSON.stringify(eventData)}
|
|
|
1326
1334
|
server2.post("/_web/import/analyze", async (request, reply) => {
|
|
1327
1335
|
const data = await request.file();
|
|
1328
1336
|
if (!data) return reply.code(400).send({ error: "No file uploaded" });
|
|
1329
|
-
const tmpDir = fs4.mkdtempSync(
|
|
1330
|
-
const tmpPath =
|
|
1337
|
+
const tmpDir = fs4.mkdtempSync(path3.join(os.tmpdir(), "chatlab-analyze-"));
|
|
1338
|
+
const tmpPath = path3.join(tmpDir, data.filename || "upload");
|
|
1331
1339
|
const chunks = [];
|
|
1332
1340
|
for await (const chunk of data.file) {
|
|
1333
1341
|
chunks.push(chunk);
|
|
@@ -1355,9 +1363,9 @@ data: ${JSON.stringify(eventData)}
|
|
|
1355
1363
|
|
|
1356
1364
|
`);
|
|
1357
1365
|
}
|
|
1358
|
-
const tmpDir = fs4.mkdtempSync(
|
|
1359
|
-
const groupPath =
|
|
1360
|
-
const privatePath =
|
|
1366
|
+
const tmpDir = fs4.mkdtempSync(path3.join(os.tmpdir(), "chatlab-demo-"));
|
|
1367
|
+
const groupPath = path3.join(tmpDir, "demo-group.json");
|
|
1368
|
+
const privatePath = path3.join(tmpDir, "demo-private.json");
|
|
1361
1369
|
try {
|
|
1362
1370
|
sendEvent("progress", { stage: "downloading", current: 1, total: 2 });
|
|
1363
1371
|
const groupResp = await fetch(`${DEMO_BASE_URL}/${locale}/demo-group.json`, {
|
|
@@ -1397,13 +1405,13 @@ data: ${JSON.stringify(eventData)}
|
|
|
1397
1405
|
// src/http/routes/web/merge.ts
|
|
1398
1406
|
import * as fs5 from "fs";
|
|
1399
1407
|
import * as os2 from "os";
|
|
1400
|
-
import * as
|
|
1408
|
+
import * as path4 from "path";
|
|
1401
1409
|
function registerMergeRoutes(server2, dbManager2, mergeCache) {
|
|
1402
1410
|
server2.post("/_web/merge/parse", async (request, reply) => {
|
|
1403
1411
|
const data = await request.file();
|
|
1404
1412
|
if (!data) return reply.code(400).send({ error: "No file uploaded" });
|
|
1405
|
-
const tmpDir = fs5.mkdtempSync(
|
|
1406
|
-
const tmpPath =
|
|
1413
|
+
const tmpDir = fs5.mkdtempSync(path4.join(os2.tmpdir(), "chatlab-merge-"));
|
|
1414
|
+
const tmpPath = path4.join(tmpDir, data.filename || "upload");
|
|
1407
1415
|
const chunks = [];
|
|
1408
1416
|
for await (const chunk of data.file) {
|
|
1409
1417
|
chunks.push(chunk);
|
|
@@ -1412,7 +1420,7 @@ function registerMergeRoutes(server2, dbManager2, mergeCache) {
|
|
|
1412
1420
|
try {
|
|
1413
1421
|
const result = await streamParseFileInfo(tmpPath, {
|
|
1414
1422
|
createTempDatabase(sourceFilePath) {
|
|
1415
|
-
return mergeCache.createTempDatabase(
|
|
1423
|
+
return mergeCache.createTempDatabase(path4.basename(sourceFilePath));
|
|
1416
1424
|
},
|
|
1417
1425
|
onProgress() {
|
|
1418
1426
|
}
|
|
@@ -1477,10 +1485,10 @@ function registerMergeRoutes(server2, dbManager2, mergeCache) {
|
|
|
1477
1485
|
const merged = buildMergedOutput(dataSources, outputName);
|
|
1478
1486
|
let sessionId;
|
|
1479
1487
|
if (andImport) {
|
|
1480
|
-
const { streamImport: serverStreamImport } = await import("./stream-import-
|
|
1488
|
+
const { streamImport: serverStreamImport } = await import("./stream-import-ZTEW3YVL.mjs");
|
|
1481
1489
|
const jsonData = JSON.stringify(merged.chatLabData);
|
|
1482
|
-
const tmpDir = fs5.mkdtempSync(
|
|
1483
|
-
const tmpPath =
|
|
1490
|
+
const tmpDir = fs5.mkdtempSync(path4.join(os2.tmpdir(), "chatlab-merged-"));
|
|
1491
|
+
const tmpPath = path4.join(tmpDir, `${outputName}.json`);
|
|
1484
1492
|
fs5.writeFileSync(tmpPath, jsonData, "utf-8");
|
|
1485
1493
|
try {
|
|
1486
1494
|
const importResult = await serverStreamImport(dbManager2, tmpPath);
|
|
@@ -1530,7 +1538,7 @@ function registerMergeRoutes(server2, dbManager2, mergeCache) {
|
|
|
1530
1538
|
const db = ensureDb2(dbManager2, sid);
|
|
1531
1539
|
const exported = exportSessionToJson(db);
|
|
1532
1540
|
const { db: tempDb, tempDbPath } = mergeCache.createTempDatabase(exported.meta.name);
|
|
1533
|
-
const { TempDbWriter } = await import("./src-
|
|
1541
|
+
const { TempDbWriter } = await import("./src-FVJL5ENA.mjs");
|
|
1534
1542
|
const writer = new TempDbWriter(tempDb);
|
|
1535
1543
|
writer.writeMeta({
|
|
1536
1544
|
name: exported.meta.name,
|
|
@@ -1592,8 +1600,192 @@ function registerExportRoutes(server2, adapter) {
|
|
|
1592
1600
|
|
|
1593
1601
|
// src/http/routes/web/cache.ts
|
|
1594
1602
|
import * as fs6 from "fs";
|
|
1595
|
-
import * as
|
|
1596
|
-
|
|
1603
|
+
import * as fsp from "fs/promises";
|
|
1604
|
+
import * as path5 from "path";
|
|
1605
|
+
import { execFile } from "child_process";
|
|
1606
|
+
function runExecFile(file, args, runner = execFile) {
|
|
1607
|
+
return new Promise((resolve2, reject) => {
|
|
1608
|
+
runner(file, args, (error) => {
|
|
1609
|
+
if (error) {
|
|
1610
|
+
reject(error);
|
|
1611
|
+
return;
|
|
1612
|
+
}
|
|
1613
|
+
resolve2();
|
|
1614
|
+
});
|
|
1615
|
+
});
|
|
1616
|
+
}
|
|
1617
|
+
async function openDirectoryPath(dirPath, platform = process.platform, runner) {
|
|
1618
|
+
if (platform === "darwin") {
|
|
1619
|
+
await runExecFile("open", [dirPath], runner);
|
|
1620
|
+
} else if (platform === "win32") {
|
|
1621
|
+
await runExecFile("explorer.exe", [dirPath], runner);
|
|
1622
|
+
} else {
|
|
1623
|
+
await runExecFile("xdg-open", [dirPath], runner);
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1626
|
+
async function showPathInFolder(filePath, platform = process.platform, runner) {
|
|
1627
|
+
if (platform === "darwin") {
|
|
1628
|
+
await runExecFile("open", ["-R", filePath], runner);
|
|
1629
|
+
} else if (platform === "win32") {
|
|
1630
|
+
await runExecFile("explorer.exe", [`/select,${filePath}`], runner);
|
|
1631
|
+
} else {
|
|
1632
|
+
await runExecFile("xdg-open", [path5.dirname(filePath)], runner);
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
async function getDirSize(dirPath) {
|
|
1636
|
+
let totalSize = 0;
|
|
1637
|
+
try {
|
|
1638
|
+
if (!fs6.existsSync(dirPath)) return 0;
|
|
1639
|
+
const files = await fsp.readdir(dirPath, { withFileTypes: true });
|
|
1640
|
+
for (const file of files) {
|
|
1641
|
+
const filePath = path5.join(dirPath, file.name);
|
|
1642
|
+
if (file.isDirectory()) {
|
|
1643
|
+
totalSize += await getDirSize(filePath);
|
|
1644
|
+
} else {
|
|
1645
|
+
const stat2 = await fsp.stat(filePath);
|
|
1646
|
+
totalSize += stat2.size;
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
} catch {
|
|
1650
|
+
}
|
|
1651
|
+
return totalSize;
|
|
1652
|
+
}
|
|
1653
|
+
async function getFileCount(dirPath) {
|
|
1654
|
+
let count = 0;
|
|
1655
|
+
try {
|
|
1656
|
+
if (!fs6.existsSync(dirPath)) return 0;
|
|
1657
|
+
const files = await fsp.readdir(dirPath, { withFileTypes: true });
|
|
1658
|
+
for (const file of files) {
|
|
1659
|
+
const filePath = path5.join(dirPath, file.name);
|
|
1660
|
+
if (file.isDirectory()) {
|
|
1661
|
+
count += await getFileCount(filePath);
|
|
1662
|
+
} else {
|
|
1663
|
+
count++;
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
} catch {
|
|
1667
|
+
}
|
|
1668
|
+
return count;
|
|
1669
|
+
}
|
|
1670
|
+
function registerCacheRoutes(server2, pathProvider) {
|
|
1671
|
+
const downloadsDir = pathProvider.getDownloadsDir();
|
|
1672
|
+
server2.get("/_web/cache/info", async () => {
|
|
1673
|
+
const directories = [
|
|
1674
|
+
{
|
|
1675
|
+
id: "databases",
|
|
1676
|
+
name: "settings.storage.cache.databases.name",
|
|
1677
|
+
description: "settings.storage.cache.databases.description",
|
|
1678
|
+
path: pathProvider.getDatabaseDir(),
|
|
1679
|
+
icon: "i-heroicons-circle-stack",
|
|
1680
|
+
canClear: false
|
|
1681
|
+
},
|
|
1682
|
+
{
|
|
1683
|
+
id: "ai",
|
|
1684
|
+
name: "settings.storage.cache.ai.name",
|
|
1685
|
+
description: "settings.storage.cache.ai.description",
|
|
1686
|
+
path: pathProvider.getAiDataDir(),
|
|
1687
|
+
icon: "i-heroicons-sparkles",
|
|
1688
|
+
canClear: false
|
|
1689
|
+
},
|
|
1690
|
+
{
|
|
1691
|
+
id: "cache",
|
|
1692
|
+
name: "settings.storage.cache.statsCache.name",
|
|
1693
|
+
description: "settings.storage.cache.statsCache.description",
|
|
1694
|
+
path: pathProvider.getCacheDir(),
|
|
1695
|
+
icon: "i-heroicons-bolt",
|
|
1696
|
+
canClear: true
|
|
1697
|
+
},
|
|
1698
|
+
{
|
|
1699
|
+
id: "logs",
|
|
1700
|
+
name: "settings.storage.cache.logs.name",
|
|
1701
|
+
description: "settings.storage.cache.logs.description",
|
|
1702
|
+
path: pathProvider.getLogsDir(),
|
|
1703
|
+
icon: "i-heroicons-document-text",
|
|
1704
|
+
canClear: true
|
|
1705
|
+
}
|
|
1706
|
+
];
|
|
1707
|
+
const results = await Promise.all(
|
|
1708
|
+
directories.map(async (dir) => {
|
|
1709
|
+
const [size, fileCount] = await Promise.all([getDirSize(dir.path), getFileCount(dir.path)]);
|
|
1710
|
+
return { ...dir, size, fileCount, exists: fs6.existsSync(dir.path) };
|
|
1711
|
+
})
|
|
1712
|
+
);
|
|
1713
|
+
return {
|
|
1714
|
+
baseDir: pathProvider.getUserDataDir(),
|
|
1715
|
+
systemDir: pathProvider.getSystemDir(),
|
|
1716
|
+
directories: results,
|
|
1717
|
+
totalSize: results.reduce((sum, d) => sum + d.size, 0)
|
|
1718
|
+
};
|
|
1719
|
+
});
|
|
1720
|
+
server2.post("/_web/cache/clear", async (request) => {
|
|
1721
|
+
const { cacheId } = request.body;
|
|
1722
|
+
const allowedDirs = {
|
|
1723
|
+
cache: pathProvider.getCacheDir(),
|
|
1724
|
+
logs: pathProvider.getLogsDir()
|
|
1725
|
+
};
|
|
1726
|
+
const dirPath = allowedDirs[cacheId];
|
|
1727
|
+
if (!dirPath) return { success: false, error: "Not allowed to clear this directory" };
|
|
1728
|
+
if (!fs6.existsSync(dirPath)) return { success: true };
|
|
1729
|
+
const files = await fsp.readdir(dirPath);
|
|
1730
|
+
for (const file of files) {
|
|
1731
|
+
const filePath = path5.join(dirPath, file);
|
|
1732
|
+
const stat2 = await fsp.stat(filePath);
|
|
1733
|
+
if (stat2.isDirectory()) {
|
|
1734
|
+
await fsp.rm(filePath, { recursive: true });
|
|
1735
|
+
} else {
|
|
1736
|
+
await fsp.unlink(filePath);
|
|
1737
|
+
}
|
|
1738
|
+
}
|
|
1739
|
+
return { success: true };
|
|
1740
|
+
});
|
|
1741
|
+
server2.post("/_web/cache/open-dir", async (request) => {
|
|
1742
|
+
const { cacheId } = request.body;
|
|
1743
|
+
const dirPaths = {
|
|
1744
|
+
base: pathProvider.getUserDataDir(),
|
|
1745
|
+
system: pathProvider.getSystemDir(),
|
|
1746
|
+
databases: pathProvider.getDatabaseDir(),
|
|
1747
|
+
cache: pathProvider.getCacheDir(),
|
|
1748
|
+
ai: pathProvider.getAiDataDir(),
|
|
1749
|
+
logs: pathProvider.getLogsDir(),
|
|
1750
|
+
downloads: downloadsDir
|
|
1751
|
+
};
|
|
1752
|
+
const dirPath = dirPaths[cacheId];
|
|
1753
|
+
if (!dirPath) return { success: false, error: "Unknown directory" };
|
|
1754
|
+
if (!fs6.existsSync(dirPath)) {
|
|
1755
|
+
await fsp.mkdir(dirPath, { recursive: true });
|
|
1756
|
+
}
|
|
1757
|
+
try {
|
|
1758
|
+
await openDirectoryPath(dirPath);
|
|
1759
|
+
} catch (error) {
|
|
1760
|
+
return { success: false, error: error instanceof Error ? error.message : String(error) };
|
|
1761
|
+
}
|
|
1762
|
+
return { success: true };
|
|
1763
|
+
});
|
|
1764
|
+
server2.get("/_web/cache/data-dir", async () => {
|
|
1765
|
+
const config = loadConfig();
|
|
1766
|
+
const isCustom = Boolean(config.data.user_data_dir || process.env.CHATLAB_DATA_DIR);
|
|
1767
|
+
return { path: pathProvider.getUserDataDir(), isCustom };
|
|
1768
|
+
});
|
|
1769
|
+
server2.get("/_web/cache/latest-import-log", async () => {
|
|
1770
|
+
const importLogDir = path5.join(pathProvider.getLogsDir(), "import");
|
|
1771
|
+
if (!fs6.existsSync(importLogDir)) {
|
|
1772
|
+
return { success: false, error: "Log directory not found" };
|
|
1773
|
+
}
|
|
1774
|
+
const files = await fsp.readdir(importLogDir);
|
|
1775
|
+
const logFiles = files.filter((f) => f.startsWith("import_") && f.endsWith(".log"));
|
|
1776
|
+
if (logFiles.length === 0) {
|
|
1777
|
+
return { success: false, error: "No import logs found" };
|
|
1778
|
+
}
|
|
1779
|
+
const fileStats = await Promise.all(
|
|
1780
|
+
logFiles.map(async (f) => {
|
|
1781
|
+
const filePath = path5.join(importLogDir, f);
|
|
1782
|
+
const stat2 = await fsp.stat(filePath);
|
|
1783
|
+
return { name: f, path: filePath, mtime: stat2.mtime.getTime() };
|
|
1784
|
+
})
|
|
1785
|
+
);
|
|
1786
|
+
fileStats.sort((a, b) => b.mtime - a.mtime);
|
|
1787
|
+
return { success: true, path: fileStats[0].path, name: fileStats[0].name };
|
|
1788
|
+
});
|
|
1597
1789
|
server2.post("/_web/cache/save-to-downloads", async (request) => {
|
|
1598
1790
|
const { filename, dataUrl } = request.body;
|
|
1599
1791
|
if (!filename || !dataUrl) {
|
|
@@ -1605,7 +1797,7 @@ function registerCacheRoutes(server2, downloadsDir) {
|
|
|
1605
1797
|
if (!fs6.existsSync(downloadsDir)) {
|
|
1606
1798
|
fs6.mkdirSync(downloadsDir, { recursive: true });
|
|
1607
1799
|
}
|
|
1608
|
-
const filePath =
|
|
1800
|
+
const filePath = path5.join(downloadsDir, filename);
|
|
1609
1801
|
fs6.writeFileSync(filePath, buffer);
|
|
1610
1802
|
return { success: true, filePath };
|
|
1611
1803
|
});
|
|
@@ -1614,26 +1806,46 @@ function registerCacheRoutes(server2, downloadsDir) {
|
|
|
1614
1806
|
if (!filePath) {
|
|
1615
1807
|
return { success: false, error: "filePath is required" };
|
|
1616
1808
|
}
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
exec(`open -R "${filePath}"`);
|
|
1622
|
-
} else if (platform === "win32") {
|
|
1623
|
-
exec(`explorer /select,"${filePath}"`);
|
|
1624
|
-
} else {
|
|
1625
|
-
exec(`xdg-open "${dir}"`);
|
|
1809
|
+
try {
|
|
1810
|
+
await showPathInFolder(filePath);
|
|
1811
|
+
} catch (error) {
|
|
1812
|
+
return { success: false, error: error instanceof Error ? error.message : String(error) };
|
|
1626
1813
|
}
|
|
1627
1814
|
return { success: true };
|
|
1628
1815
|
});
|
|
1629
1816
|
}
|
|
1630
1817
|
|
|
1631
1818
|
// src/http/routes/web/index.ts
|
|
1819
|
+
function isNewerVersion(latest, current) {
|
|
1820
|
+
const parse = (v) => {
|
|
1821
|
+
const [core, pre] = v.split("-", 2);
|
|
1822
|
+
const parts = core.split(".").map(Number);
|
|
1823
|
+
return { major: parts[0] || 0, minor: parts[1] || 0, patch: parts[2] || 0, pre };
|
|
1824
|
+
};
|
|
1825
|
+
const l = parse(latest);
|
|
1826
|
+
const c = parse(current);
|
|
1827
|
+
if (l.major !== c.major) return l.major > c.major;
|
|
1828
|
+
if (l.minor !== c.minor) return l.minor > c.minor;
|
|
1829
|
+
if (l.patch !== c.patch) return l.patch > c.patch;
|
|
1830
|
+
if (c.pre && !l.pre) return true;
|
|
1831
|
+
return false;
|
|
1832
|
+
}
|
|
1632
1833
|
function registerWebRoutes(server2, dbManager2, options) {
|
|
1633
1834
|
const adapter = createDatabaseManagerAdapter(dbManager2);
|
|
1634
1835
|
const mergeCache = options?.pathProvider ? new MergeSessionCache(options.pathProvider, { nativeBinding: options.nativeBinding }) : null;
|
|
1635
1836
|
mergeCache?.cleanupOrphans();
|
|
1636
|
-
const
|
|
1837
|
+
const fallbackPathProvider = {
|
|
1838
|
+
getSystemDir: () => path6.join(os3.homedir(), ".chatlab"),
|
|
1839
|
+
getUserDataDir: () => path6.join(os3.homedir(), ".chatlab", "data"),
|
|
1840
|
+
getDatabaseDir: () => path6.join(os3.homedir(), ".chatlab", "data", "databases"),
|
|
1841
|
+
getAiDataDir: () => path6.join(os3.homedir(), ".chatlab", "ai"),
|
|
1842
|
+
getSettingsDir: () => path6.join(os3.homedir(), ".chatlab", "settings"),
|
|
1843
|
+
getCacheDir: () => path6.join(os3.homedir(), ".chatlab", "cache"),
|
|
1844
|
+
getTempDir: () => path6.join(os3.homedir(), ".chatlab", "temp"),
|
|
1845
|
+
getLogsDir: () => path6.join(os3.homedir(), ".chatlab", "logs"),
|
|
1846
|
+
getDownloadsDir: () => path6.join(os3.homedir(), "Downloads")
|
|
1847
|
+
};
|
|
1848
|
+
const resolvedPathProvider = options?.pathProvider ?? fallbackPathProvider;
|
|
1637
1849
|
registerSessionRoutes2(server2, adapter);
|
|
1638
1850
|
registerMemberRoutes(server2, adapter);
|
|
1639
1851
|
registerAnalyticsRoutes(server2, dbManager2, adapter);
|
|
@@ -1645,11 +1857,34 @@ function registerWebRoutes(server2, dbManager2, options) {
|
|
|
1645
1857
|
registerMergeRoutes(server2, dbManager2, mergeCache);
|
|
1646
1858
|
}
|
|
1647
1859
|
registerExportRoutes(server2, adapter);
|
|
1648
|
-
registerCacheRoutes(server2,
|
|
1860
|
+
registerCacheRoutes(server2, resolvedPathProvider);
|
|
1861
|
+
server2.get("/_web/system/check-update", async () => {
|
|
1862
|
+
const currentVersion = getVersion();
|
|
1863
|
+
const packageName = "chatlab-cli";
|
|
1864
|
+
try {
|
|
1865
|
+
const resp = await fetch(`https://registry.npmjs.org/${packageName}/latest`, {
|
|
1866
|
+
headers: { Accept: "application/json" },
|
|
1867
|
+
signal: AbortSignal.timeout(1e4)
|
|
1868
|
+
});
|
|
1869
|
+
if (!resp.ok) {
|
|
1870
|
+
return { hasUpdate: false, currentVersion, error: `npm registry HTTP ${resp.status}` };
|
|
1871
|
+
}
|
|
1872
|
+
const data = await resp.json();
|
|
1873
|
+
const latestVersion = data.version || currentVersion;
|
|
1874
|
+
const hasUpdate = isNewerVersion(latestVersion, currentVersion);
|
|
1875
|
+
return { hasUpdate, currentVersion, latestVersion };
|
|
1876
|
+
} catch (err) {
|
|
1877
|
+
return {
|
|
1878
|
+
hasUpdate: false,
|
|
1879
|
+
currentVersion,
|
|
1880
|
+
error: err instanceof Error ? err.message : String(err)
|
|
1881
|
+
};
|
|
1882
|
+
}
|
|
1883
|
+
});
|
|
1649
1884
|
}
|
|
1650
1885
|
|
|
1651
1886
|
// src/http/routes/nlp.ts
|
|
1652
|
-
import * as
|
|
1887
|
+
import * as path7 from "path";
|
|
1653
1888
|
function ensureDb3(dbManager2, sessionId) {
|
|
1654
1889
|
const db = dbManager2.open(sessionId);
|
|
1655
1890
|
if (!db) {
|
|
@@ -1660,7 +1895,7 @@ function ensureDb3(dbManager2, sessionId) {
|
|
|
1660
1895
|
function registerNlpRoutes(server2, dbManager2) {
|
|
1661
1896
|
const pathProvider = dbManager2["pathProvider"];
|
|
1662
1897
|
if (pathProvider) {
|
|
1663
|
-
const nlpDir =
|
|
1898
|
+
const nlpDir = path7.join(pathProvider.getSystemDir(), "nlp");
|
|
1664
1899
|
initNlpDir(nlpDir);
|
|
1665
1900
|
ensureDefaultDict(nlpDir).catch((err) => console.warn("[NLP] Auto-download zh-CN dict failed:", err));
|
|
1666
1901
|
}
|
|
@@ -1698,12 +1933,12 @@ function registerNlpRoutes(server2, dbManager2) {
|
|
|
1698
1933
|
}
|
|
1699
1934
|
function resolveNlpDir(dbManager2) {
|
|
1700
1935
|
const pathProvider = dbManager2["pathProvider"];
|
|
1701
|
-
return
|
|
1936
|
+
return path7.join(pathProvider.getSystemDir(), "nlp");
|
|
1702
1937
|
}
|
|
1703
1938
|
|
|
1704
1939
|
// src/http/routes/ai.ts
|
|
1705
1940
|
import * as fs10 from "fs";
|
|
1706
|
-
import * as
|
|
1941
|
+
import * as path11 from "path";
|
|
1707
1942
|
|
|
1708
1943
|
// src/ai/logger.ts
|
|
1709
1944
|
var logger = null;
|
|
@@ -1752,6 +1987,7 @@ function adaptToolsForAgent(tools, getContext, options) {
|
|
|
1752
1987
|
description: tool.description,
|
|
1753
1988
|
parameters: convertJsonSchemaToParameters(tool.inputSchema),
|
|
1754
1989
|
async execute(_toolCallId, params) {
|
|
1990
|
+
const toolParams = params && typeof params === "object" ? params : {};
|
|
1755
1991
|
const ctx = getContext();
|
|
1756
1992
|
const execCtx = {
|
|
1757
1993
|
db: ctx.db,
|
|
@@ -1761,7 +1997,7 @@ function adaptToolsForAgent(tools, getContext, options) {
|
|
|
1761
1997
|
segmentText: (texts, locale, options2) => batchSegmentWithFrequency(texts, locale, options2)
|
|
1762
1998
|
};
|
|
1763
1999
|
try {
|
|
1764
|
-
const result = await tool.handler(
|
|
2000
|
+
const result = await tool.handler(toolParams, execCtx);
|
|
1765
2001
|
if (result.rawMessages && result.rawMessages.length > 0) {
|
|
1766
2002
|
const pipelineResult = applyPreprocessingPipeline({
|
|
1767
2003
|
rawMessages: result.rawMessages,
|
|
@@ -1784,9 +2020,9 @@ function adaptToolsForAgent(tools, getContext, options) {
|
|
|
1784
2020
|
|
|
1785
2021
|
// src/ai/assistant-loader.ts
|
|
1786
2022
|
import * as fs7 from "fs";
|
|
1787
|
-
import * as
|
|
2023
|
+
import * as path8 from "path";
|
|
1788
2024
|
function loadAssistantConfig(aiDataDir, assistantId) {
|
|
1789
|
-
const filePath =
|
|
2025
|
+
const filePath = path8.join(aiDataDir, "assistants", `${assistantId}.md`);
|
|
1790
2026
|
if (!fs7.existsSync(filePath)) return null;
|
|
1791
2027
|
try {
|
|
1792
2028
|
const content = fs7.readFileSync(filePath, "utf-8");
|
|
@@ -1798,7 +2034,7 @@ function loadAssistantConfig(aiDataDir, assistantId) {
|
|
|
1798
2034
|
|
|
1799
2035
|
// src/ai/manager-factory.ts
|
|
1800
2036
|
import * as fs8 from "fs";
|
|
1801
|
-
import * as
|
|
2037
|
+
import * as path9 from "path";
|
|
1802
2038
|
import { createHash, randomUUID as randomUUID3 } from "crypto";
|
|
1803
2039
|
var nodeFs = {
|
|
1804
2040
|
ensureDir(dir) {
|
|
@@ -1821,7 +2057,7 @@ var nodeFs = {
|
|
|
1821
2057
|
return fs8.existsSync(filePath);
|
|
1822
2058
|
},
|
|
1823
2059
|
joinPath(...parts) {
|
|
1824
|
-
return
|
|
2060
|
+
return path9.join(...parts);
|
|
1825
2061
|
}
|
|
1826
2062
|
};
|
|
1827
2063
|
var managerCache = /* @__PURE__ */ new Map();
|
|
@@ -1831,13 +2067,13 @@ function getAssistantManager(aiDataDir) {
|
|
|
1831
2067
|
cached = {
|
|
1832
2068
|
assistant: new AssistantManager({
|
|
1833
2069
|
fs: nodeFs,
|
|
1834
|
-
assistantsDir:
|
|
2070
|
+
assistantsDir: path9.join(aiDataDir, "assistants"),
|
|
1835
2071
|
builtinRawConfigs: [],
|
|
1836
2072
|
generateId: () => `custom_${randomUUID3().replace(/-/g, "").slice(0, 12)}`
|
|
1837
2073
|
}),
|
|
1838
2074
|
skill: new SkillManagerCore({
|
|
1839
2075
|
fs: nodeFs,
|
|
1840
|
-
skillsDir:
|
|
2076
|
+
skillsDir: path9.join(aiDataDir, "skills"),
|
|
1841
2077
|
builtinRawSkills: [],
|
|
1842
2078
|
contentHash: (content) => createHash("md5").update(content).digest("hex")
|
|
1843
2079
|
})
|
|
@@ -1980,10 +2216,10 @@ async function runServerAgent(options) {
|
|
|
1980
2216
|
|
|
1981
2217
|
// src/ai/custom-store.ts
|
|
1982
2218
|
import * as fs9 from "fs";
|
|
1983
|
-
import * as
|
|
2219
|
+
import * as path10 from "path";
|
|
1984
2220
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
1985
2221
|
function readProviders(aiDataDir) {
|
|
1986
|
-
const storePath =
|
|
2222
|
+
const storePath = path10.join(aiDataDir, "custom-providers.json");
|
|
1987
2223
|
if (!fs9.existsSync(storePath)) return [];
|
|
1988
2224
|
try {
|
|
1989
2225
|
const content = fs9.readFileSync(storePath, "utf-8");
|
|
@@ -1993,8 +2229,8 @@ function readProviders(aiDataDir) {
|
|
|
1993
2229
|
}
|
|
1994
2230
|
}
|
|
1995
2231
|
function writeProviders(aiDataDir, providers) {
|
|
1996
|
-
const storePath =
|
|
1997
|
-
const dir =
|
|
2232
|
+
const storePath = path10.join(aiDataDir, "custom-providers.json");
|
|
2233
|
+
const dir = path10.dirname(storePath);
|
|
1998
2234
|
if (!fs9.existsSync(dir)) fs9.mkdirSync(dir, { recursive: true });
|
|
1999
2235
|
fs9.writeFileSync(storePath, JSON.stringify(providers, null, 2), "utf-8");
|
|
2000
2236
|
}
|
|
@@ -2027,7 +2263,7 @@ function deleteCustomProvider(aiDataDir, id) {
|
|
|
2027
2263
|
return { success: true };
|
|
2028
2264
|
}
|
|
2029
2265
|
function readModels(aiDataDir) {
|
|
2030
|
-
const storePath =
|
|
2266
|
+
const storePath = path10.join(aiDataDir, "custom-models.json");
|
|
2031
2267
|
if (!fs9.existsSync(storePath)) return [];
|
|
2032
2268
|
try {
|
|
2033
2269
|
const content = fs9.readFileSync(storePath, "utf-8");
|
|
@@ -2037,8 +2273,8 @@ function readModels(aiDataDir) {
|
|
|
2037
2273
|
}
|
|
2038
2274
|
}
|
|
2039
2275
|
function writeModels(aiDataDir, models) {
|
|
2040
|
-
const storePath =
|
|
2041
|
-
const dir =
|
|
2276
|
+
const storePath = path10.join(aiDataDir, "custom-models.json");
|
|
2277
|
+
const dir = path10.dirname(storePath);
|
|
2042
2278
|
if (!fs9.existsSync(dir)) fs9.mkdirSync(dir, { recursive: true });
|
|
2043
2279
|
fs9.writeFileSync(storePath, JSON.stringify(models, null, 2), "utf-8");
|
|
2044
2280
|
}
|
|
@@ -2074,6 +2310,23 @@ function deleteCustomModel(aiDataDir, providerId, modelId) {
|
|
|
2074
2310
|
return { success: true };
|
|
2075
2311
|
}
|
|
2076
2312
|
|
|
2313
|
+
// src/http/routes/ai-config-display.ts
|
|
2314
|
+
var NO_KEY_PLACEHOLDER = "sk-no-key-required";
|
|
2315
|
+
function hasRealApiKey(apiKey) {
|
|
2316
|
+
return !!apiKey && apiKey !== NO_KEY_PLACEHOLDER;
|
|
2317
|
+
}
|
|
2318
|
+
function toLlmConfigDisplay(config, resolveApiKey2) {
|
|
2319
|
+
const { apiKey: _rawApiKey, ...rest } = config;
|
|
2320
|
+
const provider = typeof config.provider === "string" ? config.provider : "";
|
|
2321
|
+
const authProfile = typeof config.authProfile === "string" ? config.authProfile : void 0;
|
|
2322
|
+
const resolvedApiKey = provider ? resolveApiKey2(provider, authProfile) : "";
|
|
2323
|
+
return {
|
|
2324
|
+
...rest,
|
|
2325
|
+
apiKey: "",
|
|
2326
|
+
apiKeySet: hasRealApiKey(resolvedApiKey || "")
|
|
2327
|
+
};
|
|
2328
|
+
}
|
|
2329
|
+
|
|
2077
2330
|
// src/http/routes/ai.ts
|
|
2078
2331
|
function getAiDir(dbManager2) {
|
|
2079
2332
|
const pathProvider = dbManager2["pathProvider"];
|
|
@@ -2154,7 +2407,7 @@ function registerAiRoutes(server2, dbManager2, convManager2) {
|
|
|
2154
2407
|
return mgr.getBuiltinCatalog();
|
|
2155
2408
|
});
|
|
2156
2409
|
server2.get("/_web/ai/llm/has-config", async () => {
|
|
2157
|
-
const configPath =
|
|
2410
|
+
const configPath = path11.join(getAiDir(dbManager2), "llm-config.json");
|
|
2158
2411
|
if (!fs10.existsSync(configPath)) return false;
|
|
2159
2412
|
try {
|
|
2160
2413
|
const data = JSON.parse(fs10.readFileSync(configPath, "utf-8"));
|
|
@@ -2165,14 +2418,11 @@ function registerAiRoutes(server2, dbManager2, convManager2) {
|
|
|
2165
2418
|
}
|
|
2166
2419
|
});
|
|
2167
2420
|
server2.get("/_web/ai/llm/configs", async () => {
|
|
2168
|
-
const configPath =
|
|
2421
|
+
const configPath = path11.join(getAiDir(dbManager2), "llm-config.json");
|
|
2169
2422
|
if (!fs10.existsSync(configPath)) return { configs: [], defaultAssistant: null, fastModel: null };
|
|
2170
2423
|
try {
|
|
2171
2424
|
const data = JSON.parse(fs10.readFileSync(configPath, "utf-8"));
|
|
2172
|
-
const configs = (data.configs || []).map((c) =>
|
|
2173
|
-
const { apiKey: _k, ...rest } = c;
|
|
2174
|
-
return { ...rest, apiKey: "" };
|
|
2175
|
-
});
|
|
2425
|
+
const configs = (data.configs || []).map((c) => toLlmConfigDisplay(c, resolveApiKey));
|
|
2176
2426
|
return {
|
|
2177
2427
|
configs,
|
|
2178
2428
|
defaultAssistant: data.defaultAssistant ?? null,
|
|
@@ -2194,7 +2444,7 @@ function registerAiRoutes(server2, dbManager2, convManager2) {
|
|
|
2194
2444
|
});
|
|
2195
2445
|
});
|
|
2196
2446
|
server2.get("/_web/ai/llm/provider-registry", async () => {
|
|
2197
|
-
const customPath =
|
|
2447
|
+
const customPath = path11.join(getAiDir(dbManager2), "custom-providers.json");
|
|
2198
2448
|
let custom = [];
|
|
2199
2449
|
if (fs10.existsSync(customPath)) {
|
|
2200
2450
|
try {
|
|
@@ -2207,7 +2457,7 @@ function registerAiRoutes(server2, dbManager2, convManager2) {
|
|
|
2207
2457
|
return [...BUILTIN_PROVIDERS, ...custom];
|
|
2208
2458
|
});
|
|
2209
2459
|
server2.get("/_web/ai/llm/model-catalog", async () => {
|
|
2210
|
-
const customPath =
|
|
2460
|
+
const customPath = path11.join(getAiDir(dbManager2), "custom-models.json");
|
|
2211
2461
|
let custom = [];
|
|
2212
2462
|
if (fs10.existsSync(customPath)) {
|
|
2213
2463
|
try {
|
|
@@ -2220,7 +2470,7 @@ function registerAiRoutes(server2, dbManager2, convManager2) {
|
|
|
2220
2470
|
return [...BUILTIN_MODELS, ...custom];
|
|
2221
2471
|
});
|
|
2222
2472
|
server2.get("/_web/ai/llm/default-assistant-slot", async () => {
|
|
2223
|
-
const configPath =
|
|
2473
|
+
const configPath = path11.join(getAiDir(dbManager2), "llm-config.json");
|
|
2224
2474
|
if (!fs10.existsSync(configPath)) return null;
|
|
2225
2475
|
try {
|
|
2226
2476
|
const data = JSON.parse(fs10.readFileSync(configPath, "utf-8"));
|
|
@@ -2230,7 +2480,7 @@ function registerAiRoutes(server2, dbManager2, convManager2) {
|
|
|
2230
2480
|
}
|
|
2231
2481
|
});
|
|
2232
2482
|
server2.get("/_web/ai/llm/fast-model-slot", async () => {
|
|
2233
|
-
const configPath =
|
|
2483
|
+
const configPath = path11.join(getAiDir(dbManager2), "llm-config.json");
|
|
2234
2484
|
if (!fs10.existsSync(configPath)) return null;
|
|
2235
2485
|
try {
|
|
2236
2486
|
const data = JSON.parse(fs10.readFileSync(configPath, "utf-8"));
|
|
@@ -2587,7 +2837,7 @@ var NOOP_LOGGER = { info: noop, warn: noop, error: noop };
|
|
|
2587
2837
|
|
|
2588
2838
|
// ../../packages/sync/src/data-source-manager.ts
|
|
2589
2839
|
import * as fs11 from "fs";
|
|
2590
|
-
import * as
|
|
2840
|
+
import * as path12 from "path";
|
|
2591
2841
|
import * as crypto2 from "crypto";
|
|
2592
2842
|
var CONFIG_FILE = "data-sources.json";
|
|
2593
2843
|
function generateId(prefix = "ds") {
|
|
@@ -2615,7 +2865,7 @@ var DataSourceManager = class {
|
|
|
2615
2865
|
this.logger = logger2 ?? NOOP_LOGGER;
|
|
2616
2866
|
}
|
|
2617
2867
|
getConfigPath() {
|
|
2618
|
-
return
|
|
2868
|
+
return path12.join(this.configDir, CONFIG_FILE);
|
|
2619
2869
|
}
|
|
2620
2870
|
ensureDir() {
|
|
2621
2871
|
fs11.mkdirSync(this.configDir, { recursive: true });
|
|
@@ -2904,10 +3154,10 @@ var PullEngine = class {
|
|
|
2904
3154
|
limit: ds.pullLimit
|
|
2905
3155
|
});
|
|
2906
3156
|
try {
|
|
2907
|
-
const
|
|
2908
|
-
this.logger.info(`[Pull] "${sess.name}" page ${pageCount}: fetched ${
|
|
3157
|
+
const stat2 = fs12.statSync(tempFile);
|
|
3158
|
+
this.logger.info(`[Pull] "${sess.name}" page ${pageCount}: fetched ${stat2.size} bytes`);
|
|
2909
3159
|
const sync0 = parseSyncFromFile(tempFile);
|
|
2910
|
-
if (
|
|
3160
|
+
if (stat2.size < 1024) {
|
|
2911
3161
|
if (!fileContainsMessages(tempFile) && sync0?.hasMore === false) {
|
|
2912
3162
|
cleanupTempFile(tempFile);
|
|
2913
3163
|
const retryDelays = [2e3, 3e3, 5e3];
|
|
@@ -2990,7 +3240,7 @@ var PullEngine = class {
|
|
|
2990
3240
|
continue;
|
|
2991
3241
|
}
|
|
2992
3242
|
}
|
|
2993
|
-
if (
|
|
3243
|
+
if (stat2.size === 0) {
|
|
2994
3244
|
cleanupTempFile(tempFile);
|
|
2995
3245
|
break;
|
|
2996
3246
|
}
|
|
@@ -3198,11 +3448,11 @@ function reloadTimer(dsId, skipInitialPull = false) {
|
|
|
3198
3448
|
// src/sync/adapters.ts
|
|
3199
3449
|
import * as fs13 from "fs";
|
|
3200
3450
|
import * as os4 from "os";
|
|
3201
|
-
import * as
|
|
3451
|
+
import * as path13 from "path";
|
|
3202
3452
|
import * as crypto4 from "crypto";
|
|
3203
3453
|
function getTempFilePath(ext) {
|
|
3204
3454
|
const id = crypto4.randomBytes(8).toString("hex");
|
|
3205
|
-
return
|
|
3455
|
+
return path13.join(os4.tmpdir(), `chatlab-pull-${id}${ext}`);
|
|
3206
3456
|
}
|
|
3207
3457
|
var NodeFetcher = class {
|
|
3208
3458
|
async fetchToTempFile(baseUrl, remoteSessionId, token, params) {
|
|
@@ -3225,7 +3475,7 @@ var NodeFetcher = class {
|
|
|
3225
3475
|
};
|
|
3226
3476
|
function resolveNativeBinding2() {
|
|
3227
3477
|
if (process.versions.electron) return void 0;
|
|
3228
|
-
const nativePath =
|
|
3478
|
+
const nativePath = resolveCliPath("native/better_sqlite3.node");
|
|
3229
3479
|
if (fs13.existsSync(nativePath)) return nativePath;
|
|
3230
3480
|
return void 0;
|
|
3231
3481
|
}
|
|
@@ -3456,7 +3706,7 @@ var dbManager = null;
|
|
|
3456
3706
|
var convManager = null;
|
|
3457
3707
|
function resolveNativeBinding3() {
|
|
3458
3708
|
if (process.versions.electron) return void 0;
|
|
3459
|
-
const nativePath =
|
|
3709
|
+
const nativePath = resolveCliPath("native/better_sqlite3.node");
|
|
3460
3710
|
if (fs14.existsSync(nativePath)) return nativePath;
|
|
3461
3711
|
return void 0;
|
|
3462
3712
|
}
|
|
@@ -3481,7 +3731,7 @@ async function startHttpServer(options) {
|
|
|
3481
3731
|
const pathProvider = new NodePathProvider(userDataDir);
|
|
3482
3732
|
pathProvider.ensureAllDirs();
|
|
3483
3733
|
if (hasPendingElectronDataWarning() || !verifyCliDataPath(pathProvider.getDatabaseDir())) {
|
|
3484
|
-
|
|
3734
|
+
console.error(
|
|
3485
3735
|
"\n" + "=".repeat(68) + "\n ChatLab: Electron desktop data not found\n" + "=".repeat(68) + '\n\n Detected that ChatLab desktop app was installed on this machine,\n but could not locate your chat databases.\n\n This usually means you changed the data directory in desktop settings.\n\n To fix this, choose one of:\n\n 1. Open ChatLab desktop app \u2014 it will auto-migrate your data\n 2. Set the data directory manually:\n export CHATLAB_DATA_DIR="/path/to/your/data"\n 3. Edit ~/.chatlab/config.toml:\n [data]\n user_data_dir = "/path/to/your/data"\n\n' + "=".repeat(68) + "\n"
|
|
3486
3736
|
);
|
|
3487
3737
|
}
|
|
@@ -3558,4 +3808,4 @@ export {
|
|
|
3558
3808
|
startHttpServer,
|
|
3559
3809
|
stopHttpServer
|
|
3560
3810
|
};
|
|
3561
|
-
//# sourceMappingURL=chunk-
|
|
3811
|
+
//# sourceMappingURL=chunk-XPBPKH6B.mjs.map
|