dsh-trivium 0.4.9 → 0.4.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +76 -44
- package/README.zh-CN.md +77 -47
- package/lib/client.js +374 -45
- package/lib/index.js +9 -0
- package/lib/purge.js +122 -0
- package/lib/server.js +29 -1
- package/lib/settings.js +106 -9
- package/lib/sidecar.js +422 -0
- package/lib/store.js +69 -8
- package/package.json +4 -1
package/lib/client.js
CHANGED
|
@@ -29,12 +29,17 @@ window.__ModuleLoader__.load({
|
|
|
29
29
|
extract: "compaction/end 抽取",
|
|
30
30
|
extractHint: "规则 + 一次小 prompt;失败只记日志。turn 结束后约 12 秒空闲会再抽一次,下次 session-start 也会重放 pending。每轮写入正文合计 ≤3000 字、最多 24 条。",
|
|
31
31
|
chipTab: "芯片",
|
|
32
|
-
chipsSetting: "
|
|
33
|
-
chipsSettingHint: "打开后,标题栏「对话 /
|
|
32
|
+
chipsSetting: "芯片(记忆白名单,默认关)",
|
|
33
|
+
chipsSettingHint: "打开后,标题栏「对话 / 轨迹」旁立刻出现「芯片」(记忆白名单)。勾选的条目从下一轮注入(L0,≤300 token)。选择写入 ~/.dsh/trivium.json,重启后仍保持。节点仍在 .tdb,关开关不删记忆。不必再点「保存设置」,也不必重启。",
|
|
34
34
|
sessionLayer: "会话层(情节画布)",
|
|
35
35
|
sessionLayerHint: "可选。把 compaction / 分叉画成方框,可生成检查点。关着不记 episode,不影响 ctx_find。需先打开芯片标签。",
|
|
36
36
|
markdown: "Markdown 投影",
|
|
37
37
|
markdownHint: "只读导出,带边(- 鉴权走 header X —about→ AuthGateway)。给编辑器和 git 看。改完回写用 JSON 导入或本页编辑,不解析自由散文。",
|
|
38
|
+
gitSidecar: "Git 旁路(trivium.jsonl,默认关)",
|
|
39
|
+
gitSidecarHint: "图有改动后延迟约 1.5 秒写入工作区 .dsh/trivium.jsonl(只含业务节点和边,不含向量、情节、芯片钉选)。把这个文件交给 git,.tdb 建议 gitignore。clone / git pull 后若文件变了会自动导回。开关本身不删文件。开着时可点「生成」用当前 .tdb 覆盖写出;关掉后可点「删除 jsonl」。",
|
|
40
|
+
gitSidecarGenerate: "生成",
|
|
41
|
+
gitSidecarDelete: "删除 jsonl",
|
|
42
|
+
gitSidecarDeleteConfirm: "将删除已知工作区里的 trivium.jsonl。.tdb 记忆还在,可以再打开开关后点「生成」写回。确定删除?",
|
|
38
43
|
exportMd: "导出 Markdown",
|
|
39
44
|
external: "外部记忆一次性导入",
|
|
40
45
|
externalHint: "发现 WorkBuddy MEMORY.md、Claude Code CLAUDE.md、Codex AGENTS.md。偏严宁漏:闲聊、一次性改文件、密钥、乱码、工具 dump、无规则线索的段落跳过。不持续同步,不导入会话 jsonl。每批同样 ≤3000 字 / 24 条。",
|
|
@@ -49,6 +54,15 @@ window.__ModuleLoader__.load({
|
|
|
49
54
|
updateInstalled: "已安装",
|
|
50
55
|
updateLatest: "npm latest",
|
|
51
56
|
updateFailed: "暂时查不到 registry",
|
|
57
|
+
configPanel: "配置设置",
|
|
58
|
+
configPanelHint: "注入、抽取、芯片、Git 旁路、界面语言、导入和 embedding。默认收起。",
|
|
59
|
+
configPanelOpen: "展开",
|
|
60
|
+
configPanelClose: "收起",
|
|
61
|
+
pluginLocale: "界面语言(本插件)",
|
|
62
|
+
pluginLocaleHint: "只改本插件设置页和芯片标签的文案,不改 DSH 宿主语言。未选时跟随宿主。",
|
|
63
|
+
pluginLocaleHost: "跟随宿主",
|
|
64
|
+
pluginLocaleZh: "中文",
|
|
65
|
+
pluginLocaleEn: "English",
|
|
52
66
|
embed: "远程 embedding(OpenAI 兼容,默认关)",
|
|
53
67
|
embedHint: "失败退回关键词 + 图检索。需单独的 embeddings endpoint;官方 DeepSeek chat API 不含 embedding。",
|
|
54
68
|
embedReady: "已就绪",
|
|
@@ -113,13 +127,13 @@ window.__ModuleLoader__.load({
|
|
|
113
127
|
cutNeedTurn: "当前对话还没有可切的轮次。先在对话里发一条,再生成检查点。",
|
|
114
128
|
cutOk: "已把当前「后续」收成左边一格(seq {seq}),右边仍是后续。这不压缩 DSH 上下文。",
|
|
115
129
|
cutDup: "这个位置已经切过了(seq {seq})。再聊几轮后再生成。",
|
|
116
|
-
forkOpenFail: "
|
|
117
|
-
chatViewFail: "
|
|
118
|
-
trajViewFail: "
|
|
130
|
+
forkOpenFail: "无法打开分叉会话:芯片页没有拿到 session.open",
|
|
131
|
+
chatViewFail: "无法切换到对话页:芯片页没有拿到同一 chat store 的 setView",
|
|
132
|
+
trajViewFail: "无法切换到轨迹页:芯片页没有拿到同一 chat store 的 setView",
|
|
119
133
|
noFork: "当前壳没有 session.fork",
|
|
120
134
|
renameFail: "会话已分叉,但侧边栏改名失败:{err}",
|
|
121
135
|
deleteConfirm: "删除会从 .tdb 里拿掉这 {n} 条,不可恢复。归档只是藏起来,find / 短地图 / 芯片都不再出现。确定删除?",
|
|
122
|
-
sessionMap: "
|
|
136
|
+
sessionMap: "芯片",
|
|
123
137
|
chips: "记忆芯片",
|
|
124
138
|
chipsHint: "共 {n} 条,已钉 {pins}。默认不勾选:不钉就不会按芯片白名单注入,但仍可能被开场短地图点名带上,模型也能 find 到。",
|
|
125
139
|
cutBtn: "生成检查点",
|
|
@@ -171,12 +185,17 @@ window.__ModuleLoader__.load({
|
|
|
171
185
|
extract: "Extract on compaction/end",
|
|
172
186
|
extractHint: "Rules + one small prompt; failures are logged. Idle ~12s after turn/end also extracts; pending replays on next session-start. Per batch: body ≤3000 chars, at most 24 items.",
|
|
173
187
|
chipTab: "Chips",
|
|
174
|
-
chipsSetting: "Chips
|
|
175
|
-
chipsSettingHint: "When on, the
|
|
188
|
+
chipsSetting: "Chips (memory whitelist, off by default)",
|
|
189
|
+
chipsSettingHint: "When on, the Chips tab appears next to Conversation / Trajectory immediately (memory whitelist). Checked items inject from the next turn (L0, ≤300 tokens). Stored in ~/.dsh/trivium.json and kept across restarts. Nodes stay in .tdb; turning this off does not delete memory. No extra Save click and no restart.",
|
|
176
190
|
sessionLayer: "Session layer (plot canvas)",
|
|
177
191
|
sessionLayerHint: "Optional. Draws compaction / forks as boxes; Create checkpoint lives here. Off means no episode writes; ctx_find is unchanged. Requires the Chips tab first.",
|
|
178
192
|
markdown: "Markdown projection",
|
|
179
193
|
markdownHint: "Read-only export with edges (e.g. - auth in header X —about→ AuthGateway). For editors and git. Write back with JSON import or this page, not free prose.",
|
|
194
|
+
gitSidecar: "Git sidecar (trivium.jsonl, off by default)",
|
|
195
|
+
gitSidecarHint: "After graph writes, debounce ~1.5s and write workspace .dsh/trivium.jsonl (business nodes and edges only — no embeddings, episodes, or chip pins). Commit that file; gitignore .tdb. Clone or git pull re-imports when the file changes. The switch does not delete files. While on, Generate overwrites jsonl from the current .tdb. After turning off, Delete removes known jsonl files.",
|
|
196
|
+
gitSidecarGenerate: "Generate",
|
|
197
|
+
gitSidecarDelete: "Delete jsonl",
|
|
198
|
+
gitSidecarDeleteConfirm: "This deletes known workspace trivium.jsonl files. .tdb memory stays; turn the switch on and Generate to write them back. Delete anyway?",
|
|
180
199
|
exportMd: "Export Markdown",
|
|
181
200
|
external: "One-shot external import",
|
|
182
201
|
externalHint: "Discovers WorkBuddy MEMORY.md, Claude Code CLAUDE.md, and Codex AGENTS.md. Strict: skip chitchat, one-off file edits, secrets, mojibake, tool dumps, and lines with no rule cue. No watch, no session jsonl. Same cap: ≤3000 chars / 24 items.",
|
|
@@ -191,6 +210,15 @@ window.__ModuleLoader__.load({
|
|
|
191
210
|
updateInstalled: "Installed",
|
|
192
211
|
updateLatest: "npm latest",
|
|
193
212
|
updateFailed: "Registry unavailable",
|
|
213
|
+
configPanel: "Settings",
|
|
214
|
+
configPanelHint: "Injection, extract, chips, Git sidecar, language, import, and embedding. Collapsed by default.",
|
|
215
|
+
configPanelOpen: "Expand",
|
|
216
|
+
configPanelClose: "Collapse",
|
|
217
|
+
pluginLocale: "Plugin language",
|
|
218
|
+
pluginLocaleHint: "Only this plugin's Settings card and Chips tab. Does not change the DSH host. Default follows the host.",
|
|
219
|
+
pluginLocaleHost: "Follow host",
|
|
220
|
+
pluginLocaleZh: "中文",
|
|
221
|
+
pluginLocaleEn: "English",
|
|
194
222
|
embed: "Remote embedding (OpenAI-compatible, off by default)",
|
|
195
223
|
embedHint: "Failures fall back to keyword + graph search. Needs a separate embeddings endpoint; the official DeepSeek chat API has none.",
|
|
196
224
|
embedReady: "Ready",
|
|
@@ -261,7 +289,7 @@ window.__ModuleLoader__.load({
|
|
|
261
289
|
noFork: "This host has no session.fork",
|
|
262
290
|
renameFail: "Session forked, but sidebar rename failed: {err}",
|
|
263
291
|
deleteConfirm: "Delete removes these {n} nodes from .tdb and cannot be undone. Archive only hides them from find / short map / chips. Delete anyway?",
|
|
264
|
-
sessionMap: "
|
|
292
|
+
sessionMap: "Chips",
|
|
265
293
|
chips: "Memory chips",
|
|
266
294
|
chipsHint: "{n} chips, {pins} pinned. Unchecked by default: pinning is a whitelist, but the short map may still name them and the model can still find them.",
|
|
267
295
|
cutBtn: "Create checkpoint",
|
|
@@ -297,6 +325,8 @@ window.__ModuleLoader__.load({
|
|
|
297
325
|
};
|
|
298
326
|
|
|
299
327
|
let uiLocale = "zh";
|
|
328
|
+
let hostLocale = "";
|
|
329
|
+
let pluginLocalePref = "host";
|
|
300
330
|
const localeListeners = new Set();
|
|
301
331
|
|
|
302
332
|
function normalizeLocale(value) {
|
|
@@ -306,6 +336,11 @@ window.__ModuleLoader__.load({
|
|
|
306
336
|
return "";
|
|
307
337
|
}
|
|
308
338
|
|
|
339
|
+
function resolvedUiLocale() {
|
|
340
|
+
if (pluginLocalePref === "zh" || pluginLocalePref === "en") return pluginLocalePref;
|
|
341
|
+
return hostLocale || "zh";
|
|
342
|
+
}
|
|
343
|
+
|
|
309
344
|
function setUiLocale(next) {
|
|
310
345
|
const loc = normalizeLocale(next) || "zh";
|
|
311
346
|
if (loc === uiLocale) return;
|
|
@@ -319,6 +354,22 @@ window.__ModuleLoader__.load({
|
|
|
319
354
|
});
|
|
320
355
|
}
|
|
321
356
|
|
|
357
|
+
function applyResolvedLocale() {
|
|
358
|
+
setUiLocale(resolvedUiLocale());
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
function setHostLocale(next) {
|
|
362
|
+
const loc = normalizeLocale(next);
|
|
363
|
+
if (loc) hostLocale = loc;
|
|
364
|
+
applyResolvedLocale();
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
function setPluginLocalePref(next) {
|
|
368
|
+
const v = String(next || "").toLowerCase();
|
|
369
|
+
pluginLocalePref = v === "zh" || v === "en" ? v : "host";
|
|
370
|
+
applyResolvedLocale();
|
|
371
|
+
}
|
|
372
|
+
|
|
322
373
|
function t(key, vars) {
|
|
323
374
|
let s = (I18N[uiLocale] && I18N[uiLocale][key]) || I18N.en[key] || I18N.zh[key] || key;
|
|
324
375
|
if (vars) {
|
|
@@ -385,6 +436,54 @@ window.__ModuleLoader__.load({
|
|
|
385
436
|
saved: { fontSize: 12, opacity: 0.75 },
|
|
386
437
|
};
|
|
387
438
|
|
|
439
|
+
const chipUi = { ctx: null, sessions: null, dispose: null };
|
|
440
|
+
const chipViewListeners = new Set();
|
|
441
|
+
|
|
442
|
+
function subscribeChipView(fn) {
|
|
443
|
+
chipViewListeners.add(fn);
|
|
444
|
+
return () => chipViewListeners.delete(fn);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
function refreshChipView(hint) {
|
|
448
|
+
for (const fn of chipViewListeners) {
|
|
449
|
+
try {
|
|
450
|
+
fn(hint);
|
|
451
|
+
} catch {
|
|
452
|
+
// ignore
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
function setChipsTab(enabled) {
|
|
458
|
+
const ctx = chipUi.ctx;
|
|
459
|
+
const sessions = chipUi.sessions;
|
|
460
|
+
if (!ctx || !sessions) return;
|
|
461
|
+
if (enabled) {
|
|
462
|
+
if (chipUi.dispose) return;
|
|
463
|
+
chipUi.dispose = registerChipView(ctx, sessions);
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
if (!chipUi.dispose) return;
|
|
467
|
+
try {
|
|
468
|
+
chipUi.dispose();
|
|
469
|
+
} catch {
|
|
470
|
+
// already gone
|
|
471
|
+
}
|
|
472
|
+
chipUi.dispose = null;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
async function syncChipsTabFromServer() {
|
|
476
|
+
for (let i = 0; i < 10; i += 1) {
|
|
477
|
+
try {
|
|
478
|
+
const st = await api("/api/dsh-trivium/status");
|
|
479
|
+
setChipsTab(st && st.chipsEnabled === true);
|
|
480
|
+
return;
|
|
481
|
+
} catch {
|
|
482
|
+
await new Promise((ok) => setTimeout(ok, 200));
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
|
|
388
487
|
async function api(path, opts) {
|
|
389
488
|
const resp = await fetch(path, opts);
|
|
390
489
|
let data = null;
|
|
@@ -422,6 +521,9 @@ window.__ModuleLoader__.load({
|
|
|
422
521
|
const [extractEnabled, setExtractEnabled] = react.useState(true);
|
|
423
522
|
const [chipsEnabled, setChipsEnabled] = react.useState(false);
|
|
424
523
|
const [sessionLayerEnabled, setSessionLayerEnabled] = react.useState(false);
|
|
524
|
+
const [gitSidecarEnabled, setGitSidecarEnabled] = react.useState(false);
|
|
525
|
+
const [pluginLocale, setPluginLocale] = react.useState("host");
|
|
526
|
+
const [configPanelOpen, setConfigPanelOpen] = react.useState(false);
|
|
425
527
|
const [embeddingEnabled, setEmbeddingEnabled] = react.useState(false);
|
|
426
528
|
const [embeddingUrl, setEmbeddingUrl] = react.useState("");
|
|
427
529
|
const [embeddingModel, setEmbeddingModel] = react.useState("text-embedding-3-small");
|
|
@@ -434,20 +536,30 @@ window.__ModuleLoader__.load({
|
|
|
434
536
|
const [buddyNote, setBuddyNote] = react.useState("");
|
|
435
537
|
const [updateInfo, setUpdateInfo] = react.useState(null);
|
|
436
538
|
const [updateBusy, setUpdateBusy] = react.useState(false);
|
|
539
|
+
const persistSeq = react.useRef(0);
|
|
540
|
+
const loadSeq = react.useRef(0);
|
|
437
541
|
|
|
438
|
-
const load = react.useCallback(async () => {
|
|
542
|
+
const load = react.useCallback(async (opts = {}) => {
|
|
543
|
+
const seq = ++loadSeq.current;
|
|
439
544
|
setError("");
|
|
440
545
|
try {
|
|
441
546
|
const st = await api("/api/dsh-trivium/status");
|
|
547
|
+
if (seq !== loadSeq.current) return;
|
|
442
548
|
setStatus(st);
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
549
|
+
if (!opts.keepFlags) {
|
|
550
|
+
setRecallMode(st.recallMode || (st.autoRecall ? "auto" : st.anchorRecall ? "anchor" : "off"));
|
|
551
|
+
setExtractEnabled(st.extractEnabled !== false);
|
|
552
|
+
setChipsEnabled(!!st.chipsEnabled);
|
|
553
|
+
setSessionLayerEnabled(!!st.sessionLayerEnabled);
|
|
554
|
+
setGitSidecarEnabled(st.gitSidecarEnabled === true);
|
|
555
|
+
setPluginLocale(st.pluginLocale === "zh" || st.pluginLocale === "en" ? st.pluginLocale : "host");
|
|
556
|
+
setPluginLocalePref(st.pluginLocale);
|
|
557
|
+
setConfigPanelOpen(st.configPanelOpen === true);
|
|
558
|
+
setEmbeddingEnabled(!!st.embeddingEnabled);
|
|
559
|
+
setEmbeddingUrl(st.embeddingUrl || "");
|
|
560
|
+
setEmbeddingModel(st.embeddingModel || "text-embedding-3-small");
|
|
561
|
+
setEmbeddingApiKeySet(!!st.embeddingApiKeySet);
|
|
562
|
+
}
|
|
451
563
|
const params = new URLSearchParams();
|
|
452
564
|
if (type) params.set("type", type);
|
|
453
565
|
if (q.trim()) params.set("q", q.trim());
|
|
@@ -475,26 +587,96 @@ window.__ModuleLoader__.load({
|
|
|
475
587
|
until: n.until || "",
|
|
476
588
|
};
|
|
477
589
|
|
|
478
|
-
const
|
|
590
|
+
const flagsRef = react.useRef({
|
|
591
|
+
recallMode,
|
|
592
|
+
extractEnabled,
|
|
593
|
+
chipsEnabled,
|
|
594
|
+
sessionLayerEnabled,
|
|
595
|
+
gitSidecarEnabled,
|
|
596
|
+
pluginLocale,
|
|
597
|
+
configPanelOpen,
|
|
598
|
+
embeddingEnabled,
|
|
599
|
+
embeddingUrl,
|
|
600
|
+
embeddingModel,
|
|
601
|
+
embeddingApiKey,
|
|
602
|
+
});
|
|
603
|
+
flagsRef.current = {
|
|
604
|
+
recallMode,
|
|
605
|
+
extractEnabled,
|
|
606
|
+
chipsEnabled,
|
|
607
|
+
sessionLayerEnabled,
|
|
608
|
+
gitSidecarEnabled,
|
|
609
|
+
pluginLocale,
|
|
610
|
+
configPanelOpen,
|
|
611
|
+
embeddingEnabled,
|
|
612
|
+
embeddingUrl,
|
|
613
|
+
embeddingModel,
|
|
614
|
+
embeddingApiKey,
|
|
615
|
+
};
|
|
616
|
+
|
|
617
|
+
const persistFlags = async (patch = {}) => {
|
|
618
|
+
const cur = { ...flagsRef.current, ...patch };
|
|
619
|
+
const seq = ++persistSeq.current;
|
|
620
|
+
loadSeq.current += 1;
|
|
479
621
|
setBusy(true);
|
|
480
622
|
setSaved(false);
|
|
481
623
|
try {
|
|
482
624
|
const body = {
|
|
483
|
-
recallMode,
|
|
484
|
-
extractEnabled,
|
|
485
|
-
chipsEnabled,
|
|
486
|
-
sessionLayerEnabled,
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
625
|
+
recallMode: cur.recallMode,
|
|
626
|
+
extractEnabled: cur.extractEnabled,
|
|
627
|
+
chipsEnabled: cur.chipsEnabled,
|
|
628
|
+
sessionLayerEnabled: cur.sessionLayerEnabled,
|
|
629
|
+
gitSidecarEnabled: cur.gitSidecarEnabled === true,
|
|
630
|
+
pluginLocale: cur.pluginLocale === "zh" || cur.pluginLocale === "en" ? cur.pluginLocale : "host",
|
|
631
|
+
configPanelOpen: cur.configPanelOpen === true,
|
|
632
|
+
embeddingEnabled: cur.embeddingEnabled,
|
|
633
|
+
embeddingUrl: cur.embeddingUrl,
|
|
634
|
+
embeddingModel: cur.embeddingModel,
|
|
490
635
|
};
|
|
491
|
-
if (embeddingApiKey.trim()) body.embeddingApiKey = embeddingApiKey.trim();
|
|
636
|
+
if (String(cur.embeddingApiKey || "").trim()) body.embeddingApiKey = String(cur.embeddingApiKey).trim();
|
|
492
637
|
await api("/api/dsh-trivium/settings", {
|
|
493
638
|
method: "POST",
|
|
494
639
|
headers: { "content-type": "application/json" },
|
|
495
640
|
body: JSON.stringify(body),
|
|
496
641
|
});
|
|
497
|
-
|
|
642
|
+
if (seq !== persistSeq.current) return;
|
|
643
|
+
setChipsTab(cur.chipsEnabled === true);
|
|
644
|
+
refreshChipView({ sessionLayerEnabled: cur.sessionLayerEnabled === true });
|
|
645
|
+
setPluginLocalePref(cur.pluginLocale);
|
|
646
|
+
if (patch.embeddingApiKey != null || !Object.keys(patch).length) setEmbeddingApiKey("");
|
|
647
|
+
setSaved(true);
|
|
648
|
+
await load({ keepFlags: true });
|
|
649
|
+
} catch (err) {
|
|
650
|
+
if (seq === persistSeq.current) setError(String(err.message || err));
|
|
651
|
+
} finally {
|
|
652
|
+
if (seq === persistSeq.current) setBusy(false);
|
|
653
|
+
}
|
|
654
|
+
};
|
|
655
|
+
|
|
656
|
+
const saveFlags = () => persistFlags({});
|
|
657
|
+
|
|
658
|
+
const sidecarGenerate = async () => {
|
|
659
|
+
setBusy(true);
|
|
660
|
+
setSaved(false);
|
|
661
|
+
setError("");
|
|
662
|
+
try {
|
|
663
|
+
await api("/api/dsh-trivium/sidecar/generate", { method: "POST" });
|
|
664
|
+
setSaved(true);
|
|
665
|
+
await load();
|
|
666
|
+
} catch (err) {
|
|
667
|
+
setError(String(err.message || err));
|
|
668
|
+
} finally {
|
|
669
|
+
setBusy(false);
|
|
670
|
+
}
|
|
671
|
+
};
|
|
672
|
+
|
|
673
|
+
const sidecarDelete = async () => {
|
|
674
|
+
if (!window.confirm(t("gitSidecarDeleteConfirm"))) return;
|
|
675
|
+
setBusy(true);
|
|
676
|
+
setSaved(false);
|
|
677
|
+
setError("");
|
|
678
|
+
try {
|
|
679
|
+
await api("/api/dsh-trivium/sidecar/delete", { method: "POST" });
|
|
498
680
|
setSaved(true);
|
|
499
681
|
await load();
|
|
500
682
|
} catch (err) {
|
|
@@ -683,7 +865,10 @@ window.__ModuleLoader__.load({
|
|
|
683
865
|
type: "radio",
|
|
684
866
|
name: "dsh-trivium-recall",
|
|
685
867
|
checked: recallMode === value,
|
|
686
|
-
onChange: () =>
|
|
868
|
+
onChange: () => {
|
|
869
|
+
setRecallMode(value);
|
|
870
|
+
persistFlags({ recallMode: value });
|
|
871
|
+
},
|
|
687
872
|
style: { marginTop: 3 },
|
|
688
873
|
}),
|
|
689
874
|
jsxs("span", {
|
|
@@ -695,6 +880,25 @@ window.__ModuleLoader__.load({
|
|
|
695
880
|
],
|
|
696
881
|
});
|
|
697
882
|
|
|
883
|
+
const localeRadio = (value, label) =>
|
|
884
|
+
jsxs("label", {
|
|
885
|
+
style: ui.radio,
|
|
886
|
+
children: [
|
|
887
|
+
jsx("input", {
|
|
888
|
+
type: "radio",
|
|
889
|
+
name: "dsh-trivium-plugin-locale",
|
|
890
|
+
checked: pluginLocale === value,
|
|
891
|
+
onChange: () => {
|
|
892
|
+
setPluginLocale(value);
|
|
893
|
+
setPluginLocalePref(value);
|
|
894
|
+
persistFlags({ pluginLocale: value });
|
|
895
|
+
},
|
|
896
|
+
style: { marginTop: 3 },
|
|
897
|
+
}),
|
|
898
|
+
jsx("span", { style: { fontWeight: 600 }, children: label }),
|
|
899
|
+
],
|
|
900
|
+
});
|
|
901
|
+
|
|
698
902
|
return jsxs("div", {
|
|
699
903
|
style: ui.page,
|
|
700
904
|
children: [
|
|
@@ -792,6 +996,54 @@ window.__ModuleLoader__.load({
|
|
|
792
996
|
}),
|
|
793
997
|
],
|
|
794
998
|
}),
|
|
999
|
+
jsxs("div", {
|
|
1000
|
+
style: ui.card,
|
|
1001
|
+
children: [
|
|
1002
|
+
jsxs("button", {
|
|
1003
|
+
type: "button",
|
|
1004
|
+
onClick: () => {
|
|
1005
|
+
const on = !configPanelOpen;
|
|
1006
|
+
setConfigPanelOpen(on);
|
|
1007
|
+
persistFlags({ configPanelOpen: on });
|
|
1008
|
+
},
|
|
1009
|
+
style: {
|
|
1010
|
+
display: "flex",
|
|
1011
|
+
alignItems: "center",
|
|
1012
|
+
justifyContent: "space-between",
|
|
1013
|
+
gap: 8,
|
|
1014
|
+
width: "100%",
|
|
1015
|
+
margin: 0,
|
|
1016
|
+
padding: 0,
|
|
1017
|
+
border: 0,
|
|
1018
|
+
background: "transparent",
|
|
1019
|
+
color: "inherit",
|
|
1020
|
+
font: "inherit",
|
|
1021
|
+
cursor: "pointer",
|
|
1022
|
+
textAlign: "left",
|
|
1023
|
+
},
|
|
1024
|
+
children: [
|
|
1025
|
+
jsx("span", { style: ui.cardTitle, children: L.configPanel }),
|
|
1026
|
+
jsx("span", {
|
|
1027
|
+
style: { fontSize: 12, opacity: 0.65 },
|
|
1028
|
+
children: configPanelOpen ? L.configPanelClose : L.configPanelOpen,
|
|
1029
|
+
}),
|
|
1030
|
+
],
|
|
1031
|
+
}),
|
|
1032
|
+
jsx("div", { style: ui.hint, children: L.configPanelHint }),
|
|
1033
|
+
configPanelOpen
|
|
1034
|
+
? jsxs("div", {
|
|
1035
|
+
style: { display: "flex", flexDirection: "column", gap: 10 },
|
|
1036
|
+
children: [
|
|
1037
|
+
jsxs("div", {
|
|
1038
|
+
style: ui.card,
|
|
1039
|
+
children: [
|
|
1040
|
+
jsx("div", { style: ui.cardTitle, children: L.pluginLocale }),
|
|
1041
|
+
jsx("div", { style: ui.hint, children: L.pluginLocaleHint }),
|
|
1042
|
+
localeRadio("host", L.pluginLocaleHost),
|
|
1043
|
+
localeRadio("zh", L.pluginLocaleZh),
|
|
1044
|
+
localeRadio("en", L.pluginLocaleEn),
|
|
1045
|
+
],
|
|
1046
|
+
}),
|
|
795
1047
|
jsxs("div", {
|
|
796
1048
|
style: ui.card,
|
|
797
1049
|
children: [
|
|
@@ -811,7 +1063,11 @@ window.__ModuleLoader__.load({
|
|
|
811
1063
|
jsx("input", {
|
|
812
1064
|
type: "checkbox",
|
|
813
1065
|
checked: extractEnabled,
|
|
814
|
-
onChange: (e) =>
|
|
1066
|
+
onChange: (e) => {
|
|
1067
|
+
const on = e.target.checked;
|
|
1068
|
+
setExtractEnabled(on);
|
|
1069
|
+
persistFlags({ extractEnabled: on });
|
|
1070
|
+
},
|
|
815
1071
|
}),
|
|
816
1072
|
jsx("span", { children: L.extract }),
|
|
817
1073
|
],
|
|
@@ -828,7 +1084,11 @@ window.__ModuleLoader__.load({
|
|
|
828
1084
|
jsx("input", {
|
|
829
1085
|
type: "checkbox",
|
|
830
1086
|
checked: chipsEnabled,
|
|
831
|
-
onChange: (e) =>
|
|
1087
|
+
onChange: (e) => {
|
|
1088
|
+
const on = e.target.checked;
|
|
1089
|
+
setChipsEnabled(on);
|
|
1090
|
+
persistFlags({ chipsEnabled: on });
|
|
1091
|
+
},
|
|
832
1092
|
}),
|
|
833
1093
|
jsx("span", { children: L.chipsSetting }),
|
|
834
1094
|
],
|
|
@@ -841,7 +1101,11 @@ window.__ModuleLoader__.load({
|
|
|
841
1101
|
type: "checkbox",
|
|
842
1102
|
checked: sessionLayerEnabled,
|
|
843
1103
|
disabled: !chipsEnabled,
|
|
844
|
-
onChange: (e) =>
|
|
1104
|
+
onChange: (e) => {
|
|
1105
|
+
const on = e.target.checked;
|
|
1106
|
+
setSessionLayerEnabled(on);
|
|
1107
|
+
persistFlags({ sessionLayerEnabled: on });
|
|
1108
|
+
},
|
|
845
1109
|
}),
|
|
846
1110
|
jsx("span", { children: L.sessionLayer }),
|
|
847
1111
|
],
|
|
@@ -849,6 +1113,52 @@ window.__ModuleLoader__.load({
|
|
|
849
1113
|
jsx("div", { style: { ...ui.hint, paddingLeft: 22 }, children: L.sessionLayerHint }),
|
|
850
1114
|
],
|
|
851
1115
|
}),
|
|
1116
|
+
jsxs("div", {
|
|
1117
|
+
style: ui.card,
|
|
1118
|
+
children: [
|
|
1119
|
+
jsxs("label", {
|
|
1120
|
+
style: ui.switch,
|
|
1121
|
+
onClick: (e) => {
|
|
1122
|
+
e.preventDefault();
|
|
1123
|
+
if (busy) return;
|
|
1124
|
+
const on = !gitSidecarEnabled;
|
|
1125
|
+
setGitSidecarEnabled(on);
|
|
1126
|
+
persistFlags({ gitSidecarEnabled: on });
|
|
1127
|
+
},
|
|
1128
|
+
children: [
|
|
1129
|
+
jsx("input", {
|
|
1130
|
+
type: "checkbox",
|
|
1131
|
+
checked: gitSidecarEnabled,
|
|
1132
|
+
disabled: busy,
|
|
1133
|
+
onChange: () => {},
|
|
1134
|
+
}),
|
|
1135
|
+
jsx("span", { children: L.gitSidecar }),
|
|
1136
|
+
],
|
|
1137
|
+
}),
|
|
1138
|
+
jsx("div", { style: ui.hint, children: L.gitSidecarHint }),
|
|
1139
|
+
jsxs("div", {
|
|
1140
|
+
style: { display: "flex", flexWrap: "wrap", gap: 8 },
|
|
1141
|
+
children: [
|
|
1142
|
+
jsx(Button, {
|
|
1143
|
+
type: "button",
|
|
1144
|
+
variant: "outline",
|
|
1145
|
+
size: "sm",
|
|
1146
|
+
disabled: busy || !gitSidecarEnabled,
|
|
1147
|
+
onClick: sidecarGenerate,
|
|
1148
|
+
children: L.gitSidecarGenerate,
|
|
1149
|
+
}),
|
|
1150
|
+
jsx(Button, {
|
|
1151
|
+
type: "button",
|
|
1152
|
+
variant: "outline",
|
|
1153
|
+
size: "sm",
|
|
1154
|
+
disabled: busy || gitSidecarEnabled,
|
|
1155
|
+
onClick: sidecarDelete,
|
|
1156
|
+
children: L.gitSidecarDelete,
|
|
1157
|
+
}),
|
|
1158
|
+
],
|
|
1159
|
+
}),
|
|
1160
|
+
],
|
|
1161
|
+
}),
|
|
852
1162
|
jsxs("div", {
|
|
853
1163
|
style: ui.card,
|
|
854
1164
|
children: [
|
|
@@ -892,7 +1202,11 @@ window.__ModuleLoader__.load({
|
|
|
892
1202
|
jsx("input", {
|
|
893
1203
|
type: "checkbox",
|
|
894
1204
|
checked: embeddingEnabled,
|
|
895
|
-
onChange: (e) =>
|
|
1205
|
+
onChange: (e) => {
|
|
1206
|
+
const on = e.target.checked;
|
|
1207
|
+
setEmbeddingEnabled(on);
|
|
1208
|
+
persistFlags({ embeddingEnabled: on });
|
|
1209
|
+
},
|
|
896
1210
|
}),
|
|
897
1211
|
jsx("span", { children: L.embed }),
|
|
898
1212
|
],
|
|
@@ -950,6 +1264,11 @@ window.__ModuleLoader__.load({
|
|
|
950
1264
|
}),
|
|
951
1265
|
jsx("div", { style: ui.hint, children: L.embedKeyHint }),
|
|
952
1266
|
],
|
|
1267
|
+
}),
|
|
1268
|
+
],
|
|
1269
|
+
})
|
|
1270
|
+
: null,
|
|
1271
|
+
],
|
|
953
1272
|
}),
|
|
954
1273
|
jsxs("div", {
|
|
955
1274
|
style: ui.card,
|
|
@@ -2293,6 +2612,22 @@ window.__ModuleLoader__.load({
|
|
|
2293
2612
|
load();
|
|
2294
2613
|
}, [load, lineageKey]);
|
|
2295
2614
|
|
|
2615
|
+
react.useEffect(
|
|
2616
|
+
() =>
|
|
2617
|
+
subscribeChipView((hint) => {
|
|
2618
|
+
if (hint && typeof hint.sessionLayerEnabled === "boolean") {
|
|
2619
|
+
const layer = hint.sessionLayerEnabled;
|
|
2620
|
+
setSessionLayer(layer);
|
|
2621
|
+
if (!layer) {
|
|
2622
|
+
setNodes([]);
|
|
2623
|
+
setEdges([]);
|
|
2624
|
+
}
|
|
2625
|
+
}
|
|
2626
|
+
load();
|
|
2627
|
+
}),
|
|
2628
|
+
[load],
|
|
2629
|
+
);
|
|
2630
|
+
|
|
2296
2631
|
const { chain, kids } = react.useMemo(
|
|
2297
2632
|
() => layoutChain(nodes, edges, sessionId, liveSessions),
|
|
2298
2633
|
[nodes, edges, sessionId, liveSessions],
|
|
@@ -2932,7 +3267,7 @@ window.__ModuleLoader__.load({
|
|
|
2932
3267
|
}
|
|
2933
3268
|
|
|
2934
3269
|
function registerChipView(ctx, sessions) {
|
|
2935
|
-
ctx.slots.inject(
|
|
3270
|
+
return ctx.slots.inject(
|
|
2936
3271
|
"conversation.view",
|
|
2937
3272
|
() => {
|
|
2938
3273
|
const chatStore = sharedChatStore(ctx);
|
|
@@ -2972,7 +3307,6 @@ window.__ModuleLoader__.load({
|
|
|
2972
3307
|
SessionMapView,
|
|
2973
3308
|
);
|
|
2974
3309
|
},
|
|
2975
|
-
"dsh-trivium: chips",
|
|
2976
3310
|
);
|
|
2977
3311
|
}
|
|
2978
3312
|
|
|
@@ -2981,13 +3315,13 @@ window.__ModuleLoader__.load({
|
|
|
2981
3315
|
const sessions = ctx.sessions;
|
|
2982
3316
|
try {
|
|
2983
3317
|
const snap = ctx.locale && typeof ctx.locale.getLocale === "function" ? ctx.locale.getLocale() : null;
|
|
2984
|
-
if (snap && snap.active)
|
|
3318
|
+
if (snap && snap.active) setHostLocale(snap.active);
|
|
2985
3319
|
} catch {
|
|
2986
3320
|
// host may not expose locale
|
|
2987
3321
|
}
|
|
2988
3322
|
try {
|
|
2989
3323
|
ctx.on("locale/change", (snap) => {
|
|
2990
|
-
if (snap && snap.active)
|
|
3324
|
+
if (snap && snap.active) setHostLocale(snap.active);
|
|
2991
3325
|
});
|
|
2992
3326
|
} catch {
|
|
2993
3327
|
// ignore
|
|
@@ -3007,14 +3341,9 @@ window.__ModuleLoader__.load({
|
|
|
3007
3341
|
),
|
|
3008
3342
|
"dsh-trivium: settings section",
|
|
3009
3343
|
);
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
if (st && st.chipsEnabled === true) registerChipView(ctx, sessions);
|
|
3014
|
-
})
|
|
3015
|
-
.catch(() => {
|
|
3016
|
-
// default off: no title-bar tab
|
|
3017
|
-
});
|
|
3344
|
+
chipUi.ctx = ctx;
|
|
3345
|
+
chipUi.sessions = sessions;
|
|
3346
|
+
syncChipsTabFromServer();
|
|
3018
3347
|
}
|
|
3019
3348
|
|
|
3020
3349
|
exports.apply = apply;
|
package/lib/index.js
CHANGED
|
@@ -24,6 +24,7 @@ import { applyRecallMode, chipsEnabledOf, recallModeOf, sessionLayerEnabledOf }
|
|
|
24
24
|
import { configureEmbedding } from "./embed.js";
|
|
25
25
|
import { recordCheckpoint, ensureTail, syncForkLineage } from "./episode.js";
|
|
26
26
|
import { buildPinInject } from "./pins.js";
|
|
27
|
+
import { syncSidecarOnOpen } from "./sidecar.js";
|
|
27
28
|
|
|
28
29
|
export const name = "dsh-trivium";
|
|
29
30
|
export const inject = ["tools"];
|
|
@@ -35,6 +36,9 @@ const DEFAULTS = {
|
|
|
35
36
|
extractEnabled: true,
|
|
36
37
|
chipsEnabled: false,
|
|
37
38
|
sessionLayerEnabled: false,
|
|
39
|
+
gitSidecarEnabled: false,
|
|
40
|
+
pluginLocale: "host",
|
|
41
|
+
configPanelOpen: false,
|
|
38
42
|
writeApproval: false,
|
|
39
43
|
mapTokenBudget: 400,
|
|
40
44
|
expandDepth: 1,
|
|
@@ -282,6 +286,11 @@ export function apply(ctx, config = {}) {
|
|
|
282
286
|
const cwd = ready?.cwd || cwdOf(agent);
|
|
283
287
|
const db = ready?.db || (await openWorkspaceDb(cwd));
|
|
284
288
|
setActiveCwd(cwd);
|
|
289
|
+
try {
|
|
290
|
+
await syncSidecarOnOpen(cwd, db);
|
|
291
|
+
} catch (err) {
|
|
292
|
+
log.warn?.(`[dsh-trivium] sidecar sync skipped: ${err.message}`);
|
|
293
|
+
}
|
|
285
294
|
try {
|
|
286
295
|
const session = agent.session;
|
|
287
296
|
const sessionId = sessionKey(session);
|