@j-o-r/hello-dave 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +445 -160
  3. package/README.md.backup +269 -0
  4. package/README.md.bak +481 -0
  5. package/README.md.bak.1774780058 +338 -0
  6. package/README.md.bak2 +455 -0
  7. package/bin/dave.js +165 -0
  8. package/docs.bak.1774780058/agent-manager.md +167 -0
  9. package/docs.bak.1774780058/agent-manager.md.bak +137 -0
  10. package/docs.bak.1774780058/agent-manager.md.bak2 +157 -0
  11. package/docs.bak.1774780058/codeserver-pattern.md +191 -0
  12. package/docs.bak.1774780058/path-resolution-best-practices.md +104 -0
  13. package/docs.bak.1774780058/project-overview.md +67 -0
  14. package/docs.bak.1774780058/project-overview.md.bak +67 -0
  15. package/docs.bak.1774780058/prompt-class.md +141 -0
  16. package/docs.bak.1774780058/prompt-class.md.bak +142 -0
  17. package/docs.bak.1774780058/tools-syntax-validation.md +121 -0
  18. package/docs.bak.1774780058/tools-syntax-validation.md.bak2 +125 -0
  19. package/docs.bak.1774780058/tools-syntax-validation.md.bak3 +125 -0
  20. package/docs.bak.1774780058/tools-syntax-validation.md.bak4 +106 -0
  21. package/docs.bak.1774780058/tools-syntax-validation.md.bak_path +106 -0
  22. package/docs.bak.1774780058/toolset.md +164 -0
  23. package/docs.bak.1774780058/toolset.md.bak +94 -0
  24. package/docs.bak.1774780058/toolset.md.bak3 +161 -0
  25. package/docs.bak.1774780058/toolset.md.bak4 +161 -0
  26. package/docs.bak.1774780058/toolset.md.bak5 +161 -0
  27. package/docs.bak.1774780058/toolset.md.bak6 +163 -0
  28. package/docs.bak.1774780058/toolset.md.bak_path +163 -0
  29. package/docs.bak.1774780058/toolset.md.bak_syntax +161 -0
  30. package/docs.bak.1774780058/xai-responses.md +111 -0
  31. package/docs.bak.1774780058/xai-responses.md.bak +107 -0
  32. package/docs.bak.1774780058/xai-responses.md.bak2 +107 -0
  33. package/docs.bak.1774780058/xai_collections.md +106 -0
  34. package/examples/ask_agent.js +137 -0
  35. package/examples/code_agent.js +149 -0
  36. package/examples/coderev_agent.js +136 -0
  37. package/examples/codeserver.sh +47 -0
  38. package/examples/daisy_agent.js +170 -0
  39. package/examples/docs_agent.js +148 -0
  40. package/examples/gpt_agent.js +125 -0
  41. package/examples/grok_agent.js +132 -0
  42. package/examples/grok_agent.js.bak +98 -0
  43. package/examples/grok_agent.js.bak.2 +99 -0
  44. package/examples/grok_agent.js.bak.3 +1 -0
  45. package/examples/grok_agent.js.bak.4 +124 -0
  46. package/examples/grok_agent.js.bak.5 +1 -0
  47. package/examples/grok_agent.js.bak.6 +1 -0
  48. package/examples/memory_agent.js +152 -0
  49. package/examples/npm_agent.js +202 -0
  50. package/examples/npm_agent.js.bak.3 +2 -0
  51. package/examples/npm_agent.js.bak.4 +205 -0
  52. package/examples/npm_agent.js.bak.5 +1 -0
  53. package/examples/npm_agent.js.bak.6 +1 -0
  54. package/examples/prompt_agent.js +133 -0
  55. package/examples/readme_agent.js +148 -0
  56. package/examples/spawn_agent.js +293 -0
  57. package/examples/test_agent.js +187 -0
  58. package/examples/todo_agent.js +175 -0
  59. package/examples.bak.1774780058/ask_agent.js +114 -0
  60. package/examples.bak.1774780058/code_agent.js +149 -0
  61. package/examples.bak.1774780058/coderev_agent.js +72 -0
  62. package/examples.bak.1774780058/codeserver.sh +47 -0
  63. package/examples.bak.1774780058/daisy_agent.js +177 -0
  64. package/examples.bak.1774780058/docs_agent.js +119 -0
  65. package/{bin/hdAsk.js → examples.bak.1774780058/gpt_agent.js} +46 -40
  66. package/examples.bak.1774780058/grok_agent.js +98 -0
  67. package/examples.bak.1774780058/memory_agent.js +112 -0
  68. package/examples.bak.1774780058/npm_agent.js +175 -0
  69. package/examples.bak.1774780058/prompt_agent.js +112 -0
  70. package/examples.bak.1774780058/readme_agent.js +144 -0
  71. package/examples.bak.1774780058/spawn_agent.js +263 -0
  72. package/examples.bak.1774780058/test_agent.js +162 -0
  73. package/examples.bak.1774780058/todo_agent.js +138 -0
  74. package/lib/API/openai.com/reponses/text.js +12 -18
  75. package/lib/API/x.ai/collections.js +354 -0
  76. package/lib/API/x.ai/files.js +218 -0
  77. package/lib/API/x.ai/responses.js +492 -0
  78. package/lib/API/x.ai/text.js +1 -1
  79. package/lib/AgentClient.js +13 -6
  80. package/lib/AgentManager.js +80 -10
  81. package/lib/AgentServer.js +50 -22
  82. package/lib/Cli.js +7 -1
  83. package/lib/Prompt.js +4 -2
  84. package/lib/ToolSet.js +2 -1
  85. package/lib/genericToolset.js +258 -88
  86. package/lib/genericToolset.js.bak_syntax +402 -0
  87. package/lib/index.js +4 -2
  88. package/lib/wsCli.js +256 -0
  89. package/lib/wsIO.js +96 -0
  90. package/package.json +26 -21
  91. package/scenarios.bak.1774780058/data/eval_node_message.json +9 -0
  92. package/scenarios.bak.1774780058/data/hist_oa.json +66 -0
  93. package/scenarios.bak.1774780058/data/o3_response1.json +96 -0
  94. package/scenarios.bak.1774780058/data/oa_reasoning_parse.json +112 -0
  95. package/scenarios.bak.1774780058/data/tool_oa.json +96 -0
  96. package/scenarios.bak.1774780058/data/tool_xai.json +59 -0
  97. package/scenarios.bak.1774780058/data/tool_xai2.json +40 -0
  98. package/scenarios.bak.1774780058/data/xai-response-1.json +59 -0
  99. package/scenarios.bak.1774780058/data/xai-response-2.json +10 -0
  100. package/scenarios.bak.1774780058/data/xai_reasoning_tools_resp.json +59 -0
  101. package/scenarios.bak.1774780058/data/xai_search_response.json +58 -0
  102. package/scenarios.bak.1774780058/environment.js +10 -0
  103. package/scenarios.bak.1774780058/example.js +17 -0
  104. package/scenarios.bak.1774780058/genericToolset.test.js +182 -0
  105. package/scenarios.bak.1774780058/grok.js +113 -0
  106. package/scenarios.bak.1774780058/memory-tools.js +51 -0
  107. package/scenarios.bak.1774780058/openai-o3.js +137 -0
  108. package/scenarios.bak.1774780058/openai-prompt.js +155 -0
  109. package/scenarios.bak.1774780058/openai-session.js +148 -0
  110. package/scenarios.bak.1774780058/openai.js +102 -0
  111. package/scenarios.bak.1774780058/prompt.js +118 -0
  112. package/scenarios.bak.1774780058/promptFishbowl.js +76 -0
  113. package/scenarios.bak.1774780058/search.brave.com.js +25 -0
  114. package/scenarios.bak.1774780058/sh.js +15 -0
  115. package/scenarios.bak.1774780058/test-wsio.js +26 -0
  116. package/scenarios.bak.1774780058/testToolset.js +42 -0
  117. package/scenarios.bak.1774780058/toolset.js +16 -0
  118. package/scenarios.bak.1774780058/toolset.test.js +141 -0
  119. package/scenarios.bak.1774780058/write_file_syntax.test.js +145 -0
  120. package/scenarios.bak.1774780058/write_file_validation/README.md +30 -0
  121. package/scenarios.bak.1774780058/write_file_validation/bad.js +3 -0
  122. package/scenarios.bak.1774780058/write_file_validation/good.js +4 -0
  123. package/scenarios.bak.1774780058/write_file_validation/test.sh +43 -0
  124. package/scenarios.bak.1774780058/wsClient.js +69 -0
  125. package/scenarios.bak.1774780058/xai_responses.integration.test.js +57 -0
  126. package/scenarios.bak.1774780058/xai_responses.test.js +154 -0
  127. package/scenarios.bak.1774780058/xaicoll.js +50 -0
  128. package/scenarios.bak.1774780058/xaifiles.js +48 -0
  129. package/types/API/openai.com/reponses/text.d.ts +17 -3
  130. package/types/API/x.ai/collections.d.ts +167 -0
  131. package/types/API/x.ai/files.d.ts +84 -0
  132. package/types/API/x.ai/responses.d.ts +379 -0
  133. package/types/AgentClient.d.ts +5 -0
  134. package/types/AgentManager.d.ts +25 -31
  135. package/types/AgentServer.d.ts +5 -1
  136. package/types/Prompt.d.ts +4 -2
  137. package/types/ToolSet.d.ts +1 -0
  138. package/types/index.d.ts +4 -3
  139. package/types/wsCli.d.ts +3 -0
  140. package/types/wsIO.d.ts +26 -0
  141. package/utils/bars.js +40 -0
  142. package/utils/clear_sessions.sh +54 -0
  143. package/{bin/hdInspect.js → utils/format_log.js} +5 -0
  144. package/utils/list_sessions.sh +46 -0
  145. package/utils/search_sessions.sh +73 -0
  146. package/utils/syntax_check.sh +61 -0
  147. package/utils/test.sh +46 -0
  148. package/bin/hdClear.js +0 -13
  149. package/bin/hdCode.js +0 -115
  150. package/bin/hdConnect.js +0 -230
  151. package/bin/hdNpm.js +0 -114
  152. package/bin/hdPrompt.js +0 -108
  153. package/examples/claude-test.js +0 -89
  154. package/examples/claude.js +0 -143
  155. package/examples/gpt.js +0 -127
  156. package/examples/gpt_code.js +0 -125
  157. package/examples/gpt_note_keeping.js +0 -117
  158. package/examples/grok.js +0 -119
  159. package/examples/grok_code.js +0 -114
  160. package/examples/grok_note_keeping.js +0 -111
  161. package/module.md +0 -189
