groove-dev 0.27.143 → 0.27.145

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 (251) hide show
  1. package/CLAUDE.md +0 -7
  2. package/node_modules/@groove-dev/cli/package.json +1 -1
  3. package/node_modules/@groove-dev/daemon/package.json +1 -1
  4. package/node_modules/@groove-dev/daemon/src/api.js +1086 -6532
  5. package/node_modules/@groove-dev/daemon/src/conversations.js +18 -48
  6. package/node_modules/@groove-dev/daemon/src/gateways/manager.js +35 -1
  7. package/node_modules/@groove-dev/daemon/src/index.js +3 -0
  8. package/node_modules/@groove-dev/daemon/src/journalist.js +23 -13
  9. package/node_modules/@groove-dev/daemon/src/mlx-server.js +365 -0
  10. package/node_modules/@groove-dev/daemon/src/model-lab.js +308 -12
  11. package/node_modules/@groove-dev/daemon/src/pm.js +1 -1
  12. package/node_modules/@groove-dev/daemon/src/process.js +2 -2
  13. package/node_modules/@groove-dev/daemon/src/providers/local.js +36 -8
  14. package/node_modules/@groove-dev/daemon/src/registry.js +21 -5
  15. package/node_modules/@groove-dev/daemon/src/routes/agents.js +812 -0
  16. package/node_modules/@groove-dev/daemon/src/routes/coordination.js +318 -0
  17. package/node_modules/@groove-dev/daemon/src/routes/files.js +751 -0
  18. package/node_modules/@groove-dev/daemon/src/routes/integrations.js +485 -0
  19. package/node_modules/@groove-dev/daemon/src/routes/network.js +1784 -0
  20. package/node_modules/@groove-dev/daemon/src/routes/providers.js +755 -0
  21. package/node_modules/@groove-dev/daemon/src/routes/schedules.js +110 -0
  22. package/node_modules/@groove-dev/daemon/src/routes/teams.js +650 -0
  23. package/node_modules/@groove-dev/daemon/src/scheduler.js +456 -24
  24. package/node_modules/@groove-dev/daemon/src/teams.js +1 -1
  25. package/node_modules/@groove-dev/daemon/src/validate.js +38 -1
  26. package/node_modules/@groove-dev/daemon/templates/mlx-setup.json +12 -0
  27. package/node_modules/@groove-dev/daemon/templates/tgi-setup.json +1 -1
  28. package/node_modules/@groove-dev/daemon/templates/vllm-setup.json +1 -1
  29. package/node_modules/@groove-dev/daemon/test/introducer.test.js +3 -3
  30. package/node_modules/@groove-dev/daemon/test/journalist.test.js +7 -10
  31. package/node_modules/@groove-dev/daemon/test/registry.test.js +38 -0
  32. package/node_modules/@groove-dev/gui/dist/assets/index-Bxc0gU06.js +1006 -0
  33. package/node_modules/@groove-dev/gui/dist/assets/index-C0pztKBn.css +1 -0
  34. package/node_modules/@groove-dev/gui/dist/index.html +2 -2
  35. package/node_modules/@groove-dev/gui/package.json +1 -1
  36. package/node_modules/@groove-dev/gui/src/{app.jsx → App.jsx} +0 -2
  37. package/node_modules/@groove-dev/gui/src/app.css +35 -0
  38. package/node_modules/@groove-dev/gui/src/components/agents/agent-config.jsx +1 -128
  39. package/node_modules/@groove-dev/gui/src/components/agents/agent-feed.jsx +210 -112
  40. package/node_modules/@groove-dev/gui/src/components/agents/agent-node.jsx +8 -13
  41. package/node_modules/@groove-dev/gui/src/components/agents/agent-panel.jsx +2 -70
  42. package/node_modules/@groove-dev/gui/src/components/agents/code-review.jsx +159 -122
  43. package/node_modules/@groove-dev/gui/src/components/agents/diff-viewer.jsx +23 -23
  44. package/node_modules/@groove-dev/gui/src/components/agents/journalist-panel.jsx +1 -1
  45. package/node_modules/@groove-dev/gui/src/components/agents/spawn-wizard.jsx +2 -135
  46. package/node_modules/@groove-dev/gui/src/components/automations/automation-card.jsx +274 -0
  47. package/node_modules/@groove-dev/gui/src/components/automations/automation-wizard.jsx +1136 -0
  48. package/node_modules/@groove-dev/gui/src/components/chat/chat-header.jsx +2 -0
  49. package/node_modules/@groove-dev/gui/src/components/chat/chat-input.jsx +68 -66
  50. package/node_modules/@groove-dev/gui/src/components/chat/chat-view.jsx +4 -8
  51. package/node_modules/@groove-dev/gui/src/components/dashboard/activity-feed.jsx +3 -3
  52. package/node_modules/@groove-dev/gui/src/components/dashboard/cache-ring.jsx +5 -5
  53. package/node_modules/@groove-dev/gui/src/components/dashboard/context-gauges.jsx +6 -8
  54. package/node_modules/@groove-dev/gui/src/components/dashboard/fleet-panel.jsx +8 -14
  55. package/node_modules/@groove-dev/gui/src/components/dashboard/intel-panel.jsx +238 -656
  56. package/node_modules/@groove-dev/gui/src/components/dashboard/kpi-card.jsx +3 -3
  57. package/node_modules/@groove-dev/gui/src/components/dashboard/routing-chart.jsx +3 -3
  58. package/node_modules/@groove-dev/gui/src/components/dashboard/team-burn-panel.jsx +1 -1
  59. package/node_modules/@groove-dev/gui/src/components/dashboard/token-chart.jsx +4 -4
  60. package/node_modules/@groove-dev/gui/src/components/lab/chat-playground.jsx +39 -31
  61. package/node_modules/@groove-dev/gui/src/components/lab/lab-assistant.jsx +316 -82
  62. package/node_modules/@groove-dev/gui/src/components/lab/metrics-panel.jsx +187 -32
  63. package/node_modules/@groove-dev/gui/src/components/lab/parameter-panel.jsx +200 -18
  64. package/node_modules/@groove-dev/gui/src/components/lab/preset-manager.jsx +17 -14
  65. package/node_modules/@groove-dev/gui/src/components/lab/runtime-config.jsx +335 -152
  66. package/node_modules/@groove-dev/gui/src/components/lab/system-prompt-editor.jsx +10 -8
  67. package/node_modules/@groove-dev/gui/src/components/layout/activity-bar.jsx +2 -4
  68. package/node_modules/@groove-dev/gui/src/components/layout/terminal-panel.jsx +4 -2
  69. package/node_modules/@groove-dev/gui/src/components/layout/welcome-splash.jsx +137 -108
  70. package/node_modules/@groove-dev/gui/src/components/network/network-health.jsx +2 -2
  71. package/node_modules/@groove-dev/gui/src/components/network/performance-dashboard.jsx +4 -4
  72. package/node_modules/@groove-dev/gui/src/components/settings/ssh-wizard.jsx +81 -99
  73. package/node_modules/@groove-dev/gui/src/components/ui/sheet.jsx +5 -2
  74. package/node_modules/@groove-dev/gui/src/components/ui/slider.jsx +8 -8
  75. package/node_modules/@groove-dev/gui/src/lib/cron.js +64 -0
  76. package/node_modules/@groove-dev/gui/src/lib/status.js +25 -24
  77. package/node_modules/@groove-dev/gui/src/lib/theme-hex.js +1 -0
  78. package/node_modules/@groove-dev/gui/src/stores/groove.js +51 -3144
  79. package/node_modules/@groove-dev/gui/src/stores/helpers.js +10 -0
  80. package/node_modules/@groove-dev/gui/src/stores/slices/agents-slice.js +459 -0
  81. package/node_modules/@groove-dev/gui/src/stores/slices/automations-slice.js +96 -0
  82. package/node_modules/@groove-dev/gui/src/stores/slices/chat-slice.js +226 -0
  83. package/node_modules/@groove-dev/gui/src/stores/slices/editor-slice.js +285 -0
  84. package/node_modules/@groove-dev/gui/src/stores/slices/marketplace-slice.js +461 -0
  85. package/node_modules/@groove-dev/gui/src/stores/slices/network-slice.js +361 -0
  86. package/node_modules/@groove-dev/gui/src/stores/slices/preview-slice.js +109 -0
  87. package/node_modules/@groove-dev/gui/src/stores/slices/providers-slice.js +897 -0
  88. package/node_modules/@groove-dev/gui/src/stores/slices/teams-slice.js +413 -0
  89. package/node_modules/@groove-dev/gui/src/stores/slices/ui-slice.js +98 -0
  90. package/node_modules/@groove-dev/gui/src/views/agents.jsx +5 -5
  91. package/node_modules/@groove-dev/gui/src/views/dashboard.jsx +12 -13
  92. package/node_modules/@groove-dev/gui/src/views/marketplace.jsx +191 -3
  93. package/node_modules/@groove-dev/gui/src/views/model-lab.jsx +54 -12
  94. package/node_modules/@groove-dev/gui/src/views/models.jsx +419 -496
  95. package/node_modules/@groove-dev/gui/src/views/network.jsx +3 -3
  96. package/node_modules/@groove-dev/gui/src/views/settings.jsx +81 -94
  97. package/node_modules/@groove-dev/gui/src/views/teams.jsx +40 -483
  98. package/node_modules/axios/CHANGELOG.md +260 -0
  99. package/node_modules/axios/README.md +595 -223
  100. package/node_modules/axios/dist/axios.js +1460 -1090
  101. package/node_modules/axios/dist/axios.js.map +1 -1
  102. package/node_modules/axios/dist/axios.min.js +3 -3
  103. package/node_modules/axios/dist/axios.min.js.map +1 -1
  104. package/node_modules/axios/dist/browser/axios.cjs +1560 -1132
  105. package/node_modules/axios/dist/browser/axios.cjs.map +1 -1
  106. package/node_modules/axios/dist/esm/axios.js +1557 -1128
  107. package/node_modules/axios/dist/esm/axios.js.map +1 -1
  108. package/node_modules/axios/dist/esm/axios.min.js +2 -2
  109. package/node_modules/axios/dist/esm/axios.min.js.map +1 -1
  110. package/node_modules/axios/dist/node/axios.cjs +1594 -1057
  111. package/node_modules/axios/dist/node/axios.cjs.map +1 -1
  112. package/node_modules/axios/index.d.cts +40 -41
  113. package/node_modules/axios/index.d.ts +151 -227
  114. package/node_modules/axios/index.js +2 -0
  115. package/node_modules/axios/lib/adapters/adapters.js +4 -2
  116. package/node_modules/axios/lib/adapters/fetch.js +147 -16
  117. package/node_modules/axios/lib/adapters/http.js +306 -58
  118. package/node_modules/axios/lib/adapters/xhr.js +6 -2
  119. package/node_modules/axios/lib/core/Axios.js +7 -3
  120. package/node_modules/axios/lib/core/AxiosError.js +120 -34
  121. package/node_modules/axios/lib/core/AxiosHeaders.js +27 -25
  122. package/node_modules/axios/lib/core/buildFullPath.js +1 -1
  123. package/node_modules/axios/lib/core/dispatchRequest.js +19 -7
  124. package/node_modules/axios/lib/core/mergeConfig.js +21 -4
  125. package/node_modules/axios/lib/core/settle.js +7 -11
  126. package/node_modules/axios/lib/defaults/index.js +14 -9
  127. package/node_modules/axios/lib/env/data.js +1 -1
  128. package/node_modules/axios/lib/helpers/AxiosURLSearchParams.js +1 -2
  129. package/node_modules/axios/lib/helpers/buildURL.js +1 -1
  130. package/node_modules/axios/lib/helpers/cookies.js +14 -2
  131. package/node_modules/axios/lib/helpers/estimateDataURLDecodedBytes.js +28 -1
  132. package/node_modules/axios/lib/helpers/formDataToJSON.js +3 -1
  133. package/node_modules/axios/lib/helpers/formDataToStream.js +3 -2
  134. package/node_modules/axios/lib/helpers/parseProtocol.js +1 -1
  135. package/node_modules/axios/lib/helpers/progressEventReducer.js +5 -5
  136. package/node_modules/axios/lib/helpers/resolveConfig.js +54 -18
  137. package/node_modules/axios/lib/helpers/shouldBypassProxy.js +74 -2
  138. package/node_modules/axios/lib/helpers/toFormData.js +10 -2
  139. package/node_modules/axios/lib/helpers/validator.js +3 -1
  140. package/node_modules/axios/lib/utils.js +33 -21
  141. package/node_modules/axios/package.json +17 -24
  142. package/node_modules/follow-redirects/README.md +7 -5
  143. package/node_modules/follow-redirects/index.js +24 -1
  144. package/node_modules/follow-redirects/package.json +1 -1
  145. package/package.json +1 -1
  146. package/packages/cli/package.json +1 -1
  147. package/packages/daemon/package.json +1 -1
  148. package/packages/daemon/src/api.js +1086 -6532
  149. package/packages/daemon/src/conversations.js +18 -48
  150. package/packages/daemon/src/gateways/manager.js +35 -1
  151. package/packages/daemon/src/index.js +3 -0
  152. package/packages/daemon/src/journalist.js +23 -13
  153. package/packages/daemon/src/mlx-server.js +365 -0
  154. package/packages/daemon/src/model-lab.js +308 -12
  155. package/packages/daemon/src/pm.js +1 -1
  156. package/packages/daemon/src/process.js +2 -2
  157. package/packages/daemon/src/providers/local.js +36 -8
  158. package/packages/daemon/src/registry.js +21 -5
  159. package/packages/daemon/src/routes/agents.js +812 -0
  160. package/packages/daemon/src/routes/coordination.js +318 -0
  161. package/packages/daemon/src/routes/files.js +751 -0
  162. package/packages/daemon/src/routes/integrations.js +485 -0
  163. package/packages/daemon/src/routes/network.js +1784 -0
  164. package/packages/daemon/src/routes/providers.js +755 -0
  165. package/packages/daemon/src/routes/schedules.js +110 -0
  166. package/packages/daemon/src/routes/teams.js +650 -0
  167. package/packages/daemon/src/scheduler.js +456 -24
  168. package/packages/daemon/src/teams.js +1 -1
  169. package/packages/daemon/src/validate.js +38 -1
  170. package/packages/daemon/templates/mlx-setup.json +12 -0
  171. package/packages/daemon/templates/tgi-setup.json +1 -1
  172. package/packages/daemon/templates/vllm-setup.json +1 -1
  173. package/packages/gui/dist/assets/index-Bxc0gU06.js +1006 -0
  174. package/packages/gui/dist/assets/index-C0pztKBn.css +1 -0
  175. package/packages/gui/dist/index.html +2 -2
  176. package/packages/gui/package.json +1 -1
  177. package/packages/gui/src/{app.jsx → App.jsx} +0 -2
  178. package/packages/gui/src/app.css +35 -0
  179. package/packages/gui/src/components/agents/agent-config.jsx +1 -128
  180. package/packages/gui/src/components/agents/agent-feed.jsx +210 -112
  181. package/packages/gui/src/components/agents/agent-node.jsx +8 -13
  182. package/packages/gui/src/components/agents/agent-panel.jsx +2 -70
  183. package/packages/gui/src/components/agents/code-review.jsx +159 -122
  184. package/packages/gui/src/components/agents/diff-viewer.jsx +23 -23
  185. package/packages/gui/src/components/agents/journalist-panel.jsx +1 -1
  186. package/packages/gui/src/components/agents/spawn-wizard.jsx +2 -135
  187. package/packages/gui/src/components/automations/automation-card.jsx +274 -0
  188. package/packages/gui/src/components/automations/automation-wizard.jsx +1136 -0
  189. package/packages/gui/src/components/chat/chat-header.jsx +2 -0
  190. package/packages/gui/src/components/chat/chat-input.jsx +68 -66
  191. package/packages/gui/src/components/chat/chat-view.jsx +4 -8
  192. package/packages/gui/src/components/dashboard/activity-feed.jsx +3 -3
  193. package/packages/gui/src/components/dashboard/cache-ring.jsx +5 -5
  194. package/packages/gui/src/components/dashboard/context-gauges.jsx +6 -8
  195. package/packages/gui/src/components/dashboard/fleet-panel.jsx +8 -14
  196. package/packages/gui/src/components/dashboard/intel-panel.jsx +238 -656
  197. package/packages/gui/src/components/dashboard/kpi-card.jsx +3 -3
  198. package/packages/gui/src/components/dashboard/routing-chart.jsx +3 -3
  199. package/packages/gui/src/components/dashboard/team-burn-panel.jsx +1 -1
  200. package/packages/gui/src/components/dashboard/token-chart.jsx +4 -4
  201. package/packages/gui/src/components/lab/chat-playground.jsx +39 -31
  202. package/packages/gui/src/components/lab/lab-assistant.jsx +316 -82
  203. package/packages/gui/src/components/lab/metrics-panel.jsx +187 -32
  204. package/packages/gui/src/components/lab/parameter-panel.jsx +200 -18
  205. package/packages/gui/src/components/lab/preset-manager.jsx +17 -14
  206. package/packages/gui/src/components/lab/runtime-config.jsx +335 -152
  207. package/packages/gui/src/components/lab/system-prompt-editor.jsx +10 -8
  208. package/packages/gui/src/components/layout/activity-bar.jsx +2 -4
  209. package/packages/gui/src/components/layout/terminal-panel.jsx +4 -2
  210. package/packages/gui/src/components/layout/welcome-splash.jsx +137 -108
  211. package/packages/gui/src/components/network/network-health.jsx +2 -2
  212. package/packages/gui/src/components/network/performance-dashboard.jsx +4 -4
  213. package/packages/gui/src/components/settings/ssh-wizard.jsx +81 -99
  214. package/packages/gui/src/components/ui/sheet.jsx +5 -2
  215. package/packages/gui/src/components/ui/slider.jsx +8 -8
  216. package/packages/gui/src/lib/cron.js +64 -0
  217. package/packages/gui/src/lib/status.js +25 -24
  218. package/packages/gui/src/lib/theme-hex.js +1 -0
  219. package/packages/gui/src/stores/groove.js +51 -3144
  220. package/packages/gui/src/stores/helpers.js +10 -0
  221. package/packages/gui/src/stores/slices/agents-slice.js +459 -0
  222. package/packages/gui/src/stores/slices/automations-slice.js +96 -0
  223. package/packages/gui/src/stores/slices/chat-slice.js +226 -0
  224. package/packages/gui/src/stores/slices/editor-slice.js +285 -0
  225. package/packages/gui/src/stores/slices/marketplace-slice.js +461 -0
  226. package/packages/gui/src/stores/slices/network-slice.js +361 -0
  227. package/packages/gui/src/stores/slices/preview-slice.js +109 -0
  228. package/packages/gui/src/stores/slices/providers-slice.js +897 -0
  229. package/packages/gui/src/stores/slices/teams-slice.js +413 -0
  230. package/packages/gui/src/stores/slices/ui-slice.js +98 -0
  231. package/packages/gui/src/views/agents.jsx +5 -5
  232. package/packages/gui/src/views/dashboard.jsx +12 -13
  233. package/packages/gui/src/views/marketplace.jsx +191 -3
  234. package/packages/gui/src/views/model-lab.jsx +54 -12
  235. package/packages/gui/src/views/models.jsx +419 -496
  236. package/packages/gui/src/views/network.jsx +3 -3
  237. package/packages/gui/src/views/settings.jsx +81 -94
  238. package/packages/gui/src/views/teams.jsx +40 -483
  239. package/SECURITY_SWEEP.md +0 -228
  240. package/TRAINING_DATA_v4.md +0 -6
  241. package/node_modules/@groove-dev/gui/dist/assets/index-CCVvAoQn.css +0 -1
  242. package/node_modules/@groove-dev/gui/dist/assets/index-DGIv_TRm.js +0 -984
  243. package/node_modules/@groove-dev/gui/src/components/agents/agent-chat.jsx +0 -379
  244. package/node_modules/@groove-dev/gui/src/views/preview.jsx +0 -6
  245. package/node_modules/@groove-dev/gui/src/views/subscription-panel.jsx +0 -327
  246. package/packages/gui/dist/assets/index-CCVvAoQn.css +0 -1
  247. package/packages/gui/dist/assets/index-DGIv_TRm.js +0 -984
  248. package/packages/gui/src/components/agents/agent-chat.jsx +0 -379
  249. package/packages/gui/src/views/preview.jsx +0 -6
  250. package/packages/gui/src/views/subscription-panel.jsx +0 -327
  251. package/test.py +0 -571
