chore(apps): remove TypeScript cloud SDK (re-apply #738 onto main)#743
Conversation
- Remove the publishable apps/libs/sdk-typescript project and its
Nx/build references.
- Replace Dashboard's prior @boxlite-ai/sdk usage with a
Dashboard-private cloudBox adapter backed by generated REST clients.
- Remove TypeScript Cloud SDK playground snippets so the UI no longer
teaches users to install @boxlite-ai/sdk.
The large diff is not because the delete itself is complicated. It is
because `apps/libs/sdk-typescript` had two roles mixed together: it was
a customer-facing package, and Dashboard was also importing it as an
internal cloud box facade.
Legend:
- `*** DELETE TARGET ***` = the package this PR removes.
- `*** REMOVED USER SURFACE ***` = user-facing code/docs path removed
because it advertised that package.
- `[kept]` = still exists after this PR.
- `[new internal]` = Dashboard-only replacement, not a public SDK.
```text
BEFORE
*** REMOVED USER SURFACE ***
+------------------------------------------------+
| Playground TypeScript snippet |
| tells users: npm install @boxlite-ai/sdk |
+-------------------------+----------------------+
|
| teaches users this package exists
v
+------------------------------------------------+ imports +------------------------------------------------+
| Dashboard Playground | -----------------> | *** DELETE TARGET *** |
| hooks/providers/VNC/snippets | | apps/libs/sdk-typescript |
| | | public package: @boxlite-ai/sdk |
+------------------------------------------------+ +-------------------------+----------------------+
|
| wraps
v
+------------------------------------------------+
| [kept] generated REST API clients |
| api-client / toolbox-api-client |
+-------------------------+----------------------+
|
| HTTP
v
+------------------------------------------------+
| [kept] BoxLite API / toolbox runtime |
+------------------------------------------------+
Build graph tied to the delete target:
Dashboard tsconfig alias -> Vite SDK alias/polyfills -> Nx dependency -> Docker COPY -> eslint exception
```
```text
AFTER
*** REMOVED USER SURFACE ***
+------------------------------------------------+
| Playground TypeScript snippet |
| npm install @boxlite-ai/sdk |
| |
| STATUS: DELETED |
+------------------------------------------------+
*** DELETE TARGET ***
+------------------------------------------------+
| apps/libs/sdk-typescript |
| public package: @boxlite-ai/sdk |
| |
| STATUS: DELETED |
+------------------------------------------------+
Dashboard internal path, after removing the public SDK dependency:
+------------------------------------------------+ imports +------------------------------------------------+
| [kept] Dashboard Playground | -----------------> | [new internal] Dashboard-private cloudBox |
| hooks/providers/VNC/snippets | | apps/dashboard/src/lib/cloudBox.ts |
| | | small adapter; not published to customers |
+------------------------------------------------+ +-------------------------+----------------------+
|
| calls
v
+------------------------------------------------+
| [kept] generated REST API clients |
| api-client / toolbox-api-client |
+-------------------------+----------------------+
|
| HTTP
v
+------------------------------------------------+
| [kept] BoxLite API / toolbox runtime |
+------------------------------------------------+
Build graph cleanup after deleting the target:
No @boxlite-ai/sdk alias -> no SDK Vite polyfills -> no Nx build edge -> no Docker COPY -> no SDK lint exception
```
So the diff fans out into four necessary buckets:
1. Delete the public SDK project itself: `apps/libs/sdk-typescript/**`.
2. Keep Dashboard working by replacing SDK imports with
`apps/dashboard/src/lib/cloudBox.ts`.
3. Stop advertising the removed SDK in Playground code snippets.
4. Remove build-system references that would otherwise point at a
deleted project.
- NX_DAEMON=false corepack yarn nx build dashboard
--configuration=development --nxBail=true --output-style=stream
- NX_DAEMON=false corepack yarn nx build api --configuration=development
--nxBail=true --output-style=stream
- make lint:apps
- rg -n "@boxlite-ai/sdk|sdk-typescript" . -S
📝 WalkthroughWalkthroughIntroduce a CloudBox client abstraction and helpers, refactor dashboard hooks/components to call API clients and use CloudBox types, remove SDK-TypeScript aliases and tooling, and update build/config to stop referencing the local TypeScript SDK. ChangesSDK-TypeScript Migration to CloudBox Abstraction
Sequence DiagramsequenceDiagram
participant UI as Dashboard UI (hook)
participant useApi as useApi
participant BoxApi as boxApi
participant Poll as waitUntilStarted
participant CloudBox as createCloudBox
UI->>useApi: request boxApi, toolboxApi
UI->>BoxApi: createBox(request, orgId)
BoxApi-->>UI: ApiBox
UI->>Poll: waitUntilStarted(ApiBox)
Poll-->>UI: started ApiBox
UI->>CloudBox: createCloudBox(ApiBox, api, orgId)
CloudBox-->>UI: CloudBox (capabilities)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
apps/dashboard/src/hooks/useBoxSession.ts (2)
174-184:⚠️ Potential issue | 🟠 Major | ⚡ Quick winPoll VNC status until it becomes ready instead of failing on the first non-
activestate.This query treats every transitional status as an error.
starting/pendingwill surface as “failed to become ready” even though the desktop is still booting. The default React Query retry backoff is not a readiness poll; this needs the same poll-until-ready behavior you added for box startup.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/dashboard/src/hooks/useBoxSession.ts` around lines 174 - 184, The vncStatusQuery currently throws on any non-'active' status which treats transient states as errors; change vncStatusQuery (the useQuery wrapping toolboxApi.getComputerUseStatusDeprecated) to not throw on transitional statuses but instead return the current status and enable polling until it becomes 'active'—e.g., have the queryFn return status without throwing, add a refetchInterval (or a function refetchInterval that returns e.g. 1000–2000ms while data !== 'active' and false when 'active'), keep the same enabled condition (vnc && !!boxId && startVncMutation.isSuccess), and optionally use onSuccess to perform any one-time side effects when status === 'active'. Ensure queryKey remains queryKeys.box.vncStatus(resolvedScope, boxId).
130-149:⚠️ Potential issue | 🟠 Major | ⚡ Quick winGate terminal and VNC calls on
selectedOrganization.idtoo.The create/load paths now hard-fail without an organization ID, but the port preview and VNC flows still call organization-scoped endpoints with
selectedOrganization?.id. If a persistedboxIdexists while org selection is still loading or switching, these requests can run against the wrong scope beforeboxQueryhas a chance to block them.Also applies to: 174-191
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/dashboard/src/hooks/useBoxSession.ts` around lines 130 - 149, The port-preview and VNC flows call org-scoped endpoints with selectedOrganization?.id while not gating on its presence; update getPortPreviewUrl (useCallback) and any related functions to require a non-null selectedOrganization.id, add selectedOrganization?.id to their dependency lists, and change query/mutation enabling so they only run when selectedOrganization?.id is truthy (e.g., terminalQuery.enabled becomes terminal && !!boxId && !!selectedOrganization?.id) and startVncMutation is either disabled until the org id exists or performs an explicit guard that throws/returns early if selectedOrganization?.id is missing; apply the same gating fix to the other VNC/port-related code referenced around the 174-191 region.apps/dashboard/src/providers/PlaygroundProvider.tsx (1)
300-325:⚠️ Potential issue | 🟠 Major | ⚡ Quick winThe image-selection branch is still unreachable after removing templates.
createBoxFromTemplate = useCustomImageName || useDefaultResourceValuesstill routes the default and custom-image paths throughcreateBoxFromTemplateParams = {}. That means the newimage: 'base'default is dropped, and any non-defaulttemplateNameis dropped too. Both the Playground run flow and the generated snippets end up ignoring the selected image.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/dashboard/src/providers/PlaygroundProvider.tsx` around lines 300 - 325, The branch routing is wrong: stop treating custom/default images as "template" paths and ensure they use createBoxFromImageParams (so the image: 'base' default and any custom templateName survive). Change createBoxFromTemplate so it only represents real template use (or simply false if templates are removed) instead of using useCustomImageName || useDefaultResourceValues, and set createBoxFromImage = useCustomImageName || !useDefaultResourceValues (so both custom-image and non-default-resource flows go into createBoxFromImage). Keep createBoxFromImageParams (and its resources assignment) as-is and return/assign createBoxFromImageParams when createBoxFromImage is true; leave createBoxFromTemplateParams for actual template flows only.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/dashboard/src/lib/cloudBox.ts`:
- Around line 404-421: In getRunCommand, argv is currently built with
params?.argv?.join(' ') which allows spaces/metacharacters to be split by the
shell; instead map over params.argv and shell-escape/quote each entry (e.g.,
wrap each argument in single quotes and escape embedded single quotes) then join
those quoted entries with spaces and use that quoted-argv string in the returned
command templates for CodeLanguage.PYTHON, JAVASCRIPT and TYPESCRIPT so each
original param value is passed as a single literal argument to
python3/node/ts-node.
---
Outside diff comments:
In `@apps/dashboard/src/hooks/useBoxSession.ts`:
- Around line 174-184: The vncStatusQuery currently throws on any non-'active'
status which treats transient states as errors; change vncStatusQuery (the
useQuery wrapping toolboxApi.getComputerUseStatusDeprecated) to not throw on
transitional statuses but instead return the current status and enable polling
until it becomes 'active'—e.g., have the queryFn return status without throwing,
add a refetchInterval (or a function refetchInterval that returns e.g.
1000–2000ms while data !== 'active' and false when 'active'), keep the same
enabled condition (vnc && !!boxId && startVncMutation.isSuccess), and optionally
use onSuccess to perform any one-time side effects when status === 'active'.
Ensure queryKey remains queryKeys.box.vncStatus(resolvedScope, boxId).
- Around line 130-149: The port-preview and VNC flows call org-scoped endpoints
with selectedOrganization?.id while not gating on its presence; update
getPortPreviewUrl (useCallback) and any related functions to require a non-null
selectedOrganization.id, add selectedOrganization?.id to their dependency lists,
and change query/mutation enabling so they only run when
selectedOrganization?.id is truthy (e.g., terminalQuery.enabled becomes terminal
&& !!boxId && !!selectedOrganization?.id) and startVncMutation is either
disabled until the org id exists or performs an explicit guard that
throws/returns early if selectedOrganization?.id is missing; apply the same
gating fix to the other VNC/port-related code referenced around the 174-191
region.
In `@apps/dashboard/src/providers/PlaygroundProvider.tsx`:
- Around line 300-325: The branch routing is wrong: stop treating custom/default
images as "template" paths and ensure they use createBoxFromImageParams (so the
image: 'base' default and any custom templateName survive). Change
createBoxFromTemplate so it only represents real template use (or simply false
if templates are removed) instead of using useCustomImageName ||
useDefaultResourceValues, and set createBoxFromImage = useCustomImageName ||
!useDefaultResourceValues (so both custom-image and non-default-resource flows
go into createBoxFromImage). Keep createBoxFromImageParams (and its resources
assignment) as-is and return/assign createBoxFromImageParams when
createBoxFromImage is true; leave createBoxFromTemplateParams for actual
template flows only.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: c3f2c9e9-4ab9-40bf-8375-4529dcda8daf
📒 Files selected for processing (66)
apps/api/Dockerfileapps/dashboard/.storybook/main.tsapps/dashboard/project.jsonapps/dashboard/src/components/Playground/Box/CodeSnippets/code-language.test.tsapps/dashboard/src/components/Playground/Box/CodeSnippets/index.tsapps/dashboard/src/components/Playground/Box/CodeSnippets/types.tsapps/dashboard/src/components/Playground/Box/CodeSnippets/typescript.tsapps/dashboard/src/components/Playground/Box/CodeSnippetsResponse.tsxapps/dashboard/src/components/Playground/Box/Parameters/Management.tsxapps/dashboard/src/components/Playground/Box/Parameters/ProcessCodeExecution.tsxapps/dashboard/src/components/Playground/VNC/Interaction/Display.tsxapps/dashboard/src/components/Playground/VNC/Interaction/Keyboard.tsxapps/dashboard/src/components/Playground/VNC/Interaction/Mouse.tsxapps/dashboard/src/components/Playground/VNC/Interaction/Screenshot.tsxapps/dashboard/src/contexts/PlaygroundContext.tsxapps/dashboard/src/hooks/mutations/useCreateBoxMutation.tsxapps/dashboard/src/hooks/useBoxSession.tsapps/dashboard/src/lib/cloudBox.tsapps/dashboard/src/lib/playground.tsxapps/dashboard/src/providers/PlaygroundProvider.tsxapps/dashboard/tsconfig.app.jsonapps/dashboard/vite.config.mtsapps/eslint.config.mjsapps/infra-local/scripts/stack-up.shapps/libs/sdk-typescript/LICENSEapps/libs/sdk-typescript/README.mdapps/libs/sdk-typescript/hooks/typedoc-custom.mjsapps/libs/sdk-typescript/jest.config.jsapps/libs/sdk-typescript/package.jsonapps/libs/sdk-typescript/project.jsonapps/libs/sdk-typescript/src/Box.tsapps/libs/sdk-typescript/src/BoxLite.tsapps/libs/sdk-typescript/src/CodeInterpreter.tsapps/libs/sdk-typescript/src/ComputerUse.tsapps/libs/sdk-typescript/src/FileSystem.tsapps/libs/sdk-typescript/src/Git.tsapps/libs/sdk-typescript/src/Image.tsapps/libs/sdk-typescript/src/LspServer.tsapps/libs/sdk-typescript/src/ObjectStorage.tsapps/libs/sdk-typescript/src/Process.tsapps/libs/sdk-typescript/src/PtyHandle.tsapps/libs/sdk-typescript/src/Volume.tsapps/libs/sdk-typescript/src/__tests__/BoxLite.create-guards.test.tsapps/libs/sdk-typescript/src/code-toolbox/BoxJsCodeToolbox.tsapps/libs/sdk-typescript/src/code-toolbox/BoxPythonCodeToolbox.tsapps/libs/sdk-typescript/src/code-toolbox/BoxTsCodeToolbox.tsapps/libs/sdk-typescript/src/errors/BoxliteError.tsapps/libs/sdk-typescript/src/index.tsapps/libs/sdk-typescript/src/types/Charts.tsapps/libs/sdk-typescript/src/types/CodeInterpreter.tsapps/libs/sdk-typescript/src/types/ExecuteResponse.tsapps/libs/sdk-typescript/src/types/Pty.tsapps/libs/sdk-typescript/src/utils/ArtifactParser.tsapps/libs/sdk-typescript/src/utils/Binary.tsapps/libs/sdk-typescript/src/utils/FileTransfer.tsapps/libs/sdk-typescript/src/utils/Import.tsapps/libs/sdk-typescript/src/utils/Multipart.tsapps/libs/sdk-typescript/src/utils/Runtime.tsapps/libs/sdk-typescript/src/utils/Stream.tsapps/libs/sdk-typescript/src/utils/WebSocket.tsapps/libs/sdk-typescript/src/utils/otel.decorator.tsapps/libs/sdk-typescript/tsconfig.jsonapps/libs/sdk-typescript/tsconfig.lib.jsonapps/libs/sdk-typescript/tsconfig.spec.jsonapps/libs/sdk-typescript/typedoc.jsonapps/tsconfig.base.json
💤 Files with no reviewable changes (49)
- apps/libs/sdk-typescript/src/utils/WebSocket.ts
- apps/libs/sdk-typescript/package.json
- apps/libs/sdk-typescript/src/types/ExecuteResponse.ts
- apps/libs/sdk-typescript/tsconfig.lib.json
- apps/libs/sdk-typescript/tsconfig.json
- apps/libs/sdk-typescript/src/types/Pty.ts
- apps/libs/sdk-typescript/src/utils/Stream.ts
- apps/libs/sdk-typescript/src/FileSystem.ts
- apps/libs/sdk-typescript/src/types/Charts.ts
- apps/libs/sdk-typescript/src/Process.ts
- apps/libs/sdk-typescript/src/utils/ArtifactParser.ts
- apps/libs/sdk-typescript/src/utils/FileTransfer.ts
- apps/libs/sdk-typescript/src/code-toolbox/BoxPythonCodeToolbox.ts
- apps/libs/sdk-typescript/src/Image.ts
- apps/dashboard/src/components/Playground/Box/CodeSnippets/code-language.test.ts
- apps/libs/sdk-typescript/src/utils/Runtime.ts
- apps/libs/sdk-typescript/src/LspServer.ts
- apps/libs/sdk-typescript/src/utils/Binary.ts
- apps/libs/sdk-typescript/hooks/typedoc-custom.mjs
- apps/tsconfig.base.json
- apps/libs/sdk-typescript/src/utils/Multipart.ts
- apps/libs/sdk-typescript/src/tests/BoxLite.create-guards.test.ts
- apps/dashboard/.storybook/main.ts
- apps/libs/sdk-typescript/src/ObjectStorage.ts
- apps/api/Dockerfile
- apps/libs/sdk-typescript/src/errors/BoxliteError.ts
- apps/libs/sdk-typescript/jest.config.js
- apps/libs/sdk-typescript/src/types/CodeInterpreter.ts
- apps/libs/sdk-typescript/README.md
- apps/libs/sdk-typescript/src/code-toolbox/BoxJsCodeToolbox.ts
- apps/libs/sdk-typescript/LICENSE
- apps/libs/sdk-typescript/src/CodeInterpreter.ts
- apps/libs/sdk-typescript/src/code-toolbox/BoxTsCodeToolbox.ts
- apps/libs/sdk-typescript/src/index.ts
- apps/libs/sdk-typescript/src/Volume.ts
- apps/libs/sdk-typescript/project.json
- apps/libs/sdk-typescript/src/Box.ts
- apps/dashboard/vite.config.mts
- apps/libs/sdk-typescript/src/PtyHandle.ts
- apps/libs/sdk-typescript/tsconfig.spec.json
- apps/libs/sdk-typescript/src/ComputerUse.ts
- apps/dashboard/tsconfig.app.json
- apps/libs/sdk-typescript/typedoc.json
- apps/dashboard/src/components/Playground/Box/CodeSnippets/typescript.ts
- apps/libs/sdk-typescript/src/utils/Import.ts
- apps/eslint.config.mjs
- apps/libs/sdk-typescript/src/Git.ts
- apps/libs/sdk-typescript/src/BoxLite.ts
- apps/libs/sdk-typescript/src/utils/otel.decorator.ts
## Summary Stacked on #744. Implements the identity follow-up discussed on #735 (see the "Identity model note" comment there): the engine gains a CRI-style orchestrator reference, and the runner stops squatting the engine's `name` slot to carry the control-plane box id. ```text before after ────── ───── runner: WithName(cloudId) runner: WithExternalRef(cloudId) engine: name = cloudId (squatted) engine: external_ref = cloudId name unavailable for users name free for a future user-facing box name ``` Industry precedent (verified sources): - CRI `PodSandboxMetadata.uid` — the orchestrator's id travels as a dedicated metadata field; the runtime mints its own id ([cri-api api.proto](https://github.com/kubernetes/cri-api/blob/master/pkg/apis/runtime/v1/api.proto), `message PodSandboxMetadata`) - ECS agent attaches `com.amazonaws.ecs.task-arn` as a docker label ([docker_task_engine.go](https://github.com/aws/amazon-ecs-agent/blob/master/agent/engine/docker_task_engine.go)) - The caller-supplied-id pattern (OCI runtime spec `create <container-id>`) applies to stateless executors (runc/firecracker), not to stateful daemons like this engine — hence a reference field, not id injection. ## What changed - **engine**: `BoxOptions.external_ref` (opaque, json-persisted via the existing config blob — no DB migration; `lookup_box` already scans configs). Duplicate refs are rejected at create. Lookup order: exact id → name → external_ref → id prefix. `BoxInfo` exposes it, omitted when unset. - **C SDK**: `boxlite_options_set_external_ref`, `CBoxInfo.external_ref` (NULL when unset, freed on drop — the leak-count test now expects 5 inner CStrings), header regenerated by the crate build. - **Go SDK**: `WithExternalRef`, `BoxInfo.ExternalRef`. - **Node SDK**: field filled with `None` (orchestrator-facing knob; not exposed in JS options yet). - **CLI**: `inspect` shows `ExternalRef` only when present; `list` columns unchanged (nothing empty is rendered). - **runner**: `WithName(dto.Id)` → `WithExternalRef(dto.Id)`; restart recovery (`runtime.Get(dto.Id)`) resolves through the external_ref match. ## Verification - engine lib tests: 735/735; the new `lookup_box_by_external_ref` test was verified two-sided (fails with the lookup clause reverted, passes restored) - boxlite-c: 55/55 - CLI / Node / Python crates compile; `go vet` clean on `sdks/go` and `apps/runner/pkg/boxlite` (final cgo link needs the prebuilt `libboxlite.a`, absent in this worktree) ## Merge order #743 → #735 → #744 → this PR. Self-contained: reverting is closing this PR.
## Summary Stacked on #744. Implements the identity follow-up discussed on #735 (see the "Identity model note" comment there): the engine gains a CRI-style orchestrator reference, and the runner stops squatting the engine's `name` slot to carry the control-plane box id. ```text before after ────── ───── runner: WithName(cloudId) runner: WithExternalRef(cloudId) engine: name = cloudId (squatted) engine: external_ref = cloudId name unavailable for users name free for a future user-facing box name ``` Industry precedent (verified sources): - CRI `PodSandboxMetadata.uid` — the orchestrator's id travels as a dedicated metadata field; the runtime mints its own id ([cri-api api.proto](https://github.com/kubernetes/cri-api/blob/master/pkg/apis/runtime/v1/api.proto), `message PodSandboxMetadata`) - ECS agent attaches `com.amazonaws.ecs.task-arn` as a docker label ([docker_task_engine.go](https://github.com/aws/amazon-ecs-agent/blob/master/agent/engine/docker_task_engine.go)) - The caller-supplied-id pattern (OCI runtime spec `create <container-id>`) applies to stateless executors (runc/firecracker), not to stateful daemons like this engine — hence a reference field, not id injection. ## What changed - **engine**: `BoxOptions.external_ref` (opaque, json-persisted via the existing config blob — no DB migration; `lookup_box` already scans configs). Duplicate refs are rejected at create. Lookup order: exact id → name → external_ref → id prefix. `BoxInfo` exposes it, omitted when unset. - **C SDK**: `boxlite_options_set_external_ref`, `CBoxInfo.external_ref` (NULL when unset, freed on drop — the leak-count test now expects 5 inner CStrings), header regenerated by the crate build. - **Go SDK**: `WithExternalRef`, `BoxInfo.ExternalRef`. - **Node SDK**: field filled with `None` (orchestrator-facing knob; not exposed in JS options yet). - **CLI**: `inspect` shows `ExternalRef` only when present; `list` columns unchanged (nothing empty is rendered). - **runner**: `WithName(dto.Id)` → `WithExternalRef(dto.Id)`; restart recovery (`runtime.Get(dto.Id)`) resolves through the external_ref match. ## Verification - engine lib tests: 735/735; the new `lookup_box_by_external_ref` test was verified two-sided (fails with the lookup clause reverted, passes restored) - boxlite-c: 55/55 - CLI / Node / Python crates compile; `go vet` clean on `sdks/go` and `apps/runner/pkg/boxlite` (final cgo link needs the prebuilt `libboxlite.a`, absent in this worktree) ## Merge order #743 → #735 → #744 → this PR. Self-contained: reverting is closing this PR.
…ents (#744) ## Summary Stacked on #735. The Box entity's identity collapsed there into a single 12-char id; the `boxId` fields on `BoxDto` / the admin overview DTO were kept only as value mirrors of `id` to avoid touching the API contract and generated clients in that PR. This PR removes the mirror everywhere: ```text before (after #735) after (this PR) ─────────────────── ─────────────── entity/DB: id ✅ single unchanged BoxDto: id + boxId (same id only value, legacy shape) admin DTO: id + boxId mirror id only clients: Box/AdminBoxItem/ boxId field gone (TS + Go) Workspace carry boxId dashboard: reads .boxId ?? .id reads .id ``` - API: `BoxDto.boxId`, admin overview `boxId`, dual-id correlation matching in admin observability — all removed. - Dashboard: `box-identity` helpers read `.id`; dual-id cache updates and the uuid-shaped-name special case removed (after the DB rebuild a box name can never be a uuid). - Generated clients: regenerated with the repo's own codegen **inside a disposable BoxLite box** (CI-faithful: Linux + JDK + GNU sed, no host gofmt drift). Drift is exactly the `boxId` removal on the `Box` / `AdminBoxItem` / `Workspace` models in the TS and Go clients. - Untouched on purpose: route/query parameter names like `:boxId` (they carry the single id), other tables' `boxId` FK column names, and the analytics `ModelsBoxUsage.boxId` (a real data field, not the mirror). ## Verification - API jest: 38 suites / 112 tests pass - Dashboard: `tsc --noEmit` clean against the regenerated client - Regen ran in a BoxLite box (`boxlite run node:22-bookworm`); output is byte-for-byte what CI's api-client-drift check regenerates ## Merge order #743 (remove TS cloud SDK) → #735 (image pipeline + single box identity) → this PR.
…main)" (#743) (#751) Reverts #743. Restores `apps/libs/sdk-typescript` and the dashboard cloudBox usage to the pre-#743 state (clean `git revert` of ad155d9, no manual edits). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added TypeScript code snippet support to the Playground alongside existing Python support. * Introduced the BoxLite TypeScript SDK (`@boxlite-ai/sdk`), a new package providing APIs for box management, file operations, git workflows, code execution, and desktop automation. * **Refactor** * Migrated internal dashboard box operations to use the new SDK client library. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
…oolbox/workspace surfaces and box verbs
- Delete toolbox.deprecated.{controller,service,dto} (68 proxy endpoints).
Their only real consumer was the TypeScript cloud SDK removed in #743;
the dashboard Playground/VNC routes that also called them are dark.
- Delete workspace.deprecated.controller + dtos (legacy Daytona alias
surface, zero consumers).
- Delete createBox/deleteBox/startBox/stopBox from box.controller.
Box verbs are now owned solely by the Box API contract
(openapi/box.openapi.yaml), served by boxlite-rest. Cloud-capability
endpoints (signed URLs, ssh, archive, recover, paginated reads, getBox)
stay: they consume cloud-only ingredients the engine cannot provide.
- boxlite-rest CreateBoxDto + box.openapi.yaml: add cloud-optional create
fields (labels/public/auto_stop_interval/auto_delete_interval) so the
dashboard create form can speak the Box API dialect. Local engine
servers ignore them (serde drops unknown fields).
- metrics.interceptor: move box-create/start/stop capture from the
removed /api/box routes to the /api/v1 boxes routes.
- apps/api/Dockerfile: drop the toolbox-api-client COPY (package removed
later in this branch).
Summary
main. chore(apps): remove TypeScript cloud SDK #738 was merged with basefeat/box-curated-image-bootby mistake, so its content never reachedmain.apps/libs/sdk-typescriptproject and its Nx/build references.@boxlite-ai/sdkusage with the Dashboard-privatecloudBoxadapter backed by generated REST clients.@boxlite-ai/sdk.Differences from #738
Cherry-pick of squash commit
2f5aac6bwith three conflict resolutions against currentmain:PlaygroundProvider.tsx: kept thecloudBoximport side;Image.debianSlim('3.13')→{ image: 'base' }(identical to the chore(apps): remove TypeScript cloud SDK #738 resolved tree).apps/dashboard/.storybook/main.ts: removed a stale@boxlite-ai/sdkvite alias added onmainafter chore(apps): remove TypeScript cloud SDK #738 branched.Architecture Context: why delete + rewrite (not a rename)
What each layer is.
api-clientis machine-generated from the API's OpenAPIspec — it only knows how to call endpoints. The deleted SDK (B) and the new
cloudBox.tsare the handwritten glue above it: form-params → DTO mapping,poll-until-started, attaching
.process/.fshelpers to box objects. Gluelogic is not in the OpenAPI contract, so it cannot be generated.
Why
cloudBox.tsisadded, notrenamed. It is a from-scratch minimalreimplementation of the <5% of the SDK the Dashboard actually used: 458 lines
vs the SDK's 9.8k, only ~9 identical lines with the old
Box.ts(
git diff -M20%detects no rename). Marking it a rename would wrongly suggestthe full SDK class hierarchy survived.
Why delete the SDK at all.
Daytona — licensing and optics liability.
sweep 9.8k lines to serve a single internal consumer using <5% of it.
(Python/Node/Go/C, embedded engine + optional REST). A parallel cloud-only
TS SDK was a competing second "official way".
What external users keep. The cloud REST API is unchanged; the generated
clients (
@boxlite-ai/api-client,api-client-go) remain published. Only theconvenience wrapper is gone.
Known follow-ups (out of scope here).
cloudBox.tsstill carries the Daytona AGPL header — needs a clean-room pass.routes,
toolbox-api-clientTS package (zero runtime callers), and thecomputer-use/git sections of
cloudBox.ts.Verification
vite build --minify falseerror set diffed against anorigin/mainbaseline worktree: no new errors beyond pre-existingmainfailures (line-number shifts only).dashboard:buildis currently broken onmainitself (lightningcss minify +@boxlite-ai/api-clientresolution), unrelated to this change.Relation to #735
feat/box-curated-image-boot(#735) will be rebuilt on top of this branch so its diff contains only the curated-image work.Summary by CodeRabbit
New Features
Bug Fixes
Removed Features