feat: expand secure assistant workflows

Harden runtime execution and add local knowledge, Smart Heartbeat, usage visibility, responsive product surfaces, and cross-platform packaging support.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
This commit is contained in:
lofyer
2026-08-02 10:04:59 +08:00
co-authored by factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
parent 6ef1795b81
commit b3fdf96962
82 changed files with 17608 additions and 825 deletions
+145 -3
View File
@@ -7,22 +7,25 @@ import {
} from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { afterEach, describe, expect, it } from 'vitest'
import { afterEach, describe, expect, it, vi } from 'vitest'
import { KnowledgeService } from './knowledge-service'
import type { EmbeddingProvider } from './types'
import { UrlImporter } from './url-importer'
const temporaryDirectories: string[] = []
const services: KnowledgeService[] = []
async function createService(
urlImporter?: UrlImporter
urlImporter?: UrlImporter,
embeddingProvider?: EmbeddingProvider
): Promise<{ directory: string; service: KnowledgeService }> {
const directory = await mkdtemp(join(tmpdir(), 'goodbuddy-knowledge-service-'))
temporaryDirectories.push(directory)
const service = new KnowledgeService({
databasePath: join(directory, 'knowledge.sqlite'),
managedRoot: join(directory, 'managed'),
urlImporter
urlImporter,
embeddingProvider
})
await service.initialize()
services.push(service)
@@ -144,4 +147,143 @@ describe('KnowledgeService', () => {
expect(snapshot.evidence.length).toBeGreaterThan(0)
await service.dispose()
})
it('indexes optional embeddings and performs vector-backed hybrid search', async () => {
const provider: EmbeddingProvider = {
provider: 'test-provider',
model: 'test-model',
embed: async (input) =>
input.map((text) =>
text.includes('orbital') || text === 'related meaning'
? [1, 0]
: [0, 1]
)
}
const { directory, service } = await createService(undefined, provider)
const sourcePath = join(directory, 'vectors.txt')
await writeFile(sourcePath, 'orbital telescope notes', 'utf8')
const library = service.createLibrary({
name: 'Vector knowledge',
storageMode: 'reference',
graphEnabled: false
})
await service.importPaths(library.id, [sourcePath])
const document = service.snapshot(library.id).documents[0]
if (!document) {
throw new Error('Indexed document missing')
}
expect(
service.database.getEmbeddingIndexState(
document.id,
provider.provider,
provider.model
)
).toMatchObject({ status: 'ready', dimensions: 2 })
const results = await service.searchHybrid(
library.id,
'related meaning'
)
expect(results[0]?.document.id).toBe(document.id)
expect(results[0]?.retrieval.channels).toContain('vector')
})
it('keeps FTS available and records diagnostics when embeddings fail', async () => {
const provider: EmbeddingProvider = {
provider: 'failing-provider',
model: 'failing-model',
embed: async () => {
throw new Error('synthetic provider outage')
}
}
const { directory, service } = await createService(undefined, provider)
const sourcePath = join(directory, 'fallback.txt')
await writeFile(sourcePath, 'lexical fallback remains searchable', 'utf8')
const library = service.createLibrary({
name: 'Fallback knowledge',
storageMode: 'reference',
graphEnabled: false
})
await service.importPaths(library.id, [sourcePath])
const document = service.snapshot(library.id).documents[0]
if (!document) {
throw new Error('Indexed document missing')
}
expect(service.search(library.id, 'fallback')).toHaveLength(1)
expect(
service.database.getEmbeddingIndexState(
document.id,
provider.provider,
provider.model
)
).toMatchObject({
status: 'error',
lastError: 'synthetic provider outage'
})
const results = await service.searchHybrid(library.id, 'fallback')
expect(results[0]?.retrieval.channels).toContain('fts')
})
it('reindexes existing documents when an embedding provider is enabled', async () => {
const { directory, service } = await createService()
const sourcePath = join(directory, 'existing.txt')
await writeFile(sourcePath, 'existing semantic content', 'utf8')
const library = service.createLibrary({
name: 'Existing knowledge',
storageMode: 'reference',
graphEnabled: false
})
await service.importPaths(library.id, [sourcePath])
const document = service.snapshot(library.id).documents[0]!
const provider: EmbeddingProvider = {
provider: 'late-provider',
model: 'late-model',
embed: async (input) => input.map(() => [0.5, 0.5])
}
await service.setEmbeddingProvider(provider)
expect(
service.database.getEmbeddingIndexState(
document.id,
provider.provider,
provider.model
)
).toMatchObject({ status: 'ready', dimensions: 2 })
})
it('embeds a hybrid query once across multiple libraries', async () => {
const embed = vi.fn<EmbeddingProvider['embed']>(
async (input) => input.map(() => [1, 0])
)
const provider: EmbeddingProvider = {
provider: 'shared-query-provider',
model: 'shared-query-model',
embed
}
const { directory, service } = await createService(undefined, provider)
const libraryIds: string[] = []
for (const index of [1, 2]) {
const sourcePath = join(directory, `library-${index}.txt`)
await writeFile(sourcePath, `shared topic ${index}`, 'utf8')
const library = service.createLibrary({
name: `Library ${index}`,
storageMode: 'reference',
graphEnabled: false
})
libraryIds.push(library.id)
await service.importPaths(library.id, [sourcePath])
}
embed.mockClear()
const results = await service.searchHybridMany(
libraryIds,
'shared topic'
)
expect(embed).toHaveBeenCalledOnce()
expect(results).toHaveLength(2)
})
})