studiograph 1.1.2 → 1.2.0-beta.1

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 (349) hide show
  1. package/LICENSE +191 -0
  2. package/README.md +301 -10
  3. package/dist/agent/orchestrator.d.ts +17 -9
  4. package/dist/agent/orchestrator.js +142 -97
  5. package/dist/agent/orchestrator.js.map +1 -1
  6. package/dist/agent/prompts/system.md +186 -0
  7. package/dist/agent/skill-loader.d.ts +48 -0
  8. package/dist/agent/skill-loader.js +166 -0
  9. package/dist/agent/skill-loader.js.map +1 -0
  10. package/dist/agent/skills/enrich-entities.md +136 -0
  11. package/dist/agent/skills/entity-schema.md +502 -0
  12. package/dist/agent/skills/gather-context.md +46 -0
  13. package/dist/agent/skills/obsidian-source-setup.md +246 -0
  14. package/dist/agent/skills/skill-loader.d.ts +48 -0
  15. package/dist/agent/skills/skill-loader.js +166 -0
  16. package/dist/agent/skills/skill-loader.js.map +1 -0
  17. package/dist/agent/skills/sync-configuration.md +144 -0
  18. package/dist/agent/skills/sync-setup.md +68 -0
  19. package/dist/agent/tools/connector-tools.d.ts +37 -0
  20. package/dist/agent/tools/connector-tools.js +132 -0
  21. package/dist/agent/tools/connector-tools.js.map +1 -0
  22. package/dist/agent/tools/fs-tools.d.ts +39 -0
  23. package/dist/agent/tools/fs-tools.js +106 -0
  24. package/dist/agent/tools/fs-tools.js.map +1 -0
  25. package/dist/agent/tools/graph-tools.d.ts +30 -2
  26. package/dist/agent/tools/graph-tools.js +154 -37
  27. package/dist/agent/tools/graph-tools.js.map +1 -1
  28. package/dist/agent/tools/load-skill.d.ts +42 -0
  29. package/dist/agent/tools/load-skill.js +45 -0
  30. package/dist/agent/tools/load-skill.js.map +1 -0
  31. package/dist/agent/tools/sync-tools.d.ts +25 -0
  32. package/dist/agent/tools/sync-tools.js +691 -0
  33. package/dist/agent/tools/sync-tools.js.map +1 -0
  34. package/dist/agent/tools/tool-loader.d.ts +25 -0
  35. package/dist/agent/tools/tool-loader.js +73 -0
  36. package/dist/agent/tools/tool-loader.js.map +1 -0
  37. package/dist/auth/github.d.ts +11 -8
  38. package/dist/auth/github.js +56 -75
  39. package/dist/auth/github.js.map +1 -1
  40. package/dist/cli/colors.d.ts +54 -0
  41. package/dist/cli/colors.js +133 -0
  42. package/dist/cli/colors.js.map +1 -0
  43. package/dist/cli/commands/app.d.ts +7 -0
  44. package/dist/cli/commands/app.js +167 -0
  45. package/dist/cli/commands/app.js.map +1 -0
  46. package/dist/cli/commands/auth.d.ts +1 -1
  47. package/dist/cli/commands/auth.js +26 -10
  48. package/dist/cli/commands/auth.js.map +1 -1
  49. package/dist/cli/commands/clone.d.ts +9 -0
  50. package/dist/cli/commands/clone.js +167 -0
  51. package/dist/cli/commands/clone.js.map +1 -0
  52. package/dist/cli/commands/commit.d.ts +8 -0
  53. package/dist/cli/commands/commit.js +43 -0
  54. package/dist/cli/commands/commit.js.map +1 -0
  55. package/dist/cli/commands/config.d.ts +13 -0
  56. package/dist/cli/commands/config.js +276 -0
  57. package/dist/cli/commands/config.js.map +1 -0
  58. package/dist/cli/commands/connector.d.ts +33 -0
  59. package/dist/cli/commands/connector.js +178 -0
  60. package/dist/cli/commands/connector.js.map +1 -0
  61. package/dist/cli/commands/deploy.d.ts +11 -0
  62. package/dist/cli/commands/deploy.js +153 -0
  63. package/dist/cli/commands/deploy.js.map +1 -0
  64. package/dist/cli/commands/enrich.d.ts +11 -0
  65. package/dist/cli/commands/enrich.js +135 -0
  66. package/dist/cli/commands/enrich.js.map +1 -0
  67. package/dist/cli/commands/graphrag.d.ts +12 -0
  68. package/dist/cli/commands/graphrag.js +122 -0
  69. package/dist/cli/commands/graphrag.js.map +1 -0
  70. package/dist/cli/commands/index.d.ts +15 -0
  71. package/dist/cli/commands/index.js +117 -0
  72. package/dist/cli/commands/index.js.map +1 -0
  73. package/dist/cli/commands/init.js +110 -210
  74. package/dist/cli/commands/init.js.map +1 -1
  75. package/dist/cli/commands/join.js +89 -24
  76. package/dist/cli/commands/join.js.map +1 -1
  77. package/dist/cli/commands/lint.d.ts +8 -0
  78. package/dist/cli/commands/lint.js +70 -0
  79. package/dist/cli/commands/lint.js.map +1 -0
  80. package/dist/cli/commands/mcp.d.ts +27 -0
  81. package/dist/cli/commands/mcp.js +56 -0
  82. package/dist/cli/commands/mcp.js.map +1 -0
  83. package/dist/cli/commands/orphans.d.ts +8 -0
  84. package/dist/cli/commands/orphans.js +125 -0
  85. package/dist/cli/commands/orphans.js.map +1 -0
  86. package/dist/cli/commands/provision.d.ts +8 -0
  87. package/dist/cli/commands/provision.js +116 -0
  88. package/dist/cli/commands/provision.js.map +1 -0
  89. package/dist/cli/commands/r2.d.ts +2 -0
  90. package/dist/cli/commands/r2.js +87 -6
  91. package/dist/cli/commands/r2.js.map +1 -1
  92. package/dist/cli/commands/reset.d.ts +12 -0
  93. package/dist/cli/commands/reset.js +137 -0
  94. package/dist/cli/commands/reset.js.map +1 -0
  95. package/dist/cli/commands/review.d.ts +19 -0
  96. package/dist/cli/commands/review.js +128 -0
  97. package/dist/cli/commands/review.js.map +1 -0
  98. package/dist/cli/commands/serve.js +47 -2
  99. package/dist/cli/commands/serve.js.map +1 -1
  100. package/dist/cli/commands/source.d.ts +16 -0
  101. package/dist/cli/commands/source.js +159 -0
  102. package/dist/cli/commands/source.js.map +1 -0
  103. package/dist/cli/commands/start.js +472 -103
  104. package/dist/cli/commands/start.js.map +1 -1
  105. package/dist/cli/commands/sync-entities.d.ts +13 -0
  106. package/dist/cli/commands/sync-entities.js +242 -0
  107. package/dist/cli/commands/sync-entities.js.map +1 -0
  108. package/dist/cli/commands/sync.js +40 -9
  109. package/dist/cli/commands/sync.js.map +1 -1
  110. package/dist/cli/commands/update.d.ts +8 -0
  111. package/dist/cli/commands/update.js +155 -0
  112. package/dist/cli/commands/update.js.map +1 -0
  113. package/dist/cli/index.js +114 -3
  114. package/dist/cli/index.js.map +1 -1
  115. package/dist/cli/scaffolding.d.ts +10 -0
  116. package/dist/cli/scaffolding.js +302 -0
  117. package/dist/cli/scaffolding.js.map +1 -0
  118. package/dist/cli/setup-wizard.d.ts +30 -0
  119. package/dist/cli/setup-wizard.js +244 -0
  120. package/dist/cli/setup-wizard.js.map +1 -0
  121. package/dist/cli/sync-review-interactive.d.ts +31 -0
  122. package/dist/cli/sync-review-interactive.js +393 -0
  123. package/dist/cli/sync-review-interactive.js.map +1 -0
  124. package/dist/cli/theme.d.ts +31 -0
  125. package/dist/cli/theme.js +116 -0
  126. package/dist/cli/theme.js.map +1 -0
  127. package/dist/core/graph.d.ts +16 -9
  128. package/dist/core/graph.js +263 -145
  129. package/dist/core/graph.js.map +1 -1
  130. package/dist/core/migration-runner.d.ts +42 -0
  131. package/dist/core/migration-runner.js +232 -0
  132. package/dist/core/migration-runner.js.map +1 -0
  133. package/dist/core/migration-types.d.ts +101 -0
  134. package/dist/core/migration-types.js +21 -0
  135. package/dist/core/migration-types.js.map +1 -0
  136. package/dist/core/migrations/20260219-formalize-memory-location.d.ts +2 -0
  137. package/dist/core/migrations/20260219-formalize-memory-location.js +35 -0
  138. package/dist/core/migrations/20260219-formalize-memory-location.js.map +1 -0
  139. package/dist/core/migrations/20260220-add-workspace-metadata.d.ts +12 -0
  140. package/dist/core/migrations/20260220-add-workspace-metadata.js +65 -0
  141. package/dist/core/migrations/20260220-add-workspace-metadata.js.map +1 -0
  142. package/dist/core/migrations/20260220-add-workspace-readme.d.ts +11 -0
  143. package/dist/core/migrations/20260220-add-workspace-readme.js +82 -0
  144. package/dist/core/migrations/20260220-add-workspace-readme.js.map +1 -0
  145. package/dist/core/migrations/20260220-migrate-yaml-to-json.d.ts +9 -0
  146. package/dist/core/migrations/20260220-migrate-yaml-to-json.js +64 -0
  147. package/dist/core/migrations/20260220-migrate-yaml-to-json.js.map +1 -0
  148. package/dist/core/migrations/index.d.ts +11 -0
  149. package/dist/core/migrations/index.js +23 -0
  150. package/dist/core/migrations/index.js.map +1 -0
  151. package/dist/core/schema-registry.d.ts +36 -0
  152. package/dist/core/schema-registry.js +161 -0
  153. package/dist/core/schema-registry.js.map +1 -0
  154. package/dist/core/types.d.ts +242 -3
  155. package/dist/core/types.js +21 -2
  156. package/dist/core/types.js.map +1 -1
  157. package/dist/core/user-config.d.ts +16 -0
  158. package/dist/core/user-config.js +8 -0
  159. package/dist/core/user-config.js.map +1 -1
  160. package/dist/core/validation.d.ts +973 -32
  161. package/dist/core/validation.js +163 -4
  162. package/dist/core/validation.js.map +1 -1
  163. package/dist/core/workspace-manager.d.ts +26 -2
  164. package/dist/core/workspace-manager.js +113 -15
  165. package/dist/core/workspace-manager.js.map +1 -1
  166. package/dist/core/workspace.d.ts +20 -11
  167. package/dist/core/workspace.js +123 -34
  168. package/dist/core/workspace.js.map +1 -1
  169. package/dist/mcp/connector-manager.d.ts +65 -0
  170. package/dist/mcp/connector-manager.js +223 -0
  171. package/dist/mcp/connector-manager.js.map +1 -0
  172. package/dist/mcp/connectors/asana.d.ts +2 -0
  173. package/dist/mcp/connectors/asana.js +20 -0
  174. package/dist/mcp/connectors/asana.js.map +1 -0
  175. package/dist/mcp/connectors/definitions.d.ts +45 -0
  176. package/dist/mcp/connectors/definitions.js +32 -0
  177. package/dist/mcp/connectors/definitions.js.map +1 -0
  178. package/dist/mcp/connectors/figma.d.ts +5 -0
  179. package/dist/mcp/connectors/figma.js +21 -0
  180. package/dist/mcp/connectors/figma.js.map +1 -0
  181. package/dist/mcp/connectors/gdrive.d.ts +2 -0
  182. package/dist/mcp/connectors/gdrive.js +20 -0
  183. package/dist/mcp/connectors/gdrive.js.map +1 -0
  184. package/dist/mcp/connectors/granola.d.ts +2 -0
  185. package/dist/mcp/connectors/granola.js +12 -0
  186. package/dist/mcp/connectors/granola.js.map +1 -0
  187. package/dist/mcp/connectors/linear.d.ts +2 -0
  188. package/dist/mcp/connectors/linear.js +19 -0
  189. package/dist/mcp/connectors/linear.js.map +1 -0
  190. package/dist/mcp/connectors/obsidian.d.ts +2 -0
  191. package/dist/mcp/connectors/obsidian.js +19 -0
  192. package/dist/mcp/connectors/obsidian.js.map +1 -0
  193. package/dist/mcp/connectors/pipedrive.d.ts +2 -0
  194. package/dist/mcp/connectors/pipedrive.js +20 -0
  195. package/dist/mcp/connectors/pipedrive.js.map +1 -0
  196. package/dist/mcp/connectors/slack.d.ts +2 -0
  197. package/dist/mcp/connectors/slack.js +21 -0
  198. package/dist/mcp/connectors/slack.js.map +1 -0
  199. package/dist/mcp/oauth-provider.d.ts +41 -0
  200. package/dist/mcp/oauth-provider.js +160 -0
  201. package/dist/mcp/oauth-provider.js.map +1 -0
  202. package/dist/mcp/server.d.ts +11 -0
  203. package/dist/mcp/server.js +28 -0
  204. package/dist/mcp/server.js.map +1 -0
  205. package/dist/mcp/tools.d.ts +14 -0
  206. package/dist/mcp/tools.js +172 -0
  207. package/dist/mcp/tools.js.map +1 -0
  208. package/dist/server/index.js +17 -4
  209. package/dist/server/index.js.map +1 -1
  210. package/dist/server/plugin-loader.d.ts +15 -0
  211. package/dist/server/plugin-loader.js +68 -2
  212. package/dist/server/plugin-loader.js.map +1 -1
  213. package/dist/server/routes/graph-api.js +1 -1
  214. package/dist/server/routes/graph-api.js.map +1 -1
  215. package/dist/server/routes/webhook.js +33 -0
  216. package/dist/server/routes/webhook.js.map +1 -1
  217. package/dist/services/github-provisioner.d.ts +9 -3
  218. package/dist/services/github-provisioner.js +46 -8
  219. package/dist/services/github-provisioner.js.map +1 -1
  220. package/dist/services/lint-service.d.ts +27 -0
  221. package/dist/services/lint-service.js +83 -0
  222. package/dist/services/lint-service.js.map +1 -0
  223. package/dist/services/markdown.d.ts +9 -0
  224. package/dist/services/markdown.js +26 -5
  225. package/dist/services/markdown.js.map +1 -1
  226. package/dist/services/memory-service.d.ts +1 -2
  227. package/dist/services/memory-service.js +5 -4
  228. package/dist/services/memory-service.js.map +1 -1
  229. package/dist/services/orphan-service.d.ts +31 -0
  230. package/dist/services/orphan-service.js +100 -0
  231. package/dist/services/orphan-service.js.map +1 -0
  232. package/dist/services/sync/commit.d.ts +58 -0
  233. package/dist/services/sync/commit.js +350 -0
  234. package/dist/services/sync/commit.js.map +1 -0
  235. package/dist/services/sync/context-index.d.ts +69 -0
  236. package/dist/services/sync/context-index.js +280 -0
  237. package/dist/services/sync/context-index.js.map +1 -0
  238. package/dist/services/sync/derive.d.ts +34 -0
  239. package/dist/services/sync/derive.js +164 -0
  240. package/dist/services/sync/derive.js.map +1 -0
  241. package/dist/services/sync/enrichment-state.d.ts +31 -0
  242. package/dist/services/sync/enrichment-state.js +63 -0
  243. package/dist/services/sync/enrichment-state.js.map +1 -0
  244. package/dist/services/sync/enrichment.d.ts +25 -0
  245. package/dist/services/sync/enrichment.js +121 -0
  246. package/dist/services/sync/enrichment.js.map +1 -0
  247. package/dist/services/sync/frontmatter-extractor.d.ts +40 -0
  248. package/dist/services/sync/frontmatter-extractor.js +273 -0
  249. package/dist/services/sync/frontmatter-extractor.js.map +1 -0
  250. package/dist/services/sync/graph-match-state.d.ts +33 -0
  251. package/dist/services/sync/graph-match-state.js +61 -0
  252. package/dist/services/sync/graph-match-state.js.map +1 -0
  253. package/dist/services/sync/graph-match.d.ts +53 -0
  254. package/dist/services/sync/graph-match.js +316 -0
  255. package/dist/services/sync/graph-match.js.map +1 -0
  256. package/dist/services/sync/graphrag-client.d.ts +43 -0
  257. package/dist/services/sync/graphrag-client.js +94 -0
  258. package/dist/services/sync/graphrag-client.js.map +1 -0
  259. package/dist/services/sync/graphrag-config.d.ts +16 -0
  260. package/dist/services/sync/graphrag-config.js +39 -0
  261. package/dist/services/sync/graphrag-config.js.map +1 -0
  262. package/dist/services/sync/graphrag-context.d.ts +14 -0
  263. package/dist/services/sync/graphrag-context.js +109 -0
  264. package/dist/services/sync/graphrag-context.js.map +1 -0
  265. package/dist/services/sync/graphrag-indexer.d.ts +30 -0
  266. package/dist/services/sync/graphrag-indexer.js +358 -0
  267. package/dist/services/sync/graphrag-indexer.js.map +1 -0
  268. package/dist/services/sync/llm.d.ts +32 -0
  269. package/dist/services/sync/llm.js +115 -0
  270. package/dist/services/sync/llm.js.map +1 -0
  271. package/dist/services/sync/mcp-client.d.ts +59 -0
  272. package/dist/services/sync/mcp-client.js +285 -0
  273. package/dist/services/sync/mcp-client.js.map +1 -0
  274. package/dist/services/sync/model-factory.d.ts +10 -0
  275. package/dist/services/sync/model-factory.js +24 -0
  276. package/dist/services/sync/model-factory.js.map +1 -0
  277. package/dist/services/sync/name-quality.d.ts +31 -0
  278. package/dist/services/sync/name-quality.js +60 -0
  279. package/dist/services/sync/name-quality.js.map +1 -0
  280. package/dist/services/sync/output-schemas.d.ts +92 -0
  281. package/dist/services/sync/output-schemas.js +43 -0
  282. package/dist/services/sync/output-schemas.js.map +1 -0
  283. package/dist/services/sync/prompts.d.ts +19 -0
  284. package/dist/services/sync/prompts.js +128 -0
  285. package/dist/services/sync/prompts.js.map +1 -0
  286. package/dist/services/sync/reconciler.d.ts +48 -0
  287. package/dist/services/sync/reconciler.js +295 -0
  288. package/dist/services/sync/reconciler.js.map +1 -0
  289. package/dist/services/sync/source-config.d.ts +45 -0
  290. package/dist/services/sync/source-config.js +208 -0
  291. package/dist/services/sync/source-config.js.map +1 -0
  292. package/dist/services/sync/source-definitions/asana.d.ts +15 -0
  293. package/dist/services/sync/source-definitions/asana.js +48 -0
  294. package/dist/services/sync/source-definitions/asana.js.map +1 -0
  295. package/dist/services/sync/source-definitions/definitions.d.ts +21 -0
  296. package/dist/services/sync/source-definitions/definitions.js +26 -0
  297. package/dist/services/sync/source-definitions/definitions.js.map +1 -0
  298. package/dist/services/sync/source-definitions/gdrive.d.ts +16 -0
  299. package/dist/services/sync/source-definitions/gdrive.js +68 -0
  300. package/dist/services/sync/source-definitions/gdrive.js.map +1 -0
  301. package/dist/services/sync/source-definitions/granola.d.ts +2 -0
  302. package/dist/services/sync/source-definitions/granola.js +28 -0
  303. package/dist/services/sync/source-definitions/granola.js.map +1 -0
  304. package/dist/services/sync/source-definitions/linear.d.ts +2 -0
  305. package/dist/services/sync/source-definitions/linear.js +60 -0
  306. package/dist/services/sync/source-definitions/linear.js.map +1 -0
  307. package/dist/services/sync/source-definitions/obsidian.d.ts +2 -0
  308. package/dist/services/sync/source-definitions/obsidian.js +55 -0
  309. package/dist/services/sync/source-definitions/obsidian.js.map +1 -0
  310. package/dist/services/sync/source-definitions/pipedrive.d.ts +2 -0
  311. package/dist/services/sync/source-definitions/pipedrive.js +52 -0
  312. package/dist/services/sync/source-definitions/pipedrive.js.map +1 -0
  313. package/dist/services/sync/staging.d.ts +53 -0
  314. package/dist/services/sync/staging.js +131 -0
  315. package/dist/services/sync/staging.js.map +1 -0
  316. package/dist/services/sync/structured-extractor.d.ts +49 -0
  317. package/dist/services/sync/structured-extractor.js +344 -0
  318. package/dist/services/sync/structured-extractor.js.map +1 -0
  319. package/dist/services/sync/sync-runner.d.ts +32 -0
  320. package/dist/services/sync/sync-runner.js +195 -0
  321. package/dist/services/sync/sync-runner.js.map +1 -0
  322. package/dist/services/sync/sync-state.d.ts +43 -0
  323. package/dist/services/sync/sync-state.js +154 -0
  324. package/dist/services/sync/sync-state.js.map +1 -0
  325. package/dist/services/sync/types.d.ts +203 -0
  326. package/dist/services/sync/types.js +8 -0
  327. package/dist/services/sync/types.js.map +1 -0
  328. package/dist/services/sync/unstructured-extractor.d.ts +29 -0
  329. package/dist/services/sync/unstructured-extractor.js +197 -0
  330. package/dist/services/sync/unstructured-extractor.js.map +1 -0
  331. package/dist/services/vector-service.d.ts +88 -0
  332. package/dist/services/vector-service.js +322 -0
  333. package/dist/services/vector-service.js.map +1 -0
  334. package/dist/utils/git.d.ts +26 -4
  335. package/dist/utils/git.js +55 -7
  336. package/dist/utils/git.js.map +1 -1
  337. package/dist/utils/merge-resolver.d.ts +34 -0
  338. package/dist/utils/merge-resolver.js +201 -0
  339. package/dist/utils/merge-resolver.js.map +1 -0
  340. package/dist/utils/preflight.d.ts +2 -1
  341. package/dist/utils/preflight.js +8 -1
  342. package/dist/utils/preflight.js.map +1 -1
  343. package/dist/utils/version-checker.d.ts +23 -0
  344. package/dist/utils/version-checker.js +116 -0
  345. package/dist/utils/version-checker.js.map +1 -0
  346. package/dist/utils/workspace-config.d.ts +8 -0
  347. package/dist/utils/workspace-config.js +22 -0
  348. package/dist/utils/workspace-config.js.map +1 -0
  349. package/package.json +24 -11
