modular-studio 0.2.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 (187) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +261 -0
  3. package/dist/assets/graphPopulator-C6jg83nL.js +1 -0
  4. package/dist/assets/index-CXhIX28x.js +634 -0
  5. package/dist/assets/index-CeNF0r-K.css +1 -0
  6. package/dist/assets/jszip.min-BlpRodxc.js +2 -0
  7. package/dist/index.html +16 -0
  8. package/dist/vite.svg +1 -0
  9. package/dist-server/bin/modular-mcp.d.ts +8 -0
  10. package/dist-server/bin/modular-mcp.d.ts.map +1 -0
  11. package/dist-server/bin/modular-mcp.js +158 -0
  12. package/dist-server/bin/modular-mcp.js.map +1 -0
  13. package/dist-server/bin/modular-studio.d.ts +3 -0
  14. package/dist-server/bin/modular-studio.d.ts.map +1 -0
  15. package/dist-server/bin/modular-studio.js +63 -0
  16. package/dist-server/bin/modular-studio.js.map +1 -0
  17. package/dist-server/server/config.d.ts +4 -0
  18. package/dist-server/server/config.d.ts.map +1 -0
  19. package/dist-server/server/config.js +33 -0
  20. package/dist-server/server/config.js.map +1 -0
  21. package/dist-server/server/data/mcp-clients.json +5 -0
  22. package/dist-server/server/index.d.ts +3 -0
  23. package/dist-server/server/index.d.ts.map +1 -0
  24. package/dist-server/server/index.js +174 -0
  25. package/dist-server/server/index.js.map +1 -0
  26. package/dist-server/server/mcp/manager.d.ts +47 -0
  27. package/dist-server/server/mcp/manager.d.ts.map +1 -0
  28. package/dist-server/server/mcp/manager.js +203 -0
  29. package/dist-server/server/mcp/manager.js.map +1 -0
  30. package/dist-server/server/mcp/modular-server.d.ts +55 -0
  31. package/dist-server/server/mcp/modular-server.d.ts.map +1 -0
  32. package/dist-server/server/mcp/modular-server.js +492 -0
  33. package/dist-server/server/mcp/modular-server.js.map +1 -0
  34. package/dist-server/server/mcp/transport.d.ts +29 -0
  35. package/dist-server/server/mcp/transport.d.ts.map +1 -0
  36. package/dist-server/server/mcp/transport.js +61 -0
  37. package/dist-server/server/mcp/transport.js.map +1 -0
  38. package/dist-server/server/routes/agent-sdk.d.ts +3 -0
  39. package/dist-server/server/routes/agent-sdk.d.ts.map +1 -0
  40. package/dist-server/server/routes/agent-sdk.js +99 -0
  41. package/dist-server/server/routes/agent-sdk.js.map +1 -0
  42. package/dist-server/server/routes/agents.d.ts +10 -0
  43. package/dist-server/server/routes/agents.d.ts.map +1 -0
  44. package/dist-server/server/routes/agents.js +61 -0
  45. package/dist-server/server/routes/agents.js.map +1 -0
  46. package/dist-server/server/routes/auth-codex.d.ts +3 -0
  47. package/dist-server/server/routes/auth-codex.d.ts.map +1 -0
  48. package/dist-server/server/routes/auth-codex.js +51 -0
  49. package/dist-server/server/routes/auth-codex.js.map +1 -0
  50. package/dist-server/server/routes/capabilities.d.ts +3 -0
  51. package/dist-server/server/routes/capabilities.d.ts.map +1 -0
  52. package/dist-server/server/routes/capabilities.js +32 -0
  53. package/dist-server/server/routes/capabilities.js.map +1 -0
  54. package/dist-server/server/routes/claude-config.d.ts +3 -0
  55. package/dist-server/server/routes/claude-config.d.ts.map +1 -0
  56. package/dist-server/server/routes/claude-config.js +146 -0
  57. package/dist-server/server/routes/claude-config.js.map +1 -0
  58. package/dist-server/server/routes/connectors.d.ts +12 -0
  59. package/dist-server/server/routes/connectors.d.ts.map +1 -0
  60. package/dist-server/server/routes/connectors.js +325 -0
  61. package/dist-server/server/routes/connectors.js.map +1 -0
  62. package/dist-server/server/routes/embeddings.d.ts +6 -0
  63. package/dist-server/server/routes/embeddings.d.ts.map +1 -0
  64. package/dist-server/server/routes/embeddings.js +130 -0
  65. package/dist-server/server/routes/embeddings.js.map +1 -0
  66. package/dist-server/server/routes/health.d.ts +9 -0
  67. package/dist-server/server/routes/health.d.ts.map +1 -0
  68. package/dist-server/server/routes/health.js +284 -0
  69. package/dist-server/server/routes/health.js.map +1 -0
  70. package/dist-server/server/routes/knowledge.d.ts +3 -0
  71. package/dist-server/server/routes/knowledge.d.ts.map +1 -0
  72. package/dist-server/server/routes/knowledge.js +534 -0
  73. package/dist-server/server/routes/knowledge.js.map +1 -0
  74. package/dist-server/server/routes/llm.d.ts +3 -0
  75. package/dist-server/server/routes/llm.d.ts.map +1 -0
  76. package/dist-server/server/routes/llm.js +200 -0
  77. package/dist-server/server/routes/llm.js.map +1 -0
  78. package/dist-server/server/routes/mcp-oauth.d.ts +12 -0
  79. package/dist-server/server/routes/mcp-oauth.d.ts.map +1 -0
  80. package/dist-server/server/routes/mcp-oauth.js +137 -0
  81. package/dist-server/server/routes/mcp-oauth.js.map +1 -0
  82. package/dist-server/server/routes/mcp.d.ts +3 -0
  83. package/dist-server/server/routes/mcp.d.ts.map +1 -0
  84. package/dist-server/server/routes/mcp.js +177 -0
  85. package/dist-server/server/routes/mcp.js.map +1 -0
  86. package/dist-server/server/routes/pipeline.d.ts +45 -0
  87. package/dist-server/server/routes/pipeline.d.ts.map +1 -0
  88. package/dist-server/server/routes/pipeline.js +483 -0
  89. package/dist-server/server/routes/pipeline.js.map +1 -0
  90. package/dist-server/server/routes/providers.d.ts +3 -0
  91. package/dist-server/server/routes/providers.d.ts.map +1 -0
  92. package/dist-server/server/routes/providers.js +204 -0
  93. package/dist-server/server/routes/providers.js.map +1 -0
  94. package/dist-server/server/routes/qualification.d.ts +3 -0
  95. package/dist-server/server/routes/qualification.d.ts.map +1 -0
  96. package/dist-server/server/routes/qualification.js +105 -0
  97. package/dist-server/server/routes/qualification.js.map +1 -0
  98. package/dist-server/server/routes/repo-index.d.ts +4 -0
  99. package/dist-server/server/routes/repo-index.d.ts.map +1 -0
  100. package/dist-server/server/routes/repo-index.js +318 -0
  101. package/dist-server/server/routes/repo-index.js.map +1 -0
  102. package/dist-server/server/routes/runtime.d.ts +3 -0
  103. package/dist-server/server/routes/runtime.d.ts.map +1 -0
  104. package/dist-server/server/routes/runtime.js +122 -0
  105. package/dist-server/server/routes/runtime.js.map +1 -0
  106. package/dist-server/server/routes/skills-search.d.ts +3 -0
  107. package/dist-server/server/routes/skills-search.d.ts.map +1 -0
  108. package/dist-server/server/routes/skills-search.js +198 -0
  109. package/dist-server/server/routes/skills-search.js.map +1 -0
  110. package/dist-server/server/routes/worktrees.d.ts +3 -0
  111. package/dist-server/server/routes/worktrees.d.ts.map +1 -0
  112. package/dist-server/server/routes/worktrees.js +70 -0
  113. package/dist-server/server/routes/worktrees.js.map +1 -0
  114. package/dist-server/server/services/__tests__/embeddingService.test.d.ts +5 -0
  115. package/dist-server/server/services/__tests__/embeddingService.test.d.ts.map +1 -0
  116. package/dist-server/server/services/__tests__/embeddingService.test.js +233 -0
  117. package/dist-server/server/services/__tests__/embeddingService.test.js.map +1 -0
  118. package/dist-server/server/services/agentRunner.d.ts +46 -0
  119. package/dist-server/server/services/agentRunner.d.ts.map +1 -0
  120. package/dist-server/server/services/agentRunner.js +295 -0
  121. package/dist-server/server/services/agentRunner.js.map +1 -0
  122. package/dist-server/server/services/agentStore.d.ts +40 -0
  123. package/dist-server/server/services/agentStore.d.ts.map +1 -0
  124. package/dist-server/server/services/agentStore.js +62 -0
  125. package/dist-server/server/services/agentStore.js.map +1 -0
  126. package/dist-server/server/services/contentStore.d.ts +32 -0
  127. package/dist-server/server/services/contentStore.d.ts.map +1 -0
  128. package/dist-server/server/services/contentStore.js +68 -0
  129. package/dist-server/server/services/contentStore.js.map +1 -0
  130. package/dist-server/server/services/embeddingService.d.ts +53 -0
  131. package/dist-server/server/services/embeddingService.d.ts.map +1 -0
  132. package/dist-server/server/services/embeddingService.js +199 -0
  133. package/dist-server/server/services/embeddingService.js.map +1 -0
  134. package/dist-server/server/services/factExtractor.d.ts +14 -0
  135. package/dist-server/server/services/factExtractor.d.ts.map +1 -0
  136. package/dist-server/server/services/factExtractor.js +126 -0
  137. package/dist-server/server/services/factExtractor.js.map +1 -0
  138. package/dist-server/server/services/githubIndexer.d.ts +59 -0
  139. package/dist-server/server/services/githubIndexer.d.ts.map +1 -0
  140. package/dist-server/server/services/githubIndexer.js +183 -0
  141. package/dist-server/server/services/githubIndexer.js.map +1 -0
  142. package/dist-server/server/services/mcpOAuth.d.ts +32 -0
  143. package/dist-server/server/services/mcpOAuth.d.ts.map +1 -0
  144. package/dist-server/server/services/mcpOAuth.js +264 -0
  145. package/dist-server/server/services/mcpOAuth.js.map +1 -0
  146. package/dist-server/server/services/memoryScorer.d.ts +19 -0
  147. package/dist-server/server/services/memoryScorer.d.ts.map +1 -0
  148. package/dist-server/server/services/memoryScorer.js +147 -0
  149. package/dist-server/server/services/memoryScorer.js.map +1 -0
  150. package/dist-server/server/services/repoIndexer.d.ts +91 -0
  151. package/dist-server/server/services/repoIndexer.d.ts.map +1 -0
  152. package/dist-server/server/services/repoIndexer.js +512 -0
  153. package/dist-server/server/services/repoIndexer.js.map +1 -0
  154. package/dist-server/server/services/teamRunner.d.ts +39 -0
  155. package/dist-server/server/services/teamRunner.d.ts.map +1 -0
  156. package/dist-server/server/services/teamRunner.js +76 -0
  157. package/dist-server/server/services/teamRunner.js.map +1 -0
  158. package/dist-server/server/services/worktreeManager.d.ts +27 -0
  159. package/dist-server/server/services/worktreeManager.d.ts.map +1 -0
  160. package/dist-server/server/services/worktreeManager.js +107 -0
  161. package/dist-server/server/services/worktreeManager.js.map +1 -0
  162. package/dist-server/server/types.d.ts +30 -0
  163. package/dist-server/server/types.d.ts.map +1 -0
  164. package/dist-server/server/types.js +2 -0
  165. package/dist-server/server/types.js.map +1 -0
  166. package/dist-server/server/utils/pathSecurity.d.ts +34 -0
  167. package/dist-server/server/utils/pathSecurity.d.ts.map +1 -0
  168. package/dist-server/server/utils/pathSecurity.js +78 -0
  169. package/dist-server/server/utils/pathSecurity.js.map +1 -0
  170. package/dist-server/src/services/budgetAllocator.d.ts +37 -0
  171. package/dist-server/src/services/budgetAllocator.d.ts.map +1 -0
  172. package/dist-server/src/services/budgetAllocator.js +120 -0
  173. package/dist-server/src/services/budgetAllocator.js.map +1 -0
  174. package/dist-server/src/services/contradictionDetector.d.ts +18 -0
  175. package/dist-server/src/services/contradictionDetector.d.ts.map +1 -0
  176. package/dist-server/src/services/contradictionDetector.js +111 -0
  177. package/dist-server/src/services/contradictionDetector.js.map +1 -0
  178. package/dist-server/src/services/treeIndexer.d.ts +91 -0
  179. package/dist-server/src/services/treeIndexer.d.ts.map +1 -0
  180. package/dist-server/src/services/treeIndexer.js +289 -0
  181. package/dist-server/src/services/treeIndexer.js.map +1 -0
  182. package/dist-server/src/store/knowledgeBase.d.ts +130 -0
  183. package/dist-server/src/store/knowledgeBase.d.ts.map +1 -0
  184. package/dist-server/src/store/knowledgeBase.js +299 -0
  185. package/dist-server/src/store/knowledgeBase.js.map +1 -0
  186. package/dist-server/tsconfig.server.tsbuildinfo +1 -0
  187. package/package.json +92 -0
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Agent Store — Persistent agent state on disk
3
+ * Directory: ~/.modular-studio/agents/
4
+ * Each agent: {id}.json containing full state snapshot
5
+ */
6
+ export interface SavedAgentState {
7
+ id: string;
8
+ version: string;
9
+ savedAt: string;
10
+ agentMeta: {
11
+ name: string;
12
+ description: string;
13
+ icon: string;
14
+ category: string;
15
+ tags: string[];
16
+ avatar: string;
17
+ };
18
+ instructionState: Record<string, unknown>;
19
+ workflowSteps: Record<string, unknown>[];
20
+ channels: Record<string, unknown>[];
21
+ mcpServers: Record<string, unknown>[];
22
+ skills: Record<string, unknown>[];
23
+ connectors: Record<string, unknown>[];
24
+ agentConfig: Record<string, unknown>;
25
+ exportTarget: string;
26
+ outputFormat: string;
27
+ outputFormats: string[];
28
+ tokenBudget: number;
29
+ prompt: string;
30
+ }
31
+ export interface AgentSummary {
32
+ id: string;
33
+ agentMeta: SavedAgentState['agentMeta'];
34
+ savedAt: string;
35
+ }
36
+ export declare function saveAgent(id: string, state: SavedAgentState): void;
37
+ export declare function loadAgent(id: string): SavedAgentState | null;
38
+ export declare function listAgents(): AgentSummary[];
39
+ export declare function deleteAgent(id: string): boolean;
40
+ //# sourceMappingURL=agentStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agentStore.d.ts","sourceRoot":"","sources":["../../../server/services/agentStore.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAmBH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE;QACT,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,EAAE,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IACzC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IACpC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IACtC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAClC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IACtC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,eAAe,CAAC,WAAW,CAAC,CAAC;IACxC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,IAAI,CAKlE;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAQ5D;AAED,wBAAgB,UAAU,IAAI,YAAY,EAAE,CAiB3C;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAK/C"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Agent Store — Persistent agent state on disk
3
+ * Directory: ~/.modular-studio/agents/
4
+ * Each agent: {id}.json containing full state snapshot
5
+ */
6
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync, readdirSync } from 'node:fs';
7
+ import { join } from 'node:path';
8
+ import { homedir } from 'node:os';
9
+ const AGENTS_DIR = join(homedir(), '.modular-studio', 'agents');
10
+ function ensureDir() {
11
+ if (!existsSync(AGENTS_DIR)) {
12
+ mkdirSync(AGENTS_DIR, { recursive: true });
13
+ }
14
+ }
15
+ function agentPath(id) {
16
+ const safe = id.replace(/[^a-zA-Z0-9_-]/g, '_');
17
+ return join(AGENTS_DIR, `${safe}.json`);
18
+ }
19
+ export function saveAgent(id, state) {
20
+ ensureDir();
21
+ state.id = id;
22
+ state.savedAt = new Date().toISOString();
23
+ writeFileSync(agentPath(id), JSON.stringify(state, null, 2), 'utf-8');
24
+ }
25
+ export function loadAgent(id) {
26
+ const p = agentPath(id);
27
+ if (!existsSync(p))
28
+ return null;
29
+ try {
30
+ return JSON.parse(readFileSync(p, 'utf-8'));
31
+ }
32
+ catch {
33
+ return null;
34
+ }
35
+ }
36
+ export function listAgents() {
37
+ ensureDir();
38
+ const files = readdirSync(AGENTS_DIR).filter((f) => f.endsWith('.json'));
39
+ const summaries = [];
40
+ for (const file of files) {
41
+ try {
42
+ const raw = JSON.parse(readFileSync(join(AGENTS_DIR, file), 'utf-8'));
43
+ summaries.push({
44
+ id: raw.id ?? file.replace('.json', ''),
45
+ agentMeta: raw.agentMeta ?? { name: '', description: '', icon: 'brain', category: 'general', tags: [], avatar: 'bot' },
46
+ savedAt: raw.savedAt ?? '',
47
+ });
48
+ }
49
+ catch {
50
+ // skip corrupt files
51
+ }
52
+ }
53
+ return summaries;
54
+ }
55
+ export function deleteAgent(id) {
56
+ const p = agentPath(id);
57
+ if (!existsSync(p))
58
+ return false;
59
+ unlinkSync(p);
60
+ return true;
61
+ }
62
+ //# sourceMappingURL=agentStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agentStore.js","sourceRoot":"","sources":["../../../server/services/agentStore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ export interface ContentRepoMeta {
2
+ name: string;
3
+ stack: string[] | Record<string, string>;
4
+ totalFiles: number;
5
+ totalTokens: number;
6
+ baseUrl?: string;
7
+ features: {
8
+ name: string;
9
+ keyFiles: string[];
10
+ }[];
11
+ }
12
+ export interface StoredContent {
13
+ sourceId: string;
14
+ name: string;
15
+ overviewMarkdown: string;
16
+ knowledgeDocs: Record<string, string>;
17
+ repoMeta: ContentRepoMeta;
18
+ }
19
+ export interface ContentListItem {
20
+ sourceId: string;
21
+ name: string;
22
+ repoMeta: ContentRepoMeta;
23
+ }
24
+ export declare function saveContent(sourceId: string, data: Omit<StoredContent, 'sourceId'>): void;
25
+ export declare function loadContent(sourceId: string): StoredContent | null;
26
+ export declare function listContent(): ContentListItem[];
27
+ export declare function deleteContent(sourceId: string): boolean;
28
+ /** Derive a deterministic sourceId from a GitHub URL */
29
+ export declare function githubSourceId(url: string): string;
30
+ /** Derive a deterministic sourceId from a local path */
31
+ export declare function localSourceId(repoPath: string): string;
32
+ //# sourceMappingURL=contentStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contentStore.d.ts","sourceRoot":"","sources":["../../../server/services/contentStore.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC;CAClD;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,QAAQ,EAAE,eAAe,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,eAAe,CAAC;CAC3B;AAYD,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC,GAAG,IAAI,CAIzF;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAQlE;AAED,wBAAgB,WAAW,IAAI,eAAe,EAAE,CAa/C;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CASvD;AAED,wDAAwD;AACxD,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAIlD;AAED,wDAAwD;AACxD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGtD"}
@@ -0,0 +1,68 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync, readdirSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { homedir } from 'node:os';
4
+ const CONTENT_DIR = join(homedir(), '.modular-studio', 'content');
5
+ function ensureDir() {
6
+ if (!existsSync(CONTENT_DIR)) {
7
+ mkdirSync(CONTENT_DIR, { recursive: true });
8
+ }
9
+ }
10
+ function filePath(sourceId) {
11
+ return join(CONTENT_DIR, `${sourceId}.json`);
12
+ }
13
+ export function saveContent(sourceId, data) {
14
+ ensureDir();
15
+ const record = { sourceId, ...data };
16
+ writeFileSync(filePath(sourceId), JSON.stringify(record, null, 2), 'utf-8');
17
+ }
18
+ export function loadContent(sourceId) {
19
+ const fp = filePath(sourceId);
20
+ if (!existsSync(fp))
21
+ return null;
22
+ try {
23
+ return JSON.parse(readFileSync(fp, 'utf-8'));
24
+ }
25
+ catch {
26
+ return null;
27
+ }
28
+ }
29
+ export function listContent() {
30
+ ensureDir();
31
+ const files = readdirSync(CONTENT_DIR).filter(f => f.endsWith('.json'));
32
+ const items = [];
33
+ for (const f of files) {
34
+ try {
35
+ const raw = JSON.parse(readFileSync(join(CONTENT_DIR, f), 'utf-8'));
36
+ items.push({ sourceId: raw.sourceId, name: raw.name, repoMeta: raw.repoMeta });
37
+ }
38
+ catch {
39
+ // skip corrupt files
40
+ }
41
+ }
42
+ return items;
43
+ }
44
+ export function deleteContent(sourceId) {
45
+ const fp = filePath(sourceId);
46
+ if (!existsSync(fp))
47
+ return false;
48
+ try {
49
+ unlinkSync(fp);
50
+ return true;
51
+ }
52
+ catch {
53
+ return false;
54
+ }
55
+ }
56
+ /** Derive a deterministic sourceId from a GitHub URL */
57
+ export function githubSourceId(url) {
58
+ const match = url.match(/github\.com\/([^/]+)\/([^/.]+)/);
59
+ if (match)
60
+ return `github-${match[1]}-${match[2]}`.toLowerCase();
61
+ return `github-${url.replace(/[^a-zA-Z0-9-]/g, '-')}`.toLowerCase();
62
+ }
63
+ /** Derive a deterministic sourceId from a local path */
64
+ export function localSourceId(repoPath) {
65
+ const sanitized = repoPath.replace(/[\\/]/g, '-').replace(/[^a-zA-Z0-9-]/g, '').replace(/-+/g, '-').replace(/^-|-$/g, '');
66
+ return `local-${sanitized}`.toLowerCase();
67
+ }
68
+ //# sourceMappingURL=contentStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contentStore.js","sourceRoot":"","sources":["../../../server/services/contentStore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Server-side embedding service using HuggingFace Transformers.js
3
+ *
4
+ * This service provides semantic embeddings for text, with caching and
5
+ * similarity operations. Uses the Xenova/all-MiniLM-L6-v2 model which
6
+ * is well-tested with transformers.js in Node.js environments.
7
+ */
8
+ export interface EmbeddingService {
9
+ initialize(): Promise<void>;
10
+ embed(text: string): Promise<number[]>;
11
+ embedBatch(texts: string[]): Promise<number[][]>;
12
+ similarity(a: number[], b: number[]): number;
13
+ nearestK(query: number[], corpus: number[][], k: number): {
14
+ index: number;
15
+ score: number;
16
+ }[];
17
+ isReady(): boolean;
18
+ }
19
+ declare class EmbeddingServiceImpl implements EmbeddingService {
20
+ private model;
21
+ private ready;
22
+ private initPromise;
23
+ private cache;
24
+ private maxCacheSize;
25
+ initialize(): Promise<void>;
26
+ private _doInitialize;
27
+ isReady(): boolean;
28
+ private hashText;
29
+ private evictOldestCacheEntry;
30
+ private _embed;
31
+ embed(text: string): Promise<number[]>;
32
+ /** Maximum input length in characters (~256 tokens for all-MiniLM-L6-v2) */
33
+ private maxInputChars;
34
+ private truncateForModel;
35
+ embedBatch(texts: string[]): Promise<number[][]>;
36
+ similarity(a: number[], b: number[]): number;
37
+ nearestK(query: number[], corpus: number[][], k: number): {
38
+ index: number;
39
+ score: number;
40
+ }[];
41
+ getHealth(): {
42
+ ready: boolean;
43
+ model: string;
44
+ cacheSize: number;
45
+ maxCacheSize: number;
46
+ };
47
+ }
48
+ declare const embeddingService: EmbeddingServiceImpl;
49
+ /** Reset internal state — for tests only */
50
+ export declare function _resetForTesting(): void;
51
+ export { embeddingService };
52
+ export default embeddingService;
53
+ //# sourceMappingURL=embeddingService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embeddingService.d.ts","sourceRoot":"","sources":["../../../server/services/embeddingService.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,MAAM,WAAW,gBAAgB;IAC/B,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACvC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACjD,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAC7C,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,EAAE,CAAC;IAC3F,OAAO,IAAI,OAAO,CAAC;CACpB;AAOD,cAAM,oBAAqB,YAAW,gBAAgB;IACpD,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,WAAW,CAA8B;IAGjD,OAAO,CAAC,KAAK,CAAiC;IAC9C,OAAO,CAAC,YAAY,CAAS;IAEvB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;YASnB,aAAa;IAwB3B,OAAO,IAAI,OAAO;IAIlB,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,qBAAqB;YAgBf,MAAM;IA+Bd,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAQ5C,4EAA4E;IAC5E,OAAO,CAAC,aAAa,CAAQ;IAE7B,OAAO,CAAC,gBAAgB;IAIlB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;IA2DtD,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM;IA4B5C,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,EAAE;IAgB1F,SAAS;;;;;;CAQV;AAGD,QAAA,MAAM,gBAAgB,sBAA6B,CAAC;AAEpD,4CAA4C;AAC5C,wBAAgB,gBAAgB,IAAI,IAAI,CAKvC;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAC;AAC5B,eAAe,gBAAgB,CAAC"}
@@ -0,0 +1,199 @@
1
+ /**
2
+ * Server-side embedding service using HuggingFace Transformers.js
3
+ *
4
+ * This service provides semantic embeddings for text, with caching and
5
+ * similarity operations. Uses the Xenova/all-MiniLM-L6-v2 model which
6
+ * is well-tested with transformers.js in Node.js environments.
7
+ */
8
+ import { createHash } from 'node:crypto';
9
+ class EmbeddingServiceImpl {
10
+ model = null;
11
+ ready = false;
12
+ initPromise = null;
13
+ // LRU cache: key = hash(text), value = embedding vector
14
+ cache = new Map();
15
+ maxCacheSize = 10000;
16
+ async initialize() {
17
+ if (this.initPromise) {
18
+ return this.initPromise;
19
+ }
20
+ this.initPromise = this._doInitialize();
21
+ return this.initPromise;
22
+ }
23
+ async _doInitialize() {
24
+ try {
25
+ console.log('[Embedding] Loading model Xenova/all-MiniLM-L6-v2...');
26
+ const startTime = Date.now();
27
+ // Dynamic import to avoid top-level side effects and enable mocking in tests
28
+ const { pipeline, env } = await import('@huggingface/transformers');
29
+ env.allowLocalModels = false;
30
+ env.useBrowserCache = false;
31
+ this.model = await pipeline('feature-extraction', 'Xenova/all-MiniLM-L6-v2');
32
+ const loadTime = Date.now() - startTime;
33
+ console.log(`[Embedding] Model loaded in ${loadTime}ms`);
34
+ this.ready = true;
35
+ }
36
+ catch (error) {
37
+ console.error('[Embedding] Failed to load model:', error);
38
+ this.ready = false;
39
+ this.initPromise = null; // Allow retry
40
+ throw error;
41
+ }
42
+ }
43
+ isReady() {
44
+ return this.ready;
45
+ }
46
+ hashText(text) {
47
+ return createHash('sha256').update(text.trim()).digest('hex');
48
+ }
49
+ evictOldestCacheEntry() {
50
+ let oldestKey = null;
51
+ let oldestTime = Date.now();
52
+ for (const [key, entry] of this.cache) {
53
+ if (entry.lastAccessed < oldestTime) {
54
+ oldestTime = entry.lastAccessed;
55
+ oldestKey = key;
56
+ }
57
+ }
58
+ if (oldestKey) {
59
+ this.cache.delete(oldestKey);
60
+ }
61
+ }
62
+ async _embed(text) {
63
+ if (!this.ready || !this.model) {
64
+ await this.initialize();
65
+ }
66
+ const hash = this.hashText(text);
67
+ // Check cache first
68
+ const cached = this.cache.get(hash);
69
+ if (cached) {
70
+ cached.lastAccessed = Date.now();
71
+ return cached.embedding;
72
+ }
73
+ // Generate embedding
74
+ const result = await this.model(text, { pooling: 'mean', normalize: true });
75
+ const embedding = Array.from(result.data);
76
+ // Cache the result
77
+ if (this.cache.size >= this.maxCacheSize) {
78
+ this.evictOldestCacheEntry();
79
+ }
80
+ this.cache.set(hash, {
81
+ embedding,
82
+ lastAccessed: Date.now(),
83
+ });
84
+ return embedding;
85
+ }
86
+ async embed(text) {
87
+ if (!text || text.trim().length === 0) {
88
+ throw new Error('Text cannot be empty');
89
+ }
90
+ return this._embed(this.truncateForModel(text.trim()));
91
+ }
92
+ /** Maximum input length in characters (~256 tokens for all-MiniLM-L6-v2) */
93
+ maxInputChars = 1024; // ~256 tokens × 4 chars/token
94
+ truncateForModel(text) {
95
+ return text.length > this.maxInputChars ? text.slice(0, this.maxInputChars) : text;
96
+ }
97
+ async embedBatch(texts) {
98
+ if (!texts || texts.length === 0) {
99
+ return [];
100
+ }
101
+ if (!this.ready || !this.model) {
102
+ await this.initialize();
103
+ }
104
+ // Split into batches and use native model batching (pass array of strings)
105
+ const batchSize = 32;
106
+ const results = [];
107
+ for (let i = 0; i < texts.length; i += batchSize) {
108
+ const batch = texts.slice(i, i + batchSize).map(t => this.truncateForModel(t.trim()));
109
+ // Check cache for each text, collect uncached
110
+ const batchResults = batch.map(t => {
111
+ const hash = this.hashText(t);
112
+ const cached = this.cache.get(hash);
113
+ if (cached) {
114
+ cached.lastAccessed = Date.now();
115
+ return cached.embedding;
116
+ }
117
+ return null;
118
+ });
119
+ const uncachedIndices = batchResults
120
+ .map((r, idx) => r === null ? idx : -1)
121
+ .filter(idx => idx >= 0);
122
+ if (uncachedIndices.length > 0) {
123
+ // Native batch inference — one model call for all uncached texts
124
+ const uncachedTexts = uncachedIndices.map(idx => batch[idx]);
125
+ const batchOutput = await this.model(uncachedTexts, { pooling: 'mean', normalize: true });
126
+ // batchOutput.data is a flat Float32Array: [dim * N]
127
+ const dim = batchOutput.dims?.[1] ?? (batchOutput.data.length / uncachedTexts.length);
128
+ for (let j = 0; j < uncachedIndices.length; j++) {
129
+ const embedding = Array.from(batchOutput.data.slice(j * dim, (j + 1) * dim));
130
+ const idx = uncachedIndices[j];
131
+ batchResults[idx] = embedding;
132
+ // Cache the result
133
+ const hash = this.hashText(batch[idx]);
134
+ if (this.cache.size >= this.maxCacheSize) {
135
+ this.evictOldestCacheEntry();
136
+ }
137
+ this.cache.set(hash, { embedding, lastAccessed: Date.now() });
138
+ }
139
+ }
140
+ results.push(...batchResults);
141
+ }
142
+ return results;
143
+ }
144
+ similarity(a, b) {
145
+ if (a.length !== b.length) {
146
+ throw new Error('Vectors must have the same length');
147
+ }
148
+ if (a.length === 0) {
149
+ return 0;
150
+ }
151
+ // Cosine similarity: dot product of normalized vectors
152
+ let dotProduct = 0;
153
+ let normA = 0;
154
+ let normB = 0;
155
+ for (let i = 0; i < a.length; i++) {
156
+ dotProduct += a[i] * b[i];
157
+ normA += a[i] * a[i];
158
+ normB += b[i] * b[i];
159
+ }
160
+ const magnitude = Math.sqrt(normA) * Math.sqrt(normB);
161
+ if (magnitude === 0) {
162
+ return 0;
163
+ }
164
+ return dotProduct / magnitude;
165
+ }
166
+ nearestK(query, corpus, k) {
167
+ if (corpus.length === 0) {
168
+ return [];
169
+ }
170
+ const scores = corpus.map((embedding, index) => ({
171
+ index,
172
+ score: this.similarity(query, embedding),
173
+ }));
174
+ // Sort by score descending and take top k
175
+ scores.sort((a, b) => b.score - a.score);
176
+ return scores.slice(0, k);
177
+ }
178
+ // Health check information
179
+ getHealth() {
180
+ return {
181
+ ready: this.ready,
182
+ model: 'Xenova/all-MiniLM-L6-v2',
183
+ cacheSize: this.cache.size,
184
+ maxCacheSize: this.maxCacheSize,
185
+ };
186
+ }
187
+ }
188
+ // Singleton instance
189
+ const embeddingService = new EmbeddingServiceImpl();
190
+ /** Reset internal state — for tests only */
191
+ export function _resetForTesting() {
192
+ embeddingService.model = null;
193
+ embeddingService.ready = false;
194
+ embeddingService.initPromise = null;
195
+ embeddingService.cache.clear();
196
+ }
197
+ export { embeddingService };
198
+ export default embeddingService;
199
+ //# sourceMappingURL=embeddingService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embeddingService.js","sourceRoot":"","sources":["../../../server/services/embeddingService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export interface ExtractedFact {
2
+ key: string;
3
+ value: string;
4
+ epistemicType: 'observation' | 'inference' | 'decision' | 'hypothesis' | 'contract';
5
+ confidence: number;
6
+ source: string;
7
+ importance?: number;
8
+ created_at?: number;
9
+ accessed_at?: number;
10
+ access_count?: number;
11
+ }
12
+ export declare function extractFacts(agentOutput: string, agentId: string): ExtractedFact[];
13
+ export declare function extractFactsWithLlm(agentOutput: string, agentId: string, providerId: string, model: string): Promise<ExtractedFact[]>;
14
+ //# sourceMappingURL=factExtractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factExtractor.d.ts","sourceRoot":"","sources":["../../../server/services/factExtractor.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,aAAa,GAAG,WAAW,GAAG,UAAU,GAAG,YAAY,GAAG,UAAU,CAAC;IACpF,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAgCD,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa,EAAE,CAgClF;AAED,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,aAAa,EAAE,CAAC,CA+E1B"}
@@ -0,0 +1,126 @@
1
+ import { readConfig } from '../config.js';
2
+ const PATTERNS = [
3
+ // Decisions
4
+ { pattern: /I (?:decided|chose|picked|selected|went with|will use|am going to use) (?:to )?(.+?)(?:\.|$)/gim, epistemicType: 'decision', confidence: 0.9, keyPrefix: 'decision' },
5
+ { pattern: /(?:Let's|We should|I'll|I will) (?:use|go with|implement|create|build) (.+?)(?:\.|$)/gim, epistemicType: 'decision', confidence: 0.8, keyPrefix: 'decision' },
6
+ // Observations
7
+ { pattern: /The (?:file|directory|folder|API|endpoint|function|module|class) (.+?) (?:exports?|contains?|has|returns?|provides?) (.+?)(?:\.|$)/gim, epistemicType: 'observation', confidence: 0.85, keyPrefix: 'observation' },
8
+ { pattern: /I (?:found|noticed|observed|see|saw) (?:that )?(.+?)(?:\.|$)/gim, epistemicType: 'observation', confidence: 0.8, keyPrefix: 'observation' },
9
+ { pattern: /I (?:created|wrote|added|updated|modified|deleted|removed) (?:the )?(?:file )?(.+?)(?:\.|$)/gim, epistemicType: 'observation', confidence: 0.95, keyPrefix: 'file_action' },
10
+ // Inferences
11
+ { pattern: /(?:This means|Therefore|So|Thus|Hence|It follows that|This implies) (.+?)(?:\.|$)/gim, epistemicType: 'inference', confidence: 0.7, keyPrefix: 'inference' },
12
+ { pattern: /(?:It (?:seems|appears|looks) (?:like|that)) (.+?)(?:\.|$)/gim, epistemicType: 'inference', confidence: 0.5, keyPrefix: 'inference' },
13
+ // Hypotheses
14
+ { pattern: /(?:I think|I believe|I suspect|Maybe|Perhaps|Possibly|My guess is) (.+?)(?:\.|$)/gim, epistemicType: 'hypothesis', confidence: 0.4, keyPrefix: 'hypothesis' },
15
+ // Contracts — interfaces, types, schemas
16
+ { pattern: /(?:^|\n)((?:export )?interface \w+[\s\S]*?\n\})/gm, epistemicType: 'contract', confidence: 0.95, keyPrefix: 'contract' },
17
+ { pattern: /(?:^|\n)((?:export )?type \w+ = [\s\S]*?(?:;|\n\}))/gm, epistemicType: 'contract', confidence: 0.95, keyPrefix: 'contract' },
18
+ ];
19
+ function makeKey(prefix, index, value) {
20
+ const slug = value.slice(0, 40).replace(/[^a-zA-Z0-9]/g, '_').replace(/_+/g, '_').replace(/_$/, '').toLowerCase();
21
+ return `${prefix}_${index}_${slug}`;
22
+ }
23
+ export function extractFacts(agentOutput, agentId) {
24
+ const facts = [];
25
+ const seen = new Set();
26
+ let globalIdx = 0;
27
+ for (const rule of PATTERNS) {
28
+ // Reset regex state
29
+ rule.pattern.lastIndex = 0;
30
+ let match;
31
+ while ((match = rule.pattern.exec(agentOutput)) !== null) {
32
+ const value = (match[2] ?? match[1] ?? match[0]).trim();
33
+ if (!value || value.length < 3)
34
+ continue;
35
+ const dedupKey = `${rule.epistemicType}:${value.slice(0, 80)}`;
36
+ if (seen.has(dedupKey))
37
+ continue;
38
+ seen.add(dedupKey);
39
+ const now = Date.now();
40
+ facts.push({
41
+ key: makeKey(rule.keyPrefix, globalIdx++, value),
42
+ value,
43
+ epistemicType: rule.epistemicType,
44
+ confidence: rule.confidence,
45
+ source: agentId,
46
+ importance: rule.confidence * 0.8,
47
+ created_at: now,
48
+ accessed_at: now,
49
+ access_count: 0,
50
+ });
51
+ }
52
+ }
53
+ return facts;
54
+ }
55
+ export async function extractFactsWithLlm(agentOutput, agentId, providerId, model) {
56
+ const config = readConfig();
57
+ const provider = config.providers.find((p) => p.id === providerId);
58
+ if (!provider)
59
+ throw new Error(`Provider "${providerId}" not found`);
60
+ if (!provider.baseUrl)
61
+ throw new Error(`Provider "${providerId}" has no baseUrl`);
62
+ const extractionPrompt = `Extract structured facts from the following agent output. Return a JSON array of objects with these fields:
63
+ - key: short snake_case identifier
64
+ - value: the fact content
65
+ - epistemicType: one of "observation", "inference", "decision", "hypothesis", "contract"
66
+ - confidence: number 0-1
67
+
68
+ Only return the JSON array, no other text.
69
+
70
+ Agent output:
71
+ ${agentOutput}`;
72
+ const messages = [{ role: 'user', content: extractionPrompt }];
73
+ let url;
74
+ let headers;
75
+ let body;
76
+ if (provider.type === 'anthropic') {
77
+ url = `${provider.baseUrl}/messages`;
78
+ headers = {
79
+ 'x-api-key': provider.apiKey,
80
+ 'anthropic-version': '2023-06-01',
81
+ 'content-type': 'application/json',
82
+ };
83
+ body = JSON.stringify({ model, max_tokens: 4096, messages });
84
+ }
85
+ else {
86
+ url = `${provider.baseUrl}/chat/completions`;
87
+ headers = {
88
+ 'Authorization': `Bearer ${provider.apiKey}`,
89
+ 'Content-Type': 'application/json',
90
+ };
91
+ body = JSON.stringify({ model, messages });
92
+ }
93
+ const response = await fetch(url, { method: 'POST', headers, body });
94
+ if (!response.ok) {
95
+ const errText = await response.text();
96
+ throw new Error(`LLM extraction failed (${response.status}): ${errText}`);
97
+ }
98
+ const data = await response.json();
99
+ let text;
100
+ if (provider.type === 'anthropic') {
101
+ const content = data.content;
102
+ text = content?.find((c) => c.type === 'text')?.text ?? '';
103
+ }
104
+ else {
105
+ const choices = data.choices;
106
+ text = choices?.[0]?.message?.content ?? '';
107
+ }
108
+ // Parse JSON from response
109
+ const jsonMatch = text.match(/\[[\s\S]*\]/);
110
+ if (!jsonMatch)
111
+ return [];
112
+ const parsed = JSON.parse(jsonMatch[0]);
113
+ const now = Date.now();
114
+ return parsed.map((f) => ({
115
+ key: f.key,
116
+ value: f.value,
117
+ epistemicType: f.epistemicType,
118
+ confidence: f.confidence,
119
+ source: agentId,
120
+ importance: f.confidence * 0.8,
121
+ created_at: now,
122
+ accessed_at: now,
123
+ access_count: 0,
124
+ }));
125
+ }
126
+ //# sourceMappingURL=factExtractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factExtractor.js","sourceRoot":"","sources":["../../../server/services/factExtractor.ts"],"names":[],"mappings":"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"}