tirtc-device-builder 0.7.3 → 0.8.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.
Files changed (34) hide show
  1. package/.codex-plugin/plugin.json +1 -1
  2. package/CHANGELOG.md +26 -0
  3. package/README.md +61 -16
  4. package/bin/tirtc-device-builder.js +33 -1
  5. package/package.json +1 -1
  6. package/skills/tirtc-esp32-builder/SKILL.md +150 -39
  7. package/skills/tirtc-esp32-builder/USAGE.md +17 -2
  8. package/skills/tirtc-esp32-builder/VERSION +1 -1
  9. package/skills/tirtc-esp32-builder/agents/openai.yaml +1 -1
  10. package/skills/tirtc-esp32-builder/assets/board-audio-contract.example.json +3 -0
  11. package/skills/tirtc-esp32-builder/assets/board-identity.example.json +16 -0
  12. package/skills/tirtc-esp32-builder/assets/developer-intake-prompt.md +3 -3
  13. package/skills/tirtc-esp32-builder/assets/hardware-ir-v2.example.json +9 -1
  14. package/skills/tirtc-esp32-builder/assets/lckfb-szpi-esp32s3-portable-prompt.md +5 -5
  15. package/skills/tirtc-esp32-builder/assets/report-template.md +10 -2
  16. package/skills/tirtc-esp32-builder/assets/tirtc-runtime-contract.example.json +13 -0
  17. package/skills/tirtc-esp32-builder/knowledge/board-registry.json +4 -0
  18. package/skills/tirtc-esp32-builder/references/audio-contract.md +8 -0
  19. package/skills/tirtc-esp32-builder/references/board-knowledge.md +72 -0
  20. package/skills/tirtc-esp32-builder/references/capability-rules.md +11 -1
  21. package/skills/tirtc-esp32-builder/references/environment.md +21 -2
  22. package/skills/tirtc-esp32-builder/references/firmware-delivery.md +83 -0
  23. package/skills/tirtc-esp32-builder/references/hardware-ir.md +12 -3
  24. package/skills/tirtc-esp32-builder/references/porting-risks.md +29 -1
  25. package/skills/tirtc-esp32-builder/references/product-controls.md +76 -0
  26. package/skills/tirtc-esp32-builder/references/reporting.md +8 -4
  27. package/skills/tirtc-esp32-builder/references/runtime-contract.md +12 -2
  28. package/skills/tirtc-esp32-builder/references/tirtc-platform.md +92 -0
  29. package/skills/tirtc-esp32-builder/references/workflow.md +42 -11
  30. package/skills/tirtc-esp32-builder/scripts/audio_contract.py +2 -0
  31. package/skills/tirtc-esp32-builder/scripts/board_registry.py +677 -0
  32. package/skills/tirtc-esp32-builder/scripts/firmware_identity.py +180 -0
  33. package/skills/tirtc-esp32-builder/scripts/hardware_ir.py +147 -8
  34. package/skills/tirtc-esp32-builder/scripts/runtime_contract.py +122 -1
