@j-o-r/hello-dave 0.0.5 → 0.0.7

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 (127) hide show
  1. package/CHANGELOG.md +13 -26
  2. package/README.md +161 -522
  3. package/README.md.bak +144 -449
  4. package/{examples → agents}/ask_agent.js +5 -5
  5. package/{examples → agents}/codeserver.sh +14 -14
  6. package/{examples → agents}/daisy_agent.js +5 -5
  7. package/{examples → agents}/docs_agent.js +5 -5
  8. package/{examples → agents}/gpt_agent.js +5 -5
  9. package/{examples → agents}/grok_agent.js +5 -5
  10. package/agents/memory_agent.js +263 -0
  11. package/{examples → agents}/npm_agent.js +5 -5
  12. package/{examples → agents}/prompt_agent.js +5 -5
  13. package/agents/spawn_agent.js +137 -0
  14. package/{examples → agents}/test_agent.js +6 -8
  15. package/{examples → agents}/todo_agent.js +5 -5
  16. package/bin/codeDave +58 -0
  17. package/bin/dave.js +114 -96
  18. package/lib/AgentClient.js +111 -67
  19. package/lib/AgentManager.js +111 -80
  20. package/lib/AgentServer.js +144 -104
  21. package/lib/Cli.js +126 -93
  22. package/lib/Prompt.js +38 -5
  23. package/lib/Session.js +102 -79
  24. package/lib/ToolSet.js +79 -60
  25. package/lib/fafs.js +54 -19
  26. package/lib/genericToolset.js +109 -213
  27. package/lib/wsCli.js +50 -19
  28. package/lib/wsIO.js +11 -17
  29. package/package.json +2 -2
  30. package/types/AgentClient.d.ts +69 -35
  31. package/types/AgentManager.d.ts +50 -56
  32. package/types/AgentServer.d.ts +63 -16
  33. package/types/Cli.d.ts +56 -10
  34. package/types/Prompt.d.ts +36 -4
  35. package/types/Session.d.ts +23 -9
  36. package/types/ToolSet.d.ts +49 -32
  37. package/types/fafs.d.ts +68 -25
  38. package/types/wsCli.d.ts +14 -0
  39. package/types/wsIO.d.ts +9 -5
  40. package/utils/search_sessions.sh +100 -53
  41. package/README.md.backup +0 -269
  42. package/README.md.bak.1774780058 +0 -338
  43. package/README.md.bak2 +0 -531
  44. package/bin/spawn_agent.js +0 -293
  45. package/docs.bak.1774780058/agent-manager.md +0 -167
  46. package/docs.bak.1774780058/agent-manager.md.bak +0 -137
  47. package/docs.bak.1774780058/agent-manager.md.bak2 +0 -157
  48. package/docs.bak.1774780058/codeserver-pattern.md +0 -191
  49. package/docs.bak.1774780058/path-resolution-best-practices.md +0 -104
  50. package/docs.bak.1774780058/project-overview.md +0 -67
  51. package/docs.bak.1774780058/project-overview.md.bak +0 -67
  52. package/docs.bak.1774780058/prompt-class.md +0 -141
  53. package/docs.bak.1774780058/prompt-class.md.bak +0 -142
  54. package/docs.bak.1774780058/tools-syntax-validation.md +0 -121
  55. package/docs.bak.1774780058/tools-syntax-validation.md.bak2 +0 -125
  56. package/docs.bak.1774780058/tools-syntax-validation.md.bak3 +0 -125
  57. package/docs.bak.1774780058/tools-syntax-validation.md.bak4 +0 -106
  58. package/docs.bak.1774780058/tools-syntax-validation.md.bak_path +0 -106
  59. package/docs.bak.1774780058/toolset.md +0 -164
  60. package/docs.bak.1774780058/toolset.md.bak +0 -94
  61. package/docs.bak.1774780058/toolset.md.bak3 +0 -161
  62. package/docs.bak.1774780058/toolset.md.bak4 +0 -161
  63. package/docs.bak.1774780058/toolset.md.bak5 +0 -161
  64. package/docs.bak.1774780058/toolset.md.bak6 +0 -163
  65. package/docs.bak.1774780058/toolset.md.bak_path +0 -163
  66. package/docs.bak.1774780058/toolset.md.bak_syntax +0 -161
  67. package/docs.bak.1774780058/xai-responses.md +0 -111
  68. package/docs.bak.1774780058/xai-responses.md.bak +0 -107
  69. package/docs.bak.1774780058/xai-responses.md.bak2 +0 -107
  70. package/docs.bak.1774780058/xai_collections.md +0 -106
  71. package/examples/memory_agent.js +0 -152
  72. package/examples.bak.1774780058/ask_agent.js +0 -114
  73. package/examples.bak.1774780058/code_agent.js +0 -149
  74. package/examples.bak.1774780058/coderev_agent.js +0 -72
  75. package/examples.bak.1774780058/codeserver.sh +0 -47
  76. package/examples.bak.1774780058/daisy_agent.js +0 -177
  77. package/examples.bak.1774780058/docs_agent.js +0 -119
  78. package/examples.bak.1774780058/gpt_agent.js +0 -109
  79. package/examples.bak.1774780058/grok_agent.js +0 -98
  80. package/examples.bak.1774780058/memory_agent.js +0 -112
  81. package/examples.bak.1774780058/npm_agent.js +0 -175
  82. package/examples.bak.1774780058/prompt_agent.js +0 -112
  83. package/examples.bak.1774780058/readme_agent.js +0 -144
  84. package/examples.bak.1774780058/spawn_agent.js +0 -263
  85. package/examples.bak.1774780058/test_agent.js +0 -162
  86. package/examples.bak.1774780058/todo_agent.js +0 -138
  87. package/lib/genericToolset.js.bak_syntax +0 -402
  88. package/scenarios.bak.1774780058/data/eval_node_message.json +0 -9
  89. package/scenarios.bak.1774780058/data/hist_oa.json +0 -66
  90. package/scenarios.bak.1774780058/data/o3_response1.json +0 -96
  91. package/scenarios.bak.1774780058/data/oa_reasoning_parse.json +0 -112
  92. package/scenarios.bak.1774780058/data/tool_oa.json +0 -96
  93. package/scenarios.bak.1774780058/data/tool_xai.json +0 -59
  94. package/scenarios.bak.1774780058/data/tool_xai2.json +0 -40
  95. package/scenarios.bak.1774780058/data/xai-response-1.json +0 -59
  96. package/scenarios.bak.1774780058/data/xai-response-2.json +0 -10
  97. package/scenarios.bak.1774780058/data/xai_reasoning_tools_resp.json +0 -59
  98. package/scenarios.bak.1774780058/data/xai_search_response.json +0 -58
  99. package/scenarios.bak.1774780058/environment.js +0 -10
  100. package/scenarios.bak.1774780058/example.js +0 -17
  101. package/scenarios.bak.1774780058/genericToolset.test.js +0 -182
  102. package/scenarios.bak.1774780058/grok.js +0 -113
  103. package/scenarios.bak.1774780058/memory-tools.js +0 -51
  104. package/scenarios.bak.1774780058/openai-o3.js +0 -137
  105. package/scenarios.bak.1774780058/openai-prompt.js +0 -155
  106. package/scenarios.bak.1774780058/openai-session.js +0 -148
  107. package/scenarios.bak.1774780058/openai.js +0 -102
  108. package/scenarios.bak.1774780058/prompt.js +0 -118
  109. package/scenarios.bak.1774780058/promptFishbowl.js +0 -76
  110. package/scenarios.bak.1774780058/search.brave.com.js +0 -25
  111. package/scenarios.bak.1774780058/sh.js +0 -15
  112. package/scenarios.bak.1774780058/test-wsio.js +0 -26
  113. package/scenarios.bak.1774780058/testToolset.js +0 -42
  114. package/scenarios.bak.1774780058/toolset.js +0 -16
  115. package/scenarios.bak.1774780058/toolset.test.js +0 -141
  116. package/scenarios.bak.1774780058/write_file_syntax.test.js +0 -145
  117. package/scenarios.bak.1774780058/write_file_validation/README.md +0 -30
  118. package/scenarios.bak.1774780058/write_file_validation/bad.js +0 -3
  119. package/scenarios.bak.1774780058/write_file_validation/good.js +0 -4
  120. package/scenarios.bak.1774780058/write_file_validation/test.sh +0 -43
  121. package/scenarios.bak.1774780058/wsClient.js +0 -69
  122. package/scenarios.bak.1774780058/xai_responses.integration.test.js +0 -57
  123. package/scenarios.bak.1774780058/xai_responses.test.js +0 -154
  124. package/scenarios.bak.1774780058/xaicoll.js +0 -50
  125. package/scenarios.bak.1774780058/xaifiles.js +0 -48
  126. /package/{examples → agents}/code_agent.js +0 -0
  127. /package/{examples → agents}/readme_agent.js +0 -0
