chatlab-cli 0.22.0 → 0.23.0
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/{chunk-3UBWLWXB.mjs → chunk-3MX7VF2B.mjs} +2 -2
- package/dist/chunk-5ADKYYNA.mjs +28 -0
- package/dist/chunk-5ADKYYNA.mjs.map +1 -0
- package/dist/{chunk-4U45E7TO.mjs → chunk-643S2N2U.mjs} +2 -2
- package/dist/{chunk-AMMSVJG4.mjs → chunk-D2BR3MFN.mjs} +132 -43
- package/dist/chunk-D2BR3MFN.mjs.map +1 -0
- package/dist/{chunk-6NB475AA.mjs → chunk-FJ35V3TE.mjs} +2 -17
- package/dist/chunk-FJ35V3TE.mjs.map +1 -0
- package/dist/{chunk-QJQJIUUS.mjs → chunk-G7Q7EQ3V.mjs} +618 -108
- package/dist/chunk-G7Q7EQ3V.mjs.map +1 -0
- package/dist/{chunk-6GLMVWGA.mjs → chunk-NTWDG52H.mjs} +66 -68
- package/dist/chunk-NTWDG52H.mjs.map +1 -0
- package/dist/{chunk-D2XJ4Z7G.mjs → chunk-WTQ7LAZR.mjs} +2 -2
- package/dist/cli.mjs +4 -3
- package/dist/{http-R5UECMPJ.mjs → http-2DN3XOXO.mjs} +8 -7
- package/dist/{import-3LOWRXWA.mjs → import-LCBSBLYF.mjs} +4 -4
- package/dist/index.mjs +10 -9
- package/dist/{mcp-WBHNLED2.mjs → mcp-AR7HBIK4.mjs} +8 -6
- package/dist/{mcp-WBHNLED2.mjs.map → mcp-AR7HBIK4.mjs.map} +1 -1
- package/dist/service-WNEVPQ4N.mjs +258 -0
- package/dist/service-WNEVPQ4N.mjs.map +1 -0
- package/dist/{src-UHM2UDRD.mjs → src-EGXULYFQ.mjs} +2 -2
- package/dist/{stream-import-V6Z7DXSW.mjs → stream-import-QM5R5FDG.mjs} +3 -3
- package/dist/{update-checker-MQMQ6A4B.mjs → update-checker-JG5K67O2.mjs} +3 -2
- package/dist/{update-checker-MQMQ6A4B.mjs.map → update-checker-JG5K67O2.mjs.map} +1 -1
- package/dist-web/assets/{DebugToolsPanel-DkbsB6lr.css → DebugToolsPanel-D9O_4J04.css} +1 -1
- package/dist-web/assets/DebugToolsPanel.vue_vue_type_script_setup_true_lang-hp9Mjpub.js +161 -0
- package/dist-web/assets/{EChartWordcloud-Ubal_aYg.js → EChartWordcloud-Cenbzcyj.js} +1 -1
- package/dist-web/assets/MessageExportModal-CvocO88D.js +1 -0
- package/dist-web/assets/electron-DpE69lO4.js +1 -0
- package/dist-web/assets/electron-SyPZX9OU.js +1 -0
- package/dist-web/assets/{fetch-BS4SlQjA.js → fetch-B7OBmANJ.js} +1 -1
- package/dist-web/assets/{fetch-o5NJ2uWE.js → fetch-BikSxuED.js} +1 -1
- package/dist-web/assets/fetch-BwMZFwbF.js +1 -0
- package/dist-web/assets/fetch-CfTcWxqG.js +1 -0
- package/dist-web/assets/fetch-DTP8Q782.js +17 -0
- package/dist-web/assets/{fetch-W43zfemj.js → fetch-LBHcBBkv.js} +1 -1
- package/dist-web/assets/http-C741fIwb.js +1 -0
- package/dist-web/assets/index-B6dkyIiA.js +2 -0
- package/dist-web/assets/index-CALU1QPF.js +163 -0
- package/dist-web/assets/{index-BJUGnYn5.js → index-CHkXbqMb.js} +1 -1
- package/dist-web/assets/index-CvuHOeoU.css +1 -0
- package/dist-web/assets/{index-BE64tUWq.css → index-CxMP0DNd.css} +1 -1
- package/dist-web/assets/index-DOS5o2_H.js +7 -0
- package/dist-web/assets/{index-CbQMfheg.css → index-DuepdDzz.css} +1 -1
- package/dist-web/assets/index-niwrSprs.js +173 -0
- package/dist-web/assets/model-catalog-DUuKjIVU.js +1 -0
- package/dist-web/assets/{vendor-nuxt-ui-7OAuiz_i.js → vendor-nuxt-ui-CuCZ1aRl.js} +2 -2
- package/dist-web/assets/vendor-reka-ui-BrTYuIfH.js +11 -0
- package/dist-web/assets/{web-CZe0Ismu.js → web-DGd63PrV.js} +1 -1
- package/dist-web/index.html +4 -4
- package/package.json +1 -1
- package/dist/chunk-6GLMVWGA.mjs.map +0 -1
- package/dist/chunk-6NB475AA.mjs.map +0 -1
- package/dist/chunk-AMMSVJG4.mjs.map +0 -1
- package/dist/chunk-QJQJIUUS.mjs.map +0 -1
- package/dist-web/assets/DebugToolsPanel.vue_vue_type_script_setup_true_lang-CxYyne-Q.js +0 -147
- package/dist-web/assets/MessageExportModal-De5_tX6a.js +0 -1
- package/dist-web/assets/electron-8qi0d92j.js +0 -1
- package/dist-web/assets/electron-H65bUnhW.js +0 -1
- package/dist-web/assets/fetch-CclRWOHf.js +0 -1
- package/dist-web/assets/fetch-Q-PqsiMb.js +0 -17
- package/dist-web/assets/fetch-cFjLAPG2.js +0 -1
- package/dist-web/assets/http-CeXMt-Fv.js +0 -1
- package/dist-web/assets/index-B_31fXeB.js +0 -2
- package/dist-web/assets/index-CbOwHYzO.css +0 -1
- package/dist-web/assets/index-DKMUn8F5.js +0 -173
- package/dist-web/assets/index-D_ksezTw.js +0 -163
- package/dist-web/assets/index-Dhg3SDb6.js +0 -7
- package/dist-web/assets/vendor-reka-ui-CW2cIgMu.js +0 -11
- /package/dist/{chunk-3UBWLWXB.mjs.map → chunk-3MX7VF2B.mjs.map} +0 -0
- /package/dist/{chunk-4U45E7TO.mjs.map → chunk-643S2N2U.mjs.map} +0 -0
- /package/dist/{chunk-D2XJ4Z7G.mjs.map → chunk-WTQ7LAZR.mjs.map} +0 -0
- /package/dist/{http-R5UECMPJ.mjs.map → http-2DN3XOXO.mjs.map} +0 -0
- /package/dist/{import-3LOWRXWA.mjs.map → import-LCBSBLYF.mjs.map} +0 -0
- /package/dist/{src-UHM2UDRD.mjs.map → src-EGXULYFQ.mjs.map} +0 -0
- /package/dist/{stream-import-V6Z7DXSW.mjs.map → stream-import-QM5R5FDG.mjs.map} +0 -0
|
@@ -2022,6 +2022,25 @@ function getSessionSummaries(db, options) {
|
|
|
2022
2022
|
});
|
|
2023
2023
|
}
|
|
2024
2024
|
var DEFAULT_SESSION_GAP_THRESHOLD = 1800;
|
|
2025
|
+
function getSessionIndexStats(db) {
|
|
2026
|
+
let sessionCount = 0;
|
|
2027
|
+
if (hasTable(db, "chat_session")) {
|
|
2028
|
+
try {
|
|
2029
|
+
const row = db.prepare("SELECT COUNT(*) as count FROM chat_session").get();
|
|
2030
|
+
sessionCount = row?.count ?? 0;
|
|
2031
|
+
} catch {
|
|
2032
|
+
}
|
|
2033
|
+
}
|
|
2034
|
+
let gapThreshold = DEFAULT_SESSION_GAP_THRESHOLD;
|
|
2035
|
+
try {
|
|
2036
|
+
const meta = db.prepare("SELECT session_gap_threshold FROM meta LIMIT 1").get();
|
|
2037
|
+
if (meta?.session_gap_threshold) {
|
|
2038
|
+
gapThreshold = meta.session_gap_threshold;
|
|
2039
|
+
}
|
|
2040
|
+
} catch {
|
|
2041
|
+
}
|
|
2042
|
+
return { sessionCount, hasIndex: sessionCount > 0, gapThreshold };
|
|
2043
|
+
}
|
|
2025
2044
|
function getChatSessionList(db) {
|
|
2026
2045
|
if (!hasTable(db, "chat_session")) return [];
|
|
2027
2046
|
try {
|
|
@@ -5774,6 +5793,138 @@ function needsStreamingThinkParsing(provider, _modelId) {
|
|
|
5774
5793
|
return provider === "minimax";
|
|
5775
5794
|
}
|
|
5776
5795
|
|
|
5796
|
+
// ../../packages/core/src/ai/thinking.ts
|
|
5797
|
+
var TYPE_LEVEL_MAP = {
|
|
5798
|
+
gpt5: {
|
|
5799
|
+
minimal: "minimal",
|
|
5800
|
+
low: "low",
|
|
5801
|
+
medium: "medium",
|
|
5802
|
+
high: "high"
|
|
5803
|
+
},
|
|
5804
|
+
gpt5_1: {
|
|
5805
|
+
off: "none",
|
|
5806
|
+
low: "low",
|
|
5807
|
+
medium: "medium",
|
|
5808
|
+
high: "high",
|
|
5809
|
+
xhigh: null
|
|
5810
|
+
},
|
|
5811
|
+
gpt5_2plus: {
|
|
5812
|
+
off: "none",
|
|
5813
|
+
minimal: "minimal",
|
|
5814
|
+
low: "low",
|
|
5815
|
+
medium: "medium",
|
|
5816
|
+
high: "high",
|
|
5817
|
+
xhigh: "xhigh"
|
|
5818
|
+
},
|
|
5819
|
+
grok: {
|
|
5820
|
+
minimal: null,
|
|
5821
|
+
low: "low",
|
|
5822
|
+
medium: null,
|
|
5823
|
+
high: "high",
|
|
5824
|
+
xhigh: null
|
|
5825
|
+
},
|
|
5826
|
+
kimi: {
|
|
5827
|
+
off: "none",
|
|
5828
|
+
auto: "auto",
|
|
5829
|
+
minimal: null,
|
|
5830
|
+
low: "low",
|
|
5831
|
+
medium: "medium",
|
|
5832
|
+
high: "high",
|
|
5833
|
+
xhigh: null
|
|
5834
|
+
},
|
|
5835
|
+
doubao: {
|
|
5836
|
+
off: null,
|
|
5837
|
+
auto: "auto",
|
|
5838
|
+
high: "high"
|
|
5839
|
+
},
|
|
5840
|
+
deepseek_hybrid: {
|
|
5841
|
+
off: null,
|
|
5842
|
+
auto: "auto",
|
|
5843
|
+
high: "high"
|
|
5844
|
+
}
|
|
5845
|
+
};
|
|
5846
|
+
var REASONING_FALLBACK_REGEX = /^(?!.*-non-reasoning\b)(o\d+(?:-[\w-]+)?|.*\b(?:reasoning|reasoner|thinking|think)\b.*|.*-[rR]\d+.*|.*\bqwq(?:-[\w-]+)?\b.*|.*\bhunyuan-t1(?:-[\w-]+)?\b.*|.*\bgrok-(?:3-mini|4|4-fast|build)(?:-[\w-]+)?\b.*)$/i;
|
|
5847
|
+
function classifyThinkingType(provider, modelId) {
|
|
5848
|
+
const id = modelId.toLowerCase();
|
|
5849
|
+
const prov = provider.toLowerCase();
|
|
5850
|
+
if (id.includes("-non-reasoning")) return "none";
|
|
5851
|
+
if (prov === "anthropic") return "none";
|
|
5852
|
+
if (prov === "gemini") {
|
|
5853
|
+
if (/gemini-(?:2\.5|3(?:\.\d+)?-(?:flash|pro)|flash-latest|pro-latest)/i.test(id)) return "gemini";
|
|
5854
|
+
return "none";
|
|
5855
|
+
}
|
|
5856
|
+
if (prov === "qwen" || /\bqwen|qwq/i.test(id)) return "qwen";
|
|
5857
|
+
if (/deepseek[_-]v([4-9]|\d{2,})/i.test(id) || /deepseek-ai\/deepseek-r1/i.test(id)) return "deepseek_v4";
|
|
5858
|
+
if (/deepseek[_-]chat|deepseek[_-]v3/i.test(id)) return "deepseek_hybrid";
|
|
5859
|
+
if (prov === "openai" || prov === "openai-compatible") {
|
|
5860
|
+
if (/gpt-5\.[2-9]|gpt-5\.[1-9]\d/.test(id)) return "gpt5_2plus";
|
|
5861
|
+
if (/gpt-5\.1/.test(id)) return "gpt5_1";
|
|
5862
|
+
if (/gpt-5/.test(id)) return "gpt5";
|
|
5863
|
+
if (/^o\d/.test(id)) return "o_series";
|
|
5864
|
+
}
|
|
5865
|
+
if (/^o\d/.test(id)) return "o_series";
|
|
5866
|
+
if (/\bgrok-(?:3-mini|4|4-fast|build)\b/i.test(id)) return "grok";
|
|
5867
|
+
if (/\bkimi-k(?:2-thinking|2\.[5-9]|[3-9])/i.test(id)) return "kimi";
|
|
5868
|
+
if (prov === "kimi" && /thinking/i.test(id)) return "kimi";
|
|
5869
|
+
if (/\bdoubao-.*seed/i.test(id) || prov === "doubao" && /seed/i.test(id)) return "doubao";
|
|
5870
|
+
if (/\bhunyuan-(?:t1|a13b)/i.test(id)) return "hunyuan";
|
|
5871
|
+
if (prov === "glm" || /\bglm-?(?:5|4\.[5-7]|z1|zero)/i.test(id)) return "qwen";
|
|
5872
|
+
if (prov === "siliconflow" && /r[1-9]/i.test(id)) return "deepseek_v4";
|
|
5873
|
+
if (prov === "openrouter") {
|
|
5874
|
+
if (/deepseek.*(v[4-9]|r\d)/i.test(id)) return "deepseek_v4";
|
|
5875
|
+
if (/deepseek[_-]?(chat|v3)/i.test(id)) return "deepseek_hybrid";
|
|
5876
|
+
if (/\bgrok-(?:3-mini|4|4-fast|build)\b/i.test(id)) return "grok";
|
|
5877
|
+
if (/\bkimi-k(?:2-thinking|2\.[5-9]|[3-9])/i.test(id)) return "kimi";
|
|
5878
|
+
if (REASONING_FALLBACK_REGEX.test(id)) return "default";
|
|
5879
|
+
return "none";
|
|
5880
|
+
}
|
|
5881
|
+
if (/\bmimo-v2/i.test(id)) return "deepseek_hybrid";
|
|
5882
|
+
if (/\bminimax-m[123]/i.test(id)) return "deepseek_hybrid";
|
|
5883
|
+
if (/\bseed-oss/i.test(id)) return "deepseek_hybrid";
|
|
5884
|
+
if (/\bbaichuan-m[23]/i.test(id)) return "default";
|
|
5885
|
+
if (/\bmagistral/i.test(id)) return "default";
|
|
5886
|
+
if (/\bmistral-small-2603/i.test(id)) return "default";
|
|
5887
|
+
if (/\bstep-(?:3|r1-v-mini)/i.test(id)) return "default";
|
|
5888
|
+
if (/\bgemma-?4/i.test(id)) return "default";
|
|
5889
|
+
if (/\bpangu-pro-moe/i.test(id)) return "default";
|
|
5890
|
+
if (/\bsonar-deep-research/i.test(id)) return "default";
|
|
5891
|
+
if (/\bring-(?:1t|mini|flash)/i.test(id)) return "default";
|
|
5892
|
+
if (/\bqwen|qwq/i.test(id)) return "qwen";
|
|
5893
|
+
if (/deepseek[_-]?r\d|deepseek[_-]?v[4-9]/i.test(id)) return "deepseek_v4";
|
|
5894
|
+
if (/^o\d/i.test(id)) return "o_series";
|
|
5895
|
+
if (REASONING_FALLBACK_REGEX.test(id)) return "default";
|
|
5896
|
+
return "none";
|
|
5897
|
+
}
|
|
5898
|
+
function isReasoningModel(provider, modelId) {
|
|
5899
|
+
return classifyThinkingType(provider, modelId) !== "none";
|
|
5900
|
+
}
|
|
5901
|
+
function getThinkingCompat(provider, modelId) {
|
|
5902
|
+
const type = classifyThinkingType(provider, modelId);
|
|
5903
|
+
if (type === "none") return {};
|
|
5904
|
+
if (type === "gemini") return {};
|
|
5905
|
+
if (type === "qwen" || type === "hunyuan") {
|
|
5906
|
+
return { thinkingFormat: "qwen" };
|
|
5907
|
+
}
|
|
5908
|
+
if (type === "deepseek_v4") {
|
|
5909
|
+
return {
|
|
5910
|
+
thinkingFormat: "deepseek",
|
|
5911
|
+
thinkingLevelMap: { high: "high", xhigh: "max", minimal: null, low: null, medium: null }
|
|
5912
|
+
};
|
|
5913
|
+
}
|
|
5914
|
+
if (type === "deepseek_hybrid") {
|
|
5915
|
+
return {
|
|
5916
|
+
thinkingFormat: "deepseek",
|
|
5917
|
+
thinkingLevelMap: { auto: "auto", high: "high", minimal: null, low: null, medium: null, xhigh: null }
|
|
5918
|
+
};
|
|
5919
|
+
}
|
|
5920
|
+
const compat = { supportsReasoningEffort: true };
|
|
5921
|
+
const levelMap = TYPE_LEVEL_MAP[type];
|
|
5922
|
+
if (levelMap) {
|
|
5923
|
+
compat.thinkingLevelMap = levelMap;
|
|
5924
|
+
}
|
|
5925
|
+
return compat;
|
|
5926
|
+
}
|
|
5927
|
+
|
|
5777
5928
|
// ../../packages/core/src/import/dedup.ts
|
|
5778
5929
|
function fnv1a64(input) {
|
|
5779
5930
|
let h0 = 2166136261;
|
|
@@ -11657,6 +11808,7 @@ var AIConversationManager = class {
|
|
|
11657
11808
|
id TEXT PRIMARY KEY,
|
|
11658
11809
|
session_id TEXT NOT NULL,
|
|
11659
11810
|
title TEXT,
|
|
11811
|
+
active_message_id TEXT,
|
|
11660
11812
|
created_at INTEGER NOT NULL,
|
|
11661
11813
|
updated_at INTEGER NOT NULL
|
|
11662
11814
|
);
|
|
@@ -11670,6 +11822,9 @@ var AIConversationManager = class {
|
|
|
11670
11822
|
data_keywords TEXT,
|
|
11671
11823
|
data_message_count INTEGER,
|
|
11672
11824
|
content_blocks TEXT,
|
|
11825
|
+
parent_id TEXT,
|
|
11826
|
+
sibling_group_id TEXT,
|
|
11827
|
+
branch_index INTEGER DEFAULT 0,
|
|
11673
11828
|
FOREIGN KEY(conversation_id) REFERENCES ai_conversation(id) ON DELETE CASCADE
|
|
11674
11829
|
);
|
|
11675
11830
|
|
|
@@ -11683,6 +11838,7 @@ var AIConversationManager = class {
|
|
|
11683
11838
|
try {
|
|
11684
11839
|
const messageTableInfo = db.pragma("table_info(ai_message)");
|
|
11685
11840
|
const messageColumns = messageTableInfo.map((col) => col.name);
|
|
11841
|
+
const needsMessageTreeBackfill = !messageColumns.includes("parent_id") || !messageColumns.includes("sibling_group_id") || !messageColumns.includes("branch_index");
|
|
11686
11842
|
if (!messageColumns.includes("content_blocks")) {
|
|
11687
11843
|
db.exec("ALTER TABLE ai_message ADD COLUMN content_blocks TEXT");
|
|
11688
11844
|
}
|
|
@@ -11692,18 +11848,149 @@ var AIConversationManager = class {
|
|
|
11692
11848
|
if (!messageColumns.includes("debug_context")) {
|
|
11693
11849
|
db.exec("ALTER TABLE ai_message ADD COLUMN debug_context TEXT");
|
|
11694
11850
|
}
|
|
11851
|
+
if (!messageColumns.includes("parent_id")) {
|
|
11852
|
+
db.exec("ALTER TABLE ai_message ADD COLUMN parent_id TEXT");
|
|
11853
|
+
}
|
|
11854
|
+
if (!messageColumns.includes("sibling_group_id")) {
|
|
11855
|
+
db.exec("ALTER TABLE ai_message ADD COLUMN sibling_group_id TEXT");
|
|
11856
|
+
}
|
|
11857
|
+
if (!messageColumns.includes("branch_index")) {
|
|
11858
|
+
db.exec("ALTER TABLE ai_message ADD COLUMN branch_index INTEGER DEFAULT 0");
|
|
11859
|
+
}
|
|
11695
11860
|
const convTableInfo = db.pragma("table_info(ai_conversation)");
|
|
11696
11861
|
const convColumns = convTableInfo.map((col) => col.name);
|
|
11862
|
+
const needsConversationBackfill = !convColumns.includes("active_message_id");
|
|
11697
11863
|
if (!convColumns.includes("assistant_id")) {
|
|
11698
11864
|
db.exec(`ALTER TABLE ai_conversation ADD COLUMN assistant_id TEXT DEFAULT '${DEFAULT_GENERAL_ID}'`);
|
|
11699
11865
|
}
|
|
11866
|
+
if (!convColumns.includes("active_message_id")) {
|
|
11867
|
+
db.exec("ALTER TABLE ai_conversation ADD COLUMN active_message_id TEXT");
|
|
11868
|
+
}
|
|
11869
|
+
if (needsMessageTreeBackfill || needsConversationBackfill || this.hasUnbackfilledMessageTree(db)) {
|
|
11870
|
+
this.backfillMessageTree(db);
|
|
11871
|
+
}
|
|
11872
|
+
db.exec(`
|
|
11873
|
+
CREATE INDEX IF NOT EXISTS idx_ai_message_parent ON ai_message(parent_id);
|
|
11874
|
+
CREATE INDEX IF NOT EXISTS idx_ai_message_sibling ON ai_message(sibling_group_id);
|
|
11875
|
+
`);
|
|
11700
11876
|
} catch (error) {
|
|
11701
11877
|
console.error("[AI DB Migration] Migration failed:", error);
|
|
11702
11878
|
}
|
|
11703
11879
|
}
|
|
11880
|
+
hasUnbackfilledMessageTree(db) {
|
|
11881
|
+
const row = db.prepare(
|
|
11882
|
+
`SELECT 1
|
|
11883
|
+
FROM ai_conversation c
|
|
11884
|
+
WHERE EXISTS (
|
|
11885
|
+
SELECT 1 FROM ai_message m
|
|
11886
|
+
WHERE m.conversation_id = c.id
|
|
11887
|
+
)
|
|
11888
|
+
AND (
|
|
11889
|
+
c.active_message_id IS NULL
|
|
11890
|
+
OR EXISTS (
|
|
11891
|
+
SELECT 1 FROM ai_message m
|
|
11892
|
+
WHERE m.conversation_id = c.id
|
|
11893
|
+
AND (m.sibling_group_id IS NULL OR m.branch_index IS NULL)
|
|
11894
|
+
)
|
|
11895
|
+
)
|
|
11896
|
+
LIMIT 1`
|
|
11897
|
+
).get();
|
|
11898
|
+
return !!row;
|
|
11899
|
+
}
|
|
11900
|
+
backfillMessageTree(db) {
|
|
11901
|
+
const conversations = db.prepare("SELECT id FROM ai_conversation").all();
|
|
11902
|
+
const updateMessage = db.prepare(
|
|
11903
|
+
"UPDATE ai_message SET parent_id = ?, sibling_group_id = COALESCE(sibling_group_id, ?), branch_index = COALESCE(branch_index, 0) WHERE id = ?"
|
|
11904
|
+
);
|
|
11905
|
+
const updateConversation = db.prepare("UPDATE ai_conversation SET active_message_id = ? WHERE id = ?");
|
|
11906
|
+
const tx = db.transaction(() => {
|
|
11907
|
+
for (const conversation of conversations) {
|
|
11908
|
+
const messages = db.prepare(
|
|
11909
|
+
`SELECT id, parent_id as parentId, sibling_group_id as siblingGroupId
|
|
11910
|
+
FROM ai_message WHERE conversation_id = ? ORDER BY timestamp ASC, id ASC`
|
|
11911
|
+
).all(conversation.id);
|
|
11912
|
+
let previousId = null;
|
|
11913
|
+
for (const message of messages) {
|
|
11914
|
+
const parentId = message.parentId === void 0 ? previousId : message.parentId ?? previousId;
|
|
11915
|
+
updateMessage.run(parentId, message.siblingGroupId ?? message.id, message.id);
|
|
11916
|
+
previousId = message.id;
|
|
11917
|
+
}
|
|
11918
|
+
const conversationRow = db.prepare("SELECT active_message_id as activeMessageId FROM ai_conversation WHERE id = ?").get(conversation.id);
|
|
11919
|
+
if (!conversationRow?.activeMessageId && previousId) {
|
|
11920
|
+
updateConversation.run(previousId, conversation.id);
|
|
11921
|
+
}
|
|
11922
|
+
}
|
|
11923
|
+
});
|
|
11924
|
+
tx();
|
|
11925
|
+
}
|
|
11704
11926
|
generateId(prefix) {
|
|
11705
11927
|
return `${prefix}_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
11706
11928
|
}
|
|
11929
|
+
parseMessageRow(row) {
|
|
11930
|
+
return {
|
|
11931
|
+
id: row.id,
|
|
11932
|
+
conversationId: row.conversationId,
|
|
11933
|
+
role: row.role,
|
|
11934
|
+
content: row.content,
|
|
11935
|
+
timestamp: row.timestamp,
|
|
11936
|
+
parentId: row.parentId ?? null,
|
|
11937
|
+
dataKeywords: row.dataKeywords ? JSON.parse(row.dataKeywords) : void 0,
|
|
11938
|
+
dataMessageCount: row.dataMessageCount ?? void 0,
|
|
11939
|
+
contentBlocks: row.contentBlocks ? JSON.parse(row.contentBlocks) : void 0,
|
|
11940
|
+
tokenUsage: row.tokenUsage ? JSON.parse(row.tokenUsage) : void 0
|
|
11941
|
+
};
|
|
11942
|
+
}
|
|
11943
|
+
getMessageRow(messageId) {
|
|
11944
|
+
const db = this.getDb();
|
|
11945
|
+
const row = db.prepare(
|
|
11946
|
+
`SELECT id, conversation_id as conversationId, role, content, timestamp,
|
|
11947
|
+
parent_id as parentId, sibling_group_id as siblingGroupId, branch_index as branchIndex,
|
|
11948
|
+
data_keywords as dataKeywords, data_message_count as dataMessageCount,
|
|
11949
|
+
content_blocks as contentBlocks, token_usage as tokenUsage
|
|
11950
|
+
FROM ai_message WHERE id = ?`
|
|
11951
|
+
).get(messageId);
|
|
11952
|
+
return row ?? null;
|
|
11953
|
+
}
|
|
11954
|
+
getActiveMessageId(conversationId) {
|
|
11955
|
+
const db = this.getDb();
|
|
11956
|
+
const row = db.prepare("SELECT active_message_id as activeMessageId FROM ai_conversation WHERE id = ?").get(conversationId);
|
|
11957
|
+
if (row?.activeMessageId) {
|
|
11958
|
+
const activeExists = db.prepare("SELECT 1 FROM ai_message WHERE id = ?").get(row.activeMessageId);
|
|
11959
|
+
if (activeExists) return row.activeMessageId;
|
|
11960
|
+
}
|
|
11961
|
+
const fallback = db.prepare("SELECT id FROM ai_message WHERE conversation_id = ? ORDER BY timestamp DESC, id DESC LIMIT 1").get(conversationId);
|
|
11962
|
+
if (fallback?.id) {
|
|
11963
|
+
db.prepare("UPDATE ai_conversation SET active_message_id = ? WHERE id = ?").run(fallback.id, conversationId);
|
|
11964
|
+
return fallback.id;
|
|
11965
|
+
}
|
|
11966
|
+
return null;
|
|
11967
|
+
}
|
|
11968
|
+
getAllMessageRows(conversationId) {
|
|
11969
|
+
return this.getDb().prepare(
|
|
11970
|
+
`SELECT id, conversation_id as conversationId, role, content, timestamp,
|
|
11971
|
+
parent_id as parentId, sibling_group_id as siblingGroupId, branch_index as branchIndex,
|
|
11972
|
+
data_keywords as dataKeywords, data_message_count as dataMessageCount,
|
|
11973
|
+
content_blocks as contentBlocks, token_usage as tokenUsage
|
|
11974
|
+
FROM ai_message WHERE conversation_id = ? ORDER BY timestamp ASC, id ASC`
|
|
11975
|
+
).all(conversationId);
|
|
11976
|
+
}
|
|
11977
|
+
getActivePathRows(conversationId, leafMessageId) {
|
|
11978
|
+
if (leafMessageId === null) return [];
|
|
11979
|
+
const allRows = this.getAllMessageRows(conversationId);
|
|
11980
|
+
if (allRows.length === 0) return [];
|
|
11981
|
+
const rowMap = new Map(allRows.map((row) => [row.id, row]));
|
|
11982
|
+
let currentId = leafMessageId ?? this.getActiveMessageId(conversationId);
|
|
11983
|
+
const path37 = [];
|
|
11984
|
+
const seen = /* @__PURE__ */ new Set();
|
|
11985
|
+
while (currentId && !seen.has(currentId)) {
|
|
11986
|
+
seen.add(currentId);
|
|
11987
|
+
const row = rowMap.get(currentId);
|
|
11988
|
+
if (!row) break;
|
|
11989
|
+
path37.push(row);
|
|
11990
|
+
currentId = row.parentId;
|
|
11991
|
+
}
|
|
11992
|
+
return path37.length > 0 ? path37.reverse() : allRows;
|
|
11993
|
+
}
|
|
11707
11994
|
// ==================== 生命周期 ====================
|
|
11708
11995
|
close() {
|
|
11709
11996
|
if (this.db) {
|
|
@@ -11766,7 +12053,7 @@ var AIConversationManager = class {
|
|
|
11766
12053
|
`INSERT INTO ai_conversation (id, session_id, title, assistant_id, created_at, updated_at)
|
|
11767
12054
|
VALUES (?, ?, ?, ?, ?, ?)`
|
|
11768
12055
|
).run(id, sessionId, title || null, assistantId, now, now);
|
|
11769
|
-
return { id, sessionId, title: title || null, assistantId, createdAt: now, updatedAt: now };
|
|
12056
|
+
return { id, sessionId, title: title || null, assistantId, activeMessageId: null, createdAt: now, updatedAt: now };
|
|
11770
12057
|
}
|
|
11771
12058
|
getConversationCountsBySession() {
|
|
11772
12059
|
const result = /* @__PURE__ */ new Map();
|
|
@@ -11784,6 +12071,7 @@ var AIConversationManager = class {
|
|
|
11784
12071
|
const db = this.getDb();
|
|
11785
12072
|
return db.prepare(
|
|
11786
12073
|
`SELECT id, session_id as sessionId, title, assistant_id as assistantId,
|
|
12074
|
+
active_message_id as activeMessageId,
|
|
11787
12075
|
created_at as createdAt, updated_at as updatedAt
|
|
11788
12076
|
FROM ai_conversation WHERE session_id = ? ORDER BY updated_at DESC`
|
|
11789
12077
|
).all(sessionId);
|
|
@@ -11792,6 +12080,7 @@ var AIConversationManager = class {
|
|
|
11792
12080
|
const db = this.getDb();
|
|
11793
12081
|
const row = db.prepare(
|
|
11794
12082
|
`SELECT id, session_id as sessionId, title, assistant_id as assistantId,
|
|
12083
|
+
active_message_id as activeMessageId,
|
|
11795
12084
|
created_at as createdAt, updated_at as updatedAt
|
|
11796
12085
|
FROM ai_conversation WHERE id = ?`
|
|
11797
12086
|
).get(conversationId);
|
|
@@ -11814,13 +12103,19 @@ var AIConversationManager = class {
|
|
|
11814
12103
|
const db = this.getDb();
|
|
11815
12104
|
const now = Math.floor(Date.now() / 1e3);
|
|
11816
12105
|
const id = this.generateId("msg");
|
|
12106
|
+
const parentId = this.getActiveMessageId(conversationId);
|
|
12107
|
+
const siblingGroupId = id;
|
|
12108
|
+
const branchIndex = 0;
|
|
11817
12109
|
const pendingDebug = role === "assistant" ? this.pendingDebugContextMap.get(conversationId) : void 0;
|
|
11818
12110
|
if (pendingDebug) {
|
|
11819
12111
|
this.pendingDebugContextMap.delete(conversationId);
|
|
11820
12112
|
}
|
|
11821
12113
|
db.prepare(
|
|
11822
|
-
`INSERT INTO ai_message (
|
|
11823
|
-
|
|
12114
|
+
`INSERT INTO ai_message (
|
|
12115
|
+
id, conversation_id, role, content, timestamp, data_keywords, data_message_count,
|
|
12116
|
+
content_blocks, token_usage, debug_context, parent_id, sibling_group_id, branch_index
|
|
12117
|
+
)
|
|
12118
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
11824
12119
|
).run(
|
|
11825
12120
|
id,
|
|
11826
12121
|
conversationId,
|
|
@@ -11831,15 +12126,23 @@ var AIConversationManager = class {
|
|
|
11831
12126
|
dataMessageCount ?? null,
|
|
11832
12127
|
contentBlocks ? JSON.stringify(contentBlocks) : null,
|
|
11833
12128
|
tokenUsage ? JSON.stringify(tokenUsage) : null,
|
|
11834
|
-
pendingDebug ?? null
|
|
12129
|
+
pendingDebug ?? null,
|
|
12130
|
+
parentId,
|
|
12131
|
+
siblingGroupId,
|
|
12132
|
+
branchIndex
|
|
12133
|
+
);
|
|
12134
|
+
db.prepare("UPDATE ai_conversation SET active_message_id = ?, updated_at = ? WHERE id = ?").run(
|
|
12135
|
+
id,
|
|
12136
|
+
now,
|
|
12137
|
+
conversationId
|
|
11835
12138
|
);
|
|
11836
|
-
db.prepare("UPDATE ai_conversation SET updated_at = ? WHERE id = ?").run(now, conversationId);
|
|
11837
12139
|
return {
|
|
11838
12140
|
id,
|
|
11839
12141
|
conversationId,
|
|
11840
12142
|
role,
|
|
11841
12143
|
content,
|
|
11842
12144
|
timestamp: now,
|
|
12145
|
+
parentId,
|
|
11843
12146
|
dataKeywords,
|
|
11844
12147
|
dataMessageCount,
|
|
11845
12148
|
contentBlocks,
|
|
@@ -11847,40 +12150,181 @@ var AIConversationManager = class {
|
|
|
11847
12150
|
};
|
|
11848
12151
|
}
|
|
11849
12152
|
getMessages(conversationId) {
|
|
11850
|
-
|
|
11851
|
-
const rows = db.prepare(
|
|
11852
|
-
`SELECT id, conversation_id as conversationId, role, content, timestamp,
|
|
11853
|
-
data_keywords as dataKeywords, data_message_count as dataMessageCount,
|
|
11854
|
-
content_blocks as contentBlocks, token_usage as tokenUsage
|
|
11855
|
-
FROM ai_message WHERE conversation_id = ? ORDER BY timestamp ASC`
|
|
11856
|
-
).all(conversationId);
|
|
11857
|
-
return rows.map((row) => ({
|
|
11858
|
-
id: row.id,
|
|
11859
|
-
conversationId: row.conversationId,
|
|
11860
|
-
role: row.role,
|
|
11861
|
-
content: row.content,
|
|
11862
|
-
timestamp: row.timestamp,
|
|
11863
|
-
dataKeywords: row.dataKeywords ? JSON.parse(row.dataKeywords) : void 0,
|
|
11864
|
-
dataMessageCount: row.dataMessageCount ?? void 0,
|
|
11865
|
-
contentBlocks: row.contentBlocks ? JSON.parse(row.contentBlocks) : void 0,
|
|
11866
|
-
tokenUsage: row.tokenUsage ? JSON.parse(row.tokenUsage) : void 0
|
|
11867
|
-
}));
|
|
12153
|
+
return this.getActivePathRows(conversationId).map((row) => this.parseMessageRow(row));
|
|
11868
12154
|
}
|
|
11869
12155
|
deleteMessage(messageId) {
|
|
11870
12156
|
const db = this.getDb();
|
|
11871
12157
|
const result = db.prepare("DELETE FROM ai_message WHERE id = ?").run(messageId);
|
|
11872
12158
|
return result.changes > 0;
|
|
11873
12159
|
}
|
|
11874
|
-
|
|
12160
|
+
deleteMessagesFrom(conversationId, messageId) {
|
|
11875
12161
|
const db = this.getDb();
|
|
11876
|
-
const
|
|
11877
|
-
|
|
11878
|
-
|
|
11879
|
-
|
|
11880
|
-
|
|
11881
|
-
|
|
11882
|
-
|
|
11883
|
-
|
|
12162
|
+
const target = this.getMessageRow(messageId);
|
|
12163
|
+
if (!target || target.conversationId !== conversationId) {
|
|
12164
|
+
throw new Error("Message not found in conversation");
|
|
12165
|
+
}
|
|
12166
|
+
const activePath = this.getActivePathRows(conversationId);
|
|
12167
|
+
const targetIndex = activePath.findIndex((row) => row.id === messageId);
|
|
12168
|
+
if (targetIndex < 0) {
|
|
12169
|
+
throw new Error("Message not on active path");
|
|
12170
|
+
}
|
|
12171
|
+
const idsToDelete = activePath.slice(targetIndex).map((row) => row.id);
|
|
12172
|
+
const placeholders = idsToDelete.map(() => "?").join(", ");
|
|
12173
|
+
db.prepare(`DELETE FROM ai_message WHERE id IN (${placeholders})`).run(...idsToDelete);
|
|
12174
|
+
const newLeafId = targetIndex > 0 ? activePath[targetIndex - 1].id : null;
|
|
12175
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
12176
|
+
db.prepare("UPDATE ai_conversation SET active_message_id = ?, updated_at = ? WHERE id = ?").run(
|
|
12177
|
+
newLeafId,
|
|
12178
|
+
now,
|
|
12179
|
+
conversationId
|
|
12180
|
+
);
|
|
12181
|
+
}
|
|
12182
|
+
forkConversation(sourceConversationId, upToMessageId, title) {
|
|
12183
|
+
const db = this.getDb();
|
|
12184
|
+
const source = this.getConversation(sourceConversationId);
|
|
12185
|
+
if (!source) {
|
|
12186
|
+
throw new Error("Source conversation not found");
|
|
12187
|
+
}
|
|
12188
|
+
const activePath = this.getActivePathRows(sourceConversationId);
|
|
12189
|
+
const cutIndex = activePath.findIndex((row) => row.id === upToMessageId);
|
|
12190
|
+
if (cutIndex < 0) {
|
|
12191
|
+
throw new Error("Message not on active path");
|
|
12192
|
+
}
|
|
12193
|
+
const messagesToCopy = activePath.slice(0, cutIndex + 1);
|
|
12194
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
12195
|
+
const newConvId = this.generateId("conv");
|
|
12196
|
+
const forkTitle = title || `${source.title || "Untitled"} (fork)`;
|
|
12197
|
+
db.prepare(
|
|
12198
|
+
`INSERT INTO ai_conversation (id, session_id, title, assistant_id, active_message_id, created_at, updated_at)
|
|
12199
|
+
VALUES (?, ?, ?, ?, NULL, ?, ?)`
|
|
12200
|
+
).run(newConvId, source.sessionId, forkTitle, source.assistantId, now, now);
|
|
12201
|
+
const idMap = /* @__PURE__ */ new Map();
|
|
12202
|
+
let lastNewId = null;
|
|
12203
|
+
for (const row of messagesToCopy) {
|
|
12204
|
+
const newMsgId = this.generateId("msg");
|
|
12205
|
+
idMap.set(row.id, newMsgId);
|
|
12206
|
+
const newParentId = row.parentId ? idMap.get(row.parentId) ?? null : null;
|
|
12207
|
+
db.prepare(
|
|
12208
|
+
`INSERT INTO ai_message (
|
|
12209
|
+
id, conversation_id, role, content, timestamp, data_keywords, data_message_count,
|
|
12210
|
+
content_blocks, token_usage, debug_context, parent_id, sibling_group_id, branch_index
|
|
12211
|
+
)
|
|
12212
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, 0)`
|
|
12213
|
+
).run(
|
|
12214
|
+
newMsgId,
|
|
12215
|
+
newConvId,
|
|
12216
|
+
row.role,
|
|
12217
|
+
row.content,
|
|
12218
|
+
row.timestamp,
|
|
12219
|
+
row.dataKeywords,
|
|
12220
|
+
row.dataMessageCount,
|
|
12221
|
+
row.contentBlocks,
|
|
12222
|
+
row.tokenUsage,
|
|
12223
|
+
newParentId,
|
|
12224
|
+
newMsgId
|
|
12225
|
+
);
|
|
12226
|
+
lastNewId = newMsgId;
|
|
12227
|
+
}
|
|
12228
|
+
if (lastNewId) {
|
|
12229
|
+
db.prepare("UPDATE ai_conversation SET active_message_id = ? WHERE id = ?").run(lastNewId, newConvId);
|
|
12230
|
+
}
|
|
12231
|
+
return {
|
|
12232
|
+
id: newConvId,
|
|
12233
|
+
sessionId: source.sessionId,
|
|
12234
|
+
title: forkTitle,
|
|
12235
|
+
assistantId: source.assistantId,
|
|
12236
|
+
activeMessageId: lastNewId,
|
|
12237
|
+
createdAt: now,
|
|
12238
|
+
updatedAt: now
|
|
12239
|
+
};
|
|
12240
|
+
}
|
|
12241
|
+
updateMessageContent(messageId, newContent) {
|
|
12242
|
+
const db = this.getDb();
|
|
12243
|
+
const result = db.prepare("UPDATE ai_message SET content = ? WHERE id = ?").run(newContent, messageId);
|
|
12244
|
+
if (result.changes === 0) throw new Error("Message not found");
|
|
12245
|
+
}
|
|
12246
|
+
deleteAndRelinkMessage(conversationId, messageId) {
|
|
12247
|
+
const db = this.getDb();
|
|
12248
|
+
const target = this.getMessageRow(messageId);
|
|
12249
|
+
if (!target || target.conversationId !== conversationId) {
|
|
12250
|
+
throw new Error("Message not found in conversation");
|
|
12251
|
+
}
|
|
12252
|
+
db.prepare("UPDATE ai_message SET parent_id = ? WHERE parent_id = ? AND conversation_id = ?").run(
|
|
12253
|
+
target.parentId,
|
|
12254
|
+
messageId,
|
|
12255
|
+
conversationId
|
|
12256
|
+
);
|
|
12257
|
+
const conv = this.getConversation(conversationId);
|
|
12258
|
+
if (conv?.activeMessageId === messageId) {
|
|
12259
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
12260
|
+
db.prepare("UPDATE ai_conversation SET active_message_id = ?, updated_at = ? WHERE id = ?").run(
|
|
12261
|
+
target.parentId,
|
|
12262
|
+
now,
|
|
12263
|
+
conversationId
|
|
12264
|
+
);
|
|
12265
|
+
}
|
|
12266
|
+
db.prepare("DELETE FROM ai_message WHERE id = ?").run(messageId);
|
|
12267
|
+
}
|
|
12268
|
+
insertMessageAfter(conversationId, afterMessageId, role, content, contentBlocks, tokenUsage) {
|
|
12269
|
+
const db = this.getDb();
|
|
12270
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
12271
|
+
const id = this.generateId("msg");
|
|
12272
|
+
const pendingDebug = role === "assistant" ? this.pendingDebugContextMap.get(conversationId) : void 0;
|
|
12273
|
+
if (pendingDebug) {
|
|
12274
|
+
this.pendingDebugContextMap.delete(conversationId);
|
|
12275
|
+
}
|
|
12276
|
+
const childRow = db.prepare("SELECT id FROM ai_message WHERE parent_id = ? AND conversation_id = ? LIMIT 1").get(afterMessageId, conversationId);
|
|
12277
|
+
db.prepare(
|
|
12278
|
+
`INSERT INTO ai_message (
|
|
12279
|
+
id, conversation_id, role, content, timestamp, data_keywords, data_message_count,
|
|
12280
|
+
content_blocks, token_usage, debug_context, parent_id, sibling_group_id, branch_index
|
|
12281
|
+
)
|
|
12282
|
+
VALUES (?, ?, ?, ?, ?, NULL, NULL, ?, ?, ?, ?, ?, 0)`
|
|
12283
|
+
).run(
|
|
12284
|
+
id,
|
|
12285
|
+
conversationId,
|
|
12286
|
+
role,
|
|
12287
|
+
content,
|
|
12288
|
+
now,
|
|
12289
|
+
contentBlocks ? JSON.stringify(contentBlocks) : null,
|
|
12290
|
+
tokenUsage ? JSON.stringify(tokenUsage) : null,
|
|
12291
|
+
pendingDebug ?? null,
|
|
12292
|
+
afterMessageId,
|
|
12293
|
+
id
|
|
12294
|
+
);
|
|
12295
|
+
if (childRow) {
|
|
12296
|
+
db.prepare("UPDATE ai_message SET parent_id = ? WHERE id = ?").run(id, childRow.id);
|
|
12297
|
+
db.prepare("UPDATE ai_conversation SET updated_at = ? WHERE id = ?").run(now, conversationId);
|
|
12298
|
+
} else {
|
|
12299
|
+
db.prepare("UPDATE ai_conversation SET active_message_id = ?, updated_at = ? WHERE id = ?").run(
|
|
12300
|
+
id,
|
|
12301
|
+
now,
|
|
12302
|
+
conversationId
|
|
12303
|
+
);
|
|
12304
|
+
}
|
|
12305
|
+
return {
|
|
12306
|
+
id,
|
|
12307
|
+
conversationId,
|
|
12308
|
+
role,
|
|
12309
|
+
content,
|
|
12310
|
+
timestamp: now,
|
|
12311
|
+
parentId: afterMessageId,
|
|
12312
|
+
contentBlocks,
|
|
12313
|
+
tokenUsage
|
|
12314
|
+
};
|
|
12315
|
+
}
|
|
12316
|
+
getConversationTokenUsage(conversationId) {
|
|
12317
|
+
const rows = this.getActivePathRows(conversationId);
|
|
12318
|
+
const result = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
|
|
12319
|
+
for (const row of rows) {
|
|
12320
|
+
if (row.tokenUsage) {
|
|
12321
|
+
const usage = JSON.parse(row.tokenUsage);
|
|
12322
|
+
result.promptTokens += usage.promptTokens;
|
|
12323
|
+
result.completionTokens += usage.completionTokens;
|
|
12324
|
+
result.totalTokens += usage.totalTokens;
|
|
12325
|
+
}
|
|
12326
|
+
}
|
|
12327
|
+
return result;
|
|
11884
12328
|
}
|
|
11885
12329
|
// ==================== Debug context ====================
|
|
11886
12330
|
setPendingDebugContext(conversationId, debugContext) {
|
|
@@ -11896,8 +12340,8 @@ var AIConversationManager = class {
|
|
|
11896
12340
|
return result.changes;
|
|
11897
12341
|
}
|
|
11898
12342
|
// ==================== Agent 专用 ====================
|
|
11899
|
-
getHistoryForAgent(conversationId, maxMessages) {
|
|
11900
|
-
const messages = this.
|
|
12343
|
+
getHistoryForAgent(conversationId, maxMessages, leafMessageId) {
|
|
12344
|
+
const messages = this.getActivePathRows(conversationId, leafMessageId).map((row) => this.parseMessageRow(row));
|
|
11901
12345
|
const validMessages = messages.filter(
|
|
11902
12346
|
(m) => (m.role === "user" || m.role === "assistant" || m.role === "summary") && m.content?.trim()
|
|
11903
12347
|
);
|
|
@@ -11940,8 +12384,6 @@ var AIConversationManager = class {
|
|
|
11940
12384
|
}
|
|
11941
12385
|
// ==================== Summary / 压缩专用 ====================
|
|
11942
12386
|
addSummaryMessage(conversationId, content, meta) {
|
|
11943
|
-
const db = this.getDb();
|
|
11944
|
-
db.prepare("DELETE FROM ai_message WHERE conversation_id = ? AND role = 'summary'").run(conversationId);
|
|
11945
12387
|
const contentBlocks = [
|
|
11946
12388
|
{
|
|
11947
12389
|
type: "summary_meta",
|
|
@@ -11952,60 +12394,27 @@ var AIConversationManager = class {
|
|
|
11952
12394
|
return this.addMessage(conversationId, "summary", content, void 0, void 0, contentBlocks);
|
|
11953
12395
|
}
|
|
11954
12396
|
getLatestSummary(conversationId) {
|
|
11955
|
-
const
|
|
11956
|
-
|
|
11957
|
-
`SELECT id, conversation_id as conversationId, role, content, timestamp,
|
|
11958
|
-
data_keywords as dataKeywords, data_message_count as dataMessageCount,
|
|
11959
|
-
content_blocks as contentBlocks
|
|
11960
|
-
FROM ai_message WHERE conversation_id = ? AND role = 'summary'
|
|
11961
|
-
ORDER BY timestamp DESC LIMIT 1`
|
|
11962
|
-
).get(conversationId);
|
|
11963
|
-
if (!row) return null;
|
|
11964
|
-
return {
|
|
11965
|
-
id: row.id,
|
|
11966
|
-
conversationId: row.conversationId,
|
|
11967
|
-
role: row.role,
|
|
11968
|
-
content: row.content,
|
|
11969
|
-
timestamp: row.timestamp,
|
|
11970
|
-
dataKeywords: row.dataKeywords ? JSON.parse(row.dataKeywords) : void 0,
|
|
11971
|
-
dataMessageCount: row.dataMessageCount ?? void 0,
|
|
11972
|
-
contentBlocks: row.contentBlocks ? JSON.parse(row.contentBlocks) : void 0
|
|
11973
|
-
};
|
|
12397
|
+
const row = [...this.getActivePathRows(conversationId)].reverse().find((message) => message.role === "summary");
|
|
12398
|
+
return row ? this.parseMessageRow(row) : null;
|
|
11974
12399
|
}
|
|
11975
12400
|
getMessagesAfterSummary(conversationId, summaryTimestamp) {
|
|
11976
|
-
|
|
11977
|
-
const rows = db.prepare(
|
|
11978
|
-
`SELECT role, content, timestamp FROM ai_message
|
|
11979
|
-
WHERE conversation_id = ? AND timestamp > ? AND role IN ('user', 'assistant')
|
|
11980
|
-
ORDER BY timestamp ASC`
|
|
11981
|
-
).all(conversationId, summaryTimestamp);
|
|
11982
|
-
return rows.map((r) => ({ role: r.role, content: r.content, timestamp: r.timestamp }));
|
|
12401
|
+
return this.getActivePathRows(conversationId).filter((row) => row.timestamp > summaryTimestamp && (row.role === "user" || row.role === "assistant")).map((row) => ({ role: row.role, content: row.content, timestamp: row.timestamp }));
|
|
11983
12402
|
}
|
|
11984
12403
|
getAllUserAssistantMessages(conversationId) {
|
|
11985
|
-
|
|
11986
|
-
const rows = db.prepare(
|
|
11987
|
-
`SELECT role, content, timestamp FROM ai_message
|
|
11988
|
-
WHERE conversation_id = ? AND role IN ('user', 'assistant')
|
|
11989
|
-
ORDER BY timestamp ASC`
|
|
11990
|
-
).all(conversationId);
|
|
11991
|
-
return rows.map((r) => ({ role: r.role, content: r.content, timestamp: r.timestamp }));
|
|
12404
|
+
return this.getActivePathRows(conversationId).filter((row) => row.role === "user" || row.role === "assistant").map((row) => ({ role: row.role, content: row.content, timestamp: row.timestamp }));
|
|
11992
12405
|
}
|
|
11993
12406
|
getMessageCountAfterSummary(conversationId) {
|
|
11994
12407
|
const summary = this.getLatestSummary(conversationId);
|
|
11995
12408
|
if (!summary) {
|
|
11996
|
-
|
|
11997
|
-
const row2 = db2.prepare("SELECT COUNT(*) as count FROM ai_message WHERE conversation_id = ? AND role IN ('user', 'assistant')").get(conversationId);
|
|
11998
|
-
return row2.count;
|
|
12409
|
+
return this.getActivePathRows(conversationId).filter((row) => row.role === "user" || row.role === "assistant").length;
|
|
11999
12410
|
}
|
|
12000
12411
|
const metaBlock = summary.contentBlocks?.find(
|
|
12001
12412
|
(b) => b.type === "summary_meta"
|
|
12002
12413
|
);
|
|
12003
12414
|
const boundary = metaBlock?.bufferBoundaryTimestamp ?? summary.timestamp;
|
|
12004
|
-
|
|
12005
|
-
|
|
12006
|
-
|
|
12007
|
-
).get(conversationId, boundary);
|
|
12008
|
-
return row.count;
|
|
12415
|
+
return this.getActivePathRows(conversationId).filter(
|
|
12416
|
+
(row) => row.timestamp >= boundary && (row.role === "user" || row.role === "assistant")
|
|
12417
|
+
).length;
|
|
12009
12418
|
}
|
|
12010
12419
|
};
|
|
12011
12420
|
|
|
@@ -13177,7 +13586,8 @@ function applyPreprocessingPipeline(options) {
|
|
|
13177
13586
|
// ../../packages/node-runtime/src/ai/agent/core.ts
|
|
13178
13587
|
import { Agent as PiAgentCore } from "@earendil-works/pi-agent-core";
|
|
13179
13588
|
import {
|
|
13180
|
-
streamSimple as defaultStreamSimple
|
|
13589
|
+
streamSimple as defaultStreamSimple,
|
|
13590
|
+
clampThinkingLevel
|
|
13181
13591
|
} from "@earendil-works/pi-ai";
|
|
13182
13592
|
function createEmptyPiUsage() {
|
|
13183
13593
|
return {
|
|
@@ -13241,11 +13651,34 @@ async function runAgentCore(options) {
|
|
|
13241
13651
|
if (abortSignal?.aborted) {
|
|
13242
13652
|
return { usage: totalUsage, finalMessages: [], toolsUsed: [], toolRounds: 0 };
|
|
13243
13653
|
}
|
|
13654
|
+
const isDefault = !options.thinkingLevel || options.thinkingLevel === "default";
|
|
13655
|
+
const effectiveModel = isDefault ? { ...piModel, reasoning: false, compat: void 0, thinkingLevelMap: void 0 } : piModel;
|
|
13656
|
+
const resolvedThinkingLevel = (() => {
|
|
13657
|
+
if (isDefault) return "off";
|
|
13658
|
+
const level = options.thinkingLevel;
|
|
13659
|
+
if (level === "auto") {
|
|
13660
|
+
if (!piModel.reasoning) return "off";
|
|
13661
|
+
const compat = piModel.compat;
|
|
13662
|
+
if (compat?.thinkingFormat) return "high";
|
|
13663
|
+
if (piModel.thinkingLevelMap) return "high";
|
|
13664
|
+
return void 0;
|
|
13665
|
+
}
|
|
13666
|
+
return clampThinkingLevel(piModel, level);
|
|
13667
|
+
})();
|
|
13668
|
+
const finalThinkingLevel = resolvedThinkingLevel ?? (piModel.reasoning ? void 0 : "off");
|
|
13669
|
+
console.debug("[agent-core] thinkingLevel resolution:", {
|
|
13670
|
+
input: options.thinkingLevel,
|
|
13671
|
+
modelId: piModel.id,
|
|
13672
|
+
modelReasoning: effectiveModel.reasoning,
|
|
13673
|
+
isDefault,
|
|
13674
|
+
resolved: resolvedThinkingLevel,
|
|
13675
|
+
final: finalThinkingLevel
|
|
13676
|
+
});
|
|
13244
13677
|
const coreAgent = new PiAgentCore({
|
|
13245
13678
|
initialState: {
|
|
13246
13679
|
systemPrompt,
|
|
13247
|
-
model:
|
|
13248
|
-
thinkingLevel:
|
|
13680
|
+
model: effectiveModel,
|
|
13681
|
+
thinkingLevel: finalThinkingLevel,
|
|
13249
13682
|
tools: maxToolRounds > 0 ? tools : [],
|
|
13250
13683
|
messages: toPiHistoryMessages(history)
|
|
13251
13684
|
},
|
|
@@ -14909,11 +15342,17 @@ var aiLocales = { "zh-CN": zh_CN_default, "en-US": en_US_default, "ja-JP": ja_JP
|
|
|
14909
15342
|
var MIN_MESSAGE_COUNT = 3;
|
|
14910
15343
|
var MAX_CONTENT_PER_CALL = 8e3;
|
|
14911
15344
|
var SEGMENT_THRESHOLD = 8e3;
|
|
14912
|
-
function getSummaryLengthLimit(messageCount) {
|
|
14913
|
-
if (
|
|
14914
|
-
|
|
14915
|
-
|
|
14916
|
-
|
|
15345
|
+
function getSummaryLengthLimit(messageCount, strategy = "standard") {
|
|
15346
|
+
if (strategy === "brief") {
|
|
15347
|
+
if (messageCount <= 10) return 50;
|
|
15348
|
+
if (messageCount <= 30) return 80;
|
|
15349
|
+
if (messageCount <= 100) return 120;
|
|
15350
|
+
return 200;
|
|
15351
|
+
}
|
|
15352
|
+
if (messageCount <= 10) return 100;
|
|
15353
|
+
if (messageCount <= 30) return 200;
|
|
15354
|
+
if (messageCount <= 100) return 350;
|
|
15355
|
+
return 500;
|
|
14917
15356
|
}
|
|
14918
15357
|
var MEANINGFUL_SHORT_ZH = ["\u597D\u7684", "\u4E0D\u662F", "\u662F\u7684", "\u53EF\u4EE5", "\u4E0D\u884C", "\u597D\u5427", "\u660E\u767D", "\u77E5\u9053", "\u540C\u610F"];
|
|
14919
15358
|
var MEANINGLESS_SHORT_EN = [
|
|
@@ -15009,34 +15448,55 @@ function splitIntoSegments(messages, maxCharsPerSegment) {
|
|
|
15009
15448
|
if (currentSegment.length > 0) segments.push(currentSegment);
|
|
15010
15449
|
return segments;
|
|
15011
15450
|
}
|
|
15012
|
-
function buildSummaryPrompt(content, lengthLimit, locale) {
|
|
15451
|
+
function buildSummaryPrompt(content, lengthLimit, locale, strategy) {
|
|
15452
|
+
if (strategy === "brief") {
|
|
15453
|
+
if (locale.startsWith("zh")) {
|
|
15454
|
+
return `\u8BF7\u7528\u7B80\u6D01\u7684\u8BED\u8A00\uFF08${lengthLimit}\u5B57\u4EE5\u5185\uFF09\u603B\u7ED3\u4EE5\u4E0B\u5BF9\u8BDD\u7684\u4E3B\u8981\u5185\u5BB9\u6216\u8BDD\u9898\u3002\u53EA\u8F93\u51FA\u6458\u8981\u5185\u5BB9\uFF0C\u4E0D\u8981\u6DFB\u52A0\u4EFB\u4F55\u524D\u7F00\u3001\u89E3\u91CA\u6216\u5F15\u53F7\u3002
|
|
15455
|
+
|
|
15456
|
+
${content}`;
|
|
15457
|
+
}
|
|
15458
|
+
return `Summarize the following conversation concisely (max ${lengthLimit} characters). Output only the summary, no prefix, explanation, or quotes.
|
|
15459
|
+
|
|
15460
|
+
${content}`;
|
|
15461
|
+
}
|
|
15013
15462
|
if (locale.startsWith("zh")) {
|
|
15014
|
-
return `\u8BF7\
|
|
15463
|
+
return `\u8BF7\u603B\u7ED3\u4EE5\u4E0B\u804A\u5929\u8BB0\u5F55\uFF08${lengthLimit}\u5B57\u4EE5\u5185\uFF09\uFF0C\u9700\u5305\u542B\uFF1A\u8C01\u53C2\u4E0E\u4E86\u8BA8\u8BBA\u3001\u8BA8\u8BBA\u4E86\u4EC0\u4E48\u4E8B\u60C5\u3001\u5173\u952E\u7EC6\u8282\u548C\u7ED3\u8BBA\u3002\u75282-4\u53E5\u8BDD\u63CF\u8FF0\uFF0C\u4E0D\u8981\u7F57\u5217\u6BCF\u6761\u6D88\u606F\u3002\u53EA\u8F93\u51FA\u6458\u8981\u5185\u5BB9\uFF0C\u4E0D\u8981\u6DFB\u52A0\u4EFB\u4F55\u524D\u7F00\u3001\u89E3\u91CA\u6216\u5F15\u53F7\u3002
|
|
15015
15464
|
|
|
15016
15465
|
${content}`;
|
|
15017
15466
|
}
|
|
15018
|
-
return `Summarize the following
|
|
15467
|
+
return `Summarize the following chat log (max ${lengthLimit} characters). Include: who participated, what was discussed, key details and conclusions. Use 2-4 sentences, don't list individual messages. Output only the summary, no prefix, explanation, or quotes.
|
|
15019
15468
|
|
|
15020
15469
|
${content}`;
|
|
15021
15470
|
}
|
|
15022
|
-
function buildSubSummaryPrompt(content, locale) {
|
|
15471
|
+
function buildSubSummaryPrompt(content, locale, strategy) {
|
|
15472
|
+
const limit = strategy === "brief" ? 50 : 100;
|
|
15023
15473
|
if (locale.startsWith("zh")) {
|
|
15024
|
-
return `\u8BF7\u7528\u4E00\u53E5\u8BDD\uFF08\u4E0D\u8D85\
|
|
15474
|
+
return `\u8BF7\u7528\u4E00\u5230\u4E24\u53E5\u8BDD\uFF08\u4E0D\u8D85\u8FC7${limit}\u5B57\uFF09\u6982\u62EC\u4EE5\u4E0B\u5BF9\u8BDD\u7247\u6BB5\u7684\u4E3B\u8981\u5185\u5BB9\uFF0C\u5305\u62EC\u8C01\u8BF4\u4E86\u4EC0\u4E48\u3002\u53EA\u8F93\u51FA\u6458\u8981\u5185\u5BB9\uFF0C\u4E0D\u8981\u6DFB\u52A0\u4EFB\u4F55\u524D\u7F00\u3001\u89E3\u91CA\u6216\u5F15\u53F7\u3002
|
|
15025
15475
|
|
|
15026
15476
|
${content}`;
|
|
15027
15477
|
}
|
|
15028
|
-
return `Summarize this conversation segment in
|
|
15478
|
+
return `Summarize this conversation segment in 1-2 sentences (max ${limit} characters), including who said what. Output only the summary, no prefix or quotes.
|
|
15029
15479
|
|
|
15030
15480
|
${content}`;
|
|
15031
15481
|
}
|
|
15032
|
-
function buildMergePrompt(subSummaries, lengthLimit, locale) {
|
|
15482
|
+
function buildMergePrompt(subSummaries, lengthLimit, locale, strategy) {
|
|
15033
15483
|
const list = subSummaries.map((s, i) => `${i + 1}. ${s}`).join("\n");
|
|
15484
|
+
if (strategy === "brief") {
|
|
15485
|
+
if (locale.startsWith("zh")) {
|
|
15486
|
+
return `\u4EE5\u4E0B\u662F\u4E00\u6BB5\u5BF9\u8BDD\u7684\u591A\u4E2A\u7247\u6BB5\u6458\u8981\uFF0C\u8BF7\u5C06\u5B83\u4EEC\u5408\u5E76\u6210\u4E00\u4E2A\u5B8C\u6574\u7684\u603B\u7ED3\uFF08${lengthLimit}\u5B57\u4EE5\u5185\uFF09\u3002\u53EA\u8F93\u51FA\u6458\u8981\u5185\u5BB9\uFF0C\u4E0D\u8981\u6DFB\u52A0\u4EFB\u4F55\u524D\u7F00\u3001\u89E3\u91CA\u6216\u5F15\u53F7\u3002
|
|
15487
|
+
|
|
15488
|
+
${list}`;
|
|
15489
|
+
}
|
|
15490
|
+
return `Below are summaries of different parts of a conversation. Merge them into one cohesive summary (max ${lengthLimit} characters). Output only the summary, no prefix or quotes.
|
|
15491
|
+
|
|
15492
|
+
${list}`;
|
|
15493
|
+
}
|
|
15034
15494
|
if (locale.startsWith("zh")) {
|
|
15035
|
-
return `\u4EE5\u4E0B\u662F\u4E00\u6BB5\u5BF9\u8BDD\u7684\u591A\u4E2A\u7247\u6BB5\u6458\u8981\uFF0C\u8BF7\u5C06\u5B83\u4EEC\u5408\u5E76\u6210\u4E00\u4E2A\u5B8C\u6574\u7684\u603B\u7ED3\uFF08${lengthLimit}\u5B57\u4EE5\u5185\uFF09\u3002\u53EA\u8F93\u51FA\u6458\u8981\u5185\u5BB9\uFF0C\u4E0D\u8981\u6DFB\u52A0\u4EFB\u4F55\u524D\u7F00\u3001\u89E3\u91CA\u6216\u5F15\u53F7\u3002
|
|
15495
|
+
return `\u4EE5\u4E0B\u662F\u4E00\u6BB5\u5BF9\u8BDD\u7684\u591A\u4E2A\u7247\u6BB5\u6458\u8981\uFF0C\u8BF7\u5C06\u5B83\u4EEC\u5408\u5E76\u6210\u4E00\u4E2A\u5B8C\u6574\u7684\u603B\u7ED3\uFF08${lengthLimit}\u5B57\u4EE5\u5185\uFF09\u3002\u4FDD\u7559\u53C2\u4E0E\u8005\u3001\u4E8B\u4EF6\u548C\u5173\u952E\u7EC6\u8282\u3002\u53EA\u8F93\u51FA\u6458\u8981\u5185\u5BB9\uFF0C\u4E0D\u8981\u6DFB\u52A0\u4EFB\u4F55\u524D\u7F00\u3001\u89E3\u91CA\u6216\u5F15\u53F7\u3002
|
|
15036
15496
|
|
|
15037
15497
|
${list}`;
|
|
15038
15498
|
}
|
|
15039
|
-
return `Below are summaries of different parts of a conversation. Merge them into one cohesive summary (max ${lengthLimit} characters). Output only the summary, no prefix or quotes.
|
|
15499
|
+
return `Below are summaries of different parts of a conversation. Merge them into one cohesive summary (max ${lengthLimit} characters). Preserve participants, events, and key details. Output only the summary, no prefix or quotes.
|
|
15040
15500
|
|
|
15041
15501
|
${list}`;
|
|
15042
15502
|
}
|
|
@@ -15052,7 +15512,7 @@ function postProcessSummary(summary, lengthLimit) {
|
|
|
15052
15512
|
return result;
|
|
15053
15513
|
}
|
|
15054
15514
|
async function generateSessionSummary(deps, chatSessionId, options = {}) {
|
|
15055
|
-
const { locale = "zh-CN", forceRegenerate = false } = options;
|
|
15515
|
+
const { locale = "zh-CN", forceRegenerate = false, strategy = "standard" } = options;
|
|
15056
15516
|
const log = deps.logger;
|
|
15057
15517
|
try {
|
|
15058
15518
|
if (!forceRegenerate) {
|
|
@@ -15070,18 +15530,20 @@ async function generateSessionSummary(deps, chatSessionId, options = {}) {
|
|
|
15070
15530
|
if (validMessages.length < MIN_MESSAGE_COUNT) {
|
|
15071
15531
|
return { success: false, error: deps.t("summary.tooFewValidMessages", { count: MIN_MESSAGE_COUNT }) };
|
|
15072
15532
|
}
|
|
15073
|
-
const lengthLimit = getSummaryLengthLimit(validMessages.length);
|
|
15533
|
+
const lengthLimit = getSummaryLengthLimit(validMessages.length, strategy);
|
|
15534
|
+
const maxTokens = strategy === "brief" ? 300 : 600;
|
|
15535
|
+
const subMaxTokens = strategy === "brief" ? 100 : 200;
|
|
15074
15536
|
const content = formatMessages(validMessages);
|
|
15075
15537
|
log?.info(
|
|
15076
15538
|
"Summary",
|
|
15077
|
-
`Generating summary: sessionId=${chatSessionId}, raw=${rawMessages.length}, valid=${validMessages.length}, chars=${content.length}`
|
|
15539
|
+
`Generating summary: sessionId=${chatSessionId}, strategy=${strategy}, raw=${rawMessages.length}, valid=${validMessages.length}, chars=${content.length}`
|
|
15078
15540
|
);
|
|
15079
15541
|
let summary;
|
|
15080
15542
|
if (content.length <= SEGMENT_THRESHOLD) {
|
|
15081
15543
|
summary = await deps.llmComplete(
|
|
15082
15544
|
deps.t("summary.systemPromptDirect"),
|
|
15083
|
-
buildSummaryPrompt(content, lengthLimit, locale),
|
|
15084
|
-
{ temperature: 0.3, maxTokens
|
|
15545
|
+
buildSummaryPrompt(content, lengthLimit, locale, strategy),
|
|
15546
|
+
{ temperature: 0.3, maxTokens }
|
|
15085
15547
|
);
|
|
15086
15548
|
summary = summary.trim();
|
|
15087
15549
|
} else {
|
|
@@ -15092,8 +15554,8 @@ async function generateSessionSummary(deps, chatSessionId, options = {}) {
|
|
|
15092
15554
|
const segContent = formatMessages(segment2);
|
|
15093
15555
|
const sub = await deps.llmComplete(
|
|
15094
15556
|
deps.t("summary.systemPromptDirect"),
|
|
15095
|
-
buildSubSummaryPrompt(segContent, locale),
|
|
15096
|
-
{ temperature: 0.3, maxTokens:
|
|
15557
|
+
buildSubSummaryPrompt(segContent, locale, strategy),
|
|
15558
|
+
{ temperature: 0.3, maxTokens: subMaxTokens }
|
|
15097
15559
|
);
|
|
15098
15560
|
subSummaries.push(sub.trim());
|
|
15099
15561
|
}
|
|
@@ -15102,8 +15564,8 @@ async function generateSessionSummary(deps, chatSessionId, options = {}) {
|
|
|
15102
15564
|
} else {
|
|
15103
15565
|
summary = await deps.llmComplete(
|
|
15104
15566
|
deps.t("summary.systemPromptMerge"),
|
|
15105
|
-
buildMergePrompt(subSummaries, lengthLimit, locale),
|
|
15106
|
-
{ temperature: 0.3, maxTokens
|
|
15567
|
+
buildMergePrompt(subSummaries, lengthLimit, locale, strategy),
|
|
15568
|
+
{ temperature: 0.3, maxTokens }
|
|
15107
15569
|
);
|
|
15108
15570
|
summary = summary.trim();
|
|
15109
15571
|
}
|
|
@@ -15359,6 +15821,20 @@ var BUILTIN_PROVIDER_API = {
|
|
|
15359
15821
|
gemini: "google-generative-ai",
|
|
15360
15822
|
anthropic: "anthropic-messages"
|
|
15361
15823
|
};
|
|
15824
|
+
function inferReasoning(provider, modelId, modelDef) {
|
|
15825
|
+
const reasoning = modelDef?.capabilities.includes("reasoning") || !modelDef?.builtin && isReasoningModel(provider, modelId);
|
|
15826
|
+
if (!reasoning) return { reasoning: false, compat: void 0 };
|
|
15827
|
+
const thinkingCompat = getThinkingCompat(provider, modelId);
|
|
15828
|
+
if (Object.keys(thinkingCompat).length === 0) {
|
|
15829
|
+
return { reasoning: true, compat: void 0 };
|
|
15830
|
+
}
|
|
15831
|
+
const { thinkingLevelMap, ...compatFields } = thinkingCompat;
|
|
15832
|
+
return {
|
|
15833
|
+
reasoning: true,
|
|
15834
|
+
compat: Object.keys(compatFields).length > 0 ? compatFields : void 0,
|
|
15835
|
+
thinkingLevelMap
|
|
15836
|
+
};
|
|
15837
|
+
}
|
|
15362
15838
|
function buildPiModel(config, options) {
|
|
15363
15839
|
const providerDef = BUILTIN_PROVIDERS.find((p) => p.id === config.provider);
|
|
15364
15840
|
const baseUrl = config.baseUrl || providerDef?.defaultBaseUrl || "";
|
|
@@ -15374,7 +15850,7 @@ function buildPiModel(config, options) {
|
|
|
15374
15850
|
api: "google-generative-ai",
|
|
15375
15851
|
provider: "google",
|
|
15376
15852
|
baseUrl,
|
|
15377
|
-
reasoning:
|
|
15853
|
+
reasoning: isReasoningModel(config.provider, modelId),
|
|
15378
15854
|
input: ["text"],
|
|
15379
15855
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
15380
15856
|
contextWindow,
|
|
@@ -15396,6 +15872,7 @@ function buildPiModel(config, options) {
|
|
|
15396
15872
|
};
|
|
15397
15873
|
}
|
|
15398
15874
|
const resolvedBaseUrl = config.provider === "openai-compatible" && (apiFormat === "openai-completions" || apiFormat === "openai-responses") ? normalizeOpenAICompatibleBaseUrl(baseUrl) : baseUrl;
|
|
15875
|
+
const { reasoning, compat, thinkingLevelMap } = inferReasoning(config.provider, modelId, modelDef);
|
|
15399
15876
|
return {
|
|
15400
15877
|
id: modelId,
|
|
15401
15878
|
name: modelId,
|
|
@@ -15403,12 +15880,13 @@ function buildPiModel(config, options) {
|
|
|
15403
15880
|
provider: config.provider,
|
|
15404
15881
|
baseUrl: resolvedBaseUrl,
|
|
15405
15882
|
headers: options?.headers,
|
|
15406
|
-
reasoning
|
|
15883
|
+
reasoning,
|
|
15884
|
+
thinkingLevelMap,
|
|
15407
15885
|
input: ["text"],
|
|
15408
15886
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
15409
15887
|
contextWindow,
|
|
15410
15888
|
maxTokens: config.maxTokens ?? 4096,
|
|
15411
|
-
compat
|
|
15889
|
+
compat
|
|
15412
15890
|
};
|
|
15413
15891
|
}
|
|
15414
15892
|
|
|
@@ -16842,7 +17320,8 @@ var localeConfigSchema = z.object({
|
|
|
16842
17320
|
});
|
|
16843
17321
|
var uiConfigSchema = z.object({
|
|
16844
17322
|
default_session_tab: z.enum(["overview", "ai-chat"]).default("overview"),
|
|
16845
|
-
session_gap_threshold: z.number().int().min(60).max(86400).default(1800)
|
|
17323
|
+
session_gap_threshold: z.number().int().min(60).max(86400).default(1800),
|
|
17324
|
+
summary_strategy: z.enum(["brief", "standard"]).default("standard")
|
|
16846
17325
|
});
|
|
16847
17326
|
var configSchema = z.object({
|
|
16848
17327
|
llm: llmConfigSchema.default({}),
|
|
@@ -18774,6 +19253,7 @@ __export(session_index_service_exports, {
|
|
|
18774
19253
|
clearIndex: () => clearIndex,
|
|
18775
19254
|
generateIncrementalIndex: () => generateIncrementalIndex,
|
|
18776
19255
|
generateIndex: () => generateIndex,
|
|
19256
|
+
getAllIndexStats: () => getAllIndexStats,
|
|
18777
19257
|
getFtsStatus: () => getFtsStatus,
|
|
18778
19258
|
rebuildFts: () => rebuildFts,
|
|
18779
19259
|
searchFts: () => searchFts
|
|
@@ -18802,10 +19282,23 @@ function rebuildFts(adapter, sessionId) {
|
|
|
18802
19282
|
const db = adapter.ensureWritable(sessionId);
|
|
18803
19283
|
return rebuildFtsIndex(db);
|
|
18804
19284
|
}
|
|
19285
|
+
function getAllIndexStats(adapter) {
|
|
19286
|
+
const ids = adapter.listSessionIds();
|
|
19287
|
+
return ids.map((sessionId) => {
|
|
19288
|
+
try {
|
|
19289
|
+
const db = adapter.ensureReadonly(sessionId);
|
|
19290
|
+
const stats = getSessionIndexStats(db);
|
|
19291
|
+
return { sessionId, hasIndex: stats.hasIndex, sessionCount: stats.sessionCount };
|
|
19292
|
+
} catch {
|
|
19293
|
+
return { sessionId, hasIndex: false, sessionCount: 0 };
|
|
19294
|
+
}
|
|
19295
|
+
});
|
|
19296
|
+
}
|
|
18805
19297
|
|
|
18806
19298
|
// ../../packages/node-runtime/src/services/summary-service.ts
|
|
18807
19299
|
var summary_service_exports = {};
|
|
18808
19300
|
__export(summary_service_exports, {
|
|
19301
|
+
checkCanGenerate: () => checkCanGenerate,
|
|
18809
19302
|
generateAllSummaries: () => generateAllSummaries,
|
|
18810
19303
|
generateSummary: () => generateSummary
|
|
18811
19304
|
});
|
|
@@ -18863,6 +19356,23 @@ async function generateAllSummaries(adapter, sessionId, serviceDeps, options) {
|
|
|
18863
19356
|
}
|
|
18864
19357
|
return { success, failed, total: chatSessions.length };
|
|
18865
19358
|
}
|
|
19359
|
+
function checkCanGenerate(adapter, sessionId, chatSessionIds) {
|
|
19360
|
+
const db = adapter.ensureReadonly(sessionId);
|
|
19361
|
+
const deps = {
|
|
19362
|
+
loadMessages(chatSessionId, limit = 500) {
|
|
19363
|
+
const data = getSessionMessages(db, chatSessionId, limit);
|
|
19364
|
+
if (!data) return null;
|
|
19365
|
+
return data.messages.map((m) => ({ senderName: m.senderName, content: m.content }));
|
|
19366
|
+
},
|
|
19367
|
+
t: (key) => key
|
|
19368
|
+
};
|
|
19369
|
+
const resultMap = checkSessionsCanGenerateSummary(deps, chatSessionIds);
|
|
19370
|
+
const result = {};
|
|
19371
|
+
for (const [id, info] of resultMap) {
|
|
19372
|
+
result[id] = info;
|
|
19373
|
+
}
|
|
19374
|
+
return result;
|
|
19375
|
+
}
|
|
18866
19376
|
|
|
18867
19377
|
// ../../packages/node-runtime/src/services/export-service.ts
|
|
18868
19378
|
var export_service_exports = {};
|
|
@@ -19153,4 +19663,4 @@ export {
|
|
|
19153
19663
|
export_service_exports,
|
|
19154
19664
|
createDatabaseManagerAdapter
|
|
19155
19665
|
};
|
|
19156
|
-
//# sourceMappingURL=chunk-
|
|
19666
|
+
//# sourceMappingURL=chunk-G7Q7EQ3V.mjs.map
|