@@ -0,0 +1,92 @@
1
+ # TiRTC and ThingConnect platform contract
2
+
3
+ Read this reference when integrating the C SDK, selecting an ESP32 target, or
4
+ implementing H5, AI, device-call or WeChat VoIP.
5
+
6
+ ## Authoritative sources
7
+
8
+ - TiRTC documentation: <https://docs.tange.ai/products/tirtc/>
9
+ - C API: <https://docs.tange.ai/products/tirtc/api-reference/c.html>
10
+ - C SDK integration: <https://docs.tange.ai/products/tirtc/guides/sdk-integration/c.html>
11
+ - ESP32-S3 notes: <https://docs.tange.ai/products/tirtc/guides/integration-notes/espressif/esp32-s3.html>
12
+ - ESP32-P4 notes: <https://docs.tange.ai/products/tirtc/guides/integration-notes/espressif/esp32-p4.html>
13
+ - ThingConnect reference platform: <https://github.com/tangeai/tirtc-server-example>
14
+ - Demo platform: <https://demo-open.tange-ai.com/>
15
+
16
+ Use the locked SDK header/build contract and a pinned ThingConnect commit during
17
+ generation. Public pages explain the contract but do not replace the exact files
18
+ used by a build.
19
+
20
+ ## SDK lifecycle
21
+
22
+ TiRTC is one process-wide runtime. The exact selected header governs API and
23
+ option availability. For SDK 2.3.0 the important order is:
24
+
25
+ 1. Set `TIRTC_OPT_MAX_SEND_BUFFER` before `TiRtcInit()` when overriding it.
26
+ 2. Call `TiRtcInit()` once.
27
+ 3. Set `TIRTC_OPT_DEVICE_SECRET_KEY`, `TIRTC_OPT_CLIENT_ID`, the discovered
28
+ service endpoint, and applicable network options before `TiRtcStart()`.
29
+ 4. Call `TiRtcStart(device_id, &callbacks)` once and wait for
30
+ `TIRTC_EVENT_SYS_STARTED`; return value zero only accepts the request.
31
+ 5. Establish or accept connections, then use `TiRtcSendVideoStream()` and
32
+ `TiRtcSendAudioStream()` with the selected complete-frame contract.
33
+ 6. Stop sessions and connections through deferred lifecycle work before the one
34
+ final `TiRtcStop()` / `TiRtcUninit()` sequence.
35
+
36
+ The callback table and its context outlive the SDK runtime. Callback payloads
37
+ are borrowed; copy required data into bounded application-owned storage before
38
+ returning.
39
+
40
+ ## Product features
41
+
42
+ ### H5 live view and talkback
43
+
44
+ The device starts as a listener, accepts the H5 connection, sends the selected
45
+ audio/video streams, receives talkback, and handles refresh/key-frame requests.
46
+ Browser rendering and audible talkback are HIL evidence.
47
+
48
+ ### AI intercom
49
+
50
+ Obtain the current AI connection parameters, connect, send `start_session`,
51
+ validate the authoritative session ID and input/output formats, then start
52
+ media. Remote or local `end_session` converges through the runtime task and
53
+ restores the H5 baseline.
54
+
55
+ ### Device-to-device call
56
+
57
+ Follow the pinned `device-call.md`: contact authorization, `POST
58
+ /v1/call/request`, incoming MQTT routing, accept through `POST
59
+ /v1/call/device/info`, reject/cancel/hangup, room recovery and `TiRtcConnect`.
60
+ Expose `call <device_id> [video|audio]` only after those paths and conflict rules
61
+ are implemented.
62
+
63
+ ### WeChat VoIP
64
+
65
+ Follow the pinned `device-voip.md`: report the device media profile, maintain the
66
+ authorized contact list, route WeChat MQTT events, and use `POST
67
+ /v1/voip/device/call` for device-originated calls. `wxcall [N] [video|audio]`
68
+ selects an authorized contact; it is not a direct SDK API. Mini-program
69
+ authorization and plugin behavior are separate platform acceptance evidence.
70
+
71
+ ## Simulator before hardware
72
+
73
+ For the four-feature portfolio, use the pinned Linux C reference implementation
74
+ with file-backed media to prove platform credentials, HTTP/MQTT fields,
75
+ connection tokens, commands and the session arbiter before replacing media with
76
+ board drivers. Record this separately from ESP32 L1-L7 evidence.
77
+
78
+ The managed ESP32-S3 starter may expose fewer businesses than the full reference
79
+ repository. Missing generated modules are implementation work, not permission to
80
+ drop a requested feature or call it verified.
81
+
82
+ ## ESP32 targets
83
+
84
+ The current managed generator and Device Kit automate ESP32-S3. Official SDK
85
+ 2.3.0 also provides a distinct ESP32-P4 package. P4 needs ESP-IDF 5.5.4, matching
86
+ RISC-V toolchain/build contract, PSRAM, and an evidenced network path such as
87
+ ESP-Hosted with C6/C61 or Ethernet. P4 and S3 archives are not interchangeable.
88
+
89
+ Use FreeRTOS tasks, bounded queues and explicit memory capabilities. PSRAM is
90
+ suitable for large media, fixed pools and eligible background stacks; internal
91
+ RAM remains necessary for DMA descriptors/buffers, ISR-visible state, control
92
+ objects and allocations required while flash cache is unavailable.
@@ -4,13 +4,18 @@
4
4
 
5
5
  ### Registered board
6
6
 
