@j-o-r/hello-dave 0.0.7 → 0.0.8
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/CHANGELOG.md +6 -0
- package/TODO.md +13 -0
- package/docs/agent-manager.md +244 -0
- package/docs/bin-dave.md +62 -0
- package/docs/codeserver-pattern.md +191 -0
- package/docs/generic-toolset.md +326 -0
- package/docs/howtos/agent-networking.md +253 -0
- package/docs/howtos/spawn-agents.md.bak +200 -0
- package/docs/howtos/spawn-agents.md.bak_new +200 -0
- package/docs/jsdoc-best-practices.md +278 -0
- package/docs/multi-agent-clusters.md +265 -0
- package/docs/multi-agent-clusters.md.bak +229 -0
- package/docs/path-resolution-best-practices.md +104 -0
- package/docs/project-overview.md +67 -0
- package/docs/prompt/spawn_agent.md +173 -0
- package/docs/prompt/spawn_agent.md.bak +201 -0
- package/docs/prompt-class.md +141 -0
- package/docs/suggestions.md +38 -0
- package/docs/todo-archive-v0.0.8.md +1 -0
- package/docs/todo-archive.md +44 -0
- package/docs/tools-syntax-validation.md +121 -0
- package/docs/toolset.md +164 -0
- package/docs/xai-responses.md +111 -0
- package/docs/xai_collections.md +106 -0
- package/lib/genericToolset.js +26 -13
- package/package.json +1 -1
- package/README.md.bak +0 -218
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
## Changelog
|
|
2
2
|
|
|
3
|
+
### v0.0.8 (Released - April 15, 2026)
|
|
4
|
+
- **lib/genericToolset.js Timeout Refinements**: Switched `execute_bash_script` to @j-o-r/sh `.options({timeout: ms}).run()` with heredoc delimiter for verbatim multi-line bash_script safety. Default 360s (resets on stdout/stderr output for true idle detection only), SIGTERM on expiry. `execute_remote_script` stdin pipe preserved. Tests: success, sleep timeout (3s<7s), exit1 error, interactive `read -p` no hang.
|
|
5
|
+
- **TODO.md Cleanup**: Archived all completed tasks (timeout refinements, prior v0.0.7 carryovers) to `docs/todo-archive-v0.0.8.md`. Pending changelog task completed here. Clean post-release state.
|
|
6
|
+
- **.npmignore & package-lock.json**: Minor updates for cleaner packaging.
|
|
7
|
+
- **Release Prep**: `package.json` bumped to v0.0.8. `npm run release` ready (types + pack to `./release/`).
|
|
8
|
+
|
|
3
9
|
### v0.0.7 (Released - April 13, 2026)
|
|
4
10
|
- **spawn_agent Enhancements**: Strict blueprint enforcement in `docs/prompt/spawn_agent.md` (mandatory tool sequence: INSPECT → VALIDATE → GATHER → GENERATE → AUTO-DEPLOY/TEST). Fixed one-shot hallucination/no-deploy via verbatim AGENT BLUEPRINT TEMPLATE, temp_agent.js validation (syntax/blueprint checks), PROJECT auto-deploy (write/mv/chmod/test/rm), FRESH manual code/bash. Robust fetchLivePrompt() (live MD full-load + fallbacks). CodeServer/PM2 awareness (LAUNCH_MODE detect, client connect hints). Tested 2026-04-13: /tmp FRESH, PROJECT diag_agent.js deploy+--help success.
|
|
5
11
|
- **JSDoc Updates (lib/ modules)**: Comprehensive JSDoc added/fixed for AgentClient.js, AgentManager.js, AgentServer.js, Cli.js, Prompt.js, Session.js, ToolSet.js, fafs.js, genericToolset.js, wsCli.js, wsIO.js. Typedefs, @returns, @private tags. Note: Some parser warnings (HTML entities < → <, import() expr); HTML generated in docs/jsdoc/.
|
package/TODO.md
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
# AgentManager (\`lib/AgentManager.js\`)
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
**AgentManager** is the central orchestrator class in the hello-dave framework. It manages agent lifecycle: setup (prompts, API, tools, sessions), execution modes (CLI, direct calls, WebSocket server/client), and tool integration. Designed for simplicity and extensibility, it abstracts LLM providers (\`xai\`, \`gpt\`, \`claude\`), \`Prompt.js\`, \`ToolSet.js\`, and \`Session.js\`.
|
|
5
|
+
|
|
6
|
+
**Uses named exports from \`lib/index.js\` - NO default export.**
|
|
7
|
+
|
|
8
|
+
Key Features:
|
|
9
|
+
- **Modes**: Interactive CLI, one-shot \`directCall\`, WS **server** (expose agent as tool), **client** (attach to remote server), hybrid (server + client).
|
|
10
|
+
- **Tool Handling**: Pre-configured (\`toolsetMode: 'auto'\`/\`'required'\`), generics (\`addGenericToolcall\`), custom \`ToolSet\`.
|
|
11
|
+
- **Persistence**: Sessions in \`.cache/[name]/\` (NDJSON logs).
|
|
12
|
+
- **Networking**: WS with optional \`secret\` auth (base64-encoded).
|
|
13
|
+
- **Validation**: Strict name regex \`/^[a-z_0-9_]{2,}$/\`.
|
|
14
|
+
- **Events**: Leverages \`Prompt\` events (e.g., \`reset\` → server resetAll).
|
|
15
|
+
|
|
16
|
+
Exports: \`{ AgentManager }\` (named).
|
|
17
|
+
|
|
18
|
+
## Agent Naming Rules ⚠️
|
|
19
|
+
**CRITICAL**: The \`name\` (constructor) and \`toolName\` (in \`start()\`) **MUST** match regex \`/^[a-z_0-9_]{2,}$/\`:
|
|
20
|
+
- Lowercase \`a-z\`, digits \`0-9\`, \`_\` **only**.
|
|
21
|
+
- **Minimum 2 characters**.
|
|
22
|
+
|
|
23
|
+
**Valid ✅**:
|
|
24
|
+
- \`myagent\`
|
|
25
|
+
- \`chatbot\`
|
|
26
|
+
- \`weather_agent\`
|
|
27
|
+
- \`tool123\`
|
|
28
|
+
- \`ws_client\`
|
|
29
|
+
|
|
30
|
+
**Invalid ❌ (throws \`Error\`)**:
|
|
31
|
+
- \`MyAgent\` (uppercase)
|
|
32
|
+
- \`agent-v1\` (hyphen)
|
|
33
|
+
- \`a\` (too short)
|
|
34
|
+
- \`agent#tool\` (\`#\` invalid)
|
|
35
|
+
- \`Agent_\` (uppercase)
|
|
36
|
+
|
|
37
|
+
**Why?** Safe for folders, tool names, filesystems (no specials/caps/spaces).
|
|
38
|
+
|
|
39
|
+
## Quick Usage
|
|
40
|
+
\`\`\`javascript
|
|
41
|
+
import { AgentManager } from '@j-o-r/hello-dave';
|
|
42
|
+
|
|
43
|
+
const agent = new AgentManager({ name: 'myagent', secret: 'mysecret' });
|
|
44
|
+
agent.setup({
|
|
45
|
+
prompt: 'You are a helpful coding assistant.',
|
|
46
|
+
api: 'xai',
|
|
47
|
+
options: { model: 'grok-4-fast-reasoning' },
|
|
48
|
+
toolsetMode: 'auto',
|
|
49
|
+
contextWindow: 128000
|
|
50
|
+
});
|
|
51
|
+
agent.addGenericToolcall('execute_bash_script');
|
|
52
|
+
|
|
53
|
+
await agent.start(); // Interactive CLI mode
|
|
54
|
+
// Or: await agent.directCall('Write a Bash script'); // One-shot (pair with readIn for piped CLI)
|
|
55
|
+
// Or: await agent.start(8000); // WS server on port 8000
|
|
56
|
+
\`\`\`
|
|
57
|
+
|
|
58
|
+
## Constructor Options
|
|
59
|
+
| Property | Type | Default | Description |
|
|
60
|
+
|----------|------|---------|-------------|
|
|
61
|
+
| \`name\` | string | \`'agent'\` | **Agent ID (session folder, tool name). MUST match \`/^[a-z_0-9_]{2,}$/\` (lowercase a-z0-9_; ≥2 chars).** |
|
|
62
|
+
| \`secret\` | string | \`''\` | WS auth (base64-encoded; optional, match server/client). |
|
|
63
|
+
| \`cachePath\` | string | \`'.cache/hello-dave'\` | Session storage root. |
|
|
64
|
+
|
|
65
|
+
## setup(setup) → \`this\` (chainable)
|
|
66
|
+
Configures the agent. Must call before \`start()\`/\`directCall()\`.
|
|
67
|
+
|
|
68
|
+
| Property | Type | Default | Description |
|
|
69
|
+
|----------|------|---------|-------------|
|
|
70
|
+
| \`prompt\` | string | - | **Required**: System prompt. |
|
|
71
|
+
| \`api\` | \`'xai'|'gpt'|'claude'\` | \`'gpt'\` | LLM provider (uses \`lib/API/[provider]/text.js\`). |
|
|
72
|
+
| \`options\` | \`XAIOptions\`/\`OAOptions\`/etc. | \`{}\` | Provider-specific (model, temperature, tools, reasoning). |
|
|
73
|
+
| \`contextWindow\` | number | \`300000\` | Token limit for \`Prompt\`. |
|
|
74
|
+
| \`toolsetMode\` | \`'auto'|'required'\` | \`null\` | \`'auto'\`: Generic tools; \`'required'\`: Empty \`ToolSet\` (add manually). |
|
|
75
|
+
| \`debug\` | boolean | \`false\` | Verbose logging. |
|
|
76
|
+
|
|
77
|
+
Internals: Creates \`Prompt\`, \`Session\`, sets \`Prompt.setAdaptor(API.text[api], toolset, options)\`.
|
|
78
|
+
|
|
79
|
+
## Key Methods
|
|
80
|
+
| Method | Args | Returns | Description |
|
|
81
|
+
|--------|------|---------|-------------|
|
|
82
|
+
| \`directCall(input)\` | \`string\` | \`Promise<string>\` | One-shot query (via \`prompt.call()\`). **Ideal for piped CLI scripts & cron jobs.** |
|
|
83
|
+
| \`getPrompt()\` | - | \`Prompt\` | Access internal \`Prompt\`. |
|
|
84
|
+
| \`getToolset()\` | - | \`ToolSet\\|void\` | Access tools. |
|
|
85
|
+
| \`environment()\` | - | \`Promise<EnvironmentInfo>\` | System info (via \`fafs.js/env()\`). |
|
|
86
|
+
| \`addGenericToolcall(name)\` | string (e.g., \`'read_file'\`) | - | Copy from \`genericToolset.js\` pool. Post-setup only. |
|
|
87
|
+
| \`start(servePort?, connectUrl?, cliIntro?, toolName?, toolDesc?)\` | Mixed | \`Promise<void>\` | **Smart launcher**:<br>- \`servePort\` (num): WS **server** (\`toolName\` MUST match name regex or auto-gen).<br>- \`connectUrl\` (str, e.g. \`'ws://127.0.0.1:8000/ws'\`): WS **client** (toolName/desc for attachment).<br>- Neither: **Interactive CLI** mode.<br>- Both: Hybrid. |
|
|
88
|
+
|
|
89
|
+
## Workflow Diagram
|
|
90
|
+
\`\`\`mermaid
|
|
91
|
+
graph TD
|
|
92
|
+
A[New AgentManager name, secret] --> B[setup prompt, api, options, toolsetMode]
|
|
93
|
+
B --> C{start args?}
|
|
94
|
+
C -->|servePort| D[enableServer port, name, desc<br/>+ optional attach client]
|
|
95
|
+
C -->|connectUrl| E[attach client url, name, desc]
|
|
96
|
+
C -->|none| F[startCli intro]
|
|
97
|
+
D --> G[Session Loop: Prompt → API/Tools → Response]
|
|
98
|
+
E --> G
|
|
99
|
+
F --> G
|
|
100
|
+
G --> H[directCall or persist]
|
|
101
|
+
\`\`\`
|
|
102
|
+
|
|
103
|
+
**Per-Endpoint Options**:
|
|
104
|
+
- **Interactive CLI**: \`start()\` → chat loop until Ctrl+C.
|
|
105
|
+
- **One-Shot Piped CLI**: Custom script w/ \`readIn()\` + \`directCall()\` (stdin detection; exits after 1 response). No loop.
|
|
106
|
+
- **WS Server**: \`start(port)\` → \`AgentServer\` (localhost only). Exposes agent as tool (name/desc). \`secret\` required for clients. \`prompt.on('reset')\` → \`server.resetAll()\`.
|
|
107
|
+
- **WS Client**: \`start(undefined, url)\` → \`AgentClient\`. Connects to remote server; agent callable as tool.
|
|
108
|
+
- **Direct**: \`directCall()\` bypasses networking/CLI.
|
|
109
|
+
|
|
110
|
+
## Examples
|
|
111
|
+
|
|
112
|
+
### 1. Interactive CLI Agent
|
|
113
|
+
\`\`\`javascript
|
|
114
|
+
import { AgentManager } from '@j-o-r/hello-dave';
|
|
115
|
+
|
|
116
|
+
const agent = new AgentManager({ name: 'chatbot' });
|
|
117
|
+
agent.setup({
|
|
118
|
+
prompt: 'You are a friendly chatbot.',
|
|
119
|
+
api: 'xai',
|
|
120
|
+
toolsetMode: 'auto'
|
|
121
|
+
});
|
|
122
|
+
await agent.start('Chatbot ready!'); // Interactive chat loop
|
|
123
|
+
\`\`\`
|
|
124
|
+
|
|
125
|
+
### 2. WS Server (Expose as Tool)
|
|
126
|
+
\`\`\`javascript
|
|
127
|
+
import { AgentManager } from '@j-o-r/hello-dave';
|
|
128
|
+
|
|
129
|
+
agent.setup({ ... });
|
|
130
|
+
await agent.start(8000, undefined, undefined, 'weathertool', 'Get real-time weather');
|
|
131
|
+
\`\`\`
|
|
132
|
+
- Clients: \`npx @j-o-r/hello-dave dave --connect ws://localhost:8000/ws --secret mysecret\`
|
|
133
|
+
|
|
134
|
+
### 3. Hybrid + Direct Call
|
|
135
|
+
\`\`\`javascript
|
|
136
|
+
import { AgentManager } from '@j-o-r/hello-dave';
|
|
137
|
+
|
|
138
|
+
await agent.start(8001, 'ws://other:8000/ws'); // Server on 8001 + client to other
|
|
139
|
+
const resp = await agent.directCall('Hybrid query'); // Uses attached tools too
|
|
140
|
+
\`\`\`
|
|
141
|
+
|
|
142
|
+
### 4. Custom Tools + Generics
|
|
143
|
+
\`\`\`javascript
|
|
144
|
+
import { AgentManager } from '@j-o-r/hello-dave';
|
|
145
|
+
|
|
146
|
+
agent.setup({ toolsetMode: 'required' });
|
|
147
|
+
const ts = agent.getToolset();
|
|
148
|
+
ts.add('custommath', 'Add numbers', {
|
|
149
|
+
type: 'object', properties: {a: {type: 'number'}, b: {type: 'number'}},
|
|
150
|
+
required: ['a', 'b']
|
|
151
|
+
}, async ({a, b}) => a + b);
|
|
152
|
+
agent.addGenericToolcall('javascript_interpreter');
|
|
153
|
+
\`\`\`
|
|
154
|
+
|
|
155
|
+
### 5. CLI One-Shot Piped Usage (Scripts/Cron)
|
|
156
|
+
Uses \`@j-o-r/sh\` (\`readIn()\`, \`parseArgs()\`) + \`AgentManager.directCall()\` for fast, single-turn queries from stdin. **Detects piped input vs interactive** (empty stdin → help). Ideal for bash pipelines, cron jobs, automation.
|
|
157
|
+
|
|
158
|
+
**Boilerplate Snippet** (see \`agents/grok_agent.js\`, \`agents/docs_agent.js\` etc.):
|
|
159
|
+
\`\`\`javascript
|
|
160
|
+
#!/usr/bin/env node
|
|
161
|
+
import { AgentManager } from '@j-o-r/hello-dave';
|
|
162
|
+
import { parseArgs, readIn } from '@j-o-r/sh';
|
|
163
|
+
|
|
164
|
+
const name = 'grok_agent'; // Matches naming rules
|
|
165
|
+
const api = 'xai';
|
|
166
|
+
const secret = process.env.SECRET || '';
|
|
167
|
+
|
|
168
|
+
const input = await readIn();
|
|
169
|
+
const args = parseArgs();
|
|
170
|
+
if (args.help || !input?.trim()) {
|
|
171
|
+
console.log(\`
|
|
172
|
+
Usage: echo "query" | \${name}.js [--model grok-4] [--temperature 0.7]
|
|
173
|
+
|
|
174
|
+
Options:
|
|
175
|
+
--model [str] e.g., 'grok-4', 'grok-beta'
|
|
176
|
+
--temperature [float] 0.0 - 2.0
|
|
177
|
+
--tokens [int] Max output tokens
|
|
178
|
+
--top_p [float]
|
|
179
|
+
--context [int] Context window (default: 1.9M)
|
|
180
|
+
\`);
|
|
181
|
+
process.exit(0);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const options = {
|
|
185
|
+
tools: [{type: 'web_search'}, {type: 'x_search'}],
|
|
186
|
+
model: args.model || 'grok-4.20-multi-agent-0309',
|
|
187
|
+
temperature: args.temperature ? parseFloat(args.temperature) : undefined,
|
|
188
|
+
max_output_tokens: args.tokens ? parseInt(args.tokens) : undefined,
|
|
189
|
+
top_p: args.top_p ? parseFloat(args.top_p) : undefined,
|
|
190
|
+
reasoning: { effort: 'medium', summary: 'auto' }
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
const agent = new AgentManager({ name, secret });
|
|
194
|
+
agent.setup({
|
|
195
|
+
prompt: 'Respond briefly and directly. Reason step-by-step first.',
|
|
196
|
+
api,
|
|
197
|
+
options,
|
|
198
|
+
toolsetMode: 'auto',
|
|
199
|
+
contextWindow: args.context ? parseInt(args.context) : 1900000
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
const res = await agent.directCall(input);
|
|
203
|
+
console.log(res);
|
|
204
|
+
\`\`\`
|
|
205
|
+
|
|
206
|
+
**Bash Examples**:
|
|
207
|
+
\`\`\`bash
|
|
208
|
+
# Quick query
|
|
209
|
+
echo "Explain async/await" | agents/grok_agent.js --model grok-4
|
|
210
|
+
|
|
211
|
+
# Custom options
|
|
212
|
+
echo "Daily summary" | agents/grok_agent.js --model grok-4 --temperature 0.1 --tokens 500
|
|
213
|
+
|
|
214
|
+
# Cron job (append to log)
|
|
215
|
+
0 8 * * 1 echo "Weekly report: sales data" | /path/to/grok_agent.js >> reports.log
|
|
216
|
+
|
|
217
|
+
# Pipe chain
|
|
218
|
+
cat data.txt | agents/docs_agent.js --model grok-4 | jq .
|
|
219
|
+
\`\`\`
|
|
220
|
+
|
|
221
|
+
**Interactive vs Piped**:
|
|
222
|
+
| Mode | Invocation | Behavior |
|
|
223
|
+
|------|------------|----------|
|
|
224
|
+
| **Interactive** | \`agent.start()\` | Chat loop (multi-turn, until Ctrl+C). |
|
|
225
|
+
| **Piped** | \`readIn() + directCall()\` | Single response, fast exit. Stdin empty → help. |
|
|
226
|
+
|
|
227
|
+
**Suitability**: Cron/CLI automation (lightweight, no server). Complements WS modes.
|
|
228
|
+
|
|
229
|
+
**Cross-Ref**: [README.md#cli-one-shot-with-example-agents](../README.md#cli-one-shot-with-example-agents) (\`agents/*.js\` ready-to-run).
|
|
230
|
+
|
|
231
|
+
## Advanced: Networking & Secrets
|
|
232
|
+
- **Server-Client Chain**: Server A attaches to Server B → A callable from B (and vice versa if mutual).
|
|
233
|
+
- **Cron/CLI Messaging**: Pipe to one-shot scripts (above) or WS clients: \`echo 'query' | npx @j-o-r/hello-dave dave --connect ...\`
|
|
234
|
+
- **Reset**: \`Prompt\` emits \`'reset'\` → propagates to attached servers/clients.
|
|
235
|
+
|
|
236
|
+
## Errors
|
|
237
|
+
- No \`setup()\`: Throws.
|
|
238
|
+
- **Invalid \`name\`/\`toolName\`: Regex \`/^[a-z_0-9_]{2,}$/\` fail → \`Error\`**.
|
|
239
|
+
- No \`toolset\` on server: Throws.
|
|
240
|
+
|
|
241
|
+
See source \`lib/AgentManager.js\` for full JSDoc/types. Cross-links:
|
|
242
|
+
- [Prompt](./prompt-class.md)
|
|
243
|
+
- [ToolSet](./toolset.md)
|
|
244
|
+
- [Generic Tools](../lib/genericToolset.js)
|
package/docs/bin-dave.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Dave CLI Usage
|
|
2
|
+
|
|
3
|
+
## Introduction
|
|
4
|
+
|
|
5
|
+
The Dave CLI tool is the entry point for interacting with the Hello Dave project. It is located at `bin/dave.js` and can be run globally or via npx.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
### Global Installation
|
|
10
|
+
|
|
11
|
+
To install globally and use the `dave` command:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install -g @j-o-r/hello-dave
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### Local Usage with npx
|
|
18
|
+
|
|
19
|
+
Run without installation:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npx @j-o-r/hello-dave [flags]
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Available Flags
|
|
26
|
+
|
|
27
|
+
The CLI supports various flags for configuration and launching services. Common flags include:
|
|
28
|
+
|
|
29
|
+
- `--help`: Display help information.
|
|
30
|
+
- `--version`: Show the current version of the Dave CLI.
|
|
31
|
+
- `--code [port] [--secret secret]`: Launch a portable CodeServer instance. Optionally specify a port (defaults to 8080 if omitted). Use `--secret` to set an access password for the server.
|
|
32
|
+
|
|
33
|
+
For detailed information on the CodeServer pattern and integration, refer to [codeserver-pattern.md](codeserver-pattern.md).
|
|
34
|
+
|
|
35
|
+
Other flags may be available depending on the version; run `dave --help` for the full list.
|
|
36
|
+
|
|
37
|
+
## Examples
|
|
38
|
+
|
|
39
|
+
### Basic Usage
|
|
40
|
+
|
|
41
|
+
- Show help (global):
|
|
42
|
+
```bash
|
|
43
|
+
dave --help
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
- Show version (npx):
|
|
47
|
+
```bash
|
|
48
|
+
npx @j-o-r/hello-dave --version
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Launching CodeServer
|
|
52
|
+
|
|
53
|
+
- Launch on default port (global):
|
|
54
|
+
```bash
|
|
55
|
+
dave --code
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
- Launch on custom port with secret (npx):
|
|
59
|
+
```bash
|
|
60
|
+
npx @j-o-r/hello-dave --code 3000 --secret mysecretpassword
|
|
61
|
+
```
|
|
62
|
+
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# CodeServer Pattern
|
|
2
|
+
|
|
3
|
+
[](https://pm2.keymetrics.io/) [](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API)
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Introduction & Motivation](#introduction--motivation)
|
|
8
|
+
- [Architecture](#architecture)
|
|
9
|
+
- [Prerequisites](#prerequisites)
|
|
10
|
+
- [Step-by-Step Setup](#step-by-step-setup)
|
|
11
|
+
- [Interaction via \`bin/dave.js\`](#interaction-via-bindavejs)
|
|
12
|
+
- [Monitoring & Stopping with PM2](#monitoring--stopping-with-pm2)
|
|
13
|
+
- [Customization](#customization)
|
|
14
|
+
- [Benefits](#benefits)
|
|
15
|
+
- [Troubleshooting](#troubleshooting)
|
|
16
|
+
- [Integration with AgentManager](#integration-with-agentmanager)
|
|
17
|
+
- [References](#references)
|
|
18
|
+
|
|
19
|
+
## Introduction & Motivation
|
|
20
|
+
|
|
21
|
+
The **CodeServer pattern** demonstrates a production-ready setup for running a **persistent, always-on agent server** managed by [PM2](https://pm2.keymetrics.io/). It launches:
|
|
22
|
+
|
|
23
|
+
- **Main Server**: \`code_agent.js\` as a WebSocket server (code-focused agent with JavaScript tools).
|
|
24
|
+
- **Sub-Agents (Clients)**: Specialized agents (\`todo_agent.js\`, \`readme_agent.js\`, \`npm_agent.js\`, \`docs_agent.js\`) that **attach as tools** to the main server via WebSocket.
|
|
25
|
+
|
|
26
|
+
**Motivation**:
|
|
27
|
+
- **Persistence**: Long-running sessions without restarts (state in \`.cache/hello-dave/[agent]/\`).
|
|
28
|
+
- **Delegation**: Main agent delegates to specialists (e.g., "update docs" → \`docsDave\` tool).
|
|
29
|
+
- **No Heartbeats**: PM2 handles restarts, monitoring—no custom pings.
|
|
30
|
+
- **Scalability**: Easy to add sub-agents, deploy across machines.
|
|
31
|
+
- **CLI-Friendly**: Interact via \`bin/dave.js --connect\`.
|
|
32
|
+
|
|
33
|
+
Ideal for dev workflows: code execution, docs mgmt, npm inspection, todos—all in one persistent hub.
|
|
34
|
+
|
|
35
|
+
See live example: [agents/CodeServer](../agents/CodeServer)
|
|
36
|
+
|
|
37
|
+
## Architecture
|
|
38
|
+
|
|
39
|
+
```mermaid
|
|
40
|
+
graph TB
|
|
41
|
+
PM2[PM2 Process Manager] --> Main[Main: code_agent.js<br/>--serve PORT --secret SECRET<br/>WS Server on /ws]
|
|
42
|
+
PM2 --> Todo[todo_agent.js<br/>--connect ws://localhost:PORT/ws<br/>tool: todo_agent]
|
|
43
|
+
PM2 --> Readme[readme_agent.js<br/>--connect ...<br/>tool: readme_agent]
|
|
44
|
+
PM2 --> NPM[npm_agent.js<br/>--connect ...<br/>tool: npm_module_inspector]
|
|
45
|
+
PM2 --> Docs[docs_agent.js<br/>--connect ...<br/>tool: agent_docs]
|
|
46
|
+
|
|
47
|
+
User[bin/dave.js --connect] -.-> Main
|
|
48
|
+
Main -->|Delegates via tools| Todo & Readme & NPM & Docs
|
|
49
|
+
Todo -.->|File ops| ProjectFiles[(TODO.md, etc.)]
|
|
50
|
+
Docs -.->|Docs mgmt| DocsFolder[./docs/*.md]
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Key Flows**:
|
|
54
|
+
1. PM2 spawns all processes (named \`FOLDER_agent_PORT\`).
|
|
55
|
+
2. Clients connect to main server → auto-register as **tools** (e.g., \`todo_agent\`, \`readme_agent\`).
|
|
56
|
+
3. User queries main server → delegates (e.g., \`call todo_agent {add: "new task"}\`).
|
|
57
|
+
4. Sessions persist independently per agent.
|
|
58
|
+
|
|
59
|
+
## Prerequisites
|
|
60
|
+
|
|
61
|
+
| Requirement | Install Command | Notes |
|
|
62
|
+
|-------------|-----------------|-------|
|
|
63
|
+
| **Node.js** | `node --version` (≥18) | ESM support required. |
|
|
64
|
+
| **PM2** | `npm i -g pm2` | Process manager. Startup: `pm2 startup`. |
|
|
65
|
+
| **Project** | `git clone <repo> && cd hello-dave` | Examples in \`./agents/\`. |
|
|
66
|
+
|
|
67
|
+
Verify: `pm2 --version` & `node -e "import('@j-o-r/hello-dave')"`
|
|
68
|
+
|
|
69
|
+
## Step-by-Step Setup
|
|
70
|
+
|
|
71
|
+
1. **Navigate to project**:
|
|
72
|
+
```bash
|
|
73
|
+
cd /path/to/hello-dave
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
2. **Launch CodeServer** (pick PORT 1024-65535, SECRET ≥3 chars):
|
|
77
|
+
```bash
|
|
78
|
+
./agents/CodeServer 8080 mysecret123
|
|
79
|
+
```
|
|
80
|
+
Output:
|
|
81
|
+
```
|
|
82
|
+
Starting CodeServer on port 8080 in folder 'hello-dave' ... with SECRET 'mysecret123'
|
|
83
|
+
CodeServer processes spawned with prefix 'hello-dave_' and suffix _8080.
|
|
84
|
+
dave --connect ws://127.0.0.1:8080/ws --secret 'mysecret123'
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
3. **Verify PM2**:
|
|
88
|
+
```bash
|
|
89
|
+
pm2 list | grep 8080
|
|
90
|
+
```
|
|
91
|
+
| Name | Status | CPU | Memory |
|
|
92
|
+
|-----------------------|--------|-----|--------|
|
|
93
|
+
| hello-dave_code_agent_8080 | online | ... | ... |
|
|
94
|
+
| hello-dave_todo_agent_8080 | online | ... | ... |
|
|
95
|
+
| ... (4 total) | ... | ... | ... |
|
|
96
|
+
|
|
97
|
+
## Interaction via \`bin/dave.js\`
|
|
98
|
+
|
|
99
|
+
**Interactive**:
|
|
100
|
+
```bash
|
|
101
|
+
./bin/dave.js --connect 'ws://localhost:8080/ws' --secret 'mysecret123'
|
|
102
|
+
```
|
|
103
|
+
- Chat with **code_agent** (main agent).
|
|
104
|
+
- Delegates automatically: "Manage todos", "Inspect @j-o-r/cli", "Update docs/codeserver-pattern.md".
|
|
105
|
+
|
|
106
|
+
**Piped (one-shot)**:
|
|
107
|
+
```bash
|
|
108
|
+
echo "List pending todos" | ./bin/dave.js --connect 'ws://localhost:8080/ws' --secret 'mysecret123'
|
|
109
|
+
echo "user_reset" | ./bin/dave.js --connect ... # Reset session
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Delegation Examples**:
|
|
113
|
+
- \`code_agent\`: "Use todo_agent to add 'Review PRs'"
|
|
114
|
+
- \`code_agent\`: "Call agent_docs to create nodejs-guide.md"
|
|
115
|
+
|
|
116
|
+
## Monitoring & Stopping with PM2
|
|
117
|
+
|
|
118
|
+
**Monitor**:
|
|
119
|
+
- `pm2 list` / `pm2 monit` (dashboard)
|
|
120
|
+
- `pm2 logs hello-dave_code_agent_8080` (agent logs)
|
|
121
|
+
- `pm2 logs *8080 --lines 50`
|
|
122
|
+
|
|
123
|
+
**Stop**:
|
|
124
|
+
```bash
|
|
125
|
+
pm2 stop hello-dave_*_8080 # All related
|
|
126
|
+
# Or delete:
|
|
127
|
+
pm2 delete hello-dave_code_agent_8080 hello-dave_todo_agent_8080 ...
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**Startup** (auto-restart on boot): `pm2 save && pm2 startup`
|
|
131
|
+
|
|
132
|
+
## Customization
|
|
133
|
+
|
|
134
|
+
### Adding Sub-Agents
|
|
135
|
+
Edit [agents/CodeServer](../agents/CodeServer):
|
|
136
|
+
```bash
|
|
137
|
+
# Add new agent
|
|
138
|
+
pm2 start "${SCRIPT_DIR}/newAgent.js" --name "${FOLDER}_new_agent_${PORT}" -- --connect "ws://127.0.0.1:${PORT}/ws" --secret "${SECRET}"
|
|
139
|
+
```
|
|
140
|
+
- Create \`newAgent.js\` like [agents/todo_agent.js](../agents/todo_agent.js): Set \`tool_call_name\`, prompt.
|
|
141
|
+
|
|
142
|
+
### Changing Tools
|
|
143
|
+
- Main server: Edit \`code_agent.js\`: \`--tools javascript,bash,ssh\`
|
|
144
|
+
- Sub-agents: \`agent.addGenericToolcall('read_file')\` etc. See [toolset.md](../toolset.md).
|
|
145
|
+
|
|
146
|
+
### Prompts/Models
|
|
147
|
+
- Per-agent: Edit JS files (e.g., \`options.model = 'grok-4-1-fast-reasoning'\`).
|
|
148
|
+
|
|
149
|
+
## Benefits
|
|
150
|
+
|
|
151
|
+
| Feature | Advantage |
|
|
152
|
+
|---------|-----------|
|
|
153
|
+
| **Persistent Sessions** | State in \`.cache/hello-dave/[name]/sessions/\`—no re-explaining. |
|
|
154
|
+
| **Delegation** | Main agent uses sub-agents as tools (parallel, specialized). |
|
|
155
|
+
| **No Heartbeat** | PM2 restarts on crash; no custom logic. |
|
|
156
|
+
| **Resource Efficient** | Shared context; subs only active on call. |
|
|
157
|
+
| **Portable** | Script auto-prefixes PM2 names by folder/port. |
|
|
158
|
+
|
|
159
|
+
## Troubleshooting
|
|
160
|
+
|
|
161
|
+
| Issue | Solution |
|
|
162
|
+
|-------|----------|
|
|
163
|
+
| **Port in use** | Change PORT; `lsof -i :8080` & `kill`. |
|
|
164
|
+
| **Secret mismatch** | Ensure exact match (no extra spaces). |
|
|
165
|
+
| **PM2 not found** | `npm i -g pm2`. |
|
|
166
|
+
| **Connection refused** | Wait 5s for server startup; check `pm2 logs`. |
|
|
167
|
+
| **No delegation** | Verify client tool names in JS (e.g., \`todo_agent\`). |
|
|
168
|
+
| **High memory** | `pm2 del *` or tweak \`contextWindow\`. |
|
|
169
|
+
|
|
170
|
+
Logs: `.cache/hello-dave/[agent]/sessions/*.ndjson` (use \`bin/dave.js --inspect log.ndjson\`).
|
|
171
|
+
|
|
172
|
+
## Integration with AgentManager
|
|
173
|
+
|
|
174
|
+
Built on [AgentManager](../docs/agent-manager.md):
|
|
175
|
+
|
|
176
|
+
- **Server**: `agent.start(PORT)` → WS server exposing \`code_agent\`.
|
|
177
|
+
- **Clients**: `agent.start(undefined, 'ws://...', undefined, 'todo_agent', 'desc')` → Attaches as tool.
|
|
178
|
+
|
|
179
|
+
**Tools**: Generic from [toolset.md](../docs/toolset.md) (e.g., \`execute_bash_script\`, \`javascript_interpreter\`).
|
|
180
|
+
|
|
181
|
+
Cross-links:
|
|
182
|
+
- [Prompt Class](../docs/prompt-class.md)
|
|
183
|
+
- [Generic Tools](../lib/genericToolset.js)
|
|
184
|
+
|
|
185
|
+
## References
|
|
186
|
+
|
|
187
|
+
- [PM2 Docs](https://pm2.keymetrics.io/docs/usage/quick-start/)
|
|
188
|
+
- Examples: [CodeServer](../agents/CodeServer), [code_agent.js](../agents/code_agent.js), [todo_agent.js](../agents/todo_agent.js), etc.
|
|
189
|
+
- Sessions: \`bin/dave.js --list\`
|
|
190
|
+
|
|
191
|
+
**Updated**: March 24, 2026
|