mstro-app 0.3.0 → 0.3.1

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 (110) hide show
  1. package/bin/mstro.js +65 -2
  2. package/dist/server/cli/headless/claude-invoker.d.ts.map +1 -1
  3. package/dist/server/cli/headless/claude-invoker.js +4 -3
  4. package/dist/server/cli/headless/claude-invoker.js.map +1 -1
  5. package/dist/server/cli/headless/mcp-config.js +2 -2
  6. package/dist/server/cli/headless/mcp-config.js.map +1 -1
  7. package/dist/server/cli/headless/runner.d.ts +6 -1
  8. package/dist/server/cli/headless/runner.d.ts.map +1 -1
  9. package/dist/server/cli/headless/runner.js +36 -4
  10. package/dist/server/cli/headless/runner.js.map +1 -1
  11. package/dist/server/cli/headless/types.d.ts +1 -1
  12. package/dist/server/cli/headless/types.d.ts.map +1 -1
  13. package/dist/server/cli/improvisation-session-manager.d.ts +2 -2
  14. package/dist/server/cli/improvisation-session-manager.d.ts.map +1 -1
  15. package/dist/server/cli/improvisation-session-manager.js +3 -2
  16. package/dist/server/cli/improvisation-session-manager.js.map +1 -1
  17. package/dist/server/index.js +6 -1
  18. package/dist/server/index.js.map +1 -1
  19. package/dist/server/mcp/bouncer-cli.js +53 -14
  20. package/dist/server/mcp/bouncer-cli.js.map +1 -1
  21. package/dist/server/mcp/bouncer-integration.d.ts +1 -1
  22. package/dist/server/mcp/bouncer-integration.d.ts.map +1 -1
  23. package/dist/server/mcp/bouncer-integration.js +70 -7
  24. package/dist/server/mcp/bouncer-integration.js.map +1 -1
  25. package/dist/server/mcp/security-audit.d.ts +3 -3
  26. package/dist/server/mcp/security-audit.d.ts.map +1 -1
  27. package/dist/server/mcp/security-audit.js.map +1 -1
  28. package/dist/server/mcp/server.js +3 -2
  29. package/dist/server/mcp/server.js.map +1 -1
  30. package/dist/server/services/analytics.d.ts +2 -2
  31. package/dist/server/services/analytics.d.ts.map +1 -1
  32. package/dist/server/services/analytics.js.map +1 -1
  33. package/dist/server/services/files.js +7 -7
  34. package/dist/server/services/files.js.map +1 -1
  35. package/dist/server/services/pathUtils.js +1 -1
  36. package/dist/server/services/pathUtils.js.map +1 -1
  37. package/dist/server/services/platform.d.ts +2 -2
  38. package/dist/server/services/platform.d.ts.map +1 -1
  39. package/dist/server/services/platform.js.map +1 -1
  40. package/dist/server/services/sentry.d.ts +1 -1
  41. package/dist/server/services/sentry.d.ts.map +1 -1
  42. package/dist/server/services/sentry.js.map +1 -1
  43. package/dist/server/services/terminal/pty-manager.d.ts +10 -0
  44. package/dist/server/services/terminal/pty-manager.d.ts.map +1 -1
  45. package/dist/server/services/terminal/pty-manager.js +32 -4
  46. package/dist/server/services/terminal/pty-manager.js.map +1 -1
  47. package/dist/server/services/websocket/file-explorer-handlers.js.map +1 -1
  48. package/dist/server/services/websocket/file-utils.d.ts +4 -0
  49. package/dist/server/services/websocket/file-utils.d.ts.map +1 -1
  50. package/dist/server/services/websocket/file-utils.js +27 -8
  51. package/dist/server/services/websocket/file-utils.js.map +1 -1
  52. package/dist/server/services/websocket/git-handlers.js +17 -17
  53. package/dist/server/services/websocket/git-handlers.js.map +1 -1
  54. package/dist/server/services/websocket/git-pr-handlers.js +3 -3
  55. package/dist/server/services/websocket/git-pr-handlers.js.map +1 -1
  56. package/dist/server/services/websocket/git-worktree-handlers.js +10 -10
  57. package/dist/server/services/websocket/git-worktree-handlers.js.map +1 -1
  58. package/dist/server/services/websocket/handler.js +1 -1
  59. package/dist/server/services/websocket/handler.js.map +1 -1
  60. package/dist/server/services/websocket/session-handlers.d.ts +1 -1
  61. package/dist/server/services/websocket/session-handlers.d.ts.map +1 -1
  62. package/dist/server/services/websocket/session-handlers.js +12 -11
  63. package/dist/server/services/websocket/session-handlers.js.map +1 -1
  64. package/dist/server/services/websocket/tab-handlers.js.map +1 -1
  65. package/dist/server/services/websocket/terminal-handlers.js +1 -1
  66. package/dist/server/services/websocket/terminal-handlers.js.map +1 -1
  67. package/dist/server/services/websocket/types.d.ts.map +1 -1
  68. package/dist/server/utils/agent-manager.d.ts +22 -2
  69. package/dist/server/utils/agent-manager.d.ts.map +1 -1
  70. package/dist/server/utils/agent-manager.js +2 -2
  71. package/dist/server/utils/agent-manager.js.map +1 -1
  72. package/dist/server/utils/port-manager.js.map +1 -1
  73. package/hooks/bouncer.sh +17 -3
  74. package/package.json +4 -2
  75. package/server/cli/headless/claude-invoker.ts +21 -16
  76. package/server/cli/headless/mcp-config.ts +8 -8
  77. package/server/cli/headless/runner.ts +32 -4
  78. package/server/cli/headless/types.ts +1 -1
  79. package/server/cli/improvisation-session-manager.ts +8 -7
  80. package/server/index.ts +15 -9
  81. package/server/mcp/bouncer-cli.ts +73 -20
  82. package/server/mcp/bouncer-integration.ts +99 -16
  83. package/server/mcp/security-audit.ts +4 -4
  84. package/server/mcp/server.ts +6 -5
  85. package/server/services/analytics.ts +3 -3
  86. package/server/services/files.ts +13 -13
  87. package/server/services/pathUtils.ts +2 -2
  88. package/server/services/platform.ts +5 -5
  89. package/server/services/sentry.ts +1 -1
  90. package/server/services/terminal/pty-manager.ts +36 -9
  91. package/server/services/websocket/file-explorer-handlers.ts +1 -1
  92. package/server/services/websocket/file-utils.ts +28 -9
  93. package/server/services/websocket/git-handlers.ts +34 -34
  94. package/server/services/websocket/git-pr-handlers.ts +6 -6
  95. package/server/services/websocket/git-worktree-handlers.ts +20 -20
  96. package/server/services/websocket/handler.ts +2 -2
  97. package/server/services/websocket/session-handlers.ts +31 -30
  98. package/server/services/websocket/tab-handlers.ts +1 -1
  99. package/server/services/websocket/terminal-handlers.ts +2 -2
  100. package/server/services/websocket/types.ts +2 -0
  101. package/server/utils/agent-manager.ts +6 -6
  102. package/server/utils/port-manager.ts +1 -1
  103. package/server/cli/headless/output-utils.test.ts +0 -225
  104. package/server/cli/headless/stall-assessor.test.ts +0 -165
  105. package/server/cli/headless/tool-watchdog.test.ts +0 -429
  106. package/server/mcp/bouncer-integration.test.ts +0 -161
  107. package/server/mcp/security-patterns.test.ts +0 -258
  108. package/server/services/platform.test.ts +0 -1304
  109. package/server/services/websocket/autocomplete.test.ts +0 -194
  110. package/server/services/websocket/handler.test.ts +0 -20
