@tomorrowos/sdk 0.7.9 → 0.8.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/REPLIT_SETUP.md CHANGED
@@ -12,6 +12,7 @@ When a human pastes a prompt like this, **read this file and start Question 1 im
12
12
  ```text
13
13
  Follow @tomorrowos/sdk REPLIT_SETUP.md and set up my TomorrowOS CMS.
14
14
  Ask only the questions listed in REPLIT_SETUP.md, in order. Do not use LLM_PROMPT.md.
15
+ After all setup questions are answered (including Cloudinary Secrets if you chose Cloudinary), configure and start — minimal verification only (Web app type + Preview at /). No Supabase or WebSocket tests.
15
16
  Do not skip steps.
16
17
  ```
17
18
 
@@ -35,16 +36,19 @@ Replit Agent must ask **only** the questions defined in **this file**, in **this
35
36
  | 1 | **Question 1** — How many screens / devices? | Always |
36
37
  | 2 | **Question 2** — Supabase connection | Only if answer to Q1 is **> 5** |
37
38
  | 3 | **Question 3** — Media storage (Cloudinary vs Object Storage) | Always (after Q1 or Q2) |
39
+ | 3b | **Question 3b** — Cloudinary credentials (Secrets) | **Mandatory** if Q3 answer is Cloudinary / yes — **before Q4** |
38
40
  | 4 | **Question 4** — Brand / TomorrowOS app look | Always last, before execution |
39
41
 
40
42
  **That is the complete list.** There are no other setup questions.
41
43
 
44
+ **Critical:** Question 3 is **not complete** when the user says “Cloudinary” or “yes”. You **must** run **Question 3b** and collect `CLOUDINARY_CLOUD_NAME`, `CLOUDINARY_API_KEY`, and `CLOUDINARY_API_SECRET` (as Replit Secrets) **before** asking Question 4. Do **not** skip to branding with placeholder or invented credentials.
42
45
 
43
- If the user volunteers extra info early (e.g. brand name before Q4), **record it** and still ask the current question’s required fields you do not yet have. Do not skip ahead to execution until Q1–Q4 (or Q1, Q3, Q4 if ≤5 screens) are complete.
46
+
47
+ If the user volunteers extra info early (e.g. brand name before Q4), **record it** and still ask the current question’s required fields you do not yet have. Do not skip ahead to execution until Q1–Q4 (or Q1, Q3, Q3b, Q4 if ≤5 screens and Cloudinary) are complete.
44
48
 
45
49
  If the user says “just set it up, don’t ask questions,” respond:
46
50
 
47
- > I need four quick answers from REPLIT_SETUP.md (screen count, media storage, and branding). It takes about a minute and ensures the CMS deploys correctly on Replit.
51
+ > I need a few quick answers from REPLIT_SETUP.md (screen count, media storage — plus Cloudinary credentials if you choose Cloudinary — and branding). It takes about a minute and ensures the CMS deploys correctly on Replit.
48
52
 
49
53
  Then ask **Question 1** — do not switch to `LLM_PROMPT.md`.
50
54
 
@@ -52,24 +56,21 @@ Then ask **Question 1** — do not switch to `LLM_PROMPT.md`.
52
56
 
53
57
  ## Hard rules
54
58
 
55
- 1. **Ask only REPLIT_SETUP.md questions 1–4** (see **Questionnaire scope**). Never use `LLM_PROMPT.md` on Replit.
56
- 2. **One question at a time.** Wait for the user’s answer before asking the next question (unless they already answered several in one message).
59
+ 1. **Ask only REPLIT_SETUP.md questions 1–4 and 3b when required** (see **Questionnaire scope**). Never use `LLM_PROMPT.md` on Replit.
60
+ 2. **One question at a time.** Wait for the user’s answer before asking the next question (unless they already answered several in one message). **Exception:** Question 3b may ask for all three Cloudinary Secrets in one message — still **stop and wait** for the user’s values before Question 4.
57
61
  3. **Do not invent** screen counts, Cloudinary credentials, Supabase URLs, or brand colours.
