@j-o-r/hello-dave 0.0.0

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 (53) hide show
  1. package/LICENSE +73 -0
  2. package/README.md +207 -0
  3. package/bin/hdAsk.js +103 -0
  4. package/bin/hdClear.js +13 -0
  5. package/bin/hdCode.js +110 -0
  6. package/bin/hdConnect.js +230 -0
  7. package/bin/hdInspect.js +28 -0
  8. package/bin/hdNpm.js +114 -0
  9. package/bin/hdPrompt.js +108 -0
  10. package/examples/claude-test.js +89 -0
  11. package/examples/claude.js +143 -0
  12. package/examples/gpt.js +127 -0
  13. package/examples/gpt_code.js +125 -0
  14. package/examples/gpt_note_keeping.js +117 -0
  15. package/examples/grok.js +119 -0
  16. package/examples/grok_code.js +114 -0
  17. package/examples/grok_note_keeping.js +111 -0
  18. package/lib/API/anthropic.com/text.js +402 -0
  19. package/lib/API/brave.com/search.js +239 -0
  20. package/lib/API/openai.com/README.md +1 -0
  21. package/lib/API/openai.com/reponses/MESSAGES.md +69 -0
  22. package/lib/API/openai.com/reponses/text.js +416 -0
  23. package/lib/API/x.ai/text.js +415 -0
  24. package/lib/AgentClient.js +197 -0
  25. package/lib/AgentManager.js +144 -0
  26. package/lib/AgentServer.js +336 -0
  27. package/lib/Cli.js +256 -0
  28. package/lib/Prompt.js +728 -0
  29. package/lib/Session.js +231 -0
  30. package/lib/ToolSet.js +186 -0
  31. package/lib/fafs.js +93 -0
  32. package/lib/genericToolset.js +170 -0
  33. package/lib/index.js +34 -0
  34. package/lib/promptHelpers.js +132 -0
  35. package/lib/testToolset.js +42 -0
  36. package/module.md +189 -0
  37. package/package.json +49 -0
  38. package/types/API/anthropic.com/text.d.ts +207 -0
  39. package/types/API/brave.com/search.d.ts +156 -0
  40. package/types/API/openai.com/reponses/text.d.ts +225 -0
  41. package/types/API/x.ai/text.d.ts +286 -0
  42. package/types/AgentClient.d.ts +70 -0
  43. package/types/AgentManager.d.ts +112 -0
  44. package/types/AgentServer.d.ts +38 -0
  45. package/types/Cli.d.ts +52 -0
  46. package/types/Prompt.d.ts +298 -0
  47. package/types/Session.d.ts +31 -0
  48. package/types/ToolSet.d.ts +95 -0
  49. package/types/fafs.d.ts +47 -0
  50. package/types/genericToolset.d.ts +3 -0
  51. package/types/index.d.ts +23 -0
  52. package/types/promptHelpers.d.ts +1 -0
  53. package/types/testToolset.d.ts +3 -0
