@tomorrowos/sdk 0.9.28 → 0.9.30

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/README.md +7 -2
  2. package/VERCEL_SETUP.md +135 -115
  3. package/dist/cli.js +42 -11
  4. package/dist/tomorrowos.d.ts +13 -1
  5. package/dist/tomorrowos.d.ts.map +1 -1
  6. package/dist/tomorrowos.js +45 -9
  7. package/package.json +1 -1
  8. package/templates/cms-starter/package.json +2 -2
  9. package/templates/cms-starter/server.ts +2 -2
  10. package/templates/cms-starter-v0/.env.example +19 -0
  11. package/templates/cms-starter-v0/README.md +50 -0
  12. package/templates/cms-starter-v0/api/index.ts +10 -0
  13. package/templates/cms-starter-v0/assets/logo.svg +4 -0
  14. package/templates/cms-starter-v0/brand.json +23 -0
  15. package/templates/cms-starter-v0/cms-app.ts +75 -0
  16. package/templates/cms-starter-v0/cms-panel/assets/player-download/android.svg +1 -0
  17. package/templates/cms-starter-v0/cms-panel/assets/player-download/brightsign.svg +1 -0
  18. package/templates/cms-starter-v0/cms-panel/assets/player-download/lg-webos.svg +1 -0
  19. package/templates/cms-starter-v0/cms-panel/assets/player-download/samsung.svg +1 -0
  20. package/templates/cms-starter-v0/cms-panel/assets/player-download/toolbox.svg +1 -0
  21. package/templates/cms-starter-v0/cms-panel/index.html +290 -0
  22. package/templates/cms-starter-v0/cms-panel/methods.js +2361 -0
  23. package/templates/cms-starter-v0/cms-panel/panel.css +1127 -0
  24. package/templates/cms-starter-v0/cms-panel/uploads/.gitkeep +1 -0
  25. package/templates/cms-starter-v0/package.json +35 -0
  26. package/templates/cms-starter-v0/policy.example.json +30 -0
  27. package/templates/cms-starter-v0/preview/app/layout.tsx +11 -0
  28. package/templates/cms-starter-v0/preview/app/page.tsx +3 -0
  29. package/templates/cms-starter-v0/preview/next-env.d.ts +2 -0
  30. package/templates/cms-starter-v0/preview/next.config.mjs +18 -0
  31. package/templates/cms-starter-v0/preview/tsconfig.json +20 -0
  32. package/templates/cms-starter-v0/server.ts +6 -0
  33. package/templates/cms-starter-v0/tsconfig.json +13 -0
  34. package/templates/cms-starter-v0/vercel.json +17 -0