58
62
  4. **Do not use Replit’s reserved `DATABASE_URL` Secret for Supabase.** On Replit, `DATABASE_URL` is often pre-claimed. Always use **`SUPABASE_URL`** for TomorrowOS ↔ Supabase.
59
63
  5. **Prefer `npx @tomorrowos/sdk init`** (or the package’s `templates/cms-starter`) as the project seed. Do not rebuild pairing, WebSocket, or playlist APIs from scratch.
60
64
  6. **Never commit secrets** into git. Put credentials only in Replit **Secrets** (and optionally mirror non-secret flags in `.env` that reference env vars).
61
- 7. After Q&A, apply configuration, install deps, start the server, and verify:
62
- - HTTP Control Panel loads
63
- - `GET /brand.json` returns 200
64
- - WebSocket upgrade on `wss://<repl-host>/` succeeds (critical for TV pairing)
65
+ 7. After Q&A, **configure and start** do **not** run a long test suite (see **Post-Q&A: minimal verification only**).
65
66
  8. **Follow the Runtime & Replit publish rules below exactly.** A project that cannot Deploy / Publish on Replit is incomplete.
66
67
 
67
68
  **Question order after Q1:**
68
69
 
69
- - If **≤ 5 screens:** Q1 → Q3 → Q4 → execution checklist
70
- - If **> 5 screens:** Q1 → Q2 → Q3 → Q4 → execution checklist
70
+ - If **≤ 5 screens:** Q1 → Q3 → (Q3b if Cloudinary) → Q4 → execution checklist
71
+ - If **> 5 screens:** Q1 → Q2 → Q3 → (Q3b if Cloudinary) → Q4 → execution checklist
71
72
 
72
- Never insert extra questions between these steps.
73
+ Never insert extra questions between these steps. **Never skip Question 3b** when the user chose Cloudinary.
73
74
 
74
75
  ---
75
76
 
@@ -200,7 +201,7 @@ Allowed extras (optional): `"build-player": "tomorrowos build --platform tizen"`
200
201
  "node": ">=20"
201
202
  },
202
203
  "dependencies": {
203
- "@tomorrowos/sdk": "^0.7.9",
204
+ "@tomorrowos/sdk": "^0.8.0",
204
205
  "dotenv": "^17.2.3",
205
206
  "tsx": "^4.19.0"
206
207
  },
@@ -252,21 +253,13 @@ If the workspace already has a `.replit`, **merge** these keys — do not wipe u
252
253
 
253
254
  ### Publish readiness checklist (before telling the user “done”)
254
255
 
255
- 1. Replit project / primary artifact is **Web app** (not API-only / `api-kind`)
256
- 2. `.replit` has `entrypoint = "server.ts"`, `modules = ["nodejs-20"]`, `[[ports]]` with `externalPort = 80`, `deploymentTarget = "autoscale"`
257
- 3. Publishing type is **Autoscale** or **Reserved VM** (not Static-only)
258
- 4. `package.json` has `scripts.start` = `tsx server.ts`
259
- 5. `tsx` is listed under `dependencies` (runtime-safe for Deploy)
260
- 6. Dependency is `@tomorrowos/sdk` (not a fork or vendored rewrite)
261
- 7. `.replit` Run + `[deployment].run` use `npm run start`
262
- 8. Node is **20+**
263
- 9. Preview at `/` shows the TomorrowOS Control Panel (not Canvas, not another app, not API JSON)
264
- 10. Stale processes / port conflicts cleared before publish
265
- 11. `npm run start` prints `[TomorrowOS] listening on http://0.0.0.0:...`
266
- 12. Browser WebSocket test to `wss://<host>/` succeeds
267
- 13. Secrets required by the Q&A answers are set (`SUPABASE_URL`, Cloudinary, etc.)
268
-
269
- If any item fails, fix it before finishing.
256
+ **Only these three checks matter after setup.** Do not add more unless Publish fails.
257
+
258
+ 1. **Web app, not API** project / primary artifact is **Web app** (not `api-kind` / API-only).
259
+ 2. **`.replit` is correct** — `entrypoint = "server.ts"`, `modules = ["nodejs-20"]`, `[[ports]]` with `externalPort = 80`, `deploymentTarget = "autoscale"`, Run/Deploy = `npm run start`.
260
+ 3. **Preview at `/`** — after `npm run start`, logs show `[TomorrowOS] listening on http://0.0.0.0:...` and Preview shows the Control Panel (HTML), not empty / API JSON.
261
+
262
+ If all three pass, tell the user setup is complete. **Do not** block on extra tests below.
270
263
 