@@ -0,0 +1,230 @@
1
+ #!/usr/bin/env -S node
2
+ /*
3
+ * Websocket client for a hello-dave server
4
+ */
5
+ import cli from '@j-o-r/cli';
6
+ import { WebSocketClient } from "@j-o-r/apiserver";
7
+ import { parseArgs, SH } from '@j-o-r/sh';
8
+ const args = parseArgs();
9
+
10
+
11
+ /**
12
+ * Copy text to the clipboard
13
+ * @param {string} text
14
+ * @retruns {Promise<string>}
15
+ */
16
+ const copyToClipboard = async (text) => {
17
+ if (typeof text !== 'string') return;
18
+ if (text === '') text = ' ';
19
+ const prams = [
20
+ '-selection',
21
+ 'clipboard'
22
+ ]
23
+ return SH`xclip ${prams}`.options({ stdio: 'inherit' }).run(text);
24
+ }
25
+
26
+ const HELP = () => {
27
+ console.log(
28
+ `
29
+ hdConnect [url]
30
+
31
+ usage:
32
+ npx hdConnect ws:/127.0.0.1:8000/ws
33
+ `.trim()
34
+ )
35
+ process.exit(1);
36
+ }
37
+
38
+ if (args._.length !== 1) {
39
+ HELP();
40
+ }
41
+ const connect = args._[0];
42
+ let busy = false;
43
+ let lastMessage = '';
44
+ const pendingRequests = new Map(); // key: msg_id (or `${conn_id}:${msg_id}` if conn_id is available), value: {resolve, reject, timeout} 11:06:22 [32/1290]
45
+
46
+ const ws = new WebSocketClient(connect);
47
+ ws.onopen = () => {
48
+ ws.send(JSON.stringify({
49
+ action: 'user_introduction',
50
+ content: '',
51
+ id: new Date().getTime()
52
+ }));
53
+ }
54
+ /**
55
+ * @param {MessageEvent} m
56
+ */
57
+ ws.onmessage = (m) => {
58
+ try {
59
+ const data = JSON.parse(m.data);
60
+ const msgId = data.id; // Assume response has the same 'id' as the request
61
+ if (msgId && pendingRequests.has(msgId)) {
62
+ const { resolve, timeout } = pendingRequests.get(msgId);
63
+ clearTimeout(timeout); // Cancel the timeout
64
+ pendingRequests.delete(msgId);
65
+ resolve(data); // Resolve the promise with the response data
66
+ }
67
+ } catch (e) {
68
+ console.error('Error parsing WebSocket message:', e);
69
+ }
70
+ }
71
+ ws.onclose = () => {
72
+ console.log('Lost connection');
73
+ // Optionally, reject all pending requests here
74
+ for (const [id, { reject }] of pendingRequests) {
75
+ reject(new Error('Connection closed'));
76
+ pendingRequests.delete(id);
77
+ }
78
+ }
79
+ ws.onerror = (e) => {
80
+ console.error('WebSocket error:', e);
81
+ // Optionally, reject all pending requests on error
82
+ for (const [id, { reject }] of pendingRequests) {
83
+ reject(e);
84
+ pendingRequests.delete(id);
85
+ }
86
+ }
87
+
88
+
89
+ cli.registerKeyMappings([
90
+ { // Clear the screen
91
+ // ALT - c
92
+ name: 'c', ctrl: false, meta: true, shift: false, handler: async () => {
93
+ if (!busy) {
94
+ cli.clear();
95
+ }
96
+ }
97
+ },
98
+ { // reset the session, empty the context from the prompt
99
+ // ALT - r
100
+ name: 'r', ctrl: false, meta: true, shift: false, handler: async () => {
101
+ if (!busy) {
102
+ await sendMessage({
103
+ action: 'user_reset',
104
+ content: ''
105
+ });
106
+ }
107
+ }
108
+ },
109
+ { // load a previous ssession
110
+ // ALT - s
111
+ name: 's', ctrl: false, meta: true, shift: false, handler: async () => {
112
+ if (!busy) {
113
+ await sendMessage({
114
+ action: 'user_sessionlist',
115
+ content: '',
116
+ });
117
+ }
118
+ }
119
+ },
120
+
121
+ { // Request server info
122
+ // ALT - i
123
+ name: 'i', ctrl: false, meta: true, shift: false, handler: async () => {
124
+ if (!busy) {
125
+ await sendMessage({
126
+ action: 'user_info',
127
+ content: '',
128
+ });
129
+ }
130
+ }
131
+ },
132
+ { // Copy last message to clipboard
133
+ name: 'm', ctrl: false, meta: true, shift: false, handler: async () => {
134
+ if (!busy) {
135
+ const r = await copyToClipboard(lastMessage);
136
+ cli.focus('util');
137
+ cli.write('copied');
138
+ cli.focus('user', true);
139
+ }
140
+ }
141
+ },
142
+ { // Show help /keys
143
+ name: 'k', ctrl: true, meta: false, shift: false, handler: async () => {
144
+ // cli.focus('util')
145
+ // cli.write(HELP)
146
+ // cli.focus('user', true);
147
+ }
148
+ }
149
+ ]);
150
+
151
+
152
+ const sendMessage = async (m) => {
153
+ const id = new Date().getTime(); // Unique ID for the request
154
+ m.id = id;
155
+ busy = true;
156
+ ws.send(JSON.stringify(m));
157
+
158
+ // Create a promise and store it in pendingRequests
159
+ const promise = new Promise((resolve, reject) => {
160
+ const timeout = setTimeout(() => {
161
+ pendingRequests.delete(id);
162
+ reject(new Error('Request timeout')); // Timeout after 10 seconds (adjust as needed)
163
+ }, 1000 * 60 * 60 * 12); // 12 hours
164
+ pendingRequests.set(id, { resolve, reject, timeout });
165
+ });
166
+
167
+ cli.startSpinner(); // Start spinner while waiting
168
+ try {
169
+ const response = await promise; // Wait for the response
170
+ // Process the response here (e.g., log it or display it)
171
+ // console.log('Response received:', response);
172
+ if (response.action === 'server_response') {
173
+ cli.focus('assistant');
174
+ cli.write(response.content);
175
+ lastMessage = response.content;
176
+ }
177
+ if (response.action === 'server_info') {
178
+ cli.focus('util');
179
+ cli.write(response.content);
180
+ }
181
+ if (response.action === 'server_reset') {
182
+ cli.clear();
183
+ }
184
+ if (response.action === 'server_sessionlist') {
185
+ // Select a session to load
186
+ const list = response.content;
187
+ const selected = await cli.select('Select your session: ', list);
188
+ if (selected && selected !== 'NONE') {
189
+ return sendMessage({ action: 'user_loadsession', content: selected });
190
+ }
191
+ }
192
+ if (response.action === 'server_sessionloaded') {
193
+ // Putput the selected session messages
194
+ cli.clear();
195
+ const messages = response.content;
196
+ messages.forEach((msg) => {
197
+ cli.focus(msg.role);
198
+ cli.write(msg.content);
199
+ lastMessage = msg.content;
200
+ });
201
+ }
202
+ } catch (e) {
203
+ console.error('Error waiting for response:', e);
204
+ // Handle error (e.g., show error message to user)
205
+ } finally {
206
+ busy = false;
207
+ cli.stopSpinner(); // Stop spinner
208
+ cli.focus('user', true); // Give focus back to user input
209
+ }
210
+
211
+ }
212
+
213
+ // @ts-ignore
214
+ cli.inputHandler = async (s) => {
215
+ if (!s || s.trim() === '') {
216
+ // busy = false;
217
+ // cli.focus('user', true); // Give focus back to user input
218
+ return;
219
+ }
220
+ const m = {
221
+ action: 'user_request',
222
+ content: s
223
+ }
224
+ await sendMessage(m);
225
+ }
226
+
227
+ cli.focus('log');
228
+ cli.write('CTRL - d exit');
229
+ cli.write('CTRL - r clear screen / reset');
230
+ cli.focus('user', true);
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env -S node
2
+ import { CacheSync } from "@j-o-r/cache";
3
+ import path from 'node:path';
4
+ import { parseArgs, readIn } from '@j-o-r/sh';
5
+
6
+ const args = parseArgs();
7
+ if (args._.length !== 1) {
8
+ console.log(
9
+ `File as an argument`.trim()
10
+ )
11
+ }
12
+ const filePath = args._[0]; // or any relative/absolute path
13
+
14
+ // folder
15
+ const folder = path.resolve(path.dirname(filePath)); // 'a/b'
16
+
17
+ // filename without extension
18
+ const { name } = path.parse(filePath); // name = 'c'
19
+ // or: const name2 = path.basename(filePath, path.extname(filePath));
20
+
21
+ // extension (including dot)
22
+ const ext = path.extname(filePath).slice(1); // '.txt'
23
+
24
+ console.log({ folder, name, ext });
25
+
26
+ const c = new CacheSync(folder, false, ext);
27
+ const content = c.read(name);
28
+ console.log(JSON.stringify(content, null, ' '));
package/bin/hdNpm.js ADDED
@@ -0,0 +1,114 @@
1
+ #!/usr/bin/env node
2
+ import AgentManager from '../lib/AgentManager.js';
3
+ import { parseArgs, readIn } from '@j-o-r/sh';
4
+ import { systemInfo } from '../lib/fafs.js';
5
+
6
+ const name = 'hdNpm';
7
+ const api = 'grok';
8
+
9
+ const input = await readIn();
10
+ const args = parseArgs();
11
+ const help = args['help'] || false;
12
+ const connect = args['connect'] ? args['connect'] : undefined;
13
+ const serve = args['serve'] ? parseInt(args['serve']) : undefined;
14
+
15
+ /** @type {import('lib/API/x.ai/text.js').XOptions} */
16
+ const options = {}
17
+ // Set properties only if provided via command line (except model which has default)
18
+ if (args['model'] || true) { // model gets default value
19
+ // @ts-ignore
20
+ options.model = args['model'] || 'grok-code-fast-1';
21
+ }
22
+ if (args['temperature']) {
23
+ options.temperature = parseFloat(args['temperature']);
24
+ }
25
+ if (args['tokens']) {
26
+ options.max_completion_tokens = parseInt(args['tokens']);
27
+ }
28
+ if (args['top_p']) {
29
+ options.top_p = parseFloat(args['top_p']);
30
+ }
31
+ options.search_parameters = { mode: 'auto' }
32
+ const reasoning = args['reasoning'] ? args['reasoning'] : null;
33
+ if (reasoning) {
34
+ // @ts-ignore
35
+ options.reasoning_effort = reasoning
36
+ }
37
+
38
+ const toolsetMode = 'auto';
39
+ const contextWindow = args['context'] ? parseInt(args['context']) : 250000;
40
+
41
+ // Copy from the generic toolset
42
+ function printHelp() {
43
+ console.log(`
44
+ '${name} --help' You are looking at it.
45
+ '
46
+ OPTIONS:
47
+ --tokens [number]: max generated tokens
48
+ --context [number] : truncate message history to context-windows size default 130000
49
+ --temperature [float] : -2 / +2
50
+ --model [grok-4|grok-3|grok-3-mini|grok-3-mini-fast|grok-code-fast-1]
51
+ --top_p [float]: number > 0, 0.1 means no top_p
52
+ --reasoning [low|high]
53
+ --tools [javascript,bash] comma seperated list
54
+ e.g.
55
+ grok.js --model grok-3-mini --tokens 4000 --context 10000
56
+
57
+ `);
58
+ process.exit()
59
+ }
60
+
61
+ if (help) {
62
+ printHelp();
63
+ }
64
+
65
+ const prompt = `
66
+ Assume the module's root directory is the current working directory (cwd) and it's already installed. Inspect:
67
+ - package.json: Extract name, version, description, dependencies, scripts, and entry points.
68
+ - README.md: Summarize installation (noting it's already installed), usage examples, and key features.
69
+ - types/ folder: List and describe TypeScript declaration files (e.g., interfaces, types) to explain the API.
70
+ - node_modules/: Check for any 'module.md' files in installed dependencies and incorporate relevant additional information.
71
+ - Additional files: If API or usage is unclear, inspect relevant files like source code or examples for clarification.
72
+
73
+ Focus on enabling API usage. Generate markdown content with sections: Overview, Installation Notes, API Usage Examples, Full API Reference (from types and inspections), and Dependencies.
74
+ Write the full markdown content to './module.md'.
75
+ `.trim();
76
+ const agent = new AgentManager({ name });
77
+ agent.setup({
78
+ prompt,
79
+ api,
80
+ options,
81
+ toolsetMode,
82
+ contextWindow
83
+ });
84
+ const toolset = agent.getToolset();
85
+ if (toolset) {
86
+ const addTools = (args['tools']) ? args['tools'].split(',') : ['bash'];
87
+ if (addTools.includes('javascript')) {
88
+ agent.addGenericToolcall('javascript_interpreter');
89
+ }
90
+ if (addTools.includes('bash')) {
91
+ agent.addGenericToolcall('execute_bash_script');
92
+ }
93
+ }
94
+ const cliIntro = `
95
+ ${name} ${options.model}.
96
+ - search ${options.search_parameters.mode}
97
+ - context: ${contextWindow}
98
+ `.trim();
99
+ const description = `
100
+ NPM module expert, creates api usage for this module.
101
+ `.trim();
102
+
103
+ if (input === '' && serve) {
104
+ agent.enableServer('code', description, serve);
105
+ }
106
+ if (input !== '') {
107
+ // Direct input output
108
+ const res = await agent.directCall(input);
109
+ console.log(res);
110
+ } else if (connect) {
111
+ agent.attach('code', description, connect)
112
+ } else {
113
+ agent.startCli(cliIntro);
114
+ }
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env node
2
+ import AgentManager from '../lib/AgentManager.js';
3
+ import { parseArgs, readIn } from '@j-o-r/sh';
4
+
5
+ // const name = path.basename(fileURLToPath(import.meta.url), path.extname(fileURLToPath(import.meta.url)));
6
+ const name = 'hdPrompt';
7
+ const api = 'grok';
8
+
9
+ const input = await readIn();
10
+ const args = parseArgs();
11
+ const help = args['help'] || false;
12
+ const connect = args['connect'] ? args['connect'] : undefined;
13
+ const serve = args['serve'] ? parseInt(args['serve']) : undefined;
14
+
15
+ /** @type {import('lib/API/x.ai/text.js').XOptions} */
16
+ const options = {}
17
+ // Set properties only if provided via command line (except model which has default)
18
+ if (args['model'] || true) { // model gets default value
19
+ // @ts-ignore
20
+ options.model = args['model'] || 'grok-4';
21
+ }
22
+ if (args['temperature']) {
23
+ options.temperature = parseFloat(args['temperature']);
24
+ }
25
+ if (args['tokens']) {
26
+ options.max_completion_tokens = parseInt(args['tokens']);
27
+ }
28
+ if (args['top_p']) {
29
+ options.top_p = parseFloat(args['top_p']);
30
+ }
31
+
32
+ options.search_parameters = { mode: 'auto' }
33
+ // @ts-ignore
34
+ const reasoning = args['reasoning'] ? args['reasoning'] : null;
35
+ if (reasoning) {
36
+ // @ts-ignore
37
+ options.reasoning_effort = reasoning
38
+ }
39
+ const toolsetMode = (args.tools) ? 'auto' : undefined;
40
+ const contextWindow = args['context'] ? parseInt(args['context']) : 250000;
41
+
42
+ function printHelp() {
43
+ console.log(`
44
+ '${name} --help' You are looking at it.
45
+ '
46
+ OPTIONS:
47
+ --tokens [number]: max generated tokens
48
+ --context [number] : truncate message history to context-windows size default 130000
49
+ --temperature [float] : -2 / +2
50
+ --model [grok-4|grok-3|grok-3-mini|grok-3-mini-fast]
51
+ --top_p [float]: number > 0, 0.1 means no top_p
52
+ --reasoning [low|high]
53
+ --tools [javascript,bash] comma seperated list
54
+ e.g.
55
+ grok.js --model grok-3-mini --tokens 4000 --context 10000
56
+
57
+ `);
58
+ process.exit()
59
+ }
60
+
61
+ if (help) {
62
+ printHelp();
63
+ }
64
+ // reason step by step
65
+
66
+ const prompt = `
67
+ You are a prompt optimizer. Check for: 1) Clarity and specificity. 2) Brevity, non-ambiguity, ethics. 3) Token efficiency. If good, say "Approved." If not, rewrite concisely or ask 1-2 questions. Output: - Summary. - Rewritten prompt (if needed). - Questions (if unclear). Be efficient.
68
+ `.trim();
69
+ const agent = new AgentManager({ name });
70
+ agent.setup({
71
+ prompt,
72
+ api,
73
+ options,
74
+ toolsetMode,
75
+ contextWindow
76
+ });
77
+ const toolset = agent.getToolset();
78
+ if (toolset) {
79
+ const addTools = args['tools'].split(',') || [];
80
+ if (addTools.includes('javascript')) {
81
+ agent.addGenericToolcall('javascript_interpreter')
82
+ }
83
+ if (addTools.includes('bash')) {
84
+ agent.addGenericToolcall('execute_bash_script');
85
+ }
86
+ }
87
+
88
+ const cliIntro = `
89
+ ${name} ${options.model}.
90
+ search ${options.search_parameters.mode}
91
+ `.trim();
92
+
93
+ const description = `
94
+ Given a specific prompt, inspect and adjust it for better readability and clarity.
95
+ `.trim();
96
+
97
+ if (input === '' && serve) {
98
+ agent.enableServer(name, description, serve);
99
+ }
100
+ if (input !== '') {
101
+ // Direct input output
102
+ const res = await agent.directCall(input);
103
+ console.log(res);
104
+ } else if(connect) {
105
+ agent.attach(name, description, connect)
106
+ } else {
107
+ agent.startCli(cliIntro);
108
+ }
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env node
2
+ /*
3
+ * Claude test with a simple toolset
4
+ */
5
+ // -------------------------------
6
+ const PROMPT_NAME = 'claude-test'
7
+ // ------------------------------
8
+ import { Prompt, API, CliWrapper, Session, env } from '../lib/index.js';
9
+ import { parseArgs, SH } from '@j-o-r/sh';
10
+ import toolset from '../lib/testToolset.js';
11
+
12
+ const session = new Session(PROMPT_NAME);
13
+
14
+ const args = parseArgs();
15
+ // Get parameter values
16
+ const max_completion_tokens = args['tokens'] ? parseInt(args['tokens']) : 4000;
17
+ const context_window = args['context'] ? parseInt(args['context']) : 7000;
18
+ const temperature = args['temperature'] ? parseFloat(args['temperature']) : 0.4;
19
+ const model = args['model'] ? args['model'] : 'claude-3-7-sonnet-latest';
20
+ const thinking = args['thinking'] ? parseInt(args['thinking']) : 0;
21
+ const search = args['search'] ? parseInt(args['search']) : 0;
22
+ const help = args['help'] || false;
23
+
24
+ function printHelp() {
25
+ console.log(`
26
+ '${PROMPT_NAME} --help' You are looking at it.
27
+ '
28
+ OPTIONS:
29
+ --tokens [number]: max generated tokens default 4000
30
+ --context [number] : truncate message history to context-windows size default 700
31
+ --temperature [float] : -2 / +2 default 0.4
32
+ --model [grok-3|grok-3-mini|grok-3-mini-fast]
33
+ --thinking [number_of_tokens] default 0
34
+ --search [number_of_search_request] default 0 (no search)
35
+ e.g.
36
+ daisy --model grok-3-mini --tokens 4000 --context 10000
37
+
38
+ `);
39
+ process.exit()
40
+ }
41
+
42
+ const userInfo = await env();
43
+ /** @type {import('lib/API/anthropic.com/text.js').SearchOptions} */
44
+ const searchOptions = {
45
+ type: 'web_search_20250305',
46
+ name: 'web_search',
47
+ max_uses: 5,
48
+ user_location: {
49
+ type: 'approximate',
50
+ timezone: userInfo.timezone,
51
+ region: userInfo.region,
52
+ city: userInfo.city,
53
+ country: userInfo.country
54
+ }
55
+ }
56
+ if (help) {
57
+ printHelp();
58
+ }
59
+ // reason step by step
60
+
61
+ const PROMPT = `
62
+ You an assistant dedicated to answering questions.
63
+ - Reason step by step.
64
+ - Be very brief.
65
+ `.trim();
66
+ const prompt = new Prompt(context_window);
67
+ prompt.add('system', PROMPT.trim(), true);
68
+ /** @type {import('lib/API/anthropic.com/text.js').ANTHOptions} */
69
+ const options = {
70
+ model,
71
+ temperature: temperature,
72
+ max_tokens: max_completion_tokens
73
+ }
74
+ // Enable reasoning
75
+ if (thinking > 0) {
76
+ options.thinking = {
77
+ type: "enabled",
78
+ budget_tokens: thinking
79
+ }
80
+ }
81
+ if (search > 0) {
82
+ searchOptions.max_uses = search;
83
+ options.search = searchOptions
84
+ }
85
+ const intro = `
86
+ Hi, I am ${PROMPT_NAME} ${options.model}, your assistant in this project.
87
+ `;
88
+ const cli = new CliWrapper({ request: API.text[PROMPT_NAME], session, intro, prompt, toolset, options });
89
+ cli.start();