@@ -2,14 +2,15 @@ import { Prompt, Cli, AgentClient, AgentServer, API, ToolSet, Session, env } fro
2
2
  import toolsPool from './genericToolset.js'
3
3
  /**
4
4
  * @typedef {import('./API/x.ai/text.js').XOptions} XOptions
5
+ * @typedef {import('./API/x.ai/responses.js').XAIOptions} XAIOptions
5
6
  * @typedef {import('./API/openai.com/reponses/text.js').OAOptions} OAOptions
6
7
  * @typedef {import('./API/anthropic.com/text.js').ANTHOptions} ANTHOptions
7
8
  */
8
9
  /**
9
10
  * @typedef {Object} Setup
10
11
  * @property {string} prompt - Initial system prompt
11
- * @property {OAOptions|XOptions|ANTHOptions} options - Model options
12
- * @property {'gpt'|'grok'|'claude'} api - AI endpoint to use
12
+ * @property {XAIOptions|OAOptions|XOptions|ANTHOptions} options - Model options
13
+ * @property {'gpt'|'xai'|'claude'} api - AI endpoint to use
13
14
  * @property {number} [contextWindow] - The size in tokens for the context/session
14
15
  * @property {'auto'|'required'|void} [toolsetMode] -
15
16
  * @property {boolean} [debug] - verbose output
@@ -17,6 +18,7 @@ import toolsPool from './genericToolset.js'
17
18
  /**
18
19
  * @typedef {Object} Options
19
20
  * @property {string} name - Agent name
21
+ * @property {string} secret - Secret string for WS access authorisation (server and client secrets should match)
20
22
  * @property {string} [cachePath] - path to session/record storage
21
23
  */