@@ -7,15 +7,55 @@ import mergeConfig from '../core/mergeConfig.js';
7
7
  import AxiosHeaders from '../core/AxiosHeaders.js';
8
8
  import buildURL from './buildURL.js';
9
9
 
10
+ const FORM_DATA_CONTENT_HEADERS = ['content-type', 'content-length'];
11
+
12
+ function setFormDataHeaders(headers, formHeaders, policy) {
13
+ if (policy !== 'content-only') {
14
+ headers.set(formHeaders);
15
+ return;
16
+ }
17
+
18
+ Object.entries(formHeaders).forEach(([key, val]) => {
19
+ if (FORM_DATA_CONTENT_HEADERS.includes(key.toLowerCase())) {
20
+ headers.set(key, val);
21
+ }
22
+ });
23
+ }
24
+
25
+ /**
26
+ * Encode a UTF-8 string to a Latin-1 byte string for use with btoa().
27
+ * This is a modern replacement for the deprecated unescape(encodeURIComponent(str)) pattern.
28
+ *
29
+ * @param {string} str The string to encode
30
+ *
31
+ * @returns {string} UTF-8 bytes as a Latin-1 string
32
+ */
33
+ const encodeUTF8 = (str) =>
34
+ encodeURIComponent(str).replace(/%([0-9A-F]{2})/gi, (_, hex) =>
35
+ String.fromCharCode(parseInt(hex, 16))
36
+ );
37
+
10
38
  export default (config) => {
11
39
  const newConfig = mergeConfig({}, config);
12
40
 
13
- let { data, withXSRFToken, xsrfHeaderName, xsrfCookieName, headers, auth } = newConfig;
41
+ // Read only own properties to prevent prototype pollution gadgets
42
+ // (e.g. Object.prototype.baseURL = 'https://evil.com').
43
+ const own = (key) => (utils.hasOwnProp(newConfig, key) ? newConfig[key] : undefined);
44
+
45
+ const data = own('data');
46
+ let withXSRFToken = own('withXSRFToken');
47
+ const xsrfHeaderName = own('xsrfHeaderName');
48
+ const xsrfCookieName = own('xsrfCookieName');
49
+ let headers = own('headers');
50
+ const auth = own('auth');
51
+ const baseURL = own('baseURL');
52
+ const allowAbsoluteUrls = own('allowAbsoluteUrls');
53
+ const url = own('url');
14
54
 
15
55
  newConfig.headers = headers = AxiosHeaders.from(headers);
16
56
 
17
57
  newConfig.url = buildURL(
18
- buildFullPath(newConfig.baseURL, newConfig.url, newConfig.allowAbsoluteUrls),
58
+ buildFullPath(baseURL, url, allowAbsoluteUrls),
19
59
  config.params,
20
60
  config.paramsSerializer
21
61
  );
@@ -25,11 +65,7 @@ export default (config) => {
25
65
  headers.set(
26
66
  'Authorization',
27
67
  'Basic ' +
28
- btoa(
29
- (auth.username || '') +
30
- ':' +
31
- (auth.password ? unescape(encodeURIComponent(auth.password)) : '')
32
- )
68
+ btoa((auth.username || '') + ':' + (auth.password ? encodeUTF8(auth.password) : ''))
33
69
  );
34
70
  }
35
71
 
@@ -38,14 +74,7 @@ export default (config) => {
38
74
  headers.setContentType(undefined); // browser handles it
39
75
  } else if (utils.isFunction(data.getHeaders)) {
40
76
  // Node.js FormData (like form-data package)
41
- const formHeaders = data.getHeaders();
42
- // Only set safe headers to avoid overwriting security headers
43
- const allowedHeaders = ['content-type', 'content-length'];
44
- Object.entries(formHeaders).forEach(([key, val]) => {
45
- if (allowedHeaders.includes(key.toLowerCase())) {
46
- headers.set(key, val);
47
- }
48
- });
77
+ setFormDataHeaders(headers, data.getHeaders(), own('formDataHeaderPolicy'));
49
78
  }
50
79
  }
