fix: connect AI funding scan to the wallet scanner
This commit is contained in:
@@ -385,3 +385,15 @@ change the allowance, send a payment, start inference, or publish content. API
|
||||
keys use the existing private node credential store and are not passed to AIUI.
|
||||
Focused provider/publishing tests and production qualification are in progress;
|
||||
these changes are not yet deployed or publicly released.
|
||||
|
||||
Provider-focused validation: 20 dashboard/setup/signer tests, 22 AIUI provider
|
||||
and generation tests, and 22 trusted bridge/integration tests pass. Initial
|
||||
publishing tests required an AI-connection component stub for their isolated
|
||||
mounts; the provider default test now checks initial state before the suite's
|
||||
explicit Claude selection. The full backend suite and production builds remain
|
||||
pending. Framework still runs the preceding candidate; its management service is
|
||||
active and no Ollama container exists after cleanup.
|
||||
The funding modal's Scan action now opens the existing wallet scanner and returns
|
||||
to funding on close; six focused connection-modal tests pass after that wiring.
|
||||
The first dashboard production build passed; it will be rebuilt for this final
|
||||
scanner wiring before deployment. AIUI and isolated backend builds are ongoing.
|
||||
|
||||
@@ -28,7 +28,8 @@
|
||||
<button v-if="status?.local_ready" class="glass-button rounded-lg px-4 py-2 text-sm text-white mt-4 w-full" @click="useLocal">Use local AI</button>
|
||||
<p class="text-xs text-white/40 mt-4">Your draft stays in place when you close this window.</p>
|
||||
</BaseModal>
|
||||
<ReceiveBitcoinModal :show="show && funding" initial-method="ecash" @close="finishFunding" @received="finishFunding" />
|
||||
<ReceiveBitcoinModal :show="show && funding && !scanning" initial-method="ecash" @close="finishFunding" @received="finishFunding" @scan="scanning = true" />
|
||||
<WalletScanModal :show="show && scanning" @close="finishScan" @sent="finishScan" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@@ -36,6 +37,7 @@ import { computed, ref, watch } from 'vue'
|
||||
import { rpcClient } from '@/api/rpc-client'
|
||||
import BaseModal from './BaseModal.vue'
|
||||
import ReceiveBitcoinModal from './ReceiveBitcoinModal.vue'
|
||||
import WalletScanModal from './WalletScanModal.vue'
|
||||
import RoutstrBudgetSection from '@/views/settings/RoutstrBudgetSection.vue'
|
||||
|
||||
type Choice = 'claude' | 'openai' | 'routstr'
|
||||
@@ -59,6 +61,7 @@ const error = ref('')
|
||||
const loading = ref(false)
|
||||
const saving = ref(false)
|
||||
const funding = ref(false)
|
||||
const scanning = ref(false)
|
||||
const configured = computed(() => mode.value === 'claude' ? status.value?.claude_configured : status.value?.openai_configured)
|
||||
let refreshPromise: Promise<ProviderStatus | null> | null = null
|
||||
async function refresh(): Promise<ProviderStatus | null> {
|
||||
@@ -96,7 +99,7 @@ async function refreshBalance() {
|
||||
catch { balance.value = null }
|
||||
}
|
||||
function choose(choice: Choice) { key.value = ''; error.value = ''; mode.value = choice; if (choice === 'routstr') void refreshBalance() }
|
||||
function close() { key.value = ''; funding.value = false; emit('close') }
|
||||
function close() { key.value = ''; funding.value = false; scanning.value = false; emit('close') }
|
||||
async function save() {
|
||||
if ((mode.value !== 'claude' && mode.value !== 'openai') || saving.value) return
|
||||
const provider = mode.value
|
||||
@@ -128,8 +131,9 @@ async function continueRoutstr() {
|
||||
emit('configured', 'routstr'); close()
|
||||
} catch { error.value = 'Could not select Routstr. Try again.' }
|
||||
}
|
||||
async function finishScan() { scanning.value = false; await refreshBalance() }
|
||||
async function finishFunding() { funding.value = false; await refreshBalance() }
|
||||
watch(() => props.show, open => { if (open) { error.value = ''; void refresh(); if (mode.value === 'routstr') void refreshBalance() } else { key.value = ''; funding.value = false } })
|
||||
watch(() => props.show, open => { if (open) { error.value = ''; void refresh(); if (mode.value === 'routstr') void refreshBalance() } else { key.value = ''; funding.value = false; scanning.value = false } })
|
||||
async function syncSelection() { const state = await refresh(); if (state) emit('configured', state.settings.provider, state.settings.provider === 'openai' ? state.settings.openai_model : undefined) }
|
||||
defineExpose({ checkNeeded, syncSelection, showRoutstr: () => choose('routstr') })
|
||||
</script>
|
||||
|
||||
@@ -2,8 +2,10 @@ import { mount, flushPromises } from '@vue/test-utils'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import AIConnectionModal from '../AIConnectionModal.vue'
|
||||
import ReceiveBitcoinModal from '../ReceiveBitcoinModal.vue'
|
||||
import WalletScanModal from '../WalletScanModal.vue'
|
||||
import { rpcClient } from '@/api/rpc-client'
|
||||
vi.mock('@/api/rpc-client', () => ({ rpcClient: { call: vi.fn() } }))
|
||||
vi.mock('../WalletScanModal.vue', () => ({ default: { props: ['show'], template: '<div />' } }))
|
||||
vi.mock('../ReceiveBitcoinModal.vue', () => ({ default: { props: ['show', 'initialMethod'], template: '<div />' } }))
|
||||
vi.mock('@/views/settings/RoutstrBudgetSection.vue', () => ({ default: { template: '<div />' } }))
|
||||
const state = () => ({ schema: 1, settings: { provider: 'auto', openai_model: '' }, claude_configured: false, openai_configured: false, local_ready: false, routstr_remaining_sats: 0 })
|
||||
@@ -18,6 +20,11 @@ describe('AI connection setup', () => {
|
||||
expect(vi.mocked(rpcClient.call).mock.calls.every(([r]) => !['assistant.budget-set', 'system.settings.set'].includes(r.method))).toBe(true)
|
||||
await button(w, 'Top up with ecash').trigger('click')
|
||||
expect(w.findComponent(ReceiveBitcoinModal).props()).toMatchObject({ show: true, initialMethod: 'ecash' })
|
||||
w.findComponent(ReceiveBitcoinModal).vm.$emit('scan'); await flushPromises()
|
||||
expect(w.findComponent(WalletScanModal).props('show')).toBe(true)
|
||||
expect(w.findComponent(ReceiveBitcoinModal).props('show')).toBe(false)
|
||||
w.findComponent(WalletScanModal).vm.$emit('close'); await flushPromises()
|
||||
expect(w.findComponent(ReceiveBitcoinModal).props('show')).toBe(true)
|
||||
w.unmount()
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user