22
24
  class AgentManager {
@@ -25,13 +27,24 @@ class AgentManager {
25
27
  /** @type {Session} */
26
28
  #sessionStorage;
27
29
  #name = 'agent';
30
+ #secret = '';
28
31
  #cachePath = '.cache/hello-dave';
29
32
  #debug = false;
33
+ #model = '';
34
+ #contextWindow = 0;
35
+ #sysPrompt = '';
30
36
  /**
31
37
  * @param {Options} options
32
38
  */
33
39
  constructor(options) {
34
40
  this.#name = options.name || this.#name;
41
+ if (options.secret && typeof options.secret === 'string') {
42
+ this.#secret = Buffer.from(options.secret).toString('base64');
43
+ }
44
+ const validNameRegex = /^[a-z_0-9]{2,}$/;
45
+ 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).`);
47
+ }
35
48
  this.#cachePath = options.cachePath || this.#cachePath;
36
49
  }
37
50
 
@@ -47,6 +60,12 @@ class AgentManager {
47
60
  toolsetMode = null,
48
61
  debug = false
49
62
  } = setup;
63
+ this.#sysPrompt = prompt;
64
+ this.#contextWindow = contextWindow;
65
+ if (options?.model) this.#model = options.model;
66
+ this.#sysPrompt = prompt;
67
+ this.#contextWindow = contextWindow;
68
+ if (options?.model) this.#model = options.model;
50
69
  let toolset;
51
70
  if (toolsetMode) {
52
71
  toolset = new ToolSet(toolsetMode);
@@ -65,7 +84,7 @@ class AgentManager {
65
84
  * Start a CLI for local usage
66
85
  * @param {string} description - introduction message for the CLI user
67
86
  */
68
- startCli(description) {
87
+ #startCli(description) {
69
88
  if (!this.#prompt) throw new Error('Run setup first');
70
89
  const cli = new Cli({ prompt: this.#prompt, session: this.#sessionStorage, description });
71
90
  setTimeout(() => {
@@ -82,9 +101,9 @@ class AgentManager {
82
101
  * @param {string} description - function_call description
83
102
  * @param {string} [url='ws://127.0.0.1:8000/ws'] - ws URL
84
103
  */
85
- attach(name, description, url = 'ws://127.0.0.1:8000/ws') {
104
+ #attach(name, description, url = 'ws://127.0.0.1:8000/ws') {
86
105
  if (!this.#prompt) throw new Error('Run setup first');
87
- return new AgentClient({ prompt: this.#prompt, name, description, url });
106
+ return new AgentClient({ prompt: this.#prompt, name, description, url, secret: this.#secret });
88
107
  }
89
108
 
90
109
  /**
@@ -95,12 +114,13 @@ class AgentManager {
95
114
  * @param {string} description - function_call description
96
115
  * @param {number} [port=8000] - Start the dynamic toolset server on this port
97
116
  */
98
- enableServer(name, description = '', port = 8000) {
117
+ #enableServer(name, description = '', port = 8000) {
99
118
  if (!this.#prompt) throw new Error('Run setup first');
100
119
  if (!this.#prompt.toolset) throw new Error('No toolset defined');
101
120
  const server = new AgentServer({
102
121
  port,
103
122
  name,
123
+ secret: this.#secret,
104
124
  description,
105
125
  prompt: this.#prompt,
106
126
  session: this.#sessionStorage,
@@ -131,13 +151,63 @@ class AgentManager {
131
151
  return env();
132
152
  }
133
153
  /**
134
- * @param {string} name - the toolname
135
- */
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.
157
+ */
136
158
  addGenericToolcall(name) {
159
+ const validNameRegex = /^[a-z_0-9]{2,}$/;
160
+ 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).`);
162
+ }
137
163
  if (!this.#prompt.toolset) throw new Error('No ToolSet defined')
138
- let tool = toolsPool.get(name);
164
+ let tool = toolsPool.get(name);
139
165
  if (!tool) throw new Error('Tool not defined')
140
- this.#prompt.toolset.add(name, tool.description, tool.parameters, tool.method);
166
+ this.#prompt.toolset.add(name, tool.description, tool.parameters, tool.method);
167
+ }
168
+
169
+ /**
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).
176
+ */
177
+ async start(servePort, connectUrl, cliIntro = "", toolName = "", toolDescription = "") {
178
+ if (!this.#prompt) throw new Error("Run setup first");
179
+
180
+ const validNameRegex = /^[a-z_0-9]{2,}$/;
181
+
182
+ toolName = toolName || this.#name;
183
+ // Validate 'toolName' (or fallback agent name)
184
+ 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).`);
186
+ }
187
+
188
+ if (!toolDescription && this.#sysPrompt) {
189
+ toolDescription = this.#sysPrompt.slice(0, 100).trim() + "...";
190
+ }
191
+
192
+ if (!cliIntro) {
193
+ const introStr = this.#name + " " + (this.#model || "unknown-model") + " - context: " + this.#contextWindow;
194
+ cliIntro = introStr.trim();
195
+ }
196
+ if (servePort) {
197
+ console.log(toolName);
198
+ console.log(toolDescription);
199
+ this.#enableServer(toolName, toolDescription, servePort);
200
+ // A server can also be a client
201
+ if (connectUrl) {
202
+ this.#attach(toolName, toolDescription, connectUrl);
203
+ }
204
+ } else if (connectUrl) {
205
+ // Connect to a agent 'server' and enable via websocket / toolcalls
206
+ this.#attach(toolName, toolDescription, connectUrl);
207
+ } else {
208
+ // Terminal user CLI
209
+ this.#startCli(cliIntro);
210
+ }
141
211
  }
142
212
  }
143
213
 
@@ -19,11 +19,12 @@ let ws;
19
19
  * @property {messageContent} content
20
20
  */
21
21
  /**
22
- * @typedef {(conn: import('@j-o-r/apiserver/types/WebSocketServer.js').WebSocketConnection) => Promise<boolean>} AuthFunction
22
+ * @typedef {(conn: import('@j-o-r/apiserver/types/WebSocketServer.js').WebSocketConnection, req: any) => Promise<boolean>} AuthFunction
23
23
  */
24
24
  /**
25
25
  * @typedef {Object} AgentServerOptions
26
26
  * @property {string} name
27
+ * @property {string} secret - server access secret
27
28
  * @property {string} description
28
29
  * @property {Prompt} prompt
29
30
  * @property {Session} session
@@ -32,7 +33,7 @@ let ws;
32
33
  * @property {boolean} [debug = false]
33
34
  */
34
35
 
35
- const ACTIONS = [
36
+ const ACTIONS = [
36
37
  // Agent / Toolset function calls
37
38
  'agent_introduction', // Describe your task, your purpose and usage. This is a reaction on a 'introduce' requests
38
39
  'agent_error', // Message error
@@ -42,6 +43,7 @@ let ws;
42
43
  'user_introduction', // Websocket client connection on open
43
44
  'user_request', // A client user request
44
45
  'server_response', // A reponse to a user request
46
+ 'server_error', // A reponse to a user request
45
47
  'user_reset', // User requests a new session
46
48
  'user_sessionlist', // Request a list of sessions
47
49
  'user_loadsession', // Request to load a session
@@ -129,6 +131,7 @@ class AgentServer {
129
131
  #debug = false;
130
132
  #port = 8000;
131
133
  #name = '';
134
+ #secret = ''; // access secret
132
135
  #description = '';
133
136
  /** @type {Prompt} */
134
137
  #prompt
@@ -136,7 +139,9 @@ class AgentServer {
136
139
  #session
137
140
  /** @type {AuthFunction} */
138
141
  #auth = async (conn) => {
139
- return true;
142
+ const q = conn.client.query;
143
+ const key = q.get('wssrc_id');
144
+ return key === this.#secret;
140
145
  }
141
146
  /**
142
147
  * @param {AgentServerOptions} options
@@ -152,16 +157,25 @@ class AgentServer {
152
157
  this.#auth = options.auth;
153
158
  }
154
159
  this.#name = options.name;
160
+ this.#secret = options.secret;
155
161
  this.#description = options.description;
156
162
  this.#session = options.session;
157
163
  this.#prompt = options.prompt;
164
+ this.#debug = options.debug;
165
+ // LOG EVENTS
158
166
  const events = Object.keys(this.#prompt.EVENTS);
159
167
  events.forEach((evt) => {
160
168
  this.#prompt.on(evt, (_msg) => {
161
- console.log(evt);
169
+ // log events
170
+ console.log(`** ${this.#name} e:${evt}**`);
171
+ if (evt === 'tool_request') {
172
+ console.log(`tool execute: ${this.#name} ${_msg.name} ${_msg.call_id}`);
173
+ } else if (evt === 'tool_error') {
174
+ console.log(`tool error:`);
175
+ console.log(JSON.stringify(_msg, null, ' '));
176
+ }
162
177
  });
