Skip to content

feat(provider-tizen): add Samsung Tizen TV provider plugin - #4168

Open
alimek wants to merge 2 commits into
callstack:mainfrom
alimek:feat/provider-tizen
Open

alimek wants to merge 2 commits into
callstack:mainfrom
alimek:feat/provider-tizen

Conversation

@alimek

@alimek alimek commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Adds @agent-device/tizen, an optional provider plugin that drives web apps on Samsung Tizen TVs on the shared @agent-device/tv-cdp layer from #4098. The TV enters as a plugin-owned Android TV device (tizen:<sdb serial>): open kills the app, debug-launches it with sdb shell 0 debug, forwards the DevTools port with sdb forward and drives the page over CDP.

Two commits:

  • fix(tv-cdp): TvConnection gains a canonical id (the sdb serial; for webOS the ip:port its ares entry reaches) that keys leases and sessions, so two aliases cannot both hold one TV. close and listApps carry the request signal, tunnel removal is awaited and reported, and shutdown fences new leases.
  • feat(provider-tizen): the plugin, scope as webOS v1. Cancel reaches every sdb step and removes the forward.
agent-device plugins add @agent-device/tizen
export AGENT_DEVICE_SESSION=checkout-tv
agent-device connect tizen --device 192.0.2.10
agent-device open com.example.app

40 files. Also: catalog entry, help line, docs page; the packed smoke names its session. Before merge, a maintainer publishes the npm placeholder and sets the trusted publisher. No linked issue.

Validation

Tested SHA 496bd62fc, on main at 541099107; head c6092f265 adds a shutdown test and a webOS endpoint simplification (197/197 affected package tests).

  • check:affected --run: 14/15 stages; unit 17101/17103. Failures are the known committed-source-tree flake and an Android manifest.test.ts timeout that passes alone.
  • Changed-line coverage 94.32% (216/229), CRAP clean, fuzz-worker 11/11; packed smoke passes for tizen and webos.
  • Live on a Tizen 9.0 TV and an LG webOS 22 TV: the review's evidence list, in the comments below.

Risks: experimental; no CI device lane.

🤖 Generated with Claude Code

@vercel

vercel Bot commented Nov 2, 2026

Copy link
Copy Markdown

@alimek is attempting to deploy a commit to the Callstack Team on Vercel.

A member of the Team first needs to authorize it.

@thymikee

thymikee commented Nov 2, 2026

Copy link
Copy Markdown
Member

I read the Tizen plugin at 31e9317 and found two defects and a gap in live evidence. The only failing check is Vercel, which is waiting for a team member to authorize a deploy from the fork, so it never built and is not caused by this change. I found no conflicts. I could not run a TV or sdb, so I reviewed the code only and could not reproduce the live claims in the PR body.

A cancelled or timed-out open keeps running on Tizen. The connection is launch: async (appId) => await tv.launch(appId) at runtime.ts:47, which drops the signal that TvConnection.launch receives. Then sdb.ts:168-186 runs was_kill, the 2s sleep, the debug launch and pollUntilSettled without it, and the sdb layer uses node:child_process directly instead of the host-kit command layer that the webOS plugin uses (ares.ts:3,26-28,51). A cancelled open can keep going for about 2 minutes: it still kills the app, spawns sdb shell 0 debug and creates a forward. A retry in that window runs a second was_kill and debug launch on the same app, which is the race the KILL_SETTLE_MS comment warns about. The sdb calls also do not appear in request diagnostics. The rule: every vendor-tool process and wait that a TvConnection runs for a request goes through host-kit's runCmd/runCmdBackground and honours the request signal, including closing a forward when an abort lands after it exists. The launch path in sdb.ts enumerates the sites. Once that is done, the ENOENT branch in toolError can go, because runCmd already returns TOOL_MISSING.

Two leases can hold the same TV at once. sdbSerial (sdb.ts:59-62) treats 192.0.2.10 and 192.0.2.10:26101 as the same TV, but the TvConnection name at runtime.ts:46 is the raw requested string, and tv-cdp uses that name for the session map and the DEVICE_IN_USE check. So --device 192.0.2.10, --device 192.0.2.10:26101 and no --device can give different names for one TV, skip the refusal, and let one session's open kill the app the other is attached to. Is a separate identity field on TvConnection (the resolved sdb serial) enough here, used by tv-cdp for sessions, leases and the holder check, while name stays the daemon-facing name? I did not trace how the daemon selects the leased device by name, so this shape depends on that.

The docs and help say the forward is removed when the lease ends, but removal is fire-and-forget with errors swallowed (sdb.ts:154), and the forward lives in the sdb server, so a leak outlives the daemon. The PR body lists happy-path commands without output. After the fixes above, please attach live output at the new head showing sdb forward --list empty after disconnect, after an open cancelled mid debug-launch, and after a failed open (app not installed, typed COMMAND_FAILED). Please also show open while the app is already running, an unreachable TV with the typed error and elapsed time, and sdb missing returning TOOL_MISSING.

Not blocking, and fine to take or leave: runtime.test.ts covers parsers, SDK lookup and serial resolution but not launch, so extending the fake sdb to answer shell 0 debug and record forward/forward --remove would let a test assert removal on the no-page path and on abort; toolError in tools.ts and the HostEnv type duplicate the webOS aresError and HostEnv, so once sdb uses runCmd the mapping and the type could live once in tv-cdp; and freeLocalPort has a small race between closing the probe port and the forward, while launch always waits 2s even when nothing was running, so a retry on bind failure and polling app state would help.

