modular-studio 1.0.4 → 1.0.5

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 (101) hide show
  1. package/README.md +101 -20
  2. package/dist/assets/Badge-22Ai0eyi.js +1 -0
  3. package/dist/assets/Input-Bgp734xs.js +1 -0
  4. package/dist/assets/KnowledgeTab-DABxirZh.js +4 -0
  5. package/dist/assets/MemoryTab-DZeYElIT.js +16 -0
  6. package/dist/assets/QualificationTab-Dfpy3J30.js +1 -0
  7. package/dist/assets/ReviewTab-SD8lQuCc.js +103 -0
  8. package/dist/assets/Section-DoJrmytO.js +1 -0
  9. package/dist/assets/TestTab-PDyMF8Fw.js +33 -0
  10. package/dist/assets/ToolsTab-B83qGCmG.js +1 -0
  11. package/dist/assets/conversationStore-CkfEU2eV.js +1 -0
  12. package/dist/assets/icons-C2EV-le6.js +1 -0
  13. package/dist/assets/index-DkpMAxX7.css +1 -0
  14. package/dist/assets/index-q24ug5Qs.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-BaKotDf0.js +343 -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 +8 -4
  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 +2 -1
  27. package/dist-server/server/mcp/manager.js +0 -1
  28. package/dist-server/server/mcp/modular-server.js +0 -1
  29. package/dist-server/server/mcp/transport.js +0 -1
  30. package/dist-server/server/routes/agent-sdk.js +0 -1
  31. package/dist-server/server/routes/agents.d.ts +9 -5
  32. package/dist-server/server/routes/agents.d.ts.map +1 -1
  33. package/dist-server/server/routes/agents.js +81 -8
  34. package/dist-server/server/routes/auth-codex.js +0 -1
  35. package/dist-server/server/routes/capabilities.js +0 -1
  36. package/dist-server/server/routes/claude-config.js +0 -1
  37. package/dist-server/server/routes/connectors.d.ts.map +1 -1
  38. package/dist-server/server/routes/connectors.js +194 -1
  39. package/dist-server/server/routes/conversations.js +0 -1
  40. package/dist-server/server/routes/embeddings.js +0 -1
  41. package/dist-server/server/routes/health.js +0 -1
  42. package/dist-server/server/routes/knowledge.js +0 -1
  43. package/dist-server/server/routes/llm.js +0 -1
  44. package/dist-server/server/routes/mcp-oauth.js +0 -1
  45. package/dist-server/server/routes/mcp.js +0 -1
  46. package/dist-server/server/routes/memory.d.ts +3 -0
  47. package/dist-server/server/routes/memory.d.ts.map +1 -0
  48. package/dist-server/server/routes/memory.js +283 -0
  49. package/dist-server/server/routes/pipeline.js +0 -1
  50. package/dist-server/server/routes/providers.js +0 -1
  51. package/dist-server/server/routes/qualification.d.ts.map +1 -1
  52. package/dist-server/server/routes/qualification.js +382 -74
  53. package/dist-server/server/routes/repo-index.js +0 -1
  54. package/dist-server/server/routes/runtime.js +0 -1
  55. package/dist-server/server/routes/skills-search.d.ts.map +1 -1
  56. package/dist-server/server/routes/skills-search.js +39 -5
  57. package/dist-server/server/routes/worktrees.js +0 -1
  58. package/dist-server/server/services/__tests__/embeddingService.test.js +0 -1
  59. package/dist-server/server/services/adapters/postgresAdapter.d.ts +29 -0
  60. package/dist-server/server/services/adapters/postgresAdapter.d.ts.map +1 -0
  61. package/dist-server/server/services/adapters/postgresAdapter.js +224 -0
  62. package/dist-server/server/services/adapters/sqliteAdapter.d.ts +28 -0
  63. package/dist-server/server/services/adapters/sqliteAdapter.d.ts.map +1 -0
  64. package/dist-server/server/services/adapters/sqliteAdapter.js +219 -0
  65. package/dist-server/server/services/adapters/storageAdapter.d.ts +22 -0
  66. package/dist-server/server/services/adapters/storageAdapter.d.ts.map +1 -0
  67. package/dist-server/server/services/adapters/storageAdapter.js +1 -0
  68. package/dist-server/server/services/agentRunner.js +0 -1
  69. package/dist-server/server/services/agentStore.d.ts +18 -3
  70. package/dist-server/server/services/agentStore.d.ts.map +1 -1
  71. package/dist-server/server/services/agentStore.js +116 -23
  72. package/dist-server/server/services/contentStore.js +0 -1
  73. package/dist-server/server/services/embeddingService.d.ts +2 -0
  74. package/dist-server/server/services/embeddingService.d.ts.map +1 -1
  75. package/dist-server/server/services/embeddingService.js +30 -19
  76. package/dist-server/server/services/factExtractor.js +0 -1
  77. package/dist-server/server/services/githubIndexer.js +0 -1
  78. package/dist-server/server/services/mcpOAuth.js +0 -1
  79. package/dist-server/server/services/memoryScorer.js +0 -1
  80. package/dist-server/server/services/repoIndexer.js +0 -1
  81. package/dist-server/server/services/sqliteStore.js +0 -1
  82. package/dist-server/server/services/teamRunner.js +0 -1
  83. package/dist-server/server/services/worktreeManager.js +0 -1
  84. package/dist-server/server/types.d.ts +5 -0
  85. package/dist-server/server/types.d.ts.map +1 -1
  86. package/dist-server/server/types.js +0 -1
  87. package/dist-server/server/utils/pathSecurity.js +0 -1
  88. package/dist-server/src/services/budgetAllocator.js +0 -1
  89. package/dist-server/src/services/contradictionDetector.js +0 -1
  90. package/dist-server/src/services/treeIndexer.js +0 -1
  91. package/dist-server/src/store/knowledgeBase.d.ts +10 -0
  92. package/dist-server/src/store/knowledgeBase.d.ts.map +1 -1
  93. package/dist-server/src/store/knowledgeBase.js +13 -1
  94. package/dist-server/src/store/memoryStore.d.ts +107 -0
  95. package/dist-server/src/store/memoryStore.d.ts.map +1 -0
  96. package/dist-server/src/store/memoryStore.js +263 -0
  97. package/dist-server/tsconfig.server.tsbuildinfo +1 -1
  98. package/package.json +104 -97
  99. package/dist/assets/graphPopulator-B3rQxb5A.js +0 -1
  100. package/dist/assets/index-BA_J-aHx.js +0 -686
  101. package/dist/assets/index-C7vpqKVZ.css +0 -1
