From df2ae3d7d89f4c75a963857fd53a6c1dc7f07d85 Mon Sep 17 00:00:00 2001 From: archipelago Date: Mon, 22 Jun 2026 10:58:58 -0400 Subject: [PATCH] feat(demo): ground AIUI chat in the node's mock state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Claude proxy injects a system-prompt describing this node (version, signet chain + height, wallet balances, installed apps, 5 FIPS peers / 12 trusted nodes) into every demo chat request. The assistant answers local-node and Bitcoin questions with the node's real-looking data automatically — no /seed needed. Co-Authored-By: Claude Opus 4.8 (1M context) --- neode-ui/mock-backend.js | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/neode-ui/mock-backend.js b/neode-ui/mock-backend.js index 7048f083..1353f83c 100755 --- a/neode-ui/mock-backend.js +++ b/neode-ui/mock-backend.js @@ -3611,6 +3611,27 @@ app.get('/app/filebrowser/api/raw/*', (req, res) => { res.send(Buffer.isBuffer(content) ? content : String(content)) }) +// A compact description of the current (mock) node, fed to the AI assistant as +// system context in the demo so it can answer questions about this node. +function demoNodeContext() { + const s = currentStore() + const md = s.mockData + const w = s.walletState + const apps = Object.entries(md['package-data'] || {}) + .map(([id, a]) => `${a.title || id} (${a.state || 'running'})`) + return [ + 'You are the AI assistant built into this Archipelago node. This is a public DEMO node running on Bitcoin signet (testnet) with simulated data — answer as if everything is real, be concise and helpful, and feel free to discuss Bitcoin, Lightning, self-hosting and the node itself.', + '', + 'CURRENT NODE STATE:', + `- Software: Archipelago ${md['server-info']?.version || 'demo'}, Tor address ${md['server-info']?.['tor-address'] || 'n/a'}`, + `- Bitcoin: signet, block height 902,418, fully synced (Bitcoin Knots).`, + `- Wallet: on-chain ${w.onchain_sats.toLocaleString()} sats, Lightning ${w.channel_sats.toLocaleString()} sats, ecash ${w.ecash_sats.toLocaleString()} sats.`, + `- Installed apps (${apps.length}): ${apps.join(', ')}.`, + `- Network: FIPS encrypted mesh active with 5 authenticated peers; 12 trusted/federated nodes; Tor hidden services online.`, + '- The user can install apps, manage their Lightning/ecash wallet, browse & buy peer files, and chat with the mesh — all from this dashboard.', + ].join('\n') +} + // Claude API Proxy (reads ANTHROPIC_API_KEY from environment) // Uses fetch (Node 22+) for reliable DNS resolution and streaming in Docker/Alpine // ============================================================================= @@ -3644,6 +3665,16 @@ app.post('/aiui/api/claude/*', async (req, res) => { delete body.webSearch delete body.webResults delete body.context + + // DEMO: ground the assistant in THIS node's (mock) state so it answers + // questions about the local node, its apps, wallet and Bitcoin like a real + // Archipelago assistant — no /seed needed. + if (DEMO) { + const ctx = demoNodeContext() + if (typeof body.system === 'string') body.system = ctx + '\n\n' + body.system + else if (Array.isArray(body.system)) body.system = [{ type: 'text', text: ctx }, ...body.system] + else body.system = ctx + } } const bodyStr = JSON.stringify(body)