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,432 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Local bridge harness — talks to ftown-bridge LocalApiServer via ~/.ftown/bridge.json
4
+ */
5
+ import { existsSync, readFileSync } from 'node:fs';
6
+ import { homedir } from 'node:os';
7
+ import { join, resolve } from 'node:path';
8
+ import { Command } from 'commander';
9
+ import { cleanTerminalLine, formatLogLines, isDisplayableLine } from './harness-format.js';
10
+ const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
11
+ const BRIDGE_JSON = join(homedir(), '.ftown', 'bridge.json');
12
+ const REGISTRY_JSON = join(homedir(), '.ftown', 'session-registry.json');
13
+ function loadPointer() {
14
+ if (!existsSync(BRIDGE_JSON)) {
15
+ const wrapper = join(homedir(), '.ftown', 'bin', 'ftown-harness');
16
+ throw new Error(`Bridge not running (no ${BRIDGE_JSON}). Start ftown-bridge from the UI CLI token, then use ${wrapper}`);
17
+ }
18
+ const parsed = JSON.parse(readFileSync(BRIDGE_JSON, 'utf8'));
19
+ if (!parsed.port || !parsed.token) {
20
+ throw new Error(`Invalid ${BRIDGE_JSON} — missing port or token`);
21
+ }
22
+ return parsed;
23
+ }
24
+ function loadRegistry() {
25
+ if (!existsSync(REGISTRY_JSON)) {
26
+ return { byWorkspace: {}, byConversation: {} };
27
+ }
28
+ const parsed = JSON.parse(readFileSync(REGISTRY_JSON, 'utf8'));
29
+ return {
30
+ byWorkspace: parsed.byWorkspace ?? {},
31
+ byConversation: parsed.byConversation ?? {},
32
+ };
33
+ }
34
+ function emit(json, data, text) {
35
+ if (json)
36
+ console.log(JSON.stringify(data, null, 2));
37
+ else
38
+ console.log(text);
39
+ }
40
+ async function api(pointer, method, path, body) {
41
+ const url = `http://127.0.0.1:${pointer.port}${path}`;
42
+ const res = await fetch(url, {
43
+ method,
44
+ headers: {
45
+ Authorization: `Bearer ${pointer.token}`,
46
+ ...(body !== undefined ? { 'Content-Type': 'application/json' } : {}),
47
+ },
48
+ body: body !== undefined ? JSON.stringify(body) : undefined,
49
+ });
50
+ const data = (await res.json());
51
+ if (!res.ok) {
52
+ throw new Error(data.error ?? `HTTP ${res.status} ${path}`);
53
+ }
54
+ return data;
55
+ }
56
+ async function listSessions(pointer) {
57
+ const { sessions } = await api(pointer, 'GET', '/api/sessions');
58
+ return sessions;
59
+ }
60
+ async function getSession(pointer, id) {
61
+ const { session } = await api(pointer, 'GET', `/api/sessions/${id}`);
62
+ return session;
63
+ }
64
+ async function getLogLineCount(pointer, id) {
65
+ const meta = await api(pointer, 'GET', `/api/sessions/${id}/screen?limit=1`);
66
+ return meta.totalLines;
67
+ }
68
+ async function isAlive(pointer, id) {
69
+ const { running } = await api(pointer, 'GET', `/api/sessions/${id}/running`);
70
+ return running;
71
+ }
72
+ function resolveSessionId(sessions, query) {
73
+ if (UUID_RE.test(query) || query.length >= 8) {
74
+ const byPrefix = sessions.filter((s) => s.id === query || s.id.startsWith(query));
75
+ if (byPrefix.length === 1)
76
+ return byPrefix[0].id;
77
+ if (byPrefix.length > 1) {
78
+ throw new Error(`Ambiguous id prefix "${query}": ${byPrefix.map((s) => `${s.name} (${s.id.slice(0, 8)}…)`).join(', ')}`);
79
+ }
80
+ }
81
+ const exact = sessions.filter((s) => s.name === query);
82
+ if (exact.length === 1)
83
+ return exact[0].id;
84
+ const fuzzy = sessions.filter((s) => s.name.toLowerCase().includes(query.toLowerCase()));
85
+ if (fuzzy.length === 1)
86
+ return fuzzy[0].id;
87
+ if (fuzzy.length > 1) {
88
+ throw new Error(`Ambiguous name "${query}": ${fuzzy.map((s) => s.name).join(', ')} — use full name or id prefix`);
89
+ }
90
+ throw new Error(`No session matching "${query}"`);
91
+ }
92
+ function resolveWorkspaceSessionId(cwd) {
93
+ const reg = loadRegistry();
94
+ let dir = resolve(cwd);
95
+ const root = resolve('/');
96
+ while (dir.startsWith(root)) {
97
+ const id = reg.byWorkspace[dir];
98
+ if (id)
99
+ return { id, workspace: dir };
100
+ const parent = resolve(dir, '..');
101
+ if (parent === dir)
102
+ break;
103
+ dir = parent;
104
+ }
105
+ return undefined;
106
+ }
107
+ function submitSuffix(shellType) {
108
+ switch (shellType) {
109
+ case 'claude':
110
+ case 'cursor':
111
+ return '\x1b\r';
112
+ default:
113
+ return '\r';
114
+ }
115
+ }
116
+ async function fetchTail(pointer, id, n) {
117
+ const totalLines = await getLogLineCount(pointer, id);
118
+ if (totalLines === 0)
119
+ return [];
120
+ const start = Math.max(0, totalLines - n);
121
+ const scr = await api(pointer, 'GET', `/api/sessions/${id}/screen?offset=${start}&limit=${n}`);
122
+ return formatLogLines(scr.lines);
123
+ }
124
+ async function printTail(pointer, id, n, opts) {
125
+ const lines = await fetchTail(pointer, id, n);
126
+ if (opts.json) {
127
+ emit(true, { sessionId: id, lines }, '');
128
+ return lines;
129
+ }
130
+ if (opts.header)
131
+ console.log(opts.header);
132
+ for (const line of lines)
133
+ console.log(line);
134
+ return lines;
135
+ }
136
+ async function cmdStatus(pointer, json) {
137
+ let alive = false;
138
+ try {
139
+ await api(pointer, 'GET', '/api/sessions');
140
+ alive = true;
141
+ }
142
+ catch {
143
+ alive = false;
144
+ }
145
+ const data = {
146
+ bridge: alive ? 'up' : 'down',
147
+ url: `http://127.0.0.1:${pointer.port}`,
148
+ auth: BRIDGE_JSON,
149
+ cli: pointer.harness ?? join(homedir(), '.ftown', 'bin', 'ftown-harness'),
150
+ pid: pointer.pid,
151
+ bridgeId: pointer.bridgeId,
152
+ since: pointer.startedAt,
153
+ };
154
+ if (json)
155
+ emit(true, data, '');
156
+ else {
157
+ console.log(`bridge: ${data.bridge}`);
158
+ console.log(`url: ${data.url}`);
159
+ console.log(`auth: ${data.auth}`);
160
+ console.log(`cli: ${data.cli}`);
161
+ if (data.pid)
162
+ console.log(`pid: ${data.pid}`);
163
+ if (data.bridgeId)
164
+ console.log(`id: ${data.bridgeId}`);
165
+ if (data.since)
166
+ console.log(`since: ${data.since}`);
167
+ }
168
+ }
169
+ async function cmdLs(pointer, opts) {
170
+ const sessions = await listSessions(pointer);
171
+ if (sessions.length === 0) {
172
+ emit(opts.json, { sessions: [] }, '(no sessions)');
173
+ return;
174
+ }
175
+ const cwd = resolve(process.cwd());
176
+ const hereResolved = resolveWorkspaceSessionId(cwd);
177
+ const hereId = hereResolved?.id;
178
+ const rows = [];
179
+ for (const s of sessions.sort((a, b) => (a.name ?? '').localeCompare(b.name ?? ''))) {
180
+ const logLines = await getLogLineCount(pointer, s.id);
181
+ const alive = s.status === 'running' ? await isAlive(pointer, s.id) : false;
182
+ const hasLog = logLines > 0;
183
+ const mark = s.id === hereId;
184
+ const row = {
185
+ mark,
186
+ name: s.name,
187
+ id: s.id,
188
+ status: s.status,
189
+ alive,
190
+ shellType: s.shellType,
191
+ workingDir: s.workingDir,
192
+ logLines,
193
+ hasLog,
194
+ };
195
+ rows.push(row);
196
+ if (!opts.json) {
197
+ const wd = s.workingDir ? `…${s.workingDir.slice(-30)}` : '';
198
+ const logLabel = hasLog ? `log=${logLines}` : 'no log';
199
+ const proc = alive ? 'alive' : 'dead ';
200
+ console.log(`${mark ? '*' : ' '} ${s.name.padEnd(14)} ${s.id.slice(0, 8)}… ${s.status.padEnd(9)} ${proc} ${logLabel.padEnd(12)} ${(s.shellType ?? '?').padEnd(7)} ${wd}`);
201
+ if (opts.tail > 0 && hasLog) {
202
+ const lines = await fetchTail(pointer, s.id, opts.tail);
203
+ for (const line of lines)
204
+ console.log(` ${line.slice(0, 120)}`);
205
+ }
206
+ }
207
+ }
208
+ if (opts.json) {
209
+ emit(true, { sessions: rows, hereWorkspace: hereResolved?.workspace }, '');
210
+ }
211
+ else if (hereId) {
212
+ console.log('\n* = session for current working directory');
213
+ }
214
+ }
215
+ async function cmdHere(pointer, opts) {
216
+ const cwd = resolve(opts.cwd ?? process.cwd());
217
+ const resolved = resolveWorkspaceSessionId(cwd);
218
+ if (!resolved) {
219
+ emit(opts.json, { error: 'no_registry', cwd }, `No registry entry for workspace tree from: ${cwd}`);
220
+ return;
221
+ }
222
+ const { id, workspace } = resolved;
223
+ const session = await getSession(pointer, id);
224
+ const alive = await isAlive(pointer, id);
225
+ const logLines = await getLogLineCount(pointer, id);
226
+ const meta = {
227
+ session,
228
+ registryWorkspace: workspace,
229
+ alive,
230
+ logLines,
231
+ hasLog: logLines > 0,
232
+ };
233
+ if (opts.json) {
234
+ const out = { ...meta };
235
+ if (opts.lines > 0 && logLines > 0) {
236
+ out.tail = await fetchTail(pointer, id, opts.lines);
237
+ }
238
+ emit(true, out, '');
239
+ return;
240
+ }
241
+ console.log(`${session.name} (${id})`);
242
+ console.log(`registry=${workspace}`);
243
+ console.log(`status=${session.status} alive=${alive} shell=${session.shellType ?? '?'} log=${logLines}`);
244
+ if (session.workingDir)
245
+ console.log(`cwd=${session.workingDir}`);
246
+ if (opts.lines <= 0)
247
+ return;
248
+ if (logLines === 0) {
249
+ console.log('---');
250
+ console.log('(no terminal log yet)');
251
+ return;
252
+ }
253
+ if (!alive) {
254
+ console.log(`---`);
255
+ console.log(`# process not running — showing last ${opts.lines} log lines (status=${session.status})`);
256
+ }
257
+ else {
258
+ console.log('---');
259
+ }
260
+ await printTail(pointer, id, opts.lines, {});
261
+ }
262
+ async function cmdTail(pointer, query, opts) {
263
+ const sessions = await listSessions(pointer);
264
+ const id = resolveSessionId(sessions, query);
265
+ const session = await getSession(pointer, id);
266
+ const logLines = await getLogLineCount(pointer, id);
267
+ if (opts.json) {
268
+ emit(true, { session, logLines, lines: await fetchTail(pointer, id, opts.lines) }, '');
269
+ return;
270
+ }
271
+ console.log(`# ${session.name} (${id}) log=${logLines}`);
272
+ await printTail(pointer, id, opts.lines, {});
273
+ }
274
+ function printGrepMatch(m, context) {
275
+ if (context > 0 && m.before?.length) {
276
+ const startLine = m.lineNumber - m.before.length;
277
+ for (let i = 0; i < m.before.length; i++) {
278
+ const t = cleanTerminalLine(m.before[i]);
279
+ if (isDisplayableLine(t))
280
+ console.log(` ${startLine + i}- ${t.slice(0, 200)}`);
281
+ }
282
+ }
283
+ const hit = cleanTerminalLine(m.text);
284
+ if (isDisplayableLine(hit))
285
+ console.log(`${m.lineNumber}: ${hit.slice(0, 200)}`);
286
+ if (context > 0 && m.after?.length) {
287
+ for (let j = 0; j < m.after.length; j++) {
288
+ const t = cleanTerminalLine(m.after[j]);
289
+ if (isDisplayableLine(t))
290
+ console.log(` ${m.lineNumber + j + 1}- ${t.slice(0, 200)}`);
291
+ }
292
+ }
293
+ }
294
+ async function cmdGrep(pointer, query, pattern, opts) {
295
+ const sessions = await listSessions(pointer);
296
+ const id = resolveSessionId(sessions, query);
297
+ const result = await api(pointer, 'POST', `/api/sessions/${id}/grep`, {
298
+ pattern,
299
+ offset: opts.offset,
300
+ limit: opts.limit,
301
+ ...(opts.context > 0 ? { context: opts.context } : {}),
302
+ });
303
+ if (opts.json) {
304
+ const cleaned = result.matches.map((m) => ({
305
+ lineNumber: m.lineNumber,
306
+ text: cleanTerminalLine(m.text),
307
+ before: m.before?.map(cleanTerminalLine).filter(isDisplayableLine),
308
+ after: m.after?.map(cleanTerminalLine).filter(isDisplayableLine),
309
+ }));
310
+ emit(true, { totalMatches: result.totalMatches, matches: cleaned }, '');
311
+ return;
312
+ }
313
+ console.log(`# matches ${result.totalMatches} (showing ${result.matches.length})`);
314
+ for (const m of result.matches) {
315
+ if (opts.context > 0)
316
+ printGrepMatch(m, opts.context);
317
+ else {
318
+ const hit = cleanTerminalLine(m.text);
319
+ if (isDisplayableLine(hit))
320
+ console.log(`${m.lineNumber}: ${hit.slice(0, 200)}`);
321
+ }
322
+ }
323
+ }
324
+ async function cmdSend(pointer, query, text, opts) {
325
+ const sessions = await listSessions(pointer);
326
+ const id = resolveSessionId(sessions, query);
327
+ const session = await getSession(pointer, id);
328
+ let keys = text;
329
+ if (opts.submit)
330
+ keys += submitSuffix(session.shellType);
331
+ const plan = {
332
+ sessionId: id,
333
+ name: session.name,
334
+ shellType: session.shellType,
335
+ submit: opts.submit,
336
+ bytes: keys.length,
337
+ dryRun: opts.dryRun,
338
+ };
339
+ if (opts.dryRun) {
340
+ emit(opts.json, plan, `dry-run: would send ${keys.length} bytes to ${session.name} (submit=${opts.submit})`);
341
+ return;
342
+ }
343
+ await api(pointer, 'POST', `/api/sessions/${id}/keys`, { keys });
344
+ emit(opts.json, { ...plan, sent: true }, `sent ${keys.length} bytes to ${session.name} (submit=${opts.submit})`);
345
+ }
346
+ const program = new Command();
347
+ program
348
+ .name('ftown-harness')
349
+ .description('CLI for ftown bridge local API (~/.ftown/bridge.json)')
350
+ .option('--json', 'Machine-readable JSON output');
351
+ program
352
+ .command('status')
353
+ .description('Bridge pointer and health')
354
+ .action(async (_opts, cmd) => {
355
+ const pointer = loadPointer();
356
+ await cmdStatus(pointer, !!cmd.parent?.opts().json);
357
+ });
358
+ program
359
+ .command('ls')
360
+ .description('List sessions (* = cwd workspace)')
361
+ .option('-n, --tail <n>', 'Preview last N log lines per session (incl. dead)', '0')
362
+ .action(async (opts, cmd) => {
363
+ const pointer = loadPointer();
364
+ await cmdLs(pointer, {
365
+ tail: parseInt(opts.tail, 10) || 0,
366
+ json: !!cmd.parent?.opts().json,
367
+ });
368
+ });
369
+ program
370
+ .command('here')
371
+ .description('Session for current workspace (from registry)')
372
+ .option('-n, --lines <n>', 'Tail lines (works for dead sessions with logs)', '15')
373
+ .option('--cwd <path>', 'Workspace path (default: process.cwd())')
374
+ .action(async (opts, cmd) => {
375
+ const pointer = loadPointer();
376
+ await cmdHere(pointer, {
377
+ lines: parseInt(opts.lines, 10) || 15,
378
+ cwd: opts.cwd,
379
+ json: !!cmd.parent?.opts().json,
380
+ });
381
+ });
382
+ program
383
+ .command('tail <session>')
384
+ .description('Last N lines of terminal (ANSI/OSC stripped)')
385
+ .option('-n, --lines <n>', 'Line count', '40')
386
+ .action(async (session, opts, cmd) => {
387
+ const pointer = loadPointer();
388
+ await cmdTail(pointer, session, {
389
+ lines: parseInt(opts.lines, 10) || 40,
390
+ json: !!cmd.parent?.opts().json,
391
+ });
392
+ });
393
+ program
394
+ .command('grep <session> <pattern>')
395
+ .description('Search terminal log (regex)')
396
+ .option('-n, --limit <n>', 'Max matches', '30')
397
+ .option('--offset <n>', 'Match offset', '0')
398
+ .option('-C, --context <n>', 'Lines of context before/after each match', '0')
399
+ .action(async (session, pattern, opts, cmd) => {
400
+ const pointer = loadPointer();
401
+ await cmdGrep(pointer, session, pattern, {
402
+ limit: parseInt(opts.limit, 10) || 30,
403
+ offset: parseInt(opts.offset, 10) || 0,
404
+ context: parseInt(opts.context, 10) || 0,
405
+ json: !!cmd.parent?.opts().json,
406
+ });
407
+ });
408
+ program
409
+ .command('send <session> <text...>')
410
+ .description('Send keystrokes (--submit adds Enter for shell type)')
411
+ .option('-s, --submit', 'Append submit sequence after text')
412
+ .option('-l, --literal', 'Do not interpret escape sequences in text')
413
+ .option('--dry-run', 'Print what would be sent without writing to PTY')
414
+ .action(async (session, textParts, opts, cmd) => {
415
+ const pointer = loadPointer();
416
+ let text = textParts.join(' ');
417
+ if (!opts.literal) {
418
+ text = text.replace(/\\r/g, '\r').replace(/\\n/g, '\n').replace(/\\t/g, '\t').replace(/\\x1b/g, '\x1b');
419
+ }
420
+ await cmdSend(pointer, session, text, {
421
+ submit: !!opts.submit,
422
+ literal: !!opts.literal,
423
+ dryRun: !!opts.dryRun,
424
+ json: !!cmd.parent?.opts().json,
425
+ });
426
+ });
427
+ program.parseAsync(process.argv).catch((err) => {
428
+ const msg = err instanceof Error ? err.message : String(err);
429
+ console.error(`ftown-harness: ${msg}`);
430
+ process.exit(1);
431
+ });
432
+ //# sourceMappingURL=harness-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness-cli.js","sourceRoot":"","sources":["../src/harness-cli.ts"],"names":[],"mappings":";AACA;;GAEG;AACH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE3F,MAAM,OAAO,GAAG,iEAAiE,CAAC;AAClF,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;AAC7D,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,uBAAuB,CAAC,CAAC;AAiCzE,SAAS,WAAW;IAClB,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,eAAe,CAAC,CAAC;QAClE,MAAM,IAAI,KAAK,CACb,0BAA0B,WAAW,yDAAyD,OAAO,EAAE,CACxG,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,WAAW,EAAE,MAAM,CAAC,CAA2B,CAAC;IACvF,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,WAAW,WAAW,0BAA0B,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,MAAuB,CAAC;AACjC,CAAC;AAED,SAAS,YAAY;IACnB,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC;IACjD,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAA0B,CAAC;IACxF,OAAO;QACL,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,EAAE;QACrC,cAAc,EAAE,MAAM,CAAC,cAAc,IAAI,EAAE;KAC5C,CAAC;AACJ,CAAC;AAED,SAAS,IAAI,CAAC,IAAa,EAAE,IAAa,EAAE,IAAY;IACtD,IAAI,IAAI;QAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;;QAChD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC;AAED,KAAK,UAAU,GAAG,CAChB,OAAsB,EACtB,MAAc,EACd,IAAY,EACZ,IAAc;IAEd,MAAM,GAAG,GAAG,oBAAoB,OAAO,CAAC,IAAI,GAAG,IAAI,EAAE,CAAC;IACtD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,MAAM;QACN,OAAO,EAAE;YACP,aAAa,EAAE,UAAU,OAAO,CAAC,KAAK,EAAE;YACxC,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACtE;QACD,IAAI,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;KAC5D,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA2B,CAAC;IAC1D,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,QAAQ,GAAG,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,OAAsB;IAChD,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,GAAG,CAA0B,OAAO,EAAE,KAAK,EAAE,eAAe,CAAC,CAAC;IACzF,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,OAAsB,EAAE,EAAU;IAC1D,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,GAAG,CAAuB,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,EAAE,CAAC,CAAC;IAC3F,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,OAAsB,EAAE,EAAU;IAC/D,MAAM,IAAI,GAAG,MAAM,GAAG,CACpB,OAAO,EACP,KAAK,EACL,iBAAiB,EAAE,iBAAiB,CACrC,CAAC;IACF,OAAO,IAAI,CAAC,UAAU,CAAC;AACzB,CAAC;AAED,KAAK,UAAU,OAAO,CAAC,OAAsB,EAAE,EAAU;IACvD,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,GAAG,CAAuB,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,UAAU,CAAC,CAAC;IACnG,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,gBAAgB,CAAC,QAAmB,EAAE,KAAa;IAC1D,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QAC7C,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;QAClF,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACjD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CACb,wBAAwB,KAAK,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACxG,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC;IACvD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAE3C,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IACzF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3C,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CACb,mBAAmB,KAAK,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,+BAA+B,CACjG,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,wBAAwB,KAAK,GAAG,CAAC,CAAC;AACpD,CAAC;AAED,SAAS,yBAAyB,CAAC,GAAW;IAC5C,MAAM,GAAG,GAAG,YAAY,EAAE,CAAC;IAC3B,IAAI,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACvB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAC1B,OAAO,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5B,MAAM,EAAE,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,EAAE;YAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC;QACtC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAClC,IAAI,MAAM,KAAK,GAAG;YAAE,MAAM;QAC1B,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,YAAY,CAAC,SAAkB;IACtC,QAAQ,SAAS,EAAE,CAAC;QAClB,KAAK,QAAQ,CAAC;QACd,KAAK,QAAQ;YACX,OAAO,QAAQ,CAAC;QAClB;YACE,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,OAAsB,EAAE,EAAU,EAAE,CAAS;IACpE,MAAM,UAAU,GAAG,MAAM,eAAe,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IACtD,IAAI,UAAU,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAChC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,GAAG,CAAC,CAAC,CAAC;IAC1C,MAAM,GAAG,GAAG,MAAM,GAAG,CACnB,OAAO,EACP,KAAK,EACL,iBAAiB,EAAE,kBAAkB,KAAK,UAAU,CAAC,EAAE,CACxD,CAAC;IACF,OAAO,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AACnC,CAAC;AAED,KAAK,UAAU,SAAS,CACtB,OAAsB,EACtB,EAAU,EACV,CAAS,EACT,IAAyC;IAEzC,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IAC9C,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,IAAI,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;QACzC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,IAAI,CAAC,MAAM;QAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1C,KAAK,MAAM,IAAI,IAAI,KAAK;QAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC5C,OAAO,KAAK,CAAC;AACf,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,OAAsB,EAAE,IAAa;IAC5D,IAAI,KAAK,GAAG,KAAK,CAAC;IAClB,IAAI,CAAC;QACH,MAAM,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,eAAe,CAAC,CAAC;QAC3C,KAAK,GAAG,IAAI,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACP,KAAK,GAAG,KAAK,CAAC;IAChB,CAAC;IACD,MAAM,IAAI,GAAG;QACX,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM;QAC7B,GAAG,EAAE,oBAAoB,OAAO,CAAC,IAAI,EAAE;QACvC,IAAI,EAAE,WAAW;QACjB,GAAG,EAAE,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,eAAe,CAAC;QACzE,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,KAAK,EAAE,OAAO,CAAC,SAAS;KACzB,CAAC;IACF,IAAI,IAAI;QAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;SAC1B,CAAC;QACJ,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACnC,IAAI,IAAI,CAAC,GAAG;YAAE,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACjD,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC3D,IAAI,IAAI,CAAC,KAAK;YAAE,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IACvD,CAAC;AACH,CAAC;AAED,KAAK,UAAU,KAAK,CAClB,OAAsB,EACtB,IAAqC;IAErC,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,CAAC;IAC7C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE,eAAe,CAAC,CAAC;QACnD,OAAO;IACT,CAAC;IAED,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACnC,MAAM,YAAY,GAAG,yBAAyB,CAAC,GAAG,CAAC,CAAC;IACpD,MAAM,MAAM,GAAG,YAAY,EAAE,EAAE,CAAC;IAChC,MAAM,IAAI,GAA8B,EAAE,CAAC;IAE3C,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;QACpF,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QACtD,MAAM,KAAK,GACT,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QAChE,MAAM,MAAM,GAAG,QAAQ,GAAG,CAAC,CAAC;QAC5B,MAAM,IAAI,GAAG,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC;QAC7B,MAAM,GAAG,GAAG;YACV,IAAI;YACJ,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,KAAK;YACL,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,UAAU,EAAE,CAAC,CAAC,UAAU;YACxB,QAAQ;YACR,MAAM;SACP,CAAC;QACF,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEf,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,MAAM,EAAE,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7D,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,OAAO,QAAQ,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;YACvD,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;YACvC,OAAO,CAAC,GAAG,CACT,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAC7J,CAAC;YACF,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,MAAM,EAAE,CAAC;gBAC5B,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;gBACxD,KAAK,MAAM,IAAI,IAAI,KAAK;oBAAE,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;YACrE,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,IAAI,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;IAC7E,CAAC;SAAM,IAAI,MAAM,EAAE,CAAC;QAClB,OAAO,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;IAC7D,CAAC;AACH,CAAC;AAED,KAAK,UAAU,OAAO,CACpB,OAAsB,EACtB,IAAoD;IAEpD,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAC/C,MAAM,QAAQ,GAAG,yBAAyB,CAAC,GAAG,CAAC,CAAC;IAChD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,EAAE,8CAA8C,GAAG,EAAE,CAAC,CAAC;QACpG,OAAO;IACT,CAAC;IACD,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,GAAG,QAAQ,CAAC;IACnC,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAEpD,MAAM,IAAI,GAAG;QACX,OAAO;QACP,iBAAiB,EAAE,SAAS;QAC5B,KAAK;QACL,QAAQ;QACR,MAAM,EAAE,QAAQ,GAAG,CAAC;KACrB,CAAC;IAEF,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,MAAM,GAAG,GAA4B,EAAE,GAAG,IAAI,EAAE,CAAC;QACjD,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;YACnC,GAAG,CAAC,IAAI,GAAG,MAAM,SAAS,CAAC,OAAO,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QACtD,CAAC;QACD,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QACpB,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,KAAK,EAAE,GAAG,CAAC,CAAC;IACvC,OAAO,CAAC,GAAG,CAAC,YAAY,SAAS,EAAE,CAAC,CAAC;IACrC,OAAO,CAAC,GAAG,CAAC,UAAU,OAAO,CAAC,MAAM,UAAU,KAAK,UAAU,OAAO,CAAC,SAAS,IAAI,GAAG,QAAQ,QAAQ,EAAE,CAAC,CAAC;IACzG,IAAI,OAAO,CAAC,UAAU;QAAE,OAAO,CAAC,GAAG,CAAC,OAAO,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IAEjE,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC;QAAE,OAAO;IAE5B,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;QACnB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACnB,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;QACrC,OAAO;IACT,CAAC;IAED,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACnB,OAAO,CAAC,GAAG,CAAC,wCAAwC,IAAI,CAAC,KAAK,sBAAsB,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IACzG,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;IAED,MAAM,SAAS,CAAC,OAAO,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAC/C,CAAC;AAED,KAAK,UAAU,OAAO,CACpB,OAAsB,EACtB,KAAa,EACb,IAAsC;IAEtC,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,CAAC;IAC7C,MAAM,EAAE,GAAG,gBAAgB,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IACpD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,IAAI,CACF,IAAI,EACJ,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC,OAAO,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,EACtE,EAAE,CACH,CAAC;QACF,OAAO;IACT,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC,IAAI,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAC,CAAC;IACzD,MAAM,SAAS,CAAC,OAAO,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,cAAc,CAAC,CAAY,EAAE,OAAe;IACnD,IAAI,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;QACpC,MAAM,SAAS,GAAG,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC;QACjD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACzC,MAAM,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YACzC,IAAI,iBAAiB,CAAC,CAAC,CAAC;gBAAE,OAAO,CAAC,GAAG,CAAC,KAAK,SAAS,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QAClF,CAAC;IACH,CAAC;IACD,MAAM,GAAG,GAAG,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACtC,IAAI,iBAAiB,CAAC,GAAG,CAAC;QAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,UAAU,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IACjF,IAAI,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;QACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACxC,MAAM,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YACxC,IAAI,iBAAiB,CAAC,CAAC,CAAC;gBAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,UAAU,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QACzF,CAAC;IACH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,OAAO,CACpB,OAAsB,EACtB,KAAa,EACb,OAAe,EACf,IAAuE;IAEvE,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,CAAC;IAC7C,MAAM,EAAE,GAAG,gBAAgB,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,MAAM,GAAG,CAGrB,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE;QAC9C,OAAO;QACP,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACvD,CAAC,CAAC;IAEH,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACzC,UAAU,EAAE,CAAC,CAAC,UAAU;YACxB,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC;YAC/B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,iBAAiB,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC;YAClE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,iBAAiB,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC;SACjE,CAAC,CAAC,CAAC;QACJ,IAAI,CAAC,IAAI,EAAE,EAAE,YAAY,EAAE,MAAM,CAAC,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;QACxE,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,YAAY,aAAa,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IACnF,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QAC/B,IAAI,IAAI,CAAC,OAAO,GAAG,CAAC;YAAE,cAAc,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;aACjD,CAAC;YACJ,MAAM,GAAG,GAAG,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACtC,IAAI,iBAAiB,CAAC,GAAG,CAAC;gBAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,UAAU,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QACnF,CAAC;IACH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,OAAO,CACpB,OAAsB,EACtB,KAAa,EACb,IAAY,EACZ,IAA2E;IAE3E,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,CAAC;IAC7C,MAAM,EAAE,GAAG,gBAAgB,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC9C,IAAI,IAAI,GAAG,IAAI,CAAC;IAChB,IAAI,IAAI,CAAC,MAAM;QAAE,IAAI,IAAI,YAAY,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEzD,MAAM,IAAI,GAAG;QACX,SAAS,EAAE,EAAE;QACb,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,KAAK,EAAE,IAAI,CAAC,MAAM;QAClB,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAC;IAEF,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,uBAAuB,IAAI,CAAC,MAAM,aAAa,OAAO,CAAC,IAAI,YAAY,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAC7G,OAAO;IACT,CAAC;IAED,MAAM,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACjE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,QAAQ,IAAI,CAAC,MAAM,aAAa,OAAO,CAAC,IAAI,YAAY,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;AACnH,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAC9B,OAAO;KACJ,IAAI,CAAC,eAAe,CAAC;KACrB,WAAW,CAAC,uDAAuD,CAAC;KACpE,MAAM,CAAC,QAAQ,EAAE,8BAA8B,CAAC,CAAC;AAEpD,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,2BAA2B,CAAC;KACxC,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;IAC3B,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;IAC9B,MAAM,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC;AACtD,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,IAAI,CAAC;KACb,WAAW,CAAC,mCAAmC,CAAC;KAChD,MAAM,CAAC,gBAAgB,EAAE,mDAAmD,EAAE,GAAG,CAAC;KAClF,MAAM,CAAC,KAAK,EAAE,IAAsB,EAAE,GAAG,EAAE,EAAE;IAC5C,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;IAC9B,MAAM,KAAK,CAAC,OAAO,EAAE;QACnB,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC;QAClC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,IAAI;KAChC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,+CAA+C,CAAC;KAC5D,MAAM,CAAC,iBAAiB,EAAE,gDAAgD,EAAE,IAAI,CAAC;KACjF,MAAM,CAAC,cAAc,EAAE,yCAAyC,CAAC;KACjE,MAAM,CAAC,KAAK,EAAE,IAAqC,EAAE,GAAG,EAAE,EAAE;IAC3D,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;IAC9B,MAAM,OAAO,CAAC,OAAO,EAAE;QACrB,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,EAAE;QACrC,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,IAAI;KAChC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,gBAAgB,CAAC;KACzB,WAAW,CAAC,8CAA8C,CAAC;KAC3D,MAAM,CAAC,iBAAiB,EAAE,YAAY,EAAE,IAAI,CAAC;KAC7C,MAAM,CAAC,KAAK,EAAE,OAAe,EAAE,IAAuB,EAAE,GAAG,EAAE,EAAE;IAC9D,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;IAC9B,MAAM,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE;QAC9B,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,EAAE;QACrC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,IAAI;KAChC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,0BAA0B,CAAC;KACnC,WAAW,CAAC,6BAA6B,CAAC;KAC1C,MAAM,CAAC,iBAAiB,EAAE,aAAa,EAAE,IAAI,CAAC;KAC9C,MAAM,CAAC,cAAc,EAAE,cAAc,EAAE,GAAG,CAAC;KAC3C,MAAM,CAAC,mBAAmB,EAAE,0CAA0C,EAAE,GAAG,CAAC;KAC5E,MAAM,CAAC,KAAK,EAAE,OAAe,EAAE,OAAe,EAAE,IAAwD,EAAE,GAAG,EAAE,EAAE;IAChH,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;IAC9B,MAAM,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE;QACvC,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,EAAE;QACrC,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC;QACtC,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC;QACxC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,IAAI;KAChC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,0BAA0B,CAAC;KACnC,WAAW,CAAC,sDAAsD,CAAC;KACnE,MAAM,CAAC,cAAc,EAAE,mCAAmC,CAAC;KAC3D,MAAM,CAAC,eAAe,EAAE,2CAA2C,CAAC;KACpE,MAAM,CAAC,WAAW,EAAE,iDAAiD,CAAC;KACtE,MAAM,CAAC,KAAK,EAAE,OAAe,EAAE,SAAmB,EAAE,IAA+D,EAAE,GAAG,EAAE,EAAE;IAC3H,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;IAC9B,IAAI,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QAClB,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC1G,CAAC;IACD,MAAM,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE;QACpC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM;QACrB,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO;QACvB,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM;QACrB,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,IAAI;KAChC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IACtD,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC7D,OAAO,CAAC,KAAK,CAAC,kBAAkB,GAAG,EAAE,CAAC,CAAC;IACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function cleanTerminalLine(text: string): string;
2
+ export declare function isDisplayableLine(text: string): boolean;
3
+ export declare function formatLogLines(rawLines: string[]): string[];
@@ -0,0 +1,14 @@
1
+ /** Strip ANSI CSI/SGR and OSC sequences; drop non-printable controls. */
2
+ const ANSI_RE = /\x1b\[[0-9;?]*[a-zA-Z]/g;
3
+ const OSC_RE = /\x1b\][^\x07]*(?:\x07|\x1b\\)/g;
4
+ const CONTROL_RE = /[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g;
5
+ export function cleanTerminalLine(text) {
6
+ return text.replace(OSC_RE, '').replace(ANSI_RE, '').replace(CONTROL_RE, '').trimEnd();
7
+ }
8
+ export function isDisplayableLine(text) {
9
+ return cleanTerminalLine(text).trim().length > 0;
10
+ }
11
+ export function formatLogLines(rawLines) {
12
+ return rawLines.map(cleanTerminalLine).filter(isDisplayableLine);
13
+ }
14
+ //# sourceMappingURL=harness-format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness-format.js","sourceRoot":"","sources":["../src/harness-format.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,MAAM,OAAO,GAAG,yBAAyB,CAAC;AAC1C,MAAM,MAAM,GAAG,gCAAgC,CAAC;AAChD,MAAM,UAAU,GAAG,mCAAmC,CAAC;AAEvD,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;AACzF,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,iBAAiB,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,QAAkB;IAC/C,OAAO,QAAQ,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;AACnE,CAAC"}
@@ -0,0 +1,16 @@
1
+ export interface HarnessInstallResult {
2
+ wrapperPath: string;
3
+ cliPath: string;
4
+ binDir: string;
5
+ }
6
+ /** Deploy ftown-harness wrapper under ~/.ftown/bin (idempotent). */
7
+ export declare function installHarness(harnessCliPath: string): HarnessInstallResult;
8
+ export declare function harnessOnPath(): boolean;
9
+ export declare function pathHint(): string;
10
+ /** Agent-facing cheat sheet — rewritten on every bridge start. */
11
+ export declare function writeHarnessAgentGuide(opts: {
12
+ wrapperPath: string;
13
+ port: number;
14
+ bridgeId?: string;
15
+ }): void;
16
+ export declare function agentGuidePath(): string;
@@ -0,0 +1,108 @@
1
+ import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { homedir } from 'node:os';
4
+ const FTOWN_DIR = join(homedir(), '.ftown');
5
+ const BIN_DIR = join(FTOWN_DIR, 'bin');
6
+ const HARNESS_WRAPPER = join(BIN_DIR, 'ftown-harness');
7
+ const HARNESS_CLI_PATH_FILE = join(FTOWN_DIR, 'harness-cli.path');
8
+ const WRAPPER_SCRIPT = `#!/usr/bin/env bash
9
+ # Auto-deployed by ftown-bridge — do not edit
10
+ set -euo pipefail
11
+ CLI_PATH_FILE="${HARNESS_CLI_PATH_FILE.replace(/\\/g, '\\\\')}"
12
+ if [[ ! -f "$CLI_PATH_FILE" ]]; then
13
+ echo "ftown-harness: bridge not running (missing $CLI_PATH_FILE)" >&2
14
+ exit 1
15
+ fi
16
+ CLI="$(cat "$CLI_PATH_FILE")"
17
+ if [[ ! -f "$CLI" ]]; then
18
+ echo "ftown-harness: harness CLI missing at $CLI — restart ftown-bridge" >&2
19
+ exit 1
20
+ fi
21
+ exec node "$CLI" "$@"
22
+ `;
23
+ /** Deploy ftown-harness wrapper under ~/.ftown/bin (idempotent). */
24
+ export function installHarness(harnessCliPath) {
25
+ const cliPath = harnessCliPath;
26
+ mkdirSync(BIN_DIR, { recursive: true, mode: 0o700 });
27
+ writeFileSync(HARNESS_CLI_PATH_FILE, cliPath + '\n', { mode: 0o600 });
28
+ writeFileSync(HARNESS_WRAPPER, WRAPPER_SCRIPT, { mode: 0o755 });
29
+ return {
30
+ wrapperPath: HARNESS_WRAPPER,
31
+ cliPath,
32
+ binDir: BIN_DIR,
33
+ };
34
+ }
35
+ export function harnessOnPath() {
36
+ const pathEnv = process.env.PATH ?? '';
37
+ return pathEnv.split(':').some((p) => p === BIN_DIR || p === join(FTOWN_DIR, 'bin'));
38
+ }
39
+ export function pathHint() {
40
+ return existsSync(HARNESS_WRAPPER)
41
+ ? `Add to PATH: export PATH="${BIN_DIR}:$PATH"`
42
+ : '';
43
+ }
44
+ const AGENT_GUIDE = join(FTOWN_DIR, 'harness-agent.md');
45
+ /** Agent-facing cheat sheet — rewritten on every bridge start. */
46
+ export function writeHarnessAgentGuide(opts) {
47
+ const h = opts.wrapperPath;
48
+ const body = `# ftown bridge harness (auto-generated)
49
+
50
+ Bridge is running. Use the harness CLI — **do not** use curl, lsof, or raw HTTP for the local bridge API.
51
+
52
+ ## Command
53
+
54
+ \`\`\`bash
55
+ ${h} <subcommand>
56
+ \`\`\`
57
+
58
+ Wrapper path is stable; bridge port/token live in \`~/.ftown/bridge.json\` (current port: ${opts.port}).
59
+
60
+ ## Default workflow (run in order)
61
+
62
+ \`\`\`bash
63
+ ${h} status # bridge up?
64
+ ${h} here -n 25 # workspace session + tail (works when process dead if log exists)
65
+ ${h} ls --tail 3 # all sessions; log=N lines; preview dead sessions too
66
+ ${h} grep <name> "error|FAIL" -C 2
67
+ \`\`\`
68
+
69
+ ## Subcommands
70
+
71
+ | Subcommand | Example |
72
+ |------------|---------|
73
+ | \`status\` | \`${h} status\` |
74
+ | \`ls\` | \`${h} ls --tail 3\` |
75
+ | \`here\` | \`${h} here -n 30\` — walks up from cwd to find workspace |
76
+ | \`tail\` | \`${h} tail ftown -n 40\` |
77
+ | \`grep\` | \`${h} grep legbi "pattern" -C 2\` |
78
+ | \`send\` | \`${h} send ftown "text" -s --dry-run\` first; **only if user asked** |
79
+ | \`--json\` | \`${h} --json ls\` — machine-readable output |
80
+
81
+ ## Session names
82
+
83
+ Resolve by exact name → unique substring → id prefix. Ambiguous names print choices.
84
+
85
+ ## Submit keys (\`-s\`)
86
+
87
+ - \`cursor\` / \`claude\`: Escape+Enter (\`\\x1b\\r\`)
88
+ - \`shell\`: Enter (\`\\r\`)
89
+
90
+ ## Registry
91
+
92
+ \`~/.ftown/session-registry.json\` maps workspace roots → session id. \`here\` uses it.
93
+
94
+ ## When bridge is down
95
+
96
+ \`${h}\` exits with a clear error. Start bridge from ftown UI → CLI Token → \`npx ftown-bridge --token ... --api-url ...\`
97
+
98
+ ## context-mode
99
+
100
+ Allowed Bash: \`${h}\` subcommands (short output). Do not use curl/wget/fetch to \`127.0.0.1\` for bridge API.
101
+ `;
102
+ mkdirSync(FTOWN_DIR, { recursive: true, mode: 0o700 });
103
+ writeFileSync(AGENT_GUIDE, body, { mode: 0o600 });
104
+ }
105
+ export function agentGuidePath() {
106
+ return AGENT_GUIDE;
107
+ }
108
+ //# sourceMappingURL=harness-installer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness-installer.js","sourceRoot":"","sources":["../src/harness-installer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;AAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;AACvC,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;AACvD,MAAM,qBAAqB,GAAG,IAAI,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;AAElE,MAAM,cAAc,GAAG;;;iBAGN,qBAAqB,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC;;;;;;;;;;;CAW5D,CAAC;AAQF,oEAAoE;AACpE,MAAM,UAAU,cAAc,CAAC,cAAsB;IACnD,MAAM,OAAO,GAAG,cAAc,CAAC;IAE/B,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACrD,aAAa,CAAC,qBAAqB,EAAE,OAAO,GAAG,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACtE,aAAa,CAAC,eAAe,EAAE,cAAc,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAEhE,OAAO;QACL,WAAW,EAAE,eAAe;QAC5B,OAAO;QACP,MAAM,EAAE,OAAO;KAChB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;IACvC,OAAO,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,OAAO,IAAI,CAAC,KAAK,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;AACvF,CAAC;AAED,MAAM,UAAU,QAAQ;IACtB,OAAO,UAAU,CAAC,eAAe,CAAC;QAChC,CAAC,CAAC,6BAA6B,OAAO,SAAS;QAC/C,CAAC,CAAC,EAAE,CAAC;AACT,CAAC;AAED,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;AAExD,kEAAkE;AAClE,MAAM,UAAU,sBAAsB,CAAC,IAItC;IACC,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC;IAC3B,MAAM,IAAI,GAAG;;;;;;;EAOb,CAAC;;;4FAGyF,IAAI,CAAC,IAAI;;;;;EAKnG,CAAC;EACD,CAAC;EACD,CAAC;EACD,CAAC;;;;;;;mBAOgB,CAAC;eACL,CAAC;iBACC,CAAC;iBACD,CAAC;iBACD,CAAC;iBACD,CAAC;mBACC,CAAC;;;;;;;;;;;;;;;;;IAiBhB,CAAC;;;;kBAIa,CAAC;CAClB,CAAC;IACA,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACvD,aAAa,CAAC,WAAW,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,WAAW,CAAC;AACrB,CAAC"}
@@ -2,7 +2,7 @@ import { existsSync, readFileSync, renameSync, writeFileSync, mkdirSync } from '
2
2
  import { join, dirname } from 'node:path';
3
3
  import { homedir } from 'node:os';
4
4
  const HOOK_EVENTS = ['Notification', 'Stop', 'PreToolUse', 'PostToolUse', 'UserPromptSubmit'];
5
- const NOTIFY_SUFFIX = '/hooks/notify.sh';
5
+ import { isFtownNotifyCommand } from './install-notify-script.js';
6
6
  function isObject(value) {
7
7
  return typeof value === 'object' && value !== null && !Array.isArray(value);
8
8
  }
@@ -60,7 +60,7 @@ export function installClaudeHooks(notifyScriptPath) {
60
60
  continue;
61
61
  for (let j = 0; j < inner.length; j++) {
62
62
  const h = inner[j];
63
- if (isObject(h) && typeof h.command === 'string' && h.command.endsWith(NOTIFY_SUFFIX)) {
63
+ if (isObject(h) && typeof h.command === 'string' && isFtownNotifyCommand(h.command)) {
64
64
  foundIndex = i;
65
65
  foundHookIndex = j;
66
66
  break;
@@ -1 +1 @@
1
- {"version":3,"file":"hook-installer.js","sourceRoot":"","sources":["../src/hook-installer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hook-installer.js","sourceRoot":"","sources":["../src/hook-installer.ts"],"names":[],"mappings":"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"}