jfl 0.1.0 ā 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +443 -145
- package/clawdbot-plugin/clawdbot.plugin.json +20 -0
- package/clawdbot-plugin/index.js +555 -0
- package/clawdbot-plugin/index.ts +582 -0
- package/clawdbot-skill/SKILL.md +33 -336
- package/clawdbot-skill/index.ts +491 -321
- package/clawdbot-skill/skill.json +4 -13
- package/dist/commands/clawdbot.d.ts +11 -0
- package/dist/commands/clawdbot.d.ts.map +1 -0
- package/dist/commands/clawdbot.js +215 -0
- package/dist/commands/clawdbot.js.map +1 -0
- package/dist/commands/context-hub.d.ts +5 -0
- package/dist/commands/context-hub.d.ts.map +1 -1
- package/dist/commands/context-hub.js +394 -28
- package/dist/commands/context-hub.js.map +1 -1
- package/dist/commands/gtm-process-update.d.ts +10 -0
- package/dist/commands/gtm-process-update.d.ts.map +1 -0
- package/dist/commands/gtm-process-update.js +101 -0
- package/dist/commands/gtm-process-update.js.map +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +278 -4
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +32 -33
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/memory.d.ts +38 -0
- package/dist/commands/memory.d.ts.map +1 -0
- package/dist/commands/memory.js +229 -0
- package/dist/commands/memory.js.map +1 -0
- package/dist/commands/migrate-services.d.ts +8 -0
- package/dist/commands/migrate-services.d.ts.map +1 -0
- package/dist/commands/migrate-services.js +182 -0
- package/dist/commands/migrate-services.js.map +1 -0
- package/dist/commands/onboard.d.ts +24 -0
- package/dist/commands/onboard.d.ts.map +1 -0
- package/dist/commands/onboard.js +663 -0
- package/dist/commands/onboard.js.map +1 -0
- package/dist/commands/openclaw.d.ts +56 -0
- package/dist/commands/openclaw.d.ts.map +1 -0
- package/dist/commands/openclaw.js +700 -0
- package/dist/commands/openclaw.js.map +1 -0
- package/dist/commands/orchestrate.d.ts +14 -0
- package/dist/commands/orchestrate.d.ts.map +1 -0
- package/dist/commands/orchestrate.js +270 -0
- package/dist/commands/orchestrate.js.map +1 -0
- package/dist/commands/profile.d.ts +46 -0
- package/dist/commands/profile.d.ts.map +1 -0
- package/dist/commands/profile.js +498 -0
- package/dist/commands/profile.js.map +1 -0
- package/dist/commands/repair.d.ts.map +1 -1
- package/dist/commands/repair.js +37 -0
- package/dist/commands/repair.js.map +1 -1
- package/dist/commands/service-agent.d.ts +16 -0
- package/dist/commands/service-agent.d.ts.map +1 -0
- package/dist/commands/service-agent.js +375 -0
- package/dist/commands/service-agent.js.map +1 -0
- package/dist/commands/service-manager.d.ts +12 -0
- package/dist/commands/service-manager.d.ts.map +1 -0
- package/dist/commands/service-manager.js +967 -0
- package/dist/commands/service-manager.js.map +1 -0
- package/dist/commands/service-validate.d.ts +12 -0
- package/dist/commands/service-validate.d.ts.map +1 -0
- package/dist/commands/service-validate.js +611 -0
- package/dist/commands/service-validate.js.map +1 -0
- package/dist/commands/services-create.d.ts +15 -0
- package/dist/commands/services-create.d.ts.map +1 -0
- package/dist/commands/services-create.js +1452 -0
- package/dist/commands/services-create.js.map +1 -0
- package/dist/commands/services-scan.d.ts +13 -0
- package/dist/commands/services-scan.d.ts.map +1 -0
- package/dist/commands/services-scan.js +251 -0
- package/dist/commands/services-scan.js.map +1 -0
- package/dist/commands/services-sync-agents.d.ts +23 -0
- package/dist/commands/services-sync-agents.d.ts.map +1 -0
- package/dist/commands/services-sync-agents.js +207 -0
- package/dist/commands/services-sync-agents.js.map +1 -0
- package/dist/commands/services.d.ts +19 -0
- package/dist/commands/services.d.ts.map +1 -0
- package/dist/commands/services.js +742 -0
- package/dist/commands/services.js.map +1 -0
- package/dist/commands/session.d.ts +5 -1
- package/dist/commands/session.d.ts.map +1 -1
- package/dist/commands/session.js +68 -586
- package/dist/commands/session.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +17 -0
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +75 -21
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/validate-settings.d.ts +37 -0
- package/dist/commands/validate-settings.d.ts.map +1 -0
- package/dist/commands/validate-settings.js +197 -0
- package/dist/commands/validate-settings.js.map +1 -0
- package/dist/commands/voice.d.ts +0 -1
- package/dist/commands/voice.d.ts.map +1 -1
- package/dist/commands/voice.js +16 -15
- package/dist/commands/voice.js.map +1 -1
- package/dist/index.js +395 -141
- package/dist/index.js.map +1 -1
- package/dist/lib/agent-generator.d.ts +26 -0
- package/dist/lib/agent-generator.d.ts.map +1 -0
- package/dist/lib/agent-generator.js +331 -0
- package/dist/lib/agent-generator.js.map +1 -0
- package/dist/lib/memory-db.d.ts +102 -0
- package/dist/lib/memory-db.d.ts.map +1 -0
- package/dist/lib/memory-db.js +313 -0
- package/dist/lib/memory-db.js.map +1 -0
- package/dist/lib/memory-indexer.d.ts +47 -0
- package/dist/lib/memory-indexer.d.ts.map +1 -0
- package/dist/lib/memory-indexer.js +215 -0
- package/dist/lib/memory-indexer.js.map +1 -0
- package/dist/lib/memory-search.d.ts +41 -0
- package/dist/lib/memory-search.d.ts.map +1 -0
- package/dist/lib/memory-search.js +246 -0
- package/dist/lib/memory-search.js.map +1 -0
- package/dist/lib/openclaw-registry.d.ts +48 -0
- package/dist/lib/openclaw-registry.d.ts.map +1 -0
- package/dist/lib/openclaw-registry.js +181 -0
- package/dist/lib/openclaw-registry.js.map +1 -0
- package/dist/lib/openclaw-sdk.d.ts +107 -0
- package/dist/lib/openclaw-sdk.d.ts.map +1 -0
- package/dist/lib/openclaw-sdk.js +208 -0
- package/dist/lib/openclaw-sdk.js.map +1 -0
- package/dist/lib/peer-agent-generator.d.ts +44 -0
- package/dist/lib/peer-agent-generator.d.ts.map +1 -0
- package/dist/lib/peer-agent-generator.js +286 -0
- package/dist/lib/peer-agent-generator.js.map +1 -0
- package/dist/lib/service-dependencies.d.ts +44 -0
- package/dist/lib/service-dependencies.d.ts.map +1 -0
- package/dist/lib/service-dependencies.js +314 -0
- package/dist/lib/service-dependencies.js.map +1 -0
- package/dist/lib/service-detector.d.ts +61 -0
- package/dist/lib/service-detector.d.ts.map +1 -0
- package/dist/lib/service-detector.js +521 -0
- package/dist/lib/service-detector.js.map +1 -0
- package/dist/lib/service-gtm.d.ts +157 -0
- package/dist/lib/service-gtm.d.ts.map +1 -0
- package/dist/lib/service-gtm.js +786 -0
- package/dist/lib/service-gtm.js.map +1 -0
- package/dist/lib/service-mcp-base.d.ts +103 -0
- package/dist/lib/service-mcp-base.d.ts.map +1 -0
- package/dist/lib/service-mcp-base.js +263 -0
- package/dist/lib/service-mcp-base.js.map +1 -0
- package/dist/lib/service-utils.d.ts +103 -0
- package/dist/lib/service-utils.d.ts.map +1 -0
- package/dist/lib/service-utils.js +368 -0
- package/dist/lib/service-utils.js.map +1 -0
- package/dist/lib/skill-generator.d.ts +21 -0
- package/dist/lib/skill-generator.d.ts.map +1 -0
- package/dist/lib/skill-generator.js +253 -0
- package/dist/lib/skill-generator.js.map +1 -0
- package/dist/lib/stratus-client.d.ts +100 -0
- package/dist/lib/stratus-client.d.ts.map +1 -0
- package/dist/lib/stratus-client.js +255 -0
- package/dist/lib/stratus-client.js.map +1 -0
- package/dist/mcp/context-hub-mcp.js +135 -53
- package/dist/mcp/context-hub-mcp.js.map +1 -1
- package/dist/mcp/service-mcp-server.d.ts +12 -0
- package/dist/mcp/service-mcp-server.d.ts.map +1 -0
- package/dist/mcp/service-mcp-server.js +434 -0
- package/dist/mcp/service-mcp-server.js.map +1 -0
- package/dist/mcp/service-peer-mcp.d.ts +36 -0
- package/dist/mcp/service-peer-mcp.d.ts.map +1 -0
- package/dist/mcp/service-peer-mcp.js +220 -0
- package/dist/mcp/service-peer-mcp.js.map +1 -0
- package/dist/mcp/service-registry-mcp.d.ts +13 -0
- package/dist/mcp/service-registry-mcp.d.ts.map +1 -0
- package/dist/mcp/service-registry-mcp.js +330 -0
- package/dist/mcp/service-registry-mcp.js.map +1 -0
- package/dist/ui/banner.js +1 -1
- package/dist/ui/banner.js.map +1 -1
- package/dist/ui/context-hub-logs.d.ts +10 -0
- package/dist/ui/context-hub-logs.d.ts.map +1 -0
- package/dist/ui/context-hub-logs.js +175 -0
- package/dist/ui/context-hub-logs.js.map +1 -0
- package/dist/ui/service-dashboard.d.ts +11 -0
- package/dist/ui/service-dashboard.d.ts.map +1 -0
- package/dist/ui/service-dashboard.js +357 -0
- package/dist/ui/service-dashboard.js.map +1 -0
- package/dist/ui/services-manager.d.ts +11 -0
- package/dist/ui/services-manager.d.ts.map +1 -0
- package/dist/ui/services-manager.js +507 -0
- package/dist/ui/services-manager.js.map +1 -0
- package/dist/utils/auth-guard.d.ts.map +1 -1
- package/dist/utils/auth-guard.js +8 -9
- package/dist/utils/auth-guard.js.map +1 -1
- package/dist/utils/claude-md-generator.d.ts +10 -0
- package/dist/utils/claude-md-generator.d.ts.map +1 -0
- package/dist/utils/claude-md-generator.js +215 -0
- package/dist/utils/claude-md-generator.js.map +1 -0
- package/dist/utils/ensure-context-hub.d.ts +20 -0
- package/dist/utils/ensure-context-hub.d.ts.map +1 -0
- package/dist/utils/ensure-context-hub.js +65 -0
- package/dist/utils/ensure-context-hub.js.map +1 -0
- package/dist/utils/ensure-project.d.ts.map +1 -1
- package/dist/utils/ensure-project.js +3 -4
- package/dist/utils/ensure-project.js.map +1 -1
- package/dist/utils/jfl-config.d.ts +19 -0
- package/dist/utils/jfl-config.d.ts.map +1 -0
- package/dist/utils/jfl-config.js +112 -0
- package/dist/utils/jfl-config.js.map +1 -0
- package/dist/utils/jfl-migration.d.ts +29 -0
- package/dist/utils/jfl-migration.d.ts.map +1 -0
- package/dist/utils/jfl-migration.js +142 -0
- package/dist/utils/jfl-migration.js.map +1 -0
- package/dist/utils/jfl-paths.d.ts +55 -0
- package/dist/utils/jfl-paths.d.ts.map +1 -0
- package/dist/utils/jfl-paths.js +120 -0
- package/dist/utils/jfl-paths.js.map +1 -0
- package/dist/utils/settings-validator.d.ts +73 -0
- package/dist/utils/settings-validator.d.ts.map +1 -0
- package/dist/utils/settings-validator.js +222 -0
- package/dist/utils/settings-validator.js.map +1 -0
- package/package.json +19 -3
- package/scripts/commit-gtm.sh +56 -0
- package/scripts/commit-product.sh +68 -0
- package/scripts/context-query.sh +45 -0
- package/scripts/session/auto-commit.sh +297 -0
- package/scripts/session/jfl-doctor.sh +707 -0
- package/scripts/session/session-cleanup.sh +268 -0
- package/scripts/session/session-end.sh +198 -0
- package/scripts/session/session-init.sh +350 -0
- package/scripts/session/session-init.sh.backup +292 -0
- package/scripts/session/session-sync.sh +167 -0
- package/scripts/session/test-context-preservation.sh +160 -0
- package/scripts/session/test-critical-infrastructure.sh +293 -0
- package/scripts/session/test-experience-level.sh +336 -0
- package/scripts/session/test-session-cleanup.sh +268 -0
- package/scripts/session/test-session-sync.sh +320 -0
- package/scripts/voice-start.sh +36 -8
- package/scripts/where-am-i.sh +78 -0
- package/template/.claude/service-settings.json +32 -0
- package/template/.claude/settings.json +14 -1
- package/template/.claude/skills/end/SKILL.md +1780 -0
- package/template/.jfl/config.json +2 -1
- package/template/CLAUDE.md +1039 -134
- package/template/CLAUDE.md.bak +1187 -0
- package/template/scripts/commit-gtm.sh +56 -0
- package/template/scripts/commit-product.sh +68 -0
- package/template/scripts/migrate-to-branch-sessions.sh +201 -0
- package/template/scripts/session/auto-commit.sh +58 -6
- package/template/scripts/session/jfl-doctor.sh +137 -17
- package/template/scripts/session/session-cleanup.sh +268 -0
- package/template/scripts/session/session-end.sh +4 -0
- package/template/scripts/session/session-init.sh +253 -66
- package/template/scripts/session/test-critical-infrastructure.sh +293 -0
- package/template/scripts/session/test-experience-level.sh +336 -0
- package/template/scripts/session/test-session-cleanup.sh +268 -0
- package/template/scripts/session/test-session-sync.sh +320 -0
- package/template/scripts/where-am-i.sh +78 -0
- package/template/templates/service-agent/.claude/settings.json +32 -0
- package/template/templates/service-agent/CLAUDE.md +334 -0
- package/template/templates/service-agent/knowledge/ARCHITECTURE.md +115 -0
- package/template/templates/service-agent/knowledge/DEPLOYMENT.md +199 -0
- package/template/templates/service-agent/knowledge/RUNBOOK.md +412 -0
- package/template/templates/service-agent/knowledge/SERVICE_SPEC.md +77 -0
- package/dist/commands/session-mgmt.d.ts +0 -33
- package/dist/commands/session-mgmt.d.ts.map +0 -1
- package/dist/commands/session-mgmt.js +0 -404
- package/dist/commands/session-mgmt.js.map +0 -1
- package/template/scripts/session/auto-merge.sh +0 -325
package/dist/commands/session.js
CHANGED
|
@@ -1,25 +1,17 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
|
-
import
|
|
2
|
+
import ora from "ora";
|
|
3
3
|
import * as p from "@clack/prompts";
|
|
4
|
-
import {
|
|
5
|
-
import { existsSync, readFileSync } from "fs";
|
|
4
|
+
import { existsSync } from "fs";
|
|
6
5
|
import { join } from "path";
|
|
6
|
+
import { homedir } from "os";
|
|
7
7
|
import Conf from "conf";
|
|
8
|
-
import { ensureDayPass, isTrialMode
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
8
|
+
import { ensureDayPass, isTrialMode } from "../utils/auth-guard.js";
|
|
9
|
+
import { ensureContextHub, getContextHubConfig } from "../utils/ensure-context-hub.js";
|
|
10
|
+
import { isRunning as getContextHubStatus } from "./context-hub.js";
|
|
11
11
|
import { initCommand } from "./init.js";
|
|
12
|
+
import axios from "axios";
|
|
12
13
|
const config = new Conf({ projectName: "jfl" });
|
|
13
|
-
|
|
14
|
-
const AUTONOMOUS_FLAGS = {
|
|
15
|
-
claude: "--dangerously-skip-permissions",
|
|
16
|
-
codex: "--full-auto",
|
|
17
|
-
aider: "--yes-always",
|
|
18
|
-
none: undefined,
|
|
19
|
-
};
|
|
20
|
-
// Flag for enabling Chrome/browser capabilities (Claude only)
|
|
21
|
-
const CHROME_FLAG = "--chrome";
|
|
22
|
-
export async function sessionCommand() {
|
|
14
|
+
export async function sessionCommand(options = {}) {
|
|
23
15
|
const cwd = process.cwd();
|
|
24
16
|
// Check if in a JFL project
|
|
25
17
|
const hasJflConfig = existsSync(join(cwd, "CLAUDE.md")) || existsSync(join(cwd, "knowledge"));
|
|
@@ -32,7 +24,6 @@ export async function sessionCommand() {
|
|
|
32
24
|
console.log(chalk.yellow("\nš³ Payment required (teammates detected)\n"));
|
|
33
25
|
const dayPass = await ensureDayPass();
|
|
34
26
|
if (!dayPass) {
|
|
35
|
-
// User cancelled or failed to purchase day pass
|
|
36
27
|
console.log(chalk.red("\nā Cannot start session without active Day Pass\n"));
|
|
37
28
|
console.log(chalk.gray("Run: jfl login --x402"));
|
|
38
29
|
console.log();
|
|
@@ -49,591 +40,82 @@ export async function sessionCommand() {
|
|
|
49
40
|
projects.push(cwd);
|
|
50
41
|
config.set("projects", projects);
|
|
51
42
|
}
|
|
52
|
-
//
|
|
53
|
-
|
|
54
|
-
// Detect available CLIs
|
|
55
|
-
const available = detectAICLIs();
|
|
56
|
-
if (available.length === 0) {
|
|
57
|
-
await onboardAICLI();
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
// If preference is set and still available, use it
|
|
61
|
-
if (preferredCLI) {
|
|
62
|
-
const preferred = available.find(cli => cli.command === preferredCLI);
|
|
63
|
-
if (preferred) {
|
|
64
|
-
await launchCLI(preferred, cwd);
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
// If only one option, use it
|
|
69
|
-
if (available.length === 1) {
|
|
70
|
-
config.set("aiCLI", available[0].command);
|
|
71
|
-
await launchCLI(available[0], cwd);
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
// Multiple options - let them choose
|
|
75
|
-
console.log(chalk.bold("\nš¤ JFL - AI Session\n"));
|
|
76
|
-
console.log(chalk.gray("Multiple AI CLIs detected:\n"));
|
|
77
|
-
const { selected } = await inquirer.prompt([
|
|
78
|
-
{
|
|
79
|
-
type: "list",
|
|
80
|
-
name: "selected",
|
|
81
|
-
message: "Which AI do you want to use?",
|
|
82
|
-
choices: available.map(cli => ({
|
|
83
|
-
name: `${cli.name}${cli.version ? ` (${cli.version})` : ""}`,
|
|
84
|
-
value: cli.command,
|
|
85
|
-
})),
|
|
86
|
-
},
|
|
87
|
-
]);
|
|
88
|
-
const { remember } = await inquirer.prompt([
|
|
89
|
-
{
|
|
90
|
-
type: "confirm",
|
|
91
|
-
name: "remember",
|
|
92
|
-
message: "Remember this choice?",
|
|
93
|
-
default: true,
|
|
94
|
-
},
|
|
95
|
-
]);
|
|
96
|
-
if (remember) {
|
|
97
|
-
config.set("aiCLI", selected);
|
|
98
|
-
}
|
|
99
|
-
const cli = available.find(c => c.command === selected);
|
|
100
|
-
await launchCLI(cli, cwd);
|
|
101
|
-
}
|
|
102
|
-
function detectAICLIs() {
|
|
103
|
-
const clis = [];
|
|
104
|
-
// Claude Code
|
|
105
|
-
try {
|
|
106
|
-
const version = execSync("claude --version 2>/dev/null", { encoding: "utf-8" }).trim();
|
|
107
|
-
clis.push({
|
|
108
|
-
name: "Claude Code",
|
|
109
|
-
command: "claude",
|
|
110
|
-
provider: "claude",
|
|
111
|
-
version: version.split("\n")[0],
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
catch {
|
|
115
|
-
// Not installed
|
|
116
|
-
}
|
|
117
|
-
// OpenAI Codex CLI
|
|
118
|
-
try {
|
|
119
|
-
const version = execSync("codex --version 2>/dev/null", { encoding: "utf-8" }).trim();
|
|
120
|
-
clis.push({
|
|
121
|
-
name: "Codex CLI",
|
|
122
|
-
command: "codex",
|
|
123
|
-
provider: "codex",
|
|
124
|
-
version,
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
catch {
|
|
128
|
-
// Not installed
|
|
129
|
-
}
|
|
130
|
-
// Aider
|
|
131
|
-
try {
|
|
132
|
-
const version = execSync("aider --version 2>/dev/null", { encoding: "utf-8" }).trim();
|
|
133
|
-
clis.push({
|
|
134
|
-
name: "Aider",
|
|
135
|
-
command: "aider",
|
|
136
|
-
provider: "aider",
|
|
137
|
-
version,
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
catch {
|
|
141
|
-
// Not installed
|
|
142
|
-
}
|
|
143
|
-
return clis;
|
|
43
|
+
// Show JFL Gateway Dashboard
|
|
44
|
+
await showGatewayDashboard();
|
|
144
45
|
}
|
|
145
|
-
async function
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
type: "confirm",
|
|
158
|
-
name: "autonomous",
|
|
159
|
-
message: `Run in autonomous mode? (${flag})`,
|
|
160
|
-
default: false,
|
|
161
|
-
},
|
|
162
|
-
]);
|
|
163
|
-
if (autonomous) {
|
|
164
|
-
console.log(chalk.yellow("\nā ļø Autonomous mode: AI can execute without asking permission."));
|
|
165
|
-
}
|
|
166
|
-
const { remember } = await inquirer.prompt([
|
|
167
|
-
{
|
|
168
|
-
type: "confirm",
|
|
169
|
-
name: "remember",
|
|
170
|
-
message: "Remember this choice?",
|
|
171
|
-
default: true,
|
|
172
|
-
},
|
|
173
|
-
]);
|
|
174
|
-
if (remember) {
|
|
175
|
-
config.set(`autonomous_${cli.provider}`, autonomous);
|
|
176
|
-
}
|
|
177
|
-
return autonomous;
|
|
178
|
-
}
|
|
179
|
-
async function promptChromeMode(cli) {
|
|
180
|
-
// Chrome mode only available for Claude
|
|
181
|
-
if (cli.provider !== "claude")
|
|
182
|
-
return false;
|
|
183
|
-
const savedPref = config.get("chrome_claude");
|
|
184
|
-
// If they've already set a preference, use it
|
|
185
|
-
if (savedPref !== undefined) {
|
|
186
|
-
return savedPref;
|
|
187
|
-
}
|
|
188
|
-
console.log();
|
|
189
|
-
const { chrome } = await inquirer.prompt([
|
|
190
|
-
{
|
|
191
|
-
type: "confirm",
|
|
192
|
-
name: "chrome",
|
|
193
|
-
message: `Enable browser capabilities? (${CHROME_FLAG})`,
|
|
194
|
-
default: false,
|
|
195
|
-
},
|
|
196
|
-
]);
|
|
197
|
-
if (chrome) {
|
|
198
|
-
console.log(chalk.cyan("\nš Chrome mode: Claude can browse and interact with web pages."));
|
|
199
|
-
}
|
|
200
|
-
const { remember } = await inquirer.prompt([
|
|
201
|
-
{
|
|
202
|
-
type: "confirm",
|
|
203
|
-
name: "remember",
|
|
204
|
-
message: "Remember this choice?",
|
|
205
|
-
default: true,
|
|
206
|
-
},
|
|
207
|
-
]);
|
|
208
|
-
if (remember) {
|
|
209
|
-
config.set("chrome_claude", chrome);
|
|
210
|
-
}
|
|
211
|
-
return chrome;
|
|
212
|
-
}
|
|
213
|
-
function showBanner() {
|
|
214
|
-
// Get version from package.json
|
|
215
|
-
let version;
|
|
216
|
-
try {
|
|
217
|
-
const pkgPath = new URL("../../package.json", import.meta.url);
|
|
218
|
-
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
219
|
-
version = pkg.version;
|
|
220
|
-
}
|
|
221
|
-
catch {
|
|
222
|
-
// Ignore
|
|
223
|
-
}
|
|
224
|
-
console.log(renderBanner({ version }));
|
|
225
|
-
}
|
|
226
|
-
async function launchCLI(cli, cwd, skipAutonomousPrompt = false) {
|
|
227
|
-
// Check for autonomous mode
|
|
228
|
-
let autonomous = false;
|
|
229
|
-
if (!skipAutonomousPrompt) {
|
|
230
|
-
autonomous = await promptAutonomousMode(cli);
|
|
46
|
+
async function showGatewayDashboard() {
|
|
47
|
+
console.log(chalk.bold.cyan("\nāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā"));
|
|
48
|
+
console.log(chalk.bold.cyan("ā JFL Gateway Dashboard ā"));
|
|
49
|
+
console.log(chalk.bold.cyan("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n"));
|
|
50
|
+
// 1. Ensure and check Context Hub
|
|
51
|
+
const spinner1 = ora("Checking Context Hub...").start();
|
|
52
|
+
await ensureContextHub();
|
|
53
|
+
const contextHubConfig = getContextHubConfig();
|
|
54
|
+
const contextHubStatus = getContextHubStatus(contextHubConfig.mode === "global" ? homedir() : process.cwd());
|
|
55
|
+
if (contextHubStatus.running) {
|
|
56
|
+
spinner1.succeed(chalk.green("Context Hub") +
|
|
57
|
+
chalk.gray(` (${contextHubConfig.mode} mode, port ${contextHubConfig.port}, PID ${contextHubStatus.pid})`));
|
|
231
58
|
}
|
|
232
59
|
else {
|
|
233
|
-
|
|
234
|
-
}
|
|
235
|
-
// Check for chrome mode (Claude only)
|
|
236
|
-
let chrome = false;
|
|
237
|
-
if (cli.provider === "claude") {
|
|
238
|
-
if (!skipAutonomousPrompt) {
|
|
239
|
-
chrome = await promptChromeMode(cli);
|
|
240
|
-
}
|
|
241
|
-
else {
|
|
242
|
-
chrome = config.get("chrome_claude") || false;
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
// Build args array
|
|
246
|
-
const args = [];
|
|
247
|
-
if (autonomous && AUTONOMOUS_FLAGS[cli.provider]) {
|
|
248
|
-
args.push(AUTONOMOUS_FLAGS[cli.provider]);
|
|
60
|
+
spinner1.fail(chalk.red("Context Hub not running"));
|
|
249
61
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
62
|
+
// 2. Check Service Manager
|
|
63
|
+
const spinner2 = ora("Checking Service Manager...").start();
|
|
64
|
+
const serviceManagerStatus = await checkServiceManager();
|
|
65
|
+
if (serviceManagerStatus.running) {
|
|
66
|
+
spinner2.succeed(chalk.green("Service Manager") +
|
|
67
|
+
chalk.gray(` (port 3401, ${serviceManagerStatus.services} services)`));
|
|
256
68
|
}
|
|
257
69
|
else {
|
|
258
|
-
|
|
259
|
-
console.log();
|
|
70
|
+
spinner2.warn(chalk.yellow("Service Manager not running"));
|
|
71
|
+
console.log(chalk.gray(" Start with: pm2 start ~/.jfl/service-manager/ecosystem.config.js"));
|
|
260
72
|
}
|
|
261
|
-
//
|
|
262
|
-
const modes = [];
|
|
263
|
-
if (autonomous)
|
|
264
|
-
modes.push("autonomous");
|
|
265
|
-
if (chrome)
|
|
266
|
-
modes.push("chrome");
|
|
267
|
-
const modeStr = modes.length > 0 ? theme.dim(` (${modes.join(", ")})`) : "";
|
|
268
|
-
console.log(theme.accent(`Launching ${cli.name}`) + modeStr);
|
|
269
|
-
console.log(theme.dim("Context loaded from CLAUDE.md + knowledge/\n"));
|
|
270
|
-
console.log(theme.dimmer("ā".repeat(50)));
|
|
73
|
+
// 3. Show connection info
|
|
271
74
|
console.log();
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
...process.env,
|
|
278
|
-
JFL_PROJECT: cwd,
|
|
279
|
-
},
|
|
280
|
-
});
|
|
281
|
-
child.on("error", (err) => {
|
|
282
|
-
console.error(chalk.red(`\nFailed to launch ${cli.name}:`), err.message);
|
|
283
|
-
});
|
|
284
|
-
child.on("exit", (code) => {
|
|
285
|
-
if (code !== 0 && code !== null) {
|
|
286
|
-
console.log(chalk.yellow(`\n${cli.name} exited with code ${code}`));
|
|
287
|
-
}
|
|
288
|
-
console.log(chalk.gray("\nJFL session ended.\n"));
|
|
289
|
-
});
|
|
290
|
-
}
|
|
291
|
-
async function onboardNewUser(cwd) {
|
|
292
|
-
// Show banner with version
|
|
293
|
-
showBanner();
|
|
294
|
-
// Show "How It Works" notice
|
|
295
|
-
showHowItWorksNotice();
|
|
296
|
-
// Check for known projects first
|
|
297
|
-
const knownProjects = config.get("projects") || [];
|
|
298
|
-
const existingProjects = knownProjects.filter((p) => existsSync(join(p, "CLAUDE.md")) || existsSync(join(p, "knowledge")));
|
|
299
|
-
// Start Clawdbot-style flow
|
|
300
|
-
p.intro(chalk.hex("#FFD700")("ā JFL onboarding"));
|
|
301
|
-
// If we have known projects, show them upfront
|
|
302
|
-
if (existingProjects.length > 0) {
|
|
303
|
-
const selected = await p.select({
|
|
304
|
-
message: "Open a project or create new?",
|
|
305
|
-
options: [
|
|
306
|
-
...existingProjects.map((proj) => ({
|
|
307
|
-
label: proj.replace(process.env.HOME || "", "~"),
|
|
308
|
-
value: proj,
|
|
309
|
-
})),
|
|
310
|
-
{ label: "Join existing project (I was invited)", value: "join" },
|
|
311
|
-
{ label: "Create new project", value: "new" },
|
|
312
|
-
],
|
|
313
|
-
});
|
|
314
|
-
if (p.isCancel(selected)) {
|
|
315
|
-
p.cancel("Setup cancelled.");
|
|
316
|
-
process.exit(0);
|
|
317
|
-
}
|
|
318
|
-
if (selected === "join") {
|
|
319
|
-
await joinExistingProject();
|
|
320
|
-
return;
|
|
321
|
-
}
|
|
322
|
-
if (selected !== "new") {
|
|
323
|
-
// Update config with cleaned list
|
|
324
|
-
config.set("projects", existingProjects);
|
|
325
|
-
process.chdir(selected);
|
|
326
|
-
p.outro(chalk.hex("#FFA500")(`Opening ${selected.replace(process.env.HOME || "", "~")}`));
|
|
327
|
-
// Launch
|
|
328
|
-
const available = detectAICLIs();
|
|
329
|
-
if (available.length > 0) {
|
|
330
|
-
await launchCLI(available[0], selected);
|
|
331
|
-
}
|
|
332
|
-
else {
|
|
333
|
-
await onboardAICLI();
|
|
334
|
-
}
|
|
335
|
-
return;
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
// No known projects or they want to create new
|
|
339
|
-
const action = await p.select({
|
|
340
|
-
message: "What do you want to do?",
|
|
341
|
-
options: [
|
|
342
|
-
{ label: "Join existing project (I was invited)", value: "join" },
|
|
343
|
-
{ label: "Create a new project", value: "create" },
|
|
344
|
-
],
|
|
345
|
-
});
|
|
346
|
-
if (p.isCancel(action)) {
|
|
347
|
-
p.cancel("Setup cancelled.");
|
|
348
|
-
process.exit(0);
|
|
349
|
-
}
|
|
350
|
-
if (action === "join") {
|
|
351
|
-
await joinExistingProject();
|
|
352
|
-
return;
|
|
353
|
-
}
|
|
354
|
-
// Redirect to init command for proper project creation
|
|
355
|
-
p.outro(chalk.hex("#FFA500")("Launching project setup..."));
|
|
356
|
-
await initCommand();
|
|
357
|
-
}
|
|
358
|
-
async function joinExistingProject() {
|
|
359
|
-
console.log(chalk.cyan("\nš Join Existing Project\n"));
|
|
360
|
-
// Authenticate with GitHub using Device Flow
|
|
361
|
-
let username;
|
|
362
|
-
try {
|
|
363
|
-
username = await authenticateWithGitHub();
|
|
364
|
-
}
|
|
365
|
-
catch (error) {
|
|
366
|
-
console.error(chalk.red("\nGitHub authentication failed"));
|
|
367
|
-
console.error(chalk.gray(error instanceof Error ? error.message : String(error)));
|
|
368
|
-
return;
|
|
369
|
-
}
|
|
370
|
-
// Discover JFL projects
|
|
371
|
-
let projects;
|
|
372
|
-
try {
|
|
373
|
-
projects = await discoverJflProjects();
|
|
374
|
-
}
|
|
375
|
-
catch (error) {
|
|
376
|
-
console.error(chalk.red("\nFailed to discover projects"));
|
|
377
|
-
console.error(chalk.gray(error instanceof Error ? error.message : String(error)));
|
|
378
|
-
return;
|
|
379
|
-
}
|
|
380
|
-
if (projects.length === 0) {
|
|
381
|
-
console.log(chalk.yellow("\nNo JFL projects found that you have access to.\n"));
|
|
382
|
-
console.log(chalk.gray("Ask the project owner to add you as a collaborator."));
|
|
383
|
-
console.log(chalk.gray("The project needs a CLAUDE.md file or .jfl/ directory.\n"));
|
|
384
|
-
return;
|
|
385
|
-
}
|
|
386
|
-
// Show projects with details
|
|
75
|
+
console.log(chalk.bold("Gateway Endpoints:"));
|
|
76
|
+
console.log(chalk.gray(" Context Hub: ") + chalk.cyan(`http://localhost:${contextHubConfig.port}`));
|
|
77
|
+
console.log(chalk.gray(" Service Manager: ") + chalk.cyan("http://localhost:3401"));
|
|
78
|
+
console.log(chalk.gray(" MCP Server: ") + chalk.cyan("Connected via MCP"));
|
|
79
|
+
// 4. Show how to connect
|
|
387
80
|
console.log();
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
choices: projects.map((p) => ({
|
|
394
|
-
name: `${p.fullName}${p.hasUserSuggestions ? chalk.green(" (you're invited)") : ""}${p.description ? chalk.gray(` - ${p.description}`) : ""}`,
|
|
395
|
-
value: p,
|
|
396
|
-
})),
|
|
397
|
-
},
|
|
398
|
-
]);
|
|
399
|
-
// Check if we already have this project locally
|
|
400
|
-
const trackedProjects = config.get("projects") || [];
|
|
401
|
-
const existingLocal = trackedProjects.find((p) => {
|
|
402
|
-
const projectName = p.split("/").pop();
|
|
403
|
-
return projectName === selectedProject.name &&
|
|
404
|
-
(existsSync(join(p, "CLAUDE.md")) || existsSync(join(p, ".jfl")));
|
|
405
|
-
});
|
|
406
|
-
// Also check common locations
|
|
407
|
-
const commonPaths = [
|
|
408
|
-
join(process.env.HOME || "", "Projects", selectedProject.name),
|
|
409
|
-
join(process.env.HOME || "", selectedProject.name),
|
|
410
|
-
join(process.cwd(), selectedProject.name),
|
|
411
|
-
];
|
|
412
|
-
const existingAtCommonPath = commonPaths.find((p) => existsSync(p) && (existsSync(join(p, "CLAUDE.md")) || existsSync(join(p, ".jfl"))));
|
|
413
|
-
const alreadyCloned = existingLocal || existingAtCommonPath;
|
|
414
|
-
if (alreadyCloned) {
|
|
415
|
-
console.log(chalk.green(`\nā Already have ${selectedProject.name} at ${alreadyCloned}\n`));
|
|
416
|
-
const { openExisting } = await inquirer.prompt([
|
|
417
|
-
{
|
|
418
|
-
type: "confirm",
|
|
419
|
-
name: "openExisting",
|
|
420
|
-
message: "Open it?",
|
|
421
|
-
default: true,
|
|
422
|
-
},
|
|
423
|
-
]);
|
|
424
|
-
if (openExisting) {
|
|
425
|
-
// Track if not already
|
|
426
|
-
if (!trackedProjects.includes(alreadyCloned)) {
|
|
427
|
-
trackedProjects.push(alreadyCloned);
|
|
428
|
-
config.set("projects", trackedProjects);
|
|
429
|
-
}
|
|
430
|
-
process.chdir(alreadyCloned);
|
|
431
|
-
const available = detectAICLIs();
|
|
432
|
-
if (available.length > 0) {
|
|
433
|
-
await launchCLI(available[0], alreadyCloned);
|
|
434
|
-
}
|
|
435
|
-
else {
|
|
436
|
-
await onboardAICLI();
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
return;
|
|
440
|
-
}
|
|
441
|
-
// Show project info
|
|
81
|
+
console.log(chalk.bold("AI Tools Connection:"));
|
|
82
|
+
console.log(chalk.gray(" Claude Code connects via MCP automatically"));
|
|
83
|
+
console.log(chalk.gray(" Cursor connects via MCP automatically"));
|
|
84
|
+
console.log(chalk.gray(" Custom tools can use HTTP API"));
|
|
85
|
+
// 5. Show available commands
|
|
442
86
|
console.log();
|
|
443
|
-
console.log(chalk.bold(
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
console.log(chalk.green(`ā Your suggestions file exists (suggestions/${username}.md)`));
|
|
452
|
-
}
|
|
87
|
+
console.log(chalk.bold("Manage Services:"));
|
|
88
|
+
console.log(chalk.gray(" jfl-services list ") + "# List all services");
|
|
89
|
+
console.log(chalk.gray(" jfl-services start <id> ") + "# Start a service");
|
|
90
|
+
console.log(chalk.gray(" jfl-services logs <id> ") + "# View service logs");
|
|
91
|
+
console.log();
|
|
92
|
+
console.log(chalk.bold("View Status:"));
|
|
93
|
+
console.log(chalk.gray(" jfl status ") + "# Project status");
|
|
94
|
+
console.log(chalk.gray(" jfl hud ") + "# Campaign dashboard");
|
|
453
95
|
console.log();
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
type: "input",
|
|
459
|
-
name: "clonePath",
|
|
460
|
-
message: "Where to clone?",
|
|
461
|
-
default: defaultPath,
|
|
462
|
-
},
|
|
463
|
-
]);
|
|
464
|
-
const expandedPath = clonePath.replace(/^~/, process.env.HOME || "");
|
|
465
|
-
// Clone the repo
|
|
466
|
-
let clonedPath;
|
|
96
|
+
console.log(chalk.green("ā JFL Gateway is ready!"));
|
|
97
|
+
console.log(chalk.gray(" Open Claude Code or Cursor to connect via MCP\n"));
|
|
98
|
+
}
|
|
99
|
+
async function checkServiceManager() {
|
|
467
100
|
try {
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
console.error(chalk.red("\nClone failed"));
|
|
472
|
-
console.error(chalk.gray(error instanceof Error ? error.message : String(error)));
|
|
473
|
-
return;
|
|
474
|
-
}
|
|
475
|
-
// Track this project
|
|
476
|
-
const allProjects = config.get("projects") || [];
|
|
477
|
-
if (!allProjects.includes(clonedPath)) {
|
|
478
|
-
allProjects.push(clonedPath);
|
|
479
|
-
config.set("projects", allProjects);
|
|
480
|
-
}
|
|
481
|
-
config.set("hasOnboarded", true);
|
|
482
|
-
// Mark this teammate as joined (adds <!-- joined: DATE --> marker)
|
|
483
|
-
markTeammateJoined(username);
|
|
484
|
-
console.log(chalk.green(`\nā Joined ${selectedProject.name}!\n`));
|
|
485
|
-
// Show project configuration
|
|
486
|
-
if (selectedProject.projectConfig?.wallet) {
|
|
487
|
-
console.log(chalk.gray("Project Configuration:"));
|
|
488
|
-
console.log(chalk.gray(` Owner: ${selectedProject.projectConfig.walletOwner || selectedProject.owner}`));
|
|
489
|
-
console.log(chalk.gray(` Wallet: ${selectedProject.projectConfig.wallet} (configured)`));
|
|
490
|
-
console.log(chalk.gray(` Your role: Contributor`));
|
|
491
|
-
console.log();
|
|
101
|
+
const response = await axios.get("http://localhost:3401/health", { timeout: 2000 });
|
|
102
|
+
const services = response.data.stats?.total_services || 0;
|
|
103
|
+
return { running: true, services };
|
|
492
104
|
}
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
console.log(chalk.white(` cd ${clonedPath}`));
|
|
496
|
-
console.log(chalk.white(` jfl\n`));
|
|
497
|
-
// Offer to launch now
|
|
498
|
-
const { launchNow } = await inquirer.prompt([
|
|
499
|
-
{
|
|
500
|
-
type: "confirm",
|
|
501
|
-
name: "launchNow",
|
|
502
|
-
message: "Open project now?",
|
|
503
|
-
default: true,
|
|
504
|
-
},
|
|
505
|
-
]);
|
|
506
|
-
if (launchNow) {
|
|
507
|
-
process.chdir(clonedPath);
|
|
508
|
-
const available = detectAICLIs();
|
|
509
|
-
if (available.length > 0) {
|
|
510
|
-
await launchCLI(available[0], clonedPath);
|
|
511
|
-
}
|
|
512
|
-
else {
|
|
513
|
-
await onboardAICLI();
|
|
514
|
-
}
|
|
105
|
+
catch (err) {
|
|
106
|
+
return { running: false };
|
|
515
107
|
}
|
|
516
108
|
}
|
|
517
|
-
async function
|
|
518
|
-
console.log(chalk.
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
choices: [
|
|
526
|
-
{ name: "I'm a developer - comfortable with terminal", value: "dev" },
|
|
527
|
-
{ name: "Somewhat technical - can follow instructions", value: "some" },
|
|
528
|
-
{ name: "Not technical - need the easy path", value: "none" },
|
|
529
|
-
],
|
|
530
|
-
},
|
|
531
|
-
]);
|
|
532
|
-
if (experience === "none") {
|
|
533
|
-
// Non-technical path - recommend browser-based or desktop app
|
|
534
|
-
console.log(chalk.cyan("\nš± Easiest options for you:\n"));
|
|
535
|
-
console.log(chalk.bold("1. Claude.ai (browser)"));
|
|
536
|
-
console.log(chalk.gray(" Go to claude.ai, sign up, and chat directly"));
|
|
537
|
-
console.log(chalk.gray(" You can paste your project files into the chat\n"));
|
|
538
|
-
console.log(chalk.bold("2. Claude Desktop App"));
|
|
539
|
-
console.log(chalk.gray(" Download from claude.ai/download"));
|
|
540
|
-
console.log(chalk.gray(" Works like ChatGPT but with Claude\n"));
|
|
541
|
-
console.log(chalk.bold("3. Cursor (AI-powered code editor)"));
|
|
542
|
-
console.log(chalk.gray(" Download from cursor.com"));
|
|
543
|
-
console.log(chalk.gray(" Like VS Code but with AI built in\n"));
|
|
544
|
-
console.log(chalk.yellow("For the full JFL experience, Claude Code is best."));
|
|
545
|
-
console.log(chalk.gray("But start with what's comfortable.\n"));
|
|
546
|
-
return;
|
|
547
|
-
}
|
|
548
|
-
// Technical path - CLI tools
|
|
549
|
-
console.log(chalk.yellow("\nNo AI CLI detected.\n"));
|
|
550
|
-
const { choice } = await inquirer.prompt([
|
|
551
|
-
{
|
|
552
|
-
type: "list",
|
|
553
|
-
name: "choice",
|
|
554
|
-
message: "Which AI do you want to use?",
|
|
555
|
-
choices: [
|
|
556
|
-
{
|
|
557
|
-
name: "Claude Code (recommended for JFL)",
|
|
558
|
-
value: "claude",
|
|
559
|
-
},
|
|
560
|
-
{
|
|
561
|
-
name: "Codex CLI (OpenAI)",
|
|
562
|
-
value: "codex",
|
|
563
|
-
},
|
|
564
|
-
{
|
|
565
|
-
name: "Aider (works with multiple models)",
|
|
566
|
-
value: "aider",
|
|
567
|
-
},
|
|
568
|
-
{
|
|
569
|
-
name: "I'll set it up myself",
|
|
570
|
-
value: "manual",
|
|
571
|
-
},
|
|
572
|
-
],
|
|
573
|
-
},
|
|
574
|
-
]);
|
|
575
|
-
if (choice === "manual") {
|
|
576
|
-
console.log(chalk.gray("\nSupported AI CLIs:"));
|
|
577
|
-
console.log(" ⢠Claude Code: npm install -g @anthropic-ai/claude-code");
|
|
578
|
-
console.log(" ⢠Codex CLI: npm install -g @openai/codex");
|
|
579
|
-
console.log(" ⢠Aider: pip install aider-chat");
|
|
580
|
-
console.log(chalk.gray("\nRun 'jfl' again after installing.\n"));
|
|
581
|
-
return;
|
|
582
|
-
}
|
|
583
|
-
const installCommands = {
|
|
584
|
-
claude: {
|
|
585
|
-
cmd: "npm install -g @anthropic-ai/claude-code",
|
|
586
|
-
name: "Claude Code",
|
|
587
|
-
},
|
|
588
|
-
codex: {
|
|
589
|
-
cmd: "npm install -g @openai/codex",
|
|
590
|
-
name: "Codex CLI",
|
|
591
|
-
},
|
|
592
|
-
aider: {
|
|
593
|
-
cmd: "pip install aider-chat",
|
|
594
|
-
name: "Aider",
|
|
595
|
-
},
|
|
596
|
-
};
|
|
597
|
-
const install = installCommands[choice];
|
|
598
|
-
console.log(chalk.cyan(`\nInstalling ${install.name}...\n`));
|
|
599
|
-
console.log(chalk.gray(`$ ${install.cmd}\n`));
|
|
600
|
-
const { proceed } = await inquirer.prompt([
|
|
601
|
-
{
|
|
602
|
-
type: "confirm",
|
|
603
|
-
name: "proceed",
|
|
604
|
-
message: "Run this command?",
|
|
605
|
-
default: true,
|
|
606
|
-
},
|
|
607
|
-
]);
|
|
608
|
-
if (!proceed) {
|
|
609
|
-
console.log(chalk.gray(`\nRun manually: ${install.cmd}`));
|
|
610
|
-
console.log(chalk.gray("Then run 'jfl' again.\n"));
|
|
109
|
+
async function onboardNewUser(cwd) {
|
|
110
|
+
console.log(chalk.yellow("\nā ļø Not in a JFL project\n"));
|
|
111
|
+
const shouldInit = await p.confirm({
|
|
112
|
+
message: "Initialize this directory as a JFL project?",
|
|
113
|
+
initialValue: true,
|
|
114
|
+
});
|
|
115
|
+
if (p.isCancel(shouldInit) || !shouldInit) {
|
|
116
|
+
console.log(chalk.gray("\nRun 'jfl init' when ready\n"));
|
|
611
117
|
return;
|
|
612
118
|
}
|
|
613
|
-
|
|
614
|
-
execSync(install.cmd, { stdio: "inherit" });
|
|
615
|
-
console.log(chalk.green(`\nā ${install.name} installed!\n`));
|
|
616
|
-
// Prompt for API key setup
|
|
617
|
-
if (choice === "claude") {
|
|
618
|
-
console.log(chalk.gray("Set your Anthropic API key:"));
|
|
619
|
-
console.log(chalk.white(" export ANTHROPIC_API_KEY=your-key-here\n"));
|
|
620
|
-
console.log(chalk.gray("Or run 'claude' to authenticate interactively.\n"));
|
|
621
|
-
}
|
|
622
|
-
else if (choice === "codex") {
|
|
623
|
-
console.log(chalk.gray("Set your OpenAI API key:"));
|
|
624
|
-
console.log(chalk.white(" export OPENAI_API_KEY=your-key-here\n"));
|
|
625
|
-
}
|
|
626
|
-
else if (choice === "aider") {
|
|
627
|
-
console.log(chalk.gray("Set your API key (Anthropic or OpenAI):"));
|
|
628
|
-
console.log(chalk.white(" export ANTHROPIC_API_KEY=your-key-here"));
|
|
629
|
-
console.log(chalk.white(" # or"));
|
|
630
|
-
console.log(chalk.white(" export OPENAI_API_KEY=your-key-here\n"));
|
|
631
|
-
}
|
|
632
|
-
console.log(chalk.cyan("Run 'jfl' to start your AI session.\n"));
|
|
633
|
-
}
|
|
634
|
-
catch (error) {
|
|
635
|
-
console.error(chalk.red("\nInstallation failed."));
|
|
636
|
-
console.log(chalk.gray(`\nTry manually: ${install.cmd}\n`));
|
|
637
|
-
}
|
|
119
|
+
await initCommand();
|
|
638
120
|
}
|
|
639
121
|
//# sourceMappingURL=session.js.map
|