@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.
Files changed (66) hide show
  1. package/CHANGELOG.md +19 -33
  2. package/README.md +240 -0
  3. package/TODO.md +13 -0
  4. package/{examples → agents}/ask_agent.js +5 -5
  5. package/{examples → agents}/codeserver.sh +14 -14
  6. package/{examples → agents}/daisy_agent.js +5 -5
  7. package/{examples → agents}/docs_agent.js +5 -5
  8. package/{examples → agents}/gpt_agent.js +5 -5
  9. package/{examples → agents}/grok_agent.js +5 -5
  10. package/{examples → agents}/memory_agent.js +5 -5
  11. package/{examples → agents}/npm_agent.js +5 -5
  12. package/{examples → agents}/prompt_agent.js +5 -5
  13. package/agents/spawn_agent.js +137 -0
  14. package/{examples → agents}/test_agent.js +6 -6
  15. package/{examples → agents}/todo_agent.js +5 -5
  16. package/bin/codeDave +58 -0
  17. package/bin/dave.js +3 -5
  18. package/docs/agent-manager.md +244 -0
  19. package/docs/bin-dave.md +62 -0
  20. package/docs/codeserver-pattern.md +191 -0
  21. package/docs/generic-toolset.md +326 -0
  22. package/docs/howtos/agent-networking.md +253 -0
  23. package/docs/howtos/spawn-agents.md.bak +200 -0
  24. package/docs/howtos/spawn-agents.md.bak_new +200 -0
  25. package/docs/jsdoc-best-practices.md +278 -0
  26. package/docs/multi-agent-clusters.md +265 -0
  27. package/docs/multi-agent-clusters.md.bak +229 -0
  28. package/docs/path-resolution-best-practices.md +104 -0
  29. package/docs/project-overview.md +67 -0
  30. package/docs/prompt/spawn_agent.md +173 -0
  31. package/docs/prompt/spawn_agent.md.bak +201 -0
  32. package/docs/prompt-class.md +141 -0
  33. package/docs/suggestions.md +38 -0
  34. package/docs/todo-archive-v0.0.8.md +1 -0
  35. package/docs/todo-archive.md +44 -0
  36. package/docs/tools-syntax-validation.md +121 -0
  37. package/docs/toolset.md +164 -0
  38. package/docs/xai-responses.md +111 -0
  39. package/docs/xai_collections.md +106 -0
  40. package/lib/AgentClient.js +111 -67
  41. package/lib/AgentManager.js +111 -80
  42. package/lib/AgentServer.js +144 -104
  43. package/lib/Cli.js +126 -93
  44. package/lib/Prompt.js +38 -5
  45. package/lib/Session.js +102 -79
  46. package/lib/ToolSet.js +79 -60
  47. package/lib/fafs.js +54 -19
  48. package/lib/genericToolset.js +129 -136
  49. package/lib/wsCli.js +50 -19
  50. package/lib/wsIO.js +10 -6
  51. package/package.json +3 -3
  52. package/types/AgentClient.d.ts +69 -35
  53. package/types/AgentManager.d.ts +50 -56
  54. package/types/AgentServer.d.ts +63 -16
  55. package/types/Cli.d.ts +56 -10
  56. package/types/Prompt.d.ts +36 -4
  57. package/types/Session.d.ts +23 -9
  58. package/types/ToolSet.d.ts +49 -32
  59. package/types/fafs.d.ts +68 -25
  60. package/types/wsCli.d.ts +14 -0
  61. package/types/wsIO.d.ts +9 -5
  62. package/utils/search_sessions.sh +100 -53
  63. package/bin/spawn_agent.js +0 -293
  64. package/lib/genericToolset.js.bak_syntax +0 -402
  65. /package/{examples → agents}/code_agent.js +0 -0
  66. /package/{examples → agents}/readme_agent.js +0 -0
@@ -1,56 +1,83 @@
1
1
  import { Prompt, Cli, AgentClient, AgentServer, API, ToolSet, Session, env } from './index.js';
2
2
  import toolsPool from './genericToolset.js'
