@animalabs/connectome-host 0.3.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/.env.example +20 -0
- package/.github/workflows/publish.yml +65 -0
- package/ARCHITECTURE.md +355 -0
- package/CHANGELOG.md +30 -0
- package/HEADLESS-FLEET-PLAN.md +330 -0
- package/README.md +189 -0
- package/UNIFIED-TREE-PLAN.md +242 -0
- package/bun.lock +288 -0
- package/docs/AGENT-MEMORY-GUIDE.md +214 -0
- package/docs/AGENT-ONBOARDING.md +541 -0
- package/docs/ATTENTION-AND-GATING.md +120 -0
- package/docs/DEPLOYMENTS.md +130 -0
- package/docs/DEV-ENVIRONMENT.md +215 -0
- package/docs/LIBRARY-PIPELINE.md +286 -0
- package/docs/LOCUS-ROUTING-DESIGN.md +115 -0
- package/docs/claudeai-evacuation.md +228 -0
- package/docs/debug-context-api.md +208 -0
- package/docs/webui-deployment.md +219 -0
- package/package.json +33 -0
- package/recipes/SETUP.md +308 -0
- package/recipes/TRIUMVIRATE-SETUP.md +467 -0
- package/recipes/claude-export-revive.json +19 -0
- package/recipes/clerk.json +157 -0
- package/recipes/knowledge-miner.json +174 -0
- package/recipes/knowledge-reviewer.json +76 -0
- package/recipes/mcpl-editor-test.json +38 -0
- package/recipes/prompts/transplant-addendum.md +17 -0
- package/recipes/triumvirate.json +63 -0
- package/recipes/webui-fleet-test.json +27 -0
- package/recipes/webui-test.json +16 -0
- package/recipes/zulip-miner.json +87 -0
- package/scripts/connectome-doctor +373 -0
- package/scripts/evacuator.ts +956 -0
- package/scripts/import-claudeai-export.ts +747 -0
- package/scripts/lib/line-reader.ts +53 -0
- package/scripts/test-historical-thinking.ts +148 -0
- package/scripts/warmup-session.ts +336 -0
- package/src/agent-name.ts +58 -0
- package/src/commands.ts +1074 -0
- package/src/headless.ts +528 -0
- package/src/index.ts +867 -0
- package/src/logging-adapter.ts +208 -0
- package/src/mcpl-config.ts +199 -0
- package/src/modules/activity-module.ts +270 -0
- package/src/modules/channel-mode-module.ts +260 -0
- package/src/modules/fleet-module.ts +1705 -0
- package/src/modules/fleet-types.ts +225 -0
- package/src/modules/lessons-module.ts +465 -0
- package/src/modules/mcpl-admin-module.ts +345 -0
- package/src/modules/retrieval-module.ts +327 -0
- package/src/modules/settings-module.ts +143 -0
- package/src/modules/subagent-module.ts +2074 -0
- package/src/modules/subscription-gc-module.ts +322 -0
- package/src/modules/time-module.ts +85 -0
- package/src/modules/tui-module.ts +76 -0
- package/src/modules/web-ui-curve-page.ts +249 -0
- package/src/modules/web-ui-module.ts +2595 -0
- package/src/recipe.ts +1003 -0
- package/src/session-manager.ts +278 -0
- package/src/state/agent-tree-reducer.ts +431 -0
- package/src/state/fleet-tree-aggregator.ts +195 -0
- package/src/strategies/frontdesk-strategy.ts +364 -0
- package/src/synesthete.ts +68 -0
- package/src/tui.ts +2200 -0
- package/src/types/bun-ffi.d.ts +6 -0
- package/src/web/protocol.ts +648 -0
- package/test/agent-name.test.ts +62 -0
- package/test/agent-tree-fleet-launch.test.ts +64 -0
- package/test/agent-tree-reducer-parity.test.ts +194 -0
- package/test/agent-tree-reducer.test.ts +443 -0
- package/test/agent-tree-rollup.test.ts +109 -0
- package/test/autobio-progress-snapshot.test.ts +40 -0
- package/test/claudeai-export-importer.test.ts +386 -0
- package/test/evacuator.test.ts +332 -0
- package/test/fleet-commands.test.ts +244 -0
- package/test/fleet-no-subfleets.test.ts +147 -0
- package/test/fleet-orchestration.test.ts +353 -0
- package/test/fleet-recipe.test.ts +124 -0
- package/test/fleet-route.test.ts +44 -0
- package/test/fleet-smoke.test.ts +479 -0
- package/test/fleet-subscribe-union-e2e.test.ts +123 -0
- package/test/fleet-subscribe-union.test.ts +85 -0
- package/test/fleet-tree-aggregator-e2e.test.ts +110 -0
- package/test/fleet-tree-aggregator.test.ts +215 -0
- package/test/frontdesk-strategy.test.ts +326 -0
- package/test/headless-describe.test.ts +182 -0
- package/test/headless-smoke.test.ts +190 -0
- package/test/logging-adapter.test.ts +87 -0
- package/test/mcpl-admin-module.test.ts +213 -0
- package/test/mcpl-agent-overlay.test.ts +126 -0
- package/test/mock-headless-child.ts +133 -0
- package/test/recipe-cache-ttl.test.ts +37 -0
- package/test/recipe-env.test.ts +157 -0
- package/test/recipe-path-resolution.test.ts +170 -0
- package/test/subagent-async-timeout.test.ts +381 -0
- package/test/subagent-fork-materialise.test.ts +241 -0
- package/test/subagent-peek-scoping.test.ts +180 -0
- package/test/subagent-peek-zombie.test.ts +148 -0
- package/test/subagent-reaper-in-flight.test.ts +229 -0
- package/test/subscription-gc-module.test.ts +136 -0
- package/test/warmup-handoff.test.ts +150 -0
- package/test/web-ui-bind.test.ts +51 -0
- package/test/web-ui-module.test.ts +246 -0
- package/test/web-ui-protocol.test.ts +0 -0
- package/tsconfig.json +14 -0
- package/web/bun.lock +357 -0
- package/web/index.html +12 -0
- package/web/package.json +24 -0
- package/web/src/App.tsx +1931 -0
- package/web/src/Context.tsx +158 -0
- package/web/src/ContextDocument.tsx +150 -0
- package/web/src/Files.tsx +271 -0
- package/web/src/Lessons.tsx +164 -0
- package/web/src/Mcpl.tsx +310 -0
- package/web/src/Stream.tsx +119 -0
- package/web/src/TreeSidebar.tsx +283 -0
- package/web/src/Usage.tsx +182 -0
- package/web/src/main.tsx +7 -0
- package/web/src/styles.css +26 -0
- package/web/src/tree.ts +268 -0
- package/web/src/wire.ts +120 -0
- package/web/tsconfig.json +21 -0
- package/web/vite.config.ts +32 -0
package/.env.example
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
ANTHROPIC_API_KEY=sk-ant-...
|
|
2
|
+
# MODEL=claude-opus-4-6
|
|
3
|
+
|
|
4
|
+
# --- Recipe ${VAR} substitutions ---------------------------------------
|
|
5
|
+
# Recipes in recipes/ reference these via ${VAR}. Unset = that branch of
|
|
6
|
+
# the recipe fails to load; remove the referencing mcpServers block from
|
|
7
|
+
# the recipe if you don't use the source.
|
|
8
|
+
|
|
9
|
+
# GitLab (knowledge-miner.json: gitlab)
|
|
10
|
+
# GITLAB_TOKEN=glpat-...
|
|
11
|
+
# GITLAB_API_URL=https://gitlab.example.com/api/v4
|
|
12
|
+
|
|
13
|
+
# Notion (knowledge-miner.json: syncntn)
|
|
14
|
+
# NOTION_STORAGE_URL=http://localhost:8000
|
|
15
|
+
# NOTION_WORKSPACE_ID=...
|
|
16
|
+
|
|
17
|
+
# Scribe — audio/video transcription (knowledge-miner.json: scribe)
|
|
18
|
+
# GEMINI_API_KEY=... # REQUIRED if you keep the scribe server (recipe uses bare ${GEMINI_API_KEY}); powers transcription
|
|
19
|
+
# NOTION_API_KEY=... # optional (recipe uses ${NOTION_API_KEY:-}); only scribe--scribe_notion_page needs it
|
|
20
|
+
# SCRIBE_GLOSSARY_URL=... # optional (recipe uses ${SCRIBE_GLOSSARY_URL:-}); unset = transcribe without a glossary
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
name: Build & Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
push:
|
|
6
|
+
tags:
|
|
7
|
+
- 'v*'
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
build-and-test:
|
|
14
|
+
name: Build & Test
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Setup Node.js
|
|
21
|
+
uses: actions/setup-node@v4
|
|
22
|
+
with:
|
|
23
|
+
node-version: 24
|
|
24
|
+
|
|
25
|
+
- name: Install dependencies
|
|
26
|
+
run: npm install
|
|
27
|
+
|
|
28
|
+
- name: Build web assets
|
|
29
|
+
run: npm run build:web
|
|
30
|
+
|
|
31
|
+
- name: Test
|
|
32
|
+
run: npm test
|
|
33
|
+
|
|
34
|
+
publish:
|
|
35
|
+
name: Publish to npm
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
needs: build-and-test
|
|
38
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
39
|
+
|
|
40
|
+
# OIDC trusted publishing: GitHub mints a short-lived id-token, npm CLI
|
|
41
|
+
# exchanges it for a publish credential. No long-lived NPM_TOKEN secret.
|
|
42
|
+
# npm-side config: npmjs.com -> package -> Settings -> Trusted Publishers
|
|
43
|
+
# -> GitHub Actions, matching the repo + this workflow path.
|
|
44
|
+
permissions:
|
|
45
|
+
contents: read
|
|
46
|
+
id-token: write
|
|
47
|
+
|
|
48
|
+
steps:
|
|
49
|
+
- uses: actions/checkout@v4
|
|
50
|
+
|
|
51
|
+
- name: Setup Node.js
|
|
52
|
+
uses: actions/setup-node@v4
|
|
53
|
+
with:
|
|
54
|
+
# node 24 ships npm >= 11.5.1, required for OIDC publishing.
|
|
55
|
+
node-version: 24
|
|
56
|
+
registry-url: https://registry.npmjs.org
|
|
57
|
+
|
|
58
|
+
- name: Install dependencies
|
|
59
|
+
run: npm install
|
|
60
|
+
|
|
61
|
+
- name: Build web assets
|
|
62
|
+
run: npm run build:web
|
|
63
|
+
|
|
64
|
+
- name: Publish
|
|
65
|
+
run: npm publish --access public --provenance
|
package/ARCHITECTURE.md
ADDED
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
# connectome-host
|
|
2
|
+
|
|
3
|
+
A general-purpose agent TUI host with recipe-based configuration. Point it at any use case by loading a recipe — a JSON file that defines the system prompt, MCP servers, modules, and agent settings. Built on the Connectome stack (Agent Framework + Context Manager + Membrane + Chronicle).
|
|
4
|
+
|
|
5
|
+
## Goals
|
|
6
|
+
|
|
7
|
+
1. **Recipe-driven configuration** — a single JSON file defines the entire agent personality: system prompt, model, MCP servers, module toggles, context strategy, session naming hints
|
|
8
|
+
2. **Parallel exploration** — spawn and fork subagents to work on multiple tasks concurrently, with fleet tree view and live peeking
|
|
9
|
+
3. **Semantic memory** — persistent lesson store with confidence scoring, plus LLM-as-retriever pipeline for automatic context injection
|
|
10
|
+
4. **Reversibility** — Chronicle-backed undo/redo, named checkpoints, branch exploration via slash commands
|
|
11
|
+
5. **Session management** — isolated Chronicle stores per session, auto-naming via Haiku
|
|
12
|
+
6. **Dogfood the AF** — stress-test the agent framework's module system, MCPL integration, context strategies, and multi-agent capabilities
|
|
13
|
+
|
|
14
|
+
## Architecture
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
┌──────────────┐
|
|
18
|
+
│ OpenTUI │ ScrollBox, TextRenderable,
|
|
19
|
+
│ (tui.ts) │ InputRenderable, status bar
|
|
20
|
+
└──────┬───────┘
|
|
21
|
+
│ pushEvent('external-message')
|
|
22
|
+
┌──────┴───────┐
|
|
23
|
+
│ TuiModule │ event bridge: TUI → context messages
|
|
24
|
+
└──────┬───────┘
|
|
25
|
+
│
|
|
26
|
+
┌───────────┴───────────┐
|
|
27
|
+
│ Agent Framework │
|
|
28
|
+
│ ┌─────────────────┐ │
|
|
29
|
+
│ │ recipe agent │ │ name, model, prompt from recipe
|
|
30
|
+
│ │ (event loop) │ │
|
|
31
|
+
│ └────────┬────────┘ │
|
|
32
|
+
│ │ │
|
|
33
|
+
│ ┌────────┴────────┐ │
|
|
34
|
+
│ │ Modules │ │ (recipe-toggleable)
|
|
35
|
+
│ │ - subagent │──┼── spawn/fork ephemeral agents
|
|
36
|
+
│ │ - lessons │──┼── CRUD knowledge store (Chronicle)
|
|
37
|
+
│ │ - retrieval │──┼── LLM-as-retriever (Haiku)
|
|
38
|
+
│ │ - workspace │──┼── mount-based filesystem (Chronicle-backed)
|
|
39
|
+
│ │ - tui │ │ (always-on)
|
|
40
|
+
│ └────────┬────────┘ │
|
|
41
|
+
│ │ │
|
|
42
|
+
│ ┌────────┴────────┐ │
|
|
43
|
+
│ │ MCPL Servers │ │ from recipe + mcpl-servers.json
|
|
44
|
+
│ │ (stdio or ws) │──┼── any MCP/MCPL server
|
|
45
|
+
│ └─────────────────┘ │
|
|
46
|
+
└───────────────────────┘
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Core data flow
|
|
50
|
+
|
|
51
|
+
1. User types a message in the TUI
|
|
52
|
+
2. `TuiModule` converts it to a context message + triggers inference
|
|
53
|
+
3. The agent reads the conversation, calls tools (MCPL servers, subagent, lessons, etc.)
|
|
54
|
+
4. Before each inference, `RetrievalModule` and `LessonsModule` inject relevant knowledge via `gatherContext()`
|
|
55
|
+
5. Trace events (`inference:tokens`, `tool:started`, etc.) drive the TUI's streaming display
|
|
56
|
+
|
|
57
|
+
## Project Structure
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
connectome-host/
|
|
61
|
+
src/
|
|
62
|
+
index.ts Entry point, recipe resolution, framework factory
|
|
63
|
+
tui.ts OpenTUI-based terminal interface (@opentui/core)
|
|
64
|
+
commands.ts Slash command handler (Chronicle reversibility, /mcp, /session, etc.)
|
|
65
|
+
recipe.ts Recipe loading, validation, persistence, CLI parsing
|
|
66
|
+
mcpl-config.ts File-driven MCPL server config (mcpl-servers.json)
|
|
67
|
+
session-manager.ts Session index, isolation, migration
|
|
68
|
+
synesthete.ts Auto-naming sessions via Haiku
|
|
69
|
+
modules/
|
|
70
|
+
tui-module.ts Event bridge: external-message → context + inference
|
|
71
|
+
subagent-module.ts Spawn, fork, peek, hud, concurrency, return
|
|
72
|
+
lessons-module.ts Knowledge CRUD + gatherContext injection
|
|
73
|
+
retrieval-module.ts 3-step LLM-as-retriever pipeline
|
|
74
|
+
time-module.ts Session-start timestamp + time:now tool
|
|
75
|
+
strategies/ (reserved for future domain-specific strategies)
|
|
76
|
+
types/
|
|
77
|
+
bun-ffi.d.ts Bun FFI type declarations
|
|
78
|
+
recipes/
|
|
79
|
+
zulip-miner.json Knowledge extraction from Zulip workspaces
|
|
80
|
+
knowledge-miner.json General-purpose knowledge extraction
|
|
81
|
+
mcpl-editor-test.json Collaborative markdown editor testing via WebSocket MCPL
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Components
|
|
85
|
+
|
|
86
|
+
### Recipe System (`recipe.ts`)
|
|
87
|
+
|
|
88
|
+
Recipes are JSON files that configure everything domain-specific. See [README.md](README.md) for the full recipe schema.
|
|
89
|
+
|
|
90
|
+
**Loading precedence**:
|
|
91
|
+
1. CLI argument (`bun src/index.ts recipes/foo.json` or `bun src/index.ts https://...`)
|
|
92
|
+
2. Saved recipe from last run (`data/.recipe.json`)
|
|
93
|
+
3. Built-in default (generic assistant with all modules enabled)
|
|
94
|
+
|
|
95
|
+
**System prompt from URL**: If `agent.systemPrompt` is an HTTP(S) URL (no spaces/newlines), the text is fetched at load time.
|
|
96
|
+
|
|
97
|
+
**MCP server merging**: Recipe servers merge with `mcpl-servers.json`. The file wins on conflict, so `/mcp add` can override recipe defaults.
|
|
98
|
+
|
|
99
|
+
**Transport support**: Recipe MCP servers support both stdio (`command` + `args`) and WebSocket (`url` + `transport: 'websocket'` + optional `token`).
|
|
100
|
+
|
|
101
|
+
### TUI (`tui.ts`)
|
|
102
|
+
|
|
103
|
+
Built on [OpenTUI](https://github.com/anomalyco/opentui) (`@opentui/core`) — the same terminal UI library that powers OpenCode. Requires the Bun runtime.
|
|
104
|
+
|
|
105
|
+
**Layout**:
|
|
106
|
+
```
|
|
107
|
+
┌─────────────────────────────────────────────────────┐
|
|
108
|
+
│ ScrollBoxRenderable (flexGrow, stickyScroll) │
|
|
109
|
+
│ └─ TextRenderable per message/stream chunk │
|
|
110
|
+
├──────────────────────────────────────┬──────────────┤
|
|
111
|
+
│ [✓ idle | tool | N sub] │ 1.2kin 0.5kout│
|
|
112
|
+
├──────────────────────────────────────┴──────────────┤
|
|
113
|
+
│ InputRenderable │
|
|
114
|
+
└─────────────────────────────────────────────────────┘
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
- **Conversation area**: `ScrollBoxRenderable` with `stickyScroll: true` — auto-scrolls as content is added. Each message or tool notification is a `TextRenderable` child node.
|
|
118
|
+
- **Status bar**: Two `TextRenderable` nodes in a `BoxRenderable` with `justifyContent: 'space-between'`. Left side shows agent state, current tool, and subagent count. Right side shows cumulative token usage across the session (all agents).
|
|
119
|
+
- **Input**: `InputRenderable` with `ENTER` event for submitting messages and commands.
|
|
120
|
+
- **Keyboard**: Tab toggles fleet view (subagent tree). Esc interrupts the agent. Ctrl+V toggles verbose mode. Ctrl+B detaches a sync subagent to background. Ctrl+C exits.
|
|
121
|
+
|
|
122
|
+
**Streaming**: Tokens arrive via `inference:tokens` trace events. A plain string buffer tracks accumulated text and assigns the full string to `TextRenderable.content` each time (the `.content` property is a `StyledText` object, not a string — `+=` would break).
|
|
123
|
+
|
|
124
|
+
**Token tracking**: `usage:updated` trace events (from all agents) feed a session-wide counter tracking input tokens, output tokens, cache reads, and cache writes. Displayed compactly: `1.2kin 0.5kout 3.4kcache`.
|
|
125
|
+
|
|
126
|
+
**Dual mode**: If stdout is not a TTY (piped/CI), falls back to a plain readline loop with `waitForInference` promise gating. No OpenTUI dependency on this path.
|
|
127
|
+
|
|
128
|
+
### Subagent Module (`subagent-module.ts`)
|
|
129
|
+
|
|
130
|
+
Enables the agent to delegate work to parallel ephemeral agents.
|
|
131
|
+
|
|
132
|
+
**Tools**:
|
|
133
|
+
| Tool | Behavior |
|
|
134
|
+
|------|----------|
|
|
135
|
+
| `subagent--spawn` | Fresh agent with system prompt + task. Async by default (returns immediately). |
|
|
136
|
+
| `subagent--fork` | Agent inheriting parent's compiled context. Async by default. |
|
|
137
|
+
| `subagent--hud` | Toggle fleet status HUD overlay (injected before each inference). |
|
|
138
|
+
| `subagent--concurrency` | View/adjust concurrency ceiling (auto-adapts to rate limits). |
|
|
139
|
+
| `subagent--peek` | Live state of a running subagent (status, messages, streaming output). |
|
|
140
|
+
| `subagent--return` | Subagent calls this to deliver results back to parent and exit. |
|
|
141
|
+
|
|
142
|
+
**Async by default**: Spawn and fork return immediately; results arrive as messages + inference-request events. Pass `sync: true` to block until completion. Sync tasks are detachable (Ctrl+B or `timeoutMs` auto-detach).
|
|
143
|
+
|
|
144
|
+
**Interaction model** (parallel-async-await): When the LLM emits multiple spawn/fork calls in a single turn, the AF dispatches them concurrently. The parent blocks on `waiting_for_tools` until all results arrive together — natural fan-out without explicit orchestration.
|
|
145
|
+
|
|
146
|
+
**Isolation**: Each ephemeral agent gets its own temporary Chronicle store (temp directory, cleaned up on completion). This prevents message leakage between parent and children.
|
|
147
|
+
|
|
148
|
+
**Depth limiting**: Constructor takes `maxDepth` (default 3). At the depth limit, subagent tools are stripped from the child's tool set.
|
|
149
|
+
|
|
150
|
+
**Concurrency**: Adaptive concurrency control — halves on HTTP 429, recovers after consecutive successes.
|
|
151
|
+
|
|
152
|
+
**Terminology**: "Fork" and "branch" are distinct concepts:
|
|
153
|
+
- **Fork** = spawning a subagent that inherits the parent's compiled messages (agent-level, message copy)
|
|
154
|
+
- **Branch** = Chronicle state branch for undo/redo/checkpointing (storage-level, user-facing)
|
|
155
|
+
|
|
156
|
+
### EventGate
|
|
157
|
+
|
|
158
|
+
MCPL event gating is a core Agent Framework feature. Configuration is file-based (`{storePath}/config/gate.json`) and controlled via `GateOptions` in `FrameworkConfig`. The recipe's `modules.wake` key controls whether gating is enabled and can provide initial policy config.
|
|
159
|
+
|
|
160
|
+
### Workspace Module (from AF)
|
|
161
|
+
|
|
162
|
+
Mount-based filesystem access backed by Chronicle, imported from `@connectome/agent-framework`. Replaces the former `FilesModule` + `LocalFilesModule`.
|
|
163
|
+
|
|
164
|
+
**Default mounts** (when recipe doesn't specify):
|
|
165
|
+
- `input` — read-only, `./input`
|
|
166
|
+
- `products` — read-write, `./output`
|
|
167
|
+
|
|
168
|
+
**Recipe-configurable**: `modules.workspace.mounts` overrides the default mounts. `modules.workspace.configMount: true` adds a special `_config` mount that version-controls gate config via Chronicle.
|
|
169
|
+
|
|
170
|
+
Disabled entirely with `modules.workspace: false` (no filesystem access at all).
|
|
171
|
+
|
|
172
|
+
### Lessons Module (`lessons-module.ts`)
|
|
173
|
+
|
|
174
|
+
Persistent knowledge store backed by Chronicle state snapshots.
|
|
175
|
+
|
|
176
|
+
**Data model**:
|
|
177
|
+
```typescript
|
|
178
|
+
interface Lesson {
|
|
179
|
+
id: string; // Short UUID
|
|
180
|
+
content: string; // The knowledge itself
|
|
181
|
+
confidence: number; // 0.0–1.0
|
|
182
|
+
tags: string[]; // people, process, decision, technical, ...
|
|
183
|
+
evidence: string[]; // Source references (stream:topic:messageId)
|
|
184
|
+
created: number;
|
|
185
|
+
updated: number;
|
|
186
|
+
deprecated: boolean;
|
|
187
|
+
deprecationReason?: string;
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
**Tools**: `create`, `update`, `deprecate`, `query` (text + tags + confidence filter), `list`, `boost`, `demote`.
|
|
192
|
+
|
|
193
|
+
**Confidence dynamics**: `boost` applies diminishing-returns growth (`+0.1 * (1 - c)`); `demote` applies diminishing-returns decay (`-0.1 * c`). Lessons below 0.3 confidence are excluded from context injection.
|
|
194
|
+
|
|
195
|
+
**Context injection**: `gatherContext()` injects the top 10 active lessons (by confidence) as a `## Knowledge Library` block in the system position.
|
|
196
|
+
|
|
197
|
+
### Retrieval Module (`retrieval-module.ts`)
|
|
198
|
+
|
|
199
|
+
Semantic memory lookup using a three-step LLM-as-retriever pipeline. Runs in `gatherContext()` before each main-agent inference.
|
|
200
|
+
|
|
201
|
+
```
|
|
202
|
+
Step 1: Flag concepts Step 2: Keyword query Step 3: Validate
|
|
203
|
+
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
|
|
204
|
+
│ Recent messages │──Haiku──│ Concept keywords │──DB──│ Candidate lessons │──Haiku──│ Relevant only │
|
|
205
|
+
│ → "What concepts │ │ ["RFC", "auth"] │ │ (top 20 by conf.) │ │ (filtered IDs)│
|
|
206
|
+
│ need background │ └──────────────────┘ └──────────────────┘ └───────────────┘
|
|
207
|
+
│ knowledge?" │
|
|
208
|
+
└──────────────────┘
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
- Steps 1 and 3 use Haiku (~$0.001 each)
|
|
212
|
+
- Step 2 is mechanical keyword matching (no LLM call)
|
|
213
|
+
- Results cached by context hash — skips entirely if conversation hasn't changed
|
|
214
|
+
- Fails open: on error, returns empty (never blocks inference)
|
|
215
|
+
- Short-circuits: if only 3 or fewer candidates, skips validation step
|
|
216
|
+
|
|
217
|
+
### Session Manager (`session-manager.ts`)
|
|
218
|
+
|
|
219
|
+
Each session is an isolated Chronicle store under `{dataDir}/sessions/{id}/`. A JSON index (`sessions.json`) tracks metadata.
|
|
220
|
+
|
|
221
|
+
**Features**: create, delete, rename, switch, find (by name or ID prefix), legacy store migration.
|
|
222
|
+
|
|
223
|
+
### Synesthete (`synesthete.ts`)
|
|
224
|
+
|
|
225
|
+
Auto-generates session names via a Haiku call after the 3rd user message. Produces 2–4 word names. Recipe can provide naming examples to steer the style.
|
|
226
|
+
|
|
227
|
+
### Slash Commands (`commands.ts`)
|
|
228
|
+
|
|
229
|
+
| Command | Effect |
|
|
230
|
+
|---------|--------|
|
|
231
|
+
| `/help` | List all commands |
|
|
232
|
+
| `/quit`, `/q` | Exit |
|
|
233
|
+
| `/status` | Agent state, branch, queue depth |
|
|
234
|
+
| `/clear` | Clear conversation display |
|
|
235
|
+
| `/lessons` | Show lesson library sorted by confidence |
|
|
236
|
+
| `/undo` | Branch at the message before the last agent turn, switch to it |
|
|
237
|
+
| `/redo` | Pop from redo stack, switch back |
|
|
238
|
+
| `/checkpoint <name>` | Save `(branchId, branchName)` as named point |
|
|
239
|
+
| `/restore <name>` | Switch to checkpoint's branch |
|
|
240
|
+
| `/branches` | List all Chronicle branches with head positions |
|
|
241
|
+
| `/checkout <name>` | Switch to named branch |
|
|
242
|
+
| `/history` | Show last 20 messages in summary form |
|
|
243
|
+
| `/mcp list` | List MCPL servers from `mcpl-servers.json` |
|
|
244
|
+
| `/mcp add <id> <cmd> [args...]` | Add or overwrite a server |
|
|
245
|
+
| `/mcp remove <id>` | Remove a server |
|
|
246
|
+
| `/mcp env <id> KEY=VALUE [...]` | Set env vars on a server |
|
|
247
|
+
| `/budget [tokens]` | Show/set stream token budget (e.g. `/budget 150k`, `/budget 1m`) |
|
|
248
|
+
| `/session` | Show current session |
|
|
249
|
+
| `/session list` | List all sessions |
|
|
250
|
+
| `/session new [name]` | Create and switch to new session |
|
|
251
|
+
| `/session switch <name>` | Switch to session (by name or ID) |
|
|
252
|
+
| `/session rename <name>` | Rename current session |
|
|
253
|
+
| `/session delete <name>` | Delete a session |
|
|
254
|
+
| `/recipe` | Show current recipe info |
|
|
255
|
+
| `/newtopic [context]` | Reset head window (auto-summarize or with user context) |
|
|
256
|
+
| `/usage` | Show session token usage and cost breakdown |
|
|
257
|
+
|
|
258
|
+
## Framework Integration
|
|
259
|
+
|
|
260
|
+
The app runs on the `mcpl-first-class` branch of the Agent Framework, which embeds MCPL server management directly in the framework core.
|
|
261
|
+
|
|
262
|
+
**Key AF extensions used**:
|
|
263
|
+
- `createEphemeralAgent()` — creates an agent + context manager with an isolated temp Chronicle store; returns a cleanup function
|
|
264
|
+
- `runEphemeralToCompletion()` — temporarily registers an ephemeral agent in the framework's agent map, triggers inference through the normal event loop (full trace events, logging, tool dispatch), resolves when the agent returns to idle
|
|
265
|
+
- `executeToolCall()` — routes tool calls to module registry or MCPL servers (used by subagents to access tools)
|
|
266
|
+
- `KnowledgeStrategy` — context strategy used for subagent fork/spawn context (from `@connectome/agent-framework`)
|
|
267
|
+
|
|
268
|
+
**Configuration** is recipe-driven — see `createFramework()` in `index.ts`. The framework factory:
|
|
269
|
+
1. Builds the module list based on recipe toggles (subagent, lessons, retrieval, workspace)
|
|
270
|
+
2. Merges recipe MCP servers with `mcpl-servers.json` (file wins)
|
|
271
|
+
3. Configures EventGate via `GateOptions` (file-based, per-session)
|
|
272
|
+
4. Selects context strategy from recipe (`autobiographical` or `passthrough`, defaults to autobiographical)
|
|
273
|
+
|
|
274
|
+
## Environment
|
|
275
|
+
|
|
276
|
+
```
|
|
277
|
+
ANTHROPIC_API_KEY Required. API key for Membrane.
|
|
278
|
+
MODEL Override model for the main agent. Default: from recipe or claude-opus-4-6
|
|
279
|
+
DATA_DIR Data directory for sessions and recipes. Default: ./data
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
## Runtime
|
|
283
|
+
|
|
284
|
+
**Bun** (not Node.js). OpenTUI's native Zig core requires Bun. Chronicle's N-API bindings are validated under Bun (56 tests in `bun-compat/`).
|
|
285
|
+
|
|
286
|
+
## Running
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
# Interactive TUI (requires TTY)
|
|
290
|
+
bun src/index.ts
|
|
291
|
+
|
|
292
|
+
# Load a recipe
|
|
293
|
+
bun src/index.ts recipes/zulip-miner.json
|
|
294
|
+
|
|
295
|
+
# Piped mode (CI / testing)
|
|
296
|
+
echo -e "/help\n/status\n/quit" | bun src/index.ts
|
|
297
|
+
|
|
298
|
+
# Dev mode with watch
|
|
299
|
+
bun --watch src/index.ts
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
## Dependencies
|
|
303
|
+
|
|
304
|
+
| Package | Source |
|
|
305
|
+
|---------|--------|
|
|
306
|
+
| `@connectome/agent-framework` | `../agent-framework` (local) |
|
|
307
|
+
| `@connectome/context-manager` | `../context-manager` (local) |
|
|
308
|
+
| `chronicle` | `../chronicle` (Rust + N-API bindings, local) |
|
|
309
|
+
| `membrane` | `../membrane` (local) |
|
|
310
|
+
| `@opentui/core` | npm (native Zig terminal UI, powers OpenCode) |
|
|
311
|
+
|
|
312
|
+
## Roadmap
|
|
313
|
+
|
|
314
|
+
### 1. TUI rework for branch operations
|
|
315
|
+
The TUI is imperative (OpenTUI) and builds display state incrementally from trace events. After a Chronicle branch switch (undo/redo/checkpoint restore), the display stays stale — it doesn't re-query the store. Needs:
|
|
316
|
+
- A `refreshFromStore()` path that clears the conversation view and reloads from `queryMessages()` without tearing down the framework
|
|
317
|
+
- Called after any branch operation (`/undo`, `/redo`, `/restore`, `/branch switch`)
|
|
318
|
+
- Preserve branch-independent state (view mode, expanded nodes, layout) while rebuilding message display
|
|
319
|
+
|
|
320
|
+
### 2. Hierarchical compression in AutobiographicalStrategy
|
|
321
|
+
The context-manager's `AutobiographicalStrategy` currently does single-level compression (raw → diary). Upgrade to moltbot-style 3-level pyramid:
|
|
322
|
+
- **Merge logic in `tick()`**: when N unmerged summaries accumulate at level K, merge into one at level K+1
|
|
323
|
+
- **Anti-redundancy in `select()`**: exclude a summary if all its children are expanded at the level below
|
|
324
|
+
- **Budget carryover**: unused token budget at higher levels flows down (L3 → L2 → L1)
|
|
325
|
+
- **Self-voice framing**: summaries injected as assistant messages (the model's own recollections), not Q&A pairs
|
|
326
|
+
- **Source range tracking**: each compressed chunk records which message sequences it covers (Chronicle is lossless, but we need the mapping)
|
|
327
|
+
|
|
328
|
+
### 3. Domain-specific context strategies
|
|
329
|
+
Recipe-aware compression strategies that understand domain semantics. For example, a knowledge extraction strategy that prioritizes lesson-relevant messages, research leads, and synthesis differently from generic conversation. Builds on top of the hierarchical compression work.
|
|
330
|
+
|
|
331
|
+
### 4. Undo/redo at the framework level
|
|
332
|
+
Currently each app builds its own undo/redo on top of Chronicle branching. Should be a first-class framework feature:
|
|
333
|
+
- Auto-record the Chronicle sequence number before each inference turn
|
|
334
|
+
- Expose `undoLastTurn(agentName)` / `redo()` on `AgentFramework`
|
|
335
|
+
- Branch at the recorded sequence, switch to the new branch
|
|
336
|
+
- Emit trace events so TUI/UI layers know to refresh
|
|
337
|
+
|
|
338
|
+
### 5. MCPL integration depth
|
|
339
|
+
connectome-host has config-level MCPL support and wake subscriptions, but deeper integration is needed:
|
|
340
|
+
- Visibility into MCPL server status and activity in the TUI
|
|
341
|
+
- MCPL-triggered inference distinguished from user-triggered in the conversation view
|
|
342
|
+
- Interaction model for how MCPL-pushed content appears and is handled
|
|
343
|
+
|
|
344
|
+
## TUI Evolution
|
|
345
|
+
|
|
346
|
+
1. **Ink/React** — first attempt, clunky rendering, interleaved output
|
|
347
|
+
2. **Custom ANSI** — raw escape sequences, cursor tracking; fixed interleave but letters disappeared during typing
|
|
348
|
+
3. **OpenTUI** — production-quality terminal rendering (Zig core), handles cursor/input/scroll natively
|
|
349
|
+
|
|
350
|
+
## Gotchas
|
|
351
|
+
|
|
352
|
+
- **`TextRenderable.content` is a `StyledText` object**, not a string. Using `+=` silently breaks (stringifies as `[object Object]`). Always track text in a plain string buffer and assign the full string via `=`.
|
|
353
|
+
- **Bun auto-loads `.env`** — no `dotenv` package needed.
|
|
354
|
+
- **`child_process.spawn`** works in Bun (needed for MCPL server connections).
|
|
355
|
+
- **Tool name separator**: module tools use `--` separator (e.g. `subagent--fork`, `wake--subscribe`), not `:`.
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
### Breaking (recipe authors only)
|
|
6
|
+
|
|
7
|
+
- `modules.fleet.children[].recipe` paths now resolve at recipe-load time
|
|
8
|
+
against the **directory of the parent recipe file** (or URL base) rather
|
|
9
|
+
than `process.cwd()`. Absolute paths and `http(s)://` URLs pass through
|
|
10
|
+
unchanged. This makes recipe bundles portable: a parent file and its
|
|
11
|
+
sibling children can live anywhere on disk and be launched from any CWD.
|
|
12
|
+
|
|
13
|
+
**Who needs to act**: anyone maintaining a forked or custom
|
|
14
|
+
triumvirate-style recipe that hard-codes child paths with a `recipes/`
|
|
15
|
+
prefix (or any prefix anchored at `connectome-host/`'s CWD). After
|
|
16
|
+
upgrade, `"recipes/knowledge-miner.json"` inside
|
|
17
|
+
`<somewhere>/my-recipe.json` resolves to
|
|
18
|
+
`<somewhere>/recipes/knowledge-miner.json`, which is almost certainly
|
|
19
|
+
not what's intended.
|
|
20
|
+
|
|
21
|
+
**Migration**: drop the `recipes/` prefix so the child is referenced as a
|
|
22
|
+
sibling of the parent file (e.g. `"knowledge-miner.json"` or
|
|
23
|
+
`"./knowledge-miner.json"`). No files need to move on disk. The
|
|
24
|
+
in-tree `recipes/triumvirate.json` has already been updated.
|
|
25
|
+
|
|
26
|
+
**Unchanged**: `dataDir`, workspace mount paths, and child process CWD
|
|
27
|
+
stay CWD-relative (these are runtime paths, not authoring references).
|
|
28
|
+
`fleet--launch` invocations from the conductor are still matched
|
|
29
|
+
CWD-relative at dispatch time, so existing system prompts that document
|
|
30
|
+
CWD-relative paths continue to work.
|