codetrellis 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (449) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +27 -2
  3. package/bin/codetrellis.mjs +4 -0
  4. package/package.json +43 -4
  5. package/reader/material-reader.mjs +130346 -0
  6. package/resources/tree-sitter/README.md +150 -0
  7. package/resources/tree-sitter/tree-sitter-c-sharp.wasm +0 -0
  8. package/resources/tree-sitter/tree-sitter-go.wasm +0 -0
  9. package/resources/tree-sitter/tree-sitter-java.wasm +0 -0
  10. package/resources/tree-sitter/tree-sitter-javascript.wasm +0 -0
  11. package/resources/tree-sitter/tree-sitter-kotlin.wasm +0 -0
  12. package/resources/tree-sitter/tree-sitter-php.wasm +0 -0
  13. package/resources/tree-sitter/tree-sitter-python.wasm +0 -0
  14. package/resources/tree-sitter/tree-sitter-ruby.wasm +0 -0
  15. package/resources/tree-sitter/tree-sitter-rust.wasm +0 -0
  16. package/resources/tree-sitter/tree-sitter-swift.wasm +0 -0
  17. package/resources/tree-sitter/tree-sitter-tsx.wasm +0 -0
  18. package/resources/tree-sitter/tree-sitter-typescript.wasm +0 -0
  19. package/resources/tree-sitter/tree-sitter.wasm +0 -0
  20. package/src/backend/agent/claude-code-watcher.js +270 -0
  21. package/src/backend/index.js +8 -0
  22. package/src/backend/lib/sha256-file.js +39 -0
  23. package/src/backend/lib/zip-entries.js +98 -0
  24. package/src/backend/lifecycle.js +102 -0
  25. package/src/backend/mcp/binding-headers.js +54 -0
  26. package/src/backend/mcp/client-identity.js +44 -0
  27. package/src/backend/mcp/connector/command.js +110 -0
  28. package/src/backend/mcp/connector/core.js +278 -0
  29. package/src/backend/mcp/connector/files.js +121 -0
  30. package/src/backend/mcp/connector/hook.js +284 -0
  31. package/src/backend/mcp/connector/main.js +126 -0
  32. package/src/backend/mcp/connector/sse-upstream.js +152 -0
  33. package/src/backend/mcp/helpers.js +43 -0
  34. package/src/backend/mcp/prompt-builders.js +104 -0
  35. package/src/backend/mcp/resources.js +197 -0
  36. package/src/backend/mcp/server.js +813 -0
  37. package/src/backend/mcp/skill-guide.js +1528 -0
  38. package/src/backend/mcp/tools/architecture-tools.js +273 -0
  39. package/src/backend/mcp/tools/audio-tools.js +117 -0
  40. package/src/backend/mcp/tools/awareness-tools.js +623 -0
  41. package/src/backend/mcp/tools/budget-tools.js +185 -0
  42. package/src/backend/mcp/tools/channel-tools.js +205 -0
  43. package/src/backend/mcp/tools/contribution-tools.js +181 -0
  44. package/src/backend/mcp/tools/drift-tools.js +252 -0
  45. package/src/backend/mcp/tools/git-tools.js +316 -0
  46. package/src/backend/mcp/tools/governance-tools.js +175 -0
  47. package/src/backend/mcp/tools/graph-tools.js +181 -0
  48. package/src/backend/mcp/tools/intake-tools.js +244 -0
  49. package/src/backend/mcp/tools/mobile-tools.js +118 -0
  50. package/src/backend/mcp/tools/peer-tools.js +330 -0
  51. package/src/backend/mcp/tools/plan-item-tools.js +1601 -0
  52. package/src/backend/mcp/tools/plan-tools.js +680 -0
  53. package/src/backend/mcp/tools/presence-tools.js +185 -0
  54. package/src/backend/mcp/tools/project-config-tools.js +150 -0
  55. package/src/backend/mcp/tools/review-tools.js +172 -0
  56. package/src/backend/mcp/tools/session-tools.js +554 -0
  57. package/src/backend/mcp/tools/system-docs-tools.js +168 -0
  58. package/src/backend/mcp/tools/terminal-tools.js +186 -0
  59. package/src/backend/mcp/tools/test-tools.js +117 -0
  60. package/src/backend/mcp/tools/ui-tools.js +356 -0
  61. package/src/backend/mcp/types.js +15 -0
  62. package/src/backend/middleware/local-auth.js +116 -0
  63. package/src/backend/server.js +5951 -0
  64. package/src/backend/services/agent-event-log.js +350 -0
  65. package/src/backend/services/architecture-rule.js +584 -0
  66. package/src/backend/services/architecture-rules.js +275 -0
  67. package/src/backend/services/artefact-content-service.js +181 -0
  68. package/src/backend/services/artefact-service.js +305 -0
  69. package/src/backend/services/artefact-watcher.js +167 -0
  70. package/src/backend/services/ast-parser.js +327 -0
  71. package/src/backend/services/audio-buffer-service.js +152 -0
  72. package/src/backend/services/awareness-notices.js +139 -0
  73. package/src/backend/services/awareness-replies.js +194 -0
  74. package/src/backend/services/awareness-service.js +344 -0
  75. package/src/backend/services/awareness-signals.js +267 -0
  76. package/src/backend/services/baseline-store.js +83 -0
  77. package/src/backend/services/branch-workstreams.js +341 -0
  78. package/src/backend/services/breakpoint-service.js +584 -0
  79. package/src/backend/services/brief-service.js +299 -0
  80. package/src/backend/services/budget-service.js +528 -0
  81. package/src/backend/services/callsites/base.js +15 -0
  82. package/src/backend/services/callsites/csharp.js +148 -0
  83. package/src/backend/services/callsites/go.js +163 -0
  84. package/src/backend/services/callsites/index.js +53 -0
  85. package/src/backend/services/callsites/kotlin.js +123 -0
  86. package/src/backend/services/callsites/process-env.js +125 -0
  87. package/src/backend/services/callsites/python.js +91 -0
  88. package/src/backend/services/callsites/ruby.js +164 -0
  89. package/src/backend/services/callsites/shared.js +198 -0
  90. package/src/backend/services/callsites/swift.js +115 -0
  91. package/src/backend/services/callsites/typescript.js +87 -0
  92. package/src/backend/services/capability-token.js +108 -0
  93. package/src/backend/services/change-check.js +156 -0
  94. package/src/backend/services/channel-dispatcher-service.js +235 -0
  95. package/src/backend/services/channel-event-file-service.js +125 -0
  96. package/src/backend/services/channel-event-service.js +297 -0
  97. package/src/backend/services/check-runs.js +177 -0
  98. package/src/backend/services/checkout-identity.js +73 -0
  99. package/src/backend/services/claude-code-parallel.js +221 -0
  100. package/src/backend/services/claude-desktop-config.js +186 -0
  101. package/src/backend/services/clock.js +57 -0
  102. package/src/backend/services/cloud-files.js +191 -0
  103. package/src/backend/services/coalesce.js +50 -0
  104. package/src/backend/services/code-breakpoints.js +291 -0
  105. package/src/backend/services/comment-service.js +168 -0
  106. package/src/backend/services/commit-attribution.js +134 -0
  107. package/src/backend/services/commit-edges.js +99 -0
  108. package/src/backend/services/confined-fs.js +241 -0
  109. package/src/backend/services/conformity-gate.js +132 -0
  110. package/src/backend/services/contribution-service.js +409 -0
  111. package/src/backend/services/coverage-service.js +173 -0
  112. package/src/backend/services/criteria-service.js +721 -0
  113. package/src/backend/services/criterion-checks.js +387 -0
  114. package/src/backend/services/criterion-loop-service.js +411 -0
  115. package/src/backend/services/cross-system-service.js +231 -0
  116. package/src/backend/services/database.js +916 -0
  117. package/src/backend/services/db-schema.js +1358 -0
  118. package/src/backend/services/deviation-service.js +344 -0
  119. package/src/backend/services/diff-engine.js +168 -0
  120. package/src/backend/services/evidence.js +363 -0
  121. package/src/backend/services/external-intake-service.js +269 -0
  122. package/src/backend/services/external-pointer-service.js +195 -0
  123. package/src/backend/services/external-refs-service.js +214 -0
  124. package/src/backend/services/file-history.js +158 -0
  125. package/src/backend/services/file-watcher.js +193 -0
  126. package/src/backend/services/folder-requests.js +118 -0
  127. package/src/backend/services/freeze-service.js +189 -0
  128. package/src/backend/services/gemini-cli-hook.js +172 -0
  129. package/src/backend/services/git-activity-service.js +325 -0
  130. package/src/backend/services/git-blobs.js +70 -0
  131. package/src/backend/services/git-branches.js +357 -0
  132. package/src/backend/services/git-checkout.js +153 -0
  133. package/src/backend/services/git-commit-service.js +91 -0
  134. package/src/backend/services/git-env.js +121 -0
  135. package/src/backend/services/git-identity.js +84 -0
  136. package/src/backend/services/git-refs.js +386 -0
  137. package/src/backend/services/git-safety.js +58 -0
  138. package/src/backend/services/grant-guard.js +67 -0
  139. package/src/backend/services/html-view-policy.js +135 -0
  140. package/src/backend/services/human-decision.js +55 -0
  141. package/src/backend/services/importers.js +159 -0
  142. package/src/backend/services/intent-service.js +105 -0
  143. package/src/backend/services/ipc-dispatcher.js +164 -0
  144. package/src/backend/services/item-git-state.js +208 -0
  145. package/src/backend/services/line-changes.js +232 -0
  146. package/src/backend/services/line-history.js +174 -0
  147. package/src/backend/services/local-api-changes.js +40 -0
  148. package/src/backend/services/logger.js +217 -0
  149. package/src/backend/services/material-footprints.js +203 -0
  150. package/src/backend/services/material-place.js +82 -0
  151. package/src/backend/services/material-reader/child.js +4 -0
  152. package/src/backend/services/material-reader/docx-markdown.js +198 -0
  153. package/src/backend/services/material-reader/fixtures.test-helper.js +169 -0
  154. package/src/backend/services/material-reader/quote.js +44 -0
  155. package/src/backend/services/material-reader/read.js +430 -0
  156. package/src/backend/services/material-reader/reader-host.js +202 -0
  157. package/src/backend/services/material-signals.js +141 -0
  158. package/src/backend/services/mcp-capabilities.js +390 -0
  159. package/src/backend/services/mdns-service.js +304 -0
  160. package/src/backend/services/mobile-api-server.js +281 -0
  161. package/src/backend/services/mobile-approvals.js +306 -0
  162. package/src/backend/services/mobile-awareness.js +180 -0
  163. package/src/backend/services/mobile-breakpoints.js +115 -0
  164. package/src/backend/services/mobile-budget.js +98 -0
  165. package/src/backend/services/mobile-freeze.js +106 -0
  166. package/src/backend/services/mobile-proposals.js +100 -0
  167. package/src/backend/services/mobile-rpc-service.js +1289 -0
  168. package/src/backend/services/mobile-workstreams.js +160 -0
  169. package/src/backend/services/monorepo-detector.js +131 -0
  170. package/src/backend/services/other-work.js +45 -0
  171. package/src/backend/services/pack-seal.js +129 -0
  172. package/src/backend/services/paired-device-service.js +192 -0
  173. package/src/backend/services/pairing-server.js +323 -0
  174. package/src/backend/services/pairing-service.js +200 -0
  175. package/src/backend/services/pantry-resolution-service.js +166 -0
  176. package/src/backend/services/parsers/base.js +124 -0
  177. package/src/backend/services/parsers/csharp.js +224 -0
  178. package/src/backend/services/parsers/go.js +180 -0
  179. package/src/backend/services/parsers/index.js +101 -0
  180. package/src/backend/services/parsers/java.js +103 -0
  181. package/src/backend/services/parsers/kotlin.js +252 -0
  182. package/src/backend/services/parsers/php.js +113 -0
  183. package/src/backend/services/parsers/python.js +189 -0
  184. package/src/backend/services/parsers/ruby.js +212 -0
  185. package/src/backend/services/parsers/rust.js +97 -0
  186. package/src/backend/services/parsers/swift.js +221 -0
  187. package/src/backend/services/parsers/typescript.js +235 -0
  188. package/src/backend/services/pattern-scan.js +65 -0
  189. package/src/backend/services/patterns.js +281 -0
  190. package/src/backend/services/peer-audit-service.js +123 -0
  191. package/src/backend/services/peer-auth.js +153 -0
  192. package/src/backend/services/peer-capabilities.js +209 -0
  193. package/src/backend/services/peer-connection-service.js +450 -0
  194. package/src/backend/services/peer-grants.js +33 -0
  195. package/src/backend/services/persistence.js +116 -0
  196. package/src/backend/services/personal-sync-service.js +232 -0
  197. package/src/backend/services/pipeline-approvals.js +72 -0
  198. package/src/backend/services/pipeline.js +232 -0
  199. package/src/backend/services/plan-arrivals.js +68 -0
  200. package/src/backend/services/plan-changes-service.js +273 -0
  201. package/src/backend/services/plan-conflict-service.js +288 -0
  202. package/src/backend/services/plan-dependencies.js +91 -0
  203. package/src/backend/services/plan-doc-guard.js +90 -0
  204. package/src/backend/services/plan-documents-service.js +275 -0
  205. package/src/backend/services/plan-event-service.js +154 -0
  206. package/src/backend/services/plan-file-refs.js +106 -0
  207. package/src/backend/services/plan-file-service.js +1564 -0
  208. package/src/backend/services/plan-history-service.js +156 -0
  209. package/src/backend/services/plan-import-service.js +261 -0
  210. package/src/backend/services/plan-item-service.js +1223 -0
  211. package/src/backend/services/plan-migrate-service.js +395 -0
  212. package/src/backend/services/plan-overlay-service.js +173 -0
  213. package/src/backend/services/plan-phases-service.js +182 -0
  214. package/src/backend/services/plan-progress-service.js +134 -0
  215. package/src/backend/services/plan-review-service.js +262 -0
  216. package/src/backend/services/plan-service.js +682 -0
  217. package/src/backend/services/plan-status.js +113 -0
  218. package/src/backend/services/plan-template-publish-service.js +217 -0
  219. package/src/backend/services/plan-templates-service.js +242 -0
  220. package/src/backend/services/plan-templates.js +1164 -0
  221. package/src/backend/services/planned-overlap-actions.js +200 -0
  222. package/src/backend/services/plans-home.js +224 -0
  223. package/src/backend/services/play-forward.js +256 -0
  224. package/src/backend/services/playback-service.js +117 -0
  225. package/src/backend/services/power-service.js +167 -0
  226. package/src/backend/services/power-signals.js +81 -0
  227. package/src/backend/services/pr-draft-service.js +142 -0
  228. package/src/backend/services/presence-service.js +122 -0
  229. package/src/backend/services/pricing.js +60 -0
  230. package/src/backend/services/project-config-service.js +474 -0
  231. package/src/backend/services/project-scanner.js +184 -0
  232. package/src/backend/services/projection-service.js +69 -0
  233. package/src/backend/services/push-notification-service.js +288 -0
  234. package/src/backend/services/recent-projects-service.js +204 -0
  235. package/src/backend/services/record-chain.js +162 -0
  236. package/src/backend/services/recurrence-rule.js +63 -0
  237. package/src/backend/services/recurring-agent.js +89 -0
  238. package/src/backend/services/recurring-scheduler.js +77 -0
  239. package/src/backend/services/recurring-service.js +276 -0
  240. package/src/backend/services/reference-service.js +169 -0
  241. package/src/backend/services/release-public-key.js +30 -0
  242. package/src/backend/services/release-signature.js +64 -0
  243. package/src/backend/services/remote-audio-service.js +224 -0
  244. package/src/backend/services/remote-interaction-service.js +275 -0
  245. package/src/backend/services/remote-terminal-service.js +324 -0
  246. package/src/backend/services/rendition/child/main.js +76 -0
  247. package/src/backend/services/rendition/engine-host.js +249 -0
  248. package/src/backend/services/rendition/engine-lock.js +39 -0
  249. package/src/backend/services/rendition/engine-lock.json +14 -0
  250. package/src/backend/services/rendition/engine-manifest.js +97 -0
  251. package/src/backend/services/rendition/network-proof.js +73 -0
  252. package/src/backend/services/rendition/rendition-service.js +175 -0
  253. package/src/backend/services/replay-frames.js +387 -0
  254. package/src/backend/services/replay-state.js +201 -0
  255. package/src/backend/services/resolvers/base.js +108 -0
  256. package/src/backend/services/resolvers/csharp.js +109 -0
  257. package/src/backend/services/resolvers/go.js +105 -0
  258. package/src/backend/services/resolvers/index.js +60 -0
  259. package/src/backend/services/resolvers/java.js +63 -0
  260. package/src/backend/services/resolvers/kotlin.js +109 -0
  261. package/src/backend/services/resolvers/php.js +89 -0
  262. package/src/backend/services/resolvers/python.js +154 -0
  263. package/src/backend/services/resolvers/ruby.js +103 -0
  264. package/src/backend/services/resolvers/rust.js +77 -0
  265. package/src/backend/services/resolvers/swift.js +98 -0
  266. package/src/backend/services/resolvers/typescript.js +71 -0
  267. package/src/backend/services/retention.js +54 -0
  268. package/src/backend/services/review-architecture.js +236 -0
  269. package/src/backend/services/review-attest.js +68 -0
  270. package/src/backend/services/review-bundle.js +226 -0
  271. package/src/backend/services/review-graduation.js +93 -0
  272. package/src/backend/services/review-host/bitbucket.js +79 -0
  273. package/src/backend/services/review-host/detect.js +80 -0
  274. package/src/backend/services/review-host/github.js +97 -0
  275. package/src/backend/services/review-host/gitlab.js +77 -0
  276. package/src/backend/services/review-host/host-state.js +103 -0
  277. package/src/backend/services/review-host/http.js +58 -0
  278. package/src/backend/services/review-host/switch.js +120 -0
  279. package/src/backend/services/review-marks.js +72 -0
  280. package/src/backend/services/review-notes.js +169 -0
  281. package/src/backend/services/review-other-work.js +90 -0
  282. package/src/backend/services/review-queue-service.js +147 -0
  283. package/src/backend/services/review-risk.js +127 -0
  284. package/src/backend/services/review-task.js +121 -0
  285. package/src/backend/services/rule-approvals.js +268 -0
  286. package/src/backend/services/rule-baseline.js +134 -0
  287. package/src/backend/services/rule-changes.js +162 -0
  288. package/src/backend/services/rule-preview.js +47 -0
  289. package/src/backend/services/rule-proposals.js +104 -0
  290. package/src/backend/services/rule-scope.js +76 -0
  291. package/src/backend/services/rulebook.js +286 -0
  292. package/src/backend/services/rules-at.js +56 -0
  293. package/src/backend/services/rules-overview.js +88 -0
  294. package/src/backend/services/schema-reconciler.js +250 -0
  295. package/src/backend/services/secret-store.js +119 -0
  296. package/src/backend/services/section-workstreams.js +95 -0
  297. package/src/backend/services/self-write-tracker.js +75 -0
  298. package/src/backend/services/sensor-bridge-service.js +285 -0
  299. package/src/backend/services/session-service.js +192 -0
  300. package/src/backend/services/settings-service.js +324 -0
  301. package/src/backend/services/signal-breakpoints.js +172 -0
  302. package/src/backend/services/signed-approval-record.js +86 -0
  303. package/src/backend/services/signed-approvals.js +244 -0
  304. package/src/backend/services/signoff-pack.js +328 -0
  305. package/src/backend/services/signoff-rows.js +114 -0
  306. package/src/backend/services/skill-arrival-service.js +138 -0
  307. package/src/backend/services/skill-model.js +193 -0
  308. package/src/backend/services/skill-use-service.js +140 -0
  309. package/src/backend/services/skills-service.js +150 -0
  310. package/src/backend/services/snapshot-compare-service.js +397 -0
  311. package/src/backend/services/source-control.js +189 -0
  312. package/src/backend/services/spec-links-service.js +123 -0
  313. package/src/backend/services/spec-proposal-withdraw.js +50 -0
  314. package/src/backend/services/spec-proposals-service.js +470 -0
  315. package/src/backend/services/sql/embedded.js +95 -0
  316. package/src/backend/services/sql/index.js +63 -0
  317. package/src/backend/services/sql/refs.js +357 -0
  318. package/src/backend/services/sql/schema.js +312 -0
  319. package/src/backend/services/sql/tokenizer.js +195 -0
  320. package/src/backend/services/stack-overlaps.js +117 -0
  321. package/src/backend/services/stack-service.js +225 -0
  322. package/src/backend/services/state-sync-service.js +384 -0
  323. package/src/backend/services/stuck-sensor-service.js +200 -0
  324. package/src/backend/services/system-discovery.js +481 -0
  325. package/src/backend/services/system-docs-service.js +701 -0
  326. package/src/backend/services/task-attachments-service.js +340 -0
  327. package/src/backend/services/task-grounding.js +60 -0
  328. package/src/backend/services/task-records/check-run-record.js +146 -0
  329. package/src/backend/services/task-records/check-runs.js +115 -0
  330. package/src/backend/services/task-records/heads.js +88 -0
  331. package/src/backend/services/task-records/material-reads.js +225 -0
  332. package/src/backend/services/task-records/read-record.js +100 -0
  333. package/src/backend/services/task-records/record.js +173 -0
  334. package/src/backend/services/task-records/run-record.js +136 -0
  335. package/src/backend/services/task-records/shared-state.js +548 -0
  336. package/src/backend/services/task-records/signing.js +140 -0
  337. package/src/backend/services/task-records/split-signals.js +52 -0
  338. package/src/backend/services/task-records/test-runs.js +164 -0
  339. package/src/backend/services/task-records/trust.js +243 -0
  340. package/src/backend/services/task-rules.js +81 -0
  341. package/src/backend/services/task-workstreams.js +90 -0
  342. package/src/backend/services/terminal-history-service.js +266 -0
  343. package/src/backend/services/terminal-service.js +267 -0
  344. package/src/backend/services/test-clock.js +53 -0
  345. package/src/backend/services/tests/grounding.js +266 -0
  346. package/src/backend/services/tests/junit.js +104 -0
  347. package/src/backend/services/tests/teammate-runs.js +134 -0
  348. package/src/backend/services/tests/test-results.js +234 -0
  349. package/src/backend/services/tree-watcher.js +204 -0
  350. package/src/backend/services/trellis-service.js +204 -0
  351. package/src/backend/services/trusted-roots.js +186 -0
  352. package/src/backend/services/update-download-service.js +342 -0
  353. package/src/backend/services/update-service.js +266 -0
  354. package/src/backend/services/watch-ignore.js +76 -0
  355. package/src/backend/services/webhook-egress.js +206 -0
  356. package/src/backend/services/webrtc-service.js +413 -0
  357. package/src/backend/services/work-changes.js +59 -0
  358. package/src/backend/services/workstream-binding.js +82 -0
  359. package/src/backend/services/workstream-commits.js +116 -0
  360. package/src/backend/services/workstream-imports.js +177 -0
  361. package/src/backend/services/workstream-service.js +335 -0
  362. package/src/backend/services/workstream-symbols.js +223 -0
  363. package/src/backend/services/workstream-watch-service.js +391 -0
  364. package/src/backend/services/worktree-service.js +235 -0
  365. package/src/cli/agent.js +100 -0
  366. package/src/cli/args.js +201 -0
  367. package/src/cli/conformity.js +106 -0
  368. package/src/cli/desktop.js +91 -0
  369. package/src/cli/main.js +409 -0
  370. package/src/cli/pipeline.js +109 -0
  371. package/src/cli/plan-verbs.js +259 -0
  372. package/src/cli/review-adapters.js +218 -0
  373. package/src/cli/review-output.js +93 -0
  374. package/src/cli/review-post.js +89 -0
  375. package/src/cli/review-sink.js +183 -0
  376. package/src/cli/review-skill.js +44 -0
  377. package/src/cli/review-verify.js +104 -0
  378. package/src/cli/review.js +386 -0
  379. package/src/cli/sarif.js +148 -0
  380. package/src/cli/verbs.js +359 -0
  381. package/src/shared/build-info.js +39 -0
  382. package/src/shared/lib/agent-review.js +199 -0
  383. package/src/shared/lib/agent-turns.js +140 -0
  384. package/src/shared/lib/awareness-digest.js +120 -0
  385. package/src/shared/lib/branch-name.js +45 -0
  386. package/src/shared/lib/breakpoint-words.js +118 -0
  387. package/src/shared/lib/budget-words.js +56 -0
  388. package/src/shared/lib/burst.js +69 -0
  389. package/src/shared/lib/call-entry.js +105 -0
  390. package/src/shared/lib/check-compare.js +42 -0
  391. package/src/shared/lib/check-words.js +216 -0
  392. package/src/shared/lib/csv.js +62 -0
  393. package/src/shared/lib/folder-entry.js +87 -0
  394. package/src/shared/lib/freeze-words.js +60 -0
  395. package/src/shared/lib/fuzzy.js +84 -0
  396. package/src/shared/lib/git-state-words.js +80 -0
  397. package/src/shared/lib/grep-entry.js +86 -0
  398. package/src/shared/lib/grounding-line.js +61 -0
  399. package/src/shared/lib/import-line.js +71 -0
  400. package/src/shared/lib/item-status.js +249 -0
  401. package/src/shared/lib/line-changes.js +53 -0
  402. package/src/shared/lib/locator.js +71 -0
  403. package/src/shared/lib/matcher.js +120 -0
  404. package/src/shared/lib/merge-order.js +65 -0
  405. package/src/shared/lib/open-findings.js +68 -0
  406. package/src/shared/lib/other-work.js +108 -0
  407. package/src/shared/lib/package-entry.js +142 -0
  408. package/src/shared/lib/plan-vocab.js +40 -0
  409. package/src/shared/lib/pptx-xml.js +86 -0
  410. package/src/shared/lib/proposal-words.js +61 -0
  411. package/src/shared/lib/recurrence.js +183 -0
  412. package/src/shared/lib/references.js +72 -0
  413. package/src/shared/lib/rule-pattern.js +56 -0
  414. package/src/shared/lib/sdp-fingerprint.js +115 -0
  415. package/src/shared/lib/sdp-minimal.js +123 -0
  416. package/src/shared/lib/secret-paths.js +34 -0
  417. package/src/shared/lib/signal-words.js +172 -0
  418. package/src/shared/lib/signoff.js +56 -0
  419. package/src/shared/lib/skills-note.js +60 -0
  420. package/src/shared/lib/spec-sections.js +78 -0
  421. package/src/shared/lib/symbol-entry.js +60 -0
  422. package/src/shared/lib/tool-phrasing.js +338 -0
  423. package/src/shared/lib/turn-gap.js +27 -0
  424. package/src/shared/lib/workstream-words.js +38 -0
  425. package/src/shared/lib/xlsx-xml.js +144 -0
  426. package/src/shared/lib/zip-reader.js +99 -0
  427. package/src/shared/types/agent.js +27 -0
  428. package/src/shared/types/architecture-rules.js +30 -0
  429. package/src/shared/types/ast.js +15 -0
  430. package/src/shared/types/breakpoint.js +33 -0
  431. package/src/shared/types/channel.js +41 -0
  432. package/src/shared/types/criteria.js +15 -0
  433. package/src/shared/types/graph.js +15 -0
  434. package/src/shared/types/index.js +53 -0
  435. package/src/shared/types/peer.js +36 -0
  436. package/src/shared/types/pipeline.js +15 -0
  437. package/src/shared/types/plan.js +15 -0
  438. package/src/shared/types/play-forward.js +15 -0
  439. package/src/shared/types/power.js +15 -0
  440. package/src/shared/types/presence.js +15 -0
  441. package/src/shared/types/project-config.js +35 -0
  442. package/src/shared/types/project.js +15 -0
  443. package/src/shared/types/record.js +15 -0
  444. package/src/shared/types/recurring.js +15 -0
  445. package/src/shared/types/review.js +15 -0
  446. package/src/shared/types/settings.js +114 -0
  447. package/src/shared/types/stack.js +15 -0
  448. package/src/shared/types/system-doc.js +15 -0
  449. package/src/shared/types/system.js +15 -0