@@ -26,6 +26,7 @@ import pipelineRoutes from './routes/pipeline.js';
26
26
  import embeddingRoutes from './routes/embeddings.js';
27
27
  import embeddingService from './services/embeddingService.js';
28
28
  import conversationRoutes from './routes/conversations.js';
29
+ import memoryRoutes from './routes/memory.js';
29
30
  const __dirname = dirname(fileURLToPath(import.meta.url));
30
31
  export function createApp() {
31
32
  const app = express();
@@ -87,6 +88,7 @@ export function createApp() {
87
88
  app.use('/api/pipeline', pipelineRoutes);
88
89
  app.use('/api/embeddings', embeddingRoutes);
89
90
  app.use('/api/conversations', conversationRoutes);
91
+ app.use('/api/memory', memoryRoutes);
90
92
  // API 404 catch-all — log unmatched API routes for debugging
91
93
  app.use('/api', (_req, res) => {
92
94
  console.warn(`[API 404] ${_req.method} ${_req.originalUrl}`);
@@ -185,4 +187,3 @@ if (isMainModule && !globalThis.__modularStudioStarted) {
185
187
  process.on('SIGINT', () => { clearInterval(keepAlive); server.close(); process.exit(0); });
186
188
  process.on('SIGTERM', () => { clearInterval(keepAlive); server.close(); process.exit(0); });
187
189
  }
188
- //# sourceMappingURL=index.js.map
@@ -200,4 +200,3 @@ export class McpManager {
200
200
  }
201
201
  }
202
202
  export const mcpManager = new McpManager();
203
- //# sourceMappingURL=manager.js.map
@@ -489,4 +489,3 @@ function consolidateMemory(facts) {
489
489
  promoted,
490
490
  };
491
491
  }
492
- //# sourceMappingURL=modular-server.js.map
@@ -58,4 +58,3 @@ export function setupGracefulShutdown(server) {
58
58
  shutdown('unhandledRejection');
59
59
  });
60
60
  }
61
- //# sourceMappingURL=transport.js.map
@@ -96,4 +96,3 @@ router.get("/status", async (_req, res) => {
96
96
  }
97
97
  });
98
98
  export default router;
