feat(demo): ground AIUI chat in the node's mock state

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) <noreply@anthropic.com>
This commit is contained in:
archipelago 2026-06-22 10:58:58 -04:00
parent 3f411c1d10
commit df2ae3d7d8

View File

@ -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)