diff --git a/examples/README.md b/examples/README.md
new file mode 100644
index 00000000..087fe67c
--- /dev/null
+++ b/examples/README.md
@@ -0,0 +1,63 @@
+# Brainy Examples
+
+This directory contains examples demonstrating various features and use cases of the Brainy vector graph database.
+
+## Browser-Server Search Example
+
+The [browser-server-search](./browser-server-search/) example demonstrates how to use Brainy in a browser, call a server-hosted version for search, store the results locally, and then perform further searches against the local instance.
+
+This approach allows you to:
+- Search a server-hosted Brainy instance from a browser
+- Store the search results in a local Brainy instance
+- Perform further searches against the local instance without needing to query the server again
+- Add data to both local and server instances
+
+See the [browser-server-search README](./browser-server-search/README.md) for detailed instructions.
+
+## Other Examples
+
+### Augmentation Examples
+
+- [conduitAugmentationExample.js](./conduitAugmentationExample.js) - Demonstrates how to use conduit augmentations for syncing Brainy instances
+- [memoryAugmentationExample.js](./memoryAugmentationExample.js) - Shows how to use memory augmentations for custom storage
+
+### Pipeline Examples
+
+- [sequentialPipelineExample.js](./sequentialPipelineExample.js) - Demonstrates the sequential pipeline for processing data
+
+### Demo
+
+- [demo.html](./demo.html) - A web demo showcasing Brainy's capabilities
+
+### Configuration Examples
+
+- [configurationTest.js](./configurationTest.js) - Shows how to configure Brainy with custom options
+- [readOnlyTest.js](./readOnlyTest.js) - Demonstrates using Brainy in read-only mode
+- [buildTimeRegistration.js](./buildTimeRegistration.js) - Shows how to register augmentations at build time
+
+### Data Inspection
+
+- [dataInspectionExample.js](./dataInspectionExample.js) - Demonstrates how to inspect data stored in Brainy
+
+## Running the Examples
+
+Most JavaScript examples can be run using Node.js:
+
+```bash
+node examples/sequentialPipelineExample.js
+```
+
+For HTML examples, you can open them directly in a browser or serve them using a local HTTP server:
+
+```bash
+# Using a simple HTTP server
+npx http-server
+```
+
+Then navigate to the appropriate URL in your browser (e.g., http://localhost:8080/examples/demo.html).
+
+## Creating Your Own Examples
+
+Feel free to use these examples as a starting point for your own projects. You can copy and modify them to suit your needs.
+
+If you create an example that might be useful to others, consider contributing it back to the Brainy project!
diff --git a/examples/browser-server-search/README.md b/examples/browser-server-search/README.md
new file mode 100644
index 00000000..4427d2ba
--- /dev/null
+++ b/examples/browser-server-search/README.md
@@ -0,0 +1,187 @@
+# Brainy Browser-Server Search Example
+
+This example demonstrates how to use Brainy in a browser, call a server-hosted version for search, store the results locally, and then perform further searches against the local instance.
+
+## Overview
+
+The solution consists of:
+
+1. A `BrainyServerSearch` class that handles the connection to the server and local storage
+2. An HTML interface for testing the functionality
+3. Server-side setup using the Brainy cloud wrapper
+
+This approach allows you to:
+- Search a server-hosted Brainy instance from a browser
+- Store the search results in a local Brainy instance
+- Perform further searches against the local instance without needing to query the server again
+- Add data to both local and server instances
+
+## How It Works
+
+1. The browser creates a local Brainy instance
+2. It connects to the server-hosted Brainy instance using WebSocket
+3. When a search is performed:
+ - The query is sent to the server
+ - The server returns the search results
+ - The results are stored in the local Brainy instance
+ - The results are displayed to the user
+4. Subsequent searches can be performed against the local instance
+5. A combined search mode first checks the local instance and then queries the server only if needed
+
+## Setup Instructions
+
+### Server Setup
+
+1. Set up the Brainy cloud wrapper:
+
+```bash
+# Clone the repository if you haven't already
+git clone https://github.com/soulcraft/brainy.git
+cd brainy/cloud-wrapper
+
+# Install dependencies
+npm install --legacy-peer-deps
+
+# Configure the server
+cp .env.example .env
+# Edit .env to configure your environment
+
+# Build and start the server
+npm run build
+npm run start
+```
+
+2. Note the WebSocket URL of your server (e.g., `wss://your-server.com/ws` or `ws://localhost:3000/ws` for local development)
+
+### Client Setup
+
+1. Copy the example files to your project:
+
+```bash
+cp -r examples/browser-server-search your-project/
+```
+
+2. Include the Brainy library in your project:
+
+```bash
+npm install @soulcraft/brainy --legacy-peer-deps
+```
+
+3. Open the HTML file in a browser or serve it using a local server:
+
+```bash
+# Using a simple HTTP server
+cd your-project
+npx http-server
+```
+
+4. Navigate to http://localhost:8080/browser-server-search/ in your browser
+
+5. Enter the WebSocket URL of your server and start using the example
+
+## Usage
+
+### Using the HTML Interface
+
+1. Enter the WebSocket URL of your Brainy server
+2. Click "Connect" to establish a connection
+3. Enter a search query and click one of the search buttons:
+ - "Search Server" - Search the server and store results locally
+ - "Search Local" - Search only the local instance
+ - "Search Combined" - Search local first, then server if needed
+4. To add data, enter text in the "Add Data" field and click "Add to Both"
+
+### Using the BrainyServerSearch Class in Your Code
+
+```javascript
+import { BrainyServerSearch } from './index.js';
+
+// Create a new instance
+const brainySearch = new BrainyServerSearch('wss://your-brainy-server.com/ws');
+
+// Initialize and connect
+await brainySearch.init();
+
+// Search the server and store results locally
+const serverResults = await brainySearch.searchServer('machine learning', 5);
+
+// Search the local instance
+const localResults = await brainySearch.searchLocal('machine learning', 5);
+
+// Perform a combined search
+const combinedResults = await brainySearch.searchCombined('neural networks', 5);
+
+// Add data to both local and server
+const id = await brainySearch.add('Deep learning is a subset of machine learning', {
+ noun: 'Concept',
+ category: 'AI',
+ tags: ['deep learning', 'neural networks']
+});
+
+// Close the connection when done
+await brainySearch.close();
+```
+
+## API Reference
+
+### BrainyServerSearch Class
+
+#### Constructor
+
+```javascript
+const brainySearch = new BrainyServerSearch(serverUrl);
+```
+
+- `serverUrl` (string): WebSocket URL of the Brainy server
+
+#### Methods
+
+- `init()`: Initialize the local Brainy instance and connect to the server
+- `searchServer(query, limit = 10)`: Search the server-hosted Brainy instance, store results locally, and return them
+- `searchLocal(query, limit = 10)`: Search the local Brainy instance
+- `searchCombined(query, limit = 10)`: Search both server and local instances, combine results, and store server results locally
+- `add(data, metadata = {})`: Add data to both local and server instances
+- `close()`: Close the connection to the server
+
+## Advanced Configuration
+
+### Custom Embedding Function
+
+You can customize the embedding function used by the local Brainy instance:
+
+```javascript
+import { createSimpleEmbeddingFunction } from '@soulcraft/brainy';
+
+// In your code, before calling init():
+brainySearch.setEmbeddingFunction(createSimpleEmbeddingFunction());
+```
+
+### Persistent Storage
+
+To enable persistent storage for the local Brainy instance:
+
+```javascript
+// In your code, before calling init():
+brainySearch.setStorageOptions({
+ requestPersistentStorage: true
+});
+```
+
+## Troubleshooting
+
+### Connection Issues
+
+- Ensure the server is running and accessible
+- Check that the WebSocket URL is correct
+- Verify that your browser supports WebSockets
+- Check for CORS issues if the server is on a different domain
+
+### Search Issues
+
+- Ensure the server has data to search
+- Check that the query is not empty
+- Verify that the server is properly configured for search
+
+## License
+
+MIT
diff --git a/examples/browser-server-search/index.html b/examples/browser-server-search/index.html
new file mode 100644
index 00000000..59f2ee4f
--- /dev/null
+++ b/examples/browser-server-search/index.html
@@ -0,0 +1,251 @@
+
+
+
+ This example demonstrates how to use Brainy in a browser, call a server-hosted version for search,
+ store the results locally, and then perform further searches against the local instance.
+
+
+
+
Server URL
+
+
+
+
+
+
Search
+
+
+
+
+
+
+
+
Add Data
+
+
+
+
+
+
Results
+
Connect to a server to begin...
+
+
+
+
+
+
+
+
diff --git a/examples/browser-server-search/index.js b/examples/browser-server-search/index.js
new file mode 100644
index 00000000..05ba979a
--- /dev/null
+++ b/examples/browser-server-search/index.js
@@ -0,0 +1,278 @@
+// Browser-Server Search Example
+// This example demonstrates how to use Brainy in a browser, call a server-hosted version for search,
+// store the results locally, and then perform further searches against the local instance.
+
+import {
+ BrainyData,
+ augmentationPipeline,
+ createConduitAugmentation,
+ NounType
+} from '@soulcraft/brainy';
+
+/**
+ * BrainyServerSearch class
+ * Provides functionality to search a server-hosted Brainy instance and store results locally
+ */
+class BrainyServerSearch {
+ constructor(serverUrl) {
+ this.serverUrl = serverUrl;
+ this.localDb = null;
+ this.wsConduit = null;
+ this.connection = null;
+ this.isInitialized = false;
+ }
+
+ /**
+ * Initialize the local Brainy instance and connect to the server
+ */
+ async init() {
+ if (this.isInitialized) {
+ return;
+ }
+
+ try {
+ // Initialize local Brainy instance
+ this.localDb = new BrainyData();
+ await this.localDb.init();
+
+ // Create a WebSocket conduit augmentation
+ this.wsConduit = await createConduitAugmentation('websocket', 'server-search-conduit');
+
+ // Register the augmentation with the pipeline
+ augmentationPipeline.register(this.wsConduit);
+
+ // Connect to the server
+ const connectionResult = await augmentationPipeline.executeConduitPipeline(
+ 'establishConnection',
+ [this.serverUrl, { protocols: 'brainy-sync' }]
+ );
+
+ if (connectionResult[0] && (await connectionResult[0]).success) {
+ this.connection = (await connectionResult[0]).data;
+ console.log('Connected to server:', this.serverUrl);
+ this.isInitialized = true;
+ } else {
+ throw new Error('Failed to connect to server');
+ }
+ } catch (error) {
+ console.error('Failed to initialize BrainyServerSearch:', error);
+ throw error;
+ }
+ }
+
+ /**
+ * Search the server-hosted Brainy instance, store results locally, and return them
+ * @param {string} query - The search query
+ * @param {number} limit - Maximum number of results to return
+ * @returns {Promise} - Search results
+ */
+ async searchServer(query, limit = 10) {
+ await this.ensureInitialized();
+
+ try {
+ // Create a search request
+ const readResult = await augmentationPipeline.executeConduitPipeline(
+ 'readData',
+ [{
+ connectionId: this.connection.connectionId,
+ query: {
+ type: 'search',
+ query: query,
+ limit: limit
+ }
+ }]
+ );
+
+ if (readResult[0] && (await readResult[0]).success) {
+ const searchResults = (await readResult[0]).data;
+
+ // Store the results in the local Brainy instance
+ for (const result of searchResults) {
+ // Check if the noun already exists in the local database
+ const existingNoun = await this.localDb.get(result.id);
+
+ if (!existingNoun) {
+ // Add the noun to the local database
+ await this.localDb.add(result.vector, result.metadata);
+ }
+ }
+
+ return searchResults;
+ } else {
+ const error = readResult[0] ? (await readResult[0]).error : 'Unknown error';
+ throw new Error(`Failed to search server: ${error}`);
+ }
+ } catch (error) {
+ console.error('Error searching server:', error);
+ throw error;
+ }
+ }
+
+ /**
+ * Search the local Brainy instance
+ * @param {string} query - The search query
+ * @param {number} limit - Maximum number of results to return
+ * @returns {Promise} - Search results
+ */
+ async searchLocal(query, limit = 10) {
+ await this.ensureInitialized();
+
+ try {
+ return await this.localDb.searchText(query, limit);
+ } catch (error) {
+ console.error('Error searching local database:', error);
+ throw error;
+ }
+ }
+
+ /**
+ * Search both server and local instances, combine results, and store server results locally
+ * @param {string} query - The search query
+ * @param {number} limit - Maximum number of results to return
+ * @returns {Promise} - Combined search results
+ */
+ async searchCombined(query, limit = 10) {
+ await this.ensureInitialized();
+
+ try {
+ // Search local first
+ const localResults = await this.searchLocal(query, limit);
+
+ // If we have enough local results, return them
+ if (localResults.length >= limit) {
+ return localResults;
+ }
+
+ // Otherwise, search server for additional results
+ const serverResults = await this.searchServer(query, limit - localResults.length);
+
+ // Combine results, removing duplicates
+ const combinedResults = [...localResults];
+ const localIds = new Set(localResults.map(r => r.id));
+
+ for (const result of serverResults) {
+ if (!localIds.has(result.id)) {
+ combinedResults.push(result);
+ }
+ }
+
+ return combinedResults;
+ } catch (error) {
+ console.error('Error performing combined search:', error);
+ throw error;
+ }
+ }
+
+ /**
+ * Add data to both local and server instances
+ * @param {string|Array} data - Text or vector to add
+ * @param {Object} metadata - Metadata for the data
+ * @returns {Promise} - ID of the added data
+ */
+ async add(data, metadata = {}) {
+ await this.ensureInitialized();
+
+ try {
+ // Add to local first
+ const id = await this.localDb.add(data, metadata);
+
+ // Get the vector and metadata
+ const noun = await this.localDb.get(id);
+
+ // Add to server
+ await augmentationPipeline.executeConduitPipeline(
+ 'writeData',
+ [{
+ connectionId: this.connection.connectionId,
+ data: {
+ type: 'addNoun',
+ vector: noun.vector,
+ metadata: noun.metadata
+ }
+ }]
+ );
+
+ return id;
+ } catch (error) {
+ console.error('Error adding data:', error);
+ throw error;
+ }
+ }
+
+ /**
+ * Ensure the instance is initialized
+ */
+ async ensureInitialized() {
+ if (!this.isInitialized) {
+ await this.init();
+ }
+ }
+
+ /**
+ * Close the connection to the server
+ */
+ async close() {
+ if (this.connection) {
+ try {
+ await this.wsConduit.closeWebSocket(this.connection.connectionId);
+ this.connection = null;
+ } catch (error) {
+ console.error('Error closing connection:', error);
+ }
+ }
+
+ this.isInitialized = false;
+ }
+}
+
+// Example usage
+async function runExample() {
+ // Create a BrainyServerSearch instance
+ const brainySearch = new BrainyServerSearch('wss://your-brainy-server.com/ws');
+
+ try {
+ // Initialize
+ await brainySearch.init();
+
+ // Search the server and store results locally
+ console.log('Searching server for "machine learning"...');
+ const serverResults = await brainySearch.searchServer('machine learning', 5);
+ console.log('Server results:', serverResults);
+
+ // Now search locally - this should return the results we just stored
+ console.log('Searching local database for "machine learning"...');
+ const localResults = await brainySearch.searchLocal('machine learning', 5);
+ console.log('Local results:', localResults);
+
+ // Search for something related but different
+ console.log('Searching local database for "artificial intelligence"...');
+ const aiResults = await brainySearch.searchLocal('artificial intelligence', 5);
+ console.log('AI results:', aiResults);
+
+ // Perform a combined search
+ console.log('Performing combined search for "neural networks"...');
+ const combinedResults = await brainySearch.searchCombined('neural networks', 5);
+ console.log('Combined results:', combinedResults);
+
+ // Add new data to both local and server
+ console.log('Adding new data...');
+ const id = await brainySearch.add('Deep learning is a subset of machine learning', {
+ noun: NounType.Concept,
+ category: 'AI',
+ tags: ['deep learning', 'neural networks']
+ });
+ console.log('Added data with ID:', id);
+
+ // Close the connection
+ await brainySearch.close();
+
+ } catch (error) {
+ console.error('Example failed:', error);
+ }
+}
+
+// In a browser environment, you would call this when the page loads
+// runExample();
+
+// Export for use in other modules
+export { BrainyServerSearch };
diff --git a/examples/serverSearchAugmentationExample.js b/examples/serverSearchAugmentationExample.js
new file mode 100644
index 00000000..b24d5a02
--- /dev/null
+++ b/examples/serverSearchAugmentationExample.js
@@ -0,0 +1,346 @@
+/**
+ * Server Search Augmentation Example
+ *
+ * This example demonstrates how to use the ServerSearchConduitAugmentation and
+ * ServerSearchActivationAugmentation to search a server-hosted Brainy instance,
+ * store results locally, and perform further searches against the local instance.
+ */
+
+import {
+ BrainyData,
+ augmentationPipeline,
+ AugmentationType,
+ NounType
+} from '@soulcraft/brainy'
+
+// Import the server search augmentations
+import {
+ ServerSearchConduitAugmentation,
+ ServerSearchActivationAugmentation,
+ createServerSearchAugmentations
+} from '../src/augmentations/serverSearchAugmentations.js'
+
+/**
+ * Example 1: Using the factory function
+ *
+ * This is the simplest way to use the server search augmentations.
+ * The factory function creates both augmentations, links them together,
+ * and connects to the server.
+ */
+async function example1() {
+ console.log('Example 1: Using the factory function')
+
+ try {
+ // Create the augmentations and connect to the server
+ const { conduit, activation, connection } = await createServerSearchAugmentations(
+ 'wss://your-brainy-server.com/ws',
+ { protocols: 'brainy-sync' }
+ )
+
+ // Register the augmentations with the pipeline
+ augmentationPipeline.register(conduit)
+ augmentationPipeline.register(activation)
+
+ console.log('Connected to server with connection ID:', connection.connectionId)
+
+ // Search the server and store results locally
+ console.log('Searching server for "machine learning"...')
+ const serverSearchResult = await conduit.searchServer(
+ connection.connectionId,
+ 'machine learning',
+ 5
+ )
+
+ if (serverSearchResult.success) {
+ console.log('Server search results:', serverSearchResult.data)
+ } else {
+ console.error('Server search failed:', serverSearchResult.error)
+ }
+
+ // Now search locally - this should return the results we just stored
+ console.log('Searching local database for "machine learning"...')
+ const localSearchResult = await conduit.searchLocal('machine learning', 5)
+
+ if (localSearchResult.success) {
+ console.log('Local search results:', localSearchResult.data)
+ } else {
+ console.error('Local search failed:', localSearchResult.error)
+ }
+
+ // Perform a combined search
+ console.log('Performing combined search for "neural networks"...')
+ const combinedSearchResult = await conduit.searchCombined(
+ connection.connectionId,
+ 'neural networks',
+ 5
+ )
+
+ if (combinedSearchResult.success) {
+ console.log('Combined search results:', combinedSearchResult.data)
+ } else {
+ console.error('Combined search failed:', combinedSearchResult.error)
+ }
+
+ // Add data to both local and server
+ console.log('Adding data to both local and server...')
+ const addResult = await conduit.addToBoth(
+ connection.connectionId,
+ 'Deep learning is a subset of machine learning',
+ {
+ noun: NounType.Concept,
+ category: 'AI',
+ tags: ['deep learning', 'neural networks']
+ }
+ )
+
+ if (addResult.success) {
+ console.log('Added data with ID:', addResult.data)
+ } else {
+ console.error('Failed to add data:', addResult.error)
+ }
+
+ } catch (error) {
+ console.error('Example 1 failed:', error)
+ }
+}
+
+/**
+ * Example 2: Using the activation augmentation
+ *
+ * This example demonstrates how to use the activation augmentation
+ * to trigger actions related to server search.
+ */
+async function example2() {
+ console.log('\nExample 2: Using the activation augmentation')
+
+ try {
+ // Create the augmentations and connect to the server
+ const { conduit, activation, connection } = await createServerSearchAugmentations(
+ 'wss://your-brainy-server.com/ws',
+ { protocols: 'brainy-sync' }
+ )
+
+ // Register the augmentations with the pipeline
+ augmentationPipeline.register(conduit)
+ augmentationPipeline.register(activation)
+
+ console.log('Connected to server with connection ID:', connection.connectionId)
+
+ // Use the activation augmentation to search the server
+ console.log('Using activation to search server for "machine learning"...')
+ const serverSearchAction = activation.triggerAction('searchServer', {
+ connectionId: connection.connectionId,
+ query: 'machine learning',
+ limit: 5
+ })
+
+ if (serverSearchAction.success) {
+ // The data property contains a promise that will resolve to the search results
+ const serverSearchResult = await serverSearchAction.data
+ console.log('Server search results:', serverSearchResult)
+ } else {
+ console.error('Server search action failed:', serverSearchAction.error)
+ }
+
+ // Use the activation augmentation to search locally
+ console.log('Using activation to search local database for "machine learning"...')
+ const localSearchAction = activation.triggerAction('searchLocal', {
+ query: 'machine learning',
+ limit: 5
+ })
+
+ if (localSearchAction.success) {
+ const localSearchResult = await localSearchAction.data
+ console.log('Local search results:', localSearchResult)
+ } else {
+ console.error('Local search action failed:', localSearchAction.error)
+ }
+
+ // Use the activation augmentation to perform a combined search
+ console.log('Using activation to perform combined search for "neural networks"...')
+ const combinedSearchAction = activation.triggerAction('searchCombined', {
+ connectionId: connection.connectionId,
+ query: 'neural networks',
+ limit: 5
+ })
+
+ if (combinedSearchAction.success) {
+ const combinedSearchResult = await combinedSearchAction.data
+ console.log('Combined search results:', combinedSearchResult)
+ } else {
+ console.error('Combined search action failed:', combinedSearchAction.error)
+ }
+
+ // Use the activation augmentation to add data to both local and server
+ console.log('Using activation to add data to both local and server...')
+ const addAction = activation.triggerAction('addToBoth', {
+ connectionId: connection.connectionId,
+ data: 'Deep learning is a subset of machine learning',
+ metadata: {
+ noun: NounType.Concept,
+ category: 'AI',
+ tags: ['deep learning', 'neural networks']
+ }
+ })
+
+ if (addAction.success) {
+ const addResult = await addAction.data
+ console.log('Added data with ID:', addResult)
+ } else {
+ console.error('Add action failed:', addAction.error)
+ }
+
+ } catch (error) {
+ console.error('Example 2 failed:', error)
+ }
+}
+
+/**
+ * Example 3: Using the augmentation pipeline
+ *
+ * This example demonstrates how to use the augmentation pipeline
+ * to execute the conduit and activation augmentations.
+ */
+async function example3() {
+ console.log('\nExample 3: Using the augmentation pipeline')
+
+ try {
+ // Create the augmentations and connect to the server
+ const { conduit, activation, connection } = await createServerSearchAugmentations(
+ 'wss://your-brainy-server.com/ws',
+ { protocols: 'brainy-sync' }
+ )
+
+ // Register the augmentations with the pipeline
+ augmentationPipeline.register(conduit)
+ augmentationPipeline.register(activation)
+
+ console.log('Connected to server with connection ID:', connection.connectionId)
+
+ // Use the augmentation pipeline to search the server
+ console.log('Using pipeline to search server...')
+ const conduitResults = await augmentationPipeline.executeConduitPipeline(
+ 'searchServer',
+ [connection.connectionId, 'machine learning', 5]
+ )
+
+ if (conduitResults.length > 0 && (await conduitResults[0]).success) {
+ console.log('Server search results:', (await conduitResults[0]).data)
+ } else {
+ console.error('Server search failed')
+ }
+
+ // Use the augmentation pipeline to trigger the search action
+ console.log('Using pipeline to trigger search action...')
+ const activationResults = await augmentationPipeline.executeActivationPipeline(
+ 'triggerAction',
+ ['searchLocal', { query: 'machine learning', limit: 5 }]
+ )
+
+ if (activationResults.length > 0 && (await activationResults[0]).success) {
+ const actionResult = (await activationResults[0]).data
+ if (actionResult.success) {
+ const searchResult = await actionResult.data
+ console.log('Local search results:', searchResult)
+ }
+ } else {
+ console.error('Search action failed')
+ }
+
+ } catch (error) {
+ console.error('Example 3 failed:', error)
+ }
+}
+
+/**
+ * Example 4: Creating and using the augmentations manually
+ *
+ * This example demonstrates how to create and use the augmentations
+ * without using the factory function.
+ */
+async function example4() {
+ console.log('\nExample 4: Creating and using the augmentations manually')
+
+ try {
+ // Create a local Brainy instance
+ const localDb = new BrainyData()
+ await localDb.init()
+
+ // Create the conduit augmentation
+ const conduit = new ServerSearchConduitAugmentation('manual-server-search-conduit')
+ conduit.setLocalDb(localDb)
+ await conduit.initialize()
+
+ // Create the activation augmentation
+ const activation = new ServerSearchActivationAugmentation('manual-server-search-activation')
+ activation.setConduitAugmentation(conduit)
+ await activation.initialize()
+
+ // Register the augmentations with the pipeline
+ augmentationPipeline.register(conduit)
+ augmentationPipeline.register(activation)
+
+ // Connect to the server
+ console.log('Connecting to server...')
+ const connectionResult = await conduit.establishConnection(
+ 'wss://your-brainy-server.com/ws',
+ { protocols: 'brainy-sync' }
+ )
+
+ if (!connectionResult.success || !connectionResult.data) {
+ throw new Error(`Failed to connect to server: ${connectionResult.error}`)
+ }
+
+ const connection = connectionResult.data
+ console.log('Connected to server with connection ID:', connection.connectionId)
+
+ // Store the connection in the activation augmentation
+ activation.storeConnection(connection.connectionId, connection)
+
+ // Search the server
+ console.log('Searching server for "machine learning"...')
+ const serverSearchResult = await conduit.searchServer(
+ connection.connectionId,
+ 'machine learning',
+ 5
+ )
+
+ if (serverSearchResult.success) {
+ console.log('Server search results:', serverSearchResult.data)
+ } else {
+ console.error('Server search failed:', serverSearchResult.error)
+ }
+
+ } catch (error) {
+ console.error('Example 4 failed:', error)
+ }
+}
+
+/**
+ * Run all examples
+ */
+async function runExamples() {
+ // Initialize the augmentation pipeline
+ await augmentationPipeline.initialize()
+
+ // Run the examples
+ await example1()
+ await example2()
+ await example3()
+ await example4()
+
+ // Shut down the augmentation pipeline
+ await augmentationPipeline.shutDown()
+}
+
+// Run the examples
+// runExamples().catch(console.error)
+
+// Export for use in other modules
+export {
+ example1,
+ example2,
+ example3,
+ example4,
+ runExamples
+}
diff --git a/src/augmentations/README.md b/src/augmentations/README.md
new file mode 100644
index 00000000..c9bb1f36
--- /dev/null
+++ b/src/augmentations/README.md
@@ -0,0 +1,230 @@
+# Brainy Augmentations
+
+This directory contains the augmentation implementations for Brainy. Augmentations are pluggable components that extend Brainy's functionality in various ways.
+
+## Available Augmentations
+
+### Conduit Augmentations
+
+Conduit augmentations provide data synchronization between Brainy instances.
+
+#### WebSocketConduitAugmentation
+
+A conduit augmentation that syncs Brainy instances using WebSockets. This is used for syncing between browsers and servers, or between servers.
+
+```javascript
+import { createConduitAugmentation, augmentationPipeline } from '@soulcraft/brainy'
+
+// Create a WebSocket conduit augmentation
+const wsConduit = await createConduitAugmentation('websocket', 'my-websocket-sync')
+
+// Register the augmentation with the pipeline
+augmentationPipeline.register(wsConduit)
+
+// Connect to another Brainy instance
+const connectionResult = await wsConduit.establishConnection(
+ 'wss://your-websocket-server.com/brainy-sync',
+ { protocols: 'brainy-sync' }
+)
+```
+
+#### WebRTCConduitAugmentation
+
+A conduit augmentation that syncs Brainy instances using WebRTC. This is used for direct peer-to-peer syncing between browsers.
+
+```javascript
+import { createConduitAugmentation, augmentationPipeline } from '@soulcraft/brainy'
+
+// Create a WebRTC conduit augmentation
+const webrtcConduit = await createConduitAugmentation('webrtc', 'my-webrtc-sync')
+
+// Register the augmentation with the pipeline
+augmentationPipeline.register(webrtcConduit)
+
+// Connect to a peer
+const connectionResult = await webrtcConduit.establishConnection(
+ 'peer-id-to-connect-to',
+ {
+ signalServerUrl: 'wss://your-signal-server.com',
+ localPeerId: 'my-peer-id',
+ iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
+ }
+)
+```
+
+#### ServerSearchConduitAugmentation
+
+A specialized conduit augmentation that provides functionality for searching a server-hosted Brainy instance and storing results locally. This allows you to:
+
+- Search a server-hosted Brainy instance from a browser
+- Store the search results in a local Brainy instance
+- Perform further searches against the local instance without needing to query the server again
+- Add data to both local and server instances
+
+```javascript
+import {
+ ServerSearchConduitAugmentation,
+ createServerSearchAugmentations,
+ augmentationPipeline
+} from '@soulcraft/brainy'
+
+// Using the factory function (recommended)
+const { conduit, activation, connection } = await createServerSearchAugmentations(
+ 'wss://your-brainy-server.com/ws',
+ { protocols: 'brainy-sync' }
+)
+
+// Register the augmentations with the pipeline
+augmentationPipeline.register(conduit)
+augmentationPipeline.register(activation)
+
+// Search the server and store results locally
+const serverSearchResult = await conduit.searchServer(
+ connection.connectionId,
+ 'your search query',
+ 5 // limit
+)
+
+// Search the local instance
+const localSearchResult = await conduit.searchLocal('your search query', 5)
+
+// Perform a combined search (local first, then server if needed)
+const combinedSearchResult = await conduit.searchCombined(
+ connection.connectionId,
+ 'your search query',
+ 5
+)
+
+// Add data to both local and server
+const addResult = await conduit.addToBoth(
+ connection.connectionId,
+ 'Text to add',
+ { /* metadata */ }
+)
+```
+
+### Activation Augmentations
+
+Activation augmentations dictate how Brainy initiates actions, responses, or data manipulations.
+
+#### ServerSearchActivationAugmentation
+
+An activation augmentation that provides actions for server search functionality. This works in conjunction with the ServerSearchConduitAugmentation to provide a complete solution for browser-server search.
+
+```javascript
+import {
+ ServerSearchActivationAugmentation,
+ createServerSearchAugmentations,
+ augmentationPipeline
+} from '@soulcraft/brainy'
+
+// Using the factory function (recommended)
+const { conduit, activation, connection } = await createServerSearchAugmentations(
+ 'wss://your-brainy-server.com/ws',
+ { protocols: 'brainy-sync' }
+)
+
+// Register the augmentations with the pipeline
+augmentationPipeline.register(conduit)
+augmentationPipeline.register(activation)
+
+// Use the activation augmentation to search the server
+const serverSearchAction = activation.triggerAction('searchServer', {
+ connectionId: connection.connectionId,
+ query: 'your search query',
+ limit: 5
+})
+
+if (serverSearchAction.success) {
+ // The data property contains a promise that will resolve to the search results
+ const serverSearchResult = await serverSearchAction.data
+ console.log('Server search results:', serverSearchResult)
+}
+
+// Other available actions:
+// - 'connectToServer': Connect to a server
+// - 'searchLocal': Search the local instance
+// - 'searchCombined': Search both local and server
+// - 'addToBoth': Add data to both local and server
+```
+
+## Using the Augmentation Pipeline
+
+The augmentation pipeline provides a way to execute augmentations based on their type.
+
+```javascript
+import { augmentationPipeline } from '@soulcraft/brainy'
+
+// Execute a conduit augmentation
+const conduitResults = await augmentationPipeline.executeConduitPipeline(
+ 'methodName',
+ [arg1, arg2, ...],
+ { /* options */ }
+)
+
+// Execute an activation augmentation
+const activationResults = await augmentationPipeline.executeActivationPipeline(
+ 'methodName',
+ [arg1, arg2, ...],
+ { /* options */ }
+)
+```
+
+## Creating Custom Augmentations
+
+To create a custom augmentation, implement one of the augmentation interfaces:
+
+- `ISenseAugmentation`: For processing raw data
+- `IConduitAugmentation`: For data synchronization
+- `ICognitionAugmentation`: For reasoning and inference
+- `IMemoryAugmentation`: For data storage
+- `IPerceptionAugmentation`: For data interpretation and visualization
+- `IDialogAugmentation`: For natural language processing
+- `IActivationAugmentation`: For triggering actions
+
+Example:
+
+```javascript
+import { AugmentationType, IActivationAugmentation } from '@soulcraft/brainy'
+
+class MyCustomActivation implements IActivationAugmentation {
+ readonly name = 'my-custom-activation'
+ readonly description = 'My custom activation augmentation'
+ enabled = true
+
+ getType(): AugmentationType {
+ return AugmentationType.ACTIVATION
+ }
+
+ async initialize(): Promise {
+ // Initialization code
+ }
+
+ async shutDown(): Promise {
+ // Cleanup code
+ }
+
+ async getStatus(): Promise<'active' | 'inactive' | 'error'> {
+ return 'active'
+ }
+
+ triggerAction(actionName: string, parameters?: Record): AugmentationResponse {
+ // Implementation
+ }
+
+ generateOutput(knowledgeId: string, format: string): AugmentationResponse> {
+ // Implementation
+ }
+
+ interactExternal(systemId: string, payload: Record): AugmentationResponse {
+ // Implementation
+ }
+}
+```
+
+## Examples
+
+For complete examples of using augmentations, see the `examples` directory:
+
+- `conduitAugmentationExample.js`: Demonstrates how to use conduit augmentations
+- `serverSearchAugmentationExample.js`: Demonstrates how to use server search augmentations
diff --git a/src/augmentations/serverSearchAugmentations.ts b/src/augmentations/serverSearchAugmentations.ts
new file mode 100644
index 00000000..53537e22
--- /dev/null
+++ b/src/augmentations/serverSearchAugmentations.ts
@@ -0,0 +1,666 @@
+/**
+ * Server Search Augmentations
+ *
+ * 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.
+ */
+
+import {
+ AugmentationType,
+ IConduitAugmentation,
+ IActivationAugmentation,
+ IWebSocketSupport,
+ AugmentationResponse,
+ WebSocketConnection
+} from '../types/augmentations.js'
+import { WebSocketConduitAugmentation } from './conduitAugmentations.js'
+import { v4 as uuidv4 } from 'uuid'
+import { BrainyData } from '../brainyData.js'
+
+/**
+ * ServerSearchConduitAugmentation
+ *
+ * A specialized conduit augmentation that provides functionality for searching
+ * a server-hosted Brainy instance and storing results locally.
+ */
+export class ServerSearchConduitAugmentation extends WebSocketConduitAugmentation {
+ private localDb: BrainyData | null = null
+
+ constructor(name: string = 'server-search-conduit') {
+ super(name)
+ this.description = 'Conduit augmentation for server-hosted Brainy search'
+ }
+
+ /**
+ * Initialize the augmentation
+ */
+ async initialize(): Promise {
+ if (this.isInitialized) {
+ return
+ }
+
+ try {
+ // Initialize the base conduit
+ await super.initialize()
+
+ // Initialize local Brainy instance if not provided
+ if (!this.localDb) {
+ this.localDb = new BrainyData()
+ await this.localDb.init()
+ }
+
+ this.isInitialized = true
+ } catch (error) {
+ console.error(`Failed to initialize ${this.name}:`, error)
+ throw new Error(`Failed to initialize ${this.name}: ${error}`)
+ }
+ }
+
+ /**
+ * Set the local Brainy instance
+ * @param db The Brainy instance to use for local storage
+ */
+ setLocalDb(db: BrainyData): void {
+ this.localDb = db
+ }
+
+ /**
+ * Get the local Brainy instance
+ * @returns The local Brainy instance
+ */
+ getLocalDb(): BrainyData | null {
+ return this.localDb
+ }
+
+ /**
+ * Search the server-hosted Brainy instance and store results locally
+ * @param connectionId The ID of the established connection
+ * @param query The search query
+ * @param limit Maximum number of results to return
+ * @returns Search results
+ */
+ async searchServer(
+ connectionId: string,
+ query: string,
+ limit: number = 10
+ ): Promise> {
+ await this.ensureInitialized()
+
+ try {
+ // Create a search request
+ const readResult = await this.readData({
+ connectionId,
+ query: {
+ type: 'search',
+ query,
+ limit
+ }
+ })
+
+ if (readResult.success && readResult.data) {
+ const searchResults = readResult.data as any[]
+
+ // Store the results in the local Brainy instance
+ if (this.localDb) {
+ for (const result of searchResults) {
+ // Check if the noun already exists in the local database
+ const existingNoun = await this.localDb.get(result.id)
+
+ if (!existingNoun) {
+ // Add the noun to the local database
+ await this.localDb.add(result.vector, result.metadata)
+ }
+ }
+ }
+
+ return {
+ success: true,
+ data: searchResults
+ }
+ } else {
+ return {
+ success: false,
+ data: null,
+ error: readResult.error || 'Unknown error searching server'
+ }
+ }
+ } catch (error) {
+ console.error('Error searching server:', error)
+ return {
+ success: false,
+ data: null,
+ error: `Error searching server: ${error}`
+ }
+ }
+ }
+
+ /**
+ * Search the local Brainy instance
+ * @param query The search query
+ * @param limit Maximum number of results to return
+ * @returns Search results
+ */
+ async searchLocal(
+ query: string,
+ limit: number = 10
+ ): Promise> {
+ await this.ensureInitialized()
+
+ try {
+ if (!this.localDb) {
+ return {
+ success: false,
+ data: null,
+ error: 'Local database not initialized'
+ }
+ }
+
+ const results = await this.localDb.searchText(query, limit)
+
+ return {
+ success: true,
+ data: results
+ }
+ } catch (error) {
+ console.error('Error searching local database:', error)
+ return {
+ success: false,
+ data: null,
+ error: `Error searching local database: ${error}`
+ }
+ }
+ }
+
+ /**
+ * Search both server and local instances, combine results, and store server results locally
+ * @param connectionId The ID of the established connection
+ * @param query The search query
+ * @param limit Maximum number of results to return
+ * @returns Combined search results
+ */
+ async searchCombined(
+ connectionId: string,
+ query: string,
+ limit: number = 10
+ ): Promise> {
+ await this.ensureInitialized()
+
+ try {
+ // Search local first
+ const localSearchResult = await this.searchLocal(query, limit)
+
+ if (!localSearchResult.success) {
+ return localSearchResult
+ }
+
+ const localResults = localSearchResult.data as any[]
+
+ // If we have enough local results, return them
+ if (localResults.length >= limit) {
+ return localSearchResult
+ }
+
+ // Otherwise, search server for additional results
+ const serverSearchResult = await this.searchServer(
+ connectionId,
+ query,
+ limit - localResults.length
+ )
+
+ if (!serverSearchResult.success) {
+ // If server search fails, return local results
+ return localSearchResult
+ }
+
+ const serverResults = serverSearchResult.data as any[]
+
+ // Combine results, removing duplicates
+ const combinedResults = [...localResults]
+ const localIds = new Set(localResults.map(r => r.id))
+
+ for (const result of serverResults) {
+ if (!localIds.has(result.id)) {
+ combinedResults.push(result)
+ }
+ }
+
+ return {
+ success: true,
+ data: combinedResults
+ }
+ } catch (error) {
+ console.error('Error performing combined search:', error)
+ return {
+ success: false,
+ data: null,
+ error: `Error performing combined search: ${error}`
+ }
+ }
+ }
+
+ /**
+ * Add data to both local and server instances
+ * @param connectionId The ID of the established connection
+ * @param data Text or vector to add
+ * @param metadata Metadata for the data
+ * @returns ID of the added data
+ */
+ async addToBoth(
+ connectionId: string,
+ data: string | any[],
+ metadata: any = {}
+ ): Promise> {
+ await this.ensureInitialized()
+
+ try {
+ if (!this.localDb) {
+ return {
+ success: false,
+ data: '',
+ error: 'Local database not initialized'
+ }
+ }
+
+ // Add to local first
+ const id = await this.localDb.add(data, metadata)
+
+ // Get the vector and metadata
+ const noun = await this.localDb.get(id)
+
+ if (!noun) {
+ return {
+ success: false,
+ data: '',
+ error: 'Failed to retrieve newly created noun'
+ }
+ }
+
+ // Add to server
+ const writeResult = await this.writeData({
+ connectionId,
+ data: {
+ type: 'addNoun',
+ vector: noun.vector,
+ metadata: noun.metadata
+ }
+ })
+
+ if (!writeResult.success) {
+ return {
+ success: true,
+ data: id,
+ error: `Added locally but failed to add to server: ${writeResult.error}`
+ }
+ }
+
+ return {
+ success: true,
+ data: id
+ }
+ } catch (error) {
+ console.error('Error adding data to both:', error)
+ return {
+ success: false,
+ data: '',
+ error: `Error adding data to both: ${error}`
+ }
+ }
+ }
+}
+
+/**
+ * ServerSearchActivationAugmentation
+ *
+ * An activation augmentation that provides actions for server search functionality.
+ */
+export class ServerSearchActivationAugmentation implements IActivationAugmentation {
+ readonly name: string
+ readonly description: string
+ enabled: boolean = true
+ private isInitialized = false
+ private conduitAugmentation: ServerSearchConduitAugmentation | null = null
+ private connections: Map = new Map()
+
+ constructor(name: string = 'server-search-activation') {
+ this.name = name
+ this.description = 'Activation augmentation for server-hosted Brainy search'
+ }
+
+ getType(): AugmentationType {
+ return AugmentationType.ACTIVATION
+ }
+
+ /**
+ * Initialize the augmentation
+ */
+ async initialize(): Promise {
+ if (this.isInitialized) {
+ return
+ }
+
+ this.isInitialized = true
+ }
+
+ /**
+ * Shut down the augmentation
+ */
+ async shutDown(): Promise {
+ this.isInitialized = false
+ }
+
+ /**
+ * Get the status of the augmentation
+ */
+ async getStatus(): Promise<'active' | 'inactive' | 'error'> {
+ return this.isInitialized ? 'active' : 'inactive'
+ }
+
+ /**
+ * Set the conduit augmentation to use for server search
+ * @param conduit The ServerSearchConduitAugmentation to use
+ */
+ setConduitAugmentation(conduit: ServerSearchConduitAugmentation): void {
+ this.conduitAugmentation = conduit
+ }
+
+ /**
+ * Store a connection for later use
+ * @param connectionId The ID to use for the connection
+ * @param connection The WebSocket connection
+ */
+ storeConnection(connectionId: string, connection: WebSocketConnection): void {
+ this.connections.set(connectionId, connection)
+ }
+
+ /**
+ * Get a stored connection
+ * @param connectionId The ID of the connection to retrieve
+ * @returns The WebSocket connection
+ */
+ getConnection(connectionId: string): WebSocketConnection | undefined {
+ return this.connections.get(connectionId)
+ }
+
+ /**
+ * Trigger an action based on a processed command or internal state
+ * @param actionName The name of the action to trigger
+ * @param parameters Optional parameters for the action
+ */
+ triggerAction(
+ actionName: string,
+ parameters?: Record
+ ): AugmentationResponse {
+ if (!this.conduitAugmentation) {
+ return {
+ success: false,
+ data: null,
+ error: 'Conduit augmentation not set'
+ }
+ }
+
+ // Handle different actions
+ switch (actionName) {
+ case 'connectToServer':
+ return this.handleConnectToServer(parameters || {})
+ case 'searchServer':
+ return this.handleSearchServer(parameters || {})
+ case 'searchLocal':
+ return this.handleSearchLocal(parameters || {})
+ case 'searchCombined':
+ return this.handleSearchCombined(parameters || {})
+ case 'addToBoth':
+ return this.handleAddToBoth(parameters || {})
+ default:
+ return {
+ success: false,
+ data: null,
+ error: `Unknown action: ${actionName}`
+ }
+ }
+ }
+
+ /**
+ * Handle the connectToServer action
+ * @param parameters Action parameters
+ */
+ private handleConnectToServer(
+ parameters: Record
+ ): AugmentationResponse {
+ const serverUrl = parameters.serverUrl as string
+ const protocols = parameters.protocols as string | string[] | undefined
+
+ if (!serverUrl) {
+ return {
+ success: false,
+ data: null,
+ error: 'serverUrl parameter is required'
+ }
+ }
+
+ // Return a promise that will be resolved when the connection is established
+ return {
+ success: true,
+ data: this.conduitAugmentation!.establishConnection(serverUrl, {
+ protocols
+ })
+ }
+ }
+
+ /**
+ * Handle the searchServer action
+ * @param parameters Action parameters
+ */
+ private handleSearchServer(
+ parameters: Record
+ ): AugmentationResponse {
+ const connectionId = parameters.connectionId as string
+ const query = parameters.query as string
+ const limit = parameters.limit as number || 10
+
+ if (!connectionId) {
+ return {
+ success: false,
+ data: null,
+ error: 'connectionId parameter is required'
+ }
+ }
+
+ if (!query) {
+ return {
+ success: false,
+ data: null,
+ error: 'query parameter is required'
+ }
+ }
+
+ // Return a promise that will be resolved when the search is complete
+ return {
+ success: true,
+ data: this.conduitAugmentation!.searchServer(connectionId, query, limit)
+ }
+ }
+
+ /**
+ * Handle the searchLocal action
+ * @param parameters Action parameters
+ */
+ private handleSearchLocal(
+ parameters: Record
+ ): AugmentationResponse {
+ const query = parameters.query as string
+ const limit = parameters.limit as number || 10
+
+ if (!query) {
+ return {
+ success: false,
+ data: null,
+ error: 'query parameter is required'
+ }
+ }
+
+ // Return a promise that will be resolved when the search is complete
+ return {
+ success: true,
+ data: this.conduitAugmentation!.searchLocal(query, limit)
+ }
+ }
+
+ /**
+ * Handle the searchCombined action
+ * @param parameters Action parameters
+ */
+ private handleSearchCombined(
+ parameters: Record
+ ): AugmentationResponse {
+ const connectionId = parameters.connectionId as string
+ const query = parameters.query as string
+ const limit = parameters.limit as number || 10
+
+ if (!connectionId) {
+ return {
+ success: false,
+ data: null,
+ error: 'connectionId parameter is required'
+ }
+ }
+
+ if (!query) {
+ return {
+ success: false,
+ data: null,
+ error: 'query parameter is required'
+ }
+ }
+
+ // Return a promise that will be resolved when the search is complete
+ return {
+ success: true,
+ data: this.conduitAugmentation!.searchCombined(connectionId, query, limit)
+ }
+ }
+
+ /**
+ * Handle the addToBoth action
+ * @param parameters Action parameters
+ */
+ private handleAddToBoth(
+ parameters: Record
+ ): AugmentationResponse {
+ const connectionId = parameters.connectionId as string
+ const data = parameters.data
+ const metadata = parameters.metadata || {}
+
+ if (!connectionId) {
+ return {
+ success: false,
+ data: null,
+ error: 'connectionId parameter is required'
+ }
+ }
+
+ if (!data) {
+ return {
+ success: false,
+ data: null,
+ error: 'data parameter is required'
+ }
+ }
+
+ // Return a promise that will be resolved when the add is complete
+ return {
+ success: true,
+ data: this.conduitAugmentation!.addToBoth(connectionId, data as any, metadata as any)
+ }
+ }
+
+ /**
+ * Generates an expressive output or response from Brainy
+ * @param knowledgeId The identifier of the knowledge to express
+ * @param format The desired output format (e.g., 'text', 'json')
+ */
+ generateOutput(
+ knowledgeId: string,
+ format: string
+ ): AugmentationResponse> {
+ // This method is not used for server search functionality
+ return {
+ success: false,
+ data: '',
+ error: 'generateOutput is not implemented for ServerSearchActivationAugmentation'
+ }
+ }
+
+ /**
+ * Interacts with an external system or API
+ * @param systemId The identifier of the external system
+ * @param payload The data to send to the external system
+ */
+ interactExternal(
+ systemId: string,
+ payload: Record
+ ): AugmentationResponse {
+ // This method is not used for server search functionality
+ return {
+ success: false,
+ data: null,
+ error: 'interactExternal is not implemented for ServerSearchActivationAugmentation'
+ }
+ }
+}
+
+/**
+ * Factory function to create server search augmentations
+ * @param serverUrl The URL of the server to connect to
+ * @param options Additional options
+ * @returns An object containing the created augmentations
+ */
+export async function createServerSearchAugmentations(
+ serverUrl: string,
+ options: {
+ conduitName?: string,
+ activationName?: string,
+ protocols?: string | string[],
+ localDb?: BrainyData
+ } = {}
+): Promise<{
+ conduit: ServerSearchConduitAugmentation,
+ activation: ServerSearchActivationAugmentation,
+ connection: WebSocketConnection
+}> {
+ // Create the conduit augmentation
+ const conduit = new ServerSearchConduitAugmentation(options.conduitName)
+ await conduit.initialize()
+
+ // Set the local database if provided
+ if (options.localDb) {
+ conduit.setLocalDb(options.localDb)
+ }
+
+ // Create the activation augmentation
+ const activation = new ServerSearchActivationAugmentation(options.activationName)
+ await activation.initialize()
+
+ // Link the augmentations
+ activation.setConduitAugmentation(conduit)
+
+ // Connect to the server
+ const connectionResult = await conduit.establishConnection(
+ serverUrl,
+ { protocols: options.protocols }
+ )
+
+ if (!connectionResult.success || !connectionResult.data) {
+ throw new Error(`Failed to connect to server: ${connectionResult.error}`)
+ }
+
+ const connection = connectionResult.data
+
+ // Store the connection in the activation augmentation
+ activation.storeConnection(connection.connectionId, connection)
+
+ return {
+ conduit,
+ activation,
+ connection
+ }
+}