@waica/cli 0.3.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 (231) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +64 -0
  3. package/dist/cli.js +184 -0
  4. package/dist/editor/assets/abap-08VXUWAP.js +1 -0
  5. package/dist/editor/assets/apex-BWPQTe0t.js +1 -0
  6. package/dist/editor/assets/azcli-Bc_sGQ0U.js +1 -0
  7. package/dist/editor/assets/bat-i0X4ZdIN.js +1 -0
  8. package/dist/editor/assets/bicep-B5-_aFwp.js +2 -0
  9. package/dist/editor/assets/cameligo-DMUM7wLl.js +1 -0
  10. package/dist/editor/assets/clojure-Cm7r79vr.js +1 -0
  11. package/dist/editor/assets/codicon-DCmgc-ay.ttf +0 -0
  12. package/dist/editor/assets/coffee-Ba7i2nA0.js +1 -0
  13. package/dist/editor/assets/cpp-C7h46wYY.js +1 -0
  14. package/dist/editor/assets/csharp-BKxtCVv1.js +1 -0
  15. package/dist/editor/assets/csp-bTuwJoIa.js +1 -0
  16. package/dist/editor/assets/css-DIMkf-bt.js +3 -0
  17. package/dist/editor/assets/css.worker-Fwwr_HdT.js +88 -0
  18. package/dist/editor/assets/cssMode-CQE-WdwL.js +4 -0
  19. package/dist/editor/assets/cypher-CVaqCwHa.js +1 -0
  20. package/dist/editor/assets/dart-onAF5SnQ.js +1 -0
  21. package/dist/editor/assets/dockerfile-DZFCIeNp.js +1 -0
  22. package/dist/editor/assets/ecl-D05T4iGw.js +1 -0
  23. package/dist/editor/assets/editor.worker-DsBDrWS5.js +12 -0
  24. package/dist/editor/assets/elixir-6RTg0lbw.js +1 -0
  25. package/dist/editor/assets/flow9-C5_-GSwl.js +1 -0
  26. package/dist/editor/assets/freemarker2-CYgdVabn.js +3 -0
  27. package/dist/editor/assets/fsharp-C8Ef5oNN.js +1 -0
  28. package/dist/editor/assets/go-C-y9NEjX.js +1 -0
  29. package/dist/editor/assets/graphql-fmXr3nnJ.js +1 -0
  30. package/dist/editor/assets/handlebars-DdeORCJD.js +1 -0
  31. package/dist/editor/assets/hcl-CpzslTdj.js +1 -0
  32. package/dist/editor/assets/html-DTIAGV84.js +1 -0
  33. package/dist/editor/assets/html.worker-B3Ztmmz2.js +495 -0
  34. package/dist/editor/assets/htmlMode-CRV3iBih.js +4 -0
  35. package/dist/editor/assets/index-Btzc6zxr.css +1 -0
  36. package/dist/editor/assets/index-Dhkqk31v.js +11016 -0
  37. package/dist/editor/assets/ini-sBoK_t0W.js +1 -0
  38. package/dist/editor/assets/java-BEtHBSE6.js +1 -0
  39. package/dist/editor/assets/javascript-dxBW86cl.js +1 -0
  40. package/dist/editor/assets/json.worker-PWQxM7ZO.js +51 -0
  41. package/dist/editor/assets/jsonMode-DFA5-FFK.js +10 -0
  42. package/dist/editor/assets/julia-Bri6UV-V.js +1 -0
  43. package/dist/editor/assets/kotlin-B0qVs-E9.js +1 -0
  44. package/dist/editor/assets/less-B9JPFI3C.js +2 -0
  45. package/dist/editor/assets/lexon-CfSJPG6W.js +1 -0
  46. package/dist/editor/assets/liquid-CScWaXYV.js +1 -0
  47. package/dist/editor/assets/lua-CsQS60Ue.js +1 -0
  48. package/dist/editor/assets/m3-D-oSqn_W.js +1 -0
  49. package/dist/editor/assets/markdown-Cimd5fb3.js +1 -0
  50. package/dist/editor/assets/mdx-Bvp84SqA.js +1 -0
  51. package/dist/editor/assets/mips-CIPQ_RoX.js +1 -0
  52. package/dist/editor/assets/msdax-DauUninz.js +1 -0
  53. package/dist/editor/assets/mysql-SOo6toE5.js +1 -0
  54. package/dist/editor/assets/objective-c-FvmIjYaQ.js +1 -0
  55. package/dist/editor/assets/pascal-DrH0SRf2.js +1 -0
  56. package/dist/editor/assets/pascaligo-D-ptJ9y-.js +1 -0
  57. package/dist/editor/assets/perl-oz_6vUea.js +1 -0
  58. package/dist/editor/assets/pgsql-DTj74zXo.js +1 -0
  59. package/dist/editor/assets/php-nr791fC2.js +1 -0
  60. package/dist/editor/assets/pla-CopQ2nXW.js +1 -0
  61. package/dist/editor/assets/postiats-43DmfD33.js +1 -0
  62. package/dist/editor/assets/powerquery-D3hlyOfw.js +1 -0
  63. package/dist/editor/assets/powershell-DmHpPYUd.js +1 -0
  64. package/dist/editor/assets/protobuf-C531GsRP.js +2 -0
  65. package/dist/editor/assets/pug-Z5eAx3Zn.js +1 -0
  66. package/dist/editor/assets/python-CG-OtvFa.js +1 -0
  67. package/dist/editor/assets/qsharp-DkqhCAOL.js +1 -0
  68. package/dist/editor/assets/r-BwWrilGY.js +1 -0
  69. package/dist/editor/assets/razor-r-iUEZPj.js +1 -0
  70. package/dist/editor/assets/redis-ClamHrr6.js +1 -0
  71. package/dist/editor/assets/redshift-DT7zqm-g.js +1 -0
  72. package/dist/editor/assets/restructuredtext-BYgofb2h.js +1 -0
  73. package/dist/editor/assets/ruby-DezsRK8O.js +1 -0
  74. package/dist/editor/assets/rust-DdL9SqIa.js +1 -0
  75. package/dist/editor/assets/sb-CcwsVR0C.js +1 -0
  76. package/dist/editor/assets/scala-DHpiXF5c.js +1 -0
  77. package/dist/editor/assets/scheme-BeGwcela.js +1 -0
  78. package/dist/editor/assets/scss-gp-XZpBa.js +3 -0
  79. package/dist/editor/assets/shell-CC2rA5mh.js +1 -0
  80. package/dist/editor/assets/solidity-BEEn4gHE.js +1 -0
  81. package/dist/editor/assets/sophia-CRfGWb83.js +1 -0
  82. package/dist/editor/assets/sparql-D_Lu-MrJ.js +1 -0
  83. package/dist/editor/assets/sql-NEE52Syq.js +1 -0
  84. package/dist/editor/assets/st-DbInun42.js +1 -0
  85. package/dist/editor/assets/swift-Bxkupp3x.js +1 -0
  86. package/dist/editor/assets/systemverilog-Bz4Y3fRF.js +1 -0
  87. package/dist/editor/assets/tcl-DISqw1ZD.js +1 -0
  88. package/dist/editor/assets/ts.worker-0mEyHVru.js +51339 -0
  89. package/dist/editor/assets/tsMode-Bth1rJwM.js +11 -0
  90. package/dist/editor/assets/twig-De2hgUGE.js +1 -0
  91. package/dist/editor/assets/typescript-tNRuHsoe.js +1 -0
  92. package/dist/editor/assets/typespec-B8J7ngcE.js +1 -0
  93. package/dist/editor/assets/vb-DV3o63ZY.js +1 -0
  94. package/dist/editor/assets/wgsl-DpFanUEy.js +298 -0
  95. package/dist/editor/assets/xml-BCx9e6CK.js +1 -0
  96. package/dist/editor/assets/yaml-Bb-peGP_.js +1 -0
  97. package/dist/editor/index.html +14 -0
  98. package/dist/mcp/archetypes.js +103 -0
  99. package/dist/mcp/cli.js +6 -0
  100. package/dist/mcp/create-project.js +151 -0
  101. package/dist/mcp/introspection.js +201 -0
  102. package/dist/mcp/node_modules/@waica/archetype-platformer/assets/waica-coin.png +0 -0
  103. package/dist/mcp/node_modules/@waica/archetype-platformer/assets/waica-dog.png +0 -0
  104. package/dist/mcp/node_modules/@waica/archetype-platformer/assets/waica-slime.png +0 -0
  105. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/art.d.ts +10 -0
  106. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/art.js +13 -0
  107. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/bundle.d.ts +3 -0
  108. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/bundle.js +10 -0
  109. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/controls.d.ts +5 -0
  110. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/controls.js +12 -0
  111. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/index.d.ts +38 -0
  112. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/index.js +34 -0
  113. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/manifest.d.ts +15 -0
  114. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/manifest.js +26 -0
  115. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/prefabs.d.ts +7 -0
  116. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/prefabs.js +97 -0
  117. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/registry-data.d.ts +5 -0
  118. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/registry-data.js +45 -0
  119. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/registry.d.ts +6 -0
  120. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/registry.js +15 -0
  121. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/scene-default.d.ts +40 -0
  122. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/scene-default.js +93 -0
  123. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/ui.d.ts +10 -0
  124. package/dist/mcp/node_modules/@waica/archetype-platformer/dist/ui.js +24 -0
  125. package/dist/mcp/node_modules/@waica/archetype-platformer/package.json +30 -0
  126. package/dist/mcp/node_modules/@waica/behaviors/dist/chaser.d.ts +59 -0
  127. package/dist/mcp/node_modules/@waica/behaviors/dist/chaser.js +127 -0
  128. package/dist/mcp/node_modules/@waica/behaviors/dist/collectible.d.ts +25 -0
  129. package/dist/mcp/node_modules/@waica/behaviors/dist/collectible.js +27 -0
  130. package/dist/mcp/node_modules/@waica/behaviors/dist/hazard.d.ts +29 -0
  131. package/dist/mcp/node_modules/@waica/behaviors/dist/hazard.js +42 -0
  132. package/dist/mcp/node_modules/@waica/behaviors/dist/index.d.ts +9 -0
  133. package/dist/mcp/node_modules/@waica/behaviors/dist/index.js +9 -0
  134. package/dist/mcp/node_modules/@waica/behaviors/dist/lifetime.d.ts +16 -0
  135. package/dist/mcp/node_modules/@waica/behaviors/dist/lifetime.js +19 -0
  136. package/dist/mcp/node_modules/@waica/behaviors/dist/npc.d.ts +4 -0
  137. package/dist/mcp/node_modules/@waica/behaviors/dist/npc.js +14 -0
  138. package/dist/mcp/node_modules/@waica/behaviors/dist/patrol.d.ts +43 -0
  139. package/dist/mcp/node_modules/@waica/behaviors/dist/patrol.js +68 -0
  140. package/dist/mcp/node_modules/@waica/behaviors/dist/platformer-motor.d.ts +124 -0
  141. package/dist/mcp/node_modules/@waica/behaviors/dist/platformer-motor.js +146 -0
  142. package/dist/mcp/node_modules/@waica/behaviors/dist/player-identity.d.ts +3 -0
  143. package/dist/mcp/node_modules/@waica/behaviors/dist/player-identity.js +5 -0
  144. package/dist/mcp/node_modules/@waica/behaviors/dist/player-states.d.ts +18 -0
  145. package/dist/mcp/node_modules/@waica/behaviors/dist/player-states.js +95 -0
  146. package/dist/mcp/node_modules/@waica/behaviors/dist/respawnable.d.ts +23 -0
  147. package/dist/mcp/node_modules/@waica/behaviors/dist/respawnable.js +27 -0
  148. package/dist/mcp/node_modules/@waica/behaviors/package.json +24 -0
  149. package/dist/mcp/node_modules/@waica/engine/dist/aabb.d.ts +2 -0
  150. package/dist/mcp/node_modules/@waica/engine/dist/aabb.js +4 -0
  151. package/dist/mcp/node_modules/@waica/engine/dist/animation/clip-player.d.ts +20 -0
  152. package/dist/mcp/node_modules/@waica/engine/dist/animation/clip-player.js +24 -0
  153. package/dist/mcp/node_modules/@waica/engine/dist/animation/contract.d.ts +21 -0
  154. package/dist/mcp/node_modules/@waica/engine/dist/animation/contract.js +23 -0
  155. package/dist/mcp/node_modules/@waica/engine/dist/animation/sheet.d.ts +65 -0
  156. package/dist/mcp/node_modules/@waica/engine/dist/animation/sheet.js +44 -0
  157. package/dist/mcp/node_modules/@waica/engine/dist/archetype.d.ts +37 -0
  158. package/dist/mcp/node_modules/@waica/engine/dist/archetype.js +1 -0
  159. package/dist/mcp/node_modules/@waica/engine/dist/camera.d.ts +71 -0
  160. package/dist/mcp/node_modules/@waica/engine/dist/camera.js +59 -0
  161. package/dist/mcp/node_modules/@waica/engine/dist/collision-shape.d.ts +26 -0
  162. package/dist/mcp/node_modules/@waica/engine/dist/collision-shape.js +136 -0
  163. package/dist/mcp/node_modules/@waica/engine/dist/component-registry.d.ts +16 -0
  164. package/dist/mcp/node_modules/@waica/engine/dist/component-registry.js +44 -0
  165. package/dist/mcp/node_modules/@waica/engine/dist/component.d.ts +58 -0
  166. package/dist/mcp/node_modules/@waica/engine/dist/component.js +11 -0
  167. package/dist/mcp/node_modules/@waica/engine/dist/components/animated-sprite.d.ts +80 -0
  168. package/dist/mcp/node_modules/@waica/engine/dist/components/animated-sprite.js +210 -0
  169. package/dist/mcp/node_modules/@waica/engine/dist/components/dynamic-body.d.ts +68 -0
  170. package/dist/mcp/node_modules/@waica/engine/dist/components/dynamic-body.js +189 -0
  171. package/dist/mcp/node_modules/@waica/engine/dist/components/hitbox.d.ts +25 -0
  172. package/dist/mcp/node_modules/@waica/engine/dist/components/hitbox.js +21 -0
  173. package/dist/mcp/node_modules/@waica/engine/dist/components/solid.d.ts +32 -0
  174. package/dist/mcp/node_modules/@waica/engine/dist/components/solid.js +45 -0
  175. package/dist/mcp/node_modules/@waica/engine/dist/components/sprite.d.ts +51 -0
  176. package/dist/mcp/node_modules/@waica/engine/dist/components/sprite.js +112 -0
  177. package/dist/mcp/node_modules/@waica/engine/dist/entity.d.ts +22 -0
  178. package/dist/mcp/node_modules/@waica/engine/dist/entity.js +52 -0
  179. package/dist/mcp/node_modules/@waica/engine/dist/events.d.ts +8 -0
  180. package/dist/mcp/node_modules/@waica/engine/dist/events.js +20 -0
  181. package/dist/mcp/node_modules/@waica/engine/dist/game.d.ts +95 -0
  182. package/dist/mcp/node_modules/@waica/engine/dist/game.js +263 -0
  183. package/dist/mcp/node_modules/@waica/engine/dist/index.d.ts +39 -0
  184. package/dist/mcp/node_modules/@waica/engine/dist/index.js +26 -0
  185. package/dist/mcp/node_modules/@waica/engine/dist/input.d.ts +40 -0
  186. package/dist/mcp/node_modules/@waica/engine/dist/input.js +84 -0
  187. package/dist/mcp/node_modules/@waica/engine/dist/scene.d.ts +80 -0
  188. package/dist/mcp/node_modules/@waica/engine/dist/scene.js +93 -0
  189. package/dist/mcp/node_modules/@waica/engine/dist/solid-axis.d.ts +21 -0
  190. package/dist/mcp/node_modules/@waica/engine/dist/solid-axis.js +77 -0
  191. package/dist/mcp/node_modules/@waica/engine/dist/state/hooks.d.ts +90 -0
  192. package/dist/mcp/node_modules/@waica/engine/dist/state/hooks.js +81 -0
  193. package/dist/mcp/node_modules/@waica/engine/dist/state/state-machine.d.ts +83 -0
  194. package/dist/mcp/node_modules/@waica/engine/dist/state/state-machine.js +173 -0
  195. package/dist/mcp/node_modules/@waica/engine/dist/stats.d.ts +27 -0
  196. package/dist/mcp/node_modules/@waica/engine/dist/stats.js +54 -0
  197. package/dist/mcp/node_modules/@waica/engine/dist/ui.d.ts +47 -0
  198. package/dist/mcp/node_modules/@waica/engine/dist/ui.js +175 -0
  199. package/dist/mcp/node_modules/@waica/engine/package.json +25 -0
  200. package/dist/mcp/package-resolver.js +240 -0
  201. package/dist/mcp/project-path.js +86 -0
  202. package/dist/mcp/scaffolds.js +153 -0
  203. package/dist/mcp/server.js +217 -0
  204. package/dist/mcp/stdio.js +13 -0
  205. package/dist/mcp/template/README.md +22 -0
  206. package/dist/mcp/template/_gitignore +5 -0
  207. package/dist/mcp/template/index.html +25 -0
  208. package/dist/mcp/template/package.json.tpl +20 -0
  209. package/dist/mcp/template/public/waica.params.json +1 -0
  210. package/dist/mcp/template/src/art/waica-coin.png +0 -0
  211. package/dist/mcp/template/src/art/waica-dog.png +0 -0
  212. package/dist/mcp/template/src/art/waica-slime.png +0 -0
  213. package/dist/mcp/template/src/characters/player.character.json +133 -0
  214. package/dist/mcp/template/src/characters/slime.character.json +61 -0
  215. package/dist/mcp/template/src/controls.json +8 -0
  216. package/dist/mcp/template/src/game.json +10 -0
  217. package/dist/mcp/template/src/main.ts +105 -0
  218. package/dist/mcp/template/src/objects/coin.object.json +41 -0
  219. package/dist/mcp/template/src/scenes/main.scene.json +217 -0
  220. package/dist/mcp/template/src/stats.json +7 -0
  221. package/dist/mcp/template/src/tiles/block.tile.json +21 -0
  222. package/dist/mcp/template/src/tiles/decor.tile.json +14 -0
  223. package/dist/mcp/template/src/tiles/platform.tile.json +21 -0
  224. package/dist/mcp/template/src/ui/coin-counter.html +12 -0
  225. package/dist/mcp/template/tsconfig.json +15 -0
  226. package/dist/mcp/template/vite.config.ts +3 -0
  227. package/dist/mcp/validation.js +323 -0
  228. package/dist/mcp/workspace-loader.js +14 -0
  229. package/dist/mcp/workspace-runtime.js +109 -0
  230. package/dist/server.js +210 -0
  231. package/package.json +38 -0
