@cluesmith/codev 2.0.0-rc.72 → 2.0.0-rc.74
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/dashboard/dist/assets/{index-C7FtNK6Y.css → index-4n9zpWLY.css} +1 -1
- package/dashboard/dist/assets/{index-CDAINZKT.js → index-b38SaXk5.js} +33 -28
- package/dashboard/dist/assets/index-b38SaXk5.js.map +1 -0
- package/dashboard/dist/index.html +2 -2
- package/dist/agent-farm/commands/spawn-roles.d.ts +80 -0
- package/dist/agent-farm/commands/spawn-roles.d.ts.map +1 -0
- package/dist/agent-farm/commands/spawn-roles.js +278 -0
- package/dist/agent-farm/commands/spawn-roles.js.map +1 -0
- package/dist/agent-farm/commands/spawn-worktree.d.ts +96 -0
- package/dist/agent-farm/commands/spawn-worktree.d.ts.map +1 -0
- package/dist/agent-farm/commands/spawn-worktree.js +305 -0
- package/dist/agent-farm/commands/spawn-worktree.js.map +1 -0
- package/dist/agent-farm/commands/spawn.d.ts +5 -1
- package/dist/agent-farm/commands/spawn.d.ts.map +1 -1
- package/dist/agent-farm/commands/spawn.js +65 -725
- package/dist/agent-farm/commands/spawn.js.map +1 -1
- package/dist/agent-farm/db/index.d.ts.map +1 -1
- package/dist/agent-farm/db/index.js +56 -2
- package/dist/agent-farm/db/index.js.map +1 -1
- package/dist/agent-farm/db/schema.d.ts +1 -1
- package/dist/agent-farm/db/schema.js +3 -3
- package/dist/agent-farm/servers/tower-instances.d.ts +82 -0
- package/dist/agent-farm/servers/tower-instances.d.ts.map +1 -0
- package/dist/agent-farm/servers/tower-instances.js +454 -0
- package/dist/agent-farm/servers/tower-instances.js.map +1 -0
- package/dist/agent-farm/servers/tower-routes.d.ts +34 -0
- package/dist/agent-farm/servers/tower-routes.d.ts.map +1 -0
- package/dist/agent-farm/servers/tower-routes.js +1445 -0
- package/dist/agent-farm/servers/tower-routes.js.map +1 -0
- package/dist/agent-farm/servers/tower-server.d.ts +5 -2
- package/dist/agent-farm/servers/tower-server.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-server.js +89 -2875
- package/dist/agent-farm/servers/tower-server.js.map +1 -1
- package/dist/agent-farm/servers/tower-terminals.d.ts +119 -0
- package/dist/agent-farm/servers/tower-terminals.d.ts.map +1 -0
- package/dist/agent-farm/servers/tower-terminals.js +629 -0
- package/dist/agent-farm/servers/tower-terminals.js.map +1 -0
- package/dist/agent-farm/servers/tower-tunnel.d.ts +34 -0
- package/dist/agent-farm/servers/tower-tunnel.d.ts.map +1 -0
- package/dist/agent-farm/servers/tower-tunnel.js +299 -0
- package/dist/agent-farm/servers/tower-tunnel.js.map +1 -0
- package/dist/agent-farm/servers/tower-types.d.ts +86 -0
- package/dist/agent-farm/servers/tower-types.d.ts.map +1 -0
- package/dist/agent-farm/servers/tower-types.js +6 -0
- package/dist/agent-farm/servers/tower-types.js.map +1 -0
- package/dist/agent-farm/servers/tower-utils.d.ts +58 -0
- package/dist/agent-farm/servers/tower-utils.d.ts.map +1 -0
- package/dist/agent-farm/servers/tower-utils.js +182 -0
- package/dist/agent-farm/servers/tower-utils.js.map +1 -0
- package/dist/agent-farm/servers/tower-websocket.d.ts +25 -0
- package/dist/agent-farm/servers/tower-websocket.d.ts.map +1 -0
- package/dist/agent-farm/servers/tower-websocket.js +171 -0
- package/dist/agent-farm/servers/tower-websocket.js.map +1 -0
- package/dist/agent-farm/utils/shell.d.ts +1 -1
- package/dist/agent-farm/utils/shell.js +1 -1
- package/dist/commands/porch/next.js +4 -4
- package/dist/commands/porch/next.js.map +1 -1
- package/dist/terminal/pty-manager.d.ts +1 -1
- package/dist/terminal/pty-manager.js +5 -5
- package/dist/terminal/pty-session.d.ts +20 -20
- package/dist/terminal/pty-session.js +55 -55
- package/dist/terminal/session-manager.d.ts +15 -15
- package/dist/terminal/session-manager.js +34 -34
- package/dist/terminal/{shepherd-client.d.ts → shellper-client.d.ts} +10 -10
- package/dist/terminal/{shepherd-client.d.ts.map → shellper-client.d.ts.map} +1 -1
- package/dist/terminal/{shepherd-client.js → shellper-client.js} +20 -20
- package/dist/terminal/{shepherd-client.js.map → shellper-client.js.map} +1 -1
- package/dist/terminal/{shepherd-main.d.ts → shellper-main.d.ts} +3 -3
- package/dist/terminal/shellper-main.d.ts.map +1 -0
- package/dist/terminal/{shepherd-main.js → shellper-main.js} +17 -17
- package/dist/terminal/{shepherd-main.js.map → shellper-main.js.map} +1 -1
- package/dist/terminal/{shepherd-process.d.ts → shellper-process.d.ts} +8 -8
- package/dist/terminal/{shepherd-process.d.ts.map → shellper-process.d.ts.map} +1 -1
- package/dist/terminal/{shepherd-process.js → shellper-process.js} +11 -11
- package/dist/terminal/{shepherd-process.js.map → shellper-process.js.map} +1 -1
- package/dist/terminal/{shepherd-protocol.d.ts → shellper-protocol.d.ts} +5 -5
- package/dist/terminal/{shepherd-protocol.d.ts.map → shellper-protocol.d.ts.map} +1 -1
- package/dist/terminal/{shepherd-protocol.js → shellper-protocol.js} +5 -5
- package/dist/terminal/{shepherd-protocol.js.map → shellper-protocol.js.map} +1 -1
- package/dist/terminal/{shepherd-replay-buffer.d.ts → shellper-replay-buffer.d.ts} +4 -4
- package/dist/terminal/{shepherd-replay-buffer.d.ts.map → shellper-replay-buffer.d.ts.map} +1 -1
- package/dist/terminal/{shepherd-replay-buffer.js → shellper-replay-buffer.js} +4 -4
- package/dist/terminal/{shepherd-replay-buffer.js.map → shellper-replay-buffer.js.map} +1 -1
- package/package.json +1 -1
- package/skeleton/protocols/bugfix/builder-prompt.md +7 -1
- package/skeleton/protocols/maintain/protocol.md +3 -3
- package/skeleton/protocols/spir/builder-prompt.md +7 -0
- package/skeleton/resources/commands/agent-farm.md +2 -2
- package/skeleton/roles/builder.md +15 -1
- package/dashboard/dist/assets/index-CDAINZKT.js.map +0 -1
- package/dist/terminal/shepherd-main.d.ts.map +0 -1
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project instance lifecycle for tower server.
|
|
3
|
+
* Spec 0105: Tower Server Decomposition — Phase 3
|
|
4
|
+
*
|
|
5
|
+
* Contains: instance discovery (getInstances), launch/stop lifecycle,
|
|
6
|
+
* known project registration, and directory suggestion autocomplete.
|
|
7
|
+
*/
|
|
8
|
+
import fs from 'node:fs';
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
import crypto from 'node:crypto';
|
|
11
|
+
import { execSync } from 'node:child_process';
|
|
12
|
+
import { homedir } from 'node:os';
|
|
13
|
+
import { getGlobalDb } from '../db/index.js';
|
|
14
|
+
import { getProjectName, isTempDirectory, buildArchitectArgs, } from './tower-utils.js';
|
|
15
|
+
// ============================================================================
|
|
16
|
+
// Module-private state
|
|
17
|
+
// ============================================================================
|
|
18
|
+
let _deps = null;
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// Public lifecycle
|
|
21
|
+
// ============================================================================
|
|
22
|
+
/** Initialize the instances module with dependencies. */
|
|
23
|
+
export function initInstances(deps) {
|
|
24
|
+
_deps = deps;
|
|
25
|
+
}
|
|
26
|
+
/** Tear down the instances module. */
|
|
27
|
+
export function shutdownInstances() {
|
|
28
|
+
_deps = null;
|
|
29
|
+
}
|
|
30
|
+
// ============================================================================
|
|
31
|
+
// Known project registration
|
|
32
|
+
// ============================================================================
|
|
33
|
+
/**
|
|
34
|
+
* Register a project in the known_projects table so it persists across restarts
|
|
35
|
+
* even when all terminal sessions are gone.
|
|
36
|
+
*/
|
|
37
|
+
export function registerKnownProject(projectPath) {
|
|
38
|
+
try {
|
|
39
|
+
const db = getGlobalDb();
|
|
40
|
+
db.prepare(`
|
|
41
|
+
INSERT INTO known_projects (project_path, name, last_launched_at)
|
|
42
|
+
VALUES (?, ?, datetime('now'))
|
|
43
|
+
ON CONFLICT(project_path) DO UPDATE SET last_launched_at = datetime('now')
|
|
44
|
+
`).run(projectPath, path.basename(projectPath));
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// Table may not exist yet (pre-migration)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Get all known project paths from known_projects, terminal_sessions, and in-memory cache.
|
|
52
|
+
*/
|
|
53
|
+
export function getKnownProjectPaths() {
|
|
54
|
+
const projectPaths = new Set();
|
|
55
|
+
// From known_projects table (persists even after all terminals are killed)
|
|
56
|
+
try {
|
|
57
|
+
const db = getGlobalDb();
|
|
58
|
+
const projects = db.prepare('SELECT project_path FROM known_projects').all();
|
|
59
|
+
for (const p of projects) {
|
|
60
|
+
projectPaths.add(p.project_path);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// Table may not exist yet
|
|
65
|
+
}
|
|
66
|
+
// From terminal_sessions table (catches any missed by known_projects)
|
|
67
|
+
try {
|
|
68
|
+
const db = getGlobalDb();
|
|
69
|
+
const sessions = db.prepare('SELECT DISTINCT project_path FROM terminal_sessions').all();
|
|
70
|
+
for (const s of sessions) {
|
|
71
|
+
projectPaths.add(s.project_path);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
// Table may not exist yet
|
|
76
|
+
}
|
|
77
|
+
// From in-memory cache (includes projects activated this session)
|
|
78
|
+
if (_deps) {
|
|
79
|
+
for (const [projectPath] of _deps.projectTerminals) {
|
|
80
|
+
projectPaths.add(projectPath);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return Array.from(projectPaths);
|
|
84
|
+
}
|
|
85
|
+
// ============================================================================
|
|
86
|
+
// Instance discovery
|
|
87
|
+
// ============================================================================
|
|
88
|
+
/**
|
|
89
|
+
* Get all instances with their status.
|
|
90
|
+
*/
|
|
91
|
+
export async function getInstances() {
|
|
92
|
+
if (!_deps)
|
|
93
|
+
return []; // Module not yet initialized (startup window)
|
|
94
|
+
const knownPaths = getKnownProjectPaths();
|
|
95
|
+
const instances = [];
|
|
96
|
+
// Build a lookup of last_launched_at from known_projects
|
|
97
|
+
const lastLaunchedMap = new Map();
|
|
98
|
+
try {
|
|
99
|
+
const db = getGlobalDb();
|
|
100
|
+
const rows = db.prepare('SELECT project_path, last_launched_at FROM known_projects').all();
|
|
101
|
+
for (const row of rows) {
|
|
102
|
+
lastLaunchedMap.set(row.project_path, row.last_launched_at);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
// Table may not exist yet (pre-migration)
|
|
107
|
+
}
|
|
108
|
+
for (const projectPath of knownPaths) {
|
|
109
|
+
// Skip builder worktrees - they're managed by their parent project
|
|
110
|
+
if (projectPath.includes('/.builders/')) {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
// Skip projects in temp directories (e.g. test artifacts) or whose directories no longer exist
|
|
114
|
+
if (!projectPath.startsWith('remote:')) {
|
|
115
|
+
if (!fs.existsSync(projectPath)) {
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
if (isTempDirectory(projectPath)) {
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Encode project path for proxy URL
|
|
123
|
+
const encodedPath = Buffer.from(projectPath).toString('base64url');
|
|
124
|
+
const proxyUrl = `/project/${encodedPath}/`;
|
|
125
|
+
// Get terminals and gate status from tower's registry
|
|
126
|
+
// Phase 4 (Spec 0090): Tower manages terminals directly - no separate dashboard server
|
|
127
|
+
const { terminals, gateStatus } = await _deps.getTerminalsForProject(projectPath, proxyUrl);
|
|
128
|
+
// Project is active if it has any terminals (Phase 4: no port check needed)
|
|
129
|
+
const isActive = terminals.length > 0;
|
|
130
|
+
instances.push({
|
|
131
|
+
projectPath,
|
|
132
|
+
projectName: getProjectName(projectPath),
|
|
133
|
+
running: isActive,
|
|
134
|
+
proxyUrl,
|
|
135
|
+
architectUrl: `${proxyUrl}?tab=architect`,
|
|
136
|
+
terminals,
|
|
137
|
+
gateStatus,
|
|
138
|
+
lastUsed: lastLaunchedMap.get(projectPath),
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
// Sort: running first, then by project name
|
|
142
|
+
instances.sort((a, b) => {
|
|
143
|
+
if (a.running !== b.running) {
|
|
144
|
+
return a.running ? -1 : 1;
|
|
145
|
+
}
|
|
146
|
+
return a.projectName.localeCompare(b.projectName);
|
|
147
|
+
});
|
|
148
|
+
return instances;
|
|
149
|
+
}
|
|
150
|
+
// ============================================================================
|
|
151
|
+
// Directory suggestions (pure — no module state)
|
|
152
|
+
// ============================================================================
|
|
153
|
+
/**
|
|
154
|
+
* Get directory suggestions for autocomplete.
|
|
155
|
+
*/
|
|
156
|
+
export async function getDirectorySuggestions(inputPath) {
|
|
157
|
+
// Default to home directory if empty
|
|
158
|
+
if (!inputPath) {
|
|
159
|
+
inputPath = homedir();
|
|
160
|
+
}
|
|
161
|
+
// Expand ~ to home directory
|
|
162
|
+
if (inputPath.startsWith('~')) {
|
|
163
|
+
inputPath = inputPath.replace('~', homedir());
|
|
164
|
+
}
|
|
165
|
+
// Relative paths are meaningless for the tower daemon — only absolute paths
|
|
166
|
+
if (!path.isAbsolute(inputPath)) {
|
|
167
|
+
return [];
|
|
168
|
+
}
|
|
169
|
+
// Determine the directory to list and the prefix to filter by
|
|
170
|
+
let dirToList;
|
|
171
|
+
let prefix;
|
|
172
|
+
if (inputPath.endsWith('/')) {
|
|
173
|
+
// User typed a complete directory path, list its contents
|
|
174
|
+
dirToList = inputPath;
|
|
175
|
+
prefix = '';
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
// User is typing a partial name, list parent and filter
|
|
179
|
+
dirToList = path.dirname(inputPath);
|
|
180
|
+
prefix = path.basename(inputPath).toLowerCase();
|
|
181
|
+
}
|
|
182
|
+
// Check if directory exists
|
|
183
|
+
if (!fs.existsSync(dirToList)) {
|
|
184
|
+
return [];
|
|
185
|
+
}
|
|
186
|
+
const stat = fs.statSync(dirToList);
|
|
187
|
+
if (!stat.isDirectory()) {
|
|
188
|
+
return [];
|
|
189
|
+
}
|
|
190
|
+
// Read directory contents
|
|
191
|
+
const entries = fs.readdirSync(dirToList, { withFileTypes: true });
|
|
192
|
+
// Filter to directories only, apply prefix filter, and check for codev/
|
|
193
|
+
const suggestions = [];
|
|
194
|
+
for (const entry of entries) {
|
|
195
|
+
if (!entry.isDirectory())
|
|
196
|
+
continue;
|
|
197
|
+
if (entry.name.startsWith('.'))
|
|
198
|
+
continue; // Skip hidden directories
|
|
199
|
+
const name = entry.name.toLowerCase();
|
|
200
|
+
if (prefix && !name.startsWith(prefix))
|
|
201
|
+
continue;
|
|
202
|
+
const fullPath = path.join(dirToList, entry.name);
|
|
203
|
+
const isProject = fs.existsSync(path.join(fullPath, 'codev'));
|
|
204
|
+
suggestions.push({ path: fullPath, isProject });
|
|
205
|
+
}
|
|
206
|
+
// Sort: projects first, then alphabetically
|
|
207
|
+
suggestions.sort((a, b) => {
|
|
208
|
+
if (a.isProject !== b.isProject) {
|
|
209
|
+
return a.isProject ? -1 : 1;
|
|
210
|
+
}
|
|
211
|
+
return a.path.localeCompare(b.path);
|
|
212
|
+
});
|
|
213
|
+
// Limit to 20 suggestions
|
|
214
|
+
return suggestions.slice(0, 20);
|
|
215
|
+
}
|
|
216
|
+
// ============================================================================
|
|
217
|
+
// Instance lifecycle
|
|
218
|
+
// ============================================================================
|
|
219
|
+
/**
|
|
220
|
+
* Launch a new agent-farm instance.
|
|
221
|
+
* Phase 4 (Spec 0090): Tower manages terminals directly, no dashboard-server.
|
|
222
|
+
* Auto-adopts non-codev directories and creates architect terminal.
|
|
223
|
+
*/
|
|
224
|
+
export async function launchInstance(projectPath) {
|
|
225
|
+
if (!_deps)
|
|
226
|
+
return { success: false, error: 'Tower is still starting up. Try again shortly.' };
|
|
227
|
+
// Validate path exists
|
|
228
|
+
if (!fs.existsSync(projectPath)) {
|
|
229
|
+
return { success: false, error: `Path does not exist: ${projectPath}` };
|
|
230
|
+
}
|
|
231
|
+
// Validate it's a directory
|
|
232
|
+
const stat = fs.statSync(projectPath);
|
|
233
|
+
if (!stat.isDirectory()) {
|
|
234
|
+
return { success: false, error: `Not a directory: ${projectPath}` };
|
|
235
|
+
}
|
|
236
|
+
// Auto-adopt non-codev directories
|
|
237
|
+
const codevDir = path.join(projectPath, 'codev');
|
|
238
|
+
let adopted = false;
|
|
239
|
+
if (!fs.existsSync(codevDir)) {
|
|
240
|
+
try {
|
|
241
|
+
// Run codev adopt --yes to set up the project
|
|
242
|
+
execSync('npx codev adopt --yes', {
|
|
243
|
+
cwd: projectPath,
|
|
244
|
+
stdio: 'pipe',
|
|
245
|
+
timeout: 30000,
|
|
246
|
+
});
|
|
247
|
+
adopted = true;
|
|
248
|
+
_deps.log('INFO', `Auto-adopted codev in: ${projectPath}`);
|
|
249
|
+
}
|
|
250
|
+
catch (err) {
|
|
251
|
+
return { success: false, error: `Failed to adopt codev: ${err.message}` };
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
// Phase 4 (Spec 0090): Tower manages terminals directly
|
|
255
|
+
// No dashboard-server spawning - tower handles everything
|
|
256
|
+
try {
|
|
257
|
+
// Ensure project has port allocation
|
|
258
|
+
const resolvedPath = fs.realpathSync(projectPath);
|
|
259
|
+
// Persist in known_projects so the project survives terminal cleanup
|
|
260
|
+
registerKnownProject(resolvedPath);
|
|
261
|
+
// Initialize project terminal entry
|
|
262
|
+
const entry = _deps.getProjectTerminalsEntry(resolvedPath);
|
|
263
|
+
// Create architect terminal if not already present
|
|
264
|
+
if (!entry.architect) {
|
|
265
|
+
const manager = _deps.getTerminalManager();
|
|
266
|
+
// Read af-config.json to get the architect command
|
|
267
|
+
let architectCmd = 'claude';
|
|
268
|
+
const configPath = path.join(projectPath, 'af-config.json');
|
|
269
|
+
if (fs.existsSync(configPath)) {
|
|
270
|
+
try {
|
|
271
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
272
|
+
if (config.shell?.architect) {
|
|
273
|
+
architectCmd = config.shell.architect;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
catch {
|
|
277
|
+
// Ignore config read errors, use default
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
try {
|
|
281
|
+
// Parse command string to separate command and args, inject role prompt
|
|
282
|
+
const cmdParts = architectCmd.split(/\s+/);
|
|
283
|
+
const cmd = cmdParts[0];
|
|
284
|
+
const cmdArgs = buildArchitectArgs(cmdParts.slice(1), projectPath);
|
|
285
|
+
// Build env with CLAUDECODE removed so spawned Claude processes
|
|
286
|
+
// don't detect a nested session
|
|
287
|
+
const cleanEnv = { ...process.env };
|
|
288
|
+
delete cleanEnv['CLAUDECODE'];
|
|
289
|
+
// Try shellper first for persistent session with auto-restart
|
|
290
|
+
let shellperCreated = false;
|
|
291
|
+
if (_deps.shellperManager) {
|
|
292
|
+
try {
|
|
293
|
+
const sessionId = crypto.randomUUID();
|
|
294
|
+
const client = await _deps.shellperManager.createSession({
|
|
295
|
+
sessionId,
|
|
296
|
+
command: cmd,
|
|
297
|
+
args: cmdArgs,
|
|
298
|
+
cwd: projectPath,
|
|
299
|
+
env: cleanEnv,
|
|
300
|
+
cols: 200,
|
|
301
|
+
rows: 50,
|
|
302
|
+
restartOnExit: true,
|
|
303
|
+
restartDelay: 2000,
|
|
304
|
+
maxRestarts: 50,
|
|
305
|
+
});
|
|
306
|
+
// Get replay data and shellper info
|
|
307
|
+
const replayData = client.getReplayData() ?? Buffer.alloc(0);
|
|
308
|
+
const shellperInfo = _deps.shellperManager.getSessionInfo(sessionId);
|
|
309
|
+
// Create a PtySession backed by the shellper client
|
|
310
|
+
const session = manager.createSessionRaw({
|
|
311
|
+
label: 'Architect',
|
|
312
|
+
cwd: projectPath,
|
|
313
|
+
});
|
|
314
|
+
const ptySession = manager.getSession(session.id);
|
|
315
|
+
if (ptySession) {
|
|
316
|
+
ptySession.attachShellper(client, replayData, shellperInfo.pid, sessionId);
|
|
317
|
+
}
|
|
318
|
+
entry.architect = session.id;
|
|
319
|
+
_deps.saveTerminalSession(session.id, resolvedPath, 'architect', null, shellperInfo.pid, shellperInfo.socketPath, shellperInfo.pid, shellperInfo.startTime);
|
|
320
|
+
// Clean up cache/SQLite when the shellper session exits
|
|
321
|
+
if (ptySession) {
|
|
322
|
+
ptySession.on('exit', () => {
|
|
323
|
+
const currentEntry = _deps.getProjectTerminalsEntry(resolvedPath);
|
|
324
|
+
if (currentEntry.architect === session.id) {
|
|
325
|
+
currentEntry.architect = undefined;
|
|
326
|
+
}
|
|
327
|
+
_deps.deleteTerminalSession(session.id);
|
|
328
|
+
_deps.log('INFO', `Architect shellper session exited for ${projectPath}`);
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
shellperCreated = true;
|
|
332
|
+
_deps.log('INFO', `Created shellper-backed architect session for project: ${projectPath}`);
|
|
333
|
+
}
|
|
334
|
+
catch (shellperErr) {
|
|
335
|
+
_deps.log('WARN', `Shellper creation failed for architect, falling back: ${shellperErr.message}`);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
// Fallback: non-persistent session (graceful degradation per plan)
|
|
339
|
+
// Shellper is the only persistence backend for new sessions.
|
|
340
|
+
if (!shellperCreated) {
|
|
341
|
+
const session = await manager.createSession({
|
|
342
|
+
command: cmd,
|
|
343
|
+
args: cmdArgs,
|
|
344
|
+
cwd: projectPath,
|
|
345
|
+
label: 'Architect',
|
|
346
|
+
env: cleanEnv,
|
|
347
|
+
});
|
|
348
|
+
entry.architect = session.id;
|
|
349
|
+
_deps.saveTerminalSession(session.id, resolvedPath, 'architect', null, session.pid);
|
|
350
|
+
const ptySession = manager.getSession(session.id);
|
|
351
|
+
if (ptySession) {
|
|
352
|
+
ptySession.on('exit', () => {
|
|
353
|
+
const currentEntry = _deps.getProjectTerminalsEntry(resolvedPath);
|
|
354
|
+
if (currentEntry.architect === session.id) {
|
|
355
|
+
currentEntry.architect = undefined;
|
|
356
|
+
}
|
|
357
|
+
_deps.deleteTerminalSession(session.id);
|
|
358
|
+
_deps.log('INFO', `Architect pty exited for ${projectPath}`);
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
_deps.log('WARN', `Architect terminal for ${projectPath} is non-persistent (shellper unavailable)`);
|
|
362
|
+
}
|
|
363
|
+
_deps.log('INFO', `Created architect terminal for project: ${projectPath}`);
|
|
364
|
+
}
|
|
365
|
+
catch (err) {
|
|
366
|
+
_deps.log('WARN', `Failed to create architect terminal: ${err.message}`);
|
|
367
|
+
// Don't fail the launch - project is still active, just without architect
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
return { success: true, adopted };
|
|
371
|
+
}
|
|
372
|
+
catch (err) {
|
|
373
|
+
return { success: false, error: `Failed to launch: ${err.message}` };
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Kill a terminal session, including its shellper auto-restart if applicable.
|
|
378
|
+
* For shellper-backed sessions, calls SessionManager.killSession() which clears
|
|
379
|
+
* the restart timer and removes the session before sending SIGTERM, preventing
|
|
380
|
+
* the shellper from auto-restarting the process.
|
|
381
|
+
*/
|
|
382
|
+
export async function killTerminalWithShellper(manager, terminalId) {
|
|
383
|
+
if (!_deps)
|
|
384
|
+
return false;
|
|
385
|
+
const session = manager.getSession(terminalId);
|
|
386
|
+
if (!session)
|
|
387
|
+
return false;
|
|
388
|
+
// If shellper-backed, disable auto-restart via SessionManager before killing the PtySession
|
|
389
|
+
if (session.shellperBacked && session.shellperSessionId && _deps.shellperManager) {
|
|
390
|
+
await _deps.shellperManager.killSession(session.shellperSessionId);
|
|
391
|
+
}
|
|
392
|
+
return manager.killSession(terminalId);
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Stop an agent-farm instance by killing all its terminals.
|
|
396
|
+
* Phase 4 (Spec 0090): Tower manages terminals directly.
|
|
397
|
+
*/
|
|
398
|
+
export async function stopInstance(projectPath) {
|
|
399
|
+
if (!_deps)
|
|
400
|
+
return { success: false, error: 'Tower is still starting up. Try again shortly.', stopped: [] };
|
|
401
|
+
const stopped = [];
|
|
402
|
+
const manager = _deps.getTerminalManager();
|
|
403
|
+
// Resolve symlinks for consistent lookup
|
|
404
|
+
let resolvedPath = projectPath;
|
|
405
|
+
try {
|
|
406
|
+
if (fs.existsSync(projectPath)) {
|
|
407
|
+
resolvedPath = fs.realpathSync(projectPath);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
catch {
|
|
411
|
+
// Ignore - use original path
|
|
412
|
+
}
|
|
413
|
+
// Get project terminals
|
|
414
|
+
const entry = _deps.projectTerminals.get(resolvedPath) || _deps.projectTerminals.get(projectPath);
|
|
415
|
+
if (entry) {
|
|
416
|
+
// Kill architect (disable shellper auto-restart if applicable)
|
|
417
|
+
if (entry.architect) {
|
|
418
|
+
const session = manager.getSession(entry.architect);
|
|
419
|
+
if (session) {
|
|
420
|
+
await killTerminalWithShellper(manager, entry.architect);
|
|
421
|
+
stopped.push(session.pid);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
// Kill all shells (disable shellper auto-restart if applicable)
|
|
425
|
+
for (const terminalId of entry.shells.values()) {
|
|
426
|
+
const session = manager.getSession(terminalId);
|
|
427
|
+
if (session) {
|
|
428
|
+
await killTerminalWithShellper(manager, terminalId);
|
|
429
|
+
stopped.push(session.pid);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
// Kill all builders (disable shellper auto-restart if applicable)
|
|
433
|
+
for (const terminalId of entry.builders.values()) {
|
|
434
|
+
const session = manager.getSession(terminalId);
|
|
435
|
+
if (session) {
|
|
436
|
+
await killTerminalWithShellper(manager, terminalId);
|
|
437
|
+
stopped.push(session.pid);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
// Clear project from registry
|
|
441
|
+
_deps.projectTerminals.delete(resolvedPath);
|
|
442
|
+
_deps.projectTerminals.delete(projectPath);
|
|
443
|
+
// TICK-001: Delete all terminal sessions from SQLite
|
|
444
|
+
_deps.deleteProjectTerminalSessions(resolvedPath);
|
|
445
|
+
if (resolvedPath !== projectPath) {
|
|
446
|
+
_deps.deleteProjectTerminalSessions(projectPath);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
if (stopped.length === 0) {
|
|
450
|
+
return { success: true, error: 'No terminals found to stop', stopped };
|
|
451
|
+
}
|
|
452
|
+
return { success: true, stopped };
|
|
453
|
+
}
|
|
454
|
+
//# sourceMappingURL=tower-instances.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tower-instances.js","sourceRoot":"","sources":["../../../src/agent-farm/servers/tower-instances.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP route handlers for tower server.
|
|
3
|
+
* Spec 0105: Tower Server Decomposition — Phase 6
|
|
4
|
+
*
|
|
5
|
+
* Contains all HTTP request routing and response logic.
|
|
6
|
+
* The orchestrator (tower-server.ts) creates the HTTP server and
|
|
7
|
+
* delegates to handleRequest() for all HTTP requests.
|
|
8
|
+
*
|
|
9
|
+
* NOTE: This file exceeds the 900-line guideline because it contains
|
|
10
|
+
* all HTTP route handlers (~30 routes) which share a single responsibility
|
|
11
|
+
* (HTTP request handling). Splitting would create arbitrary boundaries
|
|
12
|
+
* without improving cohesion. See spec: "cohesion trumps arbitrary ceilings."
|
|
13
|
+
*/
|
|
14
|
+
import http from 'node:http';
|
|
15
|
+
import type { SessionManager } from '../../terminal/session-manager.js';
|
|
16
|
+
import type { SSEClient } from './tower-types.js';
|
|
17
|
+
export interface RouteContext {
|
|
18
|
+
log: (level: 'INFO' | 'ERROR' | 'WARN', message: string) => void;
|
|
19
|
+
port: number;
|
|
20
|
+
templatePath: string | null;
|
|
21
|
+
reactDashboardPath: string;
|
|
22
|
+
hasReactDashboard: boolean;
|
|
23
|
+
getShellperManager: () => SessionManager | null;
|
|
24
|
+
broadcastNotification: (notification: {
|
|
25
|
+
type: string;
|
|
26
|
+
title: string;
|
|
27
|
+
body: string;
|
|
28
|
+
project?: string;
|
|
29
|
+
}) => void;
|
|
30
|
+
addSseClient: (client: SSEClient) => void;
|
|
31
|
+
removeSseClient: (id: string) => void;
|
|
32
|
+
}
|
|
33
|
+
export declare function handleRequest(req: http.IncomingMessage, res: http.ServerResponse, ctx: RouteContext): Promise<void>;
|
|
34
|
+
//# sourceMappingURL=tower-routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tower-routes.d.ts","sourceRoot":"","sources":["../../../src/agent-farm/servers/tower-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAO7B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAExE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAuClD,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,kBAAkB,EAAE,MAAM,cAAc,GAAG,IAAI,CAAC;IAChD,qBAAqB,EAAE,CAAC,YAAY,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC/G,YAAY,EAAE,CAAC,MAAM,EAAE,SAAS,KAAK,IAAI,CAAC;IAC1C,eAAe,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC;AA6CD,wBAAsB,aAAa,CACjC,GAAG,EAAE,IAAI,CAAC,eAAe,EACzB,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,GAAG,EAAE,YAAY,GAChB,OAAO,CAAC,IAAI,CAAC,CAuEf"}
|