mstro-app 0.4.39 → 0.4.43
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/bin/commands/login.js +17 -7
- package/bin/commands/logout.js +14 -6
- package/bin/commands/status.js +9 -3
- package/bin/commands/whoami.js +10 -4
- package/bin/mstro.js +11 -1
- package/dist/server/cli/headless/claude-invoker-stream.d.ts.map +1 -1
- package/dist/server/cli/headless/claude-invoker-stream.js +1 -0
- package/dist/server/cli/headless/claude-invoker-stream.js.map +1 -1
- package/dist/server/cli/headless/index.d.ts +1 -0
- package/dist/server/cli/headless/index.d.ts.map +1 -1
- package/dist/server/cli/headless/index.js +2 -0
- package/dist/server/cli/headless/index.js.map +1 -1
- package/dist/server/cli/headless/resilient-runner.d.ts +47 -0
- package/dist/server/cli/headless/resilient-runner.d.ts.map +1 -0
- package/dist/server/cli/headless/resilient-runner.js +234 -0
- package/dist/server/cli/headless/resilient-runner.js.map +1 -0
- package/dist/server/cli/headless/retry-strategies.d.ts +44 -0
- package/dist/server/cli/headless/retry-strategies.d.ts.map +1 -0
- package/dist/server/cli/headless/retry-strategies.js +262 -0
- package/dist/server/cli/headless/retry-strategies.js.map +1 -0
- package/dist/server/cli/headless/stall-assessor.d.ts.map +1 -1
- package/dist/server/cli/headless/stall-assessor.js +5 -0
- package/dist/server/cli/headless/stall-assessor.js.map +1 -1
- package/dist/server/cli/headless/tool-watchdog.d.ts +2 -0
- package/dist/server/cli/headless/tool-watchdog.d.ts.map +1 -1
- package/dist/server/cli/headless/tool-watchdog.js +31 -4
- package/dist/server/cli/headless/tool-watchdog.js.map +1 -1
- package/dist/server/cli/improvisation-retry.d.ts.map +1 -1
- package/dist/server/cli/improvisation-retry.js +1 -30
- package/dist/server/cli/improvisation-retry.js.map +1 -1
- package/dist/server/cli/improvisation-session-manager.d.ts +1 -0
- package/dist/server/cli/improvisation-session-manager.d.ts.map +1 -1
- package/dist/server/cli/improvisation-session-manager.js +16 -3
- package/dist/server/cli/improvisation-session-manager.js.map +1 -1
- package/dist/server/cli/prompt-builders.d.ts.map +1 -1
- package/dist/server/cli/prompt-builders.js +31 -13
- package/dist/server/cli/prompt-builders.js.map +1 -1
- package/dist/server/index.js +1 -9
- package/dist/server/index.js.map +1 -1
- package/dist/server/mcp/bouncer-cli.js +5 -4
- package/dist/server/mcp/bouncer-cli.js.map +1 -1
- package/dist/server/mcp/bouncer-haiku.js +1 -1
- package/dist/server/mcp/bouncer-haiku.js.map +1 -1
- package/dist/server/mcp/bouncer-integration.d.ts.map +1 -1
- package/dist/server/mcp/bouncer-integration.js +14 -8
- package/dist/server/mcp/bouncer-integration.js.map +1 -1
- package/dist/server/mcp/security-patterns.js +1 -1
- package/dist/server/mcp/security-patterns.js.map +1 -1
- package/dist/server/services/plan/composer.d.ts.map +1 -1
- package/dist/server/services/plan/composer.js +19 -9
- package/dist/server/services/plan/composer.js.map +1 -1
- package/dist/server/services/plan/executor.d.ts +6 -1
- package/dist/server/services/plan/executor.d.ts.map +1 -1
- package/dist/server/services/plan/executor.js +158 -76
- package/dist/server/services/plan/executor.js.map +1 -1
- package/dist/server/services/plan/front-matter.d.ts +1 -0
- package/dist/server/services/plan/front-matter.d.ts.map +1 -1
- package/dist/server/services/plan/front-matter.js +6 -0
- package/dist/server/services/plan/front-matter.js.map +1 -1
- package/dist/server/services/plan/issue-classification.d.ts +11 -0
- package/dist/server/services/plan/issue-classification.d.ts.map +1 -0
- package/dist/server/services/plan/issue-classification.js +20 -0
- package/dist/server/services/plan/issue-classification.js.map +1 -0
- package/dist/server/services/plan/issue-prompt-builder.d.ts.map +1 -1
- package/dist/server/services/plan/issue-prompt-builder.js +7 -4
- package/dist/server/services/plan/issue-prompt-builder.js.map +1 -1
- package/dist/server/services/plan/issue-retry.d.ts +0 -5
- package/dist/server/services/plan/issue-retry.d.ts.map +1 -1
- package/dist/server/services/plan/issue-retry.js +12 -241
- package/dist/server/services/plan/issue-retry.js.map +1 -1
- package/dist/server/services/plan/parser-core.d.ts.map +1 -1
- package/dist/server/services/plan/parser-core.js +1 -0
- package/dist/server/services/plan/parser-core.js.map +1 -1
- package/dist/server/services/plan/review-gate.d.ts.map +1 -1
- package/dist/server/services/plan/review-gate.js +9 -6
- package/dist/server/services/plan/review-gate.js.map +1 -1
- package/dist/server/services/plan/types.d.ts +1 -0
- package/dist/server/services/plan/types.d.ts.map +1 -1
- package/dist/server/services/platform-credentials.d.ts.map +1 -1
- package/dist/server/services/platform-credentials.js +11 -4
- package/dist/server/services/platform-credentials.js.map +1 -1
- package/dist/server/services/terminal/pty-manager.d.ts.map +1 -1
- package/dist/server/services/terminal/pty-manager.js +7 -1
- package/dist/server/services/terminal/pty-manager.js.map +1 -1
- package/dist/server/services/websocket/handler-context.d.ts +2 -0
- package/dist/server/services/websocket/handler-context.d.ts.map +1 -1
- package/dist/server/services/websocket/handler.d.ts +2 -0
- package/dist/server/services/websocket/handler.d.ts.map +1 -1
- package/dist/server/services/websocket/handler.js +18 -7
- package/dist/server/services/websocket/handler.js.map +1 -1
- package/dist/server/services/websocket/plan-execution-handlers.js +6 -6
- package/dist/server/services/websocket/plan-execution-handlers.js.map +1 -1
- package/dist/server/services/websocket/quality-fix-agent.d.ts.map +1 -1
- package/dist/server/services/websocket/quality-fix-agent.js +90 -42
- package/dist/server/services/websocket/quality-fix-agent.js.map +1 -1
- package/dist/server/services/websocket/quality-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/quality-handlers.js +48 -7
- package/dist/server/services/websocket/quality-handlers.js.map +1 -1
- package/dist/server/services/websocket/quality-persistence.d.ts +22 -0
- package/dist/server/services/websocket/quality-persistence.d.ts.map +1 -1
- package/dist/server/services/websocket/quality-persistence.js +48 -1
- package/dist/server/services/websocket/quality-persistence.js.map +1 -1
- package/dist/server/services/websocket/quality-review-agent.d.ts.map +1 -1
- package/dist/server/services/websocket/quality-review-agent.js +74 -32
- package/dist/server/services/websocket/quality-review-agent.js.map +1 -1
- package/dist/server/services/websocket/quality-tools.d.ts.map +1 -1
- package/dist/server/services/websocket/quality-tools.js +18 -18
- package/dist/server/services/websocket/quality-tools.js.map +1 -1
- package/dist/server/services/websocket/skill-handlers.d.ts +3 -1
- package/dist/server/services/websocket/skill-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/skill-handlers.js +52 -41
- package/dist/server/services/websocket/skill-handlers.js.map +1 -1
- package/dist/server/services/websocket/skill-watcher.d.ts +17 -0
- package/dist/server/services/websocket/skill-watcher.d.ts.map +1 -0
- package/dist/server/services/websocket/skill-watcher.js +85 -0
- package/dist/server/services/websocket/skill-watcher.js.map +1 -0
- package/dist/server/services/websocket/types.d.ts +2 -268
- package/dist/server/services/websocket/types.d.ts.map +1 -1
- package/dist/server/services/websocket/types.js +0 -4
- package/dist/server/services/websocket/types.js.map +1 -1
- package/package.json +1 -1
- package/server/cli/headless/claude-invoker-stream.ts +1 -0
- package/server/cli/headless/index.ts +2 -0
- package/server/cli/headless/resilient-runner.ts +354 -0
- package/server/cli/headless/retry-strategies.ts +330 -0
- package/server/cli/headless/stall-assessor.ts +5 -0
- package/server/cli/headless/tool-watchdog.ts +40 -4
- package/server/cli/improvisation-retry.ts +1 -32
- package/server/cli/improvisation-session-manager.ts +17 -3
- package/server/cli/prompt-builders.ts +33 -12
- package/server/index.ts +1 -9
- package/server/mcp/bouncer-cli.ts +5 -4
- package/server/mcp/bouncer-haiku.ts +1 -1
- package/server/mcp/bouncer-integration.ts +15 -8
- package/server/mcp/security-patterns.ts +1 -1
- package/server/services/plan/agents/code-review.md +109 -0
- package/server/services/plan/agents/commit-message.md +26 -0
- package/server/services/plan/agents/fix-quality.md +24 -0
- package/server/services/plan/agents/pr-description.md +28 -0
- package/server/services/plan/composer.ts +20 -9
- package/server/services/plan/executor.ts +160 -76
- package/server/services/plan/front-matter.ts +7 -0
- package/server/services/plan/issue-classification.ts +21 -0
- package/server/services/plan/issue-prompt-builder.ts +8 -4
- package/server/services/plan/issue-retry.ts +15 -330
- package/server/services/plan/parser-core.ts +1 -0
- package/server/services/plan/review-gate.ts +9 -6
- package/server/services/plan/types.ts +3 -0
- package/server/services/platform-credentials.ts +10 -4
- package/server/services/terminal/pty-manager.ts +7 -1
- package/server/services/websocket/handler-context.ts +2 -0
- package/server/services/websocket/handler.ts +18 -8
- package/server/services/websocket/plan-execution-handlers.ts +7 -7
- package/server/services/websocket/quality-fix-agent.ts +86 -44
- package/server/services/websocket/quality-handlers.ts +48 -7
- package/server/services/websocket/quality-persistence.ts +75 -1
- package/server/services/websocket/quality-review-agent.ts +70 -31
- package/server/services/websocket/quality-tools.ts +16 -14
- package/server/services/websocket/skill-handlers.ts +50 -40
- package/server/services/websocket/skill-watcher.ts +79 -0
- package/server/services/websocket/types.ts +0 -311
- package/dist/server/services/deploy/ai-broker.d.ts +0 -63
- package/dist/server/services/deploy/ai-broker.d.ts.map +0 -1
- package/dist/server/services/deploy/ai-broker.js +0 -360
- package/dist/server/services/deploy/ai-broker.js.map +0 -1
- package/dist/server/services/deploy/board-execution-handler.d.ts +0 -114
- package/dist/server/services/deploy/board-execution-handler.d.ts.map +0 -1
- package/dist/server/services/deploy/board-execution-handler.js +0 -621
- package/dist/server/services/deploy/board-execution-handler.js.map +0 -1
- package/dist/server/services/deploy/credentials.d.ts +0 -35
- package/dist/server/services/deploy/credentials.d.ts.map +0 -1
- package/dist/server/services/deploy/credentials.js +0 -177
- package/dist/server/services/deploy/credentials.js.map +0 -1
- package/dist/server/services/deploy/deploy-ai-service.d.ts +0 -107
- package/dist/server/services/deploy/deploy-ai-service.d.ts.map +0 -1
- package/dist/server/services/deploy/deploy-ai-service.js +0 -294
- package/dist/server/services/deploy/deploy-ai-service.js.map +0 -1
- package/dist/server/services/deploy/headless-session-handler.d.ts +0 -94
- package/dist/server/services/deploy/headless-session-handler.d.ts.map +0 -1
- package/dist/server/services/deploy/headless-session-handler.js +0 -266
- package/dist/server/services/deploy/headless-session-handler.js.map +0 -1
- package/dist/server/services/websocket/deploy-handlers.d.ts +0 -14
- package/dist/server/services/websocket/deploy-handlers.d.ts.map +0 -1
- package/dist/server/services/websocket/deploy-handlers.js +0 -409
- package/dist/server/services/websocket/deploy-handlers.js.map +0 -1
- package/dist/server/services/websocket/handlers/deploy-handlers.d.ts +0 -11
- package/dist/server/services/websocket/handlers/deploy-handlers.d.ts.map +0 -1
- package/dist/server/services/websocket/handlers/deploy-handlers.js +0 -176
- package/dist/server/services/websocket/handlers/deploy-handlers.js.map +0 -1
- package/server/cli/headless/RESEARCH.md +0 -627
- package/server/services/deploy/ai-broker.ts +0 -512
- package/server/services/deploy/board-execution-handler.ts +0 -847
- package/server/services/deploy/credentials.ts +0 -200
- package/server/services/deploy/deploy-ai-service.ts +0 -401
- package/server/services/deploy/headless-session-handler.ts +0 -414
- package/server/services/websocket/deploy-handlers.ts +0 -544
- package/server/services/websocket/handlers/deploy-handlers.ts +0 -228
|
@@ -1,409 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2025-present Mstro, Inc. All rights reserved.
|
|
2
|
-
// Licensed under the MIT License. See LICENSE file for details.
|
|
3
|
-
/**
|
|
4
|
-
* Deploy Handlers — WebSocket message router for deployment management.
|
|
5
|
-
*
|
|
6
|
-
* Handles deployCreate, deployStop, deployResume, deployDelete,
|
|
7
|
-
* deployList, deployGetStatus, deployUpdateConfig, deploySetApiKey,
|
|
8
|
-
* and delegates deployHttpRequest to the HTTP relay handler.
|
|
9
|
-
*/
|
|
10
|
-
import { connect } from 'node:net';
|
|
11
|
-
import { checkValidationRateLimit, getApiKeyStatus, storeApiKey, validateAnthropicKey, } from '../deploy/credentials.js';
|
|
12
|
-
import { getCredentials } from '../platform-credentials.js';
|
|
13
|
-
import { handleDeployHttpRequest } from './handlers/deploy-handlers.js';
|
|
14
|
-
// ── Platform API ─────────��───────────────────────────────────
|
|
15
|
-
const PLATFORM_URL = process.env.PLATFORM_URL || 'https://api.mstro.app';
|
|
16
|
-
async function platformFetch(path, options = {}) {
|
|
17
|
-
const creds = getCredentials();
|
|
18
|
-
if (!creds) {
|
|
19
|
-
throw new Error('Not authenticated. Run `mstro login` first.');
|
|
20
|
-
}
|
|
21
|
-
const url = `${PLATFORM_URL}${path}`;
|
|
22
|
-
return fetch(url, {
|
|
23
|
-
...options,
|
|
24
|
-
headers: {
|
|
25
|
-
'Content-Type': 'application/json',
|
|
26
|
-
Authorization: `Bearer ${creds.token}`,
|
|
27
|
-
...options.headers,
|
|
28
|
-
},
|
|
29
|
-
signal: AbortSignal.timeout(15_000),
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
const localDeployments = new Map();
|
|
33
|
-
function toDeploymentInfo(serverRow) {
|
|
34
|
-
return {
|
|
35
|
-
deploymentId: serverRow.id,
|
|
36
|
-
config: {
|
|
37
|
-
subdomain: serverRow.subdomain,
|
|
38
|
-
port: serverRow.port || 0,
|
|
39
|
-
aiEnabled: false,
|
|
40
|
-
},
|
|
41
|
-
status: serverRow.status === 'active' ? 'running' : serverRow.status === 'stopped' ? 'stopped' : 'starting',
|
|
42
|
-
url: `https://${serverRow.subdomain}.mstro.app`,
|
|
43
|
-
createdAt: serverRow.createdAt || new Date().toISOString(),
|
|
44
|
-
updatedAt: serverRow.updatedAt || new Date().toISOString(),
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
// ── Port validation ──────────────────────────────────────────
|
|
48
|
-
function validatePort(port) {
|
|
49
|
-
return new Promise((resolve) => {
|
|
50
|
-
const socket = connect({ host: '127.0.0.1', port }, () => {
|
|
51
|
-
socket.destroy();
|
|
52
|
-
resolve(true);
|
|
53
|
-
});
|
|
54
|
-
socket.on('error', () => {
|
|
55
|
-
socket.destroy();
|
|
56
|
-
resolve(false);
|
|
57
|
-
});
|
|
58
|
-
socket.setTimeout(2_000, () => {
|
|
59
|
-
socket.destroy();
|
|
60
|
-
resolve(false);
|
|
61
|
-
});
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
// ── Error helper ───────���─────────────────────────────────────
|
|
65
|
-
function sendDeployError(ctx, ws, error, deploymentId) {
|
|
66
|
-
ctx.send(ws, {
|
|
67
|
-
type: 'deployError',
|
|
68
|
-
data: { error, deploymentId },
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
// ── Message router ───────────────────────────────────────────
|
|
72
|
-
export function handleDeployMessage(ctx, ws, msg, _tabId, _workingDir, _permission) {
|
|
73
|
-
const handlers = {
|
|
74
|
-
deployCreate: () => handleDeployCreate(ctx, ws, msg),
|
|
75
|
-
deployStop: () => handleDeployStop(ctx, ws, msg),
|
|
76
|
-
deployResume: () => handleDeployResume(ctx, ws, msg),
|
|
77
|
-
deployDelete: () => handleDeployDelete(ctx, ws, msg),
|
|
78
|
-
deployList: () => handleDeployList(ctx, ws),
|
|
79
|
-
deployGetStatus: () => handleDeployGetStatus(ctx, ws, msg),
|
|
80
|
-
deployUpdateConfig: () => handleDeployUpdateConfig(ctx, ws, msg),
|
|
81
|
-
deploySetApiKey: () => handleDeploySetApiKey(ctx, ws, msg),
|
|
82
|
-
deployValidateApiKey: () => handleDeployValidateApiKey(ctx, ws),
|
|
83
|
-
deployHttpRequest: () => handleDeployHttpRequest(ctx, ws, msg),
|
|
84
|
-
};
|
|
85
|
-
const handler = handlers[msg.type];
|
|
86
|
-
if (!handler)
|
|
87
|
-
return;
|
|
88
|
-
try {
|
|
89
|
-
const result = handler();
|
|
90
|
-
// Handle async handlers — catch rejections
|
|
91
|
-
if (result instanceof Promise) {
|
|
92
|
-
result.catch((error) => {
|
|
93
|
-
const errMsg = error instanceof Error ? error.message : String(error);
|
|
94
|
-
sendDeployError(ctx, ws, errMsg);
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
catch (error) {
|
|
99
|
-
const errMsg = error instanceof Error ? error.message : String(error);
|
|
100
|
-
sendDeployError(ctx, ws, errMsg);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
// ── Handler implementations ──────────────────────────────────
|
|
104
|
-
/**
|
|
105
|
-
* deployCreate — validate port, call platform API, store local state.
|
|
106
|
-
*/
|
|
107
|
-
async function handleDeployCreate(ctx, ws, msg) {
|
|
108
|
-
const data = msg.data;
|
|
109
|
-
if (!data?.subdomain || !data?.port) {
|
|
110
|
-
sendDeployError(ctx, ws, 'subdomain and port are required');
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
// Validate local port is in use
|
|
114
|
-
const portInUse = await validatePort(data.port);
|
|
115
|
-
if (!portInUse) {
|
|
116
|
-
sendDeployError(ctx, ws, `No service running on port ${data.port}. Start your app first.`);
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
// Call platform server API to create deployment record
|
|
120
|
-
const creds = getCredentials();
|
|
121
|
-
if (!creds) {
|
|
122
|
-
sendDeployError(ctx, ws, 'Not authenticated. Run `mstro login` first.');
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
const response = await platformFetch('/api/deployments', {
|
|
126
|
-
method: 'POST',
|
|
127
|
-
body: JSON.stringify({
|
|
128
|
-
orchestraPairingId: creds.clientId,
|
|
129
|
-
subdomain: data.subdomain,
|
|
130
|
-
port: data.port,
|
|
131
|
-
}),
|
|
132
|
-
});
|
|
133
|
-
if (!response.ok) {
|
|
134
|
-
const body = await response.json().catch(() => ({ error: 'Failed to create deployment' }));
|
|
135
|
-
sendDeployError(ctx, ws, body.error || `Server returned ${response.status}`);
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
const { deployment: serverDeployment } = await response.json();
|
|
139
|
-
const info = toDeploymentInfo(serverDeployment);
|
|
140
|
-
info.config.port = data.port;
|
|
141
|
-
info.config.aiEnabled = data.aiEnabled ?? false;
|
|
142
|
-
info.status = 'running';
|
|
143
|
-
// Store local state
|
|
144
|
-
localDeployments.set(info.deploymentId, { info, proxyActive: true });
|
|
145
|
-
ctx.send(ws, {
|
|
146
|
-
type: 'deployCreated',
|
|
147
|
-
data: { deployment: info },
|
|
148
|
-
});
|
|
149
|
-
// Notify the platform server that this deployment is now active
|
|
150
|
-
ctx.broadcastToAll({
|
|
151
|
-
type: 'deployStatus',
|
|
152
|
-
data: { deploymentId: info.deploymentId, status: 'running' },
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* deployStop — toggle local HTTP proxy off.
|
|
157
|
-
*/
|
|
158
|
-
async function handleDeployStop(ctx, ws, msg) {
|
|
159
|
-
const data = msg.data;
|
|
160
|
-
if (!data?.deploymentId) {
|
|
161
|
-
sendDeployError(ctx, ws, 'deploymentId is required');
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
const local = localDeployments.get(data.deploymentId);
|
|
165
|
-
if (!local) {
|
|
166
|
-
sendDeployError(ctx, ws, 'Deployment not found locally', data.deploymentId);
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
local.proxyActive = false;
|
|
170
|
-
local.info.status = 'stopped';
|
|
171
|
-
local.info.updatedAt = new Date().toISOString();
|
|
172
|
-
// Update server status
|
|
173
|
-
await platformFetch(`/api/deployments/${data.deploymentId}`, {
|
|
174
|
-
method: 'PATCH',
|
|
175
|
-
body: JSON.stringify({ status: 'stopped' }),
|
|
176
|
-
}).catch(() => {
|
|
177
|
-
// Non-critical: local state is authoritative for stop/resume
|
|
178
|
-
});
|
|
179
|
-
ctx.send(ws, {
|
|
180
|
-
type: 'deployStopped',
|
|
181
|
-
data: { deploymentId: data.deploymentId },
|
|
182
|
-
});
|
|
183
|
-
ctx.broadcastToAll({
|
|
184
|
-
type: 'deployStatus',
|
|
185
|
-
data: { deploymentId: data.deploymentId, status: 'stopped' },
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* deployResume — toggle local HTTP proxy on.
|
|
190
|
-
*/
|
|
191
|
-
async function handleDeployResume(ctx, ws, msg) {
|
|
192
|
-
const data = msg.data;
|
|
193
|
-
if (!data?.deploymentId) {
|
|
194
|
-
sendDeployError(ctx, ws, 'deploymentId is required');
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
const local = localDeployments.get(data.deploymentId);
|
|
198
|
-
if (!local) {
|
|
199
|
-
sendDeployError(ctx, ws, 'Deployment not found locally', data.deploymentId);
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
// Validate the port is still in use before resuming
|
|
203
|
-
const portInUse = await validatePort(local.info.config.port);
|
|
204
|
-
if (!portInUse) {
|
|
205
|
-
sendDeployError(ctx, ws, `No service running on port ${local.info.config.port}. Start your app first.`, data.deploymentId);
|
|
206
|
-
return;
|
|
207
|
-
}
|
|
208
|
-
local.proxyActive = true;
|
|
209
|
-
local.info.status = 'running';
|
|
210
|
-
local.info.updatedAt = new Date().toISOString();
|
|
211
|
-
// Update server status
|
|
212
|
-
await platformFetch(`/api/deployments/${data.deploymentId}`, {
|
|
213
|
-
method: 'PATCH',
|
|
214
|
-
body: JSON.stringify({ status: 'active' }),
|
|
215
|
-
}).catch(() => {
|
|
216
|
-
// Non-critical
|
|
217
|
-
});
|
|
218
|
-
ctx.send(ws, {
|
|
219
|
-
type: 'deployResumed',
|
|
220
|
-
data: { deploymentId: data.deploymentId },
|
|
221
|
-
});
|
|
222
|
-
ctx.broadcastToAll({
|
|
223
|
-
type: 'deployStatus',
|
|
224
|
-
data: { deploymentId: data.deploymentId, status: 'running' },
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
|
-
/**
|
|
228
|
-
* deployList — return all local deployment states.
|
|
229
|
-
*/
|
|
230
|
-
function handleDeployList(ctx, ws) {
|
|
231
|
-
const deployments = [];
|
|
232
|
-
for (const local of localDeployments.values()) {
|
|
233
|
-
deployments.push(local.info);
|
|
234
|
-
}
|
|
235
|
-
ctx.send(ws, {
|
|
236
|
-
type: 'deployListResult',
|
|
237
|
-
data: { deployments },
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
/**
|
|
241
|
-
* deployGetStatus — return detailed status for one deployment.
|
|
242
|
-
*/
|
|
243
|
-
function handleDeployGetStatus(ctx, ws, msg) {
|
|
244
|
-
const data = msg.data;
|
|
245
|
-
if (!data?.deploymentId) {
|
|
246
|
-
sendDeployError(ctx, ws, 'deploymentId is required');
|
|
247
|
-
return;
|
|
248
|
-
}
|
|
249
|
-
const local = localDeployments.get(data.deploymentId);
|
|
250
|
-
if (!local) {
|
|
251
|
-
sendDeployError(ctx, ws, 'Deployment not found', data.deploymentId);
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
254
|
-
ctx.send(ws, {
|
|
255
|
-
type: 'deployStatusResult',
|
|
256
|
-
data: { deployment: local.info },
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
/**
|
|
260
|
-
* deployUpdateConfig — update config locally and on server.
|
|
261
|
-
*/
|
|
262
|
-
async function handleDeployUpdateConfig(ctx, ws, msg) {
|
|
263
|
-
const data = msg.data;
|
|
264
|
-
if (!data?.deploymentId) {
|
|
265
|
-
sendDeployError(ctx, ws, 'deploymentId is required');
|
|
266
|
-
return;
|
|
267
|
-
}
|
|
268
|
-
const local = localDeployments.get(data.deploymentId);
|
|
269
|
-
if (!local) {
|
|
270
|
-
sendDeployError(ctx, ws, 'Deployment not found', data.deploymentId);
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
// Apply config updates locally
|
|
274
|
-
if (data.config.subdomain !== undefined) {
|
|
275
|
-
local.info.config.subdomain = data.config.subdomain;
|
|
276
|
-
local.info.url = `https://${data.config.subdomain}.mstro.app`;
|
|
277
|
-
}
|
|
278
|
-
if (data.config.port !== undefined) {
|
|
279
|
-
local.info.config.port = data.config.port;
|
|
280
|
-
}
|
|
281
|
-
if (data.config.aiEnabled !== undefined) {
|
|
282
|
-
local.info.config.aiEnabled = data.config.aiEnabled;
|
|
283
|
-
}
|
|
284
|
-
if (data.config.customDomain !== undefined) {
|
|
285
|
-
local.info.config.customDomain = data.config.customDomain;
|
|
286
|
-
}
|
|
287
|
-
local.info.updatedAt = new Date().toISOString();
|
|
288
|
-
// Sync to platform server
|
|
289
|
-
const serverUpdates = {};
|
|
290
|
-
if (data.config.subdomain !== undefined) {
|
|
291
|
-
serverUpdates.subdomain = data.config.subdomain;
|
|
292
|
-
}
|
|
293
|
-
if (data.config.port !== undefined) {
|
|
294
|
-
serverUpdates.port = data.config.port;
|
|
295
|
-
}
|
|
296
|
-
if (Object.keys(serverUpdates).length > 0) {
|
|
297
|
-
const response = await platformFetch(`/api/deployments/${data.deploymentId}`, {
|
|
298
|
-
method: 'PATCH',
|
|
299
|
-
body: JSON.stringify(serverUpdates),
|
|
300
|
-
});
|
|
301
|
-
if (!response.ok) {
|
|
302
|
-
const body = await response.json().catch(() => ({ error: 'Failed to update deployment' }));
|
|
303
|
-
sendDeployError(ctx, ws, body.error || `Server returned ${response.status}`, data.deploymentId);
|
|
304
|
-
return;
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
ctx.send(ws, {
|
|
308
|
-
type: 'deployConfigUpdated',
|
|
309
|
-
data: { deployment: local.info },
|
|
310
|
-
});
|
|
311
|
-
}
|
|
312
|
-
/**
|
|
313
|
-
* deploySetApiKey — validate with Anthropic API, encrypt, and store locally.
|
|
314
|
-
* The API key is NEVER logged, even partially.
|
|
315
|
-
* Rate limited to max 10 validation attempts per minute.
|
|
316
|
-
*/
|
|
317
|
-
async function handleDeploySetApiKey(ctx, ws, msg) {
|
|
318
|
-
const data = msg.data;
|
|
319
|
-
if (!data?.apiKey) {
|
|
320
|
-
sendDeployError(ctx, ws, 'apiKey is required');
|
|
321
|
-
return;
|
|
322
|
-
}
|
|
323
|
-
// Enforce rate limit before calling the Anthropic API
|
|
324
|
-
if (!checkValidationRateLimit()) {
|
|
325
|
-
ctx.send(ws, {
|
|
326
|
-
type: 'deployApiKeyStatus',
|
|
327
|
-
data: { status: 'rate_limited' },
|
|
328
|
-
});
|
|
329
|
-
return;
|
|
330
|
-
}
|
|
331
|
-
// Validate the key with Anthropic API
|
|
332
|
-
const isValid = await validateAnthropicKey(data.apiKey);
|
|
333
|
-
if (!isValid) {
|
|
334
|
-
ctx.send(ws, {
|
|
335
|
-
type: 'deployApiKeyStatus',
|
|
336
|
-
data: { status: 'invalid' },
|
|
337
|
-
});
|
|
338
|
-
return;
|
|
339
|
-
}
|
|
340
|
-
// Encrypt and store locally
|
|
341
|
-
const { lastFour } = storeApiKey(data.apiKey);
|
|
342
|
-
ctx.send(ws, {
|
|
343
|
-
type: 'deployApiKeyStatus',
|
|
344
|
-
data: { status: 'valid', lastFour, source: 'stored' },
|
|
345
|
-
});
|
|
346
|
-
}
|
|
347
|
-
/**
|
|
348
|
-
* deployValidateApiKey — check current key status (env var or stored).
|
|
349
|
-
* When env var is detected, source is 'env' so the UI can show
|
|
350
|
-
* "detected from environment".
|
|
351
|
-
*/
|
|
352
|
-
function handleDeployValidateApiKey(ctx, ws) {
|
|
353
|
-
const keyStatus = getApiKeyStatus();
|
|
354
|
-
ctx.send(ws, {
|
|
355
|
-
type: 'deployApiKeyStatus',
|
|
356
|
-
data: keyStatus,
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
/**
|
|
360
|
-
* deployDelete — stop proxy and call server API to delete.
|
|
361
|
-
*/
|
|
362
|
-
async function handleDeployDelete(ctx, ws, msg) {
|
|
363
|
-
const data = msg.data;
|
|
364
|
-
if (!data?.deploymentId) {
|
|
365
|
-
sendDeployError(ctx, ws, 'deploymentId is required');
|
|
366
|
-
return;
|
|
367
|
-
}
|
|
368
|
-
// Stop local proxy
|
|
369
|
-
const local = localDeployments.get(data.deploymentId);
|
|
370
|
-
if (local) {
|
|
371
|
-
local.proxyActive = false;
|
|
372
|
-
}
|
|
373
|
-
// Call server API to delete
|
|
374
|
-
const response = await platformFetch(`/api/deployments/${data.deploymentId}`, {
|
|
375
|
-
method: 'DELETE',
|
|
376
|
-
});
|
|
377
|
-
if (!response.ok) {
|
|
378
|
-
const body = await response.json().catch(() => ({ error: 'Failed to delete deployment' }));
|
|
379
|
-
sendDeployError(ctx, ws, body.error || `Server returned ${response.status}`, data.deploymentId);
|
|
380
|
-
return;
|
|
381
|
-
}
|
|
382
|
-
// Remove from local state
|
|
383
|
-
localDeployments.delete(data.deploymentId);
|
|
384
|
-
ctx.send(ws, {
|
|
385
|
-
type: 'deployDeleted',
|
|
386
|
-
data: { deploymentId: data.deploymentId },
|
|
387
|
-
});
|
|
388
|
-
ctx.broadcastToAll({
|
|
389
|
-
type: 'deployStatus',
|
|
390
|
-
data: { deploymentId: data.deploymentId, status: 'stopped' },
|
|
391
|
-
});
|
|
392
|
-
}
|
|
393
|
-
/**
|
|
394
|
-
* Check if a deployment's proxy is active. Used by the HTTP relay
|
|
395
|
-
* to decide whether to forward incoming requests.
|
|
396
|
-
*/
|
|
397
|
-
export function isDeploymentProxyActive(deploymentId) {
|
|
398
|
-
const local = localDeployments.get(deploymentId);
|
|
399
|
-
return local?.proxyActive ?? false;
|
|
400
|
-
}
|
|
401
|
-
/**
|
|
402
|
-
* Get the local port for a deployment. Used by the HTTP relay
|
|
403
|
-
* to forward requests to the correct local service.
|
|
404
|
-
*/
|
|
405
|
-
export function getDeploymentPort(deploymentId) {
|
|
406
|
-
const local = localDeployments.get(deploymentId);
|
|
407
|
-
return local?.info.config.port ?? null;
|
|
408
|
-
}
|
|
409
|
-
//# sourceMappingURL=deploy-handlers.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"deploy-handlers.js","sourceRoot":"","sources":["../../../../server/services/websocket/deploy-handlers.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Deploy HTTP Handler
|
|
3
|
-
*
|
|
4
|
-
* Handles deployHttpRequest messages from the platform server relay.
|
|
5
|
-
* Proxies HTTP requests to the developer's local server and returns
|
|
6
|
-
* the response back through the WebSocket relay.
|
|
7
|
-
*/
|
|
8
|
-
import type { HandlerContext } from '../handler-context.js';
|
|
9
|
-
import type { WebSocketMessage, WSContext } from '../types.js';
|
|
10
|
-
export declare function handleDeployHttpRequest(ctx: HandlerContext, ws: WSContext, msg: WebSocketMessage): Promise<void>;
|
|
11
|
-
//# sourceMappingURL=deploy-handlers.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"deploy-handlers.d.ts","sourceRoot":"","sources":["../../../../../server/services/websocket/handlers/deploy-handlers.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAA8E,gBAAgB,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAkI3I,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,cAAc,EACnB,EAAE,EAAE,SAAS,EACb,GAAG,EAAE,gBAAgB,GACpB,OAAO,CAAC,IAAI,CAAC,CA0Ef"}
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2025-present Mstro, Inc. All rights reserved.
|
|
2
|
-
// Licensed under the MIT License. See LICENSE file for details.
|
|
3
|
-
/** Hop-by-hop headers that must not be forwarded through a proxy (RFC 2616 §13.5.1) */
|
|
4
|
-
const HOP_BY_HOP_HEADERS = new Set([
|
|
5
|
-
'connection',
|
|
6
|
-
'keep-alive',
|
|
7
|
-
'transfer-encoding',
|
|
8
|
-
'te',
|
|
9
|
-
'trailers',
|
|
10
|
-
'upgrade',
|
|
11
|
-
]);
|
|
12
|
-
/** Request timeout in milliseconds (30 seconds) */
|
|
13
|
-
const REQUEST_TIMEOUT_MS = 30_000;
|
|
14
|
-
/** Maximum total header size in bytes (16 KB) */
|
|
15
|
-
const MAX_HEADER_SIZE_BYTES = 16_384;
|
|
16
|
-
/** Chunking threshold: responses larger than 1 MB are streamed in chunks */
|
|
17
|
-
const CHUNK_THRESHOLD_BYTES = 1_048_576;
|
|
18
|
-
/** Size of each chunk (~256 KB of raw data → ~341 KB base64) */
|
|
19
|
-
const CHUNK_SIZE_BYTES = 262_144;
|
|
20
|
-
function isHopByHopHeader(name) {
|
|
21
|
-
const lower = name.toLowerCase();
|
|
22
|
-
return HOP_BY_HOP_HEADERS.has(lower) || lower.startsWith('proxy-');
|
|
23
|
-
}
|
|
24
|
-
function stripHopByHopHeaders(headers) {
|
|
25
|
-
const result = {};
|
|
26
|
-
for (const [key, value] of Object.entries(headers)) {
|
|
27
|
-
if (!isHopByHopHeader(key)) {
|
|
28
|
-
result[key] = value;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return result;
|
|
32
|
-
}
|
|
33
|
-
/** Check headers for null bytes or CRLF injection attempts */
|
|
34
|
-
function containsHeaderInjection(headers) {
|
|
35
|
-
for (const [key, value] of Object.entries(headers)) {
|
|
36
|
-
if (key.includes('\0') || value.includes('\0'))
|
|
37
|
-
return true;
|
|
38
|
-
if (/\r|\n/.test(key) || /\r|\n/.test(value))
|
|
39
|
-
return true;
|
|
40
|
-
}
|
|
41
|
-
return false;
|
|
42
|
-
}
|
|
43
|
-
/** Calculate total size of request headers in bytes */
|
|
44
|
-
function calculateHeaderSize(headers) {
|
|
45
|
-
let size = 0;
|
|
46
|
-
for (const [key, value] of Object.entries(headers)) {
|
|
47
|
-
// key: value\r\n
|
|
48
|
-
size += key.length + 2 + value.length + 2;
|
|
49
|
-
}
|
|
50
|
-
return size;
|
|
51
|
-
}
|
|
52
|
-
function sendDeployHttpResponse(ctx, ws, data) {
|
|
53
|
-
ctx.send(ws, { type: 'deployHttpResponse', data });
|
|
54
|
-
}
|
|
55
|
-
/** Send a large response body in chunks via deployHttpResponseChunk messages */
|
|
56
|
-
function sendChunkedResponse(ctx, ws, requestId, status, headers, bodyBuffer) {
|
|
57
|
-
const totalChunks = Math.ceil(bodyBuffer.length / CHUNK_SIZE_BYTES);
|
|
58
|
-
for (let i = 0; i < totalChunks; i++) {
|
|
59
|
-
const start = i * CHUNK_SIZE_BYTES;
|
|
60
|
-
const end = Math.min(start + CHUNK_SIZE_BYTES, bodyBuffer.length);
|
|
61
|
-
const chunk = bodyBuffer.subarray(start, end);
|
|
62
|
-
const isLast = i === totalChunks - 1;
|
|
63
|
-
const chunkData = {
|
|
64
|
-
requestId,
|
|
65
|
-
chunkIndex: i,
|
|
66
|
-
totalChunks,
|
|
67
|
-
data: chunk.toString('base64'),
|
|
68
|
-
isLast,
|
|
69
|
-
};
|
|
70
|
-
// Include status and headers only in the first chunk
|
|
71
|
-
if (i === 0) {
|
|
72
|
-
chunkData.status = status;
|
|
73
|
-
chunkData.headers = headers;
|
|
74
|
-
}
|
|
75
|
-
ctx.send(ws, { type: 'deployHttpResponseChunk', data: chunkData });
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
/** Validate the incoming deploy HTTP request data. Returns an error response body string or null if valid. */
|
|
79
|
-
function validateDeployRequest(data) {
|
|
80
|
-
if (!data?.requestId || !data?.method || !data?.url || !data?.port) {
|
|
81
|
-
return { status: 400, body: 'Bad Request: missing required fields (requestId, method, url, port)' };
|
|
82
|
-
}
|
|
83
|
-
if (data.headers && containsHeaderInjection(data.headers)) {
|
|
84
|
-
return { status: 400, body: 'Bad Request: headers contain null bytes or CRLF injection' };
|
|
85
|
-
}
|
|
86
|
-
if (data.headers && calculateHeaderSize(data.headers) > MAX_HEADER_SIZE_BYTES) {
|
|
87
|
-
return { status: 431, body: 'Request Header Fields Too Large: total headers exceed 16KB' };
|
|
88
|
-
}
|
|
89
|
-
return null;
|
|
90
|
-
}
|
|
91
|
-
/** Classify a fetch error into an HTTP status code and message. */
|
|
92
|
-
function classifyFetchError(error) {
|
|
93
|
-
if (error instanceof Error) {
|
|
94
|
-
if (error.name === 'AbortError') {
|
|
95
|
-
return { status: 504, body: 'Gateway Timeout' };
|
|
96
|
-
}
|
|
97
|
-
if (isConnectionRefused(error)) {
|
|
98
|
-
return { status: 502, body: 'Bad Gateway: target server is not running' };
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
return { status: 502, body: 'Bad Gateway' };
|
|
102
|
-
}
|
|
103
|
-
export async function handleDeployHttpRequest(ctx, ws, msg) {
|
|
104
|
-
const data = msg.data;
|
|
105
|
-
const validationError = validateDeployRequest(data);
|
|
106
|
-
if (validationError) {
|
|
107
|
-
sendDeployHttpResponse(ctx, ws, {
|
|
108
|
-
requestId: data?.requestId || 'unknown',
|
|
109
|
-
status: validationError.status,
|
|
110
|
-
headers: {},
|
|
111
|
-
body: validationError.body,
|
|
112
|
-
});
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
// Build local URL: 127.0.0.1:{port}{path with query string}
|
|
116
|
-
// Use explicit IPv4 loopback to avoid IPv6 resolution issues on some systems
|
|
117
|
-
const localUrl = `http://127.0.0.1:${data.port}${data.url}`;
|
|
118
|
-
try {
|
|
119
|
-
const requestHeaders = stripHopByHopHeaders(data.headers);
|
|
120
|
-
// Only include body for methods that support it
|
|
121
|
-
const hasBody = data.body !== undefined && data.method !== 'GET' && data.method !== 'HEAD';
|
|
122
|
-
const controller = new AbortController();
|
|
123
|
-
const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
124
|
-
let response;
|
|
125
|
-
try {
|
|
126
|
-
response = await fetch(localUrl, {
|
|
127
|
-
method: data.method,
|
|
128
|
-
headers: requestHeaders,
|
|
129
|
-
body: hasBody ? data.body : undefined,
|
|
130
|
-
signal: controller.signal,
|
|
131
|
-
redirect: 'manual',
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
finally {
|
|
135
|
-
clearTimeout(timeout);
|
|
136
|
-
}
|
|
137
|
-
// Serialize response headers, stripping hop-by-hop
|
|
138
|
-
const responseHeaders = {};
|
|
139
|
-
response.headers.forEach((value, key) => {
|
|
140
|
-
if (!isHopByHopHeader(key)) {
|
|
141
|
-
responseHeaders[key] = value;
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
// Read response as binary to handle both text and binary payloads
|
|
145
|
-
const bodyBuffer = Buffer.from(await response.arrayBuffer());
|
|
146
|
-
// Stream large responses in chunks
|
|
147
|
-
if (bodyBuffer.length > CHUNK_THRESHOLD_BYTES) {
|
|
148
|
-
sendChunkedResponse(ctx, ws, data.requestId, response.status, responseHeaders, bodyBuffer);
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
// Small response — send as a single message
|
|
152
|
-
sendDeployHttpResponse(ctx, ws, {
|
|
153
|
-
requestId: data.requestId,
|
|
154
|
-
status: response.status,
|
|
155
|
-
headers: responseHeaders,
|
|
156
|
-
body: bodyBuffer.toString('utf-8'),
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
catch (error) {
|
|
160
|
-
const { status, body } = classifyFetchError(error);
|
|
161
|
-
sendDeployHttpResponse(ctx, ws, {
|
|
162
|
-
requestId: data.requestId,
|
|
163
|
-
status,
|
|
164
|
-
headers: {},
|
|
165
|
-
body,
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
/** Detect ECONNREFUSED across Node.js error shapes */
|
|
170
|
-
function isConnectionRefused(error) {
|
|
171
|
-
if (error.message.includes('ECONNREFUSED'))
|
|
172
|
-
return true;
|
|
173
|
-
const cause = error.cause;
|
|
174
|
-
return cause?.code === 'ECONNREFUSED';
|
|
175
|
-
}
|
|
176
|
-
//# sourceMappingURL=deploy-handlers.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"deploy-handlers.js","sourceRoot":"","sources":["../../../../../server/services/websocket/handlers/deploy-handlers.ts"],"names":[],"mappings":"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"}
|