ftown-bridge 0.3.16 → 0.5.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/dist/agent-commands.js +1 -1
- package/dist/agent-commands.js.map +1 -1
- package/dist/claude-runner.d.ts +29 -0
- package/dist/claude-runner.js +246 -44
- package/dist/claude-runner.js.map +1 -1
- package/dist/create-ftown-session.d.ts +16 -0
- package/dist/create-ftown-session.js +70 -5
- package/dist/create-ftown-session.js.map +1 -1
- package/dist/cursor-hook-installer.d.ts +0 -2
- package/dist/cursor-hook-installer.js +3 -14
- package/dist/cursor-hook-installer.js.map +1 -1
- package/dist/ftown-sessions-cli.js +120 -2
- package/dist/ftown-sessions-cli.js.map +1 -1
- package/dist/hook-installer.js +1 -1
- package/dist/hook-installer.js.map +1 -1
- package/dist/index.js +245 -42
- package/dist/index.js.map +1 -1
- package/dist/local-api-server.d.ts +2 -0
- package/dist/local-api-server.js +197 -4
- package/dist/local-api-server.js.map +1 -1
- package/dist/remove-ftown-session.d.ts +23 -0
- package/dist/remove-ftown-session.js +32 -0
- package/dist/remove-ftown-session.js.map +1 -0
- package/dist/session-registry.d.ts +11 -1
- package/dist/session-registry.js +3 -3
- package/dist/session-registry.js.map +1 -1
- package/dist/session-store.d.ts +6 -1
- package/dist/session-store.js +32 -1
- package/dist/session-store.js.map +1 -1
- package/dist/tmux.d.ts +24 -0
- package/dist/tmux.js +149 -0
- package/dist/tmux.js.map +1 -0
- package/dist/types.d.ts +9 -0
- package/hooks/notify.sh +34 -12
- package/package.json +1 -1
- package/skills/ftown-sessions/SKILL.md +49 -0
- package/skills/bridge-harness/SKILL.md +0 -43
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cursor-hook-installer.js","sourceRoot":"","sources":["../src/cursor-hook-installer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACzF,OAAO,EAAE,IAAI,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"cursor-hook-installer.js","sourceRoot":"","sources":["../src/cursor-hook-installer.ts"],"names":[],"mappings":"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"}
|
|
@@ -47,6 +47,33 @@ async function api(method, path, body, extraHeaders) {
|
|
|
47
47
|
}
|
|
48
48
|
return { status: res.status, data };
|
|
49
49
|
}
|
|
50
|
+
async function listSessionInfo() {
|
|
51
|
+
const { data } = await api('GET', '/api/sessions');
|
|
52
|
+
return data.sessions ?? [];
|
|
53
|
+
}
|
|
54
|
+
async function resolveFanout(mode, self) {
|
|
55
|
+
if (!self) {
|
|
56
|
+
throw new Error(`--${mode} requires FTOWN_SESSION_ID to be set`);
|
|
57
|
+
}
|
|
58
|
+
const sessions = await listSessionInfo();
|
|
59
|
+
const me = sessions.find((s) => s.id === self);
|
|
60
|
+
if (mode === 'parent') {
|
|
61
|
+
const parent = me?.parentSessionId;
|
|
62
|
+
if (!parent)
|
|
63
|
+
throw new Error('Current session has no parent');
|
|
64
|
+
return [parent];
|
|
65
|
+
}
|
|
66
|
+
if (mode === 'children') {
|
|
67
|
+
return sessions.filter((s) => s.parentSessionId === self).map((s) => s.id);
|
|
68
|
+
}
|
|
69
|
+
// siblings
|
|
70
|
+
const parent = me?.parentSessionId;
|
|
71
|
+
if (!parent)
|
|
72
|
+
throw new Error('Current session has no parent (cannot resolve siblings)');
|
|
73
|
+
return sessions
|
|
74
|
+
.filter((s) => s.parentSessionId === parent && s.id !== self)
|
|
75
|
+
.map((s) => s.id);
|
|
76
|
+
}
|
|
50
77
|
function flag(args, name) {
|
|
51
78
|
const i = args.indexOf(name);
|
|
52
79
|
if (i === -1 || i + 1 >= args.length)
|
|
@@ -66,7 +93,17 @@ Commands:
|
|
|
66
93
|
screen <session-id> Print terminal lines
|
|
67
94
|
grep <session-id> Search terminal output
|
|
68
95
|
keys <session-id> <text> Send keys to a running session
|
|
96
|
+
tell <target> <message...> Send a text message to another session's terminal
|
|
69
97
|
running <session-id> Check if session PTY is running
|
|
98
|
+
remove <session-id> Stop and remove a session (archived as a tombstone)
|
|
99
|
+
archive List archived (removed) sessions
|
|
100
|
+
revive <session-id> Recreate a removed session from its tombstone
|
|
101
|
+
|
|
102
|
+
Tell targets (one of):
|
|
103
|
+
<session-id> Explicit target session id
|
|
104
|
+
--parent Message FTOWN_SESSION_ID's parent session
|
|
105
|
+
--children Message all sessions parented to FTOWN_SESSION_ID
|
|
106
|
+
--siblings Message sessions sharing my parent (excluding me)
|
|
70
107
|
|
|
71
108
|
Create options:
|
|
72
109
|
--shell <type> cursor | claude | shell | opencode (default: claude)
|
|
@@ -76,6 +113,7 @@ Create options:
|
|
|
76
113
|
--command <cmd> Full command override
|
|
77
114
|
--parent Link parent to FTOWN_SESSION_ID or X-Ftown-Session-Id
|
|
78
115
|
--parent-id <uuid> Explicit parent session id
|
|
116
|
+
--orchestrator Brief the new agent to spawn and coordinate sibling sessions
|
|
79
117
|
--model <name> Model (cursor)
|
|
80
118
|
--json Output raw JSON (default for most commands)
|
|
81
119
|
|
|
@@ -113,6 +151,7 @@ async function main() {
|
|
|
113
151
|
const model = flag(rest, '--model');
|
|
114
152
|
const parentId = flag(rest, '--parent-id');
|
|
115
153
|
const useParent = hasFlag(rest, '--parent');
|
|
154
|
+
const orchestrator = hasFlag(rest, '--orchestrator');
|
|
116
155
|
const body = {};
|
|
117
156
|
if (shellType)
|
|
118
157
|
body.shellType = shellType;
|
|
@@ -130,6 +169,8 @@ async function main() {
|
|
|
130
169
|
body.parentSessionId = parentId;
|
|
131
170
|
else if (useParent)
|
|
132
171
|
body.parentSessionId = true;
|
|
172
|
+
if (orchestrator)
|
|
173
|
+
body.orchestrator = true;
|
|
133
174
|
const caller = process.env.FTOWN_SESSION_ID?.trim();
|
|
134
175
|
const headers = useParent && caller ? { 'X-Ftown-Session-Id': caller } : undefined;
|
|
135
176
|
const { data } = await api('POST', '/api/sessions', body, headers);
|
|
@@ -188,6 +229,49 @@ async function main() {
|
|
|
188
229
|
console.log(JSON.stringify({ sent: true, sessionId: id }));
|
|
189
230
|
break;
|
|
190
231
|
}
|
|
232
|
+
case 'tell': {
|
|
233
|
+
const useParent = hasFlag(rest, '--parent');
|
|
234
|
+
const useChildren = hasFlag(rest, '--children');
|
|
235
|
+
const useSiblings = hasFlag(rest, '--siblings');
|
|
236
|
+
const fanCount = [useParent, useChildren, useSiblings].filter(Boolean).length;
|
|
237
|
+
if (fanCount > 1) {
|
|
238
|
+
throw new Error('Use only one of --parent, --children, --siblings');
|
|
239
|
+
}
|
|
240
|
+
const positional = rest.filter((a) => !a.startsWith('--'));
|
|
241
|
+
const self = process.env.FTOWN_SESSION_ID?.trim();
|
|
242
|
+
let targets;
|
|
243
|
+
let message;
|
|
244
|
+
if (fanCount === 1) {
|
|
245
|
+
message = positional.join(' ');
|
|
246
|
+
targets = await resolveFanout(useParent ? 'parent' : useChildren ? 'children' : 'siblings', self);
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
const target = positional[0];
|
|
250
|
+
message = positional.slice(1).join(' ');
|
|
251
|
+
if (!target) {
|
|
252
|
+
throw new Error('Usage: tell <target|--parent|--children|--siblings> <message...>');
|
|
253
|
+
}
|
|
254
|
+
targets = [target];
|
|
255
|
+
}
|
|
256
|
+
if (!message)
|
|
257
|
+
throw new Error('Missing message');
|
|
258
|
+
if (targets.length === 0)
|
|
259
|
+
throw new Error('No matching target sessions');
|
|
260
|
+
for (const target of targets) {
|
|
261
|
+
const reqBody = { text: message };
|
|
262
|
+
if (self)
|
|
263
|
+
reqBody.from = self;
|
|
264
|
+
try {
|
|
265
|
+
const { data } = await api('POST', `/api/sessions/${target}/message`, reqBody);
|
|
266
|
+
console.log(JSON.stringify({ target, ...data }));
|
|
267
|
+
}
|
|
268
|
+
catch (err) {
|
|
269
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
270
|
+
console.log(JSON.stringify({ target, error: msg }));
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
break;
|
|
274
|
+
}
|
|
191
275
|
case 'running': {
|
|
192
276
|
const id = rest.find((a) => !a.startsWith('--'));
|
|
193
277
|
if (!id)
|
|
@@ -196,6 +280,38 @@ async function main() {
|
|
|
196
280
|
console.log(JSON.stringify(data, null, 2));
|
|
197
281
|
break;
|
|
198
282
|
}
|
|
283
|
+
case 'remove': {
|
|
284
|
+
const id = rest.find((a) => !a.startsWith('--'));
|
|
285
|
+
if (!id)
|
|
286
|
+
throw new Error('Missing session-id');
|
|
287
|
+
const { data } = await api('DELETE', `/api/sessions/${id}`);
|
|
288
|
+
console.log(jsonOut ? JSON.stringify(data, null, 2) : `removed ${id}`);
|
|
289
|
+
break;
|
|
290
|
+
}
|
|
291
|
+
case 'archive': {
|
|
292
|
+
const { data } = await api('GET', '/api/archive');
|
|
293
|
+
const archived = data.archived ?? [];
|
|
294
|
+
const summary = archived.map((s) => ({
|
|
295
|
+
id: s.id,
|
|
296
|
+
name: s.name,
|
|
297
|
+
removedAt: s.removedAt,
|
|
298
|
+
shellType: s.shellType,
|
|
299
|
+
}));
|
|
300
|
+
console.log(jsonOut
|
|
301
|
+
? JSON.stringify({ archived: summary }, null, 2)
|
|
302
|
+
: summary
|
|
303
|
+
.map((s) => `${s.id} ${s.removedAt} ${s.shellType ?? ''} ${s.name ?? ''}`.trimEnd())
|
|
304
|
+
.join('\n'));
|
|
305
|
+
break;
|
|
306
|
+
}
|
|
307
|
+
case 'revive': {
|
|
308
|
+
const id = rest.find((a) => !a.startsWith('--'));
|
|
309
|
+
if (!id)
|
|
310
|
+
throw new Error('Missing session-id');
|
|
311
|
+
const { data } = await api('POST', `/api/sessions/${id}/revive`);
|
|
312
|
+
console.log(jsonOut ? JSON.stringify(data, null, 2) : formatCreated(data));
|
|
313
|
+
break;
|
|
314
|
+
}
|
|
199
315
|
default:
|
|
200
316
|
usage();
|
|
201
317
|
process.exit(1);
|
|
@@ -214,10 +330,12 @@ function formatSessionList(data) {
|
|
|
214
330
|
.join('\n');
|
|
215
331
|
}
|
|
216
332
|
function formatCreated(data) {
|
|
217
|
-
const session = data
|
|
333
|
+
const { session, resumed } = data;
|
|
218
334
|
if (!session)
|
|
219
335
|
return JSON.stringify(data, null, 2);
|
|
220
|
-
|
|
336
|
+
// revive responses carry resumed; a fresh conversation lost its context.
|
|
337
|
+
const resumeNote = resumed === undefined ? '' : resumed ? ' [resumed]' : ' [fresh conversation]';
|
|
338
|
+
return `created ${session.id} ${session.name} (${session.status})${resumeNote}`;
|
|
221
339
|
}
|
|
222
340
|
main();
|
|
223
341
|
//# sourceMappingURL=ftown-sessions-cli.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ftown-sessions-cli.js","sourceRoot":"","sources":["../src/ftown-sessions-cli.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ftown-sessions-cli.js","sourceRoot":"","sources":["../src/ftown-sessions-cli.ts"],"names":[],"mappings":"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"}
|
package/dist/hook-installer.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync, renameSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
2
2
|
import { join, dirname } from 'node:path';
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
|
-
const HOOK_EVENTS = ['Notification', 'Stop', 'PreToolUse', 'PostToolUse', 'UserPromptSubmit'];
|
|
4
|
+
const HOOK_EVENTS = ['Notification', 'Stop', 'SessionEnd', 'PreToolUse', 'PostToolUse', 'UserPromptSubmit'];
|
|
5
5
|
import { isFtownNotifyCommand } from './install-notify-script.js';
|
|
6
6
|
function isObject(value) {
|
|
7
7
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hook-installer.js","sourceRoot":"","sources":["../src/hook-installer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACzF,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,MAAM,WAAW,GAAG,CAAC,cAAc,EAAE,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,kBAAkB,CAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"hook-installer.js","sourceRoot":"","sources":["../src/hook-installer.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -19,8 +19,11 @@ import { installHarness, harnessOnPath, pathHint, writeHarnessAgentGuide, agentG
|
|
|
19
19
|
import { installNotifyScript } from './install-notify-script.js';
|
|
20
20
|
import { installFtownSessionsSkill } from './install-ftown-skill.js';
|
|
21
21
|
import { installFtownSessionsCli } from './install-ftown-cli.js';
|
|
22
|
-
import { unregisterSession } from './session-registry.js';
|
|
22
|
+
import { registerSessionWorkspace, unregisterSession } from './session-registry.js';
|
|
23
23
|
import { createFtownSession } from './create-ftown-session.js';
|
|
24
|
+
import { removeFtownSession } from './remove-ftown-session.js';
|
|
25
|
+
import { buildSessionCommand } from './agent-commands.js';
|
|
26
|
+
import { isTmuxAvailable, killTmuxSession, listFtownTmuxSessions } from './tmux.js';
|
|
24
27
|
const execAsync = promisify(exec);
|
|
25
28
|
const __filename = fileURLToPath(import.meta.url);
|
|
26
29
|
const __dirname = dirname(__filename);
|
|
@@ -82,15 +85,9 @@ program
|
|
|
82
85
|
return data.token;
|
|
83
86
|
}
|
|
84
87
|
const store = new SessionStore(dataDir);
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
s.status = 'error';
|
|
89
|
-
s.updatedAt = new Date().toISOString();
|
|
90
|
-
await store.saveSession(s);
|
|
91
|
-
console.log(`[Bridge] Marked stale session ${s.id} as error`);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
88
|
+
// Sessions left in a live state by a previous bridge are handled by
|
|
89
|
+
// resurrectSessions() once Centrifugo is connected (tmux reattach,
|
|
90
|
+
// resume respawn, or marked as error).
|
|
94
91
|
const terminalManager = new TerminalManager(50000, 120);
|
|
95
92
|
const runner = new ProcessRunner();
|
|
96
93
|
const centrifugo = new CentrifugoClient(centrifugoUrl, auth.token, getToken);
|
|
@@ -224,9 +221,40 @@ program
|
|
|
224
221
|
flushTimers.set(sessionId, setTimeout(() => flushBuffer(sessionId), FLUSH_INTERVAL_MS));
|
|
225
222
|
}
|
|
226
223
|
});
|
|
227
|
-
|
|
224
|
+
// Per-session write queue so concurrent load/modify/save flows (hooks,
|
|
225
|
+
// runner exit handlers, stop_session) cannot interleave and resurrect a
|
|
226
|
+
// stale status.
|
|
227
|
+
const sessionWrites = new Map();
|
|
228
|
+
function withSessionWrite(sessionId, task) {
|
|
229
|
+
const prev = sessionWrites.get(sessionId) ?? Promise.resolve();
|
|
230
|
+
const run = prev.then(task);
|
|
231
|
+
const settled = run.catch(() => undefined);
|
|
232
|
+
sessionWrites.set(sessionId, settled);
|
|
233
|
+
void settled.finally(() => {
|
|
234
|
+
if (sessionWrites.get(sessionId) === settled) {
|
|
235
|
+
sessionWrites.delete(sessionId);
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
return run;
|
|
239
|
+
}
|
|
240
|
+
// Synthetic activity reset: some stop paths never produce a real Stop/stop
|
|
241
|
+
// hook (Claude's Stop hook doesn't fire on user interrupt, SessionEnd may be
|
|
242
|
+
// absent, runner exits/crashes). Publishing a synthetic Stop event guarantees
|
|
243
|
+
// every dashboard clears its "thinking"/"tool_use" indicator. Idle is
|
|
244
|
+
// idempotent, so an extra synthetic Stop after a real one is harmless.
|
|
245
|
+
function publishSyntheticStop(sessionId, reason) {
|
|
246
|
+
centrifugo.publishHookEvent(userId, sessionId, {
|
|
247
|
+
type: 'hook_event',
|
|
248
|
+
eventName: 'Stop',
|
|
249
|
+
data: { synthetic: true, reason },
|
|
250
|
+
}).catch((err) => {
|
|
251
|
+
console.error(`[Bridge] Failed to publish synthetic stop for ${sessionId}:`, err);
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
runner.on('complete', (sessionId) => {
|
|
228
255
|
flushBuffer(sessionId);
|
|
229
|
-
|
|
256
|
+
publishSyntheticStop(sessionId, 'complete');
|
|
257
|
+
withSessionWrite(sessionId, async () => {
|
|
230
258
|
const session = await store.loadSession(sessionId);
|
|
231
259
|
if (session) {
|
|
232
260
|
session.status = 'completed';
|
|
@@ -235,15 +263,16 @@ program
|
|
|
235
263
|
await centrifugo.publishSessionUpdate(userId, session);
|
|
236
264
|
}
|
|
237
265
|
console.log(`[Bridge] Session ${sessionId} completed`);
|
|
238
|
-
}
|
|
239
|
-
catch (err) {
|
|
266
|
+
}).catch((err) => {
|
|
240
267
|
console.error(`[Bridge] Failed to handle completion for session ${sessionId}:`, err);
|
|
241
|
-
}
|
|
242
|
-
|
|
268
|
+
}).finally(() => {
|
|
269
|
+
unregisterSession(sessionId);
|
|
270
|
+
});
|
|
243
271
|
});
|
|
244
|
-
runner.on('error',
|
|
272
|
+
runner.on('error', (sessionId, error) => {
|
|
245
273
|
flushBuffer(sessionId);
|
|
246
|
-
|
|
274
|
+
publishSyntheticStop(sessionId, 'error');
|
|
275
|
+
withSessionWrite(sessionId, async () => {
|
|
247
276
|
const session = await store.loadSession(sessionId);
|
|
248
277
|
if (session) {
|
|
249
278
|
session.status = 'error';
|
|
@@ -252,13 +281,61 @@ program
|
|
|
252
281
|
await centrifugo.publishSessionUpdate(userId, session);
|
|
253
282
|
}
|
|
254
283
|
console.error(`[Bridge] Session ${sessionId} error:`, error.message);
|
|
255
|
-
}
|
|
256
|
-
catch (err) {
|
|
284
|
+
}).catch((err) => {
|
|
257
285
|
console.error(`[Bridge] Failed to handle error for session ${sessionId}:`, err);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
|
|
286
|
+
}).finally(() => {
|
|
287
|
+
unregisterSession(sessionId);
|
|
288
|
+
terminalManager.destroy(sessionId);
|
|
289
|
+
});
|
|
261
290
|
});
|
|
291
|
+
// Last persisted agent session ids, to skip disk reads on the hot hook path.
|
|
292
|
+
const agentIdCache = new Map();
|
|
293
|
+
async function persistAgentSessionIds(hookEvent) {
|
|
294
|
+
// Workspace-fallback attribution may come from a foreign agent the user
|
|
295
|
+
// ran manually in the same directory; never persist its ids.
|
|
296
|
+
if (hookEvent.source === 'workspace')
|
|
297
|
+
return;
|
|
298
|
+
const rawClaudeId = hookEvent.data['session_id'];
|
|
299
|
+
const rawCursorId = hookEvent.data['conversation_id'];
|
|
300
|
+
// Claude Code hooks carry session_id; Cursor hooks carry conversation_id.
|
|
301
|
+
const claudeId = typeof rawClaudeId === 'string' && rawClaudeId ? rawClaudeId : undefined;
|
|
302
|
+
const cursorId = typeof rawCursorId === 'string' && rawCursorId ? rawCursorId : undefined;
|
|
303
|
+
if (!claudeId && !cursorId)
|
|
304
|
+
return;
|
|
305
|
+
const cached = agentIdCache.get(hookEvent.sessionId);
|
|
306
|
+
if (cached
|
|
307
|
+
&& (!claudeId || cached.claude === claudeId)
|
|
308
|
+
&& (!cursorId || cached.cursor === cursorId)) {
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
const session = await store.loadSession(hookEvent.sessionId);
|
|
312
|
+
if (!session)
|
|
313
|
+
return;
|
|
314
|
+
let changed = false;
|
|
315
|
+
if (claudeId && session.claudeSessionId !== claudeId) {
|
|
316
|
+
session.claudeSessionId = claudeId;
|
|
317
|
+
changed = true;
|
|
318
|
+
}
|
|
319
|
+
if (cursorId && session.cursorSessionId !== cursorId) {
|
|
320
|
+
session.cursorSessionId = cursorId;
|
|
321
|
+
changed = true;
|
|
322
|
+
}
|
|
323
|
+
if (!changed) {
|
|
324
|
+
agentIdCache.set(hookEvent.sessionId, {
|
|
325
|
+
claude: session.claudeSessionId,
|
|
326
|
+
cursor: session.cursorSessionId,
|
|
327
|
+
});
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
session.updatedAt = new Date().toISOString();
|
|
331
|
+
await store.saveSession(session);
|
|
332
|
+
// Cache only after a successful save, so a failed persist is retried.
|
|
333
|
+
agentIdCache.set(hookEvent.sessionId, {
|
|
334
|
+
claude: session.claudeSessionId,
|
|
335
|
+
cursor: session.cursorSessionId,
|
|
336
|
+
});
|
|
337
|
+
await centrifugo.publishSessionUpdate(userId, session);
|
|
338
|
+
}
|
|
262
339
|
localApiServer.on('event', (hookEvent) => {
|
|
263
340
|
centrifugo.publishHookEvent(userId, hookEvent.sessionId, {
|
|
264
341
|
type: 'hook_event',
|
|
@@ -267,6 +344,9 @@ program
|
|
|
267
344
|
}).catch((err) => {
|
|
268
345
|
console.error('[Bridge] Failed to handle hook event:', err);
|
|
269
346
|
});
|
|
347
|
+
withSessionWrite(hookEvent.sessionId, () => persistAgentSessionIds(hookEvent)).catch((err) => {
|
|
348
|
+
console.error(`[Bridge] Failed to persist agent session id for ${hookEvent.sessionId}:`, err);
|
|
349
|
+
});
|
|
270
350
|
});
|
|
271
351
|
async function handleCommand(command) {
|
|
272
352
|
console.log(`[Bridge] Received command: ${command.type} (requestId: ${command.requestId})`);
|
|
@@ -302,6 +382,7 @@ program
|
|
|
302
382
|
parentSessionId: payload.parentSessionId,
|
|
303
383
|
initialInput: payload.initialInput,
|
|
304
384
|
initialInputDelay: payload.initialInputDelay,
|
|
385
|
+
orchestrator: payload.orchestrator,
|
|
305
386
|
});
|
|
306
387
|
response = { requestId: command.requestId, success: true, data: { session } };
|
|
307
388
|
break;
|
|
@@ -314,13 +395,16 @@ program
|
|
|
314
395
|
}
|
|
315
396
|
const stopped = runner.stop(payload.sessionId);
|
|
316
397
|
if (stopped) {
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
session
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
398
|
+
publishSyntheticStop(payload.sessionId, 'stopped');
|
|
399
|
+
await withSessionWrite(payload.sessionId, async () => {
|
|
400
|
+
const session = await store.loadSession(payload.sessionId);
|
|
401
|
+
if (session) {
|
|
402
|
+
session.status = 'completed';
|
|
403
|
+
session.updatedAt = new Date().toISOString();
|
|
404
|
+
await store.saveSession(session);
|
|
405
|
+
await centrifugo.publishSessionUpdate(userId, session);
|
|
406
|
+
}
|
|
407
|
+
});
|
|
324
408
|
unregisterSession(payload.sessionId);
|
|
325
409
|
}
|
|
326
410
|
response = { requestId: command.requestId, success: true, data: { stopped } };
|
|
@@ -370,6 +454,7 @@ program
|
|
|
370
454
|
env: existingSession.env,
|
|
371
455
|
hookPort,
|
|
372
456
|
hookToken: apiToken,
|
|
457
|
+
parentSessionId: existingSession.parentSessionId,
|
|
373
458
|
});
|
|
374
459
|
centrifugo.subscribeToTerminalInput(userId, existingSession.id, (sid, data) => { runner.write(sid, data); }, (sid, cols, rows) => { handleClientResize(sid, cols, rows); }, (sid) => { publishScreenDump(sid); });
|
|
375
460
|
response = { requestId: command.requestId, success: true, data: { session: existingSession } };
|
|
@@ -431,18 +516,8 @@ program
|
|
|
431
516
|
response = { requestId: command.requestId, success: false, error: 'Missing sessionId' };
|
|
432
517
|
break;
|
|
433
518
|
}
|
|
434
|
-
runner.
|
|
435
|
-
|
|
436
|
-
await store.deleteSession(payload.sessionId);
|
|
437
|
-
if (sessionToRemove) {
|
|
438
|
-
const removedSession = {
|
|
439
|
-
...sessionToRemove,
|
|
440
|
-
status: 'removed',
|
|
441
|
-
updatedAt: new Date().toISOString(),
|
|
442
|
-
};
|
|
443
|
-
await centrifugo.publishSessionUpdate(userId, removedSession);
|
|
444
|
-
}
|
|
445
|
-
response = { requestId: command.requestId, success: true, data: { removed: true } };
|
|
519
|
+
const removed = await removeFtownSession({ store, runner, centrifugo, userId }, payload.sessionId, { onlyIfFinished: payload.onlyIfFinished });
|
|
520
|
+
response = { requestId: command.requestId, success: true, data: { removed: removed !== null } };
|
|
446
521
|
break;
|
|
447
522
|
}
|
|
448
523
|
case 'bridge_exec': {
|
|
@@ -493,6 +568,131 @@ program
|
|
|
493
568
|
console.error(`[Bridge] Failed to publish command response:`, err);
|
|
494
569
|
}
|
|
495
570
|
}
|
|
571
|
+
async function markSessionDead(session) {
|
|
572
|
+
session.status = 'error';
|
|
573
|
+
session.updatedAt = new Date().toISOString();
|
|
574
|
+
await store.saveSession(session);
|
|
575
|
+
await centrifugo.publishSessionUpdate(userId, session);
|
|
576
|
+
console.log(`[Bridge] Marked stale session ${session.id} as error`);
|
|
577
|
+
}
|
|
578
|
+
async function resurrectSession(sessionId) {
|
|
579
|
+
// Commands run concurrently with the resurrection loop; act on fresh
|
|
580
|
+
// state so a session stopped or removed mid-loop is not respawned.
|
|
581
|
+
const session = await store.loadSession(sessionId);
|
|
582
|
+
if (!session || (session.status !== 'running' && session.status !== 'pending'))
|
|
583
|
+
return;
|
|
584
|
+
if (runner.isRunning(session.id))
|
|
585
|
+
return;
|
|
586
|
+
if (runner.reattach(session.id, {
|
|
587
|
+
workingDir: session.workingDir,
|
|
588
|
+
parentSessionId: session.parentSessionId,
|
|
589
|
+
})) {
|
|
590
|
+
session.status = 'running';
|
|
591
|
+
session.bridgeId = bridgeId;
|
|
592
|
+
session.updatedAt = new Date().toISOString();
|
|
593
|
+
await store.saveSession(session);
|
|
594
|
+
await centrifugo.publishSessionUpdate(userId, session);
|
|
595
|
+
wireTerminalInput(session.id);
|
|
596
|
+
registerSessionWorkspace(session.id, session.workingDir);
|
|
597
|
+
console.log(`[Bridge] Resurrected session ${session.id} via tmux reattach`);
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
600
|
+
const shellType = session.shellType ?? 'claude';
|
|
601
|
+
const canResume = shellType === 'cursor'
|
|
602
|
+
? Boolean(session.cursorSessionId?.trim())
|
|
603
|
+
: shellType !== 'shell' && shellType !== 'opencode' && Boolean(session.claudeSessionId?.trim());
|
|
604
|
+
if (canResume) {
|
|
605
|
+
// Sessions created with a custom command rerun it verbatim (matching
|
|
606
|
+
// retry_session): injecting --resume into arbitrary commands could
|
|
607
|
+
// break wrappers, and rebuilding would drop their flags.
|
|
608
|
+
const defaultCommand = buildSessionCommand({
|
|
609
|
+
shellType: session.shellType,
|
|
610
|
+
workingDir: session.workingDir,
|
|
611
|
+
model: session.model,
|
|
612
|
+
});
|
|
613
|
+
const isCustomCommand = Boolean(session.command) && session.command !== defaultCommand;
|
|
614
|
+
const resumeCommand = isCustomCommand && session.command
|
|
615
|
+
? session.command
|
|
616
|
+
: buildSessionCommand({
|
|
617
|
+
shellType: session.shellType,
|
|
618
|
+
workingDir: session.workingDir,
|
|
619
|
+
model: session.model,
|
|
620
|
+
claudeSessionId: session.claudeSessionId,
|
|
621
|
+
cursorSessionId: session.cursorSessionId,
|
|
622
|
+
});
|
|
623
|
+
session.status = 'running';
|
|
624
|
+
session.bridgeId = bridgeId;
|
|
625
|
+
session.runtime = runner.getPreferredRuntime();
|
|
626
|
+
session.updatedAt = new Date().toISOString();
|
|
627
|
+
await store.saveSession(session);
|
|
628
|
+
await centrifugo.publishSessionUpdate(userId, session);
|
|
629
|
+
runner.run(session.id, resumeCommand, {
|
|
630
|
+
workingDir: session.workingDir,
|
|
631
|
+
env: session.env,
|
|
632
|
+
hookPort,
|
|
633
|
+
hookToken: apiToken,
|
|
634
|
+
parentSessionId: session.parentSessionId,
|
|
635
|
+
});
|
|
636
|
+
wireTerminalInput(session.id);
|
|
637
|
+
registerSessionWorkspace(session.id, session.workingDir);
|
|
638
|
+
console.log(`[Bridge] Resurrected session ${session.id} via resume respawn: ${resumeCommand}`);
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
641
|
+
await markSessionDead(session);
|
|
642
|
+
}
|
|
643
|
+
let resurrectionStarted = false;
|
|
644
|
+
async function resurrectSessions() {
|
|
645
|
+
if (resurrectionStarted)
|
|
646
|
+
return;
|
|
647
|
+
resurrectionStarted = true;
|
|
648
|
+
const sessions = await store.listSessions();
|
|
649
|
+
// Reap tmux sessions for OUR dead store records (removed records, failed
|
|
650
|
+
// kills) before resurrection re-creates any. Archived tombstones count as
|
|
651
|
+
// dead too: remove_session deletes the store record, so a failed tmux
|
|
652
|
+
// kill would otherwise leave a permanently invisible live agent. Tmux
|
|
653
|
+
// sessions with ids we have no record of are left alone — they may
|
|
654
|
+
// belong to another bridge running on this machine.
|
|
655
|
+
if (isTmuxAvailable()) {
|
|
656
|
+
const archived = await store.listArchived();
|
|
657
|
+
const deadIds = new Set([
|
|
658
|
+
...sessions
|
|
659
|
+
.filter((s) => s.status !== 'running' && s.status !== 'pending')
|
|
660
|
+
.map((s) => s.id),
|
|
661
|
+
...archived.map((a) => a.id),
|
|
662
|
+
]);
|
|
663
|
+
// A live store record outranks any tombstone for the same id (crash
|
|
664
|
+
// between archive and delete leaves both): never reap resurrectables.
|
|
665
|
+
for (const s of sessions) {
|
|
666
|
+
if (s.status === 'running' || s.status === 'pending') {
|
|
667
|
+
deadIds.delete(s.id);
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
for (const tmuxId of listFtownTmuxSessions()) {
|
|
671
|
+
if (deadIds.has(tmuxId)) {
|
|
672
|
+
console.log(`[Bridge] Killing tmux session for dead session ${tmuxId}`);
|
|
673
|
+
await killTmuxSession(tmuxId);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
for (const session of sessions) {
|
|
678
|
+
if (session.status !== 'running' && session.status !== 'pending')
|
|
679
|
+
continue;
|
|
680
|
+
try {
|
|
681
|
+
await resurrectSession(session.id);
|
|
682
|
+
}
|
|
683
|
+
catch (err) {
|
|
684
|
+
console.error(`[Bridge] Failed to resurrect session ${session.id}:`, err);
|
|
685
|
+
try {
|
|
686
|
+
const current = await store.loadSession(session.id);
|
|
687
|
+
if (current)
|
|
688
|
+
await markSessionDead(current);
|
|
689
|
+
}
|
|
690
|
+
catch (markErr) {
|
|
691
|
+
console.error(`[Bridge] Failed to mark session ${session.id} as error:`, markErr);
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
}
|
|
496
696
|
centrifugo.connect();
|
|
497
697
|
centrifugo.joinBridgesChannel(userId, bridgeId);
|
|
498
698
|
centrifugo.subscribeToSessions(userId);
|
|
@@ -507,6 +707,9 @@ program
|
|
|
507
707
|
setTimeout(() => {
|
|
508
708
|
ready = true;
|
|
509
709
|
console.log('[Bridge] Ready and listening for commands');
|
|
710
|
+
resurrectSessions().catch((err) => {
|
|
711
|
+
console.error('[Bridge] Session resurrection failed:', err);
|
|
712
|
+
});
|
|
510
713
|
}, 2000);
|
|
511
714
|
const shutdown = () => {
|
|
512
715
|
console.log('\n[Bridge] Shutting down...');
|