Files
mnote/rust/crates/mnote-web/browser/sidebar-page-ai-profile-runtime.js
T
2026-06-25 21:08:17 +08:00

282 lines
12 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
export function createSidebarPageAiProfileRuntime(context) {
const {
chatOnlyProfileRegistry,
documentRef,
pageAiAgentRecord,
pageAiCurrentAgentId,
pageAiNormalizeAgentId,
pageUiState,
} = context;
const PAGE_AI_CHAT_ONLY_PROFILE_REGISTRY = Array.isArray(chatOnlyProfileRegistry) ? chatOnlyProfileRegistry : [];
function pageAiProviderLabel(provider) {
if (provider === 'codex') return 'Codex';
if (provider === 'claudecode') return 'ClaudeCode';
return 'Hermes';
}
function pageAiNormalizeArray(value) {
return Array.isArray(value) ? value : [];
}
function pageAiDefaultAcpRuntimes() {
return [
{
name: 'reasonix',
title: 'ACP · Reasonix',
description: '通过 ACP 协议直连 ReasonixDeepSeek 缓存优先)',
model: 'deepseek-chat',
preset: 'auto'
},
{
name: 'hermes',
title: 'ACP · Hermes',
description: '通过 ACP 协议直连 Hermes agent runtime'
}
];
}
function pageAiNormalizeAcpRuntimes(runtimes) {
var byName = {};
pageAiDefaultAcpRuntimes().forEach(function(runtime) {
byName[runtime.name] = Object.assign({}, runtime);
});
pageAiNormalizeArray(runtimes).forEach(function(runtime) {
var name = String(runtime && runtime.name || '').trim();
if (name !== 'reasonix' && name !== 'hermes') return;
byName[name] = Object.assign({}, byName[name] || {}, runtime, { name: name });
});
return ['reasonix', 'hermes'].map(function(name) { return byName[name]; }).filter(Boolean);
}
function pageAiUnwrapUpstream(payload) {
if (payload && typeof payload === 'object' && payload.upstream) return payload.upstream;
return payload || null;
}
function pageAiProfileValue(profile) {
if (profile && typeof profile === 'object') {
return String(profile.profileId || profile.name || profile.profile || profile.id || '').trim();
}
return String(profile || '').trim();
}
function pageAiCurrentProfile() {
var active = String(pageUiState.pageAiActiveProfileName || '').trim();
if (active) return active;
var selected = pageUiState.pageAiProfiles.find(function(profile) {
return profile && profile.active;
});
return pageAiProfileValue(selected) || 'mnoteai';
}
function pageAiRunProfile() {
if (String(pageUiState.pageAiAcpRuntime || 'reasonix').trim() === 'reasonix') return 'reasonix';
if (pageAiCurrentAgentId() === 'chat_only') return pageAiNormalizeChatOnlyProfileId(pageAiCurrentProfile());
return pageAiCurrentProfile();
}
function pageAiMnoteToolModel() {
var doc = documentRef || document;
return String(doc.documentElement.getAttribute('data-mnote-page-ai-tool-model') || 'deepseek-v4-flash').trim() || 'deepseek-v4-flash';
}
function pageAiCurrentProfileRecord() {
var active = pageAiCurrentProfile();
return pageUiState.pageAiProfiles.find(function(profile) {
return pageAiProfileValue(profile) === active;
}) || null;
}
function pageAiChatOnlyProfileSpec(profile) {
var profileId = pageAiProfileValue(profile);
var baseProfile = String(profile && profile.baseProfile || '').trim();
var isolatedProfile = String(profile && profile.isolatedProfile || '').trim();
return PAGE_AI_CHAT_ONLY_PROFILE_REGISTRY.find(function(spec) {
return spec.profileId === profileId || spec.baseProfile === profileId || spec.baseProfile === baseProfile || isolatedProfile.indexOf(spec.baseProfile) >= 0;
}) || null;
}
function pageAiDefaultChatOnlyProfileSpec() {
return PAGE_AI_CHAT_ONLY_PROFILE_REGISTRY[0] || { profileId: 'shared_deepseek_chat', baseProfile: 'deepseek-chat', label: 'DeepSeek' };
}
function pageAiNormalizeChatOnlyProfileId(profileId) {
var profile = pageAiProfileRecordById(profileId) || { profileId: String(profileId || '').trim(), name: String(profileId || '').trim() };
var spec = pageAiChatOnlyProfileSpec(profile);
return (spec || pageAiDefaultChatOnlyProfileSpec()).profileId;
}
function pageAiProfileDisplayLabel(profile, fallback) {
var alias = String(profile && profile.alias || '').trim();
var displayName = String(profile && (profile.displayName || profile.label || '') || '').trim();
var name = pageAiProfileValue(profile);
return alias || displayName || fallback || name || 'default';
}
function pageAiProfileRecordById(profileId) {
var normalized = String(profileId || '').trim();
if (!normalized) return null;
return pageAiNormalizeArray(pageUiState.pageAiProfiles).find(function(profile) {
return pageAiProfileValue(profile) === normalized;
}) || null;
}
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();
if (agentId === 'chat_only') profileId = pageAiNormalizeChatOnlyProfileId(profileId);
return agentId + ':' + profileId;
}
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();
var profile = pageAiProfileRecordById(profileId) || { profileId: profileId, name: profileId };
var chatOnlySpec = pageAiChatOnlyProfileSpec(profile);
if (agentId === 'chat_only') {
return 'ChatOnly / ' + (chatOnlySpec || pageAiDefaultChatOnlyProfileSpec()).label;
}
if (agentId === 'hermes') return 'Hermes / ' + pageAiProfileDisplayLabel(profile, profileId);
return pageAiAgentRecord(agentId).label;
}
function pageAiSessionPreviewText(session) {
var preview = Array.isArray(session && session.messages) && session.messages.length
? String(session.messages.slice(-1)[0].content || '')
: String(session && (session.snippet || session.preview || '暂无消息') || '暂无消息');
preview = preview.replace(/\s+/g, ' ').trim();
var limit = 96;
return preview.length > limit ? preview.slice(0, limit) + '…' : preview;
}
function pageAiSessionAgentFilterOptions(rows) {
var byValue = { all: '全部 agent' };
pageAiNormalizeArray(rows).filter(pageAiVisibleHistorySession).forEach(function(session) {
var value = pageAiSessionAgentFilterValue(session);
byValue[value] = pageAiSessionAgentLabel(session);
});
return Object.keys(byValue).map(function(value) {
return { value: value, label: byValue[value] };
});
}
function pageAiSessionStatusFilterValue(session) {
var status = String(session && session.status || '').trim();
var mode = String(session && (session.runtimeMode || session.mode) || '').trim();
if (pageUiState.pageAiActiveSessionId && session && session.id === pageUiState.pageAiActiveSessionId) return 'active';
if (session && session.replaySeen) return 'replay_seen';
if (mode === 'native_live' || mode === 'cold_resumed' || mode === 'replay_seen') return mode;
if (['running', 'tool_calling', 'queued', 'pending', 'acp_pending'].indexOf(status) >= 0) return 'active';
if (['failed', 'aborted', 'cancelled', 'canceled'].indexOf(status) >= 0) return 'failed';
if (status === 'completed') return 'completed';
return status || 'unknown';
}
function pageAiSessionStatusLabel(value) {
return {
all: '全部状态',
active: 'Active',
completed: 'Completed',
failed: 'Failed',
native_live: 'Reasonix native-live',
cold_resumed: 'Cold resumed',
replay_seen: 'Replay seen',
unknown: 'Unknown'
}[value] || value;
}
function pageAiSessionStatusFilterOptions(rows) {
var byValue = {
all: pageAiSessionStatusLabel('all'),
active: pageAiSessionStatusLabel('active'),
completed: pageAiSessionStatusLabel('completed'),
failed: pageAiSessionStatusLabel('failed'),
native_live: pageAiSessionStatusLabel('native_live'),
cold_resumed: pageAiSessionStatusLabel('cold_resumed'),
replay_seen: pageAiSessionStatusLabel('replay_seen')
};
pageAiNormalizeArray(rows).filter(pageAiVisibleHistorySession).forEach(function(session) {
var value = pageAiSessionStatusFilterValue(session);
byValue[value] = pageAiSessionStatusLabel(value);
});
return Object.keys(byValue).map(function(value) {
return { value: value, label: byValue[value] };
});
}
function pageAiVisibleHistorySession(session) {
var source = String(session && session.source || '').trim();
var status = String(session && session.status || '').trim();
var messages = pageAiNormalizeArray(session && session.messages);
return !(source === 'draft' && status === 'draft' && messages.length === 0);
}
function pageAiFilteredHistoryRows(rows) {
var filterValue = String(pageUiState.pageAiSessionAgentFilter || 'all').trim() || 'all';
var statusFilter = String(pageUiState.pageAiSessionStatusFilter || 'all').trim() || 'all';
var normalized = pageAiNormalizeArray(rows).filter(pageAiVisibleHistorySession);
return normalized.filter(function(session) {
return (filterValue === 'all' || pageAiSessionAgentFilterValue(session) === filterValue)
&& (statusFilter === 'all' || pageAiSessionStatusFilterValue(session) === statusFilter);
});
}
function pageAiTimestamp(value) {
if (typeof value === 'number' && Number.isFinite(value)) return value;
if (typeof value === 'string' && value.trim()) {
var parsed = Date.parse(value);
if (Number.isFinite(parsed)) return parsed;
}
return Date.now();
}
function pageAiUsageSummary(usage) {
if (!usage || typeof usage !== 'object') return '';
var used = usage.used ?? usage.contextUsed ?? usage.input_tokens ?? usage.inputTokens ?? usage.prompt_tokens ?? usage.promptTokens;
var size = usage.size ?? usage.contextSize ?? usage.total_tokens ?? usage.totalTokens;
var output = usage.output_tokens ?? usage.outputTokens ?? usage.completion_tokens ?? usage.completionTokens;
var parts = [];
if (Number.isFinite(Number(used))) parts.push('ctx ' + Number(used));
if (Number.isFinite(Number(size)) && Number(size) > 0) parts.push('/ ' + Number(size));
if (Number.isFinite(Number(output)) && Number(output) > 0) parts.push('out ' + Number(output));
return parts.join(' ') || '';
}
return {
pageAiProviderLabel,
pageAiNormalizeArray,
pageAiDefaultAcpRuntimes,
pageAiNormalizeAcpRuntimes,
pageAiUnwrapUpstream,
pageAiProfileValue,
pageAiCurrentProfile,
pageAiRunProfile,
pageAiMnoteToolModel,
pageAiCurrentProfileRecord,
pageAiChatOnlyProfileSpec,
pageAiDefaultChatOnlyProfileSpec,
pageAiNormalizeChatOnlyProfileId,
pageAiProfileDisplayLabel,
pageAiProfileRecordById,
pageAiSessionAgentFilterValue,
pageAiSessionAgentLabel,
pageAiSessionPreviewText,
pageAiSessionAgentFilterOptions,
pageAiSessionStatusFilterValue,
pageAiSessionStatusLabel,
pageAiSessionStatusFilterOptions,
pageAiFilteredHistoryRows,
pageAiTimestamp,
pageAiUsageSummary
};
}