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,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,220 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MAX_PROVIDER_DIAGNOSTIC_STABILITY_RUNS = exports.DEFAULT_PROVIDER_DIAGNOSTIC_STABILITY_RUNS = exports.DEFAULT_PROVIDER_DIAGNOSTIC_CALL_MODE = exports.DEFAULT_PROVIDER_DIAGNOSTIC_TIMEOUT_MS = void 0;
4
+ exports.getProviderDiagnosticCallModeOptions = getProviderDiagnosticCallModeOptions;
5
+ exports.buildDefaultProviderDiagnosticPayload = buildDefaultProviderDiagnosticPayload;
6
+ exports.buildProviderDiagnosticFileName = buildProviderDiagnosticFileName;
7
+ exports.buildProviderDiagnosticOperationInput = buildProviderDiagnosticOperationInput;
8
+ exports.runProviderDiagnosticProbe = runProviderDiagnosticProbe;
9
+ exports.runProviderDiagnosticStabilityProbe = runProviderDiagnosticStabilityProbe;
10
+ exports.DEFAULT_PROVIDER_DIAGNOSTIC_TIMEOUT_MS = 10 * 60 * 1000;
11
+ const MAX_RESPONSE_PREVIEW_CHARS = 8000;
12
+ exports.DEFAULT_PROVIDER_DIAGNOSTIC_CALL_MODE = 'runtime-stable';
13
+ exports.DEFAULT_PROVIDER_DIAGNOSTIC_STABILITY_RUNS = 3;
14
+ exports.MAX_PROVIDER_DIAGNOSTIC_STABILITY_RUNS = 10;
15
+ const PROVIDER_DIAGNOSTIC_CALL_MODE_OPTIONS = [
16
+ {
17
+ value: 'runtime-stable',
18
+ label: 'Runtime stable (auto)',
19
+ description: 'Use the stable runtime path (stream -> non-stream -> fallback).',
20
+ openaiCompatibleOnly: false
21
+ },
22
+ {
23
+ value: 'runtime-requesturl-first',
24
+ label: 'Runtime requestUrl-first',
25
+ description: 'Use requestUrl-first runtime behavior before streamed fallback parsing.',
26
+ openaiCompatibleOnly: false
27
+ }
28
+ ];
29
+ function redactApiKey(apiKey) {
30
+ if (!apiKey)
31
+ return '(empty)';
32
+ if (apiKey.length <= 6)
33
+ return '[REDACTED]';
34
+ return `${apiKey.slice(0, 3)}...${apiKey.slice(-3)} (redacted)`;
35
+ }
36
+ function normalizeMultiline(input) {
37
+ return input.replace(/\r\n/g, '\n');
38
+ }
39
+ function clipPreview(input, maxChars = MAX_RESPONSE_PREVIEW_CHARS) {
40
+ if (input.length <= maxChars)
41
+ return input;
42
+ return `${input.slice(0, maxChars)}\n\n...[${input.length - maxChars} chars omitted]`;
43
+ }
44
+ function normalizeStabilityRuns(input) {
45
+ const numeric = Number.isFinite(input) ? Math.floor(input) : exports.DEFAULT_PROVIDER_DIAGNOSTIC_STABILITY_RUNS;
46
+ if (numeric < 1)
47
+ return 1;
48
+ return Math.min(numeric, exports.MAX_PROVIDER_DIAGNOSTIC_STABILITY_RUNS);
49
+ }
50
+ function getProviderDiagnosticCallModeOptions(_provider) {
51
+ return PROVIDER_DIAGNOSTIC_CALL_MODE_OPTIONS.map(option => ({ ...option }));
52
+ }
53
+ function buildDefaultProviderDiagnosticPayload(providerName) {
54
+ const prompt = 'You are a diagnostic assistant. Return plain markdown text only. Do not use code fences.';
55
+ const contentBlock = 'Please produce a structured diagnostic response with: summary, numbered findings, risk notes, and a final checklist. Expand each section with details.';
56
+ const repeated = Array.from({ length: 10 }, (_, idx) => `Input block ${idx + 1}: ${contentBlock}`).join('\n\n');
57
+ return { prompt, content: `Provider diagnostic target: ${providerName}\n\n${repeated}` };
58
+ }
59
+ function buildProviderDiagnosticFileName(providerName, now) {
60
+ const safeProviderName = providerName
61
+ .replace(/[^a-zA-Z0-9_-]+/g, '_')
62
+ .replace(/_+/g, '_')
63
+ .replace(/^_+|_+$/g, '') || 'provider';
64
+ const timestamp = now.toISOString().replace(/[:.]/g, '-');
65
+ return `Notemd_Provider_Diagnostic_${safeProviderName}_${timestamp}.txt`;
66
+ }
67
+ function buildProviderDiagnosticOperationInput(provider, settings) {
68
+ return {
69
+ providerName: provider.name,
70
+ model: provider.model,
71
+ callMode: settings.developerDiagnosticCallMode || exports.DEFAULT_PROVIDER_DIAGNOSTIC_CALL_MODE,
72
+ timeoutMs: settings.developerDiagnosticTimeoutMs ?? exports.DEFAULT_PROVIDER_DIAGNOSTIC_TIMEOUT_MS,
73
+ stabilityRuns: settings.developerDiagnosticStabilityRuns ?? exports.DEFAULT_PROVIDER_DIAGNOSTIC_STABILITY_RUNS
74
+ };
75
+ }
76
+ function createInMemoryProgressReporter(logs) {
77
+ let cancelled = false;
78
+ const reporter = {
79
+ report(_event) { },
80
+ isCancelled() { return cancelled; }
81
+ };
82
+ reporter.log = (message) => { logs.push(`[${new Date().toISOString()}] ${message}`); };
83
+ return reporter;
84
+ }
85
+ function buildProviderDiagnosticReport(params) {
86
+ const { provider, settings, startedAt, timeoutMs, callMode, requestedCallMode, success, elapsedMs, logs, responseText, errorMessage, debugInfo } = params;
87
+ const sections = [
88
+ 'Notemd Provider Diagnostic Report',
89
+ `Generated At: ${startedAt.toISOString()}`,
90
+ '',
91
+ '=== Provider Context ===',
92
+ `Provider: ${provider.name}`,
93
+ `Base URL: ${provider.baseUrl}`,
94
+ `Model: ${provider.model}`,
95
+ `Temperature: ${provider.temperature}`,
96
+ `API Key: ${redactApiKey(provider.apiKey)}`,
97
+ '',
98
+ '=== Runtime Settings ===',
99
+ `Stable API Calls: ${settings.enableStableApiCall ? 'enabled' : 'disabled'}`,
100
+ `Max Retries: ${settings.maxRetries}`,
101
+ `Requested Call Mode: ${requestedCallMode}`,
102
+ `Effective Call Mode: ${callMode}`,
103
+ `Timeout: ${timeoutMs}ms`,
104
+ '',
105
+ '=== Result ===',
106
+ `Result: ${success ? 'SUCCESS' : 'FAILED'}`,
107
+ `Elapsed: ${elapsedMs}ms`
108
+ ];
109
+ if (errorMessage)
110
+ sections.push(`Error: ${errorMessage}`);
111
+ if (debugInfo)
112
+ sections.push('', '=== Debug Details ===', normalizeMultiline(debugInfo));
113
+ if (responseText && responseText.trim())
114
+ sections.push('', '=== Response Preview ===', clipPreview(normalizeMultiline(responseText)));
115
+ sections.push('', '=== Runtime Logs ===');
116
+ sections.push(logs.length > 0 ? logs.join('\n') : '(no logs captured)');
117
+ return sections.join('\n');
118
+ }
119
+ async function runProviderDiagnosticProbe(provider, settings, llmCallImpl, options = {}) {
120
+ const payload = buildDefaultProviderDiagnosticPayload(provider.name);
121
+ const timeoutMs = options.timeoutMs ?? exports.DEFAULT_PROVIDER_DIAGNOSTIC_TIMEOUT_MS;
122
+ const requestedCallMode = options.callMode ?? exports.DEFAULT_PROVIDER_DIAGNOSTIC_CALL_MODE;
123
+ const callMode = requestedCallMode;
124
+ const runtimeStartedAtMs = Date.now();
125
+ const startedAt = options.now ?? new Date(runtimeStartedAtMs);
126
+ const logs = [];
127
+ const reporter = createInMemoryProgressReporter(logs);
128
+ reporter.log(`Developer diagnostic started for ${provider.name}.`);
129
+ reporter.log(`Using model '${provider.model}' at '${provider.baseUrl}'.`);
130
+ reporter.log(`Effective call mode: ${callMode}.`);
131
+ reporter.log(`Timeout configured to ${timeoutMs}ms.`);
132
+ const controller = new AbortController();
133
+ let timeoutHandle = null;
134
+ let success = false;
135
+ let responseText;
136
+ let errorMessage;
137
+ let debugInfo;
138
+ try {
139
+ timeoutHandle = setTimeout(() => {
140
+ reporter.log(`Diagnostic timeout reached (${timeoutMs}ms). Aborting request.`);
141
+ controller.abort();
142
+ }, timeoutMs);
143
+ responseText = await llmCallImpl(provider, payload.prompt, payload.content, { ...settings, enableApiErrorDebugMode: true, enableStableApiCall: true }, controller.signal);
144
+ success = true;
145
+ reporter.log(`Diagnostic completed successfully. Response length: ${responseText.length} chars.`);
146
+ }
147
+ catch (error) {
148
+ errorMessage = error instanceof Error ? error.message : String(error);
149
+ debugInfo = error instanceof Error ? error.stack : undefined;
150
+ reporter.log(`Diagnostic failed: ${errorMessage}`);
151
+ if (debugInfo)
152
+ reporter.log(`Diagnostic debug details:\n${debugInfo}`);
153
+ }
154
+ finally {
155
+ if (timeoutHandle)
156
+ clearTimeout(timeoutHandle);
157
+ }
158
+ const elapsedMs = Date.now() - runtimeStartedAtMs;
159
+ const report = buildProviderDiagnosticReport({
160
+ provider, settings, startedAt, timeoutMs, callMode, requestedCallMode,
161
+ success, elapsedMs, logs, responseText, errorMessage, debugInfo
162
+ });
163
+ return { success, elapsedMs, callMode, requestedCallMode, responseText, errorMessage, debugInfo, logs, report };
164
+ }
165
+ function buildProviderDiagnosticStabilityReport(params) {
166
+ const { provider, requestedCallMode, callMode, runs, successCount, failureCount, totalElapsedMs, runResults } = params;
167
+ const lines = [
168
+ 'Notemd Provider Diagnostic Stability Report',
169
+ `Generated At: ${new Date().toISOString()}`,
170
+ '',
171
+ '=== Provider Context ===',
172
+ `Provider: ${provider.name}`,
173
+ `Base URL: ${provider.baseUrl}`,
174
+ `Model: ${provider.model}`,
175
+ `Requested Call Mode: ${requestedCallMode}`,
176
+ `Effective Call Mode: ${callMode}`,
177
+ '',
178
+ '=== Summary ===',
179
+ `Runs: ${runs}`,
180
+ `Success: ${successCount}`,
181
+ `Failed: ${failureCount}`,
182
+ `Total Elapsed: ${totalElapsedMs}ms`,
183
+ `Average Elapsed: ${runs > 0 ? Math.round(totalElapsedMs / runs) : 0}ms`,
184
+ ''
185
+ ];
186
+ runResults.forEach((run, index) => {
187
+ lines.push(`=== Run ${index + 1} ===`);
188
+ lines.push(`Result: ${run.success ? 'SUCCESS' : 'FAILED'}`);
189
+ lines.push(`Elapsed: ${run.elapsedMs}ms`);
190
+ if (run.errorMessage)
191
+ lines.push(`Error: ${run.errorMessage}`);
192
+ if (run.debugInfo) {
193
+ lines.push('Debug:');
194
+ lines.push(normalizeMultiline(run.debugInfo));
195
+ }
196
+ lines.push('');
197
+ });
198
+ return lines.join('\n');
199
+ }
200
+ async function runProviderDiagnosticStabilityProbe(provider, settings, llmCallImpl, options = {}) {
201
+ const runs = normalizeStabilityRuns(options.runs);
202
+ const requestedCallMode = options.callMode ?? exports.DEFAULT_PROVIDER_DIAGNOSTIC_CALL_MODE;
203
+ const runResults = [];
204
+ const startedAtMs = Date.now();
205
+ for (let runIndex = 0; runIndex < runs; runIndex += 1) {
206
+ const runResult = await runProviderDiagnosticProbe(provider, settings, llmCallImpl, {
207
+ ...options,
208
+ callMode: requestedCallMode
209
+ });
210
+ runResults.push(runResult);
211
+ }
212
+ const totalElapsedMs = Date.now() - startedAtMs;
213
+ const successCount = runResults.filter(run => run.success).length;
214
+ const failureCount = runResults.length - successCount;
215
+ const report = buildProviderDiagnosticStabilityReport({
216
+ provider, requestedCallMode, callMode: requestedCallMode,
217
+ runs, successCount, failureCount, totalElapsedMs, runResults
218
+ });
219
+ return { runs, callMode: requestedCallMode, requestedCallMode, successCount, failureCount, totalElapsedMs, runResults, report };
220
+ }
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildProviderProfileExport = buildProviderProfileExport;
4
+ exports.parseProviderProfileImport = parseProviderProfileImport;
5
+ function buildProviderProfileExport(providers, now = new Date()) {
6
+ return {
7
+ providers,
8
+ exportedAt: now.toISOString(),
9
+ formatVersion: 1
10
+ };
11
+ }
12
+ function parseProviderProfileImport(jsonData, existingProviders) {
13
+ const parsed = JSON.parse(jsonData);
14
+ const importedProviders = Array.isArray(parsed)
15
+ ? parsed
16
+ : Array.isArray(parsed.providers)
17
+ ? parsed.providers
18
+ : null;
19
+ if (!importedProviders) {
20
+ throw new Error('Imported file does not contain a valid provider array.');
21
+ }
22
+ const existingProvidersMap = new Map(existingProviders.map(provider => [provider.name, provider]));
23
+ let updatedCount = 0;
24
+ let newCount = 0;
25
+ importedProviders.forEach(importedProvider => {
26
+ if (importedProvider && typeof importedProvider.name === 'string') {
27
+ if (existingProvidersMap.has(importedProvider.name)) {
28
+ existingProvidersMap.set(importedProvider.name, importedProvider);
29
+ updatedCount += 1;
30
+ }
31
+ else {
32
+ existingProvidersMap.set(importedProvider.name, importedProvider);
33
+ newCount += 1;
34
+ }
35
+ }
36
+ });
37
+ return {
38
+ importedProviders: Array.from(existingProvidersMap.values()),
39
+ newCount,
40
+ updatedCount
41
+ };
42
+ }
@@ -0,0 +1,231 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NOTEMD_PROVIDER_TEMPLATES = void 0;
4
+ exports.getNotemdProviderTemplate = getNotemdProviderTemplate;
5
+ exports.applyProviderTemplateToSettings = applyProviderTemplateToSettings;
6
+ exports.mergeProviderTemplatesIntoNotemdSection = mergeProviderTemplatesIntoNotemdSection;
7
+ const LlmProviderDefinitions_1 = require("./LlmProviderDefinitions");
8
+ const PROVIDER_TEMPLATE_SEEDS = [
9
+ {
10
+ id: 'deepseek-official',
11
+ providerName: 'DeepSeek',
12
+ label: 'DeepSeek Official',
13
+ recommendedFor: 'Direct hosted DeepSeek reasoning/chat models.',
14
+ apiKeyHint: 'Paste a DeepSeek API key.',
15
+ hostHint: 'Uses the official DeepSeek OpenAI-compatible endpoint.',
16
+ inspiredBy: ['Cherry Studio', 'DeepTutor'],
17
+ notes: [
18
+ 'Keep the /v1 suffix for the official endpoint.',
19
+ 'Reasoning-capable models may prefer lower temperature values.',
20
+ ],
21
+ },
22
+ {
23
+ id: 'openai-official',
24
+ providerName: 'OpenAI',
25
+ label: 'OpenAI Official',
26
+ recommendedFor: 'Direct OpenAI hosted GPT models.',
27
+ apiKeyHint: 'Paste an OpenAI API key.',
28
+ hostHint: 'Matches DeepTutor style host guidance: base URL stays at /v1.',
29
+ inspiredBy: ['Cherry Studio', 'DeepTutor'],
30
+ notes: [
31
+ 'Use a direct API key, not a session token.',
32
+ 'This preset is the cleanest baseline for hosted OpenAI models.',
33
+ ],
34
+ },
35
+ {
36
+ id: 'anthropic-official',
37
+ providerName: 'Anthropic',
38
+ label: 'Anthropic Official',
39
+ recommendedFor: 'Claude models over the native Anthropic API.',
40
+ apiKeyHint: 'Paste an Anthropic API key.',
41
+ hostHint: 'Anthropic does not use the OpenAI-compatible /v1 shape.',
42
+ inspiredBy: ['Cherry Studio'],
43
+ notes: [
44
+ 'The base URL should usually remain https://api.anthropic.com.',
45
+ 'Claude deployments do not need an OpenAI-compatible relay.',
46
+ ],
47
+ },
48
+ {
49
+ id: 'gemini-official',
50
+ providerName: 'Google',
51
+ label: 'Gemini Official',
52
+ recommendedFor: 'Google Gemini API over the official hosted endpoint.',
53
+ apiKeyHint: 'Paste a Google AI Studio / Gemini API key.',
54
+ hostHint: 'Uses the official Gemini REST endpoint, not an OpenAI relay.',
55
+ inspiredBy: ['Cherry Studio', 'DeepTutor'],
56
+ notes: [
57
+ 'This preset is for direct Gemini API usage.',
58
+ 'If you use an OpenAI-compatible Gemini relay, prefer OpenAI Compatible instead.',
59
+ ],
60
+ },
61
+ {
62
+ id: 'openrouter-gateway',
63
+ providerName: 'OpenRouter',
64
+ label: 'OpenRouter Gateway',
65
+ recommendedFor: 'Unified routing across many hosted model families.',
66
+ apiKeyHint: 'Paste an OpenRouter API key.',
67
+ hostHint: 'Gateway style endpoint inspired by Cherry Studio provider routing.',
68
+ inspiredBy: ['Cherry Studio'],
69
+ notes: [
70
+ 'Model ids usually include upstream vendor prefixes.',
71
+ 'Good default when you want one key for many providers.',
72
+ ],
73
+ },
74
+ {
75
+ id: 'lmstudio-local',
76
+ providerName: 'LMStudio',
77
+ label: 'LM Studio Local',
78
+ recommendedFor: 'Desktop local models exposed over an OpenAI-compatible server.',
79
+ apiKeyHint: 'Usually no API key is required.',
80
+ hostHint: 'DeepTutor-style local host guidance: prefer localhost on desktop, not inside containers.',
81
+ inspiredBy: ['Cherry Studio', 'DeepTutor'],
82
+ notes: [
83
+ 'Keep the local server running before testing the connection.',
84
+ 'If this app is containerized in the future, localhost must be replaced with a host bridge address.',
85
+ ],
86
+ },
87
+ {
88
+ id: 'ollama-local',
89
+ providerName: 'Ollama',
90
+ label: 'Ollama Local',
91
+ recommendedFor: 'Local Ollama chat models.',
92
+ apiKeyHint: 'No API key is required for a standard local Ollama instance.',
93
+ hostHint: "Uses Ollama's local HTTP API.",
94
+ inspiredBy: ['Cherry Studio', 'DeepTutor'],
95
+ notes: [
96
+ 'The model name must match an installed Ollama model.',
97
+ 'Keep the default host only for local desktop usage.',
98
+ ],
99
+ },
100
+ {
101
+ id: 'azure-openai',
102
+ providerName: 'Azure OpenAI',
103
+ label: 'Azure OpenAI',
104
+ recommendedFor: 'Azure OpenAI deployments that require deployment-specific base URLs.',
105
+ apiKeyHint: 'Paste an Azure OpenAI key.',
106
+ hostHint: 'Unlike standard OpenAI, Azure needs an explicit deployment URL and API version.',
107
+ inspiredBy: ['Cherry Studio', 'DeepTutor'],
108
+ notes: [
109
+ 'Fill in the full Azure resource endpoint plus deployment path.',
110
+ 'The API version field matters here and should not stay blank.',
111
+ ],
112
+ },
113
+ {
114
+ id: 'openai-compatible-custom',
115
+ providerName: 'OpenAI Compatible',
116
+ label: 'Custom OpenAI-Compatible',
117
+ recommendedFor: 'Self-hosted gateways, enterprise relays, and custom-compatible endpoints.',
118
+ apiKeyHint: 'Paste a key only if your relay requires one.',
119
+ hostHint: 'Use this when the endpoint follows OpenAI-compatible chat semantics.',
120
+ inspiredBy: ['Cherry Studio'],
121
+ notes: [
122
+ 'Best fallback preset when your provider is not in the built-in catalog.',
123
+ 'Check that the base URL already includes the /v1 segment if required by your relay.',
124
+ ],
125
+ },
126
+ ];
127
+ function buildTemplateFromSeed(seed) {
128
+ const fallback = (0, LlmProviderDefinitions_1.createDefaultProviders)().find((provider) => provider.name === seed.providerName);
129
+ const definition = (0, LlmProviderDefinitions_1.getProviderDefinition)(seed.providerName);
130
+ const defaultConfig = fallback || {
131
+ name: seed.providerName,
132
+ apiKey: '',
133
+ baseUrl: '',
134
+ model: '',
135
+ temperature: 0.5,
136
+ apiVersion: '',
137
+ enabled: true,
138
+ };
139
+ return {
140
+ id: seed.id,
141
+ label: seed.label,
142
+ providerName: seed.providerName,
143
+ category: definition.category,
144
+ transport: definition.transport,
145
+ apiKeyMode: definition.apiKeyMode,
146
+ baseUrl: defaultConfig.baseUrl,
147
+ model: defaultConfig.model,
148
+ apiVersion: String(defaultConfig.apiVersion || ''),
149
+ temperature: Number.isFinite(Number(defaultConfig.temperature))
150
+ ? Number(defaultConfig.temperature)
151
+ : 0.5,
152
+ recommendedFor: seed.recommendedFor,
153
+ apiKeyHint: seed.apiKeyHint,
154
+ hostHint: seed.hostHint,
155
+ inspiredBy: seed.inspiredBy.slice(),
156
+ notes: seed.notes.slice(),
157
+ };
158
+ }
159
+ exports.NOTEMD_PROVIDER_TEMPLATES = PROVIDER_TEMPLATE_SEEDS.map(buildTemplateFromSeed);
160
+ function getNotemdProviderTemplate(templateId) {
161
+ const normalizedId = String(templateId || '').trim();
162
+ return exports.NOTEMD_PROVIDER_TEMPLATES.find((template) => template.id === normalizedId) || null;
163
+ }
164
+ function applyProviderTemplateToSettings(settings, templateId) {
165
+ const template = getNotemdProviderTemplate(templateId);
166
+ if (!template) {
167
+ throw new Error(`Unknown provider template: ${templateId}`);
168
+ }
169
+ const next = JSON.parse(JSON.stringify(settings));
170
+ next.activeProvider = template.providerName;
171
+ let matched = false;
172
+ next.providers = next.providers.map((provider) => {
173
+ if (provider.name !== template.providerName) {
174
+ return provider;
175
+ }
176
+ matched = true;
177
+ return {
178
+ ...provider,
179
+ baseUrl: template.baseUrl,
180
+ model: template.model,
181
+ apiVersion: template.apiVersion,
182
+ temperature: template.temperature,
183
+ enabled: true,
184
+ };
185
+ });
186
+ if (!matched) {
187
+ const fallback = (0, LlmProviderDefinitions_1.createDefaultProviders)().find((provider) => provider.name === template.providerName);
188
+ if (fallback) {
189
+ next.providers.push({
190
+ ...fallback,
191
+ baseUrl: template.baseUrl,
192
+ model: template.model,
193
+ apiVersion: template.apiVersion,
194
+ temperature: template.temperature,
195
+ enabled: true,
196
+ });
197
+ }
198
+ }
199
+ return next;
200
+ }
201
+ function mergeProviderTemplatesIntoNotemdSection(notemdSectionLike) {
202
+ const nextNotemdSection = { ...(notemdSectionLike || {}) };
203
+ const existingTemplates = (nextNotemdSection.provider_templates &&
204
+ typeof nextNotemdSection.provider_templates === 'object' &&
205
+ !Array.isArray(nextNotemdSection.provider_templates))
206
+ ? { ...nextNotemdSection.provider_templates }
207
+ : {};
208
+ exports.NOTEMD_PROVIDER_TEMPLATES.forEach((template) => {
209
+ if (existingTemplates[template.id] && typeof existingTemplates[template.id] === 'object') {
210
+ return;
211
+ }
212
+ existingTemplates[template.id] = {
213
+ label: template.label,
214
+ provider_name: template.providerName,
215
+ category: template.category,
216
+ transport: template.transport,
217
+ api_key_mode: template.apiKeyMode,
218
+ base_url: template.baseUrl,
219
+ model: template.model,
220
+ api_version: template.apiVersion,
221
+ temperature: template.temperature,
222
+ recommended_for: template.recommendedFor,
223
+ api_key_hint: template.apiKeyHint,
224
+ host_hint: template.hostHint,
225
+ inspired_by: template.inspiredBy.slice(),
226
+ notes: template.notes.slice(),
227
+ };
228
+ });
229
+ nextNotemdSection.provider_templates = existingTemplates;
230
+ return nextNotemdSection;
231
+ }
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DuckDuckGoProvider = void 0;
4
+ class DuckDuckGoProvider {
5
+ constructor() {
6
+ this.name = 'duckduckgo';
7
+ }
8
+ async search(query, _apiKey, timeout = 10000) {
9
+ const encoded = encodeURIComponent(query.query);
10
+ const url = `https://api.duckduckgo.com/?q=${encoded}&format=json&no_html=1&skip_disambig=1`;
11
+ const maxResults = query.maxResults ?? 5;
12
+ const controller = new AbortController();
13
+ const timer = setTimeout(() => controller.abort(), timeout);
14
+ try {
15
+ const response = await fetch(url, { signal: controller.signal });
16
+ if (!response.ok)
17
+ return [];
18
+ const data = (await response.json());
19
+ const results = [];
20
+ if (data.AbstractText && data.AbstractURL) {
21
+ results.push({ title: data.AbstractText.slice(0, 100), url: data.AbstractURL, content: data.AbstractText });
22
+ }
23
+ const topics = data.RelatedTopics ?? [];
24
+ for (const topic of topics.slice(0, maxResults)) {
25
+ if (topic.Text && topic.FirstURL) {
26
+ results.push({ title: topic.Text.slice(0, 100), url: topic.FirstURL, content: topic.Text });
27
+ }
28
+ }
29
+ return results.slice(0, maxResults);
30
+ }
31
+ catch {
32
+ return [];
33
+ }
34
+ finally {
35
+ clearTimeout(timer);
36
+ }
37
+ }
38
+ }
39
+ exports.DuckDuckGoProvider = DuckDuckGoProvider;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SearchManager = void 0;
4
+ const DuckDuckGoProvider_1 = require("./DuckDuckGoProvider");
5
+ const TavilyProvider_1 = require("./TavilyProvider");
6
+ class SearchManager {
7
+ static getProvider(searchProvider) {
8
+ if (searchProvider === 'tavily')
9
+ return new TavilyProvider_1.TavilyProvider();
10
+ return new DuckDuckGoProvider_1.DuckDuckGoProvider();
11
+ }
12
+ }
13
+ exports.SearchManager = SearchManager;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TavilyProvider = void 0;
4
+ class TavilyProvider {
5
+ constructor() {
6
+ this.name = 'tavily';
7
+ }
8
+ async search(query, apiKey, timeout = 45000) {
9
+ if (!apiKey)
10
+ throw new Error('Tavily API key is required.');
11
+ const maxResults = query.maxResults ?? 5;
12
+ const controller = new AbortController();
13
+ const timer = setTimeout(() => controller.abort(), timeout);
14
+ try {
15
+ const response = await fetch('https://api.tavily.com/search', {
16
+ method: 'POST',
17
+ headers: { 'Content-Type': 'application/json' },
18
+ body: JSON.stringify({
19
+ api_key: apiKey,
20
+ query: query.query,
21
+ search_depth: query.searchDepth ?? 'basic',
22
+ max_results: maxResults,
23
+ include_answer: false,
24
+ include_raw_content: false
25
+ }),
26
+ signal: controller.signal
27
+ });
28
+ if (!response.ok) {
29
+ const errorText = await response.text().catch(() => 'Unknown error');
30
+ throw new Error(`Tavily API error (${response.status}): ${errorText}`);
31
+ }
32
+ const data = (await response.json());
33
+ return (data.results ?? []).slice(0, maxResults).map(r => ({
34
+ title: r.title ?? '',
35
+ url: r.url,
36
+ content: r.content
37
+ }));
38
+ }
39
+ finally {
40
+ clearTimeout(timer);
41
+ }
42
+ }
43
+ }
44
+ exports.TavilyProvider = TavilyProvider;