mstro-app 0.4.20 → 0.4.22
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/README.md +66 -0
- package/dist/server/cli/headless/claude-invoker-process.js +1 -1
- package/dist/server/cli/headless/claude-invoker-process.js.map +1 -1
- package/dist/server/cli/headless/headless-logger.js +1 -1
- package/dist/server/cli/headless/headless-logger.js.map +1 -1
- package/dist/server/cli/headless/mcp-config.d.ts +1 -1
- package/dist/server/cli/headless/mcp-config.d.ts.map +1 -1
- package/dist/server/cli/headless/mcp-config.js +4 -1
- package/dist/server/cli/headless/mcp-config.js.map +1 -1
- package/dist/server/cli/headless/runner.d.ts.map +1 -1
- package/dist/server/cli/headless/runner.js +1 -0
- package/dist/server/cli/headless/runner.js.map +1 -1
- package/dist/server/cli/headless/types.d.ts +4 -1
- package/dist/server/cli/headless/types.d.ts.map +1 -1
- package/dist/server/index.js +9 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/mcp/bouncer-integration.d.ts +2 -2
- package/dist/server/mcp/bouncer-integration.d.ts.map +1 -1
- package/dist/server/mcp/bouncer-integration.js +20 -20
- package/dist/server/mcp/bouncer-integration.js.map +1 -1
- package/dist/server/mcp/security-analysis.d.ts +6 -0
- package/dist/server/mcp/security-analysis.d.ts.map +1 -1
- package/dist/server/mcp/security-analysis.js +16 -1
- package/dist/server/mcp/security-analysis.js.map +1 -1
- package/dist/server/mcp/security-patterns.d.ts +8 -0
- package/dist/server/mcp/security-patterns.d.ts.map +1 -1
- package/dist/server/mcp/security-patterns.js +47 -2
- package/dist/server/mcp/security-patterns.js.map +1 -1
- package/dist/server/services/deploy/ai-broker.d.ts +63 -0
- package/dist/server/services/deploy/ai-broker.d.ts.map +1 -0
- package/dist/server/services/deploy/ai-broker.js +360 -0
- package/dist/server/services/deploy/ai-broker.js.map +1 -0
- package/dist/server/services/deploy/board-execution-handler.d.ts +114 -0
- package/dist/server/services/deploy/board-execution-handler.d.ts.map +1 -0
- package/dist/server/services/deploy/board-execution-handler.js +621 -0
- package/dist/server/services/deploy/board-execution-handler.js.map +1 -0
- package/dist/server/services/deploy/credentials.d.ts +35 -0
- package/dist/server/services/deploy/credentials.d.ts.map +1 -0
- package/dist/server/services/deploy/credentials.js +177 -0
- package/dist/server/services/deploy/credentials.js.map +1 -0
- package/dist/server/services/deploy/deploy-ai-service.d.ts +107 -0
- package/dist/server/services/deploy/deploy-ai-service.d.ts.map +1 -0
- package/dist/server/services/deploy/deploy-ai-service.js +294 -0
- package/dist/server/services/deploy/deploy-ai-service.js.map +1 -0
- package/dist/server/services/deploy/headless-session-handler.d.ts +94 -0
- package/dist/server/services/deploy/headless-session-handler.d.ts.map +1 -0
- package/dist/server/services/deploy/headless-session-handler.js +274 -0
- package/dist/server/services/deploy/headless-session-handler.js.map +1 -0
- package/dist/server/services/pathUtils.d.ts.map +1 -1
- package/dist/server/services/pathUtils.js +33 -1
- package/dist/server/services/pathUtils.js.map +1 -1
- package/dist/server/services/plan/agent-loader.d.ts +10 -0
- package/dist/server/services/plan/agent-loader.d.ts.map +1 -0
- package/dist/server/services/plan/agent-loader.js +65 -0
- package/dist/server/services/plan/agent-loader.js.map +1 -0
- package/dist/server/services/plan/composer.d.ts.map +1 -1
- package/dist/server/services/plan/composer.js +5 -1
- package/dist/server/services/plan/composer.js.map +1 -1
- package/dist/server/services/plan/dependency-resolver.d.ts +1 -1
- package/dist/server/services/plan/dependency-resolver.js +2 -2
- package/dist/server/services/plan/dependency-resolver.js.map +1 -1
- package/dist/server/services/plan/executor.d.ts +7 -3
- package/dist/server/services/plan/executor.d.ts.map +1 -1
- package/dist/server/services/plan/executor.js +27 -14
- package/dist/server/services/plan/executor.js.map +1 -1
- package/dist/server/services/plan/front-matter.d.ts +5 -0
- package/dist/server/services/plan/front-matter.d.ts.map +1 -1
- package/dist/server/services/plan/front-matter.js +19 -0
- package/dist/server/services/plan/front-matter.js.map +1 -1
- package/dist/server/services/plan/issue-prompt-builder.d.ts +1 -1
- package/dist/server/services/plan/issue-prompt-builder.d.ts.map +1 -1
- package/dist/server/services/plan/issue-prompt-builder.js +1 -1
- package/dist/server/services/plan/issue-retry.d.ts +25 -0
- package/dist/server/services/plan/issue-retry.d.ts.map +1 -0
- package/dist/server/services/plan/issue-retry.js +216 -0
- package/dist/server/services/plan/issue-retry.js.map +1 -0
- package/dist/server/services/plan/output-manager.d.ts +2 -2
- package/dist/server/services/plan/output-manager.js +2 -2
- package/dist/server/services/plan/parser-core.d.ts +1 -1
- package/dist/server/services/plan/parser-core.js +1 -1
- package/dist/server/services/plan/parser-core.js.map +1 -1
- package/dist/server/services/plan/parser-migration.d.ts +2 -2
- package/dist/server/services/plan/parser-migration.d.ts.map +1 -1
- package/dist/server/services/plan/parser-migration.js +5 -5
- package/dist/server/services/plan/parser-migration.js.map +1 -1
- package/dist/server/services/plan/parser.d.ts.map +1 -1
- package/dist/server/services/plan/parser.js +4 -7
- package/dist/server/services/plan/parser.js.map +1 -1
- package/dist/server/services/plan/prompt-builder.d.ts +1 -1
- package/dist/server/services/plan/prompt-builder.d.ts.map +1 -1
- package/dist/server/services/plan/review-gate.d.ts +4 -0
- package/dist/server/services/plan/review-gate.d.ts.map +1 -1
- package/dist/server/services/plan/review-gate.js +90 -35
- package/dist/server/services/plan/review-gate.js.map +1 -1
- package/dist/server/services/plan/state-reconciler.d.ts.map +1 -1
- package/dist/server/services/plan/state-reconciler.js +21 -11
- package/dist/server/services/plan/state-reconciler.js.map +1 -1
- package/dist/server/services/plan/types.d.ts +2 -2
- package/dist/server/services/plan/types.d.ts.map +1 -1
- package/dist/server/services/plan/watcher.js +1 -1
- package/dist/server/services/sentry.d.ts.map +1 -1
- package/dist/server/services/sentry.js +8 -4
- package/dist/server/services/sentry.js.map +1 -1
- package/dist/server/services/websocket/deploy-handlers.d.ts +14 -0
- package/dist/server/services/websocket/deploy-handlers.d.ts.map +1 -0
- package/dist/server/services/websocket/deploy-handlers.js +409 -0
- package/dist/server/services/websocket/deploy-handlers.js.map +1 -0
- package/dist/server/services/websocket/handler.d.ts.map +1 -1
- package/dist/server/services/websocket/handler.js +12 -0
- package/dist/server/services/websocket/handler.js.map +1 -1
- package/dist/server/services/websocket/handlers/deploy-handlers.d.ts +11 -0
- package/dist/server/services/websocket/handlers/deploy-handlers.d.ts.map +1 -0
- package/dist/server/services/websocket/handlers/deploy-handlers.js +180 -0
- package/dist/server/services/websocket/handlers/deploy-handlers.js.map +1 -0
- package/dist/server/services/websocket/plan-board-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/plan-board-handlers.js +54 -1
- package/dist/server/services/websocket/plan-board-handlers.js.map +1 -1
- package/dist/server/services/websocket/plan-helpers.d.ts +1 -1
- package/dist/server/services/websocket/plan-helpers.d.ts.map +1 -1
- package/dist/server/services/websocket/plan-helpers.js +3 -4
- package/dist/server/services/websocket/plan-helpers.js.map +1 -1
- package/dist/server/services/websocket/plan-issue-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/plan-issue-handlers.js +5 -1
- package/dist/server/services/websocket/plan-issue-handlers.js.map +1 -1
- package/dist/server/services/websocket/plan-sprint-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/plan-sprint-handlers.js +3 -11
- package/dist/server/services/websocket/plan-sprint-handlers.js.map +1 -1
- package/dist/server/services/websocket/settings-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/settings-handlers.js +17 -21
- package/dist/server/services/websocket/settings-handlers.js.map +1 -1
- package/dist/server/services/websocket/types.d.ts +264 -2
- package/dist/server/services/websocket/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/server/cli/headless/claude-invoker-process.ts +1 -1
- package/server/cli/headless/headless-logger.ts +1 -1
- package/server/cli/headless/mcp-config.ts +4 -1
- package/server/cli/headless/runner.ts +1 -0
- package/server/cli/headless/types.ts +4 -1
- package/server/index.ts +9 -1
- package/server/mcp/bouncer-integration.ts +19 -17
- package/server/mcp/security-analysis.ts +19 -0
- package/server/mcp/security-patterns.ts +53 -2
- package/server/services/deploy/ai-broker.ts +512 -0
- package/server/services/deploy/board-execution-handler.ts +847 -0
- package/server/services/deploy/credentials.ts +200 -0
- package/server/services/deploy/deploy-ai-service.ts +401 -0
- package/server/services/deploy/headless-session-handler.ts +415 -0
- package/server/services/pathUtils.ts +35 -1
- package/server/services/plan/agent-loader.ts +73 -0
- package/server/services/plan/agents/review-code.md +28 -0
- package/server/services/plan/agents/review-custom.md +27 -0
- package/server/services/plan/agents/review-quality.md +42 -0
- package/server/services/plan/composer.ts +5 -1
- package/server/services/plan/dependency-resolver.ts +2 -2
- package/server/services/plan/executor.ts +27 -15
- package/server/services/plan/front-matter.ts +23 -0
- package/server/services/plan/issue-prompt-builder.ts +2 -2
- package/server/services/plan/issue-retry.ts +297 -0
- package/server/services/plan/output-manager.ts +2 -2
- package/server/services/plan/parser-core.ts +2 -2
- package/server/services/plan/parser-migration.ts +5 -5
- package/server/services/plan/parser.ts +4 -5
- package/server/services/plan/prompt-builder.ts +1 -1
- package/server/services/plan/review-gate.ts +105 -34
- package/server/services/plan/state-reconciler.ts +21 -11
- package/server/services/plan/types.ts +3 -3
- package/server/services/plan/watcher.ts +1 -1
- package/server/services/sentry.ts +8 -4
- package/server/services/websocket/deploy-handlers.ts +544 -0
- package/server/services/websocket/handler.ts +11 -1
- package/server/services/websocket/handlers/deploy-handlers.ts +230 -0
- package/server/services/websocket/plan-board-handlers.ts +53 -1
- package/server/services/websocket/plan-helpers.ts +3 -4
- package/server/services/websocket/plan-issue-handlers.ts +6 -1
- package/server/services/websocket/plan-sprint-handlers.ts +3 -9
- package/server/services/websocket/settings-handlers.ts +18 -22
- package/server/services/websocket/types.ts +333 -2
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Headless Session Handler
|
|
3
|
+
*
|
|
4
|
+
* Handles headless Claude Code session requests from a developer's backend
|
|
5
|
+
* on behalf of end users. Each session is isolated — no shared context
|
|
6
|
+
* between end users.
|
|
7
|
+
*
|
|
8
|
+
* Security: End-user prompts are untrusted input. They are always passed as
|
|
9
|
+
* user messages, never injected into system prompts or tool parameters.
|
|
10
|
+
* The Security Bouncer governs tool access within each session.
|
|
11
|
+
*/
|
|
12
|
+
import type { ToolUseEvent } from '../../cli/headless/types.js';
|
|
13
|
+
import { type DeployExecutionResult } from './deploy-ai-service.js';
|
|
14
|
+
export interface HeadlessSessionRequest {
|
|
15
|
+
/** The end user's prompt (untrusted input) */
|
|
16
|
+
prompt: string;
|
|
17
|
+
/** Override the deployment's default system prompt */
|
|
18
|
+
systemPrompt?: string;
|
|
19
|
+
/** Restrict which tools Claude can use in this session */
|
|
20
|
+
allowedTools?: string[];
|
|
21
|
+
/** Override the deployment's default model */
|
|
22
|
+
model?: string;
|
|
23
|
+
/** Unique identifier for the end user (for isolation + rate tracking) */
|
|
24
|
+
endUserId: string;
|
|
25
|
+
}
|
|
26
|
+
export interface DeploymentAiConfig {
|
|
27
|
+
deploymentId: string;
|
|
28
|
+
aiEnabled: boolean;
|
|
29
|
+
allowedAiCapabilities: string[];
|
|
30
|
+
maxTokensPerRequest: number | null;
|
|
31
|
+
maxRequestsPerMinute: number | null;
|
|
32
|
+
maxConcurrentSessions: number;
|
|
33
|
+
defaultSystemPrompt: string | null;
|
|
34
|
+
defaultModel: string;
|
|
35
|
+
workingDir: string;
|
|
36
|
+
}
|
|
37
|
+
export type HeadlessSessionErrorCode = 'CAPABILITY_DENIED' | 'AI_DISABLED' | 'RATE_LIMIT_EXCEEDED' | 'CONCURRENT_LIMIT_EXCEEDED' | 'INVALID_REQUEST' | 'EXECUTION_FAILED';
|
|
38
|
+
export interface HeadlessSessionError {
|
|
39
|
+
code: HeadlessSessionErrorCode;
|
|
40
|
+
message: string;
|
|
41
|
+
}
|
|
42
|
+
export interface HeadlessSessionStreamCallbacks {
|
|
43
|
+
onOutput?: (text: string) => void;
|
|
44
|
+
onThinking?: (text: string) => void;
|
|
45
|
+
onToolUse?: (event: ToolUseEvent) => void;
|
|
46
|
+
onUsageReport?: (report: UsageReportData) => void;
|
|
47
|
+
onHealthUpdate?: (update: HealthUpdateData) => void;
|
|
48
|
+
}
|
|
49
|
+
export interface UsageReportData {
|
|
50
|
+
deploymentId: string;
|
|
51
|
+
endUserId: string;
|
|
52
|
+
capability: 'headless' | 'pm-board';
|
|
53
|
+
tokensUsed: number;
|
|
54
|
+
model: string;
|
|
55
|
+
durationMs: number;
|
|
56
|
+
boardId?: string;
|
|
57
|
+
}
|
|
58
|
+
export interface HealthUpdateData {
|
|
59
|
+
deploymentId: string;
|
|
60
|
+
status: 'healthy' | 'invalid_key' | 'no_credits' | 'rate_limited' | 'unknown_error';
|
|
61
|
+
message: string;
|
|
62
|
+
aiDisabled: boolean;
|
|
63
|
+
}
|
|
64
|
+
export type HeadlessSessionResult = {
|
|
65
|
+
ok: true;
|
|
66
|
+
result: DeployExecutionResult;
|
|
67
|
+
} | {
|
|
68
|
+
ok: false;
|
|
69
|
+
error: HeadlessSessionError;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Handle a headless session request for an end user.
|
|
73
|
+
*
|
|
74
|
+
* Validates the deployment config, checks rate limits, composes the prompt
|
|
75
|
+
* with the system instruction, and launches an isolated headless session
|
|
76
|
+
* via DeployAiService. Streams results back through the provided callbacks.
|
|
77
|
+
*
|
|
78
|
+
* @returns Structured result with either the execution result or an error.
|
|
79
|
+
*/
|
|
80
|
+
export declare function handleHeadlessSession(request: HeadlessSessionRequest, config: DeploymentAiConfig, callbacks?: HeadlessSessionStreamCallbacks): Promise<HeadlessSessionResult>;
|
|
81
|
+
/**
|
|
82
|
+
* Get the current rate limit state for a deployment.
|
|
83
|
+
* Useful for status/monitoring endpoints.
|
|
84
|
+
*/
|
|
85
|
+
export declare function getDeploymentRateLimitState(deploymentId: string): {
|
|
86
|
+
requestsInLastMinute: number;
|
|
87
|
+
activeSessions: number;
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Reset rate limit state for a deployment. Call when a deployment
|
|
91
|
+
* is deleted or all its sessions are force-stopped.
|
|
92
|
+
*/
|
|
93
|
+
export declare function resetDeploymentRateLimit(deploymentId: string): void;
|
|
94
|
+
//# sourceMappingURL=headless-session-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headless-session-handler.d.ts","sourceRoot":"","sources":["../../../../server/services/deploy/headless-session-handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
// Copyright (c) 2025-present Mstro, Inc. All rights reserved.
|
|
2
|
+
// Licensed under the MIT License. See LICENSE file for details.
|
|
3
|
+
import { DeployAiService } from './deploy-ai-service.js';
|
|
4
|
+
const rateBuckets = new Map();
|
|
5
|
+
function getBucket(deploymentId) {
|
|
6
|
+
let bucket = rateBuckets.get(deploymentId);
|
|
7
|
+
if (!bucket) {
|
|
8
|
+
bucket = { timestamps: [], activeSessions: 0 };
|
|
9
|
+
rateBuckets.set(deploymentId, bucket);
|
|
10
|
+
}
|
|
11
|
+
return bucket;
|
|
12
|
+
}
|
|
13
|
+
function pruneTimestamps(bucket) {
|
|
14
|
+
const oneMinuteAgo = Date.now() - 60_000;
|
|
15
|
+
// Remove timestamps older than 1 minute
|
|
16
|
+
while (bucket.timestamps.length > 0 && bucket.timestamps[0] < oneMinuteAgo) {
|
|
17
|
+
bucket.timestamps.shift();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function checkRateLimit(config) {
|
|
21
|
+
const bucket = getBucket(config.deploymentId);
|
|
22
|
+
// Check concurrent sessions
|
|
23
|
+
if (bucket.activeSessions >= config.maxConcurrentSessions) {
|
|
24
|
+
return {
|
|
25
|
+
code: 'CONCURRENT_LIMIT_EXCEEDED',
|
|
26
|
+
message: `Deployment has reached the maximum of ${config.maxConcurrentSessions} concurrent sessions. Wait for an existing session to complete.`,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
// Check requests per minute
|
|
30
|
+
if (config.maxRequestsPerMinute !== null) {
|
|
31
|
+
pruneTimestamps(bucket);
|
|
32
|
+
if (bucket.timestamps.length >= config.maxRequestsPerMinute) {
|
|
33
|
+
return {
|
|
34
|
+
code: 'RATE_LIMIT_EXCEEDED',
|
|
35
|
+
message: `Deployment has exceeded the rate limit of ${config.maxRequestsPerMinute} requests per minute. Try again shortly.`,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
function recordRequestStart(deploymentId) {
|
|
42
|
+
const bucket = getBucket(deploymentId);
|
|
43
|
+
bucket.timestamps.push(Date.now());
|
|
44
|
+
bucket.activeSessions++;
|
|
45
|
+
}
|
|
46
|
+
function recordRequestEnd(deploymentId) {
|
|
47
|
+
const bucket = getBucket(deploymentId);
|
|
48
|
+
bucket.activeSessions = Math.max(0, bucket.activeSessions - 1);
|
|
49
|
+
}
|
|
50
|
+
// ========== Prompt Composition ==========
|
|
51
|
+
/**
|
|
52
|
+
* Compose the final prompt sent to Claude. The system prompt (from deployment
|
|
53
|
+
* config or per-request override) is prepended as a system instruction block.
|
|
54
|
+
* The end-user prompt follows as a clearly delimited user message.
|
|
55
|
+
*
|
|
56
|
+
* SECURITY: The end-user prompt is always in the user-message section,
|
|
57
|
+
* never interpolated into the system instruction.
|
|
58
|
+
*/
|
|
59
|
+
function composePrompt(systemPrompt, userPrompt) {
|
|
60
|
+
if (!systemPrompt) {
|
|
61
|
+
return userPrompt;
|
|
62
|
+
}
|
|
63
|
+
return [
|
|
64
|
+
'<system-instruction>',
|
|
65
|
+
systemPrompt,
|
|
66
|
+
'</system-instruction>',
|
|
67
|
+
'',
|
|
68
|
+
userPrompt,
|
|
69
|
+
].join('\n');
|
|
70
|
+
}
|
|
71
|
+
// ========== Handler ==========
|
|
72
|
+
/**
|
|
73
|
+
* Handle a headless session request for an end user.
|
|
74
|
+
*
|
|
75
|
+
* Validates the deployment config, checks rate limits, composes the prompt
|
|
76
|
+
* with the system instruction, and launches an isolated headless session
|
|
77
|
+
* via DeployAiService. Streams results back through the provided callbacks.
|
|
78
|
+
*
|
|
79
|
+
* @returns Structured result with either the execution result or an error.
|
|
80
|
+
*/
|
|
81
|
+
export async function handleHeadlessSession(request, config, callbacks) {
|
|
82
|
+
// ── Validate request ───────────────────────────────────────
|
|
83
|
+
if (!request.prompt || request.prompt.trim().length === 0) {
|
|
84
|
+
return {
|
|
85
|
+
ok: false,
|
|
86
|
+
error: { code: 'INVALID_REQUEST', message: 'prompt is required and must not be empty.' },
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
if (!request.endUserId || request.endUserId.trim().length === 0) {
|
|
90
|
+
return {
|
|
91
|
+
ok: false,
|
|
92
|
+
error: { code: 'INVALID_REQUEST', message: 'endUserId is required.' },
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
// ── Validate AI is enabled ─────────────────────────────────
|
|
96
|
+
if (!config.aiEnabled) {
|
|
97
|
+
return {
|
|
98
|
+
ok: false,
|
|
99
|
+
error: { code: 'AI_DISABLED', message: 'AI features are not enabled for this deployment.' },
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
// ── Validate headless capability ───────────────────────────
|
|
103
|
+
if (!config.allowedAiCapabilities.includes('headless')) {
|
|
104
|
+
return {
|
|
105
|
+
ok: false,
|
|
106
|
+
error: {
|
|
107
|
+
code: 'CAPABILITY_DENIED',
|
|
108
|
+
message: "This deployment does not have the 'headless' AI capability enabled.",
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
// ── Rate limit checks ─────────────────────────────────────
|
|
113
|
+
const rateLimitError = checkRateLimit(config);
|
|
114
|
+
if (rateLimitError) {
|
|
115
|
+
return { ok: false, error: rateLimitError };
|
|
116
|
+
}
|
|
117
|
+
// ── Token limit pre-check ─────────────────────────────────
|
|
118
|
+
// Estimate input tokens from prompt length (~4 chars per token).
|
|
119
|
+
// Reject if estimated input alone exceeds the cap.
|
|
120
|
+
if (config.maxTokensPerRequest !== null) {
|
|
121
|
+
const estimatedInputTokens = Math.ceil(request.prompt.length / 4);
|
|
122
|
+
if (estimatedInputTokens > config.maxTokensPerRequest) {
|
|
123
|
+
return {
|
|
124
|
+
ok: false,
|
|
125
|
+
error: {
|
|
126
|
+
code: 'RATE_LIMIT_EXCEEDED',
|
|
127
|
+
message: `Estimated input tokens (${estimatedInputTokens}) exceeds maxTokensPerRequest (${config.maxTokensPerRequest}). Shorten your prompt.`,
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// ── Compose prompt ─────────────────────────────────────────
|
|
133
|
+
// Use per-request system prompt if provided, otherwise deployment default
|
|
134
|
+
const effectiveSystemPrompt = request.systemPrompt ?? config.defaultSystemPrompt;
|
|
135
|
+
const composedPrompt = composePrompt(effectiveSystemPrompt, request.prompt);
|
|
136
|
+
// Use per-request model if provided, otherwise deployment default
|
|
137
|
+
const effectiveModel = request.model ?? config.defaultModel;
|
|
138
|
+
// ── Launch isolated session ────────────────────────────────
|
|
139
|
+
const service = DeployAiService.getInstance();
|
|
140
|
+
recordRequestStart(config.deploymentId);
|
|
141
|
+
try {
|
|
142
|
+
const result = await service.execute({
|
|
143
|
+
deploymentId: config.deploymentId,
|
|
144
|
+
prompt: composedPrompt,
|
|
145
|
+
workingDir: config.workingDir,
|
|
146
|
+
model: effectiveModel,
|
|
147
|
+
outputCallback: callbacks?.onOutput,
|
|
148
|
+
thinkingCallback: callbacks?.onThinking,
|
|
149
|
+
toolUseCallback: callbacks?.onToolUse,
|
|
150
|
+
// allowedTools from request are inverted: any tool NOT in the list is disallowed.
|
|
151
|
+
// If allowedTools is not specified, no additional restrictions are applied
|
|
152
|
+
// (Security Bouncer still governs tool access).
|
|
153
|
+
disallowedTools: request.allowedTools
|
|
154
|
+
? invertAllowedTools(request.allowedTools)
|
|
155
|
+
: undefined,
|
|
156
|
+
});
|
|
157
|
+
// Check token limit if configured
|
|
158
|
+
if (config.maxTokensPerRequest !== null &&
|
|
159
|
+
result.totalTokens > config.maxTokensPerRequest) {
|
|
160
|
+
// Session already ran — log but don't fail the response.
|
|
161
|
+
// The token overage is informational; the developer can use this
|
|
162
|
+
// for billing or to tighten limits.
|
|
163
|
+
}
|
|
164
|
+
// Emit usage report after successful execution
|
|
165
|
+
callbacks?.onUsageReport?.({
|
|
166
|
+
deploymentId: config.deploymentId,
|
|
167
|
+
endUserId: request.endUserId,
|
|
168
|
+
capability: 'headless',
|
|
169
|
+
tokensUsed: result.totalTokens,
|
|
170
|
+
model: effectiveModel,
|
|
171
|
+
durationMs: result.durationMs,
|
|
172
|
+
});
|
|
173
|
+
// Check for API key health issues from execution result
|
|
174
|
+
const healthStatus = detectAiHealthIssue(result.error);
|
|
175
|
+
if (healthStatus) {
|
|
176
|
+
callbacks?.onHealthUpdate?.({
|
|
177
|
+
deploymentId: config.deploymentId,
|
|
178
|
+
...healthStatus,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
return { ok: true, result };
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
185
|
+
// Check for API key health issues from caught errors
|
|
186
|
+
const healthStatus = detectAiHealthIssue(message);
|
|
187
|
+
if (healthStatus) {
|
|
188
|
+
callbacks?.onHealthUpdate?.({
|
|
189
|
+
deploymentId: config.deploymentId,
|
|
190
|
+
...healthStatus,
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
return {
|
|
194
|
+
ok: false,
|
|
195
|
+
error: { code: 'EXECUTION_FAILED', message },
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
finally {
|
|
199
|
+
recordRequestEnd(config.deploymentId);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
// ========== Health Detection ==========
|
|
203
|
+
/**
|
|
204
|
+
* Detect API key health issues from error messages returned by Claude Code.
|
|
205
|
+
*
|
|
206
|
+
* Anthropic API errors that indicate credential/billing problems:
|
|
207
|
+
* - 401: Invalid API key
|
|
208
|
+
* - 402/insufficient_funds: Account has no credits
|
|
209
|
+
* - 429: Rate limited by Anthropic
|
|
210
|
+
*/
|
|
211
|
+
function detectAiHealthIssue(errorMessage) {
|
|
212
|
+
if (!errorMessage)
|
|
213
|
+
return null;
|
|
214
|
+
const lower = errorMessage.toLowerCase();
|
|
215
|
+
if (lower.includes('invalid api key') || lower.includes('invalid x-api-key') || lower.includes('authentication_error')) {
|
|
216
|
+
return { status: 'invalid_key', message: 'Anthropic API key is invalid or revoked.', aiDisabled: true };
|
|
217
|
+
}
|
|
218
|
+
if (lower.includes('insufficient_funds') || lower.includes('no credits') || lower.includes('billing') || lower.includes('credit balance')) {
|
|
219
|
+
return { status: 'no_credits', message: 'Anthropic account has insufficient credits.', aiDisabled: true };
|
|
220
|
+
}
|
|
221
|
+
if (lower.includes('rate_limit') || lower.includes('rate limit') || lower.includes('too many requests')) {
|
|
222
|
+
return { status: 'rate_limited', message: 'Anthropic API rate limit exceeded.', aiDisabled: false };
|
|
223
|
+
}
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
// ========== Helpers ==========
|
|
227
|
+
/**
|
|
228
|
+
* The DeployAiService accepts `disallowedTools` (blocklist), but the
|
|
229
|
+
* headless session API exposes `allowedTools` (allowlist) for a better
|
|
230
|
+
* developer UX. This converts an allowlist into a blocklist by marking
|
|
231
|
+
* everything outside the allowlist as disallowed.
|
|
232
|
+
*
|
|
233
|
+
* We use a known set of standard Claude Code tool names. Tools not in
|
|
234
|
+
* the known set are left unrestricted (the Security Bouncer handles them).
|
|
235
|
+
*/
|
|
236
|
+
const KNOWN_TOOLS = [
|
|
237
|
+
'Read',
|
|
238
|
+
'Write',
|
|
239
|
+
'Edit',
|
|
240
|
+
'MultiEdit',
|
|
241
|
+
'Bash',
|
|
242
|
+
'Glob',
|
|
243
|
+
'Grep',
|
|
244
|
+
'WebFetch',
|
|
245
|
+
'WebSearch',
|
|
246
|
+
'TodoRead',
|
|
247
|
+
'TodoWrite',
|
|
248
|
+
'NotebookEdit',
|
|
249
|
+
'Agent',
|
|
250
|
+
];
|
|
251
|
+
function invertAllowedTools(allowedTools) {
|
|
252
|
+
const allowed = new Set(allowedTools);
|
|
253
|
+
return KNOWN_TOOLS.filter((tool) => !allowed.has(tool));
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Get the current rate limit state for a deployment.
|
|
257
|
+
* Useful for status/monitoring endpoints.
|
|
258
|
+
*/
|
|
259
|
+
export function getDeploymentRateLimitState(deploymentId) {
|
|
260
|
+
const bucket = getBucket(deploymentId);
|
|
261
|
+
pruneTimestamps(bucket);
|
|
262
|
+
return {
|
|
263
|
+
requestsInLastMinute: bucket.timestamps.length,
|
|
264
|
+
activeSessions: bucket.activeSessions,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Reset rate limit state for a deployment. Call when a deployment
|
|
269
|
+
* is deleted or all its sessions are force-stopped.
|
|
270
|
+
*/
|
|
271
|
+
export function resetDeploymentRateLimit(deploymentId) {
|
|
272
|
+
rateBuckets.delete(deploymentId);
|
|
273
|
+
}
|
|
274
|
+
//# sourceMappingURL=headless-session-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headless-session-handler.js","sourceRoot":"","sources":["../../../../server/services/deploy/headless-session-handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pathUtils.d.ts","sourceRoot":"","sources":["../../../server/services/pathUtils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pathUtils.d.ts","sourceRoot":"","sources":["../../../server/services/pathUtils.ts"],"names":[],"mappings":"AAaA,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,CAqFtB;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"}
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
* Secure path validation utilities to prevent path traversal attacks.
|
|
7
7
|
* All file explorer operations MUST validate paths through these functions.
|
|
8
8
|
*/
|
|
9
|
-
import {
|
|
9
|
+
import { existsSync, lstatSync, realpathSync } from 'node:fs';
|
|
10
|
+
import { dirname, isAbsolute, normalize, relative, resolve } from 'node:path';
|
|
10
11
|
/**
|
|
11
12
|
* Validate that a path is within the allowed working directory.
|
|
12
13
|
* Prevents path traversal attacks using .. or absolute paths.
|
|
@@ -29,6 +30,37 @@ export function validatePathWithinWorkingDir(targetPath, workingDir) {
|
|
|
29
30
|
}
|
|
30
31
|
// Normalize to remove any .. or . segments
|
|
31
32
|
resolvedPath = normalize(resolvedPath);
|
|
33
|
+
// Resolve symlinks to prevent symlink-based path traversal.
|
|
34
|
+
// A symlink at /project/link -> /etc/passwd would pass the string
|
|
35
|
+
// check below but actually read outside the working directory.
|
|
36
|
+
// For existing paths: resolve the full path via realpath.
|
|
37
|
+
// For new paths (create operations): resolve the parent directory.
|
|
38
|
+
if (existsSync(resolvedPath)) {
|
|
39
|
+
// If the path itself is a symlink, resolve it to the real target
|
|
40
|
+
const stat = lstatSync(resolvedPath);
|
|
41
|
+
if (stat.isSymbolicLink()) {
|
|
42
|
+
resolvedPath = realpathSync(resolvedPath);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
// Path doesn't exist yet (create operation) — validate the parent
|
|
47
|
+
const parentDir = dirname(resolvedPath);
|
|
48
|
+
if (existsSync(parentDir)) {
|
|
49
|
+
const realParent = realpathSync(parentDir);
|
|
50
|
+
const parentWithSep = normalizedWorkingDir.endsWith('/')
|
|
51
|
+
? normalizedWorkingDir
|
|
52
|
+
: `${normalizedWorkingDir}/`;
|
|
53
|
+
if (realParent !== normalizedWorkingDir && !realParent.startsWith(parentWithSep)) {
|
|
54
|
+
console.error(`[PathUtils] SECURITY: Symlink traversal in parent directory blocked. ` +
|
|
55
|
+
`Target: "${targetPath}", RealParent: "${realParent}", WorkingDir: "${normalizedWorkingDir}"`);
|
|
56
|
+
return {
|
|
57
|
+
valid: false,
|
|
58
|
+
resolvedPath: '',
|
|
59
|
+
error: 'Access denied: parent directory resolves outside working directory'
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
32
64
|
// Check if the resolved path starts with the working directory
|
|
33
65
|
// Add trailing separator to prevent partial matches (e.g., /home/user vs /home/username)
|
|
34
66
|
const workingDirWithSep = normalizedWorkingDir.endsWith('/')
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pathUtils.js","sourceRoot":"","sources":["../../../server/services/pathUtils.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,gEAAgE;AAEhE;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"pathUtils.js","sourceRoot":"","sources":["../../../server/services/pathUtils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Load an agent prompt by name with layered resolution.
|
|
3
|
+
*
|
|
4
|
+
* @param agentName - The agent file name without extension (e.g., "review-code")
|
|
5
|
+
* @param variables - Key-value map for {{variable}} substitution
|
|
6
|
+
* @param boardDir - Optional board directory for board-level overrides
|
|
7
|
+
* @returns The interpolated prompt string, or null if no agent file found
|
|
8
|
+
*/
|
|
9
|
+
export declare function loadAgentPrompt(agentName: string, variables: Record<string, string>, boardDir?: string | null): string | null;
|
|
10
|
+
//# sourceMappingURL=agent-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-loader.d.ts","sourceRoot":"","sources":["../../../../server/services/plan/agent-loader.ts"],"names":[],"mappings":"AAoCA;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACjC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,GACvB,MAAM,GAAG,IAAI,CAwBf"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// Copyright (c) 2025-present Mstro, Inc. All rights reserved.
|
|
2
|
+
// Licensed under the MIT License. See LICENSE file for details.
|
|
3
|
+
/**
|
|
4
|
+
* Agent Prompt Loader — loads review agent prompts from markdown files.
|
|
5
|
+
*
|
|
6
|
+
* Resolution order (first match wins):
|
|
7
|
+
* 1. Board-level override: {boardDir}/agents/{agentName}.md
|
|
8
|
+
* 2. System default: cli/server/services/plan/agents/{agentName}.md
|
|
9
|
+
*
|
|
10
|
+
* Files use YAML frontmatter + markdown body with {{variable}} placeholders.
|
|
11
|
+
* Falls back to null when no file is found (caller should use hardcoded fallback).
|
|
12
|
+
*/
|
|
13
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
14
|
+
import { dirname, join } from 'node:path';
|
|
15
|
+
import { fileURLToPath } from 'node:url';
|
|
16
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
17
|
+
const SYSTEM_AGENTS_DIR = join(__dirname, 'agents');
|
|
18
|
+
/** Strip YAML frontmatter (--- ... ---) from markdown, returning just the body. */
|
|
19
|
+
function stripFrontmatter(content) {
|
|
20
|
+
if (!content.startsWith('---'))
|
|
21
|
+
return content;
|
|
22
|
+
const endIdx = content.indexOf('---', 3);
|
|
23
|
+
if (endIdx === -1)
|
|
24
|
+
return content;
|
|
25
|
+
return content.slice(endIdx + 3).trimStart();
|
|
26
|
+
}
|
|
27
|
+
/** Replace all {{variable}} placeholders with values from the provided map. */
|
|
28
|
+
function interpolate(template, variables) {
|
|
29
|
+
return template.replace(/\{\{(\w+)\}\}/g, (match, key) => {
|
|
30
|
+
return key in variables ? variables[key] : match;
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Load an agent prompt by name with layered resolution.
|
|
35
|
+
*
|
|
36
|
+
* @param agentName - The agent file name without extension (e.g., "review-code")
|
|
37
|
+
* @param variables - Key-value map for {{variable}} substitution
|
|
38
|
+
* @param boardDir - Optional board directory for board-level overrides
|
|
39
|
+
* @returns The interpolated prompt string, or null if no agent file found
|
|
40
|
+
*/
|
|
41
|
+
export function loadAgentPrompt(agentName, variables, boardDir) {
|
|
42
|
+
const fileName = `${agentName}.md`;
|
|
43
|
+
// 1. Board-level override
|
|
44
|
+
if (boardDir) {
|
|
45
|
+
const boardAgentPath = join(boardDir, 'agents', fileName);
|
|
46
|
+
if (existsSync(boardAgentPath)) {
|
|
47
|
+
try {
|
|
48
|
+
const raw = readFileSync(boardAgentPath, 'utf-8');
|
|
49
|
+
return interpolate(stripFrontmatter(raw), variables);
|
|
50
|
+
}
|
|
51
|
+
catch { /* fall through to system default */ }
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// 2. System default
|
|
55
|
+
const systemPath = join(SYSTEM_AGENTS_DIR, fileName);
|
|
56
|
+
if (existsSync(systemPath)) {
|
|
57
|
+
try {
|
|
58
|
+
const raw = readFileSync(systemPath, 'utf-8');
|
|
59
|
+
return interpolate(stripFrontmatter(raw), variables);
|
|
60
|
+
}
|
|
61
|
+
catch { /* return null */ }
|
|
62
|
+
}
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=agent-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-loader.js","sourceRoot":"","sources":["../../../../server/services/plan/agent-loader.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,gEAAgE;AAEhE;;;;;;;;;GASG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,iBAAiB,GAAG,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AAEpD,mFAAmF;AACnF,SAAS,gBAAgB,CAAC,OAAe;IACvC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC;IAC/C,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACzC,IAAI,MAAM,KAAK,CAAC,CAAC;QAAE,OAAO,OAAO,CAAC;IAClC,OAAO,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;AAC/C,CAAC;AAED,+EAA+E;AAC/E,SAAS,WAAW,CAAC,QAAgB,EAAE,SAAiC;IACtE,OAAO,QAAQ,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC,KAAK,EAAE,GAAW,EAAE,EAAE;QAC/D,OAAO,GAAG,IAAI,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACnD,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAC7B,SAAiB,EACjB,SAAiC,EACjC,QAAwB;IAExB,MAAM,QAAQ,GAAG,GAAG,SAAS,KAAK,CAAC;IAEnC,0BAA0B;IAC1B,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,cAAc,GAAG,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC1D,IAAI,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;YAC/B,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,YAAY,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;gBAClD,OAAO,WAAW,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,SAAS,CAAC,CAAC;YACvD,CAAC;YAAC,MAAM,CAAC,CAAC,oCAAoC,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IAED,oBAAoB;IACpB,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC;IACrD,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YAC9C,OAAO,WAAW,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,SAAS,CAAC,CAAC;QACvD,CAAC;QAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"composer.d.ts","sourceRoot":"","sources":["../../../../server/services/plan/composer.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AA6GvD,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,cAAc,EACnB,EAAE,EAAE,SAAS,EACb,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"composer.d.ts","sourceRoot":"","sources":["../../../../server/services/plan/composer.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AA6GvD,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,cAAc,EACnB,EAAE,EAAE,SAAS,EACb,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAgLf"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Plan Composer — Handles natural language prompts for PPS creation/editing.
|
|
5
5
|
*
|
|
6
6
|
* When a planPrompt message arrives, this builds a context-enriched prompt
|
|
7
|
-
* against the .pm/
|
|
7
|
+
* against the .mstro/pm/ directory and spawns a scoped
|
|
8
8
|
* HeadlessRunner session to execute it.
|
|
9
9
|
*/
|
|
10
10
|
import { existsSync, readFileSync } from 'node:fs';
|
|
@@ -214,6 +214,10 @@ User request: ${userPrompt}`;
|
|
|
214
214
|
const runner = new HeadlessRunner({
|
|
215
215
|
workingDir,
|
|
216
216
|
directPrompt: enrichedPrompt,
|
|
217
|
+
stallWarningMs: 300_000, // 5 min — compose usually finishes quickly
|
|
218
|
+
stallKillMs: 900_000, // 15 min
|
|
219
|
+
stallHardCapMs: 1_800_000, // 30 min hard cap
|
|
220
|
+
verbose: true,
|
|
217
221
|
outputCallback: (text) => {
|
|
218
222
|
ctx.send(ws, {
|
|
219
223
|
type: 'planPromptStreaming',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"composer.js","sourceRoot":"","sources":["../../../../server/services/plan/composer.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"composer.js","sourceRoot":"","sources":["../../../../server/services/plan/composer.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,gEAAgE;AAEhE;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAqB,MAAM,6BAA6B,CAAC;AAGhF,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG7G,MAAM,oBAAoB,GAA2B;IACnD,IAAI,EAAE,8BAA8B;IACpC,IAAI,EAAE,8BAA8B;IACpC,IAAI,EAAE,uBAAuB;IAC7B,KAAK,EAAE,2BAA2B;IAClC,IAAI,EAAE,2BAA2B;IACjC,IAAI,EAAE,qBAAqB;CAC5B,CAAC;AAEF,SAAS,4BAA4B,CAAC,KAAmB;IACvD,MAAM,KAAK,GAAG,KAAK,CAAC,aAAa,CAAC;IAClC,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,IAAI,KAAK,CAAC,QAAQ,KAAK,OAAO,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QAClD,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;QAChE,OAAO,WAAW,QAAQ,EAAE,CAAC;IAC/B,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,KAAK,MAAM,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QACjD,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;QAChE,OAAO,WAAW,QAAQ,EAAE,CAAC;IAC/B,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,KAAK,MAAM,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QACjD,OAAO,QAAQ,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IAC1E,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,2BAA2B;IAClC,MAAM,cAAc,GAAG,IAAI,GAAG,EAAU,CAAC;IAEzC,OAAO,CAAC,KAAmB,EAAiB,EAAE;QAC5C,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YAClD,IAAI,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC;gBAAE,OAAO,IAAI,CAAC;YACpD,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YACnC,OAAO,oBAAoB,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC;QACtD,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,eAAe;YAAE,OAAO,4BAA4B,CAAC,KAAK,CAAC,CAAC;QAC/E,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,IAAY;IACnC,IAAI,CAAC;QACH,IAAI,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;IACtB,OAAO,EAAE,CAAC;AACZ,CAAC;AAcD,SAAS,oBAAoB,CAAC,KAAa,EAAE,UAAkB,EAAE,OAAgB;IAC/E,MAAM,SAAS,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;IACjD,MAAM,gBAAgB,GAAG,OAAO,IAAI,SAAS,EAAE,SAAS,EAAE,aAAa,IAAI,IAAI,CAAC;IAEhF,IAAI,YAAY,GAAG,EAAE,CAAC;IACtB,IAAI,YAAY,GAAG,EAAE,CAAC;IACtB,IAAI,MAAM,GAAY,EAAE,CAAC;IAEzB,IAAI,gBAAgB,EAAE,CAAC;QACrB,MAAM,UAAU,GAAG,mBAAmB,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;QAChE,IAAI,UAAU,EAAE,CAAC;YACf,YAAY,GAAG,eAAe,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,UAAU,CAAC,CAAC,CAAC;YACpF,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;YAC3B,YAAY,GAAG,mBAAmB,gBAAgB,OAAO,UAAU,CAAC,KAAK,CAAC,KAAK;gBACrE,UAAU,CAAC,KAAK,CAAC,MAAM;cACzB,UAAU,CAAC,KAAK,CAAC,IAAI,IAAI,YAAY;mBAChC,KAAK,WAAW,gBAAgB;qBAC9B,KAAK,WAAW,gBAAgB,aAAa,CAAC;QAC/D,CAAC;IACH,CAAC;IAED,IAAI,CAAC,YAAY;QAAE,YAAY,GAAG,eAAe,CAAC,IAAI,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC;IAC3E,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,SAAS;QAAE,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC;IAEhE,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,SAAS,CAAC;QAC7C,CAAC,CAAC,uBAAuB,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE;QAC1G,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;IAC5D,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,GAAG,CAAC;QAC1C,CAAC,CAAC,sBAAsB,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,IAAI,eAAe,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;QAClI,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;IAC5D,MAAM,aAAa,GAAG,aAAa,CAAC,MAAM,GAAG,CAAC;QAC5C,CAAC,CAAC,qCAAqC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,MAAM,OAAO,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;QACpI,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,QAAQ,GAAG,gBAAgB,CAAC,CAAC,CAAC,UAAU,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACtE,MAAM,WAAW,GAAG,gBAAgB;QAClC,CAAC,CAAC,GAAG,KAAK,WAAW,gBAAgB,WAAW;QAChD,CAAC,CAAC,GAAG,KAAK,WAAW,CAAC;IAExB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,EAAE,gBAAgB,EAAE,CAAC;AAC7H,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,GAAmB,EACnB,EAAa,EACb,UAAkB,EAClB,UAAkB,EAClB,OAAgB;IAEhB,MAAM,KAAK,GAAG,YAAY,CAAC,UAAU,CAAC,IAAI,YAAY,CAAC,UAAU,CAAC,CAAC;IACnE,MAAM,cAAc,GAAG,eAAe,CAAC,IAAI,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC;IAClE,MAAM,EAAE,GAAG,oBAAoB,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IAE5D,MAAM,cAAc,GAAG;;EAEvB,EAAE,CAAC,YAAY;;EAEf,EAAE,CAAC,YAAY,IAAI,wBAAwB;;;;EAI3C,cAAc,IAAI,mBAAmB;;;EAGrC,EAAE,CAAC,MAAM;EACT,EAAE,CAAC,WAAW;EACd,EAAE,CAAC,aAAa;;;;;EAKhB,KAAK;;;;UAIG,EAAE,CAAC,gBAAgB,IAAI,WAAW;;;;;;;;;;;;;;6CAcC,EAAE,CAAC,WAAW;;;6DAGE,KAAK,IAAI,EAAE,CAAC,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8BAwDnD,EAAE,CAAC,WAAW;;;;;;;;gBAQ5B,UAAU,EAAE,CAAC;IAE3B,IAAI,CAAC;QACH,GAAG,CAAC,cAAc,CAAC;YACjB,IAAI,EAAE,oBAAoB;YAC1B,IAAI,EAAE,EAAE,OAAO,EAAE,8BAA8B,EAAE;SAClD,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,IAAI,cAAc,CAAC;YAChC,UAAU;YACV,YAAY,EAAE,cAAc;YAC5B,cAAc,EAAE,OAAO,EAAI,2CAA2C;YACtE,WAAW,EAAE,OAAO,EAAO,SAAS;YACpC,cAAc,EAAE,SAAS,EAAE,kBAAkB;YAC7C,OAAO,EAAE,IAAI;YACb,cAAc,EAAE,CAAC,IAAY,EAAE,EAAE;gBAC/B,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE;oBACX,IAAI,EAAE,qBAAqB;oBAC3B,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE;iBACtB,CAAC,CAAC;YACL,CAAC;YACD,eAAe,EAAE,CAAC,GAAG,EAAE;gBACrB,MAAM,kBAAkB,GAAG,2BAA2B,EAAE,CAAC;gBACzD,OAAO,CAAC,KAAmB,EAAE,EAAE;oBAC7B,MAAM,OAAO,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;oBAC1C,IAAI,OAAO,EAAE,CAAC;wBACZ,GAAG,CAAC,cAAc,CAAC;4BACjB,IAAI,EAAE,oBAAoB;4BAC1B,IAAI,EAAE,EAAE,OAAO,EAAE;yBAClB,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC,CAAC;YACJ,CAAC,CAAC,EAAE;SACL,CAAC,CAAC;QAEH,GAAG,CAAC,cAAc,CAAC;YACjB,IAAI,EAAE,oBAAoB;YAC1B,IAAI,EAAE,EAAE,OAAO,EAAE,oCAAoC,EAAE;SACxD,CAAC,CAAC;QAEH,MAAM,WAAW,GAAG,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACzG,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,YAAY,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,WAAW,CAAC,CAAC;QAEtF,GAAG,CAAC,cAAc,CAAC;YACjB,IAAI,EAAE,oBAAoB;YAC1B,IAAI,EAAE,EAAE,OAAO,EAAE,4BAA4B,EAAE;SAChD,CAAC,CAAC;QAEH,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE;YACX,IAAI,EAAE,oBAAoB;YAC1B,IAAI,EAAE;gBACJ,QAAQ,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,IAAI,eAAe,CAAC;gBAChG,OAAO,EAAE,MAAM,CAAC,SAAS;gBACzB,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,IAAI;aAC5B;SACF,CAAC,CAAC;QAEH,uCAAuC;QACvC,MAAM,YAAY,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;QACpD,IAAI,YAAY,EAAE,CAAC;YACjB,GAAG,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE;YACX,IAAI,EAAE,WAAW;YACjB,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;SACxE,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
|
|
@@ -14,7 +14,7 @@ export declare function detectCycles(issues: Issue[]): string[] | null;
|
|
|
14
14
|
* Compute the set of issues that are ready to work on.
|
|
15
15
|
* An issue is ready if:
|
|
16
16
|
* - It's not an epic
|
|
17
|
-
* - Its status is
|
|
17
|
+
* - Its status is todo (refined and ready for execution)
|
|
18
18
|
* - All its blocked_by items are done or cancelled
|
|
19
19
|
*
|
|
20
20
|
* If epicScope is provided, only returns issues belonging to that epic.
|
|
@@ -59,7 +59,7 @@ function dfs(path, issueByPath, color, parent) {
|
|
|
59
59
|
* Compute the set of issues that are ready to work on.
|
|
60
60
|
* An issue is ready if:
|
|
61
61
|
* - It's not an epic
|
|
62
|
-
* - Its status is
|
|
62
|
+
* - Its status is todo (refined and ready for execution)
|
|
63
63
|
* - All its blocked_by items are done or cancelled
|
|
64
64
|
*
|
|
65
65
|
* If epicScope is provided, only returns issues belonging to that epic.
|
|
@@ -69,7 +69,7 @@ export function resolveReadyToWork(issues, epicScope, sprintScope) {
|
|
|
69
69
|
for (const issue of issues) {
|
|
70
70
|
issueByPath.set(issue.path, issue);
|
|
71
71
|
}
|
|
72
|
-
const readyStatuses = new Set(['
|
|
72
|
+
const readyStatuses = new Set(['todo']);
|
|
73
73
|
const doneStatuses = new Set(['done', 'cancelled']);
|
|
74
74
|
const priorityOrder = { P0: 0, P1: 1, P2: 2, P3: 3 };
|
|
75
75
|
// Build set of child paths for epic scoping
|