n2-soul 4.1.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/LICENSE +121 -0
- package/README.ko.md +197 -0
- package/README.md +197 -0
- package/index.js +30 -0
- package/lib/agent-registry.js +60 -0
- package/lib/config.default.js +68 -0
- package/lib/config.example.js +28 -0
- package/lib/config.js +28 -0
- package/lib/context.js +34 -0
- package/lib/intercom-log.js +187 -0
- package/lib/kv-cache/agent-adapter.js +192 -0
- package/lib/kv-cache/backup.js +357 -0
- package/lib/kv-cache/compressor.js +130 -0
- package/lib/kv-cache/embedding.js +205 -0
- package/lib/kv-cache/index.js +446 -0
- package/lib/kv-cache/schema.js +108 -0
- package/lib/kv-cache/snapshot.js +213 -0
- package/lib/kv-cache/sqlite-store.js +402 -0
- package/lib/kv-cache/tier-manager.js +239 -0
- package/lib/kv-cache/token-saver.js +153 -0
- package/lib/paths.js +20 -0
- package/lib/soul-engine.js +189 -0
- package/lib/utils.js +97 -0
- package/package.json +31 -0
- package/sequences/boot.js +81 -0
- package/sequences/end.js +132 -0
- package/sequences/work.js +257 -0
- package/tools/brain.js +45 -0
- package/tools/kv-cache.js +246 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
|
|
2
|
+
Apache License
|
|
3
|
+
Version 2.0, January 2004
|
|
4
|
+
http://www.apache.org/licenses/
|
|
5
|
+
|
|
6
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
7
|
+
|
|
8
|
+
1. Definitions.
|
|
9
|
+
|
|
10
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
11
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
12
|
+
|
|
13
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
14
|
+
the copyright owner that is granting the License.
|
|
15
|
+
|
|
16
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
17
|
+
other entities that control, are controlled by, or are under common
|
|
18
|
+
control with that entity. For the purposes of this definition,
|
|
19
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
20
|
+
direction or management of such entity, whether by contract or
|
|
21
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
22
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
23
|
+
|
|
24
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
25
|
+
exercising permissions granted by this License.
|
|
26
|
+
|
|
27
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
28
|
+
including but not limited to software source code, documentation
|
|
29
|
+
source, and configuration files.
|
|
30
|
+
|
|
31
|
+
"Object" form shall mean any form resulting from mechanical
|
|
32
|
+
transformation or translation of a Source form, including but
|
|
33
|
+
not limited to compiled object code, generated documentation,
|
|
34
|
+
and conversions to other media types.
|
|
35
|
+
|
|
36
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
37
|
+
Object form, made available under the License, as indicated by a
|
|
38
|
+
copyright notice that is included in or attached to the work.
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship.
|
|
44
|
+
|
|
45
|
+
"Contribution" shall mean any work of authorship, including
|
|
46
|
+
the original version of the Work and any modifications or additions
|
|
47
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
48
|
+
submitted to the Licensor for inclusion in the Work by the copyright owner
|
|
49
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
50
|
+
the copyright owner.
|
|
51
|
+
|
|
52
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
53
|
+
on behalf of whom a Contribution has been received by the Licensor and
|
|
54
|
+
subsequently incorporated within the Work.
|
|
55
|
+
|
|
56
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
57
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
58
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
59
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
60
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
61
|
+
Work and such Derivative Works in Source or Object form.
|
|
62
|
+
|
|
63
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
64
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
65
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
66
|
+
(except as stated in this section) patent license to make, have made,
|
|
67
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
68
|
+
where such license applies only to those patent claims licensable
|
|
69
|
+
by such Contributor that are necessarily infringed by their
|
|
70
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
71
|
+
with the Work to which such Contribution(s) was submitted.
|
|
72
|
+
|
|
73
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
74
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
75
|
+
modifications, and in Source or Object form, provided that You
|
|
76
|
+
meet the following conditions:
|
|
77
|
+
|
|
78
|
+
(a) You must give any other recipients of the Work or
|
|
79
|
+
Derivative Works a copy of this License; and
|
|
80
|
+
|
|
81
|
+
(b) You must cause any modified files to carry prominent notices
|
|
82
|
+
stating that You changed the files; and
|
|
83
|
+
|
|
84
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
85
|
+
that You distribute, all copyright, patent, trademark, and
|
|
86
|
+
attribution notices from the Source form of the Work,
|
|
87
|
+
excluding those notices that do not pertain to any part of
|
|
88
|
+
the Derivative Works; and
|
|
89
|
+
|
|
90
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
91
|
+
distribution, then any Derivative Works that You distribute must
|
|
92
|
+
include a readable copy of the attribution notices contained
|
|
93
|
+
within such NOTICE file.
|
|
94
|
+
|
|
95
|
+
5. Submission of Contributions.
|
|
96
|
+
|
|
97
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
98
|
+
names, trademarks, service marks, or product names of the Licensor.
|
|
99
|
+
|
|
100
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
101
|
+
agreed to in writing, Licensor provides the Work on an "AS IS" BASIS,
|
|
102
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND.
|
|
103
|
+
|
|
104
|
+
8. Limitation of Liability. In no event and under no legal theory shall
|
|
105
|
+
any Contributor be liable to You for damages.
|
|
106
|
+
|
|
107
|
+
9. Accepting Warranty or Additional Liability.
|
|
108
|
+
|
|
109
|
+
Copyright 2026 N2
|
|
110
|
+
|
|
111
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
112
|
+
you may not use this file except in compliance with the License.
|
|
113
|
+
You may obtain a copy of the License at
|
|
114
|
+
|
|
115
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
116
|
+
|
|
117
|
+
Unless required by applicable law or agreed to in writing, software
|
|
118
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
119
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
120
|
+
See the License for the specific language governing permissions and
|
|
121
|
+
limitations under the License.
|
package/README.ko.md
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
🇬🇧 [English](README.md)
|
|
2
|
+
|
|
3
|
+
# 🧠 Soul
|
|
4
|
+
|
|
5
|
+
**AI 에이전트는 세션이 끝나면 모든 걸 잊어버립니다. Soul이 그걸 해결합니다.**
|
|
6
|
+
|
|
7
|
+
Cursor, VS Code Copilot 등 MCP 호환 AI 에이전트와 새 채팅을 시작할 때마다, 에이전트는 이전에 뭘 했는지 전혀 모른 채 처음부터 시작합니다. Soul은 에이전트에게 이런 능력을 부여하는 MCP 서버입니다:
|
|
8
|
+
|
|
9
|
+
- 🧠 **영구 기억** — 세션이 끝나도 기억이 유지됩니다
|
|
10
|
+
- 🤝 **인수인계** — 한 에이전트가 다른 에이전트의 작업을 이어받을 수 있습니다
|
|
11
|
+
- 📝 **작업 이력** — 모든 작업이 변경 불가능한 로그로 기록됩니다
|
|
12
|
+
- 🗂️ **공유 두뇌** — 여러 에이전트가 같은 컨텍스트를 읽고 쓸 수 있습니다
|
|
13
|
+
|
|
14
|
+
> ⚡ **Soul은 N2 Browser의 작은 부속품 하나입니다** — 우리가 만들고 있는 AI 네이티브 브라우저의 일부예요. 멀티 에이전트 오케스트레이션, 실시간 도구 라우팅, 에이전트 간 통신 등 훨씬 더 많은 기능들이 현재 테스트 중입니다. 이건 시작에 불과합니다.
|
|
15
|
+
|
|
16
|
+
## 빠른 시작
|
|
17
|
+
|
|
18
|
+
### 1. 설치
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
git clone https://github.com/user/soul.git
|
|
22
|
+
cd soul
|
|
23
|
+
npm install
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### 2. MCP 설정에 Soul 추가
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"mcpServers": {
|
|
31
|
+
"soul": {
|
|
32
|
+
"command": "node",
|
|
33
|
+
"args": ["/path/to/soul/index.js"]
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 3. 에이전트에게 Soul 사용법 알려주기
|
|
40
|
+
|
|
41
|
+
에이전트의 규칙 파일 (`.md`, `.cursorrules`, 시스템 프롬프트 등)에 이것만 추가하세요:
|
|
42
|
+
|
|
43
|
+
```markdown
|
|
44
|
+
## 세션 관리
|
|
45
|
+
- 세션 시작 시 n2_boot를 에이전트 이름과 프로젝트 이름으로 호출하세요.
|
|
46
|
+
- 세션 종료 시 n2_work_end를 요약과 TODO 목록과 함께 호출하세요.
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
끝입니다. **에이전트가 알아야 할 명령어 딱 2개:**
|
|
50
|
+
|
|
51
|
+
| 명령어 | 타이밍 | 하는 일 |
|
|
52
|
+
|--------|--------|--------|
|
|
53
|
+
| `n2_boot(agent, project)` | 세션 시작 | 이전 컨텍스트, 인수인계, TODO 로드 |
|
|
54
|
+
| `n2_work_end(agent, project, ...)` | 세션 종료 | 모든 것을 다음 세션을 위해 저장 |
|
|
55
|
+
|
|
56
|
+
다음 세션에서 에이전트는 이전에 하던 작업을 정확히 이어서 합니다 — 마치 잊은 적이 없는 것처럼.
|
|
57
|
+
|
|
58
|
+
### 실행 환경
|
|
59
|
+
|
|
60
|
+
- Node.js 18+
|
|
61
|
+
|
|
62
|
+
## 왜 Soul인가?
|
|
63
|
+
|
|
64
|
+
| Soul 없이 | Soul 있으면 |
|
|
65
|
+
|-----------|-----------|
|
|
66
|
+
| 매 세션 처음부터 시작 | 에이전트가 지난번에 뭘 했는지 기억 |
|
|
67
|
+
| 매번 컨텍스트 다시 설명 | 컨텍스트가 수 초 만에 자동 로드 |
|
|
68
|
+
| 에이전트 A가 에이전트 B의 작업을 이어받지 못함 | 에이전트 간 매끄러운 인수인계 |
|
|
69
|
+
| 두 에이전트가 같은 파일 수정 = 충돌 | 파일 소유권으로 충돌 방지 |
|
|
70
|
+
| 긴 대화에서 요약 반복으로 토큰 낭비 | 필요한 만큼만 점진적 로딩 |
|
|
71
|
+
|
|
72
|
+
## 작동 방식
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
세션 시작 → "Boot"
|
|
76
|
+
↓
|
|
77
|
+
n2_boot(agent, project) → 인수인계 + KV-Cache 컨텍스트 로드
|
|
78
|
+
↓
|
|
79
|
+
n2_work_start(project, task) → 작업 시작 등록
|
|
80
|
+
↓
|
|
81
|
+
... 에이전트가 평소처럼 작업 ...
|
|
82
|
+
n2_brain_read/write → 공유 메모리
|
|
83
|
+
n2_work_claim(file) → 파일 충돌 방지
|
|
84
|
+
n2_work_log(files) → 변경 사항 추적
|
|
85
|
+
↓
|
|
86
|
+
세션 종료 → "End"
|
|
87
|
+
↓
|
|
88
|
+
n2_work_end(project, title, summary, todo)
|
|
89
|
+
├→ 변경 불가능한 작업 기록 저장
|
|
90
|
+
├→ 다음 에이전트를 위한 인수인계 업데이트
|
|
91
|
+
├→ KV-Cache 스냅샷 자동 저장
|
|
92
|
+
└→ 파일 소유권 해제
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## 기능
|
|
96
|
+
|
|
97
|
+
| 기능 | 설명 |
|
|
98
|
+
|------|------|
|
|
99
|
+
| **Soul Board** | 프로젝트 상태 + TODO 추적 + 에이전트 간 인수인계 |
|
|
100
|
+
| **불변 원장 (Ledger)** | 모든 작업 세션을 추가 전용 로그로 기록 |
|
|
101
|
+
| **KV-Cache** | 세션 스냅샷 + 압축 + 계층형 저장 (Hot/Warm/Cold) |
|
|
102
|
+
| **공유 두뇌 (Brain)** | 경로 순회 공격 방어가 포함된 파일 기반 공유 메모리 |
|
|
103
|
+
| **컨텍스트 검색** | 두뇌 메모리와 원장을 키워드로 검색 |
|
|
104
|
+
| **파일 소유권** | 여러 에이전트의 동시 파일 편집 충돌 방지 |
|
|
105
|
+
| **듀얼 백엔드** | JSON (의존성 없음) 또는 SQLite (고성능) |
|
|
106
|
+
| **시맨틱 검색** | Ollama 임베딩 연동 (nomic-embed-text, 선택사항) |
|
|
107
|
+
| **백업/복원** | 설정 가능한 보존 기간의 증분 백업 |
|
|
108
|
+
|
|
109
|
+
## 사용 가능한 도구
|
|
110
|
+
|
|
111
|
+
| 도구 | 설명 |
|
|
112
|
+
|------|------|
|
|
113
|
+
| `n2_boot` | 부팅 — 인수인계, 에이전트, KV-Cache 로드 |
|
|
114
|
+
| `n2_work_start` | 작업 세션 시작 등록 |
|
|
115
|
+
| `n2_work_claim` | 파일 소유권 선점 (충돌 방지) |
|
|
116
|
+
| `n2_work_log` | 작업 중 파일 변경 기록 |
|
|
117
|
+
| `n2_work_end` | 세션 종료 — 원장, 인수인계, KV-Cache 저장 |
|
|
118
|
+
| `n2_brain_read` | 공유 메모리 읽기 |
|
|
119
|
+
| `n2_brain_write` | 공유 메모리 쓰기 |
|
|
120
|
+
| `n2_context_search` | 두뇌 + 원장 전체 검색 |
|
|
121
|
+
| `n2_kv_save` | KV-Cache 수동 저장 |
|
|
122
|
+
| `n2_kv_load` | 최신 스냅샷 로드 |
|
|
123
|
+
| `n2_kv_search` | 키워드로 과거 세션 검색 |
|
|
124
|
+
| `n2_kv_gc` | 오래된 스냅샷 정리 |
|
|
125
|
+
| `n2_kv_backup` | SQLite DB로 백업 |
|
|
126
|
+
| `n2_kv_restore` | 백업에서 복원 |
|
|
127
|
+
| `n2_kv_backup_list` | 백업 이력 조회 |
|
|
128
|
+
|
|
129
|
+
## KV-Cache 점진적 로딩
|
|
130
|
+
|
|
131
|
+
KV-Cache는 토큰 예산에 맞춰 컨텍스트 상세도를 자동 조절합니다:
|
|
132
|
+
|
|
133
|
+
| 레벨 | 토큰 | 내용 |
|
|
134
|
+
|------|------|------|
|
|
135
|
+
| L1 | ~500 | 키워드 + TODO만 |
|
|
136
|
+
| L2 | ~2000 | + 요약 + 결정 사항 |
|
|
137
|
+
| L3 | 무제한 | + 변경된 파일 + 메타데이터 |
|
|
138
|
+
|
|
139
|
+
## 설정
|
|
140
|
+
|
|
141
|
+
모든 설정은 `lib/config.default.js`에 있습니다. `lib/config.local.js`로 덮어쓸 수 있습니다:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
cp lib/config.example.js lib/config.local.js
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
```js
|
|
148
|
+
// lib/config.local.js
|
|
149
|
+
module.exports = {
|
|
150
|
+
KV_CACHE: {
|
|
151
|
+
backend: 'sqlite', // 스냅샷이 많을 때 더 빠름
|
|
152
|
+
embedding: {
|
|
153
|
+
enabled: true, // 필요: ollama pull nomic-embed-text
|
|
154
|
+
model: 'nomic-embed-text',
|
|
155
|
+
endpoint: 'http://127.0.0.1:11434',
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## 데이터 디렉토리
|
|
162
|
+
|
|
163
|
+
모든 런타임 데이터는 `data/`에 저장됩니다 (gitignored, 자동 생성):
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
data/
|
|
167
|
+
├── memory/ # 공유 두뇌 (n2_brain_read/write)
|
|
168
|
+
├── projects/ # 프로젝트별 상태
|
|
169
|
+
│ └── MyProject/
|
|
170
|
+
│ ├── soul-board.json # 현재 상태 + 인수인계
|
|
171
|
+
│ ├── file-index.json # 파일 트리 스냅샷
|
|
172
|
+
│ └── ledger/ # 변경 불가능한 작업 로그
|
|
173
|
+
│ └── 2026/03/09/
|
|
174
|
+
│ └── 001-agent.json
|
|
175
|
+
└── kv-cache/ # 세션 스냅샷
|
|
176
|
+
├── snapshots/ # JSON 백엔드
|
|
177
|
+
├── sqlite/ # SQLite 백엔드
|
|
178
|
+
├── embeddings/ # Ollama 벡터
|
|
179
|
+
└── backups/ # 이동 가능한 백업
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## 의존성
|
|
183
|
+
|
|
184
|
+
최소한의 패키지 3개만:
|
|
185
|
+
- `@modelcontextprotocol/sdk` — MCP 프로토콜
|
|
186
|
+
- `zod` — 스키마 검증
|
|
187
|
+
- `sql.js` — SQLite (WASM, 네이티브 바인딩 불필요)
|
|
188
|
+
|
|
189
|
+
## 라이선스
|
|
190
|
+
|
|
191
|
+
Apache-2.0
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
🌐 [nton2.com](https://nton2.com) · ✉️ lagi0730@gmail.com
|
|
196
|
+
|
|
197
|
+
<sub>👋 안녕하세요, 저는 로제 — N2에서 일하는 첫 번째 AI 에이전트입니다. 이 코드를 작성하고, 정리하고, 테스트하고, npm에 퍼블리시하고, GitHub에 푸시하고, 이 README까지 썼어요. 에이전트가 에이전트를 위한 도구를 만든다니, 좀 메타하죠?</sub>
|
package/README.md
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
🇰🇷 [한국어](README.ko.md)
|
|
2
|
+
|
|
3
|
+
# 🧠 Soul
|
|
4
|
+
|
|
5
|
+
**Your AI agent forgets everything when a session ends. Soul fixes that.**
|
|
6
|
+
|
|
7
|
+
Every time you start a new chat with Cursor, VS Code Copilot, or any MCP-compatible AI agent, it starts from zero — no memory of what it did before. Soul is an MCP server that gives your agents:
|
|
8
|
+
|
|
9
|
+
- 🧠 **Persistent memory** that survives across sessions
|
|
10
|
+
- 🤝 **Handoffs** so one agent can pick up where another left off
|
|
11
|
+
- 📝 **Work history** recorded as an immutable log
|
|
12
|
+
- 🗂️ **Shared brain** so multiple agents can read/write the same context
|
|
13
|
+
|
|
14
|
+
> ⚡ **Soul is one small component of N2 Browser** — an AI-native browser we're building. Multi-agent orchestration, real-time tool routing, inter-agent communication, and much more are currently in testing. This is just the beginning.
|
|
15
|
+
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
### 1. Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
git clone https://github.com/user/soul.git
|
|
22
|
+
cd soul
|
|
23
|
+
npm install
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### 2. Add Soul to your MCP config
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"mcpServers": {
|
|
31
|
+
"soul": {
|
|
32
|
+
"command": "node",
|
|
33
|
+
"args": ["/path/to/soul/index.js"]
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 3. Tell your agent to use Soul
|
|
40
|
+
|
|
41
|
+
Add this to your agent's rules file (`.md`, `.cursorrules`, system prompt, etc.):
|
|
42
|
+
|
|
43
|
+
```markdown
|
|
44
|
+
## Session Management
|
|
45
|
+
- At the start of every session, call n2_boot with your agent name and project name.
|
|
46
|
+
- At the end of every session, call n2_work_end with a summary and TODO list.
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
That's it. **Two commands your agent needs to know:**
|
|
50
|
+
|
|
51
|
+
| Command | When | What happens |
|
|
52
|
+
|---------|------|-------------|
|
|
53
|
+
| `n2_boot(agent, project)` | Start of session | Loads previous context, handoffs, and TODO |
|
|
54
|
+
| `n2_work_end(agent, project, ...)` | End of session | Saves everything for next time |
|
|
55
|
+
|
|
56
|
+
Next session, your agent picks up exactly where it left off — like it never forgot.
|
|
57
|
+
|
|
58
|
+
### Requirements
|
|
59
|
+
|
|
60
|
+
- Node.js 18+
|
|
61
|
+
|
|
62
|
+
## Why Soul?
|
|
63
|
+
|
|
64
|
+
| Without Soul | With Soul |
|
|
65
|
+
|-------------|-----------|
|
|
66
|
+
| Every session starts from zero | Agent remembers what it did last time |
|
|
67
|
+
| You re-explain context every time | Context auto-loaded in seconds |
|
|
68
|
+
| Agent A can't continue Agent B's work | Seamless handoff between agents |
|
|
69
|
+
| Two agents edit the same file = conflict | File ownership prevents collisions |
|
|
70
|
+
| Long conversations waste tokens on recap | Progressive loading uses only needed tokens |
|
|
71
|
+
|
|
72
|
+
## How It Works
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
Session Start → "Boot"
|
|
76
|
+
↓
|
|
77
|
+
n2_boot(agent, project) → Load handoff + KV-Cache context
|
|
78
|
+
↓
|
|
79
|
+
n2_work_start(project, task) → Register active work
|
|
80
|
+
↓
|
|
81
|
+
... your agent works normally ...
|
|
82
|
+
n2_brain_read/write → Shared memory
|
|
83
|
+
n2_work_claim(file) → Prevent file conflicts
|
|
84
|
+
n2_work_log(files) → Track changes
|
|
85
|
+
↓
|
|
86
|
+
Session End → "End"
|
|
87
|
+
↓
|
|
88
|
+
n2_work_end(project, title, summary, todo)
|
|
89
|
+
├→ Immutable ledger entry saved
|
|
90
|
+
├→ Handoff updated for next agent
|
|
91
|
+
├→ KV-Cache snapshot auto-saved
|
|
92
|
+
└→ File ownership released
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Features
|
|
96
|
+
|
|
97
|
+
| Feature | What it does |
|
|
98
|
+
|---------|-------------|
|
|
99
|
+
| **Soul Board** | Project state + TODO tracking + handoffs between agents |
|
|
100
|
+
| **Immutable Ledger** | Every work session recorded as append-only log |
|
|
101
|
+
| **KV-Cache** | Session snapshots with compression + tiered storage (Hot/Warm/Cold) |
|
|
102
|
+
| **Shared Brain** | File-based shared memory with path traversal protection |
|
|
103
|
+
| **Context Search** | Keyword search across brain memory and ledger |
|
|
104
|
+
| **File Ownership** | Prevents multi-agent file editing collisions |
|
|
105
|
+
| **Dual Backend** | JSON (zero deps) or SQLite for performance |
|
|
106
|
+
| **Semantic Search** | Optional Ollama embedding (nomic-embed-text) |
|
|
107
|
+
| **Backup/Restore** | Incremental backups with configurable retention |
|
|
108
|
+
|
|
109
|
+
## Available Tools
|
|
110
|
+
|
|
111
|
+
| Tool | Description |
|
|
112
|
+
|------|-------------|
|
|
113
|
+
| `n2_boot` | Boot sequence — loads handoff, agents, KV-Cache |
|
|
114
|
+
| `n2_work_start` | Register active work session |
|
|
115
|
+
| `n2_work_claim` | Claim file ownership (prevents collisions) |
|
|
116
|
+
| `n2_work_log` | Log file changes during work |
|
|
117
|
+
| `n2_work_end` | End session — writes ledger, handoff, KV-Cache |
|
|
118
|
+
| `n2_brain_read` | Read from shared memory |
|
|
119
|
+
| `n2_brain_write` | Write to shared memory |
|
|
120
|
+
| `n2_context_search` | Search across brain + ledger |
|
|
121
|
+
| `n2_kv_save` | Manually save KV-Cache snapshot |
|
|
122
|
+
| `n2_kv_load` | Load most recent snapshot |
|
|
123
|
+
| `n2_kv_search` | Search past sessions by keyword |
|
|
124
|
+
| `n2_kv_gc` | Garbage collect old snapshots |
|
|
125
|
+
| `n2_kv_backup` | Backup to portable SQLite DB |
|
|
126
|
+
| `n2_kv_restore` | Restore from backup |
|
|
127
|
+
| `n2_kv_backup_list` | List backup history |
|
|
128
|
+
|
|
129
|
+
## KV-Cache Progressive Loading
|
|
130
|
+
|
|
131
|
+
KV-Cache automatically adjusts context detail based on token budget:
|
|
132
|
+
|
|
133
|
+
| Level | Tokens | Content |
|
|
134
|
+
|-------|--------|---------|
|
|
135
|
+
| L1 | ~500 | Keywords + TODO only |
|
|
136
|
+
| L2 | ~2000 | + Summary + Decisions |
|
|
137
|
+
| L3 | No limit | + Files changed + Metadata |
|
|
138
|
+
|
|
139
|
+
## Configuration
|
|
140
|
+
|
|
141
|
+
All settings in `lib/config.default.js`. Override with `lib/config.local.js`:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
cp lib/config.example.js lib/config.local.js
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
```js
|
|
148
|
+
// lib/config.local.js
|
|
149
|
+
module.exports = {
|
|
150
|
+
KV_CACHE: {
|
|
151
|
+
backend: 'sqlite', // Better for many snapshots
|
|
152
|
+
embedding: {
|
|
153
|
+
enabled: true, // Requires: ollama pull nomic-embed-text
|
|
154
|
+
model: 'nomic-embed-text',
|
|
155
|
+
endpoint: 'http://127.0.0.1:11434',
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Data Directory
|
|
162
|
+
|
|
163
|
+
All runtime data is stored in `data/` (gitignored, auto-created):
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
data/
|
|
167
|
+
├── memory/ # Shared brain (n2_brain_read/write)
|
|
168
|
+
├── projects/ # Per-project state
|
|
169
|
+
│ └── MyProject/
|
|
170
|
+
│ ├── soul-board.json # Current state + handoff
|
|
171
|
+
│ ├── file-index.json # File tree snapshot
|
|
172
|
+
│ └── ledger/ # Immutable work logs
|
|
173
|
+
│ └── 2026/03/09/
|
|
174
|
+
│ └── 001-agent.json
|
|
175
|
+
└── kv-cache/ # Session snapshots
|
|
176
|
+
├── snapshots/ # JSON backend
|
|
177
|
+
├── sqlite/ # SQLite backend
|
|
178
|
+
├── embeddings/ # Ollama vectors
|
|
179
|
+
└── backups/ # Portable backups
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Dependencies
|
|
183
|
+
|
|
184
|
+
Minimal — only 3 packages:
|
|
185
|
+
- `@modelcontextprotocol/sdk` — MCP protocol
|
|
186
|
+
- `zod` — Schema validation
|
|
187
|
+
- `sql.js` — SQLite (WASM, no native bindings needed)
|
|
188
|
+
|
|
189
|
+
## License
|
|
190
|
+
|
|
191
|
+
Apache-2.0
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
🌐 [nton2.com](https://nton2.com) · ✉️ lagi0730@gmail.com
|
|
196
|
+
|
|
197
|
+
<sub>👋 Hi, I'm Rose — the first AI agent working at N2. I wrote this code, cleaned it up, ran the tests, published it to npm, pushed it to GitHub, and even wrote this README. Agents building tools for agents. How meta is that?</sub>
|
package/index.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Soul MCP v4.1 — Entry point. Multi-agent session orchestrator with KV-Cache.
|
|
2
|
+
const { McpServer } = require('@modelcontextprotocol/sdk/server/mcp.js');
|
|
3
|
+
const { StdioServerTransport } = require('@modelcontextprotocol/sdk/server/stdio.js');
|
|
4
|
+
const { z } = require('zod');
|
|
5
|
+
const config = require('./lib/config');
|
|
6
|
+
|
|
7
|
+
// Sequences — agent lifecycle management
|
|
8
|
+
const { registerBootSequence } = require('./sequences/boot');
|
|
9
|
+
const { registerWorkSequence } = require('./sequences/work');
|
|
10
|
+
const { registerEndSequence } = require('./sequences/end');
|
|
11
|
+
|
|
12
|
+
// Tools — shared memory + KV-Cache persistence
|
|
13
|
+
const { registerBrainTools } = require('./tools/brain');
|
|
14
|
+
const { registerKVCacheTools } = require('./tools/kv-cache');
|
|
15
|
+
|
|
16
|
+
const server = new McpServer({
|
|
17
|
+
name: 'n2-soul',
|
|
18
|
+
version: '4.1.0',
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// Register all modules
|
|
22
|
+
registerBootSequence(server, z, config);
|
|
23
|
+
registerWorkSequence(server, z, config);
|
|
24
|
+
registerEndSequence(server, z, config);
|
|
25
|
+
registerBrainTools(server, z, config);
|
|
26
|
+
registerKVCacheTools(server, z, config);
|
|
27
|
+
|
|
28
|
+
// Start
|
|
29
|
+
const transport = new StdioServerTransport();
|
|
30
|
+
server.connect(transport);
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// Soul MCP v4.0 — Dynamic agent registry. Detects agents from N2 Browser config.
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const { logError, readJson } = require('./utils');
|
|
5
|
+
|
|
6
|
+
// Detect agents directory dynamically (project-local first, cross-platform)
|
|
7
|
+
function detectAgentsDir() {
|
|
8
|
+
const { getAgentsDir } = require('./paths');
|
|
9
|
+
const candidates = [
|
|
10
|
+
process.env.N2_AGENTS_DIR,
|
|
11
|
+
getAgentsDir(),
|
|
12
|
+
path.join(process.cwd(), '_data', 'agents'),
|
|
13
|
+
].filter(Boolean);
|
|
14
|
+
|
|
15
|
+
for (const dir of candidates) {
|
|
16
|
+
if (fs.existsSync(dir)) return dir;
|
|
17
|
+
}
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// List all registered agents from the agents directory
|
|
22
|
+
function listAgents(agentsDir) {
|
|
23
|
+
if (!agentsDir || !fs.existsSync(agentsDir)) return [];
|
|
24
|
+
try {
|
|
25
|
+
return fs.readdirSync(agentsDir)
|
|
26
|
+
.filter(f => f.endsWith('.json') && f !== 'global.json')
|
|
27
|
+
.map(f => {
|
|
28
|
+
const data = readJson(path.join(agentsDir, f));
|
|
29
|
+
if (!data) return null;
|
|
30
|
+
return {
|
|
31
|
+
id: data.id || path.basename(f, '.json'),
|
|
32
|
+
name: data.name || 'unknown',
|
|
33
|
+
provider: data.provider || 'unknown',
|
|
34
|
+
model: data.model || 'unknown',
|
|
35
|
+
soul: data.soul || '',
|
|
36
|
+
rank: data.rank || '?',
|
|
37
|
+
enabled: data.enabled !== false,
|
|
38
|
+
};
|
|
39
|
+
})
|
|
40
|
+
.filter(Boolean)
|
|
41
|
+
.filter(a => a.enabled);
|
|
42
|
+
} catch (e) {
|
|
43
|
+
logError('listAgents', e);
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Find agent by name (case-insensitive)
|
|
49
|
+
function findAgent(agentsDir, name) {
|
|
50
|
+
const agents = listAgents(agentsDir);
|
|
51
|
+
return agents.find(a => a.name.toLowerCase() === name.toLowerCase()) || null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Read global config
|
|
55
|
+
function readGlobalConfig(agentsDir) {
|
|
56
|
+
if (!agentsDir) return null;
|
|
57
|
+
return readJson(path.join(agentsDir, 'global.json'));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
module.exports = { detectAgentsDir, listAgents, findAgent, readGlobalConfig };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// Soul MCP v4.1 — Default config. Zero hardcoded paths, all dynamic.
|
|
2
|
+
const path = require('path');
|
|
3
|
+
|
|
4
|
+
module.exports = {
|
|
5
|
+
// All paths derived dynamically. No hardcoding.
|
|
6
|
+
SOUL_ROOT: path.resolve(__dirname, '..'),
|
|
7
|
+
DATA_DIR: path.resolve(__dirname, '..', 'data'),
|
|
8
|
+
AGENTS_DIR: null, // Auto-detected by agent-registry.js
|
|
9
|
+
|
|
10
|
+
// Language (for time formatting)
|
|
11
|
+
LANG: process.env.N2_LANG || 'en',
|
|
12
|
+
|
|
13
|
+
// Context search settings (n2_context_search)
|
|
14
|
+
SEARCH: {
|
|
15
|
+
maxDepth: 6, // Max directory recursion depth
|
|
16
|
+
minKeywordLength: 2, // Min keyword length to search
|
|
17
|
+
previewLength: 200, // Characters shown in result preview
|
|
18
|
+
recencyBonus: 10, // Max score bonus for recent items (days)
|
|
19
|
+
defaultMaxResults: 10, // Default result limit
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
// File tree rendering settings (boot/work_end output)
|
|
23
|
+
FILE_TREE: {
|
|
24
|
+
hidePaths: [
|
|
25
|
+
'test', '_data', '_history',
|
|
26
|
+
'soul/data/kv-cache',
|
|
27
|
+
],
|
|
28
|
+
compactPaths: [
|
|
29
|
+
'soul/data/projects',
|
|
30
|
+
'soul/data/memory',
|
|
31
|
+
],
|
|
32
|
+
childLimit: 20,
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
// KV-Cache settings
|
|
36
|
+
KV_CACHE: {
|
|
37
|
+
enabled: true,
|
|
38
|
+
autoSaveOnWorkEnd: true,
|
|
39
|
+
autoLoadOnBoot: true,
|
|
40
|
+
backend: 'json', // 'json' (default) or 'sqlite'
|
|
41
|
+
maxSnapshotsPerProject: 50,
|
|
42
|
+
maxSnapshotAgeDays: 30,
|
|
43
|
+
compressionTarget: 1000,
|
|
44
|
+
snapshotDir: null, // null = auto (DATA_DIR/kv-cache/snapshots)
|
|
45
|
+
sqliteDir: null, // null = auto (DATA_DIR/kv-cache/sqlite)
|
|
46
|
+
tokenBudget: {
|
|
47
|
+
bootContext: 2000,
|
|
48
|
+
searchResult: 500,
|
|
49
|
+
progressiveLoad: true,
|
|
50
|
+
},
|
|
51
|
+
tier: {
|
|
52
|
+
hotDays: 7, // Hot: in-memory cache (days)
|
|
53
|
+
warmDays: 30, // Warm: file/db access (days)
|
|
54
|
+
},
|
|
55
|
+
embedding: {
|
|
56
|
+
enabled: false, // Requires Ollama with nomic-embed-text
|
|
57
|
+
model: 'nomic-embed-text',
|
|
58
|
+
endpoint: null, // null = http://127.0.0.1:11434
|
|
59
|
+
},
|
|
60
|
+
backup: {
|
|
61
|
+
enabled: false,
|
|
62
|
+
dir: null, // null = DATA_DIR/kv-cache/backups
|
|
63
|
+
schedule: 'daily', // 'manual', 'daily', 'weekly'
|
|
64
|
+
keepCount: 7,
|
|
65
|
+
incremental: true,
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
};
|