@trillboards/edge-sdk 0.2.150 → 0.2.151

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.
@@ -10,7 +10,7 @@ name = "trillboards-detector"
10
10
  # constant, a `labels.py`-only change survives `uv tool install` AND
11
11
  # `uv tool install --force`; move the version and a bare `uv tool install`
12
12
  # reinstalls. See `stamp_version.py`.
13
- version = "0.2.0+src.6d43cf061068"
13
+ version = "0.2.0+src.dd895d9aa2fd"
14
14
  description = "On-device object-detector service for the Trillboards BYO-CCTV connector (loopback HTTP, ONNX Runtime)."
15
15
  requires-python = ">=3.10"
16
16
 
@@ -99,6 +99,31 @@ class TestLocalExecution(unittest.TestCase):
99
99
  with self.assertRaisesRegex(RuntimeError, "bad input"):
100
100
  s.run([], {})
101
101
 
102
+ def test_failed_cpu_construction_retains_session_and_retries_next_request(self):
103
+ r = Runtime(gpu_failure="gpu failed")
104
+ model = b"immutable original model"
105
+ s = LocalOrtSession(r, model, None)
106
+ gpu_session = s._session
107
+ original_constructor = r.InferenceSession
108
+
109
+ def fail_cpu(*args, **kwargs):
110
+ if kwargs["providers"] == [CPU]:
111
+ raise MemoryError("temporary CPU allocation failure")
112
+ return original_constructor(*args, **kwargs)
113
+
114
+ r.InferenceSession = fail_cpu
115
+ with self.assertRaisesRegex(MemoryError, "temporary CPU allocation failure"):
116
+ s.run([], {"frame": "first"})
117
+ self.assertIs(s._session, gpu_session)
118
+ self.assertIs(s._model_bytes, model)
119
+ self.assertTrue(s._cuda_active)
120
+ self.assertEqual(s.acceleration["providers"], [CUDA, CPU])
121
+ r.InferenceSession = original_constructor
122
+ captured = {"frame": "retry"}
123
+ self.assertIs(s.run([], captured), captured)
124
+ self.assertEqual(s.acceleration["backend"], "cpu")
125
+ self.assertIsNone(s._model_bytes)
126
+
102
127
  def test_ort_internal_runtime_demotion_updates_actual_backend(self):
103
128
  s = LocalOrtSession(Runtime(demote=True), b"model", None)
104
129
  s.run([], {})
