feat: add AIUI node capabilities — file reading, log tailing, bitcoin/lnd deep data

Add readFileAsText() to filebrowser client, read-file and tail-logs action
handlers to context broker, bitcoin.getinfo and lnd.getinfo RPC enrichment
for context categories, and update AIUI protocol types.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-05 13:50:40 +00:00
co-authored by Claude Opus 4.6
parent 11cee9dc70
commit 1bb72dc87e
4 changed files with 261 additions and 76 deletions
+34
View File
@@ -121,6 +121,40 @@ class FileBrowserClient {
return { totalSize, folderCount, fileCount }
}
private static TEXT_EXTENSIONS = new Set([
'txt', 'md', 'json', 'csv', 'log', 'conf', 'yaml', 'yml', 'toml', 'xml',
'html', 'css', 'js', 'ts', 'py', 'sh', 'bash', 'env', 'ini', 'cfg',
'sql', 'rs', 'go', 'java', 'c', 'h', 'cpp', 'hpp', 'rb', 'php',
'dockerfile', 'makefile', 'gitignore', 'editorconfig',
])
isTextFile(path: string): boolean {
const ext = path.includes('.') ? path.split('.').pop()!.toLowerCase() : ''
const name = path.split('/').pop()?.toLowerCase() || ''
return FileBrowserClient.TEXT_EXTENSIONS.has(ext) || FileBrowserClient.TEXT_EXTENSIONS.has(name)
}
async readFileAsText(path: string, maxBytes = 102400): Promise<{ content: string; truncated: boolean; size: number }> {
if (!this.isAuthenticated) {
const ok = await this.login()
if (!ok) throw new Error('FileBrowser authentication failed')
}
if (!this.isTextFile(path)) {
throw new Error(`Cannot read binary file: ${path}`)
}
const safePath = path.startsWith('/') ? path : `/${path}`
const res = await fetch(`${this.baseUrl}/api/raw${safePath}`, {
headers: this.headers(),
})
if (!res.ok) throw new Error(`Failed to read file: ${res.status}`)
const blob = await res.blob()
const size = blob.size
const truncated = size > maxBytes
const slice = truncated ? blob.slice(0, maxBytes) : blob
const content = await slice.text()
return { content, truncated, size }
}
async rename(oldPath: string, newName: string): Promise<void> {
const safePath = oldPath.startsWith('/') ? oldPath : `/${oldPath}`
const dir = safePath.substring(0, safePath.lastIndexOf('/') + 1)