ftown-bridge 0.3.15 → 0.4.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 (54) hide show
  1. package/bin/ftown-sessions +5 -0
  2. package/dist/agent-commands.d.ts +17 -0
  3. package/dist/agent-commands.js +41 -0
  4. package/dist/agent-commands.js.map +1 -0
  5. package/dist/claude-runner.d.ts +27 -0
  6. package/dist/claude-runner.js +234 -44
  7. package/dist/claude-runner.js.map +1 -1
  8. package/dist/create-ftown-session.d.ts +49 -0
  9. package/dist/create-ftown-session.js +147 -0
  10. package/dist/create-ftown-session.js.map +1 -0
  11. package/dist/cursor-hook-installer.js +2 -2
  12. package/dist/cursor-hook-installer.js.map +1 -1
  13. package/dist/ftown-sessions-cli.d.ts +2 -0
  14. package/dist/ftown-sessions-cli.js +304 -0
  15. package/dist/ftown-sessions-cli.js.map +1 -0
  16. package/dist/harness-cli.d.ts +2 -0
  17. package/dist/harness-cli.js +432 -0
  18. package/dist/harness-cli.js.map +1 -0
  19. package/dist/harness-format.d.ts +3 -0
  20. package/dist/harness-format.js +14 -0
  21. package/dist/harness-format.js.map +1 -0
  22. package/dist/harness-installer.d.ts +16 -0
  23. package/dist/harness-installer.js +108 -0
  24. package/dist/harness-installer.js.map +1 -0
  25. package/dist/hook-installer.js +2 -2
  26. package/dist/hook-installer.js.map +1 -1
  27. package/dist/index.js +265 -61
  28. package/dist/index.js.map +1 -1
  29. package/dist/install-ftown-cli.d.ts +3 -0
  30. package/dist/install-ftown-cli.js +20 -0
  31. package/dist/install-ftown-cli.js.map +1 -0
  32. package/dist/install-ftown-skill.d.ts +4 -0
  33. package/dist/install-ftown-skill.js +50 -0
  34. package/dist/install-ftown-skill.js.map +1 -0
  35. package/dist/install-notify-script.d.ts +6 -0
  36. package/dist/install-notify-script.js +23 -0
  37. package/dist/install-notify-script.js.map +1 -0
  38. package/dist/local-api-server.d.ts +5 -0
  39. package/dist/local-api-server.js +137 -6
  40. package/dist/local-api-server.js.map +1 -1
  41. package/dist/session-registry.d.ts +11 -1
  42. package/dist/session-registry.js +3 -3
  43. package/dist/session-registry.js.map +1 -1
  44. package/dist/terminal-manager.d.ts +3 -1
  45. package/dist/terminal-manager.js +13 -6
  46. package/dist/terminal-manager.js.map +1 -1
  47. package/dist/tmux.d.ts +24 -0
  48. package/dist/tmux.js +149 -0
  49. package/dist/tmux.js.map +1 -0
  50. package/dist/types.d.ts +4 -0
  51. package/hooks/notify.sh +34 -12
  52. package/package.json +9 -4
  53. package/skills/ftown-sessions/SKILL.md +136 -0
  54. package/skills/ftown-sessions/scripts/ftown-sessions +4 -0
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env bash
2
+ # Dev/repo launcher — production copy lives at ~/.ftown/ftown-sessions
3
+ set -euo pipefail
4
+ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5
+ exec node "${ROOT}/dist/ftown-sessions-cli.js" "$@"
@@ -0,0 +1,17 @@
1
+ import type { ShellType } from './types.js';
2
+ /** Shell-escape a value for use inside zsh -c '...' */
3
+ export declare function shellQuote(value: string): string;
4
+ export declare function buildCursorAgentCommand(options: {
5
+ workingDir?: string;
6
+ model?: string;
7
+ cursorSessionId?: string;
8
+ }): string;
9
+ export interface BuildSessionCommandInput {
10
+ shellType?: ShellType;
11
+ workingDir?: string;
12
+ model?: string;
13
+ claudeSessionId?: string;
14
+ cursorSessionId?: string;
15
+ command?: string;
16
+ }
17
+ export declare function buildSessionCommand(input: BuildSessionCommandInput): string;
@@ -0,0 +1,41 @@
1
+ /** Shell-escape a value for use inside zsh -c '...' */
2
+ export function shellQuote(value) {
3
+ return `'${value.replace(/'/g, `'\\''`)}'`;
4
+ }
5
+ export function buildCursorAgentCommand(options) {
6
+ const parts = ['agent', '--force'];
7
+ if (options.workingDir?.trim()) {
8
+ parts.push('--workspace', shellQuote(options.workingDir.trim()));
9
+ }
10
+ if (options.model?.trim()) {
11
+ parts.push('--model', shellQuote(options.model.trim()));
12
+ }
13
+ if (options.cursorSessionId?.trim()) {
14
+ parts.push('--resume', shellQuote(options.cursorSessionId.trim()));
15
+ }
16
+ return parts.join(' ');
17
+ }
18
+ export function buildSessionCommand(input) {
19
+ if (input.command?.trim()) {
20
+ return input.command.trim();
21
+ }
22
+ const shellType = input.shellType ?? 'claude';
23
+ if (shellType === 'shell') {
24
+ return '/bin/zsh -l';
25
+ }
26
+ if (shellType === 'opencode') {
27
+ return 'opencode';
28
+ }
29
+ if (shellType === 'cursor') {
30
+ return buildCursorAgentCommand({
31
+ workingDir: input.workingDir,
32
+ model: input.model,
33
+ cursorSessionId: input.cursorSessionId,
34
+ });
35
+ }
36
+ if (input.claudeSessionId?.trim()) {
37
+ return `claude --allow-dangerously-skip-permissions --resume ${shellQuote(input.claudeSessionId.trim())}`;
38
+ }
39
+ return 'claude --allow-dangerously-skip-permissions';
40
+ }
41
+ //# sourceMappingURL=agent-commands.js.map
@@ -0,0 +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,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,42 @@ 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 whose tmux session is being killed via stop(); suppresses reattach. */
30
+ private readonly stopping;
31
+ /** Sessions detaching on shutdown; the tmux session stays alive, emit nothing. */
32
+ private readonly detachOnly;
33
+ /** Last client-requested size, so tmux reattach does not snap back to creation-time size. */
34
+ private readonly lastSizes;
35
+ getPreferredRuntime(): SessionRuntime;
36
+ getRuntime(sessionId: string): SessionRuntime | undefined;
19
37
  run(sessionId: string, command: string, options?: RunOptions): void;
38
+ /** Attach to an existing tmux session without creating it (session resurrection). */
39
+ reattach(sessionId: string, options?: ReattachOptions): boolean;
40
+ hasTmuxSession(sessionId: string): boolean;
20
41
  write(sessionId: string, data: string): boolean;
21
42
  resize(sessionId: string, cols: number, rows: number): boolean;
22
43
  stop(sessionId: string): boolean;
23
44
  stopAll(): void;
24
45
  isRunning(sessionId: string): boolean;
46
+ private killTmuxSessionLogged;
47
+ private buildEnv;
48
+ private runTmux;
49
+ private attachTmux;
50
+ private runDirect;
51
+ private scheduleInitialInput;
25
52
  }
26
53
  export {};
@@ -1,12 +1,128 @@
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 whose tmux session is being killed via stop(); suppresses reattach. */
9
+ stopping = new Set();
10
+ /** Sessions detaching on shutdown; the tmux session stays alive, emit nothing. */
11
+ detachOnly = new Set();
12
+ /** Last client-requested size, so tmux reattach does not snap back to creation-time size. */
13
+ lastSizes = new Map();
14
+ getPreferredRuntime() {
15
+ return isTmuxAvailable() ? 'tmux' : 'direct';
16
+ }
17
+ getRuntime(sessionId) {
18
+ return this.runtimes.get(sessionId);
19
+ }
6
20
  run(sessionId, command, options = {}) {
7
21
  const cwd = options.workingDir ?? process.cwd();
8
22
  const cols = options.cols ?? 120;
9
23
  const rows = options.rows ?? 40;
24
+ const env = this.buildEnv(sessionId, options);
25
+ console.log(`[ProcessRunner] Spawning command in ${cwd} (${this.getPreferredRuntime()}): ${command}`);
26
+ if (this.getPreferredRuntime() === 'tmux') {
27
+ // Registered before the async tmux creation so a stop() arriving in the
28
+ // creation window is recorded (via this.stopping) instead of lost.
29
+ this.runtimes.set(sessionId, 'tmux');
30
+ void this.runTmux(sessionId, command, env, {
31
+ cwd,
32
+ cols,
33
+ rows,
34
+ initialInput: options.initialInput,
35
+ initialInputDelay: options.initialInputDelay,
36
+ submitSuffix: options.submitSuffix,
37
+ });
38
+ return;
39
+ }
40
+ this.runDirect(sessionId, command, env, cwd, cols, rows, options);
41
+ }
42
+ /** Attach to an existing tmux session without creating it (session resurrection). */
43
+ reattach(sessionId, options = {}) {
44
+ if (this.activeProcesses.has(sessionId)) {
45
+ return true;
46
+ }
47
+ if (!isTmuxAvailable() || !hasTmuxSession(sessionId)) {
48
+ return false;
49
+ }
50
+ const env = this.buildEnv(sessionId, { parentSessionId: options.parentSessionId });
51
+ this.attachTmux(sessionId, {
52
+ env,
53
+ cwd: options.workingDir ?? process.cwd(),
54
+ cols: options.cols ?? 120,
55
+ rows: options.rows ?? 40,
56
+ });
57
+ return true;
58
+ }
59
+ hasTmuxSession(sessionId) {
60
+ return isTmuxAvailable() && hasTmuxSession(sessionId);
61
+ }
62
+ write(sessionId, data) {
63
+ const proc = this.activeProcesses.get(sessionId);
64
+ if (!proc) {
65
+ return false;
66
+ }
67
+ proc.write(data);
68
+ return true;
69
+ }
70
+ resize(sessionId, cols, rows) {
71
+ const proc = this.activeProcesses.get(sessionId);
72
+ if (!proc) {
73
+ return false;
74
+ }
75
+ proc.resize(cols, rows);
76
+ this.lastSizes.set(sessionId, { cols, rows });
77
+ return true;
78
+ }
79
+ stop(sessionId) {
80
+ const proc = this.activeProcesses.get(sessionId);
81
+ const isTmux = this.runtimes.get(sessionId) === 'tmux';
82
+ if (isTmux) {
83
+ this.stopping.add(sessionId);
84
+ this.killTmuxSessionLogged(sessionId);
85
+ }
86
+ if (!proc) {
87
+ // Orphaned tmux session with no attached client (e.g. failed reattach).
88
+ if (!isTmux && isTmuxAvailable() && hasTmuxSession(sessionId)) {
89
+ this.killTmuxSessionLogged(sessionId);
90
+ return true;
91
+ }
92
+ return isTmux;
93
+ }
94
+ proc.kill();
95
+ setTimeout(() => {
96
+ if (this.activeProcesses.has(sessionId)) {
97
+ proc.kill('SIGKILL');
98
+ this.activeProcesses.delete(sessionId);
99
+ }
100
+ }, 5000);
101
+ return true;
102
+ }
103
+ stopAll() {
104
+ for (const [sessionId, proc] of this.activeProcesses) {
105
+ if (this.runtimes.get(sessionId) === 'tmux') {
106
+ // Detach only — the tmux session keeps running and survives bridge restarts.
107
+ this.detachOnly.add(sessionId);
108
+ proc.kill();
109
+ }
110
+ else {
111
+ this.stop(sessionId);
112
+ }
113
+ }
114
+ }
115
+ isRunning(sessionId) {
116
+ return this.activeProcesses.has(sessionId);
117
+ }
118
+ killTmuxSessionLogged(sessionId) {
119
+ void killTmuxSession(sessionId).then((killed) => {
120
+ if (!killed && hasTmuxSession(sessionId)) {
121
+ console.error(`[ProcessRunner] Failed to kill tmux session for ${sessionId}`);
122
+ }
123
+ });
124
+ }
125
+ buildEnv(sessionId, options) {
10
126
  const env = {
11
127
  ...process.env,
12
128
  };
@@ -20,11 +136,109 @@ export class ProcessRunner extends EventEmitter {
20
136
  if (options.hookToken) {
21
137
  env.FTOWN_HOOK_TOKEN = options.hookToken;
22
138
  }
139
+ if (options.parentSessionId) {
140
+ env.FTOWN_PARENT_SESSION_ID = options.parentSessionId;
141
+ }
23
142
  if (options.env) {
24
143
  Object.assign(env, options.env);
25
144
  }
26
145
  applyTerminalColorEnv(env);
27
- console.log(`[ProcessRunner] Spawning command in ${cwd}: ${command}`);
146
+ return env;
147
+ }
148
+ async runTmux(sessionId, command, env, params) {
149
+ try {
150
+ await createTmuxSession({
151
+ sessionId,
152
+ command,
153
+ cwd: params.cwd,
154
+ cols: params.cols,
155
+ rows: params.rows,
156
+ env,
157
+ });
158
+ }
159
+ catch (err) {
160
+ const wasStopping = this.stopping.delete(sessionId);
161
+ this.runtimes.delete(sessionId);
162
+ console.error(`[ProcessRunner] Failed to create tmux session:`, err);
163
+ if (!wasStopping) {
164
+ this.emit('error', sessionId, err instanceof Error ? err : new Error(String(err)));
165
+ }
166
+ return;
167
+ }
168
+ // stop() may have arrived while the session was being created; honor it
169
+ // instead of attaching. stop_session already persisted the final status.
170
+ if (this.stopping.delete(sessionId)) {
171
+ this.runtimes.delete(sessionId);
172
+ this.killTmuxSessionLogged(sessionId);
173
+ return;
174
+ }
175
+ this.attachTmux(sessionId, { ...params, env });
176
+ }
177
+ attachTmux(sessionId, params) {
178
+ // params holds creation-time cols/rows; prefer the latest client size.
179
+ const size = this.lastSizes.get(sessionId);
180
+ if (size) {
181
+ params = { ...params, cols: size.cols, rows: size.rows };
182
+ }
183
+ let proc;
184
+ try {
185
+ proc = pty.spawn('tmux', ['-L', TMUX_SOCKET_NAME, 'attach-session', '-t', `=${tmuxSessionName(sessionId)}`], {
186
+ name: 'xterm-256color',
187
+ cols: params.cols,
188
+ rows: params.rows,
189
+ cwd: params.cwd,
190
+ env: params.env,
191
+ });
192
+ console.log(`[ProcessRunner] Attached to tmux session ${tmuxSessionName(sessionId)}, client pid: ${proc.pid}`);
193
+ }
194
+ catch (err) {
195
+ console.error(`[ProcessRunner] Failed to attach to tmux session:`, err);
196
+ this.emit('error', sessionId, err instanceof Error ? err : new Error(String(err)));
197
+ return;
198
+ }
199
+ this.activeProcesses.set(sessionId, proc);
200
+ this.runtimes.set(sessionId, 'tmux');
201
+ proc.onData((data) => {
202
+ this.emit('data', sessionId, data);
203
+ });
204
+ proc.onExit(({ exitCode, signal }) => {
205
+ console.log(`[ProcessRunner] tmux attach client exited, code: ${exitCode}, signal: ${signal}`);
206
+ this.activeProcesses.delete(sessionId);
207
+ this.runtimes.delete(sessionId);
208
+ if (this.detachOnly.delete(sessionId)) {
209
+ return;
210
+ }
211
+ if (this.stopping.delete(sessionId)) {
212
+ // stop() initiated this exit; stop_session persists the final status,
213
+ // so emit nothing (kill-session makes the trap record a bogus code).
214
+ readAndClearExitCode(sessionId);
215
+ this.lastSizes.delete(sessionId);
216
+ return;
217
+ }
218
+ if (hasTmuxSession(sessionId)) {
219
+ // Client detached but the command is still running — reattach to keep streaming.
220
+ this.attachTmux(sessionId, { ...params, initialInput: undefined });
221
+ return;
222
+ }
223
+ this.lastSizes.delete(sessionId);
224
+ // The attach client's exit code is unrelated to the command's; the real
225
+ // code is written to a temp file by the command wrapper inside tmux.
226
+ const realCode = readAndClearExitCode(sessionId);
227
+ if (realCode === undefined) {
228
+ // No trap file: the session was destroyed without the wrapper's EXIT
229
+ // trap running (SIGKILL, OOM, tmux server killed).
230
+ this.emit('error', sessionId, new Error('tmux session ended without recording an exit code'));
231
+ }
232
+ else if (realCode === 0) {
233
+ this.emit('complete', sessionId);
234
+ }
235
+ else {
236
+ this.emit('error', sessionId, new Error(`Process exited with code ${realCode}`));
237
+ }
238
+ });
239
+ this.scheduleInitialInput(sessionId, proc, params.initialInput, params.initialInputDelay, params.submitSuffix);
240
+ }
241
+ runDirect(sessionId, command, env, cwd, cols, rows, options) {
28
242
  let proc;
29
243
  try {
30
244
  proc = pty.spawn('/bin/zsh', ['-l', '-c', command], {
@@ -42,12 +256,15 @@ export class ProcessRunner extends EventEmitter {
42
256
  return;
43
257
  }
44
258
  this.activeProcesses.set(sessionId, proc);
259
+ this.runtimes.set(sessionId, 'direct');
45
260
  proc.onData((data) => {
46
261
  this.emit('data', sessionId, data);
47
262
  });
48
263
  proc.onExit(({ exitCode, signal }) => {
49
264
  console.log(`[ProcessRunner] Process exited, code: ${exitCode}, signal: ${signal}`);
50
265
  this.activeProcesses.delete(sessionId);
266
+ this.runtimes.delete(sessionId);
267
+ this.lastSizes.delete(sessionId);
51
268
  if (exitCode === 0 || exitCode === null || exitCode === undefined) {
52
269
  this.emit('complete', sessionId);
53
270
  }
@@ -55,53 +272,26 @@ export class ProcessRunner extends EventEmitter {
55
272
  this.emit('error', sessionId, new Error(`Process exited with code ${exitCode}`));
56
273
  }
57
274
  });
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
- }
275
+ this.scheduleInitialInput(sessionId, proc, options.initialInput, options.initialInputDelay, options.submitSuffix);
67
276
  }
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;
277
+ scheduleInitialInput(sessionId, proc, initialInput, initialInputDelay, submitSuffix) {
278
+ if (!initialInput) {
279
+ return;
88
280
  }
89
- proc.kill();
281
+ const delay = initialInputDelay ?? 2000;
90
282
  setTimeout(() => {
91
- if (this.activeProcesses.has(sessionId)) {
92
- proc.kill('SIGKILL');
93
- this.activeProcesses.delete(sessionId);
283
+ if (this.activeProcesses.get(sessionId) === proc) {
284
+ console.log(`[ProcessRunner] Sending initial input to session ${sessionId}`);
285
+ proc.write(initialInput);
286
+ // Submit separately after the paste settles: composer TUIs (Claude/Cursor) treat a
287
+ // trailing CR inside a bracketed paste of multi-line text as a newline, not a submit.
288
+ setTimeout(() => {
289
+ if (this.activeProcesses.get(sessionId) === proc) {
290
+ proc.write(submitSuffix ?? '\r');
291
+ }
292
+ }, 600);
94
293
  }
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);
294
+ }, delay);
105
295
  }
106
296
  }
107
297
  //# 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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"}
@@ -0,0 +1,49 @@
1
+ import type { CentrifugoClient } from './centrifugo-client.js';
2
+ import type { ProcessRunner } from './claude-runner.js';
3
+ import type { SessionStore } from './session-store.js';
4
+ import type { Session, ShellType } from './types.js';
5
+ export interface CreateFtownSessionDeps {
6
+ store: SessionStore;
7
+ runner: ProcessRunner;
8
+ centrifugo: CentrifugoClient;
9
+ userId: string;
10
+ bridgeId: string;
11
+ hookPort: number;
12
+ hookToken: string;
13
+ notifyScriptPath: string;
14
+ wireTerminalInput: (sessionId: string) => void;
15
+ }
16
+ export interface CreateFtownSessionInput {
17
+ command?: string;
18
+ prompt?: string;
19
+ name?: string;
20
+ workingDir?: string;
21
+ shellType?: ShellType;
22
+ model?: string;
23
+ claudeSessionId?: string;
24
+ cursorSessionId?: string;
25
+ env?: Record<string, string>;
26
+ parentSessionId?: string;
27
+ initialInput?: string;
28
+ initialInputDelay?: number;
29
+ orchestrator?: boolean;
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;
46
+ export declare function createFtownSession(deps: CreateFtownSessionDeps, input: CreateFtownSessionInput): Promise<Session>;
47
+ /** Map a Local API JSON body into create input. */
48
+ export declare function parseCreateSessionBody(body: Record<string, unknown>, callerSessionId?: string): CreateFtownSessionInput;
49
+ export {};