noteconnection 1.8.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +257 -1803
- package/dist/src/agent_workspace.contract.parity.test.js +105 -421
- package/dist/src/agent_workspace.frontend.test.js +410 -11
- package/dist/src/android.knowledgebase.picker.contract.test.js +102 -0
- package/dist/src/appimage.patchelf.test.js +113 -0
- package/dist/src/appimage.portability.test.js +156 -0
- package/dist/src/backend/FileLoader.js +18 -4
- package/dist/src/backend/FileLoader.test.js +125 -0
- package/dist/src/backend/GraphBuilder.identity.test.js +86 -0
- package/dist/src/backend/GraphBuilder.js +66 -18
- package/dist/src/backend/GraphBuilder.matching.test.js +127 -0
- package/dist/src/backend/GraphMetrics.js +0 -3
- package/dist/src/backend/ResourceIdentity.js +155 -0
- package/dist/src/backend/ResourceIdentity.test.js +113 -0
- package/dist/src/backend/algorithms/CycleDetection.js +0 -1
- package/dist/src/backend/algorithms/HybridEngine.js +0 -3
- package/dist/src/backend/algorithms/LayoutEngine.js +0 -1
- package/dist/src/backend/algorithms/StatisticalAnalyzer.js +0 -4
- package/dist/src/backend/algorithms/TopologicalSort.js +0 -2
- package/dist/src/backend/build_dag.js +0 -1
- package/dist/src/capacitor.bridge.serialization.contract.test.js +3 -0
- package/dist/src/capacitor.runtime.contract.test.js +11 -2
- package/dist/src/core/Graph.js +138 -42
- package/dist/src/core/Graph.test.js +74 -0
- package/dist/src/core/NoteConnection.js +2 -2
- package/dist/src/core/PathBridge.js +265 -2
- package/dist/src/core/ResourceReference.js +17 -0
- package/dist/src/desktop.godot.pack.test.js +142 -0
- package/dist/src/desktop.runtime.graph.test.js +66 -0
- package/dist/src/export/WorkspaceExportBundle.js +44 -0
- package/dist/src/export/WorkspaceExportBundle.test.js +61 -0
- package/dist/src/foundation.release.evidence.contract.test.js +127 -9
- package/dist/src/foundation.sqlite.runtime.contract.test.js +6 -0
- package/dist/src/frontend/README.md +257 -1803
- package/dist/src/frontend/agent_workspace.js +665 -7
- package/dist/src/frontend/index.html +31 -2
- package/dist/src/frontend/knowledge_projection_contract.js +230 -0
- package/dist/src/frontend/knowledge_projection_store.js +214 -0
- package/dist/src/frontend/libs/path_core.js +158 -42
- package/dist/src/frontend/locales/en.json +32 -0
- package/dist/src/frontend/locales/zh.json +32 -0
- package/dist/src/frontend/mobile_budget_runtime.js +33 -0
- package/dist/src/frontend/mobile_exact_analyzer.js +393 -0
- package/dist/src/frontend/mobile_identity_contract.js +221 -0
- package/dist/src/frontend/mobile_semantic_comparator.js +264 -0
- package/dist/src/frontend/path.html +6 -2
- package/dist/src/frontend/simulationWorker.js +1 -1
- package/dist/src/frontend/source_manager.js +110 -4
- package/dist/src/frontend/storage_provider.js +661 -71
- package/dist/src/frontend/styles.css +107 -13
- package/dist/src/frontend/workspace_panes.js +111 -7
- package/dist/src/frontend.runtime.assets.contract.test.js +81 -0
- package/dist/src/graph.answer.operator.contract.test.js +72 -0
- package/dist/src/index.js +6 -2
- package/dist/src/index.knowledge-root.test.js +118 -0
- package/dist/src/indexing/IndexLifecycle.js +22 -0
- package/dist/src/indexing/IndexLifecycle.test.js +24 -0
- package/dist/src/knowledge.api.contract.test.js +4 -2
- package/dist/src/knowledge_projection.contract.test.js +134 -0
- package/dist/src/knowledge_projection_store.test.js +200 -0
- package/dist/src/learning/AnswerQualityEvaluation.js +153 -0
- package/dist/src/learning/AnswerQualityEvaluation.test.js +118 -0
- package/dist/src/learning/KnowledgeLearningPlatform.js +4687 -3892
- package/dist/src/learning/KnowledgeLearningPlatform.persistence.test.js +418 -0
- package/dist/src/learning/KnowledgeLearningPlatform.test.js +243 -6
- package/dist/src/learning/KnowledgeWorkspaceConversationRegression.js +25 -1
- package/dist/src/learning/KnowledgeWorkspaceConversationRegression.test.js +13 -5
- package/dist/src/learning/MeasurementEvidenceConflicts.test.js +78 -0
- package/dist/src/learning/PublicAnswerContract.test.js +85 -0
- package/dist/src/learning/PublicEvidenceSelection.test.js +94 -0
- package/dist/src/learning/PublicMeasurementDisclosure.test.js +54 -0
- package/dist/src/learning/agentConversationExecution.js +211 -0
- package/dist/src/learning/agentConversationExecution.test.js +209 -0
- package/dist/src/learning/agentConversationSerialization.js +266 -0
- package/dist/src/learning/agentConversationSerialization.test.js +165 -0
- package/dist/src/learning/agentResponseBudget.js +179 -0
- package/dist/src/learning/agentResponseBudget.test.js +97 -0
- package/dist/src/learning/agentWorkspaceCapabilityContracts.js +65 -0
- package/dist/src/learning/answerReleaseReview.js +1191 -250
- package/dist/src/learning/answerReleaseReview.test.js +1293 -7
- package/dist/src/learning/answerTaskPlan.js +473 -0
- package/dist/src/learning/conversationComposer.js +627 -386
- package/dist/src/learning/conversationComposer.test.js +1403 -0
- package/dist/src/learning/evidenceContextAssembler.js +312 -120
- package/dist/src/learning/graphAnswerCoverage.js +37 -0
- package/dist/src/learning/graphAnswerCoverage.test.js +93 -0
- package/dist/src/learning/graphAnswerCoverageCalibration.js +59 -0
- package/dist/src/learning/graphAnswerCoverageCalibration.test.js +46 -0
- package/dist/src/learning/graphAnswerFacts.js +94 -0
- package/dist/src/learning/graphAnswerFacts.test.js +39 -0
- package/dist/src/learning/graphAnswerPlan.js +908 -0
- package/dist/src/learning/graphAnswerPlan.test.js +907 -0
- package/dist/src/learning/graphAnswerQualityCalibration.js +255 -0
- package/dist/src/learning/graphAnswerQualityCalibration.test.js +72 -0
- package/dist/src/learning/graphAnswerQualityPolicy.js +30 -0
- package/dist/src/learning/graphClaimMatcher.js +104 -0
- package/dist/src/learning/graphConditionedContext.js +109 -0
- package/dist/src/learning/graphConditionedContext.test.js +99 -0
- package/dist/src/learning/graphContextAssembler.js +3 -13
- package/dist/src/learning/graphContextAssembler.test.js +2 -2
- package/dist/src/learning/graphExpansionPolicy.js +22 -0
- package/dist/src/learning/graphExpansionPolicy.test.js +33 -0
- package/dist/src/learning/identityMetadata.test.js +26 -0
- package/dist/src/learning/index.js +1 -0
- package/dist/src/learning/mobileAnswerProjection.js +104 -0
- package/dist/src/learning/mobileAnswerProjection.test.js +102 -0
- package/dist/src/learning/queryBackend.js +34 -10
- package/dist/src/learning/queryBackend.test.js +21 -0
- package/dist/src/learning/ragContextPack.js +115 -16
- package/dist/src/learning/ragContextPack.test.js +151 -0
- package/dist/src/learning/ragEvidenceQuality.js +96 -0
- package/dist/src/learning/ragEvidenceQuality.test.js +29 -0
- package/dist/src/learning/ragPublicText.js +67 -4
- package/dist/src/learning/ragPublicText.test.js +57 -0
- package/dist/src/learning/ragSufficiencyJudge.js +11 -1
- package/dist/src/learning/ragSufficiencyProviderJudge.js +16 -26
- package/dist/src/learning/ragSufficiencyProviderJudge.test.js +51 -0
- package/dist/src/learning/requestNormalization.js +106 -0
- package/dist/src/learning/requestNormalization.test.js +101 -0
- package/dist/src/learning/store.js +116 -12
- package/dist/src/learning/store.test.js +299 -0
- package/dist/src/learning/vectorAccelerationAdapter.js +22 -6
- package/dist/src/learning/vectorAccelerationAdapter.test.js +30 -0
- package/dist/src/learning/workspaceHydration.js +168 -0
- package/dist/src/learning/workspaceHydration.test.js +30 -0
- package/dist/src/license.policy.contract.test.js +9 -4
- package/dist/src/markdown/MarkdownGateway.js +4 -0
- package/dist/src/markdown/MarkdownGateway.test.js +59 -0
- package/dist/src/middleware/SseResponseWriter.js +122 -0
- package/dist/src/middleware/SseResponseWriter.test.js +54 -0
- package/dist/src/middleware/auth.js +28 -7
- package/dist/src/middleware/auth.test.js +33 -0
- package/dist/src/middleware/index.js +2 -1
- package/dist/src/mobile.android.evidence.contract.test.js +146 -0
- package/dist/src/mobile.android.signing.contract.test.js +66 -0
- package/dist/src/mobile.artifact.contract.test.js +144 -0
- package/dist/src/mobile.budget.contract.test.js +90 -0
- package/dist/src/mobile.canonical-id.readiness.test.js +54 -0
- package/dist/src/mobile.graph.parity.contract.test.js +207 -0
- package/dist/src/mobile.identity.contract.test.js +66 -0
- package/dist/src/mobile.identity.corpus.manifest.test.js +72 -0
- package/dist/src/mobile.identity.corpus.test.js +40 -0
- package/dist/src/mobile.native.recovery.contract.test.js +64 -0
- package/dist/src/mobile.pipeline.test.js +11 -1
- package/dist/src/mobile.profile.contract.test.js +225 -0
- package/dist/src/mobile.semantic.parity.test.js +92 -0
- package/dist/src/mobile_exact_analyzer.test.js +113 -0
- package/dist/src/notemd/ContentGenerator.js +4 -9
- package/dist/src/notemd/FileProcessor.js +4 -9
- package/dist/src/notemd/NotemdService.js +12 -17
- package/dist/src/notemd/Translator.js +4 -9
- package/dist/src/notemd/progressReporter.js +9 -0
- package/dist/src/notemd.server.integration.test.js +119 -4
- package/dist/src/notemd.workflow.pipeline.test.js +1 -1
- package/dist/src/pathbridge.handshake.contract.test.js +29 -0
- package/dist/src/pathbridge.host-adapter.contract.test.js +133 -0
- package/dist/src/pathcore.bundle.contract.test.js +8 -0
- package/dist/src/platform/ExportProfile.js +28 -0
- package/dist/src/platform/MobileBudget.js +11 -0
- package/dist/src/platform/PlatformCapabilities.js +14 -0
- package/dist/src/platform/PlatformCapabilities.test.js +6 -0
- package/dist/src/query_backend.external_http.integration.test.js +2 -2
- package/dist/src/release.godot.mirror.contract.test.js +28 -4
- package/dist/src/resources/ResourceRegistry.js +40 -0
- package/dist/src/resources/ResourceRegistry.test.js +36 -0
- package/dist/src/routes/index.js +0 -4
- package/dist/src/routes/knowledge.js +46 -33
- package/dist/src/routes/knowledgePayload.js +185 -0
- package/dist/src/routes/knowledgePayload.test.js +53 -0
- package/dist/src/routes/markdown.js +8 -0
- package/dist/src/routes/notemd.js +990 -234
- package/dist/src/routes/registry.contract.test.js +5 -2
- package/dist/src/routes/registry.shadow.contract.test.js +22 -0
- package/dist/src/routes/render.js +14 -51
- package/dist/src/runtime.capabilities.test.js +18 -2
- package/dist/src/server.js +566 -1090
- package/dist/src/server.migration.test.js +417 -15
- package/dist/src/sidecar.build.lock.contract.test.js +201 -0
- package/dist/src/sidecar.freshness.contract.test.js +184 -0
- package/dist/src/sidecar.replacement.boundary.contract.test.js +6 -3
- package/dist/src/sidecar.supply.readiness.contract.test.js +11 -0
- package/dist/src/simulation.worker.offline.test.js +104 -0
- package/dist/src/storage.provider.capacitor.content.contract.test.js +4 -1
- package/dist/src/storage.provider.contract.test.js +152 -1
- package/dist/src/tauri.frontend.build.contract.test.js +8 -0
- package/dist/src/tauri.window.evidence.execution.test.js +68 -0
- package/dist/src/utils/RuntimePaths.js +6 -0
- package/dist/src/utils/RuntimePaths.test.js +27 -0
- package/dist/src/windows.installer.build.test.js +109 -0
- package/dist/src/windows.installer.payload.test.js +76 -0
- package/dist/src/windows.installer.runtime.test.js +69 -0
- package/dist/src/workspace/WorkspaceRegistry.js +13 -0
- package/package.json +32 -10
- package/dist/src/routes/data.js +0 -267
- package/dist/src/routes/diagnostics.js +0 -51
|
@@ -37,12 +37,317 @@
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
const ACTIVE_SOURCE_TARGET_STORAGE_KEY = 'nc_last_target';
|
|
40
|
+
const ANSWER_LANGUAGE_STORAGE_KEY = 'nc_agent_answer_language';
|
|
41
|
+
const RESPONSE_MODE_STORAGE_KEY = 'nc_agent_response_mode';
|
|
42
|
+
const RESPONSE_BUDGET_MODE_STORAGE_KEY = 'nc_agent_response_budget_mode';
|
|
40
43
|
const ACTIVE_SOURCE_TARGET_EVENT = 'noteconnection:active-target-changed';
|
|
41
44
|
const AGENT_CONVERSATION_ENDPOINT = '/api/knowledge/conversation';
|
|
42
45
|
const GRAPH_FOCUS_DIAGNOSTICS_EVENT = 'noteconnection:agent-graph-focus-diagnostics';
|
|
43
46
|
const GRAPH_FOCUS_DIAGNOSTICS_ENDPOINT = '/api/knowledge/session/graph-focus-diagnostics';
|
|
44
47
|
let lastGraphFocusDiagnosticsPersistenceKey = '';
|
|
45
48
|
|
|
49
|
+
function isMobileNativeRuntime() {
|
|
50
|
+
const caps = window && window.__NC_RUNTIME_CAPS && typeof window.__NC_RUNTIME_CAPS === 'object'
|
|
51
|
+
? window.__NC_RUNTIME_CAPS
|
|
52
|
+
: {};
|
|
53
|
+
const platform = String(caps.platform || '').trim().toLowerCase();
|
|
54
|
+
if (platform.startsWith('capacitor-') || platform === 'android' || platform === 'ios') {
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
if (window && window.Capacitor && typeof window.Capacitor.isNativePlatform === 'function') {
|
|
58
|
+
try {
|
|
59
|
+
return window.Capacitor.isNativePlatform() === true;
|
|
60
|
+
} catch (_error) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function trimMobileText(value, limit) {
|
|
68
|
+
const normalized = String(value || '').replace(/\s+/gu, ' ').trim();
|
|
69
|
+
return normalized.length <= limit
|
|
70
|
+
? normalized
|
|
71
|
+
: `${normalized.slice(0, Math.max(0, limit - 1)).trim()}…`;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function normalizeMobileMarkdown(value) {
|
|
75
|
+
return String(value || '').replace(/\r\n?/gu, '\n').trim();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function countMobileDisplayMathDelimiters(value) {
|
|
79
|
+
return (String(value || '').match(/(?<!\\)\$\$/gu) || []).length;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function trimMobileMarkdownText(value, limit) {
|
|
83
|
+
const normalized = normalizeMobileMarkdown(value);
|
|
84
|
+
if (normalized.length <= limit) {
|
|
85
|
+
return normalized;
|
|
86
|
+
}
|
|
87
|
+
const suffix = '…';
|
|
88
|
+
let candidate = normalized.slice(0, Math.max(0, limit - suffix.length)).trimEnd();
|
|
89
|
+
if (countMobileDisplayMathDelimiters(candidate) % 2 !== 0) {
|
|
90
|
+
const openingIndex = candidate.lastIndexOf('$$');
|
|
91
|
+
candidate = openingIndex >= 0 ? candidate.slice(0, openingIndex).trimEnd() : '';
|
|
92
|
+
}
|
|
93
|
+
return `${candidate}${suffix}`.trim();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function normalizeMobileContent(source) {
|
|
97
|
+
return normalizeMobileMarkdown(source)
|
|
98
|
+
.replace(/\$\$\s*```(?:mermaid|graph|diagram)[\s\S]*?(?:```|$)/giu, '\n')
|
|
99
|
+
.replace(/\r\n?/gu, '\n')
|
|
100
|
+
.replace(/```(?:mermaid|graph|diagram)[\s\S]*?(?:```|$)/giu, '\n')
|
|
101
|
+
.trim();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function formatMobileDisplayMath(source) {
|
|
105
|
+
return normalizeMobileContent(source)
|
|
106
|
+
.replace(/(?<!\\)\$\$([\s\S]*?)(?<!\\)\$\$/gu, (_match, expression) => {
|
|
107
|
+
const body = String(expression || '').trim();
|
|
108
|
+
return body ? `\n\n$$\n${body}\n$$\n\n` : '';
|
|
109
|
+
})
|
|
110
|
+
.replace(/[ \t]+\n/gu, '\n')
|
|
111
|
+
.replace(/\n{3,}/gu, '\n\n')
|
|
112
|
+
.trim();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function extractMobileQueryTerms(message) {
|
|
116
|
+
const source = String(message || '').trim();
|
|
117
|
+
const candidates = [];
|
|
118
|
+
const append = (value) => {
|
|
119
|
+
const term = String(value || '').replace(/^[\s??!!,,。::;;]+|[\s??!!,,。::;;]+$/gu, '').trim();
|
|
120
|
+
if (term.length >= 2 && !candidates.includes(term)) {
|
|
121
|
+
candidates.push(term);
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
const cjkTerms = source.match(/[\u3400-\u9fff]{2,}/gu) || [];
|
|
125
|
+
cjkTerms.forEach((term) => {
|
|
126
|
+
const subject = term
|
|
127
|
+
.replace(/^(?:什么是|什么叫|何为|请问|请解释(?:一下)?|解释(?:一下)?|介绍(?:一下)?|关于|我想知道)/u, '')
|
|
128
|
+
.replace(/(?:的定义|是什么|是怎样|相关知识点|知识点)$/u, '')
|
|
129
|
+
.trim();
|
|
130
|
+
append(subject);
|
|
131
|
+
const predicateSubject = subject.match(/(?:是|为|叫)([\u3400-\u9fff]{2,})$/u);
|
|
132
|
+
append(predicateSubject && predicateSubject[1]);
|
|
133
|
+
append(term);
|
|
134
|
+
});
|
|
135
|
+
const englishTerms = source
|
|
136
|
+
.replace(/\b(?:what|is|are|the|a|an|which|knowledge|points?|should|i|learn|study|define|explain|please)\b/giu, ' ')
|
|
137
|
+
.match(/[A-Za-z][A-Za-z0-9_-]*(?:\s+[A-Za-z][A-Za-z0-9_-]*){0,3}/gu) || [];
|
|
138
|
+
englishTerms.forEach(append);
|
|
139
|
+
append(source);
|
|
140
|
+
return candidates.slice(0, 8);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function takeBoundedMobileAnswerLines(lines, maxLines) {
|
|
144
|
+
const boundedLines = [];
|
|
145
|
+
let displayMathOpen = false;
|
|
146
|
+
const hardLimit = Math.max(maxLines + 12, maxLines);
|
|
147
|
+
for (const line of lines) {
|
|
148
|
+
if (boundedLines.length >= maxLines && !displayMathOpen) {
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
boundedLines.push(line);
|
|
152
|
+
if (countMobileDisplayMathDelimiters(line) % 2 !== 0) {
|
|
153
|
+
displayMathOpen = !displayMathOpen;
|
|
154
|
+
}
|
|
155
|
+
if (boundedLines.length >= hardLimit) {
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (displayMathOpen) {
|
|
160
|
+
let lastMathLine = -1;
|
|
161
|
+
for (let index = boundedLines.length - 1; index >= 0; index -= 1) {
|
|
162
|
+
if (countMobileDisplayMathDelimiters(boundedLines[index]) % 2 !== 0) {
|
|
163
|
+
lastMathLine = index;
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (lastMathLine >= 0) {
|
|
168
|
+
boundedLines.splice(lastMathLine);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return boundedLines;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function selectMobileAnswerSection(content, subject) {
|
|
175
|
+
const source = normalizeMobileContent(content);
|
|
176
|
+
if (!source) {
|
|
177
|
+
return '';
|
|
178
|
+
}
|
|
179
|
+
const subjectKey = String(subject || '').replace(/[^\p{L}\p{N}]+/gu, '').toLowerCase();
|
|
180
|
+
const lines = source.split('\n');
|
|
181
|
+
const sections = [];
|
|
182
|
+
let current = [];
|
|
183
|
+
lines.forEach((line) => {
|
|
184
|
+
if (/^\s*#{1,6}\s+/u.test(line) && current.length > 0) {
|
|
185
|
+
sections.push(current);
|
|
186
|
+
current = [];
|
|
187
|
+
}
|
|
188
|
+
current.push(line);
|
|
189
|
+
});
|
|
190
|
+
if (current.length > 0) {
|
|
191
|
+
sections.push(current);
|
|
192
|
+
}
|
|
193
|
+
const selected = sections.find((section) => {
|
|
194
|
+
const text = section.join(' ');
|
|
195
|
+
const key = text.replace(/[^\p{L}\p{N}]+/gu, '').toLowerCase();
|
|
196
|
+
return subjectKey && key.includes(subjectKey);
|
|
197
|
+
}) || sections[0] || [];
|
|
198
|
+
const usefulLines = selected
|
|
199
|
+
.filter((line) => !/^\s*#{1,6}\s+/u.test(line))
|
|
200
|
+
.map((line) => line.trim())
|
|
201
|
+
.filter(Boolean)
|
|
202
|
+
.filter((line) => !/(?:常见用例|应用场景|关键技术规格|技术规格|比较数学模型|相关技术与比较|参考文献|参考资料|bibliograph|reference|technical specification|comparison model|common use|use case|application(?:s)?|performance metric|related technolog)/iu.test(line));
|
|
203
|
+
return formatMobileDisplayMath(takeBoundedMobileAnswerLines(usefulLines, 6).join('\n\n'));
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function isMobilePrerequisiteNeighbor(neighbor) {
|
|
207
|
+
return String(neighbor && neighbor.direction || '').trim().toLowerCase() === 'incoming'
|
|
208
|
+
&& /prerequisite|precondition|foundation|先修|前置|基础|sequence/u.test(
|
|
209
|
+
String(neighbor && neighbor.edgeType || '')
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function isMobileApplicationNeighbor(neighbor) {
|
|
214
|
+
return String(neighbor && neighbor.direction || '').trim().toLowerCase() === 'outgoing'
|
|
215
|
+
&& /application|use|performance|应用|用例|性能/u.test(
|
|
216
|
+
String(neighbor && neighbor.edgeType || '')
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function buildMobileLearningRoute(primary, matches) {
|
|
221
|
+
if (Array.isArray(primary && primary.learningRoute) && primary.learningRoute.length > 0) {
|
|
222
|
+
return primary.learningRoute
|
|
223
|
+
.slice(0, 6)
|
|
224
|
+
.map((entry, index) => ({
|
|
225
|
+
nodeId: trimMobileText(entry.nodeId || entry.id, 160),
|
|
226
|
+
title: trimMobileText(entry.title || entry.label || entry.nodeId || entry.id, 160),
|
|
227
|
+
role: String(entry.role || 'mechanism').trim() || 'mechanism',
|
|
228
|
+
order: Math.max(1, Math.floor(Number(entry.order) || index + 1)),
|
|
229
|
+
}))
|
|
230
|
+
.filter((entry) => Boolean(entry.nodeId && entry.title));
|
|
231
|
+
}
|
|
232
|
+
const entries = [];
|
|
233
|
+
const seen = new Set();
|
|
234
|
+
const append = (match, role) => {
|
|
235
|
+
const nodeId = String(match && (match.id || match.nodeId) || '').trim();
|
|
236
|
+
const title = String(match && (match.label || match.title || match.id) || '').trim();
|
|
237
|
+
if (!nodeId || !title || seen.has(nodeId)) {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
seen.add(nodeId);
|
|
241
|
+
entries.push({ nodeId, title, role });
|
|
242
|
+
};
|
|
243
|
+
const neighbors = Array.isArray(primary && primary.neighbors) ? primary.neighbors : [];
|
|
244
|
+
neighbors
|
|
245
|
+
.filter(isMobilePrerequisiteNeighbor)
|
|
246
|
+
.sort((left, right) => String(left.label || left.id || '').localeCompare(String(right.label || right.id || '')))
|
|
247
|
+
.forEach((neighbor) => append(neighbor, 'prerequisite'));
|
|
248
|
+
append(primary, 'core');
|
|
249
|
+
neighbors
|
|
250
|
+
.filter((neighbor) => !isMobilePrerequisiteNeighbor(neighbor))
|
|
251
|
+
.sort((left, right) => {
|
|
252
|
+
const leftApplication = isMobileApplicationNeighbor(left) ? 1 : 0;
|
|
253
|
+
const rightApplication = isMobileApplicationNeighbor(right) ? 1 : 0;
|
|
254
|
+
return leftApplication - rightApplication
|
|
255
|
+
|| String(left.label || left.id || '').localeCompare(String(right.label || right.id || ''));
|
|
256
|
+
})
|
|
257
|
+
.forEach((neighbor) => append(neighbor, isMobileApplicationNeighbor(neighbor) ? 'application' : 'mechanism'));
|
|
258
|
+
(Array.isArray(matches) ? matches : []).forEach((match) => append(match, 'mechanism'));
|
|
259
|
+
return entries.slice(0, 6).map((entry, index) => ({
|
|
260
|
+
nodeId: trimMobileText(entry.nodeId, 160),
|
|
261
|
+
title: trimMobileText(entry.title, 160),
|
|
262
|
+
role: entry.role,
|
|
263
|
+
order: index + 1,
|
|
264
|
+
}));
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
async function requestMobileLocalConversation(requestPayload) {
|
|
268
|
+
const storage = window && window.NoteConnectionStorage;
|
|
269
|
+
if (!storage || typeof storage.createProvider !== 'function') {
|
|
270
|
+
throw new Error('mobile_local_storage_unavailable');
|
|
271
|
+
}
|
|
272
|
+
const runtimeCaps = window.__NC_RUNTIME_CAPS || {};
|
|
273
|
+
const provider = storage.createProvider({ runtimeCaps });
|
|
274
|
+
if (!provider || typeof provider.queryKnowledgeBaseExact !== 'function') {
|
|
275
|
+
throw new Error('mobile_exact_query_unavailable');
|
|
276
|
+
}
|
|
277
|
+
const matchesById = new Map();
|
|
278
|
+
for (const term of extractMobileQueryTerms(requestPayload.message)) {
|
|
279
|
+
const result = await provider.queryKnowledgeBaseExact({
|
|
280
|
+
query: term,
|
|
281
|
+
maxMatches: Math.min(8, Math.max(1, Number(requestPayload.topK) || 4)),
|
|
282
|
+
maxNeighborsPerMatch: 8,
|
|
283
|
+
edgeKinds: ['explicit', 'runtime'],
|
|
284
|
+
});
|
|
285
|
+
(Array.isArray(result && result.matches) ? result.matches : []).forEach((match) => {
|
|
286
|
+
if (match && match.id && !matchesById.has(match.id)) {
|
|
287
|
+
matchesById.set(match.id, match);
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
if (matchesById.size >= 8) {
|
|
291
|
+
break;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
const matches = Array.from(matchesById.values()).slice(0, 8);
|
|
295
|
+
if (matches.length <= 0) {
|
|
296
|
+
throw new Error('mobile_exact_query_no_match');
|
|
297
|
+
}
|
|
298
|
+
const primary = matches[0];
|
|
299
|
+
const primaryTitle = String(primary.label || primary.id || '').trim();
|
|
300
|
+
let sourceContent = '';
|
|
301
|
+
if (primary.sourceUri && typeof provider.readContent === 'function') {
|
|
302
|
+
try {
|
|
303
|
+
sourceContent = await provider.readContent(primary.sourceUri);
|
|
304
|
+
} catch (_error) {
|
|
305
|
+
sourceContent = '';
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
const useChinese = /[\u3400-\u9fff]/u.test(`${requestPayload.message || ''}${primaryTitle}`);
|
|
309
|
+
const directAnswer = selectMobileAnswerSection(sourceContent, primaryTitle)
|
|
310
|
+
|| (useChinese
|
|
311
|
+
? `本地知识图谱已定位到“${primaryTitle}”,但无法读取对应正文。`
|
|
312
|
+
: `${primaryTitle} was located in the local knowledge projection, but its source text is unavailable.`);
|
|
313
|
+
const boundedDirectAnswer = trimMobileMarkdownText(formatMobileDisplayMath(directAnswer), 2400);
|
|
314
|
+
const route = buildMobileLearningRoute(primary, matches);
|
|
315
|
+
const citations = matches.slice(0, 4).map((match) => ({
|
|
316
|
+
citationId: `mobile:${match.id}`,
|
|
317
|
+
title: trimMobileText(match.label || match.id, 160),
|
|
318
|
+
sourcePath: trimMobileText(match.sourceUri || '', 320),
|
|
319
|
+
})).filter((citation) => citation.sourcePath);
|
|
320
|
+
return {
|
|
321
|
+
userId: requestPayload.userId,
|
|
322
|
+
sessionId: requestPayload.sessionId,
|
|
323
|
+
assistantMessage: boundedDirectAnswer,
|
|
324
|
+
answer: boundedDirectAnswer,
|
|
325
|
+
message: boundedDirectAnswer,
|
|
326
|
+
responseProfile: 'mobile_compact',
|
|
327
|
+
mobileProjection: {
|
|
328
|
+
schemaVersion: 1,
|
|
329
|
+
primarySubject: trimMobileText(primaryTitle, 160),
|
|
330
|
+
directAnswer: boundedDirectAnswer,
|
|
331
|
+
route,
|
|
332
|
+
citations,
|
|
333
|
+
},
|
|
334
|
+
assistantBlocks: [],
|
|
335
|
+
knowledgePoints: [],
|
|
336
|
+
citations: [],
|
|
337
|
+
recalledMemories: [],
|
|
338
|
+
memoryActions: [],
|
|
339
|
+
summary: {
|
|
340
|
+
generatedAt: new Date().toISOString(),
|
|
341
|
+
topK: Number(requestPayload.topK) || 4,
|
|
342
|
+
returnedKnowledgePoints: route.length,
|
|
343
|
+
returnedCitations: citations.length,
|
|
344
|
+
recalledMemoryCount: 0,
|
|
345
|
+
appliedMemoryCount: 0,
|
|
346
|
+
queryEvidenceCoverageRatioPct: sourceContent ? 100 : 0,
|
|
347
|
+
},
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
|
|
46
351
|
function normalizeActiveSourceTarget(value) {
|
|
47
352
|
const normalized = String(value || '').trim();
|
|
48
353
|
return normalized || 'ALL_FOLDERS';
|
|
@@ -265,6 +570,225 @@
|
|
|
265
570
|
return 'en';
|
|
266
571
|
}
|
|
267
572
|
|
|
573
|
+
function normalizeAnswerLanguage(value) {
|
|
574
|
+
const normalized = String(value || '').trim().toLowerCase().split('-')[0];
|
|
575
|
+
return normalized === 'zh' ? 'zh' : 'en';
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
function getAnswerLanguage() {
|
|
579
|
+
const selector = getElement('agent-workspace-answer-language-select');
|
|
580
|
+
const selected = selector && typeof selector.value === 'string' ? selector.value : '';
|
|
581
|
+
if (selected === 'en' || selected === 'zh') {
|
|
582
|
+
return selected;
|
|
583
|
+
}
|
|
584
|
+
if (typeof localStorage !== 'undefined') {
|
|
585
|
+
const stored = String(localStorage.getItem(ANSWER_LANGUAGE_STORAGE_KEY) || '').trim();
|
|
586
|
+
if (stored === 'en' || stored === 'zh') {
|
|
587
|
+
return stored;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
return normalizeAnswerLanguage(getActiveLanguage());
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
function renderAnswerLanguageSelector() {
|
|
594
|
+
const selector = getElement('agent-workspace-answer-language-select');
|
|
595
|
+
if (!selector) {
|
|
596
|
+
return;
|
|
597
|
+
}
|
|
598
|
+
const stored = typeof localStorage !== 'undefined'
|
|
599
|
+
? String(localStorage.getItem(ANSWER_LANGUAGE_STORAGE_KEY) || '').trim()
|
|
600
|
+
: '';
|
|
601
|
+
const targetLanguage = stored === 'en' || stored === 'zh'
|
|
602
|
+
? stored
|
|
603
|
+
: normalizeAnswerLanguage(getActiveLanguage());
|
|
604
|
+
selector.value = targetLanguage;
|
|
605
|
+
updateAnswerLanguageSummary(targetLanguage);
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
function updateAnswerLanguageSummary(language) {
|
|
609
|
+
const summary = getElement('agent-workspace-answer-language-summary');
|
|
610
|
+
if (!summary) {
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
summary.textContent = language === 'zh'
|
|
614
|
+
? translate('agentWorkspace.answerLanguage.summaryChinese', 'Chinese answer')
|
|
615
|
+
: translate('agentWorkspace.answerLanguage.summaryEnglish', 'English answer');
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
function bindAnswerLanguageSelector() {
|
|
619
|
+
const selector = getElement('agent-workspace-answer-language-select');
|
|
620
|
+
if (!selector || selector.getAttribute('data-agent-answer-language-bound') === 'true') {
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
623
|
+
selector.setAttribute('data-agent-answer-language-bound', 'true');
|
|
624
|
+
selector.addEventListener('change', function () {
|
|
625
|
+
const language = normalizeAnswerLanguage(selector.value);
|
|
626
|
+
selector.value = language;
|
|
627
|
+
if (typeof localStorage !== 'undefined') {
|
|
628
|
+
localStorage.setItem(ANSWER_LANGUAGE_STORAGE_KEY, language);
|
|
629
|
+
}
|
|
630
|
+
updateAnswerLanguageSummary(language);
|
|
631
|
+
});
|
|
632
|
+
if (window.i18n && typeof window.i18n.onLanguageChange === 'function') {
|
|
633
|
+
window.i18n.onLanguageChange(function () {
|
|
634
|
+
const hasExplicitChoice = typeof localStorage !== 'undefined'
|
|
635
|
+
&& ['en', 'zh'].includes(String(localStorage.getItem(ANSWER_LANGUAGE_STORAGE_KEY) || '').trim());
|
|
636
|
+
if (!hasExplicitChoice) {
|
|
637
|
+
renderAnswerLanguageSelector();
|
|
638
|
+
}
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
function normalizeResponseMode(value) {
|
|
644
|
+
return String(value || '').trim().toLowerCase() === 'full' ? 'full' : 'slim';
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
function getResponseMode() {
|
|
648
|
+
const selector = getElement('agent-workspace-response-mode-select');
|
|
649
|
+
const selected = selector && typeof selector.value === 'string' ? selector.value : '';
|
|
650
|
+
if (selected === 'slim' || selected === 'full') {
|
|
651
|
+
return selected;
|
|
652
|
+
}
|
|
653
|
+
if (typeof localStorage !== 'undefined') {
|
|
654
|
+
const stored = normalizeResponseMode(localStorage.getItem(RESPONSE_MODE_STORAGE_KEY));
|
|
655
|
+
if (stored) {
|
|
656
|
+
return stored;
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
return 'slim';
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
function updateResponseModeSummary(mode) {
|
|
663
|
+
const summary = getElement('agent-workspace-response-mode-summary');
|
|
664
|
+
if (!summary) {
|
|
665
|
+
return;
|
|
666
|
+
}
|
|
667
|
+
summary.textContent = mode === 'full'
|
|
668
|
+
? translate('agentWorkspace.responseMode.summaryFull', 'Complete evidence-bounded technical report')
|
|
669
|
+
: translate('agentWorkspace.responseMode.summarySlim', 'Short grounded answer');
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
function renderResponseModeSelector() {
|
|
673
|
+
const selector = getElement('agent-workspace-response-mode-select');
|
|
674
|
+
if (!selector) {
|
|
675
|
+
return;
|
|
676
|
+
}
|
|
677
|
+
const stored = typeof localStorage !== 'undefined'
|
|
678
|
+
? normalizeResponseMode(localStorage.getItem(RESPONSE_MODE_STORAGE_KEY))
|
|
679
|
+
: 'slim';
|
|
680
|
+
selector.value = stored;
|
|
681
|
+
updateResponseModeSummary(stored);
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
function bindResponseModeSelector() {
|
|
685
|
+
const selector = getElement('agent-workspace-response-mode-select');
|
|
686
|
+
if (!selector || selector.getAttribute('data-agent-response-mode-bound') === 'true') {
|
|
687
|
+
return;
|
|
688
|
+
}
|
|
689
|
+
selector.setAttribute('data-agent-response-mode-bound', 'true');
|
|
690
|
+
selector.addEventListener('change', function () {
|
|
691
|
+
const mode = normalizeResponseMode(selector.value);
|
|
692
|
+
selector.value = mode;
|
|
693
|
+
if (typeof localStorage !== 'undefined') {
|
|
694
|
+
localStorage.setItem(RESPONSE_MODE_STORAGE_KEY, mode);
|
|
695
|
+
}
|
|
696
|
+
updateResponseModeSummary(mode);
|
|
697
|
+
});
|
|
698
|
+
if (window.i18n && typeof window.i18n.onLanguageChange === 'function') {
|
|
699
|
+
window.i18n.onLanguageChange(function () {
|
|
700
|
+
updateResponseModeSummary(getResponseMode());
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
function normalizeResponseBudgetMode(value) {
|
|
706
|
+
const normalized = String(value || '').trim().toLowerCase().replace(/[-\s]+/gu, '_');
|
|
707
|
+
return ['unbounded', 'no_cap', 'nocap', 'no_limit', 'nolimit', 'unlimited'].includes(normalized)
|
|
708
|
+
? 'unbounded'
|
|
709
|
+
: 'adaptive';
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
function getResponseBudgetMode() {
|
|
713
|
+
const selector = getElement('agent-workspace-response-budget-select');
|
|
714
|
+
const selected = selector && typeof selector.value === 'string' ? selector.value : '';
|
|
715
|
+
if (selected === 'adaptive' || selected === 'unbounded') {
|
|
716
|
+
return selected;
|
|
717
|
+
}
|
|
718
|
+
if (typeof localStorage !== 'undefined') {
|
|
719
|
+
return normalizeResponseBudgetMode(localStorage.getItem(RESPONSE_BUDGET_MODE_STORAGE_KEY));
|
|
720
|
+
}
|
|
721
|
+
return 'adaptive';
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
function getResponseBudgetCapability() {
|
|
725
|
+
if (isMobileNativeRuntime()) {
|
|
726
|
+
return undefined;
|
|
727
|
+
}
|
|
728
|
+
const navigatorObject = window && window.navigator ? window.navigator : null;
|
|
729
|
+
const deviceMemory = Number(navigatorObject && navigatorObject.deviceMemory);
|
|
730
|
+
const hardwareConcurrency = Number(navigatorObject && navigatorObject.hardwareConcurrency);
|
|
731
|
+
const memoryClass = Number.isFinite(deviceMemory) && deviceMemory > 0
|
|
732
|
+
? (deviceMemory >= 8 ? 'high' : deviceMemory >= 4 ? 'standard' : 'low')
|
|
733
|
+
: 'standard';
|
|
734
|
+
const workload = memoryClass === 'high'
|
|
735
|
+
&& Number.isFinite(hardwareConcurrency)
|
|
736
|
+
&& hardwareConcurrency >= 8
|
|
737
|
+
? 'max'
|
|
738
|
+
: getResponseMode() === 'full'
|
|
739
|
+
? 'large'
|
|
740
|
+
: 'normal';
|
|
741
|
+
return { memoryClass, workload };
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
function updateResponseBudgetSummary(mode) {
|
|
745
|
+
const summary = getElement('agent-workspace-response-budget-summary');
|
|
746
|
+
if (!summary) {
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
749
|
+
summary.textContent = mode === 'unbounded'
|
|
750
|
+
? translate('agentWorkspace.responseBudget.summaryUnbounded', 'Product cap disabled; runtime safety limits remain')
|
|
751
|
+
: translate('agentWorkspace.responseBudget.summaryAdaptive', 'Host-adaptive report budget');
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
function renderResponseBudgetSelector() {
|
|
755
|
+
const selector = getElement('agent-workspace-response-budget-select');
|
|
756
|
+
const control = selector && selector.closest('[data-agent-desktop-only]');
|
|
757
|
+
if (!selector) {
|
|
758
|
+
return;
|
|
759
|
+
}
|
|
760
|
+
const mobile = isMobileNativeRuntime();
|
|
761
|
+
if (control) {
|
|
762
|
+
control.hidden = mobile;
|
|
763
|
+
}
|
|
764
|
+
const stored = typeof localStorage !== 'undefined'
|
|
765
|
+
? normalizeResponseBudgetMode(localStorage.getItem(RESPONSE_BUDGET_MODE_STORAGE_KEY))
|
|
766
|
+
: 'adaptive';
|
|
767
|
+
selector.value = stored;
|
|
768
|
+
updateResponseBudgetSummary(stored);
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
function bindResponseBudgetSelector() {
|
|
772
|
+
const selector = getElement('agent-workspace-response-budget-select');
|
|
773
|
+
if (!selector || selector.getAttribute('data-agent-response-budget-bound') === 'true') {
|
|
774
|
+
return;
|
|
775
|
+
}
|
|
776
|
+
selector.setAttribute('data-agent-response-budget-bound', 'true');
|
|
777
|
+
selector.addEventListener('change', function () {
|
|
778
|
+
const mode = normalizeResponseBudgetMode(selector.value);
|
|
779
|
+
selector.value = mode;
|
|
780
|
+
if (typeof localStorage !== 'undefined') {
|
|
781
|
+
localStorage.setItem(RESPONSE_BUDGET_MODE_STORAGE_KEY, mode);
|
|
782
|
+
}
|
|
783
|
+
updateResponseBudgetSummary(mode);
|
|
784
|
+
});
|
|
785
|
+
if (window.i18n && typeof window.i18n.onLanguageChange === 'function') {
|
|
786
|
+
window.i18n.onLanguageChange(function () {
|
|
787
|
+
updateResponseBudgetSummary(getResponseBudgetMode());
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
|
|
268
792
|
function formatTemplate(template, params) {
|
|
269
793
|
return String(template || '').replace(/\{(\w+)\}/g, function (_match, name) {
|
|
270
794
|
return Object.prototype.hasOwnProperty.call(params || {}, name)
|
|
@@ -974,7 +1498,16 @@
|
|
|
974
1498
|
}
|
|
975
1499
|
|
|
976
1500
|
function buildConversationGroundingPayload(result) {
|
|
977
|
-
const
|
|
1501
|
+
const mobileProjection = result && result.mobileProjection && typeof result.mobileProjection === 'object'
|
|
1502
|
+
? result.mobileProjection
|
|
1503
|
+
: null;
|
|
1504
|
+
const responseCitations = Array.isArray(result && result.citations) ? result.citations : [];
|
|
1505
|
+
const projectedCitations = Array.isArray(mobileProjection && mobileProjection.citations)
|
|
1506
|
+
? mobileProjection.citations
|
|
1507
|
+
: [];
|
|
1508
|
+
const citationCount = responseCitations.length > 0
|
|
1509
|
+
? responseCitations.length
|
|
1510
|
+
: projectedCitations.length;
|
|
978
1511
|
const memoryCount = Array.isArray(result && result.recalledMemories) ? result.recalledMemories.length : 0;
|
|
979
1512
|
const memoryActionCount = Array.isArray(result && result.memoryActions) ? result.memoryActions.length : 0;
|
|
980
1513
|
const trace = result && result.trace && typeof result.trace === 'object' ? result.trace : null;
|
|
@@ -994,6 +1527,15 @@
|
|
|
994
1527
|
const ragFailureClassifications = Array.isArray(trace && trace.ragFailureClassifications)
|
|
995
1528
|
? trace.ragFailureClassifications.filter((classification) => classification && typeof classification === 'object')
|
|
996
1529
|
: [];
|
|
1530
|
+
const graphAnswerPlan = trace && trace.graphAnswerPlan && typeof trace.graphAnswerPlan === 'object'
|
|
1531
|
+
? trace.graphAnswerPlan
|
|
1532
|
+
: null;
|
|
1533
|
+
const graphAnswerCoverage = trace && trace.graphAnswerCoverage && typeof trace.graphAnswerCoverage === 'object'
|
|
1534
|
+
? trace.graphAnswerCoverage
|
|
1535
|
+
: null;
|
|
1536
|
+
const graphExpansion = trace && trace.graphExpansion && typeof trace.graphExpansion === 'object'
|
|
1537
|
+
? trace.graphExpansion
|
|
1538
|
+
: null;
|
|
997
1539
|
if (
|
|
998
1540
|
citationCount <= 0
|
|
999
1541
|
&& memoryCount <= 0
|
|
@@ -1004,6 +1546,9 @@
|
|
|
1004
1546
|
&& !ragContextPack
|
|
1005
1547
|
&& !ragSufficiencyReview
|
|
1006
1548
|
&& !ragRecovery
|
|
1549
|
+
&& !graphAnswerPlan
|
|
1550
|
+
&& !graphAnswerCoverage
|
|
1551
|
+
&& !graphExpansion
|
|
1007
1552
|
&& ragFailureClassifications.length <= 0
|
|
1008
1553
|
) {
|
|
1009
1554
|
return null;
|
|
@@ -1032,6 +1577,9 @@
|
|
|
1032
1577
|
ragSufficiencyReview,
|
|
1033
1578
|
ragRecovery,
|
|
1034
1579
|
ragFailureClassifications,
|
|
1580
|
+
graphAnswerPlan,
|
|
1581
|
+
graphAnswerCoverage,
|
|
1582
|
+
graphExpansion,
|
|
1035
1583
|
};
|
|
1036
1584
|
}
|
|
1037
1585
|
|
|
@@ -1302,6 +1850,73 @@
|
|
|
1302
1850
|
});
|
|
1303
1851
|
}
|
|
1304
1852
|
|
|
1853
|
+
function formatMobileRouteRole(role, useChinese) {
|
|
1854
|
+
const normalized = String(role || '').trim().toLowerCase();
|
|
1855
|
+
if (!useChinese) {
|
|
1856
|
+
return normalized || 'related';
|
|
1857
|
+
}
|
|
1858
|
+
return {
|
|
1859
|
+
prerequisite: '前置',
|
|
1860
|
+
core: '核心',
|
|
1861
|
+
mechanism: '机制',
|
|
1862
|
+
application: '应用',
|
|
1863
|
+
}[normalized] || '相关';
|
|
1864
|
+
}
|
|
1865
|
+
|
|
1866
|
+
function buildMobileConversationMessage(result) {
|
|
1867
|
+
if (!result || typeof result !== 'object' || result.responseProfile !== 'mobile_compact') {
|
|
1868
|
+
return '';
|
|
1869
|
+
}
|
|
1870
|
+
const projection = result.mobileProjection && typeof result.mobileProjection === 'object'
|
|
1871
|
+
? result.mobileProjection
|
|
1872
|
+
: {};
|
|
1873
|
+
const directAnswer = normalizeMobileMarkdown(
|
|
1874
|
+
projection.directAnswer || result.answer || result.assistantMessage || result.message || ''
|
|
1875
|
+
);
|
|
1876
|
+
const route = Array.isArray(projection.route)
|
|
1877
|
+
? projection.route.filter((node) => node && typeof node === 'object')
|
|
1878
|
+
: [];
|
|
1879
|
+
if (route.length <= 0) {
|
|
1880
|
+
return directAnswer;
|
|
1881
|
+
}
|
|
1882
|
+
const useChinese = /[\u3400-\u9fff]/u.test(
|
|
1883
|
+
`${projection.primarySubject || ''}${directAnswer}`
|
|
1884
|
+
);
|
|
1885
|
+
const heading = useChinese ? '### 建议学习路径' : '### Suggested learning path';
|
|
1886
|
+
const items = route.map((node, index) => {
|
|
1887
|
+
const order = Math.max(1, Math.floor(Number(node.order) || index + 1));
|
|
1888
|
+
const title = trimMobileText(node.title || node.nodeId, 160);
|
|
1889
|
+
const role = formatMobileRouteRole(node.role, useChinese);
|
|
1890
|
+
if (!title) {
|
|
1891
|
+
return '';
|
|
1892
|
+
}
|
|
1893
|
+
return useChinese
|
|
1894
|
+
? `${order}. **${title}**(${role})`
|
|
1895
|
+
: `${order}. **${title}** (${role})`;
|
|
1896
|
+
}).filter(Boolean);
|
|
1897
|
+
return [directAnswer, heading, items.join('\n')].filter(Boolean).join('\n\n');
|
|
1898
|
+
}
|
|
1899
|
+
|
|
1900
|
+
function buildMobileStructuredAnswerBlock(result) {
|
|
1901
|
+
const directAnswer = buildMobileConversationMessage(result);
|
|
1902
|
+
if (!directAnswer) {
|
|
1903
|
+
return null;
|
|
1904
|
+
}
|
|
1905
|
+
const projection = result && result.mobileProjection && typeof result.mobileProjection === 'object'
|
|
1906
|
+
? result.mobileProjection
|
|
1907
|
+
: {};
|
|
1908
|
+
const useChinese = /[\u3400-\u9fff]/u.test(`${projection.primarySubject || ''}${directAnswer}`);
|
|
1909
|
+
return {
|
|
1910
|
+
blockId: 'mobile_projection_answer',
|
|
1911
|
+
type: 'structured_answer',
|
|
1912
|
+
title: useChinese ? '可信回答' : 'Grounded Answer',
|
|
1913
|
+
directAnswer,
|
|
1914
|
+
knowledgePointCount: 0,
|
|
1915
|
+
citationCount: Array.isArray(projection.citations) ? projection.citations.length : 0,
|
|
1916
|
+
recalledMemoryCount: 0,
|
|
1917
|
+
};
|
|
1918
|
+
}
|
|
1919
|
+
|
|
1305
1920
|
function appendAssistantConversationResult(result) {
|
|
1306
1921
|
const controller = getController();
|
|
1307
1922
|
if (window && typeof window === 'object') {
|
|
@@ -1310,11 +1925,22 @@
|
|
|
1310
1925
|
const assistantBlocks = Array.isArray(result && result.assistantBlocks)
|
|
1311
1926
|
? result.assistantBlocks.filter((block) => block && typeof block === 'object')
|
|
1312
1927
|
: [];
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1928
|
+
// The conversation surface has one public release boundary: the
|
|
1929
|
+
// structured answer. Other block types are durable metadata or
|
|
1930
|
+
// capability artifacts and must stay outside the chat DOM; allowing
|
|
1931
|
+
// them through here reintroduces the Answer Context/Evidence/HTML
|
|
1932
|
+
// leakage that the backend additive contract intentionally permits.
|
|
1933
|
+
const structuredAnswerBlock = assistantBlocks.find((block) => (
|
|
1934
|
+
String(block && block.type || '').trim() === 'structured_answer'
|
|
1935
|
+
));
|
|
1936
|
+
const mobileStructuredAnswerBlock = !structuredAnswerBlock
|
|
1937
|
+
? buildMobileStructuredAnswerBlock(result)
|
|
1938
|
+
: null;
|
|
1939
|
+
const visibleAssistantBlocks = structuredAnswerBlock
|
|
1940
|
+
? [structuredAnswerBlock]
|
|
1941
|
+
: (mobileStructuredAnswerBlock ? [mobileStructuredAnswerBlock] : []);
|
|
1942
|
+
const mobileFallbackMessage = buildMobileConversationMessage(result);
|
|
1943
|
+
const fallbackMessage = mobileFallbackMessage || String(
|
|
1318
1944
|
result && (
|
|
1319
1945
|
result.assistantMessage
|
|
1320
1946
|
|| result.answer
|
|
@@ -5089,7 +5715,14 @@
|
|
|
5089
5715
|
sessionId: getOrCreateConversationSessionId(userId),
|
|
5090
5716
|
activeTarget: requestContext.activeTarget,
|
|
5091
5717
|
message,
|
|
5718
|
+
answerLanguage: getAnswerLanguage(),
|
|
5719
|
+
// Native mobile always consumes the bounded projection; a
|
|
5720
|
+
// desktop full-report preference must not inflate the APK path.
|
|
5721
|
+
responseMode: isMobileNativeRuntime() ? 'slim' : getResponseMode(),
|
|
5722
|
+
...(isMobileNativeRuntime() ? {} : { responseBudgetMode: getResponseBudgetMode() }),
|
|
5723
|
+
...(isMobileNativeRuntime() ? {} : { responseBudgetCapability: getResponseBudgetCapability() }),
|
|
5092
5724
|
topK: 6,
|
|
5725
|
+
...(isMobileNativeRuntime() ? { responseProfile: 'mobile_compact' } : {}),
|
|
5093
5726
|
memoryNamespace: 'conversation',
|
|
5094
5727
|
scope: requestContext.scope,
|
|
5095
5728
|
};
|
|
@@ -5099,7 +5732,26 @@
|
|
|
5099
5732
|
transport: 'SSE',
|
|
5100
5733
|
activeTarget: requestContext.activeTarget,
|
|
5101
5734
|
});
|
|
5102
|
-
|
|
5735
|
+
let conversationCall;
|
|
5736
|
+
if (isMobileNativeRuntime()) {
|
|
5737
|
+
const mobileStartedAt = Date.now();
|
|
5738
|
+
try {
|
|
5739
|
+
const result = await requestMobileLocalConversation(requestPayload);
|
|
5740
|
+
conversationCall = {
|
|
5741
|
+
result,
|
|
5742
|
+
transport: 'Mobile local exact',
|
|
5743
|
+
latencyMs: Date.now() - mobileStartedAt,
|
|
5744
|
+
};
|
|
5745
|
+
} catch (localError) {
|
|
5746
|
+
// Local exact analysis is the preferred low-memory path. A
|
|
5747
|
+
// remote bounded projection remains an additive fallback when
|
|
5748
|
+
// the projection is missing or the local index cannot load.
|
|
5749
|
+
console.warn('[AgentWorkspace] Mobile local analysis unavailable; using bounded remote fallback.', localError);
|
|
5750
|
+
conversationCall = await requestConversationWithStreamingFallback(requestPayload);
|
|
5751
|
+
}
|
|
5752
|
+
} else {
|
|
5753
|
+
conversationCall = await requestConversationWithStreamingFallback(requestPayload);
|
|
5754
|
+
}
|
|
5103
5755
|
const result = conversationCall && typeof conversationCall === 'object' && conversationCall.result
|
|
5104
5756
|
? conversationCall.result
|
|
5105
5757
|
: conversationCall;
|
|
@@ -5249,8 +5901,14 @@
|
|
|
5249
5901
|
controller.init();
|
|
5250
5902
|
bindWorkspaceDrawerChrome();
|
|
5251
5903
|
bindWorkspaceScopeSelector();
|
|
5904
|
+
bindAnswerLanguageSelector();
|
|
5905
|
+
bindResponseModeSelector();
|
|
5906
|
+
bindResponseBudgetSelector();
|
|
5252
5907
|
observeGlobalScopeOptions();
|
|
5253
5908
|
renderWorkspaceScopeSelector();
|
|
5909
|
+
renderAnswerLanguageSelector();
|
|
5910
|
+
renderResponseModeSelector();
|
|
5911
|
+
renderResponseBudgetSelector();
|
|
5254
5912
|
updateConversationApiStatus({
|
|
5255
5913
|
state: 'idle',
|
|
5256
5914
|
endpoint: AGENT_CONVERSATION_ENDPOINT,
|