modular-studio 1.0.4 → 1.0.6

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 (129) hide show
  1. package/README.md +122 -41
  2. package/dist/assets/Badge-DrUmDAXz.js +1 -0
  3. package/dist/assets/Input-ndEGQSgx.js +1 -0
  4. package/dist/assets/KnowledgeTab-CxlC76Rf.js +4 -0
  5. package/dist/assets/MemoryTab-CUScYWs9.js +16 -0
  6. package/dist/assets/QualificationTab-BqnWSQHm.js +1 -0
  7. package/dist/assets/ReviewTab-DKYl6cR9.js +103 -0
  8. package/dist/assets/Section-CgmwAj_2.js +1 -0
  9. package/dist/assets/TestTab-iJ2vCf9l.js +33 -0
  10. package/dist/assets/ToolsTab-C10Ulm8b.js +1 -0
  11. package/dist/assets/conversationStore-CkfEU2eV.js +1 -0
  12. package/dist/assets/icons-MKpPNvV8.js +1 -0
  13. package/dist/assets/index-B_ip7Amg.css +1 -0
  14. package/dist/assets/index-gBy3427k.js +143 -0
  15. package/dist/assets/{jszip.min-BK6ZQWkj.js → jszip.min-wf-D3Ix_.js} +1 -1
  16. package/dist/assets/markdown-DWF7F0i0.js +29 -0
  17. package/dist/assets/services-CTWXQK6j.js +356 -0
  18. package/dist/assets/stores-CeKWz7ou.js +1 -0
  19. package/dist/assets/vendor-D1h_O76p.js +9 -0
  20. package/dist/index.html +20 -16
  21. package/dist-server/bin/modular-mcp.js +0 -1
  22. package/dist-server/bin/modular-studio.js +0 -1
  23. package/dist-server/server/config.js +0 -1
  24. package/dist-server/server/data/mcp-tokens.json +3 -3
  25. package/dist-server/server/index.d.ts.map +1 -1
  26. package/dist-server/server/index.js +6 -1
  27. package/dist-server/server/mcp/manager.d.ts.map +1 -1
  28. package/dist-server/server/mcp/manager.js +16 -3
  29. package/dist-server/server/mcp/modular-server.js +0 -1
  30. package/dist-server/server/mcp/transport.js +0 -1
  31. package/dist-server/server/routes/agent-sdk.js +0 -1
  32. package/dist-server/server/routes/agents.d.ts +9 -5
  33. package/dist-server/server/routes/agents.d.ts.map +1 -1
  34. package/dist-server/server/routes/agents.js +108 -8
  35. package/dist-server/server/routes/auth-codex.js +0 -1
  36. package/dist-server/server/routes/cache.d.ts +3 -0
  37. package/dist-server/server/routes/cache.d.ts.map +1 -0
  38. package/dist-server/server/routes/cache.js +55 -0
  39. package/dist-server/server/routes/capabilities.js +0 -1
  40. package/dist-server/server/routes/claude-config.js +0 -1
  41. package/dist-server/server/routes/connectors.d.ts.map +1 -1
  42. package/dist-server/server/routes/connectors.js +224 -1
  43. package/dist-server/server/routes/conversations.js +0 -1
  44. package/dist-server/server/routes/embeddings.js +0 -1
  45. package/dist-server/server/routes/health.js +0 -1
  46. package/dist-server/server/routes/knowledge.js +0 -1
  47. package/dist-server/server/routes/lessons.d.ts +3 -0
  48. package/dist-server/server/routes/lessons.d.ts.map +1 -0
  49. package/dist-server/server/routes/lessons.js +46 -0
  50. package/dist-server/server/routes/llm.js +0 -1
  51. package/dist-server/server/routes/mcp-oauth.js +0 -1
  52. package/dist-server/server/routes/mcp.js +0 -1
  53. package/dist-server/server/routes/memory.d.ts +3 -0
  54. package/dist-server/server/routes/memory.d.ts.map +1 -0
  55. package/dist-server/server/routes/memory.js +314 -0
  56. package/dist-server/server/routes/pipeline.js +0 -1
  57. package/dist-server/server/routes/providers.js +0 -1
  58. package/dist-server/server/routes/qualification.d.ts.map +1 -1
  59. package/dist-server/server/routes/qualification.js +341 -75
  60. package/dist-server/server/routes/repo-index.d.ts.map +1 -1
  61. package/dist-server/server/routes/repo-index.js +7 -1
  62. package/dist-server/server/routes/runtime.js +0 -1
  63. package/dist-server/server/routes/skills-search.d.ts.map +1 -1
  64. package/dist-server/server/routes/skills-search.js +198 -8
  65. package/dist-server/server/routes/worktrees.js +0 -1
  66. package/dist-server/server/services/__tests__/embeddingService.test.js +0 -1
  67. package/dist-server/server/services/adapters/hindsightAdapter.d.ts +28 -0
  68. package/dist-server/server/services/adapters/hindsightAdapter.d.ts.map +1 -0
  69. package/dist-server/server/services/adapters/hindsightAdapter.js +63 -0
  70. package/dist-server/server/services/adapters/postgresAdapter.d.ts +29 -0
  71. package/dist-server/server/services/adapters/postgresAdapter.d.ts.map +1 -0
  72. package/dist-server/server/services/adapters/postgresAdapter.js +224 -0
  73. package/dist-server/server/services/adapters/sqliteAdapter.d.ts +28 -0
  74. package/dist-server/server/services/adapters/sqliteAdapter.d.ts.map +1 -0
  75. package/dist-server/server/services/adapters/sqliteAdapter.js +219 -0
  76. package/dist-server/server/services/adapters/storageAdapter.d.ts +22 -0
  77. package/dist-server/server/services/adapters/storageAdapter.d.ts.map +1 -0
  78. package/dist-server/server/services/adapters/storageAdapter.js +1 -0
  79. package/dist-server/server/services/agentRunner.js +0 -1
  80. package/dist-server/server/services/agentStore.d.ts +19 -3
  81. package/dist-server/server/services/agentStore.d.ts.map +1 -1
  82. package/dist-server/server/services/agentStore.js +117 -23
  83. package/dist-server/server/services/contentStore.js +0 -1
  84. package/dist-server/server/services/correctionDetector.d.ts +22 -0
  85. package/dist-server/server/services/correctionDetector.d.ts.map +1 -0
  86. package/dist-server/server/services/correctionDetector.js +91 -0
  87. package/dist-server/server/services/embeddingService.d.ts +2 -0
  88. package/dist-server/server/services/embeddingService.d.ts.map +1 -1
  89. package/dist-server/server/services/embeddingService.js +30 -19
  90. package/dist-server/server/services/factExtractor.js +0 -1
  91. package/dist-server/server/services/githubIndexer.js +0 -1
  92. package/dist-server/server/services/hindsightClient.d.ts +15 -0
  93. package/dist-server/server/services/hindsightClient.d.ts.map +1 -0
  94. package/dist-server/server/services/hindsightClient.js +47 -0
  95. package/dist-server/server/services/lessonExtractor.d.ts +19 -0
  96. package/dist-server/server/services/lessonExtractor.d.ts.map +1 -0
  97. package/dist-server/server/services/lessonExtractor.js +87 -0
  98. package/dist-server/server/services/mcpOAuth.js +0 -1
  99. package/dist-server/server/services/memoryScorer.js +0 -1
  100. package/dist-server/server/services/repoIndexer.js +0 -1
  101. package/dist-server/server/services/responseCache.d.ts +24 -0
  102. package/dist-server/server/services/responseCache.d.ts.map +1 -0
  103. package/dist-server/server/services/responseCache.js +163 -0
  104. package/dist-server/server/services/sqliteStore.d.ts +8 -0
  105. package/dist-server/server/services/sqliteStore.d.ts.map +1 -1
  106. package/dist-server/server/services/sqliteStore.js +53 -14
  107. package/dist-server/server/services/teamRunner.js +0 -1
  108. package/dist-server/server/services/worktreeManager.js +0 -1
  109. package/dist-server/server/types.d.ts +5 -0
  110. package/dist-server/server/types.d.ts.map +1 -1
  111. package/dist-server/server/types.js +0 -1
  112. package/dist-server/server/utils/pathSecurity.js +0 -1
  113. package/dist-server/src/services/budgetAllocator.js +0 -1
  114. package/dist-server/src/services/contradictionDetector.js +0 -1
  115. package/dist-server/src/services/treeIndexer.js +0 -1
  116. package/dist-server/src/store/knowledgeBase.d.ts +11 -0
  117. package/dist-server/src/store/knowledgeBase.d.ts.map +1 -1
  118. package/dist-server/src/store/knowledgeBase.js +13 -1
  119. package/dist-server/src/store/lessonStore.d.ts +26 -0
  120. package/dist-server/src/store/lessonStore.d.ts.map +1 -0
  121. package/dist-server/src/store/lessonStore.js +64 -0
  122. package/dist-server/src/store/memoryStore.d.ts +118 -0
  123. package/dist-server/src/store/memoryStore.d.ts.map +1 -0
  124. package/dist-server/src/store/memoryStore.js +272 -0
  125. package/dist-server/tsconfig.server.tsbuildinfo +1 -1
  126. package/package.json +9 -1
  127. package/dist/assets/graphPopulator-B3rQxb5A.js +0 -1
  128. package/dist/assets/index-BA_J-aHx.js +0 -686
  129. package/dist/assets/index-C7vpqKVZ.css +0 -1
