@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/lib/index.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import {request as gpt} from './API/openai.com/reponses/text.js';
|
|
2
|
-
import {request as
|
|
2
|
+
import {request as xai} from './API/x.ai/responses.js';
|
|
3
3
|
import {request as claude} from './API/anthropic.com/text.js';
|
|
4
4
|
import {request as brave} from './API/brave.com/search.js';
|
|
5
5
|
|
|
6
6
|
import { env, GLOBAL } from './fafs.js';
|
|
7
7
|
import ToolSet from './ToolSet.js';
|
|
8
8
|
import AgentServer from './AgentServer.js';
|
|
9
|
+
import AgentManager from './AgentManager.js';
|
|
9
10
|
import AgentClient from './AgentClient.js';
|
|
10
11
|
import Session from './Session.js';
|
|
11
12
|
import Prompt from './Prompt.js';
|
|
@@ -14,7 +15,7 @@ import Cli from './Cli.js';
|
|
|
14
15
|
const API = {
|
|
15
16
|
text:{
|
|
16
17
|
gpt,
|
|
17
|
-
|
|
18
|
+
xai,
|
|
18
19
|
claude
|
|
19
20
|
},
|
|
20
21
|
search: {
|
|
@@ -22,6 +23,7 @@ const API = {
|
|
|
22
23
|
},
|
|
23
24
|
}
|
|
24
25
|
export {
|
|
26
|
+
AgentManager,
|
|
25
27
|
AgentServer,
|
|
26
28
|
AgentClient,
|
|
27
29
|
Prompt,
|
package/lib/wsCli.js
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
#!/usr/bin/env -S node
|
|
2
|
+
/*
|
|
3
|
+
* WebSocket client for a hello-dave server with auto-reconnect and improved structure.
|
|
4
|
+
* user CLI
|
|
5
|
+
*/
|
|
6
|
+
import cli from '@j-o-r/cli';
|
|
7
|
+
import { WebSocketClient } from "@j-o-r/apiserver";
|
|
8
|
+
import { SH } from '@j-o-r/sh';
|
|
9
|
+
|
|
10
|
+
const OPEN = 1; // WebSocket.OPEN
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Copy text to the clipboard using xclip.
|
|
15
|
+
* @param {string} text
|
|
16
|
+
* @returns {Promise<void>}
|
|
17
|
+
*/
|
|
18
|
+
const copyToClipboard = async (text) => {
|
|
19
|
+
if (typeof text !== 'string') return;
|
|
20
|
+
if (text === '') text = ' ';
|
|
21
|
+
const prams = ['-selection', 'clipboard'];
|
|
22
|
+
await SH`xclip ${prams}`.options({ stdio: 'inherit' }).run(text);
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Launch a CLI to an Agent Server
|
|
26
|
+
* @param {string} connectUrl - Websocket server endpoint to connect to
|
|
27
|
+
* @param {string} [secret] - Secret websocket connection key
|
|
28
|
+
*/
|
|
29
|
+
export default (connectUrl, secret = '') => {
|
|
30
|
+
console.log('START');
|
|
31
|
+
let ws;
|
|
32
|
+
let busy = false;
|
|
33
|
+
let lastMessage = '';
|
|
34
|
+
const pendingRequests = new Map();
|
|
35
|
+
if (secret !== '') {
|
|
36
|
+
secret = Buffer.from(secret).toString('base64');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Connect to the WebSocket server (with handlers).
|
|
41
|
+
* Sets up reconnection on close.
|
|
42
|
+
*/
|
|
43
|
+
const connect = () => {
|
|
44
|
+
if (ws && ws.readyState === OPEN) {
|
|
45
|
+
console.log('Already connected');
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const url = connectUrl + '?wssrc_id=' + secret;
|
|
49
|
+
console.log(`Connecting to ${url}`);
|
|
50
|
+
ws = new WebSocketClient(url);
|
|
51
|
+
|
|
52
|
+
ws.onopen = () => {
|
|
53
|
+
console.log('Connected to server');
|
|
54
|
+
// Send introduction (no pending request for this)
|
|
55
|
+
const id = Date.now();
|
|
56
|
+
ws.send(JSON.stringify({
|
|
57
|
+
action: 'user_introduction',
|
|
58
|
+
content: '',
|
|
59
|
+
id
|
|
60
|
+
}));
|
|
61
|
+
cli.focus('user', true);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
ws.onmessage = (m) => {
|
|
65
|
+
try {
|
|
66
|
+
const data = JSON.parse(m.data);
|
|
67
|
+
const msgId = data.id;
|
|
68
|
+
if (msgId && pendingRequests.has(msgId)) {
|
|
69
|
+
const { resolve, timeout } = pendingRequests.get(msgId);
|
|
70
|
+
clearTimeout(timeout);
|
|
71
|
+
pendingRequests.delete(msgId);
|
|
72
|
+
resolve(data);
|
|
73
|
+
}
|
|
74
|
+
// Ignore unsolicited messages for now
|
|
75
|
+
} catch (e) {
|
|
76
|
+
console.error('Error parsing WebSocket message:', e, m.data);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
ws.onclose = (event) => {
|
|
81
|
+
console.log('Connection closed (reconnecting in 5s):', event.code, event.reason || 'No reason');
|
|
82
|
+
// Reject all pending requests
|
|
83
|
+
for (const [id, { reject, timeout }] of pendingRequests) {
|
|
84
|
+
clearTimeout(timeout);
|
|
85
|
+
reject(new Error(`Connection closed (${event.code})`));
|
|
86
|
+
pendingRequests.delete(id);
|
|
87
|
+
}
|
|
88
|
+
// Auto-reconnect
|
|
89
|
+
setTimeout(connect, 5000);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
ws.onerror = (event) => {
|
|
93
|
+
console.error('WebSocket error:', event.toString());
|
|
94
|
+
};
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Send a message and await response.
|
|
99
|
+
* Handles response actions and UI updates.
|
|
100
|
+
* @param {Object} message - Message object (action, content)
|
|
101
|
+
* @returns {Promise<Object>} Response data
|
|
102
|
+
*/
|
|
103
|
+
const sendMessage = async (message) => {
|
|
104
|
+
if (!ws || ws.readyState !== OPEN) {
|
|
105
|
+
throw new Error('WebSocket not connected');
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const id = Date.now();
|
|
109
|
+
message.id = id;
|
|
110
|
+
busy = true;
|
|
111
|
+
cli.startSpinner();
|
|
112
|
+
|
|
113
|
+
const promise = new Promise((resolve, reject) => {
|
|
114
|
+
const timeout = setTimeout(() => {
|
|
115
|
+
if (pendingRequests.has(id)) {
|
|
116
|
+
pendingRequests.delete(id);
|
|
117
|
+
reject(new Error('Request timeout (12 hours)'));
|
|
118
|
+
}
|
|
119
|
+
}, 1000 * 60 * 60 * 12); // 12 hours
|
|
120
|
+
pendingRequests.set(id, { resolve, reject, timeout });
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
try {
|
|
124
|
+
ws.send(JSON.stringify(message));
|
|
125
|
+
const response = await promise;
|
|
126
|
+
|
|
127
|
+
// Handle specific response actions
|
|
128
|
+
if (response.action === 'server_response') {
|
|
129
|
+
cli.focus('assistant');
|
|
130
|
+
cli.write(response.content);
|
|
131
|
+
lastMessage = response.content;
|
|
132
|
+
} else if (response.action === 'server_info') {
|
|
133
|
+
cli.focus('util');
|
|
134
|
+
cli.write(response.content);
|
|
135
|
+
} else if (response.action === 'server_reset') {
|
|
136
|
+
cli.clear();
|
|
137
|
+
} else if (response.action === 'server_sessionlist') {
|
|
138
|
+
const list = response.content;
|
|
139
|
+
const selected = await cli.select('Select your session: ', list);
|
|
140
|
+
if (selected && selected !== 'NONE') {
|
|
141
|
+
await sendMessage({ action: 'user_loadsession', content: selected });
|
|
142
|
+
}
|
|
143
|
+
} else if (response.action === 'server_sessionloaded') {
|
|
144
|
+
cli.clear();
|
|
145
|
+
const messages = response.content;
|
|
146
|
+
messages.forEach((msg) => {
|
|
147
|
+
cli.focus(msg.role);
|
|
148
|
+
cli.write(msg.content);
|
|
149
|
+
lastMessage = msg.content;
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
// Other actions ignored
|
|
153
|
+
return response;
|
|
154
|
+
} catch (e) {
|
|
155
|
+
console.error('Request error:', e.message);
|
|
156
|
+
} finally {
|
|
157
|
+
if (pendingRequests.has(id)) {
|
|
158
|
+
const { timeout } = pendingRequests.get(id);
|
|
159
|
+
clearTimeout(timeout);
|
|
160
|
+
pendingRequests.delete(id);
|
|
161
|
+
}
|
|
162
|
+
busy = false;
|
|
163
|
+
cli.stopSpinner();
|
|
164
|
+
cli.focus('user', true);
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
// Register key mappings
|
|
169
|
+
cli.registerKeyMappings([
|
|
170
|
+
// ALT-C: Clear screen
|
|
171
|
+
{
|
|
172
|
+
name: 'c', ctrl: false, meta: true, shift: false,
|
|
173
|
+
handler: async () => {
|
|
174
|
+
if (!busy) {
|
|
175
|
+
cli.clear();
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
// ALT-R: Reset session
|
|
180
|
+
{
|
|
181
|
+
name: 'r', ctrl: false, meta: true, shift: false,
|
|
182
|
+
handler: async () => {
|
|
183
|
+
if (!busy) {
|
|
184
|
+
await sendMessage({ action: 'user_reset', content: '' });
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
// ALT-S: Session list
|
|
189
|
+
{
|
|
190
|
+
name: 's', ctrl: false, meta: true, shift: false,
|
|
191
|
+
handler: async () => {
|
|
192
|
+
if (!busy) {
|
|
193
|
+
await sendMessage({ action: 'user_sessionlist', content: '' });
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
// ALT-I: Server info
|
|
198
|
+
{
|
|
199
|
+
name: 'i', ctrl: false, meta: true, shift: false,
|
|
200
|
+
handler: async () => {
|
|
201
|
+
if (!busy) {
|
|
202
|
+
await sendMessage({ action: 'user_info', content: '' });
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
// ALT-M: Copy last message
|
|
207
|
+
{
|
|
208
|
+
name: 'm', ctrl: false, meta: true, shift: false,
|
|
209
|
+
handler: async () => {
|
|
210
|
+
if (!busy && lastMessage) {
|
|
211
|
+
await copyToClipboard(lastMessage);
|
|
212
|
+
cli.focus('util');
|
|
213
|
+
cli.write('Copied last message to clipboard');
|
|
214
|
+
cli.focus('user', true);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
// CTRL-K: Help
|
|
219
|
+
{
|
|
220
|
+
name: 'k', ctrl: true, meta: false, shift: false,
|
|
221
|
+
handler: async () => {
|
|
222
|
+
cli.focus('util');
|
|
223
|
+
cli.write(`
|
|
224
|
+
Available keys:
|
|
225
|
+
• ALT-C: Clear screen
|
|
226
|
+
• ALT-R: Reset session
|
|
227
|
+
• ALT-I: Server info
|
|
228
|
+
• ALT-S: List/load sessions
|
|
229
|
+
• ALT-M: Copy last message
|
|
230
|
+
• CTRL-K: Show help
|
|
231
|
+
• CTRL-D: Exit
|
|
232
|
+
`.trim());
|
|
233
|
+
cli.focus('user', true);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
]);
|
|
237
|
+
|
|
238
|
+
// Input handler for user messages
|
|
239
|
+
cli.inputHandler = async (s) => {
|
|
240
|
+
if (busy || !s || !s.trim()) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
await sendMessage({
|
|
244
|
+
action: 'user_request',
|
|
245
|
+
content: s.trim()
|
|
246
|
+
});
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
// Initialize
|
|
250
|
+
|
|
251
|
+
cli.focus('log');
|
|
252
|
+
cli.write('Connecting... (ALT-I for info, CTRL-K for keys, CTRL-D to exit)');
|
|
253
|
+
|
|
254
|
+
connect();
|
|
255
|
+
|
|
256
|
+
}
|
|
257
|
+
|
package/lib/wsIO.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { WebSocket } from 'ws';
|
|
2
|
+
/*
|
|
3
|
+
* Oneshot direct write response to/from a Agent server
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {object} wsResponse
|
|
7
|
+
* @property {string} action
|
|
8
|
+
* @property {string} content
|
|
9
|
+
* @property {number} id - message id
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* One-shot WebSocket client for hello-dave server using standard 'ws' library.
|
|
13
|
+
* Connects directly to pure WS endpoint (no HTTP upgrade).
|
|
14
|
+
* Sends intro + action, awaits matching response by ID, closes, returns response.
|
|
15
|
+
*
|
|
16
|
+
* @param {string} connectUrl - Websocket server endpoint to connect to
|
|
17
|
+
* @param {string} [secret] - Secret websocket connection key
|
|
18
|
+
* @param {'user_request'|'user_info'|'user_reset'} action - Action
|
|
19
|
+
* @param {string} [input] - When action is 'user_request' input is the query
|
|
20
|
+
* @returns {Promise<wsResponse>}
|
|
21
|
+
*/
|
|
22
|
+
export default async function wsio(connectUrl, secret = '', action, input = '') {
|
|
23
|
+
if (!['user_request', 'user_reset', 'user_info'].includes(action)) {
|
|
24
|
+
throw new Error(`Invalid action: ${action}. Must be one of: user_input, user_reset, user_info`);
|
|
25
|
+
}
|
|
26
|
+
if (action === 'user_request' && (!input || typeof input !== 'string' || input.trim() === '')) {
|
|
27
|
+
throw new Error('Non-empty string input required for "user_input"');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let b64secret = '';
|
|
31
|
+
if (secret !== '') {
|
|
32
|
+
b64secret = Buffer.from(secret).toString('base64');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const url = `${connectUrl}${connectUrl.includes('?') ? '&' : '?'}wssrc_id=${b64secret}`;
|
|
36
|
+
|
|
37
|
+
return new Promise((resolve, reject) => {
|
|
38
|
+
const ws = new WebSocket(url);
|
|
39
|
+
|
|
40
|
+
let resolved = false;
|
|
41
|
+
const TIMEOUT_MS = 30000; // 30s timeout
|
|
42
|
+
const timeoutId = setTimeout(() => {
|
|
43
|
+
if (!resolved) {
|
|
44
|
+
ws.close();
|
|
45
|
+
reject(new Error('Request timeout (30s)'));
|
|
46
|
+
}
|
|
47
|
+
}, TIMEOUT_MS);
|
|
48
|
+
|
|
49
|
+
const actionId = Date.now();
|
|
50
|
+
|
|
51
|
+
ws.on('open', () => {
|
|
52
|
+
// Send introduction first (matches wsConnect.js protocol)
|
|
53
|
+
const introId = Date.now() - 1;
|
|
54
|
+
ws.send(JSON.stringify({
|
|
55
|
+
action: 'user_introduction',
|
|
56
|
+
content: '',
|
|
57
|
+
id: introId
|
|
58
|
+
}));
|
|
59
|
+
|
|
60
|
+
// Send the action immediately after
|
|
61
|
+
ws.send(JSON.stringify({
|
|
62
|
+
action,
|
|
63
|
+
content: input,
|
|
64
|
+
id: actionId
|
|
65
|
+
}));
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
ws.on('message', (data) => {
|
|
69
|
+
try {
|
|
70
|
+
const parsed = JSON.parse(data.toString());
|
|
71
|
+
if (parsed.id === actionId) {
|
|
72
|
+
clearTimeout(timeoutId);
|
|
73
|
+
resolved = true;
|
|
74
|
+
ws.close(1000, 'Request complete');
|
|
75
|
+
resolve(parsed);
|
|
76
|
+
}
|
|
77
|
+
} catch (e) {
|
|
78
|
+
// Ignore non-JSON or non-matching messages (e.g., intro response)
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
ws.on('close', (code, reason) => {
|
|
83
|
+
clearTimeout(timeoutId);
|
|
84
|
+
if (!resolved) {
|
|
85
|
+
reject(new Error(`Connection closed (${code}): ${reason || 'Unknown reason'}`));
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
ws.on('error', (error) => {
|
|
90
|
+
clearTimeout(timeoutId);
|
|
91
|
+
if (!resolved) {
|
|
92
|
+
reject(new Error(`WebSocket error: ${error.message}`));
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
}
|
package/package.json
CHANGED
|
@@ -1,41 +1,47 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@j-o-r/hello-dave",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
5
|
-
"description": "ESM toolkit for building AI agents with unified access to Grok, OpenAI, and Anthropic endpoints",
|
|
6
|
-
"main": "lib/
|
|
7
|
-
"types": "types/
|
|
4
|
+
"version": "0.0.3",
|
|
5
|
+
"description": "ESM toolkit for building AI agents with unified access to Grok (XAI), OpenAI, and Anthropic endpoints",
|
|
6
|
+
"main": "./lib/index.js",
|
|
7
|
+
"types": "./types/index.d.ts",
|
|
8
|
+
"typesVersions": {
|
|
9
|
+
">4": {
|
|
10
|
+
"*": [
|
|
11
|
+
"types/*"
|
|
12
|
+
]
|
|
13
|
+
}
|
|
14
|
+
},
|
|
8
15
|
"bin": {
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"hdAsk": "bin/hdAsk.js",
|
|
12
|
-
"hdCode": "bin/hdCode.js",
|
|
13
|
-
"hdConnect": "bin/hdConnect.js",
|
|
14
|
-
"hdInspect": "bin/hdInspect.js",
|
|
15
|
-
"hdClear": "bin/hdClear.js"
|
|
16
|
+
"dave": "bin/dave.js",
|
|
17
|
+
"createAgent": "examples/spawndave.js"
|
|
16
18
|
},
|
|
17
19
|
"scripts": {
|
|
18
|
-
"hdPrompt": "bin/hdPrompt.js",
|
|
19
|
-
"hdAsk": "bin/hdAsk.js",
|
|
20
|
-
"hdCode": "bin/hdCode.js",
|
|
21
|
-
"hdNpm": "bin/hdNpm.js",
|
|
22
|
-
"hdConnect": "bin/hdConnect.js",
|
|
23
|
-
"hdInspect": "bin/hdInspect.js",
|
|
24
|
-
"hdClear": "bin/hdClear.js",
|
|
25
20
|
"test": "scenarios/grok.js",
|
|
26
21
|
"release": "npm run types && npm pack --pack-destination=release",
|
|
27
22
|
"types": "rm -fr types/* && tsc -p tsc.json",
|
|
28
|
-
"publish": "npm run release && npm publish --access public"
|
|
23
|
+
"publish": "npm run release && npm publish --access public",
|
|
24
|
+
"local": "npm -g uninstall '@j-o-r/hello-dave' && npm install -g .",
|
|
25
|
+
"link-self": "mkdir -p node_modules/@j-o-r && ln -sf . node_modules/@j-o-r/hello-dave && npm ls @j-o-r/hello-dave",
|
|
26
|
+
"unlink-self": "rm -rf node_modules/@j-o-r/hello-dave"
|
|
29
27
|
},
|
|
30
28
|
"repository": {
|
|
31
29
|
"type": "git",
|
|
32
30
|
"url": "https://codeberg.org/duin/hello-dave"
|
|
33
31
|
},
|
|
34
32
|
"dependencies": {
|
|
35
|
-
"@j-o-r/apiserver": "
|
|
33
|
+
"@j-o-r/apiserver": "*",
|
|
36
34
|
"@j-o-r/cli": "*",
|
|
35
|
+
"@j-o-r/sh": "1.1.28",
|
|
37
36
|
"gpt-3-encoder": "*"
|
|
38
37
|
},
|
|
38
|
+
"exports": {
|
|
39
|
+
".": {
|
|
40
|
+
"types": "./types/index.d.ts",
|
|
41
|
+
"default": "./lib/index.js"
|
|
42
|
+
},
|
|
43
|
+
"./*": "lib/*.js"
|
|
44
|
+
},
|
|
39
45
|
"author": "Jorrit Duin <j-o-r@duin.work>",
|
|
40
46
|
"bugs": {
|
|
41
47
|
"url": "https://codeberg.org/duin/hello-dave/issues"
|
|
@@ -33,7 +33,7 @@ export type OAOptions = {
|
|
|
33
33
|
/**
|
|
34
34
|
* - Model version to use.
|
|
35
35
|
*/
|
|
36
|
-
model?: "gpt-4
|
|
36
|
+
model?: "gpt-5.4" | "gpt-5-mini" | "gpt-5-nano" | "gpt-5-pro" | undefined;
|
|
37
37
|
/**
|
|
38
38
|
* - Reusable prompt string.
|
|
39
39
|
*/
|
|
@@ -51,6 +51,9 @@ export type OAOptions = {
|
|
|
51
51
|
*/
|
|
52
52
|
summary: "auto" | "concise" | "detailed";
|
|
53
53
|
} | undefined;
|
|
54
|
+
/**
|
|
55
|
+
* - Convenience: Adds `{type: "web_search_preview", search_context_size: search}` tool.
|
|
56
|
+
*/
|
|
54
57
|
search?: "low" | "high" | "medium" | undefined;
|
|
55
58
|
/**
|
|
56
59
|
* - Service tier option, default is auto-selected.
|
|
@@ -86,9 +89,9 @@ export type OAOptions = {
|
|
|
86
89
|
*/
|
|
87
90
|
tool_choice?: "auto" | undefined;
|
|
88
91
|
/**
|
|
89
|
-
*
|
|
92
|
+
* - Array of tool objects: custom function tools (`OAToolCall`) or built-in OpenAI tools (e.g., `{type: "web_search_preview"}`).
|
|
90
93
|
*/
|
|
91
|
-
tools
|
|
94
|
+
tools?: OpenAITool[] | undefined;
|
|
92
95
|
/**
|
|
93
96
|
* =null An integer between 0 and 20 specifying the number of most likely tokens to return at each token position, each with an associated log probability.
|
|
94
97
|
*/
|
|
@@ -126,6 +129,17 @@ export type OAToolCall = {
|
|
|
126
129
|
required?: string[] | undefined;
|
|
127
130
|
};
|
|
128
131
|
};
|
|
132
|
+
export type OABuiltinTool = {
|
|
133
|
+
/**
|
|
134
|
+
* - Type of built-in OpenAI tool (Responses API).
|
|
135
|
+
*/
|
|
136
|
+
type: "code_interpreter" | "file_search" | "computer" | "web_search";
|
|
137
|
+
/**
|
|
138
|
+
* - Context size for `web_search_preview` only.
|
|
139
|
+
*/
|
|
140
|
+
search_context_size?: "low" | "high" | "medium" | undefined;
|
|
141
|
+
};
|
|
142
|
+
export type OpenAITool = OAToolCall | OABuiltinTool;
|
|
129
143
|
export type OAParameterProperty = {
|
|
130
144
|
/**
|
|
131
145
|
* - The data type of the parameter, e.g., "string".
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
declare namespace _default {
|
|
2
|
+
export { create };
|
|
3
|
+
export { list };
|
|
4
|
+
export { get };
|
|
5
|
+
export { status };
|
|
6
|
+
export { details };
|
|
7
|
+
export { update };
|
|
8
|
+
export { del };
|
|
9
|
+
export { addFileToCollection };
|
|
10
|
+
export { deleteFileFromCollection };
|
|
11
|
+
export { searchInCollections };
|
|
12
|
+
export { getStorage as storage };
|
|
13
|
+
}
|
|
14
|
+
export default _default;
|
|
15
|
+
export type Collection = {
|
|
16
|
+
/**
|
|
17
|
+
* - Unique identifier for the collection.
|
|
18
|
+
*/
|
|
19
|
+
collection_id: string;
|
|
20
|
+
/**
|
|
21
|
+
* - Name of the collection.
|
|
22
|
+
*/
|
|
23
|
+
collection_name: string;
|
|
24
|
+
/**
|
|
25
|
+
* - ISO datetime string when the collection was created.
|
|
26
|
+
*/
|
|
27
|
+
created_at: string;
|
|
28
|
+
updated_at: string;
|
|
29
|
+
/**
|
|
30
|
+
* - Configuration for the indexing model.
|
|
31
|
+
*/
|
|
32
|
+
index_configuration: {
|
|
33
|
+
model_name: string;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* - Configuration for chunking documents.
|
|
37
|
+
*/
|
|
38
|
+
chunk_configuration: {
|
|
39
|
+
tokens_configuration: {
|
|
40
|
+
max_chunk_size_tokens: number;
|
|
41
|
+
chunk_overlap_tokens: number;
|
|
42
|
+
encoding_name: string;
|
|
43
|
+
};
|
|
44
|
+
strip_whitespace: boolean;
|
|
45
|
+
inject_name_into_chunks: boolean;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* - Number of documents in the collection.
|
|
49
|
+
*/
|
|
50
|
+
documents_count: number;
|
|
51
|
+
/**
|
|
52
|
+
* - Array of field definitions.
|
|
53
|
+
*/
|
|
54
|
+
field_definitions: any[];
|
|
55
|
+
};
|
|
56
|
+
export type fileList = {
|
|
57
|
+
data: File[];
|
|
58
|
+
pagination_token: string | null;
|
|
59
|
+
};
|
|
60
|
+
export type File = {
|
|
61
|
+
/**
|
|
62
|
+
* - File size in bytes.
|
|
63
|
+
*/
|
|
64
|
+
bytes: number;
|
|
65
|
+
/**
|
|
66
|
+
* - Unix timestamp of creation.
|
|
67
|
+
*/
|
|
68
|
+
created_at: number;
|
|
69
|
+
/**
|
|
70
|
+
* - Unix timestamp of expiration, or null.
|
|
71
|
+
*/
|
|
72
|
+
expires_at: number | null;
|
|
73
|
+
/**
|
|
74
|
+
* - Path to the file.
|
|
75
|
+
*/
|
|
76
|
+
filename: string;
|
|
77
|
+
/**
|
|
78
|
+
* - Unique file identifier.
|
|
79
|
+
*/
|
|
80
|
+
id: string;
|
|
81
|
+
/**
|
|
82
|
+
* - Type of object, e.g., 'file'.
|
|
83
|
+
*/
|
|
84
|
+
object: string;
|
|
85
|
+
/**
|
|
86
|
+
* - Purpose of the file.
|
|
87
|
+
*/
|
|
88
|
+
purpose: string;
|
|
89
|
+
};
|
|
90
|
+
export type SearchResult = {
|
|
91
|
+
document_id: string;
|
|
92
|
+
content: string;
|
|
93
|
+
metadata: Object;
|
|
94
|
+
score: number;
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* Create a collection
|
|
98
|
+
* @param {string} name
|
|
99
|
+
* @returns {Promise<string>} collection_id
|
|
100
|
+
*/
|
|
101
|
+
declare function create(name: string): Promise<string>;
|
|
102
|
+
/**
|
|
103
|
+
* List collections
|
|
104
|
+
* @returns {Promise<Array<Collection>>}
|
|
105
|
+
*/
|
|
106
|
+
declare function list(): Promise<Array<Collection>>;
|
|
107
|
+
/**
|
|
108
|
+
* Get collection details
|
|
109
|
+
* @param {string} id
|
|
110
|
+
* @returns {Promise<Collection>}
|
|
111
|
+
*/
|
|
112
|
+
declare function get(id: string): Promise<Collection>;
|
|
113
|
+
/**
|
|
114
|
+
* The status of files in a collection
|
|
115
|
+
* @param {string} collectionId
|
|
116
|
+
* @returns {Promise<void>}
|
|
117
|
+
*/
|
|
118
|
+
declare function status(collectionId: string): Promise<void>;
|
|
119
|
+
/**
|
|
120
|
+
* The status of files in a collection
|
|
121
|
+
* @param {string} collectionId
|
|
122
|
+
* @param {string} fileId
|
|
123
|
+
* @returns {Promise<void>}
|
|
124
|
+
*/
|
|
125
|
+
declare function details(collectionId: string, fileId: string): Promise<void>;
|
|
126
|
+
/**
|
|
127
|
+
* Update collection collection name
|
|
128
|
+
* @param {string} id
|
|
129
|
+
* @param {string} name
|
|
130
|
+
* @returns {Promise<void>}
|
|
131
|
+
*/
|
|
132
|
+
declare function update(id: string, name: string): Promise<void>;
|
|
133
|
+
/**
|
|
134
|
+
* Delete collection
|
|
135
|
+
* @param {string} id
|
|
136
|
+
* @returns {Promise<void>}
|
|
137
|
+
*/
|
|
138
|
+
declare function del(id: string): Promise<void>;
|
|
139
|
+
/**
|
|
140
|
+
* Add file to collection
|
|
141
|
+
* @param {string} collectionId
|
|
142
|
+
* @param {string} fileId
|
|
143
|
+
* @returns {Promise<void>}
|
|
144
|
+
*/
|
|
145
|
+
declare function addFileToCollection(collectionId: string, fileId: string): Promise<void>;
|
|
146
|
+
/**
|
|
147
|
+
* Delete file from collection
|
|
148
|
+
* @param {string} collectionId
|
|
149
|
+
* @param {string} fileId
|
|
150
|
+
* @returns {Promise<void>}
|
|
151
|
+
*/
|
|
152
|
+
declare function deleteFileFromCollection(collectionId: string, fileId: string): Promise<void>;
|
|
153
|
+
/**
|
|
154
|
+
* Search in collections
|
|
155
|
+
* @param {string} query
|
|
156
|
+
* @param {string[]} collectionIds
|
|
157
|
+
* @param {Object} [options]
|
|
158
|
+
* @param {string} [options.retrieval_mode] - e.g., 'hybrid'
|
|
159
|
+
* @returns {Promise<SearchResult[]>}
|
|
160
|
+
*/
|
|
161
|
+
declare function searchInCollections(query: string, collectionIds: string[], options?: {
|
|
162
|
+
retrieval_mode?: string | undefined;
|
|
163
|
+
}): Promise<SearchResult[]>;
|
|
164
|
+
/**
|
|
165
|
+
* @returns {Promise<Map<string, Collection>>}
|
|
166
|
+
*/
|
|
167
|
+
declare function getStorage(): Promise<Map<string, Collection>>;
|