收口 MNote P0 P1 P2 审查尾项
- 归档 OnlyOffice live bridge、Page AI、mindmap、design governance 与相关 bug 条目 - 补齐 MinerU OCR 后端 runtime 合同与 smoke/test 基线 - 收口 ChatOnly/Doubao、ObjectIdentity、Page Aggregate compat 与 runtime owner 文档口径 验证: - cargo test --manifest-path rust/Cargo.toml -p mnote-web local_ocr -- --test-threads=1 - cargo test --manifest-path rust/Cargo.toml -p mnote-web onlyoffice_bridge -- --test-threads=1 - git diff --check - git diff --cached --check - codegraph index . --force && codegraph status . - codegraph sync . && codegraph status .
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
export function createSidebarPageAiPermissionRuntime(context) {
|
||||
const {
|
||||
documentRef,
|
||||
pageAiPreviewValue,
|
||||
pageUiState,
|
||||
renderPageAiConversation,
|
||||
} = context;
|
||||
const doc = documentRef || document;
|
||||
|
||||
function pageAiPermissionMessage(payload, eventType) {
|
||||
payload = payload && typeof payload === 'object' ? payload : {};
|
||||
var permissionId = String(payload.permissionId || payload.permission_id || payload.id || ('perm_' + Date.now())).trim();
|
||||
var toolName = String(payload.toolName || payload.tool || payload.name || payload.method || 'session/request_permission').trim();
|
||||
var args = payload.arguments || payload.args || payload.input || payload.params || payload;
|
||||
var decision = String(payload.decision || payload.result || '').trim();
|
||||
if (!decision && eventType === 'permission.denied') decision = 'denied';
|
||||
if (!decision && eventType === 'permission.allowed') decision = 'allowed';
|
||||
return {
|
||||
role: 'tool',
|
||||
kind: 'permission',
|
||||
permissionId: permissionId,
|
||||
toolName: toolName,
|
||||
argsSummary: pageAiPreviewValue(args),
|
||||
content: decision === 'denied' ? '已自动拒绝权限请求' : (decision === 'allowed' ? '已自动允许权限请求' : '等待权限确认'),
|
||||
resolved: decision === 'denied' || decision === 'allowed',
|
||||
decision: decision
|
||||
};
|
||||
}
|
||||
|
||||
function pageAiApplyPermissionEvent(eventName, payloadText) {
|
||||
var payload = null;
|
||||
try {
|
||||
payload = JSON.parse(payloadText || 'null');
|
||||
} catch (_) {
|
||||
payload = {};
|
||||
}
|
||||
var message = pageAiPermissionMessage(payload, eventName);
|
||||
var existing = pageUiState.pageAiMessages.find(function(item) {
|
||||
return item.kind === 'permission' && item.permissionId === message.permissionId;
|
||||
});
|
||||
if (existing) {
|
||||
Object.assign(existing, message);
|
||||
} else {
|
||||
pageUiState.pageAiMessages.push(message);
|
||||
}
|
||||
pageUiState.pageAiPermissionRequests = pageUiState.pageAiPermissionRequests.filter(function(item) {
|
||||
return item.permissionId !== message.permissionId;
|
||||
}).concat([message]).slice(-20);
|
||||
if (!message.resolved) {
|
||||
pageAiShowPermissionDialog(message);
|
||||
} else {
|
||||
pageAiHidePermissionDialog();
|
||||
}
|
||||
}
|
||||
|
||||
function pageAiResolvePermission(permissionId, decision) {
|
||||
permissionId = String(permissionId || '').trim();
|
||||
if (!permissionId) return;
|
||||
var runId = pageUiState.pageAiCurrentRunId;
|
||||
if (runId) {
|
||||
fetch('/api/hermes/client/runs/' + encodeURIComponent(runId) + '/resolve-permission', {
|
||||
method: 'POST',
|
||||
headers: { 'content-type': 'application/json' },
|
||||
body: JSON.stringify({ permissionId: permissionId, decision: decision })
|
||||
}).then(function(response) {
|
||||
if (!response.ok) console.warn('resolve-permission 后端返回异常', response.status);
|
||||
}).catch(function(err) {
|
||||
console.warn('resolve-permission 请求失败', err);
|
||||
});
|
||||
} else {
|
||||
console.warn('resolve-permission: 无活跃 runId,只能本地更新');
|
||||
}
|
||||
pageUiState.pageAiMessages.forEach(function(item) {
|
||||
if (item.kind === 'permission' && item.permissionId === permissionId) {
|
||||
item.resolved = true;
|
||||
item.decision = decision;
|
||||
item.content = decision === 'allow' ? '已允许权限请求' : '已拒绝权限请求';
|
||||
}
|
||||
});
|
||||
var dialog = doc.querySelector('[data-page-ai-permission-dialog]');
|
||||
if (dialog instanceof HTMLElement) dialog.hidden = true;
|
||||
renderPageAiConversation();
|
||||
}
|
||||
|
||||
function pageAiHidePermissionDialog() {
|
||||
var dialog = doc.querySelector('[data-page-ai-permission-dialog]');
|
||||
if (dialog instanceof HTMLElement) dialog.hidden = true;
|
||||
}
|
||||
|
||||
function pageAiShowPermissionDialog(message) {
|
||||
if (!message || message.kind !== 'permission') return;
|
||||
if (message.resolved) {
|
||||
pageAiHidePermissionDialog();
|
||||
return;
|
||||
}
|
||||
var dialog = doc.querySelector('[data-page-ai-permission-dialog]');
|
||||
if (!(dialog instanceof HTMLElement)) {
|
||||
dialog = doc.createElement('div');
|
||||
dialog.className = 'wolai-page-ai-permission-dialog';
|
||||
dialog.setAttribute('data-page-ai-permission-dialog', 'true');
|
||||
dialog.innerHTML = '' +
|
||||
'<div class="wolai-page-ai-permission-panel" role="dialog" aria-modal="false">' +
|
||||
'<div class="wolai-page-ai-memory-title" data-page-ai-permission-tool></div>' +
|
||||
'<div class="wolai-page-ai-tool-meta" data-page-ai-permission-args></div>' +
|
||||
'<div class="wolai-page-ai-message-actions">' +
|
||||
'<button type="button" class="wolai-page-ai-ghost" data-page-ai-permission-action="allow" data-page-ai-permission-dialog-action>允许</button>' +
|
||||
'<button type="button" class="wolai-page-ai-ghost" data-page-ai-permission-action="deny" data-page-ai-permission-dialog-action>拒绝</button>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
doc.body.appendChild(dialog);
|
||||
}
|
||||
var tool = dialog.querySelector('[data-page-ai-permission-tool]');
|
||||
if (tool instanceof HTMLElement) tool.textContent = message.toolName || 'session/request_permission';
|
||||
var args = dialog.querySelector('[data-page-ai-permission-args]');
|
||||
if (args instanceof HTMLElement) args.textContent = message.argsSummary || message.content || '';
|
||||
dialog.querySelectorAll('[data-page-ai-permission-dialog-action]').forEach(function(button) {
|
||||
if (button instanceof HTMLButtonElement) {
|
||||
button.setAttribute('data-page-ai-permission-id', message.permissionId || '');
|
||||
button.disabled = Boolean(message.resolved);
|
||||
}
|
||||
});
|
||||
dialog.hidden = false;
|
||||
}
|
||||
|
||||
return {
|
||||
pageAiPermissionMessage,
|
||||
pageAiApplyPermissionEvent,
|
||||
pageAiResolvePermission,
|
||||
pageAiHidePermissionDialog,
|
||||
pageAiShowPermissionDialog
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user