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.
Files changed (37) hide show
  1. package/dist/agent-commands.js +1 -1
  2. package/dist/agent-commands.js.map +1 -1
  3. package/dist/claude-runner.d.ts +29 -0
  4. package/dist/claude-runner.js +246 -44
  5. package/dist/claude-runner.js.map +1 -1
  6. package/dist/create-ftown-session.d.ts +16 -0
  7. package/dist/create-ftown-session.js +70 -5
  8. package/dist/create-ftown-session.js.map +1 -1
  9. package/dist/cursor-hook-installer.d.ts +0 -2
  10. package/dist/cursor-hook-installer.js +3 -14
  11. package/dist/cursor-hook-installer.js.map +1 -1
  12. package/dist/ftown-sessions-cli.js +120 -2
  13. package/dist/ftown-sessions-cli.js.map +1 -1
  14. package/dist/hook-installer.js +1 -1
  15. package/dist/hook-installer.js.map +1 -1
  16. package/dist/index.js +245 -42
  17. package/dist/index.js.map +1 -1
  18. package/dist/local-api-server.d.ts +2 -0
  19. package/dist/local-api-server.js +197 -4
  20. package/dist/local-api-server.js.map +1 -1
  21. package/dist/remove-ftown-session.d.ts +23 -0
  22. package/dist/remove-ftown-session.js +32 -0
  23. package/dist/remove-ftown-session.js.map +1 -0
  24. package/dist/session-registry.d.ts +11 -1
  25. package/dist/session-registry.js +3 -3
  26. package/dist/session-registry.js.map +1 -1
  27. package/dist/session-store.d.ts +6 -1
  28. package/dist/session-store.js +32 -1
  29. package/dist/session-store.js.map +1 -1
  30. package/dist/tmux.d.ts +24 -0
  31. package/dist/tmux.js +149 -0
  32. package/dist/tmux.js.map +1 -0
  33. package/dist/types.d.ts +9 -0
  34. package/hooks/notify.sh +34 -12
  35. package/package.json +1 -1
  36. package/skills/ftown-sessions/SKILL.md +49 -0
  37. package/skills/bridge-harness/SKILL.md +0 -43
@@ -34,7 +34,7 @@ export function buildSessionCommand(input) {
34
34
  });
35
35
  }
36
36
  if (input.claudeSessionId?.trim()) {
37
- return `claude --allow-dangerously-skip-permissions --resume ${input.claudeSessionId.trim()}`;
37
+ return `claude --allow-dangerously-skip-permissions --resume ${shellQuote(input.claudeSessionId.trim())}`;
38
38
  }
39
39
  return 'claude --allow-dangerously-skip-permissions';
40
40
  }