271
264
  ### Preview requirements (Replit workspace)
272
265
 
@@ -300,11 +293,37 @@ Tell the user their live CMS URLs:
300
293
 
301
294
  Replace `YOUR-REPLIT-DOMAIN` with the actual published hostname (e.g. `my-cms.replit.app`).
302
295
 
303
- Verify after publish:
296
+ **Do not** run post-publish smoke tests unless the user reports a problem. Telling them the URL is enough.
297
+
298
+ ---
299
+
300
+ ## Post-Q&A: minimal verification only
301
+
302
+ After Questions 1–4, **configure → `npm install` → `npm run start` → done.**
303
+
304
+ ### Do (maximum)
305
+
306
+ 1. Confirm **Web app** artifact (not API) — **most important**.
307
+ 2. Write Secrets / `.env` / `brand.json` / `server.ts` / `.replit` from answers.
308
+ 3. `npm install` && `npm run start`.
309
+ 4. Glance at logs for `[TomorrowOS] listening on http://0.0.0.0:...`.
310
+ 5. Glance at Preview — Control Panel visible at `/`.
304
311
 
305
- 1. `https://YOUR-REPLIT-DOMAIN/` shows the Control Panel (not empty, not API docs).
306
- 2. `https://YOUR-REPLIT-DOMAIN/brand.json` returns 200.
307
- 3. WebSocket to `wss://YOUR-REPLIT-DOMAIN/` succeeds.
312
+ ### Do NOT run after setup (unless user asks or Publish fails)
313
+
314
+ - **Supabase connection test** (no `psql`, no DB ping, no “testing Supabase connection…”)
315
+ - ❌ **Cloudinary upload test**
316
+ - ❌ **`curl` / `fetch` on `/brand.json`** as a formal gate
317
+ - ❌ **Browser WebSocket console snippet** as a formal gate
318
+ - ❌ **Publishing dry-run** unless the user asked to publish now
319
+ - ❌ **Long troubleshooting loops** when Preview already shows the Control Panel
320
+ - ❌ Re-running the full **Publish readiness checklist** item-by-item in chat
321
+
322
+ If Preview shows the Control Panel and the project is **Web app** type, **stop testing** and give the user their URL and next steps.
323
+
324
+ ### Only if Preview is empty or Publish fails
325
+
326
+ Then (and only then) check: API vs Web type → `.replit` ports/`deploymentTarget` → stale process / port conflict → see **Failure recovery cheat sheet**.
308
327
 
309
328
  ---
310
329
 