@@ -0,0 +1,304 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+ var mdns_service_exports = {};
29
+ __export(mdns_service_exports, {
30
+ getDiscoveredPeer: () => getDiscoveredPeer,
31
+ getDiscoveredPeers: () => getDiscoveredPeers,
32
+ getInstanceId: () => getInstanceId,
33
+ isMdnsRunning: () => isMdnsRunning,
34
+ onPeerDiscovered: () => onPeerDiscovered,
35
+ onPeerLost: () => onPeerLost,
36
+ startMdns: () => startMdns,
37
+ stopMdns: () => stopMdns,
38
+ updateAdvertisedName: () => updateAdvertisedName
39
+ });
40
+ module.exports = __toCommonJS(mdns_service_exports);
41
+ var import_node_os = __toESM(require("node:os"));
42
+ var import_node_fs = __toESM(require("node:fs"));
43
+ var import_node_path = __toESM(require("node:path"));
44
+ var import_node_crypto = require("node:crypto");
45
+ var import_build_info = require("../../shared/build-info");
46
+ var import_persistence = require("./persistence");
47
+ let Bonjour = null;
48
+ const SERVICE_TYPE = "codetrellis";
49
+ const STALE_PEER_MS = 12e4;
50
+ const BASE_ID_FILE = "mdns-instance-id";
51
+ const INSTANCES_FILE = "mdns-instances.json";
52
+ function isPidAlive(pid) {
53
+ if (!pid || pid === process.pid) return false;
54
+ try {
55
+ process.kill(pid, 0);
56
+ return true;
57
+ } catch (err) {
58
+ return err.code === "EPERM";
59
+ }
60
+ }
61
+ function readLiveInstances(dir) {
62
+ try {
63
+ const arr = JSON.parse(import_node_fs.default.readFileSync(import_node_path.default.join(dir, INSTANCES_FILE), "utf-8"));
64
+ return Array.isArray(arr) ? arr.filter((e) => e && typeof e.id === "string" && typeof e.pid === "number") : [];
65
+ } catch {
66
+ return [];
67
+ }
68
+ }
69
+ function writeLiveInstances(dir, list) {
70
+ try {
71
+ import_node_fs.default.mkdirSync(dir, { recursive: true });
72
+ const tmp = import_node_path.default.join(dir, `${INSTANCES_FILE}.tmp`);
73
+ import_node_fs.default.writeFileSync(tmp, JSON.stringify(list), "utf-8");
74
+ import_node_fs.default.renameSync(tmp, import_node_path.default.join(dir, INSTANCES_FILE));
75
+ } catch {
76
+ }
77
+ }
78
+ function loadStableBaseId(dir) {
79
+ try {
80
+ const file = import_node_path.default.join(dir, BASE_ID_FILE);
81
+ if (import_node_fs.default.existsSync(file)) {
82
+ const existing = import_node_fs.default.readFileSync(file, "utf-8").trim();
83
+ if (/^[0-9a-f]{8}$/i.test(existing)) return existing;
84
+ }
85
+ const id = (0, import_node_crypto.randomUUID)().slice(0, 8);
86
+ import_node_fs.default.mkdirSync(dir, { recursive: true });
87
+ import_node_fs.default.writeFileSync(file, id, "utf-8");
88
+ return id;
89
+ } catch {
90
+ return (0, import_node_crypto.randomUUID)().slice(0, 8);
91
+ }
92
+ }
93
+ function acquireInstanceId() {
94
+ let dir;
95
+ try {
96
+ dir = (0, import_persistence.getSettingsDir)();
97
+ } catch {
98
+ return (0, import_node_crypto.randomUUID)().slice(0, 8);
99
+ }
100
+ const baseId = loadStableBaseId(dir);
101
+ const live = readLiveInstances(dir).filter((e) => isPidAlive(e.pid));
102
+ const taken = new Set(live.map((e) => e.id));
103
+ let chosen = baseId;
104
+ if (taken.has(chosen)) {
105
+ for (let i = 0; i < 50 && taken.has(chosen); i++) {
106
+ chosen = `${baseId}${(0, import_node_crypto.randomUUID)().slice(0, 2)}`.slice(0, 12);
107
+ }
108
+ if (taken.has(chosen)) chosen = (0, import_node_crypto.randomUUID)().slice(0, 8);
109
+ console.log(`[mDNS] Base id ${baseId} held by a live instance \u2014 using ${chosen} to avoid an A-record collision.`);
110
+ }
111
+ writeLiveInstances(dir, [...live, { id: chosen, pid: process.pid, startedAt: (/* @__PURE__ */ new Date()).toISOString() }]);
112
+ return chosen;
113
+ }
114
+ function releaseInstanceId() {
115
+ try {
116
+ const dir = (0, import_persistence.getSettingsDir)();
117
+ writeLiveInstances(dir, readLiveInstances(dir).filter((e) => e.pid !== process.pid && isPidAlive(e.pid)));
118
+ } catch {
119
+ }
120
+ }
121
+ const instanceId = acquireInstanceId();
122
+ process.once("exit", () => releaseInstanceId());
123
+ let bonjourInstance = null;
124
+ let publishedService = null;
125
+ let browser = null;
126
+ let sweepInterval = null;
127
+ const peers = /* @__PURE__ */ new Map();
128
+ const listeners = {
129
+ discovered: /* @__PURE__ */ new Set(),
130
+ lost: /* @__PURE__ */ new Set()
131
+ };
132
+ function getInstanceId() {
133
+ return instanceId;
134
+ }
135
+ function startMdns(deviceName, fingerprint, mobileApiPort) {
136
+ stopMdns();
137
+ try {
138
+ if (!Bonjour) {
139
+ const mod = require("bonjour-service");
140
+ Bonjour = mod.default ?? mod.Bonjour ?? mod;
141
+ }
142
+ bonjourInstance = new Bonjour();
143
+ } catch (err) {
144
+ console.warn("[mDNS] Failed to initialise bonjour-service \u2014 discovery disabled:", err);
145
+ return;
146
+ }
147
+ const name = deviceName || import_node_os.default.hostname();
148
+ const version = import_build_info.BUILD_INFO?.version ?? "0.0.0";
149
+ const fp = fingerprint || "pending";
150
+ const advertisePort = mobileApiPort && mobileApiPort > 0 ? mobileApiPort : 1;
151
+ try {
152
+ publishedService = bonjourInstance.publish({
153
+ name: `${name} (${instanceId})`,
154
+ type: SERVICE_TYPE,
155
+ // Advertise under a unique, CodeTrellis-owned hostname rather than the
156
+ // machine's real `.local` name. bonjour-service runs its own mDNS
157
+ // responder and announces A-records for `host`; if that's the system
158
+ // hostname (the default), it collides with macOS's built-in Bonjour
159
+ // responder, which resolves the conflict by renaming the Mac to
160
+ // "…-2.local", "…-3.local" on every (especially unclean) restart.
161
+ // A dedicated host keeps discovery working (peers read the IP from the
162
+ // record's addresses) without ever touching the OS hostname.
163
+ host: `codetrellis-${instanceId}.local`,
164
+ port: advertisePort,
165
+ txt: {
166
+ instanceId,
167
+ version,
168
+ fingerprint: fp,
169
+ deviceName: name,
170
+ mobileApiPort: String(advertisePort)
171
+ }
172
+ });
173
+ console.log(`[mDNS] Advertising as "${name}" (${instanceId}) mobileApiPort=${advertisePort}`);
174
+ } catch (err) {
175
+ console.warn("[mDNS] Failed to publish service:", err);
176
+ }
177
+ try {
178
+ browser = bonjourInstance.find({ type: SERVICE_TYPE });
179
+ browser.on("up", (service) => {
180
+ const txt = service.txt ?? {};
181
+ const peerInstanceId = txt.instanceId;
182
+ if (!peerInstanceId || peerInstanceId === instanceId) return;
183
+ const address = service.addresses?.[0] ?? service.host ?? "";
184
+ const peer = {
185
+ instanceId: peerInstanceId,
186
+ name: txt.deviceName || "Unknown",
187
+ version: txt.version || "?",
188
+ fingerprint: txt.fingerprint || "",
189
+ address,
190
+ lastSeen: (/* @__PURE__ */ new Date()).toISOString()
191
+ };
192
+ const isNew = !peers.has(peerInstanceId);
193
+ peers.set(peerInstanceId, peer);
194
+ if (isNew) {
195
+ console.log(`[mDNS] Discovered peer: "${peer.name}" at ${peer.address}`);
196
+ for (const cb of listeners.discovered) {
197
+ try {
198
+ cb(peer);
199
+ } catch {
200
+ }
201
+ }
202
+ }
203
+ });
204
+ browser.on("down", (service) => {
205
+ const txt = service.txt ?? {};
206
+ const peerInstanceId = txt.instanceId;
207
+ if (!peerInstanceId) return;
208
+ const peer = peers.get(peerInstanceId);
209
+ if (peer) {
210
+ peers.delete(peerInstanceId);
211
+ console.log(`[mDNS] Lost peer: "${peer.name}"`);
212
+ for (const cb of listeners.lost) {
213
+ try {
214
+ cb(peer);
215
+ } catch {
216
+ }
217
+ }
218
+ }
219
+ });
220
+ console.log(`[mDNS] Browsing for _${SERVICE_TYPE}._tcp services`);
221
+ } catch (err) {
222
+ console.warn("[mDNS] Failed to start browser:", err);
223
+ }
224
+ sweepInterval = setInterval(() => {
225
+ const cutoff = Date.now() - STALE_PEER_MS;
226
+ for (const [id, peer] of peers) {
227
+ if (new Date(peer.lastSeen).getTime() < cutoff) {
228
+ peers.delete(id);
229
+ console.log(`[mDNS] Stale peer removed: "${peer.name}"`);
230
+ for (const cb of listeners.lost) {
231
+ try {
232
+ cb(peer);
233
+ } catch {
234
+ }
235
+ }
236
+ }
237
+ }
238
+ }, 3e4);
239
+ }
240
+ function stopMdns() {
241
+ if (sweepInterval) {
242
+ clearInterval(sweepInterval);
243
+ sweepInterval = null;
244
+ }
245
+ if (publishedService) {
246
+ try {
247
+ publishedService.stop?.();
248
+ } catch {
249
+ }
250
+ publishedService = null;
251
+ }
252
+ if (browser) {
253
+ try {
254
+ browser.stop();
255
+ } catch {
256
+ }
257
+ browser = null;
258
+ }
259
+ if (bonjourInstance) {
260
+ try {
261
+ bonjourInstance.destroy();
262
+ } catch {
263
+ }
264
+ bonjourInstance = null;
265
+ }
266
+ peers.clear();
267
+ }
268
+ function updateAdvertisedName(name, fingerprint, mobileApiPort) {
269
+ if (!bonjourInstance) return;
270
+ startMdns(name, fingerprint, mobileApiPort);
271
+ }
272
+ function getDiscoveredPeers() {
273
+ return Array.from(peers.values());
274
+ }
275
+ function getDiscoveredPeer(peerInstanceId) {
276
+ return peers.get(peerInstanceId);
277
+ }
278
+ function onPeerDiscovered(cb) {
279
+ listeners.discovered.add(cb);
280
+ return () => {
281
+ listeners.discovered.delete(cb);
282
+ };
283
+ }
284
+ function onPeerLost(cb) {
285
+ listeners.lost.add(cb);
286
+ return () => {
287
+ listeners.lost.delete(cb);
288
+ };
289
+ }
290
+ function isMdnsRunning() {
291
+ return bonjourInstance !== null;
292
+ }
293
+ // Annotate the CommonJS export names for ESM import in node:
294
+ 0 && (module.exports = {
295
+ getDiscoveredPeer,
296
+ getDiscoveredPeers,
297
+ getInstanceId,
298
+ isMdnsRunning,
299
+ onPeerDiscovered,
300
+ onPeerLost,
301
+ startMdns,
302
+ stopMdns,
303
+ updateAdvertisedName
304
+ });
@@ -0,0 +1,281 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+ var mobile_api_server_exports = {};
29
+ __export(mobile_api_server_exports, {
30
+ getMobileApiPort: () => getMobileApiPort,
31
+ isMobileApiRunning: () => isMobileApiRunning,
32
+ resetMobileApiRateLimit: () => resetMobileApiRateLimit,
33
+ startMobileApiServer: () => startMobileApiServer,
34
+ stopMobileApiServer: () => stopMobileApiServer
35
+ });
36
+ module.exports = __toCommonJS(mobile_api_server_exports);
37
+ var import_node_http = __toESM(require("node:http"));
38
+ var import_settings_service = require("./settings-service");
39
+ var import_peer_connection_service = require("./peer-connection-service");
40
+ const MAX_BODY_BYTES = 256 * 1024;
41
+ const SOCKET_TIMEOUT_MS = 15e3;
42
+ const RATE_WINDOW_MS = 6e4;
43
+ const RATE_MAX_REQUESTS = 60;
44
+ const RATE_MAX_SOURCES = 1024;
45
+ let server = null;
46
+ let boundPort = 0;
47
+ async function startMobileApiServer() {
48
+ if (server) {
49
+ return boundPort;
50
+ }
51
+ const settings = (0, import_settings_service.getSettings)();
52
+ const requestedPort = settings.device.mobileApiPort || 19480;
53
+ return new Promise((resolve, reject) => {
54
+ const tryPort = (candidate, attemptsLeft) => {
55
+ const srv = import_node_http.default.createServer(handleRequest);
56
+ srv.on("error", (err) => {
57
+ if (err.code === "EADDRINUSE" && attemptsLeft > 0) {
58
+ console.log(`[MobileAPI] Port ${candidate} in use, trying ${candidate + 1}\u2026`);
59
+ tryPort(candidate + 1, attemptsLeft - 1);
60
+ } else {
61
+ reject(err);
62
+ }
63
+ });
64
+ srv.setTimeout(SOCKET_TIMEOUT_MS, (socket) => socket.destroy());
65
+ srv.headersTimeout = SOCKET_TIMEOUT_MS;
66
+ srv.requestTimeout = SOCKET_TIMEOUT_MS;
67
+ srv.listen(candidate, "0.0.0.0", () => {
68
+ server = srv;
69
+ boundPort = candidate;
70
+ console.log(`[MobileAPI] Listening on 0.0.0.0:${candidate}`);
71
+ resolve(candidate);
72
+ });
73
+ };
74
+ tryPort(requestedPort, 10);
75
+ });
76
+ }
77
+ function stopMobileApiServer() {
78
+ if (server) {
79
+ try {
80
+ server.closeAllConnections?.();
81
+ server.close();
82
+ } catch {
83
+ }
84
+ server = null;
85
+ boundPort = 0;
86
+ hits.clear();
87
+ console.log("[MobileAPI] Stopped");
88
+ }
89
+ }
90
+ function getMobileApiPort() {
91
+ return boundPort;
92
+ }
93
+ function isMobileApiRunning() {
94
+ return server !== null;
95
+ }
96
+ function handleRequest(req, res) {
97
+ res.setHeader("Access-Control-Allow-Origin", "*");
98
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
99
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type");
100
+ if (req.method === "OPTIONS") {
101
+ res.writeHead(204);
102
+ res.end();
103
+ return;
104
+ }
105
+ if (rateLimited(req)) {
106
+ sendJson(res, 429, { error: "Too many requests" });
107
+ return;
108
+ }
109
+ const url = new URL(req.url || "/", `http://${req.headers.host || "localhost"}`);
110
+ if (req.method === "POST" && url.pathname === "/api/mobile/auth/challenge") {
111
+ handleChallenge(req, res);
112
+ return;
113
+ }
114
+ if (req.method === "POST" && url.pathname === "/api/mobile/reconnect") {
115
+ handleReconnect(req, res);
116
+ return;
117
+ }
118
+ if (req.method === "POST" && url.pathname === "/api/mobile/reconnect/answer") {
119
+ handleReconnectAnswer(req, res);
120
+ return;
121
+ }
122
+ if (req.method === "GET" && url.pathname === "/api/mobile/status") {
123
+ handleStatus(res);
124
+ return;
125
+ }
126
+ res.writeHead(404, { "Content-Type": "application/json" });
127
+ res.end(JSON.stringify({ error: "Not found" }));
128
+ }
129
+ function handleChallenge(req, res) {
130
+ readJsonBody(req).then((data) => {
131
+ const pairingId = typeof data.pairingId === "string" ? data.pairingId : "";
132
+ if (!pairingId) {
133
+ sendJson(res, 400, { error: "Missing pairingId" });
134
+ return;
135
+ }
136
+ sendJson(res, 200, (0, import_peer_connection_service.issueReconnectChallenge)(pairingId));
137
+ }).catch((err) => failBody(res, err));
138
+ }
139
+ function handleReconnect(req, res) {
140
+ readJsonBody(req).then(async (data) => {
141
+ const pairingId = typeof data.pairingId === "string" ? data.pairingId : "";
142
+ const nonce = typeof data.nonce === "string" ? data.nonce : "";
143
+ const mac = typeof data.mac === "string" ? data.mac : "";
144
+ const expiresAt = typeof data.expiresAt === "number" ? data.expiresAt : 0;
145
+ if (!pairingId || !nonce || !mac || !expiresAt) {
146
+ sendJson(res, 400, { error: "Missing pairingId or challenge response" });
147
+ return;
148
+ }
149
+ const result = await (0, import_peer_connection_service.startReconnection)(pairingId, { nonce, expiresAt, mac });
150
+ if (!result) {
151
+ sendJson(res, 403, { error: "Reconnection refused" });
152
+ return;
153
+ }
154
+ sendJson(res, 200, {
155
+ offer: result.offer,
156
+ ice: result.iceCandidates,
157
+ fingerprint: result.fingerprint,
158
+ pairingId: result.pairingId,
159
+ // Consumed with the answer, so a captured proof is worth one use.
160
+ answerNonce: result.answerNonce,
161
+ // Lets the phone verify it is talking to the desktop it paired with,
162
+ // without depending on a certificate that changes every restart.
163
+ offerMac: result.offerMac
164
+ });
165
+ }).catch((err) => failBody(res, err));
166
+ }
167
+ function handleReconnectAnswer(req, res) {
168
+ readJsonBody(req).then(async (data) => {
169
+ const pairingId = typeof data.pairingId === "string" ? data.pairingId : "";
170
+ const answer = typeof data.answer === "string" ? data.answer : "";
171
+ const fingerprint = typeof data.fingerprint === "string" ? data.fingerprint : "";
172
+ const ice = Array.isArray(data.ice) ? data.ice : [];
173
+ const mac = typeof data.mac === "string" ? data.mac : "";
174
+ if (!pairingId || !answer) {
175
+ sendJson(res, 400, { error: "Missing pairingId or answer" });
176
+ return;
177
+ }
178
+ const success = await (0, import_peer_connection_service.completeReconnection)(pairingId, answer, ice, fingerprint, mac);
179
+ if (!success) {
180
+ sendJson(res, 403, { error: "Reconnection refused" });
181
+ return;
182
+ }
183
+ sendJson(res, 200, { connected: true });
184
+ }).catch((err) => failBody(res, err));
185
+ }
186
+ function handleStatus(res) {
187
+ try {
188
+ const status = (0, import_peer_connection_service.getPeerManagerStatus)();
189
+ const settings = (0, import_settings_service.getSettings)();
190
+ res.writeHead(200, { "Content-Type": "application/json" });
191
+ res.end(JSON.stringify({
192
+ ok: true,
193
+ deviceName: settings.device.deviceName || require("node:os").hostname(),
194
+ port: boundPort,
195
+ ...status
196
+ }));
197
+ } catch (err) {
198
+ res.writeHead(500, { "Content-Type": "application/json" });
199
+ res.end(JSON.stringify({ error: String(err) }));
200
+ }
201
+ }
202
+ function readJsonBody(req) {
203
+ return new Promise((resolve, reject) => {
204
+ let body = "";
205
+ let size = 0;
206
+ req.on("data", (chunk) => {
207
+ size += Buffer.byteLength(chunk);
208
+ if (size > MAX_BODY_BYTES) {
209
+ reject(new BodyTooLarge());
210
+ req.destroy();
211
+ return;
212
+ }
213
+ body += chunk;
214
+ });
215
+ req.on("end", () => {
216
+ try {
217
+ const parsed = JSON.parse(body || "{}");
218
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
219
+ reject(new BadJson());
220
+ return;
221
+ }
222
+ resolve(parsed);
223
+ } catch {
224
+ reject(new BadJson());
225
+ }
226
+ });
227
+ req.on("error", reject);
228
+ });
229
+ }
230
+ class BodyTooLarge extends Error {
231
+ status = 413;
232
+ }
233
+ class BadJson extends Error {
234
+ status = 400;
235
+ }
236
+ function sendJson(res, status, payload) {
237
+ if (res.headersSent) return;
238
+ res.writeHead(status, { "Content-Type": "application/json" });
239
+ res.end(JSON.stringify(payload));
240
+ }
241
+ function failBody(res, err) {
242
+ if (err instanceof BodyTooLarge) return sendJson(res, 413, { error: "Request body too large" });
243
+ if (err instanceof BadJson) return sendJson(res, 400, { error: "Invalid JSON" });
244
+ console.warn("[MobileAPI] Request failed:", err);
245
+ sendJson(res, 500, { error: "Request failed" });
246
+ }
247
+ const hits = /* @__PURE__ */ new Map();
248
+ function rateLimited(req, now = Date.now()) {
249
+ const source = req.socket.remoteAddress ?? "unknown";
250
+ const entry = hits.get(source);
251
+ if (!entry || entry.resetAt <= now) {
252
+ if (hits.size >= RATE_MAX_SOURCES) {
253
+ for (const [key, value] of hits) if (value.resetAt <= now) hits.delete(key);
254
+ if (hits.size >= RATE_MAX_SOURCES) {
255
+ const oldest = hits.keys().next();
256
+ if (!oldest.done) hits.delete(oldest.value);
257
+ }
258
+ }
259
+ hits.set(source, { count: 1, resetAt: now + RATE_WINDOW_MS });
260
+ return false;
261
+ }
262
+ entry.count += 1;
263
+ if (entry.count > RATE_MAX_REQUESTS) {
264
+ if (entry.count === RATE_MAX_REQUESTS + 1) {
265
+ console.warn(`[MobileAPI] Rate limiting ${source} \u2014 ${entry.count} requests in the window`);
266
+ }
267
+ return true;
268
+ }
269
+ return false;
270
+ }
271
+ function resetMobileApiRateLimit() {
272
+ hits.clear();
273
+ }
274
+ // Annotate the CommonJS export names for ESM import in node:
275
+ 0 && (module.exports = {
276
+ getMobileApiPort,
277
+ isMobileApiRunning,
278
+ resetMobileApiRateLimit,
279
+ startMobileApiServer,
280
+ stopMobileApiServer
281
+ });