7
- Use this branch when a board and exact hardware revision already have a Hardware IR plus a matching board media adapter.
8
-
9
- 1. Validate and assess the saved Hardware IR against the requested features.
10
- 2. Confirm that its BSP, ESP-IDF, TiRTC SDK, and adapter revisions are still resolvable.
11
- 3. Generate a new starter project without overwriting an existing path.
12
- 4. Install the matching board adapter and configuration overlay.
13
- 5. Build, optionally flash, execute the requested acceptance levels, and issue a fresh report.
7
+ Use this branch only when `board_registry.py match` returns `exact` with
8
+ `safe_registered_reuse=true` and the package has a Hardware IR plus matching
9
+ board adapter.
10
+
11
+ 1. Recheck every required runtime probe and reject a changed sensor/codec as a
12
+ new variant.
13
+ 2. Validate and assess the saved Hardware IR against the requested features.
14
+ 3. Confirm that its BSP, ESP-IDF, TiRTC SDK, business protocol, and adapter
15
+ revisions are still resolvable.
16
+ 4. Generate a new starter project without overwriting an existing path.
17
+ 5. Install the matching board adapter and configuration overlay.
18
+ 6. Build, optionally flash, execute the requested acceptance levels, and issue a fresh report.
14
19
 
15
20
  The branch is complete when the new run has its own build and verification evidence; an older board report is provenance, not proof of the new artifact.
16
21
 
@@ -18,10 +23,16 @@ The branch is complete when the new run has its own build and verification evide
18
23
 
19
24
  Use this branch when the user supplies a board model, vendor URL, schematic, BOM, pin map, BSP, datasheets, photographs, or peripheral example projects without a verified adapter.
20
25
 
21
- 1. Resolve the full model, module, PCB marking, and hardware revision. Treat different revisions as different boards.
26
+ 1. Create `board-identity.json`, combine the developer's full model/PCB marking
27
+ with safe SoC/component probes, and query the board registry. Treat different
28
+ revisions or conflicting required probes as different variants. A probable
29
+ or component match supplies hypotheses only.
22
30
  2. Freeze the user-supplied product contract: selected video profile, audio/stream formats, duplex/AEC policy, supported Wi-Fi credential methods, selected onboarding method, transport staging, output path, and mutation boundary. Use `unknown` where the prompt lacks an answer.
23
31
  3. Prefer official schematic/BOM and BSP facts. For a PDF schematic, inspect page labels and net names; prefer an exported netlist, pin CSV, or vendor board definition when available.
24
32
  4. Cross-check critical pins, clocks, power enables, reset lines, sensor/codec variants, ESP-IDF version, resource ownership, and onboarding behavior across at least two independent artifacts when possible.
33
+ For buttons, power keys and enclosure labels, identify the full physical
34
+ product including carrier/PMIC layers; a working control missing from the
35
+ baseboard schematic is a variant or evidence gap, not proof that it is absent.
25
36
  5. Create the Hardware IR v2. Use `null` for unknown facts and retain contradictory values as an explicit issue instead of selecting one silently. Store concrete board values in the IR/adapter rather than Skill files.
26
37
  6. Validate and run the intake assessment. Classify unresolved facts by their next evidence source: source, implementation, build, HIL, or user input. Ask only for `user_blocked` facts that prevent a safe design. SoftAP is optional when another evidenced Wi-Fi credential method is available, keeps credentials outside source, and defines reprovisioning.
27
38
  7. When hardware identity, wiring, product contracts, and an evidenced resource plan reach `READY_TO_PORT`, generate the starter and implement the board adapter. Generate a compile-safe adapter by default when remaining uncertainty is implementation-, build-, or HIL-resolvable. Stop at the IR/report only when missing user evidence or an incompatible dependency makes a safe implementation impossible.
@@ -46,13 +57,16 @@ Read only the documents for the active branch, but read each selected document c
46
57
  - ESP32 starter or adapter work: `device-sim/device-sim-esp32/README.md`, `device-sim/ESP32_STARTER.md`, the selected SDK package README, and the generated template README.
47
58
  - H5 live view or talkback: `device-h5-live.md`.
48
59
  - AI intercom: `device-ai.md`.
60
+ - Device-to-device call: `device-call.md` and the applicable API reference.
61
+ - WeChat VoIP: `device-voip.md`, the mini-program integration document, and the
62
+ applicable API reference.
49
63
  - H5/AI switching, delayed callbacks, ownership, or timeouts: `device-session-model.md` and `device-session-arbiter.md`.
