@geminilight/mindos 0.6.71 → 0.6.73

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 (227) hide show
  1. package/_standalone/.mindos-build-version +1 -1
  2. package/_standalone/.next/BUILD_ID +1 -1
  3. package/_standalone/.next/app-path-routes-manifest.json +27 -27
  4. package/_standalone/.next/build-manifest.json +3 -3
  5. package/_standalone/.next/cache/.previewinfo +1 -1
  6. package/_standalone/.next/cache/.rscinfo +1 -1
  7. package/_standalone/.next/cache/config.json +3 -3
  8. package/_standalone/.next/prerender-manifest.json +3 -3
  9. package/_standalone/.next/react-loadable-manifest.json +4 -4
  10. package/_standalone/.next/server/app/.well-known/agent-card.json/route_client-reference-manifest.js +1 -1
  11. package/_standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  12. package/_standalone/.next/server/app/_global-error.html +2 -2
  13. package/_standalone/.next/server/app/_global-error.rsc +1 -1
  14. package/_standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  15. package/_standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  16. package/_standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  17. package/_standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  18. package/_standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  19. package/_standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  20. package/_standalone/.next/server/app/_not-found/page.js +1 -1
  21. package/_standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  22. package/_standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  23. package/_standalone/.next/server/app/agents/[agentKey]/page.js +1 -1
  24. package/_standalone/.next/server/app/agents/[agentKey]/page.js.nft.json +1 -1
  25. package/_standalone/.next/server/app/agents/[agentKey]/page_client-reference-manifest.js +1 -1
  26. package/_standalone/.next/server/app/agents/page.js +1 -1
  27. package/_standalone/.next/server/app/agents/page.js.nft.json +1 -1
  28. package/_standalone/.next/server/app/agents/page_client-reference-manifest.js +1 -1
  29. package/_standalone/.next/server/app/api/a2a/agents/route_client-reference-manifest.js +1 -1
  30. package/_standalone/.next/server/app/api/a2a/delegations/route_client-reference-manifest.js +1 -1
  31. package/_standalone/.next/server/app/api/a2a/discover/route_client-reference-manifest.js +1 -1
  32. package/_standalone/.next/server/app/api/a2a/route_client-reference-manifest.js +1 -1
  33. package/_standalone/.next/server/app/api/acp/config/route_client-reference-manifest.js +1 -1
  34. package/_standalone/.next/server/app/api/acp/detect/route_client-reference-manifest.js +1 -1
  35. package/_standalone/.next/server/app/api/acp/install/route_client-reference-manifest.js +1 -1
  36. package/_standalone/.next/server/app/api/acp/registry/route_client-reference-manifest.js +1 -1
  37. package/_standalone/.next/server/app/api/acp/session/route_client-reference-manifest.js +1 -1
  38. package/_standalone/.next/server/app/api/agent-activity/route_client-reference-manifest.js +1 -1
  39. package/_standalone/.next/server/app/api/agents/copy-skill/route_client-reference-manifest.js +1 -1
  40. package/_standalone/.next/server/app/api/agents/custom/detect/route_client-reference-manifest.js +1 -1
  41. package/_standalone/.next/server/app/api/agents/custom/route_client-reference-manifest.js +1 -1
  42. package/_standalone/.next/server/app/api/ask/route_client-reference-manifest.js +1 -1
  43. package/_standalone/.next/server/app/api/ask-sessions/route_client-reference-manifest.js +1 -1
  44. package/_standalone/.next/server/app/api/auth/route_client-reference-manifest.js +1 -1
  45. package/_standalone/.next/server/app/api/backlinks/route_client-reference-manifest.js +1 -1
  46. package/_standalone/.next/server/app/api/bootstrap/route_client-reference-manifest.js +1 -1
  47. package/_standalone/.next/server/app/api/changes/route_client-reference-manifest.js +1 -1
  48. package/_standalone/.next/server/app/api/channels/verify/route_client-reference-manifest.js +1 -1
  49. package/_standalone/.next/server/app/api/connect/route_client-reference-manifest.js +1 -1
  50. package/_standalone/.next/server/app/api/embedding/route_client-reference-manifest.js +1 -1
  51. package/_standalone/.next/server/app/api/export/route_client-reference-manifest.js +1 -1
  52. package/_standalone/.next/server/app/api/extract-pdf/route_client-reference-manifest.js +1 -1
  53. package/_standalone/.next/server/app/api/file/import/route_client-reference-manifest.js +1 -1
  54. package/_standalone/.next/server/app/api/file/raw/route_client-reference-manifest.js +1 -1
  55. package/_standalone/.next/server/app/api/file/route_client-reference-manifest.js +1 -1
  56. package/_standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  57. package/_standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  58. package/_standalone/.next/server/app/api/graph/route_client-reference-manifest.js +1 -1
  59. package/_standalone/.next/server/app/api/health/route_client-reference-manifest.js +1 -1
  60. package/_standalone/.next/server/app/api/im/activity/route_client-reference-manifest.js +1 -1
  61. package/_standalone/.next/server/app/api/im/config/route_client-reference-manifest.js +1 -1
  62. package/_standalone/.next/server/app/api/im/status/route_client-reference-manifest.js +1 -1
  63. package/_standalone/.next/server/app/api/im/test/route_client-reference-manifest.js +1 -1
  64. package/_standalone/.next/server/app/api/im/webhook/feishu/route_client-reference-manifest.js +1 -1
  65. package/_standalone/.next/server/app/api/im/webhook-status/route_client-reference-manifest.js +1 -1
  66. package/_standalone/.next/server/app/api/inbox/clip/route_client-reference-manifest.js +1 -1
  67. package/_standalone/.next/server/app/api/inbox/route_client-reference-manifest.js +1 -1
  68. package/_standalone/.next/server/app/api/init/route_client-reference-manifest.js +1 -1
  69. package/_standalone/.next/server/app/api/lint/route_client-reference-manifest.js +1 -1
  70. package/_standalone/.next/server/app/api/mcp/agents/route_client-reference-manifest.js +1 -1
  71. package/_standalone/.next/server/app/api/mcp/direct-tools/route_client-reference-manifest.js +1 -1
  72. package/_standalone/.next/server/app/api/mcp/install/route_client-reference-manifest.js +1 -1
  73. package/_standalone/.next/server/app/api/mcp/install-skill/route_client-reference-manifest.js +1 -1
  74. package/_standalone/.next/server/app/api/mcp/restart/route_client-reference-manifest.js +1 -1
  75. package/_standalone/.next/server/app/api/mcp/status/route_client-reference-manifest.js +1 -1
  76. package/_standalone/.next/server/app/api/mcp/tools/route_client-reference-manifest.js +1 -1
  77. package/_standalone/.next/server/app/api/mcp/uninstall/route_client-reference-manifest.js +1 -1
  78. package/_standalone/.next/server/app/api/monitoring/route_client-reference-manifest.js +1 -1
  79. package/_standalone/.next/server/app/api/recent-files/route_client-reference-manifest.js +1 -1
  80. package/_standalone/.next/server/app/api/restart/route_client-reference-manifest.js +1 -1
  81. package/_standalone/.next/server/app/api/search/route_client-reference-manifest.js +1 -1
  82. package/_standalone/.next/server/app/api/settings/list-models/route_client-reference-manifest.js +1 -1
  83. package/_standalone/.next/server/app/api/settings/reset-token/route_client-reference-manifest.js +1 -1
  84. package/_standalone/.next/server/app/api/settings/route_client-reference-manifest.js +1 -1
  85. package/_standalone/.next/server/app/api/settings/test-key/route_client-reference-manifest.js +1 -1
  86. package/_standalone/.next/server/app/api/setup/check-path/route_client-reference-manifest.js +1 -1
  87. package/_standalone/.next/server/app/api/setup/check-port/route_client-reference-manifest.js +1 -1
  88. package/_standalone/.next/server/app/api/setup/generate-token/route_client-reference-manifest.js +1 -1
  89. package/_standalone/.next/server/app/api/setup/ls/route_client-reference-manifest.js +1 -1
  90. package/_standalone/.next/server/app/api/setup/route_client-reference-manifest.js +1 -1
  91. package/_standalone/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
  92. package/_standalone/.next/server/app/api/space-overview/route_client-reference-manifest.js +1 -1
  93. package/_standalone/.next/server/app/api/sync/route_client-reference-manifest.js +1 -1
  94. package/_standalone/.next/server/app/api/tree-version/route_client-reference-manifest.js +1 -1
  95. package/_standalone/.next/server/app/api/uninstall/route_client-reference-manifest.js +1 -1
  96. package/_standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  97. package/_standalone/.next/server/app/api/update-check/route_client-reference-manifest.js +1 -1
  98. package/_standalone/.next/server/app/api/update-status/route_client-reference-manifest.js +1 -1
  99. package/_standalone/.next/server/app/api/workflows/route_client-reference-manifest.js +1 -1
  100. package/_standalone/.next/server/app/changelog/page.js +1 -1
  101. package/_standalone/.next/server/app/changelog/page.js.nft.json +1 -1
  102. package/_standalone/.next/server/app/changelog/page_client-reference-manifest.js +1 -1
  103. package/_standalone/.next/server/app/changes/page.js +1 -1
  104. package/_standalone/.next/server/app/changes/page.js.nft.json +1 -1
  105. package/_standalone/.next/server/app/changes/page_client-reference-manifest.js +1 -1
  106. package/_standalone/.next/server/app/echo/[segment]/page.js +1 -1
  107. package/_standalone/.next/server/app/echo/[segment]/page.js.nft.json +1 -1
  108. package/_standalone/.next/server/app/echo/[segment]/page_client-reference-manifest.js +1 -1
  109. package/_standalone/.next/server/app/echo/page.js +1 -1
  110. package/_standalone/.next/server/app/echo/page.js.nft.json +1 -1
  111. package/_standalone/.next/server/app/echo/page_client-reference-manifest.js +1 -1
  112. package/_standalone/.next/server/app/explore/page.js +1 -1
  113. package/_standalone/.next/server/app/explore/page.js.nft.json +1 -1
  114. package/_standalone/.next/server/app/explore/page_client-reference-manifest.js +1 -1
  115. package/_standalone/.next/server/app/help/page.js +1 -1
  116. package/_standalone/.next/server/app/help/page.js.nft.json +1 -1
  117. package/_standalone/.next/server/app/help/page_client-reference-manifest.js +1 -1
  118. package/_standalone/.next/server/app/inbox/history/page.js +1 -1
  119. package/_standalone/.next/server/app/inbox/history/page.js.nft.json +1 -1
  120. package/_standalone/.next/server/app/inbox/history/page_client-reference-manifest.js +1 -1
  121. package/_standalone/.next/server/app/login/page.js +1 -1
  122. package/_standalone/.next/server/app/login/page.js.nft.json +1 -1
  123. package/_standalone/.next/server/app/login/page_client-reference-manifest.js +1 -1
  124. package/_standalone/.next/server/app/page.js +1 -1
  125. package/_standalone/.next/server/app/page.js.nft.json +1 -1
  126. package/_standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  127. package/_standalone/.next/server/app/setup/page.js +1 -1
  128. package/_standalone/.next/server/app/setup/page.js.nft.json +1 -1
  129. package/_standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
  130. package/_standalone/.next/server/app/trash/page.js +2 -2
  131. package/_standalone/.next/server/app/trash/page_client-reference-manifest.js +1 -1
  132. package/_standalone/.next/server/app/view/[...path]/page.js +2 -2
  133. package/_standalone/.next/server/app/view/[...path]/page.js.nft.json +1 -1
  134. package/_standalone/.next/server/app/view/[...path]/page_client-reference-manifest.js +1 -1
  135. package/_standalone/.next/server/app-paths-manifest.json +27 -27
  136. package/_standalone/.next/server/chunks/{3311.js → 2449.js} +2 -2
  137. package/_standalone/.next/server/chunks/5299.js +1 -1
  138. package/_standalone/.next/server/chunks/6022.js +34 -34
  139. package/_standalone/.next/server/middleware-build-manifest.js +1 -1
  140. package/_standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  141. package/_standalone/.next/server/pages/500.html +2 -2
  142. package/_standalone/.next/server/server-reference-manifest.js +1 -1
  143. package/_standalone/.next/server/server-reference-manifest.json +1 -1
  144. package/_standalone/.next/static/chunks/{7143.879daa87569c5b02.js → 4094.09364c01df411380.js} +1 -1
  145. package/_standalone/.next/static/chunks/{5795.d9099a1afecd6047.js → 5331.c89084fd7f67887d.js} +2 -2
  146. package/_standalone/.next/static/chunks/app/{layout-a344709b8447be75.js → layout-fcbde5bee626d21a.js} +63 -63
  147. package/_standalone/.next/static/chunks/app/trash/page-e623ff0ab35de002.js +1 -0
  148. package/_standalone/.next/static/chunks/app/view/[...path]/page-49c4eff6ffdb5168.js +12 -0
  149. package/_standalone/.next/static/chunks/{webpack-2f2787d3469d3df1.js → webpack-dc486b68118d1328.js} +1 -1
  150. package/_standalone/.next/trace +72 -72
  151. package/_standalone/package-lock.json +2 -2
  152. package/_standalone/package.json +1 -1
  153. package/app/package.json +1 -1
  154. package/package.json +1 -1
  155. package/_standalone/.next/static/chunks/app/trash/page-0907fdd06a4467de.js +0 -1
  156. package/_standalone/.next/static/chunks/app/view/[...path]/page-f53ce199b4a4bbb5.js +0 -12
  157. package/browser-extension/README.md +0 -160
  158. package/browser-extension/build.mjs +0 -63
  159. package/browser-extension/extension/background/service-worker.js +0 -1
  160. package/browser-extension/extension/content/extractor.js +0 -2
  161. package/browser-extension/extension/icons/icon-128.png +0 -0
  162. package/browser-extension/extension/icons/icon-128.svg +0 -4
  163. package/browser-extension/extension/icons/icon-16.png +0 -0
  164. package/browser-extension/extension/icons/icon-16.svg +0 -4
  165. package/browser-extension/extension/icons/icon-32.png +0 -0
  166. package/browser-extension/extension/icons/icon-32.svg +0 -4
  167. package/browser-extension/extension/icons/icon-48.png +0 -0
  168. package/browser-extension/extension/icons/icon-48.svg +0 -4
  169. package/browser-extension/extension/manifest.json +0 -47
  170. package/browser-extension/extension/popup/popup.css +0 -510
  171. package/browser-extension/extension/popup/popup.html +0 -128
  172. package/browser-extension/extension/popup/popup.js +0 -73
  173. package/browser-extension/package-lock.json +0 -617
  174. package/browser-extension/package.json +0 -21
  175. package/browser-extension/scripts/gen-icons.sh +0 -38
  176. package/browser-extension/src/background/service-worker.ts +0 -27
  177. package/browser-extension/src/content/extractor.ts +0 -44
  178. package/browser-extension/src/icons/icon-128.png +0 -0
  179. package/browser-extension/src/icons/icon-128.svg +0 -4
  180. package/browser-extension/src/icons/icon-16.png +0 -0
  181. package/browser-extension/src/icons/icon-16.svg +0 -4
  182. package/browser-extension/src/icons/icon-32.png +0 -0
  183. package/browser-extension/src/icons/icon-32.svg +0 -4
  184. package/browser-extension/src/icons/icon-48.png +0 -0
  185. package/browser-extension/src/icons/icon-48.svg +0 -4
  186. package/browser-extension/src/lib/api.ts +0 -146
  187. package/browser-extension/src/lib/markdown.ts +0 -68
  188. package/browser-extension/src/lib/storage.ts +0 -37
  189. package/browser-extension/src/lib/types.ts +0 -42
  190. package/browser-extension/src/manifest.json +0 -47
  191. package/browser-extension/src/popup/popup.css +0 -510
  192. package/browser-extension/src/popup/popup.html +0 -128
  193. package/browser-extension/src/popup/popup.ts +0 -416
  194. package/browser-extension/tsconfig.json +0 -16
  195. package/tests/e2e/README.md +0 -25
  196. package/tests/e2e/navigation.spec.ts +0 -14
  197. package/tests/e2e/playwright.config.ts +0 -14
  198. package/tests/integration/README.md +0 -25
  199. package/tests/integration/mcp-contract.test.ts +0 -57
  200. package/tests/integration/mcp-transport.test.ts +0 -361
  201. package/tests/integration/package-lock.json +0 -1463
  202. package/tests/integration/package.json +0 -8
  203. package/tests/integration/vitest.config.ts +0 -11
  204. package/tests/security-hardening.test.ts +0 -456
  205. package/tests/unit/build-integrity.test.ts +0 -137
  206. package/tests/unit/cli-build.test.ts +0 -180
  207. package/tests/unit/cli-config.test.ts +0 -257
  208. package/tests/unit/cli-mcp-install-toml.test.ts +0 -586
  209. package/tests/unit/cli-mcp-install.test.ts +0 -123
  210. package/tests/unit/cli-mcp-stdio-default.test.ts +0 -180
  211. package/tests/unit/cli-modules-load.test.ts +0 -64
  212. package/tests/unit/cli-port.test.ts +0 -87
  213. package/tests/unit/cli-skill-auto-copy.test.ts +0 -260
  214. package/tests/unit/cli-smoke.test.ts +0 -88
  215. package/tests/unit/cli-uninstall.test.ts +0 -218
  216. package/tests/unit/cli-update-root.test.ts +0 -89
  217. package/tests/unit/cli-user-flow-sim.test.ts +0 -506
  218. package/tests/unit/cli-wait-hint.test.ts +0 -86
  219. package/tests/unit/custom-agents.test.ts +0 -478
  220. package/tests/unit/dep-safety.test.ts +0 -126
  221. package/tests/unit/detect-system-lang.test.ts +0 -122
  222. package/tests/unit/mcp-build.test.ts +0 -162
  223. package/tests/unit/setup-needs-restart.test.ts +0 -139
  224. package/tests/unit/stop-restart.test.ts +0 -393
  225. package/tests/unit/vitest.config.ts +0 -8
  226. /package/_standalone/.next/static/{w5bqzZbd2_vdoPRB0JQ_I → Dn8EHqUedSzanCfrM8WWS}/_buildManifest.js +0 -0
  227. /package/_standalone/.next/static/{w5bqzZbd2_vdoPRB0JQ_I → Dn8EHqUedSzanCfrM8WWS}/_ssgManifest.js +0 -0
