noteconnection 1.7.0 → 1.8.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.
Files changed (211) hide show
  1. package/LICENSE +674 -21
  2. package/README.md +242 -62
  3. package/dist/src/agent_workspace.contract.parity.test.js +475 -0
  4. package/dist/src/agent_workspace.frontend.test.js +9989 -0
  5. package/dist/src/agent_workspace.locale.contract.test.js +95 -0
  6. package/dist/src/agent_workspace.runtime.behavior.test.js +5072 -0
  7. package/dist/src/copy.assets.contract.test.js +130 -0
  8. package/dist/src/core/PathBridge.js +28 -3
  9. package/dist/src/export/WorkspaceExportBundle.js +1130 -0
  10. package/dist/src/export/WorkspaceExportBundle.test.js +1480 -0
  11. package/dist/src/export/index.js +18 -0
  12. package/dist/src/export/types.js +2 -0
  13. package/dist/src/fixrisk.issue.verifier.contract.test.js +3 -1
  14. package/dist/src/foundation.ann.runtime.contract.test.js +81 -0
  15. package/dist/src/foundation.release.evidence.contract.test.js +406 -0
  16. package/dist/src/foundation.sqlite.runtime.contract.test.js +82 -0
  17. package/dist/src/frontend/README.md +242 -62
  18. package/dist/src/frontend/agent_workspace.js +5353 -0
  19. package/dist/src/frontend/agent_workspace_runtime.js +4434 -0
  20. package/dist/src/frontend/analysis.js +31 -4
  21. package/dist/src/frontend/app.js +2178 -62
  22. package/dist/src/frontend/focus_mode_interactions.js +33 -0
  23. package/dist/src/frontend/godot_future_path_renderer.js +540 -0
  24. package/dist/src/frontend/godot_tree_interactions.js +178 -0
  25. package/dist/src/frontend/graph_state.mjs +105 -0
  26. package/dist/src/frontend/hosted_future_path_runtime.js +157 -0
  27. package/dist/src/frontend/i18n.mjs +186 -0
  28. package/dist/src/frontend/index.html +641 -266
  29. package/dist/src/frontend/layout_gpu.js +12 -4
  30. package/dist/src/frontend/locales/en.json +721 -5
  31. package/dist/src/frontend/locales/zh.json +721 -5
  32. package/dist/src/frontend/main.mjs +60 -0
  33. package/dist/src/frontend/markdown_runtime.js +827 -0
  34. package/dist/src/frontend/notemd.css +49 -0
  35. package/dist/src/frontend/notemd.html +7 -1
  36. package/dist/src/frontend/notemd.js +64 -0
  37. package/dist/src/frontend/path.html +107 -0
  38. package/dist/src/frontend/path_app.js +2108 -130
  39. package/dist/src/frontend/path_layout.mjs +143 -0
  40. package/dist/src/frontend/path_mermaid_utils.mjs +108 -0
  41. package/dist/src/frontend/path_modules_bridge.js +486 -0
  42. package/dist/src/frontend/path_state.mjs +118 -0
  43. package/dist/src/frontend/path_styles.css +146 -0
  44. package/dist/src/frontend/path_worker_bridge.mjs +85 -0
  45. package/dist/src/frontend/reader.js +393 -33
  46. package/dist/src/frontend/runtime_bridge.js +67 -54
  47. package/dist/src/frontend/runtime_bridge.mjs +279 -0
  48. package/dist/src/frontend/settings.js +130 -12
  49. package/dist/src/frontend/source_manager.js +190 -21
  50. package/dist/src/frontend/styles.css +2720 -72
  51. package/dist/src/frontend/workbench_state.mjs +101 -0
  52. package/dist/src/frontend/workspace_panes.js +10168 -0
  53. package/dist/src/frontend.locale.contract.test.js +62 -0
  54. package/dist/src/godot.sidecar.bootstrap.contract.test.js +244 -0
  55. package/dist/src/indexing/IndexLifecycle.js +195 -0
  56. package/dist/src/indexing/IndexLifecycle.test.js +49 -0
  57. package/dist/src/indexing/SegmentBuilder.js +64 -0
  58. package/dist/src/indexing/UnitBuilder.js +48 -0
  59. package/dist/src/indexing/types.js +2 -0
  60. package/dist/src/knowledge.api.contract.test.js +170 -0
  61. package/dist/src/learning/KnowledgeLearningPlatform.js +10386 -0
  62. package/dist/src/learning/KnowledgeLearningPlatform.persistence.test.js +327 -0
  63. package/dist/src/learning/KnowledgeLearningPlatform.program-f.test.js +99 -0
  64. package/dist/src/learning/KnowledgeLearningPlatform.test.js +2971 -0
  65. package/dist/src/learning/KnowledgeWorkspaceConversationRegression.js +2974 -0
  66. package/dist/src/learning/KnowledgeWorkspaceConversationRegression.test.js +3928 -0
  67. package/dist/src/learning/answerReleaseReview.js +4319 -0
  68. package/dist/src/learning/answerReleaseReview.test.js +2888 -0
  69. package/dist/src/learning/api.js +2 -0
  70. package/dist/src/learning/conversationComposer.js +1480 -0
  71. package/dist/src/learning/conversationComposer.test.js +1817 -0
  72. package/dist/src/learning/domains/ConversationManager.js +53 -0
  73. package/dist/src/learning/domains/KnowledgeIngestor.js +238 -0
  74. package/dist/src/learning/domains/KnowledgeQuerier.js +187 -0
  75. package/dist/src/learning/domains/MasteryEngine.js +387 -0
  76. package/dist/src/learning/domains/MemoryPolicyManager.js +408 -0
  77. package/dist/src/learning/domains/QualityEvaluator.js +307 -0
  78. package/dist/src/learning/domains/TutorRouter.js +313 -0
  79. package/dist/src/learning/domains/index.js +33 -0
  80. package/dist/src/learning/domains/types.js +7 -0
  81. package/dist/src/learning/errors.js +29 -0
  82. package/dist/src/learning/evidenceContextAssembler.js +1176 -0
  83. package/dist/src/learning/evidenceContextAssembler.test.js +6332 -0
  84. package/dist/src/learning/graphContextAssembler.js +870 -0
  85. package/dist/src/learning/graphContextAssembler.test.js +1033 -0
  86. package/dist/src/learning/index.js +28 -0
  87. package/dist/src/learning/queryBackend.js +1898 -0
  88. package/dist/src/learning/queryBackend.test.js +955 -0
  89. package/dist/src/learning/ragContextPack.js +257 -0
  90. package/dist/src/learning/ragContextPack.test.js +160 -0
  91. package/dist/src/learning/ragPublicText.js +38 -0
  92. package/dist/src/learning/ragSufficiencyJudge.js +161 -0
  93. package/dist/src/learning/ragSufficiencyJudge.test.js +177 -0
  94. package/dist/src/learning/ragSufficiencyProviderJudge.js +227 -0
  95. package/dist/src/learning/ragSufficiencyProviderJudge.test.js +156 -0
  96. package/dist/src/learning/requestNormalization.js +198 -0
  97. package/dist/src/learning/runtimeCapability.js +4677 -0
  98. package/dist/src/learning/runtimeCapability.test.js +3635 -0
  99. package/dist/src/learning/store.js +1240 -0
  100. package/dist/src/learning/store.test.js +1126 -0
  101. package/dist/src/learning/tutorAdapter.js +2 -0
  102. package/dist/src/learning/types.js +2 -0
  103. package/dist/src/learning/vectorAccelerationAdapter.js +942 -0
  104. package/dist/src/learning/vectorAccelerationAdapter.test.js +382 -0
  105. package/dist/src/lfs.asset.policy.contract.test.js +153 -0
  106. package/dist/src/license.policy.contract.test.js +66 -0
  107. package/dist/src/memory/MemoryGovernance.js +74 -0
  108. package/dist/src/memory/MemoryGovernance.test.js +46 -0
  109. package/dist/src/memory/types.js +2 -0
  110. package/dist/src/mermaid.frontend.guard.contract.test.js +77 -0
  111. package/dist/src/middleware/auth.js +17 -0
  112. package/dist/src/middleware/body-parser.js +45 -0
  113. package/dist/src/middleware/cors.js +44 -0
  114. package/dist/src/middleware/index.js +21 -0
  115. package/dist/src/middleware/request-trace.js +96 -0
  116. package/dist/src/notemd/AppConfigToml.js +6 -4
  117. package/dist/src/notemd/MermaidProcessor.js +400 -50
  118. package/dist/src/notemd/NotemdService.js +498 -13
  119. package/dist/src/notemd/PromptManager.js +15 -0
  120. package/dist/src/notemd/cli/commands.js +357 -0
  121. package/dist/src/notemd/cli/dispatcher.js +225 -0
  122. package/dist/src/notemd/cli/index.js +169 -0
  123. package/dist/src/notemd/cli/parser.js +68 -0
  124. package/dist/src/notemd/cli/types.js +2 -0
  125. package/dist/src/notemd/constants.js +43 -0
  126. package/dist/src/notemd/diagram/diagramGenerationService.js +78 -0
  127. package/dist/src/notemd/diagram/diagramSpec.js +79 -0
  128. package/dist/src/notemd/diagram/diagramSpecResponseParser.js +131 -0
  129. package/dist/src/notemd/diagram/intent.js +95 -0
  130. package/dist/src/notemd/diagram/planner.js +71 -0
  131. package/dist/src/notemd/diagram/prompts/diagramSpecPrompt.js +42 -0
  132. package/dist/src/notemd/diagram/types.js +18 -0
  133. package/dist/src/notemd/index.js +26 -0
  134. package/dist/src/notemd/operations/capabilityManifest.js +23 -0
  135. package/dist/src/notemd/operations/cliContracts.js +17 -0
  136. package/dist/src/notemd/operations/configProfileCommands.js +85 -0
  137. package/dist/src/notemd/operations/registry.contract.test.js +95 -0
  138. package/dist/src/notemd/operations/registry.js +991 -0
  139. package/dist/src/notemd/operations/types.js +2 -0
  140. package/dist/src/notemd/providerDiagnostics.js +220 -0
  141. package/dist/src/notemd/providerProfiles.js +42 -0
  142. package/dist/src/notemd/providerTemplates.js +231 -0
  143. package/dist/src/notemd/search/DuckDuckGoProvider.js +39 -0
  144. package/dist/src/notemd/search/SearchManager.js +13 -0
  145. package/dist/src/notemd/search/SearchProvider.js +2 -0
  146. package/dist/src/notemd/search/TavilyProvider.js +44 -0
  147. package/dist/src/notemd.agent.manifest.test.js +85 -0
  148. package/dist/src/notemd.api.contract.test.js +14 -1
  149. package/dist/src/notemd.app_config_toml.test.js +2 -1
  150. package/dist/src/notemd.batch.workflow.test.js +117 -0
  151. package/dist/src/notemd.cli.e2e.test.js +136 -0
  152. package/dist/src/notemd.core.test.js +51 -0
  153. package/dist/src/notemd.diagram.pipeline.test.js +233 -0
  154. package/dist/src/notemd.providerTemplates.test.js +34 -0
  155. package/dist/src/notemd.server.integration.test.js +143 -35
  156. package/dist/src/notemd.workflow.pipeline.test.js +162 -0
  157. package/dist/src/pathbridge.handshake.contract.test.js +16 -2
  158. package/dist/src/pathmode.background.contract.test.js +69 -0
  159. package/dist/src/pathmode.settings.api.contract.test.js +9 -0
  160. package/dist/src/pkg.sidecar.contract.test.js +9 -3
  161. package/dist/src/platform/ExportProfile.js +58 -0
  162. package/dist/src/platform/PlatformCapabilities.js +45 -0
  163. package/dist/src/platform/PlatformCapabilities.test.js +30 -0
  164. package/dist/src/platform/RenderMaterializer.js +33 -0
  165. package/dist/src/platform/RenderMaterializer.test.js +32 -0
  166. package/dist/src/query_backend.external_http.integration.test.js +410 -0
  167. package/dist/src/reader_renderer.js +404 -3
  168. package/dist/src/reader_renderer.test.js +87 -0
  169. package/dist/src/release.godot.mirror.contract.test.js +73 -0
  170. package/dist/src/resources/ResourceRegistry.js +223 -0
  171. package/dist/src/resources/ResourceRegistry.test.js +61 -0
  172. package/dist/src/resources/types.js +2 -0
  173. package/dist/src/routes/agentWorkspaceDiagnostics.js +173 -0
  174. package/dist/src/routes/data.js +267 -0
  175. package/dist/src/routes/diagnostics.js +51 -0
  176. package/dist/src/routes/index.js +23 -0
  177. package/dist/src/routes/knowledge.js +968 -0
  178. package/dist/src/routes/markdown.js +287 -0
  179. package/dist/src/routes/notemd.js +565 -0
  180. package/dist/src/routes/registry.contract.test.js +130 -0
  181. package/dist/src/routes/render.js +285 -0
  182. package/dist/src/routes/runtimeRunbookRouteOps.js +149 -0
  183. package/dist/src/routes/runtimeRunbookRouteOps.test.js +194 -0
  184. package/dist/src/routes/settings.js +6 -0
  185. package/dist/src/routes/staticFiles.js +94 -0
  186. package/dist/src/routes/types.js +2 -0
  187. package/dist/src/runtime.transport.adapter.contract.test.js +81 -0
  188. package/dist/src/server.js +11090 -1549
  189. package/dist/src/server.migration.test.js +193 -21
  190. package/dist/src/server.port.fallback.contract.test.js +63 -0
  191. package/dist/src/session/SessionStateStore.js +81 -0
  192. package/dist/src/session/SessionStateStore.test.js +58 -0
  193. package/dist/src/session/types.js +2 -0
  194. package/dist/src/settings.runtime.contract.test.js +50 -0
  195. package/dist/src/shared/types.contract.test.js +107 -0
  196. package/dist/src/shared/types.js +22 -0
  197. package/dist/src/sidecar.replacement.boundary.contract.test.js +128 -0
  198. package/dist/src/sidecar.supply.readiness.contract.test.js +144 -0
  199. package/dist/src/source_manager.loadflow.test.js +46 -0
  200. package/dist/src/startup.layout.snapshot.contract.test.js +57 -0
  201. package/dist/src/tauri.frontend.build.contract.test.js +60 -0
  202. package/dist/src/tauri.sidecar.cleanup.contract.test.js +21 -0
  203. package/dist/src/utils/RuntimePaths.js +4 -13
  204. package/dist/src/utils/platform.js +153 -0
  205. package/dist/src/workflows/WorkflowArtifactStore.js +96 -0
  206. package/dist/src/workflows/WorkflowArtifactStore.test.js +80 -0
  207. package/dist/src/workflows/types.js +2 -0
  208. package/dist/src/workspace/WorkspaceRegistry.js +122 -0
  209. package/dist/src/workspace/WorkspaceRegistry.test.js +29 -0
  210. package/dist/src/workspace/types.js +2 -0
  211. package/package.json +53 -10
