@obra-studio/figma-console-mcp 1.32.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 (354) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +879 -0
  3. package/dist/apps/design-system-dashboard/scoring/accessibility.d.ts +14 -0
  4. package/dist/apps/design-system-dashboard/scoring/accessibility.d.ts.map +1 -0
  5. package/dist/apps/design-system-dashboard/scoring/accessibility.js +278 -0
  6. package/dist/apps/design-system-dashboard/scoring/accessibility.js.map +1 -0
  7. package/dist/apps/design-system-dashboard/scoring/component-metadata.d.ts +29 -0
  8. package/dist/apps/design-system-dashboard/scoring/component-metadata.d.ts.map +1 -0
  9. package/dist/apps/design-system-dashboard/scoring/component-metadata.js +358 -0
  10. package/dist/apps/design-system-dashboard/scoring/component-metadata.js.map +1 -0
  11. package/dist/apps/design-system-dashboard/scoring/consistency.d.ts +14 -0
  12. package/dist/apps/design-system-dashboard/scoring/consistency.d.ts.map +1 -0
  13. package/dist/apps/design-system-dashboard/scoring/consistency.js +342 -0
  14. package/dist/apps/design-system-dashboard/scoring/consistency.js.map +1 -0
  15. package/dist/apps/design-system-dashboard/scoring/coverage.d.ts +14 -0
  16. package/dist/apps/design-system-dashboard/scoring/coverage.d.ts.map +1 -0
  17. package/dist/apps/design-system-dashboard/scoring/coverage.js +231 -0
  18. package/dist/apps/design-system-dashboard/scoring/coverage.js.map +1 -0
  19. package/dist/apps/design-system-dashboard/scoring/engine.d.ts +27 -0
  20. package/dist/apps/design-system-dashboard/scoring/engine.d.ts.map +1 -0
  21. package/dist/apps/design-system-dashboard/scoring/engine.js +93 -0
  22. package/dist/apps/design-system-dashboard/scoring/engine.js.map +1 -0
  23. package/dist/apps/design-system-dashboard/scoring/naming-semantics.d.ts +14 -0
  24. package/dist/apps/design-system-dashboard/scoring/naming-semantics.d.ts.map +1 -0
  25. package/dist/apps/design-system-dashboard/scoring/naming-semantics.js +309 -0
  26. package/dist/apps/design-system-dashboard/scoring/naming-semantics.js.map +1 -0
  27. package/dist/apps/design-system-dashboard/scoring/token-architecture.d.ts +14 -0
  28. package/dist/apps/design-system-dashboard/scoring/token-architecture.d.ts.map +1 -0
  29. package/dist/apps/design-system-dashboard/scoring/token-architecture.js +350 -0
  30. package/dist/apps/design-system-dashboard/scoring/token-architecture.js.map +1 -0
  31. package/dist/apps/design-system-dashboard/scoring/types.d.ts +89 -0
  32. package/dist/apps/design-system-dashboard/scoring/types.d.ts.map +1 -0
  33. package/dist/apps/design-system-dashboard/scoring/types.js +41 -0
  34. package/dist/apps/design-system-dashboard/scoring/types.js.map +1 -0
  35. package/dist/apps/design-system-dashboard/server.d.ts +24 -0
  36. package/dist/apps/design-system-dashboard/server.d.ts.map +1 -0
  37. package/dist/apps/design-system-dashboard/server.js +160 -0
  38. package/dist/apps/design-system-dashboard/server.js.map +1 -0
  39. package/dist/apps/token-browser/server.d.ts +26 -0
  40. package/dist/apps/token-browser/server.d.ts.map +1 -0
  41. package/dist/apps/token-browser/server.js +137 -0
  42. package/dist/apps/token-browser/server.js.map +1 -0
  43. package/dist/browser/base.d.ts +58 -0
  44. package/dist/browser/base.d.ts.map +1 -0
  45. package/dist/browser/base.js +6 -0
  46. package/dist/browser/base.js.map +1 -0
  47. package/dist/browser/local.d.ts +87 -0
  48. package/dist/browser/local.d.ts.map +1 -0
  49. package/dist/browser/local.js +318 -0
  50. package/dist/browser/local.js.map +1 -0
  51. package/dist/core/accessibility-tools.d.ts +21 -0
  52. package/dist/core/accessibility-tools.d.ts.map +1 -0
  53. package/dist/core/accessibility-tools.js +307 -0
  54. package/dist/core/accessibility-tools.js.map +1 -0
  55. package/dist/core/annotation-tools.d.ts +14 -0
  56. package/dist/core/annotation-tools.d.ts.map +1 -0
  57. package/dist/core/annotation-tools.js +231 -0
  58. package/dist/core/annotation-tools.js.map +1 -0
  59. package/dist/core/autodocs-tools.d.ts +7 -0
  60. package/dist/core/autodocs-tools.d.ts.map +1 -0
  61. package/dist/core/autodocs-tools.js +195 -0
  62. package/dist/core/autodocs-tools.js.map +1 -0
  63. package/dist/core/comment-tools.d.ts +11 -0
  64. package/dist/core/comment-tools.d.ts.map +1 -0
  65. package/dist/core/comment-tools.js +293 -0
  66. package/dist/core/comment-tools.js.map +1 -0
  67. package/dist/core/config.d.ts +17 -0
  68. package/dist/core/config.d.ts.map +1 -0
  69. package/dist/core/config.js +154 -0
  70. package/dist/core/config.js.map +1 -0
  71. package/dist/core/console-monitor.d.ts +82 -0
  72. package/dist/core/console-monitor.d.ts.map +1 -0
  73. package/dist/core/console-monitor.js +428 -0
  74. package/dist/core/console-monitor.js.map +1 -0
  75. package/dist/core/deep-component-tools.d.ts +14 -0
  76. package/dist/core/deep-component-tools.d.ts.map +1 -0
  77. package/dist/core/deep-component-tools.js +129 -0
  78. package/dist/core/deep-component-tools.js.map +1 -0
  79. package/dist/core/design-code-tools.d.ts +116 -0
  80. package/dist/core/design-code-tools.d.ts.map +1 -0
  81. package/dist/core/design-code-tools.js +2751 -0
  82. package/dist/core/design-code-tools.js.map +1 -0
  83. package/dist/core/design-system-manifest.d.ts +272 -0
  84. package/dist/core/design-system-manifest.d.ts.map +1 -0
  85. package/dist/core/design-system-manifest.js +261 -0
  86. package/dist/core/design-system-manifest.js.map +1 -0
  87. package/dist/core/design-system-tools.d.ts +67 -0
  88. package/dist/core/design-system-tools.d.ts.map +1 -0
  89. package/dist/core/design-system-tools.js +874 -0
  90. package/dist/core/design-system-tools.js.map +1 -0
  91. package/dist/core/diagnose-tool.d.ts +33 -0
  92. package/dist/core/diagnose-tool.d.ts.map +1 -0
  93. package/dist/core/diagnose-tool.js +97 -0
  94. package/dist/core/diagnose-tool.js.map +1 -0
  95. package/dist/core/diff/changelog-formatter.d.ts +35 -0
  96. package/dist/core/diff/changelog-formatter.d.ts.map +1 -0
  97. package/dist/core/diff/changelog-formatter.js +276 -0
  98. package/dist/core/diff/changelog-formatter.js.map +1 -0
  99. package/dist/core/diff/diff-engine.d.ts +127 -0
  100. package/dist/core/diff/diff-engine.d.ts.map +1 -0
  101. package/dist/core/diff/diff-engine.js +335 -0
  102. package/dist/core/diff/diff-engine.js.map +1 -0
  103. package/dist/core/diff/property-compare.d.ts +19 -0
  104. package/dist/core/diff/property-compare.d.ts.map +1 -0
  105. package/dist/core/diff/property-compare.js +37 -0
  106. package/dist/core/diff/property-compare.js.map +1 -0
  107. package/dist/core/diff/version-cache.d.ts +40 -0
  108. package/dist/core/diff/version-cache.d.ts.map +1 -0
  109. package/dist/core/diff/version-cache.js +75 -0
  110. package/dist/core/diff/version-cache.js.map +1 -0
  111. package/dist/core/enrichment/enrichment-service.d.ts +52 -0
  112. package/dist/core/enrichment/enrichment-service.d.ts.map +1 -0
  113. package/dist/core/enrichment/enrichment-service.js +369 -0
  114. package/dist/core/enrichment/enrichment-service.js.map +1 -0
  115. package/dist/core/enrichment/index.d.ts +8 -0
  116. package/dist/core/enrichment/index.d.ts.map +1 -0
  117. package/dist/core/enrichment/index.js +8 -0
  118. package/dist/core/enrichment/index.js.map +1 -0
  119. package/dist/core/enrichment/relationship-mapper.d.ts +106 -0
  120. package/dist/core/enrichment/relationship-mapper.d.ts.map +1 -0
  121. package/dist/core/enrichment/relationship-mapper.js +352 -0
  122. package/dist/core/enrichment/relationship-mapper.js.map +1 -0
  123. package/dist/core/enrichment/style-resolver.d.ts +80 -0
  124. package/dist/core/enrichment/style-resolver.d.ts.map +1 -0
  125. package/dist/core/enrichment/style-resolver.js +327 -0
  126. package/dist/core/enrichment/style-resolver.js.map +1 -0
  127. package/dist/core/figjam-tools.d.ts +8 -0
  128. package/dist/core/figjam-tools.d.ts.map +1 -0
  129. package/dist/core/figjam-tools.js +548 -0
  130. package/dist/core/figjam-tools.js.map +1 -0
  131. package/dist/core/figma-api.d.ts +245 -0
  132. package/dist/core/figma-api.d.ts.map +1 -0
  133. package/dist/core/figma-api.js +446 -0
  134. package/dist/core/figma-api.js.map +1 -0
  135. package/dist/core/figma-connector.d.ts +180 -0
  136. package/dist/core/figma-connector.d.ts.map +1 -0
  137. package/dist/core/figma-connector.js +8 -0
  138. package/dist/core/figma-connector.js.map +1 -0
  139. package/dist/core/figma-desktop-connector.d.ts +312 -0
  140. package/dist/core/figma-desktop-connector.d.ts.map +1 -0
  141. package/dist/core/figma-desktop-connector.js +1298 -0
  142. package/dist/core/figma-desktop-connector.js.map +1 -0
  143. package/dist/core/figma-reconstruction-spec.d.ts +166 -0
  144. package/dist/core/figma-reconstruction-spec.d.ts.map +1 -0
  145. package/dist/core/figma-reconstruction-spec.js +403 -0
  146. package/dist/core/figma-reconstruction-spec.js.map +1 -0
  147. package/dist/core/figma-style-extractor.d.ts +76 -0
  148. package/dist/core/figma-style-extractor.d.ts.map +1 -0
  149. package/dist/core/figma-style-extractor.js +312 -0
  150. package/dist/core/figma-style-extractor.js.map +1 -0
  151. package/dist/core/figma-tools.d.ts +22 -0
  152. package/dist/core/figma-tools.d.ts.map +1 -0
  153. package/dist/core/figma-tools.js +3187 -0
  154. package/dist/core/figma-tools.js.map +1 -0
  155. package/dist/core/identity.d.ts +41 -0
  156. package/dist/core/identity.d.ts.map +1 -0
  157. package/dist/core/identity.js +97 -0
  158. package/dist/core/identity.js.map +1 -0
  159. package/dist/core/library-tools.d.ts +17 -0
  160. package/dist/core/library-tools.d.ts.map +1 -0
  161. package/dist/core/library-tools.js +581 -0
  162. package/dist/core/library-tools.js.map +1 -0
  163. package/dist/core/logger.d.ts +22 -0
  164. package/dist/core/logger.d.ts.map +1 -0
  165. package/dist/core/logger.js +54 -0
  166. package/dist/core/logger.js.map +1 -0
  167. package/dist/core/port-discovery.d.ts +171 -0
  168. package/dist/core/port-discovery.d.ts.map +1 -0
  169. package/dist/core/port-discovery.js +563 -0
  170. package/dist/core/port-discovery.js.map +1 -0
  171. package/dist/core/resolve-package-root.d.ts +2 -0
  172. package/dist/core/resolve-package-root.d.ts.map +1 -0
  173. package/dist/core/resolve-package-root.js +12 -0
  174. package/dist/core/resolve-package-root.js.map +1 -0
  175. package/dist/core/slides-tools.d.ts +8 -0
  176. package/dist/core/slides-tools.d.ts.map +1 -0
  177. package/dist/core/slides-tools.js +715 -0
  178. package/dist/core/slides-tools.js.map +1 -0
  179. package/dist/core/snippet-injector.d.ts +24 -0
  180. package/dist/core/snippet-injector.d.ts.map +1 -0
  181. package/dist/core/snippet-injector.js +97 -0
  182. package/dist/core/snippet-injector.js.map +1 -0
  183. package/dist/core/tokens/alias-resolver.d.ts +55 -0
  184. package/dist/core/tokens/alias-resolver.d.ts.map +1 -0
  185. package/dist/core/tokens/alias-resolver.js +136 -0
  186. package/dist/core/tokens/alias-resolver.js.map +1 -0
  187. package/dist/core/tokens/config.d.ts +87 -0
  188. package/dist/core/tokens/config.d.ts.map +1 -0
  189. package/dist/core/tokens/config.js +285 -0
  190. package/dist/core/tokens/config.js.map +1 -0
  191. package/dist/core/tokens/figma-converter.d.ts +81 -0
  192. package/dist/core/tokens/figma-converter.d.ts.map +1 -0
  193. package/dist/core/tokens/figma-converter.js +196 -0
  194. package/dist/core/tokens/figma-converter.js.map +1 -0
  195. package/dist/core/tokens/formatters/css-vars.d.ts +24 -0
  196. package/dist/core/tokens/formatters/css-vars.d.ts.map +1 -0
  197. package/dist/core/tokens/formatters/css-vars.js +330 -0
  198. package/dist/core/tokens/formatters/css-vars.js.map +1 -0
  199. package/dist/core/tokens/formatters/dtcg.d.ts +28 -0
  200. package/dist/core/tokens/formatters/dtcg.d.ts.map +1 -0
  201. package/dist/core/tokens/formatters/dtcg.js +301 -0
  202. package/dist/core/tokens/formatters/dtcg.js.map +1 -0
  203. package/dist/core/tokens/formatters/index.d.ts +30 -0
  204. package/dist/core/tokens/formatters/index.d.ts.map +1 -0
  205. package/dist/core/tokens/formatters/index.js +46 -0
  206. package/dist/core/tokens/formatters/index.js.map +1 -0
  207. package/dist/core/tokens/formatters/json.d.ts +37 -0
  208. package/dist/core/tokens/formatters/json.d.ts.map +1 -0
  209. package/dist/core/tokens/formatters/json.js +188 -0
  210. package/dist/core/tokens/formatters/json.js.map +1 -0
  211. package/dist/core/tokens/formatters/less.d.ts +4 -0
  212. package/dist/core/tokens/formatters/less.d.ts.map +1 -0
  213. package/dist/core/tokens/formatters/less.js +5 -0
  214. package/dist/core/tokens/formatters/less.js.map +1 -0
  215. package/dist/core/tokens/formatters/scss.d.ts +26 -0
  216. package/dist/core/tokens/formatters/scss.d.ts.map +1 -0
  217. package/dist/core/tokens/formatters/scss.js +253 -0
  218. package/dist/core/tokens/formatters/scss.js.map +1 -0
  219. package/dist/core/tokens/formatters/stubs.d.ts +9 -0
  220. package/dist/core/tokens/formatters/stubs.d.ts.map +1 -0
  221. package/dist/core/tokens/formatters/stubs.js +14 -0
  222. package/dist/core/tokens/formatters/stubs.js.map +1 -0
  223. package/dist/core/tokens/formatters/style-dictionary-v3.d.ts +45 -0
  224. package/dist/core/tokens/formatters/style-dictionary-v3.d.ts.map +1 -0
  225. package/dist/core/tokens/formatters/style-dictionary-v3.js +208 -0
  226. package/dist/core/tokens/formatters/style-dictionary-v3.js.map +1 -0
  227. package/dist/core/tokens/formatters/tailwind-v3.d.ts +37 -0
  228. package/dist/core/tokens/formatters/tailwind-v3.d.ts.map +1 -0
  229. package/dist/core/tokens/formatters/tailwind-v3.js +238 -0
  230. package/dist/core/tokens/formatters/tailwind-v3.js.map +1 -0
  231. package/dist/core/tokens/formatters/tailwind-v4.d.ts +41 -0
  232. package/dist/core/tokens/formatters/tailwind-v4.d.ts.map +1 -0
  233. package/dist/core/tokens/formatters/tailwind-v4.js +331 -0
  234. package/dist/core/tokens/formatters/tailwind-v4.js.map +1 -0
  235. package/dist/core/tokens/formatters/tokens-studio.d.ts +44 -0
  236. package/dist/core/tokens/formatters/tokens-studio.d.ts.map +1 -0
  237. package/dist/core/tokens/formatters/tokens-studio.js +251 -0
  238. package/dist/core/tokens/formatters/tokens-studio.js.map +1 -0
  239. package/dist/core/tokens/formatters/ts-module.d.ts +35 -0
  240. package/dist/core/tokens/formatters/ts-module.d.ts.map +1 -0
  241. package/dist/core/tokens/formatters/ts-module.js +199 -0
  242. package/dist/core/tokens/formatters/ts-module.js.map +1 -0
  243. package/dist/core/tokens/index.d.ts +17 -0
  244. package/dist/core/tokens/index.d.ts.map +1 -0
  245. package/dist/core/tokens/index.js +16 -0
  246. package/dist/core/tokens/index.js.map +1 -0
  247. package/dist/core/tokens/parsers/css-vars.d.ts +3 -0
  248. package/dist/core/tokens/parsers/css-vars.d.ts.map +1 -0
  249. package/dist/core/tokens/parsers/css-vars.js +5 -0
  250. package/dist/core/tokens/parsers/css-vars.js.map +1 -0
  251. package/dist/core/tokens/parsers/dtcg.d.ts +21 -0
  252. package/dist/core/tokens/parsers/dtcg.d.ts.map +1 -0
  253. package/dist/core/tokens/parsers/dtcg.js +254 -0
  254. package/dist/core/tokens/parsers/dtcg.js.map +1 -0
  255. package/dist/core/tokens/parsers/index.d.ts +37 -0
  256. package/dist/core/tokens/parsers/index.d.ts.map +1 -0
  257. package/dist/core/tokens/parsers/index.js +139 -0
  258. package/dist/core/tokens/parsers/index.js.map +1 -0
  259. package/dist/core/tokens/parsers/json.d.ts +4 -0
  260. package/dist/core/tokens/parsers/json.d.ts.map +1 -0
  261. package/dist/core/tokens/parsers/json.js +8 -0
  262. package/dist/core/tokens/parsers/json.js.map +1 -0
  263. package/dist/core/tokens/parsers/scss.d.ts +3 -0
  264. package/dist/core/tokens/parsers/scss.d.ts.map +1 -0
  265. package/dist/core/tokens/parsers/scss.js +5 -0
  266. package/dist/core/tokens/parsers/scss.js.map +1 -0
  267. package/dist/core/tokens/parsers/stubs.d.ts +15 -0
  268. package/dist/core/tokens/parsers/stubs.d.ts.map +1 -0
  269. package/dist/core/tokens/parsers/stubs.js +21 -0
  270. package/dist/core/tokens/parsers/stubs.js.map +1 -0
  271. package/dist/core/tokens/parsers/style-dictionary-v3.d.ts +3 -0
  272. package/dist/core/tokens/parsers/style-dictionary-v3.d.ts.map +1 -0
  273. package/dist/core/tokens/parsers/style-dictionary-v3.js +5 -0
  274. package/dist/core/tokens/parsers/style-dictionary-v3.js.map +1 -0
  275. package/dist/core/tokens/parsers/tailwind-v3.d.ts +3 -0
  276. package/dist/core/tokens/parsers/tailwind-v3.d.ts.map +1 -0
  277. package/dist/core/tokens/parsers/tailwind-v3.js +5 -0
  278. package/dist/core/tokens/parsers/tailwind-v3.js.map +1 -0
  279. package/dist/core/tokens/parsers/tailwind-v4.d.ts +3 -0
  280. package/dist/core/tokens/parsers/tailwind-v4.d.ts.map +1 -0
  281. package/dist/core/tokens/parsers/tailwind-v4.js +5 -0
  282. package/dist/core/tokens/parsers/tailwind-v4.js.map +1 -0
  283. package/dist/core/tokens/parsers/tokens-studio.d.ts +3 -0
  284. package/dist/core/tokens/parsers/tokens-studio.d.ts.map +1 -0
  285. package/dist/core/tokens/parsers/tokens-studio.js +5 -0
  286. package/dist/core/tokens/parsers/tokens-studio.js.map +1 -0
  287. package/dist/core/tokens/schemas.d.ts +31 -0
  288. package/dist/core/tokens/schemas.d.ts.map +1 -0
  289. package/dist/core/tokens/schemas.js +149 -0
  290. package/dist/core/tokens/schemas.js.map +1 -0
  291. package/dist/core/tokens/transforms/color.d.ts +9 -0
  292. package/dist/core/tokens/transforms/color.d.ts.map +1 -0
  293. package/dist/core/tokens/transforms/color.js +13 -0
  294. package/dist/core/tokens/transforms/color.js.map +1 -0
  295. package/dist/core/tokens/transforms/index.d.ts +36 -0
  296. package/dist/core/tokens/transforms/index.d.ts.map +1 -0
  297. package/dist/core/tokens/transforms/index.js +30 -0
  298. package/dist/core/tokens/transforms/index.js.map +1 -0
  299. package/dist/core/tokens/transforms/size.d.ts +7 -0
  300. package/dist/core/tokens/transforms/size.d.ts.map +1 -0
  301. package/dist/core/tokens/transforms/size.js +8 -0
  302. package/dist/core/tokens/transforms/size.js.map +1 -0
  303. package/dist/core/tokens/types.d.ts +228 -0
  304. package/dist/core/tokens/types.d.ts.map +1 -0
  305. package/dist/core/tokens/types.js +19 -0
  306. package/dist/core/tokens/types.js.map +1 -0
  307. package/dist/core/tokens-tools.d.ts +42 -0
  308. package/dist/core/tokens-tools.d.ts.map +1 -0
  309. package/dist/core/tokens-tools.js +860 -0
  310. package/dist/core/tokens-tools.js.map +1 -0
  311. package/dist/core/types/design-code.d.ts +271 -0
  312. package/dist/core/types/design-code.d.ts.map +1 -0
  313. package/dist/core/types/design-code.js +5 -0
  314. package/dist/core/types/design-code.js.map +1 -0
  315. package/dist/core/types/enriched.d.ts +213 -0
  316. package/dist/core/types/enriched.d.ts.map +1 -0
  317. package/dist/core/types/enriched.js +6 -0
  318. package/dist/core/types/enriched.js.map +1 -0
  319. package/dist/core/types/index.d.ts +104 -0
  320. package/dist/core/types/index.d.ts.map +1 -0
  321. package/dist/core/types/index.js +5 -0
  322. package/dist/core/types/index.js.map +1 -0
  323. package/dist/core/variable-resolver.d.ts +45 -0
  324. package/dist/core/variable-resolver.d.ts.map +1 -0
  325. package/dist/core/variable-resolver.js +86 -0
  326. package/dist/core/variable-resolver.js.map +1 -0
  327. package/dist/core/version-tools.d.ts +59 -0
  328. package/dist/core/version-tools.d.ts.map +1 -0
  329. package/dist/core/version-tools.js +1159 -0
  330. package/dist/core/version-tools.js.map +1 -0
  331. package/dist/core/websocket-connector.d.ts +187 -0
  332. package/dist/core/websocket-connector.d.ts.map +1 -0
  333. package/dist/core/websocket-connector.js +378 -0
  334. package/dist/core/websocket-connector.js.map +1 -0
  335. package/dist/core/websocket-server.js +866 -0
  336. package/dist/core/websocket-server.js.map +1 -0
  337. package/dist/core/write-tools.d.ts +7 -0
  338. package/dist/core/write-tools.d.ts.map +1 -0
  339. package/dist/core/write-tools.js +2172 -0
  340. package/dist/core/write-tools.js.map +1 -0
  341. package/dist/local.d.ts +95 -0
  342. package/dist/local.d.ts.map +1 -0
  343. package/dist/local.js +3036 -0
  344. package/dist/local.js.map +1 -0
  345. package/dist/vendor/obra-autodocs/autodocs-body.generated.d.ts +2 -0
  346. package/dist/vendor/obra-autodocs/autodocs-body.generated.d.ts.map +1 -0
  347. package/dist/vendor/obra-autodocs/autodocs-body.generated.js +6 -0
  348. package/dist/vendor/obra-autodocs/autodocs-body.generated.js.map +1 -0
  349. package/figma-desktop-bridge/README.md +365 -0
  350. package/figma-desktop-bridge/code.js +6504 -0
  351. package/figma-desktop-bridge/icon.png +0 -0
  352. package/figma-desktop-bridge/manifest.json +67 -0
  353. package/figma-desktop-bridge/ui.html +2441 -0
  354. package/package.json +98 -0
