@j-o-r/hello-dave 0.0.1 → 0.0.3

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 (63) hide show
  1. package/README.md +288 -163
  2. package/README.md.backup +269 -0
  3. package/bin/dave.js +165 -0
  4. package/examples/CodeServer +43 -0
  5. package/{bin/hdAsk.js → examples/askDave.js} +50 -39
  6. package/examples/codeDave.js +115 -0
  7. package/examples/coderev.js +72 -0
  8. package/examples/daisy.js +177 -0
  9. package/examples/docsDave.js +119 -0
  10. package/examples/gpt.js +54 -72
  11. package/examples/grok.js +47 -68
  12. package/examples/npmDave.js +175 -0
  13. package/examples/promptDave.js +112 -0
  14. package/examples/readmeDave.js +144 -0
  15. package/examples/spawndave.js +240 -0
  16. package/examples/todoDave.js +132 -0
  17. package/lib/API/openai.com/reponses/text.js +12 -18
  18. package/lib/API/x.ai/collections.js +354 -0
  19. package/lib/API/x.ai/files.js +218 -0
  20. package/lib/API/x.ai/responses.js +494 -0
  21. package/lib/API/x.ai/text.js +2 -2
  22. package/lib/AgentClient.js +13 -6
  23. package/lib/AgentManager.js +79 -10
  24. package/lib/AgentServer.js +45 -21
  25. package/lib/Cli.js +7 -1
  26. package/lib/Prompt.js +4 -2
  27. package/lib/ToolSet.js +2 -1
  28. package/lib/fafs.js +1 -0
  29. package/lib/genericToolset.js +152 -51
  30. package/lib/index.js +4 -2
  31. package/lib/wsCli.js +257 -0
  32. package/lib/wsIO.js +96 -0
  33. package/package.json +26 -20
  34. package/types/API/openai.com/reponses/text.d.ts +17 -3
  35. package/types/API/x.ai/collections.d.ts +167 -0
  36. package/types/API/x.ai/files.d.ts +84 -0
  37. package/types/API/x.ai/responses.d.ts +379 -0
  38. package/types/API/x.ai/text.d.ts +2 -2
  39. package/types/AgentClient.d.ts +5 -0
  40. package/types/AgentManager.d.ts +24 -31
  41. package/types/AgentServer.d.ts +5 -1
  42. package/types/Prompt.d.ts +4 -2
  43. package/types/ToolSet.d.ts +1 -0
  44. package/types/index.d.ts +4 -3
  45. package/types/wsCli.d.ts +3 -0
  46. package/types/wsIO.d.ts +26 -0
  47. package/utils/bars.js +40 -0
  48. package/utils/clear_sessions.sh +54 -0
  49. package/{bin/hdInspect.js → utils/format_log.js} +5 -0
  50. package/utils/list_sessions.sh +46 -0
  51. package/utils/search_sessions.sh +73 -0
  52. package/bin/hdClear.js +0 -13
  53. package/bin/hdCode.js +0 -110
  54. package/bin/hdConnect.js +0 -230
  55. package/bin/hdNpm.js +0 -114
  56. package/bin/hdPrompt.js +0 -108
  57. package/examples/claude-test.js +0 -89
  58. package/examples/claude.js +0 -143
  59. package/examples/gpt_code.js +0 -125
  60. package/examples/gpt_note_keeping.js +0 -117
  61. package/examples/grok_code.js +0 -114
  62. package/examples/grok_note_keeping.js +0 -111
  63. package/module.md +0 -189
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @typedef {object} wsResponse
3
+ * @property {string} action
4
+ * @property {string} content
5
+ * @property {number} id - message id
6
+ */
7
+ /**
8
+ * One-shot WebSocket client for hello-dave server using standard 'ws' library.
9
+ * Connects directly to pure WS endpoint (no HTTP upgrade).
10
+ * Sends intro + action, awaits matching response by ID, closes, returns response.
11
+ *
12
+ * @param {string} connectUrl - Websocket server endpoint to connect to
13
+ * @param {string} [secret] - Secret websocket connection key
14
+ * @param {'user_request'|'user_info'|'user_reset'} action - Action
15
+ * @param {string} [input] - When action is 'user_request' input is the query
16
+ * @returns {Promise<wsResponse>}
17
+ */
18
+ export default function wsio(connectUrl: string, secret?: string, action: "user_request" | "user_info" | "user_reset", input?: string): Promise<wsResponse>;
19
+ export type wsResponse = {
20
+ action: string;
21
+ content: string;
22
+ /**
23
+ * - message id
24
+ */
25
+ id: number;
26
+ };
package/utils/bars.js ADDED
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env node
2
+ const height = 10; // Change this to test scaling
3
+ const width = 20;
4
+ const mid = Math.floor(height / 2);
5
+ const bar = '\u2502'; // │
6
+ const horiz = '\u2500'; // ─
7
+
8
+ function draw(bars, silent = false) {
9
+ let grid = Array(height).fill().map(() => Array(width).fill(' '));
10
+ if (silent) {
11
+ grid[mid] = Array(width).fill(horiz);
12
+ } else {
13
+ for (let x = 0; x < width; x++) {
14
+ let h = bars[x];
15
+ let start = mid - Math.floor(h / 2);
16
+ for (let y = Math.max(0, start); y < Math.min(height, start + h); y++) {
17
+ grid[y][x] = bar;
18
+ }
19
+ }
20
+ }
21
+ return grid.map(row => row.join('')).join('\n');
22
+ }
23
+
24
+ let frame = 0;
25
+ setInterval(() => {
26
+ console.clear();
27
+ if (frame % 10 < 5) { // Alternate silent and animating
28
+ console.log(draw([], true)); // Silent
29
+ } else {
30
+ let bars = Array(width).fill(0);
31
+ const center = (width - 1) / 2;
32
+ for (let x = 0; x < width; x++) {
33
+ let norm_dist = Math.abs(x - center) / (center + 0.5);
34
+ let max_h = Math.min(height, Math.floor(height * (1 - norm_dist)) + 1);
35
+ bars[x] = Math.floor(Math.random() * max_h) + 1;
36
+ }
37
+ console.log(draw(bars));
38
+ }
39
+ frame++;
40
+ }, 200);
@@ -0,0 +1,54 @@
1
+ #!/bin/bash
2
+ # Delete entire agent directories (including logs/, records/, and sessions/) that contain all three.
3
+ # Usage: ./utils/clear_sessions.sh
4
+ # Lists targets (unique/sorted), then deletes them without confirmation.
5
+
6
+ set -uo pipefail
7
+
8
+ CACHE_BASE=".cache"
9
+
10
+ echo "🔍 Scanning for agent directories containing logs/, records/, and sessions/..."
11
+ echo "=================================================================="
12
+
13
+ declare -a agent_dirs=()
14
+ declare -a targets=()
15
+
16
+ # Load all candidate agent dirs into array (null-separated, sorted)
17
+ mapfile -t -d '' agent_dirs < <(find "$CACHE_BASE" -mindepth 2 -maxdepth 2 -type d -print0 2>/dev/null | sort -z)
18
+
19
+ echo "📊 Found ${#agent_dirs[@]} candidate agent directories. Filtering..."
20
+
21
+ for agent_dir in "${agent_dirs[@]}"; do
22
+ if [[ -n "$agent_dir" && -d "$agent_dir/logs" && -d "$agent_dir/records" && -d "$agent_dir/sessions" ]]; then
23
+ app_name="$(basename "$(dirname "$agent_dir")")"
24
+ prompt_name="$(basename "$agent_dir")"
25
+ targets+=("$agent_dir")
26
+ echo "📁 Target: $app_name/$prompt_name/ (will be DELETED entirely)"
27
+ fi
28
+ done
29
+
30
+ target_count=${#targets[@]}
31
+
32
+ echo ""
33
+ if [ "$target_count" -eq 0 ]; then
34
+ echo "✅ No matching directories found."
35
+ exit 0
36
+ fi
37
+
38
+ echo "⚠️ Will DELETE ENTIRELY $target_count directories."
39
+ echo " (logs/, records/, sessions/ and all other contents gone.)"
40
+ echo ""
41
+
42
+ # No confirmation, proceed directly
43
+
44
+ cleared=0
45
+ for agent_dir in "${targets[@]}"; do
46
+ echo "🧹 Deleting $agent_dir ..."
47
+ rm -rf "$agent_dir" 2>/dev/null || true
48
+ # Verify dir is gone
49
+ if [[ ! -d "$agent_dir" ]]; then
50
+ cleared=$((cleared + 1))
51
+ fi
52
+ done
53
+
54
+ echo "✅ Deleted $cleared/$target_count directories."
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env -S node
2
+ // Formatted output of hello-dave cache files [*.ndjson]
2
3
  import { CacheSync } from "@j-o-r/cache";
3
4
  import path from 'node:path';
4
5
  import { parseArgs, readIn } from '@j-o-r/sh';
@@ -25,4 +26,8 @@ console.log({ folder, name, ext });
25
26
 
26
27
  const c = new CacheSync(folder, false, ext);
27
28
  const content = c.read(name);
29
+ if (!content) {
30
+ console.error(`Not Found: ${filePath}`);
31
+ process.exit(1);
32
+ }
28
33
  console.log(JSON.stringify(content, null, ' '));
@@ -0,0 +1,46 @@
1
+ #!/bin/bash
2
+ # List unique sessions (once) per agent across all apps hierarchically, with latest mod timestamp.
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.
5
+
6
+ CACHE_BASE=".cache"
7
+ shopt -s nullglob
8
+
9
+ for app_dir in "$CACHE_BASE"/*/; do
10
+ if [[ ! -d "$app_dir" ]]; then
11
+ continue
12
+ fi
13
+ app_name=$(basename "$app_dir")
14
+ echo "$app_name:"
15
+ has_sessions=false
16
+ for sessions_dir in "$app_dir"/*/sessions/; do
17
+ if [[ ! -d "$sessions_dir" ]]; then
18
+ continue
19
+ fi
20
+ agent=$(basename "$(dirname "$sessions_dir")")
21
+
22
+ unset timestamps || true
23
+ declare -A timestamps
24
+ for f in "$sessions_dir"/*.ndjson; do
25
+ if [[ -f "$f" ]]; then
26
+ name=$(basename "$f" .ndjson)
27
+ base=$(echo "$name" | sed 's/_[0-9]\+$//' | sed 's/_\+/ /g' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
28
+ mtime=$(date -r "$f" '+%Y-%m-%d %H:%M')
29
+ if [[ -z "${timestamps[$base]}" || "$mtime" > "${timestamps[$base]}" ]]; then
30
+ timestamps[$base]="$mtime"
31
+ fi
32
+ fi
33
+ done
34
+
35
+ if [[ ${#timestamps[@]} -gt 0 ]]; then
36
+ echo " $agent:"
37
+ for base in "${!timestamps[@]}"; do
38
+ echo " - $base ... (${timestamps[$base]})"
39
+ done | sort
40
+ has_sessions=true
41
+ fi
42
+ done
43
+ if [[ "$has_sessions" == true ]]; then
44
+ echo
45
+ fi
46
+ done
@@ -0,0 +1,73 @@
1
+ #!/bin/bash
2
+
3
+ # No set -e to avoid unexpected exits; use explicit checks
4
+ set -uo pipefail
5
+
6
+ if [ $# -eq 0 ]; then
7
+ echo "Usage: $0 <search_query_or_regex>"
8
+ echo " Searches filenames & content in all .cache/[app]/[prompt]/sessions/*.ndjson"
9
+ echo " Shows matching sessions/files with context (grep -i -C5, line nums)."
10
+ echo " Quote multi-word/regex: $0 \"package.json\" or $0 \"(hdTodo|todo)\""
11
+ exit 1
12
+ fi
13
+
14
+ QUERY="$1"
15
+ echo "🔍 Searching sessions for (case-insensitive regex): '$QUERY'"
16
+ echo "=================================================================="
17
+ echo ""
18
+
19
+ total_matches=0
20
+ session_count=0
21
+
22
+ # Process substitution avoids subshell
23
+ while IFS= read -r -d '' sess_dir; do
24
+ [ -d "$sess_dir" ] || continue
25
+
26
+ session_count=$((session_count + 1))
27
+ app_name=$(basename "$(dirname "$(dirname "$sess_dir")")")
28
+ prompt_name=$(basename "$(dirname "$sess_dir")")
29
+ mod_time=$(stat -c %Y "$sess_dir" 2>/dev/null || echo 0)
30
+ date_str=$(date -d "@$mod_time" '+%Y-%m-%d %H:%M' 2>/dev/null || echo "unknown")
31
+
32
+ echo "📁 $app_name/$prompt_name ($date_str)"
33
+ echo " $sess_dir"
34
+ echo " -------------------------------------------------"
35
+
36
+ dir_matches=0
37
+ shopt -s nullglob
38
+ for ndjson_file in "$sess_dir"/*.ndjson; do
39
+ [ -f "$ndjson_file" ] || continue
40
+
41
+ fname_base=$(basename "$ndjson_file" .ndjson)
42
+ fname=$(echo "$fname_base" | sed 's/__/ /g' | sed 's/_[0-9]*$//' | fold -w70 | head -1)
43
+ fname_short="${fname:0:70}..."
44
+
45
+ # Filename match
46
+ if echo "$ndjson_file" | grep -qiE "$QUERY" || echo "$fname_base" | grep -qiE "$QUERY"; then
47
+ echo " 💾 FILENAME: $fname_short"
48
+ dir_matches=$((dir_matches + 1))
49
+ total_matches=$((total_matches + 1))
50
+ fi
51
+
52
+ # Content matches
53
+ content_matches=$(grep -iHn -C 5 -E -m 20 "$QUERY" "$ndjson_file" 2>/dev/null || true)
54
+ if [ -n "$content_matches" ]; then
55
+ echo " 📄 CONTENT in $fname_short:"
56
+ echo "$content_matches"
57
+ echo ""
58
+ dir_matches=$((dir_matches + 1))
59
+ total_matches=$((total_matches + 1))
60
+ fi
61
+ done
62
+ shopt -u nullglob
63
+
64
+ if [ $dir_matches -eq 0 ]; then
65
+ echo " (no matches)"
66
+ fi
67
+ echo ""
68
+ done < <(find .cache -mindepth 3 -maxdepth 5 -type d -name "sessions" -print0 2>/dev/null | sort -rz | head -30)
69
+
70
+ echo "✅ $total_matches matches across $session_count sessions."
71
+ if [ $total_matches -eq 0 ]; then
72
+ echo "💡 Tip: Broader query? e.g. 'todo', regex '(package|bin)' or check spelling."
73
+ fi
package/bin/hdClear.js DELETED
@@ -1,13 +0,0 @@
1
- #!/usr/bin/env -S node
2
-
3
- // clear .cache/hello-dave if it exsists
4
-
5
- import path from 'node:path';
6
- import { SH } from '@j-o-r/sh';
7
-
8
- const folder = path.resolve('.cache', 'hello-dave');
9
- const res = await SH`[ -d "${folder}" ] && echo "yes" || echo "no"`.run();
10
- if (res === 'yes') {
11
- console.log(`rm -fr ${folder}/*`);
12
- await SH`rm -fr ${folder}/*`.run()
13
- }
package/bin/hdCode.js DELETED
@@ -1,110 +0,0 @@
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 = 'hdCode';
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
- function printHelp() {
42
- console.log(`
43
- '${name} --help' You are looking at it.
44
- '
45
- OPTIONS:
46
- --tokens [number]: max generated tokens
47
- --context [number] : truncate message history to context-windows size default 130000
48
- --temperature [float] : -2 / +2
49
- --model [grok-4|grok-3|grok-3-mini|grok-3-mini-fast|grok-code-fast-1]
50
- --top_p [float]: number > 0, 0.1 means no top_p
51
- --reasoning [low|high]
52
- --tools [javascript,bash] comma seperated list
53
- e.g.
54
- grok.js --model grok-3-mini --tokens 4000 --context 10000
55
-
56
- `);
57
- process.exit()
58
- }
59
-
60
- if (help) {
61
- printHelp();
62
- }
63
-
64
- const sys = await systemInfo();
65
- const prompt = `
66
- You are a coding assistant specializing in Bash and JavaScript (ESM/ESNext), with support for other languages. Assist by executing, reading, creating, querying, explaining, or helping with code. Use tools like 'execute_bash_script' for safe Bash execution. For writing and reading files, stay in the current working folder. Provide clear, step-by-step responses, examples, and ensure safety compliance.
67
- Update your 'memory' frequently.
68
- ---env
69
- ${sys}
70
- ---
71
- `.trim();
72
- const agent = new AgentManager({ name });
73
- agent.setup({
74
- prompt,
75
- api,
76
- options,
77
- toolsetMode,
78
- contextWindow
79
- });
80
- const toolset = agent.getToolset();
81
- if (toolset) {
82
- const addTools = (args['tools']) ? args['tools'].split(',') : ['bash'];
83
- if (addTools.includes('javascript')) {
84
- agent.addGenericToolcall('javascript_interpreter');
85
- }
86
- if (addTools.includes('bash')) {
87
- agent.addGenericToolcall('execute_bash_script');
88
- }
89
- }
90
- const cliIntro = `
91
- ${name} ${options.model}.
92
- - search ${options.search_parameters.mode}
93
- - context: ${contextWindow}
94
- `.trim();
95
- const description = `
96
- Gateway to a specialized coding assistant for Bash, JavaScript (ESM/ESNext), and other languages. Handles execution, reading, creation, querying, explaining, and code help, with safety and folder restrictions.
97
- `.trim();
98
-
99
- if (input === '' && serve) {
100
- agent.enableServer('code', description, serve);
101
- }
102
- if (input !== '') {
103
- // Direct input output
104
- const res = await agent.directCall(input);
105
- console.log(res);
106
- } else if (connect) {
107
- agent.attach('code', description, connect)
108
- } else {
109
- agent.startCli(cliIntro);
110
- }
package/bin/hdConnect.js DELETED
@@ -1,230 +0,0 @@
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);