@@ -383,6 +402,7 @@ DATABASE_SSL=true
383
402
  ```
384
403
 
385
404
  5. **Do not** write the real password into committed files.
405
+ 6. **Do not** test the Supabase connection after saving the Secret — configuration only.
386
406
 
387
407
  If the user refuses Supabase but chose > 5 screens, warn them SQLite on Replit is fragile for fleets, then offer SQLite only after they confirm.
388
408
 
@@ -402,20 +422,47 @@ If the user refuses Supabase but chose > 5 screens, warn them SQLite on Replit i
402
422
  >
403
423
  > Do you want me to set up **Cloudinary**? (yes / no)
404
424
 
405
- ### If YES — Cloudinary
425
+ ### If YES — Cloudinary → go to Question 3b (do not ask Question 4 yet)
406
426
 
407
- **Ask for (or open a Secrets form for):**
427
+ Choosing Cloudinary **does not finish** Question 3. Immediately continue to **Question 3b** below.
408
428
 
409
- - `CLOUDINARY_CLOUD_NAME`
410
- - `CLOUDINARY_API_KEY`
411
- - `CLOUDINARY_API_SECRET`
412
- - Optional: `CLOUDINARY_FOLDER` (e.g. `tomorrowos`)
429
+ ---
430
+
431
+ ## Question 3b — Cloudinary credentials (mandatory if Q3 = Cloudinary)
413
432
 
414
- Store these as Replit Secrets. The SDK auto-detects them and uploads media to Cloudinary instead of local disk.
433
+ > **Ask this before Question 4.** Do not jump to `brand.json` until the user has provided credentials or confirmed they are saved as Replit Secrets.
434
+
435
+ **Ask exactly (copy wording):**
436
+
437
+ > Great — I’ll use **Cloudinary** for media uploads.
438
+ >
439
+ > Please paste your Cloudinary credentials (from [cloudinary.com/console](https://cloudinary.com/console) → Dashboard → **API Keys**). I will store them as Replit **Secrets** — never in committed files:
440
+ >
441
+ > 1. **`CLOUDINARY_CLOUD_NAME`** — your cloud name (e.g. `dxyz123abc`)
442
+ > 2. **`CLOUDINARY_API_KEY`** — API Key
443
+ > 3. **`CLOUDINARY_API_SECRET`** — API Secret
444
+ >
445
+ > Optional: **`CLOUDINARY_FOLDER`** (e.g. `tomorrowos`) — say if you want a folder prefix.
446
+ >
447
+ > You can paste all three in one reply, or use Replit’s Secrets panel and tell me when each Secret is set.
448
+
449
+ **You must then:**
450
+
451
+ 1. Create / update Replit Secrets:
452
+ - `CLOUDINARY_CLOUD_NAME=<user value>`
453
+ - `CLOUDINARY_API_KEY=<user value>`
454
+ - `CLOUDINARY_API_SECRET=<user value>`
455
+ - Optional: `CLOUDINARY_FOLDER=<user value>`
456
+ 2. **Do not** write real secrets into `.env` files that are committed to git. Replit Secrets only (or `.env` that is gitignored and references env vars).
457
+ 3. **Do not** invent or placeholder Cloudinary credentials.
458
+ 4. **Do not** proceed to Question 4 until all three required Secrets exist.
459
+ 5. **Do not** run a Cloudinary upload test — configuration only.
415
460
 
416
461
  Tell the user:
417
462
 
418
- > After Cloudinary Secrets are set, restart the Repl. New uploads should return `https://res.cloudinary.com/...` URLs.
463
+ > After Cloudinary Secrets are set, we’ll finish branding and start the CMS. New uploads will return `https://res.cloudinary.com/...` URLs.
464
+
465
+ **If the user does not have a Cloudinary account yet:** tell them to sign up at cloudinary.com, create API keys, then return with the three values. **Wait** — do not skip to Question 4.
419
466
 
420
467
  ### If NO — Replit Object Storage (or local)
421
468
 
@@ -546,8 +593,6 @@ CLOUDINARY_API_SECRET=...
546
593
 
547
594
  ### E. Install and run
548
595
 
549
- **Before starting:** stop stale processes, clear old background tasks, free the port if needed, restart workspace if stuck.
550
-
551
596
  ```bash
552
597
  npm install
553
598
  npm run start
@@ -555,30 +600,15 @@ npm run start
555
600
 
556
601
  (Use `npm run dev` only for local edit/watch. **Publish / Deploy / Replit Run must use `npm run start`.**)
557
602
 
558
- Confirm logs contain something like:
559
-
560
- ```text
561
- [TomorrowOS] listening on http://0.0.0.0:<PORT>
562
- ```
563
-
564
- Confirm the **Web preview** (not Canvas) shows the Control Panel at `/`.
565
-
566
- ### F. Verify before telling the user “done”
603
+ **Minimal check:** logs contain `[TomorrowOS] listening on http://0.0.0.0:...` and Preview shows Control Panel at `/`. Then proceed to **G** — no further tests.
567
604
 
568
- 1. Replit project type is **Web**; preview at `/` shows Control Panel (not empty, not Canvas-only).
569
- 2. Open the Control Panel URL.
570
- 3. `GET /brand.json` → 200 and correct `name` / colours.
571
- 4. In browser console on the Control Panel origin:
605
+ ### F. Done skip extended verification
572
606
 
