@forcefield/mcp-server 0.1.4 → 0.1.6
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.
|
@@ -510,7 +510,7 @@ function generateApiKey() {
|
|
|
510
510
|
const prefix = plaintext.slice(0, 12);
|
|
511
511
|
return { plaintext, hash, prefix };
|
|
512
512
|
}
|
|
513
|
-
async function authenticateAccountAndCreateApiKey(email,
|
|
513
|
+
async function authenticateAccountAndCreateApiKey(email, password2, options) {
|
|
514
514
|
const supabaseUrl = getSupabaseUrl(options);
|
|
515
515
|
const anonKey = getAnonKey(supabaseUrl, options);
|
|
516
516
|
const supabase = createClient(supabaseUrl, anonKey, {
|
|
@@ -519,13 +519,18 @@ async function authenticateAccountAndCreateApiKey(email, password, options) {
|
|
|
519
519
|
autoRefreshToken: false
|
|
520
520
|
}
|
|
521
521
|
});
|
|
522
|
-
let signIn = await supabase.auth.signInWithPassword({ email, password });
|
|
522
|
+
let signIn = await supabase.auth.signInWithPassword({ email, password: password2 });
|
|
523
523
|
if (signIn.error || !signIn.data.user) {
|
|
524
|
-
await supabase.auth.signUp({ email, password });
|
|
525
|
-
signIn = await supabase.auth.signInWithPassword({ email, password });
|
|
524
|
+
await supabase.auth.signUp({ email, password: password2 });
|
|
525
|
+
signIn = await supabase.auth.signInWithPassword({ email, password: password2 });
|
|
526
526
|
}
|
|
527
527
|
if (signIn.error || !signIn.data.user) {
|
|
528
528
|
const message = signIn.error?.message ?? "Invalid login credentials";
|
|
529
|
+
if (/email.*not confirmed/i.test(message)) {
|
|
530
|
+
throw new Error(
|
|
531
|
+
"Authentication failed: Email not confirmed. Confirm the inbox for this account, or disable email confirmation in Supabase Auth settings for beta."
|
|
532
|
+
);
|
|
533
|
+
}
|
|
529
534
|
throw new Error(`Authentication failed: ${message}`);
|
|
530
535
|
}
|
|
531
536
|
const userId = signIn.data.user.id;
|
|
@@ -545,7 +550,7 @@ async function authenticateAccountAndCreateApiKey(email, password, options) {
|
|
|
545
550
|
supabaseUrl,
|
|
546
551
|
serviceRoleKey,
|
|
547
552
|
email,
|
|
548
|
-
password,
|
|
553
|
+
password: password2,
|
|
549
554
|
label: options?.label ?? "Setup Wizard Key"
|
|
550
555
|
});
|
|
551
556
|
}
|
|
@@ -558,8 +563,8 @@ async function authenticateAccountAndCreateApiKey(email, password, options) {
|
|
|
558
563
|
email
|
|
559
564
|
};
|
|
560
565
|
}
|
|
561
|
-
async function authenticateLocalAndCreateApiKey(email,
|
|
562
|
-
return authenticateAccountAndCreateApiKey(email,
|
|
566
|
+
async function authenticateLocalAndCreateApiKey(email, password2, options) {
|
|
567
|
+
return authenticateAccountAndCreateApiKey(email, password2, {
|
|
563
568
|
...options,
|
|
564
569
|
localDev: true,
|
|
565
570
|
label: options?.label ?? "Local Setup Key"
|
|
@@ -622,7 +627,7 @@ var WORKFLOW_DIR_CANDIDATES = [
|
|
|
622
627
|
join7(__dirname2, "..", "..", "workflows")
|
|
623
628
|
];
|
|
624
629
|
var CONFIG_FILE = ".forcefield.json";
|
|
625
|
-
var VERSION = "0.1.
|
|
630
|
+
var VERSION = "0.1.6";
|
|
626
631
|
var BANNER_TEXT = "Forcefield";
|
|
627
632
|
var BANNER_FONT = "Rowan Cap";
|
|
628
633
|
var BANNER_MIN_COLUMNS = 80;
|
|
@@ -967,7 +972,10 @@ async function promptMode() {
|
|
|
967
972
|
async function promptApiKey(preArgs) {
|
|
968
973
|
if (preArgs?.localAuth) {
|
|
969
974
|
const preEmail = preArgs.email ?? await promptTextValue("Local test email:", "alice@test.local");
|
|
970
|
-
const prePassword = preArgs.password ?? await
|
|
975
|
+
const prePassword = preArgs.password ?? await promptPasswordValue(
|
|
976
|
+
"Local test password:",
|
|
977
|
+
"Confirm local test password:"
|
|
978
|
+
);
|
|
971
979
|
if (!preEmail || !prePassword) return null;
|
|
972
980
|
try {
|
|
973
981
|
const result = await authenticateLocalAndCreateApiKey(preEmail, prePassword, {
|
|
@@ -1002,10 +1010,13 @@ async function promptApiKey(preArgs) {
|
|
|
1002
1010
|
}
|
|
1003
1011
|
if (method === "account") {
|
|
1004
1012
|
const email = await promptTextValue("Account email:", preArgs?.email ?? "you@company.com");
|
|
1005
|
-
const
|
|
1006
|
-
|
|
1013
|
+
const password2 = preArgs?.password ?? await promptPasswordValue(
|
|
1014
|
+
"Account password:",
|
|
1015
|
+
"Confirm account password:"
|
|
1016
|
+
);
|
|
1017
|
+
if (!email || !password2) return null;
|
|
1007
1018
|
try {
|
|
1008
|
-
const result = await authenticateAccountAndCreateApiKey(email,
|
|
1019
|
+
const result = await authenticateAccountAndCreateApiKey(email, password2, {
|
|
1009
1020
|
label: "Setup Wizard Key",
|
|
1010
1021
|
localDev: localMode
|
|
1011
1022
|
});
|
|
@@ -1018,10 +1029,13 @@ async function promptApiKey(preArgs) {
|
|
|
1018
1029
|
}
|
|
1019
1030
|
if (method === "local") {
|
|
1020
1031
|
const email = await promptTextValue("Local test email:", "alice@test.local");
|
|
1021
|
-
const
|
|
1022
|
-
|
|
1032
|
+
const password2 = await promptPasswordValue(
|
|
1033
|
+
"Local test password:",
|
|
1034
|
+
"Confirm local test password:"
|
|
1035
|
+
);
|
|
1036
|
+
if (!email || !password2) return null;
|
|
1023
1037
|
try {
|
|
1024
|
-
const result = await authenticateLocalAndCreateApiKey(email,
|
|
1038
|
+
const result = await authenticateLocalAndCreateApiKey(email, password2, {
|
|
1025
1039
|
label: "Setup Wizard (Local)"
|
|
1026
1040
|
});
|
|
1027
1041
|
p.log.success(`Created local API key for ${result.email}.`);
|
|
@@ -1077,11 +1091,10 @@ function isLocalSetupMode(preArgs) {
|
|
|
1077
1091
|
return false;
|
|
1078
1092
|
}
|
|
1079
1093
|
}
|
|
1080
|
-
async function promptTextValue(message, placeholder
|
|
1094
|
+
async function promptTextValue(message, placeholder) {
|
|
1081
1095
|
const value = await p.text({
|
|
1082
1096
|
message,
|
|
1083
1097
|
placeholder,
|
|
1084
|
-
...secret ? { placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" } : {},
|
|
1085
1098
|
validate: (input) => {
|
|
1086
1099
|
if (!input) return "This field is required.";
|
|
1087
1100
|
return void 0;
|
|
@@ -1093,6 +1106,39 @@ async function promptTextValue(message, placeholder, secret = false) {
|
|
|
1093
1106
|
}
|
|
1094
1107
|
return value;
|
|
1095
1108
|
}
|
|
1109
|
+
async function promptPasswordValue(message, confirmMessage) {
|
|
1110
|
+
const password2 = await p.password({
|
|
1111
|
+
message,
|
|
1112
|
+
validate: (input) => {
|
|
1113
|
+
if (!input) return "Password is required.";
|
|
1114
|
+
if (input.length < 8) return "Password must be at least 8 characters.";
|
|
1115
|
+
return void 0;
|
|
1116
|
+
}
|
|
1117
|
+
});
|
|
1118
|
+
if (p.isCancel(password2)) {
|
|
1119
|
+
p.cancel("Setup cancelled.");
|
|
1120
|
+
return null;
|
|
1121
|
+
}
|
|
1122
|
+
if (!confirmMessage) {
|
|
1123
|
+
return password2;
|
|
1124
|
+
}
|
|
1125
|
+
const confirm2 = await p.password({
|
|
1126
|
+
message: confirmMessage,
|
|
1127
|
+
validate: (input) => {
|
|
1128
|
+
if (!input) return "Please confirm your password.";
|
|
1129
|
+
return void 0;
|
|
1130
|
+
}
|
|
1131
|
+
});
|
|
1132
|
+
if (p.isCancel(confirm2)) {
|
|
1133
|
+
p.cancel("Setup cancelled.");
|
|
1134
|
+
return null;
|
|
1135
|
+
}
|
|
1136
|
+
if (password2 !== confirm2) {
|
|
1137
|
+
p.log.error("Passwords do not match. Please run setup again.");
|
|
1138
|
+
return null;
|
|
1139
|
+
}
|
|
1140
|
+
return password2;
|
|
1141
|
+
}
|
|
1096
1142
|
async function configure(projectDir, ide, mode, apiKey) {
|
|
1097
1143
|
const adapter = getAdapter(ide);
|
|
1098
1144
|
await adapter.configureMcp(projectDir, apiKey);
|
|
@@ -1226,4 +1272,4 @@ export {
|
|
|
1226
1272
|
parseArgs,
|
|
1227
1273
|
runSetupCli
|
|
1228
1274
|
};
|
|
1229
|
-
//# sourceMappingURL=chunk-
|
|
1275
|
+
//# sourceMappingURL=chunk-PSCW3GLJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../setup/wizard.ts","../setup/ide-detect.ts","../setup/ide-adapters/claude-code.ts","../setup/ide-adapters/mcp-runtime.ts","../setup/ide-adapters/cursor.ts","../setup/ide-adapters/codex.ts","../setup/ide-adapters/windsurf.ts","../setup/ide-adapters/index.ts","../setup/auth.ts","../setup/index.ts"],"sourcesContent":["/**\n * setup/wizard.ts — Interactive setup wizard using @clack/prompts.\n *\n * Orchestrates the full setup flow:\n * 1. Welcome banner\n * 2. Existing setup check\n * 3. IDE detection + selection\n * 4. Mode selection (Core vs Full)\n * 5. Authentication\n * 6. Configure + install\n * 7. Verify + success\n */\n\nimport * as p from '@clack/prompts';\nimport pc from 'picocolors';\nimport figlet from 'figlet';\nimport gradient from 'gradient-string';\nimport { readFile, writeFile, access } from 'node:fs/promises';\nimport { join, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { Ide, SetupMode, SetupConfig, CliArgs } from './types.js';\nimport { detectIde } from './ide-detect.js';\nimport { getAdapter, IDE_CHOICES } from './ide-adapters/index.js';\nimport {\n authenticateAccountAndCreateApiKey,\n authenticateLocalAndCreateApiKey,\n authenticateWithRetry,\n verifyApiKey,\n} from './auth.js';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst WORKFLOW_DIR_CANDIDATES = [\n join(__dirname, '..', 'workflows'),\n join(__dirname, '..', '..', 'workflows'),\n];\nconst CONFIG_FILE = '.forcefield.json';\nconst VERSION = '0.1.6';\nconst BANNER_TEXT = 'Forcefield';\nconst BANNER_FONT = 'Rowan Cap';\nconst BANNER_MIN_COLUMNS = 80;\nconst BANNER_FALLBACK_TEXT = ' Forcefield';\nconst BANNER_SUBTITLE = ' Corporate compliance copilot\\n';\n// rainbow2-like palette cycling red -> violet for the terminal banner\nconst BANNER_GRADIENT_STOPS = ['#ff3b3b', '#ff9f1a', '#ffe74c', '#2ed573', '#1e90ff', '#7d5fff', '#e056fd'];\nconst bannerGradient = gradient(BANNER_GRADIENT_STOPS);\n\nasync function resolveWorkflowsDir(): Promise<string> {\n for (const dir of WORKFLOW_DIR_CANDIDATES) {\n try {\n await access(dir);\n return dir;\n } catch {\n // try next candidate\n }\n }\n throw new Error(\n `Unable to locate workflow templates. Checked: ${WORKFLOW_DIR_CANDIDATES.join(', ')}`,\n );\n}\n\n/**\n * Run the interactive setup wizard.\n */\nexport async function runWizard(projectDir: string, args: CliArgs): Promise<void> {\n // --status: read-only check\n if (args.status) {\n await showStatus(projectDir);\n return;\n }\n\n // --doctor: setup diagnostics\n if (args.doctor) {\n await runDoctor(projectDir, args);\n return;\n }\n\n // Non-interactive mode\n if (args.ide && args.mode && (args.token || args.localAuth || (args.email && args.password))) {\n await runNonInteractive(projectDir, args);\n return;\n }\n\n // Interactive mode\n await runInteractive(projectDir, args);\n}\n\n// === Welcome Banner ===\n\nfunction showBanner(): void {\n const cols = process.stdout.columns || 80;\n\n if (cols >= BANNER_MIN_COLUMNS) {\n try {\n const banner = figlet.textSync(BANNER_TEXT, { font: BANNER_FONT });\n const colored = applyBannerGradient(banner);\n console.log(colored);\n } catch {\n // figlet font not available — use fallback\n console.log(pc.bold(applyBannerGradient(BANNER_FALLBACK_TEXT)));\n }\n } else {\n console.log(pc.bold(applyBannerGradient(BANNER_FALLBACK_TEXT)));\n }\n console.log(pc.dim(BANNER_SUBTITLE));\n}\n\nfunction applyBannerGradient(text: string): string {\n return bannerGradient.multiline(text);\n}\n\n// === Status Check ===\n\nasync function showStatus(projectDir: string): Promise<void> {\n const config = await readConfig(projectDir);\n\n if (!config) {\n console.log(pc.yellow('No Forcefield setup found in this directory.'));\n console.log(`Run ${pc.cyan('forcefield setup')} to get started.`);\n process.exit(1);\n }\n\n console.log(pc.bold('Forcefield Setup Status'));\n console.log(` IDE: ${pc.cyan(config.ide)}`);\n console.log(` Mode: ${pc.cyan(config.mode)}`);\n console.log(` Version: ${pc.cyan(config.version)}`);\n console.log(` Installed: ${pc.dim(config.installed_at)}`);\n}\n\ninterface DoctorCheckResult {\n ok: boolean;\n label: string;\n detail: string;\n}\n\ninterface McpCheckResult {\n ok: boolean;\n filePath: string;\n key?: string;\n detail: string;\n}\n\nasync function runDoctor(projectDir: string, args: CliArgs): Promise<void> {\n console.log(pc.bold('Forcefield Setup Doctor'));\n console.log(pc.dim(`Project: ${projectDir}`));\n\n const checks: DoctorCheckResult[] = [];\n const config = await readConfig(projectDir);\n\n if (!config) {\n checks.push({\n ok: false,\n label: 'Setup config',\n detail: `Missing ${CONFIG_FILE}. Run forcefield setup first.`,\n });\n } else {\n checks.push({\n ok: true,\n label: 'Setup config',\n detail: `${config.ide} / ${config.mode} / v${config.version}`,\n });\n\n const mcp = await inspectMcpConfig(projectDir, config.ide);\n checks.push({\n ok: mcp.ok,\n label: 'MCP config',\n detail: `${mcp.filePath} — ${mcp.detail}`,\n });\n\n if (mcp.key) {\n const verified = await verifyApiKey(mcp.key, { localDev: isLocalSetupMode(args) });\n checks.push({\n ok: verified.valid,\n label: 'API key exchange',\n detail: verified.valid\n ? 'Key exchange succeeded.'\n : (verified.error ?? 'Key exchange failed.'),\n });\n } else {\n checks.push({\n ok: false,\n label: 'API key exchange',\n detail: 'FORCEFIELD_API_KEY not found in MCP config env.',\n });\n }\n }\n\n for (const check of checks) {\n const symbol = check.ok ? pc.green('✓') : pc.red('✗');\n console.log(`${symbol} ${pc.bold(check.label)}: ${check.detail}`);\n }\n\n const failures = checks.filter((check) => !check.ok);\n if (failures.length > 0) {\n console.log('');\n console.log(pc.yellow('Suggested fixes:'));\n console.log(` 1. Re-run ${pc.cyan('forcefield setup')} in this project.`);\n console.log(` 2. Confirm your coding agent shows Forcefield connected (${pc.cyan('/mcp')}).`);\n console.log(` 3. Re-run ${pc.cyan('forcefield doctor')} after setup.`);\n process.exit(1);\n }\n\n console.log('');\n console.log(pc.green('Doctor checks passed. Forcefield should be ready.'));\n}\n\nasync function inspectMcpConfig(projectDir: string, ide: Ide): Promise<McpCheckResult> {\n if (ide === 'claude-code') {\n return inspectJsonMcpConfig(join(projectDir, '.mcp.json'), 'mcpServers');\n }\n\n if (ide === 'cursor') {\n return inspectJsonMcpConfig(join(projectDir, '.cursor', 'mcp.json'), 'mcpServers');\n }\n\n if (ide === 'windsurf') {\n return inspectJsonMcpConfig(join(projectDir, '.windsurf', 'mcp_config.json'), 'mcpServers');\n }\n\n return inspectCodexMcpConfig(join(projectDir, '.codex', 'config.toml'));\n}\n\nasync function inspectJsonMcpConfig(\n filePath: string,\n rootKey: string,\n): Promise<McpCheckResult> {\n let raw = '';\n try {\n raw = await readFile(filePath, 'utf-8');\n } catch {\n return {\n ok: false,\n filePath,\n detail: 'File not found.',\n };\n }\n\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(raw) as Record<string, unknown>;\n } catch {\n return {\n ok: false,\n filePath,\n detail: 'Invalid JSON.',\n };\n }\n\n const servers =\n typeof parsed[rootKey] === 'object' && parsed[rootKey] != null\n ? (parsed[rootKey] as Record<string, unknown>)\n : null;\n\n if (!servers || typeof servers.forcefield !== 'object' || servers.forcefield == null) {\n return {\n ok: false,\n filePath,\n detail: 'Missing forcefield MCP server entry.',\n };\n }\n\n const ffServer = servers.forcefield as Record<string, unknown>;\n const command = typeof ffServer.command === 'string' ? ffServer.command : '';\n const env = typeof ffServer.env === 'object' && ffServer.env != null\n ? (ffServer.env as Record<string, unknown>)\n : {};\n const key = typeof env.FORCEFIELD_API_KEY === 'string'\n ? env.FORCEFIELD_API_KEY\n : undefined;\n\n if (!command) {\n return {\n ok: false,\n filePath,\n key,\n detail: 'forcefield entry missing command.',\n };\n }\n\n return {\n ok: true,\n filePath,\n key,\n detail: `Found forcefield entry (command: ${command}).`,\n };\n}\n\nasync function inspectCodexMcpConfig(filePath: string): Promise<McpCheckResult> {\n let raw = '';\n try {\n raw = await readFile(filePath, 'utf-8');\n } catch {\n return {\n ok: false,\n filePath,\n detail: 'File not found.',\n };\n }\n\n const command = extractTomlValue(raw, /^\\s*command\\s*=\\s*\"([^\"]+)\"/m);\n const key = extractTomlValue(raw, /^\\s*FORCEFIELD_API_KEY\\s*=\\s*\"([^\"]+)\"/m);\n const hasServerSection = raw.includes('[mcp_servers.forcefield]');\n\n if (!hasServerSection) {\n return {\n ok: false,\n filePath,\n key,\n detail: 'Missing [mcp_servers.forcefield] section.',\n };\n }\n\n if (!command) {\n return {\n ok: false,\n filePath,\n key,\n detail: 'forcefield section missing command.',\n };\n }\n\n return {\n ok: true,\n filePath,\n key,\n detail: `Found forcefield section (command: ${command}).`,\n };\n}\n\nfunction extractTomlValue(content: string, pattern: RegExp): string | undefined {\n const match = content.match(pattern);\n return match?.[1];\n}\n\n// === Non-Interactive Mode ===\n\nasync function runNonInteractive(projectDir: string, args: CliArgs): Promise<void> {\n const ide = args.ide!;\n const mode = args.mode!;\n let apiKey = args.token;\n\n if (args.localAuth) {\n if (!args.email || !args.password) {\n console.error(pc.red('Non-interactive local auth requires --email and --password.'));\n process.exit(1);\n }\n\n const auth = await authenticateLocalAndCreateApiKey(args.email, args.password, {\n label: 'Setup Wizard (Local)',\n });\n apiKey = auth.apiKey;\n console.log(`Created local API key for ${auth.email}.`);\n } else if (!apiKey && args.email && args.password) {\n const auth = await authenticateAccountAndCreateApiKey(args.email, args.password, {\n label: 'Setup Wizard Key',\n localDev: isLocalSetupMode(args),\n });\n apiKey = auth.apiKey;\n console.log(`Created API key for ${auth.email}.`);\n } else if (apiKey) {\n const verified = await authenticateWithRetry(async () => apiKey ?? null, {\n localDev: isLocalSetupMode(args),\n });\n if (!verified.valid) {\n console.error(pc.red(verified.error ?? 'API key validation failed.'));\n process.exit(1);\n }\n apiKey = verified.apiKey;\n }\n\n if (!apiKey) {\n console.error(pc.red('Missing auth input. Pass --token, --local-auth, or --email/--password.'));\n process.exit(1);\n }\n\n console.log(`Setting up Forcefield for ${ide} in ${mode} mode...`);\n\n await configure(projectDir, ide, mode, apiKey);\n\n console.log(pc.green('Setup complete!'));\n for (const line of getPostSetupInstructions(ide, mode, projectDir)) {\n console.log(line);\n }\n}\n\n// === Interactive Mode ===\n\nasync function runInteractive(projectDir: string, preArgs: CliArgs): Promise<void> {\n showBanner();\n\n p.intro(pc.bgCyan(pc.black(' Forcefield Setup ')));\n\n // Step 1: Check existing setup\n const existingConfig = await readConfig(projectDir);\n if (existingConfig) {\n const updateChoice = await p.select({\n message: `Forcefield is already set up (${existingConfig.ide}, ${existingConfig.mode} mode).`,\n options: [\n { value: 'update', label: 'Update existing setup', hint: 'Refresh workflows + auth' },\n { value: 'fresh', label: 'Start fresh', hint: 'Remove existing config and reconfigure' },\n ],\n });\n\n if (p.isCancel(updateChoice)) {\n p.cancel('Setup cancelled.');\n process.exit(0);\n }\n\n if (updateChoice === 'update') {\n // Re-run configure with existing settings\n const apiKey = await promptApiKey();\n if (!apiKey) return;\n await configure(projectDir, existingConfig.ide, existingConfig.mode, apiKey);\n showSuccess(existingConfig.ide, existingConfig.mode, projectDir);\n return;\n }\n // fresh → continue with full wizard\n }\n\n // Step 2: IDE detection + selection\n const ide = preArgs.ide ?? await promptIde(projectDir);\n if (!ide) return;\n\n // Step 3: Mode selection\n const mode = preArgs.mode ?? await promptMode();\n if (!mode) return;\n\n // Step 4: Authentication\n const apiKey = preArgs.token ?? await promptApiKey(preArgs);\n if (!apiKey) return;\n\n // Step 5: Configure + install\n const s = p.spinner();\n s.start('Configuring Forcefield...');\n\n try {\n await configure(projectDir, ide, mode, apiKey);\n s.stop('Configuration complete.');\n } catch (err) {\n s.stop('Configuration failed.');\n p.cancel(err instanceof Error ? err.message : 'Unknown error');\n process.exit(1);\n }\n\n // Step 6: Success\n showSuccess(ide, mode, projectDir);\n}\n\n// === Prompts ===\n\nasync function promptIde(projectDir: string): Promise<Ide | null> {\n const detection = await detectIde(projectDir);\n\n if (detection.detected) {\n const adapter = getAdapter(detection.detected);\n const confirm = await p.confirm({\n message: `Detected ${adapter.name} (${detection.markers[0]!.marker} found). Use ${adapter.name}?`,\n });\n\n if (p.isCancel(confirm)) {\n p.cancel('Setup cancelled.');\n return null;\n }\n\n if (confirm) return detection.detected;\n }\n\n const choice = await p.select({\n message: 'Which IDE do you use?',\n options: IDE_CHOICES,\n });\n\n if (p.isCancel(choice)) {\n p.cancel('Setup cancelled.');\n return null;\n }\n\n return choice as Ide;\n}\n\nasync function promptMode(): Promise<SetupMode | null> {\n const choice = await p.select({\n message: 'Installation type:',\n options: [\n { value: 'full' as const, label: 'Full — MCP server + guided workflows', hint: 'Recommended' },\n { value: 'core' as const, label: 'Core — MCP server only', hint: 'Minimal' },\n ],\n });\n\n if (p.isCancel(choice)) {\n p.cancel('Setup cancelled.');\n return null;\n }\n\n return choice as SetupMode;\n}\n\nasync function promptApiKey(preArgs?: CliArgs): Promise<string | null> {\n if (preArgs?.localAuth) {\n const preEmail = preArgs.email ?? await promptTextValue('Local test email:', 'alice@test.local');\n const prePassword = preArgs.password ?? await promptPasswordValue(\n 'Local test password:',\n 'Confirm local test password:',\n );\n if (!preEmail || !prePassword) return null;\n\n try {\n const result = await authenticateLocalAndCreateApiKey(preEmail, prePassword, {\n label: 'Setup Wizard (Local)',\n });\n p.log.success(`Created local API key for ${result.email}.`);\n return result.apiKey;\n } catch (err) {\n p.log.error(err instanceof Error ? err.message : 'Failed local auth');\n return null;\n }\n }\n\n const localMode = isLocalSetupMode(preArgs);\n const methodOptions = [\n { value: 'account', label: 'Sign in / create account + API key', hint: 'Recommended' },\n { value: 'paste', label: 'Paste existing API key', hint: 'Use an existing ff_live_... key' },\n ];\n\n if (localMode) {\n methodOptions.push({\n value: 'local',\n label: 'Create local account + API key',\n hint: 'For local Supabase testing',\n });\n }\n\n const method = await p.select({\n message: 'How do you want to authenticate?',\n options: methodOptions,\n });\n\n if (p.isCancel(method)) {\n p.cancel('Setup cancelled.');\n return null;\n }\n\n if (method === 'account') {\n const email = await promptTextValue('Account email:', preArgs?.email ?? 'you@company.com');\n const password = preArgs?.password ?? await promptPasswordValue(\n 'Account password:',\n 'Confirm account password:',\n );\n if (!email || !password) return null;\n\n try {\n const result = await authenticateAccountAndCreateApiKey(email, password, {\n label: 'Setup Wizard Key',\n localDev: localMode,\n });\n p.log.success(`Created API key for ${result.email}.`);\n return result.apiKey;\n } catch (err) {\n p.log.error(err instanceof Error ? err.message : 'Account authentication failed');\n return null;\n }\n }\n\n if (method === 'local') {\n const email = await promptTextValue('Local test email:', 'alice@test.local');\n const password = await promptPasswordValue(\n 'Local test password:',\n 'Confirm local test password:',\n );\n if (!email || !password) return null;\n\n try {\n const result = await authenticateLocalAndCreateApiKey(email, password, {\n label: 'Setup Wizard (Local)',\n });\n p.log.success(`Created local API key for ${result.email}.`);\n return result.apiKey;\n } catch (err) {\n p.log.error(err instanceof Error ? err.message : 'Failed local auth');\n return null;\n }\n }\n\n const auth = await authenticateWithRetry(\n async () => {\n const key = await p.text({\n message: 'Enter your Forcefield API key:',\n placeholder: 'ff_live_...',\n validate: (value) => {\n if (!value) return 'API key is required.';\n if (!value.startsWith('ff_live_')) return 'Key must start with \"ff_live_\".';\n if (value.length < 20) return 'Key seems too short.';\n return undefined;\n },\n });\n\n if (p.isCancel(key)) {\n p.cancel('Setup cancelled.');\n return null;\n }\n\n return key;\n },\n {\n localDev: localMode,\n },\n );\n\n if (!auth.valid) {\n p.log.error(auth.error ?? 'Authentication failed. Check your credentials and retry.');\n return null;\n }\n\n return auth.apiKey;\n}\n\nfunction isLocalSetupMode(preArgs?: CliArgs): boolean {\n if (preArgs?.localAuth) return true;\n const localValue = process.env.FORCEFIELD_LOCAL_DEV;\n if (localValue) {\n const normalized = localValue.trim().toLowerCase();\n if (['1', 'true', 'yes', 'on'].includes(normalized)) {\n return true;\n }\n }\n\n const supabaseUrl = process.env.SUPABASE_URL;\n if (!supabaseUrl) return false;\n try {\n const parsed = new URL(supabaseUrl);\n return parsed.hostname === '127.0.0.1' || parsed.hostname === 'localhost';\n } catch {\n return false;\n }\n}\n\nasync function promptTextValue(\n message: string,\n placeholder: string,\n): Promise<string | null> {\n const value = await p.text({\n message,\n placeholder,\n validate: (input) => {\n if (!input) return 'This field is required.';\n return undefined;\n },\n });\n\n if (p.isCancel(value)) {\n p.cancel('Setup cancelled.');\n return null;\n }\n return value;\n}\n\nasync function promptPasswordValue(\n message: string,\n confirmMessage?: string,\n): Promise<string | null> {\n const password = await p.password({\n message,\n validate: (input) => {\n if (!input) return 'Password is required.';\n if (input.length < 8) return 'Password must be at least 8 characters.';\n return undefined;\n },\n });\n\n if (p.isCancel(password)) {\n p.cancel('Setup cancelled.');\n return null;\n }\n\n if (!confirmMessage) {\n return password;\n }\n\n const confirm = await p.password({\n message: confirmMessage,\n validate: (input) => {\n if (!input) return 'Please confirm your password.';\n return undefined;\n },\n });\n\n if (p.isCancel(confirm)) {\n p.cancel('Setup cancelled.');\n return null;\n }\n\n if (password !== confirm) {\n p.log.error('Passwords do not match. Please run setup again.');\n return null;\n }\n\n return password;\n}\n\n// === Configure ===\n\nasync function configure(\n projectDir: string,\n ide: Ide,\n mode: SetupMode,\n apiKey: string,\n): Promise<void> {\n const adapter = getAdapter(ide);\n\n // Configure MCP\n await adapter.configureMcp(projectDir, apiKey);\n\n // Install workflows (full mode only)\n let workflowCount = 0;\n if (mode === 'full') {\n const workflowsDir = await resolveWorkflowsDir();\n workflowCount = await adapter.installWorkflows(projectDir, workflowsDir);\n }\n\n // Write config\n const config: SetupConfig = {\n ide,\n mode,\n installed_at: new Date().toISOString(),\n version: VERSION,\n };\n await writeConfig(projectDir, config);\n\n void workflowCount; // Used in logging below\n}\n\nfunction getPostSetupInstructions(ide: Ide, mode: SetupMode, projectDir: string): string[] {\n const repo = pc.cyan(projectDir);\n const dashboardHint =\n `Optional beta companion: run local dashboard in the Forcefield repo via ${pc.cyan('pnpm run dev:dashboard')} and sign in at ${pc.cyan('http://localhost:3000')}.`;\n\n if (mode === 'core') {\n return [\n `Next: open your coding agent in ${repo} and use Forcefield MCP tools directly (e.g. ${pc.cyan('ff_system(action: \"health\")')}).`,\n dashboardHint,\n ];\n }\n\n const common = [\n `Next: start your coding agent in ${repo}.`,\n `Then in IDE chat (not terminal), run ${pc.cyan('/ff-onboard')} to set up your company profile and deadlines.`,\n `Optional: run ${pc.cyan('/ff-start')} only if you want a command primer or connection troubleshooting.`,\n `If connection fails, run ${pc.cyan('forcefield doctor')} in terminal for diagnostics.`,\n dashboardHint,\n ];\n\n if (ide === 'claude-code') {\n return [\n ...common,\n `If tools are missing, run ${pc.cyan('/mcp')} and confirm ${pc.cyan('forcefield')} is connected.`,\n ];\n }\n\n return common;\n}\n\nfunction showSuccess(ide: Ide, mode: SetupMode, projectDir: string): void {\n const adapter = getAdapter(ide);\n const workflowStatus =\n mode === 'full'\n ? `${pc.green('✓')} Project workflow commands installed`\n : `${pc.yellow('•')} Core mode selected (no slash-command workflows installed)`;\n\n p.note(\n [\n `${pc.green('✓')} MCP server configured`,\n workflowStatus,\n `${pc.green('✓')} IDE: ${adapter.name}`,\n ].join('\\n'),\n 'Setup Complete',\n );\n\n p.outro(getPostSetupInstructions(ide, mode, projectDir).join('\\n'));\n}\n\n// === Config File ===\n\nasync function readConfig(projectDir: string): Promise<SetupConfig | null> {\n const configPath = join(projectDir, CONFIG_FILE);\n try {\n await access(configPath);\n const raw = await readFile(configPath, 'utf-8');\n return JSON.parse(raw) as SetupConfig;\n } catch {\n return null;\n }\n}\n\nasync function writeConfig(projectDir: string, config: SetupConfig): Promise<void> {\n const configPath = join(projectDir, CONFIG_FILE);\n await writeFile(configPath, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n}\n\nexport {\n readConfig,\n writeConfig,\n CONFIG_FILE,\n VERSION,\n BANNER_FONT,\n BANNER_MIN_COLUMNS,\n BANNER_GRADIENT_STOPS,\n showBanner,\n applyBannerGradient,\n getPostSetupInstructions,\n inspectMcpConfig,\n inspectJsonMcpConfig,\n inspectCodexMcpConfig,\n extractTomlValue,\n};\n","/**\n * setup/ide-detect.ts — Auto-detect IDE from project directory markers.\n */\n\nimport { access } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { Ide } from './types.js';\n\ninterface DetectionResult {\n detected: Ide | null;\n markers: Array<{ ide: Ide; marker: string }>;\n}\n\nconst IDE_MARKERS: Array<{ ide: Ide; marker: string; isDir: boolean }> = [\n { ide: 'claude-code', marker: '.claude', isDir: true },\n { ide: 'cursor', marker: '.cursor', isDir: true },\n { ide: 'codex', marker: 'AGENTS.md', isDir: false },\n { ide: 'windsurf', marker: '.windsurfrules', isDir: false },\n];\n\nexport async function detectIde(projectDir: string): Promise<DetectionResult> {\n const found: Array<{ ide: Ide; marker: string }> = [];\n\n for (const { ide, marker } of IDE_MARKERS) {\n const markerPath = join(projectDir, marker);\n try {\n await access(markerPath);\n found.push({ ide, marker });\n } catch {\n // Marker not found — skip\n }\n }\n\n return {\n detected: found.length === 1 ? found[0]!.ide : null,\n markers: found,\n };\n}\n\nexport { IDE_MARKERS };\n","/**\n * IDE adapter for Claude Code.\n * Workflows → .claude/commands/ff-*.md\n * MCP → project-scoped .mcp.json entry\n */\n\nimport { mkdir, readdir, copyFile, rm, readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { IdeAdapter } from '../types.js';\nimport { buildMcpEnv, getMcpLaunchConfig } from './mcp-runtime.js';\n\nexport const claudeCodeAdapter: IdeAdapter = {\n name: 'Claude Code',\n\n async configureMcp(projectDir: string, apiKey: string): Promise<void> {\n // Ensure Claude config folder exists for slash-command workflows.\n const claudeDir = join(projectDir, '.claude');\n await mkdir(claudeDir, { recursive: true });\n\n // Configure project-scoped MCP entry used by Claude Code.\n const launch = await getMcpLaunchConfig();\n const mcpPath = join(projectDir, '.mcp.json');\n\n let existing: Record<string, unknown> = {};\n try {\n existing = JSON.parse(await readFile(mcpPath, 'utf-8')) as Record<string, unknown>;\n } catch {\n // file missing/invalid: start fresh\n }\n\n const existingServers =\n typeof existing.mcpServers === 'object' && existing.mcpServers != null\n ? (existing.mcpServers as Record<string, unknown>)\n : {};\n\n existingServers.forcefield = {\n command: launch.command,\n args: launch.args,\n env: buildMcpEnv(apiKey),\n };\n\n const nextConfig = {\n ...existing,\n mcpServers: existingServers,\n };\n\n await writeFile(mcpPath, JSON.stringify(nextConfig, null, 2) + '\\n', 'utf-8');\n },\n\n async installWorkflows(projectDir: string, workflowsDir: string): Promise<number> {\n const commandsDir = join(projectDir, '.claude', 'commands');\n await mkdir(commandsDir, { recursive: true });\n\n const files = await readdir(workflowsDir);\n const mdFiles = files.filter((f) => f.startsWith('ff-') && f.endsWith('.md'));\n\n for (const file of mdFiles) {\n await copyFile(join(workflowsDir, file), join(commandsDir, file));\n }\n\n return mdFiles.length;\n },\n\n async removeWorkflows(projectDir: string): Promise<void> {\n const commandsDir = join(projectDir, '.claude', 'commands');\n try {\n const files = await readdir(commandsDir);\n for (const file of files) {\n if (file.startsWith('ff-') && file.endsWith('.md')) {\n await rm(join(commandsDir, file));\n }\n }\n } catch {\n // Directory doesn't exist — nothing to remove\n }\n },\n};\n","import { access } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst LOCAL_ENTRY_CANDIDATES = [\n join(__dirname, '..', '..', 'build', 'index.js'),\n join(__dirname, '..', '..', 'index.js'),\n];\nconst RUNNING_FROM_NODE_MODULES = __dirname.includes('node_modules');\n\nconst FORWARDED_ENV_KEYS = [\n 'SUPABASE_URL',\n 'SUPABASE_ANON_KEY',\n 'FORCEFIELD_LOCAL_DEV',\n 'FORCEFIELD_DISABLE_GATING',\n 'FORCEFIELD_LOCAL_DATA_FALLBACK',\n] as const;\n\nfunction isTruthy(value: string | undefined): boolean {\n if (!value) return false;\n const normalized = value.trim().toLowerCase();\n return normalized === '1' || normalized === 'true' || normalized === 'yes' || normalized === 'on';\n}\n\nasync function resolveLocalEntry(): Promise<string | null> {\n for (const candidate of LOCAL_ENTRY_CANDIDATES) {\n try {\n await access(candidate);\n return candidate;\n } catch {\n // try next candidate\n }\n }\n return null;\n}\n\nexport async function getMcpLaunchConfig(): Promise<{ command: string; args: string[] }> {\n if (\n RUNNING_FROM_NODE_MODULES\n || isTruthy(process.env.FORCEFIELD_LOCAL_DEV)\n || isTruthy(process.env.FORCEFIELD_SETUP_USE_LOCAL_BUILD)\n ) {\n const localEntry = await resolveLocalEntry();\n if (localEntry) {\n return {\n command: process.execPath,\n args: [localEntry],\n };\n }\n }\n\n return {\n command: 'npx',\n args: ['-y', '-p', '@forcefield/mcp-server', 'forcefield-mcp'],\n };\n}\n\nexport function buildMcpEnv(apiKey: string): Record<string, string> {\n const env: Record<string, string> = {\n FORCEFIELD_API_KEY: apiKey,\n };\n\n for (const key of FORWARDED_ENV_KEYS) {\n const value = process.env[key];\n if (value && value.trim().length > 0) {\n env[key] = value;\n }\n }\n\n return env;\n}\n","/**\n * IDE adapter for Cursor.\n * Workflows → .cursor/rules/ff-*.md\n * MCP → .cursor/mcp.json\n */\n\nimport { mkdir, readdir, copyFile, rm, readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { IdeAdapter } from '../types.js';\nimport { buildMcpEnv, getMcpLaunchConfig } from './mcp-runtime.js';\n\ntype CursorMcpConfig = {\n mcpServers?: Record<string, { command: string; args: string[]; env?: Record<string, string> }>;\n};\n\nexport const cursorAdapter: IdeAdapter = {\n name: 'Cursor',\n\n async configureMcp(projectDir: string, apiKey: string): Promise<void> {\n const cursorDir = join(projectDir, '.cursor');\n await mkdir(cursorDir, { recursive: true });\n\n const configPath = join(cursorDir, 'mcp.json');\n const launch = await getMcpLaunchConfig();\n\n let existing: CursorMcpConfig = {};\n try {\n existing = JSON.parse(await readFile(configPath, 'utf-8')) as CursorMcpConfig;\n } catch {\n // file missing/invalid: overwrite with fresh config\n }\n\n const existingServers =\n typeof existing.mcpServers === 'object' && existing.mcpServers != null\n ? existing.mcpServers\n : {};\n\n existingServers.forcefield = {\n command: launch.command,\n args: launch.args,\n env: buildMcpEnv(apiKey),\n };\n\n const merged: CursorMcpConfig = {\n ...existing,\n mcpServers: existingServers,\n };\n\n await writeFile(configPath, JSON.stringify(merged, null, 2) + '\\n', 'utf-8');\n },\n\n async installWorkflows(projectDir: string, workflowsDir: string): Promise<number> {\n const rulesDir = join(projectDir, '.cursor', 'rules');\n await mkdir(rulesDir, { recursive: true });\n\n const files = await readdir(workflowsDir);\n const mdFiles = files.filter((f) => f.startsWith('ff-') && f.endsWith('.md'));\n\n for (const file of mdFiles) {\n await copyFile(join(workflowsDir, file), join(rulesDir, file));\n }\n\n return mdFiles.length;\n },\n\n async removeWorkflows(projectDir: string): Promise<void> {\n const rulesDir = join(projectDir, '.cursor', 'rules');\n try {\n const files = await readdir(rulesDir);\n for (const file of files) {\n if (file.startsWith('ff-') && file.endsWith('.md')) {\n await rm(join(rulesDir, file));\n }\n }\n } catch {\n // Directory doesn't exist\n }\n },\n};\n","/**\n * IDE adapter for Codex (OpenAI).\n * Workflows → appended to AGENTS.md with markers\n * MCP → .codex/config.toml or project-level config\n */\n\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { IdeAdapter } from '../types.js';\nimport { buildMcpEnv, getMcpLaunchConfig } from './mcp-runtime.js';\n\nconst START_MARKER = '<!-- forcefield:start -->';\nconst END_MARKER = '<!-- forcefield:end -->';\nconst MCP_START_MARKER = '# forcefield:mcp:start';\nconst MCP_END_MARKER = '# forcefield:mcp:end';\n\nexport const codexAdapter: IdeAdapter = {\n name: 'Codex',\n\n async configureMcp(projectDir: string, apiKey: string): Promise<void> {\n const codexDir = join(projectDir, '.codex');\n await mkdir(codexDir, { recursive: true });\n\n const configPath = join(codexDir, 'config.toml');\n const launch = await getMcpLaunchConfig();\n const env = buildMcpEnv(apiKey);\n\n const forcefieldBlock = buildForcefieldTomlBlock(launch.command, launch.args, env);\n\n let existing = '';\n try {\n existing = await readFile(configPath, 'utf-8');\n } catch {\n // file missing — create new\n }\n\n const cleaned = removeTomlForcefieldSection(existing).trim();\n const final = cleaned ? `${cleaned}\\n\\n${forcefieldBlock}\\n` : `${forcefieldBlock}\\n`;\n await writeFile(configPath, final, 'utf-8');\n },\n\n async installWorkflows(projectDir: string, workflowsDir: string): Promise<number> {\n const agentsPath = join(projectDir, 'AGENTS.md');\n const { readdir } = await import('node:fs/promises');\n\n // Read all workflow files\n const files = await readdir(workflowsDir);\n const mdFiles = files.filter((f) => f.startsWith('ff-') && f.endsWith('.md'));\n\n const workflowContents: string[] = [];\n for (const file of mdFiles) {\n const content = await readFile(join(workflowsDir, file), 'utf-8');\n workflowContents.push(content);\n }\n\n const forcefieldSection = [\n START_MARKER,\n '',\n '# Forcefield Workflows',\n '',\n 'The following workflows are available for compliance management:',\n '',\n ...workflowContents.map((c) => c + '\\n\\n---\\n'),\n END_MARKER,\n ].join('\\n');\n\n // Read existing AGENTS.md or create new\n let existing = '';\n try {\n existing = await readFile(agentsPath, 'utf-8');\n } catch {\n // File doesn't exist — will create\n }\n\n // Remove existing Forcefield section if present\n const cleaned = removeSection(existing);\n\n // Append new section\n const final = cleaned.trim()\n ? cleaned.trim() + '\\n\\n' + forcefieldSection\n : forcefieldSection;\n\n await writeFile(agentsPath, final, 'utf-8');\n return mdFiles.length;\n },\n\n async removeWorkflows(projectDir: string): Promise<void> {\n const agentsPath = join(projectDir, 'AGENTS.md');\n try {\n const content = await readFile(agentsPath, 'utf-8');\n const cleaned = removeSection(content);\n await writeFile(agentsPath, cleaned, 'utf-8');\n } catch {\n // File doesn't exist — nothing to remove\n }\n },\n};\n\nfunction removeSection(content: string): string {\n const startIdx = content.indexOf(START_MARKER);\n const endIdx = content.indexOf(END_MARKER);\n\n if (startIdx === -1 || endIdx === -1) return content;\n\n const before = content.slice(0, startIdx).trimEnd();\n const after = content.slice(endIdx + END_MARKER.length).trimStart();\n\n return before + (after ? '\\n\\n' + after : '');\n}\n\nfunction removeTomlForcefieldSection(content: string): string {\n const markerStart = content.indexOf(MCP_START_MARKER);\n const markerEnd = content.indexOf(MCP_END_MARKER);\n\n if (markerStart !== -1 && markerEnd !== -1) {\n const before = content.slice(0, markerStart).trimEnd();\n const after = content.slice(markerEnd + MCP_END_MARKER.length).trimStart();\n return before + (after ? '\\n\\n' + after : '');\n }\n\n // Backward-compatible cleanup if a previous config wrote unmanaged sections.\n return content\n .replace(/^\\[mcp_servers\\.forcefield\\]\\n[\\s\\S]*?(?=^\\[|$)/gm, '')\n .replace(/^\\[mcp_servers\\.forcefield\\.env\\]\\n[\\s\\S]*?(?=^\\[|$)/gm, '')\n .trim();\n}\n\nfunction buildForcefieldTomlBlock(\n command: string,\n args: string[],\n env: Record<string, string>,\n): string {\n const envLines = Object.entries(env)\n .map(([key, value]) => `${key} = \"${escapeTomlString(value)}\"`);\n\n return [\n MCP_START_MARKER,\n '[mcp_servers.forcefield]',\n `command = \"${escapeTomlString(command)}\"`,\n `args = [${args.map((arg) => `\"${escapeTomlString(arg)}\"`).join(', ')}]`,\n '[mcp_servers.forcefield.env]',\n ...envLines,\n MCP_END_MARKER,\n ].join('\\n');\n}\n\nfunction escapeTomlString(value: string): string {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n}\n","/**\n * IDE adapter for Windsurf.\n * Workflows → appended to .windsurfrules with markers\n * MCP → Windsurf MCP config\n */\n\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { IdeAdapter } from '../types.js';\nimport { buildMcpEnv, getMcpLaunchConfig } from './mcp-runtime.js';\n\nconst START_MARKER = '<!-- forcefield:start -->';\nconst END_MARKER = '<!-- forcefield:end -->';\n\nexport const windsurfAdapter: IdeAdapter = {\n name: 'Windsurf',\n\n async configureMcp(projectDir: string, apiKey: string): Promise<void> {\n const configDir = join(projectDir, '.windsurf');\n await mkdir(configDir, { recursive: true });\n\n const configPath = join(configDir, 'mcp_config.json');\n const launch = await getMcpLaunchConfig();\n\n let existing: Record<string, unknown> = {};\n try {\n existing = JSON.parse(await readFile(configPath, 'utf-8')) as Record<string, unknown>;\n } catch {\n // file missing/invalid: start fresh\n }\n\n const existingServers =\n typeof existing.mcpServers === 'object' && existing.mcpServers != null\n ? (existing.mcpServers as Record<string, unknown>)\n : {};\n\n existingServers.forcefield = {\n command: launch.command,\n args: launch.args,\n env: buildMcpEnv(apiKey),\n };\n\n const merged = {\n ...existing,\n mcpServers: existingServers,\n };\n\n await writeFile(configPath, JSON.stringify(merged, null, 2) + '\\n', 'utf-8');\n },\n\n async installWorkflows(projectDir: string, workflowsDir: string): Promise<number> {\n const rulesPath = join(projectDir, '.windsurfrules');\n const { readdir } = await import('node:fs/promises');\n\n const files = await readdir(workflowsDir);\n const mdFiles = files.filter((f) => f.startsWith('ff-') && f.endsWith('.md'));\n\n const workflowContents: string[] = [];\n for (const file of mdFiles) {\n const content = await readFile(join(workflowsDir, file), 'utf-8');\n workflowContents.push(content);\n }\n\n const forcefieldSection = [\n START_MARKER,\n '',\n '# Forcefield Workflows',\n '',\n ...workflowContents.map((c) => c + '\\n\\n---\\n'),\n END_MARKER,\n ].join('\\n');\n\n let existing = '';\n try {\n existing = await readFile(rulesPath, 'utf-8');\n } catch {\n // File doesn't exist\n }\n\n const cleaned = removeSection(existing);\n const final = cleaned.trim()\n ? cleaned.trim() + '\\n\\n' + forcefieldSection\n : forcefieldSection;\n\n await writeFile(rulesPath, final, 'utf-8');\n return mdFiles.length;\n },\n\n async removeWorkflows(projectDir: string): Promise<void> {\n const rulesPath = join(projectDir, '.windsurfrules');\n try {\n const content = await readFile(rulesPath, 'utf-8');\n const cleaned = removeSection(content);\n await writeFile(rulesPath, cleaned, 'utf-8');\n } catch {\n // File doesn't exist\n }\n },\n};\n\nfunction removeSection(content: string): string {\n const startIdx = content.indexOf(START_MARKER);\n const endIdx = content.indexOf(END_MARKER);\n\n if (startIdx === -1 || endIdx === -1) return content;\n\n const before = content.slice(0, startIdx).trimEnd();\n const after = content.slice(endIdx + END_MARKER.length).trimStart();\n\n return before + (after ? '\\n\\n' + after : '');\n}\n","/**\n * IDE adapter registry.\n */\n\nimport type { Ide, IdeAdapter } from '../types.js';\nimport { claudeCodeAdapter } from './claude-code.js';\nimport { cursorAdapter } from './cursor.js';\nimport { codexAdapter } from './codex.js';\nimport { windsurfAdapter } from './windsurf.js';\n\nconst adapters: Record<Ide, IdeAdapter> = {\n 'claude-code': claudeCodeAdapter,\n 'cursor': cursorAdapter,\n 'codex': codexAdapter,\n 'windsurf': windsurfAdapter,\n};\n\nexport function getAdapter(ide: Ide): IdeAdapter {\n return adapters[ide];\n}\n\nexport const IDE_CHOICES: Array<{ value: Ide; label: string; hint: string }> = [\n { value: 'claude-code', label: 'Claude Code', hint: '.claude/commands/' },\n { value: 'cursor', label: 'Cursor', hint: '.cursor/rules/' },\n { value: 'codex', label: 'Codex (OpenAI)', hint: 'AGENTS.md' },\n { value: 'windsurf', label: 'Windsurf', hint: '.windsurfrules' },\n];\n","/**\n * setup/auth.ts — Authentication and API key issuance for setup wizard.\n */\n\nimport { createHash, randomBytes } from 'node:crypto';\nimport { createClient } from '@supabase/supabase-js';\nimport {\n LOCAL_SUPABASE_ANON_KEY,\n LOCAL_SUPABASE_SERVICE_ROLE_KEY,\n PRODUCTION_SUPABASE_PUBLISHABLE_KEY,\n PRODUCTION_SUPABASE_URL,\n} from '../src/supabase-defaults.js';\n\nconst API_KEY_PREFIX = 'ff_live_';\nconst MAX_RETRIES = 3;\n\nexport interface AuthResult {\n valid: boolean;\n apiKey: string;\n error?: string;\n}\n\nexport interface LocalAuthResult {\n apiKey: string;\n userId: string;\n email: string;\n}\n\ninterface SetupAuthOptions {\n supabaseUrl?: string;\n anonKey?: string;\n localDev?: boolean;\n}\n\nfunction isTruthy(value: string | undefined): boolean {\n if (!value) return false;\n const normalized = value.trim().toLowerCase();\n return normalized === '1' || normalized === 'true' || normalized === 'yes' || normalized === 'on';\n}\n\nfunction getSupabaseUrl(options?: SetupAuthOptions): string {\n return options?.supabaseUrl ?? process.env.SUPABASE_URL ?? PRODUCTION_SUPABASE_URL;\n}\n\nfunction isLocalSupabaseUrl(supabaseUrl: string): boolean {\n try {\n const parsed = new URL(supabaseUrl);\n return parsed.hostname === '127.0.0.1' || parsed.hostname === 'localhost';\n } catch {\n return false;\n }\n}\n\nfunction isLocalMode(options?: SetupAuthOptions): boolean {\n if (options?.localDev !== undefined) return options.localDev;\n if (isTruthy(process.env.FORCEFIELD_LOCAL_DEV)) return true;\n return isLocalSupabaseUrl(getSupabaseUrl(options));\n}\n\nfunction getAnonKey(supabaseUrl: string, options?: SetupAuthOptions): string {\n const explicit = options?.anonKey ?? process.env.SUPABASE_ANON_KEY;\n if (explicit && explicit.trim().length > 0) return explicit;\n\n if (isLocalSupabaseUrl(supabaseUrl)) {\n return LOCAL_SUPABASE_ANON_KEY;\n }\n\n return PRODUCTION_SUPABASE_PUBLISHABLE_KEY;\n}\n\nfunction getServiceRoleKey(supabaseUrl: string): string | null {\n const explicit = process.env.SUPABASE_SERVICE_ROLE_KEY;\n if (explicit && explicit.trim().length > 0) return explicit;\n\n if (isLocalSupabaseUrl(supabaseUrl)) {\n return LOCAL_SUPABASE_SERVICE_ROLE_KEY;\n }\n\n return null;\n}\n\n/**\n * Validate API key format.\n */\nexport function validateApiKeyFormat(key: string): boolean {\n return key.startsWith(API_KEY_PREFIX) && key.length > API_KEY_PREFIX.length + 8;\n}\n\n/**\n * Verify an API key through key-exchange endpoint.\n */\nexport async function verifyApiKey(apiKey: string, options?: SetupAuthOptions): Promise<AuthResult> {\n if (!validateApiKeyFormat(apiKey)) {\n return {\n valid: false,\n apiKey: '',\n error: 'Invalid API key format. Keys must start with \"ff_live_\".',\n };\n }\n\n const supabaseUrl = getSupabaseUrl(options);\n const endpoint = `${supabaseUrl}/functions/v1/key-exchange`;\n\n try {\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${apiKey}`,\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n const payload = await response.json().catch(() => ({})) as { error?: string };\n const detail = payload.error ?? 'API key invalid or revoked.';\n return {\n valid: false,\n apiKey: '',\n error: `Authentication failed (${response.status}): ${detail}`,\n };\n }\n\n return { valid: true, apiKey };\n } catch {\n return {\n valid: false,\n apiKey: '',\n error: `Could not reach Forcefield backend at ${supabaseUrl}. Check SUPABASE_URL/network and retry.`,\n };\n }\n}\n\n/**\n * Authenticate with retries.\n */\nexport async function authenticateWithRetry(\n getKey: () => Promise<string | null>,\n options?: SetupAuthOptions,\n): Promise<AuthResult> {\n let lastError: string | undefined;\n\n for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {\n const key = await getKey();\n\n if (!key) {\n return { valid: false, apiKey: '', error: 'No API key provided.' };\n }\n\n const verified = await verifyApiKey(key, options);\n if (verified.valid) {\n return verified;\n }\n\n lastError = verified.error;\n\n if (attempt < MAX_RETRIES) {\n continue;\n }\n }\n\n return {\n valid: false,\n apiKey: '',\n error: lastError ?? `Authentication failed after ${MAX_RETRIES} attempts.`,\n };\n}\n\nfunction generateApiKey(): { plaintext: string; hash: string; prefix: string } {\n const raw = randomBytes(32).toString('hex');\n const plaintext = `${API_KEY_PREFIX}${raw}`;\n const hash = createHash('sha256').update(plaintext).digest('hex');\n const prefix = plaintext.slice(0, 12);\n return { plaintext, hash, prefix };\n}\n\n/**\n * Hosted/local account flow:\n * 1. Sign in (or sign up + sign in)\n * 2. Insert API key under authenticated user\n */\nexport async function authenticateAccountAndCreateApiKey(\n email: string,\n password: string,\n options?: {\n supabaseUrl?: string;\n anonKey?: string;\n label?: string;\n localDev?: boolean;\n },\n): Promise<LocalAuthResult> {\n const supabaseUrl = getSupabaseUrl(options);\n const anonKey = getAnonKey(supabaseUrl, options);\n\n const supabase = createClient(supabaseUrl, anonKey, {\n auth: {\n persistSession: false,\n autoRefreshToken: false,\n },\n });\n\n let signIn = await supabase.auth.signInWithPassword({ email, password });\n\n if (signIn.error || !signIn.data.user) {\n await supabase.auth.signUp({ email, password });\n signIn = await supabase.auth.signInWithPassword({ email, password });\n }\n\n if (signIn.error || !signIn.data.user) {\n const message = signIn.error?.message ?? 'Invalid login credentials';\n if (/email.*not confirmed/i.test(message)) {\n throw new Error(\n 'Authentication failed: Email not confirmed. Confirm the inbox for this account, or disable email confirmation in Supabase Auth settings for beta.',\n );\n }\n throw new Error(`Authentication failed: ${message}`);\n }\n\n const userId = signIn.data.user.id;\n const { plaintext, hash, prefix } = generateApiKey();\n const { error: insertError } = await supabase\n .from('api_keys')\n .insert({\n user_id: userId,\n key_hash: hash,\n key_prefix: prefix,\n label: options?.label ?? 'Setup Wizard Key',\n tier: 'free',\n });\n\n if (insertError) {\n if (isLocalMode(options)) {\n const serviceRoleKey = getServiceRoleKey(supabaseUrl);\n if (serviceRoleKey) {\n return createApiKeyViaServiceRole({\n supabaseUrl,\n serviceRoleKey,\n email,\n password,\n label: options?.label ?? 'Setup Wizard Key',\n });\n }\n }\n\n throw new Error(`Failed to create API key: ${insertError.message}`);\n }\n\n return {\n apiKey: plaintext,\n userId,\n email,\n };\n}\n\n/**\n * Local auth flow preserved for scripted local development.\n */\nexport async function authenticateLocalAndCreateApiKey(\n email: string,\n password: string,\n options?: { supabaseUrl?: string; anonKey?: string; label?: string },\n): Promise<LocalAuthResult> {\n return authenticateAccountAndCreateApiKey(email, password, {\n ...options,\n localDev: true,\n label: options?.label ?? 'Local Setup Key',\n });\n}\n\nasync function createApiKeyViaServiceRole(params: {\n supabaseUrl: string;\n serviceRoleKey: string;\n email: string;\n password: string;\n label: string;\n}): Promise<LocalAuthResult> {\n const admin = createClient(params.supabaseUrl, params.serviceRoleKey, {\n auth: {\n persistSession: false,\n autoRefreshToken: false,\n },\n });\n\n let userId: string | undefined;\n const createUser = await admin.auth.admin.createUser({\n email: params.email,\n password: params.password,\n email_confirm: true,\n });\n\n if (createUser.data.user?.id) {\n userId = createUser.data.user.id;\n } else if (createUser.error) {\n const authDb = createClient(params.supabaseUrl, params.serviceRoleKey, {\n db: { schema: 'auth' },\n auth: {\n persistSession: false,\n autoRefreshToken: false,\n },\n });\n\n const existingUser = await authDb\n .from('users')\n .select('id,email')\n .eq('email', params.email)\n .limit(1)\n .maybeSingle();\n\n if (existingUser.error) {\n throw new Error(`Local login failed: ${createUser.error.message}`);\n }\n userId = existingUser.data?.id;\n }\n\n if (!userId) {\n throw new Error('Local login failed: could not resolve user account');\n }\n\n const { plaintext, hash, prefix } = generateApiKey();\n const { error: insertError } = await admin.from('api_keys').insert({\n user_id: userId,\n key_hash: hash,\n key_prefix: prefix,\n label: params.label,\n tier: 'free',\n });\n\n if (insertError) {\n throw new Error(`Failed to create local API key: ${insertError.message}`);\n }\n\n return {\n apiKey: plaintext,\n userId,\n email: params.email,\n };\n}\n\nexport { API_KEY_PREFIX, MAX_RETRIES };\n","/**\n * Forcefield Setup Wizard — entry point.\n *\n * This is the setup wizard binary (forcefield-setup), invoked via\n * `npx -y -p @forcefield/mcp-server forcefield setup`.\n * Parses CLI arguments and launches the interactive wizard.\n */\n\nimport type { CliArgs, Ide, SetupMode } from './types.js';\nimport { runWizard } from './wizard.js';\nimport { pathToFileURL } from 'node:url';\n\nfunction parseArgs(argv: string[]): CliArgs {\n const args: CliArgs = {};\n\n for (let i = 2; i < argv.length; i++) {\n const arg = argv[i]!;\n\n if (arg === '--status') {\n args.status = true;\n } else if (arg === '--doctor') {\n args.doctor = true;\n } else if (arg === '--ide' && argv[i + 1]) {\n const ide = argv[++i]!;\n if (['claude-code', 'cursor', 'codex', 'windsurf'].includes(ide)) {\n args.ide = ide as Ide;\n }\n } else if (arg === '--mode' && argv[i + 1]) {\n const mode = argv[++i]!;\n if (['full', 'core'].includes(mode)) {\n args.mode = mode as SetupMode;\n }\n } else if (arg === '--token' && argv[i + 1]) {\n args.token = argv[++i]!;\n } else if (arg === '--email' && argv[i + 1]) {\n args.email = argv[++i]!;\n } else if (arg === '--password' && argv[i + 1]) {\n args.password = argv[++i]!;\n } else if (arg === '--local-auth') {\n args.localAuth = true;\n }\n }\n\n return args;\n}\n\nasync function main(): Promise<void> {\n const args = parseArgs(process.argv);\n const projectDir = process.cwd();\n\n try {\n await runWizard(projectDir, args);\n } catch (err) {\n console.error('Setup failed:', err instanceof Error ? err.message : err);\n process.exit(1);\n }\n}\n\nexport async function runSetupCli(argv: string[] = process.argv): Promise<void> {\n const originalArgv = process.argv;\n process.argv = argv;\n try {\n await main();\n } finally {\n process.argv = originalArgv;\n }\n}\n\nfunction isExecutedDirectly(metaUrl: string): boolean {\n const entryPath = process.argv[1];\n if (!entryPath) return false;\n return metaUrl === pathToFileURL(entryPath).href;\n}\n\nif (isExecutedDirectly(import.meta.url)) {\n void runSetupCli();\n}\n\nexport { parseArgs };\n"],"mappings":"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","names":["readFile","writeFile","access","join","dirname","fileURLToPath","join","access","join","join","mkdir","readdir","copyFile","rm","readFile","writeFile","join","join","mkdir","readFile","writeFile","readdir","copyFile","rm","mkdir","readFile","writeFile","join","join","mkdir","readFile","writeFile","readdir","mkdir","readFile","writeFile","join","START_MARKER","END_MARKER","join","mkdir","readFile","writeFile","readdir","removeSection","isTruthy","password","__dirname","dirname","fileURLToPath","join","access","text","readFile","apiKey","confirm","password","writeFile"]}
|
package/build/cli/index.js
CHANGED
package/build/setup/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../setup/wizard.ts","../setup/ide-detect.ts","../setup/ide-adapters/claude-code.ts","../setup/ide-adapters/mcp-runtime.ts","../setup/ide-adapters/cursor.ts","../setup/ide-adapters/codex.ts","../setup/ide-adapters/windsurf.ts","../setup/ide-adapters/index.ts","../setup/auth.ts","../setup/index.ts"],"sourcesContent":["/**\n * setup/wizard.ts — Interactive setup wizard using @clack/prompts.\n *\n * Orchestrates the full setup flow:\n * 1. Welcome banner\n * 2. Existing setup check\n * 3. IDE detection + selection\n * 4. Mode selection (Core vs Full)\n * 5. Authentication\n * 6. Configure + install\n * 7. Verify + success\n */\n\nimport * as p from '@clack/prompts';\nimport pc from 'picocolors';\nimport figlet from 'figlet';\nimport gradient from 'gradient-string';\nimport { readFile, writeFile, access } from 'node:fs/promises';\nimport { join, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { Ide, SetupMode, SetupConfig, CliArgs } from './types.js';\nimport { detectIde } from './ide-detect.js';\nimport { getAdapter, IDE_CHOICES } from './ide-adapters/index.js';\nimport {\n authenticateAccountAndCreateApiKey,\n authenticateLocalAndCreateApiKey,\n authenticateWithRetry,\n verifyApiKey,\n} from './auth.js';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst WORKFLOW_DIR_CANDIDATES = [\n join(__dirname, '..', 'workflows'),\n join(__dirname, '..', '..', 'workflows'),\n];\nconst CONFIG_FILE = '.forcefield.json';\nconst VERSION = '0.1.4';\nconst BANNER_TEXT = 'Forcefield';\nconst BANNER_FONT = 'Rowan Cap';\nconst BANNER_MIN_COLUMNS = 80;\nconst BANNER_FALLBACK_TEXT = ' Forcefield';\nconst BANNER_SUBTITLE = ' Corporate compliance copilot\\n';\n// rainbow2-like palette cycling red -> violet for the terminal banner\nconst BANNER_GRADIENT_STOPS = ['#ff3b3b', '#ff9f1a', '#ffe74c', '#2ed573', '#1e90ff', '#7d5fff', '#e056fd'];\nconst bannerGradient = gradient(BANNER_GRADIENT_STOPS);\n\nasync function resolveWorkflowsDir(): Promise<string> {\n for (const dir of WORKFLOW_DIR_CANDIDATES) {\n try {\n await access(dir);\n return dir;\n } catch {\n // try next candidate\n }\n }\n throw new Error(\n `Unable to locate workflow templates. Checked: ${WORKFLOW_DIR_CANDIDATES.join(', ')}`,\n );\n}\n\n/**\n * Run the interactive setup wizard.\n */\nexport async function runWizard(projectDir: string, args: CliArgs): Promise<void> {\n // --status: read-only check\n if (args.status) {\n await showStatus(projectDir);\n return;\n }\n\n // --doctor: setup diagnostics\n if (args.doctor) {\n await runDoctor(projectDir, args);\n return;\n }\n\n // Non-interactive mode\n if (args.ide && args.mode && (args.token || args.localAuth || (args.email && args.password))) {\n await runNonInteractive(projectDir, args);\n return;\n }\n\n // Interactive mode\n await runInteractive(projectDir, args);\n}\n\n// === Welcome Banner ===\n\nfunction showBanner(): void {\n const cols = process.stdout.columns || 80;\n\n if (cols >= BANNER_MIN_COLUMNS) {\n try {\n const banner = figlet.textSync(BANNER_TEXT, { font: BANNER_FONT });\n const colored = applyBannerGradient(banner);\n console.log(colored);\n } catch {\n // figlet font not available — use fallback\n console.log(pc.bold(applyBannerGradient(BANNER_FALLBACK_TEXT)));\n }\n } else {\n console.log(pc.bold(applyBannerGradient(BANNER_FALLBACK_TEXT)));\n }\n console.log(pc.dim(BANNER_SUBTITLE));\n}\n\nfunction applyBannerGradient(text: string): string {\n return bannerGradient.multiline(text);\n}\n\n// === Status Check ===\n\nasync function showStatus(projectDir: string): Promise<void> {\n const config = await readConfig(projectDir);\n\n if (!config) {\n console.log(pc.yellow('No Forcefield setup found in this directory.'));\n console.log(`Run ${pc.cyan('forcefield setup')} to get started.`);\n process.exit(1);\n }\n\n console.log(pc.bold('Forcefield Setup Status'));\n console.log(` IDE: ${pc.cyan(config.ide)}`);\n console.log(` Mode: ${pc.cyan(config.mode)}`);\n console.log(` Version: ${pc.cyan(config.version)}`);\n console.log(` Installed: ${pc.dim(config.installed_at)}`);\n}\n\ninterface DoctorCheckResult {\n ok: boolean;\n label: string;\n detail: string;\n}\n\ninterface McpCheckResult {\n ok: boolean;\n filePath: string;\n key?: string;\n detail: string;\n}\n\nasync function runDoctor(projectDir: string, args: CliArgs): Promise<void> {\n console.log(pc.bold('Forcefield Setup Doctor'));\n console.log(pc.dim(`Project: ${projectDir}`));\n\n const checks: DoctorCheckResult[] = [];\n const config = await readConfig(projectDir);\n\n if (!config) {\n checks.push({\n ok: false,\n label: 'Setup config',\n detail: `Missing ${CONFIG_FILE}. Run forcefield setup first.`,\n });\n } else {\n checks.push({\n ok: true,\n label: 'Setup config',\n detail: `${config.ide} / ${config.mode} / v${config.version}`,\n });\n\n const mcp = await inspectMcpConfig(projectDir, config.ide);\n checks.push({\n ok: mcp.ok,\n label: 'MCP config',\n detail: `${mcp.filePath} — ${mcp.detail}`,\n });\n\n if (mcp.key) {\n const verified = await verifyApiKey(mcp.key, { localDev: isLocalSetupMode(args) });\n checks.push({\n ok: verified.valid,\n label: 'API key exchange',\n detail: verified.valid\n ? 'Key exchange succeeded.'\n : (verified.error ?? 'Key exchange failed.'),\n });\n } else {\n checks.push({\n ok: false,\n label: 'API key exchange',\n detail: 'FORCEFIELD_API_KEY not found in MCP config env.',\n });\n }\n }\n\n for (const check of checks) {\n const symbol = check.ok ? pc.green('✓') : pc.red('✗');\n console.log(`${symbol} ${pc.bold(check.label)}: ${check.detail}`);\n }\n\n const failures = checks.filter((check) => !check.ok);\n if (failures.length > 0) {\n console.log('');\n console.log(pc.yellow('Suggested fixes:'));\n console.log(` 1. Re-run ${pc.cyan('forcefield setup')} in this project.`);\n console.log(` 2. Confirm your coding agent shows Forcefield connected (${pc.cyan('/mcp')}).`);\n console.log(` 3. Re-run ${pc.cyan('forcefield doctor')} after setup.`);\n process.exit(1);\n }\n\n console.log('');\n console.log(pc.green('Doctor checks passed. Forcefield should be ready.'));\n}\n\nasync function inspectMcpConfig(projectDir: string, ide: Ide): Promise<McpCheckResult> {\n if (ide === 'claude-code') {\n return inspectJsonMcpConfig(join(projectDir, '.mcp.json'), 'mcpServers');\n }\n\n if (ide === 'cursor') {\n return inspectJsonMcpConfig(join(projectDir, '.cursor', 'mcp.json'), 'mcpServers');\n }\n\n if (ide === 'windsurf') {\n return inspectJsonMcpConfig(join(projectDir, '.windsurf', 'mcp_config.json'), 'mcpServers');\n }\n\n return inspectCodexMcpConfig(join(projectDir, '.codex', 'config.toml'));\n}\n\nasync function inspectJsonMcpConfig(\n filePath: string,\n rootKey: string,\n): Promise<McpCheckResult> {\n let raw = '';\n try {\n raw = await readFile(filePath, 'utf-8');\n } catch {\n return {\n ok: false,\n filePath,\n detail: 'File not found.',\n };\n }\n\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(raw) as Record<string, unknown>;\n } catch {\n return {\n ok: false,\n filePath,\n detail: 'Invalid JSON.',\n };\n }\n\n const servers =\n typeof parsed[rootKey] === 'object' && parsed[rootKey] != null\n ? (parsed[rootKey] as Record<string, unknown>)\n : null;\n\n if (!servers || typeof servers.forcefield !== 'object' || servers.forcefield == null) {\n return {\n ok: false,\n filePath,\n detail: 'Missing forcefield MCP server entry.',\n };\n }\n\n const ffServer = servers.forcefield as Record<string, unknown>;\n const command = typeof ffServer.command === 'string' ? ffServer.command : '';\n const env = typeof ffServer.env === 'object' && ffServer.env != null\n ? (ffServer.env as Record<string, unknown>)\n : {};\n const key = typeof env.FORCEFIELD_API_KEY === 'string'\n ? env.FORCEFIELD_API_KEY\n : undefined;\n\n if (!command) {\n return {\n ok: false,\n filePath,\n key,\n detail: 'forcefield entry missing command.',\n };\n }\n\n return {\n ok: true,\n filePath,\n key,\n detail: `Found forcefield entry (command: ${command}).`,\n };\n}\n\nasync function inspectCodexMcpConfig(filePath: string): Promise<McpCheckResult> {\n let raw = '';\n try {\n raw = await readFile(filePath, 'utf-8');\n } catch {\n return {\n ok: false,\n filePath,\n detail: 'File not found.',\n };\n }\n\n const command = extractTomlValue(raw, /^\\s*command\\s*=\\s*\"([^\"]+)\"/m);\n const key = extractTomlValue(raw, /^\\s*FORCEFIELD_API_KEY\\s*=\\s*\"([^\"]+)\"/m);\n const hasServerSection = raw.includes('[mcp_servers.forcefield]');\n\n if (!hasServerSection) {\n return {\n ok: false,\n filePath,\n key,\n detail: 'Missing [mcp_servers.forcefield] section.',\n };\n }\n\n if (!command) {\n return {\n ok: false,\n filePath,\n key,\n detail: 'forcefield section missing command.',\n };\n }\n\n return {\n ok: true,\n filePath,\n key,\n detail: `Found forcefield section (command: ${command}).`,\n };\n}\n\nfunction extractTomlValue(content: string, pattern: RegExp): string | undefined {\n const match = content.match(pattern);\n return match?.[1];\n}\n\n// === Non-Interactive Mode ===\n\nasync function runNonInteractive(projectDir: string, args: CliArgs): Promise<void> {\n const ide = args.ide!;\n const mode = args.mode!;\n let apiKey = args.token;\n\n if (args.localAuth) {\n if (!args.email || !args.password) {\n console.error(pc.red('Non-interactive local auth requires --email and --password.'));\n process.exit(1);\n }\n\n const auth = await authenticateLocalAndCreateApiKey(args.email, args.password, {\n label: 'Setup Wizard (Local)',\n });\n apiKey = auth.apiKey;\n console.log(`Created local API key for ${auth.email}.`);\n } else if (!apiKey && args.email && args.password) {\n const auth = await authenticateAccountAndCreateApiKey(args.email, args.password, {\n label: 'Setup Wizard Key',\n localDev: isLocalSetupMode(args),\n });\n apiKey = auth.apiKey;\n console.log(`Created API key for ${auth.email}.`);\n } else if (apiKey) {\n const verified = await authenticateWithRetry(async () => apiKey ?? null, {\n localDev: isLocalSetupMode(args),\n });\n if (!verified.valid) {\n console.error(pc.red(verified.error ?? 'API key validation failed.'));\n process.exit(1);\n }\n apiKey = verified.apiKey;\n }\n\n if (!apiKey) {\n console.error(pc.red('Missing auth input. Pass --token, --local-auth, or --email/--password.'));\n process.exit(1);\n }\n\n console.log(`Setting up Forcefield for ${ide} in ${mode} mode...`);\n\n await configure(projectDir, ide, mode, apiKey);\n\n console.log(pc.green('Setup complete!'));\n for (const line of getPostSetupInstructions(ide, mode, projectDir)) {\n console.log(line);\n }\n}\n\n// === Interactive Mode ===\n\nasync function runInteractive(projectDir: string, preArgs: CliArgs): Promise<void> {\n showBanner();\n\n p.intro(pc.bgCyan(pc.black(' Forcefield Setup ')));\n\n // Step 1: Check existing setup\n const existingConfig = await readConfig(projectDir);\n if (existingConfig) {\n const updateChoice = await p.select({\n message: `Forcefield is already set up (${existingConfig.ide}, ${existingConfig.mode} mode).`,\n options: [\n { value: 'update', label: 'Update existing setup', hint: 'Refresh workflows + auth' },\n { value: 'fresh', label: 'Start fresh', hint: 'Remove existing config and reconfigure' },\n ],\n });\n\n if (p.isCancel(updateChoice)) {\n p.cancel('Setup cancelled.');\n process.exit(0);\n }\n\n if (updateChoice === 'update') {\n // Re-run configure with existing settings\n const apiKey = await promptApiKey();\n if (!apiKey) return;\n await configure(projectDir, existingConfig.ide, existingConfig.mode, apiKey);\n showSuccess(existingConfig.ide, existingConfig.mode, projectDir);\n return;\n }\n // fresh → continue with full wizard\n }\n\n // Step 2: IDE detection + selection\n const ide = preArgs.ide ?? await promptIde(projectDir);\n if (!ide) return;\n\n // Step 3: Mode selection\n const mode = preArgs.mode ?? await promptMode();\n if (!mode) return;\n\n // Step 4: Authentication\n const apiKey = preArgs.token ?? await promptApiKey(preArgs);\n if (!apiKey) return;\n\n // Step 5: Configure + install\n const s = p.spinner();\n s.start('Configuring Forcefield...');\n\n try {\n await configure(projectDir, ide, mode, apiKey);\n s.stop('Configuration complete.');\n } catch (err) {\n s.stop('Configuration failed.');\n p.cancel(err instanceof Error ? err.message : 'Unknown error');\n process.exit(1);\n }\n\n // Step 6: Success\n showSuccess(ide, mode, projectDir);\n}\n\n// === Prompts ===\n\nasync function promptIde(projectDir: string): Promise<Ide | null> {\n const detection = await detectIde(projectDir);\n\n if (detection.detected) {\n const adapter = getAdapter(detection.detected);\n const confirm = await p.confirm({\n message: `Detected ${adapter.name} (${detection.markers[0]!.marker} found). Use ${adapter.name}?`,\n });\n\n if (p.isCancel(confirm)) {\n p.cancel('Setup cancelled.');\n return null;\n }\n\n if (confirm) return detection.detected;\n }\n\n const choice = await p.select({\n message: 'Which IDE do you use?',\n options: IDE_CHOICES,\n });\n\n if (p.isCancel(choice)) {\n p.cancel('Setup cancelled.');\n return null;\n }\n\n return choice as Ide;\n}\n\nasync function promptMode(): Promise<SetupMode | null> {\n const choice = await p.select({\n message: 'Installation type:',\n options: [\n { value: 'full' as const, label: 'Full — MCP server + guided workflows', hint: 'Recommended' },\n { value: 'core' as const, label: 'Core — MCP server only', hint: 'Minimal' },\n ],\n });\n\n if (p.isCancel(choice)) {\n p.cancel('Setup cancelled.');\n return null;\n }\n\n return choice as SetupMode;\n}\n\nasync function promptApiKey(preArgs?: CliArgs): Promise<string | null> {\n if (preArgs?.localAuth) {\n const preEmail = preArgs.email ?? await promptTextValue('Local test email:', 'alice@test.local');\n const prePassword = preArgs.password ?? await promptTextValue('Local test password:', 'password123', true);\n if (!preEmail || !prePassword) return null;\n\n try {\n const result = await authenticateLocalAndCreateApiKey(preEmail, prePassword, {\n label: 'Setup Wizard (Local)',\n });\n p.log.success(`Created local API key for ${result.email}.`);\n return result.apiKey;\n } catch (err) {\n p.log.error(err instanceof Error ? err.message : 'Failed local auth');\n return null;\n }\n }\n\n const localMode = isLocalSetupMode(preArgs);\n const methodOptions = [\n { value: 'account', label: 'Sign in / create account + API key', hint: 'Recommended' },\n { value: 'paste', label: 'Paste existing API key', hint: 'Use an existing ff_live_... key' },\n ];\n\n if (localMode) {\n methodOptions.push({\n value: 'local',\n label: 'Create local account + API key',\n hint: 'For local Supabase testing',\n });\n }\n\n const method = await p.select({\n message: 'How do you want to authenticate?',\n options: methodOptions,\n });\n\n if (p.isCancel(method)) {\n p.cancel('Setup cancelled.');\n return null;\n }\n\n if (method === 'account') {\n const email = await promptTextValue('Account email:', preArgs?.email ?? 'you@company.com');\n const password = await promptTextValue('Account password:', '••••••••', true);\n if (!email || !password) return null;\n\n try {\n const result = await authenticateAccountAndCreateApiKey(email, password, {\n label: 'Setup Wizard Key',\n localDev: localMode,\n });\n p.log.success(`Created API key for ${result.email}.`);\n return result.apiKey;\n } catch (err) {\n p.log.error(err instanceof Error ? err.message : 'Account authentication failed');\n return null;\n }\n }\n\n if (method === 'local') {\n const email = await promptTextValue('Local test email:', 'alice@test.local');\n const password = await promptTextValue('Local test password:', 'password123', true);\n if (!email || !password) return null;\n\n try {\n const result = await authenticateLocalAndCreateApiKey(email, password, {\n label: 'Setup Wizard (Local)',\n });\n p.log.success(`Created local API key for ${result.email}.`);\n return result.apiKey;\n } catch (err) {\n p.log.error(err instanceof Error ? err.message : 'Failed local auth');\n return null;\n }\n }\n\n const auth = await authenticateWithRetry(\n async () => {\n const key = await p.text({\n message: 'Enter your Forcefield API key:',\n placeholder: 'ff_live_...',\n validate: (value) => {\n if (!value) return 'API key is required.';\n if (!value.startsWith('ff_live_')) return 'Key must start with \"ff_live_\".';\n if (value.length < 20) return 'Key seems too short.';\n return undefined;\n },\n });\n\n if (p.isCancel(key)) {\n p.cancel('Setup cancelled.');\n return null;\n }\n\n return key;\n },\n {\n localDev: localMode,\n },\n );\n\n if (!auth.valid) {\n p.log.error(auth.error ?? 'Authentication failed. Check your credentials and retry.');\n return null;\n }\n\n return auth.apiKey;\n}\n\nfunction isLocalSetupMode(preArgs?: CliArgs): boolean {\n if (preArgs?.localAuth) return true;\n const localValue = process.env.FORCEFIELD_LOCAL_DEV;\n if (localValue) {\n const normalized = localValue.trim().toLowerCase();\n if (['1', 'true', 'yes', 'on'].includes(normalized)) {\n return true;\n }\n }\n\n const supabaseUrl = process.env.SUPABASE_URL;\n if (!supabaseUrl) return false;\n try {\n const parsed = new URL(supabaseUrl);\n return parsed.hostname === '127.0.0.1' || parsed.hostname === 'localhost';\n } catch {\n return false;\n }\n}\n\nasync function promptTextValue(\n message: string,\n placeholder: string,\n secret = false,\n): Promise<string | null> {\n const value = await p.text({\n message,\n placeholder,\n ...(secret ? { placeholder: '••••••••' } : {}),\n validate: (input) => {\n if (!input) return 'This field is required.';\n return undefined;\n },\n });\n\n if (p.isCancel(value)) {\n p.cancel('Setup cancelled.');\n return null;\n }\n return value;\n}\n\n// === Configure ===\n\nasync function configure(\n projectDir: string,\n ide: Ide,\n mode: SetupMode,\n apiKey: string,\n): Promise<void> {\n const adapter = getAdapter(ide);\n\n // Configure MCP\n await adapter.configureMcp(projectDir, apiKey);\n\n // Install workflows (full mode only)\n let workflowCount = 0;\n if (mode === 'full') {\n const workflowsDir = await resolveWorkflowsDir();\n workflowCount = await adapter.installWorkflows(projectDir, workflowsDir);\n }\n\n // Write config\n const config: SetupConfig = {\n ide,\n mode,\n installed_at: new Date().toISOString(),\n version: VERSION,\n };\n await writeConfig(projectDir, config);\n\n void workflowCount; // Used in logging below\n}\n\nfunction getPostSetupInstructions(ide: Ide, mode: SetupMode, projectDir: string): string[] {\n const repo = pc.cyan(projectDir);\n const dashboardHint =\n `Optional beta companion: run local dashboard in the Forcefield repo via ${pc.cyan('pnpm run dev:dashboard')} and sign in at ${pc.cyan('http://localhost:3000')}.`;\n\n if (mode === 'core') {\n return [\n `Next: open your coding agent in ${repo} and use Forcefield MCP tools directly (e.g. ${pc.cyan('ff_system(action: \"health\")')}).`,\n dashboardHint,\n ];\n }\n\n const common = [\n `Next: start your coding agent in ${repo}.`,\n `Then in IDE chat (not terminal), run ${pc.cyan('/ff-onboard')} to set up your company profile and deadlines.`,\n `Optional: run ${pc.cyan('/ff-start')} only if you want a command primer or connection troubleshooting.`,\n `If connection fails, run ${pc.cyan('forcefield doctor')} in terminal for diagnostics.`,\n dashboardHint,\n ];\n\n if (ide === 'claude-code') {\n return [\n ...common,\n `If tools are missing, run ${pc.cyan('/mcp')} and confirm ${pc.cyan('forcefield')} is connected.`,\n ];\n }\n\n return common;\n}\n\nfunction showSuccess(ide: Ide, mode: SetupMode, projectDir: string): void {\n const adapter = getAdapter(ide);\n const workflowStatus =\n mode === 'full'\n ? `${pc.green('✓')} Project workflow commands installed`\n : `${pc.yellow('•')} Core mode selected (no slash-command workflows installed)`;\n\n p.note(\n [\n `${pc.green('✓')} MCP server configured`,\n workflowStatus,\n `${pc.green('✓')} IDE: ${adapter.name}`,\n ].join('\\n'),\n 'Setup Complete',\n );\n\n p.outro(getPostSetupInstructions(ide, mode, projectDir).join('\\n'));\n}\n\n// === Config File ===\n\nasync function readConfig(projectDir: string): Promise<SetupConfig | null> {\n const configPath = join(projectDir, CONFIG_FILE);\n try {\n await access(configPath);\n const raw = await readFile(configPath, 'utf-8');\n return JSON.parse(raw) as SetupConfig;\n } catch {\n return null;\n }\n}\n\nasync function writeConfig(projectDir: string, config: SetupConfig): Promise<void> {\n const configPath = join(projectDir, CONFIG_FILE);\n await writeFile(configPath, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n}\n\nexport {\n readConfig,\n writeConfig,\n CONFIG_FILE,\n VERSION,\n BANNER_FONT,\n BANNER_MIN_COLUMNS,\n BANNER_GRADIENT_STOPS,\n showBanner,\n applyBannerGradient,\n getPostSetupInstructions,\n inspectMcpConfig,\n inspectJsonMcpConfig,\n inspectCodexMcpConfig,\n extractTomlValue,\n};\n","/**\n * setup/ide-detect.ts — Auto-detect IDE from project directory markers.\n */\n\nimport { access } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { Ide } from './types.js';\n\ninterface DetectionResult {\n detected: Ide | null;\n markers: Array<{ ide: Ide; marker: string }>;\n}\n\nconst IDE_MARKERS: Array<{ ide: Ide; marker: string; isDir: boolean }> = [\n { ide: 'claude-code', marker: '.claude', isDir: true },\n { ide: 'cursor', marker: '.cursor', isDir: true },\n { ide: 'codex', marker: 'AGENTS.md', isDir: false },\n { ide: 'windsurf', marker: '.windsurfrules', isDir: false },\n];\n\nexport async function detectIde(projectDir: string): Promise<DetectionResult> {\n const found: Array<{ ide: Ide; marker: string }> = [];\n\n for (const { ide, marker } of IDE_MARKERS) {\n const markerPath = join(projectDir, marker);\n try {\n await access(markerPath);\n found.push({ ide, marker });\n } catch {\n // Marker not found — skip\n }\n }\n\n return {\n detected: found.length === 1 ? found[0]!.ide : null,\n markers: found,\n };\n}\n\nexport { IDE_MARKERS };\n","/**\n * IDE adapter for Claude Code.\n * Workflows → .claude/commands/ff-*.md\n * MCP → project-scoped .mcp.json entry\n */\n\nimport { mkdir, readdir, copyFile, rm, readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { IdeAdapter } from '../types.js';\nimport { buildMcpEnv, getMcpLaunchConfig } from './mcp-runtime.js';\n\nexport const claudeCodeAdapter: IdeAdapter = {\n name: 'Claude Code',\n\n async configureMcp(projectDir: string, apiKey: string): Promise<void> {\n // Ensure Claude config folder exists for slash-command workflows.\n const claudeDir = join(projectDir, '.claude');\n await mkdir(claudeDir, { recursive: true });\n\n // Configure project-scoped MCP entry used by Claude Code.\n const launch = await getMcpLaunchConfig();\n const mcpPath = join(projectDir, '.mcp.json');\n\n let existing: Record<string, unknown> = {};\n try {\n existing = JSON.parse(await readFile(mcpPath, 'utf-8')) as Record<string, unknown>;\n } catch {\n // file missing/invalid: start fresh\n }\n\n const existingServers =\n typeof existing.mcpServers === 'object' && existing.mcpServers != null\n ? (existing.mcpServers as Record<string, unknown>)\n : {};\n\n existingServers.forcefield = {\n command: launch.command,\n args: launch.args,\n env: buildMcpEnv(apiKey),\n };\n\n const nextConfig = {\n ...existing,\n mcpServers: existingServers,\n };\n\n await writeFile(mcpPath, JSON.stringify(nextConfig, null, 2) + '\\n', 'utf-8');\n },\n\n async installWorkflows(projectDir: string, workflowsDir: string): Promise<number> {\n const commandsDir = join(projectDir, '.claude', 'commands');\n await mkdir(commandsDir, { recursive: true });\n\n const files = await readdir(workflowsDir);\n const mdFiles = files.filter((f) => f.startsWith('ff-') && f.endsWith('.md'));\n\n for (const file of mdFiles) {\n await copyFile(join(workflowsDir, file), join(commandsDir, file));\n }\n\n return mdFiles.length;\n },\n\n async removeWorkflows(projectDir: string): Promise<void> {\n const commandsDir = join(projectDir, '.claude', 'commands');\n try {\n const files = await readdir(commandsDir);\n for (const file of files) {\n if (file.startsWith('ff-') && file.endsWith('.md')) {\n await rm(join(commandsDir, file));\n }\n }\n } catch {\n // Directory doesn't exist — nothing to remove\n }\n },\n};\n","import { access } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst LOCAL_ENTRY_CANDIDATES = [\n join(__dirname, '..', '..', 'build', 'index.js'),\n join(__dirname, '..', '..', 'index.js'),\n];\nconst RUNNING_FROM_NODE_MODULES = __dirname.includes('node_modules');\n\nconst FORWARDED_ENV_KEYS = [\n 'SUPABASE_URL',\n 'SUPABASE_ANON_KEY',\n 'FORCEFIELD_LOCAL_DEV',\n 'FORCEFIELD_DISABLE_GATING',\n 'FORCEFIELD_LOCAL_DATA_FALLBACK',\n] as const;\n\nfunction isTruthy(value: string | undefined): boolean {\n if (!value) return false;\n const normalized = value.trim().toLowerCase();\n return normalized === '1' || normalized === 'true' || normalized === 'yes' || normalized === 'on';\n}\n\nasync function resolveLocalEntry(): Promise<string | null> {\n for (const candidate of LOCAL_ENTRY_CANDIDATES) {\n try {\n await access(candidate);\n return candidate;\n } catch {\n // try next candidate\n }\n }\n return null;\n}\n\nexport async function getMcpLaunchConfig(): Promise<{ command: string; args: string[] }> {\n if (\n RUNNING_FROM_NODE_MODULES\n || isTruthy(process.env.FORCEFIELD_LOCAL_DEV)\n || isTruthy(process.env.FORCEFIELD_SETUP_USE_LOCAL_BUILD)\n ) {\n const localEntry = await resolveLocalEntry();\n if (localEntry) {\n return {\n command: process.execPath,\n args: [localEntry],\n };\n }\n }\n\n return {\n command: 'npx',\n args: ['-y', '-p', '@forcefield/mcp-server', 'forcefield-mcp'],\n };\n}\n\nexport function buildMcpEnv(apiKey: string): Record<string, string> {\n const env: Record<string, string> = {\n FORCEFIELD_API_KEY: apiKey,\n };\n\n for (const key of FORWARDED_ENV_KEYS) {\n const value = process.env[key];\n if (value && value.trim().length > 0) {\n env[key] = value;\n }\n }\n\n return env;\n}\n","/**\n * IDE adapter for Cursor.\n * Workflows → .cursor/rules/ff-*.md\n * MCP → .cursor/mcp.json\n */\n\nimport { mkdir, readdir, copyFile, rm, readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { IdeAdapter } from '../types.js';\nimport { buildMcpEnv, getMcpLaunchConfig } from './mcp-runtime.js';\n\ntype CursorMcpConfig = {\n mcpServers?: Record<string, { command: string; args: string[]; env?: Record<string, string> }>;\n};\n\nexport const cursorAdapter: IdeAdapter = {\n name: 'Cursor',\n\n async configureMcp(projectDir: string, apiKey: string): Promise<void> {\n const cursorDir = join(projectDir, '.cursor');\n await mkdir(cursorDir, { recursive: true });\n\n const configPath = join(cursorDir, 'mcp.json');\n const launch = await getMcpLaunchConfig();\n\n let existing: CursorMcpConfig = {};\n try {\n existing = JSON.parse(await readFile(configPath, 'utf-8')) as CursorMcpConfig;\n } catch {\n // file missing/invalid: overwrite with fresh config\n }\n\n const existingServers =\n typeof existing.mcpServers === 'object' && existing.mcpServers != null\n ? existing.mcpServers\n : {};\n\n existingServers.forcefield = {\n command: launch.command,\n args: launch.args,\n env: buildMcpEnv(apiKey),\n };\n\n const merged: CursorMcpConfig = {\n ...existing,\n mcpServers: existingServers,\n };\n\n await writeFile(configPath, JSON.stringify(merged, null, 2) + '\\n', 'utf-8');\n },\n\n async installWorkflows(projectDir: string, workflowsDir: string): Promise<number> {\n const rulesDir = join(projectDir, '.cursor', 'rules');\n await mkdir(rulesDir, { recursive: true });\n\n const files = await readdir(workflowsDir);\n const mdFiles = files.filter((f) => f.startsWith('ff-') && f.endsWith('.md'));\n\n for (const file of mdFiles) {\n await copyFile(join(workflowsDir, file), join(rulesDir, file));\n }\n\n return mdFiles.length;\n },\n\n async removeWorkflows(projectDir: string): Promise<void> {\n const rulesDir = join(projectDir, '.cursor', 'rules');\n try {\n const files = await readdir(rulesDir);\n for (const file of files) {\n if (file.startsWith('ff-') && file.endsWith('.md')) {\n await rm(join(rulesDir, file));\n }\n }\n } catch {\n // Directory doesn't exist\n }\n },\n};\n","/**\n * IDE adapter for Codex (OpenAI).\n * Workflows → appended to AGENTS.md with markers\n * MCP → .codex/config.toml or project-level config\n */\n\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { IdeAdapter } from '../types.js';\nimport { buildMcpEnv, getMcpLaunchConfig } from './mcp-runtime.js';\n\nconst START_MARKER = '<!-- forcefield:start -->';\nconst END_MARKER = '<!-- forcefield:end -->';\nconst MCP_START_MARKER = '# forcefield:mcp:start';\nconst MCP_END_MARKER = '# forcefield:mcp:end';\n\nexport const codexAdapter: IdeAdapter = {\n name: 'Codex',\n\n async configureMcp(projectDir: string, apiKey: string): Promise<void> {\n const codexDir = join(projectDir, '.codex');\n await mkdir(codexDir, { recursive: true });\n\n const configPath = join(codexDir, 'config.toml');\n const launch = await getMcpLaunchConfig();\n const env = buildMcpEnv(apiKey);\n\n const forcefieldBlock = buildForcefieldTomlBlock(launch.command, launch.args, env);\n\n let existing = '';\n try {\n existing = await readFile(configPath, 'utf-8');\n } catch {\n // file missing — create new\n }\n\n const cleaned = removeTomlForcefieldSection(existing).trim();\n const final = cleaned ? `${cleaned}\\n\\n${forcefieldBlock}\\n` : `${forcefieldBlock}\\n`;\n await writeFile(configPath, final, 'utf-8');\n },\n\n async installWorkflows(projectDir: string, workflowsDir: string): Promise<number> {\n const agentsPath = join(projectDir, 'AGENTS.md');\n const { readdir } = await import('node:fs/promises');\n\n // Read all workflow files\n const files = await readdir(workflowsDir);\n const mdFiles = files.filter((f) => f.startsWith('ff-') && f.endsWith('.md'));\n\n const workflowContents: string[] = [];\n for (const file of mdFiles) {\n const content = await readFile(join(workflowsDir, file), 'utf-8');\n workflowContents.push(content);\n }\n\n const forcefieldSection = [\n START_MARKER,\n '',\n '# Forcefield Workflows',\n '',\n 'The following workflows are available for compliance management:',\n '',\n ...workflowContents.map((c) => c + '\\n\\n---\\n'),\n END_MARKER,\n ].join('\\n');\n\n // Read existing AGENTS.md or create new\n let existing = '';\n try {\n existing = await readFile(agentsPath, 'utf-8');\n } catch {\n // File doesn't exist — will create\n }\n\n // Remove existing Forcefield section if present\n const cleaned = removeSection(existing);\n\n // Append new section\n const final = cleaned.trim()\n ? cleaned.trim() + '\\n\\n' + forcefieldSection\n : forcefieldSection;\n\n await writeFile(agentsPath, final, 'utf-8');\n return mdFiles.length;\n },\n\n async removeWorkflows(projectDir: string): Promise<void> {\n const agentsPath = join(projectDir, 'AGENTS.md');\n try {\n const content = await readFile(agentsPath, 'utf-8');\n const cleaned = removeSection(content);\n await writeFile(agentsPath, cleaned, 'utf-8');\n } catch {\n // File doesn't exist — nothing to remove\n }\n },\n};\n\nfunction removeSection(content: string): string {\n const startIdx = content.indexOf(START_MARKER);\n const endIdx = content.indexOf(END_MARKER);\n\n if (startIdx === -1 || endIdx === -1) return content;\n\n const before = content.slice(0, startIdx).trimEnd();\n const after = content.slice(endIdx + END_MARKER.length).trimStart();\n\n return before + (after ? '\\n\\n' + after : '');\n}\n\nfunction removeTomlForcefieldSection(content: string): string {\n const markerStart = content.indexOf(MCP_START_MARKER);\n const markerEnd = content.indexOf(MCP_END_MARKER);\n\n if (markerStart !== -1 && markerEnd !== -1) {\n const before = content.slice(0, markerStart).trimEnd();\n const after = content.slice(markerEnd + MCP_END_MARKER.length).trimStart();\n return before + (after ? '\\n\\n' + after : '');\n }\n\n // Backward-compatible cleanup if a previous config wrote unmanaged sections.\n return content\n .replace(/^\\[mcp_servers\\.forcefield\\]\\n[\\s\\S]*?(?=^\\[|$)/gm, '')\n .replace(/^\\[mcp_servers\\.forcefield\\.env\\]\\n[\\s\\S]*?(?=^\\[|$)/gm, '')\n .trim();\n}\n\nfunction buildForcefieldTomlBlock(\n command: string,\n args: string[],\n env: Record<string, string>,\n): string {\n const envLines = Object.entries(env)\n .map(([key, value]) => `${key} = \"${escapeTomlString(value)}\"`);\n\n return [\n MCP_START_MARKER,\n '[mcp_servers.forcefield]',\n `command = \"${escapeTomlString(command)}\"`,\n `args = [${args.map((arg) => `\"${escapeTomlString(arg)}\"`).join(', ')}]`,\n '[mcp_servers.forcefield.env]',\n ...envLines,\n MCP_END_MARKER,\n ].join('\\n');\n}\n\nfunction escapeTomlString(value: string): string {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n}\n","/**\n * IDE adapter for Windsurf.\n * Workflows → appended to .windsurfrules with markers\n * MCP → Windsurf MCP config\n */\n\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { IdeAdapter } from '../types.js';\nimport { buildMcpEnv, getMcpLaunchConfig } from './mcp-runtime.js';\n\nconst START_MARKER = '<!-- forcefield:start -->';\nconst END_MARKER = '<!-- forcefield:end -->';\n\nexport const windsurfAdapter: IdeAdapter = {\n name: 'Windsurf',\n\n async configureMcp(projectDir: string, apiKey: string): Promise<void> {\n const configDir = join(projectDir, '.windsurf');\n await mkdir(configDir, { recursive: true });\n\n const configPath = join(configDir, 'mcp_config.json');\n const launch = await getMcpLaunchConfig();\n\n let existing: Record<string, unknown> = {};\n try {\n existing = JSON.parse(await readFile(configPath, 'utf-8')) as Record<string, unknown>;\n } catch {\n // file missing/invalid: start fresh\n }\n\n const existingServers =\n typeof existing.mcpServers === 'object' && existing.mcpServers != null\n ? (existing.mcpServers as Record<string, unknown>)\n : {};\n\n existingServers.forcefield = {\n command: launch.command,\n args: launch.args,\n env: buildMcpEnv(apiKey),\n };\n\n const merged = {\n ...existing,\n mcpServers: existingServers,\n };\n\n await writeFile(configPath, JSON.stringify(merged, null, 2) + '\\n', 'utf-8');\n },\n\n async installWorkflows(projectDir: string, workflowsDir: string): Promise<number> {\n const rulesPath = join(projectDir, '.windsurfrules');\n const { readdir } = await import('node:fs/promises');\n\n const files = await readdir(workflowsDir);\n const mdFiles = files.filter((f) => f.startsWith('ff-') && f.endsWith('.md'));\n\n const workflowContents: string[] = [];\n for (const file of mdFiles) {\n const content = await readFile(join(workflowsDir, file), 'utf-8');\n workflowContents.push(content);\n }\n\n const forcefieldSection = [\n START_MARKER,\n '',\n '# Forcefield Workflows',\n '',\n ...workflowContents.map((c) => c + '\\n\\n---\\n'),\n END_MARKER,\n ].join('\\n');\n\n let existing = '';\n try {\n existing = await readFile(rulesPath, 'utf-8');\n } catch {\n // File doesn't exist\n }\n\n const cleaned = removeSection(existing);\n const final = cleaned.trim()\n ? cleaned.trim() + '\\n\\n' + forcefieldSection\n : forcefieldSection;\n\n await writeFile(rulesPath, final, 'utf-8');\n return mdFiles.length;\n },\n\n async removeWorkflows(projectDir: string): Promise<void> {\n const rulesPath = join(projectDir, '.windsurfrules');\n try {\n const content = await readFile(rulesPath, 'utf-8');\n const cleaned = removeSection(content);\n await writeFile(rulesPath, cleaned, 'utf-8');\n } catch {\n // File doesn't exist\n }\n },\n};\n\nfunction removeSection(content: string): string {\n const startIdx = content.indexOf(START_MARKER);\n const endIdx = content.indexOf(END_MARKER);\n\n if (startIdx === -1 || endIdx === -1) return content;\n\n const before = content.slice(0, startIdx).trimEnd();\n const after = content.slice(endIdx + END_MARKER.length).trimStart();\n\n return before + (after ? '\\n\\n' + after : '');\n}\n","/**\n * IDE adapter registry.\n */\n\nimport type { Ide, IdeAdapter } from '../types.js';\nimport { claudeCodeAdapter } from './claude-code.js';\nimport { cursorAdapter } from './cursor.js';\nimport { codexAdapter } from './codex.js';\nimport { windsurfAdapter } from './windsurf.js';\n\nconst adapters: Record<Ide, IdeAdapter> = {\n 'claude-code': claudeCodeAdapter,\n 'cursor': cursorAdapter,\n 'codex': codexAdapter,\n 'windsurf': windsurfAdapter,\n};\n\nexport function getAdapter(ide: Ide): IdeAdapter {\n return adapters[ide];\n}\n\nexport const IDE_CHOICES: Array<{ value: Ide; label: string; hint: string }> = [\n { value: 'claude-code', label: 'Claude Code', hint: '.claude/commands/' },\n { value: 'cursor', label: 'Cursor', hint: '.cursor/rules/' },\n { value: 'codex', label: 'Codex (OpenAI)', hint: 'AGENTS.md' },\n { value: 'windsurf', label: 'Windsurf', hint: '.windsurfrules' },\n];\n","/**\n * setup/auth.ts — Authentication and API key issuance for setup wizard.\n */\n\nimport { createHash, randomBytes } from 'node:crypto';\nimport { createClient } from '@supabase/supabase-js';\nimport {\n LOCAL_SUPABASE_ANON_KEY,\n LOCAL_SUPABASE_SERVICE_ROLE_KEY,\n PRODUCTION_SUPABASE_PUBLISHABLE_KEY,\n PRODUCTION_SUPABASE_URL,\n} from '../src/supabase-defaults.js';\n\nconst API_KEY_PREFIX = 'ff_live_';\nconst MAX_RETRIES = 3;\n\nexport interface AuthResult {\n valid: boolean;\n apiKey: string;\n error?: string;\n}\n\nexport interface LocalAuthResult {\n apiKey: string;\n userId: string;\n email: string;\n}\n\ninterface SetupAuthOptions {\n supabaseUrl?: string;\n anonKey?: string;\n localDev?: boolean;\n}\n\nfunction isTruthy(value: string | undefined): boolean {\n if (!value) return false;\n const normalized = value.trim().toLowerCase();\n return normalized === '1' || normalized === 'true' || normalized === 'yes' || normalized === 'on';\n}\n\nfunction getSupabaseUrl(options?: SetupAuthOptions): string {\n return options?.supabaseUrl ?? process.env.SUPABASE_URL ?? PRODUCTION_SUPABASE_URL;\n}\n\nfunction isLocalSupabaseUrl(supabaseUrl: string): boolean {\n try {\n const parsed = new URL(supabaseUrl);\n return parsed.hostname === '127.0.0.1' || parsed.hostname === 'localhost';\n } catch {\n return false;\n }\n}\n\nfunction isLocalMode(options?: SetupAuthOptions): boolean {\n if (options?.localDev !== undefined) return options.localDev;\n if (isTruthy(process.env.FORCEFIELD_LOCAL_DEV)) return true;\n return isLocalSupabaseUrl(getSupabaseUrl(options));\n}\n\nfunction getAnonKey(supabaseUrl: string, options?: SetupAuthOptions): string {\n const explicit = options?.anonKey ?? process.env.SUPABASE_ANON_KEY;\n if (explicit && explicit.trim().length > 0) return explicit;\n\n if (isLocalSupabaseUrl(supabaseUrl)) {\n return LOCAL_SUPABASE_ANON_KEY;\n }\n\n return PRODUCTION_SUPABASE_PUBLISHABLE_KEY;\n}\n\nfunction getServiceRoleKey(supabaseUrl: string): string | null {\n const explicit = process.env.SUPABASE_SERVICE_ROLE_KEY;\n if (explicit && explicit.trim().length > 0) return explicit;\n\n if (isLocalSupabaseUrl(supabaseUrl)) {\n return LOCAL_SUPABASE_SERVICE_ROLE_KEY;\n }\n\n return null;\n}\n\n/**\n * Validate API key format.\n */\nexport function validateApiKeyFormat(key: string): boolean {\n return key.startsWith(API_KEY_PREFIX) && key.length > API_KEY_PREFIX.length + 8;\n}\n\n/**\n * Verify an API key through key-exchange endpoint.\n */\nexport async function verifyApiKey(apiKey: string, options?: SetupAuthOptions): Promise<AuthResult> {\n if (!validateApiKeyFormat(apiKey)) {\n return {\n valid: false,\n apiKey: '',\n error: 'Invalid API key format. Keys must start with \"ff_live_\".',\n };\n }\n\n const supabaseUrl = getSupabaseUrl(options);\n const endpoint = `${supabaseUrl}/functions/v1/key-exchange`;\n\n try {\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${apiKey}`,\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n const payload = await response.json().catch(() => ({})) as { error?: string };\n const detail = payload.error ?? 'API key invalid or revoked.';\n return {\n valid: false,\n apiKey: '',\n error: `Authentication failed (${response.status}): ${detail}`,\n };\n }\n\n return { valid: true, apiKey };\n } catch {\n return {\n valid: false,\n apiKey: '',\n error: `Could not reach Forcefield backend at ${supabaseUrl}. Check SUPABASE_URL/network and retry.`,\n };\n }\n}\n\n/**\n * Authenticate with retries.\n */\nexport async function authenticateWithRetry(\n getKey: () => Promise<string | null>,\n options?: SetupAuthOptions,\n): Promise<AuthResult> {\n let lastError: string | undefined;\n\n for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {\n const key = await getKey();\n\n if (!key) {\n return { valid: false, apiKey: '', error: 'No API key provided.' };\n }\n\n const verified = await verifyApiKey(key, options);\n if (verified.valid) {\n return verified;\n }\n\n lastError = verified.error;\n\n if (attempt < MAX_RETRIES) {\n continue;\n }\n }\n\n return {\n valid: false,\n apiKey: '',\n error: lastError ?? `Authentication failed after ${MAX_RETRIES} attempts.`,\n };\n}\n\nfunction generateApiKey(): { plaintext: string; hash: string; prefix: string } {\n const raw = randomBytes(32).toString('hex');\n const plaintext = `${API_KEY_PREFIX}${raw}`;\n const hash = createHash('sha256').update(plaintext).digest('hex');\n const prefix = plaintext.slice(0, 12);\n return { plaintext, hash, prefix };\n}\n\n/**\n * Hosted/local account flow:\n * 1. Sign in (or sign up + sign in)\n * 2. Insert API key under authenticated user\n */\nexport async function authenticateAccountAndCreateApiKey(\n email: string,\n password: string,\n options?: {\n supabaseUrl?: string;\n anonKey?: string;\n label?: string;\n localDev?: boolean;\n },\n): Promise<LocalAuthResult> {\n const supabaseUrl = getSupabaseUrl(options);\n const anonKey = getAnonKey(supabaseUrl, options);\n\n const supabase = createClient(supabaseUrl, anonKey, {\n auth: {\n persistSession: false,\n autoRefreshToken: false,\n },\n });\n\n let signIn = await supabase.auth.signInWithPassword({ email, password });\n\n if (signIn.error || !signIn.data.user) {\n await supabase.auth.signUp({ email, password });\n signIn = await supabase.auth.signInWithPassword({ email, password });\n }\n\n if (signIn.error || !signIn.data.user) {\n const message = signIn.error?.message ?? 'Invalid login credentials';\n throw new Error(`Authentication failed: ${message}`);\n }\n\n const userId = signIn.data.user.id;\n const { plaintext, hash, prefix } = generateApiKey();\n const { error: insertError } = await supabase\n .from('api_keys')\n .insert({\n user_id: userId,\n key_hash: hash,\n key_prefix: prefix,\n label: options?.label ?? 'Setup Wizard Key',\n tier: 'free',\n });\n\n if (insertError) {\n if (isLocalMode(options)) {\n const serviceRoleKey = getServiceRoleKey(supabaseUrl);\n if (serviceRoleKey) {\n return createApiKeyViaServiceRole({\n supabaseUrl,\n serviceRoleKey,\n email,\n password,\n label: options?.label ?? 'Setup Wizard Key',\n });\n }\n }\n\n throw new Error(`Failed to create API key: ${insertError.message}`);\n }\n\n return {\n apiKey: plaintext,\n userId,\n email,\n };\n}\n\n/**\n * Local auth flow preserved for scripted local development.\n */\nexport async function authenticateLocalAndCreateApiKey(\n email: string,\n password: string,\n options?: { supabaseUrl?: string; anonKey?: string; label?: string },\n): Promise<LocalAuthResult> {\n return authenticateAccountAndCreateApiKey(email, password, {\n ...options,\n localDev: true,\n label: options?.label ?? 'Local Setup Key',\n });\n}\n\nasync function createApiKeyViaServiceRole(params: {\n supabaseUrl: string;\n serviceRoleKey: string;\n email: string;\n password: string;\n label: string;\n}): Promise<LocalAuthResult> {\n const admin = createClient(params.supabaseUrl, params.serviceRoleKey, {\n auth: {\n persistSession: false,\n autoRefreshToken: false,\n },\n });\n\n let userId: string | undefined;\n const createUser = await admin.auth.admin.createUser({\n email: params.email,\n password: params.password,\n email_confirm: true,\n });\n\n if (createUser.data.user?.id) {\n userId = createUser.data.user.id;\n } else if (createUser.error) {\n const authDb = createClient(params.supabaseUrl, params.serviceRoleKey, {\n db: { schema: 'auth' },\n auth: {\n persistSession: false,\n autoRefreshToken: false,\n },\n });\n\n const existingUser = await authDb\n .from('users')\n .select('id,email')\n .eq('email', params.email)\n .limit(1)\n .maybeSingle();\n\n if (existingUser.error) {\n throw new Error(`Local login failed: ${createUser.error.message}`);\n }\n userId = existingUser.data?.id;\n }\n\n if (!userId) {\n throw new Error('Local login failed: could not resolve user account');\n }\n\n const { plaintext, hash, prefix } = generateApiKey();\n const { error: insertError } = await admin.from('api_keys').insert({\n user_id: userId,\n key_hash: hash,\n key_prefix: prefix,\n label: params.label,\n tier: 'free',\n });\n\n if (insertError) {\n throw new Error(`Failed to create local API key: ${insertError.message}`);\n }\n\n return {\n apiKey: plaintext,\n userId,\n email: params.email,\n };\n}\n\nexport { API_KEY_PREFIX, MAX_RETRIES };\n","/**\n * Forcefield Setup Wizard — entry point.\n *\n * This is the setup wizard binary (forcefield-setup), invoked via\n * `npx -y -p @forcefield/mcp-server forcefield setup`.\n * Parses CLI arguments and launches the interactive wizard.\n */\n\nimport type { CliArgs, Ide, SetupMode } from './types.js';\nimport { runWizard } from './wizard.js';\nimport { pathToFileURL } from 'node:url';\n\nfunction parseArgs(argv: string[]): CliArgs {\n const args: CliArgs = {};\n\n for (let i = 2; i < argv.length; i++) {\n const arg = argv[i]!;\n\n if (arg === '--status') {\n args.status = true;\n } else if (arg === '--doctor') {\n args.doctor = true;\n } else if (arg === '--ide' && argv[i + 1]) {\n const ide = argv[++i]!;\n if (['claude-code', 'cursor', 'codex', 'windsurf'].includes(ide)) {\n args.ide = ide as Ide;\n }\n } else if (arg === '--mode' && argv[i + 1]) {\n const mode = argv[++i]!;\n if (['full', 'core'].includes(mode)) {\n args.mode = mode as SetupMode;\n }\n } else if (arg === '--token' && argv[i + 1]) {\n args.token = argv[++i]!;\n } else if (arg === '--email' && argv[i + 1]) {\n args.email = argv[++i]!;\n } else if (arg === '--password' && argv[i + 1]) {\n args.password = argv[++i]!;\n } else if (arg === '--local-auth') {\n args.localAuth = true;\n }\n }\n\n return args;\n}\n\nasync function main(): Promise<void> {\n const args = parseArgs(process.argv);\n const projectDir = process.cwd();\n\n try {\n await runWizard(projectDir, args);\n } catch (err) {\n console.error('Setup failed:', err instanceof Error ? err.message : err);\n process.exit(1);\n }\n}\n\nexport async function runSetupCli(argv: string[] = process.argv): Promise<void> {\n const originalArgv = process.argv;\n process.argv = argv;\n try {\n await main();\n } finally {\n process.argv = originalArgv;\n }\n}\n\nfunction isExecutedDirectly(metaUrl: string): boolean {\n const entryPath = process.argv[1];\n if (!entryPath) return false;\n return metaUrl === pathToFileURL(entryPath).href;\n}\n\nif (isExecutedDirectly(import.meta.url)) {\n void runSetupCli();\n}\n\nexport { parseArgs };\n"],"mappings":"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","names":["readFile","writeFile","access","join","dirname","fileURLToPath","join","access","join","join","mkdir","readdir","copyFile","rm","readFile","writeFile","join","join","mkdir","readFile","writeFile","readdir","copyFile","rm","mkdir","readFile","writeFile","join","join","mkdir","readFile","writeFile","readdir","mkdir","readFile","writeFile","join","START_MARKER","END_MARKER","join","mkdir","readFile","writeFile","readdir","removeSection","isTruthy","__dirname","dirname","fileURLToPath","join","access","text","readFile","apiKey","confirm","writeFile"]}
|