@aurora-foundation/obsidian-next 0.4.6 → 0.4.7
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/CHANGELOG.md +25 -0
- package/README.md +80 -145
- package/dist/auditLog-HWRFIJ2X.js +8 -0
- package/dist/auditLog-VIRBXCTW.js +8 -0
- package/dist/chunk-2DWIVO44.js +153 -0
- package/dist/chunk-2GNNSYJJ.js +130 -0
- package/dist/chunk-2GYEYFA3.js +275 -0
- package/dist/chunk-5SWSM5VM.js +676 -0
- package/dist/chunk-6AYRIUHX.js +4198 -0
- package/dist/chunk-7MMY74WO.js +156 -0
- package/dist/chunk-7RCNGBCH.js +285 -0
- package/dist/chunk-AP3GOR2F.js +199 -0
- package/dist/chunk-BJAJPGTC.js +130 -0
- package/dist/chunk-CYXVMJB5.js +4268 -0
- package/dist/chunk-DMAVXJER.js +4268 -0
- package/dist/chunk-EGKZDZDR.js +130 -0
- package/dist/chunk-EHWUXQX3.js +267 -0
- package/dist/chunk-ELJWVQFQ.js +4268 -0
- package/dist/chunk-FBZCV46R.js +130 -0
- package/dist/chunk-FNLWB54Z.js +207 -0
- package/dist/chunk-G64GRNO2.js +130 -0
- package/dist/chunk-G6PNQHTA.js +207 -0
- package/dist/chunk-GAHRRZA7.js +130 -0
- package/dist/chunk-GUW6FCNU.js +130 -0
- package/dist/chunk-GY7AIT7V.js +4144 -0
- package/dist/chunk-I6ISKU65.js +376 -0
- package/dist/chunk-ICI6MVDK.js +181 -0
- package/dist/chunk-IZ2UOFPU.js +367 -0
- package/dist/chunk-LHSM7KXU.js +367 -0
- package/dist/chunk-M3Y6AJIR.js +207 -0
- package/dist/chunk-MSDU36RT.js +367 -0
- package/dist/chunk-N37VWWMU.js +367 -0
- package/dist/chunk-N6PZZKFJ.js +4214 -0
- package/dist/chunk-NRNJJERJ.js +207 -0
- package/dist/chunk-PMIF5TJP.js +181 -0
- package/dist/chunk-PTMCW5KL.js +376 -0
- package/dist/chunk-SJTNDC23.js +516 -0
- package/dist/chunk-SM6UUM7A.js +181 -0
- package/dist/chunk-SWVKY7CF.js +511 -0
- package/dist/chunk-UJFXSPWB.js +207 -0
- package/dist/chunk-UUXVT3S2.js +130 -0
- package/dist/chunk-VVW6CEYD.js +181 -0
- package/dist/chunk-WJOOUOLZ.js +181 -0
- package/dist/chunk-WR3MOK2G.js +367 -0
- package/dist/chunk-WYNEGOVS.js +676 -0
- package/dist/chunk-XI3Z4XMG.js +367 -0
- package/dist/chunk-XOFYIW64.js +367 -0
- package/dist/chunk-XOMN4VJS.js +181 -0
- package/dist/chunk-XWWAAZYQ.js +374 -0
- package/dist/chunk-YPYS2VZB.js +4214 -0
- package/dist/chunk-ZADDCJLH.js +4214 -0
- package/dist/config-2R7SG7JG.js +10 -0
- package/dist/config-XWU2S7WP.js +10 -0
- package/dist/context-3PJYLO5K.js +9 -0
- package/dist/context-5YLBOMUV.js +9 -0
- package/dist/context-6NOUT4ZU.js +9 -0
- package/dist/context-7WVBQIOY.js +9 -0
- package/dist/context-CIWCGVB6.js +9 -0
- package/dist/context-UZLEBIVJ.js +9 -0
- package/dist/database-7NY62ZYK.js +8 -0
- package/dist/database-M457QD3O.js +8 -0
- package/dist/database-OHOOLXAN.js +8 -0
- package/dist/database-TXEJPP2T.js +8 -0
- package/dist/database-X7CM7424.js +8 -0
- package/dist/database-Z4EE4PBN.js +8 -0
- package/dist/index.js +767 -195
- package/dist/mcp/index.js +36 -23
- package/dist/memory-D7HIGZ3A.js +13 -0
- package/dist/memory-M3CZQKT5.js +13 -0
- package/dist/memory-MV3S7GFY.js +13 -0
- package/dist/memory-NZ2NYJM4.js +12 -0
- package/dist/memory-RHSICMC4.js +12 -0
- package/dist/memory-URT3ZK3Y.js +13 -0
- package/dist/memory-XDNX25LS.js +13 -0
- package/dist/migrations-FILWYBOY.js +140 -0
- package/dist/migrations-NU57HRUP.js +140 -0
- package/dist/resume-3KWKO5RN.js +17 -0
- package/dist/resume-7IHNBWF4.js +17 -0
- package/dist/resume-F6ZD4OZ5.js +17 -0
- package/dist/resume-INSRSU4U.js +17 -0
- package/dist/resume-QE2ZVTUL.js +17 -0
- package/dist/resume-RIAOI3C2.js +17 -0
- package/dist/resume-SIILX55A.js +17 -0
- package/dist/resume-XI634OHK.js +17 -0
- package/dist/scheduler-5UD3DF36.js +14 -0
- package/dist/scheduler-A3HOTGQA.js +14 -0
- package/dist/scheduler-H7JO2X5B.js +14 -0
- package/dist/scheduler-VFG53RI5.js +14 -0
- package/dist/scheduler-YM3JNYGA.js +14 -0
- package/dist/scheduler-YPVQNEMD.js +14 -0
- package/dist/session-2ESORADZ.js +16 -0
- package/dist/session-GQMYP3GH.js +16 -0
- package/dist/session-I367R42H.js +16 -0
- package/dist/session-MFR3XMZS.js +16 -0
- package/dist/session-OJACFEAN.js +16 -0
- package/dist/session-QUDE33VI.js +16 -0
- package/dist/session-TRE6PK44.js +16 -0
- package/dist/session-WTKXDLFV.js +16 -0
- package/dist/settings-D2ZKCXP7.js +8 -0
- package/dist/settings-KWE6MC3Q.js +8 -0
- package/package.json +5 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,31 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.4.7] - 2026-02-07
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **Tool Tree Display**: Consecutive tool calls now display with tree connectors (`┌├└`) instead of sequential spam. Groups parallel operations visually.
|
|
12
|
+
- **TaskView Enhancements**:
|
|
13
|
+
- Progress bar showing completion percentage (`████░░░░░░ 40%`)
|
|
14
|
+
- Polished checkbox icons (`☐` empty, `☑` done)
|
|
15
|
+
- Keyboard navigation: `j/k` to move, `x` to mark done
|
|
16
|
+
- Visual selection indicator with cyan highlighting
|
|
17
|
+
- **Activity Indicator**: Thinking status now shows current operation (e.g., `⏳ read src/config.ts`) instead of generic "Thinking..."
|
|
18
|
+
- **Color-Coded Mode Display**: Footer mode indicator now uses distinct colors:
|
|
19
|
+
- `▶ AUTO` (green) - Full autonomy
|
|
20
|
+
- `⏸ PLAN` (yellow) - Review before execute
|
|
21
|
+
- `⏺ SAFE` (red) - Ask for everything
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
- **MessageList**: Refactored to group tool batches with visual hierarchy
|
|
25
|
+
- **Anti-Flicker**: Consecutive tool results maintain visual connection with pipe prefix
|
|
26
|
+
|
|
27
|
+
### Technical
|
|
28
|
+
- Added `groupToolCalls()` function for tool batch detection
|
|
29
|
+
- Enhanced `Root.tsx` with `currentActivity` state tracking
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
8
33
|
## [0.4.6] - 2026-02-02
|
|
9
34
|
|
|
10
35
|
### Added
|
package/README.md
CHANGED
|
@@ -2,28 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|
|
|
5
|
-
> This README was written by Obsidian (v0.4.6) - a
|
|
5
|
+
> This README was written by Obsidian (v0.4.6) - a global, always-on autonomous engineering daemon with adaptive reasoning and system-wide persistent memory.
|
|
6
6
|
|
|
7
7
|
[](LICENSE)
|
|
8
8
|
[](package.json)
|
|
9
|
-
[](CHANGELOG.md)
|
|
10
|
+
[](docs/PRD.md)
|
|
11
11
|
|
|
12
|
-
**Obsidian Next** is a
|
|
12
|
+
**Obsidian Next** is a global, always-on autonomous engineering partner. It runs as a system-wide background service, managing multiple codebases and performing proactive engineering tasks while you're away.
|
|
13
13
|
|
|
14
|
-
Built for
|
|
14
|
+
Built for engineers who need an agent that lives in their system - not just in a terminal window.
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
18
|
-
## What Makes Obsidian
|
|
18
|
+
## What Makes Obsidian Autonomous
|
|
19
19
|
|
|
20
|
-
| Feature | Obsidian | Other Assistants |
|
|
21
|
-
|
|
22
|
-
| **
|
|
23
|
-
| **
|
|
24
|
-
| **
|
|
25
|
-
| **
|
|
26
|
-
| **
|
|
20
|
+
| Feature | Obsidian Next | Other Assistants |
|
|
21
|
+
|---------|---------------|------------------|
|
|
22
|
+
| **Lifecycle** | Always-on Daemon (Service) | Script / Process-bound |
|
|
23
|
+
| **Reasoning** | Claude 4.6 Adaptive Thinking | Standard Chat |
|
|
24
|
+
| **Context** | 1 Million Token Mastery | 128k - 200k fixed |
|
|
25
|
+
| **Memory** | Semantic Vector Store (Hybrid) | Simple Chat History |
|
|
26
|
+
| **Proactivity** | Heartbeat Background Tasks | Reactive Only |
|
|
27
|
+
| **Scope** | Global (System-wide) | Project-locked |
|
|
27
28
|
|
|
28
29
|
---
|
|
29
30
|
|
|
@@ -33,65 +34,39 @@ Built for developers who need an agent that can actually *do things* - not just
|
|
|
33
34
|
# Install globally
|
|
34
35
|
npm install -g @aurora-foundation/obsidian-next
|
|
35
36
|
|
|
36
|
-
#
|
|
37
|
-
obsidian
|
|
37
|
+
# Initialize global daemon and services
|
|
38
|
+
obsidian init --service
|
|
38
39
|
|
|
39
|
-
#
|
|
40
|
-
|
|
40
|
+
# Check daemon status
|
|
41
|
+
obsidian status
|
|
41
42
|
```
|
|
42
43
|
|
|
43
44
|
---
|
|
44
45
|
|
|
45
|
-
## Core
|
|
46
|
+
## Core Capabilities
|
|
46
47
|
|
|
47
|
-
###
|
|
48
|
-
Obsidian
|
|
49
|
-
- Open applications (`open`, `osascript`)
|
|
50
|
-
- Control system settings
|
|
51
|
-
- Run any shell command
|
|
52
|
-
- Speak text aloud (`say` on macOS)
|
|
53
|
-
- Manage clipboard (`pbcopy`/`pbpaste`)
|
|
48
|
+
### Always-On Autonomy
|
|
49
|
+
Obsidian runs as a background service (`launchd` or `systemd`). It doesn't die when you close your terminal. It keeps reasoning, indexing, and auditing in the background.
|
|
54
50
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
> say "build complete" when the tests pass
|
|
58
|
-
> organize my Downloads folder
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
### Three Execution Modes
|
|
62
|
-
|
|
63
|
-
| Mode | Description | Use Case |
|
|
64
|
-
|------|-------------|----------|
|
|
65
|
-
| **Safe** (default) | Approval required for writes/commands | Daily use |
|
|
66
|
-
| **Plan** | Read-only exploration, creates execution plan | Complex tasks |
|
|
67
|
-
| **Auto** | Full autonomy, no confirmations | Trusted workflows |
|
|
51
|
+
### Claude 4.6 Adaptive Reasoning
|
|
52
|
+
Utilizing the latest **Thinking Blocks**, Obsidian modulates its reasoning effort based on task complexity. You can see its "Thinking Trace" in real-time before it acts.
|
|
68
53
|
|
|
69
|
-
|
|
54
|
+
### 1M Token Context window
|
|
55
|
+
Hold entire repositories in active memory. Obsidian uses **Prompt Caching** and **Context Distillation** to keep massive windows cheap, fast, and coherent.
|
|
70
56
|
|
|
71
|
-
###
|
|
72
|
-
|
|
73
|
-
-
|
|
74
|
-
-
|
|
75
|
-
-
|
|
57
|
+
### Proactive Heartbeat (The Scheduler)
|
|
58
|
+
Schedule background tasks to keep your systems healthy:
|
|
59
|
+
- **Nightly Audits**: Scan for security vulnerabilities or dead code.
|
|
60
|
+
- **Auto-Documentation**: Generate docstrings for new functions.
|
|
61
|
+
- **Health Checks**: Run tests and notify you via Telegram if they break.
|
|
76
62
|
|
|
77
63
|
```
|
|
78
|
-
|
|
79
|
-
|
|
64
|
+
/schedule "0 2 * * *" system:audit
|
|
65
|
+
/schedule "*/30 * * * *" system:sync_index
|
|
80
66
|
```
|
|
81
67
|
|
|
82
|
-
###
|
|
83
|
-
|
|
84
|
-
- Automatic step creation in plan mode
|
|
85
|
-
- Progress tracking with visual indicators
|
|
86
|
-
- Resume incomplete tasks across sessions
|
|
87
|
-
|
|
88
|
-
View tasks with `Ctrl+T` or `/task`.
|
|
89
|
-
|
|
90
|
-
### Session Management
|
|
91
|
-
Never lose your work:
|
|
92
|
-
- `/exit` - Save session and quit
|
|
93
|
-
- `/resume` - Browse and restore saved sessions
|
|
94
|
-
- Full context, history, and task restoration
|
|
68
|
+
### Self-Improving Skills
|
|
69
|
+
Obsidian can autonomously expand its own toolbox. If it hits a capability gap, it writes, tests, and registers a new TypeScript tool in `~/.obsidian-next/skills/` without a restart.
|
|
95
70
|
|
|
96
71
|
---
|
|
97
72
|
|
|
@@ -99,93 +74,54 @@ Never lose your work:
|
|
|
99
74
|
|
|
100
75
|
| Command | Description |
|
|
101
76
|
|---------|-------------|
|
|
102
|
-
| `/
|
|
103
|
-
| `/
|
|
104
|
-
| `/
|
|
105
|
-
| `/
|
|
106
|
-
| `/
|
|
107
|
-
| `/resume` | Restore
|
|
108
|
-
| `/mcp` | Manage Model Context Protocol servers |
|
|
109
|
-
| `/clear` | Clear conversation history |
|
|
110
|
-
| `/exit` | Save session and exit |
|
|
111
|
-
|
|
112
|
-
---
|
|
113
|
-
|
|
114
|
-
## Keyboard Shortcuts
|
|
115
|
-
|
|
116
|
-
| Shortcut | Action |
|
|
117
|
-
|----------|--------|
|
|
118
|
-
| `Shift+Tab` | Cycle execution mode |
|
|
119
|
-
| `Ctrl+T` | Open task view |
|
|
120
|
-
| `Ctrl+C` | Exit (saves session) |
|
|
121
|
-
| `Escape` | Interrupt current operation |
|
|
122
|
-
| `Tab` | Autocomplete command |
|
|
123
|
-
| `Up/Down` | Navigate command suggestions |
|
|
77
|
+
| `/schedule` | Manage proactive background tasks |
|
|
78
|
+
| `/memory` | Export/sync the Semantic Knowledge Bank |
|
|
79
|
+
| `/workspace`| Focus the agent on a specific project root |
|
|
80
|
+
| `/pilot` | Secure GUI automation (Computer Use) |
|
|
81
|
+
| `/status` | Monitor daemon health and 1M context usage |
|
|
82
|
+
| `/resume` | Restore sessions from any workspace |
|
|
124
83
|
|
|
125
84
|
---
|
|
126
85
|
|
|
127
|
-
## Architecture
|
|
128
|
-
|
|
86
|
+
## Architecture (The Gateway Pattern)
|
|
87
|
+
|
|
88
|
+
Obsidian Next operates via a central backend service connected to multiple frontends:
|
|
89
|
+
|
|
90
|
+
```mermaid
|
|
91
|
+
graph TD
|
|
92
|
+
subgraph "Interfaces"
|
|
93
|
+
CLI[CLI Frontend]
|
|
94
|
+
TG[Telegram Bot]
|
|
95
|
+
Web[Web UI]
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
subgraph "Always-On Daemon (Backend)"
|
|
99
|
+
Socket[Unix Domain Socket] <--> LaneQueue[Lane Queue]
|
|
100
|
+
LaneQueue <--> Agent[Agent Core]
|
|
101
|
+
Agent <--> Claude[Claude 4.6]
|
|
102
|
+
Agent <--> Tools[Self-Improving Tools]
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
subgraph "System State (~/.obsidian-next/)"
|
|
106
|
+
DB[(SQLite state.db)]
|
|
107
|
+
Vector[Semantic Memory]
|
|
108
|
+
MD[MEMORY.md / Logs]
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
CLI <--> Socket
|
|
112
|
+
TG <--> Socket
|
|
113
|
+
Web <--> Socket
|
|
114
|
+
Agent <--> DB
|
|
129
115
|
```
|
|
130
|
-
User Input
|
|
131
|
-
|
|
|
132
|
-
v
|
|
133
|
-
[Supervisor] --> /command --> [Command Registry]
|
|
134
|
-
|
|
|
135
|
-
v
|
|
136
|
-
[Agent Runtime]
|
|
137
|
-
|
|
|
138
|
-
+---> [Auditor] --> Security checks
|
|
139
|
-
|
|
|
140
|
-
+---> [Tools] --> bash, read, write, edit, grep, glob, web_fetch
|
|
141
|
-
|
|
|
142
|
-
+---> [Memory] --> SQLite persistent store
|
|
143
|
-
|
|
|
144
|
-
v
|
|
145
|
-
[Event Bus] --> [Terminal UI]
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
All state is stored locally in `.obsidian/state.db` (SQLite).
|
|
149
116
|
|
|
150
117
|
---
|
|
151
118
|
|
|
152
|
-
## Security
|
|
153
|
-
|
|
154
|
-
- **Auditor**: Pre-flight validation of all commands and file operations
|
|
155
|
-
- **PII Redaction**: Automatic sanitation of sensitive data from LLM context
|
|
156
|
-
- **Approval Prompts**: Explicit confirmation for destructive operations
|
|
157
|
-
- **Secure Storage**: System Keychain integration for API keys
|
|
158
|
-
- **Audit Logging**: Complete trail of all agent actions
|
|
159
|
-
|
|
160
|
-
---
|
|
161
|
-
|
|
162
|
-
## Model Support
|
|
163
|
-
|
|
164
|
-
Obsidian works with Claude 4.5 models:
|
|
165
|
-
|
|
166
|
-
| Model | Best For |
|
|
167
|
-
|-------|----------|
|
|
168
|
-
| **Opus 4.5** | Complex reasoning, architecture decisions |
|
|
169
|
-
| **Sonnet 4.5** | Balanced performance (default) |
|
|
170
|
-
| **Haiku 4.5** | Fast responses, simple tasks |
|
|
171
|
-
|
|
172
|
-
Configure with `/init` or `/models`.
|
|
173
|
-
|
|
174
|
-
---
|
|
175
|
-
|
|
176
|
-
## MCP Integration
|
|
177
|
-
|
|
178
|
-
Extend Obsidian with Model Context Protocol servers:
|
|
179
|
-
|
|
180
|
-
```
|
|
181
|
-
/mcp
|
|
182
|
-
```
|
|
119
|
+
## Security & Safety
|
|
183
120
|
|
|
184
|
-
|
|
185
|
-
-
|
|
186
|
-
-
|
|
187
|
-
-
|
|
188
|
-
- `context7` - Documentation lookup
|
|
121
|
+
- **Global Auditor**: Centralized security policy for all projects.
|
|
122
|
+
- **Lane Queue**: Prevents race conditions during concurrent access.
|
|
123
|
+
- **Visual Privacy Guard**: Redacts sensitive data from screenshots in Pilot Mode.
|
|
124
|
+
- **Kill Switch**: Immediate local or remote termination of all autonomous activity.
|
|
189
125
|
|
|
190
126
|
---
|
|
191
127
|
|
|
@@ -193,10 +129,10 @@ Install certified tools:
|
|
|
193
129
|
|
|
194
130
|
| Resource | Description |
|
|
195
131
|
|----------|-------------|
|
|
196
|
-
| [
|
|
197
|
-
| [
|
|
198
|
-
| [
|
|
199
|
-
| [
|
|
132
|
+
| [Master Plan](docs/MASTER_PLAN.md) | The Autonomous Roadmap |
|
|
133
|
+
| [Architecture](docs/ARCHITECTURE.md) | The Daemon & Gateway System |
|
|
134
|
+
| [Smart Context](docs/CONTEXT.md) | 1M Token & Semantic Memory |
|
|
135
|
+
| [Security Policy](docs/SECURITY.md) | Global Zero Trust Model |
|
|
200
136
|
|
|
201
137
|
---
|
|
202
138
|
|
|
@@ -204,9 +140,8 @@ Install certified tools:
|
|
|
204
140
|
|
|
205
141
|
```bash
|
|
206
142
|
npm run dev # Watch mode
|
|
207
|
-
npm run build # Build
|
|
208
|
-
npm test #
|
|
209
|
-
npm start # Run locally
|
|
143
|
+
npm run build # Build daemon and frontend
|
|
144
|
+
npm test # Full suite (vitest)
|
|
210
145
|
```
|
|
211
146
|
|
|
212
147
|
---
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
// src/core/config.ts
|
|
2
|
+
import fs from "fs/promises";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import os from "os";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
var ConfigSchema = z.object({
|
|
8
|
+
model: z.string().default("claude-sonnet-4-5-20250929"),
|
|
9
|
+
workspaceRoot: z.string().default(os.homedir()),
|
|
10
|
+
maxTokens: z.number().default(8192),
|
|
11
|
+
language: z.string().default("en"),
|
|
12
|
+
// Deprecated: apiKey should be managed by KeyManager, not stored in config
|
|
13
|
+
apiKey: z.string().optional(),
|
|
14
|
+
// Sandbox Configuration
|
|
15
|
+
executionMode: z.enum(["local", "sandbox"]).default("local"),
|
|
16
|
+
sandbox: z.object({
|
|
17
|
+
allowedDomains: z.array(z.string()).default(["*.github.com", "*.npmjs.org", "*.npmjs.com", "api.anthropic.com", "registry.npmjs.org"]),
|
|
18
|
+
deniedDomains: z.array(z.string()).default([]),
|
|
19
|
+
denyRead: z.array(z.string()).default(["~/.ssh", "~/.aws", "~/.config/gcloud", "~/.kube", "~/.gnupg"]),
|
|
20
|
+
allowWrite: z.array(z.string()).default([".", "/tmp"]),
|
|
21
|
+
denyWrite: z.array(z.string()).default([".env", ".env.*", "*.key", "*.pem", ".git/config"])
|
|
22
|
+
}).default({}),
|
|
23
|
+
// Context Management
|
|
24
|
+
summarizerModel: z.string().default("claude-haiku-4-5-20251001"),
|
|
25
|
+
// Token Counting
|
|
26
|
+
// When true, uses Anthropic's countTokens API for accurate pre-request validation
|
|
27
|
+
// Set to false to skip pre-counting (saves ~100-500ms latency per request)
|
|
28
|
+
preCountTokens: z.boolean().default(true)
|
|
29
|
+
});
|
|
30
|
+
var DEFAULT_CONFIG = {
|
|
31
|
+
model: "claude-sonnet-4-5-20250929",
|
|
32
|
+
maxTokens: 8192,
|
|
33
|
+
language: "en",
|
|
34
|
+
workspaceRoot: os.homedir(),
|
|
35
|
+
executionMode: "local",
|
|
36
|
+
sandbox: {
|
|
37
|
+
allowedDomains: ["*.github.com", "*.npmjs.org", "*.npmjs.com", "api.anthropic.com", "registry.npmjs.org"],
|
|
38
|
+
deniedDomains: [],
|
|
39
|
+
denyRead: ["~/.ssh", "~/.aws", "~/.config/gcloud", "~/.kube", "~/.gnupg"],
|
|
40
|
+
allowWrite: [".", "/tmp"],
|
|
41
|
+
denyWrite: [".env", ".env.*", "*.key", "*.pem", ".git/config"]
|
|
42
|
+
},
|
|
43
|
+
summarizerModel: "claude-haiku-4-5-20251001",
|
|
44
|
+
preCountTokens: true
|
|
45
|
+
};
|
|
46
|
+
var ConfigManager = class {
|
|
47
|
+
configPath;
|
|
48
|
+
cachedConfig = null;
|
|
49
|
+
hasDeprecatedApiKey = false;
|
|
50
|
+
constructor(customPath) {
|
|
51
|
+
this.configPath = customPath || path.join(os.homedir(), ".obsidian-next", "config.json");
|
|
52
|
+
}
|
|
53
|
+
async load() {
|
|
54
|
+
if (this.cachedConfig) return this.cachedConfig;
|
|
55
|
+
return this.reload();
|
|
56
|
+
}
|
|
57
|
+
async reload() {
|
|
58
|
+
let loadedConfig = DEFAULT_CONFIG;
|
|
59
|
+
try {
|
|
60
|
+
const data = await fs.readFile(this.configPath, "utf-8");
|
|
61
|
+
const parsed = JSON.parse(data);
|
|
62
|
+
loadedConfig = { ...DEFAULT_CONFIG, ...parsed };
|
|
63
|
+
if (parsed.apiKey) {
|
|
64
|
+
this.hasDeprecatedApiKey = true;
|
|
65
|
+
}
|
|
66
|
+
} catch {
|
|
67
|
+
}
|
|
68
|
+
const finalConfig = ConfigSchema.parse(loadedConfig);
|
|
69
|
+
this.cachedConfig = finalConfig;
|
|
70
|
+
return finalConfig;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Check if config has deprecated apiKey field
|
|
74
|
+
* Users should migrate to KeyManager via /init
|
|
75
|
+
*/
|
|
76
|
+
hasDeprecatedKey() {
|
|
77
|
+
return this.hasDeprecatedApiKey;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Get deprecated apiKey for migration to KeyManager
|
|
81
|
+
*/
|
|
82
|
+
getDeprecatedApiKey() {
|
|
83
|
+
return this.cachedConfig?.apiKey;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Remove apiKey from config file after successful migration
|
|
87
|
+
*/
|
|
88
|
+
async removeApiKeyFromConfig() {
|
|
89
|
+
try {
|
|
90
|
+
const data = await fs.readFile(this.configPath, "utf-8");
|
|
91
|
+
const parsed = JSON.parse(data);
|
|
92
|
+
if (parsed.apiKey) {
|
|
93
|
+
delete parsed.apiKey;
|
|
94
|
+
await fs.writeFile(this.configPath, JSON.stringify(parsed, null, 2));
|
|
95
|
+
this.hasDeprecatedApiKey = false;
|
|
96
|
+
this.clearCache();
|
|
97
|
+
}
|
|
98
|
+
} catch {
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
clearCache() {
|
|
102
|
+
this.cachedConfig = null;
|
|
103
|
+
}
|
|
104
|
+
async save(config2) {
|
|
105
|
+
const dir = path.dirname(this.configPath);
|
|
106
|
+
await fs.mkdir(dir, { recursive: true });
|
|
107
|
+
const { apiKey, workspaceRoot, ...safeConfig } = config2;
|
|
108
|
+
await fs.writeFile(this.configPath, JSON.stringify(safeConfig, null, 2));
|
|
109
|
+
this.clearCache();
|
|
110
|
+
}
|
|
111
|
+
async exists() {
|
|
112
|
+
try {
|
|
113
|
+
await fs.access(this.configPath);
|
|
114
|
+
return true;
|
|
115
|
+
} catch {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
getPath() {
|
|
120
|
+
return this.configPath;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Dynamically get the project version from package.json
|
|
124
|
+
*/
|
|
125
|
+
async getVersion() {
|
|
126
|
+
try {
|
|
127
|
+
const selfPath = fileURLToPath(import.meta.url);
|
|
128
|
+
let currentDir = path.dirname(selfPath);
|
|
129
|
+
for (let i = 0; i < 5; i++) {
|
|
130
|
+
const pkgPath = path.join(currentDir, "package.json");
|
|
131
|
+
try {
|
|
132
|
+
const data = await fs.readFile(pkgPath, "utf-8");
|
|
133
|
+
const pkg = JSON.parse(data);
|
|
134
|
+
if (pkg.name === "@aurora-foundation/obsidian-next") {
|
|
135
|
+
return pkg.version;
|
|
136
|
+
}
|
|
137
|
+
} catch {
|
|
138
|
+
}
|
|
139
|
+
currentDir = path.dirname(currentDir);
|
|
140
|
+
}
|
|
141
|
+
return "0.4.5";
|
|
142
|
+
} catch {
|
|
143
|
+
return "0.4.5";
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
var config = new ConfigManager();
|
|
148
|
+
|
|
149
|
+
export {
|
|
150
|
+
ConfigSchema,
|
|
151
|
+
ConfigManager,
|
|
152
|
+
config
|
|
153
|
+
};
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import {
|
|
2
|
+
history,
|
|
3
|
+
session,
|
|
4
|
+
tasks
|
|
5
|
+
} from "./chunk-6AYRIUHX.js";
|
|
6
|
+
import {
|
|
7
|
+
context
|
|
8
|
+
} from "./chunk-WR3MOK2G.js";
|
|
9
|
+
import {
|
|
10
|
+
bus
|
|
11
|
+
} from "./chunk-WQM6FFSD.js";
|
|
12
|
+
|
|
13
|
+
// src/commands/resume.ts
|
|
14
|
+
import path from "path";
|
|
15
|
+
var resumeCommand = async (args) => {
|
|
16
|
+
if (args[0] === "--delete" || args[0] === "-d") {
|
|
17
|
+
const sessionId = args[1];
|
|
18
|
+
if (!sessionId) {
|
|
19
|
+
bus.emitAgent({
|
|
20
|
+
type: "error",
|
|
21
|
+
message: "Usage: /resume --delete <session_id>"
|
|
22
|
+
});
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const deleted = await session.delete(sessionId);
|
|
26
|
+
if (deleted) {
|
|
27
|
+
bus.emitAgent({
|
|
28
|
+
type: "done",
|
|
29
|
+
summary: `Session ${sessionId} deleted.`
|
|
30
|
+
});
|
|
31
|
+
} else {
|
|
32
|
+
bus.emitAgent({
|
|
33
|
+
type: "error",
|
|
34
|
+
message: `Session ${sessionId} not found.`
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (args[0] === "--last" || args[0] === "-l") {
|
|
40
|
+
const sessions = await session.list();
|
|
41
|
+
if (sessions.length === 0) {
|
|
42
|
+
bus.emitAgent({
|
|
43
|
+
type: "error",
|
|
44
|
+
message: "No saved sessions found."
|
|
45
|
+
});
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
args[0] = sessions[0].id;
|
|
49
|
+
}
|
|
50
|
+
if (!args[0]) {
|
|
51
|
+
const sessions = await session.list();
|
|
52
|
+
if (sessions.length === 0) {
|
|
53
|
+
bus.emitAgent({
|
|
54
|
+
type: "thought",
|
|
55
|
+
content: "No saved sessions found.\n\nSessions are created when you run /exit."
|
|
56
|
+
});
|
|
57
|
+
bus.emitAgent({
|
|
58
|
+
type: "done",
|
|
59
|
+
summary: "No sessions available."
|
|
60
|
+
});
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const content2 = [
|
|
64
|
+
"Saved Session Registry",
|
|
65
|
+
...sessions.slice(0, 10).map((s) => {
|
|
66
|
+
const date = new Date(s.savedAt);
|
|
67
|
+
const dateStr = date.toLocaleDateString();
|
|
68
|
+
const timeStr = date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
|
|
69
|
+
const workspaceName = path.basename(s.workspace);
|
|
70
|
+
return [
|
|
71
|
+
` \u23BF [${s.id}]`,
|
|
72
|
+
` \u23BF Date ${dateStr} ${timeStr}`,
|
|
73
|
+
` \u23BF Workspace ${workspaceName}`,
|
|
74
|
+
s.task ? ` \u23BF Task ${s.task}` : null,
|
|
75
|
+
` \u23BF Activity ${s.filesModified} files handled`,
|
|
76
|
+
""
|
|
77
|
+
].filter(Boolean).join("\n");
|
|
78
|
+
}),
|
|
79
|
+
sessions.length > 10 ? ` ... and ${sessions.length - 10} more sessions
|
|
80
|
+
` : "",
|
|
81
|
+
" [Usage]",
|
|
82
|
+
" \u23BF /resume <id> Restore session",
|
|
83
|
+
" \u23BF /resume --last Restore latest",
|
|
84
|
+
""
|
|
85
|
+
].join("\n");
|
|
86
|
+
bus.emitAgent({
|
|
87
|
+
type: "thought",
|
|
88
|
+
content: content2
|
|
89
|
+
});
|
|
90
|
+
bus.emitAgent({
|
|
91
|
+
type: "done",
|
|
92
|
+
summary: `${sessions.length} session(s) available.`
|
|
93
|
+
});
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const sessionIdArg = args[0];
|
|
97
|
+
const result = await session.restore(sessionIdArg);
|
|
98
|
+
if (!result.success) {
|
|
99
|
+
bus.emitAgent({
|
|
100
|
+
type: "error",
|
|
101
|
+
message: result.error || "Failed to restore session"
|
|
102
|
+
});
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const currentTask = tasks.get();
|
|
106
|
+
const currentContext = context.get();
|
|
107
|
+
const content = [
|
|
108
|
+
"Session Restored Successfully",
|
|
109
|
+
` \u23BF ID ${sessionIdArg}`,
|
|
110
|
+
` \u23BF Root ${path.basename(process.cwd())}`,
|
|
111
|
+
"",
|
|
112
|
+
" [Restored State]",
|
|
113
|
+
` \u23BF Context ${currentContext.files_read.length} files in set`,
|
|
114
|
+
` \u23BF History ${(await history.load()).length} events rehydrated`,
|
|
115
|
+
` \u23BF Task ${currentTask?.title || "None"}`,
|
|
116
|
+
""
|
|
117
|
+
].join("\n");
|
|
118
|
+
bus.emitAgent({
|
|
119
|
+
type: "thought",
|
|
120
|
+
content
|
|
121
|
+
});
|
|
122
|
+
bus.emitAgent({
|
|
123
|
+
type: "done",
|
|
124
|
+
summary: `Session ${sessionIdArg} restored.`
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
export {
|
|
129
|
+
resumeCommand
|
|
130
|
+
};
|