@@ -0,0 +1,46 @@
1
+ import { Router } from 'express';
2
+ import { readConfig } from '../config.js';
3
+ import { detectCorrection } from '../services/correctionDetector.js';
4
+ import { extractLesson } from '../services/lessonExtractor.js';
5
+ const router = Router();
6
+ function genId() {
7
+ return `lesson-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
8
+ }
9
+ router.post('/extract', async (req, res) => {
10
+ const { userMessage, previousAssistant, providerId, model, agentId } = req.body;
11
+ if (!userMessage || !providerId || !model) {
12
+ res.status(400).json({ error: 'Missing required fields' });
13
+ return;
14
+ }
15
+ const correction = detectCorrection(userMessage, previousAssistant ?? '');
16
+ if (!correction) {
17
+ res.json({ lesson: null });
18
+ return;
19
+ }
20
+ const config = readConfig();
21
+ const provider = config.providers.find((p) => p.id === providerId);
22
+ if (!provider) {
23
+ res.json({ lesson: null });
24
+ return;
25
+ }
26
+ try {
27
+ const extracted = await extractLesson(correction, { type: provider.type, baseUrl: provider.baseUrl, apiKey: provider.apiKey }, model);
28
+ if (!extracted) {
29
+ res.json({ lesson: null });
30
+ return;
31
+ }
32
+ const lesson = {
33
+ rule: extracted.rule,
34
+ category: extracted.category,
35
+ agentId: agentId ?? '',
36
+ sourceUserMessage: userMessage,
37
+ sourcePreviousAssistant: previousAssistant ?? '',
38
+ };
39
+ res.json({ lesson: { ...lesson, id: genId(), createdAt: Date.now(), appliedCount: 0, status: 'pending' } });
40
+ }
41
+ catch (err) {
42
+ const message = err instanceof Error ? err.message : 'Extraction failed';
43
+ res.status(500).json({ error: message });
44
+ }
45
+ });
46
+ export default router;
@@ -197,4 +197,3 @@ router.post('/chat-tools', async (req, res) => {
197
197
  }
198
198
  });
199
199
  export default router;
200
- //# sourceMappingURL=llm.js.map
@@ -134,4 +134,3 @@ function callbackPage(success, error, serverUrl) {
134
134
  </body>
135
135
  </html>`;
136
136
  }
