ftown-bridge 0.19.39 → 0.19.41

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 (116) hide show
  1. package/dist/cli-client.d.ts +17 -0
  2. package/dist/cli-client.js +76 -0
  3. package/dist/cli-client.js.map +1 -0
  4. package/dist/cli-entry.d.ts +2 -0
  5. package/dist/cli-entry.js +22 -0
  6. package/dist/cli-entry.js.map +1 -0
  7. package/dist/codex-installer.d.ts +1 -1
  8. package/dist/codex-installer.js +7 -6
  9. package/dist/codex-installer.js.map +1 -1
  10. package/dist/command-rpc.js +0 -1
  11. package/dist/command-rpc.js.map +1 -1
  12. package/dist/create-ftown-session.d.ts +1 -6
  13. package/dist/create-ftown-session.js +3 -25
  14. package/dist/create-ftown-session.js.map +1 -1
  15. package/dist/cursor-hook-installer.d.ts +1 -1
  16. package/dist/cursor-hook-installer.js +6 -5
  17. package/dist/cursor-hook-installer.js.map +1 -1
  18. package/dist/ensure-ftown-path.js +1 -1
  19. package/dist/env-commands.d.ts +32 -0
  20. package/dist/env-commands.js +162 -0
  21. package/dist/env-commands.js.map +1 -0
  22. package/dist/ftown-cli.d.ts +2 -6
  23. package/dist/ftown-cli.js +25 -79
  24. package/dist/ftown-cli.js.map +1 -1
  25. package/dist/ftown-env-cli.d.ts +2 -31
  26. package/dist/ftown-env-cli.js +7 -176
  27. package/dist/ftown-env-cli.js.map +1 -1
  28. package/dist/ftown-home.d.ts +24 -10
  29. package/dist/ftown-home.js +19 -41
  30. package/dist/ftown-home.js.map +1 -1
  31. package/dist/ftown-sessions-cli.d.ts +1 -1
  32. package/dist/ftown-sessions-cli.js +6 -499
  33. package/dist/ftown-sessions-cli.js.map +1 -1
  34. package/dist/harness-cli.d.ts +1 -1
  35. package/dist/harness-cli.js +6 -626
  36. package/dist/harness-cli.js.map +1 -1
  37. package/dist/harness-commands.d.ts +2 -0
  38. package/dist/harness-commands.js +576 -0
  39. package/dist/harness-commands.js.map +1 -0
  40. package/dist/harness-installer.d.ts +1 -10
  41. package/dist/harness-installer.js +13 -166
  42. package/dist/harness-installer.js.map +1 -1
  43. package/dist/harness-registry.d.ts +1 -27
  44. package/dist/harness-registry.js +1 -20
  45. package/dist/harness-registry.js.map +1 -1
  46. package/dist/hook-installer.d.ts +1 -1
  47. package/dist/hook-installer.js +5 -4
  48. package/dist/hook-installer.js.map +1 -1
  49. package/dist/index.js +10 -108
  50. package/dist/index.js.map +1 -1
  51. package/dist/install-ftown-command-cli.d.ts +3 -3
  52. package/dist/install-ftown-command-cli.js +67 -22
  53. package/dist/install-ftown-command-cli.js.map +1 -1
  54. package/dist/install-ftown-skill.d.ts +6 -0
  55. package/dist/install-ftown-skill.js +111 -10
  56. package/dist/install-ftown-skill.js.map +1 -1
  57. package/dist/install-notify-script.d.ts +1 -1
  58. package/dist/install-notify-script.js +7 -6
  59. package/dist/install-notify-script.js.map +1 -1
  60. package/dist/mail-delivery.d.ts +1 -1
  61. package/dist/mail-delivery.js +3 -5
  62. package/dist/mail-delivery.js.map +1 -1
  63. package/dist/mcp/server.js +1 -1
  64. package/dist/mcp/server.js.map +1 -1
  65. package/dist/muse-plugin-installer.js +4 -0
  66. package/dist/muse-plugin-installer.js.map +1 -1
  67. package/dist/opencode-plugin-installer.d.ts +1 -2
  68. package/dist/opencode-plugin-installer.js +1 -2
  69. package/dist/opencode-plugin-installer.js.map +1 -1
  70. package/dist/provider-env-store.js +1 -1
  71. package/dist/provider-env-store.js.map +1 -1
  72. package/dist/retired-skill-assets.d.ts +3 -0
  73. package/dist/retired-skill-assets.js +11 -0
  74. package/dist/retired-skill-assets.js.map +1 -1
  75. package/dist/sessions-commands.d.ts +2 -0
  76. package/dist/sessions-commands.js +445 -0
  77. package/dist/sessions-commands.js.map +1 -0
  78. package/dist/setup-migrations.d.ts +6 -0
  79. package/dist/setup-migrations.js +28 -0
  80. package/dist/setup-migrations.js.map +1 -0
  81. package/dist/setup-state.d.ts +16 -0
  82. package/dist/setup-state.js +163 -0
  83. package/dist/setup-state.js.map +1 -0
  84. package/dist/setup.d.ts +25 -0
  85. package/dist/setup.js +120 -0
  86. package/dist/setup.js.map +1 -0
  87. package/dist/types.d.ts +1 -0
  88. package/dist/wire-types.js +1 -8
  89. package/dist/wire-types.js.map +1 -1
  90. package/package.json +2 -3
  91. package/pi-extension/API.md +4 -0
  92. package/pi-extension/ftown.js +1 -2
  93. package/skills/ftown/SKILL.md +71 -19
  94. package/skills/ftown/references/orchestrator.md +23 -99
  95. package/skills/ftown/references/sessions.md +37 -42
  96. package/dist/claude-trust.d.ts +0 -11
  97. package/dist/claude-trust.js +0 -47
  98. package/dist/claude-trust.js.map +0 -1
  99. package/dist/install-ftown-cli.d.ts +0 -3
  100. package/dist/install-ftown-cli.js +0 -29
  101. package/dist/install-ftown-cli.js.map +0 -1
  102. package/dist/install-ftown-env-cli.d.ts +0 -3
  103. package/dist/install-ftown-env-cli.js +0 -30
  104. package/dist/install-ftown-env-cli.js.map +0 -1
  105. package/dist/install-ftown-workflows-cli.d.ts +0 -3
  106. package/dist/install-ftown-workflows-cli.js +0 -33
  107. package/dist/install-ftown-workflows-cli.js.map +0 -1
  108. package/dist/workflow-runner-cli.d.ts +0 -2
  109. package/dist/workflow-runner-cli.js +0 -376
  110. package/dist/workflow-runner-cli.js.map +0 -1
  111. package/dist/workflow-runner.d.ts +0 -163
  112. package/dist/workflow-runner.js +0 -307
  113. package/dist/workflow-runner.js.map +0 -1
  114. package/skills/fticket/SKILL.md +0 -166
  115. package/skills/ftown/references/workflows.md +0 -470
  116. package/skills/ftown/scripts/example.flow.mjs +0 -170
