brainy/src/utils/environment.ts
David Snelling 266715aeee chore(8.0)!: drop browser support, cloud SDKs, legacy pipeline, dead threading
Brainy 8.0 is server-only. This commit takes the consequences seriously and
removes everything that was only there to keep browser/cloud/threading
surfaces alive.

Browser support drop (per the @deprecated notes in environment.ts):
  - isBrowser, isWebWorker, areWebWorkersAvailable, navigator.deviceMemory
    paths, window/document/self.onmessage code.
  - browser console.log in unified.ts, the 'browser' branch in
    autoConfiguration.ts (env enum + scaleUp cases), 'browser-cache' model
    path, MCP service environment value.
  - package.json browser field.
  - src/worker.ts (Web Worker entrypoint) deleted.

Cloud SDK removal (the four adapters were dropped in Phase 7; the SDKs
were the lingering tax):
  - @aws-sdk/client-s3, @azure/identity, @azure/storage-blob, and
    @google-cloud/storage removed from package.json. Lockfile drops the
    entire @aws/@azure/@google-cloud/@smithy transitive tree.
  - EnhancedS3Clear class deleted from enhancedClearOperations.ts (the
    only @aws-sdk/client-s3 consumer; the dynamic import sites went with
    it). EnhancedFileSystemClear stays.
  - src/utils/adaptiveSocketManager.ts deleted entirely (474 LOC of HTTPS
    socket-pool management for the dropped cloud HTTP handler).
    performanceMonitor.ts no longer reports a socketConfig; socket
    utilization is fixed at 0.

Dead threading subsystem:
  - executeInThread was imported by distance.ts and hnswIndex.ts but
    never called. It was scaffolding for a future "off-main-thread
    distance batch" optimization that never shipped.
  - src/utils/workerUtils.ts deleted (Web Worker code path + an
    unreachable Node Worker Threads code path).
  - environment.ts loses isThreadingAvailable, isThreadingAvailableAsync,
    areWorkerThreadsAvailable, areWorkerThreadsAvailableSync. All exports
    purged from index.ts and unified.ts.
  - autoConfiguration.ts drops AutoConfigResult.threadingAvailable.

Legacy plugin/augmentation pipeline:
  - src/pipeline.ts deleted. The whole file was a no-op stub for
    backwards compat — Pipeline class had no methods, no lifecycle hooks,
    no before/after callbacks. AugmentationPipeline, augmentationPipeline,
    createPipeline, createStreamingPipeline, StreamlinedPipelineOptions,
    StreamlinedPipelineResult, StreamlinedExecutionMode were all aliases
    for the same stub.
  - src/mcp/mcpAugmentationToolset.ts deleted. executePipeline always
    threw "deprecated", isValidAugmentationType always returned false,
    getAvailableTools always returned []. Dead surface.
  - BrainyMCPService no longer instantiates a toolset. TOOL_EXECUTION
    requests now return the standard UNSUPPORTED_REQUEST_TYPE error.
    'availableTools' system-info returns [] (was the same in practice).

Net: 22 files changed, ~6400 LOC deleted (including legacy code +
mechanical lockfile churn). Build clean, 1409/1409 tests pass.
2026-06-09 16:38:30 -07:00

83 lines
3.2 KiB
TypeScript

/**
* @module utils/environment
* @description Runtime environment detection helpers. 8.0 supports Node.js,
* Bun, and Deno on the server side only — browsers were dropped from the
* support matrix in 8.0, so the helpers here assume a Node-like runtime.
*/
/**
* @description True when running inside a Node-compatible runtime
* (Node.js, Bun, Deno node-compat). 8.0 has no browser path, so this is
* effectively always true in a deployed brain — the function is kept for
* defensive checks at runtime boundaries.
*/
export function isNode(): boolean {
return (
typeof process !== 'undefined' &&
process.versions != null &&
process.versions.node != null
)
}
/**
* @description Auto-detect a production deployment. Returns true when any
* common managed-runtime indicator is present (Cloud Run, Lambda, Azure
* Functions, Vercel, Netlify, Heroku, Railway, Fly.io, Docker prod), or
* when `NODE_ENV=production`. Used to silence verbose logging in prod.
*/
export function isProductionEnvironment(): boolean {
if (!isNode()) return false
const nodeEnv = process.env.NODE_ENV?.toLowerCase()
if (nodeEnv === 'production' || nodeEnv === 'prod') return true
if (process.env.K_SERVICE || process.env.GOOGLE_CLOUD_PROJECT) return true
if (process.env.AWS_LAMBDA_FUNCTION_NAME || process.env.AWS_EXECUTION_ENV) return true
if (process.env.AZURE_FUNCTIONS_ENVIRONMENT || process.env.WEBSITE_SITE_NAME) return true
if (process.env.VERCEL || process.env.VERCEL_ENV === 'production') return true
if (process.env.NETLIFY && process.env.CONTEXT === 'production') return true
if (process.env.DYNO && process.env.NODE_ENV !== 'development') return true
if (process.env.RAILWAY_ENVIRONMENT === 'production') return true
if (process.env.FLY_APP_NAME && process.env.FLY_REGION) return true
if (process.env.DOCKER_ENV === 'production' || process.env.ENVIRONMENT === 'production') return true
if (process.env.PROD === 'true' || process.env.PRODUCTION === 'true') return true
return false
}
/**
* @description Resolve a log level from BRAINY_LOG_LEVEL, NODE_ENV, and
* deployment-environment heuristics. Production defaults to 'error' so a
* busy app doesn't pay for verbose logging.
*/
export function getLogLevel(): 'silent' | 'error' | 'warn' | 'info' | 'verbose' {
const explicitLevel = process.env.BRAINY_LOG_LEVEL?.toLowerCase()
if (explicitLevel && ['silent', 'error', 'warn', 'info', 'verbose'].includes(explicitLevel)) {
return explicitLevel as 'silent' | 'error' | 'warn' | 'info' | 'verbose'
}
if (isProductionEnvironment()) return 'error'
if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'dev') {
return 'verbose'
}
if (process.env.NODE_ENV === 'test') return 'warn'
return 'info'
}
/**
* @description True when a log message at the requested level should be
* emitted given the current configured log level. Returns false in 'silent'.
*/
export function shouldLog(level: 'error' | 'warn' | 'info' | 'verbose'): boolean {
const currentLevel = getLogLevel()
if (currentLevel === 'silent') return false
const levels = ['error', 'warn', 'info', 'verbose']
const currentIndex = levels.indexOf(currentLevel)
const messageIndex = levels.indexOf(level)
return messageIndex <= currentIndex
}