mstro-app 0.3.7 → 0.3.9
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 +4 -8
- package/bin/mstro.js +54 -15
- package/dist/server/cli/headless/claude-invoker.d.ts.map +1 -1
- package/dist/server/cli/headless/claude-invoker.js +18 -9
- package/dist/server/cli/headless/claude-invoker.js.map +1 -1
- package/dist/server/cli/headless/headless-logger.d.ts +10 -0
- package/dist/server/cli/headless/headless-logger.d.ts.map +1 -0
- package/dist/server/cli/headless/headless-logger.js +66 -0
- package/dist/server/cli/headless/headless-logger.js.map +1 -0
- package/dist/server/cli/headless/mcp-config.d.ts.map +1 -1
- package/dist/server/cli/headless/mcp-config.js +6 -5
- 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 +4 -0
- package/dist/server/cli/headless/runner.js.map +1 -1
- package/dist/server/cli/headless/stall-assessor.d.ts +21 -0
- package/dist/server/cli/headless/stall-assessor.d.ts.map +1 -1
- package/dist/server/cli/headless/stall-assessor.js +74 -20
- package/dist/server/cli/headless/stall-assessor.js.map +1 -1
- package/dist/server/cli/headless/tool-watchdog.d.ts +0 -12
- package/dist/server/cli/headless/tool-watchdog.d.ts.map +1 -1
- package/dist/server/cli/headless/tool-watchdog.js +30 -9
- package/dist/server/cli/headless/tool-watchdog.js.map +1 -1
- package/dist/server/cli/headless/types.d.ts +8 -1
- package/dist/server/cli/headless/types.d.ts.map +1 -1
- package/dist/server/cli/improvisation-session-manager.d.ts +16 -0
- package/dist/server/cli/improvisation-session-manager.d.ts.map +1 -1
- package/dist/server/cli/improvisation-session-manager.js +94 -11
- package/dist/server/cli/improvisation-session-manager.js.map +1 -1
- package/dist/server/index.js +0 -4
- package/dist/server/index.js.map +1 -1
- package/dist/server/mcp/bouncer-cli.d.ts +3 -0
- package/dist/server/mcp/bouncer-cli.d.ts.map +1 -0
- package/dist/server/mcp/bouncer-cli.js +54 -0
- package/dist/server/mcp/bouncer-cli.js.map +1 -0
- package/dist/server/mcp/bouncer-integration.d.ts +2 -0
- package/dist/server/mcp/bouncer-integration.d.ts.map +1 -1
- package/dist/server/mcp/bouncer-integration.js +55 -39
- package/dist/server/mcp/bouncer-integration.js.map +1 -1
- package/dist/server/mcp/bouncer-sandbox.d.ts +60 -0
- package/dist/server/mcp/bouncer-sandbox.d.ts.map +1 -0
- package/dist/server/mcp/bouncer-sandbox.js +182 -0
- package/dist/server/mcp/bouncer-sandbox.js.map +1 -0
- package/dist/server/mcp/security-patterns.d.ts +6 -12
- package/dist/server/mcp/security-patterns.d.ts.map +1 -1
- package/dist/server/mcp/security-patterns.js +197 -10
- package/dist/server/mcp/security-patterns.js.map +1 -1
- package/dist/server/services/plan/composer.d.ts +4 -0
- package/dist/server/services/plan/composer.d.ts.map +1 -0
- package/dist/server/services/plan/composer.js +181 -0
- package/dist/server/services/plan/composer.js.map +1 -0
- package/dist/server/services/plan/dependency-resolver.d.ts +28 -0
- package/dist/server/services/plan/dependency-resolver.d.ts.map +1 -0
- package/dist/server/services/plan/dependency-resolver.js +152 -0
- package/dist/server/services/plan/dependency-resolver.js.map +1 -0
- package/dist/server/services/plan/executor.d.ts +91 -0
- package/dist/server/services/plan/executor.d.ts.map +1 -0
- package/dist/server/services/plan/executor.js +545 -0
- package/dist/server/services/plan/executor.js.map +1 -0
- package/dist/server/services/plan/parser.d.ts +11 -0
- package/dist/server/services/plan/parser.d.ts.map +1 -0
- package/dist/server/services/plan/parser.js +415 -0
- package/dist/server/services/plan/parser.js.map +1 -0
- package/dist/server/services/plan/state-reconciler.d.ts +2 -0
- package/dist/server/services/plan/state-reconciler.d.ts.map +1 -0
- package/dist/server/services/plan/state-reconciler.js +105 -0
- package/dist/server/services/plan/state-reconciler.js.map +1 -0
- package/dist/server/services/plan/types.d.ts +120 -0
- package/dist/server/services/plan/types.d.ts.map +1 -0
- package/dist/server/services/plan/types.js +4 -0
- package/dist/server/services/plan/types.js.map +1 -0
- package/dist/server/services/plan/watcher.d.ts +14 -0
- package/dist/server/services/plan/watcher.d.ts.map +1 -0
- package/dist/server/services/plan/watcher.js +69 -0
- package/dist/server/services/plan/watcher.js.map +1 -0
- package/dist/server/services/websocket/file-explorer-handlers.js +20 -0
- package/dist/server/services/websocket/file-explorer-handlers.js.map +1 -1
- package/dist/server/services/websocket/handler.d.ts +0 -1
- package/dist/server/services/websocket/handler.d.ts.map +1 -1
- package/dist/server/services/websocket/handler.js +28 -2
- package/dist/server/services/websocket/handler.js.map +1 -1
- package/dist/server/services/websocket/plan-handlers.d.ts +6 -0
- package/dist/server/services/websocket/plan-handlers.d.ts.map +1 -0
- package/dist/server/services/websocket/plan-handlers.js +494 -0
- package/dist/server/services/websocket/plan-handlers.js.map +1 -0
- package/dist/server/services/websocket/quality-handlers.d.ts +4 -0
- package/dist/server/services/websocket/quality-handlers.d.ts.map +1 -0
- package/dist/server/services/websocket/quality-handlers.js +470 -0
- package/dist/server/services/websocket/quality-handlers.js.map +1 -0
- package/dist/server/services/websocket/quality-persistence.d.ts +45 -0
- package/dist/server/services/websocket/quality-persistence.d.ts.map +1 -0
- package/dist/server/services/websocket/quality-persistence.js +187 -0
- package/dist/server/services/websocket/quality-persistence.js.map +1 -0
- package/dist/server/services/websocket/quality-service.d.ts +54 -0
- package/dist/server/services/websocket/quality-service.d.ts.map +1 -0
- package/dist/server/services/websocket/quality-service.js +816 -0
- package/dist/server/services/websocket/quality-service.js.map +1 -0
- package/dist/server/services/websocket/session-handlers.d.ts.map +1 -1
- package/dist/server/services/websocket/session-handlers.js +23 -0
- package/dist/server/services/websocket/session-handlers.js.map +1 -1
- package/dist/server/services/websocket/types.d.ts +2 -2
- package/dist/server/services/websocket/types.d.ts.map +1 -1
- package/package.json +3 -2
- package/server/cli/headless/claude-invoker.ts +21 -9
- package/server/cli/headless/headless-logger.ts +78 -0
- package/server/cli/headless/mcp-config.ts +6 -5
- package/server/cli/headless/runner.ts +4 -0
- package/server/cli/headless/stall-assessor.ts +101 -20
- package/server/cli/headless/tool-watchdog.ts +18 -9
- package/server/cli/headless/types.ts +10 -1
- package/server/cli/improvisation-session-manager.ts +118 -11
- package/server/index.ts +0 -4
- package/server/mcp/bouncer-cli.ts +73 -0
- package/server/mcp/bouncer-integration.ts +66 -44
- package/server/mcp/bouncer-sandbox.ts +214 -0
- package/server/mcp/security-patterns.ts +206 -10
- package/server/services/plan/composer.ts +199 -0
- package/server/services/plan/dependency-resolver.ts +179 -0
- package/server/services/plan/executor.ts +604 -0
- package/server/services/plan/parser.ts +459 -0
- package/server/services/plan/state-reconciler.ts +132 -0
- package/server/services/plan/types.ts +164 -0
- package/server/services/plan/watcher.ts +73 -0
- package/server/services/websocket/file-explorer-handlers.ts +20 -0
- package/server/services/websocket/handler.ts +28 -2
- package/server/services/websocket/plan-handlers.ts +592 -0
- package/server/services/websocket/quality-handlers.ts +570 -0
- package/server/services/websocket/quality-persistence.ts +250 -0
- package/server/services/websocket/quality-service.ts +975 -0
- package/server/services/websocket/session-handlers.ts +26 -0
- package/server/services/websocket/types.ts +62 -2
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
// Copyright (c) 2025-present Mstro, Inc. All rights reserved.
|
|
2
|
+
// Licensed under the MIT License. See LICENSE file for details.
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Plan Types — Project Plan Spec (PPS) data structures
|
|
6
|
+
*
|
|
7
|
+
* These types represent the parsed contents of .pm/ directory files.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Project Config (project.md front matter)
|
|
12
|
+
// ============================================================================
|
|
13
|
+
|
|
14
|
+
export interface ProjectConfig {
|
|
15
|
+
name: string;
|
|
16
|
+
id: string;
|
|
17
|
+
created: string;
|
|
18
|
+
status: 'active' | 'paused' | 'completed' | 'archived';
|
|
19
|
+
estimation: 'fibonacci' | 'tshirt' | 'hours' | 'none';
|
|
20
|
+
idPrefixes: Record<string, string>;
|
|
21
|
+
workflows: WorkflowStatus[];
|
|
22
|
+
labels: string[];
|
|
23
|
+
teams: Team[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface WorkflowStatus {
|
|
27
|
+
status: string;
|
|
28
|
+
category: 'unstarted' | 'started' | 'completed' | 'cancelled';
|
|
29
|
+
description: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface Team {
|
|
33
|
+
name: string;
|
|
34
|
+
description?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// ============================================================================
|
|
38
|
+
// Project State (STATE.md front matter + body)
|
|
39
|
+
// ============================================================================
|
|
40
|
+
|
|
41
|
+
export interface ProjectState {
|
|
42
|
+
project: string;
|
|
43
|
+
currentSprint: string | null;
|
|
44
|
+
activeMilestone: string | null;
|
|
45
|
+
paused: boolean;
|
|
46
|
+
lastSession: string | null;
|
|
47
|
+
// Parsed from markdown body sections:
|
|
48
|
+
readyToWork: IssueSummary[];
|
|
49
|
+
inProgress: IssueSummary[];
|
|
50
|
+
blocked: IssueSummary[];
|
|
51
|
+
recentlyCompleted: IssueSummary[];
|
|
52
|
+
warnings: string[];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface IssueSummary {
|
|
56
|
+
id: string;
|
|
57
|
+
title: string;
|
|
58
|
+
path: string;
|
|
59
|
+
priority: string;
|
|
60
|
+
blockedBy?: string;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// ============================================================================
|
|
64
|
+
// Issue / Epic / Bug (backlog/*.md)
|
|
65
|
+
// ============================================================================
|
|
66
|
+
|
|
67
|
+
export interface Issue {
|
|
68
|
+
id: string;
|
|
69
|
+
title: string;
|
|
70
|
+
type: 'issue' | 'epic' | 'bug' | 'task';
|
|
71
|
+
status: string;
|
|
72
|
+
priority: string;
|
|
73
|
+
estimate: number | string | null;
|
|
74
|
+
labels: string[];
|
|
75
|
+
epic: string | null;
|
|
76
|
+
sprint: string | null;
|
|
77
|
+
milestone: string | null;
|
|
78
|
+
assigned: string | null;
|
|
79
|
+
created: string;
|
|
80
|
+
updated: string | null;
|
|
81
|
+
due: string | null;
|
|
82
|
+
blockedBy: string[];
|
|
83
|
+
blocks: string[];
|
|
84
|
+
relatesTo: string[];
|
|
85
|
+
// Body sections
|
|
86
|
+
description: string;
|
|
87
|
+
acceptanceCriteria: AcceptanceCriterion[];
|
|
88
|
+
technicalNotes: string | null;
|
|
89
|
+
filesToModify: string[];
|
|
90
|
+
activity: string[];
|
|
91
|
+
// Children (for epics)
|
|
92
|
+
children: string[];
|
|
93
|
+
// Progress (for epics)
|
|
94
|
+
progress: string | null;
|
|
95
|
+
// Full markdown body
|
|
96
|
+
body: string;
|
|
97
|
+
// File path relative to .pm/
|
|
98
|
+
path: string;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export interface AcceptanceCriterion {
|
|
102
|
+
text: string;
|
|
103
|
+
checked: boolean;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// ============================================================================
|
|
107
|
+
// Sprint (sprints/*.md)
|
|
108
|
+
// ============================================================================
|
|
109
|
+
|
|
110
|
+
export interface Sprint {
|
|
111
|
+
id: string;
|
|
112
|
+
title: string;
|
|
113
|
+
status: 'planned' | 'active' | 'completed';
|
|
114
|
+
start: string;
|
|
115
|
+
end: string;
|
|
116
|
+
goal: string;
|
|
117
|
+
capacity: number | null;
|
|
118
|
+
committed: number | null;
|
|
119
|
+
completed: number | null;
|
|
120
|
+
issues: SprintIssueSummary[];
|
|
121
|
+
path: string;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export interface SprintIssueSummary {
|
|
125
|
+
id: string;
|
|
126
|
+
title: string;
|
|
127
|
+
path: string;
|
|
128
|
+
points: number | string | null;
|
|
129
|
+
status: string;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// ============================================================================
|
|
133
|
+
// Milestone (milestones/*.md)
|
|
134
|
+
// ============================================================================
|
|
135
|
+
|
|
136
|
+
export interface Milestone {
|
|
137
|
+
id: string;
|
|
138
|
+
title: string;
|
|
139
|
+
status: 'planned' | 'in_progress' | 'completed' | 'missed';
|
|
140
|
+
targetDate: string | null;
|
|
141
|
+
progress: string | null;
|
|
142
|
+
definition: string;
|
|
143
|
+
epics: MilestoneEpicSummary[];
|
|
144
|
+
path: string;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export interface MilestoneEpicSummary {
|
|
148
|
+
id: string;
|
|
149
|
+
title: string;
|
|
150
|
+
path: string;
|
|
151
|
+
progress: string;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// ============================================================================
|
|
155
|
+
// Plan full state (sent on planInit)
|
|
156
|
+
// ============================================================================
|
|
157
|
+
|
|
158
|
+
export interface PlanFullState {
|
|
159
|
+
project: ProjectConfig;
|
|
160
|
+
state: ProjectState;
|
|
161
|
+
issues: Issue[];
|
|
162
|
+
sprints: Sprint[];
|
|
163
|
+
milestones: Milestone[];
|
|
164
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// Copyright (c) 2025-present Mstro, Inc. All rights reserved.
|
|
2
|
+
// Licensed under the MIT License. See LICENSE file for details.
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Plan Watcher — Watches .pm/ (or legacy .plan/) directory for changes and broadcasts updates.
|
|
6
|
+
*
|
|
7
|
+
* Uses fs.watch with debouncing to batch rapid changes.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { type FSWatcher, watch } from 'node:fs';
|
|
11
|
+
import type { HandlerContext } from '../websocket/handler-context.js';
|
|
12
|
+
import { parsePlanDirectory, resolvePmDir } from './parser.js';
|
|
13
|
+
|
|
14
|
+
export class PlanWatcher {
|
|
15
|
+
private watcher: FSWatcher | null = null;
|
|
16
|
+
private debounceTimer: ReturnType<typeof setTimeout> | null = null;
|
|
17
|
+
private readonly workingDir: string;
|
|
18
|
+
private readonly ctx: HandlerContext;
|
|
19
|
+
private started = false;
|
|
20
|
+
|
|
21
|
+
constructor(workingDir: string, ctx: HandlerContext) {
|
|
22
|
+
this.workingDir = workingDir;
|
|
23
|
+
this.ctx = ctx;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
start(): void {
|
|
27
|
+
if (this.started) return;
|
|
28
|
+
|
|
29
|
+
const planDir = resolvePmDir(this.workingDir);
|
|
30
|
+
if (!planDir) return;
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
this.watcher = watch(planDir, { recursive: true }, (_event, filename) => {
|
|
34
|
+
if (!filename || !filename.endsWith('.md')) return;
|
|
35
|
+
this.debounce();
|
|
36
|
+
});
|
|
37
|
+
this.started = true;
|
|
38
|
+
} catch {
|
|
39
|
+
// fs.watch recursive may not be supported on all platforms
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
stop(): void {
|
|
44
|
+
if (this.watcher) {
|
|
45
|
+
this.watcher.close();
|
|
46
|
+
this.watcher = null;
|
|
47
|
+
}
|
|
48
|
+
if (this.debounceTimer) {
|
|
49
|
+
clearTimeout(this.debounceTimer);
|
|
50
|
+
this.debounceTimer = null;
|
|
51
|
+
}
|
|
52
|
+
this.started = false;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private debounce(): void {
|
|
56
|
+
if (this.debounceTimer) clearTimeout(this.debounceTimer);
|
|
57
|
+
this.debounceTimer = setTimeout(() => {
|
|
58
|
+
this.handleChange();
|
|
59
|
+
}, 200);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
private handleChange(): void {
|
|
63
|
+
try {
|
|
64
|
+
// Always do a full reparse — concurrent changes may affect multiple files
|
|
65
|
+
const fullState = parsePlanDirectory(this.workingDir);
|
|
66
|
+
if (fullState) {
|
|
67
|
+
this.ctx.broadcastToAll({ type: 'planStateUpdated', data: fullState });
|
|
68
|
+
}
|
|
69
|
+
} catch {
|
|
70
|
+
// Ignore parse errors from partial writes
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -542,6 +542,22 @@ function handleFindDefinition(ctx: HandlerContext, ws: WSContext, msg: WebSocket
|
|
|
542
542
|
`(fn|struct|enum|trait|type|const|static|mod)\\s+${s}\\b`,
|
|
543
543
|
`impl\\s+${s}\\b`,
|
|
544
544
|
],
|
|
545
|
+
swift: (s) => [
|
|
546
|
+
`(func|class|struct|enum|protocol|typealias|actor)\\s+${s}\\b`,
|
|
547
|
+
`(let|var)\\s+${s}\\b`,
|
|
548
|
+
`extension\\s+${s}\\b`,
|
|
549
|
+
],
|
|
550
|
+
kotlin: (s) => [
|
|
551
|
+
`(fun|class|object|interface|typealias|enum\\s+class)\\s+${s}\\b`,
|
|
552
|
+
`(val|var)\\s+${s}\\b`,
|
|
553
|
+
],
|
|
554
|
+
java: (s) => [
|
|
555
|
+
`(class|interface|enum)\\s+${s}\\b`,
|
|
556
|
+
`(public|private|protected|static)?\\s*(void|int|String|boolean|\\w+)\\s+${s}\\s*\\(`,
|
|
557
|
+
],
|
|
558
|
+
ruby: (s) => [
|
|
559
|
+
`(def|class|module)\\s+${s}\\b`,
|
|
560
|
+
],
|
|
545
561
|
};
|
|
546
562
|
|
|
547
563
|
const LANGUAGE_GLOBS: Record<string, string> = {
|
|
@@ -550,6 +566,10 @@ function handleFindDefinition(ctx: HandlerContext, ws: WSContext, msg: WebSocket
|
|
|
550
566
|
python: '*.py',
|
|
551
567
|
go: '*.go',
|
|
552
568
|
rust: '*.rs',
|
|
569
|
+
swift: '*.swift',
|
|
570
|
+
kotlin: '*.{kt,kts}',
|
|
571
|
+
java: '*.java',
|
|
572
|
+
ruby: '*.rb',
|
|
553
573
|
};
|
|
554
574
|
|
|
555
575
|
const patterns = DEFINITION_PATTERNS[language] || DEFINITION_PATTERNS.typescript;
|
|
@@ -19,6 +19,8 @@ import { handleFileExplorerMessage, handleFileMessage } from './file-explorer-ha
|
|
|
19
19
|
import { FileUploadHandler } from './file-upload-handler.js';
|
|
20
20
|
import { handleGitMessage } from './git-handlers.js';
|
|
21
21
|
import type { HandlerContext, UsageReporter } from './handler-context.js';
|
|
22
|
+
import { handlePlanMessage } from './plan-handlers.js';
|
|
23
|
+
import { handleQualityMessage } from './quality-handlers.js';
|
|
22
24
|
import { handleHistoryMessage, handleSessionMessage, initializeTab, resumeHistoricalSession } from './session-handlers.js';
|
|
23
25
|
import { SessionRegistry } from './session-registry.js';
|
|
24
26
|
import { generateNotificationSummary, handleGetSettings, handleUpdateSettings } from './settings-handlers.js';
|
|
@@ -220,6 +222,32 @@ export class WebSocketImproviseHandler implements HandlerContext {
|
|
|
220
222
|
return handleRemoveTab(this, ws, tabId, workingDir);
|
|
221
223
|
case 'markTabViewed':
|
|
222
224
|
return handleMarkTabViewed(this, ws, tabId, workingDir);
|
|
225
|
+
// Quality messages
|
|
226
|
+
case 'qualityDetectTools':
|
|
227
|
+
case 'qualityScan':
|
|
228
|
+
case 'qualityInstallTools':
|
|
229
|
+
case 'qualityCodeReview':
|
|
230
|
+
case 'qualityFixIssues':
|
|
231
|
+
case 'qualityLoadState':
|
|
232
|
+
case 'qualitySaveDirectories':
|
|
233
|
+
return handleQualityMessage(this, ws, msg, tabId, workingDir);
|
|
234
|
+
// Plan messages
|
|
235
|
+
case 'planInit':
|
|
236
|
+
case 'planGetState':
|
|
237
|
+
case 'planListIssues':
|
|
238
|
+
case 'planGetIssue':
|
|
239
|
+
case 'planGetSprint':
|
|
240
|
+
case 'planGetMilestone':
|
|
241
|
+
case 'planCreateIssue':
|
|
242
|
+
case 'planUpdateIssue':
|
|
243
|
+
case 'planDeleteIssue':
|
|
244
|
+
case 'planScaffold':
|
|
245
|
+
case 'planPrompt':
|
|
246
|
+
case 'planExecute':
|
|
247
|
+
case 'planPause':
|
|
248
|
+
case 'planStop':
|
|
249
|
+
case 'planResume':
|
|
250
|
+
return handlePlanMessage(this, ws, msg, tabId, workingDir, permission);
|
|
223
251
|
// Settings messages
|
|
224
252
|
case 'getSettings':
|
|
225
253
|
return handleGetSettings(this, ws);
|
|
@@ -291,6 +319,4 @@ export class WebSocketImproviseHandler implements HandlerContext {
|
|
|
291
319
|
this.sessions.delete(sessionId);
|
|
292
320
|
}
|
|
293
321
|
|
|
294
|
-
cleanupStaleSessions(): void {
|
|
295
|
-
}
|
|
296
322
|
}
|