diff --git a/src/core/pglite-engine.ts b/src/core/pglite-engine.ts index b2de9b52..50492cbc 100644 --- a/src/core/pglite-engine.ts +++ b/src/core/pglite-engine.ts @@ -861,7 +861,18 @@ export class PGLiteEngine implements BrainEngine { ORDER BY cc.chunk_index`, [slug] ); - return (rows as Record[]).map(r => rowToChunk(r, true)); + return (rows as Record[]).map(r => { + const chunk = rowToChunk(r, true); + // PGLite returns vector columns as JSON-stringified arrays. Parse to Float32Array + // so downstream code (e.g. postgres-engine.upsertChunks during migrate) can iterate. + // Mirrors the same defensive parse already in getEmbeddingsByChunkIds. + if (typeof chunk.embedding === 'string') { + try { + chunk.embedding = new Float32Array(JSON.parse(chunk.embedding)); + } catch { /* leave as-is if unparseable */ } + } + return chunk; + }); } async executeRaw>(sql: string, params?: unknown[]): Promise { diff --git a/src/core/postgres-engine.ts b/src/core/postgres-engine.ts index a22aa587..50cfce5c 100644 --- a/src/core/postgres-engine.ts +++ b/src/core/postgres-engine.ts @@ -304,7 +304,9 @@ export class PostgresEngine implements BrainEngine { for (const chunk of chunks) { const embeddingStr = chunk.embedding - ? '[' + Array.from(chunk.embedding).join(',') + ']' + ? (typeof chunk.embedding === 'string' + ? chunk.embedding + : '[' + Array.from(chunk.embedding).join(',') + ']') : null; if (embeddingStr) {