OverviewFilesCommitsIssuesDocsReleasesPeers

keet-cli commits / eab34a4

Add file attachments to messages, file.preview route, and missing stubs
Messages now include files[] with id, name, type, size, dimensions, httpLink. File-only messages no longer dropped. Added file.preview route (getLocalFiles + search since getFileEntry is broken), plus file.subscribe/unsubscribe/path stubs to prevent Godot RPC errors. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
eab34a4140f3ca2935a2f9557d81a96cab630fa8
by plankatron <fleeky@gmail.com> · 2026-02-17T18:29:21.000Z

Changed files (2) +58 -2

lib/router.js +45 -1
……@@ -101,6 +101,10 @@ export class Router {
101101 case 'file.remove': return this._fileRemove(params)
102102 case 'file.clear': return this._fileClear(params)
103103 case 'file.fetch': return this._fileFetch(params)
104 case 'file.preview': return this._filePreview(params)
105 case 'file.subscribe': return { ok: true }
106 case 'file.unsubscribe': return { ok: true }
107 case 'file.path': return this._filePath(params)
104108
105109 // --- Advanced Members ---
106110 case 'members.active': return this._membersActive(params)
……@@ -245,6 +249,17 @@ export class Router {
245249 } else if (generic) {
246250 system = generic
247251 }
252 // Extract file attachments
253 const rawFiles = msg.message?.files || []
254 const files = Array.isArray(rawFiles) ? rawFiles.map(f => ({
255 id: f.pointer?.externalBlob?.id || null,
256 name: f.name || f.fileName || 'file',
257 type: f.mimeType || '',
258 size: f.size || 0,
259 dimensions: f.dimensions || null,
260 httpLink: f.httpLink || ''
261 })) : []
262
248263 return {
249264 memberId,
250265 name: nameMap[memberId] || memberId.slice(0, 8),
……@@ -252,10 +267,11 @@ export class Router {
252267 timestamp: msg.timestamp || null,
253268 deleted: msg.deleted || false,
254269 system,
270 files: files.length > 0 ? files : null,
255271 seq: msg.seq ?? msg.clock ?? null,
256272 id: msg.id || null
257273 }
258 }).filter(m => m.text || m.system)
274 }).filter(m => m.text || m.system || m.files)
259275 }
260276
261277 async _getMemberNames (roomId) {
……@@ -745,6 +761,34 @@ export class Router {
745761 return { base64: buf.toString('base64'), contentType, size: buf.length }
746762 }
747763
764 async _filePath (params) {
765 if (!params.roomId) throw new Error('Missing required param: roomId')
766 if (!params.fileId) throw new Error('Missing required param: fileId')
767 const result = await this.backend.api.core.getFileEntry(params.roomId, params.fileId)
768 return result || {}
769 }
770
771 async _filePreview (params) {
772 if (!params.roomId) throw new Error('Missing required param: roomId')
773 if (!params.fileId) throw new Error('Missing required param: fileId')
774 // getFileEntry is broken — use getLocalFiles + search
775 const files = await this.backend.api.core.getLocalFiles(params.roomId)
776 const entries = Array.isArray(files) ? files : (files?.data || files?.entries || [])
777 const entry = entries.find(f => {
778 const id = f.id || f.fileId || f.pointer?.externalBlob?.id
779 return id === params.fileId
780 })
781 if (!entry) throw new Error('File not found: ' + params.fileId)
782 return {
783 name: entry.fileName || entry.name || 'file',
784 type: entry.mimeType || entry.type || '',
785 size: entry.size || 0,
786 httpLink: entry.httpLink || '',
787 fullHttpLink: entry.httpLink || '',
788 dimensions: entry.dimensions || null
789 }
790 }
791
748792 // --- Advanced Members ---
749793
750794 async _membersActive (params) {
lib/uds-transport.js +13 -1
……@@ -252,7 +252,18 @@ function normalizeEvent (event, nameMap) {
252252 system = generic
253253 }
254254
255 if (!text && !system) return null
255 // Extract file attachments
256 const rawFiles = event.message?.files || []
257 const files = Array.isArray(rawFiles) ? rawFiles.map(f => ({
258 id: f.pointer?.externalBlob?.id || null,
259 name: f.name || f.fileName || 'file',
260 type: f.mimeType || '',
261 size: f.size || 0,
262 dimensions: f.dimensions || null,
263 httpLink: f.httpLink || ''
264 })) : []
265
266 if (!text && !system && files.length === 0) return null
256267
257268 const memberId = event.memberId || 'unknown'
258269
……@@ -263,6 +274,7 @@ function normalizeEvent (event, nameMap) {
263274 timestamp: event.timestamp || Date.now(),
264275 deleted: event.deleted || false,
265276 system,
277 files: files.length > 0 ? files : null,
266278 seq: event.seq ?? event.clock ?? null,
267279 id: event.id || null
268280 }