@j-o-r/hello-dave 0.1.1 → 0.1.5

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.
Files changed (173) hide show
  1. package/CHANGELOG.md +42 -25
  2. package/README.md +81 -221
  3. package/TODO.md +173 -35
  4. package/agents/agent_creator.js +105 -0
  5. package/agents/agent_creator.prompt.md +371 -0
  6. package/agents/ask_agent.js +64 -127
  7. package/agents/claude_agent.js +68 -0
  8. package/agents/code_agent.js +55 -135
  9. package/agents/code_agent.prompt.md +50 -0
  10. package/agents/echo_agent.js +76 -0
  11. package/agents/financial_expert.js +75 -0
  12. package/agents/gpt_agent.js +52 -103
  13. package/agents/gpt_code.js +81 -0
  14. package/agents/grok_agent.js +58 -114
  15. package/agents/minimax_agent.js +92 -0
  16. package/agents/mureka_agent.js +77 -0
  17. package/agents/planner_agent.js +172 -0
  18. package/agents/stability_agent.js +87 -0
  19. package/agents/test_agent.js +75 -157
  20. package/agents/weather_agent.js +73 -0
  21. package/agents/workflow_agent.js +189 -0
  22. package/bin/dave.js +436 -184
  23. package/docs/bin-dave.md +85 -35
  24. package/docs/cdn-ssh.md +100 -0
  25. package/docs/creating-agents.md +301 -0
  26. package/docs/creating-toolsets.md +336 -0
  27. package/docs/docs-organization.md +48 -0
  28. package/docs/project-overview.md +86 -51
  29. package/lib/API/elevenlabs.io/music.compose.md +441 -0
  30. package/lib/API/elevenlabs.io/music.create-composition-plan.md +370 -0
  31. package/lib/API/elevenlabs.io/music.stream.md +425 -0
  32. package/lib/API/lalal.ai/lalal.js +445 -0
  33. package/lib/API/lalal.ai/openapi.json +2614 -0
  34. package/lib/API/minimax/ImageToolset.js +82 -37
  35. package/lib/API/minimax/MusicToolset.js +125 -79
  36. package/lib/API/minimax/VideoToolset.js +170 -167
  37. package/lib/API/minimax/image.js +5 -1
  38. package/lib/API/minimax/music.js +210 -23
  39. package/lib/API/minimax/video.js +242 -53
  40. package/lib/API/mureka/MusicToolset.js +646 -0
  41. package/lib/API/mureka/README.md +41 -0
  42. package/lib/API/mureka/index.js +7 -0
  43. package/lib/API/mureka/music.js +658 -0
  44. package/lib/API/openai.com/index.js +7 -0
  45. package/lib/API/openai.com/{reponses/text.js → responses.js} +64 -18
  46. package/lib/API/openai.com/video.create.character.md +40 -0
  47. package/lib/API/openai.com/video.create.md +219 -0
  48. package/lib/API/openai.com/video.delete.md +44 -0
  49. package/lib/API/openai.com/video.download.md +31 -0
  50. package/lib/API/openai.com/video.edit.md +155 -0
  51. package/lib/API/openai.com/video.extend.md +166 -0
  52. package/lib/API/openai.com/video.fetch.character.md +43 -0
  53. package/lib/API/openai.com/video.js +784 -0
  54. package/lib/API/openai.com/video.list.md +201 -0
  55. package/lib/API/openai.com/video.remix.md +175 -0
  56. package/lib/API/openai.com/video.retrieve.md +139 -0
  57. package/lib/API/openai.com/videoToolset.js +616 -0
  58. package/lib/API/stability.ai/ImageToolset.js +131 -40
  59. package/lib/API/stability.ai/MusicToolset.js +79 -47
  60. package/lib/API/stability.ai/audio.js +63 -131
  61. package/lib/API/x.ai/chat.responses.md +1040 -0
  62. package/lib/API/x.ai/image.js +229 -59
  63. package/lib/API/x.ai/imageToolset.js +376 -0
  64. package/lib/API/x.ai/index.js +1 -1
  65. package/lib/API/x.ai/responses.js +9 -18
  66. package/lib/Agent.js +271 -0
  67. package/lib/Agent.js.old +284 -0
  68. package/lib/AgentLauncher.js +593 -0
  69. package/lib/Cli.js +87 -13
  70. package/lib/Prompt.js +23 -1
  71. package/lib/Session.js +5 -4
  72. package/lib/ToolSet.js +102 -6
  73. package/lib/agentLoader.js +369 -0
  74. package/lib/cdn.js +67 -231
  75. package/lib/{CdnToolset.js → cdnToolset.js} +47 -64
  76. package/lib/defaultToolsets.js +43 -0
  77. package/lib/fafs.js +1 -1
  78. package/lib/genericToolset.js +442 -119
  79. package/lib/handOffToolset.js +179 -0
  80. package/lib/index.js +34 -27
  81. package/lib/toolsetLoader.js +248 -0
  82. package/package.json +10 -4
  83. package/types/API/lalal.ai/lalal.d.ts +116 -0
  84. package/types/API/minimax/image.d.ts +2 -1
  85. package/types/API/minimax/music.d.ts +189 -26
  86. package/types/API/minimax/video.d.ts +100 -31
  87. package/types/API/mureka/index.d.ts +7 -0
  88. package/types/API/mureka/music.d.ts +472 -0
  89. package/types/API/openai.com/index.d.ts +7 -0
  90. package/types/API/openai.com/{reponses/text.d.ts → responses.d.ts} +11 -11
  91. package/types/API/openai.com/video.d.ts +409 -0
  92. package/types/API/openai.com/videoToolset.d.ts +24 -0
  93. package/types/API/stability.ai/audio.d.ts +14 -103
  94. package/types/API/stability.ai/image.d.ts +2 -2
  95. package/types/API/x.ai/image.d.ts +138 -26
  96. package/types/API/x.ai/imageToolset.d.ts +3 -0
  97. package/types/API/x.ai/index.d.ts +1 -1
  98. package/types/API/x.ai/responses.d.ts +4 -4
  99. package/types/Agent.d.ts +123 -0
  100. package/types/AgentLauncher.d.ts +250 -0
  101. package/types/Cli.d.ts +28 -8
  102. package/types/Prompt.d.ts +23 -5
  103. package/types/Session.d.ts +1 -1
  104. package/types/ToolSet.d.ts +10 -0
  105. package/types/agentLoader.d.ts +78 -0
  106. package/types/cdn.d.ts +15 -90
  107. package/types/defaultToolsets.d.ts +9 -0
  108. package/types/fafs.d.ts +1 -1
  109. package/types/genericToolset.d.ts +1 -1
  110. package/types/handOffToolset.d.ts +28 -0
  111. package/types/index.d.ts +19 -17
  112. package/types/toolsetLoader.d.ts +114 -0
  113. package/utils/format_log.js +101 -23
  114. package/utils/launch_agent.js +18 -0
  115. package/utils/list_sessions.sh +13 -5
  116. package/utils/search_sessions.sh +65 -29
  117. package/utils/toolsets.js +33 -0
  118. package/README.md.bak.1779452127 +0 -240
  119. package/agents/codeserver.sh +0 -47
  120. package/agents/daisy_agent.js +0 -173
  121. package/agents/docs_agent.js +0 -148
  122. package/agents/memory_agent.js +0 -263
  123. package/agents/minimax.js +0 -173
  124. package/agents/npm_agent.js +0 -202
  125. package/agents/prompt_agent.js +0 -133
  126. package/agents/readme_agent.js +0 -148
  127. package/agents/spawn_agent.js +0 -160
  128. package/agents/stability.js +0 -173
  129. package/agents/todo_agent.js +0 -175
  130. package/bin/codeDave +0 -58
  131. package/docs/agent-dave-websocket-protocol.md +0 -180
  132. package/docs/agent-manager.md +0 -244
  133. package/docs/codeserver-pattern.md +0 -191
  134. package/docs/generic-toolset.md +0 -326
  135. package/docs/howtos/agent-networking.md +0 -253
  136. package/docs/howtos/spawn-agents.md.bak +0 -200
  137. package/docs/howtos/spawn-agents.md.bak_new +0 -200
  138. package/docs/multi-agent-clusters.md +0 -265
  139. package/docs/music-toolsets.md +0 -137
  140. package/docs/path-resolution-best-practices.md +0 -104
  141. package/docs/plans/minimax-music-generation.md +0 -80
  142. package/docs/plans/unified-agent-architecture.md +0 -146
  143. package/docs/plans/websocket-streaming-plan.md.bak +0 -317
  144. package/docs/prompt/spawn_agent.md +0 -175
  145. package/docs/prompt/spawn_agent.md.bak +0 -201
  146. package/docs/prompt/task_clarification_and_documentation.md +0 -35
  147. package/docs/prompt-class.md +0 -141
  148. package/docs/todo-archive-infra-2026-04-21.md +0 -15
  149. package/docs/todo-archive-v0.0.8.md +0 -1
  150. package/docs/todo-archive-v0.1.0.md +0 -32
  151. package/docs/todo-archive.md +0 -44
  152. package/docs/tools-syntax-validation.md +0 -121
  153. package/docs/toolset.md +0 -164
  154. package/docs/xai-responses.md +0 -111
  155. package/docs/xai_collections.md +0 -106
  156. package/lib/API/x.ai/ImageToolset.js +0 -165
  157. package/lib/API/x.ai/text.js +0 -415
  158. package/lib/AgentClient.js +0 -248
  159. package/lib/AgentManager.js +0 -245
  160. package/lib/AgentServer.js +0 -404
  161. package/lib/wsCli.js +0 -287
  162. package/lib/wsIO.js +0 -90
  163. package/types/API/x.ai/text.d.ts +0 -286
  164. package/types/AgentClient.d.ts +0 -109
  165. package/types/AgentManager.d.ts +0 -100
  166. package/types/AgentServer.d.ts +0 -89
  167. package/types/wsCli.d.ts +0 -17
  168. package/types/wsIO.d.ts +0 -30
  169. package/utils/test.sh +0 -46
  170. /package/docs/{suggestions.md → _notes/token-counts.md} +0 -0
  171. /package/lib/API/openai.com/{reponses/MESSAGES.md → MESSAGES.md} +0 -0
  172. /package/types/API/{x.ai/ImageToolset.d.ts → mureka/MusicToolset.d.ts} +0 -0
  173. /package/types/{CdnToolset.d.ts → cdnToolset.d.ts} +0 -0
