chatlab-cli 0.25.0 → 0.25.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-5XMRLXZM.mjs +166 -0
- package/dist/chat-command-5XMRLXZM.mjs.map +1 -0
- package/dist/{chunk-4OMV4VNH.mjs → chunk-7VG6QGQ2.mjs} +977 -568
- package/dist/chunk-7VG6QGQ2.mjs.map +1 -0
- package/dist/{chunk-TCPXAX3F.mjs → chunk-CUCDRAY6.mjs} +17 -25
- package/dist/chunk-CUCDRAY6.mjs.map +1 -0
- package/dist/chunk-FDK6SPCG.mjs +40 -0
- package/dist/chunk-FDK6SPCG.mjs.map +1 -0
- package/dist/{chunk-FSHVDWI2.mjs → chunk-GTCTDD2Z.mjs} +116 -569
- package/dist/chunk-GTCTDD2Z.mjs.map +1 -0
- package/dist/{chunk-E65ABM3C.mjs → chunk-JE3FOFF7.mjs} +53 -53
- package/dist/chunk-JE3FOFF7.mjs.map +1 -0
- package/dist/{chunk-GNT5G74Z.mjs → chunk-PDQFSQO6.mjs} +59 -33
- package/dist/chunk-PDQFSQO6.mjs.map +1 -0
- package/dist/chunk-WYHGWTA4.mjs +485 -0
- package/dist/chunk-WYHGWTA4.mjs.map +1 -0
- package/dist/{chunk-CIBTUWAE.mjs → chunk-YZYP5ST6.mjs} +37 -8
- package/dist/chunk-YZYP5ST6.mjs.map +1 -0
- package/dist/cli.mjs +3 -2
- package/dist/{http-PMNZ42EN.mjs → http-C3CGXUBU.mjs} +8 -6
- package/dist/{import-OP7R4CYY.mjs → import-VS7L5JDX.mjs} +4 -4
- package/dist/index.mjs +10 -8
- package/dist/{mcp-ABXNFUJO.mjs → mcp-6VXDPUQK.mjs} +11 -6
- package/dist/mcp-6VXDPUQK.mjs.map +1 -0
- package/dist/{stream-import-L6RJHH4L.mjs → stream-import-TFDBNVIW.mjs} +3 -3
- package/dist-web/assets/{DebugToolsPanel-DaSNc1o-.css → DebugToolsPanel-vn-bnUxn.css} +1 -1
- package/dist-web/assets/{DebugToolsPanel.vue_vue_type_script_setup_true_lang-BUwpIerl.js → DebugToolsPanel.vue_vue_type_script_setup_true_lang-B1xZmp9r.js} +13 -13
- package/dist-web/assets/{MessageExportModal-BAJKWX4y.js → MessageExportModal-B79pPBL9.js} +1 -1
- package/dist-web/assets/{electron-CZt36wW5.js → electron-DRkrjeIl.js} +1 -1
- package/dist-web/assets/{electron-CwERrTWp.js → electron-Dv8jdn_2.js} +1 -1
- package/dist-web/assets/{fetch-JzVEwamn.js → fetch-BmZIm6mS.js} +1 -1
- package/dist-web/assets/fetch-BqLy63aj.js +1 -0
- package/dist-web/assets/fetch-BstX-wd4.js +1 -0
- package/dist-web/assets/{fetch-CgBIWyAo.js → fetch-Bvcxe5PI.js} +1 -1
- package/dist-web/assets/{fetch-yWwp067l.js → fetch-CDamdvtb.js} +1 -1
- package/dist-web/assets/{fetch-GMkMBzBS.js → fetch-DWg-2kOp.js} +1 -1
- package/dist-web/assets/{fetch-qoGEVjNg.js → fetch-DfgdagMN.js} +1 -1
- package/dist-web/assets/{fetch-DD1EGRKV.js → fetch-Drk9dLaF.js} +1 -1
- package/dist-web/assets/{fetch-D4p9vj1A.js → fetch-Y-_WsCuk.js} +1 -1
- package/dist-web/assets/{fetch-DXfZysDf.js → fetch-ph2_d79v.js} +1 -1
- package/dist-web/assets/{index-BrS_VrIY.js → index-9urfJP1r.js} +1 -1
- package/dist-web/assets/{index-DABpUm3J.js → index-CfKjh0Jr.js} +5 -5
- package/dist-web/assets/{index-C1t-kzfo.css → index-CprJOAB1.css} +1 -1
- package/dist-web/assets/{index-O0PG26_v.js → index-DMWf5On7.js} +1 -1
- package/dist-web/assets/{index-Cvlw0RLu.js → index-D_hHm7bQ.js} +2 -2
- package/dist-web/assets/index-MCdpiX_O.js +173 -0
- package/dist-web/assets/{index-DvWI6Yqa.js → index-deYDOVUa.js} +3 -3
- package/dist-web/assets/{web-4rtrAcLu.js → web-XJV6Vj5t.js} +1 -1
- package/dist-web/index.html +2 -2
- package/package.json +1 -1
- package/dist/chunk-4OMV4VNH.mjs.map +0 -1
- package/dist/chunk-CIBTUWAE.mjs.map +0 -1
- package/dist/chunk-E65ABM3C.mjs.map +0 -1
- package/dist/chunk-FSHVDWI2.mjs.map +0 -1
- package/dist/chunk-GNT5G74Z.mjs.map +0 -1
- package/dist/chunk-TCPXAX3F.mjs.map +0 -1
- package/dist/mcp-ABXNFUJO.mjs.map +0 -1
- package/dist-web/assets/fetch-BxFAkm7O.js +0 -1
- package/dist-web/assets/fetch-DO8lty7_.js +0 -1
- package/dist-web/assets/index-OsjX5hXw.js +0 -173
- /package/dist/{http-PMNZ42EN.mjs.map → http-C3CGXUBU.mjs.map} +0 -0
- /package/dist/{import-OP7R4CYY.mjs.map → import-VS7L5JDX.mjs.map} +0 -0
- /package/dist/{stream-import-L6RJHH4L.mjs.map → stream-import-TFDBNVIW.mjs.map} +0 -0
|
@@ -619,8 +619,8 @@ var require_FilterBase = __commonJS({
|
|
|
619
619
|
var FilterBase = class _FilterBase extends Transform {
|
|
620
620
|
static stringFilter(string, separator) {
|
|
621
621
|
return (stack) => {
|
|
622
|
-
const
|
|
623
|
-
return
|
|
622
|
+
const path36 = stack.join(separator);
|
|
623
|
+
return path36.length === string.length && path36 === string || path36.length > string.length && path36.substr(0, string.length) === string && path36.substr(string.length, separator.length) === separator;
|
|
624
624
|
};
|
|
625
625
|
}
|
|
626
626
|
static regExpFilter(regExp, separator) {
|
|
@@ -1074,12 +1074,12 @@ var require_Assembler = __commonJS({
|
|
|
1074
1074
|
return (this.stack.length >> 1) + (this.done ? 0 : 1);
|
|
1075
1075
|
}
|
|
1076
1076
|
get path() {
|
|
1077
|
-
const
|
|
1077
|
+
const path36 = [];
|
|
1078
1078
|
for (let i = 0; i < this.stack.length; i += 2) {
|
|
1079
1079
|
const key = this.stack[i + 1];
|
|
1080
|
-
|
|
1080
|
+
path36.push(key === null ? this.stack[i].length : key);
|
|
1081
1081
|
}
|
|
1082
|
-
return
|
|
1082
|
+
return path36;
|
|
1083
1083
|
}
|
|
1084
1084
|
dropToLevel(level) {
|
|
1085
1085
|
if (level < this.depth) {
|
|
@@ -1854,63 +1854,6 @@ var ALL_MIGRATIONS = [
|
|
|
1854
1854
|
m004EncryptedKeysToAuthProfiles
|
|
1855
1855
|
];
|
|
1856
1856
|
|
|
1857
|
-
// ../../packages/node-runtime/src/better-sqlite3-adapter.ts
|
|
1858
|
-
import Database from "better-sqlite3";
|
|
1859
|
-
var BetterSqlitePreparedStatement = class {
|
|
1860
|
-
constructor(stmt) {
|
|
1861
|
-
this.stmt = stmt;
|
|
1862
|
-
this.readonly = stmt.readonly;
|
|
1863
|
-
}
|
|
1864
|
-
stmt;
|
|
1865
|
-
readonly;
|
|
1866
|
-
get(...params) {
|
|
1867
|
-
return this.stmt.get(...params);
|
|
1868
|
-
}
|
|
1869
|
-
all(...params) {
|
|
1870
|
-
return this.stmt.all(...params);
|
|
1871
|
-
}
|
|
1872
|
-
run(...params) {
|
|
1873
|
-
const result = this.stmt.run(...params);
|
|
1874
|
-
return {
|
|
1875
|
-
changes: result.changes,
|
|
1876
|
-
lastInsertRowid: result.lastInsertRowid
|
|
1877
|
-
};
|
|
1878
|
-
}
|
|
1879
|
-
};
|
|
1880
|
-
var BetterSqliteAdapter = class {
|
|
1881
|
-
constructor(db) {
|
|
1882
|
-
this.db = db;
|
|
1883
|
-
this.readonly = db.readonly;
|
|
1884
|
-
}
|
|
1885
|
-
db;
|
|
1886
|
-
readonly;
|
|
1887
|
-
exec(sql) {
|
|
1888
|
-
this.db.exec(sql);
|
|
1889
|
-
}
|
|
1890
|
-
prepare(sql) {
|
|
1891
|
-
return new BetterSqlitePreparedStatement(this.db.prepare(sql));
|
|
1892
|
-
}
|
|
1893
|
-
transaction(fn) {
|
|
1894
|
-
return this.db.transaction(fn)();
|
|
1895
|
-
}
|
|
1896
|
-
pragma(pragma) {
|
|
1897
|
-
return this.db.pragma(pragma);
|
|
1898
|
-
}
|
|
1899
|
-
close() {
|
|
1900
|
-
this.db.close();
|
|
1901
|
-
}
|
|
1902
|
-
};
|
|
1903
|
-
function openBetterSqliteDatabase(filePath, options) {
|
|
1904
|
-
const db = new Database(filePath, {
|
|
1905
|
-
readonly: options?.readonly ?? false,
|
|
1906
|
-
nativeBinding: options?.nativeBinding
|
|
1907
|
-
});
|
|
1908
|
-
if (!options?.readonly) {
|
|
1909
|
-
db.pragma("journal_mode = WAL");
|
|
1910
|
-
}
|
|
1911
|
-
return new BetterSqliteAdapter(db);
|
|
1912
|
-
}
|
|
1913
|
-
|
|
1914
1857
|
// ../../packages/core/src/query/filters.ts
|
|
1915
1858
|
function buildTimeFilter(filter, tableAlias) {
|
|
1916
1859
|
const conditions = [];
|
|
@@ -2165,8 +2108,8 @@ function getSessionInfo(db) {
|
|
|
2165
2108
|
return buildSessionInfo(meta, overview, sc);
|
|
2166
2109
|
}
|
|
2167
2110
|
function getSummaryCount(db) {
|
|
2168
|
-
if (!hasTable(db, "
|
|
2169
|
-
const row = db.prepare("SELECT COUNT(*) as count FROM
|
|
2111
|
+
if (!hasTable(db, "segment")) return 0;
|
|
2112
|
+
const row = db.prepare("SELECT COUNT(*) as count FROM segment WHERE summary IS NOT NULL AND summary != ''").get();
|
|
2170
2113
|
return row?.count ?? 0;
|
|
2171
2114
|
}
|
|
2172
2115
|
function isChatSessionDb(db) {
|
|
@@ -2231,11 +2174,11 @@ function getChatOverview(db, topN = 10) {
|
|
|
2231
2174
|
topMembers
|
|
2232
2175
|
};
|
|
2233
2176
|
}
|
|
2234
|
-
function
|
|
2235
|
-
if (!hasTable(db, "
|
|
2177
|
+
function searchSegments(db, keywords, timeFilter, limit = 20, previewCount = 5, ftsMatchExpression) {
|
|
2178
|
+
if (!hasTable(db, "segment")) return [];
|
|
2236
2179
|
let sessionSql = `
|
|
2237
2180
|
SELECT cs.id, cs.start_ts as startTs, cs.end_ts as endTs, cs.message_count as messageCount
|
|
2238
|
-
FROM
|
|
2181
|
+
FROM segment cs WHERE 1=1
|
|
2239
2182
|
`;
|
|
2240
2183
|
const params = [];
|
|
2241
2184
|
if (timeFilter?.startTs !== void 0) {
|
|
@@ -2250,7 +2193,7 @@ function searchSessions(db, keywords, timeFilter, limit = 20, previewCount = 5,
|
|
|
2250
2193
|
if (ftsMatchExpression) {
|
|
2251
2194
|
sessionSql += `
|
|
2252
2195
|
AND cs.id IN (
|
|
2253
|
-
SELECT DISTINCT mc.
|
|
2196
|
+
SELECT DISTINCT mc.segment_id FROM message_context mc
|
|
2254
2197
|
WHERE mc.message_id IN (SELECT rowid FROM message_fts WHERE content MATCH ?)
|
|
2255
2198
|
)
|
|
2256
2199
|
`;
|
|
@@ -2259,7 +2202,7 @@ function searchSessions(db, keywords, timeFilter, limit = 20, previewCount = 5,
|
|
|
2259
2202
|
const keywordConditions = keywords.map(() => "m.content LIKE ?").join(" OR ");
|
|
2260
2203
|
sessionSql += `
|
|
2261
2204
|
AND cs.id IN (
|
|
2262
|
-
SELECT DISTINCT mc.
|
|
2205
|
+
SELECT DISTINCT mc.segment_id FROM message_context mc
|
|
2263
2206
|
JOIN message m ON m.id = mc.message_id
|
|
2264
2207
|
WHERE (${keywordConditions})
|
|
2265
2208
|
)
|
|
@@ -2280,7 +2223,7 @@ function searchSessions(db, keywords, timeFilter, limit = 20, previewCount = 5,
|
|
|
2280
2223
|
FROM message_context mc
|
|
2281
2224
|
JOIN message m ON m.id = mc.message_id
|
|
2282
2225
|
JOIN member mb ON mb.id = m.sender_id
|
|
2283
|
-
WHERE mc.
|
|
2226
|
+
WHERE mc.segment_id = ? ORDER BY m.ts ASC LIMIT ?
|
|
2284
2227
|
`;
|
|
2285
2228
|
return sessions.map((session) => {
|
|
2286
2229
|
const previewMessages = db.prepare(previewSql).all(session.id, previewCount);
|
|
@@ -2294,12 +2237,12 @@ function searchSessions(db, keywords, timeFilter, limit = 20, previewCount = 5,
|
|
|
2294
2237
|
};
|
|
2295
2238
|
});
|
|
2296
2239
|
}
|
|
2297
|
-
function
|
|
2298
|
-
if (!hasTable(db, "
|
|
2240
|
+
function getSegmentMessages(db, segmentId, limit = 500) {
|
|
2241
|
+
if (!hasTable(db, "segment")) return null;
|
|
2299
2242
|
const session = db.prepare(
|
|
2300
2243
|
`SELECT id, start_ts as startTs, end_ts as endTs, message_count as messageCount
|
|
2301
|
-
FROM
|
|
2302
|
-
).get(
|
|
2244
|
+
FROM segment WHERE id = ?`
|
|
2245
|
+
).get(segmentId);
|
|
2303
2246
|
if (!session) return null;
|
|
2304
2247
|
const messages = db.prepare(
|
|
2305
2248
|
`SELECT m.id, mb.id as senderId,
|
|
@@ -2309,14 +2252,14 @@ function getSessionMessages(db, chatSessionId, limit = 500) {
|
|
|
2309
2252
|
FROM message_context mc
|
|
2310
2253
|
JOIN message m ON m.id = mc.message_id
|
|
2311
2254
|
JOIN member mb ON mb.id = m.sender_id
|
|
2312
|
-
WHERE mc.
|
|
2313
|
-
).all(
|
|
2255
|
+
WHERE mc.segment_id = ? ORDER BY m.ts ASC LIMIT ?`
|
|
2256
|
+
).all(segmentId, limit);
|
|
2314
2257
|
const participantsSet = /* @__PURE__ */ new Set();
|
|
2315
2258
|
for (const msg of messages) {
|
|
2316
2259
|
participantsSet.add(msg.senderName);
|
|
2317
2260
|
}
|
|
2318
2261
|
return {
|
|
2319
|
-
|
|
2262
|
+
segmentId: session.id,
|
|
2320
2263
|
startTs: session.startTs,
|
|
2321
2264
|
endTs: session.endTs,
|
|
2322
2265
|
messageCount: session.messageCount,
|
|
@@ -2325,13 +2268,13 @@ function getSessionMessages(db, chatSessionId, limit = 500) {
|
|
|
2325
2268
|
messages
|
|
2326
2269
|
};
|
|
2327
2270
|
}
|
|
2328
|
-
function
|
|
2329
|
-
if (!hasTable(db, "
|
|
2271
|
+
function getSegmentSummaries(db, options) {
|
|
2272
|
+
if (!hasTable(db, "segment")) return [];
|
|
2330
2273
|
const { limit = 50, timeFilter } = options ?? {};
|
|
2331
2274
|
let sql = `
|
|
2332
2275
|
SELECT cs.id, cs.start_ts as startTs, cs.end_ts as endTs,
|
|
2333
2276
|
cs.message_count as messageCount, cs.summary
|
|
2334
|
-
FROM
|
|
2277
|
+
FROM segment cs
|
|
2335
2278
|
WHERE cs.summary IS NOT NULL AND cs.summary != ''
|
|
2336
2279
|
`;
|
|
2337
2280
|
const params = [];
|
|
@@ -2351,7 +2294,7 @@ function getSessionSummaries(db, options) {
|
|
|
2351
2294
|
FROM message_context mc
|
|
2352
2295
|
JOIN message m ON m.id = mc.message_id
|
|
2353
2296
|
JOIN member mb ON mb.id = m.sender_id
|
|
2354
|
-
WHERE mc.
|
|
2297
|
+
WHERE mc.segment_id = ? LIMIT 10
|
|
2355
2298
|
`;
|
|
2356
2299
|
return sessions.map((session) => {
|
|
2357
2300
|
const participants = db.prepare(participantsSql).all(session.id);
|
|
@@ -2368,9 +2311,9 @@ function getSessionSummaries(db, options) {
|
|
|
2368
2311
|
var DEFAULT_SESSION_GAP_THRESHOLD = 1800;
|
|
2369
2312
|
function getSessionIndexStats(db) {
|
|
2370
2313
|
let sessionCount = 0;
|
|
2371
|
-
if (hasTable(db, "
|
|
2314
|
+
if (hasTable(db, "segment")) {
|
|
2372
2315
|
try {
|
|
2373
|
-
const row = db.prepare("SELECT COUNT(*) as count FROM
|
|
2316
|
+
const row = db.prepare("SELECT COUNT(*) as count FROM segment").get();
|
|
2374
2317
|
sessionCount = row?.count ?? 0;
|
|
2375
2318
|
} catch {
|
|
2376
2319
|
}
|
|
@@ -2386,7 +2329,7 @@ function getSessionIndexStats(db) {
|
|
|
2386
2329
|
return { sessionCount, hasIndex: sessionCount > 0, gapThreshold };
|
|
2387
2330
|
}
|
|
2388
2331
|
function getChatSessionList(db) {
|
|
2389
|
-
if (!hasTable(db, "
|
|
2332
|
+
if (!hasTable(db, "segment")) return [];
|
|
2390
2333
|
try {
|
|
2391
2334
|
return db.prepare(
|
|
2392
2335
|
`SELECT
|
|
@@ -2396,24 +2339,24 @@ function getChatSessionList(db) {
|
|
|
2396
2339
|
cs.message_count as messageCount,
|
|
2397
2340
|
cs.summary,
|
|
2398
2341
|
(SELECT mc.message_id FROM message_context mc
|
|
2399
|
-
WHERE mc.
|
|
2400
|
-
FROM
|
|
2342
|
+
WHERE mc.segment_id = cs.id ORDER BY mc.message_id LIMIT 1) as firstMessageId
|
|
2343
|
+
FROM segment cs
|
|
2401
2344
|
ORDER BY cs.start_ts ASC`
|
|
2402
2345
|
).all();
|
|
2403
2346
|
} catch {
|
|
2404
2347
|
return [];
|
|
2405
2348
|
}
|
|
2406
2349
|
}
|
|
2407
|
-
function
|
|
2350
|
+
function getSegmentSummary(db, segmentId) {
|
|
2408
2351
|
try {
|
|
2409
|
-
const row = db.prepare("SELECT summary FROM
|
|
2352
|
+
const row = db.prepare("SELECT summary FROM segment WHERE id = ?").get(segmentId);
|
|
2410
2353
|
return row?.summary ?? null;
|
|
2411
2354
|
} catch {
|
|
2412
2355
|
return null;
|
|
2413
2356
|
}
|
|
2414
2357
|
}
|
|
2415
|
-
function
|
|
2416
|
-
db.prepare("UPDATE
|
|
2358
|
+
function saveSegmentSummary(db, segmentId, summary) {
|
|
2359
|
+
db.prepare("UPDATE segment SET summary = ? WHERE id = ?").run(summary, segmentId);
|
|
2417
2360
|
}
|
|
2418
2361
|
function updateSessionOwnerId(db, ownerId) {
|
|
2419
2362
|
db.prepare("UPDATE meta SET owner_id = ?").run(ownerId);
|
|
@@ -2423,7 +2366,7 @@ function renameSession(db, newName) {
|
|
|
2423
2366
|
}
|
|
2424
2367
|
function clearSessionIndex(db) {
|
|
2425
2368
|
db.exec("DELETE FROM message_context");
|
|
2426
|
-
db.exec("DELETE FROM
|
|
2369
|
+
db.exec("DELETE FROM segment");
|
|
2427
2370
|
}
|
|
2428
2371
|
function generateSessionIndex(db, gapThreshold = DEFAULT_SESSION_GAP_THRESHOLD, onProgress) {
|
|
2429
2372
|
const countRow = db.prepare("SELECT COUNT(*) as count FROM message").get();
|
|
@@ -2457,9 +2400,9 @@ function generateSessionIndex(db, gapThreshold = DEFAULT_SESSION_GAP_THRESHOLD,
|
|
|
2457
2400
|
}
|
|
2458
2401
|
}
|
|
2459
2402
|
const insertSession = db.prepare(
|
|
2460
|
-
"INSERT INTO
|
|
2403
|
+
"INSERT INTO segment (start_ts, end_ts, message_count, is_manual, summary) VALUES (?, ?, ?, 0, NULL)"
|
|
2461
2404
|
);
|
|
2462
|
-
const insertContext = db.prepare("INSERT INTO message_context (message_id,
|
|
2405
|
+
const insertContext = db.prepare("INSERT INTO message_context (message_id, segment_id, topic_id) VALUES (?, ?, NULL)");
|
|
2463
2406
|
return db.transaction(() => {
|
|
2464
2407
|
let processed = 0;
|
|
2465
2408
|
const total = sessionMap.size;
|
|
@@ -2485,13 +2428,13 @@ function generateIncrementalSessionIndex(db, gapThreshold = DEFAULT_SESSION_GAP_
|
|
|
2485
2428
|
const allMessages = db.prepare("SELECT id, ts FROM message ORDER BY ts, id").all();
|
|
2486
2429
|
const newMessages = allMessages.filter((m) => !indexedIds.has(m.id));
|
|
2487
2430
|
if (newMessages.length === 0) return 0;
|
|
2488
|
-
const lastSession = hasTable(db, "
|
|
2431
|
+
const lastSession = hasTable(db, "segment") ? db.prepare("SELECT id, end_ts FROM segment ORDER BY end_ts DESC LIMIT 1").get() : void 0;
|
|
2489
2432
|
newMessages.sort((a, b) => a.ts - b.ts || a.id - b.id);
|
|
2490
2433
|
const insertSession = db.prepare(
|
|
2491
|
-
"INSERT INTO
|
|
2434
|
+
"INSERT INTO segment (start_ts, end_ts, message_count, is_manual, summary) VALUES (?, ?, ?, 0, NULL)"
|
|
2492
2435
|
);
|
|
2493
|
-
const insertContext = db.prepare("INSERT INTO message_context (message_id,
|
|
2494
|
-
const updateSession = db.prepare("UPDATE
|
|
2436
|
+
const insertContext = db.prepare("INSERT INTO message_context (message_id, segment_id, topic_id) VALUES (?, ?, NULL)");
|
|
2437
|
+
const updateSession = db.prepare("UPDATE segment SET end_ts = ?, message_count = message_count + ? WHERE id = ?");
|
|
2495
2438
|
return db.transaction(() => {
|
|
2496
2439
|
let newSessionCount = 0;
|
|
2497
2440
|
let currentSessionId = null;
|
|
@@ -2867,22 +2810,22 @@ function getSearchMessageContext(db, messageIds, contextBefore = 2, contextAfter
|
|
|
2867
2810
|
for (const messageId of messageIds) {
|
|
2868
2811
|
contextIds.add(messageId);
|
|
2869
2812
|
if (hasSessionData) {
|
|
2870
|
-
const sessionRow = db.prepare("SELECT
|
|
2813
|
+
const sessionRow = db.prepare("SELECT segment_id FROM message_context WHERE message_id = ?").get(messageId);
|
|
2871
2814
|
if (sessionRow) {
|
|
2872
2815
|
if (contextBefore > 0) {
|
|
2873
2816
|
const rows = db.prepare(
|
|
2874
2817
|
`SELECT mc.message_id as id FROM message_context mc
|
|
2875
|
-
WHERE mc.
|
|
2818
|
+
WHERE mc.segment_id = ? AND mc.message_id < ?
|
|
2876
2819
|
ORDER BY mc.message_id DESC LIMIT ?`
|
|
2877
|
-
).all(sessionRow.
|
|
2820
|
+
).all(sessionRow.segment_id, messageId, contextBefore);
|
|
2878
2821
|
rows.forEach((r) => contextIds.add(r.id));
|
|
2879
2822
|
}
|
|
2880
2823
|
if (contextAfter > 0) {
|
|
2881
2824
|
const rows = db.prepare(
|
|
2882
2825
|
`SELECT mc.message_id as id FROM message_context mc
|
|
2883
|
-
WHERE mc.
|
|
2826
|
+
WHERE mc.segment_id = ? AND mc.message_id > ?
|
|
2884
2827
|
ORDER BY mc.message_id ASC LIMIT ?`
|
|
2885
|
-
).all(sessionRow.
|
|
2828
|
+
).all(sessionRow.segment_id, messageId, contextAfter);
|
|
2886
2829
|
rows.forEach((r) => contextIds.add(r.id));
|
|
2887
2830
|
}
|
|
2888
2831
|
continue;
|
|
@@ -3229,17 +3172,17 @@ function filterMessagesWithContext(db, options = {}) {
|
|
|
3229
3172
|
pagination: { page, pageSize, totalBlocks, totalHits, hasMore }
|
|
3230
3173
|
};
|
|
3231
3174
|
}
|
|
3232
|
-
function getMultipleSessionsMessages(db,
|
|
3233
|
-
if (
|
|
3175
|
+
function getMultipleSessionsMessages(db, segmentIds, page = 1, pageSize = 50) {
|
|
3176
|
+
if (segmentIds.length === 0) {
|
|
3234
3177
|
return emptyResult(page, pageSize);
|
|
3235
3178
|
}
|
|
3236
3179
|
const sessionsSql = `
|
|
3237
3180
|
SELECT id, start_ts as startTs, end_ts as endTs, message_count as messageCount
|
|
3238
|
-
FROM
|
|
3239
|
-
WHERE id IN (${
|
|
3181
|
+
FROM segment
|
|
3182
|
+
WHERE id IN (${segmentIds.map(() => "?").join(",")})
|
|
3240
3183
|
ORDER BY start_ts ASC
|
|
3241
3184
|
`;
|
|
3242
|
-
const allSessions = db.prepare(sessionsSql).all(...
|
|
3185
|
+
const allSessions = db.prepare(sessionsSql).all(...segmentIds);
|
|
3243
3186
|
const totalBlocks = allSessions.length;
|
|
3244
3187
|
const startIdx = (page - 1) * pageSize;
|
|
3245
3188
|
const endIdx = Math.min(startIdx + pageSize, totalBlocks);
|
|
@@ -3262,7 +3205,7 @@ function getMultipleSessionsMessages(db, chatSessionIds, page = 1, pageSize = 50
|
|
|
3262
3205
|
JOIN member m ON msg.sender_id = m.id
|
|
3263
3206
|
LEFT JOIN message reply_msg ON msg.reply_to_message_id = reply_msg.platform_message_id
|
|
3264
3207
|
LEFT JOIN member reply_m ON reply_msg.sender_id = reply_m.id
|
|
3265
|
-
WHERE mc.
|
|
3208
|
+
WHERE mc.segment_id = ?
|
|
3266
3209
|
ORDER BY msg.ts ASC
|
|
3267
3210
|
`;
|
|
3268
3211
|
for (const session of pageSessions) {
|
|
@@ -3904,7 +3847,7 @@ function getRelationshipStats(db, filter, options) {
|
|
|
3904
3847
|
monthlyPerseverance: [],
|
|
3905
3848
|
perseveranceThreshold
|
|
3906
3849
|
};
|
|
3907
|
-
const sessionCount = db.prepare("SELECT COUNT(*) as count FROM
|
|
3850
|
+
const sessionCount = db.prepare("SELECT COUNT(*) as count FROM segment").get();
|
|
3908
3851
|
if (!sessionCount || sessionCount.count === 0) return emptyResult2;
|
|
3909
3852
|
const timeConditions = [];
|
|
3910
3853
|
const params = [];
|
|
@@ -3917,13 +3860,13 @@ function getRelationshipStats(db, filter, options) {
|
|
|
3917
3860
|
params.push(filter.endTs);
|
|
3918
3861
|
}
|
|
3919
3862
|
const whereClause = timeConditions.length > 0 ? `WHERE ${timeConditions.join(" AND ")}` : "";
|
|
3920
|
-
const
|
|
3921
|
-
`SELECT cs.id AS
|
|
3863
|
+
const segmentRows = db.prepare(
|
|
3864
|
+
`SELECT cs.id AS segment_id, cs.start_ts, cs.end_ts,
|
|
3922
3865
|
(SELECT m.sender_id FROM message_context mc JOIN message m ON m.id = mc.message_id
|
|
3923
|
-
WHERE mc.
|
|
3866
|
+
WHERE mc.segment_id = cs.id ORDER BY m.ts ASC, m.id ASC LIMIT 1) AS initiator_id,
|
|
3924
3867
|
(SELECT m.sender_id FROM message_context mc JOIN message m ON m.id = mc.message_id
|
|
3925
|
-
WHERE mc.
|
|
3926
|
-
FROM
|
|
3868
|
+
WHERE mc.segment_id = cs.id ORDER BY m.ts DESC, m.id DESC LIMIT 1) AS closer_id
|
|
3869
|
+
FROM segment cs ${whereClause} ORDER BY cs.start_ts ASC`
|
|
3927
3870
|
).all(...params);
|
|
3928
3871
|
const memberNames = /* @__PURE__ */ new Map();
|
|
3929
3872
|
const memberRows = db.prepare("SELECT id, COALESCE(group_nickname, account_name, platform_id) as name FROM member").all();
|
|
@@ -3934,7 +3877,7 @@ function getRelationshipStats(db, filter, options) {
|
|
|
3934
3877
|
const iceBreakMap = /* @__PURE__ */ new Map();
|
|
3935
3878
|
let totalIceBreaks = 0;
|
|
3936
3879
|
let prevEndTs = null;
|
|
3937
|
-
for (const row of
|
|
3880
|
+
for (const row of segmentRows) {
|
|
3938
3881
|
const month = toLocalMonth(row.start_ts);
|
|
3939
3882
|
if (!monthMap.has(month)) monthMap.set(month, { initiateMap: /* @__PURE__ */ new Map(), closeMap: /* @__PURE__ */ new Map(), totalSessions: 0 });
|
|
3940
3883
|
const ms = monthMap.get(month);
|
|
@@ -3983,12 +3926,12 @@ function getRelationshipStats(db, filter, options) {
|
|
|
3983
3926
|
iceBreakers.push({ month, memberId, name: memberNames.get(memberId) ?? `Unknown(${memberId})`, count });
|
|
3984
3927
|
}
|
|
3985
3928
|
}
|
|
3986
|
-
const
|
|
3987
|
-
const msgStats = queryMessageLevelStats(db,
|
|
3929
|
+
const segmentIdList = segmentRows.map((r) => r.segment_id);
|
|
3930
|
+
const msgStats = queryMessageLevelStats(db, segmentIdList, memberNames, perseveranceThreshold);
|
|
3988
3931
|
return {
|
|
3989
3932
|
months,
|
|
3990
3933
|
members,
|
|
3991
|
-
totalSessions:
|
|
3934
|
+
totalSessions: segmentRows.length,
|
|
3992
3935
|
hasSessionIndex: true,
|
|
3993
3936
|
iceBreakers,
|
|
3994
3937
|
totalIceBreaks,
|
|
@@ -3996,7 +3939,7 @@ function getRelationshipStats(db, filter, options) {
|
|
|
3996
3939
|
perseveranceThreshold
|
|
3997
3940
|
};
|
|
3998
3941
|
}
|
|
3999
|
-
function queryMessageLevelStats(db,
|
|
3942
|
+
function queryMessageLevelStats(db, segmentIds, memberNames, perseveranceThreshold) {
|
|
4000
3943
|
const empty = {
|
|
4001
3944
|
responseLatency: [],
|
|
4002
3945
|
perseverance: [],
|
|
@@ -4004,22 +3947,22 @@ function queryMessageLevelStats(db, sessionIds, memberNames, perseveranceThresho
|
|
|
4004
3947
|
monthlyResponseLatency: [],
|
|
4005
3948
|
monthlyPerseverance: []
|
|
4006
3949
|
};
|
|
4007
|
-
if (
|
|
3950
|
+
if (segmentIds.length === 0) return empty;
|
|
4008
3951
|
const BATCH_SIZE2 = 500;
|
|
4009
3952
|
const responseTotals = /* @__PURE__ */ new Map();
|
|
4010
3953
|
const dtTotals = /* @__PURE__ */ new Map();
|
|
4011
3954
|
const monthlyRespMap = /* @__PURE__ */ new Map();
|
|
4012
3955
|
const monthlyDtMap = /* @__PURE__ */ new Map();
|
|
4013
|
-
for (let i = 0; i <
|
|
4014
|
-
const batch =
|
|
3956
|
+
for (let i = 0; i < segmentIds.length; i += BATCH_SIZE2) {
|
|
3957
|
+
const batch = segmentIds.slice(i, i + BATCH_SIZE2);
|
|
4015
3958
|
const placeholders = batch.map(() => "?").join(",");
|
|
4016
3959
|
const latencyRows = db.prepare(
|
|
4017
3960
|
`WITH msg_lag AS (
|
|
4018
3961
|
SELECT m.sender_id, m.ts,
|
|
4019
|
-
LAG(m.sender_id) OVER (PARTITION BY mc.
|
|
4020
|
-
LAG(m.ts) OVER (PARTITION BY mc.
|
|
3962
|
+
LAG(m.sender_id) OVER (PARTITION BY mc.segment_id ORDER BY m.ts, m.id) AS prev_sender_id,
|
|
3963
|
+
LAG(m.ts) OVER (PARTITION BY mc.segment_id ORDER BY m.ts, m.id) AS prev_ts
|
|
4021
3964
|
FROM message_context mc JOIN message m ON m.id = mc.message_id
|
|
4022
|
-
WHERE mc.
|
|
3965
|
+
WHERE mc.segment_id IN (${placeholders}) AND m.type = 0
|
|
4023
3966
|
)
|
|
4024
3967
|
SELECT strftime('%Y-%m', datetime(ts, 'unixepoch', 'localtime')) AS month,
|
|
4025
3968
|
sender_id AS responder_id, SUM(ts - prev_ts) AS total_time, COUNT(*) AS response_count
|
|
@@ -4043,10 +3986,10 @@ function queryMessageLevelStats(db, sessionIds, memberNames, perseveranceThresho
|
|
|
4043
3986
|
const dtRows = db.prepare(
|
|
4044
3987
|
`WITH msg_lag AS (
|
|
4045
3988
|
SELECT m.sender_id, m.ts,
|
|
4046
|
-
LAG(m.sender_id) OVER (PARTITION BY mc.
|
|
4047
|
-
LAG(m.ts) OVER (PARTITION BY mc.
|
|
3989
|
+
LAG(m.sender_id) OVER (PARTITION BY mc.segment_id ORDER BY m.ts, m.id) AS prev_sender_id,
|
|
3990
|
+
LAG(m.ts) OVER (PARTITION BY mc.segment_id ORDER BY m.ts, m.id) AS prev_ts
|
|
4048
3991
|
FROM message_context mc JOIN message m ON m.id = mc.message_id
|
|
4049
|
-
WHERE mc.
|
|
3992
|
+
WHERE mc.segment_id IN (${placeholders}) AND m.type = 0
|
|
4050
3993
|
)
|
|
4051
3994
|
SELECT strftime('%Y-%m', datetime(ts, 'unixepoch', 'localtime')) AS month,
|
|
4052
3995
|
sender_id, COUNT(*) AS double_text_count
|
|
@@ -4258,125 +4201,6 @@ function getLanguagePreferenceAnalysis(db, params) {
|
|
|
4258
4201
|
return { members: memberProfiles, sharedWords, similarityScore };
|
|
4259
4202
|
}
|
|
4260
4203
|
|
|
4261
|
-
// ../../packages/core/src/schema/tables.ts
|
|
4262
|
-
var CURRENT_SCHEMA_VERSION = 5;
|
|
4263
|
-
var CHAT_DB_TABLES = `
|
|
4264
|
-
CREATE TABLE IF NOT EXISTS meta (
|
|
4265
|
-
name TEXT NOT NULL,
|
|
4266
|
-
platform TEXT NOT NULL,
|
|
4267
|
-
type TEXT NOT NULL,
|
|
4268
|
-
imported_at INTEGER NOT NULL,
|
|
4269
|
-
group_id TEXT,
|
|
4270
|
-
group_avatar TEXT,
|
|
4271
|
-
owner_id TEXT,
|
|
4272
|
-
schema_version INTEGER DEFAULT ${CURRENT_SCHEMA_VERSION},
|
|
4273
|
-
session_gap_threshold INTEGER
|
|
4274
|
-
);
|
|
4275
|
-
|
|
4276
|
-
CREATE TABLE IF NOT EXISTS member (
|
|
4277
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
4278
|
-
platform_id TEXT NOT NULL UNIQUE,
|
|
4279
|
-
account_name TEXT,
|
|
4280
|
-
group_nickname TEXT,
|
|
4281
|
-
aliases TEXT DEFAULT '[]',
|
|
4282
|
-
avatar TEXT,
|
|
4283
|
-
roles TEXT DEFAULT '[]'
|
|
4284
|
-
);
|
|
4285
|
-
|
|
4286
|
-
CREATE TABLE IF NOT EXISTS member_name_history (
|
|
4287
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
4288
|
-
member_id INTEGER NOT NULL,
|
|
4289
|
-
name_type TEXT NOT NULL,
|
|
4290
|
-
name TEXT NOT NULL,
|
|
4291
|
-
start_ts INTEGER NOT NULL,
|
|
4292
|
-
end_ts INTEGER,
|
|
4293
|
-
FOREIGN KEY(member_id) REFERENCES member(id)
|
|
4294
|
-
);
|
|
4295
|
-
|
|
4296
|
-
CREATE TABLE IF NOT EXISTS message (
|
|
4297
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
4298
|
-
sender_id INTEGER NOT NULL,
|
|
4299
|
-
sender_account_name TEXT,
|
|
4300
|
-
sender_group_nickname TEXT,
|
|
4301
|
-
ts INTEGER NOT NULL,
|
|
4302
|
-
type INTEGER NOT NULL,
|
|
4303
|
-
content TEXT,
|
|
4304
|
-
reply_to_message_id TEXT DEFAULT NULL,
|
|
4305
|
-
platform_message_id TEXT DEFAULT NULL,
|
|
4306
|
-
FOREIGN KEY(sender_id) REFERENCES member(id)
|
|
4307
|
-
);
|
|
4308
|
-
|
|
4309
|
-
CREATE TABLE IF NOT EXISTS chat_session (
|
|
4310
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
4311
|
-
start_ts INTEGER NOT NULL,
|
|
4312
|
-
end_ts INTEGER NOT NULL,
|
|
4313
|
-
message_count INTEGER DEFAULT 0,
|
|
4314
|
-
is_manual INTEGER DEFAULT 0,
|
|
4315
|
-
summary TEXT
|
|
4316
|
-
);
|
|
4317
|
-
|
|
4318
|
-
CREATE TABLE IF NOT EXISTS message_context (
|
|
4319
|
-
message_id INTEGER PRIMARY KEY,
|
|
4320
|
-
session_id INTEGER NOT NULL,
|
|
4321
|
-
topic_id INTEGER
|
|
4322
|
-
);
|
|
4323
|
-
`;
|
|
4324
|
-
var CHAT_DB_INDEXES = `
|
|
4325
|
-
CREATE INDEX IF NOT EXISTS idx_message_ts ON message(ts);
|
|
4326
|
-
CREATE INDEX IF NOT EXISTS idx_message_sender ON message(sender_id);
|
|
4327
|
-
CREATE INDEX IF NOT EXISTS idx_message_platform_id ON message(platform_message_id);
|
|
4328
|
-
CREATE INDEX IF NOT EXISTS idx_member_name_history_member_id ON member_name_history(member_id);
|
|
4329
|
-
CREATE INDEX IF NOT EXISTS idx_session_time ON chat_session(start_ts, end_ts);
|
|
4330
|
-
CREATE INDEX IF NOT EXISTS idx_context_session ON message_context(session_id);
|
|
4331
|
-
`;
|
|
4332
|
-
var CHAT_DB_SCHEMA = CHAT_DB_TABLES + CHAT_DB_INDEXES;
|
|
4333
|
-
var FTS_TABLE_SCHEMA = `
|
|
4334
|
-
CREATE VIRTUAL TABLE IF NOT EXISTS message_fts USING fts5(
|
|
4335
|
-
content,
|
|
4336
|
-
content='',
|
|
4337
|
-
content_rowid=id
|
|
4338
|
-
);
|
|
4339
|
-
`;
|
|
4340
|
-
|
|
4341
|
-
// ../../packages/core/src/schema/migrations.ts
|
|
4342
|
-
function getSchemaVersion(db) {
|
|
4343
|
-
try {
|
|
4344
|
-
const tableInfo = db.pragma("table_info(meta)");
|
|
4345
|
-
const hasVersionColumn = tableInfo.some((col) => col.name === "schema_version");
|
|
4346
|
-
if (!hasVersionColumn) return 0;
|
|
4347
|
-
const result = db.prepare("SELECT schema_version FROM meta LIMIT 1").get();
|
|
4348
|
-
return result?.schema_version ?? 0;
|
|
4349
|
-
} catch {
|
|
4350
|
-
return 0;
|
|
4351
|
-
}
|
|
4352
|
-
}
|
|
4353
|
-
function setSchemaVersion(db, version) {
|
|
4354
|
-
const tableInfo = db.pragma("table_info(meta)");
|
|
4355
|
-
const hasVersionColumn = tableInfo.some((col) => col.name === "schema_version");
|
|
4356
|
-
if (!hasVersionColumn) {
|
|
4357
|
-
db.exec("ALTER TABLE meta ADD COLUMN schema_version INTEGER DEFAULT 0");
|
|
4358
|
-
}
|
|
4359
|
-
db.prepare("UPDATE meta SET schema_version = ?").run(version);
|
|
4360
|
-
}
|
|
4361
|
-
function needsMigration(db, targetVersion) {
|
|
4362
|
-
return getSchemaVersion(db) < targetVersion;
|
|
4363
|
-
}
|
|
4364
|
-
function runMigrations(db, migrationsList, forceRepair = false) {
|
|
4365
|
-
const currentVersion = getSchemaVersion(db);
|
|
4366
|
-
if (!forceRepair && currentVersion >= (migrationsList.at(-1)?.version ?? 0)) {
|
|
4367
|
-
return false;
|
|
4368
|
-
}
|
|
4369
|
-
const pending = forceRepair ? migrationsList : migrationsList.filter((m) => m.version > currentVersion);
|
|
4370
|
-
if (pending.length === 0) return false;
|
|
4371
|
-
db.transaction(() => {
|
|
4372
|
-
for (const migration of pending) {
|
|
4373
|
-
migration.up(db);
|
|
4374
|
-
setSchemaVersion(db, migration.version);
|
|
4375
|
-
}
|
|
4376
|
-
});
|
|
4377
|
-
return true;
|
|
4378
|
-
}
|
|
4379
|
-
|
|
4380
4204
|
// ../../packages/core/src/version.ts
|
|
4381
4205
|
function parseStableVersion(version) {
|
|
4382
4206
|
const normalized = version.trim().replace(/^v/i, "");
|
|
@@ -5450,6 +5274,17 @@ function isValidWord(word, locale, minLength, enableStopwords, isStopwordFn) {
|
|
|
5450
5274
|
}
|
|
5451
5275
|
|
|
5452
5276
|
// ../../packages/core/src/ai/tool-catalog.ts
|
|
5277
|
+
var LEGACY_BUILTIN_TOOL_NAME_ALIASES = {
|
|
5278
|
+
search_sessions: "search_segments",
|
|
5279
|
+
get_session_messages: "get_segment_messages",
|
|
5280
|
+
get_session_summaries: "get_segment_summaries"
|
|
5281
|
+
};
|
|
5282
|
+
function normalizeBuiltinToolName(toolName) {
|
|
5283
|
+
return LEGACY_BUILTIN_TOOL_NAME_ALIASES[toolName] ?? toolName;
|
|
5284
|
+
}
|
|
5285
|
+
function normalizeBuiltinToolNames(toolNames) {
|
|
5286
|
+
return Array.from(new Set(toolNames.map(normalizeBuiltinToolName)));
|
|
5287
|
+
}
|
|
5453
5288
|
var BUILTIN_TOOL_CATALOG = [
|
|
5454
5289
|
// Core 工具
|
|
5455
5290
|
{ name: "get_chat_overview", category: "core" },
|
|
@@ -5457,8 +5292,8 @@ var BUILTIN_TOOL_CATALOG = [
|
|
|
5457
5292
|
{ name: "deep_search_messages", category: "core" },
|
|
5458
5293
|
{ name: "get_recent_messages", category: "core" },
|
|
5459
5294
|
{ name: "get_message_context", category: "core" },
|
|
5460
|
-
{ name: "
|
|
5461
|
-
{ name: "
|
|
5295
|
+
{ name: "search_segments", category: "core" },
|
|
5296
|
+
{ name: "get_segment_messages", category: "core" },
|
|
5462
5297
|
{ name: "get_members", category: "core" },
|
|
5463
5298
|
{ name: "get_schema", category: "core" },
|
|
5464
5299
|
// Analysis 工具
|
|
@@ -5466,7 +5301,7 @@ var BUILTIN_TOOL_CATALOG = [
|
|
|
5466
5301
|
{ name: "get_time_stats", category: "analysis" },
|
|
5467
5302
|
{ name: "get_member_name_history", category: "analysis" },
|
|
5468
5303
|
{ name: "get_conversation_between", category: "analysis" },
|
|
5469
|
-
{ name: "
|
|
5304
|
+
{ name: "get_segment_summaries", category: "analysis" },
|
|
5470
5305
|
{ name: "response_time_analysis", category: "analysis" },
|
|
5471
5306
|
{ name: "keyword_frequency", category: "analysis" },
|
|
5472
5307
|
{ name: "render_chart", category: "analysis" },
|
|
@@ -7001,6 +6836,125 @@ function mergeMembers2(sources, collidingIds) {
|
|
|
7001
6836
|
return map;
|
|
7002
6837
|
}
|
|
7003
6838
|
|
|
6839
|
+
// ../../packages/core/src/schema/tables.ts
|
|
6840
|
+
var CURRENT_SCHEMA_VERSION = 6;
|
|
6841
|
+
var CHAT_DB_TABLES = `
|
|
6842
|
+
CREATE TABLE IF NOT EXISTS meta (
|
|
6843
|
+
name TEXT NOT NULL,
|
|
6844
|
+
platform TEXT NOT NULL,
|
|
6845
|
+
type TEXT NOT NULL,
|
|
6846
|
+
imported_at INTEGER NOT NULL,
|
|
6847
|
+
group_id TEXT,
|
|
6848
|
+
group_avatar TEXT,
|
|
6849
|
+
owner_id TEXT,
|
|
6850
|
+
schema_version INTEGER DEFAULT ${CURRENT_SCHEMA_VERSION},
|
|
6851
|
+
session_gap_threshold INTEGER
|
|
6852
|
+
);
|
|
6853
|
+
|
|
6854
|
+
CREATE TABLE IF NOT EXISTS member (
|
|
6855
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
6856
|
+
platform_id TEXT NOT NULL UNIQUE,
|
|
6857
|
+
account_name TEXT,
|
|
6858
|
+
group_nickname TEXT,
|
|
6859
|
+
aliases TEXT DEFAULT '[]',
|
|
6860
|
+
avatar TEXT,
|
|
6861
|
+
roles TEXT DEFAULT '[]'
|
|
6862
|
+
);
|
|
6863
|
+
|
|
6864
|
+
CREATE TABLE IF NOT EXISTS member_name_history (
|
|
6865
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
6866
|
+
member_id INTEGER NOT NULL,
|
|
6867
|
+
name_type TEXT NOT NULL,
|
|
6868
|
+
name TEXT NOT NULL,
|
|
6869
|
+
start_ts INTEGER NOT NULL,
|
|
6870
|
+
end_ts INTEGER,
|
|
6871
|
+
FOREIGN KEY(member_id) REFERENCES member(id)
|
|
6872
|
+
);
|
|
6873
|
+
|
|
6874
|
+
CREATE TABLE IF NOT EXISTS message (
|
|
6875
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
6876
|
+
sender_id INTEGER NOT NULL,
|
|
6877
|
+
sender_account_name TEXT,
|
|
6878
|
+
sender_group_nickname TEXT,
|
|
6879
|
+
ts INTEGER NOT NULL,
|
|
6880
|
+
type INTEGER NOT NULL,
|
|
6881
|
+
content TEXT,
|
|
6882
|
+
reply_to_message_id TEXT DEFAULT NULL,
|
|
6883
|
+
platform_message_id TEXT DEFAULT NULL,
|
|
6884
|
+
FOREIGN KEY(sender_id) REFERENCES member(id)
|
|
6885
|
+
);
|
|
6886
|
+
|
|
6887
|
+
CREATE TABLE IF NOT EXISTS segment (
|
|
6888
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
6889
|
+
start_ts INTEGER NOT NULL,
|
|
6890
|
+
end_ts INTEGER NOT NULL,
|
|
6891
|
+
message_count INTEGER DEFAULT 0,
|
|
6892
|
+
is_manual INTEGER DEFAULT 0,
|
|
6893
|
+
summary TEXT
|
|
6894
|
+
);
|
|
6895
|
+
|
|
6896
|
+
CREATE TABLE IF NOT EXISTS message_context (
|
|
6897
|
+
message_id INTEGER PRIMARY KEY,
|
|
6898
|
+
segment_id INTEGER NOT NULL,
|
|
6899
|
+
topic_id INTEGER
|
|
6900
|
+
);
|
|
6901
|
+
`;
|
|
6902
|
+
var CHAT_DB_INDEXES = `
|
|
6903
|
+
CREATE INDEX IF NOT EXISTS idx_message_ts ON message(ts);
|
|
6904
|
+
CREATE INDEX IF NOT EXISTS idx_message_sender ON message(sender_id);
|
|
6905
|
+
CREATE INDEX IF NOT EXISTS idx_message_platform_id ON message(platform_message_id);
|
|
6906
|
+
CREATE INDEX IF NOT EXISTS idx_member_name_history_member_id ON member_name_history(member_id);
|
|
6907
|
+
CREATE INDEX IF NOT EXISTS idx_segment_time ON segment(start_ts, end_ts);
|
|
6908
|
+
CREATE INDEX IF NOT EXISTS idx_context_segment ON message_context(segment_id);
|
|
6909
|
+
`;
|
|
6910
|
+
var CHAT_DB_SCHEMA = CHAT_DB_TABLES + CHAT_DB_INDEXES;
|
|
6911
|
+
var FTS_TABLE_SCHEMA = `
|
|
6912
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS message_fts USING fts5(
|
|
6913
|
+
content,
|
|
6914
|
+
content='',
|
|
6915
|
+
content_rowid=id
|
|
6916
|
+
);
|
|
6917
|
+
`;
|
|
6918
|
+
|
|
6919
|
+
// ../../packages/core/src/schema/migrations.ts
|
|
6920
|
+
function getSchemaVersion(db) {
|
|
6921
|
+
try {
|
|
6922
|
+
const tableInfo = db.pragma("table_info(meta)");
|
|
6923
|
+
const hasVersionColumn = tableInfo.some((col) => col.name === "schema_version");
|
|
6924
|
+
if (!hasVersionColumn) return 0;
|
|
6925
|
+
const result = db.prepare("SELECT schema_version FROM meta LIMIT 1").get();
|
|
6926
|
+
return result?.schema_version ?? 0;
|
|
6927
|
+
} catch {
|
|
6928
|
+
return 0;
|
|
6929
|
+
}
|
|
6930
|
+
}
|
|
6931
|
+
function setSchemaVersion(db, version) {
|
|
6932
|
+
const tableInfo = db.pragma("table_info(meta)");
|
|
6933
|
+
const hasVersionColumn = tableInfo.some((col) => col.name === "schema_version");
|
|
6934
|
+
if (!hasVersionColumn) {
|
|
6935
|
+
db.exec("ALTER TABLE meta ADD COLUMN schema_version INTEGER DEFAULT 0");
|
|
6936
|
+
}
|
|
6937
|
+
db.prepare("UPDATE meta SET schema_version = ?").run(version);
|
|
6938
|
+
}
|
|
6939
|
+
function needsMigration(db, targetVersion) {
|
|
6940
|
+
return getSchemaVersion(db) < targetVersion;
|
|
6941
|
+
}
|
|
6942
|
+
function runMigrations(db, migrationsList, forceRepair = false) {
|
|
6943
|
+
const currentVersion = getSchemaVersion(db);
|
|
6944
|
+
if (!forceRepair && currentVersion >= (migrationsList.at(-1)?.version ?? 0)) {
|
|
6945
|
+
return false;
|
|
6946
|
+
}
|
|
6947
|
+
const pending = forceRepair ? migrationsList : migrationsList.filter((m) => m.version > currentVersion);
|
|
6948
|
+
if (pending.length === 0) return false;
|
|
6949
|
+
db.transaction(() => {
|
|
6950
|
+
for (const migration of pending) {
|
|
6951
|
+
migration.up(db);
|
|
6952
|
+
setSchemaVersion(db, migration.version);
|
|
6953
|
+
}
|
|
6954
|
+
});
|
|
6955
|
+
return true;
|
|
6956
|
+
}
|
|
6957
|
+
|
|
7004
6958
|
// ../../packages/parser/src/index.ts
|
|
7005
6959
|
import * as fs24 from "fs";
|
|
7006
6960
|
import * as path20 from "path";
|
|
@@ -12207,17 +12161,17 @@ function writeParseResultToDb(db, meta, members, messages) {
|
|
|
12207
12161
|
// ../../packages/node-runtime/src/import/perf-logger.ts
|
|
12208
12162
|
var lastLogTime = Date.now();
|
|
12209
12163
|
|
|
12210
|
-
// ../../packages/node-runtime/src/ai/
|
|
12211
|
-
import
|
|
12164
|
+
// ../../packages/node-runtime/src/ai/chats.ts
|
|
12165
|
+
import Database from "better-sqlite3";
|
|
12212
12166
|
import * as fs28 from "fs";
|
|
12213
12167
|
import * as path23 from "path";
|
|
12214
12168
|
var DEFAULT_GENERAL_ID = "general_cn";
|
|
12215
12169
|
var defaultLogger = {
|
|
12216
12170
|
warn(_category, message, extra) {
|
|
12217
|
-
console.warn(`[AI
|
|
12171
|
+
console.warn(`[AI Chats] ${message}`, extra ?? "");
|
|
12218
12172
|
}
|
|
12219
12173
|
};
|
|
12220
|
-
var
|
|
12174
|
+
var AIChatManager = class {
|
|
12221
12175
|
db = null;
|
|
12222
12176
|
aiDataDir;
|
|
12223
12177
|
logger;
|
|
@@ -12237,13 +12191,14 @@ var AIConversationManager = class {
|
|
|
12237
12191
|
if (this.db) return this.db;
|
|
12238
12192
|
this.ensureDir(this.aiDataDir);
|
|
12239
12193
|
const dbPath = path23.join(this.aiDataDir, "conversations.db");
|
|
12240
|
-
this.db = this.nativeBinding ? new
|
|
12194
|
+
this.db = this.nativeBinding ? new Database(dbPath, { nativeBinding: this.nativeBinding }) : new Database(dbPath);
|
|
12241
12195
|
this.db.pragma("journal_mode = WAL");
|
|
12242
12196
|
this.db.exec(`
|
|
12243
|
-
CREATE TABLE IF NOT EXISTS
|
|
12197
|
+
CREATE TABLE IF NOT EXISTS ai_chat (
|
|
12244
12198
|
id TEXT PRIMARY KEY,
|
|
12245
12199
|
session_id TEXT NOT NULL,
|
|
12246
12200
|
title TEXT,
|
|
12201
|
+
assistant_id TEXT DEFAULT '${DEFAULT_GENERAL_ID}',
|
|
12247
12202
|
active_message_id TEXT,
|
|
12248
12203
|
created_at INTEGER NOT NULL,
|
|
12249
12204
|
updated_at INTEGER NOT NULL
|
|
@@ -12251,7 +12206,7 @@ var AIConversationManager = class {
|
|
|
12251
12206
|
|
|
12252
12207
|
CREATE TABLE IF NOT EXISTS ai_message (
|
|
12253
12208
|
id TEXT PRIMARY KEY,
|
|
12254
|
-
|
|
12209
|
+
ai_chat_id TEXT NOT NULL,
|
|
12255
12210
|
role TEXT NOT NULL,
|
|
12256
12211
|
content TEXT NOT NULL,
|
|
12257
12212
|
timestamp INTEGER NOT NULL,
|
|
@@ -12261,51 +12216,113 @@ var AIConversationManager = class {
|
|
|
12261
12216
|
parent_id TEXT,
|
|
12262
12217
|
sibling_group_id TEXT,
|
|
12263
12218
|
branch_index INTEGER DEFAULT 0,
|
|
12264
|
-
|
|
12219
|
+
debug_context TEXT,
|
|
12220
|
+
token_usage TEXT,
|
|
12221
|
+
FOREIGN KEY(ai_chat_id) REFERENCES ai_chat(id) ON DELETE CASCADE
|
|
12265
12222
|
);
|
|
12266
12223
|
|
|
12267
|
-
CREATE INDEX IF NOT EXISTS idx_ai_conversation_session ON ai_conversation(session_id);
|
|
12268
|
-
CREATE INDEX IF NOT EXISTS idx_ai_message_conversation ON ai_message(conversation_id);
|
|
12269
12224
|
`);
|
|
12270
12225
|
this.migrateDatabase(this.db);
|
|
12271
12226
|
return this.db;
|
|
12272
12227
|
}
|
|
12228
|
+
tableExists(db, tableName) {
|
|
12229
|
+
const row = db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?").get(tableName);
|
|
12230
|
+
return !!row;
|
|
12231
|
+
}
|
|
12232
|
+
getTableColumns(db, tableName) {
|
|
12233
|
+
const tableInfo = db.pragma(`table_info(${tableName})`);
|
|
12234
|
+
return tableInfo.map((col) => col.name);
|
|
12235
|
+
}
|
|
12236
|
+
ensureMessageMigrationColumns(db, tableName) {
|
|
12237
|
+
const messageColumns = this.getTableColumns(db, tableName);
|
|
12238
|
+
if (!messageColumns.includes("content_blocks")) {
|
|
12239
|
+
db.exec(`ALTER TABLE ${tableName} ADD COLUMN content_blocks TEXT`);
|
|
12240
|
+
}
|
|
12241
|
+
if (!messageColumns.includes("token_usage")) {
|
|
12242
|
+
db.exec(`ALTER TABLE ${tableName} ADD COLUMN token_usage TEXT`);
|
|
12243
|
+
}
|
|
12244
|
+
if (!messageColumns.includes("debug_context")) {
|
|
12245
|
+
db.exec(`ALTER TABLE ${tableName} ADD COLUMN debug_context TEXT`);
|
|
12246
|
+
}
|
|
12247
|
+
if (!messageColumns.includes("parent_id")) {
|
|
12248
|
+
db.exec(`ALTER TABLE ${tableName} ADD COLUMN parent_id TEXT`);
|
|
12249
|
+
}
|
|
12250
|
+
if (!messageColumns.includes("sibling_group_id")) {
|
|
12251
|
+
db.exec(`ALTER TABLE ${tableName} ADD COLUMN sibling_group_id TEXT`);
|
|
12252
|
+
}
|
|
12253
|
+
if (!messageColumns.includes("branch_index")) {
|
|
12254
|
+
db.exec(`ALTER TABLE ${tableName} ADD COLUMN branch_index INTEGER DEFAULT 0`);
|
|
12255
|
+
}
|
|
12256
|
+
}
|
|
12273
12257
|
migrateDatabase(db) {
|
|
12274
12258
|
try {
|
|
12275
|
-
const
|
|
12276
|
-
|
|
12277
|
-
|
|
12278
|
-
|
|
12279
|
-
|
|
12280
|
-
|
|
12281
|
-
|
|
12282
|
-
|
|
12283
|
-
|
|
12284
|
-
|
|
12285
|
-
|
|
12286
|
-
|
|
12287
|
-
|
|
12288
|
-
|
|
12289
|
-
|
|
12290
|
-
|
|
12291
|
-
|
|
12292
|
-
}
|
|
12293
|
-
if (!messageColumns.includes("branch_index")) {
|
|
12294
|
-
db.exec("ALTER TABLE ai_message ADD COLUMN branch_index INTEGER DEFAULT 0");
|
|
12259
|
+
const hasLegacyConversationTable = this.tableExists(db, "ai_conversation");
|
|
12260
|
+
if (hasLegacyConversationTable) {
|
|
12261
|
+
const convColumns = this.getTableColumns(db, "ai_conversation");
|
|
12262
|
+
if (!convColumns.includes("assistant_id")) {
|
|
12263
|
+
db.exec(`ALTER TABLE ai_conversation ADD COLUMN assistant_id TEXT DEFAULT '${DEFAULT_GENERAL_ID}'`);
|
|
12264
|
+
}
|
|
12265
|
+
if (!convColumns.includes("active_message_id")) {
|
|
12266
|
+
db.exec("ALTER TABLE ai_conversation ADD COLUMN active_message_id TEXT");
|
|
12267
|
+
}
|
|
12268
|
+
db.exec(`
|
|
12269
|
+
INSERT OR IGNORE INTO ai_chat (
|
|
12270
|
+
id, session_id, title, assistant_id, active_message_id, created_at, updated_at
|
|
12271
|
+
)
|
|
12272
|
+
SELECT id, session_id, title, COALESCE(assistant_id, '${DEFAULT_GENERAL_ID}'),
|
|
12273
|
+
active_message_id, created_at, updated_at
|
|
12274
|
+
FROM ai_conversation
|
|
12275
|
+
`);
|
|
12295
12276
|
}
|
|
12296
|
-
|
|
12297
|
-
const
|
|
12298
|
-
const
|
|
12299
|
-
|
|
12300
|
-
|
|
12277
|
+
this.ensureMessageMigrationColumns(db, "ai_message");
|
|
12278
|
+
const messageColumns = this.getTableColumns(db, "ai_message");
|
|
12279
|
+
const hadLegacyConversationId = messageColumns.includes("conversation_id");
|
|
12280
|
+
const needsMessageTreeBackfill = !messageColumns.includes("parent_id") || !messageColumns.includes("sibling_group_id") || !messageColumns.includes("branch_index") || hadLegacyConversationId;
|
|
12281
|
+
if (hadLegacyConversationId && !messageColumns.includes("ai_chat_id")) {
|
|
12282
|
+
db.exec(`
|
|
12283
|
+
DROP INDEX IF EXISTS idx_ai_message_conversation;
|
|
12284
|
+
ALTER TABLE ai_message RENAME TO ai_message_legacy;
|
|
12285
|
+
|
|
12286
|
+
CREATE TABLE ai_message (
|
|
12287
|
+
id TEXT PRIMARY KEY,
|
|
12288
|
+
ai_chat_id TEXT NOT NULL,
|
|
12289
|
+
role TEXT NOT NULL,
|
|
12290
|
+
content TEXT NOT NULL,
|
|
12291
|
+
timestamp INTEGER NOT NULL,
|
|
12292
|
+
data_keywords TEXT,
|
|
12293
|
+
data_message_count INTEGER,
|
|
12294
|
+
content_blocks TEXT,
|
|
12295
|
+
parent_id TEXT,
|
|
12296
|
+
sibling_group_id TEXT,
|
|
12297
|
+
branch_index INTEGER DEFAULT 0,
|
|
12298
|
+
debug_context TEXT,
|
|
12299
|
+
token_usage TEXT,
|
|
12300
|
+
FOREIGN KEY(ai_chat_id) REFERENCES ai_chat(id) ON DELETE CASCADE
|
|
12301
|
+
);
|
|
12302
|
+
|
|
12303
|
+
INSERT INTO ai_message (
|
|
12304
|
+
id, ai_chat_id, role, content, timestamp, data_keywords, data_message_count,
|
|
12305
|
+
content_blocks, parent_id, sibling_group_id, branch_index, debug_context, token_usage
|
|
12306
|
+
)
|
|
12307
|
+
SELECT id, conversation_id, role, content, timestamp, data_keywords, data_message_count,
|
|
12308
|
+
content_blocks, parent_id, sibling_group_id, branch_index, debug_context, token_usage
|
|
12309
|
+
FROM ai_message_legacy;
|
|
12310
|
+
|
|
12311
|
+
DROP TABLE ai_message_legacy;
|
|
12312
|
+
`);
|
|
12301
12313
|
}
|
|
12302
|
-
if (
|
|
12303
|
-
db.exec(
|
|
12314
|
+
if (hasLegacyConversationTable) {
|
|
12315
|
+
db.exec(`
|
|
12316
|
+
DROP INDEX IF EXISTS idx_ai_conversation_session;
|
|
12317
|
+
DROP TABLE ai_conversation;
|
|
12318
|
+
`);
|
|
12304
12319
|
}
|
|
12305
|
-
if (needsMessageTreeBackfill ||
|
|
12320
|
+
if (needsMessageTreeBackfill || this.hasUnbackfilledMessageTree(db)) {
|
|
12306
12321
|
this.backfillMessageTree(db);
|
|
12307
12322
|
}
|
|
12308
12323
|
db.exec(`
|
|
12324
|
+
CREATE INDEX IF NOT EXISTS idx_ai_chat_session ON ai_chat(session_id);
|
|
12325
|
+
CREATE INDEX IF NOT EXISTS idx_ai_message_ai_chat ON ai_message(ai_chat_id);
|
|
12309
12326
|
CREATE INDEX IF NOT EXISTS idx_ai_message_parent ON ai_message(parent_id);
|
|
12310
12327
|
CREATE INDEX IF NOT EXISTS idx_ai_message_sibling ON ai_message(sibling_group_id);
|
|
12311
12328
|
`);
|
|
@@ -12316,16 +12333,16 @@ var AIConversationManager = class {
|
|
|
12316
12333
|
hasUnbackfilledMessageTree(db) {
|
|
12317
12334
|
const row = db.prepare(
|
|
12318
12335
|
`SELECT 1
|
|
12319
|
-
FROM
|
|
12336
|
+
FROM ai_chat c
|
|
12320
12337
|
WHERE EXISTS (
|
|
12321
12338
|
SELECT 1 FROM ai_message m
|
|
12322
|
-
WHERE m.
|
|
12339
|
+
WHERE m.ai_chat_id = c.id
|
|
12323
12340
|
)
|
|
12324
12341
|
AND (
|
|
12325
12342
|
c.active_message_id IS NULL
|
|
12326
12343
|
OR EXISTS (
|
|
12327
12344
|
SELECT 1 FROM ai_message m
|
|
12328
|
-
WHERE m.
|
|
12345
|
+
WHERE m.ai_chat_id = c.id
|
|
12329
12346
|
AND (m.sibling_group_id IS NULL OR m.branch_index IS NULL)
|
|
12330
12347
|
)
|
|
12331
12348
|
)
|
|
@@ -12334,26 +12351,26 @@ var AIConversationManager = class {
|
|
|
12334
12351
|
return !!row;
|
|
12335
12352
|
}
|
|
12336
12353
|
backfillMessageTree(db) {
|
|
12337
|
-
const
|
|
12354
|
+
const aiChats = db.prepare("SELECT id FROM ai_chat").all();
|
|
12338
12355
|
const updateMessage = db.prepare(
|
|
12339
12356
|
"UPDATE ai_message SET parent_id = ?, sibling_group_id = COALESCE(sibling_group_id, ?), branch_index = COALESCE(branch_index, 0) WHERE id = ?"
|
|
12340
12357
|
);
|
|
12341
|
-
const
|
|
12358
|
+
const updateAIChat = db.prepare("UPDATE ai_chat SET active_message_id = ? WHERE id = ?");
|
|
12342
12359
|
const tx = db.transaction(() => {
|
|
12343
|
-
for (const
|
|
12360
|
+
for (const aiChat of aiChats) {
|
|
12344
12361
|
const messages = db.prepare(
|
|
12345
12362
|
`SELECT id, parent_id as parentId, sibling_group_id as siblingGroupId
|
|
12346
|
-
FROM ai_message WHERE
|
|
12347
|
-
).all(
|
|
12363
|
+
FROM ai_message WHERE ai_chat_id = ? ORDER BY timestamp ASC, id ASC`
|
|
12364
|
+
).all(aiChat.id);
|
|
12348
12365
|
let previousId = null;
|
|
12349
12366
|
for (const message of messages) {
|
|
12350
12367
|
const parentId = message.parentId === void 0 ? previousId : message.parentId ?? previousId;
|
|
12351
12368
|
updateMessage.run(parentId, message.siblingGroupId ?? message.id, message.id);
|
|
12352
12369
|
previousId = message.id;
|
|
12353
12370
|
}
|
|
12354
|
-
const
|
|
12355
|
-
if (!
|
|
12356
|
-
|
|
12371
|
+
const aiChatRow = db.prepare("SELECT active_message_id as activeMessageId FROM ai_chat WHERE id = ?").get(aiChat.id);
|
|
12372
|
+
if (!aiChatRow?.activeMessageId && previousId) {
|
|
12373
|
+
updateAIChat.run(previousId, aiChat.id);
|
|
12357
12374
|
}
|
|
12358
12375
|
}
|
|
12359
12376
|
});
|
|
@@ -12365,7 +12382,7 @@ var AIConversationManager = class {
|
|
|
12365
12382
|
parseMessageRow(row) {
|
|
12366
12383
|
return {
|
|
12367
12384
|
id: row.id,
|
|
12368
|
-
|
|
12385
|
+
aiChatId: row.aiChatId,
|
|
12369
12386
|
role: row.role,
|
|
12370
12387
|
content: row.content,
|
|
12371
12388
|
timestamp: row.timestamp,
|
|
@@ -12379,7 +12396,7 @@ var AIConversationManager = class {
|
|
|
12379
12396
|
getMessageRow(messageId) {
|
|
12380
12397
|
const db = this.getDb();
|
|
12381
12398
|
const row = db.prepare(
|
|
12382
|
-
`SELECT id,
|
|
12399
|
+
`SELECT id, ai_chat_id as aiChatId, role, content, timestamp,
|
|
12383
12400
|
parent_id as parentId, sibling_group_id as siblingGroupId, branch_index as branchIndex,
|
|
12384
12401
|
data_keywords as dataKeywords, data_message_count as dataMessageCount,
|
|
12385
12402
|
content_blocks as contentBlocks, token_usage as tokenUsage
|
|
@@ -12387,45 +12404,45 @@ var AIConversationManager = class {
|
|
|
12387
12404
|
).get(messageId);
|
|
12388
12405
|
return row ?? null;
|
|
12389
12406
|
}
|
|
12390
|
-
getActiveMessageId(
|
|
12407
|
+
getActiveMessageId(aiChatId) {
|
|
12391
12408
|
const db = this.getDb();
|
|
12392
|
-
const row = db.prepare("SELECT active_message_id as activeMessageId FROM
|
|
12409
|
+
const row = db.prepare("SELECT active_message_id as activeMessageId FROM ai_chat WHERE id = ?").get(aiChatId);
|
|
12393
12410
|
if (row?.activeMessageId) {
|
|
12394
12411
|
const activeExists = db.prepare("SELECT 1 FROM ai_message WHERE id = ?").get(row.activeMessageId);
|
|
12395
12412
|
if (activeExists) return row.activeMessageId;
|
|
12396
12413
|
}
|
|
12397
|
-
const fallback = db.prepare("SELECT id FROM ai_message WHERE
|
|
12414
|
+
const fallback = db.prepare("SELECT id FROM ai_message WHERE ai_chat_id = ? ORDER BY timestamp DESC, id DESC LIMIT 1").get(aiChatId);
|
|
12398
12415
|
if (fallback?.id) {
|
|
12399
|
-
db.prepare("UPDATE
|
|
12416
|
+
db.prepare("UPDATE ai_chat SET active_message_id = ? WHERE id = ?").run(fallback.id, aiChatId);
|
|
12400
12417
|
return fallback.id;
|
|
12401
12418
|
}
|
|
12402
12419
|
return null;
|
|
12403
12420
|
}
|
|
12404
|
-
getAllMessageRows(
|
|
12421
|
+
getAllMessageRows(aiChatId) {
|
|
12405
12422
|
return this.getDb().prepare(
|
|
12406
|
-
`SELECT id,
|
|
12423
|
+
`SELECT id, ai_chat_id as aiChatId, role, content, timestamp,
|
|
12407
12424
|
parent_id as parentId, sibling_group_id as siblingGroupId, branch_index as branchIndex,
|
|
12408
12425
|
data_keywords as dataKeywords, data_message_count as dataMessageCount,
|
|
12409
12426
|
content_blocks as contentBlocks, token_usage as tokenUsage
|
|
12410
|
-
FROM ai_message WHERE
|
|
12411
|
-
).all(
|
|
12427
|
+
FROM ai_message WHERE ai_chat_id = ? ORDER BY timestamp ASC, id ASC`
|
|
12428
|
+
).all(aiChatId);
|
|
12412
12429
|
}
|
|
12413
|
-
getActivePathRows(
|
|
12430
|
+
getActivePathRows(aiChatId, leafMessageId) {
|
|
12414
12431
|
if (leafMessageId === null) return [];
|
|
12415
|
-
const allRows = this.getAllMessageRows(
|
|
12432
|
+
const allRows = this.getAllMessageRows(aiChatId);
|
|
12416
12433
|
if (allRows.length === 0) return [];
|
|
12417
12434
|
const rowMap = new Map(allRows.map((row) => [row.id, row]));
|
|
12418
|
-
let currentId = leafMessageId ?? this.getActiveMessageId(
|
|
12419
|
-
const
|
|
12435
|
+
let currentId = leafMessageId ?? this.getActiveMessageId(aiChatId);
|
|
12436
|
+
const path36 = [];
|
|
12420
12437
|
const seen = /* @__PURE__ */ new Set();
|
|
12421
12438
|
while (currentId && !seen.has(currentId)) {
|
|
12422
12439
|
seen.add(currentId);
|
|
12423
12440
|
const row = rowMap.get(currentId);
|
|
12424
12441
|
if (!row) break;
|
|
12425
|
-
|
|
12442
|
+
path36.push(row);
|
|
12426
12443
|
currentId = row.parentId;
|
|
12427
12444
|
}
|
|
12428
|
-
return
|
|
12445
|
+
return path36.length > 0 ? path36.reverse() : allRows;
|
|
12429
12446
|
}
|
|
12430
12447
|
// ==================== 生命周期 ====================
|
|
12431
12448
|
close() {
|
|
@@ -12481,21 +12498,21 @@ var AIConversationManager = class {
|
|
|
12481
12498
|
}
|
|
12482
12499
|
}
|
|
12483
12500
|
// ==================== 对话管理 ====================
|
|
12484
|
-
|
|
12501
|
+
createAIChat(sessionId, title, assistantId) {
|
|
12485
12502
|
const db = this.getDb();
|
|
12486
12503
|
const now = Math.floor(Date.now() / 1e3);
|
|
12487
12504
|
const id = this.generateId("conv");
|
|
12488
12505
|
db.prepare(
|
|
12489
|
-
`INSERT INTO
|
|
12506
|
+
`INSERT INTO ai_chat (id, session_id, title, assistant_id, created_at, updated_at)
|
|
12490
12507
|
VALUES (?, ?, ?, ?, ?, ?)`
|
|
12491
12508
|
).run(id, sessionId, title || null, assistantId, now, now);
|
|
12492
12509
|
return { id, sessionId, title: title || null, assistantId, activeMessageId: null, createdAt: now, updatedAt: now };
|
|
12493
12510
|
}
|
|
12494
|
-
|
|
12511
|
+
getAIChatCountsBySession() {
|
|
12495
12512
|
const result = /* @__PURE__ */ new Map();
|
|
12496
12513
|
try {
|
|
12497
12514
|
const db = this.getDb();
|
|
12498
|
-
const rows = db.prepare("SELECT session_id, COUNT(*) as count FROM
|
|
12515
|
+
const rows = db.prepare("SELECT session_id, COUNT(*) as count FROM ai_chat GROUP BY session_id").all();
|
|
12499
12516
|
for (const row of rows) {
|
|
12500
12517
|
result.set(row.session_id, row.count);
|
|
12501
12518
|
}
|
|
@@ -12503,58 +12520,58 @@ var AIConversationManager = class {
|
|
|
12503
12520
|
}
|
|
12504
12521
|
return result;
|
|
12505
12522
|
}
|
|
12506
|
-
|
|
12523
|
+
getAIChats(sessionId) {
|
|
12507
12524
|
const db = this.getDb();
|
|
12508
12525
|
return db.prepare(
|
|
12509
12526
|
`SELECT id, session_id as sessionId, title, assistant_id as assistantId,
|
|
12510
12527
|
active_message_id as activeMessageId,
|
|
12511
12528
|
created_at as createdAt, updated_at as updatedAt
|
|
12512
|
-
FROM
|
|
12529
|
+
FROM ai_chat WHERE session_id = ? ORDER BY updated_at DESC`
|
|
12513
12530
|
).all(sessionId);
|
|
12514
12531
|
}
|
|
12515
|
-
|
|
12532
|
+
getAIChat(aiChatId) {
|
|
12516
12533
|
const db = this.getDb();
|
|
12517
12534
|
const row = db.prepare(
|
|
12518
12535
|
`SELECT id, session_id as sessionId, title, assistant_id as assistantId,
|
|
12519
12536
|
active_message_id as activeMessageId,
|
|
12520
12537
|
created_at as createdAt, updated_at as updatedAt
|
|
12521
|
-
FROM
|
|
12522
|
-
).get(
|
|
12538
|
+
FROM ai_chat WHERE id = ?`
|
|
12539
|
+
).get(aiChatId);
|
|
12523
12540
|
return row || null;
|
|
12524
12541
|
}
|
|
12525
|
-
|
|
12542
|
+
updateAIChatTitle(aiChatId, title) {
|
|
12526
12543
|
const db = this.getDb();
|
|
12527
12544
|
const now = Math.floor(Date.now() / 1e3);
|
|
12528
|
-
const result = db.prepare("UPDATE
|
|
12545
|
+
const result = db.prepare("UPDATE ai_chat SET title = ?, updated_at = ? WHERE id = ?").run(title, now, aiChatId);
|
|
12529
12546
|
return result.changes > 0;
|
|
12530
12547
|
}
|
|
12531
|
-
|
|
12548
|
+
deleteAIChat(aiChatId) {
|
|
12532
12549
|
const db = this.getDb();
|
|
12533
|
-
db.prepare("DELETE FROM ai_message WHERE
|
|
12534
|
-
const result = db.prepare("DELETE FROM
|
|
12550
|
+
db.prepare("DELETE FROM ai_message WHERE ai_chat_id = ?").run(aiChatId);
|
|
12551
|
+
const result = db.prepare("DELETE FROM ai_chat WHERE id = ?").run(aiChatId);
|
|
12535
12552
|
return result.changes > 0;
|
|
12536
12553
|
}
|
|
12537
12554
|
// ==================== 消息管理 ====================
|
|
12538
|
-
addMessage(
|
|
12555
|
+
addMessage(aiChatId, role, content, dataKeywords, dataMessageCount, contentBlocks, tokenUsage) {
|
|
12539
12556
|
const db = this.getDb();
|
|
12540
12557
|
const now = Math.floor(Date.now() / 1e3);
|
|
12541
12558
|
const id = this.generateId("msg");
|
|
12542
|
-
const parentId = this.getActiveMessageId(
|
|
12559
|
+
const parentId = this.getActiveMessageId(aiChatId);
|
|
12543
12560
|
const siblingGroupId = id;
|
|
12544
12561
|
const branchIndex = 0;
|
|
12545
|
-
const pendingDebug = role === "assistant" ? this.pendingDebugContextMap.get(
|
|
12562
|
+
const pendingDebug = role === "assistant" ? this.pendingDebugContextMap.get(aiChatId) : void 0;
|
|
12546
12563
|
if (pendingDebug) {
|
|
12547
|
-
this.pendingDebugContextMap.delete(
|
|
12564
|
+
this.pendingDebugContextMap.delete(aiChatId);
|
|
12548
12565
|
}
|
|
12549
12566
|
db.prepare(
|
|
12550
12567
|
`INSERT INTO ai_message (
|
|
12551
|
-
id,
|
|
12568
|
+
id, ai_chat_id, role, content, timestamp, data_keywords, data_message_count,
|
|
12552
12569
|
content_blocks, token_usage, debug_context, parent_id, sibling_group_id, branch_index
|
|
12553
12570
|
)
|
|
12554
12571
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
12555
12572
|
).run(
|
|
12556
12573
|
id,
|
|
12557
|
-
|
|
12574
|
+
aiChatId,
|
|
12558
12575
|
role,
|
|
12559
12576
|
content,
|
|
12560
12577
|
now,
|
|
@@ -12567,14 +12584,14 @@ var AIConversationManager = class {
|
|
|
12567
12584
|
siblingGroupId,
|
|
12568
12585
|
branchIndex
|
|
12569
12586
|
);
|
|
12570
|
-
db.prepare("UPDATE
|
|
12587
|
+
db.prepare("UPDATE ai_chat SET active_message_id = ?, updated_at = ? WHERE id = ?").run(
|
|
12571
12588
|
id,
|
|
12572
12589
|
now,
|
|
12573
|
-
|
|
12590
|
+
aiChatId
|
|
12574
12591
|
);
|
|
12575
12592
|
return {
|
|
12576
12593
|
id,
|
|
12577
|
-
|
|
12594
|
+
aiChatId,
|
|
12578
12595
|
role,
|
|
12579
12596
|
content,
|
|
12580
12597
|
timestamp: now,
|
|
@@ -12585,21 +12602,21 @@ var AIConversationManager = class {
|
|
|
12585
12602
|
tokenUsage
|
|
12586
12603
|
};
|
|
12587
12604
|
}
|
|
12588
|
-
getMessages(
|
|
12589
|
-
return this.getActivePathRows(
|
|
12605
|
+
getMessages(aiChatId) {
|
|
12606
|
+
return this.getActivePathRows(aiChatId).map((row) => this.parseMessageRow(row));
|
|
12590
12607
|
}
|
|
12591
12608
|
deleteMessage(messageId) {
|
|
12592
12609
|
const db = this.getDb();
|
|
12593
12610
|
const result = db.prepare("DELETE FROM ai_message WHERE id = ?").run(messageId);
|
|
12594
12611
|
return result.changes > 0;
|
|
12595
12612
|
}
|
|
12596
|
-
deleteMessagesFrom(
|
|
12613
|
+
deleteMessagesFrom(aiChatId, messageId) {
|
|
12597
12614
|
const db = this.getDb();
|
|
12598
12615
|
const target = this.getMessageRow(messageId);
|
|
12599
|
-
if (!target || target.
|
|
12600
|
-
throw new Error("Message not found in
|
|
12616
|
+
if (!target || target.aiChatId !== aiChatId) {
|
|
12617
|
+
throw new Error("Message not found in AI chat");
|
|
12601
12618
|
}
|
|
12602
|
-
const activePath = this.getActivePathRows(
|
|
12619
|
+
const activePath = this.getActivePathRows(aiChatId);
|
|
12603
12620
|
const targetIndex = activePath.findIndex((row) => row.id === messageId);
|
|
12604
12621
|
if (targetIndex < 0) {
|
|
12605
12622
|
throw new Error("Message not on active path");
|
|
@@ -12609,19 +12626,19 @@ var AIConversationManager = class {
|
|
|
12609
12626
|
db.prepare(`DELETE FROM ai_message WHERE id IN (${placeholders})`).run(...idsToDelete);
|
|
12610
12627
|
const newLeafId = targetIndex > 0 ? activePath[targetIndex - 1].id : null;
|
|
12611
12628
|
const now = Math.floor(Date.now() / 1e3);
|
|
12612
|
-
db.prepare("UPDATE
|
|
12629
|
+
db.prepare("UPDATE ai_chat SET active_message_id = ?, updated_at = ? WHERE id = ?").run(
|
|
12613
12630
|
newLeafId,
|
|
12614
12631
|
now,
|
|
12615
|
-
|
|
12632
|
+
aiChatId
|
|
12616
12633
|
);
|
|
12617
12634
|
}
|
|
12618
|
-
|
|
12635
|
+
forkAIChat(sourceAIChatId, upToMessageId, title) {
|
|
12619
12636
|
const db = this.getDb();
|
|
12620
|
-
const source = this.
|
|
12637
|
+
const source = this.getAIChat(sourceAIChatId);
|
|
12621
12638
|
if (!source) {
|
|
12622
|
-
throw new Error("Source
|
|
12639
|
+
throw new Error("Source AI chat not found");
|
|
12623
12640
|
}
|
|
12624
|
-
const activePath = this.getActivePathRows(
|
|
12641
|
+
const activePath = this.getActivePathRows(sourceAIChatId);
|
|
12625
12642
|
const cutIndex = activePath.findIndex((row) => row.id === upToMessageId);
|
|
12626
12643
|
if (cutIndex < 0) {
|
|
12627
12644
|
throw new Error("Message not on active path");
|
|
@@ -12631,7 +12648,7 @@ var AIConversationManager = class {
|
|
|
12631
12648
|
const newConvId = this.generateId("conv");
|
|
12632
12649
|
const forkTitle = title || `${source.title || "Untitled"} (fork)`;
|
|
12633
12650
|
db.prepare(
|
|
12634
|
-
`INSERT INTO
|
|
12651
|
+
`INSERT INTO ai_chat (id, session_id, title, assistant_id, active_message_id, created_at, updated_at)
|
|
12635
12652
|
VALUES (?, ?, ?, ?, NULL, ?, ?)`
|
|
12636
12653
|
).run(newConvId, source.sessionId, forkTitle, source.assistantId, now, now);
|
|
12637
12654
|
const idMap = /* @__PURE__ */ new Map();
|
|
@@ -12642,7 +12659,7 @@ var AIConversationManager = class {
|
|
|
12642
12659
|
const newParentId = row.parentId ? idMap.get(row.parentId) ?? null : null;
|
|
12643
12660
|
db.prepare(
|
|
12644
12661
|
`INSERT INTO ai_message (
|
|
12645
|
-
id,
|
|
12662
|
+
id, ai_chat_id, role, content, timestamp, data_keywords, data_message_count,
|
|
12646
12663
|
content_blocks, token_usage, debug_context, parent_id, sibling_group_id, branch_index
|
|
12647
12664
|
)
|
|
12648
12665
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, 0)`
|
|
@@ -12662,7 +12679,7 @@ var AIConversationManager = class {
|
|
|
12662
12679
|
lastNewId = newMsgId;
|
|
12663
12680
|
}
|
|
12664
12681
|
if (lastNewId) {
|
|
12665
|
-
db.prepare("UPDATE
|
|
12682
|
+
db.prepare("UPDATE ai_chat SET active_message_id = ? WHERE id = ?").run(lastNewId, newConvId);
|
|
12666
12683
|
}
|
|
12667
12684
|
return {
|
|
12668
12685
|
id: newConvId,
|
|
@@ -12679,46 +12696,46 @@ var AIConversationManager = class {
|
|
|
12679
12696
|
const result = db.prepare("UPDATE ai_message SET content = ? WHERE id = ?").run(newContent, messageId);
|
|
12680
12697
|
if (result.changes === 0) throw new Error("Message not found");
|
|
12681
12698
|
}
|
|
12682
|
-
deleteAndRelinkMessage(
|
|
12699
|
+
deleteAndRelinkMessage(aiChatId, messageId) {
|
|
12683
12700
|
const db = this.getDb();
|
|
12684
12701
|
const target = this.getMessageRow(messageId);
|
|
12685
|
-
if (!target || target.
|
|
12686
|
-
throw new Error("Message not found in
|
|
12702
|
+
if (!target || target.aiChatId !== aiChatId) {
|
|
12703
|
+
throw new Error("Message not found in AI chat");
|
|
12687
12704
|
}
|
|
12688
|
-
db.prepare("UPDATE ai_message SET parent_id = ? WHERE parent_id = ? AND
|
|
12705
|
+
db.prepare("UPDATE ai_message SET parent_id = ? WHERE parent_id = ? AND ai_chat_id = ?").run(
|
|
12689
12706
|
target.parentId,
|
|
12690
12707
|
messageId,
|
|
12691
|
-
|
|
12708
|
+
aiChatId
|
|
12692
12709
|
);
|
|
12693
|
-
const conv = this.
|
|
12710
|
+
const conv = this.getAIChat(aiChatId);
|
|
12694
12711
|
if (conv?.activeMessageId === messageId) {
|
|
12695
12712
|
const now = Math.floor(Date.now() / 1e3);
|
|
12696
|
-
db.prepare("UPDATE
|
|
12713
|
+
db.prepare("UPDATE ai_chat SET active_message_id = ?, updated_at = ? WHERE id = ?").run(
|
|
12697
12714
|
target.parentId,
|
|
12698
12715
|
now,
|
|
12699
|
-
|
|
12716
|
+
aiChatId
|
|
12700
12717
|
);
|
|
12701
12718
|
}
|
|
12702
12719
|
db.prepare("DELETE FROM ai_message WHERE id = ?").run(messageId);
|
|
12703
12720
|
}
|
|
12704
|
-
insertMessageAfter(
|
|
12721
|
+
insertMessageAfter(aiChatId, afterMessageId, role, content, contentBlocks, tokenUsage) {
|
|
12705
12722
|
const db = this.getDb();
|
|
12706
12723
|
const now = Math.floor(Date.now() / 1e3);
|
|
12707
12724
|
const id = this.generateId("msg");
|
|
12708
|
-
const pendingDebug = role === "assistant" ? this.pendingDebugContextMap.get(
|
|
12725
|
+
const pendingDebug = role === "assistant" ? this.pendingDebugContextMap.get(aiChatId) : void 0;
|
|
12709
12726
|
if (pendingDebug) {
|
|
12710
|
-
this.pendingDebugContextMap.delete(
|
|
12727
|
+
this.pendingDebugContextMap.delete(aiChatId);
|
|
12711
12728
|
}
|
|
12712
|
-
const childRow = db.prepare("SELECT id FROM ai_message WHERE parent_id = ? AND
|
|
12729
|
+
const childRow = db.prepare("SELECT id FROM ai_message WHERE parent_id = ? AND ai_chat_id = ? LIMIT 1").get(afterMessageId, aiChatId);
|
|
12713
12730
|
db.prepare(
|
|
12714
12731
|
`INSERT INTO ai_message (
|
|
12715
|
-
id,
|
|
12732
|
+
id, ai_chat_id, role, content, timestamp, data_keywords, data_message_count,
|
|
12716
12733
|
content_blocks, token_usage, debug_context, parent_id, sibling_group_id, branch_index
|
|
12717
12734
|
)
|
|
12718
12735
|
VALUES (?, ?, ?, ?, ?, NULL, NULL, ?, ?, ?, ?, ?, 0)`
|
|
12719
12736
|
).run(
|
|
12720
12737
|
id,
|
|
12721
|
-
|
|
12738
|
+
aiChatId,
|
|
12722
12739
|
role,
|
|
12723
12740
|
content,
|
|
12724
12741
|
now,
|
|
@@ -12730,17 +12747,17 @@ var AIConversationManager = class {
|
|
|
12730
12747
|
);
|
|
12731
12748
|
if (childRow) {
|
|
12732
12749
|
db.prepare("UPDATE ai_message SET parent_id = ? WHERE id = ?").run(id, childRow.id);
|
|
12733
|
-
db.prepare("UPDATE
|
|
12750
|
+
db.prepare("UPDATE ai_chat SET updated_at = ? WHERE id = ?").run(now, aiChatId);
|
|
12734
12751
|
} else {
|
|
12735
|
-
db.prepare("UPDATE
|
|
12752
|
+
db.prepare("UPDATE ai_chat SET active_message_id = ?, updated_at = ? WHERE id = ?").run(
|
|
12736
12753
|
id,
|
|
12737
12754
|
now,
|
|
12738
|
-
|
|
12755
|
+
aiChatId
|
|
12739
12756
|
);
|
|
12740
12757
|
}
|
|
12741
12758
|
return {
|
|
12742
12759
|
id,
|
|
12743
|
-
|
|
12760
|
+
aiChatId,
|
|
12744
12761
|
role,
|
|
12745
12762
|
content,
|
|
12746
12763
|
timestamp: now,
|
|
@@ -12749,8 +12766,8 @@ var AIConversationManager = class {
|
|
|
12749
12766
|
tokenUsage
|
|
12750
12767
|
};
|
|
12751
12768
|
}
|
|
12752
|
-
|
|
12753
|
-
const rows = this.getActivePathRows(
|
|
12769
|
+
getAIChatTokenUsage(aiChatId) {
|
|
12770
|
+
const rows = this.getActivePathRows(aiChatId);
|
|
12754
12771
|
const result = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
|
|
12755
12772
|
for (const row of rows) {
|
|
12756
12773
|
if (row.tokenUsage) {
|
|
@@ -12763,8 +12780,8 @@ var AIConversationManager = class {
|
|
|
12763
12780
|
return result;
|
|
12764
12781
|
}
|
|
12765
12782
|
// ==================== Debug context ====================
|
|
12766
|
-
setPendingDebugContext(
|
|
12767
|
-
this.pendingDebugContextMap.set(
|
|
12783
|
+
setPendingDebugContext(aiChatId, debugContext) {
|
|
12784
|
+
this.pendingDebugContextMap.set(aiChatId, debugContext);
|
|
12768
12785
|
}
|
|
12769
12786
|
setDebugContext(messageId, debugContext) {
|
|
12770
12787
|
const db = this.getDb();
|
|
@@ -12776,8 +12793,8 @@ var AIConversationManager = class {
|
|
|
12776
12793
|
return result.changes;
|
|
12777
12794
|
}
|
|
12778
12795
|
// ==================== Agent 专用 ====================
|
|
12779
|
-
getHistoryForAgent(
|
|
12780
|
-
const messages = this.getActivePathRows(
|
|
12796
|
+
getHistoryForAgent(aiChatId, maxMessages, leafMessageId) {
|
|
12797
|
+
const messages = this.getActivePathRows(aiChatId, leafMessageId).map((row) => this.parseMessageRow(row));
|
|
12781
12798
|
const validMessages = messages.filter(
|
|
12782
12799
|
(m) => (m.role === "user" || m.role === "assistant" || m.role === "summary") && m.content?.trim()
|
|
12783
12800
|
);
|
|
@@ -12795,8 +12812,8 @@ var AIConversationManager = class {
|
|
|
12795
12812
|
);
|
|
12796
12813
|
const bufferBoundary = metaBlock?.bufferBoundaryTimestamp;
|
|
12797
12814
|
if (!metaBlock) {
|
|
12798
|
-
this.logger.warn("
|
|
12799
|
-
|
|
12815
|
+
this.logger.warn("AIChats", "summary message missing summary_meta; agent context will be summary-only", {
|
|
12816
|
+
aiChatId,
|
|
12800
12817
|
messageId: summaryMsg.id
|
|
12801
12818
|
});
|
|
12802
12819
|
}
|
|
@@ -12819,7 +12836,7 @@ var AIConversationManager = class {
|
|
|
12819
12836
|
return result;
|
|
12820
12837
|
}
|
|
12821
12838
|
// ==================== Summary / 压缩专用 ====================
|
|
12822
|
-
addSummaryMessage(
|
|
12839
|
+
addSummaryMessage(aiChatId, content, meta) {
|
|
12823
12840
|
const contentBlocks = [
|
|
12824
12841
|
{
|
|
12825
12842
|
type: "summary_meta",
|
|
@@ -12827,28 +12844,28 @@ var AIConversationManager = class {
|
|
|
12827
12844
|
compressedMessageCount: meta.compressedMessageCount
|
|
12828
12845
|
}
|
|
12829
12846
|
];
|
|
12830
|
-
return this.addMessage(
|
|
12847
|
+
return this.addMessage(aiChatId, "summary", content, void 0, void 0, contentBlocks);
|
|
12831
12848
|
}
|
|
12832
|
-
getLatestSummary(
|
|
12833
|
-
const row = [...this.getActivePathRows(
|
|
12849
|
+
getLatestSummary(aiChatId) {
|
|
12850
|
+
const row = [...this.getActivePathRows(aiChatId)].reverse().find((message) => message.role === "summary");
|
|
12834
12851
|
return row ? this.parseMessageRow(row) : null;
|
|
12835
12852
|
}
|
|
12836
|
-
getMessagesAfterSummary(
|
|
12837
|
-
return this.getActivePathRows(
|
|
12853
|
+
getMessagesAfterSummary(aiChatId, summaryTimestamp) {
|
|
12854
|
+
return this.getActivePathRows(aiChatId).filter((row) => row.timestamp > summaryTimestamp && (row.role === "user" || row.role === "assistant")).map((row) => ({ role: row.role, content: row.content, timestamp: row.timestamp }));
|
|
12838
12855
|
}
|
|
12839
|
-
getAllUserAssistantMessages(
|
|
12840
|
-
return this.getActivePathRows(
|
|
12856
|
+
getAllUserAssistantMessages(aiChatId) {
|
|
12857
|
+
return this.getActivePathRows(aiChatId).filter((row) => row.role === "user" || row.role === "assistant").map((row) => ({ role: row.role, content: row.content, timestamp: row.timestamp }));
|
|
12841
12858
|
}
|
|
12842
|
-
getMessageCountAfterSummary(
|
|
12843
|
-
const summary = this.getLatestSummary(
|
|
12859
|
+
getMessageCountAfterSummary(aiChatId) {
|
|
12860
|
+
const summary = this.getLatestSummary(aiChatId);
|
|
12844
12861
|
if (!summary) {
|
|
12845
|
-
return this.getActivePathRows(
|
|
12862
|
+
return this.getActivePathRows(aiChatId).filter((row) => row.role === "user" || row.role === "assistant").length;
|
|
12846
12863
|
}
|
|
12847
12864
|
const metaBlock = summary.contentBlocks?.find(
|
|
12848
12865
|
(b) => b.type === "summary_meta"
|
|
12849
12866
|
);
|
|
12850
12867
|
const boundary = metaBlock?.bufferBoundaryTimestamp ?? summary.timestamp;
|
|
12851
|
-
return this.getActivePathRows(
|
|
12868
|
+
return this.getActivePathRows(aiChatId).filter(
|
|
12852
12869
|
(row) => row.timestamp >= boundary && (row.role === "user" || row.role === "assistant")
|
|
12853
12870
|
).length;
|
|
12854
12871
|
}
|
|
@@ -13316,7 +13333,7 @@ function parseAssistantFile(content, filePath) {
|
|
|
13316
13333
|
name,
|
|
13317
13334
|
systemPrompt: body.trim(),
|
|
13318
13335
|
presetQuestions: parseStringArray(fm.presetQuestions),
|
|
13319
|
-
allowedBuiltinTools: parseStringArray(fm.allowedBuiltinTools),
|
|
13336
|
+
allowedBuiltinTools: normalizeBuiltinToolNames(parseStringArray(fm.allowedBuiltinTools)),
|
|
13320
13337
|
builtinId: typeof fm.builtinId === "string" ? fm.builtinId : void 0,
|
|
13321
13338
|
applicableChatTypes: parseChatTypes(fm.applicableChatTypes),
|
|
13322
13339
|
supportedLocales: parseStringArray(fm.supportedLocales)
|
|
@@ -13333,7 +13350,7 @@ function serializeAssistant(config) {
|
|
|
13333
13350
|
if (config.builtinId) fm.builtinId = config.builtinId;
|
|
13334
13351
|
if (config.applicableChatTypes?.length) fm.applicableChatTypes = config.applicableChatTypes;
|
|
13335
13352
|
if (config.supportedLocales?.length) fm.supportedLocales = config.supportedLocales;
|
|
13336
|
-
if (config.allowedBuiltinTools?.length) fm.allowedBuiltinTools = config.allowedBuiltinTools;
|
|
13353
|
+
if (config.allowedBuiltinTools?.length) fm.allowedBuiltinTools = normalizeBuiltinToolNames(config.allowedBuiltinTools);
|
|
13337
13354
|
if (config.presetQuestions?.length) fm.presetQuestions = config.presetQuestions;
|
|
13338
13355
|
return matter.stringify(`
|
|
13339
13356
|
${config.systemPrompt}
|
|
@@ -13387,8 +13404,8 @@ var AssistantManager = class {
|
|
|
13387
13404
|
}
|
|
13388
13405
|
// ==================== Init ====================
|
|
13389
13406
|
init() {
|
|
13390
|
-
const { fs:
|
|
13391
|
-
|
|
13407
|
+
const { fs: fs40, assistantsDir } = this.deps;
|
|
13408
|
+
fs40.ensureDir(assistantsDir);
|
|
13392
13409
|
const generalCreated = this.ensureGeneralAssistants();
|
|
13393
13410
|
this.loadAll();
|
|
13394
13411
|
this.initialized = true;
|
|
@@ -13399,26 +13416,26 @@ var AssistantManager = class {
|
|
|
13399
13416
|
return { total: this.cache.size, generalCreated };
|
|
13400
13417
|
}
|
|
13401
13418
|
ensureGeneralAssistants() {
|
|
13402
|
-
const { fs:
|
|
13419
|
+
const { fs: fs40, assistantsDir } = this.deps;
|
|
13403
13420
|
let anyCreated = false;
|
|
13404
13421
|
for (const id of this.generalIds) {
|
|
13405
13422
|
const config = this.getBuiltinConfig(id);
|
|
13406
13423
|
if (!config) continue;
|
|
13407
|
-
const filePath =
|
|
13408
|
-
if (
|
|
13409
|
-
|
|
13424
|
+
const filePath = fs40.joinPath(assistantsDir, `${id}.md`);
|
|
13425
|
+
if (fs40.fileExists(filePath)) continue;
|
|
13426
|
+
fs40.writeFile(filePath, serializeAssistant({ ...config, builtinId: config.id }));
|
|
13410
13427
|
anyCreated = true;
|
|
13411
13428
|
}
|
|
13412
13429
|
return anyCreated;
|
|
13413
13430
|
}
|
|
13414
13431
|
loadAll() {
|
|
13415
|
-
const { fs:
|
|
13432
|
+
const { fs: fs40, assistantsDir } = this.deps;
|
|
13416
13433
|
this.cache.clear();
|
|
13417
|
-
const files =
|
|
13434
|
+
const files = fs40.listFiles(assistantsDir, ".md");
|
|
13418
13435
|
for (const file of files) {
|
|
13419
13436
|
try {
|
|
13420
|
-
const filePath =
|
|
13421
|
-
const content =
|
|
13437
|
+
const filePath = fs40.joinPath(assistantsDir, file);
|
|
13438
|
+
const content = fs40.readFile(filePath);
|
|
13422
13439
|
const config = parseAssistantFile(content, filePath);
|
|
13423
13440
|
if (config) {
|
|
13424
13441
|
this.cache.set(config.id, config);
|
|
@@ -13704,21 +13721,21 @@ var SkillManagerCore = class {
|
|
|
13704
13721
|
}
|
|
13705
13722
|
// ==================== Init ====================
|
|
13706
13723
|
init() {
|
|
13707
|
-
const { fs:
|
|
13708
|
-
|
|
13724
|
+
const { fs: fs40, skillsDir } = this.deps;
|
|
13725
|
+
fs40.ensureDir(skillsDir);
|
|
13709
13726
|
this.loadAll();
|
|
13710
13727
|
this.initialized = true;
|
|
13711
13728
|
this.deps.logger?.info("SkillManager", "Initialized", { total: this.cache.size });
|
|
13712
13729
|
return { total: this.cache.size };
|
|
13713
13730
|
}
|
|
13714
13731
|
loadAll() {
|
|
13715
|
-
const { fs:
|
|
13732
|
+
const { fs: fs40, skillsDir } = this.deps;
|
|
13716
13733
|
this.cache.clear();
|
|
13717
|
-
const files =
|
|
13734
|
+
const files = fs40.listFiles(skillsDir, ".md");
|
|
13718
13735
|
for (const file of files) {
|
|
13719
13736
|
try {
|
|
13720
|
-
const filePath =
|
|
13721
|
-
const content =
|
|
13737
|
+
const filePath = fs40.joinPath(skillsDir, file);
|
|
13738
|
+
const content = fs40.readFile(filePath);
|
|
13722
13739
|
const def = parseSkillFile(content, filePath);
|
|
13723
13740
|
if (def) {
|
|
13724
13741
|
this.cache.set(def.id, def);
|
|
@@ -14209,23 +14226,23 @@ var defaultLogger3 = {
|
|
|
14209
14226
|
error: () => {
|
|
14210
14227
|
}
|
|
14211
14228
|
};
|
|
14212
|
-
async function checkAndCompress(
|
|
14229
|
+
async function checkAndCompress(aiChatId, config, systemPrompt, llmAdapter, convManager, logger = defaultLogger3) {
|
|
14213
14230
|
if (!config.enabled) {
|
|
14214
14231
|
return { compressed: false, reason: "skipped_disabled" };
|
|
14215
14232
|
}
|
|
14216
14233
|
try {
|
|
14217
14234
|
const contextWindow = llmAdapter.contextWindow || DEFAULT_CONTEXT_WINDOW;
|
|
14218
14235
|
const thresholdTokens = Math.floor(contextWindow * (config.tokenThresholdPercent / 100) * 0.95);
|
|
14219
|
-
const summary = convManager.getLatestSummary(
|
|
14236
|
+
const summary = convManager.getLatestSummary(aiChatId);
|
|
14220
14237
|
let messages;
|
|
14221
14238
|
if (summary) {
|
|
14222
14239
|
const metaBlock = summary.contentBlocks?.find(
|
|
14223
14240
|
(b) => b.type === "summary_meta"
|
|
14224
14241
|
);
|
|
14225
14242
|
const boundary = metaBlock?.bufferBoundaryTimestamp ?? summary.timestamp;
|
|
14226
|
-
messages = convManager.getMessagesAfterSummary(
|
|
14243
|
+
messages = convManager.getMessagesAfterSummary(aiChatId, boundary - 1);
|
|
14227
14244
|
} else {
|
|
14228
|
-
messages = convManager.getAllUserAssistantMessages(
|
|
14245
|
+
messages = convManager.getAllUserAssistantMessages(aiChatId);
|
|
14229
14246
|
}
|
|
14230
14247
|
const historyForTokenCount = [];
|
|
14231
14248
|
if (summary) {
|
|
@@ -14236,7 +14253,7 @@ async function checkAndCompress(conversationId, config, systemPrompt, llmAdapter
|
|
|
14236
14253
|
}
|
|
14237
14254
|
const currentTokens = countMessagesTokens(historyForTokenCount, systemPrompt);
|
|
14238
14255
|
logger.info("Compression", `Token check: ${currentTokens} / ${thresholdTokens} (${contextWindow} window)`, {
|
|
14239
|
-
|
|
14256
|
+
aiChatId,
|
|
14240
14257
|
messageCount: messages.length,
|
|
14241
14258
|
hasSummary: !!summary
|
|
14242
14259
|
});
|
|
@@ -14260,7 +14277,7 @@ async function checkAndCompress(conversationId, config, systemPrompt, llmAdapter
|
|
|
14260
14277
|
summaryText = forceTruncate(compressInput, targetTokens);
|
|
14261
14278
|
}
|
|
14262
14279
|
const bufferBoundary = bufferMessages.length > 0 ? bufferMessages[0].timestamp : messagesToCompress[messagesToCompress.length - 1].timestamp + 1;
|
|
14263
|
-
convManager.addSummaryMessage(
|
|
14280
|
+
convManager.addSummaryMessage(aiChatId, summaryText, {
|
|
14264
14281
|
bufferBoundaryTimestamp: bufferBoundary,
|
|
14265
14282
|
compressedMessageCount: messagesToCompress.length
|
|
14266
14283
|
});
|
|
@@ -15481,40 +15498,40 @@ var zh_CN_default = {
|
|
|
15481
15498
|
context_size: "\u4E0A\u4E0B\u6587\u5927\u5C0F\uFF0C\u5373\u83B7\u53D6\u524D\u540E\u5404\u591A\u5C11\u6761\u6D88\u606F\uFF0C\u9ED8\u8BA4 20"
|
|
15482
15499
|
}
|
|
15483
15500
|
},
|
|
15484
|
-
|
|
15485
|
-
desc: "\u641C\u7D22\u804A\u5929\
|
|
15501
|
+
search_segments: {
|
|
15502
|
+
desc: "\u641C\u7D22\u804A\u5929\u6BB5\u843D\uFF08\u5BF9\u8BDD\u6BB5\u843D\uFF09\u3002\u6BB5\u843D\u662F\u6839\u636E\u6D88\u606F\u65F6\u95F4\u95F4\u9694\u81EA\u52A8\u5207\u5206\u7684\u5BF9\u8BDD\u5355\u5143\u3002\u9002\u7528\u4E8E\u67E5\u627E\u7279\u5B9A\u8BDD\u9898\u7684\u8BA8\u8BBA\u3001\u4E86\u89E3\u67D0\u4E2A\u65F6\u95F4\u6BB5\u5185\u53D1\u751F\u4E86\u51E0\u6B21\u5BF9\u8BDD\u7B49\u573A\u666F\u3002\u8FD4\u56DE\u5339\u914D\u7684\u6BB5\u843D\u5217\u8868\u53CA\u6BCF\u4E2A\u6BB5\u843D\u7684\u524D5\u6761\u6D88\u606F\u9884\u89C8\u3002",
|
|
15486
15503
|
params: {
|
|
15487
|
-
keywords: "\u53EF\u9009\u7684\u641C\u7D22\u5173\u952E\u8BCD\u5217\u8868\uFF0C\u53EA\u8FD4\u56DE\u5305\u542B\u8FD9\u4E9B\u5173\u952E\u8BCD\u7684\
|
|
15488
|
-
limit: "\u8FD4\u56DE\
|
|
15489
|
-
year: "\u6307\u5B9A\u5E74\u4EFD\u7B5B\u9009\
|
|
15490
|
-
month: "\u6307\u5B9A\u6708\u4EFD\u7B5B\u9009\
|
|
15491
|
-
day: "\u6307\u5B9A\u65E5\u671F\u7B5B\u9009\
|
|
15504
|
+
keywords: "\u53EF\u9009\u7684\u641C\u7D22\u5173\u952E\u8BCD\u5217\u8868\uFF0C\u53EA\u8FD4\u56DE\u5305\u542B\u8FD9\u4E9B\u5173\u952E\u8BCD\u7684\u6BB5\u843D\uFF08OR \u903B\u8F91\u5339\u914D\uFF09",
|
|
15505
|
+
limit: "\u8FD4\u56DE\u6BB5\u843D\u6570\u91CF\u9650\u5236\uFF0C\u9ED8\u8BA4 20",
|
|
15506
|
+
year: "\u6307\u5B9A\u5E74\u4EFD\u7B5B\u9009\u6BB5\u843D\uFF0C\u5982 2024",
|
|
15507
|
+
month: "\u6307\u5B9A\u6708\u4EFD\u7B5B\u9009\u6BB5\u843D\uFF081-12\uFF09\uFF0C\u9700\u914D\u5408 year \u4F7F\u7528",
|
|
15508
|
+
day: "\u6307\u5B9A\u65E5\u671F\u7B5B\u9009\u6BB5\u843D\uFF081-31\uFF09\uFF0C\u9700\u914D\u5408 year \u548C month \u4F7F\u7528",
|
|
15492
15509
|
start_time: '\u5F00\u59CB\u65F6\u95F4\uFF0C\u683C\u5F0F "YYYY-MM-DD HH:mm"\uFF0C\u5982 "2024-03-15 14:00"',
|
|
15493
15510
|
end_time: '\u7ED3\u675F\u65F6\u95F4\uFF0C\u683C\u5F0F "YYYY-MM-DD HH:mm"\uFF0C\u5982 "2024-03-15 18:30"'
|
|
15494
15511
|
}
|
|
15495
15512
|
},
|
|
15496
|
-
|
|
15497
|
-
desc: "\u83B7\u53D6\u6307\u5B9A\
|
|
15513
|
+
get_segment_messages: {
|
|
15514
|
+
desc: "\u83B7\u53D6\u6307\u5B9A\u6BB5\u843D\u7684\u5B8C\u6574\u6D88\u606F\u5217\u8868\u3002\u7528\u4E8E\u5728 search_segments \u627E\u5230\u76F8\u5173\u6BB5\u843D\u540E\uFF0C\u83B7\u53D6\u8BE5\u6BB5\u843D\u7684\u5B8C\u6574\u4E0A\u4E0B\u6587\u3002\u8FD4\u56DE\u6BB5\u843D\u7684\u6240\u6709\u6D88\u606F\u53CA\u53C2\u4E0E\u8005\u4FE1\u606F\u3002",
|
|
15498
15515
|
params: {
|
|
15499
|
-
|
|
15500
|
-
limit: "\u8FD4\u56DE\u6D88\u606F\u6570\u91CF\u9650\u5236\uFF0C\u9ED8\u8BA4 1000\u3002\u5BF9\u4E8E\u8D85\u957F\
|
|
15516
|
+
segment_id: "\u6BB5\u843D ID\uFF0C\u53EF\u4EE5\u4ECE search_segments \u7684\u8FD4\u56DE\u7ED3\u679C\u4E2D\u83B7\u53D6",
|
|
15517
|
+
limit: "\u8FD4\u56DE\u6D88\u606F\u6570\u91CF\u9650\u5236\uFF0C\u9ED8\u8BA4 1000\u3002\u5BF9\u4E8E\u8D85\u957F\u6BB5\u843D\u53EF\u4EE5\u9650\u5236\u8FD4\u56DE\u6570\u91CF\u4EE5\u8282\u7701 token"
|
|
15501
15518
|
}
|
|
15502
15519
|
},
|
|
15503
|
-
|
|
15504
|
-
desc: `\u83B7\u53D6\
|
|
15520
|
+
get_segment_summaries: {
|
|
15521
|
+
desc: `\u83B7\u53D6\u6BB5\u843D\u6458\u8981\u5217\u8868\uFF0C\u5FEB\u901F\u4E86\u89E3\u7FA4\u804A\u5386\u53F2\u8BA8\u8BBA\u7684\u4E3B\u9898\u3002
|
|
15505
15522
|
|
|
15506
15523
|
\u9002\u7528\u573A\u666F\uFF1A
|
|
15507
15524
|
1. \u4E86\u89E3\u7FA4\u91CC\u6700\u8FD1\u5728\u804A\u4EC0\u4E48\u8BDD\u9898
|
|
15508
15525
|
2. \u6309\u5173\u952E\u8BCD\u641C\u7D22\u8BA8\u8BBA\u8FC7\u7684\u8BDD\u9898
|
|
15509
15526
|
3. \u6982\u89C8\u6027\u95EE\u9898\u5982"\u7FA4\u91CC\u6709\u6CA1\u6709\u8BA8\u8BBA\u8FC7\u65C5\u6E38"
|
|
15510
15527
|
|
|
15511
|
-
\u8FD4\u56DE\u7684\u6458\u8981\u662F\u5BF9\u6BCF\u4E2A\
|
|
15528
|
+
\u8FD4\u56DE\u7684\u6458\u8981\u662F\u5BF9\u6BCF\u4E2A\u6BB5\u843D\u7684\u7B80\u77ED\u603B\u7ED3\uFF0C\u53EF\u4EE5\u5E2E\u52A9\u5FEB\u901F\u5B9A\u4F4D\u611F\u5174\u8DA3\u7684\u6BB5\u843D\uFF0C\u7136\u540E\u7528 get_segment_messages \u83B7\u53D6\u8BE6\u60C5\u3002`,
|
|
15512
15529
|
params: {
|
|
15513
15530
|
keywords: "\u5728\u6458\u8981\u4E2D\u641C\u7D22\u7684\u5173\u952E\u8BCD\u5217\u8868\uFF08OR \u903B\u8F91\u5339\u914D\uFF09",
|
|
15514
|
-
limit: "\u8FD4\u56DE\
|
|
15515
|
-
year: "\u6307\u5B9A\u5E74\u4EFD\u7B5B\u9009\
|
|
15516
|
-
month: "\u6307\u5B9A\u6708\u4EFD\u7B5B\u9009\
|
|
15517
|
-
day: "\u6307\u5B9A\u65E5\u671F\u7B5B\u9009\
|
|
15531
|
+
limit: "\u8FD4\u56DE\u6BB5\u843D\u6570\u91CF\u9650\u5236\uFF0C\u9ED8\u8BA4 20",
|
|
15532
|
+
year: "\u6307\u5B9A\u5E74\u4EFD\u7B5B\u9009\u6BB5\u843D",
|
|
15533
|
+
month: "\u6307\u5B9A\u6708\u4EFD\u7B5B\u9009\u6BB5\u843D\uFF081-12\uFF09",
|
|
15534
|
+
day: "\u6307\u5B9A\u65E5\u671F\u7B5B\u9009\u6BB5\u843D\uFF081-31\uFF09",
|
|
15518
15535
|
start_time: '\u5F00\u59CB\u65F6\u95F4\uFF0C\u683C\u5F0F "YYYY-MM-DD HH:mm"',
|
|
15519
15536
|
end_time: '\u7ED3\u675F\u65F6\u95F4\uFF0C\u683C\u5F0F "YYYY-MM-DD HH:mm"'
|
|
15520
15537
|
}
|
|
@@ -15601,14 +15618,14 @@ var zh_CN_default = {
|
|
|
15601
15618
|
fallback: "\u8BE5\u65F6\u95F4\u8303\u56F4\u5185\u6CA1\u6709\u6D88\u606F\u8BB0\u5F55"
|
|
15602
15619
|
},
|
|
15603
15620
|
conversation_initiator_stats: {
|
|
15604
|
-
desc: "\u7EDF\u8BA1\u6BCF\u4E2A\u6210\u5458\u53D1\u8D77\
|
|
15621
|
+
desc: "\u7EDF\u8BA1\u6BCF\u4E2A\u6210\u5458\u53D1\u8D77\u6BB5\u843D\uFF08\u4F5C\u4E3A\u6BB5\u843D\u9996\u6761\u6D88\u606F\u7684\u53D1\u9001\u8005\uFF09\u7684\u6B21\u6570\uFF0C\u627E\u51FA\u8C01\u6700\u5E38\u5F00\u542F\u8BDD\u9898\u3002\u9700\u8981\u5DF2\u751F\u6210\u6BB5\u843D\u7D22\u5F15\u3002",
|
|
15605
15622
|
params: {
|
|
15606
15623
|
days: "\u7EDF\u8BA1\u6700\u8FD1\u591A\u5C11\u5929\u7684\u6570\u636E",
|
|
15607
15624
|
limit: "\u8FD4\u56DE\u524D\u591A\u5C11\u540D"
|
|
15608
15625
|
},
|
|
15609
15626
|
rowTemplate: "{name}\uFF1A\u53D1\u8D77 {initiated_count} \u6B21\u8BDD\u9898",
|
|
15610
15627
|
summaryTemplate: "\u8BDD\u9898\u53D1\u8D77\u8005 Top {rowCount}\uFF1A",
|
|
15611
|
-
fallback: "\u8BE5\u65F6\u95F4\u8303\u56F4\u5185\u6CA1\u6709\
|
|
15628
|
+
fallback: "\u8BE5\u65F6\u95F4\u8303\u56F4\u5185\u6CA1\u6709\u6BB5\u843D\u8BB0\u5F55\uFF0C\u53EF\u80FD\u9700\u8981\u5148\u751F\u6210\u6BB5\u843D\u7D22\u5F15"
|
|
15612
15629
|
},
|
|
15613
15630
|
activity_heatmap: {
|
|
15614
15631
|
desc: "\u8FD4\u56DE \u661F\u671F\xD7\u5C0F\u65F6 \u7684\u6D88\u606F\u6570\u77E9\u9635\uFF0C\u9002\u5408\u751F\u6210\u6D3B\u8DC3\u5EA6\u70ED\u529B\u56FE\u3002weekday: 0=\u5468\u65E5, 1=\u5468\u4E00, ..., 6=\u5468\u516D\u3002",
|
|
@@ -15712,10 +15729,10 @@ var zh_CN_default = {
|
|
|
15712
15729
|
rawErrorLabel: "\u539F\u59CB\u9519\u8BEF"
|
|
15713
15730
|
},
|
|
15714
15731
|
summary: {
|
|
15715
|
-
|
|
15732
|
+
segmentNotFound: "\u6BB5\u843D\u4E0D\u5B58\u5728\u6216\u6570\u636E\u5E93\u6253\u5F00\u5931\u8D25",
|
|
15716
15733
|
tooFewMessages: "\u6D88\u606F\u6570\u91CF\u5C11\u4E8E{{count}}\u6761\uFF0C\u65E0\u9700\u751F\u6210\u6458\u8981",
|
|
15717
15734
|
tooFewValidMessages: "\u6709\u6548\u6D88\u606F\u6570\u91CF\u5C11\u4E8E{{count}}\u6761\uFF0C\u65E0\u9700\u751F\u6210\u6458\u8981",
|
|
15718
|
-
|
|
15735
|
+
segmentNotExist: "\u6BB5\u843D\u4E0D\u5B58\u5728",
|
|
15719
15736
|
messagesTooFew: "\u6D88\u606F\u592A\u5C11",
|
|
15720
15737
|
validMessagesTooFew: "\u6709\u6548\u6D88\u606F\u592A\u5C11",
|
|
15721
15738
|
systemPromptDirect: "\u4F60\u662F\u4E00\u4E2A\u5BF9\u8BDD\u6458\u8981\u4E13\u5BB6\uFF0C\u64C5\u957F\u7528\u7B80\u6D01\u7684\u8BED\u8A00\u603B\u7ED3\u5BF9\u8BDD\u5185\u5BB9\u3002",
|
|
@@ -15815,40 +15832,40 @@ var en_US_default = {
|
|
|
15815
15832
|
context_size: "Context size, i.e. how many messages before and after to retrieve, default 20"
|
|
15816
15833
|
}
|
|
15817
15834
|
},
|
|
15818
|
-
|
|
15819
|
-
desc: "Search chat
|
|
15835
|
+
search_segments: {
|
|
15836
|
+
desc: "Search chat segments (conversation segments). Segments are conversation units automatically split by message time intervals. Suitable for finding discussions on specific topics or understanding how many conversations occurred in a time period. Returns matching segments with a 5-message preview each.",
|
|
15820
15837
|
params: {
|
|
15821
|
-
keywords: "Optional keyword list, only returns
|
|
15838
|
+
keywords: "Optional keyword list, only returns segments containing these keywords (OR logic)",
|
|
15822
15839
|
limit: "Session count limit, default 20",
|
|
15823
|
-
year: "Filter
|
|
15824
|
-
month: "Filter
|
|
15825
|
-
day: "Filter
|
|
15840
|
+
year: "Filter segments by year, e.g. 2024",
|
|
15841
|
+
month: "Filter segments by month (1-12), use with year",
|
|
15842
|
+
day: "Filter segments by day (1-31), use with year and month",
|
|
15826
15843
|
start_time: 'Start time, format "YYYY-MM-DD HH:mm", e.g. "2024-03-15 14:00"',
|
|
15827
15844
|
end_time: 'End time, format "YYYY-MM-DD HH:mm", e.g. "2024-03-15 18:30"'
|
|
15828
15845
|
}
|
|
15829
15846
|
},
|
|
15830
|
-
|
|
15831
|
-
desc: "Get the complete message list for a specific
|
|
15847
|
+
get_segment_messages: {
|
|
15848
|
+
desc: "Get the complete message list for a specific segment. Used to get full context after finding a relevant segment via search_segments. Returns all messages and participant information.",
|
|
15832
15849
|
params: {
|
|
15833
|
-
|
|
15834
|
-
limit: "Message count limit, default 1000. Can be limited for very long
|
|
15850
|
+
segment_id: "Segment ID, can be obtained from search_segments results",
|
|
15851
|
+
limit: "Message count limit, default 1000. Can be limited for very long segments to save tokens"
|
|
15835
15852
|
}
|
|
15836
15853
|
},
|
|
15837
|
-
|
|
15838
|
-
desc: `Get
|
|
15854
|
+
get_segment_summaries: {
|
|
15855
|
+
desc: `Get segment summary list to quickly understand discussion topics in chat history.
|
|
15839
15856
|
|
|
15840
15857
|
Use cases:
|
|
15841
15858
|
1. Understand what topics have been discussed recently
|
|
15842
15859
|
2. Search for discussed topics by keyword
|
|
15843
15860
|
3. Overview questions like "has the group discussed travel"
|
|
15844
15861
|
|
|
15845
|
-
Returned summaries are brief descriptions of each
|
|
15862
|
+
Returned summaries are brief descriptions of each segment, helping quickly locate segments of interest. Use get_segment_messages for details.`,
|
|
15846
15863
|
params: {
|
|
15847
15864
|
keywords: "Keyword list to search within summaries (OR logic)",
|
|
15848
15865
|
limit: "Session count limit, default 20",
|
|
15849
|
-
year: "Filter
|
|
15850
|
-
month: "Filter
|
|
15851
|
-
day: "Filter
|
|
15866
|
+
year: "Filter segments by year",
|
|
15867
|
+
month: "Filter segments by month (1-12)",
|
|
15868
|
+
day: "Filter segments by day (1-31)",
|
|
15852
15869
|
start_time: 'Start time, format "YYYY-MM-DD HH:mm"',
|
|
15853
15870
|
end_time: 'End time, format "YYYY-MM-DD HH:mm"'
|
|
15854
15871
|
}
|
|
@@ -15936,14 +15953,14 @@ Returned summaries are brief descriptions of each session, helping quickly locat
|
|
|
15936
15953
|
fallback: "No messages in this time range"
|
|
15937
15954
|
},
|
|
15938
15955
|
conversation_initiator_stats: {
|
|
15939
|
-
desc: "Count how many times each member initiated a conversation (was the first sender in a
|
|
15956
|
+
desc: "Count how many times each member initiated a conversation (was the first sender in a segment). Requires segment index to be generated.",
|
|
15940
15957
|
params: {
|
|
15941
15958
|
days: "Number of recent days to analyze",
|
|
15942
15959
|
limit: "Number of top members to return"
|
|
15943
15960
|
},
|
|
15944
15961
|
rowTemplate: "{name}: initiated {initiated_count} topics",
|
|
15945
15962
|
summaryTemplate: "Topic initiator Top {rowCount}:",
|
|
15946
|
-
fallback: "No
|
|
15963
|
+
fallback: "No segment records in this time range. Session index may need to be generated first."
|
|
15947
15964
|
},
|
|
15948
15965
|
activity_heatmap: {
|
|
15949
15966
|
desc: "Return a weekday \xD7 hour message count matrix for generating activity heatmaps. weekday: 0=Sun, 1=Mon, ..., 6=Sat.",
|
|
@@ -16044,10 +16061,10 @@ Your task is to help users understand and analyze their private chat data.
|
|
|
16044
16061
|
rawErrorLabel: "Raw error"
|
|
16045
16062
|
},
|
|
16046
16063
|
summary: {
|
|
16047
|
-
|
|
16064
|
+
segmentNotFound: "Session not found or database could not be opened",
|
|
16048
16065
|
tooFewMessages: "Message count less than {{count}}, no need to generate summary",
|
|
16049
16066
|
tooFewValidMessages: "Valid message count less than {{count}}, no need to generate summary",
|
|
16050
|
-
|
|
16067
|
+
segmentNotExist: "Session not found",
|
|
16051
16068
|
messagesTooFew: "Too few messages",
|
|
16052
16069
|
validMessagesTooFew: "Too few valid messages",
|
|
16053
16070
|
systemPromptDirect: "You are a conversation summarization expert. Summarize conversations concisely.",
|
|
@@ -16147,40 +16164,40 @@ var ja_JP_default = {
|
|
|
16147
16164
|
context_size: "\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u30B5\u30A4\u30BA\u3002\u524D\u5F8C\u305D\u308C\u305E\u308C\u4F55\u4EF6\u306E\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u53D6\u5F97\u3059\u308B\u304B\u3002\u30C7\u30D5\u30A9\u30EB\u30C8 20"
|
|
16148
16165
|
}
|
|
16149
16166
|
},
|
|
16150
|
-
|
|
16151
|
-
desc: "\u30C1\u30E3\u30C3\u30C8\u30BB\
|
|
16167
|
+
search_segments: {
|
|
16168
|
+
desc: "\u30C1\u30E3\u30C3\u30C8\u30BB\u30B0\u30E1\u30F3\u30C8\uFF08\u4F1A\u8A71\u30BB\u30B0\u30E1\u30F3\u30C8\uFF09\u3092\u691C\u7D22\u3059\u308B\u3002\u30BB\u30B0\u30E1\u30F3\u30C8\u306F\u30E1\u30C3\u30BB\u30FC\u30B8\u306E\u6642\u9593\u9593\u9694\u306B\u57FA\u3065\u3044\u3066\u81EA\u52D5\u5206\u5272\u3055\u308C\u305F\u4F1A\u8A71\u5358\u4F4D\u3067\u3042\u308B\u3002\u7279\u5B9A\u30C8\u30D4\u30C3\u30AF\u306E\u8B70\u8AD6\u3092\u898B\u3064\u3051\u305F\u308A\u3001\u3042\u308B\u671F\u9593\u5185\u306E\u4F1A\u8A71\u56DE\u6570\u3092\u628A\u63E1\u3059\u308B\u306E\u306B\u9069\u3057\u3066\u3044\u308B\u3002\u30DE\u30C3\u30C1\u3057\u305F\u30BB\u30B0\u30E1\u30F3\u30C8\u30EA\u30B9\u30C8\u3068\u5404\u30BB\u30B0\u30E1\u30F3\u30C8\u306E\u6700\u521D\u306E5\u4EF6\u306E\u30E1\u30C3\u30BB\u30FC\u30B8\u30D7\u30EC\u30D3\u30E5\u30FC\u3092\u8FD4\u5374\u3059\u308B\u3002",
|
|
16152
16169
|
params: {
|
|
16153
|
-
keywords: "\u4EFB\u610F\u306E\u691C\u7D22\u30AD\u30FC\u30EF\u30FC\u30C9\u30EA\u30B9\u30C8\u3002\u3053\u308C\u3089\u306E\u30AD\u30FC\u30EF\u30FC\u30C9\u3092\u542B\u3080\u30BB\
|
|
16154
|
-
limit: "\u8FD4\u5374\u30BB\
|
|
16155
|
-
year: "\u6307\u5B9A\u5E74\u306E\u30BB\
|
|
16156
|
-
month: "\u6307\u5B9A\u6708\u306E\u30BB\
|
|
16157
|
-
day: "\u6307\u5B9A\u65E5\u306E\u30BB\
|
|
16170
|
+
keywords: "\u4EFB\u610F\u306E\u691C\u7D22\u30AD\u30FC\u30EF\u30FC\u30C9\u30EA\u30B9\u30C8\u3002\u3053\u308C\u3089\u306E\u30AD\u30FC\u30EF\u30FC\u30C9\u3092\u542B\u3080\u30BB\u30B0\u30E1\u30F3\u30C8\u306E\u307F\u8FD4\u5374\u3059\u308B\uFF08OR \u30ED\u30B8\u30C3\u30AF\u30DE\u30C3\u30C1\uFF09",
|
|
16171
|
+
limit: "\u8FD4\u5374\u30BB\u30B0\u30E1\u30F3\u30C8\u6570\u306E\u4E0A\u9650\u3002\u30C7\u30D5\u30A9\u30EB\u30C8 20",
|
|
16172
|
+
year: "\u6307\u5B9A\u5E74\u306E\u30BB\u30B0\u30E1\u30F3\u30C8\u3092\u30D5\u30A3\u30EB\u30BF\u30EA\u30F3\u30B0\uFF08\u4F8B\uFF1A2024\uFF09",
|
|
16173
|
+
month: "\u6307\u5B9A\u6708\u306E\u30BB\u30B0\u30E1\u30F3\u30C8\u3092\u30D5\u30A3\u30EB\u30BF\u30EA\u30F3\u30B0\uFF081-12\uFF09\u3002year \u3068\u4F75\u7528\u3059\u308B\u5FC5\u8981\u304C\u3042\u308B",
|
|
16174
|
+
day: "\u6307\u5B9A\u65E5\u306E\u30BB\u30B0\u30E1\u30F3\u30C8\u3092\u30D5\u30A3\u30EB\u30BF\u30EA\u30F3\u30B0\uFF081-31\uFF09\u3002year \u3068 month \u3068\u4F75\u7528\u3059\u308B\u5FC5\u8981\u304C\u3042\u308B",
|
|
16158
16175
|
start_time: '\u958B\u59CB\u6642\u523B\u3002\u5F62\u5F0F "YYYY-MM-DD HH:mm"\uFF08\u4F8B\uFF1A"2024-03-15 14:00"\uFF09',
|
|
16159
16176
|
end_time: '\u7D42\u4E86\u6642\u523B\u3002\u5F62\u5F0F "YYYY-MM-DD HH:mm"\uFF08\u4F8B\uFF1A"2024-03-15 18:30"\uFF09'
|
|
16160
16177
|
}
|
|
16161
16178
|
},
|
|
16162
|
-
|
|
16163
|
-
desc: "\u6307\u5B9A\u30BB\
|
|
16179
|
+
get_segment_messages: {
|
|
16180
|
+
desc: "\u6307\u5B9A\u30BB\u30B0\u30E1\u30F3\u30C8\u306E\u5B8C\u5168\u306A\u30E1\u30C3\u30BB\u30FC\u30B8\u30EA\u30B9\u30C8\u3092\u53D6\u5F97\u3059\u308B\u3002search_segments \u3067\u95A2\u9023\u30BB\u30B0\u30E1\u30F3\u30C8\u3092\u898B\u3064\u3051\u305F\u5F8C\u3001\u305D\u306E\u30BB\u30B0\u30E1\u30F3\u30C8\u306E\u5B8C\u5168\u306A\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u3092\u53D6\u5F97\u3059\u308B\u305F\u3081\u306B\u4F7F\u7528\u3059\u308B\u3002\u30BB\u30B0\u30E1\u30F3\u30C8\u306E\u5168\u30E1\u30C3\u30BB\u30FC\u30B8\u3068\u53C2\u52A0\u8005\u60C5\u5831\u3092\u8FD4\u5374\u3059\u308B\u3002",
|
|
16164
16181
|
params: {
|
|
16165
|
-
|
|
16166
|
-
limit: "\u8FD4\u5374\u30E1\u30C3\u30BB\u30FC\u30B8\u6570\u306E\u4E0A\u9650\u3002\u30C7\u30D5\u30A9\u30EB\u30C8 1000\u3002\u975E\u5E38\u306B\u9577\u3044\u30BB\
|
|
16182
|
+
segment_id: "\u30BB\u30B0\u30E1\u30F3\u30C8 ID\u3002search_segments \u306E\u8FD4\u5374\u7D50\u679C\u304B\u3089\u53D6\u5F97\u3067\u304D\u308B",
|
|
16183
|
+
limit: "\u8FD4\u5374\u30E1\u30C3\u30BB\u30FC\u30B8\u6570\u306E\u4E0A\u9650\u3002\u30C7\u30D5\u30A9\u30EB\u30C8 1000\u3002\u975E\u5E38\u306B\u9577\u3044\u30BB\u30B0\u30E1\u30F3\u30C8\u3067\u306F Token \u7BC0\u7D04\u306E\u305F\u3081\u4EF6\u6570\u3092\u5236\u9650\u3067\u304D\u308B"
|
|
16167
16184
|
}
|
|
16168
16185
|
},
|
|
16169
|
-
|
|
16170
|
-
desc: `\u30BB\
|
|
16186
|
+
get_segment_summaries: {
|
|
16187
|
+
desc: `\u30BB\u30B0\u30E1\u30F3\u30C8\u8981\u7D04\u30EA\u30B9\u30C8\u3092\u53D6\u5F97\u3057\u3001\u30B0\u30EB\u30FC\u30D7\u30C1\u30E3\u30C3\u30C8\u306E\u904E\u53BB\u306E\u8B70\u8AD6\u30C8\u30D4\u30C3\u30AF\u3092\u3059\u3070\u3084\u304F\u628A\u63E1\u3059\u308B\u3002
|
|
16171
16188
|
|
|
16172
16189
|
\u9069\u7528\u30B7\u30FC\u30F3\uFF1A
|
|
16173
16190
|
1. \u30B0\u30EB\u30FC\u30D7\u3067\u6700\u8FD1\u4F55\u304C\u8A71\u984C\u306B\u306A\u3063\u3066\u3044\u305F\u304B\u77E5\u308A\u305F\u3044
|
|
16174
16191
|
2. \u30AD\u30FC\u30EF\u30FC\u30C9\u3067\u904E\u53BB\u306B\u8B70\u8AD6\u3055\u308C\u305F\u30C8\u30D4\u30C3\u30AF\u3092\u691C\u7D22
|
|
16175
16192
|
3. \u300C\u30B0\u30EB\u30FC\u30D7\u3067\u65C5\u884C\u306B\u3064\u3044\u3066\u8A71\u3057\u305F\u3053\u3068\u3042\u308B\uFF1F\u300D\u306A\u3069\u306E\u6982\u8981\u7684\u306A\u8CEA\u554F
|
|
16176
16193
|
|
|
16177
|
-
\u8FD4\u5374\u3055\u308C\u308B\u8981\u7D04\u306F\u5404\u30BB\
|
|
16194
|
+
\u8FD4\u5374\u3055\u308C\u308B\u8981\u7D04\u306F\u5404\u30BB\u30B0\u30E1\u30F3\u30C8\u306E\u77ED\u3044\u6982\u8981\u3067\u3042\u308A\u3001\u8208\u5473\u306E\u3042\u308B\u30BB\u30B0\u30E1\u30F3\u30C8\u3092\u3059\u3070\u3084\u304F\u7279\u5B9A\u3057\u3001get_segment_messages \u3067\u8A73\u7D30\u3092\u53D6\u5F97\u3067\u304D\u308B\u3002`,
|
|
16178
16195
|
params: {
|
|
16179
16196
|
keywords: "\u8981\u7D04\u5185\u3067\u691C\u7D22\u3059\u308B\u30AD\u30FC\u30EF\u30FC\u30C9\u30EA\u30B9\u30C8\uFF08OR \u30ED\u30B8\u30C3\u30AF\u30DE\u30C3\u30C1\uFF09",
|
|
16180
|
-
limit: "\u8FD4\u5374\u30BB\
|
|
16181
|
-
year: "\u6307\u5B9A\u5E74\u306E\u30BB\
|
|
16182
|
-
month: "\u6307\u5B9A\u6708\u306E\u30BB\
|
|
16183
|
-
day: "\u6307\u5B9A\u65E5\u306E\u30BB\
|
|
16197
|
+
limit: "\u8FD4\u5374\u30BB\u30B0\u30E1\u30F3\u30C8\u6570\u306E\u4E0A\u9650\u3002\u30C7\u30D5\u30A9\u30EB\u30C8 20",
|
|
16198
|
+
year: "\u6307\u5B9A\u5E74\u306E\u30BB\u30B0\u30E1\u30F3\u30C8\u3092\u30D5\u30A3\u30EB\u30BF\u30EA\u30F3\u30B0",
|
|
16199
|
+
month: "\u6307\u5B9A\u6708\u306E\u30BB\u30B0\u30E1\u30F3\u30C8\u3092\u30D5\u30A3\u30EB\u30BF\u30EA\u30F3\u30B0\uFF081-12\uFF09",
|
|
16200
|
+
day: "\u6307\u5B9A\u65E5\u306E\u30BB\u30B0\u30E1\u30F3\u30C8\u3092\u30D5\u30A3\u30EB\u30BF\u30EA\u30F3\u30B0\uFF081-31\uFF09",
|
|
16184
16201
|
start_time: '\u958B\u59CB\u6642\u523B\u3002\u5F62\u5F0F "YYYY-MM-DD HH:mm"',
|
|
16185
16202
|
end_time: '\u7D42\u4E86\u6642\u523B\u3002\u5F62\u5F0F "YYYY-MM-DD HH:mm"'
|
|
16186
16203
|
}
|
|
@@ -16267,14 +16284,14 @@ var ja_JP_default = {
|
|
|
16267
16284
|
fallback: "\u3053\u306E\u671F\u9593\u306B\u30E1\u30C3\u30BB\u30FC\u30B8\u306E\u8A18\u9332\u304C\u3042\u308A\u307E\u305B\u3093"
|
|
16268
16285
|
},
|
|
16269
16286
|
conversation_initiator_stats: {
|
|
16270
|
-
desc: "\u5404\u30E1\u30F3\u30D0\u30FC\u304C\u4F1A\u8A71\u3092\u958B\u59CB\u3057\u305F\u56DE\u6570\uFF08\u30BB\
|
|
16287
|
+
desc: "\u5404\u30E1\u30F3\u30D0\u30FC\u304C\u4F1A\u8A71\u3092\u958B\u59CB\u3057\u305F\u56DE\u6570\uFF08\u30BB\u30B0\u30E1\u30F3\u30C8\u306E\u6700\u521D\u306E\u767A\u8A00\u8005\uFF09\u3092\u96C6\u8A08\u3057\u3001\u8AB0\u304C\u6700\u3082\u8A71\u984C\u3092\u5207\u308A\u51FA\u3059\u304B\u3092\u767A\u898B\u3059\u308B\u3002\u30BB\u30B0\u30E1\u30F3\u30C8\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u306E\u751F\u6210\u304C\u5FC5\u8981\u3002",
|
|
16271
16288
|
params: {
|
|
16272
16289
|
days: "\u76F4\u8FD1\u4F55\u65E5\u9593\u306E\u30C7\u30FC\u30BF\u3092\u96C6\u8A08\u3059\u308B\u304B",
|
|
16273
16290
|
limit: "\u4E0A\u4F4D\u4F55\u540D\u3092\u8FD4\u5374\u3059\u308B\u304B"
|
|
16274
16291
|
},
|
|
16275
16292
|
rowTemplate: "{name}\uFF1A{initiated_count} \u56DE\u8A71\u984C\u3092\u958B\u59CB",
|
|
16276
16293
|
summaryTemplate: "\u8A71\u984C\u958B\u59CB\u8005 Top {rowCount}\uFF1A",
|
|
16277
|
-
fallback: "\u3053\u306E\u671F\u9593\u306B\u30BB\
|
|
16294
|
+
fallback: "\u3053\u306E\u671F\u9593\u306B\u30BB\u30B0\u30E1\u30F3\u30C8\u8A18\u9332\u304C\u3042\u308A\u307E\u305B\u3093\u3002\u5148\u306B\u30BB\u30B0\u30E1\u30F3\u30C8\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u3092\u751F\u6210\u3059\u308B\u5FC5\u8981\u304C\u3042\u308B\u304B\u3082\u3057\u308C\u307E\u305B\u3093"
|
|
16278
16295
|
},
|
|
16279
16296
|
activity_heatmap: {
|
|
16280
16297
|
desc: "\u66DC\u65E5\xD7\u6642\u9593\u5E2F\u306E\u30E1\u30C3\u30BB\u30FC\u30B8\u6570\u30DE\u30C8\u30EA\u30C3\u30AF\u30B9\u3092\u8FD4\u5374\u3059\u308B\u3002\u6D3B\u6027\u5EA6\u30D2\u30FC\u30C8\u30DE\u30C3\u30D7\u306E\u751F\u6210\u306B\u9069\u3057\u3066\u3044\u308B\u3002weekday: 0=\u65E5\u66DC, 1=\u6708\u66DC, ..., 6=\u571F\u66DC\u3002",
|
|
@@ -16376,10 +16393,10 @@ var ja_JP_default = {
|
|
|
16376
16393
|
rawErrorLabel: "\u5143\u306E\u30A8\u30E9\u30FC"
|
|
16377
16394
|
},
|
|
16378
16395
|
summary: {
|
|
16379
|
-
|
|
16396
|
+
segmentNotFound: "\u30BB\u30B0\u30E1\u30F3\u30C8\u304C\u5B58\u5728\u3057\u306A\u3044\u304B\u3001\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u958B\u3051\u307E\u305B\u3093\u3067\u3057\u305F",
|
|
16380
16397
|
tooFewMessages: "\u30E1\u30C3\u30BB\u30FC\u30B8\u6570\u304C{{count}}\u4EF6\u672A\u6E80\u306E\u305F\u3081\u3001\u8981\u7D04\u306E\u751F\u6210\u306F\u4E0D\u8981\u3067\u3059",
|
|
16381
16398
|
tooFewValidMessages: "\u6709\u52B9\u306A\u30E1\u30C3\u30BB\u30FC\u30B8\u6570\u304C{{count}}\u4EF6\u672A\u6E80\u306E\u305F\u3081\u3001\u8981\u7D04\u306E\u751F\u6210\u306F\u4E0D\u8981\u3067\u3059",
|
|
16382
|
-
|
|
16399
|
+
segmentNotExist: "\u30BB\u30B0\u30E1\u30F3\u30C8\u304C\u5B58\u5728\u3057\u307E\u305B\u3093",
|
|
16383
16400
|
messagesTooFew: "\u30E1\u30C3\u30BB\u30FC\u30B8\u304C\u5C11\u306A\u3059\u304E\u307E\u3059",
|
|
16384
16401
|
validMessagesTooFew: "\u6709\u52B9\u306A\u30E1\u30C3\u30BB\u30FC\u30B8\u304C\u5C11\u306A\u3059\u304E\u307E\u3059",
|
|
16385
16402
|
systemPromptDirect: "\u3042\u306A\u305F\u306F\u4F1A\u8A71\u8981\u7D04\u306E\u5C02\u9580\u5BB6\u3067\u3042\u308A\u3001\u7C21\u6F54\u306A\u8A00\u8449\u3067\u4F1A\u8A71\u5185\u5BB9\u3092\u8981\u7D04\u3059\u308B\u3053\u3068\u306B\u9577\u3051\u3066\u3044\u308B\u3002",
|
|
@@ -16479,7 +16496,7 @@ var zh_TW_default = {
|
|
|
16479
16496
|
context_size: "\u4E0A\u4E0B\u6587\u5927\u5C0F\uFF0C\u5373\u53D6\u5F97\u524D\u5F8C\u5404\u591A\u5C11\u689D\u8A0A\u606F\uFF0C\u9810\u8A2D 20"
|
|
16480
16497
|
}
|
|
16481
16498
|
},
|
|
16482
|
-
|
|
16499
|
+
search_segments: {
|
|
16483
16500
|
desc: "\u641C\u5C0B\u804A\u5929\u6703\u8A71\uFF08\u5C0D\u8A71\u6BB5\u843D\uFF09\u3002\u6703\u8A71\u662F\u6839\u64DA\u8A0A\u606F\u6642\u9593\u9593\u9694\u81EA\u52D5\u5207\u5206\u7684\u5C0D\u8A71\u55AE\u5143\u3002\u9069\u7528\u65BC\u67E5\u627E\u7279\u5B9A\u8A71\u984C\u7684\u8A0E\u8AD6\u3001\u4E86\u89E3\u67D0\u500B\u6642\u9593\u6BB5\u5167\u767C\u751F\u4E86\u5E7E\u6B21\u5C0D\u8A71\u7B49\u5834\u666F\u3002\u56DE\u50B3\u5339\u914D\u7684\u6703\u8A71\u6E05\u55AE\u53CA\u6BCF\u500B\u6703\u8A71\u7684\u524D5\u689D\u8A0A\u606F\u9810\u89BD\u3002",
|
|
16484
16501
|
params: {
|
|
16485
16502
|
keywords: "\u53EF\u9078\u7684\u641C\u5C0B\u95DC\u9375\u8A5E\u6E05\u55AE\uFF0C\u53EA\u56DE\u50B3\u5305\u542B\u9019\u4E9B\u95DC\u9375\u8A5E\u7684\u6703\u8A71\uFF08OR \u908F\u8F2F\u5339\u914D\uFF09",
|
|
@@ -16491,22 +16508,22 @@ var zh_TW_default = {
|
|
|
16491
16508
|
end_time: '\u7D50\u675F\u6642\u9593\uFF0C\u683C\u5F0F "YYYY-MM-DD HH:mm"\uFF0C\u5982 "2024-03-15 18:30"'
|
|
16492
16509
|
}
|
|
16493
16510
|
},
|
|
16494
|
-
|
|
16495
|
-
desc: "\u53D6\u5F97\u6307\u5B9A\u6703\u8A71\u7684\u5B8C\u6574\u8A0A\u606F\u6E05\u55AE\u3002\u7528\u65BC\u5728
|
|
16511
|
+
get_segment_messages: {
|
|
16512
|
+
desc: "\u53D6\u5F97\u6307\u5B9A\u6703\u8A71\u7684\u5B8C\u6574\u8A0A\u606F\u6E05\u55AE\u3002\u7528\u65BC\u5728 search_segments \u627E\u5230\u76F8\u95DC\u6703\u8A71\u5F8C\uFF0C\u53D6\u5F97\u8A72\u6703\u8A71\u7684\u5B8C\u6574\u4E0A\u4E0B\u6587\u3002\u56DE\u50B3\u6703\u8A71\u7684\u6240\u6709\u8A0A\u606F\u53CA\u53C3\u8207\u8005\u8CC7\u8A0A\u3002",
|
|
16496
16513
|
params: {
|
|
16497
|
-
|
|
16514
|
+
segment_id: "\u6703\u8A71 ID\uFF0C\u53EF\u4EE5\u5F9E search_segments \u7684\u56DE\u50B3\u7D50\u679C\u4E2D\u53D6\u5F97",
|
|
16498
16515
|
limit: "\u56DE\u50B3\u8A0A\u606F\u6578\u91CF\u9650\u5236\uFF0C\u9810\u8A2D 1000\u3002\u5C0D\u65BC\u8D85\u9577\u6703\u8A71\u53EF\u4EE5\u9650\u5236\u56DE\u50B3\u6578\u91CF\u4EE5\u7BC0\u7701 token"
|
|
16499
16516
|
}
|
|
16500
16517
|
},
|
|
16501
|
-
|
|
16502
|
-
desc: `\u53D6\u5F97\
|
|
16518
|
+
get_segment_summaries: {
|
|
16519
|
+
desc: `\u53D6\u5F97\u6BB5\u843D\u6458\u8981\u6E05\u55AE\uFF0C\u5FEB\u901F\u4E86\u89E3\u7FA4\u804A\u6B77\u53F2\u8A0E\u8AD6\u7684\u4E3B\u984C\u3002
|
|
16503
16520
|
|
|
16504
16521
|
\u9069\u7528\u5834\u666F\uFF1A
|
|
16505
16522
|
1. \u4E86\u89E3\u7FA4\u88E1\u6700\u8FD1\u5728\u804A\u4EC0\u9EBC\u8A71\u984C
|
|
16506
16523
|
2. \u6309\u95DC\u9375\u8A5E\u641C\u5C0B\u8A0E\u8AD6\u904E\u7684\u8A71\u984C
|
|
16507
16524
|
3. \u6982\u89BD\u6027\u554F\u984C\u5982\u300C\u7FA4\u88E1\u6709\u6C92\u6709\u8A0E\u8AD6\u904E\u65C5\u904A\u300D
|
|
16508
16525
|
|
|
16509
|
-
\u56DE\u50B3\u7684\u6458\u8981\u662F\u5C0D\u6BCF\u500B\u6703\u8A71\u7684\u7C21\u77ED\u7E3D\u7D50\uFF0C\u53EF\u4EE5\u5E6B\u52A9\u5FEB\u901F\u5B9A\u4F4D\u611F\u8208\u8DA3\u7684\u6703\u8A71\uFF0C\u7136\u5F8C\u7528
|
|
16526
|
+
\u56DE\u50B3\u7684\u6458\u8981\u662F\u5C0D\u6BCF\u500B\u6703\u8A71\u7684\u7C21\u77ED\u7E3D\u7D50\uFF0C\u53EF\u4EE5\u5E6B\u52A9\u5FEB\u901F\u5B9A\u4F4D\u611F\u8208\u8DA3\u7684\u6703\u8A71\uFF0C\u7136\u5F8C\u7528 get_segment_messages \u53D6\u5F97\u8A73\u60C5\u3002`,
|
|
16510
16527
|
params: {
|
|
16511
16528
|
keywords: "\u5728\u6458\u8981\u4E2D\u641C\u5C0B\u7684\u95DC\u9375\u8A5E\u6E05\u55AE\uFF08OR \u908F\u8F2F\u5339\u914D\uFF09",
|
|
16512
16529
|
limit: "\u56DE\u50B3\u6703\u8A71\u6578\u91CF\u9650\u5236\uFF0C\u9810\u8A2D 20",
|
|
@@ -16708,10 +16725,10 @@ var zh_TW_default = {
|
|
|
16708
16725
|
rawErrorLabel: "\u539F\u59CB\u932F\u8AA4"
|
|
16709
16726
|
},
|
|
16710
16727
|
summary: {
|
|
16711
|
-
|
|
16728
|
+
segmentNotFound: "\u6703\u8A71\u4E0D\u5B58\u5728\u6216\u8CC7\u6599\u5EAB\u958B\u555F\u5931\u6557",
|
|
16712
16729
|
tooFewMessages: "\u8A0A\u606F\u6578\u91CF\u5C11\u65BC {{count}} \u689D\uFF0C\u7121\u9700\u7522\u751F\u6458\u8981",
|
|
16713
16730
|
tooFewValidMessages: "\u6709\u6548\u8A0A\u606F\u6578\u91CF\u5C11\u65BC {{count}} \u689D\uFF0C\u7121\u9700\u7522\u751F\u6458\u8981",
|
|
16714
|
-
|
|
16731
|
+
segmentNotExist: "\u627E\u4E0D\u5230\u6703\u8A71",
|
|
16715
16732
|
messagesTooFew: "\u8A0A\u606F\u592A\u5C11",
|
|
16716
16733
|
validMessagesTooFew: "\u6709\u6548\u8A0A\u606F\u592A\u5C11",
|
|
16717
16734
|
systemPromptDirect: "\u4F60\u662F\u4E00\u500B\u5C0D\u8A71\u6458\u8981\u5C08\u5BB6\uFF0C\u64C5\u9577\u7528\u7C21\u6F54\u7684\u8A9E\u8A00\u7E3D\u7D50\u5C0D\u8A71\u5167\u5BB9\u3002",
|
|
@@ -16726,9 +16743,9 @@ var localeMap = {
|
|
|
16726
16743
|
"ja-JP": ja_JP_default,
|
|
16727
16744
|
"zh-TW": zh_TW_default
|
|
16728
16745
|
};
|
|
16729
|
-
function getNestedValue(obj,
|
|
16746
|
+
function getNestedValue(obj, path36) {
|
|
16730
16747
|
let current = obj;
|
|
16731
|
-
for (const segment2 of
|
|
16748
|
+
for (const segment2 of path36.split(".")) {
|
|
16732
16749
|
if (current == null || typeof current !== "object") return void 0;
|
|
16733
16750
|
current = current[segment2];
|
|
16734
16751
|
}
|
|
@@ -16924,15 +16941,15 @@ function postProcessSummary(summary, lengthLimit) {
|
|
|
16924
16941
|
}
|
|
16925
16942
|
return result;
|
|
16926
16943
|
}
|
|
16927
|
-
async function generateSessionSummary(deps,
|
|
16944
|
+
async function generateSessionSummary(deps, segmentId, options = {}) {
|
|
16928
16945
|
const { locale = "zh-CN", forceRegenerate = false, strategy = "standard" } = options;
|
|
16929
16946
|
const log = deps.logger;
|
|
16930
16947
|
try {
|
|
16931
16948
|
if (!forceRegenerate) {
|
|
16932
|
-
const existing = deps.getSummary(
|
|
16949
|
+
const existing = deps.getSummary(segmentId);
|
|
16933
16950
|
if (existing) return { success: true, summary: existing };
|
|
16934
16951
|
}
|
|
16935
|
-
const rawMessages = deps.loadMessages(
|
|
16952
|
+
const rawMessages = deps.loadMessages(segmentId);
|
|
16936
16953
|
if (!rawMessages) {
|
|
16937
16954
|
return { success: false, error: deps.t("summary.sessionNotFound") };
|
|
16938
16955
|
}
|
|
@@ -16949,7 +16966,7 @@ async function generateSessionSummary(deps, chatSessionId, options = {}) {
|
|
|
16949
16966
|
const content = formatMessages(validMessages);
|
|
16950
16967
|
log?.info(
|
|
16951
16968
|
"Summary",
|
|
16952
|
-
`Generating summary: sessionId=${
|
|
16969
|
+
`Generating summary: sessionId=${segmentId}, strategy=${strategy}, raw=${rawMessages.length}, valid=${validMessages.length}, chars=${content.length}`
|
|
16953
16970
|
);
|
|
16954
16971
|
let summary;
|
|
16955
16972
|
if (content.length <= SEGMENT_THRESHOLD) {
|
|
@@ -16984,7 +17001,7 @@ async function generateSessionSummary(deps, chatSessionId, options = {}) {
|
|
|
16984
17001
|
}
|
|
16985
17002
|
}
|
|
16986
17003
|
summary = postProcessSummary(summary, lengthLimit);
|
|
16987
|
-
deps.saveSummary(
|
|
17004
|
+
deps.saveSummary(segmentId, summary);
|
|
16988
17005
|
log?.info("Summary", `Summary generated: "${summary.slice(0, 50)}..."`);
|
|
16989
17006
|
return { success: true, summary };
|
|
16990
17007
|
} catch (error) {
|
|
@@ -16992,9 +17009,9 @@ async function generateSessionSummary(deps, chatSessionId, options = {}) {
|
|
|
16992
17009
|
return { success: false, error: error instanceof Error ? error.message : String(error) };
|
|
16993
17010
|
}
|
|
16994
17011
|
}
|
|
16995
|
-
function checkSessionsCanGenerateSummary(deps,
|
|
17012
|
+
function checkSessionsCanGenerateSummary(deps, segmentIds) {
|
|
16996
17013
|
const results = /* @__PURE__ */ new Map();
|
|
16997
|
-
for (const id of
|
|
17014
|
+
for (const id of segmentIds) {
|
|
16998
17015
|
const messages = deps.loadMessages(id);
|
|
16999
17016
|
if (!messages) {
|
|
17000
17017
|
results.set(id, { canGenerate: false, reason: deps.t("summary.sessionNotExist") });
|
|
@@ -17305,7 +17322,7 @@ function getNoopLogger() {
|
|
|
17305
17322
|
var _logger = getNoopLogger();
|
|
17306
17323
|
|
|
17307
17324
|
// ../../packages/node-runtime/src/ai/rag/chunking/session.ts
|
|
17308
|
-
import
|
|
17325
|
+
import Database2 from "better-sqlite3";
|
|
17309
17326
|
var _logger2 = getNoopLogger();
|
|
17310
17327
|
|
|
17311
17328
|
// ../../packages/node-runtime/src/ai/rag/embedding/openai-compatible.ts
|
|
@@ -17315,7 +17332,7 @@ var _logger3 = getNoopLogger();
|
|
|
17315
17332
|
var _logger4 = getNoopLogger();
|
|
17316
17333
|
|
|
17317
17334
|
// ../../packages/node-runtime/src/ai/rag/store/sqlite.ts
|
|
17318
|
-
import
|
|
17335
|
+
import Database3 from "better-sqlite3";
|
|
17319
17336
|
var _logger5 = getNoopLogger();
|
|
17320
17337
|
|
|
17321
17338
|
// ../../packages/node-runtime/src/ai/rag/store/memory.ts
|
|
@@ -17840,7 +17857,216 @@ function expandHome(filePath) {
|
|
|
17840
17857
|
return filePath;
|
|
17841
17858
|
}
|
|
17842
17859
|
|
|
17860
|
+
// ../../packages/node-runtime/src/data-dir-compat.ts
|
|
17861
|
+
import fs34 from "fs";
|
|
17862
|
+
import path31 from "path";
|
|
17863
|
+
var DataDirCompatibilityError = class extends Error {
|
|
17864
|
+
code;
|
|
17865
|
+
userDataDir;
|
|
17866
|
+
metaPath;
|
|
17867
|
+
currentVersion;
|
|
17868
|
+
minRuntimeVersion;
|
|
17869
|
+
statusCode = 409;
|
|
17870
|
+
constructor(code, message, options) {
|
|
17871
|
+
super(message, { cause: options.cause });
|
|
17872
|
+
this.name = "DataDirCompatibilityError";
|
|
17873
|
+
this.code = code;
|
|
17874
|
+
this.userDataDir = options.userDataDir;
|
|
17875
|
+
this.metaPath = options.metaPath;
|
|
17876
|
+
this.currentVersion = options.currentVersion;
|
|
17877
|
+
this.minRuntimeVersion = options.minRuntimeVersion;
|
|
17878
|
+
}
|
|
17879
|
+
};
|
|
17880
|
+
function readDataDirCompatibilityMeta(userDataDir) {
|
|
17881
|
+
const metaPath = getMetaPath(userDataDir);
|
|
17882
|
+
if (!fs34.existsSync(metaPath)) return null;
|
|
17883
|
+
let parsed;
|
|
17884
|
+
try {
|
|
17885
|
+
parsed = JSON.parse(fs34.readFileSync(metaPath, "utf-8"));
|
|
17886
|
+
} catch (error) {
|
|
17887
|
+
throw createInvalidMetaError(userDataDir, metaPath, "Invalid data directory compatibility meta JSON.", error);
|
|
17888
|
+
}
|
|
17889
|
+
return validateDataDirCompatibilityMeta(parsed, userDataDir, metaPath);
|
|
17890
|
+
}
|
|
17891
|
+
function assertDataDirCompatible(pathProvider, runtime, options = {}) {
|
|
17892
|
+
const userDataDir = pathProvider.getUserDataDir();
|
|
17893
|
+
const meta = readDataDirCompatibilityMeta(userDataDir);
|
|
17894
|
+
if (!meta) return;
|
|
17895
|
+
if (!isStableSemver(runtime.version)) {
|
|
17896
|
+
throw new DataDirCompatibilityError(
|
|
17897
|
+
"DATA_DIR_REQUIRES_NEWER_RUNTIME",
|
|
17898
|
+
`ChatLab data directory compatibility check requires a stable runtime version; current version is ${runtime.version}.`,
|
|
17899
|
+
{
|
|
17900
|
+
userDataDir,
|
|
17901
|
+
metaPath: getMetaPath(userDataDir),
|
|
17902
|
+
currentVersion: runtime.version,
|
|
17903
|
+
minRuntimeVersion: meta.minRuntimeVersion
|
|
17904
|
+
}
|
|
17905
|
+
);
|
|
17906
|
+
}
|
|
17907
|
+
if (compareStableSemver(runtime.version, meta.minRuntimeVersion) < 0) {
|
|
17908
|
+
const env = options.env ?? process.env;
|
|
17909
|
+
if (env.CHATLAB_ALLOW_INCOMPATIBLE_DATA_DIR === "1") {
|
|
17910
|
+
const warn = options.warn ?? console.warn;
|
|
17911
|
+
warn(
|
|
17912
|
+
[
|
|
17913
|
+
"CHATLAB_ALLOW_INCOMPATIBLE_DATA_DIR=1 is set. ChatLab will bypass the data directory runtime version gate.",
|
|
17914
|
+
`Current runtime ${runtime.kind}@${runtime.version} is below required version ${meta.minRuntimeVersion}.`,
|
|
17915
|
+
`Data directory: ${userDataDir}. Continuing may risk data corruption.`
|
|
17916
|
+
].join(" ")
|
|
17917
|
+
);
|
|
17918
|
+
return;
|
|
17919
|
+
}
|
|
17920
|
+
throw new DataDirCompatibilityError(
|
|
17921
|
+
"DATA_DIR_REQUIRES_NEWER_RUNTIME",
|
|
17922
|
+
`ChatLab data directory requires runtime version ${meta.minRuntimeVersion} or newer; current version is ${runtime.version}.`,
|
|
17923
|
+
{
|
|
17924
|
+
userDataDir,
|
|
17925
|
+
metaPath: getMetaPath(userDataDir),
|
|
17926
|
+
currentVersion: runtime.version,
|
|
17927
|
+
minRuntimeVersion: meta.minRuntimeVersion
|
|
17928
|
+
}
|
|
17929
|
+
);
|
|
17930
|
+
}
|
|
17931
|
+
}
|
|
17932
|
+
function raiseDataDirMinRuntimeVersion(pathProvider, input) {
|
|
17933
|
+
const userDataDir = pathProvider.getUserDataDir();
|
|
17934
|
+
const metaPath = getMetaPath(userDataDir);
|
|
17935
|
+
assertStableVersion(input.minRuntimeVersion, userDataDir, metaPath, "Invalid minRuntimeVersion.");
|
|
17936
|
+
assertStableVersion(input.runtime.version, userDataDir, metaPath, "Invalid runtime version.");
|
|
17937
|
+
if (!isRuntimeKind(input.runtime.kind)) {
|
|
17938
|
+
throw createInvalidMetaError(userDataDir, metaPath, "Invalid runtime kind.");
|
|
17939
|
+
}
|
|
17940
|
+
if (!isNonEmptyString(input.module) || !isNonEmptyString(input.reason)) {
|
|
17941
|
+
throw createInvalidMetaError(userDataDir, metaPath, "Invalid compatibility raise metadata.");
|
|
17942
|
+
}
|
|
17943
|
+
if (!Number.isInteger(input.dataCompatibilityVersion) || input.dataCompatibilityVersion < 0) {
|
|
17944
|
+
throw createInvalidMetaError(userDataDir, metaPath, "Invalid dataCompatibilityVersion.");
|
|
17945
|
+
}
|
|
17946
|
+
const existing = readDataDirCompatibilityMeta(userDataDir);
|
|
17947
|
+
const minRuntimeVersion = existing && compareStableSemver(existing.minRuntimeVersion, input.minRuntimeVersion) > 0 ? existing.minRuntimeVersion : input.minRuntimeVersion;
|
|
17948
|
+
const dataCompatibilityVersion = Math.max(existing?.dataCompatibilityVersion ?? 0, input.dataCompatibilityVersion);
|
|
17949
|
+
const reasons = mergeReasons(existing?.reasons ?? [], input.reason);
|
|
17950
|
+
const now = input.now ?? (() => Math.floor(Date.now() / 1e3));
|
|
17951
|
+
const nextMeta = {
|
|
17952
|
+
formatVersion: 1,
|
|
17953
|
+
minRuntimeVersion,
|
|
17954
|
+
dataCompatibilityVersion,
|
|
17955
|
+
reasons,
|
|
17956
|
+
updatedBy: {
|
|
17957
|
+
runtime: input.runtime.kind,
|
|
17958
|
+
module: input.module,
|
|
17959
|
+
version: input.runtime.version
|
|
17960
|
+
},
|
|
17961
|
+
updatedAt: now()
|
|
17962
|
+
};
|
|
17963
|
+
writeMetaAtomic(userDataDir, metaPath, nextMeta);
|
|
17964
|
+
return nextMeta;
|
|
17965
|
+
}
|
|
17966
|
+
function getMetaPath(userDataDir) {
|
|
17967
|
+
return path31.join(userDataDir, ".chatlab-meta.json");
|
|
17968
|
+
}
|
|
17969
|
+
function validateDataDirCompatibilityMeta(value, userDataDir, metaPath) {
|
|
17970
|
+
if (!isRecord2(value)) {
|
|
17971
|
+
throw createInvalidMetaError(userDataDir, metaPath, "Data directory compatibility meta must be an object.");
|
|
17972
|
+
}
|
|
17973
|
+
if (value.formatVersion !== 1) {
|
|
17974
|
+
throw createInvalidMetaError(userDataDir, metaPath, "Unsupported data directory compatibility meta format.");
|
|
17975
|
+
}
|
|
17976
|
+
const minRuntimeVersion = value.minRuntimeVersion;
|
|
17977
|
+
const dataCompatibilityVersion = value.dataCompatibilityVersion;
|
|
17978
|
+
const reasons = value.reasons;
|
|
17979
|
+
const updatedBy = value.updatedBy;
|
|
17980
|
+
const updatedAt = value.updatedAt;
|
|
17981
|
+
if (!isStableSemver(minRuntimeVersion) || typeof dataCompatibilityVersion !== "number" || !Number.isInteger(dataCompatibilityVersion) || dataCompatibilityVersion < 0 || !Array.isArray(reasons) || !reasons.every(isNonEmptyString) || !isRecord2(updatedBy) || !isRuntimeKind(updatedBy.runtime) || !isNonEmptyString(updatedBy.module) || !isStableSemver(updatedBy.version) || typeof updatedAt !== "number" || !Number.isInteger(updatedAt) || updatedAt < 0) {
|
|
17982
|
+
throw createInvalidMetaError(userDataDir, metaPath, "Invalid data directory compatibility meta fields.");
|
|
17983
|
+
}
|
|
17984
|
+
return {
|
|
17985
|
+
formatVersion: 1,
|
|
17986
|
+
minRuntimeVersion,
|
|
17987
|
+
dataCompatibilityVersion,
|
|
17988
|
+
reasons: [...reasons],
|
|
17989
|
+
updatedBy: {
|
|
17990
|
+
runtime: updatedBy.runtime,
|
|
17991
|
+
module: updatedBy.module,
|
|
17992
|
+
version: updatedBy.version
|
|
17993
|
+
},
|
|
17994
|
+
updatedAt
|
|
17995
|
+
};
|
|
17996
|
+
}
|
|
17997
|
+
function createInvalidMetaError(userDataDir, metaPath, message, cause) {
|
|
17998
|
+
return new DataDirCompatibilityError("DATA_DIR_COMPATIBILITY_META_INVALID", message, {
|
|
17999
|
+
userDataDir,
|
|
18000
|
+
metaPath,
|
|
18001
|
+
cause
|
|
18002
|
+
});
|
|
18003
|
+
}
|
|
18004
|
+
function assertStableVersion(version, userDataDir, metaPath, message) {
|
|
18005
|
+
if (!isStableSemver(version)) {
|
|
18006
|
+
throw createInvalidMetaError(userDataDir, metaPath, message);
|
|
18007
|
+
}
|
|
18008
|
+
}
|
|
18009
|
+
function isStableSemver(version) {
|
|
18010
|
+
return typeof version === "string" && /^\d+\.\d+\.\d+$/.test(version);
|
|
18011
|
+
}
|
|
18012
|
+
function compareStableSemver(left, right) {
|
|
18013
|
+
const leftParts = left.split(".").map(Number);
|
|
18014
|
+
const rightParts = right.split(".").map(Number);
|
|
18015
|
+
for (let i = 0; i < 3; i += 1) {
|
|
18016
|
+
if (leftParts[i] > rightParts[i]) return 1;
|
|
18017
|
+
if (leftParts[i] < rightParts[i]) return -1;
|
|
18018
|
+
}
|
|
18019
|
+
return 0;
|
|
18020
|
+
}
|
|
18021
|
+
function mergeReasons(existing, next) {
|
|
18022
|
+
return [.../* @__PURE__ */ new Set([...existing, next])];
|
|
18023
|
+
}
|
|
18024
|
+
function writeMetaAtomic(userDataDir, metaPath, meta) {
|
|
18025
|
+
fs34.mkdirSync(userDataDir, { recursive: true });
|
|
18026
|
+
const tempPath = path31.join(userDataDir, `.chatlab-meta.json.${process.pid}.${Date.now()}.tmp`);
|
|
18027
|
+
try {
|
|
18028
|
+
fs34.writeFileSync(tempPath, `${JSON.stringify(meta, null, 2)}
|
|
18029
|
+
`, "utf-8");
|
|
18030
|
+
fs34.renameSync(tempPath, metaPath);
|
|
18031
|
+
} catch (error) {
|
|
18032
|
+
try {
|
|
18033
|
+
if (fs34.existsSync(tempPath)) fs34.unlinkSync(tempPath);
|
|
18034
|
+
} catch {
|
|
18035
|
+
}
|
|
18036
|
+
throw error;
|
|
18037
|
+
}
|
|
18038
|
+
}
|
|
18039
|
+
function isRecord2(value) {
|
|
18040
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
18041
|
+
}
|
|
18042
|
+
function isNonEmptyString(value) {
|
|
18043
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
18044
|
+
}
|
|
18045
|
+
function isRuntimeKind(value) {
|
|
18046
|
+
return value === "cli" || value === "desktop" || value === "mcp" || value === "unknown";
|
|
18047
|
+
}
|
|
18048
|
+
|
|
17843
18049
|
// ../../packages/node-runtime/src/migrations/chat-db-migrations.ts
|
|
18050
|
+
var CHAT_DB_COMPATIBILITY_RAISES = [
|
|
18051
|
+
{
|
|
18052
|
+
migrationVersion: 6,
|
|
18053
|
+
minRuntimeVersion: "0.25.1",
|
|
18054
|
+
dataCompatibilityVersion: 1,
|
|
18055
|
+
reason: "segment-schema",
|
|
18056
|
+
module: "chat-db-migration"
|
|
18057
|
+
}
|
|
18058
|
+
];
|
|
18059
|
+
function raiseChatDbCompatibilityGate(pathProvider, runtime) {
|
|
18060
|
+
for (const compatibilityRaise of CHAT_DB_COMPATIBILITY_RAISES) {
|
|
18061
|
+
raiseDataDirMinRuntimeVersion(pathProvider, {
|
|
18062
|
+
minRuntimeVersion: compatibilityRaise.minRuntimeVersion,
|
|
18063
|
+
dataCompatibilityVersion: compatibilityRaise.dataCompatibilityVersion,
|
|
18064
|
+
reason: compatibilityRaise.reason,
|
|
18065
|
+
runtime,
|
|
18066
|
+
module: compatibilityRaise.module
|
|
18067
|
+
});
|
|
18068
|
+
}
|
|
18069
|
+
}
|
|
17844
18070
|
function getChatDbMigrations(deps) {
|
|
17845
18071
|
const hasColumn2 = (db, tableName, columnName) => {
|
|
17846
18072
|
const tableInfo = db.pragma(`table_info(${tableName})`);
|
|
@@ -18015,13 +18241,120 @@ function getChatDbMigrations(deps) {
|
|
|
18015
18241
|
db.exec("CREATE INDEX IF NOT EXISTS idx_session_time ON chat_session(start_ts, end_ts)");
|
|
18016
18242
|
db.exec("CREATE INDEX IF NOT EXISTS idx_context_session ON message_context(session_id)");
|
|
18017
18243
|
}
|
|
18244
|
+
},
|
|
18245
|
+
{
|
|
18246
|
+
version: 6,
|
|
18247
|
+
description: "Rename chat_session index tables to segment terminology",
|
|
18248
|
+
up: (db) => {
|
|
18249
|
+
const hasTable2 = (tableName) => {
|
|
18250
|
+
const row = db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name = ?").get(tableName);
|
|
18251
|
+
return !!row;
|
|
18252
|
+
};
|
|
18253
|
+
db.exec(`
|
|
18254
|
+
DROP INDEX IF EXISTS idx_session_time;
|
|
18255
|
+
DROP INDEX IF EXISTS idx_context_session;
|
|
18256
|
+
`);
|
|
18257
|
+
const hasLegacyChatSession = hasTable2("chat_session");
|
|
18258
|
+
const hasSegment = hasTable2("segment");
|
|
18259
|
+
if (hasLegacyChatSession && !hasSegment) {
|
|
18260
|
+
db.exec("ALTER TABLE chat_session RENAME TO segment");
|
|
18261
|
+
} else if (hasLegacyChatSession && hasSegment) {
|
|
18262
|
+
db.exec(`
|
|
18263
|
+
INSERT OR IGNORE INTO segment (id, start_ts, end_ts, message_count, is_manual, summary)
|
|
18264
|
+
SELECT id, start_ts, end_ts, message_count, is_manual, summary
|
|
18265
|
+
FROM chat_session;
|
|
18266
|
+
DROP TABLE chat_session;
|
|
18267
|
+
`);
|
|
18268
|
+
}
|
|
18269
|
+
if (hasTable2("message_context") && hasColumn2(db, "message_context", "session_id")) {
|
|
18270
|
+
db.exec("ALTER TABLE message_context RENAME COLUMN session_id TO segment_id");
|
|
18271
|
+
}
|
|
18272
|
+
db.exec(`
|
|
18273
|
+
CREATE TABLE IF NOT EXISTS segment (
|
|
18274
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
18275
|
+
start_ts INTEGER NOT NULL,
|
|
18276
|
+
end_ts INTEGER NOT NULL,
|
|
18277
|
+
message_count INTEGER DEFAULT 0,
|
|
18278
|
+
is_manual INTEGER DEFAULT 0,
|
|
18279
|
+
summary TEXT
|
|
18280
|
+
);
|
|
18281
|
+
|
|
18282
|
+
CREATE TABLE IF NOT EXISTS message_context (
|
|
18283
|
+
message_id INTEGER PRIMARY KEY,
|
|
18284
|
+
segment_id INTEGER NOT NULL,
|
|
18285
|
+
topic_id INTEGER
|
|
18286
|
+
);
|
|
18287
|
+
|
|
18288
|
+
CREATE INDEX IF NOT EXISTS idx_segment_time ON segment(start_ts, end_ts);
|
|
18289
|
+
CREATE INDEX IF NOT EXISTS idx_context_segment ON message_context(segment_id);
|
|
18290
|
+
`);
|
|
18291
|
+
}
|
|
18018
18292
|
}
|
|
18019
18293
|
];
|
|
18020
18294
|
}
|
|
18021
18295
|
|
|
18022
18296
|
// ../../packages/node-runtime/src/database-manager.ts
|
|
18023
|
-
import * as
|
|
18024
|
-
import * as
|
|
18297
|
+
import * as fs35 from "fs";
|
|
18298
|
+
import * as path32 from "path";
|
|
18299
|
+
|
|
18300
|
+
// ../../packages/node-runtime/src/better-sqlite3-adapter.ts
|
|
18301
|
+
import Database4 from "better-sqlite3";
|
|
18302
|
+
var BetterSqlitePreparedStatement = class {
|
|
18303
|
+
constructor(stmt) {
|
|
18304
|
+
this.stmt = stmt;
|
|
18305
|
+
this.readonly = stmt.readonly;
|
|
18306
|
+
}
|
|
18307
|
+
stmt;
|
|
18308
|
+
readonly;
|
|
18309
|
+
get(...params) {
|
|
18310
|
+
return this.stmt.get(...params);
|
|
18311
|
+
}
|
|
18312
|
+
all(...params) {
|
|
18313
|
+
return this.stmt.all(...params);
|
|
18314
|
+
}
|
|
18315
|
+
run(...params) {
|
|
18316
|
+
const result = this.stmt.run(...params);
|
|
18317
|
+
return {
|
|
18318
|
+
changes: result.changes,
|
|
18319
|
+
lastInsertRowid: result.lastInsertRowid
|
|
18320
|
+
};
|
|
18321
|
+
}
|
|
18322
|
+
};
|
|
18323
|
+
var BetterSqliteAdapter = class {
|
|
18324
|
+
constructor(db) {
|
|
18325
|
+
this.db = db;
|
|
18326
|
+
this.readonly = db.readonly;
|
|
18327
|
+
}
|
|
18328
|
+
db;
|
|
18329
|
+
readonly;
|
|
18330
|
+
exec(sql) {
|
|
18331
|
+
this.db.exec(sql);
|
|
18332
|
+
}
|
|
18333
|
+
prepare(sql) {
|
|
18334
|
+
return new BetterSqlitePreparedStatement(this.db.prepare(sql));
|
|
18335
|
+
}
|
|
18336
|
+
transaction(fn) {
|
|
18337
|
+
return this.db.transaction(fn)();
|
|
18338
|
+
}
|
|
18339
|
+
pragma(pragma) {
|
|
18340
|
+
return this.db.pragma(pragma);
|
|
18341
|
+
}
|
|
18342
|
+
close() {
|
|
18343
|
+
this.db.close();
|
|
18344
|
+
}
|
|
18345
|
+
};
|
|
18346
|
+
function openBetterSqliteDatabase(filePath, options) {
|
|
18347
|
+
const db = new Database4(filePath, {
|
|
18348
|
+
readonly: options?.readonly ?? false,
|
|
18349
|
+
nativeBinding: options?.nativeBinding
|
|
18350
|
+
});
|
|
18351
|
+
if (!options?.readonly) {
|
|
18352
|
+
db.pragma("journal_mode = WAL");
|
|
18353
|
+
}
|
|
18354
|
+
return new BetterSqliteAdapter(db);
|
|
18355
|
+
}
|
|
18356
|
+
|
|
18357
|
+
// ../../packages/node-runtime/src/database-manager.ts
|
|
18025
18358
|
function createMigrationDeps(overrides) {
|
|
18026
18359
|
return {
|
|
18027
18360
|
tokenizeForFts,
|
|
@@ -18029,25 +18362,32 @@ function createMigrationDeps(overrides) {
|
|
|
18029
18362
|
};
|
|
18030
18363
|
}
|
|
18031
18364
|
var DatabaseManager = class {
|
|
18032
|
-
constructor(pathProvider, options) {
|
|
18365
|
+
constructor(pathProvider, options = {}) {
|
|
18033
18366
|
this.pathProvider = pathProvider;
|
|
18367
|
+
if (!options.runtime && !options.allowMissingRuntimeForTests) {
|
|
18368
|
+
throw new Error("DatabaseManager runtime identity is required for data directory compatibility checks.");
|
|
18369
|
+
}
|
|
18034
18370
|
this.nativeBinding = options?.nativeBinding;
|
|
18035
18371
|
this.migrationDeps = createMigrationDeps(options?.migrationDeps);
|
|
18372
|
+
this.runtime = options?.runtime ?? null;
|
|
18036
18373
|
}
|
|
18037
18374
|
pathProvider;
|
|
18038
18375
|
cache = /* @__PURE__ */ new Map();
|
|
18039
18376
|
nativeBinding;
|
|
18040
18377
|
migrationDeps;
|
|
18378
|
+
runtime;
|
|
18041
18379
|
/**
|
|
18042
18380
|
* Open a session DB (read-only by default, cached).
|
|
18043
18381
|
*/
|
|
18044
18382
|
open(sessionId, options) {
|
|
18383
|
+
this.assertCompatible();
|
|
18045
18384
|
if (this.cache.has(sessionId)) {
|
|
18046
18385
|
return this.cache.get(sessionId);
|
|
18047
18386
|
}
|
|
18048
18387
|
const dbPath = this.getDbPath(sessionId);
|
|
18049
|
-
if (!
|
|
18388
|
+
if (!fs35.existsSync(dbPath)) return null;
|
|
18050
18389
|
this.migrateIfNeeded(dbPath);
|
|
18390
|
+
this.assertCompatible();
|
|
18051
18391
|
const adapter = openBetterSqliteDatabase(dbPath, {
|
|
18052
18392
|
readonly: options?.readonly ?? true,
|
|
18053
18393
|
nativeBinding: this.nativeBinding
|
|
@@ -18061,7 +18401,9 @@ var DatabaseManager = class {
|
|
|
18061
18401
|
nativeBinding: this.nativeBinding
|
|
18062
18402
|
});
|
|
18063
18403
|
try {
|
|
18064
|
-
if (!isChatSessionDb(readonlyAdapter)
|
|
18404
|
+
if (!isChatSessionDb(readonlyAdapter)) return;
|
|
18405
|
+
this.raiseCompatibilityGateIfNeeded(getSchemaVersion(readonlyAdapter));
|
|
18406
|
+
if (!needsMigration(readonlyAdapter, CURRENT_SCHEMA_VERSION)) return;
|
|
18065
18407
|
} finally {
|
|
18066
18408
|
readonlyAdapter.close();
|
|
18067
18409
|
}
|
|
@@ -18071,7 +18413,7 @@ var DatabaseManager = class {
|
|
|
18071
18413
|
});
|
|
18072
18414
|
try {
|
|
18073
18415
|
const migrations = getChatDbMigrations(this.migrationDeps);
|
|
18074
|
-
runMigrations(adapter, migrations);
|
|
18416
|
+
this.runMigrations(adapter, migrations);
|
|
18075
18417
|
} finally {
|
|
18076
18418
|
adapter.close();
|
|
18077
18419
|
}
|
|
@@ -18081,6 +18423,7 @@ var DatabaseManager = class {
|
|
|
18081
18423
|
* Falls back to `open(id, { readonly: false })` if migration is unnecessary.
|
|
18082
18424
|
*/
|
|
18083
18425
|
openWritable(sessionId) {
|
|
18426
|
+
this.assertCompatible();
|
|
18084
18427
|
const existing = this.cache.get(sessionId);
|
|
18085
18428
|
if (existing && !existing.readonly) return existing;
|
|
18086
18429
|
if (existing) {
|
|
@@ -18088,14 +18431,17 @@ var DatabaseManager = class {
|
|
|
18088
18431
|
this.cache.delete(sessionId);
|
|
18089
18432
|
}
|
|
18090
18433
|
const dbPath = this.getDbPath(sessionId);
|
|
18091
|
-
if (!
|
|
18434
|
+
if (!fs35.existsSync(dbPath)) return null;
|
|
18092
18435
|
const adapter = openBetterSqliteDatabase(dbPath, {
|
|
18093
18436
|
readonly: false,
|
|
18094
18437
|
nativeBinding: this.nativeBinding
|
|
18095
18438
|
});
|
|
18096
18439
|
if (needsMigration(adapter, CURRENT_SCHEMA_VERSION)) {
|
|
18097
18440
|
const migrations = getChatDbMigrations(this.migrationDeps);
|
|
18098
|
-
runMigrations(adapter, migrations);
|
|
18441
|
+
this.runMigrations(adapter, migrations);
|
|
18442
|
+
this.assertCompatible();
|
|
18443
|
+
} else {
|
|
18444
|
+
this.raiseCompatibilityGateIfNeeded(getSchemaVersion(adapter));
|
|
18099
18445
|
}
|
|
18100
18446
|
this.cache.set(sessionId, adapter);
|
|
18101
18447
|
return adapter;
|
|
@@ -18123,9 +18469,10 @@ var DatabaseManager = class {
|
|
|
18123
18469
|
* 列举数据库目录下的所有聊天会话 ID
|
|
18124
18470
|
*/
|
|
18125
18471
|
listSessionIds() {
|
|
18472
|
+
this.assertCompatible();
|
|
18126
18473
|
const dbDir = this.pathProvider.getDatabaseDir();
|
|
18127
|
-
if (!
|
|
18128
|
-
return
|
|
18474
|
+
if (!fs35.existsSync(dbDir)) return [];
|
|
18475
|
+
return fs35.readdirSync(dbDir).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", "")).filter((id) => {
|
|
18129
18476
|
const db = this.open(id);
|
|
18130
18477
|
if (!db) return false;
|
|
18131
18478
|
return isChatSessionDb(db);
|
|
@@ -18135,9 +18482,70 @@ var DatabaseManager = class {
|
|
|
18135
18482
|
* 获取数据库文件路径
|
|
18136
18483
|
*/
|
|
18137
18484
|
getDbPath(sessionId) {
|
|
18138
|
-
return
|
|
18485
|
+
return path32.join(this.pathProvider.getDatabaseDir(), `${sessionId}.db`);
|
|
18486
|
+
}
|
|
18487
|
+
openRawSessionDatabase(sessionId, options = {}) {
|
|
18488
|
+
this.assertCompatible();
|
|
18489
|
+
const dbPath = this.getDbPath(sessionId);
|
|
18490
|
+
if (!options.create && !fs35.existsSync(dbPath)) {
|
|
18491
|
+
throw new Error(`Session database not found: ${sessionId}`);
|
|
18492
|
+
}
|
|
18493
|
+
if (!options.readonly) {
|
|
18494
|
+
this.close(sessionId);
|
|
18495
|
+
fs35.mkdirSync(path32.dirname(dbPath), { recursive: true });
|
|
18496
|
+
}
|
|
18497
|
+
const adapter = openBetterSqliteDatabase(dbPath, {
|
|
18498
|
+
readonly: options.readonly ?? false,
|
|
18499
|
+
nativeBinding: this.nativeBinding
|
|
18500
|
+
});
|
|
18501
|
+
if (options.initializeChatTables) {
|
|
18502
|
+
adapter.exec(CHAT_DB_TABLES);
|
|
18503
|
+
}
|
|
18504
|
+
return adapter;
|
|
18505
|
+
}
|
|
18506
|
+
deleteSessionDatabaseFiles(sessionId) {
|
|
18507
|
+
this.close(sessionId);
|
|
18508
|
+
const dbPath = this.getDbPath(sessionId);
|
|
18509
|
+
for (const suffix of ["", "-wal", "-shm"]) {
|
|
18510
|
+
try {
|
|
18511
|
+
const filePath = dbPath + suffix;
|
|
18512
|
+
if (fs35.existsSync(filePath)) fs35.unlinkSync(filePath);
|
|
18513
|
+
} catch {
|
|
18514
|
+
}
|
|
18515
|
+
}
|
|
18516
|
+
}
|
|
18517
|
+
raiseCurrentChatDbCompatibilityGate() {
|
|
18518
|
+
if (!this.runtime) return;
|
|
18519
|
+
raiseChatDbCompatibilityGate(this.pathProvider, this.runtime);
|
|
18520
|
+
}
|
|
18521
|
+
assertCompatible() {
|
|
18522
|
+
if (!this.runtime) return;
|
|
18523
|
+
assertDataDirCompatible(this.pathProvider, this.runtime);
|
|
18524
|
+
}
|
|
18525
|
+
runMigrations(adapter, migrations) {
|
|
18526
|
+
const beforeVersion = getSchemaVersion(adapter);
|
|
18527
|
+
const migrated = runMigrations(adapter, migrations);
|
|
18528
|
+
if (!migrated || !this.runtime) return;
|
|
18529
|
+
const afterVersion = getSchemaVersion(adapter);
|
|
18530
|
+
if (shouldRaiseCompatibilityGate(beforeVersion, afterVersion)) {
|
|
18531
|
+
this.raiseCurrentChatDbCompatibilityGate();
|
|
18532
|
+
}
|
|
18533
|
+
}
|
|
18534
|
+
raiseCompatibilityGateIfNeeded(schemaVersion) {
|
|
18535
|
+
if (!this.runtime) return;
|
|
18536
|
+
if (shouldRepairCompatibilityGate(schemaVersion)) {
|
|
18537
|
+
this.raiseCurrentChatDbCompatibilityGate();
|
|
18538
|
+
}
|
|
18139
18539
|
}
|
|
18140
18540
|
};
|
|
18541
|
+
function shouldRaiseCompatibilityGate(beforeVersion, afterVersion) {
|
|
18542
|
+
return CHAT_DB_COMPATIBILITY_RAISES.some(
|
|
18543
|
+
(compatibilityRaise) => beforeVersion < compatibilityRaise.migrationVersion && afterVersion >= compatibilityRaise.migrationVersion
|
|
18544
|
+
);
|
|
18545
|
+
}
|
|
18546
|
+
function shouldRepairCompatibilityGate(schemaVersion) {
|
|
18547
|
+
return CHAT_DB_COMPATIBILITY_RAISES.some((compatibilityRaise) => schemaVersion >= compatibilityRaise.migrationVersion);
|
|
18548
|
+
}
|
|
18141
18549
|
|
|
18142
18550
|
// ../../packages/node-runtime/src/jieba-nlp-provider.ts
|
|
18143
18551
|
function createJiebaNlpProvider(dictType = "default") {
|
|
@@ -18183,7 +18591,7 @@ function exportFilterResultToMarkdown(params, deps, writer) {
|
|
|
18183
18591
|
} else {
|
|
18184
18592
|
writer.write(`- Mode: session filter
|
|
18185
18593
|
`);
|
|
18186
|
-
writer.write(`- Selected sessions: ${params.
|
|
18594
|
+
writer.write(`- Selected sessions: ${params.segmentIds?.length || 0}
|
|
18187
18595
|
`);
|
|
18188
18596
|
}
|
|
18189
18597
|
writer.write("\n");
|
|
@@ -18341,7 +18749,7 @@ function exportConditionMode(db, params, writer, progress) {
|
|
|
18341
18749
|
return { totalMessages, blockIndex };
|
|
18342
18750
|
}
|
|
18343
18751
|
function exportSessionMode(db, params, writer, progress) {
|
|
18344
|
-
if (!params.
|
|
18752
|
+
if (!params.segmentIds || params.segmentIds.length === 0) {
|
|
18345
18753
|
writer.write(`## Statistics
|
|
18346
18754
|
|
|
18347
18755
|
- No sessions selected
|
|
@@ -18352,17 +18760,17 @@ function exportSessionMode(db, params, writer, progress) {
|
|
|
18352
18760
|
progress?.({
|
|
18353
18761
|
stage: "preparing",
|
|
18354
18762
|
currentBlock: 0,
|
|
18355
|
-
totalBlocks: params.
|
|
18763
|
+
totalBlocks: params.segmentIds.length,
|
|
18356
18764
|
percentage: 10,
|
|
18357
|
-
message: `Preparing to export ${params.
|
|
18765
|
+
message: `Preparing to export ${params.segmentIds.length} sessions...`
|
|
18358
18766
|
});
|
|
18359
18767
|
const sessionsSql = `
|
|
18360
18768
|
SELECT id, start_ts as startTs, end_ts as endTs
|
|
18361
|
-
FROM
|
|
18362
|
-
WHERE id IN (${params.
|
|
18769
|
+
FROM segment
|
|
18770
|
+
WHERE id IN (${params.segmentIds.map(() => "?").join(",")})
|
|
18363
18771
|
ORDER BY start_ts ASC
|
|
18364
18772
|
`;
|
|
18365
|
-
const sessions = db.prepare(sessionsSql).all(...params.
|
|
18773
|
+
const sessions = db.prepare(sessionsSql).all(...params.segmentIds);
|
|
18366
18774
|
const totalBlocks = sessions.length;
|
|
18367
18775
|
writer.write(`## Statistics
|
|
18368
18776
|
|
|
@@ -18380,7 +18788,7 @@ function exportSessionMode(db, params, writer, progress) {
|
|
|
18380
18788
|
FROM message_context mc
|
|
18381
18789
|
JOIN message msg ON msg.id = mc.message_id
|
|
18382
18790
|
JOIN member m ON msg.sender_id = m.id
|
|
18383
|
-
WHERE mc.
|
|
18791
|
+
WHERE mc.segment_id = ?
|
|
18384
18792
|
ORDER BY msg.ts ASC
|
|
18385
18793
|
`;
|
|
18386
18794
|
let totalMessages = 0;
|
|
@@ -18413,8 +18821,8 @@ function exportSessionMode(db, params, writer, progress) {
|
|
|
18413
18821
|
}
|
|
18414
18822
|
|
|
18415
18823
|
// ../../packages/node-runtime/src/preferences.ts
|
|
18416
|
-
import * as
|
|
18417
|
-
import * as
|
|
18824
|
+
import * as fs36 from "fs";
|
|
18825
|
+
import * as path33 from "path";
|
|
18418
18826
|
var DEFAULTS = {
|
|
18419
18827
|
pinnedSessionIds: [],
|
|
18420
18828
|
aiPreprocessConfig: {
|
|
@@ -18456,13 +18864,13 @@ var PreferencesManager = class {
|
|
|
18456
18864
|
filePath;
|
|
18457
18865
|
cache = null;
|
|
18458
18866
|
constructor(systemDir) {
|
|
18459
|
-
this.filePath =
|
|
18867
|
+
this.filePath = path33.join(systemDir, "preferences.json");
|
|
18460
18868
|
}
|
|
18461
18869
|
load() {
|
|
18462
18870
|
if (this.cache) return this.cache;
|
|
18463
18871
|
try {
|
|
18464
|
-
if (
|
|
18465
|
-
const raw =
|
|
18872
|
+
if (fs36.existsSync(this.filePath)) {
|
|
18873
|
+
const raw = fs36.readFileSync(this.filePath, "utf-8");
|
|
18466
18874
|
const parsed = JSON.parse(raw);
|
|
18467
18875
|
const migrated = this.migrateLegacyDesensitizeRules(parsed, raw);
|
|
18468
18876
|
this.cache = this.mergeDefaults(migrated.preferences);
|
|
@@ -18574,21 +18982,21 @@ var PreferencesManager = class {
|
|
|
18574
18982
|
};
|
|
18575
18983
|
}
|
|
18576
18984
|
backupLegacyPreferences(rawContent) {
|
|
18577
|
-
const backupDir =
|
|
18578
|
-
if (!
|
|
18579
|
-
|
|
18985
|
+
const backupDir = path33.join(path33.dirname(this.filePath), "backups");
|
|
18986
|
+
if (!fs36.existsSync(backupDir)) {
|
|
18987
|
+
fs36.mkdirSync(backupDir, { recursive: true });
|
|
18580
18988
|
}
|
|
18581
18989
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
18582
|
-
const backupPath =
|
|
18583
|
-
|
|
18990
|
+
const backupPath = path33.join(backupDir, `preferences-pre-desensitize-groups-${timestamp}.json`);
|
|
18991
|
+
fs36.writeFileSync(backupPath, rawContent, "utf-8");
|
|
18584
18992
|
console.info(`[Preferences] Backed up legacy desensitize rules to ${backupPath}`);
|
|
18585
18993
|
}
|
|
18586
18994
|
writePreferences(preferences) {
|
|
18587
|
-
const dir =
|
|
18588
|
-
if (!
|
|
18589
|
-
|
|
18995
|
+
const dir = path33.dirname(this.filePath);
|
|
18996
|
+
if (!fs36.existsSync(dir)) {
|
|
18997
|
+
fs36.mkdirSync(dir, { recursive: true });
|
|
18590
18998
|
}
|
|
18591
|
-
|
|
18999
|
+
fs36.writeFileSync(this.filePath, JSON.stringify(preferences, null, 2), "utf-8");
|
|
18592
19000
|
}
|
|
18593
19001
|
/**
|
|
18594
19002
|
* Deep merge: arrays are replaced (not concatenated), objects are merged.
|
|
@@ -18708,8 +19116,8 @@ function* serializeChatLabToJsonl(data) {
|
|
|
18708
19116
|
}
|
|
18709
19117
|
|
|
18710
19118
|
// ../../packages/node-runtime/src/merger/temp-db.ts
|
|
18711
|
-
import * as
|
|
18712
|
-
import * as
|
|
19119
|
+
import * as fs37 from "fs";
|
|
19120
|
+
import * as path34 from "path";
|
|
18713
19121
|
var TEMP_DB_SCHEMA = `
|
|
18714
19122
|
CREATE TABLE IF NOT EXISTS meta (
|
|
18715
19123
|
name TEXT NOT NULL,
|
|
@@ -18954,21 +19362,21 @@ function exportSessionToJson(db) {
|
|
|
18954
19362
|
}
|
|
18955
19363
|
function deleteTempDatabase(dbPath) {
|
|
18956
19364
|
try {
|
|
18957
|
-
if (
|
|
19365
|
+
if (fs37.existsSync(dbPath)) fs37.unlinkSync(dbPath);
|
|
18958
19366
|
const walPath = dbPath + "-wal";
|
|
18959
19367
|
const shmPath = dbPath + "-shm";
|
|
18960
|
-
if (
|
|
18961
|
-
if (
|
|
19368
|
+
if (fs37.existsSync(walPath)) fs37.unlinkSync(walPath);
|
|
19369
|
+
if (fs37.existsSync(shmPath)) fs37.unlinkSync(shmPath);
|
|
18962
19370
|
} catch {
|
|
18963
19371
|
}
|
|
18964
19372
|
}
|
|
18965
19373
|
function cleanupTempDatabases(tempDir) {
|
|
18966
19374
|
try {
|
|
18967
|
-
if (!
|
|
18968
|
-
const files =
|
|
19375
|
+
if (!fs37.existsSync(tempDir)) return;
|
|
19376
|
+
const files = fs37.readdirSync(tempDir);
|
|
18969
19377
|
for (const file of files) {
|
|
18970
19378
|
if (file.startsWith("merge_") && file.endsWith(".db")) {
|
|
18971
|
-
deleteTempDatabase(
|
|
19379
|
+
deleteTempDatabase(path34.join(tempDir, file));
|
|
18972
19380
|
}
|
|
18973
19381
|
}
|
|
18974
19382
|
} catch {
|
|
@@ -19129,16 +19537,16 @@ __export(summary_service_exports, {
|
|
|
19129
19537
|
function buildSummaryDeps(db, llmConfig, deps) {
|
|
19130
19538
|
const piModel = deps.buildPiModel(llmConfig);
|
|
19131
19539
|
return {
|
|
19132
|
-
loadMessages(
|
|
19133
|
-
const data =
|
|
19540
|
+
loadMessages(segmentId, limit = 500) {
|
|
19541
|
+
const data = getSegmentMessages(db, segmentId, limit);
|
|
19134
19542
|
if (!data) return null;
|
|
19135
19543
|
return data.messages.map((m) => ({ senderName: m.senderName, content: m.content }));
|
|
19136
19544
|
},
|
|
19137
|
-
saveSummary(
|
|
19138
|
-
|
|
19545
|
+
saveSummary(segmentId, summary) {
|
|
19546
|
+
saveSegmentSummary(db, segmentId, summary);
|
|
19139
19547
|
},
|
|
19140
|
-
getSummary(
|
|
19141
|
-
return
|
|
19548
|
+
getSummary(segmentId) {
|
|
19549
|
+
return getSegmentSummary(db, segmentId);
|
|
19142
19550
|
},
|
|
19143
19551
|
async llmComplete(systemPrompt, userPrompt, options) {
|
|
19144
19552
|
const result = await completeSimple4(
|
|
@@ -19154,14 +19562,14 @@ function buildSummaryDeps(db, llmConfig, deps) {
|
|
|
19154
19562
|
t: (key) => key
|
|
19155
19563
|
};
|
|
19156
19564
|
}
|
|
19157
|
-
async function generateSummary(adapter, sessionId,
|
|
19565
|
+
async function generateSummary(adapter, sessionId, segmentId, serviceDeps, options) {
|
|
19158
19566
|
const llmConfig = serviceDeps.getLlmConfig();
|
|
19159
19567
|
if (!llmConfig) {
|
|
19160
19568
|
return { success: false, error: "No LLM configuration available" };
|
|
19161
19569
|
}
|
|
19162
19570
|
const db = adapter.ensureWritable(sessionId);
|
|
19163
19571
|
const deps = buildSummaryDeps(db, llmConfig, serviceDeps);
|
|
19164
|
-
return generateSessionSummary(deps,
|
|
19572
|
+
return generateSessionSummary(deps, segmentId, options);
|
|
19165
19573
|
}
|
|
19166
19574
|
async function generateAllSummaries(adapter, sessionId, serviceDeps, options) {
|
|
19167
19575
|
const llmConfig = serviceDeps.getLlmConfig();
|
|
@@ -19180,17 +19588,17 @@ async function generateAllSummaries(adapter, sessionId, serviceDeps, options) {
|
|
|
19180
19588
|
}
|
|
19181
19589
|
return { success, failed, total: chatSessions.length };
|
|
19182
19590
|
}
|
|
19183
|
-
function checkCanGenerate(adapter, sessionId,
|
|
19591
|
+
function checkCanGenerate(adapter, sessionId, segmentIds) {
|
|
19184
19592
|
const db = adapter.ensureReadonly(sessionId);
|
|
19185
19593
|
const deps = {
|
|
19186
|
-
loadMessages(
|
|
19187
|
-
const data =
|
|
19594
|
+
loadMessages(segmentId, limit = 500) {
|
|
19595
|
+
const data = getSegmentMessages(db, segmentId, limit);
|
|
19188
19596
|
if (!data) return null;
|
|
19189
19597
|
return data.messages.map((m) => ({ senderName: m.senderName, content: m.content }));
|
|
19190
19598
|
},
|
|
19191
19599
|
t: (key) => key
|
|
19192
19600
|
};
|
|
19193
|
-
const resultMap = checkSessionsCanGenerateSummary(deps,
|
|
19601
|
+
const resultMap = checkSessionsCanGenerateSummary(deps, segmentIds);
|
|
19194
19602
|
const result = {};
|
|
19195
19603
|
for (const [id, info] of resultMap) {
|
|
19196
19604
|
result[id] = info;
|
|
@@ -19224,7 +19632,7 @@ function exportMarkdown(adapter, params) {
|
|
|
19224
19632
|
}
|
|
19225
19633
|
|
|
19226
19634
|
// ../../packages/node-runtime/src/services/adapters/database-manager-adapter.ts
|
|
19227
|
-
import * as
|
|
19635
|
+
import * as fs38 from "fs";
|
|
19228
19636
|
function createDatabaseManagerAdapter(dbManager) {
|
|
19229
19637
|
return {
|
|
19230
19638
|
listSessionIds: () => dbManager.listSessionIds(),
|
|
@@ -19235,8 +19643,8 @@ function createDatabaseManagerAdapter(dbManager) {
|
|
|
19235
19643
|
deleteSessionFile(sessionId) {
|
|
19236
19644
|
dbManager.close(sessionId);
|
|
19237
19645
|
const dbPath = dbManager.getDbPath(sessionId);
|
|
19238
|
-
if (!
|
|
19239
|
-
|
|
19646
|
+
if (!fs38.existsSync(dbPath)) return false;
|
|
19647
|
+
fs38.unlinkSync(dbPath);
|
|
19240
19648
|
return true;
|
|
19241
19649
|
},
|
|
19242
19650
|
ensureReadonly(sessionId) {
|
|
@@ -19257,8 +19665,8 @@ function createDatabaseManagerAdapter(dbManager) {
|
|
|
19257
19665
|
}
|
|
19258
19666
|
|
|
19259
19667
|
// ../../packages/node-runtime/src/services/merge-cache.ts
|
|
19260
|
-
import * as
|
|
19261
|
-
import * as
|
|
19668
|
+
import * as fs39 from "fs";
|
|
19669
|
+
import * as path35 from "path";
|
|
19262
19670
|
import * as crypto from "crypto";
|
|
19263
19671
|
var MergeSessionCache = class {
|
|
19264
19672
|
cache = /* @__PURE__ */ new Map();
|
|
@@ -19267,15 +19675,15 @@ var MergeSessionCache = class {
|
|
|
19267
19675
|
constructor(pathProvider, options) {
|
|
19268
19676
|
this.tempDir = pathProvider.getTempDir();
|
|
19269
19677
|
this.nativeBinding = options?.nativeBinding;
|
|
19270
|
-
if (!
|
|
19271
|
-
|
|
19678
|
+
if (!fs39.existsSync(this.tempDir)) {
|
|
19679
|
+
fs39.mkdirSync(this.tempDir, { recursive: true });
|
|
19272
19680
|
}
|
|
19273
19681
|
}
|
|
19274
19682
|
generateTempDbPath(filename) {
|
|
19275
19683
|
const ts = Date.now();
|
|
19276
19684
|
const rand = Math.random().toString(36).slice(2, 8);
|
|
19277
19685
|
const safeName = filename.replace(/[/\\?%*:|"<>]/g, "_").slice(0, 40);
|
|
19278
|
-
return
|
|
19686
|
+
return path35.join(this.tempDir, `merge_${safeName}_${ts}_${rand}.db`);
|
|
19279
19687
|
}
|
|
19280
19688
|
/** Store a parsed file's temp DB and return a handle for subsequent requests. */
|
|
19281
19689
|
store(filename, tempDbPath) {
|
|
@@ -19286,7 +19694,7 @@ var MergeSessionCache = class {
|
|
|
19286
19694
|
/** Open a TempDbReader for a given handle. Caller must close the reader. */
|
|
19287
19695
|
openReader(handle) {
|
|
19288
19696
|
const entry = this.cache.get(handle);
|
|
19289
|
-
if (!entry || !
|
|
19697
|
+
if (!entry || !fs39.existsSync(entry.tempDbPath)) return null;
|
|
19290
19698
|
const adapter = openBetterSqliteDatabase(entry.tempDbPath, {
|
|
19291
19699
|
readonly: true,
|
|
19292
19700
|
nativeBinding: this.nativeBinding
|
|
@@ -19339,7 +19747,6 @@ export {
|
|
|
19339
19747
|
writeAuthProfile,
|
|
19340
19748
|
MigrationRunner,
|
|
19341
19749
|
ALL_MIGRATIONS,
|
|
19342
|
-
openBetterSqliteDatabase,
|
|
19343
19750
|
writeParseResultToDb,
|
|
19344
19751
|
getTimeRange,
|
|
19345
19752
|
getAvailableYears,
|
|
@@ -19356,9 +19763,9 @@ export {
|
|
|
19356
19763
|
getSessionOverview,
|
|
19357
19764
|
getDatabaseSchema,
|
|
19358
19765
|
getChatOverview,
|
|
19359
|
-
|
|
19360
|
-
|
|
19361
|
-
|
|
19766
|
+
searchSegments,
|
|
19767
|
+
getSegmentMessages,
|
|
19768
|
+
getSegmentSummaries,
|
|
19362
19769
|
generateSessionIndex,
|
|
19363
19770
|
generateIncrementalSessionIndex,
|
|
19364
19771
|
queryMessages,
|
|
@@ -19387,6 +19794,7 @@ export {
|
|
|
19387
19794
|
isNewerStableVersion,
|
|
19388
19795
|
buildChartPayload,
|
|
19389
19796
|
POS_TAG_DEFINITIONS,
|
|
19797
|
+
normalizeBuiltinToolNames,
|
|
19390
19798
|
BUILTIN_TOOL_CATALOG,
|
|
19391
19799
|
BUILTIN_PROVIDERS,
|
|
19392
19800
|
BUILTIN_MODELS,
|
|
@@ -19394,7 +19802,6 @@ export {
|
|
|
19394
19802
|
stripAvatarFields,
|
|
19395
19803
|
generateMessageKey,
|
|
19396
19804
|
buildMemberIdMap,
|
|
19397
|
-
CHAT_DB_TABLES,
|
|
19398
19805
|
CHAT_DB_SCHEMA,
|
|
19399
19806
|
FTS_TABLE_SCHEMA,
|
|
19400
19807
|
detectFormat,
|
|
@@ -19421,7 +19828,7 @@ export {
|
|
|
19421
19828
|
formatAIError,
|
|
19422
19829
|
parseAssistantFile,
|
|
19423
19830
|
AssistantManager,
|
|
19424
|
-
|
|
19831
|
+
AIChatManager,
|
|
19425
19832
|
initTokenizer,
|
|
19426
19833
|
countMessagesTokens,
|
|
19427
19834
|
SkillManagerCore,
|
|
@@ -19459,6 +19866,8 @@ export {
|
|
|
19459
19866
|
applyPendingNodeDataDirMigrationIfNeeded,
|
|
19460
19867
|
NodePathProvider,
|
|
19461
19868
|
getDefaultNodeUserDataDir,
|
|
19869
|
+
DataDirCompatibilityError,
|
|
19870
|
+
assertDataDirCompatible,
|
|
19462
19871
|
DatabaseManager,
|
|
19463
19872
|
createJiebaNlpProvider,
|
|
19464
19873
|
PreferencesManager,
|
|
@@ -19475,4 +19884,4 @@ export {
|
|
|
19475
19884
|
createDatabaseManagerAdapter,
|
|
19476
19885
|
MergeSessionCache
|
|
19477
19886
|
};
|
|
19478
|
-
//# sourceMappingURL=chunk-
|
|
19887
|
+
//# sourceMappingURL=chunk-7VG6QGQ2.mjs.map
|