feat: add external plugin loader and examples for Brainy
Introduced `pluginLoader.ts` to enable loading and configuring augmentation plugins from external packages. Added `examples/externalPlugins.js` to demonstrate usage. Enhanced storage status reporting in `opfsStorage` and `BrainyData` with detailed storage capacity and usage methods. Updated README with an external plugin usage guide.
This commit is contained in:
parent
767c349f63
commit
b031a40b1c
11 changed files with 2220 additions and 1033 deletions
85
README.md
85
README.md
|
|
@ -577,7 +577,90 @@ This enum can be used by consumers of the library to identify the different type
|
|||
|
||||
Brainy provides an event pipeline that allows registering and executing multiple augmentations of each type. The pipeline supports different execution modes and provides a flexible way to manage augmentations.
|
||||
|
||||
#### Using the Pipeline
|
||||
#### Using External Augmentation Plugins
|
||||
|
||||
Brainy provides a plugin loader that makes it easy to load and configure augmentation plugins from external npm packages. This allows you to extend Brainy's capabilities with specialized augmentations developed by third parties or maintained in separate packages.
|
||||
|
||||
```typescript
|
||||
import {
|
||||
BrainyData,
|
||||
configureAndStartPipeline,
|
||||
createSensePluginConfig,
|
||||
createConduitPluginConfig,
|
||||
AugmentationType
|
||||
} from '@soulcraft/brainy';
|
||||
|
||||
// Create a new BrainyData instance
|
||||
const db = new BrainyData();
|
||||
await db.init();
|
||||
|
||||
// Configure and start the augmentation pipeline with external plugins
|
||||
// Note: These are example plugin names. You would need to install these packages via npm first.
|
||||
const result = await configureAndStartPipeline([
|
||||
// Sense augmentations (will be loaded first)
|
||||
createSensePluginConfig('@example/text-sense-augmentation', {
|
||||
language: 'english',
|
||||
enableNER: true
|
||||
}),
|
||||
|
||||
// Conduit augmentations for two-way synchronization
|
||||
createConduitPluginConfig('@example/websocket-conduit', {
|
||||
url: 'wss://example.com/sync',
|
||||
reconnectInterval: 5000
|
||||
}),
|
||||
|
||||
// Other augmentation types
|
||||
{
|
||||
plugin: '@example/memory-augmentation',
|
||||
config: { storageType: 'persistent' },
|
||||
type: AugmentationType.MEMORY
|
||||
}
|
||||
], {
|
||||
// Optional: Customize the loading options
|
||||
useDefaultPipeline: true, // Use the default pipeline instance
|
||||
initializeAfterLoading: true, // Initialize augmentations after loading
|
||||
augmentationOrder: [ // Custom order (Sense first, as recommended)
|
||||
AugmentationType.SENSE,
|
||||
AugmentationType.CONDUIT,
|
||||
AugmentationType.MEMORY,
|
||||
AugmentationType.COGNITION,
|
||||
AugmentationType.PERCEPTION,
|
||||
AugmentationType.DIALOG,
|
||||
AugmentationType.ACTIVATION
|
||||
]
|
||||
});
|
||||
|
||||
// Get the pipeline instance
|
||||
const { pipeline } = result;
|
||||
|
||||
// Use the pipeline to execute augmentations
|
||||
const senseResults = await pipeline.executeSensePipeline(
|
||||
'processRawData',
|
||||
['This is some example text to process', 'text']
|
||||
);
|
||||
|
||||
// Process the results and insert data into BrainyData
|
||||
for (const resultPromise of senseResults) {
|
||||
const result = await resultPromise;
|
||||
if (result.success) {
|
||||
// Insert the extracted nouns and verbs into BrainyData according to graphTypes
|
||||
for (const noun of result.data.nouns) {
|
||||
await db.add(noun, { type: 'noun' });
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The plugin loader provides several functions for working with external plugins:
|
||||
|
||||
- `loadPlugins(plugins, options)`: Loads augmentation plugins from external npm packages
|
||||
- `configureAndStartPipeline(plugins, options)`: Configures and starts the augmentation pipeline with the specified plugins
|
||||
- `createSensePluginConfig(plugin, config)`: Creates a plugin configuration for a sense augmentation
|
||||
- `createConduitPluginConfig(plugin, config)`: Creates a plugin configuration for a conduit augmentation
|
||||
|
||||
For more details, see the [externalPlugins.js](examples/externalPlugins.js) example.
|
||||
|
||||
#### Using the Pipeline Directly
|
||||
|
||||
```typescript
|
||||
import { augmentationPipeline, ExecutionMode, AugmentationType } from '@soulcraft/brainy';
|
||||
|
|
|
|||
1514
examples/demo.html
1514
examples/demo.html
File diff suppressed because it is too large
Load diff
158
examples/externalPlugins.js
Normal file
158
examples/externalPlugins.js
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
/**
|
||||
* Example: Using External Augmentation Plugins with Brainy
|
||||
*
|
||||
* This example demonstrates how to load and configure external augmentation plugins
|
||||
* with the Brainy library. It shows how to use the plugin loader to integrate
|
||||
* externally installed augmentation plugins into the Brainy system.
|
||||
*/
|
||||
|
||||
import {
|
||||
BrainyData,
|
||||
configureAndStartPipeline,
|
||||
createSensePluginConfig,
|
||||
createConduitPluginConfig,
|
||||
AugmentationType
|
||||
} from '../dist/index.js';
|
||||
|
||||
// Create a new BrainyData instance
|
||||
const db = new BrainyData();
|
||||
await db.init();
|
||||
|
||||
console.log('BrainyData initialized successfully');
|
||||
|
||||
// Configure and start the augmentation pipeline with external plugins
|
||||
// Note: These are example plugin names. You would need to install these packages via npm first.
|
||||
const result = await configureAndStartPipeline([
|
||||
// Sense augmentations (will be loaded first)
|
||||
createSensePluginConfig('@example/text-sense-augmentation', {
|
||||
language: 'english',
|
||||
enableNER: true
|
||||
}),
|
||||
createSensePluginConfig('@example/image-sense-augmentation', {
|
||||
modelSize: 'medium',
|
||||
detectObjects: true
|
||||
}),
|
||||
|
||||
// Conduit augmentations for two-way synchronization
|
||||
createConduitPluginConfig('@example/websocket-conduit', {
|
||||
url: 'wss://example.com/sync',
|
||||
reconnectInterval: 5000
|
||||
}),
|
||||
createConduitPluginConfig('@example/webrtc-conduit', {
|
||||
iceServers: [{ urls: 'stun:stun.example.com:19302' }],
|
||||
peerConfig: { reliable: true }
|
||||
}),
|
||||
|
||||
// Other augmentation types
|
||||
{
|
||||
plugin: '@example/memory-augmentation',
|
||||
config: { storageType: 'persistent' },
|
||||
type: AugmentationType.MEMORY
|
||||
}
|
||||
], {
|
||||
// Optional: Customize the loading options
|
||||
useDefaultPipeline: true, // Use the default pipeline instance
|
||||
initializeAfterLoading: true, // Initialize augmentations after loading
|
||||
augmentationOrder: [ // Custom order (Sense first, as recommended)
|
||||
AugmentationType.SENSE,
|
||||
AugmentationType.CONDUIT,
|
||||
AugmentationType.MEMORY,
|
||||
AugmentationType.COGNITION,
|
||||
AugmentationType.PERCEPTION,
|
||||
AugmentationType.DIALOG,
|
||||
AugmentationType.ACTIVATION
|
||||
]
|
||||
});
|
||||
|
||||
// Check for any errors during loading
|
||||
if (result.errors.length > 0) {
|
||||
console.error('Errors occurred while loading plugins:');
|
||||
result.errors.forEach(error => console.error(` - ${error.message}`));
|
||||
} else {
|
||||
console.log('All plugins loaded successfully');
|
||||
}
|
||||
|
||||
// Get the pipeline instance
|
||||
const { pipeline } = result;
|
||||
|
||||
// Get all loaded augmentations by type
|
||||
console.log('Loaded augmentations:');
|
||||
for (const [type, augmentations] of result.augmentations.entries()) {
|
||||
if (augmentations.length > 0) {
|
||||
console.log(`${type}: ${augmentations.map(a => a.name).join(', ')}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Example: Using a sense augmentation to process raw data
|
||||
try {
|
||||
const senseResults = await pipeline.executeSensePipeline(
|
||||
'processRawData',
|
||||
['This is some example text to process', 'text']
|
||||
);
|
||||
|
||||
// Process the results
|
||||
for (const resultPromise of senseResults) {
|
||||
const result = await resultPromise;
|
||||
if (result.success) {
|
||||
console.log('Processed data:', result.data);
|
||||
|
||||
// Insert the extracted nouns and verbs into BrainyData according to graphTypes
|
||||
for (const noun of result.data.nouns) {
|
||||
await db.add(noun, { type: 'noun' });
|
||||
}
|
||||
|
||||
for (const verb of result.data.verbs) {
|
||||
await db.add(verb, { type: 'verb' });
|
||||
}
|
||||
} else {
|
||||
console.error('Error processing data:', result.error);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error executing sense pipeline:', error);
|
||||
}
|
||||
|
||||
// Example: Using a conduit augmentation for two-way synchronization
|
||||
try {
|
||||
// Establish a connection
|
||||
const connectionResults = await pipeline.executeConduitPipeline(
|
||||
'establishConnection',
|
||||
['external-system', { apiKey: 'your-api-key' }]
|
||||
);
|
||||
|
||||
// Process the results
|
||||
for (const resultPromise of connectionResults) {
|
||||
const result = await resultPromise;
|
||||
if (result.success) {
|
||||
console.log('Connection established:', result.data);
|
||||
|
||||
// Read data from the external system
|
||||
const readResults = await pipeline.executeConduitPipeline(
|
||||
'readData',
|
||||
[{ query: 'get-latest-data' }]
|
||||
);
|
||||
|
||||
// Process the read results
|
||||
for (const readResultPromise of readResults) {
|
||||
const readResult = await readResultPromise;
|
||||
if (readResult.success) {
|
||||
console.log('Data read from external system:', readResult.data);
|
||||
|
||||
// Write data to the external system
|
||||
await pipeline.executeConduitPipeline(
|
||||
'writeData',
|
||||
[{ updatedData: 'example' }]
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.error('Error establishing connection:', result.error);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error executing conduit pipeline:', error);
|
||||
}
|
||||
|
||||
// Shut down the pipeline when done
|
||||
await pipeline.shutDown();
|
||||
console.log('Pipeline shut down successfully');
|
||||
832
package-lock.json
generated
832
package-lock.json
generated
|
|
@ -14,6 +14,7 @@
|
|||
"@tensorflow/tfjs-backend-cpu": "^4.22.0",
|
||||
"@tensorflow/tfjs-core": "^4.22.0",
|
||||
"@tensorflow/tfjs-layers": "^4.22.0",
|
||||
"firebase": "^10.8.0",
|
||||
"uuid": "^9.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
@ -648,6 +649,638 @@
|
|||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/analytics": {
|
||||
"version": "0.10.8",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.8.tgz",
|
||||
"integrity": "sha512-CVnHcS4iRJPqtIDc411+UmFldk0ShSK3OB+D0bKD8Ck5Vro6dbK5+APZpkuWpbfdL359DIQUnAaMLE+zs/PVyA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.9",
|
||||
"@firebase/installations": "0.6.9",
|
||||
"@firebase/logger": "0.4.2",
|
||||
"@firebase/util": "1.10.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/analytics-compat": {
|
||||
"version": "0.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.14.tgz",
|
||||
"integrity": "sha512-unRVY6SvRqfNFIAA/kwl4vK+lvQAL2HVcgu9zTrUtTyYDmtIt/lOuHJynBMYEgLnKm39YKBDhtqdapP2e++ASw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/analytics": "0.10.8",
|
||||
"@firebase/analytics-types": "0.8.2",
|
||||
"@firebase/component": "0.6.9",
|
||||
"@firebase/util": "1.10.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app-compat": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/analytics-types": {
|
||||
"version": "0.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.2.tgz",
|
||||
"integrity": "sha512-EnzNNLh+9/sJsimsA/FGqzakmrAUKLeJvjRHlg8df1f97NLUlFidk9600y0ZgWOp3CAxn6Hjtk+08tixlUOWyw==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@firebase/app": {
|
||||
"version": "0.10.13",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.10.13.tgz",
|
||||
"integrity": "sha512-OZiDAEK/lDB6xy/XzYAyJJkaDqmQ+BCtOEPLqFvxWKUz5JbBmej7IiiRHdtiIOD/twW7O5AxVsfaaGA/V1bNsA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.9",
|
||||
"@firebase/logger": "0.4.2",
|
||||
"@firebase/util": "1.10.0",
|
||||
"idb": "7.1.1",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/app-check": {
|
||||
"version": "0.8.8",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.8.tgz",
|
||||
"integrity": "sha512-O49RGF1xj7k6BuhxGpHmqOW5hqBIAEbt2q6POW0lIywx7emYtzPDeQI+ryQpC4zbKX646SoVZ711TN1DBLNSOQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.9",
|
||||
"@firebase/logger": "0.4.2",
|
||||
"@firebase/util": "1.10.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/app-check-compat": {
|
||||
"version": "0.3.15",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.15.tgz",
|
||||
"integrity": "sha512-zFIvIFFNqDXpOT2huorz9cwf56VT3oJYRFjSFYdSbGYEJYEaXjLJbfC79lx/zjx4Fh+yuN8pry3TtvwaevrGbg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/app-check": "0.8.8",
|
||||
"@firebase/app-check-types": "0.5.2",
|
||||
"@firebase/component": "0.6.9",
|
||||
"@firebase/logger": "0.4.2",
|
||||
"@firebase/util": "1.10.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app-compat": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/app-check-interop-types": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.2.tgz",
|
||||
"integrity": "sha512-LMs47Vinv2HBMZi49C09dJxp0QT5LwDzFaVGf/+ITHe3BlIhUiLNttkATSXplc89A2lAaeTqjgqVkiRfUGyQiQ==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@firebase/app-check-types": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.2.tgz",
|
||||
"integrity": "sha512-FSOEzTzL5bLUbD2co3Zut46iyPWML6xc4x+78TeaXMSuJap5QObfb+rVvZJtla3asN4RwU7elaQaduP+HFizDA==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@firebase/app-compat": {
|
||||
"version": "0.2.43",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.43.tgz",
|
||||
"integrity": "sha512-HM96ZyIblXjAC7TzE8wIk2QhHlSvksYkQ4Ukh1GmEenzkucSNUmUX4QvoKrqeWsLEQ8hdcojABeCV8ybVyZmeg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/app": "0.10.13",
|
||||
"@firebase/component": "0.6.9",
|
||||
"@firebase/logger": "0.4.2",
|
||||
"@firebase/util": "1.10.0",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/app-types": {
|
||||
"version": "0.9.2",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.2.tgz",
|
||||
"integrity": "sha512-oMEZ1TDlBz479lmABwWsWjzHwheQKiAgnuKxE0pz0IXCVx7/rtlkx1fQ6GfgK24WCrxDKMplZrT50Kh04iMbXQ==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@firebase/auth": {
|
||||
"version": "1.7.9",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.7.9.tgz",
|
||||
"integrity": "sha512-yLD5095kVgDw965jepMyUrIgDklD6qH/BZNHeKOgvu7pchOKNjVM+zQoOVYJIKWMWOWBq8IRNVU6NXzBbozaJg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.9",
|
||||
"@firebase/logger": "0.4.2",
|
||||
"@firebase/util": "1.10.0",
|
||||
"tslib": "^2.1.0",
|
||||
"undici": "6.19.7"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app": "0.x",
|
||||
"@react-native-async-storage/async-storage": "^1.18.1"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@react-native-async-storage/async-storage": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/auth-compat": {
|
||||
"version": "0.5.14",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.14.tgz",
|
||||
"integrity": "sha512-2eczCSqBl1KUPJacZlFpQayvpilg3dxXLy9cSMTKtQMTQSmondUtPI47P3ikH3bQAXhzKLOE+qVxJ3/IRtu9pw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/auth": "1.7.9",
|
||||
"@firebase/auth-types": "0.12.2",
|
||||
"@firebase/component": "0.6.9",
|
||||
"@firebase/util": "1.10.0",
|
||||
"tslib": "^2.1.0",
|
||||
"undici": "6.19.7"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app-compat": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/auth-interop-types": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.3.tgz",
|
||||
"integrity": "sha512-Fc9wuJGgxoxQeavybiuwgyi+0rssr76b+nHpj+eGhXFYAdudMWyfBHvFL/I5fEHniUM/UQdFzi9VXJK2iZF7FQ==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@firebase/auth-types": {
|
||||
"version": "0.12.2",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.12.2.tgz",
|
||||
"integrity": "sha512-qsEBaRMoGvHO10unlDJhaKSuPn4pyoTtlQuP1ghZfzB6rNQPuhp/N/DcFZxm9i4v0SogjCbf9reWupwIvfmH6w==",
|
||||
"license": "Apache-2.0",
|
||||
"peerDependencies": {
|
||||
"@firebase/app-types": "0.x",
|
||||
"@firebase/util": "1.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/component": {
|
||||
"version": "0.6.9",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.9.tgz",
|
||||
"integrity": "sha512-gm8EUEJE/fEac86AvHn8Z/QW8BvR56TBw3hMW0O838J/1mThYQXAIQBgUv75EqlCZfdawpWLrKt1uXvp9ciK3Q==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/util": "1.10.0",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/data-connect": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.1.0.tgz",
|
||||
"integrity": "sha512-vSe5s8dY13ilhLnfY0eYRmQsdTbH7PUFZtBbqU6JVX/j8Qp9A6G5gG6//ulbX9/1JFOF1IWNOne9c8S/DOCJaQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/auth-interop-types": "0.2.3",
|
||||
"@firebase/component": "0.6.9",
|
||||
"@firebase/logger": "0.4.2",
|
||||
"@firebase/util": "1.10.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/database": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.8.tgz",
|
||||
"integrity": "sha512-dzXALZeBI1U5TXt6619cv0+tgEhJiwlUtQ55WNZY7vGAjv7Q1QioV969iYwt1AQQ0ovHnEW0YW9TiBfefLvErg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/app-check-interop-types": "0.3.2",
|
||||
"@firebase/auth-interop-types": "0.2.3",
|
||||
"@firebase/component": "0.6.9",
|
||||
"@firebase/logger": "0.4.2",
|
||||
"@firebase/util": "1.10.0",
|
||||
"faye-websocket": "0.11.4",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/database-compat": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-1.0.8.tgz",
|
||||
"integrity": "sha512-OpeWZoPE3sGIRPBKYnW9wLad25RaWbGyk7fFQe4xnJQKRzlynWeFBSRRAoLE2Old01WXwskUiucNqUUVlFsceg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.9",
|
||||
"@firebase/database": "1.0.8",
|
||||
"@firebase/database-types": "1.0.5",
|
||||
"@firebase/logger": "0.4.2",
|
||||
"@firebase/util": "1.10.0",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/database-types": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.5.tgz",
|
||||
"integrity": "sha512-fTlqCNwFYyq/C6W7AJ5OCuq5CeZuBEsEwptnVxlNPkWCo5cTTyukzAHRSO/jaQcItz33FfYrrFk1SJofcu2AaQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/app-types": "0.9.2",
|
||||
"@firebase/util": "1.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/firestore": {
|
||||
"version": "4.7.3",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.7.3.tgz",
|
||||
"integrity": "sha512-NwVU+JPZ/3bhvNSJMCSzfcBZZg8SUGyzZ2T0EW3/bkUeefCyzMISSt/TTIfEHc8cdyXGlMqfGe3/62u9s74UEg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.9",
|
||||
"@firebase/logger": "0.4.2",
|
||||
"@firebase/util": "1.10.0",
|
||||
"@firebase/webchannel-wrapper": "1.0.1",
|
||||
"@grpc/grpc-js": "~1.9.0",
|
||||
"@grpc/proto-loader": "^0.7.8",
|
||||
"tslib": "^2.1.0",
|
||||
"undici": "6.19.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.10.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/firestore-compat": {
|
||||
"version": "0.3.38",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.38.tgz",
|
||||
"integrity": "sha512-GoS0bIMMkjpLni6StSwRJarpu2+S5m346Na7gr9YZ/BZ/W3/8iHGNr9PxC+f0rNZXqS4fGRn88pICjrZEgbkqQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.9",
|
||||
"@firebase/firestore": "4.7.3",
|
||||
"@firebase/firestore-types": "3.0.2",
|
||||
"@firebase/util": "1.10.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app-compat": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/firestore-types": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.2.tgz",
|
||||
"integrity": "sha512-wp1A+t5rI2Qc/2q7r2ZpjUXkRVPtGMd6zCLsiWurjsQpqPgFin3AhNibKcIzoF2rnToNa/XYtyWXuifjOOwDgg==",
|
||||
"license": "Apache-2.0",
|
||||
"peerDependencies": {
|
||||
"@firebase/app-types": "0.x",
|
||||
"@firebase/util": "1.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/functions": {
|
||||
"version": "0.11.8",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.11.8.tgz",
|
||||
"integrity": "sha512-Lo2rTPDn96naFIlSZKVd1yvRRqqqwiJk7cf9TZhUerwnPKgBzXy+aHE22ry+6EjCaQusUoNai6mU6p+G8QZT1g==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/app-check-interop-types": "0.3.2",
|
||||
"@firebase/auth-interop-types": "0.2.3",
|
||||
"@firebase/component": "0.6.9",
|
||||
"@firebase/messaging-interop-types": "0.2.2",
|
||||
"@firebase/util": "1.10.0",
|
||||
"tslib": "^2.1.0",
|
||||
"undici": "6.19.7"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/functions-compat": {
|
||||
"version": "0.3.14",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.14.tgz",
|
||||
"integrity": "sha512-dZ0PKOKQFnOlMfcim39XzaXonSuPPAVuzpqA4ONTIdyaJK/OnBaIEVs/+BH4faa1a2tLeR+Jy15PKqDRQoNIJw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.9",
|
||||
"@firebase/functions": "0.11.8",
|
||||
"@firebase/functions-types": "0.6.2",
|
||||
"@firebase/util": "1.10.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app-compat": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/functions-types": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.2.tgz",
|
||||
"integrity": "sha512-0KiJ9lZ28nS2iJJvimpY4nNccV21rkQyor5Iheu/nq8aKXJqtJdeSlZDspjPSBBiHRzo7/GMUttegnsEITqR+w==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@firebase/installations": {
|
||||
"version": "0.6.9",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.9.tgz",
|
||||
"integrity": "sha512-hlT7AwCiKghOX3XizLxXOsTFiFCQnp/oj86zp1UxwDGmyzsyoxtX+UIZyVyH/oBF5+XtblFG9KZzZQ/h+dpy+Q==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.9",
|
||||
"@firebase/util": "1.10.0",
|
||||
"idb": "7.1.1",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/installations-compat": {
|
||||
"version": "0.2.9",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.9.tgz",
|
||||
"integrity": "sha512-2lfdc6kPXR7WaL4FCQSQUhXcPbI7ol3wF+vkgtU25r77OxPf8F/VmswQ7sgIkBBWtymn5ZF20TIKtnOj9rjb6w==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.9",
|
||||
"@firebase/installations": "0.6.9",
|
||||
"@firebase/installations-types": "0.5.2",
|
||||
"@firebase/util": "1.10.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app-compat": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/installations-types": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.2.tgz",
|
||||
"integrity": "sha512-que84TqGRZJpJKHBlF2pkvc1YcXrtEDOVGiDjovP/a3s6W4nlbohGXEsBJo0JCeeg/UG9A+DEZVDUV9GpklUzA==",
|
||||
"license": "Apache-2.0",
|
||||
"peerDependencies": {
|
||||
"@firebase/app-types": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/logger": {
|
||||
"version": "0.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz",
|
||||
"integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/messaging": {
|
||||
"version": "0.12.12",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.12.tgz",
|
||||
"integrity": "sha512-6q0pbzYBJhZEtUoQx7hnPhZvAbuMNuBXKQXOx2YlWhSrlv9N1m0ZzlNpBbu/ItTzrwNKTibdYzUyaaxdWLg+4w==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.9",
|
||||
"@firebase/installations": "0.6.9",
|
||||
"@firebase/messaging-interop-types": "0.2.2",
|
||||
"@firebase/util": "1.10.0",
|
||||
"idb": "7.1.1",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/messaging-compat": {
|
||||
"version": "0.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.12.tgz",
|
||||
"integrity": "sha512-pKsiUVZrbmRgdImYqhBNZlkKJbqjlPkVdQRZGRbkTyX4OSGKR0F/oJeCt1a8jEg5UnBp4fdVwSWSp4DuCovvEQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.9",
|
||||
"@firebase/messaging": "0.12.12",
|
||||
"@firebase/util": "1.10.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app-compat": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/messaging-interop-types": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.2.tgz",
|
||||
"integrity": "sha512-l68HXbuD2PPzDUOFb3aG+nZj5KA3INcPwlocwLZOzPp9rFM9yeuI9YLl6DQfguTX5eAGxO0doTR+rDLDvQb5tA==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@firebase/performance": {
|
||||
"version": "0.6.9",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.6.9.tgz",
|
||||
"integrity": "sha512-PnVaak5sqfz5ivhua+HserxTJHtCar/7zM0flCX6NkzBNzJzyzlH4Hs94h2Il0LQB99roBqoE5QT1JqWqcLJHQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.9",
|
||||
"@firebase/installations": "0.6.9",
|
||||
"@firebase/logger": "0.4.2",
|
||||
"@firebase/util": "1.10.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/performance-compat": {
|
||||
"version": "0.2.9",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.9.tgz",
|
||||
"integrity": "sha512-dNl95IUnpsu3fAfYBZDCVhXNkASE0uo4HYaEPd2/PKscfTvsgqFAOxfAXzBEDOnynDWiaGUnb5M1O00JQ+3FXA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.9",
|
||||
"@firebase/logger": "0.4.2",
|
||||
"@firebase/performance": "0.6.9",
|
||||
"@firebase/performance-types": "0.2.2",
|
||||
"@firebase/util": "1.10.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app-compat": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/performance-types": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.2.tgz",
|
||||
"integrity": "sha512-gVq0/lAClVH5STrIdKnHnCo2UcPLjJlDUoEB/tB4KM+hAeHUxWKnpT0nemUPvxZ5nbdY/pybeyMe8Cs29gEcHA==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@firebase/remote-config": {
|
||||
"version": "0.4.9",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.4.9.tgz",
|
||||
"integrity": "sha512-EO1NLCWSPMHdDSRGwZ73kxEEcTopAxX1naqLJFNApp4hO8WfKfmEpmjxmP5TrrnypjIf2tUkYaKsfbEA7+AMmA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.9",
|
||||
"@firebase/installations": "0.6.9",
|
||||
"@firebase/logger": "0.4.2",
|
||||
"@firebase/util": "1.10.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/remote-config-compat": {
|
||||
"version": "0.2.9",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.9.tgz",
|
||||
"integrity": "sha512-AxzGpWfWFYejH2twxfdOJt5Cfh/ATHONegTd/a0p5flEzsD5JsxXgfkFToop+mypEL3gNwawxrxlZddmDoNxyA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.9",
|
||||
"@firebase/logger": "0.4.2",
|
||||
"@firebase/remote-config": "0.4.9",
|
||||
"@firebase/remote-config-types": "0.3.2",
|
||||
"@firebase/util": "1.10.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app-compat": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/remote-config-types": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.3.2.tgz",
|
||||
"integrity": "sha512-0BC4+Ud7y2aPTyhXJTMTFfrGGLqdYXrUB9sJVAB8NiqJswDTc4/2qrE/yfUbnQJhbSi6ZaTTBKyG3n1nplssaA==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@firebase/storage": {
|
||||
"version": "0.13.2",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.13.2.tgz",
|
||||
"integrity": "sha512-fxuJnHshbhVwuJ4FuISLu+/76Aby2sh+44ztjF2ppoe0TELIDxPW6/r1KGlWYt//AD0IodDYYA8ZTN89q8YqUw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.9",
|
||||
"@firebase/util": "1.10.0",
|
||||
"tslib": "^2.1.0",
|
||||
"undici": "6.19.7"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/storage-compat": {
|
||||
"version": "0.3.12",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.12.tgz",
|
||||
"integrity": "sha512-hA4VWKyGU5bWOll+uwzzhEMMYGu9PlKQc1w4DWxB3aIErWYzonrZjF0icqNQZbwKNIdh8SHjZlFeB2w6OSsjfg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.6.9",
|
||||
"@firebase/storage": "0.13.2",
|
||||
"@firebase/storage-types": "0.8.2",
|
||||
"@firebase/util": "1.10.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app-compat": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/storage-types": {
|
||||
"version": "0.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.2.tgz",
|
||||
"integrity": "sha512-0vWu99rdey0g53lA7IShoA2Lol1jfnPovzLDUBuon65K7uKG9G+L5uO05brD9pMw+l4HRFw23ah3GwTGpEav6g==",
|
||||
"license": "Apache-2.0",
|
||||
"peerDependencies": {
|
||||
"@firebase/app-types": "0.x",
|
||||
"@firebase/util": "1.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/util": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.0.tgz",
|
||||
"integrity": "sha512-xKtx4A668icQqoANRxyDLBLz51TAbDP9KRfpbKGxiCAW346d0BeJe5vN6/hKxxmWwnZ0mautyv39JxviwwQMOQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/vertexai-preview": {
|
||||
"version": "0.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/vertexai-preview/-/vertexai-preview-0.0.4.tgz",
|
||||
"integrity": "sha512-EBSqyu9eg8frQlVU9/HjKtHN7odqbh9MtAcVz3WwHj4gLCLOoN9F/o+oxlq3CxvFrd3CNTZwu6d2mZtVlEInng==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/app-check-interop-types": "0.3.2",
|
||||
"@firebase/component": "0.6.9",
|
||||
"@firebase/logger": "0.4.2",
|
||||
"@firebase/util": "1.10.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app": "0.x",
|
||||
"@firebase/app-types": "0.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@firebase/webchannel-wrapper": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.1.tgz",
|
||||
"integrity": "sha512-jmEnr/pk0yVkA7mIlHNnxCi+wWzOFUg0WyIotgkKAb2u1J7fAeDBcVNSTjTihbAYNusCLQdW5s9IJ5qwnEufcQ==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@grpc/grpc-js": {
|
||||
"version": "1.9.15",
|
||||
"resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz",
|
||||
"integrity": "sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@grpc/proto-loader": "^0.7.8",
|
||||
"@types/node": ">=12.12.47"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^8.13.0 || >=10.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@grpc/proto-loader": {
|
||||
"version": "0.7.15",
|
||||
"resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.15.tgz",
|
||||
"integrity": "sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"lodash.camelcase": "^4.3.0",
|
||||
"long": "^5.0.0",
|
||||
"protobufjs": "^7.2.5",
|
||||
"yargs": "^17.7.2"
|
||||
},
|
||||
"bin": {
|
||||
"proto-loader-gen-types": "build/bin/proto-loader-gen-types.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@grpc/proto-loader/node_modules/cliui": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
|
||||
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"string-width": "^4.2.0",
|
||||
"strip-ansi": "^6.0.1",
|
||||
"wrap-ansi": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@grpc/proto-loader/node_modules/long": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
|
||||
"integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@grpc/proto-loader/node_modules/yargs": {
|
||||
"version": "17.7.2",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
|
||||
"integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cliui": "^8.0.1",
|
||||
"escalade": "^3.1.1",
|
||||
"get-caller-file": "^2.0.5",
|
||||
"require-directory": "^2.1.1",
|
||||
"string-width": "^4.2.3",
|
||||
"y18n": "^5.0.5",
|
||||
"yargs-parser": "^21.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@humanwhocodes/config-array": {
|
||||
"version": "0.13.0",
|
||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
|
||||
|
|
@ -1200,6 +1833,70 @@
|
|||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/@protobufjs/aspromise": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
|
||||
"integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@protobufjs/base64": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
|
||||
"integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@protobufjs/codegen": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
|
||||
"integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@protobufjs/eventemitter": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
|
||||
"integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@protobufjs/fetch": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
|
||||
"integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@protobufjs/aspromise": "^1.1.1",
|
||||
"@protobufjs/inquire": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@protobufjs/float": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
|
||||
"integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@protobufjs/inquire": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
|
||||
"integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@protobufjs/path": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
|
||||
"integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@protobufjs/pool": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
|
||||
"integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@protobufjs/utf8": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
|
||||
"integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@sinclair/typebox": {
|
||||
"version": "0.27.8",
|
||||
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
|
||||
|
|
@ -2866,6 +3563,18 @@
|
|||
"reusify": "^1.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/faye-websocket": {
|
||||
"version": "0.11.4",
|
||||
"resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz",
|
||||
"integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"websocket-driver": ">=0.5.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fb-watchman": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
|
||||
|
|
@ -2942,6 +3651,42 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/firebase": {
|
||||
"version": "10.14.1",
|
||||
"resolved": "https://registry.npmjs.org/firebase/-/firebase-10.14.1.tgz",
|
||||
"integrity": "sha512-0KZxU+Ela9rUCULqFsUUOYYkjh7OM1EWdIfG6///MtXd0t2/uUIf0iNV5i0KariMhRQ5jve/OY985nrAXFaZeQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/analytics": "0.10.8",
|
||||
"@firebase/analytics-compat": "0.2.14",
|
||||
"@firebase/app": "0.10.13",
|
||||
"@firebase/app-check": "0.8.8",
|
||||
"@firebase/app-check-compat": "0.3.15",
|
||||
"@firebase/app-compat": "0.2.43",
|
||||
"@firebase/app-types": "0.9.2",
|
||||
"@firebase/auth": "1.7.9",
|
||||
"@firebase/auth-compat": "0.5.14",
|
||||
"@firebase/data-connect": "0.1.0",
|
||||
"@firebase/database": "1.0.8",
|
||||
"@firebase/database-compat": "1.0.8",
|
||||
"@firebase/firestore": "4.7.3",
|
||||
"@firebase/firestore-compat": "0.3.38",
|
||||
"@firebase/functions": "0.11.8",
|
||||
"@firebase/functions-compat": "0.3.14",
|
||||
"@firebase/installations": "0.6.9",
|
||||
"@firebase/installations-compat": "0.2.9",
|
||||
"@firebase/messaging": "0.12.12",
|
||||
"@firebase/messaging-compat": "0.2.12",
|
||||
"@firebase/performance": "0.6.9",
|
||||
"@firebase/performance-compat": "0.2.9",
|
||||
"@firebase/remote-config": "0.4.9",
|
||||
"@firebase/remote-config-compat": "0.2.9",
|
||||
"@firebase/storage": "0.13.2",
|
||||
"@firebase/storage-compat": "0.3.12",
|
||||
"@firebase/util": "1.10.0",
|
||||
"@firebase/vertexai-preview": "0.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/flat-cache": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
|
||||
|
|
@ -3266,6 +4011,12 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/http-parser-js": {
|
||||
"version": "0.5.10",
|
||||
"resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz",
|
||||
"integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/human-signals": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
|
||||
|
|
@ -3276,6 +4027,12 @@
|
|||
"node": ">=10.17.0"
|
||||
}
|
||||
},
|
||||
"node_modules/idb": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz",
|
||||
"integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/ignore": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
||||
|
|
@ -4336,6 +5093,12 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash.camelcase": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
|
||||
"integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.memoize": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
|
||||
|
|
@ -4873,6 +5636,36 @@
|
|||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/protobufjs": {
|
||||
"version": "7.4.0",
|
||||
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz",
|
||||
"integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==",
|
||||
"hasInstallScript": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@protobufjs/aspromise": "^1.1.2",
|
||||
"@protobufjs/base64": "^1.1.2",
|
||||
"@protobufjs/codegen": "^2.0.4",
|
||||
"@protobufjs/eventemitter": "^1.1.0",
|
||||
"@protobufjs/fetch": "^1.1.0",
|
||||
"@protobufjs/float": "^1.0.2",
|
||||
"@protobufjs/inquire": "^1.1.0",
|
||||
"@protobufjs/path": "^1.1.2",
|
||||
"@protobufjs/pool": "^1.1.0",
|
||||
"@protobufjs/utf8": "^1.1.0",
|
||||
"@types/node": ">=13.7.0",
|
||||
"long": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/protobufjs/node_modules/long": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
|
||||
"integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||
|
|
@ -5450,6 +6243,12 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/type-check": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||
|
|
@ -5500,6 +6299,15 @@
|
|||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "6.19.7",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-6.19.7.tgz",
|
||||
"integrity": "sha512-HR3W/bMGPSr90i8AAp2C4DM3wChFdJPLrWYpIS++LxS8K+W535qftjt+4MyjNYHeWabMj1nvtmLIi7l++iq91A==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.17"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "6.19.8",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
|
||||
|
|
@ -5591,6 +6399,29 @@
|
|||
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
|
||||
"license": "BSD-2-Clause"
|
||||
},
|
||||
"node_modules/websocket-driver": {
|
||||
"version": "0.7.4",
|
||||
"resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
|
||||
"integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"http-parser-js": ">=0.5.1",
|
||||
"safe-buffer": ">=5.1.0",
|
||||
"websocket-extensions": ">=0.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/websocket-extensions": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz",
|
||||
"integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/whatwg-url": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||
|
|
@ -5703,7 +6534,6 @@
|
|||
"version": "21.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
|
||||
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
|
|
|
|||
|
|
@ -38,7 +38,9 @@
|
|||
"hnsw",
|
||||
"opfs",
|
||||
"origin-private-file-system",
|
||||
"embeddings"
|
||||
"embeddings",
|
||||
"graph-database",
|
||||
"streaming-data"
|
||||
],
|
||||
"author": "David Snelling (david@soulcraft.com)",
|
||||
"license": "MIT",
|
||||
|
|
|
|||
|
|
@ -6,7 +6,16 @@
|
|||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { HNSWIndex } from './hnsw/hnswIndex.js'
|
||||
import { createStorage } from './storage/opfsStorage.js'
|
||||
import { DistanceFunction, Edge, EmbeddingFunction, HNSWConfig, SearchResult, StorageAdapter, Vector, VectorDocument } from './coreTypes.js'
|
||||
import {
|
||||
DistanceFunction,
|
||||
Edge,
|
||||
EmbeddingFunction,
|
||||
HNSWConfig,
|
||||
SearchResult,
|
||||
StorageAdapter,
|
||||
Vector,
|
||||
VectorDocument
|
||||
} from './coreTypes.js'
|
||||
import { cosineDistance, defaultEmbeddingFunction, euclideanDistance } from './utils/index.js'
|
||||
|
||||
export interface BrainyDataConfig {
|
||||
|
|
@ -181,9 +190,9 @@ export class BrainyData<T = any> {
|
|||
* @returns Array of IDs for the added items
|
||||
*/
|
||||
public async addBatch(
|
||||
items: Array<{
|
||||
vectorOrData: Vector | any;
|
||||
metadata?: T
|
||||
items: Array<{
|
||||
vectorOrData: Vector | any;
|
||||
metadata?: T
|
||||
}>,
|
||||
options: {
|
||||
forceEmbed?: boolean // Force using the embedding function even if input is a vector
|
||||
|
|
@ -550,7 +559,7 @@ export class BrainyData<T = any> {
|
|||
/**
|
||||
* Embed text or data into a vector using the same embedding function used by this instance
|
||||
* This allows clients to use the same TensorFlow Universal Sentence Encoder throughout their application
|
||||
*
|
||||
*
|
||||
* @param data Text or data to embed
|
||||
* @returns A promise that resolves to the embedded vector
|
||||
*/
|
||||
|
|
@ -568,7 +577,7 @@ export class BrainyData<T = any> {
|
|||
/**
|
||||
* Search for similar documents using a text query
|
||||
* This is a convenience method that embeds the query text and performs a search
|
||||
*
|
||||
*
|
||||
* @param query Text query to search for
|
||||
* @param k Number of results to return
|
||||
* @returns Array of search results
|
||||
|
|
@ -596,6 +605,54 @@ export class BrainyData<T = any> {
|
|||
await this.init()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get information about the current storage usage and capacity
|
||||
* @returns Object containing the storage type, used space, quota, and additional details
|
||||
*/
|
||||
public async status(): Promise<{
|
||||
type: string;
|
||||
used: number;
|
||||
quota: number | null;
|
||||
details?: Record<string, any>;
|
||||
}> {
|
||||
await this.ensureInitialized()
|
||||
|
||||
if (!this.storage) {
|
||||
return {
|
||||
type: 'unknown',
|
||||
used: 0,
|
||||
quota: null,
|
||||
details: { error: 'Storage not initialized' }
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// Get storage status from the storage adapter
|
||||
const storageStatus = await this.storage.getStorageStatus()
|
||||
|
||||
// Add index information to the details
|
||||
const indexInfo = {
|
||||
indexSize: this.size()
|
||||
}
|
||||
|
||||
return {
|
||||
...storageStatus,
|
||||
details: {
|
||||
...storageStatus.details,
|
||||
index: indexInfo
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to get storage status:', error)
|
||||
return {
|
||||
type: 'unknown',
|
||||
used: 0,
|
||||
quota: null,
|
||||
details: { error: String(error) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Export distance functions for convenience
|
||||
|
|
|
|||
|
|
@ -120,4 +120,30 @@ export interface StorageAdapter {
|
|||
getMetadata(id: string): Promise<any | null>;
|
||||
|
||||
clear(): Promise<void>;
|
||||
|
||||
/**
|
||||
* Get information about storage usage and capacity
|
||||
* @returns Promise that resolves to an object containing storage status information
|
||||
*/
|
||||
getStorageStatus(): Promise<{
|
||||
/**
|
||||
* The type of storage being used (e.g., 'filesystem', 'opfs', 'memory')
|
||||
*/
|
||||
type: string;
|
||||
|
||||
/**
|
||||
* The amount of storage being used in bytes
|
||||
*/
|
||||
used: number;
|
||||
|
||||
/**
|
||||
* The total amount of storage available in bytes, or null if unknown
|
||||
*/
|
||||
quota: number | null;
|
||||
|
||||
/**
|
||||
* Additional storage-specific information
|
||||
*/
|
||||
details?: Record<string, any>;
|
||||
}>;
|
||||
}
|
||||
|
|
|
|||
24
src/index.ts
24
src/index.ts
|
|
@ -66,6 +66,30 @@ export {
|
|||
}
|
||||
export type { PipelineOptions }
|
||||
|
||||
// Export plugin loader
|
||||
import {
|
||||
loadPlugins,
|
||||
configureAndStartPipeline,
|
||||
createSensePluginConfig,
|
||||
createConduitPluginConfig
|
||||
} from './pluginLoader.js'
|
||||
import type {
|
||||
PluginLoaderOptions,
|
||||
PluginConfig,
|
||||
PluginLoadResult
|
||||
} from './pluginLoader.js'
|
||||
export {
|
||||
loadPlugins,
|
||||
configureAndStartPipeline,
|
||||
createSensePluginConfig,
|
||||
createConduitPluginConfig
|
||||
}
|
||||
export type {
|
||||
PluginLoaderOptions,
|
||||
PluginConfig,
|
||||
PluginLoadResult
|
||||
}
|
||||
|
||||
// Export types
|
||||
import type {
|
||||
Vector,
|
||||
|
|
|
|||
241
src/pluginLoader.ts
Normal file
241
src/pluginLoader.ts
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
/**
|
||||
* Plugin Loader for Brainy Augmentations
|
||||
*
|
||||
* This module provides functionality for loading and configuring augmentation plugins
|
||||
* from external npm packages. It allows consumers of the library to easily integrate
|
||||
* externally installed augmentation plugins into the Brainy system.
|
||||
*/
|
||||
|
||||
import { AugmentationPipeline, augmentationPipeline, ExecutionMode } from './augmentationPipeline.js';
|
||||
import { AugmentationType, IAugmentation, ISenseAugmentation, IConduitAugmentation } from './types/augmentations.js';
|
||||
|
||||
/**
|
||||
* Configuration options for loading plugins
|
||||
*/
|
||||
export interface PluginLoaderOptions {
|
||||
/**
|
||||
* Whether to use the default augmentation pipeline instance
|
||||
* If false, a new pipeline instance will be created
|
||||
* @default true
|
||||
*/
|
||||
useDefaultPipeline?: boolean;
|
||||
|
||||
/**
|
||||
* Whether to initialize the augmentations after loading
|
||||
* @default true
|
||||
*/
|
||||
initializeAfterLoading?: boolean;
|
||||
|
||||
/**
|
||||
* Order of augmentation types to load
|
||||
* By default, sense augmentations are loaded first
|
||||
* @default [AugmentationType.SENSE, AugmentationType.CONDUIT, ...]
|
||||
*/
|
||||
augmentationOrder?: AugmentationType[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Default options for the plugin loader
|
||||
*/
|
||||
const DEFAULT_OPTIONS: PluginLoaderOptions = {
|
||||
useDefaultPipeline: true,
|
||||
initializeAfterLoading: true,
|
||||
augmentationOrder: [
|
||||
AugmentationType.SENSE,
|
||||
AugmentationType.CONDUIT,
|
||||
AugmentationType.COGNITION,
|
||||
AugmentationType.MEMORY,
|
||||
AugmentationType.PERCEPTION,
|
||||
AugmentationType.DIALOG,
|
||||
AugmentationType.ACTIVATION,
|
||||
AugmentationType.WEBSOCKET
|
||||
]
|
||||
};
|
||||
|
||||
/**
|
||||
* Plugin configuration for a specific augmentation
|
||||
*/
|
||||
export interface PluginConfig {
|
||||
/**
|
||||
* The plugin module name or path
|
||||
* This can be an npm package name or a relative path
|
||||
*/
|
||||
plugin: string;
|
||||
|
||||
/**
|
||||
* Optional configuration to pass to the plugin
|
||||
*/
|
||||
config?: Record<string, any>;
|
||||
|
||||
/**
|
||||
* Optional type of the augmentation
|
||||
* If not provided, it will be determined automatically
|
||||
*/
|
||||
type?: AugmentationType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Result of loading plugins
|
||||
*/
|
||||
export interface PluginLoadResult {
|
||||
/**
|
||||
* The augmentation pipeline instance
|
||||
*/
|
||||
pipeline: AugmentationPipeline;
|
||||
|
||||
/**
|
||||
* Map of loaded augmentations by type
|
||||
*/
|
||||
augmentations: Map<AugmentationType, IAugmentation[]>;
|
||||
|
||||
/**
|
||||
* Any errors that occurred during loading
|
||||
*/
|
||||
errors: Error[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads augmentation plugins from external npm packages
|
||||
*
|
||||
* @param plugins Array of plugin configurations
|
||||
* @param options Options for loading plugins
|
||||
* @returns Promise that resolves to the plugin load result
|
||||
*/
|
||||
export async function loadPlugins(
|
||||
plugins: PluginConfig[],
|
||||
options: PluginLoaderOptions = {}
|
||||
): Promise<PluginLoadResult> {
|
||||
// Merge options with defaults
|
||||
const opts = { ...DEFAULT_OPTIONS, ...options };
|
||||
|
||||
// Use the default pipeline or create a new one
|
||||
const pipeline = opts.useDefaultPipeline ? augmentationPipeline : new AugmentationPipeline();
|
||||
|
||||
// Track loaded augmentations by type
|
||||
const loadedAugmentations = new Map<AugmentationType, IAugmentation[]>();
|
||||
const errors: Error[] = [];
|
||||
|
||||
// Group plugins by type according to the specified order
|
||||
const pluginsByType = new Map<AugmentationType, PluginConfig[]>();
|
||||
|
||||
// Initialize the map with empty arrays for each type
|
||||
for (const type of opts.augmentationOrder!) {
|
||||
pluginsByType.set(type, []);
|
||||
loadedAugmentations.set(type, []);
|
||||
}
|
||||
|
||||
// Group plugins by type
|
||||
for (const pluginConfig of plugins) {
|
||||
const type = pluginConfig.type || AugmentationType.SENSE; // Default to SENSE if not specified
|
||||
const typePlugins = pluginsByType.get(type) || [];
|
||||
typePlugins.push(pluginConfig);
|
||||
pluginsByType.set(type, typePlugins);
|
||||
}
|
||||
|
||||
// Load plugins in the specified order
|
||||
for (const type of opts.augmentationOrder!) {
|
||||
const typePlugins = pluginsByType.get(type) || [];
|
||||
|
||||
for (const pluginConfig of typePlugins) {
|
||||
try {
|
||||
// Import the plugin module
|
||||
const pluginModule = await import(pluginConfig.plugin);
|
||||
|
||||
// Get the default export or the named export that matches the plugin name
|
||||
const PluginClass = pluginModule.default || pluginModule[pluginConfig.plugin.split('/').pop()!];
|
||||
|
||||
if (!PluginClass) {
|
||||
throw new Error(`Could not find a valid export in plugin ${pluginConfig.plugin}`);
|
||||
}
|
||||
|
||||
// Instantiate the plugin with the provided configuration
|
||||
const plugin = new PluginClass(pluginConfig.config);
|
||||
|
||||
// Register the plugin with the pipeline
|
||||
pipeline.register(plugin);
|
||||
|
||||
// Add to the loaded augmentations map
|
||||
const typeAugmentations = loadedAugmentations.get(type) || [];
|
||||
typeAugmentations.push(plugin);
|
||||
loadedAugmentations.set(type, typeAugmentations);
|
||||
} catch (error) {
|
||||
const err = error instanceof Error ? error : new Error(String(error));
|
||||
errors.push(err);
|
||||
console.error(`Error loading plugin ${pluginConfig.plugin}:`, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the augmentations if requested
|
||||
if (opts.initializeAfterLoading) {
|
||||
try {
|
||||
await pipeline.initialize();
|
||||
} catch (error) {
|
||||
const err = error instanceof Error ? error : new Error(String(error));
|
||||
errors.push(err);
|
||||
console.error('Error initializing augmentations:', err);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
pipeline,
|
||||
augmentations: loadedAugmentations,
|
||||
errors
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures and starts the augmentation pipeline with the specified plugins
|
||||
*
|
||||
* @param plugins Array of plugin configurations
|
||||
* @param options Options for loading plugins
|
||||
* @returns Promise that resolves to the plugin load result
|
||||
*/
|
||||
export async function configureAndStartPipeline(
|
||||
plugins: PluginConfig[],
|
||||
options: PluginLoaderOptions = {}
|
||||
): Promise<PluginLoadResult> {
|
||||
// Load the plugins
|
||||
const result = await loadPlugins(plugins, {
|
||||
...options,
|
||||
initializeAfterLoading: true
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a plugin configuration for a sense augmentation
|
||||
*
|
||||
* @param plugin The plugin module name or path
|
||||
* @param config Optional configuration to pass to the plugin
|
||||
* @returns Plugin configuration
|
||||
*/
|
||||
export function createSensePluginConfig(
|
||||
plugin: string,
|
||||
config?: Record<string, any>
|
||||
): PluginConfig {
|
||||
return {
|
||||
plugin,
|
||||
config,
|
||||
type: AugmentationType.SENSE
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a plugin configuration for a conduit augmentation
|
||||
*
|
||||
* @param plugin The plugin module name or path
|
||||
* @param config Optional configuration to pass to the plugin
|
||||
* @returns Plugin configuration
|
||||
*/
|
||||
export function createConduitPluginConfig(
|
||||
plugin: string,
|
||||
config?: Record<string, any>
|
||||
): PluginConfig {
|
||||
return {
|
||||
plugin,
|
||||
config,
|
||||
type: AugmentationType.CONDUIT
|
||||
};
|
||||
}
|
||||
|
|
@ -451,4 +451,113 @@ export class FileSystemStorage implements StorageAdapter {
|
|||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
/**
|
||||
* Get information about storage usage and capacity
|
||||
*/
|
||||
public async getStorageStatus(): Promise<{
|
||||
type: string;
|
||||
used: number;
|
||||
quota: number | null;
|
||||
details?: Record<string, any>;
|
||||
}> {
|
||||
await this.ensureInitialized()
|
||||
|
||||
try {
|
||||
// Calculate the total size of all files in the storage directories
|
||||
let totalSize = 0
|
||||
|
||||
// Helper function to calculate directory size
|
||||
const calculateDirSize = async (dirPath: string): Promise<number> => {
|
||||
let size = 0
|
||||
try {
|
||||
const files = await fs.promises.readdir(dirPath)
|
||||
|
||||
for (const file of files) {
|
||||
const filePath = path.join(dirPath, file)
|
||||
const stats = await fs.promises.stat(filePath)
|
||||
|
||||
if (stats.isDirectory()) {
|
||||
size += await calculateDirSize(filePath)
|
||||
} else {
|
||||
size += stats.size
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn(`Error calculating size for ${dirPath}:`, error)
|
||||
}
|
||||
return size
|
||||
}
|
||||
|
||||
// Calculate size for each directory
|
||||
const nodesDirSize = await calculateDirSize(this.nodesDir)
|
||||
const edgesDirSize = await calculateDirSize(this.edgesDir)
|
||||
const metadataDirSize = await calculateDirSize(this.metadataDir)
|
||||
|
||||
totalSize = nodesDirSize + edgesDirSize + metadataDirSize
|
||||
|
||||
// Get filesystem information
|
||||
let quota = null
|
||||
let details = {}
|
||||
|
||||
try {
|
||||
// Try to get disk space information
|
||||
const stats = await fs.promises.statfs(this.rootDir)
|
||||
if (stats) {
|
||||
const availableSpace = stats.bavail * stats.bsize
|
||||
const totalSpace = stats.blocks * stats.bsize
|
||||
|
||||
quota = totalSpace
|
||||
details = {
|
||||
availableSpace,
|
||||
totalSpace,
|
||||
freePercentage: (availableSpace / totalSpace) * 100
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Unable to get filesystem stats:', error)
|
||||
// If statfs is not available, try to use df command on Unix-like systems
|
||||
try {
|
||||
const { exec } = await import('child_process')
|
||||
const util = await import('util')
|
||||
const execPromise = util.promisify(exec)
|
||||
|
||||
const { stdout } = await execPromise(`df -k "${this.rootDir}"`)
|
||||
const lines = stdout.trim().split('\n')
|
||||
if (lines.length > 1) {
|
||||
const parts = lines[1].split(/\s+/)
|
||||
if (parts.length >= 4) {
|
||||
const totalKB = parseInt(parts[1], 10)
|
||||
const usedKB = parseInt(parts[2], 10)
|
||||
const availableKB = parseInt(parts[3], 10)
|
||||
|
||||
quota = totalKB * 1024
|
||||
details = {
|
||||
availableSpace: availableKB * 1024,
|
||||
totalSpace: totalKB * 1024,
|
||||
freePercentage: (availableKB / totalKB) * 100
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (dfError) {
|
||||
console.warn('Unable to get disk space using df command:', dfError)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'filesystem',
|
||||
used: totalSize,
|
||||
quota,
|
||||
details
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to get storage status:', error)
|
||||
return {
|
||||
type: 'filesystem',
|
||||
used: 0,
|
||||
quota: null,
|
||||
details: { error: String(error) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -498,6 +498,89 @@ export class OPFSStorage implements StorageAdapter {
|
|||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
/**
|
||||
* Get information about storage usage and capacity
|
||||
*/
|
||||
public async getStorageStatus(): Promise<{
|
||||
type: string;
|
||||
used: number;
|
||||
quota: number | null;
|
||||
details?: Record<string, any>;
|
||||
}> {
|
||||
await this.ensureInitialized()
|
||||
|
||||
try {
|
||||
// Calculate the total size of all files in the storage directories
|
||||
let totalSize = 0
|
||||
|
||||
// Helper function to calculate directory size
|
||||
const calculateDirSize = async (dirHandle: FileSystemDirectoryHandle): Promise<number> => {
|
||||
let size = 0
|
||||
try {
|
||||
// @ts-ignore - TypeScript doesn't recognize FileSystemDirectoryHandle.entries() properly
|
||||
for await (const [name, handle] of dirHandle.entries()) {
|
||||
if (handle.kind === 'file') {
|
||||
const file = await handle.getFile()
|
||||
size += file.size
|
||||
} else if (handle.kind === 'directory') {
|
||||
size += await calculateDirSize(handle)
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn(`Error calculating size for directory:`, error)
|
||||
}
|
||||
return size
|
||||
}
|
||||
|
||||
// Calculate size for each directory
|
||||
if (this.nodesDir) {
|
||||
totalSize += await calculateDirSize(this.nodesDir)
|
||||
}
|
||||
if (this.edgesDir) {
|
||||
totalSize += await calculateDirSize(this.edgesDir)
|
||||
}
|
||||
if (this.metadataDir) {
|
||||
totalSize += await calculateDirSize(this.metadataDir)
|
||||
}
|
||||
|
||||
// Get storage quota information using the Storage API
|
||||
let quota = null
|
||||
let details: Record<string, any> = {
|
||||
isPersistent: await this.isPersistent()
|
||||
}
|
||||
|
||||
try {
|
||||
if (navigator.storage && navigator.storage.estimate) {
|
||||
const estimate = await navigator.storage.estimate()
|
||||
quota = estimate.quota || null
|
||||
details = {
|
||||
...details,
|
||||
usage: estimate.usage,
|
||||
quota: estimate.quota,
|
||||
freePercentage: estimate.quota ? ((estimate.quota - (estimate.usage || 0)) / estimate.quota) * 100 : null
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Unable to get storage estimate:', error)
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'opfs',
|
||||
used: totalSize,
|
||||
quota,
|
||||
details
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to get storage status:', error)
|
||||
return {
|
||||
type: 'opfs',
|
||||
used: 0,
|
||||
quota: null,
|
||||
details: { error: String(error) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -693,6 +776,114 @@ export class MemoryStorage implements StorageAdapter {
|
|||
this.edges.clear()
|
||||
this.metadata.clear()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get information about storage usage and capacity
|
||||
*/
|
||||
public async getStorageStatus(): Promise<{
|
||||
type: string;
|
||||
used: number;
|
||||
quota: number | null;
|
||||
details?: Record<string, any>;
|
||||
}> {
|
||||
try {
|
||||
// Estimate the size of data in memory
|
||||
let totalSize = 0
|
||||
|
||||
// Helper function to estimate object size in bytes
|
||||
const estimateSize = (obj: any): number => {
|
||||
if (obj === null || obj === undefined) return 0
|
||||
|
||||
const type = typeof obj
|
||||
|
||||
// Handle primitive types
|
||||
if (type === 'number') return 8
|
||||
if (type === 'string') return obj.length * 2
|
||||
if (type === 'boolean') return 4
|
||||
|
||||
// Handle arrays and objects
|
||||
if (Array.isArray(obj)) {
|
||||
return obj.reduce((size, item) => size + estimateSize(item), 0)
|
||||
}
|
||||
|
||||
if (type === 'object') {
|
||||
if (obj instanceof Map) {
|
||||
let mapSize = 0
|
||||
for (const [key, value] of obj.entries()) {
|
||||
mapSize += estimateSize(key) + estimateSize(value)
|
||||
}
|
||||
return mapSize
|
||||
}
|
||||
|
||||
if (obj instanceof Set) {
|
||||
let setSize = 0
|
||||
for (const item of obj) {
|
||||
setSize += estimateSize(item)
|
||||
}
|
||||
return setSize
|
||||
}
|
||||
|
||||
// Regular object
|
||||
return Object.entries(obj).reduce(
|
||||
(size, [key, value]) => size + key.length * 2 + estimateSize(value),
|
||||
0
|
||||
)
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// Estimate size of nodes
|
||||
for (const node of this.nodes.values()) {
|
||||
totalSize += estimateSize(node)
|
||||
}
|
||||
|
||||
// Estimate size of edges
|
||||
for (const edge of this.edges.values()) {
|
||||
totalSize += estimateSize(edge)
|
||||
}
|
||||
|
||||
// Estimate size of metadata
|
||||
for (const meta of this.metadata.values()) {
|
||||
totalSize += estimateSize(meta)
|
||||
}
|
||||
|
||||
// Get memory information if available
|
||||
let quota = null
|
||||
let details: Record<string, any> = {
|
||||
nodesCount: this.nodes.size,
|
||||
edgesCount: this.edges.size,
|
||||
metadataCount: this.metadata.size
|
||||
}
|
||||
|
||||
// Try to get memory information if in a browser environment
|
||||
if (typeof window !== 'undefined' && (window as any).performance && (window as any).performance.memory) {
|
||||
const memory = (window as any).performance.memory
|
||||
quota = memory.jsHeapSizeLimit
|
||||
details = {
|
||||
...details,
|
||||
totalJSHeapSize: memory.totalJSHeapSize,
|
||||
usedJSHeapSize: memory.usedJSHeapSize,
|
||||
jsHeapSizeLimit: memory.jsHeapSizeLimit
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'memory',
|
||||
used: totalSize,
|
||||
quota,
|
||||
details
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to get memory storage status:', error)
|
||||
return {
|
||||
type: 'memory',
|
||||
used: 0,
|
||||
quota: null,
|
||||
details: { error: String(error) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue