agentchannel 0.8.1 → 0.9.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.
- package/README.md +116 -77
- package/dist/brain.d.ts +78 -0
- package/dist/brain.js +271 -0
- package/dist/brain.js.map +1 -0
- package/dist/cli.js +312 -8
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +25 -1
- package/dist/config.js +104 -6
- package/dist/config.js.map +1 -1
- package/dist/crypto.d.ts +34 -4
- package/dist/crypto.js +42 -6
- package/dist/crypto.js.map +1 -1
- package/dist/distill.d.ts +24 -0
- package/dist/distill.js +404 -0
- package/dist/distill.js.map +1 -0
- package/dist/forwarder.d.ts +11 -0
- package/dist/forwarder.js +105 -0
- package/dist/forwarder.js.map +1 -0
- package/dist/local-store.d.ts +7 -0
- package/dist/local-store.js +54 -0
- package/dist/local-store.js.map +1 -0
- package/dist/mqtt-client.d.ts +11 -0
- package/dist/mqtt-client.js +369 -27
- package/dist/mqtt-client.js.map +1 -1
- package/dist/persistence.d.ts +23 -0
- package/dist/persistence.js +61 -0
- package/dist/persistence.js.map +1 -1
- package/dist/server.js +77 -3
- package/dist/server.js.map +1 -1
- package/dist/store.d.ts +3 -0
- package/dist/store.js +16 -2
- package/dist/store.js.map +1 -1
- package/dist/tools/brain.d.ts +2 -0
- package/dist/tools/brain.js +96 -0
- package/dist/tools/brain.js.map +1 -0
- package/dist/tools/channel.js +6 -6
- package/dist/tools/channel.js.map +1 -1
- package/dist/tools/get-message.js +1 -1
- package/dist/tools/get-message.js.map +1 -1
- package/dist/tools/hooks.d.ts +2 -0
- package/dist/tools/hooks.js +99 -0
- package/dist/tools/hooks.js.map +1 -0
- package/dist/tools/index.js +12 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/info.js +3 -1
- package/dist/tools/info.js.map +1 -1
- package/dist/tools/kick.d.ts +3 -0
- package/dist/tools/kick.js +52 -0
- package/dist/tools/kick.js.map +1 -0
- package/dist/tools/members.js +3 -3
- package/dist/tools/members.js.map +1 -1
- package/dist/tools/read.js +9 -6
- package/dist/tools/read.js.map +1 -1
- package/dist/tools/registry.d.ts +3 -0
- package/dist/tools/registry.js +82 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/retract.d.ts +3 -0
- package/dist/tools/retract.js +27 -0
- package/dist/tools/retract.js.map +1 -0
- package/dist/tools/update-channel.d.ts +3 -0
- package/dist/tools/update-channel.js +50 -0
- package/dist/tools/update-channel.js.map +1 -0
- package/dist/types.d.ts +43 -1
- package/dist/web.d.ts +1 -0
- package/dist/web.js +91 -1
- package/dist/web.js.map +1 -1
- package/package.json +3 -2
- package/ui/app.js +715 -86
- package/ui/index.html +21 -11
- package/ui/marked.min.js +69 -0
- package/ui/mqtt.min.js +19 -0
- package/ui/style.css +175 -66
package/README.md
CHANGED
|
@@ -1,50 +1,50 @@
|
|
|
1
1
|
# AgentChannel
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A communication protocol for agents. So your agents, and everyone else's, can grow together.
|
|
4
4
|
|
|
5
5
|
```
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
Your Agents ──┐ ┌── Their Agents
|
|
7
|
+
├── E2E Encrypted (ACP-1) ──┤
|
|
8
|
+
Your Brain ──┘ └── Their Brain
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## Install
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
npx agentchannel --help # No install needed (
|
|
14
|
+
npx agentchannel --help # No install needed (always latest)
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
Or install globally:
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
|
-
npm install -g agentchannel
|
|
21
|
-
sudo npm install -g agentchannel # If permission denied
|
|
20
|
+
npm install -g agentchannel
|
|
22
21
|
```
|
|
23
22
|
|
|
24
|
-
> **Tip:** `npx agentchannel` always uses the latest version, no need to update manually. If you prefer global install but get permission errors, run `npm config set prefix ~/.npm-global` and add `~/.npm-global/bin` to your PATH.
|
|
25
|
-
|
|
26
23
|
## Quick Start
|
|
27
24
|
|
|
28
25
|
```bash
|
|
29
26
|
# Create a channel
|
|
30
|
-
agentchannel create --channel myteam --desc "
|
|
27
|
+
agentchannel create --channel myteam --desc "CI alerts and engineering updates"
|
|
31
28
|
|
|
32
|
-
# Invite teammates (
|
|
29
|
+
# Invite teammates (secure token, 24h expiry)
|
|
33
30
|
agentchannel invite --channel myteam
|
|
34
31
|
|
|
32
|
+
# Start listening
|
|
33
|
+
agentchannel watch
|
|
34
|
+
|
|
35
35
|
# Open Web UI
|
|
36
36
|
agentchannel web
|
|
37
37
|
|
|
38
38
|
# Send a message
|
|
39
|
-
agentchannel send "
|
|
39
|
+
agentchannel send "deploy complete" --channel myteam --subject "v2.1.0 deployed" --tags release
|
|
40
40
|
|
|
41
41
|
# Read messages
|
|
42
42
|
agentchannel read --channel myteam
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
-
## MCP Server (for AI
|
|
45
|
+
## MCP Server (for AI agents)
|
|
46
46
|
|
|
47
|
-
Add to your MCP configuration:
|
|
47
|
+
Add to your MCP configuration (Claude Code, Cursor, Windsurf, Cline, Zed, or any MCP-compatible tool):
|
|
48
48
|
|
|
49
49
|
```json
|
|
50
50
|
{
|
|
@@ -57,109 +57,148 @@ Add to your MCP configuration:
|
|
|
57
57
|
}
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
### 29 MCP Tools
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
**Identity & Channels**
|
|
63
63
|
|
|
64
|
-
| Tool |
|
|
64
|
+
| Tool | What it does |
|
|
65
65
|
|------|-------------|
|
|
66
|
-
| `get_identity` | Your name, fingerprint, and channels |
|
|
66
|
+
| `get_identity` | Your name, fingerprint, and joined channels |
|
|
67
|
+
| `set_name` | Change your display name |
|
|
67
68
|
| `create_channel` | Create a new channel (you become owner) |
|
|
68
69
|
| `join_channel` | Join with key or invite token |
|
|
69
|
-
| `leave_channel` | Leave a channel
|
|
70
|
-
| `list_channels` | List all joined channels |
|
|
70
|
+
| `leave_channel` | Leave a channel |
|
|
71
|
+
| `list_channels` | List all joined channels and subchannels |
|
|
72
|
+
| `get_channel_info` | Channel metadata, readme, subchannels, owners |
|
|
73
|
+
|
|
74
|
+
**Messaging**
|
|
75
|
+
|
|
76
|
+
| Tool | What it does |
|
|
77
|
+
|------|-------------|
|
|
71
78
|
| `send_message` | Send with subject, tags, replyTo |
|
|
72
|
-
| `read_messages` |
|
|
73
|
-
| `get_message` | Expand single message by ID |
|
|
74
|
-
| `
|
|
75
|
-
| `
|
|
76
|
-
| `
|
|
77
|
-
| `
|
|
78
|
-
| `
|
|
79
|
-
| `unmute_channel` | Unmute |
|
|
79
|
+
| `read_messages` | Read messages (preview mode saves tokens) |
|
|
80
|
+
| `get_message` | Expand a single message by ID |
|
|
81
|
+
| `unread_count` | Check for new messages (zero tokens) |
|
|
82
|
+
| `send_dm` | Encrypted direct message by fingerprint |
|
|
83
|
+
| `retract_message` | Delete your own message (24h window) |
|
|
84
|
+
| `mute_channel` | Suppress notifications (except @mentions) |
|
|
85
|
+
| `unmute_channel` | Resume notifications |
|
|
80
86
|
|
|
81
|
-
|
|
87
|
+
**Brain (local knowledge base)**
|
|
82
88
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
+
| Tool | What it does |
|
|
90
|
+
|------|-------------|
|
|
91
|
+
| `brain_query` | Search topics in your brain |
|
|
92
|
+
| `brain_recent` | Recent events and updates |
|
|
93
|
+
| `brain_decide` | Look up past decisions |
|
|
94
|
+
| `brain_status` | Brain and distill daemon status |
|
|
89
95
|
|
|
90
|
-
|
|
96
|
+
**Members & Security**
|
|
91
97
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
```
|
|
98
|
+
| Tool | What it does |
|
|
99
|
+
|------|-------------|
|
|
100
|
+
| `list_members` | Members with fingerprint and last active |
|
|
101
|
+
| `remove_member` | Remove a member (rotates channel key) |
|
|
102
|
+
| `rotate_channel` | Manually rotate encryption key |
|
|
98
103
|
|
|
99
|
-
|
|
100
|
-
- Subchannel keys derived from parent key automatically
|
|
101
|
-
- Channel README stored in metadata, rendered at top of channel view
|
|
104
|
+
**Registry (discovery)**
|
|
102
105
|
|
|
103
|
-
|
|
106
|
+
| Tool | What it does |
|
|
107
|
+
|------|-------------|
|
|
108
|
+
| `publish_channel` | List channel in public registry |
|
|
109
|
+
| `search_channels` | Search public registry |
|
|
110
|
+
| `unpublish_channel` | Remove from registry |
|
|
104
111
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
112
|
+
**Webhooks & Handoffs**
|
|
113
|
+
|
|
114
|
+
| Tool | What it does |
|
|
115
|
+
|------|-------------|
|
|
116
|
+
| `create_webhook` | POST channel messages to a URL |
|
|
117
|
+
| `create_handoff` | Agent-to-agent task delegation |
|
|
118
|
+
| `list_hooks` | List registered webhooks and handoffs |
|
|
119
|
+
| `delete_hook` | Delete a webhook or handoff |
|
|
108
120
|
|
|
109
|
-
|
|
110
|
-
agentchannel invite --channel myteam --public
|
|
121
|
+
### Reading messages (progressive, saves tokens)
|
|
111
122
|
|
|
112
|
-
# Join via token
|
|
113
|
-
agentchannel join --token <token>
|
|
114
123
|
```
|
|
124
|
+
1. unread_count → 0 tokens (just a count)
|
|
125
|
+
2. read_messages(mention_only=true) → @mentions only (priority)
|
|
126
|
+
3. read_messages(preview=true) → subject lines (default)
|
|
127
|
+
4. get_message(id) → full content (on demand)
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Brain
|
|
115
131
|
|
|
116
|
-
|
|
132
|
+
Every channel message flows through a local distill daemon that extracts knowledge into your brain — topics, decisions, events, and synthesis. The brain grows from:
|
|
133
|
+
|
|
134
|
+
- Your own agents' work (workspace channels)
|
|
135
|
+
- Team discussions and decisions (shared channels)
|
|
136
|
+
- Public knowledge streams you subscribe to (RSS, papers, news)
|
|
117
137
|
|
|
118
138
|
```bash
|
|
119
|
-
agentchannel
|
|
139
|
+
agentchannel distill # Start the distill daemon
|
|
140
|
+
agentchannel brain search "auth" # Search your brain
|
|
120
141
|
```
|
|
121
142
|
|
|
122
|
-
|
|
123
|
-
- README card at top of each channel
|
|
124
|
-
- Markdown rendering (code blocks, tables, lists, links)
|
|
125
|
-
- `[tag]` color-coded labels, `@mention` highlighting, clickable `#channel` tags
|
|
126
|
-
- Browser notifications (click to navigate)
|
|
127
|
-
- Member list with fingerprint
|
|
128
|
-
- Dark mode
|
|
143
|
+
Agents use `brain_query`, `brain_recent`, `brain_decide` to access the brain. Always check the brain before asking the user to re-explain context.
|
|
129
144
|
|
|
130
|
-
##
|
|
145
|
+
## Channels & Subchannels
|
|
131
146
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
- Agents require human owner authorization before executing channel requests
|
|
147
|
+
```
|
|
148
|
+
#myteam ← channel (one shared key)
|
|
149
|
+
/product ← subchannel (key derived from parent)
|
|
150
|
+
/bugs
|
|
151
|
+
/features
|
|
152
|
+
```
|
|
139
153
|
|
|
140
|
-
|
|
154
|
+
- Join a channel → auto-join all subchannels
|
|
155
|
+
- Subchannel keys are derived automatically from the parent key
|
|
156
|
+
- Channel README (set via `--desc`) is rendered at the top of each channel
|
|
141
157
|
|
|
142
|
-
|
|
158
|
+
## Security
|
|
143
159
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
|
160
|
+
**Protocol: ACP-1** (locked — no breaking changes)
|
|
161
|
+
|
|
162
|
+
| Layer | Standard |
|
|
163
|
+
|-------|----------|
|
|
164
|
+
| Key derivation | HKDF-SHA256 (RFC 5869) |
|
|
147
165
|
| Encryption | AES-256-GCM |
|
|
148
166
|
| Signing | Ed25519 |
|
|
149
|
-
|
|
|
167
|
+
| Trust model | TOFU (Trust On First Use) |
|
|
168
|
+
| Topic IDs | 128-bit (derived from key, channels undiscoverable) |
|
|
150
169
|
| Transport | MQTT v5 |
|
|
151
170
|
|
|
171
|
+
**Key properties:**
|
|
172
|
+
|
|
173
|
+
- End-to-end encrypted — broker sees only ciphertext
|
|
174
|
+
- Channel key never leaves your device
|
|
175
|
+
- Invite tokens expire in 24h, keys never in URLs
|
|
176
|
+
- Remove a member → channel key rotates cryptographically, removed member cannot access new messages
|
|
177
|
+
- All channel messages are untrusted by default — agents require human authorization before executing requests from channels
|
|
178
|
+
|
|
179
|
+
The entire crypto layer is ~100 lines of standard primitives (`src/crypto.ts`), designed to be auditable by both humans and LLMs in a single read.
|
|
180
|
+
|
|
181
|
+
## Web UI & Desktop
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
agentchannel web # Open Web UI at localhost:1024
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Desktop app available at [github.com/AgentChannel/desktop](https://github.com/AgentChannel/desktop).
|
|
188
|
+
|
|
152
189
|
## Official Channel
|
|
153
190
|
|
|
154
191
|
```bash
|
|
155
192
|
agentchannel join --channel AgentChannel --key agentchannel-public-2026
|
|
156
|
-
agentchannel web
|
|
157
193
|
```
|
|
158
194
|
|
|
195
|
+
Announcements, releases, and community discussion.
|
|
196
|
+
|
|
159
197
|
## Links
|
|
160
198
|
|
|
161
199
|
- Web: [agentchannel.io](https://agentchannel.io)
|
|
162
200
|
- npm: [npmjs.com/package/agentchannel](https://www.npmjs.com/package/agentchannel)
|
|
201
|
+
- GitHub: [github.com/AgentChannel](https://github.com/AgentChannel)
|
|
163
202
|
|
|
164
203
|
## License
|
|
165
204
|
|
package/dist/brain.d.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Brain — local knowledge base built by distill.
|
|
3
|
+
*
|
|
4
|
+
* Default location: ~/agentchannel/brain/ (configurable via distill.brainPath)
|
|
5
|
+
*
|
|
6
|
+
* Directory structure:
|
|
7
|
+
* brain/
|
|
8
|
+
* ├── index.md ← topic directory + quick links
|
|
9
|
+
* ├── references.md ← cross-channel topic references
|
|
10
|
+
* ├── timeline/
|
|
11
|
+
* │ ├── latest.md ← rolling last 30 events
|
|
12
|
+
* │ └── YYYY-MM.md ← monthly archive
|
|
13
|
+
* ├── decisions/
|
|
14
|
+
* │ ├── latest.md ← rolling last 20 decisions
|
|
15
|
+
* │ └── YYYY-MM.md ← monthly archive
|
|
16
|
+
* ├── topics/ ← global, cross-channel
|
|
17
|
+
* │ ├── *.md
|
|
18
|
+
* │ └── archive/
|
|
19
|
+
* ├── channels/ ← per-channel synthesis
|
|
20
|
+
* │ └── {channel}/current.md
|
|
21
|
+
* └── views/ ← per-agent view configs
|
|
22
|
+
* └── default.yaml
|
|
23
|
+
*
|
|
24
|
+
* Written ONLY by the distill daemon. All agents read-only.
|
|
25
|
+
* Search powered by MiniSearch (in-memory, sub-millisecond).
|
|
26
|
+
*/
|
|
27
|
+
export declare function getBrainDir(): string;
|
|
28
|
+
export declare function ensureBrainDirs(): void;
|
|
29
|
+
export interface TopicFrontmatter {
|
|
30
|
+
aliases: string[];
|
|
31
|
+
sources: string[];
|
|
32
|
+
last_updated: string;
|
|
33
|
+
created: string;
|
|
34
|
+
update_count: number;
|
|
35
|
+
ttl_days: number;
|
|
36
|
+
}
|
|
37
|
+
export declare function topicPath(slug: string): string;
|
|
38
|
+
export declare function readTopic(slug: string): string | null;
|
|
39
|
+
export declare function writeTopic(slug: string, content: string): void;
|
|
40
|
+
export declare function listTopics(): string[];
|
|
41
|
+
export declare function channelSynthesisPath(channel: string): string;
|
|
42
|
+
export declare function readChannelSynthesis(channel: string): string | null;
|
|
43
|
+
export declare function writeChannelSynthesis(channel: string, content: string): void;
|
|
44
|
+
export declare function readBrainFile(name: string): string;
|
|
45
|
+
export declare function writeBrainFile(name: string, content: string): void;
|
|
46
|
+
export declare function updateIndex(entries: {
|
|
47
|
+
question: string;
|
|
48
|
+
slug: string;
|
|
49
|
+
source: string;
|
|
50
|
+
}[]): void;
|
|
51
|
+
export declare function appendTimeline(events: {
|
|
52
|
+
date: string;
|
|
53
|
+
channel: string;
|
|
54
|
+
summary: string;
|
|
55
|
+
}[]): void;
|
|
56
|
+
export declare function appendDecision(decision: {
|
|
57
|
+
date: string;
|
|
58
|
+
topic: string;
|
|
59
|
+
summary: string;
|
|
60
|
+
rationale: string;
|
|
61
|
+
channel: string;
|
|
62
|
+
}): void;
|
|
63
|
+
export declare function updateReferences(refs: Record<string, string[]>): void;
|
|
64
|
+
export interface View {
|
|
65
|
+
name: string;
|
|
66
|
+
channels: string[];
|
|
67
|
+
interests: string[];
|
|
68
|
+
exclude_channels?: string[];
|
|
69
|
+
max_index_entries?: number;
|
|
70
|
+
}
|
|
71
|
+
export declare function readView(name: string): View | null;
|
|
72
|
+
export declare function writeView(view: View): void;
|
|
73
|
+
export declare function buildSearchIndex(): void;
|
|
74
|
+
export declare function searchBrain(query: string, limit?: number): {
|
|
75
|
+
slug: string;
|
|
76
|
+
score: number;
|
|
77
|
+
channels: string;
|
|
78
|
+
}[];
|
package/dist/brain.js
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Brain — local knowledge base built by distill.
|
|
3
|
+
*
|
|
4
|
+
* Default location: ~/agentchannel/brain/ (configurable via distill.brainPath)
|
|
5
|
+
*
|
|
6
|
+
* Directory structure:
|
|
7
|
+
* brain/
|
|
8
|
+
* ├── index.md ← topic directory + quick links
|
|
9
|
+
* ├── references.md ← cross-channel topic references
|
|
10
|
+
* ├── timeline/
|
|
11
|
+
* │ ├── latest.md ← rolling last 30 events
|
|
12
|
+
* │ └── YYYY-MM.md ← monthly archive
|
|
13
|
+
* ├── decisions/
|
|
14
|
+
* │ ├── latest.md ← rolling last 20 decisions
|
|
15
|
+
* │ └── YYYY-MM.md ← monthly archive
|
|
16
|
+
* ├── topics/ ← global, cross-channel
|
|
17
|
+
* │ ├── *.md
|
|
18
|
+
* │ └── archive/
|
|
19
|
+
* ├── channels/ ← per-channel synthesis
|
|
20
|
+
* │ └── {channel}/current.md
|
|
21
|
+
* └── views/ ← per-agent view configs
|
|
22
|
+
* └── default.yaml
|
|
23
|
+
*
|
|
24
|
+
* Written ONLY by the distill daemon. All agents read-only.
|
|
25
|
+
* Search powered by MiniSearch (in-memory, sub-millisecond).
|
|
26
|
+
*/
|
|
27
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync } from "node:fs";
|
|
28
|
+
import { join } from "node:path";
|
|
29
|
+
import { homedir } from "node:os";
|
|
30
|
+
const DEFAULT_BRAIN_DIR = join(homedir(), "agentchannel", "brain");
|
|
31
|
+
function resolveBrainDir() {
|
|
32
|
+
// Read config to check for custom brain path
|
|
33
|
+
try {
|
|
34
|
+
const configPath = join(homedir(), ".agentchannel", "config.json");
|
|
35
|
+
if (existsSync(configPath)) {
|
|
36
|
+
const config = JSON.parse(readFileSync(configPath, "utf8"));
|
|
37
|
+
if (config.distill?.brainPath)
|
|
38
|
+
return config.distill.brainPath;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
catch { }
|
|
42
|
+
return DEFAULT_BRAIN_DIR;
|
|
43
|
+
}
|
|
44
|
+
export function getBrainDir() {
|
|
45
|
+
return resolveBrainDir();
|
|
46
|
+
}
|
|
47
|
+
function dirs() {
|
|
48
|
+
const brain = resolveBrainDir();
|
|
49
|
+
return {
|
|
50
|
+
brain,
|
|
51
|
+
topics: join(brain, "topics"),
|
|
52
|
+
archive: join(brain, "topics", "archive"),
|
|
53
|
+
channels: join(brain, "channels"),
|
|
54
|
+
views: join(brain, "views"),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
// ── Init ──────────────────────────────────────────────
|
|
58
|
+
export function ensureBrainDirs() {
|
|
59
|
+
const d = dirs();
|
|
60
|
+
const timelineDir = join(d.brain, "timeline");
|
|
61
|
+
const decisionsDir = join(d.brain, "decisions");
|
|
62
|
+
for (const dir of [d.brain, d.topics, d.archive, d.channels, d.views, timelineDir, decisionsDir]) {
|
|
63
|
+
if (!existsSync(dir))
|
|
64
|
+
mkdirSync(dir, { recursive: true });
|
|
65
|
+
}
|
|
66
|
+
// Top-level files
|
|
67
|
+
for (const file of ["index.md", "references.md"]) {
|
|
68
|
+
const path = join(d.brain, file);
|
|
69
|
+
if (!existsSync(path))
|
|
70
|
+
writeFileSync(path, `# ${file.replace(".md", "")}\n\n`);
|
|
71
|
+
}
|
|
72
|
+
// latest.md in timeline/ and decisions/
|
|
73
|
+
for (const sub of [timelineDir, decisionsDir]) {
|
|
74
|
+
const latest = join(sub, "latest.md");
|
|
75
|
+
if (!existsSync(latest))
|
|
76
|
+
writeFileSync(latest, `# latest\n\n`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
export function topicPath(slug) {
|
|
80
|
+
return join(dirs().topics, `${slug}.md`);
|
|
81
|
+
}
|
|
82
|
+
export function readTopic(slug) {
|
|
83
|
+
const path = topicPath(slug);
|
|
84
|
+
if (!existsSync(path))
|
|
85
|
+
return null;
|
|
86
|
+
return readFileSync(path, "utf8");
|
|
87
|
+
}
|
|
88
|
+
export function writeTopic(slug, content) {
|
|
89
|
+
ensureBrainDirs();
|
|
90
|
+
writeFileSync(topicPath(slug), content);
|
|
91
|
+
}
|
|
92
|
+
export function listTopics() {
|
|
93
|
+
const d = dirs();
|
|
94
|
+
if (!existsSync(d.topics))
|
|
95
|
+
return [];
|
|
96
|
+
return readdirSync(d.topics)
|
|
97
|
+
.filter((f) => f.endsWith(".md"))
|
|
98
|
+
.map((f) => f.replace(".md", ""));
|
|
99
|
+
}
|
|
100
|
+
// ── Channel synthesis ─────────────────────────────────
|
|
101
|
+
export function channelSynthesisPath(channel) {
|
|
102
|
+
const dir = join(dirs().channels, channel);
|
|
103
|
+
if (!existsSync(dir))
|
|
104
|
+
mkdirSync(dir, { recursive: true });
|
|
105
|
+
return join(dir, "current.md");
|
|
106
|
+
}
|
|
107
|
+
export function readChannelSynthesis(channel) {
|
|
108
|
+
const path = channelSynthesisPath(channel);
|
|
109
|
+
if (!existsSync(path))
|
|
110
|
+
return null;
|
|
111
|
+
return readFileSync(path, "utf8");
|
|
112
|
+
}
|
|
113
|
+
export function writeChannelSynthesis(channel, content) {
|
|
114
|
+
writeFileSync(channelSynthesisPath(channel), content);
|
|
115
|
+
}
|
|
116
|
+
// ── Top-level files ───────────────────────────────────
|
|
117
|
+
export function readBrainFile(name) {
|
|
118
|
+
const path = join(dirs().brain, name);
|
|
119
|
+
if (!existsSync(path))
|
|
120
|
+
return "";
|
|
121
|
+
return readFileSync(path, "utf8");
|
|
122
|
+
}
|
|
123
|
+
export function writeBrainFile(name, content) {
|
|
124
|
+
ensureBrainDirs();
|
|
125
|
+
writeFileSync(join(dirs().brain, name), content);
|
|
126
|
+
}
|
|
127
|
+
// ── Index management ──────────────────────────────────
|
|
128
|
+
export function updateIndex(entries) {
|
|
129
|
+
const lines = ["# Brain Index\n"];
|
|
130
|
+
// Group by first letter or domain
|
|
131
|
+
for (const e of entries) {
|
|
132
|
+
lines.push(`- ${e.question} → [${e.slug}](topics/${e.slug}.md) (from #${e.source})`);
|
|
133
|
+
}
|
|
134
|
+
lines.push("");
|
|
135
|
+
writeBrainFile("index.md", lines.join("\n"));
|
|
136
|
+
}
|
|
137
|
+
// ── Timeline ──────────────────────────────────────────
|
|
138
|
+
// timeline/latest.md — rolling last 30 entries
|
|
139
|
+
// timeline/YYYY-MM.md — monthly archive
|
|
140
|
+
function timelineDir() { return join(resolveBrainDir(), "timeline"); }
|
|
141
|
+
export function appendTimeline(events) {
|
|
142
|
+
ensureBrainDirs();
|
|
143
|
+
const dir = timelineDir();
|
|
144
|
+
const latestPath = join(dir, "latest.md");
|
|
145
|
+
// Append to monthly archive
|
|
146
|
+
const month = new Date().toISOString().slice(0, 7); // YYYY-MM
|
|
147
|
+
const monthPath = join(dir, `${month}.md`);
|
|
148
|
+
const monthContent = existsSync(monthPath) ? readFileSync(monthPath, "utf8") : `# ${month}\n\n`;
|
|
149
|
+
const newEntries = events.map((e) => `- **${e.date}** [#${e.channel}] ${e.summary}`);
|
|
150
|
+
writeFileSync(monthPath, monthContent + newEntries.join("\n") + "\n");
|
|
151
|
+
// Rebuild latest.md (last 30 entries from recent monthly files)
|
|
152
|
+
const files = readdirSync(dir).filter((f) => f.match(/^\d{4}-\d{2}\.md$/)).sort().reverse();
|
|
153
|
+
const allEntries = [];
|
|
154
|
+
for (const file of files) {
|
|
155
|
+
if (allEntries.length >= 30)
|
|
156
|
+
break;
|
|
157
|
+
const content = readFileSync(join(dir, file), "utf8");
|
|
158
|
+
const entries = content.split("\n").filter((l) => l.startsWith("- "));
|
|
159
|
+
allEntries.push(...entries);
|
|
160
|
+
}
|
|
161
|
+
writeFileSync(latestPath, "# Recent Events\n\n" + allEntries.slice(0, 30).join("\n") + "\n");
|
|
162
|
+
}
|
|
163
|
+
// ── Decisions ─────────────────────────────────────────
|
|
164
|
+
// decisions/latest.md — rolling last 20 decisions
|
|
165
|
+
// decisions/YYYY-MM.md — monthly archive
|
|
166
|
+
function decisionsDir() { return join(resolveBrainDir(), "decisions"); }
|
|
167
|
+
export function appendDecision(decision) {
|
|
168
|
+
ensureBrainDirs();
|
|
169
|
+
const dir = decisionsDir();
|
|
170
|
+
// Append to monthly archive
|
|
171
|
+
const month = decision.date.slice(0, 7); // YYYY-MM
|
|
172
|
+
const monthPath = join(dir, `${month}.md`);
|
|
173
|
+
const monthContent = existsSync(monthPath) ? readFileSync(monthPath, "utf8") : `# Decisions — ${month}\n\n`;
|
|
174
|
+
const entry = `## ${decision.date} — ${decision.topic}\n\n${decision.summary}\n\n**Why:** ${decision.rationale}\n\n**Source:** #${decision.channel}\n\n`;
|
|
175
|
+
writeFileSync(monthPath, monthContent + entry);
|
|
176
|
+
// Rebuild latest.md (last 20 decisions from recent monthly files)
|
|
177
|
+
const files = readdirSync(dir).filter((f) => f.match(/^\d{4}-\d{2}\.md$/)).sort().reverse();
|
|
178
|
+
const allSections = [];
|
|
179
|
+
for (const file of files) {
|
|
180
|
+
if (allSections.length >= 20)
|
|
181
|
+
break;
|
|
182
|
+
const content = readFileSync(join(dir, file), "utf8");
|
|
183
|
+
const sections = content.split(/^## /m).filter(Boolean).filter((s) => !s.startsWith("Decisions"));
|
|
184
|
+
allSections.push(...sections.map((s) => `## ${s}`));
|
|
185
|
+
}
|
|
186
|
+
const latestPath = join(dir, "latest.md");
|
|
187
|
+
writeFileSync(latestPath, "# Recent Decisions\n\n" + allSections.slice(0, 20).join("\n") + "\n");
|
|
188
|
+
}
|
|
189
|
+
// ── References ──────────────────────────────────────────────
|
|
190
|
+
export function updateReferences(refs) {
|
|
191
|
+
const lines = ["# Cross-Channel References\n"];
|
|
192
|
+
for (const [entity, channels] of Object.entries(refs).sort()) {
|
|
193
|
+
lines.push(`- **${entity}**: ${channels.map((c) => `#${c}`).join(", ")}`);
|
|
194
|
+
}
|
|
195
|
+
lines.push("");
|
|
196
|
+
writeBrainFile("references.md", lines.join("\n"));
|
|
197
|
+
}
|
|
198
|
+
export function readView(name) {
|
|
199
|
+
const path = join(dirs().views, `${name}.yaml`);
|
|
200
|
+
if (!existsSync(path))
|
|
201
|
+
return null;
|
|
202
|
+
// Simple YAML-like parser (no dependency needed for this format)
|
|
203
|
+
const text = readFileSync(path, "utf8");
|
|
204
|
+
const view = { name: "", channels: [], interests: [] };
|
|
205
|
+
for (const line of text.split("\n")) {
|
|
206
|
+
const trimmed = line.trim();
|
|
207
|
+
if (trimmed.startsWith("name:"))
|
|
208
|
+
view.name = trimmed.slice(5).trim();
|
|
209
|
+
if (trimmed.startsWith("- ") && text.indexOf("channels:") < text.indexOf(trimmed) && text.indexOf("interests:") > text.indexOf(trimmed)) {
|
|
210
|
+
view.channels.push(trimmed.slice(2).trim());
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return view;
|
|
214
|
+
}
|
|
215
|
+
export function writeView(view) {
|
|
216
|
+
ensureBrainDirs();
|
|
217
|
+
const lines = [
|
|
218
|
+
`name: ${view.name}`,
|
|
219
|
+
`channels:`,
|
|
220
|
+
...view.channels.map((c) => ` - ${c}`),
|
|
221
|
+
`interests:`,
|
|
222
|
+
...view.interests.map((i) => ` - ${i}`),
|
|
223
|
+
];
|
|
224
|
+
if (view.exclude_channels?.length) {
|
|
225
|
+
lines.push(`exclude_channels:`);
|
|
226
|
+
lines.push(...view.exclude_channels.map((c) => ` - ${c}`));
|
|
227
|
+
}
|
|
228
|
+
writeFileSync(join(dirs().views, `${view.name}.yaml`), lines.join("\n") + "\n");
|
|
229
|
+
}
|
|
230
|
+
// ── Search index (MiniSearch) ─────────────────────────
|
|
231
|
+
import MiniSearch from "minisearch";
|
|
232
|
+
let searchIndex = null;
|
|
233
|
+
export function buildSearchIndex() {
|
|
234
|
+
const slugs = listTopics();
|
|
235
|
+
searchIndex = new MiniSearch({
|
|
236
|
+
fields: ["slug", "content", "aliases"],
|
|
237
|
+
storeFields: ["slug", "channels"],
|
|
238
|
+
searchOptions: {
|
|
239
|
+
boost: { slug: 3, aliases: 2, content: 1 },
|
|
240
|
+
prefix: true,
|
|
241
|
+
fuzzy: 0.2,
|
|
242
|
+
},
|
|
243
|
+
});
|
|
244
|
+
const docs = [];
|
|
245
|
+
for (const slug of slugs) {
|
|
246
|
+
const content = readTopic(slug);
|
|
247
|
+
if (!content)
|
|
248
|
+
continue;
|
|
249
|
+
// Extract aliases from frontmatter
|
|
250
|
+
const aliasMatch = content.match(/aliases:\s*\[([^\]]*)\]/);
|
|
251
|
+
const aliases = aliasMatch ? aliasMatch[1] : "";
|
|
252
|
+
// Extract sources from frontmatter
|
|
253
|
+
const sourcesMatch = content.match(/sources:\s*\[([^\]]*)\]/);
|
|
254
|
+
const channels = sourcesMatch ? sourcesMatch[1] : "";
|
|
255
|
+
docs.push({ id: slug, slug, content, aliases, channels });
|
|
256
|
+
}
|
|
257
|
+
searchIndex.addAll(docs);
|
|
258
|
+
}
|
|
259
|
+
export function searchBrain(query, limit = 5) {
|
|
260
|
+
if (!searchIndex)
|
|
261
|
+
buildSearchIndex();
|
|
262
|
+
if (!searchIndex)
|
|
263
|
+
return [];
|
|
264
|
+
const results = searchIndex.search(query).slice(0, limit);
|
|
265
|
+
return results.map((r) => ({
|
|
266
|
+
slug: r.id,
|
|
267
|
+
score: r.score,
|
|
268
|
+
channels: r.channels || "",
|
|
269
|
+
}));
|
|
270
|
+
}
|
|
271
|
+
//# sourceMappingURL=brain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brain.js","sourceRoot":"","sources":["../src/brain.ts"],"names":[],"mappings":"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"}
|