bonecode 1.1.0 → 1.2.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 +145 -9
- package/bin/bonecode +47 -42
- package/compat/opencode_adapter.ts +188 -17
- package/dist/bone/output/agent/src/algorithms.d.ts +1 -0
- package/dist/bone/output/agent/src/algorithms.js +3 -0
- package/dist/bone/output/agent/src/algorithms.js.map +1 -0
- package/dist/bone/output/agent/src/audit.d.ts +3 -0
- package/dist/bone/output/agent/src/audit.js +40 -0
- package/dist/bone/output/agent/src/audit.js.map +1 -0
- package/dist/bone/output/agent/src/auth.d.ts +8 -0
- package/dist/bone/output/agent/src/auth.js +56 -0
- package/dist/bone/output/agent/src/auth.js.map +1 -0
- package/dist/bone/output/agent/src/db.d.ts +6 -0
- package/dist/bone/output/agent/src/db.js +63 -0
- package/dist/bone/output/agent/src/db.js.map +1 -0
- package/dist/bone/output/agent/src/events.d.ts +25 -0
- package/dist/bone/output/agent/src/events.js +184 -0
- package/dist/bone/output/agent/src/events.js.map +1 -0
- package/dist/bone/output/agent/src/logger.d.ts +28 -0
- package/dist/bone/output/agent/src/logger.js +45 -0
- package/dist/bone/output/agent/src/logger.js.map +1 -0
- package/dist/bone/output/agent/src/metrics.d.ts +5 -0
- package/dist/bone/output/agent/src/metrics.js +60 -0
- package/dist/bone/output/agent/src/metrics.js.map +1 -0
- package/dist/bone/output/agent/src/routes/agent_instance.d.ts +1 -0
- package/dist/bone/output/agent/src/routes/agent_instance.js +253 -0
- package/dist/bone/output/agent/src/routes/agent_instance.js.map +1 -0
- package/dist/bone/output/agent/src/routes/build_step.d.ts +1 -0
- package/dist/bone/output/agent/src/routes/build_step.js +133 -0
- package/dist/bone/output/agent/src/routes/build_step.js.map +1 -0
- package/dist/bone/output/agent/src/routes/plan.d.ts +1 -0
- package/dist/bone/output/agent/src/routes/plan.js +119 -0
- package/dist/bone/output/agent/src/routes/plan.js.map +1 -0
- package/dist/bone/output/agent/src/routes/task.d.ts +1 -0
- package/dist/bone/output/agent/src/routes/task.js +133 -0
- package/dist/bone/output/agent/src/routes/task.js.map +1 -0
- package/dist/bone/output/agent/src/routes/tool_call.d.ts +1 -0
- package/dist/bone/output/agent/src/routes/tool_call.js +190 -0
- package/dist/bone/output/agent/src/routes/tool_call.js.map +1 -0
- package/dist/bone/output/agent/src/state_machines/agent_instance.d.ts +9 -0
- package/dist/bone/output/agent/src/state_machines/agent_instance.js +22 -0
- package/dist/bone/output/agent/src/state_machines/agent_instance.js.map +1 -0
- package/dist/bone/output/agent/src/state_machines/build_step.d.ts +9 -0
- package/dist/bone/output/agent/src/state_machines/build_step.js +20 -0
- package/dist/bone/output/agent/src/state_machines/build_step.js.map +1 -0
- package/dist/bone/output/agent/src/state_machines/plan.d.ts +9 -0
- package/dist/bone/output/agent/src/state_machines/plan.js +20 -0
- package/dist/bone/output/agent/src/state_machines/plan.js.map +1 -0
- package/dist/bone/output/agent/src/state_machines/task.d.ts +9 -0
- package/dist/bone/output/agent/src/state_machines/task.js +20 -0
- package/dist/bone/output/agent/src/state_machines/task.js.map +1 -0
- package/dist/bone/output/agent/src/state_machines/tool_call.d.ts +9 -0
- package/dist/bone/output/agent/src/state_machines/tool_call.js +20 -0
- package/dist/bone/output/agent/src/state_machines/tool_call.js.map +1 -0
- package/dist/bone/output/rag/src/algorithms.d.ts +1 -0
- package/dist/bone/output/rag/src/algorithms.js +3 -0
- package/dist/bone/output/rag/src/algorithms.js.map +1 -0
- package/dist/bone/output/rag/src/auth.d.ts +8 -0
- package/dist/bone/output/rag/src/auth.js +56 -0
- package/dist/bone/output/rag/src/auth.js.map +1 -0
- package/dist/bone/output/rag/src/db.d.ts +6 -0
- package/dist/bone/output/rag/src/db.js +63 -0
- package/dist/bone/output/rag/src/db.js.map +1 -0
- package/dist/bone/output/rag/src/events.d.ts +25 -0
- package/dist/bone/output/rag/src/events.js +184 -0
- package/dist/bone/output/rag/src/events.js.map +1 -0
- package/dist/bone/output/rag/src/extensions.d.ts +83 -0
- package/dist/bone/output/rag/src/extensions.js +329 -0
- package/dist/bone/output/rag/src/extensions.js.map +1 -0
- package/dist/bone/output/rag/src/flows.d.ts +24 -0
- package/dist/bone/output/rag/src/flows.js +236 -0
- package/dist/bone/output/rag/src/flows.js.map +1 -0
- package/dist/bone/output/rag/src/logger.d.ts +28 -0
- package/dist/bone/output/rag/src/logger.js +45 -0
- package/dist/bone/output/rag/src/logger.js.map +1 -0
- package/dist/bone/output/rag/src/metrics.d.ts +5 -0
- package/dist/bone/output/rag/src/metrics.js +60 -0
- package/dist/bone/output/rag/src/metrics.js.map +1 -0
- package/dist/bone/output/rag/src/routes/code_chunk.d.ts +1 -0
- package/dist/bone/output/rag/src/routes/code_chunk.js +100 -0
- package/dist/bone/output/rag/src/routes/code_chunk.js.map +1 -0
- package/dist/bone/output/rag/src/routes/code_file.d.ts +1 -0
- package/dist/bone/output/rag/src/routes/code_file.js +127 -0
- package/dist/bone/output/rag/src/routes/code_file.js.map +1 -0
- package/dist/bone/output/rag/src/routes/indexing_job.d.ts +1 -0
- package/dist/bone/output/rag/src/routes/indexing_job.js +113 -0
- package/dist/bone/output/rag/src/routes/indexing_job.js.map +1 -0
- package/dist/bone/output/rag/src/routes/knowledge_base.d.ts +1 -0
- package/dist/bone/output/rag/src/routes/knowledge_base.js +242 -0
- package/dist/bone/output/rag/src/routes/knowledge_base.js.map +1 -0
- package/dist/bone/output/rag/src/routes/memory_entry.d.ts +1 -0
- package/dist/bone/output/rag/src/routes/memory_entry.js +113 -0
- package/dist/bone/output/rag/src/routes/memory_entry.js.map +1 -0
- package/dist/bone/output/rag/src/state_machines/code_file.d.ts +9 -0
- package/dist/bone/output/rag/src/state_machines/code_file.js +21 -0
- package/dist/bone/output/rag/src/state_machines/code_file.js.map +1 -0
- package/dist/bone/output/rag/src/state_machines/indexing_job.d.ts +9 -0
- package/dist/bone/output/rag/src/state_machines/indexing_job.js +20 -0
- package/dist/bone/output/rag/src/state_machines/indexing_job.js.map +1 -0
- package/dist/bone/output/rag/src/state_machines/knowledge_base.d.ts +9 -0
- package/dist/bone/output/rag/src/state_machines/knowledge_base.js +21 -0
- package/dist/bone/output/rag/src/state_machines/knowledge_base.js.map +1 -0
- package/dist/bone/output/rag/src/state_machines/memory_entry.d.ts +9 -0
- package/dist/bone/output/rag/src/state_machines/memory_entry.js +18 -0
- package/dist/bone/output/rag/src/state_machines/memory_entry.js.map +1 -0
- package/dist/bone/output/session/src/algorithms.d.ts +1 -0
- package/dist/bone/output/session/src/algorithms.js +3 -0
- package/dist/bone/output/session/src/algorithms.js.map +1 -0
- package/dist/bone/output/session/src/audit.d.ts +3 -0
- package/dist/bone/output/session/src/audit.js +40 -0
- package/dist/bone/output/session/src/audit.js.map +1 -0
- package/dist/bone/output/session/src/auth.d.ts +8 -0
- package/dist/bone/output/session/src/auth.js +56 -0
- package/dist/bone/output/session/src/auth.js.map +1 -0
- package/dist/bone/output/session/src/db.d.ts +6 -0
- package/dist/bone/output/session/src/db.js +63 -0
- package/dist/bone/output/session/src/db.js.map +1 -0
- package/dist/bone/output/session/src/events.d.ts +26 -0
- package/dist/bone/output/session/src/events.js +212 -0
- package/dist/bone/output/session/src/events.js.map +1 -0
- package/dist/bone/output/session/src/extensions.d.ts +41 -0
- package/dist/bone/output/session/src/extensions.js +217 -0
- package/dist/bone/output/session/src/extensions.js.map +1 -0
- package/dist/bone/output/session/src/logger.d.ts +28 -0
- package/dist/bone/output/session/src/logger.js +44 -0
- package/dist/bone/output/session/src/logger.js.map +1 -0
- package/dist/bone/output/session/src/metrics.d.ts +5 -0
- package/dist/bone/output/session/src/metrics.js +60 -0
- package/dist/bone/output/session/src/metrics.js.map +1 -0
- package/dist/bone/output/session/src/routes/message.d.ts +1 -0
- package/dist/bone/output/session/src/routes/message.js +120 -0
- package/dist/bone/output/session/src/routes/message.js.map +1 -0
- package/dist/bone/output/session/src/routes/part.d.ts +1 -0
- package/dist/bone/output/session/src/routes/part.js +106 -0
- package/dist/bone/output/session/src/routes/part.js.map +1 -0
- package/dist/bone/output/session/src/routes/permission.d.ts +1 -0
- package/dist/bone/output/session/src/routes/permission.js +106 -0
- package/dist/bone/output/session/src/routes/permission.js.map +1 -0
- package/dist/bone/output/session/src/routes/project.d.ts +1 -0
- package/dist/bone/output/session/src/routes/project.js +106 -0
- package/dist/bone/output/session/src/routes/project.js.map +1 -0
- package/dist/bone/output/session/src/routes/session.d.ts +1 -0
- package/dist/bone/output/session/src/routes/session.js +308 -0
- package/dist/bone/output/session/src/routes/session.js.map +1 -0
- package/dist/bone/output/session/src/state_machines/session.d.ts +9 -0
- package/dist/bone/output/session/src/state_machines/session.js +21 -0
- package/dist/bone/output/session/src/state_machines/session.js.map +1 -0
- package/dist/bone/output/session/src/websocket.d.ts +15 -0
- package/dist/bone/output/session/src/websocket.js +215 -0
- package/dist/bone/output/session/src/websocket.js.map +1 -0
- package/dist/bone/output/workspace/src/algorithms.d.ts +1 -0
- package/dist/bone/output/workspace/src/algorithms.js +3 -0
- package/dist/bone/output/workspace/src/algorithms.js.map +1 -0
- package/dist/bone/output/workspace/src/auth.d.ts +8 -0
- package/dist/bone/output/workspace/src/auth.js +56 -0
- package/dist/bone/output/workspace/src/auth.js.map +1 -0
- package/dist/bone/output/workspace/src/db.d.ts +6 -0
- package/dist/bone/output/workspace/src/db.js +63 -0
- package/dist/bone/output/workspace/src/db.js.map +1 -0
- package/dist/bone/output/workspace/src/events.d.ts +25 -0
- package/dist/bone/output/workspace/src/events.js +184 -0
- package/dist/bone/output/workspace/src/events.js.map +1 -0
- package/dist/bone/output/workspace/src/logger.d.ts +28 -0
- package/dist/bone/output/workspace/src/logger.js +45 -0
- package/dist/bone/output/workspace/src/logger.js.map +1 -0
- package/dist/bone/output/workspace/src/metrics.d.ts +5 -0
- package/dist/bone/output/workspace/src/metrics.js +60 -0
- package/dist/bone/output/workspace/src/metrics.js.map +1 -0
- package/dist/bone/output/workspace/src/routes/codebase.d.ts +1 -0
- package/dist/bone/output/workspace/src/routes/codebase.js +113 -0
- package/dist/bone/output/workspace/src/routes/codebase.js.map +1 -0
- package/dist/bone/output/workspace/src/routes/snapshot.d.ts +1 -0
- package/dist/bone/output/workspace/src/routes/snapshot.js +151 -0
- package/dist/bone/output/workspace/src/routes/snapshot.js.map +1 -0
- package/dist/bone/output/workspace/src/routes/workspace.d.ts +1 -0
- package/dist/bone/output/workspace/src/routes/workspace.js +209 -0
- package/dist/bone/output/workspace/src/routes/workspace.js.map +1 -0
- package/dist/bone/output/workspace/src/state_machines/codebase.d.ts +9 -0
- package/dist/bone/output/workspace/src/state_machines/codebase.js +19 -0
- package/dist/bone/output/workspace/src/state_machines/codebase.js.map +1 -0
- package/dist/bone/output/workspace/src/state_machines/snapshot.d.ts +9 -0
- package/dist/bone/output/workspace/src/state_machines/snapshot.js +18 -0
- package/dist/bone/output/workspace/src/state_machines/snapshot.js.map +1 -0
- package/dist/bone/output/workspace/src/state_machines/workspace.d.ts +9 -0
- package/dist/bone/output/workspace/src/state_machines/workspace.js +19 -0
- package/dist/bone/output/workspace/src/state_machines/workspace.js.map +1 -0
- package/dist/compat/opencode_adapter.d.ts +25 -0
- package/dist/compat/opencode_adapter.js +599 -0
- package/dist/compat/opencode_adapter.js.map +1 -0
- package/dist/extensions/chunker.d.ts +24 -0
- package/dist/extensions/chunker.js +360 -0
- package/dist/extensions/chunker.js.map +1 -0
- package/dist/extensions/embedding_provider.d.ts +18 -0
- package/dist/extensions/embedding_provider.js +150 -0
- package/dist/extensions/embedding_provider.js.map +1 -0
- package/dist/extensions/llm_provider.d.ts +33 -0
- package/dist/extensions/llm_provider.js +338 -0
- package/dist/extensions/llm_provider.js.map +1 -0
- package/dist/extensions/mcp_bridge.d.ts +44 -0
- package/dist/extensions/mcp_bridge.js +151 -0
- package/dist/extensions/mcp_bridge.js.map +1 -0
- package/dist/extensions/rag_search.d.ts +38 -0
- package/dist/extensions/rag_search.js +242 -0
- package/dist/extensions/rag_search.js.map +1 -0
- package/dist/extensions/snapshot.d.ts +14 -0
- package/dist/extensions/snapshot.js +158 -0
- package/dist/extensions/snapshot.js.map +1 -0
- package/dist/extensions/tool_executor.d.ts +28 -0
- package/dist/extensions/tool_executor.js +268 -0
- package/dist/extensions/tool_executor.js.map +1 -0
- package/dist/src/cli.d.ts +15 -0
- package/dist/src/cli.js +687 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/config.d.ts +44 -0
- package/dist/src/config.js +165 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/context_builder.d.ts +51 -0
- package/dist/src/context_builder.js +558 -0
- package/dist/src/context_builder.js.map +1 -0
- package/dist/src/db_adapter.d.ts +24 -0
- package/dist/src/db_adapter.js +341 -0
- package/dist/src/db_adapter.js.map +1 -0
- package/dist/src/engine/session/compaction_logic.d.ts +11 -0
- package/dist/src/engine/session/compaction_logic.js +113 -0
- package/dist/src/engine/session/compaction_logic.js.map +1 -0
- package/dist/src/engine/session/instruction_loader.d.ts +5 -0
- package/dist/src/engine/session/instruction_loader.js +78 -0
- package/dist/src/engine/session/instruction_loader.js.map +1 -0
- package/dist/src/engine/session/overflow_check.d.ts +14 -0
- package/dist/src/engine/session/overflow_check.js +45 -0
- package/dist/src/engine/session/overflow_check.js.map +1 -0
- package/dist/src/engine/session/prompt.d.ts +45 -0
- package/dist/src/engine/session/prompt.js +584 -0
- package/dist/src/engine/session/prompt.js.map +1 -0
- package/dist/src/engine/session/provider_transform.d.ts +59 -0
- package/dist/src/engine/session/provider_transform.js +193 -0
- package/dist/src/engine/session/provider_transform.js.map +1 -0
- package/dist/src/engine/session/retry_logic.d.ts +12 -0
- package/dist/src/engine/session/retry_logic.js +72 -0
- package/dist/src/engine/session/retry_logic.js.map +1 -0
- package/dist/src/engine/session/system_prompt.d.ts +9 -0
- package/dist/src/engine/session/system_prompt.js +96 -0
- package/dist/src/engine/session/system_prompt.js.map +1 -0
- package/dist/src/engine/session/tool_registry.d.ts +5 -0
- package/dist/src/engine/session/tool_registry.js +117 -0
- package/dist/src/engine/session/tool_registry.js.map +1 -0
- package/dist/src/export.d.ts +13 -0
- package/dist/src/export.js +103 -0
- package/dist/src/export.js.map +1 -0
- package/dist/src/mdns.d.ts +7 -0
- package/dist/src/mdns.js +60 -0
- package/dist/src/mdns.js.map +1 -0
- package/dist/src/rag_worker.d.ts +38 -0
- package/dist/src/rag_worker.js +435 -0
- package/dist/src/rag_worker.js.map +1 -0
- package/dist/src/server.d.ts +11 -0
- package/dist/src/server.js +214 -0
- package/dist/src/server.js.map +1 -0
- package/dist/src/stats.d.ts +45 -0
- package/dist/src/stats.js +233 -0
- package/dist/src/stats.js.map +1 -0
- package/dist/src/tui.d.ts +29 -0
- package/dist/src/tui.js +1053 -0
- package/dist/src/tui.js.map +1 -0
- package/package.json +7 -4
- package/src/cli.ts +247 -5
- package/src/export.ts +122 -0
- package/src/mdns.ts +53 -0
- package/src/server.ts +32 -0
- package/src/stats.ts +290 -0
- package/src/tui.ts +749 -248
package/README.md
CHANGED
|
@@ -11,27 +11,90 @@
|
|
|
11
11
|
npm install -g bonecode
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
Then
|
|
14
|
+
Then run it from any project directory:
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
17
|
bonecode
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Interfaces
|
|
23
|
+
|
|
24
|
+
BoneCode ships three ways to interact with the agent.
|
|
25
|
+
|
|
26
|
+
### Terminal UI (default)
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
bonecode
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Opens an interactive terminal session in the current directory. Type `/` to see all available commands.
|
|
33
|
+
|
|
34
|
+
| Key | Action |
|
|
35
|
+
|-----|--------|
|
|
36
|
+
| `/` | Show command menu (arrow keys to navigate, Enter/Tab to select) |
|
|
37
|
+
| `Ctrl+C` | Interrupt the current agent request |
|
|
38
|
+
| `Ctrl+D` | Exit |
|
|
39
|
+
| `↑ / ↓` | Scroll through prompt history |
|
|
40
|
+
| `@<path>` | Attach a file (Tab to autocomplete) |
|
|
41
|
+
|
|
42
|
+
### Web UI
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
bonecode web
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Starts the server and opens the web interface in your browser at `http://localhost:3000/ui`.
|
|
49
|
+
|
|
50
|
+
If you already have the server running separately (`bonecode serve`), just navigate to:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
http://localhost:3000/ui
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Build the web UI for production** (optional — the server serves it automatically after building):
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
cd web && npm install && npm run build
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The built assets are served from `/ui`. Without a build, the server serves the raw source files in dev mode — functional but without bundling.
|
|
63
|
+
|
|
64
|
+
**Run the web UI in hot-reload dev mode** (separate terminal):
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
cd web && npm install && npm run dev
|
|
68
|
+
# Opens at http://localhost:5173 with proxy to the BoneCode server
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Headless server
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
bonecode serve
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Starts the API server only (no TUI, no browser). Useful for CI, Docker, or connecting your own client.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
20
81
|
## Database modes
|
|
21
82
|
|
|
22
|
-
BoneCode automatically detects what's available
|
|
83
|
+
BoneCode automatically detects what's available:
|
|
23
84
|
|
|
24
85
|
| Mode | Setup required | Features |
|
|
25
86
|
|------|---------------|----------|
|
|
26
87
|
| **PostgreSQL** (full) | Docker | Sessions + agents + **pgvector RAG** + hybrid search + durable events |
|
|
27
88
|
| **SQLite** (basic) | Nothing | Sessions + agents only — no RAG, no vector search |
|
|
28
89
|
|
|
29
|
-
|
|
90
|
+
No Docker? BoneCode falls back to SQLite automatically — fully working agent, just without codebase indexing.
|
|
30
91
|
|
|
31
|
-
|
|
92
|
+
Want the full experience? Install Docker and run `bonecode` — it starts Postgres automatically on first run.
|
|
32
93
|
|
|
33
94
|
> Install Docker: https://docs.docker.com/get-docker/
|
|
34
95
|
|
|
96
|
+
---
|
|
97
|
+
|
|
35
98
|
## Configuration
|
|
36
99
|
|
|
37
100
|
Copy `.env.example` to `.env` and set your LLM provider:
|
|
@@ -50,14 +113,77 @@ OPENAI_API_KEY=not-needed
|
|
|
50
113
|
MODEL_SUPPORTS_TOOLS=false
|
|
51
114
|
```
|
|
52
115
|
|
|
53
|
-
For cloud providers
|
|
116
|
+
For cloud providers just set the API key — no base URL needed:
|
|
117
|
+
|
|
118
|
+
```env
|
|
119
|
+
# Anthropic
|
|
120
|
+
ANTHROPIC_API_KEY=sk-ant-...
|
|
121
|
+
DEFAULT_PROVIDER=anthropic
|
|
122
|
+
DEFAULT_MODEL=claude-sonnet-4-5
|
|
123
|
+
|
|
124
|
+
# OpenAI
|
|
125
|
+
OPENAI_API_KEY=sk-...
|
|
126
|
+
DEFAULT_PROVIDER=openai
|
|
127
|
+
DEFAULT_MODEL=gpt-4o
|
|
128
|
+
|
|
129
|
+
# Google
|
|
130
|
+
GOOGLE_API_KEY=...
|
|
131
|
+
DEFAULT_PROVIDER=google
|
|
132
|
+
DEFAULT_MODEL=gemini-2.0-flash
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## CLI commands
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
bonecode Start server + open TUI
|
|
141
|
+
bonecode serve Start headless server only
|
|
142
|
+
bonecode web Start server + open web UI in browser
|
|
143
|
+
bonecode run "fix the bug" Send a one-shot prompt
|
|
144
|
+
bonecode run -i Interactive terminal mode (no TUI)
|
|
145
|
+
bonecode stats Show token usage and cost statistics
|
|
146
|
+
bonecode export [id] Export a session as JSON
|
|
147
|
+
bonecode pr <number> Checkout a GitHub PR branch
|
|
148
|
+
bonecode github install Show GitHub Actions agent setup
|
|
149
|
+
bonecode compile Recompile .bone domain models
|
|
150
|
+
bonecode migrate Run database migrations
|
|
151
|
+
bonecode status Check if server is running
|
|
152
|
+
bonecode --version Show version
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Stats
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
bonecode stats # all-time usage
|
|
159
|
+
bonecode stats --days 7 # last 7 days
|
|
160
|
+
bonecode stats --models 5 # show top 5 models
|
|
161
|
+
bonecode stats --tools # show tool usage breakdown
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Export
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
bonecode export # export most recent session
|
|
168
|
+
bonecode export <session-id> # export specific session
|
|
169
|
+
bonecode export --sanitize # redact file paths, tool outputs, etc.
|
|
170
|
+
bonecode export > session.json # pipe to file
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
54
174
|
|
|
55
175
|
## What's different from OpenCode
|
|
56
176
|
|
|
57
|
-
- **BoneScript backend** —
|
|
58
|
-
- **pgvector RAG** —
|
|
59
|
-
- **
|
|
60
|
-
- **
|
|
177
|
+
- **BoneScript backend** — domain models declared in `.bone` files, compiled to Express + state machines + saga flows + durable events
|
|
178
|
+
- **pgvector RAG** — hybrid search (vector + BM25 + RRF fusion), works without an embedding model using structural context
|
|
179
|
+
- **Web UI** — browser interface at `/ui` in addition to the TUI
|
|
180
|
+
- **mDNS discovery** — server announces itself as `bonecode.local` on the local network
|
|
181
|
+
- **Cursor pagination** — v2 session and message APIs support bidirectional keyset pagination
|
|
182
|
+
- **Subagent spawning** — `POST /v2/session/:id/subagent` creates and runs a child session
|
|
183
|
+
- **Single command** — `bonecode` starts everything in one process
|
|
184
|
+
- **SQLite fallback** — works out of the box without Docker
|
|
185
|
+
|
|
186
|
+
---
|
|
61
187
|
|
|
62
188
|
## Architecture
|
|
63
189
|
|
|
@@ -77,8 +203,18 @@ BoneCode/
|
|
|
77
203
|
│ ├── cli.ts # bonecode CLI entry point
|
|
78
204
|
│ ├── tui.ts # Interactive terminal UI
|
|
79
205
|
│ ├── server.ts # Express server (auto Postgres/SQLite)
|
|
206
|
+
│ ├── mdns.ts # mDNS/Bonjour local network discovery
|
|
207
|
+
│ ├── stats.ts # Token/cost statistics
|
|
208
|
+
│ ├── export.ts # Session export with PII redaction
|
|
80
209
|
│ ├── db_adapter.ts # Database detection + SQLite shim
|
|
81
210
|
│ └── engine/ # Agent loop, tools, context builder
|
|
211
|
+
├── web/ # Web UI (vanilla TypeScript + Vite)
|
|
212
|
+
│ ├── index.html
|
|
213
|
+
│ ├── src/
|
|
214
|
+
│ │ ├── main.ts # Entry point
|
|
215
|
+
│ │ ├── app.ts # Main app class
|
|
216
|
+
│ │ └── api.ts # API client
|
|
217
|
+
│ └── vite.config.ts # Dev server with proxy to :3000
|
|
82
218
|
├── compat/
|
|
83
219
|
│ └── opencode_adapter.ts # OpenCode v2 API compatibility layer
|
|
84
220
|
└── extensions/ # Custom extension points (embeddings, chunking, etc.)
|
package/bin/bonecode
CHANGED
|
@@ -1,62 +1,67 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// Resolves and runs the CLI via ts-node (dev) or compiled JS (prod).
|
|
2
|
+
"use strict";
|
|
4
3
|
|
|
5
4
|
const path = require("path");
|
|
6
5
|
const { spawnSync } = require("child_process");
|
|
7
6
|
const fs = require("fs");
|
|
8
|
-
const os = require("os");
|
|
9
7
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
// Resolve the package root (two levels up from bin/)
|
|
13
|
-
const scriptPath = fs.realpathSync(__filename);
|
|
14
|
-
const pkgRoot = path.dirname(path.dirname(scriptPath));
|
|
8
|
+
// Resolve package root (one level up from bin/)
|
|
9
|
+
const pkgRoot = path.dirname(path.dirname(fs.realpathSync(__filename)));
|
|
15
10
|
|
|
11
|
+
// Prefer compiled JS — always built by `npm run build`
|
|
16
12
|
const cliJs = path.join(pkgRoot, "dist", "src", "cli.js");
|
|
17
|
-
|
|
13
|
+
if (fs.existsSync(cliJs)) {
|
|
14
|
+
const result = spawnSync(process.execPath, [cliJs, ...process.argv.slice(2)], {
|
|
15
|
+
stdio: "inherit",
|
|
16
|
+
cwd: process.cwd(),
|
|
17
|
+
env: process.env,
|
|
18
|
+
});
|
|
19
|
+
process.exit(result.status ?? 0);
|
|
20
|
+
}
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
// Dev fallback: try tsx (works without compilation, no .cmd issues)
|
|
23
|
+
const cliTs = path.join(pkgRoot, "src", "cli.ts");
|
|
24
|
+
if (!fs.existsSync(cliTs)) {
|
|
25
|
+
console.error("BoneCode: CLI entry point not found.");
|
|
26
|
+
console.error(" Run `npm run build` inside the BoneCode directory first.");
|
|
27
|
+
process.exit(1);
|
|
25
28
|
}
|
|
26
29
|
|
|
27
|
-
|
|
28
|
-
|
|
30
|
+
// Find tsx in local node_modules
|
|
31
|
+
const tsxLocal = path.join(pkgRoot, "node_modules", ".bin", "tsx");
|
|
32
|
+
const tsxLocalCmd = tsxLocal + (process.platform === "win32" ? ".cmd" : "");
|
|
33
|
+
|
|
34
|
+
if (fs.existsSync(tsxLocalCmd)) {
|
|
35
|
+
const result = spawnSync(tsxLocalCmd, [cliTs, ...process.argv.slice(2)], {
|
|
29
36
|
stdio: "inherit",
|
|
30
37
|
cwd: process.cwd(),
|
|
31
38
|
env: process.env,
|
|
32
|
-
shell:
|
|
39
|
+
shell: process.platform === "win32",
|
|
33
40
|
});
|
|
34
|
-
|
|
35
|
-
if (result.error) {
|
|
36
|
-
// If the command failed (e.g. .cmd not found), try with shell: true
|
|
37
|
-
const result2 = spawnSync(cmd, args, {
|
|
38
|
-
stdio: "inherit",
|
|
39
|
-
cwd: process.cwd(),
|
|
40
|
-
env: process.env,
|
|
41
|
-
shell: true,
|
|
42
|
-
});
|
|
43
|
-
process.exit(result2.status ?? 0);
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
41
|
process.exit(result.status ?? 0);
|
|
48
42
|
}
|
|
49
43
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
console.error("BoneCode: could not find CLI entry point.");
|
|
60
|
-
console.error(" Run `npm run build` to compile, or ensure ts-node is installed.");
|
|
44
|
+
// Last resort: npx tsx (downloads on first run)
|
|
45
|
+
console.error("BoneCode: compiled JS not found. Building now...");
|
|
46
|
+
const build = spawnSync(
|
|
47
|
+
process.platform === "win32" ? "npm.cmd" : "npm",
|
|
48
|
+
["run", "build"],
|
|
49
|
+
{ stdio: "inherit", cwd: pkgRoot, shell: process.platform === "win32" }
|
|
50
|
+
);
|
|
51
|
+
if (build.status !== 0) {
|
|
52
|
+
console.error("Build failed. Run `npm run build` manually in the BoneCode directory.");
|
|
61
53
|
process.exit(1);
|
|
62
54
|
}
|
|
55
|
+
|
|
56
|
+
// Retry with compiled JS
|
|
57
|
+
if (fs.existsSync(cliJs)) {
|
|
58
|
+
const result = spawnSync(process.execPath, [cliJs, ...process.argv.slice(2)], {
|
|
59
|
+
stdio: "inherit",
|
|
60
|
+
cwd: process.cwd(),
|
|
61
|
+
env: process.env,
|
|
62
|
+
});
|
|
63
|
+
process.exit(result.status ?? 0);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
console.error("Build succeeded but CLI not found at:", cliJs);
|
|
67
|
+
process.exit(1);
|
|
@@ -11,7 +11,9 @@
|
|
|
11
11
|
* GET /v2/session/:id → get session
|
|
12
12
|
* DELETE /v2/session/:id → delete_session
|
|
13
13
|
* POST /v2/session/:id/prompt → run_agent_turn (streaming SSE)
|
|
14
|
-
*
|
|
14
|
+
* POST /v2/session/:id/cancel → cancel in-flight agent turn
|
|
15
|
+
* POST /v2/session/:id/subagent → spawn child session
|
|
16
|
+
* GET /v2/session/:id/message → list messages (cursor pagination)
|
|
15
17
|
* GET /v2/session/:id/message/:msgId → get message
|
|
16
18
|
* GET /v2/event → SSE event stream (global)
|
|
17
19
|
* GET /v2/provider → list providers
|
|
@@ -86,10 +88,12 @@ compatRouter.post("/v2/session", async (req: Request, res: Response) => {
|
|
|
86
88
|
}
|
|
87
89
|
});
|
|
88
90
|
|
|
89
|
-
// GET /v2/session — list sessions
|
|
91
|
+
// GET /v2/session — list sessions (with optional cursor pagination)
|
|
90
92
|
compatRouter.get("/v2/session", async (req: Request, res: Response) => {
|
|
91
93
|
try {
|
|
92
|
-
const { projectID, directory, search } = req.query;
|
|
94
|
+
const { projectID, directory, search, cursor, limit: limitStr, direction = "next", roots } = req.query;
|
|
95
|
+
const limit = Math.min(parseInt(String(limitStr || "100")), 200);
|
|
96
|
+
|
|
93
97
|
let sql = `SELECT * FROM sessions WHERE state != 'deleted'`;
|
|
94
98
|
const params: unknown[] = [];
|
|
95
99
|
let idx = 1;
|
|
@@ -97,11 +101,43 @@ compatRouter.get("/v2/session", async (req: Request, res: Response) => {
|
|
|
97
101
|
if (projectID) { sql += ` AND project_id = $${idx++}`; params.push(projectID); }
|
|
98
102
|
if (directory) { sql += ` AND directory = $${idx++}`; params.push(directory); }
|
|
99
103
|
if (search) { sql += ` AND title ILIKE $${idx++}`; params.push(`%${search}%`); }
|
|
104
|
+
if (roots === "true") { sql += ` AND parent_id IS NULL`; }
|
|
105
|
+
|
|
106
|
+
// Cursor-based keyset pagination (opencode v2 pattern)
|
|
107
|
+
if (cursor) {
|
|
108
|
+
try {
|
|
109
|
+
const decoded = JSON.parse(Buffer.from(String(cursor), "base64url").toString("utf8"));
|
|
110
|
+
const { id, time } = decoded;
|
|
111
|
+
if (direction === "next") {
|
|
112
|
+
sql += ` AND (updated_at < $${idx++} OR (updated_at = $${idx++} AND id < $${idx++}))`;
|
|
113
|
+
params.push(new Date(time), new Date(time), id);
|
|
114
|
+
idx += 2; // already incremented above
|
|
115
|
+
} else {
|
|
116
|
+
sql += ` AND (updated_at > $${idx++} OR (updated_at = $${idx++} AND id > $${idx++}))`;
|
|
117
|
+
params.push(new Date(time), new Date(time), id);
|
|
118
|
+
idx += 2;
|
|
119
|
+
}
|
|
120
|
+
} catch {}
|
|
121
|
+
}
|
|
100
122
|
|
|
101
|
-
|
|
123
|
+
const orderDir = direction === "previous" ? "ASC" : "DESC";
|
|
124
|
+
sql += ` ORDER BY updated_at ${orderDir}, id ${orderDir} LIMIT $${idx++}`;
|
|
125
|
+
params.push(limit + 1); // fetch one extra to detect "more"
|
|
102
126
|
|
|
103
127
|
const result = await pool.query(sql, params);
|
|
104
|
-
|
|
128
|
+
const rows = result.rows;
|
|
129
|
+
const more = rows.length > limit;
|
|
130
|
+
const slice = more ? rows.slice(0, limit) : rows;
|
|
131
|
+
const items = direction === "previous" ? slice.reverse() : slice;
|
|
132
|
+
|
|
133
|
+
const nextCursor = more && slice.length > 0
|
|
134
|
+
? Buffer.from(JSON.stringify({
|
|
135
|
+
id: slice[slice.length - 1].id,
|
|
136
|
+
time: new Date(slice[slice.length - 1].updated_at).getTime(),
|
|
137
|
+
})).toString("base64url")
|
|
138
|
+
: undefined;
|
|
139
|
+
|
|
140
|
+
res.json(items.map(toOpenCodeSession));
|
|
105
141
|
} catch (e: any) {
|
|
106
142
|
res.status(500).json({ error: { code: "LIST_FAILED", message: e.message } });
|
|
107
143
|
}
|
|
@@ -128,6 +164,35 @@ compatRouter.delete("/v2/session/:id", async (req: Request, res: Response) => {
|
|
|
128
164
|
}
|
|
129
165
|
});
|
|
130
166
|
|
|
167
|
+
// POST /v2/session/:id/cancel — cancel an in-flight agent turn
|
|
168
|
+
compatRouter.post("/v2/session/:id/cancel", async (req: Request, res: Response) => {
|
|
169
|
+
const session_id = req.params.id;
|
|
170
|
+
try {
|
|
171
|
+
// Mark any running agents as cancelled
|
|
172
|
+
await pool.query(
|
|
173
|
+
`UPDATE agent_instances SET state = 'cancelled', updated_at = NOW()
|
|
174
|
+
WHERE session_id = $1 AND state IN ('running', 'waiting_for_tool', 'compacting')`,
|
|
175
|
+
[session_id]
|
|
176
|
+
);
|
|
177
|
+
// Move session back to active so the user can keep working
|
|
178
|
+
await pool.query(
|
|
179
|
+
`UPDATE sessions SET state = 'active', updated_at = NOW()
|
|
180
|
+
WHERE id = $1 AND state IN ('busy', 'compacting')`,
|
|
181
|
+
[session_id]
|
|
182
|
+
);
|
|
183
|
+
// Notify subscribers
|
|
184
|
+
await eventBus.publish("AgentFailed", {
|
|
185
|
+
agent_id: "",
|
|
186
|
+
session_id,
|
|
187
|
+
error: "cancelled by user",
|
|
188
|
+
failed_at: new Date().toISOString(),
|
|
189
|
+
}, "CompatAdapter");
|
|
190
|
+
res.json({ ok: true });
|
|
191
|
+
} catch (e: any) {
|
|
192
|
+
res.status(500).json({ error: { code: "CANCEL_FAILED", message: e.message } });
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
|
|
131
196
|
// POST /v2/session/:id/prompt — run agent turn (streaming SSE)
|
|
132
197
|
compatRouter.post("/v2/session/:id/prompt", requireAuth, async (req: Request, res: Response) => {
|
|
133
198
|
const session_id = req.params.id;
|
|
@@ -211,24 +276,109 @@ compatRouter.post("/v2/session/:id/prompt", requireAuth, async (req: Request, re
|
|
|
211
276
|
}
|
|
212
277
|
});
|
|
213
278
|
|
|
214
|
-
// GET /v2/session/:id/message — list messages
|
|
279
|
+
// GET /v2/session/:id/message — list messages (with cursor pagination)
|
|
215
280
|
compatRouter.get("/v2/session/:id/message", async (req: Request, res: Response) => {
|
|
216
281
|
try {
|
|
217
|
-
const
|
|
218
|
-
|
|
282
|
+
const { cursor, limit: limitStr, direction = "next" } = req.query;
|
|
283
|
+
const limit = Math.min(parseInt(String(limitStr || "200")), 500);
|
|
284
|
+
|
|
285
|
+
let sql = `SELECT m.*, json_agg(p.* ORDER BY p.order_index) FILTER (WHERE p.id IS NOT NULL) as parts
|
|
219
286
|
FROM messages m
|
|
220
287
|
LEFT JOIN parts p ON p.message_id = m.id
|
|
221
|
-
WHERE m.session_id = $1
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
)
|
|
226
|
-
|
|
288
|
+
WHERE m.session_id = $1`;
|
|
289
|
+
const params: unknown[] = [req.params.id];
|
|
290
|
+
let idx = 2;
|
|
291
|
+
|
|
292
|
+
if (cursor) {
|
|
293
|
+
try {
|
|
294
|
+
const decoded = JSON.parse(Buffer.from(String(cursor), "base64url").toString("utf8"));
|
|
295
|
+
const { id, time } = decoded;
|
|
296
|
+
if (direction === "next") {
|
|
297
|
+
sql += ` AND (m.created_at < $${idx++} OR (m.created_at = $${idx++} AND m.id < $${idx++}))`;
|
|
298
|
+
params.push(new Date(time), new Date(time), id);
|
|
299
|
+
idx += 2;
|
|
300
|
+
} else {
|
|
301
|
+
sql += ` AND (m.created_at > $${idx++} OR (m.created_at = $${idx++} AND m.id > $${idx++}))`;
|
|
302
|
+
params.push(new Date(time), new Date(time), id);
|
|
303
|
+
idx += 2;
|
|
304
|
+
}
|
|
305
|
+
} catch {}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const orderDir = direction === "previous" ? "ASC" : "DESC";
|
|
309
|
+
sql += ` GROUP BY m.id ORDER BY m.created_at ${orderDir}, m.id ${orderDir} LIMIT $${idx++}`;
|
|
310
|
+
params.push(limit + 1);
|
|
311
|
+
|
|
312
|
+
const result = await pool.query(sql, params);
|
|
313
|
+
const rows = result.rows;
|
|
314
|
+
const more = rows.length > limit;
|
|
315
|
+
const slice = more ? rows.slice(0, limit) : rows;
|
|
316
|
+
const items = direction === "previous" ? slice.reverse() : slice;
|
|
317
|
+
|
|
318
|
+
const nextCursor = more && slice.length > 0
|
|
319
|
+
? Buffer.from(JSON.stringify({
|
|
320
|
+
id: slice[slice.length - 1].id,
|
|
321
|
+
time: new Date(slice[slice.length - 1].created_at).getTime(),
|
|
322
|
+
})).toString("base64url")
|
|
323
|
+
: undefined;
|
|
324
|
+
|
|
325
|
+
res.json(items.map(toOpenCodeMessage));
|
|
227
326
|
} catch (e: any) {
|
|
228
327
|
res.status(500).json({ error: { code: "DB_ERROR", message: e.message } });
|
|
229
328
|
}
|
|
230
329
|
});
|
|
231
330
|
|
|
331
|
+
// POST /v2/session/:id/subagent — spawn a child session and run it
|
|
332
|
+
compatRouter.post("/v2/session/:parentId/subagent", requireAuth, async (req: Request, res: Response) => {
|
|
333
|
+
try {
|
|
334
|
+
const { prompt, agent = "build", modelID, providerID } = req.body;
|
|
335
|
+
if (!prompt) return res.status(400).json({ error: { code: "MISSING_PROMPT", message: "prompt is required" } });
|
|
336
|
+
|
|
337
|
+
const parentId = req.params.parentId;
|
|
338
|
+
const parentResult = await pool.query(`SELECT * FROM sessions WHERE id = $1`, [parentId]);
|
|
339
|
+
if (!parentResult.rows[0]) return res.status(404).json({ error: { code: "NOT_FOUND", message: "Parent session not found" } });
|
|
340
|
+
const parent = parentResult.rows[0];
|
|
341
|
+
|
|
342
|
+
// Create child session
|
|
343
|
+
const childId = require("uuid").v4();
|
|
344
|
+
const slug = `subagent-${Date.now()}`;
|
|
345
|
+
await pool.query(
|
|
346
|
+
`INSERT INTO sessions (id, slug, project_id, parent_id, directory, title, version, state)
|
|
347
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, 'created')`,
|
|
348
|
+
[childId, slug, parent.project_id, parentId, parent.directory, `Subagent: ${prompt.slice(0, 60)}`, "1.0.0"]
|
|
349
|
+
);
|
|
350
|
+
|
|
351
|
+
// Add user message
|
|
352
|
+
const msgId = require("uuid").v4();
|
|
353
|
+
await pool.query(
|
|
354
|
+
`INSERT INTO messages (id, session_id, role) VALUES ($1, $2, 'user')`,
|
|
355
|
+
[msgId, childId]
|
|
356
|
+
);
|
|
357
|
+
const partId = require("uuid").v4();
|
|
358
|
+
await pool.query(
|
|
359
|
+
`INSERT INTO parts (id, message_id, session_id, part_type, data, order_index) VALUES ($1, $2, $3, 'text', $4, 0)`,
|
|
360
|
+
[partId, msgId, childId, JSON.stringify({ text: prompt })]
|
|
361
|
+
);
|
|
362
|
+
|
|
363
|
+
// Run agent asynchronously
|
|
364
|
+
const { runAgentLoop } = await import("../src/engine/session/prompt");
|
|
365
|
+
runAgentLoop({
|
|
366
|
+
session_id: childId,
|
|
367
|
+
message_id: msgId,
|
|
368
|
+
content: prompt,
|
|
369
|
+
model_id: modelID || process.env.DEFAULT_MODEL || "claude-sonnet-4-5",
|
|
370
|
+
provider_id: providerID || process.env.DEFAULT_PROVIDER || "anthropic",
|
|
371
|
+
agent_name: agent,
|
|
372
|
+
}).catch((e: any) => {
|
|
373
|
+
console.error(`[Subagent] Failed for session ${childId}:`, e.message);
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
res.status(202).json({ childSessionId: childId, status: "running" });
|
|
377
|
+
} catch (e: any) {
|
|
378
|
+
res.status(500).json({ error: { code: "SUBAGENT_FAILED", message: e.message } });
|
|
379
|
+
}
|
|
380
|
+
});
|
|
381
|
+
|
|
232
382
|
// ─── Global SSE Event Stream ──────────────────────────────────────────────────
|
|
233
383
|
|
|
234
384
|
// GET /v2/event — global SSE stream for all events
|
|
@@ -458,16 +608,35 @@ function subscribeToSessionEvents(
|
|
|
458
608
|
): () => void {
|
|
459
609
|
const handler = async (event: any) => {
|
|
460
610
|
if (event.payload?.session_id === session_id) {
|
|
461
|
-
|
|
611
|
+
// Pass through key tool fields directly so SSE listeners can render them
|
|
612
|
+
const payload: any = { ...event.payload };
|
|
613
|
+
if (event.type === "ToolCallRequested") {
|
|
614
|
+
payload.tool_call_id = event.payload.tool_call_id;
|
|
615
|
+
payload.tool_name = event.payload.tool_name;
|
|
616
|
+
payload.tool_input = event.payload.tool_input;
|
|
617
|
+
}
|
|
618
|
+
if (event.type === "ToolCallCompleted") {
|
|
619
|
+
payload.tool_call_id = event.payload.tool_call_id;
|
|
620
|
+
payload.tool_name = event.payload.tool_name;
|
|
621
|
+
payload.duration_ms = event.payload.duration_ms;
|
|
622
|
+
}
|
|
623
|
+
callback({ type: mapEventType(event.type), data: payload });
|
|
462
624
|
}
|
|
463
625
|
};
|
|
464
626
|
|
|
465
|
-
const types = [
|
|
627
|
+
const types = [
|
|
628
|
+
"PartUpdated",
|
|
629
|
+
"MessageAdded",
|
|
630
|
+
"AgentCompleted",
|
|
631
|
+
"AgentFailed",
|
|
632
|
+
"ToolCallRequested",
|
|
633
|
+
"ToolCallCompleted",
|
|
634
|
+
"SessionCompacted",
|
|
635
|
+
];
|
|
466
636
|
for (const type of types) {
|
|
467
637
|
eventBus.subscribe(type, handler);
|
|
468
638
|
}
|
|
469
639
|
|
|
470
|
-
// Return a real cleanup function that removes all registered handlers
|
|
471
640
|
return () => {
|
|
472
641
|
for (const type of types) {
|
|
473
642
|
eventBus.unsubscribe(type, handler);
|
|
@@ -482,6 +651,8 @@ function mapEventType(boneEventType: string): string {
|
|
|
482
651
|
AgentCompleted: "session.updated",
|
|
483
652
|
AgentFailed: "session.updated",
|
|
484
653
|
ToolCallRequested: "tool.requested",
|
|
654
|
+
ToolCallCompleted: "tool.completed",
|
|
655
|
+
SessionCompacted: "session.compacted",
|
|
485
656
|
};
|
|
486
657
|
return map[boneEventType] || boneEventType.toLowerCase();
|
|
487
658
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"algorithms.js","sourceRoot":"","sources":["../../../../../bone/output/agent/src/algorithms.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from "express";
|
|
2
|
+
export declare function auditLog(action: string, entityType?: string): (req: Request, _res: Response, next: NextFunction) => Promise<void>;
|
|
3
|
+
export declare function getAuditLog(entityType: string, entityId: string): Promise<any[]>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Generated by BoneScript compiler.
|
|
3
|
+
// Audit middleware for: AgentDomain v1.0.0
|
|
4
|
+
//
|
|
5
|
+
// Modules requiring audit logging:
|
|
6
|
+
// - AgentInstanceService
|
|
7
|
+
// - TaskService
|
|
8
|
+
// - PlanService
|
|
9
|
+
// - BuildStepService
|
|
10
|
+
// - ToolCallService
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.getAuditLog = exports.auditLog = void 0;
|
|
13
|
+
const db_1 = require("./db");
|
|
14
|
+
function auditLog(action, entityType) {
|
|
15
|
+
return async (req, _res, next) => {
|
|
16
|
+
try {
|
|
17
|
+
const auth = req.auth;
|
|
18
|
+
const actorId = auth?.actor_id ?? null;
|
|
19
|
+
const entityId = req.params.id ?? req.body?.id ?? null;
|
|
20
|
+
const payload = req.body ?? null;
|
|
21
|
+
const ipAddress = req.ip ?? null;
|
|
22
|
+
const userAgent = req.headers["user-agent"] ?? null;
|
|
23
|
+
await (0, db_1.query)(`INSERT INTO audit_log
|
|
24
|
+
(actor_id, action, entity_type, entity_id, payload, ip_address, user_agent)
|
|
25
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7)`, [actorId, action, entityType ?? null, entityId, JSON.stringify(payload), ipAddress, userAgent]);
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
// Audit failures must not block the request — log and continue
|
|
29
|
+
console.error("[audit] Failed to write audit log:", err);
|
|
30
|
+
}
|
|
31
|
+
next();
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
exports.auditLog = auditLog;
|
|
35
|
+
async function getAuditLog(entityType, entityId) {
|
|
36
|
+
const result = await (0, db_1.query)("SELECT * FROM audit_log WHERE entity_type = $1 AND entity_id = $2 ORDER BY created_at DESC LIMIT 100", [entityType, entityId]);
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
exports.getAuditLog = getAuditLog;
|
|
40
|
+
//# sourceMappingURL=audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../../../../bone/output/agent/src/audit.ts"],"names":[],"mappings":";AAAA,oCAAoC;AACpC,2CAA2C;AAC3C,EAAE;AACF,mCAAmC;AACnC,2BAA2B;AAC3B,kBAAkB;AAClB,kBAAkB;AAClB,uBAAuB;AACvB,sBAAsB;;;AAGtB,6BAA6B;AAE7B,SAAgB,QAAQ,CAAC,MAAc,EAAE,UAAmB;IAC1D,OAAO,KAAK,EAAE,GAAY,EAAE,IAAc,EAAE,IAAkB,EAAiB,EAAE;QAC/E,IAAI,CAAC;YACH,MAAM,IAAI,GAAI,GAAW,CAAC,IAAgD,CAAC;YAC3E,MAAM,OAAO,GAAG,IAAI,EAAE,QAAQ,IAAI,IAAI,CAAC;YACvC,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,IAAK,GAAG,CAAC,IAAgC,EAAE,EAAE,IAAI,IAAI,CAAC;YACpF,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC;YACjC,MAAM,SAAS,GAAG,GAAG,CAAC,EAAE,IAAI,IAAI,CAAC;YACjC,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,IAAI,CAAC;YAEpD,MAAM,IAAA,UAAK,EACT;;8CAEsC,EACtC,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,IAAI,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,SAAS,CAAC,CAC/F,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,+DAA+D;YAC/D,OAAO,CAAC,KAAK,CAAC,oCAAoC,EAAE,GAAG,CAAC,CAAC;QAC3D,CAAC;QACD,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;AACJ,CAAC;AAtBD,4BAsBC;AAEM,KAAK,UAAU,WAAW,CAAC,UAAkB,EAAE,QAAgB;IACpE,MAAM,MAAM,GAAG,MAAM,IAAA,UAAK,EACxB,sGAAsG,EACtG,CAAC,UAAU,EAAE,QAAQ,CAAC,CACvB,CAAC;IACF,OAAO,MAAM,CAAC;AAChB,CAAC;AAND,kCAMC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from "express";
|
|
2
|
+
export interface AuthContext {
|
|
3
|
+
authenticated: boolean;
|
|
4
|
+
actor_id: string | null;
|
|
5
|
+
trace_id: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function authMiddleware(req: Request, res: Response, next: NextFunction): void;
|
|
8
|
+
export declare function requireAuth(req: Request, res: Response, next: NextFunction): void;
|