@@ -1,145 +0,0 @@
1
- #!/usr/bin/env node
2
- import { Test, assert, jsType } from '@j-o-r/sh';
3
- import { execSync } from 'child_process';
4
- import { mkdtempSync, writeFileSync, rmSync, mkdirSync } from 'fs';
5
- import { tmpdir } from 'os';
6
- import { join, dirname } from 'path';
7
-
8
- const t = new Test();
9
- const TMP = mkdtempSync(join(tmpdir(), 'syntax_test_'));
10
- process.on('exit', () => rmSync(TMP, { recursive: true, force: true }));
11
-
12
- const checkSyntax = (file) => {
13
- try {
14
- execSync(`./utils/syntax_check.sh "${file}"`, { cwd: process.cwd(), stdio: 'pipe', timeout: 5000 });
15
- return true;
16
- } catch (e) {
17
- return false;
18
- }
19
- };
20
-
21
- const writeTemp = (relpath, content) => {
22
- const file = join(TMP, relpath);
23
- mkdirSync(dirname(file), { recursive: true });
24
- writeFileSync(file, content);
25
- return file;
26
- };
27
-
28
- t.add('checkSyntax returns boolean', () => {
29
- const file = writeTemp('test.js', 'console.log("ok");');
30
- assert.strictEqual(jsType(checkSyntax(file)), 'Boolean');
31
- });
32
-
33
- t.add('syntax_check: JS valid', () => {
34
- const file = writeTemp('valid.js', '// Valid JS\nconsole.log("ok");');
35
- assert.strictEqual(checkSyntax(file), true);
36
- });
37
-
38
- t.add('syntax_check: JS invalid (unexpected token)', () => {
39
- const file = writeTemp('invalid.js', 'const x = ; console.log(x);');
40
- assert.strictEqual(checkSyntax(file), false);
41
- });
42
-
43
- t.add('syntax_check: JS invalid unterminated quote', () => {
44
- const file = writeTemp('invalid-quote.js', 'console.log("hi );');
45
- assert.strictEqual(checkSyntax(file), false);
46
- });
47
-
48
- t.add('syntax_check: JS invalid unbalanced paren', () => {
49
- const file = writeTemp('invalid-paren.js', 'if (true {\n console.log("ok");\n}');
50
- assert.strictEqual(checkSyntax(file), false);
51
- });
52
-
53
- t.add('syntax_check: JS valid ESM import', () => {
54
- const file = writeTemp('valid-esm.js', 'import { Test } from "@j-o-r/sh";\nconsole.log("ok");');
55
- assert.strictEqual(checkSyntax(file), true);
56
- });
57
-
58
- t.add('syntax_check: JS shebang valid', () => {
59
- const file = writeTemp('valid-shebang.js', '#!/usr/bin/env node\nimport { Test } from "@j-o-r/sh";');
60
- assert.strictEqual(checkSyntax(file), true);
61
- });
62
-
63
- t.add('syntax_check: JS subdir valid', () => {
64
- const file = writeTemp('subdir/valid.js', 'console.log("ok");');
65
- assert.strictEqual(checkSyntax(file), true);
66
- });
67
-
68
- // PY invalid: missing indent
69
- t.add('syntax_check: PY invalid (indent err)', () => {
70
- const file = writeTemp('invalid.py', 'def f():\nprint("hi")');
71
- assert.strictEqual(checkSyntax(file), false);
72
- });
73
-
74
- // PY valid
75
- t.add('syntax_check: PY valid', () => {
76
- const file = writeTemp('valid.py', '#!/usr/bin/env python3\ndef f():\n print("hi")\nf()');
77
- assert.strictEqual(checkSyntax(file), true);
78
- });
79
-
80
- // SH invalid: missing fi
81
- t.add('syntax_check: SH invalid (missing fi)', () => {
82
- const file = writeTemp('invalid.sh', '#!/bin/bash\nif true; then\necho "hi"');
83
- assert.strictEqual(checkSyntax(file), false);
84
- });
85
-
86
- // SH valid
87
- t.add('syntax_check: SH valid', () => {
88
- const file = writeTemp('valid.sh', '#!/bin/bash\necho "ok"');
89
- assert.strictEqual(checkSyntax(file), true);
90
- });
91
-
92
- // SH shebang + if/fi
93
- t.add('syntax_check: SH valid (if/fi)', () => {
94
- const file = writeTemp('valid-if.sh', '#!/usr/bin/env bash\nif true; then\n echo "ok"\nfi');
95
- assert.strictEqual(checkSyntax(file), true);
96
- });
97
-
98
- // JSON invalid: trailing comma
99
- t.add('syntax_check: JSON invalid', () => {
100
- const file = writeTemp('invalid.json', '{ "key": "value", }');
101
- assert.strictEqual(checkSyntax(file), false);
102
- });
103
-
104
- // JSON valid
105
- t.add('syntax_check: JSON valid', () => {
106
- const file = writeTemp('valid.json', '{ "key": "value" }');
107
- assert.strictEqual(checkSyntax(file), true);
108
- });
109
-
110
- // Unknown ext: non-fatal pass
111
- t.add('syntax_check: unknown ext (txt)', () => {
112
- const file = writeTemp('test.txt', 'plain text');
113
- assert.strictEqual(checkSyntax(file), true);
114
- });
115
-
116
- // write_file sim: invalid → reject (PY/SH/JSON/JS)
117
- t.add('syntax_check: write_file sim JS reject', () => {
118
- const file = writeTemp('sim_invalid.js', 'console.log("hi );');
119
- assert.strictEqual(checkSyntax(file), false);
120
- });
121
-
122
- t.add('syntax_check: write_file sim PY reject', () => {
123
- const file = writeTemp('sim_invalid.py', 'def f():\nprint("hi")');
124
- assert.strictEqual(checkSyntax(file), false);
125
- });
126
-
127
- t.add('syntax_check: write_file sim SH reject', () => {
128
- const file = writeTemp('sim_invalid.sh', '#!/bin/bash\nif true; then echo hi');
129
- assert.strictEqual(checkSyntax(file), false);
130
- });
131
-
132
- t.add('syntax_check: write_file sim JSON reject', () => {
133
- const file = writeTemp('sim_invalid.json', '{invalid}');
134
- assert.strictEqual(checkSyntax(file), false);
135
- });
136
-
137
- t.add('syntax_check: async valid JS', async () => {
138
- const file = writeTemp('async-valid.js', 'console.log("ok");');
139
- await new Promise(r => setTimeout(r, 10));
140
- assert.strictEqual(checkSyntax(file), true);
141
- });
142
-
143
- const report = await t.run();
144
- assert.strictEqual(jsType(report), 'Object');
145
- process.exit(report.errors > 0 ? 1 : 0);
@@ -1,30 +0,0 @@
1
- # write_file Auto-Validation Test Suite
2
-
3
- ## Purpose
4
- Tests the enhanced \`write_file\` tool in \`lib/genericToolset.js\`:
5
- - **JS Syntax Check**: \`node --check\` on .js/shebang files → blocks invalid.
6
- - **Error Guidance**: Forces LLM retry with \\\` fix hints.
7
- - **chmod +x**: Auto for shebangs.
8
- - **Self-Healing**: LLM sees error → regenerates valid JS.
9
-
10
- ## Files
11
- - \`bad.js\`: Intentional syntax error (unclosed template literal \`console.log(\`).
12
- - \`good.js\`: Fixed (properly escaped \`console.log(\\\\\\`hello\\\\\\\`); \`).
13
- - \`test.sh\`: Runs write_file simulation → expect error on bad → success on good.
14
-
15
- ## Run
16
- ```bash
17
- cd scenarios/write_file_validation
18
- chmod +x test.sh
19
- ./test.sh
20
- ```
21
- Expected:
22
- ```
23
- ❌ Write bad.js → SYNTAX ERROR (node --check fails)
24
- ✅ Write good.js → ✓ JS syntax OK + chmod +x (if shebang)
25
- ```
26
-
27
- ## LLM Test (via CodeServer)
28
- Query: \"Use write_file to create bad.js with console.log(\`hi\`); then fix it.\" → Auto-triggers retry loop.
29
-
30
- Current date: March 27, 2026.
@@ -1,3 +0,0 @@
1
- #!/usr/bin/env node
2
- console.log(`Unclosed backtick syntax error!
3
- import { foo } from 'bar';
@@ -1,4 +0,0 @@
1
- #!/usr/bin/env node
2
- console.log(`Hello, fixed template literal!`);
3
- console.log('Proper JS syntax.');
4
- import { parseArgs } from '@j-o-r/sh'; // ESM OK
@@ -1,43 +0,0 @@
1
- #!/bin/bash
2
- set -e
3
-
4
- echo "=== write_file Auto-Validation Test ==="
5
- cd "$(dirname "$0")"
6
-
7
- # Simulate toolset write_file (manual for demo; real uses lib/genericToolset.js)
8
- echo "1. Write BAD JS (expect SYNTAX ERROR)..."
9
- cat > temp_bad.js << 'EOF'
10
- #!/usr/bin/env node
11
- console.log(`Unclosed backtick! // ERROR: Missing closing \`
12
- EOF
13
-
14
- # Manual node --check (mimics tool)
15
- if node --check temp_bad.js 2>&1; then
16
- echo "❌ FAIL: Bad JS passed check!"
17
- else
18
- echo "✅ PASS: Bad JS correctly rejected ($(node --check temp_bad.js 2>&1 | head -1))"
19
- fi
20
-
21
- echo "2. Write GOOD JS (expect ✓ OK + chmod)..."
22
- cat > temp_good.js << 'EOF'
23
- #!/usr/bin/env node
24
- console.log(`Fixed template!`);
25
- console.log('All good.');
26
- EOF
27
-
28
- if node --check temp_good.js 2>&1; then
29
- echo "✅ PASS: Good JS syntax OK"
30
- chmod +x temp_good.js
31
- echo "✅ PASS: chmod +x applied"
32
- ./temp_good.js # Runs!
33
- else
34
- echo "❌ FAIL: Good JS failed check!"
35
- fi
36
-
37
- # Real toolset test (requires running agent)
38
- echo "3. REAL TOOL TEST (run via CodeServer):"
39
- echo " echo 'write_file scenarios/write_file_validation/new.js: console.log(\`test\`);' | dave --connect ws://...:8081/ws"
40
- echo " → If bad: Error → LLM fixes → ✓ OK"
41
-
42
- rm -f temp_*.js
43
- echo "=== ALL TESTS PASS ✅ ==="
@@ -1,69 +0,0 @@
1
- #!/usr/bin/env node
2
- import cli from '@j-o-r/cli';
3
- import { WebSocketClient } from "@j-o-r/apiserver";
4
- const NAME = 'clarification';
5
- const wsUser = new WebSocketClient('ws://localhost:2000/ws?test=param'); // Match server port/path
6
-
7
- const queryMessages = new Map();
8
-
9
- /*
10
- HANDSHAKE:
11
-
12
- 1: requests an introduction with 'introduce'
13
- 2: get a response 'introduction'
14
-
15
- This must be DONE before anything else can take place
16
-
17
- */
18
-
19
- cli.registerKeyMappings([
20
- { name: 'd', ctrl: true, meta: false, shift: false, handler: async () => {
21
- process.exit(0);
22
- }},
23
- { name: 'r', ctrl: true, meta: false, shift: false, handler: async () => {
24
- cli.clear();
25
- }}
26
-
27
- ]);
28
- // @ts-ignore
29
- cli.inputHandler = async (s, role) => {
30
- const message = {
31
- action: 'query',
32
- content: s,
33
- }
34
- wsUser.send(JSON.stringify(message));
35
- cli.startSpinner();
36
- }
37
- cli.focus('log');
38
- cli.write('CTRL - d exit');
39
- cli.write('CTRL - r clear screen / reset');
40
- // cli.focus('user', true);
41
-
42
- wsUser.onopen = () => {
43
- cli.focus('log');
44
- cli.write('Jorrit connected');
45
- // Send my introduction to the server
46
- wsUser.send(JSON.stringify({
47
- action: 'introduction',
48
- name: NAME,
49
- content: 'I am a human named Jorrit. Query me for questions that needs clearfication',
50
- id: new Date().getTime()
51
- }));
52
- cli.focus('user', true);
53
-
54
- };
55
- /**
56
- * @type {MessageEvent} event
57
- */
58
- wsUser.onmessage = (event) => {
59
- const data = JSON.parse(event.data); // Forwarded HTTP request
60
- console.log('Received request:', data);
61
- cli.focus('user', true);
62
- };
63
- wsUser.onclose = () => {
64
- console.log('WS closed');
65
- process.exit();
66
- }
67
- wsUser.onerror = (err) => {
68
- console.error('WS error:', err);
69
- }
@@ -1,57 +0,0 @@
1
- #!/usr/bin/env node
2
- import { Test, assert } from '@j-o-r/sh';
3
- import { request } from '../lib/API/x.ai/responses.js';
4
- import Prompt from '../lib/Prompt.js';
5
- import tools from './testToolset.js'; // Reuse weather mock for recursion
6
-
7
- const t = new Test();
8
-
9
- // Real API: tools + recursion (default model)
10
- t.add('request: real with tools (recursion)', async () => {
11
- const p = new Prompt();
12
- p.add('system', 'You are helpful. Use tools for weather.', true);
13
- p.add('user', 'Weather in Amsterdam?');
14
- const msg = await request(p, tools);
15
- assert.strictEqual(msg.role, 'assistant');
16
- assert.ok(msg.content.some(c => c.type === 'text'), 'Final text response');
17
- const toolMsg = p.messages.find(m => m.role === 'tool');
18
- assert.ok(toolMsg, 'Tool executed');
19
- });
20
-
21
- // Real API: custom options (non-reasoning model)
22
- t.add('request: real options (model/temp/store)', async () => {
23
- const p = new Prompt();
24
- p.add('system', 'Answer in JSON.', true);
25
- p.add('user', '2+2 as JSON.');
26
- const msg = await request(p, null, {
27
- model: 'grok-4-fast-non-reasoning',
28
- temperature: 0.1,
29
- store: true,
30
- max_output_tokens: 100
31
- });
32
- assert.strictEqual(msg.role, 'assistant');
33
- assert.ok(msg.content[0].text.includes('4'), 'JSON with 4');
34
- });
35
-
36
- // Real API: reasoning rejected (unsupported on default model)
37
- t.add('request: reasoning rejected on incompatible model', async () => {
38
- const p = new Prompt();
39
- p.add('user', 'Why is sky blue?');
40
- await assert.rejects(
41
- () => request(p, null, { reasoning: { effort: 'high', summary: 'concise' } }),
42
- /invalid argument|reasoningEffort/
43
- );
44
- });
45
-
46
- // Real API: invalid model rejects (4xx)
47
- t.add('request: invalid model rejects', async () => {
48
- const p = new Prompt();
49
- p.add('user', 'Hi');
50
- await assert.rejects(
51
- () => request(p, null, { model: 'invalid-xyz' }),
52
- /Error.*4\\d{2}|Model not found|400/
53
- );
54
- });
55
-
56
- const report = await t.run();
57
- process.exit(report.errors > 0 ? 1 : 0);
@@ -1,154 +0,0 @@
1
- #!/usr/bin/env node
2
- import { Test, assert } from '@j-o-r/sh';
3
- import { generateRequest, parseResponse, request } from '../lib/API/x.ai/responses.js';
4
- import Prompt from '../lib/Prompt.js';
5
- import ToolSet from '../lib/ToolSet.js';
6
- import tools from './testToolset.js';
7
-
8
- const t = new Test();
9
-
10
- // Fake response helpers
11
- const fakeTextRes = () => ({
12
- status: 200,
13
- response: {
14
- id: 'fake-text',
15
- model: 'grok-beta',
16
- created_at: Math.floor(Date.now() / 1000),
17
- usage: { input_tokens: 10, output_tokens: 5 },
18
- output: [{ type: 'message', content: [{ type: 'output_text', text: 'Hello!' }] }]
19
- }
20
- });
21
-
22
- const fakeReasoningRes = () => ({
23
- status: 200,
24
- response: {
25
- id: 'fake-reason',
26
- model: 'grok-beta',
27
- created_at: Math.floor(Date.now() / 1000),
28
- usage: { input_tokens: 10, output_tokens: 5 },
29
- output: [{ type: 'reasoning', summary: [{ type: 'summary_text', text: 'Thought.' }] }]
30
- }
31
- });
32
-
33
- const fakeCitationRes = () => ({
34
- status: 200,
35
- response: {
36
- id: 'fake-cit',
37
- model: 'grok-beta',
38
- created_at: Math.floor(Date.now() / 1000),
39
- usage: { input_tokens: 10, output_tokens: 5 },
40
- output: [{ type: 'message', content: [{ type: 'output_text', text: 'Text', annotations: [{ type: 'url_citation', url: 'https://ex.com' }] }] }]
41
- }
42
- });
43
-
44
- const fakeToolRes = (name = 'get_current_weather', args = '{"location":"Amsterdam"}') => ({
45
- status: 200,
46
- response: {
47
- id: 'fake-tool',
48
- model: 'grok-beta',
49
- created_at: Math.floor(Date.now() / 1000),
50
- usage: { input_tokens: 20, output_tokens: 10 },
51
- output: [{ type: 'function_call', name, id: 'fid', call_id: 'fcid', arguments: args, status: 'complete' }]
52
- }
53
- });
54
-
55
- t.add('generateRequest: basic', () => {
56
- const p = new Prompt();
57
- p.add('system', 'Helpful', true);
58
- p.add('user', 'Hi');
59
- const { url, headers, body } = generateRequest(p);
60
- assert.strictEqual(url, 'https://api.x.ai/v1/responses');
61
- assert.strictEqual(headers['Content-Type'], 'application/json');
62
- assert.ok(headers.Authorization.startsWith('Bearer'));
63
- assert.strictEqual(body.model, 'grok-4-fast-reasoning');
64
- assert.strictEqual(body.instructions, 'Helpful');
65
- assert.strictEqual(body.input.length, 1);
66
- });
67
-
68
- t.add('generateRequest: tools', () => {
69
- const p = new Prompt();
70
- p.add('user', 'Weather');
71
- const { body } = generateRequest(p, tools);
72
- assert.ok(body.tools.some(tl => tl.name === 'get_current_weather'));
73
- assert.strictEqual(body.parallel_tool_calls, true);
74
- });
75
-
76
- t.add('generateRequest: options', () => {
77
- const p = new Prompt();
78
- p.add('user', 'Hi');
79
- const { body } = generateRequest(p, null, { model: 'grok-4-1-fast-reasoning' });
80
- assert.strictEqual(body.model, 'grok-4-1-fast-reasoning');
81
- });
82
-
83
- t.add('generateRequest: throws bad last role', () => {
84
- const p = new Prompt();
85
- p.add('system', '', true);
86
- p.add('assistant', 'bad');
87
- assert.throws(() => generateRequest(p));
88
- });
89
-
90
- t.add('parseResponse: text', async () => {
91
- const p = new Prompt();
92
- p.add('user', 'Hi');
93
- await parseResponse(100, p, fakeTextRes());
94
- const msg = p.getLastMessage();
95
- assert.strictEqual(msg.role, 'assistant');
96
- assert.strictEqual(msg.content[0].text, 'Hello!');
97
- });
98
-
99
- t.add('parseResponse: reasoning', async () => {
100
- const p = new Prompt();
101
- await parseResponse(100, p, fakeReasoningRes());
102
- const msg = p.getLastMessage();
103
- assert.strictEqual(msg.role, 'reasoning');
104
- assert.strictEqual(msg.content[0].text, 'Thought.');
105
- });
106
-
107
- t.add('parseResponse: citations', async () => {
108
- const p = new Prompt();
109
- await parseResponse(100, p, fakeCitationRes());
110
- const log = p.messages.find(m => m.role === 'log');
111
- assert.ok(log);
112
- assert.ok(log.content[0].text.includes('https://ex.com'));
113
- });
114
-
115
- t.add('parseResponse: function_call', async () => {
116
- const p = new Prompt();
117
- p.add('user', 'Weather');
118
- await parseResponse(100, p, fakeToolRes());
119
- const msg = p.getLastMessage();
120
- assert.strictEqual(msg.role, 'assistant');
121
- assert.strictEqual(msg.content[0].type, 'function_request');
122
- assert.strictEqual(msg.content[0].function_request.name, 'get_current_weather');
123
- assert.strictEqual(msg.content[0].function_request.parameters, '{"location":"Amsterdam"}');
124
- assert.strictEqual(msg.content[0].function_request.call_id, 'fcid');
125
- });
126
-
127
- t.add('parseResponse: toolset exec', async () => {
128
- const p = new Prompt();
129
- p.add('user', 'Weather Amsterdam');
130
- await parseResponse(100, p, fakeToolRes('get_current_weather', '{"location":"Amsterdam"}'), tools);
131
- const toolMsg = p.getLastMessage();
132
- assert.strictEqual(toolMsg.role, 'tool');
133
- assert.strictEqual(toolMsg.content[0].type, 'function_response');
134
- assert.strictEqual(toolMsg.content[0].function_response.name, 'get_current_weather');
135
- assert.ok(toolMsg.content[0].function_response.response.includes('24 C'));
136
- });
137
-
138
- t.add('parseResponse: non-200 rejects', async () => {
139
- const p = new Prompt();
140
- const bad = { status: 400, response: { error: 'bad' } };
141
- await assert.rejects(async () => parseResponse(100, p, bad), /400: /);
142
- });
143
-
144
- t.add('request: real simple', async () => {
145
- const p = new Prompt();
146
- p.add('system', 'You are a helpful assistant. Answer briefly.', true);
147
- p.add('user', 'What is 2+2?');
148
- const msg = await request(p);
149
- assert.strictEqual(msg.role, 'assistant');
150
- assert.ok(msg.content.some(c => c.type === 'text' && c.text.includes('4')), 'Expected 4');
151
- });
152
-
153
- const report = await t.run();
154
- process.exit(report.errors > 0 ? 1 : 0);
@@ -1,50 +0,0 @@
1
- #!/usr/bin/env node
2
- import { Test, assert, SH } from '@j-o-r/sh'
3
- import collections from '../lib/API/x.ai/collections.js';
4
- import path from 'node:path'
5
-
6
-
7
- import Prompt from '../lib/Prompt.js';
8
- import tools from './testToolset.js';
9
-
10
- function LOG(me) {
11
- console.log(JSON.stringify(me, null, ' '));
12
- }
13
-
14
- const test = new Test();
15
-
16
- test.add('List collections, start in a clean state', async () => {
17
- const list = await collections.list();
18
- let i = 0;
19
- const len = list.length;
20
- for (; i < len; i++) {
21
- const col = list[i];
22
- if (col.collection_name === 'test_col' || col.collection_name === 'test_col2') {
23
- const check = await collections.get(col.collection_id);
24
- assert.equal(check.collection_id, col.collection_id);
25
- // Delete all test collections
26
- await collections.del(check.collection_id);
27
- }
28
- }
29
- });
30
-
31
- test.add('Add, update, delete a collection', async () => {
32
- const coll_id = await collections.create('test_col');
33
- let coll = await collections.get(coll_id);
34
- assert.strictEqual(coll_id, coll.collection_id);
35
- await collections.update(coll_id, 'test_col2');
36
- coll = await collections.get(coll_id);
37
- assert.strictEqual(coll.collection_name, 'test_col2');
38
- await collections.del(coll_id);
39
- // DELETED
40
- await assert.rejects(
41
- async () => await collections.get(coll_id),
42
- (err) => {
43
- return err.toString().includes('doesn\'t exist or your team');
44
- }
45
- )
46
- })
47
-
48
-
49
-
50
- await test.run();
@@ -1,48 +0,0 @@
1
- #!/usr/bin/env node
2
- import { Test, assert, SH } from '@j-o-r/sh'
3
- import { files } from '../lib/API/x.ai/files.js';
4
- import path from 'node:path'
5
-
6
- import Prompt from '../lib/Prompt.js';
7
- import tools from './testToolset.js';
8
-
9
- function LOG(me) {
10
- console.log(JSON.stringify(me, null, ' '));
11
- }
12
-
13
- const test = new Test();
14
-
15
- test.add('List files', async () => {
16
- const fp = path.resolve('docs', 'toolset.md');
17
- const list = (await files.list()).data;
18
- let i = 0;
19
- const len = list.length;
20
- for(;i < len; i++) {
21
- const f = list[i];
22
- if (f.filename === 'test.md' || f.filename === fp) {
23
- await files.rm(f.id);
24
- }
25
- }
26
- });
27
-
28
- test.add('create, add and remove files', async () => {
29
- const fp = path.resolve('docs', 'toolset.md');
30
- const res = await files.upload(fp);
31
- const content = await files.get(res.id);
32
- assert.equal(content.length, res.bytes);
33
- const meta = await files.getMeta(res.id);
34
- assert.equal(content.length, meta.bytes);
35
- await files.rm(res.id);
36
- })
37
-
38
- test.add('create, add and remove files with custom content', async () => {
39
- const fp = 'test.md';
40
- // Add custom content to a file instead of reading the file itself
41
- const res = await files.upload(fp, 'Hello World');
42
- const content = await files.get(res.id);
43
- assert.equal(content, 'Hello World');
44
- const meta = await files.getMeta(res.id);
45
- assert.equal(content.length, meta.bytes);
46
- await files.rm(res.id);
47
- })
48
- await test.run();
File without changes
File without changes