@@ -1,393 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
-
3
- // ── Extracted logic from bin/lib/stop.js ─────────────────────────────────────
4
- // Unit-testable pure functions extracted from the source to prevent regressions.
5
- // If the source changes, update these in sync.
6
-
7
- /**
8
- * Parse PIDs from `ss -tlnp` output for a given port.
9
- * Must not false-positive on partial port matches (e.g. port 80 ≠ :8080).
10
- */
11
- function parseSsPids(ssOutput: string, port: number): number[] {
12
- const pidsToKill = new Set<number>();
13
- const portRe = new RegExp(`:${port}(?!\\d)`);
14
- for (const line of ssOutput.split('\n')) {
15
- if (!portRe.test(line)) continue;
16
- const pidMatch = line.match(/pid=(\d+)/g);
17
- if (pidMatch) {
18
- for (const m of pidMatch) {
19
- const pid = Number(m.slice(4));
20
- if (pid > 0) pidsToKill.add(pid);
21
- }
22
- }
23
- }
24
- return [...pidsToKill];
25
- }
26
-
27
- /**
28
- * Parse PIDs from `lsof -ti :PORT` output.
29
- */
30
- function parseLsofPids(lsofOutput: string): number[] {
31
- return lsofOutput
32
- .trim()
33
- .split('\n')
34
- .map(Number)
35
- .filter((p) => p > 0);
36
- }
37
-
38
- // ── ss PID parsing ───────────────────────────────────────────────────────────
39
-
40
- const SS_SAMPLE = `State Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
41
- LISTEN 0 511 0.0.0.0:5175 0.0.0.0:* users:(("node",pid=100,fd=22))
42
- LISTEN 0 511 127.0.0.1:8787 0.0.0.0:* users:(("node",pid=200,fd=31))
43
- LISTEN 0 511 *:3003 *:* users:(("next-server (v1",pid=300,fd=21))
44
- LISTEN 0 2048 0.0.0.0:3001 0.0.0.0:* users:(("python",pid=400,fd=16))
45
- LISTEN 0 2048 0.0.0.0:30030 0.0.0.0:* users:(("node",pid=500,fd=10))
46
- LISTEN 0 511 *:80 *:* users:(("nginx",pid=600,fd=6))
47
- LISTEN 0 511 *:8080 *:* users:(("node",pid=700,fd=8))`;
48
-
49
- describe('parseSsPids — basic extraction', () => {
50
- it('finds PID for port 8787', () => {
51
- expect(parseSsPids(SS_SAMPLE, 8787)).toEqual([200]);
52
- });
53
-
54
- it('finds PID for port 3003', () => {
55
- expect(parseSsPids(SS_SAMPLE, 3003)).toEqual([300]);
56
- });
57
-
58
- it('finds PID for port 3001', () => {
59
- expect(parseSsPids(SS_SAMPLE, 3001)).toEqual([400]);
60
- });
61
-
62
- it('returns empty for non-existent port', () => {
63
- expect(parseSsPids(SS_SAMPLE, 9999)).toEqual([]);
64
- });
65
- });
66
-
67
- describe('parseSsPids — no partial port matches', () => {
68
- it('port 3003 does NOT match :30030', () => {
69
- // :30030 contains :3003 as substring — must not match
70
- const pids = parseSsPids(SS_SAMPLE, 3003);
71
- expect(pids).not.toContain(500);
72
- expect(pids).toEqual([300]);
73
- });
74
-
75
- it('port 80 does NOT match :8080 or :8787', () => {
76
- const pids = parseSsPids(SS_SAMPLE, 80);
77
- expect(pids).not.toContain(700); // 8080
78
- expect(pids).not.toContain(200); // 8787
79
- expect(pids).toEqual([600]); // only port 80
80
- });
81
-
82
- it('port 800 does NOT match :8001 or :80', () => {
83
- const pids = parseSsPids(SS_SAMPLE, 800);
84
- expect(pids).toEqual([]);
85
- });
86
-
87
- it('port 300 does NOT match :3001 or :3003 or :30030', () => {
88
- const pids = parseSsPids(SS_SAMPLE, 300);
89
- expect(pids).toEqual([]);
90
- });
91
- });
92
-
93
- describe('parseSsPids — multiple PIDs on one line', () => {
94
- it('extracts all PIDs when multiple processes share a port', () => {
95
- const line = `LISTEN 0 128 *:4000 *:* users:(("node",pid=111,fd=3),("node",pid=222,fd=4))`;
96
- expect(parseSsPids(line, 4000).sort()).toEqual([111, 222]);
97
- });
98
- });
99
-
100
- describe('parseSsPids — empty / malformed input', () => {
101
- it('handles empty string', () => {
102
- expect(parseSsPids('', 3000)).toEqual([]);
103
- });
104
-
105
- it('handles header-only output', () => {
106
- expect(parseSsPids('State Recv-Q Send-Q ...', 3000)).toEqual([]);
107
- });
108
-
109
- it('handles line with port but no pid=', () => {
110
- const line = `LISTEN 0 511 *:3000 *:*`;
111
- expect(parseSsPids(line, 3000)).toEqual([]);
112
- });
113
- });
114
-
115
- // ── lsof PID parsing ─────────────────────────────────────────────────────────
116
-
117
- describe('parseLsofPids', () => {
118
- it('parses single PID', () => {
119
- expect(parseLsofPids('12345\n')).toEqual([12345]);
120
- });
121
-
122
- it('parses multiple PIDs', () => {
123
- expect(parseLsofPids('111\n222\n333\n')).toEqual([111, 222, 333]);
124
- });
125
-
126
- it('handles empty string', () => {
127
- expect(parseLsofPids('')).toEqual([]);
128
- });
129
-
130
- it('filters out non-numeric lines', () => {
131
- expect(parseLsofPids('abc\n123\n\n456')).toEqual([123, 456]);
132
- });
133
- });
134
-
135
- // ── setup.js finish() contract ───────────────────────────────────────────────
136
- // These tests verify the logic contract: when needsRestart is true and server
137
- // is running, the CLI must call 'restart' (not 'start') to avoid port conflicts.
138
-
139
- describe('finish() restart contract', () => {
140
- // Extracted logic from scripts/setup.js finish() — the command selection
141
- function getRestartCommand(needsRestart: boolean, isRunning: boolean): string | null {
142
- if (needsRestart && isRunning) {
143
- // Must use 'restart' to stop old process first
144
- return 'restart';
145
- }
146
- if (needsRestart && !isRunning) {
147
- // No running process, can start fresh
148
- return 'start';
149
- }
150
- return null; // no restart needed
151
- }
152
-
153
- it('uses restart when server is running and config changed', () => {
154
- expect(getRestartCommand(true, true)).toBe('restart');
155
- });
156
-
157
- it('uses start when server is NOT running and config changed', () => {
158
- expect(getRestartCommand(true, false)).toBe('start');
159
- });
160
-
161
- it('returns null when no restart needed', () => {
162
- expect(getRestartCommand(false, true)).toBeNull();
163
- expect(getRestartCommand(false, false)).toBeNull();
164
- });
165
-
166
- // Regression: the old code called 'start' when needsRestart=true and
167
- // isRunning=true, which failed assertPortFree because ports were still held.
168
- it('NEVER returns start when server is running (regression)', () => {
169
- expect(getRestartCommand(true, true)).not.toBe('start');
170
- });
171
- });
172
-
173
- // ── CLI restart contract ─────────────────────────────────────────────────────
174
- // restart must: (1) stop first, (2) wait for ports to free, (3) then start.
175
- // We test the port-wait logic.
176
-
177
- describe('restart port-wait logic', () => {
178
- // Simulate the port-wait loop from bin/cli.js restart command
179
- async function waitForPortsFree(
180
- isPortInUse: (port: number) => Promise<boolean>,
181
- webPort: number,
182
- mcpPort: number,
183
- deadlineMs: number,
184
- ): Promise<boolean> {
185
- const deadline = Date.now() + deadlineMs;
186
- while (Date.now() < deadline) {
187
- const webBusy = await isPortInUse(webPort);
188
- const mcpBusy = await isPortInUse(mcpPort);
189
- if (!webBusy && !mcpBusy) return true;
190
- await new Promise((r) => setTimeout(r, 10)); // fast tick for tests
191
- }
192
- return false;
193
- }
194
-
195
- it('returns true immediately when ports are free', async () => {
196
- const result = await waitForPortsFree(() => Promise.resolve(false), 3000, 8787, 1000);
197
- expect(result).toBe(true);
198
- });
199
-
200
- it('waits until ports become free', async () => {
201
- let callCount = 0;
202
- const isPortInUse = async () => {
203
- callCount++;
204
- return callCount <= 4; // busy for first 4 checks, then free
205
- };
206
- const result = await waitForPortsFree(isPortInUse, 3000, 8787, 5000);
207
- expect(result).toBe(true);
208
- expect(callCount).toBeGreaterThan(4);
209
- });
210
-
211
- it('times out when ports never free', async () => {
212
- const result = await waitForPortsFree(() => Promise.resolve(true), 3000, 8787, 50);
213
- expect(result).toBe(false);
214
- });
215
- });
216
-
217
- // ── stopMindos contract ──────────────────────────────────────────────────────
218
- // Verifies that port-based cleanup always runs, even when PID file exists.
219
-
220
- describe('stopMindos — port cleanup always runs', () => {
221
- // Simulate stopMindos flow
222
- function simulateStop(opts: {
223
- pidsFromFile: number[];
224
- killTreeSuccess: boolean;
225
- killByPortResult: number;
226
- }): { pidKilled: boolean; portCleanupRan: boolean } {
227
- let pidKilled = false;
228
- let portCleanupRan = false;
229
-
230
- const pids = opts.pidsFromFile;
231
- if (pids.length) {
232
- // Kill saved PIDs
233
- pidKilled = opts.killTreeSuccess;
234
- }
235
-
236
- // Port-based cleanup — ALWAYS runs
237
- portCleanupRan = true;
238
- // In real code: portKilled += killByPort(port);
239
-
240
- return { pidKilled, portCleanupRan };
241
- }
242
-
243
- it('runs port cleanup even when PID file exists and kill succeeds', () => {
244
- const result = simulateStop({
245
- pidsFromFile: [1234, 5678],
246
- killTreeSuccess: true,
247
- killByPortResult: 0,
248
- });
249
- expect(result.pidKilled).toBe(true);
250
- expect(result.portCleanupRan).toBe(true); // KEY: always runs
251
- });
252
-
253
- it('runs port cleanup when PID file is empty', () => {
254
- const result = simulateStop({
255
- pidsFromFile: [],
256
- killTreeSuccess: false,
257
- killByPortResult: 1,
258
- });
259
- expect(result.portCleanupRan).toBe(true);
260
- });
261
-
262
- // Regression: old code skipped port cleanup when PID file existed,
263
- // leaving Next.js worker processes orphaned.
264
- it('REGRESSION: port cleanup must not be skipped when PIDs exist', () => {
265
- const result = simulateStop({
266
- pidsFromFile: [1111],
267
- killTreeSuccess: true,
268
- killByPortResult: 0,
269
- });
270
- expect(result.portCleanupRan).toBe(true);
271
- });
272
- });
273
-
274
- // ── Port-change restart contract ────────────────────────────────────────────
275
- // When user changes ports in GUI, the config file has NEW ports but processes
276
- // still listen on OLD ports. stopMindos must clean up BOTH old and new ports.
277
-
278
- describe('restart with port change — old ports must be cleaned', () => {
279
- // Simulate the restart logic: collect old ports, pass as extraPorts
280
- function getExtraPorts(
281
- oldEnv: { webPort?: string; mcpPort?: string },
282
- newConfig: { webPort: number; mcpPort: number },
283
- ): string[] {
284
- const extra: string[] = [];
285
- if (oldEnv.webPort && Number(oldEnv.webPort) !== newConfig.webPort) {
286
- extra.push(oldEnv.webPort);
287
- }
288
- if (oldEnv.mcpPort && Number(oldEnv.mcpPort) !== newConfig.mcpPort) {
289
- extra.push(oldEnv.mcpPort);
290
- }
291
- return extra;
292
- }
293
-
294
- // Simulate stopMindos port collection
295
- function getPortsToClean(
296
- configPorts: { webPort: string; mcpPort: string },
297
- extraPorts: string[],
298
- ): Set<string> {
299
- const ports = new Set([configPorts.webPort, configPorts.mcpPort]);
300
- for (const p of extraPorts) ports.add(p);
301
- return ports;
302
- }
303
-
304
- it('includes old ports when ports changed', () => {
305
- const extra = getExtraPorts(
306
- { webPort: '3011', mcpPort: '8787' },
307
- { webPort: 3012, mcpPort: 8796 },
308
- );
309
- expect(extra).toEqual(['3011', '8787']);
310
-
311
- // stopMindos config already has new ports
312
- const ports = getPortsToClean({ webPort: '3012', mcpPort: '8796' }, extra);
313
- expect(ports.has('3011')).toBe(true); // old web port
314
- expect(ports.has('8787')).toBe(true); // old mcp port
315
- expect(ports.has('3012')).toBe(true); // new web port
316
- expect(ports.has('8796')).toBe(true); // new mcp port
317
- });
318
-
319
- it('no extra ports when ports unchanged', () => {
320
- const extra = getExtraPorts(
321
- { webPort: '3011', mcpPort: '8787' },
322
- { webPort: 3011, mcpPort: 8787 },
323
- );
324
- expect(extra).toEqual([]);
325
- });
326
-
327
- it('handles missing old env vars (fresh start)', () => {
328
- const extra = getExtraPorts({}, { webPort: 3012, mcpPort: 8796 });
329
- expect(extra).toEqual([]);
330
- });
331
-
332
- // Regression: /api/restart passed process.env directly to child,
333
- // so loadConfig() skipped new values because env vars were already set.
334
- it('REGRESSION: child process env must not contain stale port vars', () => {
335
- // Simulate what /api/restart does now
336
- const parentEnv: Record<string, string> = {
337
- MINDOS_WEB_PORT: '3011',
338
- MINDOS_MCP_PORT: '8787',
339
- PATH: '/usr/bin',
340
- };
341
- const childEnv = { ...parentEnv };
342
- const oldWeb = childEnv.MINDOS_WEB_PORT;
343
- const oldMcp = childEnv.MINDOS_MCP_PORT;
344
- delete childEnv.MINDOS_WEB_PORT;
345
- delete childEnv.MINDOS_MCP_PORT;
346
- // Old ports must be passed via MINDOS_OLD_* so restart can clean them up
347
- if (oldWeb) childEnv.MINDOS_OLD_WEB_PORT = oldWeb;
348
- if (oldMcp) childEnv.MINDOS_OLD_MCP_PORT = oldMcp;
349
-
350
- expect(childEnv.MINDOS_WEB_PORT).toBeUndefined();
351
- expect(childEnv.MINDOS_MCP_PORT).toBeUndefined();
352
- expect(childEnv.MINDOS_OLD_WEB_PORT).toBe('3011');
353
- expect(childEnv.MINDOS_OLD_MCP_PORT).toBe('8787');
354
- expect(childEnv.PATH).toBe('/usr/bin'); // other vars preserved
355
- });
356
-
357
- // cli.js restart reads old ports from MINDOS_OLD_* OR current MINDOS_*
358
- it('restart reads old ports from MINDOS_OLD_* env (GUI path)', () => {
359
- // Simulate: /api/restart set MINDOS_OLD_* and deleted MINDOS_*
360
- const env: Record<string, string | undefined> = {
361
- MINDOS_OLD_WEB_PORT: '3011',
362
- MINDOS_OLD_MCP_PORT: '8787',
363
- };
364
- const oldWebPort = env.MINDOS_OLD_WEB_PORT || env.MINDOS_WEB_PORT;
365
- const oldMcpPort = env.MINDOS_OLD_MCP_PORT || env.MINDOS_MCP_PORT;
366
- expect(oldWebPort).toBe('3011');
367
- expect(oldMcpPort).toBe('8787');
368
- });
369
-
370
- it('restart reads old ports from MINDOS_* env (CLI path)', () => {
371
- // Simulate: `mindos restart` from CLI, no MINDOS_OLD_* set
372
- const env: Record<string, string | undefined> = {
373
- MINDOS_WEB_PORT: '3011',
374
- MINDOS_MCP_PORT: '8787',
375
- };
376
- const oldWebPort = env.MINDOS_OLD_WEB_PORT || env.MINDOS_WEB_PORT;
377
- const oldMcpPort = env.MINDOS_OLD_MCP_PORT || env.MINDOS_MCP_PORT;
378
- expect(oldWebPort).toBe('3011');
379
- expect(oldMcpPort).toBe('8787');
380
- });
381
-
382
- // The restart wait loop must wait for ALL ports (old + new) to be free
383
- it('wait loop covers both old and new ports', async () => {
384
- const allPorts = new Set([3012, 8796]);
385
- for (const p of ['3011', '8787']) allPorts.add(Number(p));
386
-
387
- expect(allPorts.size).toBe(4);
388
- expect(allPorts.has(3011)).toBe(true);
389
- expect(allPorts.has(8787)).toBe(true);
390
- expect(allPorts.has(3012)).toBe(true);
391
- expect(allPorts.has(8796)).toBe(true);
392
- });
393
- });
@@ -1,8 +0,0 @@
1
- import { defineConfig } from '../integration/node_modules/vitest/dist/config.js';
2
-
3
- export default defineConfig({
4
- test: {
5
- include: ['**/*.test.ts'],
6
- testTimeout: 30_000,
7
- },
8
- });