@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,123 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
- import fs from 'fs';
3
- import os from 'os';
4
- import path from 'path';
5
-
6
- /**
7
- * Tests for MCP install config — entry format and config file merging.
8
- *
9
- * mcpInstall() is an interactive TUI function that can't be directly imported
10
- * without triggering readline. We test the two critical contracts:
11
- *
12
- * 1. Entry format (contract test — logic extracted from source)
13
- * 2. Config file merge (e2e — real file I/O)
14
- */
15
-
16
- let tempDir: string;
17
-
18
- beforeEach(() => {
19
- tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mindos-mcp-test-'));
20
- });
21
-
22
- afterEach(() => {
23
- fs.rmSync(tempDir, { recursive: true, force: true });
24
- });
25
-
26
- // ── Entry format contract ───────────────────────────────────────────────────
27
- // Extracted from mcp-install.js lines 278-282
28
-
29
- function buildEntry(transport: string, url?: string, token?: string) {
30
- return transport === 'stdio'
31
- ? { type: 'stdio', command: 'mindos', args: ['mcp'], env: { MCP_TRANSPORT: 'stdio' } }
32
- : token
33
- ? { url, headers: { Authorization: `Bearer ${token}` } }
34
- : { url };
35
- }
36
-
37
- describe('MCP entry format', () => {
38
- it('stdio entry has correct structure', () => {
39
- const entry = buildEntry('stdio');
40
- expect(entry).toEqual({
41
- type: 'stdio',
42
- command: 'mindos',
43
- args: ['mcp'],
44
- env: { MCP_TRANSPORT: 'stdio' },
45
- });
46
- });
47
-
48
- it('http entry with token includes Authorization header', () => {
49
- const entry = buildEntry('http', 'http://localhost:8781/mcp', 'tok-abc');
50
- expect(entry).toEqual({
51
- url: 'http://localhost:8781/mcp',
52
- headers: { Authorization: 'Bearer tok-abc' },
53
- });
54
- });
55
-
56
- it('http entry without token has no headers', () => {
57
- const entry = buildEntry('http', 'http://localhost:8781/mcp');
58
- expect(entry).toEqual({ url: 'http://localhost:8781/mcp' });
59
- expect(entry).not.toHaveProperty('headers');
60
- });
61
- });
62
-
63
- // ── Config file merge ───────────────────────────────────────────────────────
64
- // Simulates the read→merge→write logic from mcp-install.js lines 312-329
65
-
66
- function mergeAndWrite(configPath: string, agentKey: string, entry: unknown) {
67
- let config: Record<string, Record<string, unknown>> = {};
68
- if (fs.existsSync(configPath)) {
69
- config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
70
- }
71
- if (!config[agentKey]) config[agentKey] = {};
72
- config[agentKey].mindos = entry;
73
-
74
- const dir = path.dirname(configPath);
75
- if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
76
- fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n', 'utf-8');
77
- }
78
-
79
- describe('MCP config file merge', () => {
80
- it('creates new config file when none exists', () => {
81
- const configPath = path.join(tempDir, 'mcp.json');
82
- const entry = buildEntry('stdio');
83
- mergeAndWrite(configPath, 'mcpServers', entry);
84
-
85
- const result = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
86
- expect(result.mcpServers.mindos).toEqual(entry);
87
- });
88
-
89
- it('preserves other mcpServers when adding mindos', () => {
90
- const configPath = path.join(tempDir, 'mcp.json');
91
- // Pre-existing config with another server
92
- fs.writeFileSync(configPath, JSON.stringify({
93
- mcpServers: {
94
- 'other-server': { url: 'http://other:9000/mcp' },
95
- },
96
- }, null, 2));
97
-
98
- const entry = buildEntry('http', 'http://localhost:8781/mcp', 'tok-123');
99
- mergeAndWrite(configPath, 'mcpServers', entry);
100
-
101
- const result = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
102
- expect(result.mcpServers.mindos).toEqual(entry);
103
- expect(result.mcpServers['other-server']).toEqual({ url: 'http://other:9000/mcp' });
104
- });
105
-
106
- it('updates existing mindos entry without losing other servers', () => {
107
- const configPath = path.join(tempDir, 'mcp.json');
108
- // Pre-existing config with old mindos + another server
109
- fs.writeFileSync(configPath, JSON.stringify({
110
- mcpServers: {
111
- mindos: { url: 'http://old:8000/mcp' },
112
- 'other-server': { command: 'other-cmd' },
113
- },
114
- }, null, 2));
115
-
116
- const newEntry = buildEntry('stdio');
117
- mergeAndWrite(configPath, 'mcpServers', newEntry);
118
-
119
- const result = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
120
- expect(result.mcpServers.mindos).toEqual(newEntry);
121
- expect(result.mcpServers['other-server']).toEqual({ command: 'other-cmd' });
122
- });
123
- });
@@ -1,180 +0,0 @@
1
- import { describe, it, expect, afterEach } from 'vitest';
2
- import { createServer, Server } from 'net';
3
- import { spawn, ChildProcess } from 'child_process';
4
- import { join } from 'path';
5
-
6
- /**
7
- * Regression test: `mindos mcp` (standalone) must default to stdio transport.
8
- *
9
- * Bug: When MindOS is already running (ports 3456 + 8781 bound), invoking
10
- * `mindos mcp` via an MCP client would start the MCP server in HTTP mode
11
- * (the default) and crash with EADDRINUSE on port 8781.
12
- *
13
- * Root cause: bin/cli.js `mcp` handler did not set MCP_TRANSPORT, so
14
- * mcp/src/index.ts fell through to the default "http" transport.
15
- */
16
-
17
- const CLI = join(__dirname, '../../bin/cli.js');
18
-
19
- const children: ChildProcess[] = [];
20
-
21
- afterEach(() => {
22
- for (const child of children) {
23
- try { child.kill('SIGTERM'); } catch {}
24
- }
25
- children.length = 0;
26
- });
27
-
28
- function getFreePort(): Promise<number> {
29
- return new Promise((resolve, reject) => {
30
- const srv = createServer();
31
- srv.listen(0, '127.0.0.1', () => {
32
- const addr = srv.address();
33
- if (addr && typeof addr === 'object') {
34
- srv.close(() => resolve(addr.port));
35
- } else {
36
- reject(new Error('no addr'));
37
- }
38
- });
39
- srv.on('error', reject);
40
- });
41
- }
42
-
43
- // ── Core regression test ──────────────────────────────────────────────────
44
-
45
- describe('mindos mcp stdio transport (regression)', () => {
46
- let blocker: Server | null = null;
47
-
48
- afterEach(async () => {
49
- if (blocker) {
50
- await new Promise<void>((resolve) => blocker!.close(() => resolve()));
51
- blocker = null;
52
- }
53
- });
54
-
55
- it('starts in stdio mode even when MCP_PORT is already in use', async () => {
56
- const port = await getFreePort();
57
-
58
- blocker = createServer();
59
- await new Promise<void>((resolve, reject) => {
60
- blocker!.listen(port, '127.0.0.1', () => resolve());
61
- blocker!.on('error', reject);
62
- });
63
-
64
- const proc = spawn(process.execPath, [CLI, 'mcp'], {
65
- env: {
66
- ...process.env,
67
- MCP_TRANSPORT: 'stdio',
68
- MCP_PORT: String(port),
69
- MINDOS_URL: 'http://localhost:3456',
70
- },
71
- stdio: ['pipe', 'pipe', 'pipe'],
72
- });
73
- children.push(proc);
74
-
75
- let stderr = '';
76
- proc.stderr?.on('data', (d: Buffer) => { stderr += d.toString(); });
77
-
78
- const response = await new Promise<string>((resolve, reject) => {
79
- const timeout = setTimeout(
80
- () => reject(new Error(`No response within 10s. stderr: ${stderr}`)),
81
- 10_000,
82
- );
83
- let buf = '';
84
- proc.stdout?.on('data', (chunk: Buffer) => {
85
- buf += chunk.toString();
86
- for (const line of buf.split('\n')) {
87
- if (!line.trim()) continue;
88
- try {
89
- const parsed = JSON.parse(line);
90
- if (parsed.id === 1) {
91
- clearTimeout(timeout);
92
- resolve(line);
93
- return;
94
- }
95
- } catch { /* incomplete */ }
96
- }
97
- });
98
-
99
- proc.stdin?.write(JSON.stringify({
100
- jsonrpc: '2.0', method: 'initialize', id: 1,
101
- params: {
102
- protocolVersion: '2025-03-26',
103
- capabilities: {},
104
- clientInfo: { name: 'test', version: '0.0.1' },
105
- },
106
- }) + '\n');
107
- });
108
-
109
- const parsed = JSON.parse(response);
110
- expect(parsed).toHaveProperty('result');
111
- expect(parsed.result.serverInfo.name).toBe('mindos-mcp-server');
112
-
113
- // Port is STILL occupied by blocker — stdio never tried to bind
114
- expect(blocker!.listening).toBe(true);
115
- proc.kill('SIGTERM');
116
- }, 15_000);
117
- });
118
-
119
- // ── CLI handler env construction (pure logic, no spawning) ────────────────
120
-
121
- describe('CLI mcp handler environment construction', () => {
122
- /**
123
- * Mirrors the logic in bin/cli.js `mcp` handler after the fix.
124
- * This is the contract we're verifying.
125
- */
126
- function buildMcpEnv(incoming: Record<string, string | undefined>) {
127
- const env = { ...incoming };
128
- if (!env.MCP_TRANSPORT) {
129
- env.MCP_TRANSPORT = 'stdio';
130
- }
131
- const webPort = env.MINDOS_WEB_PORT || '3456';
132
- env.MINDOS_URL = env.MINDOS_URL || `http://localhost:${webPort}`;
133
- if (env.MCP_TRANSPORT === 'http') {
134
- env.MCP_PORT = env.MINDOS_MCP_PORT || '8781';
135
- }
136
- return env;
137
- }
138
-
139
- it('defaults MCP_TRANSPORT to stdio when not set', () => {
140
- const env = buildMcpEnv({});
141
- expect(env.MCP_TRANSPORT).toBe('stdio');
142
- });
143
-
144
- it('preserves MCP_TRANSPORT when caller provides it', () => {
145
- const env = buildMcpEnv({ MCP_TRANSPORT: 'http' });
146
- expect(env.MCP_TRANSPORT).toBe('http');
147
- });
148
-
149
- it('does not set MCP_PORT for stdio transport', () => {
150
- const env = buildMcpEnv({});
151
- expect(env.MCP_PORT).toBeUndefined();
152
- });
153
-
154
- it('sets MCP_PORT for explicit http transport', () => {
155
- const env = buildMcpEnv({ MCP_TRANSPORT: 'http' });
156
- expect(env.MCP_PORT).toBe('8781');
157
- });
158
-
159
- it('respects custom MCP port from config for http', () => {
160
- const env = buildMcpEnv({ MCP_TRANSPORT: 'http', MINDOS_MCP_PORT: '9999' });
161
- expect(env.MCP_PORT).toBe('9999');
162
- });
163
-
164
- it('sets MINDOS_URL from web port when not provided', () => {
165
- const env = buildMcpEnv({ MINDOS_WEB_PORT: '4000' });
166
- expect(env.MINDOS_URL).toBe('http://localhost:4000');
167
- });
168
-
169
- it('preserves MINDOS_URL when already set', () => {
170
- const env = buildMcpEnv({ MINDOS_URL: 'http://remote:5000' });
171
- expect(env.MINDOS_URL).toBe('http://remote:5000');
172
- });
173
-
174
- it('uses default ports when nothing is configured', () => {
175
- const env = buildMcpEnv({});
176
- expect(env.MCP_TRANSPORT).toBe('stdio');
177
- expect(env.MINDOS_URL).toBe('http://localhost:3456');
178
- expect(env.MCP_PORT).toBeUndefined();
179
- });
180
- });
@@ -1,64 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { execFileSync } from 'child_process';
3
- import fs from 'fs';
4
- import path from 'path';
5
-
6
- /**
7
- * Module-load smoke tests — verify every bin/ JS module can be parsed by
8
- * the Node.js ESM loader without SyntaxError.
9
- *
10
- * Catches issues like premature comment termination (e.g. `MINDOS_*​/` inside
11
- * a block comment being treated as the closing `*​/`).
12
- */
13
-
14
- const ROOT = path.resolve(__dirname, '..', '..');
15
- const BIN = path.join(ROOT, 'bin');
16
-
17
- /** Collect all .js files under a directory (non-recursive, single level). */
18
- function listJs(dir: string): string[] {
19
- if (!fs.existsSync(dir)) return [];
20
- return fs
21
- .readdirSync(dir)
22
- .filter((f) => f.endsWith('.js'))
23
- .sort()
24
- .map((f) => path.join(dir, f));
25
- }
26
-
27
- // Gather every module under bin/
28
- const modules = [
29
- ...listJs(BIN),
30
- ...listJs(path.join(BIN, 'commands')),
31
- ...listJs(path.join(BIN, 'lib')),
32
- ];
33
-
34
- describe('bin/ modules can be parsed by Node.js ESM loader', () => {
35
- it.each(modules.map((m) => [path.relative(ROOT, m), m]))(
36
- '%s loads without SyntaxError',
37
- (_label, modulePath) => {
38
- // Use a subprocess so a SyntaxError in one module doesn't kill the
39
- // test runner. The script simply imports the module and exits.
40
- const script = `import(${JSON.stringify('file://' + modulePath)}).then(() => process.exit(0)).catch(e => { process.stderr.write(e.message); process.exit(1); })`;
41
-
42
- try {
43
- execFileSync(process.execPath, ['--input-type=module', '-e', script], {
44
- encoding: 'utf-8',
45
- timeout: 10_000,
46
- stdio: ['pipe', 'pipe', 'pipe'],
47
- });
48
- } catch (err: unknown) {
49
- const e = err as { stderr?: string };
50
- const msg = (e.stderr || '').trim();
51
- expect.fail(
52
- `Module failed to load: ${path.relative(ROOT, modulePath as string)}\n` +
53
- ` Error: ${msg}`,
54
- );
55
- }
56
- },
57
- );
58
-
59
- it('discovered at least 40 modules (sanity check)', () => {
60
- // We currently have ~50 modules; fail if the glob suddenly finds very few,
61
- // which would mean the test isn't actually covering anything.
62
- expect(modules.length).toBeGreaterThanOrEqual(40);
63
- });
64
- });
@@ -1,87 +0,0 @@
1
- import { describe, it, expect, afterEach } from 'vitest';
2
- import { createServer, Server } from 'net';
3
-
4
- /**
5
- * Tests for bin/lib/port.js — isPortInUse.
6
- * Uses real TCP servers to verify port detection accuracy.
7
- */
8
-
9
- // Dynamic import to match ESM module
10
- async function importPort() {
11
- return await import('../../bin/lib/port.js') as {
12
- isPortInUse: (port: number) => Promise<boolean>;
13
- };
14
- }
15
-
16
- let server: Server | null = null;
17
-
18
- afterEach(async () => {
19
- if (server) {
20
- await new Promise<void>((resolve) => {
21
- server!.close(() => resolve());
22
- });
23
- server = null;
24
- }
25
- });
26
-
27
- function startServer(): Promise<number> {
28
- return new Promise((resolve, reject) => {
29
- server = createServer();
30
- server.listen(0, '127.0.0.1', () => {
31
- const addr = server!.address();
32
- if (addr && typeof addr === 'object') {
33
- resolve(addr.port);
34
- } else {
35
- reject(new Error('Could not get server port'));
36
- }
37
- });
38
- server.on('error', reject);
39
- });
40
- }
41
-
42
- describe('isPortInUse', () => {
43
- it('returns false for an unused port', async () => {
44
- const { isPortInUse } = await importPort();
45
- // Use a random high port that's very unlikely to be in use
46
- // First find one by binding and immediately releasing
47
- const tmpServer = createServer();
48
- const port = await new Promise<number>((resolve, reject) => {
49
- tmpServer.listen(0, '127.0.0.1', () => {
50
- const addr = tmpServer.address();
51
- if (addr && typeof addr === 'object') {
52
- const p = addr.port;
53
- tmpServer.close(() => resolve(p));
54
- } else {
55
- reject(new Error('no addr'));
56
- }
57
- });
58
- });
59
- const result = await isPortInUse(port);
60
- expect(result).toBe(false);
61
- });
62
-
63
- it('returns true when a server is listening on the port', async () => {
64
- const port = await startServer();
65
- const { isPortInUse } = await importPort();
66
- const result = await isPortInUse(port);
67
- expect(result).toBe(true);
68
- });
69
-
70
- it('returns false after server is closed', async () => {
71
- const port = await startServer();
72
- const { isPortInUse } = await importPort();
73
-
74
- // Verify it's in use first
75
- expect(await isPortInUse(port)).toBe(true);
76
-
77
- // Close the server
78
- await new Promise<void>((resolve) => {
79
- server!.close(() => resolve());
80
- });
81
- server = null;
82
-
83
- // Now should be free
84
- const result = await isPortInUse(port);
85
- expect(result).toBe(false);
86
- });
87
- });