arkaos 2.3.6 → 2.4.1

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/VERSION CHANGED
@@ -1 +1 @@
1
- 2.3.6
1
+ 2.4.1
@@ -13,19 +13,22 @@ const VERSION = JSON.parse(readFileSync(join(ARKAOS_ROOT, "package.json"), "utf-
13
13
  export async function install({ runtime, path, force }) {
14
14
  const startTime = Date.now();
15
15
  const config = getRuntimeConfig(runtime);
16
- const installDir = path || join(homedir(), ".arkaos");
17
- const isUpgrade = existsSync(join(installDir, "install-manifest.json"));
16
+ const isUpgrade = existsSync(join(path || join(homedir(), ".arkaos"), "install-manifest.json"));
18
17
 
19
18
  console.log(`
20
19
  ╔══════════════════════════════════════════════════════════╗
21
20
  ║ ArkaOS v${VERSION} — The Operating System for AI Agent Teams ║
22
21
  ╚══════════════════════════════════════════════════════════╝
23
22
 
24
- Runtime: ${config.name}
25
- Install dir: ${installDir}
26
- Mode: ${isUpgrade ? "Upgrade" : "Fresh install"}
23
+ Runtime: ${config.name}
24
+ Mode: ${isUpgrade ? "Upgrade" : "Fresh install"}
27
25
  `);
28
26
 
27
+ // ═══ Interactive Setup ═══
28
+ const { runSetupPrompts } = await import("./prompts.js");
29
+ const userConfig = await runSetupPrompts(isUpgrade);
30
+ const installDir = userConfig.installDir;
31
+
29
32
  // ═══ Step 1: Create directories ═══
30
33
  step(1, 12, "Creating directories...");
31
34
  ensureDir(installDir);
@@ -52,9 +55,9 @@ export async function install({ runtime, path, force }) {
52
55
  const pythonCmd = checkPython();
53
56
  ok(`Found: ${pythonCmd}`);
54
57
 
55
- // ═══ Step 4: Install Python core + ALL dependencies ═══
58
+ // ═══ Step 4: Install Python core + dependencies based on user choices ═══
56
59
  step(4, 12, "Installing Python dependencies (this may take a minute)...");
57
- installAllPythonDeps(pythonCmd);
60
+ installAllPythonDeps(pythonCmd, userConfig);
58
61
 
59
62
  // ═══ Step 5: Copy configuration files ═══
60
63
  step(5, 12, "Copying configuration files...");
@@ -83,32 +86,60 @@ export async function install({ runtime, path, force }) {
83
86
  writeFileSync(join(skillsDir, ".arkaos-root"), ARKAOS_ROOT);
84
87
 
85
88
  const profilePath = join(installDir, "profile.json");
86
- if (!existsSync(profilePath)) {
87
- writeFileSync(profilePath, JSON.stringify({
88
- version: "2",
89
- created: new Date().toISOString(),
90
- }, null, 2));
91
- ok("New profile created");
92
- } else {
93
- ok("Existing profile preserved");
89
+ const profile = {
90
+ version: "2",
91
+ language: userConfig.language,
92
+ market: userConfig.market,
93
+ role: userConfig.role,
94
+ company: userConfig.company,
95
+ projectsDir: userConfig.projectsDir,
96
+ vaultPath: userConfig.vaultPath,
97
+ created: existsSync(profilePath)
98
+ ? JSON.parse(readFileSync(profilePath, "utf-8")).created
99
+ : new Date().toISOString(),
100
+ updated: new Date().toISOString(),
101
+ };
102
+ writeFileSync(profilePath, JSON.stringify(profile, null, 2));
103
+ ok("Profile saved");
104
+
105
+ // Save API keys if provided
106
+ if (userConfig.openaiKey || userConfig.googleKey || userConfig.falKey) {
107
+ const keysPath = join(installDir, "keys.json");
108
+ const keys = existsSync(keysPath) ? JSON.parse(readFileSync(keysPath, "utf-8")) : {};
109
+ if (userConfig.openaiKey) keys.OPENAI_API_KEY = userConfig.openaiKey;
110
+ if (userConfig.googleKey) keys.GOOGLE_API_KEY = userConfig.googleKey;
111
+ if (userConfig.falKey) keys.FAL_API_KEY = userConfig.falKey;
112
+ writeFileSync(keysPath, JSON.stringify(keys, null, 2));
113
+ try { chmodSync(keysPath, 0o600); } catch {}
114
+ ok("API keys saved");
94
115
  }
95
116
 
96
- // ═══ Step 10: Index knowledge base (if vault configured) ═══
97
- step(10, 12, "Checking knowledge base...");
98
- const kbDb = join(installDir, "knowledge.db");
99
- if (!existsSync(kbDb)) {
117
+ // ═══ Step 10: Index knowledge base ═══
118
+ step(10, 12, "Setting up knowledge base...");
119
+ if (userConfig.installKnowledge) {
120
+ const kbDb = join(installDir, "knowledge.db");
121
+ // Index ArkaOS skills first
100
122
  try {
101
123
  execSync(`${pythonCmd} "${join(ARKAOS_ROOT, "scripts", "knowledge-index.py")}" --dir "${join(ARKAOS_ROOT, "departments")}" --db "${kbDb}"`, {
102
- stdio: "pipe",
103
- timeout: 60000,
104
- env: { ...process.env, ARKAOS_ROOT },
124
+ stdio: "pipe", timeout: 60000, env: { ...process.env, ARKAOS_ROOT },
105
125
  });
106
- ok("ArkaOS skills indexed into knowledge base");
126
+ ok("ArkaOS skills indexed");
107
127
  } catch {
108
- warn("Knowledge indexing skipped (run 'npx arkaos index' later)");
128
+ warn("Skill indexing skipped");
129
+ }
130
+ // Index user's Obsidian vault if provided
131
+ if (userConfig.vaultPath && existsSync(userConfig.vaultPath)) {
132
+ try {
133
+ execSync(`${pythonCmd} "${join(ARKAOS_ROOT, "scripts", "knowledge-index.py")}" --vault "${userConfig.vaultPath}" --db "${kbDb}"`, {
134
+ stdio: "pipe", timeout: 120000, env: { ...process.env, ARKAOS_ROOT },
135
+ });
136
+ ok(`Obsidian vault indexed: ${userConfig.vaultPath}`);
137
+ } catch {
138
+ warn("Vault indexing skipped (run 'npx arkaos index' later)");
139
+ }
109
140
  }
110
141
  } else {
111
- ok("Knowledge base already exists");
142
+ ok("Knowledge base skipped (install later with 'npx arkaos index')");
112
143
  }
113
144
 
114
145
  // ═══ Step 11: Verify installation ═══
@@ -213,7 +244,7 @@ function checkPython() {
213
244
  process.exit(1);
214
245
  }
215
246
 
216
- function installAllPythonDeps(pythonCmd) {
247
+ function installAllPythonDeps(pythonCmd, userConfig = {}) {
217
248
  // Core dependencies
218
249
  const coreDeps = "pyyaml pydantic rich click jinja2";
219
250
  // Knowledge + Vector DB
@@ -225,7 +256,11 @@ function installAllPythonDeps(pythonCmd) {
225
256
  // Transcription
226
257
  const transcriptionDeps = "faster-whisper";
227
258
 
228
- const allDeps = `${coreDeps} ${knowledgeDeps} ${ingestDeps} ${dashboardDeps}`;
259
+ // Build deps list based on user choices
260
+ let allDeps = coreDeps;
261
+ if (userConfig.installKnowledge !== false) allDeps += ` ${knowledgeDeps}`;
262
+ allDeps += ` ${ingestDeps}`;
263
+ if (userConfig.installDashboard !== false) allDeps += ` ${dashboardDeps}`;
229
264
 
230
265
  try {
231
266
  // Try uv first (faster)
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Interactive prompts for ArkaOS installer.
3
+ * Asks user for directories, language, market, preferences.
4
+ * Nothing is hardcoded — everything comes from the user.
5
+ */
6
+
7
+ import { createInterface } from "node:readline";
8
+ import { existsSync } from "node:fs";
9
+ import { join } from "node:path";
10
+ import { homedir } from "node:os";
11
+
12
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
13
+
14
+ function ask(question, defaultValue = "") {
15
+ const suffix = defaultValue ? ` [${defaultValue}]` : "";
16
+ return new Promise((resolve) => {
17
+ rl.question(` ${question}${suffix}: `, (answer) => {
18
+ resolve(answer.trim() || defaultValue);
19
+ });
20
+ });
21
+ }
22
+
23
+ function askYN(question, defaultYes = true) {
24
+ const suffix = defaultYes ? " [Y/n]" : " [y/N]";
25
+ return new Promise((resolve) => {
26
+ rl.question(` ${question}${suffix}: `, (answer) => {
27
+ const a = answer.trim().toLowerCase();
28
+ if (!a) resolve(defaultYes);
29
+ else resolve(a === "y" || a === "yes");
30
+ });
31
+ });
32
+ }
33
+
34
+ function askChoice(question, options) {
35
+ return new Promise((resolve) => {
36
+ console.log(` ${question}`);
37
+ options.forEach((opt, i) => {
38
+ console.log(` ${i + 1}) ${opt.label}`);
39
+ });
40
+ rl.question(` Choose [1-${options.length}]: `, (answer) => {
41
+ const idx = parseInt(answer.trim()) - 1;
42
+ if (idx >= 0 && idx < options.length) {
43
+ resolve(options[idx].value);
44
+ } else {
45
+ resolve(options[0].value); // Default to first
46
+ }
47
+ });
48
+ });
49
+ }
50
+
51
+ export async function runSetupPrompts(isUpgrade = false) {
52
+ console.log(`
53
+ ╔══════════════════════════════════════════════════════╗
54
+ ║ ArkaOS Setup — Let's configure your environment ║
55
+ ╚══════════════════════════════════════════════════════╝
56
+ `);
57
+
58
+ const config = {};
59
+
60
+ // ── Language ──
61
+ config.language = await askChoice("What is your primary language?", [
62
+ { label: "English", value: "en" },
63
+ { label: "Português", value: "pt" },
64
+ { label: "Español", value: "es" },
65
+ { label: "Français", value: "fr" },
66
+ { label: "Deutsch", value: "de" },
67
+ { label: "Italiano", value: "it" },
68
+ { label: "中文 (Chinese)", value: "zh" },
69
+ { label: "日本語 (Japanese)", value: "ja" },
70
+ { label: "한국어 (Korean)", value: "ko" },
71
+ { label: "Other", value: "other" },
72
+ ]);
73
+
74
+ if (config.language === "other") {
75
+ config.language = await ask("Enter language code (e.g., nl, pl, ru)");
76
+ }
77
+
78
+ // ── Market/Country ──
79
+ config.market = await ask("What is your primary market/country?", "");
80
+ console.log(" (e.g., United States, Portugal, Brazil, Germany, Global)");
81
+ if (!config.market) {
82
+ config.market = await ask("Market/Country");
83
+ }
84
+
85
+ // ── Role ──
86
+ config.role = await askChoice("What best describes your role?", [
87
+ { label: "Developer / Engineer", value: "developer" },
88
+ { label: "Founder / CEO", value: "founder" },
89
+ { label: "Marketing / Growth", value: "marketing" },
90
+ { label: "Product Manager", value: "product" },
91
+ { label: "Designer", value: "designer" },
92
+ { label: "Consultant / Agency", value: "consultant" },
93
+ { label: "Other", value: "other" },
94
+ ]);
95
+
96
+ // ── Company ──
97
+ config.company = await ask("Company or organization name (optional)", "");
98
+
99
+ // ── Directories ──
100
+ console.log("\n ── Directories ──\n");
101
+
102
+ config.projectsDir = await ask(
103
+ "Where are your projects?",
104
+ join(homedir(), "Projects")
105
+ );
106
+
107
+ config.vaultPath = await ask(
108
+ "Where is your Obsidian vault? (leave empty if none)",
109
+ ""
110
+ );
111
+ if (config.vaultPath && !existsSync(config.vaultPath)) {
112
+ console.log(` ⚠ Directory not found: ${config.vaultPath}`);
113
+ const create = await askYN("Create it?", false);
114
+ if (!create) config.vaultPath = "";
115
+ }
116
+
117
+ config.installDir = await ask(
118
+ "ArkaOS data directory",
119
+ join(homedir(), ".arkaos")
120
+ );
121
+
122
+ // ── Features ──
123
+ console.log("\n ── Optional Features ──\n");
124
+
125
+ config.installDashboard = await askYN("Install monitoring dashboard?", true);
126
+ config.installKnowledge = await askYN("Install knowledge base (vector DB)?", true);
127
+ config.installTranscription = await askYN("Install audio transcription (Whisper)?", false);
128
+
129
+ // ── API Keys (optional) ──
130
+ console.log("\n ── API Keys (optional, can be configured later) ──\n");
131
+
132
+ config.openaiKey = await ask("OpenAI API key (for Whisper, embeddings — leave empty to skip)", "");
133
+ config.googleKey = await ask("Google API key (Gemini, Nano Banana — leave empty to skip)", "");
134
+ config.falKey = await ask("fal.ai API key (image/video generation — leave empty to skip)", "");
135
+
136
+ // ── Summary ──
137
+ console.log(`
138
+ ── Configuration Summary ──
139
+
140
+ Language: ${config.language}
141
+ Market: ${config.market || "(not set)"}
142
+ Role: ${config.role}
143
+ Company: ${config.company || "(not set)"}
144
+ Projects dir: ${config.projectsDir}
145
+ Obsidian vault: ${config.vaultPath || "(none)"}
146
+ Install dir: ${config.installDir}
147
+ Dashboard: ${config.installDashboard ? "Yes" : "No"}
148
+ Knowledge DB: ${config.installKnowledge ? "Yes" : "No"}
149
+ Transcription: ${config.installTranscription ? "Yes" : "No"}
150
+ OpenAI key: ${config.openaiKey ? "configured" : "not set"}
151
+ Google key: ${config.googleKey ? "configured" : "not set"}
152
+ fal.ai key: ${config.falKey ? "configured" : "not set"}
153
+ `);
154
+
155
+ const confirmed = await askYN("Proceed with this configuration?", true);
156
+ if (!confirmed) {
157
+ console.log("\n Installation cancelled.\n");
158
+ rl.close();
159
+ process.exit(0);
160
+ }
161
+
162
+ rl.close();
163
+ return config;
164
+ }
165
+
166
+ export function closePrompts() {
167
+ try { rl.close(); } catch {}
168
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arkaos",
3
- "version": "2.3.6",
3
+ "version": "2.4.1",
4
4
  "description": "The Operating System for AI Agent Teams",
5
5
  "type": "module",
6
6
  "bin": {
package/pyproject.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "arkaos-core"
3
- version = "2.3.6"
3
+ version = "2.4.1"
4
4
  description = "Core engine for ArkaOS — The Operating System for AI Agent Teams"
5
5
  readme = "README.md"
6
6
  license = {text = "MIT"}
@@ -36,17 +36,33 @@ echo " ArkaOS Dashboard"
36
36
  echo " ─────────────────"
37
37
 
38
38
  # ── Start FastAPI backend ──
39
+ API_LOG="$HOME/.arkaos/api.log"
39
40
  echo " Starting API on :${API_PORT}..."
40
- ARKAOS_ROOT="$ARKAOS_ROOT" python3 "${ARKAOS_ROOT}/scripts/dashboard-api.py" --port "$API_PORT" >/dev/null 2>&1 &
41
+ ARKAOS_ROOT="$ARKAOS_ROOT" python3 "${ARKAOS_ROOT}/scripts/dashboard-api.py" --port "$API_PORT" > "$API_LOG" 2>&1 &
41
42
  API_PID=$!
42
- sleep 2
43
43
 
44
- # Verify API started
45
- if ! kill -0 "$API_PID" 2>/dev/null; then
46
- echo " ✗ API failed to start"
47
- exit 1
44
+ # Wait for API with health check (up to 10 seconds)
45
+ API_READY=false
46
+ for i in $(seq 1 20); do
47
+ sleep 0.5
48
+ if ! kill -0 "$API_PID" 2>/dev/null; then
49
+ break
50
+ fi
51
+ if curl -s "http://localhost:${API_PORT}/api/overview" >/dev/null 2>&1; then
52
+ API_READY=true
53
+ break
54
+ fi
55
+ done
56
+
57
+ if [ "$API_READY" = true ]; then
58
+ echo " ✓ API: http://localhost:${API_PORT}"
59
+ else
60
+ echo " ⚠ API may still be starting (check log: $API_LOG)"
61
+ if [ -f "$API_LOG" ]; then
62
+ echo " Last error: $(tail -3 "$API_LOG" | head -1)"
63
+ fi
64
+ # Don't exit — API might still be loading, continue with dashboard
48
65
  fi
49
- echo " ✓ API: http://localhost:${API_PORT}"
50
66
 
51
67
  # ── Start Nuxt frontend ──
52
68
  UI_PID=""