@camstack/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +143 -0
- package/dist/index.d.ts +143 -0
- package/dist/index.js +666 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +630 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +31 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/events/event-bus.ts","../src/download/model-downloader.ts","../src/python/python-env-manager.ts","../src/addon/addon-loader.ts","../src/addon/addon-engine-manager.ts","../src/addon/addon-installer.ts","../src/pipeline/pipeline-validator.ts","../src/pipeline/pipeline-runner.ts"],"sourcesContent":["export { EventBus } from './events/event-bus.js'\nexport { downloadModel } from './download/model-downloader.js'\nexport { PythonEnvManager } from './python/python-env-manager.js'\nexport type { RegisteredAddon } from './addon/addon-loader.js'\nexport { AddonLoader } from './addon/addon-loader.js'\nexport { AddonEngineManager } from './addon/addon-engine-manager.js'\nexport type { AddonInstallerConfig, InstalledPackage } from './addon/addon-installer.js'\nexport { AddonInstaller, BUILTIN_PACKAGES } from './addon/addon-installer.js'\nexport type { ValidationIssue, ValidationResult } from './pipeline/pipeline-validator.js'\nexport { PipelineValidator } from './pipeline/pipeline-validator.js'\nexport { PipelineRunner } from './pipeline/pipeline-runner.js'\n","type EventCallback<T = unknown> = (data: T) => void\n\nexport class EventBus {\n private listeners = new Map<string, Set<EventCallback>>()\n\n on<T = unknown>(event: string, callback: EventCallback<T>): () => void {\n if (!this.listeners.has(event)) this.listeners.set(event, new Set())\n const set = this.listeners.get(event)!\n set.add(callback as EventCallback)\n return () => set.delete(callback as EventCallback)\n }\n\n emit<T = unknown>(event: string, data: T): void {\n const set = this.listeners.get(event)\n if (!set) return\n for (const cb of set) {\n try { cb(data) } catch { /* don't let one listener break others */ }\n }\n }\n\n once<T = unknown>(event: string, callback: EventCallback<T>): () => void {\n const unsub = this.on<T>(event, (data) => {\n unsub()\n callback(data)\n })\n return unsub\n }\n\n removeAllListeners(event?: string): void {\n if (event) this.listeners.delete(event)\n else this.listeners.clear()\n }\n\n listenerCount(event: string): number {\n return this.listeners.get(event)?.size ?? 0\n }\n}\n","import type { ModelDownloadOptions, ModelDownloadResult } from '@camstack/types'\nimport * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport * as https from 'node:https'\nimport * as http from 'node:http'\nimport { createHash } from 'node:crypto'\n\nexport async function downloadModel(options: ModelDownloadOptions): Promise<ModelDownloadResult> {\n const { url, fallbackUrls = [], destDir, filename, expectedSha256, onProgress } = options\n\n // Derive filename from URL if not provided\n const fname = filename ?? url.split('/').pop() ?? 'model.bin'\n const destPath = path.join(destDir, fname)\n\n // Check cache\n if (fs.existsSync(destPath)) {\n return { filePath: destPath, downloadedBytes: 0, fromCache: true }\n }\n\n fs.mkdirSync(destDir, { recursive: true })\n\n // Try primary URL, then fallbacks\n const urls = [url, ...fallbackUrls]\n let lastError: Error | null = null\n\n for (const tryUrl of urls) {\n try {\n const bytes = await downloadFile(tryUrl, destPath, onProgress)\n\n // Verify SHA256 if provided\n if (expectedSha256) {\n const hash = await computeSha256(destPath)\n if (hash !== expectedSha256) {\n fs.unlinkSync(destPath)\n throw new Error(`SHA256 mismatch: expected ${expectedSha256}, got ${hash}`)\n }\n }\n\n return { filePath: destPath, downloadedBytes: bytes, fromCache: false }\n } catch (e) {\n lastError = e as Error\n if (fs.existsSync(destPath)) fs.unlinkSync(destPath) // cleanup partial\n }\n }\n\n throw lastError ?? new Error(`Failed to download model from ${url}`)\n}\n\nasync function downloadFile(\n url: string,\n destPath: string,\n onProgress?: (downloaded: number, total: number) => void,\n): Promise<number> {\n return new Promise((resolve, reject) => {\n const mod = url.startsWith('https') ? https : http\n\n const request = (targetUrl: string, redirectCount = 0) => {\n if (redirectCount > 5) return reject(new Error('Too many redirects'))\n\n mod.get(targetUrl, (res) => {\n // Handle redirects\n if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {\n return request(res.headers.location, redirectCount + 1)\n }\n\n if (res.statusCode !== 200) {\n return reject(new Error(`HTTP ${res.statusCode} downloading ${targetUrl}`))\n }\n\n const total = parseInt(res.headers['content-length'] ?? '0', 10)\n let downloaded = 0\n\n const fileStream = fs.createWriteStream(destPath)\n\n res.on('data', (chunk: Buffer) => {\n downloaded += chunk.length\n onProgress?.(downloaded, total)\n })\n\n res.pipe(fileStream)\n fileStream.on('finish', () => resolve(downloaded))\n fileStream.on('error', reject)\n res.on('error', reject)\n }).on('error', reject)\n }\n\n request(url)\n })\n}\n\nasync function computeSha256(filePath: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const hash = createHash('sha256')\n const stream = fs.createReadStream(filePath)\n stream.on('data', (chunk) => hash.update(chunk))\n stream.on('end', () => resolve(hash.digest('hex')))\n stream.on('error', reject)\n })\n}\n","import type { IPythonEnvironment, PythonProbeResult, PythonEnvReady } from '@camstack/types'\nimport { execFile, spawn } from 'node:child_process'\nimport type { ChildProcess } from 'node:child_process'\nimport { promisify } from 'node:util'\nimport * as fs from 'node:fs'\nimport * as path from 'node:path'\n\nconst execFileAsync = promisify(execFile)\n\nexport class PythonEnvManager implements IPythonEnvironment {\n private venvPath: string\n private cachedProbe: PythonProbeResult | null = null\n\n constructor(private readonly dataDir: string) {\n this.venvPath = path.join(dataDir, '.venv')\n }\n\n async probe(): Promise<PythonProbeResult> {\n if (this.cachedProbe) return this.cachedProbe\n\n // Try python3, then python\n for (const cmd of ['python3', 'python']) {\n try {\n const { stdout } = await execFileAsync(cmd, ['--version'])\n const version = stdout.trim().replace('Python ', '')\n const major = parseInt(version.split('.')[0] ?? '0', 10)\n const minor = parseInt(version.split('.')[1] ?? '0', 10)\n\n if (major < 3 || (major === 3 && minor < 10)) continue\n\n // Get path\n const { stdout: pathOut } = await execFileAsync(cmd, ['-c', 'import sys; print(sys.executable)'])\n\n this.cachedProbe = {\n available: true,\n version,\n path: pathOut.trim(),\n }\n return this.cachedProbe\n } catch { continue }\n }\n\n this.cachedProbe = { available: false }\n return this.cachedProbe\n }\n\n async ensure(options: { packages: readonly string[] }): Promise<PythonEnvReady> {\n const probe = await this.probe()\n if (!probe.available || !probe.path) {\n throw new Error('Python 3.10+ is required but not found on this system')\n }\n\n // Create venv if needed\n if (!fs.existsSync(path.join(this.venvPath, 'bin', 'python'))) {\n await execFileAsync(probe.path, ['-m', 'venv', this.venvPath])\n }\n\n const venvPython = path.join(this.venvPath, 'bin', 'python')\n\n // Install packages\n if (options.packages.length > 0) {\n await execFileAsync(venvPython, ['-m', 'pip', 'install', '-q', ...options.packages])\n }\n\n return {\n pythonPath: venvPython,\n venvPath: this.venvPath,\n spawn: (script: string, args: readonly string[]) => {\n return spawn(venvPython, [script, ...args])\n },\n }\n }\n\n spawn(script: string, args: readonly string[]): ChildProcess {\n const venvPython = path.join(this.venvPath, 'bin', 'python')\n if (!fs.existsSync(venvPython)) {\n throw new Error('Python venv not initialized. Call ensure() first.')\n }\n return spawn(venvPython, [script, ...args])\n }\n}\n","import type { AddonDeclaration, AddonPackageManifest, ICamstackAddon } from '@camstack/types'\nimport * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport type { AddonInstaller } from './addon-installer.js'\n\nexport interface RegisteredAddon {\n readonly declaration: AddonDeclaration\n readonly packageName: string\n readonly addonClass: new () => ICamstackAddon\n}\n\nexport class AddonLoader {\n private addons = new Map<string, RegisteredAddon>()\n\n /** Load all addons from an npm package */\n async loadPackage(packageName: string): Promise<void> {\n // Read package.json\n const pkgJsonPath = require.resolve(`${packageName}/package.json`)\n const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8')) as Record<string, unknown>\n const manifest = pkgJson['camstack'] as AddonPackageManifest | undefined\n\n if (!manifest?.addons?.length) {\n throw new Error(`Package ${packageName} has no camstack.addons manifest`)\n }\n\n for (const declaration of manifest.addons) {\n // Dynamic import the addon module\n const entryPath = require.resolve(\n `${packageName}/${declaration.entry.replace('./dist/', '').replace(/\\.js$/, '')}`,\n )\n const mod = (await import(entryPath)) as Record<string, unknown>\n const AddonClass = (mod['default'] ?? mod[Object.keys(mod)[0]!]) as (new () => ICamstackAddon) | undefined\n\n if (!AddonClass) {\n throw new Error(`Addon ${declaration.id} from ${packageName} has no default export`)\n }\n\n this.addons.set(declaration.id, {\n declaration,\n packageName,\n addonClass: AddonClass,\n })\n }\n }\n\n /** Load addon from a direct path (for development/testing) */\n async loadFromPath(addonId: string, modulePath: string, packageName: string): Promise<void> {\n const mod = (await import(modulePath)) as Record<string, unknown>\n const AddonClass = (mod['default'] ?? mod[Object.keys(mod)[0]!]) as (new () => ICamstackAddon) | undefined\n\n if (!AddonClass) {\n throw new Error(`Module ${modulePath} has no default export`)\n }\n\n this.addons.set(addonId, {\n declaration: { id: addonId, entry: modulePath, slot: 'detector' as AddonDeclaration['slot'] },\n packageName,\n addonClass: AddonClass,\n })\n }\n\n /** Get a registered addon by ID */\n getAddon(addonId: string): RegisteredAddon | undefined {\n return this.addons.get(addonId)\n }\n\n /** List all registered addons */\n listAddons(): RegisteredAddon[] {\n return [...this.addons.values()]\n }\n\n /** Check if an addon is registered */\n hasAddon(addonId: string): boolean {\n return this.addons.has(addonId)\n }\n\n /** Create a new instance of an addon (not yet initialized) */\n createInstance(addonId: string): ICamstackAddon {\n const registered = this.addons.get(addonId)\n if (!registered) {\n throw new Error(`Addon \"${addonId}\" is not registered`)\n }\n return new registered.addonClass()\n }\n\n /** Load all installed addon packages from the addon directory */\n async loadAllInstalled(installer: AddonInstaller): Promise<void> {\n const installed = installer.listInstalled()\n for (const pkg of installed) {\n try {\n await this.loadPackageFromPath(pkg.name, pkg.path)\n } catch (error: unknown) {\n // Log but don't fail — one broken addon shouldn't prevent others from loading\n const message = error instanceof Error ? error.message : String(error)\n console.warn(`Failed to load addon package ${pkg.name}: ${message}`)\n }\n }\n }\n\n /** Load addon package from a specific filesystem path */\n async loadPackageFromPath(packageName: string, packagePath: string): Promise<void> {\n const pkgJsonPath = path.join(packagePath, 'package.json')\n const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8')) as Record<string, unknown>\n const manifest = pkgJson['camstack'] as AddonPackageManifest | undefined\n\n if (!manifest?.addons?.length) {\n throw new Error(`Package ${packageName} at ${packagePath} has no camstack.addons manifest`)\n }\n\n for (const declaration of manifest.addons) {\n const entryPath = path.join(packagePath, declaration.entry)\n const mod = (await import(entryPath)) as Record<string, unknown>\n const AddonClass = (mod['default'] ?? mod[Object.keys(mod)[0]!]) as (new () => ICamstackAddon) | undefined\n\n if (!AddonClass) {\n throw new Error(`Addon ${declaration.id} from ${packageName} has no default export`)\n }\n\n this.addons.set(declaration.id, {\n declaration,\n packageName,\n addonClass: AddonClass,\n })\n }\n }\n}\n","import type { ICamstackAddon, AddonContext } from '@camstack/types'\nimport { AddonLoader } from './addon-loader.js'\nimport { createHash } from 'node:crypto'\n\nexport class AddonEngineManager {\n private engines = new Map<string, ICamstackAddon>()\n\n constructor(\n private readonly loader: AddonLoader,\n private readonly baseContext: Omit<AddonContext, 'addonConfig'>,\n ) {}\n\n /**\n * Get or create an addon engine for the given effective config.\n * Cameras with the same addonId + effective config share the same engine.\n */\n async getOrCreateEngine(\n addonId: string,\n globalConfig: Record<string, unknown>,\n cameraOverride?: Record<string, unknown>,\n ): Promise<ICamstackAddon> {\n // Merge global + override\n const effectiveConfig = { ...globalConfig, ...cameraOverride }\n const configKey = `${addonId}:${this.hashConfig(effectiveConfig)}`\n\n const existing = this.engines.get(configKey)\n if (existing) return existing\n\n // Create new instance\n const addon = this.loader.createInstance(addonId)\n await addon.initialize({ ...this.baseContext, addonConfig: effectiveConfig })\n this.engines.set(configKey, addon)\n return addon\n }\n\n /** Get all active engines */\n getActiveEngines(): Map<string, ICamstackAddon> {\n return new Map(this.engines)\n }\n\n /** Shutdown a specific engine by its config key */\n async shutdownEngine(configKey: string): Promise<void> {\n const engine = this.engines.get(configKey)\n if (engine) {\n await engine.shutdown()\n this.engines.delete(configKey)\n }\n }\n\n /** Shutdown all engines */\n async shutdownAll(): Promise<void> {\n for (const [, engine] of this.engines) {\n await engine.shutdown()\n }\n this.engines.clear()\n }\n\n /** Compute a deterministic config key (visible for tests) */\n computeConfigKey(addonId: string, effectiveConfig: Record<string, unknown>): string {\n return `${addonId}:${this.hashConfig(effectiveConfig)}`\n }\n\n private hashConfig(config: Record<string, unknown>): string {\n const sorted = JSON.stringify(config, Object.keys(config).sort())\n return createHash('md5').update(sorted).digest('hex').slice(0, 12)\n }\n}\n","import { execFile } from 'node:child_process'\nimport { promisify } from 'node:util'\nimport * as fs from 'node:fs'\nimport * as path from 'node:path'\n\nconst execFileAsync = promisify(execFile)\n\nexport interface AddonInstallerConfig {\n /** Directory where addons are installed (e.g., ~/.camstack/addons or {dataDir}/addons) */\n readonly addonsDir: string\n /** Builtin packages to auto-install on first boot */\n readonly builtinPackages: readonly string[]\n /** npm registry URL (default: https://registry.npmjs.org) */\n readonly registry?: string\n}\n\nexport interface InstalledPackage {\n readonly name: string\n readonly version: string\n readonly path: string\n}\n\nexport class AddonInstaller {\n constructor(private readonly config: AddonInstallerConfig) {}\n\n /** Initialize addon directory — create if not exists, install builtins if needed */\n async initialize(): Promise<void> {\n await this.ensureAddonDirectory()\n await this.installBuiltins()\n }\n\n /** Ensure addon directory exists with a package.json */\n private async ensureAddonDirectory(): Promise<void> {\n const { addonsDir } = this.config\n fs.mkdirSync(addonsDir, { recursive: true })\n\n const pkgJsonPath = path.join(addonsDir, 'package.json')\n if (!fs.existsSync(pkgJsonPath)) {\n const pkgJson = {\n name: 'camstack-addons',\n version: '1.0.0',\n private: true,\n description: 'CamStack addon packages — managed automatically',\n dependencies: {},\n }\n fs.writeFileSync(pkgJsonPath, JSON.stringify(pkgJson, null, 2))\n }\n }\n\n /** Install builtin packages if not already present */\n private async installBuiltins(): Promise<void> {\n const missing = this.config.builtinPackages.filter(pkg => !this.isInstalled(pkg))\n if (missing.length === 0) return\n\n await this.installPackages(missing)\n }\n\n /** Check if a package is installed */\n isInstalled(packageName: string): boolean {\n const pkgPath = path.join(this.config.addonsDir, 'node_modules', packageName, 'package.json')\n return fs.existsSync(pkgPath)\n }\n\n /** Get installed package info */\n getInstalledPackage(packageName: string): InstalledPackage | null {\n const pkgPath = path.join(this.config.addonsDir, 'node_modules', packageName, 'package.json')\n if (!fs.existsSync(pkgPath)) return null\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')) as { name: string; version: string }\n return {\n name: pkg.name,\n version: pkg.version,\n path: path.dirname(pkgPath),\n }\n }\n\n /** List all installed addon packages (those with camstack.addons in package.json) */\n listInstalled(): InstalledPackage[] {\n const nodeModulesDir = path.join(this.config.addonsDir, 'node_modules')\n if (!fs.existsSync(nodeModulesDir)) return []\n\n const packages: InstalledPackage[] = []\n\n // Check scoped packages (@camstack/*)\n const scopeDirs = fs.readdirSync(nodeModulesDir).filter(d => d.startsWith('@'))\n for (const scope of scopeDirs) {\n const scopePath = path.join(nodeModulesDir, scope)\n if (!fs.statSync(scopePath).isDirectory()) continue\n for (const pkg of fs.readdirSync(scopePath)) {\n const pkgJsonPath = path.join(scopePath, pkg, 'package.json')\n if (!fs.existsSync(pkgJsonPath)) continue\n const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8')) as {\n name: string\n version: string\n camstack?: { addons?: unknown[] }\n }\n if (pkgJson.camstack?.addons) {\n packages.push({ name: pkgJson.name, version: pkgJson.version, path: path.join(scopePath, pkg) })\n }\n }\n }\n\n // Check non-scoped packages\n for (const dir of fs.readdirSync(nodeModulesDir)) {\n if (dir.startsWith('@') || dir.startsWith('.')) continue\n const pkgJsonPath = path.join(nodeModulesDir, dir, 'package.json')\n if (!fs.existsSync(pkgJsonPath)) continue\n const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8')) as {\n name: string\n version: string\n camstack?: { addons?: unknown[] }\n }\n if (pkgJson.camstack?.addons) {\n packages.push({ name: pkgJson.name, version: pkgJson.version, path: path.join(nodeModulesDir, dir) })\n }\n }\n\n return packages\n }\n\n /** Install one or more packages from npm */\n async installPackages(packages: readonly string[]): Promise<void> {\n if (packages.length === 0) return\n\n const args = ['install', '--save', ...packages]\n if (this.config.registry) {\n args.push('--registry', this.config.registry)\n }\n\n await execFileAsync('npm', args, {\n cwd: this.config.addonsDir,\n timeout: 120_000, // 2 min timeout\n })\n\n // npm install --save already updates package.json, but re-read and re-write to normalise formatting\n const pkgJsonPath = path.join(this.config.addonsDir, 'package.json')\n const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8')) as Record<string, unknown>\n fs.writeFileSync(pkgJsonPath, JSON.stringify(pkgJson, null, 2))\n }\n\n /** Uninstall a package */\n async uninstallPackage(packageName: string): Promise<void> {\n // Prevent uninstalling builtins\n if (this.config.builtinPackages.includes(packageName)) {\n throw new Error(`Cannot uninstall builtin package: ${packageName}`)\n }\n\n await execFileAsync('npm', ['uninstall', packageName], {\n cwd: this.config.addonsDir,\n timeout: 60_000,\n })\n }\n\n /** Update a package to latest version */\n async updatePackage(packageName: string): Promise<void> {\n await execFileAsync('npm', ['update', packageName], {\n cwd: this.config.addonsDir,\n timeout: 120_000,\n })\n }\n\n /** Update all packages */\n async updateAll(): Promise<void> {\n await execFileAsync('npm', ['update'], {\n cwd: this.config.addonsDir,\n timeout: 300_000,\n })\n }\n\n /** Get the node_modules path for require/import resolution */\n getNodeModulesPath(): string {\n return path.join(this.config.addonsDir, 'node_modules')\n }\n}\n\n/** Default builtin packages that are auto-installed */\nexport const BUILTIN_PACKAGES: readonly string[] = [\n '@camstack/vision',\n '@camstack/pipeline-analysis',\n '@camstack/benchmark',\n] as const\n","import type { PipelineConfig, PipelineNode } from '@camstack/types'\nimport { AddonLoader } from '../addon/addon-loader.js'\n\nexport interface ValidationIssue {\n readonly step?: string\n readonly addon?: string\n readonly message: string\n readonly severity: 'error' | 'warning'\n}\n\nexport interface ValidationResult {\n readonly valid: boolean\n readonly errors: readonly ValidationIssue[]\n readonly warnings: readonly ValidationIssue[]\n}\n\nexport class PipelineValidator {\n constructor(private readonly loader: AddonLoader) {}\n\n validate(config: PipelineConfig): ValidationResult {\n const errors: ValidationIssue[] = []\n const warnings: ValidationIssue[] = []\n\n // Validate video pipeline\n for (const node of config.video) {\n this.validateNode(node, errors, warnings, [])\n }\n\n // Validate audio\n if (config.audio) {\n this.validateNode(config.audio, errors, warnings, [])\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n }\n }\n\n private validateNode(\n node: PipelineNode,\n errors: ValidationIssue[],\n warnings: ValidationIssue[],\n ancestors: PipelineNode[],\n ): void {\n // Check addon exists\n if (!this.loader.hasAddon(node.addon)) {\n errors.push({\n step: node.step,\n addon: node.addon,\n message: `Addon \"${node.addon}\" is not registered`,\n severity: 'error',\n })\n return\n }\n\n // Check requiredSteps (from addon manifest)\n const registered = this.loader.getAddon(node.addon)\n if (registered) {\n const manifest = registered.declaration\n // Warn if a node appears at root but its addon has inputClasses\n // (This is a simplified check — full implementation would read manifest.requiredSteps)\n void manifest // reserved for future manifest-driven checks\n }\n\n // Validate children recursively\n if (node.children) {\n for (const child of node.children) {\n this.validateNode(child, errors, warnings, [...ancestors, node])\n }\n }\n }\n}\n","import type {\n FrameInput,\n CropInput,\n PipelineConfig,\n PipelineNode,\n PipelineResult,\n StepResult,\n DetectorOutput,\n CropperOutput,\n ClassifierOutput,\n SpatialDetection,\n PipelineSlot,\n ICamstackAddon,\n} from '@camstack/types'\nimport { AddonEngineManager } from '../addon/addon-engine-manager.js'\nimport { randomUUID } from 'node:crypto'\n\nexport class PipelineRunner {\n constructor(\n private readonly engineManager: AddonEngineManager,\n private readonly addonConfigs: Map<string, Record<string, unknown>>, // addonId → global config\n ) {}\n\n async run(frame: FrameInput, config: PipelineConfig): Promise<PipelineResult> {\n const startTime = performance.now()\n const results: StepResult[] = []\n const timings: Record<string, number> = {}\n\n // Execute video pipeline root nodes\n for (const rootNode of config.video) {\n await this.executeNode(rootNode, frame, null, results, timings)\n }\n\n // Execute audio node if present (independent)\n if (config.audio) {\n await this.executeNode(config.audio, frame, null, results, timings)\n }\n\n return {\n results,\n totalMs: performance.now() - startTime,\n timings,\n frameTimestamp: frame.timestamp,\n }\n }\n\n private async executeNode(\n node: PipelineNode,\n frame: FrameInput,\n parentDetection: { det: SpatialDetection; resultId: string } | null,\n results: StepResult[],\n timings: Record<string, number>,\n ): Promise<void> {\n const resultId = randomUUID()\n const stepStart = performance.now()\n\n try {\n // Get or create engine for this addon\n const globalConfig = this.addonConfigs.get(node.addon) ?? {}\n const engine = await this.engineManager.getOrCreateEngine(\n node.addon, globalConfig, node.configOverride,\n )\n\n // Determine slot type and execute\n let output: DetectorOutput | CropperOutput | ClassifierOutput\n\n if (parentDetection) {\n // This is a child node — needs crop input\n const cropInput: CropInput = {\n frame,\n roi: parentDetection.det.bbox,\n parentDetection: parentDetection.det,\n }\n\n // Try cropper first, then classifier, then detector\n if ('crop' in engine && typeof (engine as unknown as Record<string, unknown>)['crop'] === 'function') {\n output = await (engine as unknown as { crop: (input: CropInput) => Promise<CropperOutput> }).crop(cropInput)\n } else if ('classify' in engine && typeof (engine as unknown as Record<string, unknown>)['classify'] === 'function') {\n output = await (engine as unknown as { classify: (input: CropInput) => Promise<ClassifierOutput> }).classify(cropInput)\n } else if ('detect' in engine && typeof (engine as unknown as Record<string, unknown>)['detect'] === 'function') {\n // Detector child (e.g., object-detection triggered by motion)\n output = await (engine as unknown as { detect: (input: FrameInput) => Promise<DetectorOutput> }).detect(frame)\n } else {\n throw new Error(`Addon \"${node.addon}\" has no detect/crop/classify method`)\n }\n } else {\n // Root node — full frame\n if ('detect' in engine && typeof (engine as unknown as Record<string, unknown>)['detect'] === 'function') {\n output = await (engine as unknown as { detect: (input: FrameInput) => Promise<DetectorOutput> }).detect(frame)\n } else if ('classify' in engine && typeof (engine as unknown as Record<string, unknown>)['classify'] === 'function') {\n // Audio classifier at root\n const rootCropInput: CropInput = {\n frame,\n roi: { x: 0, y: 0, w: frame.width, h: frame.height },\n parentDetection: { class: '', originalClass: '', score: 1, bbox: { x: 0, y: 0, w: frame.width, h: frame.height } },\n }\n output = await (engine as unknown as { classify: (input: CropInput) => Promise<ClassifierOutput> }).classify(rootCropInput)\n } else {\n throw new Error(`Addon \"${node.addon}\" has no detect/classify method`)\n }\n }\n\n const stepMs = performance.now() - stepStart\n\n // Determine slot type from output shape\n const slot: PipelineSlot =\n 'detections' in output ? 'detector' :\n 'crops' in output ? 'cropper' :\n 'classifier'\n\n const stepResult: StepResult = {\n addon: node.addon,\n slot,\n output,\n parentResultId: parentDetection?.resultId,\n resultId,\n inferenceMs: output.inferenceMs,\n preprocessMs: 0,\n totalMs: stepMs,\n }\n results.push(stepResult)\n timings[node.step] = stepMs\n\n // Process children\n if (node.children?.length) {\n const detections: readonly SpatialDetection[] =\n 'detections' in output ? output.detections :\n 'crops' in output ? output.crops :\n []\n\n // For each detection, find children with matching inputClasses and execute\n await this.executeChildren(node.children, frame, detections, resultId, results, timings)\n }\n } catch (error: unknown) {\n const stepMs = performance.now() - stepStart\n const message = error instanceof Error ? error.message : String(error)\n results.push({\n addon: node.addon,\n slot: 'detector',\n output: { detections: [], inferenceMs: 0, modelId: '' },\n parentResultId: parentDetection?.resultId,\n resultId,\n inferenceMs: 0,\n preprocessMs: 0,\n totalMs: stepMs,\n error: {\n code: 'ADDON_ERROR',\n message,\n childrenSkipped: true,\n },\n })\n }\n }\n\n private async executeChildren(\n children: readonly PipelineNode[],\n frame: FrameInput,\n parentDetections: readonly SpatialDetection[],\n parentResultId: string,\n results: StepResult[],\n timings: Record<string, number>,\n ): Promise<void> {\n // For each parent detection, run all matching children in parallel\n const promises: Promise<void>[] = []\n\n for (const detection of parentDetections) {\n for (const child of children) {\n // TODO: Check inputClasses matching from addon manifest\n // For now, run all children on all detections (caller configures tree correctly)\n promises.push(\n this.executeNode(child, frame, { det: detection, resultId: parentResultId }, results, timings),\n )\n }\n }\n\n await Promise.allSettled(promises)\n }\n}\n"],"mappings":"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","names":["fs","path","fs","path","import_node_crypto","import_node_child_process","import_node_util","fs","path","execFileAsync","import_node_crypto"]}
|