@@ -0,0 +1,163 @@
1
+ import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, renameSync, writeFileSync, unlinkSync, rmdirSync, rmSync } from 'node:fs';
2
+ import { randomBytes } from 'node:crypto';
3
+ import { CLI_RUNTIME_MODULES } from './install-ftown-command-cli.js';
4
+ import { homedir } from 'node:os';
5
+ import { join } from 'node:path';
6
+ export function setupStatePath(home = homedir()) { return join(home, '.ftown', 'setup-state.json'); }
7
+ export function readSetupState(home = homedir()) {
8
+ try {
9
+ const value = JSON.parse(readFileSync(setupStatePath(home), 'utf8'));
10
+ if (!value || typeof value !== 'object' || Array.isArray(value) || value.schema !== 1 || !Array.isArray(value.completedMigrations) || !value.completedMigrations.every((id) => typeof id === 'string'))
11
+ return { schema: 1, completedMigrations: [] };
12
+ return { schema: 1, ...(typeof value.packageVersion === 'string' ? { packageVersion: value.packageVersion } : {}), completedMigrations: value.completedMigrations };
13
+ }
14
+ catch (error) {
15
+ if (error instanceof SyntaxError || ['ENOENT', 'ENOTDIR'].includes(error.code ?? ''))
16
+ return { schema: 1, completedMigrations: [] };
17
+ throw error;
18
+ }
19
+ }
20
+ export function writeSetupState(state, home = homedir()) {
21
+ const dir = join(home, '.ftown');
22
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
23
+ if (lstatSync(dir).isSymbolicLink() || !lstatSync(dir).isDirectory())
24
+ throw new Error('Setup directory must be a real directory');
25
+ const path = setupStatePath(home);
26
+ if (existsSync(path) && lstatSync(path).isSymbolicLink())
27
+ throw new Error('Setup state must not be a symlink');
28
+ const temporary = `${path}.${process.pid}.tmp`;
29
+ writeFileSync(temporary, JSON.stringify(state, null, 2) + '\n', { mode: 0o600 });
30
+ renameSync(temporary, path);
31
+ }
32
+ export function setupHint(version) {
33
+ return `npm exec --yes --package ftown-bridge@${version} -- ftown setup`;
34
+ }
35
+ export function assertSetupReady(version, home = homedir()) {
36
+ const state = readSetupState(home);
37
+ const missing = REQUIRED_SETUP_ASSETS.some((asset) => {
38
+ try {
39
+ return !lstatSync(join(home, '.ftown', asset)).isFile();
40
+ }
41
+ catch {
42
+ return true;
43
+ }
44
+ });
45
+ if (state.packageVersion !== version || missing) {
46
+ const repair = state.packageVersion === version ? ' --repair' : '';
47
+ throw new Error(`FTown setup is missing, incomplete or outdated. Run: ${setupHint(version)}${repair}`);
48
+ }
49
+ }
50
+ /** Existence/type inventory; startup never repairs or hashes global integrations. */
51
+ export const REQUIRED_SETUP_ASSETS = [
52
+ 'ftown', 'ftown-sessions', 'ftown-env', 'bin/ftown-harness', 'notify.sh',
53
+ 'pi/ftown.js', 'harness-agent.md', 'skills/ftown/SKILL.md',
54
+ 'cli/package.json', 'cli/node_modules/commander/package.json', 'cli/node_modules/commander/index.js',
55
+ 'cli/hooks/notify.sh', 'cli/pi-extension/ftown.js', 'cli/opencode-plugin/ftown.js',
56
+ 'cli/muse-plugin/.muse-plugin/plugin.json', 'cli/skills/ftown/SKILL.md',
57
+ ...CLI_RUNTIME_MODULES.map((name) => `cli/dist/${name}.js`),
58
+ ];
59
+ /** Reject stale npm-cache setup rather than overwrite a newer installed runtime. */
60
+ export function assertSetupVersion(version, installed) {
61
+ if (installed && installed.localeCompare(version, undefined, { numeric: true }) > 0) {
62
+ throw new Error(`Installed FTown ${installed} is newer than ${version}. Run matching setup: ${setupHint(installed)} --repair`);
63
+ }
64
+ }
65
+ /** Atomic nonempty-directory lock. Reclaim only an exact provably dead owner. */
66
+ export function acquireSetupLock(home = homedir()) {
67
+ const parent = join(home, '.ftown');
68
+ mkdirSync(parent, { recursive: true, mode: 0o700 });
69
+ if (lstatSync(parent).isSymbolicLink())
70
+ throw new Error('Setup directory must be real');
71
+ const token = randomBytes(12).toString('hex');
72
+ const owner = `owner-${process.pid}-${token}.json`;
73
+ const candidate = join(parent, `.setup-pending-${process.pid}-${token}`);
74
+ const lock = join(parent, 'setup.lock');
75
+ mkdirSync(candidate, { mode: 0o700 });
76
+ writeFileSync(join(candidate, owner), JSON.stringify({ pid: process.pid, token }), { mode: 0o600 });
77
+ let acquired = false;
78
+ try {
79
+ for (let attempt = 0; attempt < 3; attempt++) {
80
+ try {
81
+ renameSync(candidate, lock);
82
+ acquired = true;
83
+ break;
84
+ }
85
+ catch (error) {
86
+ if (!['EEXIST', 'ENOTEMPTY'].includes(error.code ?? ''))
87
+ throw error;
88
+ const stat = lstatSync(lock);
89
+ if (!stat.isDirectory() || stat.isSymbolicLink())
90
+ throw new Error('Setup lock has an unknown owner; preserved');
91
+ const entries = readdirSync(lock);
92
+ if (entries.length === 0)
93
+ continue; // owner is releasing; never recursively remove a lock
94
+ const match = entries.length === 1 ? /^owner-(\d+)-([a-f0-9]+)\.json$/.exec(entries[0]) : null;
95
+ if (!match)
96
+ throw new Error('Setup lock has an unknown owner; preserved');
97
+ const marker = join(lock, entries[0]);
98
+ let recorded;
99
+ try {
100
+ if (!lstatSync(marker).isFile() || lstatSync(marker).isSymbolicLink())
101
+ throw new Error('unknown marker');
102
+ recorded = JSON.parse(readFileSync(marker, 'utf8'));
103
+ }
104
+ catch {
105
+ throw new Error('Setup lock has an unknown owner; preserved');
106
+ }
107
+ const pid = Number(match[1]);
108
+ if (!recorded || recorded.pid !== pid || recorded.token !== match[2])
109
+ throw new Error('Setup lock has an unknown owner; preserved');
110
+ let dead = false;
111
+ if (Number.isSafeInteger(pid) && pid > 0) {
112
+ try {
113
+ process.kill(pid, 0);
114
+ }
115
+ catch (probe) {
116
+ dead = probe.code === 'ESRCH';
117
+ }
118
+ }
119
+ if (!dead)
120
+ throw new Error(`Another ftown setup owns the lock (pid ${pid}); retry after it finishes`);
121
+ // An active successor uses a different owner filename. Removing this exact
122
+ // dead marker and rmdir of an empty dir cannot displace a successor.
123
+ try {
124
+ unlinkSync(join(lock, entries[0]));
125
+ }
126
+ catch (unlinkError) {
127
+ if (unlinkError.code !== 'ENOENT')
128
+ throw unlinkError;
129
+ }
130
+ try {
131
+ rmdirSync(lock);
132
+ }
133
+ catch (removeError) {
134
+ if (!['ENOENT', 'ENOTEMPTY', 'EEXIST'].includes(removeError.code ?? ''))
135
+ throw removeError;
136
+ }
137
+ }
138
+ }
139
+ if (!acquired)
140
+ throw new Error('Setup lock changed; retry after the other setup finishes');
141
+ return () => {
142
+ try {
143
+ unlinkSync(join(lock, owner));
144
+ }
145
+ catch (error) {
146
+ if (error.code !== 'ENOENT')
147
+ throw error;
148
+ }
149
+ try {
150
+ rmdirSync(lock);
151
+ }
152
+ catch (error) {
153
+ if (!['ENOENT', 'ENOTEMPTY', 'EEXIST'].includes(error.code ?? ''))
154
+ throw error;
155
+ }
156
+ };
157
+ }
158
+ finally {
159
+ if (!acquired)
160
+ rmSync(candidate, { recursive: true, force: true });
161
+ }
162
+ }
163
+ //# sourceMappingURL=setup-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup-state.js","sourceRoot":"","sources":["../src/setup-state.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ export interface IntegrationResult {
2
+ name: string;
3
+ status: 'installed' | 'skipped';
4
+ detail?: string;
5
+ }
6
+ export interface SetupDependencies {
7
+ installRuntime: (packageRoot: string) => void;
8
+ integrations: (runtimeRoot: string) => Promise<IntegrationResult[]>;
9
+ skillAndPath: (runtimeRoot: string) => void;
10
+ migrate: (repair: boolean) => string[];
11
+ }
12
+ export interface SetupResult {
13
+ version: string;
14
+ action: 'installed' | 'current';
15
+ migrations: string[];
16
+ integrations: IntegrationResult[];
17
+ }
18
+ export declare function packageRoot(): string;
19
+ export declare function packageVersion(root?: string): string;
20
+ export declare function performSetup(options?: {
21
+ root?: string;
22
+ repair?: boolean;
23
+ dependencies?: SetupDependencies;
24
+ }): Promise<SetupResult>;
25
+ export declare function runSetup(argv: string[]): Promise<number>;
package/dist/setup.js ADDED
@@ -0,0 +1,120 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { homedir } from 'node:os';
3
+ import { dirname, join, resolve } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { installFtownCommandCli } from './install-ftown-command-cli.js';
6
+ import { installNotifyScript } from './install-notify-script.js';
7
+ import { installPiExtension } from './pi-extension-installer.js';
8
+ import { installClaudeHooks } from './hook-installer.js';
9
+ import { installCursorHooks } from './cursor-hook-installer.js';
10
+ import { codexBinaryAvailable, ensureCodexHooks } from './codex-installer.js';
11
+ import { opencodeBinaryAvailable, installOpencodePlugin } from './opencode-plugin-installer.js';
12
+ import { ensureMusePlugin } from './muse-plugin-installer.js';
13
+ import { installFtownSkill } from './install-ftown-skill.js';
14
+ import { writeHarnessAgentGuide } from './harness-installer.js';
15
+ import { ensureFtownOnPath } from './ensure-ftown-path.js';
16
+ import { readSetupState, writeSetupState, assertSetupReady, acquireSetupLock, assertSetupVersion } from './setup-state.js';
17
+ import { runSetupMigrations } from './setup-migrations.js';
18
+ export function packageRoot() { return resolve(dirname(fileURLToPath(import.meta.url)), '..'); }
19
+ export function packageVersion(root = packageRoot()) {
20
+ return JSON.parse(readFileSync(join(root, 'package.json'), 'utf8')).version;
21
+ }
22
+ async function installIntegrations(root) {
23
+ const notify = installNotifyScript(join(root, 'hooks', 'notify.sh'));
24
+ installPiExtension(join(root, 'pi-extension', 'ftown.js'));
25
+ if (!installClaudeHooks(notify))
26
+ throw new Error('Claude hook setup failed; fix settings.json and rerun ftown setup --repair');
27
+ if (!installCursorHooks(notify))
28
+ throw new Error('Cursor hook setup failed; fix hooks.json and rerun ftown setup --repair');
29
+ const results = [{ name: 'claude/cursor/pi', status: 'installed' }];
30
+ if (await codexBinaryAvailable()) {
31
+ if (!ensureCodexHooks(join(homedir(), '.ftown', 'bin', 'ftown-harness'), notify))
32
+ throw new Error('Codex hook setup failed; fix hooks.json and rerun ftown setup --repair');
33
+ results.push({ name: 'codex', status: 'installed' });
34
+ }
35
+ else
36
+ results.push({ name: 'codex', status: 'skipped', detail: 'binary not installed' });
37
+ if (await opencodeBinaryAvailable()) {
38
+ installOpencodePlugin(join(root, 'opencode-plugin', 'ftown.js'));
39
+ results.push({ name: 'opencode', status: 'installed' });
40
+ }
41
+ else
42
+ results.push({ name: 'opencode', status: 'skipped', detail: 'binary not installed' });
43
+ const muse = await ensureMusePlugin(join(root, 'muse-plugin'));
44
+ if (muse.action === 'skipped')
45
+ results.push({ name: 'muse', status: 'skipped', detail: muse.warning ?? 'binary not installed' });
46
+ else {
47
+ if (muse.action === 'failed' || !muse.approved || muse.warning)
48
+ throw new Error(muse.warning ?? 'Muse plugin setup failed; rerun ftown setup --repair');
49
+ results.push({ name: 'muse', status: 'installed' });
50
+ }
51
+ return results;
52
+ }
53
+ function defaultDependencies() {
54
+ return {
55
+ installRuntime: (root) => { installFtownCommandCli(root); },
56
+ integrations: installIntegrations,
57
+ skillAndPath: (root) => {
58
+ installFtownSkill('ftown', join(root, 'skills', 'ftown'));
59
+ writeHarnessAgentGuide({ wrapperPath: join(homedir(), '.ftown', 'bin', 'ftown-harness') });
60
+ ensureFtownOnPath();
61
+ },
62
+ migrate: (repair) => runSetupMigrations(repair),
63
+ };
64
+ }
65
+ export async function performSetup(options = {}) {
66
+ const root = options.root ?? packageRoot();
67
+ const version = packageVersion(root);
68
+ const release = acquireSetupLock();
69
+ try {
70
+ const state = readSetupState();
71
+ let installedVersion = state.packageVersion;
72
+ try {
73
+ installedVersion = packageVersion(join(homedir(), '.ftown', 'cli'));
74
+ }
75
+ catch { /* Fresh runtime; durable ready version still applies. */ }
76
+ assertSetupVersion(version, state.packageVersion);
77
+ assertSetupVersion(version, installedVersion);
78
+ if (!options.repair && state.packageVersion === version) {
79
+ // Explicit repair is the recovery path for missing assets or new integrations.
80
+ assertSetupReady(version);
81
+ return { version, action: 'current', migrations: [], integrations: [] };
82
+ }
83
+ const deps = options.dependencies ?? defaultDependencies();
84
+ // Invalidate readiness BEFORE changing any integration; a failure remains retryable.
85
+ writeSetupState({ schema: 1, completedMigrations: state.completedMigrations });
86
+ const migrations = deps.migrate(!!options.repair);
87
+ deps.installRuntime(root);
88
+ const installedRoot = join(homedir(), '.ftown', 'cli');
89
+ const integrations = await deps.integrations(installedRoot);
90
+ deps.skillAndPath(installedRoot);
91
+ writeSetupState({ ...readSetupState(), packageVersion: version });
92
+ return { version, action: 'installed', migrations, integrations };
93
+ }
94
+ finally {
95
+ release();
96
+ }
97
+ }
98
+ export async function runSetup(argv) {
99
+ if (argv.includes('--help') || argv.includes('-h')) {
100
+ console.log('Usage: ftown setup [--repair]\nInstall or upgrade local runtime, integrations, skill and PATH. --repair rechecks current setup and cleanup.');
101
+ return 0;
102
+ }
103
+ if (argv.some((arg) => arg !== '--repair')) {
104
+ console.error('Usage: ftown setup [--repair]');
105
+ return 1;
106
+ }
107
+ try {
108
+ const result = await performSetup({ repair: argv.includes('--repair') });
109
+ console.log(`ftown setup ${result.version}: ${result.action}`);
110
+ for (const integration of result.integrations)
111
+ console.log(` ${integration.name}: ${integration.status}${integration.detail ? ` (${integration.detail})` : ''}`);
112
+ console.log('Open a new shell for PATH changes; start ftown-bridge when ready.');
113
+ return 0;
114
+ }
115
+ catch (error) {
116
+ console.error(`ftown setup: ${error instanceof Error ? error.message : String(error)}`);
117
+ return 1;
118
+ }
119
+ }
120
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -99,6 +99,7 @@ export interface CreateSessionPayload {
99
99
  opencodeSessionId?: string;
100
100
  museSessionId?: string;
101
101
  parentSessionId?: string;
102
+ /** @deprecated Ignored compatibility input. Ordinary sessions use task + parent. */
102
103
  orchestrator?: boolean;
103
104
  suppressBriefing?: boolean;
104
105
  createMissingWorkingDir?: boolean;
@@ -1,11 +1,4 @@
1
- // No imports beyond Node builtins — this file must stay dependency-free so compiled
2
- // sibling copies work standalone when this file is copied alongside harness-cli.js
3
- // and ftown-sessions-cli.js into ~/.ftown (see harness-installer.ts / install-ftown-cli.ts).
4
- //
5
- // This module holds the wire shapes shared by the standalone CLIs (harness-cli.ts,
6
- // ftown-sessions-cli.ts) that talk to LocalApiServer over ~/.ftown/bridge.json. These
7
- // are the shapes as seen over the wire by those CLIs — not necessarily identical to the
8
- // richer internal types in ./types.ts.
1
+ // Shared wire shapes for the in-process CLI runtime and local bridge API.
9
2
  export const MAIL_TYPES = ['message', 'task', 'result', 'escalation'];
10
3
  export const AUTOMATION_REMOVED_CODE = 'automation_removed';
11
4
  export const AUTOMATION_REMOVED_MESSAGE = 'Recurring loops and factory automation have been removed';
@@ -1 +1 @@
1
- {"version":3,"file":"wire-types.js","sourceRoot":"","sources":["../src/wire-types.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,mFAAmF;AACnF,6FAA6F;AAC7F,EAAE;AACF,mFAAmF;AACnF,sFAAsF;AACtF,wFAAwF;AACxF,uCAAuC;AAwDvC,MAAM,CAAC,MAAM,UAAU,GAAwB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;AAgB3F,MAAM,CAAC,MAAM,uBAAuB,GAAG,oBAA6B,CAAC;AACrE,MAAM,CAAC,MAAM,0BAA0B,GAAG,0DAA0D,CAAC;AAErG;;;;;;;;;;GAUG;AACH,MAAM,UAAU,YAAY,CAAC,UAAmB;IAC9C,OAAO,IAAI,CAAC;AACd,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,iBAAiB,CAAC,CAAc;IAC9C,OAAO,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;AACpE,CAAC"}
1
+ {"version":3,"file":"wire-types.js","sourceRoot":"","sources":["../src/wire-types.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAwD1E,MAAM,CAAC,MAAM,UAAU,GAAwB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;AAgB3F,MAAM,CAAC,MAAM,uBAAuB,GAAG,oBAA6B,CAAC;AACrE,MAAM,CAAC,MAAM,0BAA0B,GAAG,0DAA0D,CAAC;AAErG;;;;;;;;;;GAUG;AACH,MAAM,UAAU,YAAY,CAAC,UAAmB;IAC9C,OAAO,IAAI,CAAC;AACd,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,iBAAiB,CAAC,CAAc;IAC9C,OAAO,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;AACpE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ftown-bridge",
3
- "version": "0.19.39",
3
+ "version": "0.19.41",
4
4
  "description": "CLI bridge for ftown — generic PTY-over-Centrifugo relay",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -10,7 +10,6 @@
10
10
  "ftown-harness": "dist/harness-cli.js",
11
11
  "ftown-env": "dist/ftown-env-cli.js",
12
12
  "ftown-sessions": "bin/ftown-sessions",
13
- "ftown-workflows": "dist/workflow-runner-cli.js",
14
13
  "ftown-mcp": "dist/mcp-cli.js"
15
14
  },
16
15
  "files": [
@@ -23,7 +22,7 @@
23
22
  "skills"
24
23
  ],
25
24
  "scripts": {
26
- "build": "tsc",
25
+ "build": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\" && tsc",
27
26
  "test": "node --import tsx --test \"src/**/*.test.ts\"",
28
27
  "prepublishOnly": "npm run build",
29
28
  "start": "tsx src/index.ts",
@@ -64,3 +64,7 @@ The tool schemas ship with `ftown-bridge` and follow its semantic version. Addin
64
64
  ## Consumer walkthrough
65
65
 
66
66
  An agent can call `ftown_sessions.list`, use the returned session ID with `ftown_sessions.get` or `usage`, and then send context with `ftown_mail.send`. To delegate, it can create a child with `ftown_session_create`, retain the returned ID, inspect its output, and later rename, reparent, stop, remove, or revive it.
67
+
68
+ The ftown extension is installed by explicit `ftown setup`; use
69
+ `ftown setup --repair` after installing a new optional harness. Structured creates
70
+ use ordinary task and parent inputs. Legacy orchestrator booleans are ignored.
@@ -526,7 +526,7 @@ export function registerFtownPiExtension(pi, options = {}) {
526
526
  parent: { type: 'boolean', description: 'Make the current Pi session the parent.' },
527
527
  parentId: { type: 'string', description: 'Explicit ftown parent session id.' },
528
528
  createWorkdir: { type: 'boolean' },
529
- orchestrator: { type: 'boolean' },
529
+ orchestrator: { type: 'boolean', description: 'Deprecated compatibility input; ignored.' },
530
530
  },
531
531
  required: ['prompt'],
532
532
  additionalProperties: false,
@@ -544,7 +544,6 @@ export function registerFtownPiExtension(pi, options = {}) {
544
544
  ? { parentSessionId: params.parentId }
545
545
  : params.parent ? { parentSessionId: true } : {}),
546
546
  ...(params.createWorkdir ? { createMissingWorkingDir: true } : {}),
547
- ...(params.orchestrator ? { orchestrator: true } : {}),
548
547
  };
549
548
  const extraHeaders = ftownSessionId
550
549
  ? { 'x-ftown-session-id': ftownSessionId }
@@ -1,33 +1,85 @@
1
1
  ---
2
2
  name: ftown
3
3
  description: >-
4
- Control ftown from inside agent sessions: create/list/read/drive sibling
5
- sessions, send ftown mail, and coordinate worker agent sessions. Use when a task
6
- mentions ftown, ftown sessions, bridge sessions, child/sibling agents, mail/inbox,
7
- orchestration, or fan-out.
4
+ Control ftown sessions: create/list/read/drive sibling sessions, send ftown
5
+ mail, and coordinate worker agents. Use for ftown sessions, child/sibling
6
+ agents, bridge mail/inbox, or explicitly requested orchestration.
8
7
  ---
9
8
 
10
9
  # ftown
11
10
 
12
- Use the local bridge CLIs installed under `~/.ftown`. They read
13
- `~/.ftown/bridge.json`; anyone who can read that file can control the bridge's
14
- sessions.
11
+ Use `ftown sessions`, `ftown harness`, and `ftown env`. Run `ftown --help`
12
+ for command discovery; if it is missing from PATH, use `~/.ftown/ftown`.
13
+ The bridge installs this skill at `~/.ftown/skills/ftown`, linked from the agent
14
+ skill directories. Startup checks setup readiness and never rewrites global
15
+ integrations. Before the installed command exists, run setup from the package:
15
16
 
16
- ## Pick The Reference
17
+ ```bash
18
+ npm exec --yes --package ftown-bridge -- ftown setup
19
+ ```
20
+
21
+ For upgrades, use the exact new version named by the startup readiness hint:
22
+
23
+ ```bash
24
+ npm exec --yes --package ftown-bridge@<new-version> -- ftown setup
25
+ ```
26
+
27
+ The installed alias uses its copied version and does not discover newer packages.
28
+ Use `ftown setup --repair` to repair that current copied version or detect new
29
+ optional harnesses. If the copied runtime is incomplete, use the matching package
30
+ entrypoint with `--repair`.
31
+
32
+ ## Commands and references
33
+
34
+ ```bash
35
+ ftown sessions list
36
+ ftown sessions create --prompt "Review the auth module" --workdir "$PWD" --parent
37
+ ftown sessions screen <session-id> --limit 200
38
+ ftown harness mail send <session-id> --type task "review the API client"
39
+ ftown harness mail read
40
+ ftown env --help
41
+ ftown setup --help
42
+ ```
43
+
44
+ Read `references/sessions.md` for the session, mail and terminal command
45
+ reference. Read `references/orchestrator.md` for practical worker coordination
46
+ examples. Each command group also has `--help`.
47
+
48
+ ## Identity and reporting
49
+
50
+ Your id is `$FTOWN_SESSION_ID`; children also receive `$FTOWN_PARENT_SESSION_ID`.
51
+ A child's initial briefing identifies it and its parent and explains reporting:
52
+
53
+ ```bash
54
+ ftown harness mail send --parent --type result "Done; checks passed"
55
+ ftown harness mail send --parent --type escalation "Blocked: need the API contract"
56
+ ```
57
+
58
+ Mail arrives as `[ftown mail]` context through harness hooks/extensions where
59
+ available. Cursor and shell sessions receive an idle nudge to read their inbox.
60
+ Prefer mail for agent communication; use terminal key injection only when the
61
+ task needs it. Inspect peers with `ftown sessions list` and
62
+ `ftown sessions screen <id> --limit 100`.
17
63
 
18
- - Session control, mail, terminal output, archive/revive, or local API:
19
- read `references/sessions.md`.
20
- - Ad-hoc multi-agent coordination from an orchestrator session:
21
- read `references/orchestrator.md`.
64
+ ## Cleanup
22
65
 
23
- ## Quick Commands
66
+ Session cleanup is an explicit user or orchestrator action. Reporting a result
67
+ does not remove a child automatically. Keep sessions available for follow-up
68
+ until cleanup is requested or the coordinating task calls for it.
24
69
 
25
70
  ```bash
26
- # Sessions
27
- ~/.ftown/ftown-sessions list
28
- ~/.ftown/ftown-sessions create --prompt "Run tests" --workdir "$PWD" --parent
29
- ~/.ftown/ftown-sessions screen <session-id> --limit 200
30
- ~/.ftown/ftown-sessions tell <session-id> --type task "continue with the API client"
71
+ ftown sessions remove <finished-session-id>
72
+ ftown sessions archive
73
+ ftown sessions revive <archived-session-id>
31
74
  ```
32
75
 
33
- Use orchestrator guidance for ad-hoc multi-agent coordination.
76
+ Removal archives the session; revival creates a new session id and resumes its
77
+ agent conversation when supported. Preserve useful results before cleanup.
78
+
79
+ ## Connection and compatibility
80
+
81
+ The commands read `~/.ftown/bridge.json`. Anyone who can read that file can
82
+ control the bridge's sessions. Existing `ftown-sessions`, `ftown-harness`, and
83
+ `ftown-env` launchers remain compatible; use the grouped commands above in new
84
+ instructions. ftown does not install a ticket system or provide a workflow
85
+ runner. Independently installed coordination tools remain yours to manage.