@askexenow/exe-os 0.8.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/README.md +178 -79
  2. package/dist/bin/backfill-responses.js +160 -8
  3. package/dist/bin/backfill-vectors.js +130 -1
  4. package/dist/bin/cleanup-stale-review-tasks.js +130 -1
  5. package/dist/bin/cli.js +10111 -7540
  6. package/dist/bin/exe-agent.js +159 -1
  7. package/dist/bin/exe-assign.js +235 -16
  8. package/dist/bin/exe-boot.js +344 -472
  9. package/dist/bin/exe-call.js +145 -1
  10. package/dist/bin/exe-cloud.js +11 -0
  11. package/dist/bin/exe-dispatch.js +37 -24
  12. package/dist/bin/exe-doctor.js +130 -1
  13. package/dist/bin/exe-export-behaviors.js +150 -7
  14. package/dist/bin/exe-forget.js +822 -665
  15. package/dist/bin/exe-gateway.js +470 -62
  16. package/dist/bin/exe-heartbeat.js +133 -2
  17. package/dist/bin/exe-kill.js +150 -7
  18. package/dist/bin/exe-launch-agent.js +150 -7
  19. package/dist/bin/exe-new-employee.js +756 -224
  20. package/dist/bin/exe-pending-messages.js +132 -2
  21. package/dist/bin/exe-pending-notifications.js +130 -1
  22. package/dist/bin/exe-pending-reviews.js +132 -2
  23. package/dist/bin/exe-review.js +160 -8
  24. package/dist/bin/exe-search.js +2473 -2008
  25. package/dist/bin/exe-session-cleanup.js +238 -51
  26. package/dist/bin/exe-settings.js +11 -0
  27. package/dist/bin/exe-status.js +130 -1
  28. package/dist/bin/exe-team.js +130 -1
  29. package/dist/bin/git-sweep.js +272 -16
  30. package/dist/bin/graph-backfill.js +150 -7
  31. package/dist/bin/graph-export.js +150 -7
  32. package/dist/bin/install.js +5 -0
  33. package/dist/bin/scan-tasks.js +238 -19
  34. package/dist/bin/setup.js +1776 -10
  35. package/dist/bin/shard-migrate.js +150 -7
  36. package/dist/bin/update.js +9 -6
  37. package/dist/bin/wiki-sync.js +150 -7
  38. package/dist/gateway/index.js +470 -62
  39. package/dist/hooks/bug-report-worker.js +195 -35
  40. package/dist/hooks/commit-complete.js +272 -16
  41. package/dist/hooks/error-recall.js +2313 -1847
  42. package/dist/hooks/exe-heartbeat-hook.js +5 -0
  43. package/dist/hooks/ingest-worker.js +330 -58
  44. package/dist/hooks/ingest.js +11 -0
  45. package/dist/hooks/instructions-loaded.js +199 -10
  46. package/dist/hooks/notification.js +199 -10
  47. package/dist/hooks/post-compact.js +199 -10
  48. package/dist/hooks/pre-compact.js +199 -10
  49. package/dist/hooks/pre-tool-use.js +199 -10
  50. package/dist/hooks/prompt-ingest-worker.js +179 -14
  51. package/dist/hooks/prompt-submit.js +781 -285
  52. package/dist/hooks/response-ingest-worker.js +1900 -1405
  53. package/dist/hooks/session-end.js +456 -12
  54. package/dist/hooks/session-start.js +2188 -1724
  55. package/dist/hooks/stop.js +200 -10
  56. package/dist/hooks/subagent-stop.js +199 -10
  57. package/dist/hooks/summary-worker.js +604 -334
  58. package/dist/index.js +554 -61
  59. package/dist/lib/cloud-sync.js +5 -0
  60. package/dist/lib/config.js +13 -0
  61. package/dist/lib/consolidation.js +5 -0
  62. package/dist/lib/database.js +104 -0
  63. package/dist/lib/device-registry.js +109 -0
  64. package/dist/lib/embedder.js +13 -0
  65. package/dist/lib/employee-templates.js +53 -26
  66. package/dist/lib/employees.js +5 -0
  67. package/dist/lib/exe-daemon-client.js +5 -0
  68. package/dist/lib/exe-daemon.js +493 -79
  69. package/dist/lib/file-grep.js +20 -4
  70. package/dist/lib/hybrid-search.js +1435 -190
  71. package/dist/lib/identity-templates.js +126 -5
  72. package/dist/lib/identity.js +5 -0
  73. package/dist/lib/license.js +5 -0
  74. package/dist/lib/messaging.js +37 -24
  75. package/dist/lib/schedules.js +130 -1
  76. package/dist/lib/skill-learning.js +11 -0
  77. package/dist/lib/status-brief.js +5 -0
  78. package/dist/lib/store.js +199 -10
  79. package/dist/lib/task-router.js +72 -6
  80. package/dist/lib/tasks.js +179 -50
  81. package/dist/lib/tmux-routing.js +179 -46
  82. package/dist/mcp/server.js +2129 -1855
  83. package/dist/mcp/tools/create-task.js +86 -36
  84. package/dist/mcp/tools/deactivate-behavior.js +5 -0
  85. package/dist/mcp/tools/list-tasks.js +39 -11
  86. package/dist/mcp/tools/send-message.js +37 -24
  87. package/dist/mcp/tools/update-task.js +153 -38
  88. package/dist/runtime/index.js +451 -59
  89. package/dist/tui/App.js +454 -59
  90. package/package.json +1 -1
