diff --git a/.claude/plans/reflective-meandering-castle.md b/.claude/plans/reflective-meandering-castle.md index f078efd8..a2b26d37 100644 --- a/.claude/plans/reflective-meandering-castle.md +++ b/.claude/plans/reflective-meandering-castle.md @@ -84,7 +84,7 @@ After getting Claude Max OAuth working on the live server, hardening the deploy - **Change**: Add search input with `ref('')`. Filter `sortedPackageEntries` by query against `manifest.title` and `manifest.description.short`. Style like Marketplace search. - **Verify**: Type in search — only matching apps shown -### Task 15: AIUI context broker integration test +### Task 15: AIUI context broker integration test [DONE] - **Files**: `neode-ui/src/services/contextBroker.ts` - **Change**: Verify each category (apps, system, network, bitcoin, wallet, media, files, search, ai-local, notes) returns real data. Wire any that send placeholder/empty data to real store data. - **Verify**: Chat mode, ask AI about installed apps, gets real context diff --git a/neode-ui/src/services/contextBroker.ts b/neode-ui/src/services/contextBroker.ts index a3495a04..466bc957 100644 --- a/neode-ui/src/services/contextBroker.ts +++ b/neode-ui/src/services/contextBroker.ts @@ -10,6 +10,7 @@ import { useAIPermissionsStore } from '@/stores/aiPermissions' import { useAppStore } from '@/stores/app' import { useContainerStore, BUNDLED_APPS } from '@/stores/container' import { rpcClient } from '@/api/rpc-client' +import { fileBrowserClient } from '@/api/filebrowser-client' /** * Context Broker — mediates all communication between AIUI (iframe) and Archy. @@ -365,11 +366,11 @@ export class ContextBroker { for (const id of mediaAppIds) { const pkg = packages[id] - if (pkg && pkg.state === 'installed') { + if (pkg && (pkg.state === 'installed' || pkg.state === 'running' || pkg.state === 'stopped')) { libraries.push({ source: id, name: pkg.manifest?.title || id, - status: pkg.installed?.status || 'unknown', + status: pkg.state, }) } } @@ -384,13 +385,31 @@ export class ContextBroker { return { available: true, libraries } } - // T9: Files from cloud/nextcloud - private sanitizeFiles(): unknown { - return { - available: false, - folders: [], - recentFiles: [], - message: 'File browser not yet available', + // T9: Files from FileBrowser + private async sanitizeFiles(): Promise { + try { + if (!fileBrowserClient.isAuthenticated) { + const ok = await fileBrowserClient.login() + if (!ok) return { available: false, message: 'File browser authentication failed' } + } + const usage = await fileBrowserClient.getUsage() + const items = await fileBrowserClient.listDirectory('/') + const folders = items.filter(i => i.isDir).map(i => ({ name: i.name, path: i.path })) + const recentFiles = items + .filter(i => !i.isDir) + .sort((a, b) => new Date(b.modified).getTime() - new Date(a.modified).getTime()) + .slice(0, 10) + .map(i => ({ name: i.name, path: i.path, size: i.size, modified: i.modified })) + return { + available: true, + totalSize: usage.totalSize, + folderCount: usage.folderCount, + fileCount: usage.fileCount, + folders, + recentFiles, + } + } catch { + return { available: false, message: 'File browser not reachable' } } } diff --git a/neode-ui/src/views/CloudFolder.vue b/neode-ui/src/views/CloudFolder.vue index 07304c47..7b109777 100644 --- a/neode-ui/src/views/CloudFolder.vue +++ b/neode-ui/src/views/CloudFolder.vue @@ -12,11 +12,7 @@
-

{{ audioPlayer.currentName.value }}

+

{{ audioPlayer.error.value }}

+

{{ audioPlayer.currentName.value }}

@@ -168,7 +165,7 @@ import CloudToolbar from '../components/cloud/CloudToolbar.vue' import FileGrid from '../components/cloud/FileGrid.vue' import { useAudioPlayer } from '../composables/useAudioPlayer' -const { bottomPosition } = useMobileBackButton() +useMobileBackButton() const router = useRouter() const route = useRoute() const store = useAppStore()