51
80
 
@@ -54,10 +83,17 @@ export default (config) => {
54
83
  // Specifically not if we're in a web worker, or react-native.
55
84
 
56
85
  if (platform.hasStandardBrowserEnv) {
57
- withXSRFToken && utils.isFunction(withXSRFToken) && (withXSRFToken = withXSRFToken(newConfig));
86
+ if (utils.isFunction(withXSRFToken)) {
87
+ withXSRFToken = withXSRFToken(newConfig);
88
+ }
89
+
90
+ // Strict boolean check — prevents proto-pollution gadgets (e.g. Object.prototype.withXSRFToken = 1)
91
+ // and misconfigurations (e.g. "false") from short-circuiting the same-origin check and leaking
92
+ // the XSRF token cross-origin.
93
+ const shouldSendXSRF =
94
+ withXSRFToken === true || (withXSRFToken == null && isURLSameOrigin(newConfig.url));
58
95
 
59
- if (withXSRFToken || (withXSRFToken !== false && isURLSameOrigin(newConfig.url))) {
60
- // Add xsrf header
96
+ if (shouldSendXSRF) {
61
97
  const xsrfValue = xsrfHeaderName && xsrfCookieName && cookies.read(xsrfCookieName);
62
98
 
63
99
  if (xsrfValue) {
@@ -1,3 +1,50 @@
1
+ const LOOPBACK_HOSTNAMES = new Set(['localhost']);
2
+
3
+ const isIPv4Loopback = (host) => {
4
+ const parts = host.split('.');
5
+ if (parts.length !== 4) return false;
6
+ if (parts[0] !== '127') return false;
7
+ return parts.every((p) => /^\d+$/.test(p) && Number(p) >= 0 && Number(p) <= 255);
8
+ };
9
+
10
+ const isIPv6Loopback = (host) => {
11
+ // Collapse all-zero groups: any form of ::1 / 0:0:...:0:1
12
+ // First, strip any leading "::" by normalising with Set lookup of common forms,
13
+ // then fall back to structural check.
14
+ if (host === '::1') return true;
15
+
16
+ // Check IPv4-mapped IPv6 loopback: ::ffff:<v4-loopback> or ::ffff:<hex-v4-loopback>
17
+ // Node's URL parser normalises ::ffff:127.0.0.1 → ::ffff:7f00:1
18
+ const v4MappedDotted = host.match(/^::ffff:(\d+\.\d+\.\d+\.\d+)$/i);
19
+ if (v4MappedDotted) return isIPv4Loopback(v4MappedDotted[1]);
20
+
21
+ const v4MappedHex = host.match(/^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i);
22
+ if (v4MappedHex) {
23
+ const high = parseInt(v4MappedHex[1], 16);
24
+ // High 16 bits must start with 127 (0x7f) — i.e. 0x7f00..0x7fff
25
+ return high >= 0x7f00 && high <= 0x7fff;
26
+ }
27
+
28
+ // Full-form ::1 variants: any number of zero groups followed by trailing 1
29
+ // e.g. 0:0:0:0:0:0:0:1, 0000:...:0001
30
+ const groups = host.split(':');
31
+ if (groups.length === 8) {
32
+ for (let i = 0; i < 7; i++) {
33
+ if (!/^0+$/.test(groups[i])) return false;
34
+ }
35
+ return /^0*1$/.test(groups[7]);
36
+ }
37
+
38
+ return false;
39
+ };
40
+
41
+ const isLoopback = (host) => {
42
+ if (!host) return false;
43
+ if (LOOPBACK_HOSTNAMES.has(host)) return true;
44
+ if (isIPv4Loopback(host)) return true;
45
+ return isIPv6Loopback(host);
46
+ };
47
+
1
48
  const DEFAULT_PORTS = {
2
49
  http: 80,
3
50
  https: 443,
@@ -40,6 +87,31 @@ const parseNoProxyEntry = (entry) => {
40
87
  return [entryHost, entryPort];
41
88
  };
42
89
 
90
+ // Convert IPv4-mapped IPv6 (::ffff:0:0/96 prefix) to IPv4 dotted form so both
91
+ // sides of a NO_PROXY comparison see the same canonical address. Without this,
92
+ // `NO_PROXY=192.168.1.5` would not match a request to `http://[::ffff:192.168.1.5]/`
93
+ // (Node's URL parser normalises that to `[::ffff:c0a8:105]`), and vice-versa,
94
+ // allowing the proxy-bypass policy to be circumvented by using the alternate
95
+ // representation. Returns the input unchanged when not IPv4-mapped.
96
+ const IPV4_MAPPED_DOTTED_RE = /^(?:::|(?:0{1,4}:){1,4}:|(?:0{1,4}:){5})ffff:(\d+\.\d+\.\d+\.\d+)$/i;
97
+ const IPV4_MAPPED_HEX_RE = /^(?:::|(?:0{1,4}:){1,4}:|(?:0{1,4}:){5})ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i;
98
+
99
+ const unmapIPv4MappedIPv6 = (host) => {
100
+ if (typeof host !== 'string' || host.indexOf(':') === -1) return host;
101
+
102
+ const dotted = host.match(IPV4_MAPPED_DOTTED_RE);
103
+ if (dotted) return dotted[1];
104
+
105
+ const hex = host.match(IPV4_MAPPED_HEX_RE);
106
+ if (hex) {
107
+ const high = parseInt(hex[1], 16);
108
+ const low = parseInt(hex[2], 16);
109
+ return `${high >> 8}.${high & 0xff}.${low >> 8}.${low & 0xff}`;
110
+ }
111
+
112
+ return host;
113
+ };
114
+
43
115
  const normalizeNoProxyHost = (hostname) => {
44
116
  if (!hostname) {
45
117
  return hostname;
@@ -49,7 +121,7 @@ const normalizeNoProxyHost = (hostname) => {
49
121
  hostname = hostname.slice(1, -1);
50
122
  }
51
123
 
52
- return hostname.replace(/\.+$/, '');
124
+ return unmapIPv4MappedIPv6(hostname.replace(/\.+$/, ''));
53
125
  };
54
126
 
55
127
  export default function shouldBypassProxy(location) {
@@ -101,6 +173,6 @@ export default function shouldBypassProxy(location) {
101
173
  return hostname.endsWith(entryHost);
102
174
  }
103
175
 
104
- return hostname === entryHost;
176
+ return hostname === entryHost || (isLoopback(hostname) && isLoopback(entryHost));
105
177
  });
106
178
  }
@@ -115,6 +115,7 @@ function toFormData(obj, formData, options) {
115
115
  const dots = options.dots;
116
116
  const indexes = options.indexes;
117
117
  const _Blob = options.Blob || (typeof Blob !== 'undefined' && Blob);
118
+ const maxDepth = options.maxDepth === undefined ? 100 : options.maxDepth;
118
119
  const useBlob = _Blob && utils.isSpecCompliantForm(formData);
119
120
 
120
121
  if (!utils.isFunction(visitor)) {
@@ -207,9 +208,16 @@ function toFormData(obj, formData, options) {
207
208
  isVisitable,
208
209
  });
209
210
 
210
- function build(value, path) {
211
+ function build(value, path, depth = 0) {
211
212
  if (utils.isUndefined(value)) return;
212
213
 
214
+ if (depth > maxDepth) {
215
+ throw new AxiosError(
216
+ 'Object is too deeply nested (' + depth + ' levels). Max depth: ' + maxDepth,
217
+ AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED
218
+ );
219
+ }
220
+
213
221
  if (stack.indexOf(value) !== -1) {
214
222
  throw Error('Circular reference detected in ' + path.join('.'));
215
223
  }
@@ -222,7 +230,7 @@ function toFormData(obj, formData, options) {
222
230
  visitor.call(formData, el, utils.isString(key) ? key.trim() : key, path, exposedHelpers);
223
231
 
224
232
  if (result === true) {
225
- build(el, path ? path.concat(key) : [key]);
233
+ build(el, path ? path.concat(key) : [key], depth + 1);
226
234
  }
227
235
  });
228
236
 
@@ -86,7 +86,9 @@ function assertOptions(options, schema, allowUnknown) {
86
86
  let i = keys.length;
87
87
  while (i-- > 0) {
88
88
  const opt = keys[i];
89
- const validator = schema[opt];
89
+ // Use hasOwnProperty so a polluted Object.prototype.<opt> cannot supply
90
+ // a non-function validator and cause a TypeError.
91
+ const validator = Object.prototype.hasOwnProperty.call(schema, opt) ? schema[opt] : undefined;
90
92
  if (validator) {
91
93
  const value = options[opt];
92
94
  const result = value === undefined || validator(value, opt, options);
@@ -192,21 +192,21 @@ const isFile = kindOfTest('File');
192
192
  * also have a `name` and `type` attribute to specify filename and content type
193
193
  *
194
194
  * @see https://github.com/facebook/react-native/blob/26684cf3adf4094eb6c405d345a75bf8c7c0bf88/Libraries/Network/FormData.js#L68-L71
195
- *
195
+ *
196
196
  * @param {*} value The value to test
197
- *
197
+ *
198
198
  * @returns {boolean} True if value is a React Native Blob, otherwise false
199
199
  */
200
200
  const isReactNativeBlob = (value) => {
201
201
  return !!(value && typeof value.uri !== 'undefined');
202
- }
202
+ };
203
203
 
204
204
  /**
205
205
  * Determine if environment is React Native
206
206
  * ReactNative `FormData` has a non-standard `getParts()` method
207
- *
207
+ *
208
208
  * @param {*} formData The formData to test
209
- *
209
+ *
210
210
  * @returns {boolean} True if environment is React Native, otherwise false
211
211
  */
212
212
  const isReactNative = (formData) => formData && typeof formData.getParts !== 'undefined';
@@ -225,7 +225,7 @@ const isBlob = kindOfTest('Blob');
225
225
  *
226
226
  * @param {*} val The value to test
227
227
  *
228
- * @returns {boolean} True if value is a File, otherwise false
228
+ * @returns {boolean} True if value is a FileList, otherwise false
229
229
  */
230
230
  const isFileList = kindOfTest('FileList');
231
231
 
@@ -257,15 +257,17 @@ const G = getGlobal();
257
257
  const FormDataCtor = typeof G.FormData !== 'undefined' ? G.FormData : undefined;
258
258
 
259
259
  const isFormData = (thing) => {
260
- let kind;
261
- return thing && (
262
- (FormDataCtor && thing instanceof FormDataCtor) || (
263
- isFunction(thing.append) && (
264
- (kind = kindOf(thing)) === 'formdata' ||
265
- // detect form-data instance
266
- (kind === 'object' && isFunction(thing.toString) && thing.toString() === '[object FormData]')
267
- )
268
- )
260
+ if (!thing) return false;
261
+ if (FormDataCtor && thing instanceof FormDataCtor) return true;
262
+ // Reject plain objects inheriting directly from Object.prototype so prototype-pollution gadgets can't spoof FormData.
263
+ const proto = getPrototypeOf(thing);
264
+ if (!proto || proto === Object.prototype) return false;
265
+ if (!isFunction(thing.append)) return false;
266
+ const kind = kindOf(thing);
267
+ return (
268
+ kind === 'formdata' ||
269
+ // detect form-data instance
270
+ (kind === 'object' && isFunction(thing.toString) && thing.toString() === '[object FormData]')
269
271
  );
270
272
  };
271
273
 
@@ -401,7 +403,7 @@ const isContextDefined = (context) => !isUndefined(context) && context !== _glob
401
403
  *
402
404
  * @returns {Object} Result of all merge properties
403
405
  */
404
- function merge(/* obj1, obj2, obj3, ... */) {
406
+ function merge(...objs) {
405
407
  const { caseless, skipUndefined } = (isContextDefined(this) && this) || {};
406
408
  const result = {};
407
409
  const assignValue = (val, key) => {
@@ -411,8 +413,12 @@ function merge(/* obj1, obj2, obj3, ... */) {
411
413
  }
412
414
 
413
415
  const targetKey = (caseless && findKey(result, key)) || key;
414
- if (isPlainObject(result[targetKey]) && isPlainObject(val)) {
415
- result[targetKey] = merge(result[targetKey], val);
416
+ // Read via own-prop only — a bare `result[targetKey]` walks the prototype
417
+ // chain, so a polluted Object.prototype value could surface here and get
418
+ // copied into the merged result.
419
+ const existing = hasOwnProperty(result, targetKey) ? result[targetKey] : undefined;
420
+ if (isPlainObject(existing) && isPlainObject(val)) {
421
+ result[targetKey] = merge(existing, val);
416
422
  } else if (isPlainObject(val)) {
417
423
  result[targetKey] = merge({}, val);
418
424
  } else if (isArray(val)) {
@@ -422,8 +428,8 @@ function merge(/* obj1, obj2, obj3, ... */) {
422
428
  }
423
429
  };
424
430
 
425
- for (let i = 0, l = arguments.length; i < l; i++) {
426
- arguments[i] && forEach(arguments[i], assignValue);
431
+ for (let i = 0, l = objs.length; i < l; i++) {
432
+ objs[i] && forEach(objs[i], assignValue);
427
433
  }
428
434
  return result;
429
435
  }
@@ -445,6 +451,9 @@ const extend = (a, b, thisArg, { allOwnKeys } = {}) => {
445
451
  (val, key) => {
446
452
  if (thisArg && isFunction(val)) {
447
453
  Object.defineProperty(a, key, {
454
+ // Null-proto descriptor so a polluted Object.prototype.get cannot
455
+ // hijack defineProperty's accessor-vs-data resolution.
456
+ __proto__: null,
448
457
  value: bind(val, thisArg),
449
458
  writable: true,
450
459
  enumerable: true,
@@ -452,6 +461,7 @@ const extend = (a, b, thisArg, { allOwnKeys } = {}) => {
452
461
  });
453
462
  } else {
454
463
  Object.defineProperty(a, key, {
464
+ __proto__: null,
455
465
  value: val,
456
466
  writable: true,
457
467
  enumerable: true,
@@ -490,12 +500,14 @@ const stripBOM = (content) => {
490
500
  const inherits = (constructor, superConstructor, props, descriptors) => {
491
501
  constructor.prototype = Object.create(superConstructor.prototype, descriptors);
492
502
  Object.defineProperty(constructor.prototype, 'constructor', {
503
+ __proto__: null,
493
504
  value: constructor,
494
505
  writable: true,
495
506
  enumerable: false,
496
507
  configurable: true,
497
508
  });
498
509
  Object.defineProperty(constructor, 'super', {
510
+ __proto__: null,
499
511
  value: superConstructor.prototype,
500
512
  });
501
513
  props && Object.assign(constructor.prototype, props);
@@ -677,7 +689,7 @@ const reduceDescriptors = (obj, reducer) => {
677
689
  const freezeMethods = (obj) => {
678
690
  reduceDescriptors(obj, (descriptor, name) => {
679
691
  // skip restricted props in strict mode
680
- if (isFunction(obj) && ['arguments', 'caller', 'callee'].indexOf(name) !== -1) {
692
+ if (isFunction(obj) && ['arguments', 'caller', 'callee'].includes(name)) {
681
693
  return false;
682
694
  }
683
695
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "axios",
3
- "version": "1.15.0",
3
+ "version": "1.16.0",
4
4
  "description": "Promise based HTTP client for the browser and node.js",
5
5
  "main": "./dist/node/axios.cjs",
6
6
  "module": "./index.js",
@@ -86,10 +86,10 @@
86
86
  "Justin Beckwith (https://github.com/JustinBeckwith)",
87
87
  "Martti Laine (https://github.com/codeclown)",
88
88
  "Xianming Zhong (https://github.com/chinesedfan)",
89
- "Remco Haszing (https://github.com/remcohaszing)",
90
89
  "Willian Agostini (https://github.com/WillianAgostini)",
91
- "Rikki Gibson (https://github.com/RikkiGibson)",
92
- "Ben Carp (https://github.com/carpben)"
90
+ "Shaan Majid (https://github.com/shaanmajid)",
91
+ "Remco Haszing (https://github.com/remcohaszing)",
92
+ "Rikki Gibson (https://github.com/RikkiGibson)"
93
93
  ],
94
94
  "sideEffects": false,
95
95
  "license": "MIT",
@@ -121,15 +121,15 @@
121
121
  "prepare": "husky"
122
122
  },
123
123
  "dependencies": {
124
- "follow-redirects": "^1.15.11",
124
+ "follow-redirects": "^1.16.0",
125
125
  "form-data": "^4.0.5",
126
126
  "proxy-from-env": "^2.1.0"
127
127
  },
128
128
  "devDependencies": {
129
129
  "@babel/core": "^7.29.0",
130
- "@babel/preset-env": "^7.29.0",
131
- "@commitlint/cli": "^20.4.4",
132
- "@commitlint/config-conventional": "^20.4.4",
130
+ "@babel/preset-env": "^7.29.2",
131
+ "@commitlint/cli": "^20.5.0",
132
+ "@commitlint/config-conventional": "^20.5.0",
133
133
  "@eslint/js": "^10.0.1",
134
134
  "@rollup/plugin-alias": "^6.0.0",
135
135
  "@rollup/plugin-babel": "^7.0.0",
@@ -137,40 +137,33 @@
137
137
  "@rollup/plugin-json": "^6.1.0",
138
138
  "@rollup/plugin-node-resolve": "^16.0.3",
139
139
  "@rollup/plugin-terser": "^1.0.0",
140
- "@vitest/browser": "^4.1.1",
141
- "@vitest/browser-playwright": "^4.1.1",
140
+ "@vitest/browser": "^4.1.5",
141
+ "@vitest/browser-playwright": "^4.1.5",
142
142
  "abortcontroller-polyfill": "^1.7.8",
143
- "auto-changelog": "^2.5.0",
144
143
  "body-parser": "^2.2.2",
145
144
  "chalk": "^5.6.2",
146
145
  "cross-env": "^10.1.0",
147
146
  "dev-null": "^0.1.1",
148
- "eslint": "^10.1.0",
147
+ "eslint": "^10.2.1",
149
148
  "express": "^5.2.1",
150
149
  "formdata-node": "^6.0.3",
151
- "formidable": "^3.2.4",
150
+ "formidable": "^3.5.4",
152
151
  "fs-extra": "^11.3.4",
153
152
  "get-stream": "^9.0.1",
154
- "globals": "^17.4.0",
153
+ "globals": "^17.5.0",
155
154
  "gulp": "^5.0.1",
156
- "handlebars": "^4.7.8",
157
155
  "husky": "^9.1.7",
158
156
  "lint-staged": "^16.4.0",
159
- "memoizee": "^0.4.17",
160
157
  "minimist": "^1.2.8",
161
158
  "multer": "^2.1.1",
162
- "pacote": "^21.5.0",
163
- "playwright": "^1.58.2",
164
- "prettier": "^3.8.1",
165
- "pretty-bytes": "^7.1.0",
166
- "rollup": "^4.60.0",
159
+ "playwright": "^1.59.1",
160
+ "prettier": "^3.8.3",
161
+ "rollup": "^4.60.2",
167
162
  "rollup-plugin-bundle-size": "^1.0.3",
168
163
  "selfsigned": "^5.5.0",
169
164
  "stream-throttle": "^0.1.3",
170
- "string-replace-async": "^3.0.2",
171
- "tar-stream": "^3.1.8",
172
165
  "typescript": "^5.9.3",
173
- "vitest": "^4.1.1"
166
+ "vitest": "^4.1.5"
174
167
  },
175
168
  "commitlint": {
176
169
  "rules": {
@@ -15,7 +15,7 @@ Drop-in replacement for Node's `http` and `https` modules that automatically fol
15
15
  ```javascript
16
16
  const { http, https } = require('follow-redirects');
17
17
 
18
- http.get('http://bit.ly/900913', response => {
18
+ http.get('http://en.wikipedia.org/', response => {
19
19
  response.on('data', chunk => {
20
20
  console.log(chunk);
21
21
  });
@@ -29,8 +29,8 @@ If no redirection happened, `responseUrl` is the original request URL.
29
29
 
30
30
  ```javascript
31
31
  const request = https.request({
32
- host: 'bitly.com',
33
- path: '/UHfDGO',
32
+ host: 'en.wikipedia.org',
33
+ path: '/',
34
34
  }, response => {
35
35
  console.log(response.responseUrl);
36
36
  // 'http://duckduckgo.com/robots.txt'
@@ -61,7 +61,7 @@ Per-request options are set by passing an `options` object:
61
61
  const url = require('url');
62
62
  const { http, https } = require('follow-redirects');
63
63
 
64
- const options = url.parse('http://bit.ly/900913');
64
+ const options = url.parse('http://en.wikipedia.org/');
65
65
  options.maxRedirects = 10;
66
66
  options.beforeRedirect = (options, response, request) => {
67
67
  // Use this to adjust the request options upon redirecting,
@@ -74,7 +74,7 @@ options.beforeRedirect = (options, response, request) => {
74
74
  // request.url = the requested URL that resulted in a redirect
75
75
  // request.headers = the headers in the request that resulted in a redirect
76
76
  // request.method = the method of the request that resulted in a redirect
77
- if (options.hostname === "example.com") {
77
+ if (options.hostname === "example.org") {
78
78
  options.auth = "user:password";
79
79
  }
80
80
  };
@@ -95,6 +95,8 @@ the following per-request options are supported:
95
95
 
96
96
  - `trackRedirects` (default: `false`) – whether to store the redirected response details into the `redirects` array on the response object.
97
97
 
98
+ - `sensitiveHeaders` (default: `[]`) – names of headers to omit when making redirected requests (such as `X-API-Key`, `X-Auth-Token`…)
99
+
98
100
 
99
101
  ### Advanced usage
100
102
  By default, `follow-redirects` will use the Node.js default implementations
@@ -26,6 +26,13 @@ catch (error) {
26
26
  useNativeURL = error.code === "ERR_INVALID_URL";
27
27
  }
28
28
 
29
+ // HTTP headers to drop across HTTP/HTTPS and domain boundaries
30
+ var sensitiveHeaders = [
31
+ "Authorization",
32
+ "Proxy-Authorization",
33
+ "Cookie",
34
+ ];
35
+
29
36
  // URL fields to preserve in copy operations
30
37
  var preservedUrlFields = [
31
38
  "auth",
@@ -107,6 +114,11 @@ function RedirectableRequest(options, responseCallback) {
107
114
  }
108
115
  };
109
116
 
117
+ // Create filter for sensitive HTTP headers
118
+ this._headerFilter = new RegExp("^(?:" +
119
+ sensitiveHeaders.concat(options.sensitiveHeaders).map(escapeRegex).join("|") +
120
+ ")$", "i");
121
+
110
122
  // Perform the first request
111
123
  this._performRequest();
112
124
  }
@@ -290,6 +302,9 @@ RedirectableRequest.prototype._sanitizeOptions = function (options) {
290
302
  if (!options.headers) {
291
303
  options.headers = {};
292
304
  }
305
+ if (!isArray(options.sensitiveHeaders)) {
306
+ options.sensitiveHeaders = [];
307
+ }
293
308
 
294
309
  // Since http.request treats host as an alias of hostname,
295
310
  // but the url module interprets host as hostname plus port,
@@ -472,7 +487,7 @@ RedirectableRequest.prototype._processResponse = function (response) {
472
487
  redirectUrl.protocol !== "https:" ||
473
488
  redirectUrl.host !== currentHost &&
474
489
  !isSubdomain(redirectUrl.host, currentHost)) {
475
- removeMatchingHeaders(/^(?:(?:proxy-)?authorization|cookie)$/i, this._options.headers);
490
+ removeMatchingHeaders(this._headerFilter, this._options.headers);
476
491
  }
477
492
 
478
493
  // Evaluate the beforeRedirect callback
@@ -665,6 +680,10 @@ function isSubdomain(subdomain, domain) {
665
680
  return dot > 0 && subdomain[dot] === "." && subdomain.endsWith(domain);
666
681
  }
667
682
 
683
+ function isArray(value) {
684
+ return value instanceof Array;
685
+ }
686
+
668
687
  function isString(value) {
669
688
  return typeof value === "string" || value instanceof String;
670
689
  }
@@ -681,6 +700,10 @@ function isURL(value) {
681
700
  return URL && value instanceof URL;
682
701
  }
683
702
 
703
+ function escapeRegex(regex) {
704
+ return regex.replace(/[\]\\/()*+?.$]/g, "\\$&");
705
+ }
706
+
684
707
  // Exports
685
708
  module.exports = wrap({ http: http, https: https });
686
709
  module.exports.wrap = wrap;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "follow-redirects",
3
- "version": "1.15.11",
3
+ "version": "1.16.0",
4
4
  "description": "HTTP and HTTPS modules that follow redirects.",
5
5
  "license": "MIT",
6
6
  "main": "index.js",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "groove-dev",
3
- "version": "0.27.143",
3
+ "version": "0.27.145",
4
4
  "description": "Open-source agent orchestration layer — the AI company OS. Local model agent engine (GGUF/Ollama/llama-server), HuggingFace model browser, MCP integrations (Slack, Gmail, Stripe, 15+), agent scheduling (cron), business roles (CMO, CFO, EA). GUI dashboard, multi-agent coordination, zero cold-start, infinite sessions. Works with Claude Code, Codex, Gemini CLI, Ollama, any local model.",
5
5
  "license": "FSL-1.1-Apache-2.0",
6
6
  "author": "Groove Dev <hello@groovedev.ai> (https://groovedev.ai)",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groove-dev/cli",
3
- "version": "0.27.143",
3
+ "version": "0.27.145",
4
4
  "description": "GROOVE CLI — manage AI coding agents from your terminal",
5
5
  "license": "FSL-1.1-Apache-2.0",
6
6
  "type": "module",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groove-dev/daemon",
3
- "version": "0.27.143",
3
+ "version": "0.27.145",
4
4
  "description": "GROOVE daemon — agent orchestration engine",
5
5
  "license": "FSL-1.1-Apache-2.0",
6
6
  "type": "module",