mstro-app 0.1.58 → 0.2.0
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 +27 -14
- package/bin/commands/logout.js +35 -1
- package/bin/commands/status.js +1 -1
- package/bin/mstro.js +5 -108
- package/dist/server/cli/headless/claude-invoker.d.ts.map +1 -1
- package/dist/server/cli/headless/claude-invoker.js +432 -103
- package/dist/server/cli/headless/claude-invoker.js.map +1 -1
- package/dist/server/cli/headless/index.d.ts +2 -1
- 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/prompt-utils.d.ts +5 -8
- package/dist/server/cli/headless/prompt-utils.d.ts.map +1 -1
- package/dist/server/cli/headless/prompt-utils.js +40 -5
- package/dist/server/cli/headless/prompt-utils.js.map +1 -1
- package/dist/server/cli/headless/runner.d.ts +1 -1
- package/dist/server/cli/headless/runner.d.ts.map +1 -1
- package/dist/server/cli/headless/runner.js +29 -7
- package/dist/server/cli/headless/runner.js.map +1 -1
- package/dist/server/cli/headless/stall-assessor.d.ts +77 -1
- package/dist/server/cli/headless/stall-assessor.d.ts.map +1 -1
- package/dist/server/cli/headless/stall-assessor.js +336 -20
- package/dist/server/cli/headless/stall-assessor.js.map +1 -1
- package/dist/server/cli/headless/tool-watchdog.d.ts +67 -0
- package/dist/server/cli/headless/tool-watchdog.d.ts.map +1 -0
- package/dist/server/cli/headless/tool-watchdog.js +296 -0
- package/dist/server/cli/headless/tool-watchdog.js.map +1 -0
- package/dist/server/cli/headless/types.d.ts +80 -1
- package/dist/server/cli/headless/types.d.ts.map +1 -1
- package/dist/server/cli/improvisation-session-manager.d.ts +109 -2
- package/dist/server/cli/improvisation-session-manager.d.ts.map +1 -1
- package/dist/server/cli/improvisation-session-manager.js +737 -132
- package/dist/server/cli/improvisation-session-manager.js.map +1 -1
- package/dist/server/index.js +5 -10
- package/dist/server/index.js.map +1 -1
- package/dist/server/mcp/bouncer-integration.d.ts.map +1 -1
- package/dist/server/mcp/bouncer-integration.js +18 -0
- package/dist/server/mcp/bouncer-integration.js.map +1 -1
- package/dist/server/mcp/security-audit.d.ts +2 -2
- package/dist/server/mcp/security-audit.d.ts.map +1 -1
- package/dist/server/mcp/security-audit.js +12 -8
- package/dist/server/mcp/security-audit.js.map +1 -1
- package/dist/server/mcp/security-patterns.d.ts.map +1 -1
- package/dist/server/mcp/security-patterns.js +9 -4
- package/dist/server/mcp/security-patterns.js.map +1 -1
- package/dist/server/routes/improvise.js +6 -6
- package/dist/server/routes/improvise.js.map +1 -1
- package/dist/server/services/analytics.d.ts +2 -0
- package/dist/server/services/analytics.d.ts.map +1 -1
- package/dist/server/services/analytics.js +13 -3
- package/dist/server/services/analytics.js.map +1 -1
- package/dist/server/services/platform.d.ts.map +1 -1
- package/dist/server/services/platform.js +4 -9
- package/dist/server/services/platform.js.map +1 -1
- package/dist/server/services/sandbox-utils.d.ts +6 -0
- package/dist/server/services/sandbox-utils.d.ts.map +1 -0
- package/dist/server/services/sandbox-utils.js +72 -0
- package/dist/server/services/sandbox-utils.js.map +1 -0
- package/dist/server/services/settings.d.ts +6 -0
- package/dist/server/services/settings.d.ts.map +1 -1
- package/dist/server/services/settings.js +21 -0
- package/dist/server/services/settings.js.map +1 -1
- package/dist/server/services/terminal/pty-manager.d.ts +3 -51
- package/dist/server/services/terminal/pty-manager.d.ts.map +1 -1
- package/dist/server/services/terminal/pty-manager.js +14 -100
- package/dist/server/services/terminal/pty-manager.js.map +1 -1
- package/dist/server/services/websocket/handler.d.ts +36 -15
- package/dist/server/services/websocket/handler.d.ts.map +1 -1
- package/dist/server/services/websocket/handler.js +452 -223
- package/dist/server/services/websocket/handler.js.map +1 -1
- package/dist/server/services/websocket/types.d.ts +6 -2
- package/dist/server/services/websocket/types.d.ts.map +1 -1
- package/hooks/bouncer.sh +11 -4
- package/package.json +4 -1
- package/server/cli/headless/claude-invoker.ts +602 -119
- package/server/cli/headless/index.ts +7 -1
- package/server/cli/headless/prompt-utils.ts +37 -5
- package/server/cli/headless/runner.ts +30 -8
- package/server/cli/headless/stall-assessor.ts +453 -22
- package/server/cli/headless/tool-watchdog.ts +390 -0
- package/server/cli/headless/types.ts +84 -1
- package/server/cli/improvisation-session-manager.ts +884 -143
- package/server/index.ts +5 -10
- package/server/mcp/bouncer-integration.ts +28 -0
- package/server/mcp/security-audit.ts +12 -8
- package/server/mcp/security-patterns.ts +8 -2
- package/server/routes/improvise.ts +6 -6
- package/server/services/analytics.ts +13 -3
- package/server/services/platform.test.ts +0 -10
- package/server/services/platform.ts +4 -10
- package/server/services/sandbox-utils.ts +78 -0
- package/server/services/settings.ts +25 -0
- package/server/services/terminal/pty-manager.ts +16 -127
- package/server/services/websocket/handler.ts +515 -251
- package/server/services/websocket/types.ts +10 -4
- package/dist/server/services/terminal/tmux-manager.d.ts +0 -82
- package/dist/server/services/terminal/tmux-manager.d.ts.map +0 -1
- package/dist/server/services/terminal/tmux-manager.js +0 -352
- package/dist/server/services/terminal/tmux-manager.js.map +0 -1
- package/server/services/terminal/tmux-manager.ts +0 -426
|
@@ -26,14 +26,20 @@ export {
|
|
|
26
26
|
} from './prompt-utils.js';
|
|
27
27
|
// Main runner class
|
|
28
28
|
export { HeadlessRunner } from './runner.js';
|
|
29
|
+
// Tool watchdog
|
|
30
|
+
export { ToolWatchdog } from './tool-watchdog.js';
|
|
29
31
|
// Types
|
|
30
32
|
export type {
|
|
33
|
+
ExecutionCheckpoint,
|
|
31
34
|
ExecutionResult,
|
|
32
35
|
HeadlessConfig,
|
|
33
36
|
ImageAttachment,
|
|
34
|
-
|
|
37
|
+
PendingToolMap,
|
|
38
|
+
ResolvedHeadlessConfig,
|
|
35
39
|
SessionResult,
|
|
36
40
|
SessionState,
|
|
41
|
+
ToolDurationTracker,
|
|
42
|
+
ToolTimeoutProfile,
|
|
37
43
|
ToolUseAccumulator,
|
|
38
44
|
ToolUseEvent
|
|
39
45
|
} from './types.js';
|
|
@@ -7,16 +7,19 @@
|
|
|
7
7
|
* Utilities for enriching prompts with context from previous conversation.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
import { assessApproval } from './stall-assessor.js';
|
|
10
11
|
import type { ImageAttachment, PromptContext } from './types.js';
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
|
-
* Enrich prompt with context from previous conversation
|
|
14
|
+
* Enrich prompt with context from previous conversation.
|
|
15
|
+
* Async because ambiguous short prompts are classified by Haiku.
|
|
14
16
|
*/
|
|
15
|
-
export function enrichPromptWithContext(prompt: string, context: PromptContext): string {
|
|
17
|
+
export async function enrichPromptWithContext(prompt: string, context: PromptContext): Promise<string> {
|
|
16
18
|
let enriched = prompt;
|
|
17
19
|
|
|
18
|
-
// Detect if this is a continuation/approval prompt
|
|
19
|
-
|
|
20
|
+
// Detect if this is a continuation/approval prompt.
|
|
21
|
+
// Fast regex path for obvious approvals, Haiku for ambiguous short prompts.
|
|
22
|
+
const isApprovalOrContinuation = await detectApproval(prompt);
|
|
20
23
|
|
|
21
24
|
// Add accumulated knowledge from previous prompts
|
|
22
25
|
if (context.accumulatedKnowledge) {
|
|
@@ -36,9 +39,38 @@ export function enrichPromptWithContext(prompt: string, context: PromptContext):
|
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
/**
|
|
39
|
-
* Detect if a prompt is an approval or continuation
|
|
42
|
+
* Detect if a prompt is an approval or continuation.
|
|
43
|
+
* Layer 1: Regex fast path for obvious approvals (free, sync).
|
|
44
|
+
* Layer 2: Haiku assessment for ambiguous short prompts (<100 chars).
|
|
45
|
+
*/
|
|
46
|
+
async function detectApproval(prompt: string): Promise<boolean> {
|
|
47
|
+
// Layer 1: fast regex path
|
|
48
|
+
if (isApprovalPromptFast(prompt)) return true;
|
|
49
|
+
|
|
50
|
+
// Layer 2: Haiku for short ambiguous prompts.
|
|
51
|
+
// Long prompts (>100 chars) are almost certainly new tasks, not approvals.
|
|
52
|
+
if (prompt.trim().length <= 100) {
|
|
53
|
+
try {
|
|
54
|
+
const claudeCmd = process.env.CLAUDE_COMMAND || 'claude';
|
|
55
|
+
const verdict = await assessApproval(prompt, claudeCmd, false);
|
|
56
|
+
return verdict.isApproval;
|
|
57
|
+
} catch {
|
|
58
|
+
// Haiku failed — fall through to false
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Fast regex-based approval detection (sync, no API call).
|
|
67
|
+
* Catches obvious affirmatives. Ambiguous cases fall through to Haiku.
|
|
40
68
|
*/
|
|
41
69
|
export function isApprovalPrompt(prompt: string): boolean {
|
|
70
|
+
return isApprovalPromptFast(prompt);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function isApprovalPromptFast(prompt: string): boolean {
|
|
42
74
|
const lower = prompt.toLowerCase().trim();
|
|
43
75
|
|
|
44
76
|
// Short affirmative responses
|
|
@@ -20,7 +20,7 @@ import type {
|
|
|
20
20
|
} from './types.js';
|
|
21
21
|
|
|
22
22
|
// Re-export types for backward compatibility
|
|
23
|
-
export type { HeadlessConfig, ImageAttachment, SessionResult, SessionState, ToolUseEvent } from './types.js';
|
|
23
|
+
export type { ExecutionCheckpoint, HeadlessConfig, ImageAttachment, SessionResult, SessionState, ToolTimeoutProfile, ToolUseEvent } from './types.js';
|
|
24
24
|
|
|
25
25
|
export class HeadlessRunner {
|
|
26
26
|
private config: ResolvedHeadlessConfig;
|
|
@@ -33,9 +33,9 @@ export class HeadlessRunner {
|
|
|
33
33
|
maxSessions: config.maxSessions || 50,
|
|
34
34
|
maxRetries: config.maxRetries || 3,
|
|
35
35
|
claudeCommand: config.claudeCommand || process.env.CLAUDE_COMMAND || 'claude',
|
|
36
|
-
verbose: config.verbose
|
|
37
|
-
noColor: config.noColor
|
|
38
|
-
improvisationMode: config.improvisationMode
|
|
36
|
+
verbose: !!config.verbose,
|
|
37
|
+
noColor: !!config.noColor,
|
|
38
|
+
improvisationMode: !!config.improvisationMode,
|
|
39
39
|
movementNumber: config.movementNumber ?? 0,
|
|
40
40
|
outputCallback: config.outputCallback,
|
|
41
41
|
thinkingCallback: config.thinkingCallback,
|
|
@@ -51,6 +51,11 @@ export class HeadlessRunner {
|
|
|
51
51
|
stallMaxExtensions: config.stallMaxExtensions ?? 3,
|
|
52
52
|
stallHardCapMs: config.stallHardCapMs ?? 3_600_000,
|
|
53
53
|
model: config.model,
|
|
54
|
+
toolTimeoutProfiles: config.toolTimeoutProfiles,
|
|
55
|
+
enableToolWatchdog: config.enableToolWatchdog !== false,
|
|
56
|
+
maxAutoRetries: config.maxAutoRetries ?? 2,
|
|
57
|
+
onToolTimeout: config.onToolTimeout,
|
|
58
|
+
sandboxed: config.sandboxed,
|
|
54
59
|
};
|
|
55
60
|
}
|
|
56
61
|
|
|
@@ -78,22 +83,36 @@ export class HeadlessRunner {
|
|
|
78
83
|
const sessionId = `direct-${Date.now()}`;
|
|
79
84
|
|
|
80
85
|
const enrichedPrompt = context
|
|
81
|
-
? enrichPromptWithContext(userPrompt, context)
|
|
86
|
+
? await enrichPromptWithContext(userPrompt, context)
|
|
82
87
|
: userPrompt;
|
|
83
88
|
|
|
84
89
|
const result = await this.executePromptCommand(enrichedPrompt, 'main', 1);
|
|
85
90
|
|
|
86
91
|
if (result.exitCode !== 0) {
|
|
92
|
+
// Build meaningful error: prefer stderr, fall back to non-JSON stdout lines
|
|
93
|
+
let errorMessage = result.error;
|
|
94
|
+
if (!errorMessage && result.output) {
|
|
95
|
+
const plainLines = result.output.split('\n')
|
|
96
|
+
.filter(l => l.trim() && !l.trim().startsWith('{'))
|
|
97
|
+
.join('\n')
|
|
98
|
+
.trim();
|
|
99
|
+
if (plainLines) {
|
|
100
|
+
errorMessage = plainLines.slice(0, 500);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
87
103
|
return {
|
|
88
104
|
completed: false,
|
|
89
105
|
needsHandoff: false,
|
|
90
106
|
totalTokens: 0,
|
|
91
107
|
sessionId,
|
|
92
|
-
error:
|
|
108
|
+
error: errorMessage || `Claude exited with code ${result.exitCode}`,
|
|
93
109
|
assistantResponse: result.assistantResponse,
|
|
94
110
|
thinkingOutput: result.thinkingOutput,
|
|
95
111
|
toolUseHistory: result.toolUseHistory,
|
|
96
|
-
claudeSessionId: result.claudeSessionId
|
|
112
|
+
claudeSessionId: result.claudeSessionId,
|
|
113
|
+
nativeTimeoutCount: result.nativeTimeoutCount,
|
|
114
|
+
postTimeoutOutput: result.postTimeoutOutput,
|
|
115
|
+
resumeBufferedOutput: result.resumeBufferedOutput,
|
|
97
116
|
};
|
|
98
117
|
}
|
|
99
118
|
|
|
@@ -107,7 +126,10 @@ export class HeadlessRunner {
|
|
|
107
126
|
assistantResponse: result.assistantResponse,
|
|
108
127
|
thinkingOutput: result.thinkingOutput,
|
|
109
128
|
toolUseHistory: result.toolUseHistory,
|
|
110
|
-
claudeSessionId: result.claudeSessionId
|
|
129
|
+
claudeSessionId: result.claudeSessionId,
|
|
130
|
+
nativeTimeoutCount: result.nativeTimeoutCount,
|
|
131
|
+
postTimeoutOutput: result.postTimeoutOutput,
|
|
132
|
+
resumeBufferedOutput: result.resumeBufferedOutput,
|
|
111
133
|
};
|
|
112
134
|
}
|
|
113
135
|
|