feat: update server search augmentations and increment version to 0.7.6

This commit is contained in:
David Snelling 2025-06-06 10:49:29 -07:00
parent a206b9926d
commit 099b192071
2 changed files with 80 additions and 80 deletions

View file

@ -1,6 +1,6 @@
/** /**
* Server Search Augmentations * Server Search Augmentations
* *
* This file implements conduit and activation augmentations for browser-server search functionality. * This file implements conduit and activation augmentations for browser-server search functionality.
* It allows Brainy to search a server-hosted instance and store results locally. * It allows Brainy to search a server-hosted instance and store results locally.
*/ */
@ -19,18 +19,18 @@ import { BrainyData } from '../brainyData.js'
/** /**
* ServerSearchConduitAugmentation * ServerSearchConduitAugmentation
* *
* A specialized conduit augmentation that provides functionality for searching * A specialized conduit augmentation that provides functionality for searching
* a server-hosted Brainy instance and storing results locally. * a server-hosted Brainy instance and storing results locally.
*/ */
export class ServerSearchConduitAugmentation extends WebSocketConduitAugmentation { export class ServerSearchConduitAugmentation extends WebSocketConduitAugmentation {
private localDb: BrainyData | null = null private localDb: BrainyData | null = null
constructor(name: string = 'server-search-conduit') { constructor(name: string = 'server-search-conduit') {
super(name) super(name)
this.description = 'Conduit augmentation for server-hosted Brainy search' // this.description = 'Conduit augmentation for server-hosted Brainy search'
} }
/** /**
* Initialize the augmentation * Initialize the augmentation
*/ */
@ -38,24 +38,24 @@ export class ServerSearchConduitAugmentation extends WebSocketConduitAugmentatio
if (this.isInitialized) { if (this.isInitialized) {
return return
} }
try { try {
// Initialize the base conduit // Initialize the base conduit
await super.initialize() await super.initialize()
// Initialize local Brainy instance if not provided // Initialize local Brainy instance if not provided
if (!this.localDb) { if (!this.localDb) {
this.localDb = new BrainyData() this.localDb = new BrainyData()
await this.localDb.init() await this.localDb.init()
} }
this.isInitialized = true this.isInitialized = true
} catch (error) { } catch (error) {
console.error(`Failed to initialize ${this.name}:`, error) console.error(`Failed to initialize ${this.name}:`, error)
throw new Error(`Failed to initialize ${this.name}: ${error}`) throw new Error(`Failed to initialize ${this.name}: ${error}`)
} }
} }
/** /**
* Set the local Brainy instance * Set the local Brainy instance
* @param db The Brainy instance to use for local storage * @param db The Brainy instance to use for local storage
@ -63,7 +63,7 @@ export class ServerSearchConduitAugmentation extends WebSocketConduitAugmentatio
setLocalDb(db: BrainyData): void { setLocalDb(db: BrainyData): void {
this.localDb = db this.localDb = db
} }
/** /**
* Get the local Brainy instance * Get the local Brainy instance
* @returns The local Brainy instance * @returns The local Brainy instance
@ -71,7 +71,7 @@ export class ServerSearchConduitAugmentation extends WebSocketConduitAugmentatio
getLocalDb(): BrainyData | null { getLocalDb(): BrainyData | null {
return this.localDb return this.localDb
} }
/** /**
* Search the server-hosted Brainy instance and store results locally * Search the server-hosted Brainy instance and store results locally
* @param connectionId The ID of the established connection * @param connectionId The ID of the established connection
@ -85,7 +85,7 @@ export class ServerSearchConduitAugmentation extends WebSocketConduitAugmentatio
limit: number = 10 limit: number = 10
): Promise<AugmentationResponse<unknown>> { ): Promise<AugmentationResponse<unknown>> {
await this.ensureInitialized() await this.ensureInitialized()
try { try {
// Create a search request // Create a search request
const readResult = await this.readData({ const readResult = await this.readData({
@ -96,23 +96,23 @@ export class ServerSearchConduitAugmentation extends WebSocketConduitAugmentatio
limit limit
} }
}) })
if (readResult.success && readResult.data) { if (readResult.success && readResult.data) {
const searchResults = readResult.data as any[] const searchResults = readResult.data as any[]
// Store the results in the local Brainy instance // Store the results in the local Brainy instance
if (this.localDb) { if (this.localDb) {
for (const result of searchResults) { for (const result of searchResults) {
// Check if the noun already exists in the local database // Check if the noun already exists in the local database
const existingNoun = await this.localDb.get(result.id) const existingNoun = await this.localDb.get(result.id)
if (!existingNoun) { if (!existingNoun) {
// Add the noun to the local database // Add the noun to the local database
await this.localDb.add(result.vector, result.metadata) await this.localDb.add(result.vector, result.metadata)
} }
} }
} }
return { return {
success: true, success: true,
data: searchResults data: searchResults
@ -133,7 +133,7 @@ export class ServerSearchConduitAugmentation extends WebSocketConduitAugmentatio
} }
} }
} }
/** /**
* Search the local Brainy instance * Search the local Brainy instance
* @param query The search query * @param query The search query
@ -145,7 +145,7 @@ export class ServerSearchConduitAugmentation extends WebSocketConduitAugmentatio
limit: number = 10 limit: number = 10
): Promise<AugmentationResponse<unknown>> { ): Promise<AugmentationResponse<unknown>> {
await this.ensureInitialized() await this.ensureInitialized()
try { try {
if (!this.localDb) { if (!this.localDb) {
return { return {
@ -154,9 +154,9 @@ export class ServerSearchConduitAugmentation extends WebSocketConduitAugmentatio
error: 'Local database not initialized' error: 'Local database not initialized'
} }
} }
const results = await this.localDb.searchText(query, limit) const results = await this.localDb.searchText(query, limit)
return { return {
success: true, success: true,
data: results data: results
@ -170,7 +170,7 @@ export class ServerSearchConduitAugmentation extends WebSocketConduitAugmentatio
} }
} }
} }
/** /**
* Search both server and local instances, combine results, and store server results locally * Search both server and local instances, combine results, and store server results locally
* @param connectionId The ID of the established connection * @param connectionId The ID of the established connection
@ -184,46 +184,46 @@ export class ServerSearchConduitAugmentation extends WebSocketConduitAugmentatio
limit: number = 10 limit: number = 10
): Promise<AugmentationResponse<unknown>> { ): Promise<AugmentationResponse<unknown>> {
await this.ensureInitialized() await this.ensureInitialized()
try { try {
// Search local first // Search local first
const localSearchResult = await this.searchLocal(query, limit) const localSearchResult = await this.searchLocal(query, limit)
if (!localSearchResult.success) { if (!localSearchResult.success) {
return localSearchResult return localSearchResult
} }
const localResults = localSearchResult.data as any[] const localResults = localSearchResult.data as any[]
// If we have enough local results, return them // If we have enough local results, return them
if (localResults.length >= limit) { if (localResults.length >= limit) {
return localSearchResult return localSearchResult
} }
// Otherwise, search server for additional results // Otherwise, search server for additional results
const serverSearchResult = await this.searchServer( const serverSearchResult = await this.searchServer(
connectionId, connectionId,
query, query,
limit - localResults.length limit - localResults.length
) )
if (!serverSearchResult.success) { if (!serverSearchResult.success) {
// If server search fails, return local results // If server search fails, return local results
return localSearchResult return localSearchResult
} }
const serverResults = serverSearchResult.data as any[] const serverResults = serverSearchResult.data as any[]
// Combine results, removing duplicates // Combine results, removing duplicates
const combinedResults = [...localResults] const combinedResults = [...localResults]
const localIds = new Set(localResults.map(r => r.id)) const localIds = new Set(localResults.map(r => r.id))
for (const result of serverResults) { for (const result of serverResults) {
if (!localIds.has(result.id)) { if (!localIds.has(result.id)) {
combinedResults.push(result) combinedResults.push(result)
} }
} }
return { return {
success: true, success: true,
data: combinedResults data: combinedResults
@ -237,7 +237,7 @@ export class ServerSearchConduitAugmentation extends WebSocketConduitAugmentatio
} }
} }
} }
/** /**
* Add data to both local and server instances * Add data to both local and server instances
* @param connectionId The ID of the established connection * @param connectionId The ID of the established connection
@ -251,7 +251,7 @@ export class ServerSearchConduitAugmentation extends WebSocketConduitAugmentatio
metadata: any = {} metadata: any = {}
): Promise<AugmentationResponse<string>> { ): Promise<AugmentationResponse<string>> {
await this.ensureInitialized() await this.ensureInitialized()
try { try {
if (!this.localDb) { if (!this.localDb) {
return { return {
@ -260,13 +260,13 @@ export class ServerSearchConduitAugmentation extends WebSocketConduitAugmentatio
error: 'Local database not initialized' error: 'Local database not initialized'
} }
} }
// Add to local first // Add to local first
const id = await this.localDb.add(data, metadata) const id = await this.localDb.add(data, metadata)
// Get the vector and metadata // Get the vector and metadata
const noun = await this.localDb.get(id) const noun = await this.localDb.get(id)
if (!noun) { if (!noun) {
return { return {
success: false, success: false,
@ -274,7 +274,7 @@ export class ServerSearchConduitAugmentation extends WebSocketConduitAugmentatio
error: 'Failed to retrieve newly created noun' error: 'Failed to retrieve newly created noun'
} }
} }
// Add to server // Add to server
const writeResult = await this.writeData({ const writeResult = await this.writeData({
connectionId, connectionId,
@ -284,7 +284,7 @@ export class ServerSearchConduitAugmentation extends WebSocketConduitAugmentatio
metadata: noun.metadata metadata: noun.metadata
} }
}) })
if (!writeResult.success) { if (!writeResult.success) {
return { return {
success: true, success: true,
@ -292,7 +292,7 @@ export class ServerSearchConduitAugmentation extends WebSocketConduitAugmentatio
error: `Added locally but failed to add to server: ${writeResult.error}` error: `Added locally but failed to add to server: ${writeResult.error}`
} }
} }
return { return {
success: true, success: true,
data: id data: id
@ -310,7 +310,7 @@ export class ServerSearchConduitAugmentation extends WebSocketConduitAugmentatio
/** /**
* ServerSearchActivationAugmentation * ServerSearchActivationAugmentation
* *
* An activation augmentation that provides actions for server search functionality. * An activation augmentation that provides actions for server search functionality.
*/ */
export class ServerSearchActivationAugmentation implements IActivationAugmentation { export class ServerSearchActivationAugmentation implements IActivationAugmentation {
@ -320,16 +320,16 @@ export class ServerSearchActivationAugmentation implements IActivationAugmentati
private isInitialized = false private isInitialized = false
private conduitAugmentation: ServerSearchConduitAugmentation | null = null private conduitAugmentation: ServerSearchConduitAugmentation | null = null
private connections: Map<string, WebSocketConnection> = new Map() private connections: Map<string, WebSocketConnection> = new Map()
constructor(name: string = 'server-search-activation') { constructor(name: string = 'server-search-activation') {
this.name = name this.name = name
this.description = 'Activation augmentation for server-hosted Brainy search' this.description = 'Activation augmentation for server-hosted Brainy search'
} }
getType(): AugmentationType { getType(): AugmentationType {
return AugmentationType.ACTIVATION return AugmentationType.ACTIVATION
} }
/** /**
* Initialize the augmentation * Initialize the augmentation
*/ */
@ -337,24 +337,24 @@ export class ServerSearchActivationAugmentation implements IActivationAugmentati
if (this.isInitialized) { if (this.isInitialized) {
return return
} }
this.isInitialized = true this.isInitialized = true
} }
/** /**
* Shut down the augmentation * Shut down the augmentation
*/ */
async shutDown(): Promise<void> { async shutDown(): Promise<void> {
this.isInitialized = false this.isInitialized = false
} }
/** /**
* Get the status of the augmentation * Get the status of the augmentation
*/ */
async getStatus(): Promise<'active' | 'inactive' | 'error'> { async getStatus(): Promise<'active' | 'inactive' | 'error'> {
return this.isInitialized ? 'active' : 'inactive' return this.isInitialized ? 'active' : 'inactive'
} }
/** /**
* Set the conduit augmentation to use for server search * Set the conduit augmentation to use for server search
* @param conduit The ServerSearchConduitAugmentation to use * @param conduit The ServerSearchConduitAugmentation to use
@ -362,7 +362,7 @@ export class ServerSearchActivationAugmentation implements IActivationAugmentati
setConduitAugmentation(conduit: ServerSearchConduitAugmentation): void { setConduitAugmentation(conduit: ServerSearchConduitAugmentation): void {
this.conduitAugmentation = conduit this.conduitAugmentation = conduit
} }
/** /**
* Store a connection for later use * Store a connection for later use
* @param connectionId The ID to use for the connection * @param connectionId The ID to use for the connection
@ -371,7 +371,7 @@ export class ServerSearchActivationAugmentation implements IActivationAugmentati
storeConnection(connectionId: string, connection: WebSocketConnection): void { storeConnection(connectionId: string, connection: WebSocketConnection): void {
this.connections.set(connectionId, connection) this.connections.set(connectionId, connection)
} }
/** /**
* Get a stored connection * Get a stored connection
* @param connectionId The ID of the connection to retrieve * @param connectionId The ID of the connection to retrieve
@ -380,7 +380,7 @@ export class ServerSearchActivationAugmentation implements IActivationAugmentati
getConnection(connectionId: string): WebSocketConnection | undefined { getConnection(connectionId: string): WebSocketConnection | undefined {
return this.connections.get(connectionId) return this.connections.get(connectionId)
} }
/** /**
* Trigger an action based on a processed command or internal state * Trigger an action based on a processed command or internal state
* @param actionName The name of the action to trigger * @param actionName The name of the action to trigger
@ -397,7 +397,7 @@ export class ServerSearchActivationAugmentation implements IActivationAugmentati
error: 'Conduit augmentation not set' error: 'Conduit augmentation not set'
} }
} }
// Handle different actions // Handle different actions
switch (actionName) { switch (actionName) {
case 'connectToServer': case 'connectToServer':
@ -418,7 +418,7 @@ export class ServerSearchActivationAugmentation implements IActivationAugmentati
} }
} }
} }
/** /**
* Handle the connectToServer action * Handle the connectToServer action
* @param parameters Action parameters * @param parameters Action parameters
@ -428,7 +428,7 @@ export class ServerSearchActivationAugmentation implements IActivationAugmentati
): AugmentationResponse<unknown> { ): AugmentationResponse<unknown> {
const serverUrl = parameters.serverUrl as string const serverUrl = parameters.serverUrl as string
const protocols = parameters.protocols as string | string[] | undefined const protocols = parameters.protocols as string | string[] | undefined
if (!serverUrl) { if (!serverUrl) {
return { return {
success: false, success: false,
@ -436,7 +436,7 @@ export class ServerSearchActivationAugmentation implements IActivationAugmentati
error: 'serverUrl parameter is required' error: 'serverUrl parameter is required'
} }
} }
// Return a promise that will be resolved when the connection is established // Return a promise that will be resolved when the connection is established
return { return {
success: true, success: true,
@ -445,7 +445,7 @@ export class ServerSearchActivationAugmentation implements IActivationAugmentati
}) })
} }
} }
/** /**
* Handle the searchServer action * Handle the searchServer action
* @param parameters Action parameters * @param parameters Action parameters
@ -456,7 +456,7 @@ export class ServerSearchActivationAugmentation implements IActivationAugmentati
const connectionId = parameters.connectionId as string const connectionId = parameters.connectionId as string
const query = parameters.query as string const query = parameters.query as string
const limit = parameters.limit as number || 10 const limit = parameters.limit as number || 10
if (!connectionId) { if (!connectionId) {
return { return {
success: false, success: false,
@ -464,7 +464,7 @@ export class ServerSearchActivationAugmentation implements IActivationAugmentati
error: 'connectionId parameter is required' error: 'connectionId parameter is required'
} }
} }
if (!query) { if (!query) {
return { return {
success: false, success: false,
@ -472,14 +472,14 @@ export class ServerSearchActivationAugmentation implements IActivationAugmentati
error: 'query parameter is required' error: 'query parameter is required'
} }
} }
// Return a promise that will be resolved when the search is complete // Return a promise that will be resolved when the search is complete
return { return {
success: true, success: true,
data: this.conduitAugmentation!.searchServer(connectionId, query, limit) data: this.conduitAugmentation!.searchServer(connectionId, query, limit)
} }
} }
/** /**
* Handle the searchLocal action * Handle the searchLocal action
* @param parameters Action parameters * @param parameters Action parameters
@ -489,7 +489,7 @@ export class ServerSearchActivationAugmentation implements IActivationAugmentati
): AugmentationResponse<unknown> { ): AugmentationResponse<unknown> {
const query = parameters.query as string const query = parameters.query as string
const limit = parameters.limit as number || 10 const limit = parameters.limit as number || 10
if (!query) { if (!query) {
return { return {
success: false, success: false,
@ -497,14 +497,14 @@ export class ServerSearchActivationAugmentation implements IActivationAugmentati
error: 'query parameter is required' error: 'query parameter is required'
} }
} }
// Return a promise that will be resolved when the search is complete // Return a promise that will be resolved when the search is complete
return { return {
success: true, success: true,
data: this.conduitAugmentation!.searchLocal(query, limit) data: this.conduitAugmentation!.searchLocal(query, limit)
} }
} }
/** /**
* Handle the searchCombined action * Handle the searchCombined action
* @param parameters Action parameters * @param parameters Action parameters
@ -515,7 +515,7 @@ export class ServerSearchActivationAugmentation implements IActivationAugmentati
const connectionId = parameters.connectionId as string const connectionId = parameters.connectionId as string
const query = parameters.query as string const query = parameters.query as string
const limit = parameters.limit as number || 10 const limit = parameters.limit as number || 10
if (!connectionId) { if (!connectionId) {
return { return {
success: false, success: false,
@ -523,7 +523,7 @@ export class ServerSearchActivationAugmentation implements IActivationAugmentati
error: 'connectionId parameter is required' error: 'connectionId parameter is required'
} }
} }
if (!query) { if (!query) {
return { return {
success: false, success: false,
@ -531,14 +531,14 @@ export class ServerSearchActivationAugmentation implements IActivationAugmentati
error: 'query parameter is required' error: 'query parameter is required'
} }
} }
// Return a promise that will be resolved when the search is complete // Return a promise that will be resolved when the search is complete
return { return {
success: true, success: true,
data: this.conduitAugmentation!.searchCombined(connectionId, query, limit) data: this.conduitAugmentation!.searchCombined(connectionId, query, limit)
} }
} }
/** /**
* Handle the addToBoth action * Handle the addToBoth action
* @param parameters Action parameters * @param parameters Action parameters
@ -549,7 +549,7 @@ export class ServerSearchActivationAugmentation implements IActivationAugmentati
const connectionId = parameters.connectionId as string const connectionId = parameters.connectionId as string
const data = parameters.data const data = parameters.data
const metadata = parameters.metadata || {} const metadata = parameters.metadata || {}
if (!connectionId) { if (!connectionId) {
return { return {
success: false, success: false,
@ -557,7 +557,7 @@ export class ServerSearchActivationAugmentation implements IActivationAugmentati
error: 'connectionId parameter is required' error: 'connectionId parameter is required'
} }
} }
if (!data) { if (!data) {
return { return {
success: false, success: false,
@ -565,14 +565,14 @@ export class ServerSearchActivationAugmentation implements IActivationAugmentati
error: 'data parameter is required' error: 'data parameter is required'
} }
} }
// Return a promise that will be resolved when the add is complete // Return a promise that will be resolved when the add is complete
return { return {
success: true, success: true,
data: this.conduitAugmentation!.addToBoth(connectionId, data as any, metadata as any) data: this.conduitAugmentation!.addToBoth(connectionId, data as any, metadata as any)
} }
} }
/** /**
* Generates an expressive output or response from Brainy * Generates an expressive output or response from Brainy
* @param knowledgeId The identifier of the knowledge to express * @param knowledgeId The identifier of the knowledge to express
@ -589,7 +589,7 @@ export class ServerSearchActivationAugmentation implements IActivationAugmentati
error: 'generateOutput is not implemented for ServerSearchActivationAugmentation' error: 'generateOutput is not implemented for ServerSearchActivationAugmentation'
} }
} }
/** /**
* Interacts with an external system or API * Interacts with an external system or API
* @param systemId The identifier of the external system * @param systemId The identifier of the external system
@ -630,34 +630,34 @@ export async function createServerSearchAugmentations(
// Create the conduit augmentation // Create the conduit augmentation
const conduit = new ServerSearchConduitAugmentation(options.conduitName) const conduit = new ServerSearchConduitAugmentation(options.conduitName)
await conduit.initialize() await conduit.initialize()
// Set the local database if provided // Set the local database if provided
if (options.localDb) { if (options.localDb) {
conduit.setLocalDb(options.localDb) conduit.setLocalDb(options.localDb)
} }
// Create the activation augmentation // Create the activation augmentation
const activation = new ServerSearchActivationAugmentation(options.activationName) const activation = new ServerSearchActivationAugmentation(options.activationName)
await activation.initialize() await activation.initialize()
// Link the augmentations // Link the augmentations
activation.setConduitAugmentation(conduit) activation.setConduitAugmentation(conduit)
// Connect to the server // Connect to the server
const connectionResult = await conduit.establishConnection( const connectionResult = await conduit.establishConnection(
serverUrl, serverUrl,
{ protocols: options.protocols } { protocols: options.protocols }
) )
if (!connectionResult.success || !connectionResult.data) { if (!connectionResult.success || !connectionResult.data) {
throw new Error(`Failed to connect to server: ${connectionResult.error}`) throw new Error(`Failed to connect to server: ${connectionResult.error}`)
} }
const connection = connectionResult.data const connection = connectionResult.data
// Store the connection in the activation augmentation // Store the connection in the activation augmentation
activation.storeConnection(connection.connectionId, connection) activation.storeConnection(connection.connectionId, connection)
return { return {
conduit, conduit,
activation, activation,

View file

@ -3,4 +3,4 @@
* Do not modify this file directly. * Do not modify this file directly.
*/ */
export const VERSION = '0.7.5'; export const VERSION = '0.7.6';