@@ -1,33 +1,111 @@
1
1
  #!/usr/bin/env -S node
2
- // Formatted output of hello-dave cache files [*.ndjson]
3
- import { CacheSync } from "@j-o-r/cache";
2
+ // Formatted output of @j-o-r/hello-dave cache files [*.ndjson]
3
+ import { open } from 'node:fs/promises';
4
4
  import path from 'node:path';
5
- import { parseArgs, readIn } from '@j-o-r/sh';
6
5
 
7
- const args = parseArgs();
8
- if (args._.length !== 1) {
9
- console.log(
10
- `File as an argument`.trim()
11
- )
6
+ const DEFAULT_LAST = 20;
7
+ const CHUNK_SIZE = 64 * 1024;
8
+
9
+ /**
10
+ * Print command usage and exit.
11
+ * @param {number} code Process exit code.
12
+ * @returns {never}
13
+ */
14
+ function usage(code = 0) {
15
+ const script = path.basename(process.argv[1] ?? 'format_log.js');
16
+ console.log(`Usage: ${script} [--last 20|-n 20] <file.ndjson>`);
17
+ process.exit(code);
12
18
  }
13
- const filePath = args._[0]; // or any relative/absolute path
14
19
 
15
- // folder
16
- const folder = path.resolve(path.dirname(filePath)); // 'a/b'
20
+ /**
21
+ * Parse CLI arguments.
22
+ * @param {string[]} argv Raw CLI arguments.
23
+ * @returns {{ filePath: string, last: number }} Parsed arguments.
24
+ */
25
+ function parseCliArgs(argv) {
26
+ let last = DEFAULT_LAST;
27
+ const files = [];
28
+
29
+ for (let i = 0; i < argv.length; i += 1) {
30
+ const arg = argv[i];
17
31
 
18
- // filename without extension
19
- const { name } = path.parse(filePath); // name = 'c'
20
- // or: const name2 = path.basename(filePath, path.extname(filePath));
32
+ if (arg === '--help' || arg === '-h') usage(0);
21
33
 
22
- // extension (including dot)
23
- const ext = path.extname(filePath).slice(1); // '.txt'
34
+ if (arg === '--last' || arg === '-n') {
35
+ const value = argv[i + 1];
36
+ if (!value) usage(1);
37
+ last = Number.parseInt(value, 10);
38
+ i += 1;
39
+ continue;
40
+ }
24
41
 
25
- console.log({ folder, name, ext });
42
+ if (arg.startsWith('--last=')) {
43
+ last = Number.parseInt(arg.slice('--last='.length), 10);
44
+ continue;
45
+ }
26
46
 
27
- const c = new CacheSync(folder, false, ext);
28
- const content = c.read(name);
29
- if (!content) {
30
- console.error(`Not Found: ${filePath}`);
31
- process.exit(1);
47
+ files.push(arg);
48
+ }
49
+
50
+ if (files.length !== 1 || !Number.isSafeInteger(last) || last < 1) usage(1);
51
+ return { filePath: files[0], last };
32
52
  }
33
- console.log(JSON.stringify(content, null, ' '));
53
+
54
+ /**
55
+ * Read the last non-empty lines from a text file without loading the whole file.
56
+ * @param {string} filePath Path to the text/NDJSON file.
57
+ * @param {number} count Number of bottom entries to read.
58
+ * @returns {Promise<string[]>} Last non-empty lines in original order.
59
+ */
60
+ async function readLastLines(filePath, count) {
61
+ const file = await open(filePath, 'r');
62
+
63
+ try {
64
+ const { size } = await file.stat();
65
+ const chunks = [];
66
+ let position = size;
67
+ let newlineCount = 0;
68
+
69
+ while (position > 0 && newlineCount <= count) {
70
+ const readSize = Math.min(CHUNK_SIZE, position);
71
+ position -= readSize;
72
+
73
+ const buffer = Buffer.allocUnsafe(readSize);
74
+ await file.read(buffer, 0, readSize, position);
75
+ chunks.unshift(buffer);
76
+
77
+ for (let i = 0; i < readSize; i += 1) {
78
+ if (buffer[i] === 0x0a) newlineCount += 1;
79
+ }
80
+ }
81
+
82
+ return Buffer.concat(chunks)
83
+ .toString('utf8')
84
+ .split(/\r?\n/u)
85
+ .filter((line) => line.trim() !== '')
86
+ .slice(-count);
87
+ } finally {
88
+ await file.close();
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Parse NDJSON lines as JSON objects.
94
+ * @param {string[]} lines NDJSON lines.
95
+ * @returns {unknown[]} Parsed events.
96
+ */
97
+ function parseNdjsonLines(lines) {
98
+ return lines.map((line, index) => {
99
+ try {
100
+ return JSON.parse(line);
101
+ } catch (error) {
102
+ throw new Error(`Invalid JSON on selected line ${index + 1}: ${error.message}`);
103
+ }
104
+ });
105
+ }
106
+
107
+ const { filePath, last } = parseCliArgs(process.argv.slice(2));
108
+ const fullPath = path.resolve(filePath);
109
+ const lines = await readLastLines(fullPath, last);
110
+ const events = parseNdjsonLines(lines);
111
+ console.log(JSON.stringify(events, null, 2));
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * utils/launch_agent.js
4
+ *
5
+ * Tiny CLI wrapper.
6
+ *
7
+ * All logic lives in AgentLauncher.
8
+ *
9
+ * Usage:
10
+ * node utils/launch_agent.js weather_agent
11
+ * node utils/launch_agent.js weather_agent "What is the weather in Miami?"
12
+ */
13
+
14
+ import AgentLauncher from '../lib/AgentLauncher.js';
15
+
16
+ const launcher = new AgentLauncher({ from: import.meta.url });
17
+ await launcher.load();
18
+ await launcher.run();
@@ -1,7 +1,7 @@
1
1
  #!/bin/bash
2
2
  # List unique sessions (once) per agent across all apps hierarchically, with latest mod timestamp.
3
3
  # Strips trailing _[0-9]+, converts _+ to spaces, trims. Picks newest mtime per base name.
4
- # FIXED: Reset assoc array per agent; skip empty agents.
4
+ # Only prints app folders that contain at least one session log.
5
5
 
6
6
  CACHE_BASE=".cache"
7
7
  shopt -s nullglob
@@ -10,13 +10,16 @@ for app_dir in "$CACHE_BASE"/*/; do
10
10
  if [[ ! -d "$app_dir" ]]; then
11
11
  continue
12
12
  fi
13
+
13
14
  app_name=$(basename "$app_dir")
14
- echo "$app_name:"
15
15
  has_sessions=false
16
+ app_output=""
17
+
16
18
  for sessions_dir in "$app_dir"/*/sessions/; do
17
19
  if [[ ! -d "$sessions_dir" ]]; then
18
20
  continue
19
21
  fi
22
+
20
23
  agent=$(basename "$(dirname "$sessions_dir")")
21
24
 
22
25
  unset timestamps || true
@@ -33,14 +36,19 @@ for app_dir in "$CACHE_BASE"/*/; do
33
36
  done
34
37
 
35
38
  if [[ ${#timestamps[@]} -gt 0 ]]; then
36
- echo " $agent:"
37
- for base in "${!timestamps[@]}"; do
39
+ session_output=$(for base in "${!timestamps[@]}"; do
38
40
  echo " - $base ... (${timestamps[$base]})"
39
- done | sort
41
+ done | sort)
42
+
43
+ app_output+=" $agent:"$'\n'
44
+ app_output+="$session_output"$'\n'
40
45
  has_sessions=true
41
46
  fi
42
47
  done
48
+
43
49
  if [[ "$has_sessions" == true ]]; then
50
+ echo "$app_name:"
51
+ printf '%s' "$app_output"
44
52
  echo
45
53
  fi
46
54
  done
@@ -31,7 +31,17 @@ while [ $# -gt 0 ]; do
31
31
  esac
32
32
  done
33
33
 
34
- # 1st pass: matching sessions/files
34
+ # Helper: does this file contain the query (case-insensitive)?
35
+ has_query() {
36
+ grep -qiE "$QUERY" "$1" 2>/dev/null
37
+ }
38
+
39
+ # Helper: does this file contain a user or assistant role line?
40
+ has_user_or_assistant_role() {
41
+ grep -qiE '"role"\s*:\s*"(user|assistant)"' "$1" 2>/dev/null
42
+ }
43
+
44
+ # 1st pass: find sessions that have at least one matching file
35
45
  declare -a matching_sessions=()
36
46
  total_files=0
37
47
  scanned=0
@@ -45,40 +55,52 @@ while IFS= read -r -d '' sess_dir <&3; do
45
55
  for file in "$sess_dir"/*.ndjson; do
46
56
  base=$(basename "$file" .ndjson)
47
57
  has_match=false
48
- # Filename
49
- if echo "$base" | grep -qiE "$QUERY"; then
50
- has_match=true
51
- # Content (role-filtered if enabled)
52
- elif ! $BRIEF && [ "$ROLE_FILTER" = true ] && \
53
- awk -v q="$QUERY" 'tolower($0) ~ tolower(q) && /"role"\s*:\s*"(user|assistant)"/ {exit 0} END{exit !NR}' "$file" 2>/dev/null; then
54
- has_match=true
55
- elif ! $BRIEF && [ "$ROLE_FILTER" = false ] && grep -qiE -m1 "$QUERY" "$file" 2>/dev/null; then
58
+
59
+ # 1. Filename match (also try normalized query with _ for spaces)
60
+ norm_query=$(echo "$QUERY" | tr ' ' '_')
61
+ if echo "$base" | grep -qiE "$QUERY" || echo "$base" | grep -qiE "$norm_query"; then
56
62
  has_match=true
63
+ # 2. Content match
64
+ elif ! $BRIEF; then
65
+ if has_query "$file"; then
66
+ if [ "$ROLE_FILTER" = true ]; then
67
+ if has_user_or_assistant_role "$file"; then
68
+ has_match=true
69
+ fi
70
+ else
71
+ has_match=true
72
+ fi
73
+ fi
57
74
  fi
75
+
58
76
  [ "$has_match" = true ] && ((files_matched++))
59
77
  done
60
78
  shopt -u nullglob
79
+
61
80
  [ $files_matched -gt 0 ] || continue
62
81
  matching_sessions+=("$sess_dir")
63
82
  ((total_files += files_matched))
64
- done 3< <(find .cache -mindepth 3 -maxdepth 5 -type d -name sessions -print0 2>/dev/null | sort -rz | head -"$LIMIT")
83
+ done 3< <(find .cache -mindepth 3 -maxdepth 5 -type d -name sessions -print0 2>/dev/null | sort -rz)
84
+
85
+ # Respect --limit on the number of sessions we will print
86
+ if [ ${#matching_sessions[@]} -gt "$LIMIT" ]; then
87
+ matching_sessions=("${matching_sessions[@]:0:$LIMIT}")
88
+ fi
65
89
 
66
90
  [ $total_files -eq 0 ] && exit 0
67
91
 
68
- echo "🔍 $QUERY: $total_files files / ${#matching_sessions[@]} sessions (limit=$LIMIT)"
92
+ echo "🔍 $QUERY: $total_files files / ${#matching_sessions[@]} sessions (scanned $scanned, limit=$LIMIT)"
69
93
  echo ===
70
94
 
71
- # 2nd pass: condensed output
95
+ # 2nd pass: condensed output for the (limited) matching sessions
72
96
  for sess_dir in "${matching_sessions[@]}"; do
73
97
  app=$(basename "$(dirname "$(dirname "$sess_dir")")")
74
98
  prompt=$(basename "$(dirname "$sess_dir")")
75
99
  time=$(stat -c %Y "$sess_dir" 2>/dev/null | xargs -I{} date -d "@{}" '+%H:%M' 2>/dev/null || echo ??)
76
100
 
77
- echo "📁 $app/$prompt ($time)"
78
- echo ---
79
-
80
101
  dir_count=0
81
- all_snips="" # Condense all files' snippets here
102
+ all_snips=""
103
+ file_lines=""
82
104
  shopt -s nullglob
83
105
  for file in "$sess_dir"/*.ndjson; do
84
106
  [ -f "$file" ] || continue
@@ -86,16 +108,22 @@ for sess_dir in "${matching_sessions[@]}"; do
86
108
  name=$(echo "$base" | sed 's/__/ /g; s/_[0-9]*$//' | fold -w30 | sed -E 's/(.{27}).*/\1.../') || name="$base..."
87
109
 
88
110
  printed=false
89
- # Filename
90
- if echo "$base" | grep -qiE "$QUERY"; then
91
- echo " 💾 $name"
111
+
112
+ # Filename match (same logic as pass 1)
113
+ norm_query=$(echo "$QUERY" | tr ' ' '_')
114
+ if echo "$base" | grep -qiE "$QUERY" || echo "$base" | grep -qiE "$norm_query"; then
115
+ file_lines+=" 💾 $name"$'\n'
92
116
  printed=true
93
117
  fi
94
118
 
95
- # Content snippets (role-filtered awk)
96
- if ! $BRIEF; then
119
+ # Content snippets
120
+ if ! $BRIEF && has_query "$file"; then
97
121
  if [ "$ROLE_FILTER" = true ]; then
98
- snips=$(awk -v q="$QUERY" 'tolower($0) ~ tolower(q) && /"role"\s*:\s*"(user|assistant)"/ { print substr($0, 1, 100) }' "$file" 2>/dev/null | head -"$MAX_SNIP" | paste -sd'; ')
122
+ # Only extract from user/assistant lines that also contain the query
123
+ snips=$(awk -v q="$QUERY" '
124
+ tolower($0) ~ tolower(q) && /"role"\s*:\s*"(user|assistant)"/ {
125
+ print substr($0, 1, 100)
126
+ }' "$file" 2>/dev/null | head -"$MAX_SNIP" | paste -sd'; ')
99
127
  else
100
128
  snips=$(grep -iE "$QUERY" "$file" 2>/dev/null | cut -c1-100 | head -"$MAX_SNIP" | paste -sd'; ')
101
129
  fi
@@ -104,17 +132,25 @@ for sess_dir in "${matching_sessions[@]}"; do
104
132
  printed=true
105
133
  }
106
134
  fi
135
+
107
136
  [ "$printed" = true ] && ((dir_count++))
108
137
  done
109
138
  shopt -u nullglob
110
139
 
111
- # Condensed session block
112
- [ -n "$all_snips" ] && {
113
- echo " 📄 Session ($dir_count files): $(echo "$all_snips" | fold -w90 | sed ':a;N;$!ba;s/\n/ /g' | cut -c1-180)"
140
+ # Only print the session block if it actually contributed matches
141
+ if [ $dir_count -gt 0 ]; then
142
+ echo "📁 $app/$prompt ($time)"
143
+ echo ---
144
+
145
+ [ -n "$file_lines" ] && echo -n "$file_lines"
146
+
147
+ [ -n "$all_snips" ] && {
148
+ echo " 📄 Session ($dir_count files): $(echo "$all_snips" | fold -w90 | sed ':a;N;$!ba;s/\n/ /g' | cut -c1-180)"
149
+ echo
150
+ }
151
+ echo " ($dir_count files)"
114
152
  echo
115
- }
116
- echo " ($dir_count files)"
117
- echo
153
+ fi
118
154
  done
119
155
 
120
- echo "✅ $total_files files / ${#matching_sessions[@]} sessions (scanned $scanned)"
156
+ echo "✅ $total_files files / ${#matching_sessions[@]} sessions (scanned $scanned)"
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * utils/toolsets.js
4
+ *
5
+ * Thin CLI wrapper around lib/toolsetLoader.js.
6
+ */
7
+
8
+ import { listToolsets, parseToolsetArgs, renderToolsetList, renderToolsetsHelp } from '../lib/toolsetLoader.js';
9
+
10
+ /**
11
+ * Run the toolsets utility CLI.
12
+ *
13
+ * @returns {void}
14
+ */
15
+ function main() {
16
+ const { filters, json, help } = parseToolsetArgs(process.argv.slice(2));
17
+
18
+ if (help) {
19
+ console.log(renderToolsetsHelp('utils/toolsets.js'));
20
+ return;
21
+ }
22
+
23
+ const result = listToolsets({ filters });
24
+
25
+ if (json) {
26
+ console.log(JSON.stringify(result, null, 2));
27
+ return;
28
+ }
29
+
30
+ console.log(renderToolsetList(result));
31
+ }
32
+
33
+ main();
@@ -1,240 +0,0 @@
1
- # hello-dave
2
-
3
- [![License: Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
4
- [![Node.js >=20](https://img.shields.io/badge/Node.js-%3E=20-green.svg)](https://nodejs.org/)
5
- [![Version: v0.0.8](https://img.shields.io/badge/Version-v0.0.8-green.svg)](https://codeberg.org/duin/hello-dave)
6
- [![PM2 Compatible](https://img.shields.io/badge/PM2-Compatible-orange.svg)](https://pm2.keymetrics.io/)
7
-
8
- ## Table of Contents
9
-
10
- - [Description](#description)
11
- - [Features](#features)
12
- - [Folder Structure](#folder-structure)
13
- - [Installation](#installation)
14
- - [Usage](#usage)
15
- - [Usage Examples](#usage-examples)
16
- - [Development](#development)
17
- - [Contributing](#contributing)
18
- - [License](#license)
19
-
20
- ## Description
21
-
22
- **hello-dave** is an ESM (ECMAScript Modules) toolkit for building AI agents with unified access to endpoints from Grok (xAI), OpenAI, and Anthropic. It provides CLI tools for interacting with agents locally or via WebSocket servers, along with pre-built agent scripts for various tasks like code generation, documentation, testing, and more.
23
-
24
- The project emphasizes modular agent management, tool integration (e.g., web search, file operations), and session handling with memory and caching. With v0.0.8, enhanced portability allows spawning agents in isolated environments like `/tmp` while maintaining tool functionality relative to the current working directory (CWD).
25
-
26
- ## Features
27
-
28
- - **Unified API Access**: Seamless integration with xAI (Grok), OpenAI, and Anthropic models.
29
- - **CLI Tools**: `dave` for querying agents, `agentDave` for spawning servers, `codeDave` for code servers.
30
- - **Agent Scripts**: Specialized agents for code, docs, npm, todo, readme, memory, and more.
31
- - **WebSocket Support**: Connect to remote agent servers for interactive or one-shot interactions.
32
- - **Toolsets**: Built-in tools for search, file I/O, email, and custom toolcalls.
33
- - **Session Management**: Cache history, search sessions, reset, and inspect logs.
34
- - **ESM-First**: Modern Node.js modules with TypeScript definitions.
35
- - **Portable Agent Spawning**: `spawn_agent.js` enables creating and deploying agents anywhere (project dirs or fresh `/tmp`). Supports auto-deploy in existing projects (detects `./agents/*.js`), manual code+bash in isolated setups. Tools adapt to CWD for portability. Hybrid modes combine server/client for chaining. See [docs/prompt/spawn_agent.md](docs/prompt/spawn_agent.md) for blueprint and validation.
36
- - **Multi-Agent Clusters**: PM2-powered CodeServer for scalable, clustered agent deployments (e.g., code_agent + todo_agent). Defaults to port 9000/secret '123'. See [docs/multi-agent-clusters.md](docs/multi-agent-clusters.md) for configuration.
37
-
38
- ## Folder Structure
39
-
40
- - **bin/**: Executables for CLI tools.
41
- - `dave.js`: Main CLI for asking agents or connecting to WebSocket servers.
42
- - `spawn_agent.js`: Spawns agent instances (binary: `agentDave`).
43
- - `codeDave`: Launches code servers (via PM2 clusters). References [docs/multi-agent-clusters.md](docs/multi-agent-clusters.md) for setup and scaling.
44
-
45
- - **agents/**: Agent scripts (`*_agent.js`) for specific tasks. These can be run directly with `node agents/<script>.js`.
46
- - `ask_agent.js`: General query agent.
47
- - `code_agent.js`: Code generation and execution agent (serves as main server in code clusters).
48
- - `daisy_agent.js`: Specialized agent (details in script).
49
- - `docs_agent.js`: Documentation-focused agent.
50
- - `gpt_agent.js`: OpenAI GPT integration agent.
51
- - `grok_agent.js`: xAI Grok-specific agent.
52
- - `memory_agent.js`: Agent with enhanced memory and context handling.
53
- - `npm_agent.js`: NPM package management agent.
54
- - `prompt_agent.js`: Prompt engineering and testing agent.
55
- - `readme_agent.js`: README.md management agent.
56
- - `spawn_agent.js`: Agent spawner (also in bin/). Creates portable CLI/WS agents + PM2 launchers. Validates/tests/deploys to `./agents/<name>.js`. Supports hybrid server/client modes. Portable to `/tmp` (tools follow CWD). Blueprint: [docs/prompt/spawn_agent.md](docs/prompt/spawn_agent.md).
57
- - `test_agent.js`: Testing and validation agent.
58
- - `todo_agent.js`: TODO list and task management agent.
59
- - `codeserver.sh`: Shell script for launching PM2-based code server clusters (uses agents above). See [docs/multi-agent-clusters.md](docs/multi-agent-clusters.md).
60
-
61
- - **lib/**: Core library modules (e.g., `index.js`, `wsCli.js`, `wsIO.js`, API integrations).
62
- - **scenarios/**: Test and example scenarios (e.g., toolset tests, integration scripts).
63
- - **types/**: TypeScript definitions.
64
- - **utils/**: Utility scripts (e.g., session management, testing).
65
- - **docs/**: Additional documentation, including agent blueprints (e.g., [prompt/spawn_agent.md](docs/prompt/spawn_agent.md)) and multi-agent guides (e.g., [multi-agent-clusters.md](docs/multi-agent-clusters.md)).
66
- - **release/**: Build artifacts.
67
-
68
- Other files: `package.json`, `CHANGELOG.md`, `TODO.md`, `LICENSE`.
69
-
70
- ## Installation
71
-
72
- 1. **Prerequisites**: Node.js >= 20. PM2 for multi-agent clusters: `npm install -g pm2`.
73
-
74
- 2. **Local Development**:
75
- ```bash
76
- git clone https://codeberg.org/duin/hello-dave.git
77
- cd hello-dave
78
- npm install
79
- ```
80
-
81
- 3. **Global CLI Installation** (for `dave`, `agentDave`, `codeDave`):
82
- ```bash
83
- npm install -g .
84
- # Or link for dev: npm run link-self
85
- ```
86
-
87
- 4. **API Keys**: Set environment variables (e.g., `XAIKEY` for xAI, `OPENAI_API_KEY` for OpenAI).
88
-
89
- ## Usage
90
-
91
- ### CLI Tools
92
-
93
- - **dave**: Interact with agents locally or remotely.
94
- - Local query: `dave --ask "Predict the weather"`
95
- - One-shot remote: `echo "Hello" | dave --connect 'ws://127.0.0.1:8080' --secret '123'`
96
- - Interactive remote: `dave --connect 'ws://127.0.0.1:8080' --secret '123'`
97
- - Other: `dave --list` (sessions), `dave --clear` (cache), `dave --help`.
98
-
99
- - **agentDave**: Spawn an agent server (powered by `spawn_agent.js`).
100
- ```bash
101
- agentDave --serve 8080 --secret '123' # Starts WebSocket server
102
- ```
103
-
104
- - **codeDave**: Launch a PM2 code server cluster.
105
- ```bash
106
- codeDave 8080 --secret '123' # Or: dave --code 8080 --secret '123'
107
- ```
108
-
109
- ### Running Agents
110
-
111
- Run agent scripts directly:
112
- ```bash
113
- node agents/spawn_agent.js --serve 8080 --secret '123' # Spawn server
114
- node agents/code_agent.js --connect 'ws://127.0.0.1:8080' --secret '123' # Client mode
115
- ```
116
-
117
- For full options, see script headers or run with `--help`.
118
-
119
- ### Programmatic Usage
120
-
121
- Import and use in your Node.js app:
122
- ```javascript
123
- import { AgentManager } from '@j-o-r/hello-dave';
124
- // Setup and run agent...
125
- ```
126
-
127
- ### spawn_agent.js Specifics (v0.0.8 Portability Ready)
128
-
129
- `spawn_agent.js` (executable as `agentDave`) creates and deploys portable agents in CLI, WebSocket server, client, or **hybrid** modes (server + client for tool chaining). It fetches live prompts from [docs/prompt/spawn_agent.md](docs/prompt/spawn_agent.md) and validates new agents via blueprint (temp files, syntax checks, grep for modes/tools).
130
-
131
- - **Modes**:
132
- - **Direct (One-Shot)**: Positional input, e.g., `node agents/spawn_agent.js "Create a tester"`.
133
- - **Interactive CLI**: No input; runs REPL-like session.
134
- - **Server**: `--serve <port>` – Exposes as remote tool (e.g., for other agents to call `spawn_agent`).
135
- - **Client**: `--connect <ws_url>` – Connects to remote server for tool access.
136
- - **Hybrid**: `--serve <port> --connect <ws_url>` – Serves locally while using remote tools.
137
-
138
- - **Portability**:
139
- - **In Project**: Auto-deploys to `./agents/<name>.js` if `./agents/*.js` exist (uses existing structure).
140
- - **Fresh /tmp**: Manual code generation + bash setup (e.g., `mkdir /tmp/myproj/agents; cd /tmp/myproj; node spawn_agent.js ...`). Tools (e.g., `read_file`) follow CWD, ensuring isolation without fixed paths.
141
- - Works in any dir; no repo deps beyond Node.js + npm installs.
142
-
143
- - **Custom Tools**: Specify in prompt, e.g., "name=coderev, tools=read_file,web_search,execute_bash_script".
144
-
145
- For validation/testing: See blueprint in [docs/prompt/spawn_agent.md](docs/prompt/spawn_agent.md) (includes bash examples like `node agents/NEW_AGENT.js --help` or server connect tests).
146
-
147
- ### CodeServer & PM2 Multi-Agent (v0.0.8)
148
-
149
- CodeServer (via `bin/codeDave` or `agents/codeserver.sh`) launches scalable, PM2-clustered multi-agent environments for collaborative tasks (e.g., code generation + task management). It deploys agents like `code_agent`, `todo_agent`, and `readme_agent` on a WebSocket server, enabling chaining and load balancing.
150
-
151
- - **Defaults**: Port 9000, secret '123' (customizable via args).
152
- - **Prerequisites**: Install PM2 globally (`npm install -g pm2`).
153
- - **Quickstart**:
154
- ```bash
155
- codeDave 9000 --secret 123 # Launches PM2 cluster on ws://127.0.0.1:9000/ws
156
- pm2 list # Verify processes (e.g., code_agent, todo_agent instances)
157
- echo "task" | bin/dave.js --connect ws://127.0.0.1:9000/ws --secret 123 # One-shot query to cluster
158
- ```
159
- This starts the cluster, lists running agents, and sends a test task (response routed to available agents).
160
-
161
- - **Scaling & Management**: Use PM2 commands (e.g., `pm2 scale <app> 4`, `pm2 stop all`). For ecosystem config, PM2 JSON files, or agent orchestration, see the [full guide in docs/multi-agent-clusters.md](docs/multi-agent-clusters.md).
162
-
163
- - **Integration**: Combine with `spawn_agent.js` for dynamic agent addition to clusters (e.g., spawn new agents and connect via `--connect ws://127.0.0.1:9000/ws`).
164
-
165
- ## Usage Examples
166
-
167
- - **Direct Spawn (Project)**:
168
- ```bash
169
- cd hello-dave # Or any project with ./agents/
170
- node agents/spawn_agent.js "Create code-review agent: name=coderev, desc=Git diff analyzer, tools=read_file,execute_bash_script,web_search"
171
- # Deploys to ./agents/coderev_agent.js; test: node agents/coderev_agent.js "Review this diff"
172
- ```
173
-
174
- - **/tmp Workflow (Portable, Fresh Setup)**:
175
- ```bash
176
- mkdir -p /tmp/myportable/agents
177
- cd /tmp/myportable
178
- # Copy or fetch spawn_agent.js (e.g., curl from repo or npm install @j-o-r/hello-dave)
179
- npm init -y && npm i @j-o-r/hello-dave @j-o-r/sh
180
- node spawn_agent.js "Create todo agent: name=todo, desc=Task manager, tools=read_file,write_file"
181
- # Deploys to ./agents/todo_agent.js; tools use /tmp/myportable as CWD
182
- node agents/todo_agent.js --serve 8081 --secret abc # Test server mode
183
- ```
184
-
185
- - **Hybrid Mode with Custom Tools**:
186
- ```bash
187
- node agents/spawn_agent.js --serve 8081 --connect ws://127.0.0.1:8080/ws --secret abc "Spawn a docs agent with custom email tool"
188
- # Serves on 8081 (exposes new agent), connects to 8080 (gains remote tools like email)
189
- # Test: In another term, node agents/spawn_agent.js --connect ws://127.0.0.1:8081/ws --secret abc "Use the new docs agent"
190
- ```
191
-
192
- - **Spawn a Server**:
193
- ```bash
194
- node agents/spawn_agent.js --serve 8080 --secret '123'
195
- # Then connect: echo "Task" | dave --connect 'ws://127.0.0.1:8080' --secret '123'
196
- ```
197
-
198
- - **Launch Code Cluster** (includes multiple agents):
199
- ```bash
200
- node agents/codeserver.sh 9000 '123' # Or use codeDave 9000 --secret 123
201
- # Connects code_agent, todo_agent, readme_agent, etc., to the server on ws://127.0.0.1:9000/ws.
202
- # Test: pm2 list; echo "Optimize this code" | dave --connect ws://127.0.0.1:9000/ws --secret 123
203
- # For advanced config: See [docs/multi-agent-clusters.md](docs/multi-agent-clusters.md).
204
- ```
205
-
206
- - **Local Agent Query** (no server):
207
- ```bash
208
- dave --ask --model 'grok-4-1-fast-reasoning' "Write a function"
209
- ```
210
-
211
- - **Custom Agent**:
212
- ```bash
213
- node agents/docs_agent.js --connect 'ws://127.0.0.1:8080' --secret '123'
214
- ```
215
-
216
- See `scenarios/` for more test scenarios.
217
-
218
- ## Development
219
-
220
- - **Build Types**: `npm run types`
221
- - **Test**: `npm run tests` (runs `utils/test.sh`)
222
- - **Release**: `npm run release` then `npm run publish`
223
- - **Local Linking**: `npm run link-self` / `npm run unlink-self`
224
-
225
- Use `git status` and `ls` to inspect changes. Ensure ESM compatibility.
226
-
227
- ## Contributing
228
-
229
- Contributions welcome! Fork the repo, create a branch, and submit a pull request to https://codeberg.org/duin/hello-dave.
230
-
231
- - Report bugs: https://codeberg.org/duin/hello-dave/issues
232
- - Follow Apache-2.0 license.
233
-
234
- ## License
235
-
236
- This project is licensed under the Apache-2.0 License - see the [LICENSE](LICENSE) file for details.
237
-
238
- ---
239
- *Repository: https://codeberg.org/duin/hello-dave*
240
- ---
@@ -1,47 +0,0 @@
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 paths relative to THIS script's location (portable from anywhere)
21
- SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
22
- PROJECT_DIR="$( cd "$( dirname "${SCRIPT_DIR}" )" && pwd )"
23
- FOLDER=$(basename "$PROJECT_DIR")
24
-
25
- echo "Starting CodeServer on port ${PORT} in folder '${FOLDER}' (SCRIPT_DIR: ${SCRIPT_DIR}) with SECRET '${SECRET}'..."
26
-
27
- # Delete existing processes with folder_port suffix
28
- pm2 delete "${FOLDER}_code_${PORT}" 2>/dev/null || true
29
- pm2 delete "${FOLDER}_todo_${PORT}" 2>/dev/null || true
30
- pm2 delete "${FOLDER}_readme_${PORT}" 2>/dev/null || true
31
- pm2 delete "${FOLDER}_npm_${PORT}" 2>/dev/null || true
32
- pm2 delete "${FOLDER}_docs_${PORT}" 2>/dev/null || true
33
- pm2 delete "${FOLDER}_test_${PORT}" 2>/dev/null || true
34
- pm2 delete "${FOLDER}_memory__${PORT}" 2>/dev/null || true
35
-
36
- # Spawn main Agent / server (absolute paths to scripts)
37
- pm2 start "${SCRIPT_DIR}/code_agent.js" --name "${FOLDER}_code_${PORT}" -- --serve "${PORT}" --tools javascript --secret "${SECRET}"
38
- # Attach clients
39
- pm2 start "${SCRIPT_DIR}/todo_agent.js" --name "${FOLDER}_todo_${PORT}" -- --connect "ws://127.0.0.1:${PORT}/ws" --secret "${SECRET}"
40
- pm2 start "${SCRIPT_DIR}/readme_agent.js" --name "${FOLDER}_readme_${PORT}" -- --connect "ws://127.0.0.1:${PORT}/ws" --secret "${SECRET}"
41
- pm2 start "${SCRIPT_DIR}/npm_agent.js" --name "${FOLDER}_npm_${PORT}" -- --connect "ws://127.0.0.1:${PORT}/ws" --secret "${SECRET}"
42
- pm2 start "${SCRIPT_DIR}/docs_agent.js" --name "${FOLDER}_docs_${PORT}" -- --connect "ws://127.0.0.1:${PORT}/ws" --secret "${SECRET}"
43
- pm2 start "${SCRIPT_DIR}/test_agent.js" --name "${FOLDER}_test_${PORT}" -- --connect "ws://127.0.0.1:${PORT}/ws" --secret "${SECRET}"
44
- pm2 start "${SCRIPT_DIR}/memory_agent.js" --name "${FOLDER}_memory_${PORT}" -- --connect "ws://127.0.0.1:${PORT}/ws" --secret "${SECRET}"
45
-
46
- echo "CodeServer processes spawned with prefix '${FOLDER}_' and suffix _${PORT}. Check with: pm2 list | grep '${FOLDER}_${PORT}'"
47
- echo "dave --connect ws://127.0.0.1:${PORT}/ws --secret '$SECRET'"