163
178
  });
164
- this.#debug = options.debug;
165
179
  // start
166
180
  (async () => {
167
181
  await this._start();
@@ -213,8 +227,8 @@ class AgentServer {
213
227
  const key = `${conn.id}:${msg.id}`; // Assume client includes original 'id' in response
214
228
  const pending = pendingResponses.get(key);
215
229
  if (pending) {
216
- try { clearInterval(pending.timer); } catch {}
217
- pending.resolve(msg.content);
230
+ try { clearInterval(pending.timer); } catch { }
231
+ pending.resolve(msg.content);
218
232
  pendingResponses.delete(key);
219
233
  }
220
234
  return;
@@ -223,8 +237,8 @@ class AgentServer {
223
237
  const key = `${conn.id}:${msg.id}`; // Assume client includes original 'id' in response
224
238
  const pending = pendingResponses.get(key);
225
239
  if (pending) {
226
- try { clearInterval(pending.timer); } catch {}
227
- pending.reject(msg.content);
240
+ try { clearInterval(pending.timer); } catch { }
241
+ pending.reject(msg.content);
228
242
  pendingResponses.delete(key);
229
243
  }
230
244
  return;
@@ -245,13 +259,23 @@ class AgentServer {
245
259
  }
246
260
  // Bind to THIS prompt
247
261
  console.log(`user_request:>>\n${msg.content}\n`);
248
- const content = await this.#prompt.call(msg.content);
249
- ws.sendToConnection(conn.id, JSON.stringify({
250
- action: 'server_response',
251
- id,
252
- content
253
- }));
254
- console.log(`server_reponse:>>\n${content}\n`);
262
+ try {
263
+ const content = await this.#prompt.call(msg.content);
264
+ ws.sendToConnection(conn.id, JSON.stringify({
265
+ action: 'server_response',
266
+ id,
267
+ content
268
+ }));
269
+ console.log(`server_reponse:>>\n${content}\n`);
270
+ } catch (e) {
271
+ console.log(`server_error:>>\n`);
272
+ console.error(e);
273
+ ws.sendToConnection(conn.id, JSON.stringify({
274
+ action: 'server_error',
275
+ id,
276
+ e
277
+ }));
278
+ }
255
279
  }
256
280
  if (msg.action === 'user_reset') {
257
281
  const id = msg.id;
@@ -278,18 +302,22 @@ class AgentServer {
278
302
  const selected = msg.content;
279
303
  const messages = [];
280
304
  const list = this.#session.set(selected);
281
- list.forEach((msg) => {
305
+ this.#prompt.messages = list;
306
+ let i = 0;
307
+ const length = list.length;
308
+ for (; i < length; i++) {
309
+ const msg = list[i];
282
310
  if (!msg.sticky) {
283
311
  if (['user', 'assistant', 'reasoning', 'log'].includes(msg.role)) {
284
- if (msg.role === 'assistant' && msg.content[0].type === 'function_request') {
285
-
286
- } else {
312
+ if (msg.content[0].type !== 'function_request') {
287
313
  const content = this.#prompt.contentToString(msg.content);
288
314
  messages.push({ role: msg.role, content });
289
315
  }
290
316
  }
291
317
  }
292
- });
318
+ };
319
+ // Resume execution
320
+ await this.#prompt.triggerRequest();
293
321
  ws.sendToConnection(conn.id, JSON.stringify({
294
322
  action: 'server_sessionloaded',
295
323
  id,
@@ -322,7 +350,7 @@ class AgentServer {
322
350
  }
323
351
  });
324
352
  await server.create('v1', { port, host: '127.0.0.1', ws, strict: DEBUG, verbose: DEBUG }, API);
325
- console.log(`ws running on port: ${port}`);
353
+ console.log(`Websocket server: ws://127.0.0.1:${port}/ws`);
326
354
  }
327
355
  /**
328
356
  * Send a reset messages to all clients
package/lib/Cli.js CHANGED
@@ -138,24 +138,30 @@ class Cli {
138
138
  ]);
139
139
  // Write messages
140
140
  this.#prompt.on('message', (msg) => {
141
+ let write = false;
141
142
  if (msg.role === 'reasoning') {
142
143
  const content = this.#prompt.contentToString(msg.content);
143
144
  cli.focus('util');
144
145
  cli.write(`REASONING: ---------\n${content}\n---------\n`);
146
+ write = true;
145
147
  } else if (msg.role === 'log') {
146
148
  const content = this.#prompt.contentToString(msg.content);
147
149
  cli.focus('log');
148
150
  cli.write(content);
151
+ write = true;
149
152
  } else if (msg.role === 'assistant') {
150
153
  if (msg.content[0].type === 'text') {
151
154
  const content = this.#prompt.contentToString(msg.content);
152
155
  if (content.trim() !== '') {
153
156
  cli.focus('assistant');
154
157
  cli.write(content);
158
+ write = true;
155
159
  }
156
160
  }
157
161
  }
158
- cli.startSpinner();
162
+ if (write) {
163
+ cli.startSpinner();
164
+ }
159
165
  });
160
166
  this.#prompt.on('truncated', () => {
161
167
  cli.focus('log');
package/lib/Prompt.js CHANGED
@@ -11,15 +11,17 @@ import { pruneResolvedToolIOByCallIdExceptLast as pruneResolvedToolIOByCallIdExc
11
11
  /**
12
12
  * @typedef {import('./API/openai.com/reponses/text.js').request} OARequest
13
13
  * @typedef {import('./API/x.ai/text.js').request} XRequest
14
+ * @typedef {import('./API/x.ai/responses.js').request} XAIRequest
14
15
  * @typedef {import('./API/anthropic.com/text.js').request} ANTHRequest
15
16
  *
16
17
  * @typedef {import('./API/x.ai/text.js').XOptions} XOptions
18
+ * @typedef {import('./API/x.ai/responses.js').XAIOptions} XAIOptions
17
19
  * @typedef {import('./API/openai.com/reponses/text.js').OAOptions} OAOptions
18
20
  * @typedef {import('./API/anthropic.com/text.js').ANTHOptions} ANTHOptions
19
21
  *
20
22
  * @typedef {import('./ToolSet.js').default} ToolSet
21
- * @typedef {OARequest|XRequest|ANTHRequest} request - The AI model to use for chat functionality.
22
- * @typedef {OAOptions|XOptions|ANTHOptions} options - Model options
23
+ * @typedef {OARequest|XRequest|ANTHRequest|XAIRequest} request - The AI model to use for chat functionality.
24
+ * @typedef {OAOptions|XOptions|ANTHOptions|XAIOptions} options - Model options
23
25
  */
24
26
 
25
27
  /**
package/lib/ToolSet.js CHANGED
@@ -126,6 +126,7 @@ class ToolSet {
126
126
  * Execute a method
127
127
  * @param {string} name
128
128
  * @param {object} params
129
+ * @returns {Promise<*>}
129
130
  */
130
131
  async call(name, params) {
131
132
  if (!this.has(name)) {
@@ -158,8 +159,8 @@ class ToolSet {
158
159
  try {
159
160
  response = await this.call(call.function_request.name, JSON.parse(call.function_request.parameters));
160
161
  } catch (error) {
161
- prompt.emit(prompt.EVENTS.tool_error, { name: call.function_request.name, call_id: call.function_request.call_id, error });
162
162
  response = `Error: ${error.name} - ${error.message}`;
163
+ prompt.emit(prompt.EVENTS.tool_error, { name: call.function_request.name, call_id: call.function_request.call_id, error: response });
163
164
  }
164
165
  const duration = new Date().getTime() - startTime;
165
166
  prompt.emit(prompt.EVENTS.tool_response, { name: call.function_request.name, call_id: call.function_request.call_id, duration });