aboutsummaryrefslogtreecommitdiff
path: root/modules/core/module-aiassist.js
diff options
context:
space:
mode:
Diffstat (limited to 'modules/core/module-aiassist.js')
-rw-r--r--modules/core/module-aiassist.js46
1 files changed, 37 insertions, 9 deletions
diff --git a/modules/core/module-aiassist.js b/modules/core/module-aiassist.js
index 3af7f9b..5a0c389 100644
--- a/modules/core/module-aiassist.js
+++ b/modules/core/module-aiassist.js
@@ -66,9 +66,10 @@ buildSystemPrompt() {
}
} catch (e) {}
return 'Current date: ' + dateStr + nvfsNote + '\n'
- + 'VFS\u2192Modules\u2192AI. nvfs-index for commands. Tool\u2192Observe\u2192Answer. nvfs-resolve. Destructive cmds need confirm.\n'
- + 'FS: list/read/write/delete | NVFS: nvfs-resolve | Web: search/fetch | Mod: view/edit/test/reload | Config | Skills\n'
- + 'Other: floating, webdav, cron, vault, sandbox, agents, wpm, mindmap, memgraph, guardrail, wget, tar, secret-* \u2014 discoverable via help';
+ + 'VFS→Modules→AI. nvfs-index for commands. Tool→Observe→Answer. nvfs-resolve. Destructive cmds need confirm.\n'
+ + 'FS: list/read/write/delete | NVFS: nvfs-resolve | Web: search/fetch [POST=method+body] | Mod: view/edit/test/reload | Config | Skills\n'
+ + 'web_fetch tool: GET for normal pages (returns title+content+word_count), POST for JSON APIs like Hyperliquid /info (pass method="POST" and body as JSON string).\n'
+ + 'Other: floating, webdav, cron, vault, sandbox, agents, wpm, mindmap, memgraph, guardrail, wget, tar, secret-* — discoverable via help';
}
getToolDefinitions() {
if (!this._toolDefs) this._toolDefs = this._buildToolDefs();
@@ -135,8 +136,17 @@ buildSystemPrompt() {
type: 'function',
function: {
name: 'web_fetch',
- description: 'Fetch & extract URL content',
- parameters: { type: 'object', properties: { url: { type: 'string', description: 'Full URL' } }, required: ['url'] }
+ description: 'Fetch & extract URL content. Supports GET (default) and POST (for APIs like Hyperliquid /info).',
+ parameters: {
+ type: 'object',
+ properties: {
+ url: { type: 'string', description: 'Full URL' },
+ method: { type: 'string', enum: ['GET', 'POST'], description: 'HTTP method (default GET)' },
+ body: { type: 'string', description: 'Request body for POST (JSON string, max 10KB)' },
+ content_type: { type: 'string', description: 'Content-Type header (default application/json for POST)' }
+ },
+ required: ['url']
+ }
}
}, {
type: 'function',
@@ -1466,7 +1476,10 @@ buildSystemPrompt() {
if (!query) return JSON.stringify({ error: 'No query provided' });
try {
const resp = await fetch('/api/search?q=' + encodeURIComponent(query));
- if (!resp.ok) { return JSON.stringify({ error: 'Search API returned HTTP ' + resp.status }); }
+ if (!resp.ok) {
+ const err = await resp.json().catch(() => ({}));
+ return JSON.stringify({ error: 'Search failed: ' + (err.error || `HTTP ${resp.status}`), status: resp.status, details: err.details || '' });
+ }
const data = await resp.json();
const results = data.results || [];
if (results.length === 0) return JSON.stringify({ message: 'No results found' });
@@ -1476,12 +1489,27 @@ buildSystemPrompt() {
case 'web_fetch': {
const url = a.url || '';
if (!url) return JSON.stringify({ error: 'No URL provided' });
+ const method = (a.method || 'GET').toUpperCase();
+ const body = a.body || '';
+ const contentType = a.content_type || (method === 'POST' ? 'application/json' : '');
try {
- const resp = await fetch('/api/extract?url=' + encodeURIComponent(url));
+ // Use /api/fetch for POST, /api/extract for GET (extract is cleaner for readable content)
+ const endpoint = method === 'POST' ? '/api/fetch' : '/api/extract';
+ const params = new URLSearchParams({ url });
+ if (method === 'POST') { params.set('method', 'POST'); params.set('body', body); if (contentType) params.set('content_type', contentType); }
+ const resp = await fetch(endpoint + '?' + params.toString());
if (resp.status === 403) return JSON.stringify({ error: 'URL blocked — internal network' });
- if (!resp.ok) { return JSON.stringify({ error: 'Fetch API returned HTTP ' + resp.status }); }
+ if (!resp.ok) {
+ const err = await resp.json().catch(() => ({}));
+ return JSON.stringify({ error: 'Fetch failed: ' + (err.error || `HTTP ${resp.status}`), status: resp.status, details: err.details || '' });
+ }
+ // For POST/route, the response is raw text; for GET/extract it's JSON
+ if (method === 'POST') {
+ const text = await resp.text();
+ return JSON.stringify({ method, content: text.substring(0, 4000), content_length: text.length });
+ }
const data = await resp.json();
- return JSON.stringify({ title: data.title || '', content: (data.content || '').substring(0, 4000), word_count: data.word_count || 0, method: data.method || 'extract' });
+ return JSON.stringify({ method, title: data.title || '', content: (data.content || '').substring(0, 4000), word_count: data.word_count || 0, method_proxy: data.method || 'extract' });
} catch (e) { return JSON.stringify({ error: 'Fetch failed: ' + e.message }); }
}
case 'wpm_install': {