@@ -0,0 +1,563 @@
1
+ /**
2
+ * Port Discovery Module
3
+ *
4
+ * Handles dynamic WebSocket port assignment with range-based fallback.
5
+ * When the preferred port (default 9223) is taken by another MCP server instance
6
+ * (e.g., Claude Desktop Chat tab vs Code tab), the server automatically tries
7
+ * the next port in a fixed range (9223-9232).
8
+ *
9
+ * Port advertisement files are written to /tmp so the Figma plugin can discover
10
+ * which port to connect to. Each instance writes its own file with PID for
11
+ * stale-file detection.
12
+ *
13
+ * Zombie process detection:
14
+ * Active servers refresh their port file every 30s (heartbeat).
15
+ * On startup, cleanupStalePortFiles() detects zombies via:
16
+ * 1. Dead PID — process no longer exists (existing behavior)
17
+ * 2. Stale heartbeat — lastSeen older than 5 minutes (process frozen/hung)
18
+ * 3. Age ceiling — startedAt older than 4 hours with no heartbeat (pre-v1.12 compat)
19
+ * Zombie processes are terminated with SIGTERM to free their ports.
20
+ *
21
+ * Data flow:
22
+ * Server binds port → writes /tmp/figma-console-mcp-{port}.json
23
+ * Server heartbeat → refreshes lastSeen every 30s
24
+ * Plugin scans ports 9223-9232 → connects to first responding server
25
+ * External tools read port files for discovery
26
+ */
27
+ import { writeFileSync, readFileSync, unlinkSync, existsSync, readdirSync } from 'fs';
28
+ import { join } from 'path';
29
+ import { tmpdir } from 'os';
30
+ import { createChildLogger } from './logger.js';
31
+ const logger = createChildLogger({ component: 'port-discovery' });
32
+ /** Default preferred WebSocket port */
33
+ export const DEFAULT_WS_PORT = 9223;
34
+ /** Number of ports in the fallback range (9223-9232 = 10 ports) */
35
+ export const PORT_RANGE_SIZE = 10;
36
+ /** Prefix for port advertisement files in /tmp */
37
+ const PORT_FILE_PREFIX = 'figma-console-mcp-';
38
+ /** Directory for port advertisement files */
39
+ const PORT_FILE_DIR = tmpdir();
40
+ /** Maximum age before a port file without heartbeat is considered stale (4 hours) */
41
+ export const MAX_PORT_FILE_AGE_MS = 4 * 60 * 60 * 1000;
42
+ /** Maximum time since last heartbeat before a process is considered stale (5 minutes) */
43
+ export const HEARTBEAT_STALE_MS = 5 * 60 * 1000;
44
+ /** Grace period after SIGTERM before escalating to SIGKILL (ms) */
45
+ export const TERMINATE_GRACE_MS = 400;
46
+ /**
47
+ * Minimum process age before an orphan may be reaped (ms). Protects a sibling
48
+ * server that is mid-startup — it has bound a port but not yet written its
49
+ * advertisement file, so it would otherwise look like an orphan. By the time a
50
+ * real server is this old it has advertised and is in the known-PID set.
51
+ */
52
+ export const ORPHAN_MIN_AGE_MS = 60 * 1000;
53
+ /** Interval for the periodic background reaper (ms) */
54
+ export const REAP_INTERVAL_MS = 5 * 60 * 1000;
55
+ /** Minimum age before an instance can be evicted as last resort (2 minutes) */
56
+ export const EVICTION_MIN_AGE_MS = 2 * 60 * 1000;
57
+ /** Interval between heartbeat refreshes (30 seconds) */
58
+ export const HEARTBEAT_INTERVAL_MS = 30 * 1000;
59
+ /**
60
+ * Try to bind a WebSocket server to ports in a range, starting from the preferred port.
61
+ * Returns the first port that binds successfully.
62
+ *
63
+ * @param preferredPort - The port to try first (default 9223)
64
+ * @param host - The host to bind to (default 'localhost')
65
+ * @returns The actual port that was bound
66
+ * @throws If all ports in the range are exhausted
67
+ */
68
+ export function getPortRange(preferredPort = DEFAULT_WS_PORT) {
69
+ const ports = [];
70
+ for (let i = 0; i < PORT_RANGE_SIZE; i++) {
71
+ ports.push(preferredPort + i);
72
+ }
73
+ return ports;
74
+ }
75
+ /**
76
+ * Get the file path for a port advertisement file.
77
+ */
78
+ export function getPortFilePath(port) {
79
+ return join(PORT_FILE_DIR, `${PORT_FILE_PREFIX}${port}.json`);
80
+ }
81
+ /**
82
+ * Write a port advertisement file so clients can discover this server instance.
83
+ * Includes PID for stale-file detection and lastSeen for heartbeat tracking.
84
+ */
85
+ export function advertisePort(port, host = 'localhost') {
86
+ const now = new Date().toISOString();
87
+ const data = {
88
+ port,
89
+ pid: process.pid,
90
+ host,
91
+ startedAt: now,
92
+ lastSeen: now,
93
+ };
94
+ const filePath = getPortFilePath(port);
95
+ try {
96
+ writeFileSync(filePath, JSON.stringify(data, null, 2));
97
+ logger.info({ port, filePath }, 'Port advertised');
98
+ }
99
+ catch (error) {
100
+ logger.warn({ port, filePath, error }, 'Failed to write port advertisement file');
101
+ }
102
+ }
103
+ /**
104
+ * Refresh the lastSeen timestamp in a port advertisement file.
105
+ * Called periodically as a heartbeat to prove this server is still active.
106
+ * Non-fatal — heartbeat failures are silently ignored.
107
+ */
108
+ export function refreshPortAdvertisement(port) {
109
+ const filePath = getPortFilePath(port);
110
+ try {
111
+ if (!existsSync(filePath))
112
+ return;
113
+ const raw = readFileSync(filePath, 'utf-8');
114
+ const data = JSON.parse(raw);
115
+ // Only refresh our own port file
116
+ if (data.pid !== process.pid)
117
+ return;
118
+ data.lastSeen = new Date().toISOString();
119
+ writeFileSync(filePath, JSON.stringify(data, null, 2));
120
+ }
121
+ catch {
122
+ // Best-effort — heartbeat failures are non-fatal
123
+ }
124
+ }
125
+ /**
126
+ * Remove the port advertisement file for this instance.
127
+ * Call on clean shutdown.
128
+ */
129
+ export function unadvertisePort(port) {
130
+ const filePath = getPortFilePath(port);
131
+ try {
132
+ if (existsSync(filePath)) {
133
+ unlinkSync(filePath);
134
+ logger.debug({ port, filePath }, 'Port advertisement removed');
135
+ }
136
+ }
137
+ catch {
138
+ // Best-effort cleanup — file may already be gone
139
+ }
140
+ }
141
+ /**
142
+ * Check if a PID is still alive.
143
+ */
144
+ function isProcessAlive(pid) {
145
+ try {
146
+ process.kill(pid, 0); // Signal 0 = existence check, doesn't actually kill
147
+ return true;
148
+ }
149
+ catch {
150
+ return false;
151
+ }
152
+ }
153
+ /**
154
+ * Determine if a port file represents a zombie/stale MCP instance.
155
+ *
156
+ * Detection layers:
157
+ * 1. If lastSeen exists (v1.12+): stale if older than HEARTBEAT_STALE_MS (5 min)
158
+ * 2. If lastSeen is missing (pre-v1.12): stale if startedAt older than MAX_PORT_FILE_AGE_MS (4h)
159
+ *
160
+ * Assumes the owning process IS alive (PID check should happen before calling this).
161
+ */
162
+ export function isStaleInstance(data) {
163
+ const now = Date.now();
164
+ // If heartbeat exists, use it — active servers refresh every 30s
165
+ if (data.lastSeen) {
166
+ const lastSeenAge = now - new Date(data.lastSeen).getTime();
167
+ return lastSeenAge > HEARTBEAT_STALE_MS;
168
+ }
169
+ // No heartbeat (pre-v1.12 instance) — fall back to startup age
170
+ const startedAge = now - new Date(data.startedAt).getTime();
171
+ return startedAge > MAX_PORT_FILE_AGE_MS;
172
+ }
173
+ /**
174
+ * Block the current thread for `ms` milliseconds (synchronous).
175
+ * Used between SIGTERM and SIGKILL so terminateProcess can stay synchronous
176
+ * (its callers — cleanup functions — are synchronous and use execSync).
177
+ */
178
+ function sleepSyncMs(ms) {
179
+ if (ms <= 0)
180
+ return;
181
+ try {
182
+ // Cross-platform, no child process. SharedArrayBuffer/Atomics are standard in Node 18+.
183
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
184
+ }
185
+ catch {
186
+ const end = Date.now() + ms;
187
+ while (Date.now() < end) { /* best-effort spin fallback */ }
188
+ }
189
+ }
190
+ /**
191
+ * Elapsed time since a process started, in milliseconds. Returns null if it
192
+ * cannot be determined (process gone, or `ps` unavailable/unparseable).
193
+ */
194
+ function getProcessAgeMs(pid) {
195
+ if (process.platform === 'win32')
196
+ return null;
197
+ try {
198
+ const { execSync } = require('child_process');
199
+ // `etime` (formatted elapsed time) is portable across macOS and Linux;
200
+ // `etimes` (seconds) is Linux-only — macOS ps rejects it. Format is
201
+ // [[DD-]HH:]MM:SS, e.g. "05:51", "55:27", "01:13:31", "09-14:15:41".
202
+ const out = execSync(`ps -p ${pid} -o etime= 2>/dev/null`, {
203
+ encoding: 'utf-8',
204
+ timeout: 2000,
205
+ }).trim();
206
+ const m = out.match(/^(?:(\d+)-)?(?:(\d+):)?(\d+):(\d+)$/);
207
+ if (!m)
208
+ return null;
209
+ const days = parseInt(m[1] || '0', 10);
210
+ const hours = parseInt(m[2] || '0', 10);
211
+ const mins = parseInt(m[3], 10);
212
+ const secs = parseInt(m[4], 10);
213
+ return ((((days * 24 + hours) * 60 + mins) * 60) + secs) * 1000;
214
+ }
215
+ catch {
216
+ return null;
217
+ }
218
+ }
219
+ /**
220
+ * Terminate a process by PID, escalating to SIGKILL if it ignores SIGTERM.
221
+ *
222
+ * A hung MCP server can catch SIGTERM (its shutdown handler runs) yet never
223
+ * reach process.exit() — e.g. when graceful WebSocket/HTTP close blocks on a
224
+ * lingering connection. SIGTERM alone then leaves a zombie holding its port
225
+ * (often with its advertisement file already removed by the handler). We send
226
+ * SIGTERM, wait briefly, and force-kill with SIGKILL if it is still alive.
227
+ *
228
+ * @returns true if the process is confirmed gone afterwards, false if it survived.
229
+ */
230
+ function terminateProcess(pid, graceMs = TERMINATE_GRACE_MS) {
231
+ // SIGTERM first — give the process a chance to shut down gracefully.
232
+ try {
233
+ process.kill(pid, 'SIGTERM');
234
+ }
235
+ catch {
236
+ return true; // already gone — nothing to terminate
237
+ }
238
+ // Windows: SIGTERM maps to TerminateProcess (immediate, uncatchable).
239
+ if (process.platform === 'win32')
240
+ return !isProcessAlive(pid);
241
+ // POSIX: let the graceful handler run, then force-kill if it ignored SIGTERM.
242
+ sleepSyncMs(graceMs);
243
+ if (!isProcessAlive(pid))
244
+ return true;
245
+ try {
246
+ process.kill(pid, 'SIGKILL');
247
+ }
248
+ catch {
249
+ return true; // exited between the check and the kill
250
+ }
251
+ sleepSyncMs(Math.min(graceMs, 200));
252
+ return !isProcessAlive(pid);
253
+ }
254
+ /**
255
+ * Read and validate a port advertisement file.
256
+ * Returns null if the file doesn't exist, is invalid, or the owning process is dead.
257
+ */
258
+ export function readPortFile(port) {
259
+ const filePath = getPortFilePath(port);
260
+ if (!existsSync(filePath))
261
+ return null;
262
+ try {
263
+ const raw = readFileSync(filePath, 'utf-8');
264
+ const data = JSON.parse(raw);
265
+ // Validate the owning process is still alive
266
+ if (!isProcessAlive(data.pid)) {
267
+ logger.debug({ port, pid: data.pid }, 'Stale port file detected (process dead), cleaning up');
268
+ try {
269
+ unlinkSync(filePath);
270
+ }
271
+ catch { /* best-effort */ }
272
+ return null;
273
+ }
274
+ return data;
275
+ }
276
+ catch {
277
+ return null;
278
+ }
279
+ }
280
+ /**
281
+ * Discover all active Figma Console MCP server instances by scanning port files.
282
+ * Validates each file's PID to filter out stale entries.
283
+ */
284
+ export function discoverActiveInstances(preferredPort = DEFAULT_WS_PORT) {
285
+ const instances = [];
286
+ for (const port of getPortRange(preferredPort)) {
287
+ const data = readPortFile(port);
288
+ if (data) {
289
+ instances.push(data);
290
+ }
291
+ }
292
+ return instances;
293
+ }
294
+ /**
295
+ * Clean up stale port files and terminate zombie MCP processes.
296
+ *
297
+ * Runs at startup before port binding. Detects stale instances via:
298
+ * 1. Dead PID — process no longer exists → delete file
299
+ * 2. Zombie process — alive but stale (no heartbeat or expired heartbeat)
300
+ * → send SIGTERM to free the port, then delete file
301
+ * 3. Corrupt file — invalid JSON → delete file
302
+ */
303
+ export function cleanupStalePortFiles() {
304
+ let cleaned = 0;
305
+ try {
306
+ const files = readdirSync(PORT_FILE_DIR);
307
+ for (const file of files) {
308
+ if (file.startsWith(PORT_FILE_PREFIX) && file.endsWith('.json')) {
309
+ const filePath = join(PORT_FILE_DIR, file);
310
+ try {
311
+ const raw = readFileSync(filePath, 'utf-8');
312
+ const data = JSON.parse(raw);
313
+ if (!isProcessAlive(data.pid)) {
314
+ // Dead PID — just clean up the file
315
+ unlinkSync(filePath);
316
+ cleaned++;
317
+ logger.debug({ port: data.port, pid: data.pid }, 'Cleaned up stale port file (dead process)');
318
+ }
319
+ else if (data.pid !== process.pid && isStaleInstance(data)) {
320
+ // Live PID but stale — zombie process, terminate it to free the port
321
+ logger.info({ port: data.port, pid: data.pid, startedAt: data.startedAt, lastSeen: data.lastSeen }, 'Detected zombie MCP process — sending SIGTERM to free port');
322
+ terminateProcess(data.pid);
323
+ try {
324
+ unlinkSync(filePath);
325
+ }
326
+ catch { /* best-effort */ }
327
+ cleaned++;
328
+ }
329
+ }
330
+ catch {
331
+ // Corrupt file — remove it
332
+ try {
333
+ unlinkSync(filePath);
334
+ cleaned++;
335
+ }
336
+ catch { /* ignore */ }
337
+ }
338
+ }
339
+ }
340
+ }
341
+ catch {
342
+ // Can't read /tmp — unusual but not fatal
343
+ }
344
+ return cleaned;
345
+ }
346
+ /**
347
+ * Deep scan for orphaned MCP server processes that hold ports but have no port files.
348
+ * These are processes left behind by Claude Desktop when tabs close without proper cleanup.
349
+ *
350
+ * Uses lsof (macOS/Linux) to find PIDs listening on each port in the range,
351
+ * then verifies they're figma-console-mcp before terminating.
352
+ *
353
+ * Call AFTER cleanupStalePortFiles() — that handles the port-file-based cleanup first,
354
+ * then this catches any remaining ghosts.
355
+ */
356
+ export function cleanupOrphanedProcesses(preferredPort = DEFAULT_WS_PORT, options = {}) {
357
+ // Only supported on macOS/Linux (lsof)
358
+ if (process.platform === 'win32')
359
+ return 0;
360
+ const minAgeMs = options.minAgeMs ?? ORPHAN_MIN_AGE_MS;
361
+ let cleaned = 0;
362
+ const myPid = process.pid;
363
+ const ports = getPortRange(preferredPort);
364
+ // Collect PIDs that have valid port files (known-good servers)
365
+ const knownPids = new Set();
366
+ for (const port of ports) {
367
+ const data = readPortFile(port);
368
+ if (data)
369
+ knownPids.add(data.pid);
370
+ }
371
+ knownPids.add(myPid); // Never kill ourselves
372
+ for (const port of ports) {
373
+ try {
374
+ // Find PIDs listening on this port via lsof
375
+ const { execSync } = require('child_process');
376
+ const output = execSync(`lsof -i :${port} -sTCP:LISTEN -t 2>/dev/null`, {
377
+ encoding: 'utf-8',
378
+ timeout: 3000,
379
+ }).trim();
380
+ if (!output)
381
+ continue;
382
+ const pids = output.split('\n').map(Number).filter(Boolean);
383
+ for (const pid of pids) {
384
+ if (knownPids.has(pid))
385
+ continue; // Skip known-good servers
386
+ // Verify this is actually a figma-console-mcp process before killing
387
+ try {
388
+ const cmdline = execSync(`ps -p ${pid} -o command= 2>/dev/null`, {
389
+ encoding: 'utf-8',
390
+ timeout: 2000,
391
+ }).trim();
392
+ if (cmdline.includes('figma-console-mcp') || cmdline.includes('figma_console_mcp') || cmdline.includes('local.js')) {
393
+ // Don't reap a sibling that is still starting up (bound a port but
394
+ // hasn't advertised yet). Real orphans are far older than this.
395
+ const ageMs = getProcessAgeMs(pid);
396
+ if (minAgeMs > 0 && ageMs !== null && ageMs < minAgeMs) {
397
+ continue;
398
+ }
399
+ logger.info({ port, pid, command: cmdline.substring(0, 120) }, 'Terminating orphaned MCP server (no port file, holding port)');
400
+ // terminateProcess escalates SIGTERM -> SIGKILL. Only count it as
401
+ // cleaned when the process is confirmed gone, so the log reflects
402
+ // reality (the old code counted attempts and reported success even
403
+ // when a SIGTERM-ignoring zombie survived).
404
+ if (terminateProcess(pid)) {
405
+ cleaned++;
406
+ }
407
+ else {
408
+ logger.warn({ port, pid }, 'Failed to terminate orphaned MCP server (survived SIGKILL)');
409
+ }
410
+ }
411
+ }
412
+ catch {
413
+ // Can't read process info — skip to be safe
414
+ }
415
+ }
416
+ }
417
+ catch {
418
+ // lsof failed for this port — skip
419
+ }
420
+ }
421
+ if (cleaned > 0) {
422
+ // Give terminated processes a moment to release their ports
423
+ try {
424
+ const { execSync } = require('child_process');
425
+ execSync('sleep 0.5', { timeout: 2000 });
426
+ }
427
+ catch { /* non-critical */ }
428
+ logger.info({ cleaned }, `Cleaned up ${cleaned} orphaned MCP server process(es)`);
429
+ }
430
+ return cleaned;
431
+ }
432
+ /**
433
+ * Last-resort eviction: terminate the oldest MCP server instance to free a port.
434
+ *
435
+ * Called ONLY when all ports in the range are exhausted after both cleanup phases
436
+ * (cleanupStalePortFiles + cleanupOrphanedProcesses) have already run. This handles
437
+ * the case where old instances are still alive and heartbeating but no longer needed
438
+ * (e.g., from yesterday's Claude Desktop session that was closed without terminating
439
+ * the MCP server process).
440
+ *
441
+ * Safety guards:
442
+ * - Only evicts instances older than EVICTION_MIN_AGE_MS (2 min) to prevent cascade
443
+ * - Never evicts our own PID
444
+ * - Re-reads port file before kill to avoid TOCTOU race
445
+ * - Uses SIGTERM for graceful shutdown
446
+ * - Waits briefly for port release before returning
447
+ *
448
+ * @returns true if an instance was evicted (caller should retry port binding), false otherwise
449
+ */
450
+ export function evictOldestInstance(preferredPort = DEFAULT_WS_PORT) {
451
+ const myPid = process.pid;
452
+ const ports = getPortRange(preferredPort);
453
+ const candidates = [];
454
+ // Collect all valid port file entries that aren't us
455
+ for (const port of ports) {
456
+ const filePath = getPortFilePath(port);
457
+ try {
458
+ if (!existsSync(filePath))
459
+ continue;
460
+ const raw = readFileSync(filePath, 'utf-8');
461
+ const data = JSON.parse(raw);
462
+ if (data.pid === myPid)
463
+ continue; // Never evict ourselves
464
+ if (!isProcessAlive(data.pid)) {
465
+ // Dead process — just clean up the file (port should already be free)
466
+ try {
467
+ unlinkSync(filePath);
468
+ }
469
+ catch { /* best-effort */ }
470
+ continue;
471
+ }
472
+ candidates.push({ ...data, filePath });
473
+ }
474
+ catch {
475
+ // Corrupt or unreadable — skip
476
+ }
477
+ }
478
+ if (candidates.length === 0) {
479
+ logger.debug('No eviction candidates — ports may be held by non-MCP processes');
480
+ return false;
481
+ }
482
+ // Sort by startedAt ascending — oldest first
483
+ candidates.sort((a, b) => new Date(a.startedAt).getTime() - new Date(b.startedAt).getTime());
484
+ const oldest = candidates[0];
485
+ const ageMs = Date.now() - new Date(oldest.startedAt).getTime();
486
+ // Safety: don't evict instances that started recently (prevents cascade)
487
+ if (ageMs < EVICTION_MIN_AGE_MS) {
488
+ logger.info({ port: oldest.port, pid: oldest.pid, ageSeconds: Math.round(ageMs / 1000) }, 'Oldest instance is too recent to evict — skipping');
489
+ return false;
490
+ }
491
+ // Re-read the port file to avoid TOCTOU race
492
+ try {
493
+ const raw = readFileSync(oldest.filePath, 'utf-8');
494
+ const freshData = JSON.parse(raw);
495
+ if (freshData.pid !== oldest.pid) {
496
+ // PID changed between reads — another process took over, skip
497
+ return false;
498
+ }
499
+ }
500
+ catch {
501
+ // File disappeared — port may already be free
502
+ return true;
503
+ }
504
+ logger.info({ port: oldest.port, pid: oldest.pid, startedAt: oldest.startedAt, ageHours: Math.round(ageMs / 3600000 * 10) / 10 }, 'Evicting oldest MCP server instance to free port (all ports exhausted)');
505
+ terminateProcess(oldest.pid);
506
+ try {
507
+ unlinkSync(oldest.filePath);
508
+ }
509
+ catch { /* best-effort */ }
510
+ // Brief wait for the port to be released by the OS
511
+ try {
512
+ const { execSync } = require('child_process');
513
+ execSync('sleep 0.5', { timeout: 2000 });
514
+ }
515
+ catch { /* non-critical */ }
516
+ return true;
517
+ }
518
+ /**
519
+ * Register process exit handlers to clean up port advertisement file.
520
+ * Should be called once after the port is successfully bound.
521
+ */
522
+ export function registerPortCleanup(port) {
523
+ const cleanup = () => unadvertisePort(port);
524
+ process.on('exit', cleanup);
525
+ // Re-register SIGINT/SIGTERM to ensure cleanup runs before the
526
+ // existing handlers in local.ts main() call process.exit()
527
+ const originalSigintListeners = process.listeners('SIGINT');
528
+ const originalSigtermListeners = process.listeners('SIGTERM');
529
+ // Prepend our cleanup — it runs first, then existing handlers take over
530
+ process.prependListener('SIGINT', cleanup);
531
+ process.prependListener('SIGTERM', cleanup);
532
+ }
533
+ /**
534
+ * Start a periodic background reaper that re-runs the cleanup passes while this
535
+ * server is alive. Startup-only reaping leaves orphans to accumulate between
536
+ * launches (a sibling client that closes without its server exiting cleanly
537
+ * keeps holding a port until the *next* server starts). Periodic reaping keeps
538
+ * the range clean continuously.
539
+ *
540
+ * Safe against live siblings: they hold fresh advertisement files (heartbeat
541
+ * every 30s) so they are in the known-PID set and skipped, and the age guard in
542
+ * cleanupOrphanedProcesses protects mid-startup siblings.
543
+ *
544
+ * The interval is unref'd so it never keeps the process alive on its own.
545
+ *
546
+ * @returns a stop function that clears the interval.
547
+ */
548
+ export function startPeriodicReaper(preferredPort = DEFAULT_WS_PORT) {
549
+ const tick = () => {
550
+ try {
551
+ cleanupStalePortFiles();
552
+ cleanupOrphanedProcesses(preferredPort);
553
+ }
554
+ catch (error) {
555
+ logger.warn({ error }, 'Periodic reaper tick failed');
556
+ }
557
+ };
558
+ const interval = setInterval(tick, REAP_INTERVAL_MS);
559
+ if (typeof interval.unref === 'function')
560
+ interval.unref();
561
+ return () => clearInterval(interval);
562
+ }
563
+ //# sourceMappingURL=port-discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"port-discovery.js","sourceRoot":"","sources":["../../src/core/port-discovery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const PACKAGE_ROOT: any;
2
+ //# sourceMappingURL=resolve-package-root.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-package-root.d.ts","sourceRoot":"","sources":["../../src/core/resolve-package-root.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,YAAY,KAA4D,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Resolve the package root directory.
3
+ *
4
+ * Uses import.meta.url (ESM) to compute an absolute path to the package root,
5
+ * independent of process.cwd(). This file is ESM-only; in CJS test contexts
6
+ * (Jest/ts-jest), it is replaced via moduleNameMapper — see jest.config.cjs.
7
+ */
8
+ import { dirname, join } from 'path';
9
+ import { fileURLToPath } from 'url';
10
+ // dist/core/resolve-package-root.js → ../../ = package root
11
+ export const PACKAGE_ROOT = join(dirname(fileURLToPath(import.meta.url)), '..', '..');
12
+ //# sourceMappingURL=resolve-package-root.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-package-root.js","sourceRoot":"","sources":["../../src/core/resolve-package-root.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,4DAA4D;AAC5D,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ /**
3
+ * Register Figma Slides tools.
4
+ * These tools only work when the connected file is a Figma Slides presentation (editorType === 'slides').
5
+ * Used by both local mode (src/local.ts) and cloud mode (src/index.ts).
6
+ */
7
+ export declare function registerSlidesTools(server: McpServer, getDesktopConnector: () => Promise<any>): void;
8
+ //# sourceMappingURL=slides-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slides-tools.d.ts","sourceRoot":"","sources":["../../src/core/slides-tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA+DzE;;;;GAIG;AACH,wBAAgB,mBAAmB,CAClC,MAAM,EAAE,SAAS,EACjB,mBAAmB,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,GACrC,IAAI,CAsuBN"}