@@ -0,0 +1,290 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>TomorrowOS Control Panel</title>
7
+ <link rel="stylesheet" href="./panel.css" />
8
+ </head>
9
+ <body>
10
+ <header class="app-header">
11
+ <h1>TomorrowOS Control Panel</h1>
12
+ <p>Create playlists, save with confirm, then publish selected playlists per device.</p>
13
+ </header>
14
+
15
+ <div class="layout">
16
+ <aside class="panel-playlist-nav">
17
+ <div class="playlist-nav-header">
18
+ <h2>Playlists</h2>
19
+ <button type="button" class="primary" id="newPlaylistBtn" title="New playlist">+</button>
20
+ </div>
21
+ <ul id="playlistCatalog" class="playlist-catalog"></ul>
22
+ <div class="download-players-nav-slot">
23
+ <button type="button" id="downloadPlayersBtn" class="download-players-trigger">
24
+ Download Players
25
+ </button>
26
+ <button type="button" id="updateSdkBtn" class="download-players-trigger">
27
+ Update SDK
28
+ </button>
29
+ </div>
30
+ </aside>
31
+
32
+ <main class="panel-main">
33
+ <section class="card server-status-card" id="serverStatusSection" aria-live="polite">
34
+ <div class="server-status-header">
35
+ <h2>Server status</h2>
36
+ <button type="button" id="serverStatusRefreshBtn" title="Refresh status">Refresh</button>
37
+ </div>
38
+ <p class="hint server-status-overall" id="serverStatusOverall">Checking connectors…</p>
39
+ <ul class="server-status-list" id="serverStatusList"></ul>
40
+ <div id="serverStatusBlockers" class="server-status-blockers hidden"></div>
41
+ </section>
42
+
43
+ <section class="card">
44
+ <h2>Pair device</h2>
45
+ <p class="hint">Enter the 6-character code on the screen (A–Z or 0–9).</p>
46
+ <div class="row pair-code-row">
47
+ <input
48
+ id="code"
49
+ class="pair-code-input"
50
+ type="text"
51
+ maxlength="6"
52
+ placeholder="e.g. A3K9Z1"
53
+ autocapitalize="characters"
54
+ />
55
+ <button type="button" class="pair-verify-btn" onclick="verify()">Verify</button>
56
+ </div>
57
+ </section>
58
+
59
+ <section class="card" id="pairedDevicesSection">
60
+ <h2>Paired devices</h2>
61
+ <div id="devicesGrid" class="devices-grid">
62
+ <p class="devices-empty" id="devicesEmpty">No paired devices yet.</p>
63
+ </div>
64
+ </section>
65
+
66
+ <section class="card" id="cmsUrlSection">
67
+ <h2>CMS URL for screens</h2>
68
+ <p class="hint">
69
+ <strong>Local development only.</strong> Defaults to this PC’s LAN IP and listen port so TVs
70
+ can reach media (not localhost). Change and Save if the auto-detected address is wrong.
71
+ Hosted CMS (e.g. Replit) uses its public URL automatically — this section is hidden there.
72
+ </p>
73
+ <div class="row">
74
+ <input
75
+ id="cmsDeviceBaseUrl"
76
+ type="text"
77
+ style="flex: 1; min-width: 16rem"
78
+ placeholder="Detecting LAN address…"
79
+ />
80
+ <button type="button" onclick="saveCmsDeviceBaseUrl()">Save</button>
81
+ </div>
82
+ </section>
83
+
84
+ <section class="card hidden" id="playlistEditorSection">
85
+ <h2 id="editorTitle">Playlist editor</h2>
86
+ <p class="hint">Save confirms changes. Names must be unique. Schedule applies to this playlist only.</p>
87
+ <label class="field-label">
88
+ Name
89
+ <input type="text" id="playlistName" placeholder="e.g. Weekday promo" />
90
+ </label>
91
+
92
+ <h3 class="subheading">When this playlist plays</h3>
93
+ <p class="hint">
94
+ Leave blank for always on. Uses the <strong>TV/device local clock</strong> (not CMS server time).
95
+ Schedule is one continuous run: <strong>from date/time → until date/time</strong>
96
+ (e.g. May 5 13:00 through May 8 14:00), not a daily repeat inside those dates.
97
+ “Until” time stops at that moment (exclusive).
98
+ </p>
99
+ <div class="schedule-grid">
100
+ <label>
101
+ Run from (date)
102
+ <input type="date" id="scheduleStartDate" />
103
+ </label>
104
+ <label>
105
+ Run from (time)
106
+ <input type="time" id="scheduleStartTime" />
107
+ </label>
108
+ <label>
109
+ Run until (date)
110
+ <input type="date" id="scheduleEndDate" />
111
+ </label>
112
+ <label>
113
+ Run until (time)
114
+ <input type="time" id="scheduleEndTime" />
115
+ </label>
116
+ </div>
117
+
118
+ <div class="editor-actions">
119
+ <button type="button" class="primary" id="savePlaylistBtn">Save playlist</button>
120
+ <button type="button" class="danger" id="deletePlaylistBtn">Delete playlist</button>
121
+ </div>
122
+ </section>
123
+
124
+ <pre id="result" aria-live="polite"></pre>
125
+ </main>
126
+
127
+ <aside class="panel-playlist">
128
+ <div class="playlist-header">
129
+ <h2>Assets</h2>
130
+ <button type="button" class="primary" id="addAssetBtn" title="Add image or video">+</button>
131
+ </div>
132
+ <p class="hint playlist-assets-hint">Drag ⋮⋮ to reorder assets. Save playlist to keep the new order.</p>
133
+ <input
134
+ type="file"
135
+ id="fileInput"
136
+ class="hidden"
137
+ accept="image/*,video/*,.wgt,.zip"
138
+ multiple
139
+ />
140
+ <div id="uploadStatusShell" class="upload-status hidden" aria-live="polite">
141
+ <div id="uploadStatusText" class="upload-status-text">Uploading...</div>
142
+ <div class="upload-progress-track">
143
+ <div id="uploadProgressBar" class="upload-progress-bar"></div>
144
+ </div>
145
+ <div id="uploadQueueText" class="upload-queue-text"></div>
146
+ </div>
147
+ <ul id="playlistList" class="playlist-list">
148
+ <li class="playlist-empty" id="playlistEmpty">Select or create a playlist, then add assets.</li>
149
+ </ul>
150
+ </aside>
151
+ </div>
152
+
153
+ <div id="publishModal" class="modal hidden" role="dialog" aria-modal="true">
154
+ <div class="modal-backdrop" data-close-modal="1"></div>
155
+ <div class="modal-card">
156
+ <h2>Publish to device</h2>
157
+ <p class="hint" id="publishModalHint">Select playlists to add to this device. Already-published playlists are not listed here.</p>
158
+ <div id="publishChecklist" class="publish-checklist"></div>
159
+ <div id="publishStatusShell" class="publish-status hidden" aria-live="polite">
160
+ <div id="publishStatusText" class="publish-status-text">Working...</div>
161
+ <div class="upload-progress-track">
162
+ <div id="publishProgressBar" class="upload-progress-bar"></div>
163
+ </div>
164
+ </div>
165
+ <div class="modal-actions">
166
+ <button type="button" id="publishConfirmBtn" class="primary">Publish selected</button>
167
+ <button type="button" data-close-modal="1">Cancel</button>
168
+ </div>
169
+ </div>
170
+ </div>
171
+
172
+ <div id="screenshotModal" class="modal hidden" role="dialog" aria-modal="true">
173
+ <div class="modal-backdrop" data-close-screenshot-modal="1"></div>
174
+ <div class="modal-card screenshot-modal-card">
175
+ <h2>Latest screenshot</h2>
176
+ <p class="hint" id="screenshotModalHint">No screenshot loaded.</p>
177
+ <img id="screenshotModalImage" class="screenshot-preview hidden" alt="Latest device screenshot" />
178
+ <div class="modal-actions">
179
+ <button type="button" data-close-screenshot-modal="1">Close</button>
180
+ </div>
181
+ </div>
182
+ </div>
183
+
184
+ <div id="onOffTimerModal" class="modal hidden" role="dialog" aria-modal="true">
185
+ <div class="modal-backdrop" data-close-on-off-timer-modal="1"></div>
186
+ <div class="modal-card">
187
+ <h2>On / off timer</h2>
188
+ <p class="hint" id="onOffTimerModalHint">
189
+ Daily on/off times follow the device clock. Off blacks the screen; the player stays powered and connected to the CMS.
190
+ Removing the timer stops the schedule and leaves the screen in its current on or off state until you set a timer again.
191
+ </p>
192
+ <div class="on-off-timer-grid">
193
+ <label class="field-label">
194
+ Turn on (unmute)
195
+ <input type="time" id="onOffTimerTurnOnAt" value="06:00" />
196
+ </label>
197
+ <label class="field-label">
198
+ Turn off (mute)
199
+ <input type="time" id="onOffTimerTurnOffAt" value="18:00" />
200
+ </label>
201
+ </div>
202
+ <div class="modal-actions">
203
+ <button type="button" id="onOffTimerSaveBtn" class="primary">Save</button>
204
+ <button type="button" id="onOffTimerRemoveBtn" class="danger hidden">Remove timer</button>
205
+ <button type="button" data-close-on-off-timer-modal="1">Cancel</button>
206
+ </div>
207
+ </div>
208
+ </div>
209
+
210
+ <div id="downloadFailedModal" class="modal hidden" role="dialog" aria-modal="true">
211
+ <div class="modal-backdrop" data-close-download-failed-modal="1"></div>
212
+ <div class="modal-card">
213
+ <h2>Download failed</h2>
214
+ <p class="hint" id="downloadFailedModalMessage">Could not download this asset.</p>
215
+ <p class="hint">
216
+ For permanent, reliable storage of media assets, configure
217
+ <strong>Cloudinary</strong> on your CMS server (<code>CLOUDINARY_CLOUD_NAME</code>,
218
+ <code>CLOUDINARY_API_KEY</code>, <code>CLOUDINARY_API_SECRET</code>). Uploads stored on
219
+ Cloudinary use stable public URLs that are easier to download and share.
220
+ </p>
221
+ <div class="modal-actions">
222
+ <button type="button" data-close-download-failed-modal="1">Close</button>
223
+ </div>
224
+ </div>
225
+ </div>
226
+
227
+ <div id="updateSdkModal" class="modal hidden" role="dialog" aria-modal="true" aria-labelledby="updateSdkModalTitle">
228
+ <div class="modal-backdrop" data-close-update-sdk-modal="1"></div>
229
+ <div class="modal-card update-sdk-modal-card">
230
+ <h2 id="updateSdkModalTitle">Update SDK</h2>
231
+ <p class="hint">Current installed SDK version:</p>
232
+ <p class="update-sdk-version" id="updateSdkVersionLabel">Loading…</p>
233
+ <p class="hint">
234
+ To upgrade on AI agent platforms (Replit, Vercel, etc.), paste this prompt into the Agent chat:
235
+ </p>
236
+ <pre class="update-sdk-prompt" id="updateSdkPromptText">Follow @tomorrowos/sdk REPLIT_UPGRADE.md to upgrade my CMS with the latest SDK.</pre>
237
+ <div class="modal-actions update-sdk-modal-actions">
238
+ <button type="button" id="copyUpdateSdkPromptBtn" class="primary">Copy prompt</button>
239
+ <button type="button" data-close-update-sdk-modal="1">Close</button>
240
+ </div>
241
+ </div>
242
+ </div>
243
+
244
+ <div id="downloadPlayersModal" class="modal hidden" role="dialog" aria-modal="true" aria-labelledby="downloadPlayersModalTitle">
245
+ <div class="modal-backdrop" data-close-download-players-modal="1"></div>
246
+ <div class="modal-card download-players-modal-card">
247
+ <h2 id="downloadPlayersModalTitle" class="visually-hidden">Download Players</h2>
248
+ <div class="player-platform-grid">
249
+ <div class="player-platform-cell">
250
+ <a
251
+ href="https://tmr.sh/app/brightsign/TomorrowOS_BrightSign.zip"
252
+ class="player-platform-link"
253
+ rel="noopener noreferrer"
254
+ >
255
+ <img src="./assets/player-download/brightsign.svg" alt="BrightSign" class="player-platform-logo player-platform-logo--wide" />
256
+ </a>
257
+ <p class="player-platform-caption">Supported Series 5 / 6</p>
258
+ </div>
259
+ <div class="player-platform-cell">
260
+ <a
261
+ href="https://tmr.sh/app/tizen/TomorrowOS_Tizen.zip"
262
+ class="player-platform-link"
263
+ rel="noopener noreferrer"
264
+ >
265
+ <img src="./assets/player-download/samsung.svg" alt="Samsung" class="player-platform-logo player-platform-logo--wide" />
266
+ </a>
267
+ <p class="player-platform-caption">Supported Tizen 6.5+</p>
268
+ </div>
269
+ <div class="player-platform-cell">
270
+ <img src="./assets/player-download/android.svg" alt="Android" class="player-platform-logo player-platform-logo--wide" />
271
+ <p class="player-platform-caption player-platform-caption--muted">Launching Q4 2026</p>
272
+ </div>
273
+ <div class="player-platform-cell">
274
+ <img src="./assets/player-download/lg-webos.svg" alt="LG webOS" class="player-platform-logo player-platform-logo--wide" />
275
+ <p class="player-platform-caption player-platform-caption--muted">Launching Q4 2026</p>
276
+ </div>
277
+ </div>
278
+ <div class="player-platform-diy">
279
+ <img src="./assets/player-download/toolbox.svg" alt="" class="player-platform-toolbox" />
280
+ <p class="player-platform-caption">Build your own player support</p>
281
+ </div>
282
+ <div class="modal-actions download-players-modal-actions">
283
+ <button type="button" data-close-download-players-modal="1">Close</button>
284
+ </div>
285
+ </div>
286
+ </div>
287
+
288
+ <script src="./methods.js" defer></script>
289
+ </body>
290
+ </html>