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.
- package/dist/cli-client.d.ts +17 -0
- package/dist/cli-client.js +76 -0
- package/dist/cli-client.js.map +1 -0
- package/dist/cli-entry.d.ts +2 -0
- package/dist/cli-entry.js +22 -0
- package/dist/cli-entry.js.map +1 -0
- package/dist/codex-installer.d.ts +1 -1
- package/dist/codex-installer.js +7 -6
- package/dist/codex-installer.js.map +1 -1
- package/dist/command-rpc.js +0 -1
- package/dist/command-rpc.js.map +1 -1
- package/dist/create-ftown-session.d.ts +1 -6
- package/dist/create-ftown-session.js +3 -25
- package/dist/create-ftown-session.js.map +1 -1
- package/dist/cursor-hook-installer.d.ts +1 -1
- package/dist/cursor-hook-installer.js +6 -5
- package/dist/cursor-hook-installer.js.map +1 -1
- package/dist/ensure-ftown-path.js +1 -1
- package/dist/env-commands.d.ts +32 -0
- package/dist/env-commands.js +162 -0
- package/dist/env-commands.js.map +1 -0
- package/dist/ftown-cli.d.ts +2 -6
- package/dist/ftown-cli.js +25 -79
- package/dist/ftown-cli.js.map +1 -1
- package/dist/ftown-env-cli.d.ts +2 -31
- package/dist/ftown-env-cli.js +7 -176
- package/dist/ftown-env-cli.js.map +1 -1
- package/dist/ftown-home.d.ts +24 -10
- package/dist/ftown-home.js +19 -41
- package/dist/ftown-home.js.map +1 -1
- package/dist/ftown-sessions-cli.d.ts +1 -1
- package/dist/ftown-sessions-cli.js +6 -499
- package/dist/ftown-sessions-cli.js.map +1 -1
- package/dist/harness-cli.d.ts +1 -1
- package/dist/harness-cli.js +6 -626
- package/dist/harness-cli.js.map +1 -1
- package/dist/harness-commands.d.ts +2 -0
- package/dist/harness-commands.js +576 -0
- package/dist/harness-commands.js.map +1 -0
- package/dist/harness-installer.d.ts +1 -10
- package/dist/harness-installer.js +13 -166
- package/dist/harness-installer.js.map +1 -1
- package/dist/harness-registry.d.ts +1 -27
- package/dist/harness-registry.js +1 -20
- package/dist/harness-registry.js.map +1 -1
- package/dist/hook-installer.d.ts +1 -1
- package/dist/hook-installer.js +5 -4
- package/dist/hook-installer.js.map +1 -1
- package/dist/index.js +10 -108
- package/dist/index.js.map +1 -1
- package/dist/install-ftown-command-cli.d.ts +3 -3
- package/dist/install-ftown-command-cli.js +67 -22
- package/dist/install-ftown-command-cli.js.map +1 -1
- package/dist/install-ftown-skill.d.ts +6 -0
- package/dist/install-ftown-skill.js +111 -10
- package/dist/install-ftown-skill.js.map +1 -1
- package/dist/install-notify-script.d.ts +1 -1
- package/dist/install-notify-script.js +7 -6
- package/dist/install-notify-script.js.map +1 -1
- package/dist/mail-delivery.d.ts +1 -1
- package/dist/mail-delivery.js +3 -5
- package/dist/mail-delivery.js.map +1 -1
- package/dist/mcp/server.js +1 -1
- package/dist/mcp/server.js.map +1 -1
- package/dist/muse-plugin-installer.js +4 -0
- package/dist/muse-plugin-installer.js.map +1 -1
- package/dist/opencode-plugin-installer.d.ts +1 -2
- package/dist/opencode-plugin-installer.js +1 -2
- package/dist/opencode-plugin-installer.js.map +1 -1
- package/dist/provider-env-store.js +1 -1
- package/dist/provider-env-store.js.map +1 -1
- package/dist/retired-skill-assets.d.ts +3 -0
- package/dist/retired-skill-assets.js +11 -0
- package/dist/retired-skill-assets.js.map +1 -1
- package/dist/sessions-commands.d.ts +2 -0
- package/dist/sessions-commands.js +445 -0
- package/dist/sessions-commands.js.map +1 -0
- package/dist/setup-migrations.d.ts +6 -0
- package/dist/setup-migrations.js +28 -0
- package/dist/setup-migrations.js.map +1 -0
- package/dist/setup-state.d.ts +16 -0
- package/dist/setup-state.js +163 -0
- package/dist/setup-state.js.map +1 -0
- package/dist/setup.d.ts +25 -0
- package/dist/setup.js +120 -0
- package/dist/setup.js.map +1 -0
- package/dist/types.d.ts +1 -0
- package/dist/wire-types.js +1 -8
- package/dist/wire-types.js.map +1 -1
- package/package.json +2 -3
- package/pi-extension/API.md +4 -0
- package/pi-extension/ftown.js +1 -2
- package/skills/ftown/SKILL.md +71 -19
- package/skills/ftown/references/orchestrator.md +23 -99
- package/skills/ftown/references/sessions.md +37 -42
- package/dist/claude-trust.d.ts +0 -11
- package/dist/claude-trust.js +0 -47
- package/dist/claude-trust.js.map +0 -1
- package/dist/install-ftown-cli.d.ts +0 -3
- package/dist/install-ftown-cli.js +0 -29
- package/dist/install-ftown-cli.js.map +0 -1
- package/dist/install-ftown-env-cli.d.ts +0 -3
- package/dist/install-ftown-env-cli.js +0 -30
- package/dist/install-ftown-env-cli.js.map +0 -1
- package/dist/install-ftown-workflows-cli.d.ts +0 -3
- package/dist/install-ftown-workflows-cli.js +0 -33
- package/dist/install-ftown-workflows-cli.js.map +0 -1
- package/dist/workflow-runner-cli.d.ts +0 -2
- package/dist/workflow-runner-cli.js +0 -376
- package/dist/workflow-runner-cli.js.map +0 -1
- package/dist/workflow-runner.d.ts +0 -163
- package/dist/workflow-runner.js +0 -307
- package/dist/workflow-runner.js.map +0 -1
- package/skills/fticket/SKILL.md +0 -166
- package/skills/ftown/references/workflows.md +0 -470
- 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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"}
|
package/dist/setup.d.ts
ADDED
|
@@ -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;
|
package/dist/wire-types.js
CHANGED
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
//
|
|
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';
|
package/dist/wire-types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wire-types.js","sourceRoot":"","sources":["../src/wire-types.ts"],"names":[],"mappings":"AAAA,
|
|
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.
|
|
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",
|
package/pi-extension/API.md
CHANGED
|
@@ -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.
|
package/pi-extension/ftown.js
CHANGED
|
@@ -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 }
|
package/skills/ftown/SKILL.md
CHANGED
|
@@ -1,33 +1,85 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ftown
|
|
3
3
|
description: >-
|
|
4
|
-
Control ftown
|
|
5
|
-
|
|
6
|
-
|
|
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
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
-
|
|
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.
|