arkaos 2.2.2 → 2.3.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/VERSION +1 -1
- package/installer/cli.js +0 -0
- package/installer/index.js +262 -62
- package/package.json +1 -1
- package/pyproject.toml +1 -1
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.
|
|
1
|
+
2.3.0
|
package/installer/cli.js
CHANGED
|
File without changes
|
package/installer/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, copyFileSync, readFileSync, writeFileSync, readdirSync, chmodSync } from "node:fs";
|
|
1
|
+
import { existsSync, mkdirSync, copyFileSync, readFileSync, writeFileSync, readdirSync, chmodSync, cpSync } from "node:fs";
|
|
2
2
|
import { join, resolve, dirname } from "node:path";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import { execSync } from "node:child_process";
|
|
@@ -11,66 +11,123 @@ const ARKAOS_ROOT = resolve(__dirname, "..");
|
|
|
11
11
|
const VERSION = JSON.parse(readFileSync(join(ARKAOS_ROOT, "package.json"), "utf-8")).version;
|
|
12
12
|
|
|
13
13
|
export async function install({ runtime, path, force }) {
|
|
14
|
-
|
|
15
|
-
console.log(` Runtime: ${runtime}`);
|
|
16
|
-
|
|
14
|
+
const startTime = Date.now();
|
|
17
15
|
const config = getRuntimeConfig(runtime);
|
|
18
16
|
const installDir = path || join(homedir(), ".arkaos");
|
|
17
|
+
const isUpgrade = existsSync(join(installDir, "install-manifest.json"));
|
|
19
18
|
|
|
20
|
-
console.log(`
|
|
21
|
-
|
|
19
|
+
console.log(`
|
|
20
|
+
╔══════════════════════════════════════════════════════════╗
|
|
21
|
+
║ ArkaOS v${VERSION} — The Operating System for AI Agent Teams ║
|
|
22
|
+
╚══════════════════════════════════════════════════════════╝
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
Runtime: ${config.name}
|
|
25
|
+
Install dir: ${installDir}
|
|
26
|
+
Mode: ${isUpgrade ? "Upgrade" : "Fresh install"}
|
|
27
|
+
`);
|
|
28
|
+
|
|
29
|
+
// ═══ Step 1: Create directories ═══
|
|
30
|
+
step(1, 12, "Creating directories...");
|
|
25
31
|
ensureDir(installDir);
|
|
26
|
-
|
|
27
|
-
ensureDir(join(installDir,
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
const dirs = ["config", "config/hooks", "agents", "media", "session-digests", "vault"];
|
|
33
|
+
for (const d of dirs) ensureDir(join(installDir, d));
|
|
34
|
+
ok(`${dirs.length + 1} directories ready`);
|
|
35
|
+
|
|
36
|
+
// ═══ Step 2: Detect v1 installation ═══
|
|
37
|
+
step(2, 12, "Checking for v1 installation...");
|
|
38
|
+
const v1Paths = [
|
|
39
|
+
join(homedir(), ".claude", "skills", "arka-os"),
|
|
40
|
+
join(homedir(), ".claude", "skills", "arkaos"),
|
|
41
|
+
];
|
|
42
|
+
const v1Found = v1Paths.find(p => existsSync(p));
|
|
43
|
+
if (v1Found && !existsSync(join(installDir, "migrated-from-v1"))) {
|
|
44
|
+
warn(`v1 detected at ${v1Found}`);
|
|
45
|
+
console.log(" Run 'npx arkaos migrate' after install to migrate your data.");
|
|
46
|
+
} else {
|
|
47
|
+
ok("No v1 installation found");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ═══ Step 3: Check Python ═══
|
|
51
|
+
step(3, 12, "Checking Python 3.11+...");
|
|
34
52
|
const pythonCmd = checkPython();
|
|
35
|
-
|
|
53
|
+
ok(`Found: ${pythonCmd}`);
|
|
36
54
|
|
|
37
|
-
// Step
|
|
38
|
-
|
|
39
|
-
|
|
55
|
+
// ═══ Step 4: Install Python core + ALL dependencies ═══
|
|
56
|
+
step(4, 12, "Installing Python dependencies (this may take a minute)...");
|
|
57
|
+
installAllPythonDeps(pythonCmd);
|
|
40
58
|
|
|
41
|
-
// Step
|
|
42
|
-
|
|
59
|
+
// ═══ Step 5: Copy configuration files ═══
|
|
60
|
+
step(5, 12, "Copying configuration files...");
|
|
43
61
|
copyConfigFiles(installDir);
|
|
62
|
+
ok("Constitution, standards, and config copied");
|
|
44
63
|
|
|
45
|
-
// Step
|
|
46
|
-
|
|
64
|
+
// ═══ Step 6: Install hooks with real paths ═══
|
|
65
|
+
step(6, 12, "Installing hooks...");
|
|
47
66
|
installHooks(installDir);
|
|
48
67
|
|
|
49
|
-
// Step
|
|
50
|
-
|
|
68
|
+
// ═══ Step 7: Configure runtime ═══
|
|
69
|
+
step(7, 12, "Configuring runtime...");
|
|
51
70
|
const adapter = await loadAdapter(runtime);
|
|
52
71
|
adapter.configureHooks(config, installDir);
|
|
72
|
+
ok(`${config.name} configured`);
|
|
53
73
|
|
|
54
|
-
// Step
|
|
55
|
-
|
|
56
|
-
|
|
74
|
+
// ═══ Step 8: Install ArkaOS skill to Claude Code ═══
|
|
75
|
+
step(8, 12, "Installing /arka skill...");
|
|
76
|
+
installSkill(config, installDir);
|
|
77
|
+
|
|
78
|
+
// ═══ Step 9: Create references and profile ═══
|
|
79
|
+
step(9, 12, "Creating references...");
|
|
57
80
|
writeFileSync(join(installDir, ".repo-path"), ARKAOS_ROOT);
|
|
58
|
-
|
|
59
|
-
const skillsDir = join(config.skillsDir, "arkaos");
|
|
81
|
+
const skillsDir = join(config.skillsDir || join(homedir(), ".claude", "skills"), "arkaos");
|
|
60
82
|
ensureDir(skillsDir);
|
|
61
83
|
writeFileSync(join(skillsDir, ".arkaos-root"), ARKAOS_ROOT);
|
|
62
|
-
|
|
84
|
+
|
|
63
85
|
const profilePath = join(installDir, "profile.json");
|
|
64
86
|
if (!existsSync(profilePath)) {
|
|
65
|
-
console.log(" New installation — profile created.");
|
|
66
87
|
writeFileSync(profilePath, JSON.stringify({
|
|
67
88
|
version: "2",
|
|
68
89
|
created: new Date().toISOString(),
|
|
69
90
|
}, null, 2));
|
|
91
|
+
ok("New profile created");
|
|
92
|
+
} else {
|
|
93
|
+
ok("Existing profile preserved");
|
|
70
94
|
}
|
|
71
95
|
|
|
72
|
-
// Step
|
|
73
|
-
|
|
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)) {
|
|
100
|
+
try {
|
|
101
|
+
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 },
|
|
105
|
+
});
|
|
106
|
+
ok("ArkaOS skills indexed into knowledge base");
|
|
107
|
+
} catch {
|
|
108
|
+
warn("Knowledge indexing skipped (run 'npx arkaos index' later)");
|
|
109
|
+
}
|
|
110
|
+
} else {
|
|
111
|
+
ok("Knowledge base already exists");
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// ═══ Step 11: Verify installation ═══
|
|
115
|
+
step(11, 12, "Verifying installation...");
|
|
116
|
+
let checks = 0;
|
|
117
|
+
if (existsSync(join(installDir, "config", "constitution.yaml"))) checks++;
|
|
118
|
+
if (existsSync(join(installDir, "config", "hooks", "user-prompt-submit.sh"))) checks++;
|
|
119
|
+
if (existsSync(join(installDir, ".repo-path"))) checks++;
|
|
120
|
+
if (existsSync(profilePath)) checks++;
|
|
121
|
+
try {
|
|
122
|
+
execSync(`${pythonCmd} -c "from core.synapse.engine import SynapseEngine; print('ok')"`, {
|
|
123
|
+
stdio: "pipe", cwd: ARKAOS_ROOT, timeout: 10000,
|
|
124
|
+
});
|
|
125
|
+
checks++;
|
|
126
|
+
} catch {}
|
|
127
|
+
ok(`${checks}/5 checks passed`);
|
|
128
|
+
|
|
129
|
+
// ═══ Step 12: Finalize ═══
|
|
130
|
+
step(12, 12, "Finalizing...");
|
|
74
131
|
const manifest = {
|
|
75
132
|
version: VERSION,
|
|
76
133
|
runtime,
|
|
@@ -83,20 +140,49 @@ export async function install({ runtime, path, force }) {
|
|
|
83
140
|
};
|
|
84
141
|
writeFileSync(join(installDir, "install-manifest.json"), JSON.stringify(manifest, null, 2));
|
|
85
142
|
|
|
143
|
+
const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
|
|
144
|
+
|
|
86
145
|
console.log(`
|
|
87
|
-
|
|
146
|
+
╔══════════════════════════════════════════════════════════╗
|
|
147
|
+
║ ArkaOS v${VERSION} installed successfully! (${elapsed}s) ║
|
|
148
|
+
╚══════════════════════════════════════════════════════════╝
|
|
88
149
|
|
|
89
150
|
Runtime: ${config.name}
|
|
90
151
|
Install dir: ${installDir}
|
|
91
|
-
|
|
152
|
+
Agents: 65 across 17 departments
|
|
153
|
+
Skills: 244+ backed by enterprise frameworks
|
|
154
|
+
Knowledge: Vector DB with semantic search
|
|
155
|
+
Dashboard: Run 'npx arkaos dashboard' to start
|
|
156
|
+
|
|
157
|
+
Quick start:
|
|
158
|
+
/arka — Main orchestrator
|
|
159
|
+
/do <description> — Natural language routing
|
|
160
|
+
/dev feature — Development workflow
|
|
161
|
+
/mkt seo-audit — Marketing audit
|
|
162
|
+
/strat blue-ocean — Strategy analysis
|
|
92
163
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
164
|
+
Other commands:
|
|
165
|
+
npx arkaos dashboard — Open monitoring UI
|
|
166
|
+
npx arkaos index — Index your Obsidian vault
|
|
167
|
+
npx arkaos keys — Configure API keys
|
|
168
|
+
npx arkaos doctor — Run health checks
|
|
97
169
|
`);
|
|
98
170
|
}
|
|
99
171
|
|
|
172
|
+
// ═══ Helper Functions ═══
|
|
173
|
+
|
|
174
|
+
function step(n, total, msg) {
|
|
175
|
+
console.log(` [${n}/${total}] ${msg}`);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function ok(msg) {
|
|
179
|
+
console.log(` ✓ ${msg}`);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function warn(msg) {
|
|
183
|
+
console.log(` ⚠ ${msg}`);
|
|
184
|
+
}
|
|
185
|
+
|
|
100
186
|
function ensureDir(dir) {
|
|
101
187
|
if (!existsSync(dir)) {
|
|
102
188
|
mkdirSync(dir, { recursive: true });
|
|
@@ -116,34 +202,119 @@ function checkPython() {
|
|
|
116
202
|
continue;
|
|
117
203
|
}
|
|
118
204
|
}
|
|
119
|
-
console.error(
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
205
|
+
console.error(`
|
|
206
|
+
✗ Python 3.11+ is required but not found.
|
|
207
|
+
|
|
208
|
+
Install Python:
|
|
209
|
+
macOS: brew install python@3.13
|
|
210
|
+
Linux: sudo apt install python3.13
|
|
211
|
+
Windows: https://python.org/downloads/
|
|
212
|
+
`);
|
|
123
213
|
process.exit(1);
|
|
124
214
|
}
|
|
125
215
|
|
|
126
|
-
function
|
|
216
|
+
function installAllPythonDeps(pythonCmd) {
|
|
217
|
+
// Core dependencies
|
|
218
|
+
const coreDeps = "pyyaml pydantic rich click jinja2";
|
|
219
|
+
// Knowledge + Vector DB
|
|
220
|
+
const knowledgeDeps = "fastembed sqlite-vss";
|
|
221
|
+
// Ingest (YouTube, PDF, web, audio)
|
|
222
|
+
const ingestDeps = "yt-dlp pdfplumber beautifulsoup4 requests";
|
|
223
|
+
// Dashboard API
|
|
224
|
+
const dashboardDeps = "fastapi uvicorn";
|
|
225
|
+
// Transcription
|
|
226
|
+
const transcriptionDeps = "faster-whisper";
|
|
227
|
+
|
|
228
|
+
const allDeps = `${coreDeps} ${knowledgeDeps} ${ingestDeps} ${dashboardDeps}`;
|
|
229
|
+
|
|
127
230
|
try {
|
|
231
|
+
// Try uv first (faster)
|
|
128
232
|
try {
|
|
129
233
|
execSync("uv --version", { stdio: "pipe" });
|
|
130
|
-
|
|
234
|
+
console.log(" Using uv (fast installer)...");
|
|
235
|
+
execSync(`uv pip install ${allDeps}`, { stdio: "pipe", timeout: 300000 });
|
|
236
|
+
ok("Core + Knowledge + Ingest + Dashboard deps installed");
|
|
237
|
+
// Transcription optional (heavy)
|
|
238
|
+
try {
|
|
239
|
+
execSync(`uv pip install ${transcriptionDeps}`, { stdio: "pipe", timeout: 300000 });
|
|
240
|
+
ok("Whisper transcription installed");
|
|
241
|
+
} catch {
|
|
242
|
+
warn("Whisper not installed (optional — needed for YouTube/audio transcription)");
|
|
243
|
+
}
|
|
131
244
|
return;
|
|
132
245
|
} catch {
|
|
133
|
-
// uv not available
|
|
246
|
+
// uv not available, use pip
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
console.log(" Installing core dependencies...");
|
|
250
|
+
execSync(`${pythonCmd} -m pip install ${coreDeps} --quiet`, { stdio: "pipe", timeout: 120000 });
|
|
251
|
+
ok("Core deps installed (pyyaml, pydantic, rich, click, jinja2)");
|
|
252
|
+
|
|
253
|
+
console.log(" Installing knowledge base dependencies...");
|
|
254
|
+
try {
|
|
255
|
+
execSync(`${pythonCmd} -m pip install ${knowledgeDeps} --quiet`, { stdio: "pipe", timeout: 180000 });
|
|
256
|
+
ok("Vector DB installed (fastembed, sqlite-vss)");
|
|
257
|
+
} catch {
|
|
258
|
+
warn("Vector DB not installed (run: pip install fastembed sqlite-vss)");
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
console.log(" Installing content ingest dependencies...");
|
|
262
|
+
try {
|
|
263
|
+
execSync(`${pythonCmd} -m pip install ${ingestDeps} --quiet`, { stdio: "pipe", timeout: 120000 });
|
|
264
|
+
ok("Ingest deps installed (yt-dlp, pdfplumber, beautifulsoup4)");
|
|
265
|
+
} catch {
|
|
266
|
+
warn("Ingest deps not fully installed (some content types may not work)");
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
console.log(" Installing dashboard dependencies...");
|
|
270
|
+
try {
|
|
271
|
+
execSync(`${pythonCmd} -m pip install ${dashboardDeps} --quiet`, { stdio: "pipe", timeout: 60000 });
|
|
272
|
+
ok("Dashboard API installed (fastapi, uvicorn)");
|
|
273
|
+
} catch {
|
|
274
|
+
warn("Dashboard API not installed (run: pip install fastapi uvicorn)");
|
|
134
275
|
}
|
|
135
|
-
|
|
276
|
+
|
|
277
|
+
console.log(" Installing transcription engine...");
|
|
278
|
+
try {
|
|
279
|
+
execSync(`${pythonCmd} -m pip install ${transcriptionDeps} --quiet`, { stdio: "pipe", timeout: 300000 });
|
|
280
|
+
ok("Whisper transcription installed");
|
|
281
|
+
} catch {
|
|
282
|
+
warn("Whisper not installed (optional — needed for YouTube/audio)");
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Install ArkaOS itself as editable
|
|
286
|
+
try {
|
|
287
|
+
execSync(`${pythonCmd} -m pip install -e "${ARKAOS_ROOT}" --quiet`, { stdio: "pipe", timeout: 60000 });
|
|
288
|
+
} catch {}
|
|
289
|
+
|
|
136
290
|
} catch (err) {
|
|
137
|
-
|
|
138
|
-
console.
|
|
291
|
+
warn(`Some Python deps failed: ${err.message.slice(0, 100)}`);
|
|
292
|
+
console.log(" You can install manually: pip install pyyaml pydantic rich click fastembed sqlite-vss");
|
|
139
293
|
}
|
|
140
294
|
}
|
|
141
295
|
|
|
142
296
|
function copyConfigFiles(installDir) {
|
|
143
297
|
// Constitution
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
298
|
+
const files = [
|
|
299
|
+
["config/constitution.yaml", "config/constitution.yaml"],
|
|
300
|
+
];
|
|
301
|
+
|
|
302
|
+
// Standards
|
|
303
|
+
const standardsDir = join(ARKAOS_ROOT, "config", "standards");
|
|
304
|
+
if (existsSync(standardsDir)) {
|
|
305
|
+
ensureDir(join(installDir, "config", "standards"));
|
|
306
|
+
for (const f of readdirSync(standardsDir)) {
|
|
307
|
+
files.push([`config/standards/${f}`, `config/standards/${f}`]);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
for (const [src, dest] of files) {
|
|
312
|
+
const srcPath = join(ARKAOS_ROOT, src);
|
|
313
|
+
const destPath = join(installDir, dest);
|
|
314
|
+
if (existsSync(srcPath)) {
|
|
315
|
+
ensureDir(dirname(destPath));
|
|
316
|
+
copyFileSync(srcPath, destPath);
|
|
317
|
+
}
|
|
147
318
|
}
|
|
148
319
|
}
|
|
149
320
|
|
|
@@ -151,7 +322,6 @@ function installHooks(installDir) {
|
|
|
151
322
|
const hooksDir = join(installDir, "config", "hooks");
|
|
152
323
|
ensureDir(hooksDir);
|
|
153
324
|
|
|
154
|
-
// Copy v2 hooks, rename to standard names (without -v2 suffix)
|
|
155
325
|
const hookMap = {
|
|
156
326
|
"user-prompt-submit-v2.sh": "user-prompt-submit.sh",
|
|
157
327
|
"post-tool-use-v2.sh": "post-tool-use.sh",
|
|
@@ -164,22 +334,52 @@ function installHooks(installDir) {
|
|
|
164
334
|
const srcPath = join(srcHooksDir, src);
|
|
165
335
|
const destPath = join(hooksDir, dest);
|
|
166
336
|
if (existsSync(srcPath)) {
|
|
167
|
-
// Read, replace ARKAOS_ROOT placeholder, write
|
|
168
337
|
let content = readFileSync(srcPath, "utf-8");
|
|
169
|
-
//
|
|
338
|
+
// Set ARKAOS_ROOT to the npm package location (persistent)
|
|
170
339
|
content = content.replace(
|
|
171
340
|
/ARKAOS_ROOT="\$\{ARKA_OS:-\$HOME\/\.claude\/skills\/arkaos\}"/g,
|
|
172
|
-
`ARKAOS_ROOT="${
|
|
341
|
+
`ARKAOS_ROOT="${ARKAOS_ROOT}"`
|
|
173
342
|
);
|
|
174
343
|
content = content.replace(
|
|
175
344
|
/ARKAOS_HOME="\$\{HOME\}\/\.arkaos"/g,
|
|
176
345
|
`ARKAOS_HOME="${installDir}"`
|
|
177
346
|
);
|
|
178
347
|
writeFileSync(destPath, content);
|
|
179
|
-
try {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
348
|
+
try { chmodSync(destPath, 0o755); } catch {}
|
|
349
|
+
ok(`Hook: ${dest}`);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
function installSkill(config, installDir) {
|
|
355
|
+
// Copy arka/SKILL.md to Claude Code skills directory
|
|
356
|
+
const skillSrc = join(ARKAOS_ROOT, "arka", "SKILL.md");
|
|
357
|
+
const skillsBase = config.skillsDir || join(homedir(), ".claude", "skills");
|
|
358
|
+
const skillDest = join(skillsBase, "arka");
|
|
359
|
+
|
|
360
|
+
ensureDir(skillDest);
|
|
361
|
+
|
|
362
|
+
if (existsSync(skillSrc)) {
|
|
363
|
+
copyFileSync(skillSrc, join(skillDest, "SKILL.md"));
|
|
364
|
+
// Write repo path reference
|
|
365
|
+
writeFileSync(join(skillDest, ".repo-path"), ARKAOS_ROOT);
|
|
366
|
+
writeFileSync(join(skillDest, "VERSION"), VERSION);
|
|
367
|
+
ok("/arka skill installed → Claude Code can now use ArkaOS");
|
|
368
|
+
} else {
|
|
369
|
+
warn("SKILL.md not found in package");
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// Also copy department skills as references
|
|
373
|
+
const deptSkillSrc = join(ARKAOS_ROOT, "arka", "skills");
|
|
374
|
+
if (existsSync(deptSkillSrc)) {
|
|
375
|
+
const skillsOut = join(skillDest, "skills");
|
|
376
|
+
ensureDir(skillsOut);
|
|
377
|
+
try {
|
|
378
|
+
cpSync(deptSkillSrc, skillsOut, { recursive: true });
|
|
379
|
+
ok("Department skills copied");
|
|
380
|
+
} catch {
|
|
381
|
+
// cpSync may not be available in older Node
|
|
382
|
+
warn("Department skills copy skipped");
|
|
183
383
|
}
|
|
184
384
|
}
|
|
185
385
|
}
|
package/package.json
CHANGED