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

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.
@@ -0,0 +1,121 @@
1
+ # Syntax Validation in Generic Tools
2
+
3
+ ## Overview
4
+ **Integration Complete**: `lib/genericToolset.js` now includes **automatic JS syntax validation** in `write_file` **and a new `syntax_check` tool** using `./utils/syntax_check.sh` for multi-language support (JS/Python/Bash/JSON). Prevents invalid code, resolves escaping issues, auto `chmod +x` shebangs. Post-write errors prompt LLM retries.
5
+ **Path Note**: Uses `__dirname` for utils/; resolves files to `process.cwd()`. See [path-resolution-best-practices.md](path-resolution-best-practices.md).
6
+
7
+ **Key Benefits**:
8
+ - **JS Safety**: `node --check` (in `write_file`); full multi-lang in `syntax_check`.
9
+ **Path Note**: Uses `__dirname` for utils/; resolves files to `process.cwd()`. See [path-resolution-best-practices.md](path-resolution-best-practices.md).
10
+ - **Executable Prep**: Auto `chmod +x`.
11
+ - **Retry-Friendly**: Descriptive errors + previews.
12
+ - **Generic Access**: `toolsetMode: 'auto'` loads both.
13
+
14
+ **Commit History** (relevant):
15
+ - `3c8e1ae`: Initial `read_file`/`write_file`.
16
+ - Recent: JS validation + `syntax_check` tool.
17
+ **Path Note**: Uses `__dirname` for utils/; resolves files to `process.cwd()`. See [path-resolution-best-practices.md](path-resolution-best-practices.md).
18
+
19
+ ## write_file Tool Updates
20
+
21
+ ### Description (Updated)
22
+ ```
23
+ Write raw content to a file strictly within the current working directory (CWD). Paths must be relative (no leading /, no ..). Content written as-is (no escaping). **AUTO-VALIDATES JS FILES** with `node --check`; chmod +x shebangs. Retries syntax errors force LLM fix.
24
+ ```
25
+
26
+ ### Examples
27
+ **Success** (CLI/Agent):
28
+ ```bash
29
+ echo 'const x = \`hi\`; console.log(x);' | agent.directCall("Use write_file on test.js with this content")
30
+ # Returns: "Successfully wrote to 'test.js' (42 bytes). ✓ JS syntax OK"
31
+ ```
32
+
33
+ **Failure + Retry**:
34
+ ```javascript
35
+ // LLM generates invalid:
36
+ const msg = `Hello ${name`; // Missing `
37
+ ```
38
+ **Error**:
39
+ ```
40
+ ❌ JS SYNTAX ERROR in 'test.js' (node --check failed):
41
+ SyntaxError: Unexpected token '}'
42
+
43
+ PREVIEW:
44
+ const msg = `Hello ${name
45
+ ...
46
+
47
+ ... Fix escaping/backticks in template literals (use \\\\` for \` in JS strings) and retry.
48
+ ```
49
+ **LLM Sees → Fixes**: Uses `"Hello \${name}"` or proper `` \` ``.
50
+
51
+ **Shebang**:
52
+ ```javascript
53
+ content: '#!/usr/bin/env node\nconst hello = () => console.log("Hi");'
54
+ # Returns: "... ✓ JS syntax OK ✓ chmod +x"
55
+ ```
56
+
57
+ ## New: syntax_check Tool
58
+ **Path Note**: Uses `__dirname` for utils/; resolves files to `process.cwd()`. See [path-resolution-best-practices.md](path-resolution-best-practices.md).
59
+
60
+ **Description**:
61
+ ```
62
+ Validate syntax of a file (JS, Python, Bash/Sh, JSON). Detects language from extension/shebang. Uses native checkers... Exit 1 on fail.
63
+ ```
64
+
65
+ ### Parameters
66
+ ```json
67
+ {
68
+ "type": "object",
69
+ "properties": { "file": { "type": "string" } },
70
+ "required": ["file"]
71
+ }
72
+ ```
73
+
74
+ ### Examples
75
+ **Agent Call**:
76
+ ```
77
+ agent.directCall("Use syntax_check on test.js") → "🔍 Validating test.js (lang: js)\n✅ JS OK\n✅ Syntax validation passed for test.js"
78
+ **Path Note**: Uses `__dirname` for utils/; resolves files to `process.cwd()`. See [path-resolution-best-practices.md](path-resolution-best-practices.md).
79
+ ```
80
+
81
+ **Multi-Lang**:
82
+ - **Python**: `syntax_check script.py` → `✅ Python OK`
83
+ **Path Note**: Uses `__dirname` for utils/; resolves files to `process.cwd()`. See [path-resolution-best-practices.md](path-resolution-best-practices.md).
84
+ - **Bash**: `syntax_check script.sh` → `✅ Bash OK` ( + Shellcheck if avail.)
85
+ **Path Note**: Uses `__dirname` for utils/; resolves files to `process.cwd()`. See [path-resolution-best-practices.md](path-resolution-best-practices.md).
86
+ - **JSON**: `syntax_check config.json` → `✅ JSON OK`
87
+ **Path Note**: Uses `__dirname` for utils/; resolves files to `process.cwd()`. See [path-resolution-best-practices.md](path-resolution-best-practices.md).
88
+ - **Fail**: Invalid JSON → `❌ JSON invalid`
89
+
90
+ **Integration**: Post-`write_file`, agent can call `syntax_check(file)` for non-JS.
91
+ **Path Note**: Uses `__dirname` for utils/; resolves files to `process.cwd()`. See [path-resolution-best-practices.md](path-resolution-best-practices.md).
92
+
93
+ ## utils/syntax_check.sh (Underlying Script)
94
+ **Path Note**: Uses `__dirname` for utils/; resolves files to `process.cwd()`. See [path-resolution-best-practices.md](path-resolution-best-practices.md).
95
+ [Full source in prior doc]. Detects lang, runs checkers. Standalone/executable.
96
+
97
+ ### Usage (Direct)
98
+ ```bash
99
+ ./utils/syntax_check.sh test.js # ✅ JS OK
100
+ **Path Note**: Uses `__dirname` for utils/; resolves files to `process.cwd()`. See [path-resolution-best-practices.md](path-resolution-best-practices.md).
101
+ ./utils/syntax_check.sh bad.py # ❌ Python syntax error
102
+ **Path Note**: Uses `__dirname` for utils/; resolves files to `process.cwd()`. See [path-resolution-best-practices.md](path-resolution-best-practices.md).
103
+ ```
104
+
105
+ ## Agent Workflow Example
106
+ ```
107
+ User: "Create & validate test.js: const add = (a,b) => a+b; export {add};"
108
+ Agent:
109
+ 1. write_file(test.js, content) → ✓ JS OK
110
+ 2. syntax_check(test.js) → ✅ (redundant but confirms)
111
+ **Path Note**: Uses `__dirname` for utils/; resolves files to `process.cwd()`. See [path-resolution-best-practices.md](path-resolution-best-practices.md).
112
+ ```
113
+
114
+ ## Cross-Links
115
+ - [ToolSet](../toolset.md#generic-tools) ← [Linked below](#update-to-toolsetmd)
116
+ - [AgentManager](../agent-manager.md)
117
+ - Source: [lib/genericToolset.js](../lib/genericToolset.js), [utils/syntax_check.sh](../utils/syntax_check.sh)
118
+ **Path Note**: Uses `__dirname` for utils/; resolves files to `process.cwd()`. See [path-resolution-best-practices.md](path-resolution-best-practices.md).
119
+
120
+ **Updated**: March 27, 2026 (syntax_check integrated).
121
+ **Path Note**: Uses `__dirname` for utils/; resolves files to `process.cwd()`. See [path-resolution-best-practices.md](path-resolution-best-practices.md).
@@ -0,0 +1,164 @@
1
+ # ToolSet (\`lib/ToolSet.js\`)
2
+
3
+ ## Overview
4
+ **ToolSet** manages LLM function calls (tools): registration, execution, listing. Integrates with \`Prompt.js\` (via \`execute(prompt)\`) and \`AgentManager.js\` (pre-configured modes, generics). Supports JSON Schema params, async methods. Exports from \`lib/genericToolset.js\`: \`toolsPool\` (11 pre-built tools).
5
+
6
+ **Uses named exports from \`lib/index.js\` - NO default export.**
7
+
8
+ Key Features:
9
+ - **Modes**: \`toolChoice: 'auto'|'none'|'required'\` (default \`'auto'\`).
10
+ - **Validation**: Name regex \`/^\[#![a-z_0-9]{2,}$/\`.
11
+ - **Events** (via \`Prompt\`): \`tool_request\`, \`tool_error\`, \`tool_response\`.
12
+ - **Execution**: \`execute(prompt)\` processes \`function_request\`s from last message → calls → adds \`function_response\`s.
13
+
14
+ ## Constructor
15
+ \`\`\`javascript
16
+ import { ToolSet } from '@j-o-r/hello-dave';
17
+
18
+ new ToolSet(choice = 'auto'); // 'auto'|'none'|'required'
19
+ \`\`\`
20
+
21
+ ## Methods
22
+ | Method | Args | Returns | Description |
23
+ |--------|------|---------|-------------|
24
+ | \`add(name, desc, params, method)\` | \`string\`, \`string\`, \`TSSchema\`, \`async (params) => *\` | \`void\` | Register tool. Overwrites if exists. |
25
+ | \`get(name)\` | \`string\` | \`TSTool\` | Get tool details. |
26
+ | \`delete(name)\` | \`string\` | \`void\` | Remove tool. |
27
+ | \`has(name)\` | \`string\` | \`boolean\` | Exists? |
28
+ | \`list()\` | - | \`TSToolListItem[]\` (sorted) | All tools (name/desc/params). |
29
+ | \`call(name, params)\` | \`string\`, \`object\` | \`Promise<*\>\` | Execute tool. |
30
+ | \`execute(prompt)\` | \`Prompt\` | \`Promise<void>\` | Process last message \`function_request\`s → execute → add \`function_response\`s to \`tool\` role. |
31
+ | \`length\` | - | \`number\` | Tool count. |
32
+ | \`toolChoice\` | - | \`string\` | Getter for mode. |
33
+
34
+ **TSTool**: \`{description: string, parameters: TSSchema, method: async (params) => *}\`
35
+ **TSSchema**: OpenAI-style JSON Schema (\`{type: 'object', properties: {...}, required: [...]}\`).
36
+
37
+ ## Generic Tools (\`lib/genericToolset.js\` → \`toolsPool\`)
38
+ | `syntax_check` | Validate syntax (JS/Py/Bash/JSON) via utils/syntax_check.sh. |\n|-----|-----|
39
+ Pre-built \`ToolSet('auto')\` with **11 tools**. Copied via \`AgentManager.addGenericToolcall(name)\` or \`toolsetMode: 'auto'\`.
40
+
41
+ | Tool Name | Description |
42
+ |----------------------------|-------------|
43
+ | \`javascript_interpreter\` | Execute ESM ES6 JavaScript on \`node\`. \`console.log\` captures output. cwd: \`~/devpri/js/hello-dave\`. |
44
+ | \`get_user_env\` | Get user environment (name, system, city/region/country/timezone, external IP). |
45
+ | \`execute_bash_script\` | Execute raw Bash script/command (no escaping; verbatim \`$\| < > & " ' \\\\` newlines \`$(())\` \`[[ ]]\`. Heredoc-safe). Ubuntu 25.10. |
46
+ | \`send_email\` | Send email via \`msmtp\` (to, subject, body). |
47
+ | \`open_link\` | Open URL/file with \`xdg-open\`. |
48
+ | \`execute_remote_script\` | Execute raw Bash on remote via SSH (\`ssh://user@host[:port]\`). |
49
+ | \`history_search\` | Search chat sessions: \`"(todo\\|task)"\` or \`"package.json"\`. Regex in \`.cache/[app]/[prompt]/sessions/*.ndjson\`. |
50
+ | \`read_file\` | Read raw file in CWD (relative path, no \`/\` \`..\` \`\\\\\`). |
51
+ | \`write_file\` | Write raw content to file in CWD (relative, as-is; no escaping). Returns bytes written. |
52
+ | \`memory_recall\` | Recall persistent memory entries from agent-specific storage (\`.cache/[agent]/memory.ndjson\`). |
53
+ | \`memory_write\` | Write/update persistent memory entries for long-term state (\`.cache/[agent]/memory.ndjson\`). |
54
+
55
+ ## Memory Tools (New)
56
+ These tools provide persistent, agent-specific memory storage in NDJSON format (\`.cache/[agent-name]/memory.ndjson\`). Append-only; latest value per key. Ideal for token efficiency by offloading state/decisions from context.
57
+
58
+ ### \`memory_recall\`
59
+ **Description**: Retrieve the latest values for specified keys from memory file. Returns JSON: \`{key: value, ...}\` or \`{}\` if missing.
60
+
61
+ **Parameters**:
62
+ \`\`\`json
63
+ {
64
+ "type": "object",
65
+ "properties": {
66
+ "keys": {
67
+ "type": "array",
68
+ "items": { "type": "string" },
69
+ "description": "List of memory keys to recall, e.g., ['current_task', 'last_decision']"
70
+ }
71
+ },
72
+ "required": ["keys"]
73
+ }
74
+ \`\`\`
75
+
76
+ **Example Usage in Agent Prompt**:
77
+ \`\`\`
78
+ Before proceeding, recall your current task and previous decision:
79
+ - Call memory_recall with keys: ["current_task", "last_decision"]
80
+ Then, use the recalled info to avoid repetition.
81
+ \`\`\`
82
+
83
+ **Token Efficiency**: Stores tasks/decisions externally. Recall only needed state (e.g., 100 tokens) vs. full history (10k+ tokens), preventing loops/re-reasoning.
84
+
85
+ ### \`memory_write\`
86
+ **Description**: Append/update key-value pairs to memory (overwrites prior same-key entries). Returns confirmation with stored entries.
87
+
88
+ **Parameters**:
89
+ \`\`\`json
90
+ {
91
+ "type": "object",
92
+ "properties": {
93
+ "entries": {
94
+ "type": "array",
95
+ "items": {
96
+ "type": "object",
97
+ "properties": {
98
+ "key": { "type": "string", "description": "Unique key (e.g., 'current_task')" },
99
+ "value": { "type": "string", "description": "JSON-stringifiable value" }
100
+ },
101
+ "required": ["key", "value"]
102
+ },
103
+ "description": "List of {key, value} pairs to store"
104
+ }
105
+ },
106
+ "required": ["entries"]
107
+ }
108
+ \`\`\`
109
+
110
+ **Example Usage in Agent Prompt**:
111
+ \`\`\`
112
+ After analyzing, store the plan:
113
+ - Call memory_write with entries: [{"key": "current_task", "value": "Implement login feature"}, {"key": "step", "value": "1/5"}]
114
+ \`\`\`
115
+
116
+ **Token Efficiency**: Persist intermediate results across calls/sessions. Avoids context explosion/loops by recalling compact state instead of regenerating.
117
+
118
+ ## Integration with AgentManager
119
+ In \`setup()\`:
120
+ \`\`\`javascript
121
+ agent.setup({
122
+ toolsetMode: 'auto', // Loads all 11 generic tools
123
+ // or 'required': Empty ToolSet (add manually)
124
+ });
125
+ agent.addGenericToolcall('memory_recall'); // Selective copy post-setup
126
+ \`\`\`
127
+
128
+ **Custom Tools**:
129
+ \`\`\`javascript
130
+ import { AgentManager } from '@j-o-r/hello-dave';
131
+
132
+ agent.setup({ toolsetMode: 'required' });
133
+ const ts = agent.getToolset();
134
+ ts.add('math', 'Add numbers', {
135
+ type: 'object',
136
+ properties: {a: {type: 'number'}, b: {type: 'number'}},
137
+ required: ['a', 'b']
138
+ }, async ({a, b}) => a + b);
139
+ \`\`\`
140
+
141
+ **Workflow** (in \`Prompt.call()\` / API adapters):
142
+ 1. LLM → \`function_request\`s (assistant message).
143
+ 2. \`ToolSet.execute(prompt)\` → parallel \`call()\` → \`function_response\`s (tool message).
144
+ 3. Recurse until text response.
145
+
146
+ ## Examples
147
+ ### Standalone ToolSet
148
+ \`\`\`javascript
149
+ import { ToolSet } from '@j-o-r/hello-dave';
150
+
151
+ const ts = new ToolSet('required');
152
+ ts.add('hello', 'Say hello', {type: 'object', properties: {name: {type: 'string'}}, required: ['name']},
153
+ async ({name}) => \`Hello, \${name}!\`);
154
+ console.log(await ts.call('hello', {name: 'World'})); // "Hello, World!"
155
+ \`\`\`
156
+
157
+ ### With Prompt/AgentManager
158
+ See [AgentManager](./agent-manager.md#custom-tools--generics), [Prompt](./prompt-class.md).
159
+
160
+ **Updated:** March 26, 2026 (11 generics from \`lib/genericToolset.js\`).
161
+
162
+ See also: [GenericToolset Source](./generic-toolset.md).
163
+ \n## Syntax Validation\nSee [tools-syntax-validation.md](tools-syntax-validation.md) for `write_file` JS checks + `syntax_check` tool.
164
+ \n## Path Resolution\nSee [path-resolution-best-practices.md](path-resolution-best-practices.md) for __dirname vs cwd() in tools (e.g., syntax_check.sh).\\n
@@ -0,0 +1,111 @@
1
+ # xAI Responses API Integration (`lib/API/x.ai/responses.js`)
2
+
3
+ ## Overview
4
+ This module provides a seamless wrapper for the [xAI Responses API](https://docs.x.ai/docs/api-reference#create-new-response) (formerly Grok API), adapted for the hello-dave framework. It integrates directly with `Prompt.js` and `ToolSet.js`, enabling tool-using agents via `AgentManager`.
5
+
6
+ **Uses named exports from `lib/index.js` - NO default export.**
7
+
8
+ Key adaptations:
9
+ - **Unified Interface**: Uses `Prompt` messages/history for input; parses `output` into assistant/tool responses.
10
+ - **Recursive Tool Calls**: Automatically handles `function_call` → execute tools → `function_call_output` loops (up to `GLOBAL.max_recursive_requests`).
11
+ - **Tool Support**: Converts `ToolSet` to xAI `function` tools; supports native xAI tools like `web_search`, `x_search`.
12
+ - **Reasoning & Search**: Configurable `reasoning.effort` (`low`/`medium`/`high`), `search_parameters`.
13
+ - **Streaming**: Not yet implemented (future).
14
+ - **Auth**: Requires `XAIKEY` env var.
15
+
16
+ Default model: `grok-4-fast-reasoning`. Supports: `grok-4-fast-reasoning`, `grok-4-fast-non-reasoning`, etc.
17
+
18
+ ## Usage in AgentManager
19
+ ```javascript
20
+ import { AgentManager } from '@j-o-r/hello-dave';
21
+
22
+ const agent = new AgentManager({ name: 'weatheragent', secret: 'optional-ws-secret' });
23
+ agent.setup({
24
+ prompt: 'You are a precise weather expert. Use tools for real-time data.',
25
+ api: 'xai',
26
+ options: { model: 'grok-4-fast-reasoning', reasoning: { effort: 'high' } },
27
+ toolsetMode: 'auto', // Adds generic tools like web_search
28
+ contextWindow: 128000
29
+ });
30
+ agent.addGenericToolcall('web_search'); // Optional: Add extras
31
+
32
+ // CLI mode
33
+ agent.start(); // Interactive chat
34
+
35
+ // Or direct call
36
+ const response = await agent.directCall('Weather in Amsterdam today?');
37
+ console.log(response); // Handles search/tools automatically
38
+ ```
39
+
40
+ Under the hood:
41
+ 1. `Prompt.setAdaptor(API.text['xai'], toolset, options)` → uses `responses.request()`.
42
+ 2. Converts history to xAI `input[]` (system/user/assistant/tool).
43
+ 3. POST to `https://api.x.ai/v1/responses`.
44
+ 4. Parses `output` → adds text/reasoning/tools to `Prompt`.
45
+ 5. If tools needed, `ToolSet.execute()` → recurse until complete.
46
+
47
+ ## Options (XAIOptions)
48
+ | Property | Type | Default | Description |
49
+ |----------|------|---------|-------------|
50
+ | `model` | string | `'grok-4-fast-non-reasoning'` | e.g., `'grok-4-fast-reasoning'` |
51
+ | `input` | `XAIInput[]` | `[{role: 'system', content: 'Be precise'}]` | Messages/history |
52
+ | `reasoning.effort` | `'low'\|'medium'\|'high'` | `'medium'` | Reasoning depth |
53
+ | `reasoning.summary` | `'auto'\|'concise'\|'detailed'` | `'auto'` | Reasoning output style |
54
+ | `temperature` | number | `1` (0-2) | Sampling |
55
+ | `parallel_tool_calls` | boolean | `true` | Parallel functions |
56
+ | `tool_choice` | `'auto'` | `'auto'` | Tool selection |
57
+ | `tools` | `XAIFunctionTool[]` | `[]` | From `ToolSet` |
58
+ | `store` | boolean | `false` | Persist response (still bills tokens) |
59
+ | `max_output_tokens` | number | `4000` | Limit |
60
+ | `search_parameters` | object | - | `{max_search_results: 4, mode: 'auto', return_citations: true}` |
61
+
62
+ **Tool Types**:
63
+ - `function`: From `ToolSet` (name, description, parameters JSONSchema).
64
+ - Native: `web_search`, `x_search` (filters: dates, domains, etc.).
65
+
66
+ ## Example Request (Generated Internally)
67
+ ```json
68
+ {
69
+ "model": "grok-4-fast-reasoning",
70
+ "input": [
71
+ {"role": "system", "content": "You are a precise weather expert."},
72
+ {"role": "user", "content": "Weather in Amsterdam today?"}
73
+ ],
74
+ "parallel_tool_calls": true,
75
+ "reasoning": {"effort": "high"},
76
+ "search_parameters": {"mode": "auto", "return_citations": true},
77
+ "tools": [{"type": "function", "name": "web_search", ...}]
78
+ }
79
+ ```
80
+
81
+ ## Example Response (Parsed to Prompt)
82
+ - **Text + Citations**: Added as `assistant` text + `log` annotations (URLs).
83
+ - **Function Calls**: `assistant` with `function_request` → `ToolSet.execute()`.
84
+ - **Reasoning**: Prepended as `reasoning` multimodal text.
85
+
86
+ Sample parsed:
87
+ ```
88
+ Today is [date]. Weather: Cloudy, 5°C... [citations]
89
+ ```
90
+ Tokens: `input_tokens`, `output_tokens` (incl. `reasoning_tokens`) logged in `Prompt.records`.
91
+
92
+ ## Advanced: Custom Tools
93
+ Extend `ToolSet` before `setup()`:
94
+ ```javascript
95
+ import { ToolSet } from '@j-o-r/hello-dave';
96
+
97
+ const ts = new ToolSet('required');
98
+ ts.add('get_weather', 'Get weather for a location', {
99
+ type: 'object',
100
+ properties: { location: {type: 'string'} },
101
+ required: ['location']
102
+ }, async (params) => `Weather: ${params.location} - 20°C`); // Handler
103
+ agent.setup({ ..., toolsetMode: ts });
104
+ ```
105
+
106
+ ## Errors & Limits
107
+ - `Max recursive calls`: `GLOBAL.max_recursive_requests`.
108
+ - Missing `XAIKEY`: Throws.
109
+ - Invalid last message: Must end in `user`/`tool`.
110
+
111
+ See `lib/API/x.ai/responses.js` source for full JSDoc/types. Cross-links: [Prompt](../prompt-class.md), [ToolSet](../toolset.md), [AgentManager](agent-manager.md).
@@ -0,0 +1,106 @@
1
+ [x.ai collections](https://docs.x.ai/docs/guides/using-collections/api)
2
+
3
+
4
+ Creating a collection:
5
+
6
+ ```bash
7
+ curl https://management-api.x.ai/v1/collections \
8
+ -X POST \
9
+ -H "Content-Type: application/json" \
10
+ -H "Authorization: Bearer $XAI_MANAGEMENT_API_KEY" \
11
+ -d '{"collection_name": "SEC Filings"}'
12
+ ```
13
+
14
+ Listing collections:
15
+ ```bash
16
+ curl https://management-api.x.ai/v1/collections \
17
+ -H "Authorization: Bearer $XAI_MANAGEMENT_API_KEY"
18
+ ```
19
+
20
+ Viewing collection configuration:
21
+ ```bash
22
+ 'curl https://management-api.x.ai/v1/collections/collection_dbc087b1-6c99-493d-86c6-b401fee34a9d \
23
+ -H "Authorization: Bearer $XAI_MANAGEMENT_API_KEY"
24
+ ```
25
+
26
+ Updating collection configuration
27
+ ```bash
28
+ curl https://management-api.x.ai/v1/collections/collection_dbc087b1-6c99-493d-86c6-b401fee34a9d \
29
+ -X PUT \
30
+ -H "Content-Type: application/json" \
31
+ -H "Authorization: Bearer $XAI_MANAGEMENT_API_KEY" \
32
+ -d '{"collection_name": "SEC Filings (New)"}'
33
+ ```
34
+
35
+ Uploading documents:
36
+
37
+ ```bash
38
+ # Step 1: Upload file
39
+ curl https://api.x.ai/v1/files \
40
+ -H "Authorization: Bearer $XAI_API_KEY" \
41
+ -F file=@tesla-20241231.html
42
+
43
+ # Step 2: Add file to collection (use file_id from step 1)
44
+ curl -X POST https://management-api.x.ai/v1/collections/$COLLECTION_ID/documents/$FILE_ID \
45
+ -H "Authorization: Bearer $XAI_MANAGEMENT_API_KEY"
46
+
47
+ ```
48
+
49
+ Uploading with metadata fields
50
+
51
+ ```bash
52
+ curl https://management-api.x.ai/v1/collections/collection_dbc087b1-6c99-493d-86c6-b401fee34a9d/documents \
53
+ -H "Authorization: Bearer $XAI_MANAGEMENT_API_KEY" \
54
+ -F "name=paper.pdf" \
55
+ -F "data=@paper.pdf" \
56
+ -F "content_type=application/pdf" \
57
+ -F 'fields={"author": "Sandra Kim", "year": "2024", "title": "Q3 Revenue Analysis"}'
58
+
59
+ ```
60
+
61
+ Searching documents
62
+
63
+ ```bash
64
+ curl https://api.x.ai/v1/documents/search \
65
+ -H "Content-Type: application/json" \
66
+ -H "Authorization: Bearer $XAI_API_KEY" \
67
+ -d '{
68
+ "query": "What were the key revenue drivers based on the SEC filings?",
69
+ "source": {
70
+ "collection_ids": ["collection_dbc087b1-6c99-493d-86c6-b401fee34a9d"]
71
+ }
72
+ }'
73
+ ```
74
+
75
+ ```bash
76
+ curl https://api.x.ai/v1/documents/search \
77
+ -H "Content-Type: application/json" \
78
+ -H "Authorization: Bearer $XAI_API_KEY" \
79
+ -d '{
80
+ "query": "What were the key revenue drivers based on the SEC filings?",
81
+ "source": {
82
+ "collection_ids": [
83
+ "collection_dbc087b1-6c99-493d-86c6-b401fee34a9d"
84
+ ]
85
+ },
86
+ "retrieval_mode": {"type": "hybrid"}
87
+ }'
88
+ ```
89
+
90
+
91
+ Deleting a document:
92
+
93
+ ```bash
94
+ curl https://management-api.x.ai/v1/collections/collection_dbc087b1-6c99-493d-86c6-b401fee34a9d/documents/file_55a709d4-8edc-4f83-84d9-9f04fe49f832 \
95
+ -X DELETE \
96
+ -H "Authorization: Bearer $XAI_MANAGEMENT_API_KEY"
97
+
98
+ ```
99
+
100
+ Deleting a collection
101
+
102
+ ```bash
103
+ curl https://management-api.x.ai/v1/collections/collection_dbc087b1-6c99-493d-86c6-b401fee34a9d \
104
+ -X DELETE \
105
+ -H "Authorization: Bearer $XAI_MANAGEMENT_API_KEY"
106
+ ```
@@ -92,23 +92,33 @@ tools.add(
92
92
 
93
93
  tools.add(
94
94
  'execute_bash_script',
95
- 'Execute raw bash script or command (no escaping needed).',
95
+ 'Execute raw bash script or command (no escaping needed). Supports timeout to prevent hangs.',
96
96
  {
97
97
  type: 'object',
98
98
  properties: {
99
99
  bash_script: {
100
100
  type: 'string',
101
- description: `Raw bash verbatim. Supports all syntax safely via heredoc. System: ${user.system}`
101
+ description: `Raw bash verbatim. Supports all syntax safely via stdin. System: ${user.system}`
102
+ },
103
+ timeout: {
104
+ type: 'number',
105
+ default: 360,
106
+ description: 'Max execution time in seconds (default 360 seconds, 0 is no timeout). Uses @j-o-r/sh timeout (ms) with SIGTERM on expiry to prevent hangs from interactive prompts or slow commands.'
102
107
  }
103
108
  },
104
109
  required: ['bash_script']
105
110
  },
106
111
  async (params) => {
107
- const delim = `END_SCRIPT_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
112
+ const timeoutSec = Number(params.timeout ?? 300);
113
+ if (isNaN(timeoutSec) || timeoutSec < 0) throw new Error('Invalid timeout');
114
+ const timeout = timeoutSec * 1000;
115
+ // return await SH`bash`.options({ timeout: timeoutMs }).run(params.bash_script);
116
+ const delim = `END_SCRIPT_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
108
117
  return await SH`bash <<'${delim}'
109
118
  ${params.bash_script}
110
119
  ${delim}
111
- `.run();
120
+ `.options({timeout}).run();
121
+
112
122
  }
113
123
  );
114
124
 
@@ -151,17 +161,25 @@ tools.add(
151
161
 
152
162
  tools.add(
153
163
  'execute_remote_script',
154
- 'Run bash on remote via SSH.',
164
+ 'Run bash on remote via SSH. Supports timeout to prevent hangs.',
155
165
  {
156
166
  type: 'object',
157
167
  properties: {
158
168
  url: { type: 'string', description: 'ssh://user@host[:port]' },
159
- script: { type: 'string', description: 'Raw script' }
169
+ script: { type: 'string', description: 'Raw script' },
170
+ timeout: {
171
+ type: 'number',
172
+ default: 30,
173
+ description: 'Max execution time in seconds (default 30). Uses @j-o-r/sh timeout (ms) with SIGTERM on SSH process expiry.'
174
+ }
160
175
  },
161
176
  required: ['url', 'script']
162
177
  },
163
178
  async (params) => {
164
179
  const { url, script } = params;
180
+ const timeoutSec = Number(params.timeout ?? 30);
181
+ if (isNaN(timeoutSec) || timeoutSec <= 0) throw new Error('Invalid timeout');
182
+ const timeoutMs = timeoutSec * 1000;
165
183
  if (!url.startsWith('ssh://')) throw new Error('ssh://user@host[:port]');
166
184
  const withoutProto = url.slice(6);
167
185
  const parts = withoutProto.split(':');
@@ -169,12 +187,7 @@ tools.add(
169
187
  if (parts.length > 1) { userHost = parts[0]; port = parseInt(parts[1]); }
170
188
  const [user, host] = userHost.split('@');
171
189
  if (!user || !host) throw new Error('Invalid SSH URL');
172
-
173
- const delim = `END_SCRIPT_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
174
- return await SH`ssh -p ${port} ${user}@${host} bash <<'${delim}'
175
- ${script}
176
- ${delim}
177
- `.run();
190
+ return await SH`ssh -p ${port} ${user}@${host} bash`.options({ timeout: timeoutMs }).run(script);
178
191
  }
179
192
  );
180
193
 
@@ -297,4 +310,4 @@ tools.add(
297
310
  }
298
311
  );
299
312
 
300
- export default tools;
313
+ export default tools;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@j-o-r/hello-dave",
3
3
  "type": "module",
4
- "version": "0.0.7",
4
+ "version": "0.0.8",
5
5
  "description": "ESM toolkit for building AI agents with unified access to Grok (XAI), OpenAI, and Anthropic endpoints",
6
6
  "main": "./lib/index.js",
7
7
  "types": "./types/index.d.ts",