@cluesmith/codev 3.2.2 → 3.2.4
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-BZ1x7x1X.js.map +1 -1
- package/dist/agent-farm/cli.d.ts.map +1 -1
- package/dist/agent-farm/cli.js +31 -0
- package/dist/agent-farm/cli.js.map +1 -1
- package/dist/agent-farm/commands/attach.js +2 -2
- package/dist/agent-farm/commands/attach.js.map +1 -1
- package/dist/agent-farm/commands/send.d.ts +2 -2
- package/dist/agent-farm/commands/send.js +3 -3
- package/dist/agent-farm/commands/send.js.map +1 -1
- package/dist/agent-farm/commands/setup.d.ts +4 -1
- package/dist/agent-farm/commands/setup.d.ts.map +1 -1
- package/dist/agent-farm/commands/setup.js +8 -4
- package/dist/agent-farm/commands/setup.js.map +1 -1
- package/dist/agent-farm/commands/spawn-worktree.d.ts +11 -0
- package/dist/agent-farm/commands/spawn-worktree.d.ts.map +1 -1
- package/dist/agent-farm/commands/spawn-worktree.js +64 -16
- package/dist/agent-farm/commands/spawn-worktree.js.map +1 -1
- package/dist/agent-farm/commands/status.d.ts.map +1 -1
- package/dist/agent-farm/commands/status.js +26 -2
- package/dist/agent-farm/commands/status.js.map +1 -1
- package/dist/agent-farm/commands/tower-sweep-husks.d.ts +6 -0
- package/dist/agent-farm/commands/tower-sweep-husks.d.ts.map +1 -0
- package/dist/agent-farm/commands/tower-sweep-husks.js +77 -0
- package/dist/agent-farm/commands/tower-sweep-husks.js.map +1 -0
- package/dist/agent-farm/commands/tower.d.ts.map +1 -1
- package/dist/agent-farm/commands/tower.js +34 -0
- package/dist/agent-farm/commands/tower.js.map +1 -1
- package/dist/agent-farm/commands/whoami.d.ts +65 -0
- package/dist/agent-farm/commands/whoami.d.ts.map +1 -0
- package/dist/agent-farm/commands/whoami.js +196 -0
- package/dist/agent-farm/commands/whoami.js.map +1 -0
- package/dist/agent-farm/commands/workspace-recover.d.ts +31 -0
- package/dist/agent-farm/commands/workspace-recover.d.ts.map +1 -1
- package/dist/agent-farm/commands/workspace-recover.js +70 -30
- package/dist/agent-farm/commands/workspace-recover.js.map +1 -1
- package/dist/agent-farm/db/index.d.ts.map +1 -1
- package/dist/agent-farm/db/index.js +8 -2
- package/dist/agent-farm/db/index.js.map +1 -1
- package/dist/agent-farm/lib/tower-client.d.ts +1 -1
- package/dist/agent-farm/lib/tower-client.d.ts.map +1 -1
- package/dist/agent-farm/lib/tower-client.js.map +1 -1
- package/dist/agent-farm/servers/architect-session-holder.d.ts +133 -0
- package/dist/agent-farm/servers/architect-session-holder.d.ts.map +1 -0
- package/dist/agent-farm/servers/architect-session-holder.js +268 -0
- package/dist/agent-farm/servers/architect-session-holder.js.map +1 -0
- package/dist/agent-farm/servers/process-census.d.ts +41 -0
- package/dist/agent-farm/servers/process-census.d.ts.map +1 -0
- package/dist/agent-farm/servers/process-census.js +62 -0
- package/dist/agent-farm/servers/process-census.js.map +1 -0
- package/dist/agent-farm/servers/send-buffer.d.ts.map +1 -1
- package/dist/agent-farm/servers/send-buffer.js +13 -0
- package/dist/agent-farm/servers/send-buffer.js.map +1 -1
- package/dist/agent-farm/servers/session-log-sweep.d.ts +93 -0
- package/dist/agent-farm/servers/session-log-sweep.d.ts.map +1 -0
- package/dist/agent-farm/servers/session-log-sweep.js +165 -0
- package/dist/agent-farm/servers/session-log-sweep.js.map +1 -0
- package/dist/agent-farm/servers/shellper-husk-sweep.d.ts +87 -0
- package/dist/agent-farm/servers/shellper-husk-sweep.d.ts.map +1 -0
- package/dist/agent-farm/servers/shellper-husk-sweep.js +129 -0
- package/dist/agent-farm/servers/shellper-husk-sweep.js.map +1 -0
- package/dist/agent-farm/servers/tower-instances.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-instances.js +203 -36
- package/dist/agent-farm/servers/tower-instances.js.map +1 -1
- package/dist/agent-farm/servers/tower-routes.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-routes.js +147 -4
- package/dist/agent-farm/servers/tower-routes.js.map +1 -1
- package/dist/agent-farm/servers/tower-server.js +95 -1
- package/dist/agent-farm/servers/tower-server.js.map +1 -1
- package/dist/agent-farm/servers/tower-terminals.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-terminals.js +66 -8
- package/dist/agent-farm/servers/tower-terminals.js.map +1 -1
- package/dist/agent-farm/servers/tower-utils.d.ts +106 -4
- package/dist/agent-farm/servers/tower-utils.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-utils.js +155 -19
- package/dist/agent-farm/servers/tower-utils.js.map +1 -1
- package/dist/agent-farm/state.d.ts +13 -1
- package/dist/agent-farm/state.d.ts.map +1 -1
- package/dist/agent-farm/state.js +17 -2
- package/dist/agent-farm/state.js.map +1 -1
- package/dist/agent-farm/utils/claude-session-discovery.d.ts +12 -0
- package/dist/agent-farm/utils/claude-session-discovery.d.ts.map +1 -1
- package/dist/agent-farm/utils/claude-session-discovery.js +42 -4
- package/dist/agent-farm/utils/claude-session-discovery.js.map +1 -1
- package/dist/agent-farm/utils/harness.d.ts +15 -3
- package/dist/agent-farm/utils/harness.d.ts.map +1 -1
- package/dist/agent-farm/utils/harness.js +4 -1
- package/dist/agent-farm/utils/harness.js.map +1 -1
- package/dist/commands/adopt.d.ts +3 -2
- package/dist/commands/adopt.d.ts.map +1 -1
- package/dist/commands/adopt.js +7 -6
- package/dist/commands/adopt.js.map +1 -1
- package/dist/commands/consult/agy-auth-cache.d.ts +97 -0
- package/dist/commands/consult/agy-auth-cache.d.ts.map +1 -0
- package/dist/commands/consult/agy-auth-cache.js +320 -0
- package/dist/commands/consult/agy-auth-cache.js.map +1 -0
- package/dist/commands/consult/index.d.ts.map +1 -1
- package/dist/commands/consult/index.js +59 -0
- package/dist/commands/consult/index.js.map +1 -1
- package/dist/commands/doctor.d.ts +28 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +187 -3
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/init.d.ts +3 -2
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +7 -6
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/porch/index.d.ts.map +1 -1
- package/dist/commands/porch/index.js +11 -8
- package/dist/commands/porch/index.js.map +1 -1
- package/dist/commands/update.d.ts +4 -4
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +9 -11
- package/dist/commands/update.js.map +1 -1
- package/dist/lib/config.d.ts +1 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/default-branch.d.ts +1 -1
- package/dist/lib/default-branch.js +1 -1
- package/dist/lib/gitignore.d.ts +25 -2
- package/dist/lib/gitignore.d.ts.map +1 -1
- package/dist/lib/gitignore.js +70 -0
- package/dist/lib/gitignore.js.map +1 -1
- package/dist/lib/migration-backup-audit.d.ts +64 -0
- package/dist/lib/migration-backup-audit.d.ts.map +1 -0
- package/dist/lib/migration-backup-audit.js +145 -0
- package/dist/lib/migration-backup-audit.js.map +1 -0
- package/dist/lib/protocol-drift-audit.d.ts +118 -0
- package/dist/lib/protocol-drift-audit.d.ts.map +1 -0
- package/dist/lib/protocol-drift-audit.js +217 -0
- package/dist/lib/protocol-drift-audit.js.map +1 -0
- package/dist/lib/scaffold.d.ts +10 -3
- package/dist/lib/scaffold.d.ts.map +1 -1
- package/dist/lib/scaffold.js +29 -26
- package/dist/lib/scaffold.js.map +1 -1
- package/dist/terminal/pty-manager.d.ts +7 -0
- package/dist/terminal/pty-manager.d.ts.map +1 -1
- package/dist/terminal/pty-manager.js +16 -0
- package/dist/terminal/pty-manager.js.map +1 -1
- package/dist/terminal/pty-session.d.ts +25 -4
- package/dist/terminal/pty-session.d.ts.map +1 -1
- package/dist/terminal/pty-session.js +83 -11
- package/dist/terminal/pty-session.js.map +1 -1
- package/dist/terminal/session-manager.d.ts +109 -0
- package/dist/terminal/session-manager.d.ts.map +1 -1
- package/dist/terminal/session-manager.js +314 -45
- package/dist/terminal/session-manager.js.map +1 -1
- package/dist/terminal/shellper-client.d.ts +19 -4
- package/dist/terminal/shellper-client.d.ts.map +1 -1
- package/dist/terminal/shellper-client.js +70 -8
- package/dist/terminal/shellper-client.js.map +1 -1
- package/dist/terminal/shellper-process.d.ts.map +1 -1
- package/dist/terminal/shellper-process.js +20 -5
- package/dist/terminal/shellper-process.js.map +1 -1
- package/dist/terminal/shellper-protocol.d.ts +40 -2
- package/dist/terminal/shellper-protocol.d.ts.map +1 -1
- package/dist/terminal/shellper-protocol.js +72 -5
- package/dist/terminal/shellper-protocol.js.map +1 -1
- package/package.json +8 -8
- package/skeleton/.claude/skills/afx/SKILL.md +13 -0
- package/skeleton/.claude/skills/arch-init/SKILL.md +122 -0
- package/skeleton/.claude/skills/codev/SKILL.md +2 -2
- package/skeleton/.codex/skills/afx/SKILL.md +157 -0
- package/skeleton/.codex/skills/arch-init/SKILL.md +122 -0
- package/skeleton/.codex/skills/codev/SKILL.md +59 -0
- package/skeleton/.codex/skills/consult/SKILL.md +96 -0
- package/skeleton/.codex/skills/generate-image/SKILL.md +45 -0
- package/skeleton/.codex/skills/porch/SKILL.md +60 -0
- package/skeleton/.codex/skills/update-arch-docs/SKILL.md +132 -0
- package/skeleton/protocols/pir/prompts/implement.md +1 -1
- package/skeleton/protocols/pir/prompts/review.md +1 -1
- package/skeleton/protocols/pir/protocol.md +3 -3
- package/skeleton/resources/commands/agent-farm.md +89 -0
- package/skeleton/resources/commands/codev.md +5 -0
- package/skeleton/resources/commands/consult.md +26 -0
- package/skeleton/roles/architect.md +11 -0
|
@@ -42,6 +42,9 @@ import { fetchIssue, searchIssues, fetchPRList, fetchCurrentUser, parseLinkedIss
|
|
|
42
42
|
import { computeAnalytics } from './analytics.js';
|
|
43
43
|
import { getAllTasks, executeTask, getTaskId } from './tower-cron.js';
|
|
44
44
|
import { getGlobalDb } from '../db/index.js';
|
|
45
|
+
import { listProcessCensus } from './process-census.js';
|
|
46
|
+
import { SHELLPER_MARKER, computeRegisteredShellperPids, findHuskShellpers, sweepShellperHusks, resolveHuskGraceMs, } from './shellper-husk-sweep.js';
|
|
47
|
+
import { getProcessStartTime } from '../../terminal/session-manager.js';
|
|
45
48
|
import { getWorkspaceTerminals, getTerminalManager, getWorkspaceTerminalsEntry, getNextShellId, saveTerminalSession, isSessionPersistent, deleteTerminalSession, removeTerminalFromRegistry, deleteWorkspaceTerminalSessions, deleteFileTabsForWorkspace, saveFileTab, deleteFileTab, getRehydratedTerminalsEntry, isStartupReconcileSettled, getTerminalSessionById, getActiveShellLabels, updateTerminalLabel, } from './tower-terminals.js';
|
|
46
49
|
const __filename = fileURLToPath(import.meta.url);
|
|
47
50
|
const __dirname = path.dirname(__filename);
|
|
@@ -65,7 +68,9 @@ export function stopSendBuffer() {
|
|
|
65
68
|
sendBuffer.stop();
|
|
66
69
|
}
|
|
67
70
|
const ROUTES = {
|
|
68
|
-
'GET /health': (_req, res) => handleHealthCheck(res),
|
|
71
|
+
'GET /health': (_req, res, _url, ctx) => handleHealthCheck(res, ctx),
|
|
72
|
+
'GET /api/shellpers/husks': (_req, res, _url, ctx) => handleHuskPreview(res, ctx),
|
|
73
|
+
'POST /api/shellpers/husks/sweep': (_req, res, _url, ctx) => handleHuskSweep(res, ctx),
|
|
69
74
|
'GET /api/workspaces': (_req, res) => handleListWorkspaces(res),
|
|
70
75
|
'POST /api/terminals': (req, res, _url, ctx) => handleTerminalCreate(req, res, ctx),
|
|
71
76
|
'GET /api/terminals': (_req, res) => handleTerminalList(res),
|
|
@@ -177,9 +182,56 @@ export async function handleRequest(req, res, ctx) {
|
|
|
177
182
|
// ============================================================================
|
|
178
183
|
// Global route handlers
|
|
179
184
|
// ============================================================================
|
|
180
|
-
|
|
185
|
+
/**
|
|
186
|
+
* Issue #1227: fleet RSS + unregistered-shellper count, scoped to this Tower
|
|
187
|
+
* instance's socketDir. `fleetRssKb` sums every in-scope shellper AND its
|
|
188
|
+
* direct children (the full process-group tree Tower manages) regardless of
|
|
189
|
+
* DB-registration state, so a husk not yet swept still counts toward the
|
|
190
|
+
* visible cost. `unregisteredShellperCount` is the lighter, ungated signal
|
|
191
|
+
* ("N shellpers Tower doesn't currently track") — distinct from the stricter
|
|
192
|
+
* childless+aged reap predicate in shellper-husk-sweep.ts.
|
|
193
|
+
*
|
|
194
|
+
* Best-effort: returns undefined fields (never throws) if `ps` or the DB read
|
|
195
|
+
* fails, so a fleet-accounting hiccup never takes down /health itself.
|
|
196
|
+
*/
|
|
197
|
+
async function computeFleetHealthFields(ctx) {
|
|
198
|
+
const shellperManager = ctx.getShellperManager();
|
|
199
|
+
if (!shellperManager)
|
|
200
|
+
return {};
|
|
201
|
+
try {
|
|
202
|
+
const census = await listProcessCensus();
|
|
203
|
+
const scopeMarker = shellperManager.socketDir.endsWith('/')
|
|
204
|
+
? shellperManager.socketDir
|
|
205
|
+
: `${shellperManager.socketDir}/`;
|
|
206
|
+
const inScopePids = new Set();
|
|
207
|
+
let fleetRssKb = 0;
|
|
208
|
+
for (const entry of census) {
|
|
209
|
+
if (entry.cmdline.includes(SHELLPER_MARKER) && entry.cmdline.includes(scopeMarker)) {
|
|
210
|
+
inScopePids.add(entry.pid);
|
|
211
|
+
fleetRssKb += entry.rssKb;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
for (const entry of census) {
|
|
215
|
+
if (inScopePids.has(entry.ppid)) {
|
|
216
|
+
fleetRssKb += entry.rssKb;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
const registered = await computeRegisteredShellperPids(getGlobalDb());
|
|
220
|
+
let unregisteredShellperCount = 0;
|
|
221
|
+
for (const pid of inScopePids) {
|
|
222
|
+
if (!registered.has(pid))
|
|
223
|
+
unregisteredShellperCount++;
|
|
224
|
+
}
|
|
225
|
+
return { fleetRssKb, unregisteredShellperCount };
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
return {};
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
async function handleHealthCheck(res, ctx) {
|
|
181
232
|
const instances = await getInstances();
|
|
182
233
|
const activeCount = instances.filter((i) => i.running).length;
|
|
234
|
+
const fleetFields = await computeFleetHealthFields(ctx);
|
|
183
235
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
184
236
|
res.end(JSON.stringify({
|
|
185
237
|
status: 'healthy',
|
|
@@ -191,9 +243,82 @@ async function handleHealthCheck(res) {
|
|
|
191
243
|
activeWorkspaces: activeCount,
|
|
192
244
|
totalWorkspaces: instances.length,
|
|
193
245
|
memoryUsage: process.memoryUsage().heapUsed,
|
|
246
|
+
...fleetFields,
|
|
194
247
|
timestamp: new Date().toISOString(),
|
|
195
248
|
}));
|
|
196
249
|
}
|
|
250
|
+
/**
|
|
251
|
+
* Issue #1227: GET /api/shellpers/husks — preview, read-only. Returns the
|
|
252
|
+
* husk candidates the next sweep (periodic or `--apply`) would reap, without
|
|
253
|
+
* touching anything.
|
|
254
|
+
*/
|
|
255
|
+
async function handleHuskPreview(res, ctx) {
|
|
256
|
+
const shellperManager = ctx.getShellperManager();
|
|
257
|
+
if (!shellperManager) {
|
|
258
|
+
res.writeHead(503, { 'Content-Type': 'application/json' });
|
|
259
|
+
res.end(JSON.stringify({ error: 'Shellper manager not initialized' }));
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
try {
|
|
263
|
+
const graceMs = resolveHuskGraceMs();
|
|
264
|
+
// One census snapshot, shared between the candidate decision and the
|
|
265
|
+
// displayed RSS — passing it via the `census` seam avoids a second `ps`
|
|
266
|
+
// scan and guarantees the RSS shown is for the exact snapshot that decided
|
|
267
|
+
// candidacy, not a later, possibly-different one (codex #1227 PR review).
|
|
268
|
+
const census = await listProcessCensus();
|
|
269
|
+
const rssByPid = new Map(census.map((entry) => [entry.pid, entry.rssKb]));
|
|
270
|
+
const registered = await computeRegisteredShellperPids(getGlobalDb());
|
|
271
|
+
const pids = await findHuskShellpers({
|
|
272
|
+
socketDir: shellperManager.socketDir,
|
|
273
|
+
registeredShellperPids: registered,
|
|
274
|
+
graceMs,
|
|
275
|
+
census: () => census,
|
|
276
|
+
});
|
|
277
|
+
const now = Date.now();
|
|
278
|
+
const candidates = await Promise.all(pids.map(async (pid) => {
|
|
279
|
+
const startTime = await getProcessStartTime(pid);
|
|
280
|
+
return {
|
|
281
|
+
pid,
|
|
282
|
+
rssKb: rssByPid.get(pid) ?? 0,
|
|
283
|
+
ageMs: startTime !== null ? now - startTime : null,
|
|
284
|
+
};
|
|
285
|
+
}));
|
|
286
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
287
|
+
res.end(JSON.stringify({ candidates, graceMs }));
|
|
288
|
+
}
|
|
289
|
+
catch (err) {
|
|
290
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
291
|
+
res.end(JSON.stringify({ error: err.message }));
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Issue #1227: POST /api/shellpers/husks/sweep — apply. Actually reaps the
|
|
296
|
+
* current husk candidates. Destructive; the `afx tower sweep-husks` CLI is
|
|
297
|
+
* the only caller expected in practice, and it gates this behind `--apply`
|
|
298
|
+
* plus a confirmation prompt (unless `--yes`).
|
|
299
|
+
*/
|
|
300
|
+
async function handleHuskSweep(res, ctx) {
|
|
301
|
+
const shellperManager = ctx.getShellperManager();
|
|
302
|
+
if (!shellperManager) {
|
|
303
|
+
res.writeHead(503, { 'Content-Type': 'application/json' });
|
|
304
|
+
res.end(JSON.stringify({ error: 'Shellper manager not initialized' }));
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
try {
|
|
308
|
+
const result = await sweepShellperHusks({
|
|
309
|
+
socketDir: shellperManager.socketDir,
|
|
310
|
+
db: getGlobalDb(),
|
|
311
|
+
graceMs: resolveHuskGraceMs(),
|
|
312
|
+
log: (msg) => ctx.log('INFO', msg),
|
|
313
|
+
});
|
|
314
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
315
|
+
res.end(JSON.stringify(result));
|
|
316
|
+
}
|
|
317
|
+
catch (err) {
|
|
318
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
319
|
+
res.end(JSON.stringify({ error: err.message }));
|
|
320
|
+
}
|
|
321
|
+
}
|
|
197
322
|
/**
|
|
198
323
|
* GET /api/version (#983) — report the version of the *running* Tower process.
|
|
199
324
|
*
|
|
@@ -448,8 +573,11 @@ async function handleTerminalCreate(req, res, ctx) {
|
|
|
448
573
|
...defaultSessionOptions(),
|
|
449
574
|
cols: cols || DEFAULT_COLS,
|
|
450
575
|
});
|
|
451
|
-
|
|
576
|
+
// Read session info BEFORE awaiting replay: an instantly-exiting
|
|
577
|
+
// child's EXIT frame can remove the session from the manager during
|
|
578
|
+
// the await, and this lookup must not miss (#1198).
|
|
452
579
|
const shellperInfo = shellperManager.getSessionInfo(sessionId);
|
|
580
|
+
const replayData = await client.waitForReplay(); // #1198: fresh shellpers always send REPLAY (possibly empty); awaiting avoids racing early child output
|
|
453
581
|
const session = manager.createSessionRaw({
|
|
454
582
|
label: label || `terminal-${sessionId.slice(0, 8)}`,
|
|
455
583
|
cwd,
|
|
@@ -1083,6 +1211,18 @@ async function handleSend(req, res, ctx) {
|
|
|
1083
1211
|
}));
|
|
1084
1212
|
return;
|
|
1085
1213
|
}
|
|
1214
|
+
// #1198: a session whose shellper connection died still reports status
|
|
1215
|
+
// 'running', but every write to it is dropped. Fail the send loudly
|
|
1216
|
+
// instead of logging "Message sent" for a message that went nowhere.
|
|
1217
|
+
if (!session.writable) {
|
|
1218
|
+
ctx.log('ERROR', `Message DROPPED: ${from ?? 'unknown'} → ${result.agent} (terminal ${result.terminalId.slice(0, 8)}...): terminal not writable (shellper connection down)`);
|
|
1219
|
+
res.writeHead(503, { 'Content-Type': 'application/json' });
|
|
1220
|
+
res.end(JSON.stringify({
|
|
1221
|
+
error: 'TERMINAL_NOT_WRITABLE',
|
|
1222
|
+
message: `Terminal for '${result.agent}' is not accepting input (its process connection is down). Retry shortly; if this persists, check Tower logs.`,
|
|
1223
|
+
}));
|
|
1224
|
+
return;
|
|
1225
|
+
}
|
|
1086
1226
|
// Format the message based on sender/target
|
|
1087
1227
|
const isArchitectTarget = result.agent === 'architect';
|
|
1088
1228
|
let formattedMessage;
|
|
@@ -1706,8 +1846,11 @@ async function handleWorkspaceShellCreate(res, ctx, workspacePath) {
|
|
|
1706
1846
|
env: shellEnv,
|
|
1707
1847
|
...defaultSessionOptions(),
|
|
1708
1848
|
});
|
|
1709
|
-
|
|
1849
|
+
// Read session info BEFORE awaiting replay: an instantly-exiting
|
|
1850
|
+
// child's EXIT frame can remove the session from the manager during
|
|
1851
|
+
// the await, and this lookup must not miss (#1198).
|
|
1710
1852
|
const shellperInfo = shellperManager.getSessionInfo(sessionId);
|
|
1853
|
+
const replayData = await client.waitForReplay(); // #1198: fresh shellpers always send REPLAY (possibly empty); awaiting avoids racing early child output
|
|
1711
1854
|
const session = manager.createSessionRaw({
|
|
1712
1855
|
label: `Shell ${shellId.replace('shell-', '')}`,
|
|
1713
1856
|
cwd: workspacePath,
|