@j-o-r/hello-dave 0.0.2 → 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.
- package/README.md +288 -163
- package/README.md.backup +269 -0
- package/bin/dave.js +165 -0
- package/examples/CodeServer +43 -0
- package/{bin/hdAsk.js → examples/askDave.js} +50 -39
- package/{bin/hdCode.js → examples/codeDave.js} +47 -47
- package/examples/coderev.js +72 -0
- package/examples/daisy.js +177 -0
- package/examples/docsDave.js +119 -0
- package/examples/gpt.js +54 -72
- package/examples/grok.js +47 -68
- package/examples/npmDave.js +175 -0
- package/examples/promptDave.js +112 -0
- package/examples/readmeDave.js +144 -0
- package/examples/spawndave.js +240 -0
- package/examples/todoDave.js +132 -0
- package/lib/API/openai.com/reponses/text.js +12 -18
- package/lib/API/x.ai/collections.js +354 -0
- package/lib/API/x.ai/files.js +218 -0
- package/lib/API/x.ai/responses.js +494 -0
- package/lib/API/x.ai/text.js +1 -1
- package/lib/AgentClient.js +13 -6
- package/lib/AgentManager.js +79 -10
- package/lib/AgentServer.js +45 -21
- package/lib/Cli.js +7 -1
- package/lib/Prompt.js +4 -2
- package/lib/ToolSet.js +2 -1
- package/lib/genericToolset.js +124 -87
- package/lib/index.js +4 -2
- package/lib/wsCli.js +257 -0
- package/lib/wsIO.js +96 -0
- package/package.json +26 -20
- package/types/API/openai.com/reponses/text.d.ts +17 -3
- package/types/API/x.ai/collections.d.ts +167 -0
- package/types/API/x.ai/files.d.ts +84 -0
- package/types/API/x.ai/responses.d.ts +379 -0
- package/types/AgentClient.d.ts +5 -0
- package/types/AgentManager.d.ts +24 -31
- package/types/AgentServer.d.ts +5 -1
- package/types/Prompt.d.ts +4 -2
- package/types/ToolSet.d.ts +1 -0
- package/types/index.d.ts +4 -3
- package/types/wsCli.d.ts +3 -0
- package/types/wsIO.d.ts +26 -0
- package/utils/bars.js +40 -0
- package/utils/clear_sessions.sh +54 -0
- package/{bin/hdInspect.js → utils/format_log.js} +5 -0
- package/utils/list_sessions.sh +46 -0
- package/utils/search_sessions.sh +73 -0
- package/bin/hdClear.js +0 -13
- package/bin/hdConnect.js +0 -230
- package/bin/hdNpm.js +0 -114
- package/bin/hdPrompt.js +0 -108
- package/examples/claude-test.js +0 -89
- package/examples/claude.js +0 -143
- package/examples/gpt_code.js +0 -125
- package/examples/gpt_note_keeping.js +0 -117
- package/examples/grok_code.js +0 -114
- package/examples/grok_note_keeping.js +0 -111
- package/module.md +0 -189
package/types/wsIO.d.ts
ADDED
|
@@ -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/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);
|
package/bin/hdNpm.js
DELETED
|
@@ -1,114 +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 = '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
|
-
}
|