99
- //# sourceMappingURL=agent-sdk.js.map
@@ -1,9 +1,13 @@
1
1
  /**
2
- * Agent CRUD Routes
3
- * GET /api/agents — list all (summary only)
4
- * GET /api/agents/:id full state
5
- * PUT /api/agents/:id save/update
6
- * DELETE /api/agents/:id delete
2
+ * Agent CRUD Routes with Versioning
3
+ * GET /api/agents — list all (summary only)
4
+ * POST /api/agents create new agent (returns agentId)
5
+ * GET /api/agents/:id full latest state
6
+ * PUT /api/agents/:id save/update (creates new version)
7
+ * DELETE /api/agents/:id — delete
8
+ * GET /api/agents/:id/versions — list all versions
9
+ * POST /api/agents/:id/versions/:version/restore — restore to specific version
10
+ * DELETE /api/agents/:id/versions/:version — delete a version
7
11
  */
8
12
  declare const router: import("express-serve-static-core").Router;
9
13
  export default router;
@@ -1 +1 @@
1
- {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../../server/routes/agents.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,QAAA,MAAM,MAAM,4CAAW,CAAC;AAmDxB,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../../server/routes/agents.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAeH,QAAA,MAAM,MAAM,4CAAW,CAAC;AA6HxB,eAAe,MAAM,CAAC"}
@@ -1,13 +1,18 @@
1
1
  /**
2
- * Agent CRUD Routes
3
- * GET /api/agents — list all (summary only)
4
- * GET /api/agents/:id full state
5
- * PUT /api/agents/:id save/update
6
- * DELETE /api/agents/:id delete
2
+ * Agent CRUD Routes with Versioning
3
+ * GET /api/agents — list all (summary only)
4
+ * POST /api/agents create new agent (returns agentId)
5
+ * GET /api/agents/:id full latest state
6
+ * PUT /api/agents/:id save/update (creates new version)
7
+ * DELETE /api/agents/:id — delete
8
+ * GET /api/agents/:id/versions — list all versions
9
+ * POST /api/agents/:id/versions/:version/restore — restore to specific version
10
+ * DELETE /api/agents/:id/versions/:version — delete a version
7
11
  */
8
12
  import { Router } from 'express';
9
- import { saveAgent, loadAgent, listAgents, deleteAgent } from '../services/agentStore.js';
13
+ import { saveAgent, loadAgent, listAgents, deleteAgent, createAgentVersion, listAgentVersions, restoreAgentVersion, deleteAgentVersion } from '../services/agentStore.js';
10
14
  const router = Router();
15
+ // List all agents
11
16
  router.get('/', (_req, res) => {
12
17
  try {
13
18
  const agents = listAgents();
@@ -17,6 +22,24 @@ router.get('/', (_req, res) => {
17
22
  res.status(500).json({ status: 'error', error: err.message });
18
23
  }
19
24
  });
25
+ // Create new agent
26
+ router.post('/', (req, res) => {
27
+ try {
28
+ const state = req.body;
29
+ if (!state || typeof state !== 'object') {
30
+ res.status(400).json({ status: 'error', error: 'Invalid body' });
31
+ return;
32
+ }
33
+ const agentId = state.id || `agent-${Date.now()}`;
34
+ state.version = state.version || '0.1.0';
35
+ saveAgent(agentId, state);
36
+ res.json({ status: 'ok', data: { id: agentId } });
37
+ }
38
+ catch (err) {
39
+ res.status(500).json({ status: 'error', error: err.message });
40
+ }
41
+ });
42
+ // Get latest agent state
20
43
  router.get('/:id', (req, res) => {
21
44
  try {
22
45
  const agent = loadAgent(req.params.id);
@@ -30,6 +53,7 @@ router.get('/:id', (req, res) => {
30
53
  res.status(500).json({ status: 'error', error: err.message });
31
54
  }
32
55
  });
56
+ // Save/update agent (creates version)
33
57
  router.put('/:id', (req, res) => {
34
58
  try {
35
59
  const state = req.body;
@@ -37,13 +61,19 @@ router.put('/:id', (req, res) => {
37
61
  res.status(400).json({ status: 'error', error: 'Invalid body' });
38
62
  return;
39
63
  }
64
+ // Create version if agent exists and version changed
65
+ const existing = loadAgent(req.params.id);
66
+ if (existing && state.version && state.version !== existing.version) {
67
+ createAgentVersion(req.params.id, existing.version, 'Auto-saved version');
68
+ }
40
69
  saveAgent(req.params.id, state);
41
- res.json({ status: 'ok', data: { id: req.params.id } });
70
+ res.json({ status: 'ok', data: { id: req.params.id, version: state.version } });
42
71
  }
43
72
  catch (err) {
44
73
  res.status(500).json({ status: 'error', error: err.message });
45
74
  }
46
75
  });
76
+ // Delete agent
47
77
  router.delete('/:id', (req, res) => {
48
78
  try {
49
79
  const deleted = deleteAgent(req.params.id);
@@ -57,5 +87,48 @@ router.delete('/:id', (req, res) => {
57
87
  res.status(500).json({ status: 'error', error: err.message });
58
88
  }
59
89
  });
90
+ // List agent versions
91
+ router.get('/:id/versions', (req, res) => {
92
+ try {
93
+ const versions = listAgentVersions(req.params.id);
94
+ const formatted = versions.map(v => ({
95
+ id: v.id,
96
+ version: v.version,
97
+ timestamp: v.timestamp,
98
+ label: v.label,
99
+ }));
100
+ res.json({ status: 'ok', data: formatted });
101
+ }
102
+ catch (err) {
103
+ res.status(500).json({ status: 'error', error: err.message });
104
+ }
105
+ });
106
+ // Restore agent version
107
+ router.post('/:id/versions/:version/restore', (req, res) => {
108
+ try {
109
+ const restored = restoreAgentVersion(req.params.id, req.params.version);
110
+ if (!restored) {
111
+ res.status(404).json({ status: 'error', error: 'Version not found' });
112
+ return;
113
+ }
114
+ res.json({ status: 'ok', data: { restored: req.params.version } });
115
+ }
116
+ catch (err) {
117
+ res.status(500).json({ status: 'error', error: err.message });
118
+ }
119
+ });
120
+ // Delete agent version
121
+ router.delete('/:id/versions/:version', (req, res) => {
122
+ try {
123
+ const deleted = deleteAgentVersion(req.params.id, req.params.version);
124
+ if (!deleted) {
125
+ res.status(404).json({ status: 'error', error: 'Version not found' });
126
+ return;
127
+ }
128
+ res.json({ status: 'ok' });
129
+ }
130
+ catch (err) {
131
+ res.status(500).json({ status: 'error', error: err.message });
132
+ }
133
+ });
60
134
  export default router;
61
- //# sourceMappingURL=agents.js.map
@@ -48,4 +48,3 @@ router.post('/complete/:sessionId', (req, res) => {
48
48
  res.json(resp);
49
49
  });
50
50
  export default router;
51
- //# sourceMappingURL=auth-codex.js.map
@@ -29,4 +29,3 @@ router.get('/:providerId', (req, res) => {
29
29
  res.json({ status: 'ok', data: resolveMatrix(req.params.providerId) });
30
30
  });
31
31
  export default router;
32
- //# sourceMappingURL=capabilities.js.map
@@ -143,4 +143,3 @@ router.get('/project-mcp', (req, res) => {
143
143
  }
144
144
  });
145
145
  export default router;
146
- //# sourceMappingURL=claude-config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"connectors.d.ts","sourceRoot":"","sources":["../../../server/routes/connectors.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,QAAA,MAAM,MAAM,4CAAW,CAAC;AA0XxB,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"connectors.d.ts","sourceRoot":"","sources":["../../../server/routes/connectors.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,QAAA,MAAM,MAAM,4CAAW,CAAC;AA2jBxB,eAAe,MAAM,CAAC"}
@@ -324,5 +324,198 @@ router.delete('/auth/:service', (req, res) => {
324
324
  saveAuth(auth);
325
325
  res.json({ status: 'ok' });
326
326
  });
327
+ // ── In-memory session keys (never persisted to disk) ──
328
+ const sessionKeys = new Map();
329
+ // ── Notion helpers ──
330
+ function extractPageId(url) {
331
+ const hex32 = url.match(/([a-f0-9]{32})(?:[?#/]|$)/i);
332
+ if (hex32)
333
+ return hex32[1];
334
+ const uuid = url.match(/([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/i);
335
+ return uuid ? uuid[1].replace(/-/g, '') : null;
336
+ }
337
+ function notionHeaders(key) {
338
+ return { 'Authorization': `Bearer ${key}`, 'Notion-Version': '2022-06-28', 'Content-Type': 'application/json' };
339
+ }
340
+ function getBlockText(block) {
341
+ const content = block[block.type];
342
+ if (typeof content !== 'object' || !content || Array.isArray(content))
343
+ return '';
344
+ const rt = content.rich_text;
345
+ if (!Array.isArray(rt))
346
+ return '';
347
+ return rt.map(r => (typeof r === 'object' && r !== null ? String(r.plain_text ?? '') : '')).join('');
348
+ }
349
+ function blocksToMarkdown(blocks) {
350
+ const lines = [];
351
+ for (const b of blocks) {
352
+ const text = getBlockText(b);
353
+ if (!text)
354
+ continue;
355
+ if (b.type === 'heading_1')
356
+ lines.push(`# ${text}`);
357
+ else if (b.type === 'heading_2')
358
+ lines.push(`## ${text}`);
359
+ else if (b.type === 'heading_3')
360
+ lines.push(`### ${text}`);
361
+ else if (b.type === 'bulleted_list_item')
362
+ lines.push(`- ${text}`);
363
+ else if (b.type === 'numbered_list_item')
364
+ lines.push(`1. ${text}`);
365
+ else if (b.type === 'code')
366
+ lines.push(`\`\`\`\n${text}\n\`\`\``);
367
+ else
368
+ lines.push(text);
369
+ }
370
+ return lines.join('\n');
371
+ }
372
+ function getPageTitle(page) {
373
+ const titleProp = Object.values(page.properties).find(p => p.type === 'title');
374
+ return titleProp?.title?.[0]?.plain_text ?? page.id;
375
+ }
376
+ async function fetchAllBlocks(pageId, key) {
377
+ const blocks = [];
378
+ let cursor;
379
+ do {
380
+ const qs = cursor ? `?start_cursor=${encodeURIComponent(cursor)}` : '';
381
+ const resp = await fetch(`https://api.notion.com/v1/blocks/${pageId}/children${qs}`, { headers: notionHeaders(key) });
382
+ if (!resp.ok)
383
+ break;
384
+ const data = await resp.json();
385
+ blocks.push(...data.results);
386
+ cursor = data.has_more && data.next_cursor ? data.next_cursor : undefined;
387
+ } while (cursor);
388
+ return blocks;
389
+ }
390
+ async function fetchPage(pageId, key) {
391
+ const resp = await fetch(`https://api.notion.com/v1/pages/${pageId}`, { headers: notionHeaders(key) });
392
+ if (!resp.ok)
393
+ return null;
394
+ const page = await resp.json();
395
+ const title = getPageTitle(page);
396
+ const blocks = await fetchAllBlocks(pageId, key);
397
+ const content = blocksToMarkdown(blocks);
398
+ return { id: pageId, title, content, tokens: Math.ceil(content.length / 4) };
399
+ }
400
+ async function queryDatabase(dbId, key) {
401
+ const items = [];
402
+ let cursor;
403
+ do {
404
+ const body = JSON.stringify(cursor ? { start_cursor: cursor } : {});
405
+ const resp = await fetch(`https://api.notion.com/v1/databases/${dbId}/query`, { method: 'POST', headers: notionHeaders(key), body });
406
+ if (!resp.ok)
407
+ break;
408
+ const data = await resp.json();
409
+ for (const row of data.results) {
410
+ const title = getPageTitle(row);
411
+ items.push({ id: row.id, title, content: `# ${title}`, tokens: Math.ceil(title.length / 4) + 10 });
412
+ }
413
+ cursor = data.has_more && data.next_cursor ? data.next_cursor : undefined;
414
+ } while (cursor);
415
+ return items;
416
+ }
417
+ async function searchWorkspace(key) {
418
+ const body = JSON.stringify({ sort: { direction: 'descending', timestamp: 'last_edited_time' }, page_size: 10 });
419
+ const resp = await fetch('https://api.notion.com/v1/search', { method: 'POST', headers: notionHeaders(key), body });
420
+ if (!resp.ok)
421
+ return [];
422
+ const data = await resp.json();
423
+ const items = [];
424
+ for (const result of data.results) {
425
+ if (result.object !== 'page')
426
+ continue;
427
+ const page = await fetchPage(result.id, key);
428
+ if (page)
429
+ items.push(page);
430
+ }
431
+ return items;
432
+ }
433
+ /**
434
+ * POST /api/connectors/notion/test
435
+ * Validate a Notion API key by calling users/me.
436
+ */
437
+ router.post('/notion/test', async (req, res) => {
438
+ const body = req.body;
439
+ const apiKey = typeof body.apiKey === 'string' ? body.apiKey : '';
440
+ if (!apiKey) {
441
+ res.status(400).json({ status: 'error', error: 'Missing apiKey' });
442
+ return;
443
+ }
444
+ try {
445
+ const resp = await fetch('https://api.notion.com/v1/users/me', {
446
+ headers: { 'Authorization': `Bearer ${apiKey}`, 'Notion-Version': '2022-06-28' },
447
+ });
448
+ if (resp.status === 401) {
449
+ res.status(401).json({ status: 'error', error: 'Invalid Notion API key. Create one at notion.so/my-integrations' });
450
+ return;
451
+ }
452
+ if (resp.status === 429) {
453
+ const retryAfter = resp.headers.get('Retry-After') ?? '60';
454
+ res.status(429).json({ status: 'error', error: `Notion rate limit hit. Retry in ${retryAfter}s` });
455
+ return;
456
+ }
457
+ if (!resp.ok) {
458
+ res.status(resp.status).json({ status: 'error', error: `Notion API error: ${resp.status}` });
459
+ return;
460
+ }
461
+ const user = await resp.json();
462
+ sessionKeys.set('notion', apiKey);
463
+ res.json({ status: 'ok', data: { user: user.name ?? user.id } });
464
+ }
465
+ catch {
466
+ res.status(500).json({ status: 'error', error: 'Connection error. Check your network.' });
467
+ }
468
+ });
469
+ /**
470
+ * POST /api/connectors/notion/fetch
471
+ * Fetch pages/databases from Notion and return as markdown items.
472
+ * Body: { apiKey?, databaseIds?: string[], pageUrls?: string[] }
473
+ */
474
+ router.post('/notion/fetch', async (req, res) => {
475
+ const body = req.body;
476
+ const apiKey = typeof body.apiKey === 'string' && body.apiKey
477
+ ? body.apiKey
478
+ : (sessionKeys.get('notion') ?? '');
479
+ if (!apiKey) {
480
+ res.status(401).json({ status: 'error', error: 'No API key. Test connection first.' });
481
+ return;
482
+ }
483
+ const databaseIds = Array.isArray(body.databaseIds)
484
+ ? body.databaseIds.filter((s) => typeof s === 'string')
485
+ : [];
486
+ const pageUrls = Array.isArray(body.pageUrls)
487
+ ? body.pageUrls.filter((s) => typeof s === 'string')
488
+ : [];
489
+ try {
490
+ let items = [];
491
+ if (databaseIds.length > 0) {
492
+ for (const dbId of databaseIds) {
493
+ const rows = await queryDatabase(dbId.trim(), apiKey);
494
+ items.push(...rows);
495
+ }
496
+ }
497
+ else if (pageUrls.length > 0) {
498
+ for (const url of pageUrls) {
499
+ const pageId = extractPageId(url);
500
+ if (!pageId)
501
+ continue;
502
+ const page = await fetchPage(pageId, apiKey);
503
+ if (page)
504
+ items.push(page);
505
+ }
506
+ }
507
+ else {
508
+ items = await searchWorkspace(apiKey);
509
+ }
510
+ res.json({ status: 'ok', data: items });
511
+ }
512
+ catch (err) {
513
+ const msg = err instanceof Error ? err.message : '';
514
+ if (msg.includes('429')) {
515
+ res.status(429).json({ status: 'error', error: 'Notion rate limit hit. Retry in 60s' });
516
+ return;
517
+ }
518
+ res.status(500).json({ status: 'error', error: 'Failed to fetch from Notion. Check API key permissions.' });
519
+ }
520
+ });
327
521
  export default router;
328
- //# sourceMappingURL=connectors.js.map
@@ -108,4 +108,3 @@ router.delete('/:id', async (req, res) => {
108
108
  }
109
109
  });
110
110
  export default router;
111
- //# sourceMappingURL=conversations.js.map
@@ -152,4 +152,3 @@ router.post('/search', async (req, res) => {
152
152
  }
153
153
  });
154
154
  export default router;
155
- //# sourceMappingURL=embeddings.js.map
@@ -291,4 +291,3 @@ router.post('/skills/:id/update', async (req, res) => {
291
291
  }
292
292
  });
293
293
  export default router;
294
- //# sourceMappingURL=health.js.map
@@ -531,4 +531,3 @@ router.post('/embed', async (req, res) => {
531
531
  }
532
532
  });
533
533
  export default router;
534
- //# sourceMappingURL=knowledge.js.map
@@ -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":"AASA,QAAA,MAAM,MAAM,4CAAW,CAAC;AAmSxB,eAAe,MAAM,CAAC"}