137
- //# sourceMappingURL=mcp-oauth.js.map
@@ -174,4 +174,3 @@ router.get('/:id/health', (req, res) => {
174
174
  }
175
175
  });
176
176
  export default router;
177
- //# sourceMappingURL=mcp.js.map
@@ -0,0 +1,3 @@
1
+ declare const router: import("express-serve-static-core").Router;
2
+ export default router;
3
+ //# sourceMappingURL=memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../../server/routes/memory.ts"],"names":[],"mappings":"AAUA,QAAA,MAAM,MAAM,4CAAW,CAAC;AA8TxB,eAAe,MAAM,CAAC"}
@@ -0,0 +1,314 @@
1
+ import { Router } from 'express';
2
+ import { SqliteAdapter } from '../services/adapters/sqliteAdapter.js';
3
+ import { PostgresAdapter } from '../services/adapters/postgresAdapter.js';
4
+ import { HindsightAdapter } from '../services/adapters/hindsightAdapter.js';
5
+ import { extractFacts, extractFactsWithLlm } from '../services/factExtractor.js';
6
+ import { rankFacts } from '../services/memoryScorer.js';
7
+ import { readConfig, writeConfig } from '../config.js';
8
+ const router = Router();
9
+ // Global state for the current adapter
10
+ let currentAdapter = null;
11
+ let currentBackend = 'local_sqlite';
12
+ let connectionString = null;
13
+ async function getAdapter() {
14
+ if (!currentAdapter) {
15
+ const config = readConfig();
16
+ const memoryConfig = config.memory || { backend: 'local_sqlite' };
17
+ currentBackend = memoryConfig.backend || 'local_sqlite';
18
+ connectionString = memoryConfig.connectionString || null;
19
+ if (currentBackend === 'postgres' && connectionString) {
20
+ currentAdapter = new PostgresAdapter(connectionString);
21
+ }
22
+ else if (currentBackend === 'hindsight') {
23
+ currentAdapter = new HindsightAdapter(connectionString ?? 'http://localhost:8888');
24
+ }
25
+ else {
26
+ currentAdapter = new SqliteAdapter();
27
+ }
28
+ await currentAdapter.initialize();
29
+ }
30
+ return currentAdapter;
31
+ }
32
+ async function switchAdapter(backend, connStr) {
33
+ if (currentAdapter) {
34
+ await currentAdapter.close();
35
+ currentAdapter = null;
36
+ }
37
+ currentBackend = backend;
38
+ connectionString = connStr || null;
39
+ if (backend === 'postgres' && connStr) {
40
+ currentAdapter = new PostgresAdapter(connStr);
41
+ }
42
+ else if (backend === 'hindsight') {
43
+ currentAdapter = new HindsightAdapter(connStr ?? 'http://localhost:8888');
44
+ }
45
+ else {
46
+ currentAdapter = new SqliteAdapter();
47
+ }
48
+ await currentAdapter.initialize();
49
+ // Save config
50
+ const config = readConfig();
51
+ config.memory = {
52
+ ...config.memory,
53
+ backend,
54
+ ...(connStr && { connectionString: connStr })
55
+ };
56
+ writeConfig(config);
57
+ }
58
+ // GET /api/memory/facts - list facts (with pagination, domain filter)
59
+ router.get('/facts', async (req, res) => {
60
+ try {
61
+ const { domain, limit, offset } = req.query;
62
+ const adapter = await getAdapter();
63
+ const options = {};
64
+ if (domain)
65
+ options.domain = domain;
66
+ if (limit)
67
+ options.limit = parseInt(limit);
68
+ if (offset)
69
+ options.offset = parseInt(offset);
70
+ const facts = await adapter.getFacts(options);
71
+ res.json({ status: 'success', facts });
72
+ }
73
+ catch (error) {
74
+ console.error('[Memory] Failed to get facts:', error);
75
+ res.status(500).json({
76
+ status: 'error',
77
+ error: error instanceof Error ? error.message : 'Unknown error'
78
+ });
79
+ }
80
+ });
81
+ // POST /api/memory/facts - create fact
82
+ router.post('/facts', async (req, res) => {
83
+ try {
84
+ const fact = req.body;
85
+ if (!fact.id || !fact.content) {
86
+ return res.status(400).json({
87
+ status: 'error',
88
+ error: 'Missing required fields: id, content'
89
+ });
90
+ }
91
+ const adapter = await getAdapter();
92
+ await adapter.storeFact(fact);
93
+ res.json({ status: 'success' });
94
+ }
95
+ catch (error) {
96
+ console.error('[Memory] Failed to create fact:', error);
97
+ res.status(500).json({
98
+ status: 'error',
99
+ error: error instanceof Error ? error.message : 'Unknown error'
100
+ });
101
+ }
102
+ });
103
+ // PUT /api/memory/facts/:id - update fact
104
+ router.put('/facts/:id', async (req, res) => {
105
+ try {
106
+ const { id } = req.params;
107
+ const patch = req.body;
108
+ const adapter = await getAdapter();
109
+ await adapter.updateFact(id, patch);
110
+ res.json({ status: 'success' });
111
+ }
112
+ catch (error) {
113
+ console.error('[Memory] Failed to update fact:', error);
114
+ res.status(500).json({
115
+ status: 'error',
116
+ error: error instanceof Error ? error.message : 'Unknown error'
117
+ });
118
+ }
119
+ });
120
+ // DELETE /api/memory/facts/:id - delete fact
121
+ router.delete('/facts/:id', async (req, res) => {
122
+ try {
123
+ const { id } = req.params;
124
+ const adapter = await getAdapter();
125
+ await adapter.deleteFact(id);
126
+ res.json({ status: 'success' });
127
+ }
128
+ catch (error) {
129
+ console.error('[Memory] Failed to delete fact:', error);
130
+ res.status(500).json({
131
+ status: 'error',
132
+ error: error instanceof Error ? error.message : 'Unknown error'
133
+ });
134
+ }
135
+ });
136
+ // POST /api/memory/search - semantic search
137
+ router.post('/search', async (req, res) => {
138
+ try {
139
+ const { query, k } = req.body;
140
+ if (!query) {
141
+ return res.status(400).json({
142
+ status: 'error',
143
+ error: 'Missing required field: query'
144
+ });
145
+ }
146
+ const adapter = await getAdapter();
147
+ const results = await adapter.searchFacts(query, k || 5);
148
+ res.json({ status: 'success', results });
149
+ }
150
+ catch (error) {
151
+ console.error('[Memory] Failed to search facts:', error);
152
+ res.status(500).json({
153
+ status: 'error',
154
+ error: error instanceof Error ? error.message : 'Unknown error'
155
+ });
156
+ }
157
+ });
158
+ // POST /api/memory/extract - call factExtractor on input text
159
+ router.post('/extract', async (req, res) => {
160
+ try {
161
+ const { text, agentId, useLlm, providerId, model } = req.body;
162
+ if (!text || !agentId) {
163
+ return res.status(400).json({
164
+ status: 'error',
165
+ error: 'Missing required fields: text, agentId'
166
+ });
167
+ }
168
+ let facts;
169
+ if (useLlm && providerId && model) {
170
+ facts = await extractFactsWithLlm(text, agentId, providerId, model);
171
+ }
172
+ else {
173
+ facts = extractFacts(text, agentId);
174
+ }
175
+ res.json({ status: 'success', facts });
176
+ }
177
+ catch (error) {
178
+ console.error('[Memory] Failed to extract facts:', error);
179
+ res.status(500).json({
180
+ status: 'error',
181
+ error: error instanceof Error ? error.message : 'Unknown error'
182
+ });
183
+ }
184
+ });
185
+ // POST /api/memory/score - call memoryScorer on facts
186
+ router.post('/score', async (req, res) => {
187
+ try {
188
+ const { facts, query, limit } = req.body;
189
+ if (!facts || !Array.isArray(facts)) {
190
+ return res.status(400).json({
191
+ status: 'error',
192
+ error: 'Missing or invalid required field: facts (array)'
193
+ });
194
+ }
195
+ const scored = rankFacts(facts, query || '', limit);
196
+ res.json({ status: 'success', facts: scored });
197
+ }
198
+ catch (error) {
199
+ console.error('[Memory] Failed to score facts:', error);
200
+ res.status(500).json({
201
+ status: 'error',
202
+ error: error instanceof Error ? error.message : 'Unknown error'
203
+ });
204
+ }
205
+ });
206
+ // GET /api/memory/config - get current backend config
207
+ router.get('/config', (_req, res) => {
208
+ try {
209
+ const config = readConfig();
210
+ const memoryConfig = config.memory || { backend: 'local_sqlite' };
211
+ res.json({
212
+ status: 'success',
213
+ config: {
214
+ ...memoryConfig,
215
+ backend: currentBackend,
216
+ connectionString: currentBackend === 'postgres' ? connectionString : undefined
217
+ }
218
+ });
219
+ }
220
+ catch (error) {
221
+ console.error('[Memory] Failed to get config:', error);
222
+ res.status(500).json({
223
+ status: 'error',
224
+ error: error instanceof Error ? error.message : 'Unknown error'
225
+ });
226
+ }
227
+ });
228
+ // POST /api/memory/config - set backend config (store type, connection string)
229
+ router.post('/config', async (req, res) => {
230
+ try {
231
+ const { backend, connectionString: connStr } = req.body;
232
+ if (!backend) {
233
+ return res.status(400).json({
234
+ status: 'error',
235
+ error: 'Missing required field: backend'
236
+ });
237
+ }
238
+ if (backend === 'postgres' && !connStr) {
239
+ return res.status(400).json({
240
+ status: 'error',
241
+ error: 'PostgreSQL backend requires connectionString'
242
+ });
243
+ }
244
+ // Test connection before switching
245
+ let testAdapter;
246
+ if (backend === 'postgres') {
247
+ testAdapter = new PostgresAdapter(connStr);
248
+ }
249
+ else if (backend === 'hindsight') {
250
+ testAdapter = new HindsightAdapter(connStr ?? 'http://localhost:8888');
251
+ }
252
+ else {
253
+ testAdapter = new SqliteAdapter();
254
+ }
255
+ try {
256
+ await testAdapter.initialize();
257
+ await testAdapter.getHealth();
258
+ await testAdapter.close();
259
+ }
260
+ catch (testError) {
261
+ return res.status(400).json({
262
+ status: 'error',
263
+ error: `Failed to connect to ${backend}: ${testError instanceof Error ? testError.message : 'Unknown error'}`
264
+ });
265
+ }
266
+ await switchAdapter(backend, connStr);
267
+ res.json({ status: 'success' });
268
+ }
269
+ catch (error) {
270
+ console.error('[Memory] Failed to set config:', error);
271
+ res.status(500).json({
272
+ status: 'error',
273
+ error: error instanceof Error ? error.message : 'Unknown error'
274
+ });
275
+ }
276
+ });
277
+ // POST /api/memory/hindsight/reflect - generate higher-order insight (Hindsight only)
278
+ router.post('/hindsight/reflect', async (req, res) => {
279
+ try {
280
+ const { query } = req.body;
281
+ if (!query) {
282
+ return res.status(400).json({ status: 'error', error: 'Missing required field: query' });
283
+ }
284
+ const adapter = await getAdapter();
285
+ if (!(adapter instanceof HindsightAdapter)) {
286
+ return res.status(400).json({ status: 'error', error: 'reflect requires hindsight backend' });
287
+ }
288
+ const insight = await adapter.reflect(query);
289
+ res.json({ status: 'success', insight });
290
+ }
291
+ catch (error) {
292
+ res.status(500).json({
293
+ status: 'error',
294
+ error: error instanceof Error ? error.message : 'Unknown error'
295
+ });
296
+ }
297
+ });
298
+ // GET /api/memory/health - backend health check (never 500 — always returns a health object)
299
+ router.get('/health', async (_req, res) => {
300
+ try {
301
+ const adapter = await getAdapter();
302
+ const health = await adapter.getHealth();
303
+ res.json({ status: 'success', health, backend: currentBackend });
304
+ }
305
+ catch (error) {
306
+ // Return 200 with degraded health — don't 500 or the frontend will loop
307
+ res.json({
308
+ status: 'success',
309
+ health: { status: 'unavailable', factCount: 0, error: error instanceof Error ? error.message : 'Adapter init failed' },
310
+ backend: currentBackend
311
+ });
312
+ }
313
+ });
314
+ export default router;
@@ -480,4 +480,3 @@ router.post('/assemble', async (req, res) => {
480
480
  }
481
481
  });
482
482
  export default router;
483
- //# sourceMappingURL=pipeline.js.map
@@ -201,4 +201,3 @@ router.post('/:id/test', async (req, res) => {
201
201
  }
202
202
  });
203
203
  export default router;
204
- //# sourceMappingURL=providers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"qualification.d.ts","sourceRoot":"","sources":["../../../server/routes/qualification.ts"],"names":[],"mappings":"AAIA,QAAA,MAAM,MAAM,4CAAW,CAAC;AA2LxB,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"qualification.d.ts","sourceRoot":"","sources":["../../../server/routes/qualification.ts"],"names":[],"mappings":"AAOA,QAAA,MAAM,MAAM,4CAAW,CAAC;AAkexB,eAAe,MAAM,CAAC"}