@gtkx/cli 0.20.0 → 1.0.0-rc.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 (341) hide show
  1. package/README.md +173 -0
  2. package/bin/gtkx-dev-runner.js +9 -0
  3. package/dist/builder.d.ts +2 -50
  4. package/dist/builder.d.ts.map +1 -1
  5. package/dist/builder.js +22 -48
  6. package/dist/builder.js.map +1 -1
  7. package/dist/cli.d.ts +1 -2
  8. package/dist/cli.d.ts.map +1 -1
  9. package/dist/cli.js +11 -124
  10. package/dist/cli.js.map +1 -1
  11. package/dist/codegen/freshness.d.ts +11 -0
  12. package/dist/codegen/freshness.d.ts.map +1 -0
  13. package/dist/codegen/freshness.js +42 -0
  14. package/dist/codegen/freshness.js.map +1 -0
  15. package/dist/codegen/report.d.ts +3 -0
  16. package/dist/codegen/report.d.ts.map +1 -0
  17. package/dist/codegen/report.js +16 -0
  18. package/dist/codegen/report.js.map +1 -0
  19. package/dist/codegen/run-codegen.d.ts +35 -0
  20. package/dist/codegen/run-codegen.d.ts.map +1 -0
  21. package/dist/codegen/run-codegen.js +133 -0
  22. package/dist/codegen/run-codegen.js.map +1 -0
  23. package/dist/codegen/store-resolver.d.ts +21 -0
  24. package/dist/codegen/store-resolver.d.ts.map +1 -0
  25. package/dist/codegen/store-resolver.js +52 -0
  26. package/dist/codegen/store-resolver.js.map +1 -0
  27. package/dist/commands/build.d.ts +9 -0
  28. package/dist/commands/build.d.ts.map +1 -0
  29. package/dist/commands/build.js +33 -0
  30. package/dist/commands/build.js.map +1 -0
  31. package/dist/commands/codegen.d.ts +9 -0
  32. package/dist/commands/codegen.d.ts.map +1 -0
  33. package/dist/commands/codegen.js +40 -0
  34. package/dist/commands/codegen.js.map +1 -0
  35. package/dist/commands/dev.d.ts +5 -0
  36. package/dist/commands/dev.d.ts.map +1 -0
  37. package/dist/commands/dev.js +21 -0
  38. package/dist/commands/dev.js.map +1 -0
  39. package/dist/commands/docs.d.ts +19 -0
  40. package/dist/commands/docs.d.ts.map +1 -0
  41. package/dist/commands/docs.js +59 -0
  42. package/dist/commands/docs.js.map +1 -0
  43. package/dist/dev/icon-dir.d.ts +2 -0
  44. package/dist/dev/icon-dir.d.ts.map +1 -0
  45. package/dist/dev/icon-dir.js +13 -0
  46. package/dist/dev/icon-dir.js.map +1 -0
  47. package/dist/dev/refresh-tracker.d.ts +6 -0
  48. package/dist/dev/refresh-tracker.d.ts.map +1 -0
  49. package/dist/dev/refresh-tracker.js +18 -0
  50. package/dist/dev/refresh-tracker.js.map +1 -0
  51. package/dist/dev/runner-deps.d.ts +3 -0
  52. package/dist/dev/runner-deps.d.ts.map +1 -0
  53. package/dist/dev/runner-deps.js +39 -0
  54. package/dist/dev/runner-deps.js.map +1 -0
  55. package/dist/dev/runner-main.d.ts +2 -0
  56. package/dist/dev/runner-main.d.ts.map +1 -0
  57. package/dist/dev/runner-main.js +28 -0
  58. package/dist/dev/runner-main.js.map +1 -0
  59. package/dist/dev/runner.d.ts +23 -0
  60. package/dist/dev/runner.d.ts.map +1 -0
  61. package/dist/dev/runner.js +88 -0
  62. package/dist/dev/runner.js.map +1 -0
  63. package/dist/dev/schema-dir.d.ts +2 -0
  64. package/dist/dev/schema-dir.d.ts.map +1 -0
  65. package/dist/dev/schema-dir.js +10 -0
  66. package/dist/dev/schema-dir.js.map +1 -0
  67. package/dist/dev/supervisor.d.ts +17 -0
  68. package/dist/dev/supervisor.d.ts.map +1 -0
  69. package/dist/dev/supervisor.js +142 -0
  70. package/dist/dev/supervisor.js.map +1 -0
  71. package/dist/dev/vite-dev-server.d.ts +21 -0
  72. package/dist/dev/vite-dev-server.d.ts.map +1 -0
  73. package/dist/dev/vite-dev-server.js +12 -0
  74. package/dist/dev/vite-dev-server.js.map +1 -0
  75. package/dist/internal/banner.d.ts +3 -0
  76. package/dist/internal/banner.d.ts.map +1 -0
  77. package/dist/internal/banner.js +8 -0
  78. package/dist/internal/banner.js.map +1 -0
  79. package/dist/internal/data-dir.d.ts +3 -0
  80. package/dist/internal/data-dir.d.ts.map +1 -0
  81. package/dist/internal/data-dir.js +37 -0
  82. package/dist/internal/data-dir.js.map +1 -0
  83. package/dist/internal/entry-arg.d.ts +19 -0
  84. package/dist/internal/entry-arg.d.ts.map +1 -0
  85. package/dist/internal/entry-arg.js +33 -0
  86. package/dist/internal/entry-arg.js.map +1 -0
  87. package/dist/internal/errors.d.ts +4 -0
  88. package/dist/internal/errors.d.ts.map +1 -0
  89. package/dist/internal/errors.js +27 -0
  90. package/dist/internal/errors.js.map +1 -0
  91. package/dist/internal/list-files.d.ts +6 -0
  92. package/dist/internal/list-files.d.ts.map +1 -0
  93. package/dist/internal/list-files.js +13 -0
  94. package/dist/internal/list-files.js.map +1 -0
  95. package/dist/internal/resolve-cli-tool.d.ts +2 -0
  96. package/dist/internal/resolve-cli-tool.d.ts.map +1 -0
  97. package/dist/internal/resolve-cli-tool.js +20 -0
  98. package/dist/internal/resolve-cli-tool.js.map +1 -0
  99. package/dist/internal/staging-dir.d.ts +3 -0
  100. package/dist/internal/staging-dir.d.ts.map +1 -0
  101. package/dist/internal/staging-dir.js +16 -0
  102. package/dist/internal/staging-dir.js.map +1 -0
  103. package/dist/internal/xdg-data-dirs.d.ts +2 -0
  104. package/dist/internal/xdg-data-dirs.d.ts.map +1 -0
  105. package/dist/internal/xdg-data-dirs.js +8 -0
  106. package/dist/internal/xdg-data-dirs.js.map +1 -0
  107. package/dist/mcp/client.d.ts +23 -0
  108. package/dist/mcp/client.d.ts.map +1 -0
  109. package/dist/mcp/client.js +157 -0
  110. package/dist/mcp/client.js.map +1 -0
  111. package/dist/mcp/handlers.d.ts +8 -0
  112. package/dist/mcp/handlers.d.ts.map +1 -0
  113. package/dist/mcp/handlers.js +119 -0
  114. package/dist/mcp/handlers.js.map +1 -0
  115. package/dist/mcp/index.d.ts +4 -0
  116. package/dist/mcp/index.d.ts.map +1 -0
  117. package/dist/mcp/index.js +17 -0
  118. package/dist/mcp/index.js.map +1 -0
  119. package/dist/mcp/serialize-widget.d.ts +10 -0
  120. package/dist/mcp/serialize-widget.d.ts.map +1 -0
  121. package/dist/mcp/serialize-widget.js +20 -0
  122. package/dist/mcp/serialize-widget.js.map +1 -0
  123. package/dist/mcp/testing-loader.d.ts +6 -0
  124. package/dist/mcp/testing-loader.d.ts.map +1 -0
  125. package/dist/mcp/testing-loader.js +25 -0
  126. package/dist/mcp/testing-loader.js.map +1 -0
  127. package/dist/mcp/widget-registry.d.ts +13 -0
  128. package/dist/mcp/widget-registry.d.ts.map +1 -0
  129. package/dist/mcp/widget-registry.js +38 -0
  130. package/dist/mcp/widget-registry.js.map +1 -0
  131. package/dist/refresh-runtime.d.ts +10 -20
  132. package/dist/refresh-runtime.d.ts.map +1 -1
  133. package/dist/refresh-runtime.js +12 -36
  134. package/dist/refresh-runtime.js.map +1 -1
  135. package/dist/settings/compile.d.ts +2 -0
  136. package/dist/settings/compile.d.ts.map +1 -0
  137. package/dist/settings/compile.js +19 -0
  138. package/dist/settings/compile.js.map +1 -0
  139. package/dist/settings/parser.d.ts +23 -0
  140. package/dist/settings/parser.d.ts.map +1 -0
  141. package/dist/settings/parser.js +117 -0
  142. package/dist/settings/parser.js.map +1 -0
  143. package/dist/settings/render.d.ts +4 -0
  144. package/dist/settings/render.d.ts.map +1 -0
  145. package/dist/settings/render.js +148 -0
  146. package/dist/settings/render.js.map +1 -0
  147. package/dist/settings/schema.d.ts +13 -0
  148. package/dist/settings/schema.d.ts.map +1 -0
  149. package/dist/settings/schema.js +103 -0
  150. package/dist/settings/schema.js.map +1 -0
  151. package/dist/vite-plugins/asset-extensions.d.ts +4 -0
  152. package/dist/vite-plugins/asset-extensions.d.ts.map +1 -0
  153. package/dist/vite-plugins/asset-extensions.js +27 -0
  154. package/dist/vite-plugins/asset-extensions.js.map +1 -0
  155. package/dist/vite-plugins/built-url.d.ts +3 -0
  156. package/dist/vite-plugins/built-url.d.ts.map +1 -0
  157. package/dist/{vite-plugin-gtkx-built-url.js → vite-plugins/built-url.js} +4 -17
  158. package/dist/vite-plugins/built-url.js.map +1 -0
  159. package/dist/vite-plugins/css.d.ts +3 -0
  160. package/dist/vite-plugins/css.d.ts.map +1 -0
  161. package/dist/vite-plugins/css.js +30 -0
  162. package/dist/vite-plugins/css.js.map +1 -0
  163. package/dist/vite-plugins/fast-refresh/refresh-filter.d.ts +7 -0
  164. package/dist/vite-plugins/fast-refresh/refresh-filter.d.ts.map +1 -0
  165. package/dist/vite-plugins/fast-refresh/refresh-filter.js +15 -0
  166. package/dist/vite-plugins/fast-refresh/refresh-filter.js.map +1 -0
  167. package/dist/vite-plugins/fast-refresh/swc-refresh.d.ts +5 -0
  168. package/dist/vite-plugins/fast-refresh/swc-refresh.d.ts.map +1 -0
  169. package/dist/vite-plugins/fast-refresh/swc-refresh.js +66 -0
  170. package/dist/vite-plugins/fast-refresh/swc-refresh.js.map +1 -0
  171. package/dist/vite-plugins/icons.d.ts +3 -0
  172. package/dist/vite-plugins/icons.d.ts.map +1 -0
  173. package/dist/vite-plugins/icons.js +47 -0
  174. package/dist/vite-plugins/icons.js.map +1 -0
  175. package/dist/vite-plugins/index.d.ts +3 -0
  176. package/dist/vite-plugins/index.d.ts.map +1 -0
  177. package/dist/vite-plugins/index.js +21 -0
  178. package/dist/vite-plugins/index.js.map +1 -0
  179. package/dist/vite-plugins/native.d.ts +3 -0
  180. package/dist/vite-plugins/native.d.ts.map +1 -0
  181. package/dist/vite-plugins/native.js +60 -0
  182. package/dist/vite-plugins/native.js.map +1 -0
  183. package/dist/vite-plugins/react-compiler.d.ts +4 -0
  184. package/dist/vite-plugins/react-compiler.d.ts.map +1 -0
  185. package/dist/vite-plugins/react-compiler.js +56 -0
  186. package/dist/vite-plugins/react-compiler.js.map +1 -0
  187. package/dist/vite-plugins/react-dom-prebundle.d.ts +3 -0
  188. package/dist/vite-plugins/react-dom-prebundle.d.ts.map +1 -0
  189. package/dist/vite-plugins/react-dom-prebundle.js +11 -0
  190. package/dist/vite-plugins/react-dom-prebundle.js.map +1 -0
  191. package/dist/vite-plugins/resource-init-module.d.ts +5 -0
  192. package/dist/vite-plugins/resource-init-module.d.ts.map +1 -0
  193. package/dist/vite-plugins/resource-init-module.js +50 -0
  194. package/dist/vite-plugins/resource-init-module.js.map +1 -0
  195. package/dist/vite-plugins/resource-shared.d.ts +6 -0
  196. package/dist/vite-plugins/resource-shared.d.ts.map +1 -0
  197. package/dist/vite-plugins/resource-shared.js +21 -0
  198. package/dist/vite-plugins/resource-shared.js.map +1 -0
  199. package/dist/vite-plugins/resources.d.ts +4 -0
  200. package/dist/vite-plugins/resources.d.ts.map +1 -0
  201. package/dist/vite-plugins/resources.js +220 -0
  202. package/dist/vite-plugins/resources.js.map +1 -0
  203. package/dist/vite-plugins/settings-worker-env.d.ts +3 -0
  204. package/dist/vite-plugins/settings-worker-env.d.ts.map +1 -0
  205. package/dist/vite-plugins/settings-worker-env.js +21 -0
  206. package/dist/vite-plugins/settings-worker-env.js.map +1 -0
  207. package/dist/vite-plugins/settings.d.ts +3 -0
  208. package/dist/vite-plugins/settings.d.ts.map +1 -0
  209. package/dist/vite-plugins/settings.js +190 -0
  210. package/dist/vite-plugins/settings.js.map +1 -0
  211. package/dist/vite-plugins/undeclared-library.d.ts +3 -0
  212. package/dist/vite-plugins/undeclared-library.d.ts.map +1 -0
  213. package/dist/vite-plugins/undeclared-library.js +47 -0
  214. package/dist/vite-plugins/undeclared-library.js.map +1 -0
  215. package/dist/vite-plugins/virtual-module.d.ts +22 -0
  216. package/dist/vite-plugins/virtual-module.d.ts.map +1 -0
  217. package/dist/vite-plugins/virtual-module.js +18 -0
  218. package/dist/vite-plugins/virtual-module.js.map +1 -0
  219. package/dist/vitest-plugin.d.ts +10 -0
  220. package/dist/vitest-plugin.d.ts.map +1 -0
  221. package/dist/vitest-plugin.js +12 -0
  222. package/dist/vitest-plugin.js.map +1 -0
  223. package/env.d.ts +131 -3
  224. package/package.json +32 -38
  225. package/src/babel-modules.d.ts +13 -0
  226. package/src/builder.ts +28 -76
  227. package/src/cli.ts +22 -0
  228. package/src/codegen/freshness.ts +52 -0
  229. package/src/codegen/report.ts +20 -0
  230. package/src/codegen/run-codegen.ts +185 -0
  231. package/src/codegen/store-resolver.ts +75 -0
  232. package/src/commands/build.ts +37 -0
  233. package/src/commands/codegen.ts +44 -0
  234. package/src/commands/dev.ts +25 -0
  235. package/src/commands/docs.ts +66 -0
  236. package/src/dev/icon-dir.ts +11 -0
  237. package/src/dev/refresh-tracker.ts +21 -0
  238. package/src/dev/runner-deps.ts +42 -0
  239. package/src/dev/runner-main.ts +33 -0
  240. package/src/dev/runner.ts +126 -0
  241. package/src/dev/schema-dir.ts +11 -0
  242. package/src/dev/supervisor.ts +178 -0
  243. package/src/dev/vite-dev-server.ts +34 -0
  244. package/src/internal/banner.ts +9 -0
  245. package/src/internal/data-dir.ts +39 -0
  246. package/src/internal/entry-arg.ts +38 -0
  247. package/src/internal/errors.ts +28 -0
  248. package/src/internal/list-files.ts +17 -0
  249. package/src/internal/resolve-cli-tool.ts +21 -0
  250. package/src/internal/staging-dir.ts +16 -0
  251. package/src/internal/xdg-data-dirs.ts +7 -0
  252. package/src/mcp/client.ts +177 -0
  253. package/src/mcp/handlers.ts +156 -0
  254. package/src/mcp/index.ts +22 -0
  255. package/src/mcp/serialize-widget.ts +34 -0
  256. package/src/mcp/testing-loader.ts +32 -0
  257. package/src/mcp/widget-registry.ts +43 -0
  258. package/src/refresh-runtime.ts +12 -41
  259. package/src/settings/compile.ts +19 -0
  260. package/src/settings/parser.ts +154 -0
  261. package/src/settings/render.ts +167 -0
  262. package/src/settings/schema.ts +115 -0
  263. package/src/vite-plugins/asset-extensions.ts +28 -0
  264. package/src/{vite-plugin-gtkx-built-url.ts → vite-plugins/built-url.ts} +3 -16
  265. package/src/vite-plugins/css.ts +38 -0
  266. package/src/vite-plugins/fast-refresh/refresh-filter.ts +18 -0
  267. package/src/vite-plugins/fast-refresh/swc-refresh.ts +79 -0
  268. package/src/vite-plugins/icons.ts +58 -0
  269. package/src/vite-plugins/index.ts +22 -0
  270. package/src/vite-plugins/native.ts +74 -0
  271. package/src/vite-plugins/react-compiler.ts +70 -0
  272. package/src/vite-plugins/react-dom-prebundle.ts +14 -0
  273. package/src/vite-plugins/resource-init-module.ts +54 -0
  274. package/src/vite-plugins/resource-shared.ts +27 -0
  275. package/src/vite-plugins/resources.ts +272 -0
  276. package/src/vite-plugins/settings-worker-env.ts +25 -0
  277. package/src/vite-plugins/settings.ts +221 -0
  278. package/src/vite-plugins/undeclared-library.ts +69 -0
  279. package/src/vite-plugins/virtual-module.ts +37 -0
  280. package/src/vitest-plugin.ts +14 -0
  281. package/dist/create.d.ts +0 -54
  282. package/dist/create.d.ts.map +0 -1
  283. package/dist/create.js +0 -221
  284. package/dist/create.js.map +0 -1
  285. package/dist/dev-server.d.ts +0 -38
  286. package/dist/dev-server.d.ts.map +0 -1
  287. package/dist/dev-server.js +0 -128
  288. package/dist/dev-server.js.map +0 -1
  289. package/dist/index.d.ts +0 -4
  290. package/dist/index.d.ts.map +0 -1
  291. package/dist/index.js +0 -4
  292. package/dist/index.js.map +0 -1
  293. package/dist/mcp-client.d.ts +0 -31
  294. package/dist/mcp-client.d.ts.map +0 -1
  295. package/dist/mcp-client.js +0 -430
  296. package/dist/mcp-client.js.map +0 -1
  297. package/dist/templates.d.ts +0 -9
  298. package/dist/templates.d.ts.map +0 -1
  299. package/dist/templates.js +0 -16
  300. package/dist/templates.js.map +0 -1
  301. package/dist/vite-plugin-gtkx-assets.d.ts +0 -20
  302. package/dist/vite-plugin-gtkx-assets.d.ts.map +0 -1
  303. package/dist/vite-plugin-gtkx-assets.js +0 -57
  304. package/dist/vite-plugin-gtkx-assets.js.map +0 -1
  305. package/dist/vite-plugin-gtkx-built-url.d.ts +0 -18
  306. package/dist/vite-plugin-gtkx-built-url.d.ts.map +0 -1
  307. package/dist/vite-plugin-gtkx-built-url.js.map +0 -1
  308. package/dist/vite-plugin-gtkx-native.d.ts +0 -14
  309. package/dist/vite-plugin-gtkx-native.d.ts.map +0 -1
  310. package/dist/vite-plugin-gtkx-native.js +0 -53
  311. package/dist/vite-plugin-gtkx-native.js.map +0 -1
  312. package/dist/vite-plugin-gtkx-refresh.d.ts +0 -8
  313. package/dist/vite-plugin-gtkx-refresh.d.ts.map +0 -1
  314. package/dist/vite-plugin-gtkx-refresh.js +0 -37
  315. package/dist/vite-plugin-gtkx-refresh.js.map +0 -1
  316. package/dist/vite-plugin-swc-ssr-refresh.d.ts +0 -8
  317. package/dist/vite-plugin-swc-ssr-refresh.d.ts.map +0 -1
  318. package/dist/vite-plugin-swc-ssr-refresh.js +0 -46
  319. package/dist/vite-plugin-swc-ssr-refresh.js.map +0 -1
  320. package/src/cli.tsx +0 -154
  321. package/src/create.ts +0 -310
  322. package/src/dev-server.tsx +0 -162
  323. package/src/index.ts +0 -3
  324. package/src/mcp-client.ts +0 -518
  325. package/src/templates.ts +0 -26
  326. package/src/vite-plugin-gtkx-assets.ts +0 -69
  327. package/src/vite-plugin-gtkx-native.ts +0 -64
  328. package/src/vite-plugin-gtkx-refresh.ts +0 -54
  329. package/src/vite-plugin-swc-ssr-refresh.ts +0 -61
  330. package/templates/claude/EXAMPLES.md.ejs +0 -744
  331. package/templates/claude/SKILL.md.ejs +0 -93
  332. package/templates/claude/WIDGETS.md.ejs +0 -820
  333. package/templates/config/vitest.config.ts.ejs +0 -11
  334. package/templates/gitignore.ejs +0 -4
  335. package/templates/package.json.ejs +0 -16
  336. package/templates/src/app.tsx.ejs +0 -32
  337. package/templates/src/dev.tsx.ejs +0 -5
  338. package/templates/src/gtkx-env.d.ts.ejs +0 -1
  339. package/templates/src/index.tsx.ejs +0 -5
  340. package/templates/tests/app.test.tsx.ejs +0 -16
  341. package/templates/tsconfig.json.ejs +0 -14
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entry-arg.js","sourceRoot":"","sources":["../../src/internal/entry-arg.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,MAAM,kBAAkB,GAAG,WAAW,CAAC;AACvC,MAAM,wBAAwB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAChE,MAAM,aAAa,GAAG,GAAG,kBAAkB,IAAI,wBAAwB,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;AAErF,MAAM,CAAC,MAAM,MAAM,GAA0B;IACzC,GAAG,EAAE;QACD,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,mDAAmD;KACnE;CACJ,CAAC;AAEF,MAAM,CAAC,MAAM,QAAQ,GAAmD;IACpE,KAAK,EAAE;QACH,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,wBAAwB,aAAa,GAAG;QACrD,QAAQ,EAAE,KAAK;KAClB;IACD,GAAG,MAAM;CACZ,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,IAAsB,EAAU,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;AAE7G,MAAM,mBAAmB,GAAG,CAAC,GAAW,EAAU,EAAE;IAChD,KAAK,MAAM,SAAS,IAAI,wBAAwB,EAAE,CAAC;QAC/C,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,kBAAkB,GAAG,SAAS,EAAE,CAAC,CAAC;QACpE,IAAI,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;IAChD,CAAC;IACD,OAAO,OAAO,CAAC,GAAG,EAAE,GAAG,kBAAkB,GAAG,wBAAwB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAC/E,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,IAAsC,EAAkC,EAAE;IACnG,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC7B,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,GAAG,CAAC,EAAE,CAAC;AAC5F,CAAC,CAAC","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { PositionalArgDef, StringArgDef } from \"citty\";\n\nconst DEFAULT_ENTRY_BASE = \"src/index\";\nconst DEFAULT_ENTRY_EXTENSIONS = [\".tsx\", \".jsx\", \".ts\", \".js\"];\nconst DEFAULT_ENTRY = `${DEFAULT_ENTRY_BASE}{${DEFAULT_ENTRY_EXTENSIONS.join(\",\")}}`;\n\nexport const cwdArg: { cwd: StringArgDef } = {\n cwd: {\n type: \"string\",\n description: \"Project root (default: current working directory)\",\n },\n};\n\nexport const entryArg: { entry: PositionalArgDef; cwd: StringArgDef } = {\n entry: {\n type: \"positional\",\n description: `Entry file (default: ${DEFAULT_ENTRY})`,\n required: false,\n },\n ...cwdArg,\n};\n\nexport const resolveCwd = (args: { cwd?: string }): string => (args.cwd ? resolve(args.cwd) : process.cwd());\n\nconst resolveDefaultEntry = (cwd: string): string => {\n for (const extension of DEFAULT_ENTRY_EXTENSIONS) {\n const candidate = resolve(cwd, `${DEFAULT_ENTRY_BASE}${extension}`);\n if (existsSync(candidate)) return candidate;\n }\n return resolve(cwd, `${DEFAULT_ENTRY_BASE}${DEFAULT_ENTRY_EXTENSIONS[0]}`);\n};\n\nexport const resolveEntry = (args: { entry?: string; cwd?: string }): { cwd: string; entry: string } => {\n const cwd = resolveCwd(args);\n return { cwd, entry: args.entry ? resolve(cwd, args.entry) : resolveDefaultEntry(cwd) };\n};\n"]}
@@ -0,0 +1,4 @@
1
+ import type { ArgsDef, CommandDef } from "citty";
2
+ export declare const printError: (cause: unknown) => never;
3
+ export declare const withErrorBoundary: <T extends ArgsDef>(command: CommandDef<T>) => CommandDef<T>;
4
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/internal/errors.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAIjD,eAAO,MAAM,UAAU,UAAW,OAAO,KAAG,KAO3C,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,CAAC,SAAS,OAAO,WAAW,UAAU,CAAC,CAAC,CAAC,KAAG,UAAU,CAAC,CAAC,CAazF,CAAC"}
@@ -0,0 +1,27 @@
1
+ import { logger } from "@gtkx/utils";
2
+ const ERROR_EXIT_CODE = 1;
3
+ export const printError = (cause) => {
4
+ const message = cause instanceof Error ? cause.message : String(cause);
5
+ logger.error(message);
6
+ if (cause instanceof Error && cause.stack !== undefined) {
7
+ logger.debug(cause.stack);
8
+ }
9
+ process.exit(ERROR_EXIT_CODE);
10
+ };
11
+ export const withErrorBoundary = (command) => {
12
+ const run = command.run;
13
+ if (run === undefined)
14
+ return command;
15
+ return {
16
+ ...command,
17
+ run: async (context) => {
18
+ try {
19
+ return await run(context);
20
+ }
21
+ catch (cause) {
22
+ printError(cause);
23
+ }
24
+ },
25
+ };
26
+ };
27
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/internal/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,MAAM,eAAe,GAAG,CAAC,CAAC;AAE1B,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAc,EAAS,EAAE;IAChD,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACtB,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QACtD,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;AAClC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAoB,OAAsB,EAAiB,EAAE;IAC1F,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IACxB,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,OAAO,CAAC;IACtC,OAAO;QACH,GAAG,OAAO;QACV,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;YACnB,IAAI,CAAC;gBACD,OAAO,MAAM,GAAG,CAAC,OAAO,CAAC,CAAC;YAC9B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACb,UAAU,CAAC,KAAK,CAAC,CAAC;YACtB,CAAC;QACL,CAAC;KACJ,CAAC;AACN,CAAC,CAAC","sourcesContent":["import { logger } from \"@gtkx/utils\";\nimport type { ArgsDef, CommandDef } from \"citty\";\n\nconst ERROR_EXIT_CODE = 1;\n\nexport const printError = (cause: unknown): never => {\n const message = cause instanceof Error ? cause.message : String(cause);\n logger.error(message);\n if (cause instanceof Error && cause.stack !== undefined) {\n logger.debug(cause.stack);\n }\n process.exit(ERROR_EXIT_CODE);\n};\n\nexport const withErrorBoundary = <T extends ArgsDef>(command: CommandDef<T>): CommandDef<T> => {\n const run = command.run;\n if (run === undefined) return command;\n return {\n ...command,\n run: async (context) => {\n try {\n return await run(context);\n } catch (cause) {\n printError(cause);\n }\n },\n };\n};\n"]}
@@ -0,0 +1,6 @@
1
+ export type ListedFile = {
2
+ absPath: string;
3
+ rel: string;
4
+ };
5
+ export declare const listFilesRecursive: (dir: string, predicate?: (name: string) => boolean) => ListedFile[];
6
+ //# sourceMappingURL=list-files.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-files.d.ts","sourceRoot":"","sources":["../../src/internal/list-files.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,UAAU,GAAG;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,eAAO,MAAM,kBAAkB,QAAS,MAAM,cAAc,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,KAAG,UAAU,EAQjG,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { existsSync, readdirSync } from "node:fs";
2
+ import { join, relative } from "node:path";
3
+ export const listFilesRecursive = (dir, predicate) => {
4
+ if (!existsSync(dir))
5
+ return [];
6
+ return readdirSync(dir, { recursive: true, withFileTypes: true })
7
+ .filter((entry) => entry.isFile() && (predicate === undefined || predicate(entry.name)))
8
+ .map((entry) => {
9
+ const absPath = join(entry.parentPath, entry.name);
10
+ return { absPath, rel: relative(dir, absPath) };
11
+ });
12
+ };
13
+ //# sourceMappingURL=list-files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-files.js","sourceRoot":"","sources":["../../src/internal/list-files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAO3C,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,GAAW,EAAE,SAAqC,EAAgB,EAAE;IACnG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAChC,OAAO,WAAW,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;SAC5D,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,KAAK,SAAS,IAAI,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;SACvF,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACX,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACnD,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,CAAC;IACpD,CAAC,CAAC,CAAC;AACX,CAAC,CAAC","sourcesContent":["import { existsSync, readdirSync } from \"node:fs\";\nimport { join, relative } from \"node:path\";\n\nexport type ListedFile = {\n absPath: string;\n rel: string;\n};\n\nexport const listFilesRecursive = (dir: string, predicate?: (name: string) => boolean): ListedFile[] => {\n if (!existsSync(dir)) return [];\n return readdirSync(dir, { recursive: true, withFileTypes: true })\n .filter((entry) => entry.isFile() && (predicate === undefined || predicate(entry.name)))\n .map((entry) => {\n const absPath = join(entry.parentPath, entry.name);\n return { absPath, rel: relative(dir, absPath) };\n });\n};\n"]}
@@ -0,0 +1,2 @@
1
+ export declare const resolveCliTool: (executable: string) => string;
2
+ //# sourceMappingURL=resolve-cli-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-cli-tool.d.ts","sourceRoot":"","sources":["../../src/internal/resolve-cli-tool.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,cAAc,eAGH,MAAM,KAAG,MAc7B,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { existsSync, statSync } from "node:fs";
2
+ import { delimiter, join } from "node:path";
3
+ export const resolveCliTool = (() => {
4
+ const cache = new Map();
5
+ return (executable) => {
6
+ const cached = cache.get(executable);
7
+ if (cached)
8
+ return cached;
9
+ const dirs = (process.env.PATH ?? "").split(delimiter).filter(Boolean);
10
+ for (const dir of dirs) {
11
+ const candidate = join(dir, executable);
12
+ if (existsSync(candidate) && statSync(candidate).isFile()) {
13
+ cache.set(executable, candidate);
14
+ return candidate;
15
+ }
16
+ }
17
+ throw new Error(`${executable} not found in PATH`);
18
+ };
19
+ })();
20
+ //# sourceMappingURL=resolve-cli-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-cli-tool.js","sourceRoot":"","sources":["../../src/internal/resolve-cli-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE5C,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE;IAChC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;IAExC,OAAO,CAAC,UAAkB,EAAU,EAAE;QAClC,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACrC,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;QAE1B,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACvE,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACrB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;YACxC,IAAI,UAAU,CAAC,SAAS,CAAC,IAAI,QAAQ,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;gBACxD,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;gBACjC,OAAO,SAAS,CAAC;YACrB,CAAC;QACL,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,GAAG,UAAU,oBAAoB,CAAC,CAAC;IACvD,CAAC,CAAC;AACN,CAAC,CAAC,EAAE,CAAC","sourcesContent":["import { existsSync, statSync } from \"node:fs\";\nimport { delimiter, join } from \"node:path\";\n\nexport const resolveCliTool = (() => {\n const cache = new Map<string, string>();\n\n return (executable: string): string => {\n const cached = cache.get(executable);\n if (cached) return cached;\n\n const dirs = (process.env.PATH ?? \"\").split(delimiter).filter(Boolean);\n for (const dir of dirs) {\n const candidate = join(dir, executable);\n if (existsSync(candidate) && statSync(candidate).isFile()) {\n cache.set(executable, candidate);\n return candidate;\n }\n }\n throw new Error(`${executable} not found in PATH`);\n };\n})();\n"]}
@@ -0,0 +1,3 @@
1
+ export declare const removeTempDir: (dir: string) => void;
2
+ export declare const withStagingDir: <T>(prefix: string, produce: (dir: string) => T) => T;
3
+ //# sourceMappingURL=staging-dir.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"staging-dir.d.ts","sourceRoot":"","sources":["../../src/internal/staging-dir.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,aAAa,QAAS,MAAM,KAAG,IAE3C,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,CAAC,UAAU,MAAM,WAAW,CAAC,GAAG,EAAE,MAAM,KAAK,CAAC,KAAG,CAO/E,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { mkdtempSync, rmSync } from "node:fs";
2
+ import { tmpdir } from "node:os";
3
+ import { join } from "node:path";
4
+ export const removeTempDir = (dir) => {
5
+ rmSync(dir, { recursive: true, force: true, maxRetries: 5 });
6
+ };
7
+ export const withStagingDir = (prefix, produce) => {
8
+ const dir = mkdtempSync(join(tmpdir(), `gtkx-${prefix}-`));
9
+ try {
10
+ return produce(dir);
11
+ }
12
+ finally {
13
+ removeTempDir(dir);
14
+ }
15
+ };
16
+ //# sourceMappingURL=staging-dir.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"staging-dir.js","sourceRoot":"","sources":["../../src/internal/staging-dir.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,GAAW,EAAQ,EAAE;IAC/C,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;AACjE,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAI,MAAc,EAAE,OAA2B,EAAK,EAAE;IAChF,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,QAAQ,MAAM,GAAG,CAAC,CAAC,CAAC;IAC3D,IAAI,CAAC;QACD,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;YAAS,CAAC;QACP,aAAa,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC;AACL,CAAC,CAAC","sourcesContent":["import { mkdtempSync, rmSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport const removeTempDir = (dir: string): void => {\n rmSync(dir, { recursive: true, force: true, maxRetries: 5 });\n};\n\nexport const withStagingDir = <T>(prefix: string, produce: (dir: string) => T): T => {\n const dir = mkdtempSync(join(tmpdir(), `gtkx-${prefix}-`));\n try {\n return produce(dir);\n } finally {\n removeTempDir(dir);\n }\n};\n"]}
@@ -0,0 +1,2 @@
1
+ export declare const prependXdgDataDir: (dir: string, existing: string | undefined) => string;
2
+ //# sourceMappingURL=xdg-data-dirs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xdg-data-dirs.d.ts","sourceRoot":"","sources":["../../src/internal/xdg-data-dirs.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,iBAAiB,QAAS,MAAM,YAAY,MAAM,GAAG,SAAS,KAAG,MAI7E,CAAC"}
@@ -0,0 +1,8 @@
1
+ const XDG_DATA_DIRS_DEFAULT = "/usr/local/share:/usr/share";
2
+ export const prependXdgDataDir = (dir, existing) => {
3
+ const base = existing === undefined || existing.length === 0 ? XDG_DATA_DIRS_DEFAULT : existing;
4
+ if (base.split(":").includes(dir))
5
+ return base;
6
+ return `${dir}:${base}`;
7
+ };
8
+ //# sourceMappingURL=xdg-data-dirs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xdg-data-dirs.js","sourceRoot":"","sources":["../../src/internal/xdg-data-dirs.ts"],"names":[],"mappings":"AAAA,MAAM,qBAAqB,GAAG,6BAA6B,CAAC;AAE5D,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,GAAW,EAAE,QAA4B,EAAU,EAAE;IACnF,MAAM,IAAI,GAAG,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,QAAQ,CAAC;IAChG,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/C,OAAO,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;AAC5B,CAAC,CAAC","sourcesContent":["const XDG_DATA_DIRS_DEFAULT = \"/usr/local/share:/usr/share\";\n\nexport const prependXdgDataDir = (dir: string, existing: string | undefined): string => {\n const base = existing === undefined || existing.length === 0 ? XDG_DATA_DIRS_DEFAULT : existing;\n if (base.split(\":\").includes(dir)) return base;\n return `${dir}:${base}`;\n};\n"]}
@@ -0,0 +1,23 @@
1
+ export type McpClientOptions = {
2
+ socketPath?: string;
3
+ applicationId: string;
4
+ };
5
+ export declare class McpClient {
6
+ private socket;
7
+ private connection;
8
+ private socketPath;
9
+ private applicationId;
10
+ private reconnectTimer;
11
+ private hasConnected;
12
+ private isStopping;
13
+ private pendingConnectReject;
14
+ private registry;
15
+ constructor(options: McpClientOptions);
16
+ connect(): Promise<void>;
17
+ disconnect(): void;
18
+ private attemptConnect;
19
+ private scheduleReconnect;
20
+ private register;
21
+ private handleRequest;
22
+ }
23
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/mcp/client.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,gBAAgB,GAAG;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;CACzB,CAAC;AAKF,qBAAa,SAAS;IAClB,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,UAAU,CAAmC;IACrD,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,oBAAoB,CAAyC;IACrE,OAAO,CAAC,QAAQ,CAAwB;IAExC,YAAY,OAAO,EAAE,gBAAgB,EAGpC;IAEK,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAc7B;IAED,UAAU,IAAI,IAAI,CAkBjB;IAED,OAAO,CAAC,cAAc;IA0DtB,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,QAAQ;YAeF,aAAa;CA2B9B"}
@@ -0,0 +1,157 @@
1
+ import * as net from "node:net";
2
+ import * as Gio from "@gtkx/gi/gio";
3
+ import * as Gtk from "@gtkx/gi/gtk";
4
+ import { DEFAULT_SOCKET_PATH, ErrorCode, ProtocolConnection, ProtocolError } from "@gtkx/mcp/internal";
5
+ import { error, errorMessage, info, normalizeError, warn } from "@gtkx/utils";
6
+ import { dispatch } from "./handlers.js";
7
+ import { WidgetRegistry } from "./widget-registry.js";
8
+ const RECONNECT_DELAY_MS = 2000;
9
+ const REGISTER_TIMEOUT_MS = 30000;
10
+ export class McpClient {
11
+ socket = null;
12
+ connection = null;
13
+ socketPath;
14
+ applicationId;
15
+ reconnectTimer = null;
16
+ hasConnected = false;
17
+ isStopping = false;
18
+ pendingConnectReject = null;
19
+ registry = new WidgetRegistry();
20
+ constructor(options) {
21
+ this.socketPath = options.socketPath ?? DEFAULT_SOCKET_PATH;
22
+ this.applicationId = options.applicationId;
23
+ }
24
+ async connect() {
25
+ return new Promise((resolve, reject) => {
26
+ this.pendingConnectReject = reject;
27
+ this.attemptConnect(() => {
28
+ this.pendingConnectReject = null;
29
+ resolve();
30
+ }, (error) => {
31
+ this.pendingConnectReject = null;
32
+ reject(error);
33
+ });
34
+ });
35
+ }
36
+ disconnect() {
37
+ this.isStopping = true;
38
+ if (this.pendingConnectReject) {
39
+ this.pendingConnectReject(new Error("Client disconnected before connection registered"));
40
+ this.pendingConnectReject = null;
41
+ }
42
+ if (this.reconnectTimer) {
43
+ clearTimeout(this.reconnectTimer);
44
+ this.reconnectTimer = null;
45
+ }
46
+ this.connection?.rejectPending(new Error("Client disconnected"));
47
+ if (this.socket) {
48
+ this.connection?.write({ id: crypto.randomUUID(), method: "app.unregister" });
49
+ this.socket.destroy();
50
+ this.socket = null;
51
+ }
52
+ this.connection = null;
53
+ this.hasConnected = false;
54
+ }
55
+ attemptConnect(onSuccess, onError) {
56
+ let settled = false;
57
+ const settle = (callback, ...args) => {
58
+ if (settled)
59
+ return;
60
+ settled = true;
61
+ callback?.(...args);
62
+ };
63
+ const socket = net.createConnection(this.socketPath, () => {
64
+ info(`Connected to MCP server at ${this.socketPath}`);
65
+ this.hasConnected = true;
66
+ this.register()
67
+ .then(() => {
68
+ info("Registered with MCP server");
69
+ settle(onSuccess);
70
+ })
71
+ .catch((cause) => {
72
+ error("Failed to register with MCP server:", cause.message);
73
+ settle(onError, normalizeError(cause));
74
+ });
75
+ });
76
+ const connection = ProtocolConnection.fromSocket(socket, {
77
+ onClose: () => {
78
+ if (this.hasConnected) {
79
+ info("Disconnected from MCP server");
80
+ this.hasConnected = false;
81
+ }
82
+ this.socket = null;
83
+ this.connection = null;
84
+ this.scheduleReconnect();
85
+ },
86
+ onError: (socketError) => {
87
+ const code = socketError.code;
88
+ const isDisconnectError = code === "ENOENT" || code === "ECONNREFUSED" || code === "EPIPE" || code === "ECONNRESET";
89
+ if (isDisconnectError) {
90
+ this.scheduleReconnect();
91
+ }
92
+ else {
93
+ error("Socket error:", socketError.message);
94
+ }
95
+ settle(onError, socketError);
96
+ },
97
+ });
98
+ connection.on("request", (request) => {
99
+ this.handleRequest(request).catch((cause) => {
100
+ error("Error handling request:", cause);
101
+ });
102
+ });
103
+ connection.on("invalid", ({ error: parseError }) => {
104
+ warn(`Received invalid JSON from MCP server: ${parseError.message}`);
105
+ });
106
+ this.socket = socket;
107
+ this.connection = connection;
108
+ }
109
+ scheduleReconnect() {
110
+ if (this.reconnectTimer || this.isStopping)
111
+ return;
112
+ this.reconnectTimer = setTimeout(() => {
113
+ this.reconnectTimer = null;
114
+ this.attemptConnect();
115
+ }, RECONNECT_DELAY_MS);
116
+ }
117
+ register() {
118
+ if (!this.connection) {
119
+ return Promise.reject(new Error("Connection not initialized"));
120
+ }
121
+ return this.connection.send("app.register", {
122
+ applicationId: this.applicationId,
123
+ pid: process.pid,
124
+ projectRoot: process.cwd(),
125
+ }, REGISTER_TIMEOUT_MS);
126
+ }
127
+ async handleRequest(request) {
128
+ const { id, method, params } = request;
129
+ const connection = this.connection;
130
+ if (!connection)
131
+ return;
132
+ try {
133
+ const defaultApp = Gio.Application.getDefault();
134
+ if (!(defaultApp instanceof Gtk.Application)) {
135
+ throw new TypeError("Application not initialized");
136
+ }
137
+ this.registry.refresh();
138
+ const result = await dispatch(method, params, { app: defaultApp, registry: this.registry });
139
+ connection.write({ id, result });
140
+ }
141
+ catch (error) {
142
+ if (error instanceof ProtocolError) {
143
+ connection.write({ id, error: error.toErrorObject() });
144
+ }
145
+ else {
146
+ connection.write({
147
+ id,
148
+ error: {
149
+ code: ErrorCode.INTERNAL_ERROR,
150
+ message: errorMessage(error),
151
+ },
152
+ });
153
+ }
154
+ }
155
+ }
156
+ }
157
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/mcp/client.ts"],"names":[],"mappings":"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","sourcesContent":["import * as net from \"node:net\";\nimport * as Gio from \"@gtkx/gi/gio\";\nimport * as Gtk from \"@gtkx/gi/gtk\";\nimport { DEFAULT_SOCKET_PATH, ErrorCode, ProtocolConnection, ProtocolError, type Request } from \"@gtkx/mcp/internal\";\nimport { error, errorMessage, info, normalizeError, warn } from \"@gtkx/utils\";\nimport { dispatch } from \"./handlers.js\";\nimport { WidgetRegistry } from \"./widget-registry.js\";\n\nexport type McpClientOptions = {\n socketPath?: string;\n applicationId: string;\n};\n\nconst RECONNECT_DELAY_MS = 2000;\nconst REGISTER_TIMEOUT_MS = 30000;\n\nexport class McpClient {\n private socket: net.Socket | null = null;\n private connection: ProtocolConnection | null = null;\n private socketPath: string;\n private applicationId: string;\n private reconnectTimer: NodeJS.Timeout | null = null;\n private hasConnected = false;\n private isStopping = false;\n private pendingConnectReject: ((error: Error) => void) | null = null;\n private registry = new WidgetRegistry();\n\n constructor(options: McpClientOptions) {\n this.socketPath = options.socketPath ?? DEFAULT_SOCKET_PATH;\n this.applicationId = options.applicationId;\n }\n\n async connect(): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n this.pendingConnectReject = reject;\n this.attemptConnect(\n () => {\n this.pendingConnectReject = null;\n resolve();\n },\n (error) => {\n this.pendingConnectReject = null;\n reject(error);\n },\n );\n });\n }\n\n disconnect(): void {\n this.isStopping = true;\n if (this.pendingConnectReject) {\n this.pendingConnectReject(new Error(\"Client disconnected before connection registered\"));\n this.pendingConnectReject = null;\n }\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n this.connection?.rejectPending(new Error(\"Client disconnected\"));\n if (this.socket) {\n this.connection?.write({ id: crypto.randomUUID(), method: \"app.unregister\" });\n this.socket.destroy();\n this.socket = null;\n }\n this.connection = null;\n this.hasConnected = false;\n }\n\n private attemptConnect(onSuccess?: () => void, onError?: (error: Error) => void): void {\n let settled = false;\n\n const settle = <T extends unknown[]>(callback: ((...args: T) => void) | undefined, ...args: T) => {\n if (settled) return;\n settled = true;\n callback?.(...args);\n };\n\n const socket = net.createConnection(this.socketPath, () => {\n info(`Connected to MCP server at ${this.socketPath}`);\n this.hasConnected = true;\n this.register()\n .then(() => {\n info(\"Registered with MCP server\");\n settle(onSuccess);\n })\n .catch((cause) => {\n error(\"Failed to register with MCP server:\", cause.message);\n settle(onError, normalizeError(cause));\n });\n });\n\n const connection = ProtocolConnection.fromSocket(socket, {\n onClose: () => {\n if (this.hasConnected) {\n info(\"Disconnected from MCP server\");\n this.hasConnected = false;\n }\n this.socket = null;\n this.connection = null;\n this.scheduleReconnect();\n },\n onError: (socketError) => {\n const code = (socketError as NodeJS.ErrnoException).code;\n const isDisconnectError =\n code === \"ENOENT\" || code === \"ECONNREFUSED\" || code === \"EPIPE\" || code === \"ECONNRESET\";\n if (isDisconnectError) {\n this.scheduleReconnect();\n } else {\n error(\"Socket error:\", socketError.message);\n }\n settle(onError, socketError);\n },\n });\n connection.on(\"request\", (request) => {\n this.handleRequest(request).catch((cause) => {\n error(\"Error handling request:\", cause);\n });\n });\n connection.on(\"invalid\", ({ error: parseError }) => {\n warn(`Received invalid JSON from MCP server: ${parseError.message}`);\n });\n\n this.socket = socket;\n this.connection = connection;\n }\n\n private scheduleReconnect(): void {\n if (this.reconnectTimer || this.isStopping) return;\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n this.attemptConnect();\n }, RECONNECT_DELAY_MS);\n }\n\n private register(): Promise<unknown> {\n if (!this.connection) {\n return Promise.reject(new Error(\"Connection not initialized\"));\n }\n return this.connection.send(\n \"app.register\",\n {\n applicationId: this.applicationId,\n pid: process.pid,\n projectRoot: process.cwd(),\n },\n REGISTER_TIMEOUT_MS,\n );\n }\n\n private async handleRequest(request: Request): Promise<void> {\n const { id, method, params } = request;\n const connection = this.connection;\n if (!connection) return;\n\n try {\n const defaultApp = Gio.Application.getDefault();\n if (!(defaultApp instanceof Gtk.Application)) {\n throw new TypeError(\"Application not initialized\");\n }\n this.registry.refresh();\n const result = await dispatch(method, params, { app: defaultApp, registry: this.registry });\n connection.write({ id, result });\n } catch (error) {\n if (error instanceof ProtocolError) {\n connection.write({ id, error: error.toErrorObject() });\n } else {\n connection.write({\n id,\n error: {\n code: ErrorCode.INTERNAL_ERROR,\n message: errorMessage(error),\n },\n });\n }\n }\n }\n}\n"]}
@@ -0,0 +1,8 @@
1
+ import * as Gtk from "@gtkx/gi/gtk";
2
+ import type { WidgetRegistry } from "./widget-registry.js";
3
+ export type HandlerContext = {
4
+ app: Gtk.Application;
5
+ registry: WidgetRegistry;
6
+ };
7
+ export declare const dispatch: (method: string, params: unknown, ctx: HandlerContext) => Promise<unknown>;
8
+ //# sourceMappingURL=handlers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../../src/mcp/handlers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAYpC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,MAAM,MAAM,cAAc,GAAG;IACzB,GAAG,EAAE,GAAG,CAAC,WAAW,CAAC;IACrB,QAAQ,EAAE,cAAc,CAAC;CAC5B,CAAC;AAmIF,eAAO,MAAM,QAAQ,WAAkB,MAAM,UAAU,OAAO,OAAO,cAAc,KAAG,OAAO,CAAC,OAAO,CAKpG,CAAC"}
@@ -0,0 +1,119 @@
1
+ import { mkdirSync, writeFileSync } from "node:fs";
2
+ import { dirname } from "node:path";
3
+ import * as Gtk from "@gtkx/gi/gtk";
4
+ import { invalidRequestError, methodNotFoundError, ServerRequestParamsSchemas, widgetNotFoundError, } from "@gtkx/mcp/internal";
5
+ import { serializeWidget } from "./serialize-widget.js";
6
+ import { loadTestingModule } from "./testing-loader.js";
7
+ const validated = (schema, handler) => {
8
+ return (ctx, params) => {
9
+ const parsed = schema.safeParse(params ?? {});
10
+ if (!parsed.success) {
11
+ throw invalidRequestError(parsed.error.message);
12
+ }
13
+ return handler(ctx, parsed.data);
14
+ };
15
+ };
16
+ const requireWidget = (registry, widgetId) => {
17
+ if (widgetId === undefined) {
18
+ throw widgetNotFoundError("undefined");
19
+ }
20
+ const widget = registry.get(widgetId);
21
+ if (!widget) {
22
+ throw widgetNotFoundError(widgetId);
23
+ }
24
+ return widget;
25
+ };
26
+ const extractSignalArg = (arg) => {
27
+ const isTypedArg = typeof arg === "object" && arg !== null && "type" in arg && "value" in arg;
28
+ return isTypedArg ? arg.value : arg;
29
+ };
30
+ const handleQuery = async ({ app, registry }, params) => {
31
+ const testing = await loadTestingModule();
32
+ let widgets = [];
33
+ switch (params.by) {
34
+ case "role": {
35
+ const roleValue = typeof params.value === "string"
36
+ ? Gtk.AccessibleRole[params.value]
37
+ : params.value;
38
+ widgets = await testing.findAllByRole(app, roleValue, params.options);
39
+ break;
40
+ }
41
+ case "text":
42
+ widgets = await testing.findAllByText(app, String(params.value), params.options);
43
+ break;
44
+ case "name":
45
+ widgets = await testing.findAllByName(app, String(params.value), params.options);
46
+ break;
47
+ case "labelText":
48
+ widgets = await testing.findAllByLabelText(app, String(params.value), params.options);
49
+ break;
50
+ }
51
+ return { widgets: widgets.map((w) => serializeWidget(w, (widget) => registry.idFor(widget), testing)) };
52
+ };
53
+ const defaultScreenshotTarget = (registry) => {
54
+ const [toplevel] = registry.toplevels();
55
+ if (!toplevel) {
56
+ throw new Error("No windows available for screenshot");
57
+ }
58
+ return toplevel;
59
+ };
60
+ const handleScreenshot = async ({ registry }, params) => {
61
+ const testing = await loadTestingModule();
62
+ const target = params.windowId ? requireWidget(registry, params.windowId) : defaultScreenshotTarget(registry);
63
+ const result = await testing.screenshot(target);
64
+ if (params.path) {
65
+ mkdirSync(dirname(params.path), { recursive: true });
66
+ writeFileSync(params.path, Buffer.from(result.data, "base64"));
67
+ return { data: result.data, mimeType: result.mimeType, savedPath: params.path };
68
+ }
69
+ return { data: result.data, mimeType: result.mimeType };
70
+ };
71
+ const HANDLERS = {
72
+ "app.getWindows": validated(ServerRequestParamsSchemas["app.getWindows"], async ({ registry }) => ({
73
+ windows: registry.toplevels().map((window) => ({
74
+ id: registry.idFor(window),
75
+ title: window.getTitle(),
76
+ })),
77
+ })),
78
+ "widget.getTree": validated(ServerRequestParamsSchemas["widget.getTree"], async ({ app, registry }) => {
79
+ const testing = await loadTestingModule();
80
+ return { tree: testing.prettyWidget(app, { getId: (w) => registry.idFor(w), highlight: false }) };
81
+ }),
82
+ "widget.query": validated(ServerRequestParamsSchemas["widget.query"], handleQuery),
83
+ "widget.getProps": validated(ServerRequestParamsSchemas["widget.getProps"], async ({ registry }, params) => {
84
+ const testing = await loadTestingModule();
85
+ const widget = requireWidget(registry, params.widgetId);
86
+ return serializeWidget(widget, (target) => registry.idFor(target), testing);
87
+ }),
88
+ "widget.click": validated(ServerRequestParamsSchemas["widget.click"], async ({ registry }, params) => {
89
+ const testing = await loadTestingModule();
90
+ const widget = requireWidget(registry, params.widgetId);
91
+ await testing.userEvent.click(widget);
92
+ return { success: true };
93
+ }),
94
+ "widget.type": validated(ServerRequestParamsSchemas["widget.type"], async ({ registry }, params) => {
95
+ const testing = await loadTestingModule();
96
+ const widget = requireWidget(registry, params.widgetId);
97
+ if (params.clear) {
98
+ await testing.userEvent.clear(widget);
99
+ }
100
+ await testing.userEvent.type(widget, params.text);
101
+ return { success: true };
102
+ }),
103
+ "widget.fireEvent": validated(ServerRequestParamsSchemas["widget.fireEvent"], async ({ registry }, params) => {
104
+ const testing = await loadTestingModule();
105
+ const widget = requireWidget(registry, params.widgetId);
106
+ const signalArgs = (params.args ?? []).map(extractSignalArg);
107
+ await testing.fireEvent(widget, params.signal, ...signalArgs);
108
+ return { success: true };
109
+ }),
110
+ "widget.screenshot": validated(ServerRequestParamsSchemas["widget.screenshot"], handleScreenshot),
111
+ };
112
+ const isServerInitiatedMethod = (method) => Object.hasOwn(ServerRequestParamsSchemas, method);
113
+ export const dispatch = async (method, params, ctx) => {
114
+ if (!isServerInitiatedMethod(method)) {
115
+ throw methodNotFoundError(method);
116
+ }
117
+ return HANDLERS[method](ctx, params);
118
+ };
119
+ //# sourceMappingURL=handlers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handlers.js","sourceRoot":"","sources":["../../src/mcp/handlers.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport * as Gtk from \"@gtkx/gi/gtk\";\nimport {\n invalidRequestError,\n methodNotFoundError,\n type ParamsSchema,\n type ServerInitiatedMethod,\n type ServerRequestParams,\n ServerRequestParamsSchemas,\n widgetNotFoundError,\n} from \"@gtkx/mcp/internal\";\nimport { serializeWidget } from \"./serialize-widget.js\";\nimport { loadTestingModule } from \"./testing-loader.js\";\nimport type { WidgetRegistry } from \"./widget-registry.js\";\n\nexport type HandlerContext = {\n app: Gtk.Application;\n registry: WidgetRegistry;\n};\n\ntype ValidatedHandler = (ctx: HandlerContext, params: unknown) => Promise<unknown>;\n\nconst validated = <Params>(\n schema: ParamsSchema<Params>,\n handler: (ctx: HandlerContext, params: Params) => Promise<unknown>,\n): ValidatedHandler => {\n return (ctx, params) => {\n const parsed = schema.safeParse(params ?? {});\n if (!parsed.success) {\n throw invalidRequestError(parsed.error.message);\n }\n return handler(ctx, parsed.data);\n };\n};\n\nconst requireWidget = (registry: WidgetRegistry, widgetId: string | undefined): Gtk.Widget => {\n if (widgetId === undefined) {\n throw widgetNotFoundError(\"undefined\");\n }\n const widget = registry.get(widgetId);\n if (!widget) {\n throw widgetNotFoundError(widgetId);\n }\n return widget;\n};\n\nconst extractSignalArg = (arg: unknown): unknown => {\n const isTypedArg = typeof arg === \"object\" && arg !== null && \"type\" in arg && \"value\" in arg;\n return isTypedArg ? (arg as { value: unknown }).value : arg;\n};\n\nconst handleQuery = async (\n { app, registry }: HandlerContext,\n params: ServerRequestParams<\"widget.query\">,\n): Promise<unknown> => {\n const testing = await loadTestingModule();\n let widgets: Gtk.Widget[] = [];\n\n switch (params.by) {\n case \"role\": {\n const roleValue =\n typeof params.value === \"string\"\n ? Gtk.AccessibleRole[params.value as keyof typeof Gtk.AccessibleRole]\n : params.value;\n widgets = await testing.findAllByRole(app, roleValue as Gtk.AccessibleRole, params.options);\n break;\n }\n case \"text\":\n widgets = await testing.findAllByText(app, String(params.value), params.options);\n break;\n case \"name\":\n widgets = await testing.findAllByName(app, String(params.value), params.options);\n break;\n case \"labelText\":\n widgets = await testing.findAllByLabelText(app, String(params.value), params.options);\n break;\n }\n\n return { widgets: widgets.map((w) => serializeWidget(w, (widget) => registry.idFor(widget), testing)) };\n};\n\nconst defaultScreenshotTarget = (registry: WidgetRegistry): Gtk.Widget => {\n const [toplevel] = registry.toplevels();\n if (!toplevel) {\n throw new Error(\"No windows available for screenshot\");\n }\n return toplevel;\n};\n\nconst handleScreenshot = async (\n { registry }: HandlerContext,\n params: ServerRequestParams<\"widget.screenshot\">,\n): Promise<unknown> => {\n const testing = await loadTestingModule();\n const target = params.windowId ? requireWidget(registry, params.windowId) : defaultScreenshotTarget(registry);\n const result = await testing.screenshot(target);\n if (params.path) {\n mkdirSync(dirname(params.path), { recursive: true });\n writeFileSync(params.path, Buffer.from(result.data, \"base64\"));\n return { data: result.data, mimeType: result.mimeType, savedPath: params.path };\n }\n return { data: result.data, mimeType: result.mimeType };\n};\n\nconst HANDLERS: Record<ServerInitiatedMethod, ValidatedHandler> = {\n \"app.getWindows\": validated(ServerRequestParamsSchemas[\"app.getWindows\"], async ({ registry }) => ({\n windows: registry.toplevels().map((window) => ({\n id: registry.idFor(window),\n title: window.getTitle(),\n })),\n })),\n \"widget.getTree\": validated(ServerRequestParamsSchemas[\"widget.getTree\"], async ({ app, registry }) => {\n const testing = await loadTestingModule();\n return { tree: testing.prettyWidget(app, { getId: (w) => registry.idFor(w), highlight: false }) };\n }),\n \"widget.query\": validated(ServerRequestParamsSchemas[\"widget.query\"], handleQuery),\n \"widget.getProps\": validated(ServerRequestParamsSchemas[\"widget.getProps\"], async ({ registry }, params) => {\n const testing = await loadTestingModule();\n const widget = requireWidget(registry, params.widgetId);\n return serializeWidget(widget, (target) => registry.idFor(target), testing);\n }),\n \"widget.click\": validated(ServerRequestParamsSchemas[\"widget.click\"], async ({ registry }, params) => {\n const testing = await loadTestingModule();\n const widget = requireWidget(registry, params.widgetId);\n await testing.userEvent.click(widget);\n return { success: true };\n }),\n \"widget.type\": validated(ServerRequestParamsSchemas[\"widget.type\"], async ({ registry }, params) => {\n const testing = await loadTestingModule();\n const widget = requireWidget(registry, params.widgetId);\n if (params.clear) {\n await testing.userEvent.clear(widget);\n }\n await testing.userEvent.type(widget, params.text);\n return { success: true };\n }),\n \"widget.fireEvent\": validated(ServerRequestParamsSchemas[\"widget.fireEvent\"], async ({ registry }, params) => {\n const testing = await loadTestingModule();\n const widget = requireWidget(registry, params.widgetId);\n const signalArgs = (params.args ?? []).map(extractSignalArg);\n await testing.fireEvent(widget, params.signal, ...signalArgs);\n return { success: true };\n }),\n \"widget.screenshot\": validated(ServerRequestParamsSchemas[\"widget.screenshot\"], handleScreenshot),\n};\n\nconst isServerInitiatedMethod = (method: string): method is ServerInitiatedMethod =>\n Object.hasOwn(ServerRequestParamsSchemas, method);\n\nexport const dispatch = async (method: string, params: unknown, ctx: HandlerContext): Promise<unknown> => {\n if (!isServerInitiatedMethod(method)) {\n throw methodNotFoundError(method);\n }\n return HANDLERS[method](ctx, params);\n};\n"]}
@@ -0,0 +1,4 @@
1
+ import { McpClient } from "./client.js";
2
+ export declare const startMcpClient: (applicationId: string) => Promise<McpClient>;
3
+ export declare const stopMcpClient: () => void;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAIxC,eAAO,MAAM,cAAc,kBAAyB,MAAM,KAAG,OAAO,CAAC,SAAS,CAU7E,CAAC;AAEF,eAAO,MAAM,aAAa,QAAO,IAKhC,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { McpClient } from "./client.js";
2
+ let globalClient = null;
3
+ export const startMcpClient = async (applicationId) => {
4
+ if (globalClient) {
5
+ return globalClient;
6
+ }
7
+ globalClient = new McpClient({ applicationId });
8
+ await globalClient.connect().catch(() => { });
9
+ return globalClient;
10
+ };
11
+ export const stopMcpClient = () => {
12
+ if (globalClient) {
13
+ globalClient.disconnect();
14
+ globalClient = null;
15
+ }
16
+ };
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,IAAI,YAAY,GAAqB,IAAI,CAAC;AAE1C,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EAAE,aAAqB,EAAsB,EAAE;IAC9E,IAAI,YAAY,EAAE,CAAC;QACf,OAAO,YAAY,CAAC;IACxB,CAAC;IAED,YAAY,GAAG,IAAI,SAAS,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC;IAEhD,MAAM,YAAY,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAE7C,OAAO,YAAY,CAAC;AACxB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,GAAS,EAAE;IACpC,IAAI,YAAY,EAAE,CAAC;QACf,YAAY,CAAC,UAAU,EAAE,CAAC;QAC1B,YAAY,GAAG,IAAI,CAAC;IACxB,CAAC;AACL,CAAC,CAAC","sourcesContent":["import { McpClient } from \"./client.js\";\n\nlet globalClient: McpClient | null = null;\n\nexport const startMcpClient = async (applicationId: string): Promise<McpClient> => {\n if (globalClient) {\n return globalClient;\n }\n\n globalClient = new McpClient({ applicationId });\n\n await globalClient.connect().catch(() => {});\n\n return globalClient;\n};\n\nexport const stopMcpClient = (): void => {\n if (globalClient) {\n globalClient.disconnect();\n globalClient = null;\n }\n};\n"]}
@@ -0,0 +1,10 @@
1
+ import type * as Gtk from "@gtkx/gi/gtk";
2
+ import type { SerializedWidget } from "@gtkx/mcp/internal";
3
+ type WidgetIdResolver = (widget: Gtk.Widget) => string;
4
+ export type WidgetFormatting = {
5
+ formatRole(role: Gtk.AccessibleRole): string;
6
+ getWidgetNodeText(widget: Gtk.Widget): string | null;
7
+ };
8
+ export declare const serializeWidget: (widget: Gtk.Widget, idFor: WidgetIdResolver, testing: WidgetFormatting) => SerializedWidget;
9
+ export {};
10
+ //# sourceMappingURL=serialize-widget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serialize-widget.d.ts","sourceRoot":"","sources":["../../src/mcp/serialize-widget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,GAAG,MAAM,cAAc,CAAC;AACzC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,KAAK,gBAAgB,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,KAAK,MAAM,CAAC;AAEvD,MAAM,MAAM,gBAAgB,GAAG;IAC3B,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,cAAc,GAAG,MAAM,CAAC;IAC7C,iBAAiB,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;CACxD,CAAC;AAEF,eAAO,MAAM,eAAe,WAChB,GAAG,CAAC,MAAM,SACX,gBAAgB,WACd,gBAAgB,KAC1B,gBAmBF,CAAC"}
@@ -0,0 +1,20 @@
1
+ export const serializeWidget = (widget, idFor, testing) => {
2
+ const children = [];
3
+ let child = widget.getFirstChild();
4
+ while (child) {
5
+ children.push(serializeWidget(child, idFor, testing));
6
+ child = child.getNextSibling();
7
+ }
8
+ return {
9
+ id: idFor(widget),
10
+ type: widget.constructor.name,
11
+ role: testing.formatRole(widget.getAccessibleRole()),
12
+ name: widget.getName() || null,
13
+ text: testing.getWidgetNodeText(widget),
14
+ sensitive: widget.getSensitive(),
15
+ visible: widget.getVisible(),
16
+ cssClasses: widget.getCssClasses(),
17
+ children,
18
+ };
19
+ };
20
+ //# sourceMappingURL=serialize-widget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serialize-widget.js","sourceRoot":"","sources":["../../src/mcp/serialize-widget.ts"],"names":[],"mappings":"AAUA,MAAM,CAAC,MAAM,eAAe,GAAG,CAC3B,MAAkB,EAClB,KAAuB,EACvB,OAAyB,EACT,EAAE;IAClB,MAAM,QAAQ,GAAuB,EAAE,CAAC;IACxC,IAAI,KAAK,GAAG,MAAM,CAAC,aAAa,EAAE,CAAC;IACnC,OAAO,KAAK,EAAE,CAAC;QACX,QAAQ,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;QACtD,KAAK,GAAG,KAAK,CAAC,cAAc,EAAE,CAAC;IACnC,CAAC;IAED,OAAO;QACH,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC,WAAW,CAAC,IAAI;QAC7B,IAAI,EAAE,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC;QACpD,IAAI,EAAE,MAAM,CAAC,OAAO,EAAE,IAAI,IAAI;QAC9B,IAAI,EAAE,OAAO,CAAC,iBAAiB,CAAC,MAAM,CAAC;QACvC,SAAS,EAAE,MAAM,CAAC,YAAY,EAAE;QAChC,OAAO,EAAE,MAAM,CAAC,UAAU,EAAE;QAC5B,UAAU,EAAE,MAAM,CAAC,aAAa,EAAE;QAClC,QAAQ;KACX,CAAC;AACN,CAAC,CAAC","sourcesContent":["import type * as Gtk from \"@gtkx/gi/gtk\";\nimport type { SerializedWidget } from \"@gtkx/mcp/internal\";\n\ntype WidgetIdResolver = (widget: Gtk.Widget) => string;\n\nexport type WidgetFormatting = {\n formatRole(role: Gtk.AccessibleRole): string;\n getWidgetNodeText(widget: Gtk.Widget): string | null;\n};\n\nexport const serializeWidget = (\n widget: Gtk.Widget,\n idFor: WidgetIdResolver,\n testing: WidgetFormatting,\n): SerializedWidget => {\n const children: SerializedWidget[] = [];\n let child = widget.getFirstChild();\n while (child) {\n children.push(serializeWidget(child, idFor, testing));\n child = child.getNextSibling();\n }\n\n return {\n id: idFor(widget),\n type: widget.constructor.name,\n role: testing.formatRole(widget.getAccessibleRole()),\n name: widget.getName() || null,\n text: testing.getWidgetNodeText(widget),\n sensitive: widget.getSensitive(),\n visible: widget.getVisible(),\n cssClasses: widget.getCssClasses(),\n children,\n };\n};\n"]}