@decibelsystems/tools 2.1.2 → 2.1.4
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 +144 -63
- package/dist/agentCommands.d.ts +11 -0
- package/dist/agentCommands.d.ts.map +1 -0
- package/dist/agentCommands.js +267 -0
- package/dist/agentCommands.js.map +1 -0
- package/dist/agentInbox.d.ts +37 -0
- package/dist/agentInbox.d.ts.map +1 -0
- package/dist/agentInbox.js +128 -0
- package/dist/agentInbox.js.map +1 -0
- package/dist/agentPresence.d.ts +36 -0
- package/dist/agentPresence.d.ts.map +1 -0
- package/dist/agentPresence.js +227 -0
- package/dist/agentPresence.js.map +1 -0
- package/dist/agenticJobs.d.ts +49 -0
- package/dist/agenticJobs.d.ts.map +1 -0
- package/dist/agenticJobs.js +190 -0
- package/dist/agenticJobs.js.map +1 -0
- package/dist/architectAdrs.d.ts +7 -0
- package/dist/architectAdrs.d.ts.map +1 -1
- package/dist/architectAdrs.js +91 -28
- package/dist/architectAdrs.js.map +1 -1
- package/dist/daemon.d.ts +6 -0
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +14 -0
- package/dist/daemon.js.map +1 -1
- package/dist/facades/definitions.d.ts.map +1 -1
- package/dist/facades/definitions.js +40 -6
- package/dist/facades/definitions.js.map +1 -1
- package/dist/hq/defineAgent.d.ts +11 -0
- package/dist/hq/defineAgent.d.ts.map +1 -0
- package/dist/hq/defineAgent.js +185 -0
- package/dist/hq/defineAgent.js.map +1 -0
- package/dist/hq/index.d.ts +3 -0
- package/dist/hq/index.d.ts.map +1 -0
- package/dist/hq/index.js +28 -0
- package/dist/hq/index.js.map +1 -0
- package/dist/hq/types.d.ts +59 -0
- package/dist/hq/types.d.ts.map +1 -0
- package/dist/hq/types.js +12 -0
- package/dist/hq/types.js.map +1 -0
- package/dist/httpServer.d.ts +1 -1
- package/dist/httpServer.d.ts.map +1 -1
- package/dist/httpServer.js +327 -19
- package/dist/httpServer.js.map +1 -1
- package/dist/kernel.d.ts +3 -1
- package/dist/kernel.d.ts.map +1 -1
- package/dist/kernel.js +40 -9
- package/dist/kernel.js.map +1 -1
- package/dist/projectRegistry.d.ts +27 -0
- package/dist/projectRegistry.d.ts.map +1 -1
- package/dist/projectRegistry.js +191 -5
- package/dist/projectRegistry.js.map +1 -1
- package/dist/sentinelIssues.d.ts +5 -0
- package/dist/sentinelIssues.d.ts.map +1 -1
- package/dist/sentinelIssues.js +1 -1
- package/dist/sentinelIssues.js.map +1 -1
- package/dist/server.js +12 -0
- package/dist/server.js.map +1 -1
- package/dist/store/fsStore.d.ts +6 -0
- package/dist/store/fsStore.d.ts.map +1 -0
- package/dist/store/fsStore.js +77 -0
- package/dist/store/fsStore.js.map +1 -0
- package/dist/store/index.d.ts +8 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/index.js +23 -0
- package/dist/store/index.js.map +1 -0
- package/dist/store/markdown.d.ts +21 -0
- package/dist/store/markdown.d.ts.map +1 -0
- package/dist/store/markdown.js +175 -0
- package/dist/store/markdown.js.map +1 -0
- package/dist/store/supabaseStore.d.ts +6 -0
- package/dist/store/supabaseStore.d.ts.map +1 -0
- package/dist/store/supabaseStore.js +152 -0
- package/dist/store/supabaseStore.js.map +1 -0
- package/dist/store/types.d.ts +49 -0
- package/dist/store/types.d.ts.map +1 -0
- package/dist/store/types.js +11 -0
- package/dist/store/types.js.map +1 -0
- package/dist/supabaseRetry.d.ts +21 -0
- package/dist/supabaseRetry.d.ts.map +1 -0
- package/dist/supabaseRetry.js +72 -0
- package/dist/supabaseRetry.js.map +1 -0
- package/dist/toolConfig.d.ts +49 -0
- package/dist/toolConfig.d.ts.map +1 -0
- package/dist/toolConfig.js +309 -0
- package/dist/toolConfig.js.map +1 -0
- package/dist/tools/agentic/agentQueue.d.ts.map +1 -1
- package/dist/tools/agentic/agentQueue.js +7 -5
- package/dist/tools/agentic/agentQueue.js.map +1 -1
- package/dist/tools/agentic/index.d.ts +3 -0
- package/dist/tools/agentic/index.d.ts.map +1 -1
- package/dist/tools/agentic/index.js +158 -1
- package/dist/tools/agentic/index.js.map +1 -1
- package/dist/tools/codereview/index.d.ts +4 -0
- package/dist/tools/codereview/index.d.ts.map +1 -0
- package/dist/tools/codereview/index.js +93 -0
- package/dist/tools/codereview/index.js.map +1 -0
- package/dist/tools/codereview.d.ts +56 -0
- package/dist/tools/codereview.d.ts.map +1 -0
- package/dist/tools/codereview.js +304 -0
- package/dist/tools/codereview.js.map +1 -0
- package/dist/tools/concepts.d.ts +38 -0
- package/dist/tools/concepts.d.ts.map +1 -0
- package/dist/tools/concepts.js +283 -0
- package/dist/tools/concepts.js.map +1 -0
- package/dist/tools/corpus/index.d.ts +3 -0
- package/dist/tools/corpus/index.d.ts.map +1 -1
- package/dist/tools/corpus/index.js +183 -1
- package/dist/tools/corpus/index.js.map +1 -1
- package/dist/tools/corpus.d.ts +52 -0
- package/dist/tools/corpus.d.ts.map +1 -1
- package/dist/tools/corpus.js +207 -2
- package/dist/tools/corpus.js.map +1 -1
- package/dist/tools/dojo.d.ts.map +1 -1
- package/dist/tools/dojo.js +11 -1
- package/dist/tools/dojo.js.map +1 -1
- package/dist/tools/git-sentinel.d.ts.map +1 -1
- package/dist/tools/git-sentinel.js +24 -8
- package/dist/tools/git-sentinel.js.map +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +6 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/oracle.d.ts +2 -0
- package/dist/tools/oracle.d.ts.map +1 -1
- package/dist/tools/oracle.js +146 -17
- package/dist/tools/oracle.js.map +1 -1
- package/dist/tools/peers.d.ts +15 -0
- package/dist/tools/peers.d.ts.map +1 -0
- package/dist/tools/peers.js +70 -0
- package/dist/tools/peers.js.map +1 -0
- package/dist/tools/registry/index.d.ts +4 -0
- package/dist/tools/registry/index.d.ts.map +1 -1
- package/dist/tools/registry/index.js +274 -1
- package/dist/tools/registry/index.js.map +1 -1
- package/dist/tools/roadmap.d.ts +4 -0
- package/dist/tools/roadmap.d.ts.map +1 -1
- package/dist/tools/roadmap.js.map +1 -1
- package/dist/tools/sentinel.d.ts +15 -1
- package/dist/tools/sentinel.d.ts.map +1 -1
- package/dist/tools/sentinel.js +198 -34
- package/dist/tools/sentinel.js.map +1 -1
- package/dist/tools/voice/index.d.ts.map +1 -1
- package/dist/tools/voice/index.js +2 -3
- package/dist/tools/voice/index.js.map +1 -1
- package/dist/tools/voice.d.ts +1 -1
- package/dist/tools/voice.js +2 -2
- package/dist/tools/voice.js.map +1 -1
- package/dist/tools/workflow.js +5 -5
- package/dist/tools/workflow.js.map +1 -1
- package/dist/transports/http.js +1 -1
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -1,42 +1,73 @@
|
|
|
1
1
|
# @decibelsystems/tools
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Project intelligence for AI coding sessions.** A single MCP server that gives Claude (or any MCP client) a durable memory for your project — issues, decisions, friction, roadmap, and more — stored as plain files inside your repo, so the context survives when the chat window doesn't.
|
|
4
4
|
|
|
5
|
-
Tested with Claude Desktop, Claude Code, and Cursor. [Learn more](https://decibel.systems/tools)
|
|
5
|
+
> 29 facade tools (170+ internal handlers) across work tracking, architecture, experiments, design, git forensics, agent coordination, and security. Tested with Claude Desktop, Claude Code, and Cursor. [Learn more →](https://decibel.systems/tools)
|
|
6
6
|
|
|
7
7
|
<a href="https://github.com/decibelsystems/decibel-tools-mcp#cursor">
|
|
8
8
|
<img src="https://cursor.com/deeplink/mcp-install-dark.svg" alt="Add to Cursor" height="32" />
|
|
9
9
|
</a>
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## What is this?
|
|
14
|
+
|
|
15
|
+
When you work with an AI assistant, everything it "knows" about your project lives in the chat — and vanishes when the session ends. The next session starts cold: it re-discovers the same bugs, re-makes the same decisions, forgets why you chose Postgres over SQLite three weeks ago.
|
|
16
|
+
|
|
17
|
+
Decibel fixes that. It’s an MCP server that lets your AI **write project knowledge to disk** in a structured way and **read it back** in any future session. Track an issue in one conversation; a week later, a fresh session asks "what should I work on?" and gets the answer. Record an architecture decision once; it’s there forever. No database to run, no account to create — it’s just YAML and Markdown in a `.decibel/` folder in your repo.
|
|
18
|
+
|
|
19
|
+
## Objectives
|
|
20
|
+
|
|
21
|
+
Decibel is built around a few goals:
|
|
22
|
+
|
|
23
|
+
- **Persistence over recall.** Project state should outlive a single chat — so knowledge accrues instead of evaporating.
|
|
24
|
+
- **Local-first and private.** Everything is plain files in *your* repo. No telemetry, no cloud dependency, no lock-in. You can read, diff, and commit it like any other source.
|
|
25
|
+
- **One tool, many domains.** A handful of "facade" tools (each with an `action`) cover tracking, decisions, design, security, and coordination — instead of 170 separate tools cluttering the model’s context.
|
|
26
|
+
- **AI-native, human-readable.** Designed for an assistant to drive, but every artifact is something a person can open and understand.
|
|
27
|
+
- **Works everywhere MCP does.** Same tool set across Claude Code, Claude Desktop, Cursor, and custom agents over HTTP.
|
|
28
|
+
|
|
29
|
+
## Contents
|
|
30
|
+
|
|
31
|
+
- [Requirements](#requirements)
|
|
32
|
+
- [Quick Start](#quick-start)
|
|
33
|
+
- [Connect your AI client](#connect-your-ai-client) — [Claude Code](#claude-code) · [Claude Desktop](#claude-desktop) · [Cursor](#cursor)
|
|
34
|
+
- [Your first 5 minutes](#your-first-5-minutes)
|
|
35
|
+
- [The tools](#the-tools)
|
|
36
|
+
- [Daemon mode](#daemon-mode)
|
|
37
|
+
- [Configuration & Pro license](#configuration--pro-license)
|
|
38
|
+
- [Data storage](#data-storage)
|
|
39
|
+
- [Environment variables](#environment-variables)
|
|
40
|
+
- [Troubleshooting](#troubleshooting)
|
|
41
|
+
- [Privacy](#privacy)
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Requirements
|
|
46
|
+
|
|
47
|
+
- **Node.js ≥ 18** (`node --version` to check). On macOS, the easiest path is [Homebrew](https://brew.sh): `brew install node`.
|
|
48
|
+
- An MCP-capable client: Claude Code, Claude Desktop, Cursor, or your own.
|
|
12
49
|
|
|
13
50
|
## Quick Start
|
|
14
51
|
|
|
15
52
|
```bash
|
|
16
|
-
# Install globally
|
|
53
|
+
# Install globally…
|
|
17
54
|
npm install -g @decibelsystems/tools
|
|
18
55
|
|
|
19
|
-
#
|
|
56
|
+
# …or run on demand with npx (no install)
|
|
20
57
|
npx @decibelsystems/tools
|
|
21
58
|
```
|
|
22
59
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
After installing, initialize your first project:
|
|
60
|
+
Then wire it into your AI client below, and [initialize your first project](#your-first-5-minutes).
|
|
26
61
|
|
|
27
|
-
|
|
28
|
-
# Copy the example registry (one-time setup)
|
|
29
|
-
cp projects.example.json projects.json
|
|
30
|
-
# Edit projects.json with your project paths
|
|
31
|
-
```
|
|
62
|
+
---
|
|
32
63
|
|
|
33
|
-
|
|
64
|
+
## Connect your AI client
|
|
34
65
|
|
|
35
|
-
|
|
66
|
+
The tool set is identical across every client — only the config file location differs.
|
|
36
67
|
|
|
37
68
|
### Claude Code
|
|
38
69
|
|
|
39
|
-
Add to `.mcp.json` in your project root or `~/.claude/settings.json
|
|
70
|
+
Add to `.mcp.json` in your project root (or `~/.claude/settings.json` to make it global):
|
|
40
71
|
|
|
41
72
|
```json
|
|
42
73
|
{
|
|
@@ -49,24 +80,30 @@ Add to `.mcp.json` in your project root or `~/.claude/settings.json`:
|
|
|
49
80
|
}
|
|
50
81
|
```
|
|
51
82
|
|
|
52
|
-
###
|
|
83
|
+
### Claude Desktop
|
|
53
84
|
|
|
54
|
-
|
|
85
|
+
Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS). If the file doesn’t exist yet, create it.
|
|
86
|
+
|
|
87
|
+
> **Important — use the login-shell wrapper.** Claude Desktop launches with a stripped `PATH` and often can’t find a bare `npx`, so the server silently fails to start. Wrapping the command in `zsh -lc` makes it load your shell profile and find Node, wherever it’s installed:
|
|
55
88
|
|
|
56
89
|
```json
|
|
57
90
|
{
|
|
58
91
|
"mcpServers": {
|
|
59
92
|
"decibel-tools": {
|
|
60
|
-
"command": "
|
|
61
|
-
"args": ["-
|
|
93
|
+
"command": "/bin/zsh",
|
|
94
|
+
"args": ["-lc", "npx -y @decibelsystems/tools"]
|
|
62
95
|
}
|
|
63
96
|
}
|
|
64
97
|
}
|
|
65
98
|
```
|
|
66
99
|
|
|
67
|
-
|
|
100
|
+
After saving, **fully quit Claude Desktop (⌘Q, not just the window) and reopen.** The server appears under the **Desktop** group in *Settings → Connectors*. First launch is slow while `npx` downloads the package — give it 30–60s.
|
|
68
101
|
|
|
69
|
-
|
|
102
|
+
*Prefer a background service?* Run the [daemon](#daemon-mode) and add it as a **custom connector** (URL `http://127.0.0.1:4888/mcp`) instead — no per-app process, shared across clients.
|
|
103
|
+
|
|
104
|
+
### Cursor
|
|
105
|
+
|
|
106
|
+
Add to `~/.cursor/mcp.json`:
|
|
70
107
|
|
|
71
108
|
```json
|
|
72
109
|
{
|
|
@@ -81,92 +118,120 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)
|
|
|
81
118
|
|
|
82
119
|
---
|
|
83
120
|
|
|
84
|
-
##
|
|
121
|
+
## Your first 5 minutes
|
|
122
|
+
|
|
123
|
+
**1. Register a project.** Tools are scoped to a project, so this comes first. Just ask your assistant:
|
|
124
|
+
|
|
125
|
+
> "Run `project_init` for this folder."
|
|
85
126
|
|
|
86
|
-
|
|
127
|
+
That creates a `.decibel/` directory and registers the project. (Prefer files? Copy `projects.example.json` to `projects.json` and add your paths.)
|
|
128
|
+
|
|
129
|
+
**2. Start using it.** Everything is plain-language — the assistant maps your request to the right tool:
|
|
130
|
+
|
|
131
|
+
| You say… | What happens |
|
|
132
|
+
|----------|--------------|
|
|
133
|
+
| "Track a bug: the daemon doesn’t reconnect after sleep" | `sentinel` logs an issue |
|
|
134
|
+
| "Record why we chose Postgres over SQLite" | `architect` writes an ADR |
|
|
135
|
+
| "This build step keeps breaking — log it" | `friction` captures the pain point |
|
|
136
|
+
| "What should I work on next?" | `oracle` returns prioritized actions |
|
|
137
|
+
| "How healthy is this project?" | `workflow status` / `oracle` report |
|
|
138
|
+
|
|
139
|
+
**3. Come back later.** In a brand-new session, ask *"what’s open and what should I work on?"* — and the assistant reads back everything from `.decibel/`. That’s the whole point.
|
|
140
|
+
|
|
141
|
+
> 💡 **Tip:** Add a short note to your `CLAUDE.md` (Claude Code) or project instructions (Claude Desktop) telling the assistant to prefer Decibel tools for tracking work — so it reaches for them automatically.
|
|
142
|
+
|
|
143
|
+
---
|
|
87
144
|
|
|
88
|
-
|
|
145
|
+
## The tools
|
|
89
146
|
|
|
90
|
-
|
|
147
|
+
Every tool is a **facade**: one tool per domain, with an `action` parameter selecting the operation (e.g. `sentinel` + action `create_issue`).
|
|
148
|
+
|
|
149
|
+
### Core — always available
|
|
150
|
+
|
|
151
|
+
| Facade | Domain | Key actions |
|
|
91
152
|
|--------|--------|-------------|
|
|
92
153
|
| **sentinel** | Work tracking | `create_issue`, `close_issue`, `log_epic`, `list_epics`, `scan` |
|
|
93
|
-
| **architect** | Decisions | `create_adr`, `create_policy`, `list_policies`, `compile_oversight` |
|
|
154
|
+
| **architect** | Decisions (ADRs) | `create_adr`, `create_policy`, `list_policies`, `compile_oversight` |
|
|
94
155
|
| **dojo** | Incubation | `add_wish`, `create_proposal`, `scaffold_experiment`, `run_experiment` |
|
|
95
|
-
| **designer** | Design | `record_design_decision`, `crit`, `sync_tokens`, `review_figma` |
|
|
96
|
-
| **oracle** | Recommendations | `next_actions`, `roadmap` |
|
|
156
|
+
| **designer** | Design decisions | `record_design_decision`, `crit`, `sync_tokens`, `review_figma` |
|
|
157
|
+
| **oracle** | Recommendations | `next_actions`, `portfolio_summary`, `roadmap` |
|
|
97
158
|
| **roadmap** | Strategy | `get`, `list`, `get_health`, `link_epic`, `init` |
|
|
98
159
|
| **git** | Git forensics | `history`, `changes`, `link_issue` |
|
|
99
160
|
| **workflow** | Composites | `status`, `preflight`, `ship`, `investigate` |
|
|
100
|
-
| **vector** | Agent
|
|
101
|
-
| **context** | AI memory | `pin`, `unpin`, `list`, `
|
|
161
|
+
| **vector** | Agent run tracking | `track`, `drift`, `score` |
|
|
162
|
+
| **context** | AI memory | `pin`, `unpin`, `list`, `event_append`, `event_search` |
|
|
102
163
|
| **auditor** | Code quality | `health`, `refactor_score` |
|
|
103
164
|
| **forecast** | Estimation | `estimate`, `decompose`, `capacity` |
|
|
104
165
|
| **velocity** | Metrics | `trends`, `contributors` |
|
|
105
|
-
| **coordinator** | Multi-agent | `lock`, `unlock`, `heartbeat`, `log`, `message` |
|
|
166
|
+
| **coordinator** | Multi-agent locks | `lock`, `unlock`, `heartbeat`, `log`, `message` |
|
|
106
167
|
| **swarm** | Agent sessions | `start_session`, `join_session`, `emit_signal`, `claim_signal` |
|
|
168
|
+
| **peers** | Peer discovery | agent-to-agent presence & messaging |
|
|
169
|
+
| **concepts** | Concept graph | relate and query project concepts |
|
|
107
170
|
| **friction** | Pain points | `log`, `list`, `resolve`, `bump` |
|
|
108
171
|
| **registry** | Projects | `add`, `remove`, `list`, `alias`, `init`, `status` |
|
|
109
172
|
| **feedback** | Tool feedback | `submit`, `list` |
|
|
110
|
-
| **learnings** | Knowledge | `append`, `list` |
|
|
173
|
+
| **learnings** | Knowledge base | `append`, `list` |
|
|
111
174
|
| **provenance** | Audit trail | `list` |
|
|
112
175
|
| **bench** | Benchmarks | `run`, `compare` |
|
|
113
|
-
| **guardian** | Security | `scan_deps`, `scan_secrets`, `scan_http`, `scan_config`, `report` |
|
|
176
|
+
| **guardian** | Security scanning | `scan_deps`, `scan_secrets`, `scan_http`, `scan_config`, `report` |
|
|
114
177
|
|
|
115
|
-
### Pro
|
|
178
|
+
### Pro — requires a license key
|
|
116
179
|
|
|
117
|
-
| Facade | Domain | Key
|
|
180
|
+
| Facade | Domain | Key actions |
|
|
118
181
|
|--------|--------|-------------|
|
|
119
182
|
| **voice** | Voice inbox | `sync`, `list`, `process` |
|
|
120
183
|
| **studio** | Creative assets | `generate_image`, `generate_video` |
|
|
121
184
|
| **corpus** | Code patterns | `search`, `index` |
|
|
122
185
|
| **agentic** | Config compilation | `compile_pack`, `render`, `lint`, `golden_eval` |
|
|
123
186
|
|
|
124
|
-
> Add your license key to `~/.decibel/config.yaml` under `license.key` to
|
|
187
|
+
> Add your license key to `~/.decibel/config.yaml` under `license.key` to unlock Pro. See [Configuration](#configuration--pro-license).
|
|
125
188
|
|
|
126
189
|
---
|
|
127
190
|
|
|
128
|
-
## Daemon
|
|
191
|
+
## Daemon mode
|
|
129
192
|
|
|
130
|
-
Run as a persistent background service with HTTP transport
|
|
193
|
+
Run Decibel as a persistent background service with an HTTP transport — useful when several clients (Desktop, Cursor, custom agents) should share one server and one set of `.decibel` data.
|
|
131
194
|
|
|
132
195
|
```bash
|
|
133
|
-
# Start daemon (default
|
|
196
|
+
# Start the daemon (default 127.0.0.1:4888)
|
|
134
197
|
npx @decibelsystems/tools --daemon
|
|
135
198
|
|
|
136
|
-
#
|
|
199
|
+
# Both transports (stdio + HTTP) from one process
|
|
137
200
|
npx @decibelsystems/tools --daemon --stdio
|
|
138
201
|
|
|
139
|
-
# macOS launchd
|
|
202
|
+
# Manage it as a macOS launchd service (auto-start on login)
|
|
140
203
|
npx @decibelsystems/tools --daemon install
|
|
141
204
|
npx @decibelsystems/tools --daemon uninstall
|
|
142
205
|
npx @decibelsystems/tools --daemon status
|
|
143
206
|
```
|
|
144
207
|
|
|
145
|
-
The daemon includes log rotation, crash
|
|
208
|
+
The daemon includes log rotation, crash-loop protection (5 crashes in 60s), graceful shutdown with request draining, and a `/health` endpoint. MCP clients connect at **`http://127.0.0.1:4888/mcp`**; check it’s alive with `curl http://127.0.0.1:4888/health`.
|
|
209
|
+
|
|
210
|
+
---
|
|
146
211
|
|
|
147
|
-
|
|
212
|
+
## Configuration & Pro license
|
|
148
213
|
|
|
149
|
-
Create `~/.decibel/config.yaml
|
|
214
|
+
Create `~/.decibel/config.yaml`:
|
|
150
215
|
|
|
151
216
|
```yaml
|
|
152
217
|
daemon:
|
|
153
218
|
port: 4888
|
|
154
|
-
host:
|
|
155
|
-
auth_token: your-secret-token
|
|
219
|
+
host: 127.0.0.1
|
|
220
|
+
auth_token: your-secret-token # optional; required for non-localhost
|
|
156
221
|
log_max_size_mb: 10
|
|
157
222
|
log_max_files: 3
|
|
158
223
|
rate_limit_rpm: 60
|
|
159
224
|
license:
|
|
160
|
-
key: your-license-key
|
|
225
|
+
key: your-license-key # unlocks Pro facades
|
|
161
226
|
```
|
|
162
227
|
|
|
163
|
-
CLI flags override config
|
|
228
|
+
CLI flags override config-file values. Send `SIGHUP` to reload config without restarting.
|
|
164
229
|
|
|
165
230
|
---
|
|
166
231
|
|
|
167
|
-
## Data
|
|
232
|
+
## Data storage
|
|
168
233
|
|
|
169
|
-
|
|
234
|
+
Everything lives in a project-local `.decibel/` folder — readable, diffable, commit-able:
|
|
170
235
|
|
|
171
236
|
```
|
|
172
237
|
{project}/
|
|
@@ -186,39 +251,55 @@ Data is stored in project-local `.decibel/` folders:
|
|
|
186
251
|
├── learnings/ # Knowledge documents
|
|
187
252
|
├── context/ # Pinned facts, events
|
|
188
253
|
├── guardian/ # Security scan results, allowlists
|
|
189
|
-
└── voice/inbox/ # Voice messages
|
|
254
|
+
└── voice/inbox/ # Voice messages (Pro)
|
|
190
255
|
```
|
|
191
256
|
|
|
192
|
-
## Environment
|
|
257
|
+
## Environment variables
|
|
193
258
|
|
|
194
259
|
### Core
|
|
195
260
|
|
|
196
261
|
| Variable | Default | Description |
|
|
197
262
|
|----------|---------|-------------|
|
|
198
|
-
| `DECIBEL_ENV` | `dev` | Environment (dev
|
|
263
|
+
| `DECIBEL_ENV` | `dev` | Environment (`dev`, `staging`, `prod`) |
|
|
199
264
|
| `DECIBEL_ORG` | `default` | Organization name |
|
|
200
265
|
| `DECIBEL_MCP_ROOT` | `~/.decibel` | Global data storage root |
|
|
201
266
|
| `DECIBEL_PROJECT_ROOT` | — | Current project root path |
|
|
202
267
|
| `DECIBEL_REGISTRY_PATH` | — | Custom registry file location |
|
|
268
|
+
| `DECIBEL_PRO` | — | Set to `1` to enable Pro facades in dev |
|
|
203
269
|
|
|
204
|
-
### Optional
|
|
270
|
+
### Optional integrations
|
|
205
271
|
|
|
206
|
-
| Variable | Used
|
|
272
|
+
| Variable | Used by |
|
|
207
273
|
|----------|---------|
|
|
208
|
-
| `SUPABASE_URL` | Voice inbox, swarm sessions |
|
|
209
|
-
| `SUPABASE_SERVICE_KEY` | Supabase service role key |
|
|
274
|
+
| `SUPABASE_URL` / `SUPABASE_SERVICE_KEY` | Voice inbox, swarm sessions |
|
|
210
275
|
| `FIGMA_ACCESS_TOKEN` | Designer: `sync_tokens`, `review_figma` |
|
|
211
276
|
| `OPENAI_API_KEY` | Studio: image generation |
|
|
212
277
|
| `TOGETHER_API_KEY` | Studio: alternative image generation |
|
|
213
278
|
|
|
214
|
-
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## Troubleshooting
|
|
215
282
|
|
|
216
|
-
**
|
|
283
|
+
**Tools don’t show up in Claude Desktop.**
|
|
284
|
+
1. You almost certainly hit the `PATH` problem — use the [`zsh -lc` wrapper](#claude-desktop), not a bare `npx`.
|
|
285
|
+
2. **Fully quit** (⌘Q) and reopen — a closed window isn’t a restart.
|
|
286
|
+
3. First launch downloads the package; wait 30–60s.
|
|
287
|
+
4. Check the log: `~/Library/Logs/Claude/mcp-server-decibel-tools.log`.
|
|
288
|
+
|
|
289
|
+
**`PROJECT_NOT_FOUND` errors.** Nothing’s registered yet — run `project_init` (or `registry add`) for your project before calling other tools.
|
|
290
|
+
|
|
291
|
+
**Local server vs. hosted connector.** decibel-tools is a *local* MCP server — it’s configured in the JSON file and only appears once you add it there. It won’t show up in the connector *search* (that only lists Anthropic’s hosted catalog). Hosted connectors (GitHub, Gmail) are separate, account-scoped, and enabled per-app and per-conversation.
|
|
292
|
+
|
|
293
|
+
**Pro facades missing.** They need a `license.key` in `~/.decibel/config.yaml` (or `DECIBEL_PRO=1` in dev).
|
|
294
|
+
|
|
295
|
+
---
|
|
217
296
|
|
|
218
|
-
|
|
297
|
+
## Privacy
|
|
219
298
|
|
|
220
|
-
**
|
|
299
|
+
- **Local storage only.** All project data stays in `.decibel/` folders in your repos. Nothing is sent anywhere by default.
|
|
300
|
+
- **Optional cloud integrations** activate only when you configure API keys (Figma, Supabase, OpenAI) — marked `openWorldHint: true` in their tool annotations.
|
|
301
|
+
- **No telemetry.** No usage analytics, no tracking.
|
|
221
302
|
|
|
222
303
|
## License
|
|
223
304
|
|
|
224
|
-
MIT
|
|
305
|
+
MIT — [Decibel Systems](https://decibel.systems)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const ORG_ID: string;
|
|
2
|
+
/**
|
|
3
|
+
* Settle a command from an SDK ack (POST /agents/commands/ack). The SDK ran
|
|
4
|
+
* onCommand and reports done|failed (+ optional result/error). We write it back to
|
|
5
|
+
* Core via service_role, org-scoped. Returns false if Supabase is unconfigured.
|
|
6
|
+
* Only 'done'|'failed' are accepted from an ack (the SDK can't set other states).
|
|
7
|
+
*/
|
|
8
|
+
export declare function settleCommandFromAck(id: string, status: 'done' | 'failed', result?: Record<string, unknown> | null, error?: string | null): Promise<boolean>;
|
|
9
|
+
/** Start the command dispatcher loop. Returns a stop function. No-ops if Supabase unconfigured. */
|
|
10
|
+
export declare function startCommandDispatcher(): () => void;
|
|
11
|
+
//# sourceMappingURL=agentCommands.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agentCommands.d.ts","sourceRoot":"","sources":["../src/agentCommands.ts"],"names":[],"mappings":"AAyCA,eAAO,MAAM,MAAM,QAAuE,CAAC;AAoO3F;;;;;GAKG;AACH,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,GAAG,QAAQ,EACzB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,EACvC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACpB,OAAO,CAAC,OAAO,CAAC,CASlB;AAED,mGAAmG;AACnG,wBAAgB,sBAAsB,IAAI,MAAM,IAAI,CAcnD"}
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Agent-command dispatcher — HQ → agent control surface (Plan D, v1)
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// The inverse of agentPresence: HQ (org admin) WRITES commands into
|
|
5
|
+
// hq.agent_commands under RLS; this daemon picks up pending commands targeted at
|
|
6
|
+
// sessions IT hosts and dispatches them, writing status/result back via
|
|
7
|
+
// SERVICE_ROLE. v1 kinds (Ben-scoped, allowlisted): 'message' + 'request_status'.
|
|
8
|
+
// No shell, no lifecycle. Contract co-designed with decibel-hq (hq.agent_commands
|
|
9
|
+
// migration + cancel RPC + expire sweep). EPIC-0033.
|
|
10
|
+
//
|
|
11
|
+
// SAFETY: a 'message' is delivered to the target peer as untrusted-channel DATA
|
|
12
|
+
// (via the claude-peers broker) — it is NOT an auto-executed instruction. The
|
|
13
|
+
// daemon only transports it.
|
|
14
|
+
//
|
|
15
|
+
// ⚠️ LOAD-BEARING CROSS-ORG INVARIANT (per HQ /security-review):
|
|
16
|
+
// target_session_key / target_host are FREE TEXT on hq.agent_commands — HQ does
|
|
17
|
+
// NOT bind them to a same-org live session (keys churn). The ENTIRE cross-org
|
|
18
|
+
// targeting defense therefore rests on THIS query: it MUST filter on org_id
|
|
19
|
+
// FIRST (the org this daemon is authorized to serve), with target_host ==
|
|
20
|
+
// own hostname + target_session_key ∈ live registry as defense-in-depth.
|
|
21
|
+
// An org-A admin can write a row naming an org-B peer's guessable session_key,
|
|
22
|
+
// but that row carries org_id=A; as long as org-B's daemon only ever dispatches
|
|
23
|
+
// rows scoped to org B's org_id, the A-row never reaches B. DO NOT refactor this
|
|
24
|
+
// to key purely on (host, session_key) ignoring org_id — that opens cross-org
|
|
25
|
+
// targeting on a shared host.
|
|
26
|
+
//
|
|
27
|
+
// Other boundaries:
|
|
28
|
+
// - host-match: only dispatch commands whose target_host == this host.
|
|
29
|
+
// - expiry: skip expires_at < now; also call the DB sweep each cycle.
|
|
30
|
+
// - poll every 5s (robust; realtime is HQ's status view, not our pickup path).
|
|
31
|
+
// ============================================================================
|
|
32
|
+
import { createClient } from '@supabase/supabase-js';
|
|
33
|
+
import { log } from './config.js';
|
|
34
|
+
import { withRetryResult } from './supabaseRetry.js';
|
|
35
|
+
import { enqueueCommand } from './agentInbox.js';
|
|
36
|
+
import { resolveHost } from './agentPresence.js';
|
|
37
|
+
const BROKER_URL = `http://127.0.0.1:${process.env.CLAUDE_PEERS_PORT ?? '7899'}`;
|
|
38
|
+
// Exported so the HTTP inbox endpoints (httpServer.ts) org-scope drainCommands to
|
|
39
|
+
// the same org this daemon serves — keeps the org-id-first invariant on the read path.
|
|
40
|
+
export const ORG_ID = process.env.DECIBEL_ORG_ID || '1cb79e24-e06f-46c9-8a22-5ee025ffb0f4';
|
|
41
|
+
const POLL_MS = 5_000;
|
|
42
|
+
const ALLOWED_KINDS = new Set(['message', 'request_status']);
|
|
43
|
+
// Ben-scoped staged rollout: the FIRST run dispatches request_status ONLY so he can
|
|
44
|
+
// watch a read-only round-trip before any message reaches a live agent. 'message'
|
|
45
|
+
// dispatch stays held (rows left pending → they expire) until DECIBEL_ENABLE_AGENT_MESSAGES=1.
|
|
46
|
+
const MESSAGES_ENABLED = process.env.DECIBEL_ENABLE_AGENT_MESSAGES === '1';
|
|
47
|
+
function serviceClient() {
|
|
48
|
+
const url = process.env.SUPABASE_URL;
|
|
49
|
+
const key = process.env.SUPABASE_SERVICE_KEY;
|
|
50
|
+
if (!url || !key)
|
|
51
|
+
return null;
|
|
52
|
+
return createClient(url, key, {
|
|
53
|
+
auth: { persistSession: false, autoRefreshToken: false },
|
|
54
|
+
db: { schema: 'hq' },
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
async function brokerListPeers() {
|
|
58
|
+
try {
|
|
59
|
+
const res = await fetch(`${BROKER_URL}/list-peers`, {
|
|
60
|
+
method: 'POST',
|
|
61
|
+
headers: { 'Content-Type': 'application/json' },
|
|
62
|
+
body: JSON.stringify({ requester_id: 'decibel-daemon', scope: 'machine' }),
|
|
63
|
+
signal: AbortSignal.timeout(2000),
|
|
64
|
+
});
|
|
65
|
+
if (!res.ok)
|
|
66
|
+
return [];
|
|
67
|
+
return (await res.json());
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return [];
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/** Send a peer message via the claude-peers broker. Returns ok + optional error. */
|
|
74
|
+
async function brokerSend(to, message) {
|
|
75
|
+
try {
|
|
76
|
+
const res = await fetch(`${BROKER_URL}/send-message`, {
|
|
77
|
+
method: 'POST',
|
|
78
|
+
headers: { 'Content-Type': 'application/json' },
|
|
79
|
+
// Broker contract: {from_id, to_id, text} (claude-peers broker.ts:280,
|
|
80
|
+
// shared/types.ts:59 — confirmed line-by-line by the claude-peers owner).
|
|
81
|
+
// from_id="decibel-daemon": a plainly NON-privileged relay label. Deliberately
|
|
82
|
+
// NOT "system" — a "system" sender reads to the receiving agent as a trusted/
|
|
83
|
+
// privileged directive, the OPPOSITE of the required posture (an HQ command is
|
|
84
|
+
// untrusted-channel DATA, not an auto-executed instruction). Human provenance
|
|
85
|
+
// rides in `text` ("HQ · <issuer>: ..."). FK is off in the broker so any
|
|
86
|
+
// from_id delivers; if FK is ever enabled, register decibel-daemon then.
|
|
87
|
+
body: JSON.stringify({ from_id: 'decibel-daemon', to_id: to, text: message }),
|
|
88
|
+
signal: AbortSignal.timeout(3000),
|
|
89
|
+
});
|
|
90
|
+
const body = (await res.json().catch(() => ({})));
|
|
91
|
+
return { ok: body.ok === true, error: body.error ?? (res.ok ? undefined : `HTTP ${res.status}`) };
|
|
92
|
+
}
|
|
93
|
+
catch (e) {
|
|
94
|
+
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
const TERMINAL = new Set(['done', 'failed', 'cancelled', 'expired']);
|
|
98
|
+
async function settle(client, id, patch) {
|
|
99
|
+
// Stamp completed_at on terminal transitions so HQ can show completion timing.
|
|
100
|
+
if (typeof patch.status === 'string' && TERMINAL.has(patch.status) && !('completed_at' in patch)) {
|
|
101
|
+
patch = { ...patch, completed_at: new Date().toISOString() };
|
|
102
|
+
}
|
|
103
|
+
// org_id-scoped settle too — never update a row outside our authorized org.
|
|
104
|
+
const { error } = await client.from('agent_commands').update(patch).eq('id', id).eq('org_id', ORG_ID);
|
|
105
|
+
if (error)
|
|
106
|
+
log(`Commands: settle ${id} failed: ${error.message}`);
|
|
107
|
+
}
|
|
108
|
+
async function dispatchOne(client, cmd, peers, sdkSessions) {
|
|
109
|
+
// Defensive expiry + kind allowlist (DB also enforces, belt-and-suspenders).
|
|
110
|
+
if (cmd.expires_at && Date.parse(cmd.expires_at) < Date.now())
|
|
111
|
+
return;
|
|
112
|
+
if (!ALLOWED_KINDS.has(cmd.kind)) {
|
|
113
|
+
await settle(client, cmd.id, { status: 'failed', error: `unsupported kind '${cmd.kind}'` });
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
// Staged rollout: hold 'message' until explicitly enabled. Leave the row pending
|
|
117
|
+
// (untouched) so it simply expires — do NOT settle, so it can dispatch later if
|
|
118
|
+
// messages are enabled before it expires.
|
|
119
|
+
if (cmd.kind === 'message' && !MESSAGES_ENABLED)
|
|
120
|
+
return;
|
|
121
|
+
const peer = peers.find((p) => p.id === cmd.target_session_key);
|
|
122
|
+
const isSdkSession = !peer && sdkSessions.has(cmd.target_session_key);
|
|
123
|
+
// Target not (yet) resolvable as either a broker peer OR a known SDK session.
|
|
124
|
+
// DON'T permanently fail it — a session that registers in the split-second after
|
|
125
|
+
// the command was issued would otherwise be lost on the first tick. Leave it
|
|
126
|
+
// 'pending' so the next tick re-checks; the DB expiry sweep terminates it (→
|
|
127
|
+
// 'expired') if the target never appears. (Race fix found via SDK e2e 2026-06-15.)
|
|
128
|
+
if (!peer && !isSdkSession) {
|
|
129
|
+
return; // leave pending; retried next tick, expires if truly absent
|
|
130
|
+
}
|
|
131
|
+
// SDK-runtime target (registered via /agents/register, NOT a claude-peers peer):
|
|
132
|
+
// it has no broker transport, so we don't resolve/deliver here. Enqueue it for the
|
|
133
|
+
// SDK to poll + ack (which settles the Core row). Mark 'delivered' so HQ sees
|
|
134
|
+
// pickup; the SDK ack flips it to done/failed. (request_status is treated the same
|
|
135
|
+
// way for SDK sessions — the SDK answers it via onCommand and acks with a result.)
|
|
136
|
+
if (isSdkSession) {
|
|
137
|
+
await settle(client, cmd.id, { status: 'delivered', delivered_at: new Date().toISOString() });
|
|
138
|
+
enqueueCommand(cmd.target_session_key, {
|
|
139
|
+
id: cmd.id,
|
|
140
|
+
org_id: cmd.org_id,
|
|
141
|
+
kind: cmd.kind,
|
|
142
|
+
payload: cmd.payload ?? {},
|
|
143
|
+
enqueued_at: Date.now(),
|
|
144
|
+
});
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
// From here, peer is a live broker session. Mark delivered (picked up).
|
|
148
|
+
await settle(client, cmd.id, { status: 'delivered', delivered_at: new Date().toISOString() });
|
|
149
|
+
if (cmd.kind === 'request_status') {
|
|
150
|
+
await settle(client, cmd.id, {
|
|
151
|
+
status: 'done',
|
|
152
|
+
result: { summary: peer.summary || null, cwd: peer.cwd || null, last_seen: peer.last_seen, status: 'active' },
|
|
153
|
+
});
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
// kind === 'message'
|
|
157
|
+
const text = cmd.payload?.text;
|
|
158
|
+
if (!text) {
|
|
159
|
+
await settle(client, cmd.id, { status: 'failed', error: 'message payload missing text' });
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
const label = cmd.payload?.from_label ? `${cmd.payload.from_label}: ` : '';
|
|
163
|
+
const r = await brokerSend(cmd.target_session_key, `${label}${text}`);
|
|
164
|
+
if (r.ok) {
|
|
165
|
+
await settle(client, cmd.id, { status: 'done', result: { delivered: true } });
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
await settle(client, cmd.id, { status: 'failed', error: r.error || 'broker send failed' });
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
async function tick(client) {
|
|
172
|
+
const host = resolveHost();
|
|
173
|
+
// DB-side sweep: flip pending->expired where past expiry (idempotent, service_role).
|
|
174
|
+
try {
|
|
175
|
+
await client.rpc('expire_stale_agent_commands');
|
|
176
|
+
}
|
|
177
|
+
catch { /* RPC optional/non-fatal */ }
|
|
178
|
+
// Pending commands for OUR org (primary cross-org filter — see invariant above),
|
|
179
|
+
// targeted at sessions THIS daemon hosts. withRetryResult smooths transient
|
|
180
|
+
// "fetch failed" blips (issue 2026-06-13) before giving up for this tick.
|
|
181
|
+
const { data, error } = await withRetryResult(() => client
|
|
182
|
+
.from('agent_commands')
|
|
183
|
+
.select('id,org_id,target_session_key,target_host,kind,payload,expires_at,status')
|
|
184
|
+
.eq('org_id', ORG_ID)
|
|
185
|
+
.eq('status', 'pending')
|
|
186
|
+
.eq('target_host', host), 'commands.poll');
|
|
187
|
+
if (error) {
|
|
188
|
+
log(`Commands: poll failed: ${error.message}`);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
const pending = (data ?? []);
|
|
192
|
+
if (pending.length === 0)
|
|
193
|
+
return;
|
|
194
|
+
// SDK runtimes hosting on this box (live, non-claude-code sessions): commands
|
|
195
|
+
// targeting these route to the in-daemon inbox for the SDK to poll+ack, instead
|
|
196
|
+
// of failing as "not found in live registry". org-id-first + host-match preserved.
|
|
197
|
+
const sdkSessions = await loadSdkSessions(client, host);
|
|
198
|
+
const peers = await brokerListPeers();
|
|
199
|
+
for (const cmd of pending) {
|
|
200
|
+
try {
|
|
201
|
+
await dispatchOne(client, cmd, peers, sdkSessions);
|
|
202
|
+
}
|
|
203
|
+
catch (e) {
|
|
204
|
+
log(`Commands: dispatch ${cmd.id} error: ${e instanceof Error ? e.message : String(e)}`);
|
|
205
|
+
await settle(client, cmd.id, { status: 'failed', error: 'dispatch exception' }).catch(() => { });
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Live SDK-runtime session_keys this daemon hosts (org + host scoped, runtime not
|
|
211
|
+
* claude-code, status active). These receive commands via the inbox, not the broker.
|
|
212
|
+
*/
|
|
213
|
+
async function loadSdkSessions(client, host) {
|
|
214
|
+
const { data, error } = await withRetryResult(() => client
|
|
215
|
+
.from('agent_sessions')
|
|
216
|
+
.select('session_key,runtime,status')
|
|
217
|
+
.eq('org_id', ORG_ID)
|
|
218
|
+
.eq('host', host)
|
|
219
|
+
.eq('status', 'active')
|
|
220
|
+
.neq('runtime', 'claude-code'), 'commands.sdkSessions');
|
|
221
|
+
const set = new Set();
|
|
222
|
+
if (error)
|
|
223
|
+
log(`Commands: loadSdkSessions query error: ${error.message}`);
|
|
224
|
+
if (!error && data) {
|
|
225
|
+
for (const r of data)
|
|
226
|
+
set.add(r.session_key);
|
|
227
|
+
}
|
|
228
|
+
return set;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Settle a command from an SDK ack (POST /agents/commands/ack). The SDK ran
|
|
232
|
+
* onCommand and reports done|failed (+ optional result/error). We write it back to
|
|
233
|
+
* Core via service_role, org-scoped. Returns false if Supabase is unconfigured.
|
|
234
|
+
* Only 'done'|'failed' are accepted from an ack (the SDK can't set other states).
|
|
235
|
+
*/
|
|
236
|
+
export async function settleCommandFromAck(id, status, result, error) {
|
|
237
|
+
const client = serviceClient();
|
|
238
|
+
if (!client)
|
|
239
|
+
return false;
|
|
240
|
+
if (status !== 'done' && status !== 'failed')
|
|
241
|
+
return false;
|
|
242
|
+
const patch = { status };
|
|
243
|
+
if (result !== undefined && result !== null)
|
|
244
|
+
patch.result = result;
|
|
245
|
+
if (error !== undefined && error !== null)
|
|
246
|
+
patch.error = error;
|
|
247
|
+
await settle(client, id, patch);
|
|
248
|
+
return true;
|
|
249
|
+
}
|
|
250
|
+
/** Start the command dispatcher loop. Returns a stop function. No-ops if Supabase unconfigured. */
|
|
251
|
+
export function startCommandDispatcher() {
|
|
252
|
+
const client = serviceClient();
|
|
253
|
+
if (!client) {
|
|
254
|
+
log('Commands: SUPABASE_URL/SERVICE_KEY not set — agent-command dispatcher disabled.');
|
|
255
|
+
return () => { };
|
|
256
|
+
}
|
|
257
|
+
log(`Commands: dispatcher started (5s poll of hq.agent_commands, host ${resolveHost()}, org ${ORG_ID}).`);
|
|
258
|
+
const run = () => {
|
|
259
|
+
tick(client).catch((e) => log(`Commands: tick error: ${e instanceof Error ? e.message : String(e)}`));
|
|
260
|
+
};
|
|
261
|
+
run();
|
|
262
|
+
const iv = setInterval(run, POLL_MS);
|
|
263
|
+
if (typeof iv.unref === 'function')
|
|
264
|
+
iv.unref();
|
|
265
|
+
return () => clearInterval(iv);
|
|
266
|
+
}
|
|
267
|
+
//# sourceMappingURL=agentCommands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agentCommands.js","sourceRoot":"","sources":["../src/agentCommands.ts"],"names":[],"mappings":"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"}
|