package/dist/server.js ADDED
@@ -0,0 +1,210 @@
1
+ import { createServer } from 'node:http';
2
+ import { readFile } from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ export const DEFAULT_PORT = 5178;
5
+ export function parseArgs(argv) {
6
+ const args = { port: DEFAULT_PORT, open: true, help: false, version: false };
7
+ for (let i = 0; i < argv.length; i++) {
8
+ const flag = argv[i];
9
+ switch (flag) {
10
+ case '--port': {
11
+ const port = Number(argv[++i]);
12
+ if (!Number.isInteger(port) || port < 1 || port > 65535) {
13
+ throw new Error('--port expects a number between 1 and 65535');
14
+ }
15
+ args.port = port;
16
+ break;
17
+ }
18
+ case '--no-open':
19
+ args.open = false;
20
+ break;
21
+ case '--help':
22
+ args.help = true;
23
+ break;
24
+ case '--version':
25
+ args.version = true;
26
+ break;
27
+ default:
28
+ throw new Error(`unknown option "${flag}" — try --help`);
29
+ }
30
+ }
31
+ return args;
32
+ }
33
+ const MIME = {
34
+ '.html': 'text/html; charset=utf-8',
35
+ '.js': 'text/javascript; charset=utf-8',
36
+ '.mjs': 'text/javascript; charset=utf-8',
37
+ '.css': 'text/css; charset=utf-8',
38
+ '.json': 'application/json',
39
+ '.map': 'application/json',
40
+ '.png': 'image/png',
41
+ '.jpg': 'image/jpeg',
42
+ '.gif': 'image/gif',
43
+ '.svg': 'image/svg+xml',
44
+ '.ico': 'image/x-icon',
45
+ '.ttf': 'font/ttf',
46
+ '.woff': 'font/woff',
47
+ '.woff2': 'font/woff2',
48
+ '.wasm': 'application/wasm',
49
+ '.txt': 'text/plain; charset=utf-8',
50
+ };
51
+ export function contentType(filePath) {
52
+ return MIME[path.extname(filePath).toLowerCase()] ?? 'application/octet-stream';
53
+ }
54
+ /**
55
+ * Maps a request url to an absolute path under root, or null when the path
56
+ * would escape it (traversal, including percent-encoded dots).
57
+ */
58
+ export function resolveFile(root, url) {
59
+ const pathname = url.split(/[?#]/, 1)[0] ?? url;
60
+ let decoded;
61
+ try {
62
+ decoded = decodeURIComponent(pathname);
63
+ }
64
+ catch {
65
+ return null;
66
+ }
67
+ const resolved = path.resolve(root, decoded.replace(/^\/+/, ''));
68
+ if (resolved !== root && !resolved.startsWith(root + path.sep))
69
+ return null;
70
+ return resolved;
71
+ }
72
+ /**
73
+ * Health endpoint every waica server exposes, so a starting instance can tell
74
+ * "that port is another waica" apart from "that port is some other app".
75
+ */
76
+ export const HEALTH_PATH = '/__waica.json';
77
+ /**
78
+ * Static server for the bundled editor: files by content type, index.html for
79
+ * extension-less routes (the editor is a SPA).
80
+ */
81
+ export function createEditorServer(root, version = '0.0.0') {
82
+ return createServer((req, res) => {
83
+ void handle(root, version, req, res);
84
+ });
85
+ }
86
+ async function handle(root, version, req, res) {
87
+ if (req.method !== 'GET' && req.method !== 'HEAD') {
88
+ res.writeHead(405, { allow: 'GET, HEAD' }).end();
89
+ return;
90
+ }
91
+ if ((req.url ?? '').split(/[?#]/, 1)[0] === HEALTH_PATH) {
92
+ const body = JSON.stringify({ name: 'waica', version, pid: process.pid });
93
+ res.writeHead(200, { 'content-type': 'application/json' });
94
+ res.end(req.method === 'HEAD' ? undefined : body);
95
+ return;
96
+ }
97
+ const target = resolveFile(root, req.url ?? '/');
98
+ if (target === null) {
99
+ res.writeHead(403).end();
100
+ return;
101
+ }
102
+ const file = target === root || path.extname(target) === '' ? path.join(root, 'index.html') : target;
103
+ try {
104
+ const body = await readFile(file);
105
+ res.writeHead(200, {
106
+ 'content-type': contentType(file),
107
+ 'content-length': body.byteLength,
108
+ 'cache-control': 'no-cache',
109
+ });
110
+ res.end(req.method === 'HEAD' ? undefined : body);
111
+ }
112
+ catch {
113
+ res.writeHead(404).end();
114
+ }
115
+ }
116
+ /**
117
+ * Asks whatever listens on host:port whether it is a waica server. Any network
118
+ * error, timeout or unexpected payload means "not waica" — never throws.
119
+ */
120
+ export async function probeWaica(host, port, timeoutMs) {
121
+ try {
122
+ const res = await fetch(`http://${host}:${port}${HEALTH_PATH}`, {
123
+ signal: AbortSignal.timeout(timeoutMs),
124
+ });
125
+ if (!res.ok)
126
+ return null;
127
+ const data = (await res.json());
128
+ if (data.name !== 'waica' || typeof data.version !== 'string' || typeof data.pid !== 'number') {
129
+ return null;
130
+ }
131
+ return { version: data.version, pid: data.pid };
132
+ }
133
+ catch {
134
+ return null;
135
+ }
136
+ }
137
+ /** Numeric segment-wise version compare: 1 if a > b, -1 if a < b, 0 if equal. */
138
+ export function compareVersions(a, b) {
139
+ const pa = a.split('.').map((s) => Number.parseInt(s, 10) || 0);
140
+ const pb = b.split('.').map((s) => Number.parseInt(s, 10) || 0);
141
+ for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
142
+ const diff = (pa[i] ?? 0) - (pb[i] ?? 0);
143
+ if (diff !== 0)
144
+ return Math.sign(diff);
145
+ }
146
+ return 0;
147
+ }
148
+ /**
149
+ * Fetches {version} from a registry "latest" URL. Null on any failure — the
150
+ * update check must never break or delay startup beyond its timeout.
151
+ */
152
+ export async function fetchLatestVersion(url, timeoutMs) {
153
+ try {
154
+ const res = await fetch(url, { signal: AbortSignal.timeout(timeoutMs) });
155
+ if (!res.ok)
156
+ return null;
157
+ const data = (await res.json());
158
+ return typeof data.version === 'string' ? data.version : null;
159
+ }
160
+ catch {
161
+ return null;
162
+ }
163
+ }
164
+ /**
165
+ * Listens on one fixed port, retrying while it is still in use — for taking
166
+ * over a port whose previous owner was just asked to exit.
167
+ */
168
+ export async function listenWithRetry(server, port, host, attempts, delayMs) {
169
+ for (let attempt = 1;; attempt++) {
170
+ try {
171
+ await new Promise((resolve, reject) => {
172
+ server.once('error', reject);
173
+ server.listen(port, host, () => {
174
+ server.off('error', reject);
175
+ resolve();
176
+ });
177
+ });
178
+ return;
179
+ }
180
+ catch (error) {
181
+ if (error.code !== 'EADDRINUSE' || attempt >= attempts)
182
+ throw error;
183
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
184
+ }
185
+ }
186
+ }
187
+ /**
188
+ * Listens on the preferred port, walking forward past ports already in use.
189
+ * Returns the port that actually got bound.
190
+ */
191
+ export async function listenOnFreePort(server, preferredPort, host) {
192
+ const last = Math.min(preferredPort + 9, 65535);
193
+ for (let port = preferredPort; port <= last; port++) {
194
+ try {
195
+ await new Promise((resolve, reject) => {
196
+ server.once('error', reject);
197
+ server.listen(port, host, () => {
198
+ server.off('error', reject);
199
+ resolve();
200
+ });
201
+ });
202
+ return port;
203
+ }
204
+ catch (error) {
205
+ if (error.code !== 'EADDRINUSE')
206
+ throw error;
207
+ }
208
+ }
209
+ throw new Error(`ports ${preferredPort}-${last} are all in use — pick one with --port`);
210
+ }
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@waica/cli",
3
+ "version": "0.3.0",
4
+ "description": "Waica in one command — `npx @waica/cli` opens the editor, `waica mcp` serves the MCP server",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/chichex/waica",
10
+ "directory": "packages/cli"
11
+ },
12
+ "bin": {
13
+ "waica": "dist/cli.js",
14
+ "waica-mcp": "dist/mcp/cli.js"
15
+ },
16
+ "publishConfig": {
17
+ "access": "public"
18
+ },
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "engines": {
23
+ "node": ">=20.19"
24
+ },
25
+ "dependencies": {
26
+ "@modelcontextprotocol/sdk": "^1.30.0",
27
+ "three": "^0.185.1"
28
+ },
29
+ "devDependencies": {
30
+ "@types/node": "^24.13.3",
31
+ "@waica/editor": "^0.1.0",
32
+ "@waica/mcp": "^0.1.0"
33
+ },
34
+ "scripts": {
35
+ "build": "tsc -p tsconfig.build.json && node bundle-editor.mjs && node bundle-mcp.mjs",
36
+ "typecheck": "tsc --noEmit"
37
+ }
38
+ }