@blueharford/scrypted-spatial-awareness 0.6.27 → 0.6.28

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/plugin.zip CHANGED
Binary file
@@ -35410,31 +35410,38 @@ class SpatialReasoningEngine {
35410
35410
  // Load balancing for multiple LLMs
35411
35411
  llmDevices = [];
35412
35412
  llmIndex = 0;
35413
- /** Find LLM devices - uses configured device or auto-discovers all for load balancing */
35413
+ /** Find LLM devices - uses configured devices or auto-discovers all for load balancing */
35414
35414
  async findAllLlmDevices() {
35415
35415
  if (this.llmSearched)
35416
35416
  return;
35417
35417
  this.llmSearched = true;
35418
35418
  try {
35419
- // If a specific LLM device is configured, use only that one
35420
- if (this.config.llmDeviceId) {
35421
- const device = systemManager.getDeviceById(this.config.llmDeviceId);
35422
- if (device?.interfaces?.includes('ChatCompletion')) {
35423
- const providerTypeEnum = this.detectProviderType(device);
35424
- this.llmDevices.push({
35425
- device: device,
35426
- id: this.config.llmDeviceId,
35427
- name: device.name || this.config.llmDeviceId,
35428
- providerType: providerTypeEnum,
35429
- lastUsed: 0,
35430
- errorCount: 0,
35431
- });
35432
- this.console.log(`[LLM] Using configured LLM: ${device.name}`);
35433
- return;
35419
+ // If specific LLM devices are configured, use only those
35420
+ if (this.config.llmDeviceIds && this.config.llmDeviceIds.length > 0) {
35421
+ for (const deviceId of this.config.llmDeviceIds) {
35422
+ const device = systemManager.getDeviceById(deviceId);
35423
+ if (device?.interfaces?.includes('ChatCompletion')) {
35424
+ const providerTypeEnum = this.detectProviderType(device);
35425
+ this.llmDevices.push({
35426
+ device: device,
35427
+ id: deviceId,
35428
+ name: device.name || deviceId,
35429
+ providerType: providerTypeEnum,
35430
+ lastUsed: 0,
35431
+ errorCount: 0,
35432
+ });
35433
+ this.console.log(`[LLM] Using configured LLM: ${device.name}`);
35434
+ }
35435
+ else {
35436
+ this.console.warn(`[LLM] Configured device ${deviceId} not found or doesn't support ChatCompletion`);
35437
+ }
35434
35438
  }
35435
- else {
35436
- this.console.warn(`[LLM] Configured device ${this.config.llmDeviceId} not found or doesn't support ChatCompletion`);
35439
+ if (this.llmDevices.length > 0) {
35440
+ this.console.log(`[LLM] Using ${this.llmDevices.length} configured LLM provider(s)`);
35441
+ return;
35437
35442
  }
35443
+ // Fall through to auto-discovery if none of the configured devices worked
35444
+ this.console.warn('[LLM] No configured devices available, falling back to auto-discovery');
35438
35445
  }
35439
35446
  // Auto-discover all LLM devices for load balancing
35440
35447
  for (const id of Object.keys(systemManager.getSystemState())) {
@@ -35451,7 +35458,7 @@ class SpatialReasoningEngine {
35451
35458
  lastUsed: 0,
35452
35459
  errorCount: 0,
35453
35460
  });
35454
- this.console.log(`[LLM] Found: ${device.name}`);
35461
+ this.console.log(`[LLM] Auto-discovered: ${device.name}`);
35455
35462
  }
35456
35463
  }
35457
35464
  if (this.llmDevices.length === 0) {
@@ -37343,7 +37350,7 @@ class TrackingEngine {
37343
37350
  // Initialize spatial reasoning engine
37344
37351
  const spatialConfig = {
37345
37352
  enableLlm: config.useLlmDescriptions,
37346
- llmDeviceId: config.llmDeviceId,
37353
+ llmDeviceIds: config.llmDeviceIds,
37347
37354
  enableLandmarkLearning: config.enableLandmarkLearning ?? true,
37348
37355
  landmarkConfidenceThreshold: config.landmarkConfidenceThreshold ?? 0.7,
37349
37356
  contextCacheTtl: 60000, // 1 minute cache
@@ -39458,11 +39465,12 @@ class SpatialAwarenessPlugin extends sdk_1.ScryptedDeviceBase {
39458
39465
  group: 'MQTT Integration',
39459
39466
  },
39460
39467
  // Integrations
39461
- llmDevice: {
39462
- title: 'LLM Provider',
39468
+ llmDevices: {
39469
+ title: 'LLM Providers',
39463
39470
  type: 'device',
39471
+ multiple: true,
39464
39472
  deviceFilter: `interfaces.includes('ChatCompletion')`,
39465
- description: 'Select the LLM plugin to use for smart descriptions (e.g., OpenAI, Anthropic, Ollama)',
39473
+ description: 'Select one or more LLM providers for smart descriptions. Multiple providers will be load-balanced.',
39466
39474
  group: 'Integrations',
39467
39475
  },
39468
39476
  defaultNotifiers: {
@@ -39568,7 +39576,7 @@ class SpatialAwarenessPlugin extends sdk_1.ScryptedDeviceBase {
39568
39576
  loiteringThreshold: (this.storageSettings.values.loiteringThreshold || 3) * 1000,
39569
39577
  objectAlertCooldown: (this.storageSettings.values.objectAlertCooldown || 30) * 1000,
39570
39578
  useLlmDescriptions: this.storageSettings.values.useLlmDescriptions ?? true,
39571
- llmDeviceId: this.storageSettings.values.llmDevice || undefined,
39579
+ llmDeviceIds: this.parseLlmDevices(),
39572
39580
  llmDebounceInterval: (this.storageSettings.values.llmDebounceInterval || 30) * 1000,
39573
39581
  llmFallbackEnabled: this.storageSettings.values.llmFallbackEnabled ?? true,
39574
39582
  llmFallbackTimeout: (this.storageSettings.values.llmFallbackTimeout || 3) * 1000,
@@ -39610,6 +39618,34 @@ class SpatialAwarenessPlugin extends sdk_1.ScryptedDeviceBase {
39610
39618
  }
39611
39619
  }
39612
39620
  }
39621
+ /** Parse LLM devices from settings - handles both array and single value formats */
39622
+ parseLlmDevices() {
39623
+ const value = this.storageSettings.values.llmDevices;
39624
+ if (!value)
39625
+ return undefined;
39626
+ // Handle array format
39627
+ if (Array.isArray(value)) {
39628
+ const filtered = value.filter(Boolean);
39629
+ return filtered.length > 0 ? filtered : undefined;
39630
+ }
39631
+ // Handle JSON string format
39632
+ if (typeof value === 'string') {
39633
+ try {
39634
+ const parsed = JSON.parse(value);
39635
+ if (Array.isArray(parsed)) {
39636
+ const filtered = parsed.filter(Boolean);
39637
+ return filtered.length > 0 ? filtered : undefined;
39638
+ }
39639
+ // Single device ID string
39640
+ return value ? [value] : undefined;
39641
+ }
39642
+ catch {
39643
+ // Not JSON, treat as single device ID
39644
+ return value ? [value] : undefined;
39645
+ }
39646
+ }
39647
+ return undefined;
39648
+ }
39613
39649
  // ==================== DeviceProvider Implementation ====================
39614
39650
  async getDevice(nativeId) {
39615
39651
  let device = this.devices.get(nativeId);
@@ -39886,7 +39922,7 @@ class SpatialAwarenessPlugin extends sdk_1.ScryptedDeviceBase {
39886
39922
  key === 'llmDebounceInterval' ||
39887
39923
  key === 'llmFallbackEnabled' ||
39888
39924
  key === 'llmFallbackTimeout' ||
39889
- key === 'llmDevice' ||
39925
+ key === 'llmDevices' ||
39890
39926
  key === 'enableTransitTimeLearning' ||
39891
39927
  key === 'enableConnectionSuggestions' ||
39892
39928
  key === 'enableLandmarkLearning' ||