groove-dev 0.27.93 → 0.27.96

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 (511) hide show
  1. package/CLAUDE.md +7 -0
  2. package/README.md +25 -52
  3. package/moe-training/package.json +2 -1
  4. package/node_modules/@groove-dev/cli/package.json +1 -1
  5. package/node_modules/@groove-dev/daemon/package.json +1 -1
  6. package/node_modules/@groove-dev/daemon/src/api.js +39 -23
  7. package/node_modules/@groove-dev/daemon/src/introducer.js +21 -6
  8. package/node_modules/@groove-dev/daemon/src/process.js +20 -2
  9. package/node_modules/@groove-dev/daemon/src/providers/gemini.js +27 -28
  10. package/node_modules/@groove-dev/gui/dist/assets/{index-VB4_k5Pz.js → index-BgTyFy4f.js} +331 -331
  11. package/node_modules/@groove-dev/gui/dist/assets/{index-Bo6AeNmM.css → index-QADLyUj5.css} +1 -1
  12. package/node_modules/@groove-dev/gui/dist/index.html +2 -2
  13. package/node_modules/@groove-dev/gui/package.json +1 -1
  14. package/node_modules/@groove-dev/gui/src/components/agents/agent-file-tree.jsx +68 -16
  15. package/node_modules/@groove-dev/gui/src/components/agents/agent-panel.jsx +2 -0
  16. package/node_modules/@groove-dev/gui/src/components/agents/code-review.jsx +9 -1
  17. package/node_modules/@groove-dev/gui/src/components/agents/workspace-mode.jsx +2 -2
  18. package/node_modules/@groove-dev/gui/src/components/editor/code-editor.jsx +1 -1
  19. package/node_modules/@groove-dev/gui/src/stores/groove.js +40 -26
  20. package/node_modules/@groove-dev/gui/src/views/agents.jsx +14 -65
  21. package/node_modules/base64-js/LICENSE +21 -0
  22. package/node_modules/base64-js/README.md +34 -0
  23. package/node_modules/base64-js/base64js.min.js +1 -0
  24. package/node_modules/base64-js/index.d.ts +3 -0
  25. package/node_modules/base64-js/index.js +150 -0
  26. package/node_modules/base64-js/package.json +47 -0
  27. package/node_modules/better-sqlite3/LICENSE +21 -0
  28. package/node_modules/better-sqlite3/README.md +99 -0
  29. package/node_modules/better-sqlite3/binding.gyp +38 -0
  30. package/node_modules/better-sqlite3/deps/common.gypi +68 -0
  31. package/node_modules/better-sqlite3/deps/copy.js +31 -0
  32. package/node_modules/better-sqlite3/deps/defines.gypi +41 -0
  33. package/node_modules/better-sqlite3/deps/download.sh +122 -0
  34. package/node_modules/better-sqlite3/deps/patches/1208.patch +15 -0
  35. package/node_modules/better-sqlite3/deps/sqlite3/sqlite3.c +268845 -0
  36. package/node_modules/better-sqlite3/deps/sqlite3/sqlite3.h +14335 -0
  37. package/node_modules/better-sqlite3/deps/sqlite3/sqlite3ext.h +739 -0
  38. package/node_modules/better-sqlite3/deps/sqlite3.gyp +80 -0
  39. package/node_modules/better-sqlite3/deps/test_extension.c +21 -0
  40. package/node_modules/better-sqlite3/lib/database.js +90 -0
  41. package/node_modules/better-sqlite3/lib/index.js +3 -0
  42. package/node_modules/better-sqlite3/lib/methods/aggregate.js +43 -0
  43. package/node_modules/better-sqlite3/lib/methods/backup.js +67 -0
  44. package/node_modules/better-sqlite3/lib/methods/function.js +31 -0
  45. package/node_modules/better-sqlite3/lib/methods/inspect.js +7 -0
  46. package/node_modules/better-sqlite3/lib/methods/pragma.js +12 -0
  47. package/node_modules/better-sqlite3/lib/methods/serialize.js +16 -0
  48. package/node_modules/better-sqlite3/lib/methods/table.js +189 -0
  49. package/node_modules/better-sqlite3/lib/methods/transaction.js +78 -0
  50. package/node_modules/better-sqlite3/lib/methods/wrappers.js +54 -0
  51. package/node_modules/better-sqlite3/lib/sqlite-error.js +20 -0
  52. package/node_modules/better-sqlite3/lib/util.js +12 -0
  53. package/node_modules/better-sqlite3/package.json +59 -0
  54. package/node_modules/better-sqlite3/src/addon.cpp +47 -0
  55. package/node_modules/better-sqlite3/src/better_sqlite3.cpp +74 -0
  56. package/node_modules/better-sqlite3/src/objects/backup.cpp +120 -0
  57. package/node_modules/better-sqlite3/src/objects/backup.hpp +36 -0
  58. package/node_modules/better-sqlite3/src/objects/database.cpp +417 -0
  59. package/node_modules/better-sqlite3/src/objects/database.hpp +103 -0
  60. package/node_modules/better-sqlite3/src/objects/statement-iterator.cpp +113 -0
  61. package/node_modules/better-sqlite3/src/objects/statement-iterator.hpp +50 -0
  62. package/node_modules/better-sqlite3/src/objects/statement.cpp +383 -0
  63. package/node_modules/better-sqlite3/src/objects/statement.hpp +58 -0
  64. package/node_modules/better-sqlite3/src/util/bind-map.cpp +73 -0
  65. package/node_modules/better-sqlite3/src/util/binder.cpp +193 -0
  66. package/node_modules/better-sqlite3/src/util/constants.cpp +172 -0
  67. package/node_modules/better-sqlite3/src/util/custom-aggregate.cpp +121 -0
  68. package/node_modules/better-sqlite3/src/util/custom-function.cpp +59 -0
  69. package/node_modules/better-sqlite3/src/util/custom-table.cpp +409 -0
  70. package/node_modules/better-sqlite3/src/util/data-converter.cpp +17 -0
  71. package/node_modules/better-sqlite3/src/util/data.cpp +194 -0
  72. package/node_modules/better-sqlite3/src/util/helpers.cpp +109 -0
  73. package/node_modules/better-sqlite3/src/util/macros.cpp +83 -0
  74. package/node_modules/better-sqlite3/src/util/query-macros.cpp +71 -0
  75. package/node_modules/better-sqlite3/src/util/row-builder.cpp +49 -0
  76. package/node_modules/bindings/LICENSE.md +22 -0
  77. package/node_modules/bindings/README.md +98 -0
  78. package/node_modules/bindings/bindings.js +221 -0
  79. package/node_modules/bindings/package.json +28 -0
  80. package/node_modules/bl/.travis.yml +17 -0
  81. package/node_modules/bl/BufferList.js +396 -0
  82. package/node_modules/bl/LICENSE.md +13 -0
  83. package/node_modules/bl/README.md +247 -0
  84. package/node_modules/bl/bl.js +84 -0
  85. package/node_modules/bl/package.json +37 -0
  86. package/node_modules/bl/test/convert.js +21 -0
  87. package/node_modules/bl/test/indexOf.js +492 -0
  88. package/node_modules/bl/test/isBufferList.js +32 -0
  89. package/node_modules/bl/test/test.js +869 -0
  90. package/node_modules/buffer/AUTHORS.md +70 -0
  91. package/node_modules/buffer/LICENSE +21 -0
  92. package/node_modules/buffer/README.md +410 -0
  93. package/node_modules/buffer/index.d.ts +186 -0
  94. package/node_modules/buffer/index.js +1817 -0
  95. package/node_modules/buffer/package.json +96 -0
  96. package/node_modules/decompress-response/index.d.ts +22 -0
  97. package/node_modules/decompress-response/index.js +58 -0
  98. package/node_modules/decompress-response/license +9 -0
  99. package/node_modules/decompress-response/node_modules/mimic-response/index.d.ts +17 -0
  100. package/node_modules/decompress-response/node_modules/mimic-response/index.js +77 -0
  101. package/node_modules/decompress-response/node_modules/mimic-response/license +9 -0
  102. package/node_modules/decompress-response/node_modules/mimic-response/package.json +42 -0
  103. package/node_modules/decompress-response/node_modules/mimic-response/readme.md +78 -0
  104. package/node_modules/decompress-response/package.json +56 -0
  105. package/node_modules/decompress-response/readme.md +48 -0
  106. package/node_modules/deep-extend/LICENSE +20 -0
  107. package/node_modules/deep-extend/README.md +91 -0
  108. package/node_modules/deep-extend/index.js +1 -0
  109. package/node_modules/deep-extend/lib/deep-extend.js +150 -0
  110. package/node_modules/deep-extend/package.json +62 -0
  111. package/node_modules/end-of-stream/LICENSE +21 -0
  112. package/node_modules/end-of-stream/README.md +54 -0
  113. package/node_modules/end-of-stream/index.js +96 -0
  114. package/node_modules/end-of-stream/package.json +37 -0
  115. package/node_modules/expand-template/.travis.yml +6 -0
  116. package/node_modules/expand-template/LICENSE +21 -0
  117. package/node_modules/expand-template/README.md +43 -0
  118. package/node_modules/expand-template/index.js +26 -0
  119. package/node_modules/expand-template/package.json +29 -0
  120. package/node_modules/expand-template/test.js +67 -0
  121. package/node_modules/file-uri-to-path/.npmignore +1 -0
  122. package/node_modules/file-uri-to-path/.travis.yml +30 -0
  123. package/node_modules/file-uri-to-path/History.md +21 -0
  124. package/node_modules/file-uri-to-path/LICENSE +20 -0
  125. package/node_modules/file-uri-to-path/README.md +74 -0
  126. package/node_modules/file-uri-to-path/index.d.ts +2 -0
  127. package/node_modules/file-uri-to-path/index.js +66 -0
  128. package/node_modules/file-uri-to-path/package.json +32 -0
  129. package/node_modules/file-uri-to-path/test/test.js +24 -0
  130. package/node_modules/file-uri-to-path/test/tests.json +13 -0
  131. package/node_modules/fs-constants/LICENSE +21 -0
  132. package/node_modules/fs-constants/README.md +26 -0
  133. package/node_modules/fs-constants/browser.js +1 -0
  134. package/node_modules/fs-constants/index.js +1 -0
  135. package/node_modules/fs-constants/package.json +19 -0
  136. package/node_modules/github-from-package/.travis.yml +4 -0
  137. package/node_modules/github-from-package/LICENSE +18 -0
  138. package/node_modules/github-from-package/example/package.json +8 -0
  139. package/node_modules/github-from-package/example/url.js +3 -0
  140. package/node_modules/github-from-package/index.js +17 -0
  141. package/node_modules/github-from-package/package.json +30 -0
  142. package/node_modules/github-from-package/readme.markdown +53 -0
  143. package/node_modules/github-from-package/test/a.json +8 -0
  144. package/node_modules/github-from-package/test/b.json +5 -0
  145. package/node_modules/github-from-package/test/c.json +5 -0
  146. package/node_modules/github-from-package/test/d.json +7 -0
  147. package/node_modules/github-from-package/test/e.json +5 -0
  148. package/node_modules/github-from-package/test/url.js +19 -0
  149. package/node_modules/ieee754/LICENSE +11 -0
  150. package/node_modules/ieee754/README.md +51 -0
  151. package/node_modules/ieee754/index.d.ts +10 -0
  152. package/node_modules/ieee754/index.js +85 -0
  153. package/node_modules/ieee754/package.json +52 -0
  154. package/node_modules/ini/LICENSE +15 -0
  155. package/node_modules/ini/README.md +102 -0
  156. package/node_modules/ini/ini.js +206 -0
  157. package/node_modules/ini/package.json +33 -0
  158. package/node_modules/minimist/.eslintrc +29 -0
  159. package/node_modules/minimist/.github/FUNDING.yml +12 -0
  160. package/node_modules/minimist/.nycrc +14 -0
  161. package/node_modules/minimist/CHANGELOG.md +298 -0
  162. package/node_modules/minimist/LICENSE +18 -0
  163. package/node_modules/minimist/README.md +121 -0
  164. package/node_modules/minimist/example/parse.js +4 -0
  165. package/node_modules/minimist/index.js +263 -0
  166. package/node_modules/minimist/package.json +75 -0
  167. package/node_modules/minimist/test/all_bool.js +34 -0
  168. package/node_modules/minimist/test/bool.js +177 -0
  169. package/node_modules/minimist/test/dash.js +43 -0
  170. package/node_modules/minimist/test/default_bool.js +37 -0
  171. package/node_modules/minimist/test/dotted.js +24 -0
  172. package/node_modules/minimist/test/kv_short.js +32 -0
  173. package/node_modules/minimist/test/long.js +33 -0
  174. package/node_modules/minimist/test/num.js +38 -0
  175. package/node_modules/minimist/test/parse.js +209 -0
  176. package/node_modules/minimist/test/parse_modified.js +11 -0
  177. package/node_modules/minimist/test/proto.js +64 -0
  178. package/node_modules/minimist/test/short.js +69 -0
  179. package/node_modules/minimist/test/stop_early.js +17 -0
  180. package/node_modules/minimist/test/unknown.js +104 -0
  181. package/node_modules/minimist/test/whitespace.js +10 -0
  182. package/node_modules/mkdirp-classic/LICENSE +21 -0
  183. package/node_modules/mkdirp-classic/README.md +18 -0
  184. package/node_modules/mkdirp-classic/index.js +98 -0
  185. package/node_modules/mkdirp-classic/package.json +18 -0
  186. package/node_modules/moe-training/DEPLOY_CENTRAL_COMMAND.md +413 -0
  187. package/node_modules/moe-training/client/consent.js +96 -0
  188. package/node_modules/moe-training/client/envelope-builder.js +56 -0
  189. package/node_modules/moe-training/client/index.js +10 -0
  190. package/node_modules/moe-training/client/parsers/claude-code.js +108 -0
  191. package/node_modules/moe-training/client/parsers/codex.js +80 -0
  192. package/node_modules/moe-training/client/parsers/gemini.js +80 -0
  193. package/node_modules/moe-training/client/parsers/grok.js +16 -0
  194. package/node_modules/moe-training/client/parsers/index.js +20 -0
  195. package/node_modules/moe-training/client/scrubber.js +128 -0
  196. package/node_modules/moe-training/client/session-attestation.js +115 -0
  197. package/node_modules/moe-training/client/step-classifier.js +68 -0
  198. package/node_modules/moe-training/client/trajectory-capture.js +307 -0
  199. package/node_modules/moe-training/client/transmission-queue.js +104 -0
  200. package/node_modules/moe-training/package.json +21 -0
  201. package/node_modules/moe-training/server/enrichment.js +24 -0
  202. package/node_modules/moe-training/server/index.js +119 -0
  203. package/node_modules/moe-training/server/ledger.js +110 -0
  204. package/node_modules/moe-training/server/routes/ingest.js +96 -0
  205. package/node_modules/moe-training/server/routes/sessions.js +43 -0
  206. package/node_modules/moe-training/server/routes/stats.js +31 -0
  207. package/node_modules/moe-training/server/scoring.js +63 -0
  208. package/node_modules/moe-training/server/session-registry.js +156 -0
  209. package/node_modules/moe-training/server/stats.js +129 -0
  210. package/node_modules/moe-training/server/stitcher.js +69 -0
  211. package/node_modules/moe-training/server/storage.js +147 -0
  212. package/node_modules/moe-training/server/verifier.js +102 -0
  213. package/node_modules/moe-training/shared/constants.js +30 -0
  214. package/node_modules/moe-training/shared/crypto.js +45 -0
  215. package/node_modules/moe-training/shared/envelope-schema.js +220 -0
  216. package/node_modules/moe-training/test/client/consent.test.js +121 -0
  217. package/node_modules/moe-training/test/client/envelope-builder.test.js +107 -0
  218. package/node_modules/moe-training/test/client/parsers/claude-code.test.js +119 -0
  219. package/node_modules/moe-training/test/client/parsers/codex.test.js +83 -0
  220. package/node_modules/moe-training/test/client/parsers/gemini.test.js +99 -0
  221. package/node_modules/moe-training/test/client/scrubber.test.js +143 -0
  222. package/node_modules/moe-training/test/client/session-attestation-security.test.js +95 -0
  223. package/node_modules/moe-training/test/client/step-classifier.test.js +135 -0
  224. package/node_modules/moe-training/test/client/transmission-queue.test.js +33 -0
  225. package/node_modules/moe-training/test/integration/handshake.test.js +260 -0
  226. package/node_modules/moe-training/test/server/ingest-security.test.js +166 -0
  227. package/node_modules/moe-training/test/server/ledger.test.js +131 -0
  228. package/node_modules/moe-training/test/server/scoring.test.js +242 -0
  229. package/node_modules/moe-training/test/server/session-registry.test.js +125 -0
  230. package/node_modules/moe-training/test/server/stitcher.test.js +157 -0
  231. package/node_modules/moe-training/test/server/verifier.test.js +232 -0
  232. package/node_modules/moe-training/test/shared/crypto.test.js +87 -0
  233. package/node_modules/moe-training/test/shared/envelope-schema.test.js +351 -0
  234. package/node_modules/napi-build-utils/.github/workflows/run-npm-tests.yml +31 -0
  235. package/node_modules/napi-build-utils/LICENSE +21 -0
  236. package/node_modules/napi-build-utils/README.md +52 -0
  237. package/node_modules/napi-build-utils/index.js +214 -0
  238. package/node_modules/napi-build-utils/index.md +0 -0
  239. package/node_modules/napi-build-utils/package.json +42 -0
  240. package/node_modules/prebuild-install/CHANGELOG.md +131 -0
  241. package/node_modules/prebuild-install/CONTRIBUTING.md +6 -0
  242. package/node_modules/prebuild-install/LICENSE +21 -0
  243. package/node_modules/prebuild-install/README.md +163 -0
  244. package/node_modules/prebuild-install/asset.js +44 -0
  245. package/node_modules/prebuild-install/bin.js +78 -0
  246. package/node_modules/prebuild-install/download.js +142 -0
  247. package/node_modules/prebuild-install/error.js +14 -0
  248. package/node_modules/prebuild-install/help.txt +16 -0
  249. package/node_modules/prebuild-install/index.js +1 -0
  250. package/node_modules/prebuild-install/log.js +33 -0
  251. package/node_modules/prebuild-install/node_modules/node-abi/LICENSE +21 -0
  252. package/node_modules/prebuild-install/node_modules/node-abi/README.md +54 -0
  253. package/node_modules/prebuild-install/node_modules/node-abi/abi_registry.json +439 -0
  254. package/node_modules/prebuild-install/node_modules/node-abi/index.js +179 -0
  255. package/node_modules/prebuild-install/node_modules/node-abi/package.json +45 -0
  256. package/node_modules/prebuild-install/node_modules/semver/LICENSE +15 -0
  257. package/node_modules/prebuild-install/node_modules/semver/README.md +665 -0
  258. package/node_modules/prebuild-install/node_modules/semver/bin/semver.js +191 -0
  259. package/node_modules/prebuild-install/node_modules/semver/classes/comparator.js +143 -0
  260. package/node_modules/prebuild-install/node_modules/semver/classes/index.js +7 -0
  261. package/node_modules/prebuild-install/node_modules/semver/classes/range.js +557 -0
  262. package/node_modules/prebuild-install/node_modules/semver/classes/semver.js +333 -0
  263. package/node_modules/prebuild-install/node_modules/semver/functions/clean.js +8 -0
  264. package/node_modules/prebuild-install/node_modules/semver/functions/cmp.js +54 -0
  265. package/node_modules/prebuild-install/node_modules/semver/functions/coerce.js +62 -0
  266. package/node_modules/prebuild-install/node_modules/semver/functions/compare-build.js +9 -0
  267. package/node_modules/prebuild-install/node_modules/semver/functions/compare-loose.js +5 -0
  268. package/node_modules/prebuild-install/node_modules/semver/functions/compare.js +7 -0
  269. package/node_modules/prebuild-install/node_modules/semver/functions/diff.js +60 -0
  270. package/node_modules/prebuild-install/node_modules/semver/functions/eq.js +5 -0
  271. package/node_modules/prebuild-install/node_modules/semver/functions/gt.js +5 -0
  272. package/node_modules/prebuild-install/node_modules/semver/functions/gte.js +5 -0
  273. package/node_modules/prebuild-install/node_modules/semver/functions/inc.js +21 -0
  274. package/node_modules/prebuild-install/node_modules/semver/functions/lt.js +5 -0
  275. package/node_modules/prebuild-install/node_modules/semver/functions/lte.js +5 -0
  276. package/node_modules/prebuild-install/node_modules/semver/functions/major.js +5 -0
  277. package/node_modules/prebuild-install/node_modules/semver/functions/minor.js +5 -0
  278. package/node_modules/prebuild-install/node_modules/semver/functions/neq.js +5 -0
  279. package/node_modules/prebuild-install/node_modules/semver/functions/parse.js +18 -0
  280. package/node_modules/prebuild-install/node_modules/semver/functions/patch.js +5 -0
  281. package/node_modules/prebuild-install/node_modules/semver/functions/prerelease.js +8 -0
  282. package/node_modules/prebuild-install/node_modules/semver/functions/rcompare.js +5 -0
  283. package/node_modules/prebuild-install/node_modules/semver/functions/rsort.js +5 -0
  284. package/node_modules/prebuild-install/node_modules/semver/functions/satisfies.js +12 -0
  285. package/node_modules/prebuild-install/node_modules/semver/functions/sort.js +5 -0
  286. package/node_modules/prebuild-install/node_modules/semver/functions/valid.js +8 -0
  287. package/node_modules/prebuild-install/node_modules/semver/index.js +91 -0
  288. package/node_modules/prebuild-install/node_modules/semver/internal/constants.js +37 -0
  289. package/node_modules/prebuild-install/node_modules/semver/internal/debug.js +11 -0
  290. package/node_modules/prebuild-install/node_modules/semver/internal/identifiers.js +29 -0
  291. package/node_modules/prebuild-install/node_modules/semver/internal/lrucache.js +42 -0
  292. package/node_modules/prebuild-install/node_modules/semver/internal/parse-options.js +17 -0
  293. package/node_modules/prebuild-install/node_modules/semver/internal/re.js +223 -0
  294. package/node_modules/prebuild-install/node_modules/semver/package.json +78 -0
  295. package/node_modules/prebuild-install/node_modules/semver/preload.js +4 -0
  296. package/node_modules/prebuild-install/node_modules/semver/range.bnf +16 -0
  297. package/node_modules/prebuild-install/node_modules/semver/ranges/gtr.js +6 -0
  298. package/node_modules/prebuild-install/node_modules/semver/ranges/intersects.js +9 -0
  299. package/node_modules/prebuild-install/node_modules/semver/ranges/ltr.js +6 -0
  300. package/node_modules/prebuild-install/node_modules/semver/ranges/max-satisfying.js +27 -0
  301. package/node_modules/prebuild-install/node_modules/semver/ranges/min-satisfying.js +26 -0
  302. package/node_modules/prebuild-install/node_modules/semver/ranges/min-version.js +63 -0
  303. package/node_modules/prebuild-install/node_modules/semver/ranges/outside.js +82 -0
  304. package/node_modules/prebuild-install/node_modules/semver/ranges/simplify.js +49 -0
  305. package/node_modules/prebuild-install/node_modules/semver/ranges/subset.js +249 -0
  306. package/node_modules/prebuild-install/node_modules/semver/ranges/to-comparators.js +10 -0
  307. package/node_modules/prebuild-install/node_modules/semver/ranges/valid.js +13 -0
  308. package/node_modules/prebuild-install/package.json +67 -0
  309. package/node_modules/prebuild-install/proxy.js +35 -0
  310. package/node_modules/prebuild-install/rc.js +64 -0
  311. package/node_modules/prebuild-install/util.js +143 -0
  312. package/node_modules/pump/.github/FUNDING.yml +2 -0
  313. package/node_modules/pump/.travis.yml +5 -0
  314. package/node_modules/pump/LICENSE +21 -0
  315. package/node_modules/pump/README.md +74 -0
  316. package/node_modules/pump/SECURITY.md +5 -0
  317. package/node_modules/pump/empty.js +1 -0
  318. package/node_modules/pump/index.js +86 -0
  319. package/node_modules/pump/package.json +30 -0
  320. package/node_modules/pump/test-browser.js +66 -0
  321. package/node_modules/pump/test-node.js +53 -0
  322. package/node_modules/rc/LICENSE.APACHE2 +15 -0
  323. package/node_modules/rc/LICENSE.BSD +26 -0
  324. package/node_modules/rc/LICENSE.MIT +24 -0
  325. package/node_modules/rc/README.md +227 -0
  326. package/node_modules/rc/browser.js +7 -0
  327. package/node_modules/rc/cli.js +4 -0
  328. package/node_modules/rc/index.js +53 -0
  329. package/node_modules/rc/lib/utils.js +104 -0
  330. package/node_modules/rc/package.json +29 -0
  331. package/node_modules/rc/test/ini.js +16 -0
  332. package/node_modules/rc/test/nested-env-vars.js +50 -0
  333. package/node_modules/rc/test/test.js +59 -0
  334. package/node_modules/readable-stream/CONTRIBUTING.md +38 -0
  335. package/node_modules/readable-stream/GOVERNANCE.md +136 -0
  336. package/node_modules/readable-stream/LICENSE +47 -0
  337. package/node_modules/readable-stream/README.md +106 -0
  338. package/node_modules/readable-stream/errors-browser.js +127 -0
  339. package/node_modules/readable-stream/errors.js +116 -0
  340. package/node_modules/readable-stream/experimentalWarning.js +17 -0
  341. package/node_modules/readable-stream/lib/_stream_duplex.js +126 -0
  342. package/node_modules/readable-stream/lib/_stream_passthrough.js +37 -0
  343. package/node_modules/readable-stream/lib/_stream_readable.js +1027 -0
  344. package/node_modules/readable-stream/lib/_stream_transform.js +190 -0
  345. package/node_modules/readable-stream/lib/_stream_writable.js +641 -0
  346. package/node_modules/readable-stream/lib/internal/streams/async_iterator.js +180 -0
  347. package/node_modules/readable-stream/lib/internal/streams/buffer_list.js +183 -0
  348. package/node_modules/readable-stream/lib/internal/streams/destroy.js +96 -0
  349. package/node_modules/readable-stream/lib/internal/streams/end-of-stream.js +86 -0
  350. package/node_modules/readable-stream/lib/internal/streams/from-browser.js +3 -0
  351. package/node_modules/readable-stream/lib/internal/streams/from.js +52 -0
  352. package/node_modules/readable-stream/lib/internal/streams/pipeline.js +86 -0
  353. package/node_modules/readable-stream/lib/internal/streams/state.js +22 -0
  354. package/node_modules/readable-stream/lib/internal/streams/stream-browser.js +1 -0
  355. package/node_modules/readable-stream/lib/internal/streams/stream.js +1 -0
  356. package/node_modules/readable-stream/package.json +68 -0
  357. package/node_modules/readable-stream/readable-browser.js +9 -0
  358. package/node_modules/readable-stream/readable.js +16 -0
  359. package/node_modules/simple-concat/.travis.yml +3 -0
  360. package/node_modules/simple-concat/LICENSE +20 -0
  361. package/node_modules/simple-concat/README.md +44 -0
  362. package/node_modules/simple-concat/index.js +15 -0
  363. package/node_modules/simple-concat/package.json +47 -0
  364. package/node_modules/simple-concat/test/basic.js +41 -0
  365. package/node_modules/simple-get/.github/dependabot.yml +15 -0
  366. package/node_modules/simple-get/.github/workflows/ci.yml +23 -0
  367. package/node_modules/simple-get/LICENSE +20 -0
  368. package/node_modules/simple-get/README.md +333 -0
  369. package/node_modules/simple-get/index.js +108 -0
  370. package/node_modules/simple-get/package.json +67 -0
  371. package/node_modules/string_decoder/LICENSE +48 -0
  372. package/node_modules/string_decoder/README.md +47 -0
  373. package/node_modules/string_decoder/lib/string_decoder.js +296 -0
  374. package/node_modules/string_decoder/package.json +34 -0
  375. package/node_modules/strip-json-comments/index.js +70 -0
  376. package/node_modules/strip-json-comments/license +21 -0
  377. package/node_modules/strip-json-comments/package.json +42 -0
  378. package/node_modules/strip-json-comments/readme.md +64 -0
  379. package/node_modules/tar-fs/.travis.yml +6 -0
  380. package/node_modules/tar-fs/LICENSE +21 -0
  381. package/node_modules/tar-fs/README.md +165 -0
  382. package/node_modules/tar-fs/index.js +363 -0
  383. package/node_modules/tar-fs/node_modules/chownr/LICENSE +15 -0
  384. package/node_modules/tar-fs/node_modules/chownr/README.md +3 -0
  385. package/node_modules/tar-fs/node_modules/chownr/chownr.js +167 -0
  386. package/node_modules/tar-fs/node_modules/chownr/package.json +29 -0
  387. package/node_modules/tar-fs/package.json +41 -0
  388. package/node_modules/tar-fs/test/fixtures/a/hello.txt +1 -0
  389. package/node_modules/tar-fs/test/fixtures/b/a/test.txt +1 -0
  390. package/node_modules/tar-fs/test/fixtures/d/file1 +0 -0
  391. package/node_modules/tar-fs/test/fixtures/d/file2 +0 -0
  392. package/node_modules/tar-fs/test/fixtures/d/sub-dir/file5 +0 -0
  393. package/node_modules/tar-fs/test/fixtures/d/sub-files/file3 +0 -0
  394. package/node_modules/tar-fs/test/fixtures/d/sub-files/file4 +0 -0
  395. package/node_modules/tar-fs/test/fixtures/e/directory/.ignore +0 -0
  396. package/node_modules/tar-fs/test/fixtures/e/file +0 -0
  397. package/node_modules/tar-fs/test/fixtures/invalid.tar +0 -0
  398. package/node_modules/tar-fs/test/index.js +346 -0
  399. package/node_modules/tar-stream/LICENSE +21 -0
  400. package/node_modules/tar-stream/README.md +168 -0
  401. package/node_modules/tar-stream/extract.js +257 -0
  402. package/node_modules/tar-stream/headers.js +295 -0
  403. package/node_modules/tar-stream/index.js +2 -0
  404. package/node_modules/tar-stream/pack.js +255 -0
  405. package/node_modules/tar-stream/package.json +58 -0
  406. package/node_modules/tar-stream/sandbox.js +11 -0
  407. package/node_modules/tunnel-agent/LICENSE +55 -0
  408. package/node_modules/tunnel-agent/README.md +4 -0
  409. package/node_modules/tunnel-agent/index.js +244 -0
  410. package/node_modules/tunnel-agent/package.json +22 -0
  411. package/node_modules/util-deprecate/History.md +16 -0
  412. package/node_modules/util-deprecate/LICENSE +24 -0
  413. package/node_modules/util-deprecate/README.md +53 -0
  414. package/node_modules/util-deprecate/browser.js +67 -0
  415. package/node_modules/util-deprecate/node.js +6 -0
  416. package/node_modules/util-deprecate/package.json +27 -0
  417. package/node_modules/uuid/CHANGELOG.md +274 -0
  418. package/node_modules/uuid/CONTRIBUTING.md +18 -0
  419. package/node_modules/uuid/LICENSE.md +9 -0
  420. package/node_modules/uuid/README.md +466 -0
  421. package/node_modules/uuid/dist/bin/uuid +2 -0
  422. package/node_modules/uuid/dist/commonjs-browser/index.js +79 -0
  423. package/node_modules/uuid/dist/commonjs-browser/md5.js +223 -0
  424. package/node_modules/uuid/dist/commonjs-browser/native.js +11 -0
  425. package/node_modules/uuid/dist/commonjs-browser/nil.js +8 -0
  426. package/node_modules/uuid/dist/commonjs-browser/parse.js +45 -0
  427. package/node_modules/uuid/dist/commonjs-browser/regex.js +8 -0
  428. package/node_modules/uuid/dist/commonjs-browser/rng.js +25 -0
  429. package/node_modules/uuid/dist/commonjs-browser/sha1.js +104 -0
  430. package/node_modules/uuid/dist/commonjs-browser/stringify.js +44 -0
  431. package/node_modules/uuid/dist/commonjs-browser/v1.js +107 -0
  432. package/node_modules/uuid/dist/commonjs-browser/v3.js +16 -0
  433. package/node_modules/uuid/dist/commonjs-browser/v35.js +80 -0
  434. package/node_modules/uuid/dist/commonjs-browser/v4.js +43 -0
  435. package/node_modules/uuid/dist/commonjs-browser/v5.js +16 -0
  436. package/node_modules/uuid/dist/commonjs-browser/validate.js +17 -0
  437. package/node_modules/uuid/dist/commonjs-browser/version.js +21 -0
  438. package/node_modules/uuid/dist/esm-browser/index.js +9 -0
  439. package/node_modules/uuid/dist/esm-browser/md5.js +215 -0
  440. package/node_modules/uuid/dist/esm-browser/native.js +4 -0
  441. package/node_modules/uuid/dist/esm-browser/nil.js +1 -0
  442. package/node_modules/uuid/dist/esm-browser/parse.js +35 -0
  443. package/node_modules/uuid/dist/esm-browser/regex.js +1 -0
  444. package/node_modules/uuid/dist/esm-browser/rng.js +18 -0
  445. package/node_modules/uuid/dist/esm-browser/sha1.js +96 -0
  446. package/node_modules/uuid/dist/esm-browser/stringify.js +33 -0
  447. package/node_modules/uuid/dist/esm-browser/v1.js +95 -0
  448. package/node_modules/uuid/dist/esm-browser/v3.js +4 -0
  449. package/node_modules/uuid/dist/esm-browser/v35.js +66 -0
  450. package/node_modules/uuid/dist/esm-browser/v4.js +29 -0
  451. package/node_modules/uuid/dist/esm-browser/v5.js +4 -0
  452. package/node_modules/uuid/dist/esm-browser/validate.js +7 -0
  453. package/node_modules/uuid/dist/esm-browser/version.js +11 -0
  454. package/node_modules/uuid/dist/esm-node/index.js +9 -0
  455. package/node_modules/uuid/dist/esm-node/md5.js +13 -0
  456. package/node_modules/uuid/dist/esm-node/native.js +4 -0
  457. package/node_modules/uuid/dist/esm-node/nil.js +1 -0
  458. package/node_modules/uuid/dist/esm-node/parse.js +35 -0
  459. package/node_modules/uuid/dist/esm-node/regex.js +1 -0
  460. package/node_modules/uuid/dist/esm-node/rng.js +12 -0
  461. package/node_modules/uuid/dist/esm-node/sha1.js +13 -0
  462. package/node_modules/uuid/dist/esm-node/stringify.js +33 -0
  463. package/node_modules/uuid/dist/esm-node/v1.js +95 -0
  464. package/node_modules/uuid/dist/esm-node/v3.js +4 -0
  465. package/node_modules/uuid/dist/esm-node/v35.js +66 -0
  466. package/node_modules/uuid/dist/esm-node/v4.js +29 -0
  467. package/node_modules/uuid/dist/esm-node/v5.js +4 -0
  468. package/node_modules/uuid/dist/esm-node/validate.js +7 -0
  469. package/node_modules/uuid/dist/esm-node/version.js +11 -0
  470. package/node_modules/uuid/dist/index.js +79 -0
  471. package/node_modules/uuid/dist/md5-browser.js +223 -0
  472. package/node_modules/uuid/dist/md5.js +23 -0
  473. package/node_modules/uuid/dist/native-browser.js +11 -0
  474. package/node_modules/uuid/dist/native.js +15 -0
  475. package/node_modules/uuid/dist/nil.js +8 -0
  476. package/node_modules/uuid/dist/parse.js +45 -0
  477. package/node_modules/uuid/dist/regex.js +8 -0
  478. package/node_modules/uuid/dist/rng-browser.js +25 -0
  479. package/node_modules/uuid/dist/rng.js +24 -0
  480. package/node_modules/uuid/dist/sha1-browser.js +104 -0
  481. package/node_modules/uuid/dist/sha1.js +23 -0
  482. package/node_modules/uuid/dist/stringify.js +44 -0
  483. package/node_modules/uuid/dist/uuid-bin.js +85 -0
  484. package/node_modules/uuid/dist/v1.js +107 -0
  485. package/node_modules/uuid/dist/v3.js +16 -0
  486. package/node_modules/uuid/dist/v35.js +80 -0
  487. package/node_modules/uuid/dist/v4.js +43 -0
  488. package/node_modules/uuid/dist/v5.js +16 -0
  489. package/node_modules/uuid/dist/validate.js +17 -0
  490. package/node_modules/uuid/dist/version.js +21 -0
  491. package/node_modules/uuid/package.json +135 -0
  492. package/node_modules/uuid/wrapper.mjs +10 -0
  493. package/package.json +5 -3
  494. package/packages/cli/package.json +1 -1
  495. package/packages/daemon/package.json +1 -1
  496. package/packages/daemon/src/api.js +39 -23
  497. package/packages/daemon/src/introducer.js +21 -6
  498. package/packages/daemon/src/process.js +20 -2
  499. package/packages/daemon/src/providers/gemini.js +27 -28
  500. package/packages/gui/dist/assets/{index-VB4_k5Pz.js → index-BgTyFy4f.js} +331 -331
  501. package/packages/gui/dist/assets/{index-Bo6AeNmM.css → index-QADLyUj5.css} +1 -1
  502. package/packages/gui/dist/index.html +2 -2
  503. package/packages/gui/package.json +1 -1
  504. package/packages/gui/src/components/agents/agent-file-tree.jsx +68 -16
  505. package/packages/gui/src/components/agents/agent-panel.jsx +2 -0
  506. package/packages/gui/src/components/agents/code-review.jsx +9 -1
  507. package/packages/gui/src/components/agents/workspace-mode.jsx +2 -2
  508. package/packages/gui/src/components/editor/code-editor.jsx +1 -1
  509. package/packages/gui/src/stores/groove.js +40 -26
  510. package/packages/gui/src/views/agents.jsx +14 -65
  511. package/workspace.png +0 -0
