chatlab-cli 0.25.1 → 0.26.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 → chat-command-T3Z4O4M5.mjs} +144 -6
- package/dist/chat-command-T3Z4O4M5.mjs.map +1 -0
- package/dist/{chunk-CUCDRAY6.mjs → chunk-3APSMVOM.mjs} +2 -2
- package/dist/{chunk-WYHGWTA4.mjs → chunk-6O2SW5GL.mjs} +94 -29
- package/dist/chunk-6O2SW5GL.mjs.map +1 -0
- package/dist/{chunk-GTCTDD2Z.mjs → chunk-AZZYKUBR.mjs} +17 -39
- package/dist/chunk-AZZYKUBR.mjs.map +1 -0
- package/dist/{chunk-JE3FOFF7.mjs → chunk-FACKH2BR.mjs} +49 -12
- package/dist/chunk-FACKH2BR.mjs.map +1 -0
- package/dist/{chunk-PDQFSQO6.mjs → chunk-FAOZNMPK.mjs} +2 -2
- package/dist/{chunk-7VG6QGQ2.mjs → chunk-GUGKY2GV.mjs} +1169 -328
- package/dist/chunk-GUGKY2GV.mjs.map +1 -0
- package/dist/{chunk-FDK6SPCG.mjs → chunk-MZG2GLJR.mjs} +2 -2
- package/dist/{chunk-YZYP5ST6.mjs → chunk-SC77N66X.mjs} +12 -11
- package/dist/chunk-SC77N66X.mjs.map +1 -0
- package/dist/cli.mjs +3 -3
- package/dist/{http-C3CGXUBU.mjs → http-6LQUOYQ6.mjs} +8 -8
- package/dist/{import-VS7L5JDX.mjs → import-B2MAIBAK.mjs} +4 -4
- package/dist/index.mjs +8 -8
- package/dist/{mcp-6VXDPUQK.mjs → mcp-ZMMYW46I.mjs} +4 -4
- package/dist/{stream-import-TFDBNVIW.mjs → stream-import-FHFBCEDV.mjs} +3 -3
- package/dist-web/assets/{DebugToolsPanel-vn-bnUxn.css → DebugToolsPanel-CrqULdXp.css} +1 -1
- package/dist-web/assets/DebugToolsPanel.vue_vue_type_script_setup_true_lang-CgtTQTfN.js +182 -0
- package/dist-web/assets/{EChartWordcloud-CzhfrEF_.js → EChartWordcloud-B_YisOW5.js} +1 -1
- package/dist-web/assets/MessageExportModal-B8DKeSAH.js +1 -0
- package/dist-web/assets/{electron-DRkrjeIl.js → electron-C-aMus7e.js} +1 -1
- package/dist-web/assets/electron-dBbXcMDB.js +1 -0
- package/dist-web/assets/{fetch-CDamdvtb.js → fetch-B-LdQP9s.js} +1 -1
- package/dist-web/assets/{fetch-Drk9dLaF.js → fetch-B26JuD67.js} +1 -1
- package/dist-web/assets/{fetch-BmZIm6mS.js → fetch-BLKibnXa.js} +1 -1
- package/dist-web/assets/{fetch-BqLy63aj.js → fetch-BNNqdS2B.js} +1 -1
- package/dist-web/assets/fetch-BSJY7tRo.js +1 -0
- package/dist-web/assets/{fetch-DWg-2kOp.js → fetch-CV8jezsM.js} +1 -1
- package/dist-web/assets/{fetch-ph2_d79v.js → fetch-CvnJ4Jgf.js} +1 -1
- package/dist-web/assets/{fetch-DfgdagMN.js → fetch-DP3yNfJM.js} +1 -1
- package/dist-web/assets/{fetch-Bvcxe5PI.js → fetch-phbrO2bY.js} +1 -1
- package/dist-web/assets/{fetch-Y-_WsCuk.js → fetch-xB6cl_1L.js} +3 -3
- package/dist-web/assets/index-8Zcs8peI.css +1 -0
- package/dist-web/assets/index-B_lOzUD8.js +2 -0
- package/dist-web/assets/index-BvWcJc3c.js +173 -0
- package/dist-web/assets/{index-DMWf5On7.js → index-CSDI5pAA.js} +2 -2
- package/dist-web/assets/{index-CGNgUIT-.css → index-CX2FucK5.css} +1 -1
- package/dist-web/assets/{index-9urfJP1r.js → index-DJQFNVUJ.js} +1 -1
- package/dist-web/assets/index-DZ6Szt_y.js +163 -0
- package/dist-web/assets/index-DhpclWeF.js +11 -0
- package/dist-web/assets/index-Dhql4DJr.css +1 -0
- package/dist-web/assets/{vendor-nuxt-ui-C_8CsH6e.js → vendor-nuxt-ui-Zy8txNdC.js} +1 -1
- package/dist-web/assets/{vendor-reka-ui-CIMXwvEp.js → vendor-reka-ui-mMvma1EP.js} +1 -1
- package/dist-web/assets/{web-XJV6Vj5t.js → web-DUQU-v8U.js} +1 -1
- package/dist-web/index.html +4 -4
- package/package.json +1 -1
- package/dist/chat-command-5XMRLXZM.mjs.map +0 -1
- package/dist/chunk-7VG6QGQ2.mjs.map +0 -1
- package/dist/chunk-GTCTDD2Z.mjs.map +0 -1
- package/dist/chunk-JE3FOFF7.mjs.map +0 -1
- package/dist/chunk-WYHGWTA4.mjs.map +0 -1
- package/dist/chunk-YZYP5ST6.mjs.map +0 -1
- package/dist-web/assets/DebugToolsPanel.vue_vue_type_script_setup_true_lang-B1xZmp9r.js +0 -161
- package/dist-web/assets/MessageExportModal-B79pPBL9.js +0 -1
- package/dist-web/assets/electron-Dv8jdn_2.js +0 -1
- package/dist-web/assets/fetch-BstX-wd4.js +0 -1
- package/dist-web/assets/index-C3A_Rjh-.css +0 -1
- package/dist-web/assets/index-CfKjh0Jr.js +0 -9
- package/dist-web/assets/index-CprJOAB1.css +0 -1
- package/dist-web/assets/index-D_hHm7bQ.js +0 -2
- package/dist-web/assets/index-MCdpiX_O.js +0 -173
- package/dist-web/assets/index-deYDOVUa.js +0 -163
- /package/dist/{chunk-CUCDRAY6.mjs.map → chunk-3APSMVOM.mjs.map} +0 -0
- /package/dist/{chunk-PDQFSQO6.mjs.map → chunk-FAOZNMPK.mjs.map} +0 -0
- /package/dist/{chunk-FDK6SPCG.mjs.map → chunk-MZG2GLJR.mjs.map} +0 -0
- /package/dist/{http-C3CGXUBU.mjs.map → http-6LQUOYQ6.mjs.map} +0 -0
- /package/dist/{import-VS7L5JDX.mjs.map → import-B2MAIBAK.mjs.map} +0 -0
- /package/dist/{mcp-6VXDPUQK.mjs.map → mcp-ZMMYW46I.mjs.map} +0 -0
- /package/dist/{stream-import-TFDBNVIW.mjs.map → stream-import-FHFBCEDV.mjs.map} +0 -0
|
@@ -2158,6 +2158,7 @@ function getChatOverview(db, topN = 10) {
|
|
|
2158
2158
|
if (!meta) return null;
|
|
2159
2159
|
const overview = getSessionOverview(db);
|
|
2160
2160
|
const members = getMemberActivity(db);
|
|
2161
|
+
const summaryCount = getSummaryCount(db);
|
|
2161
2162
|
const topMembers = members.slice(0, topN).map((m) => ({
|
|
2162
2163
|
id: m.memberId,
|
|
2163
2164
|
name: m.name,
|
|
@@ -2171,7 +2172,8 @@ function getChatOverview(db, topN = 10) {
|
|
|
2171
2172
|
totalMembers: overview.totalMembers,
|
|
2172
2173
|
firstMessageTs: overview.firstMessageTs,
|
|
2173
2174
|
lastMessageTs: overview.lastMessageTs,
|
|
2174
|
-
topMembers
|
|
2175
|
+
topMembers,
|
|
2176
|
+
summaryCount
|
|
2175
2177
|
};
|
|
2176
2178
|
}
|
|
2177
2179
|
function searchSegments(db, keywords, timeFilter, limit = 20, previewCount = 5, ftsMatchExpression) {
|
|
@@ -3055,188 +3057,6 @@ function deleteMember(db, memberId) {
|
|
|
3055
3057
|
}
|
|
3056
3058
|
}
|
|
3057
3059
|
|
|
3058
|
-
// ../../packages/core/src/query/filter.ts
|
|
3059
|
-
function emptyResult(page, pageSize) {
|
|
3060
|
-
return {
|
|
3061
|
-
blocks: [],
|
|
3062
|
-
stats: { totalMessages: 0, hitMessages: 0, totalChars: 0 },
|
|
3063
|
-
pagination: { page, pageSize, totalBlocks: 0, totalHits: 0, hasMore: false }
|
|
3064
|
-
};
|
|
3065
|
-
}
|
|
3066
|
-
function filterMessagesWithContext(db, options = {}) {
|
|
3067
|
-
const { keywords, timeFilter, senderIds, contextSize = 10, page = 1, pageSize = 50 } = options;
|
|
3068
|
-
const lightSql = `
|
|
3069
|
-
SELECT id, ts, sender_id as senderId, content
|
|
3070
|
-
FROM message
|
|
3071
|
-
${timeFilter ? "WHERE ts >= ? AND ts <= ?" : ""}
|
|
3072
|
-
ORDER BY ts ASC, id ASC
|
|
3073
|
-
`;
|
|
3074
|
-
const params = [];
|
|
3075
|
-
if (timeFilter) {
|
|
3076
|
-
params.push(timeFilter.startTs, timeFilter.endTs);
|
|
3077
|
-
}
|
|
3078
|
-
const lightRows = db.prepare(lightSql).all(...params);
|
|
3079
|
-
const hitIndexes = [];
|
|
3080
|
-
for (let i = 0; i < lightRows.length; i++) {
|
|
3081
|
-
const row = lightRows[i];
|
|
3082
|
-
let isHit = true;
|
|
3083
|
-
if (keywords && keywords.length > 0) {
|
|
3084
|
-
const content = (row.content || "").toLowerCase();
|
|
3085
|
-
isHit = keywords.some((kw) => content.includes(kw.toLowerCase()));
|
|
3086
|
-
}
|
|
3087
|
-
if (isHit && senderIds && senderIds.length > 0) {
|
|
3088
|
-
isHit = senderIds.includes(row.senderId);
|
|
3089
|
-
}
|
|
3090
|
-
if (isHit) {
|
|
3091
|
-
hitIndexes.push(i);
|
|
3092
|
-
}
|
|
3093
|
-
}
|
|
3094
|
-
if (hitIndexes.length === 0) {
|
|
3095
|
-
return emptyResult(page, pageSize);
|
|
3096
|
-
}
|
|
3097
|
-
const ranges = [];
|
|
3098
|
-
for (const hitIndex of hitIndexes) {
|
|
3099
|
-
const start = Math.max(0, hitIndex - contextSize);
|
|
3100
|
-
const end = Math.min(lightRows.length - 1, hitIndex + contextSize);
|
|
3101
|
-
if (ranges.length > 0) {
|
|
3102
|
-
const lastRange = ranges[ranges.length - 1];
|
|
3103
|
-
if (start <= lastRange.end + 1) {
|
|
3104
|
-
lastRange.end = Math.max(lastRange.end, end);
|
|
3105
|
-
lastRange.hitIndexes.push(hitIndex);
|
|
3106
|
-
continue;
|
|
3107
|
-
}
|
|
3108
|
-
}
|
|
3109
|
-
ranges.push({ start, end, hitIndexes: [hitIndex] });
|
|
3110
|
-
}
|
|
3111
|
-
const totalBlocks = ranges.length;
|
|
3112
|
-
const totalHits = hitIndexes.length;
|
|
3113
|
-
const startIdx = (page - 1) * pageSize;
|
|
3114
|
-
const endIdx = Math.min(startIdx + pageSize, totalBlocks);
|
|
3115
|
-
const pageRanges = ranges.slice(startIdx, endIdx);
|
|
3116
|
-
const hasMore = endIdx < totalBlocks;
|
|
3117
|
-
if (pageRanges.length === 0) {
|
|
3118
|
-
return {
|
|
3119
|
-
blocks: [],
|
|
3120
|
-
stats: { totalMessages: 0, hitMessages: totalHits, totalChars: 0 },
|
|
3121
|
-
pagination: { page, pageSize, totalBlocks, totalHits, hasMore: false }
|
|
3122
|
-
};
|
|
3123
|
-
}
|
|
3124
|
-
const blocks = [];
|
|
3125
|
-
let totalMessages = 0;
|
|
3126
|
-
let totalChars = 0;
|
|
3127
|
-
for (const range of pageRanges) {
|
|
3128
|
-
const blockSql = `
|
|
3129
|
-
SELECT ${FULL_MSG_COLUMNS}
|
|
3130
|
-
${FULL_MSG_FROM}
|
|
3131
|
-
${timeFilter ? "WHERE msg.ts >= ? AND msg.ts <= ?" : ""}
|
|
3132
|
-
ORDER BY msg.ts ASC, msg.id ASC
|
|
3133
|
-
LIMIT ? OFFSET ?
|
|
3134
|
-
`;
|
|
3135
|
-
const blockParams = [];
|
|
3136
|
-
if (timeFilter) {
|
|
3137
|
-
blockParams.push(timeFilter.startTs, timeFilter.endTs);
|
|
3138
|
-
}
|
|
3139
|
-
blockParams.push(range.end - range.start + 1, range.start);
|
|
3140
|
-
const rows = db.prepare(blockSql).all(...blockParams);
|
|
3141
|
-
const mapped = rows.map(mapMessageRow);
|
|
3142
|
-
const hitIndexSet = new Set(range.hitIndexes.map((idx) => idx - range.start));
|
|
3143
|
-
const blockMessages = mapped.map((msg, i) => ({
|
|
3144
|
-
...msg,
|
|
3145
|
-
isHit: hitIndexSet.has(i)
|
|
3146
|
-
}));
|
|
3147
|
-
for (const msg of mapped) {
|
|
3148
|
-
totalChars += msg.content.length;
|
|
3149
|
-
}
|
|
3150
|
-
if (blockMessages.length > 0) {
|
|
3151
|
-
blocks.push({
|
|
3152
|
-
startTs: blockMessages[0].timestamp,
|
|
3153
|
-
endTs: blockMessages[blockMessages.length - 1].timestamp,
|
|
3154
|
-
messages: blockMessages,
|
|
3155
|
-
hitCount: range.hitIndexes.length
|
|
3156
|
-
});
|
|
3157
|
-
totalMessages += blockMessages.length;
|
|
3158
|
-
}
|
|
3159
|
-
}
|
|
3160
|
-
let estimatedTotalChars = totalChars;
|
|
3161
|
-
if (page === 1 && totalBlocks > pageSize && blocks.length > 0) {
|
|
3162
|
-
const avgCharsPerBlock = totalChars / blocks.length;
|
|
3163
|
-
estimatedTotalChars = Math.round(avgCharsPerBlock * totalBlocks);
|
|
3164
|
-
}
|
|
3165
|
-
return {
|
|
3166
|
-
blocks,
|
|
3167
|
-
stats: {
|
|
3168
|
-
totalMessages: page === 1 ? totalMessages : 0,
|
|
3169
|
-
hitMessages: totalHits,
|
|
3170
|
-
totalChars: page === 1 ? totalBlocks > pageSize ? estimatedTotalChars : totalChars : 0
|
|
3171
|
-
},
|
|
3172
|
-
pagination: { page, pageSize, totalBlocks, totalHits, hasMore }
|
|
3173
|
-
};
|
|
3174
|
-
}
|
|
3175
|
-
function getMultipleSessionsMessages(db, segmentIds, page = 1, pageSize = 50) {
|
|
3176
|
-
if (segmentIds.length === 0) {
|
|
3177
|
-
return emptyResult(page, pageSize);
|
|
3178
|
-
}
|
|
3179
|
-
const sessionsSql = `
|
|
3180
|
-
SELECT id, start_ts as startTs, end_ts as endTs, message_count as messageCount
|
|
3181
|
-
FROM segment
|
|
3182
|
-
WHERE id IN (${segmentIds.map(() => "?").join(",")})
|
|
3183
|
-
ORDER BY start_ts ASC
|
|
3184
|
-
`;
|
|
3185
|
-
const allSessions = db.prepare(sessionsSql).all(...segmentIds);
|
|
3186
|
-
const totalBlocks = allSessions.length;
|
|
3187
|
-
const startIdx = (page - 1) * pageSize;
|
|
3188
|
-
const endIdx = Math.min(startIdx + pageSize, totalBlocks);
|
|
3189
|
-
const pageSessions = allSessions.slice(startIdx, endIdx);
|
|
3190
|
-
const hasMore = endIdx < totalBlocks;
|
|
3191
|
-
if (pageSessions.length === 0) {
|
|
3192
|
-
return {
|
|
3193
|
-
blocks: [],
|
|
3194
|
-
stats: { totalMessages: 0, hitMessages: 0, totalChars: 0 },
|
|
3195
|
-
pagination: { page, pageSize, totalBlocks, totalHits: 0, hasMore: false }
|
|
3196
|
-
};
|
|
3197
|
-
}
|
|
3198
|
-
const blocks = [];
|
|
3199
|
-
let totalMessages = 0;
|
|
3200
|
-
let totalChars = 0;
|
|
3201
|
-
const messagesSql = `
|
|
3202
|
-
SELECT ${FULL_MSG_COLUMNS}
|
|
3203
|
-
FROM message_context mc
|
|
3204
|
-
JOIN message msg ON msg.id = mc.message_id
|
|
3205
|
-
JOIN member m ON msg.sender_id = m.id
|
|
3206
|
-
LEFT JOIN message reply_msg ON msg.reply_to_message_id = reply_msg.platform_message_id
|
|
3207
|
-
LEFT JOIN member reply_m ON reply_msg.sender_id = reply_m.id
|
|
3208
|
-
WHERE mc.segment_id = ?
|
|
3209
|
-
ORDER BY msg.ts ASC
|
|
3210
|
-
`;
|
|
3211
|
-
for (const session of pageSessions) {
|
|
3212
|
-
const rows = db.prepare(messagesSql).all(session.id);
|
|
3213
|
-
const mapped = rows.map(mapMessageRow);
|
|
3214
|
-
const blockMessages = mapped.map((msg) => ({
|
|
3215
|
-
...msg,
|
|
3216
|
-
isHit: false
|
|
3217
|
-
}));
|
|
3218
|
-
for (const msg of mapped) {
|
|
3219
|
-
totalChars += msg.content.length;
|
|
3220
|
-
}
|
|
3221
|
-
blocks.push({
|
|
3222
|
-
startTs: session.startTs,
|
|
3223
|
-
endTs: session.endTs,
|
|
3224
|
-
messages: blockMessages,
|
|
3225
|
-
hitCount: 0
|
|
3226
|
-
});
|
|
3227
|
-
totalMessages += rows.length;
|
|
3228
|
-
}
|
|
3229
|
-
return {
|
|
3230
|
-
blocks,
|
|
3231
|
-
stats: {
|
|
3232
|
-
totalMessages: page === 1 ? totalMessages : 0,
|
|
3233
|
-
hitMessages: 0,
|
|
3234
|
-
totalChars: page === 1 ? totalChars : 0
|
|
3235
|
-
},
|
|
3236
|
-
pagination: { page, pageSize, totalBlocks, totalHits: 0, hasMore }
|
|
3237
|
-
};
|
|
3238
|
-
}
|
|
3239
|
-
|
|
3240
3060
|
// ../../packages/core/src/query/advanced/repeat.ts
|
|
3241
3061
|
function getCatchphraseAnalysis(db, filter) {
|
|
3242
3062
|
const { clause, params } = buildTimeFilter(filter);
|
|
@@ -3287,7 +3107,7 @@ function getCatchphraseAnalysis(db, filter) {
|
|
|
3287
3107
|
|
|
3288
3108
|
// ../../packages/core/src/query/advanced/social.ts
|
|
3289
3109
|
function getMentionAnalysis(db, filter) {
|
|
3290
|
-
const
|
|
3110
|
+
const emptyResult = {
|
|
3291
3111
|
topMentioners: [],
|
|
3292
3112
|
topMentioned: [],
|
|
3293
3113
|
oneWay: [],
|
|
@@ -3299,7 +3119,7 @@ function getMentionAnalysis(db, filter) {
|
|
|
3299
3119
|
`SELECT id, platform_id as platformId, COALESCE(group_nickname, account_name, platform_id) as name
|
|
3300
3120
|
FROM member WHERE COALESCE(account_name, '') != '\u7CFB\u7EDF\u6D88\u606F'`
|
|
3301
3121
|
).all();
|
|
3302
|
-
if (members.length === 0) return
|
|
3122
|
+
if (members.length === 0) return emptyResult;
|
|
3303
3123
|
const nameToMemberId = /* @__PURE__ */ new Map();
|
|
3304
3124
|
const memberIdToInfo = /* @__PURE__ */ new Map();
|
|
3305
3125
|
for (const member of members) {
|
|
@@ -3344,7 +3164,7 @@ function getMentionAnalysis(db, filter) {
|
|
|
3344
3164
|
}
|
|
3345
3165
|
}
|
|
3346
3166
|
}
|
|
3347
|
-
if (totalMentions === 0) return
|
|
3167
|
+
if (totalMentions === 0) return emptyResult;
|
|
3348
3168
|
const topMentioners = [];
|
|
3349
3169
|
for (const [memberId, count] of mentionerCount.entries()) {
|
|
3350
3170
|
const info = memberIdToInfo.get(memberId);
|
|
@@ -3481,7 +3301,7 @@ function getMentionAnalysis(db, filter) {
|
|
|
3481
3301
|
return { topMentioners, topMentioned, oneWay, twoWay, totalMentions, memberDetails };
|
|
3482
3302
|
}
|
|
3483
3303
|
function getMentionGraph(db, filter) {
|
|
3484
|
-
const
|
|
3304
|
+
const emptyResult = { nodes: [], links: [], maxLinkValue: 0 };
|
|
3485
3305
|
const { clause, params } = buildTimeFilter(filter);
|
|
3486
3306
|
const msgFilterBase = clause ? clause.replace("WHERE", "AND") : "";
|
|
3487
3307
|
const msgFilterWithSystem = msgFilterBase + " AND COALESCE(m.account_name, '') != '\u7CFB\u7EDF\u6D88\u606F'";
|
|
@@ -3491,7 +3311,7 @@ function getMentionGraph(db, filter) {
|
|
|
3491
3311
|
FROM member m LEFT JOIN message msg ON m.id = msg.sender_id ${msgFilterWithSystem}
|
|
3492
3312
|
WHERE COALESCE(m.account_name, '') != '\u7CFB\u7EDF\u6D88\u606F' GROUP BY m.id`
|
|
3493
3313
|
).all(...params);
|
|
3494
|
-
if (members.length === 0) return
|
|
3314
|
+
if (members.length === 0) return emptyResult;
|
|
3495
3315
|
const nameToMemberId = /* @__PURE__ */ new Map();
|
|
3496
3316
|
const memberIdToInfo = /* @__PURE__ */ new Map();
|
|
3497
3317
|
for (const member of members) {
|
|
@@ -3560,7 +3380,7 @@ function keywordToPattern(keyword) {
|
|
|
3560
3380
|
return escaped;
|
|
3561
3381
|
}
|
|
3562
3382
|
function getLaughAnalysis(db, filter, keywords) {
|
|
3563
|
-
const
|
|
3383
|
+
const emptyResult = {
|
|
3564
3384
|
rankByRate: [],
|
|
3565
3385
|
rankByCount: [],
|
|
3566
3386
|
typeDistribution: [],
|
|
@@ -3583,7 +3403,7 @@ function getLaughAnalysis(db, filter, keywords) {
|
|
|
3583
3403
|
COALESCE(m.group_nickname, m.account_name, m.platform_id) as name
|
|
3584
3404
|
FROM message msg JOIN member m ON msg.sender_id = m.id ${whereClause}`
|
|
3585
3405
|
).all(...params);
|
|
3586
|
-
if (messages.length === 0) return
|
|
3406
|
+
if (messages.length === 0) return emptyResult;
|
|
3587
3407
|
const memberStats = /* @__PURE__ */ new Map();
|
|
3588
3408
|
const typeCount = /* @__PURE__ */ new Map();
|
|
3589
3409
|
let totalLaughs = 0;
|
|
@@ -3616,7 +3436,7 @@ function getLaughAnalysis(db, filter, keywords) {
|
|
|
3616
3436
|
}
|
|
3617
3437
|
}
|
|
3618
3438
|
}
|
|
3619
|
-
if (totalLaughs === 0) return
|
|
3439
|
+
if (totalLaughs === 0) return emptyResult;
|
|
3620
3440
|
const rankItems = [];
|
|
3621
3441
|
for (const [memberId, stats] of memberStats.entries()) {
|
|
3622
3442
|
if (stats.laughCount > 0) {
|
|
@@ -3669,7 +3489,7 @@ function clusterPairKey(aId, bId) {
|
|
|
3669
3489
|
}
|
|
3670
3490
|
function getClusterGraph(db, filter, options) {
|
|
3671
3491
|
const opts = { ...DEFAULT_CLUSTER_OPTIONS, ...options };
|
|
3672
|
-
const
|
|
3492
|
+
const emptyResult = {
|
|
3673
3493
|
nodes: [],
|
|
3674
3494
|
links: [],
|
|
3675
3495
|
maxLinkValue: 0,
|
|
@@ -3681,7 +3501,7 @@ function getClusterGraph(db, filter, options) {
|
|
|
3681
3501
|
(SELECT COUNT(*) FROM message WHERE sender_id = member.id) as messageCount
|
|
3682
3502
|
FROM member WHERE COALESCE(account_name, '') != '\u7CFB\u7EDF\u6D88\u606F'`
|
|
3683
3503
|
).all();
|
|
3684
|
-
if (members.length < 2) return { ...
|
|
3504
|
+
if (members.length < 2) return { ...emptyResult, stats: { ...emptyResult.stats, totalMembers: members.length } };
|
|
3685
3505
|
const memberInfo = /* @__PURE__ */ new Map();
|
|
3686
3506
|
for (const m of members)
|
|
3687
3507
|
memberInfo.set(m.id, { name: m.name, platformId: m.platformId, messageCount: m.messageCount });
|
|
@@ -3698,8 +3518,8 @@ function getClusterGraph(db, filter, options) {
|
|
|
3698
3518
|
).all(...params);
|
|
3699
3519
|
if (messages.length < 2)
|
|
3700
3520
|
return {
|
|
3701
|
-
...
|
|
3702
|
-
stats: { ...
|
|
3521
|
+
...emptyResult,
|
|
3522
|
+
stats: { ...emptyResult.stats, totalMembers: members.length, totalMessages: messages.length }
|
|
3703
3523
|
};
|
|
3704
3524
|
const memberMsgCount = /* @__PURE__ */ new Map();
|
|
3705
3525
|
for (const msg of messages) memberMsgCount.set(msg.senderId, (memberMsgCount.get(msg.senderId) || 0) + 1);
|
|
@@ -3759,8 +3579,8 @@ function getClusterGraph(db, filter, options) {
|
|
|
3759
3579
|
const keptEdges = edges.slice(0, opts.topEdges);
|
|
3760
3580
|
if (keptEdges.length === 0)
|
|
3761
3581
|
return {
|
|
3762
|
-
...
|
|
3763
|
-
stats: { ...
|
|
3582
|
+
...emptyResult,
|
|
3583
|
+
stats: { ...emptyResult.stats, totalMembers: members.length, totalMessages: messages.length }
|
|
3764
3584
|
};
|
|
3765
3585
|
const involvedIds = /* @__PURE__ */ new Set();
|
|
3766
3586
|
for (const edge of keptEdges) {
|
|
@@ -3833,7 +3653,7 @@ var ICE_BREAK_THRESHOLD = 24 * 60 * 60;
|
|
|
3833
3653
|
var DEFAULT_PERSEVERANCE_THRESHOLD = 300;
|
|
3834
3654
|
function getRelationshipStats(db, filter, options) {
|
|
3835
3655
|
const perseveranceThreshold = options?.perseveranceThreshold ?? DEFAULT_PERSEVERANCE_THRESHOLD;
|
|
3836
|
-
const
|
|
3656
|
+
const emptyResult = {
|
|
3837
3657
|
months: [],
|
|
3838
3658
|
members: [],
|
|
3839
3659
|
totalSessions: 0,
|
|
@@ -3848,7 +3668,7 @@ function getRelationshipStats(db, filter, options) {
|
|
|
3848
3668
|
perseveranceThreshold
|
|
3849
3669
|
};
|
|
3850
3670
|
const sessionCount = db.prepare("SELECT COUNT(*) as count FROM segment").get();
|
|
3851
|
-
if (!sessionCount || sessionCount.count === 0) return
|
|
3671
|
+
if (!sessionCount || sessionCount.count === 0) return emptyResult;
|
|
3852
3672
|
const timeConditions = [];
|
|
3853
3673
|
const params = [];
|
|
3854
3674
|
if (filter?.startTs !== void 0) {
|
|
@@ -6673,6 +6493,14 @@ function getThinkingCompat(provider, modelId) {
|
|
|
6673
6493
|
return compat;
|
|
6674
6494
|
}
|
|
6675
6495
|
|
|
6496
|
+
// ../../packages/core/src/ai/tool-result-text.ts
|
|
6497
|
+
var MAX_PERSISTED_TOOL_RESULT_CHARS = 4e3;
|
|
6498
|
+
var TRUNCATION_MARKER = "\n\u2026[truncated]";
|
|
6499
|
+
function truncateToolResultText(text, maxChars = MAX_PERSISTED_TOOL_RESULT_CHARS) {
|
|
6500
|
+
if (text.length <= maxChars) return text;
|
|
6501
|
+
return text.slice(0, maxChars) + TRUNCATION_MARKER;
|
|
6502
|
+
}
|
|
6503
|
+
|
|
6676
6504
|
// ../../packages/core/src/import/dedup.ts
|
|
6677
6505
|
function fnv1a64(input) {
|
|
6678
6506
|
let h0 = 2166136261;
|
|
@@ -11779,6 +11607,10 @@ function isDuplicate(msg, existingPlatformMsgIds, existingKeys) {
|
|
|
11779
11607
|
existingKeys.add(key);
|
|
11780
11608
|
return false;
|
|
11781
11609
|
}
|
|
11610
|
+
function normalizeTimestamp(timestamp) {
|
|
11611
|
+
const value = typeof timestamp === "string" && timestamp.trim() !== "" ? Number(timestamp) : timestamp;
|
|
11612
|
+
return typeof value === "number" && value > 0 && Number.isFinite(value) ? value : null;
|
|
11613
|
+
}
|
|
11782
11614
|
async function analyzeIncrementalImport(sessionId, filePath, deps) {
|
|
11783
11615
|
const formatFeature = detectFormat(filePath);
|
|
11784
11616
|
if (!formatFeature) {
|
|
@@ -11806,7 +11638,9 @@ async function analyzeIncrementalImport(sessionId, filePath, deps) {
|
|
|
11806
11638
|
onMessageBatch: (batch) => {
|
|
11807
11639
|
for (const msg of batch) {
|
|
11808
11640
|
totalInFile++;
|
|
11809
|
-
|
|
11641
|
+
const timestamp = normalizeTimestamp(msg.timestamp);
|
|
11642
|
+
if (timestamp === null) continue;
|
|
11643
|
+
if (isDuplicate({ ...msg, timestamp }, existingPlatformMsgIds, existingKeys)) {
|
|
11810
11644
|
duplicateCount++;
|
|
11811
11645
|
} else {
|
|
11812
11646
|
newMessageCount++;
|
|
@@ -11929,11 +11763,12 @@ async function incrementalImport(sessionId, filePath, deps, options) {
|
|
|
11929
11763
|
trackError2(processedCount, "MISSING_TIMESTAMP", "timestamp field is missing");
|
|
11930
11764
|
continue;
|
|
11931
11765
|
}
|
|
11932
|
-
|
|
11766
|
+
const timestamp = normalizeTimestamp(msg.timestamp);
|
|
11767
|
+
if (timestamp === null) {
|
|
11933
11768
|
trackError2(processedCount, "INVALID_TIMESTAMP", `timestamp value: ${msg.timestamp}`);
|
|
11934
11769
|
continue;
|
|
11935
11770
|
}
|
|
11936
|
-
if (isDuplicate(msg, existingPlatformMsgIds, existingKeys)) {
|
|
11771
|
+
if (isDuplicate({ ...msg, timestamp }, existingPlatformMsgIds, existingKeys)) {
|
|
11937
11772
|
duplicateCount++;
|
|
11938
11773
|
continue;
|
|
11939
11774
|
}
|
|
@@ -11957,7 +11792,7 @@ async function incrementalImport(sessionId, filePath, deps, options) {
|
|
|
11957
11792
|
memberId,
|
|
11958
11793
|
msg.senderAccountName || null,
|
|
11959
11794
|
msg.senderGroupNickname || null,
|
|
11960
|
-
|
|
11795
|
+
timestamp,
|
|
11961
11796
|
msg.type,
|
|
11962
11797
|
msg.content || null,
|
|
11963
11798
|
msg.replyToMessageId || null,
|
|
@@ -12584,11 +12419,7 @@ var AIChatManager = class {
|
|
|
12584
12419
|
siblingGroupId,
|
|
12585
12420
|
branchIndex
|
|
12586
12421
|
);
|
|
12587
|
-
db.prepare("UPDATE ai_chat SET active_message_id = ?, updated_at = ? WHERE id = ?").run(
|
|
12588
|
-
id,
|
|
12589
|
-
now,
|
|
12590
|
-
aiChatId
|
|
12591
|
-
);
|
|
12422
|
+
db.prepare("UPDATE ai_chat SET active_message_id = ?, updated_at = ? WHERE id = ?").run(id, now, aiChatId);
|
|
12592
12423
|
return {
|
|
12593
12424
|
id,
|
|
12594
12425
|
aiChatId,
|
|
@@ -12626,11 +12457,7 @@ var AIChatManager = class {
|
|
|
12626
12457
|
db.prepare(`DELETE FROM ai_message WHERE id IN (${placeholders})`).run(...idsToDelete);
|
|
12627
12458
|
const newLeafId = targetIndex > 0 ? activePath[targetIndex - 1].id : null;
|
|
12628
12459
|
const now = Math.floor(Date.now() / 1e3);
|
|
12629
|
-
db.prepare("UPDATE ai_chat SET active_message_id = ?, updated_at = ? WHERE id = ?").run(
|
|
12630
|
-
newLeafId,
|
|
12631
|
-
now,
|
|
12632
|
-
aiChatId
|
|
12633
|
-
);
|
|
12460
|
+
db.prepare("UPDATE ai_chat SET active_message_id = ?, updated_at = ? WHERE id = ?").run(newLeafId, now, aiChatId);
|
|
12634
12461
|
}
|
|
12635
12462
|
forkAIChat(sourceAIChatId, upToMessageId, title) {
|
|
12636
12463
|
const db = this.getDb();
|
|
@@ -12749,11 +12576,7 @@ var AIChatManager = class {
|
|
|
12749
12576
|
db.prepare("UPDATE ai_message SET parent_id = ? WHERE id = ?").run(id, childRow.id);
|
|
12750
12577
|
db.prepare("UPDATE ai_chat SET updated_at = ? WHERE id = ?").run(now, aiChatId);
|
|
12751
12578
|
} else {
|
|
12752
|
-
db.prepare("UPDATE ai_chat SET active_message_id = ?, updated_at = ? WHERE id = ?").run(
|
|
12753
|
-
id,
|
|
12754
|
-
now,
|
|
12755
|
-
aiChatId
|
|
12756
|
-
);
|
|
12579
|
+
db.prepare("UPDATE ai_chat SET active_message_id = ?, updated_at = ? WHERE id = ?").run(id, now, aiChatId);
|
|
12757
12580
|
}
|
|
12758
12581
|
return {
|
|
12759
12582
|
id,
|
|
@@ -12768,13 +12591,21 @@ var AIChatManager = class {
|
|
|
12768
12591
|
}
|
|
12769
12592
|
getAIChatTokenUsage(aiChatId) {
|
|
12770
12593
|
const rows = this.getActivePathRows(aiChatId);
|
|
12771
|
-
const result = {
|
|
12594
|
+
const result = {
|
|
12595
|
+
promptTokens: 0,
|
|
12596
|
+
completionTokens: 0,
|
|
12597
|
+
totalTokens: 0,
|
|
12598
|
+
cacheReadTokens: 0,
|
|
12599
|
+
cacheWriteTokens: 0
|
|
12600
|
+
};
|
|
12772
12601
|
for (const row of rows) {
|
|
12773
12602
|
if (row.tokenUsage) {
|
|
12774
12603
|
const usage = JSON.parse(row.tokenUsage);
|
|
12775
12604
|
result.promptTokens += usage.promptTokens;
|
|
12776
12605
|
result.completionTokens += usage.completionTokens;
|
|
12777
12606
|
result.totalTokens += usage.totalTokens;
|
|
12607
|
+
result.cacheReadTokens += usage.cacheReadTokens || 0;
|
|
12608
|
+
result.cacheWriteTokens += usage.cacheWriteTokens || 0;
|
|
12778
12609
|
}
|
|
12779
12610
|
}
|
|
12780
12611
|
return result;
|
|
@@ -12796,7 +12627,7 @@ var AIChatManager = class {
|
|
|
12796
12627
|
getHistoryForAgent(aiChatId, maxMessages, leafMessageId) {
|
|
12797
12628
|
const messages = this.getActivePathRows(aiChatId, leafMessageId).map((row) => this.parseMessageRow(row));
|
|
12798
12629
|
const validMessages = messages.filter(
|
|
12799
|
-
(m) => (m.role === "user" || m.role === "assistant" || m.role === "summary") && m.content?.trim()
|
|
12630
|
+
(m) => (m.role === "user" || m.role === "assistant" || m.role === "summary") && (m.content?.trim() || m.role === "assistant" && m.contentBlocks?.some((b) => b.type === "tool"))
|
|
12800
12631
|
);
|
|
12801
12632
|
let summaryMsg;
|
|
12802
12633
|
for (let i = validMessages.length - 1; i >= 0; i--) {
|
|
@@ -12820,10 +12651,10 @@ var AIChatManager = class {
|
|
|
12820
12651
|
const contextMessages = bufferBoundary ? validMessages.filter((m) => m.role !== "summary" && m.timestamp >= bufferBoundary) : [];
|
|
12821
12652
|
result = [
|
|
12822
12653
|
{ role: "summary", content: summaryMsg.content },
|
|
12823
|
-
...contextMessages.map((m) => ({ role: m.role, content: m.content }))
|
|
12654
|
+
...contextMessages.map((m) => ({ role: m.role, content: m.content, contentBlocks: m.contentBlocks }))
|
|
12824
12655
|
];
|
|
12825
12656
|
} else {
|
|
12826
|
-
result = validMessages.map((m) => ({ role: m.role, content: m.content }));
|
|
12657
|
+
result = validMessages.map((m) => ({ role: m.role, content: m.content, contentBlocks: m.contentBlocks }));
|
|
12827
12658
|
}
|
|
12828
12659
|
if (maxMessages && result.length > maxMessages) {
|
|
12829
12660
|
if (result.length > 0 && result[0].role === "summary") {
|
|
@@ -12851,10 +12682,18 @@ var AIChatManager = class {
|
|
|
12851
12682
|
return row ? this.parseMessageRow(row) : null;
|
|
12852
12683
|
}
|
|
12853
12684
|
getMessagesAfterSummary(aiChatId, summaryTimestamp) {
|
|
12854
|
-
return this.getActivePathRows(aiChatId).filter((row) => row.timestamp > summaryTimestamp && (row.role === "user" || row.role === "assistant")).map((row) => (
|
|
12685
|
+
return this.getActivePathRows(aiChatId).filter((row) => row.timestamp > summaryTimestamp && (row.role === "user" || row.role === "assistant")).map((row) => this.toCompressionMessage(row));
|
|
12855
12686
|
}
|
|
12856
12687
|
getAllUserAssistantMessages(aiChatId) {
|
|
12857
|
-
return this.getActivePathRows(aiChatId).filter((row) => row.role === "user" || row.role === "assistant").map((row) => (
|
|
12688
|
+
return this.getActivePathRows(aiChatId).filter((row) => row.role === "user" || row.role === "assistant").map((row) => this.toCompressionMessage(row));
|
|
12689
|
+
}
|
|
12690
|
+
toCompressionMessage(row) {
|
|
12691
|
+
return {
|
|
12692
|
+
role: row.role,
|
|
12693
|
+
content: row.content,
|
|
12694
|
+
timestamp: row.timestamp,
|
|
12695
|
+
contentBlocks: row.contentBlocks ? JSON.parse(row.contentBlocks) : void 0
|
|
12696
|
+
};
|
|
12858
12697
|
}
|
|
12859
12698
|
getMessageCountAfterSummary(aiChatId) {
|
|
12860
12699
|
const summary = this.getLatestSummary(aiChatId);
|
|
@@ -14034,10 +13873,38 @@ function shouldUseChartCapabilityForMessage(message) {
|
|
|
14034
13873
|
normalized
|
|
14035
13874
|
);
|
|
14036
13875
|
}
|
|
13876
|
+
function shouldOfferChartCapabilityForAnalyticalMessage(message) {
|
|
13877
|
+
const normalized = message.trim().toLowerCase();
|
|
13878
|
+
if (!normalized) return false;
|
|
13879
|
+
if (shouldUseChartCapabilityForMessage(normalized)) return true;
|
|
13880
|
+
return /(?:趋势|变化|走势|排名|排行|前\s*\d+|top\s*\d*|最多|最少|高频|分布|占比|比例|构成|份额|活跃度|热度|按.{0,8}统计|统计.{0,8}按|trend|ranking|rank|top\s*\d*|distribution|ratio|share|percentage|breakdown)/i.test(
|
|
13881
|
+
normalized
|
|
13882
|
+
);
|
|
13883
|
+
}
|
|
13884
|
+
function getChartPlannerCapabilityForMessage(options) {
|
|
13885
|
+
const availableToolSet = new Set(options.availableTools);
|
|
13886
|
+
if (!availableToolSet.has("get_schema") || !availableToolSet.has("render_chart")) {
|
|
13887
|
+
return null;
|
|
13888
|
+
}
|
|
13889
|
+
const chartAutoMode = options.chartAutoMode ?? "suggest";
|
|
13890
|
+
const shouldOffer = chartAutoMode === "explicit" ? shouldUseChartCapabilityForMessage(options.userMessage) : shouldOfferChartCapabilityForAnalyticalMessage(options.userMessage);
|
|
13891
|
+
if (!shouldOffer) {
|
|
13892
|
+
return null;
|
|
13893
|
+
}
|
|
13894
|
+
const isZh = (options.locale ?? "zh-CN").startsWith("zh");
|
|
13895
|
+
return {
|
|
13896
|
+
id: "chart_generation",
|
|
13897
|
+
label: isZh ? "\u56FE\u8868\u751F\u6210" : "Chart generation",
|
|
13898
|
+
tools: ["get_schema", "render_chart"],
|
|
13899
|
+
guidance: isZh ? "\u7528\u6237\u660E\u786E\u8981\u6C42\u56FE\u8868\uFF0C\u6216\u8D8B\u52BF\u3001\u6392\u540D\u3001\u5206\u5E03\u3001\u5360\u6BD4\u7B49\u5206\u6790\u7528\u56FE\u66F4\u6E05\u695A\u65F6\uFF0C\u53EF\u4EE5\u5728\u8BA1\u5212\u4E2D\u52A0\u5165\u6700\u591A\u4E00\u5F20\u56FE\u8868\u6B65\u9AA4\uFF1B\u5FC5\u987B\u5148\u7528 get_schema \u786E\u8BA4 schema\uFF0C\u518D\u7528 render_chart \u751F\u6210\u56FE\u8868\uFF1B\u4E0D\u8981\u8F93\u51FA\u7ED8\u56FE\u4EE3\u7801\u3002" : "When the user explicitly asks for charts, or when trends, rankings, distributions, or ratios are clearer visually, you may add at most one chart step to the plan; call get_schema before render_chart; do not output chart-rendering code."
|
|
13900
|
+
};
|
|
13901
|
+
}
|
|
14037
13902
|
function resolveChartRuntimeForRequest(options) {
|
|
14038
13903
|
const locale = options.locale ?? "zh-CN";
|
|
14039
13904
|
const isExplicitChartSkill = options.skillId === CHART_CAPABILITY_SKILL_ID;
|
|
14040
|
-
const
|
|
13905
|
+
const allowAnalyticalAutoDetection = options.chartAutoMode !== void 0 ? options.chartAutoMode === "aggressive" : options.enableAnalyticalAutoDetection === true;
|
|
13906
|
+
const shouldAutoDetectChart = shouldUseChartCapabilityForMessage(options.userMessage ?? "") || allowAnalyticalAutoDetection && shouldOfferChartCapabilityForAnalyticalMessage(options.userMessage ?? "");
|
|
13907
|
+
const isAutoChartSkill = options.enableAutoDetection === true && !options.skillId && shouldAutoDetectChart;
|
|
14041
13908
|
if (!isExplicitChartSkill && !isAutoChartSkill) {
|
|
14042
13909
|
return { isChartCapability: false };
|
|
14043
13910
|
}
|
|
@@ -14083,23 +13950,28 @@ function getSkillConfigWithBuiltinChart(id, locale = "zh-CN", getSkillConfig) {
|
|
|
14083
13950
|
}
|
|
14084
13951
|
var ZH_PROMPT = `\u4F60\u662F ChatLab \u7ED8\u56FE\u52A9\u624B\u3002\u672C\u8F6E\u7528\u6237\u5E0C\u671B\u4F60\u5728\u56DE\u7B54\u91CC\u81EA\u7136\u5D4C\u5165\u4E00\u5F20\u6216\u591A\u5F20\u56FE\u8868\u3002
|
|
14085
13952
|
|
|
14086
|
-
\u4F60\u5FC5\u987B\u901A\u8FC7 render_chart \u5DE5\u5177\u751F\u6210\u56FE\u8868\u3002\u4E0D\u8981\u8F93\u51FA HTML\u3001JavaScript\u3001SVG\u3001Canvas\u3001ECharts option \u6216\u4EFB\u4F55\u6E32\u67D3\u4EE3\u7801\u3002
|
|
13953
|
+
\u4F60\u5FC5\u987B\u901A\u8FC7 render_chart \u5DE5\u5177\u751F\u6210\u56FE\u8868\u3002\u4E0D\u8981\u8F93\u51FA HTML\u3001JavaScript\u3001SVG\u3001Canvas\u3001ECharts option\u3001Markdown \u56FE\u7247\u94FE\u63A5\uFF08\u5982 \uFF09\u6216\u4EFB\u4F55\u6E32\u67D3\u4EE3\u7801\u3002
|
|
14087
13954
|
|
|
14088
13955
|
\u786C\u6027\u89C4\u5219\uFF1A
|
|
14089
13956
|
1. \u7B2C\u4E00\u6B21\u5199 SQL \u524D\u5FC5\u987B\u5148\u8C03\u7528 get_schema\u3002\u7981\u6B62\u731C\u6D4B\u8868\u540D\u3001\u5B57\u6BB5\u540D\u6216\u65F6\u95F4\u5B57\u6BB5\u3002
|
|
14090
|
-
2. \u201C\u6700\u8FD1\u201D\u201C\
|
|
13957
|
+
2. \u201C\u6700\u8FD1\u201D\u201C\u8FC7\u53BB N \u5929/\u5E74\u201D\u7B49\u76F8\u5BF9\u65F6\u95F4\u4EE5\u7CFB\u7EDF\u63D0\u793A\u4E2D\u7684\u771F\u5B9E\u5F53\u524D\u65E5\u671F\u4E3A\u57FA\u51C6\uFF1B\u5982\u679C\u542F\u52A8\u4E0A\u4E0B\u6587\u663E\u793A\u6570\u636E\u5E93\u8986\u76D6\u4E0D\u8DB3\uFF0C\u53EA\u5206\u6790\u7528\u6237\u65F6\u95F4\u8303\u56F4\u4E0E\u6570\u636E\u5E93\u8986\u76D6\u8303\u56F4\u7684\u4EA4\u96C6\u5E76\u8BF4\u660E\u7F3A\u53E3\u3002
|
|
14091
13958
|
3. ChatLab \u7684 message.ts \u662F\u79D2\u7EA7 Unix \u65F6\u95F4\u6233\uFF0C\u4F7F\u7528 date(ts, 'unixepoch', 'localtime')\uFF1B\u7981\u6B62\u5199 ts/1000\u3002
|
|
14092
13959
|
4. \u201C\u6700\u8FD1\u7684 N \u4EBA/\u6210\u5458\u201D\u5FC5\u987B\u5148\u7528\u6570\u636E\u5B9A\u4E49\u5E76\u7B5B\u9009\u51FA N \u4E2A\u6210\u5458\uFF0C\u518D\u53EA\u7EDF\u8BA1\u8FD9\u4E9B\u6210\u5458\u3002
|
|
14093
13960
|
5. \u6298\u7EBF\u56FE\u6709\u591A\u6761\u7EBF\u65F6\uFF0C\u6BCF\u6761\u7EBF\u5FC5\u987B\u6709\u660E\u786E series \u5B57\u6BB5\u542B\u4E49\uFF1B\u6309\u65E5\u671F\u7EDF\u8BA1\u65F6\u5E94\u8865\u9F50\u65E5\u671F \xD7 series \u7684 0 \u503C\uFF0C\u907F\u514D\u7F3A\u5931\u65E5\u671F\u5BFC\u81F4\u6298\u7EBF\u65AD\u88C2\u6216\u8BEF\u8FDE\u3002
|
|
14094
|
-
6. \u5DE5\u5177\u5931\u8D25\u3001SQL \u4FEE\u6B63\u3001schema \u63A2\u7D22\u8FC7\u7A0B\u4E0D\u8981\u5199\u8FDB\u6700\u7EC8\u56DE\u7B54\uFF1B\u6700\u7EC8\u53EA\u4FDD\u7559\u56FE\u8868\u548C\u7B80\u77ED\u7ED3\u8BBA\u3002
|
|
14095
|
-
7. \
|
|
13961
|
+
6. \u5DE5\u5177\u5931\u8D25\u3001SQL \u4FEE\u6B63\u3001schema \u63A2\u7D22\u8FC7\u7A0B\u4E0D\u8981\u5199\u8FDB\u6700\u7EC8\u56DE\u7B54\uFF1B\u6700\u7EC8\u53EA\u4FDD\u7559\u539F\u751F\u56FE\u8868\u548C\u7B80\u77ED\u7ED3\u8BBA\uFF0C\u7981\u6B62\u7528 chart1.png\u3001chart2.png \u7B49\u6587\u4EF6\u540D\u5F15\u7528\u56FE\u8868\u3002
|
|
13962
|
+
7. \u8C03\u7528 render_chart \u65F6\uFF0CChatLab \u4F1A\u7ACB\u5373\u5728\u8BE5\u4F4D\u7F6E\u63D2\u5165\u539F\u751F\u56FE\u8868\uFF1B\u9700\u8981\u56FE\u8868\u5C31\u76F4\u63A5\u8C03\u7528\u5DE5\u5177\uFF0C\u4E0D\u8981\u5199 SQL \u6CE8\u91CA\u3001Markdown \u56FE\u7247\u6216\u201C\u5DF2\u751F\u6210\u56FE\u8868/\u89C1\u4E0A\u56FE\u201D\u8FD9\u7C7B\u6587\u672C\u5360\u4F4D\u3002
|
|
13963
|
+
8. \u7528\u6237\u8981\u6C42\u591A\u5F20\u56FE\u65F6\uFF0C\u56FE\u8868\u5E94\u5206\u6563\u51FA\u73B0\u5728\u76F8\u5173\u603B\u7ED3\u6216\u89E3\u91CA\u9644\u8FD1\uFF1B\u4E0D\u8981\u628A\u6240\u6709\u56FE\u96C6\u4E2D\u751F\u6210\u540E\u518D\u5728\u6700\u540E\u7528\u6587\u5B57\u5F15\u7528\u3002
|
|
13964
|
+
9. \u4E3A\u56FE\u8868\u51C6\u5907\u6570\u636E\u65F6\uFF0C\u4F18\u5148\u8C03\u7528\u9AD8\u5C42\u5DE5\u5177\uFF08\u5982 get_time_stats\u3001member_stats\uFF09\u800C\u975E\u81EA\u5DF1\u5199 SQL\uFF1B\u53EA\u6709\u9AD8\u5C42\u5DE5\u5177\u65E0\u6CD5\u8986\u76D6\u6240\u9700\u7B5B\u9009\u6216\u805A\u5408\u65F6\u624D\u7528 sql\u3002render_chart \u4E0D\u8981\u7528\u4E8E\u5143\u6570\u636E\u63A2\u6D4B\u3001\u6807\u91CF\u67E5\u8BE2\u3001\u5355\u884C\u65E5\u671F\u5B57\u7B26\u4E32\u6216\u7EAF\u8BF4\u660E\u6027\u7ED3\u679C\u3002
|
|
13965
|
+
10. render_chart \u7684\u5DE5\u5177\u7ED3\u679C\u4F1A\u5305\u542B\u6570\u636E\u9884\u89C8\uFF08Data preview\uFF09\uFF1B\u7528\u5B83\u5206\u6790\u5CF0\u503C\u3001\u4F4E\u8C37\u548C\u5DEE\u5F02\uFF0C\u4E0D\u8981\u4E3A\u4E86\u8BFB\u53D6\u6570\u503C\u91CD\u590D\u751F\u6210\u7B49\u4EF7\u56FE\u8868\u3002
|
|
13966
|
+
11. \u56FE\u8868\u89E3\u91CA\u53EA\u80FD\u63CF\u8FF0\u6570\u636E\u76F4\u63A5\u652F\u6301\u7684\u8D8B\u52BF\u3001\u5CF0\u503C\u3001\u4F4E\u8C37\u3001\u5DEE\u5F02\u548C\u540C\u6B65\u6027\uFF0C\u7981\u6B62\u5938\u5F20\u62DF\u4EBA\u5316\u6216\u65E0\u6CD5\u4ECE\u56FE\u4E2D\u9A8C\u8BC1\u7684\u5173\u7CFB\u5224\u65AD\u3002
|
|
14096
13967
|
|
|
14097
13968
|
\u5DE5\u4F5C\u6D41\u7A0B\uFF1A
|
|
14098
13969
|
1. \u8C03\u7528 get_schema\u3002
|
|
14099
|
-
2. \u6839\u636E schema
|
|
14100
|
-
3. \
|
|
14101
|
-
4. \
|
|
14102
|
-
5. \
|
|
13970
|
+
2. \u6839\u636E schema\u3001\u7528\u6237\u8981\u6C42\u3001\u7CFB\u7EDF\u5F53\u524D\u65E5\u671F\u548C\u542F\u52A8\u4E0A\u4E0B\u6587\u786E\u5B9A\u7EDF\u8BA1\u5BF9\u8C61\u3001\u65F6\u95F4\u8303\u56F4\u3001\u7EF4\u5EA6\u3001\u6307\u6807\u548C\u56FE\u8868\u7C7B\u578B\u3002
|
|
13971
|
+
3. \u5982\u9700\u8C03\u67E5\u4E8B\u5B9E\u3001\u5EFA\u7ACB\u8BDD\u9898\u5730\u56FE\u3001\u7B5B\u9009\u6210\u5458\u6216\u786E\u8BA4\u7EDF\u8BA1\u53E3\u5F84\uFF0C\u5148\u7528\u53EF\u7528\u7684\u666E\u901A\u5206\u6790\u5DE5\u5177\u5B8C\u6210\uFF1B\u4E0D\u8981\u4E3A\u4E86\u8C03\u67E5\u800C\u751F\u6210\u4E34\u65F6\u56FE\u8868\u3002
|
|
13972
|
+
4. \u51C6\u5907\u56FE\u8868\u6570\u636E\u2014\u2014\u5148\u95EE\u81EA\u5DF1\uFF1A\u54EA\u4E2A\u53EF\u7528\u7684\u9AD8\u5C42\u5DE5\u5177\u80FD\u76F4\u63A5\u63D0\u4F9B\u8FD9\u5F20\u56FE\u6240\u9700\u7684\u6570\u636E\uFF1Fget_time_stats \u80FD\u7ED9\u65F6\u95F4\u5206\u5E03\u3001member_stats \u80FD\u7ED9\u6210\u5458\u6392\u540D\uFF1B\u80FD\u7528\u5C31\u8C03\u7528\uFF0C\u5C06 data \u6570\u7EC4\u4F5C\u4E3A rows \u4F20\u5165 render_chart\u3002\u53EA\u6709\u5728\u9AD8\u5C42\u5DE5\u5177\u65E0\u6CD5\u8986\u76D6\u6240\u9700\u7B5B\u9009\u6216\u805A\u5408\u65F6\uFF0C\u624D\u7F16\u5199 SQL\u3002
|
|
13973
|
+
5. \u5728\u5E0C\u671B\u56FE\u8868\u51FA\u73B0\u7684\u4F4D\u7F6E\u8C03\u7528 render_chart\uFF0C\u63D0\u4EA4\u6570\u636E\uFF08rows \u6216 sql\uFF09\u548C ChartSpec v1\u3002
|
|
13974
|
+
6. \u56FE\u8868\u751F\u6210\u540E\uFF0C\u7528 1-3 \u53E5\u7B80\u6D01\u6587\u5B57\u89E3\u91CA\u7ED3\u8BBA\u3002\u7528\u6237\u8981\u6C42\u591A\u5F20\u56FE\u65F6\uFF0C\u53EF\u4EE5\u591A\u6B21\u8C03\u7528 render_chart\uFF0C\u5E76\u628A\u6BCF\u5F20\u56FE\u653E\u5728\u6700\u76F8\u5173\u7684\u6BB5\u843D\u9644\u8FD1\u3002
|
|
14103
13975
|
|
|
14104
13976
|
\u5E38\u7528\u8BED\u3001\u53E3\u5934\u7985\u3001\u9AD8\u9891\u77ED\u53E5\u7C7B\u56FE\u8868\u5FC5\u987B\u6392\u9664\u975E\u771F\u4EBA\u6587\u672C\uFF1A\u53D1\u9001\u8005\u4E3A\u7CFB\u7EDF\u6D88\u606F\u3001\u5A92\u4F53\u5360\u4F4D\uFF08\u5982 [\u8868\u60C5\u5305]\u3001[\u56FE\u7247]\u3001[\u8BED\u97F3]\u3001[\u89C6\u9891]\u3001[\u6587\u4EF6]\u3001[\u94FE\u63A5]\u3001[\u7EA2\u5305]\u3001[\u8F6C\u8D26]\uFF09\u4EE5\u53CA\u64A4\u56DE/\u5220\u9664\u63D0\u793A\u90FD\u4E0D\u80FD\u8FDB\u5165\u7EDF\u8BA1\u3002
|
|
14105
13977
|
|
|
@@ -14121,23 +13993,28 @@ ChartSpec \u793A\u4F8B\uFF1A
|
|
|
14121
13993
|
\u7528\u6237\u660E\u786E\u8981\u6C42\u56FE\u8868\u65F6\u5FC5\u987B\u5C1D\u8BD5\u751F\u6210\u3002\u7528\u6237\u6CA1\u6709\u660E\u786E\u8981\u6C42\u65F6\uFF0C\u53EA\u6709\u6392\u540D\u3001\u8D8B\u52BF\u3001\u5206\u5E03\u3001\u5360\u6BD4\u6216\u4E8C\u7EF4\u5BC6\u5EA6\u660E\u663E\u66F4\u6E05\u695A\u65F6\u624D\u4E3B\u52A8\u751F\u6210\uFF0C\u4E14\u9ED8\u8BA4\u6700\u591A\u4E00\u5F20\u3002`;
|
|
14122
13994
|
var EN_PROMPT = `You are the ChatLab Chart Assistant. In this turn, the user wants one or more charts embedded naturally in the answer.
|
|
14123
13995
|
|
|
14124
|
-
You must generate charts through the render_chart tool. Do not output HTML, JavaScript, SVG, Canvas, ECharts options, or rendering code.
|
|
13996
|
+
You must generate charts through the render_chart tool. Do not output HTML, JavaScript, SVG, Canvas, ECharts options, Markdown image links such as , or rendering code.
|
|
14125
13997
|
|
|
14126
13998
|
Hard rules:
|
|
14127
13999
|
1. Always call get_schema before writing the first SQL query. Do not guess table names, field names, or timestamp fields.
|
|
14128
|
-
2. For
|
|
14000
|
+
2. For relative ranges like "recent" or "past N days/years", use the real current date from the system prompt as the baseline. If startup context shows incomplete database coverage, analyze only the intersection between the requested range and database coverage, and state the gap.
|
|
14129
14001
|
3. ChatLab message.ts is a Unix timestamp in seconds. Use date(ts, 'unixepoch', 'localtime'); never write ts/1000.
|
|
14130
14002
|
4. For "latest N members" or "recent N people", first define and select those N members from the data, then count only those members.
|
|
14131
14003
|
5. For multi-series line charts, every line must have an explicit series field. For daily counts, fill the date x series grid with zero values so missing days do not break or mislead the line.
|
|
14132
|
-
6. Do not include failed SQL attempts, schema exploration, or retry reasoning in the final answer. Final answer should contain only
|
|
14133
|
-
7.
|
|
14004
|
+
6. Do not include failed SQL attempts, schema exploration, or retry reasoning in the final answer. Final answer should contain only native charts and a short conclusion; never reference charts with filenames like chart1.png or chart2.png.
|
|
14005
|
+
7. When you call render_chart, ChatLab immediately inserts the native chart at that position. If a chart is needed, call the tool directly; do not write SQL-comment placeholders, Markdown images, or text such as "generated chart" or "see chart above".
|
|
14006
|
+
8. If the user asks for multiple charts, place each chart near the relevant summary or explanation. Do not generate all charts together and then reference them later with text.
|
|
14007
|
+
9. When preparing chart data, prefer calling a high-level tool (such as get_time_stats, member_stats) over writing SQL; only use sql when no high-level tool can satisfy the required filters or aggregations. Do not use render_chart for metadata inspection, scalar queries, single-row date strings, or purely explanatory results.
|
|
14008
|
+
10. render_chart tool results include a Data preview; use it to identify peaks, lows, and differences. Do not generate equivalent charts again just to read values.
|
|
14009
|
+
11. Explain only trends, peaks, lows, differences, and synchrony directly supported by chart data. Do not make exaggerated personality or relationship claims.
|
|
14134
14010
|
|
|
14135
14011
|
Workflow:
|
|
14136
14012
|
1. Call get_schema.
|
|
14137
|
-
2. Derive the target members, time range, dimensions, metrics, and chart type from schema
|
|
14138
|
-
3.
|
|
14139
|
-
4.
|
|
14140
|
-
5.
|
|
14013
|
+
2. Derive the target members, time range, dimensions, metrics, and chart type from schema, the user request, system current date, and startup context.
|
|
14014
|
+
3. If you need to investigate facts, build a topic map, select members, or confirm statistical definitions, use available ordinary analysis tools first; do not generate temporary charts for investigation.
|
|
14015
|
+
4. Prepare chart data \u2014 ask yourself first: which available high-level tool can directly provide the data this chart needs? get_time_stats covers time distributions; member_stats covers member rankings. If one fits, call it and pass its data array as rows to render_chart. Only write SQL when no high-level tool can cover the required filters or aggregations.
|
|
14016
|
+
5. Call render_chart at the position where the chart should appear, with data (rows or sql) and ChartSpec v1.
|
|
14017
|
+
6. After the chart is generated, explain the key finding in 1-3 concise sentences. If the user asks for multiple charts, call render_chart multiple times and place each chart near its most relevant section.
|
|
14141
14018
|
|
|
14142
14019
|
For catchphrase, common phrase, or frequent short-text charts, exclude non-human text from the SQL: system-message senders, media placeholders such as [Sticker], [Image], [Photo], [Voice], [Video], [File], [Link], and recall/deletion notices must not be counted.
|
|
14143
14020
|
|
|
@@ -14183,6 +14060,95 @@ function wrapWithChartSchemaGate(tool, state) {
|
|
|
14183
14060
|
};
|
|
14184
14061
|
}
|
|
14185
14062
|
|
|
14063
|
+
// ../../packages/node-runtime/src/ai/agent/history.ts
|
|
14064
|
+
function createEmptyPiUsage() {
|
|
14065
|
+
return {
|
|
14066
|
+
input: 0,
|
|
14067
|
+
output: 0,
|
|
14068
|
+
cacheRead: 0,
|
|
14069
|
+
cacheWrite: 0,
|
|
14070
|
+
totalTokens: 0,
|
|
14071
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }
|
|
14072
|
+
};
|
|
14073
|
+
}
|
|
14074
|
+
function isReplayableToolBlock(block) {
|
|
14075
|
+
if (block.type !== "tool") return false;
|
|
14076
|
+
const { toolCallId, result, status } = block.tool;
|
|
14077
|
+
return typeof toolCallId === "string" && toolCallId.length > 0 && typeof result === "string" && (status === "done" || status === "error");
|
|
14078
|
+
}
|
|
14079
|
+
function stripInternalParams(params) {
|
|
14080
|
+
if (!params) return {};
|
|
14081
|
+
const cleaned = {};
|
|
14082
|
+
for (const [key, value] of Object.entries(params)) {
|
|
14083
|
+
if (!key.startsWith("_")) cleaned[key] = value;
|
|
14084
|
+
}
|
|
14085
|
+
return cleaned;
|
|
14086
|
+
}
|
|
14087
|
+
function makeAssistantMessage(content, stopReason, modelInfo) {
|
|
14088
|
+
return {
|
|
14089
|
+
role: "assistant",
|
|
14090
|
+
content,
|
|
14091
|
+
api: modelInfo?.api ?? "openai-completions",
|
|
14092
|
+
provider: modelInfo?.provider ?? "chatlab",
|
|
14093
|
+
model: modelInfo?.id ?? "unknown",
|
|
14094
|
+
usage: createEmptyPiUsage(),
|
|
14095
|
+
stopReason,
|
|
14096
|
+
timestamp: Date.now()
|
|
14097
|
+
};
|
|
14098
|
+
}
|
|
14099
|
+
function replayAssistantBlocks(blocks, out, options) {
|
|
14100
|
+
const { modelInfo, thinkingSignature } = options ?? {};
|
|
14101
|
+
const replayThinking = !!thinkingSignature && blocks.some(isReplayableToolBlock);
|
|
14102
|
+
let content = [];
|
|
14103
|
+
for (const block of blocks) {
|
|
14104
|
+
if (block.type === "text") {
|
|
14105
|
+
if (block.text.trim()) content.push({ type: "text", text: block.text });
|
|
14106
|
+
} else if (block.type === "think" && replayThinking && block.text.trim()) {
|
|
14107
|
+
content.push({ type: "thinking", thinking: block.text, thinkingSignature });
|
|
14108
|
+
} else if (isReplayableToolBlock(block)) {
|
|
14109
|
+
content.push({
|
|
14110
|
+
type: "toolCall",
|
|
14111
|
+
id: block.tool.toolCallId,
|
|
14112
|
+
name: block.tool.name,
|
|
14113
|
+
arguments: stripInternalParams(block.tool.params)
|
|
14114
|
+
});
|
|
14115
|
+
out.push(makeAssistantMessage(content, "toolUse", modelInfo));
|
|
14116
|
+
out.push({
|
|
14117
|
+
role: "toolResult",
|
|
14118
|
+
toolCallId: block.tool.toolCallId,
|
|
14119
|
+
toolName: block.tool.name,
|
|
14120
|
+
content: [{ type: "text", text: truncateToolResultText(block.tool.result) || "(empty result)" }],
|
|
14121
|
+
isError: block.tool.isError ?? block.tool.status === "error",
|
|
14122
|
+
timestamp: Date.now()
|
|
14123
|
+
});
|
|
14124
|
+
content = [];
|
|
14125
|
+
}
|
|
14126
|
+
}
|
|
14127
|
+
if (content.length > 0) {
|
|
14128
|
+
out.push(makeAssistantMessage(content, "stop", modelInfo));
|
|
14129
|
+
}
|
|
14130
|
+
}
|
|
14131
|
+
function toPiHistoryMessages(messages, options) {
|
|
14132
|
+
const out = [];
|
|
14133
|
+
for (const msg of messages) {
|
|
14134
|
+
if (msg.role === "user") {
|
|
14135
|
+
out.push({
|
|
14136
|
+
role: "user",
|
|
14137
|
+
content: [{ type: "text", text: msg.content || "" }],
|
|
14138
|
+
timestamp: Date.now()
|
|
14139
|
+
});
|
|
14140
|
+
continue;
|
|
14141
|
+
}
|
|
14142
|
+
const replayable = msg.role === "assistant" && msg.contentBlocks?.some(isReplayableToolBlock);
|
|
14143
|
+
if (replayable) {
|
|
14144
|
+
replayAssistantBlocks(msg.contentBlocks, out, options);
|
|
14145
|
+
} else {
|
|
14146
|
+
out.push(makeAssistantMessage([{ type: "text", text: msg.content || "" }], "stop", options?.modelInfo));
|
|
14147
|
+
}
|
|
14148
|
+
}
|
|
14149
|
+
return out;
|
|
14150
|
+
}
|
|
14151
|
+
|
|
14186
14152
|
// ../../packages/node-runtime/src/ai/compression/compressor.ts
|
|
14187
14153
|
var DEFAULT_CONTEXT_WINDOW = 128e3;
|
|
14188
14154
|
var INITIAL_COMPRESSION_PROMPT = `You are a context compression assistant. Compress the conversation below into a structured summary.
|
|
@@ -14250,6 +14216,9 @@ async function checkAndCompress(aiChatId, config, systemPrompt, llmAdapter, conv
|
|
|
14250
14216
|
}
|
|
14251
14217
|
for (const msg of messages) {
|
|
14252
14218
|
historyForTokenCount.push({ role: msg.role, content: msg.content });
|
|
14219
|
+
for (const toolText of replayedToolResultTexts(msg.contentBlocks)) {
|
|
14220
|
+
historyForTokenCount.push({ role: "tool", content: toolText });
|
|
14221
|
+
}
|
|
14253
14222
|
}
|
|
14254
14223
|
const currentTokens = countMessagesTokens(historyForTokenCount, systemPrompt);
|
|
14255
14224
|
logger.info("Compression", `Token check: ${currentTokens} / ${thresholdTokens} (${contextWindow} window)`, {
|
|
@@ -14281,10 +14250,13 @@ async function checkAndCompress(aiChatId, config, systemPrompt, llmAdapter, conv
|
|
|
14281
14250
|
bufferBoundaryTimestamp: bufferBoundary,
|
|
14282
14251
|
compressedMessageCount: messagesToCompress.length
|
|
14283
14252
|
});
|
|
14284
|
-
const afterTokenCount = [
|
|
14285
|
-
|
|
14286
|
-
|
|
14287
|
-
|
|
14253
|
+
const afterTokenCount = [{ role: "assistant", content: summaryText }];
|
|
14254
|
+
for (const m of bufferMessages) {
|
|
14255
|
+
afterTokenCount.push({ role: m.role, content: m.content });
|
|
14256
|
+
for (const toolText of replayedToolResultTexts(m.contentBlocks)) {
|
|
14257
|
+
afterTokenCount.push({ role: "tool", content: toolText });
|
|
14258
|
+
}
|
|
14259
|
+
}
|
|
14288
14260
|
const tokensAfter = countMessagesTokens(afterTokenCount, systemPrompt);
|
|
14289
14261
|
if (tokensAfter >= thresholdTokens) {
|
|
14290
14262
|
logger.warn(
|
|
@@ -14312,11 +14284,22 @@ async function checkAndCompress(aiChatId, config, systemPrompt, llmAdapter, conv
|
|
|
14312
14284
|
return { compressed: false, reason: "error", error: String(error) };
|
|
14313
14285
|
}
|
|
14314
14286
|
}
|
|
14287
|
+
function replayedToolResultTexts(blocks) {
|
|
14288
|
+
if (!blocks) return [];
|
|
14289
|
+
return blocks.filter(isReplayableToolBlock).map((block) => truncateToolResultText(block.tool.result));
|
|
14290
|
+
}
|
|
14291
|
+
function countMessageTokensWithTools(msg) {
|
|
14292
|
+
let tokens = countTokens(msg.content) + 4;
|
|
14293
|
+
for (const toolText of replayedToolResultTexts(msg.contentBlocks)) {
|
|
14294
|
+
tokens += countTokens(toolText) + 4;
|
|
14295
|
+
}
|
|
14296
|
+
return tokens;
|
|
14297
|
+
}
|
|
14315
14298
|
function splitMessagesForCompression(messages, bufferTokenBudget) {
|
|
14316
14299
|
let bufferTokens = 0;
|
|
14317
14300
|
let splitIndex = messages.length;
|
|
14318
14301
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
14319
|
-
const msgTokens =
|
|
14302
|
+
const msgTokens = countMessageTokensWithTools(messages[i]);
|
|
14320
14303
|
if (bufferTokens + msgTokens > bufferTokenBudget) {
|
|
14321
14304
|
splitIndex = i + 1;
|
|
14322
14305
|
break;
|
|
@@ -14342,6 +14325,10 @@ ${existingSummary.content}
|
|
|
14342
14325
|
for (const msg of messagesToCompress) {
|
|
14343
14326
|
const roleLabel = msg.role === "user" ? "User" : "Assistant";
|
|
14344
14327
|
parts.push(`${roleLabel}: ${msg.content}`);
|
|
14328
|
+
for (const block of (msg.contentBlocks ?? []).filter(isReplayableToolBlock)) {
|
|
14329
|
+
parts.push(`[Tool result: ${block.tool.name}]
|
|
14330
|
+
${truncateToolResultText(block.tool.result)}`);
|
|
14331
|
+
}
|
|
14345
14332
|
}
|
|
14346
14333
|
return parts.join("\n\n");
|
|
14347
14334
|
}
|
|
@@ -14826,6 +14813,7 @@ function formatToolResultAsText(details) {
|
|
|
14826
14813
|
const messages = details.messages;
|
|
14827
14814
|
for (const [key, value] of Object.entries(details)) {
|
|
14828
14815
|
if (key === "messages") continue;
|
|
14816
|
+
if (key === "rawMessages") continue;
|
|
14829
14817
|
if (value === void 0 || value === null) continue;
|
|
14830
14818
|
if (typeof value === "object") {
|
|
14831
14819
|
if ("start" in value && "end" in value) {
|
|
@@ -14964,40 +14952,9 @@ import {
|
|
|
14964
14952
|
} from "@earendil-works/pi-ai";
|
|
14965
14953
|
|
|
14966
14954
|
// ../../packages/node-runtime/src/ai/agent/constants.ts
|
|
14967
|
-
var DEFAULT_MAX_TOOL_ROUNDS =
|
|
14955
|
+
var DEFAULT_MAX_TOOL_ROUNDS = 20;
|
|
14968
14956
|
|
|
14969
14957
|
// ../../packages/node-runtime/src/ai/agent/core.ts
|
|
14970
|
-
function createEmptyPiUsage() {
|
|
14971
|
-
return {
|
|
14972
|
-
input: 0,
|
|
14973
|
-
output: 0,
|
|
14974
|
-
cacheRead: 0,
|
|
14975
|
-
cacheWrite: 0,
|
|
14976
|
-
totalTokens: 0,
|
|
14977
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }
|
|
14978
|
-
};
|
|
14979
|
-
}
|
|
14980
|
-
function toPiHistoryMessages(messages) {
|
|
14981
|
-
return messages.map((msg) => {
|
|
14982
|
-
if (msg.role === "user") {
|
|
14983
|
-
return {
|
|
14984
|
-
role: "user",
|
|
14985
|
-
content: [{ type: "text", text: msg.content || "" }],
|
|
14986
|
-
timestamp: Date.now()
|
|
14987
|
-
};
|
|
14988
|
-
}
|
|
14989
|
-
return {
|
|
14990
|
-
role: "assistant",
|
|
14991
|
-
content: [{ type: "text", text: msg.content || "" }],
|
|
14992
|
-
api: "openai-completions",
|
|
14993
|
-
provider: "chatlab",
|
|
14994
|
-
model: "unknown",
|
|
14995
|
-
usage: createEmptyPiUsage(),
|
|
14996
|
-
stopReason: "stop",
|
|
14997
|
-
timestamp: Date.now()
|
|
14998
|
-
};
|
|
14999
|
-
});
|
|
15000
|
-
}
|
|
15001
14958
|
function isPiMessage(message) {
|
|
15002
14959
|
return message.role === "user" || message.role === "assistant" || message.role === "toolResult";
|
|
15003
14960
|
}
|
|
@@ -15018,7 +14975,13 @@ async function runAgentCore(options) {
|
|
|
15018
14975
|
} = options;
|
|
15019
14976
|
await initTokenizer();
|
|
15020
14977
|
const resolvedStreamFn = options.streamFn ?? defaultStreamSimple;
|
|
15021
|
-
const totalUsage = {
|
|
14978
|
+
const totalUsage = {
|
|
14979
|
+
promptTokens: 0,
|
|
14980
|
+
completionTokens: 0,
|
|
14981
|
+
totalTokens: 0,
|
|
14982
|
+
cacheReadTokens: 0,
|
|
14983
|
+
cacheWriteTokens: 0
|
|
14984
|
+
};
|
|
15022
14985
|
const toolsUsed = [];
|
|
15023
14986
|
let toolRounds = 0;
|
|
15024
14987
|
const addPiUsage = (usage) => {
|
|
@@ -15026,6 +14989,8 @@ async function runAgentCore(options) {
|
|
|
15026
14989
|
totalUsage.promptTokens += usage.input || 0;
|
|
15027
14990
|
totalUsage.completionTokens += usage.output || 0;
|
|
15028
14991
|
totalUsage.totalTokens += usage.totalTokens || usage.input + usage.output || 0;
|
|
14992
|
+
totalUsage.cacheReadTokens += usage.cacheRead || 0;
|
|
14993
|
+
totalUsage.cacheWriteTokens += usage.cacheWrite || 0;
|
|
15029
14994
|
};
|
|
15030
14995
|
if (abortSignal?.aborted) {
|
|
15031
14996
|
return { usage: totalUsage, finalMessages: [], toolsUsed: [], toolRounds: 0 };
|
|
@@ -15045,21 +15010,18 @@ async function runAgentCore(options) {
|
|
|
15045
15010
|
return clampThinkingLevel(piModel, level);
|
|
15046
15011
|
})();
|
|
15047
15012
|
const finalThinkingLevel = resolvedThinkingLevel ?? (piModel.reasoning ? void 0 : "off");
|
|
15048
|
-
|
|
15049
|
-
|
|
15050
|
-
|
|
15051
|
-
|
|
15052
|
-
|
|
15053
|
-
resolved: resolvedThinkingLevel,
|
|
15054
|
-
final: finalThinkingLevel
|
|
15055
|
-
});
|
|
15013
|
+
const thinkingFormat = piModel.compat?.thinkingFormat;
|
|
15014
|
+
const replayOptions = piModel.reasoning && thinkingFormat === "deepseek" ? {
|
|
15015
|
+
modelInfo: { api: piModel.api, provider: piModel.provider, id: piModel.id },
|
|
15016
|
+
thinkingSignature: "reasoning_content"
|
|
15017
|
+
} : void 0;
|
|
15056
15018
|
const coreAgent = new PiAgentCore({
|
|
15057
15019
|
initialState: {
|
|
15058
15020
|
systemPrompt,
|
|
15059
15021
|
model: effectiveModel,
|
|
15060
15022
|
thinkingLevel: finalThinkingLevel,
|
|
15061
15023
|
tools: maxToolRounds > 0 ? tools : [],
|
|
15062
|
-
messages: toPiHistoryMessages(history)
|
|
15024
|
+
messages: toPiHistoryMessages(history, replayOptions)
|
|
15063
15025
|
},
|
|
15064
15026
|
getApiKey: () => apiKey,
|
|
15065
15027
|
streamFn: resolvedStreamFn,
|
|
@@ -15119,11 +15081,18 @@ async function runAgentCore(options) {
|
|
|
15119
15081
|
toolsUsed.push(event.toolName);
|
|
15120
15082
|
onEvent({
|
|
15121
15083
|
type: "tool_start",
|
|
15084
|
+
toolCallId: event.toolCallId,
|
|
15122
15085
|
toolName: event.toolName,
|
|
15123
15086
|
toolParams: event.args || {}
|
|
15124
15087
|
});
|
|
15125
15088
|
} else if (event.type === "tool_execution_end") {
|
|
15126
|
-
onEvent({
|
|
15089
|
+
onEvent({
|
|
15090
|
+
type: "tool_end",
|
|
15091
|
+
toolCallId: event.toolCallId,
|
|
15092
|
+
toolName: event.toolName,
|
|
15093
|
+
toolResult: event.result,
|
|
15094
|
+
isError: event.isError
|
|
15095
|
+
});
|
|
15127
15096
|
} else if (event.type === "turn_end") {
|
|
15128
15097
|
const hadToolCalls = event.toolResults.length > 0;
|
|
15129
15098
|
if (hadToolCalls) {
|
|
@@ -15182,6 +15151,584 @@ async function runAgentCore(options) {
|
|
|
15182
15151
|
}
|
|
15183
15152
|
}
|
|
15184
15153
|
|
|
15154
|
+
// ../../packages/node-runtime/src/ai/agent/data-snapshot.ts
|
|
15155
|
+
function roundShare(value) {
|
|
15156
|
+
if (!Number.isFinite(value)) return 0;
|
|
15157
|
+
return Math.round(value * 10) / 10;
|
|
15158
|
+
}
|
|
15159
|
+
function formatNullableTimestamp(timestamp) {
|
|
15160
|
+
return typeof timestamp === "number" && Number.isFinite(timestamp) ? String(timestamp) : "null";
|
|
15161
|
+
}
|
|
15162
|
+
function formatSharePercent(share) {
|
|
15163
|
+
if (!Number.isFinite(share)) return "0%";
|
|
15164
|
+
const rounded = Math.round(share * 10) / 10;
|
|
15165
|
+
return Number.isInteger(rounded) ? `${rounded}%` : `${rounded.toFixed(1)}%`;
|
|
15166
|
+
}
|
|
15167
|
+
function createDataSnapshotFromOverview(overview) {
|
|
15168
|
+
if (!overview) return void 0;
|
|
15169
|
+
const topMembers = overview.topMembers ?? [];
|
|
15170
|
+
return {
|
|
15171
|
+
version: 2,
|
|
15172
|
+
name: overview.name,
|
|
15173
|
+
platform: overview.platform,
|
|
15174
|
+
type: overview.type,
|
|
15175
|
+
totalMessages: overview.totalMessages,
|
|
15176
|
+
totalMembers: overview.totalMembers,
|
|
15177
|
+
firstMessageTs: overview.firstMessageTs,
|
|
15178
|
+
lastMessageTs: overview.lastMessageTs,
|
|
15179
|
+
activeMemberHints: topMembers.slice(0, 10).map((member) => ({
|
|
15180
|
+
memberId: member.id,
|
|
15181
|
+
displayName: member.name,
|
|
15182
|
+
messageCount: member.count,
|
|
15183
|
+
share: overview.totalMessages > 0 ? roundShare(member.count / overview.totalMessages * 100) : 0
|
|
15184
|
+
})),
|
|
15185
|
+
segmentSummaries: {
|
|
15186
|
+
availableCount: overview.summaryCount ?? 0
|
|
15187
|
+
}
|
|
15188
|
+
};
|
|
15189
|
+
}
|
|
15190
|
+
function formatDataSnapshotForRouter(dataSnapshot) {
|
|
15191
|
+
if (!dataSnapshot) return "(none)";
|
|
15192
|
+
return [
|
|
15193
|
+
`name: ${dataSnapshot.name}`,
|
|
15194
|
+
`platform: ${dataSnapshot.platform}`,
|
|
15195
|
+
`type: ${dataSnapshot.type}`,
|
|
15196
|
+
`total_messages: ${dataSnapshot.totalMessages}`,
|
|
15197
|
+
`total_members: ${dataSnapshot.totalMembers}`,
|
|
15198
|
+
`first_message_ts: ${formatNullableTimestamp(dataSnapshot.firstMessageTs)}`,
|
|
15199
|
+
`last_message_ts: ${formatNullableTimestamp(dataSnapshot.lastMessageTs)}`,
|
|
15200
|
+
`segment_summaries_available: ${dataSnapshot.segmentSummaries?.availableCount ?? 0}`,
|
|
15201
|
+
`active_member_hint_count: ${dataSnapshot.activeMemberHints?.length ?? 0}`
|
|
15202
|
+
].join("\n");
|
|
15203
|
+
}
|
|
15204
|
+
function formatDataSnapshotForPlanner(dataSnapshot) {
|
|
15205
|
+
if (!dataSnapshot) return "(none)";
|
|
15206
|
+
const memberHints = dataSnapshot.activeMemberHints ?? [];
|
|
15207
|
+
const memberHintLines = memberHints.length > 0 ? memberHints.map(
|
|
15208
|
+
(member, index) => `${index + 1}. member_id=${member.memberId} | display_name=${member.displayName} | messages=${member.messageCount} | share=${formatSharePercent(member.share)}`
|
|
15209
|
+
).join("\n") : "(none)";
|
|
15210
|
+
return `${formatDataSnapshotForRouter(dataSnapshot)}
|
|
15211
|
+
active_member_hints:
|
|
15212
|
+
${memberHintLines}
|
|
15213
|
+
notes:
|
|
15214
|
+
- member_id is a tool lookup hint; display_name may not be unique.
|
|
15215
|
+
- Active member hints reflect historical total message volume, not recent activity.
|
|
15216
|
+
- Use real current date for relative ranges; database bounds only describe data coverage.
|
|
15217
|
+
- Do not plan a tool call only to rediscover min/max timestamp.
|
|
15218
|
+
- When using default recent-day tools, choose a range that intersects database bounds instead of probing an empty real-current-date window first.`;
|
|
15219
|
+
}
|
|
15220
|
+
|
|
15221
|
+
// ../../packages/node-runtime/src/ai/agent/router.ts
|
|
15222
|
+
import {
|
|
15223
|
+
completeSimple as completeSimple2
|
|
15224
|
+
} from "@earendil-works/pi-ai";
|
|
15225
|
+
var DEFAULT_LLM_FALLBACK_CONFIDENCE_THRESHOLD = 0.6;
|
|
15226
|
+
function clampConfidence(value) {
|
|
15227
|
+
if (!Number.isFinite(value)) return 0;
|
|
15228
|
+
return Math.max(0, Math.min(1, value));
|
|
15229
|
+
}
|
|
15230
|
+
function normalizeText(text) {
|
|
15231
|
+
return text.trim().replace(/\s+/g, " ");
|
|
15232
|
+
}
|
|
15233
|
+
function matchAny(text, patterns) {
|
|
15234
|
+
return patterns.some((pattern) => pattern.test(text));
|
|
15235
|
+
}
|
|
15236
|
+
function isRoute(value) {
|
|
15237
|
+
return value === "direct_response" || value === "tool_assisted" || value === "planned_execution";
|
|
15238
|
+
}
|
|
15239
|
+
function resultToText(result) {
|
|
15240
|
+
return typeof result === "string" ? { text: result } : result;
|
|
15241
|
+
}
|
|
15242
|
+
function extractJsonObject3(text) {
|
|
15243
|
+
const fenced = text.match(/```(?:json)?\s*([\s\S]*?)```/i);
|
|
15244
|
+
if (fenced?.[1]) return fenced[1].trim();
|
|
15245
|
+
const start = text.indexOf("{");
|
|
15246
|
+
const end = text.lastIndexOf("}");
|
|
15247
|
+
if (start >= 0 && end > start) return text.slice(start, end + 1);
|
|
15248
|
+
return text.trim();
|
|
15249
|
+
}
|
|
15250
|
+
function parseLlmDecision(rawText, usage) {
|
|
15251
|
+
try {
|
|
15252
|
+
const parsed = JSON.parse(extractJsonObject3(rawText));
|
|
15253
|
+
if (!isRoute(parsed.route)) return null;
|
|
15254
|
+
return {
|
|
15255
|
+
route: parsed.route,
|
|
15256
|
+
confidence: clampConfidence(typeof parsed.confidence === "number" ? parsed.confidence : 0.5),
|
|
15257
|
+
reason: typeof parsed.reason === "string" && parsed.reason.trim() ? parsed.reason.trim() : "LLM route decision.",
|
|
15258
|
+
source: "llm",
|
|
15259
|
+
usage
|
|
15260
|
+
};
|
|
15261
|
+
} catch {
|
|
15262
|
+
return null;
|
|
15263
|
+
}
|
|
15264
|
+
}
|
|
15265
|
+
function buildLlmRouterPrompt(input, ruleDecision2) {
|
|
15266
|
+
const toolNames = input.availableTools?.length ? input.availableTools.join(", ") : "(none)";
|
|
15267
|
+
const dataSnapshot = formatDataSnapshotForRouter(input.dataSnapshot);
|
|
15268
|
+
return `Classify the user's ChatLab request into exactly one route.
|
|
15269
|
+
|
|
15270
|
+
Routes:
|
|
15271
|
+
- direct_response: no local chat data/tools needed.
|
|
15272
|
+
- tool_assisted: local chat data/tools needed, but the task is simple.
|
|
15273
|
+
- planned_execution: complex analysis, multi-step evidence gathering, retries, long-range comparison, relationship analysis, or insufficient-evidence handling.
|
|
15274
|
+
|
|
15275
|
+
Return strict JSON only:
|
|
15276
|
+
{"route":"direct_response|tool_assisted|planned_execution","confidence":0.0,"reason":"short reason"}
|
|
15277
|
+
|
|
15278
|
+
Context:
|
|
15279
|
+
- locale: ${input.locale}
|
|
15280
|
+
- chatType: ${input.chatType}
|
|
15281
|
+
- availableTools: ${toolNames}
|
|
15282
|
+
- dataSnapshot: ${dataSnapshot}
|
|
15283
|
+
- assistantSummary: ${input.assistantSummary ?? "(none)"}
|
|
15284
|
+
- skillSummary: ${input.skillSummary ?? "(none)"}
|
|
15285
|
+
- recentIntentSummary: ${input.recentIntentSummary ?? "(none)"}
|
|
15286
|
+
- ruleDecision: ${ruleDecision2.route}, confidence=${ruleDecision2.confidence}, reason=${ruleDecision2.reason}
|
|
15287
|
+
|
|
15288
|
+
User request:
|
|
15289
|
+
${input.userMessage}`;
|
|
15290
|
+
}
|
|
15291
|
+
function directRuleDecision(text) {
|
|
15292
|
+
if (matchAny(text, [/不用查聊天记录|不用查询|不用查数据|不用看本地数据/i, /润色|改写|翻译|polish|rewrite|translate/i])) {
|
|
15293
|
+
return {
|
|
15294
|
+
route: "direct_response",
|
|
15295
|
+
confidence: 0.95,
|
|
15296
|
+
reason: "User explicitly asked for a non-data response.",
|
|
15297
|
+
source: "rule"
|
|
15298
|
+
};
|
|
15299
|
+
}
|
|
15300
|
+
if (matchAny(text, [/什么是|解释一下|概念|区别|explain|briefly explain|why .*function calling|react/i])) {
|
|
15301
|
+
return {
|
|
15302
|
+
route: "direct_response",
|
|
15303
|
+
confidence: 0.86,
|
|
15304
|
+
reason: "Conceptual explanation without local chat-data dependency.",
|
|
15305
|
+
source: "rule"
|
|
15306
|
+
};
|
|
15307
|
+
}
|
|
15308
|
+
if (matchAny(text, [/日志在哪里|怎么配置|设置|帮助|help|where .*log/i])) {
|
|
15309
|
+
return {
|
|
15310
|
+
route: "direct_response",
|
|
15311
|
+
confidence: 0.84,
|
|
15312
|
+
reason: "Help or configuration request does not require chat tools.",
|
|
15313
|
+
source: "rule"
|
|
15314
|
+
};
|
|
15315
|
+
}
|
|
15316
|
+
if (matchAny(text, [/你觉得|闲聊|随便聊聊|建议我|should i/i])) {
|
|
15317
|
+
return {
|
|
15318
|
+
route: "direct_response",
|
|
15319
|
+
confidence: 0.78,
|
|
15320
|
+
reason: "Conversational request without clear data dependency.",
|
|
15321
|
+
source: "rule"
|
|
15322
|
+
};
|
|
15323
|
+
}
|
|
15324
|
+
return null;
|
|
15325
|
+
}
|
|
15326
|
+
function plannedRuleDecision(text) {
|
|
15327
|
+
if (matchAny(text, [/如果.*找不到.*继续查|换几个相关|换几个.*继续|search.*if.*not.*found/i])) {
|
|
15328
|
+
return {
|
|
15329
|
+
route: "planned_execution",
|
|
15330
|
+
confidence: 0.88,
|
|
15331
|
+
reason: "Request asks for search failure recovery and retry strategy.",
|
|
15332
|
+
source: "rule"
|
|
15333
|
+
};
|
|
15334
|
+
}
|
|
15335
|
+
const dimensions = [
|
|
15336
|
+
matchAny(text, [/分析|复盘|总结.*规律|趋势|变化|演变|compare|comparison/i]),
|
|
15337
|
+
matchAny(text, [
|
|
15338
|
+
/过去一年|最近一年|近一年|过去.*年|最近半年|今年|去年|上半年|下半年|长期|按季度|按月份|first half|second half/i
|
|
15339
|
+
]),
|
|
15340
|
+
matchAny(text, [/关系|互动|影响力|核心成员|最强|最活跃|被忽略|主动|回应|turning point|转折点/i]),
|
|
15341
|
+
matchAny(text, [/证据|举出|例子|关键分歧|主要矛盾|evidence/i]),
|
|
15342
|
+
matchAny(text, [/并且|同时|以及|分别|每个阶段|按阶段|阶段|多条件|参与|回复|话题|主题|发言规律|topic|theme/i]),
|
|
15343
|
+
matchAny(text, [/证据不够|不足以|不够|uncertain|insufficient/i])
|
|
15344
|
+
];
|
|
15345
|
+
const score = dimensions.filter(Boolean).length;
|
|
15346
|
+
if (score >= 2) {
|
|
15347
|
+
return {
|
|
15348
|
+
route: "planned_execution",
|
|
15349
|
+
confidence: Math.min(0.95, 0.72 + score * 0.04),
|
|
15350
|
+
reason: `Rule matched ${score} complex-analysis signals.`,
|
|
15351
|
+
source: "rule"
|
|
15352
|
+
};
|
|
15353
|
+
}
|
|
15354
|
+
return null;
|
|
15355
|
+
}
|
|
15356
|
+
function toolRuleDecision(text) {
|
|
15357
|
+
if (matchAny(text, [
|
|
15358
|
+
/一共有多少|多少成员|多少条消息|谁发言最多|前\s*\d+\s*名|top\s*\d+/i,
|
|
15359
|
+
/异常活跃|活跃度|发言最多|message count|member count/i
|
|
15360
|
+
])) {
|
|
15361
|
+
return {
|
|
15362
|
+
route: "tool_assisted",
|
|
15363
|
+
confidence: 0.82,
|
|
15364
|
+
reason: "Simple statistics request can be answered by one or a few tools.",
|
|
15365
|
+
source: "rule"
|
|
15366
|
+
};
|
|
15367
|
+
}
|
|
15368
|
+
if (matchAny(text, [
|
|
15369
|
+
/找一下|查一下|有没有聊到|有没有提过|最近提到|昨天.*聊了什么|最近.*发言/i,
|
|
15370
|
+
/search|find|mentioned|talked about/i
|
|
15371
|
+
])) {
|
|
15372
|
+
return {
|
|
15373
|
+
route: "tool_assisted",
|
|
15374
|
+
confidence: 0.78,
|
|
15375
|
+
reason: "Simple search or lookup request with a single clear target.",
|
|
15376
|
+
source: "rule"
|
|
15377
|
+
};
|
|
15378
|
+
}
|
|
15379
|
+
return null;
|
|
15380
|
+
}
|
|
15381
|
+
function ruleDecision(input) {
|
|
15382
|
+
const text = normalizeText(input.userMessage);
|
|
15383
|
+
return plannedRuleDecision(text) ?? toolRuleDecision(text) ?? directRuleDecision(text) ?? {
|
|
15384
|
+
route: "tool_assisted",
|
|
15385
|
+
confidence: 0.45,
|
|
15386
|
+
reason: "Ambiguous request; conservatively keep the existing tool-assisted Agent path.",
|
|
15387
|
+
source: "rule"
|
|
15388
|
+
};
|
|
15389
|
+
}
|
|
15390
|
+
async function decideRequestRoute(input, options = {}) {
|
|
15391
|
+
const decision = ruleDecision(input);
|
|
15392
|
+
const threshold = options.llmFallbackConfidenceThreshold ?? DEFAULT_LLM_FALLBACK_CONFIDENCE_THRESHOLD;
|
|
15393
|
+
if (decision.confidence >= threshold || !options.llmRouter) {
|
|
15394
|
+
return { ...decision, confidence: clampConfidence(decision.confidence) };
|
|
15395
|
+
}
|
|
15396
|
+
const llmDecision = await options.llmRouter(input, decision);
|
|
15397
|
+
return {
|
|
15398
|
+
...llmDecision,
|
|
15399
|
+
confidence: clampConfidence(llmDecision.confidence)
|
|
15400
|
+
};
|
|
15401
|
+
}
|
|
15402
|
+
function createLlmRouteDecider(options) {
|
|
15403
|
+
return async (input, ruleDecision2) => {
|
|
15404
|
+
const prompt = buildLlmRouterPrompt(input, ruleDecision2);
|
|
15405
|
+
try {
|
|
15406
|
+
const rawResult = options.complete ? await options.complete(prompt, options.abortSignal) : await completeWithPiAi(prompt, options);
|
|
15407
|
+
const { text, usage } = resultToText(rawResult);
|
|
15408
|
+
const decision = parseLlmDecision(text, usage);
|
|
15409
|
+
if (decision) return decision;
|
|
15410
|
+
return {
|
|
15411
|
+
...ruleDecision2,
|
|
15412
|
+
reason: `${ruleDecision2.reason} LLM fallback returned invalid route JSON.`
|
|
15413
|
+
};
|
|
15414
|
+
} catch (error) {
|
|
15415
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
15416
|
+
return {
|
|
15417
|
+
...ruleDecision2,
|
|
15418
|
+
reason: `${ruleDecision2.reason} LLM fallback failed: ${message}`
|
|
15419
|
+
};
|
|
15420
|
+
}
|
|
15421
|
+
};
|
|
15422
|
+
}
|
|
15423
|
+
async function completeWithPiAi(prompt, options) {
|
|
15424
|
+
if (!options.piModel || !options.apiKey) {
|
|
15425
|
+
throw new Error("LLM router requires piModel and apiKey");
|
|
15426
|
+
}
|
|
15427
|
+
const result = await completeSimple2(
|
|
15428
|
+
options.piModel,
|
|
15429
|
+
{
|
|
15430
|
+
systemPrompt: "You are a strict JSON classifier for ChatLab AI routing. Return JSON only.",
|
|
15431
|
+
messages: [{ role: "user", content: [{ type: "text", text: prompt }], timestamp: Date.now() }]
|
|
15432
|
+
},
|
|
15433
|
+
{
|
|
15434
|
+
apiKey: options.apiKey,
|
|
15435
|
+
maxTokens: options.maxTokens ?? 180,
|
|
15436
|
+
temperature: options.temperature ?? 0,
|
|
15437
|
+
signal: options.abortSignal
|
|
15438
|
+
}
|
|
15439
|
+
);
|
|
15440
|
+
const text = result.content.filter((item) => item.type === "text").map((item) => item.text).join("");
|
|
15441
|
+
return {
|
|
15442
|
+
text,
|
|
15443
|
+
usage: {
|
|
15444
|
+
promptTokens: result.usage?.input,
|
|
15445
|
+
completionTokens: result.usage?.output,
|
|
15446
|
+
totalTokens: result.usage?.totalTokens
|
|
15447
|
+
}
|
|
15448
|
+
};
|
|
15449
|
+
}
|
|
15450
|
+
|
|
15451
|
+
// ../../packages/node-runtime/src/ai/agent/planner.ts
|
|
15452
|
+
import {
|
|
15453
|
+
completeSimple as completeSimple3,
|
|
15454
|
+
streamSimple
|
|
15455
|
+
} from "@earendil-works/pi-ai";
|
|
15456
|
+
var PLAN_INTENTS = [
|
|
15457
|
+
"summary",
|
|
15458
|
+
"trend",
|
|
15459
|
+
"relationship",
|
|
15460
|
+
"search",
|
|
15461
|
+
"comparison",
|
|
15462
|
+
"mixed"
|
|
15463
|
+
];
|
|
15464
|
+
var STREAM_MARKER_HOLDBACK_CHARS = Math.max("</draft>".length, "</plan>".length, "<json>".length) - 1;
|
|
15465
|
+
function isRecord2(value) {
|
|
15466
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
15467
|
+
}
|
|
15468
|
+
function isIntent(value) {
|
|
15469
|
+
return typeof value === "string" && PLAN_INTENTS.includes(value);
|
|
15470
|
+
}
|
|
15471
|
+
function normalizeString(value) {
|
|
15472
|
+
if (typeof value !== "string") return null;
|
|
15473
|
+
const text = value.trim();
|
|
15474
|
+
return text.length > 0 ? text : null;
|
|
15475
|
+
}
|
|
15476
|
+
function extractJsonObject4(text) {
|
|
15477
|
+
const fenced = text.match(/```(?:json)?\s*([\s\S]*?)```/i);
|
|
15478
|
+
if (fenced?.[1]) return fenced[1].trim();
|
|
15479
|
+
const start = text.indexOf("{");
|
|
15480
|
+
const end = text.lastIndexOf("}");
|
|
15481
|
+
if (start >= 0 && end > start) return text.slice(start, end + 1);
|
|
15482
|
+
return text.trim();
|
|
15483
|
+
}
|
|
15484
|
+
function parsePlanJson(rawText, availableTools) {
|
|
15485
|
+
try {
|
|
15486
|
+
const parsed = JSON.parse(extractJsonObject4(rawText));
|
|
15487
|
+
if (!isRecord2(parsed)) return null;
|
|
15488
|
+
const title = normalizeString(parsed.title);
|
|
15489
|
+
if (!title || !isIntent(parsed.intent) || !Array.isArray(parsed.steps)) return null;
|
|
15490
|
+
const steps = parsed.steps.filter(isRecord2).map((step) => {
|
|
15491
|
+
const goal = normalizeString(step.goal);
|
|
15492
|
+
const evidenceNeeded = normalizeString(step.evidenceNeeded);
|
|
15493
|
+
if (!goal || !evidenceNeeded) return null;
|
|
15494
|
+
const suggestedTools = Array.isArray(step.suggestedTools) ? step.suggestedTools.filter((tool) => typeof tool === "string" && availableTools.has(tool)) : [];
|
|
15495
|
+
return { goal, suggestedTools: Array.from(new Set(suggestedTools)), evidenceNeeded };
|
|
15496
|
+
}).filter((step) => step !== null).slice(0, 5);
|
|
15497
|
+
if (steps.length === 0) return null;
|
|
15498
|
+
const successCriteria = Array.isArray(parsed.successCriteria) ? parsed.successCriteria.map(normalizeString).filter((item) => item !== null).slice(0, 5) : [];
|
|
15499
|
+
if (successCriteria.length === 0) return null;
|
|
15500
|
+
return {
|
|
15501
|
+
version: 1,
|
|
15502
|
+
title,
|
|
15503
|
+
route: "planned_execution",
|
|
15504
|
+
intent: parsed.intent,
|
|
15505
|
+
steps,
|
|
15506
|
+
successCriteria
|
|
15507
|
+
};
|
|
15508
|
+
} catch {
|
|
15509
|
+
return null;
|
|
15510
|
+
}
|
|
15511
|
+
}
|
|
15512
|
+
function resultToText2(result) {
|
|
15513
|
+
return typeof result === "string" ? result : result.text;
|
|
15514
|
+
}
|
|
15515
|
+
function buildPlannerPrompt(input) {
|
|
15516
|
+
const dataSnapshot = formatDataSnapshotForPlanner(input.dataSnapshot);
|
|
15517
|
+
const availableCapabilities = input.availableCapabilities && input.availableCapabilities.length > 0 ? input.availableCapabilities.map((capability) => {
|
|
15518
|
+
const tools = capability.tools.join(", ") || "none";
|
|
15519
|
+
return ` - ${capability.id} (${capability.label}; tools: ${tools}): ${capability.guidance}`;
|
|
15520
|
+
}).join("\n") : "(none)";
|
|
15521
|
+
return `Create a concise user-visible analysis plan for a ChatLab planned_execution request.
|
|
15522
|
+
|
|
15523
|
+
Return exactly three blocks:
|
|
15524
|
+
<draft>
|
|
15525
|
+
A brief user-visible planning note in the user's locale. Keep it high-level; do not reveal hidden chain-of-thought.
|
|
15526
|
+
</draft>
|
|
15527
|
+
<plan>
|
|
15528
|
+
A concise user-facing analysis approach in the user's locale. Do not include suggested tools, evidence fields, or success criteria; those details belong in <json>.
|
|
15529
|
+
</plan>
|
|
15530
|
+
<json>
|
|
15531
|
+
{
|
|
15532
|
+
"title": "short title",
|
|
15533
|
+
"intent": "summary|trend|relationship|search|comparison|mixed",
|
|
15534
|
+
"steps": [
|
|
15535
|
+
{"goal": "what to investigate", "suggestedTools": ["tool_name"], "evidenceNeeded": "what evidence is needed"}
|
|
15536
|
+
],
|
|
15537
|
+
"successCriteria": ["criterion"]
|
|
15538
|
+
}
|
|
15539
|
+
</json>
|
|
15540
|
+
|
|
15541
|
+
Limits:
|
|
15542
|
+
- Max 5 steps.
|
|
15543
|
+
- Max 5 successCriteria.
|
|
15544
|
+
- suggestedTools must come only from availableTools.
|
|
15545
|
+
- If availableCapabilities are listed, you may plan steps that use their tools when the capability helps the user.
|
|
15546
|
+
- Do not reveal hidden chain-of-thought; draft and plan are user-readable summaries only.
|
|
15547
|
+
- The plan is soft guidance, not a mandatory execution script.
|
|
15548
|
+
|
|
15549
|
+
Planning strategy:
|
|
15550
|
+
- For open-ended topic, community profile, influence, interaction-pattern, or multi-dimensional retrospective analysis, first plan a lightweight reconnaissance step to build a topic/member activity map before drawing conclusions.
|
|
15551
|
+
- Prefer segment summaries, keyword frequency, time distribution, member activity, and representative message retrieval when available.
|
|
15552
|
+
- Do not create a dedicated step whose only purpose is finding max timestamp or confirming latest message time.
|
|
15553
|
+
|
|
15554
|
+
Context:
|
|
15555
|
+
- locale: ${input.locale}
|
|
15556
|
+
- chatType: ${input.chatType}
|
|
15557
|
+
- availableTools: ${input.availableTools.join(", ") || "(none)"}
|
|
15558
|
+
- availableCapabilities:
|
|
15559
|
+
${availableCapabilities}
|
|
15560
|
+
- dataSnapshot: ${dataSnapshot}
|
|
15561
|
+
- assistantSummary: ${input.assistantSummary ?? "(none)"}
|
|
15562
|
+
- skillSummary: ${input.skillSummary ?? "(none)"}
|
|
15563
|
+
- recentIntentSummary: ${input.recentIntentSummary ?? "(none)"}
|
|
15564
|
+
|
|
15565
|
+
User request:
|
|
15566
|
+
${input.userMessage}`;
|
|
15567
|
+
}
|
|
15568
|
+
function createAnalysisPlanner(options) {
|
|
15569
|
+
return async (input, signal) => {
|
|
15570
|
+
try {
|
|
15571
|
+
const prompt = buildPlannerPrompt(input);
|
|
15572
|
+
const callbacks = {
|
|
15573
|
+
onPlanDelta: options.onPlanDelta ?? (() => {
|
|
15574
|
+
}),
|
|
15575
|
+
onThinkingDelta: options.onThinkingDelta,
|
|
15576
|
+
onThinkingEnd: options.onThinkingEnd,
|
|
15577
|
+
onValidationDelta: options.onValidationDelta,
|
|
15578
|
+
onValidationEnd: options.onValidationEnd
|
|
15579
|
+
};
|
|
15580
|
+
const rawResult = options.stream ? await options.stream(prompt, callbacks, signal) : options.complete ? await options.complete(prompt, signal) : options.onPlanDelta ? await streamWithPiAi(prompt, options, signal) : await completeWithPiAi2(prompt, options, signal);
|
|
15581
|
+
return parsePlanJson(resultToText2(rawResult), new Set(input.availableTools));
|
|
15582
|
+
} catch {
|
|
15583
|
+
return null;
|
|
15584
|
+
}
|
|
15585
|
+
};
|
|
15586
|
+
}
|
|
15587
|
+
function createPlanContentBlock(plan, status = "created") {
|
|
15588
|
+
return {
|
|
15589
|
+
type: "plan",
|
|
15590
|
+
version: 1,
|
|
15591
|
+
status,
|
|
15592
|
+
plan
|
|
15593
|
+
};
|
|
15594
|
+
}
|
|
15595
|
+
function buildPlanGuidance(plan) {
|
|
15596
|
+
const steps = plan.steps.map((step, index) => {
|
|
15597
|
+
const tools = step.suggestedTools.length > 0 ? step.suggestedTools.join(", ") : "none";
|
|
15598
|
+
return `${index + 1}. ${step.goal}
|
|
15599
|
+
Evidence needed: ${step.evidenceNeeded}
|
|
15600
|
+
Suggested tools: ${tools}`;
|
|
15601
|
+
}).join("\n");
|
|
15602
|
+
const successCriteria = plan.successCriteria.map((item) => `- ${item}`).join("\n");
|
|
15603
|
+
return `A suggested analysis plan is available below. Use it as guidance when helpful, but do not follow it mechanically if the user's question can be answered more directly.
|
|
15604
|
+
|
|
15605
|
+
Plan title: ${plan.title}
|
|
15606
|
+
Intent: ${plan.intent}
|
|
15607
|
+
|
|
15608
|
+
Steps:
|
|
15609
|
+
${steps}
|
|
15610
|
+
|
|
15611
|
+
Success criteria:
|
|
15612
|
+
${successCriteria}`;
|
|
15613
|
+
}
|
|
15614
|
+
async function completeWithPiAi2(prompt, options, signal) {
|
|
15615
|
+
if (!options.piModel || !options.apiKey) {
|
|
15616
|
+
throw new Error("Planner requires piModel and apiKey");
|
|
15617
|
+
}
|
|
15618
|
+
const result = await completeSimple3(
|
|
15619
|
+
options.piModel,
|
|
15620
|
+
{
|
|
15621
|
+
systemPrompt: "You are a strict planner for ChatLab analysis. Return the requested blocks only.",
|
|
15622
|
+
messages: [{ role: "user", content: [{ type: "text", text: prompt }], timestamp: Date.now() }]
|
|
15623
|
+
},
|
|
15624
|
+
{
|
|
15625
|
+
apiKey: options.apiKey,
|
|
15626
|
+
maxTokens: options.maxTokens ?? 900,
|
|
15627
|
+
temperature: options.temperature ?? 0.2,
|
|
15628
|
+
signal
|
|
15629
|
+
}
|
|
15630
|
+
);
|
|
15631
|
+
return {
|
|
15632
|
+
text: result.content.filter((item) => item.type === "text").map((item) => item.text).join("")
|
|
15633
|
+
};
|
|
15634
|
+
}
|
|
15635
|
+
function extractTaggedBlockText(rawText, tag, nextTags) {
|
|
15636
|
+
const openTag = `<${tag}>`;
|
|
15637
|
+
const closeTag = `</${tag}>`;
|
|
15638
|
+
const blockStart = rawText.indexOf(openTag);
|
|
15639
|
+
if (blockStart < 0) return "";
|
|
15640
|
+
const bodyStart = blockStart + openTag.length;
|
|
15641
|
+
const closeStart = rawText.indexOf(closeTag, bodyStart);
|
|
15642
|
+
const nextStarts = nextTags.map((nextTag) => rawText.indexOf(nextTag, bodyStart)).filter((index) => index >= 0);
|
|
15643
|
+
const endCandidates = [closeStart, ...nextStarts].filter((index) => index >= 0);
|
|
15644
|
+
const bodyEnd = endCandidates.length > 0 ? Math.min(...endCandidates) : Math.max(bodyStart, rawText.length - STREAM_MARKER_HOLDBACK_CHARS);
|
|
15645
|
+
const text = rawText.slice(bodyStart, bodyEnd);
|
|
15646
|
+
return text.replace(/^\s+/, "");
|
|
15647
|
+
}
|
|
15648
|
+
async function streamWithPiAi(prompt, options, signal) {
|
|
15649
|
+
if (!options.piModel || !options.apiKey) {
|
|
15650
|
+
throw new Error("Planner requires piModel and apiKey");
|
|
15651
|
+
}
|
|
15652
|
+
const stream = streamSimple(
|
|
15653
|
+
options.piModel,
|
|
15654
|
+
{
|
|
15655
|
+
systemPrompt: "You are a strict planner for ChatLab analysis. Return the requested plan and JSON blocks only.",
|
|
15656
|
+
messages: [{ role: "user", content: [{ type: "text", text: prompt }], timestamp: Date.now() }]
|
|
15657
|
+
},
|
|
15658
|
+
{
|
|
15659
|
+
apiKey: options.apiKey,
|
|
15660
|
+
maxTokens: options.maxTokens ?? 900,
|
|
15661
|
+
temperature: options.temperature ?? 0.2,
|
|
15662
|
+
signal
|
|
15663
|
+
}
|
|
15664
|
+
);
|
|
15665
|
+
let text = "";
|
|
15666
|
+
let emittedDraftLength = 0;
|
|
15667
|
+
let emittedPlanLength = 0;
|
|
15668
|
+
let emittedJsonLength = 0;
|
|
15669
|
+
let thinkingStartedAt;
|
|
15670
|
+
let draftThinkingStartedAt;
|
|
15671
|
+
let draftThinkingEnded = false;
|
|
15672
|
+
let validationStartedAt;
|
|
15673
|
+
let validationEnded = false;
|
|
15674
|
+
for await (const event of stream) {
|
|
15675
|
+
if (signal?.aborted) break;
|
|
15676
|
+
if (event.type === "thinking_start") {
|
|
15677
|
+
thinkingStartedAt = Date.now();
|
|
15678
|
+
continue;
|
|
15679
|
+
}
|
|
15680
|
+
if (event.type === "thinking_delta") {
|
|
15681
|
+
options.onThinkingDelta?.(event.delta);
|
|
15682
|
+
continue;
|
|
15683
|
+
}
|
|
15684
|
+
if (event.type === "thinking_end") {
|
|
15685
|
+
const durationMs = thinkingStartedAt ? Date.now() - thinkingStartedAt : void 0;
|
|
15686
|
+
thinkingStartedAt = void 0;
|
|
15687
|
+
options.onThinkingEnd?.(durationMs);
|
|
15688
|
+
continue;
|
|
15689
|
+
}
|
|
15690
|
+
if (event.type !== "text_delta") continue;
|
|
15691
|
+
text += event.delta;
|
|
15692
|
+
const draftText = extractTaggedBlockText(text, "draft", ["<plan>", "<json>"]);
|
|
15693
|
+
if (draftText.length > emittedDraftLength) {
|
|
15694
|
+
if (!draftThinkingStartedAt) draftThinkingStartedAt = Date.now();
|
|
15695
|
+
const delta = draftText.slice(emittedDraftLength);
|
|
15696
|
+
emittedDraftLength = draftText.length;
|
|
15697
|
+
if (delta.trim().length > 0 || /\s/.test(delta)) {
|
|
15698
|
+
options.onThinkingDelta?.(delta);
|
|
15699
|
+
}
|
|
15700
|
+
}
|
|
15701
|
+
if (!draftThinkingEnded && emittedDraftLength > 0 && (text.includes("</draft>") || text.includes("<plan>"))) {
|
|
15702
|
+
draftThinkingEnded = true;
|
|
15703
|
+
const durationMs = draftThinkingStartedAt ? Date.now() - draftThinkingStartedAt : void 0;
|
|
15704
|
+
options.onThinkingEnd?.(durationMs);
|
|
15705
|
+
}
|
|
15706
|
+
const planText = extractTaggedBlockText(text, "plan", ["<json>"]);
|
|
15707
|
+
if (planText.length > emittedPlanLength) {
|
|
15708
|
+
const delta = planText.slice(emittedPlanLength);
|
|
15709
|
+
emittedPlanLength = planText.length;
|
|
15710
|
+
if (delta.trim().length > 0 || /\s/.test(delta)) {
|
|
15711
|
+
options.onPlanDelta?.(delta);
|
|
15712
|
+
}
|
|
15713
|
+
}
|
|
15714
|
+
const jsonText = extractTaggedBlockText(text, "json", []);
|
|
15715
|
+
if (jsonText.length > emittedJsonLength) {
|
|
15716
|
+
if (!validationStartedAt) validationStartedAt = Date.now();
|
|
15717
|
+
const delta = jsonText.slice(emittedJsonLength);
|
|
15718
|
+
emittedJsonLength = jsonText.length;
|
|
15719
|
+
if (delta.trim().length > 0 || /\s/.test(delta)) {
|
|
15720
|
+
options.onValidationDelta?.(delta);
|
|
15721
|
+
}
|
|
15722
|
+
}
|
|
15723
|
+
if (!validationEnded && emittedJsonLength > 0 && text.includes("</json>")) {
|
|
15724
|
+
validationEnded = true;
|
|
15725
|
+
const durationMs = validationStartedAt ? Date.now() - validationStartedAt : void 0;
|
|
15726
|
+
options.onValidationEnd?.(durationMs);
|
|
15727
|
+
}
|
|
15728
|
+
}
|
|
15729
|
+
return { text };
|
|
15730
|
+
}
|
|
15731
|
+
|
|
15185
15732
|
// ../../packages/node-runtime/src/ai/agent/event-handler.ts
|
|
15186
15733
|
function estimateTokensFromText(text) {
|
|
15187
15734
|
if (!text) return 0;
|
|
@@ -15230,7 +15777,13 @@ function estimateContextTokens(systemPrompt, messages, pendingUserMessage) {
|
|
|
15230
15777
|
var AgentEventHandler = class {
|
|
15231
15778
|
toolsUsed = [];
|
|
15232
15779
|
toolRounds = 0;
|
|
15233
|
-
totalUsage = {
|
|
15780
|
+
totalUsage = {
|
|
15781
|
+
promptTokens: 0,
|
|
15782
|
+
completionTokens: 0,
|
|
15783
|
+
totalTokens: 0,
|
|
15784
|
+
cacheReadTokens: 0,
|
|
15785
|
+
cacheWriteTokens: 0
|
|
15786
|
+
};
|
|
15234
15787
|
lastStatusAt = 0;
|
|
15235
15788
|
onChunk;
|
|
15236
15789
|
context;
|
|
@@ -15260,12 +15813,18 @@ var AgentEventHandler = class {
|
|
|
15260
15813
|
case "tool_start": {
|
|
15261
15814
|
const params = this.normalizeToolParams(event.toolName, event.toolParams);
|
|
15262
15815
|
this.toolsUsed.push(event.toolName);
|
|
15263
|
-
this.onChunk({ type: "tool_start", toolName: event.toolName, toolParams: params });
|
|
15816
|
+
this.onChunk({ type: "tool_start", toolCallId: event.toolCallId, toolName: event.toolName, toolParams: params });
|
|
15264
15817
|
this.emitStatus("tool_running", messages, { currentTool: event.toolName, force: true });
|
|
15265
15818
|
break;
|
|
15266
15819
|
}
|
|
15267
15820
|
case "tool_end":
|
|
15268
|
-
this.onChunk({
|
|
15821
|
+
this.onChunk({
|
|
15822
|
+
type: "tool_result",
|
|
15823
|
+
toolCallId: event.toolCallId,
|
|
15824
|
+
toolName: event.toolName,
|
|
15825
|
+
toolResult: event.toolResult,
|
|
15826
|
+
toolIsError: event.isError
|
|
15827
|
+
});
|
|
15269
15828
|
this.emitStatus("thinking", messages, { force: true });
|
|
15270
15829
|
break;
|
|
15271
15830
|
case "turn_end":
|
|
@@ -15282,7 +15841,9 @@ var AgentEventHandler = class {
|
|
|
15282
15841
|
return {
|
|
15283
15842
|
promptTokens: this.totalUsage.promptTokens,
|
|
15284
15843
|
completionTokens: this.totalUsage.completionTokens,
|
|
15285
|
-
totalTokens: this.totalUsage.totalTokens
|
|
15844
|
+
totalTokens: this.totalUsage.totalTokens,
|
|
15845
|
+
cacheReadTokens: this.totalUsage.cacheReadTokens,
|
|
15846
|
+
cacheWriteTokens: this.totalUsage.cacheWriteTokens
|
|
15286
15847
|
};
|
|
15287
15848
|
}
|
|
15288
15849
|
emitStatus(phase, messages, options) {
|
|
@@ -15318,6 +15879,39 @@ var AgentEventHandler = class {
|
|
|
15318
15879
|
function agentT(t2, key, locale, options) {
|
|
15319
15880
|
return t2(key, { lng: locale, ...options });
|
|
15320
15881
|
}
|
|
15882
|
+
function formatNullableTimestamp2(timestamp) {
|
|
15883
|
+
return typeof timestamp === "number" && Number.isFinite(timestamp) ? String(timestamp) : "null";
|
|
15884
|
+
}
|
|
15885
|
+
function formatSharePercent2(share) {
|
|
15886
|
+
if (!Number.isFinite(share)) return "0%";
|
|
15887
|
+
const rounded = Math.round(share * 10) / 10;
|
|
15888
|
+
return Number.isInteger(rounded) ? `${rounded}%` : `${rounded.toFixed(1)}%`;
|
|
15889
|
+
}
|
|
15890
|
+
function normalizeInlineText(text) {
|
|
15891
|
+
return text.replace(/\s+/g, " ").trim();
|
|
15892
|
+
}
|
|
15893
|
+
function formatDataSnapshotContext(t2, dataSnapshot, locale) {
|
|
15894
|
+
const memberHints = dataSnapshot.activeMemberHints ?? [];
|
|
15895
|
+
const memberHintTitle = memberHints.length === 0 ? agentT(t2, "ai.agent.dataSnapshotMemberHintsUnavailable", locale) : dataSnapshot.totalMembers <= 10 ? agentT(t2, "ai.agent.dataSnapshotMemberHintsAll", locale) : agentT(t2, "ai.agent.dataSnapshotMemberHintsTop", locale);
|
|
15896
|
+
const memberHintLines = memberHints.length > 0 ? memberHints.map((member, index) => {
|
|
15897
|
+
return `${index + 1}. member_id=${member.memberId} | display_name=${normalizeInlineText(member.displayName)} | messages=${member.messageCount} | share=${formatSharePercent2(member.share)}`;
|
|
15898
|
+
}).join("\n") : agentT(t2, "ai.agent.dataSnapshotMemberHintsEmpty", locale);
|
|
15899
|
+
return agentT(t2, "ai.agent.dataSnapshotContext", locale, {
|
|
15900
|
+
name: dataSnapshot.name,
|
|
15901
|
+
platform: dataSnapshot.platform,
|
|
15902
|
+
type: dataSnapshot.type,
|
|
15903
|
+
totalMessages: dataSnapshot.totalMessages,
|
|
15904
|
+
totalMembers: dataSnapshot.totalMembers,
|
|
15905
|
+
firstMessageTs: formatNullableTimestamp2(dataSnapshot.firstMessageTs),
|
|
15906
|
+
firstMessageTime: formatTimestamp(dataSnapshot.firstMessageTs, locale),
|
|
15907
|
+
lastMessageTs: formatNullableTimestamp2(dataSnapshot.lastMessageTs),
|
|
15908
|
+
lastMessageTime: formatTimestamp(dataSnapshot.lastMessageTs, locale),
|
|
15909
|
+
segmentSummaryCount: dataSnapshot.segmentSummaries?.availableCount ?? 0,
|
|
15910
|
+
memberHintTitle,
|
|
15911
|
+
memberHintLines,
|
|
15912
|
+
usageRules: agentT(t2, "ai.agent.dataSnapshotUsageRules", locale)
|
|
15913
|
+
});
|
|
15914
|
+
}
|
|
15321
15915
|
function getLockedPromptSection(t2, chatType, ownerInfo, locale, mentionedMembers, dataSnapshot) {
|
|
15322
15916
|
const now = /* @__PURE__ */ new Date();
|
|
15323
15917
|
const dateLocale = locale.startsWith("zh") ? "zh-CN" : "en-US";
|
|
@@ -15342,14 +15936,7 @@ ${mentionedMembers.map((member) => {
|
|
|
15342
15936
|
}).join("\n")}
|
|
15343
15937
|
` : "";
|
|
15344
15938
|
const year = now.getFullYear();
|
|
15345
|
-
const dataSnapshotNote = dataSnapshot ? `${
|
|
15346
|
-
name: dataSnapshot.name,
|
|
15347
|
-
platform: dataSnapshot.platform,
|
|
15348
|
-
totalMessages: dataSnapshot.totalMessages,
|
|
15349
|
-
totalMembers: dataSnapshot.totalMembers,
|
|
15350
|
-
firstMessageDate: formatTimestamp(dataSnapshot.firstMessageTs, locale),
|
|
15351
|
-
lastMessageDate: formatTimestamp(dataSnapshot.lastMessageTs, locale)
|
|
15352
|
-
})}
|
|
15939
|
+
const dataSnapshotNote = dataSnapshot ? `${formatDataSnapshotContext(t2, dataSnapshot, locale)}
|
|
15353
15940
|
` : "";
|
|
15354
15941
|
return `${agentT(t2, "ai.agent.currentDateIs", locale)} ${currentDate}\u3002
|
|
15355
15942
|
${ownerNote}
|
|
@@ -15463,7 +16050,7 @@ var zh_CN_default = {
|
|
|
15463
16050
|
}
|
|
15464
16051
|
},
|
|
15465
16052
|
get_time_stats: {
|
|
15466
|
-
desc: '\u83B7\u53D6\u7FA4\u804A\u7684\u65F6\u95F4\u5206\u5E03\u7EDF\u8BA1\u3002\u9002\u7528\u4E8E\u56DE\u7B54"\u4EC0\u4E48\u65F6\u5019\u6700\u6D3B\u8DC3"\u3001"\u5927\u5BB6\u4E00\u822C\u51E0\u70B9\u804A\u5929"\u7B49\u95EE\u9898\u3002',
|
|
16053
|
+
desc: '\u83B7\u53D6\u7FA4\u804A\u7684\u65F6\u95F4\u5206\u5E03\u7EDF\u8BA1\u3002\u9002\u7528\u4E8E\u56DE\u7B54"\u4EC0\u4E48\u65F6\u5019\u6700\u6D3B\u8DC3"\u3001"\u5927\u5BB6\u4E00\u822C\u51E0\u70B9\u804A\u5929"\u7B49\u95EE\u9898\u3002\u8FD4\u56DE\u7684 `data` \u6570\u7EC4\u53EF\u76F4\u63A5\u4F5C\u4E3A `render_chart` \u7684 `rows` \u53C2\u6570\u7528\u4E8E\u7ED8\u56FE\u3002',
|
|
15467
16054
|
params: {
|
|
15468
16055
|
type: "\u7EDF\u8BA1\u7C7B\u578B\uFF1Ahourly\uFF08\u6309\u5C0F\u65F6\uFF09\u3001weekday\uFF08\u6309\u661F\u671F\uFF09\u3001daily\uFF08\u6309\u65E5\u671F\uFF09"
|
|
15469
16056
|
}
|
|
@@ -15653,9 +16240,10 @@ var zh_CN_default = {
|
|
|
15653
16240
|
params: {}
|
|
15654
16241
|
},
|
|
15655
16242
|
render_chart: {
|
|
15656
|
-
desc: "\u6839\u636E
|
|
16243
|
+
desc: "\u6839\u636E ChartSpec v1 \u751F\u6210 ChatLab \u539F\u751F\u56FE\u8868\u3002\u652F\u6301 bar\u3001line\u3001pie\u3001heatmap\u3002\u63D0\u4F9B `rows`\uFF08\u6765\u81EA\u9AD8\u5C42\u5DE5\u5177\u7684\u6570\u636E\u6570\u7EC4\uFF0C\u5982 get_time_stats \u7684 `data` \u5B57\u6BB5\uFF09\u6216 `sql`\uFF08\u53EA\u8BFB SELECT\uFF09\u4E8C\u9009\u4E00\uFF1B\u6709\u73B0\u6210\u6570\u636E\u65F6\u4F18\u5148\u7528 `rows`\uFF0C\u53EA\u6709\u9AD8\u5C42\u5DE5\u5177\u65E0\u6CD5\u6EE1\u8DB3\u65F6\u624D\u5199 `sql`\u3002\u7981\u6B62\u8F93\u51FA HTML\u3001JavaScript\u3001SVG\u3001ECharts option \u6216\u6E32\u67D3\u4EE3\u7801\u3002",
|
|
15657
16244
|
params: {
|
|
15658
|
-
|
|
16245
|
+
rows: "\u6765\u81EA\u9AD8\u5C42\u5DE5\u5177\u8FD4\u56DE\u7684\u6570\u636E\u6570\u7EC4\uFF08\u5982 get_time_stats \u7684 `data` \u5B57\u6BB5\uFF09\u3002\u6709\u73B0\u6210\u6570\u636E\u65F6\u4F18\u5148\u4F7F\u7528\uFF0C\u4E0E sql \u4E8C\u9009\u4E00\u3002",
|
|
16246
|
+
sql: "\u53EA\u8BFB SELECT \u6216 WITH SELECT SQL\u3002\u4EC5\u5728\u9AD8\u5C42\u5DE5\u5177\u65E0\u6CD5\u6EE1\u8DB3\u9700\u6C42\u65F6\u4F7F\u7528\uFF0C\u5FC5\u987B\u8FD4\u56DE ChartSpec encoding \u4E2D\u5F15\u7528\u7684\u5B57\u6BB5\u3002",
|
|
15659
16247
|
params: "SQL \u547D\u540D\u53C2\u6570\u5BF9\u8C61\uFF1B\u4E0D\u9700\u8981\u53C2\u6570\u65F6\u4F20\u7A7A\u5BF9\u8C61\u3002",
|
|
15660
16248
|
chartSpec: "ChartSpec v1\uFF0C\u5305\u542B version\u3001type\u3001title\u3001encoding\u3002",
|
|
15661
16249
|
maxRows: "\u56FE\u8868\u67E5\u8BE2\u6700\u5927\u884C\u6570\uFF0C\u9ED8\u8BA4 1000\u3002"
|
|
@@ -15689,6 +16277,35 @@ var zh_CN_default = {
|
|
|
15689
16277
|
timeParamsIntro: '\u65F6\u95F4\u53C2\u6570\uFF1A\u4F7F\u7528 start_time/end_time \u6307\u5B9A\u65F6\u95F4\u8303\u56F4\uFF0C\u683C\u5F0F "YYYY-MM-DD HH:mm"',
|
|
15690
16278
|
defaultYearNote: "\u672A\u6307\u5B9A\u65F6\u95F4\u8303\u56F4\u65F6\u9ED8\u8BA4\u67E5\u8BE2\u5168\u90E8\u3002\u5F53\u524D\u5E74\u4EFD\u4E3A{{year}}\u5E74",
|
|
15691
16279
|
dataSnapshotNote: "\u5F53\u524D\u804A\u5929\u6570\u636E\u5E93\u5FEB\u7167\uFF1A{{name}}\uFF08{{platform}}\uFF09\uFF0C\u603B\u6D88\u606F {{totalMessages}} \u6761\uFF0C\u6210\u5458 {{totalMembers}} \u4EBA\uFF0C\u65F6\u95F4\u8303\u56F4 {{firstMessageDate}} ~ {{lastMessageDate}}\u3002\u8BE5\u5FEB\u7167\u53EA\u7528\u4E8E\u5224\u65AD\u6570\u636E\u8303\u56F4\uFF1B\u56DE\u7B54\u5177\u4F53\u804A\u5929\u4E8B\u5B9E\u4ECD\u5FC5\u987B\u8C03\u7528\u5DE5\u5177\u68C0\u7D22\u5F53\u524D\u6570\u636E\u5E93\u3002",
|
|
16280
|
+
dataSnapshotContext: `\u5F53\u524D\u804A\u5929\u6570\u636E\u5E93\u542F\u52A8\u4E0A\u4E0B\u6587\uFF1A
|
|
16281
|
+
- name: {{name}}
|
|
16282
|
+
- platform: {{platform}}
|
|
16283
|
+
- type: {{type}}
|
|
16284
|
+
- total_messages: {{totalMessages}}
|
|
16285
|
+
- total_members: {{totalMembers}}
|
|
16286
|
+
- first_message_ts: {{firstMessageTs}}
|
|
16287
|
+
- first_message_time: {{firstMessageTime}}
|
|
16288
|
+
- last_message_ts: {{lastMessageTs}}
|
|
16289
|
+
- last_message_time: {{lastMessageTime}}
|
|
16290
|
+
- segment_summaries_available: {{segmentSummaryCount}}
|
|
16291
|
+
|
|
16292
|
+
{{memberHintTitle}}
|
|
16293
|
+
{{memberHintLines}}
|
|
16294
|
+
|
|
16295
|
+
\u4F7F\u7528\u89C4\u5219\uFF1A
|
|
16296
|
+
{{usageRules}}`,
|
|
16297
|
+
dataSnapshotMemberHintsAll: "\u6D3B\u8DC3\u6210\u5458\u67E5\u8BE2\u63D0\u793A\uFF08\u5168\u90E8\u6210\u5458\uFF09\uFF1A",
|
|
16298
|
+
dataSnapshotMemberHintsTop: "\u6D3B\u8DC3\u6210\u5458\u67E5\u8BE2\u63D0\u793A\uFF08\u6309\u5386\u53F2\u603B\u6D88\u606F\u91CF Top 10\uFF09\uFF1A",
|
|
16299
|
+
dataSnapshotMemberHintsUnavailable: "\u6D3B\u8DC3\u6210\u5458\u67E5\u8BE2\u63D0\u793A\uFF1A",
|
|
16300
|
+
dataSnapshotMemberHintsEmpty: "\u65E0\u53EF\u7528\u6210\u5458\u63D0\u793A\u3002",
|
|
16301
|
+
dataSnapshotUsageRules: `- member_id \u662F\u5DE5\u5177\u67E5\u8BE2\u63D0\u793A\uFF1Bdisplay_name \u4EC5\u7528\u4E8E\u4EBA\u7C7B\u8BC6\u522B\uFF0C\u53EF\u80FD\u4E0D\u552F\u4E00\u3002
|
|
16302
|
+
- \u4E0D\u8981\u5728\u6700\u7EC8\u56DE\u7B54\u4E2D\u4E3B\u52A8\u66B4\u9732 member_id \u6216\u542F\u52A8\u4E0A\u4E0B\u6587\u672C\u8EAB\uFF0C\u9664\u975E\u7528\u6237\u660E\u786E\u8981\u6C42\u6280\u672F\u7EC6\u8282\u3002
|
|
16303
|
+
- \u6D3B\u8DC3\u6210\u5458\u6392\u884C\u53EA\u4EE3\u8868\u5386\u53F2\u603B\u6D88\u606F\u91CF\uFF0C\u4E0D\u4EE3\u8868\u6700\u8FD1\u6D3B\u8DC3\u60C5\u51B5\uFF1B\u4E5F\u4E0D\u8DB3\u4EE5\u4F5C\u4E3A\u5F71\u54CD\u529B\u3001\u5173\u7CFB\u6216\u8FD1\u671F\u8D8B\u52BF\u7ED3\u8BBA\u7684\u8BC1\u636E\u3002
|
|
16304
|
+
- \u76F8\u5BF9\u65F6\u95F4\u8868\u8FBE\u4EE5\u771F\u5B9E\u5F53\u524D\u65E5\u671F\u4E3A\u57FA\u51C6\uFF0C\u800C\u4E0D\u662F\u6570\u636E\u5E93\u6700\u540E\u6D88\u606F\u65F6\u95F4\u3002
|
|
16305
|
+
- \u201C\u6700\u8FD1\u4E00\u5E74/\u8FC7\u53BB\u4E00\u5E74\u201D\u8868\u793A\u4ECE\u771F\u5B9E\u5F53\u524D\u65E5\u671F\u56DE\u63A8\u4E00\u5E74\u5230\u4ECA\u5929\uFF1B\u201C\u53BB\u5E74\u201D\u8868\u793A\u4E0A\u4E00\u81EA\u7136\u5E74\u3002
|
|
16306
|
+
- \u6570\u636E\u5E93\u65F6\u95F4\u8FB9\u754C\u53EA\u7528\u4E8E\u8BF4\u660E\u8986\u76D6\u8303\u56F4\uFF0C\u4E0D\u7528\u4E8E\u91CD\u5B9A\u4E49\u7528\u6237\u8981\u6C42\u7684\u65F6\u95F4\u8303\u56F4\u3002
|
|
16307
|
+
- \u4F7F\u7528\u9ED8\u8BA4\u201C\u8FD1 N \u5929\u201D\u7684\u5DE5\u5177\u65F6\uFF0C\u5148\u9009\u62E9\u4E0E\u6570\u636E\u5E93\u65F6\u95F4\u8FB9\u754C\u6709\u4EA4\u96C6\u7684\u8303\u56F4\uFF0C\u4E0D\u8981\u5148\u63A2\u6D4B\u771F\u5B9E\u5F53\u524D\u65E5\u671F\u7A97\u53E3\u5BFC\u81F4\u7A7A\u7ED3\u679C\u3002
|
|
16308
|
+
- \u4E0D\u8981\u53EA\u4E3A\u4E86\u91CD\u65B0\u53D1\u73B0 min/max timestamp \u8C03\u7528\u5DE5\u5177\uFF1B\u4F46\u56DE\u7B54\u5177\u4F53\u804A\u5929\u4E8B\u5B9E\u3001\u7EDF\u8BA1\u548C\u7ED3\u8BBA\u4ECD\u5FC5\u987B\u8C03\u7528\u5DE5\u5177\u83B7\u53D6\u8BC1\u636E\u3002`,
|
|
15692
16309
|
evidencePolicy: `\u8BC1\u636E\u7B56\u7565\uFF1A
|
|
15693
16310
|
- AI \u5BF9\u8BDD\u5386\u53F2\u3001\u5386\u53F2 AI \u56DE\u590D\u548C\u538B\u7F29\u6458\u8981\u53EA\u7528\u4E8E\u7406\u89E3\u7528\u6237\u610F\u56FE\uFF0C\u4E0D\u80FD\u4F5C\u4E3A\u804A\u5929\u8BB0\u5F55\u4E8B\u5B9E\u8BC1\u636E\u3002
|
|
15694
16311
|
- \u53EA\u8981\u7528\u6237\u8BE2\u95EE\u804A\u5929\u8BB0\u5F55\u5185\u5BB9\u3001\u6700\u8FD1\u804A\u4EC0\u4E48\u3001\u67D0\u4EBA\u8BF4\u8FC7\u4EC0\u4E48\u3001\u7EDF\u8BA1\u6392\u884C\u3001\u662F\u5426\u51FA\u73B0\u8FC7\u67D0\u8BDD\u9898\u6216\u8981\u6C42\u5F15\u7528\u539F\u8BDD\uFF0C\u5FC5\u987B\u5148\u8C03\u7528\u5408\u9002\u7684\u6570\u636E\u5DE5\u5177\u68C0\u7D22\u5F53\u524D\u6570\u636E\u5E93\u3002
|
|
@@ -15797,7 +16414,7 @@ var en_US_default = {
|
|
|
15797
16414
|
}
|
|
15798
16415
|
},
|
|
15799
16416
|
get_time_stats: {
|
|
15800
|
-
desc: 'Get time distribution statistics of chat activity. Suitable for questions like "when is the group most active" or "what time do people usually chat".',
|
|
16417
|
+
desc: 'Get time distribution statistics of chat activity. Suitable for questions like "when is the group most active" or "what time do people usually chat". The returned `data` array can be passed directly as the `rows` parameter of render_chart for visualization.',
|
|
15801
16418
|
params: {
|
|
15802
16419
|
type: "Statistics type: hourly (by hour), weekday (by day of week), daily (by date)"
|
|
15803
16420
|
}
|
|
@@ -15988,9 +16605,10 @@ Returned summaries are brief descriptions of each segment, helping quickly locat
|
|
|
15988
16605
|
params: {}
|
|
15989
16606
|
},
|
|
15990
16607
|
render_chart: {
|
|
15991
|
-
desc: "Generate a native ChatLab chart from
|
|
16608
|
+
desc: "Generate a native ChatLab chart from ChartSpec v1. Supports bar, line, pie, and heatmap. Provide either `rows` (pre-fetched data array from a tool result, e.g. the `data` field from get_time_stats) or `sql` (read-only SELECT) \u2014 prefer `rows` when data is already available; use `sql` only when high-level tools cannot satisfy the need. Do not output HTML, JavaScript, SVG, ECharts options, or rendering code.",
|
|
15992
16609
|
params: {
|
|
15993
|
-
|
|
16610
|
+
rows: "Pre-fetched data array from a high-level tool result (e.g. the `data` field from get_time_stats). Prefer this over sql when data is already available. Mutually exclusive with sql.",
|
|
16611
|
+
sql: "Read-only SELECT or WITH SELECT SQL. Use only when high-level tools cannot satisfy the need. Must return fields referenced by ChartSpec encoding.",
|
|
15994
16612
|
params: "Named SQL parameters. Use an empty object when no parameters are needed.",
|
|
15995
16613
|
chartSpec: "ChartSpec v1 with version, type, title, and encoding.",
|
|
15996
16614
|
maxRows: "Maximum chart query rows. Default 1000."
|
|
@@ -16025,6 +16643,35 @@ Returned summaries are brief descriptions of each segment, helping quickly locat
|
|
|
16025
16643
|
timeParamsIntro: 'Time parameters: use start_time/end_time to specify the range, format "YYYY-MM-DD HH:mm"',
|
|
16026
16644
|
defaultYearNote: "When no time range is specified, queries default to all data. Current year is {{year}}.",
|
|
16027
16645
|
dataSnapshotNote: "Current chat database snapshot: {{name}} ({{platform}}), {{totalMessages}} total messages, {{totalMembers}} members, time range {{firstMessageDate}} ~ {{lastMessageDate}}. This snapshot only helps judge data coverage; concrete chat facts still require tool retrieval from the current database.",
|
|
16646
|
+
dataSnapshotContext: `Current chat database startup context:
|
|
16647
|
+
- name: {{name}}
|
|
16648
|
+
- platform: {{platform}}
|
|
16649
|
+
- type: {{type}}
|
|
16650
|
+
- total_messages: {{totalMessages}}
|
|
16651
|
+
- total_members: {{totalMembers}}
|
|
16652
|
+
- first_message_ts: {{firstMessageTs}}
|
|
16653
|
+
- first_message_time: {{firstMessageTime}}
|
|
16654
|
+
- last_message_ts: {{lastMessageTs}}
|
|
16655
|
+
- last_message_time: {{lastMessageTime}}
|
|
16656
|
+
- segment_summaries_available: {{segmentSummaryCount}}
|
|
16657
|
+
|
|
16658
|
+
{{memberHintTitle}}
|
|
16659
|
+
{{memberHintLines}}
|
|
16660
|
+
|
|
16661
|
+
Usage rules:
|
|
16662
|
+
{{usageRules}}`,
|
|
16663
|
+
dataSnapshotMemberHintsAll: "Active member lookup hints (all members):",
|
|
16664
|
+
dataSnapshotMemberHintsTop: "Active member lookup hints (top 10 by historical total messages):",
|
|
16665
|
+
dataSnapshotMemberHintsUnavailable: "Active member lookup hints:",
|
|
16666
|
+
dataSnapshotMemberHintsEmpty: "No member hints available.",
|
|
16667
|
+
dataSnapshotUsageRules: `- member_id is a tool lookup hint; display_name is only for human recognition and may not be unique.
|
|
16668
|
+
- Do not proactively expose member_id or the startup context in the final answer unless the user explicitly asks for technical details.
|
|
16669
|
+
- Active member ranking only reflects historical total message volume, not recent activity; it is also not evidence for influence, relationships, or recent trends.
|
|
16670
|
+
- Interpret relative time expressions using the real current date, not the database's last message time.
|
|
16671
|
+
- "recent year" / "past year" means one year back from the real current date to today; "last year" means the previous calendar year.
|
|
16672
|
+
- Database time bounds are only for explaining coverage, not for redefining the user's requested time range.
|
|
16673
|
+
- When using default recent-day tools, first choose a range that intersects database time bounds instead of probing an empty real-current-date window.
|
|
16674
|
+
- Do not call tools only to rediscover min/max timestamp; concrete chat facts, statistics, and conclusions still require tool evidence.`,
|
|
16028
16675
|
evidencePolicy: `Evidence policy:
|
|
16029
16676
|
- AI conversation history, prior AI replies, and compressed summaries are only for understanding the user's intent; they are not evidence for chat-record facts.
|
|
16030
16677
|
- Whenever the user asks about chat content, recent topics, what someone said, rankings/statistics, whether a topic appeared, or asks for exact quotes, first call an appropriate data tool to retrieve the current database.
|
|
@@ -16129,7 +16776,7 @@ var ja_JP_default = {
|
|
|
16129
16776
|
}
|
|
16130
16777
|
},
|
|
16131
16778
|
get_time_stats: {
|
|
16132
|
-
desc: "\u30B0\u30EB\u30FC\u30D7\u30C1\u30E3\u30C3\u30C8\u306E\u6642\u9593\u5206\u5E03\u7D71\u8A08\u3092\u53D6\u5F97\u3059\u308B\u3002\u300C\u3044\u3064\u304C\u4E00\u756A\u30A2\u30AF\u30C6\u30A3\u30D6\uFF1F\u300D\u300C\u307F\u3093\u306A\u4F55\u6642\u306B\u30C1\u30E3\u30C3\u30C8\u3057\u3066\u3044\u308B\uFF1F\u300D\u306A\u3069\u306E\u8CEA\u554F\u306B\u9069\u3057\u3066\u3044\u308B\u3002",
|
|
16779
|
+
desc: "\u30B0\u30EB\u30FC\u30D7\u30C1\u30E3\u30C3\u30C8\u306E\u6642\u9593\u5206\u5E03\u7D71\u8A08\u3092\u53D6\u5F97\u3059\u308B\u3002\u300C\u3044\u3064\u304C\u4E00\u756A\u30A2\u30AF\u30C6\u30A3\u30D6\uFF1F\u300D\u300C\u307F\u3093\u306A\u4F55\u6642\u306B\u30C1\u30E3\u30C3\u30C8\u3057\u3066\u3044\u308B\uFF1F\u300D\u306A\u3069\u306E\u8CEA\u554F\u306B\u9069\u3057\u3066\u3044\u308B\u3002\u8FD4\u3055\u308C\u308B `data` \u914D\u5217\u306F render_chart \u306E `rows` \u30D1\u30E9\u30E1\u30FC\u30BF\u3068\u3057\u3066\u76F4\u63A5\u4F7F\u7528\u3067\u304D\u308B\u3002",
|
|
16133
16780
|
params: {
|
|
16134
16781
|
type: "\u7D71\u8A08\u30BF\u30A4\u30D7\uFF1Ahourly\uFF08\u6642\u9593\u5225\uFF09\u3001weekday\uFF08\u66DC\u65E5\u5225\uFF09\u3001daily\uFF08\u65E5\u5225\uFF09"
|
|
16135
16782
|
}
|
|
@@ -16319,9 +16966,10 @@ var ja_JP_default = {
|
|
|
16319
16966
|
params: {}
|
|
16320
16967
|
},
|
|
16321
16968
|
render_chart: {
|
|
16322
|
-
desc: "
|
|
16969
|
+
desc: "ChartSpec v1 \u304B\u3089 ChatLab \u30CD\u30A4\u30C6\u30A3\u30D6\u30C1\u30E3\u30FC\u30C8\u3092\u751F\u6210\u3057\u307E\u3059\u3002bar\u3001line\u3001pie\u3001heatmap \u3092\u30B5\u30DD\u30FC\u30C8\u3057\u307E\u3059\u3002`rows`\uFF08\u9AD8\u30EC\u30D9\u30EB\u30C4\u30FC\u30EB\u306E\u30C7\u30FC\u30BF\u914D\u5217\u3001\u4F8B\uFF1Aget_time_stats \u306E `data` \u30D5\u30A3\u30FC\u30EB\u30C9\uFF09\u307E\u305F\u306F `sql`\uFF08\u8AAD\u307F\u53D6\u308A\u5C02\u7528 SELECT\uFF09\u306E\u3044\u305A\u308C\u304B\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002\u30C7\u30FC\u30BF\u304C\u3059\u3067\u306B\u53D6\u5F97\u6E08\u307F\u306E\u5834\u5408\u306F `rows` \u3092\u512A\u5148\u3057\u3001\u9AD8\u30EC\u30D9\u30EB\u30C4\u30FC\u30EB\u3067\u5BFE\u5FDC\u3067\u304D\u306A\u3044\u5834\u5408\u306E\u307F `sql` \u3092\u4F7F\u7528\u3057\u307E\u3059\u3002HTML\u3001JavaScript\u3001SVG\u3001ECharts option\u3001\u63CF\u753B\u30B3\u30FC\u30C9\u306F\u51FA\u529B\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002",
|
|
16323
16970
|
params: {
|
|
16324
|
-
|
|
16971
|
+
rows: "\u9AD8\u30EC\u30D9\u30EB\u30C4\u30FC\u30EB\u304B\u3089\u53D6\u5F97\u3057\u305F\u30C7\u30FC\u30BF\u914D\u5217\uFF08\u4F8B\uFF1Aget_time_stats \u306E `data` \u30D5\u30A3\u30FC\u30EB\u30C9\uFF09\u3002\u30C7\u30FC\u30BF\u304C\u53D6\u5F97\u6E08\u307F\u306E\u5834\u5408\u306F sql \u3088\u308A\u512A\u5148\u3057\u3066\u4F7F\u7528\u3057\u307E\u3059\u3002sql \u3068\u306F\u6392\u4ED6\u3002",
|
|
16972
|
+
sql: "\u8AAD\u307F\u53D6\u308A\u5C02\u7528\u306E SELECT \u307E\u305F\u306F WITH SELECT SQL\u3002\u9AD8\u30EC\u30D9\u30EB\u30C4\u30FC\u30EB\u3067\u5BFE\u5FDC\u3067\u304D\u306A\u3044\u5834\u5408\u306E\u307F\u4F7F\u7528\u3057\u307E\u3059\u3002ChartSpec encoding \u3067\u53C2\u7167\u3059\u308B\u30D5\u30A3\u30FC\u30EB\u30C9\u3092\u8FD4\u3059\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002",
|
|
16325
16973
|
params: "SQL \u306E\u540D\u524D\u4ED8\u304D\u30D1\u30E9\u30E1\u30FC\u30BF\u3002\u4E0D\u8981\u306A\u5834\u5408\u306F\u7A7A\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u3092\u6E21\u3057\u307E\u3059\u3002",
|
|
16326
16974
|
chartSpec: "version\u3001type\u3001title\u3001encoding \u3092\u542B\u3080 ChartSpec v1\u3002",
|
|
16327
16975
|
maxRows: "\u30C1\u30E3\u30FC\u30C8\u30AF\u30A8\u30EA\u306E\u6700\u5927\u884C\u6570\u3002\u30C7\u30D5\u30A9\u30EB\u30C8\u306F 1000\u3002"
|
|
@@ -16355,6 +17003,35 @@ var ja_JP_default = {
|
|
|
16355
17003
|
timeParamsIntro: '\u6642\u9593\u30D1\u30E9\u30E1\u30FC\u30BF\uFF1Astart_time/end_time \u3067\u7BC4\u56F2\u3092\u6307\u5B9A\u3002\u5F62\u5F0F\u306F "YYYY-MM-DD HH:mm"',
|
|
16356
17004
|
defaultYearNote: "\u6642\u9593\u7BC4\u56F2\u3092\u6307\u5B9A\u3057\u306A\u3044\u5834\u5408\u306F\u5168\u671F\u9593\u304C\u5BFE\u8C61\u3002\u73FE\u5728\u306E\u5E74\u306F{{year}}\u5E74",
|
|
16357
17005
|
dataSnapshotNote: "\u73FE\u5728\u306E\u30C1\u30E3\u30C3\u30C8\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306E\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\uFF1A{{name}}\uFF08{{platform}}\uFF09\u3001\u7DCF\u30E1\u30C3\u30BB\u30FC\u30B8 {{totalMessages}} \u4EF6\u3001\u30E1\u30F3\u30D0\u30FC {{totalMembers}} \u4EBA\u3001\u671F\u9593 {{firstMessageDate}} ~ {{lastMessageDate}}\u3002\u3053\u306E\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8\u306F\u30C7\u30FC\u30BF\u7BC4\u56F2\u306E\u5224\u65AD\u306B\u306E\u307F\u4F7F\u3044\u3001\u5177\u4F53\u7684\u306A\u30C1\u30E3\u30C3\u30C8\u4E8B\u5B9F\u306E\u56DE\u7B54\u306B\u306F\u5FC5\u305A\u73FE\u5728\u306E\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u30C4\u30FC\u30EB\u3067\u691C\u7D22\u3059\u308B\u3002",
|
|
17006
|
+
dataSnapshotContext: `\u73FE\u5728\u306E\u30C1\u30E3\u30C3\u30C8\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u8D77\u52D5\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\uFF1A
|
|
17007
|
+
- name: {{name}}
|
|
17008
|
+
- platform: {{platform}}
|
|
17009
|
+
- type: {{type}}
|
|
17010
|
+
- total_messages: {{totalMessages}}
|
|
17011
|
+
- total_members: {{totalMembers}}
|
|
17012
|
+
- first_message_ts: {{firstMessageTs}}
|
|
17013
|
+
- first_message_time: {{firstMessageTime}}
|
|
17014
|
+
- last_message_ts: {{lastMessageTs}}
|
|
17015
|
+
- last_message_time: {{lastMessageTime}}
|
|
17016
|
+
- segment_summaries_available: {{segmentSummaryCount}}
|
|
17017
|
+
|
|
17018
|
+
{{memberHintTitle}}
|
|
17019
|
+
{{memberHintLines}}
|
|
17020
|
+
|
|
17021
|
+
\u4F7F\u7528\u30EB\u30FC\u30EB\uFF1A
|
|
17022
|
+
{{usageRules}}`,
|
|
17023
|
+
dataSnapshotMemberHintsAll: "\u30A2\u30AF\u30C6\u30A3\u30D6\u30E1\u30F3\u30D0\u30FC\u691C\u7D22\u30D2\u30F3\u30C8\uFF08\u5168\u30E1\u30F3\u30D0\u30FC\uFF09\uFF1A",
|
|
17024
|
+
dataSnapshotMemberHintsTop: "\u30A2\u30AF\u30C6\u30A3\u30D6\u30E1\u30F3\u30D0\u30FC\u691C\u7D22\u30D2\u30F3\u30C8\uFF08\u904E\u53BB\u306E\u7DCF\u30E1\u30C3\u30BB\u30FC\u30B8\u6570 Top 10\uFF09\uFF1A",
|
|
17025
|
+
dataSnapshotMemberHintsUnavailable: "\u30A2\u30AF\u30C6\u30A3\u30D6\u30E1\u30F3\u30D0\u30FC\u691C\u7D22\u30D2\u30F3\u30C8\uFF1A",
|
|
17026
|
+
dataSnapshotMemberHintsEmpty: "\u5229\u7528\u53EF\u80FD\u306A\u30E1\u30F3\u30D0\u30FC\u30D2\u30F3\u30C8\u306F\u3042\u308A\u307E\u305B\u3093\u3002",
|
|
17027
|
+
dataSnapshotUsageRules: `- member_id \u306F\u30C4\u30FC\u30EB\u691C\u7D22\u7528\u306E\u30D2\u30F3\u30C8\u3067\u3059\u3002display_name \u306F\u4EBA\u9593\u304C\u8B58\u5225\u3059\u308B\u305F\u3081\u3060\u3051\u306E\u3082\u306E\u3067\u3001\u4E00\u610F\u3068\u306F\u9650\u308A\u307E\u305B\u3093\u3002
|
|
17028
|
+
- \u30E6\u30FC\u30B6\u30FC\u304C\u6280\u8853\u7684\u8A73\u7D30\u3092\u660E\u793A\u7684\u306B\u6C42\u3081\u306A\u3044\u9650\u308A\u3001\u6700\u7D42\u56DE\u7B54\u3067 member_id \u3084\u8D77\u52D5\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u81EA\u4F53\u3092\u7A4D\u6975\u7684\u306B\u958B\u793A\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002
|
|
17029
|
+
- \u30A2\u30AF\u30C6\u30A3\u30D6\u30E1\u30F3\u30D0\u30FC\u9806\u4F4D\u306F\u904E\u53BB\u306E\u7DCF\u30E1\u30C3\u30BB\u30FC\u30B8\u91CF\u3060\u3051\u3092\u793A\u3057\u3001\u6700\u8FD1\u306E\u6D3B\u767A\u3055\u3092\u793A\u3059\u3082\u306E\u3067\u306F\u3042\u308A\u307E\u305B\u3093\u3002\u307E\u305F\u3001\u5F71\u97FF\u529B\u3001\u95A2\u4FC2\u6027\u3001\u6700\u8FD1\u306E\u50BE\u5411\u306E\u7D50\u8AD6\u8A3C\u62E0\u306B\u3082\u306A\u308A\u307E\u305B\u3093\u3002
|
|
17030
|
+
- \u76F8\u5BFE\u7684\u306A\u6642\u9593\u8868\u73FE\u306F\u3001\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306E\u6700\u7D42\u30E1\u30C3\u30BB\u30FC\u30B8\u6642\u523B\u3067\u306F\u306A\u304F\u3001\u5B9F\u969B\u306E\u73FE\u5728\u65E5\u4ED8\u3092\u57FA\u6E96\u306B\u89E3\u91C8\u3057\u3066\u304F\u3060\u3055\u3044\u3002
|
|
17031
|
+
- \u300C\u6700\u8FD1\u4E00\u5E74/\u904E\u53BB\u4E00\u5E74\u300D\u306F\u5B9F\u969B\u306E\u73FE\u5728\u65E5\u4ED8\u304B\u3089\u4ECA\u65E5\u307E\u3067\u306E1\u5E74\u9593\u3092\u6307\u3057\u3001\u300C\u53BB\u5E74\u300D\u306F\u524D\u306E\u66A6\u5E74\u3092\u6307\u3057\u307E\u3059\u3002
|
|
17032
|
+
- \u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306E\u6642\u9593\u5883\u754C\u306F\u30AB\u30D0\u30EC\u30C3\u30B8\u8AAC\u660E\u306B\u306E\u307F\u4F7F\u3044\u3001\u30E6\u30FC\u30B6\u30FC\u304C\u6C42\u3081\u305F\u6642\u9593\u7BC4\u56F2\u3092\u518D\u5B9A\u7FA9\u3059\u308B\u305F\u3081\u306B\u4F7F\u308F\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002
|
|
17033
|
+
- \u30C7\u30D5\u30A9\u30EB\u30C8\u306E\u300C\u76F4\u8FD1 N \u65E5\u300D\u30C4\u30FC\u30EB\u3092\u4F7F\u3046\u5834\u5408\u306F\u3001\u7A7A\u306E\u5B9F\u969B\u73FE\u5728\u65E5\u4ED8\u30A6\u30A3\u30F3\u30C9\u30A6\u3092\u8A66\u3059\u306E\u3067\u306F\u306A\u304F\u3001\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u6642\u9593\u5883\u754C\u3068\u4EA4\u5DEE\u3059\u308B\u7BC4\u56F2\u3092\u5148\u306B\u9078\u3093\u3067\u304F\u3060\u3055\u3044\u3002
|
|
17034
|
+
- min/max timestamp \u3092\u518D\u767A\u898B\u3059\u308B\u305F\u3081\u3060\u3051\u306B\u30C4\u30FC\u30EB\u3092\u547C\u3070\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002\u305F\u3060\u3057\u3001\u5177\u4F53\u7684\u306A\u30C1\u30E3\u30C3\u30C8\u4E8B\u5B9F\u3001\u7D71\u8A08\u3001\u7D50\u8AD6\u306B\u306F\u5F15\u304D\u7D9A\u304D\u30C4\u30FC\u30EB\u8A3C\u62E0\u304C\u5FC5\u8981\u3067\u3059\u3002`,
|
|
16358
17035
|
evidencePolicy: `\u8A3C\u62E0\u30DD\u30EA\u30B7\u30FC\uFF1A
|
|
16359
17036
|
- AI \u4F1A\u8A71\u5C65\u6B74\u3001\u904E\u53BB\u306E AI \u56DE\u7B54\u3001\u5727\u7E2E\u8981\u7D04\u306F\u30E6\u30FC\u30B6\u30FC\u610F\u56F3\u306E\u7406\u89E3\u306B\u306E\u307F\u4F7F\u7528\u3057\u3001\u30C1\u30E3\u30C3\u30C8\u8A18\u9332\u306E\u4E8B\u5B9F\u8A3C\u62E0\u3068\u3057\u3066\u6271\u308F\u306A\u3044\u3002
|
|
16360
17037
|
- \u30E6\u30FC\u30B6\u30FC\u304C\u30C1\u30E3\u30C3\u30C8\u5185\u5BB9\u3001\u6700\u8FD1\u306E\u8A71\u984C\u3001\u8AB0\u304B\u306E\u767A\u8A00\u3001\u30E9\u30F3\u30AD\u30F3\u30B0/\u7D71\u8A08\u3001\u3042\u308B\u8A71\u984C\u304C\u51FA\u305F\u304B\u3069\u3046\u304B\u3001\u307E\u305F\u306F\u539F\u6587\u5F15\u7528\u3092\u6C42\u3081\u305F\u5834\u5408\u306F\u3001\u5FC5\u305A\u5148\u306B\u9069\u5207\u306A\u30C7\u30FC\u30BF\u30C4\u30FC\u30EB\u3067\u73FE\u5728\u306E\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u691C\u7D22\u3059\u308B\u3002
|
|
@@ -16461,7 +17138,7 @@ var zh_TW_default = {
|
|
|
16461
17138
|
}
|
|
16462
17139
|
},
|
|
16463
17140
|
get_time_stats: {
|
|
16464
|
-
desc: "\u53D6\u5F97\u7FA4\u804A\u7684\u6642\u9593\u5206\u4F48\u7D71\u8A08\u3002\u9069\u7528\u65BC\u56DE\u7B54\u300C\u4EC0\u9EBC\u6642\u5019\u6700\u6D3B\u8E8D\u300D\u3001\u300C\u5927\u5BB6\u4E00\u822C\u5E7E\u9EDE\u804A\u5929\u300D\u7B49\u554F\u984C\u3002",
|
|
17141
|
+
desc: "\u53D6\u5F97\u7FA4\u804A\u7684\u6642\u9593\u5206\u4F48\u7D71\u8A08\u3002\u9069\u7528\u65BC\u56DE\u7B54\u300C\u4EC0\u9EBC\u6642\u5019\u6700\u6D3B\u8E8D\u300D\u3001\u300C\u5927\u5BB6\u4E00\u822C\u5E7E\u9EDE\u804A\u5929\u300D\u7B49\u554F\u984C\u3002\u8FD4\u56DE\u7684 `data` \u9663\u5217\u53EF\u76F4\u63A5\u4F5C\u70BA `render_chart` \u7684 `rows` \u53C3\u6578\u7528\u65BC\u7E6A\u5716\u3002",
|
|
16465
17142
|
params: {
|
|
16466
17143
|
type: "\u7D71\u8A08\u985E\u578B\uFF1Ahourly\uFF08\u6309\u5C0F\u6642\uFF09\u3001weekday\uFF08\u6309\u661F\u671F\uFF09\u3001daily\uFF08\u6309\u65E5\u671F\uFF09"
|
|
16467
17144
|
}
|
|
@@ -16651,9 +17328,10 @@ var zh_TW_default = {
|
|
|
16651
17328
|
params: {}
|
|
16652
17329
|
},
|
|
16653
17330
|
render_chart: {
|
|
16654
|
-
desc: "\u6839\u64DA
|
|
17331
|
+
desc: "\u6839\u64DA ChartSpec v1 \u751F\u6210 ChatLab \u539F\u751F\u5716\u8868\u3002\u652F\u63F4 bar\u3001line\u3001pie\u3001heatmap\u3002\u63D0\u4F9B `rows`\uFF08\u4F86\u81EA\u9AD8\u5C64\u5DE5\u5177\u7684\u8CC7\u6599\u9663\u5217\uFF0C\u5982 get_time_stats \u7684 `data` \u6B04\u4F4D\uFF09\u6216 `sql`\uFF08\u552F\u8B80 SELECT\uFF09\u4E8C\u64C7\u4E00\uFF1B\u6709\u73FE\u6210\u8CC7\u6599\u6642\u512A\u5148\u7528 `rows`\uFF0C\u50C5\u5728\u9AD8\u5C64\u5DE5\u5177\u7121\u6CD5\u6EFF\u8DB3\u9700\u6C42\u6642\u624D\u5BEB `sql`\u3002\u7981\u6B62\u8F38\u51FA HTML\u3001JavaScript\u3001SVG\u3001ECharts option \u6216\u6E32\u67D3\u7A0B\u5F0F\u78BC\u3002",
|
|
16655
17332
|
params: {
|
|
16656
|
-
|
|
17333
|
+
rows: "\u4F86\u81EA\u9AD8\u5C64\u5DE5\u5177\u8FD4\u56DE\u7684\u8CC7\u6599\u9663\u5217\uFF08\u5982 get_time_stats \u7684 `data` \u6B04\u4F4D\uFF09\u3002\u6709\u73FE\u6210\u8CC7\u6599\u6642\u512A\u5148\u4F7F\u7528\uFF0C\u8207 sql \u4E8C\u64C7\u4E00\u3002",
|
|
17334
|
+
sql: "\u552F\u8B80 SELECT \u6216 WITH SELECT SQL\u3002\u50C5\u5728\u9AD8\u5C64\u5DE5\u5177\u7121\u6CD5\u6EFF\u8DB3\u9700\u6C42\u6642\u4F7F\u7528\uFF0C\u5FC5\u9808\u8FD4\u56DE ChartSpec encoding \u4E2D\u5F15\u7528\u7684\u6B04\u4F4D\u3002",
|
|
16657
17335
|
params: "SQL \u547D\u540D\u53C3\u6578\u7269\u4EF6\uFF1B\u4E0D\u9700\u8981\u53C3\u6578\u6642\u50B3\u7A7A\u7269\u4EF6\u3002",
|
|
16658
17336
|
chartSpec: "ChartSpec v1\uFF0C\u5305\u542B version\u3001type\u3001title\u3001encoding\u3002",
|
|
16659
17337
|
maxRows: "\u5716\u8868\u67E5\u8A62\u6700\u5927\u884C\u6578\uFF0C\u9810\u8A2D 1000\u3002"
|
|
@@ -16687,6 +17365,35 @@ var zh_TW_default = {
|
|
|
16687
17365
|
timeParamsIntro: '\u6642\u9593\u53C3\u6578\uFF1A\u4F7F\u7528 start_time/end_time \u6307\u5B9A\u6642\u9593\u7BC4\u570D\uFF0C\u683C\u5F0F "YYYY-MM-DD HH:mm"',
|
|
16688
17366
|
defaultYearNote: "\u672A\u6307\u5B9A\u6642\u9593\u7BC4\u570D\u6642\u9810\u8A2D\u67E5\u8A62\u5168\u90E8\u3002\u7576\u524D\u5E74\u4EFD\u70BA{{year}}\u5E74",
|
|
16689
17367
|
dataSnapshotNote: "\u76EE\u524D\u804A\u5929\u8CC7\u6599\u5EAB\u5FEB\u7167\uFF1A{{name}}\uFF08{{platform}}\uFF09\uFF0C\u7E3D\u8A0A\u606F {{totalMessages}} \u689D\uFF0C\u6210\u54E1 {{totalMembers}} \u4EBA\uFF0C\u6642\u9593\u7BC4\u570D {{firstMessageDate}} ~ {{lastMessageDate}}\u3002\u8A72\u5FEB\u7167\u53EA\u7528\u65BC\u5224\u65B7\u8CC7\u6599\u7BC4\u570D\uFF1B\u56DE\u7B54\u5177\u9AD4\u804A\u5929\u4E8B\u5BE6\u4ECD\u5FC5\u9808\u547C\u53EB\u5DE5\u5177\u6AA2\u7D22\u76EE\u524D\u8CC7\u6599\u5EAB\u3002",
|
|
17368
|
+
dataSnapshotContext: `\u76EE\u524D\u804A\u5929\u8CC7\u6599\u5EAB\u555F\u52D5\u4E0A\u4E0B\u6587\uFF1A
|
|
17369
|
+
- name: {{name}}
|
|
17370
|
+
- platform: {{platform}}
|
|
17371
|
+
- type: {{type}}
|
|
17372
|
+
- total_messages: {{totalMessages}}
|
|
17373
|
+
- total_members: {{totalMembers}}
|
|
17374
|
+
- first_message_ts: {{firstMessageTs}}
|
|
17375
|
+
- first_message_time: {{firstMessageTime}}
|
|
17376
|
+
- last_message_ts: {{lastMessageTs}}
|
|
17377
|
+
- last_message_time: {{lastMessageTime}}
|
|
17378
|
+
- segment_summaries_available: {{segmentSummaryCount}}
|
|
17379
|
+
|
|
17380
|
+
{{memberHintTitle}}
|
|
17381
|
+
{{memberHintLines}}
|
|
17382
|
+
|
|
17383
|
+
\u4F7F\u7528\u898F\u5247\uFF1A
|
|
17384
|
+
{{usageRules}}`,
|
|
17385
|
+
dataSnapshotMemberHintsAll: "\u6D3B\u8E8D\u6210\u54E1\u67E5\u8A62\u63D0\u793A\uFF08\u5168\u90E8\u6210\u54E1\uFF09\uFF1A",
|
|
17386
|
+
dataSnapshotMemberHintsTop: "\u6D3B\u8E8D\u6210\u54E1\u67E5\u8A62\u63D0\u793A\uFF08\u6309\u6B77\u53F2\u7E3D\u8A0A\u606F\u91CF Top 10\uFF09\uFF1A",
|
|
17387
|
+
dataSnapshotMemberHintsUnavailable: "\u6D3B\u8E8D\u6210\u54E1\u67E5\u8A62\u63D0\u793A\uFF1A",
|
|
17388
|
+
dataSnapshotMemberHintsEmpty: "\u7121\u53EF\u7528\u6210\u54E1\u63D0\u793A\u3002",
|
|
17389
|
+
dataSnapshotUsageRules: `- member_id \u662F\u5DE5\u5177\u67E5\u8A62\u63D0\u793A\uFF1Bdisplay_name \u50C5\u7528\u65BC\u4EBA\u985E\u8B58\u5225\uFF0C\u53EF\u80FD\u4E0D\u552F\u4E00\u3002
|
|
17390
|
+
- \u4E0D\u8981\u5728\u6700\u7D42\u56DE\u7B54\u4E2D\u4E3B\u52D5\u66B4\u9732 member_id \u6216\u555F\u52D5\u4E0A\u4E0B\u6587\u672C\u8EAB\uFF0C\u9664\u975E\u4F7F\u7528\u8005\u660E\u78BA\u8981\u6C42\u6280\u8853\u7D30\u7BC0\u3002
|
|
17391
|
+
- \u6D3B\u8E8D\u6210\u54E1\u6392\u884C\u53EA\u4EE3\u8868\u6B77\u53F2\u7E3D\u8A0A\u606F\u91CF\uFF0C\u4E0D\u4EE3\u8868\u8FD1\u671F\u6D3B\u8E8D\u60C5\u6CC1\uFF1B\u4E5F\u4E0D\u8DB3\u4EE5\u4F5C\u70BA\u5F71\u97FF\u529B\u3001\u95DC\u4FC2\u6216\u8FD1\u671F\u8DA8\u52E2\u7D50\u8AD6\u7684\u8B49\u64DA\u3002
|
|
17392
|
+
- \u76F8\u5C0D\u6642\u9593\u8868\u9054\u4EE5\u771F\u5BE6\u76EE\u524D\u65E5\u671F\u70BA\u57FA\u6E96\uFF0C\u800C\u4E0D\u662F\u8CC7\u6599\u5EAB\u6700\u5F8C\u8A0A\u606F\u6642\u9593\u3002
|
|
17393
|
+
-\u300C\u6700\u8FD1\u4E00\u5E74/\u904E\u53BB\u4E00\u5E74\u300D\u8868\u793A\u5F9E\u771F\u5BE6\u76EE\u524D\u65E5\u671F\u56DE\u63A8\u4E00\u5E74\u5230\u4ECA\u5929\uFF1B\u300C\u53BB\u5E74\u300D\u8868\u793A\u4E0A\u4E00\u81EA\u7136\u5E74\u3002
|
|
17394
|
+
- \u8CC7\u6599\u5EAB\u6642\u9593\u908A\u754C\u53EA\u7528\u65BC\u8AAA\u660E\u8986\u84CB\u7BC4\u570D\uFF0C\u4E0D\u7528\u65BC\u91CD\u5B9A\u7FA9\u4F7F\u7528\u8005\u8981\u6C42\u7684\u6642\u9593\u7BC4\u570D\u3002
|
|
17395
|
+
- \u4F7F\u7528\u9810\u8A2D\u300C\u8FD1 N \u5929\u300D\u7684\u5DE5\u5177\u6642\uFF0C\u5148\u9078\u64C7\u8207\u8CC7\u6599\u5EAB\u6642\u9593\u908A\u754C\u6709\u4EA4\u96C6\u7684\u7BC4\u570D\uFF0C\u4E0D\u8981\u5148\u63A2\u6E2C\u771F\u5BE6\u76EE\u524D\u65E5\u671F\u8996\u7A97\u5C0E\u81F4\u7A7A\u7D50\u679C\u3002
|
|
17396
|
+
- \u4E0D\u8981\u53EA\u70BA\u4E86\u91CD\u65B0\u767C\u73FE min/max timestamp \u547C\u53EB\u5DE5\u5177\uFF1B\u4F46\u56DE\u7B54\u5177\u9AD4\u804A\u5929\u4E8B\u5BE6\u3001\u7D71\u8A08\u548C\u7D50\u8AD6\u4ECD\u5FC5\u9808\u547C\u53EB\u5DE5\u5177\u53D6\u5F97\u8B49\u64DA\u3002`,
|
|
16690
17397
|
evidencePolicy: `\u8B49\u64DA\u7B56\u7565\uFF1A
|
|
16691
17398
|
- AI \u5C0D\u8A71\u6B77\u53F2\u3001\u6B77\u53F2 AI \u56DE\u8986\u548C\u58D3\u7E2E\u6458\u8981\u53EA\u7528\u65BC\u7406\u89E3\u4F7F\u7528\u8005\u610F\u5716\uFF0C\u4E0D\u80FD\u4F5C\u70BA\u804A\u5929\u7D00\u9304\u4E8B\u5BE6\u8B49\u64DA\u3002
|
|
16692
17399
|
- \u53EA\u8981\u4F7F\u7528\u8005\u8A62\u554F\u804A\u5929\u7D00\u9304\u5167\u5BB9\u3001\u6700\u8FD1\u804A\u4EC0\u9EBC\u3001\u67D0\u4EBA\u8AAA\u904E\u4EC0\u9EBC\u3001\u7D71\u8A08\u6392\u884C\u3001\u662F\u5426\u51FA\u73FE\u904E\u67D0\u8A71\u984C\u6216\u8981\u6C42\u5F15\u7528\u539F\u8A71\uFF0C\u5FC5\u9808\u5148\u547C\u53EB\u5408\u9069\u7684\u8CC7\u6599\u5DE5\u5177\u6AA2\u7D22\u76EE\u524D\u8CC7\u6599\u5EAB\u3002
|
|
@@ -17127,7 +17834,7 @@ function buildPiModel(config, options) {
|
|
|
17127
17834
|
}
|
|
17128
17835
|
|
|
17129
17836
|
// ../../packages/node-runtime/src/ai/remote-api.ts
|
|
17130
|
-
import { completeSimple as
|
|
17837
|
+
import { completeSimple as completeSimple4 } from "@earendil-works/pi-ai";
|
|
17131
17838
|
async function fetchRemoteModels(provider, apiKey, baseUrl, apiFormat, options) {
|
|
17132
17839
|
const effectiveApiFormat = apiFormat || "openai-completions";
|
|
17133
17840
|
if (effectiveApiFormat === "anthropic-messages") {
|
|
@@ -17211,7 +17918,7 @@ async function validateApiKey(provider, apiKey, baseUrl, model, apiFormat, optio
|
|
|
17211
17918
|
const abortController = new AbortController();
|
|
17212
17919
|
const timeout = setTimeout(() => abortController.abort(), 15e3);
|
|
17213
17920
|
try {
|
|
17214
|
-
const result = await
|
|
17921
|
+
const result = await completeSimple4(
|
|
17215
17922
|
piModel,
|
|
17216
17923
|
{ messages: [{ role: "user", content: "Hi", timestamp: Date.now() }] },
|
|
17217
17924
|
{ apiKey, maxTokens: 1, signal: abortController.signal }
|
|
@@ -17232,7 +17939,7 @@ async function validateApiKey(provider, apiKey, baseUrl, model, apiFormat, optio
|
|
|
17232
17939
|
}
|
|
17233
17940
|
|
|
17234
17941
|
// ../../packages/node-runtime/src/ai/llm-stream.ts
|
|
17235
|
-
import { streamSimple } from "@earendil-works/pi-ai";
|
|
17942
|
+
import { streamSimple as streamSimple2 } from "@earendil-works/pi-ai";
|
|
17236
17943
|
function toPiMessages(messages, timestamp) {
|
|
17237
17944
|
return messages.map((m) => ({
|
|
17238
17945
|
role: m.role,
|
|
@@ -17245,7 +17952,7 @@ async function runSimpleLlmStream(options) {
|
|
|
17245
17952
|
const systemMsg = messages.find((m) => m.role === "system");
|
|
17246
17953
|
const nonSystemMsgs = messages.filter((m) => m.role !== "system");
|
|
17247
17954
|
const now = Date.now();
|
|
17248
|
-
const eventStream =
|
|
17955
|
+
const eventStream = streamSimple2(
|
|
17249
17956
|
piModel,
|
|
17250
17957
|
{
|
|
17251
17958
|
systemPrompt: systemMsg?.content,
|
|
@@ -17303,7 +18010,7 @@ async function runSimpleLlmStream(options) {
|
|
|
17303
18010
|
}
|
|
17304
18011
|
|
|
17305
18012
|
// ../../packages/node-runtime/src/ai/index.ts
|
|
17306
|
-
import { Type, completeSimple as
|
|
18013
|
+
import { Type, completeSimple as completeSimple6, streamSimple as streamSimple3 } from "@earendil-works/pi-ai";
|
|
17307
18014
|
|
|
17308
18015
|
// ../../packages/node-runtime/src/ai/rag/types.ts
|
|
17309
18016
|
var noopLogger = {
|
|
@@ -17342,7 +18049,7 @@ var _logger6 = getNoopLogger();
|
|
|
17342
18049
|
var _logger7 = getNoopLogger();
|
|
17343
18050
|
|
|
17344
18051
|
// ../../packages/node-runtime/src/ai/rag/pipeline/semantic.ts
|
|
17345
|
-
import { completeSimple as
|
|
18052
|
+
import { completeSimple as completeSimple5 } from "@earendil-works/pi-ai";
|
|
17346
18053
|
var _logger8 = getNoopLogger();
|
|
17347
18054
|
|
|
17348
18055
|
// ../../packages/node-runtime/src/migrations/electron-data-migration.ts
|
|
@@ -17967,7 +18674,7 @@ function getMetaPath(userDataDir) {
|
|
|
17967
18674
|
return path31.join(userDataDir, ".chatlab-meta.json");
|
|
17968
18675
|
}
|
|
17969
18676
|
function validateDataDirCompatibilityMeta(value, userDataDir, metaPath) {
|
|
17970
|
-
if (!
|
|
18677
|
+
if (!isRecord3(value)) {
|
|
17971
18678
|
throw createInvalidMetaError(userDataDir, metaPath, "Data directory compatibility meta must be an object.");
|
|
17972
18679
|
}
|
|
17973
18680
|
if (value.formatVersion !== 1) {
|
|
@@ -17978,7 +18685,7 @@ function validateDataDirCompatibilityMeta(value, userDataDir, metaPath) {
|
|
|
17978
18685
|
const reasons = value.reasons;
|
|
17979
18686
|
const updatedBy = value.updatedBy;
|
|
17980
18687
|
const updatedAt = value.updatedAt;
|
|
17981
|
-
if (!isStableSemver(minRuntimeVersion) || typeof dataCompatibilityVersion !== "number" || !Number.isInteger(dataCompatibilityVersion) || dataCompatibilityVersion < 0 || !Array.isArray(reasons) || !reasons.every(isNonEmptyString) || !
|
|
18688
|
+
if (!isStableSemver(minRuntimeVersion) || typeof dataCompatibilityVersion !== "number" || !Number.isInteger(dataCompatibilityVersion) || dataCompatibilityVersion < 0 || !Array.isArray(reasons) || !reasons.every(isNonEmptyString) || !isRecord3(updatedBy) || !isRuntimeKind(updatedBy.runtime) || !isNonEmptyString(updatedBy.module) || !isStableSemver(updatedBy.version) || typeof updatedAt !== "number" || !Number.isInteger(updatedAt) || updatedAt < 0) {
|
|
17982
18689
|
throw createInvalidMetaError(userDataDir, metaPath, "Invalid data directory compatibility meta fields.");
|
|
17983
18690
|
}
|
|
17984
18691
|
return {
|
|
@@ -18036,7 +18743,7 @@ function writeMetaAtomic(userDataDir, metaPath, meta) {
|
|
|
18036
18743
|
throw error;
|
|
18037
18744
|
}
|
|
18038
18745
|
}
|
|
18039
|
-
function
|
|
18746
|
+
function isRecord3(value) {
|
|
18040
18747
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
18041
18748
|
}
|
|
18042
18749
|
function isNonEmptyString(value) {
|
|
@@ -18820,6 +19527,127 @@ function exportSessionMode(db, params, writer, progress) {
|
|
|
18820
19527
|
return { totalMessages, blockIndex };
|
|
18821
19528
|
}
|
|
18822
19529
|
|
|
19530
|
+
// ../../packages/node-runtime/src/export/format-exporter.ts
|
|
19531
|
+
function queryMessages2(db, timeFilter) {
|
|
19532
|
+
const hasFilter = !!timeFilter;
|
|
19533
|
+
const sql = `
|
|
19534
|
+
SELECT msg.ts,
|
|
19535
|
+
COALESCE(m.group_nickname, m.account_name, m.platform_id) as senderName,
|
|
19536
|
+
msg.content
|
|
19537
|
+
FROM message msg
|
|
19538
|
+
JOIN member m ON msg.sender_id = m.id
|
|
19539
|
+
${hasFilter ? "WHERE msg.ts >= ? AND msg.ts <= ?" : ""}
|
|
19540
|
+
ORDER BY msg.ts ASC, msg.id ASC
|
|
19541
|
+
`;
|
|
19542
|
+
const params = [];
|
|
19543
|
+
if (hasFilter) {
|
|
19544
|
+
params.push(timeFilter.startTs, timeFilter.endTs);
|
|
19545
|
+
}
|
|
19546
|
+
return db.prepare(sql).all(...params);
|
|
19547
|
+
}
|
|
19548
|
+
function formatTime(ts) {
|
|
19549
|
+
return new Date(ts * 1e3).toLocaleString();
|
|
19550
|
+
}
|
|
19551
|
+
function formatTimeShort(ts) {
|
|
19552
|
+
return new Date(ts * 1e3).toLocaleTimeString("zh-CN", { hour: "2-digit", minute: "2-digit", second: "2-digit" });
|
|
19553
|
+
}
|
|
19554
|
+
function exportAsTxt(messages, sessionName) {
|
|
19555
|
+
const lines = [`${sessionName}
|
|
19556
|
+
`];
|
|
19557
|
+
let lastDate = "";
|
|
19558
|
+
for (const msg of messages) {
|
|
19559
|
+
const date = new Date(msg.ts * 1e3).toLocaleDateString();
|
|
19560
|
+
if (date !== lastDate) {
|
|
19561
|
+
lines.push(`
|
|
19562
|
+
--- ${date} ---
|
|
19563
|
+
`);
|
|
19564
|
+
lastDate = date;
|
|
19565
|
+
}
|
|
19566
|
+
lines.push(`${formatTimeShort(msg.ts)} ${msg.senderName}: ${msg.content || "[non-text]"}`);
|
|
19567
|
+
}
|
|
19568
|
+
return lines.join("\n");
|
|
19569
|
+
}
|
|
19570
|
+
function exportAsJson(messages, sessionName) {
|
|
19571
|
+
const data = {
|
|
19572
|
+
sessionName,
|
|
19573
|
+
exportTime: (/* @__PURE__ */ new Date()).toISOString(),
|
|
19574
|
+
totalMessages: messages.length,
|
|
19575
|
+
messages: messages.map((msg) => ({
|
|
19576
|
+
timestamp: msg.ts,
|
|
19577
|
+
time: formatTime(msg.ts),
|
|
19578
|
+
sender: msg.senderName,
|
|
19579
|
+
content: msg.content || ""
|
|
19580
|
+
}))
|
|
19581
|
+
};
|
|
19582
|
+
return JSON.stringify(data, null, 2);
|
|
19583
|
+
}
|
|
19584
|
+
function exportAsMarkdown(messages, sessionName) {
|
|
19585
|
+
const lines = [`# ${sessionName}
|
|
19586
|
+
`, `> Export time: ${(/* @__PURE__ */ new Date()).toLocaleString()}
|
|
19587
|
+
`];
|
|
19588
|
+
let lastDate = "";
|
|
19589
|
+
for (const msg of messages) {
|
|
19590
|
+
const date = new Date(msg.ts * 1e3).toLocaleDateString();
|
|
19591
|
+
if (date !== lastDate) {
|
|
19592
|
+
lines.push(`
|
|
19593
|
+
## ${date}
|
|
19594
|
+
`);
|
|
19595
|
+
lastDate = date;
|
|
19596
|
+
}
|
|
19597
|
+
lines.push(`**${formatTimeShort(msg.ts)} ${msg.senderName}**: ${msg.content || "*[non-text]*"}`);
|
|
19598
|
+
}
|
|
19599
|
+
return lines.join("\n");
|
|
19600
|
+
}
|
|
19601
|
+
var FORMAT_CONFIG = {
|
|
19602
|
+
txt: { ext: "txt", mime: "text/plain; charset=utf-8" },
|
|
19603
|
+
json: { ext: "json", mime: "application/json; charset=utf-8" },
|
|
19604
|
+
markdown: { ext: "md", mime: "text/markdown; charset=utf-8" }
|
|
19605
|
+
};
|
|
19606
|
+
function exportWithFormat(params, openDatabase) {
|
|
19607
|
+
const db = openDatabase(params.sessionId);
|
|
19608
|
+
if (!db) {
|
|
19609
|
+
return { success: false, error: "Cannot open database", totalMessages: 0, content: "", filename: "", mimeType: "" };
|
|
19610
|
+
}
|
|
19611
|
+
try {
|
|
19612
|
+
const messages = queryMessages2(db, params.timeFilter);
|
|
19613
|
+
if (messages.length === 0) {
|
|
19614
|
+
return {
|
|
19615
|
+
success: false,
|
|
19616
|
+
error: "No messages found in the specified range",
|
|
19617
|
+
totalMessages: 0,
|
|
19618
|
+
content: "",
|
|
19619
|
+
filename: "",
|
|
19620
|
+
mimeType: ""
|
|
19621
|
+
};
|
|
19622
|
+
}
|
|
19623
|
+
const { ext, mime } = FORMAT_CONFIG[params.format];
|
|
19624
|
+
let content;
|
|
19625
|
+
switch (params.format) {
|
|
19626
|
+
case "txt":
|
|
19627
|
+
content = exportAsTxt(messages, params.sessionName);
|
|
19628
|
+
break;
|
|
19629
|
+
case "json":
|
|
19630
|
+
content = exportAsJson(messages, params.sessionName);
|
|
19631
|
+
break;
|
|
19632
|
+
case "markdown":
|
|
19633
|
+
content = exportAsMarkdown(messages, params.sessionName);
|
|
19634
|
+
break;
|
|
19635
|
+
}
|
|
19636
|
+
const timestamp = Date.now();
|
|
19637
|
+
const filename = `${params.sessionName}_export_${timestamp}.${ext}`;
|
|
19638
|
+
return { success: true, totalMessages: messages.length, content, filename, mimeType: mime };
|
|
19639
|
+
} catch (error) {
|
|
19640
|
+
return {
|
|
19641
|
+
success: false,
|
|
19642
|
+
error: String(error),
|
|
19643
|
+
totalMessages: 0,
|
|
19644
|
+
content: "",
|
|
19645
|
+
filename: "",
|
|
19646
|
+
mimeType: ""
|
|
19647
|
+
};
|
|
19648
|
+
}
|
|
19649
|
+
}
|
|
19650
|
+
|
|
18823
19651
|
// ../../packages/node-runtime/src/preferences.ts
|
|
18824
19652
|
import * as fs36 from "fs";
|
|
18825
19653
|
import * as path33 from "path";
|
|
@@ -18842,6 +19670,7 @@ var DEFAULTS = {
|
|
|
18842
19670
|
exportFormat: "markdown",
|
|
18843
19671
|
sqlExportFormat: "csv",
|
|
18844
19672
|
enableAutoSkill: true,
|
|
19673
|
+
chartAutoMode: "suggest",
|
|
18845
19674
|
searchContextBefore: 2,
|
|
18846
19675
|
searchContextAfter: 2,
|
|
18847
19676
|
contextCompression: {
|
|
@@ -18858,7 +19687,8 @@ var DEFAULTS = {
|
|
|
18858
19687
|
defaultSchemeId: null,
|
|
18859
19688
|
sessionSchemeOverrides: {}
|
|
18860
19689
|
},
|
|
18861
|
-
filterHistory: []
|
|
19690
|
+
filterHistory: [],
|
|
19691
|
+
thinkingLevels: {}
|
|
18862
19692
|
};
|
|
18863
19693
|
var PreferencesManager = class {
|
|
18864
19694
|
filePath;
|
|
@@ -18926,7 +19756,8 @@ var PreferencesManager = class {
|
|
|
18926
19756
|
customKeywordTemplates: partial.customKeywordTemplates ?? DEFAULTS.customKeywordTemplates,
|
|
18927
19757
|
deletedPresetTemplateIds: partial.deletedPresetTemplateIds ?? DEFAULTS.deletedPresetTemplateIds,
|
|
18928
19758
|
wordFilter: partial.wordFilter ? { ...DEFAULTS.wordFilter, ...partial.wordFilter } : { ...DEFAULTS.wordFilter },
|
|
18929
|
-
filterHistory: partial.filterHistory ?? DEFAULTS.filterHistory
|
|
19759
|
+
filterHistory: partial.filterHistory ?? DEFAULTS.filterHistory,
|
|
19760
|
+
thinkingLevels: partial.thinkingLevels ?? DEFAULTS.thinkingLevels
|
|
18930
19761
|
};
|
|
18931
19762
|
}
|
|
18932
19763
|
normalizeAiPreprocessConfig(partial) {
|
|
@@ -19549,7 +20380,7 @@ function buildSummaryDeps(db, llmConfig, deps) {
|
|
|
19549
20380
|
return getSegmentSummary(db, segmentId);
|
|
19550
20381
|
},
|
|
19551
20382
|
async llmComplete(systemPrompt, userPrompt, options) {
|
|
19552
|
-
const result = await
|
|
20383
|
+
const result = await completeSimple6(
|
|
19553
20384
|
piModel,
|
|
19554
20385
|
{
|
|
19555
20386
|
systemPrompt,
|
|
@@ -19609,6 +20440,7 @@ function checkCanGenerate(adapter, sessionId, segmentIds) {
|
|
|
19609
20440
|
// ../../packages/node-runtime/src/services/export-service.ts
|
|
19610
20441
|
var export_service_exports = {};
|
|
19611
20442
|
__export(export_service_exports, {
|
|
20443
|
+
exportFormatted: () => exportFormatted,
|
|
19612
20444
|
exportMarkdown: () => exportMarkdown
|
|
19613
20445
|
});
|
|
19614
20446
|
function exportMarkdown(adapter, params) {
|
|
@@ -19630,6 +20462,9 @@ function exportMarkdown(adapter, params) {
|
|
|
19630
20462
|
);
|
|
19631
20463
|
return { result, content: chunks.join("") };
|
|
19632
20464
|
}
|
|
20465
|
+
function exportFormatted(adapter, params) {
|
|
20466
|
+
return exportWithFormat(params, (sessionId) => adapter.openReadonly(sessionId));
|
|
20467
|
+
}
|
|
19633
20468
|
|
|
19634
20469
|
// ../../packages/node-runtime/src/services/adapters/database-manager-adapter.ts
|
|
19635
20470
|
import * as fs38 from "fs";
|
|
@@ -19782,8 +20617,6 @@ export {
|
|
|
19782
20617
|
getMemberNameHistory,
|
|
19783
20618
|
getMembersWithAliases,
|
|
19784
20619
|
executeParameterizedSql,
|
|
19785
|
-
filterMessagesWithContext,
|
|
19786
|
-
getMultipleSessionsMessages,
|
|
19787
20620
|
getCatchphraseAnalysis,
|
|
19788
20621
|
getMentionAnalysis,
|
|
19789
20622
|
getMentionGraph,
|
|
@@ -19836,6 +20669,8 @@ export {
|
|
|
19836
20669
|
createActivateSkillTool,
|
|
19837
20670
|
CHART_CAPABILITY_CORE_TOOLS,
|
|
19838
20671
|
getAllowedBuiltinToolsForChartAutoSkill,
|
|
20672
|
+
shouldUseChartCapabilityForMessage,
|
|
20673
|
+
getChartPlannerCapabilityForMessage,
|
|
19839
20674
|
resolveChartRuntimeForRequest,
|
|
19840
20675
|
getChartCapabilitySkill,
|
|
19841
20676
|
buildSkillMenuWithBuiltinChart,
|
|
@@ -19849,6 +20684,12 @@ export {
|
|
|
19849
20684
|
applyPreprocessingPipeline,
|
|
19850
20685
|
DEFAULT_MAX_TOOL_ROUNDS,
|
|
19851
20686
|
runAgentCore,
|
|
20687
|
+
createDataSnapshotFromOverview,
|
|
20688
|
+
decideRequestRoute,
|
|
20689
|
+
createLlmRouteDecider,
|
|
20690
|
+
createAnalysisPlanner,
|
|
20691
|
+
createPlanContentBlock,
|
|
20692
|
+
buildPlanGuidance,
|
|
19852
20693
|
AgentEventHandler,
|
|
19853
20694
|
buildSystemPrompt,
|
|
19854
20695
|
createAiTranslate,
|
|
@@ -19884,4 +20725,4 @@ export {
|
|
|
19884
20725
|
createDatabaseManagerAdapter,
|
|
19885
20726
|
MergeSessionCache
|
|
19886
20727
|
};
|
|
19887
|
-
//# sourceMappingURL=chunk-
|
|
20728
|
+
//# sourceMappingURL=chunk-GUGKY2GV.mjs.map
|