@@ -1,194 +0,0 @@
1
- import { describe, expect, it, vi } from 'vitest';
2
- import { AutocompleteService } from './autocomplete.js';
3
-
4
- // Mock file system operations to avoid hitting real FS
5
- vi.mock('node:fs', () => ({
6
- existsSync: vi.fn(() => false),
7
- readdirSync: vi.fn(() => []),
8
- statSync: vi.fn(() => ({ isDirectory: () => false })),
9
- }));
10
-
11
- vi.mock('./file-utils.js', () => ({
12
- CACHE_TTL_MS: 5000,
13
- directoryCache: new Map(),
14
- getFileType: vi.fn((path: string) => {
15
- const ext = path.split('.').pop() || '';
16
- return ext || 'unknown';
17
- }),
18
- isIgnored: vi.fn(() => false),
19
- parseGitignore: vi.fn(() => []),
20
- scanDirectoryRecursiveWithDepth: vi.fn(() => []),
21
- }));
22
-
23
- describe('AutocompleteService', () => {
24
- // ========== Frecency ==========
25
-
26
- describe('calculateFrecencyScore', () => {
27
- it('returns 0 for unknown files', () => {
28
- const svc = new AutocompleteService();
29
- expect(svc.calculateFrecencyScore('nonexistent.ts')).toBe(0);
30
- });
31
-
32
- it('returns positive score for recently used files', () => {
33
- const svc = new AutocompleteService();
34
- svc.recordFileSelection('src/index.ts');
35
- const score = svc.calculateFrecencyScore('src/index.ts');
36
- expect(score).toBeGreaterThan(0);
37
- });
38
-
39
- it('increases score with more selections', () => {
40
- const svc = new AutocompleteService();
41
- svc.recordFileSelection('src/index.ts');
42
- const score1 = svc.calculateFrecencyScore('src/index.ts');
43
-
44
- svc.recordFileSelection('src/index.ts');
45
- svc.recordFileSelection('src/index.ts');
46
- const score3 = svc.calculateFrecencyScore('src/index.ts');
47
-
48
- expect(score3).toBeGreaterThan(score1);
49
- });
50
-
51
- it('decays score over time', () => {
52
- const svc = new AutocompleteService();
53
-
54
- // Record selection at a specific time
55
- const now = Date.now();
56
- vi.spyOn(Date, 'now').mockReturnValue(now);
57
- svc.recordFileSelection('src/index.ts');
58
- const recentScore = svc.calculateFrecencyScore('src/index.ts');
59
-
60
- // Move forward 8 days (past the 7-day recency window)
61
- vi.spyOn(Date, 'now').mockReturnValue(now + 8 * 24 * 60 * 60 * 1000);
62
- const staleScore = svc.calculateFrecencyScore('src/index.ts');
63
-
64
- expect(staleScore).toBeLessThan(recentScore);
65
- vi.restoreAllMocks();
66
- });
67
-
68
- it('handles initial frecency data in constructor', () => {
69
- const svc = new AutocompleteService({
70
- 'src/main.ts': { count: 5, lastUsed: Date.now() },
71
- });
72
- expect(svc.calculateFrecencyScore('src/main.ts')).toBeGreaterThan(0);
73
- });
74
- });
75
-
76
- // ========== recordFileSelection ==========
77
-
78
- describe('recordFileSelection', () => {
79
- it('creates new entry for first selection', () => {
80
- const svc = new AutocompleteService();
81
- svc.recordFileSelection('new-file.ts');
82
-
83
- const data = svc.getFrecencyData();
84
- expect(data['new-file.ts']).toBeDefined();
85
- expect(data['new-file.ts'].count).toBe(1);
86
- });
87
-
88
- it('increments count for existing entry', () => {
89
- const svc = new AutocompleteService();
90
- svc.recordFileSelection('file.ts');
91
- svc.recordFileSelection('file.ts');
92
- svc.recordFileSelection('file.ts');
93
-
94
- const data = svc.getFrecencyData();
95
- expect(data['file.ts'].count).toBe(3);
96
- });
97
-
98
- it('updates lastUsed timestamp', () => {
99
- const svc = new AutocompleteService();
100
- const before = Date.now();
101
- svc.recordFileSelection('file.ts');
102
- const data = svc.getFrecencyData();
103
- expect(data['file.ts'].lastUsed).toBeGreaterThanOrEqual(before);
104
- });
105
- });
106
-
107
- // ========== setFrecencyData / getFrecencyData ==========
108
-
109
- describe('setFrecencyData / getFrecencyData', () => {
110
- it('replaces frecency data', () => {
111
- const svc = new AutocompleteService();
112
- svc.recordFileSelection('old.ts');
113
-
114
- const newData = {
115
- 'new.ts': { count: 10, lastUsed: Date.now() },
116
- };
117
- svc.setFrecencyData(newData);
118
-
119
- expect(svc.getFrecencyData()).toBe(newData);
120
- expect(svc.calculateFrecencyScore('old.ts')).toBe(0);
121
- expect(svc.calculateFrecencyScore('new.ts')).toBeGreaterThan(0);
122
- });
123
- });
124
-
125
- // ========== getFileCompletions ==========
126
-
127
- describe('getFileCompletions', () => {
128
- it('returns empty array when no files match', () => {
129
- const svc = new AutocompleteService();
130
- const results = svc.getFileCompletions('nonexistent', '/tmp/test');
131
- expect(results).toEqual([]);
132
- });
133
-
134
- it('handles @ symbol prefix', () => {
135
- const svc = new AutocompleteService();
136
- // Should not throw when handling @ prefix
137
- const results = svc.getFileCompletions('@src/index', '/tmp/test');
138
- expect(Array.isArray(results)).toBe(true);
139
- });
140
-
141
- it('returns empty array on error', () => {
142
- const svc = new AutocompleteService();
143
- // Invalid working dir should return empty (caught by try/catch)
144
- const results = svc.getFileCompletions('test', '/nonexistent/path');
145
- expect(results).toEqual([]);
146
- });
147
-
148
- it('limits results to 15', () => {
149
- // This is tested structurally — the code slices to 15
150
- const svc = new AutocompleteService();
151
- const results = svc.getFileCompletions('', '/tmp/test');
152
- expect(results.length).toBeLessThanOrEqual(15);
153
- });
154
- });
155
-
156
- // ========== Scoring logic (frecency weight formula) ==========
157
-
158
- describe('frecency scoring formula', () => {
159
- it('uses log2 for frequency weight', () => {
160
- const svc = new AutocompleteService();
161
-
162
- // count=1: log2(2) = 1
163
- svc.setFrecencyData({ 'a.ts': { count: 1, lastUsed: Date.now() } });
164
- const score1 = svc.calculateFrecencyScore('a.ts');
165
-
166
- // count=7: log2(8) = 3
167
- svc.setFrecencyData({ 'a.ts': { count: 7, lastUsed: Date.now() } });
168
- const score7 = svc.calculateFrecencyScore('a.ts');
169
-
170
- // Score should roughly triple (3x) since frequency goes from 1 to 3
171
- expect(score7 / score1).toBeCloseTo(3, 0);
172
- });
173
-
174
- it('recency weight is ~1.0 for very recent files', () => {
175
- const svc = new AutocompleteService();
176
- svc.setFrecencyData({ 'a.ts': { count: 1, lastUsed: Date.now() } });
177
- const score = svc.calculateFrecencyScore('a.ts');
178
-
179
- // With recencyWeight ≈ 1, score ≈ log2(2) * (0.3 + 0.7*1) * 100 = 100
180
- expect(score).toBeCloseTo(100, -1);
181
- });
182
-
183
- it('recency weight is ~0.3 for files used > 7 days ago', () => {
184
- const svc = new AutocompleteService();
185
- const eightDaysAgo = Date.now() - (8 * 24 * 60 * 60 * 1000);
186
- svc.setFrecencyData({ 'a.ts': { count: 1, lastUsed: eightDaysAgo } });
187
- const score = svc.calculateFrecencyScore('a.ts');
188
-
189
- // With recencyWeight = max(0, 1 - 8*24/168) = 0
190
- // score ≈ log2(2) * (0.3 + 0.7*0) * 100 = 30
191
- expect(score).toBeCloseTo(30, -1);
192
- });
193
- });
194
- });
@@ -1,20 +0,0 @@
1
- import { readFileSync } from 'node:fs'
2
- import { join } from 'node:path'
3
- import { describe, expect, it } from 'vitest'
4
-
5
- describe('WebSocket handler code quality', () => {
6
- const handlerSource = readFileSync(
7
- join(import.meta.dirname || __dirname, 'handler.ts'),
8
- 'utf-8'
9
- )
10
-
11
- it('does not use require() — ESM only', () => {
12
- // Ensure no require() calls exist (the bug was require('fs').mkdirSync)
13
- const requireCalls = handlerSource.match(/require\s*\(/g)
14
- expect(requireCalls).toBeNull()
15
- })
16
-
17
- it('imports mkdirSync from fs at the top level', () => {
18
- expect(handlerSource).toContain("import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'")
19
- })
20
- })