@@ -0,0 +1,147 @@
1
+ // FSL-1.1-Apache-2.0 — see LICENSE
2
+
3
+ import { mkdirSync, appendFileSync, readFileSync, readdirSync, statSync, existsSync } from 'node:fs';
4
+ import { join } from 'node:path';
5
+
6
+ const QUOTA_BYTES = 50 * 1024 * 1024 * 1024; // 50GB
7
+ const WARN_BYTES = 40 * 1024 * 1024 * 1024; // 40GB
8
+
9
+ export class EnvelopeStorage {
10
+ constructor(basePath = './data/envelopes') {
11
+ this.basePath = basePath;
12
+ if (!existsSync(basePath)) mkdirSync(basePath, { recursive: true, mode: 0o700 });
13
+ }
14
+
15
+ checkQuota() {
16
+ const files = this._listFiles();
17
+ let total = 0;
18
+ for (const file of files) {
19
+ try { total += statSync(file).size; } catch { /* skip */ }
20
+ }
21
+ if (total > WARN_BYTES && total <= QUOTA_BYTES) {
22
+ console.warn(`[storage] WARNING: storage at ${(total / (1024 * 1024 * 1024)).toFixed(1)}GB, approaching 50GB quota`);
23
+ }
24
+ return total < QUOTA_BYTES;
25
+ }
26
+
27
+ store(envelope) {
28
+ if (!this.checkQuota()) {
29
+ throw new Error('STORAGE_QUOTA_EXCEEDED');
30
+ }
31
+
32
+ const date = new Date().toISOString().slice(0, 10);
33
+ const filePath = join(this.basePath, `${date}.jsonl`);
34
+
35
+ if (!existsSync(this.basePath)) {
36
+ mkdirSync(this.basePath, { recursive: true, mode: 0o700 });
37
+ }
38
+
39
+ const line = JSON.stringify(envelope) + '\n';
40
+ appendFileSync(filePath, line, { mode: 0o600 });
41
+ }
42
+
43
+ getSessionEnvelopes(sessionId) {
44
+ const envelopes = [];
45
+ const files = this._listFiles();
46
+
47
+ for (const file of files) {
48
+ const lines = readFileSync(file, 'utf-8').split('\n').filter(Boolean);
49
+ for (const line of lines) {
50
+ try {
51
+ const env = JSON.parse(line);
52
+ if (env.session_id === sessionId) envelopes.push(env);
53
+ } catch { /* skip malformed lines */ }
54
+ }
55
+ }
56
+
57
+ return envelopes.sort((a, b) => (a.chunk_sequence ?? 0) - (b.chunk_sequence ?? 0));
58
+ }
59
+
60
+ getDateRange(startDate, endDate) {
61
+ const envelopes = [];
62
+ const files = this._listFiles();
63
+
64
+ for (const file of files) {
65
+ const fileName = file.split('/').pop().replace('.jsonl', '');
66
+ if (fileName < startDate || fileName > endDate) continue;
67
+
68
+ const lines = readFileSync(file, 'utf-8').split('\n').filter(Boolean);
69
+ for (const line of lines) {
70
+ try {
71
+ envelopes.push(JSON.parse(line));
72
+ } catch { /* skip */ }
73
+ }
74
+ }
75
+
76
+ return envelopes;
77
+ }
78
+
79
+ getDailyStats(days = 7) {
80
+ const stats = [];
81
+ const files = this._listFiles();
82
+
83
+ const cutoff = new Date();
84
+ cutoff.setDate(cutoff.getDate() - days);
85
+ const cutoffStr = cutoff.toISOString().slice(0, 10);
86
+
87
+ for (const file of files) {
88
+ const date = file.split('/').pop().replace('.jsonl', '');
89
+ if (date < cutoffStr) continue;
90
+
91
+ const lines = readFileSync(file, 'utf-8').split('\n').filter(Boolean);
92
+ let stepCount = 0;
93
+ for (const line of lines) {
94
+ try {
95
+ const env = JSON.parse(line);
96
+ stepCount += env.trajectory_log?.length ?? 0;
97
+ } catch { /* skip */ }
98
+ }
99
+
100
+ stats.push({ date, envelopeCount: lines.length, stepCount });
101
+ }
102
+
103
+ return stats.sort((a, b) => a.date.localeCompare(b.date));
104
+ }
105
+
106
+ getTotalStats() {
107
+ const files = this._listFiles();
108
+ let totalEnvelopes = 0;
109
+ let totalSteps = 0;
110
+ let storageSizeBytes = 0;
111
+ const contributors = new Set();
112
+ const sessions = new Set();
113
+
114
+ for (const file of files) {
115
+ const stat = statSync(file);
116
+ storageSizeBytes += stat.size;
117
+
118
+ const lines = readFileSync(file, 'utf-8').split('\n').filter(Boolean);
119
+ totalEnvelopes += lines.length;
120
+
121
+ for (const line of lines) {
122
+ try {
123
+ const env = JSON.parse(line);
124
+ totalSteps += env.trajectory_log?.length ?? 0;
125
+ if (env.contributor_id) contributors.add(env.contributor_id);
126
+ if (env.session_id) sessions.add(env.session_id);
127
+ } catch { /* skip */ }
128
+ }
129
+ }
130
+
131
+ return {
132
+ totalEnvelopes,
133
+ totalSteps,
134
+ storageSizeMb: +(storageSizeBytes / 1_048_576).toFixed(2),
135
+ uniqueContributors: contributors.size,
136
+ uniqueSessions: sessions.size,
137
+ };
138
+ }
139
+
140
+ _listFiles() {
141
+ if (!existsSync(this.basePath)) return [];
142
+ return readdirSync(this.basePath)
143
+ .filter(f => f.endsWith('.jsonl'))
144
+ .map(f => join(this.basePath, f))
145
+ .sort();
146
+ }
147
+ }
@@ -0,0 +1,102 @@
1
+ // FSL-1.1-Apache-2.0 — see LICENSE
2
+
3
+ import { verifyEnvelope } from '../shared/crypto.js';
4
+
5
+ let validateEnvelope;
6
+ try {
7
+ const schema = await import('../shared/envelope-schema.js');
8
+ validateEnvelope = schema.validateEnvelope;
9
+ } catch {
10
+ validateEnvelope = () => ({ valid: true });
11
+ }
12
+
13
+ export class EnvelopeVerifier {
14
+ constructor(sessionRegistry) {
15
+ this.sessionRegistry = sessionRegistry;
16
+ }
17
+
18
+ verify(envelope) {
19
+ const sessionId = envelope.session_id;
20
+ if (!sessionId) return { valid: false, reason: 'missing session_id' };
21
+
22
+ const session = this.sessionRegistry.getSession(sessionId);
23
+ if (!session) return { valid: false, reason: 'unknown session_id' };
24
+ if (session.status !== 'active') return { valid: false, reason: 'session is closed' };
25
+
26
+ const attestation = envelope.attestation;
27
+ if (!attestation) return { valid: false, reason: 'missing attestation' };
28
+
29
+ if (!attestation.session_hmac || typeof attestation.session_hmac !== 'string' || attestation.session_hmac.length === 0) {
30
+ return { valid: false, reason: 'empty or missing HMAC' };
31
+ }
32
+
33
+ // HMAC covers the entire envelope EXCEPT the attestation block
34
+ const envelopeForHmac = { ...envelope };
35
+ delete envelopeForHmac.attestation;
36
+ const envelopeBytes = JSON.stringify(envelopeForHmac);
37
+
38
+ const hmacValid = verifyEnvelope(
39
+ session.shared_secret,
40
+ envelopeBytes,
41
+ attestation.sequence,
42
+ attestation.session_hmac
43
+ );
44
+ if (!hmacValid) return { valid: false, reason: 'HMAC verification failed' };
45
+
46
+ // Atomic sequence check + increment (prevents race conditions)
47
+ const seqResult = this.sessionRegistry.checkAndIncrementSequence(sessionId, attestation.sequence);
48
+ if (!seqResult.valid) {
49
+ return { valid: false, reason: seqResult.reason };
50
+ }
51
+
52
+ const schemaResult = validateEnvelope(envelope);
53
+ if (!schemaResult.valid) {
54
+ return { valid: false, reason: `schema validation failed: ${schemaResult.reason || schemaResult.errors?.join(', ')}` };
55
+ }
56
+
57
+ return { valid: true };
58
+ }
59
+
60
+ verifyClose(envelope) {
61
+ const sessionId = envelope.session_id;
62
+ if (!sessionId) return { valid: false, reason: 'missing session_id' };
63
+
64
+ const session = this.sessionRegistry.getSession(sessionId);
65
+ if (!session) return { valid: false, reason: 'unknown session_id' };
66
+ if (session.status !== 'active') return { valid: false, reason: 'session already closed' };
67
+
68
+ const attestation = envelope.attestation;
69
+ if (!attestation) return { valid: false, reason: 'missing attestation' };
70
+
71
+ if (!attestation.session_hmac || typeof attestation.session_hmac !== 'string' || attestation.session_hmac.length === 0) {
72
+ return { valid: false, reason: 'empty or missing HMAC' };
73
+ }
74
+
75
+ // HMAC covers the entire envelope EXCEPT the attestation block
76
+ const envelopeForHmac = { ...envelope };
77
+ delete envelopeForHmac.attestation;
78
+ const envelopeBytes = JSON.stringify(envelopeForHmac);
79
+
80
+ const hmacValid = verifyEnvelope(
81
+ session.shared_secret,
82
+ envelopeBytes,
83
+ attestation.sequence,
84
+ attestation.session_hmac
85
+ );
86
+ if (!hmacValid) return { valid: false, reason: 'HMAC verification failed' };
87
+
88
+ // Sequence check for close envelopes too
89
+ const seqResult = this.sessionRegistry.checkAndIncrementSequence(sessionId, attestation.sequence);
90
+ if (!seqResult.valid) {
91
+ return { valid: false, reason: seqResult.reason };
92
+ }
93
+
94
+ const schemaResult = validateEnvelope(envelope);
95
+ if (!schemaResult.valid) {
96
+ return { valid: false, reason: `schema validation failed: ${schemaResult.reason || schemaResult.errors?.join(', ')}` };
97
+ }
98
+
99
+ this.sessionRegistry.closeSession(sessionId);
100
+ return { valid: true };
101
+ }
102
+ }
@@ -0,0 +1,30 @@
1
+ // FSL-1.1-Apache-2.0 — see LICENSE
2
+
3
+ export const CURRENT_CONSENT_VERSION = '1.0';
4
+ export const CHUNK_SIZE = 200;
5
+ export const CHUNK_TIMEOUT_MS = 300_000;
6
+ export const MAX_QUEUE_SIZE = 10_000;
7
+ export const OBSERVATION_TRUNCATE_HEAD = 50;
8
+ export const OBSERVATION_TRUNCATE_TAIL = 20;
9
+ export const SUPPORTED_PROVIDERS = ['claude-code', 'codex', 'gemini'];
10
+
11
+ export const MODEL_TIERS = {
12
+ 'claude-opus-4-6': 5,
13
+ 'claude-opus-4-7': 5,
14
+ 'claude-sonnet-4-6': 3,
15
+ 'gpt-4.5': 5,
16
+ 'o3': 5,
17
+ 'o4-mini': 2,
18
+ 'gemini-2.5-pro': 3,
19
+ 'gemini-2.5-flash': 1.5,
20
+ };
21
+
22
+ export const QUALITY_MULTIPLIERS = {
23
+ correction: 10,
24
+ coordination: 5,
25
+ errorRecovery: 3,
26
+ heavyTask: 2,
27
+ highQuality: 1.5,
28
+ };
29
+
30
+ export const CENTRAL_COMMAND_URL = process.env.GROOVE_CENTRAL_URL || 'https://api.groovedev.ai';
@@ -0,0 +1,45 @@
1
+ // FSL-1.1-Apache-2.0 — see LICENSE
2
+
3
+ import { createECDH, createHmac, createHash, randomBytes } from 'node:crypto';
4
+ import { readFileSync } from 'node:fs';
5
+
6
+ export function generateECDHKeypair() {
7
+ const ecdh = createECDH('prime256v1');
8
+ ecdh.generateKeys();
9
+ return {
10
+ publicKey: ecdh.getPublicKey('base64'),
11
+ privateKey: ecdh.getPrivateKey('base64'),
12
+ };
13
+ }
14
+
15
+ export function deriveSharedSecret(privateKeyB64, otherPublicKeyB64) {
16
+ const ecdh = createECDH('prime256v1');
17
+ ecdh.setPrivateKey(Buffer.from(privateKeyB64, 'base64'));
18
+ const secret = ecdh.computeSecret(Buffer.from(otherPublicKeyB64, 'base64'));
19
+ return secret.toString('base64');
20
+ }
21
+
22
+ // envelopeBytes MUST contain ALL envelope fields EXCEPT attestation (which holds the HMAC itself).
23
+ // Callers must strip attestation before JSON.stringify to produce envelopeBytes.
24
+ export function signEnvelope(sharedSecretB64, envelopeBytes, sequenceNumber) {
25
+ const key = Buffer.from(sharedSecretB64, 'base64');
26
+ const seqBuf = Buffer.alloc(4);
27
+ seqBuf.writeUInt32BE(sequenceNumber);
28
+ const payload = Buffer.concat([seqBuf, Buffer.from(envelopeBytes)]);
29
+ return createHmac('sha256', key).update(payload).digest('hex');
30
+ }
31
+
32
+ export function verifyEnvelope(sharedSecretB64, envelopeBytes, sequenceNumber, hmac) {
33
+ const expected = signEnvelope(sharedSecretB64, envelopeBytes, sequenceNumber);
34
+ if (expected.length !== hmac.length) return false;
35
+ let diff = 0;
36
+ for (let i = 0; i < expected.length; i++) {
37
+ diff |= expected.charCodeAt(i) ^ hmac.charCodeAt(i);
38
+ }
39
+ return diff === 0;
40
+ }
41
+
42
+ export function computeAppHash(filePath) {
43
+ const content = readFileSync(filePath);
44
+ return createHash('sha256').update(content).digest('hex');
45
+ }
@@ -0,0 +1,220 @@
1
+ // FSL-1.1-Apache-2.0 — see LICENSE
2
+
3
+ import { SUPPORTED_PROVIDERS, MODEL_TIERS } from './constants.js';
4
+
5
+ export const STEP_TYPES = ['thought', 'action', 'observation', 'correction', 'resolution', 'error', 'coordination'];
6
+
7
+ const VALID_MODEL_ENGINES = Object.keys(MODEL_TIERS);
8
+ const VALID_COMPLEXITIES = ['light', 'medium', 'heavy'];
9
+ const VALID_OUTCOME_STATUSES = ['SUCCESS', 'CRASH', 'KILLED'];
10
+ const MAX_STEPS_PER_ENVELOPE = 500;
11
+ const MAX_STEP_CONTENT_LENGTH = 10_000;
12
+ const MAX_TOKEN_COUNT = 100_000;
13
+ const MAX_STEP_NUMBER = 50_000;
14
+ const SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1000;
15
+ const ONE_HOUR_MS = 60 * 60 * 1000;
16
+ const HEX_32 = /^[0-9a-f]{32}$/;
17
+ const HEX_64 = /^[0-9a-f]{64}$/;
18
+ const MAX_OUTCOME_NUMERIC = 50_000;
19
+
20
+ export class EnvelopeBuilder {
21
+ constructor() {
22
+ this._steps = [];
23
+ }
24
+
25
+ addStep(step) {
26
+ this._steps.push(step);
27
+ return this;
28
+ }
29
+
30
+ build(envelopeId, sessionId, chunkSequence, contributorId, metadata) {
31
+ return {
32
+ envelope_id: envelopeId,
33
+ session_id: sessionId,
34
+ chunk_sequence: chunkSequence,
35
+ contributor_id: contributorId,
36
+ attestation: { session_hmac: '', sequence: 0, app_version_hash: '' },
37
+ metadata,
38
+ trajectory_log: [...this._steps],
39
+ };
40
+ }
41
+
42
+ static buildSessionClose(envelopeId, sessionId, outcome) {
43
+ return {
44
+ envelope_id: envelopeId,
45
+ session_id: sessionId,
46
+ type: 'SESSION_CLOSE',
47
+ attestation: { session_hmac: '', sequence: 0, app_version_hash: '' },
48
+ outcome,
49
+ };
50
+ }
51
+ }
52
+
53
+ export function validateEnvelope(envelope) {
54
+ const errors = [];
55
+
56
+ if (!envelope) {
57
+ return { valid: false, errors: ['Envelope is null or undefined'] };
58
+ }
59
+
60
+ if (envelope.type === 'SESSION_CLOSE') {
61
+ return validateSessionClose(envelope);
62
+ }
63
+
64
+ if (!envelope.session_id || typeof envelope.session_id !== 'string') {
65
+ errors.push('Missing or invalid session_id');
66
+ }
67
+ if (typeof envelope.chunk_sequence !== 'number') {
68
+ errors.push('Missing or invalid chunk_sequence');
69
+ }
70
+
71
+ // contributor_id: must be 32-char hex (UUID without dashes)
72
+ if (!envelope.contributor_id || typeof envelope.contributor_id !== 'string') {
73
+ errors.push('Missing or invalid contributor_id');
74
+ } else if (!HEX_32.test(envelope.contributor_id)) {
75
+ errors.push('contributor_id must be a 32-character hex string');
76
+ }
77
+
78
+ // Attestation validation
79
+ if (!envelope.attestation || typeof envelope.attestation !== 'object') {
80
+ errors.push('Missing attestation');
81
+ } else {
82
+ if (typeof envelope.attestation.session_hmac !== 'string' || !HEX_64.test(envelope.attestation.session_hmac)) {
83
+ errors.push('attestation.session_hmac must be exactly 64 hex characters');
84
+ }
85
+ if (typeof envelope.attestation.sequence !== 'number' || !Number.isInteger(envelope.attestation.sequence) || envelope.attestation.sequence < 0 || envelope.attestation.sequence > 1_000_000) {
86
+ errors.push('attestation.sequence must be a non-negative integer, max 1000000');
87
+ }
88
+ if (typeof envelope.attestation.app_version_hash !== 'string' || !HEX_64.test(envelope.attestation.app_version_hash)) {
89
+ errors.push('attestation.app_version_hash must be exactly 64 hex characters');
90
+ }
91
+ }
92
+
93
+ // Metadata validation
94
+ if (!envelope.metadata || typeof envelope.metadata !== 'object') {
95
+ errors.push('Missing metadata');
96
+ } else {
97
+ const m = envelope.metadata;
98
+ if (!m.provider || !SUPPORTED_PROVIDERS.includes(m.provider)) {
99
+ errors.push(`metadata.provider must be one of: ${SUPPORTED_PROVIDERS.join(', ')}`);
100
+ }
101
+ if (!m.model_engine || !VALID_MODEL_ENGINES.includes(m.model_engine)) {
102
+ errors.push(`metadata.model_engine must be one of: ${VALID_MODEL_ENGINES.join(', ')}`);
103
+ }
104
+ if (!m.agent_role || typeof m.agent_role !== 'string' || m.agent_role.length > 50) {
105
+ errors.push('metadata.agent_role must be a string, max 50 characters');
106
+ }
107
+ if (!m.agent_id || typeof m.agent_id !== 'string' || m.agent_id.length > 100) {
108
+ errors.push('metadata.agent_id must be a string, max 100 characters');
109
+ }
110
+ if (m.team_size !== undefined && m.team_size !== null) {
111
+ if (!Number.isInteger(m.team_size) || m.team_size < 1 || m.team_size > 50) {
112
+ errors.push('metadata.team_size must be an integer 1-50');
113
+ }
114
+ }
115
+ if (m.task_complexity !== undefined && m.task_complexity !== null) {
116
+ if (!VALID_COMPLEXITIES.includes(m.task_complexity)) {
117
+ errors.push('metadata.task_complexity must be light, medium, or heavy');
118
+ }
119
+ }
120
+ if (m.groove_version !== undefined && m.groove_version !== null) {
121
+ if (typeof m.groove_version !== 'string' || m.groove_version.length > 20) {
122
+ errors.push('metadata.groove_version must be a string, max 20 characters');
123
+ }
124
+ }
125
+ // session_quality is ignored from client — server derives quality
126
+ }
127
+
128
+ // Trajectory log validation
129
+ if (!Array.isArray(envelope.trajectory_log)) {
130
+ errors.push('Missing or invalid trajectory_log');
131
+ } else {
132
+ if (envelope.trajectory_log.length > MAX_STEPS_PER_ENVELOPE) {
133
+ errors.push(`trajectory_log exceeds maximum of ${MAX_STEPS_PER_ENVELOPE} steps (got ${envelope.trajectory_log.length})`);
134
+ }
135
+
136
+ const now = Date.now();
137
+ const sevenDaysAgo = now - SEVEN_DAYS_MS;
138
+ const futureLimit = now + ONE_HOUR_MS;
139
+
140
+ for (let i = 0; i < Math.min(envelope.trajectory_log.length, MAX_STEPS_PER_ENVELOPE); i++) {
141
+ const step = envelope.trajectory_log[i];
142
+ if (!STEP_TYPES.includes(step.type)) {
143
+ errors.push(`Invalid step type "${step.type}" at index ${i}`);
144
+ }
145
+ if (typeof step.step !== 'number' || !Number.isInteger(step.step) || step.step < 0 || step.step > MAX_STEP_NUMBER) {
146
+ errors.push(`step.step must be a non-negative integer, max ${MAX_STEP_NUMBER} at index ${i}`);
147
+ }
148
+ if (typeof step.timestamp !== 'number') {
149
+ errors.push(`Missing timestamp at index ${i}`);
150
+ } else {
151
+ const tsMs = step.timestamp < 1e12 ? step.timestamp * 1000 : step.timestamp;
152
+ if (tsMs < sevenDaysAgo || tsMs > futureLimit) {
153
+ errors.push(`Timestamp out of range at index ${i} (must be within last 7 days, max 1 hour in future)`);
154
+ }
155
+ }
156
+ if (step.content !== undefined && typeof step.content === 'string' && step.content.length > MAX_STEP_CONTENT_LENGTH) {
157
+ errors.push(`step.content exceeds ${MAX_STEP_CONTENT_LENGTH} characters at index ${i}`);
158
+ }
159
+ if (step.token_count !== undefined) {
160
+ if (typeof step.token_count !== 'number' || step.token_count < 0 || step.token_count > MAX_TOKEN_COUNT) {
161
+ errors.push(`step.token_count must be 0-${MAX_TOKEN_COUNT} at index ${i}`);
162
+ }
163
+ }
164
+ }
165
+ }
166
+
167
+ return { valid: errors.length === 0, errors };
168
+ }
169
+
170
+ function validateSessionClose(envelope) {
171
+ const errors = [];
172
+
173
+ if (!envelope.session_id || typeof envelope.session_id !== 'string') {
174
+ errors.push('Missing or invalid session_id');
175
+ }
176
+ if (envelope.type !== 'SESSION_CLOSE') {
177
+ errors.push('Invalid type for SESSION_CLOSE envelope');
178
+ }
179
+
180
+ // Attestation validation
181
+ if (!envelope.attestation || typeof envelope.attestation !== 'object') {
182
+ errors.push('Missing attestation');
183
+ } else {
184
+ if (typeof envelope.attestation.session_hmac !== 'string' || !HEX_64.test(envelope.attestation.session_hmac)) {
185
+ errors.push('attestation.session_hmac must be exactly 64 hex characters');
186
+ }
187
+ if (typeof envelope.attestation.sequence !== 'number' || !Number.isInteger(envelope.attestation.sequence) || envelope.attestation.sequence < 0 || envelope.attestation.sequence > 1_000_000) {
188
+ errors.push('attestation.sequence must be a non-negative integer, max 1000000');
189
+ }
190
+ if (typeof envelope.attestation.app_version_hash !== 'string' || !HEX_64.test(envelope.attestation.app_version_hash)) {
191
+ errors.push('attestation.app_version_hash must be exactly 64 hex characters');
192
+ }
193
+ }
194
+
195
+ // Outcome validation
196
+ if (!envelope.outcome || typeof envelope.outcome !== 'object') {
197
+ errors.push('Missing outcome');
198
+ } else {
199
+ if (!VALID_OUTCOME_STATUSES.includes(envelope.outcome.status)) {
200
+ errors.push(`outcome.status must be one of: ${VALID_OUTCOME_STATUSES.join(', ')}`);
201
+ }
202
+ if (typeof envelope.outcome.total_steps !== 'number' || !Number.isInteger(envelope.outcome.total_steps) || envelope.outcome.total_steps < 0 || envelope.outcome.total_steps > MAX_OUTCOME_NUMERIC) {
203
+ errors.push('Missing or invalid outcome.total_steps');
204
+ }
205
+ if (typeof envelope.outcome.total_chunks !== 'number' || !Number.isInteger(envelope.outcome.total_chunks) || envelope.outcome.total_chunks < 0 || envelope.outcome.total_chunks > MAX_OUTCOME_NUMERIC) {
206
+ errors.push('Missing or invalid outcome.total_chunks');
207
+ }
208
+ const numericFields = ['user_interventions', 'total_tokens', 'duration_seconds', 'files_modified', 'errors_encountered', 'errors_recovered', 'coordination_events'];
209
+ for (const field of numericFields) {
210
+ if (envelope.outcome[field] !== undefined) {
211
+ const v = envelope.outcome[field];
212
+ if (typeof v !== 'number' || !Number.isInteger(v) || v < 0 || v > MAX_OUTCOME_NUMERIC) {
213
+ errors.push(`outcome.${field} must be a non-negative integer, max ${MAX_OUTCOME_NUMERIC}`);
214
+ }
215
+ }
216
+ }
217
+ }
218
+
219
+ return { valid: errors.length === 0, errors };
220
+ }
@@ -0,0 +1,121 @@
1
+ // FSL-1.1-Apache-2.0 — see LICENSE
2
+
3
+ import { describe, it, beforeEach, afterEach } from 'node:test';
4
+ import assert from 'node:assert/strict';
5
+ import { mkdtempSync, rmSync, existsSync, readFileSync } from 'node:fs';
6
+ import { join } from 'node:path';
7
+ import { tmpdir } from 'node:os';
8
+ import { ConsentManager } from '../../client/consent.js';
9
+
10
+ describe('ConsentManager', () => {
11
+ let tmpDir, dbPath, manager;
12
+
13
+ beforeEach(() => {
14
+ tmpDir = mkdtempSync(join(tmpdir(), 'consent-test-'));
15
+ dbPath = join(tmpDir, 'consent.db');
16
+ manager = new ConsentManager(dbPath);
17
+ });
18
+
19
+ afterEach(() => {
20
+ manager.close();
21
+ rmSync(tmpDir, { recursive: true });
22
+ });
23
+
24
+ it('opt in then isOptedIn returns true', () => {
25
+ manager.recordConsent('user1', true, '1.0');
26
+ assert.equal(manager.isOptedIn('user1'), true);
27
+ });
28
+
29
+ it('opt out then isOptedIn returns false', () => {
30
+ manager.recordConsent('user1', true, '1.0');
31
+ manager.revokeConsent('user1');
32
+ assert.equal(manager.isOptedIn('user1'), false);
33
+ });
34
+
35
+ it('no consent record returns false', () => {
36
+ assert.equal(manager.isOptedIn('nonexistent'), false);
37
+ });
38
+
39
+ it('version mismatch returns false', () => {
40
+ manager.recordConsent('user1', true, '0.9');
41
+ assert.equal(manager.isOptedIn('user1'), false);
42
+ });
43
+
44
+ it('getOptedInCount counts correctly', () => {
45
+ manager.recordConsent('user1', true, '1.0');
46
+ manager.recordConsent('user2', true, '1.0');
47
+ manager.recordConsent('user3', false, '1.0');
48
+ assert.equal(manager.getOptedInCount(), 2);
49
+ });
50
+
51
+ it('getConsentHistory returns all records', () => {
52
+ manager.recordConsent('user1', true, '1.0', { source: 'ui' });
53
+ manager.revokeConsent('user1');
54
+ const history = manager.getConsentHistory('user1');
55
+ assert.equal(history.length, 2);
56
+ assert.equal(history[0].opted_in, true);
57
+ assert.deepEqual(history[0].metadata, { source: 'ui' });
58
+ assert.equal(history[1].opted_in, false);
59
+ });
60
+ });
61
+
62
+ describe('ConsentManager.getOrCreateUserId', () => {
63
+ let tmpDir, userIdPath;
64
+
65
+ beforeEach(() => {
66
+ tmpDir = mkdtempSync(join(tmpdir(), 'userid-test-'));
67
+ userIdPath = join(tmpDir, 'user_id');
68
+ });
69
+
70
+ afterEach(() => {
71
+ rmSync(tmpDir, { recursive: true });
72
+ });
73
+
74
+ it('creates user_id file and returns id', () => {
75
+ const id = ConsentManager.getOrCreateUserId(userIdPath);
76
+ assert.ok(id.length > 0);
77
+ assert.ok(existsSync(userIdPath));
78
+ });
79
+
80
+ it('returns same id on second call', () => {
81
+ const id1 = ConsentManager.getOrCreateUserId(userIdPath);
82
+ const id2 = ConsentManager.getOrCreateUserId(userIdPath);
83
+ assert.equal(id1, id2);
84
+ });
85
+ });
86
+
87
+ describe('ConsentManager.isCaptureEnabled', () => {
88
+ let tmpDir;
89
+
90
+ beforeEach(() => {
91
+ tmpDir = mkdtempSync(join(tmpdir(), 'capture-test-'));
92
+ });
93
+
94
+ afterEach(() => {
95
+ rmSync(tmpDir, { recursive: true });
96
+ });
97
+
98
+ it('returns false when no user_id file exists', () => {
99
+ const result = ConsentManager.isCaptureEnabled(join(tmpDir, 'no_file'), join(tmpDir, 'c.db'));
100
+ assert.equal(result, false);
101
+ });
102
+
103
+ it('returns false when user not opted in', () => {
104
+ const uidPath = join(tmpDir, 'user_id');
105
+ const uid = ConsentManager.getOrCreateUserId(uidPath);
106
+ const dbPath = join(tmpDir, 'consent.db');
107
+ const result = ConsentManager.isCaptureEnabled(uidPath, dbPath);
108
+ assert.equal(result, false);
109
+ });
110
+
111
+ it('returns true when user is opted in', () => {
112
+ const uidPath = join(tmpDir, 'user_id');
113
+ const uid = ConsentManager.getOrCreateUserId(uidPath);
114
+ const dbPath = join(tmpDir, 'consent.db');
115
+ const mgr = new ConsentManager(dbPath);
116
+ mgr.recordConsent(uid, true, '1.0');
117
+ mgr.close();
118
+ const result = ConsentManager.isCaptureEnabled(uidPath, dbPath);
119
+ assert.equal(result, true);
120
+ });
121
+ });