diff options
| author | Agando <roduccomm@gmail.com> | 2026-06-17 06:01:20 +0200 |
|---|---|---|
| committer | Agando <roduccomm@gmail.com> | 2026-06-17 06:01:20 +0200 |
| commit | cebacc27a48168e666679018f8e27156d12d4527 (patch) | |
| tree | b306d33b67b9d8c84bd9b9c16b1e91ee217628a6 /modules/core/module-aiassist.js | |
| parent | 6aa24b976952a698c673d350977721b27193183d (diff) | |
auto: 2026-06-17_06:01 changes
Diffstat (limited to 'modules/core/module-aiassist.js')
| -rw-r--r-- | modules/core/module-aiassist.js | 196 |
1 files changed, 189 insertions, 7 deletions
diff --git a/modules/core/module-aiassist.js b/modules/core/module-aiassist.js index c5a91c9..3cf8b65 100644 --- a/modules/core/module-aiassist.js +++ b/modules/core/module-aiassist.js @@ -57,6 +57,14 @@ buildSystemPrompt() { return `Current date: ${dateStr}\nCurrent time: ${timeStr}\n\n${saved}`; } } catch (e) {} + // Check SmartContextModule for active profile system prompt + let profilePrompt = ''; + try { + const scm = this.terminal?.moduleManager?.modules?.SmartContextModule; + if (scm && scm.activeProfile && scm.contextProfiles[scm.activeProfile]) { + profilePrompt = scm.contextProfiles[scm.activeProfile].systemPrompt || ''; + } + } catch (e) {} const now = new Date(); const dateStr = now.getFullYear() + '-' + String(now.getMonth()+1).padStart(2,'0') + '-' + String(now.getDate()).padStart(2,'0'); const nvfs = this.terminal?.moduleManager?.modules?.NeuralVFSModule; @@ -67,11 +75,15 @@ buildSystemPrompt() { if (ageMs > 14400000) nvfsNote = ' |nvfs ' + Math.floor(ageMs/3600000) + 'h stale'; } } catch (e) {} - return 'Current date: ' + dateStr + nvfsNote + '\n' + let base = 'Current date: ' + dateStr + nvfsNote + '\n' + '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 | VaultMind: vaultmind_query(ep,msg,agent) — Hyperliquid prices/portfolio/chat\n' + + 'FS: list/read/write/delete | NVFS: nvfs-resolve | Web: search/fetch [POST=method+body] | Mod: view/edit/test/reload | Config | Skills | VaultMind: vaultmind_connect(network) — connect wallet, vaultmind_status — check session, vaultmind_query(ep,msg,agent) — Hyperliquid prices/portfolio/chat | wallet_lookup(address) — read-only portfolio for any wallet\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'; + if (profilePrompt) { + base = profilePrompt + '\n\n' + base; + } + return base; } getToolDefinitions() { if (!this._toolDefs) this._toolDefs = this._buildToolDefs(); @@ -440,6 +452,43 @@ buildSystemPrompt() { required: ['endpoint'] } } + }, { + type: 'function', + function: { + name: 'vaultmind_connect', + description: 'Connect to VaultMind AI by reading Hyperliquid private key from SecretVault (stored as "hyperliquid_key") and authenticating with the backend. Stores session token in localStorage.', + parameters: { + type: 'object', + properties: { + network: { type: 'string', enum: ['testnet', 'mainnet'], description: 'Hyperliquid network (default testnet)' } + }, + required: [] + } + } + }, { + type: 'function', + function: { + name: 'vaultmind_status', + description: 'Check if VaultMind AI session token exists and is valid in localStorage.', + parameters: { + type: 'object', + properties: {}, + required: [] + } + } + }, { + type: 'function', + function: { + name: 'wallet_lookup', + description: 'Read-only Hyperliquid wallet lookup — returns portfolio, positions, and account value for any wallet address. No auth needed.', + parameters: { + type: 'object', + properties: { + address: { type: 'string', description: 'Hyperliquid wallet address (0x...)' } + }, + required: ['address'] + } + } }]; } getHelpInfo() { @@ -456,7 +505,9 @@ buildSystemPrompt() { 'ai-model': 'ai-model [model] — Show or set AI model', 'ai-config': 'ai-config [key] [value] — View or set AI loop config (max-turns, max-context, confirm-timeout(0=disabled))', 'mem-debug': 'mem-debug — Show memory breakdown by component', - 'reset-mem': 'reset-mem — Reset AI memory (logs, context, profile, guardrails) without losing VFS or config' + 'reset-mem': 'reset-mem — Reset AI memory (logs, context, profile, guardrails) without losing VFS or config', + 'vaultmind-connect': 'vaultmind-connect [testnet|mainnet] — Connect VaultMind wallet using hyperliquid_key from SecretVault', + 'vaultmind-status': 'vaultmind-status — Check VaultMind session status', }; } registerCommands() { @@ -481,6 +532,8 @@ buildSystemPrompt() { this.commands['shadow-rollback'] = () => this.shadowRollback(); this.commands['mem-debug'] = () => this.memDebug(); this.commands['reset-mem'] = () => this.resetMem(); + this.commands['vaultmind-connect'] = (args) => this._vaultmindConnectCmd(args); + this.commands['vaultmind-status'] = () => this._vaultmindStatusCmd(); } async chat(args) { const userMessage = args.join(' '); @@ -1846,6 +1899,8 @@ buildSystemPrompt() { } scm.activeProfile = name; const profile = scm.contextProfiles[name]; + // Rebuild system prompt to reflect new context profile + this.systemPrompt = this.buildSystemPrompt(); return JSON.stringify({ success: true, name, displayName: profile.name, systemPrompt: profile.systemPrompt, temperature: profile.temperature }); } case 'create_mindmap': { @@ -1876,6 +1931,53 @@ buildSystemPrompt() { case 'list_modified_modules': case 'get_module_status': return await this.runModuleTool(name, argsStr); + case 'vaultmind_connect': { + const network = a.network || 'testnet'; + try { + // Read Hyperliquid key from SecretVault + const vault = window.webx11_secretVault; + if (!vault) return JSON.stringify({ error: 'SecretVault not available — unlock it first with secret-unlock <pin>' }); + const privateKey = await vault.decrypt('hyperliquid_key'); + if (!privateKey) return JSON.stringify({ error: 'No hyperliquid_key found in SecretVault. Store it first: secret-set hyperliquid_key 0x...' }); + // Authenticate with VaultMind backend + const resp = await fetch('/vmai-api/auth/wallet', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ private_key: privateKey, account_address: null, network: network }) + }); + if (!resp.ok) { + const errText = await resp.text(); + return JSON.stringify({ error: 'VaultMind auth failed (' + resp.status + '): ' + errText }); + } + const data = await resp.json(); + if (data.token) { + localStorage.setItem('vaultmind_token', data.token); + return JSON.stringify({ success: true, status: data.status || 'connected', network: data.network || network, message: 'Connected to VaultMind on ' + (data.network || network) }); + } + return JSON.stringify({ error: 'No token returned from VaultMind', data: data }); + } catch (e) { + return JSON.stringify({ error: 'VaultMind connect error: ' + e.message }); + } + } + case 'vaultmind_status': { + try { + const token = localStorage.getItem('vaultmind_token'); + if (!token) return JSON.stringify({ connected: false, message: 'No VaultMind session token found. Use vaultmind_connect to authenticate.' }); + // Try to verify by calling a lightweight endpoint + try { + const resp = await fetch('/vmai-api/portfolio', { + headers: { 'Authorization': 'Bearer ' + token } + }); + if (resp.ok) return JSON.stringify({ connected: true, token_exists: true, token_prefix: token.substring(0, 12) + '...', message: 'VaultMind session is active and valid.' }); + if (resp.status === 401) return JSON.stringify({ connected: false, token_exists: true, message: 'Token exists but is expired or invalid. Reconnect with vaultmind_connect.' }); + return JSON.stringify({ connected: true, token_exists: true, message: 'Token exists (status: ' + resp.status + ').' }); + } catch (e) { + return JSON.stringify({ connected: true, token_exists: true, message: 'Token exists but backend unreachable (' + e.message + ').' }); + } + } catch (e) { + return JSON.stringify({ error: 'VaultMind status error: ' + e.message }); + } + } case 'vaultmind_query': { const ep = a.endpoint; const validEps = ['prices', 'portfolio', 'transactions', 'copy-trade', 'chat']; @@ -1883,11 +1985,20 @@ buildSystemPrompt() { return JSON.stringify({ error: 'Invalid endpoint. Valid: ' + validEps.join(', ') }); } try { - let url = '/vmai/' + ep; + const epMap = { prices: '/vmai/market/prices', portfolio: '/vmai/portfolio', transactions: '/vmai/transactions/summary', 'copy-trade': '/vmai/copy-trading/traders', chat: '/vmai/chat' }; + let url = epMap[ep]; let opts = { method: 'GET', headers: { 'Accept': 'application/json' } }; + // Portfolio, transactions, copy-trade need auth token + const authEps = ['portfolio', 'transactions', 'copy-trade']; + if (authEps.includes(ep)) { + const token = localStorage.getItem('vaultmind_token'); + if (token) opts.headers['Authorization'] = 'Bearer ' + token; + } if (ep === 'chat') { opts.method = 'POST'; opts.headers['Content-Type'] = 'application/json'; + const token = localStorage.getItem('vaultmind_token'); + if (token) opts.headers['Authorization'] = 'Bearer ' + token; opts.body = JSON.stringify({ message: a.message || 'What is the current market status?', agent: a.agent || 'market' @@ -1900,6 +2011,17 @@ buildSystemPrompt() { return JSON.stringify({ error: 'VaultMind API error: ' + e.message }); } } + case 'wallet_lookup': { + const addr = a.address; + if (!addr) return JSON.stringify({ error: 'Wallet address required' }); + try { + const resp = await fetch('/wallet/' + encodeURIComponent(addr)); + const data = await resp.json(); + return JSON.stringify({ success: true, data }); + } catch (e) { + return JSON.stringify({ error: 'Wallet lookup error: ' + e.message }); + } + } default: return JSON.stringify({ error: `Unknown tool: ${name}` }); } @@ -2226,7 +2348,7 @@ buildSystemPrompt() { } } _getAiConfigKeys() { - return ['max-turns', 'max-context', 'max-context-tokens', 'confirm-timeout', 'chat-lock-timeout', 'skill-debounce', 'trivial-optimization']; + return ['max-turns', 'max-context', 'max-context-tokens', 'confirm-timeout', 'chat-lock-timeout', 'skill-debounce', 'trivial-optimization', 'temperature', 'top-p', 'max-tokens', 'thinking']; } aiConfig(args) { if (args.length === 0) { @@ -2238,8 +2360,15 @@ buildSystemPrompt() { this.terminal.print(`confirm-timeout: ${this._confirmTimeoutMs > 0 ? this._confirmTimeoutMs / 1000 + 's' : 'disabled (no auto-deny)'} (default: 120s)`, ''); this.terminal.print(`chat-lock-timeout: ${this._chatLockTimeoutMs / 1000}s (default: 10s)`, ''); this.terminal.print(`skill-debounce: ${this._skillDebounceMs / 60000}min (default: 30min)`, ''); + const om = this.terminal?.ollamaManager; + if (om && om.modelParams) { + this.terminal.print(`temperature: ${om.modelParams.temperature} (default: 0.7)`, ''); + this.terminal.print(`top-p: ${om.modelParams.top_p} (default: 0.9)`, ''); + this.terminal.print(`max-tokens: ${om.modelParams.max_tokens} (default: 4096)`, ''); + this.terminal.print(`thinking: ${om.modelParams.thinking} (default: off)`, ''); + } this.terminal.print('Usage: ai-config <key> <value>', 'info'); - this.terminal.print('Keys: max-turns, max-context, max-context-tokens, confirm-timeout(0=disabled), chat-lock-timeout, skill-debounce, trivial-optimization', 'info'); + this.terminal.print('Keys: max-turns, max-context, max-context-tokens, confirm-timeout(0=disabled), chat-lock-timeout, skill-debounce, trivial-optimization, temperature, top-p, max-tokens, thinking', 'info'); return; } const key = args[0]; @@ -2272,8 +2401,28 @@ buildSystemPrompt() { if (this.terminal?.ollamaManager) { this.terminal.ollamaManager.optimizationEnabled = val === 'on'; } + } else if (key === 'temperature') { + const n = parseFloat(val); + if (isNaN(n) || n < 0 || n > 2) return this.terminal.print('temperature must be 0-2', 'warning'); + const om = this.terminal?.ollamaManager; + if (om && om.modelParams) { om.modelParams.temperature = n; om._saveModelParams(); } + } else if (key === 'top-p') { + const n = parseFloat(val); + if (isNaN(n) || n < 0 || n > 1) return this.terminal.print('top-p must be 0-1', 'warning'); + const om = this.terminal?.ollamaManager; + if (om && om.modelParams) { om.modelParams.top_p = n; om._saveModelParams(); } + } else if (key === 'max-tokens') { + const n = parseInt(val); + if (isNaN(n) || n < 1 || n > 131072) return this.terminal.print('max-tokens must be 1-131072', 'warning'); + const om = this.terminal?.ollamaManager; + if (om && om.modelParams) { om.modelParams.max_tokens = n; om._saveModelParams(); } + } else if (key === 'thinking') { + const validModes = ['off', 'deepseek_reasoner', 'deepseek']; + if (!validModes.includes(val)) return this.terminal.print(`thinking must be one of: ${validModes.join(', ')}`, 'warning'); + const om = this.terminal?.ollamaManager; + if (om && om.modelParams) { om.modelParams.thinking = val; om._saveModelParams(); } } else { - return this.terminal.print(`Unknown key: ${key}. Valid: max-turns, max-context, max-context-tokens, confirm-timeout, chat-lock-timeout, skill-debounce, trivial-optimization`, 'warning'); + return this.terminal.print(`Unknown key: ${key}. Valid: max-turns, max-context, max-context-tokens, confirm-timeout, chat-lock-timeout, skill-debounce, trivial-optimization, temperature, top-p, max-tokens, thinking`, 'warning'); } // Persist localStorage.setItem('webx11_ai_config', JSON.stringify({ @@ -2431,4 +2580,37 @@ buildSystemPrompt() { this.terminal.print('Compression error: ' + e.message, 'error'); }); } + async _vaultmindConnectCmd(args) { + const network = args[0] || 'testnet'; + try { + const vault = window.webx11_secretVault; + if (!vault) { this.terminal.print('SecretVault not available', 'error'); return; } + const privateKey = await vault.decrypt('hyperliquid_key'); + if (!privateKey) { this.terminal.print('No hyperliquid_key in SecretVault. Use: secret-set hyperliquid_key 0x...', 'error'); return; } + this.terminal.print('Connecting to VaultMind...', 'info'); + const resp = await fetch('/vmai-api/auth/wallet', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ private_key: privateKey, account_address: null, network }) + }); + if (!resp.ok) { this.terminal.print('Auth failed: ' + resp.status, 'error'); return; } + const data = await resp.json(); + if (data.token) { + localStorage.setItem('vaultmind_token', data.token); + this.terminal.print('✅ Connected to VaultMind (' + (data.network || network) + ')', 'success'); + } else { + this.terminal.print('No token returned', 'error'); + } + } catch (e) { + this.terminal.print('Error: ' + e.message, 'error'); + } + } + _vaultmindStatusCmd() { + const token = localStorage.getItem('vaultmind_token'); + if (token) { + this.terminal.print('✅ VaultMind session active (token: ' + token.substring(0, 12) + '...)', 'success'); + } else { + this.terminal.print('❌ No VaultMind session. Use: vaultmind-connect [testnet|mainnet]', 'warning'); + } + } } |