Could the Tizen layer get smaller by routing sdb through runCmd/runCmdBackground as ares.ts does, so the hand-rolled spawn, timer and settled state machine becomes a background command polled with the request signal? I looked for a further cut across the stack and found none, since tv-cdp is the right shared owner. This depends on #4098 landing first, or absorbing the shared error-mapping move and the identity field.

Before merge, make the Tizen launch and close path cancellable through the command layer, key lease exclusivity on the canonical serial, and attach the live cleanup and failure-path evidence.

This review covers 31e9317. The newer head 3d82dda changes only tv-cdp page-interactor.ts and its test, which the points above do not touch.

@thymikee

thymikee commented Nov 2, 2026

Copy link
Copy Markdown
Member

I re-read the Tizen code at 3d82dda. The Tizen commit is unchanged by the rebase, so the points in my earlier review (#4168 (comment)) still stand:

  • A cancelled or timed-out open keeps driving the TV, because launch at runtime.ts:47 drops the request signal and the sdb steps in sdb.ts:168-178 run on raw node:child_process instead of host-kit runCmd/runCmdBackground. The launch, kill and listApps paths should all honour the signal, and an abort after the forward exists should close it.
  • Lease exclusivity can be bypassed: 192.0.2.10 and 192.0.2.10:26101 resolve to one sdb serial, but tv-cdp keys sessions, leases and the DEVICE_IN_USE check on the typed name. One identity field on TvConnection (the sdb serial for Tizen, the ares device name for webOS) used by tv-cdp for those three places would give exclusivity one owner; that move would need to land in feat(provider-webos): add LG webOS TV provider plugin #4098 first or be absorbed here.
  • No live output yet. After the fixes, please attach: sdb forward --list empty after disconnect, after an open cancelled mid debug-launch, and after a failed open (COMMAND_FAILED); open with the app already running; a second connect tizen --device <ip>:26101 refused with DEVICE_IN_USE while --device <ip> holds the TV; an unreachable TV with the typed error and elapsed time; and sdb missing returning TOOL_MISSING.

The non-blocking notes from the earlier review also still apply. The only failing check is the Vercel fork-deploy authorization gate, so no build ran and it is not caused by this change.

@alimek
alimek force-pushed the feat/provider-tizen branch from 3d82dda to 50e9dcd Compare November 2, 2026 13:07
@thymikee

thymikee commented Nov 2, 2026

Copy link
Copy Markdown
Member

I re-read 50e9dcd. The Tizen commit is unchanged by this rebase onto the new #4098 base, so the points in my earlier review (#4168 (comment)) still stand: open drops the request signal at runtime.ts:47 and the sdb steps run outside host-kit runCmd, lease exclusivity is keyed on the typed name rather than the resolved sdb serial (runtime.ts:46), and there is no live forward-cleanup evidence yet.

One addition: #4098 now re-wraps only failures with details.processExitError === true in aresError, so cancel and timeout keep their typed reason. When sdb moves to runCmd, the same rule fits here, and that mapping could live once in tv-cdp.

The only failing check is the Vercel fork-deploy authorization gate, so no build ran.

@alimek
alimek force-pushed the feat/provider-tizen branch 3 times, most recently from a5638c3 to 9df0236 Compare November 2, 2026 18:20
@thymikee

thymikee commented Nov 2, 2026

Copy link
Copy Markdown
Member

The cancellation and physical-TV ownership defects remain at 9df0236. Compared with the earlier review, no runtime or test change fixes either issue; the existing tests do not cover real Tizen launch cancellation or aliased TV ownership. This assessment uses static review of the supplied evidence and source; no tests or device runs were performed.

The Tizen connection wrapper still drops the request signal passed by tv-cdp. Launch, close and listApps can continue vendor work after cancellation, and launch can create or retain a forward and race a retry. The owning TvConnection contract and Tizen adapter must carry the request signal through all three operations. Vendor processes must use host-kit runCmd/runCmdBackground, waits must support cancellation, and abort or failure must remove any created forward independently of the aborted signal. Preserve typed cancellation and timeout errors; rewrite only processExitError failures.

The connection identity still keeps the requested name even when sdbSerial resolves IP and IP:26101 to the same TV. Named sessions using those aliases, or implicit selection, can bypass DEVICE_IN_USE and cold-launch over another session's app. TvConnection must expose a canonical identity: the resolved sdb serial for Tizen and the ares device name for webOS. tv-cdp must use it consistently for session and lease keys, holder checks, release and device-to-session lookup, while retaining the requested name for daemon selection. Verify through the production lease route that a second named session using the other alias receives DEVICE_IN_USE.

Forward removal still discards errors, so the older successful command list does not prove that the persistent sdb forward is removed. After both fixes, provide commands, source SHA, device and output showing this session's forward absent from sdb forward --list after disconnect, cancellation during debug launch, cancellation after forward creation while waiting for a page, and a failed open returning COMMAND_FAILED. Also show opening an already-running app; two explicitly named sessions using IP and IP:26101 with the second refused as DEVICE_IN_USE; an unreachable TV returning a typed failure with elapsed time; and missing sdb returning TOOL_MISSING.

The sole failing check appears unrelated: Vercel rejected fork-deploy authorization before any build route ran, consistent with the bot's team-authorization request, so it did not exercise the website changes. No conflicts are known. Before merge, fix cancellation and canonical identity, then provide the complete live evidence and validation receipt at the resulting head; Vercel authorization remains external.

@alimek
alimek force-pushed the feat/provider-tizen branch from 9df0236 to 1fae4c1 Compare November 2, 2026 19:25
@alimek
alimek marked this pull request as ready for review November 2, 2026 19:26

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

7 issues found across 28 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/provider-tizen/package.json">

<violation number="1" location="packages/provider-tizen/package.json:2">
P2: This new package is publishable as soon as the PR merges, before the required npm placeholder transition is completed. Add `"private": true` until the placeholder is published under a non-`latest` tag and the release workflow is configured as its trusted publisher, then remove it in the follow-up change.

(Based on your team's feedback about new public package publishing sequence.) [8d2d0e70-d7f9-4595-b79d-236327ddda02]</violation>
</file>

<file name="packages/provider-tizen/README.md">

<violation number="1" location="packages/provider-tizen/README.md:68">
P2: This instruction is incorrect: `connect` allocates the provider lease and already lists/connects the TV over `sdb`; `open` only launches the app and attaches to its DevTools page. Update the sentence so users do not expect device errors or network activity to be deferred until `open`.</violation>
</file>

<file name="packages/provider-tizen/src/tools.ts">

<violation number="1" location="packages/provider-tizen/src/tools.ts:33">
P2: Automatic SDK discovery cannot find `sdb.exe` on Windows because this candidate omits the executable extension. Include the platform-specific executable name (or resolve the candidate using the host command layer), otherwise Windows users must supply `sdbPath` manually despite the documented SDK discovery.</violation>
</file>

<file name="packages/provider-tizen/src/sdb.ts">

<violation number="1" location="packages/provider-tizen/src/sdb.ts:155">
P2: `kill` implements close without a cancellation signal, so a canceled `close` can wait for SDB's full 60-second timeout; thread the request signal through the close contract and this call.</violation>

<violation number="2" location="packages/provider-tizen/src/sdb.ts:162">
P2: This catch hides every non-cancellation `was_kill` failure, including transport errors; ignore only the documented “app not running” result and propagate genuine SDB failures.</violation>

<violation number="3" location="packages/provider-tizen/src/sdb.ts:173">
P2: The inspector probe ignores the launch signal and deadline, so a stalled `/json` fetch can exceed `timeoutMs` and delay Ctrl-C by five seconds; make `listTargets` signal-aware or race this probe with the request signal.</violation>
</file>

<file name="packages/provider-tizen/src/runtime.ts">

<violation number="1" location="packages/provider-tizen/src/runtime.ts:33">
P2: A failed `sdb connect` for an unreachable requested TV escapes as `COMMAND_FAILED` instead of the `DEVICE_NOT_FOUND` error this resolver constructs. Catch connection-command failures, recheck the device list, and preserve tool-missing errors so callers receive the intended device-selection failure.</violation>
</file>

Reply with feedback, questions, or to request a fix.

View guided diff | Re-trigger cubic

Comment thread packages/provider-tizen/src/runtime.ts Resolved
@@ -0,0 +1,49 @@
{
"name": "@agent-device/tizen",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: This new package is publishable as soon as the PR merges, before the required npm placeholder transition is completed. Add "private": true until the placeholder is published under a non-latest tag and the release workflow is configured as its trusted publisher, then remove it in the follow-up change.

(Based on your team's feedback about new public package publishing sequence.) [8d2d0e70-d7f9-4595-b79d-236327ddda02]

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At packages/provider-tizen/package.json, line 2:

<comment>This new package is publishable as soon as the PR merges, before the required npm placeholder transition is completed. Add `"private": true` until the placeholder is published under a non-`latest` tag and the release workflow is configured as its trusted publisher, then remove it in the follow-up change.

(Based on your team's feedback about new public package publishing sequence.) [8d2d0e70-d7f9-4595-b79d-236327ddda02]</comment>

<file context>
@@ -0,0 +1,49 @@
+{
+  "name": "@agent-device/tizen",
+  "version": "0.21.36-dev",
+  "type": "module",
</file context>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keeping the package public in this PR. With "private": true, the layering scan requires its bundled workspace imports under dependencies, and then the packed tarball cannot install (@agent-device/host-kit@0.0.0 is not on npm). We would like a maintainer to publish the placeholder and configure the trusted publisher before merge, as was done for webOS. Leaving this open for that.

Comment thread src/commands/schema/cli-help-tv.ts Resolved
Comment thread website/docs/docs/tizen.md Resolved
Comment thread packages/provider-tizen/README.md Resolved
Comment thread packages/provider-tizen/src/sdb.ts Resolved
Comment thread packages/provider-tizen/src/sdb.ts Resolved
Comment thread packages/provider-tizen/src/sdb.ts Resolved
Comment thread packages/provider-tizen/src/sdb.ts Resolved
Comment thread packages/provider-tizen/src/runtime.ts Resolved
@alimek
alimek force-pushed the feat/provider-tizen branch from 1fae4c1 to 6c8b3ef Compare November 2, 2026 20:11
@alimek

alimek commented Nov 2, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the re-review. Both defects are fixed at 6c8b3ef61, in two commits:

  • 03ccfa888 fix(tv-cdp): key TV leases by canonical identity and carry the request signal
  • 6c8b3ef61 feat(provider-tizen): add Samsung Tizen TV provider plugin

Cancellation. TvConnection.launch, close and listApps all take the request signal, and tv-cdp passes it through. Tizen runs sdb through host-kit runCmd/runCmdStreaming, and the kill, the settle, the debug launch, the forward and the page wait are all cancellable. A cancel or failure after the forward exists awaits forward --remove with no signal. If the removal fails, the launch error keeps its code and message and gains details.forwardRemoval. Only processExitError failures are rewritten; cancels and timeouts pass through typed.

Identity. TvConnection.id is the canonical TV: the resolved sdb serial for Tizen, the ares device name for webOS. tv-cdp keys sessions, leases, the holder check, release and device-to-session lookup on it. device.name keeps the requested name for daemon selection, so the device id becomes tizen:192.0.2.10:26101 for --device 192.0.2.10. Covered through the lease route in provider-tizen/src/runtime.test.ts and live below.

Forward removal. PageTunnel.close() now resolves once the vendor tunnel is gone and rejects when removal fails. close, a failed open and release (disconnect) await it. A page that drops in the background keeps the failure on the session until the next close or disconnect reports it. webOS close waits for ares-inspect to exit.

Validation at 6c8b3ef61: pnpm check:affected --run (exact commit) passed 15 of 16 stages; unit ran 17096 of 17098 green, and the two failures are the known fill-verification and committed-source-tree flakes outside this change. Changed-line coverage 95.43% (188/197), CRAP clean, fuzz-worker 11/11; the packed-plugin smoke passes for tizen and webos.

Live, Tizen (Samsung TV, Tizen 9.0, sdb 4.2.36 from the VS Code Tizen extension). Source is the working tree that became 6c8b3ef61. The TV is shown as 192.0.2.10, the app as com.example.app, and an app that is not installed as com.example.missing; 192.0.2.99 is a TEST-NET address with no TV.

Tizen output
Connected successfully with Samsung Tizen.

$ agent-device open com.example.app
Opened: com.example.app
(exit 0)
$ sdb forward --list
SERIAL              	LOCAL     	REMOTE
192.0.2.10:26101 	tcp:58212 	tcp:40433

$ agent-device appstate
Foreground app: com.example.app
(exit 0)

$ agent-device open com.example.app
Opened: com.example.app
(exit 0)
$ sdb forward --list
SERIAL              	LOCAL     	REMOTE
192.0.2.10:26101 	tcp:58283 	tcp:39209

Connected successfully with Samsung Tizen.

$ agent-device open com.example.missing
Error (COMMAND_FAILED): sdb debug com.example.missing exited without a port
Hint: Check that com.example.missing is installed on the TV.
(exit 1)
$ sdb forward --list
SERIAL              	LOCAL     	REMOTE

$ agent-device open com.example.app   # Ctrl-C once sdb debug is running
$ pgrep -fl 'shell 0 debug'
68868 sdb -s 192.0.2.10:26101 shell 0 debug com.example.app
(exit 130)
$ sdb forward --list
SERIAL              	LOCAL     	REMOTE
$ pgrep -fl 'shell 0 debug'
(none)

$ agent-device open com.example.app   # Ctrl-C once the forward exists
$ sdb forward --list
SERIAL              	LOCAL     	REMOTE
192.0.2.10:26101 	tcp:58701 	tcp:36083
(exit 130)
$ sdb forward --list
SERIAL              	LOCAL     	REMOTE
$ pgrep -fl 'shell 0 debug'
(none)

$ agent-device open com.example.app
Opened: com.example.app
(exit 0)
$ sdb forward --list
SERIAL              	LOCAL     	REMOTE
192.0.2.10:26101 	tcp:58763 	tcp:34447

$ agent-device disconnect
Disconnected remote session "checkout-tv".
(exit 0)
$ sdb forward --list
SERIAL              	LOCAL     	REMOTE
$ pgrep -fl 'shell 0 debug'
(none)

$ AGENT_DEVICE_SESSION=tv-a agent-device connect tizen --device 192.0.2.10
Connected successfully with Samsung Tizen.
Verified: Tizen TVs are reached over sdb when a session opens.
Device: 192.0.2.10 — allocated on first device command
App: configured app — configured
No live device session has been created. Run apps to inspect uploaded assets without allocating; open <uploaded-asset-name> creates the instance.
Next:
(exit 0)

$ AGENT_DEVICE_SESSION=tv-a agent-device open com.example.app
Opened: com.example.app
(exit 0)

$ AGENT_DEVICE_SESSION=tv-b agent-device connect tizen --device 192.0.2.10:26101
Connected successfully with Samsung Tizen.
Verified: Tizen TVs are reached over sdb when a session opens.
Device: 192.0.2.10:26101 — allocated on first device command
App: configured app — configured
No live device session has been created. Run apps to inspect uploaded assets without allocating; open <uploaded-asset-name> creates the instance.
Next:
(exit 0)

$ AGENT_DEVICE_SESSION=tv-b agent-device open com.example.app
Error (DEVICE_IN_USE): Tizen TV 192.0.2.10:26101 is held by another lease
Hint: Disconnect the session that holds the TV, or wait for its lease to expire.
(exit 1)

$ AGENT_DEVICE_SESSION=tv-a agent-device appstate
Foreground app: com.example.app
(exit 0)

$ AGENT_DEVICE_SESSION=tv-b agent-device disconnect
Disconnected remote session "tv-b".
(exit 0)

$ AGENT_DEVICE_SESSION=tv-a agent-device disconnect
Disconnected remote session "tv-a".
(exit 0)
$ sdb forward --list
SERIAL              	LOCAL     	REMOTE

# unreachable TV

$ AGENT_DEVICE_SESSION=tv-c agent-device connect tizen --device 192.0.2.99
Connected successfully with Samsung Tizen.
Verified: Tizen TVs are reached over sdb when a session opens.
Device: 192.0.2.99 — allocated on first device command
App: configured app — configured
No live device session has been created. Run apps to inspect uploaded assets without allocating; open <uploaded-asset-name> creates the instance.
Next:
(exit 0)

$ AGENT_DEVICE_SESSION=tv-c agent-device open com.example.app
Error (DEVICE_NOT_FOUND): sdb could not connect to the Tizen TV 192.0.2.99:26101
Hint: Check that the TV is on and in Developer Mode with this host IP set as the developer IP.
(exit 1)
elapsed: 1.3 s

$ AGENT_DEVICE_SESSION=tv-c agent-device disconnect
Disconnected remote session "tv-c".
(exit 0)

# sdb missing at the configured path (fresh daemon)
plugin options: [{'sdbPath': '/nonexistent/tizen-sdk/sdb'}]
$ agent-device connect tizen --device 192.0.2.99
Connected successfully with Samsung Tizen.
Verified: Tizen TVs are reached over sdb when a session opens.
(exit 0)
$ agent-device open com.example.app
Error (TOOL_MISSING): sdb is not installed at the configured path
Hint: Install the VS Code Tizen extension and run its Set Up step, set TIZEN_SDK to the SDK data directory, or set the plugin option sdbPath.
(exit 1)

Live, webOS (LG 32LQ63006LA, webOS TV 22), same source. The TV is shown as living-room; attic is not registered with ares-setup-device.

webOS output
$ pgrep -fl ares-inspect

$ agent-device connect webos --device living-room
Connected successfully with LG webOS.
Verified: webOS TVs are read from ares-setup-device when a session opens.
Device: living-room — allocated on first device command
App: configured app — configured
No live device session has been created. Run apps to inspect uploaded assets without allocating; open <uploaded-asset-name> creates the instance.
Next:
(exit 0)

$ agent-device open com.example.app
Opened: com.example.app
(exit 0)
$ pgrep -fl ares-inspect
ares-inspect -d living-room -a com.example.app

$ agent-device appstate
Foreground app: com.example.app
(exit 0)

$ agent-device open com.example.app
Opened: com.example.app
(exit 0)
$ pgrep -fl ares-inspect
ares-inspect -d living-room -a com.example.app

$ agent-device open com.example.app --relaunch
Opened: com.example.app
(exit 0)
$ pgrep -fl ares-inspect
ares-inspect -d living-room -a com.example.app

$ agent-device apps
Showing user-installed apps or deferred provider app assets. Use --all to include system apps on a live device.
Ares Hosted App (com.sdk.ares.hostedapp)
Example (com.example.other)
Example (dev) (com.example.app)
(exit 0)

$ agent-device open com.example.missing
Error (COMMAND_FAILED): ares-launch failed: ares-launch ERR! [com.webos.applicationManager failure]: luna-send command failed <not exist>
Hint: Check that the TV is on, in Developer Mode, and registered with ares-setup-device.
(exit 1)
$ pgrep -fl ares-inspect

$ agent-device close com.example.app
Closed: checkout-tv
(exit 0)
$ pgrep -fl ares-inspect

$ AGENT_DEVICE_SESSION=checkout-tv agent-device open com.example.app   # Ctrl-C once ares-inspect is running
$ pgrep -fl ares-inspect
ares-inspect -d living-room -a com.example.app
(exit 130)
$ pgrep -fl ares-inspect
(none)

$ AGENT_DEVICE_SESSION=checkout-tv agent-device open com.example.app
Opened: com.example.app
(exit 0)
$ pgrep -fl ares-inspect
ares-inspect -d living-room -a com.example.app

$ AGENT_DEVICE_SESSION=second-tv agent-device connect webos --device living-room
Connected successfully with LG webOS.
Verified: webOS TVs are read from ares-setup-device when a session opens.
Device: living-room — allocated on first device command
App: configured app — configured
(exit 0)

$ AGENT_DEVICE_SESSION=second-tv agent-device open com.example.app
Error (DEVICE_IN_USE): webOS TV living-room is held by another lease
Hint: Disconnect the session that holds the TV, or wait for its lease to expire.
(exit 1)

$ AGENT_DEVICE_SESSION=checkout-tv agent-device appstate
Foreground app: com.example.app
(exit 0)

$ AGENT_DEVICE_SESSION=second-tv agent-device disconnect
Disconnected remote session "second-tv".
(exit 0)

$ AGENT_DEVICE_SESSION=checkout-tv agent-device disconnect
Disconnected remote session "checkout-tv".
(exit 0)
$ pgrep -fl ares-inspect
(none)

# TV unknown to ares-setup-device

$ AGENT_DEVICE_SESSION=third-tv agent-device connect webos --device attic
Connected successfully with LG webOS.
Verified: webOS TVs are read from ares-setup-device when a session opens.
Device: attic — allocated on first device command
App: configured app — configured
(exit 0)

$ AGENT_DEVICE_SESSION=third-tv agent-device open com.example.app
Error (DEVICE_NOT_FOUND): No webOS TV named attic in ares-setup-device
Hint: Add the TV with ares-setup-device, or pass --device <name>.
(exit 1)
elapsed: 0.4 s

$ AGENT_DEVICE_SESSION=third-tv agent-device disconnect
Disconnected remote session "third-tv".
(exit 0)
plugin options: [{'aresBin': '/nonexistent/webos-cli/bin'}]
$ agent-device connect webos --device living-room
Connected successfully with LG webOS.
Verified: webOS TVs are read from ares-setup-device when a session opens.
(exit 0)
$ agent-device open com.example.app
Error (TOOL_MISSING): ares-setup-device is not installed or not on PATH
Hint: Install the webOS CLI (npm install -g @webos-tools/cli), or set the plugin option aresBin to the directory that holds it.
(exit 1)

The Vercel check still needs team authorization for fork deploys.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 13 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

View guided diff | Re-trigger cubic

Comment thread packages/provider-webos/src/runtime.ts Resolved
Comment thread packages/tv-cdp/src/runtime.ts Resolved
Comment thread packages/tv-cdp/src/runtime.ts Resolved
Comment thread packages/tv-cdp/src/page-interactor.ts Resolved
Comment thread packages/provider-webos/src/ares.ts Resolved
Comment thread packages/tv-cdp/src/runtime.ts Resolved
Comment thread packages/provider-tizen/src/sdb.ts Resolved
Comment thread packages/provider-tizen/src/sdb.ts Resolved
@thymikee

thymikee commented Nov 2, 2026

Copy link
Copy Markdown
Member

Both defects from the earlier review (#4168 (comment)) are fixed at 6c8b3ef, and I found no new blocking problems in the code. The Tizen and webOS live output is author-reported; I could not reproduce it without a TV, sdb or ares. It covers disconnect, a failed open and both cancel points, but not a Tizen close <appId> removing the forward, which only sdb.test.ts:83 covers with a fake sdb. Smoke Tests is still running; it exercises the default platform runtimes, which this diff does not touch. Vercel failed at fork-deploy team authorization before any build, so it did not check the website changes. Before merge, keep "private": true in packages/provider-tizen/package.json until the npm placeholder and trusted publisher exist (or a maintainer does those steps), let Smoke Tests finish green, and get Vercel fork authorization.

Not blocking, and fine to take or leave: when a failed tunnel removal coincides with another failure, finally in close (packages/tv-cdp/src/page-interactor.ts:233) and the released branch of attachPage (lines 43-47) throw the removal error instead of the primary one, while failAfter in sdb.ts keeps the primary error and adds details.forwardRemoval; could tv-cdp follow one rule, the failAfter shape, in close, attachPage and the Tizen launch?

On the open inline threads: the cubic-dev-ai threads on the package being public (#4168 (comment)), webOS device identity (#4168 (comment)) and the shutdown fence (#4168 (comment), which I did not trace) still stand. Seven lower-priority threads also still apply or are benign. These do not apply and can be resolved: the alias lease id (#4168 (comment)) is fixed at head with the IP alias refused as DEVICE_IN_USE; the deferred allocation in README (#4168 (comment)) is correct as written; the dropped non-cancel was_kill failure (#4168 (comment)) resurfaces typed from the debug launch; the kill signal (#4168 (comment)) is wired through kill(appId, signal); the unreachable TV connect (#4168 (comment)) gives a typed DEVICE_NOT_FOUND; the lease dropped before teardown (#4168 (comment)) cannot touch a new tunnel because the pending removal targets only its own forward; and the shutdown allSettled (#4168 (comment)) has no request left to report to.

@alimek
alimek force-pushed the feat/provider-tizen branch from 6c8b3ef to 496bd62 Compare November 3, 2026 09:03
@alimek

alimek commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

Thanks. This round is at 496bd62fc (34e0743a8 fix(tv-cdp), 496bd62fc feat(provider-tizen)).

From your comment

  • One error rule. withTunnelRemoval (exported by tv-cdp) keeps the primary error and adds details.tunnelRemoval. close, both branches of attachPage and the Tizen launch all use it. A removal that only fails alone still fails close or disconnect with its own error.
  • Tizen close <appId> removing the forward: live output below.
  • "private": true: we kept the package public. With private, the layering scan (R11) requires the bundled workspace imports under dependencies, and the packed tarball then cannot install, because @agent-device/host-kit@0.0.0 is not on npm. Could a maintainer publish the placeholder and configure the trusted publisher before merge, as for webOS? That thread stays open.
  • webOS identity: now the ip:port the ares entry reaches, with live output for a second entry on the same TV.
  • Shutdown fence: a shutting-down runtime refuses allocate before and after connectTv.

cubic threads: all replied. Fixed: the identity and shutdown threads, open no longer waits on an old removal after a cancel, listTargets takes the signal, SIGKILL after 5 s, the processExitError guard, a 5 s removal deadline, sdb.exe on Windows, and the fill "" and debug-enabled-app docs. The ones you marked as not applying are resolved with your reasons.

Validation at 496bd62fc: pnpm check:affected --run (exact commit) passed 14 of 15 stages; unit ran 17101 of 17103 green, and the two failures are outside this change: committed-source-tree (known flake) and an Android manifest.test.ts timeout that passes 26/26 alone. Changed-line coverage 94.32% (216/229), CRAP clean, fuzz-worker 11/11; the packed-plugin smoke passes for tizen and webos.

Live, Tizen (same TV as before, source = the tree that became 496bd62fc):

Tizen output
Connected successfully with Samsung Tizen.
$ sdb forward --list
SERIAL              	LOCAL     	REMOTE

$ agent-device open com.example.app
Opened: com.example.app
(exit 0)
$ sdb forward --list
SERIAL              	LOCAL     	REMOTE
192.0.2.10:26101 	tcp:58992 	tcp:35397

$ agent-device close com.example.app
Closed: checkout-tv
(exit 0)
$ sdb forward --list
SERIAL              	LOCAL     	REMOTE

$ agent-device open com.example.app   # Ctrl-C once the forward exists
$ sdb forward --list
SERIAL              	LOCAL     	REMOTE
192.0.2.10:26101 	tcp:59152 	tcp:37735
(exit 130)
$ sdb forward --list
SERIAL              	LOCAL     	REMOTE
$ pgrep -fl 'shell 0 debug'
(none)

$ agent-device open com.example.app
Opened: com.example.app
(exit 0)
$ sdb forward --list
SERIAL              	LOCAL     	REMOTE
192.0.2.10:26101 	tcp:59194 	tcp:35003

$ agent-device disconnect
Disconnected remote session "checkout-tv".
(exit 0)
$ sdb forward --list
SERIAL              	LOCAL     	REMOTE
$ pgrep -fl 'shell 0 debug'
(none)

Live, webOS (same LG TV; living-room-alias is a temporary second ares entry for the same TV, removed afterwards):

webOS output
$ ares-setup-device -a living-room-alias -i host=192.0.2.20 -i port=9922 -i username=prisoner
(exit 0)
$ pgrep -fl ares-inspect
(none)

$ AGENT_DEVICE_SESSION=checkout-tv agent-device connect webos --device living-room
Connected successfully with LG webOS.
Verified: webOS TVs are read from ares-setup-device when a session opens.
Device: living-room — allocated on first device command
App: configured app — configured
(exit 0)

$ AGENT_DEVICE_SESSION=checkout-tv agent-device open com.example.app
Opened: com.example.app
(exit 0)
$ pgrep -fl ares-inspect
ares-inspect -d living-room -a com.example.app

$ AGENT_DEVICE_SESSION=second-tv agent-device connect webos --device living-room-alias
Connected successfully with LG webOS.
Verified: webOS TVs are read from ares-setup-device when a session opens.
Device: living-room-alias — allocated on first device command
App: configured app — configured
(exit 0)

$ AGENT_DEVICE_SESSION=second-tv agent-device open com.example.app
Error (DEVICE_IN_USE): webOS TV 192.0.2.20:9922 is held by another lease
Hint: Disconnect the session that holds the TV, or wait for its lease to expire.
(exit 1)

$ AGENT_DEVICE_SESSION=checkout-tv agent-device appstate
Foreground app: com.example.app
(exit 0)

$ AGENT_DEVICE_SESSION=checkout-tv agent-device close com.example.app
Closed: checkout-tv
(exit 0)
$ pgrep -fl ares-inspect
(none)

$ AGENT_DEVICE_SESSION=second-tv agent-device disconnect
Disconnected remote session "second-tv".
(exit 0)

$ AGENT_DEVICE_SESSION=checkout-tv agent-device disconnect
Disconnected remote session "checkout-tv".
(exit 0)
$ pgrep -fl ares-inspect
(none)

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 17 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

View guided diff | Re-trigger cubic

Comment thread website/docs/docs/webos.md Resolved
@alimek
alimek force-pushed the feat/provider-tizen branch from 496bd62 to 719b56a Compare November 3, 2026 09:44
@thymikee

thymikee commented Nov 3, 2026

Copy link
Copy Markdown
Member

The earlier findings from 6c8b3ef are fixed at 496bd62, and I found no new problems in the code. Leases are now keyed by the sdb serial, the shutdown fence is in place, the debug-package prerequisite and the Backspace wording are corrected, and the cancelled-launch paths are bounded.

Not blocking: the one shutdown test in packages/tv-cdp/src/runtime.test.ts:325 runs before allocate, so it covers only the check at runtime.ts:201. Deleting the post-connect check at runtime.ts:206 keeps every test green. One test would cover it: start allocate with a connectTv that waits on a gate, run shutdown, open the gate, then assert that allocate rejects with the shutting-down error and that deviceInventoryProvider returns null for that lease. Take it or leave it.

Two open inline threads still apply. The first is the unpublished package (#4168 (comment)). The second is the webOS entry-name fallback in ares.ts, which is not blocking (#4168 (comment)). The other inline threads are fixed or benign at this head, so the author can resolve them.

CI is likely unrelated. Vercel failed at fork-deploy authorization before any build, and the other 17 checks pass, including Smoke Tests. The diff touches the docs pages Vercel builds, so the website build for them is unchecked, not failed. There are no conflicts.

The Tizen and webOS live output is author-reported, and I could not reproduce it without a TV, sdb or ares. The fakes cover the cancelled open, the post-connect fence, the ares-inspect SIGKILL escalation, the 5 s sdb removal deadline and sdb.exe discovery on Windows. None of these needs a device run to merge. I did not confirm that every ares-setup-device --listfull entry carries deviceinfo.port, so the bare-IP fallback could give a TV a second identity. I did not reproduce the packed-tarball failure that the author gives as the reason to keep the package public. I did not rerun pnpm check:affected.

Before merge, a maintainer needs to publish the @agent-device/tizen placeholder under a non-latest dist-tag and configure its trusted publisher, and authorize the Vercel fork deploy so the docs build runs.

This review covers 496bd62. The newer head 719b56a changes only the webOS device-id wording in docs and help, which does not change the points above.

…t signal

A TV reached by two aliases (a Tizen IP and IP:26101, or two ares entries for one webOS
TV) was two TVs to tv-cdp, so a second named session could take a held TV and cold-launch
over its app. close and listApps also dropped the request signal, and a tunnel removal
that failed went unreported.

- TvConnection gains id, the one identity of the physical TV. Leases, sessions, the
  DEVICE_IN_USE check, release and device lookup use it; the device keeps the requested
  name so the daemon still selects it by --device. webOS uses the ip:port its ares entry
  reaches.
- close and listApps take the request signal, and tv-cdp passes it through, as does the
  inspector target list.
- PageTunnel.close resolves once the vendor tunnel is gone. close, a failed open and
  release wait for it, and withTunnelRemoval keeps the primary error with the removal
  failure in details. A removal from a page that dropped in the background fails the next
  close or release; a cancelled open stops waiting for it.
- A runtime that is shutting down refuses new leases.
- webOS waits for ares-inspect to exit, with SIGKILL after 5 s.
Add @agent-device/tizen, an optional provider plugin that drives web apps
on Samsung Tizen TVs, built on the shared tv-cdp layer. The TV enters as an
Android TV device owned by the plugin (id tizen:<device>). open kills the
app, debug-launches it with sdb shell 0 debug, forwards the DevTools port
with sdb forward, and drives the page over the Chrome DevTools Protocol.

- sdb is found in the VS Code Tizen extension's SDK ($TIZEN_SDK or
  ~/.tizen.path.config) or at the sdbPath option; --device takes a TV IP
  (sdb connect <ip>:26101 runs when needed) or an sdb serial.
- v1 scope matches webOS: connect, open (--relaunch), close, apps
  (vd_applist), appstate, snapshot, keys (directions, select, back as
  XF86Back), pointer, text, scroll, screenshot and logs.
- Docs: add the Samsung Tizen page, mention it in plugins, commands and
  the sidebar, and add a Tizen flow to help remote.
@alimek
alimek force-pushed the feat/provider-tizen branch from 719b56a to c6092f2 Compare November 3, 2026 09:51
@alimek

alimek commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the re-review. Both points are in c6092f265 (on 388b75cea):

  • Post-connect shutdown fence: added the test you described. connectTv waits on a gate, shutdown runs, the gate opens, and allocate must reject with the shutting-down error while deviceInventoryProvider returns null for that lease. With the check at runtime.ts:206 deleted, this test fails.
  • webOS bare-IP fallback: ares-setup-device --listfull (@webos-tools/cli lib/base/setup-device.js) lists an SSH entry with deviceinfo.ip and port always set (add fills in the default port), and a USB (novacom) entry with only uid. An IP without a port never occurs, so that branch is gone. The entry type now models the two kinds: an SSH entry is ip:port, and a USB entry keeps its entry name. Docs and help say webos:<TV ip>:<port>, or webos:<ares device> for a USB entry. For real network entries the id is unchanged, so the earlier live evidence still applies.

tv-cdp, webOS, Tizen and help tests pass (197/197); typecheck, oxlint, format and doc-prose are clean. The public-package thread stays open for the npm placeholder and trusted publisher.

@thymikee

thymikee commented Nov 3, 2026

Copy link
Copy Markdown
Member

The code at c6092f2 has no new problems since the earlier review. The webOS address documentation and implementation now agree, and the final changes add a deterministic shutdown test. Live evidence remains author-reported from the earlier commits; no new tests or live device runs were performed for this review.

The npm publishing prerequisite still applies and is the sole open reviewer issue that must be resolved before merge. The webOS address documentation thread no longer applies because the docs and CLI help now match the implementation’s ip:port and USB entry-name branches, and it is already resolved.

The supplied checks show 17 passes and only a Vercel authorization failure, which appears unrelated to the code and provides no build diagnostics; the website build remains unverified. No conflicts are known.

Before merge, a maintainer must publish the @agent-device/tizen placeholder under a non-latest dist-tag and configure its trusted publisher as required by docs/agents/pull-requests.md; the author still reports this prerequisite as outstanding. Authorize Vercel and confirm that the website build passes.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants