@esp-vision/device-core 0.5.0 → 0.5.1

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/CHANGELOG.md CHANGED
@@ -1,6 +1,12 @@
1
1
  # Changelog
2
2
 
3
- ## [Unreleased]
3
+ ## 0.5.1
4
+
5
+ ### Fixed
6
+
7
+ - Make packaged execution-deadline regressions deterministic with a controlled clock, including expiry before VM entry, and keep installation guidance independent of temporary publication state.
8
+
9
+ ## 0.5.0
4
10
 
5
11
  ### Changed
6
12
 
package/README.md CHANGED
@@ -19,10 +19,10 @@
19
19
  | Visibility | Public; installation needs no npm login |
20
20
  | Source location | `host/device-core` in the ESP-VISION firmware repository |
21
21
 
22
- The latest public npm release is **0.4.2**. This source prepares **0.5.0 (not yet published)**: Core becomes an SDK-only package, the management CLI moves to `@esp-vision/device-cli`, and Python execution/file reads have no aggregate deadline unless configured. Pin the exact package version and verify it exists in the public registry before installing. Until publication, use a tarball packed from an exact reviewed source commit. CI authenticates with the protected `NPM_PUBLISH_TOKEN` and verifies that `npm whoami` returns `esp-vision` before publishing. Tokens are not part of this package or its documentation.
22
+ The **0.5.x** package line is SDK-only: the management CLI lives in `@esp-vision/device-cli`, and Python execution/file reads have no aggregate deadline unless configured. Pin the exact package version and verify it exists in the public registry before installing. For unpublished source changes, use a tarball packed from an exact reviewed source commit. CI authenticates with the protected `NPM_PUBLISH_TOKEN` and verifies that `npm whoami` returns `esp-vision` before publishing. Tokens are not part of this package or its documentation.
23
23
 
24
24
  ```sh
25
- npm install --save-exact @esp-vision/device-core@0.5.0 --registry=https://registry.npmjs.org/
25
+ npm install --save-exact @esp-vision/device-core@0.5.1 --registry=https://registry.npmjs.org/
26
26
  ```
27
27
 
28
28
  EV-MUX v4 firmware is required. A v3 hello is rejected with `VERSION_MISMATCH`; applications should ask the user to update firmware. Core has no runtime dependency on the IDE, Agent, DOM or Node serial libraries. The host supplies the physical byte transport and discovery adapter; Core owns protocol parsing, session negotiation, REPL coordination and device operations.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@esp-vision/device-core",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "Shared EV-MUX, framed REPL, device session, and action contracts for ESP Vision clients.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "title": "ESP Vision Device Actions",
4
- "deviceCoreVersion": "0.5.0",
4
+ "deviceCoreVersion": "0.5.1",
5
5
  "schemaVersion": 1,
6
6
  "actions": [
7
7
  {
@@ -341,18 +341,45 @@ test('failed stop does not claim execution has finished', async () => {
341
341
  fixture.session.close()
342
342
  })
343
343
 
344
- test('bounded Agent execution still times out and sends a shared interrupt', async () => {
344
+ test('bounded Agent execution still times out and sends a shared interrupt', async (t) => {
345
+ t.mock.timers.enable({ apis: ['setTimeout'] })
345
346
  const fixture = executionFixture()
347
+ t.after(() => fixture.session.close())
348
+ // Isolate the running-script deadline from the separately covered upload
349
+ // and REPL setup. A real 30 ms startup budget races CI scheduling.
350
+ fixture.session.stopForRepl = async () => true
351
+ fixture.session.writeScript = async () => {}
346
352
  let started
347
353
  const starting = new Promise(resolve => { started = resolve })
348
354
  const done = fixture.session.runScript('/trial.py', 'while True: pass', { timeout: 30, onStarted: started })
349
355
  const rejected = assert.rejects(done, (error) => error.code === 'SCRIPT_TIMEOUT')
350
356
  await starting
357
+ t.mock.timers.tick(30)
351
358
  await rejected
352
359
  assert.equal(fixture.session.scriptRunSnapshot(), null)
353
- await new Promise(resolve => setTimeout(resolve, 0))
360
+ await new Promise(resolve => setImmediate(resolve))
354
361
  assert.ok(fixture.requests.some(({ metadata, payload }) => metadata.method === 'device.control' && payload.action === 'stop'))
355
- fixture.session.close()
362
+ })
363
+
364
+ test('bounded start handles reject when the deadline precedes VM entry', async (t) => {
365
+ t.mock.timers.enable({ apis: ['setTimeout'] })
366
+ const fixture = executionFixture({ deferStart: true })
367
+ t.after(() => fixture.session.close())
368
+ fixture.session.stopForRepl = async () => true
369
+ fixture.session.writeScript = async () => {}
370
+ let started = false
371
+ const starting = fixture.session.startScript('/trial.py', undefined, {
372
+ inlineCompletion: true,
373
+ timeout: 30,
374
+ onStarted() { started = true },
375
+ })
376
+ const rejected = assert.rejects(starting, { code: 'SCRIPT_TIMEOUT' })
377
+ await new Promise(resolve => setImmediate(resolve))
378
+ t.mock.timers.tick(30)
379
+ await rejected
380
+ assert.equal(started, false)
381
+ assert.equal(fixture.session.scriptRunSnapshot(), null)
382
+ assert.equal(fixture.session.runStarting, false)
356
383
  })
357
384
 
358
385
  test('VM reset and disconnect settle interactive completion and allow the next VM run', async () => {