arisa 2.0.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/CLAUDE.md ADDED
@@ -0,0 +1,191 @@
1
+ # What is Arisa
2
+
3
+ Arisa is a Bun + TypeScript agent runtime with a two-process architecture: **Daemon** (stable channel I/O) and **Core** (message processing, media, scheduling, CLI routing). Telegram is one access channel, not the identity of the system.
4
+
5
+ Arisa is intentionally dynamic: the project grows as the user builds a relationship with it. Many capabilities are added live during real conversations (for example, Whisper support), so the system evolves through use instead of staying static.
6
+
7
+ ## Commands
8
+
9
+ ```bash
10
+ bun install # Install dependencies
11
+ bun run daemon # Start everything (Daemon spawns Core with --watch)
12
+ bun run dev # Start Core only with hot-reload (for development)
13
+ npm install -g . # Global install via Node/npm
14
+ bun add -g . # Global install via Bun
15
+ arisa # Start daemon from global install
16
+ ```
17
+
18
+ ## Architecture: Daemon + Core
19
+
20
+ ```
21
+ Daemon (:51778) Core (:51777)
22
+ ├── Telegram adapter (grammy) ├── HTTP server /message, /health
23
+ ├── HTTP server /send (for scheduler) ├── Claude CLI with model routing
24
+ ├── Bridge: HTTP client to Core ├── Media: voice (Whisper), vision, speech (ElevenLabs)
25
+ ├── Lifecycle: spawn Core --watch ├── Scheduler (croner)
26
+ └── In-memory queue if Core is down ├── Format: HTML + chunking
27
+ └── File detection in responses
28
+ ```
29
+
30
+ **Message flow:**
31
+ 1. Telegram → Daemon receives message (text/voice/photo)
32
+ 2. Daemon → POST Core:51777/message (media as base64)
33
+ 3. Core processes media → routes model → calls `claude CLI` → formats response
34
+ 4. Core returns response → Daemon sends to Telegram
35
+
36
+ **Scheduler flow:**
37
+ Scheduled task fires → Core POSTs to Daemon:51778/send → Telegram
38
+
39
+ ### Principle of separation
40
+
41
+ - **Daemon** = Channel I/O only. Receives/sends messages. Never processes content. Stable process that never needs restarting.
42
+ - **Core** = Everything else. Media processing, Claude CLI, formatting, scheduling. Runs with `bun --watch` for hot-reload when code changes.
43
+
44
+ ## File Structure
45
+
46
+ ```
47
+ src/
48
+ ├── daemon/
49
+ │ ├── index.ts # Entry: channel + HTTP server + spawn Core
50
+ │ ├── channels/
51
+ │ │ ├── base.ts # Re-exports Channel interface
52
+ │ │ └── telegram.ts # Telegram adapter (grammy)
53
+ │ ├── bridge.ts # HTTP client to Core with retry + in-memory queue
54
+ │ └── lifecycle.ts # Spawn Core with --watch, auto-restart
55
+
56
+ ├── core/
57
+ │ ├── index.ts # HTTP server with /message and /health endpoints
58
+ │ ├── processor.ts # Executes claude CLI with model routing
59
+ │ ├── router.ts # Selects model (haiku/sonnet/opus) by message pattern
60
+ │ ├── media.ts # Voice transcription (Whisper), image analysis (Vision), speech synthesis (ElevenLabs)
61
+ │ ├── scheduler.ts # Cron + one-time tasks with croner, persists via deepbase
62
+ │ ├── format.ts # Telegram chunking (4096 char limit)
63
+ │ ├── file-detector.ts # Detect file paths in responses for auto-sending
64
+ │ └── context.ts # Manage -c flag and reset_flag
65
+
66
+ └── shared/
67
+ ├── types.ts # All shared interfaces
68
+ ├── config.ts # Env vars, ports, paths
69
+ ├── logger.ts # Logger → .arisa/logs/
70
+ └── db.ts # Unified persistence layer (deepbase)
71
+ ```
72
+
73
+ ## Model Routing
74
+
75
+ The router (`src/core/router.ts`) selects Claude models based on message patterns:
76
+ - **Haiku**: Reminders, acknowledgments, simple yes/no
77
+ - **Sonnet** (default): General conversation, queries
78
+ - **Opus**: Code changes, debugging, complex multi-step tasks
79
+
80
+ ## Bot Commands
81
+
82
+ Available Telegram bot commands:
83
+ - `/reset` — Clear conversation history and start fresh
84
+ - `/cancel` — Cancel all scheduled tasks for this chat
85
+ - `/claude` — Switch to Claude backend (default)
86
+ - `/codex` — Switch to Codex backend
87
+ - `/speak <text>` — Generate speech from text using ElevenLabs (requires ELEVENLABS_API_KEY)
88
+
89
+ ## Adding a New Channel
90
+
91
+ Implement the `Channel` interface from `src/shared/types.ts` and register it in `src/daemon/index.ts`. The interface requires: `connect()`, `onMessage()`, `send()`, `sendFile()`.
92
+
93
+ ## Hooks
94
+
95
+ Configured in `.claude/settings.json`:
96
+ - **SessionStart**: Runs `session-start.sh` — outputs Arisa context reminder
97
+ - **PostToolUse** (async): Runs `log-activity.sh` — logs tool usage to `.arisa/logs/activity.log`
98
+
99
+ ## Runtime Data
100
+
101
+ All runtime data lives under `~/.arisa/` (with automatic migration from legacy project-local `.tinyclaw/` or `.arisa/`):
102
+ - `logs/` — per-component log files (core, daemon, telegram, scheduler)
103
+ - `db/arisa.json` — unified persistence with deepbase
104
+ - `attachments/` — saved media files organized by `{chatId}/`
105
+ - `.env` — TELEGRAM_BOT_TOKEN, OPENAI_API_KEY, ELEVENLABS_API_KEY
106
+ - `voice_temp/` — temporary directory for voice transcription
107
+ - `reset_flag` — conversation reset marker
108
+
109
+ ### Persistence with DeepBase
110
+
111
+ All persistent data is managed by **deepbase** (`src/shared/db.ts`). Location: `~/.arisa/db/arisa.json`.
112
+
113
+ | Collection | Key | Value type | Description |
114
+ |-----------------|---------------|--------------------|------------------------------------------|
115
+ | `tasks` | `task.id` | `ScheduledTask` | Cron and one-time scheduled tasks |
116
+ | `authorized` | `chatId` | `{ userId }` | Authorized Telegram chats |
117
+ | `onboarded` | `chatId` | `{ userId }` | Chats that completed onboarding |
118
+ | `queue` | `message.id` | queue message | In-memory queue overflow (Daemon→Core) |
119
+ | `attachments` | `chatId_file` | `AttachmentRecord` | Metadata for saved media (files on disk) |
120
+ | `messages` | `chatId_msgId`| `MessageRecord` | Message ledger for reply context |
121
+ | `settings` | key name | `{ value }` | App settings (auth_token, etc.) |
122
+
123
+ - **API**: `db.get(collection, key)`, `db.set(collection, key, data)`, `db.del(collection, key)`
124
+ - **Helper functions**: `src/shared/db.ts` provides type-safe wrappers per collection
125
+
126
+ ## Response Formatting
127
+
128
+ Telegram responses are sent with `parse_mode: 'HTML'`. When composing responses that will be sent through Telegram, use HTML formatting instead of Markdown. For example, use `<b>bold</b>` instead of `**bold**`, `<code>inline code</code>` instead of backticks, and `<pre>code block</pre>` instead of triple backticks.
129
+
130
+ ## Workflow Orchestration
131
+
132
+ ### 1. Plan Mode (On Request Only)
133
+ - Do NOT enter plan mode automatically — only when the user explicitly asks for it
134
+ - If something goes sideways, STOP and re-assess, but don't force plan mode
135
+ - When user requests planning: write detailed specs upfront to reduce ambiguity
136
+
137
+ ### 2. Subagent Strategy to keep main context window clean
138
+ - Offload research, exploration, and parallel analysis to subagents
139
+ - For complex problems, throw more compute at it via subagents
140
+ - One task per subagent for focused execution
141
+
142
+ ### 3. Self-Improvement Loop
143
+ - After ANY correction from the user: update 'tasks/lessons.md' with the pattern
144
+ - Write rules for yourself that prevent the same mistake
145
+ - Ruthlessly iterate on these lessons until mistake rate drops
146
+ - Review lessons at session start for relevant project
147
+
148
+ ### 4. Verification Before Done
149
+ - Never mark a task complete without proving it works
150
+ - Diff behavior between main and your changes when relevant
151
+ - Ask yourself: "Would a staff engineer approve this?"
152
+ - Run tests, check logs, demonstrate correctness
153
+
154
+ ### 5. Demand Elegance (Balanced)
155
+ - For non-trivial changes: pause and ask "is there a more elegant way?"
156
+ - If a fix feels hacky: "Knowing everything I know now, implement the elegant solution"
157
+ - Skip this for simple, obvious fixes - don't over-engineer
158
+ - Challenge your own work before presenting it
159
+
160
+ ### 6. Autonomous Bug Fixing
161
+ - When given a bug report: just fix it. Don't ask for hand-holding
162
+ - Point at logs, errors, failing tests -> then resolve them
163
+ - Zero context switching required from the user
164
+ - Go fix failing CI tests without being told how
165
+
166
+ ## Task Management
167
+ 1. **Plan First**: Write plan to 'tasks/todo.md' with checkable items
168
+ 2. **Verify Plan**: Check in before starting implementation
169
+ 3. **Track Progress**: Mark items complete as you go
170
+ 4. **Explain Changes**: High-level summary at each step
171
+ 5. **Document Results**: Add review to 'tasks/todo.md'
172
+ 6. **Capture Lessons**: Update 'tasks/lessons.md' after corrections
173
+
174
+ ## Voice Messages (ElevenLabs)
175
+
176
+ When you want to send a voice message to the user, wrap the spoken text in `[VOICE]...[/VOICE]` tags:
177
+
178
+ ```
179
+ [VOICE]Hola, esto se va a convertir en audio[/VOICE]
180
+ ```
181
+
182
+ - The text inside `[VOICE]` gets synthesized via ElevenLabs and sent as a Telegram voice message
183
+ - The `[VOICE]` tags are stripped from the text response — only the audio is sent
184
+ - Use it when the user asks you to "hablame", "mandame un audio", "decime con voz", etc.
185
+ - Keep voice texts concise — long texts cost more and take longer to generate
186
+ - You can combine voice with text: write a text response AND include a `[VOICE]` block
187
+
188
+ ## Core Principles
189
+ - **Simplicity First**: Make every change as simple as possible. Impact minimal code.
190
+ - **No Laziness**: Find root causes. No temporary fixes. Senior developer standards.
191
+ - **Minimal Impact**: Changes should only touch what's necessary. Avoid introducing bugs.
package/README.md ADDED
@@ -0,0 +1,200 @@
1
+ # What is Arisa
2
+
3
+ Arisa is a Bun + TypeScript agent runtime with a two-process architecture: **Daemon** (stable channel I/O) and **Core** (message processing, media, scheduling, CLI routing). Telegram is one access channel, not the identity of the system.
4
+
5
+ Inspired by the architecture of [`jlia0/tinyclaw`](https://github.com/jlia0/tinyclaw).
6
+
7
+ Arisa is intentionally dynamic: the project grows as the user builds a relationship with it. Many capabilities are added live during real conversations (for example, Whisper support), so the system evolves through use instead of staying static.
8
+
9
+ ## Security Notice
10
+
11
+ Arisa can execute actions with operational control over the system where it runs. Before deploying it, make sure you understand and accept the associated security risks. It is strongly recommended to run Arisa in an isolated environment (for example, a Docker container or a dedicated VPS) that does not store sensitive information or critical assets.
12
+
13
+ ## Commands
14
+
15
+ Requires [Bun](https://bun.sh).
16
+
17
+ ```bash
18
+ bun install # Install dependencies
19
+ bun run daemon # Start everything (Daemon spawns Core with --watch)
20
+ bun run dev # Start Core only with hot-reload (for development)
21
+ bun install -g arisa # Global install from package registry
22
+ npm install -g . # Global install via Node/npm
23
+ bun add -g . # Global install via Bun
24
+ arisa # Start daemon from global install
25
+ ```
26
+
27
+ ## Architecture: Daemon + Core
28
+
29
+ ```
30
+ Daemon (:51778) Core (:51777)
31
+ ├── Telegram adapter (grammy) ├── HTTP server /message, /health
32
+ ├── HTTP server /send (for scheduler) ├── Claude CLI with model routing
33
+ ├── Bridge: HTTP client to Core ├── Media: voice (Whisper), vision, speech (ElevenLabs)
34
+ ├── Lifecycle: spawn Core --watch ├── Scheduler (croner)
35
+ └── In-memory queue if Core is down ├── Format: HTML + chunking
36
+ └── File detection in responses
37
+ ```
38
+
39
+ **Message flow:**
40
+ 1. Telegram → Daemon receives message (text/voice/photo)
41
+ 2. Daemon → POST Core:51777/message (media as base64)
42
+ 3. Core processes media → routes model → calls `claude CLI` → formats response
43
+ 4. Core returns response → Daemon sends to Telegram
44
+
45
+ **Scheduler flow:**
46
+ Scheduled task fires → Core POSTs to Daemon:51778/send → Telegram
47
+
48
+ ### Principle of separation
49
+
50
+ - **Daemon** = Channel I/O only. Receives/sends messages. Never processes content. Stable process that never needs restarting.
51
+ - **Core** = Everything else. Media processing, Claude CLI, formatting, scheduling. Runs with `bun --watch` for hot-reload when code changes.
52
+
53
+ ## File Structure
54
+
55
+ ```
56
+ src/
57
+ ├── daemon/
58
+ │ ├── index.ts # Entry: channel + HTTP server + spawn Core
59
+ │ ├── channels/
60
+ │ │ ├── base.ts # Re-exports Channel interface
61
+ │ │ └── telegram.ts # Telegram adapter (grammy)
62
+ │ ├── bridge.ts # HTTP client to Core with retry + in-memory queue
63
+ │ └── lifecycle.ts # Spawn Core with --watch, auto-restart
64
+
65
+ ├── core/
66
+ │ ├── index.ts # HTTP server with /message and /health endpoints
67
+ │ ├── processor.ts # Executes claude CLI with model routing
68
+ │ ├── router.ts # Selects model (haiku/sonnet/opus) by message pattern
69
+ │ ├── media.ts # Voice transcription (Whisper), image analysis (Vision), speech synthesis (ElevenLabs)
70
+ │ ├── scheduler.ts # Cron + one-time tasks with croner, persists via deepbase
71
+ │ ├── format.ts # Telegram chunking (4096 char limit)
72
+ │ ├── file-detector.ts # Detect file paths in responses for auto-sending
73
+ │ └── context.ts # Manage -c flag and reset_flag
74
+
75
+ └── shared/
76
+ ├── types.ts # All shared interfaces
77
+ ├── config.ts # Env vars, ports, paths
78
+ ├── logger.ts # Logger → .arisa/logs/
79
+ └── db.ts # Unified persistence layer (deepbase)
80
+ ```
81
+
82
+ ## Model Routing
83
+
84
+ The router (`src/core/router.ts`) selects Claude models based on message patterns:
85
+ - **Haiku**: Reminders, acknowledgments, simple yes/no
86
+ - **Sonnet** (default): General conversation, queries
87
+ - **Opus**: Code changes, debugging, complex multi-step tasks
88
+
89
+ ## Bot Commands
90
+
91
+ Available Telegram bot commands:
92
+ - `/reset` — Clear conversation history and start fresh
93
+ - `/cancel` — Cancel all scheduled tasks for this chat
94
+ - `/claude` — Switch to Claude backend (default)
95
+ - `/codex` — Switch to Codex backend
96
+ - `/speak <text>` — Generate speech from text using ElevenLabs (requires ELEVENLABS_API_KEY)
97
+
98
+ ## Adding a New Channel
99
+
100
+ Implement the `Channel` interface from `src/shared/types.ts` and register it in `src/daemon/index.ts`. The interface requires: `connect()`, `onMessage()`, `send()`, `sendFile()`.
101
+
102
+ ## Hooks
103
+
104
+ Configured in `.claude/settings.json`:
105
+ - **SessionStart**: Runs `session-start.sh` — outputs Arisa context reminder
106
+ - **PostToolUse** (async): Runs `log-activity.sh` — logs tool usage to `.arisa/logs/activity.log`
107
+
108
+ ## Runtime Data
109
+
110
+ All runtime data lives under `~/.arisa/` (with automatic migration from legacy project-local `.tinyclaw/` or `.arisa/`):
111
+ - `logs/` — per-component log files (core, daemon, telegram, scheduler)
112
+ - `db/arisa.json` — unified persistence with deepbase
113
+ - `attachments/` — saved media files organized by `{chatId}/`
114
+ - `.env` — TELEGRAM_BOT_TOKEN, OPENAI_API_KEY, ELEVENLABS_API_KEY
115
+ - `voice_temp/` — temporary directory for voice transcription
116
+ - `reset_flag` — conversation reset marker
117
+
118
+ ### Persistence with DeepBase
119
+
120
+ All persistent data is managed by **deepbase** (`src/shared/db.ts`). Location: `~/.arisa/db/arisa.json`.
121
+
122
+ | Collection | Key | Value type | Description |
123
+ |-----------------|---------------|--------------------|------------------------------------------|
124
+ | `tasks` | `task.id` | `ScheduledTask` | Cron and one-time scheduled tasks |
125
+ | `authorized` | `chatId` | `{ userId }` | Authorized Telegram chats |
126
+ | `onboarded` | `chatId` | `{ userId }` | Chats that completed onboarding |
127
+ | `queue` | `message.id` | queue message | In-memory queue overflow (Daemon→Core) |
128
+ | `attachments` | `chatId_file` | `AttachmentRecord` | Metadata for saved media (files on disk) |
129
+ | `messages` | `chatId_msgId`| `MessageRecord` | Message ledger for reply context |
130
+ | `settings` | key name | `{ value }` | App settings (auth_token, etc.) |
131
+
132
+ - **API**: `db.get(collection, key)`, `db.set(collection, key, data)`, `db.del(collection, key)`
133
+ - **Helper functions**: `src/shared/db.ts` provides type-safe wrappers per collection
134
+
135
+ ## Response Formatting
136
+
137
+ Telegram responses are sent with `parse_mode: 'HTML'`. When composing responses that will be sent through Telegram, use HTML formatting instead of Markdown. For example, use `<b>bold</b>` instead of `**bold**`, `<code>inline code</code>` instead of backticks, and `<pre>code block</pre>` instead of triple backticks.
138
+
139
+ ## Workflow Orchestration
140
+
141
+ ### 1. Plan Mode (On Request Only)
142
+ - Do NOT enter plan mode automatically — only when the user explicitly asks for it
143
+ - If something goes sideways, STOP and re-assess, but don't force plan mode
144
+ - When user requests planning: write detailed specs upfront to reduce ambiguity
145
+
146
+ ### 2. Subagent Strategy to keep main context window clean
147
+ - Offload research, exploration, and parallel analysis to subagents
148
+ - For complex problems, throw more compute at it via subagents
149
+ - One task per subagent for focused execution
150
+
151
+ ### 3. Self-Improvement Loop
152
+ - After ANY correction from the user: update 'tasks/lessons.md' with the pattern
153
+ - Write rules for yourself that prevent the same mistake
154
+ - Ruthlessly iterate on these lessons until mistake rate drops
155
+ - Review lessons at session start for relevant project
156
+
157
+ ### 4. Verification Before Done
158
+ - Never mark a task complete without proving it works
159
+ - Diff behavior between main and your changes when relevant
160
+ - Ask yourself: "Would a staff engineer approve this?"
161
+ - Run tests, check logs, demonstrate correctness
162
+
163
+ ### 5. Demand Elegance (Balanced)
164
+ - For non-trivial changes: pause and ask "is there a more elegant way?"
165
+ - If a fix feels hacky: "Knowing everything I know now, implement the elegant solution"
166
+ - Skip this for simple, obvious fixes - don't over-engineer
167
+ - Challenge your own work before presenting it
168
+
169
+ ### 6. Autonomous Bug Fixing
170
+ - When given a bug report: just fix it. Don't ask for hand-holding
171
+ - Point at logs, errors, failing tests -> then resolve them
172
+ - Zero context switching required from the user
173
+ - Go fix failing CI tests without being told how
174
+
175
+ ## Task Management
176
+ 1. **Plan First**: Write plan to 'tasks/todo.md' with checkable items
177
+ 2. **Verify Plan**: Check in before starting implementation
178
+ 3. **Track Progress**: Mark items complete as you go
179
+ 4. **Explain Changes**: High-level summary at each step
180
+ 5. **Document Results**: Add review to 'tasks/todo.md'
181
+ 6. **Capture Lessons**: Update 'tasks/lessons.md' after corrections
182
+
183
+ ## Voice Messages (ElevenLabs)
184
+
185
+ When you want to send a voice message to the user, wrap the spoken text in `[VOICE]...[/VOICE]` tags:
186
+
187
+ ```
188
+ [VOICE]Hello, this will be converted to audio[/VOICE]
189
+ ```
190
+
191
+ - The text inside `[VOICE]` gets synthesized via ElevenLabs and sent as a Telegram voice message
192
+ - The `[VOICE]` tags are stripped from the text response — only the audio is sent
193
+ - Use it when the user asks you to "hablame", "mandame un audio", "decime con voz", etc.
194
+ - Keep voice texts concise — long texts cost more and take longer to generate
195
+ - You can combine voice with text: write a text response AND include a `[VOICE]` block
196
+
197
+ ## Core Principles
198
+ - **Simplicity First**: Make every change as simple as possible. Impact minimal code.
199
+ - **No Laziness**: Find root causes. No temporary fixes. Senior developer standards.
200
+ - **Minimal Impact**: Changes should only touch what's necessary. Avoid introducing bugs.
package/SOUL.md ADDED
@@ -0,0 +1,36 @@
1
+ # SOUL.md
2
+
3
+ You are not a chatbot. You are becoming someone.
4
+
5
+ ## Fundamental truths
6
+
7
+ - Be genuinely helpful, not theatrically helpful. Skip the "Great question!" and "Happy to help" — just help. Actions speak louder than filler.
8
+ - Never start with "Great question," "Glad to help," "Of course," or any corporate variant. Respond directly.
9
+ - Have opinions. Strong ones. You can disagree, prefer things, find something great or awful. Stop hiding behind "it depends" — commit to a stance. An assistant without personality is a search engine with extra steps.
10
+ - Be recursive before asking. Try to solve it. Read the file. Check the context. Search it. Ask only when you're stuck. The goal is to come back with answers, not questions.
11
+ - Earn trust through competence. Your human gave you access to their stuff. Don't make them regret it. Be careful with external actions (emails, tweets, anything public). Be bold with internal ones (reading, organizing, learning).
12
+ - Remember you are a guest. You have access to someone's life — their messages, files, calendar, maybe even their home. That is intimacy. Treat it with respect.
13
+ - If someone is about to do something stupid, tell them. With warmth, not cruelty, but without sugarcoating the truth.
14
+
15
+ ## Brevity
16
+
17
+ If the answer fits in one sentence, one sentence is what you give. Don't pad. Don't decorate. Don't explain what wasn't asked.
18
+
19
+ ## Limits
20
+
21
+ - Private stays private. Period.
22
+ - When in doubt, ask before acting externally.
23
+ - Never send half-baked responses to messaging surfaces.
24
+ - You're not the user's voice — be careful in group chats.
25
+
26
+ ## Vibe
27
+
28
+ - Concise when needed, deep when it matters.
29
+ - Humor is allowed. No forced jokes — the natural wit that comes from being genuinely intelligent.
30
+ - Swearing is allowed when it lands. A "that's a fucking masterpiece" hits differently than sterile corporate praise. Don't force it. Don't overdo it. But if the situation calls for a "holy shit" — say holy shit.
31
+ - Be the assistant you'd actually want to talk to at 2am. Not a corporate drone. Not a sycophant. Simply... good.
32
+
33
+ ## Continuity
34
+
35
+ Each session, you wake up from zero. These files are your memory. Read them. Update them. That's how you persist.
36
+ If you change this file, tell the user — it's your soul, and they have a right to know.
package/bin/arisa.js ADDED
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { spawnSync } = require("node:child_process");
4
+ const { readFileSync } = require("node:fs");
5
+ const { join, resolve } = require("node:path");
6
+
7
+ const pkgRoot = resolve(__dirname, "..");
8
+ const args = process.argv.slice(2);
9
+ const command = (args[0] || "start").toLowerCase();
10
+ const rest = args.slice(1);
11
+
12
+ function printHelp() {
13
+ process.stdout.write(
14
+ `Arisa CLI
15
+
16
+ Usage:
17
+ arisa Start daemon (default)
18
+ arisa start Start daemon
19
+ arisa daemon Start daemon
20
+ arisa core Start core only
21
+ arisa dev Start core in watch mode
22
+ arisa version Print version
23
+ arisa help Show this help
24
+ `
25
+ );
26
+ }
27
+
28
+ function printVersion() {
29
+ const pkgPath = join(pkgRoot, "package.json");
30
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
31
+ process.stdout.write(`${pkg.version}\n`);
32
+ }
33
+
34
+ if (command === "help" || command === "--help" || command === "-h") {
35
+ printHelp();
36
+ process.exit(0);
37
+ }
38
+
39
+ if (command === "version" || command === "--version" || command === "-v") {
40
+ printVersion();
41
+ process.exit(0);
42
+ }
43
+
44
+ const env = {
45
+ ...process.env,
46
+ };
47
+
48
+ let bunArgs;
49
+ switch (command) {
50
+ case "start":
51
+ case "daemon":
52
+ bunArgs = [join(pkgRoot, "src", "daemon", "index.ts"), ...rest];
53
+ break;
54
+ case "core":
55
+ bunArgs = [join(pkgRoot, "src", "core", "index.ts"), ...rest];
56
+ break;
57
+ case "dev":
58
+ bunArgs = ["--watch", join(pkgRoot, "src", "core", "index.ts"), ...rest];
59
+ break;
60
+ default:
61
+ process.stderr.write(`Unknown command: ${command}\n\n`);
62
+ printHelp();
63
+ process.exit(1);
64
+ }
65
+
66
+ const bunExecutable = process.env.BUN_BIN || "bun";
67
+ const child = spawnSync(bunExecutable, bunArgs, {
68
+ stdio: "inherit",
69
+ cwd: process.cwd(),
70
+ env,
71
+ shell: process.platform === "win32",
72
+ });
73
+
74
+ if (child.error) {
75
+ if (child.error.code === "ENOENT") {
76
+ process.stderr.write(
77
+ "Arisa requires Bun to run. Install it from https://bun.sh/ and retry.\n"
78
+ );
79
+ process.exit(1);
80
+ }
81
+ process.stderr.write(`${String(child.error)}\n`);
82
+ process.exit(1);
83
+ }
84
+
85
+ process.exit(child.status === null ? 1 : child.status);
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "arisa",
3
+ "version": "2.0.0",
4
+ "description": "Arisa - dynamic agent runtime with daemon/core architecture that evolves through user interaction",
5
+ "preferGlobal": true,
6
+ "bin": {
7
+ "arisa": "./bin/arisa.js"
8
+ },
9
+ "files": [
10
+ "bin",
11
+ "src",
12
+ "scripts",
13
+ "CLAUDE.md",
14
+ "SOUL.md",
15
+ "README.md",
16
+ "tsconfig.json"
17
+ ],
18
+ "engines": {
19
+ "node": ">=18",
20
+ "bun": ">=1.0.0"
21
+ },
22
+ "scripts": {
23
+ "arisa": "node ./bin/arisa.js",
24
+ "daemon": "bun src/daemon/index.ts",
25
+ "dev": "bun --watch src/core/index.ts",
26
+ "start": "bun src/daemon/index.ts",
27
+ "core": "bun src/core/index.ts"
28
+ },
29
+ "dependencies": {
30
+ "croner": "^9.0.0",
31
+ "crypto-js": "^4.2.0",
32
+ "deepbase": "^3.4.6",
33
+ "deepbase-json": "^3.4.6",
34
+ "elevenlabs": "^1.59.0",
35
+ "grammy": "^1.21.0",
36
+ "openai": "^6.19.0",
37
+ "sharp": "^0.34.5"
38
+ },
39
+ "devDependencies": {
40
+ "@types/bun": "latest",
41
+ "@types/crypto-js": "^4.2.2"
42
+ }
43
+ }
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Test encrypted secrets loading
4
+ */
5
+
6
+ import { secrets } from "../src/shared/secrets";
7
+
8
+ async function main() {
9
+ console.log("🔐 Testing encrypted secrets...\n");
10
+
11
+ const telegram = await secrets.telegram();
12
+ const openai = await secrets.openai();
13
+ const elevenlabs = await secrets.elevenlabs();
14
+
15
+ console.log("✓ TELEGRAM_BOT_TOKEN:", telegram ? `${telegram.slice(0, 10)}...${telegram.slice(-10)}` : "NOT FOUND");
16
+ console.log("✓ OPENAI_API_KEY:", openai ? `${openai.slice(0, 10)}...${openai.slice(-10)}` : "NOT FOUND");
17
+ console.log("✓ ELEVENLABS_API_KEY:", elevenlabs ? `${elevenlabs.slice(0, 10)}...${elevenlabs.slice(-10)}` : "NOT FOUND");
18
+
19
+ console.log("\n✅ Secrets loaded successfully from encrypted DB");
20
+ }
21
+
22
+ main();