@@ -0,0 +1,115 @@
1
+ /**
2
+ * LLM utilities for the sync pipeline — powered by the Vercel AI SDK.
3
+ *
4
+ * - llmExtract: Structured extraction from unstructured content
5
+ * - llmEnrich: Enrichment with cross-source context
6
+ * - llmGraphMatch: Entity deduplication comparison
7
+ *
8
+ * All three functions use generateText + Output.object() for Zod-validated
9
+ * structured output. Provider is configurable via user config:
10
+ * enrichment_model_id → model_id → 'claude-sonnet-4-5-20250929'
11
+ * enrichment_model_provider → model_provider → 'anthropic'
12
+ */
13
+ import { generateText, Output } from 'ai';
14
+ import { createModel } from './model-factory.js';
15
+ import { ExtractOutputSchema, EnrichOutputSchema, GraphMatchOutputSchema, flattenCustomFields, } from './output-schemas.js';
16
+ import { buildExtractionPrompt, buildEnrichmentPrompt, buildGraphMatchPrompt, describeSchema } from './prompts.js';
17
+ import { loadUserConfig, getAnthropicCredential } from '../../core/user-config.js';
18
+ const DEFAULT_MODEL = 'claude-sonnet-4-5-20250929';
19
+ const DEFAULT_PROVIDER = 'anthropic';
20
+ function resolveModel(config) {
21
+ return {
22
+ provider: config.enrichment_model_provider ?? config.model_provider ?? DEFAULT_PROVIDER,
23
+ model: config.enrichment_model_id ?? config.model_id ?? DEFAULT_MODEL,
24
+ };
25
+ }
26
+ function resolveApiKey(config, _provider) {
27
+ const configKey = getAnthropicCredential(config);
28
+ if (configKey)
29
+ return configKey;
30
+ return undefined;
31
+ }
32
+ const CUSTOM_FIELDS_INSTRUCTION = '\n\nIMPORTANT: Put any extracted fields that are NOT in the base schema (entity_type, entity_id, name) into the `custom_fields` object.';
33
+ // Cast Output to suppress TS2589 "excessively deep" type instantiation from
34
+ // AI SDK generics × Zod. Runtime validation is still handled by Zod at parse time.
35
+ const OutputAny = Output;
36
+ const extractOutput = OutputAny.object({ schema: ExtractOutputSchema });
37
+ const enrichOutput = OutputAny.object({ schema: EnrichOutputSchema });
38
+ const graphMatchOutput = OutputAny.object({ schema: GraphMatchOutputSchema });
39
+ /**
40
+ * Extract structured frontmatter from content using LLM.
41
+ */
42
+ export async function llmExtract(content, entityType, schema, graphragContext) {
43
+ const config = loadUserConfig();
44
+ const { provider, model: modelId } = resolveModel(config);
45
+ const apiKey = resolveApiKey(config, provider);
46
+ const schemaDescription = describeSchema(schema);
47
+ const prompt = buildExtractionPrompt(content, entityType, schemaDescription, graphragContext) + CUSTOM_FIELDS_INSTRUCTION;
48
+ const llmModel = createModel(provider, modelId, apiKey);
49
+ const result = await generateText({
50
+ model: llmModel,
51
+ prompt,
52
+ output: extractOutput,
53
+ maxOutputTokens: 2048,
54
+ maxRetries: 2,
55
+ });
56
+ const extracted = result.output;
57
+ if (!extracted?.frontmatter) {
58
+ throw new Error('LLM extraction returned no frontmatter');
59
+ }
60
+ return flattenCustomFields(extracted.frontmatter);
61
+ }
62
+ /**
63
+ * Enrich an entity with cross-source context using LLM.
64
+ * Returns updated frontmatter and generated content.
65
+ */
66
+ export async function llmEnrich(entityData, contextBundle, entityType, schema) {
67
+ const config = loadUserConfig();
68
+ const { provider, model: modelId } = resolveModel(config);
69
+ const apiKey = resolveApiKey(config, provider);
70
+ const schemaDescription = describeSchema(schema);
71
+ const prompt = buildEnrichmentPrompt(entityType, entityData, contextBundle, schemaDescription) + CUSTOM_FIELDS_INSTRUCTION;
72
+ const llmModel = createModel(provider, modelId, apiKey);
73
+ const result = await generateText({
74
+ model: llmModel,
75
+ prompt,
76
+ output: enrichOutput,
77
+ maxOutputTokens: 4096,
78
+ maxRetries: 2,
79
+ });
80
+ const enriched = result.output;
81
+ if (!enriched?.frontmatter) {
82
+ throw new Error('LLM enrichment returned no frontmatter');
83
+ }
84
+ return {
85
+ frontmatter: flattenCustomFields(enriched.frontmatter),
86
+ content: enriched.content ?? '',
87
+ };
88
+ }
89
+ /**
90
+ * Ask LLM whether two entities (staged vs existing) are the same real-world entity.
91
+ */
92
+ export async function llmGraphMatch(stagedFrontmatter, existingFrontmatter, entityType) {
93
+ const config = loadUserConfig();
94
+ const { provider, model: modelId } = resolveModel(config);
95
+ const apiKey = resolveApiKey(config, provider);
96
+ const prompt = buildGraphMatchPrompt(stagedFrontmatter, existingFrontmatter, entityType);
97
+ const llmModel = createModel(provider, modelId, apiKey);
98
+ const result = await generateText({
99
+ model: llmModel,
100
+ prompt,
101
+ output: graphMatchOutput,
102
+ maxOutputTokens: 1024,
103
+ maxRetries: 2,
104
+ });
105
+ const match = result.output;
106
+ if (!match) {
107
+ throw new Error('LLM graph match returned no output');
108
+ }
109
+ return {
110
+ is_same: match.is_same,
111
+ confidence: match.confidence ?? 0.5,
112
+ reasoning: match.reasoning ?? '',
113
+ };
114
+ }
115
+ //# sourceMappingURL=llm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm.js","sourceRoot":"","sources":["../../../src/services/sync/llm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * SyncMCPClient
3
+ *
4
+ * Persistent MCP client for the sync pipeline. Holds a single connection
5
+ * for the entire sync run to avoid repeated handshake overhead.
6
+ *
7
+ * 30s timeout on all MCP calls via Promise.race.
8
+ */
9
+ import type { ConnectorConfig } from '../../mcp/connector-manager.js';
10
+ import type { DetectedEntityType } from './types.js';
11
+ interface MCPTool {
12
+ name: string;
13
+ description?: string;
14
+ inputSchema?: Record<string, any>;
15
+ }
16
+ export declare class SyncMCPClient {
17
+ private client;
18
+ private config;
19
+ private tools;
20
+ private connected;
21
+ constructor(connectorConfig: ConnectorConfig);
22
+ /**
23
+ * Connect to the MCP server.
24
+ */
25
+ connect(): Promise<void>;
26
+ /**
27
+ * Close the MCP connection.
28
+ */
29
+ close(): Promise<void>;
30
+ /**
31
+ * Get available tools from the connected server.
32
+ */
33
+ getTools(): MCPTool[];
34
+ /**
35
+ * Call an MCP tool with a 30s timeout.
36
+ */
37
+ callTool(name: string, args?: Record<string, any>): Promise<string>;
38
+ /**
39
+ * Detect available entity types by inspecting tool names.
40
+ * Looks for list_* / get_* tool pairs.
41
+ */
42
+ detectAvailableEntityTypes(): DetectedEntityType[];
43
+ /**
44
+ * Find the list tool for a given source type.
45
+ * Checks exact patterns first, then falls back to a broader search
46
+ * for tools containing "list" and the source type (handles prefixed
47
+ * tool names like list_granola_documents).
48
+ */
49
+ findListTool(sourceType: string): string | null;
50
+ /**
51
+ * Find the get/detail tool for a given source type.
52
+ */
53
+ findGetTool(sourceType: string): string | null;
54
+ /**
55
+ * Detect the ID parameter name from a get tool's input schema.
56
+ */
57
+ getToolIdParam(toolName: string): string;
58
+ }
59
+ export {};
@@ -0,0 +1,285 @@
1
+ /**
2
+ * SyncMCPClient
3
+ *
4
+ * Persistent MCP client for the sync pipeline. Holds a single connection
5
+ * for the entire sync run to avoid repeated handshake overhead.
6
+ *
7
+ * 30s timeout on all MCP calls via Promise.race.
8
+ */
9
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
10
+ import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
11
+ import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
12
+ import { ConnectorManager } from '../../mcp/connector-manager.js';
13
+ const CALL_TIMEOUT = 120_000;
14
+ export class SyncMCPClient {
15
+ client;
16
+ config;
17
+ tools = [];
18
+ connected = false;
19
+ constructor(connectorConfig) {
20
+ this.config = connectorConfig;
21
+ this.client = new Client({ name: 'studiograph-sync', version: '1.0.0' });
22
+ }
23
+ /**
24
+ * Connect to the MCP server.
25
+ */
26
+ async connect() {
27
+ if (this.connected)
28
+ return;
29
+ const transport = this.config.type === 'stdio'
30
+ ? new StdioClientTransport({
31
+ command: this.config.command,
32
+ args: this.config.args,
33
+ env: this.config.env,
34
+ stderr: 'ignore',
35
+ })
36
+ : new StreamableHTTPClientTransport(new URL(this.config.url), {
37
+ requestInit: {
38
+ headers: { Authorization: `Bearer ${ConnectorManager.resolveToken(this.config.token)}` },
39
+ },
40
+ });
41
+ await this.client.connect(transport);
42
+ const { tools } = await this.client.listTools();
43
+ this.tools = tools.map(t => ({
44
+ name: t.name,
45
+ description: t.description,
46
+ inputSchema: t.inputSchema,
47
+ }));
48
+ this.connected = true;
49
+ }
50
+ /**
51
+ * Close the MCP connection.
52
+ */
53
+ async close() {
54
+ if (!this.connected)
55
+ return;
56
+ try {
57
+ await this.client.close();
58
+ }
59
+ catch {
60
+ // ignore close errors
61
+ }
62
+ this.connected = false;
63
+ }
64
+ /**
65
+ * Get available tools from the connected server.
66
+ */
67
+ getTools() {
68
+ return this.tools;
69
+ }
70
+ /**
71
+ * Call an MCP tool with a 30s timeout.
72
+ */
73
+ async callTool(name, args) {
74
+ if (!this.connected) {
75
+ throw new Error('SyncMCPClient not connected. Call connect() first.');
76
+ }
77
+ const call = this.client.callTool({ name, arguments: args ?? {} });
78
+ let timer;
79
+ const timeout = new Promise((_, reject) => {
80
+ timer = setTimeout(() => reject(new Error(`MCP call to "${name}" timed out after ${CALL_TIMEOUT}ms`)), CALL_TIMEOUT);
81
+ });
82
+ const result = await Promise.race([call, timeout]).finally(() => clearTimeout(timer));
83
+ const text = result.content
84
+ .filter((c) => c.type === 'text')
85
+ .map((c) => c.text)
86
+ .join('\n');
87
+ let output = text || JSON.stringify(result, null, 2);
88
+ // Handle double-wrapped MCP responses — some servers (e.g. Pipedrive)
89
+ // return { content: [{ type: "text", text: "..." }] } as their text payload
90
+ try {
91
+ const parsed = JSON.parse(output);
92
+ if (parsed.content && Array.isArray(parsed.content)) {
93
+ const inner = parsed.content
94
+ .filter((c) => c.type === 'text')
95
+ .map((c) => c.text)
96
+ .join('\n');
97
+ if (inner)
98
+ output = inner;
99
+ }
100
+ }
101
+ catch {
102
+ // not JSON or not double-wrapped — use as-is
103
+ }
104
+ return output;
105
+ }
106
+ /**
107
+ * Detect available entity types by inspecting tool names.
108
+ * Looks for list_* / get_* tool pairs.
109
+ */
110
+ detectAvailableEntityTypes() {
111
+ const detected = [];
112
+ const toolNames = new Set(this.tools.map(t => t.name));
113
+ // Common patterns: list_<type>s, search_<type>s, get_<type>
114
+ // Also: <type>_list, <type>_search, <type>_get
115
+ for (const tool of this.tools) {
116
+ let sourceType = null;
117
+ let isList = false;
118
+ // Pattern: list_<type>s or list_<type>
119
+ const listMatch = tool.name.match(/^list_(.+?)s?$/);
120
+ if (listMatch) {
121
+ sourceType = listMatch[1];
122
+ isList = true;
123
+ }
124
+ // Pattern: search_<type>s or search_<type>
125
+ if (!sourceType) {
126
+ const searchMatch = tool.name.match(/^search_(.+?)s?$/);
127
+ if (searchMatch) {
128
+ sourceType = searchMatch[1];
129
+ isList = true;
130
+ }
131
+ }
132
+ // Pattern: <prefix>__list_<type>s (namespaced)
133
+ if (!sourceType) {
134
+ const nsListMatch = tool.name.match(/^[a-z_]+__list_(.+?)s?$/);
135
+ if (nsListMatch) {
136
+ sourceType = nsListMatch[1];
137
+ isList = true;
138
+ }
139
+ }
140
+ // Pattern: <prefix>__search_<type>s (namespaced)
141
+ if (!sourceType) {
142
+ const nsSearchMatch = tool.name.match(/^[a-z_]+__search_(.+?)s?$/);
143
+ if (nsSearchMatch) {
144
+ sourceType = nsSearchMatch[1];
145
+ isList = true;
146
+ }
147
+ }
148
+ // Pattern: <type>s_list or <type>s_search
149
+ if (!sourceType) {
150
+ const suffixMatch = tool.name.match(/^(.+?)s?_(?:list|search)$/);
151
+ if (suffixMatch) {
152
+ sourceType = suffixMatch[1];
153
+ isList = true;
154
+ }
155
+ }
156
+ if (!sourceType || !isList)
157
+ continue;
158
+ // Avoid duplicates
159
+ if (detected.some(d => d.source_type === sourceType))
160
+ continue;
161
+ // Look for corresponding get tool
162
+ const getVariants = [
163
+ `get_${sourceType}`,
164
+ `${sourceType}_get`,
165
+ `read_${sourceType}`,
166
+ ];
167
+ const getTool = getVariants.find(g => toolNames.has(g));
168
+ detected.push({
169
+ source_type: sourceType,
170
+ list_tool: tool.name,
171
+ get_tool: getTool,
172
+ suggested_entity_type: suggestEntityType(sourceType),
173
+ suggested_repo: suggestRepo(sourceType),
174
+ });
175
+ }
176
+ return detected;
177
+ }
178
+ /**
179
+ * Find the list tool for a given source type.
180
+ * Checks exact patterns first, then falls back to a broader search
181
+ * for tools containing "list" and the source type (handles prefixed
182
+ * tool names like list_granola_documents).
183
+ */
184
+ findListTool(sourceType) {
185
+ const candidates = [
186
+ `list_${sourceType}s`,
187
+ `list_${sourceType}`,
188
+ `${sourceType}s_list`,
189
+ `${sourceType}_list`,
190
+ `${sourceType}s_list_all_auto`,
191
+ `${sourceType}_list_all_auto`,
192
+ // Search-based APIs (e.g. Asana)
193
+ `search_${sourceType}s`,
194
+ `search_${sourceType}`,
195
+ `${sourceType}s_search`,
196
+ `${sourceType}_search`,
197
+ ];
198
+ for (const name of candidates) {
199
+ if (this.tools.some(t => t.name === name))
200
+ return name;
201
+ }
202
+ // Fallback: find any tool containing "list" or "search" and the source type
203
+ const plural = sourceType.endsWith('s') ? sourceType : sourceType + 's';
204
+ const match = this.tools.find(t => (t.name.includes('list') || t.name.includes('search')) &&
205
+ (t.name.includes(plural) || t.name.includes(sourceType)));
206
+ return match?.name ?? null;
207
+ }
208
+ /**
209
+ * Find the get/detail tool for a given source type.
210
+ */
211
+ findGetTool(sourceType) {
212
+ const candidates = [
213
+ `get_${sourceType}`,
214
+ `${sourceType}_get`,
215
+ `${sourceType}s_get`,
216
+ `read_${sourceType}`,
217
+ ];
218
+ for (const name of candidates) {
219
+ if (this.tools.some(t => t.name === name))
220
+ return name;
221
+ }
222
+ // Fallback: find any tool containing "get" and the source type
223
+ const match = this.tools.find(t => (t.name.includes('get') || t.name.includes('read')) &&
224
+ t.name.includes(sourceType) &&
225
+ !t.name.includes('list') &&
226
+ !t.name.includes('search'));
227
+ return match?.name ?? null;
228
+ }
229
+ /**
230
+ * Detect the ID parameter name from a get tool's input schema.
231
+ */
232
+ getToolIdParam(toolName) {
233
+ const tool = this.tools.find(t => t.name === toolName);
234
+ if (!tool?.inputSchema?.properties)
235
+ return 'id';
236
+ const required = tool.inputSchema.required ?? [];
237
+ // Return the first required param (usually "id")
238
+ for (const param of required) {
239
+ const prop = tool.inputSchema.properties[param];
240
+ if (prop && (prop.type === 'string' || prop.type === 'number')) {
241
+ return param;
242
+ }
243
+ }
244
+ return 'id';
245
+ }
246
+ }
247
+ // ── Helpers ──────────────────────────────────────────────────────────────────
248
+ const TYPE_MAP = {
249
+ deal: 'project',
250
+ deals: 'project',
251
+ person: 'person',
252
+ persons: 'person',
253
+ people: 'person',
254
+ organization: 'client',
255
+ organizations: 'client',
256
+ company: 'client',
257
+ companies: 'client',
258
+ document: 'meeting',
259
+ documents: 'meeting',
260
+ note: 'meeting',
261
+ notes: 'meeting',
262
+ activity: 'task',
263
+ activities: 'task',
264
+ product: 'deliverable',
265
+ products: 'deliverable',
266
+ };
267
+ const REPO_MAP = {
268
+ project: 'projects',
269
+ person: 'people',
270
+ client: 'clients',
271
+ meeting: 'meetings',
272
+ task: 'tasks',
273
+ deliverable: 'deliverables',
274
+ deal: 'deals',
275
+ };
276
+ function suggestEntityType(sourceType) {
277
+ return TYPE_MAP[sourceType.toLowerCase()];
278
+ }
279
+ function suggestRepo(sourceType) {
280
+ const entityType = suggestEntityType(sourceType);
281
+ if (!entityType)
282
+ return undefined;
283
+ return REPO_MAP[entityType];
284
+ }
285
+ //# sourceMappingURL=mcp-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-client.js","sourceRoot":"","sources":["../../../src/services/sync/mcp-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Maps (provider, modelId, apiKey?) to an AI SDK LanguageModel.
3
+ *
4
+ * Each provider falls back to its own env var when no apiKey is given:
5
+ * anthropic → ANTHROPIC_API_KEY
6
+ * openai → OPENAI_API_KEY
7
+ * google → GOOGLE_GENERATIVE_AI_API_KEY
8
+ */
9
+ import type { LanguageModel } from 'ai';
10
+ export declare function createModel(provider: string, modelId: string, apiKey?: string): LanguageModel;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Maps (provider, modelId, apiKey?) to an AI SDK LanguageModel.
3
+ *
4
+ * Each provider falls back to its own env var when no apiKey is given:
5
+ * anthropic → ANTHROPIC_API_KEY
6
+ * openai → OPENAI_API_KEY
7
+ * google → GOOGLE_GENERATIVE_AI_API_KEY
8
+ */
9
+ import { createAnthropic } from '@ai-sdk/anthropic';
10
+ import { createOpenAI } from '@ai-sdk/openai';
11
+ import { createGoogleGenerativeAI } from '@ai-sdk/google';
12
+ export function createModel(provider, modelId, apiKey) {
13
+ switch (provider) {
14
+ case 'anthropic':
15
+ return createAnthropic(apiKey ? { apiKey } : {})(modelId);
16
+ case 'openai':
17
+ return createOpenAI(apiKey ? { apiKey } : {})(modelId);
18
+ case 'google':
19
+ return createGoogleGenerativeAI(apiKey ? { apiKey } : {})(modelId);
20
+ default:
21
+ throw new Error(`Unsupported provider: ${provider}. Supported: anthropic, openai, google`);
22
+ }
23
+ }
24
+ //# sourceMappingURL=model-factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-factory.js","sourceRoot":"","sources":["../../../src/services/sync/model-factory.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAG1D,MAAM,UAAU,WAAW,CAAC,QAAgB,EAAE,OAAe,EAAE,MAAe;IAC5E,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,WAAW;YACd,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;QAC5D,KAAK,QAAQ;YACX,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;QACzD,KAAK,QAAQ;YACX,OAAO,wBAAwB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;QACrE;YACE,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,wCAAwC,CAAC,CAAC;IAC/F,CAAC;AACH,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Name quality scoring for sync pipeline (STU-92)
3
+ *
4
+ * Detects username-like strings (dw8768a, dkim06) and other low-quality
5
+ * names that shouldn't enter the knowledge graph at full confidence.
6
+ *
7
+ * Returns a confidence value (0–1) that can be applied as a penalty
8
+ * to extracted records. Records aren't dropped — just flagged with
9
+ * lower confidence so they surface in staging review.
10
+ */
11
+ /**
12
+ * Score the quality of an entity name.
13
+ *
14
+ * @returns confidence multiplier (0–1). 1.0 = normal, lower = suspicious.
15
+ */
16
+ export declare function nameQuality(name: string, entityType: string): number;
17
+ /**
18
+ * Detect username/ID-like strings.
19
+ *
20
+ * Patterns caught:
21
+ * - Letters + digits: dkim06, dk784, dw8768a, user123
22
+ * - Digits + letters: 3dsmith
23
+ * - Single lowercase word with no vowels: dvrbrk (rare but catches some IDs)
24
+ *
25
+ * Patterns allowed:
26
+ * - Multi-word names: "John Doe", "Mary Jane Watson"
27
+ * - Names with hyphens: "Jean-Pierre", "O'Brien"
28
+ * - Names with apostrophes: "O'Connor"
29
+ * - Single-word names without digits: "Beyonce", "Madonna"
30
+ */
31
+ export declare function isLikelyUsername(name: string): boolean;
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Name quality scoring for sync pipeline (STU-92)
3
+ *
4
+ * Detects username-like strings (dw8768a, dkim06) and other low-quality
5
+ * names that shouldn't enter the knowledge graph at full confidence.
6
+ *
7
+ * Returns a confidence value (0–1) that can be applied as a penalty
8
+ * to extracted records. Records aren't dropped — just flagged with
9
+ * lower confidence so they surface in staging review.
10
+ */
11
+ /**
12
+ * Score the quality of an entity name.
13
+ *
14
+ * @returns confidence multiplier (0–1). 1.0 = normal, lower = suspicious.
15
+ */
16
+ export function nameQuality(name, entityType) {
17
+ if (!name || typeof name !== 'string')
18
+ return 0;
19
+ const trimmed = name.trim();
20
+ if (trimmed.length === 0)
21
+ return 0;
22
+ // All entity types: all-digit strings are not names
23
+ if (/^\d+$/.test(trimmed))
24
+ return 0.1;
25
+ // All entity types: single char is not a name
26
+ if (trimmed.length === 1)
27
+ return 0.2;
28
+ // Person-specific checks
29
+ if (entityType === 'person') {
30
+ if (trimmed.length <= 2)
31
+ return 0.2;
32
+ if (isLikelyUsername(trimmed))
33
+ return 0.2;
34
+ }
35
+ return 1.0;
36
+ }
37
+ /**
38
+ * Detect username/ID-like strings.
39
+ *
40
+ * Patterns caught:
41
+ * - Letters + digits: dkim06, dk784, dw8768a, user123
42
+ * - Digits + letters: 3dsmith
43
+ * - Single lowercase word with no vowels: dvrbrk (rare but catches some IDs)
44
+ *
45
+ * Patterns allowed:
46
+ * - Multi-word names: "John Doe", "Mary Jane Watson"
47
+ * - Names with hyphens: "Jean-Pierre", "O'Brien"
48
+ * - Names with apostrophes: "O'Connor"
49
+ * - Single-word names without digits: "Beyonce", "Madonna"
50
+ */
51
+ export function isLikelyUsername(name) {
52
+ // Multi-word names are almost never usernames
53
+ if (/\s/.test(name.trim()))
54
+ return false;
55
+ // Single word containing digits mixed with letters → username
56
+ if (/[a-z]/i.test(name) && /\d/.test(name))
57
+ return true;
58
+ return false;
59
+ }
60
+ //# sourceMappingURL=name-quality.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"name-quality.js","sourceRoot":"","sources":["../../../src/services/sync/name-quality.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,UAAkB;IAC1D,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,CAAC,CAAC;IAEhD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAEnC,oDAAoD;IACpD,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,GAAG,CAAC;IAEtC,8CAA8C;IAC9C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IAErC,yBAAyB;IACzB,IAAI,UAAU,KAAK,QAAQ,EAAE,CAAC;QAC5B,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC;YAAE,OAAO,GAAG,CAAC;QACpC,IAAI,gBAAgB,CAAC,OAAO,CAAC;YAAE,OAAO,GAAG,CAAC;IAC5C,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,8CAA8C;IAC9C,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAAE,OAAO,KAAK,CAAC;IAEzC,8DAA8D;IAC9D,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAExD,OAAO,KAAK,CAAC;AACf,CAAC"}