aboutsummaryrefslogtreecommitdiff
path: root/modules/core/module-aiassist.js
diff options
context:
space:
mode:
authorAgando <roduccomm@gmail.com>2026-06-17 06:01:20 +0200
committerAgando <roduccomm@gmail.com>2026-06-17 06:01:20 +0200
commitcebacc27a48168e666679018f8e27156d12d4527 (patch)
treeb306d33b67b9d8c84bd9b9c16b1e91ee217628a6 /modules/core/module-aiassist.js
parent6aa24b976952a698c673d350977721b27193183d (diff)
auto: 2026-06-17_06:01 changes
Diffstat (limited to 'modules/core/module-aiassist.js')
-rw-r--r--modules/core/module-aiassist.js196
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');
+ }
+ }
}