**chore(version): bump version to 0.9.33 and update references**
- Updated version to `0.9.33` in `README.md`, `cli-package/package.json`, and `src/utils/version.ts`. - Synced `@soulcraft/brainy` dependency version to `0.9.33` in the CLI package for consistency. - Updated npm version badge in `README.md` to reflect the new version. - Refactored `TextEncoder` and `TextDecoder` implementations in `src/utils/tensorflowUtils.ts`: - Added dynamic environment-aware loading for improved Node.js and browser compatibility. - Enhanced fallback mechanisms for environments without global support. This update ensures consistent versioning across the project and improves the robustness of utility methods for broader environment compatibility.
This commit is contained in:
parent
ce590adc27
commit
4fb1ff7cfc
4 changed files with 175 additions and 33 deletions
|
|
@ -6,7 +6,7 @@
|
|||
[](https://nodejs.org/)
|
||||
[](https://www.typescriptlang.org/)
|
||||
[](CONTRIBUTING.md)
|
||||
[](https://www.npmjs.com/package/@soulcraft/brainy)
|
||||
[](https://www.npmjs.com/package/@soulcraft/brainy)
|
||||
|
||||
[//]: # ([](https://github.com/sodal-project/cartographer))
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@soulcraft/brainy-cli",
|
||||
"version": "0.9.32",
|
||||
"version": "0.9.33",
|
||||
"description": "Command-line interface for the Brainy vector graph database",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
|
|
@ -40,7 +40,7 @@
|
|||
"url": "git+https://github.com/soulcraft-research/brainy.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"@soulcraft/brainy": "0.9.32",
|
||||
"@soulcraft/brainy": "0.9.33",
|
||||
"commander": "^14.0.0",
|
||||
"omelette": "^0.4.17"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -10,6 +10,93 @@ import type {
|
|||
PlatformNodeObject
|
||||
} from '../types/tensorflowTypes.js'
|
||||
|
||||
// Flag to track if we're in a Node.js environment
|
||||
const isNodeEnvironment =
|
||||
typeof process !== 'undefined' &&
|
||||
process.versions &&
|
||||
process.versions.node
|
||||
|
||||
// Promise to load Node.js TextEncoder and TextDecoder
|
||||
let nodeUtilPromise: Promise<any> | null = null
|
||||
|
||||
// Function to get TextEncoder based on environment
|
||||
async function getTextEncoder(): Promise<typeof TextEncoder | null> {
|
||||
// First check if TextEncoder is globally available
|
||||
if (typeof TextEncoder !== 'undefined') {
|
||||
return TextEncoder
|
||||
}
|
||||
|
||||
// Then try to get it from Node.js util module
|
||||
if (isNodeEnvironment) {
|
||||
try {
|
||||
// Check if we can access the util module directly (in case it's already loaded)
|
||||
// @ts-ignore - Ignore TypeScript error for global.require
|
||||
if (typeof global !== 'undefined' && global.require && global.require.cache && global.require.cache['util']) {
|
||||
// @ts-ignore - Ignore TypeScript error for global.require
|
||||
const cachedUtil = global.require('util')
|
||||
if (cachedUtil && cachedUtil.TextEncoder) {
|
||||
return cachedUtil.TextEncoder
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, use dynamic import
|
||||
if (!nodeUtilPromise) {
|
||||
nodeUtilPromise = import('util').catch(error => {
|
||||
console.warn('Failed to import from util:', error)
|
||||
return null
|
||||
})
|
||||
}
|
||||
|
||||
const util = await nodeUtilPromise
|
||||
return util?.TextEncoder || null
|
||||
} catch (error) {
|
||||
console.warn('Error accessing TextEncoder:', error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
// Function to get TextDecoder based on environment
|
||||
async function getTextDecoder(): Promise<typeof TextDecoder | null> {
|
||||
// First check if TextDecoder is globally available
|
||||
if (typeof TextDecoder !== 'undefined') {
|
||||
return TextDecoder
|
||||
}
|
||||
|
||||
// Then try to get it from Node.js util module
|
||||
if (isNodeEnvironment) {
|
||||
try {
|
||||
// Check if we can access the util module directly (in case it's already loaded)
|
||||
// @ts-ignore - Ignore TypeScript error for global.require
|
||||
if (typeof global !== 'undefined' && global.require && global.require.cache && global.require.cache['util']) {
|
||||
// @ts-ignore - Ignore TypeScript error for global.require
|
||||
const cachedUtil = global.require('util')
|
||||
if (cachedUtil && cachedUtil.TextDecoder) {
|
||||
return cachedUtil.TextDecoder
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, use dynamic import
|
||||
if (!nodeUtilPromise) {
|
||||
nodeUtilPromise = import('util').catch(error => {
|
||||
console.warn('Failed to import from util:', error)
|
||||
return null
|
||||
})
|
||||
}
|
||||
|
||||
const util = await nodeUtilPromise
|
||||
return util?.TextDecoder || null
|
||||
} catch (error) {
|
||||
console.warn('Error accessing TextDecoder:', error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
// Define a global PlatformNode class for TensorFlow.js compatibility
|
||||
// This is needed because TensorFlow.js creates its own PlatformNode instance
|
||||
// and we need to ensure it uses the correct TextEncoder/TextDecoder
|
||||
|
|
@ -32,39 +119,94 @@ if (
|
|||
this.util = {
|
||||
isFloat32Array,
|
||||
isTypedArray,
|
||||
// Use the global TextEncoder/TextDecoder directly
|
||||
TextEncoder:
|
||||
typeof TextEncoder !== 'undefined'
|
||||
? TextEncoder
|
||||
: function () {
|
||||
console.warn(
|
||||
'TextEncoder constructor called but not available'
|
||||
)
|
||||
return { encode: (str: string) => new Uint8Array([]) }
|
||||
},
|
||||
TextDecoder:
|
||||
typeof TextDecoder !== 'undefined'
|
||||
? TextDecoder
|
||||
: function () {
|
||||
console.warn(
|
||||
'TextDecoder constructor called but not available'
|
||||
)
|
||||
return { decode: (bytes: Uint8Array) => '' }
|
||||
// Provide synchronous constructors that return objects with the expected interface
|
||||
// TensorFlow.js expects these to be synchronous
|
||||
TextEncoder: function() {
|
||||
// For Node.js environments, create a direct implementation
|
||||
if (isNodeEnvironment) {
|
||||
return {
|
||||
encode: (str: string) => {
|
||||
try {
|
||||
// Direct implementation for Node.js
|
||||
// Convert string to UTF-8 encoded Uint8Array
|
||||
const buffer = Buffer.from(str, 'utf-8')
|
||||
const uint8Array = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength)
|
||||
return uint8Array
|
||||
} catch (error) {
|
||||
console.warn('Error in Node.js TextEncoder implementation:', error)
|
||||
return new Uint8Array([])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// For browser environments, use the global TextEncoder
|
||||
else if (typeof TextEncoder !== 'undefined') {
|
||||
return new TextEncoder()
|
||||
}
|
||||
// Fallback for other environments
|
||||
else {
|
||||
console.warn('TextEncoder not available in this environment')
|
||||
return {
|
||||
encode: (str: string) => new Uint8Array([])
|
||||
}
|
||||
}
|
||||
},
|
||||
TextDecoder: function() {
|
||||
// For Node.js environments, create a direct implementation
|
||||
if (isNodeEnvironment) {
|
||||
return {
|
||||
decode: (bytes: Uint8Array) => {
|
||||
try {
|
||||
// Direct implementation for Node.js
|
||||
// Convert Uint8Array to string using Buffer
|
||||
const buffer = Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength)
|
||||
return buffer.toString('utf-8')
|
||||
} catch (error) {
|
||||
console.warn('Error in Node.js TextDecoder implementation:', error)
|
||||
return ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// For browser environments, use the global TextDecoder
|
||||
else if (typeof TextDecoder !== 'undefined') {
|
||||
return new TextDecoder()
|
||||
}
|
||||
// Fallback for other environments
|
||||
else {
|
||||
console.warn('TextDecoder not available in this environment')
|
||||
return {
|
||||
decode: (bytes: Uint8Array) => ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize TextEncoder/TextDecoder directly from globals
|
||||
if (typeof TextEncoder !== 'undefined') {
|
||||
this.textEncoder = new TextEncoder()
|
||||
} else {
|
||||
console.warn('TextEncoder is not available in this environment')
|
||||
// Initialize TextEncoder/TextDecoder
|
||||
this.initializeEncoders()
|
||||
}
|
||||
|
||||
// Initialize TextEncoder and TextDecoder asynchronously
|
||||
async initializeEncoders() {
|
||||
try {
|
||||
const TextEncoderClass = await getTextEncoder()
|
||||
if (TextEncoderClass) {
|
||||
this.textEncoder = new TextEncoderClass()
|
||||
} else {
|
||||
console.warn('TextEncoder is not available in this environment')
|
||||
this.textEncoder = { encode: (str: string) => new Uint8Array([]) }
|
||||
}
|
||||
|
||||
const TextDecoderClass = await getTextDecoder()
|
||||
if (TextDecoderClass) {
|
||||
this.textDecoder = new TextDecoderClass()
|
||||
} else {
|
||||
console.warn('TextDecoder is not available in this environment')
|
||||
this.textDecoder = { decode: (bytes: Uint8Array) => '' }
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize encoders:', error)
|
||||
this.textEncoder = { encode: (str: string) => new Uint8Array([]) }
|
||||
}
|
||||
|
||||
if (typeof TextDecoder !== 'undefined') {
|
||||
this.textDecoder = new TextDecoder()
|
||||
} else {
|
||||
console.warn('TextDecoder is not available in this environment')
|
||||
this.textDecoder = { decode: (bytes: Uint8Array) => '' }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,4 +3,4 @@
|
|||
* Do not modify this file directly.
|
||||
*/
|
||||
|
||||
export const VERSION = '0.9.32';
|
||||
export const VERSION = '0.9.33';
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue