重构基线
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
// MNote UI 基础运行时:全局 portal 与 toast API。
|
||||
(function initMnoteUiRuntime() {
|
||||
if (window.__mnoteUiRuntimeStarted) return;
|
||||
window.__mnoteUiRuntimeStarted = true;
|
||||
|
||||
function ensurePortalRoot() {
|
||||
var root = document.getElementById('mnote-portal-root');
|
||||
if (root instanceof HTMLElement) return root;
|
||||
root = document.createElement('div');
|
||||
root.id = 'mnote-portal-root';
|
||||
root.setAttribute('data-mnote-portal-root', 'true');
|
||||
document.body.appendChild(root);
|
||||
return root;
|
||||
}
|
||||
|
||||
function ensureToastRegion() {
|
||||
var root = ensurePortalRoot();
|
||||
var region = root.querySelector('[data-mnote-toast-region="true"]');
|
||||
if (region instanceof HTMLElement) return region;
|
||||
region = document.createElement('div');
|
||||
region.className = 'mnote-toast-region';
|
||||
region.setAttribute('data-mnote-toast-region', 'true');
|
||||
region.setAttribute('role', 'status');
|
||||
region.setAttribute('aria-live', 'polite');
|
||||
root.appendChild(region);
|
||||
return region;
|
||||
}
|
||||
|
||||
function toast(message, options) {
|
||||
var text = String(message || '').trim();
|
||||
if (!text) return null;
|
||||
var config = options || {};
|
||||
var kind = String(config.kind || config.type || 'info').trim() || 'info';
|
||||
var timeoutMs = Number(config.timeoutMs || config.duration || 3200);
|
||||
if (!Number.isFinite(timeoutMs) || timeoutMs < 800) timeoutMs = 3200;
|
||||
var region = ensureToastRegion();
|
||||
var item = document.createElement('div');
|
||||
item.className = 'mnote-toast mnote-toast--' + kind;
|
||||
item.setAttribute('data-mnote-toast', 'true');
|
||||
item.setAttribute('data-kind', kind);
|
||||
item.textContent = text;
|
||||
region.appendChild(item);
|
||||
requestAnimationFrame(function showToast() {
|
||||
item.classList.add('mnote-toast--visible');
|
||||
});
|
||||
window.setTimeout(function hideToast() {
|
||||
item.classList.remove('mnote-toast--visible');
|
||||
window.setTimeout(function removeToast() {
|
||||
if (item.parentNode) item.parentNode.removeChild(item);
|
||||
}, 180);
|
||||
}, timeoutMs);
|
||||
return item;
|
||||
}
|
||||
|
||||
window.mnote = window.mnote || {};
|
||||
window.mnote.ensurePortalRoot = ensurePortalRoot;
|
||||
window.mnote.toast = toast;
|
||||
|
||||
window.addEventListener('mnote:toast', function onMnoteToast(event) {
|
||||
var detail = event && event.detail ? event.detail : {};
|
||||
toast(detail.message, detail);
|
||||
});
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', ensurePortalRoot, { once: true });
|
||||
} else {
|
||||
ensurePortalRoot();
|
||||
}
|
||||
})();
|
||||
@@ -123,6 +123,7 @@ export function createSidebarPageAiProfileRuntime(context) {
|
||||
}
|
||||
|
||||
function pageAiSessionAgentFilterValue(session) {
|
||||
if (String(session && session.source || '') === 'board' || session && session.workerPresetId) return 'board:mnote-page-ai';
|
||||
var agentId = pageAiNormalizeAgentId(session && session.agentId);
|
||||
if (agentId === 'reasonix') return 'reasonix';
|
||||
var profileId = String(session && (session.profileId || session.profile) || '').trim();
|
||||
@@ -131,6 +132,11 @@ export function createSidebarPageAiProfileRuntime(context) {
|
||||
}
|
||||
|
||||
function pageAiSessionAgentLabel(session) {
|
||||
if (String(session && session.source || '') === 'board' || session && session.workerPresetId) {
|
||||
var worker = String(session && session.workerPresetId || 'mnote-page-ai-zcode').trim();
|
||||
var model = String(session && session.modelOverride || '').trim();
|
||||
return 'Agent Board / ' + worker + (model ? ' / ' + model : '');
|
||||
}
|
||||
var agentId = pageAiNormalizeAgentId(session && session.agentId);
|
||||
if (agentId === 'reasonix') return pageAiAgentRecord(agentId).label || 'Reasonix';
|
||||
var profileId = String(session && (session.profileId || session.profile) || '').trim();
|
||||
|
||||
@@ -54,6 +54,16 @@ export function createSidebarPageAiRenderRuntime(context) {
|
||||
pageAiSkillSourceParts,
|
||||
pageAiToggleableSkillEntries,
|
||||
pageAiUsageSummary,
|
||||
pageAiBoardFirstEnabled,
|
||||
pageAiBoardWorkerOptions,
|
||||
pageAiBoardWorkflowOptions,
|
||||
pageAiBoardSelectedWorkerId,
|
||||
pageAiBoardSelectedWorkflowId,
|
||||
pageAiBoardWorkerLabel,
|
||||
pageAiBoardWorkflowLabel,
|
||||
pageAiBoardModelOptions,
|
||||
pageAiBoardSelectedModelOverride,
|
||||
pageAiBoardModelLabel,
|
||||
pageUiState,
|
||||
renderPageAiMarkdown,
|
||||
searchText,
|
||||
@@ -62,6 +72,18 @@ export function createSidebarPageAiRenderRuntime(context) {
|
||||
} = context;
|
||||
const PAGE_AI_CONTEXT_REF_REGISTRY = Array.isArray(contextRefRegistry) ? contextRefRegistry : [];
|
||||
|
||||
function pageAiLocalBoardFirstEnabled() {
|
||||
try {
|
||||
return window.localStorage ? window.localStorage.getItem('mnote.page_ai.legacy_provider_mode') !== '1' : true;
|
||||
} catch (_error) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function isPageAiBoardFirstEnabled() {
|
||||
return typeof pageAiBoardFirstEnabled === 'function' ? pageAiBoardFirstEnabled() : pageAiLocalBoardFirstEnabled();
|
||||
}
|
||||
|
||||
function pageAiTargetLabel(target) {
|
||||
var workspacePath = target && target.workspacePath && typeof target.workspacePath === 'object' ? target.workspacePath : {};
|
||||
var kind = String(target && (target.resourceKind || target.editorKind) || workspacePath.resourceKind || '').trim();
|
||||
@@ -430,6 +452,8 @@ export function createSidebarPageAiRenderRuntime(context) {
|
||||
|
||||
function renderPageAiProviderButtons() {
|
||||
var drawer = ensurePageAiDrawer();
|
||||
if (drawer.getAttribute('data-page-ai-opencode-host') === 'true') return;
|
||||
var boardFirst = isPageAiBoardFirstEnabled();
|
||||
var isAcp = pageUiState.pageAiAcpRuntime !== '';
|
||||
drawer.querySelectorAll('[data-page-ai-provider]').forEach(function(button) {
|
||||
var provider = button.getAttribute('data-page-ai-provider') || 'hermes';
|
||||
@@ -439,12 +463,14 @@ export function createSidebarPageAiRenderRuntime(context) {
|
||||
});
|
||||
var providerNode = drawer.querySelector('.wolai-page-ai-subtitle span:first-child');
|
||||
if (providerNode instanceof HTMLElement) {
|
||||
providerNode.textContent = pageAiAgentRecord(pageAiCurrentAgentId()).label;
|
||||
providerNode.textContent = boardFirst ? 'Agent Board' : pageAiAgentRecord(pageAiCurrentAgentId()).label;
|
||||
}
|
||||
}
|
||||
|
||||
function renderPageAiControls() {
|
||||
var drawer = ensurePageAiDrawer();
|
||||
if (drawer.getAttribute('data-page-ai-opencode-host') === 'true') return;
|
||||
var boardFirst = isPageAiBoardFirstEnabled();
|
||||
var isAcp = pageUiState.pageAiAcpRuntime !== '';
|
||||
var activeAgentId = pageAiCurrentAgentId();
|
||||
var activeProfile = pageAiCurrentProfile();
|
||||
@@ -456,19 +482,52 @@ export function createSidebarPageAiRenderRuntime(context) {
|
||||
documentRef.documentElement.setAttribute('data-mnote-page-ai-agent-id', activeAgentId);
|
||||
var agentButton = drawer.querySelector('[data-page-ai-agent-button]');
|
||||
var agentPopoverId = 'mnote-page-ai-agent-popover';
|
||||
var activeAgentLabel = pageAiCurrentAgentSelectionLabel();
|
||||
var activeAgentLabel = boardFirst && typeof pageAiBoardWorkerLabel === 'function'
|
||||
? pageAiBoardWorkerLabel() + ' / ' + (typeof pageAiBoardModelLabel === 'function' ? pageAiBoardModelLabel() : '默认')
|
||||
: pageAiCurrentAgentSelectionLabel();
|
||||
if (agentButton instanceof HTMLElement) {
|
||||
agentButton.textContent = 'AI';
|
||||
agentButton.textContent = boardFirst ? 'Board' : 'AI';
|
||||
agentButton.setAttribute('aria-expanded', pageUiState.pageAiAgentPopoverOpen ? 'true' : 'false');
|
||||
agentButton.setAttribute('aria-controls', agentPopoverId);
|
||||
agentButton.setAttribute('data-page-ai-agent-summary', activeAgentLabel);
|
||||
agentButton.setAttribute('aria-label', 'Agent:' + activeAgentLabel);
|
||||
agentButton.setAttribute('title', 'Agent:' + activeAgentLabel);
|
||||
agentButton.setAttribute('aria-label', (boardFirst ? '运行控制:' : 'Agent:') + activeAgentLabel);
|
||||
agentButton.setAttribute('title', (boardFirst ? '运行控制:' : 'Agent:') + activeAgentLabel);
|
||||
}
|
||||
var agentPopover = drawer.querySelector('[data-page-ai-agent-popover]');
|
||||
if (agentPopover instanceof HTMLElement) {
|
||||
agentPopover.id = agentPopoverId;
|
||||
agentPopover.hidden = !pageUiState.pageAiAgentPopoverOpen;
|
||||
if (boardFirst) {
|
||||
var selectedWorkerId = typeof pageAiBoardSelectedWorkerId === 'function' ? pageAiBoardSelectedWorkerId() : 'mnote-page-ai-zcode';
|
||||
var selectedWorkflowId = typeof pageAiBoardSelectedWorkflowId === 'function' ? pageAiBoardSelectedWorkflowId() : 'builtin-mnote-page-ai-chat';
|
||||
var workerOptions = typeof pageAiBoardWorkerOptions === 'function' ? pageAiBoardWorkerOptions() : [];
|
||||
var workflowOptions = typeof pageAiBoardWorkflowOptions === 'function' ? pageAiBoardWorkflowOptions() : [];
|
||||
var modelOptions = typeof pageAiBoardModelOptions === 'function' ? pageAiBoardModelOptions(selectedWorkerId) : [];
|
||||
var selectedModelOverride = typeof pageAiBoardSelectedModelOverride === 'function' ? pageAiBoardSelectedModelOverride() : 'zcode-default';
|
||||
var workerSelect = workerOptions.length > 1 ? '<label class="wolai-page-ai-profile-select"><span>Worker</span><select data-page-ai-board-worker>' + workerOptions.map(function(worker) {
|
||||
var id = String(worker.id || '').trim();
|
||||
var label = String(worker.name || worker.id || '').trim();
|
||||
var detail = [worker.agentType, worker.agentModel].filter(Boolean).join(' · ');
|
||||
return '<option value="' + escapeHtml(id) + '"' + (id === selectedWorkerId ? ' selected' : '') + '>' + escapeHtml([label, detail].filter(Boolean).join(' · ')) + '</option>';
|
||||
}).join('') + '</select></label>' : '<div class="wolai-page-ai-profile-select"><span>Worker</span><strong>' + escapeHtml(typeof pageAiBoardWorkerLabel === 'function' ? pageAiBoardWorkerLabel() : 'MNote 页面 AI · ZCode') + '</strong></div>';
|
||||
var workflowSelect = workflowOptions.length > 1 ? '<label class="wolai-page-ai-profile-select"><span>Workflow</span><select data-page-ai-board-workflow>' + workflowOptions.map(function(workflow) {
|
||||
var id = String(workflow.id || '').trim();
|
||||
var label = String(workflow.name || workflow.id || '').trim();
|
||||
return '<option value="' + escapeHtml(id) + '"' + (id === selectedWorkflowId ? ' selected' : '') + '>' + escapeHtml(label) + '</option>';
|
||||
}).join('') + '</select></label>' : '<div class="wolai-page-ai-profile-select"><span>Workflow</span><strong>' + escapeHtml(typeof pageAiBoardWorkflowLabel === 'function' ? pageAiBoardWorkflowLabel() : 'MNote 页面 AI') + '</strong></div>';
|
||||
var modelSelect = '<label class="wolai-page-ai-profile-select"><span>模型</span><select data-page-ai-board-model>' + modelOptions.map(function(option) {
|
||||
var id = String(option.id || '').trim();
|
||||
var label = String(option.label || option.id || '').trim();
|
||||
return '<option value="' + escapeHtml(id) + '"' + (id === selectedModelOverride ? ' selected' : '') + '>' + escapeHtml(label) + '</option>';
|
||||
}).join('') + '</select></label>';
|
||||
agentPopover.innerHTML = '' +
|
||||
'<div class="wolai-page-ai-context-popover-head">' +
|
||||
'<strong>Agent Board</strong>' +
|
||||
'<button type="button" class="wolai-page-ai-ghost" data-page-ai-action="close-agent-popover">完成</button>' +
|
||||
'</div>' +
|
||||
'<div class="wolai-page-ai-settings-grid">' + workerSelect + modelSelect + workflowSelect + '</div>' +
|
||||
'<div class="wolai-page-ai-empty">MNote 只发送 capability/envelope;provider、执行和 workflow 由 Agent Board 负责。</div>';
|
||||
} else {
|
||||
var chatOnlyOptions = pageAiChatOnlyProfileEntries().map(function(profile) {
|
||||
var spec = pageAiChatOnlyProfileSpec(profile);
|
||||
var label = profile.menuLabel || (spec && spec.label) || pageAiProfileDisplayLabel(profile, '');
|
||||
@@ -509,11 +568,12 @@ export function createSidebarPageAiRenderRuntime(context) {
|
||||
'</button>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
}
|
||||
}
|
||||
var agentChip = drawer.querySelector('[data-page-ai-agent-chip]');
|
||||
if (agentChip instanceof HTMLElement) {
|
||||
agentChip.textContent = activeAgentLabel;
|
||||
agentChip.setAttribute('title', '当前 Agent:' + activeAgentLabel);
|
||||
agentChip.textContent = boardFirst && typeof pageAiBoardWorkerLabel === 'function' ? pageAiBoardWorkerLabel() + ' / ' + (typeof pageAiBoardModelLabel === 'function' ? pageAiBoardModelLabel() : '默认') : activeAgentLabel;
|
||||
agentChip.setAttribute('title', boardFirst ? '当前 worker/model:' + agentChip.textContent : '当前 Agent:' + activeAgentLabel);
|
||||
}
|
||||
var contextButton = drawer.querySelector('[data-page-ai-context-button]');
|
||||
var contextPopoverId = 'mnote-page-ai-context-popover';
|
||||
@@ -676,7 +736,10 @@ export function createSidebarPageAiRenderRuntime(context) {
|
||||
runStatus.textContent = pageAiRunStatusLabel(pageUiState.pageAiRunStatus) + queueSuffix;
|
||||
}
|
||||
drawer.querySelectorAll('[data-page-ai-runtime-badge]').forEach(function(runtimeBadge) {
|
||||
if (runtimeBadge instanceof HTMLElement) runtimeBadge.textContent = pageAiRuntimeStatusLabel();
|
||||
if (runtimeBadge instanceof HTMLElement) {
|
||||
var workflowLabel = boardFirst && typeof pageAiBoardWorkflowLabel === 'function' ? pageAiBoardWorkflowLabel() : '';
|
||||
runtimeBadge.textContent = boardFirst ? 'Agent Board · ' + workflowLabel : pageAiRuntimeStatusLabel();
|
||||
}
|
||||
});
|
||||
var runtimeActive = drawer.querySelector('[data-page-ai-runtime-active-run]');
|
||||
if (runtimeActive instanceof HTMLElement) {
|
||||
@@ -684,7 +747,7 @@ export function createSidebarPageAiRenderRuntime(context) {
|
||||
runtimeActive.textContent = pageAiRunStatusLabel(activeRunStatus);
|
||||
}
|
||||
var runtimeAcp = drawer.querySelector('[data-page-ai-runtime-acp]');
|
||||
if (runtimeAcp instanceof HTMLElement) runtimeAcp.textContent = pageAiRuntimeStatusValue('acp.acpSessionId', '无 ACP session');
|
||||
if (runtimeAcp instanceof HTMLElement) runtimeAcp.textContent = boardFirst ? 'provider 由 Board worker 决定' : pageAiRuntimeStatusValue('acp.acpSessionId', '无 ACP session');
|
||||
var runtimeDetail = drawer.querySelector('[data-page-ai-runtime-detail]');
|
||||
if (runtimeDetail instanceof HTMLElement) runtimeDetail.innerHTML = pageAiRuntimeDetailHtml();
|
||||
var jobsList = drawer.querySelector('[data-page-ai-jobs-list]');
|
||||
@@ -709,12 +772,12 @@ export function createSidebarPageAiRenderRuntime(context) {
|
||||
}
|
||||
var usageDetail = drawer.querySelector('[data-page-ai-usage-detail]');
|
||||
if (usageDetail instanceof HTMLElement) usageDetail.innerHTML = pageAiUsageDetailHtml();
|
||||
var stopButton = drawer.querySelector('[data-page-ai-action="stop-run"]');
|
||||
if (stopButton instanceof HTMLButtonElement) {
|
||||
var canStop = ['queued', 'running', 'tool_calling'].indexOf(pageUiState.pageAiRunStatus) >= 0 && pageUiState.pageAiCurrentRunId;
|
||||
var canStop = ['queued', 'running', 'tool_calling'].indexOf(pageUiState.pageAiRunStatus) >= 0 && pageUiState.pageAiCurrentRunId;
|
||||
drawer.querySelectorAll('[data-page-ai-action="stop-run"]').forEach(function(stopButton) {
|
||||
if (!(stopButton instanceof HTMLButtonElement)) return;
|
||||
stopButton.disabled = !canStop;
|
||||
stopButton.setAttribute('aria-disabled', canStop ? 'false' : 'true');
|
||||
}
|
||||
});
|
||||
var settingsLink = drawer.querySelector('[data-page-ai-action="open-hermes-settings"]');
|
||||
if (settingsLink instanceof HTMLButtonElement) {
|
||||
settingsLink.disabled = !pageAiHermesSettingsUrl();
|
||||
@@ -771,6 +834,19 @@ export function createSidebarPageAiRenderRuntime(context) {
|
||||
panel.hidden = panel.getAttribute('data-page-ai-panel') !== pageUiState.pageAiPage;
|
||||
}
|
||||
});
|
||||
if (boardFirst) {
|
||||
var subtitle = drawer.querySelector('.wolai-page-ai-subtitle');
|
||||
if (subtitle instanceof HTMLElement) {
|
||||
var workerLabel = typeof pageAiBoardWorkerLabel === 'function' ? pageAiBoardWorkerLabel() : 'ZCode 默认 developer';
|
||||
subtitle.innerHTML = '<span>Agent Board</span><span>' + escapeHtml(workerLabel) + '</span><span>local-first 文件编辑</span>';
|
||||
}
|
||||
drawer.querySelectorAll('[data-page-ai-tab="agent"], [data-page-ai-tab="reasonix-settings"], [data-page-ai-tab="hermes-settings"]').forEach(function(node) {
|
||||
if (node instanceof HTMLElement) node.hidden = true;
|
||||
});
|
||||
drawer.querySelectorAll('[data-page-ai-panel="agent"], [data-page-ai-panel="reasonix-settings"], [data-page-ai-panel="hermes-settings"]').forEach(function(node) {
|
||||
if (node instanceof HTMLElement) node.setAttribute('data-page-ai-legacy-provider-panel', 'true');
|
||||
});
|
||||
}
|
||||
var profileError = drawer.querySelector('[data-page-ai-profile-error]');
|
||||
if (profileError instanceof HTMLElement) {
|
||||
profileError.textContent = pageUiState.pageAiProfileError || '';
|
||||
@@ -1068,8 +1144,8 @@ export function createSidebarPageAiRenderRuntime(context) {
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'<div class="wolai-page-ai-header-actions">' +
|
||||
'<button type="button" class="wolai-page-ai-icon" data-page-ai-action="new-session" aria-label="新建 AI 会话" title="新建 AI 会话">+</button>' +
|
||||
'<button type="button" class="wolai-page-ai-icon" data-page-ai-action="history" aria-label="历史会话" title="历史会话">⌕</button>' +
|
||||
'<button type="button" class="wolai-page-ai-icon" data-page-ai-action="new-session" aria-label="新建 AI 会话" title="新建 AI 会话"><span class="material-symbols-outlined" data-icon="add" aria-hidden="true"></span></button>' +
|
||||
'<button type="button" class="wolai-page-ai-icon" data-page-ai-action="history" aria-label="历史会话" title="历史会话"><span class="material-symbols-outlined" data-icon="history" aria-hidden="true"></span></button>' +
|
||||
'<button type="button" class="wolai-page-ai-icon" data-page-ai-tab="skills" aria-label="能力" title="能力">' +
|
||||
'<svg class="wolai-page-ai-icon-svg" viewBox="0 0 24 24" aria-hidden="true" focusable="false">' +
|
||||
'<path d="M12 3l1.35 4.15L17.5 8.5l-4.15 1.35L12 14l-1.35-4.15L6.5 8.5l4.15-1.35L12 3z" />' +
|
||||
@@ -1077,8 +1153,8 @@ export function createSidebarPageAiRenderRuntime(context) {
|
||||
'<path d="M5.5 14l.65 1.85L8 16.5l-1.85.65L5.5 19l-.65-1.85L3 16.5l1.85-.65L5.5 14z" />' +
|
||||
'</svg>' +
|
||||
'</button>' +
|
||||
'<button type="button" class="wolai-page-ai-icon" data-page-ai-tab="agent" aria-label="打开页面 AI 设置">⚙</button>' +
|
||||
'<button type="button" class="wolai-page-ai-icon" data-page-ai-action="close" aria-label="关闭页面 AI">×</button>' +
|
||||
'<button type="button" class="wolai-page-ai-icon" data-page-ai-tab="agent" aria-label="打开页面 AI 设置"><span class="material-symbols-outlined" data-icon="admin_panel_settings" aria-hidden="true"></span></button>' +
|
||||
'<button type="button" class="wolai-page-ai-icon" data-page-ai-action="close" aria-label="关闭页面 AI"><span class="material-symbols-outlined" data-icon="close" aria-hidden="true"></span></button>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'<button type="button" class="wolai-page-ai-runtime-strip" data-page-ai-runtime-strip data-page-ai-tab="status" aria-label="打开 Page AI 状态">' +
|
||||
@@ -1540,6 +1616,13 @@ export function createSidebarPageAiRenderRuntime(context) {
|
||||
|
||||
function pageAiRenderNonToolMessage(item) {
|
||||
var roleLabel = item.role === 'user' ? '你' : (item.role === 'tool' ? '工具' : 'AI');
|
||||
if (item.kind === 'status') {
|
||||
return '' +
|
||||
'<div class="wolai-page-ai-message wolai-page-ai-message--assistant" data-page-ai-status-message="true"' + (item.streaming ? ' data-page-ai-streaming="true"' : '') + '>' +
|
||||
'<div class="wolai-page-ai-message-role">AI</div>' +
|
||||
'<div class="wolai-page-ai-message-text">' + escapeHtml(item.content || '') + '</div>' +
|
||||
'</div>';
|
||||
}
|
||||
if (item.kind === 'thought') {
|
||||
return '' +
|
||||
'<div class="wolai-page-ai-message wolai-page-ai-message--assistant" data-page-ai-collapse-card data-page-ai-collapse-id="thought-single">' +
|
||||
@@ -1602,10 +1685,14 @@ export function createSidebarPageAiRenderRuntime(context) {
|
||||
}
|
||||
if (pageAiLooksLikeReasonixPlanMessage(item)) return pageAiRenderReasonixPlanCard(item);
|
||||
var streamingAttr = item.streaming ? ' data-page-ai-streaming="true"' : '';
|
||||
var detailButton = item.boardRunId
|
||||
? '<div class="wolai-page-ai-message-actions"><button type="button" class="wolai-page-ai-ghost" data-page-ai-board-run-detail="' + escapeHtml(item.boardRunId) + '">Run detail</button>' + (item.retryPrompt ? '<button type="button" class="wolai-page-ai-ghost" data-page-ai-retry-message="' + escapeHtml(item.boardRunId) + '">重试</button>' : '') + '<button type="button" class="wolai-page-ai-ghost" data-page-ai-copy-message="' + escapeHtml(item.boardRunId) + '">复制</button></div>'
|
||||
: '';
|
||||
return '' +
|
||||
'<div class="wolai-page-ai-message wolai-page-ai-message--' + escapeHtml(item.role || 'assistant') + '"' + streamingAttr + '>' +
|
||||
'<div class="wolai-page-ai-message-role">' + escapeHtml(roleLabel) + '</div>' +
|
||||
'<div class="wolai-page-ai-message-text">' + (item.role === 'assistant' ? renderPageAiMarkdown(item.content || '') : escapeHtml(item.content || '')) + '</div>' +
|
||||
detailButton +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
@@ -1669,6 +1756,38 @@ export function createSidebarPageAiRenderRuntime(context) {
|
||||
return titleKey === previewKey || previewKey.indexOf(titleKey) === 0 || titleKey.indexOf(previewKey) === 0;
|
||||
}
|
||||
|
||||
function pageAiBoardRunDetailHtml(runId) {
|
||||
var current = typeof pageAiCurrentSession === 'function' ? pageAiCurrentSession() : null;
|
||||
var detail = pageUiState.pageAiBoardRunDetails && pageUiState.pageAiBoardRunDetails[runId]
|
||||
|| current && current.boardRuns && current.boardRuns[runId]
|
||||
|| null;
|
||||
if (!detail) return '<div class="wolai-page-ai-empty">暂无 run detail。</div>';
|
||||
var changedFiles = pageAiNormalizeArray(detail.changedFiles).map(function(file) {
|
||||
return '<li>' + escapeHtml(String(file.path || file || '')) + (file.status ? ' · ' + escapeHtml(file.status) : '') + '</li>';
|
||||
}).join('');
|
||||
var verification = pageAiNormalizeArray(detail.verification).map(function(item) {
|
||||
return '<li>' + escapeHtml([item.command, item.status, item.output].filter(Boolean).join(' · ')) + '</li>';
|
||||
}).join('');
|
||||
var timeline = pageAiNormalizeArray(detail.timeline).map(function(event) {
|
||||
return '<li>' + escapeHtml([event.type, event.message, event.timestamp].filter(Boolean).join(' · ')) + '</li>';
|
||||
}).join('');
|
||||
return '' +
|
||||
'<div class="wolai-page-ai-message wolai-page-ai-message--tool" data-page-ai-board-run-detail-card="true">' +
|
||||
'<div class="wolai-page-ai-permission-card-header">' +
|
||||
'<div class="wolai-page-ai-plan-card-title-wrap"><span class="wolai-page-ai-plan-card-kicker">Run detail</span><strong class="wolai-page-ai-plan-card-title">' + escapeHtml(detail.runId || runId) + '</strong></div>' +
|
||||
'<span class="wolai-page-ai-permission-badge">' + escapeHtml(detail.status || '') + '</span>' +
|
||||
'</div>' +
|
||||
'<div class="wolai-page-ai-permission-summary">' +
|
||||
'<div class="wolai-page-ai-permission-row"><span>Worker</span><strong>' + escapeHtml(detail.workerName || detail.workerPresetId || '') + '</strong></div>' +
|
||||
'<div class="wolai-page-ai-permission-row"><span>Model</span><strong>' + escapeHtml(detail.modelLabel || detail.modelOverride || '') + '</strong></div>' +
|
||||
'<div class="wolai-page-ai-permission-row"><span>Workflow</span><strong>' + escapeHtml(detail.workflowName || detail.workflowId || '') + '</strong></div>' +
|
||||
'</div>' +
|
||||
(changedFiles ? '<details class="wolai-page-ai-tool-details" open><summary><strong>changed files</strong><span>' + String(pageAiNormalizeArray(detail.changedFiles).length) + '</span></summary><ul>' + changedFiles + '</ul></details>' : '') +
|
||||
(verification ? '<details class="wolai-page-ai-tool-details"><summary><strong>verification</strong><span>' + String(pageAiNormalizeArray(detail.verification).length) + '</span></summary><ul>' + verification + '</ul></details>' : '') +
|
||||
(timeline ? '<details class="wolai-page-ai-tool-details"><summary><strong>timeline</strong><span>' + String(pageAiNormalizeArray(detail.timeline).length) + '</span></summary><ul>' + timeline + '</ul></details>' : '') +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
function renderPageAiConversation() {
|
||||
var drawer = ensurePageAiDrawer();
|
||||
renderPageAiSuggestions();
|
||||
@@ -1721,6 +1840,9 @@ export function createSidebarPageAiRenderRuntime(context) {
|
||||
var previousScrollTop = conversation.scrollTop;
|
||||
var openToolDetails = pageAiCaptureOpenToolDetails(conversation);
|
||||
conversation.innerHTML = pageAiConversationRenderHtml(pageUiState.pageAiMessages);
|
||||
if (pageUiState.pageAiBoardActiveDetailRunId) {
|
||||
conversation.insertAdjacentHTML('beforeend', pageAiBoardRunDetailHtml(pageUiState.pageAiBoardActiveDetailRunId));
|
||||
}
|
||||
pageAiRestoreOpenToolDetails(conversation, openToolDetails);
|
||||
if (shouldStickToBottom) {
|
||||
conversation.scrollTop = conversation.scrollHeight;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -82,6 +82,7 @@ export function createSidebarPageAiSessionRuntime(context) {
|
||||
profile = profileId;
|
||||
}
|
||||
return {
|
||||
schema: String(session && session.schema || '').trim(),
|
||||
id: String(session && session.id || '').trim() || pageAiNewSession().id,
|
||||
title: String(session && session.title || '').trim() || '新会话',
|
||||
agentId: agentId,
|
||||
@@ -97,12 +98,18 @@ export function createSidebarPageAiSessionRuntime(context) {
|
||||
shareId: String(session && (session.shareId || session.share_id) || '').trim(),
|
||||
acpSessionId: String(session && (session.acpSessionId || session.acp_session_id) || '').trim(),
|
||||
runId: String(session && (session.runId || session.run_id) || '').trim(),
|
||||
boardRunId: String(session && (session.boardRunId || session.board_run_id || session.runId || session.run_id) || '').trim(),
|
||||
workflowId: String(session && (session.workflowId || session.workflow_id) || '').trim(),
|
||||
workerPresetId: String(session && (session.workerPresetId || session.worker_preset_id) || '').trim(),
|
||||
modelOverride: String(session && (session.modelOverride || session.model_override) || '').trim(),
|
||||
receiptId: String(session && (session.receiptId || session.receipt_id) || '').trim(),
|
||||
boardRuns: session && session.boardRuns && typeof session.boardRuns === 'object' ? session.boardRuns : {},
|
||||
status: String(session && session.status || '').trim(),
|
||||
runtimeMode: String(session && (session.runtimeMode || session.runtime_mode) || '').trim(),
|
||||
replaySeen: Boolean(session && session.replaySeen),
|
||||
usage: session && session.usage && typeof session.usage === 'object' ? session.usage : null,
|
||||
preview: String(session && session.preview || '').trim(),
|
||||
messages: Array.isArray(session && session.messages) ? session.messages.slice(-300) : []
|
||||
messages: Array.isArray(session && session.messages) ? session.messages.slice(-300).map(function(message) { return Object.assign({}, message); }) : []
|
||||
};
|
||||
})
|
||||
.sort(function(a, b) {
|
||||
@@ -208,6 +215,15 @@ export function createSidebarPageAiSessionRuntime(context) {
|
||||
var storageVersion = Number(parsed && parsed.version || 0);
|
||||
if (storageVersion >= sessionStorageVersion && activeAcpRuntime) pageUiState.pageAiAcpRuntime = activeAcpRuntime;
|
||||
if (activeProfile) pageAiSetActiveProfile(activeProfile);
|
||||
var storedSessions = pageAiNormalizeSessions(parsed && parsed.sessions);
|
||||
if (storageVersion >= sessionStorageVersion && storedSessions.length) {
|
||||
pageUiState.pageAiSessions = storedSessions;
|
||||
var activeSessionId = String(parsed && parsed.activeSessionId || '').trim();
|
||||
pageUiState.pageAiActiveSessionId = storedSessions.some(function(session) { return session.id === activeSessionId; }) ? activeSessionId : storedSessions[0].id;
|
||||
var active = pageAiCurrentSession();
|
||||
pageUiState.pageAiMessages = active && Array.isArray(active.messages) ? active.messages.slice() : [];
|
||||
return;
|
||||
}
|
||||
} catch (_) {}
|
||||
var fresh = pageAiNewSession();
|
||||
pageUiState.pageAiSessions = [fresh];
|
||||
@@ -443,15 +459,16 @@ export function createSidebarPageAiSessionRuntime(context) {
|
||||
}
|
||||
|
||||
function pageAiPersistSessions() {
|
||||
pageAiSyncCurrentSessionMessages();
|
||||
doc.documentElement.setAttribute('data-mnote-page-ai-session-owner', 'hermes');
|
||||
doc.documentElement.setAttribute('data-mnote-page-ai-session-key', pageAiStorageKey());
|
||||
try {
|
||||
pageAiSyncCurrentSessionMessages();
|
||||
win.localStorage.setItem(pageAiStorageKey(), JSON.stringify({
|
||||
version: sessionStorageVersion,
|
||||
activeSessionId: pageUiState.pageAiActiveSessionId,
|
||||
activeProfileName: pageAiCurrentProfile(),
|
||||
activeAcpRuntime: pageUiState.pageAiAcpRuntime || 'reasonix'
|
||||
activeAcpRuntime: pageUiState.pageAiAcpRuntime || 'reasonix',
|
||||
sessions: pageAiNormalizeArray(pageUiState.pageAiSessions).slice(0, 20)
|
||||
}));
|
||||
} catch (_) {}
|
||||
}
|
||||
@@ -603,6 +620,12 @@ export function createSidebarPageAiSessionRuntime(context) {
|
||||
session.profileId = pageUiState.pageAiAcpRuntime === 'hermes' ? runProfile : '';
|
||||
session.profile = runProfile;
|
||||
session.acpRuntime = pageUiState.pageAiAcpRuntime || 'reasonix';
|
||||
if (String(session.source || '') === 'board') {
|
||||
session.schema = session.schema || 'mnote.page_ai.session.v2';
|
||||
session.workerPresetId = pageUiState.pageAiBoardWorkerId || session.workerPresetId || '';
|
||||
session.workflowId = pageUiState.pageAiBoardWorkflowId || session.workflowId || '';
|
||||
session.modelOverride = pageUiState.pageAiBoardModelOverride || session.modelOverride || '';
|
||||
}
|
||||
session.updatedAt = Date.now();
|
||||
}
|
||||
|
||||
@@ -611,6 +634,14 @@ export function createSidebarPageAiSessionRuntime(context) {
|
||||
if (!session) return;
|
||||
pageUiState.pageAiActiveSessionId = session.id;
|
||||
if (session.agentId) pageUiState.pageAiAgentId = pageAiNormalizeAgentId(session.agentId);
|
||||
if (session.source === 'board') {
|
||||
if (session.workerPresetId) pageUiState.pageAiBoardWorkerId = session.workerPresetId;
|
||||
if (session.workflowId) pageUiState.pageAiBoardWorkflowId = session.workflowId;
|
||||
if (session.modelOverride) pageUiState.pageAiBoardModelOverride = session.modelOverride;
|
||||
if (session.boardRuns && typeof session.boardRuns === 'object') {
|
||||
pageUiState.pageAiBoardRunDetails = Object.assign({}, pageUiState.pageAiBoardRunDetails || {}, session.boardRuns);
|
||||
}
|
||||
}
|
||||
if (session.acpRuntime) pageUiState.pageAiAcpRuntime = session.acpRuntime;
|
||||
if (session.profileId || session.profile) pageAiSetActiveProfile(session.profileId || session.profile);
|
||||
pageUiState.pageAiMessages = Array.isArray(session.messages) ? session.messages.slice() : [];
|
||||
|
||||
@@ -464,7 +464,7 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
'<div class="wolai-page-history-panel">' +
|
||||
'<div class="wolai-page-history-header">' +
|
||||
'<div><div class="wolai-page-history-title">页面历史</div><div class="wolai-page-history-subtitle">当前会话内最近保存的 15 个快照。</div></div>' +
|
||||
'<button type="button" class="wolai-surface-close" data-page-history-action="close" aria-label="关闭页面历史">×</button>' +
|
||||
'<button type="button" class="wolai-surface-close" data-page-history-action="close" aria-label="关闭页面历史"><span class="material-symbols-outlined" data-icon="close" aria-hidden="true"></span></button>' +
|
||||
'</div>' +
|
||||
'<div class="wolai-page-history-list" data-page-history-list></div>' +
|
||||
'</div>';
|
||||
@@ -527,7 +527,7 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
'<div class="wolai-page-share-card" role="dialog" aria-modal="true">' +
|
||||
'<div class="wolai-page-share-header">' +
|
||||
'<div><div class="wolai-page-share-title">公开分享页面</div><div class="wolai-page-share-subtitle">当前 3000 公开入口由 mnote-web 持有。</div></div>' +
|
||||
'<button type="button" class="wolai-surface-close" data-page-share-action="close" aria-label="关闭公开分享页面">×</button>' +
|
||||
'<button type="button" class="wolai-surface-close" data-page-share-action="close" aria-label="关闭公开分享页面"><span class="material-symbols-outlined" data-icon="close" aria-hidden="true"></span></button>' +
|
||||
'</div>' +
|
||||
'<div class="wolai-page-share-state">' +
|
||||
'<span class="wolai-public-pill wolai-public-pill--inline">全网公开</span>' +
|
||||
@@ -658,7 +658,7 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
'<div class="wolai-page-settings-panel mnote-settings-panel mnote-local-index-settings-panel" role="dialog" aria-modal="false" aria-label="索引设置">' +
|
||||
'<div class="mnote-settings-panel-head">' +
|
||||
'<strong>索引设置</strong>' +
|
||||
'<button type="button" class="mnote-settings-panel-close" data-settings-action="close" aria-label="关闭索引设置">×</button>' +
|
||||
'<button type="button" class="mnote-settings-panel-close" data-settings-action="close" aria-label="关闭索引设置"><span class="material-symbols-outlined" data-icon="close" aria-hidden="true"></span></button>' +
|
||||
'</div>' +
|
||||
'<div class="wolai-page-settings-index-panel" data-testid="wolai-page-settings-local-index-panel">' +
|
||||
'<div class="wolai-page-settings-index-status" data-testid="wolai-page-settings-local-index-status"></div>' +
|
||||
@@ -703,7 +703,7 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
'<div class="wolai-page-settings-panel mnote-settings-panel mnote-knowledge-rag-settings-panel" role="dialog" aria-modal="false" aria-label="资料库问答设置">' +
|
||||
'<div class="mnote-settings-panel-head">' +
|
||||
'<strong>资料库问答</strong>' +
|
||||
'<button type="button" class="mnote-settings-panel-close" data-settings-action="close" aria-label="关闭资料库问答设置">×</button>' +
|
||||
'<button type="button" class="mnote-settings-panel-close" data-settings-action="close" aria-label="关闭资料库问答设置"><span class="material-symbols-outlined" data-icon="close" aria-hidden="true"></span></button>' +
|
||||
'</div>' +
|
||||
'<div class="mnote-knowledge-rag-detail-tabs" role="tablist" aria-label="资料库设置子面板">' +
|
||||
'<button type="button" class="mnote-knowledge-rag-detail-tab is-active" role="tab" aria-selected="true" data-kb-rag-tab="sources">资料源管理</button>' +
|
||||
@@ -919,7 +919,7 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
'<span class="wolai-page-settings-index-status-dot" data-index-status="' + kind + '" title="' + escapeHtml(localIndexStatusLabel(kind)) + '"></span>' +
|
||||
'<input type="text" class="wolai-page-settings-index-path" data-local-index-range-input="true" data-local-index-value="' + escapeHtml(normalizedPath) + '" value="' + escapeHtml(displayPath) + '" spellcheck="false"' + (inputDisabled ? ' disabled' : '') + (isPersisted ? ' data-local-index-persisted="true" title="已保存的索引目录不能直接修改;删除后重新新增范围"' : '') + ' />' +
|
||||
rootScopeHint +
|
||||
'<button type="button" class="wolai-page-settings-index-remove" data-local-index-action="remove-path" data-local-index-path-index="' + String(index) + '"' + (disabled ? ' disabled' : '') + ' aria-label="删除索引范围">×</button>' +
|
||||
'<button type="button" class="wolai-page-settings-index-remove" data-local-index-action="remove-path" data-local-index-path-index="' + String(index) + '"' + (disabled ? ' disabled' : '') + ' aria-label="删除索引范围"><span class="material-symbols-outlined" data-icon="close" aria-hidden="true"></span></button>' +
|
||||
'</div>';
|
||||
}).join('');
|
||||
}
|
||||
@@ -1132,7 +1132,7 @@ export function createSidebarPageSettingsRuntime(context) {
|
||||
'<div class="mnote-knowledge-rag-source-input-row" data-knowledge-rag-source-input-row="true">' +
|
||||
'<input type="text" class="wolai-page-settings-index-path" data-knowledge-rag-source-input="true" value="' + escapeHtml(value || '') + '" placeholder="文件或目录,例如 docs/book.pdf / docs" spellcheck="false" />' +
|
||||
'<span class="mnote-knowledge-rag-input-status" data-knowledge-rag-input-status-label="true" hidden></span>' +
|
||||
'<button type="button" class="wolai-page-settings-index-remove" data-knowledge-rag-action="remove-source" aria-label="删除资料来源">×</button>' +
|
||||
'<button type="button" class="wolai-page-settings-index-remove" data-knowledge-rag-action="remove-source" aria-label="删除资料来源"><span class="material-symbols-outlined" data-icon="close" aria-hidden="true"></span></button>' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user