mstro-app 0.1.47
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.
- package/LICENSE +21 -0
- package/README.md +177 -0
- package/bin/commands/config.js +145 -0
- package/bin/commands/login.js +313 -0
- package/bin/commands/logout.js +75 -0
- package/bin/commands/status.js +197 -0
- package/bin/commands/whoami.js +161 -0
- package/bin/configure-claude.js +298 -0
- package/bin/mstro.js +581 -0
- package/bin/postinstall.js +45 -0
- package/bin/release.sh +110 -0
- package/dist/server/cli/headless/claude-invoker.d.ts +17 -0
- package/dist/server/cli/headless/claude-invoker.d.ts.map +1 -0
- package/dist/server/cli/headless/claude-invoker.js +311 -0
- package/dist/server/cli/headless/claude-invoker.js.map +1 -0
- package/dist/server/cli/headless/index.d.ts +13 -0
- package/dist/server/cli/headless/index.d.ts.map +1 -0
- package/dist/server/cli/headless/index.js +10 -0
- package/dist/server/cli/headless/index.js.map +1 -0
- package/dist/server/cli/headless/mcp-config.d.ts +11 -0
- package/dist/server/cli/headless/mcp-config.d.ts.map +1 -0
- package/dist/server/cli/headless/mcp-config.js +76 -0
- package/dist/server/cli/headless/mcp-config.js.map +1 -0
- package/dist/server/cli/headless/output-utils.d.ts +33 -0
- package/dist/server/cli/headless/output-utils.d.ts.map +1 -0
- package/dist/server/cli/headless/output-utils.js +101 -0
- package/dist/server/cli/headless/output-utils.js.map +1 -0
- package/dist/server/cli/headless/prompt-utils.d.ts +21 -0
- package/dist/server/cli/headless/prompt-utils.d.ts.map +1 -0
- package/dist/server/cli/headless/prompt-utils.js +84 -0
- package/dist/server/cli/headless/prompt-utils.js.map +1 -0
- package/dist/server/cli/headless/runner.d.ts +24 -0
- package/dist/server/cli/headless/runner.d.ts.map +1 -0
- package/dist/server/cli/headless/runner.js +99 -0
- package/dist/server/cli/headless/runner.js.map +1 -0
- package/dist/server/cli/headless/types.d.ts +106 -0
- package/dist/server/cli/headless/types.d.ts.map +1 -0
- package/dist/server/cli/headless/types.js +4 -0
- package/dist/server/cli/headless/types.js.map +1 -0
- package/dist/server/cli/improvisation-session-manager.d.ts +155 -0
- package/dist/server/cli/improvisation-session-manager.d.ts.map +1 -0
- package/dist/server/cli/improvisation-session-manager.js +415 -0
- package/dist/server/cli/improvisation-session-manager.js.map +1 -0
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +386 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/mcp/bouncer-cli.d.ts +3 -0
- package/dist/server/mcp/bouncer-cli.d.ts.map +1 -0
- package/dist/server/mcp/bouncer-cli.js +99 -0
- package/dist/server/mcp/bouncer-cli.js.map +1 -0
- package/dist/server/mcp/bouncer-integration.d.ts +36 -0
- package/dist/server/mcp/bouncer-integration.d.ts.map +1 -0
- package/dist/server/mcp/bouncer-integration.js +301 -0
- package/dist/server/mcp/bouncer-integration.js.map +1 -0
- package/dist/server/mcp/security-audit.d.ts +52 -0
- package/dist/server/mcp/security-audit.d.ts.map +1 -0
- package/dist/server/mcp/security-audit.js +118 -0
- package/dist/server/mcp/security-audit.js.map +1 -0
- package/dist/server/mcp/security-patterns.d.ts +73 -0
- package/dist/server/mcp/security-patterns.d.ts.map +1 -0
- package/dist/server/mcp/security-patterns.js +247 -0
- package/dist/server/mcp/security-patterns.js.map +1 -0
- package/dist/server/mcp/server.d.ts +3 -0
- package/dist/server/mcp/server.d.ts.map +1 -0
- package/dist/server/mcp/server.js +146 -0
- package/dist/server/mcp/server.js.map +1 -0
- package/dist/server/routes/files.d.ts +9 -0
- package/dist/server/routes/files.d.ts.map +1 -0
- package/dist/server/routes/files.js +24 -0
- package/dist/server/routes/files.js.map +1 -0
- package/dist/server/routes/improvise.d.ts +3 -0
- package/dist/server/routes/improvise.d.ts.map +1 -0
- package/dist/server/routes/improvise.js +72 -0
- package/dist/server/routes/improvise.js.map +1 -0
- package/dist/server/routes/index.d.ts +10 -0
- package/dist/server/routes/index.d.ts.map +1 -0
- package/dist/server/routes/index.js +12 -0
- package/dist/server/routes/index.js.map +1 -0
- package/dist/server/routes/instances.d.ts +10 -0
- package/dist/server/routes/instances.d.ts.map +1 -0
- package/dist/server/routes/instances.js +47 -0
- package/dist/server/routes/instances.js.map +1 -0
- package/dist/server/routes/notifications.d.ts +3 -0
- package/dist/server/routes/notifications.d.ts.map +1 -0
- package/dist/server/routes/notifications.js +136 -0
- package/dist/server/routes/notifications.js.map +1 -0
- package/dist/server/services/analytics.d.ts +56 -0
- package/dist/server/services/analytics.d.ts.map +1 -0
- package/dist/server/services/analytics.js +240 -0
- package/dist/server/services/analytics.js.map +1 -0
- package/dist/server/services/auth.d.ts +26 -0
- package/dist/server/services/auth.d.ts.map +1 -0
- package/dist/server/services/auth.js +71 -0
- package/dist/server/services/auth.js.map +1 -0
- package/dist/server/services/client-id.d.ts +10 -0
- package/dist/server/services/client-id.d.ts.map +1 -0
- package/dist/server/services/client-id.js +61 -0
- package/dist/server/services/client-id.js.map +1 -0
- package/dist/server/services/credentials.d.ts +39 -0
- package/dist/server/services/credentials.d.ts.map +1 -0
- package/dist/server/services/credentials.js +110 -0
- package/dist/server/services/credentials.js.map +1 -0
- package/dist/server/services/files.d.ts +119 -0
- package/dist/server/services/files.d.ts.map +1 -0
- package/dist/server/services/files.js +560 -0
- package/dist/server/services/files.js.map +1 -0
- package/dist/server/services/instances.d.ts +52 -0
- package/dist/server/services/instances.d.ts.map +1 -0
- package/dist/server/services/instances.js +241 -0
- package/dist/server/services/instances.js.map +1 -0
- package/dist/server/services/pathUtils.d.ts +47 -0
- package/dist/server/services/pathUtils.d.ts.map +1 -0
- package/dist/server/services/pathUtils.js +124 -0
- package/dist/server/services/pathUtils.js.map +1 -0
- package/dist/server/services/platform.d.ts +72 -0
- package/dist/server/services/platform.d.ts.map +1 -0
- package/dist/server/services/platform.js +368 -0
- package/dist/server/services/platform.js.map +1 -0
- package/dist/server/services/sentry.d.ts +5 -0
- package/dist/server/services/sentry.d.ts.map +1 -0
- package/dist/server/services/sentry.js +71 -0
- package/dist/server/services/sentry.js.map +1 -0
- package/dist/server/services/terminal/pty-manager.d.ts +149 -0
- package/dist/server/services/terminal/pty-manager.d.ts.map +1 -0
- package/dist/server/services/terminal/pty-manager.js +377 -0
- package/dist/server/services/terminal/pty-manager.js.map +1 -0
- package/dist/server/services/terminal/tmux-manager.d.ts +82 -0
- package/dist/server/services/terminal/tmux-manager.d.ts.map +1 -0
- package/dist/server/services/terminal/tmux-manager.js +352 -0
- package/dist/server/services/terminal/tmux-manager.js.map +1 -0
- package/dist/server/services/websocket/autocomplete.d.ts +50 -0
- package/dist/server/services/websocket/autocomplete.d.ts.map +1 -0
- package/dist/server/services/websocket/autocomplete.js +361 -0
- package/dist/server/services/websocket/autocomplete.js.map +1 -0
- package/dist/server/services/websocket/file-utils.d.ts +44 -0
- package/dist/server/services/websocket/file-utils.d.ts.map +1 -0
- package/dist/server/services/websocket/file-utils.js +272 -0
- package/dist/server/services/websocket/file-utils.js.map +1 -0
- package/dist/server/services/websocket/handler.d.ts +246 -0
- package/dist/server/services/websocket/handler.d.ts.map +1 -0
- package/dist/server/services/websocket/handler.js +1771 -0
- package/dist/server/services/websocket/handler.js.map +1 -0
- package/dist/server/services/websocket/index.d.ts +11 -0
- package/dist/server/services/websocket/index.d.ts.map +1 -0
- package/dist/server/services/websocket/index.js +14 -0
- package/dist/server/services/websocket/index.js.map +1 -0
- package/dist/server/services/websocket/types.d.ts +214 -0
- package/dist/server/services/websocket/types.d.ts.map +1 -0
- package/dist/server/services/websocket/types.js +4 -0
- package/dist/server/services/websocket/types.js.map +1 -0
- package/dist/server/utils/agent-manager.d.ts +69 -0
- package/dist/server/utils/agent-manager.d.ts.map +1 -0
- package/dist/server/utils/agent-manager.js +269 -0
- package/dist/server/utils/agent-manager.js.map +1 -0
- package/dist/server/utils/paths.d.ts +25 -0
- package/dist/server/utils/paths.d.ts.map +1 -0
- package/dist/server/utils/paths.js +38 -0
- package/dist/server/utils/paths.js.map +1 -0
- package/dist/server/utils/port-manager.d.ts +10 -0
- package/dist/server/utils/port-manager.d.ts.map +1 -0
- package/dist/server/utils/port-manager.js +60 -0
- package/dist/server/utils/port-manager.js.map +1 -0
- package/dist/server/utils/port.d.ts +26 -0
- package/dist/server/utils/port.d.ts.map +1 -0
- package/dist/server/utils/port.js +83 -0
- package/dist/server/utils/port.js.map +1 -0
- package/hooks/bouncer.sh +138 -0
- package/package.json +74 -0
- package/server/README.md +191 -0
- package/server/cli/headless/claude-invoker.ts +415 -0
- package/server/cli/headless/index.ts +39 -0
- package/server/cli/headless/mcp-config.ts +87 -0
- package/server/cli/headless/output-utils.ts +109 -0
- package/server/cli/headless/prompt-utils.ts +108 -0
- package/server/cli/headless/runner.ts +133 -0
- package/server/cli/headless/types.ts +118 -0
- package/server/cli/improvisation-session-manager.ts +531 -0
- package/server/index.ts +456 -0
- package/server/mcp/README.md +122 -0
- package/server/mcp/bouncer-cli.ts +127 -0
- package/server/mcp/bouncer-integration.ts +430 -0
- package/server/mcp/security-audit.ts +180 -0
- package/server/mcp/security-patterns.ts +290 -0
- package/server/mcp/server.ts +174 -0
- package/server/routes/files.ts +29 -0
- package/server/routes/improvise.ts +82 -0
- package/server/routes/index.ts +13 -0
- package/server/routes/instances.ts +54 -0
- package/server/routes/notifications.ts +158 -0
- package/server/services/analytics.ts +277 -0
- package/server/services/auth.ts +80 -0
- package/server/services/client-id.ts +68 -0
- package/server/services/credentials.ts +134 -0
- package/server/services/files.ts +710 -0
- package/server/services/instances.ts +275 -0
- package/server/services/pathUtils.ts +158 -0
- package/server/services/platform.test.ts +1314 -0
- package/server/services/platform.ts +435 -0
- package/server/services/sentry.ts +81 -0
- package/server/services/terminal/pty-manager.ts +464 -0
- package/server/services/terminal/tmux-manager.ts +426 -0
- package/server/services/websocket/autocomplete.ts +438 -0
- package/server/services/websocket/file-utils.ts +305 -0
- package/server/services/websocket/handler.test.ts +20 -0
- package/server/services/websocket/handler.ts +2047 -0
- package/server/services/websocket/index.ts +40 -0
- package/server/services/websocket/types.ts +339 -0
- package/server/tsconfig.json +19 -0
- package/server/utils/agent-manager.ts +323 -0
- package/server/utils/paths.ts +45 -0
- package/server/utils/port-manager.ts +70 -0
- package/server/utils/port.ts +102 -0
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
// Copyright (c) 2025-present Mstro, Inc. All rights reserved.
|
|
2
|
+
// Licensed under the MIT License. See LICENSE file for details.
|
|
3
|
+
/**
|
|
4
|
+
* Instance Registry Service
|
|
5
|
+
*
|
|
6
|
+
* Manages multiple Mstro server instances
|
|
7
|
+
*/
|
|
8
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
9
|
+
import { homedir } from 'node:os';
|
|
10
|
+
import { join } from 'node:path';
|
|
11
|
+
function clearStaleLock(lockPath) {
|
|
12
|
+
if (!existsSync(lockPath))
|
|
13
|
+
return;
|
|
14
|
+
try {
|
|
15
|
+
const lockTime = parseInt(readFileSync(lockPath, 'utf-8'), 10);
|
|
16
|
+
if (Date.now() - lockTime > 10000) {
|
|
17
|
+
try {
|
|
18
|
+
unlinkSync(lockPath);
|
|
19
|
+
}
|
|
20
|
+
catch { }
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
catch { }
|
|
24
|
+
}
|
|
25
|
+
function tryCreateLock(lockPath) {
|
|
26
|
+
try {
|
|
27
|
+
writeFileSync(lockPath, Date.now().toString(), { flag: 'wx' });
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function busyWait() {
|
|
35
|
+
const endTime = Date.now() + Math.random() * 50 + 10;
|
|
36
|
+
while (Date.now() < endTime) { /* busy wait */ }
|
|
37
|
+
}
|
|
38
|
+
function acquireLock(lockPath, timeout = 5000) {
|
|
39
|
+
const start = Date.now();
|
|
40
|
+
while (Date.now() - start < timeout) {
|
|
41
|
+
clearStaleLock(lockPath);
|
|
42
|
+
if (tryCreateLock(lockPath))
|
|
43
|
+
return true;
|
|
44
|
+
busyWait();
|
|
45
|
+
}
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
function releaseLock(lockPath) {
|
|
49
|
+
try {
|
|
50
|
+
unlinkSync(lockPath);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// Ignore errors when releasing lock
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export class InstanceRegistry {
|
|
57
|
+
registryPath;
|
|
58
|
+
currentInstance = null;
|
|
59
|
+
heartbeatInterval = null;
|
|
60
|
+
constructor() {
|
|
61
|
+
const mstroDir = join(homedir(), '.mstro');
|
|
62
|
+
if (!existsSync(mstroDir)) {
|
|
63
|
+
mkdirSync(mstroDir, { recursive: true, mode: 0o700 });
|
|
64
|
+
}
|
|
65
|
+
this.registryPath = join(mstroDir, 'instances.json');
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Register current instance
|
|
69
|
+
*/
|
|
70
|
+
register(port, workingDirectory) {
|
|
71
|
+
const instance = {
|
|
72
|
+
id: `mstro-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
73
|
+
port,
|
|
74
|
+
url: `http://localhost:${port}`,
|
|
75
|
+
workingDirectory,
|
|
76
|
+
startedAt: Date.now(),
|
|
77
|
+
lastHeartbeat: Date.now(),
|
|
78
|
+
pid: process.pid
|
|
79
|
+
};
|
|
80
|
+
this.currentInstance = instance;
|
|
81
|
+
this.saveInstance(instance);
|
|
82
|
+
this.startHeartbeat();
|
|
83
|
+
return instance;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Unregister current instance
|
|
87
|
+
*/
|
|
88
|
+
unregister() {
|
|
89
|
+
if (this.currentInstance) {
|
|
90
|
+
this.removeInstance(this.currentInstance.id);
|
|
91
|
+
this.currentInstance = null;
|
|
92
|
+
}
|
|
93
|
+
this.stopHeartbeat();
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Get current instance info
|
|
97
|
+
*/
|
|
98
|
+
getCurrentInstance() {
|
|
99
|
+
return this.currentInstance;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Get all instances (with file locking to prevent race conditions)
|
|
103
|
+
*/
|
|
104
|
+
static getAllInstances() {
|
|
105
|
+
const mstroDir = join(homedir(), '.mstro');
|
|
106
|
+
const registryPath = join(mstroDir, 'instances.json');
|
|
107
|
+
const lockPath = join(mstroDir, 'instances.lock');
|
|
108
|
+
if (!existsSync(registryPath)) {
|
|
109
|
+
return [];
|
|
110
|
+
}
|
|
111
|
+
const locked = acquireLock(lockPath, 3000);
|
|
112
|
+
try {
|
|
113
|
+
const data = readFileSync(registryPath, 'utf-8');
|
|
114
|
+
// Handle empty or whitespace-only content
|
|
115
|
+
if (!data || !data.trim()) {
|
|
116
|
+
return [];
|
|
117
|
+
}
|
|
118
|
+
const parsed = JSON.parse(data);
|
|
119
|
+
// Ensure we have an array
|
|
120
|
+
const instances = Array.isArray(parsed) ? parsed : [];
|
|
121
|
+
// Filter out stale instances (no heartbeat in last 2 minutes)
|
|
122
|
+
const now = Date.now();
|
|
123
|
+
const maxAge = 2 * 60 * 1000; // 2 minutes
|
|
124
|
+
return instances.filter(instance => now - instance.lastHeartbeat < maxAge);
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
// If JSON is corrupted, log but don't spam - return empty and let next write fix it
|
|
128
|
+
if (error instanceof SyntaxError) {
|
|
129
|
+
console.warn('[InstanceRegistry] Registry file corrupted, will be recreated on next write');
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
console.error('[InstanceRegistry] Failed to read instances registry:', error);
|
|
133
|
+
}
|
|
134
|
+
return [];
|
|
135
|
+
}
|
|
136
|
+
finally {
|
|
137
|
+
if (locked) {
|
|
138
|
+
releaseLock(lockPath);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Get instance by ID
|
|
144
|
+
*/
|
|
145
|
+
static getInstance(id) {
|
|
146
|
+
const instances = InstanceRegistry.getAllInstances();
|
|
147
|
+
return instances.find(i => i.id === id) || null;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Save instance to registry (with file locking)
|
|
151
|
+
*/
|
|
152
|
+
saveInstance(instance) {
|
|
153
|
+
const lockPath = join(homedir(), '.mstro', 'instances.lock');
|
|
154
|
+
const locked = acquireLock(lockPath, 5000);
|
|
155
|
+
try {
|
|
156
|
+
// Read current instances directly (without calling getAllInstances to avoid double-locking)
|
|
157
|
+
let instances = [];
|
|
158
|
+
if (existsSync(this.registryPath)) {
|
|
159
|
+
try {
|
|
160
|
+
const data = readFileSync(this.registryPath, 'utf-8');
|
|
161
|
+
if (data?.trim()) {
|
|
162
|
+
const parsed = JSON.parse(data);
|
|
163
|
+
instances = Array.isArray(parsed) ? parsed : [];
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
// If file is corrupted, start fresh
|
|
168
|
+
instances = [];
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// Filter out stale instances while we're at it
|
|
172
|
+
const now = Date.now();
|
|
173
|
+
const maxAge = 2 * 60 * 1000;
|
|
174
|
+
instances = instances.filter(i => i.id !== instance.id && now - i.lastHeartbeat < maxAge);
|
|
175
|
+
// Add new/updated instance
|
|
176
|
+
instances.push(instance);
|
|
177
|
+
// Write atomically by writing to temp file first then renaming
|
|
178
|
+
const tempPath = `${this.registryPath}.tmp`;
|
|
179
|
+
writeFileSync(tempPath, JSON.stringify(instances, null, 2), 'utf-8');
|
|
180
|
+
// Rename is atomic on most filesystems
|
|
181
|
+
renameSync(tempPath, this.registryPath);
|
|
182
|
+
}
|
|
183
|
+
finally {
|
|
184
|
+
if (locked) {
|
|
185
|
+
releaseLock(lockPath);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Remove instance from registry (with file locking)
|
|
191
|
+
*/
|
|
192
|
+
removeInstance(id) {
|
|
193
|
+
const lockPath = join(homedir(), '.mstro', 'instances.lock');
|
|
194
|
+
const locked = acquireLock(lockPath, 5000);
|
|
195
|
+
try {
|
|
196
|
+
let instances = [];
|
|
197
|
+
if (existsSync(this.registryPath)) {
|
|
198
|
+
try {
|
|
199
|
+
const data = readFileSync(this.registryPath, 'utf-8');
|
|
200
|
+
if (data?.trim()) {
|
|
201
|
+
const parsed = JSON.parse(data);
|
|
202
|
+
instances = Array.isArray(parsed) ? parsed : [];
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
instances = [];
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
instances = instances.filter(i => i.id !== id);
|
|
210
|
+
const tempPath = `${this.registryPath}.tmp`;
|
|
211
|
+
writeFileSync(tempPath, JSON.stringify(instances, null, 2), 'utf-8');
|
|
212
|
+
renameSync(tempPath, this.registryPath);
|
|
213
|
+
}
|
|
214
|
+
finally {
|
|
215
|
+
if (locked) {
|
|
216
|
+
releaseLock(lockPath);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Start heartbeat to keep instance alive
|
|
222
|
+
*/
|
|
223
|
+
startHeartbeat() {
|
|
224
|
+
this.heartbeatInterval = setInterval(() => {
|
|
225
|
+
if (this.currentInstance) {
|
|
226
|
+
this.currentInstance.lastHeartbeat = Date.now();
|
|
227
|
+
this.saveInstance(this.currentInstance);
|
|
228
|
+
}
|
|
229
|
+
}, 30000); // Every 30 seconds
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Stop heartbeat
|
|
233
|
+
*/
|
|
234
|
+
stopHeartbeat() {
|
|
235
|
+
if (this.heartbeatInterval) {
|
|
236
|
+
clearInterval(this.heartbeatInterval);
|
|
237
|
+
this.heartbeatInterval = null;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
//# sourceMappingURL=instances.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instances.js","sourceRoot":"","sources":["../../../server/services/instances.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export interface PathValidationResult {
|
|
2
|
+
valid: boolean;
|
|
3
|
+
resolvedPath: string;
|
|
4
|
+
error?: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Validate that a path is within the allowed working directory.
|
|
8
|
+
* Prevents path traversal attacks using .. or absolute paths.
|
|
9
|
+
*
|
|
10
|
+
* @param targetPath - The path to validate (relative or absolute)
|
|
11
|
+
* @param workingDir - The allowed working directory boundary
|
|
12
|
+
* @returns PathValidationResult with validation status and resolved path
|
|
13
|
+
*/
|
|
14
|
+
export declare function validatePathWithinWorkingDir(targetPath: string, workingDir: string): PathValidationResult;
|
|
15
|
+
/**
|
|
16
|
+
* Validate both source and destination paths for rename/move operations.
|
|
17
|
+
* Both paths must be within the working directory.
|
|
18
|
+
*
|
|
19
|
+
* @param sourcePath - The source path
|
|
20
|
+
* @param destPath - The destination path
|
|
21
|
+
* @param workingDir - The allowed working directory boundary
|
|
22
|
+
* @returns Object with validation results for both paths
|
|
23
|
+
*/
|
|
24
|
+
export declare function validateBothPathsWithinWorkingDir(sourcePath: string, destPath: string, workingDir: string): {
|
|
25
|
+
valid: boolean;
|
|
26
|
+
resolvedSourcePath: string;
|
|
27
|
+
resolvedDestPath: string;
|
|
28
|
+
error?: string;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Get the relative path from working directory.
|
|
32
|
+
* Useful for returning user-friendly paths in responses.
|
|
33
|
+
*
|
|
34
|
+
* @param absolutePath - The absolute path
|
|
35
|
+
* @param workingDir - The working directory
|
|
36
|
+
* @returns Relative path from working directory
|
|
37
|
+
*/
|
|
38
|
+
export declare function getRelativePath(absolutePath: string, workingDir: string): string;
|
|
39
|
+
/**
|
|
40
|
+
* Check if a path contains dangerous patterns that should be blocked.
|
|
41
|
+
* This is an additional layer of defense beyond path validation.
|
|
42
|
+
*
|
|
43
|
+
* @param path - The path to check
|
|
44
|
+
* @returns true if path contains dangerous patterns
|
|
45
|
+
*/
|
|
46
|
+
export declare function containsDangerousPatterns(path: string): boolean;
|
|
47
|
+
//# sourceMappingURL=pathUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pathUtils.d.ts","sourceRoot":"","sources":["../../../server/services/pathUtils.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,wBAAgB,4BAA4B,CAC1C,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,oBAAoB,CAoDtB;AAED;;;;;;;;GAQG;AACH,wBAAgB,iCAAiC,CAC/C,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB;IACD,KAAK,EAAE,OAAO,CAAC;IACf,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CA0BA;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAEhF;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAS/D"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// Copyright (c) 2025-present Mstro, Inc. All rights reserved.
|
|
2
|
+
// Licensed under the MIT License. See LICENSE file for details.
|
|
3
|
+
/**
|
|
4
|
+
* Path Utilities
|
|
5
|
+
*
|
|
6
|
+
* Secure path validation utilities to prevent path traversal attacks.
|
|
7
|
+
* All file explorer operations MUST validate paths through these functions.
|
|
8
|
+
*/
|
|
9
|
+
import { isAbsolute, normalize, relative, resolve } from 'node:path';
|
|
10
|
+
/**
|
|
11
|
+
* Validate that a path is within the allowed working directory.
|
|
12
|
+
* Prevents path traversal attacks using .. or absolute paths.
|
|
13
|
+
*
|
|
14
|
+
* @param targetPath - The path to validate (relative or absolute)
|
|
15
|
+
* @param workingDir - The allowed working directory boundary
|
|
16
|
+
* @returns PathValidationResult with validation status and resolved path
|
|
17
|
+
*/
|
|
18
|
+
export function validatePathWithinWorkingDir(targetPath, workingDir) {
|
|
19
|
+
try {
|
|
20
|
+
// Normalize the working directory to get canonical path
|
|
21
|
+
const normalizedWorkingDir = resolve(workingDir);
|
|
22
|
+
// Resolve the target path relative to working directory
|
|
23
|
+
let resolvedPath;
|
|
24
|
+
if (isAbsolute(targetPath)) {
|
|
25
|
+
resolvedPath = resolve(targetPath);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
resolvedPath = resolve(normalizedWorkingDir, targetPath);
|
|
29
|
+
}
|
|
30
|
+
// Normalize to remove any .. or . segments
|
|
31
|
+
resolvedPath = normalize(resolvedPath);
|
|
32
|
+
// Check if the resolved path starts with the working directory
|
|
33
|
+
// Add trailing separator to prevent partial matches (e.g., /home/user vs /home/username)
|
|
34
|
+
const workingDirWithSep = normalizedWorkingDir.endsWith('/')
|
|
35
|
+
? normalizedWorkingDir
|
|
36
|
+
: `${normalizedWorkingDir}/`;
|
|
37
|
+
const isWithinWorkingDir = resolvedPath === normalizedWorkingDir ||
|
|
38
|
+
resolvedPath.startsWith(workingDirWithSep);
|
|
39
|
+
if (!isWithinWorkingDir) {
|
|
40
|
+
// Log security violation for monitoring
|
|
41
|
+
console.error(`[PathUtils] SECURITY: Path traversal attempt blocked. ` +
|
|
42
|
+
`Target: "${targetPath}", Resolved: "${resolvedPath}", WorkingDir: "${normalizedWorkingDir}"`);
|
|
43
|
+
return {
|
|
44
|
+
valid: false,
|
|
45
|
+
resolvedPath: '',
|
|
46
|
+
error: 'Access denied: path is outside working directory'
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
valid: true,
|
|
51
|
+
resolvedPath
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
console.error('[PathUtils] Error validating path:', error);
|
|
56
|
+
return {
|
|
57
|
+
valid: false,
|
|
58
|
+
resolvedPath: '',
|
|
59
|
+
error: `Invalid path: ${error.message}`
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Validate both source and destination paths for rename/move operations.
|
|
65
|
+
* Both paths must be within the working directory.
|
|
66
|
+
*
|
|
67
|
+
* @param sourcePath - The source path
|
|
68
|
+
* @param destPath - The destination path
|
|
69
|
+
* @param workingDir - The allowed working directory boundary
|
|
70
|
+
* @returns Object with validation results for both paths
|
|
71
|
+
*/
|
|
72
|
+
export function validateBothPathsWithinWorkingDir(sourcePath, destPath, workingDir) {
|
|
73
|
+
const sourceValidation = validatePathWithinWorkingDir(sourcePath, workingDir);
|
|
74
|
+
if (!sourceValidation.valid) {
|
|
75
|
+
return {
|
|
76
|
+
valid: false,
|
|
77
|
+
resolvedSourcePath: '',
|
|
78
|
+
resolvedDestPath: '',
|
|
79
|
+
error: `Source path error: ${sourceValidation.error}`
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
const destValidation = validatePathWithinWorkingDir(destPath, workingDir);
|
|
83
|
+
if (!destValidation.valid) {
|
|
84
|
+
return {
|
|
85
|
+
valid: false,
|
|
86
|
+
resolvedSourcePath: '',
|
|
87
|
+
resolvedDestPath: '',
|
|
88
|
+
error: `Destination path error: ${destValidation.error}`
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
valid: true,
|
|
93
|
+
resolvedSourcePath: sourceValidation.resolvedPath,
|
|
94
|
+
resolvedDestPath: destValidation.resolvedPath
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Get the relative path from working directory.
|
|
99
|
+
* Useful for returning user-friendly paths in responses.
|
|
100
|
+
*
|
|
101
|
+
* @param absolutePath - The absolute path
|
|
102
|
+
* @param workingDir - The working directory
|
|
103
|
+
* @returns Relative path from working directory
|
|
104
|
+
*/
|
|
105
|
+
export function getRelativePath(absolutePath, workingDir) {
|
|
106
|
+
return relative(resolve(workingDir), absolutePath);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Check if a path contains dangerous patterns that should be blocked.
|
|
110
|
+
* This is an additional layer of defense beyond path validation.
|
|
111
|
+
*
|
|
112
|
+
* @param path - The path to check
|
|
113
|
+
* @returns true if path contains dangerous patterns
|
|
114
|
+
*/
|
|
115
|
+
export function containsDangerousPatterns(path) {
|
|
116
|
+
const dangerousPatterns = [
|
|
117
|
+
/\0/, // Null bytes
|
|
118
|
+
/^~/, // Home directory expansion (should use absolute paths)
|
|
119
|
+
/\$\{/, // Variable expansion
|
|
120
|
+
/\$\(/, // Command substitution
|
|
121
|
+
];
|
|
122
|
+
return dangerousPatterns.some(pattern => pattern.test(path));
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=pathUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pathUtils.js","sourceRoot":"","sources":["../../../server/services/pathUtils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get machine identification string
|
|
3
|
+
* Format: "hostname @ node-vX.X.X platform (arch)"
|
|
4
|
+
* Example: "Jessica @ node-v22.21.1 linux (arm64)"
|
|
5
|
+
*/
|
|
6
|
+
export declare function getMachineIdentifier(): string;
|
|
7
|
+
interface ConnectionCallbacks {
|
|
8
|
+
onConnected?: (connectionId: string) => void;
|
|
9
|
+
onDisconnected?: () => void;
|
|
10
|
+
onError?: (error: string) => void;
|
|
11
|
+
onWebConnected?: () => void;
|
|
12
|
+
onWebDisconnected?: () => void;
|
|
13
|
+
onRelayedMessage?: (message: any) => void;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Platform WebSocket connection with token-based authentication
|
|
17
|
+
*/
|
|
18
|
+
export declare class PlatformConnection {
|
|
19
|
+
private ws;
|
|
20
|
+
private reconnectTimeout;
|
|
21
|
+
private reconnectAttempts;
|
|
22
|
+
private maxReconnectAttempts;
|
|
23
|
+
private isIntentionallyClosed;
|
|
24
|
+
private workingDirectory;
|
|
25
|
+
private platformUrl;
|
|
26
|
+
private callbacks;
|
|
27
|
+
private connectionId;
|
|
28
|
+
private isConnected;
|
|
29
|
+
private tokenRefreshInterval;
|
|
30
|
+
private heartbeatInterval;
|
|
31
|
+
constructor(workingDirectory: string, callbacks?: ConnectionCallbacks, platformUrl?: string);
|
|
32
|
+
/**
|
|
33
|
+
* Refresh the device token if needed
|
|
34
|
+
*/
|
|
35
|
+
private maybeRefreshToken;
|
|
36
|
+
/**
|
|
37
|
+
* Start periodic token refresh check
|
|
38
|
+
*/
|
|
39
|
+
private startTokenRefreshCheck;
|
|
40
|
+
/**
|
|
41
|
+
* Start heartbeat to keep connection alive and refresh server-side TTL
|
|
42
|
+
*/
|
|
43
|
+
private startHeartbeat;
|
|
44
|
+
/**
|
|
45
|
+
* Stop heartbeat
|
|
46
|
+
*/
|
|
47
|
+
private stopHeartbeat;
|
|
48
|
+
/**
|
|
49
|
+
* Stop periodic token refresh check
|
|
50
|
+
*/
|
|
51
|
+
private stopTokenRefreshCheck;
|
|
52
|
+
/**
|
|
53
|
+
* Connect to platform WebSocket
|
|
54
|
+
*/
|
|
55
|
+
connect(): void;
|
|
56
|
+
private handleMessage;
|
|
57
|
+
private scheduleReconnect;
|
|
58
|
+
/**
|
|
59
|
+
* Send message to platform (will be relayed to web if connected)
|
|
60
|
+
*/
|
|
61
|
+
send(message: any): void;
|
|
62
|
+
/**
|
|
63
|
+
* Check if connected to platform
|
|
64
|
+
*/
|
|
65
|
+
isConnectedToPlatform(): boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Disconnect from platform
|
|
68
|
+
*/
|
|
69
|
+
disconnect(): void;
|
|
70
|
+
}
|
|
71
|
+
export {};
|
|
72
|
+
//# sourceMappingURL=platform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../../../server/services/platform.ts"],"names":[],"mappings":"AAkFA;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAM7C;AAeD,UAAU,mBAAmB;IAC3B,WAAW,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5C,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;IAC3B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;IAC3B,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAA;IAC9B,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,IAAI,CAAA;CAC1C;AAED;;GAEG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,EAAE,CAAyB;IACnC,OAAO,CAAC,gBAAgB,CAA6C;IACrE,OAAO,CAAC,iBAAiB,CAAI;IAC7B,OAAO,CAAC,oBAAoB,CAAK;IACjC,OAAO,CAAC,qBAAqB,CAAQ;IACrC,OAAO,CAAC,gBAAgB,CAAQ;IAChC,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,YAAY,CAAsB;IAC1C,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,oBAAoB,CAA8C;IAC1E,OAAO,CAAC,iBAAiB,CAA8C;gBAGrE,gBAAgB,EAAE,MAAM,EACxB,SAAS,GAAE,mBAAwB,EACnC,WAAW,CAAC,EAAE,MAAM;IAOtB;;OAEG;YACW,iBAAiB;IA6B/B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAO9B;;OAEG;IACH,OAAO,CAAC,cAAc;IAatB;;OAEG;IACH,OAAO,CAAC,aAAa;IAOrB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAO7B;;OAEG;IACH,OAAO,IAAI,IAAI;IAwHf,OAAO,CAAC,aAAa;IAiCrB,OAAO,CAAC,iBAAiB;IAiBzB;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI;IAMxB;;OAEG;IACH,qBAAqB,IAAI,OAAO;IAIhC;;OAEG;IACH,UAAU,IAAI,IAAI;CAoBnB"}
|