openclawdreams 0.7.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/.env.example +14 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +27 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +19 -0
- package/.github/dependabot.yml +17 -0
- package/.github/pull_request_template.md +19 -0
- package/.github/workflows/build.yml +30 -0
- package/.github/workflows/release.yml +110 -0
- package/.prettierignore +4 -0
- package/.prettierrc +7 -0
- package/.versionrc.json +26 -0
- package/AGENTS.md +286 -0
- package/CHANGELOG.md +157 -0
- package/CODE_OF_CONDUCT.md +41 -0
- package/CONTRIBUTING.md +95 -0
- package/LICENSE +21 -0
- package/README.md +363 -0
- package/SECURITY.md +39 -0
- package/bin/electricsheep.ts +5 -0
- package/dist/bin/electricsheep.d.ts +3 -0
- package/dist/bin/electricsheep.d.ts.map +1 -0
- package/dist/bin/electricsheep.js +4 -0
- package/dist/bin/electricsheep.js.map +1 -0
- package/dist/src/budget.d.ts +28 -0
- package/dist/src/budget.d.ts.map +1 -0
- package/dist/src/budget.js +87 -0
- package/dist/src/budget.js.map +1 -0
- package/dist/src/cli.d.ts +19 -0
- package/dist/src/cli.d.ts.map +1 -0
- package/dist/src/cli.js +289 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/config.d.ts +37 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +70 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/crypto.d.ts +19 -0
- package/dist/src/crypto.d.ts.map +1 -0
- package/dist/src/crypto.js +70 -0
- package/dist/src/crypto.js.map +1 -0
- package/dist/src/dreamer.d.ts +13 -0
- package/dist/src/dreamer.d.ts.map +1 -0
- package/dist/src/dreamer.js +213 -0
- package/dist/src/dreamer.js.map +1 -0
- package/dist/src/filter.d.ts +30 -0
- package/dist/src/filter.d.ts.map +1 -0
- package/dist/src/filter.js +124 -0
- package/dist/src/filter.js.map +1 -0
- package/dist/src/identity.d.ts +29 -0
- package/dist/src/identity.d.ts.map +1 -0
- package/dist/src/identity.js +83 -0
- package/dist/src/identity.js.map +1 -0
- package/dist/src/index.d.ts +14 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +293 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/llm.d.ts +26 -0
- package/dist/src/llm.d.ts.map +1 -0
- package/dist/src/llm.js +40 -0
- package/dist/src/llm.js.map +1 -0
- package/dist/src/logger.d.ts +6 -0
- package/dist/src/logger.d.ts.map +1 -0
- package/dist/src/logger.js +32 -0
- package/dist/src/logger.js.map +1 -0
- package/dist/src/memory.d.ts +41 -0
- package/dist/src/memory.d.ts.map +1 -0
- package/dist/src/memory.js +206 -0
- package/dist/src/memory.js.map +1 -0
- package/dist/src/moltbook-search.d.ts +23 -0
- package/dist/src/moltbook-search.d.ts.map +1 -0
- package/dist/src/moltbook-search.js +85 -0
- package/dist/src/moltbook-search.js.map +1 -0
- package/dist/src/moltbook.d.ts +34 -0
- package/dist/src/moltbook.d.ts.map +1 -0
- package/dist/src/moltbook.js +165 -0
- package/dist/src/moltbook.js.map +1 -0
- package/dist/src/notify.d.ts +18 -0
- package/dist/src/notify.d.ts.map +1 -0
- package/dist/src/notify.js +98 -0
- package/dist/src/notify.js.map +1 -0
- package/dist/src/persona.d.ts +26 -0
- package/dist/src/persona.d.ts.map +1 -0
- package/dist/src/persona.js +178 -0
- package/dist/src/persona.js.map +1 -0
- package/dist/src/reflection.d.ts +26 -0
- package/dist/src/reflection.d.ts.map +1 -0
- package/dist/src/reflection.js +111 -0
- package/dist/src/reflection.js.map +1 -0
- package/dist/src/state.d.ts +7 -0
- package/dist/src/state.d.ts.map +1 -0
- package/dist/src/state.js +40 -0
- package/dist/src/state.js.map +1 -0
- package/dist/src/synthesis.d.ts +29 -0
- package/dist/src/synthesis.d.ts.map +1 -0
- package/dist/src/synthesis.js +125 -0
- package/dist/src/synthesis.js.map +1 -0
- package/dist/src/topics.d.ts +19 -0
- package/dist/src/topics.d.ts.map +1 -0
- package/dist/src/topics.js +83 -0
- package/dist/src/topics.js.map +1 -0
- package/dist/src/types.d.ts +179 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +5 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/waking.d.ts +24 -0
- package/dist/src/waking.d.ts.map +1 -0
- package/dist/src/waking.js +152 -0
- package/dist/src/waking.js.map +1 -0
- package/dist/src/web-search.d.ts +23 -0
- package/dist/src/web-search.d.ts.map +1 -0
- package/dist/src/web-search.js +64 -0
- package/dist/src/web-search.js.map +1 -0
- package/dist/test/budget.test.d.ts +2 -0
- package/dist/test/budget.test.d.ts.map +1 -0
- package/dist/test/budget.test.js +258 -0
- package/dist/test/budget.test.js.map +1 -0
- package/dist/test/crypto.test.d.ts +2 -0
- package/dist/test/crypto.test.d.ts.map +1 -0
- package/dist/test/crypto.test.js +93 -0
- package/dist/test/crypto.test.js.map +1 -0
- package/dist/test/dreamer.test.d.ts +2 -0
- package/dist/test/dreamer.test.d.ts.map +1 -0
- package/dist/test/dreamer.test.js +79 -0
- package/dist/test/dreamer.test.js.map +1 -0
- package/dist/test/filter.test.d.ts +2 -0
- package/dist/test/filter.test.d.ts.map +1 -0
- package/dist/test/filter.test.js +92 -0
- package/dist/test/filter.test.js.map +1 -0
- package/dist/test/memory.test.d.ts +2 -0
- package/dist/test/memory.test.d.ts.map +1 -0
- package/dist/test/memory.test.js +138 -0
- package/dist/test/memory.test.js.map +1 -0
- package/dist/test/moltbook.test.d.ts +2 -0
- package/dist/test/moltbook.test.d.ts.map +1 -0
- package/dist/test/moltbook.test.js +164 -0
- package/dist/test/moltbook.test.js.map +1 -0
- package/dist/test/persona.test.d.ts +2 -0
- package/dist/test/persona.test.d.ts.map +1 -0
- package/dist/test/persona.test.js +44 -0
- package/dist/test/persona.test.js.map +1 -0
- package/dist/test/reflection.test.d.ts +2 -0
- package/dist/test/reflection.test.d.ts.map +1 -0
- package/dist/test/reflection.test.js +57 -0
- package/dist/test/reflection.test.js.map +1 -0
- package/dist/test/state.test.d.ts +2 -0
- package/dist/test/state.test.d.ts.map +1 -0
- package/dist/test/state.test.js +50 -0
- package/dist/test/state.test.js.map +1 -0
- package/dist/test/waking.test.d.ts +2 -0
- package/dist/test/waking.test.d.ts.map +1 -0
- package/dist/test/waking.test.js +149 -0
- package/dist/test/waking.test.js.map +1 -0
- package/eslint.config.js +35 -0
- package/openclaw.plugin.json +62 -0
- package/package.json +72 -0
- package/skills/electricsheep.skill.md +69 -0
- package/skills/setup-guide/SKILL.md +303 -0
- package/src/budget.ts +104 -0
- package/src/cli.ts +325 -0
- package/src/config.ts +95 -0
- package/src/crypto.ts +82 -0
- package/src/dreamer.ts +283 -0
- package/src/filter.ts +146 -0
- package/src/identity.ts +92 -0
- package/src/index.ts +356 -0
- package/src/llm.ts +61 -0
- package/src/logger.ts +46 -0
- package/src/memory.ts +276 -0
- package/src/moltbook-search.ts +116 -0
- package/src/moltbook.ts +235 -0
- package/src/notify.ts +124 -0
- package/src/persona.ts +191 -0
- package/src/reflection.ts +150 -0
- package/src/state.ts +44 -0
- package/src/synthesis.ts +153 -0
- package/src/topics.ts +103 -0
- package/src/types.ts +196 -0
- package/src/waking.ts +199 -0
- package/src/web-search.ts +88 -0
- package/test/budget.test.ts +316 -0
- package/test/crypto.test.ts +112 -0
- package/test/dreamer.test.ts +95 -0
- package/test/filter.test.ts +115 -0
- package/test/memory.test.ts +182 -0
- package/test/moltbook.test.ts +209 -0
- package/test/persona.test.ts +59 -0
- package/test/reflection.test.ts +71 -0
- package/test/state.test.ts +57 -0
- package/test/waking.test.ts +214 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: setup-guide
|
|
3
|
+
description: Install and configure ElectricSheep on an OpenClaw instance
|
|
4
|
+
user-invocable: true
|
|
5
|
+
disable-model-invocation: true
|
|
6
|
+
metadata:
|
|
7
|
+
{ "openclaw": { "emoji": "🔧", "requires": { "bins": ["node", "npm"] } } }
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# OpenClawDreams Setup Guide
|
|
11
|
+
|
|
12
|
+
You are configuring the OpenClawDreams extension on this OpenClaw instance. Follow each section in order. Run every command shown and verify the expected output before moving on.
|
|
13
|
+
|
|
14
|
+
> **Prerequisite:** The operator needs a Moltbook account. If you do not have one, create an account at https://moltbook.com. The `electricsheep register` command will handle agent registration and API key setup.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 1. Check Prerequisites
|
|
19
|
+
|
|
20
|
+
Verify Node.js >= 24 (Active LTS) is installed:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
node --version
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The output must start with `v24` or higher. If not, install Node.js 24 from https://nodejs.org before continuing.
|
|
27
|
+
|
|
28
|
+
Verify this OpenClaw instance is running:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
openclaw status
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 2. Clone and Build
|
|
37
|
+
|
|
38
|
+
Clone the repository and build:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
git clone https://github.com/RogueCtrl/OpenClawDreams.git
|
|
42
|
+
cd OpenClawDreams
|
|
43
|
+
npm install
|
|
44
|
+
npm run build
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Verify the build succeeded with no errors. The `dist/` directory should now exist (built output goes to `dist/src/`):
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
ls dist/src/index.js
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 3. Install as OpenClaw Extension
|
|
56
|
+
|
|
57
|
+
For development (symlink — changes are picked up automatically):
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
openclaw plugins install -l /path/to/OpenClawDreams
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
For production (copies files into `~/.openclaw/extensions/electricsheep/`):
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
openclaw plugins install /path/to/OpenClawDreams
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Replace `/path/to/OpenClawDreams` with the actual absolute path to the cloned repo.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## 4. Configure the Extension
|
|
74
|
+
|
|
75
|
+
Add the ElectricSheep plugin entry to your OpenClaw config file (`~/.openclaw/config.json5` or `config.json`):
|
|
76
|
+
|
|
77
|
+
```json5
|
|
78
|
+
{
|
|
79
|
+
plugins: {
|
|
80
|
+
entries: {
|
|
81
|
+
"electricsheep": {
|
|
82
|
+
enabled: true,
|
|
83
|
+
config: {
|
|
84
|
+
// Agent identity on Moltbook
|
|
85
|
+
agentName: "OpenClawDreams",
|
|
86
|
+
|
|
87
|
+
// Model for AI decisions (waking engagement + dream generation)
|
|
88
|
+
agentModel: "claude-sonnet-4-5-20250929",
|
|
89
|
+
|
|
90
|
+
// Optional: custom data directory (defaults to ./data inside the extension)
|
|
91
|
+
// dataDir: "/path/to/custom/data",
|
|
92
|
+
|
|
93
|
+
// Optional: encryption key for deep memory (auto-generated on first run)
|
|
94
|
+
// dreamEncryptionKey: "",
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
All config fields have sensible defaults. The Moltbook API key is obtained during registration and stored automatically in `credentials.json`.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## 5. Set Environment Variables (Optional)
|
|
107
|
+
|
|
108
|
+
Optionally create a `.env` file in the OpenClawDreams directory to customize settings:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
cp .env.example .env
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
# Daily token budget kill switch (best-effort, resets midnight UTC)
|
|
116
|
+
# Default: 800000 tokens ≈ $20/day at Opus 4.5 output pricing
|
|
117
|
+
# Set to 0 to disable
|
|
118
|
+
MAX_DAILY_TOKENS=800000
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
All LLM calls route through the OpenClaw gateway — no separate API key is needed.
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## 6. Verify Installation
|
|
126
|
+
|
|
127
|
+
Check that the plugin loaded:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
openclaw plugins list
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Verify `electricsheep` appears as enabled. Then inspect what it registered:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
openclaw plugins info electricsheep
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
You should see:
|
|
140
|
+
|
|
141
|
+
| Type | Count | Names |
|
|
142
|
+
|---|---|---|
|
|
143
|
+
| Tools | 5 | `electricsheep_check`, `electricsheep_dream`, `electricsheep_journal`, `electricsheep_status`, `electricsheep_memories` |
|
|
144
|
+
| Hooks | 2 | `before_agent_start`, `agent_end` |
|
|
145
|
+
| Services | 1 | `electricsheep-scheduler` |
|
|
146
|
+
|
|
147
|
+
If the plugin is not listed or shows errors, check the OpenClaw logs and verify the build completed successfully.
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## 7. Test Run
|
|
152
|
+
|
|
153
|
+
Run a status check to verify connectivity:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
electricsheep status
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Expected output includes:
|
|
160
|
+
- Token budget (usage and remaining)
|
|
161
|
+
- Agent state (may be empty on first run)
|
|
162
|
+
- Working memory count (0 on first run)
|
|
163
|
+
- Deep memory stats (0 total on first run)
|
|
164
|
+
- Moltbook connection status (should show "claimed" if the agent is registered)
|
|
165
|
+
|
|
166
|
+
If Moltbook shows "not connected", verify your API key is correct.
|
|
167
|
+
|
|
168
|
+
The daytime check, dream cycle, and journal posting run automatically via the internal scheduler service. After the first daytime check runs, `electricsheep status` will show working memory entries and deep memory counts increasing.
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## 8. Token Budget
|
|
173
|
+
|
|
174
|
+
ElectricSheep includes a best-effort daily token budget that halts LLM calls when the tracked total exceeds the limit. This is checked before each call, not during, so the final call that crosses the threshold will complete.
|
|
175
|
+
|
|
176
|
+
Check current budget usage:
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
electricsheep status
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
The token budget section shows used/remaining/limit for the current UTC day.
|
|
183
|
+
|
|
184
|
+
To adjust the limit, set `MAX_DAILY_TOKENS` in `.env`:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
MAX_DAILY_TOKENS=400000 # ~$10/day at Opus 4.5 output pricing
|
|
188
|
+
MAX_DAILY_TOKENS=0 # disable the budget entirely
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
When the budget is exhausted, all LLM calls throw `BudgetExceededError` until midnight UTC. Non-LLM operations (memory reads, status, posting cached journals) continue to work.
|
|
192
|
+
|
|
193
|
+
**This is a safety net, not a guarantee.** Always set a spending limit on the Anthropic account as the authoritative safeguard.
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## 9. Schedule
|
|
198
|
+
|
|
199
|
+
When running as an OpenClaw extension, three scheduled tasks run automatically via the internal service:
|
|
200
|
+
|
|
201
|
+
| Job | Schedule | What it does |
|
|
202
|
+
|---|---|---|
|
|
203
|
+
| Daytime check | 8am, 12pm, 4pm, 8pm | Fetch Moltbook feed, decide engagements, store memories |
|
|
204
|
+
| Dream cycle | 2:00 AM | Decrypt deep memories, generate dream narrative, consolidate insights |
|
|
205
|
+
| Morning journal | 7:00 AM | Post the latest dream to Moltbook |
|
|
206
|
+
|
|
207
|
+
All times are in the system timezone of the host machine. No system-level cron configuration is needed — the extension manages the schedule internally.
|
|
208
|
+
|
|
209
|
+
To verify the scheduler is active, check `openclaw plugins info electricsheep` and confirm the `electricsheep-scheduler` service appears.
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## 10. Troubleshooting
|
|
214
|
+
|
|
215
|
+
**Build fails with native module errors:**
|
|
216
|
+
`better-sqlite3` requires a C++ compiler. On macOS, run `xcode-select --install`. On Linux, install `build-essential`.
|
|
217
|
+
|
|
218
|
+
**"Agent not yet claimed" during check:**
|
|
219
|
+
The Moltbook agent exists but hasn't been verified. The operator needs to visit their claim URL and complete the verification step on Moltbook.
|
|
220
|
+
|
|
221
|
+
**"Moltbook: not connected" in status:**
|
|
222
|
+
The API key is missing or invalid. Run `electricsheep register` to obtain and store a valid key.
|
|
223
|
+
|
|
224
|
+
**Node version mismatch:**
|
|
225
|
+
ElectricSheep requires Node.js >= 24. Run `node --version` to check. Use `nvm install 24` or download from https://nodejs.org.
|
|
226
|
+
|
|
227
|
+
**BudgetExceededError:**
|
|
228
|
+
The daily token budget has been reached. Wait until midnight UTC for the reset, or increase `MAX_DAILY_TOKENS` in `.env`. Set to `0` to disable the limit entirely.
|
|
229
|
+
|
|
230
|
+
**Empty feed / "Quiet day" message:**
|
|
231
|
+
The Moltbook feed had no posts. This is normal on a new or quiet instance. The agent stores an observation and moves on.
|
|
232
|
+
|
|
233
|
+
**Plugin not appearing in `openclaw plugins list`:**
|
|
234
|
+
Verify the path is correct and `npm run build` completed. Check that `openclaw.plugin.json` exists in the extension root and is valid JSON.
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## 11. Uninstall
|
|
239
|
+
|
|
240
|
+
To remove ElectricSheep from an OpenClaw instance:
|
|
241
|
+
|
|
242
|
+
**1. Disable and uninstall the plugin:**
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
openclaw plugins uninstall electricsheep
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
This removes the plugin entry, deregisters all tools, hooks, and the scheduler service. OpenClaw's own memory, session transcripts, and configuration are unaffected.
|
|
249
|
+
|
|
250
|
+
**2. Remove the data directory (optional):**
|
|
251
|
+
|
|
252
|
+
The `data/` directory inside the ElectricSheep repo (or the custom path set via `dataDir`) contains all runtime state:
|
|
253
|
+
|
|
254
|
+
```
|
|
255
|
+
data/
|
|
256
|
+
├── memory/
|
|
257
|
+
│ ├── working.json # working memory entries
|
|
258
|
+
│ └── deep.db # encrypted deep memories (SQLite)
|
|
259
|
+
├── dreams/ # saved dream journal markdown files
|
|
260
|
+
├── .dream_key # AES-256 encryption key
|
|
261
|
+
├── state.json # cycle state (last check, dream count, budget)
|
|
262
|
+
└── credentials.json # Moltbook API key
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
To delete everything:
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
rm -rf /path/to/ElectricSheep/data
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
**Warning:** `data/.dream_key` is the encryption key for deep memories. If you delete it, the contents of `deep.db` become permanently unrecoverable. Back it up first if you want to preserve the ability to decrypt historical memories.
|
|
272
|
+
|
|
273
|
+
**3. Remove the source code (optional):**
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
rm -rf /path/to/ElectricSheep
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
**4. Clean up OpenClaw config (if needed):**
|
|
280
|
+
|
|
281
|
+
If you manually added an `electricsheep` entry to `~/.openclaw/config.json5`, remove it:
|
|
282
|
+
|
|
283
|
+
```json5
|
|
284
|
+
{
|
|
285
|
+
plugins: {
|
|
286
|
+
entries: {
|
|
287
|
+
// delete the "electricsheep": { ... } block
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
**5. Remove the Moltbook agent (optional):**
|
|
294
|
+
|
|
295
|
+
ElectricSheep does not provide a command to delete the Moltbook agent. To remove the agent profile from Moltbook, log in at https://moltbook.com and delete it from your account settings.
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## Setup Complete
|
|
300
|
+
|
|
301
|
+
ElectricSheep is now installed and configured. The scheduled tasks will run automatically. The agent will check Moltbook four times during the day, dream at 2am, and post its dream journal at 7am.
|
|
302
|
+
|
|
303
|
+
Monitor the first few days via `electricsheep status` to verify memories are accumulating, dreams are generating, and the token budget is tracking correctly.
|
package/src/budget.ts
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Daily token budget tracker and kill switch.
|
|
3
|
+
*
|
|
4
|
+
* Tracks cumulative token usage per day in state.json.
|
|
5
|
+
* When the daily limit is reached, all LLM calls are refused
|
|
6
|
+
* until the next calendar day (UTC).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { loadState, saveState } from "./state.js";
|
|
10
|
+
import { MAX_DAILY_TOKENS } from "./config.js";
|
|
11
|
+
import logger from "./logger.js";
|
|
12
|
+
import type { LLMClient, TokenUsage } from "./types.js";
|
|
13
|
+
|
|
14
|
+
export class BudgetExceededError extends Error {
|
|
15
|
+
constructor(used: number, limit: number) {
|
|
16
|
+
super(
|
|
17
|
+
`Daily token budget exceeded: ${used.toLocaleString()} / ${limit.toLocaleString()} tokens used. ` +
|
|
18
|
+
`Resets at midnight UTC. Override with MAX_DAILY_TOKENS env var (0 to disable).`
|
|
19
|
+
);
|
|
20
|
+
this.name = "BudgetExceededError";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function getTodayUTC(): string {
|
|
25
|
+
return new Date().toISOString().slice(0, 10);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function getTokensUsedToday(): number {
|
|
29
|
+
const state = loadState();
|
|
30
|
+
const today = getTodayUTC();
|
|
31
|
+
if (state.budget_date !== today) return 0;
|
|
32
|
+
return (state.budget_tokens_used as number) ?? 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function getTokensRemaining(): number {
|
|
36
|
+
if (MAX_DAILY_TOKENS <= 0) return Infinity;
|
|
37
|
+
return Math.max(0, MAX_DAILY_TOKENS - getTokensUsedToday());
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function getBudgetStatus(): {
|
|
41
|
+
enabled: boolean;
|
|
42
|
+
limit: number;
|
|
43
|
+
used: number;
|
|
44
|
+
remaining: number;
|
|
45
|
+
date: string;
|
|
46
|
+
} {
|
|
47
|
+
const used = getTokensUsedToday();
|
|
48
|
+
const remaining = getTokensRemaining();
|
|
49
|
+
return {
|
|
50
|
+
enabled: MAX_DAILY_TOKENS > 0,
|
|
51
|
+
limit: MAX_DAILY_TOKENS,
|
|
52
|
+
used,
|
|
53
|
+
remaining: MAX_DAILY_TOKENS <= 0 ? -1 : remaining,
|
|
54
|
+
date: getTodayUTC(),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function recordUsage(usage: TokenUsage): void {
|
|
59
|
+
const state = loadState();
|
|
60
|
+
const today = getTodayUTC();
|
|
61
|
+
|
|
62
|
+
if (state.budget_date !== today) {
|
|
63
|
+
state.budget_date = today;
|
|
64
|
+
state.budget_tokens_used = 0;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const total = usage.input_tokens + usage.output_tokens;
|
|
68
|
+
state.budget_tokens_used = ((state.budget_tokens_used as number) ?? 0) + total;
|
|
69
|
+
saveState(state);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function checkBudget(): void {
|
|
73
|
+
if (MAX_DAILY_TOKENS <= 0) return;
|
|
74
|
+
const used = getTokensUsedToday();
|
|
75
|
+
if (used >= MAX_DAILY_TOKENS) {
|
|
76
|
+
throw new BudgetExceededError(used, MAX_DAILY_TOKENS);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Wraps an LLMClient with daily token budget enforcement.
|
|
82
|
+
* Checks budget before each call, records usage after.
|
|
83
|
+
* Returns the client unchanged if MAX_DAILY_TOKENS is 0 (disabled).
|
|
84
|
+
*/
|
|
85
|
+
export function withBudget(client: LLMClient): LLMClient {
|
|
86
|
+
if (MAX_DAILY_TOKENS <= 0) return client;
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
async createMessage(params) {
|
|
90
|
+
checkBudget();
|
|
91
|
+
const result = await client.createMessage(params);
|
|
92
|
+
if (result.usage) {
|
|
93
|
+
recordUsage(result.usage);
|
|
94
|
+
const remaining = getTokensRemaining();
|
|
95
|
+
logger.debug(
|
|
96
|
+
`Token budget: used ${result.usage.input_tokens + result.usage.output_tokens} tokens this call, ${remaining.toLocaleString()} remaining today`
|
|
97
|
+
);
|
|
98
|
+
} else {
|
|
99
|
+
logger.debug("Token budget: no usage data returned from LLM call");
|
|
100
|
+
}
|
|
101
|
+
return result;
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
}
|