3
3
  /**
4
- * @typedef {import('./API/x.ai/text.js').XOptions} XOptions
5
- * @typedef {import('./API/x.ai/responses.js').XAIOptions} XAIOptions
6
- * @typedef {import('./API/openai.com/reponses/text.js').OAOptions} OAOptions
7
- * @typedef {import('./API/anthropic.com/text.js').ANTHOptions} ANTHOptions
8
- */
4
+ * @module lib/AgentManager
5
+ * @exports default AgentManager
6
+ * High-level orchestrator for AI agent lifecycle: configures Prompt/Session/ToolSet, launches CLI/Server/Client modes.
7
+ * Supports chaining setup() → start(); adds generic tools; direct calls.
8
+ */
9
+
10
+ /**
11
+ * @typedef {import('./API/x.ai/text.js').XOptions} XOptions
12
+ * @typedef {import('./API/x.ai/responses.js').XAIOptions} XAIOptions
13
+ * @typedef {import('./API/openai.com/reponses/text.js').OAOptions} OAOptions
14
+ * @typedef {import('./API/anthropic.com/text.js').ANTHOptions} ANTHOptions
15
+ */
9
16
  /**
10
- * @typedef {Object} Setup
11
- * @property {string} prompt - Initial system prompt
12
- * @property {XAIOptions|OAOptions|XOptions|ANTHOptions} options - Model options
13
- * @property {'gpt'|'xai'|'claude'} api - AI endpoint to use
14
- * @property {number} [contextWindow] - The size in tokens for the context/session
15
- * @property {'auto'|'required'|void} [toolsetMode] -
16
- * @property {boolean} [debug] - verbose output
17
- */
17
+ * @typedef {Object} Setup
18
+ * @property {string} prompt - Initial system prompt.
19
+ * @property {XAIOptions|OAOptions|XOptions|ANTHOptions} options - API model options.
20
+ * @property {'gpt'|'xai'|'claude'} api - AI provider.
21
+ * @property {number} [contextWindow=300000] - Token limit for context.
22
+ * @property {'auto'|'required'|null} [toolsetMode] - Toolset activation mode.
23
+ * @property {boolean} [debug] - Enable verbose output.
24
+ */
18
25
  /**
19
- * @typedef {Object} Options
20
- * @property {string} name - Agent name
21
- * @property {string} secret - Secret string for WS access authorisation (server and client secrets should match)
22
- * @property {string} [cachePath] - path to session/record storage
23
- */
26
+ * @typedef {Object} Options
27
+ * @property {string} name - Agent name (validated /^[a-z_0-9]{2,}$/).
28
+ * @property {string} secret - WS auth secret (base64-encoded).
29
+ * @property {string} [cachePath='.cache/hello-dave'] - Session cache directory.
30
+ * @example { name: 'code-agent', secret: 'mysecret' }
31
+ */
32
+ /** @const {RegExp} Validates agent/tool names (lowercase a-z0-9_, min 2 chars). */
33
+ const validNameRegex = /^[a-z_0-9]{2,}$/;
34
+
24
35
  class AgentManager {
25
- /** @type {Prompt} */
36
+ /** @private @type {Prompt} */
26
37
  #prompt;
27
- /** @type {Session} */
38
+ /** @private @type {Session} */
28
39
  #sessionStorage;
40
+ /** @private @type {string} */
29
41
  #name = 'agent';
42
+ /** @private @type {string} */
30
43
  #secret = '';
44
+ /** @private @type {string} */
31
45
  #cachePath = '.cache/hello-dave';
46
+ /** @private @type {boolean} */
32
47
  #debug = false;
48
+ /** @private @type {string} */
33
49
  #model = '';
50
+ /** @private @type {number} */
34
51
  #contextWindow = 0;
52
+ /** @private @type {string} */
35
53
  #sysPrompt = '';
54
+
36
55
  /**
37
- * @param {Options} options
38
- */
56
+ * Initializes AgentManager with base options.
57
+ * Validates name regex; encodes secret.
58
+ * @param {Options} options - Base configuration.
59
+ * @throws {Error} Invalid name (regex) or options.
60
+ * @chainable
61
+ */
39
62
  constructor(options) {
40
63
  this.#name = options.name || this.#name;
41
64
  if (options.secret && typeof options.secret === 'string') {
42
65
  this.#secret = Buffer.from(options.secret).toString('base64');
43
66
  }
44
- const validNameRegex = /^[a-z_0-9]{2,}$/;
45
67
  if (!validNameRegex.test(this.#name)) {
46
- throw new Error(`Invalid agent 'name' in options: '${this.#name}'. Must match /^[a-z_0-9]{2,}$/ (lowercase a-z, digits, underscores; min 2 chars).`);
68
+ throw new Error(`Invalid agent 'name': '${this.#name}'. Must match /^[a-z_0-9]{2,}$/`);
47
69
  }
48
70
  this.#cachePath = options.cachePath || this.#cachePath;
49
71
  }
50
72
 
51
73
  /**
52
- * @param {Setup} setup
53
- */
74
+ * Configures the Prompt/Session/ToolSet with API adaptor.
75
+ * Adds system prompt; chains to start().
76
+ * @param {Setup} setup - AI setup details.
77
+ * @returns {AgentManager} This instance (chainable).
78
+ * @throws {Error} Invalid setup.
79
+ * @example mgr.setup({ prompt: 'You are a coder...', api: 'gpt', options: { model: 'gpt-4o' } });
80
+ */
54
81
  setup(setup) {
55
82
  const {
56
83
  prompt,
@@ -63,9 +90,6 @@ class AgentManager {
63
90
  this.#sysPrompt = prompt;
64
91
  this.#contextWindow = contextWindow;
65
92
  if (options?.model) this.#model = options.model;
66
- this.#sysPrompt = prompt;
67
- this.#contextWindow = contextWindow;
68
- if (options?.model) this.#model = options.model;
69
93
  let toolset;
70
94
  if (toolsetMode) {
71
95
  toolset = new ToolSet(toolsetMode);
@@ -77,43 +101,48 @@ class AgentManager {
77
101
  this.#sessionStorage = new Session(this.#name, this.#prompt, this.#cachePath);
78
102
  this.#prompt.add('system', prompt, true);
79
103
  this.#prompt.setAdaptor(API.text[api], toolset, options);
80
- return this; // For chaining
104
+ return this;
81
105
  }
82
106
 
83
107
  /**
84
- * Start a CLI for local usage
85
- * @param {string} description - introduction message for the CLI user
86
- */
108
+ * @private
109
+ * Launches interactive CLI mode.
110
+ * @param {string} description - CLI intro message.
111
+ * @returns {void}
112
+ * @throws {Error} No setup() called.
113
+ */
87
114
  #startCli(description) {
88
115
  if (!this.#prompt) throw new Error('Run setup first');
89
116
  const cli = new Cli({ prompt: this.#prompt, session: this.#sessionStorage, description });
90
117
  setTimeout(() => {
91
- // This resolves issues with log output after the console has been started
92
118
  cli.start();
93
119
  }, 1000);
94
120
  }
95
121
 
96
122
  /**
97
- * Attach a session to an AgentServer
98
- * DO NOT ATTACH TO SELF, however, when in server mode
99
- * An AgentServer can attach as client to another server
100
- * @param {string} name - function_call name
101
- * @param {string} description - function_call description
102
- * @param {string} [url='ws://127.0.0.1:8000/ws'] - ws URL
103
- */
123
+ * @private
124
+ * Attaches this agent as a WS client to another server (for chaining agents).
125
+ * @param {string} name - Tool name.
126
+ * @param {string} description - Tool desc.
127
+ * @param {string} [url='ws://127.0.0.1:8000/ws'] - Target WS URL.
128
+ * @returns {AgentClient} New client instance.
129
+ * @throws {Error} No setup().
130
+ */
104
131
  #attach(name, description, url = 'ws://127.0.0.1:8000/ws') {
105
132
  if (!this.#prompt) throw new Error('Run setup first');
106
133
  return new AgentClient({ prompt: this.#prompt, name, description, url, secret: this.#secret });
107
134
  }
108
135
 
109
136
  /**
110
- * Start the Agent in server mode.
111
- * A server is always started on localhost
112
- * Clients can attach now and are accesible as via function_calls (toolset)
113
- * @param {string} name - function_call name
114
- * @param {string} description - function_call description
115
- * @param {number} [port=8000] - Start the dynamic toolset server on this port
116
- */
137
+ * @private
138
+ * Enables server mode: Registers this agent for remote tool calls.
139
+ * Optionally attaches as client too.
140
+ * @param {string} name - Server/tool name.
141
+ * @param {string} [description=''] - Desc (auto from sysPrompt).
142
+ * @param {number} [port=8000] - Port.
143
+ * @returns {void}
144
+ * @throws {Error} No setup/toolset.
145
+ */
117
146
  #enableServer(name, description = '', port = 8000) {
118
147
  if (!this.#prompt) throw new Error('Run setup first');
119
148
  if (!this.#prompt.toolset) throw new Error('No toolset defined');
@@ -125,64 +154,68 @@ class AgentManager {
125
154
  prompt: this.#prompt,
126
155
  session: this.#sessionStorage,
127
156
  debug: this.#debug
128
-
129
157
  });
130
- // trigger reset on all Agents
131
158
  this.#prompt.on('reset', () => {
132
- // Generate new context for all Agents
133
159
  server.resetAll();
134
- })
160
+ });
135
161
  }
162
+
136
163
  /**
137
- * Direct call to the prompt
138
- * @param {string} input
139
- * @returns {Promise<string>}
140
- */
164
+ * Direct synchronous call to the underlying Prompt.
165
+ * @param {string} input - User input.
166
+ * @returns {Promise&lt;string&gt;} Response.
167
+ * @throws {Error} No setup.
168
+ */
141
169
  async directCall(input) {
142
170
  const res = await this.#prompt.call(input);
143
171
  return res;
144
172
  }
145
- /** @returns {Prompt} */
173
+
174
+ /** @returns {Prompt} Underlying Prompt instance. */
146
175
  getPrompt() { return this.#prompt; }
147
- /** @returns {ToolSet|void} */
176
+
177
+ /** @returns {ToolSet|null} Toolset if configured. */
148
178
  getToolset() { return this.#prompt.toolset; }
149
- /** @returns {Promise<import('./fafs.js').EnvironmentInfo>} */
179
+
180
+ /** @returns {Promise&lt;import('./fafs.js').EnvironmentInfo&gt;} System env info. */
150
181
  async environment() {
151
182
  return env();
152
183
  }
184
+
153
185
  /**
154
- * Adds a pre-defined generic tool from lib/genericToolset.js to this agent's ToolSet.
155
- * @param {'execute_bash_script'|'execute_remote_script'|'get_user_env'|'history_search'|'javascript_interpreter'|'memory_recall'|'memory_write'|'open_link'|'read_file'|'send_email'|'syntax_check'|'write_file'} name - Valid generic tool name (validated /^[a-z_0-9]{2,}$/).
156
- * @throws {Error} If toolset not initialized or tool not found in pool.
186
+ * Adds a pre-defined generic tool from toolsPool to this agent's ToolSet.
187
+ * @param {'execute_bash_script'|'execute_remote_script'|'get_user_env'|'history_search'|'javascript_interpreter'|'memory_recall'|'memory_write'|'open_link'|'read_file'|'send_email'|'syntax_check'|'write_file'} name - Tool name.
188
+ * @throws {Error} Invalid name, no toolset, or tool missing.
189
+ * @example mgr.addGenericToolcall('read_file');
157
190
  */
158
191
  addGenericToolcall(name) {
159
- const validNameRegex = /^[a-z_0-9]{2,}$/;
160
192
  if (!validNameRegex.test(name)) {
161
- throw new Error(`Invalid 'name': '${name}'. Must match /^[a-z_0-9]{2,}$/ (lowercase a-z, digits, underscores; min 2 chars).`);
193
+ throw new Error(`Invalid 'name': '${name}'. Must match /^[a-z_0-9]{2,}$/`);
162
194
  }
163
- if (!this.#prompt.toolset) throw new Error('No ToolSet defined')
195
+ if (!this.#prompt.toolset) throw new Error('No ToolSet defined');
164
196
  let tool = toolsPool.get(name);
165
- if (!tool) throw new Error('Tool not defined')
197
+ if (!tool) throw new Error(`Tool '${name}' not found in pool`);
166
198
  this.#prompt.toolset.add(name, tool.description, tool.parameters, tool.method);
167
199
  }
168
200
 
169
201
  /**
170
- * Smart launcher: Dispatches to CLI/server/attach/direct. Auto-gens cliIntro/desc if empty.
171
- * @param {number} [servePort] - Server port (if no input).
172
- * @param {string} [connectUrl] - WS to attach. e.g. ws://127.0.0.1:8091/ws
173
- * @param {string} [cliIntro=""] - CLI intro (auto-gen if falsy).
174
- * @param {string} [toolName=""] - name /^[a-z_0-9]{2,}$/ Tool name for server/attach (defaults to agent.name).
175
- * @param {string} [toolDescription=""] - Tool desc (auto-gen if falsy).
202
+ * Smart launcher: CLI (default), server (servePort), or client (connectUrl).
203
+ * Auto-generates intros/descriptions if empty.
204
+ * @param {number} [servePort] - Launch server on port.
205
+ * @param {string} [connectUrl] - Connect as client to WS.
206
+ * @param {string} [cliIntro=""] - CLI intro text.
207
+ * @param {string} [toolName=""] - Tool/server name (falls back to #name).
208
+ * @param {string} [toolDescription=""] - Tool desc.
209
+ * @returns {Promise&lt;void&gt;}
210
+ * @throws {Error} No setup; invalid names/ports.
211
+ * @example mgr.start(8000); // Server\nmgr.start(undefined, 'ws://other:8001/ws'); // Client\nmgr.start(); // CLI
176
212
  */
177
213
  async start(servePort, connectUrl, cliIntro = "", toolName = "", toolDescription = "") {
178
214
  if (!this.#prompt) throw new Error("Run setup first");
179
215
 
180
- const validNameRegex = /^[a-z_0-9]{2,}$/;
181
-
182
216
  toolName = toolName || this.#name;
183
- // Validate 'toolName' (or fallback agent name)
184
217
  if (!validNameRegex.test(toolName)) {
185
- throw new Error(`Invalid 'toolName' (or agent #name): '${toolName}'. Must match /^[a-z_0-9]{2,}$/ (lowercase a-z, digits, underscores; min 2 chars).`);
218
+ throw new Error(`Invalid 'toolName': '${toolName}'. Must match /^[a-z_0-9]{2,}$/`);
186
219
  }
187
220
 
188
221
  if (!toolDescription && this.#sysPrompt) {
@@ -190,22 +223,20 @@ class AgentManager {
190
223
  }
191
224
 
192
225
  if (!cliIntro) {
193
- const introStr = this.#name + " " + (this.#model || "unknown-model") + " - context: " + this.#contextWindow;
226
+ const introStr = `${this.#name} ${this.#model || "unknown-model"} - context: ${this.#contextWindow}`;
194
227
  cliIntro = introStr.trim();
195
228
  }
229
+
196
230
  if (servePort) {
197
231
  console.log(toolName);
198
232
  console.log(toolDescription);
199
233
  this.#enableServer(toolName, toolDescription, servePort);
200
- // A server can also be a client
201
234
  if (connectUrl) {
202
235
  this.#attach(toolName, toolDescription, connectUrl);
203
236
  }
204
237
  } else if (connectUrl) {
205
- // Connect to a agent 'server' and enable via websocket / toolcalls
206
238
  this.#attach(toolName, toolDescription, connectUrl);
207
239
  } else {
208
- // Terminal user CLI
209
240
  this.#startCli(cliIntro);
210
241
  }
211
242
  }