@@ -1 +1 @@
1
- {"version":3,"file":"agent-commands.js","sourceRoot":"","sources":["../src/agent-commands.ts"],"names":[],"mappings":"AAEA,uDAAuD;AACvD,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,OAIvC;IACC,MAAM,KAAK,GAAG,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IAEnC,IAAI,OAAO,CAAC,UAAU,EAAE,IAAI,EAAE,EAAE,CAAC;QAC/B,KAAK,CAAC,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACnE,CAAC;IAED,IAAI,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC;QAC1B,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC1D,CAAC;IAED,IAAI,OAAO,CAAC,eAAe,EAAE,IAAI,EAAE,EAAE,CAAC;QACpC,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACrE,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAWD,MAAM,UAAU,mBAAmB,CAAC,KAA+B;IACjE,IAAI,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IAC9B,CAAC;IAED,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,QAAQ,CAAC;IAE9C,IAAI,SAAS,KAAK,OAAO,EAAE,CAAC;QAC1B,OAAO,aAAa,CAAC;IACvB,CAAC;IACD,IAAI,SAAS,KAAK,UAAU,EAAE,CAAC;QAC7B,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;QAC3B,OAAO,uBAAuB,CAAC;YAC7B,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,eAAe,EAAE,KAAK,CAAC,eAAe;SACvC,CAAC,CAAC;IACL,CAAC;IACD,IAAI,KAAK,CAAC,eAAe,EAAE,IAAI,EAAE,EAAE,CAAC;QAClC,OAAO,wDAAwD,KAAK,CAAC,eAAe,CAAC,IAAI,EAAE,EAAE,CAAC;IAChG,CAAC;IACD,OAAO,6CAA6C,CAAC;AACvD,CAAC"}
1
+ {"version":3,"file":"agent-commands.js","sourceRoot":"","sources":["../src/agent-commands.ts"],"names":[],"mappings":"AAEA,uDAAuD;AACvD,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,OAIvC;IACC,MAAM,KAAK,GAAG,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IAEnC,IAAI,OAAO,CAAC,UAAU,EAAE,IAAI,EAAE,EAAE,CAAC;QAC/B,KAAK,CAAC,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACnE,CAAC;IAED,IAAI,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC;QAC1B,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC1D,CAAC;IAED,IAAI,OAAO,CAAC,eAAe,EAAE,IAAI,EAAE,EAAE,CAAC;QACpC,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACrE,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAWD,MAAM,UAAU,mBAAmB,CAAC,KAA+B;IACjE,IAAI,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IAC9B,CAAC;IAED,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,QAAQ,CAAC;IAE9C,IAAI,SAAS,KAAK,OAAO,EAAE,CAAC;QAC1B,OAAO,aAAa,CAAC;IACvB,CAAC;IACD,IAAI,SAAS,KAAK,UAAU,EAAE,CAAC;QAC7B,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;QAC3B,OAAO,uBAAuB,CAAC;YAC7B,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,eAAe,EAAE,KAAK,CAAC,eAAe;SACvC,CAAC,CAAC;IACL,CAAC;IACD,IAAI,KAAK,CAAC,eAAe,EAAE,IAAI,EAAE,EAAE,CAAC;QAClC,OAAO,wDAAwD,UAAU,CAAC,KAAK,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;IAC5G,CAAC;IACD,OAAO,6CAA6C,CAAC;AACvD,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import { EventEmitter } from 'node:events';
2
+ import type { SessionRuntime } from './types.js';
2
3
  export interface ProcessRunnerEvents {
3
4
  data: [string, string];
4
5
  complete: [string];
@@ -11,16 +12,44 @@ interface RunOptions {
11
12
  env?: Record<string, string>;
12
13
  initialInput?: string;
13
14
  initialInputDelay?: number;
15
+ submitSuffix?: string;
14
16
  hookPort?: number;
15
17
  hookToken?: string;
18
+ parentSessionId?: string;
19
+ }
20
+ export interface ReattachOptions {
21
+ workingDir?: string;
22
+ cols?: number;
23
+ rows?: number;
24
+ parentSessionId?: string;
16
25
  }
17
26
  export declare class ProcessRunner extends EventEmitter<ProcessRunnerEvents> {
18
27
  private readonly activeProcesses;
28
+ private readonly runtimes;
29
+ /** Sessions being killed via stop(); suppresses tmux reattach and exit-event
30
+ * emission — callers of stop() persist the final status themselves, and a
31
+ * late 'complete'/'error' save can resurrect a record removal just deleted. */
32
+ private readonly stopping;
33
+ /** Sessions detaching on shutdown; the tmux session stays alive, emit nothing. */
34
+ private readonly detachOnly;
35
+ /** Last client-requested size, so tmux reattach does not snap back to creation-time size. */
36
+ private readonly lastSizes;
37
+ getPreferredRuntime(): SessionRuntime;
38
+ getRuntime(sessionId: string): SessionRuntime | undefined;
19
39
  run(sessionId: string, command: string, options?: RunOptions): void;
40
+ /** Attach to an existing tmux session without creating it (session resurrection). */
41
+ reattach(sessionId: string, options?: ReattachOptions): boolean;
42
+ hasTmuxSession(sessionId: string): boolean;
20
43
  write(sessionId: string, data: string): boolean;
21
44
  resize(sessionId: string, cols: number, rows: number): boolean;
22
45
  stop(sessionId: string): boolean;
23
46
  stopAll(): void;
24
47
  isRunning(sessionId: string): boolean;
48
+ private killTmuxSessionLogged;
49
+ private buildEnv;
50
+ private runTmux;
51
+ private attachTmux;
52
+ private runDirect;
53
+ private scheduleInitialInput;
25
54
  }
26
55
  export {};
@@ -1,12 +1,136 @@
1
1
  import * as pty from 'node-pty';
2
2
  import { EventEmitter } from 'node:events';
3
+ import { TMUX_SOCKET_NAME, createTmuxSession, hasTmuxSession, isTmuxAvailable, killTmuxSession, readAndClearExitCode, tmuxSessionName, } from './tmux.js';
3
4
  import { applyTerminalColorEnv } from './xterm-theme.js';
4
5
  export class ProcessRunner extends EventEmitter {
5
6
  activeProcesses = new Map();
7
+ runtimes = new Map();
8
+ /** Sessions being killed via stop(); suppresses tmux reattach and exit-event
9
+ * emission — callers of stop() persist the final status themselves, and a
10
+ * late 'complete'/'error' save can resurrect a record removal just deleted. */
11
+ stopping = new Set();
12
+ /** Sessions detaching on shutdown; the tmux session stays alive, emit nothing. */
13
+ detachOnly = new Set();
14
+ /** Last client-requested size, so tmux reattach does not snap back to creation-time size. */
15
+ lastSizes = new Map();
16
+ getPreferredRuntime() {
17
+ return isTmuxAvailable() ? 'tmux' : 'direct';
18
+ }
19
+ getRuntime(sessionId) {
20
+ return this.runtimes.get(sessionId);
21
+ }
6
22
  run(sessionId, command, options = {}) {
7
23
  const cwd = options.workingDir ?? process.cwd();
8
24
  const cols = options.cols ?? 120;
9
25
  const rows = options.rows ?? 40;
26
+ const env = this.buildEnv(sessionId, options);
27
+ console.log(`[ProcessRunner] Spawning command in ${cwd} (${this.getPreferredRuntime()}): ${command}`);
28
+ if (this.getPreferredRuntime() === 'tmux') {
29
+ // Registered before the async tmux creation so a stop() arriving in the
30
+ // creation window is recorded (via this.stopping) instead of lost.
31
+ this.runtimes.set(sessionId, 'tmux');
32
+ void this.runTmux(sessionId, command, env, {
33
+ cwd,
34
+ cols,
35
+ rows,
36
+ initialInput: options.initialInput,
37
+ initialInputDelay: options.initialInputDelay,
38
+ submitSuffix: options.submitSuffix,
39
+ });
40
+ return;
41
+ }
42
+ this.runDirect(sessionId, command, env, cwd, cols, rows, options);
43
+ }
44
+ /** Attach to an existing tmux session without creating it (session resurrection). */
45
+ reattach(sessionId, options = {}) {
46
+ if (this.activeProcesses.has(sessionId)) {
47
+ return true;
48
+ }
49
+ if (!isTmuxAvailable() || !hasTmuxSession(sessionId)) {
50
+ return false;
51
+ }
52
+ const env = this.buildEnv(sessionId, { parentSessionId: options.parentSessionId });
53
+ this.attachTmux(sessionId, {
54
+ env,
55
+ cwd: options.workingDir ?? process.cwd(),
56
+ cols: options.cols ?? 120,
57
+ rows: options.rows ?? 40,
58
+ });
59
+ return true;
60
+ }
61
+ hasTmuxSession(sessionId) {
62
+ return isTmuxAvailable() && hasTmuxSession(sessionId);
63
+ }
64
+ write(sessionId, data) {
65
+ const proc = this.activeProcesses.get(sessionId);
66
+ if (!proc) {
67
+ return false;
68
+ }
69
+ proc.write(data);
70
+ return true;
71
+ }
72
+ resize(sessionId, cols, rows) {
73
+ const proc = this.activeProcesses.get(sessionId);
74
+ if (!proc) {
75
+ return false;
76
+ }
77
+ proc.resize(cols, rows);
78
+ this.lastSizes.set(sessionId, { cols, rows });
79
+ return true;
80
+ }
81
+ stop(sessionId) {
82
+ const proc = this.activeProcesses.get(sessionId);
83
+ const isTmux = this.runtimes.get(sessionId) === 'tmux';
84
+ if (isTmux) {
85
+ this.stopping.add(sessionId);
86
+ this.killTmuxSessionLogged(sessionId);
87
+ }
88
+ if (!proc) {
89
+ // Orphaned tmux session with no attached client (e.g. failed reattach).
90
+ if (!isTmux && isTmuxAvailable() && hasTmuxSession(sessionId)) {
91
+ this.killTmuxSessionLogged(sessionId);
92
+ return true;
93
+ }
94
+ return isTmux;
95
+ }
96
+ // Direct runtime: mark stopping so the PTY onExit emits nothing — like the
97
+ // tmux path, the caller owns the final status, and emitting here races
98
+ // remove_session's delete with a status save that recreates the record.
99
+ if (!isTmux) {
100
+ this.stopping.add(sessionId);
101
+ }
102
+ proc.kill();
103
+ setTimeout(() => {
104
+ if (this.activeProcesses.has(sessionId)) {
105
+ proc.kill('SIGKILL');
106
+ this.activeProcesses.delete(sessionId);
107
+ }
108
+ }, 5000);
109
+ return true;
110
+ }
111
+ stopAll() {
112
+ for (const [sessionId, proc] of this.activeProcesses) {
113
+ if (this.runtimes.get(sessionId) === 'tmux') {
114
+ // Detach only — the tmux session keeps running and survives bridge restarts.
115
+ this.detachOnly.add(sessionId);
116
+ proc.kill();
117
+ }
118
+ else {
119
+ this.stop(sessionId);
120
+ }
121
+ }
122
+ }
123
+ isRunning(sessionId) {
124
+ return this.activeProcesses.has(sessionId);
125
+ }
126
+ killTmuxSessionLogged(sessionId) {
127
+ void killTmuxSession(sessionId).then((killed) => {
128
+ if (!killed && hasTmuxSession(sessionId)) {
129
+ console.error(`[ProcessRunner] Failed to kill tmux session for ${sessionId}`);
130
+ }
131
+ });
132
+ }
133
+ buildEnv(sessionId, options) {
10
134
  const env = {
11
135
  ...process.env,
12
136
  };
@@ -20,11 +144,109 @@ export class ProcessRunner extends EventEmitter {
20
144
  if (options.hookToken) {
21
145
  env.FTOWN_HOOK_TOKEN = options.hookToken;
22
146
  }
147
+ if (options.parentSessionId) {
148
+ env.FTOWN_PARENT_SESSION_ID = options.parentSessionId;
149
+ }
23
150
  if (options.env) {
24
151
  Object.assign(env, options.env);
25
152
  }
26
153
  applyTerminalColorEnv(env);
27
- console.log(`[ProcessRunner] Spawning command in ${cwd}: ${command}`);
154
+ return env;
155
+ }
156
+ async runTmux(sessionId, command, env, params) {
157
+ try {
158
+ await createTmuxSession({
159
+ sessionId,
160
+ command,
161
+ cwd: params.cwd,
162
+ cols: params.cols,
163
+ rows: params.rows,
164
+ env,
165
+ });
166
+ }
167
+ catch (err) {
168
+ const wasStopping = this.stopping.delete(sessionId);
169
+ this.runtimes.delete(sessionId);
170
+ console.error(`[ProcessRunner] Failed to create tmux session:`, err);
171
+ if (!wasStopping) {
172
+ this.emit('error', sessionId, err instanceof Error ? err : new Error(String(err)));
173
+ }
174
+ return;
175
+ }
176
+ // stop() may have arrived while the session was being created; honor it
177
+ // instead of attaching. stop_session already persisted the final status.
178
+ if (this.stopping.delete(sessionId)) {
179
+ this.runtimes.delete(sessionId);
180
+ this.killTmuxSessionLogged(sessionId);
181
+ return;
182
+ }
183
+ this.attachTmux(sessionId, { ...params, env });
184
+ }
185
+ attachTmux(sessionId, params) {
186
+ // params holds creation-time cols/rows; prefer the latest client size.
187
+ const size = this.lastSizes.get(sessionId);
188
+ if (size) {
189
+ params = { ...params, cols: size.cols, rows: size.rows };
190
+ }
191
+ let proc;
192
+ try {
193
+ proc = pty.spawn('tmux', ['-L', TMUX_SOCKET_NAME, 'attach-session', '-t', `=${tmuxSessionName(sessionId)}`], {
194
+ name: 'xterm-256color',
195
+ cols: params.cols,
196
+ rows: params.rows,
197
+ cwd: params.cwd,
198
+ env: params.env,
199
+ });
200
+ console.log(`[ProcessRunner] Attached to tmux session ${tmuxSessionName(sessionId)}, client pid: ${proc.pid}`);
201
+ }
202
+ catch (err) {
203
+ console.error(`[ProcessRunner] Failed to attach to tmux session:`, err);
204
+ this.emit('error', sessionId, err instanceof Error ? err : new Error(String(err)));
205
+ return;
206
+ }
207
+ this.activeProcesses.set(sessionId, proc);
208
+ this.runtimes.set(sessionId, 'tmux');
209
+ proc.onData((data) => {
210
+ this.emit('data', sessionId, data);
211
+ });
212
+ proc.onExit(({ exitCode, signal }) => {
213
+ console.log(`[ProcessRunner] tmux attach client exited, code: ${exitCode}, signal: ${signal}`);
214
+ this.activeProcesses.delete(sessionId);
215
+ this.runtimes.delete(sessionId);
216
+ if (this.detachOnly.delete(sessionId)) {
217
+ return;
218
+ }
219
+ if (this.stopping.delete(sessionId)) {
220
+ // stop() initiated this exit; stop_session persists the final status,
221
+ // so emit nothing (kill-session makes the trap record a bogus code).
222
+ readAndClearExitCode(sessionId);
223
+ this.lastSizes.delete(sessionId);
224
+ return;
225
+ }
226
+ if (hasTmuxSession(sessionId)) {
227
+ // Client detached but the command is still running — reattach to keep streaming.
228
+ this.attachTmux(sessionId, { ...params, initialInput: undefined });
229
+ return;
230
+ }
231
+ this.lastSizes.delete(sessionId);
232
+ // The attach client's exit code is unrelated to the command's; the real
233
+ // code is written to a temp file by the command wrapper inside tmux.
234
+ const realCode = readAndClearExitCode(sessionId);
235
+ if (realCode === undefined) {
236
+ // No trap file: the session was destroyed without the wrapper's EXIT
237
+ // trap running (SIGKILL, OOM, tmux server killed).
238
+ this.emit('error', sessionId, new Error('tmux session ended without recording an exit code'));
239
+ }
240
+ else if (realCode === 0) {
241
+ this.emit('complete', sessionId);
242
+ }
243
+ else {
244
+ this.emit('error', sessionId, new Error(`Process exited with code ${realCode}`));
245
+ }
246
+ });
247
+ this.scheduleInitialInput(sessionId, proc, params.initialInput, params.initialInputDelay, params.submitSuffix);
248
+ }
249
+ runDirect(sessionId, command, env, cwd, cols, rows, options) {
28
250
  let proc;
29
251
  try {
30
252
  proc = pty.spawn('/bin/zsh', ['-l', '-c', command], {
@@ -42,12 +264,19 @@ export class ProcessRunner extends EventEmitter {
42
264
  return;
43
265
  }
44
266
  this.activeProcesses.set(sessionId, proc);
267
+ this.runtimes.set(sessionId, 'direct');
45
268
  proc.onData((data) => {
46
269
  this.emit('data', sessionId, data);
47
270
  });
48
271
  proc.onExit(({ exitCode, signal }) => {
49
272
  console.log(`[ProcessRunner] Process exited, code: ${exitCode}, signal: ${signal}`);
50
273
  this.activeProcesses.delete(sessionId);
274
+ this.runtimes.delete(sessionId);
275
+ this.lastSizes.delete(sessionId);
276
+ if (this.stopping.delete(sessionId)) {
277
+ // stop() initiated this exit; the caller persists the final status.
278
+ return;
279
+ }
51
280
  if (exitCode === 0 || exitCode === null || exitCode === undefined) {
52
281
  this.emit('complete', sessionId);
53
282
  }
@@ -55,53 +284,26 @@ export class ProcessRunner extends EventEmitter {
55
284
  this.emit('error', sessionId, new Error(`Process exited with code ${exitCode}`));
56
285
  }
57
286
  });
58
- if (options.initialInput) {
59
- const delay = options.initialInputDelay ?? 2000;
60
- setTimeout(() => {
61
- if (this.activeProcesses.has(sessionId)) {
62
- console.log(`[ProcessRunner] Sending initial input to session ${sessionId}`);
63
- proc.write(options.initialInput + '\r');
64
- }
65
- }, delay);
66
- }
287
+ this.scheduleInitialInput(sessionId, proc, options.initialInput, options.initialInputDelay, options.submitSuffix);
67
288
  }
68
- write(sessionId, data) {
69
- const proc = this.activeProcesses.get(sessionId);
70
- if (!proc) {
71
- return false;
72
- }
73
- proc.write(data);
74
- return true;
75
- }
76
- resize(sessionId, cols, rows) {
77
- const proc = this.activeProcesses.get(sessionId);
78
- if (!proc) {
79
- return false;
80
- }
81
- proc.resize(cols, rows);
82
- return true;
83
- }
84
- stop(sessionId) {
85
- const proc = this.activeProcesses.get(sessionId);
86
- if (!proc) {
87
- return false;
289
+ scheduleInitialInput(sessionId, proc, initialInput, initialInputDelay, submitSuffix) {
290
+ if (!initialInput) {
291
+ return;
88
292
  }
89
- proc.kill();
293
+ const delay = initialInputDelay ?? 2000;
90
294
  setTimeout(() => {
91
- if (this.activeProcesses.has(sessionId)) {
92
- proc.kill('SIGKILL');
93
- this.activeProcesses.delete(sessionId);
295
+ if (this.activeProcesses.get(sessionId) === proc) {
296
+ console.log(`[ProcessRunner] Sending initial input to session ${sessionId}`);
297
+ proc.write(initialInput);
298
+ // Submit separately after the paste settles: composer TUIs (Claude/Cursor) treat a
299
+ // trailing CR inside a bracketed paste of multi-line text as a newline, not a submit.
300
+ setTimeout(() => {
301
+ if (this.activeProcesses.get(sessionId) === proc) {
302
+ proc.write(submitSuffix ?? '\r');
303
+ }
304
+ }, 600);
94
305
  }
95
- }, 5000);
96
- return true;
97
- }
98
- stopAll() {
99
- for (const [sessionId] of this.activeProcesses) {
100
- this.stop(sessionId);
101
- }
102
- }
103
- isRunning(sessionId) {
104
- return this.activeProcesses.has(sessionId);
306
+ }, delay);
105
307
  }
106
308
  }
107
309
  //# sourceMappingURL=claude-runner.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"claude-runner.js","sourceRoot":"","sources":["../src/claude-runner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"claude-runner.js","sourceRoot":"","sources":["../src/claude-runner.ts"],"names":[],"mappings":"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"}
@@ -26,8 +26,24 @@ export interface CreateFtownSessionInput {
26
26
  parentSessionId?: string;
27
27
  initialInput?: string;
28
28
  initialInputDelay?: number;
29
+ orchestrator?: boolean;
29
30
  }
30
31
  export declare function resolveParentSessionId(store: SessionStore, parentSessionId: string | undefined): Promise<string | undefined>;
32
+ interface ChildBriefingParams {
33
+ childName: string;
34
+ childId: string;
35
+ parentName: string;
36
+ parentId: string;
37
+ }
38
+ /** One compact paragraph injected into a child agent's first input. */
39
+ export declare function buildChildBriefing(params: ChildBriefingParams): string;
40
+ interface OrchestratorBriefingParams {
41
+ sessionName: string;
42
+ sessionId: string;
43
+ }
44
+ /** One compact paragraph injected into an orchestrator agent's first input. */
45
+ export declare function buildOrchestratorBriefing(params: OrchestratorBriefingParams): string;
31
46
  export declare function createFtownSession(deps: CreateFtownSessionDeps, input: CreateFtownSessionInput): Promise<Session>;
32
47
  /** Map a Local API JSON body into create input. */
33
48
  export declare function parseCreateSessionBody(body: Record<string, unknown>, callerSessionId?: string): CreateFtownSessionInput;
49
+ export {};
@@ -1,6 +1,5 @@
1
1
  import { v4 as uuidv4 } from 'uuid';
2
2
  import { buildSessionCommand } from './agent-commands.js';
3
- import { installProjectCursorHooks } from './cursor-hook-installer.js';
4
3
  import { registerSessionWorkspace } from './session-registry.js';
5
4
  export async function resolveParentSessionId(store, parentSessionId) {
6
5
  if (!parentSessionId)
@@ -11,12 +10,39 @@ export async function resolveParentSessionId(store, parentSessionId) {
11
10
  }
12
11
  return proposed.parentSessionId ?? proposed.id;
13
12
  }
13
+ /** One compact paragraph injected into a child agent's first input. */
14
+ export function buildChildBriefing(params) {
15
+ return (`[ftown] You are child session '${params.childName}' (${params.childId}), ` +
16
+ `spawned by parent '${params.parentName}' (${params.parentId}). ` +
17
+ `Report results/questions to your parent with: ~/.ftown/ftown-sessions tell --parent "<message>" ` +
18
+ `— message siblings with tell --siblings, and inspect peers with ` +
19
+ `~/.ftown/ftown-sessions list / screen <id>. Your parent can read your terminal at any time.`);
20
+ }
21
+ /** One compact paragraph injected into an orchestrator agent's first input. */
22
+ export function buildOrchestratorBriefing(params) {
23
+ return (`[ftown] You are running inside ftown session '${params.sessionName}' ` +
24
+ `(${params.sessionId}) and can orchestrate sibling agent sessions on this machine. ` +
25
+ `Spawn workers with: ~/.ftown/ftown-sessions create --shell claude|cursor|shell ` +
26
+ `--parent --workdir <dir> --name <name> --prompt "<task>" — children are ` +
27
+ `automatically briefed to report back to you via tell, and their reports arrive in ` +
28
+ `your terminal as messages starting with [ftown msg from <name>]. Inspect any session ` +
29
+ `with ~/.ftown/ftown-sessions list / screen <id> / grep <id> --pattern <re>, and ` +
30
+ `message one with tell <id> "<text>". Workers you no longer need should be cleaned ` +
31
+ `up with ~/.ftown/ftown-sessions remove <id> — they are archived and can be brought ` +
32
+ `back with revive <id> (the worker's conversation is resumed only if its agent ` +
33
+ `session id was recorded before removal; otherwise it restarts fresh).`);
34
+ }
14
35
  export async function createFtownSession(deps, input) {
15
36
  const command = buildSessionCommand(input);
16
37
  const prompt = input.prompt?.trim() ?? '';
17
38
  let parentSessionId;
39
+ let parentName;
18
40
  if (input.parentSessionId) {
19
41
  parentSessionId = await resolveParentSessionId(deps.store, input.parentSessionId);
42
+ if (parentSessionId) {
43
+ const parentSession = await deps.store.loadSession(parentSessionId);
44
+ parentName = parentSession?.name ?? parentSessionId.slice(0, 8);
45
+ }
20
46
  }
21
47
  const sessionId = uuidv4();
22
48
  const session = {
@@ -35,22 +61,60 @@ export async function createFtownSession(deps, input) {
35
61
  cursorSessionId: input.cursorSessionId,
36
62
  env: input.env,
37
63
  parentSessionId,
64
+ runtime: deps.runner.getPreferredRuntime(),
38
65
  };
39
66
  await deps.store.saveSession(session);
40
67
  await deps.centrifugo.publishSessionUpdate(deps.userId, session);
41
68
  registerSessionWorkspace(sessionId, input.workingDir);
42
- if (input.shellType === 'cursor' && input.workingDir) {
43
- installProjectCursorHooks(input.workingDir, deps.notifyScriptPath);
69
+ // Agent sessions (anything but a plain 'shell') spawned by a parent get a
70
+ // one-paragraph briefing prepended to their first input so they know their
71
+ // place in the session tree and how to talk to parent/siblings.
72
+ const isAgent = input.shellType !== 'shell';
73
+ const childBriefing = parentSessionId && parentName && isAgent
74
+ ? buildChildBriefing({
75
+ childName: session.name,
76
+ childId: sessionId,
77
+ parentName,
78
+ parentId: parentSessionId,
79
+ })
80
+ : undefined;
81
+ const orchestratorBriefing = input.orchestrator && isAgent
82
+ ? buildOrchestratorBriefing({ sessionName: session.name, sessionId })
83
+ : undefined;
84
+ // Orchestrator paragraph follows the child paragraph, separated by a blank line.
85
+ const briefing = [childBriefing, orchestratorBriefing].filter(Boolean).join('\n\n') || undefined;
86
+ // Composer TUIs need the submit CR sent separately after the paste settles —
87
+ // a CR inside the pasted chunk becomes a newline, and ESC+CR reads as
88
+ // Alt+Enter (newline) on current Claude Code, so plain CR it is.
89
+ const promptSubmitSuffix = '\r';
90
+ let initialInput;
91
+ let initialInputDelay;
92
+ let submitSuffix;
93
+ if (briefing) {
94
+ initialInput = prompt ? `${briefing}\n\nTask: ${prompt}` : briefing;
95
+ initialInputDelay = input.initialInputDelay ?? 2000;
96
+ submitSuffix = promptSubmitSuffix;
97
+ }
98
+ else if (input.initialInput !== undefined) {
99
+ // Raw passthrough: callers own the submit keystrokes; suppress the default CR.
100
+ initialInput = input.initialInput;
101
+ initialInputDelay = input.initialInputDelay;
102
+ submitSuffix = '';
103
+ }
104
+ else {
105
+ initialInput = prompt || undefined;
106
+ initialInputDelay = input.initialInputDelay ?? (prompt ? 2000 : undefined);
107
+ submitSuffix = promptSubmitSuffix;
44
108
  }
45
- const initialInput = input.initialInput ?? (prompt ? `${prompt}\r` : undefined);
46
- const initialInputDelay = input.initialInputDelay ?? (prompt ? 2000 : undefined);
47
109
  deps.runner.run(sessionId, command, {
48
110
  workingDir: input.workingDir,
49
111
  env: input.env,
50
112
  initialInput,
51
113
  initialInputDelay,
114
+ submitSuffix,
52
115
  hookPort: deps.hookPort,
53
116
  hookToken: deps.hookToken,
117
+ parentSessionId,
54
118
  });
55
119
  deps.wireTerminalInput(sessionId);
56
120
  return session;
@@ -76,6 +140,7 @@ export function parseCreateSessionBody(body, callerSessionId) {
76
140
  parentSessionId,
77
141
  initialInput: typeof body.initialInput === 'string' ? body.initialInput : undefined,
78
142
  initialInputDelay: typeof body.initialInputDelay === 'number' ? body.initialInputDelay : undefined,
143
+ orchestrator: body.orchestrator === true,
79
144
  };
80
145
  }
81
146
  //# sourceMappingURL=create-ftown-session.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-ftown-session.js","sourceRoot":"","sources":["../src/create-ftown-session.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"create-ftown-session.js","sourceRoot":"","sources":["../src/create-ftown-session.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,2 @@
1
1
  /** User-level ~/.cursor/hooks.json (global Cursor CLI). */
2
2
  export declare function installCursorHooks(notifyScriptPath: string): void;
3
- /** Project-level .cursor/hooks.json — Cursor CLI prefers this when agent runs in a repo. */
4
- export declare function installProjectCursorHooks(projectRoot: string, notifyScriptPath: string): void;
@@ -1,15 +1,17 @@
1
1
  import { existsSync, readFileSync, renameSync, writeFileSync, mkdirSync } from 'node:fs';
2
- import { join, dirname, resolve } from 'node:path';
2
+ import { join, dirname } from 'node:path';
3
3
  import { homedir } from 'node:os';
4
4
  /** Cursor CLI hook events with reliable CLI support (see cursor.com/docs/hooks). */
5
5
  const CURSOR_HOOK_EVENTS = [
6
6
  'sessionStart',
7
7
  'preToolUse',
8
8
  'postToolUse',
9
+ 'postToolUseFailure',
9
10
  'beforeShellExecution',
10
11
  'afterShellExecution',
11
12
  'afterFileEdit',
12
13
  'stop',
14
+ 'sessionEnd',
13
15
  'beforeSubmitPrompt',
14
16
  ];
15
17
  import { isFtownNotifyCommand } from './install-notify-script.js';
@@ -92,17 +94,4 @@ function mergeHooksFile(settingsPath, notifyScriptPath, label) {
92
94
  export function installCursorHooks(notifyScriptPath) {
93
95
  mergeHooksFile(join(homedir(), '.cursor', 'hooks.json'), notifyScriptPath, 'hooks.json');
94
96
  }
95
- /** Project-level .cursor/hooks.json — Cursor CLI prefers this when agent runs in a repo. */
96
- export function installProjectCursorHooks(projectRoot, notifyScriptPath) {
97
- const root = resolve(projectRoot);
98
- const settingsPath = join(root, '.cursor', 'hooks.json');
99
- try {
100
- mkdirSync(join(root, '.cursor'), { recursive: true });
101
- mergeHooksFile(settingsPath, notifyScriptPath, `project hooks (${root})`);
102
- }
103
- catch (err) {
104
- const msg = err instanceof Error ? err.message : String(err);
105
- console.error(`[CursorHookInstaller] project failed: ${msg}`);
106
- }
107
- }
108
97
  //# sourceMappingURL=cursor-hook-installer.js.map