create-arete-workspace 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 +77 -0
- package/bin/arete.js +156 -0
- package/bin/create.js +111 -0
- package/lib/install-openclaw.js +50 -0
- package/lib/scaffold.js +213 -0
- package/lib/setup-wizard.js +88 -0
- package/lib/updater.js +130 -0
- package/package.json +34 -0
- package/packages/gatsaeng-os/README.md +36 -0
- package/packages/gatsaeng-os/components.json +23 -0
- package/packages/gatsaeng-os/eslint.config.mjs +18 -0
- package/packages/gatsaeng-os/next.config.ts +7 -0
- package/packages/gatsaeng-os/package.json +59 -0
- package/packages/gatsaeng-os/postcss.config.mjs +7 -0
- package/packages/gatsaeng-os/public/file.svg +1 -0
- package/packages/gatsaeng-os/public/globe.svg +1 -0
- package/packages/gatsaeng-os/public/next.svg +1 -0
- package/packages/gatsaeng-os/public/vercel.svg +1 -0
- package/packages/gatsaeng-os/public/window.svg +1 -0
- package/packages/gatsaeng-os/python/api_server.py +248 -0
- package/packages/gatsaeng-os/python/briefing.py +145 -0
- package/packages/gatsaeng-os/python/config.py +55 -0
- package/packages/gatsaeng-os/python/goal_context_agent.py +193 -0
- package/packages/gatsaeng-os/python/gyeokguk.py +171 -0
- package/packages/gatsaeng-os/python/proactive.py +158 -0
- package/packages/gatsaeng-os/python/requirements.txt +11 -0
- package/packages/gatsaeng-os/python/run.py +28 -0
- package/packages/gatsaeng-os/python/scoring.py +44 -0
- package/packages/gatsaeng-os/python/streak.py +70 -0
- package/packages/gatsaeng-os/python/telegram_bot.py +331 -0
- package/packages/gatsaeng-os/python/timing_engine.py +117 -0
- package/packages/gatsaeng-os/python/vault_io.py +423 -0
- package/packages/gatsaeng-os/src/app/(dashboard)/areas/[id]/page.tsx +215 -0
- package/packages/gatsaeng-os/src/app/(dashboard)/areas/page.tsx +161 -0
- package/packages/gatsaeng-os/src/app/(dashboard)/books/[id]/page.tsx +215 -0
- package/packages/gatsaeng-os/src/app/(dashboard)/books/page.tsx +268 -0
- package/packages/gatsaeng-os/src/app/(dashboard)/calendar/page.tsx +379 -0
- package/packages/gatsaeng-os/src/app/(dashboard)/error.tsx +30 -0
- package/packages/gatsaeng-os/src/app/(dashboard)/focus/page.tsx +293 -0
- package/packages/gatsaeng-os/src/app/(dashboard)/goals/[id]/page.tsx +426 -0
- package/packages/gatsaeng-os/src/app/(dashboard)/goals/page.tsx +178 -0
- package/packages/gatsaeng-os/src/app/(dashboard)/layout.tsx +29 -0
- package/packages/gatsaeng-os/src/app/(dashboard)/notes/[id]/page.tsx +147 -0
- package/packages/gatsaeng-os/src/app/(dashboard)/notes/page.tsx +254 -0
- package/packages/gatsaeng-os/src/app/(dashboard)/page.tsx +26 -0
- package/packages/gatsaeng-os/src/app/(dashboard)/projects/[id]/page.tsx +86 -0
- package/packages/gatsaeng-os/src/app/(dashboard)/projects/page.tsx +215 -0
- package/packages/gatsaeng-os/src/app/(dashboard)/review/page.tsx +475 -0
- package/packages/gatsaeng-os/src/app/(dashboard)/routines/page.tsx +436 -0
- package/packages/gatsaeng-os/src/app/(dashboard)/tasks/[id]/page.tsx +210 -0
- package/packages/gatsaeng-os/src/app/(dashboard)/tasks/page.tsx +307 -0
- package/packages/gatsaeng-os/src/app/(dashboard)/voice/page.tsx +212 -0
- package/packages/gatsaeng-os/src/app/api/areas/[id]/route.ts +26 -0
- package/packages/gatsaeng-os/src/app/api/areas/route.ts +22 -0
- package/packages/gatsaeng-os/src/app/api/auth/login/route.ts +52 -0
- package/packages/gatsaeng-os/src/app/api/auth/logout/route.ts +8 -0
- package/packages/gatsaeng-os/src/app/api/books/[id]/route.ts +27 -0
- package/packages/gatsaeng-os/src/app/api/books/route.ts +20 -0
- package/packages/gatsaeng-os/src/app/api/calendar/[id]/route.ts +24 -0
- package/packages/gatsaeng-os/src/app/api/calendar/import/route.ts +52 -0
- package/packages/gatsaeng-os/src/app/api/calendar/route.ts +37 -0
- package/packages/gatsaeng-os/src/app/api/daily/route.ts +51 -0
- package/packages/gatsaeng-os/src/app/api/goals/[id]/route.ts +34 -0
- package/packages/gatsaeng-os/src/app/api/goals/route.ts +30 -0
- package/packages/gatsaeng-os/src/app/api/logs/energy/route.ts +40 -0
- package/packages/gatsaeng-os/src/app/api/logs/focus/route.ts +22 -0
- package/packages/gatsaeng-os/src/app/api/logs/routine/route.ts +54 -0
- package/packages/gatsaeng-os/src/app/api/milestones/[id]/route.ts +26 -0
- package/packages/gatsaeng-os/src/app/api/milestones/route.ts +47 -0
- package/packages/gatsaeng-os/src/app/api/notes/[id]/route.ts +29 -0
- package/packages/gatsaeng-os/src/app/api/notes/route.ts +37 -0
- package/packages/gatsaeng-os/src/app/api/profile/route.ts +17 -0
- package/packages/gatsaeng-os/src/app/api/projects/[id]/route.ts +27 -0
- package/packages/gatsaeng-os/src/app/api/projects/route.ts +25 -0
- package/packages/gatsaeng-os/src/app/api/reviews/[id]/route.ts +26 -0
- package/packages/gatsaeng-os/src/app/api/reviews/route.ts +29 -0
- package/packages/gatsaeng-os/src/app/api/routines/[id]/route.ts +26 -0
- package/packages/gatsaeng-os/src/app/api/routines/route.ts +28 -0
- package/packages/gatsaeng-os/src/app/api/tasks/[id]/route.ts +28 -0
- package/packages/gatsaeng-os/src/app/api/tasks/route.ts +66 -0
- package/packages/gatsaeng-os/src/app/api/timing/current/route.ts +63 -0
- package/packages/gatsaeng-os/src/app/api/voice/chat/route.ts +50 -0
- package/packages/gatsaeng-os/src/app/api/voice/transcribe/route.ts +25 -0
- package/packages/gatsaeng-os/src/app/api/voice/tts/route.ts +36 -0
- package/packages/gatsaeng-os/src/app/error.tsx +30 -0
- package/packages/gatsaeng-os/src/app/favicon.ico +0 -0
- package/packages/gatsaeng-os/src/app/globals.css +208 -0
- package/packages/gatsaeng-os/src/app/layout.tsx +33 -0
- package/packages/gatsaeng-os/src/app/login/page.tsx +87 -0
- package/packages/gatsaeng-os/src/app/providers.tsx +27 -0
- package/packages/gatsaeng-os/src/components/ErrorBoundary.tsx +46 -0
- package/packages/gatsaeng-os/src/components/dashboard/DashboardGrid.tsx +86 -0
- package/packages/gatsaeng-os/src/components/dashboard/DdayWidget.tsx +88 -0
- package/packages/gatsaeng-os/src/components/dashboard/EnergyTracker.tsx +87 -0
- package/packages/gatsaeng-os/src/components/dashboard/FocusTimer.tsx +139 -0
- package/packages/gatsaeng-os/src/components/dashboard/GatsaengScore.tsx +30 -0
- package/packages/gatsaeng-os/src/components/dashboard/GoalRings.tsx +107 -0
- package/packages/gatsaeng-os/src/components/dashboard/ProactiveBar.tsx +98 -0
- package/packages/gatsaeng-os/src/components/dashboard/RoutineChecklist.tsx +81 -0
- package/packages/gatsaeng-os/src/components/dashboard/TimingWidget.tsx +86 -0
- package/packages/gatsaeng-os/src/components/dashboard/WidgetCustomizer.tsx +95 -0
- package/packages/gatsaeng-os/src/components/dashboard/WidgetWrapper.tsx +33 -0
- package/packages/gatsaeng-os/src/components/dashboard/ZeigarnikPanel.tsx +43 -0
- package/packages/gatsaeng-os/src/components/editor/EditorToolbar.tsx +186 -0
- package/packages/gatsaeng-os/src/components/editor/TiptapEditor.tsx +114 -0
- package/packages/gatsaeng-os/src/components/layout/Header.tsx +47 -0
- package/packages/gatsaeng-os/src/components/layout/MobileBottomNav.tsx +122 -0
- package/packages/gatsaeng-os/src/components/layout/MobileSidebar.tsx +29 -0
- package/packages/gatsaeng-os/src/components/layout/Sidebar.tsx +142 -0
- package/packages/gatsaeng-os/src/components/onboarding/OnboardingFlow.tsx +229 -0
- package/packages/gatsaeng-os/src/components/onboarding/OnboardingGate.tsx +78 -0
- package/packages/gatsaeng-os/src/components/projects/CalendarView.tsx +152 -0
- package/packages/gatsaeng-os/src/components/projects/KanbanView.tsx +180 -0
- package/packages/gatsaeng-os/src/components/projects/ListView.tsx +82 -0
- package/packages/gatsaeng-os/src/components/projects/TableView.tsx +206 -0
- package/packages/gatsaeng-os/src/components/projects/TaskCard.tsx +154 -0
- package/packages/gatsaeng-os/src/components/projects/TaskForm.tsx +128 -0
- package/packages/gatsaeng-os/src/components/projects/ViewSwitcher.tsx +40 -0
- package/packages/gatsaeng-os/src/components/search/GlobalSearch.tsx +179 -0
- package/packages/gatsaeng-os/src/components/shared/InlineEdit.tsx +77 -0
- package/packages/gatsaeng-os/src/components/shared/PinButton.tsx +42 -0
- package/packages/gatsaeng-os/src/components/tasks/DDayBadge.tsx +34 -0
- package/packages/gatsaeng-os/src/components/ui/badge.tsx +48 -0
- package/packages/gatsaeng-os/src/components/ui/button.tsx +64 -0
- package/packages/gatsaeng-os/src/components/ui/card.tsx +92 -0
- package/packages/gatsaeng-os/src/components/ui/checkbox.tsx +32 -0
- package/packages/gatsaeng-os/src/components/ui/command.tsx +184 -0
- package/packages/gatsaeng-os/src/components/ui/dialog.tsx +158 -0
- package/packages/gatsaeng-os/src/components/ui/input.tsx +21 -0
- package/packages/gatsaeng-os/src/components/ui/label.tsx +24 -0
- package/packages/gatsaeng-os/src/components/ui/popover.tsx +89 -0
- package/packages/gatsaeng-os/src/components/ui/progress.tsx +31 -0
- package/packages/gatsaeng-os/src/components/ui/select.tsx +190 -0
- package/packages/gatsaeng-os/src/components/ui/sheet.tsx +143 -0
- package/packages/gatsaeng-os/src/components/ui/tabs.tsx +91 -0
- package/packages/gatsaeng-os/src/components/ui/toggle-group.tsx +83 -0
- package/packages/gatsaeng-os/src/components/ui/toggle.tsx +47 -0
- package/packages/gatsaeng-os/src/components/ui/tooltip.tsx +57 -0
- package/packages/gatsaeng-os/src/hooks/useAreas.ts +53 -0
- package/packages/gatsaeng-os/src/hooks/useBooks.ts +62 -0
- package/packages/gatsaeng-os/src/hooks/useCalendar.ts +59 -0
- package/packages/gatsaeng-os/src/hooks/useDaily.ts +15 -0
- package/packages/gatsaeng-os/src/hooks/useGlobalTasks.ts +45 -0
- package/packages/gatsaeng-os/src/hooks/useGoals.ts +53 -0
- package/packages/gatsaeng-os/src/hooks/useMilestones.ts +75 -0
- package/packages/gatsaeng-os/src/hooks/useNotes.ts +65 -0
- package/packages/gatsaeng-os/src/hooks/useProjects.ts +102 -0
- package/packages/gatsaeng-os/src/hooks/useRoutines.ts +76 -0
- package/packages/gatsaeng-os/src/hooks/useTiming.ts +27 -0
- package/packages/gatsaeng-os/src/lib/apiFetch.ts +14 -0
- package/packages/gatsaeng-os/src/lib/auth.ts +32 -0
- package/packages/gatsaeng-os/src/lib/date.ts +7 -0
- package/packages/gatsaeng-os/src/lib/editor/markdown.ts +35 -0
- package/packages/gatsaeng-os/src/lib/llm-governor.ts +167 -0
- package/packages/gatsaeng-os/src/lib/neuroscience/energyCycle.ts +35 -0
- package/packages/gatsaeng-os/src/lib/neuroscience/habitStack.ts +22 -0
- package/packages/gatsaeng-os/src/lib/neuroscience/scoring.ts +32 -0
- package/packages/gatsaeng-os/src/lib/routes.ts +15 -0
- package/packages/gatsaeng-os/src/lib/utils.ts +6 -0
- package/packages/gatsaeng-os/src/lib/vault/config.ts +29 -0
- package/packages/gatsaeng-os/src/lib/vault/frontmatter.ts +84 -0
- package/packages/gatsaeng-os/src/lib/vault/index.ts +180 -0
- package/packages/gatsaeng-os/src/lib/vault/schemas.ts +274 -0
- package/packages/gatsaeng-os/src/middleware.ts +34 -0
- package/packages/gatsaeng-os/src/stores/dashboardStore.ts +26 -0
- package/packages/gatsaeng-os/src/stores/favoritesStore.ts +47 -0
- package/packages/gatsaeng-os/src/stores/timerStore.ts +65 -0
- package/packages/gatsaeng-os/src/types/index.ts +320 -0
- package/packages/gatsaeng-os/tsconfig.json +34 -0
- package/templates/scripts/forge_qa.sh.tmpl +237 -0
- package/templates/scripts/forge_ship.sh.tmpl +183 -0
- package/templates/scripts/session_indexer.py.tmpl +420 -0
- package/templates/scripts/tracer.py.tmpl +266 -0
- package/templates/workspace/AGENTS.md.tmpl +190 -0
- package/templates/workspace/BOOTSTRAP.md.tmpl +27 -0
- package/templates/workspace/HEARTBEAT.md.tmpl +23 -0
- package/templates/workspace/MEMORY.md.tmpl +35 -0
- package/templates/workspace/SOUL.md.tmpl +258 -0
- package/templates/workspace/TOOLS.md.tmpl +28 -0
- package/templates/workspace/USER.md.tmpl +43 -0
package/README.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# ARETE Starter
|
|
2
|
+
|
|
3
|
+
AI Operating System — set up in 5 minutes.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx create-arete-workspace
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## What's Included
|
|
12
|
+
|
|
13
|
+
- **Eve**: AI Chief of Staff (Telegram integration)
|
|
14
|
+
- **Memory Bridge**: Auto-integrate knowledge across agents
|
|
15
|
+
- **FORGE Workflow**: Coding agent + Impact Map
|
|
16
|
+
- **Verify Loop**: Automatic implementation verification
|
|
17
|
+
- **Tracer Agent**: Evidence-based bug causal tracking
|
|
18
|
+
|
|
19
|
+
## 갓생OS
|
|
20
|
+
|
|
21
|
+
Neuroscience-based habit & productivity dashboard powered by Obsidian.
|
|
22
|
+
|
|
23
|
+
- **Dashboard**: Routines, goals, D-day, energy tracking, focus timer
|
|
24
|
+
- **Obsidian Vault Backend**: All data stored as markdown with frontmatter
|
|
25
|
+
- **Neuroscience Engine**: Ultradian rhythm scoring, habit stacking, Zeigarnik tracking
|
|
26
|
+
- **Voice AI**: Eve voice assistant integration (OpenAI)
|
|
27
|
+
- **Review System**: Weekly/monthly plan & retrospective
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# Launch 갓생OS dashboard
|
|
31
|
+
arete start
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Runs on `http://localhost:3000` (Next.js dev server). Requires `VAULT_PATH` pointing to your Obsidian vault.
|
|
35
|
+
|
|
36
|
+
## Architecture
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
Layer 1 (Framework) — updated via `arete update`
|
|
40
|
+
├── scripts/ Session indexer, tracer, forge tools
|
|
41
|
+
└── templates/ System templates
|
|
42
|
+
|
|
43
|
+
Layer 2 (User Config) — NEVER auto-updated
|
|
44
|
+
├── SOUL.md Agent personality & behavior
|
|
45
|
+
├── AGENTS.md Agent routing & policies
|
|
46
|
+
├── MEMORY.md Persistent memory
|
|
47
|
+
├── USER.md User profile & preferences
|
|
48
|
+
├── TOOLS.md Local environment config
|
|
49
|
+
├── HEARTBEAT.md Health monitoring rules
|
|
50
|
+
└── BOOTSTRAP.md Session startup protocol
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Commands
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Initial setup
|
|
57
|
+
npx create-arete-workspace
|
|
58
|
+
|
|
59
|
+
# Check status
|
|
60
|
+
arete status
|
|
61
|
+
|
|
62
|
+
# Launch 갓생OS dashboard
|
|
63
|
+
arete start
|
|
64
|
+
|
|
65
|
+
# Update framework only (config files protected)
|
|
66
|
+
arete update
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Update Safety
|
|
70
|
+
|
|
71
|
+
`arete update` only touches Layer 1 files (scripts, templates). Your personal configuration files (SOUL.md, AGENTS.md, MEMORY.md, USER.md, etc.) are never modified during updates.
|
|
72
|
+
|
|
73
|
+
## Requirements
|
|
74
|
+
|
|
75
|
+
- Node.js 18+
|
|
76
|
+
- Python 3.10+
|
|
77
|
+
- macOS or Linux
|
package/bin/arete.js
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { checkForUpdate, runUpdate } from '../lib/updater.js';
|
|
5
|
+
import { execSync } from 'child_process';
|
|
6
|
+
import { readFileSync, existsSync, readdirSync, statSync } from 'fs';
|
|
7
|
+
import { resolve, join } from 'path';
|
|
8
|
+
import { homedir } from 'os';
|
|
9
|
+
|
|
10
|
+
const command = process.argv[2];
|
|
11
|
+
|
|
12
|
+
async function cmdUpdate() {
|
|
13
|
+
console.log(chalk.blue('Checking for updates...'));
|
|
14
|
+
const result = await checkForUpdate();
|
|
15
|
+
|
|
16
|
+
if (!result.updateAvailable) {
|
|
17
|
+
console.log(chalk.green(`Already on latest version (${result.currentVersion})`));
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
console.log(chalk.yellow(`Update available: ${result.currentVersion} → ${result.latestVersion}`));
|
|
22
|
+
console.log('');
|
|
23
|
+
|
|
24
|
+
await runUpdate(result.latestVersion);
|
|
25
|
+
console.log(chalk.green('Update complete!'));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function cmdStatus() {
|
|
29
|
+
console.log(chalk.bold('ARETE Status'));
|
|
30
|
+
console.log('');
|
|
31
|
+
|
|
32
|
+
// OpenClaw running?
|
|
33
|
+
let openclawRunning = false;
|
|
34
|
+
try {
|
|
35
|
+
const out = execSync('openclaw status', { stdio: 'pipe', timeout: 5000 }).toString();
|
|
36
|
+
openclawRunning = out.toLowerCase().includes('running');
|
|
37
|
+
console.log(` OpenClaw: ${openclawRunning ? chalk.green('running') : chalk.yellow('stopped')}`);
|
|
38
|
+
} catch {
|
|
39
|
+
console.log(` OpenClaw: ${chalk.red('not detected')}`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Workspace path
|
|
43
|
+
const workspacePath = resolve(homedir(), '.openclaw', 'workspace');
|
|
44
|
+
if (existsSync(workspacePath)) {
|
|
45
|
+
console.log(` Workspace: ${chalk.dim(workspacePath)}`);
|
|
46
|
+
} else {
|
|
47
|
+
console.log(` Workspace: ${chalk.red('not found')}`);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Agent count
|
|
52
|
+
const agentsDir = resolve(homedir(), '.openclaw', 'agents');
|
|
53
|
+
if (existsSync(agentsDir)) {
|
|
54
|
+
try {
|
|
55
|
+
const agents = readdirSync(agentsDir).filter((f) =>
|
|
56
|
+
statSync(join(agentsDir, f)).isDirectory()
|
|
57
|
+
);
|
|
58
|
+
console.log(` Agents: ${chalk.bold(agents.length)}`);
|
|
59
|
+
} catch {
|
|
60
|
+
console.log(` Agents: ${chalk.dim('unknown')}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Last memory update
|
|
65
|
+
const memoryDir = resolve(workspacePath, 'memory');
|
|
66
|
+
if (existsSync(memoryDir)) {
|
|
67
|
+
try {
|
|
68
|
+
const files = readdirSync(memoryDir)
|
|
69
|
+
.filter((f) => f.endsWith('.md') && !f.startsWith('.'))
|
|
70
|
+
.sort()
|
|
71
|
+
.reverse();
|
|
72
|
+
if (files.length > 0) {
|
|
73
|
+
console.log(` Last memory: ${chalk.dim(files[0])}`);
|
|
74
|
+
}
|
|
75
|
+
} catch {
|
|
76
|
+
console.log(` Last memory: ${chalk.dim('unknown')}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Package version
|
|
81
|
+
try {
|
|
82
|
+
const pkg = JSON.parse(
|
|
83
|
+
readFileSync(new URL('../package.json', import.meta.url), 'utf-8')
|
|
84
|
+
);
|
|
85
|
+
console.log(` Version: ${chalk.dim(pkg.version)}`);
|
|
86
|
+
} catch {}
|
|
87
|
+
|
|
88
|
+
console.log('');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function cmdStart() {
|
|
92
|
+
const workspacePath = resolve(homedir(), '.openclaw', 'workspace');
|
|
93
|
+
const gatsaengDir = join(workspacePath, 'gatsaeng-os');
|
|
94
|
+
|
|
95
|
+
if (!existsSync(gatsaengDir)) {
|
|
96
|
+
console.log(chalk.red('갓생OS not found. Run create-arete-workspace with 갓생OS enabled.'));
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const pkgJson = join(gatsaengDir, 'package.json');
|
|
101
|
+
if (!existsSync(pkgJson)) {
|
|
102
|
+
console.log(chalk.red('갓생OS package.json not found.'));
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Check if node_modules exists, install if not
|
|
107
|
+
if (!existsSync(join(gatsaengDir, 'node_modules'))) {
|
|
108
|
+
console.log(chalk.blue('Installing 갓생OS dependencies...'));
|
|
109
|
+
try {
|
|
110
|
+
execSync('npm install', { cwd: gatsaengDir, stdio: 'inherit' });
|
|
111
|
+
} catch {
|
|
112
|
+
console.log(chalk.red('Failed to install dependencies.'));
|
|
113
|
+
process.exit(1);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
console.log(chalk.green('Starting 갓생OS...'));
|
|
118
|
+
console.log(chalk.dim(` ${gatsaengDir}`));
|
|
119
|
+
console.log('');
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
execSync('npm run dev', { cwd: gatsaengDir, stdio: 'inherit' });
|
|
123
|
+
} catch {
|
|
124
|
+
// User ctrl-c — normal exit
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function showHelp() {
|
|
129
|
+
console.log('');
|
|
130
|
+
console.log(chalk.bold(' arete') + ' — ARETE workspace manager');
|
|
131
|
+
console.log('');
|
|
132
|
+
console.log(' Commands:');
|
|
133
|
+
console.log(' start Launch 갓생OS dashboard');
|
|
134
|
+
console.log(' update Update framework files (Layer 1 only)');
|
|
135
|
+
console.log(' status Show workspace status');
|
|
136
|
+
console.log(' help Show this help');
|
|
137
|
+
console.log('');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
switch (command) {
|
|
141
|
+
case 'start':
|
|
142
|
+
cmdStart();
|
|
143
|
+
break;
|
|
144
|
+
case 'update':
|
|
145
|
+
cmdUpdate().catch((e) => {
|
|
146
|
+
console.error(chalk.red('Update failed: ' + e.message));
|
|
147
|
+
process.exit(1);
|
|
148
|
+
});
|
|
149
|
+
break;
|
|
150
|
+
case 'status':
|
|
151
|
+
cmdStatus();
|
|
152
|
+
break;
|
|
153
|
+
default:
|
|
154
|
+
showHelp();
|
|
155
|
+
break;
|
|
156
|
+
}
|
package/bin/create.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { dirname, resolve } from 'path';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import { checkEnvironment } from '../lib/install-openclaw.js';
|
|
7
|
+
import { runWizard } from '../lib/setup-wizard.js';
|
|
8
|
+
import { scaffold } from '../lib/scaffold.js';
|
|
9
|
+
import { execSync } from 'child_process';
|
|
10
|
+
|
|
11
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
12
|
+
const __dirname = dirname(__filename);
|
|
13
|
+
const ROOT = resolve(__dirname, '..');
|
|
14
|
+
|
|
15
|
+
const DRY_RUN = process.argv.includes('--dry-run');
|
|
16
|
+
|
|
17
|
+
async function main() {
|
|
18
|
+
console.log('');
|
|
19
|
+
console.log(chalk.bold(' ARETE Workspace Setup'));
|
|
20
|
+
console.log(chalk.dim(' AI Operating System in 5 minutes'));
|
|
21
|
+
console.log('');
|
|
22
|
+
|
|
23
|
+
// Step 1: Environment check
|
|
24
|
+
console.log(chalk.blue('[1/5]') + ' Checking environment...');
|
|
25
|
+
const envOk = await checkEnvironment({ dryRun: DRY_RUN });
|
|
26
|
+
if (!envOk) {
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
console.log(chalk.green(' Environment OK'));
|
|
30
|
+
console.log('');
|
|
31
|
+
|
|
32
|
+
// Step 2: OpenClaw check
|
|
33
|
+
console.log(chalk.blue('[2/5]') + ' Checking OpenClaw...');
|
|
34
|
+
let openclawInstalled = false;
|
|
35
|
+
try {
|
|
36
|
+
execSync('openclaw --version', { stdio: 'pipe' });
|
|
37
|
+
openclawInstalled = true;
|
|
38
|
+
console.log(chalk.green(' OpenClaw found'));
|
|
39
|
+
} catch {
|
|
40
|
+
openclawInstalled = false;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (!openclawInstalled) {
|
|
44
|
+
const { default: inquirer } = await import('inquirer');
|
|
45
|
+
const { install } = await inquirer.prompt([
|
|
46
|
+
{
|
|
47
|
+
type: 'confirm',
|
|
48
|
+
name: 'install',
|
|
49
|
+
message: 'OpenClaw not found. Install now?',
|
|
50
|
+
default: true,
|
|
51
|
+
},
|
|
52
|
+
]);
|
|
53
|
+
if (install) {
|
|
54
|
+
if (DRY_RUN) {
|
|
55
|
+
console.log(chalk.yellow(' [dry-run] Would run: npm install -g openclaw'));
|
|
56
|
+
} else {
|
|
57
|
+
console.log(' Installing OpenClaw...');
|
|
58
|
+
try {
|
|
59
|
+
execSync('npm install -g openclaw', { stdio: 'inherit' });
|
|
60
|
+
console.log(chalk.green(' OpenClaw installed'));
|
|
61
|
+
} catch (e) {
|
|
62
|
+
console.log(chalk.red(' Failed to install OpenClaw.'));
|
|
63
|
+
console.log(chalk.dim(' Try manually: npm install -g openclaw'));
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
} else {
|
|
68
|
+
console.log(chalk.red(' OpenClaw is required. Exiting.'));
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
console.log('');
|
|
73
|
+
|
|
74
|
+
// Step 3: Interactive wizard
|
|
75
|
+
console.log(chalk.blue('[3/5]') + ' Configuration...');
|
|
76
|
+
const config = await runWizard({ dryRun: DRY_RUN });
|
|
77
|
+
console.log('');
|
|
78
|
+
|
|
79
|
+
// Step 4: Scaffold workspace
|
|
80
|
+
console.log(chalk.blue('[4/5]') + ' Creating workspace...');
|
|
81
|
+
await scaffold({ config, templateDir: resolve(ROOT, 'templates'), dryRun: DRY_RUN });
|
|
82
|
+
console.log(chalk.green(' Workspace created at ' + config.workspacePath));
|
|
83
|
+
console.log('');
|
|
84
|
+
|
|
85
|
+
// Step 5: openclaw init
|
|
86
|
+
console.log(chalk.blue('[5/5]') + ' Registering with OpenClaw...');
|
|
87
|
+
if (DRY_RUN) {
|
|
88
|
+
console.log(chalk.yellow(' [dry-run] Would run: openclaw init in ' + config.workspacePath));
|
|
89
|
+
} else {
|
|
90
|
+
try {
|
|
91
|
+
execSync('openclaw init', { cwd: config.workspacePath, stdio: 'inherit' });
|
|
92
|
+
} catch {
|
|
93
|
+
console.log(chalk.yellow(' openclaw init skipped (may need manual setup)'));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Done
|
|
98
|
+
console.log('');
|
|
99
|
+
console.log(chalk.green.bold(' ARETE workspace setup complete!'));
|
|
100
|
+
console.log('');
|
|
101
|
+
console.log(' Next steps:');
|
|
102
|
+
console.log(` 1. Find your bot on Telegram and send ${chalk.bold('/start')}`);
|
|
103
|
+
console.log(` 2. Run ${chalk.bold('openclaw start')}`);
|
|
104
|
+
console.log(' 3. Send your first message');
|
|
105
|
+
console.log('');
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
main().catch((err) => {
|
|
109
|
+
console.error(chalk.red('Error: ' + err.message));
|
|
110
|
+
process.exit(1);
|
|
111
|
+
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
|
|
4
|
+
export async function checkEnvironment({ dryRun = false } = {}) {
|
|
5
|
+
const errors = [];
|
|
6
|
+
|
|
7
|
+
// OS check
|
|
8
|
+
const platform = process.platform;
|
|
9
|
+
if (platform !== 'darwin' && platform !== 'linux') {
|
|
10
|
+
errors.push(`Unsupported OS: ${platform}. ARETE requires macOS or Linux.`);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Node.js 18+
|
|
14
|
+
const nodeVersion = process.versions.node;
|
|
15
|
+
const major = parseInt(nodeVersion.split('.')[0], 10);
|
|
16
|
+
if (major < 18) {
|
|
17
|
+
errors.push(`Node.js ${nodeVersion} detected. ARETE requires Node.js 18+.`);
|
|
18
|
+
console.log(chalk.dim(' Install: https://nodejs.org/'));
|
|
19
|
+
} else {
|
|
20
|
+
console.log(chalk.dim(` Node.js ${nodeVersion}`));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Python 3.10+
|
|
24
|
+
try {
|
|
25
|
+
const pyVersion = execSync('python3 --version', { stdio: 'pipe' }).toString().trim();
|
|
26
|
+
const match = pyVersion.match(/Python (\d+)\.(\d+)/);
|
|
27
|
+
if (match) {
|
|
28
|
+
const pyMajor = parseInt(match[1], 10);
|
|
29
|
+
const pyMinor = parseInt(match[2], 10);
|
|
30
|
+
if (pyMajor < 3 || (pyMajor === 3 && pyMinor < 10)) {
|
|
31
|
+
errors.push(`${pyVersion} detected. ARETE requires Python 3.10+.`);
|
|
32
|
+
} else {
|
|
33
|
+
console.log(chalk.dim(` ${pyVersion}`));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
} catch {
|
|
37
|
+
errors.push('Python 3 not found. ARETE requires Python 3.10+.');
|
|
38
|
+
console.log(chalk.dim(' Install: https://www.python.org/downloads/'));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (errors.length > 0) {
|
|
42
|
+
console.log('');
|
|
43
|
+
for (const err of errors) {
|
|
44
|
+
console.log(chalk.red(' ' + err));
|
|
45
|
+
}
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return true;
|
|
50
|
+
}
|
package/lib/scaffold.js
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync, cpSync } from 'fs';
|
|
2
|
+
import { resolve, join, dirname } from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
|
|
6
|
+
function replaceVars(content, vars) {
|
|
7
|
+
let result = content;
|
|
8
|
+
for (const [key, value] of Object.entries(vars)) {
|
|
9
|
+
result = result.replaceAll(`{{${key}}}`, value);
|
|
10
|
+
}
|
|
11
|
+
return result;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function generateDomainAgentsTable(domains) {
|
|
15
|
+
if (!domains || domains.length === 0) return '(No domain agents configured)';
|
|
16
|
+
const rows = domains.map(
|
|
17
|
+
(d) => `| ${d} | ${d}-analyst sub-agent spawn |`
|
|
18
|
+
);
|
|
19
|
+
return `| Domain | Routing |\n|--------|--------|\n${rows.join('\n')}`;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function generateDomainAgentsConfig(domains) {
|
|
23
|
+
if (!domains || domains.length === 0) return '{}';
|
|
24
|
+
const config = {};
|
|
25
|
+
for (const d of domains) {
|
|
26
|
+
config[`${d}-analyst`] = { tag: d.charAt(0).toUpperCase() + d.slice(1), emoji: '📊' };
|
|
27
|
+
}
|
|
28
|
+
return JSON.stringify(config, null, 4);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export async function scaffold({ config, templateDir, dryRun = false }) {
|
|
32
|
+
const { name, telegramToken, agentName, domains, workspacePath, openclawPath } = config;
|
|
33
|
+
|
|
34
|
+
const vars = {
|
|
35
|
+
NAME: name,
|
|
36
|
+
AGENT_NAME: agentName,
|
|
37
|
+
TELEGRAM_TOKEN: telegramToken,
|
|
38
|
+
WORKSPACE_PATH: workspacePath,
|
|
39
|
+
OPENCLAW_PATH: openclawPath,
|
|
40
|
+
DOMAINS: domains.join(', '),
|
|
41
|
+
DOMAIN_AGENTS_TABLE: generateDomainAgentsTable(domains),
|
|
42
|
+
DOMAIN_AGENTS_CONFIG: generateDomainAgentsConfig(domains),
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// Create workspace directories
|
|
46
|
+
const dirs = [
|
|
47
|
+
workspacePath,
|
|
48
|
+
join(workspacePath, 'memory'),
|
|
49
|
+
join(workspacePath, 'scripts'),
|
|
50
|
+
join(workspacePath, 'data'),
|
|
51
|
+
join(workspacePath, 'data', 'traces'),
|
|
52
|
+
join(workspacePath, 'ref'),
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
for (const dir of dirs) {
|
|
56
|
+
if (dryRun) {
|
|
57
|
+
console.log(chalk.yellow(` [dry-run] Would create dir: ${dir}`));
|
|
58
|
+
} else {
|
|
59
|
+
mkdirSync(dir, { recursive: true });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Process workspace templates
|
|
64
|
+
const wsTemplateDir = join(templateDir, 'workspace');
|
|
65
|
+
if (existsSync(wsTemplateDir)) {
|
|
66
|
+
const templates = readdirSync(wsTemplateDir).filter((f) => f.endsWith('.tmpl'));
|
|
67
|
+
for (const tmpl of templates) {
|
|
68
|
+
const outputName = tmpl.replace('.tmpl', '');
|
|
69
|
+
const outputPath = join(workspacePath, outputName);
|
|
70
|
+
const content = readFileSync(join(wsTemplateDir, tmpl), 'utf-8');
|
|
71
|
+
const rendered = replaceVars(content, vars);
|
|
72
|
+
|
|
73
|
+
if (dryRun) {
|
|
74
|
+
console.log(chalk.yellow(` [dry-run] Would write: ${outputPath}`));
|
|
75
|
+
} else {
|
|
76
|
+
writeFileSync(outputPath, rendered, 'utf-8');
|
|
77
|
+
console.log(chalk.dim(` Created: ${outputName}`));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Process script templates
|
|
83
|
+
const scriptTemplateDir = join(templateDir, 'scripts');
|
|
84
|
+
if (existsSync(scriptTemplateDir)) {
|
|
85
|
+
const scripts = readdirSync(scriptTemplateDir).filter((f) => f.endsWith('.tmpl'));
|
|
86
|
+
for (const tmpl of scripts) {
|
|
87
|
+
const outputName = tmpl.replace('.tmpl', '');
|
|
88
|
+
const outputPath = join(workspacePath, 'scripts', outputName);
|
|
89
|
+
const content = readFileSync(join(scriptTemplateDir, tmpl), 'utf-8');
|
|
90
|
+
const rendered = replaceVars(content, vars);
|
|
91
|
+
|
|
92
|
+
if (dryRun) {
|
|
93
|
+
console.log(chalk.yellow(` [dry-run] Would write: ${outputPath}`));
|
|
94
|
+
} else {
|
|
95
|
+
writeFileSync(outputPath, rendered, 'utf-8');
|
|
96
|
+
console.log(chalk.dim(` Created: scripts/${outputName}`));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Create .env template
|
|
102
|
+
const envPath = join(workspacePath, '.env.example');
|
|
103
|
+
const envContent = `# ARETE Workspace Environment
|
|
104
|
+
# Copy to .env and fill in your values
|
|
105
|
+
TELEGRAM_BOT_TOKEN=your_token_here
|
|
106
|
+
OPENAI_API_KEY=
|
|
107
|
+
ANTHROPIC_API_KEY=
|
|
108
|
+
`;
|
|
109
|
+
|
|
110
|
+
if (dryRun) {
|
|
111
|
+
console.log(chalk.yellow(` [dry-run] Would write: ${envPath}`));
|
|
112
|
+
} else {
|
|
113
|
+
writeFileSync(envPath, envContent, 'utf-8');
|
|
114
|
+
console.log(chalk.dim(' Created: .env.example'));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Create .gitignore
|
|
118
|
+
const gitignorePath = join(workspacePath, '.gitignore');
|
|
119
|
+
const gitignoreContent = `.env
|
|
120
|
+
.env.*
|
|
121
|
+
!.env.example
|
|
122
|
+
node_modules/
|
|
123
|
+
__pycache__/
|
|
124
|
+
*.pyc
|
|
125
|
+
.session_indexer_state.json
|
|
126
|
+
`;
|
|
127
|
+
|
|
128
|
+
if (dryRun) {
|
|
129
|
+
console.log(chalk.yellow(` [dry-run] Would write: ${gitignorePath}`));
|
|
130
|
+
} else {
|
|
131
|
+
writeFileSync(gitignorePath, gitignoreContent, 'utf-8');
|
|
132
|
+
console.log(chalk.dim(' Created: .gitignore'));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// 갓생OS scaffold
|
|
136
|
+
if (config.gatsaeng) {
|
|
137
|
+
await scaffoldGatsaeng({ config, dryRun });
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export async function scaffoldGatsaeng({ config, dryRun = false }) {
|
|
142
|
+
const { workspacePath, vaultPath } = config;
|
|
143
|
+
const gatsaengDir = join(workspacePath, 'gatsaeng-os');
|
|
144
|
+
|
|
145
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
146
|
+
const pkgRoot = resolve(dirname(__filename), '..');
|
|
147
|
+
const srcDir = join(pkgRoot, 'packages', 'gatsaeng-os');
|
|
148
|
+
|
|
149
|
+
if (!existsSync(srcDir)) {
|
|
150
|
+
console.log(chalk.red(' 갓생OS source not found in package. Skipping.'));
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
console.log(chalk.blue(' Setting up 갓생OS...'));
|
|
155
|
+
|
|
156
|
+
if (dryRun) {
|
|
157
|
+
console.log(chalk.yellow(` [dry-run] Would copy 갓생OS to: ${gatsaengDir}`));
|
|
158
|
+
console.log(chalk.yellow(` [dry-run] VAULT_PATH = ${vaultPath}`));
|
|
159
|
+
console.log(chalk.yellow(` [dry-run] Would create Obsidian vault dirs in: ${vaultPath}`));
|
|
160
|
+
console.log(chalk.yellow(' [dry-run] Would run: npm install in gatsaeng-os/'));
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Copy 갓생OS source
|
|
165
|
+
cpSync(srcDir, gatsaengDir, { recursive: true });
|
|
166
|
+
console.log(chalk.dim(' Copied 갓생OS source'));
|
|
167
|
+
|
|
168
|
+
// Create .env with VAULT_PATH
|
|
169
|
+
const envContent = `# 갓생OS Environment
|
|
170
|
+
VAULT_PATH=${vaultPath}
|
|
171
|
+
AUTH_USERNAME=admin
|
|
172
|
+
AUTH_PASSWORD=changeme
|
|
173
|
+
JWT_SECRET=${generateSecret()}
|
|
174
|
+
`;
|
|
175
|
+
writeFileSync(join(gatsaengDir, '.env'), envContent, 'utf-8');
|
|
176
|
+
console.log(chalk.dim(' Created gatsaeng-os/.env'));
|
|
177
|
+
|
|
178
|
+
// Create Obsidian vault directories
|
|
179
|
+
const vaultDirs = [
|
|
180
|
+
vaultPath,
|
|
181
|
+
join(vaultPath, 'areas'),
|
|
182
|
+
join(vaultPath, 'goals'),
|
|
183
|
+
join(vaultPath, 'milestones'),
|
|
184
|
+
join(vaultPath, 'projects'),
|
|
185
|
+
join(vaultPath, 'tasks'),
|
|
186
|
+
join(vaultPath, 'routines'),
|
|
187
|
+
join(vaultPath, 'reviews'),
|
|
188
|
+
join(vaultPath, 'sessions'),
|
|
189
|
+
join(vaultPath, 'timing'),
|
|
190
|
+
join(vaultPath, 'books'),
|
|
191
|
+
join(vaultPath, 'calendar'),
|
|
192
|
+
join(vaultPath, 'notes'),
|
|
193
|
+
join(vaultPath, 'logs', 'routine'),
|
|
194
|
+
join(vaultPath, 'logs', 'energy'),
|
|
195
|
+
join(vaultPath, 'logs', 'focus'),
|
|
196
|
+
];
|
|
197
|
+
|
|
198
|
+
for (const dir of vaultDirs) {
|
|
199
|
+
mkdirSync(dir, { recursive: true });
|
|
200
|
+
}
|
|
201
|
+
console.log(chalk.dim(` Created Obsidian vault dirs at ${vaultPath}`));
|
|
202
|
+
|
|
203
|
+
console.log(chalk.green(' 갓생OS ready — run `arete start` to launch'));
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function generateSecret() {
|
|
207
|
+
const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
|
208
|
+
let result = '';
|
|
209
|
+
for (let i = 0; i < 48; i++) {
|
|
210
|
+
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
211
|
+
}
|
|
212
|
+
return result;
|
|
213
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { resolve } from 'path';
|
|
2
|
+
import { homedir } from 'os';
|
|
3
|
+
|
|
4
|
+
export async function runWizard({ dryRun = false } = {}) {
|
|
5
|
+
if (dryRun) {
|
|
6
|
+
return {
|
|
7
|
+
name: 'TestUser',
|
|
8
|
+
telegramToken: 'dry-run-token',
|
|
9
|
+
agentName: 'Eve',
|
|
10
|
+
domains: ['invest', 'design'],
|
|
11
|
+
workspacePath: resolve(homedir(), 'arete-workspace'),
|
|
12
|
+
openclawPath: resolve(homedir(), '.openclaw'),
|
|
13
|
+
gatsaeng: true,
|
|
14
|
+
vaultPath: resolve(homedir(), 'Documents', 'Obsidian', 'GatsaengOS'),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const { default: inquirer } = await import('inquirer');
|
|
19
|
+
|
|
20
|
+
const answers = await inquirer.prompt([
|
|
21
|
+
{
|
|
22
|
+
type: 'input',
|
|
23
|
+
name: 'name',
|
|
24
|
+
message: 'Your name (English):',
|
|
25
|
+
validate: (v) => (v.trim().length > 0 ? true : 'Name is required'),
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
type: 'input',
|
|
29
|
+
name: 'telegramToken',
|
|
30
|
+
message: 'Telegram bot token:',
|
|
31
|
+
validate: (v) => (v.trim().length > 0 ? true : 'Token is required'),
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
type: 'input',
|
|
35
|
+
name: 'agentName',
|
|
36
|
+
message: 'Assistant name (default: Eve):',
|
|
37
|
+
default: 'Eve',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
type: 'input',
|
|
41
|
+
name: 'domainsRaw',
|
|
42
|
+
message: 'Primary domains (comma-separated, e.g. invest, design, marketing):',
|
|
43
|
+
default: 'general',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
type: 'input',
|
|
47
|
+
name: 'workspacePath',
|
|
48
|
+
message: `Workspace path (default: ${resolve(homedir(), 'arete-workspace')}):`,
|
|
49
|
+
default: resolve(homedir(), 'arete-workspace'),
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
type: 'confirm',
|
|
53
|
+
name: 'gatsaeng',
|
|
54
|
+
message: 'Install 갓생OS? (neuroscience-based habit & productivity dashboard)',
|
|
55
|
+
default: true,
|
|
56
|
+
},
|
|
57
|
+
]);
|
|
58
|
+
|
|
59
|
+
let vaultPath = '';
|
|
60
|
+
if (answers.gatsaeng) {
|
|
61
|
+
const vaultAnswer = await inquirer.prompt([
|
|
62
|
+
{
|
|
63
|
+
type: 'input',
|
|
64
|
+
name: 'vaultPath',
|
|
65
|
+
message: 'Obsidian vault path for 갓생OS data:',
|
|
66
|
+
default: resolve(homedir(), 'Documents', 'Obsidian', 'GatsaengOS'),
|
|
67
|
+
validate: (v) => (v.trim().length > 0 ? true : 'Vault path is required for 갓생OS'),
|
|
68
|
+
},
|
|
69
|
+
]);
|
|
70
|
+
vaultPath = resolve(vaultAnswer.vaultPath);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const domains = answers.domainsRaw
|
|
74
|
+
.split(',')
|
|
75
|
+
.map((d) => d.trim().toLowerCase())
|
|
76
|
+
.filter(Boolean);
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
name: answers.name.trim(),
|
|
80
|
+
telegramToken: answers.telegramToken.trim(),
|
|
81
|
+
agentName: answers.agentName.trim(),
|
|
82
|
+
domains,
|
|
83
|
+
workspacePath: resolve(answers.workspacePath),
|
|
84
|
+
openclawPath: resolve(homedir(), '.openclaw'),
|
|
85
|
+
gatsaeng: answers.gatsaeng,
|
|
86
|
+
vaultPath,
|
|
87
|
+
};
|
|
88
|
+
}
|