573
- ```javascript
574
- const ws = new WebSocket(location.origin.replace(/^http/, "ws") + "/");
575
- ws.onopen = () => console.log("WS OK");
576
- ws.onerror = (e) => console.log("WS ERR", e);
577
- ```
607
+ If the **three-item Publish readiness checklist** passes (especially **Web app, not API**), mark setup complete.
578
608
 
579
- 5. Confirm the **Publish readiness checklist** in **Runtime & Replit publish rules**.
609
+ **Do not** run WebSocket console tests, Supabase connection tests, or `brand.json` curl checks here.
580
610
 
581
- If WebSocket fails, fix Run command / process crash / sleep **before** asking the user to pair a TV.
611
+ Only investigate further if Preview is empty, server crashed, or user reports Publish failure.
582
612
 
583
613
  ### G. Tell the user next steps (no code)
584
614
 
@@ -611,12 +641,14 @@ Do **not**:
611
641
  - Change the production start command away from `tsx server.ts` / `npm run start`
612
642
  - Point Supabase at Replit’s reserved `DATABASE_URL` when `SUPABASE_URL` should be used
613
643
  - Skip Cloudinary recommendation without stating the persistence tradeoff
644
+ - **Skip Question 3b** after the user chooses Cloudinary — always collect `CLOUDINARY_*` Secrets before Question 4
614
645
  - Claim uploads are “permanent” on Replit local disk without Object Storage or Cloudinary
615
646
  - Leave `tsx` only in `devDependencies` if the Deploy pipeline installs production deps only
616
647
  - Use Canvas preview as the primary CMS verification surface
617
648
  - Serve a different app or API-only response at `/` instead of the Control Panel
618
649
  - Create the Repl as **API-only** or publish with **Static Deployment** only
619
650
  - Omit `[[ports]]` / `deploymentTarget` from `.replit` when setting up for Publish
651
+ - Run **Supabase connection tests**, **WebSocket console tests**, or other post-setup smoke tests unless Preview fails or the user asks
620
652
 
621
653
  ---
622
654
 
@@ -657,6 +689,8 @@ TOMORROWOS_STORE=sqlite
657
689
 
658
690
  ## Protocol version
659
691
 
660
- `replit-setup/1.2` — aligned with TomorrowOS protocol `1.0` and `@tomorrowos/sdk` store drivers `sqlite` | `supabase` | `postgres` | `memory`.
692
+ `replit-setup/1.4` — aligned with TomorrowOS protocol `1.0` and `@tomorrowos/sdk` store drivers `sqlite` | `supabase` | `postgres` | `memory`.
693
+
694
+ **Changelog 1.4:** **Question 3b** — mandatory Cloudinary credential collection (Replit Secrets) before Question 4; fixes agents skipping secrets after “yes” to Cloudinary.
661
695
 
662
- **Changelog 1.2:** Web app deployability rules avoid `api-kind` publish failure; full `.replit` with `[[ports]]`, `deploymentTarget = "autoscale"`, `entrypoint = "server.ts"`.
696
+ **Changelog 1.3:** minimal post-Q&A verificationno Supabase/WS smoke tests; prioritize **Web app vs API** only.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomorrowos/sdk",
3
- "version": "0.7.9",
3
+ "version": "0.8.0",
4
4
  "description": "TomorrowOS CMS server SDK - WebSocket transport, pairing, device commands, optional static CMS UI. Includes CLI (tomorrowos init / build) and starter templates.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "my-cms",
3
- "version": "0.7.9",
3
+ "version": "0.8.0",
4
4
  "description": "CMS server on @tomorrowos/sdk. Add your UI (React, static files, etc.) alongside this server.",
5
5
  "private": true,
6
6
  "type": "module",
@@ -13,7 +13,7 @@
13
13
  "build-player": "tomorrowos build --platform tizen"
14
14
  },
15
15
  "dependencies": {
16
- "@tomorrowos/sdk": "^0.7.9",
16
+ "@tomorrowos/sdk": "^0.8.0",
17
17
  "dotenv": "^17.2.3",
18
18
  "tsx": "^4.19.0"
19
19
  },