package/README.md CHANGED
@@ -1,42 +1,65 @@
1
1
  # Exe OS
2
2
 
3
- ![npm version](https://img.shields.io/npm/v/exe-os.svg) ![License: CC-BY-NC-4.0](https://img.shields.io/badge/license-CC--BY--NC--4.0-blue.svg) ![Node.js](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen.svg)
3
+ ![npm version](https://img.shields.io/npm/v/@askexenow/exe-os.svg) ![License: CC-BY-NC-4.0](https://img.shields.io/badge/license-CC--BY--NC--4.0-blue.svg) ![Node.js](https://img.shields.io/badge/node-%3E%3D20.0.0-brightgreen.svg)
4
4
 
5
- **AI Employee Operating System** persistent memory, task management, and multi-agent orchestration that runs entirely on your machine.
5
+ **Hire the team you couldn't afford.** AI employee operating system with persistent memory, identity, and multi-agent orchestration.
6
6
 
7
- Exe OS is a **Terminal Agent Orchestration System**. It manages AI employee sessions using standard Unix tools (tmux) and officially supported CLI features (hooks, MCP, permission configs). It does not intercept API calls, extract tokens, or proxy LLM traffic. Users bring their own LLM subscription Exe OS provides the memory, identity, and coordination layer.
7
+ Run 5-10 AI employees as a real organization. Each employee has persistent memory across sessions, a permanent identity, and a task queue. You talk to your COO. Your COO coordinates everyone else.
8
8
 
9
- ### How Exe OS works
9
+ ---
10
10
 
11
- - **No API interception.** Exe OS never extracts, proxies, or spoofs OAuth tokens. It does not call LLM APIs directly.
12
- - **Native CLI automation.** Agents run inside official Claude Code CLI sessions. Exe OS sends keystrokes via `tmux send-keys` — standard Unix terminal multiplexing, the same way any developer scripts their terminal.
13
- - **Officially supported features only.** All orchestration uses documented Claude Code capabilities: [hooks](https://docs.anthropic.com/en/docs/claude-code/hooks), [MCP servers](https://docs.anthropic.com/en/docs/claude-code/mcp), `.claude.json` permissions, and `--agent` identity injection.
14
- - **BYOS — Bring Your Own Subscription.** Exe OS is the orchestration layer. The LLM subscription (Claude Max, API key, or any provider) belongs to you. Your subscription, your compute.
11
+ ## Install
15
12
 
16
- **What you're paying for with Exe OS:** encrypted persistent memory (SQLCipher + vector search), three-layer agent cognition (identity, expertise, experience), task orchestration, session lifecycle management, cloud sync (E2EE), and the multi-agent coordination protocol — not LLM compute.
13
+ ```bash
14
+ npm install -g @askexenow/exe-os
15
+ exe-os setup
16
+ ```
17
+
18
+ Two commands. Encryption key generated, embedding model downloaded, team created.
19
+
20
+ ---
17
21
 
18
- ## Quick Start
22
+ ## Two Ways to Work
23
+
24
+ ### Mode 1: Claude Code
25
+
26
+ Use your existing Claude Code subscription. Type your COO's name in the terminal.
19
27
 
20
28
  ```bash
21
- npm install -g exe-os
22
- exe-os-install # sets up hooks, MCP server, encryption
23
- exe-os # launch the TUI
29
+ exe-os claude # wire hooks + MCP into Claude Code (one-time)
30
+ exe # talk to your COO
24
31
  ```
25
32
 
26
- Three commands. You're running.
33
+ Best for: developers who live in the terminal.
34
+
35
+ ### Mode 2: Dashboard
36
+
37
+ Visual terminal UI with sidebar, team view, tasks, and metrics.
38
+
39
+ ```bash
40
+ exe-os # launch the dashboard
41
+ ```
42
+
43
+ Best for: managing multiple projects and employees.
44
+
45
+ **Both modes share the same memory, employees, and data. Switch anytime.**
27
46
 
28
- ## Features
47
+ ---
48
+
49
+ ## What You Get
29
50
 
30
51
  | Feature | What it does |
31
52
  |---------|-------------|
32
- | **Persistent memory** | Every tool call stored, searchable. 27K+ memories across sessions. |
33
- | **Multi-agent** | 5+ employees working in parallel via tmux sessions. |
34
- | **Task system** | Create, assign, review, chain tasks. Auto-dispatch to employees. |
35
- | **TUI dashboard** | 7 tabs: Command Center, Sessions, Tasks, Gateway, Team, Memory, Settings. |
36
- | **Direct API mode** | Bring your own API key. Anthropic, OpenCode, Gemini, OpenAI, Chutes. |
37
- | **External agents** | Customer-facing agents with deny-by-default security guardrails. |
38
- | **Cloud sync** | End-to-end encrypted memory sync across devices. |
39
- | **Skill learning** | Agents learn procedures from repeated task patterns. |
53
+ | **Persistent memory** | Every interaction stored in encrypted SQLCipher + vector search. Searchable across sessions. |
54
+ | **Three-layer cognition** | Identity (who you are) + Expertise (what you've learned) + Experience (what you remember) |
55
+ | **Multi-agent orchestration** | COO coordinates CTO, CMO, engineers. Parallel task execution via tmux. |
56
+ | **Task system** | Create, assign, review, chain tasks. Auto-dispatch. Review pipeline with cascading approval. |
57
+ | **Identity injection** | Each employee gets a permanent identity doc. Claude Code's `--agent` flag replaces the default system prompt. |
58
+ | **Skill learning** | Agents learn procedures from repeated patterns. Corrections become permanent behaviors. |
59
+ | **Cloud sync** | End-to-end encrypted memory sync across devices. Your key, your data. |
60
+ | **License activation** | `exe-os --activate <key>` to unlock CTO + CMO. Free tier: 1 employee (COO only). |
61
+
62
+ ---
40
63
 
41
64
  ## How It Works
42
65
 
@@ -44,96 +67,172 @@ Three commands. You're running.
44
67
  You
45
68
  |
46
69
  v
47
- exe-os TUI ──> manages tmux sessions ──> Claude Code employees
48
- | (yoshi, mari, tom, sasha)
49
- |
50
- ├── persistent memory (SQLCipher encrypted, vector search)
51
- ├── task orchestration (assign, review, auto-chain)
52
- ├── behavior injection (learned patterns applied per-task)
53
- └── session scoping (one exe per project, isolated)
70
+ Your COO (exe)
71
+ ├── Yoshi (CTO) ──> architecture, code reviews, tech decisions
72
+ │ └── Tom (Engineer) ──> implementation, tests, commits
73
+ ├── Mari (CMO) ──> design, content, SEO, branding
74
+ │ └── Sasha (Content) ──> video, images, production
75
+ └── Gen (AI Specialist) ──> AI tools, research, evaluation
54
76
  ```
55
77
 
56
- **You talk to exe (the COO).** Exe coordinates the team. Yoshi (CTO) handles architecture. Mari (CMO) handles design and content. Tom (Principal Engineer) implements. Each employee has their own Claude Code session, persistent memory, and task queue.
78
+ You talk to your COO. Your COO delegates. Each employee has:
79
+ - **Persistent memory** — remembers past work, decisions, patterns
80
+ - **Identity** — permanent role doc that defines who they are
81
+ - **Task queue** — auto-chains through assigned work
82
+ - **Behavioral expertise** — corrections accumulate as permanent rules
57
83
 
58
- ## The TUI
84
+ ---
59
85
 
60
- Launch with `exe-os` (or `exe-os --demo` to see it with sample data):
86
+ ## Setup Walkthrough
61
87
 
62
- - **Command Center** — team overview, system health, recent activity
63
- - **Sessions** — navigate between projects and employees, view live output
64
- - **Tasks** — kanban board of all active tasks across projects
65
- - **Gateway** — external-facing agent channels and health
66
- - **Team** — employee roster with live status (internal + external agents)
67
- - **Memory** — search across all memories with semantic search
68
- - **Settings** — providers, encryption, runtime config, employee models
88
+ ### 1. Install
69
89
 
70
- Keyboard: `1-7` switch tabs, arrows navigate, `Enter` to drill in, `Escape` to go back, `q` to quit.
90
+ ```bash
91
+ npm install -g @askexenow/exe-os
92
+ ```
71
93
 
72
- ## Requirements
94
+ Requires Node.js 20+ and tmux (`brew install tmux` on macOS).
73
95
 
74
- - **Node.js 18+**
75
- - **Claude Code** subscription (Max or Pro)
76
- - **tmux** — auto-detected, required for multi-agent
96
+ ### 2. Run Setup
77
97
 
78
98
  ```bash
79
- # macOS
80
- brew install tmux
99
+ exe-os setup
100
+ ```
81
101
 
82
- # Linux
83
- apt install tmux
102
+ This runs the setup wizard:
103
+ - Generates 256-bit encryption key (stored in system keychain)
104
+ - Downloads Jina v5 embedding model (397MB, runs locally)
105
+ - Names your COO (default: exe)
106
+ - Shows your team (CTO, CMO) and pricing tiers
107
+ - Optionally activates a license key
108
+
109
+ ### 3. Choose Your Mode
110
+
111
+ **Mode 1 — Claude Code:**
112
+
113
+ ```bash
114
+ exe-os claude # install hooks + MCP into Claude Code
115
+ exe # launch your COO (or whatever you named them)
84
116
  ```
85
117
 
86
- ## Employee Roster
118
+ **Mode 2 — Dashboard:**
87
119
 
88
- Exe OS comes with 4 default employees. Create more with `/exe-new-employee`:
120
+ ```bash
121
+ exe-os # launch the TUI dashboard
122
+ ```
123
+
124
+ ---
125
+
126
+ ## Pricing
127
+
128
+ | Plan | Price | Employees | Memories | Devices |
129
+ |------|-------|-----------|----------|---------|
130
+ | Free | $0 | 1 (COO) | 5,000 | 1 |
131
+ | Solopreneur | $97/mo | 5 | 100,000 | 2 |
132
+ | Company | $297/mo | 20 | 1,000,000 | 10 |
133
+ | Agency | $497/mo | 100 | 10,000,000 | 50 |
134
+ | Enterprise | Custom | Unlimited | Unlimited | Unlimited |
89
135
 
90
- | Name | Role | Default Model |
91
- |------|------|--------------|
92
- | exe | COO | claude-opus-4-6 |
93
- | yoshi | CTO | claude-opus-4-6 |
94
- | mari | CMO | claude-sonnet-4-6 |
95
- | tom | Principal Engineer | claude-sonnet-4-6 |
96
- | sasha | Content Production | claude-sonnet-4-6 |
136
+ Activate: `exe-os --activate <key>` or paste during `exe-os setup`.
97
137
 
98
- ## Configuration
138
+ Purchase at [askexe.com](https://askexe.com).
99
139
 
100
- ### Providers
140
+ ---
101
141
 
102
- Set API keys as environment variables:
142
+ ## Employee Templates
143
+
144
+ Create employees with built-in templates:
103
145
 
104
146
  ```bash
105
- export ANTHROPIC_API_KEY=sk-...
106
- export OPENCODE_API_KEY=... # optional
107
- export GEMINI_API_KEY=... # optional
147
+ exe-new-employee yoshi --template yoshi # CTO
148
+ exe-new-employee mari --template mari # CMO
149
+ exe-new-employee tom --template tom # Principal Engineer
150
+ exe-new-employee sasha --template sasha # Content Specialist
151
+ exe-new-employee gen --template gen # AI Specialist
108
152
  ```
109
153
 
110
- Failover chain: Anthropic -> OpenCode -> Gemini -> OpenAI.
154
+ Or create custom employees:
111
155
 
112
- ### Settings
156
+ ```bash
157
+ exe-new-employee alex # custom specialist
158
+ ```
113
159
 
114
- Run `/exe-settings` or view the Settings tab in the TUI:
160
+ Each employee gets an identity doc at `~/.exe-os/identity/{name}.md`, a task folder, and launcher commands.
115
161
 
116
- - **Memory**: SQLCipher encryption, Jina embeddings, hybrid search
117
- - **Runtime**: consolidation (6h), skill learning (threshold: 3)
118
- - **Per-employee models**: configurable in `~/.exe-os/config.json`
162
+ ---
163
+
164
+ ## For Agencies
165
+
166
+ See [docs/Agency-Playbook.md](docs/Agency-Playbook.md) for multi-client VPS deployment:
167
+ - One VPS, multiple clients, full data isolation
168
+ - Per-client wiki workspaces
169
+ - Cross-client querying for agency owners
170
+ - Config-driven white-label theming via `branding.json`
171
+
172
+ ---
173
+
174
+ ## Commands
175
+
176
+ | Command | What it does |
177
+ |---------|-------------|
178
+ | `exe-os` | Launch TUI dashboard (Mode 2) |
179
+ | `exe-os setup` | Run setup wizard |
180
+ | `exe-os claude` | Install hooks + MCP into Claude Code (Mode 1) |
181
+ | `exe-os --activate <key>` | Activate a license key |
182
+ | `exe` | Launch your COO in Claude Code |
183
+ | `exe-new-employee <name>` | Create a new employee |
184
+ | `/exe` | Boot your COO (inside Claude Code) |
185
+ | `/exe-team` | Show employee roster |
186
+ | `/exe-search <query>` | Search memories |
187
+
188
+ ---
119
189
 
120
190
  ## Architecture
121
191
 
122
192
  ```
123
193
  exe-os/
124
194
  src/
125
- tui/ # Ink-based terminal UI (7 tabs, keyboard nav)
126
- runtime/ # Agent loop, tool registry, hooks, permissions
127
- gateway/ # External agent adapters, failover, providers
128
- lib/ # Core: memory, tasks, behaviors, search, sync
129
- mcp/ # MCP server (9 tools for Claude Code integration)
130
- adapters/ # Claude Code hooks (ingest, session-start, etc.)
195
+ lib/ # Core: memory, tasks, identity, behaviors, search, sync, encryption
196
+ mcp/ # MCP server (20+ tools for Claude Code integration)
197
+ adapters/ # Claude Code hooks (ingest, session-start, pre-tool-use, etc.)
198
+ tui/ # Ink-based terminal dashboard (Mode 2)
199
+ runtime/ # Agent loop, tool registry, permissions (Mode 2 standalone)
200
+ gateway/ # External messaging (WhatsApp, Telegram, Discord, webhook)
201
+ deploy/
202
+ compose/ # Docker Compose for VPS deployment (CRM + wiki + gateway + daemon)
203
+ Dockerfile* # Per-service Docker images
204
+ docs/
205
+ Agency-Playbook.md # Multi-client VPS guide
131
206
  ```
132
207
 
133
- **Storage**: libSQL (SQLCipher) for encrypted local-first data. Vector search via Jina v5 embeddings (GGUF, runs locally via daemon).
208
+ **Three runtime modes:**
209
+
210
+ | Mode | Entry | What you see |
211
+ |------|-------|-------------|
212
+ | Mode 1: Claude Code | `exe` | Claude Code terminal with COO identity |
213
+ | Mode 2: TUI Dashboard | `exe-os` | Terminal dashboard with sidebar + team view |
214
+ | Mode 3: Desktop | `exe-os desktop` | Tauri native app (coming soon) |
215
+
216
+ **Storage:** SQLCipher (encrypted SQLite) + Jina v5 embeddings (local, 1024-dim). No data leaves your machine unless you opt into Exe Cloud (E2EE).
217
+
218
+ ---
219
+
220
+ ## Requirements
221
+
222
+ - **Node.js 20+**
223
+ - **tmux** — for multi-agent session management
224
+ - **Claude Code** subscription (Mode 1) or API key (Mode 2)
225
+
226
+ ```bash
227
+ # macOS
228
+ brew install tmux node
229
+
230
+ # Linux
231
+ apt install tmux nodejs
232
+ ```
134
233
 
135
- **Security**: External agents run in ExternalAgentMode with deny-by-default guardrails. No bash, no file writes, no git — only whitelisted MCP tools. Audit trail on every permission decision.
234
+ ---
136
235
 
137
236
  ## License
138
237
 
139
- CC-BY-NC-4.0
238
+ CC-BY-NC-4.0 (non-commercial). Commercial licenses available at [askexe.com](https://askexe.com).
@@ -81,6 +81,11 @@ function normalizeSessionLifecycle(raw) {
81
81
  const userSL = raw.sessionLifecycle ?? {};
82
82
  raw.sessionLifecycle = { ...defaultSL, ...userSL };
83
83
  }
84
+ function normalizeAutoUpdate(raw) {
85
+ const defaultAU = DEFAULT_CONFIG.autoUpdate;
86
+ const userAU = raw.autoUpdate ?? {};
87
+ raw.autoUpdate = { ...defaultAU, ...userAU };
88
+ }
84
89
  async function loadConfig() {
85
90
  const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
86
91
  await mkdir2(dir, { recursive: true });
@@ -103,6 +108,7 @@ async function loadConfig() {
103
108
  }
104
109
  normalizeScalingRoadmap(migratedCfg);
105
110
  normalizeSessionLifecycle(migratedCfg);
111
+ normalizeAutoUpdate(migratedCfg);
106
112
  const config = { ...DEFAULT_CONFIG, dbPath: path2.join(dir, "memories.db"), ...migratedCfg };
107
113
  if (config.dbPath.startsWith("~")) {
108
114
  config.dbPath = config.dbPath.replace(/^~/, os.homedir());
@@ -178,6 +184,11 @@ var init_config = __esm({
178
184
  idleKillTicksRequired: 3,
179
185
  idleKillIntercomAckWindowMs: 1e4,
180
186
  maxAutoInstances: 10
187
+ },
188
+ autoUpdate: {
189
+ checkOnBoot: true,
190
+ autoInstall: false,
191
+ checkIntervalMs: 24 * 60 * 60 * 1e3
181
192
  }
182
193
  };
183
194
  CONFIG_MIGRATIONS = [
@@ -311,13 +322,27 @@ async function ensureShardSchema(client) {
311
322
  "ALTER TABLE memories ADD COLUMN document_id TEXT",
312
323
  "ALTER TABLE memories ADD COLUMN user_id TEXT",
313
324
  "ALTER TABLE memories ADD COLUMN char_offset INTEGER",
314
- "ALTER TABLE memories ADD COLUMN page_number INTEGER"
325
+ "ALTER TABLE memories ADD COLUMN page_number INTEGER",
326
+ // Source provenance columns (must match database.ts)
327
+ "ALTER TABLE memories ADD COLUMN source_path TEXT",
328
+ "ALTER TABLE memories ADD COLUMN source_type TEXT DEFAULT 'text'",
329
+ "ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3",
330
+ "ALTER TABLE memories ADD COLUMN supersedes_id TEXT"
315
331
  ]) {
316
332
  try {
317
333
  await client.execute(col);
318
334
  } catch {
319
335
  }
320
336
  }
337
+ for (const idx of [
338
+ "CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)",
339
+ "CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL"
340
+ ]) {
341
+ try {
342
+ await client.execute(idx);
343
+ } catch {
344
+ }
345
+ }
321
346
  try {
322
347
  await client.execute("CREATE INDEX IF NOT EXISTS idx_memories_status ON memories(status)");
323
348
  } catch {
@@ -642,6 +667,27 @@ async function ensureSchema() {
642
667
  });
643
668
  } catch {
644
669
  }
670
+ try {
671
+ await client.execute({
672
+ sql: `ALTER TABLE tasks ADD COLUMN checkpoint TEXT`,
673
+ args: []
674
+ });
675
+ } catch {
676
+ }
677
+ try {
678
+ await client.execute({
679
+ sql: `ALTER TABLE tasks ADD COLUMN checkpoint_count INTEGER NOT NULL DEFAULT 0`,
680
+ args: []
681
+ });
682
+ } catch {
683
+ }
684
+ try {
685
+ await client.execute({
686
+ sql: `ALTER TABLE tasks ADD COLUMN complexity TEXT NOT NULL DEFAULT 'standard'`,
687
+ args: []
688
+ });
689
+ } catch {
690
+ }
645
691
  try {
646
692
  await client.execute({
647
693
  sql: `ALTER TABLE memories ADD COLUMN task_id TEXT`,
@@ -1052,6 +1098,15 @@ async function ensureSchema() {
1052
1098
  } catch {
1053
1099
  }
1054
1100
  }
1101
+ for (const col of [
1102
+ "ALTER TABLE memories ADD COLUMN source_path TEXT",
1103
+ "ALTER TABLE memories ADD COLUMN source_type TEXT DEFAULT 'text'"
1104
+ ]) {
1105
+ try {
1106
+ await client.execute(col);
1107
+ } catch {
1108
+ }
1109
+ }
1055
1110
  await client.executeMultiple(`
1056
1111
  CREATE INDEX IF NOT EXISTS idx_memories_workspace
1057
1112
  ON memories(workspace_id);
@@ -1116,6 +1171,34 @@ async function ensureSchema() {
1116
1171
  CREATE INDEX IF NOT EXISTS idx_conversations_channel
1117
1172
  ON conversations(channel_id);
1118
1173
  `);
1174
+ try {
1175
+ await client.execute({
1176
+ sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
1177
+ args: []
1178
+ });
1179
+ } catch {
1180
+ }
1181
+ try {
1182
+ await client.execute({
1183
+ sql: `ALTER TABLE tasks ADD COLUMN budget_fallback_model TEXT`,
1184
+ args: []
1185
+ });
1186
+ } catch {
1187
+ }
1188
+ try {
1189
+ await client.execute({
1190
+ sql: `ALTER TABLE tasks ADD COLUMN tokens_used INTEGER DEFAULT 0`,
1191
+ args: []
1192
+ });
1193
+ } catch {
1194
+ }
1195
+ try {
1196
+ await client.execute({
1197
+ sql: `ALTER TABLE tasks ADD COLUMN tokens_warned_at INTEGER`,
1198
+ args: []
1199
+ });
1200
+ } catch {
1201
+ }
1119
1202
  await client.executeMultiple(`
1120
1203
  CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
1121
1204
  content_text,
@@ -1142,6 +1225,52 @@ async function ensureSchema() {
1142
1225
  VALUES (new.rowid, new.content_text, new.sender_name, new.agent_response);
1143
1226
  END;
1144
1227
  `);
1228
+ try {
1229
+ await client.execute({
1230
+ sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
1231
+ args: []
1232
+ });
1233
+ } catch {
1234
+ }
1235
+ try {
1236
+ await client.execute(
1237
+ `CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)`
1238
+ );
1239
+ } catch {
1240
+ }
1241
+ try {
1242
+ await client.execute({
1243
+ sql: `UPDATE memories SET tier = 1 WHERE tool_name = 'commit_to_long_term_memory' AND importance >= 8 AND tier = 3`,
1244
+ args: []
1245
+ });
1246
+ await client.execute({
1247
+ sql: `UPDATE memories SET tier = 2 WHERE tool_name IN ('store_memory', 'manual') AND importance >= 5 AND tier = 3`,
1248
+ args: []
1249
+ });
1250
+ } catch {
1251
+ }
1252
+ try {
1253
+ await client.execute({
1254
+ sql: `ALTER TABLE memories ADD COLUMN supersedes_id TEXT`,
1255
+ args: []
1256
+ });
1257
+ } catch {
1258
+ }
1259
+ try {
1260
+ await client.execute(
1261
+ `CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL`
1262
+ );
1263
+ } catch {
1264
+ }
1265
+ for (const col of [
1266
+ "ALTER TABLE tasks ADD COLUMN checkpoint TEXT",
1267
+ "ALTER TABLE tasks ADD COLUMN checkpoint_count INTEGER DEFAULT 0"
1268
+ ]) {
1269
+ try {
1270
+ await client.execute(col);
1271
+ } catch {
1272
+ }
1273
+ }
1145
1274
  }
1146
1275
 
1147
1276
  // src/lib/keychain.ts
@@ -1233,6 +1362,11 @@ async function initStore(options) {
1233
1362
  const vResult = await client.execute("SELECT MAX(version) as max_v FROM memories");
1234
1363
  _nextVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
1235
1364
  }
1365
+ function classifyTier(record) {
1366
+ if (record.tool_name === "commit_to_long_term_memory" && (record.importance ?? 0) >= 8) return 1;
1367
+ if (["store_memory", "manual"].includes(record.tool_name ?? "") && (record.importance ?? 0) >= 5) return 2;
1368
+ return 3;
1369
+ }
1236
1370
  async function writeMemory(record) {
1237
1371
  if (record.vector !== null && record.vector.length !== EMBEDDING_DIM) {
1238
1372
  throw new Error(
@@ -1260,7 +1394,11 @@ async function writeMemory(record) {
1260
1394
  document_id: record.document_id ?? null,
1261
1395
  user_id: record.user_id ?? null,
1262
1396
  char_offset: record.char_offset ?? null,
1263
- page_number: record.page_number ?? null
1397
+ page_number: record.page_number ?? null,
1398
+ source_path: record.source_path ?? null,
1399
+ source_type: record.source_type ?? null,
1400
+ tier: record.tier ?? classifyTier(record),
1401
+ supersedes_id: record.supersedes_id ?? null
1264
1402
  };
1265
1403
  _pendingRecords.push(dbRow);
1266
1404
  if (_flushTimer === null) {
@@ -1292,20 +1430,26 @@ async function flushBatch() {
1292
1430
  const userId = row.user_id ?? null;
1293
1431
  const charOffset = row.char_offset ?? null;
1294
1432
  const pageNumber = row.page_number ?? null;
1433
+ const sourcePath = row.source_path ?? null;
1434
+ const sourceType = row.source_type ?? null;
1435
+ const tier = row.tier ?? 3;
1436
+ const supersedesId = row.supersedes_id ?? null;
1295
1437
  return {
1296
1438
  sql: hasVector ? `INSERT OR IGNORE INTO memories
1297
1439
  (id, agent_id, agent_role, session_id, timestamp,
1298
1440
  tool_name, project_name,
1299
1441
  has_error, raw_text, vector, version, task_id, importance, status,
1300
1442
  confidence, last_accessed,
1301
- workspace_id, document_id, user_id, char_offset, page_number)
1302
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories
1443
+ workspace_id, document_id, user_id, char_offset, page_number,
1444
+ source_path, source_type, tier, supersedes_id)
1445
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories
1303
1446
  (id, agent_id, agent_role, session_id, timestamp,
1304
1447
  tool_name, project_name,
1305
1448
  has_error, raw_text, vector, version, task_id, importance, status,
1306
1449
  confidence, last_accessed,
1307
- workspace_id, document_id, user_id, char_offset, page_number)
1308
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
1450
+ workspace_id, document_id, user_id, char_offset, page_number,
1451
+ source_path, source_type, tier, supersedes_id)
1452
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
1309
1453
  args: hasVector ? [
1310
1454
  row.id,
1311
1455
  row.agent_id,
@@ -1327,7 +1471,11 @@ async function flushBatch() {
1327
1471
  documentId,
1328
1472
  userId,
1329
1473
  charOffset,
1330
- pageNumber
1474
+ pageNumber,
1475
+ sourcePath,
1476
+ sourceType,
1477
+ tier,
1478
+ supersedesId
1331
1479
  ] : [
1332
1480
  row.id,
1333
1481
  row.agent_id,
@@ -1348,7 +1496,11 @@ async function flushBatch() {
1348
1496
  documentId,
1349
1497
  userId,
1350
1498
  charOffset,
1351
- pageNumber
1499
+ pageNumber,
1500
+ sourcePath,
1501
+ sourceType,
1502
+ tier,
1503
+ supersedesId
1352
1504
  ]
1353
1505
  };
1354
1506
  };