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
|
@@ -5,48 +5,29 @@ const require = __createRequire(import.meta.url);
|
|
|
5
5
|
const __filename = __fileURLToPath(import.meta.url);
|
|
6
6
|
const __dirname = __pathDirname(__filename);
|
|
7
7
|
import {
|
|
8
|
-
|
|
8
|
+
DataDirCompatibilityError,
|
|
9
9
|
analyzeIncrementalImport,
|
|
10
10
|
analyzeNewImport,
|
|
11
11
|
generateIncrementalSessionIndex,
|
|
12
12
|
generateSessionIndex,
|
|
13
13
|
incrementalImport,
|
|
14
|
-
openBetterSqliteDatabase,
|
|
15
14
|
streamingImport
|
|
16
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-7VG6QGQ2.mjs";
|
|
17
16
|
|
|
18
17
|
// src/import/stream-import.ts
|
|
19
|
-
import * as fs from "fs";
|
|
20
|
-
import * as path from "path";
|
|
21
18
|
import * as crypto from "crypto";
|
|
22
19
|
function generateSessionId() {
|
|
23
20
|
const ts = Date.now();
|
|
24
21
|
const rand = crypto.randomBytes(4).toString("hex");
|
|
25
22
|
return `chat_${ts}_${rand}`;
|
|
26
23
|
}
|
|
27
|
-
function resolveNativeBinding(dbManager) {
|
|
28
|
-
return dbManager.nativeBinding;
|
|
29
|
-
}
|
|
30
24
|
function buildStreamImportDeps(dbManager, onProgress) {
|
|
31
|
-
const nativeBinding = resolveNativeBinding(dbManager);
|
|
32
25
|
return {
|
|
33
26
|
openDatabase(sessionId) {
|
|
34
|
-
|
|
35
|
-
const dir = path.dirname(dbPath);
|
|
36
|
-
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
37
|
-
const db = openBetterSqliteDatabase(dbPath, { nativeBinding });
|
|
38
|
-
db.exec(CHAT_DB_TABLES);
|
|
39
|
-
return db;
|
|
27
|
+
return dbManager.openRawSessionDatabase(sessionId, { create: true, initializeChatTables: true });
|
|
40
28
|
},
|
|
41
29
|
deleteDatabase(sessionId) {
|
|
42
|
-
|
|
43
|
-
for (const suffix of ["", "-wal", "-shm"]) {
|
|
44
|
-
try {
|
|
45
|
-
const p = dbPath + suffix;
|
|
46
|
-
if (fs.existsSync(p)) fs.unlinkSync(p);
|
|
47
|
-
} catch {
|
|
48
|
-
}
|
|
49
|
-
}
|
|
30
|
+
dbManager.deleteSessionDatabaseFiles(sessionId);
|
|
50
31
|
},
|
|
51
32
|
onProgress: onProgress ?? (() => {
|
|
52
33
|
}),
|
|
@@ -59,6 +40,9 @@ function buildStreamImportDeps(dbManager, onProgress) {
|
|
|
59
40
|
generateSessionId
|
|
60
41
|
};
|
|
61
42
|
}
|
|
43
|
+
function deleteSessionDatabase(dbManager, sessionId) {
|
|
44
|
+
dbManager.deleteSessionDatabaseFiles(sessionId);
|
|
45
|
+
}
|
|
62
46
|
async function streamImport(dbManager, filePath, options) {
|
|
63
47
|
const { formatId, chatIndex, onProgress } = options || {};
|
|
64
48
|
const formatOptions = {};
|
|
@@ -101,17 +85,29 @@ async function streamImport(dbManager, filePath, options) {
|
|
|
101
85
|
} : () => {
|
|
102
86
|
};
|
|
103
87
|
const deps = buildStreamImportDeps(dbManager, progressAdapter);
|
|
104
|
-
|
|
88
|
+
const result = await streamingImport(filePath, deps, formatOptions);
|
|
89
|
+
if (!result.success || !result.sessionId) return result;
|
|
90
|
+
try {
|
|
91
|
+
dbManager.raiseCurrentChatDbCompatibilityGate();
|
|
92
|
+
} catch (error) {
|
|
93
|
+
deleteSessionDatabase(dbManager, result.sessionId);
|
|
94
|
+
return {
|
|
95
|
+
success: false,
|
|
96
|
+
error: error instanceof Error ? error.message : String(error),
|
|
97
|
+
diagnostics: result.diagnostics
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
return result;
|
|
105
101
|
}
|
|
106
|
-
function buildIncrementalDeps(dbManager, onProgress) {
|
|
107
|
-
const nativeBinding = resolveNativeBinding(dbManager);
|
|
102
|
+
function buildIncrementalDeps(dbManager, onProgress, onCompatibilityError) {
|
|
108
103
|
return {
|
|
109
104
|
openDatabase(sessionId, readonly) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
105
|
+
try {
|
|
106
|
+
return dbManager.openRawSessionDatabase(sessionId, { readonly: readonly ?? false });
|
|
107
|
+
} catch (error) {
|
|
108
|
+
if (error instanceof DataDirCompatibilityError) onCompatibilityError?.(error);
|
|
109
|
+
throw error;
|
|
113
110
|
}
|
|
114
|
-
return openBetterSqliteDatabase(dbPath, { readonly: readonly ?? false, nativeBinding });
|
|
115
111
|
},
|
|
116
112
|
onProgress: onProgress ?? (() => {
|
|
117
113
|
}),
|
|
@@ -125,10 +121,40 @@ function buildIncrementalDeps(dbManager, onProgress) {
|
|
|
125
121
|
}
|
|
126
122
|
async function incrementalImport2(dbManager, sessionId, filePath, options) {
|
|
127
123
|
const { onProgress, ...importOpts } = options || {};
|
|
128
|
-
|
|
124
|
+
let compatibilityError = null;
|
|
125
|
+
const result = await incrementalImport(
|
|
126
|
+
sessionId,
|
|
127
|
+
filePath,
|
|
128
|
+
buildIncrementalDeps(dbManager, onProgress, (error) => {
|
|
129
|
+
compatibilityError = error;
|
|
130
|
+
}),
|
|
131
|
+
importOpts
|
|
132
|
+
);
|
|
133
|
+
if (compatibilityError) throw compatibilityError;
|
|
134
|
+
if (!result.success) return result;
|
|
135
|
+
try {
|
|
136
|
+
dbManager.raiseCurrentChatDbCompatibilityGate();
|
|
137
|
+
} catch (error) {
|
|
138
|
+
return {
|
|
139
|
+
...result,
|
|
140
|
+
success: false,
|
|
141
|
+
newMessageCount: 0,
|
|
142
|
+
error: error instanceof Error ? error.message : String(error)
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
return result;
|
|
129
146
|
}
|
|
130
147
|
async function analyzeIncrementalImport2(dbManager, sessionId, filePath, onProgress) {
|
|
131
|
-
|
|
148
|
+
let compatibilityError = null;
|
|
149
|
+
const result = await analyzeIncrementalImport(
|
|
150
|
+
sessionId,
|
|
151
|
+
filePath,
|
|
152
|
+
buildIncrementalDeps(dbManager, onProgress, (error) => {
|
|
153
|
+
compatibilityError = error;
|
|
154
|
+
})
|
|
155
|
+
);
|
|
156
|
+
if (compatibilityError) throw compatibilityError;
|
|
157
|
+
return result;
|
|
132
158
|
}
|
|
133
159
|
async function analyzeNewImport2(filePath, onProgress) {
|
|
134
160
|
return analyzeNewImport(filePath, onProgress ?? (() => {
|
|
@@ -141,4 +167,4 @@ export {
|
|
|
141
167
|
analyzeIncrementalImport2 as analyzeIncrementalImport,
|
|
142
168
|
analyzeNewImport2 as analyzeNewImport
|
|
143
169
|
};
|
|
144
|
-
//# sourceMappingURL=chunk-
|
|
170
|
+
//# sourceMappingURL=chunk-PDQFSQO6.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/import/stream-import.ts"],"sourcesContent":["/**\n * Server/CLI streaming import — adapter for @openchatlab/node-runtime StreamingImporter.\n *\n * Replaces the old buffered-in-memory approach with the same high-performance\n * streaming pipeline used by Electron (batched transactions, deferred indexes,\n * nickname history, FTS, format fallback).\n */\n\nimport type { DatabaseManager } from '@openchatlab/node-runtime'\nimport {\n DataDirCompatibilityError,\n streamingImport,\n analyzeNewImport as sharedAnalyzeNewImport,\n analyzeIncrementalImport as sharedAnalyzeIncremental,\n incrementalImport as sharedIncrementalImport,\n} from '@openchatlab/node-runtime'\nimport { generateSessionIndex, generateIncrementalSessionIndex } from '@openchatlab/core'\nimport type {\n StreamImportResult,\n StreamImportDeps,\n ImportProgressCallback,\n IncrementalImportResult,\n IncrementalAnalyzeResult,\n IncrementalImportDeps,\n ImportOptions,\n AnalyzeNewImportResult,\n} from '@openchatlab/node-runtime'\nimport {\n detectFormat as parserDetectFormat,\n detectAllFormats,\n getFormatFeatureById,\n getSupportedFormats as parserGetSupportedFormats,\n scanMultiChatFile as parserScanMultiChatFile,\n findEntryFileInDirectory,\n type FormatFeature,\n type MultiChatInfo,\n type ParseProgress,\n} from '@openchatlab/parser'\nimport * as crypto from 'crypto'\n\n// ==================== Legacy progress interface (for SSE routes) ====================\n\nexport interface StreamImportProgress {\n stage: 'detecting' | 'parsing' | 'saving' | 'indexing' | 'done' | 'error'\n progress: number\n message: string\n bytesRead?: number\n totalBytes?: number\n messagesProcessed?: number\n}\n\nexport interface StreamImportOptions {\n formatId?: string\n chatIndex?: number\n nativeBinding?: string\n onProgress?: (progress: StreamImportProgress) => void\n}\n\nfunction generateSessionId(): string {\n const ts = Date.now()\n const rand = crypto.randomBytes(4).toString('hex')\n return `chat_${ts}_${rand}`\n}\n\nfunction buildStreamImportDeps(dbManager: DatabaseManager, onProgress?: ImportProgressCallback): StreamImportDeps {\n return {\n openDatabase(sessionId: string) {\n return dbManager.openRawSessionDatabase(sessionId, { create: true, initializeChatTables: true })\n },\n deleteDatabase(sessionId: string) {\n dbManager.deleteSessionDatabaseFiles(sessionId)\n },\n onProgress: onProgress ?? (() => {}),\n postImportHook(db) {\n try {\n generateSessionIndex(db)\n } catch {\n /* non-fatal: frontend can regenerate via generate-index route */\n }\n },\n generateSessionId,\n }\n}\n\nfunction deleteSessionDatabase(dbManager: DatabaseManager, sessionId: string): void {\n dbManager.deleteSessionDatabaseFiles(sessionId)\n}\n\n/**\n * High-performance streaming import: parse a file and write to DB\n * with batched transactions, deferred indexes, and FTS.\n */\nexport async function streamImport(\n dbManager: DatabaseManager,\n filePath: string,\n options?: StreamImportOptions\n): Promise<StreamImportResult> {\n const { formatId, chatIndex, onProgress } = options || {}\n\n const formatOptions: Record<string, unknown> = {}\n if (formatId) formatOptions.formatId = formatId\n if (chatIndex !== undefined) formatOptions.chatIndex = chatIndex\n\n const progressAdapter: ImportProgressCallback = onProgress\n ? (progress) => {\n let stage: StreamImportProgress['stage'] = 'parsing'\n let pct = 0\n switch (progress.stage) {\n case 'detecting':\n stage = 'detecting'\n pct = 5\n break\n case 'parsing':\n stage = 'parsing'\n pct = Math.min(Math.round(progress.percentage * 0.7), 70)\n break\n case 'importing':\n case 'saving':\n stage = 'saving'\n pct = 80\n break\n case 'done':\n stage = 'done'\n pct = 100\n break\n case 'error':\n stage = 'error'\n pct = 0\n break\n }\n onProgress({\n stage,\n progress: pct,\n message: progress.message || '',\n bytesRead: progress.bytesRead,\n totalBytes: progress.totalBytes,\n messagesProcessed: progress.messagesProcessed,\n })\n }\n : () => {}\n\n const deps = buildStreamImportDeps(dbManager, progressAdapter)\n const result = await streamingImport(filePath, deps, formatOptions)\n if (!result.success || !result.sessionId) return result\n\n try {\n dbManager.raiseCurrentChatDbCompatibilityGate()\n } catch (error) {\n deleteSessionDatabase(dbManager, result.sessionId)\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n diagnostics: result.diagnostics,\n }\n }\n\n return result\n}\n\n// ==================== Incremental import ====================\n\nfunction buildIncrementalDeps(\n dbManager: DatabaseManager,\n onProgress?: ImportProgressCallback,\n onCompatibilityError?: (error: DataDirCompatibilityError) => void\n): IncrementalImportDeps {\n return {\n openDatabase(sessionId: string, readonly?: boolean) {\n try {\n return dbManager.openRawSessionDatabase(sessionId, { readonly: readonly ?? false })\n } catch (error) {\n if (error instanceof DataDirCompatibilityError) onCompatibilityError?.(error)\n throw error\n }\n },\n onProgress: onProgress ?? (() => {}),\n postImportHook(db) {\n try {\n generateIncrementalSessionIndex(db)\n } catch {\n /* non-fatal */\n }\n },\n }\n}\n\nexport async function incrementalImport(\n dbManager: DatabaseManager,\n sessionId: string,\n filePath: string,\n options?: ImportOptions & { onProgress?: ImportProgressCallback }\n): Promise<IncrementalImportResult> {\n const { onProgress, ...importOpts } = options || {}\n let compatibilityError: DataDirCompatibilityError | null = null\n const result = await sharedIncrementalImport(\n sessionId,\n filePath,\n buildIncrementalDeps(dbManager, onProgress, (error) => {\n compatibilityError = error\n }),\n importOpts\n )\n if (compatibilityError) throw compatibilityError\n if (!result.success) return result\n\n try {\n dbManager.raiseCurrentChatDbCompatibilityGate()\n } catch (error) {\n return {\n ...result,\n success: false,\n newMessageCount: 0,\n error: error instanceof Error ? error.message : String(error),\n }\n }\n\n return result\n}\n\nexport async function analyzeIncrementalImport(\n dbManager: DatabaseManager,\n sessionId: string,\n filePath: string,\n onProgress?: ImportProgressCallback\n): Promise<IncrementalAnalyzeResult> {\n let compatibilityError: DataDirCompatibilityError | null = null\n const result = await sharedAnalyzeIncremental(\n sessionId,\n filePath,\n buildIncrementalDeps(dbManager, onProgress, (error) => {\n compatibilityError = error\n })\n )\n if (compatibilityError) throw compatibilityError\n return result\n}\n\nexport async function analyzeNewImport(\n filePath: string,\n onProgress?: ImportProgressCallback\n): Promise<AnalyzeNewImportResult> {\n return sharedAnalyzeNewImport(filePath, onProgress ?? (() => {}))\n}\n\n// ==================== Re-exports from parser ====================\n\nexport {\n parserDetectFormat as detectFormat,\n detectAllFormats,\n getFormatFeatureById,\n parserGetSupportedFormats as getSupportedFormats,\n parserScanMultiChatFile as scanMultiChatFile,\n findEntryFileInDirectory,\n}\nexport type { FormatFeature, MultiChatInfo, ParseProgress }\nexport type {\n StreamImportResult,\n IncrementalImportResult,\n IncrementalAnalyzeResult,\n AnalyzeNewImportResult,\n ImportOptions,\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAsCA,YAAY,YAAY;AAoBxB,SAAS,oBAA4B;AACnC,QAAM,KAAK,KAAK,IAAI;AACpB,QAAM,OAAc,mBAAY,CAAC,EAAE,SAAS,KAAK;AACjD,SAAO,QAAQ,EAAE,IAAI,IAAI;AAC3B;AAEA,SAAS,sBAAsB,WAA4B,YAAuD;AAChH,SAAO;AAAA,IACL,aAAa,WAAmB;AAC9B,aAAO,UAAU,uBAAuB,WAAW,EAAE,QAAQ,MAAM,sBAAsB,KAAK,CAAC;AAAA,IACjG;AAAA,IACA,eAAe,WAAmB;AAChC,gBAAU,2BAA2B,SAAS;AAAA,IAChD;AAAA,IACA,YAAY,eAAe,MAAM;AAAA,IAAC;AAAA,IAClC,eAAe,IAAI;AACjB,UAAI;AACF,6BAAqB,EAAE;AAAA,MACzB,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,sBAAsB,WAA4B,WAAyB;AAClF,YAAU,2BAA2B,SAAS;AAChD;AAMA,eAAsB,aACpB,WACA,UACA,SAC6B;AAC7B,QAAM,EAAE,UAAU,WAAW,WAAW,IAAI,WAAW,CAAC;AAExD,QAAM,gBAAyC,CAAC;AAChD,MAAI,SAAU,eAAc,WAAW;AACvC,MAAI,cAAc,OAAW,eAAc,YAAY;AAEvD,QAAM,kBAA0C,aAC5C,CAAC,aAAa;AACZ,QAAI,QAAuC;AAC3C,QAAI,MAAM;AACV,YAAQ,SAAS,OAAO;AAAA,MACtB,KAAK;AACH,gBAAQ;AACR,cAAM;AACN;AAAA,MACF,KAAK;AACH,gBAAQ;AACR,cAAM,KAAK,IAAI,KAAK,MAAM,SAAS,aAAa,GAAG,GAAG,EAAE;AACxD;AAAA,MACF,KAAK;AAAA,MACL,KAAK;AACH,gBAAQ;AACR,cAAM;AACN;AAAA,MACF,KAAK;AACH,gBAAQ;AACR,cAAM;AACN;AAAA,MACF,KAAK;AACH,gBAAQ;AACR,cAAM;AACN;AAAA,IACJ;AACA,eAAW;AAAA,MACT;AAAA,MACA,UAAU;AAAA,MACV,SAAS,SAAS,WAAW;AAAA,MAC7B,WAAW,SAAS;AAAA,MACpB,YAAY,SAAS;AAAA,MACrB,mBAAmB,SAAS;AAAA,IAC9B,CAAC;AAAA,EACH,IACA,MAAM;AAAA,EAAC;AAEX,QAAM,OAAO,sBAAsB,WAAW,eAAe;AAC7D,QAAM,SAAS,MAAM,gBAAgB,UAAU,MAAM,aAAa;AAClE,MAAI,CAAC,OAAO,WAAW,CAAC,OAAO,UAAW,QAAO;AAEjD,MAAI;AACF,cAAU,oCAAoC;AAAA,EAChD,SAAS,OAAO;AACd,0BAAsB,WAAW,OAAO,SAAS;AACjD,WAAO;AAAA,MACL,SAAS;AAAA,MACT,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,MAC5D,aAAa,OAAO;AAAA,IACtB;AAAA,EACF;AAEA,SAAO;AACT;AAIA,SAAS,qBACP,WACA,YACA,sBACuB;AACvB,SAAO;AAAA,IACL,aAAa,WAAmB,UAAoB;AAClD,UAAI;AACF,eAAO,UAAU,uBAAuB,WAAW,EAAE,UAAU,YAAY,MAAM,CAAC;AAAA,MACpF,SAAS,OAAO;AACd,YAAI,iBAAiB,0BAA2B,wBAAuB,KAAK;AAC5E,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,YAAY,eAAe,MAAM;AAAA,IAAC;AAAA,IAClC,eAAe,IAAI;AACjB,UAAI;AACF,wCAAgC,EAAE;AAAA,MACpC,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsBA,mBACpB,WACA,WACA,UACA,SACkC;AAClC,QAAM,EAAE,YAAY,GAAG,WAAW,IAAI,WAAW,CAAC;AAClD,MAAI,qBAAuD;AAC3D,QAAM,SAAS,MAAM;AAAA,IACnB;AAAA,IACA;AAAA,IACA,qBAAqB,WAAW,YAAY,CAAC,UAAU;AACrD,2BAAqB;AAAA,IACvB,CAAC;AAAA,IACD;AAAA,EACF;AACA,MAAI,mBAAoB,OAAM;AAC9B,MAAI,CAAC,OAAO,QAAS,QAAO;AAE5B,MAAI;AACF,cAAU,oCAAoC;AAAA,EAChD,SAAS,OAAO;AACd,WAAO;AAAA,MACL,GAAG;AAAA,MACH,SAAS;AAAA,MACT,iBAAiB;AAAA,MACjB,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,IAC9D;AAAA,EACF;AAEA,SAAO;AACT;AAEA,eAAsBC,0BACpB,WACA,WACA,UACA,YACmC;AACnC,MAAI,qBAAuD;AAC3D,QAAM,SAAS,MAAM;AAAA,IACnB;AAAA,IACA;AAAA,IACA,qBAAqB,WAAW,YAAY,CAAC,UAAU;AACrD,2BAAqB;AAAA,IACvB,CAAC;AAAA,EACH;AACA,MAAI,mBAAoB,OAAM;AAC9B,SAAO;AACT;AAEA,eAAsBC,kBACpB,UACA,YACiC;AACjC,SAAO,iBAAuB,UAAU,eAAe,MAAM;AAAA,EAAC,EAAE;AAClE;","names":["incrementalImport","analyzeIncrementalImport","analyzeNewImport"]}
|
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
import { createRequire as __createRequire } from 'module';
|
|
2
|
+
import { dirname as __pathDirname } from 'path';
|
|
3
|
+
import { fileURLToPath as __fileURLToPath } from 'url';
|
|
4
|
+
const require = __createRequire(import.meta.url);
|
|
5
|
+
const __filename = __fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = __pathDirname(__filename);
|
|
7
|
+
import {
|
|
8
|
+
AGENT_TOOL_REGISTRY,
|
|
9
|
+
CoreDataProvider
|
|
10
|
+
} from "./chunk-JE3FOFF7.mjs";
|
|
11
|
+
import {
|
|
12
|
+
AgentEventHandler,
|
|
13
|
+
AiLogger,
|
|
14
|
+
CHART_CAPABILITY_CORE_TOOLS,
|
|
15
|
+
DEFAULT_MAX_TOOL_ROUNDS,
|
|
16
|
+
SkillManager,
|
|
17
|
+
applyPreprocessingPipeline,
|
|
18
|
+
batchSegmentWithFrequency,
|
|
19
|
+
buildPiModel,
|
|
20
|
+
buildSkillMenuWithBuiltinChart,
|
|
21
|
+
buildSystemPrompt,
|
|
22
|
+
checkAndCompress,
|
|
23
|
+
createActivateSkillTool,
|
|
24
|
+
createAiTranslate,
|
|
25
|
+
createChartSchemaGateState,
|
|
26
|
+
createCompressionLlmAdapter,
|
|
27
|
+
formatAIError,
|
|
28
|
+
getAllowedBuiltinToolsForChartAutoSkill,
|
|
29
|
+
getChartCapabilitySkill,
|
|
30
|
+
getChatOverview,
|
|
31
|
+
getSkillConfigWithBuiltinChart,
|
|
32
|
+
initTokenizer,
|
|
33
|
+
normalizeBuiltinToolNames,
|
|
34
|
+
parseAssistantFile,
|
|
35
|
+
resolveApiKey,
|
|
36
|
+
resolveChartRuntimeForRequest,
|
|
37
|
+
runAgentCore,
|
|
38
|
+
wrapWithChartSchemaGate
|
|
39
|
+
} from "./chunk-7VG6QGQ2.mjs";
|
|
40
|
+
|
|
41
|
+
// src/ai/logger.ts
|
|
42
|
+
var logger = null;
|
|
43
|
+
function initServerAiLogger(logsDir) {
|
|
44
|
+
if (!logger) {
|
|
45
|
+
logger = new AiLogger(logsDir);
|
|
46
|
+
}
|
|
47
|
+
return logger;
|
|
48
|
+
}
|
|
49
|
+
function getServerAiLogger() {
|
|
50
|
+
return logger;
|
|
51
|
+
}
|
|
52
|
+
function closeServerAiLogger() {
|
|
53
|
+
if (logger) {
|
|
54
|
+
logger.close();
|
|
55
|
+
logger = null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// src/ai/tool-adapter.ts
|
|
60
|
+
var DEFAULT_MAX_TOOL_RESULT_TOKENS = 8e3;
|
|
61
|
+
var TOOL_TRUNCATION_STRATEGY = {
|
|
62
|
+
search_messages: "keep_first",
|
|
63
|
+
deep_search_messages: "keep_first",
|
|
64
|
+
get_recent_messages: "keep_last",
|
|
65
|
+
get_message_context: "keep_last",
|
|
66
|
+
get_segment_messages: "keep_last",
|
|
67
|
+
get_conversation_between: "keep_last"
|
|
68
|
+
};
|
|
69
|
+
function convertJsonSchemaToParameters(schema) {
|
|
70
|
+
const properties = {};
|
|
71
|
+
for (const [key, prop] of Object.entries(schema.properties)) {
|
|
72
|
+
properties[key] = { ...prop };
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
type: "object",
|
|
76
|
+
properties,
|
|
77
|
+
required: schema.required || []
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function adaptToolsForAgent(tools, getContext, options) {
|
|
81
|
+
const tokenBudget = options?.maxToolResultTokens ?? DEFAULT_MAX_TOOL_RESULT_TOKENS;
|
|
82
|
+
const chartSchemaGateState = createChartSchemaGateState();
|
|
83
|
+
return tools.map(
|
|
84
|
+
(tool) => wrapWithChartSchemaGate(
|
|
85
|
+
{
|
|
86
|
+
name: tool.name,
|
|
87
|
+
label: tool.name,
|
|
88
|
+
description: tool.description,
|
|
89
|
+
parameters: convertJsonSchemaToParameters(tool.inputSchema),
|
|
90
|
+
async execute(_toolCallId, params) {
|
|
91
|
+
const toolParams = params && typeof params === "object" ? params : {};
|
|
92
|
+
const ctx = getContext();
|
|
93
|
+
const execCtx = {
|
|
94
|
+
db: ctx.db,
|
|
95
|
+
dataProvider: new CoreDataProvider(ctx.db),
|
|
96
|
+
sessionId: ctx.sessionId,
|
|
97
|
+
locale: ctx.locale,
|
|
98
|
+
segmentText: (texts, locale, options2) => batchSegmentWithFrequency(texts, locale, options2)
|
|
99
|
+
};
|
|
100
|
+
try {
|
|
101
|
+
const result = await tool.handler(toolParams, execCtx);
|
|
102
|
+
const chartDetails = result.chart || result.charts ? {
|
|
103
|
+
...result.chart ? { chart: result.chart } : {},
|
|
104
|
+
...result.charts ? { charts: result.charts } : {}
|
|
105
|
+
} : {};
|
|
106
|
+
if (result.rawMessages && result.rawMessages.length > 0) {
|
|
107
|
+
const pipelineResult = applyPreprocessingPipeline({
|
|
108
|
+
rawMessages: result.rawMessages,
|
|
109
|
+
locale: ctx.locale,
|
|
110
|
+
maxToolResultTokens: tokenBudget,
|
|
111
|
+
truncationStrategy: TOOL_TRUNCATION_STRATEGY[tool.name] ?? "keep_last",
|
|
112
|
+
extraDetails: result.data ?? {},
|
|
113
|
+
logger: getServerAiLogger() ?? void 0
|
|
114
|
+
});
|
|
115
|
+
return {
|
|
116
|
+
content: [{ type: "text", text: pipelineResult.text }],
|
|
117
|
+
details: Object.keys(chartDetails).length > 0 ? chartDetails : null
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
const baseDetails = typeof result.data === "object" && result.data !== null ? result.data : result.data === void 0 ? null : { value: result.data };
|
|
121
|
+
return {
|
|
122
|
+
content: [{ type: "text", text: result.content }],
|
|
123
|
+
details: Object.keys(chartDetails).length > 0 ? { ...baseDetails ?? {}, ...chartDetails } : baseDetails
|
|
124
|
+
};
|
|
125
|
+
} catch (error) {
|
|
126
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
127
|
+
return { content: [{ type: "text", text: `Error: ${msg}` }], details: null };
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
chartSchemaGateState
|
|
132
|
+
)
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// src/ai/llm-config.ts
|
|
137
|
+
import * as fs from "fs";
|
|
138
|
+
import * as path from "path";
|
|
139
|
+
function loadLlmConfig(aiDataDir) {
|
|
140
|
+
const configPath = path.join(aiDataDir, "llm-config.json");
|
|
141
|
+
if (!fs.existsSync(configPath)) {
|
|
142
|
+
return { configs: [], defaultAssistant: null, fastModel: null };
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
const data = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
146
|
+
const configs = (data.configs || []).map((c) => {
|
|
147
|
+
const provider = c.provider || "";
|
|
148
|
+
const authProfile = c.authProfile;
|
|
149
|
+
const profileKey = resolveApiKey(provider, authProfile);
|
|
150
|
+
const rawKey = c.apiKey || "";
|
|
151
|
+
const fallbackKey = rawKey.startsWith("enc:") ? "" : rawKey;
|
|
152
|
+
return {
|
|
153
|
+
...c,
|
|
154
|
+
apiKey: profileKey || fallbackKey
|
|
155
|
+
};
|
|
156
|
+
});
|
|
157
|
+
return {
|
|
158
|
+
configs,
|
|
159
|
+
defaultAssistant: data.defaultAssistant ?? null,
|
|
160
|
+
fastModel: data.fastModel ?? null
|
|
161
|
+
};
|
|
162
|
+
} catch {
|
|
163
|
+
return { configs: [], defaultAssistant: null, fastModel: null };
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
function resolveSlot(slot, configs) {
|
|
167
|
+
if (slot && configs.some((c) => c.id === slot.configId)) return slot;
|
|
168
|
+
const fallback = configs[0];
|
|
169
|
+
if (!fallback) return null;
|
|
170
|
+
return { configId: fallback.id, modelId: fallback.model };
|
|
171
|
+
}
|
|
172
|
+
function getDefaultAssistantConfig(aiDataDir) {
|
|
173
|
+
const store = loadLlmConfig(aiDataDir);
|
|
174
|
+
const slot = resolveSlot(store.defaultAssistant, store.configs);
|
|
175
|
+
if (!slot) return null;
|
|
176
|
+
const config = store.configs.find((c) => c.id === slot.configId);
|
|
177
|
+
if (!config) return null;
|
|
178
|
+
return { ...config, model: slot.modelId || config.model };
|
|
179
|
+
}
|
|
180
|
+
function buildPiModel2(config) {
|
|
181
|
+
return buildPiModel(config);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// src/ai/assistant-loader.ts
|
|
185
|
+
import * as fs2 from "fs";
|
|
186
|
+
import * as path2 from "path";
|
|
187
|
+
function loadAssistantConfig(aiDataDir, assistantId) {
|
|
188
|
+
const filePath = path2.join(aiDataDir, "assistants", `${assistantId}.md`);
|
|
189
|
+
if (!fs2.existsSync(filePath)) return null;
|
|
190
|
+
try {
|
|
191
|
+
const content = fs2.readFileSync(filePath, "utf-8");
|
|
192
|
+
return parseAssistantFile(content, filePath);
|
|
193
|
+
} catch {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// src/ai/agent.ts
|
|
199
|
+
async function runServerAgent(options) {
|
|
200
|
+
const {
|
|
201
|
+
userMessage,
|
|
202
|
+
aiChatId,
|
|
203
|
+
historyLeafMessageId,
|
|
204
|
+
chatType = "group",
|
|
205
|
+
locale = "zh-CN",
|
|
206
|
+
assistantSystemPrompt,
|
|
207
|
+
skillMenu,
|
|
208
|
+
skillDef,
|
|
209
|
+
compressionConfig,
|
|
210
|
+
tools = [],
|
|
211
|
+
aiDataDir,
|
|
212
|
+
aiChatManager,
|
|
213
|
+
onEvent,
|
|
214
|
+
abortSignal,
|
|
215
|
+
ownerInfo,
|
|
216
|
+
mentionedMembers,
|
|
217
|
+
dataSnapshot,
|
|
218
|
+
thinkingLevel
|
|
219
|
+
} = options;
|
|
220
|
+
const aiLogger = getServerAiLogger();
|
|
221
|
+
await initTokenizer();
|
|
222
|
+
const llmConfig = getDefaultAssistantConfig(aiDataDir);
|
|
223
|
+
if (!llmConfig) {
|
|
224
|
+
onEvent({ type: "error", error: { name: "ConfigError", message: "LLM service not configured" } });
|
|
225
|
+
onEvent({ type: "done", isFinished: true });
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
const piModel = buildPiModel2(llmConfig);
|
|
229
|
+
const t = createAiTranslate(locale);
|
|
230
|
+
let skillCtx;
|
|
231
|
+
if (skillDef) {
|
|
232
|
+
skillCtx = { skillDef };
|
|
233
|
+
} else if (skillMenu) {
|
|
234
|
+
skillCtx = { skillMenu };
|
|
235
|
+
}
|
|
236
|
+
const systemPrompt = buildSystemPrompt({
|
|
237
|
+
t,
|
|
238
|
+
chatType,
|
|
239
|
+
assistantSystemPrompt,
|
|
240
|
+
ownerInfo,
|
|
241
|
+
locale,
|
|
242
|
+
skillCtx,
|
|
243
|
+
mentionedMembers,
|
|
244
|
+
dataSnapshot
|
|
245
|
+
});
|
|
246
|
+
const handler = new AgentEventHandler({
|
|
247
|
+
onChunk: onEvent,
|
|
248
|
+
context: {},
|
|
249
|
+
systemPrompt
|
|
250
|
+
});
|
|
251
|
+
if (compressionConfig?.enabled && historyLeafMessageId === void 0) {
|
|
252
|
+
const llmAdapter = createCompressionLlmAdapter({
|
|
253
|
+
piModel,
|
|
254
|
+
apiKey: llmConfig.apiKey,
|
|
255
|
+
onCompressing: () => handler.emitStatus("compressing", [])
|
|
256
|
+
});
|
|
257
|
+
const compressionResult = await checkAndCompress(
|
|
258
|
+
aiChatId,
|
|
259
|
+
compressionConfig,
|
|
260
|
+
systemPrompt,
|
|
261
|
+
llmAdapter,
|
|
262
|
+
aiChatManager,
|
|
263
|
+
aiLogger ?? void 0
|
|
264
|
+
);
|
|
265
|
+
if (compressionResult.compressed) {
|
|
266
|
+
onEvent({
|
|
267
|
+
type: "compression_done",
|
|
268
|
+
compressionResult: {
|
|
269
|
+
summaryContent: compressionResult.summaryContent ?? "",
|
|
270
|
+
tokensBefore: compressionResult.tokensBefore ?? 0,
|
|
271
|
+
tokensAfter: compressionResult.tokensAfter ?? 0,
|
|
272
|
+
timestamp: Date.now()
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
} else if (compressionConfig?.enabled && historyLeafMessageId !== void 0) {
|
|
277
|
+
aiLogger?.info?.("Compression", "Skipping compression for edited branch request", {
|
|
278
|
+
aiChatId,
|
|
279
|
+
historyLeafMessageId
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
if (abortSignal?.aborted) {
|
|
283
|
+
handler.emitStatus("aborted", [], { force: true });
|
|
284
|
+
onEvent({ type: "done", isFinished: true, usage: handler.cloneUsage() });
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
let history = [];
|
|
288
|
+
try {
|
|
289
|
+
history = aiChatManager.getHistoryForAgent(aiChatId, void 0, historyLeafMessageId);
|
|
290
|
+
} catch {
|
|
291
|
+
}
|
|
292
|
+
handler.emitStatus("preparing", [], { pendingUserMessage: userMessage, force: true });
|
|
293
|
+
const steerMessage = t("ai.agent.answerWithoutTools");
|
|
294
|
+
let cachedMessages = [];
|
|
295
|
+
try {
|
|
296
|
+
const result = await runAgentCore({
|
|
297
|
+
piModel,
|
|
298
|
+
apiKey: llmConfig.apiKey,
|
|
299
|
+
systemPrompt,
|
|
300
|
+
tools,
|
|
301
|
+
history,
|
|
302
|
+
userMessage,
|
|
303
|
+
maxToolRounds: DEFAULT_MAX_TOOL_ROUNDS,
|
|
304
|
+
abortSignal,
|
|
305
|
+
steerMessage,
|
|
306
|
+
thinkingLevel,
|
|
307
|
+
onConvertToLlm: (filteredMessages) => {
|
|
308
|
+
cachedMessages = filteredMessages;
|
|
309
|
+
},
|
|
310
|
+
onEvent: (coreEvent) => handler.handleCoreEvent(coreEvent, cachedMessages),
|
|
311
|
+
onDebugContext: (messages) => {
|
|
312
|
+
try {
|
|
313
|
+
aiChatManager.setPendingDebugContext(aiChatId, JSON.stringify(messages, null, 2));
|
|
314
|
+
} catch {
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
if (result.error) {
|
|
319
|
+
const friendlyMessage = formatAIError(result.error);
|
|
320
|
+
onEvent({ type: "error", error: { name: "AgentError", message: friendlyMessage } });
|
|
321
|
+
}
|
|
322
|
+
handler.emitStatus("completed", cachedMessages, { force: true });
|
|
323
|
+
onEvent({ type: "done", isFinished: true, usage: result.usage });
|
|
324
|
+
} catch (error) {
|
|
325
|
+
const friendlyMessage = formatAIError(error);
|
|
326
|
+
aiLogger?.error("ServerAgent", "Agent execution error", { error: String(error) });
|
|
327
|
+
handler.emitStatus("error", cachedMessages, { force: true });
|
|
328
|
+
onEvent({ type: "error", error: { name: "AgentError", message: friendlyMessage } });
|
|
329
|
+
onEvent({ type: "done", isFinished: true, usage: handler.cloneUsage() });
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// src/ai/agent-stream-runner.ts
|
|
334
|
+
function getAiDir(dbManager) {
|
|
335
|
+
const pathProvider = dbManager["pathProvider"];
|
|
336
|
+
if (!pathProvider) {
|
|
337
|
+
throw Object.assign(new Error("PathProvider not available"), { statusCode: 500 });
|
|
338
|
+
}
|
|
339
|
+
return pathProvider.getAiDataDir();
|
|
340
|
+
}
|
|
341
|
+
var RAW_SQL_TOOL_NAMES = /* @__PURE__ */ new Set(["execute_sql"]);
|
|
342
|
+
function getAvailableToolDefs(isChartCapability, allowedToolSet) {
|
|
343
|
+
if (isChartCapability) {
|
|
344
|
+
const chartCoreTools = new Set(CHART_CAPABILITY_CORE_TOOLS);
|
|
345
|
+
return AGENT_TOOL_REGISTRY.filter(
|
|
346
|
+
(tool) => chartCoreTools.has(tool.name) || tool.category === "analysis" && allowedToolSet?.has(tool.name) && !RAW_SQL_TOOL_NAMES.has(tool.name)
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
return allowedToolSet ? AGENT_TOOL_REGISTRY.filter((tool) => tool.category !== "analysis" || allowedToolSet.has(tool.name)) : AGENT_TOOL_REGISTRY;
|
|
350
|
+
}
|
|
351
|
+
function getAllowedToolSet(isChartCapability, allowedBuiltinTools) {
|
|
352
|
+
if (isChartCapability) {
|
|
353
|
+
return new Set(normalizeBuiltinToolNames(allowedBuiltinTools ?? []));
|
|
354
|
+
}
|
|
355
|
+
return allowedBuiltinTools === void 0 ? null : new Set(normalizeBuiltinToolNames(allowedBuiltinTools));
|
|
356
|
+
}
|
|
357
|
+
function createCliRunAgentStream(dbManager, aiChatManager) {
|
|
358
|
+
return async (params, onEvent, abortSignal) => {
|
|
359
|
+
const {
|
|
360
|
+
userMessage,
|
|
361
|
+
aiChatId,
|
|
362
|
+
historyLeafMessageId,
|
|
363
|
+
sessionId,
|
|
364
|
+
chatType,
|
|
365
|
+
locale,
|
|
366
|
+
assistantId,
|
|
367
|
+
skillId,
|
|
368
|
+
enableAutoSkill,
|
|
369
|
+
compressionConfig,
|
|
370
|
+
ownerInfo,
|
|
371
|
+
mentionedMembers,
|
|
372
|
+
thinkingLevel
|
|
373
|
+
} = params;
|
|
374
|
+
const aiDataDir = getAiDir(dbManager);
|
|
375
|
+
let assistantSystemPrompt;
|
|
376
|
+
let assistantAllowedTools;
|
|
377
|
+
if (assistantId) {
|
|
378
|
+
const assistantConfig = loadAssistantConfig(aiDataDir, assistantId);
|
|
379
|
+
if (assistantConfig?.systemPrompt) {
|
|
380
|
+
assistantSystemPrompt = assistantConfig.systemPrompt;
|
|
381
|
+
}
|
|
382
|
+
assistantAllowedTools = assistantConfig?.allowedBuiltinTools;
|
|
383
|
+
}
|
|
384
|
+
const llmConfig = getDefaultAssistantConfig(aiDataDir);
|
|
385
|
+
const maxToolResultPercent = compressionConfig?.maxToolResultPercent ?? 50;
|
|
386
|
+
const contextWindow = llmConfig ? buildPiModel2(llmConfig).contextWindow ?? 128e3 : 128e3;
|
|
387
|
+
const maxToolResultTokens = Math.floor(contextWindow * (maxToolResultPercent / 100));
|
|
388
|
+
const db = dbManager.open?.(sessionId);
|
|
389
|
+
const chartRuntime = resolveChartRuntimeForRequest({
|
|
390
|
+
skillId,
|
|
391
|
+
userMessage,
|
|
392
|
+
locale,
|
|
393
|
+
assistantAllowedTools
|
|
394
|
+
});
|
|
395
|
+
const isChartCapability = chartRuntime.isChartCapability;
|
|
396
|
+
const autoSkillAllowedTools = !skillId && enableAutoSkill ? getAllowedBuiltinToolsForChartAutoSkill(assistantAllowedTools) : assistantAllowedTools;
|
|
397
|
+
const allowedToolSet = getAllowedToolSet(
|
|
398
|
+
isChartCapability,
|
|
399
|
+
isChartCapability ? chartRuntime.allowedBuiltinTools : autoSkillAllowedTools
|
|
400
|
+
);
|
|
401
|
+
const availableToolDefs = getAvailableToolDefs(isChartCapability, allowedToolSet);
|
|
402
|
+
const agentTools = db ? adaptToolsForAgent(availableToolDefs, () => ({ db, sessionId, locale }), { maxToolResultTokens }) : [];
|
|
403
|
+
const skillMgr = new SkillManager(aiDataDir);
|
|
404
|
+
skillMgr.init();
|
|
405
|
+
const toolNames = agentTools.map((t) => t.name);
|
|
406
|
+
let resolvedSkillDef;
|
|
407
|
+
let resolvedSkillMenu;
|
|
408
|
+
if (isChartCapability) {
|
|
409
|
+
const def = chartRuntime.skillDef ?? getChartCapabilitySkill(locale ?? "zh-CN");
|
|
410
|
+
resolvedSkillDef = { name: def.name, prompt: def.prompt };
|
|
411
|
+
} else if (skillId) {
|
|
412
|
+
const def = skillMgr.getSkillConfig(skillId);
|
|
413
|
+
if (def) resolvedSkillDef = { name: def.name, prompt: def.prompt };
|
|
414
|
+
} else if (enableAutoSkill) {
|
|
415
|
+
const menu = buildSkillMenuWithBuiltinChart(
|
|
416
|
+
skillMgr.getSkillMenu(chatType ?? "group", toolNames),
|
|
417
|
+
locale,
|
|
418
|
+
toolNames
|
|
419
|
+
);
|
|
420
|
+
if (menu) resolvedSkillMenu = menu;
|
|
421
|
+
}
|
|
422
|
+
if (resolvedSkillMenu) {
|
|
423
|
+
const activateSkillTool = createActivateSkillTool({
|
|
424
|
+
chatType: chatType ?? "group",
|
|
425
|
+
allowedTools: toolNames,
|
|
426
|
+
coreToolNames: new Set(CHART_CAPABILITY_CORE_TOOLS),
|
|
427
|
+
locale,
|
|
428
|
+
getSkillConfig: (id) => getSkillConfigWithBuiltinChart(id, locale, (skillConfigId) => skillMgr.getSkillConfig(skillConfigId))
|
|
429
|
+
});
|
|
430
|
+
agentTools.push(activateSkillTool);
|
|
431
|
+
}
|
|
432
|
+
const resolvedCompression = compressionConfig?.enabled ? {
|
|
433
|
+
enabled: true,
|
|
434
|
+
tokenThresholdPercent: compressionConfig.tokenThresholdPercent ?? 75,
|
|
435
|
+
bufferSizePercent: compressionConfig.bufferSizePercent ?? 20,
|
|
436
|
+
maxToolResultPercent: compressionConfig.maxToolResultPercent
|
|
437
|
+
} : void 0;
|
|
438
|
+
let dataSnapshot;
|
|
439
|
+
if (db) {
|
|
440
|
+
try {
|
|
441
|
+
const overview = getChatOverview(db, 5);
|
|
442
|
+
if (overview) {
|
|
443
|
+
dataSnapshot = {
|
|
444
|
+
name: overview.name,
|
|
445
|
+
platform: overview.platform,
|
|
446
|
+
type: overview.type,
|
|
447
|
+
totalMessages: overview.totalMessages,
|
|
448
|
+
totalMembers: overview.totalMembers,
|
|
449
|
+
firstMessageTs: overview.firstMessageTs,
|
|
450
|
+
lastMessageTs: overview.lastMessageTs,
|
|
451
|
+
capturedAt: Math.floor(Date.now() / 1e3)
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
} catch {
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
await runServerAgent({
|
|
458
|
+
userMessage,
|
|
459
|
+
aiChatId,
|
|
460
|
+
historyLeafMessageId,
|
|
461
|
+
chatType,
|
|
462
|
+
locale,
|
|
463
|
+
assistantSystemPrompt,
|
|
464
|
+
skillMenu: resolvedSkillMenu,
|
|
465
|
+
skillDef: resolvedSkillDef,
|
|
466
|
+
compressionConfig: resolvedCompression,
|
|
467
|
+
tools: agentTools,
|
|
468
|
+
aiDataDir,
|
|
469
|
+
aiChatManager,
|
|
470
|
+
onEvent,
|
|
471
|
+
abortSignal,
|
|
472
|
+
ownerInfo,
|
|
473
|
+
mentionedMembers,
|
|
474
|
+
dataSnapshot,
|
|
475
|
+
thinkingLevel
|
|
476
|
+
});
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
export {
|
|
481
|
+
initServerAiLogger,
|
|
482
|
+
closeServerAiLogger,
|
|
483
|
+
createCliRunAgentStream
|
|
484
|
+
};
|
|
485
|
+
//# sourceMappingURL=chunk-WYHGWTA4.mjs.map
|