@@ -0,0 +1,827 @@
1
+ (function () {
2
+ const state = {
3
+ mermaidInitialized: false,
4
+ mermaidRenderCounter: 0,
5
+ };
6
+
7
+ function escapeHtml(value) {
8
+ return String(value || '')
9
+ .replace(/&/g, '&')
10
+ .replace(/</g, '&lt;')
11
+ .replace(/>/g, '&gt;')
12
+ .replace(/"/g, '&quot;')
13
+ .replace(/'/g, '&#39;');
14
+ }
15
+
16
+ function sanitizeMarkdownSource(markdownText) {
17
+ const source = String(markdownText || '');
18
+ if (!source.includes('```mermaid') || !source.includes('$$')) {
19
+ return source;
20
+ }
21
+ return source.replace(/\$\$[ \t]*```mermaid\b/g, '$$\n```mermaid');
22
+ }
23
+
24
+ function normalizeMarkdownBlockText(value) {
25
+ return String(value || '')
26
+ .replace(/\[([^\]]+)\]\(([^)]+)\)/g, '$1')
27
+ .replace(/<br\s*\/?>/giu, ' ')
28
+ .replace(/&nbsp;/giu, ' ')
29
+ .replace(/[*_~`|]/g, ' ')
30
+ .replace(/\s+/g, ' ')
31
+ .trim();
32
+ }
33
+
34
+ function stripMarkdownBlockPrefix(line) {
35
+ return String(line || '')
36
+ .replace(/^\s{0,3}>+\s?/u, '')
37
+ .replace(/^\s{0,3}#{1,6}\s+/u, '')
38
+ .replace(/^\s{0,3}(?:[-*+]|(?:\d+)[.)])\s+/u, '')
39
+ .trim();
40
+ }
41
+
42
+ function isBlankMarkdownLine(line) {
43
+ return String(line || '').trim().length <= 0;
44
+ }
45
+
46
+ function getMarkdownIndentWidth(line) {
47
+ const match = String(line || '').match(/^\s*/u);
48
+ return match ? match[0].length : 0;
49
+ }
50
+
51
+ function isMarkdownFenceLine(line) {
52
+ return /^\s*(?:```+|~~~+)/u.test(String(line || ''));
53
+ }
54
+
55
+ function isMarkdownHeadingLine(line) {
56
+ return /^\s{0,3}#{1,6}\s+/u.test(String(line || ''));
57
+ }
58
+
59
+ function isMarkdownBlockquoteLine(line) {
60
+ return /^\s{0,3}>/u.test(String(line || ''));
61
+ }
62
+
63
+ function isMarkdownListItemLine(line) {
64
+ return /^\s{0,3}(?:[-*+]|(?:\d+)[.)])\s+/u.test(String(line || ''));
65
+ }
66
+
67
+ function buildMarkdownSourceBlock(kind, startLine, endLine, text) {
68
+ const normalizedText = normalizeMarkdownBlockText(text);
69
+ if (!normalizedText) {
70
+ return null;
71
+ }
72
+ return {
73
+ kind,
74
+ startLine: Math.max(1, Number(startLine) || 1),
75
+ endLine: Math.max(Math.max(1, Number(startLine) || 1), Number(endLine) || Number(startLine) || 1),
76
+ text: normalizedText,
77
+ };
78
+ }
79
+
80
+ function collectMarkdownSourceBlocks(markdownText) {
81
+ const lines = String(markdownText || '').split(/\r?\n/u);
82
+ const blocks = [];
83
+ let lineIndex = 0;
84
+ while (lineIndex < lines.length) {
85
+ const currentLine = String(lines[lineIndex] || '');
86
+ if (isBlankMarkdownLine(currentLine)) {
87
+ lineIndex += 1;
88
+ continue;
89
+ }
90
+
91
+ if (isMarkdownFenceLine(currentLine)) {
92
+ const startLine = lineIndex + 1;
93
+ const fenceMarkerMatch = currentLine.match(/^\s*(```+|~~~+)/u);
94
+ const fenceMarker = fenceMarkerMatch ? fenceMarkerMatch[1] : '```';
95
+ const bodyLines = [];
96
+ lineIndex += 1;
97
+ let endLine = startLine;
98
+ while (lineIndex < lines.length) {
99
+ const candidateLine = String(lines[lineIndex] || '');
100
+ endLine = lineIndex + 1;
101
+ if (new RegExp(`^\\s*${fenceMarker}\\s*$`, 'u').test(candidateLine)) {
102
+ lineIndex += 1;
103
+ break;
104
+ }
105
+ bodyLines.push(candidateLine);
106
+ lineIndex += 1;
107
+ }
108
+ const preBlock = buildMarkdownSourceBlock('pre', startLine, endLine, bodyLines.join(' '));
109
+ if (preBlock) {
110
+ blocks.push(preBlock);
111
+ }
112
+ continue;
113
+ }
114
+
115
+ if (isMarkdownHeadingLine(currentLine)) {
116
+ const headingBlock = buildMarkdownSourceBlock(
117
+ 'heading',
118
+ lineIndex + 1,
119
+ lineIndex + 1,
120
+ stripMarkdownBlockPrefix(currentLine)
121
+ );
122
+ if (headingBlock) {
123
+ blocks.push(headingBlock);
124
+ }
125
+ lineIndex += 1;
126
+ continue;
127
+ }
128
+
129
+ if (isMarkdownBlockquoteLine(currentLine)) {
130
+ const startLine = lineIndex + 1;
131
+ const bodyLines = [];
132
+ let endLine = startLine;
133
+ while (lineIndex < lines.length && isMarkdownBlockquoteLine(lines[lineIndex])) {
134
+ bodyLines.push(stripMarkdownBlockPrefix(lines[lineIndex]));
135
+ endLine = lineIndex + 1;
136
+ lineIndex += 1;
137
+ }
138
+ const blockquoteBlock = buildMarkdownSourceBlock('blockquote', startLine, endLine, bodyLines.join(' '));
139
+ if (blockquoteBlock) {
140
+ blocks.push(blockquoteBlock);
141
+ }
142
+ continue;
143
+ }
144
+
145
+ if (isMarkdownListItemLine(currentLine)) {
146
+ const startLine = lineIndex + 1;
147
+ const startIndent = getMarkdownIndentWidth(currentLine);
148
+ const bodyLines = [stripMarkdownBlockPrefix(currentLine)];
149
+ let endLine = startLine;
150
+ lineIndex += 1;
151
+ while (lineIndex < lines.length) {
152
+ const candidateLine = String(lines[lineIndex] || '');
153
+ if (isBlankMarkdownLine(candidateLine)) {
154
+ break;
155
+ }
156
+ if (
157
+ isMarkdownFenceLine(candidateLine)
158
+ || isMarkdownHeadingLine(candidateLine)
159
+ || isMarkdownBlockquoteLine(candidateLine)
160
+ ) {
161
+ break;
162
+ }
163
+ if (
164
+ isMarkdownListItemLine(candidateLine)
165
+ && getMarkdownIndentWidth(candidateLine) <= startIndent
166
+ ) {
167
+ break;
168
+ }
169
+ bodyLines.push(stripMarkdownBlockPrefix(candidateLine));
170
+ endLine = lineIndex + 1;
171
+ lineIndex += 1;
172
+ }
173
+ const listItemBlock = buildMarkdownSourceBlock('list_item', startLine, endLine, bodyLines.join(' '));
174
+ if (listItemBlock) {
175
+ blocks.push(listItemBlock);
176
+ }
177
+ continue;
178
+ }
179
+
180
+ const startLine = lineIndex + 1;
181
+ const bodyLines = [currentLine];
182
+ let endLine = startLine;
183
+ lineIndex += 1;
184
+ while (lineIndex < lines.length) {
185
+ const candidateLine = String(lines[lineIndex] || '');
186
+ if (
187
+ isBlankMarkdownLine(candidateLine)
188
+ || isMarkdownFenceLine(candidateLine)
189
+ || isMarkdownHeadingLine(candidateLine)
190
+ || isMarkdownBlockquoteLine(candidateLine)
191
+ || isMarkdownListItemLine(candidateLine)
192
+ ) {
193
+ break;
194
+ }
195
+ bodyLines.push(candidateLine);
196
+ endLine = lineIndex + 1;
197
+ lineIndex += 1;
198
+ }
199
+ const paragraphBlock = buildMarkdownSourceBlock('paragraph', startLine, endLine, bodyLines.join(' '));
200
+ if (paragraphBlock) {
201
+ blocks.push(paragraphBlock);
202
+ }
203
+ }
204
+ return blocks;
205
+ }
206
+
207
+ function collectMarkdownBlockFeatures(value) {
208
+ return normalizeMarkdownBlockText(value)
209
+ .toLowerCase()
210
+ .split(/[^a-z0-9\u3400-\u9fff]+/u)
211
+ .map((part) => part.trim())
212
+ .filter((part) => part.length >= 2 || /[\u3400-\u9fff]/u.test(part));
213
+ }
214
+
215
+ function computeMarkdownBlockTextScore(renderedText, sourceText) {
216
+ const normalizedRendered = normalizeMarkdownBlockText(renderedText).toLowerCase();
217
+ const normalizedSource = normalizeMarkdownBlockText(sourceText).toLowerCase();
218
+ if (!normalizedRendered || !normalizedSource) {
219
+ return 0;
220
+ }
221
+ if (normalizedRendered === normalizedSource) {
222
+ return 10000;
223
+ }
224
+ if (
225
+ normalizedRendered.includes(normalizedSource)
226
+ || normalizedSource.includes(normalizedRendered)
227
+ ) {
228
+ return 8000 - Math.abs(normalizedRendered.length - normalizedSource.length);
229
+ }
230
+ const renderedFeatures = collectMarkdownBlockFeatures(normalizedRendered);
231
+ const sourceFeatures = new Set(collectMarkdownBlockFeatures(normalizedSource));
232
+ if (renderedFeatures.length <= 0 || sourceFeatures.size <= 0) {
233
+ return 0;
234
+ }
235
+ const overlapCount = renderedFeatures.filter((feature) => sourceFeatures.has(feature)).length;
236
+ const overlapRatio = overlapCount / renderedFeatures.length;
237
+ if (overlapRatio < 0.6) {
238
+ return 0;
239
+ }
240
+ return Math.round(overlapRatio * 1000);
241
+ }
242
+
243
+ function resolveRenderedMarkdownBlockKind(element) {
244
+ const tagName = String(element && element.tagName || '').toLowerCase();
245
+ if (/^h[1-6]$/u.test(tagName)) {
246
+ return 'heading';
247
+ }
248
+ if (tagName === 'p') {
249
+ return 'paragraph';
250
+ }
251
+ if (tagName === 'li') {
252
+ return 'list_item';
253
+ }
254
+ if (tagName === 'blockquote') {
255
+ return 'blockquote';
256
+ }
257
+ if (tagName === 'pre') {
258
+ return 'pre';
259
+ }
260
+ return '';
261
+ }
262
+
263
+ function collectRenderedMarkdownBlockCandidates(container) {
264
+ if (!container || typeof container.querySelectorAll !== 'function') {
265
+ return [];
266
+ }
267
+ return Array.from(container.querySelectorAll('p, li, blockquote, pre, h1, h2, h3, h4, h5, h6'));
268
+ }
269
+
270
+ function clearRenderedMarkdownBlockProvenance(container) {
271
+ collectRenderedMarkdownBlockCandidates(container).forEach((element) => {
272
+ element.removeAttribute('data-agent-markdown-source-start-line');
273
+ element.removeAttribute('data-agent-markdown-source-end-line');
274
+ element.removeAttribute('data-agent-markdown-source-kind');
275
+ });
276
+ }
277
+
278
+ function annotateRenderedMarkdownBlocks(container, rawMarkdown) {
279
+ const renderedCandidates = collectRenderedMarkdownBlockCandidates(container);
280
+ const sourceBlocks = collectMarkdownSourceBlocks(rawMarkdown);
281
+ clearRenderedMarkdownBlockProvenance(container);
282
+ if (renderedCandidates.length <= 0 || sourceBlocks.length <= 0) {
283
+ return {
284
+ sourceBlockCount: sourceBlocks.length,
285
+ attributedNodeCount: 0,
286
+ };
287
+ }
288
+ let sourceCursor = 0;
289
+ let attributedNodeCount = 0;
290
+ renderedCandidates.forEach((candidate) => {
291
+ const renderedKind = resolveRenderedMarkdownBlockKind(candidate);
292
+ const renderedText = normalizeMarkdownBlockText(candidate && candidate.textContent || '');
293
+ if (!renderedKind || !renderedText) {
294
+ return;
295
+ }
296
+ let bestMatchIndex = -1;
297
+ let bestMatchScore = 0;
298
+ const searchEnd = Math.min(sourceBlocks.length, sourceCursor + 24);
299
+ for (let index = sourceCursor; index < searchEnd; index += 1) {
300
+ const sourceBlock = sourceBlocks[index];
301
+ if (!sourceBlock || sourceBlock.kind !== renderedKind) {
302
+ continue;
303
+ }
304
+ const score = computeMarkdownBlockTextScore(renderedText, sourceBlock.text);
305
+ if (score <= bestMatchScore) {
306
+ continue;
307
+ }
308
+ bestMatchIndex = index;
309
+ bestMatchScore = score;
310
+ }
311
+ if (bestMatchIndex < 0 || bestMatchScore < 600) {
312
+ return;
313
+ }
314
+ const matchedSourceBlock = sourceBlocks[bestMatchIndex];
315
+ candidate.setAttribute('data-agent-markdown-source-start-line', String(matchedSourceBlock.startLine));
316
+ candidate.setAttribute('data-agent-markdown-source-end-line', String(matchedSourceBlock.endLine));
317
+ candidate.setAttribute('data-agent-markdown-source-kind', matchedSourceBlock.kind);
318
+ sourceCursor = bestMatchIndex + 1;
319
+ attributedNodeCount += 1;
320
+ });
321
+ return {
322
+ sourceBlockCount: sourceBlocks.length,
323
+ attributedNodeCount,
324
+ };
325
+ }
326
+
327
+ function getRuntimeUrl(resourcePath) {
328
+ const runtime = window.NoteConnectionRuntime;
329
+ if (runtime && typeof runtime.buildUrl === 'function') {
330
+ return runtime.buildUrl(resourcePath);
331
+ }
332
+ return resourcePath;
333
+ }
334
+
335
+ function getRuntimeFetchOptions(init) {
336
+ const runtime = window.NoteConnectionRuntime;
337
+ if (runtime && typeof runtime.buildFetchOptions === 'function') {
338
+ return runtime.buildFetchOptions(init || {});
339
+ }
340
+ return init || {};
341
+ }
342
+
343
+ function isSafeAssistantUrl(tagName, attrName, rawValue) {
344
+ const value = String(rawValue || '').trim();
345
+ if (!value) {
346
+ return true;
347
+ }
348
+ const lowered = value.toLowerCase();
349
+ if (
350
+ tagName === 'img'
351
+ && attrName === 'src'
352
+ && (
353
+ lowered.startsWith('data:image/png')
354
+ || lowered.startsWith('data:image/jpeg')
355
+ || lowered.startsWith('data:image/jpg')
356
+ || lowered.startsWith('data:image/gif')
357
+ || lowered.startsWith('data:image/webp')
358
+ || lowered.startsWith('data:image/svg+xml')
359
+ )
360
+ ) {
361
+ return true;
362
+ }
363
+ if (
364
+ lowered.startsWith('javascript:')
365
+ || lowered.startsWith('vbscript:')
366
+ || lowered.startsWith('data:text/html')
367
+ ) {
368
+ return false;
369
+ }
370
+ return true;
371
+ }
372
+
373
+ function sanitizeRenderedHtml(container) {
374
+ if (!container || typeof container.querySelectorAll !== 'function') {
375
+ return;
376
+ }
377
+
378
+ container.querySelectorAll('script, iframe, object, embed, form, style').forEach((node) => {
379
+ if (node && node.parentNode) {
380
+ node.parentNode.removeChild(node);
381
+ }
382
+ });
383
+
384
+ container.querySelectorAll('*').forEach((element) => {
385
+ if (!element || typeof element.getAttributeNames !== 'function') {
386
+ return;
387
+ }
388
+ const tagName = String(element.tagName || '').toLowerCase();
389
+ element.getAttributeNames().forEach((attributeName) => {
390
+ const normalizedName = String(attributeName || '').toLowerCase();
391
+ const attributeValue = element.getAttribute(attributeName);
392
+ if (normalizedName.startsWith('on') || normalizedName === 'style') {
393
+ element.removeAttribute(attributeName);
394
+ return;
395
+ }
396
+ if (
397
+ (normalizedName === 'href' || normalizedName === 'src' || normalizedName === 'xlink:href')
398
+ && !isSafeAssistantUrl(tagName, normalizedName, attributeValue)
399
+ ) {
400
+ element.removeAttribute(attributeName);
401
+ }
402
+ });
403
+ if (tagName === 'a') {
404
+ element.setAttribute('target', '_blank');
405
+ element.setAttribute('rel', 'noopener noreferrer');
406
+ }
407
+ if (tagName === 'img') {
408
+ element.setAttribute('loading', 'lazy');
409
+ }
410
+ });
411
+ }
412
+
413
+ function renderMathInContainer(container) {
414
+ if (!window.renderMathInElement) {
415
+ return;
416
+ }
417
+ window.renderMathInElement(container, {
418
+ delimiters: [
419
+ { left: '$$', right: '$$', display: true },
420
+ { left: '$', right: '$', display: false },
421
+ ],
422
+ });
423
+ }
424
+
425
+ function isMermaidErrorArtifactText(text) {
426
+ const normalized = String(text || '').toLowerCase();
427
+ if (!normalized) {
428
+ return false;
429
+ }
430
+ return (
431
+ normalized.includes('syntax error in text')
432
+ || normalized.includes('lexical error on line')
433
+ || normalized.includes('parse error on line')
434
+ || normalized.includes('mermaid version')
435
+ || normalized.includes('diagram syntax error')
436
+ );
437
+ }
438
+
439
+ function resolveMermaidErrorArtifactHost(node) {
440
+ if (!node || typeof node.closest !== 'function') {
441
+ return node;
442
+ }
443
+ return (
444
+ node.closest('.mermaid-render-host-offscreen')
445
+ || node.closest('.mermaid')
446
+ || node.closest('.mermaid-render-failed')
447
+ || node.closest('.agent-chat-message')
448
+ || node.closest('svg')
449
+ || node
450
+ );
451
+ }
452
+
453
+ function isProtectedMermaidSuppressionHost(host) {
454
+ if (!host || host.nodeType !== 1) {
455
+ return true;
456
+ }
457
+ return (
458
+ host === document.body
459
+ || host === document.documentElement
460
+ || host === document.head
461
+ || host.id === 'graph-wrapper'
462
+ || host.id === 'path-container'
463
+ || host.id === 'reading-window'
464
+ || host.id === 'reading-content-box'
465
+ || host.id === 'reading-body'
466
+ );
467
+ }
468
+
469
+ function collectMermaidErrorArtifactHosts(root) {
470
+ const hosts = [];
471
+ const seen = new Set();
472
+ const candidates = [];
473
+ if (!root) {
474
+ return hosts;
475
+ }
476
+ if (root.nodeType === 1 && root !== document.body && root !== document.documentElement && root !== document.head) {
477
+ candidates.push(root);
478
+ }
479
+ if (typeof root.querySelectorAll === 'function') {
480
+ root.querySelectorAll('svg, .mermaid, div, section, article, aside, img, foreignObject').forEach((node) => {
481
+ candidates.push(node);
482
+ });
483
+ }
484
+ candidates.forEach((candidate) => {
485
+ if (!candidate || candidate.nodeType !== 1) {
486
+ return;
487
+ }
488
+ const text = String(
489
+ candidate.textContent
490
+ || candidate.getAttribute?.('alt')
491
+ || candidate.getAttribute?.('aria-label')
492
+ || ''
493
+ ).trim();
494
+ const hasErrorClass = Boolean(
495
+ candidate.classList?.contains('error-icon')
496
+ || candidate.querySelector?.('.error-icon')
497
+ );
498
+ if (!hasErrorClass && !isMermaidErrorArtifactText(text)) {
499
+ return;
500
+ }
501
+ const host = resolveMermaidErrorArtifactHost(candidate);
502
+ if (!host || seen.has(host) || isProtectedMermaidSuppressionHost(host)) {
503
+ return;
504
+ }
505
+ seen.add(host);
506
+ hosts.push(host);
507
+ });
508
+ return hosts;
509
+ }
510
+
511
+ function suppressLeakedMermaidErrorArtifacts(options) {
512
+ const root = options && options.root ? options.root : document.body;
513
+ const preserveNode = options && options.preserveNode ? options.preserveNode : null;
514
+ const hosts = collectMermaidErrorArtifactHosts(root);
515
+ hosts.forEach((host) => {
516
+ if (!host || host.closest?.('.mermaid-render-failed')) {
517
+ return;
518
+ }
519
+ if (preserveNode && (host === preserveNode || preserveNode.contains(host) || host.contains(preserveNode))) {
520
+ return;
521
+ }
522
+ if (host.parentNode) {
523
+ host.parentNode.removeChild(host);
524
+ } else if (host.style) {
525
+ host.style.display = 'none';
526
+ }
527
+ });
528
+ return hosts.length;
529
+ }
530
+
531
+ function createOffscreenMermaidRenderHost(widthHint) {
532
+ const hostWidth = Math.max(480, Number(widthHint) || 960);
533
+ const host = document.createElement('div');
534
+ host.className = 'mermaid-render-host-offscreen';
535
+ host.style.position = 'fixed';
536
+ host.style.left = '-20000px';
537
+ host.style.top = '0';
538
+ host.style.width = String(hostWidth) + 'px';
539
+ host.style.minWidth = String(hostWidth) + 'px';
540
+ host.style.height = 'auto';
541
+ host.style.overflow = 'visible';
542
+ host.style.opacity = '0';
543
+ host.style.pointerEvents = 'none';
544
+ host.style.background = 'transparent';
545
+ host.style.fontFamily = '"Microsoft YaHei UI", "Microsoft YaHei", "PingFang SC", "Noto Sans CJK SC", "Segoe UI", sans-serif';
546
+ (document.body || document.documentElement).appendChild(host);
547
+ return host;
548
+ }
549
+
550
+ function normalizeMermaidDefinition(source) {
551
+ if (
552
+ window.pathModules
553
+ && window.pathModules.utils
554
+ && typeof window.pathModules.utils.normalizeBridgeMermaidDefinition === 'function'
555
+ ) {
556
+ return window.pathModules.utils.normalizeBridgeMermaidDefinition(source);
557
+ }
558
+ return String(source || '').trim();
559
+ }
560
+
561
+ function getMermaidDefinitionCandidates(source) {
562
+ const candidates = [];
563
+ const normalized = normalizeMermaidDefinition(source);
564
+ const raw = String(source || '').replace(/\r\n?/g, '\n').trim();
565
+ [normalized, raw].forEach((candidate) => {
566
+ const next = String(candidate || '').trim();
567
+ if (!next || candidates.includes(next)) {
568
+ return;
569
+ }
570
+ candidates.push(next);
571
+ });
572
+ return candidates;
573
+ }
574
+
575
+ async function canParseMermaidDefinition(definition) {
576
+ if (!window.mermaid || typeof window.mermaid.parse !== 'function') {
577
+ return true;
578
+ }
579
+ try {
580
+ await window.mermaid.parse(definition);
581
+ return true;
582
+ } catch (_error) {
583
+ return false;
584
+ }
585
+ }
586
+
587
+ function isMermaidErrorSvgMarkup(markup) {
588
+ const text = String(markup || '').toLowerCase();
589
+ if (!text) {
590
+ return false;
591
+ }
592
+ return (
593
+ text.includes('syntax error in text')
594
+ || text.includes('lexical error on line')
595
+ || text.includes('parse error on line')
596
+ || text.includes('mermaid version')
597
+ || text.includes('class="error-icon"')
598
+ || text.includes('id="error-icon"')
599
+ );
600
+ }
601
+
602
+ function renderCompactMermaidFailure(wrapper, error, source) {
603
+ wrapper.classList.add('mermaid-render-failed');
604
+ wrapper.innerHTML = '';
605
+
606
+ const notice = document.createElement('div');
607
+ notice.className = 'mermaid-render-notice';
608
+
609
+ const title = document.createElement('div');
610
+ title.className = 'mermaid-render-notice-title';
611
+ title.textContent = 'Mermaid diagram unavailable.';
612
+ notice.appendChild(title);
613
+
614
+ const summary = document.createElement('div');
615
+ summary.className = 'mermaid-render-notice-summary';
616
+ summary.textContent = 'Rendering failed in the current runtime. Details are available on demand.';
617
+ notice.appendChild(summary);
618
+
619
+ const details = document.createElement('details');
620
+ details.className = 'mermaid-render-notice-details';
621
+
622
+ const detailsSummary = document.createElement('summary');
623
+ detailsSummary.textContent = 'Render details';
624
+ details.appendChild(detailsSummary);
625
+
626
+ const detailText = document.createElement('pre');
627
+ detailText.className = 'mermaid-render-notice-code';
628
+ const errorMessage = String(error && error.message ? error.message : error || 'Unknown error').trim();
629
+ const sourceSnippet = String(source || '').trim().slice(0, 320);
630
+ detailText.textContent = errorMessage + (sourceSnippet ? `\n\n${sourceSnippet}` : '');
631
+ details.appendChild(detailText);
632
+
633
+ notice.appendChild(details);
634
+ wrapper.appendChild(notice);
635
+ }
636
+
637
+ async function renderMermaidViaBackend(graphDefinition) {
638
+ const source = normalizeMermaidDefinition(graphDefinition || '');
639
+ if (!source) {
640
+ return null;
641
+ }
642
+ try {
643
+ const response = await fetch(
644
+ getRuntimeUrl('/api/render/mermaid'),
645
+ getRuntimeFetchOptions({
646
+ method: 'POST',
647
+ headers: {
648
+ 'Content-Type': 'application/json',
649
+ },
650
+ body: JSON.stringify({
651
+ source,
652
+ renderer: 'auto',
653
+ }),
654
+ })
655
+ );
656
+ const payload = await response.json().catch(() => null);
657
+ if (!response.ok || !payload || typeof payload.pngBase64 !== 'string' || !payload.pngBase64.trim()) {
658
+ return null;
659
+ }
660
+ return {
661
+ pngBase64: payload.pngBase64.trim(),
662
+ renderer: typeof payload.renderer === 'string' ? payload.renderer.trim() : '',
663
+ };
664
+ } catch (_error) {
665
+ return null;
666
+ }
667
+ }
668
+
669
+ async function renderMermaidInContainer(container) {
670
+ const hasFrontendMermaid = Boolean(window.mermaid);
671
+ if (hasFrontendMermaid && !state.mermaidInitialized) {
672
+ window.mermaid.initialize({
673
+ startOnLoad: false,
674
+ theme: 'dark',
675
+ securityLevel: 'loose',
676
+ htmlLabels: true,
677
+ });
678
+ state.mermaidInitialized = true;
679
+ }
680
+
681
+ suppressLeakedMermaidErrorArtifacts({ root: document.body });
682
+
683
+ let mermaidBlocks = Array.from(container.querySelectorAll('pre code.language-mermaid, pre code.lang-mermaid'));
684
+ if (mermaidBlocks.length === 0 && container.dataset && container.dataset.codeLanguage === 'mermaid') {
685
+ const fallbackBlock = container.querySelector('pre code');
686
+ if (fallbackBlock) {
687
+ mermaidBlocks = [fallbackBlock];
688
+ }
689
+ }
690
+
691
+ for (const block of mermaidBlocks) {
692
+ const txt = document.createElement('textarea');
693
+ txt.innerHTML = block.innerHTML;
694
+ const candidateDefinitions = getMermaidDefinitionCandidates(txt.value);
695
+ const graphDefinition = candidateDefinitions[0] || '';
696
+ const parentPre = block.parentElement;
697
+ if (!parentPre || !parentPre.parentNode) {
698
+ continue;
699
+ }
700
+
701
+ state.mermaidRenderCounter += 1;
702
+ const renderId = `agent-mermaid-${state.mermaidRenderCounter}`;
703
+ const wrapper = document.createElement('div');
704
+ wrapper.className = 'mermaid';
705
+ parentPre.parentNode.replaceChild(wrapper, parentPre);
706
+ let rendered = false;
707
+ const renderErrors = [];
708
+
709
+ if (hasFrontendMermaid) {
710
+ for (let candidateIndex = 0; candidateIndex < candidateDefinitions.length; candidateIndex += 1) {
711
+ const candidate = candidateDefinitions[candidateIndex];
712
+ const offscreenHost = createOffscreenMermaidRenderHost(
713
+ wrapper.clientWidth || parentPre.clientWidth || container.clientWidth || 960
714
+ );
715
+ try {
716
+ wrapper.innerHTML = '';
717
+ const renderedResult = await window.mermaid.render(`${renderId}-${candidateIndex}`, candidate, offscreenHost);
718
+ if (renderedResult && typeof renderedResult.svg === 'string' && renderedResult.svg.trim()) {
719
+ if (isMermaidErrorSvgMarkup(renderedResult.svg)) {
720
+ throw new Error('Mermaid frontend renderer returned an error SVG instead of a diagram.');
721
+ }
722
+ wrapper.innerHTML = renderedResult.svg;
723
+ }
724
+ if (/<svg[\s>]/i.test(String(wrapper.innerHTML || ''))) {
725
+ rendered = true;
726
+ break;
727
+ }
728
+ } catch (error) {
729
+ renderErrors.push(error);
730
+ wrapper.innerHTML = '';
731
+ suppressLeakedMermaidErrorArtifacts({
732
+ root: document.body,
733
+ preserveNode: wrapper,
734
+ });
735
+ } finally {
736
+ offscreenHost.remove();
737
+ }
738
+ }
739
+ } else {
740
+ renderErrors.push(new Error('Mermaid runtime is unavailable in current webview.'));
741
+ }
742
+
743
+ if (!rendered && hasFrontendMermaid) {
744
+ for (let candidateIndex = 0; candidateIndex < candidateDefinitions.length; candidateIndex += 1) {
745
+ const candidate = candidateDefinitions[candidateIndex];
746
+ const canParse = await canParseMermaidDefinition(candidate);
747
+ if (!canParse) {
748
+ continue;
749
+ }
750
+ try {
751
+ wrapper.innerHTML = '';
752
+ wrapper.textContent = candidate;
753
+ await window.mermaid.run({ nodes: [wrapper] });
754
+ rendered = /<svg[\s>]/i.test(String(wrapper.innerHTML || ''))
755
+ && !isMermaidErrorSvgMarkup(String(wrapper.innerHTML || ''));
756
+ if (rendered) {
757
+ break;
758
+ }
759
+ } catch (error) {
760
+ renderErrors.push(error);
761
+ wrapper.innerHTML = '';
762
+ suppressLeakedMermaidErrorArtifacts({
763
+ root: document.body,
764
+ preserveNode: wrapper,
765
+ });
766
+ }
767
+ }
768
+ }
769
+
770
+ if (!rendered) {
771
+ wrapper.innerHTML = '';
772
+ const backendRendered = await renderMermaidViaBackend(graphDefinition);
773
+ if (backendRendered && backendRendered.pngBase64) {
774
+ const altRenderer = backendRendered.renderer ? ` (${backendRendered.renderer})` : '';
775
+ wrapper.innerHTML = `<img class="mermaid-fallback-image" src="data:image/png;base64,${backendRendered.pngBase64}" alt="Mermaid diagram${altRenderer}" />`;
776
+ rendered = true;
777
+ }
778
+ }
779
+
780
+ if (!rendered) {
781
+ const lastError = renderErrors.length > 0 ? renderErrors[renderErrors.length - 1] : null;
782
+ renderCompactMermaidFailure(wrapper, lastError, graphDefinition);
783
+ }
784
+
785
+ suppressLeakedMermaidErrorArtifacts({
786
+ root: document.body,
787
+ preserveNode: wrapper,
788
+ });
789
+ }
790
+ }
791
+
792
+ function renderPlainTextInto(container, text) {
793
+ container.innerHTML = '';
794
+ const paragraph = document.createElement('p');
795
+ paragraph.style.whiteSpace = 'pre-wrap';
796
+ paragraph.textContent = String(text || '');
797
+ container.appendChild(paragraph);
798
+ }
799
+
800
+ async function renderMarkdownInto(container, rawMarkdown) {
801
+ if (!container) {
802
+ return {
803
+ sourceBlockCount: 0,
804
+ attributedNodeCount: 0,
805
+ };
806
+ }
807
+ const source = sanitizeMarkdownSource(rawMarkdown);
808
+ if (!window.marked || typeof window.marked.parse !== 'function') {
809
+ renderPlainTextInto(container, source);
810
+ return annotateRenderedMarkdownBlocks(container, source);
811
+ }
812
+ container.innerHTML = window.marked.parse(source);
813
+ sanitizeRenderedHtml(container);
814
+ renderMathInContainer(container);
815
+ await renderMermaidInContainer(container);
816
+ return annotateRenderedMarkdownBlocks(container, source);
817
+ }
818
+
819
+ window.NoteConnectionMarkdownRuntime = {
820
+ escapeHtml,
821
+ sanitizeMarkdownSource,
822
+ renderMathInContainer,
823
+ renderMermaidInContainer,
824
+ renderMarkdownInto,
825
+ renderPlainTextInto,
826
+ };
827
+ }());