50
64
  - Onboarding, binding, MQTT, token, or identity: `device-integration.md`.
51
65
  - Public HTTP field or error changes: `api-reference.md` and `error-response-policy.md`.
52
66
 
53
67
  ## Generation and board seam
54
68
 
55
- The runtime-facing `starter_media` interface stays stable. A reusable board integration should implement an internal `BoardMediaAdapterV1`-style adapter owned by `starter_media` rather than editing H5, AI, `starter_runtime`, or `starter_tirtc` for each board.
69
+ The runtime-facing `starter_media` interface stays stable. A reusable board integration should implement an internal `BoardMediaAdapterV1`-style adapter owned by `starter_media` rather than editing H5, AI, CALL, VOIP, `starter_runtime`, or `starter_tirtc` for each board.
56
70
 
57
71
  The adapter owns:
58
72
 
@@ -62,13 +76,30 @@ The adapter owns:
62
76
  - DMA buffers, hardware clocks, power, reset, GPIO, refresh/key-frame requests, and realtime task allocation;
63
77
  - bounded stop, resource release, and generation-aware flushing.
64
78
 
65
- The stable modules own the discovered TiRTC service endpoint, stream IDs, negotiated/contracted formats, TiRTC callback copying, connection handles, session generation, and H5/AI sequencing. SDK lifecycle changes such as disconnect run in a worker/state-machine context, never directly inside an SDK callback.
79
+ The stable modules own the discovered TiRTC service endpoint, stream IDs,
80
+ negotiated/contracted formats, HTTP/MQTT business fields, TiRTC callback copying,
81
+ connection handles, pending calls, monotonic deadlines, session generation, and
82
+ H5/AI/CALL/VOIP sequencing. SDK lifecycle changes such as disconnect run in a
83
+ worker/state-machine context, never directly inside an SDK callback.
84
+
85
+ A separate product-controls adapter owns physical input setup, debounce,
86
+ boot-held suppression and gestures. It queues bounded intents into the stable
87
+ runtime. It never manipulates TiRTC/session state directly or keeps a competing
88
+ session Boolean. Prefer an atomic runtime-owned toggle intent; when only explicit
89
+ start/stop intents exist, follow
90
+ [product-controls.md](product-controls.md) for snapshot mapping and authoritative
91
+ runtime revalidation.
66
92
 
67
93
  ## Verification loop
68
94
 
69
95
  Use a bounded loop per layer: diagnose one failing invariant, make the smallest correction, and rerun that layer before moving forward. Change one high-risk variable per HIL comparison. Turn reusable invariants into tests or post-link gates. Stop and report when the remaining failure requires unavailable hardware, credentials, a new SDK binary, a public protocol change, or a user choice.
70
96
 
71
- For every generated H5/AI project, validate `tirtc-runtime-contract.json` and run `install_runtime_gate.py <project>` before the ordinary build. Audio and video projects additionally install their media gates. A build that bypasses any applicable gate is not `BUILD_VERIFIED`.
97
+ For every generated H5/AI/call/VoIP project, validate `tirtc-runtime-contract.json` and run `install_runtime_gate.py <project>` before the ordinary build. Audio and video projects additionally install their media gates. AI/call/VoIP also require the full-duplex AEC result from the audio gate. A build that bypasses any applicable gate is not `BUILD_VERIFIED`.
98
+
99
+ When CALL or VOIP is requested, the runtime contract must also bind the project
100
+ to the pinned business protocol and unified session arbiter. First prove those
101
+ flows with the Linux C simulator. Simulator success establishes the protocol
102
+ baseline but cannot replace the ESP32 build or HIL levels.
72
103
 
73
104
  Run the assessor once per layer:
74
105
 
@@ -383,6 +383,8 @@ def verify_contract(contract_path: Path, project_path: Path) -> dict[str, Any]:
383
383
  f"simultaneous={shared.get('directions_simultaneous')} "
384
384
  f"aec={aec.get('enabled', False)}"
385
385
  ),
386
+ "simultaneous_capture_playback": shared.get("directions_simultaneous") is True,
387
+ "echo_cancellation_enabled": aec.get("enabled") is True,
386
388
  "inputs": inputs,
387
389
  "errors": errors,
388
390
  }