prts-terrarchive 0.2.0 → 0.2.2
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.en.md +84 -18
- package/README.md +64 -15
- package/THIRD_PARTY_NOTICES.md +10 -0
- package/bin/build-runtime.mjs +32 -0
- package/bin/check-runtime.mjs +56 -0
- package/bin/install.js +24 -5
- package/contracts/corpus_i18n_v1.schema.json +10 -10
- package/cordis.patch.yml +4 -4
- package/docs/web-access.md +24 -0
- package/lib/client.js +84 -23
- package/lib/rhine/rhine.css +1 -1
- package/lib/rhine/rhine.js +208 -208
- package/lib/runtime/licenses/js-yaml-MIT.txt +21 -0
- package/lib/runtime/licenses/zod-MIT.txt +21 -0
- package/lib/runtime/versions.json +4 -0
- package/lib/runtime/yaml.js +3062 -0
- package/lib/runtime/zod.js +14356 -0
- package/lib/skins/common.css +59 -0
- package/lib/skins/endfield-aic.css +22 -9
- package/lib/skins/prts-agent.css +15 -5
- package/lib/skins/rhine-lab.css +9 -0
- package/package.json +15 -8
- package/presets/composition.js +53 -0
- package/presets/definition.js +2 -2
- package/presets/prts/agent.cordis.yml +1 -1
- package/presets/prts/preset.yml +1 -1
- package/presets/register.js +23 -10
- package/resources/runtime/yaml.js +1 -0
- package/resources/runtime/zod.js +1 -0
- package/skills/prts-composition/SKILL.md +60 -0
- package/skills/prts-investigation/SKILL.md +19 -102
- package/skills/prts-investigation/references/board-guide.md +131 -0
- package/skills/prts-retrieval/SKILL.md +5 -3
- package/src/composition-skill.js +19 -0
- package/src/i18n.js +11 -17
- package/src/index.js +63 -81
- package/src/investigation-review.js +14 -6
- package/src/investigation-store.js +97 -25
- package/src/investigation-tools.js +67 -30
- package/src/investigation-validation.js +33 -0
- package/src/manual-search.js +1 -1
- package/src/skill.js +25 -16
- package/src/skin-capabilities.js +28 -0
- package/src/tools.js +13 -0
- package/src/web-guidance.js +44 -0
- package/ui/rhine/archive-rack.ts +10 -8
- package/ui/rhine/catalogue.ts +16 -4
- package/ui/rhine/evidence-board-panel.ts +15 -0
- package/ui/rhine/investigation-board.css +3 -0
- package/ui/rhine/investigation-board.ts +71 -24
- package/ui/rhine/investigation-history.ts +15 -0
- package/ui/rhine/reading-room.css +14 -3
- package/ui/rhine/scene.ts +44 -24
- package/ui/rhine/tool-activity.ts +13 -6
- package/ui/rhine/types.ts +6 -0
- package/ui/rhine/workbench.ts +82 -40
package/ui/rhine/workbench.ts
CHANGED
|
@@ -102,6 +102,7 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
102
102
|
const quality = { ...WORKBENCH_QUALITY };
|
|
103
103
|
const navigationLimiter = new ArchiveNavigationLimiter();
|
|
104
104
|
let manualSources: ArchiveSource[] = [];
|
|
105
|
+
let restoredSources: ArchiveSource[] = [];
|
|
105
106
|
let extracts: Extract[] = [];
|
|
106
107
|
let sources: ArchiveSource[] = [];
|
|
107
108
|
let discoveredSources: ArchiveSource[] = [];
|
|
@@ -190,6 +191,7 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
190
191
|
let navigationHint: { axis: 'row' | 'lane'; direction: number } | undefined;
|
|
191
192
|
let hostState: RhineHostState | undefined = options.host?.getState();
|
|
192
193
|
let hostActionBusy = false;
|
|
194
|
+
let hostCancelBusy = false;
|
|
193
195
|
let hostActionError = '';
|
|
194
196
|
let hostRetry: (() => Promise<void>) | undefined;
|
|
195
197
|
let hostTrigger: HTMLElement | null = null;
|
|
@@ -273,8 +275,8 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
273
275
|
</section>
|
|
274
276
|
<section class="rhine-desk-panel" aria-label="本次调查档案架" hidden>
|
|
275
277
|
<div class="tiny-label">EVIDENCE RACK / <span class="rhine-desk-count">00</span></div><h2>调查档案架</h2><p class="rhine-rack-intro">选择标题定位档案,抽取后阅读原文。</p><label class="rhine-shelf-search"><span aria-hidden="true">⌕</span><input class="rhine-shelf-filter" type="search" placeholder="在全部档案中筛选标题、内容…" aria-label="筛选全部档案"/><button type="button" class="rhine-shelf-clear" hidden aria-label="清除档案筛选">×</button></label><div class="rhine-rack-range" role="status"></div>
|
|
276
|
-
<div class="rhine-shelf-current"><span class="rhine-shelf-number">S-000</span><h3 class="rhine-shelf-title">等待第一份资料</h3><div class="rhine-shelf-meta"></div><p class="rhine-shelf-excerpt"
|
|
277
|
-
<div class="rhine-shelf-navigation"><button type="button" class="rhine-shelf-prev" aria-label="翻阅上一份资料">←</button><div class="rhine-desk-list" role="group" aria-label="档案标题选择列表"></div><button type="button" class="rhine-shelf-next" aria-label="翻阅下一份资料">→</button></div><div class="rhine-desk-pagination"></div><button type="button" class="rhine-rack-directory"
|
|
278
|
+
<div class="rhine-shelf-current"><span class="rhine-shelf-number">S-000</span><h3 class="rhine-shelf-title">等待第一份资料</h3><div class="rhine-shelf-meta"></div><p class="rhine-shelf-excerpt">已交付给 Agent 的资料与手动收藏,留在这里供回查;入架不代表已读原文。</p><label class="rhine-evidence-target"><span>证据盒归属</span><select aria-label="证据盒归属" disabled><option>正在读取调查板…</option></select></label><div class="rhine-priority-actions"><button type="button" class="rhine-shelf-open">抽取阅读 <span>↗</span></button><button type="button" class="rhine-shelf-stage">+ 放入重点证据盒</button></div></div>
|
|
279
|
+
<div class="rhine-shelf-navigation"><button type="button" class="rhine-shelf-prev" aria-label="翻阅上一份资料">←</button><div class="rhine-desk-list" role="group" aria-label="档案标题选择列表"></div><button type="button" class="rhine-shelf-next" aria-label="翻阅下一份资料">→</button></div><div class="rhine-desk-pagination"></div><button type="button" class="rhine-rack-directory">档案架目录 <span>↗</span></button>
|
|
278
280
|
<div class="rhine-rack-legend"><span data-state="found">查得</span><span data-state="read">Agent 已读</span><span data-state="cited">已引用</span><span data-state="saved">手动收藏</span></div><button type="button" class="rhine-shelf-report" hidden>调查报告 <span>↗</span></button>
|
|
279
281
|
</section>
|
|
280
282
|
<button type="button" class="rhine-location-button"><span class="rhine-location-title">调查档案架 <b>→</b></span><span class="rhine-location-count">00</span></button>
|
|
@@ -286,7 +288,7 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
286
288
|
<form class="rhine-agent-form" aria-label="向 Agent 提问">
|
|
287
289
|
<div class="rhine-agent-heading"><label for="rhine-agent-question">ASK THE ARCHIVE</label><div class="rhine-agent-settings" aria-label="调查配置" hidden><button type="button" class="rhine-session-mode" aria-haspopup="dialog"><small>MODE</small><span>选择模式</span><i aria-hidden="true">⌄</i></button><button type="button" class="rhine-session-model" aria-haspopup="dialog"><small>MODEL</small><span>选择模型</span><i aria-hidden="true">⌄</i></button></div><span class="rhine-agent-availability">AGENT / READY</span></div>
|
|
288
290
|
<div class="rhine-agent-field"><span aria-hidden="true">⌕</span><input id="rhine-agent-question" type="text" autocomplete="off" placeholder="输入问题,交给 Agent 调查…" maxlength="3000" aria-label="调查问题"/><button type="button" class="rhine-agent-cancel" hidden aria-label="停止当前任务">■ 停止</button><button type="submit" class="rhine-agent-submit" aria-label="提交调查问题">SEND <span>↗</span></button></div>
|
|
289
|
-
<div class="rhine-agent-board-context" title="查看或切换调查板不会改变 Agent 的工作板"></div><div class="rhine-agent-footer"><span class="rhine-agent-hint"
|
|
291
|
+
<div class="rhine-agent-board-context" title="查看或切换调查板不会改变 Agent 的工作板"></div><div class="rhine-agent-footer"><span class="rhine-agent-hint">资料交付给 Agent 后入架,已读与引用状态分别保留。</span><button type="button" class="rhine-manual-search">检索资料 <span>→</span></button></div>
|
|
290
292
|
<button type="button" class="rhine-session-alert" hidden aria-haspopup="dialog"><span>会话设置暂不可用</span><b>查看详情 ↗</b></button>
|
|
291
293
|
</form>
|
|
292
294
|
<section class="rhine-activity" aria-label="Agent 检索状态" hidden><span class="rhine-status-dot"></span><span class="rhine-status-title" role="status"></span><span class="rhine-activity-query"></span><span class="rhine-activity-detail"></span></section>
|
|
@@ -300,8 +302,8 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
300
302
|
</section>
|
|
301
303
|
<section class="rhine-basket modal-backdrop" aria-label="收藏与摘录" hidden><div class="terminal-modal rhine-basket-modal"><div class="modal-top"><span>RHINE LAB / RESEARCH EXTRACTS</span><button type="button" class="rhine-close-basket" aria-label="关闭收藏">CLOSE <span>×</span></button></div><h2>RESEARCH EXTRACTS<small>收藏与摘录 <span class="rhine-extract-count">00</span></small></h2><p class="rhine-panel-description">选取原文,保存线索和来源。摘录随你提交的调查问题一起发送。</p><div class="rhine-basket-list"></div><button type="button" class="rhine-send-extracts solid-button">将摘录交给 Agent ↗</button></div></section>
|
|
302
304
|
<section class="rhine-log modal-backdrop" aria-label="Agent 调查记录" hidden><div class="terminal-modal rhine-log-modal"><div class="modal-top"><span>RHINE LAB / INVESTIGATION RECORDS</span><button type="button" class="rhine-close-log" aria-label="关闭调查记录">CLOSE <span>×</span></button></div><h2>RESEARCH LOG<small>调查记录</small></h2><div class="rhine-log-status"></div><div class="rhine-log-content"><div class="rhine-log-sources"></div><div class="rhine-log-records-heading tiny-label">TOOL RECEIPTS / 工具调用记录</div><div class="rhine-log-records"></div><div class="rhine-log-answer"></div></div></div></section>
|
|
303
|
-
<section class="rhine-rack-index modal-backdrop" aria-label="调查资料目录" hidden><div class="terminal-modal rhine-rack-index-modal"><div class="modal-top"><span>RHINE LAB / EVIDENCE INDEX</span><button type="button" class="rhine-close-rack-index" aria-label="关闭调查资料目录">CLOSE <span>×</span></button></div><h2>档案架目录<small>Agent
|
|
304
|
-
<section class="rhine-report modal-backdrop" aria-label="
|
|
305
|
+
<section class="rhine-rack-index modal-backdrop" aria-label="调查资料目录" hidden><div class="terminal-modal rhine-rack-index-modal"><div class="modal-top"><span>RHINE LAB / EVIDENCE INDEX</span><button type="button" class="rhine-close-rack-index" aria-label="关闭调查资料目录">CLOSE <span>×</span></button></div><h2>档案架目录<small>Agent 上下文资料与手动收藏</small></h2><label class="search-field"><span>⌕</span><input class="rhine-rack-filter" type="search" autocomplete="off" placeholder="筛选资料标题、来源或内容" aria-label="筛选档案架资料"/></label><label class="rhine-evidence-target"><span>证据盒归属</span><select aria-label="证据盒归属" disabled><option>正在读取调查板…</option></select></label><div class="rhine-rack-index-list"></div><div class="rhine-rack-index-count" role="status"></div></div></section>
|
|
306
|
+
<section class="rhine-report modal-backdrop" aria-label="本轮答复" hidden><div class="terminal-modal rhine-report-modal"><div class="modal-top"><span>RHINE LAB / CONVERSATION</span><button type="button" class="rhine-close-report" aria-label="关闭本轮答复">返回调查 <span>×</span></button></div><header class="rhine-report-header"><div class="rhine-report-kicker tiny-label">RESEARCH REPORT</div><h2 class="rhine-report-title">调查报告</h2><div class="rhine-report-status" role="status"></div></header><div class="rhine-report-layout"><aside class="rhine-report-outline" aria-label="报告目录"><div class="tiny-label">CONTENTS / 目录</div><nav class="rhine-report-toc"></nav></aside><article class="rhine-report-body" tabindex="0" aria-label="Agent 回答"></article><aside class="rhine-report-references" aria-label="报告引用"><div class="rhine-report-sources"></div></aside></div><footer class="rhine-report-footer"><button type="button" class="rhine-report-rack">翻阅调查资料 <span>↗</span></button><span class="rhine-report-position"></span></footer></div></section>
|
|
305
307
|
<section class="rhine-session-panel modal-backdrop" role="dialog" aria-modal="true" aria-labelledby="rhine-session-heading" hidden><div class="terminal-modal rhine-session-modal"><div class="modal-top"><span>RHINE LAB / SESSION CONTROL</span><button type="button" class="rhine-close-session" aria-label="关闭对话管理">CLOSE <span>×</span></button></div><h2 id="rhine-session-heading">RESEARCH SESSIONS<small>对话与模式</small></h2><p class="rhine-session-workspace"></p><div class="rhine-session-error" role="alert" hidden><p></p><button type="button" class="rhine-session-retry">重试 ↗</button></div><div class="rhine-session-content"><section class="rhine-session-config" aria-label="对话设置"><div class="rhine-session-mode-field"><label for="rhine-mode-select">AGENT MODE <span>调查模式</span></label><div class="rhine-session-select-row"><select id="rhine-mode-select" aria-describedby="rhine-mode-description rhine-mode-hint"></select><button type="button" class="rhine-mode-apply">使用此模式</button></div><p id="rhine-mode-description"></p><p id="rhine-mode-hint"></p></div><div class="rhine-session-model-field" hidden><label for="rhine-model-select">MODEL <span>当前对话模型</span></label><div class="rhine-session-select-row"><select id="rhine-model-select"></select><button type="button" class="rhine-model-apply">切换模型</button></div></div></section><section class="rhine-session-history-section" aria-label="历史会话"><div class="rhine-session-list-heading"><span>SESSION ARCHIVE / 历史会话</span><button type="button" class="rhine-session-refresh">刷新 ↻</button></div><div class="rhine-session-list" tabindex="-1"></div></section></div><div class="rhine-session-modal-footer"><span class="rhine-session-notice" role="status"></span><button type="button" class="rhine-session-create solid-button">+ 新建对话</button></div></div></section>
|
|
306
308
|
<button type="button" class="rhine-completion-notice" aria-label="调查已完成,阅读报告" hidden><span>✓ 调查完成</span><strong>阅读调查报告</strong><b aria-hidden="true">↗</b></button><div class="rhine-completion-announcement" role="status" aria-live="polite"></div><div class="rhine-toast toast" role="status" hidden></div>
|
|
307
309
|
</div>
|
|
@@ -358,18 +360,18 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
358
360
|
let investigationReading: ReadingObject | null = null;
|
|
359
361
|
let investigationReturn = { fullscreen: false, kind: 'report' as 'report' | 'clue' | 'inbox' };
|
|
360
362
|
let evidenceTarget = 'auto';
|
|
361
|
-
let investigationContext: InvestigationContext = { sessionId: snapshot.sessionId, boards: [], selectedId: '', workingId: '', ready: false };
|
|
363
|
+
let investigationContext: InvestigationContext = { sessionId: snapshot.sessionId, boards: [], selectedId: '', workingId: '', ready: false, version:0, readOnly:false, reportAvailable:false };
|
|
362
364
|
let contextSignature = '';
|
|
363
365
|
let investigation: ReturnType<typeof mountInvestigationBoard> | undefined;
|
|
364
366
|
const archiveRack = createArchiveRack({ api: options.api,
|
|
365
|
-
changed(value) { manualSources=value;persist();mergeSources();updateReaderSave(); }, failed: toast });
|
|
367
|
+
changed(value) { restoredSources=value;manualSources=value.filter(source=>source.saved);persist();mergeSources();updateReaderSave(); }, failed: toast });
|
|
366
368
|
const boardPanel = mountEvidenceBoardPanel(stage, {
|
|
367
369
|
getCardBounds: id => scene?.getBoardCardBounds(id) || null,
|
|
368
370
|
managed: true,
|
|
371
|
+
isReadOnly: () => investigation?.getContext().readOnly === true,
|
|
369
372
|
sessionId: snapshot.sessionId,
|
|
370
373
|
onChange(cards) {
|
|
371
374
|
investigation?.userChange(cards);
|
|
372
|
-
$('.rhine-board-count').textContent = String(cards.length).padStart(2, '0');
|
|
373
375
|
},
|
|
374
376
|
onSelect(id) { scene?.selectBoardCard(id); },
|
|
375
377
|
onToolChange(tool) {
|
|
@@ -393,9 +395,9 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
393
395
|
investigation = mountInvestigationBoard(stage, {
|
|
394
396
|
sessionId: snapshot.sessionId, api: options.api, panel: boardPanel,
|
|
395
397
|
onRackRevision(revision) { void archiveRack.refresh(revision).catch(()=>{}); },
|
|
396
|
-
onCards(cards) { scene?.setBoardCards(cards); $('.rhine-board-count').textContent = String(
|
|
398
|
+
onCards(cards,total) { scene?.setBoardCards(cards); $('.rhine-board-count').textContent = String(total).padStart(2, '0'); },
|
|
397
399
|
openSource(source,inbox=false) { investigation?.holdReadingContext();investigationReturn={fullscreen:boardFullscreen,kind:inbox?'inbox':investigationReading?.kind||'report'};openSource(source,'investigation'); }, notify: toast,
|
|
398
|
-
onContext(value){investigationContext=value;renderInvestigationContext();},
|
|
400
|
+
onContext(value){investigationContext=value;renderInvestigationContext();renderSavedReportEntry();},
|
|
399
401
|
onInbox(value,open){if(open)boardPanel.closeTools();scene?.setEvidenceInbox(value,open);},
|
|
400
402
|
askInbox:options.agentAvailable===false?undefined:async(boardId,title)=>{await options.askAgent(`请继续整理调查板「${title}」(board_id: ${boardId})的重点证据盒。先读取这块板和 inbox,resume 同一调查;核对待整理资料,尤其是我手动选入的材料,将有依据的内容整理为线索。不要仅为清空盒子而生成线索。`);},
|
|
401
403
|
onReading(value) { investigationReading=value;syncReadingObject(); },
|
|
@@ -458,6 +460,7 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
458
460
|
const sourceMotion = new ReadCardMotion();
|
|
459
461
|
let agentReadFocus: ReturnType<typeof latestReadFocus>;
|
|
460
462
|
let followAgent = true;
|
|
463
|
+
let followPausedByUser = false;
|
|
461
464
|
const unseenReads = new Set<string>();
|
|
462
465
|
const observedReads = new Set<string>();
|
|
463
466
|
let activityTurn = '';
|
|
@@ -734,13 +737,14 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
734
737
|
updateArchiveSelection(next?.id || null, next ? archiveLane(next) : archiveLaneIndex, false);
|
|
735
738
|
}
|
|
736
739
|
function renderFollowMode() {
|
|
737
|
-
$('.rhine-follow-status').textContent = followAgent ? '跟随 Agent 查阅' :
|
|
740
|
+
$('.rhine-follow-status').textContent = followAgent ? '跟随 Agent 查阅' : `${followPausedByUser ? '已暂停跟随' : '手动浏览 · 下次查阅时跟随'}${unseenReads.size ? ` · 新查阅 ${unseenReads.size} 次` : ''}`;
|
|
738
741
|
$('.rhine-follow-toggle').textContent = followAgent ? '暂停跟随' : '恢复跟随 ↗';
|
|
739
742
|
$('.rhine-follow-toggle').setAttribute('aria-pressed', String(followAgent));
|
|
740
743
|
}
|
|
741
|
-
function setFollowAgent(value: boolean) {
|
|
744
|
+
function setFollowAgent(value: boolean, explicit = false) {
|
|
745
|
+
if (explicit || value) followPausedByUser = !value;
|
|
742
746
|
followAgent = value; scene?.setFollowAgent(value);
|
|
743
|
-
if (value) { unseenReads.clear(); if (agentReadFocus && !selectedSource) scene?.selectArchiveSource(agentReadFocus.source.id, false); }
|
|
747
|
+
if (value) { unseenReads.clear(); if (agentReadFocus && !selectedSource && location === 'archive') scene?.selectArchiveSource(agentReadFocus.source.id, false); }
|
|
744
748
|
renderFollowMode();
|
|
745
749
|
}
|
|
746
750
|
function selectArchiveSource(id: string) {
|
|
@@ -833,6 +837,7 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
833
837
|
}
|
|
834
838
|
function storageKey() { return `prts-rhine-desk:v1:${encodeURIComponent(snapshot.sessionId || 'default')}`; }
|
|
835
839
|
function loadSaved() {
|
|
840
|
+
restoredSources = [];
|
|
836
841
|
manualSources = [];
|
|
837
842
|
extracts = [];
|
|
838
843
|
try {
|
|
@@ -898,7 +903,7 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
898
903
|
const hostSessionNodes = new Map<string, HTMLButtonElement>();
|
|
899
904
|
function renderHostControls() { return performancePanel.capture.measureWork('host-controls', renderHostControlsBody); }
|
|
900
905
|
function renderHostControlsBody() {
|
|
901
|
-
const signature = JSON.stringify([hostState, hostActionBusy, hostActionError, extracting]);
|
|
906
|
+
const signature = JSON.stringify([hostState, hostActionBusy, hostCancelBusy, hostActionError, extracting]);
|
|
902
907
|
if (signature === hostPaintSignature) return;
|
|
903
908
|
hostPaintSignature = signature;
|
|
904
909
|
$('.rhine-session-controls').hidden = !options.host;
|
|
@@ -974,9 +979,17 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
974
979
|
for (const [id, entry] of hostSessionNodes) entry.disabled = busy || id === hostState.sessionId;
|
|
975
980
|
const cancel = $<HTMLButtonElement>('.rhine-agent-cancel');
|
|
976
981
|
cancel.hidden = !hostState.running;
|
|
977
|
-
cancel.disabled =
|
|
982
|
+
cancel.disabled = hostCancelBusy || Boolean(hostState.cancelling);
|
|
983
|
+
cancel.textContent = cancel.disabled ? '正在停止…' : '停止';
|
|
978
984
|
renderHostChoice();
|
|
979
985
|
}
|
|
986
|
+
async function cancelAgent() {
|
|
987
|
+
if (!options.host || hostCancelBusy || hostState?.cancelling || !hostState?.running) return;
|
|
988
|
+
hostCancelBusy = true; renderAgentControls();
|
|
989
|
+
try { await options.host.cancel(); }
|
|
990
|
+
catch (error) { if (!disposed) toast(plainError(error)); }
|
|
991
|
+
finally { if (!disposed) { hostCancelBusy = false; hostState = options.host.getState(); renderAgentControls(); } }
|
|
992
|
+
}
|
|
980
993
|
async function runHostAction(action: () => Promise<void>, closeOnSuccess = false) {
|
|
981
994
|
if (!options.host || hostBlocked() || extracting) return;
|
|
982
995
|
hostActionBusy = true; hostActionError = ''; hostRetry = undefined;
|
|
@@ -1027,6 +1040,23 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
1027
1040
|
scene?.setLocation(next);
|
|
1028
1041
|
syncMode(); renderStatus();
|
|
1029
1042
|
}
|
|
1043
|
+
function renderSavedReportEntry() {
|
|
1044
|
+
const saved=investigationContext.report, completed=investigationComplete();
|
|
1045
|
+
const reportEntry=$('.rhine-report-open');
|
|
1046
|
+
const visible=!!saved||investigationActivity(snapshot).showReport;
|
|
1047
|
+
reportEntry.hidden=!visible;$('.rhine-shelf-report').hidden=!visible;
|
|
1048
|
+
reportEntry.dataset.state=completed?'complete':snapshot.running?'running':snapshot.outcome==='interrupted'||snapshot.error?'error':'returned';
|
|
1049
|
+
$('.rhine-report-open strong').textContent=saved?'阅读调查报告':'阅读本轮答复';
|
|
1050
|
+
if(saved){
|
|
1051
|
+
$('.rhine-report-open-kicker').textContent=`SAVED REPORT / V${saved.version}`;
|
|
1052
|
+
$('.rhine-report-open-meta').textContent=`${saved.title} · ${saved.clues} 条依据 · ${saved.sources} 份来源`;
|
|
1053
|
+
}else{
|
|
1054
|
+
const received=mergeSourcesInOrder([],currentInvestigationSources());
|
|
1055
|
+
const citations=(snapshot.reportSources||received.filter(source=>source.state==='cited')).length;
|
|
1056
|
+
$('.rhine-report-open-kicker').textContent=completed?'✓ 调查完成 / REPORT READY':snapshot.running?'LIVE REPORT / 正在生成':snapshot.outcome==='interrupted'?'调查已停止 / 已返回内容':'RESEARCH REPORT / 已返回回答';
|
|
1057
|
+
$('.rhine-report-open-meta').textContent=`本轮查得 ${received.length} 份资料 · ${citations} 份引用${completed?' · 随时核对原文':''}`;
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1030
1060
|
function renderInvestigationContext() {
|
|
1031
1061
|
const context=investigationContext;
|
|
1032
1062
|
const signature=JSON.stringify([context,evidenceTarget]);
|
|
@@ -1056,7 +1086,9 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
1056
1086
|
function mergeSourcesBody(animate: boolean) {
|
|
1057
1087
|
uiUpdates.sourceMerges++;
|
|
1058
1088
|
activitySources = undefined;
|
|
1059
|
-
|
|
1089
|
+
// Snapshot sources are actual tool deliveries, also on older hosts without the flag.
|
|
1090
|
+
const delivered = (snapshot.sources || []).map(source => source.agentReceived ? source : { ...source, agentReceived: true });
|
|
1091
|
+
discoveredSources = mergeSourcesInOrder(discoveredSources, [...delivered, ...restoredSources, ...manualSources]);
|
|
1060
1092
|
sources = mergeSourcesInOrder(sources, discoveredSources.filter(belongsOnShelf));
|
|
1061
1093
|
const signature = JSON.stringify(sources);
|
|
1062
1094
|
scene?.setInvestigation(snapshot);
|
|
@@ -1142,15 +1174,15 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
1142
1174
|
deskPage = Math.min(deskPage, Math.max(0, Math.ceil(sources.length / SHELF_PAGE_SIZE) - 1));
|
|
1143
1175
|
const pageSources = sources.slice(deskPage * SHELF_PAGE_SIZE, (deskPage + 1) * SHELF_PAGE_SIZE);
|
|
1144
1176
|
const visible = query ? sources.filter(source => matchesSource(source, query)) : pageSources;
|
|
1145
|
-
$('.rhine-rack-range').textContent = query ? `全部档案 · 匹配 ${visible.length} / ${sources.length} 份` : sources.length ? `本架 ${deskPage * SHELF_PAGE_SIZE + 1}–${Math.min(sources.length, (deskPage + 1) * SHELF_PAGE_SIZE)} / 共 ${sources.length} 份资料` : 'Agent
|
|
1177
|
+
$('.rhine-rack-range').textContent = query ? `全部档案 · 匹配 ${visible.length} / ${sources.length} 份` : sources.length ? `本架 ${deskPage * SHELF_PAGE_SIZE + 1}–${Math.min(sources.length, (deskPage + 1) * SHELF_PAGE_SIZE)} / 共 ${sources.length} 份资料` : '资料交付给 Agent 或手动收藏后入架';
|
|
1146
1178
|
$('.rhine-shelf-clear').hidden = !query;
|
|
1147
|
-
$('.rhine-rack-directory').firstChild!.textContent =
|
|
1179
|
+
$('.rhine-rack-directory').firstChild!.textContent = `档案架目录 · ${sources.length} `;
|
|
1148
1180
|
if (!pageSources.some(source => source.id === shelfSelected)) shelfSelected = pageSources[0]?.id || null;
|
|
1149
1181
|
const focused = sources.find(source => source.id === shelfSelected);
|
|
1150
1182
|
$('.rhine-shelf-number').textContent = focused ? `已选 S-${String(sourceNumber(focused)).padStart(3, '0')} / ${shelfSlot(sources.indexOf(focused)).level === 0 ? '下层' : '上层'}` : 'NO SOURCES YET';
|
|
1151
1183
|
$('.rhine-shelf-title').textContent = focused?.title || '留一个位置,给下一条线索。';
|
|
1152
1184
|
$('.rhine-shelf-meta').textContent = focused ? `${kind(focused)} / ${origin(focused)} / ${state(focused)}${focused.saved ? ' / 已收藏' : ''}` : '';
|
|
1153
|
-
$('.rhine-shelf-excerpt').textContent = focused?.excerpt || (focused ? '抽取档案,查看完整原文和 Agent 实际读过的段落。' : 'Agent
|
|
1185
|
+
$('.rhine-shelf-excerpt').textContent = focused?.excerpt || (focused ? '抽取档案,查看完整原文和 Agent 实际读过的段落。' : '已交付给 Agent 的资料与手动收藏,留在这里供回查;入架不代表已读原文。');
|
|
1154
1186
|
$<HTMLButtonElement>('.rhine-shelf-open').disabled = !focused;
|
|
1155
1187
|
$<HTMLButtonElement>('.rhine-shelf-stage').disabled = !focused;
|
|
1156
1188
|
for (const selector of ['.rhine-shelf-prev', '.rhine-shelf-next']) $<HTMLButtonElement>(selector).disabled = visible.length < 2;
|
|
@@ -1172,7 +1204,7 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
1172
1204
|
slot.setAttribute('aria-pressed', String(source.id === shelfSelected));
|
|
1173
1205
|
if (list.children[position] !== slot) list.insertBefore(slot, list.children[position] || null);
|
|
1174
1206
|
});
|
|
1175
|
-
if (!visible.length) list.append(node('p', 'rhine-empty', query ? '没有匹配的档案,试试更短的标题或清除筛选。' : 'Agent
|
|
1207
|
+
if (!visible.length) list.append(node('p', 'rhine-empty', query ? '没有匹配的档案,试试更短的标题或清除筛选。' : '已交付给 Agent 或你主动收藏的资料,会按入架顺序显示在这里。'));
|
|
1176
1208
|
list.dataset.selected = shelfSelected || '';
|
|
1177
1209
|
if (previousSelected !== list.dataset.selected && location === 'desk') {
|
|
1178
1210
|
const chosen = shelfSelected && shelfChoiceNodes.get(shelfSelected);
|
|
@@ -1211,7 +1243,7 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
1211
1243
|
row.querySelector('span')!.textContent = `${kind(source)} · ${origin(source)} · ${state(source)} ↗`;
|
|
1212
1244
|
if (list.children[index] !== row) list.insertBefore(row, list.children[index] || null);
|
|
1213
1245
|
});
|
|
1214
|
-
if (!matches.length) list.append(node('p', 'rhine-empty', sources.length ? '没有匹配的资料,换一个关键词试试。' : 'Agent
|
|
1246
|
+
if (!matches.length) list.append(node('p', 'rhine-empty', sources.length ? '没有匹配的资料,换一个关键词试试。' : '已交付给 Agent 或你手动收藏的资料,会在这里按入架顺序显示。'));
|
|
1215
1247
|
$('.rhine-rack-index-count').textContent = `显示 ${matches.length} / ${sources.length} 份资料 · 点击标题打开原文`;
|
|
1216
1248
|
}
|
|
1217
1249
|
function openRackIndex() {
|
|
@@ -1546,7 +1578,7 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
1546
1578
|
basket.hidden = true;
|
|
1547
1579
|
resultsPanel.hidden = true;
|
|
1548
1580
|
syncModalState();
|
|
1549
|
-
toast('调查已交给 Agent
|
|
1581
|
+
toast('调查已交给 Agent,检索返回的资料会进入档案架。');
|
|
1550
1582
|
} catch (error) { if (!disposed && snapshot.sessionId === submissionSession) toast(`未能开始调查:${plainError(error)}`); }
|
|
1551
1583
|
finally { if (!disposed && snapshot.sessionId === submissionSession) { extracting = false; $<HTMLButtonElement>('.rhine-agent-submit').disabled = false; $<HTMLButtonElement>('.rhine-ask-agent').disabled = false; renderBasket(); renderStatus(); } }
|
|
1552
1584
|
}
|
|
@@ -1677,7 +1709,7 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
1677
1709
|
reportText = ''; reportSourceSignature = ''; reportTocSignature = '';
|
|
1678
1710
|
}
|
|
1679
1711
|
reportMeasure('report-header', () => {
|
|
1680
|
-
reportTextContent($('.rhine-report-title'),
|
|
1712
|
+
reportTextContent($('.rhine-report-title'), '本轮答复');
|
|
1681
1713
|
const completed = investigationComplete();
|
|
1682
1714
|
reportTextContent($('.rhine-report-kicker'), completed ? 'INVESTIGATION COMPLETE / 调查完成' : snapshot.running ? 'LIVE REPORT / 正在生成' : 'RESEARCH RECORD / 调查记录');
|
|
1683
1715
|
reportTextContent($('.rhine-report-status'), snapshot.error || (snapshot.running ? '内容随回答更新。你可以先阅读,或点右侧引用核对原文。' : completed ? '本轮调查已完成 · 点击目录跳转章节,点击引用查阅原文。' : snapshot.outcome === 'interrupted' ? '本轮调查已停止 · 以下保留停止前已返回的内容。' : '已返回的回答 · 来源可在右侧逐份查阅。'));
|
|
@@ -1742,7 +1774,20 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
1742
1774
|
if (report.hidden && (snapshot.running || !snapshot.answer || reportText === snapshot.answer && reportInvestigationKey === investigationKey())) return;
|
|
1743
1775
|
reportRenderTimer = window.setTimeout(() => { reportRenderTimer = undefined; if (!disposed) renderReport(); }, report.hidden || snapshot.running ? 180 : 0);
|
|
1744
1776
|
}
|
|
1745
|
-
function openReport(returning = false) {
|
|
1777
|
+
async function openReport(returning = false) {
|
|
1778
|
+
if (!returning && investigation) {
|
|
1779
|
+
try {
|
|
1780
|
+
const sessionId=snapshot.sessionId;
|
|
1781
|
+
const available=await investigation.prepareReport();
|
|
1782
|
+
if(disposed||snapshot.sessionId!==sessionId)return;
|
|
1783
|
+
if(available){
|
|
1784
|
+
reportViewedKey=investigationKey();syncCompletionNotice();
|
|
1785
|
+
setLocation('board');investigation.showReport();return;
|
|
1786
|
+
}
|
|
1787
|
+
} catch(error) { if(!disposed)toast(plainError(error));return; }
|
|
1788
|
+
}
|
|
1789
|
+
return reportMeasure('report-open', () => openReportBody(returning));
|
|
1790
|
+
}
|
|
1746
1791
|
function openReportBody(returning: boolean) {
|
|
1747
1792
|
if (!returning && document.activeElement instanceof HTMLElement && !report.contains(document.activeElement) && !readerReturn && !reader.contains(document.activeElement)) reportTrigger = document.activeElement;
|
|
1748
1793
|
// Populate while hidden so parsing/patching cannot repeatedly flush visible report layout.
|
|
@@ -1774,14 +1819,14 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
1774
1819
|
function syncToolActivityBody() {
|
|
1775
1820
|
const turn = `${snapshot.sessionId}:${snapshot.investigationId || ''}`;
|
|
1776
1821
|
if (activityTurn !== turn) {
|
|
1777
|
-
activityTurn = turn;
|
|
1822
|
+
activityTurn = turn;
|
|
1778
1823
|
sourceMotion.dispose();
|
|
1779
1824
|
}
|
|
1780
1825
|
const next = latestReadFocus(snapshot, activitySources ??= mergeSourcesInOrder(snapshot.sources || [], archiveSources));
|
|
1781
1826
|
const changed = Boolean(next && next.key !== agentReadFocus?.key);
|
|
1782
1827
|
for(const operation of snapshot.operations||[]){
|
|
1783
1828
|
if(operation.kind!=='read')continue;
|
|
1784
|
-
const key=`${
|
|
1829
|
+
const key=`${snapshot.sessionId}:${operation.id}`;
|
|
1785
1830
|
if(!observedReads.has(key)&&!followAgent&&activityInitialized)unseenReads.add(key);
|
|
1786
1831
|
observedReads.add(key);
|
|
1787
1832
|
}
|
|
@@ -1790,6 +1835,10 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
1790
1835
|
const operation = snapshot.operations?.find(call => call.id === agentReadFocus?.operation.id);
|
|
1791
1836
|
if (operation) agentReadFocus = { ...agentReadFocus, operation };
|
|
1792
1837
|
}
|
|
1838
|
+
// Manual navigation only holds the card until the next resolved Agent read.
|
|
1839
|
+
// An explicit pause remains sticky. The open reader is independent of this
|
|
1840
|
+
// card, so its document and scroll position never change during a new read.
|
|
1841
|
+
if (changed && !followAgent && !followPausedByUser) setFollowAgent(true);
|
|
1793
1842
|
updateArchiveSelection(archiveSelected, archiveLaneIndex, false);
|
|
1794
1843
|
renderFollowMode();
|
|
1795
1844
|
if (followAgent && changed && next?.operation.state !== 'error' && activityInitialized && snapshot.running && active && !document.hidden && !selectedSource)
|
|
@@ -1856,13 +1905,6 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
1856
1905
|
$('.rhine-found-count').textContent = String(received.length).padStart(2, '0');
|
|
1857
1906
|
$('.rhine-read-count').textContent = String(reads).padStart(2, '0');
|
|
1858
1907
|
$('.rhine-cited-count').textContent = String(citations).padStart(2, '0');
|
|
1859
|
-
$('.rhine-report-open').hidden = !activity.showReport;
|
|
1860
|
-
$('.rhine-shelf-report').hidden = !activity.showReport;
|
|
1861
|
-
const reportEntry = $('.rhine-report-open');
|
|
1862
|
-
reportEntry.dataset.state = completed ? 'complete' : snapshot.running ? 'running' : snapshot.outcome === 'interrupted' || snapshot.error ? 'error' : 'returned';
|
|
1863
|
-
$('.rhine-report-open-kicker').textContent = completed ? '✓ 调查完成 / REPORT READY' : snapshot.running ? 'LIVE REPORT / 正在生成' : snapshot.outcome === 'interrupted' ? '调查已停止 / 已返回内容' : 'RESEARCH REPORT / 已返回回答';
|
|
1864
|
-
$('.rhine-report-open strong').textContent = completed ? '阅读调查报告' : '查看已返回的回答';
|
|
1865
|
-
$('.rhine-report-open-meta').textContent = `本轮查得 ${received.length} 份资料 · ${citations} 份引用${completed ? ' · 随时核对原文' : ''}`;
|
|
1866
1908
|
if (completed && snapshot.answer && lastCompletedKey !== investigationKey()) {
|
|
1867
1909
|
lastCompletedKey = investigationKey();
|
|
1868
1910
|
if (hasRenderedStatus) {
|
|
@@ -1874,6 +1916,7 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
1874
1916
|
}
|
|
1875
1917
|
if (!completed) for (const selector of ['.rhine-report-open', '.rhine-completion-notice']) $(selector).classList.remove('is-new');
|
|
1876
1918
|
hasRenderedStatus = true;
|
|
1919
|
+
renderSavedReportEntry();
|
|
1877
1920
|
syncCompletionNotice();
|
|
1878
1921
|
$('.rhine-activity').hidden = location !== 'desk' || !running && !snapshot.error;
|
|
1879
1922
|
$('.rhine-status-title').textContent = searching ? 'RETRIEVING ARCHIVES' : snapshot.running ? 'INVESTIGATION IN PROGRESS' : 'INVESTIGATION / PAUSED';
|
|
@@ -1942,7 +1985,7 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
1942
1985
|
evidenceTarget=select.value;renderInvestigationContext();
|
|
1943
1986
|
});
|
|
1944
1987
|
$('.rhine-array-stage').addEventListener('click',()=>{const source=displayedArchiveSource;if(source)pinToBoard(source);});
|
|
1945
|
-
$('.rhine-follow-toggle').addEventListener('click',()=>{setFollowAgent(!followAgent);updateArchiveSelection(archiveSelected,archiveLaneIndex,false);});
|
|
1988
|
+
$('.rhine-follow-toggle').addEventListener('click',()=>{setFollowAgent(!followAgent, true);updateArchiveSelection(archiveSelected,archiveLaneIndex,false);});
|
|
1946
1989
|
$('.rhine-shelf-stage').addEventListener('click',()=>{const source=sources.find(item=>item.id===shelfSelected);if(source)pinToBoard(source);});
|
|
1947
1990
|
$('.rhine-shelf-open').addEventListener('click', () => { const source = sources.find(item => item.id === shelfSelected); if (source) void openSource(source); });
|
|
1948
1991
|
$('.rhine-agent-form').addEventListener('submit', event => { event.preventDefault(); void askAgent(); });
|
|
@@ -1963,7 +2006,7 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
1963
2006
|
}
|
|
1964
2007
|
});
|
|
1965
2008
|
$('.rhine-model-apply').addEventListener('click', () => { const model = modelSelect.value; if (options.host && hostState?.models.some(item => item.id === model)) void runHostAction(() => options.host!.selectModel(model)); });
|
|
1966
|
-
$('.rhine-agent-cancel').addEventListener('click', () => {
|
|
2009
|
+
$('.rhine-agent-cancel').addEventListener('click', () => { void cancelAgent(); });
|
|
1967
2010
|
modeSelect.addEventListener('change', renderHostChoice);
|
|
1968
2011
|
modelSelect.addEventListener('change', renderHostChoice);
|
|
1969
2012
|
$('.rhine-nav-close').addEventListener('click', options.close);
|
|
@@ -2058,7 +2101,6 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
2058
2101
|
syncMode();
|
|
2059
2102
|
stage.classList.toggle('reduce-motion', reducedMotion.matches);
|
|
2060
2103
|
root.dataset.location = location;
|
|
2061
|
-
const initialCatalogue = search(false, false);
|
|
2062
2104
|
|
|
2063
2105
|
// Keep the moment loading began as the history baseline. Fast reads that
|
|
2064
2106
|
// finish while the GLB loads are new activity, not historical playback.
|
|
@@ -2086,6 +2128,7 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
2086
2128
|
onLocationRequest: next => { setFollowAgent(false); setLocation(next); },
|
|
2087
2129
|
onInboxOpen:()=>investigation?.openInbox(),
|
|
2088
2130
|
onBoardSelect: (id, openEditor) => { if (!disposed) investigation?.select(id, openEditor); },
|
|
2131
|
+
isBoardReadOnly: () => investigation?.getContext().readOnly === true,
|
|
2089
2132
|
onBoardMove: (id, x, y) => { if (!disposed) boardPanel.moveCard(id, x, y); },
|
|
2090
2133
|
onBoardResize: (id, scale, x, y) => { if (!disposed) boardPanel.resizeCard(id, scale, x, y); },
|
|
2091
2134
|
onBoardAnchors: frame => { if (!disposed) { boardFrame = frame; investigation?.setBoardFrame(frame); syncBoardToolbar(); } },
|
|
@@ -2100,7 +2143,6 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
2100
2143
|
if (!value) return;
|
|
2101
2144
|
if (disposed || sceneStartupCancelled) { value.dispose(); return; }
|
|
2102
2145
|
scene = value;
|
|
2103
|
-
await initialCatalogue;
|
|
2104
2146
|
if (disposed || sceneStartupCancelled) return;
|
|
2105
2147
|
$('.rhine-loader-message').textContent = '正在准备模型与画面…';
|
|
2106
2148
|
scene.setFollowAgent(followAgent);
|
|
@@ -2151,6 +2193,7 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
2151
2193
|
const changedSession = changes.sessionChanged;
|
|
2152
2194
|
snapshot = next;
|
|
2153
2195
|
if (changedSession) {
|
|
2196
|
+
agentReadFocus = undefined; activityInitialized = false; activityTurn = '';
|
|
2154
2197
|
setBoardFullscreen(false);
|
|
2155
2198
|
evidenceTarget='auto';contextSignature='';
|
|
2156
2199
|
boardPanel.closeTools();
|
|
@@ -2168,7 +2211,7 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
2168
2211
|
setArrayListExpanded(false, true);
|
|
2169
2212
|
results = []; resultsPage = 0; deskPage = 0; searchCursor = undefined; searchDataVersion = undefined;
|
|
2170
2213
|
sources = []; discoveredSources = []; archiveSources = []; archiveSelected = null; shelfSelected = null;
|
|
2171
|
-
followAgent = true; unseenReads.clear(); observedReads.clear(); scene?.setFollowAgent(true);
|
|
2214
|
+
followAgent = true; followPausedByUser = false; unseenReads.clear(); observedReads.clear(); scene?.setFollowAgent(true);
|
|
2172
2215
|
archiveLaneIndex = 0; columnMemory.fill(null); catalogueLoaded = false;
|
|
2173
2216
|
sourceSignature = ''; input.value = ''; agentInput.value = ''; extracting = false;
|
|
2174
2217
|
readerBody.replaceChildren(); $('.rhine-reader-title').textContent = '';
|
|
@@ -2188,7 +2231,6 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
2188
2231
|
searchQuery = ''; searchError = ''; searchWarning = ''; manualSearch.resetMode(); searchMode = 'local';
|
|
2189
2232
|
scene?.setInvestigation(snapshot); scene?.setSources([], false); scene?.setArchiveSources([]);
|
|
2190
2233
|
setLocation('archive'); updateArchiveSelection(null, 0, false); renderDesk();
|
|
2191
|
-
void search(false, false);
|
|
2192
2234
|
visibleRecordCount = 20; recordNodes.clear(); $('.rhine-log-records').replaceChildren();
|
|
2193
2235
|
logSourcesSignature = logRecordsSignature = ''; activitySources = undefined;
|
|
2194
2236
|
loadSaved(); renderBasket();
|
|
@@ -2204,7 +2246,7 @@ export function mountRhineWorkbench(host: HTMLElement, options: RhineOptions): R
|
|
|
2204
2246
|
} finally { finishWork?.(); }
|
|
2205
2247
|
},
|
|
2206
2248
|
setActive(next: boolean) { active = next; if (!next) { cancelAnimationFrame(readerPositionFrame); readerPositionFrame = 0; } edgeNavigation?.sync(); performancePanel.setActive(next); scene?.setActive(next && !viewer?.isOpen); root.hidden = !next; if (next) { scheduleReportPosition(); scheduleReaderPosition(); } else { cancelAnimationFrame(reportPositionFrame); reportPositionFrame = 0; } if (next && viewer?.isOpen && !viewerFrame) viewerFrame = requestAnimationFrame(renderViewer); else if (!next) { cancelAnimationFrame(viewerFrame); viewerFrame = 0; } },
|
|
2207
|
-
stats() { return { uiUpdates: { ...uiUpdates }, hostBridge: options.host?.performanceStats?.() ?? null, snapshotBridge: options.snapshotDiagnostics?.performanceStats?.() ?? null, ...scene?.stats(), board: boardPanel.stats(), investigations: investigation?.stats(), boardFullscreen, navigation: navigationLimiter.stats(), quality: { ...quality }, sourceCount: sources.length, candidateCount: archiveSources.length, followAgent, unseenReads: unseenReads.size, displayedSourceId: displayedArchiveSource?.id, manualSourceCount: manualSources.length, extractCount: extracts.length, location, readerOpen: !reader.hidden, searchBusy, resultCount: results.length, reportOpen: !report.hidden, shelfSelected, deskPage, viewerOpen: Boolean(viewer?.isOpen), archiveIndex: archiveSelected }; },
|
|
2249
|
+
stats() { return { uiUpdates: { ...uiUpdates }, hostBridge: options.host?.performanceStats?.() ?? null, snapshotBridge: options.snapshotDiagnostics?.performanceStats?.() ?? null, ...scene?.stats(), board: boardPanel.stats(), investigations: investigation?.stats(), boardFullscreen, navigation: navigationLimiter.stats(), quality: { ...quality }, sourceCount: sources.length, candidateCount: archiveSources.length, followAgent, followPausedByUser, unseenReads: unseenReads.size, displayedSourceId: displayedArchiveSource?.id, manualSourceCount: manualSources.length, extractCount: extracts.length, location, readerOpen: !reader.hidden, searchBusy, resultCount: results.length, reportOpen: !report.hidden, shelfSelected, deskPage, viewerOpen: Boolean(viewer?.isOpen), archiveIndex: archiveSelected }; },
|
|
2208
2250
|
dispose() {
|
|
2209
2251
|
manualSearch.dispose();
|
|
2210
2252
|
if (disposed) return;
|