@desklink/host 0.1.0
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/LICENSE +202 -0
- package/NOTICE +44 -0
- package/README.md +266 -0
- package/bin/desklink-host.mjs +113 -0
- package/dist/bridge.d.ts +57 -0
- package/dist/bridge.d.ts.map +1 -0
- package/dist/bridge.js +208 -0
- package/dist/bridge.js.map +1 -0
- package/dist/engineProcess.d.ts +82 -0
- package/dist/engineProcess.d.ts.map +1 -0
- package/dist/engineProcess.js +243 -0
- package/dist/engineProcess.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/protocol.d.ts +169 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +18 -0
- package/dist/protocol.js.map +1 -0
- package/dist/resolveEngine.d.ts +34 -0
- package/dist/resolveEngine.d.ts.map +1 -0
- package/dist/resolveEngine.js +103 -0
- package/dist/resolveEngine.js.map +1 -0
- package/docs/BOUNDARY.md +145 -0
- package/docs/PROTOCOL.md +363 -0
- package/engine/Cargo.lock +3077 -0
- package/engine/Cargo.toml +37 -0
- package/engine/build.rs +107 -0
- package/engine/native/inputtino_shim.cpp +11 -0
- package/engine/native/vpx_shim.c +184 -0
- package/engine/native/wrapper.h +7 -0
- package/engine/src/capture.rs +510 -0
- package/engine/src/clipboard.rs +132 -0
- package/engine/src/convert.rs +299 -0
- package/engine/src/encoder.rs +204 -0
- package/engine/src/input.rs +355 -0
- package/engine/src/keymap.rs +338 -0
- package/engine/src/main.rs +614 -0
- package/engine/src/peer.rs +775 -0
- package/engine/src/portal.rs +115 -0
- package/engine/src/protocol.rs +331 -0
- package/engine/src/session.rs +2159 -0
- package/engine/src/x11.rs +244 -0
- package/engine/vendor/inputtino/.clang-format +166 -0
- package/engine/vendor/inputtino/.clang-tidy +30 -0
- package/engine/vendor/inputtino/.dockerignore +11 -0
- package/engine/vendor/inputtino/.github/workflows/mirror-repo.yml +14 -0
- package/engine/vendor/inputtino/.github/workflows/python-lint-format-test-typecheck.yml +124 -0
- package/engine/vendor/inputtino/.github/workflows/python-test-install.yaml +49 -0
- package/engine/vendor/inputtino/.github/workflows/rust.yml +40 -0
- package/engine/vendor/inputtino/CMakeLists.txt +187 -0
- package/engine/vendor/inputtino/LICENSE +21 -0
- package/engine/vendor/inputtino/README.md +110 -0
- package/engine/vendor/inputtino/bindings/python/.devcontainer/Dockerfile +23 -0
- package/engine/vendor/inputtino/bindings/python/.devcontainer/devcontainer.json +28 -0
- package/engine/vendor/inputtino/bindings/python/.python-version +1 -0
- package/engine/vendor/inputtino/bindings/python/CMakeLists.txt +23 -0
- package/engine/vendor/inputtino/bindings/python/CPPLINT.cfg +2 -0
- package/engine/vendor/inputtino/bindings/python/Makefile +49 -0
- package/engine/vendor/inputtino/bindings/python/README.md +215 -0
- package/engine/vendor/inputtino/bindings/python/pyproject.toml +178 -0
- package/engine/vendor/inputtino/bindings/python/src/inputtino/__init__.py +43 -0
- package/engine/vendor/inputtino/bindings/python/src/inputtino/_core.pyi +533 -0
- package/engine/vendor/inputtino/bindings/python/src/inputtino/base.py +63 -0
- package/engine/vendor/inputtino/bindings/python/src/inputtino/joypad.py +248 -0
- package/engine/vendor/inputtino/bindings/python/src/inputtino/keyboard.py +256 -0
- package/engine/vendor/inputtino/bindings/python/src/inputtino/mouse.py +106 -0
- package/engine/vendor/inputtino/bindings/python/src/inputtino/pentablet.py +73 -0
- package/engine/vendor/inputtino/bindings/python/src/inputtino/py.typed +0 -0
- package/engine/vendor/inputtino/bindings/python/src/inputtino/touchscreen.py +61 -0
- package/engine/vendor/inputtino/bindings/python/src/inputtino/trackpad.py +74 -0
- package/engine/vendor/inputtino/bindings/python/src/main.cpp +217 -0
- package/engine/vendor/inputtino/bindings/python/tests/__init__.py +0 -0
- package/engine/vendor/inputtino/bindings/python/tests/helpers.py +3 -0
- package/engine/vendor/inputtino/bindings/python/tests/test_base.py +60 -0
- package/engine/vendor/inputtino/bindings/python/tests/test_inputtino.py +5 -0
- package/engine/vendor/inputtino/bindings/python/tests/test_joypad.py +332 -0
- package/engine/vendor/inputtino/bindings/python/tests/test_keyboard.py +164 -0
- package/engine/vendor/inputtino/bindings/python/tests/test_mouse.py +185 -0
- package/engine/vendor/inputtino/bindings/python/tests/test_pentablet.py +198 -0
- package/engine/vendor/inputtino/bindings/python/tests/test_touchscreen.py +144 -0
- package/engine/vendor/inputtino/bindings/python/tests/test_trackpad.py +146 -0
- package/engine/vendor/inputtino/bindings/python/uv.lock +390 -0
- package/engine/vendor/inputtino/bindings/rust/Cargo.toml +6 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/.dockerignore +1 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/Cargo.toml +18 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/examples/keyboard.rs +33 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/examples/mouse.rs +17 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/src/common.rs +116 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/src/error.rs +17 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/src/joypad.rs +74 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/src/joypad_nintendo.rs +135 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/src/joypad_ps5.rs +280 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/src/joypad_xbox.rs +134 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/src/keyboard.rs +76 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/src/lib.rs +32 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/src/mouse.rs +178 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/tests/common.rs +38 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/tests/joypads.rs +150 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/tests/keyboard.rs +73 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/tests/mouse.rs +139 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino-sys/.dockerignore +1 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino-sys/Cargo.toml +12 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino-sys/build.rs +48 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino-sys/src/lib.rs +5 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino-sys/wrapper.h +1 -0
- package/engine/vendor/inputtino/cmake/utils.cmake +9 -0
- package/engine/vendor/inputtino/docker/Dockerfile +70 -0
- package/engine/vendor/inputtino/include/inputtino/input.h +324 -0
- package/engine/vendor/inputtino/include/inputtino/input.hpp +466 -0
- package/engine/vendor/inputtino/include/inputtino/result.hpp +37 -0
- package/engine/vendor/inputtino/share/pkgconfig/libinputtino.pc.in +17 -0
- package/engine/vendor/inputtino/src/c-bindings/helpers.hpp +19 -0
- package/engine/vendor/inputtino/src/c-bindings/joypad_ps5.cpp +115 -0
- package/engine/vendor/inputtino/src/c-bindings/joypad_switch.cpp +63 -0
- package/engine/vendor/inputtino/src/c-bindings/joypad_xone.cpp +62 -0
- package/engine/vendor/inputtino/src/c-bindings/keyboard.cpp +42 -0
- package/engine/vendor/inputtino/src/c-bindings/mouse.cpp +67 -0
- package/engine/vendor/inputtino/src/c-bindings/pen_tablet.cpp +50 -0
- package/engine/vendor/inputtino/src/c-bindings/touchscreen.cpp +43 -0
- package/engine/vendor/inputtino/src/c-bindings/trackpad.cpp +49 -0
- package/engine/vendor/inputtino/src/uhid/README.adoc +63 -0
- package/engine/vendor/inputtino/src/uhid/include/crc32.hpp +38 -0
- package/engine/vendor/inputtino/src/uhid/include/uhid/protected_types.hpp +36 -0
- package/engine/vendor/inputtino/src/uhid/include/uhid/ps5.hpp +550 -0
- package/engine/vendor/inputtino/src/uhid/include/uhid/uhid.hpp +168 -0
- package/engine/vendor/inputtino/src/uhid/joypad_ps5.cpp +580 -0
- package/engine/vendor/inputtino/src/uinput/include/inputtino/keyboard.hpp +84 -0
- package/engine/vendor/inputtino/src/uinput/include/inputtino/protected_ps5_types.hpp +7 -0
- package/engine/vendor/inputtino/src/uinput/include/inputtino/protected_types.hpp +110 -0
- package/engine/vendor/inputtino/src/uinput/joypad_nintendo.cpp +190 -0
- package/engine/vendor/inputtino/src/uinput/joypad_ps.cpp +203 -0
- package/engine/vendor/inputtino/src/uinput/joypad_utils.hpp +246 -0
- package/engine/vendor/inputtino/src/uinput/joypad_xbox.cpp +190 -0
- package/engine/vendor/inputtino/src/uinput/keyboard.cpp +120 -0
- package/engine/vendor/inputtino/src/uinput/mouse.cpp +199 -0
- package/engine/vendor/inputtino/src/uinput/pentablet.cpp +162 -0
- package/engine/vendor/inputtino/src/uinput/touchscreen.cpp +140 -0
- package/engine/vendor/inputtino/src/uinput/trackpad.cpp +192 -0
- package/examples/reference-client.html +428 -0
- package/package.json +38 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
|
|
2
|
+
Apache License
|
|
3
|
+
Version 2.0, January 2004
|
|
4
|
+
http://www.apache.org/licenses/
|
|
5
|
+
|
|
6
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
7
|
+
|
|
8
|
+
1. Definitions.
|
|
9
|
+
|
|
10
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
11
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
12
|
+
|
|
13
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
14
|
+
the copyright owner that is granting the License.
|
|
15
|
+
|
|
16
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
17
|
+
other entities that control, are controlled by, or are under common
|
|
18
|
+
control with that entity. For the purposes of this definition,
|
|
19
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
20
|
+
direction or management of such entity, whether by contract or
|
|
21
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
22
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
23
|
+
|
|
24
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
25
|
+
exercising permissions granted by this License.
|
|
26
|
+
|
|
27
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
28
|
+
including but not limited to software source code, documentation
|
|
29
|
+
source, and configuration files.
|
|
30
|
+
|
|
31
|
+
"Object" form shall mean any form resulting from mechanical
|
|
32
|
+
transformation or translation of a Source form, including but
|
|
33
|
+
not limited to compiled object code, generated documentation,
|
|
34
|
+
and conversions to other media types.
|
|
35
|
+
|
|
36
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
37
|
+
Object form, made available under the License, as indicated by a
|
|
38
|
+
copyright notice that is included in or attached to the work
|
|
39
|
+
(an example is provided in the Appendix below).
|
|
40
|
+
|
|
41
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
42
|
+
form, that is based on (or derived from) the Work and for which the
|
|
43
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
44
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
45
|
+
of this License, Derivative Works shall not include works that remain
|
|
46
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
47
|
+
the Work and Derivative Works thereof.
|
|
48
|
+
|
|
49
|
+
"Contribution" shall mean any work of authorship, including
|
|
50
|
+
the original version of the Work and any modifications or additions
|
|
51
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
52
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
53
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
54
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
55
|
+
means any form of electronic, verbal, or written communication sent
|
|
56
|
+
to the Licensor or its representatives, including but not limited to
|
|
57
|
+
communication on electronic mailing lists, source code control systems,
|
|
58
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
59
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
60
|
+
excluding communication that is conspicuously marked or otherwise
|
|
61
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
62
|
+
|
|
63
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
64
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
65
|
+
subsequently incorporated within the Work.
|
|
66
|
+
|
|
67
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
68
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
69
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
70
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
71
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
72
|
+
Work and such Derivative Works in Source or Object form.
|
|
73
|
+
|
|
74
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
75
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
76
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
77
|
+
(except as stated in this section) patent license to make, have made,
|
|
78
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
79
|
+
where such license applies only to those patent claims licensable
|
|
80
|
+
by such Contributor that are necessarily infringed by their
|
|
81
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
82
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
83
|
+
institute patent litigation against any entity (including a
|
|
84
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
85
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
86
|
+
or contributory patent infringement, then any patent licenses
|
|
87
|
+
granted to You under this License for that Work shall terminate
|
|
88
|
+
as of the date such litigation is filed.
|
|
89
|
+
|
|
90
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
91
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
92
|
+
modifications, and in Source or Object form, provided that You
|
|
93
|
+
meet the following conditions:
|
|
94
|
+
|
|
95
|
+
(a) You must give any other recipients of the Work or
|
|
96
|
+
Derivative Works a copy of this License; and
|
|
97
|
+
|
|
98
|
+
(b) You must cause any modified files to carry prominent notices
|
|
99
|
+
stating that You changed the files; and
|
|
100
|
+
|
|
101
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
102
|
+
that You distribute, all copyright, patent, trademark, and
|
|
103
|
+
attribution notices from the Source form of the Work,
|
|
104
|
+
excluding those notices that do not pertain to any part of
|
|
105
|
+
the Derivative Works; and
|
|
106
|
+
|
|
107
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
108
|
+
distribution, then any Derivative Works that You distribute must
|
|
109
|
+
include a readable copy of the attribution notices contained
|
|
110
|
+
within such NOTICE file, excluding those notices that do not
|
|
111
|
+
pertain to any part of the Derivative Works, in at least one
|
|
112
|
+
of the following places: within a NOTICE text file distributed
|
|
113
|
+
as part of the Derivative Works; within the Source form or
|
|
114
|
+
documentation, if provided along with the Derivative Works; or,
|
|
115
|
+
within a display generated by the Derivative Works, if and
|
|
116
|
+
wherever such third-party notices normally appear. The contents
|
|
117
|
+
of the NOTICE file are for informational purposes only and
|
|
118
|
+
do not modify the License. You may add Your own attribution
|
|
119
|
+
notices within Derivative Works that You distribute, alongside
|
|
120
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
121
|
+
that such additional attribution notices cannot be construed
|
|
122
|
+
as modifying the License.
|
|
123
|
+
|
|
124
|
+
You may add Your own copyright statement to Your modifications and
|
|
125
|
+
may provide additional or different license terms and conditions
|
|
126
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
127
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
128
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
129
|
+
the conditions stated in this License.
|
|
130
|
+
|
|
131
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
132
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
133
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
134
|
+
this License, without any additional terms or conditions.
|
|
135
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
136
|
+
the terms of any separate license agreement you may have executed
|
|
137
|
+
with Licensor regarding such Contributions.
|
|
138
|
+
|
|
139
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
140
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
141
|
+
except as required for reasonable and customary use in describing the
|
|
142
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
143
|
+
|
|
144
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
145
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
146
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
147
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
148
|
+
implied, including, without limitation, any warranties or conditions
|
|
149
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
150
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
151
|
+
appropriateness of using or redistributing the Work and assume any
|
|
152
|
+
risks associated with Your exercise of permissions under this License.
|
|
153
|
+
|
|
154
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
155
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
156
|
+
unless required by applicable law (such as deliberate and grossly
|
|
157
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
158
|
+
liable to You for damages, including any direct, indirect, special,
|
|
159
|
+
incidental, or consequential damages of any character arising as a
|
|
160
|
+
result of this License or out of the use or inability to use the
|
|
161
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
162
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
163
|
+
other commercial damages or losses), even if such Contributor
|
|
164
|
+
has been advised of the possibility of such damages.
|
|
165
|
+
|
|
166
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
167
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
168
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
169
|
+
or other liability obligations and/or rights consistent with this
|
|
170
|
+
License. However, in accepting such obligations, You may act only
|
|
171
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
172
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
173
|
+
defend, and hold each Contributor harmless for any liability
|
|
174
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
175
|
+
of your accepting any such warranty or additional liability.
|
|
176
|
+
|
|
177
|
+
END OF TERMS AND CONDITIONS
|
|
178
|
+
|
|
179
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
180
|
+
|
|
181
|
+
To apply the Apache License to your work, attach the following
|
|
182
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
183
|
+
replaced with your own identifying information. (Don't include
|
|
184
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
185
|
+
comment syntax for the file format. We also recommend that a
|
|
186
|
+
file or class name and description of purpose be included on the
|
|
187
|
+
same "printed page" as the copyright notice for easier
|
|
188
|
+
identification within third-party archives.
|
|
189
|
+
|
|
190
|
+
Copyright [yyyy] [name of copyright owner]
|
|
191
|
+
|
|
192
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
|
+
you may not use this file except in compliance with the License.
|
|
194
|
+
You may obtain a copy of the License at
|
|
195
|
+
|
|
196
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
197
|
+
|
|
198
|
+
Unless required by applicable law or agreed to in writing, software
|
|
199
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
200
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
201
|
+
See the License for the specific language governing permissions and
|
|
202
|
+
limitations under the License.
|
package/NOTICE
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
desklink host engine
|
|
2
|
+
Copyright the desklink authors. Licensed under the Apache License, Version 2.0.
|
|
3
|
+
|
|
4
|
+
This distribution links or calls the following third-party components. None of
|
|
5
|
+
them is copyleft; the notices below are the conditions of their permissive
|
|
6
|
+
licences.
|
|
7
|
+
|
|
8
|
+
libvpx BSD-3-Clause
|
|
9
|
+
VP9 encoding. A source build links the host system's libvpx; the prebuilt
|
|
10
|
+
engine (@desklink/host-linux-x64-gnu) links libvpx v1.16.0 statically and
|
|
11
|
+
carries its licence and patent grant in THIRD_PARTY_LICENSES.txt.
|
|
12
|
+
https://chromium.googlesource.com/webm/libvpx/+/refs/heads/main/LICENSE
|
|
13
|
+
|
|
14
|
+
inputtino MIT
|
|
15
|
+
Virtual pointer and keyboard over uinput/libevdev. Vendored unmodified
|
|
16
|
+
under engine/vendor/inputtino at commit
|
|
17
|
+
f4ce2b0df536ef309e9ff318f75b460f7097d7c1; its LICENSE file is retained
|
|
18
|
+
alongside its source.
|
|
19
|
+
|
|
20
|
+
libevdev MIT (with a Linux-header GPL notice retained
|
|
21
|
+
upstream; no GPL code is linked from it)
|
|
22
|
+
Used by inputtino to open and manage uinput devices.
|
|
23
|
+
|
|
24
|
+
xdg-desktop-portal LGPL-2.1-or-later (NOT linked)
|
|
25
|
+
xdg-desktop-portal-hyprland MIT (NOT linked)
|
|
26
|
+
Called over D-Bus, in a separate process, as any other desktop client does.
|
|
27
|
+
No portal implementation is bundled, linked or modified by this package.
|
|
28
|
+
|
|
29
|
+
PipeWire MIT (NOT bundled)
|
|
30
|
+
The client library the engine uses to read the portal's stream.
|
|
31
|
+
|
|
32
|
+
wayland / wayland-protocols MIT
|
|
33
|
+
xkbcommon MIT
|
|
34
|
+
Keyboard layout lookup.
|
|
35
|
+
|
|
36
|
+
webrtc (webrtc-rs) MIT / Apache-2.0
|
|
37
|
+
rustls, ring and their transitive dependencies: see their own notices. The
|
|
38
|
+
prebuilt engine reproduces every linked crate's licence text in
|
|
39
|
+
THIRD_PARTY_LICENSES.txt, and its build refuses any crate whose licence is
|
|
40
|
+
not permissive.
|
|
41
|
+
|
|
42
|
+
No code from Sunshine, Moonlight, Apollo, RustDesk, GNOME Remote Desktop, KRdp,
|
|
43
|
+
WayVNC, Guacamole or MeshCentral is copied, linked or derived from here. Those
|
|
44
|
+
projects were read as architecture references only.
|
package/README.md
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
# @desklink/host
|
|
2
|
+
|
|
3
|
+
A per-user, on-demand desktop engine: capture the user's own screen, encode it,
|
|
4
|
+
carry it over WebRTC, and apply that session's pointer, keyboard and clipboard
|
|
5
|
+
actions back to the same desktop.
|
|
6
|
+
|
|
7
|
+
It is a **process with a documented local protocol**, not a service. A consumer
|
|
8
|
+
starts it, owns its stdin/stdout, carries the SDP/ICE over its own authenticated
|
|
9
|
+
channel, and stops it. Nothing in the engine's public surface refers to any
|
|
10
|
+
particular application.
|
|
11
|
+
|
|
12
|
+
## What it does
|
|
13
|
+
|
|
14
|
+
- **Capture** through the XDG Desktop Portal (`ScreenCast`) and PipeWire, with
|
|
15
|
+
compositor consent, or from an explicitly selected X display's root window.
|
|
16
|
+
The portal path asks for shared-memory buffers rather than DMA-BUFs, keeping
|
|
17
|
+
its pixel path on the CPU and out of the driver.
|
|
18
|
+
- **Encode** VP9 with libvpx in real time, single pass, no lookahead: one frame
|
|
19
|
+
in, one packet out. Software by default, because a hardware encoder would put a
|
|
20
|
+
vendor driver dependency on every machine class. Tuned for a desktop: the
|
|
21
|
+
desktop's own pixels up to 4K (a phone zooms in, and text has to survive it),
|
|
22
|
+
screen-content mode, key frames only on request, and a refinement pass that
|
|
23
|
+
re-codes a still desktop once at a fine quantizer so it reads sharp.
|
|
24
|
+
- **Transport** with WebRTC — ICE, DTLS, SRTP, RTP — and one data channel for the
|
|
25
|
+
session's pointer/keyboard/clipboard.
|
|
26
|
+
- **Input** through [inputtino](https://github.com/games-on-whales/inputtino)
|
|
27
|
+
(MIT) over `uinput`/`libevdev` for portal capture, or XTest for an X display.
|
|
28
|
+
Both release held input when the session ends.
|
|
29
|
+
- **Clipboard** explicitly, in both directions, only when asked. It is never
|
|
30
|
+
polled and never used as a hidden way to type. On Wayland, writes require
|
|
31
|
+
`wl-copy` from `wl-clipboard`; its selection server keeps the copied text
|
|
32
|
+
available after the desktop session ends, until another app replaces it.
|
|
33
|
+
|
|
34
|
+
## What it deliberately does not do
|
|
35
|
+
|
|
36
|
+
- It does not decide *who* the user is. The consumer authorizes; the engine
|
|
37
|
+
enforces the scope it was given.
|
|
38
|
+
- It does not open a public listener, run as root, install udev rules, join
|
|
39
|
+
groups or raise capabilities.
|
|
40
|
+
- It does not carry audio, arbitrate between two controllers, or remember a
|
|
41
|
+
session across a restart.
|
|
42
|
+
|
|
43
|
+
## Install and run
|
|
44
|
+
|
|
45
|
+
```sh
|
|
46
|
+
npm install @desklink/host
|
|
47
|
+
npx desklink-host path # the engine this install will run
|
|
48
|
+
npx desklink-host capabilities # what this machine can do right now
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
On **Linux x64 with glibc 2.36 or newer** — Debian 12, Ubuntu 24.04, Fedora 37
|
|
52
|
+
or later, Arch — that is the whole install. npm also installs the optional
|
|
53
|
+
platform package `@desklink/host-linux-x64-gnu`, which carries the prebuilt
|
|
54
|
+
engine, and `resolveEngine()` finds it there. No Rust toolchain, compiler or
|
|
55
|
+
install script is involved, so `--ignore-scripts` installs work. The engine
|
|
56
|
+
requires the system's `libpipewire-0.3.so.0`, `libxkbcommon.so.0`,
|
|
57
|
+
`libevdev.so.2` and `libstdc++.so.6` (normally supplied by a modern Linux
|
|
58
|
+
desktop). If one is missing, the host reports `missing system library: <name>`
|
|
59
|
+
with code `missing-system-library` rather than failing silently; it does not
|
|
60
|
+
bundle these system libraries. libvpx and inputtino are linked into the engine.
|
|
61
|
+
|
|
62
|
+
The one step no install does for you is [kernel input access](#kernel-input-access),
|
|
63
|
+
and only the portal backend needs it.
|
|
64
|
+
|
|
65
|
+
There is no prebuilt engine for any other platform. Another Linux (arm64, musl)
|
|
66
|
+
can [build it from source](#building-from-source). macOS and Windows are not
|
|
67
|
+
supported: `capabilities` there says the engine runs on Linux only.
|
|
68
|
+
|
|
69
|
+
Point `MUXR_DESKLINK_ENGINE` at a binary built elsewhere if you have one. The
|
|
70
|
+
package never searches `PATH` for a same-named program: "a binary called
|
|
71
|
+
desklink-host" is not evidence of which program is about to be given control of
|
|
72
|
+
someone's desktop.
|
|
73
|
+
|
|
74
|
+
### Building from source
|
|
75
|
+
|
|
76
|
+
```sh
|
|
77
|
+
cd packages/desktop-host # from the repository root
|
|
78
|
+
cargo build --release --manifest-path engine/Cargo.toml
|
|
79
|
+
./bin/desklink-host.mjs path # prints the binary this package will run
|
|
80
|
+
./bin/desklink-host.mjs capabilities
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
A source build links system libraries through `pkg-config` (and libxcb
|
|
84
|
+
directly), compiles `native/vpx_shim.c` against libvpx's headers, and builds
|
|
85
|
+
the vendored inputtino project with CMake. On a clean machine, install:
|
|
86
|
+
|
|
87
|
+
| Need | Debian/Ubuntu | Fedora | Arch |
|
|
88
|
+
|---|---|---|---|
|
|
89
|
+
| Rust toolchain (`cargo`, `cc`) | `rustup` + `build-essential` | `rustup` + `gcc gcc-c++` | `rustup` + `base-devel` |
|
|
90
|
+
| CMake | `cmake` | `cmake` | `cmake` |
|
|
91
|
+
| `pkg-config` | `pkg-config` | `pkgconf-pkg-config` | `pkgconf` |
|
|
92
|
+
| libvpx (`vpx.pc`) | `libvpx-dev` | `libvpx-devel` | `libvpx` |
|
|
93
|
+
| PipeWire 0.3.65+ (`libpipewire-0.3`) | `libpipewire-0.3-dev` | `pipewire-devel` | `pipewire` |
|
|
94
|
+
| xkbcommon | `libxkbcommon-dev` | `libxkbcommon-devel` | `libxkbcommon` |
|
|
95
|
+
| Wayland (`wayland-client`) | `libwayland-dev` | `wayland-devel` | `wayland` |
|
|
96
|
+
| libevdev | `libevdev-dev` | `libevdev-devel` | `libevdev` |
|
|
97
|
+
| libxcb (source/container builds only) | `libxcb1-dev` | `libxcb-devel` | `libxcb` |
|
|
98
|
+
|
|
99
|
+
These are build prerequisites, not additional runtime requirements for the
|
|
100
|
+
prebuilt package; in particular, libxcb is not a prebuilt runtime requirement.
|
|
101
|
+
Nothing is downloaded by the build itself. The engine step in `yarn run check`
|
|
102
|
+
skips with a list of missing prerequisites when any of these is absent; direct
|
|
103
|
+
`cargo test --manifest-path engine/Cargo.toml` does not skip and needs them
|
|
104
|
+
installed. Only a machine with all of them compiles and tests the crate.
|
|
105
|
+
|
|
106
|
+
### Kernel input access
|
|
107
|
+
|
|
108
|
+
Ordinary tests do not create real desktop devices. To opt into the hardware
|
|
109
|
+
probe explicitly, run `DESKLINK_TEST_UINPUT=1 cargo test this_host_can_create_and_destroy_the_virtual_devices`
|
|
110
|
+
inside `engine/` on a desktop you are authorized to control.
|
|
111
|
+
|
|
112
|
+
Creating virtual input devices needs write access to `/dev/uinput`. That is
|
|
113
|
+
whole-desktop control of the logged-in session, so it is a decision the user
|
|
114
|
+
makes, not something an installation does for them:
|
|
115
|
+
|
|
116
|
+
```sh
|
|
117
|
+
npx desklink-host setup-input # where @desklink/host is installed
|
|
118
|
+
npx -p @desklink/host desklink-host setup-input # anywhere else, e.g. under an application that depends on it
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
That prints the exact, narrowly scoped rule — and changes nothing. Without
|
|
122
|
+
`uinput` access a portal session can still be opened with `view` permission;
|
|
123
|
+
asking for `control` is refused rather than presenting inert controls. An X
|
|
124
|
+
session instead uses XTest and does not need `/dev/uinput`.
|
|
125
|
+
|
|
126
|
+
## Licence and provenance
|
|
127
|
+
|
|
128
|
+
Apache-2.0. The engine links two permissive native libraries — libvpx
|
|
129
|
+
(BSD-3-Clause) and inputtino (MIT, vendored under `engine/vendor/`) — and calls
|
|
130
|
+
the portal over D-Bus rather than linking it. See `NOTICE`. The prebuilt engine
|
|
131
|
+
links libvpx statically and carries every licence text it owes, including each
|
|
132
|
+
linked crate's, in its package's `THIRD_PARTY_LICENSES.txt`, with the Rust
|
|
133
|
+
standard library's own notices in `COPYRIGHT-rust-library.html`. Its build
|
|
134
|
+
refuses any crate whose licence is not permissive.
|
|
135
|
+
|
|
136
|
+
No GPL/AGPL remote-desktop code is copied, linked or derived; Sunshine,
|
|
137
|
+
Moonlight, Apollo and RustDesk were read as architecture references only.
|
|
138
|
+
|
|
139
|
+
## Connecting an application to it
|
|
140
|
+
|
|
141
|
+
The engine needs one thing from a consumer: somewhere for the SDP and ICE
|
|
142
|
+
candidates to go, and somewhere for the answer and the client's candidates to
|
|
143
|
+
come back. See `docs/PROTOCOL.md` for the authoritative wire contract.
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
import { EngineClient, resolveEngine } from '@desklink/host';
|
|
147
|
+
|
|
148
|
+
const engine = resolveEngine(); // prebuilt, or a source build
|
|
149
|
+
const client = await EngineClient.start(engine.command, engine.args);
|
|
150
|
+
const session = await client.openSession({ permissions: ['view', 'control', 'clipboard'] });
|
|
151
|
+
|
|
152
|
+
// Everything the engine wants to tell the client arrives here, in order.
|
|
153
|
+
client.drainEvents().forEach((event) => myChannel.send(event));
|
|
154
|
+
|
|
155
|
+
// Bring the client's answer and candidates back.
|
|
156
|
+
await client.acceptAnswer(session.sessionId, session.generation, answerSdp);
|
|
157
|
+
await client.addCandidate(session.sessionId, session.generation, candidate, sdpMid, sdpMLineIndex);
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
`myChannel` is the application's own authenticated connection, whatever that is.
|
|
161
|
+
There is no second identity system, no pairing ceremony and no account: the
|
|
162
|
+
engine trusts the consumer's decision and enforces the scope it was given.
|
|
163
|
+
|
|
164
|
+
### If you have no channel of your own
|
|
165
|
+
|
|
166
|
+
`desklink-host bridge` is the minimal runnable example for third-party consumers:
|
|
167
|
+
it re-serves the same protocol over a WebSocket and serves a reference client
|
|
168
|
+
at `/` so the first run is one command:
|
|
169
|
+
|
|
170
|
+
```sh
|
|
171
|
+
desklink-host bridge --listen 127.0.0.1:19400
|
|
172
|
+
# engine /path/to/desklink-host
|
|
173
|
+
# bridge ws://127.0.0.1:19400/desktop
|
|
174
|
+
# token <generated>
|
|
175
|
+
# open http://127.0.0.1:19400/?token=<generated>
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Open that URL and you have a desktop in a browser. `examples/reference-client.html`
|
|
179
|
+
is that page's source: one file, no build step, and the shortest complete
|
|
180
|
+
description of the protocol that exists. The bridge operator chooses the capture
|
|
181
|
+
source with its flag or environment; clients cannot choose or override it.
|
|
182
|
+
|
|
183
|
+
Two things the bridge is honest about: `ws://` is plaintext, so keep it on a
|
|
184
|
+
private network or put it behind TLS; and the token in the URL *is* the
|
|
185
|
+
authorisation for that socket, so treat it as a credential.
|
|
186
|
+
|
|
187
|
+
## Packaging
|
|
188
|
+
|
|
189
|
+
The engine is a native executable, so the package ships a small JavaScript
|
|
190
|
+
launcher and depends on one platform package per supported target, which npm
|
|
191
|
+
installs only where its `os`, `cpu` and `libc` match:
|
|
192
|
+
|
|
193
|
+
```text
|
|
194
|
+
@desklink/host
|
|
195
|
+
optionalDependencies:
|
|
196
|
+
@desklink/host-linux-x64-gnu # the executable, THIRD_PARTY_LICENSES.txt, provenance.json
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
The optional dependency is written into the published manifest by
|
|
200
|
+
`release/pack.mjs`, pinned to the same version, and is deliberately absent from
|
|
201
|
+
the source `package.json`: an optional dependency the registry does not have
|
|
202
|
+
yet makes a workspace's `yarn install --frozen-lockfile` fail outright rather
|
|
203
|
+
than skip it.
|
|
204
|
+
|
|
205
|
+
`resolveEngine` looks for the platform package first and falls back to a source
|
|
206
|
+
build, and it never searches `PATH`: a program that happens to be called
|
|
207
|
+
`desklink-host` is not evidence of which program is about to be given control of
|
|
208
|
+
a desktop.
|
|
209
|
+
|
|
210
|
+
The platform packages must be usable **without lifecycle scripts**, because
|
|
211
|
+
muxr's documented install uses `npm install --global --ignore-scripts`. Nothing
|
|
212
|
+
here downloads or chmods anything at install time; the executable arrives with
|
|
213
|
+
the executable bit already set in the tarball.
|
|
214
|
+
|
|
215
|
+
`platformTag()` includes the libc (`-gnu` or `-musl`) because a glibc binary on a
|
|
216
|
+
musl system fails in ways that read as "broken install" rather than "unsupported
|
|
217
|
+
platform". Only variants that have passed their own qualification are published:
|
|
218
|
+
`linux-x64-gnu` now, `linux-arm64-gnu` when a real machine has run a real
|
|
219
|
+
journey on it. macOS and Windows are separate backends, not separate builds.
|
|
220
|
+
|
|
221
|
+
### Building and packing a release
|
|
222
|
+
|
|
223
|
+
Needs Docker and Node, nothing else: no Rust toolchain or system libraries.
|
|
224
|
+
|
|
225
|
+
```sh
|
|
226
|
+
packages/desktop-host/release/build-engine.sh # -> dist-desklink/engine-linux-x64-gnu/
|
|
227
|
+
npx tsc --build packages/desktop-host
|
|
228
|
+
node packages/desktop-host/release/pack.mjs --engine dist-desklink/engine-linux-x64-gnu
|
|
229
|
+
packages/desktop-host/release/check-install.sh # fresh install in a clean container
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
`build-engine.sh` builds the engine from this checkout in the container that
|
|
233
|
+
`release/linux-x64-gnu.Dockerfile` pins: base images by digest, Debian packages
|
|
234
|
+
by snapshot date, the Rust toolchain by version, libvpx by commit, crates by
|
|
235
|
+
`Cargo.lock`. The same source gives the same executable, byte for byte. The
|
|
236
|
+
build fails if libvpx ends up dynamically linked, if the executable needs a
|
|
237
|
+
glibc newer than 2.36, or if any crate's licence is not permissive
|
|
238
|
+
(`release/notices.mjs`, which also writes `THIRD_PARTY_LICENSES.txt`).
|
|
239
|
+
`provenance.json` records the source commit, the pinned inputs and the
|
|
240
|
+
executable's SHA-256.
|
|
241
|
+
|
|
242
|
+
The scripts use only the repository's `dist-desklink/` paths shown above; none
|
|
243
|
+
accepts an alternate output or tarball directory. `pack.mjs` requires the
|
|
244
|
+
verified engine output and replaces older desklink tarballs with the current
|
|
245
|
+
`desklink-host-<version>.tgz` and `desklink-host-linux-x64-gnu-<version>.tgz`.
|
|
246
|
+
It cannot pack a host-only release and publishes nothing.
|
|
247
|
+
The package smoke instead uses `npm pack` on this checkout's host package as a
|
|
248
|
+
registry stand-in, without Docker or a native build. `check-install.sh` installs
|
|
249
|
+
only the current version's two tarballs into an empty project in a container
|
|
250
|
+
with no Rust toolchain, no display and no `/dev/uinput`, and checks both
|
|
251
|
+
installed versions. It checks the typed
|
|
252
|
+
missing-library error before installing the system runtime libraries, then has
|
|
253
|
+
the host package resolve the prebuilt engine, start it and answer the protocol
|
|
254
|
+
handshake and a capabilities probe.
|
|
255
|
+
|
|
256
|
+
Publishing is by hand, from an `npm login` with publish rights on the scope.
|
|
257
|
+
`release/publish.mjs` publishes the platform package first and waits until the
|
|
258
|
+
registry serves it before publishing `@desklink/host`, so the host never points
|
|
259
|
+
at an engine npm does not have. A version already on npm with the same bytes is
|
|
260
|
+
skipped; with different bytes it is refused. `--dry-run` does everything but the
|
|
261
|
+
upload:
|
|
262
|
+
|
|
263
|
+
```sh
|
|
264
|
+
node packages/desktop-host/release/publish.mjs --dry-run
|
|
265
|
+
node packages/desktop-host/release/publish.mjs
|
|
266
|
+
```
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CLI for the desktop host engine package.
|
|
4
|
+
*
|
|
5
|
+
* `path` and `capabilities` work without starting a session, so a consumer can
|
|
6
|
+
* tell the user what is wrong before a desktop is opened rather than after.
|
|
7
|
+
* Everything else is forwarded to the engine binary, so the CLI cannot drift
|
|
8
|
+
* from the process protocol it documents.
|
|
9
|
+
*/
|
|
10
|
+
import { spawn } from 'node:child_process';
|
|
11
|
+
import { randomBytes } from 'node:crypto';
|
|
12
|
+
import { Bridge } from '../dist/bridge.js';
|
|
13
|
+
import { EngineClient } from '../dist/engineProcess.js';
|
|
14
|
+
import { explainMissingEngine, resolveEngine } from '../dist/resolveEngine.js';
|
|
15
|
+
|
|
16
|
+
const [command, ...rest] = process.argv.slice(2);
|
|
17
|
+
|
|
18
|
+
async function main() {
|
|
19
|
+
if (command === 'help' || command === '--help' || command === undefined) {
|
|
20
|
+
console.log(`desklink-host
|
|
21
|
+
|
|
22
|
+
USAGE:
|
|
23
|
+
desklink-host path print the engine binary this package would run
|
|
24
|
+
desklink-host capabilities print what this machine can do right now
|
|
25
|
+
desklink-host bridge [--listen H:P] [--token T] [--source portal|x11] [--display :0]
|
|
26
|
+
re-serve the engine's protocol over a WebSocket and
|
|
27
|
+
print the URL to open; no signaling of your own needed
|
|
28
|
+
desklink-host <engine command> ... run the engine directly (serve, capture-probe, setup-input, version)
|
|
29
|
+
|
|
30
|
+
Set MUXR_DESKLINK_ENGINE to use an engine built somewhere else.`);
|
|
31
|
+
return 0;
|
|
32
|
+
}
|
|
33
|
+
if (command === 'path') {
|
|
34
|
+
const resolved = resolveEngine();
|
|
35
|
+
if (resolved === null) {
|
|
36
|
+
console.error(explainMissingEngine());
|
|
37
|
+
return 1;
|
|
38
|
+
}
|
|
39
|
+
console.log(resolved.command);
|
|
40
|
+
return 0;
|
|
41
|
+
}
|
|
42
|
+
if (command === 'bridge') {
|
|
43
|
+
const resolved = resolveEngine();
|
|
44
|
+
if (resolved === null) {
|
|
45
|
+
console.error(explainMissingEngine());
|
|
46
|
+
return 1;
|
|
47
|
+
}
|
|
48
|
+
const flag = (name, fallback) => {
|
|
49
|
+
const index = rest.indexOf(`--${name}`);
|
|
50
|
+
return index === -1 ? fallback : rest[index + 1];
|
|
51
|
+
};
|
|
52
|
+
const listen = flag('listen', '127.0.0.1:19400');
|
|
53
|
+
const token = flag('token', randomBytes(24).toString('base64url'));
|
|
54
|
+
if (typeof token !== 'string' || token.trim() === '') throw new Error('the bridge token must not be blank');
|
|
55
|
+
const sourceKind = flag('source', process.env.MUXR_DESKTOP_SOURCE ?? 'portal');
|
|
56
|
+
const display = flag('display', process.env.MUXR_DESKTOP_X11_DISPLAY);
|
|
57
|
+
const bridge = await Bridge.start({
|
|
58
|
+
listen,
|
|
59
|
+
token,
|
|
60
|
+
engineCommand: resolved.command,
|
|
61
|
+
engineArgs: resolved.args,
|
|
62
|
+
// The engine's own diagnostics are the only clue when a session
|
|
63
|
+
// fails below the protocol, so they are forwarded rather than
|
|
64
|
+
// swallowed.
|
|
65
|
+
engineOptions: { onDiagnostic: (line) => console.error(`engine: ${line}`) },
|
|
66
|
+
...(sourceKind === 'x11'
|
|
67
|
+
? { source: display === undefined ? { kind: 'x11' } : { kind: 'x11', display } }
|
|
68
|
+
: {}),
|
|
69
|
+
});
|
|
70
|
+
const host = listen.startsWith('0.0.0.0:') ? '<this machine>' : listen.split(':')[0];
|
|
71
|
+
console.log(`engine ${resolved.command}`);
|
|
72
|
+
console.log(`bridge ws://${listen}${'/desktop'}`);
|
|
73
|
+
console.log(`token ${token}`);
|
|
74
|
+
console.log('');
|
|
75
|
+
console.log(`open http://${host}:${bridge.port}/?token=${encodeURIComponent(token)}`);
|
|
76
|
+
console.log('');
|
|
77
|
+
console.log('Open that URL in a browser on this machine, or point a phone at it.');
|
|
78
|
+
console.log('ws:// is plaintext: keep it on a private network, or put it behind TLS.');
|
|
79
|
+
const stop = async () => { await bridge.close(); process.exit(0); };
|
|
80
|
+
process.on('SIGINT', () => void stop());
|
|
81
|
+
process.on('SIGTERM', () => void stop());
|
|
82
|
+
return await new Promise(() => undefined);
|
|
83
|
+
}
|
|
84
|
+
if (command === 'capabilities') {
|
|
85
|
+
const resolved = resolveEngine();
|
|
86
|
+
if (resolved === null) {
|
|
87
|
+
console.error(explainMissingEngine());
|
|
88
|
+
return 1;
|
|
89
|
+
}
|
|
90
|
+
const client = await EngineClient.start(resolved.command, resolved.args);
|
|
91
|
+
try {
|
|
92
|
+
console.log(JSON.stringify(await client.capabilities(), null, 2));
|
|
93
|
+
} finally {
|
|
94
|
+
await client.stop();
|
|
95
|
+
}
|
|
96
|
+
return 0;
|
|
97
|
+
}
|
|
98
|
+
const resolved = resolveEngine();
|
|
99
|
+
if (resolved === null) {
|
|
100
|
+
console.error(explainMissingEngine());
|
|
101
|
+
return 1;
|
|
102
|
+
}
|
|
103
|
+
const child = spawn(resolved.command, [command, ...rest], { stdio: 'inherit' });
|
|
104
|
+
return await new Promise((resolve) => child.on('exit', (code) => resolve(code ?? 0)));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
main().then(
|
|
108
|
+
(code) => process.exit(code),
|
|
109
|
+
(error) => {
|
|
110
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
111
|
+
process.exit(1);
|
|
112
|
+
},
|
|
113
|
+
);
|