@@ -13,5 +13,5 @@ human sets.
13
13
  """
14
14
 
15
15
  BASE_VERSION = "0.2.0"
16
- SOURCE_FINGERPRINT = "6d43cf061068"
17
- VERSION = "0.2.0+src.6d43cf061068"
16
+ SOURCE_FINGERPRINT = "dd895d9aa2fd"
17
+ VERSION = "0.2.0+src.dd895d9aa2fd"
@@ -57,16 +57,17 @@ class LocalOrtSession:
57
57
  LOG.info("[detector] local execution: %s", self.acceleration)
58
58
 
59
59
  def _cpu(self, reason):
60
- # A failed GPU attempt must not keep its allocation while CPU starts.
61
- self._session = None
62
- self._cuda_active = False
63
- self.fallback_reason = reason[:1000]
64
- self._acceleration = {"requested": self.requested, "backend": "initializing_cpu",
65
- "providers": [], "fallback_reason": self.fallback_reason}
66
- LOG.warning("[detector] GPU unavailable; CPU fallback: %s", self.fallback_reason)
67
- self._session = self._runtime.InferenceSession(
60
+ # Construct before replacing the live session. If CPU construction also
61
+ # fails (for example under memory pressure), retain the GPU session and
62
+ # immutable bytes so the next request can retry, rather than publishing
63
+ # a permanently broken None session as ready in the model registry.
64
+ LOG.warning("[detector] GPU unavailable; CPU fallback: %s", reason[:1000])
65
+ cpu_session = self._runtime.InferenceSession(
68
66
  self._model_bytes, sess_options=self._options, providers=[CPU]
69
67
  )
68
+ self._session = cpu_session
69
+ self._cuda_active = False
70
+ self.fallback_reason = reason[:1000]
70
71
  self._model_bytes = None
71
72
  self._publish_acceleration()
72
73
 
@@ -61,9 +61,9 @@ function Register-Connector([string]$Root) {
61
61
  update indefinitely. The provisioner serializes replacement, verifies its
62
62
  installed stamp and chooses one CPU/CUDA dependency set. Pairings stay intact.
63
63
 
64
- BEST EFFORT, ALWAYS. The detector is a cost optimisation: without it every
65
- frame goes to the VLM exactly as it does today. It must never be able to fail
66
- a customer's upgrade, so every path here returns quietly.
64
+ BEST EFFORT, ALWAYS. Restart the connector before this potentially network-
65
+ bound work. Detector-backed profiles report the unavailable local detector
66
+ until it is repaired; this must not fail the connector upgrade or pairing.
67
67
  #>
68
68
  function Update-DetectorTask([string]$Root) {
69
69
  try {
@@ -194,10 +194,12 @@ try {
194
194
  Assert-ConnectorVersion $InstallDir
195
195
  Register-Connector $InstallDir
196
196
  Assert-ConnectorScheduled
197
- Update-DetectorTask $InstallDir
198
197
  if (Test-Path (Join-Path $InstallDir "trillboards.config.json")) {
199
198
  Start-ScheduledTask -TaskName "TrillboardsEdge" -ErrorAction Stop
200
199
  }
200
+ # Runtime provisioning can download CUDA packages. Resume the connector
201
+ # before that best-effort work so capture is not held behind the download.
202
+ Update-DetectorTask $InstallDir
201
203
 
202
204
  Remove-Item -Recurse -Force $previousDir -ErrorAction SilentlyContinue
203
205
  Remove-Item -Recurse -Force $StagingDir -ErrorAction SilentlyContinue
package/dist/EdgeAgent.js CHANGED
@@ -44,7 +44,7 @@ const edge_ads_1 = require("@trillboards/edge-ads");
44
44
  const CommandRouter_1 = require("./CommandRouter");
45
45
  const config_1 = require("./config");
46
46
  const dataDir_1 = require("./dataDir");
47
- const SDK_VERSION = '0.2.150';
47
+ const SDK_VERSION = '0.2.151';
48
48
  class EdgeAgent extends events_1.EventEmitter {
49
49
  constructor(config, deps) {
50
50
  super();
@@ -31,7 +31,7 @@ export interface DiagnosticReport {
31
31
  skipped: number;
32
32
  };
33
33
  }
34
- declare const SDK_VERSION = "0.2.150";
34
+ declare const SDK_VERSION = "0.2.151";
35
35
  declare function checkNodeVersion(): CheckResult;
36
36
  declare function checkPlatform(): CheckResult;
37
37
  declare function checkMemory(): CheckResult;
package/dist/diagnose.js CHANGED
@@ -63,7 +63,7 @@ const localNetworkAccess_1 = require("./localNetworkAccess");
63
63
  // ---------------------------------------------------------------------------
64
64
  // SDK version — mirrors package.json; kept in sync by CI
65
65
  // ---------------------------------------------------------------------------
66
- const SDK_VERSION = '0.2.150';
66
+ const SDK_VERSION = '0.2.151';
67
67
  exports._SDK_VERSION = SDK_VERSION;
68
68
  // ---------------------------------------------------------------------------
69
69
  // ANSI helpers (no external deps)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trillboards/edge-sdk",
3
- "version": "0.2.150",
3
+ "version": "0.2.151",
4
4
  "description": "Composable cross-platform Edge AI SDK for audience sensing on DOOH/CTV devices",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",