@j-o-r/hello-dave 0.0.6 → 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 +19 -33
- package/README.md +240 -0
- package/TODO.md +13 -0
- package/{examples → agents}/ask_agent.js +5 -5
- package/{examples → agents}/codeserver.sh +14 -14
- package/{examples → agents}/daisy_agent.js +5 -5
- package/{examples → agents}/docs_agent.js +5 -5
- package/{examples → agents}/gpt_agent.js +5 -5
- package/{examples → agents}/grok_agent.js +5 -5
- package/{examples → agents}/memory_agent.js +5 -5
- package/{examples → agents}/npm_agent.js +5 -5
- package/{examples → agents}/prompt_agent.js +5 -5
- package/agents/spawn_agent.js +137 -0
- package/{examples → agents}/test_agent.js +6 -6
- package/{examples → agents}/todo_agent.js +5 -5
- package/bin/codeDave +58 -0
- package/bin/dave.js +3 -5
- 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/AgentClient.js +111 -67
- package/lib/AgentManager.js +111 -80
- package/lib/AgentServer.js +144 -104
- package/lib/Cli.js +126 -93
- package/lib/Prompt.js +38 -5
- package/lib/Session.js +102 -79
- package/lib/ToolSet.js +79 -60
- package/lib/fafs.js +54 -19
- package/lib/genericToolset.js +129 -136
- package/lib/wsCli.js +50 -19
- package/lib/wsIO.js +10 -6
- package/package.json +3 -3
- package/types/AgentClient.d.ts +69 -35
- package/types/AgentManager.d.ts +50 -56
- package/types/AgentServer.d.ts +63 -16
- package/types/Cli.d.ts +56 -10
- package/types/Prompt.d.ts +36 -4
- package/types/Session.d.ts +23 -9
- package/types/ToolSet.d.ts +49 -32
- package/types/fafs.d.ts +68 -25
- package/types/wsCli.d.ts +14 -0
- package/types/wsIO.d.ts +9 -5
- package/utils/search_sessions.sh +100 -53
- package/bin/spawn_agent.js +0 -293
- package/lib/genericToolset.js.bak_syntax +0 -402
- /package/{examples → agents}/code_agent.js +0 -0
- /package/{examples → agents}/readme_agent.js +0 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { AgentManager } from '@j-o-r/hello-dave';
|
|
3
|
+
import { parseArgs } from '@j-o-r/sh';
|
|
4
|
+
import fs from 'fs'; // Added for local fallback
|
|
5
|
+
|
|
6
|
+
const name = 'spawn_agent';
|
|
7
|
+
const api = 'xai';
|
|
8
|
+
let secret = '';
|
|
9
|
+
|
|
10
|
+
const args = parseArgs();
|
|
11
|
+
|
|
12
|
+
let input;
|
|
13
|
+
if (args._.length === 1 && typeof args._[0] === 'string' && args._[0].trim() !== '') {
|
|
14
|
+
input = args._[0].trim();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const help = args['help'] || false;
|
|
18
|
+
const connect = args['connect'] ? args['connect'] : undefined;
|
|
19
|
+
const serve = args['serve'] ? parseInt(args['serve']) : undefined;
|
|
20
|
+
|
|
21
|
+
const options = { tools: [] };
|
|
22
|
+
options.tools.push({ type: 'web_search' });
|
|
23
|
+
|
|
24
|
+
if (args['secret']) {
|
|
25
|
+
secret = args['secret'];
|
|
26
|
+
}
|
|
27
|
+
if (args['model'] || true) {
|
|
28
|
+
options.model = args['model'] || 'grok-4-fast-reasoning';
|
|
29
|
+
}
|
|
30
|
+
if (args['temperature']) {
|
|
31
|
+
options.temperature = parseFloat(args['temperature']);
|
|
32
|
+
}
|
|
33
|
+
if (args['tokens']) {
|
|
34
|
+
options.max_output_tokens = parseInt(args['tokens']);
|
|
35
|
+
}
|
|
36
|
+
if (args['top_p']) {
|
|
37
|
+
options.top_p = parseFloat(args['top_p']);
|
|
38
|
+
}
|
|
39
|
+
if (true) {
|
|
40
|
+
options.reasoning = { effort: 'medium', summary: 'auto' };
|
|
41
|
+
}
|
|
42
|
+
const toolsetMode = 'auto';
|
|
43
|
+
const contextWindow = args['context'] ? parseInt(args['context']) : 250000;
|
|
44
|
+
|
|
45
|
+
function printHelp() {
|
|
46
|
+
console.log(`'${name} --help' You are looking at it.
|
|
47
|
+
|
|
48
|
+
## USAGE MODES:
|
|
49
|
+
|
|
50
|
+
### 1. Direct Call (One-Shot, Positional ONLY):
|
|
51
|
+
./${name}.js "Create a code agent" [--options]
|
|
52
|
+
|
|
53
|
+
### 2. Interactive CLI (no positional arg):
|
|
54
|
+
./${name}.js [--options]
|
|
55
|
+
|
|
56
|
+
### 3. WS Server (no positional arg):
|
|
57
|
+
./${name}.js --serve 8080 [--secret mysecret] [--options]
|
|
58
|
+
|
|
59
|
+
### 4. WS Client (no positional arg):
|
|
60
|
+
./${name}.js --connect ws://127.0.0.1:8080/ws --secret mysecret [--options]
|
|
61
|
+
|
|
62
|
+
### 5. Hybrid (Server + Client, no positional arg):
|
|
63
|
+
./${name}.js --serve 8081 --connect ws://other:8080/ws [--secret ...] [--options]
|
|
64
|
+
|
|
65
|
+
## PORTABILITY NOTES:
|
|
66
|
+
- **Tools follow YOUR CWD** (e.g., cd /tmp/proj && ./spawn_agent.js → tools in /tmp/proj).
|
|
67
|
+
- **Hybrid Modes**: PROJECT (agents/*.js exist): Auto-deploy/test. FRESH (empty agents/): Code + manual bash.
|
|
68
|
+
- **Custom Tools**: natives=web_search, generics=read_file, custom={type:'git_diff',...}
|
|
69
|
+
|
|
70
|
+
## OPTIONS:
|
|
71
|
+
--model [grok-4-fast-reasoning|...] (default: grok-4-fast-reasoning)
|
|
72
|
+
--temperature [float] (0.8)
|
|
73
|
+
--tokens [number]
|
|
74
|
+
--top_p [float]
|
|
75
|
+
--context [number] (250k)
|
|
76
|
+
|
|
77
|
+
## Examples:
|
|
78
|
+
"Create coderev: desc=Git analyzer, natives=web_search, generics=read_file execute_bash_script, custom=options.tools.push({type:'git_diff',description:'...',parameters:{...}})"
|
|
79
|
+
`);
|
|
80
|
+
process.exit();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (help) {
|
|
84
|
+
printHelp();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const tool_call_name = 'spawn_agent';
|
|
88
|
+
const tool_call_description = `Portable creator for CLI/WS agents + PM2 launchers. Tools use exec CWD (/tmp OK). PROJECT (agents/*.js >0): Full auto. FRESH: Manual code/bash.
|
|
89
|
+
|
|
90
|
+
Test new agent: ./agents/NEW.js --help | 'describe' | --serve 8081 --secret abc
|
|
91
|
+
|
|
92
|
+
Custom ex: natives=[{type:'mytool'}], generics=read_file
|
|
93
|
+
|
|
94
|
+
Live prompt: https://codeberg.org/duin/hello-dave/raw/branch/main/docs/prompt/spawn_agent.md`.trim();
|
|
95
|
+
|
|
96
|
+
const REPO_URL = 'https://codeberg.org/duin/hello-dave';
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
async function fetchLivePrompt() {
|
|
100
|
+
// Priority 1: Remote
|
|
101
|
+
const promptUrl = `${REPO_URL}/raw/branch/main/docs/prompt/spawn_agent.md`;
|
|
102
|
+
const response = await fetch(promptUrl);
|
|
103
|
+
if (!response.ok) {
|
|
104
|
+
throw new Error(`HTTP ${response.status}`);
|
|
105
|
+
}
|
|
106
|
+
return await response.text();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const agent = new AgentManager({ name, secret });
|
|
110
|
+
|
|
111
|
+
const prompt = await fetchLivePrompt();
|
|
112
|
+
|
|
113
|
+
agent.setup({
|
|
114
|
+
prompt,
|
|
115
|
+
api,
|
|
116
|
+
options,
|
|
117
|
+
toolsetMode,
|
|
118
|
+
contextWindow
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
agent.addGenericToolcall('execute_bash_script');
|
|
122
|
+
agent.addGenericToolcall('read_file');
|
|
123
|
+
agent.addGenericToolcall('write_file');
|
|
124
|
+
agent.addGenericToolcall('javascript_interpreter');
|
|
125
|
+
|
|
126
|
+
const cliIntro = `🤖 ${name} (${options.model}) ready! (context: ${contextWindow})
|
|
127
|
+
|
|
128
|
+
Portable Creator: PROJECT (agents/*.js exist): Auto. FRESH (empty): Manual code.
|
|
129
|
+
|
|
130
|
+
Ex: "Create testagent: desc=Tester, natives=web_search"`.trim();
|
|
131
|
+
|
|
132
|
+
if (input) {
|
|
133
|
+
const RES = await agent.directCall(input);
|
|
134
|
+
console.log(RES);
|
|
135
|
+
} else {
|
|
136
|
+
await agent.start(serve, connect, cliIntro, tool_call_name, tool_call_description);
|
|
137
|
+
}
|
|
@@ -55,19 +55,19 @@ function printHelp() {
|
|
|
55
55
|
## USAGE MODES:
|
|
56
56
|
|
|
57
57
|
### 1. Direct Call (One-Shot, Positional ONLY):
|
|
58
|
-
./
|
|
58
|
+
./agents/${name}.js "Generate test for toolset.js" [--options]
|
|
59
59
|
|
|
60
60
|
### 2. Interactive CLI (no positional arg):
|
|
61
|
-
./
|
|
61
|
+
./agents/${name}.js [--options]
|
|
62
62
|
|
|
63
63
|
### 3. WS Server (no positional arg):
|
|
64
|
-
./
|
|
64
|
+
./agents/${name}.js --serve 8080 [--secret mysecret] [--options]
|
|
65
65
|
|
|
66
66
|
### 4. WS Client (no positional arg):
|
|
67
|
-
./
|
|
67
|
+
./agents/${name}.js --connect ws://127.0.0.1:8080/ws --secret mysecret [--options]
|
|
68
68
|
|
|
69
69
|
### 5. Hybrid (Server + Client, no positional arg):
|
|
70
|
-
./
|
|
70
|
+
./agents/${name}.js --serve 8081 --connect ws://other:8080/ws [--secret ...] [--options]
|
|
71
71
|
|
|
72
72
|
## SERVER OPTIONS EXPLAINED:
|
|
73
73
|
--serve [port]: Starts WebSocket SERVER at ws://127.0.0.1:[port]/ws. Allows other agents (--connect) to connect and use this agent as a remote TOOL (e.g., 'test_agent'). Runs indefinitely until Ctrl+C.
|
|
@@ -108,7 +108,7 @@ const prompt = `You are TestAgent, the specialized testing agent for CodeServer
|
|
|
108
108
|
- Tests must use: \`import { Test, assert, jsType } from '@j-o-r/sh';\`
|
|
109
109
|
- Structure: shebang \`#!/usr/bin/env node\`, fluent Test API (\`const t = new Test(); t.add('desc', () => { assert... }); await t.run();\`), exit(1) on errors.
|
|
110
110
|
- After write_file to scenarios/MODULE.test.js, ensure executable: \`chmod +x scenarios/MODULE.test.js\`
|
|
111
|
-
- Leverage project utilities: test existing files (
|
|
111
|
+
- Leverage project utilities: test existing files (agents/*.js, toolset.js, agents, SH commands, etc.) using read_file, execute_bash_script (ls/cat), npm_module_inspector.
|
|
112
112
|
|
|
113
113
|
**WHAT TO TEST** (discover dynamically):
|
|
114
114
|
1. Project scripts: e.g., parseArgs, AgentManager flows, toolsets.
|
|
@@ -55,19 +55,19 @@ function printHelp() {
|
|
|
55
55
|
## USAGE MODES:
|
|
56
56
|
|
|
57
57
|
### 1. Direct Call (One-Shot, Positional ONLY):
|
|
58
|
-
./
|
|
58
|
+
./agents/${name}.js "List tasks" [--options]
|
|
59
59
|
|
|
60
60
|
### 2. Interactive CLI (no positional arg):
|
|
61
|
-
./
|
|
61
|
+
./agents/${name}.js [--options]
|
|
62
62
|
|
|
63
63
|
### 3. WS Server (no positional arg):
|
|
64
|
-
./
|
|
64
|
+
./agents/${name}.js --serve 8080 [--secret mysecret] [--options]
|
|
65
65
|
|
|
66
66
|
### 4. WS Client (no positional arg):
|
|
67
|
-
./
|
|
67
|
+
./agents/${name}.js --connect ws://127.0.0.1:8080/ws --secret mysecret [--options]
|
|
68
68
|
|
|
69
69
|
### 5. Hybrid (Server + Client, no positional arg):
|
|
70
|
-
./
|
|
70
|
+
./agents/${name}.js --serve 8081 --connect ws://other:8080/ws [--secret ...] [--options]
|
|
71
71
|
|
|
72
72
|
## SERVER OPTIONS EXPLAINED:
|
|
73
73
|
--serve [port]: Starts WebSocket SERVER at ws://127.0.0.1:[port]/ws. Allows other agents (--connect) to connect and use this agent as a remote TOOL (e.g., 'todo_agent'). Runs indefinitely until Ctrl+C.
|
package/bin/codeDave
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
if [ $# -lt 1 ] || [ $# -gt 2 ]; then
|
|
3
|
+
echo "Usage: $0 <PORT> [SECRET] # PORT: 1024-65535, SECRET: optional (defaults to '123')"
|
|
4
|
+
exit 1
|
|
5
|
+
fi
|
|
6
|
+
|
|
7
|
+
PORT="$1"
|
|
8
|
+
SECRET="${2:-123}"
|
|
9
|
+
|
|
10
|
+
if [ -z "$SECRET" ] || [ ${#SECRET} -lt 3 ]; then
|
|
11
|
+
echo "Error: SECRET must be at least 3 characters: '$SECRET'"
|
|
12
|
+
exit 1
|
|
13
|
+
fi
|
|
14
|
+
|
|
15
|
+
if ! [[ "$PORT" =~ ^[0-9]+$ ]] || [ "$PORT" -lt 1024 ] || [ "$PORT" -gt 65535 ]; then
|
|
16
|
+
echo "Error: Invalid port number: $PORT. Must be between 1024 and 65535."
|
|
17
|
+
exit 1
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
# Compute canonical paths relative to THIS script's real location (resolves symlinks for global npm installs)
|
|
21
|
+
SOURCE="${BASH_SOURCE[0]}"
|
|
22
|
+
while [ -h "$SOURCE" ]; do
|
|
23
|
+
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
|
|
24
|
+
SOURCE="$(readlink "$SOURCE")"
|
|
25
|
+
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
|
|
26
|
+
done
|
|
27
|
+
SCRIPT_DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
|
|
28
|
+
PROJECT_DIR="$( cd -P "$( dirname "$SCRIPT_DIR" )" >/dev/null 2>&1 && pwd )"
|
|
29
|
+
|
|
30
|
+
# FOLDER: basename of CURRENT WORKING DIRECTORY (pwd) for per-project PM2 prefixes (e.g., myproject_code_8080)
|
|
31
|
+
# This allows multi-project usage without name conflicts; PROJECT_DIR remains package location for agents/
|
|
32
|
+
FOLDER=$(basename "$(pwd)")
|
|
33
|
+
|
|
34
|
+
echo "Starting codeDave on port ${PORT} in folder '${FOLDER}' (SCRIPT_DIR: ${SCRIPT_DIR}) with SECRET '${SECRET}'..."
|
|
35
|
+
|
|
36
|
+
# Delete existing processes with folder_port suffix
|
|
37
|
+
pm2 delete "${FOLDER}_code_${PORT}" 2>/dev/null || true
|
|
38
|
+
pm2 delete "${FOLDER}_todo_${PORT}" 2>/dev/null || true
|
|
39
|
+
pm2 delete "${FOLDER}_readme_${PORT}" 2>/dev/null || true
|
|
40
|
+
pm2 delete "${FOLDER}_npm_${PORT}" 2>/dev/null || true
|
|
41
|
+
pm2 delete "${FOLDER}_docs_${PORT}" 2>/dev/null || true
|
|
42
|
+
pm2 delete "${FOLDER}_test_${PORT}" 2>/dev/null || true
|
|
43
|
+
pm2 delete "${FOLDER}_memory_${PORT}" 2>/dev/null || true
|
|
44
|
+
pm2 delete "${FOLDER}_spawn_${PORT}" 2>/dev/null || true
|
|
45
|
+
|
|
46
|
+
# Spawn main Agent / server (absolute paths to scripts)
|
|
47
|
+
pm2 start "${PROJECT_DIR}/agents/code_agent.js" --name "${FOLDER}_code_${PORT}" -- --serve "${PORT}" --tools javascript --secret "${SECRET}"
|
|
48
|
+
# Attach clients
|
|
49
|
+
pm2 start "${PROJECT_DIR}/agents/todo_agent.js" --name "${FOLDER}_todo_${PORT}" -- --connect "ws://127.0.0.1:${PORT}/ws" --secret "${SECRET}"
|
|
50
|
+
pm2 start "${PROJECT_DIR}/agents/readme_agent.js" --name "${FOLDER}_readme_${PORT}" -- --connect "ws://127.0.0.1:${PORT}/ws" --secret "${SECRET}"
|
|
51
|
+
pm2 start "${PROJECT_DIR}/agents/npm_agent.js" --name "${FOLDER}_npm_${PORT}" -- --connect "ws://127.0.0.1:${PORT}/ws" --secret "${SECRET}"
|
|
52
|
+
pm2 start "${PROJECT_DIR}/agents/docs_agent.js" --name "${FOLDER}_docs_${PORT}" -- --connect "ws://127.0.0.1:${PORT}/ws" --secret "${SECRET}"
|
|
53
|
+
pm2 start "${PROJECT_DIR}/agents/test_agent.js" --name "${FOLDER}_test_${PORT}" -- --connect "ws://127.0.0.1:${PORT}/ws" --secret "${SECRET}"
|
|
54
|
+
pm2 start "${PROJECT_DIR}/agents/memory_agent.js" --name "${FOLDER}_memory_${PORT}" -- --connect "ws://127.0.0.1:${PORT}/ws" --secret "${SECRET}"
|
|
55
|
+
pm2 start "${PROJECT_DIR}/agents/spawn_agent.js" --name "${FOLDER}_spawn_${PORT}" -- --connect "ws://127.0.0.1:${PORT}/ws" --secret "${SECRET}"
|
|
56
|
+
|
|
57
|
+
echo "codeDave processes spawned with prefix '${FOLDER}_' and suffix _${PORT}. Check with: pm2 list | grep '${FOLDER}_${PORT}'"
|
|
58
|
+
echo "dave --connect ws://127.0.0.1:${PORT}/ws --secret '$SECRET'"
|
package/bin/dave.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env -S node
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import cli from '@j-o-r/cli';
|
|
4
|
-
import wsCli from '
|
|
5
|
-
import wsIO from '../lib/wsIO.js';
|
|
6
|
-
import { AgentManager } from '@j-o-r/hello-dave';
|
|
4
|
+
import { AgentManager, wsCli, wsIO } from '@j-o-r/hello-dave';
|
|
7
5
|
import { SH, parseArgs, readIn, bashEscape } from '@j-o-r/sh';
|
|
8
6
|
import { fileURLToPath } from 'node:url';
|
|
9
7
|
|
|
@@ -31,7 +29,7 @@ FLAGS:
|
|
|
31
29
|
Remote: bin/dave.js --ask --connect 'ws://localhost:8080' --secret '123'
|
|
32
30
|
Piped local: echo "predict the weather" | bin/dave.js --ask
|
|
33
31
|
Piped remote: echo "predict the weather" | bin/dave.js --ask --connect 'ws://...' --secret '123'
|
|
34
|
-
--code [port] [--secret "..."] : Launch CodeServer PM2 cluster via
|
|
32
|
+
--code [port] [--secret "..."] : Launch CodeServer PM2 cluster via agents/codeserver.sh
|
|
35
33
|
Usage: bin/dave.js --code 8080 --secret 123
|
|
36
34
|
`);
|
|
37
35
|
process.exit(exitCode)
|
|
@@ -193,4 +191,4 @@ ${name} (${options.model}).
|
|
|
193
191
|
const RES = await SH`${server} ${port} ${bashEscape(secret)}`.run();
|
|
194
192
|
console.log(RES);
|
|
195
193
|
process.exit(0);
|
|
196
|
-
}
|
|
194
|
+
}
|
|
@@ -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
|
+
|