Showing preview only (3,680K chars total). Download the full file or copy to clipboard to get everything.
Repository: cyberdesk-hq/cyberdesk
Branch: main
Commit: 6536bfbb543b
Files: 568
Total size: 3.4 MB
Directory structure:
gitextract_b1wrjbeg/
├── .gitignore
├── LICENSE
├── README.md
├── apps/
│ ├── api/
│ │ ├── .dockerignore
│ │ ├── .gitignore
│ │ ├── Dockerfile
│ │ ├── README.md
│ │ ├── drizzle/
│ │ │ └── migrations/
│ │ │ ├── 0000_oval_outlaw_kid.sql
│ │ │ ├── 0001_busy_warstar.sql
│ │ │ ├── 0002_regular_doctor_faustus.sql
│ │ │ ├── 0003_superb_betty_brant.sql
│ │ │ ├── 0004_simple_komodo.sql
│ │ │ ├── 0005_mighty_hiroim.sql
│ │ │ ├── 0006_icy_black_bird.sql
│ │ │ ├── 0007_panoramic_tomorrow_man.sql
│ │ │ └── meta/
│ │ │ ├── 0000_snapshot.json
│ │ │ ├── 0001_snapshot.json
│ │ │ ├── 0002_snapshot.json
│ │ │ ├── 0003_snapshot.json
│ │ │ ├── 0004_snapshot.json
│ │ │ ├── 0005_snapshot.json
│ │ │ ├── 0006_snapshot.json
│ │ │ ├── 0007_snapshot.json
│ │ │ └── _journal.json
│ │ ├── drizzle.config.ts
│ │ ├── fly.toml
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── db/
│ │ │ │ ├── dbActions.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── schema.ts
│ │ │ ├── index.ts
│ │ │ ├── lib/
│ │ │ │ ├── cache.ts
│ │ │ │ ├── errors.ts
│ │ │ │ ├── hono.ts
│ │ │ │ ├── posthog.ts
│ │ │ │ └── ratelimit.ts
│ │ │ ├── routes/
│ │ │ │ └── desktop.ts
│ │ │ └── schema/
│ │ │ ├── desktop.ts
│ │ │ ├── errors.ts
│ │ │ └── gateway.ts
│ │ └── tsconfig.json
│ ├── docs/
│ │ ├── .gitignore
│ │ ├── .map.ts
│ │ ├── README.md
│ │ ├── app/
│ │ │ ├── api/
│ │ │ │ └── search/
│ │ │ │ └── route.ts
│ │ │ ├── docs/
│ │ │ │ ├── [[...slug]]/
│ │ │ │ │ └── page.tsx
│ │ │ │ └── layout.tsx
│ │ │ ├── global.css
│ │ │ ├── layout.config.tsx
│ │ │ ├── layout.tsx
│ │ │ ├── page.tsx
│ │ │ └── source.ts
│ │ ├── content/
│ │ │ └── docs/
│ │ │ ├── api-reference.mdx
│ │ │ ├── conceptual-guide.mdx
│ │ │ ├── index.mdx
│ │ │ ├── introduction.mdx
│ │ │ ├── meta.json
│ │ │ ├── quickstart.mdx
│ │ │ └── tutorials.mdx
│ │ ├── mdx-components.tsx
│ │ ├── next-env.d.ts
│ │ ├── next.config.mjs
│ │ ├── package.json
│ │ ├── postcss.config.js
│ │ ├── scripts/
│ │ │ └── generate-docs.mjs
│ │ ├── tailwind.config.js
│ │ └── tsconfig.json
│ └── web/
│ ├── .eslintrc.json
│ ├── .gitignore
│ ├── LICENSE.md
│ ├── README.md
│ ├── components.json
│ ├── config.ts
│ ├── middleware.ts
│ ├── next.config.mjs
│ ├── package.json
│ ├── postcss.config.js
│ ├── prettier.config.js
│ ├── radiant/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── eslint.config.mjs
│ │ ├── package.json
│ │ ├── sanity.cli.ts
│ │ ├── sanity.config.ts
│ │ ├── schemaTypes/
│ │ │ └── index.ts
│ │ ├── static/
│ │ │ └── .gitkeep
│ │ └── tsconfig.json
│ ├── sanity-typegen.json
│ ├── sanity.cli.ts
│ ├── sanity.config.ts
│ ├── src/
│ │ ├── app/
│ │ │ ├── api/
│ │ │ │ ├── playground/
│ │ │ │ │ ├── chat/
│ │ │ │ │ │ └── route.ts
│ │ │ │ │ └── kill-desktop/
│ │ │ │ │ └── route.ts
│ │ │ │ ├── stripe/
│ │ │ │ │ ├── checkout/
│ │ │ │ │ │ └── route.ts
│ │ │ │ │ ├── portal/
│ │ │ │ │ │ └── route.ts
│ │ │ │ │ └── webhook/
│ │ │ │ │ └── route.ts
│ │ │ │ └── unkey/
│ │ │ │ └── route.ts
│ │ │ ├── auth/
│ │ │ │ └── callback/
│ │ │ │ └── route.ts
│ │ │ ├── blog/
│ │ │ │ ├── [slug]/
│ │ │ │ │ └── page.tsx
│ │ │ │ ├── feed.xml/
│ │ │ │ │ └── route.ts
│ │ │ │ └── page.tsx
│ │ │ ├── company/
│ │ │ │ └── page.tsx
│ │ │ ├── dashboard/
│ │ │ │ ├── dashboard-content.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── demo/
│ │ │ │ └── page.tsx
│ │ │ ├── layout.tsx
│ │ │ ├── login/
│ │ │ │ ├── login-form.d.ts
│ │ │ │ ├── login-form.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── page.tsx
│ │ │ ├── playground/
│ │ │ │ └── page.tsx
│ │ │ ├── pricing/
│ │ │ │ └── page.tsx
│ │ │ ├── privacy/
│ │ │ │ └── page.tsx
│ │ │ ├── studio/
│ │ │ │ └── [[...tool]]/
│ │ │ │ └── page.tsx
│ │ │ └── terms/
│ │ │ └── page.tsx
│ │ ├── components/
│ │ │ ├── LogoText.tsx
│ │ │ ├── PostHogProvider.tsx
│ │ │ ├── animated-number.tsx
│ │ │ ├── bento-card.tsx
│ │ │ ├── bento-section.tsx
│ │ │ ├── button.tsx
│ │ │ ├── container.tsx
│ │ │ ├── dark-bento-section.tsx
│ │ │ ├── dashboard/
│ │ │ │ ├── api-key-manager.tsx
│ │ │ │ ├── api-key-section.tsx
│ │ │ │ ├── dashboard-layout.tsx
│ │ │ │ ├── desktop-sidebar.tsx
│ │ │ │ ├── faq-section.tsx
│ │ │ │ ├── mobile-header.tsx
│ │ │ │ ├── mobile-sidebar.tsx
│ │ │ │ ├── sidebar-navigation.tsx
│ │ │ │ ├── subscription-section.tsx
│ │ │ │ └── vm-instances-manager.tsx
│ │ │ ├── demo-section.tsx
│ │ │ ├── feature-section.tsx
│ │ │ ├── footer.tsx
│ │ │ ├── gradient.tsx
│ │ │ ├── hero.tsx
│ │ │ ├── keyboard.tsx
│ │ │ ├── link.tsx
│ │ │ ├── linked-avatars.tsx
│ │ │ ├── logo-cloud.tsx
│ │ │ ├── logo-cluster.tsx
│ │ │ ├── logo-timeline.tsx
│ │ │ ├── logo.tsx
│ │ │ ├── map.tsx
│ │ │ ├── markdown-text.tsx
│ │ │ ├── navbar.tsx
│ │ │ ├── playground/
│ │ │ │ ├── chat-error.tsx
│ │ │ │ ├── icons.tsx
│ │ │ │ ├── input.tsx
│ │ │ │ ├── markdown.tsx
│ │ │ │ ├── message.tsx
│ │ │ │ ├── project-info.tsx
│ │ │ │ └── prompt-suggestions.tsx
│ │ │ ├── plus-grid.tsx
│ │ │ ├── screenshot.tsx
│ │ │ ├── shared/
│ │ │ │ └── app-logo.tsx
│ │ │ ├── stripe/
│ │ │ │ ├── checkout-button.tsx
│ │ │ │ ├── client-pricing-card.tsx
│ │ │ │ ├── client-pricing-cards.tsx
│ │ │ │ ├── payment-success.tsx
│ │ │ │ └── subscription-management.tsx
│ │ │ ├── testimonials.tsx
│ │ │ ├── text.tsx
│ │ │ ├── thread-list.tsx
│ │ │ ├── thread.tsx
│ │ │ ├── tooltip-icon-button.tsx
│ │ │ ├── ui/
│ │ │ │ ├── button.tsx
│ │ │ │ ├── input.tsx
│ │ │ │ ├── resizable.tsx
│ │ │ │ ├── sonner.tsx
│ │ │ │ └── tooltip.tsx
│ │ │ └── yc-banner.tsx
│ │ ├── sanity/
│ │ │ ├── client.ts
│ │ │ ├── env.ts
│ │ │ ├── image.ts
│ │ │ ├── queries.ts
│ │ │ ├── schema.ts
│ │ │ ├── types/
│ │ │ │ ├── author.ts
│ │ │ │ ├── block-content.ts
│ │ │ │ ├── category.ts
│ │ │ │ └── post.ts
│ │ │ └── types.ts
│ │ ├── styles/
│ │ │ └── tailwind.css
│ │ ├── types/
│ │ │ └── database.ts
│ │ └── utils/
│ │ ├── misc-utils.ts
│ │ ├── playground/
│ │ │ ├── cyberdesk-client.ts
│ │ │ ├── misc-demo-utils.ts
│ │ │ ├── server-actions.ts
│ │ │ ├── tools.ts
│ │ │ └── use-scroll-to-bottom.ts
│ │ ├── posthog/
│ │ │ └── posthog.ts
│ │ ├── stripe/
│ │ │ ├── stripe-server.ts
│ │ │ ├── stripe.ts
│ │ │ └── tiers.ts
│ │ └── supabase/
│ │ ├── client.ts
│ │ ├── middleware.ts
│ │ ├── server.ts
│ │ ├── supabaseClient.js
│ │ └── supabaseServerClient.ts
│ └── tsconfig.json
├── cyberdesk-architecture.md
├── infra/
│ ├── README.md
│ ├── kubernetes/
│ │ ├── azure-snapshot-class.yaml
│ │ ├── cdi-cr.yaml
│ │ ├── cdi-operator.yaml
│ │ ├── cluster-issuer.yaml
│ │ ├── cyberdesk-cr-v2.yaml
│ │ ├── cyberdesk-cr.yaml
│ │ ├── cyberdesk-operator.yaml
│ │ ├── default-backend.yaml
│ │ ├── gateway-deploy.yaml
│ │ ├── gateway-ingress-dev.yaml
│ │ ├── gateway-ingress-prod.yaml
│ │ ├── golden-vm-snapshot-request.yaml
│ │ ├── kubevirt-cr.yaml
│ │ ├── kubevirt-operator.yaml
│ │ ├── readme-todo.txt
│ │ ├── start-cyberdesk-operator-cr.yaml
│ │ └── warm-pool.yaml
│ └── terraform/
│ ├── .terraform.lock.hcl
│ ├── main.tf
│ └── variables.tf
├── sdks/
│ ├── openapi.json
│ ├── py-sdk/
│ │ ├── .gitignore
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── cyberdesk/
│ │ │ ├── __init__.py
│ │ │ ├── actions.py
│ │ │ ├── client.py
│ │ │ └── types.py
│ │ ├── openapi_client/
│ │ │ ├── .gitignore
│ │ │ ├── README.md
│ │ │ ├── api_reference_client/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── api/
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ └── desktop/
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── get_v1_desktop_id.py
│ │ │ │ │ ├── post_v1_desktop.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action.py
│ │ │ │ │ └── post_v1_desktop_id_stop.py
│ │ │ │ ├── client.py
│ │ │ │ ├── errors.py
│ │ │ │ ├── models/
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── get_v1_desktop_id_response_200.py
│ │ │ │ │ ├── get_v1_desktop_id_response_200_status.py
│ │ │ │ │ ├── get_v1_desktop_id_response_400.py
│ │ │ │ │ ├── get_v1_desktop_id_response_400_status.py
│ │ │ │ │ ├── get_v1_desktop_id_response_401.py
│ │ │ │ │ ├── get_v1_desktop_id_response_401_status.py
│ │ │ │ │ ├── get_v1_desktop_id_response_403.py
│ │ │ │ │ ├── get_v1_desktop_id_response_403_status.py
│ │ │ │ │ ├── get_v1_desktop_id_response_404.py
│ │ │ │ │ ├── get_v1_desktop_id_response_404_status.py
│ │ │ │ │ ├── get_v1_desktop_id_response_409.py
│ │ │ │ │ ├── get_v1_desktop_id_response_409_status.py
│ │ │ │ │ ├── get_v1_desktop_id_response_429.py
│ │ │ │ │ ├── get_v1_desktop_id_response_429_status.py
│ │ │ │ │ ├── get_v1_desktop_id_response_500.py
│ │ │ │ │ ├── get_v1_desktop_id_response_500_status.py
│ │ │ │ │ ├── get_v1_desktop_id_response_502.py
│ │ │ │ │ ├── get_v1_desktop_id_response_502_status.py
│ │ │ │ │ ├── post_v1_desktop_body.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_body.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_200.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_400.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_400_status.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_401.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_401_status.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_403.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_403_status.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_404.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_404_status.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_409.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_409_status.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_429.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_429_status.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_500.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_500_status.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_502.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_502_status.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_click_mouse_action.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_click_mouse_action_button.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_click_mouse_action_click_type.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_click_mouse_action_type.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_drag_mouse_action.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_drag_mouse_action_end.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_drag_mouse_action_start.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_drag_mouse_action_type.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_get_cursor_position_action.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_get_cursor_position_action_type.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_move_mouse_action.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_move_mouse_action_type.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_press_keys_action.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_press_keys_action_key_action_type.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_press_keys_action_type.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_200.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_400.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_400_status.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_401.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_401_status.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_403.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_403_status.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_404.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_404_status.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_409.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_409_status.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_429.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_429_status.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_500.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_500_status.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_502.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_502_status.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_screenshot_action.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_screenshot_action_type.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_scroll_action.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_scroll_action_direction.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_scroll_action_type.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_type_text_action.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_type_text_action_type.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_wait_action.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_wait_action_type.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_200.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_200_status.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_400.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_400_status.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_401.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_401_status.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_403.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_403_status.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_404.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_404_status.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_409.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_409_status.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_429.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_429_status.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_500.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_500_status.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_502.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_502_status.py
│ │ │ │ │ ├── post_v1_desktop_response_200.py
│ │ │ │ │ ├── post_v1_desktop_response_200_status.py
│ │ │ │ │ ├── post_v1_desktop_response_400.py
│ │ │ │ │ ├── post_v1_desktop_response_400_status.py
│ │ │ │ │ ├── post_v1_desktop_response_401.py
│ │ │ │ │ ├── post_v1_desktop_response_401_status.py
│ │ │ │ │ ├── post_v1_desktop_response_403.py
│ │ │ │ │ ├── post_v1_desktop_response_403_status.py
│ │ │ │ │ ├── post_v1_desktop_response_404.py
│ │ │ │ │ ├── post_v1_desktop_response_404_status.py
│ │ │ │ │ ├── post_v1_desktop_response_409.py
│ │ │ │ │ ├── post_v1_desktop_response_409_status.py
│ │ │ │ │ ├── post_v1_desktop_response_429.py
│ │ │ │ │ ├── post_v1_desktop_response_429_status.py
│ │ │ │ │ ├── post_v1_desktop_response_500.py
│ │ │ │ │ ├── post_v1_desktop_response_500_status.py
│ │ │ │ │ ├── post_v1_desktop_response_502.py
│ │ │ │ │ └── post_v1_desktop_response_502_status.py
│ │ │ │ ├── py.typed
│ │ │ │ └── types.py
│ │ │ └── pyproject.toml
│ │ ├── pyproject.toml
│ │ └── scripts/
│ │ └── generate.py
│ ├── sandbox/
│ │ └── py-sdk/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ └── test_sdk.py
│ └── ts-sdk/
│ ├── .gitignore
│ ├── LICENSE
│ ├── README.md
│ ├── openapi-ts.config.ts
│ ├── package.json
│ ├── src/
│ │ ├── client/
│ │ │ ├── client.gen.ts
│ │ │ ├── index.ts
│ │ │ ├── sdk.gen.ts
│ │ │ └── types.gen.ts
│ │ └── index.ts
│ └── tsconfig.json
├── self-host.md
└── services/
├── cyberdesk-operator/
│ ├── .gitignore
│ ├── Dockerfile
│ ├── README.md
│ ├── checklist.md
│ ├── docs/
│ │ └── troubleshooting.md
│ ├── handlers/
│ │ └── controller.py
│ ├── requirements.txt
│ └── tests/
│ ├── README.md
│ ├── test-cyberdesk-cr.yaml
│ ├── test-start-operator-cr.yaml
│ ├── test-start-operator-crd.yaml
│ └── test.py
└── gateway/
├── Dockerfile
├── README.md
├── main.py
├── noVNC/
│ ├── .github/
│ │ ├── ISSUE_TEMPLATE/
│ │ │ ├── bug_report.md
│ │ │ ├── config.yml
│ │ │ └── feature_request.md
│ │ └── workflows/
│ │ ├── deploy.yml
│ │ ├── lint.yml
│ │ ├── test.yml
│ │ └── translate.yml
│ ├── .gitignore
│ ├── .gitmodules
│ ├── AUTHORS
│ ├── LICENSE.txt
│ ├── README.md
│ ├── app/
│ │ ├── error-handler.js
│ │ ├── images/
│ │ │ └── icons/
│ │ │ └── Makefile
│ │ ├── locale/
│ │ │ ├── README
│ │ │ ├── cs.json
│ │ │ ├── de.json
│ │ │ ├── el.json
│ │ │ ├── es.json
│ │ │ ├── fr.json
│ │ │ ├── it.json
│ │ │ ├── ja.json
│ │ │ ├── ko.json
│ │ │ ├── nl.json
│ │ │ ├── pl.json
│ │ │ ├── pt_BR.json
│ │ │ ├── ru.json
│ │ │ ├── sv.json
│ │ │ ├── tr.json
│ │ │ ├── zh_CN.json
│ │ │ └── zh_TW.json
│ │ ├── localization.js
│ │ ├── sounds/
│ │ │ ├── CREDITS
│ │ │ └── bell.oga
│ │ ├── styles/
│ │ │ ├── base.css
│ │ │ ├── constants.css
│ │ │ └── input.css
│ │ ├── ui.js
│ │ └── webutil.js
│ ├── core/
│ │ ├── base64.js
│ │ ├── crypto/
│ │ │ ├── aes.js
│ │ │ ├── bigint.js
│ │ │ ├── crypto.js
│ │ │ ├── des.js
│ │ │ ├── dh.js
│ │ │ ├── md5.js
│ │ │ └── rsa.js
│ │ ├── decoders/
│ │ │ ├── copyrect.js
│ │ │ ├── h264.js
│ │ │ ├── hextile.js
│ │ │ ├── jpeg.js
│ │ │ ├── raw.js
│ │ │ ├── rre.js
│ │ │ ├── tight.js
│ │ │ ├── tightpng.js
│ │ │ ├── zlib.js
│ │ │ └── zrle.js
│ │ ├── deflator.js
│ │ ├── display.js
│ │ ├── encodings.js
│ │ ├── inflator.js
│ │ ├── input/
│ │ │ ├── domkeytable.js
│ │ │ ├── fixedkeys.js
│ │ │ ├── gesturehandler.js
│ │ │ ├── keyboard.js
│ │ │ ├── keysym.js
│ │ │ ├── keysymdef.js
│ │ │ ├── util.js
│ │ │ ├── vkeys.js
│ │ │ └── xtscancodes.js
│ │ ├── ra2.js
│ │ ├── rfb.js
│ │ ├── util/
│ │ │ ├── browser.js
│ │ │ ├── cursor.js
│ │ │ ├── element.js
│ │ │ ├── events.js
│ │ │ ├── eventtarget.js
│ │ │ ├── int.js
│ │ │ ├── logging.js
│ │ │ └── strings.js
│ │ └── websock.js
│ ├── defaults.json
│ ├── docs/
│ │ ├── API-internal.md
│ │ ├── API.md
│ │ ├── EMBEDDING.md
│ │ ├── LIBRARY.md
│ │ ├── LICENSE.BSD-2-Clause
│ │ ├── LICENSE.BSD-3-Clause
│ │ ├── LICENSE.MPL-2.0
│ │ ├── LICENSE.OFL-1.1
│ │ ├── flash_policy.txt
│ │ ├── links
│ │ ├── notes
│ │ ├── novnc_proxy.1
│ │ └── rfb_notes
│ ├── eslint.config.mjs
│ ├── karma.conf.js
│ ├── mandatory.json
│ ├── package.json
│ ├── po/
│ │ ├── Makefile
│ │ ├── cs.po
│ │ ├── de.po
│ │ ├── el.po
│ │ ├── es.po
│ │ ├── fr.po
│ │ ├── it.po
│ │ ├── ja.po
│ │ ├── ko.po
│ │ ├── nl.po
│ │ ├── noVNC.pot
│ │ ├── pl.po
│ │ ├── po2js
│ │ ├── pt_BR.po
│ │ ├── ru.po
│ │ ├── sv.po
│ │ ├── tr.po
│ │ ├── xgettext-html
│ │ ├── zh_CN.po
│ │ └── zh_TW.po
│ ├── snap/
│ │ ├── hooks/
│ │ │ └── configure
│ │ ├── local/
│ │ │ └── svc_wrapper.sh
│ │ └── snapcraft.yaml
│ ├── tests/
│ │ ├── assertions.js
│ │ ├── fake.websocket.js
│ │ ├── playback-ui.js
│ │ ├── playback.js
│ │ ├── test.base64.js
│ │ ├── test.browser.js
│ │ ├── test.copyrect.js
│ │ ├── test.deflator.js
│ │ ├── test.display.js
│ │ ├── test.gesturehandler.js
│ │ ├── test.h264.js
│ │ ├── test.helper.js
│ │ ├── test.hextile.js
│ │ ├── test.inflator.js
│ │ ├── test.int.js
│ │ ├── test.jpeg.js
│ │ ├── test.keyboard.js
│ │ ├── test.localization.js
│ │ ├── test.raw.js
│ │ ├── test.rfb.js
│ │ ├── test.rre.js
│ │ ├── test.tight.js
│ │ ├── test.tightpng.js
│ │ ├── test.util.js
│ │ ├── test.websock.js
│ │ ├── test.webutil.js
│ │ ├── test.zlib.js
│ │ ├── test.zrle.js
│ │ └── vnc_playback.html
│ ├── utils/
│ │ ├── README.md
│ │ ├── b64-to-binary.pl
│ │ ├── convert.js
│ │ ├── genkeysymdef.js
│ │ ├── novnc_proxy
│ │ ├── u2x11
│ │ └── validate
│ ├── vendor/
│ │ └── pako/
│ │ ├── LICENSE
│ │ ├── README.md
│ │ └── lib/
│ │ ├── utils/
│ │ │ └── common.js
│ │ └── zlib/
│ │ ├── adler32.js
│ │ ├── constants.js
│ │ ├── crc32.js
│ │ ├── deflate.js
│ │ ├── gzheader.js
│ │ ├── inffast.js
│ │ ├── inflate.js
│ │ ├── inftrees.js
│ │ ├── messages.js
│ │ ├── trees.js
│ │ └── zstream.js
│ ├── vnc.html
│ └── vnc_lite.html
└── requirements.txt
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Local .terraform directories
**/.terraform/*
# .tfstate files
*.tfstate
*.tfstate.*
# Crash log files
crash.log
crash.*.log
# Exclude all .tfvars files, which are likely to contain sensitive data
*.tfvars
*.tfvars.json
# Ignore override files as they are usually used for local development
override.tf
override.tf.json
*_override.tf
*_override.tf.json
# Ignore CLI configuration files
.terraformrc
terraform.rc
# Ignore kubeconfig
kubeconfig.yaml
# Ignore testing-do-not-push
testing-do-not-push/*
user-data.yaml
user-data-base64.txt
# Kubernetes secrets - DO NOT COMMIT REAL CREDENTIALS
infra/kubernetes/cyberdesk-secret.yaml
infra/kubernetes/checkpoint-cyberdesk-secret.yaml
infra/kubernetes/golden-vm-deploy.yaml
# Local development environment variables
.env
infra/kubernetes/test-secret.yaml
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
(a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[ ]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
Copyright 2024 Cyberdesk Team
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: README.md
================================================
<p align="center">
<img src="assets/cyberdesk-logo-with-text.png" width="400" alt="Cyberdesk Logo" />
</p>
<p align="center">
<b>The open source infra for virtual desktop orchestration, tailored for computer agents</b>
</p>
<p align="center">
<!-- NPM Version -->
<a href="https://www.npmjs.com/package/cyberdesk">
<img src="https://img.shields.io/npm/v/cyberdesk?color=cb3837&logo=npm" alt="NPM Version" />
</a>
<!-- NPM Downloads -->
<a href="https://www.npmjs.com/package/cyberdesk">
<img src="https://img.shields.io/npm/dw/cyberdesk?color=cb3837&logo=npm" alt="NPM Downloads" />
</a>
<!-- PyPI Version -->
<a href="https://pypi.org/project/cyberdesk/">
<img src="https://img.shields.io/pypi/v/cyberdesk?color=3776ab&logo=pypi" alt="PyPI Version" />
</a>
<!-- PyPI Downloads -->
<a href="https://pypi.org/project/cyberdesk/">
<img src="https://img.shields.io/pypi/dw/cyberdesk?color=3776ab&logo=pypi" alt="PyPI Downloads" />
</a>
</p>
<p align="center">
<!-- Discord -->
<a href="https://discord.gg/ws5ddx5yZ8">
<img src="https://img.shields.io/discord/1228348939648004096?label=discord&logo=discord&color=5865F2" alt="Discord" />
</a>
<!-- License -->
<a href="LICENSE">
<img src="https://img.shields.io/badge/license-Apache%202.0-blue.svg" alt="License: Apache 2.0" />
</a>
<!-- GitHub Stars (optional) -->
<a href="https://github.com/cyberdesk-hq/cyberdesk">
<img src="https://img.shields.io/github/stars/cyberdesk-hq/cyberdesk?style=social" alt="GitHub Stars" />
</a>
</p>
<p align="center">
<img src="assets/QuickDemo.gif" alt="Cyberdesk Demo" width="600" />
<br>
<i>A computer agent operating a Cyberdesk virtual desktop from a user prompt</i>
</p>
---
## 🚀 Quick Start
### TypeScript
```bash
npm install cyberdesk@0.2.1
```
```typescript
import { createCyberdeskClient } from 'cyberdesk';
const cyberdesk = createCyberdeskClient({ apiKey: 'YOUR_API_KEY' });
const launchResult = await cyberdesk.launchDesktop({ body: { timeout_ms: 10000 } });
const desktopId = launchResult.id;
// Take a screenshot
const screenshot = await cyberdesk.executeComputerAction({
path: { id: desktopId },
body: { type: 'screenshot' }
});
// Left click at (100, 150)
await cyberdesk.executeComputerAction({
path: { id: desktopId },
body: { type: 'click_mouse', x: 100, y: 150, button: 'left' }
});
```
### Python
```bash
pip install cyberdesk==0.2.7
```
```python
from cyberdesk import CyberdeskClient
from cyberdesk.actions import click_mouse, screenshot, ClickMouseButton
client = CyberdeskClient(api_key="YOUR_API_KEY")
result = client.launch_desktop(timeout_ms=10000)
desktop_id = result.id
# Take a screenshot
screenshot_action = screenshot()
screenshot_result = client.execute_computer_action(desktop_id, screenshot_action)
# Left click at (100, 150)
click_action = click_mouse(x=100, y=150, button=ClickMouseButton.LEFT)
client.execute_computer_action(desktop_id, click_action)
```
👉 For more details and advanced usage, see the [Quickstart Guide](https://docs.cyberdesk.io/docs/quickstart) and [Official Documentation](#-official-documentation).
---
## ✨ Features
<div align="center">
<table>
<tr>
<td align="center" width="260"><br><b>🚀 Fast Launch</b><br><sub>Spin up virtual desktops in seconds, ready for automation or remote use.</sub><br><br></td>
<td align="center" width="260"><br><b>🖱️ Full Automation</b><br><sub>Control mouse, keyboard, and more—perfect for computer agents.</sub><br><br></td>
<td align="center" width="260"><br><b>🖥️ Cloud Native</b><br><sub>Runs on AKS, or self-hosted on your own infrastructure.</sub><br><br></td>
</tr>
<tr>
<td align="center" width="260"><br><b>🔒 Secure & Auditable</b><br><sub>Session logs, API keys, and enterprise-grade security.</sub><br><br></td>
<td align="center" width="260"><br><b>🧩 Type-Safe SDKs</b><br><sub>Official Python & TypeScript SDKs with full type hints.</sub><br><br></td>
<td align="center" width="260"><br><b>🤖 AI-Ready</b><br><sub>Tailor built for the next generation of computer use agents</sub><br><br></td>
</tr>
</table>
</div>
---
## 📚 Official Documentation
- [Quickstart Guide](https://docs.cyberdesk.io/docs/quickstart)
- [API Reference](https://docs.cyberdesk.io/docs/api-reference)
- [TypeScript SDK](sdks/ts-sdk/README.md)
- [Python SDK](sdks/py-sdk/README.md)
---
## 🛠️ Project Structure
### /apps
- **web**: Landing page and dashboard ([README](apps/web/README.md))
- **api**: Developer-facing API ([README](apps/api/README.md))
- **docs**: Documentation site ([README](apps/docs/README.md))
### /services
- **cyberdesk-operator**: Kubernetes operator for managing Cyberdesk Custom Resources, and starting/stopping Kubevirt virtual machines ([README](services/cyberdesk-operator/README.md))
- **gateway**: HTTP service that proxies requests to the Kubevirt API, and routes them to the correct virtual machine ([README](services/gateway/README.md))
### /sdks
- **ts-sdk**: TypeScript SDK ([README](sdks/ts-sdk/README.md))
- **py-sdk**: Python SDK ([README](sdks/py-sdk/README.md))
### /infrastructure
- **terraform**: AKS Cluster Setup (Terraform) ([README](infrastructure/README.md))
- **kubernetes**: Kubernetes resources for the Cyberdesk operator
---
## 🤝 Contributing
We welcome contributions!
- Join the [Discord](https://discord.gg/ws5ddx5yZ8) for discussion and support
- Get a personal 1-1 walkthrough of how to self host the project by contacting us on [Discord](https://discord.gg/ws5ddx5yZ8)
---
## 📣 Community & Support
- [Discord](https://discord.gg/ws5ddx5yZ8) for help and chat
- [Good First Issues](https://github.com/cyberdesk-hq/cyberdesk/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)
- [Open an Issue](https://github.com/cyberdesk-hq/cyberdesk/issues)
---
## 💡 Philosophy
> At **Cyberdesk** our mission is to make building computer agents as easy as playing with legos. We believe in open, simple, and extensible tools for the new generation of developers: *computer agent developers*.
---
## 📄 License
Apache License 2.0. See [LICENSE](LICENSE).
---
<p align="center">
<sub>Made with ❤️ by the Cyberdesk Team</sub>
</p>
================================================
FILE: apps/api/.dockerignore
================================================
/.git
/node_modules
.dockerignore
.env
Dockerfile
fly.toml
================================================
FILE: apps/api/.gitignore
================================================
# prod
dist/
# dev
.yarn/
!.yarn/releases
.vscode/*
!.vscode/launch.json
!.vscode/*.code-snippets
.idea/workspace.xml
.idea/usage.statistics.xml
.idea/shelf
# deps
node_modules/
.wrangler
# env
.env
.env.production
.dev.vars
# logs
logs/
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
# misc
.DS_Store
# turbo
.turbo
================================================
FILE: apps/api/Dockerfile
================================================
# syntax = docker/dockerfile:1
# Adjust NODE_VERSION as desired
ARG NODE_VERSION=20.18.0
FROM node:${NODE_VERSION}-slim AS base
LABEL fly_launch_runtime="Node.js"
# Node.js app lives here
WORKDIR /app
# Set production environment
ENV NODE_ENV="production"
# Throw-away build stage to reduce size of final image
FROM base AS build
# Install packages needed to build node modules
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y build-essential node-gyp pkg-config python-is-python3
# Install node modules
COPY package.json ./
RUN npm install --include=dev
# Copy application code
COPY . .
# Build application
RUN npm run build
# Remove development dependencies
RUN npm prune --omit=dev
# Final stage for app image
FROM base
# Copy built application
COPY --from=build /app /app
# Start the server by default, this can be overwritten at runtime
EXPOSE 3000
CMD [ "npm", "run", "start" ]
================================================
FILE: apps/api/README.md
================================================
# Created by Unkey's toolbox
This API is built with speed, and security in mind. The API is built with [Hono](https://hono.dev), [Unkey](https://unkey.com) and [Supabase](https://supabase.com) with hosting on [Fly.io](https://fly.io).
## Getting Started
You will need a free account for both Unkey and Supabase to run this project.
### Unkey
For Unkey you will need your API ID and a root key scoped to:
- Create Key
- Create Namespace
- Limit
You can of course add more scopes as required.
### Supabase
For Supabase, you'll need to create a project and get your:
- Supabase URL
- Supabase Anon Key
- Supabase Connection String (found in the Database settings under Connection Pooling)
## Environment Variables
To run this project, you will need to add the following environment variables to your .dev.vars file
```env
SUPABASE_URL=https://your-project-id.supabase.co
SUPABASE_ANON_KEY=your-supabase-anon-key
SUPABASE_CONNECTION_STRING=postgres://postgres:your-password@your-project-id.supabase.co:5432/postgres?pgbouncer=true
UNKEY_API_ID=UNKEY_API_ID
UNKEY_ROOT_KEY=UNKEY_ROOT_KEY
```
## Usage
Make sure that you have run:
```bash
npm run db:generate
npm run db:push
```
You can then run `npm run dev`
Then you will have access to the following routes:
`/keys/create` - To create an API key to use with the other endpoints.
Then the desktop routes (all under the `/v1` prefix):
```bash
/v1/desktop # Create a new desktop instance
/v1/desktop/{id}/stop # Stop a desktop instance
/v1/desktop/{id}/computer-action # Perform a computer action
/v1/desktop/{id}/bash-action # Execute a bash command
```
You also have access to the open-api spec found at [http://localhost:8787/open-api](http://localhost:8787/open-api)
================================================
FILE: apps/api/drizzle/migrations/0000_oval_outlaw_kid.sql
================================================
CREATE TABLE IF NOT EXISTS "desktop_instances" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"user_id" uuid NOT NULL,
"created_at" timestamp DEFAULT now(),
"ended_at" timestamp
);
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "desktop_instances" ADD CONSTRAINT "desktop_instances_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "auth"."users"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
================================================
FILE: apps/api/drizzle/migrations/0001_busy_warstar.sql
================================================
ALTER TABLE "desktop_instances" ADD COLUMN "remote_id" varchar(255);
================================================
FILE: apps/api/drizzle/migrations/0002_regular_doctor_faustus.sql
================================================
CREATE TABLE IF NOT EXISTS "profiles" (
"id" uuid PRIMARY KEY NOT NULL,
"unkey_key_id" varchar(255),
"stripe_customer_id" varchar(255),
"stripe_subscription_id" varchar(255),
"current_period_end" timestamp,
"subscription_status" varchar(50),
"plan_id" varchar(100),
"cancel_at_period_end" boolean DEFAULT false,
"created_at" timestamp DEFAULT now(),
"updated_at" timestamp DEFAULT now()
);
--> statement-breakpoint
ALTER TABLE "desktop_instances" ALTER COLUMN "remote_id" SET NOT NULL;--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "profiles" ADD CONSTRAINT "profiles_id_users_id_fk" FOREIGN KEY ("id") REFERENCES "auth"."users"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
================================================
FILE: apps/api/drizzle/migrations/0003_superb_betty_brant.sql
================================================
ALTER TABLE "desktop_instances" ADD COLUMN "stream_url" varchar(1024) NOT NULL;
================================================
FILE: apps/api/drizzle/migrations/0004_simple_komodo.sql
================================================
ALTER TABLE "desktop_instances" ALTER COLUMN "stream_url" SET DEFAULT 'https://placeholder-stream-url.cyberdesk.dev';
================================================
FILE: apps/api/drizzle/migrations/0005_mighty_hiroim.sql
================================================
ALTER TABLE "desktop_instances" DROP CONSTRAINT "desktop_instances_user_id_users_id_fk";
--> statement-breakpoint
ALTER TABLE "profiles" DROP CONSTRAINT "profiles_id_users_id_fk";
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "desktop_instances" ADD CONSTRAINT "desktop_instances_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "auth"."users"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "profiles" ADD CONSTRAINT "profiles_id_users_id_fk" FOREIGN KEY ("id") REFERENCES "auth"."users"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
================================================
FILE: apps/api/drizzle/migrations/0006_icy_black_bird.sql
================================================
DO $$ BEGIN
CREATE TYPE "public"."instance_status" AS ENUM('pending', 'running', 'completed', 'error');
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "cyberdesk_instances" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"user_id" uuid NOT NULL,
"created_at" timestamp DEFAULT now(),
"updated_at" timestamp,
"status" "instance_status" DEFAULT 'pending' NOT NULL,
"timeout_at" timestamp DEFAULT NOW() + interval '24 hours' NOT NULL,
"stream_url" varchar(1024)
);
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "cyberdesk_instances" ADD CONSTRAINT "cyberdesk_instances_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "auth"."users"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
================================================
FILE: apps/api/drizzle/migrations/0007_panoramic_tomorrow_man.sql
================================================
ALTER TYPE "instance_status" ADD VALUE 'terminated';
================================================
FILE: apps/api/drizzle/migrations/meta/0000_snapshot.json
================================================
{
"id": "1816b590-90c5-4f05-9726-cc8f33d18251",
"prevId": "00000000-0000-0000-0000-000000000000",
"version": "6",
"dialect": "postgresql",
"tables": {
"public.desktop_instances": {
"name": "desktop_instances",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"ended_at": {
"name": "ended_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"desktop_instances_user_id_users_id_fk": {
"name": "desktop_instances_user_id_users_id_fk",
"tableFrom": "desktop_instances",
"tableTo": "users",
"schemaTo": "auth",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
}
},
"enums": {},
"schemas": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}
================================================
FILE: apps/api/drizzle/migrations/meta/0001_snapshot.json
================================================
{
"id": "61aff1d0-bd56-4301-852c-bc67c46a1cd9",
"prevId": "1816b590-90c5-4f05-9726-cc8f33d18251",
"version": "6",
"dialect": "postgresql",
"tables": {
"public.desktop_instances": {
"name": "desktop_instances",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"remote_id": {
"name": "remote_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"ended_at": {
"name": "ended_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"desktop_instances_user_id_users_id_fk": {
"name": "desktop_instances_user_id_users_id_fk",
"tableFrom": "desktop_instances",
"tableTo": "users",
"schemaTo": "auth",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
}
},
"enums": {},
"schemas": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}
================================================
FILE: apps/api/drizzle/migrations/meta/0002_snapshot.json
================================================
{
"id": "4d86e969-3e44-4e26-bb6d-b76b9daa733e",
"prevId": "61aff1d0-bd56-4301-852c-bc67c46a1cd9",
"version": "6",
"dialect": "postgresql",
"tables": {
"public.desktop_instances": {
"name": "desktop_instances",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"remote_id": {
"name": "remote_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"ended_at": {
"name": "ended_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"desktop_instances_user_id_users_id_fk": {
"name": "desktop_instances_user_id_users_id_fk",
"tableFrom": "desktop_instances",
"tableTo": "users",
"schemaTo": "auth",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"public.profiles": {
"name": "profiles",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"unkey_key_id": {
"name": "unkey_key_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"stripe_customer_id": {
"name": "stripe_customer_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"stripe_subscription_id": {
"name": "stripe_subscription_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"current_period_end": {
"name": "current_period_end",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"subscription_status": {
"name": "subscription_status",
"type": "varchar(50)",
"primaryKey": false,
"notNull": false
},
"plan_id": {
"name": "plan_id",
"type": "varchar(100)",
"primaryKey": false,
"notNull": false
},
"cancel_at_period_end": {
"name": "cancel_at_period_end",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"profiles_id_users_id_fk": {
"name": "profiles_id_users_id_fk",
"tableFrom": "profiles",
"tableTo": "users",
"schemaTo": "auth",
"columnsFrom": [
"id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
}
},
"enums": {},
"schemas": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}
================================================
FILE: apps/api/drizzle/migrations/meta/0003_snapshot.json
================================================
{
"id": "9b509c40-ab3f-410b-ac01-9401df6598c2",
"prevId": "4d86e969-3e44-4e26-bb6d-b76b9daa733e",
"version": "6",
"dialect": "postgresql",
"tables": {
"public.desktop_instances": {
"name": "desktop_instances",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"remote_id": {
"name": "remote_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"stream_url": {
"name": "stream_url",
"type": "varchar(1024)",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"ended_at": {
"name": "ended_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"desktop_instances_user_id_users_id_fk": {
"name": "desktop_instances_user_id_users_id_fk",
"tableFrom": "desktop_instances",
"tableTo": "users",
"schemaTo": "auth",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"public.profiles": {
"name": "profiles",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"unkey_key_id": {
"name": "unkey_key_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"stripe_customer_id": {
"name": "stripe_customer_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"stripe_subscription_id": {
"name": "stripe_subscription_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"current_period_end": {
"name": "current_period_end",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"subscription_status": {
"name": "subscription_status",
"type": "varchar(50)",
"primaryKey": false,
"notNull": false
},
"plan_id": {
"name": "plan_id",
"type": "varchar(100)",
"primaryKey": false,
"notNull": false
},
"cancel_at_period_end": {
"name": "cancel_at_period_end",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"profiles_id_users_id_fk": {
"name": "profiles_id_users_id_fk",
"tableFrom": "profiles",
"tableTo": "users",
"schemaTo": "auth",
"columnsFrom": [
"id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
}
},
"enums": {},
"schemas": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}
================================================
FILE: apps/api/drizzle/migrations/meta/0004_snapshot.json
================================================
{
"id": "36e12ff1-cb7e-46bd-bdc4-796464df0849",
"prevId": "9b509c40-ab3f-410b-ac01-9401df6598c2",
"version": "6",
"dialect": "postgresql",
"tables": {
"public.desktop_instances": {
"name": "desktop_instances",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"remote_id": {
"name": "remote_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"stream_url": {
"name": "stream_url",
"type": "varchar(1024)",
"primaryKey": false,
"notNull": true,
"default": "'https://placeholder-stream-url.cyberdesk.io'"
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"ended_at": {
"name": "ended_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"desktop_instances_user_id_users_id_fk": {
"name": "desktop_instances_user_id_users_id_fk",
"tableFrom": "desktop_instances",
"tableTo": "users",
"schemaTo": "auth",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"public.profiles": {
"name": "profiles",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"unkey_key_id": {
"name": "unkey_key_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"stripe_customer_id": {
"name": "stripe_customer_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"stripe_subscription_id": {
"name": "stripe_subscription_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"current_period_end": {
"name": "current_period_end",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"subscription_status": {
"name": "subscription_status",
"type": "varchar(50)",
"primaryKey": false,
"notNull": false
},
"plan_id": {
"name": "plan_id",
"type": "varchar(100)",
"primaryKey": false,
"notNull": false
},
"cancel_at_period_end": {
"name": "cancel_at_period_end",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"profiles_id_users_id_fk": {
"name": "profiles_id_users_id_fk",
"tableFrom": "profiles",
"tableTo": "users",
"schemaTo": "auth",
"columnsFrom": [
"id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
}
},
"enums": {},
"schemas": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}
================================================
FILE: apps/api/drizzle/migrations/meta/0005_snapshot.json
================================================
{
"id": "0efe305c-c062-4173-bc2d-8d92af93250f",
"prevId": "36e12ff1-cb7e-46bd-bdc4-796464df0849",
"version": "6",
"dialect": "postgresql",
"tables": {
"public.desktop_instances": {
"name": "desktop_instances",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"remote_id": {
"name": "remote_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"stream_url": {
"name": "stream_url",
"type": "varchar(1024)",
"primaryKey": false,
"notNull": true,
"default": "'https://placeholder-stream-url.cyberdesk.io'"
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"ended_at": {
"name": "ended_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"desktop_instances_user_id_users_id_fk": {
"name": "desktop_instances_user_id_users_id_fk",
"tableFrom": "desktop_instances",
"tableTo": "users",
"schemaTo": "auth",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"public.profiles": {
"name": "profiles",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"unkey_key_id": {
"name": "unkey_key_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"stripe_customer_id": {
"name": "stripe_customer_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"stripe_subscription_id": {
"name": "stripe_subscription_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"current_period_end": {
"name": "current_period_end",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"subscription_status": {
"name": "subscription_status",
"type": "varchar(50)",
"primaryKey": false,
"notNull": false
},
"plan_id": {
"name": "plan_id",
"type": "varchar(100)",
"primaryKey": false,
"notNull": false
},
"cancel_at_period_end": {
"name": "cancel_at_period_end",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"profiles_id_users_id_fk": {
"name": "profiles_id_users_id_fk",
"tableFrom": "profiles",
"tableTo": "users",
"schemaTo": "auth",
"columnsFrom": [
"id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
}
},
"enums": {},
"schemas": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}
================================================
FILE: apps/api/drizzle/migrations/meta/0006_snapshot.json
================================================
{
"id": "1f1576f8-a386-4198-a4b4-dbe02dbc8468",
"prevId": "0efe305c-c062-4173-bc2d-8d92af93250f",
"version": "6",
"dialect": "postgresql",
"tables": {
"public.cyberdesk_instances": {
"name": "cyberdesk_instances",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"status": {
"name": "status",
"type": "instance_status",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'pending'"
},
"timeout_at": {
"name": "timeout_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "NOW() + interval '24 hours'"
},
"stream_url": {
"name": "stream_url",
"type": "varchar(1024)",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"cyberdesk_instances_user_id_users_id_fk": {
"name": "cyberdesk_instances_user_id_users_id_fk",
"tableFrom": "cyberdesk_instances",
"tableTo": "users",
"schemaTo": "auth",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"public.desktop_instances": {
"name": "desktop_instances",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"remote_id": {
"name": "remote_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"stream_url": {
"name": "stream_url",
"type": "varchar(1024)",
"primaryKey": false,
"notNull": true,
"default": "'https://placeholder-stream-url.cyberdesk.io'"
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"ended_at": {
"name": "ended_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"desktop_instances_user_id_users_id_fk": {
"name": "desktop_instances_user_id_users_id_fk",
"tableFrom": "desktop_instances",
"tableTo": "users",
"schemaTo": "auth",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"public.profiles": {
"name": "profiles",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"unkey_key_id": {
"name": "unkey_key_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"stripe_customer_id": {
"name": "stripe_customer_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"stripe_subscription_id": {
"name": "stripe_subscription_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"current_period_end": {
"name": "current_period_end",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"subscription_status": {
"name": "subscription_status",
"type": "varchar(50)",
"primaryKey": false,
"notNull": false
},
"plan_id": {
"name": "plan_id",
"type": "varchar(100)",
"primaryKey": false,
"notNull": false
},
"cancel_at_period_end": {
"name": "cancel_at_period_end",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"profiles_id_users_id_fk": {
"name": "profiles_id_users_id_fk",
"tableFrom": "profiles",
"tableTo": "users",
"schemaTo": "auth",
"columnsFrom": [
"id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
}
},
"enums": {
"public.instance_status": {
"name": "instance_status",
"schema": "public",
"values": [
"pending",
"running",
"completed",
"error"
]
}
},
"schemas": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}
================================================
FILE: apps/api/drizzle/migrations/meta/0007_snapshot.json
================================================
{
"id": "39ccedc0-27c0-448a-971b-3217e72e8dfe",
"prevId": "1f1576f8-a386-4198-a4b4-dbe02dbc8468",
"version": "6",
"dialect": "postgresql",
"tables": {
"public.cyberdesk_instances": {
"name": "cyberdesk_instances",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"status": {
"name": "status",
"type": "instance_status",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'pending'"
},
"timeout_at": {
"name": "timeout_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "NOW() + interval '24 hours'"
},
"stream_url": {
"name": "stream_url",
"type": "varchar(1024)",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"cyberdesk_instances_user_id_users_id_fk": {
"name": "cyberdesk_instances_user_id_users_id_fk",
"tableFrom": "cyberdesk_instances",
"tableTo": "users",
"schemaTo": "auth",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"public.desktop_instances": {
"name": "desktop_instances",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"remote_id": {
"name": "remote_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"stream_url": {
"name": "stream_url",
"type": "varchar(1024)",
"primaryKey": false,
"notNull": true,
"default": "'https://placeholder-stream-url.cyberdesk.io'"
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"ended_at": {
"name": "ended_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"desktop_instances_user_id_users_id_fk": {
"name": "desktop_instances_user_id_users_id_fk",
"tableFrom": "desktop_instances",
"tableTo": "users",
"schemaTo": "auth",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"public.profiles": {
"name": "profiles",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"unkey_key_id": {
"name": "unkey_key_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"stripe_customer_id": {
"name": "stripe_customer_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"stripe_subscription_id": {
"name": "stripe_subscription_id",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"current_period_end": {
"name": "current_period_end",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"subscription_status": {
"name": "subscription_status",
"type": "varchar(50)",
"primaryKey": false,
"notNull": false
},
"plan_id": {
"name": "plan_id",
"type": "varchar(100)",
"primaryKey": false,
"notNull": false
},
"cancel_at_period_end": {
"name": "cancel_at_period_end",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"profiles_id_users_id_fk": {
"name": "profiles_id_users_id_fk",
"tableFrom": "profiles",
"tableTo": "users",
"schemaTo": "auth",
"columnsFrom": [
"id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
}
},
"enums": {
"public.instance_status": {
"name": "instance_status",
"schema": "public",
"values": [
"pending",
"running",
"terminated",
"error"
]
}
},
"schemas": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}
================================================
FILE: apps/api/drizzle/migrations/meta/_journal.json
================================================
{
"version": "5",
"dialect": "postgresql",
"entries": [
{
"idx": 0,
"version": "6",
"when": 1743009299784,
"tag": "0000_oval_outlaw_kid",
"breakpoints": true
},
{
"idx": 1,
"version": "6",
"when": 1743018990086,
"tag": "0001_busy_warstar",
"breakpoints": true
},
{
"idx": 2,
"version": "6",
"when": 1743040137195,
"tag": "0002_regular_doctor_faustus",
"breakpoints": true
},
{
"idx": 3,
"version": "6",
"when": 1743119400161,
"tag": "0003_superb_betty_brant",
"breakpoints": true
},
{
"idx": 4,
"version": "6",
"when": 1743119816127,
"tag": "0004_simple_komodo",
"breakpoints": true
},
{
"idx": 5,
"version": "6",
"when": 1743122830319,
"tag": "0005_mighty_hiroim",
"breakpoints": true
},
{
"idx": 6,
"version": "6",
"when": 1744919270291,
"tag": "0006_icy_black_bird",
"breakpoints": true
},
{
"idx": 7,
"version": "6",
"when": 1745534258042,
"tag": "0007_panoramic_tomorrow_man",
"breakpoints": true
}
]
}
================================================
FILE: apps/api/drizzle.config.ts
================================================
import { defineConfig } from "drizzle-kit";
export default defineConfig({
schema: "./src/db/supabase.ts",
schemaFilter: ["public"],
out: "./drizzle/migrations",
dialect: "postgresql",
dbCredentials: {
url: process.env.SUPABASE_CONNECTION_STRING!,
},
});
================================================
FILE: apps/api/fly.toml
================================================
# fly.toml app configuration file generated for cyberdesk-mvp-backend on 2025-03-27T05:00:43Z
#
# See https://fly.io/docs/reference/configuration/ for information about how to use this file.
#
app = 'cyberdesk-mvp-backend'
primary_region = 'dfw'
[build]
[http_service]
internal_port = 3000
force_https = true
auto_stop_machines = 'stop'
auto_start_machines = true
min_machines_running = 0
processes = ['app']
[[vm]]
memory = '1gb'
cpu_kind = 'shared'
cpus = 1
memory_mb = 1024
================================================
FILE: apps/api/package.json
================================================
{
"name": "api",
"type": "module",
"scripts": {
"build": "tsc",
"dev": "tsx watch src/index.ts",
"start": "node dist/index.js",
"env": "dotenv",
"db:push": "npm run env -- drizzle-kit push",
"db:studio": "npm run env -- drizzle-kit studio",
"db:generate": "npm run env -- drizzle-kit generate",
"db:migrate": "npm run env -- drizzle-kit migrate"
},
"dependencies": {
"@hono/node-server": "^1.14.0",
"@hono/zod-openapi": "^0.14.5",
"@libsql/client": "^0.6.2",
"@supabase/supabase-js": "^2.49.3",
"@unkey/api": "^0.20.7",
"@unkey/cache": "^1.0.2",
"@unkey/hono": "^1.2.0",
"@unkey/ratelimit": "^0.1.12",
"axios": "^1.9.0",
"dotenv": "^16.4.7",
"drizzle-orm": "^0.30.10",
"hono": "^4.4.7",
"postgres": "^3.4.5",
"posthog-node": "^4.17.1",
"zod": "^3.23.8"
},
"devDependencies": {
"@cloudflare/workers-types": "^4.20240529.0",
"@types/node": "^22.15.0",
"dotenv-cli": "^7.4.2",
"drizzle-kit": "^0.21.4",
"eslint-plugin-drizzle": "^0.2.3",
"tsx": "^3.10.6",
"typescript": "^5.8.2",
"wrangler": "^3.57.2"
}
}
================================================
FILE: apps/api/src/db/dbActions.ts
================================================
import { eq, and, sql } from "drizzle-orm";
import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
import { schema } from "../index.js";
import { InstanceStatus, instanceStatusEnum } from "./schema.js";
import { NotFoundError } from "../lib/errors.js";
/**
* Creates a new Cyberdesk instance for a user.
* @param db Drizzle database instance
* @param userId The user ID to create the instance for
* @param timeoutMs Optional timeout in milliseconds. Defaults to 24 hours.
* @returns The newly created Cyberdesk instance details (id, status)
*/
export async function addDbInstance(
db: PostgresJsDatabase<typeof schema>,
userId: string,
timeoutMs?: number
) {
const timeoutInterval = timeoutMs ? `${timeoutMs} milliseconds` : '24 hours';
const [newInstance] = await db
.insert(schema.cyberdeskInstances)
.values({
userId,
status: InstanceStatus.Pending,
timeoutAt: sql`NOW() + interval '${sql.raw(timeoutInterval)}'`,
})
.returning({
id: schema.cyberdeskInstances.id,
status: schema.cyberdeskInstances.status,
});
return newInstance;
}
/**
* Updates the status of a specific Cyberdesk instance, verifying ownership.
* @param db Drizzle database instance
* @param id The UUID of the Cyberdesk instance to update
* @param userId The user ID making the request (for authorization)
* @param status The new status to set
* @returns The updated instance details
* @throws NotFoundError if the instance is not found or the user is not authorized
*/
export async function updateDbInstanceStatus(
db: PostgresJsDatabase<typeof schema>,
id: string,
userId: string,
status: InstanceStatus
) {
const [updatedInstance] = await db
.update(schema.cyberdeskInstances)
.set({
status: status,
updatedAt: new Date(),
})
.where(
and(
eq(schema.cyberdeskInstances.id, id),
eq(schema.cyberdeskInstances.userId, userId)
)
)
.returning({
id: schema.cyberdeskInstances.id,
status: schema.cyberdeskInstances.status,
});
if (!updatedInstance) {
throw new NotFoundError("Desktop instance not found or user not authorized.");
}
return updatedInstance;
}
/**
* Gets specific details (id, status, createdAt, timeoutAt) for a Cyberdesk instance by ID, verifying ownership.
* @param db Drizzle database instance
* @param id The UUID of the Cyberdesk instance to get details for
* @param userId The user ID making the request (for authorization)
* @returns The instance details
* @throws NotFoundError if the instance is not found or the user is not authorized
*/
export async function getDbInstanceDetails(
db: PostgresJsDatabase<typeof schema>,
id: string,
userId: string
) {
const [result] = await db
.select({
id: schema.cyberdeskInstances.id,
status: schema.cyberdeskInstances.status,
createdAt: schema.cyberdeskInstances.createdAt,
timeoutAt: schema.cyberdeskInstances.timeoutAt,
streamUrl: schema.cyberdeskInstances.streamUrl,
})
.from(schema.cyberdeskInstances)
.where(
and(
eq(schema.cyberdeskInstances.id, id),
eq(schema.cyberdeskInstances.userId, userId)
)
)
.limit(1);
if (!result) {
throw new NotFoundError("Desktop instance not found or user not authorized.");
}
return result;
}
================================================
FILE: apps/api/src/db/index.ts
================================================
import { drizzle } from "drizzle-orm/postgres-js";
import postgres from "postgres";
import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
import * as dotenv from 'dotenv';
// Ensure environment variables are loaded
dotenv.config();
import { schema } from "../index.js";
function connectDatabase(env: { SUPABASE_CONNECTION_STRING: string }): PostgresJsDatabase<typeof schema> {
// Create a Postgres client for Drizzle
const connectionString = env.SUPABASE_CONNECTION_STRING;
const client = postgres(connectionString);
// Return a Drizzle instance with the schema
return drizzle(client, { schema });
}
// Use the connection string directly from process.env
const connectionString = process.env.SUPABASE_CONNECTION_STRING || "";
let db: PostgresJsDatabase<typeof schema>;
try {
db = connectDatabase({
SUPABASE_CONNECTION_STRING: connectionString,
});
} catch (error) {
console.error("Failed to connect to database:", error);
throw error;
}
export { db };
================================================
FILE: apps/api/src/db/schema.ts
================================================
import { pgTable, serial, text, index, varchar, uuid, timestamp, pgSchema, jsonb, boolean, pgEnum } from "drizzle-orm/pg-core";
import { sql } from "drizzle-orm";
// Define the auth schema and users table
const authSchema = pgSchema('auth');
const users = authSchema.table('users', {
id: uuid('id').primaryKey(),
// You can add other fields from auth.users if needed
});
// Define the profiles table
export const profiles = pgTable("profiles", {
id: uuid("id").primaryKey().references(() => users.id, { onDelete: 'cascade' }),
unkeyKeyId: varchar("unkey_key_id", { length: 255 }),
stripeCustomerId: varchar("stripe_customer_id", { length: 255 }),
stripeSubscriptionId: varchar("stripe_subscription_id", { length: 255 }),
currentPeriodEnd: timestamp("current_period_end"),
subscriptionStatus: varchar("subscription_status", { length: 50 }),
planId: varchar("plan_id", { length: 100 }),
cancelAtPeriodEnd: boolean("cancel_at_period_end").default(false),
createdAt: timestamp("created_at").defaultNow(),
updatedAt: timestamp("updated_at").defaultNow(),
});
// Define the status enum type
export enum InstanceStatus {
Pending = 'pending',
Running = 'running',
Terminated = 'terminated',
Error = 'error',
}
// Define the status enum type for Drizzle using the TS enum values
// Assert type as [string, ...string[]] to satisfy pgEnum's expectation
export const instanceStatusEnum = pgEnum('instance_status', Object.values(InstanceStatus) as [string, ...string[]]);
// Define the desktop_instances table
export const desktopInstances = pgTable("desktop_instances", {
id: uuid("id").primaryKey().defaultRandom(),
remoteId: varchar("remote_id", { length: 255 }).notNull(),
userId: uuid("user_id").notNull().references(() => users.id, { onDelete: 'cascade' }), // Required field
streamUrl: varchar("stream_url", { length: 1024 }).notNull().default("https://placeholder-stream-url.cyberdesk.io"), // Default value for existing records
createdAt: timestamp("created_at").defaultNow(),
endedAt: timestamp("ended_at"), // Optional field (nullable by default)
});
// Define the cyberdesk_instances table (MVP 3)
export const cyberdeskInstances = pgTable("cyberdesk_instances", {
id: uuid("id").primaryKey().defaultRandom(),
userId: uuid("user_id").notNull().references(() => users.id, { onDelete: 'cascade' }), // Required field
createdAt: timestamp("created_at").defaultNow(),
updatedAt: timestamp("updated_at"),
status: instanceStatusEnum("status").notNull().default(InstanceStatus.Pending),
timeoutAt: timestamp("timeout_at").notNull().default(sql`NOW() + interval '24 hours'`), // Set default to 24 hours from now
streamUrl: varchar("stream_url", { length: 1024 })
});
================================================
FILE: apps/api/src/index.ts
================================================
import { newApp } from "./lib/hono.js";
import desktop from "./routes/desktop.js";
import { serve } from "@hono/node-server";
import * as dotenv from 'dotenv'
export * as schema from "./db/schema.js"
// Load environment variables from .env.local file
dotenv.config()
const app = newApp();
// app.use(initCache());
// app.use(initRatelimiter());
app.route("/v1/", desktop);
// Use PORT environment variable with fallback to 3000 for local development
const port = process.env.PORT ? parseInt(process.env.PORT) : 3000;
serve(
{
fetch: app.fetch,
port: port
},
(info) => {
console.log(`Server is running on port ${info.port}`);
}
);
================================================
FILE: apps/api/src/lib/cache.ts
================================================
import { createCache, type Cache as C} from "@unkey/cache";
import { MemoryStore } from "@unkey/cache/stores";
import type { Context, Middleware } from "./hono.js";
import type { Next } from "hono";
export type CacheNamespaces = {
// Define new namespaces here as needed
}
export type Cache = C<CacheNamespaces>
const persistentMap = new Map();
export function initCache(): Middleware {
return async (c: Context, next: Next) => {
const memory = new MemoryStore({ persistentMap: new Map() });
const cache = createCache<CacheNamespaces>({
// Add new namespaces as needed
});
c.set("cache", cache);
return next();
};
}
================================================
FILE: apps/api/src/lib/errors.ts
================================================
import { type Context, type Next } from 'hono';
import { HTTPException } from 'hono/http-exception';
import { ZodError } from 'zod';
import type { ContentfulStatusCode } from 'hono/utils/http-status';
// Base API Error class
export class ApiError extends Error {
public readonly statusCode: number;
constructor(message: string, statusCode: number) {
super(message);
this.statusCode = statusCode;
this.name = this.constructor.name; // Set the error name to the class name
Error.captureStackTrace(this, this.constructor); // Capture stack trace
}
}
// Specific Error Types
export class BadRequestError extends ApiError {
constructor(message = 'Bad Request') {
super(message, 400);
}
}
export class UnauthorizedError extends ApiError {
constructor(message = 'Unauthorized') {
super(message, 401);
}
}
export class NotFoundError extends ApiError {
constructor(message = 'Not Found') {
super(message, 404);
}
}
export class ConflictError extends ApiError {
constructor(message = 'Conflict') {
super(message, 409);
}
}
export class GatewayError extends ApiError {
constructor(message = 'Bad Gateway') {
super(message, 502);
}
}
export class InternalServerError extends ApiError {
constructor(message = 'Internal Server Error') {
super(message, 500);
}
}
// Specific error for when a command fails *inside* the CyberDesk instance
// We might still want to return a 200 OK with an error status for this scenario.
export class ActionExecutionError extends Error {
public readonly details?: string; // e.g., stderr output
constructor(message: string, details?: string) {
super(message);
this.details = details;
this.name = this.constructor.name;
Error.captureStackTrace(this, this.constructor);
}
}
// Hono Error Handler Middleware
export const honoErrorHandler = (err: Error, c: Context) => {
console.error("Error caught by middleware:", err); // Log the full error
// Handle Zod validation errors specifically
if (err instanceof ZodError) {
const validationErrors = err.errors.map(e => `${e.path.join('.')}: ${e.message}`).join(', ');
return c.json(
{
status: "error",
error: `Validation failed: ${validationErrors}`,
docs: "https://docs.cyberdesk.io/docs/api-reference/",
},
400 // Bad Request for validation errors
);
}
// Handle our custom ApiError instances
if (err instanceof ApiError) {
return c.json(
{
status: "error",
error: err.message,
docs: "https://docs.cyberdesk.io/docs/api-reference/",
},
err.statusCode as ContentfulStatusCode
);
}
// Handle Hono's built-in HTTPException
if (err instanceof HTTPException) {
return c.json(
{
status: "error",
error: err.message,
docs: "https://docs.cyberdesk.io/docs/api-reference/",
},
err.status as ContentfulStatusCode
);
}
// Handle ActionExecutionError specifically (return 200 OK with error status)
if (err instanceof ActionExecutionError) {
return c.json(
{
status: "error",
error: err.message,
details: err.details, // Optionally include details like stderr
},
200 // Special case: Action failed but API communication was successful
);
}
// Fallback for unexpected errors
return c.json(
{
status: "error",
error: "An unexpected internal server error occurred.",
docs: "https://docs.cyberdesk.io/docs/api-reference/",
},
500 as const
);
};
================================================
FILE: apps/api/src/lib/hono.ts
================================================
import { OpenAPIHono, z } from "@hono/zod-openapi";
import type { UnkeyContext } from "@unkey/hono";
import type { Ratelimit } from "@unkey/ratelimit";
import type { Context as GenericContext, MiddlewareHandler } from "hono";
import type { ZodError } from "zod";
import type { Cache } from "./cache.js";
export type HonoEnv = {
Bindings: {
SUPABASE_CONNECTION_STRING: string;
// Unkey credentials
UNKEY_ROOT_KEY: string;
UNKEY_API_ID: string;
GATEWAY_URL: string;
};
Variables: {
cache: Cache
unkey: UnkeyContext;
ratelimit: Ratelimit;
};
};
export function parseZodErrorMessage(err: z.ZodError): string {
try {
const arr = JSON.parse(err.message) as Array<{
message: string;
path: Array<string>;
}>;
const { path, message } = arr[0];
return `${path.join(".")}: ${message}`;
} catch {
return err.message;
}
}
export function handleZodError(
result:
| {
success: true;
data: any;
}
| {
success: false;
error: ZodError;
},
c: Context
) {
if (!result.success) {
return c.json(
{
error: parseZodErrorMessage(result.error),
},
{ status: 400 }
);
}
}
export function newApp() {
const app = new OpenAPIHono<HonoEnv>({
defaultHook: handleZodError,
});
app.onError((err: Error, c: Context) => {
console.error(err);
return c.json(
{
error: err.message,
},
{ status: 500 }
);
});
app.doc("/openapi.json", {
openapi: "3.1.0",
info: {
title: "API Reference",
version: "1.2.1",
description: "API for Cyberdesk, to create, control, and manage virtual desktop instances.",
},
servers: [
{
url: "https://api.cyberdesk.io",
description: "Production server"
}
],
});
app.openAPIRegistry.registerComponent("securitySchemes", "apiKeyAuth", {
type: "apiKey",
in: "header",
name: "x-api-key"
});
return app;
}
export type App = ReturnType<typeof newApp>;
export type Context = GenericContext<HonoEnv>;
export type Middleware = MiddlewareHandler<HonoEnv>;
================================================
FILE: apps/api/src/lib/posthog.ts
================================================
import { PostHog } from 'posthog-node'
import * as dotenv from 'dotenv';
// Ensure environment variables are loaded
dotenv.config();
const POSTHOG_API_KEY = process.env.POSTHOG_API_KEY;
if (!POSTHOG_API_KEY) {
throw new Error('POSTHOG_API_KEY is not set');
}
const POSTHOG_HOST = process.env.POSTHOG_HOST || 'https://us.i.posthog.com';
const client = new PostHog(
POSTHOG_API_KEY,
{ host: POSTHOG_HOST, enableExceptionAutocapture: true },
)
export default client;
================================================
FILE: apps/api/src/lib/ratelimit.ts
================================================
import { Ratelimit } from "@unkey/ratelimit";
import type { Context, Middleware } from "./hono.js";
import type { Next } from "hono";
export function initRatelimiter(): Middleware {
return async (c: Context, next: Next) => {
const ratelimit = new Ratelimit({
rootKey: c.env.UNKEY_ROOT_KEY,
namespace: "api-toolbox",
limit: 10,
duration: "30s",
async: true,
});
c.set("ratelimit", ratelimit);
return next();
};
}
================================================
FILE: apps/api/src/routes/desktop.ts
================================================
import { OpenAPIHono } from "@hono/zod-openapi";
import { env } from 'hono/adapter';
import { unkey, type UnkeyContext } from "@unkey/hono";
import { z } from "@hono/zod-openapi";
import axios from "axios";
import { profiles, cyberdeskInstances, InstanceStatus } from "../db/schema.js";
import {
bashAction,
computerAction,
createDesktop,
stopDesktop,
ComputerActionSchema,
CreateDesktopParamsSchema,
getDesktop,
BashActionSchema,
} from "../schema/desktop.js";
import { GatewayExecuteCommandRequestSchema, GatewayExecuteCommandResponseSchema } from "../schema/gateway.js";
import { db } from "../db/index.js";
import {
addDbInstance,
getDbInstanceDetails,
updateDbInstanceStatus,
} from "../db/dbActions.js";
import {
ApiError,
NotFoundError,
ConflictError,
BadRequestError,
GatewayError,
ActionExecutionError,
honoErrorHandler,
UnauthorizedError,
InternalServerError,
} from "../lib/errors.js";
import posthogClient from '../lib/posthog.js';
import type { Context } from "hono";
// Type definitions
type EnvVars = {
UNKEY_API_ID: string;
SUPABASE_URL: string;
SUPABASE_ANON_KEY: string;
SUPABASE_CONNECTION_STRING?: string;
WEB_URL: string;
GATEWAY_URL: string;
};
// Use the schema type for computer actions
type ComputerAction = z.infer<typeof ComputerActionSchema>;
// Use the schema type for desktop creation parameters
type CreateDesktopParams = z.infer<typeof CreateDesktopParamsSchema>;
type BashAction = z.infer<typeof BashActionSchema>;
// Create Hono instance
const desktop = new OpenAPIHono<{
Variables: {
unkey: UnkeyContext;
userId: string;
};
}>();
// Register the global error handler
desktop.onError(honoErrorHandler);
// API key verification middleware
desktop.use("*", async (c, next) => {
const { UNKEY_API_ID } = env<EnvVars>(c);
const handler = unkey({
apiId: UNKEY_API_ID,
getKey: (c) => c.req.header("x-api-key"),
});
await handler(c, next);
});
// Helper function to capture API events in PostHog
async function captureApiEvent(
c: Context,
userId: string,
eventName: string,
additionalProperties: Record<string, any> = {}
) {
const properties = {
path: c.req.path,
method: c.req.method,
userAgent: c.req.header('User-Agent'),
...additionalProperties,
};
posthogClient.capture({
distinctId: userId,
event: eventName,
properties: properties,
});
}
// Authentication and database connection middleware
desktop.use("*", async (c, next) => {
const result = c.get("unkey");
if (!result?.valid) {
throw new UnauthorizedError("Invalid API key");
}
const userId = result.ownerId;
if (!userId) {
throw new UnauthorizedError("No user associated with this key");
}
c.set("userId", userId);
await next();
});
// Route for getting a desktop instance's details
desktop.openapi(getDesktop, async (c) => {
const userId = c.get("userId");
const id = c.req.param("id");
const { GATEWAY_URL } = env<EnvVars>(c);
if (!id) {
throw new BadRequestError("Instance ID is required");
}
await captureApiEvent(c, userId, 'Viewed Desktop Details');
const instanceDetails = await getDbInstanceDetails(db, id, userId);
// Adjust stream_url for dev environment if needed
let streamUrl: string | null = instanceDetails.streamUrl ?? null;
if (streamUrl && GATEWAY_URL.includes('dev-gateway')) {
// Replace any 'gateway.' (with or without subdomain) with 'dev-gateway.'
// This is to support the dev environment, where the gateway is accessible via dev-gateway.cyberdesk.io (or whatever subdomain you've set up)
streamUrl = streamUrl.replace(/\bgateway\./g, 'dev-gateway.');
}
return c.json({
id: instanceDetails.id,
status: instanceDetails.status,
created_at: (instanceDetails.createdAt || new Date(0)).toISOString(),
timeout_at: instanceDetails.timeoutAt.toISOString(),
stream_url: streamUrl
}, 200);
});
// Route for creating a new desktop instance
desktop.openapi(createDesktop, async (c) => {
const { GATEWAY_URL } = env<EnvVars>(c);
const userId = c.get("userId");
let createDesktopParams: CreateDesktopParams;
try {
const body = await c.req.json().catch(() => ({}));
createDesktopParams = CreateDesktopParamsSchema.parse(body);
await captureApiEvent(c, userId, 'Created Desktop');
const newInstance = await addDbInstance(db, userId, createDesktopParams.timeout_ms);
try {
const provisioningUrl = `${GATEWAY_URL}/cyberdesk/${newInstance.id}`;
const response = await axios.post(provisioningUrl, {
timeoutMs: createDesktopParams.timeout_ms
});
console.log('Provisioning request successful:', response.data);
return c.json(
{
id: newInstance.id,
status: newInstance.status,
},
200
);
} catch (provisioningError) {
console.error('Error calling provisioning service during creation:', provisioningError);
await updateDbInstanceStatus(db, newInstance.id, userId, InstanceStatus.Error).catch(console.error);
if (axios.isAxiosError(provisioningError)) {
throw new GatewayError(`Failed to provision via Gateway: ${provisioningError.response?.statusText || provisioningError.message}`);
} else {
throw new GatewayError('Failed to initiate provisioning of Cyberdesk resource via Gateway for instance ' + newInstance.id);
}
}
} catch (error) {
if (error instanceof z.ZodError) {
throw error;
} else if (error instanceof ApiError) {
throw error;
} else {
console.error('Unexpected error during desktop creation:', error);
throw new InternalServerError("Failed to create desktop instance due to an unexpected error.");
}
}
});
// Route for stopping a desktop instance
desktop.openapi(stopDesktop, async (c) => {
const userId = c.get("userId");
const id = c.req.param("id");
const { GATEWAY_URL } = env<EnvVars>(c);
await captureApiEvent(c, userId, 'Stopped Desktop');
const updatedInstance = await updateDbInstanceStatus(db, id, userId, InstanceStatus.Terminated);
try {
const provisioningUrl = `${GATEWAY_URL}/cyberdesk/${id}/stop`;
await axios.post(provisioningUrl);
} catch (provisioningError) {
console.error('Error calling provisioning service during stop:', provisioningError);
}
const responsePayload: { status: InstanceStatus } = {
status: updatedInstance.status as InstanceStatus,
};
return c.json(
responsePayload,
200
);
});
async function executeComputerAction(
id: string,
userId: string,
action: ComputerAction,
GATEWAY_URL: string
): Promise<string> {
console.log("Executing computer action:", action);
const instance = await getDbInstanceDetails(db, id, userId);
if (!instance) {
throw new NotFoundError("Instance not found or unauthorized");
}
if (instance.status !== 'running') {
throw new ConflictError(`Instance is not running (status: ${instance.status}). Cannot perform action.`);
}
let command: string;
const displayPrefix = "export DISPLAY=:99;";
switch (action.type) {
case "click_mouse": {
const { x, y, button = "left", num_of_clicks = 1, click_type = "click" } = action;
const buttonMap: { [key: string]: number } = { left: 1, middle: 2, right: 3 };
const btn = buttonMap[button] || 1;
let moveCmd = "";
if (x !== undefined && y !== undefined) {
moveCmd = `xdotool mousemove ${x} ${y} && `;
}
let clickCmd: string;
if (click_type === "click") {
clickCmd = `xdotool click --repeat ${num_of_clicks} ${btn}`;
} else if (click_type === "down") {
clickCmd = `xdotool mousedown ${btn}`;
} else { // up
clickCmd = `xdotool mouseup ${btn}`;
}
command = `${displayPrefix} ${moveCmd}${clickCmd}`;
break;
}
case "scroll": {
const { direction, amount } = action;
const directionMap: { [key: string]: number } = { up: 4, down: 5, left: 6, right: 7 };
const btn = directionMap[direction];
// Ensure amount is a reasonable positive integer
const repeatCount = Math.max(1, Math.min(Math.floor(amount), 500)); // Cap repeat at 500 for sanity
const delayMs = 25; // Reduce delay for faster scrolling
command = `${displayPrefix} xdotool click --repeat ${repeatCount} --delay ${delayMs} ${btn}`;
break;
}
case "move_mouse": {
command = `${displayPrefix} xdotool mousemove ${action.x} ${action.y}`;
break;
}
case "drag_mouse": {
const { start, end } = action;
command = `${displayPrefix} xdotool mousemove ${start.x} ${start.y} mousedown 1 mousemove ${end.x} ${end.y} mouseup 1`;
break;
}
case "type": {
const escapedText = action.text.replace(/'/g, "'\''");
command = `${displayPrefix} xdotool type --clearmodifiers --delay 50 '${escapedText}'`;
break;
}
case "press_keys": {
const { keys, key_action_type = "press" } = action;
const keyString = Array.isArray(keys) ? keys.join('+') : keys;
let keyCmd: string;
if (key_action_type === "down") {
keyCmd = `keydown`;
} else if (key_action_type === "up") {
keyCmd = `keyup`;
} else { // press
keyCmd = `key`;
}
command = `${displayPrefix} xdotool ${keyCmd} --clearmodifiers ${keyString}`;
break;
}
case "wait": {
const seconds = Math.max(0, action.ms / 1000);
command = `sleep ${seconds}`;
break;
}
case "screenshot": {
command = `${displayPrefix} scrot -q 100 /tmp/screen.jpg && base64 /tmp/screen.jpg && rm /tmp/screen.jpg`;
break;
}
case "get_cursor_position": {
command = `${displayPrefix} xdotool getmouselocation --shell`;
break;
}
default:
throw new BadRequestError(`Unsupported action type: ${(action as any).type}`);
}
console.log(`Executing command for instance ${id}: ${command}`);
const provisioningUrl = `${GATEWAY_URL}/cyberdesk/${id}/execute-command`;
const requestBody = GatewayExecuteCommandRequestSchema.parse({ command });
try {
const response = await axios.post<z.infer<typeof GatewayExecuteCommandResponseSchema>>(
provisioningUrl,
requestBody
);
const parsedResponse = GatewayExecuteCommandResponseSchema.parse(response.data);
if (parsedResponse.vm_response.return_code !== 0) {
throw new ActionExecutionError(
`Command failed with code ${parsedResponse.vm_response.return_code}`,
parsedResponse.vm_response.stderr || 'No stderr output'
);
}
return parsedResponse.vm_response.stdout.trim();
} catch (error: any) {
console.error(`Error executing command for instance ${id}:`, error);
if (error instanceof z.ZodError) {
throw new GatewayError(`Invalid response structure from gateway: ${error.errors.map(e => e.message).join(', ')}`);
} else if (axios.isAxiosError(error)) {
const gatewayMessage = error.response?.data?.message || error.message || "Failed to execute command via gateway";
throw new GatewayError(`Action execution failed via gateway: ${gatewayMessage}`);
} else if (error instanceof ApiError) {
throw error;
} else {
throw new InternalServerError(`Unexpected error during action execution: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
}
/**
* Executes a raw bash command on the target instance via the gateway.
* @param id Instance ID
* @param userId User ID for authorization
* @param command The bash command string to execute
* @param GATEWAY_URL Gateway URL
* @returns Promise<string> Resolves with stdout on success
* @throws Error on command failure or communication issues
*/
async function executeBashCommand(
id: string,
userId: string,
command: string,
GATEWAY_URL: string
): Promise<string> {
const instance = await getDbInstanceDetails(db, id, userId);
if (!instance) {
throw new NotFoundError("Instance not found or unauthorized");
}
if (instance.status !== 'running') {
throw new ConflictError(`Instance is not running (status: ${instance.status}). Cannot execute command.`);
}
console.log(`Executing bash command for instance ${id}: ${command}`);
const provisioningUrl = `${GATEWAY_URL}/cyberdesk/${id}/execute-command`;
const requestBody = GatewayExecuteCommandRequestSchema.parse({ command });
try {
const response = await axios.post<z.infer<typeof GatewayExecuteCommandResponseSchema>>(
provisioningUrl,
requestBody
);
const parsedResponse = GatewayExecuteCommandResponseSchema.parse(response.data);
console.log(`Bash command execution response for instance ${id}:`, parsedResponse);
return parsedResponse.vm_response.stdout.trim() || parsedResponse.vm_response.stderr.trim();
} catch (error: any) {
console.error(`Error executing bash command for instance ${id}:`, error);
if (error instanceof z.ZodError) {
throw new GatewayError(`Invalid response structure from gateway: ${error.errors.map(e => e.message).join(', ')}`);
} else if (axios.isAxiosError(error)) {
const gatewayMessage = error.response?.data?.message || error.message || "Failed to execute command via gateway";
throw new GatewayError(`Bash command execution failed via gateway: ${gatewayMessage}`);
} else if (error instanceof ApiError) {
throw error;
} else {
throw new InternalServerError(`Unexpected error during bash command execution: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
}
// Route for performing a computer action on a desktop
desktop.openapi(computerAction, async (c) => {
const userId = c.get("userId");
const id = c.req.param("id");
const { GATEWAY_URL } = env<EnvVars>(c);
let action: ComputerAction;
try {
const body = await c.req.json().catch(() => ({}));
action = ComputerActionSchema.parse(body);
// Capture event with actionType
await captureApiEvent(c, userId, 'Performed Computer Action', { actionType: action.type });
} catch (parseError: any) {
if (parseError instanceof z.ZodError) {
throw parseError;
}
throw new BadRequestError(`Invalid request body: ${parseError?.message || 'Unknown parsing error'}`);
}
const resultString = await executeComputerAction(id, userId, action, GATEWAY_URL);
if (action.type === "screenshot") {
// Remove all whitespace (including newlines) from base64 string
const cleanedBase64 = resultString.replace(/\s+/g, '');
return c.json({ base64_image: cleanedBase64 }, 200);
} else if (action.type === "get_cursor_position") {
return c.json({ output: resultString, }, 200);
} else {
return c.json({ output: resultString, }, 200);
}
});
// Route for executing a bash command on a desktop
desktop.openapi(bashAction, async (c) => {
const userId = c.get("userId");
const id = c.req.param("id");
const { GATEWAY_URL } = env<EnvVars>(c);
let bashAction: BashAction;
try {
const body = await c.req.json().catch(() => ({}));
bashAction = BashActionSchema.parse(body);
await captureApiEvent(c, userId, 'Executed Bash Command');
} catch (parseError: any) {
if (parseError instanceof z.ZodError) {
throw parseError;
}
throw new BadRequestError(`Invalid request body: ${parseError?.message || 'Unknown parsing error'}`);
}
const resultString = await executeBashCommand(id, userId, bashAction.command, GATEWAY_URL);
return c.json({ status: "success", output: resultString, }, 200);
});
export default desktop;
================================================
FILE: apps/api/src/schema/desktop.ts
================================================
import { createRoute, z } from "@hono/zod-openapi";
import { openApiErrorResponses } from "./errors.js";
import { InstanceStatus, instanceStatusEnum } from "../db/schema.js";
// Header schema for API key authentication
const HeadersSchema = z.object({
"x-api-key": z.string().openapi({
description: "API key for authentication",
example: "api_12345",
}),
});
// Common schema for action oriented API responses
const ActionResponseSchema = z.object({
output: z.string().optional().openapi({
description: "Raw string output from the executed command (if any)",
example: "X=500 Y=300",
}),
error: z.string().optional().openapi({
description: "Error message if the operation failed (also indicated by non-2xx HTTP status)",
example: "Command failed with code 1: xdotool: command not found",
}),
base64_image: z.string().optional().openapi({
description: "Base64 encoded JPEG image data (only returned for screenshot actions)",
example: "/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQ...",
})
});
// Point schema for coordinates
const PointSchema = z.object({
x: z.number().int().openapi({
description: "X coordinate on the screen",
example: 500,
}),
y: z.number().int().openapi({
description: "Y coordinate on the screen",
example: 300,
}),
});
// Schema for desktop creation parameters
export const CreateDesktopParamsSchema = z.object({
timeout_ms: z.number().int().optional().openapi({
description: "Timeout in milliseconds for the desktop session",
example: 3600000,
}),
});
// Schema for the response of the create desktop endpoint
export const CreateDesktopResponseSchema = z.object({
id: z.string().openapi({
description: "Unique identifier for the desktop instance",
example: "desktop_12345",
}),
status: z.enum(instanceStatusEnum.enumValues).openapi({
description: "Initial status of the desktop instance after creation request",
example: InstanceStatus.Pending,
}),
});
// Schema for the response of the stop desktop endpoint
export const StopDesktopResponseSchema = z.object({
status: z.enum(instanceStatusEnum.enumValues).openapi({
description: "Status of the desktop instance after stopping",
example: InstanceStatus.Terminated,
}),
});
// Computer action schema with discriminated union
export const ComputerActionSchema = z.discriminatedUnion("type", [
z.object({
type: z.literal("click_mouse").openapi({
description: "Perform a mouse action: click, press (down), or release (up). Defaults to a single left click at the current position.",
example: "click_mouse",
}),
x: z.number().int().optional().openapi({
description: "X coordinate for the action (optional, uses current position if omitted)",
example: 500,
}),
y: z.number().int().optional().openapi({
description: "Y coordinate for the action (optional, uses current position if omitted)",
example: 300,
}),
button: z.enum(["left", "right", "middle"]).optional().openapi({
description: "Mouse button to use (optional, defaults to 'left')",
example: "left",
}),
num_of_clicks: z.number().int().min(0).optional().openapi({
description: "Number of clicks to perform (optional, defaults to 1, only applicable for 'click' type)",
example: 1,
}),
click_type: z.enum(["click", "down", "up"]).optional().openapi({
description: "Type of mouse action (optional, defaults to 'click')",
example: "click",
}),
}).openapi({ title: "Click Mouse Action" }),
z.object({
type: z.literal("scroll").openapi({
description: "Scroll the mouse wheel in the specified direction",
example: "scroll",
}),
direction: z.enum(["up", "down", "left", "right"]).openapi({
description: "Direction to scroll",
example: "down",
}),
amount: z.number().int().openapi({
description: "Amount to scroll in pixels",
example: 100,
}),
}).openapi({ title: "Scroll Action" }),
z.object({
type: z.literal("move_mouse").openapi({
description: "Move the mouse cursor to the specified coordinates",
example: "move_mouse",
}),
x: z.number().int().openapi({
description: "X coordinate to move to",
example: 500,
}),
y: z.number().int().openapi({
description: "Y coordinate to move to",
example: 300,
}),
}).openapi({ title: "Move Mouse Action" }),
z.object({
type: z.literal("drag_mouse").openapi({
description: "Drag the mouse from start to end coordinates",
example: "drag_mouse",
}),
start: PointSchema.openapi({
description: "Starting coordinates for the drag operation",
example: { x: 100, y: 100 },
}),
end: PointSchema.openapi({
description: "Ending coordinates for the drag operation",
example: { x: 300, y: 300 },
}),
}).openapi({ title: "Drag Mouse Action" }),
z.object({
type: z.literal("type").openapi({
description: "Type text at the current cursor position",
example: "type",
}),
text: z.string().openapi({
description: "Text to type",
example: "Hello, World!",
}),
}).openapi({ title: "Type Text Action" }),
z.object({
type: z.literal("press_keys").openapi({
description: "Press, hold down, or release one or more keyboard keys. Defaults to a single press and release.",
example: "press_keys",
}),
keys: z.union([
z.string().openapi({
description: "Single key to press",
example: "Enter",
}),
z.array(z.string()).openapi({
description: "Multiple keys to press simultaneously",
example: ["Control", "c"],
})
]),
key_action_type: z.enum(["press", "down", "up"]).optional().openapi({
description: "Type of key action (optional, defaults to 'press' which is a down and up action)",
example: "press",
}),
}).openapi({ title: "Press Keys Action" }),
z.object({
type: z.literal("wait").openapi({
description: "Wait for the specified number of milliseconds",
example: "wait",
}),
ms: z.number().int().openapi({
description: "Time to wait in milliseconds",
example: 1000,
}),
}).openapi({ title: "Wait Action" }),
z.object({
type: z.literal("screenshot").openapi({
description: "Take a screenshot of the desktop",
example: "screenshot",
}),
}).openapi({ title: "Screenshot Action" }),
z.object({
type: z.literal("get_cursor_position").openapi({
description: "Get the current mouse cursor position",
example: "get_cursor_position",
}),
}).openapi({ title: "Get Cursor Position Action" }),
]);
// Schema for Bash Action parameters
export const BashActionSchema = z.object({
command: z.string().openapi({
description: "Bash command to execute",
example: "echo 'Hello, World!'",
}),
});
// Create Desktop Route
export const createDesktop = createRoute({
method: "post",
path: "/desktop",
tags: ["Desktop"],
summary: "Create a new virtual desktop instance",
description: "Creates a new virtual desktop instance and returns its ID and stream URL",
request: {
headers: HeadersSchema,
body: {
content: {
"application/json": {
schema: CreateDesktopParamsSchema,
},
},
},
},
responses: {
200: {
content: {
"application/json": {
schema: CreateDesktopResponseSchema,
},
},
description: "Desktop creation initiated successfully",
},
...openApiErrorResponses,
},
});
// Stop Desktop Route
export const stopDesktop = createRoute({
method: "post",
path: "/desktop/{id}/stop",
tags: ["Desktop"],
summary: "Stop a running desktop instance",
description: "Stops a running desktop instance and cleans up resources",
request: {
headers: HeadersSchema,
params: z.object({
id: z.string().openapi({
description: "Desktop instance ID to stop",
example: "desktop_12345",
}),
}),
},
responses: {
200: {
content: {
"application/json": {
schema: StopDesktopResponseSchema,
},
},
description: "Desktop stopped successfully",
},
...openApiErrorResponses,
},
});
// Get Desktop Route Response Schema
const GetDesktopResponseSchema = z.object({
id: z.string().uuid().openapi({
description: "Unique identifier for the desktop instance",
example: "a1b2c3d4-e5f6-7890-1234-567890abcdef",
}),
status: z.enum(instanceStatusEnum.enumValues).openapi({
description: "Current status of the desktop instance",
example: "running",
}),
stream_url: z.string().nullable().openapi({
description: "URL for the desktop stream (null if the desktop is not running)",
example: "https://cyberdesk.com/vnc/a1b2c3d4-e5f6-7890-1234-567890abcdef",
}),
created_at: z.string().datetime().openapi({
description: "Timestamp when the instance was created",
example: "2023-10-27T10:00:00Z",
}),
timeout_at: z.string().datetime().openapi({
description: "Timestamp when the instance will automatically time out",
example: "2023-10-28T10:00:00Z",
}),
});
// Get Desktop Route
export const getDesktop = createRoute({
method: "get",
path: "/desktop/{id}",
tags: ["Desktop"],
summary: "Get details of a specific desktop instance",
description: "Returns the ID, status, creation timestamp, and timeout timestamp for a given desktop instance.",
request: {
headers: HeadersSchema,
params: z.object({
id: z.string().uuid().openapi({
description: "The UUID of the desktop instance to retrieve",
example: "a1b2c3d4-e5f6-7890-1234-567890abcdef",
}),
}),
},
responses: {
200: {
content: {
"application/json": {
schema: GetDesktopResponseSchema,
},
},
description: "Desktop instance details retrieved successfully",
},
...openApiErrorResponses,
},
});
// Computer Action Route
export const computerAction = createRoute({
method: "post",
path: "/desktop/{id}/computer-action",
tags: ["Desktop"],
summary: "Perform an action on the desktop",
description: "Executes a computer action such as mouse clicks, keyboard input, or screenshots on the desktop",
request: {
headers: HeadersSchema,
params: z.object({
id: z.string().openapi({
description: "Desktop instance ID to perform the action on",
example: "desktop_12345",
}),
}),
body: {
content: {
"application/json": {
schema: ComputerActionSchema,
},
},
},
},
responses: {
200: {
content: {
"application/json": {
schema: ActionResponseSchema,
},
},
description: "Action executed successfully. Response may contain output or image data depending on the action.",
},
...openApiErrorResponses,
},
});
// Bash Action Route
export const bashAction = createRoute({
method: "post",
path: "/desktop/{id}/bash-action",
tags: ["Desktop"],
summary: "Execute a bash command on the desktop",
description: "Runs a bash command on the desktop and returns the command output",
request: {
headers: HeadersSchema,
params: z.object({
id: z.string().openapi({
description: "Desktop instance ID to run the command on",
example: "desktop_12345",
}),
}),
body: {
content: {
"application/json": {
schema: BashActionSchema,
},
},
},
},
responses: {
200: {
content: {
"application/json": {
schema: ActionResponseSchema,
},
},
description: "Command executed successfully. Response contains command output.",
},
...openApiErrorResponses,
},
});
================================================
FILE: apps/api/src/schema/errors.ts
================================================
import { z } from "@hono/zod-openapi";
const errorSchema = z.object({
status: z.literal("error").openapi({ example: "error" }),
error: z.string().openapi({
description: "Error message detailing what went wrong",
example: "Instance not found or unauthorized"
})
});
export const openApiErrorResponses = {
400: {
description:
"The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).",
content: {
"application/json": {
schema: errorSchema,
},
},
},
401: {
description: `Although the HTTP standard specifies "unauthorized", semantically this response means "unauthenticated". That is, the client must authenticate itself to get the requested response.`,
content: {
"application/json": {
schema: errorSchema,
},
},
},
403: {
description:
"The client does not have access rights to the content; that is, it is unauthorized, so the server is refusing to give the requested resource. Unlike 401 Unauthorized, the client's identity is known to the server.",
content: {
"application/json": {
schema: errorSchema,
},
},
},
404: {
description:
"The server cannot find the requested resource. In the browser, this means the URL is not recognized. In an API, this can also mean that the endpoint is valid but the resource itself does not exist. Servers may also send this response instead of 403 Forbidden to hide the existence of a resource from an unauthorized client. This response code is probably the most well known due to its frequent occurrence on the web.",
content: {
"application/json": {
schema: errorSchema,
},
},
},
409: {
description:
"This response is sent when a request conflicts with the current state of the server.",
content: {
"application/json": {
schema: errorSchema,
},
},
},
429: {
description: `The user has sent too many requests in a given amount of time ("rate limiting")`,
content: {
"application/json": {
schema: errorSchema,
},
},
},
500: {
description:
"The server has encountered a situation it does not know how to handle.",
content: {
"application/json": {
schema: errorSchema,
},
},
},
502: {
description:
"The server, while acting as a gateway or proxy, received an invalid response from the upstream server.",
content: {
"application/json": {
schema: errorSchema,
},
},
},
};
================================================
FILE: apps/api/src/schema/gateway.ts
================================================
import { z } from 'zod';
// Schema for Gateway Execute Command Request
export const GatewayExecuteCommandRequestSchema = z.object({
command: z.string()
});
// Schema for Gateway Execute Command Response
export const GatewayExecuteCommandResponseSchema = z.object({
status: z.string(),
vm_status_code: z.number().int(),
vm_response: z.object({
args: z.array(z.string()).optional(),
return_code: z.number().int(),
stdout: z.string(),
stderr: z.string(),
duration_s: z.number().optional(),
})
});
================================================
FILE: apps/api/tsconfig.json
================================================
{
"compilerOptions": {
"target": "ESNext",
"module": "esnext",
"moduleResolution": "bundler",
"strict": true,
"verbatimModuleSyntax": false,
"esModuleInterop": true,
"skipLibCheck": true,
"types": [
"node"
],
"jsx": "react-jsx",
"jsxImportSource": "hono/jsx",
"outDir": "./dist",
"incremental": true
},
"include": ["src/**/*.ts", "src/**/*.tsx"],
"exclude": ["node_modules"]
}
================================================
FILE: apps/docs/.gitignore
================================================
# Dependencies
node_modules/
.pnp
.pnp.js
# Build outputs
.next/
out/
build/
dist/
.cache/
# Generated files
.docusaurus/
.cache-loader/
.vercel/
# Environment variables
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
# Debug logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# Editor directories and files
.idea/
.vscode/
*.swp
*.swo
.DS_Store
# Temporary files
*.log
*.tmp
tmp/
temp/
# Coverage directory
coverage/
================================================
FILE: apps/docs/.map.ts
================================================
/** Auto-generated **/
declare const map: Record<string, unknown>
export { map }
================================================
FILE: apps/docs/README.md
================================================
# docs
This is a Next.js application generated with
[Create Fumadocs](https://github.com/fuma-nama/fumadocs).
Run development server:
```bash
npm run dev
# or
pnpm dev
# or
yarn dev
```
Open http://localhost:3000/docs to view the documentation.
You can also view the reference documentation for the API at https://docs.cyberdesk.io/docs/api-reference which is generated from the /scripts/ directory.
## Learn More
To learn more about Fumadocs features , take a look at the following
resources:
- [Fumadocs](https://fumadocs.vercel.app) - learn about Fumadocs
================================================
FILE: apps/docs/app/api/search/route.ts
================================================
import { getPages } from "@/app/source";
import { createSearchAPI } from "fumadocs-core/search/server";
export const { GET } = createSearchAPI("advanced", {
indexes: getPages().map((page) => ({
title: page.data.title,
structuredData: page.data.exports.structuredData,
id: page.url,
url: page.url,
})),
});
================================================
FILE: apps/docs/app/docs/[[...slug]]/page.tsx
================================================
import { getPage, getPages } from "@/app/source";
import { DocsBody, DocsPage } from "fumadocs-ui/page";
import type { Metadata } from "next";
import { notFound } from "next/navigation";
export default async function Page({
params,
}: {
params: { slug?: string[] };
}) {
const page = getPage(params.slug);
if (page == null) {
notFound();
}
const MDX = page.data.exports.default;
return (
<DocsPage toc={page.data.exports.toc}>
<DocsBody>
<h1>{page.data.title}</h1>
<MDX />
</DocsBody>
</DocsPage>
);
}
export async function generateStaticParams() {
return getPages().map((page) => ({
slug: page.slugs,
}));
}
export function generateMetadata({ params }: { params: { slug?: string[] } }) {
const page = getPage(params.slug);
if (page == null) notFound();
return {
title: page.data.title,
description: page.data.description,
} satisfies Metadata;
}
================================================
FILE: apps/docs/app/docs/layout.tsx
================================================
import { DocsLayout } from "fumadocs-ui/layout";
import type { ReactNode } from "react";
import { baseOptions } from "../layout.config";
import { pageTree } from "../source";
export default function Layout({ children }: { children: ReactNode }) {
return (
<DocsLayout tree={pageTree} {...baseOptions}>
{children}
</DocsLayout>
);
}
================================================
FILE: apps/docs/app/global.css
================================================
@tailwind base;
@tailwind components;
@tailwind utilities;
================================================
FILE: apps/docs/app/layout.config.tsx
================================================
import { type BaseLayoutProps } from "fumadocs-ui/layout";
// basic configuration here
export const baseOptions: BaseLayoutProps = {
nav: {
title: "Cyberdesk Docs",
},
links: [
{
text: "Documentation",
url: "/docs",
active: "nested-url",
},
{
text: "Main Site",
url: "https://cyberdesk.io",
}
],
githubUrl: "https://github.com/cyberdesk-hq/cyberdesk",
};
================================================
FILE: apps/docs/app/layout.tsx
================================================
import "./global.css";
import { RootProvider } from "fumadocs-ui/provider";
import { Inter } from "next/font/google";
import type { ReactNode } from "react";
import { Analytics } from "@vercel/analytics/react";
const inter = Inter({
subsets: ["latin"],
});
export default function Layout({ children }: { children: ReactNode }) {
return (
<html lang="en" className={inter.className} suppressHydrationWarning>
<body>
<RootProvider>
{children}
<Analytics />
</RootProvider>
</body>
</html>
);
}
================================================
FILE: apps/docs/app/page.tsx
================================================
import { redirect } from 'next/navigation';
export default function HomePage() {
redirect('/docs');
}
================================================
FILE: apps/docs/app/source.ts
================================================
import { map } from "@/.map";
import { loader } from "fumadocs-core/source";
import { createMDXSource } from "fumadocs-mdx";
export const { getPage, getPages, pageTree } = loader({
baseUrl: "/docs",
rootDir: "docs",
source: createMDXSource(map),
});
================================================
FILE: apps/docs/content/docs/api-reference.mdx
================================================
---
title: API Reference
description: API for Cyberdesk, to create, control, and manage virtual desktop instances.
full: true
toc: false
---
import { Root, API, APIInfo, APIExample, Responses, Response, ResponseTypes, ExampleResponse, TypeScriptResponse, Property, ObjectCollapsible, Requests, Request } from "fumadocs-ui/components/api";
<Root>
<API>
<APIInfo method={"GET"} route={"/v1/desktop/:id"}>
## Get details of a specific desktop instance
Returns the ID, status, creation timestamp, and timeout timestamp for a given desktop instance.
### Path Parameters
<Property name={"id"} type={"string"} required={true} deprecated={false}>
The UUID of the desktop instance to retrieve
<span>Example: `"a1b2c3d4-e5f6-7890-1234-567890abcdef"`</span>
<span>Format: `"uuid"`</span>
</Property>
### Header Parameters
<Property name={"x-api-key"} type={"string"} required={true} deprecated={false}>
API key for authentication
<span>Example: `"api_12345"`</span>
</Property>
| Status code | Description |
| ----------- | ----------- |
| `200` | Desktop instance details retrieved successfully |
| `400` | The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing). |
| `401` | Although the HTTP standard specifies "unauthorized", semantically this response means "unauthenticated". That is, the client must authenticate itself to get the requested response. |
| `403` | The client does not have access rights to the content; that is, it is unauthorized, so the server is refusing to give the requested resource. Unlike 401 Unauthorized, the client's identity is known to the server. |
| `404` | The server cannot find the requested resource. In the browser, this means the URL is not recognized. In an API, this can also mean that the endpoint is valid but the resource itself does not exist. Servers may also send this response instead of 403 Forbidden to hide the existence of a resource from an unauthorized client. This response code is probably the most well known due to its frequent occurrence on the web. |
| `409` | This response is sent when a request conflicts with the current state of the server. |
| `429` | The user has sent too many requests in a given amount of time ("rate limiting") |
| `500` | The server has encountered a situation it does not know how to handle. |
| `502` | The server, while acting as a gateway or proxy, received an invalid response from the upstream server. |
</APIInfo>
<APIExample>
<Requests items={["cURL","JavaScript"]}>
<Request value={"cURL"}>
```bash
curl -X GET "https://api.cyberdesk.io/v1/desktop/:id" \
-H "x-api-key: api_12345"
```
</Request>
<Request value={"JavaScript"}>
```js
fetch("https://api.cyberdesk.io/v1/desktop/:id", {
method: "GET",
headers: {
"x-api-key": "api_12345"
}
});
```
</Request>
</Requests>
<Responses items={["200","400","401","403","404","409","429","500","502"]}>
<Response value={"200"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"id": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
"status": "running",
"stream_url": "https://cyberdesk.com/vnc/a1b2c3d4-e5f6-7890-1234-567890abcdef",
"created_at": "2023-10-27T10:00:00Z",
"timeout_at": "2023-10-28T10:00:00Z"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
/**
* Unique identifier for the desktop instance
*/
id: string;
/**
* Current status of the desktop instance
*/
status: "pending" | "running" | "terminated" | "error";
/**
* URL for the desktop stream (null if the desktop is not running)
*/
stream_url: string;
/**
* Timestamp when the instance was created
*/
created_at: string;
/**
* Timestamp when the instance will automatically time out
*/
timeout_at: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"400"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"401"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"403"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"404"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"409"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"429"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"500"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"502"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
</Responses>
</APIExample>
</API>
<API>
<APIInfo method={"POST"} route={"/v1/desktop"}>
## Create a new virtual desktop instance
Creates a new virtual desktop instance and returns its ID and stream URL
### Request Body (Optional)
<Property name={"timeout_ms"} type={"integer"} required={false} deprecated={undefined}>
Timeout in milliseconds for the desktop session
<span>Example: `3600000`</span>
</Property>
### Header Parameters
<Property name={"x-api-key"} type={"string"} required={true} deprecated={false}>
API key for authentication
<span>Example: `"api_12345"`</span>
</Property>
| Status code | Description |
| ----------- | ----------- |
| `200` | Desktop creation initiated successfully |
| `400` | The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing). |
| `401` | Although the HTTP standard specifies "unauthorized", semantically this response means "unauthenticated". That is, the client must authenticate itself to get the requested response. |
| `403` | The client does not have access rights to the content; that is, it is unauthorized, so the server is refusing to give the requested resource. Unlike 401 Unauthorized, the client's identity is known to the server. |
| `404` | The server cannot find the requested resource. In the browser, this means the URL is not recognized. In an API, this can also mean that the endpoint is valid but the resource itself does not exist. Servers may also send this response instead of 403 Forbidden to hide the existence of a resource from an unauthorized client. This response code is probably the most well known due to its frequent occurrence on the web. |
| `409` | This response is sent when a request conflicts with the current state of the server. |
| `429` | The user has sent too many requests in a given amount of time ("rate limiting") |
| `500` | The server has encountered a situation it does not know how to handle. |
| `502` | The server, while acting as a gateway or proxy, received an invalid response from the upstream server. |
</APIInfo>
<APIExample>
<Requests items={["cURL","JavaScript"]}>
<Request value={"cURL"}>
```bash
curl -X POST "https://api.cyberdesk.io/v1/desktop" \
-H "x-api-key: api_12345" \
-d '{
"timeout_ms": 3600000
}'
```
</Request>
<Request value={"JavaScript"}>
```js
fetch("https://api.cyberdesk.io/v1/desktop", {
method: "POST",
headers: {
"x-api-key": "api_12345"
}
});
```
</Request>
</Requests>
<Responses items={["200","400","401","403","404","409","429","500","502"]}>
<Response value={"200"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"id": "desktop_12345",
"status": "pending"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
/**
* Unique identifier for the desktop instance
*/
id: string;
/**
* Initial status of the desktop instance after creation request
*/
status: "pending" | "running" | "terminated" | "error";
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"400"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"401"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"403"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"404"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"409"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"429"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"500"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"502"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
</Responses>
</APIExample>
</API>
<API>
<APIInfo method={"POST"} route={"/v1/desktop/:id/stop"}>
## Stop a running desktop instance
Stops a running desktop instance and cleans up resources
### Path Parameters
<Property name={"id"} type={"string"} required={true} deprecated={false}>
Desktop instance ID to stop
<span>Example: `"desktop_12345"`</span>
</Property>
### Header Parameters
<Property name={"x-api-key"} type={"string"} required={true} deprecated={false}>
API key for authentication
<span>Example: `"api_12345"`</span>
</Property>
| Status code | Description |
| ----------- | ----------- |
| `200` | Desktop stopped successfully |
| `400` | The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing). |
| `401` | Although the HTTP standard specifies "unauthorized", semantically this response means "unauthenticated". That is, the client must authenticate itself to get the requested response. |
| `403` | The client does not have access rights to the content; that is, it is unauthorized, so the server is refusing to give the requested resource. Unlike 401 Unauthorized, the client's identity is known to the server. |
| `404` | The server cannot find the requested resource. In the browser, this means the URL is not recognized. In an API, this can also mean that the endpoint is valid but the resource itself does not exist. Servers may also send this response instead of 403 Forbidden to hide the existence of a resource from an unauthorized client. This response code is probably the most well known due to its frequent occurrence on the web. |
| `409` | This response is sent when a request conflicts with the current state of the server. |
| `429` | The user has sent too many requests in a given amount of time ("rate limiting") |
| `500` | The server has encountered a situation it does not know how to handle. |
| `502` | The server, while acting as a gateway or proxy, received an invalid response from the upstream server. |
</APIInfo>
<APIExample>
<Requests items={["cURL","JavaScript"]}>
<Request value={"cURL"}>
```bash
curl -X POST "https://api.cyberdesk.io/v1/desktop/:id/stop" \
-H "x-api-key: api_12345"
```
</Request>
<Request value={"JavaScript"}>
```js
fetch("https://api.cyberdesk.io/v1/desktop/:id/stop", {
method: "POST",
headers: {
"x-api-key": "api_12345"
}
});
```
</Request>
</Requests>
<Responses items={["200","400","401","403","404","409","429","500","502"]}>
<Response value={"200"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "terminated"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
/**
* Status of the desktop instance after stopping
*/
status: "pending" | "running" | "terminated" | "error";
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"400"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"401"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"403"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"404"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"409"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"429"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"500"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"502"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
</Responses>
</APIExample>
</API>
<API>
<APIInfo method={"POST"} route={"/v1/desktop/:id/computer-action"}>
## Perform an action on the desktop
Executes a computer action such as mouse clicks, keyboard input, or screenshots on the desktop
### Request Body (Optional)
<Property name={"body"} type={"Click Mouse Action | Scroll Action | Move Mouse Action | Drag Mouse Action | Type Text Action | Press Keys Action | Wait Action | Screenshot Action | Get Cursor Position Action"} required={false} deprecated={undefined}>
<ObjectCollapsible name={"Click Mouse Action"}>
<Property name={"type"} type={"string"} required={true} deprecated={undefined}>
Perform a mouse action: click, press (down), or release (up). Defaults to a single left click at the current position.
<span>Example: `"click_mouse"`</span>
<span>Value in: `"click_mouse"`</span>
</Property>
<Property name={"x"} type={"integer"} required={false} deprecated={undefined}>
X coordinate for the action (optional, uses current position if omitted)
<span>Example: `500`</span>
</Property>
<Property name={"y"} type={"integer"} required={false} deprecated={undefined}>
Y coordinate for the action (optional, uses current position if omitted)
<span>Example: `300`</span>
</Property>
<Property name={"button"} type={"string"} required={false} deprecated={undefined}>
Mouse button to use (optional, defaults to 'left')
<span>Example: `"left"`</span>
<span>Value in: `"left" | "right" | "middle"`</span>
</Property>
<Property name={"num_of_clicks"} type={"integer"} required={false} deprecated={undefined}>
Number of clicks to perform (optional, defaults to 1, only applicable for 'click' type)
<span>Example: `1`</span>
<span>Minimum: `0`</span>
</Property>
<Property name={"click_type"} type={"string"} required={false} deprecated={undefined}>
Type of mouse action (optional, defaults to 'click')
<span>Example: `"click"`</span>
<span>Value in: `"click" | "down" | "up"`</span>
</Property>
</ObjectCollapsible>
<ObjectCollapsible name={"Scroll Action"}>
<Property name={"type"} type={"string"} required={true} deprecated={undefined}>
Scroll the mouse wheel in the specified direction
<span>Example: `"scroll"`</span>
<span>Value in: `"scroll"`</span>
</Property>
<Property name={"direction"} type={"string"} required={true} deprecated={undefined}>
Direction to scroll
<span>Example: `"down"`</span>
<span>Value in: `"up" | "down" | "left" | "right"`</span>
</Property>
<Property name={"amount"} type={"integer"} required={true} deprecated={undefined}>
Amount to scroll in pixels
<span>Example: `100`</span>
</Property>
</ObjectCollapsible>
<ObjectCollapsible name={"Move Mouse Action"}>
<Property name={"type"} type={"string"} required={true} deprecated={undefined}>
Move the mouse cursor to the specified coordinates
<span>Example: `"move_mouse"`</span>
<span>Value in: `"move_mouse"`</span>
</Property>
<Property name={"x"} type={"integer"} required={true} deprecated={undefined}>
X coordinate to move to
<span>Example: `500`</span>
</Property>
<Property name={"y"} type={"integer"} required={true} deprecated={undefined}>
Y coordinate to move to
<span>Example: `300`</span>
</Property>
</ObjectCollapsible>
<ObjectCollapsible name={"Drag Mouse Action"}>
<Property name={"type"} type={"string"} required={true} deprecated={undefined}>
Drag the mouse from start to end coordinates
<span>Example: `"drag_mouse"`</span>
<span>Value in: `"drag_mouse"`</span>
</Property>
<Property name={"start"} type={"object"} required={true} deprecated={undefined}>
Starting coordinates for the drag operation
<span>Example: `{"x":100,"y":100}`</span>
<ObjectCollapsible name={"start"}>
<Property name={"x"} type={"integer"} required={true} deprecated={undefined}>
X coordinate on the screen
<span>Example: `500`</span>
</Property>
<Property name={"y"} type={"integer"} required={true} deprecated={undefined}>
Y coordinate on the screen
<span>Example: `300`</span>
</Property>
</ObjectCollapsible>
</Property>
<Property name={"end"} type={"object"} required={true} deprecated={undefined}>
Ending coordinates for the drag operation
<span>Example: `{"x":300,"y":300}`</span>
<ObjectCollapsible name={"end"}>
<Property name={"x"} type={"integer"} required={true} deprecated={undefined}>
X coordinate on the screen
<span>Example: `500`</span>
</Property>
<Property name={"y"} type={"integer"} required={true} deprecated={undefined}>
Y coordinate on the screen
<span>Example: `300`</span>
</Property>
</ObjectCollapsible>
</Property>
</ObjectCollapsible>
<ObjectCollapsible name={"Type Text Action"}>
<Property name={"type"} type={"string"} required={true} deprecated={undefined}>
Type text at the current cursor position
<span>Example: `"type"`</span>
<span>Value in: `"type"`</span>
</Property>
<Property name={"text"} type={"string"} required={true} deprecated={undefined}>
Text to type
<span>Example: `"Hello, World!"`</span>
</Property>
</ObjectCollapsible>
<ObjectCollapsible name={"Press Keys Action"}>
<Property name={"type"} type={"string"} required={true} deprecated={undefined}>
Press, hold down, or release one or more keyboard keys. Defaults to a single press and release.
<span>Example: `"press_keys"`</span>
<span>Value in: `"press_keys"`</span>
</Property>
<Property name={"keys"} type={"Any properties in string, array<string>"} required={true} deprecated={undefined}>
<ObjectCollapsible name={"Object 1"}>
<Property name={"element"} type={"array<string>"} required={false} deprecated={undefined}>
Multiple keys to press simultaneously
<span>Example: `["Control","c"]`</span>
</Property>
</ObjectCollapsible>
</Property>
<Property name={"key_action_type"} type={"string"} required={false} deprecated={undefined}>
Type of key action (optional, defaults to 'press' which is a down and up action)
<span>Example: `"press"`</span>
<span>Value in: `"press" | "down" | "up"`</span>
</Property>
</ObjectCollapsible>
<ObjectCollapsible name={"Wait Action"}>
<Property name={"type"} type={"string"} required={true} deprecated={undefined}>
Wait for the specified number of milliseconds
<span>Example: `"wait"`</span>
<span>Value in: `"wait"`</span>
</Property>
<Property name={"ms"} type={"integer"} required={true} deprecated={undefined}>
Time to wait in milliseconds
<span>Example: `1000`</span>
</Property>
</ObjectCollapsible>
<ObjectCollapsible name={"Screenshot Action"}>
<Property name={"type"} type={"string"} required={true} deprecated={undefined}>
Take a screenshot of the desktop
<span>Example: `"screenshot"`</span>
<span>Value in: `"screenshot"`</span>
</Property>
</ObjectCollapsible>
<ObjectCollapsible name={"Get Cursor Position Action"}>
<Property name={"type"} type={"string"} required={true} deprecated={undefined}>
Get the current mouse cursor position
<span>Example: `"get_cursor_position"`</span>
<span>Value in: `"get_cursor_position"`</span>
</Property>
</ObjectCollapsible>
</Property>
### Path Parameters
<Property name={"id"} type={"string"} required={true} deprecated={false}>
Desktop instance ID to perform the action on
<span>Example: `"desktop_12345"`</span>
</Property>
### Header Parameters
<Property name={"x-api-key"} type={"string"} required={true} deprecated={false}>
API key for authentication
<span>Example: `"api_12345"`</span>
</Property>
| Status code | Description |
| ----------- | ----------- |
| `200` | Action executed successfully. Response may contain output or image data depending on the action. |
| `400` | The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing). |
| `401` | Although the HTTP standard specifies "unauthorized", semantically this response means "unauthenticated". That is, the client must authenticate itself to get the requested response. |
| `403` | The client does not have access rights to the content; that is, it is unauthorized, so the server is refusing to give the requested resource. Unlike 401 Unauthorized, the client's identity is known to the server. |
| `404` | The server cannot find the requested resource. In the browser, this means the URL is not recognized. In an API, this can also mean that the endpoint is valid but the resource itself does not exist. Servers may also send this response instead of 403 Forbidden to hide the existence of a resource from an unauthorized client. This response code is probably the most well known due to its frequent occurrence on the web. |
| `409` | This response is sent when a request conflicts with the current state of the server. |
| `429` | The user has sent too many requests in a given amount of time ("rate limiting") |
| `500` | The server has encountered a situation it does not know how to handle. |
| `502` | The server, while acting as a gateway or proxy, received an invalid response from the upstream server. |
</APIInfo>
<APIExample>
<Requests items={["cURL","JavaScript"]}>
<Request value={"cURL"}>
```bash
curl -X POST "https://api.cyberdesk.io/v1/desktop/:id/computer-action" \
-H "x-api-key: api_12345" \
-d '{
"type": "click_mouse",
"x": 500,
"y": 300,
"button": "left",
"num_of_clicks": 1,
"click_type": "click"
}'
```
</Request>
<Request value={"JavaScript"}>
```js
fetch("https://api.cyberdesk.io/v1/desktop/:id/computer-action", {
method: "POST",
headers: {
"x-api-key": "api_12345"
}
});
```
</Request>
</Requests>
<Responses items={["200","400","401","403","404","409","429","500","502"]}>
<Response value={"200"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"output": "X=500 Y=300",
"error": "Command failed with code 1: xdotool: command not found",
"base64_image": "/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQ..."
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
/**
* Raw string output from the executed command (if any)
*/
output?: string;
/**
* Error message if the operation failed (also indicated by non-2xx HTTP status)
*/
error?: string;
/**
* Base64 encoded JPEG image data (only returned for screenshot actions)
*/
base64_image?: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"400"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"401"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"403"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"404"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"409"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"429"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"500"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"502"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
</Responses>
</APIExample>
</API>
<API>
<APIInfo method={"POST"} route={"/v1/desktop/:id/bash-action"}>
## Execute a bash command on the desktop
Runs a bash command on the desktop and returns the command output
### Request Body (Optional)
<Property name={"command"} type={"string"} required={true} deprecated={undefined}>
Bash command to execute
<span>Example: `"echo 'Hello, World!'"`</span>
</Property>
### Path Parameters
<Property name={"id"} type={"string"} required={true} deprecated={false}>
Desktop instance ID to run the command on
<span>Example: `"desktop_12345"`</span>
</Property>
### Header Parameters
<Property name={"x-api-key"} type={"string"} required={true} deprecated={false}>
API key for authentication
<span>Example: `"api_12345"`</span>
</Property>
| Status code | Description |
| ----------- | ----------- |
| `200` | Command executed successfully. Response contains command output. |
| `400` | The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing). |
| `401` | Although the HTTP standard specifies "unauthorized", semantically this response means "unauthenticated". That is, the client must authenticate itself to get the requested response. |
| `403` | The client does not have access rights to the content; that is, it is unauthorized, so the server is refusing to give the requested resource. Unlike 401 Unauthorized, the client's identity is known to the server. |
| `404` | The server cannot find the requested resource. In the browser, this means the URL is not recognized. In an API, this can also mean that the endpoint is valid but the resource itself does not exist. Servers may also send this response instead of 403 Forbidden to hide the existence of a resource from an unauthorized client. This response code is probably the most well known due to its frequent occurrence on the web. |
| `409` | This response is sent when a request conflicts with the current state of the server. |
| `429` | The user has sent too many requests in a given amount of time ("rate limiting") |
| `500` | The server has encountered a situation it does not know how to handle. |
| `502` | The server, while acting as a gateway or proxy, received an invalid response from the upstream server. |
</APIInfo>
<APIExample>
<Requests items={["cURL","JavaScript"]}>
<Request value={"cURL"}>
```bash
curl -X POST "https://api.cyberdesk.io/v1/desktop/:id/bash-action" \
-H "x-api-key: api_12345" \
-d '{
"command": "echo 'Hello, World!'"
}'
```
</Request>
<Request value={"JavaScript"}>
```js
fetch("https://api.cyberdesk.io/v1/desktop/:id/bash-action", {
method: "POST",
headers: {
"x-api-key": "api_12345"
}
});
```
</Request>
</Requests>
<Responses items={["200","400","401","403","404","409","429","500","502"]}>
<Response value={"200"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"output": "X=500 Y=300",
"error": "Command failed with code 1: xdotool: command not found",
"base64_image": "/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQ..."
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
/**
* Raw string output from the executed command (if any)
*/
output?: string;
/**
* Error message if the operation failed (also indicated by non-2xx HTTP status)
*/
error?: string;
/**
* Base64 encoded JPEG image data (only returned for screenshot actions)
*/
base64_image?: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"400"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"401"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"403"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"404"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"409"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"429"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"500"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
<Response value={"502"}>
<ResponseTypes>
<ExampleResponse>
```json
{
"status": "error",
"error": "Instance not found or unauthorized"
}
```
</ExampleResponse>
<TypeScriptResponse>
```ts
export interface Response {
status: "error";
/**
* Error message detailing what went wrong
*/
error: string;
}
```
</TypeScriptResponse>
</ResponseTypes>
</Response>
</Responses>
</APIExample>
</API>
</Root>
================================================
FILE: apps/docs/content/docs/conceptual-guide.mdx
================================================
---
title: Conceptual Guide
description: Understanding core concepts of Cyberdesk
---
Understanding the core concepts of Cyberdesk will help you build more effective applications.
## Architecture Overview
Cyberdesk is built on a microservices architecture that provides scalable, reliable access to virtual desktop environments. The system consists of:
- **API Service**: The backend service accessed via the SDK.
- **Desktop Pool**: Managed virtual desktop instances.
- **Stream Service**: Real-time visual streaming of desktop environments.
- **Database**: Persistent storage for desktop metadata and user information.
## Desktop Instances
A desktop instance is a virtual desktop environment running in the cloud. Each instance:
- Has a unique identifier (UUID format).
- Runs in an isolated environment for security.
- Can be controlled programmatically through the **SDK methods**.
- Provides a `stream_url` (obtained via SDK methods) for visual feedback.
- Persists until explicitly stopped (via `terminateDesktop`) or times out.
- Has configurable resources (CPU, memory, storage) - future feature.
When creating a desktop instance using `launchDesktop`, you can specify a custom timeout in milliseconds using the `body.timeout_ms` parameter. This allows you to control how long the desktop instance will remain active before being automatically terminated. If not specified, a default timeout is applied. Check your plan for maximum allowed timeout values.
## Computer Actions
Cyberdesk supports various computer actions to interact with the desktop via the **`executeComputerAction` SDK method**. Actions are specified using a `body` object containing a `type` field and associated parameters:
### Mouse Actions
- **`type: 'click_mouse'`**: Perform a mouse action (click, press down, or release up).
- `x`, `y` (optional): Coordinates for the click.
- `button` (optional): `left`, `right`, or `middle` (defaults to `left`).
- `num_of_clicks` (optional): Number of clicks (defaults to 1, for `click_type: 'click'`).
- `click_type` (optional): `click` (down and up), `down` (press), or `up` (release) (defaults to `click`).
- **`type: 'scroll'`**: Scroll the mouse wheel.
- `direction`: `up`, `down`, `left`, or `right`.
- `amount`: Amount to scroll in pixels.
- **`type: 'move_mouse'`**: Move the mouse cursor to specific coordinates.
- `x`, `y`: Target coordinates.
- **`type: 'drag_mouse'`**: Drag the mouse from a start point to an end point.
- `start`: `{ x, y }` starting coordinates.
- `end`: `{ x, y }` ending coordinates.
### Keyboard Actions
- **`type: 'type'`**: Type text at the current cursor position.
- `text`: The string to type.
- **`type: 'press_keys'`**: Press, hold down, or release keyboard keys.
- `keys`: A single key string (e.g., `'Enter'`) or an array of keys to press simultaneously (e.g., `['Control', 'c']`).
- `key_action_type` (optional): `press` (down and up), `down` (hold), or `up` (release) (defaults to `press`).
### Other Actions
- **`type: 'wait'`**: Pause execution for a specified duration.
- `ms`: Time to wait in milliseconds.
- **`type: 'screenshot'`**: Capture the current state of the desktop.
- Returns a `base64_image` field in the successful response object.
- **`type: 'get_cursor_position'`**: Get the current mouse cursor coordinates.
- Returns `x`, `y` coordinates in the successful response object.
## Bash Actions
Bash actions allow you to execute shell commands on the desktop instance via the **`executeBashAction` SDK method**. This is useful for:
- Installing software
- Running applications
- Manipulating files
- Executing scripts
- System configuration
The method accepts a `body.command` parameter containing the shell command to execute and returns the command `output` (stdout/stderr) as a string in the successful response object.
## Desktop Streaming
Cyberdesk provides real-time streaming of desktop visuals. The `stream_url` obtained from the `launchDesktop` or `getDesktop` SDK methods can be used for:
1. **Web-based Viewer**: Opening the URL in a browser.
2. **VNC Protocol**: Connecting with a VNC client (if the stream URL supports it).
3. **Embedded Iframe**: Embedding the desktop view directly in your web applications.
The streaming service aims for low-latency transmission suitable for real-time interaction.
## Authentication and Security
Cyberdesk uses API keys for authentication. The **SDK client is initialized with your API key**, which is then automatically included in all requests.
- API keys are associated with a specific user account.
- Rate limits apply to prevent abuse.
- Keys can be revoked or regenerated from your dashboard.
- Keep your API key secure.
Communication with the API is encrypted using TLS/SSL.
## Resource Management
Cyberdesk automatically manages resources:
- Desktop instances are cleaned up when stopped via the **`terminateDesktop` SDK method** or when they reach their timeout.
- Users are responsible for stopping instances when no longer needed to manage costs and resources.
- Resource quotas and limits may apply depending on your subscription plan.
## Error Handling
The Cyberdesk **SDK methods** simplify error handling. Each method returns a promise that resolves to an object. You should check if this object contains an `error` property:
```typescript
const result = await cyberdesk.someMethod(...);
if ('error' in result) {
// Handle the error
console.error('Cyberdesk SDK Error:', result.error);
// The 'error' property contains the descriptive error message from the API
} else {
// Process the successful result
console.log('Success:', result);
}
```
Common error scenarios include:
- Invalid parameters in the request body (`body` property of the method call).
- Missing or invalid API key (during client initialization or if the key is revoked).
- Attempting an action not allowed by your plan.
- Referencing a non-existent desktop instance ID (`path.id`).
- Rate limit exceeded.
- Server-side issues on the Cyberdesk platform.
Check the specific error message returned in the `error` property for details.
## Performance Considerations
When building applications with the Cyberdesk SDK, consider:
- **API Call Latency**: Network latency affects the time it takes for SDK methods to complete.
- **Action Duration**: Some actions (like `wait` or long bash commands) naturally take time.
- **Streaming Latency**: There will be some delay in the visual stream.
- **Error Retries**: For transient issues (like network errors or potential server-side hiccups), consider implementing retry logic around your SDK calls, possibly with exponential backoff.
## Billing and Usage
Cyberdesk billing is typically based on factors like:
- **Active Desktop Time**: The duration desktop instances are running (often billed per second or minute).
Monitor your usage and understand the pricing model via the Cyberdesk dashboard (coming soon!).
================================================
FILE: apps/docs/content/docs/index.mdx
================================================
---
title: Cyberdesk Documentation
description: Comprehensive documentation for Cyberdesk service
---
Welcome to the official documentation for Cyberdesk, a powerful service for creating, controlling, and managing virtual desktop instances in the cloud. This documentation focuses on using the **official TypeScript SDK**, the recommended way to interact with the Cyberdesk API. We also provide a Python SDK (docs coming soon!).
Whether you're building automation tools, testing applications, or creating AI agents that can interact with computers, the Cyberdesk SDK provides the tools you need.
## What's New
- **TypeScript + Python SDKs**: The easiest way to integrate Cyberdesk into your applications.
- **AI Integration Guide**: Learn how to integrate Cyberdesk with AI models like Claude to create agents that can use computers.
- **Responsive Desktop Viewer**: Implement a responsive viewer for desktop streams that works across all devices.
- **Enhanced API Reference**: Complete API documentation with examples and response formats
## Documentation Sections
- [Introduction](/docs/introduction) - Learn what Cyberdesk is and its key features
- [Quickstart](/docs/quickstart) - Get up and running with the Cyberdesk SDK in minutes
- [Tutorials](/docs/tutorials) - Step-by-step guides using the SDK for common use cases, including integration with AI agents
- [Conceptual Guide](/docs/conceptual-guide) - Understand the core concepts of Cyberdesk
- [API Reference](/docs/api-reference) - Detailed REST API documentation (primarily for reference, SDK usage is recommended)
## Key Features
- **Virtual Desktop Creation**: Create cloud-based desktop instances on demand
- **Programmatic Control**: Control mouse, keyboard, and system actions via API
- **Bash Command Execution**: Run shell commands on desktop instances
- **Visual Streaming**: Stream desktop visuals to your applications
- **AI Integration**: Easily integrate with AI models for computer control
- **Secure Authentication**: API key-based authentication for secure access
## Getting Started
The fastest way to get started with Cyberdesk is to follow our [Quickstart Guide](/docs/quickstart), which will walk you through setting up the SDK, creating your first desktop instance, and performing basic interactions.
For more detailed examples and use cases using the SDK, check out our [Tutorials](/docs/tutorials), which include step-by-step guides for common scenarios.
## Support
If you need help or have questions about Cyberdesk, you can:
- Join our [Discord community](https://discord.gg/ws5ddx5yZ8) for discussions and support
- Contact us at dev@cyberdesk.io, for issues and feature requests
We're constantly improving Cyberdesk based on user feedback, so please let us know how we can make it better!
================================================
FILE: apps/docs/content/docs/introduction.mdx
================================================
---
title: Introduction
description: Introduction to Cyberdesk
---
Cyberdesk provides a seamless way to create and interact with virtual desktop environments through a simple API. Whether you're building automation tools, testing applications, creating AI agents that can use computers, or developing remote desktop solutions, Cyberdesk offers a robust platform to handle your virtual desktop needs.
## What is Cyberdesk?
Cyberdesk is a cloud-based service that allows you to:
- Create virtual desktop instances on demand via the SDK
- Control desktop interactions programmatically (mouse movements, clicks, keyboard input) using SDK methods
- Execute bash commands remotely via the SDK
- Manage desktop lifecycle (creation, interaction, termination) through the SDK
- Stream desktop visuals to your applications or AI agents
## Key Features
- **Simple SDK**: An easy-to-use TypeScript SDK for Node.js and browser environments
- **Programmatic Control**: Full control over mouse, keyboard, and system actions via intuitive SDK functions
- **Secure Authentication**: Simple API key configuration within the SDK
- **Streaming Capability**: Stream desktop visuals to your applications with VNC support (SDK helps manage instance details)
- **Resource Management**: Efficient creation and cleanup of desktop instances managed via SDK calls
- **AI Integration**: Easily integrate with AI models like Claude or GPT to create agents that can use computers (see tutorials)
- **Cross-Platform**: Works across different operating systems and environments
- **Low Latency**: Fast response times for real-time interaction
## Use Cases
Cyberdesk is ideal for a variety of applications:
- **AI Agents**: Create AI assistants that can interact with desktop applications
- **Automated Testing**: Test desktop applications with programmatic control
- **Remote Automation**: Control desktop environments from anywhere
- **Demo Environments**: Create disposable demo environments for software showcases
- **Training Data Generation**: Generate training data for computer vision models
- **Virtual Workstations**: Provide remote access to virtual desktop environments
## Getting Started
To get started with Cyberdesk:
1. [Sign up](https://cyberdesk.io/signup) for an account
2. Obtain your API key from the dashboard
3. Follow our [Quickstart Guide](/docs/quickstart) to set up the SDK and create your first desktop instance
4. Explore our [Tutorials](/docs/tutorials) for common use cases
Ready to dive deeper? Check out our [Conceptual Guide](/docs/conceptual-guide) to understand the core concepts behind Cyberdesk.
================================================
FILE: apps/docs/content/docs/meta.json
================================================
{
"title": "Docs",
"pages": ["index", "introduction", "quickstart", "tutorials", "conceptual-guide", "api-reference"],
"defaultOpen": true,
"root": true
}
================================================
FILE: apps/docs/content/docs/quickstart.mdx
================================================
---
title: Quickstart
description: Get started quickly with Cyberdesk
---
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
Get up and running with Cyberdesk in minutes.
## Fastest Start: Cyberdesk Starter Assistant UI
The quickest way to get started with Cyberdesk is to use our [AI SDK Starter](https://github.com/cyberdesk-hq/cyberdesk-ai-sdk-starter) template. This ready-to-use Next.js application demonstrates how to build an AI assistant with virtual desktop control capabilities using the Cyberdesk API and Anthropic's Claude AI model.
### Features
- Interactive virtual desktop with streaming capabilities
- AI assistant chat interface powered by Claude 3.7 Sonnet
- Desktop control via AI (mouse clicks, keyboard input, screenshots)
- Bash command execution in the virtual environment
### Quick Setup
1. Clone the repository (alternatively, click "Use this template" on GitHub):
```bash
git clone https://github.com/cyberdesk-hq/cyberdesk-ai-sdk-starter.git
cd cyberdesk-ai-sdk-starter
```
2. Install dependencies:
```bash
npm install
```
3. Create a `.env.local` file with your API keys:
```
CYBERDESK_API_KEY=your_cyberdesk_api_key_here
ANTHROPIC_API_KEY=your_anthropic_api_key_here
```
4. Start the development server:
```bash
npm run dev
```
5. Open [http://localhost:3000](http://localhost:3000) in your browser
This template provides a complete working example that you can customize for your specific use case. For more details, check out the [repository README](https://github.com/cyberdesk-hq/cyberdesk-ai-sdk-starter).
## Building a Custom Integration
If you want to build your own integration, you can use either the **official TypeScript SDK** or the **official Python SDK**. See the code tabs below for both options.
### Prerequisites
- Node.js or Python 3.8+
- A Cyberdesk API key (obtain from your [Cyberdesk dashboard](https://cyberdesk.io/dashboard))
### Installation
<Tabs groupId="language" items={["TypeScript", "Python"]} persist>
<Tab value="TypeScript">
```bash
npm install cyberdesk
# or
yarn add cyberdesk
# or
pnpm add cyberdesk
```
</Tab>
<Tab value="Python">
```bash
pip install cyberdesk
```
</Tab>
</Tabs>
### 1. Initialize the Client
<Tabs groupId="language" items={["TypeScript", "Python"]} persist>
<Tab value="TypeScript">
```typescript
import { createCyberdeskClient } from 'cyberdesk';
const cyberdesk = createCyberdeskClient({
apiKey: 'YOUR_API_KEY',
// Optionally, you can override the baseUrl or provide a custom fetch implementation
});
```
</Tab>
<Tab value="Python">
```python
from cyberdesk import CyberdeskClient
client = CyberdeskClient(api_key="YOUR_API_KEY")
```
</Tab>
</Tabs>
### 2. Launch a Desktop Instance
<Tabs groupId="language" items={["TypeScript", "Python"]} persist>
<Tab value="TypeScript">
```typescript
const launchResult = await cyberdesk.launchDesktop({
body: { timeout_ms: 600000 } // Optional: 10-minute timeout
});
if ('error' in launchResult) {
throw new Error('Failed to launch desktop: ' + launchResult.error);
}
const desktopId = launchResult.id;
```
</Tab>
<Tab value="Python">
```python
result = client.launch_desktop(timeout_ms=10000) # Optional: set a timeout for the desktop session
if result.error:
raise Exception('Failed to launch desktop: ' + str(result.error))
desktop_id = result.id
```
</Tab>
</Tabs>
### 3. Get Desktop Information (Including Stream URL)
<Tabs groupId="language" items={["TypeScript", "Python"]} persist>
<Tab value="TypeScript">
```typescript
const info = await cyberdesk.getDesktop({ path: { id: desktopId } });
if ('error' in info) {
throw new Error('Failed to get desktop info: ' + info.error);
}
console.log('Desktop info:', info);
console.log('Stream URL:', info.stream_url);
```
</Tab>
<Tab value="Python">
```python
info = client.get_desktop(desktop_id)
if info.error:
raise Exception('Failed to get desktop info: ' + str(info.error))
print('Desktop info:', info)
# If available: print('Stream URL:', info.stream_url)
```
</Tab>
</Tabs>
### 4. Control the Desktop
#### Perform a Mouse Click
<Tabs groupId="language" items={["TypeScript", "Python"]} persist>
<Tab value="TypeScript">
```typescript
const actionResult = await cyberdesk.executeComputerAction({
path: { id: desktopId },
body: {
type: 'click_mouse',
x: 100,
y: 150,
button: 'left'
}
});
if ('error' in actionResult) {
throw new Error('Mouse click failed: ' + actionResult.error);
}
```
</Tab>
<Tab value="Python">
```python
from cyberdesk.actions import click_mouse, ClickMouseButton
action = click_mouse(x=100, y=150, button=ClickMouseButton.LEFT)
action_result = client.execute_computer_action(desktop_id, action)
if action_result.error:
raise Exception('Action failed: ' + str(action_result.error))
```
</Tab>
</Tabs>
#### Run a Bash Command
<Tabs groupId="language" items={["TypeScript", "Python"]} persist>
<Tab value="TypeScript">
```typescript
const bashResult = await cyberdesk.executeBashAction({
path: { id: desktopId },
body: {
command: 'ls -la /tmp'
}
});
if ('error' in bashResult) {
throw new Error('Bash command failed: ' + bashResult.error);
}
console.log('Bash command output:', bashResult.output);
```
</Tab>
<Tab value="Python">
```python
bash_result = client.execute_bash_action(
desktop_id,
"ls -la /tmp"
)
if bash_result.error:
raise Exception('Bash command failed: ' + str(bash_result.error))
print('Bash command output:', getattr(bash_result, 'output', bash_result))
```
</Tab>
</Tabs>
### 5. Stop the Desktop Instance
<Tabs groupId="language" items={["TypeScript", "Python"]} persist>
<Tab value="TypeScript">
```typescript
const terminateResult = await cyberdesk.terminateDesktop({
path: { id: desktopId }
});
if ('error' in terminateResult) {
// You might still want to proceed even if termination fails
}
```
</Tab>
<Tab value="Python">
```python
terminate_result = client.terminate_desktop(desktop_id)
if terminate_result.error:
print('Termination failed:', terminate_result.error)
```
</Tab>
</Tabs>
### 6. Async Usage
<Tabs groupId="language" items={["TypeScript", "Python"]} persist>
<Tab value="TypeScript">
```typescript
// All methods are available as async functions (see above)
```
</Tab>
<Tab value="Python">
```python
import asyncio
from cyberdesk import CyberdeskClient
from cyberdesk.actions import click_mouse, ClickMouseButton
async def main():
client = CyberdeskClient(api_key="YOUR_API_KEY")
result = await client.async_launch_desktop(timeout_ms=10000)
print(result)
action = click_mouse(x=100, y=200, button=ClickMouseButton.LEFT)
await client.async_execute_computer_action(desktop_id, action)
# ... use other async_ methods as needed
asyncio.run(main())
```
</Tab>
</Tabs>
### 7. Type Hints and Models
<Tabs groupId="language" items={["TypeScript", "Python"]} persist>
<Tab value="TypeScript">
```typescript
// All request/response types are available from the generated models
```
</Tab>
<Tab value="Python">
```python
from cyberdesk.actions import click_mouse, drag_mouse, type_text, wait, scroll, move_mouse, press_keys, screenshot, get_cursor_position, ClickMouseButton, ClickMouseActionType, PressKeyActionType, ScrollDirection
```
</Tab>
</Tabs>
### 8. Available Computer Actions
| Action | Factory Function (Python Only) | Description |
|----------------|-------------------------|----------------------------|
| Click Mouse | `click_mouse` | Mouse click at (x, y) |
| Drag Mouse | `drag_mouse` | Mouse drag from/to (x, y) |
| Move Mouse | `move_mouse` | Move mouse to (x, y) |
| Scroll | `scroll` | Scroll by dx, dy |
| Type Text | `type_text` | Type text |
| Press Keys | `press_keys` | Press keyboard keys |
| Screenshot | `screenshot` | Take a screenshot |
| Wait | `wait` | Wait for ms milliseconds |
| Get Cursor Pos | `get_cursor_position` | Get mouse cursor position |
## Next Steps
- Explore the [Tutorials](/docs/tutorials) for more complex examples using the SDK.
- Understand core concepts in the [Conceptual Guide](/docs/conceptual-guide).
- Review the [API Reference](/docs/api-reference) if you need details on the underlying REST API.
================================================
FILE: apps/docs/content/docs/tutorials.mdx
================================================
---
title: Tutorials
description: Step-by-step tutorials for using the Cyberdesk TypeScript SDK
---
Learn how to use the Cyberdesk TypeScript SDK effectively with these step-by-step tutorials.
**Setup:** All examples assume you have initialized the SDK client as shown in the [Quickstart](/docs/quickstart):
```typescript
import { createCyberdeskClient } from 'cyberdesk';
const cyberdesk = createCyberdeskClient({
apiKey: 'YOUR_API_KEY',
});
```
## Tutorial 1: Creating and Interacting with a Desktop
This tutorial walks you through creating a desktop instance and performing basic interactions using the SDK.
### Step 1: Create a Desktop Instance
Use `launchDesktop`:
```typescript
async function createDesktop() {
console.log('Creating desktop...');
const launchResult = await cyberdesk.launchDesktop({
body: { timeout_ms: 3600000 } // Optional: 1-hour timeout
});
if ('error' in launchResult) {
console.error('Failed to create desktop:', launchResult.error);
throw new Error('Failed to create desktop: ' + launchResult.error);
}
console.log(`Desktop created with ID: ${launchResult.id}`);
// Note: You might need to wait or use getDesktop to get the streamUrl
return launchResult.id;
}
// Example usage:
// const desktopId = await createDesktop();
```
### Step 2: Perform Mouse Actions
Use `executeComputerAction` with `type: 'click_mouse'`:
```typescript
async function clickOnDesktop(desktopId: string) {
console.log(`Clicking on desktop ${desktopId}...`);
const clickResult = await cyberdesk.executeComputerAction({
path: { id: desktopId },
body: {
type: 'click_mouse',
x: 100,
y: 200,
button: 'left' // Optional
}
});
if ('error' in clickResult) {
console.error('Mouse click failed:', clickResult.error);
throw new Error('Mouse click failed: ' + clickResult.error);
}
console.log('Mouse click successful:', clickResult);
}
// Example usage:
// await clickOnDesktop(desktopId);
```
### Step 3: Type Text
Use `executeComputerAction` with `type: 'type'`:
```typescript
async function typeOnDesktop(desktopId: string) {
console.log(`Typing on desktop ${desktopId}...`);
const typeResult = await cyberdesk.executeComputerAction({
path: { id: desktopId },
body: {
type: 'type',
text: 'Hello, Cyberdesk SDK!'
}
});
if ('error' in typeResult) {
console.error('Typing failed:', typeResult.error);
throw new Error('Typing failed: ' + typeResult.error);
}
console.log('Typing successful:', typeResult);
}
// Example usage:
// await typeOnDesktop(desktopId);
```
### Step 4: Take a Screenshot
Use `executeComputerAction` with `type: 'screenshot'`:
```typescript
async function captureScreenshot(desktopId: string) {
console.log(`Taking screenshot of desktop ${desktopId}...`);
const screenshotResult = await cyberdesk.executeComputerAction({
path: { id: desktopId },
body: {
type: 'screenshot'
}
});
if ('error' in screenshotResult) {
console.error('Screenshot failed:', screenshotResult.error);
throw new Error('Screenshot failed: ' + screenshotResult.error);
}
console.log('Screenshot successful.');
// Access the image data:
// const base64Image = screenshotResult.base64_image;
// console.log('Base64 Image length:', base64Image?.length);
return screenshotResult.base64_image;
}
// Example usage:
// const imageData = await captureScreenshot(desktopId);
```
### Step 5: Execute a Bash Command
Use `executeBashAction`:
```typescript
async function runCommand(desktopId: string) {
console.log(`Running command on desktop ${desktopId}...`);
const bashResult = await cyberdesk.executeBashAction({
path: { id: desktopId },
body: {
command: 'ls -la /tmp'
}
});
if ('error' in bashResult) {
console.error('Bash command failed:', bashResult.error);
throw new Error('Bash command failed: ' + bashResult.error);
}
console.log('Command successful.');
console.log('Output:', bashResult.output);
return bashResult.output;
}
// Example usage:
// const commandOutput = await runCommand(desktopId);
```
### Step 6: Stop the Desktop
Use `terminateDesktop`:
```typescript
async function stopDesktop(desktopId: string) {
console.log(`Stopping desktop ${desktopId}...`);
const stopResult = await cyberdesk.terminateDesktop({
path: { id: desktopId }
});
if ('error' in stopResult) {
console.error('Failed to stop desktop:', stopResult.error);
// Decide if you need to throw an error or just log
}
console.log('Desktop stop requested.', stopResult);
}
// Example usage:
// await stopDesktop(desktopId);
```
## Tutorial 2: Automating Web Testing
This tutorial demonstrates how to use the Cyberdesk SDK to automate simple web browser tasks.
### Step 1: Create a Desktop Instance
Create a desktop instance using the `createDesktop` function from Tutorial 1.
```typescript
// const desktopId = await createDesktop();
```
### Step 2: Open a Web Browser and Wait
Use `executeBashAction` to open a browser (e.g., Firefox) in the background, then use `executeComputerAction` with `type: 'wait'` to allow time for it to load.
```typescript
async function openBrowserAndWait(desktopId: string, url: string, waitMs: number = 5000) {
console.log(`Opening ${url} on desktop ${desktopId}...`);
const openResult = await cyberdesk.executeBashAction({
path: { id: desktopId },
body: {
command: `firefox ${url} &` // Run in background
}
});
if ('error' in openResult) {
console.error('Failed to send open browser command:', openResult.error);
throw new Error('Failed to send open browser command: ' + openResult.error);
}
console.log('Browser opening command sent.');
console.log(`Waiting ${waitMs}ms for browser to load...`);
const waitResult = await cyberdesk.executeComputerAction({
path: { id: desktopId },
body: {
type: 'wait',
ms: waitMs
}
});
if ('error' in waitResult) {
console.error('Wait action failed:', waitResult.error);
throw new Error('Wait action failed: ' + waitResult.error);
}
console.log('Wait complete.');
}
// Example usage:
// await openBrowserAndWait(desktopId, 'https://example.com');
```
### Step 3: Take a Screenshot for Verification
Capture a screenshot using the `captureScreenshot` function from Tutorial 1 to verify the page loaded.
```typescript
async function verifyPageLoad(desktopId: string) {
console.log('Taking verification screenshot...');
const imageData = await captureScreenshot(desktopId);
if (imageData) {
console.log('Verification screenshot captured (length:', imageData.length, ')');
// Add logic here to analyze the screenshot if needed
} else {
console.warn('Could not capture verification screenshot.');
}
}
// Example usage:
// await verifyPageLoad(desktopId);
```
### Step 4: Stop the Desktop
Remember to stop the desktop instance using the `stopDesktop` function from Tutorial 1 when the test is complete.
```typescript
// await stopDesktop(desktopId);
```
## Tutorial 3: Integrating with AI Models for Computer Use
This tutorial demonstrates how to integrate the Cyberdesk SDK with AI models (like Anthropic's Claude) using the Vercel AI SDK to create agents that can use computers.
### Step 1: Prerequisites and Setup
Install the necessary dependencies:
```bash
npm install cyberdesk @ai-sdk/anthropic ai
```
Initialize the Cyberdesk SDK client (likely in a shared module, e.g., `@/lib/cyberdeskClient.ts`):
```typescript
// src/lib/cyberdeskClient.ts
import { createCyberdeskClient } from 'cyberdesk';
const client = createCyberdeskClient({
apiKey: process.env.CYBERDESK_API_KEY || 'YOUR_API_KEY', // Use environment variable
});
export default client;
```
Ensure you have `CYBERDESK_API_KEY` set in your environment variables.
### Step 2: Implement `executeComputerAction` Utility
Create a utility function that maps AI tool parameters to the Cyberdesk SDK's `executeComputerAction` method. This function handles the various action types supported by the AI tool.
```typescript
// src/utils/computer-use.ts
import client from '@/lib/cyberdeskClient';
import type { ExecuteComputerActionParams } from "cyberdesk"
// Define the action types your AI tool might use
export type ClaudeComputerActionType0124 = /* ... (action types like 'left_click', 'type', etc.) ... */
| "left_click"
| "right_click"
// ... (include all action types from the provided code) ...
| "screenshot";
export async function executeComputerAction(
action: ClaudeComputerActionType0124,
desktopId: string,
coordinate?: { x: number; y: number },
text?: string,
duration?: number,
scroll_amount?: number,
scroll_direction?: "left" | "right" | "down" | "up",
start_coordinate?: { x: number; y: number }
): Promise<string | { type: "image"; data: string }> {
try {
let requestBody: ExecuteComputerActionParams['body'];
// Map the AI tool action to the Cyberdesk SDK's expected format
switch (action) {
case 'left_click':
requestBody = {
type: 'click_mouse',
x: coordinate?.x,
y: coordinate?.y,
button: 'left',
click_type: 'click',
num_of_clicks: 1
};
break;
// ... Map other actions (right_click, type, scroll, screenshot, etc.) ...
case 'type':
requestBody = {
type: 'type',
text: text || ''
};
break;
case 'screenshot':
requestBody = {
type: 'screenshot'
};
break;
// ... (Include all case mappings from the provided computer-use.ts code) ...
default: {
const _exhaustiveCheck: never = action;
throw new Error(`Unhandled action: ${action}`);
}
}
const clientParams: ExecuteComputerActionParams = {
path: { id: desktopId },
body: requestBody
};
// *** Use the Cyberdesk SDK client ***
const result = await client.executeComputerAction(clientParams);
// Check the raw response status embedded in the SDK result
if (result.response.status !== 200) {
let errorDetails = `Failed with status: ${result.response.status}`;
try {
// Attempt to parse error details from the response body
const errorBody = await result.response.json();
errorDetails = errorBody.message || errorBody.error || JSON.stringify(errorBody);
} catch (e) { /* Failed to parse body */ }
throw new Error(`Failed to execute computer action ${action}: ${errorDetails}`);
}
const data = result.data; // Access the parsed data from the SDK result
if (data?.base64_image) {
return {
type: "image",
data: data.base64_image
};
}
return data?.output || 'Action completed successfully';
} catch (error) {
console.error(`Error executing computer action ${action}:`, error);
throw error; // Re-throw to be handled by the AI SDK
}
}
```
*Note: The full mapping logic for all action types is omitted for brevity but should be included as shown in the `computer-use.ts` file.*
### Step 3: Implement `executeBashCommand` Utility
Create a similar utility for bash commands, calling the `executeBashAction` SDK method.
```typescript
// src/utils/bash.ts
import client from '@/lib/cyberdeskClient';
export async function executeBashCommand(
command: string,
desktopId: string
): Promise<string> {
try {
// *** Use the Cyberdesk SDK client ***
const result = await client.executeBashAction({
path: { id: desktopId },
body: { command },
});
// Check the raw response status
if (result.response.status !== 200) {
let errorDetails = `Failed with status: ${result.response.status}`;
try {
const errorBody = await result.response.json();
errorDetails = errorBody.message || errorBody.error || JSON.stringify(errorBody);
} catch (e) { /* Failed to parse body */ }
throw new Error(`Failed to execute bash command: ${errorDetails}`);
}
const data = result.data; // Access the parsed data
return data?.output || ''; // Return output or empty string
} catch (error) {
console.error(`Error executing bash command "${command}":`, error);
// Return a meaningful error message for the AI to potentially see
return 'Error executing bash command: ' + (error as Error).message;
}
}
```
### Step 4: Set Up the AI Tools and API Route
Create an API route (e.g., `/api/chat`) that uses the Vercel AI SDK (`streamText`) and defines tools that call your utility functions.
```typescript
// src/app/api/chat/route.ts
import { anthropic } from '@ai-sdk/anthropic';
import { streamText } from 'ai';
import { executeComputerAction } from '../../../utils/computer-use'; // Adjust path
import { executeBashCommand } from '../../../utils/bash'; // Adjust path
// Define result types if needed
interface ComputerActionResult { type: "image"; data: string; }
export const maxDuration = 300;
export async function POST(req: Request) {
const desktopId = req.headers.get('X-Desktop-Id');
const { messages } = await req.json();
if (!desktopId) {
return Response.json({ error: "Desktop ID is required" }, { status: 400 });
}
const lastMessage = messages[messages.length - 1];
const userContent = /* ... logic to extract text from lastMessage.content ... */ "";
// Define the computer tool using the AI SDK
const computerTool = anthropic.tools.computer_20250124({
displayWidthPx: 1024,
displayHeightPx: 768,
// The execute function calls *your* utility function, which uses the Cyberdesk SDK
execute: async ({ action, coordinate, duration, scroll_amount, scroll_direction, start_coordinate, text }) => {
const coordinateObj = coordinate ? { x: coordinate[0], y: coordinate[1] } : undefined;
const startCoordinateObj = start_coordinate ? { x: start_coordinate[0], y: start_coordinate[1] } : undefined;
// *** Call your utility function ***
const result = await executeComputerAction(
action,
desktopId,
coordinateObj,
text,
duration,
scroll_amount,
scroll_direction,
startCoordinateObj
);
// Format the result for the AI SDK tool
return (typeof result === 'string')
? { type: "text" as const, text: result }
: { type: "image" as const, data: result.data };
},
// Optional: Format the tool result content for the AI model
experimental_toToolResultContent(result: { type: "text"; text: string } | ComputerActionResult) {
return result.type === 'text'
? [{ type: 'text', text: result.text }]
: [{ type: 'image', data: result.data, mimeType: 'image/jpeg' }];
},
});
// Define the bash tool using the AI SDK
const bashTool = anthropic.tools.bash_20250124({
// The execute function calls *your* utility function
execute: async ({ command }) => {
// *** Call your utility function ***
const output = await executeBashCommand(command, desktopId);
return output; // Return the string output directly
}
});
try {
// Call the AI model with the tools
const response = streamText({
model: anthropic("claude-3-7-sonnet-20250219"),
prompt: userContent,
system: "You are an AI assistant that can control a computer...", // Your system prompt
tools: {
computer: computerTool,
bash: bashTool
},
maxSteps: 100
});
return response.toDataStreamResponse();
} catch (error) {
console.error("Error calling Anthropic:", error);
return Response.json({ error: "Failed to process request" }, { status: 500 });
}
}
```
### Step 5: Frontend Implementation
A frontend application would:
1. Create a desktop instance (perhaps via another API route that uses `cyberdesk.launchDesktop`).
2. Render a chat interface.
3. Display the desktop stream using the `stream_url`.
4. Send user messages to the `/api/chat` endpoint, including the `desktopId` in the `X-Desktop-Id` header.
5. Process the streamed response from the API, updating the chat UI.
*(Refer to the Cyberdesk Starter Assistant UI template for a full frontend example)*.
### Conclusion
By wrapping the Cyberdesk SDK methods within utility functions called by your AI tool's `execute` logic, you can seamlessly integrate robust desktop control into your AI agents. The SDK handles the direct API communication, authentication, and response parsing, simplifying your integration code.
================================================
FILE: apps/docs/mdx-components.tsx
================================================
import defaultComponents from "fumadocs-ui/mdx";
import type { MDXComponents } from "mdx/types";
export function useMDXComponents(components: MDXComponents): MDXComponents {
return {
...defaultComponents,
...components,
};
}
================================================
FILE: apps/docs/next-env.d.ts
================================================
/// <reference types="next" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
================================================
FILE: apps/docs/next.config.mjs
================================================
import createMDX from "fumadocs-mdx/config";
const withMDX = createMDX();
/** @type {import('next').NextConfig} */
const config = {
reactStrictMode: true,
};
export default withMDX(config);
================================================
FILE: apps/docs/package.json
================================================
{
"name": "docs",
"version": "0.0.0",
"private": true,
"scripts": {
"generate": "node scripts/generate-docs.mjs",
"build": "next build",
"dev": "next dev",
"start": "next start"
},
"dependencies": {
"@vercel/analytics": "^1.5.0",
"fumadocs-core": "^12.1.2",
"fumadocs-mdx": "^8.2.32",
"fumadocs-openapi": "^3.0.0",
"fumadocs-typescript": "^2.0.1",
"fumadocs-ui": "^12.1.2",
"next": "^14.2.4",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"zod": "^3.23.8"
},
"devDependencies": {
"@types/mdx": "^2.0.13",
"@types/node": "^20.11.30",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"autoprefixer": "^10.4.19",
"postcss": "^8.4.38",
"tailwindcss": "^3.4.4",
"typescript": "^5.4.5"
}
}
================================================
FILE: apps/docs/postcss.config.js
================================================
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
================================================
FILE: apps/docs/scripts/generate-docs.mjs
================================================
import * as path from "node:path";
import * as OpenAPI from "fumadocs-openapi";
import * as Typescript from "fumadocs-typescript";
void OpenAPI.generateFiles({
input: ["../../sdks/openapi.json"],
output: "./content/docs/",
name: () => "api-reference",
frontmatter: (title) => ({
toc: false,
title: `${title[0].toUpperCase()}${title.slice(1)}`,
}),
});
void Typescript.generateFiles({
input: ["./content/docs/**/*.model.mdx"],
output: (file) =>
path.resolve(
path.dirname(file),
`${path.basename(file).split(".")[0]}.mdx`
),
});
================================================
FILE: apps/docs/tailwind.config.js
================================================
import { createPreset } from 'fumadocs-ui/tailwind-plugin';
/** @type {import('tailwindcss').Config} */
export default {
content: [
'./components/**/*.{ts,tsx}',
'./app/**/*.{ts,tsx}',
'./content/**/*.{md,mdx}',
'./mdx-components.{ts,tsx}',
'./node_modules/fumadocs-ui/dist/**/*.js',
'./node_modules/fumadocs-openapi/dist/**/*.js',
],
presets: [createPreset()],
theme: {
extend: {
typography: {
DEFAULT: {
css: {
h1: {
letterSpacing: '-0.025em', // This is what tracking-tight does
fontWeight: '500', // font-medium (500) instead of bold (700)
},
h2: {
letterSpacing: '-0.025em',
fontWeight: '500',
},
h3: {
letterSpacing: '-0.025em',
fontWeight: '500',
},
h4: {
letterSpacing: '-0.025em',
fontWeight: '500',
},
h5: {
letterSpacing: '-0.025em',
fontWeight: '500',
},
h6: {
letterSpacing: '-0.025em',
fontWeight: '500',
},
},
},
},
},
},
};
================================================
FILE: apps/docs/tsconfig.json
================================================
{
"compilerOptions": {
"baseUrl": ".",
"target": "ESNext",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental
gitextract_b1wrjbeg/
├── .gitignore
├── LICENSE
├── README.md
├── apps/
│ ├── api/
│ │ ├── .dockerignore
│ │ ├── .gitignore
│ │ ├── Dockerfile
│ │ ├── README.md
│ │ ├── drizzle/
│ │ │ └── migrations/
│ │ │ ├── 0000_oval_outlaw_kid.sql
│ │ │ ├── 0001_busy_warstar.sql
│ │ │ ├── 0002_regular_doctor_faustus.sql
│ │ │ ├── 0003_superb_betty_brant.sql
│ │ │ ├── 0004_simple_komodo.sql
│ │ │ ├── 0005_mighty_hiroim.sql
│ │ │ ├── 0006_icy_black_bird.sql
│ │ │ ├── 0007_panoramic_tomorrow_man.sql
│ │ │ └── meta/
│ │ │ ├── 0000_snapshot.json
│ │ │ ├── 0001_snapshot.json
│ │ │ ├── 0002_snapshot.json
│ │ │ ├── 0003_snapshot.json
│ │ │ ├── 0004_snapshot.json
│ │ │ ├── 0005_snapshot.json
│ │ │ ├── 0006_snapshot.json
│ │ │ ├── 0007_snapshot.json
│ │ │ └── _journal.json
│ │ ├── drizzle.config.ts
│ │ ├── fly.toml
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── db/
│ │ │ │ ├── dbActions.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── schema.ts
│ │ │ ├── index.ts
│ │ │ ├── lib/
│ │ │ │ ├── cache.ts
│ │ │ │ ├── errors.ts
│ │ │ │ ├── hono.ts
│ │ │ │ ├── posthog.ts
│ │ │ │ └── ratelimit.ts
│ │ │ ├── routes/
│ │ │ │ └── desktop.ts
│ │ │ └── schema/
│ │ │ ├── desktop.ts
│ │ │ ├── errors.ts
│ │ │ └── gateway.ts
│ │ └── tsconfig.json
│ ├── docs/
│ │ ├── .gitignore
│ │ ├── .map.ts
│ │ ├── README.md
│ │ ├── app/
│ │ │ ├── api/
│ │ │ │ └── search/
│ │ │ │ └── route.ts
│ │ │ ├── docs/
│ │ │ │ ├── [[...slug]]/
│ │ │ │ │ └── page.tsx
│ │ │ │ └── layout.tsx
│ │ │ ├── global.css
│ │ │ ├── layout.config.tsx
│ │ │ ├── layout.tsx
│ │ │ ├── page.tsx
│ │ │ └── source.ts
│ │ ├── content/
│ │ │ └── docs/
│ │ │ ├── api-reference.mdx
│ │ │ ├── conceptual-guide.mdx
│ │ │ ├── index.mdx
│ │ │ ├── introduction.mdx
│ │ │ ├── meta.json
│ │ │ ├── quickstart.mdx
│ │ │ └── tutorials.mdx
│ │ ├── mdx-components.tsx
│ │ ├── next-env.d.ts
│ │ ├── next.config.mjs
│ │ ├── package.json
│ │ ├── postcss.config.js
│ │ ├── scripts/
│ │ │ └── generate-docs.mjs
│ │ ├── tailwind.config.js
│ │ └── tsconfig.json
│ └── web/
│ ├── .eslintrc.json
│ ├── .gitignore
│ ├── LICENSE.md
│ ├── README.md
│ ├── components.json
│ ├── config.ts
│ ├── middleware.ts
│ ├── next.config.mjs
│ ├── package.json
│ ├── postcss.config.js
│ ├── prettier.config.js
│ ├── radiant/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── eslint.config.mjs
│ │ ├── package.json
│ │ ├── sanity.cli.ts
│ │ ├── sanity.config.ts
│ │ ├── schemaTypes/
│ │ │ └── index.ts
│ │ ├── static/
│ │ │ └── .gitkeep
│ │ └── tsconfig.json
│ ├── sanity-typegen.json
│ ├── sanity.cli.ts
│ ├── sanity.config.ts
│ ├── src/
│ │ ├── app/
│ │ │ ├── api/
│ │ │ │ ├── playground/
│ │ │ │ │ ├── chat/
│ │ │ │ │ │ └── route.ts
│ │ │ │ │ └── kill-desktop/
│ │ │ │ │ └── route.ts
│ │ │ │ ├── stripe/
│ │ │ │ │ ├── checkout/
│ │ │ │ │ │ └── route.ts
│ │ │ │ │ ├── portal/
│ │ │ │ │ │ └── route.ts
│ │ │ │ │ └── webhook/
│ │ │ │ │ └── route.ts
│ │ │ │ └── unkey/
│ │ │ │ └── route.ts
│ │ │ ├── auth/
│ │ │ │ └── callback/
│ │ │ │ └── route.ts
│ │ │ ├── blog/
│ │ │ │ ├── [slug]/
│ │ │ │ │ └── page.tsx
│ │ │ │ ├── feed.xml/
│ │ │ │ │ └── route.ts
│ │ │ │ └── page.tsx
│ │ │ ├── company/
│ │ │ │ └── page.tsx
│ │ │ ├── dashboard/
│ │ │ │ ├── dashboard-content.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── demo/
│ │ │ │ └── page.tsx
│ │ │ ├── layout.tsx
│ │ │ ├── login/
│ │ │ │ ├── login-form.d.ts
│ │ │ │ ├── login-form.tsx
│ │ │ │ └── page.tsx
│ │ │ ├── page.tsx
│ │ │ ├── playground/
│ │ │ │ └── page.tsx
│ │ │ ├── pricing/
│ │ │ │ └── page.tsx
│ │ │ ├── privacy/
│ │ │ │ └── page.tsx
│ │ │ ├── studio/
│ │ │ │ └── [[...tool]]/
│ │ │ │ └── page.tsx
│ │ │ └── terms/
│ │ │ └── page.tsx
│ │ ├── components/
│ │ │ ├── LogoText.tsx
│ │ │ ├── PostHogProvider.tsx
│ │ │ ├── animated-number.tsx
│ │ │ ├── bento-card.tsx
│ │ │ ├── bento-section.tsx
│ │ │ ├── button.tsx
│ │ │ ├── container.tsx
│ │ │ ├── dark-bento-section.tsx
│ │ │ ├── dashboard/
│ │ │ │ ├── api-key-manager.tsx
│ │ │ │ ├── api-key-section.tsx
│ │ │ │ ├── dashboard-layout.tsx
│ │ │ │ ├── desktop-sidebar.tsx
│ │ │ │ ├── faq-section.tsx
│ │ │ │ ├── mobile-header.tsx
│ │ │ │ ├── mobile-sidebar.tsx
│ │ │ │ ├── sidebar-navigation.tsx
│ │ │ │ ├── subscription-section.tsx
│ │ │ │ └── vm-instances-manager.tsx
│ │ │ ├── demo-section.tsx
│ │ │ ├── feature-section.tsx
│ │ │ ├── footer.tsx
│ │ │ ├── gradient.tsx
│ │ │ ├── hero.tsx
│ │ │ ├── keyboard.tsx
│ │ │ ├── link.tsx
│ │ │ ├── linked-avatars.tsx
│ │ │ ├── logo-cloud.tsx
│ │ │ ├── logo-cluster.tsx
│ │ │ ├── logo-timeline.tsx
│ │ │ ├── logo.tsx
│ │ │ ├── map.tsx
│ │ │ ├── markdown-text.tsx
│ │ │ ├── navbar.tsx
│ │ │ ├── playground/
│ │ │ │ ├── chat-error.tsx
│ │ │ │ ├── icons.tsx
│ │ │ │ ├── input.tsx
│ │ │ │ ├── markdown.tsx
│ │ │ │ ├── message.tsx
│ │ │ │ ├── project-info.tsx
│ │ │ │ └── prompt-suggestions.tsx
│ │ │ ├── plus-grid.tsx
│ │ │ ├── screenshot.tsx
│ │ │ ├── shared/
│ │ │ │ └── app-logo.tsx
│ │ │ ├── stripe/
│ │ │ │ ├── checkout-button.tsx
│ │ │ │ ├── client-pricing-card.tsx
│ │ │ │ ├── client-pricing-cards.tsx
│ │ │ │ ├── payment-success.tsx
│ │ │ │ └── subscription-management.tsx
│ │ │ ├── testimonials.tsx
│ │ │ ├── text.tsx
│ │ │ ├── thread-list.tsx
│ │ │ ├── thread.tsx
│ │ │ ├── tooltip-icon-button.tsx
│ │ │ ├── ui/
│ │ │ │ ├── button.tsx
│ │ │ │ ├── input.tsx
│ │ │ │ ├── resizable.tsx
│ │ │ │ ├── sonner.tsx
│ │ │ │ └── tooltip.tsx
│ │ │ └── yc-banner.tsx
│ │ ├── sanity/
│ │ │ ├── client.ts
│ │ │ ├── env.ts
│ │ │ ├── image.ts
│ │ │ ├── queries.ts
│ │ │ ├── schema.ts
│ │ │ ├── types/
│ │ │ │ ├── author.ts
│ │ │ │ ├── block-content.ts
│ │ │ │ ├── category.ts
│ │ │ │ └── post.ts
│ │ │ └── types.ts
│ │ ├── styles/
│ │ │ └── tailwind.css
│ │ ├── types/
│ │ │ └── database.ts
│ │ └── utils/
│ │ ├── misc-utils.ts
│ │ ├── playground/
│ │ │ ├── cyberdesk-client.ts
│ │ │ ├── misc-demo-utils.ts
│ │ │ ├── server-actions.ts
│ │ │ ├── tools.ts
│ │ │ └── use-scroll-to-bottom.ts
│ │ ├── posthog/
│ │ │ └── posthog.ts
│ │ ├── stripe/
│ │ │ ├── stripe-server.ts
│ │ │ ├── stripe.ts
│ │ │ └── tiers.ts
│ │ └── supabase/
│ │ ├── client.ts
│ │ ├── middleware.ts
│ │ ├── server.ts
│ │ ├── supabaseClient.js
│ │ └── supabaseServerClient.ts
│ └── tsconfig.json
├── cyberdesk-architecture.md
├── infra/
│ ├── README.md
│ ├── kubernetes/
│ │ ├── azure-snapshot-class.yaml
│ │ ├── cdi-cr.yaml
│ │ ├── cdi-operator.yaml
│ │ ├── cluster-issuer.yaml
│ │ ├── cyberdesk-cr-v2.yaml
│ │ ├── cyberdesk-cr.yaml
│ │ ├── cyberdesk-operator.yaml
│ │ ├── default-backend.yaml
│ │ ├── gateway-deploy.yaml
│ │ ├── gateway-ingress-dev.yaml
│ │ ├── gateway-ingress-prod.yaml
│ │ ├── golden-vm-snapshot-request.yaml
│ │ ├── kubevirt-cr.yaml
│ │ ├── kubevirt-operator.yaml
│ │ ├── readme-todo.txt
│ │ ├── start-cyberdesk-operator-cr.yaml
│ │ └── warm-pool.yaml
│ └── terraform/
│ ├── .terraform.lock.hcl
│ ├── main.tf
│ └── variables.tf
├── sdks/
│ ├── openapi.json
│ ├── py-sdk/
│ │ ├── .gitignore
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── cyberdesk/
│ │ │ ├── __init__.py
│ │ │ ├── actions.py
│ │ │ ├── client.py
│ │ │ └── types.py
│ │ ├── openapi_client/
│ │ │ ├── .gitignore
│ │ │ ├── README.md
│ │ │ ├── api_reference_client/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── api/
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ └── desktop/
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── get_v1_desktop_id.py
│ │ │ │ │ ├── post_v1_desktop.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action.py
│ │ │ │ │ └── post_v1_desktop_id_stop.py
│ │ │ │ ├── client.py
│ │ │ │ ├── errors.py
│ │ │ │ ├── models/
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── get_v1_desktop_id_response_200.py
│ │ │ │ │ ├── get_v1_desktop_id_response_200_status.py
│ │ │ │ │ ├── get_v1_desktop_id_response_400.py
│ │ │ │ │ ├── get_v1_desktop_id_response_400_status.py
│ │ │ │ │ ├── get_v1_desktop_id_response_401.py
│ │ │ │ │ ├── get_v1_desktop_id_response_401_status.py
│ │ │ │ │ ├── get_v1_desktop_id_response_403.py
│ │ │ │ │ ├── get_v1_desktop_id_response_403_status.py
│ │ │ │ │ ├── get_v1_desktop_id_response_404.py
│ │ │ │ │ ├── get_v1_desktop_id_response_404_status.py
│ │ │ │ │ ├── get_v1_desktop_id_response_409.py
│ │ │ │ │ ├── get_v1_desktop_id_response_409_status.py
│ │ │ │ │ ├── get_v1_desktop_id_response_429.py
│ │ │ │ │ ├── get_v1_desktop_id_response_429_status.py
│ │ │ │ │ ├── get_v1_desktop_id_response_500.py
│ │ │ │ │ ├── get_v1_desktop_id_response_500_status.py
│ │ │ │ │ ├── get_v1_desktop_id_response_502.py
│ │ │ │ │ ├── get_v1_desktop_id_response_502_status.py
│ │ │ │ │ ├── post_v1_desktop_body.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_body.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_200.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_400.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_400_status.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_401.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_401_status.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_403.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_403_status.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_404.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_404_status.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_409.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_409_status.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_429.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_429_status.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_500.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_500_status.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_502.py
│ │ │ │ │ ├── post_v1_desktop_id_bash_action_response_502_status.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_click_mouse_action.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_click_mouse_action_button.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_click_mouse_action_click_type.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_click_mouse_action_type.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_drag_mouse_action.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_drag_mouse_action_end.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_drag_mouse_action_start.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_drag_mouse_action_type.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_get_cursor_position_action.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_get_cursor_position_action_type.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_move_mouse_action.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_move_mouse_action_type.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_press_keys_action.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_press_keys_action_key_action_type.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_press_keys_action_type.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_200.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_400.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_400_status.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_401.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_401_status.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_403.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_403_status.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_404.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_404_status.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_409.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_409_status.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_429.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_429_status.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_500.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_500_status.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_502.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_response_502_status.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_screenshot_action.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_screenshot_action_type.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_scroll_action.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_scroll_action_direction.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_scroll_action_type.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_type_text_action.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_type_text_action_type.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_wait_action.py
│ │ │ │ │ ├── post_v1_desktop_id_computer_action_wait_action_type.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_200.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_200_status.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_400.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_400_status.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_401.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_401_status.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_403.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_403_status.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_404.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_404_status.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_409.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_409_status.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_429.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_429_status.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_500.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_500_status.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_502.py
│ │ │ │ │ ├── post_v1_desktop_id_stop_response_502_status.py
│ │ │ │ │ ├── post_v1_desktop_response_200.py
│ │ │ │ │ ├── post_v1_desktop_response_200_status.py
│ │ │ │ │ ├── post_v1_desktop_response_400.py
│ │ │ │ │ ├── post_v1_desktop_response_400_status.py
│ │ │ │ │ ├── post_v1_desktop_response_401.py
│ │ │ │ │ ├── post_v1_desktop_response_401_status.py
│ │ │ │ │ ├── post_v1_desktop_response_403.py
│ │ │ │ │ ├── post_v1_desktop_response_403_status.py
│ │ │ │ │ ├── post_v1_desktop_response_404.py
│ │ │ │ │ ├── post_v1_desktop_response_404_status.py
│ │ │ │ │ ├── post_v1_desktop_response_409.py
│ │ │ │ │ ├── post_v1_desktop_response_409_status.py
│ │ │ │ │ ├── post_v1_desktop_response_429.py
│ │ │ │ │ ├── post_v1_desktop_response_429_status.py
│ │ │ │ │ ├── post_v1_desktop_response_500.py
│ │ │ │ │ ├── post_v1_desktop_response_500_status.py
│ │ │ │ │ ├── post_v1_desktop_response_502.py
│ │ │ │ │ └── post_v1_desktop_response_502_status.py
│ │ │ │ ├── py.typed
│ │ │ │ └── types.py
│ │ │ └── pyproject.toml
│ │ ├── pyproject.toml
│ │ └── scripts/
│ │ └── generate.py
│ ├── sandbox/
│ │ └── py-sdk/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ └── test_sdk.py
│ └── ts-sdk/
│ ├── .gitignore
│ ├── LICENSE
│ ├── README.md
│ ├── openapi-ts.config.ts
│ ├── package.json
│ ├── src/
│ │ ├── client/
│ │ │ ├── client.gen.ts
│ │ │ ├── index.ts
│ │ │ ├── sdk.gen.ts
│ │ │ └── types.gen.ts
│ │ └── index.ts
│ └── tsconfig.json
├── self-host.md
└── services/
├── cyberdesk-operator/
│ ├── .gitignore
│ ├── Dockerfile
│ ├── README.md
│ ├── checklist.md
│ ├── docs/
│ │ └── troubleshooting.md
│ ├── handlers/
│ │ └── controller.py
│ ├── requirements.txt
│ └── tests/
│ ├── README.md
│ ├── test-cyberdesk-cr.yaml
│ ├── test-start-operator-cr.yaml
│ ├── test-start-operator-crd.yaml
│ └── test.py
└── gateway/
├── Dockerfile
├── README.md
├── main.py
├── noVNC/
│ ├── .github/
│ │ ├── ISSUE_TEMPLATE/
│ │ │ ├── bug_report.md
│ │ │ ├── config.yml
│ │ │ └── feature_request.md
│ │ └── workflows/
│ │ ├── deploy.yml
│ │ ├── lint.yml
│ │ ├── test.yml
│ │ └── translate.yml
│ ├── .gitignore
│ ├── .gitmodules
│ ├── AUTHORS
│ ├── LICENSE.txt
│ ├── README.md
│ ├── app/
│ │ ├── error-handler.js
│ │ ├── images/
│ │ │ └── icons/
│ │ │ └── Makefile
│ │ ├── locale/
│ │ │ ├── README
│ │ │ ├── cs.json
│ │ │ ├── de.json
│ │ │ ├── el.json
│ │ │ ├── es.json
│ │ │ ├── fr.json
│ │ │ ├── it.json
│ │ │ ├── ja.json
│ │ │ ├── ko.json
│ │ │ ├── nl.json
│ │ │ ├── pl.json
│ │ │ ├── pt_BR.json
│ │ │ ├── ru.json
│ │ │ ├── sv.json
│ │ │ ├── tr.json
│ │ │ ├── zh_CN.json
│ │ │ └── zh_TW.json
│ │ ├── localization.js
│ │ ├── sounds/
│ │ │ ├── CREDITS
│ │ │ └── bell.oga
│ │ ├── styles/
│ │ │ ├── base.css
│ │ │ ├── constants.css
│ │ │ └── input.css
│ │ ├── ui.js
│ │ └── webutil.js
│ ├── core/
│ │ ├── base64.js
│ │ ├── crypto/
│ │ │ ├── aes.js
│ │ │ ├── bigint.js
│ │ │ ├── crypto.js
│ │ │ ├── des.js
│ │ │ ├── dh.js
│ │ │ ├── md5.js
│ │ │ └── rsa.js
│ │ ├── decoders/
│ │ │ ├── copyrect.js
│ │ │ ├── h264.js
│ │ │ ├── hextile.js
│ │ │ ├── jpeg.js
│ │ │ ├── raw.js
│ │ │ ├── rre.js
│ │ │ ├── tight.js
│ │ │ ├── tightpng.js
│ │ │ ├── zlib.js
│ │ │ └── zrle.js
│ │ ├── deflator.js
│ │ ├── display.js
│ │ ├── encodings.js
│ │ ├── inflator.js
│ │ ├── input/
│ │ │ ├── domkeytable.js
│ │ │ ├── fixedkeys.js
│ │ │ ├── gesturehandler.js
│ │ │ ├── keyboard.js
│ │ │ ├── keysym.js
│ │ │ ├── keysymdef.js
│ │ │ ├── util.js
│ │ │ ├── vkeys.js
│ │ │ └── xtscancodes.js
│ │ ├── ra2.js
│ │ ├── rfb.js
│ │ ├── util/
│ │ │ ├── browser.js
│ │ │ ├── cursor.js
│ │ │ ├── element.js
│ │ │ ├── events.js
│ │ │ ├── eventtarget.js
│ │ │ ├── int.js
│ │ │ ├── logging.js
│ │ │ └── strings.js
│ │ └── websock.js
│ ├── defaults.json
│ ├── docs/
│ │ ├── API-internal.md
│ │ ├── API.md
│ │ ├── EMBEDDING.md
│ │ ├── LIBRARY.md
│ │ ├── LICENSE.BSD-2-Clause
│ │ ├── LICENSE.BSD-3-Clause
│ │ ├── LICENSE.MPL-2.0
│ │ ├── LICENSE.OFL-1.1
│ │ ├── flash_policy.txt
│ │ ├── links
│ │ ├── notes
│ │ ├── novnc_proxy.1
│ │ └── rfb_notes
│ ├── eslint.config.mjs
│ ├── karma.conf.js
│ ├── mandatory.json
│ ├── package.json
│ ├── po/
│ │ ├── Makefile
│ │ ├── cs.po
│ │ ├── de.po
│ │ ├── el.po
│ │ ├── es.po
│ │ ├── fr.po
│ │ ├── it.po
│ │ ├── ja.po
│ │ ├── ko.po
│ │ ├── nl.po
│ │ ├── noVNC.pot
│ │ ├── pl.po
│ │ ├── po2js
│ │ ├── pt_BR.po
│ │ ├── ru.po
│ │ ├── sv.po
│ │ ├── tr.po
│ │ ├── xgettext-html
│ │ ├── zh_CN.po
│ │ └── zh_TW.po
│ ├── snap/
│ │ ├── hooks/
│ │ │ └── configure
│ │ ├── local/
│ │ │ └── svc_wrapper.sh
│ │ └── snapcraft.yaml
│ ├── tests/
│ │ ├── assertions.js
│ │ ├── fake.websocket.js
│ │ ├── playback-ui.js
│ │ ├── playback.js
│ │ ├── test.base64.js
│ │ ├── test.browser.js
│ │ ├── test.copyrect.js
│ │ ├── test.deflator.js
│ │ ├── test.display.js
│ │ ├── test.gesturehandler.js
│ │ ├── test.h264.js
│ │ ├── test.helper.js
│ │ ├── test.hextile.js
│ │ ├── test.inflator.js
│ │ ├── test.int.js
│ │ ├── test.jpeg.js
│ │ ├── test.keyboard.js
│ │ ├── test.localization.js
│ │ ├── test.raw.js
│ │ ├── test.rfb.js
│ │ ├── test.rre.js
│ │ ├── test.tight.js
│ │ ├── test.tightpng.js
│ │ ├── test.util.js
│ │ ├── test.websock.js
│ │ ├── test.webutil.js
│ │ ├── test.zlib.js
│ │ ├── test.zrle.js
│ │ └── vnc_playback.html
│ ├── utils/
│ │ ├── README.md
│ │ ├── b64-to-binary.pl
│ │ ├── convert.js
│ │ ├── genkeysymdef.js
│ │ ├── novnc_proxy
│ │ ├── u2x11
│ │ └── validate
│ ├── vendor/
│ │ └── pako/
│ │ ├── LICENSE
│ │ ├── README.md
│ │ └── lib/
│ │ ├── utils/
│ │ │ └── common.js
│ │ └── zlib/
│ │ ├── adler32.js
│ │ ├── constants.js
│ │ ├── crc32.js
│ │ ├── deflate.js
│ │ ├── gzheader.js
│ │ ├── inffast.js
│ │ ├── inflate.js
│ │ ├── inftrees.js
│ │ ├── messages.js
│ │ ├── trees.js
│ │ └── zstream.js
│ ├── vnc.html
│ └── vnc_lite.html
└── requirements.txt
SYMBOL INDEX (1907 symbols across 319 files)
FILE: apps/api/drizzle/migrations/0000_oval_outlaw_kid.sql
type "desktop_instances" (line 1) | CREATE TABLE IF NOT EXISTS "desktop_instances" (
FILE: apps/api/drizzle/migrations/0002_regular_doctor_faustus.sql
type "profiles" (line 1) | CREATE TABLE IF NOT EXISTS "profiles" (
FILE: apps/api/drizzle/migrations/0006_icy_black_bird.sql
type "cyberdesk_instances" (line 7) | CREATE TABLE IF NOT EXISTS "cyberdesk_instances" (
FILE: apps/api/src/db/dbActions.ts
function addDbInstance (line 14) | async function addDbInstance(
function updateDbInstanceStatus (line 45) | async function updateDbInstanceStatus(
function getDbInstanceDetails (line 83) | async function getDbInstanceDetails(
FILE: apps/api/src/db/index.ts
function connectDatabase (line 11) | function connectDatabase(env: { SUPABASE_CONNECTION_STRING: string }): P...
FILE: apps/api/src/db/schema.ts
type InstanceStatus (line 27) | enum InstanceStatus {
FILE: apps/api/src/lib/cache.ts
type CacheNamespaces (line 7) | type CacheNamespaces = {
type Cache (line 11) | type Cache = C<CacheNamespaces>
function initCache (line 15) | function initCache(): Middleware {
FILE: apps/api/src/lib/errors.ts
class ApiError (line 7) | class ApiError extends Error {
method constructor (line 10) | constructor(message: string, statusCode: number) {
class BadRequestError (line 19) | class BadRequestError extends ApiError {
method constructor (line 20) | constructor(message = 'Bad Request') {
class UnauthorizedError (line 25) | class UnauthorizedError extends ApiError {
method constructor (line 26) | constructor(message = 'Unauthorized') {
class NotFoundError (line 31) | class NotFoundError extends ApiError {
method constructor (line 32) | constructor(message = 'Not Found') {
class ConflictError (line 37) | class ConflictError extends ApiError {
method constructor (line 38) | constructor(message = 'Conflict') {
class GatewayError (line 43) | class GatewayError extends ApiError {
method constructor (line 44) | constructor(message = 'Bad Gateway') {
class InternalServerError (line 49) | class InternalServerError extends ApiError {
method constructor (line 50) | constructor(message = 'Internal Server Error') {
class ActionExecutionError (line 57) | class ActionExecutionError extends Error {
method constructor (line 60) | constructor(message: string, details?: string) {
FILE: apps/api/src/lib/hono.ts
type HonoEnv (line 9) | type HonoEnv = {
function parseZodErrorMessage (line 26) | function parseZodErrorMessage(err: z.ZodError): string {
function handleZodError (line 38) | function handleZodError(
function newApp (line 60) | function newApp() {
type App (line 99) | type App = ReturnType<typeof newApp>;
type Context (line 100) | type Context = GenericContext<HonoEnv>;
type Middleware (line 101) | type Middleware = MiddlewareHandler<HonoEnv>;
FILE: apps/api/src/lib/posthog.ts
constant POSTHOG_API_KEY (line 7) | const POSTHOG_API_KEY = process.env.POSTHOG_API_KEY;
constant POSTHOG_HOST (line 13) | const POSTHOG_HOST = process.env.POSTHOG_HOST || 'https://us.i.posthog.c...
FILE: apps/api/src/lib/ratelimit.ts
function initRatelimiter (line 5) | function initRatelimiter(): Middleware {
FILE: apps/api/src/routes/desktop.ts
type EnvVars (line 39) | type EnvVars = {
type ComputerAction (line 49) | type ComputerAction = z.infer<typeof ComputerActionSchema>;
type CreateDesktopParams (line 51) | type CreateDesktopParams = z.infer<typeof CreateDesktopParamsSchema>;
type BashAction (line 52) | type BashAction = z.infer<typeof BashActionSchema>;
function captureApiEvent (line 78) | async function captureApiEvent(
function executeComputerAction (line 221) | async function executeComputerAction(
function executeBashCommand (line 359) | async function executeBashCommand(
FILE: apps/docs/app/docs/[[...slug]]/page.tsx
function Page (line 6) | async function Page({
function generateStaticParams (line 29) | async function generateStaticParams() {
function generateMetadata (line 35) | function generateMetadata({ params }: { params: { slug?: string[] } }) {
FILE: apps/docs/app/docs/layout.tsx
function Layout (line 7) | function Layout({ children }: { children: ReactNode }) {
FILE: apps/docs/app/layout.tsx
function Layout (line 12) | function Layout({ children }: { children: ReactNode }) {
FILE: apps/docs/app/page.tsx
function HomePage (line 3) | function HomePage() {
FILE: apps/docs/mdx-components.tsx
function useMDXComponents (line 4) | function useMDXComponents(components: MDXComponents): MDXComponents {
FILE: apps/web/config.ts
constant CONFIG (line 1) | const CONFIG = {
FILE: apps/web/middleware.ts
function middleware (line 4) | async function middleware(request: NextRequest) {
FILE: apps/web/next.config.mjs
method rewrites (line 4) | async rewrites() {
FILE: apps/web/src/app/api/playground/chat/route.ts
function POST (line 10) | async function POST(req: Request) {
FILE: apps/web/src/app/api/playground/kill-desktop/route.ts
function handleKillDesktop (line 4) | async function handleKillDesktop(request: Request) {
function POST (line 30) | async function POST(request: Request) {
FILE: apps/web/src/app/api/stripe/checkout/route.ts
function POST (line 4) | async function POST(req: NextRequest) {
FILE: apps/web/src/app/api/stripe/portal/route.ts
function POST (line 4) | async function POST(req: NextRequest) {
FILE: apps/web/src/app/api/stripe/webhook/route.ts
type SubscriptionStatus (line 8) | type SubscriptionStatus = Stripe.Subscription.Status;
function POST (line 13) | async function POST(req: NextRequest) {
FILE: apps/web/src/app/api/unkey/route.ts
constant UNKEY_API_URL (line 5) | const UNKEY_API_URL = 'https://api.unkey.dev/v1';
constant UNKEY_API_ID (line 6) | const UNKEY_API_ID = process.env.UNKEY_API_ID;
constant UNKEY_ROOT_KEY (line 7) | const UNKEY_ROOT_KEY = process.env.UNKEY_ROOT_KEY;
function GET (line 13) | async function GET(request: Request) {
function POST (line 98) | async function POST(request: Request) {
FILE: apps/web/src/app/auth/callback/route.ts
function GET (line 5) | async function GET(request: NextRequest) {
FILE: apps/web/src/app/blog/[slug]/page.tsx
function generateMetadata (line 16) | async function generateMetadata({
function BlogPost (line 26) | async function BlogPost({
FILE: apps/web/src/app/blog/feed.xml/route.ts
function GET (line 6) | async function GET(req: Request) {
FILE: apps/web/src/app/blog/page.tsx
function FeaturedPosts (line 36) | async function FeaturedPosts() {
function Categories (line 96) | async function Categories({ selected }: { selected?: string }) {
function Posts (line 147) | async function Posts({ page, category }: { page: number; category?: stri...
function Pagination (line 208) | async function Pagination({
function Blog (line 270) | async function Blog({
FILE: apps/web/src/app/company/page.tsx
function Header (line 16) | function Header() {
function Person (line 110) | function Person({
function Team (line 130) | function Team() {
function Investors (line 233) | function Investors() {
function Testimonial (line 320) | function Testimonial() {
function Careers (line 352) | function Careers() {
function Company (line 459) | function Company() {
FILE: apps/web/src/app/dashboard/dashboard-content.tsx
type DashboardContentProps (line 13) | interface DashboardContentProps {
function DashboardContent (line 19) | function DashboardContent({ userEmail, userId, profile }: DashboardConte...
FILE: apps/web/src/app/dashboard/page.tsx
function Dashboard (line 8) | async function Dashboard() {
FILE: apps/web/src/app/demo/page.tsx
function PlaygroundDemo (line 13) | function PlaygroundDemo() {
FILE: apps/web/src/app/layout.tsx
function RootLayout (line 15) | function RootLayout({
FILE: apps/web/src/app/login/login-form.tsx
function LoginForm (line 9) | function LoginForm() {
FILE: apps/web/src/app/login/page.tsx
function Login (line 10) | function Login() {
FILE: apps/web/src/app/page.tsx
function Home (line 12) | function Home() {
FILE: apps/web/src/app/playground/page.tsx
function pollForDesktopURL (line 23) | async function pollForDesktopURL(sandboxId: string | null | undefined) {
function Playground (line 42) | function Playground() {
FILE: apps/web/src/app/pricing/page.tsx
function Header (line 25) | function Header() {
function PricingTable (line 42) | function PricingTable({
function FeatureItem (line 208) | function FeatureItem({
function PlusIcon (line 229) | function PlusIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
function Testimonial (line 237) | function Testimonial() {
function Pricing (line 279) | async function Pricing({
FILE: apps/web/src/app/privacy/page.tsx
function Header (line 14) | function Header() {
function Privacy (line 25) | function Privacy() {
FILE: apps/web/src/app/studio/[[...tool]]/page.tsx
function StudioPage (line 17) | function StudioPage() {
FILE: apps/web/src/app/terms/page.tsx
function Header (line 14) | function Header() {
function Terms (line 25) | function Terms() {
FILE: apps/web/src/components/LogoText.tsx
type LogoTextProps (line 4) | interface LogoTextProps extends React.HTMLAttributes<HTMLSpanElement> {}
FILE: apps/web/src/components/PostHogProvider.tsx
function PostHogProvider (line 8) | function PostHogProvider({ children }: { children: React.ReactNode }) {
function PostHogPageView (line 26) | function PostHogPageView() {
function SuspendedPostHogPageView (line 45) | function SuspendedPostHogPageView() {
FILE: apps/web/src/components/animated-number.tsx
function AnimatedNumber (line 12) | function AnimatedNumber({
FILE: apps/web/src/components/bento-card.tsx
function BentoCard (line 7) | function BentoCard({
FILE: apps/web/src/components/bento-section.tsx
function BentoSection (line 8) | function BentoSection() {
FILE: apps/web/src/components/button.tsx
type ButtonProps (line 27) | type ButtonProps = {
function Button (line 34) | function Button({
FILE: apps/web/src/components/container.tsx
function Container (line 3) | function Container({
FILE: apps/web/src/components/dark-bento-section.tsx
function DarkBentoSection (line 7) | function DarkBentoSection() {
FILE: apps/web/src/components/dashboard/api-key-manager.tsx
type ApiKey (line 8) | interface ApiKey {
function ApiKeyManager (line 14) | function ApiKeyManager() {
FILE: apps/web/src/components/dashboard/api-key-section.tsx
type ApiKeyData (line 8) | interface ApiKeyData {
function ApiKeySection (line 13) | function ApiKeySection() {
FILE: apps/web/src/components/dashboard/dashboard-layout.tsx
type DashboardLayoutProps (line 8) | interface DashboardLayoutProps {
function DashboardLayout (line 13) | function DashboardLayout({ children, userEmail }: DashboardLayoutProps) {
FILE: apps/web/src/components/dashboard/desktop-sidebar.tsx
type DesktopSidebarProps (line 7) | interface DesktopSidebarProps {
function DesktopSidebar (line 11) | function DesktopSidebar({ userEmail }: DesktopSidebarProps) {
FILE: apps/web/src/components/dashboard/faq-section.tsx
function FAQSection (line 42) | function FAQSection() {
FILE: apps/web/src/components/dashboard/mobile-header.tsx
type MobileHeaderProps (line 5) | interface MobileHeaderProps {
function MobileHeader (line 9) | function MobileHeader({ setSidebarOpen }: MobileHeaderProps) {
FILE: apps/web/src/components/dashboard/mobile-sidebar.tsx
type MobileSidebarProps (line 8) | interface MobileSidebarProps {
function MobileSidebar (line 13) | function MobileSidebar({ sidebarOpen, setSidebarOpen }: MobileSidebarPro...
FILE: apps/web/src/components/dashboard/sidebar-navigation.tsx
type NavItem (line 10) | interface NavItem {
function classNames (line 34) | function classNames(...classes: string[]) {
FILE: apps/web/src/components/dashboard/subscription-section.tsx
type SubscriptionSectionProps (line 9) | interface SubscriptionSectionProps {
function SubscriptionSection (line 15) | function SubscriptionSection({ userEmail, userId, profile }: Subscriptio...
FILE: apps/web/src/components/dashboard/vm-instances-manager.tsx
function VMInstancesManager (line 8) | function VMInstancesManager() {
FILE: apps/web/src/components/demo-section.tsx
constant DESKTOP_TIMEOUT_MS (line 9) | const DESKTOP_TIMEOUT_MS = 600000
type DemoSectionProps (line 12) | interface DemoSectionProps {
type DesktopLaunchResponse (line 19) | interface DesktopLaunchResponse {
function DemoSection (line 25) | function DemoSection({
FILE: apps/web/src/components/feature-section.tsx
function FeatureSection (line 5) | function FeatureSection() {
FILE: apps/web/src/components/footer.tsx
function CallToAction (line 13) | function CallToAction() {
function SitemapHeading (line 36) | function SitemapHeading({ children }: { children: React.ReactNode }) {
function SitemapLinks (line 40) | function SitemapLinks({ children }: { children: React.ReactNode }) {
function SitemapLink (line 44) | function SitemapLink(props: React.ComponentPropsWithoutRef<typeof Link>) {
function Sitemap (line 55) | function Sitemap() {
function SocialIconX (line 104) | function SocialIconX(props: React.ComponentPropsWithoutRef<'svg'>) {
function SocialIconFacebook (line 112) | function SocialIconFacebook(props: React.ComponentPropsWithoutRef<'svg'>) {
function SocialIconLinkedIn (line 124) | function SocialIconLinkedIn(props: React.ComponentPropsWithoutRef<'svg'>) {
function Copyright (line 134) | function Copyright() {
function Footer (line 143) | function Footer() {
FILE: apps/web/src/components/gradient.tsx
function Gradient (line 3) | function Gradient({
function GradientBackground (line 18) | function GradientBackground({ children }: { children?: React.ReactNode }) {
FILE: apps/web/src/components/hero.tsx
function Hero (line 13) | function Hero() {
FILE: apps/web/src/components/keyboard.tsx
function Row (line 11) | function Row(props: { children: React.ReactNode }) {
function Key (line 15) | function Key({
function KeyGroup (line 69) | function KeyGroup(props: { children: React.ReactNode }) {
function EscapeKey (line 78) | function EscapeKey() {
function F1Key (line 88) | function F1Key() {
function F2Key (line 101) | function F2Key() {
function F3Key (line 114) | function F3Key() {
function F4Key (line 127) | function F4Key() {
function F5Key (line 140) | function F5Key() {
function F6Key (line 153) | function F6Key() {
function F7Key (line 166) | function F7Key() {
function F8Key (line 179) | function F8Key() {
function F9Key (line 192) | function F9Key() {
function F10Key (line 205) | function F10Key() {
function F11Key (line 218) | function F11Key() {
function F12Key (line 231) | function F12Key() {
function LockKey (line 244) | function LockKey() {
function BacktickKey (line 254) | function BacktickKey() {
function OneKey (line 267) | function OneKey() {
function TwoKey (line 280) | function TwoKey() {
function ThreeKey (line 293) | function ThreeKey() {
function FourKey (line 306) | function FourKey() {
function FiveKey (line 319) | function FiveKey() {
function SixKey (line 332) | function SixKey() {
function SevenKey (line 345) | function SevenKey() {
function EightKey (line 358) | function EightKey() {
function NineKey (line 371) | function NineKey() {
function ZeroKey (line 384) | function ZeroKey() {
function DashKey (line 397) | function DashKey() {
function EqualsKey (line 410) | function EqualsKey() {
function DeleteKey (line 423) | function DeleteKey() {
function TabKey (line 433) | function TabKey() {
function QKey (line 443) | function QKey() {
function WKey (line 453) | function WKey() {
function EKey (line 463) | function EKey() {
function RKey (line 473) | function RKey() {
function TKey (line 483) | function TKey() {
function YKey (line 493) | function YKey() {
function UKey (line 503) | function UKey() {
function IKey (line 513) | function IKey() {
function OKey (line 523) | function OKey() {
function PKey (line 533) | function PKey() {
function LeftSquareBracketKey (line 543) | function LeftSquareBracketKey() {
function RightSquareBracketKey (line 556) | function RightSquareBracketKey() {
function BackSlashKey (line 569) | function BackSlashKey() {
function CapsLockKey (line 582) | function CapsLockKey() {
function AKey (line 595) | function AKey() {
function SKey (line 605) | function SKey() {
function DKey (line 615) | function DKey() {
function FKey (line 625) | function FKey() {
function GKey (line 635) | function GKey() {
function HKey (line 645) | function HKey() {
function JKey (line 655) | function JKey() {
function KKey (line 665) | function KKey() {
function LKey (line 675) | function LKey() {
function SemicolonKey (line 685) | function SemicolonKey() {
function SingleQuoteKey (line 698) | function SingleQuoteKey() {
function ReturnKey (line 711) | function ReturnKey() {
function ShiftKey (line 721) | function ShiftKey({ position }: { position: 'Left' | 'Right' }) {
function ZKey (line 734) | function ZKey() {
function XKey (line 744) | function XKey() {
function CKey (line 754) | function CKey() {
function VKey (line 764) | function VKey() {
function BKey (line 774) | function BKey() {
function NKey (line 784) | function NKey() {
function MKey (line 794) | function MKey() {
function CommaKey (line 804) | function CommaKey() {
function PeriodKey (line 817) | function PeriodKey() {
function ForwardSlashKey (line 830) | function ForwardSlashKey() {
function FunctionKey (line 843) | function FunctionKey() {
function ControlKey (line 856) | function ControlKey() {
function OptionKey (line 869) | function OptionKey({ position }: { position: 'Left' | 'Right' }) {
function CommandKey (line 888) | function CommandKey({ position }: { position: 'Left' | 'Right' }) {
function SpaceKey (line 907) | function SpaceKey() {
function LeftKey (line 911) | function LeftKey() {
function UpKey (line 921) | function UpKey() {
function DownKey (line 931) | function DownKey() {
function RightKey (line 941) | function RightKey() {
function Keyboard (line 951) | function Keyboard({ highlighted = [] }: { highlighted?: string[] }) {
FILE: apps/web/src/components/linked-avatars.tsx
function Rings (line 13) | function Rings() {
function Checkmark (line 47) | function Checkmark() {
function Photos (line 66) | function Photos() {
function LinkedAvatars (line 85) | function LinkedAvatars() {
FILE: apps/web/src/components/logo-cloud.tsx
function LogoCloud (line 3) | function LogoCloud({
FILE: apps/web/src/components/logo-cluster.tsx
function Circle (line 7) | function Circle({
function Circles (line 42) | function Circles() {
function MainLogo (line 54) | function MainLogo() {
function Logo (line 62) | function Logo({
function LogoCluster (line 98) | function LogoCluster() {
FILE: apps/web/src/components/logo-timeline.tsx
function Row (line 4) | function Row({ children }: { children: React.ReactNode }) {
function Logo (line 14) | function Logo({
function LogoTimeline (line 38) | function LogoTimeline() {
FILE: apps/web/src/components/logo.tsx
function Logo (line 6) | function Logo({ className }: { className?: string }) {
function Mark (line 88) | function Mark({ className }: { className?: string }) {
FILE: apps/web/src/components/map.tsx
function Marker (line 5) | function Marker({
function Map (line 45) | function Map() {
FILE: apps/web/src/components/navbar.tsx
type NavLink (line 21) | interface NavLink {
function GitHubIcon (line 35) | function GitHubIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
function DesktopNav (line 43) | function DesktopNav() {
function MobileNavButton (line 106) | function MobileNavButton() {
function MobileNav (line 117) | function MobileNav({ githubIcon }: { githubIcon?: React.ReactNode }) {
function Navbar (line 198) | function Navbar({ banner }: { banner?: React.ReactNode }) {
FILE: apps/web/src/components/playground/chat-error.tsx
function ChatError (line 4) | function ChatError({ error, onRetry }: { error: unknown, onRetry: () => ...
FILE: apps/web/src/components/playground/input.tsx
type InputProps (line 4) | interface InputProps {
FILE: apps/web/src/components/plus-grid.tsx
function PlusGrid (line 3) | function PlusGrid({
function PlusGridRow (line 13) | function PlusGridRow({
function PlusGridItem (line 41) | function PlusGridItem({
function PlusGridIcon (line 68) | function PlusGridIcon({
FILE: apps/web/src/components/screenshot.tsx
function Screenshot (line 3) | function Screenshot({
FILE: apps/web/src/components/shared/app-logo.tsx
type AppLogoProps (line 6) | interface AppLogoProps {
function AppLogo (line 12) | function AppLogo({
FILE: apps/web/src/components/stripe/checkout-button.tsx
type CheckoutButtonProps (line 9) | interface CheckoutButtonProps {
function CheckoutButton (line 18) | function CheckoutButton({
FILE: apps/web/src/components/stripe/client-pricing-card.tsx
function FeatureItem (line 11) | function FeatureItem({
function PlusIcon (line 33) | function PlusIcon(props: React.ComponentPropsWithoutRef<'svg'>) {
type Tier (line 42) | interface Tier {
function PricingCard (line 52) | function PricingCard({
FILE: apps/web/src/components/stripe/client-pricing-cards.tsx
type Tier (line 14) | interface Tier {
function ClientPricingCards (line 24) | function ClientPricingCards({
FILE: apps/web/src/components/stripe/payment-success.tsx
type PaymentSuccessProps (line 5) | interface PaymentSuccessProps {
function PaymentSuccess (line 9) | function PaymentSuccess({ className }: PaymentSuccessProps) {
FILE: apps/web/src/components/stripe/subscription-management.tsx
type SubscriptionManagementProps (line 5) | interface SubscriptionManagementProps {
function SubscriptionManagement (line 10) | function SubscriptionManagement({
FILE: apps/web/src/components/testimonials.tsx
function TestimonialCard (line 64) | function TestimonialCard({
function CallToAction (line 155) | function CallToAction() {
function Testimonials (line 175) | function Testimonials() {
FILE: apps/web/src/components/text.tsx
type HeadingProps (line 3) | type HeadingProps = {
function Heading (line 10) | function Heading({
function Subheading (line 28) | function Subheading({
function Lead (line 46) | function Lead({
FILE: apps/web/src/components/tooltip-icon-button.tsx
type TooltipIconButtonProps (line 14) | type TooltipIconButtonProps = ComponentPropsWithoutRef<typeof Button> & {
FILE: apps/web/src/components/ui/button.tsx
function Button (line 39) | function Button({
FILE: apps/web/src/components/ui/input.tsx
function Input (line 5) | function Input({ className, type, ...props }: React.ComponentProps<"inpu...
FILE: apps/web/src/components/ui/resizable.tsx
function ResizablePanelGroup (line 9) | function ResizablePanelGroup({
function ResizablePanel (line 25) | function ResizablePanel({
function ResizableHandle (line 31) | function ResizableHandle({
FILE: apps/web/src/components/ui/tooltip.tsx
function TooltipProvider (line 8) | function TooltipProvider({
function Tooltip (line 21) | function Tooltip({
function TooltipTrigger (line 31) | function TooltipTrigger({
function TooltipContent (line 37) | function TooltipContent({
FILE: apps/web/src/components/yc-banner.tsx
function YCBanner (line 3) | function YCBanner() {
FILE: apps/web/src/sanity/client.ts
function sanityFetch (line 13) | async function sanityFetch<const QueryString extends string>({
FILE: apps/web/src/sanity/env.ts
function assertValue (line 14) | function assertValue<T>(v: T | undefined, errorMessage: string): T {
FILE: apps/web/src/sanity/image.ts
function image (line 7) | function image(source: SanityImageSource) {
FILE: apps/web/src/sanity/queries.ts
constant TOTAL_POSTS_QUERY (line 4) | const TOTAL_POSTS_QUERY = defineQuery(/* groq */ `count(*[
function getPostsCount (line 11) | async function getPostsCount(category?: string) {
constant POSTS_QUERY (line 18) | const POSTS_QUERY = defineQuery(/* groq */ `*[
function getPosts (line 34) | async function getPosts(
constant FEATURED_POSTS_QUERY (line 49) | const FEATURED_POSTS_QUERY = defineQuery(/* groq */ `*[
function getFeaturedPosts (line 65) | async function getFeaturedPosts(quantity: number) {
constant FEED_POSTS_QUERY (line 72) | const FEED_POSTS_QUERY = defineQuery(/* groq */ `*[
function getPostsForFeed (line 86) | async function getPostsForFeed() {
constant POST_QUERY (line 92) | const POST_QUERY = defineQuery(/* groq */ `*[
function getPost (line 112) | async function getPost(slug: string) {
constant CATEGORIES_QUERY (line 119) | const CATEGORIES_QUERY = defineQuery(/* groq */ `*[
function getCategories (line 127) | async function getCategories() {
FILE: apps/web/src/sanity/types.ts
type SanityImagePaletteSwatch (line 16) | type SanityImagePaletteSwatch = {
type SanityImagePalette (line 24) | type SanityImagePalette = {
type SanityImageDimensions (line 35) | type SanityImageDimensions = {
type SanityFileAsset (line 42) | type SanityFileAsset = {
type Geopoint (line 64) | type Geopoint = {
type Post (line 71) | type Post = {
type Author (line 142) | type Author = {
type Category (line 163) | type Category = {
type Slug (line 173) | type Slug = {
type BlockContent (line 179) | type BlockContent = Array<
type SanityImageCrop (line 213) | type SanityImageCrop = {
type SanityImageHotspot (line 221) | type SanityImageHotspot = {
type SanityImageAsset (line 229) | type SanityImageAsset = {
type SanityAssetSourceData (line 252) | type SanityAssetSourceData = {
type SanityImageMetadata (line 259) | type SanityImageMetadata = {
type AllSanitySchemaTypes (line 270) | type AllSanitySchemaTypes =
type TOTAL_POSTS_QUERYResult (line 290) | type TOTAL_POSTS_QUERYResult = number
type POSTS_QUERYResult (line 293) | type POSTS_QUERYResult = Array<{
type FEATURED_POSTS_QUERYResult (line 315) | type FEATURED_POSTS_QUERYResult = Array<{
type FEED_POSTS_QUERYResult (line 349) | type FEED_POSTS_QUERYResult = Array<{
type POST_QUERYResult (line 372) | type POST_QUERYResult = {
type CATEGORIES_QUERYResult (line 442) | type CATEGORIES_QUERYResult = Array<{
type SanityQueries (line 450) | interface SanityQueries {
FILE: apps/web/src/sanity/types/post.ts
method prepare (line 96) | prepare({ title, author, media, isFeatured }) {
FILE: apps/web/src/types/database.ts
type Profile (line 1) | interface Profile {
type CyberdeskInstance (line 15) | interface CyberdeskInstance {
FILE: apps/web/src/utils/misc-utils.ts
function cn (line 4) | function cn(...inputs: ClassValue[]) {
FILE: apps/web/src/utils/playground/misc-demo-utils.ts
constant ABORTED (line 2) | const ABORTED = "User aborted";
FILE: apps/web/src/utils/playground/tools.ts
method experimental_toToolResultContent (line 314) | experimental_toToolResultContent(result) {
FILE: apps/web/src/utils/playground/use-scroll-to-bottom.ts
function useScrollToBottom (line 3) | function useScrollToBottom(): [
FILE: apps/web/src/utils/posthog/posthog.ts
function PostHogClient (line 3) | function PostHogClient() {
FILE: apps/web/src/utils/stripe/stripe-server.ts
constant STRIPE_PRICE_ID (line 14) | const STRIPE_PRICE_ID = process.env.STRIPE_PRICE_ID_PRO || '';
FILE: apps/web/src/utils/stripe/tiers.ts
type Tier (line 2) | interface Tier {
FILE: apps/web/src/utils/supabase/client.ts
function createClient (line 3) | function createClient() {
FILE: apps/web/src/utils/supabase/middleware.ts
function updateSession (line 4) | async function updateSession(request: NextRequest) {
FILE: apps/web/src/utils/supabase/server.ts
function createClient (line 4) | function createClient() {
FILE: apps/web/src/utils/supabase/supabaseClient.js
function createClient (line 4) | function createClient() {
FILE: apps/web/src/utils/supabase/supabaseServerClient.ts
function createClient (line 4) | function createClient() {
FILE: sdks/py-sdk/cyberdesk/actions.py
function click_mouse (line 34) | def click_mouse(
function drag_mouse (line 50) | def drag_mouse(
function get_cursor_position (line 64) | def get_cursor_position() -> PostV1DesktopIdComputerActionGetCursorPosit...
function move_mouse (line 69) | def move_mouse(
function press_keys (line 79) | def press_keys(
function screenshot (line 89) | def screenshot() -> PostV1DesktopIdComputerActionScreenshotAction:
function scroll (line 94) | def scroll(
function type_text (line 104) | def type_text(
function wait (line 112) | def wait(
FILE: sdks/py-sdk/cyberdesk/client.py
class CyberdeskClient (line 24) | class CyberdeskClient:
method __init__ (line 29) | def __init__(self, api_key: str, base_url: str = "https://api.cyberdes...
method get_desktop (line 33) | def get_desktop(self, id: GetDesktopParams):
method async_get_desktop (line 37) | async def async_get_desktop(self, id: GetDesktopParams):
method launch_desktop (line 41) | def launch_desktop(self, timeout_ms: int = None):
method async_launch_desktop (line 46) | async def async_launch_desktop(self, timeout_ms: int = None):
method terminate_desktop (line 51) | def terminate_desktop(self, id: TerminateDesktopParams):
method async_terminate_desktop (line 55) | async def async_terminate_desktop(self, id: TerminateDesktopParams):
method execute_computer_action (line 59) | def execute_computer_action(self, id: GetDesktopParams, action: Comput...
method async_execute_computer_action (line 63) | async def async_execute_computer_action(self, id: GetDesktopParams, ac...
method execute_bash_action (line 67) | def execute_bash_action(self, id: GetDesktopParams, command: ExecuteBa...
method async_execute_bash_action (line 72) | async def async_execute_bash_action(self, id: GetDesktopParams, comman...
FILE: sdks/py-sdk/openapi_client/api_reference_client/api/desktop/get_v1_desktop_id.py
function _get_kwargs (line 21) | def _get_kwargs(
function _parse_response (line 38) | def _parse_response(
function _build_response (line 95) | def _build_response(
function sync_detailed (line 118) | def sync_detailed(
function sync (line 165) | def sync(
function asyncio_detailed (line 207) | async def asyncio_detailed(
function asyncio (line 252) | async def asyncio(
FILE: sdks/py-sdk/openapi_client/api_reference_client/api/desktop/post_v1_desktop.py
function _get_kwargs (line 21) | def _get_kwargs(
function _parse_response (line 43) | def _parse_response(
function _build_response (line 100) | def _build_response(
function sync_detailed (line 123) | def sync_detailed(
function sync (line 169) | def sync(
function asyncio_detailed (line 210) | async def asyncio_detailed(
function asyncio (line 254) | async def asyncio(
FILE: sdks/py-sdk/openapi_client/api_reference_client/api/desktop/post_v1_desktop_id_bash_action.py
function _get_kwargs (line 21) | def _get_kwargs(
function _parse_response (line 44) | def _parse_response(
function _build_response (line 101) | def _build_response(
function sync_detailed (line 124) | def sync_detailed(
function sync (line 173) | def sync(
function asyncio_detailed (line 217) | async def asyncio_detailed(
function asyncio (line 264) | async def asyncio(
FILE: sdks/py-sdk/openapi_client/api_reference_client/api/desktop/post_v1_desktop_id_computer_action.py
function _get_kwargs (line 33) | def _get_kwargs(
function _parse_response (line 84) | def _parse_response(
function _build_response (line 141) | def _build_response(
function sync_detailed (line 164) | def sync_detailed(
function sync (line 231) | def sync(
function asyncio_detailed (line 293) | async def asyncio_detailed(
function asyncio (line 358) | async def asyncio(
FILE: sdks/py-sdk/openapi_client/api_reference_client/api/desktop/post_v1_desktop_id_stop.py
function _get_kwargs (line 20) | def _get_kwargs(
function _parse_response (line 37) | def _parse_response(
function _build_response (line 94) | def _build_response(
function sync_detailed (line 117) | def sync_detailed(
function sync (line 163) | def sync(
function asyncio_detailed (line 204) | async def asyncio_detailed(
function asyncio (line 248) | async def asyncio(
FILE: sdks/py-sdk/openapi_client/api_reference_client/client.py
class Client (line 9) | class Client:
method with_headers (line 48) | def with_headers(self, headers: dict[str, str]) -> "Client":
method with_cookies (line 56) | def with_cookies(self, cookies: dict[str, str]) -> "Client":
method with_timeout (line 64) | def with_timeout(self, timeout: httpx.Timeout) -> "Client":
method set_httpx_client (line 72) | def set_httpx_client(self, client: httpx.Client) -> "Client":
method get_httpx_client (line 80) | def get_httpx_client(self) -> httpx.Client:
method __enter__ (line 94) | def __enter__(self) -> "Client":
method __exit__ (line 99) | def __exit__(self, *args: Any, **kwargs: Any) -> None:
method set_async_httpx_client (line 103) | def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "...
method get_async_httpx_client (line 111) | def get_async_httpx_client(self) -> httpx.AsyncClient:
method __aenter__ (line 125) | async def __aenter__(self) -> "Client":
method __aexit__ (line 130) | async def __aexit__(self, *args: Any, **kwargs: Any) -> None:
class AuthenticatedClient (line 136) | class AuthenticatedClient:
method with_headers (line 182) | def with_headers(self, headers: dict[str, str]) -> "AuthenticatedClient":
method with_cookies (line 190) | def with_cookies(self, cookies: dict[str, str]) -> "AuthenticatedClient":
method with_timeout (line 198) | def with_timeout(self, timeout: httpx.Timeout) -> "AuthenticatedClient":
method set_httpx_client (line 206) | def set_httpx_client(self, client: httpx.Client) -> "AuthenticatedClie...
method get_httpx_client (line 214) | def get_httpx_client(self) -> httpx.Client:
method __enter__ (line 229) | def __enter__(self) -> "AuthenticatedClient":
method __exit__ (line 234) | def __exit__(self, *args: Any, **kwargs: Any) -> None:
method set_async_httpx_client (line 238) | def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "...
method get_async_httpx_client (line 246) | def get_async_httpx_client(self) -> httpx.AsyncClient:
method __aenter__ (line 261) | async def __aenter__(self) -> "AuthenticatedClient":
method __aexit__ (line 266) | async def __aexit__(self, *args: Any, **kwargs: Any) -> None:
FILE: sdks/py-sdk/openapi_client/api_reference_client/errors.py
class UnexpectedStatus (line 4) | class UnexpectedStatus(Exception):
method __init__ (line 7) | def __init__(self, status_code: int, content: bytes):
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/get_v1_desktop_id_response_200.py
class GetV1DesktopIdResponse200 (line 16) | class GetV1DesktopIdResponse200:
method to_dict (line 35) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 62) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 91) | def additional_keys(self) -> list[str]:
method __getitem__ (line 94) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 97) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 100) | def __delitem__(self, key: str) -> None:
method __contains__ (line 103) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/get_v1_desktop_id_response_200_status.py
class GetV1DesktopIdResponse200Status (line 4) | class GetV1DesktopIdResponse200Status(str, Enum):
method __str__ (line 10) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/get_v1_desktop_id_response_400.py
class GetV1DesktopIdResponse400 (line 13) | class GetV1DesktopIdResponse400:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/get_v1_desktop_id_response_400_status.py
class GetV1DesktopIdResponse400Status (line 4) | class GetV1DesktopIdResponse400Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/get_v1_desktop_id_response_401.py
class GetV1DesktopIdResponse401 (line 13) | class GetV1DesktopIdResponse401:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/get_v1_desktop_id_response_401_status.py
class GetV1DesktopIdResponse401Status (line 4) | class GetV1DesktopIdResponse401Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/get_v1_desktop_id_response_403.py
class GetV1DesktopIdResponse403 (line 13) | class GetV1DesktopIdResponse403:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/get_v1_desktop_id_response_403_status.py
class GetV1DesktopIdResponse403Status (line 4) | class GetV1DesktopIdResponse403Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/get_v1_desktop_id_response_404.py
class GetV1DesktopIdResponse404 (line 13) | class GetV1DesktopIdResponse404:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/get_v1_desktop_id_response_404_status.py
class GetV1DesktopIdResponse404Status (line 4) | class GetV1DesktopIdResponse404Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/get_v1_desktop_id_response_409.py
class GetV1DesktopIdResponse409 (line 13) | class GetV1DesktopIdResponse409:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/get_v1_desktop_id_response_409_status.py
class GetV1DesktopIdResponse409Status (line 4) | class GetV1DesktopIdResponse409Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/get_v1_desktop_id_response_429.py
class GetV1DesktopIdResponse429 (line 13) | class GetV1DesktopIdResponse429:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/get_v1_desktop_id_response_429_status.py
class GetV1DesktopIdResponse429Status (line 4) | class GetV1DesktopIdResponse429Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/get_v1_desktop_id_response_500.py
class GetV1DesktopIdResponse500 (line 13) | class GetV1DesktopIdResponse500:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/get_v1_desktop_id_response_500_status.py
class GetV1DesktopIdResponse500Status (line 4) | class GetV1DesktopIdResponse500Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/get_v1_desktop_id_response_502.py
class GetV1DesktopIdResponse502 (line 13) | class GetV1DesktopIdResponse502:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/get_v1_desktop_id_response_502_status.py
class GetV1DesktopIdResponse502Status (line 4) | class GetV1DesktopIdResponse502Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_body.py
class PostV1DesktopBody (line 13) | class PostV1DesktopBody:
method to_dict (line 22) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 34) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 46) | def additional_keys(self) -> list[str]:
method __getitem__ (line 49) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 52) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 55) | def __delitem__(self, key: str) -> None:
method __contains__ (line 58) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_bash_action_body.py
class PostV1DesktopIdBashActionBody (line 11) | class PostV1DesktopIdBashActionBody:
method to_dict (line 20) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 34) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 46) | def additional_keys(self) -> list[str]:
method __getitem__ (line 49) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 52) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 55) | def __delitem__(self, key: str) -> None:
method __contains__ (line 58) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_bash_action_response_200.py
class PostV1DesktopIdBashActionResponse200 (line 13) | class PostV1DesktopIdBashActionResponse200:
method to_dict (line 28) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 48) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 66) | def additional_keys(self) -> list[str]:
method __getitem__ (line 69) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 72) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 75) | def __delitem__(self, key: str) -> None:
method __contains__ (line 78) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_bash_action_response_400.py
class PostV1DesktopIdBashActionResponse400 (line 13) | class PostV1DesktopIdBashActionResponse400:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_bash_action_response_400_status.py
class PostV1DesktopIdBashActionResponse400Status (line 4) | class PostV1DesktopIdBashActionResponse400Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_bash_action_response_401.py
class PostV1DesktopIdBashActionResponse401 (line 13) | class PostV1DesktopIdBashActionResponse401:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_bash_action_response_401_status.py
class PostV1DesktopIdBashActionResponse401Status (line 4) | class PostV1DesktopIdBashActionResponse401Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_bash_action_response_403.py
class PostV1DesktopIdBashActionResponse403 (line 13) | class PostV1DesktopIdBashActionResponse403:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_bash_action_response_403_status.py
class PostV1DesktopIdBashActionResponse403Status (line 4) | class PostV1DesktopIdBashActionResponse403Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_bash_action_response_404.py
class PostV1DesktopIdBashActionResponse404 (line 13) | class PostV1DesktopIdBashActionResponse404:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_bash_action_response_404_status.py
class PostV1DesktopIdBashActionResponse404Status (line 4) | class PostV1DesktopIdBashActionResponse404Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_bash_action_response_409.py
class PostV1DesktopIdBashActionResponse409 (line 13) | class PostV1DesktopIdBashActionResponse409:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_bash_action_response_409_status.py
class PostV1DesktopIdBashActionResponse409Status (line 4) | class PostV1DesktopIdBashActionResponse409Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_bash_action_response_429.py
class PostV1DesktopIdBashActionResponse429 (line 13) | class PostV1DesktopIdBashActionResponse429:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_bash_action_response_429_status.py
class PostV1DesktopIdBashActionResponse429Status (line 4) | class PostV1DesktopIdBashActionResponse429Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_bash_action_response_500.py
class PostV1DesktopIdBashActionResponse500 (line 13) | class PostV1DesktopIdBashActionResponse500:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_bash_action_response_500_status.py
class PostV1DesktopIdBashActionResponse500Status (line 4) | class PostV1DesktopIdBashActionResponse500Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_bash_action_response_502.py
class PostV1DesktopIdBashActionResponse502 (line 13) | class PostV1DesktopIdBashActionResponse502:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_bash_action_response_502_status.py
class PostV1DesktopIdBashActionResponse502Status (line 4) | class PostV1DesktopIdBashActionResponse502Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_click_mouse_action.py
class PostV1DesktopIdComputerActionClickMouseAction (line 22) | class PostV1DesktopIdComputerActionClickMouseAction:
method to_dict (line 45) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 83) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 120) | def additional_keys(self) -> list[str]:
method __getitem__ (line 123) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 126) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 129) | def __delitem__(self, key: str) -> None:
method __contains__ (line 132) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_click_mouse_action_button.py
class PostV1DesktopIdComputerActionClickMouseActionButton (line 4) | class PostV1DesktopIdComputerActionClickMouseActionButton(str, Enum):
method __str__ (line 9) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_click_mouse_action_click_type.py
class PostV1DesktopIdComputerActionClickMouseActionClickType (line 4) | class PostV1DesktopIdComputerActionClickMouseActionClickType(str, Enum):
method __str__ (line 9) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_click_mouse_action_type.py
class PostV1DesktopIdComputerActionClickMouseActionType (line 4) | class PostV1DesktopIdComputerActionClickMouseActionType(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_drag_mouse_action.py
class PostV1DesktopIdComputerActionDragMouseAction (line 24) | class PostV1DesktopIdComputerActionDragMouseAction:
method to_dict (line 40) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 60) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 85) | def additional_keys(self) -> list[str]:
method __getitem__ (line 88) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 91) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 94) | def __delitem__(self, key: str) -> None:
method __contains__ (line 97) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_drag_mouse_action_end.py
class PostV1DesktopIdComputerActionDragMouseActionEnd (line 11) | class PostV1DesktopIdComputerActionDragMouseActionEnd:
method to_dict (line 26) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 43) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 58) | def additional_keys(self) -> list[str]:
method __getitem__ (line 61) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 64) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 67) | def __delitem__(self, key: str) -> None:
method __contains__ (line 70) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_drag_mouse_action_start.py
class PostV1DesktopIdComputerActionDragMouseActionStart (line 11) | class PostV1DesktopIdComputerActionDragMouseActionStart:
method to_dict (line 26) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 43) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 58) | def additional_keys(self) -> list[str]:
method __getitem__ (line 61) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 64) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 67) | def __delitem__(self, key: str) -> None:
method __contains__ (line 70) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_drag_mouse_action_type.py
class PostV1DesktopIdComputerActionDragMouseActionType (line 4) | class PostV1DesktopIdComputerActionDragMouseActionType(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_get_cursor_position_action.py
class PostV1DesktopIdComputerActionGetCursorPositionAction (line 15) | class PostV1DesktopIdComputerActionGetCursorPositionAction:
method to_dict (line 25) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 39) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 51) | def additional_keys(self) -> list[str]:
method __getitem__ (line 54) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 57) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 60) | def __delitem__(self, key: str) -> None:
method __contains__ (line 63) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_get_cursor_position_action_type.py
class PostV1DesktopIdComputerActionGetCursorPositionActionType (line 4) | class PostV1DesktopIdComputerActionGetCursorPositionActionType(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_move_mouse_action.py
class PostV1DesktopIdComputerActionMoveMouseAction (line 15) | class PostV1DesktopIdComputerActionMoveMouseAction:
method to_dict (line 29) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 49) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 67) | def additional_keys(self) -> list[str]:
method __getitem__ (line 70) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 73) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 76) | def __delitem__(self, key: str) -> None:
method __contains__ (line 79) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_move_mouse_action_type.py
class PostV1DesktopIdComputerActionMoveMouseActionType (line 4) | class PostV1DesktopIdComputerActionMoveMouseActionType(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_press_keys_action.py
class PostV1DesktopIdComputerActionPressKeysAction (line 19) | class PostV1DesktopIdComputerActionPressKeysAction:
method to_dict (line 34) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 62) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 96) | def additional_keys(self) -> list[str]:
method __getitem__ (line 99) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 102) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 105) | def __delitem__(self, key: str) -> None:
method __contains__ (line 108) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_press_keys_action_key_action_type.py
class PostV1DesktopIdComputerActionPressKeysActionKeyActionType (line 4) | class PostV1DesktopIdComputerActionPressKeysActionKeyActionType(str, Enum):
method __str__ (line 9) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_press_keys_action_type.py
class PostV1DesktopIdComputerActionPressKeysActionType (line 4) | class PostV1DesktopIdComputerActionPressKeysActionType(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_response_200.py
class PostV1DesktopIdComputerActionResponse200 (line 13) | class PostV1DesktopIdComputerActionResponse200:
method to_dict (line 28) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 48) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 66) | def additional_keys(self) -> list[str]:
method __getitem__ (line 69) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 72) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 75) | def __delitem__(self, key: str) -> None:
method __contains__ (line 78) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_response_400.py
class PostV1DesktopIdComputerActionResponse400 (line 15) | class PostV1DesktopIdComputerActionResponse400:
method to_dict (line 26) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 43) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 58) | def additional_keys(self) -> list[str]:
method __getitem__ (line 61) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 64) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 67) | def __delitem__(self, key: str) -> None:
method __contains__ (line 70) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_response_400_status.py
class PostV1DesktopIdComputerActionResponse400Status (line 4) | class PostV1DesktopIdComputerActionResponse400Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_response_401.py
class PostV1DesktopIdComputerActionResponse401 (line 15) | class PostV1DesktopIdComputerActionResponse401:
method to_dict (line 26) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 43) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 58) | def additional_keys(self) -> list[str]:
method __getitem__ (line 61) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 64) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 67) | def __delitem__(self, key: str) -> None:
method __contains__ (line 70) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_response_401_status.py
class PostV1DesktopIdComputerActionResponse401Status (line 4) | class PostV1DesktopIdComputerActionResponse401Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_response_403.py
class PostV1DesktopIdComputerActionResponse403 (line 15) | class PostV1DesktopIdComputerActionResponse403:
method to_dict (line 26) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 43) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 58) | def additional_keys(self) -> list[str]:
method __getitem__ (line 61) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 64) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 67) | def __delitem__(self, key: str) -> None:
method __contains__ (line 70) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_response_403_status.py
class PostV1DesktopIdComputerActionResponse403Status (line 4) | class PostV1DesktopIdComputerActionResponse403Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_response_404.py
class PostV1DesktopIdComputerActionResponse404 (line 15) | class PostV1DesktopIdComputerActionResponse404:
method to_dict (line 26) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 43) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 58) | def additional_keys(self) -> list[str]:
method __getitem__ (line 61) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 64) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 67) | def __delitem__(self, key: str) -> None:
method __contains__ (line 70) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_response_404_status.py
class PostV1DesktopIdComputerActionResponse404Status (line 4) | class PostV1DesktopIdComputerActionResponse404Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_response_409.py
class PostV1DesktopIdComputerActionResponse409 (line 15) | class PostV1DesktopIdComputerActionResponse409:
method to_dict (line 26) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 43) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 58) | def additional_keys(self) -> list[str]:
method __getitem__ (line 61) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 64) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 67) | def __delitem__(self, key: str) -> None:
method __contains__ (line 70) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_response_409_status.py
class PostV1DesktopIdComputerActionResponse409Status (line 4) | class PostV1DesktopIdComputerActionResponse409Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_response_429.py
class PostV1DesktopIdComputerActionResponse429 (line 15) | class PostV1DesktopIdComputerActionResponse429:
method to_dict (line 26) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 43) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 58) | def additional_keys(self) -> list[str]:
method __getitem__ (line 61) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 64) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 67) | def __delitem__(self, key: str) -> None:
method __contains__ (line 70) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_response_429_status.py
class PostV1DesktopIdComputerActionResponse429Status (line 4) | class PostV1DesktopIdComputerActionResponse429Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_response_500.py
class PostV1DesktopIdComputerActionResponse500 (line 15) | class PostV1DesktopIdComputerActionResponse500:
method to_dict (line 26) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 43) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 58) | def additional_keys(self) -> list[str]:
method __getitem__ (line 61) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 64) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 67) | def __delitem__(self, key: str) -> None:
method __contains__ (line 70) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_response_500_status.py
class PostV1DesktopIdComputerActionResponse500Status (line 4) | class PostV1DesktopIdComputerActionResponse500Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_response_502.py
class PostV1DesktopIdComputerActionResponse502 (line 15) | class PostV1DesktopIdComputerActionResponse502:
method to_dict (line 26) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 43) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 58) | def additional_keys(self) -> list[str]:
method __getitem__ (line 61) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 64) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 67) | def __delitem__(self, key: str) -> None:
method __contains__ (line 70) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_response_502_status.py
class PostV1DesktopIdComputerActionResponse502Status (line 4) | class PostV1DesktopIdComputerActionResponse502Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_screenshot_action.py
class PostV1DesktopIdComputerActionScreenshotAction (line 15) | class PostV1DesktopIdComputerActionScreenshotAction:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 38) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 50) | def additional_keys(self) -> list[str]:
method __getitem__ (line 53) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 56) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 59) | def __delitem__(self, key: str) -> None:
method __contains__ (line 62) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_screenshot_action_type.py
class PostV1DesktopIdComputerActionScreenshotActionType (line 4) | class PostV1DesktopIdComputerActionScreenshotActionType(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_scroll_action.py
class PostV1DesktopIdComputerActionScrollAction (line 16) | class PostV1DesktopIdComputerActionScrollAction:
method to_dict (line 30) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 50) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 68) | def additional_keys(self) -> list[str]:
method __getitem__ (line 71) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 74) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 77) | def __delitem__(self, key: str) -> None:
method __contains__ (line 80) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_scroll_action_direction.py
class PostV1DesktopIdComputerActionScrollActionDirection (line 4) | class PostV1DesktopIdComputerActionScrollActionDirection(str, Enum):
method __str__ (line 10) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_scroll_action_type.py
class PostV1DesktopIdComputerActionScrollActionType (line 4) | class PostV1DesktopIdComputerActionScrollActionType(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_type_text_action.py
class PostV1DesktopIdComputerActionTypeTextAction (line 15) | class PostV1DesktopIdComputerActionTypeTextAction:
method to_dict (line 26) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 43) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 58) | def additional_keys(self) -> list[str]:
method __getitem__ (line 61) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 64) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 67) | def __delitem__(self, key: str) -> None:
method __contains__ (line 70) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_type_text_action_type.py
class PostV1DesktopIdComputerActionTypeTextActionType (line 4) | class PostV1DesktopIdComputerActionTypeTextActionType(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_wait_action.py
class PostV1DesktopIdComputerActionWaitAction (line 13) | class PostV1DesktopIdComputerActionWaitAction:
method to_dict (line 25) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 42) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 57) | def additional_keys(self) -> list[str]:
method __getitem__ (line 60) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 63) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 66) | def __delitem__(self, key: str) -> None:
method __contains__ (line 69) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_computer_action_wait_action_type.py
class PostV1DesktopIdComputerActionWaitActionType (line 4) | class PostV1DesktopIdComputerActionWaitActionType(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_stop_response_200.py
class PostV1DesktopIdStopResponse200 (line 13) | class PostV1DesktopIdStopResponse200:
method to_dict (line 23) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 37) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 49) | def additional_keys(self) -> list[str]:
method __getitem__ (line 52) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 55) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 58) | def __delitem__(self, key: str) -> None:
method __contains__ (line 61) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_stop_response_200_status.py
class PostV1DesktopIdStopResponse200Status (line 4) | class PostV1DesktopIdStopResponse200Status(str, Enum):
method __str__ (line 10) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_stop_response_400.py
class PostV1DesktopIdStopResponse400 (line 13) | class PostV1DesktopIdStopResponse400:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_stop_response_400_status.py
class PostV1DesktopIdStopResponse400Status (line 4) | class PostV1DesktopIdStopResponse400Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_stop_response_401.py
class PostV1DesktopIdStopResponse401 (line 13) | class PostV1DesktopIdStopResponse401:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_stop_response_401_status.py
class PostV1DesktopIdStopResponse401Status (line 4) | class PostV1DesktopIdStopResponse401Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_stop_response_403.py
class PostV1DesktopIdStopResponse403 (line 13) | class PostV1DesktopIdStopResponse403:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_stop_response_403_status.py
class PostV1DesktopIdStopResponse403Status (line 4) | class PostV1DesktopIdStopResponse403Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_stop_response_404.py
class PostV1DesktopIdStopResponse404 (line 13) | class PostV1DesktopIdStopResponse404:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_stop_response_404_status.py
class PostV1DesktopIdStopResponse404Status (line 4) | class PostV1DesktopIdStopResponse404Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_stop_response_409.py
class PostV1DesktopIdStopResponse409 (line 13) | class PostV1DesktopIdStopResponse409:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_stop_response_409_status.py
class PostV1DesktopIdStopResponse409Status (line 4) | class PostV1DesktopIdStopResponse409Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_stop_response_429.py
class PostV1DesktopIdStopResponse429 (line 13) | class PostV1DesktopIdStopResponse429:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_stop_response_429_status.py
class PostV1DesktopIdStopResponse429Status (line 4) | class PostV1DesktopIdStopResponse429Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_stop_response_500.py
class PostV1DesktopIdStopResponse500 (line 13) | class PostV1DesktopIdStopResponse500:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_stop_response_500_status.py
class PostV1DesktopIdStopResponse500Status (line 4) | class PostV1DesktopIdStopResponse500Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_stop_response_502.py
class PostV1DesktopIdStopResponse502 (line 13) | class PostV1DesktopIdStopResponse502:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_id_stop_response_502_status.py
class PostV1DesktopIdStopResponse502Status (line 4) | class PostV1DesktopIdStopResponse502Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_response_200.py
class PostV1DesktopResponse200 (line 13) | class PostV1DesktopResponse200:
method to_dict (line 25) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 42) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 57) | def additional_keys(self) -> list[str]:
method __getitem__ (line 60) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 63) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 66) | def __delitem__(self, key: str) -> None:
method __contains__ (line 69) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_response_200_status.py
class PostV1DesktopResponse200Status (line 4) | class PostV1DesktopResponse200Status(str, Enum):
method __str__ (line 10) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_response_400.py
class PostV1DesktopResponse400 (line 13) | class PostV1DesktopResponse400:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_response_400_status.py
class PostV1DesktopResponse400Status (line 4) | class PostV1DesktopResponse400Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_response_401.py
class PostV1DesktopResponse401 (line 13) | class PostV1DesktopResponse401:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_response_401_status.py
class PostV1DesktopResponse401Status (line 4) | class PostV1DesktopResponse401Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_response_403.py
class PostV1DesktopResponse403 (line 13) | class PostV1DesktopResponse403:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_response_403_status.py
class PostV1DesktopResponse403Status (line 4) | class PostV1DesktopResponse403Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_response_404.py
class PostV1DesktopResponse404 (line 13) | class PostV1DesktopResponse404:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_response_404_status.py
class PostV1DesktopResponse404Status (line 4) | class PostV1DesktopResponse404Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_response_409.py
class PostV1DesktopResponse409 (line 13) | class PostV1DesktopResponse409:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_response_409_status.py
class PostV1DesktopResponse409Status (line 4) | class PostV1DesktopResponse409Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_response_429.py
class PostV1DesktopResponse429 (line 13) | class PostV1DesktopResponse429:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_response_429_status.py
class PostV1DesktopResponse429Status (line 4) | class PostV1DesktopResponse429Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_response_500.py
class PostV1DesktopResponse500 (line 13) | class PostV1DesktopResponse500:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_response_500_status.py
class PostV1DesktopResponse500Status (line 4) | class PostV1DesktopResponse500Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_response_502.py
class PostV1DesktopResponse502 (line 13) | class PostV1DesktopResponse502:
method to_dict (line 24) | def to_dict(self) -> dict[str, Any]:
method from_dict (line 41) | def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
method additional_keys (line 56) | def additional_keys(self) -> list[str]:
method __getitem__ (line 59) | def __getitem__(self, key: str) -> Any:
method __setitem__ (line 62) | def __setitem__(self, key: str, value: Any) -> None:
method __delitem__ (line 65) | def __delitem__(self, key: str) -> None:
method __contains__ (line 68) | def __contains__(self, key: str) -> bool:
FILE: sdks/py-sdk/openapi_client/api_reference_client/models/post_v1_desktop_response_502_status.py
class PostV1DesktopResponse502Status (line 4) | class PostV1DesktopResponse502Status(str, Enum):
method __str__ (line 7) | def __str__(self) -> str:
FILE: sdks/py-sdk/openapi_client/api_reference_client/types.py
class Unset (line 10) | class Unset:
method __bool__ (line 11) | def __bool__(self) -> Literal[False]:
class File (line 21) | class File:
method to_tuple (line 28) | def to_tuple(self) -> FileJsonType:
class Response (line 37) | class Response(Generic[T]):
FILE: sdks/sandbox/py-sdk/test_sdk.py
function main (line 7) | def main():
FILE: sdks/ts-sdk/src/client/client.gen.ts
type CreateClientConfig (line 14) | type CreateClientConfig<T extends DefaultClientOptions = ClientOptions> ...
FILE: sdks/ts-sdk/src/client/sdk.gen.ts
type Options (line 7) | type Options<TData extends TDataShape = TDataShape, ThrowOnError extends...
FILE: sdks/ts-sdk/src/client/types.gen.ts
type GetV1DesktopByIdData (line 3) | type GetV1DesktopByIdData = {
type GetV1DesktopByIdErrors (line 21) | type GetV1DesktopByIdErrors = {
type GetV1DesktopByIdError (line 104) | type GetV1DesktopByIdError = GetV1DesktopByIdErrors[keyof GetV1DesktopBy...
type GetV1DesktopByIdResponses (line 106) | type GetV1DesktopByIdResponses = {
type GetV1DesktopByIdResponse (line 134) | type GetV1DesktopByIdResponse = GetV1DesktopByIdResponses[keyof GetV1Des...
type PostV1DesktopData (line 136) | type PostV1DesktopData = {
type PostV1DesktopErrors (line 154) | type PostV1DesktopErrors = {
type PostV1DesktopError (line 237) | type PostV1DesktopError = PostV1DesktopErrors[keyof PostV1DesktopErrors];
type PostV1DesktopResponses (line 239) | type PostV1DesktopResponses = {
type PostV1DesktopResponse (line 255) | type PostV1DesktopResponse = PostV1DesktopResponses[keyof PostV1DesktopR...
type PostV1DesktopByIdStopData (line 257) | type PostV1DesktopByIdStopData = {
type PostV1DesktopByIdStopErrors (line 275) | type PostV1DesktopByIdStopErrors = {
type PostV1DesktopByIdStopError (line 358) | type PostV1DesktopByIdStopError = PostV1DesktopByIdStopErrors[keyof Post...
type PostV1DesktopByIdStopResponses (line 360) | type PostV1DesktopByIdStopResponses = {
type PostV1DesktopByIdStopResponse (line 372) | type PostV1DesktopByIdStopResponse = PostV1DesktopByIdStopResponses[keyo...
type PostV1DesktopByIdComputerActionData (line 374) | type PostV1DesktopByIdComputerActionData = {
type PostV1DesktopByIdComputerActionErrors (line 512) | type PostV1DesktopByIdComputerActionErrors = {
type PostV1DesktopByIdComputerActionError (line 595) | type PostV1DesktopByIdComputerActionError = PostV1DesktopByIdComputerAct...
type PostV1DesktopByIdComputerActionResponses (line 597) | type PostV1DesktopByIdComputerActionResponses = {
type PostV1DesktopByIdComputerActionResponse (line 617) | type PostV1DesktopByIdComputerActionResponse = PostV1DesktopByIdComputer...
type PostV1DesktopByIdBashActionData (line 619) | type PostV1DesktopByIdBashActionData = {
type PostV1DesktopByIdBashActionErrors (line 642) | type PostV1DesktopByIdBashActionErrors = {
type PostV1DesktopByIdBashActionError (line 725) | type PostV1DesktopByIdBashActionError = PostV1DesktopByIdBashActionError...
type PostV1DesktopByIdBashActionResponses (line 727) | type PostV1DesktopByIdBashActionResponses = {
type PostV1DesktopByIdBashActionResponse (line 747) | type PostV1DesktopByIdBashActionResponse = PostV1DesktopByIdBashActionRe...
type ClientOptions (line 749) | type ClientOptions = {
FILE: sdks/ts-sdk/src/index.ts
constant DEFAULT_BASE_URL (line 13) | const DEFAULT_BASE_URL = 'https://api.cyberdesk.io';
type FetchFn (line 15) | type FetchFn = (input: RequestInfo | URL, init?: RequestInit) => Promise...
type CyberdeskClientOptions (line 20) | interface CyberdeskClientOptions {
type GetDesktopParams (line 33) | type GetDesktopParams = Omit<GetV1DesktopByIdData, 'headers' | 'url'>;
type LaunchDesktopParams (line 34) | type LaunchDesktopParams = Omit<PostV1DesktopData, 'headers' | 'url'>;
type TerminateDesktopParams (line 35) | type TerminateDesktopParams = Omit<PostV1DesktopByIdStopData, 'headers' ...
type ExecuteComputerActionParams (line 36) | type ExecuteComputerActionParams = Omit<PostV1DesktopByIdComputerActionD...
type ExecuteBashActionParams (line 37) | type ExecuteBashActionParams = Omit<PostV1DesktopByIdBashActionData, 'he...
type CyberdeskSDK (line 39) | type CyberdeskSDK = {
function createCyberdeskClient (line 54) | function createCyberdeskClient(options: CyberdeskClientOptions): Cyberde...
FILE: services/cyberdesk-operator/handlers/controller.py
class KubeVirtVMIPhase (line 84) | class KubeVirtVMIPhase(str, Enum):
class SupabaseInstanceStatus (line 96) | class SupabaseInstanceStatus(str, Enum):
function _init_supabase (line 128) | def _init_supabase() -> Client:
function _init_kubernetes_clients (line 147) | def _init_kubernetes_clients() -> tuple[CoreV1Api, CustomObjectsApi, Api...
function get_instance_status (line 192) | def get_instance_status(instance_id: str) -> Optional[str]:
function update_instance_status (line 203) | def update_instance_status(instance_id: str, vmi_phase: str) -> None:
function get_free_vm_from_pool (line 223) | def get_free_vm_from_pool(namespace: str, logger: kopf.Logger) -> Option...
function ensure_golden_snapshot_exists (line 356) | def ensure_golden_snapshot_exists():
function configure_kopf (line 385) | def configure_kopf(settings: OperatorSettings, **_: Dict[str, object]) -...
function crd_bootstrap (line 394) | def crd_bootstrap(spec: dict, meta: dict, **_: Dict[str, object]) -> None:
function _ensure_vm_patched_and_running (line 408) | def _ensure_vm_patched_and_running(vm_name: str, namespace: str, logger:...
function cyberdesk_create (line 457) | def cyberdesk_create(spec: dict, meta: dict, status: dict, logger: kopf....
function vmi_phase_change (line 761) | def vmi_phase_change(old: str | None, new: str | None, meta: dict, statu...
function cyberdesk_delete (line 815) | def cyberdesk_delete(meta: dict, body: dict, logger: kopf.Logger, **_: D...
function cyberdesk_timeout_check (line 868) | def cyberdesk_timeout_check(body: dict, logger: kopf.Logger, **_: Dict[s...
function vmi_ready_watcher (line 901) | def vmi_ready_watcher(old, new, status, meta, logger: kopf.Logger, **kwa...
FILE: services/cyberdesk-operator/tests/test.py
function test_operator (line 5) | def test_operator():
FILE: services/gateway/main.py
function init_kube_clients (line 81) | def init_kube_clients() -> tuple[Optional[CustomObjectsApi], Optional[Co...
class CyberdeskCreateRequest (line 131) | class CyberdeskCreateRequest(BaseModel):
class CommandRequest (line 138) | class CommandRequest(BaseModel):
class CyberdeskCreateResponse (line 144) | class CyberdeskCreateResponse(BaseModel):
class StatusMessageResponse (line 148) | class StatusMessageResponse(BaseModel):
class CyberdeskReadyResponse (line 153) | class CyberdeskReadyResponse(StatusMessageResponse):
class VMCommandExecutionResponse (line 157) | class VMCommandExecutionResponse(BaseModel):
class GatewayCommandResponse (line 165) | class GatewayCommandResponse(BaseModel):
class HealthCheckResponse (line 171) | class HealthCheckResponse(BaseModel):
class VmHealthCheckResponse (line 175) | class VmHealthCheckResponse(BaseModel):
function serve_novnc (line 207) | async def serve_novnc(vm_id: str) -> FileResponse:
function _relay (line 221) | async def _relay(
function proxy_vnc (line 237) | async def proxy_vnc(websocket: WebSocket, vm_id: str) -> None:
function require_k8s (line 372) | def require_k8s() -> CustomObjectsApi:
function require_k8s_core (line 381) | def require_k8s_core() -> CoreV1Api:
function require_supabase (line 390) | def require_supabase() -> Client:
function update_supabase_instance (line 401) | async def update_supabase_instance(vm_id: str, stream_url: str):
function create_cyberdesk (line 440) | async def create_cyberdesk(vm_id: str, payload: CyberdeskCreateRequest):
function stop_cyberdesk (line 473) | async def stop_cyberdesk(vm_id: str):
function cyberdesk_ready (line 501) | async def cyberdesk_ready(vm_id: str):
function execute_vm_command (line 530) | async def execute_vm_command(vm_id: str, payload: CommandRequest):
function health_check (line 594) | async def health_check():
function vm_health_check (line 599) | async def vm_health_check(vmid: str):
function _proxy_request_to_vm (line 643) | async def _proxy_request_to_vm(
FILE: services/gateway/noVNC/app/error-handler.js
function handleError (line 10) | function handleError(event, err) {
FILE: services/gateway/noVNC/app/localization.js
class Localizer (line 13) | class Localizer {
method constructor (line 14) | constructor() {
method setup (line 23) | async setup(supportedLanguages, baseURL) {
method _setupLanguage (line 31) | _setupLanguage(supportedLanguages) {
method _setupDictionary (line 92) | async _setupDictionary(baseURL) {
method get (line 114) | get(id) {
method translateDOM (line 125) | translateDOM() {
FILE: services/gateway/noVNC/app/ui.js
constant PAGE_TITLE (line 21) | const PAGE_TITLE = "noVNC";
constant LINGUAS (line 23) | const LINGUAS = ["cs", "de", "el", "es", "fr", "it", "ja", "ko", "nl", "...
method start (line 49) | async start(options={}) {
method initFullscreen (line 140) | initFullscreen() {
method initSettings (line 154) | initSettings() {
method setupSettingLabels (line 187) | setupSettingLabels() {
method addControlbarHandlers (line 213) | addControlbarHandlers() {
method addTouchSpecificHandlers (line 246) | addTouchSpecificHandlers() {
method addExtraKeysHandlers (line 287) | addExtraKeysHandlers() {
method addMachineHandlers (line 304) | addMachineHandlers() {
method addConnectionControlHandlers (line 315) | addConnectionControlHandlers() {
method addClipboardHandlers (line 331) | addClipboardHandlers() {
method addSettingChangeHandler (line 340) | addSettingChangeHandler(name, changeFunc) {
method addSettingsHandlers (line 348) | addSettingsHandlers() {
method addFullscreenHandlers (line 377) | addFullscreenHandlers() {
method updateVisualState (line 394) | updateVisualState(state) {
method showStatus (line 460) | showStatus(text, statusType, time) {
method hideStatus (line 516) | hideStatus() {
method activateControlbar (line 521) | activateControlbar(event) {
method idleControlbar (line 530) | idleControlbar() {
method keepControlbar (line 542) | keepControlbar() {
method openControlbar (line 546) | openControlbar() {
method closeControlbar (line 551) | closeControlbar() {
method toggleControlbar (line 558) | toggleControlbar() {
method toggleControlbarSide (line 567) | toggleControlbarSide() {
method showControlbarHint (line 593) | showControlbarHint(show, animate=true) {
method dragControlbarHandle (line 609) | dragControlbarHandle(e) {
method moveControlbarHandle (line 644) | moveControlbarHandle(viewportRelativeY) {
method updateControlbarHandle (line 681) | updateControlbarHandle() {
method controlbarHandleMouseUp (line 689) | controlbarHandleMouseUp(e) {
method controlbarHandleMouseDown (line 704) | controlbarHandleMouseDown(e) {
method toggleExpander (line 730) | toggleExpander(e) {
method initSetting (line 745) | initSetting(name, defVal) {
method forceSetting (line 766) | forceSetting(name, val) {
method updateSetting (line 774) | updateSetting(name) {
method saveSetting (line 799) | saveSetting(name) {
method getSetting (line 815) | getSetting(name) {
method disableSetting (line 832) | disableSetting(name) {
method enableSetting (line 842) | enableSetting(name) {
method closeAllPanels (line 858) | closeAllPanels() {
method openSettingsPanel (line 871) | openSettingsPanel() {
method closeSettingsPanel (line 895) | closeSettingsPanel() {
method toggleSettingsPanel (line 902) | toggleSettingsPanel() {
method openPowerPanel (line 917) | openPowerPanel() {
method closePowerPanel (line 927) | closePowerPanel() {
method togglePowerPanel (line 934) | togglePowerPanel() {
method updatePowerButton (line 944) | updatePowerButton() {
method openClipboardPanel (line 964) | openClipboardPanel() {
method closeClipboardPanel (line 974) | closeClipboardPanel() {
method toggleClipboardPanel (line 981) | toggleClipboardPanel() {
method clipboardReceive (line 990) | clipboardReceive(e) {
method clipboardSend (line 996) | clipboardSend() {
method openConnectPanel (line 1009) | openConnectPanel() {
method closeConnectPanel (line 1014) | closeConnectPanel() {
method connect (line 1019) | connect(event, password) {
method disconnect (line 1122) | disconnect() {
method reconnect (line 1135) | reconnect() {
method cancelReconnect (line 1146) | cancelReconnect() {
method connectFinished (line 1158) | connectFinished(e) {
method disconnectFinished (line 1175) | disconnectFinished(e) {
method securityFailed (line 1213) | securityFailed(e) {
method serverVerify (line 1233) | async serverVerify(e) {
method approveServer (line 1246) | approveServer(e) {
method rejectServer (line 1252) | rejectServer(e) {
method credentials (line 1264) | credentials(e) {
method setCredentials (line 1291) | setCredentials(e) {
method toggleFullscreen (line 1315) | toggleFullscreen() {
method updateFullscreenButton (line 1343) | updateFullscreenButton() {
method applyResizeMode (line 1363) | applyResizeMode() {
method updateViewClip (line 1379) | updateViewClip() {
method toggleViewDrag (line 1421) | toggleViewDrag() {
method updateViewDrag (line 1428) | updateViewDrag() {
method updateQuality (line 1461) | updateQuality() {
method updateCompression (line 1473) | updateCompression() {
method showVirtualKeyboard (line 1485) | showVirtualKeyboard() {
method hideVirtualKeyboard (line 1503) | hideVirtualKeyboard() {
method toggleVirtualKeyboard (line 1513) | toggleVirtualKeyboard() {
method onfocusVirtualKeyboard (line 1522) | onfocusVirtualKeyboard(event) {
method onblurVirtualKeyboard (line 1530) | onblurVirtualKeyboard(event) {
method keepVirtualKeyboard (line 1538) | keepVirtualKeyboard(event) {
method keyboardinputReset (line 1566) | keyboardinputReset() {
method keyEvent (line 1572) | keyEvent(keysym, code, down) {
method keyInput (line 1582) | keyInput(event) {
method openExtraKeys (line 1649) | openExtraKeys() {
method closeExtraKeys (line 1659) | closeExtraKeys() {
method toggleExtraKeys (line 1666) | toggleExtraKeys() {
method sendEsc (line 1675) | sendEsc() {
method sendTab (line 1679) | sendTab() {
method toggleCtrl (line 1683) | toggleCtrl() {
method toggleWindows (line 1694) | toggleWindows() {
method toggleAlt (line 1705) | toggleAlt() {
method sendCtrlAltDel (line 1716) | sendCtrlAltDel() {
method sendKey (line 1723) | sendKey(keysym, code, down) {
method updateViewOnly (line 1749) | updateViewOnly() {
method updateShowDotCursor (line 1771) | updateShowDotCursor() {
method updateLogging (line 1776) | updateLogging() {
method updateDesktopName (line 1780) | updateDesktopName(e) {
method bell (line 1786) | bell(e) {
method addOption (line 1805) | addOption(selectbox, text, value) {
FILE: services/gateway/noVNC/app/webutil.js
function initLogging (line 12) | function initLogging(level) {
function getQueryVar (line 32) | function getQueryVar(name, defVal) {
function getHashVar (line 46) | function getHashVar(name, defVal) {
function getConfigVar (line 61) | function getConfigVar(name, defVal) {
function createCookie (line 77) | function createCookie(name, value, days) {
function readCookie (line 97) | function readCookie(name, defaultValue) {
function eraseCookie (line 115) | function eraseCookie(name) {
function initSettings (line 126) | function initSettings() {
function setSetting (line 137) | function setSetting(name, value) {
function writeSetting (line 142) | function writeSetting(name, value) {
function readSetting (line 153) | function readSetting(name, defaultValue) {
function eraseSetting (line 173) | function eraseSetting(name) {
function logOnce (line 189) | function logOnce(msg, level = "warn") {
function localStorageGet (line 210) | function localStorageGet(name) {
function localStorageSet (line 225) | function localStorageSet(name, value) {
function localStorageRemove (line 238) | function localStorageRemove(name) {
FILE: services/gateway/noVNC/core/base64.js
method encode (line 14) | encode(data) {
method decode (line 59) | decode(data, offset = 0) {
FILE: services/gateway/noVNC/core/crypto/aes.js
class AESECBCipher (line 1) | class AESECBCipher {
method constructor (line 2) | constructor() {
method algorithm (line 6) | get algorithm() {
method importKey (line 10) | static async importKey(key, _algorithm, extractable, keyUsages) {
method _importKey (line 16) | async _importKey(key, extractable, keyUsages) {
method encrypt (line 21) | async encrypt(_algorithm, plaintext) {
class AESEAXCipher (line 38) | class AESEAXCipher {
method constructor (line 39) | constructor() {
method algorithm (line 49) | get algorithm() {
method _encryptBlock (line 53) | async _encryptBlock(block) {
method _initCMAC (line 61) | async _initCMAC() {
method _encryptCTR (line 77) | async _encryptCTR(data, counter) {
method _decryptCTR (line 86) | async _decryptCTR(data, counter) {
method _computeCMAC (line 95) | async _computeCMAC(data, prefixBlock) {
method importKey (line 125) | static async importKey(key, _algorithm, _extractable, _keyUsages) {
method _importKey (line 131) | async _importKey(key) {
method encrypt (line 140) | async encrypt(algorithm, message) {
method decrypt (line 156) | async decrypt(algorithm, data) {
FILE: services/gateway/noVNC/core/crypto/bigint.js
function modPow (line 1) | function modPow(b, e, m) {
function bigIntToU8Array (line 14) | function bigIntToU8Array(bigint, padLength=0) {
function u8ArrayToBigInt (line 28) | function u8ArrayToBigInt(arr) {
FILE: services/gateway/noVNC/core/crypto/crypto.js
class LegacyCrypto (line 9) | class LegacyCrypto {
method constructor (line 10) | constructor() {
method encrypt (line 22) | encrypt(algorithm, key, data) {
method decrypt (line 32) | decrypt(algorithm, key, data) {
method importKey (line 42) | importKey(format, keyData, algorithm, extractable, keyUsages) {
method generateKey (line 53) | generateKey(algorithm, extractable, keyUsages) {
method exportKey (line 61) | exportKey(format, key) {
method digest (line 71) | digest(algorithm, data) {
method deriveBits (line 79) | deriveBits(algorithm, key, length) {
FILE: services/gateway/noVNC/core/crypto/des.js
constant PC2 (line 81) | const PC2 = [13,16,10,23, 0, 4, 2,27,14, 5,20, 9,22,18,11, 3,
constant SP1 (line 89) | const SP1 = [c|e,z|z,a|z,c|f,c|d,a|f,z|d,a|z,z|e,c|e,c|f,z|e,b|f,c|d,b|z...
constant SP2 (line 94) | const SP2 = [c|f,b|e,z|e,a|f,a|z,z|d,c|d,b|f,b|d,c|f,c|e,b|z,b|e,a|z,z|d...
constant SP3 (line 99) | const SP3 = [z|f,c|e,z|z,c|d,b|e,z|z,a|f,b|e,a|d,b|d,b|d,a|z,c|f,a|d,c|z...
constant SP4 (line 104) | const SP4 = [c|d,a|f,a|f,z|e,c|e,b|f,b|d,a|d,z|z,c|z,c|z,c|f,z|f,z|z,b|e...
constant SP5 (line 109) | const SP5 = [z|d,a|f,a|e,c|d,z|e,z|d,b|z,a|e,b|f,z|e,a|d,b|f,c|d,c|e,z|f...
constant SP6 (line 114) | const SP6 = [b|d,c|z,z|e,c|f,c|z,z|d,c|f,a|z,b|e,a|f,a|z,b|d,a|d,b|e,b|z...
constant SP7 (line 119) | const SP7 = [a|z,c|d,b|f,z|z,z|e,b|f,a|f,c|e,c|f,a|z,z|z,b|d,z|d,b|z,c|d...
constant SP8 (line 124) | const SP8 = [b|f,z|e,a|z,c|f,b|z,b|f,z|d,b|z,a|d,c|z,c|f,a|e,c|e,a|f,z|e...
class DES (line 131) | class DES {
method constructor (line 132) | constructor(password) {
method enc8 (line 182) | enc8(text) {
class DESECBCipher (line 263) | class DESECBCipher {
method constructor (line 264) | constructor() {
method algorithm (line 268) | get algorithm() {
method importKey (line 272) | static importKey(key, _algorithm, _extractable, _keyUsages) {
method _importKey (line 278) | _importKey(key, _extractable, _keyUsages) {
method encrypt (line 282) | encrypt(_algorithm, plaintext) {
class DESCBCCipher (line 295) | class DESCBCCipher {
method constructor (line 296) | constructor() {
method algorithm (line 300) | get algorithm() {
method importKey (line 304) | static importKey(key, _algorithm, _extractable, _keyUsages) {
method _importKey (line 310) | _importKey(key) {
method encrypt (line 314) | encrypt(algorithm, plaintext) {
FILE: services/gateway/noVNC/core/crypto/dh.js
class DHPublicKey (line 3) | class DHPublicKey {
method constructor (line 4) | constructor(key) {
method algorithm (line 8) | get algorithm() {
method exportKey (line 12) | exportKey() {
class DHCipher (line 17) | class DHCipher {
method constructor (line 18) | constructor() {
method algorithm (line 26) | get algorithm() {
method generateKey (line 30) | static generateKey(algorithm, _extractable) {
method _generateKey (line 36) | _generateKey(algorithm) {
method deriveBits (line 48) | deriveBits(algorithm, length) {
FILE: services/gateway/noVNC/core/crypto/md5.js
function MD5 (line 13) | async function MD5(d) {
function M (line 21) | function M(d) {
function X (line 29) | function X(d) {
function V (line 36) | function V(d) {
function Y (line 42) | function Y(d, g) {
function cmn (line 55) | function cmn(d, g, m, f, r, i) {
function ff (line 59) | function ff(d, g, m, f, r, i, n) {
function gg (line 63) | function gg(d, g, m, f, r, i, n) {
function hh (line 67) | function hh(d, g, m, f, r, i, n) {
function ii (line 71) | function ii(d, g, m, f, r, i, n) {
function add (line 75) | function add(d, g) {
function rol (line 80) | function rol(d, g) {
FILE: services/gateway/noVNC/core/crypto/rsa.js
class RSACipher (line 4) | class RSACipher {
method constructor (line 5) | constructor() {
method algorithm (line 17) | get algorithm() {
method _base64urlDecode (line 21) | _base64urlDecode(data) {
method _padArray (line 27) | _padArray(arr, length) {
method generateKey (line 33) | static async generateKey(algorithm, extractable, _keyUsages) {
method _generateKey (line 39) | async _generateKey(algorithm, extractable) {
method importKey (line 60) | static async importKey(key, _algorithm, extractable, keyUsages) {
method _importKey (line 69) | async _importKey(key, extractable) {
method encrypt (line 86) | async encrypt(_algorithm, message) {
method decrypt (line 104) | async decrypt(_algorithm, message) {
method exportKey (line 126) | async exportKey() {
FILE: services/gateway/noVNC/core/decoders/copyrect.js
class CopyRectDecoder (line 10) | class CopyRectDecoder {
method decodeRect (line 11) | decodeRect(x, y, width, height, sock, display, depth) {
FILE: services/gateway/noVNC/core/decoders/h264.js
class H264Parser (line 12) | class H264Parser {
method constructor (line 13) | constructor(data) {
method _getStartSequenceLen (line 21) | _getStartSequenceLen(index) {
method _indexOfNextNalUnit (line 32) | _indexOfNextNalUnit(index) {
method _parseSps (line 42) | _parseSps(index) {
method _parseNalUnit (line 48) | _parseNalUnit(index) {
method parse (line 74) | parse() {
class H264Context (line 112) | class H264Context {
method constructor (line 113) | constructor(width, height) {
method _handleFrame (line 124) | _handleFrame(frame) {
method _handleError (line 144) | _handleError(e) {
method _configureDecoder (line 148) | _configureDecoder(profileIdc, constraintSet, levelIdc) {
method _preparePendingFrame (line 167) | _preparePendingFrame(timestamp) {
method decode (line 184) | decode(payload) {
class H264Decoder (line 241) | class H264Decoder {
method constructor (line 242) | constructor() {
method _contextId (line 247) | _contextId(x, y, width, height) {
method _findOldestContextId (line 251) | _findOldestContextId() {
method _createContext (line 263) | _createContext(x, y, width, height) {
method _getContext (line 274) | _getContext(x, y, width, height) {
method _resetContext (line 279) | _resetContext(x, y, width, height) {
method _resetAllContexts (line 283) | _resetAllContexts() {
method decodeRect (line 287) | decodeRect(x, y, width, height, sock, display, depth) {
FILE: services/gateway/noVNC/core/decoders/hextile.js
class HextileDecoder (line 12) | class HextileDecoder {
method constructor (line 13) | constructor() {
method decodeRect (line 19) | decodeRect(x, y, width, height, sock, display, depth) {
method _startTile (line 135) | _startTile(x, y, width, height, color) {
method _subTile (line 155) | _subTile(x, y, w, h, color) {
method _finishTile (line 176) | _finishTile(display) {
FILE: services/gateway/noVNC/core/decoders/jpeg.js
class JPEGDecoder (line 10) | class JPEGDecoder {
method constructor (line 11) | constructor() {
method decodeRect (line 20) | decodeRect(x, y, width, height, sock, display, depth) {
method _readSegment (line 89) | _readSegment(sock) {
FILE: services/gateway/noVNC/core/decoders/raw.js
class RawDecoder (line 10) | class RawDecoder {
method constructor (line 11) | constructor() {
method decodeRect (line 15) | decodeRect(x, y, width, height, sock, display, depth) {
FILE: services/gateway/noVNC/core/decoders/rre.js
class RREDecoder (line 10) | class RREDecoder {
method constructor (line 11) | constructor() {
method decodeRect (line 15) | decodeRect(x, y, width, height, sock, display, depth) {
FILE: services/gateway/noVNC/core/decoders/tight.js
class TightDecoder (line 14) | class TightDecoder {
method constructor (line 15) | constructor() {
method decodeRect (line 28) | decodeRect(x, y, width, height, sock, display, depth) {
method _fillRect (line 74) | _fillRect(x, y, width, height, sock, display, depth) {
method _jpegRect (line 85) | _jpegRect(x, y, width, height, sock, display, depth) {
method _pngRect (line 96) | _pngRect(x, y, width, height, sock, display, depth) {
method _basicRect (line 100) | _basicRect(ctl, x, y, width, height, sock, display, depth) {
method _copyFilter (line 143) | _copyFilter(streamId, x, y, width, height, sock, display, depth) {
method _paletteFilter (line 181) | _paletteFilter(streamId, x, y, width, height, sock, display, depth) {
method _monoRect (line 239) | _monoRect(x, y, width, height, data, palette, display) {
method _paletteRect (line 272) | _paletteRect(x, y, width, height, data, palette, display) {
method _gradientFilter (line 287) | _gradientFilter(streamId, x, y, width, height, sock, display, depth) {
method _readData (line 357) | _readData(sock) {
method _getScratchBuffer (line 387) | _getScratchBuffer(size) {
FILE: services/gateway/noVNC/core/decoders/tightpng.js
class TightPNGDecoder (line 12) | class TightPNGDecoder extends TightDecoder {
method _pngRect (line 13) | _pngRect(x, y, width, height, sock, display, depth) {
method _basicRect (line 24) | _basicRect(ctl, x, y, width, height, sock, display, depth) {
FILE: services/gateway/noVNC/core/decoders/zlib.js
class ZlibDecoder (line 12) | class ZlibDecoder {
method constructor (line 13) | constructor() {
method decodeRect (line 18) | decodeRect(x, y, width, height, sock, display, depth) {
FILE: services/gateway/noVNC/core/decoders/zrle.js
constant ZRLE_TILE_WIDTH (line 12) | const ZRLE_TILE_WIDTH = 64;
constant ZRLE_TILE_HEIGHT (line 13) | const ZRLE_TILE_HEIGHT = 64;
class ZRLEDecoder (line 15) | class ZRLEDecoder {
method constructor (line 16) | constructor() {
method decodeRect (line 24) | decodeRect(x, y, width, height, sock, display, depth) {
method _getBitsPerPixelInPalette (line 73) | _getBitsPerPixelInPalette(paletteSize) {
method _readPixels (line 83) | _readPixels(pixels) {
method _decodePaletteTile (line 95) | _decodePaletteTile(paletteSize, tileSize, tilew, tileh) {
method _decodeRLETile (line 127) | _decodeRLETile(tileSize) {
method _decodeRLEPaletteTile (line 144) | _decodeRLEPaletteTile(paletteSize, tileSize) {
method _readRLELength (line 176) | _readRLELength() {
FILE: services/gateway/noVNC/core/deflator.js
class Deflator (line 13) | class Deflator {
method constructor (line 14) | constructor() {
method deflate (line 22) | deflate(inData) {
FILE: services/gateway/noVNC/core/display.js
class Display (line 13) | class Display {
method constructor (line 14) | constructor(target) {
method scale (line 68) | get scale() { return this._scale; }
method scale (line 69) | set scale(scale) {
method clipViewport (line 73) | get clipViewport() { return this._clipViewport; }
method clipViewport (line 74) | set clipViewport(viewport) {
method width (line 82) | get width() {
method height (line 86) | get height() {
method viewportChangePos (line 92) | viewportChangePos(deltaX, deltaY) {
method viewportChangeSize (line 134) | viewportChangeSize(width, height) {
method absX (line 175) | absX(x) {
method absY (line 182) | absY(y) {
method resize (line 189) | resize(width, height) {
method getImageData (line 223) | getImageData() {
method toDataURL (line 227) | toDataURL(type, encoderOptions) {
method toBlob (line 231) | toBlob(callback, type, quality) {
method _damage (line 236) | _damage(x, y, w, h) {
method flip (line 253) | flip(fromQueue) {
method pending (line 299) | pending() {
method flush (line 303) | flush() {
method fillRect (line 316) | fillRect(x, y, width, height, color, fromQueue) {
method copyImage (line 333) | copyImage(oldX, oldY, newX, newY, w, h, fromQueue) {
method imageRect (line 364) | imageRect(x, y, width, height, mime, arr) {
method videoFrame (line 383) | videoFrame(x, y, width, height, frame) {
method blitImage (line 394) | blitImage(x, y, width, height, arr, offset, fromQueue) {
method drawImage (line 420) | drawImage(img, ...args) {
method autoscale (line 432) | autoscale(containerWidth, containerHeight) {
method _rescale (line 456) | _rescale(factor) {
method _setFillColor (line 474) | _setFillColor(color) {
method _renderQPush (line 482) | _renderQPush(action) {
method _resumeRenderQ (line 491) | _resumeRenderQ() {
method _scanRenderQ (line 498) | _scanRenderQ() {
FILE: services/gateway/noVNC/core/encodings.js
function encodingName (line 40) | function encodingName(num) {
FILE: services/gateway/noVNC/core/inflator.js
class Inflate (line 12) | class Inflate {
method constructor (line 13) | constructor() {
method setInput (line 21) | setInput(data) {
method inflate (line 36) | inflate(expected) {
method reset (line 62) | reset() {
FILE: services/gateway/noVNC/core/input/domkeytable.js
function addStandard (line 18) | function addStandard(key, standard) {
function addLeftRight (line 24) | function addLeftRight(key, left, right) {
function addNumpad (line 31) | function addNumpad(key, standard, numpad) {
FILE: services/gateway/noVNC/core/input/gesturehandler.js
constant GH_NOGESTURE (line 10) | const GH_NOGESTURE = 0;
constant GH_ONETAP (line 11) | const GH_ONETAP = 1;
constant GH_TWOTAP (line 12) | const GH_TWOTAP = 2;
constant GH_THREETAP (line 13) | const GH_THREETAP = 4;
constant GH_DRAG (line 14) | const GH_DRAG = 8;
constant GH_LONGPRESS (line 15) | const GH_LONGPRESS = 16;
constant GH_TWODRAG (line 16) | const GH_TWODRAG = 32;
constant GH_PINCH (line 17) | const GH_PINCH = 64;
constant GH_INITSTATE (line 19) | const GH_INITSTATE = 127;
constant GH_MOVE_THRESHOLD (line 21) | const GH_MOVE_THRESHOLD = 50;
constant GH_ANGLE_THRESHOLD (line 22) | const GH_ANGLE_THRESHOLD = 90;
constant GH_MULTITOUCH_TIMEOUT (line 25) | const GH_MULTITOUCH_TIMEOUT = 250;
constant GH_TAP_TIMEOUT (line 28) | const GH_TAP_TIMEOUT = 1000;
constant GH_LONGPRESS_TIMEOUT (line 31) | const GH_LONGPRESS_TIMEOUT = 1000;
constant GH_TWOTOUCH_TIMEOUT (line 34) | const GH_TWOTOUCH_TIMEOUT = 50;
class GestureHandler (line 36) | class GestureHandler {
method constructor (line 37) | constructor() {
method attach (line 54) | attach(target) {
method detach (line 68) | detach() {
method _eventHandler (line 87) | _eventHandler(e) {
method _touchStart (line 112) | _touchStart(id, x, y) {
method _touchMove (line 167) | _touchMove(id, x, y) {
method _touchEnd (line 252) | _touchEnd(id, x, y) {
method _hasDetectedGesture (line 352) | _hasDetectedGesture() {
method _startLongpressTimeout (line 373) | _startLongpressTimeout() {
method _stopLongpressTimeout (line 379) | _stopLongpressTimeout() {
method _longpressTimeout (line 384) | _longpressTimeout() {
method _startTwoTouchTimeout (line 393) | _startTwoTouchTimeout() {
method _stopTwoTouchTimeout (line 399) | _stopTwoTouchTimeout() {
method _isTwoTouchTimeoutRunning (line 404) | _isTwoTouchTimeoutRunning() {
method _twoTouchTimeout (line 408) | _twoTouchTimeout() {
method _pushEvent (line 435) | _pushEvent(type) {
method _stateToGesture (line 488) | _stateToGesture(state) {
method _getPosition (line 509) | _getPosition() {
method _getAverageMovement (line 530) | _getAverageMovement() {
method _getAverageDistance (line 548) | _getAverageDistance() {
FILE: services/gateway/noVNC/core/input/keyboard.js
class Keyboard (line 17) | class Keyboard {
method constructor (line 18) | constructor(target) {
method _sendKeyEvent (line 39) | _sendKeyEvent(keysym, code, down, numlock = null, capslock = null) {
method _getKeyCode (line 56) | _getKeyCode(e) {
method _handleKeyDown (line 87) | _handleKeyDown(e) {
method _handleKeyUp (line 214) | _handleKeyUp(e) {
method _interruptAltGrSequence (line 248) | _interruptAltGrSequence() {
method _allKeysUp (line 256) | _allKeysUp() {
method grab (line 270) | grab() {
method ungrab (line 282) | ungrab() {
FILE: services/gateway/noVNC/core/input/keysymdef.js
method lookup (line 673) | lookup(u) {
FILE: services/gateway/noVNC/core/input/util.js
function getKeycode (line 9) | function getKeycode(evt) {
function getKey (line 68) | function getKey(evt) {
function getKeysym (line 111) | function getKeysym(evt) {
FILE: services/gateway/noVNC/core/ra2.js
class RA2Cipher (line 5) | class RA2Cipher {
method constructor (line 6) | constructor() {
method setKey (line 11) | async setKey(key) {
method makeMessage (line 16) | async makeMessage(message) {
method receiveMessage (line 30) | async receiveMessage(length, encrypted) {
class RSAAESAuthenticationState (line 42) | class RSAAESAuthenticationState extends EventTargetMixin {
method constructor (line 43) | constructor(sock, getCredentials) {
method _waitSockAsync (line 56) | _waitSockAsync(len) {
method _waitApproveKeyAsync (line 74) | _waitApproveKeyAsync() {
method _waitCredentialsAsync (line 81) | _waitCredentialsAsync(subtype) {
method checkInternalEvents (line 107) | checkInternalEvents() {
method approveServer (line 116) | approveServer() {
method disconnect (line 123) | disconnect() {
method negotiateRA2neAuthAsync (line 138) | async negotiateRA2neAuthAsync() {
method hasStarted (line 305) | get hasStarted() {
method hasStarted (line 309) | set hasStarted(s) {
FILE: services/gateway/noVNC/core/rfb.js
constant DISCONNECT_TIMEOUT (line 42) | const DISCONNECT_TIMEOUT = 3;
constant DEFAULT_BACKGROUND (line 43) | const DEFAULT_BACKGROUND = 'rgb(40, 40, 40)';
constant MOUSE_MOVE_DELAY (line 46) | const MOUSE_MOVE_DELAY = 17;
constant WHEEL_STEP (line 49) | const WHEEL_STEP = 50;
constant WHEEL_LINE_HEIGHT (line 50) | const WHEEL_LINE_HEIGHT = 19;
constant GESTURE_ZOOMSENS (line 53) | const GESTURE_ZOOMSENS = 75;
constant GESTURE_SCRLSENS (line 54) | const GESTURE_SCRLSENS = 50;
constant DOUBLE_TAP_TIMEOUT (line 55) | const DOUBLE_TAP_TIMEOUT = 1000;
constant DOUBLE_TAP_THRESHOLD (line 56) | const DOUBLE_TAP_THRESHOLD = 50;
class RFB (line 90) | class RFB extends EventTargetMixin {
method constructor (line 91) | constructor(target, urlOrChannel, options) {
method viewOnly (line 314) | get viewOnly() { return this._viewOnly; }
method viewOnly (line 315) | set viewOnly(viewOnly) {
method capabilities (line 328) | get capabilities() { return this._capabilities; }
method clippingViewport (line 330) | get clippingViewport() { return this._clippingViewport; }
method _setClippingViewport (line 331) | _setClippingViewport(on) {
method touchButton (line 340) | get touchButton() { return 0; }
method touchButton (line 341) | set touchButton(button) { Log.Warn("Using old API!"); }
method clipViewport (line 343) | get clipViewport() { return this._clipViewport; }
method clipViewport (line 344) | set clipViewport(viewport) {
method scaleViewport (line 349) | get scaleViewport() { return this._scaleViewport; }
method scaleViewport (line 350) | set scaleViewport(scale) {
method resizeSession (line 363) | get resizeSession() { return this._resizeSession; }
method resizeSession (line 364) | set resizeSession(resize) {
method showDotCursor (line 371) | get showDotCursor() { return this._showDotCursor; }
method showDotCursor (line 372) | set showDotCursor(show) {
method background (line 377) | get background() { return this._screen.style.background; }
method background (line 378) | set background(cssValue) { this._screen.style.background = cssValue; }
method qualityLevel (line 380) | get qualityLevel() {
method qualityLevel (line 383) | set qualityLevel(qualityLevel) {
method compressionLevel (line 400) | get compressionLevel() {
method compressionLevel (line 403) | set compressionLevel(compressionLevel) {
method disconnect (line 422) | disconnect() {
method approveServer (line 432) | approveServer() {
method sendCredentials (line 438) | sendCredentials(creds) {
method sendCtrlAltDel (line 443) | sendCtrlAltDel() {
method machineShutdown (line 455) | machineShutdown() {
method machineReboot (line 459) | machineReboot() {
method machineReset (line 463) | machineReset() {
method sendKey (line 469) | sendKey(keysym, code, down) {
method focus (line 496) | focus(options) {
method blur (line 500) | blur() {
method clipboardPasteFrom (line 504) | clipboardPasteFrom(text) {
method getImageData (line 540) | getImageData() {
method toDataURL (line 544) | toDataURL(type, encoderOptions) {
method toBlob (line 548) | toBlob(callback, type, quality) {
method _connect (line 554) | _connect() {
method _disconnect (line 612) | _disconnect() {
method _socketOpen (line 645) | _socketOpen() {
method _socketClose (line 656) | _socketClose(e) {
method _socketError (line 693) | _socketError(e) {
method _focusCanvas (line 697) | _focusCanvas(event) {
method _setDesktopName (line 705) | _setDesktopName(name) {
method _saveExpectedClientSize (line 712) | _saveExpectedClientSize() {
method _currentClientSize (line 717) | _currentClientSize() {
method _clientHasExpectedSize (line 721) | _clientHasExpectedSize() {
method _handleResize (line 728) | _handleResize() {
method _updateClip (line 748) | _updateClip() {
method _updateScale (line 780) | _updateScale() {
method _requestRemoteResize (line 792) | _requestRemoteResize() {
method _screenSize (line 835) | _screenSize() {
method _fixScrollbars (line 840) | _fixScrollbars() {
method _updateConnectionState (line 860) | _updateConnectionState(state) {
method _fail (line 959) | _fail(details) {
method _setCapability (line 983) | _setCapability(cap, val) {
method _handleMessage (line 989) | _handleMessage() {
method _handleKeyEvent (line 1025) | _handleKeyEvent(keysym, code, down, numlock, capslock) {
method _convertButtonMask (line 1057) | static _convertButtonMask(buttons) {
method _handleMouse (line 1087) | _handleMouse(ev) {
method _handleMouseButton (line 1176) | _handleMouseButton(x, y, bmask) {
method _handleMouseMove (line 1184) | _handleMouseMove(x, y) {
method _handleDelayedMouseMove (line 1203) | _handleDelayedMouseMove() {
method _sendMouse (line 1210) | _sendMouse(x, y, mask) {
method _handleWheel (line 1230) | _handleWheel(ev) {
method _fakeMouseMove (line 1287) | _fakeMouseMove(ev, elementX, elementY) {
method _handleTapEvent (line 1292) | _handleTapEvent(ev, bmask) {
method _handleGesture (line 1323) | _handleGesture(ev) {
method _flushMouseMoveTimer (line 1490) | _flushMouseMoveTimer(x, y) {
method _negotiateProtocolVersion (line 1500) | _negotiateProtocolVersion() {
method _isSupportedSecurityType (line 1553) | _isSupportedSecurityType(type) {
method _negotiateSecurity (line 1569) | _negotiateSecurity() {
method _handleSecurityReason (line 1620) | _handleSecurityReason() {
method _negotiateXvpAuth (line 1652) | _negotiateXvpAuth() {
method _negotiateVeNCryptAuth (line 1675) | _negotiateVeNCryptAuth() {
method _negotiatePlainAuth (line 1757) | _negotiatePlainAuth() {
method _negotiateStdVNCAuth (line 1779) | _negotiateStdVNCAuth() {
method _negotiateARDAuth (line 1798) | _negotiateARDAuth() {
method _negotiateARDAuthAsync (line 1839) | async _negotiateARDAuthAsync(keyLength, serverPublicKey, clientKey) {
method _negotiateTightUnixAuth (line 1868) | _negotiateTightUnixAuth() {
method _negotiateTightTunnels (line 1887) | _negotiateTightTunnels(numTunnels) {
method _negotiateTightAuth (line 1929) | _negotiateTightAuth() {
method _handleRSAAESCredentialsRequired (line 1995) | _handleRSAAESCredentialsRequired(event) {
method _handleRSAAESServerVerification (line 1999) | _handleRSAAESServerVerification(event) {
method _negotiateRA2neAuth (line 2003) | _negotiateRA2neAuth() {
method _negotiateMSLogonIIAuth (line 2033) | _negotiateMSLogonIIAuth() {
method _negotiateAuthentication (line 2076) | _negotiateAuthentication() {
method _handleSecurityResult (line 2119) | _handleSecurityResult() {
method _negotiateServerInit (line 2144) | _negotiateServerInit() {
method _sendEncodings (line 2232) | _sendEncodings() {
method _initMsg (line 2284) | _initMsg() {
method _resumeAuthentication (line 2318) | _resumeAuthentication() {
method _handleSetColourMapMsg (line 2324) | _handleSetColourMapMsg() {
method _handleServerCutText (line 2330) | _handleServerCutText() {
method _handleServerFenceMsg (line 2498) | _handleServerFenceMsg() {
method _handleXvpMsg (line 2540) | _handleXvpMsg() {
method _normalMsg (line 2563) | _normalMsg() {
method _framebufferUpdate (line 2621) | _framebufferUpdate() {
method _handleRect (line 2670) | _handleRect() {
method _handleVMwareCursor (line 2708) | _handleVMwareCursor() {
method _handleCursor (line 2824) | _handleCursor() {
method _handleDesktopName (line 2861) | _handleDesktopName() {
method _handleLedEvent (line 2880) | _handleLedEvent() {
method _handleExtendedDesktopSize (line 2895) | _handleExtendedDesktopSize() {
method _handleDataRect (line 2980) | _handleDataRect() {
method _updateContinuousUpdates (line 2999) | _updateContinuousUpdates() {
method _resize (line 3007) | _resize(width, height) {
method _xvpOp (line 3023) | _xvpOp(ver, op) {
method _updateCursor (line 3029) | _updateCursor(rgba, hotx, hoty, w, h) {
method _shouldShowDotCursor (line 3037) | _shouldShowDotCursor() {
method _refreshCursor (line 3059) | _refreshCursor() {
method genDES (line 3071) | static genDES(password, challenge) {
method keyEvent (line 3081) | keyEvent(sock, keysym, down) {
method QEMUExtendedKeyEvent (line 3092) | QEMUExtendedKeyEvent(sock, keysym, down, keycode) {
method pointerEvent (line 3116) | pointerEvent(sock, x, y, mask) {
method extendedPointerEvent (line 3131) | extendedPointerEvent(sock, x, y, mask) {
method _buildExtendedClipboardFlags (line 3153) | _buildExtendedClipboardFlags(actions, formats) {
method extendedClipboardProvide (line 3174) | extendedClipboardProvide(sock, formats, inData) {
method extendedClipboardNotify (line 3212) | extendedClipboardNotify(sock, formats) {
method extendedClipboardRequest (line 3218) | extendedClipboardRequest(sock, formats) {
method extendedClipboardCaps (line 3224) | extendedClipboardCaps(sock, actions, formats) {
method clientCutText (line 3247) | clientCutText(sock, data, extended = false) {
method setDesktopSize (line 3266) | setDesktopSize(sock, width, height, id, flags) {
method clientFence (line 3289) | clientFence(sock, flags, payload) {
method enableContinuousUpdates (line 3304) | enableContinuousUpdates(sock, enable, x, y, width, height) {
method pixelFormat (line 3317) | pixelFormat(sock, depth, trueColor) {
method clientEncodings (line 3356) | clientEncodings(sock, encodings) {
method fbUpdateRequest (line 3369) | fbUpdateRequest(sock, incremental, x, y, w, h) {
method xvpOp (line 3385) | xvpOp(sock, ver, op) {
FILE: services/gateway/noVNC/core/util/browser.js
function _checkWebCodecsH264DecodeSupport (line 76) | async function _checkWebCodecsH264DecodeSupport() {
function isMac (line 163) | function isMac() {
function isWindows (line 167) | function isWindows() {
function isIOS (line 171) | function isIOS() {
function isAndroid (line 177) | function isAndroid() {
function isChromeOS (line 182) | function isChromeOS() {
function isSafari (line 189) | function isSafari() {
function isFirefox (line 196) | function isFirefox() {
function isChrome (line 201) | function isChrome() {
function isChromium (line 208) | function isChromium() {
function isOpera (line 212) | function isOpera() {
function isEdge (line 216) | function isEdge() {
function isGecko (line 222) | function isGecko() {
function isWebKit (line 226) | function isWebKit() {
function isBlink (line 231) | function isBlink() {
FILE: services/gateway/noVNC/core/util/cursor.js
class Cursor (line 11) | class Cursor {
method constructor (line 12) | constructor() {
method attach (line 40) | attach(target) {
method detach (line 60) | detach() {
method change (line 80) | change(rgba, hotx, hoty, w, h) {
method clear (line 108) | clear() {
method move (line 120) | move(clientX, clientY) {
method _handleMouseOver (line 139) | _handleMouseOver(event) {
method _handleMouseLeave (line 146) | _handleMouseLeave(event) {
method _handleMouseMove (line 151) | _handleMouseMove(event) {
method _handleMouseUp (line 160) | _handleMouseUp(event) {
method _showCursor (line 191) | _showCursor() {
method _hideCursor (line 197) | _hideCursor() {
method _shouldShowCursor (line 206) | _shouldShowCursor(target) {
method _updateVisibility (line 227) | _updateVisibility(target) {
method _updatePosition (line 240) | _updatePosition() {
method _captureIsActive (line 245) | _captureIsActive() {
FILE: services/gateway/noVNC/core/util/element.js
function clientToElement (line 13) | function clientToElement(x, y, elem) {
FILE: services/gateway/noVNC/core/util/events.js
function getPointerEvent (line 13) | function getPointerEvent(e) {
function stopEvent (line 17) | function stopEvent(e) {
function _captureProxy (line 26) | function _captureProxy(e) {
function _capturedElemChanged (line 56) | function _capturedElemChanged() {
function setCapture (line 63) | function setCapture(target) {
function releaseCapture (line 110) | function releaseCapture() {
FILE: services/gateway/noVNC/core/util/eventtarget.js
class EventTargetMixin (line 9) | class EventTargetMixin {
method constructor (line 10) | constructor() {
method addEventListener (line 14) | addEventListener(type, callback) {
method removeEventListener (line 21) | removeEventListener(type, callback) {
method dispatchEvent (line 27) | dispatchEvent(event) {
FILE: services/gateway/noVNC/core/util/int.js
function toUnsigned32bit (line 9) | function toUnsigned32bit(toConvert) {
function toSigned32bit (line 13) | function toSigned32bit(toConvert) {
FILE: services/gateway/noVNC/core/util/logging.js
function initLogging (line 20) | function initLogging(level) {
function getLogging (line 49) | function getLogging() {
FILE: services/gateway/noVNC/core/util/strings.js
function decodeUTF8 (line 10) | function decodeUTF8(utf8string, allowLatin1=false) {
function encodeUTF8 (line 26) | function encodeUTF8(DOMString) {
FILE: services/gateway/noVNC/core/websock.js
constant MAX_RQ_GROW_SIZE (line 20) | const MAX_RQ_GROW_SIZE = 40 * 1024 * 1024;
class Websock (line 50) | class Websock {
method constructor (line 51) | constructor() {
method readyState (line 75) | get readyState() {
method rQpeek8 (line 98) | rQpeek8() {
method rQskipBytes (line 102) | rQskipBytes(bytes) {
method rQshift8 (line 106) | rQshift8() {
method rQshift16 (line 110) | rQshift16() {
method rQshift32 (line 114) | rQshift32() {
method _rQshift (line 119) | _rQshift(bytes) {
method rQshiftStr (line 127) | rQshiftStr(len) {
method rQshiftBytes (line 137) | rQshiftBytes(len, copy=true) {
method rQshiftTo (line 146) | rQshiftTo(target, len) {
method rQpeekBytes (line 152) | rQpeekBytes(len, copy=true) {
method rQwait (line 163) | rQwait(msg, num, goback) {
method sQpush8 (line 178) | sQpush8(num) {
method sQpush16 (line 183) | sQpush16(num) {
method sQpush32 (line 189) | sQpush32(num) {
method sQpushString (line 197) | sQpushString(str) {
method sQpushBytes (line 202) | sQpushBytes(bytes) {
method flush (line 217) | flush() {
method _sQensureSpace (line 224) | _sQensureSpace(bytes) {
method off (line 231) | off(evt) {
method on (line 235) | on(evt, handler) {
method _allocateBuffers (line 239) | _allocateBuffers() {
method init (line 244) | init() {
method open (line 250) | open(uri, protocols) {
method attach (line 254) | attach(rawChannel) {
method close (line 293) | close() {
method _expandCompactRQ (line 312) | _expandCompactRQ(minFit) {
method _recvMessage (line 345) | _recvMessage(e) {
FILE: services/gateway/noVNC/karma.conf.js
function SafariBrowser (line 4) | function SafariBrowser(id, baseBrowserDecorator, args) {
FILE: services/gateway/noVNC/tests/assertions.js
function _equal (line 12) | function _equal(a, b) {
FILE: services/gateway/noVNC/tests/fake.websocket.js
class FakeWebSocket (line 3) | class FakeWebSocket {
method constructor (line 4) | constructor(uri, protocols) {
method close (line 27) | close(code, reason) {
method send (line 34) | send(data) {
method _getSentData (line 53) | _getSentData() {
method _open (line 59) | _open() {
method _receiveData (line 66) | _receiveData(data) {
FILE: services/gateway/noVNC/tests/playback-ui.js
function message (line 9) | function message(str) {
function loadFile (line 15) | function loadFile() {
function enableUI (line 33) | function enableUI() {
class IterationPlayer (line 103) | class IterationPlayer {
method constructor (line 104) | constructor(iterations, frames) {
method start (line 121) | start(realtime) {
method _nextIteration (line 130) | _nextIteration() {
method _finish (line 145) | _finish() {
method _iterationFinish (line 156) | _iterationFinish(duration) {
method _disconnected (line 166) | _disconnected(clean, frame) {
function start (line 180) | function start() {
FILE: services/gateway/noVNC/tests/playback.js
class FakeWebSocket (line 45) | class FakeWebSocket {
method constructor (line 46) | constructor() {
method send (line 56) | send() {
method close (line 59) | close() {
class RecordingPlayer (line 63) | class RecordingPlayer {
method constructor (line 64) | constructor(frames, disconnected) {
method run (line 82) | run(realtime, trafficManagement) {
method _queueNextPacket (line 103) | _queueNextPacket() {
method _doPacket (line 131) | _doPacket() {
method _finish (line 149) | _finish() {
method _handleDisconnect (line 161) | _handleDisconnect(evt) {
method _handleCredentials (line 166) | _handleCredentials(evt) {
FILE: services/gateway/noVNC/tests/test.copyrect.js
function testDecodeRect (line 8) | function testDecodeRect(decoder, x, y, width, height, data, display, dep...
FILE: services/gateway/noVNC/tests/test.deflator.js
function _inflator (line 5) | function _inflator(compText, expected) {
FILE: services/gateway/noVNC/tests/test.display.js
function makeImageCanvas (line 14) | function makeImageCanvas(inputData, width, height) {
function makeImagePng (line 24) | function makeImagePng(inputData, width, height) {
FILE: services/gateway/noVNC/tests/test.gesturehandler.js
class DummyTarget (line 5) | class DummyTarget extends EventTargetMixin {
function touchStart (line 41) | function touchStart(id, x, y) {
function touchMove (line 54) | function touchMove(id, x, y) {
function touchEnd (line 67) | function touchEnd(id) {
FILE: services/gateway/noVNC/tests/test.h264.js
function createSolidColorFrameBuffer (line 33) | function createSolidColorFrameBuffer(color, width, height) {
function makeMessageHeader (line 52) | function makeMessageHeader(length, resetContext, resetAllContexts) {
function wrapRectData (line 77) | function wrapRectData(data, resetContext, resetAllContexts) {
function testDecodeRect (line 82) | function testDecodeRect(decoder, x, y, width, height, data, display, dep...
function almost (line 106) | function almost(a, b) {
FILE: services/gateway/noVNC/tests/test.hextile.js
function testDecodeRect (line 8) | function testDecodeRect(decoder, x, y, width, height, data, display, dep...
function push32 (line 32) | function push32(arr, num) {
FILE: services/gateway/noVNC/tests/test.inflator.js
function _deflator (line 5) | function _deflator(data) {
FILE: services/gateway/noVNC/tests/test.jpeg.js
function testDecodeRect (line 8) | function testDecodeRect(decoder, x, y, width, height, data, display, dep...
function almost (line 147) | function almost(a, b) {
function almost (line 282) | function almost(a, b) {
FILE: services/gateway/noVNC/tests/test.keyboard.js
function keyevent (line 8) | function keyevent(typeArg, KeyboardEventInit) {
FILE: services/gateway/noVNC/tests/test.raw.js
function testDecodeRect (line 8) | function testDecodeRect(decoder, x, y, width, height, data, display, dep...
FILE: services/gateway/noVNC/tests/test.rfb.js
function push8 (line 13) | function push8(arr, num) {
function push16 (line 18) | function push16(arr, num) {
function push32 (line 24) | function push32(arr, num) {
function pushString (line 32) | function pushString(arr, string) {
function deflateWithSize (line 39) | function deflateWithSize(data) {
class FakeResizeObserver (line 79) | class FakeResizeObserver {
method constructor (line 80) | constructor(handler) {
method disconnect (line 84) | disconnect() {}
method observe (line 85) | observe(target, options) {}
method unobserve (line 86) | unobserve(target) {}
function makeRFB (line 150) | function makeRFB(url, options) {
function elementToClient (line 161) | function elementToClient(x, y, client) {
function sendMouseMoveEvent (line 179) | function sendMouseMoveEvent(x, y, buttons, client) {
function sendMouseButtonEvent (line 192) | function sendMouseButtonEvent(x, y, down, buttons, client) {
function gestureStart (line 205) | function gestureStart(gestureType, x, y, client,
function gestureMove (line 217) | function gestureMove(gestureType, x, y, client,
function gestureEnd (line 229) | function gestureEnd(gestureType, x, y, client) {
function sendFbuMsg (line 236) | function sendFbuMsg(rectInfo, rectData, client, rectCnt) {
function sendExtendedDesktopSize (line 260) | function sendExtendedDesktopSize(client, reason, result, width, height, ...
function sendVer (line 1395) | function sendVer(ver, client) {
function sendSecurity (line 1405) | function sendSecurity(type, cl) {
function fakeGetRandomValues (line 1652) | function fakeGetRandomValues(arr) {
function fakeGeneratekey (line 1694) | async function fakeGeneratekey() {
function fakeGetRandomValues (line 2098) | function fakeGetRandomValues(arr) {
function fakeGetRandomValues (line 2190) | function fakeGetRandomValues(arr) {
function sendNumStrPairs (line 2327) | function sendNumStrPairs(pairs, client) {
function sendServerInit (line 2659) | function sendServerInit(opts, client) {
function makeScreenData (line 2901) | function makeScreenData(nrOfScreens) {
function sendLedStateUpdate (line 3304) | function sendLedStateUpdate(state) {
function sendWheelEvent (line 4068) | function sendWheelEvent(x, y, dx, dy, mode=0, buttons=0) {
FILE: services/gateway/noVNC/tests/test.rre.js
function testDecodeRect (line 8) | function testDecodeRect(decoder, x, y, width, height, data, display, dep...
function push16 (line 32) | function push16(arr, num) {
function push32 (line 37) | function push32(arr, num) {
FILE: services/gateway/noVNC/tests/test.tight.js
function testDecodeRect (line 8) | function testDecodeRect(decoder, x, y, width, height, data, display, dep...
function almost (line 472) | function almost(a, b) {
FILE: services/gateway/noVNC/tests/test.tightpng.js
function testDecodeRect (line 8) | function testDecodeRect(decoder, x, y, width, height, data, display, dep...
function almost (line 135) | function almost(a, b) {
FILE: services/gateway/noVNC/tests/test.webutil.js
method get (line 172) | get(cb) { cb(settings); }
method set (line 173) | set() {}
method remove (line 174) | remove() {}
FILE: services/gateway/noVNC/tests/test.zlib.js
function testDecodeRect (line 8) | function testDecodeRect(decoder, x, y, width, height, data, display, dep...
FILE: services/gateway/noVNC/tests/test.zrle.js
function testDecodeRect (line 8) | function testDecodeRect(decoder, x, y, width, height, data, display, dep...
FILE: services/gateway/noVNC/utils/convert.js
function promisify (line 23) | function promisify(original) {
function walkDir (line 46) | function walkDir(basePath, cb, filter) {
function makeLibFiles (line 61) | function makeLibFiles(sourceMaps) {
FILE: services/gateway/noVNC/utils/genkeysymdef.js
function toHex (line 80) | function toHex(num) {
FILE: services/gateway/noVNC/vendor/pako/lib/utils/common.js
function shrinkBuf (line 2) | function shrinkBuf (buf, size) {
function arraySet (line 10) | function arraySet (dest, src, src_offs, len, dest_offs) {
function flattenChunks (line 22) | function flattenChunks (chunks) {
FILE: services/gateway/noVNC/vendor/pako/lib/zlib/adler32.js
function adler32 (line 5) | function adler32(adler, buf, len, pos) {
FILE: services/gateway/noVNC/vendor/pako/lib/zlib/crc32.js
function makeTable (line 7) | function makeTable() {
function crc32 (line 25) | function crc32(crc, buf, len, pos) {
FILE: services/gateway/noVNC/vendor/pako/lib/zlib/deflate.js
constant Z_NO_FLUSH (line 12) | const Z_NO_FLUSH = 0;
constant Z_PARTIAL_FLUSH (line 13) | const Z_PARTIAL_FLUSH = 1;
constant Z_FULL_FLUSH (line 15) | const Z_FULL_FLUSH = 3;
constant Z_FINISH (line 16) | const Z_FINISH = 4;
constant Z_BLOCK (line 17) | const Z_BLOCK = 5;
constant Z_OK (line 24) | const Z_OK = 0;
constant Z_STREAM_END (line 25) | const Z_STREAM_END = 1;
constant Z_STREAM_ERROR (line 28) | const Z_STREAM_ERROR = -2;
constant Z_DATA_ERROR (line 29) | const Z_DATA_ERROR = -3;
constant Z_BUF_ERROR (line 31) | const Z_BUF_ERROR = -5;
constant Z_DEFAULT_COMPRESSION (line 39) | const Z_DEFAULT_COMPRESSION = -1;
constant Z_FILTERED (line 42) | const Z_FILTERED = 1;
constant Z_HUFFMAN_ONLY (line 43) | const Z_HUFFMAN_ONLY = 2;
constant Z_RLE (line 44) | const Z_RLE = 3;
constant Z_FIXED (line 45) | const Z_FIXED = 4;
constant Z_DEFAULT_STRATEGY (line 46) | const Z_DEFAULT_STRATEGY = 0;
constant Z_UNKNOWN (line 52) | const Z_UNKNOWN = 2;
constant Z_DEFLATED (line 56) | const Z_DEFLATED = 8;
function err (line 104) | function err(strm, errorCode) {
function rank (line 109) | function rank(f) {
function zero (line 113) | function zero(buf) { var len = buf.length; while (--len >= 0) { buf[len]...
function flush_pending (line 122) | function flush_pending(strm) {
function flush_block_only (line 144) | function flush_block_only(s, last) {
function put_byte (line 151) | function put_byte(s, b) {
function putShortMSB (line 161) | function putShortMSB(s, b) {
function read_buf (line 176) | function read_buf(strm, buf, start, size) {
function longest_match (line 210) | function longest_match(s, cur_match) {
function fill_window (line 323) | function fill_window(s) {
function deflate_stored (line 479) | function deflate_stored(s, flush) {
function deflate_fast (line 577) | function deflate_fast(s, flush) {
function deflate_slow (line 705) | function deflate_slow(s, flush) {
function deflate_rle (line 867) | function deflate_rle(s, flush) {
function deflate_huff (line 962) | function deflate_huff(s, flush) {
function Config (line 1019) | function Config(good_length, max_lazy, nice_length, max_chain, func) {
function lm_init (line 1048) | function lm_init(s) {
function DeflateState (line 1071) | function DeflateState() {
function deflateResetKeep (line 1260) | function deflateResetKeep(strm) {
function deflateReset (line 1289) | function deflateReset(strm) {
function deflateSetHeader (line 1298) | function deflateSetHeader(strm, head) {
function deflateInit2 (line 1306) | function deflateInit2(strm, level, method, windowBits, memLevel, strateg...
function deflateInit (line 1384) | function deflateInit(strm, level) {
function deflate (line 1389) | function deflate(strm, flush) {
function deflateEnd (line 1723) | function deflateEnd(strm) {
function deflateSetDictionary (line 1752) | function deflateSetDictionary(strm, dictionary) {
FILE: services/gateway/noVNC/vendor/pako/lib/zlib/gzheader.js
function GZheader (line 1) | function GZheader() {
FILE: services/gateway/noVNC/vendor/pako/lib/zlib/inffast.js
function inflate_fast (line 40) | function inflate_fast(strm, start) {
FILE: services/gateway/noVNC/vendor/pako/lib/zlib/inflate.js
constant Z_FINISH (line 20) | const Z_FINISH = 4;
constant Z_BLOCK (line 21) | const Z_BLOCK = 5;
constant Z_TREES (line 22) | const Z_TREES = 6;
constant Z_OK (line 28) | const Z_OK = 0;
constant Z_STREAM_END (line 29) | const Z_STREAM_END = 1;
constant Z_NEED_DICT (line 30) | const Z_NEED_DICT = 2;
constant Z_STREAM_ERROR (line 32) | const Z_STREAM_ERROR = -2;
constant Z_DATA_ERROR (line 33) | const Z_DATA_ERROR = -3;
constant Z_MEM_ERROR (line 34) | const Z_MEM_ERROR = -4;
constant Z_BUF_ERROR (line 35) | const Z_BUF_ERROR = -5;
constant Z_DEFLATED (line 39) | const Z_DEFLATED = 8;
function zswap32 (line 92) | function zswap32(q) {
function InflateState (line 100) | function InflateState() {
function inflateResetKeep (line 158) | function inflateResetKeep(strm) {
function inflateReset (line 185) | function inflateReset(strm) {
function inflateReset2 (line 197) | function inflateReset2(strm, windowBits) {
function inflateInit2 (line 231) | function inflateInit2(strm, windowBits) {
function inflateInit (line 251) | function inflateInit(strm) {
function fixedtables (line 270) | function fixedtables(state) {
function updatewindow (line 318) | function updatewindow(strm, src, end, copy) {
function inflate (line 360) | function inflate(strm, flush) {
function inflateEnd (line 1452) | function inflateEnd(strm) {
function inflateGetHeader (line 1466) | function inflateGetHeader(strm, head) {
function inflateSetDictionary (line 1480) | function inflateSetDictionary(strm, dictionary) {
FILE: services/gateway/noVNC/vendor/pako/lib/zlib/inftrees.js
function inflate_table (line 34) | function inflate_table(type, lens, lens_index, codes, table, table_index...
FILE: services/gateway/noVNC/vendor/pako/lib/zlib/trees.js
function zero (line 22) | function zero(buf) { var len = buf.length; while (--len >= 0) { buf[len]...
function StaticTreeDesc (line 145) | function StaticTreeDesc(static_tree, extra_bits, extra_base, elems, max_...
function TreeDesc (line 163) | function TreeDesc(dyn_tree, stat_desc) {
function d_code (line 171) | function d_code(dist) {
function put_short (line 180) | function put_short(s, w) {
function send_bits (line 192) | function send_bits(s, value, length) {
function send_code (line 205) | function send_code(s, c, tree) {
function bi_reverse (line 215) | function bi_reverse(code, len) {
function bi_flush (line 229) | function bi_flush(s) {
function gen_bitlen (line 253) | function gen_bitlen(s, desc)
function gen_codes (line 350) | function gen_codes(tree, max_code, bl_count)
function tr_static_init (line 388) | function tr_static_init() {
function init_block (line 492) | function init_block(s) {
function bi_windup (line 509) | function bi_windup(s)
function copy_block (line 525) | function copy_block(s, buf, len, header)
function smaller (line 548) | function smaller(tree, n, m, depth) {
function pqdownheap (line 561) | function pqdownheap(s, tree, k)
function compress_block (line 594) | function compress_block(s, ltree, dtree)
function build_tree (line 654) | function build_tree(s, desc)
function scan_tree (line 750) | function scan_tree(s, tree, max_code)
function send_tree (line 816) | function send_tree(s, tree, max_code)
function build_bl_tree (line 887) | function build_bl_tree(s) {
function send_all_trees (line 923) | function send_all_trees(s, lcodes, dcodes, blcodes)
function detect_data_type (line 963) | function detect_data_type(s) {
function _tr_init (line 1001) | function _tr_init(s)
function _tr_stored_block (line 1024) | function _tr_stored_block(s, buf, stored_len, last)
function _tr_align (line 1039) | function _tr_align(s) {
function _tr_flush_block (line 1050) | function _tr_flush_block(s, buf, stored_len, last)
function _tr_tally (line 1137) | function _tr_tally(s, dist, lc)
FILE: services/gateway/noVNC/vendor/pako/lib/zlib/zstream.js
function ZStream (line 1) | function ZStream() {
Condensed preview — 568 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,730K chars).
[
{
"path": ".gitignore",
"chars": 811,
"preview": "# Local .terraform directories\n**/.terraform/*\n\n# .tfstate files\n*.tfstate\n*.tfstate.*\n\n# Crash log files\ncrash.log\ncras"
},
{
"path": "LICENSE",
"chars": 10245,
"preview": "Apache License\nVersion 2.0, January 2004\nhttp://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AN"
},
{
"path": "README.md",
"chars": 6206,
"preview": "<p align=\"center\">\n <img src=\"assets/cyberdesk-logo-with-text.png\" width=\"400\" alt=\"Cyberdesk Logo\" />\n</p>\n\n<p align=\""
},
{
"path": "apps/api/.dockerignore",
"chars": 59,
"preview": "/.git\n/node_modules\n.dockerignore\n.env\nDockerfile\nfly.toml\n"
},
{
"path": "apps/api/.gitignore",
"chars": 362,
"preview": "# prod\ndist/\n\n# dev\n.yarn/\n!.yarn/releases\n.vscode/*\n!.vscode/launch.json\n!.vscode/*.code-snippets\n.idea/workspace.xml\n."
},
{
"path": "apps/api/Dockerfile",
"chars": 926,
"preview": "# syntax = docker/dockerfile:1\n\n# Adjust NODE_VERSION as desired\nARG NODE_VERSION=20.18.0\nFROM node:${NODE_VERSION}-slim"
},
{
"path": "apps/api/README.md",
"chars": 1774,
"preview": "# Created by Unkey's toolbox\n\nThis API is built with speed, and security in mind. The API is built with [Hono](https://h"
},
{
"path": "apps/api/drizzle/migrations/0000_oval_outlaw_kid.sql",
"chars": 472,
"preview": "CREATE TABLE IF NOT EXISTS \"desktop_instances\" (\n\t\"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,\n\t\"user_id\" u"
},
{
"path": "apps/api/drizzle/migrations/0001_busy_warstar.sql",
"chars": 68,
"preview": "ALTER TABLE \"desktop_instances\" ADD COLUMN \"remote_id\" varchar(255);"
},
{
"path": "apps/api/drizzle/migrations/0002_regular_doctor_faustus.sql",
"chars": 741,
"preview": "CREATE TABLE IF NOT EXISTS \"profiles\" (\n\t\"id\" uuid PRIMARY KEY NOT NULL,\n\t\"unkey_key_id\" varchar(255),\n\t\"stripe_customer"
},
{
"path": "apps/api/drizzle/migrations/0003_superb_betty_brant.sql",
"chars": 79,
"preview": "ALTER TABLE \"desktop_instances\" ADD COLUMN \"stream_url\" varchar(1024) NOT NULL;"
},
{
"path": "apps/api/drizzle/migrations/0004_simple_komodo.sql",
"chars": 117,
"preview": "ALTER TABLE \"desktop_instances\" ALTER COLUMN \"stream_url\" SET DEFAULT 'https://placeholder-stream-url.cyberdesk.dev';"
},
{
"path": "apps/api/drizzle/migrations/0005_mighty_hiroim.sql",
"chars": 696,
"preview": "ALTER TABLE \"desktop_instances\" DROP CONSTRAINT \"desktop_instances_user_id_users_id_fk\";\n--> statement-breakpoint\nALTER "
},
{
"path": "apps/api/drizzle/migrations/0006_icy_black_bird.sql",
"chars": 815,
"preview": "DO $$ BEGIN\n CREATE TYPE \"public\".\"instance_status\" AS ENUM('pending', 'running', 'completed', 'error');\nEXCEPTION\n WHEN"
},
{
"path": "apps/api/drizzle/migrations/0007_panoramic_tomorrow_man.sql",
"chars": 52,
"preview": "ALTER TYPE \"instance_status\" ADD VALUE 'terminated';"
},
{
"path": "apps/api/drizzle/migrations/meta/0000_snapshot.json",
"chars": 1577,
"preview": "{\n \"id\": \"1816b590-90c5-4f05-9726-cc8f33d18251\",\n \"prevId\": \"00000000-0000-0000-0000-000000000000\",\n \"version\": \"6\",\n"
},
{
"path": "apps/api/drizzle/migrations/meta/0001_snapshot.json",
"chars": 1734,
"preview": "{\n \"id\": \"61aff1d0-bd56-4301-852c-bc67c46a1cd9\",\n \"prevId\": \"1816b590-90c5-4f05-9726-cc8f33d18251\",\n \"version\": \"6\",\n"
},
{
"path": "apps/api/drizzle/migrations/meta/0002_snapshot.json",
"chars": 4052,
"preview": "{\n \"id\": \"4d86e969-3e44-4e26-bb6d-b76b9daa733e\",\n \"prevId\": \"61aff1d0-bd56-4301-852c-bc67c46a1cd9\",\n \"version\": \"6\",\n"
},
{
"path": "apps/api/drizzle/migrations/meta/0003_snapshot.json",
"chars": 4211,
"preview": "{\n \"id\": \"9b509c40-ab3f-410b-ac01-9401df6598c2\",\n \"prevId\": \"4d86e969-3e44-4e26-bb6d-b76b9daa733e\",\n \"version\": \"6\",\n"
},
{
"path": "apps/api/drizzle/migrations/meta/0004_snapshot.json",
"chars": 4281,
"preview": "{\n \"id\": \"36e12ff1-cb7e-46bd-bdc4-796464df0849\",\n \"prevId\": \"9b509c40-ab3f-410b-ac01-9401df6598c2\",\n \"version\": \"6\",\n"
},
{
"path": "apps/api/drizzle/migrations/meta/0005_snapshot.json",
"chars": 4277,
"preview": "{\n \"id\": \"0efe305c-c062-4173-bc2d-8d92af93250f\",\n \"prevId\": \"36e12ff1-cb7e-46bd-bdc4-796464df0849\",\n \"version\": \"6\",\n"
},
{
"path": "apps/api/drizzle/migrations/meta/0006_snapshot.json",
"chars": 6385,
"preview": "{\n \"id\": \"1f1576f8-a386-4198-a4b4-dbe02dbc8468\",\n \"prevId\": \"0efe305c-c062-4173-bc2d-8d92af93250f\",\n \"version\": \"6\",\n"
},
{
"path": "apps/api/drizzle/migrations/meta/0007_snapshot.json",
"chars": 6386,
"preview": "{\n \"id\": \"39ccedc0-27c0-448a-971b-3217e72e8dfe\",\n \"prevId\": \"1f1576f8-a386-4198-a4b4-dbe02dbc8468\",\n \"version\": \"6\",\n"
},
{
"path": "apps/api/drizzle/migrations/meta/_journal.json",
"chars": 1219,
"preview": "{\n \"version\": \"5\",\n \"dialect\": \"postgresql\",\n \"entries\": [\n {\n \"idx\": 0,\n \"version\": \"6\",\n \"when\": "
},
{
"path": "apps/api/drizzle.config.ts",
"chars": 271,
"preview": "import { defineConfig } from \"drizzle-kit\";\n\nexport default defineConfig({\n schema: \"./src/db/supabase.ts\",\n schemaFil"
},
{
"path": "apps/api/fly.toml",
"chars": 501,
"preview": "# fly.toml app configuration file generated for cyberdesk-mvp-backend on 2025-03-27T05:00:43Z\n#\n# See https://fly.io/doc"
},
{
"path": "apps/api/package.json",
"chars": 1143,
"preview": "{\n \"name\": \"api\",\n \"type\": \"module\",\n \"scripts\": {\n \"build\": \"tsc\",\n \"dev\": \"tsx watch src/index.ts\",\n \"star"
},
{
"path": "apps/api/src/db/dbActions.ts",
"chars": 3363,
"preview": "import { eq, and, sql } from \"drizzle-orm\";\nimport type { PostgresJsDatabase } from \"drizzle-orm/postgres-js\";\nimport { "
},
{
"path": "apps/api/src/db/index.ts",
"chars": 999,
"preview": "import { drizzle } from \"drizzle-orm/postgres-js\";\nimport postgres from \"postgres\";\nimport type { PostgresJsDatabase } f"
},
{
"path": "apps/api/src/db/schema.ts",
"chars": 2731,
"preview": "import { pgTable, serial, text, index, varchar, uuid, timestamp, pgSchema, jsonb, boolean, pgEnum } from \"drizzle-orm/pg"
},
{
"path": "apps/api/src/index.ts",
"chars": 656,
"preview": "import { newApp } from \"./lib/hono.js\";\nimport desktop from \"./routes/desktop.js\";\nimport { serve } from \"@hono/node-ser"
},
{
"path": "apps/api/src/lib/cache.ts",
"chars": 654,
"preview": "import { createCache, type Cache as C} from \"@unkey/cache\";\nimport { MemoryStore } from \"@unkey/cache/stores\";\n\nimport t"
},
{
"path": "apps/api/src/lib/errors.ts",
"chars": 3643,
"preview": "import { type Context, type Next } from 'hono';\nimport { HTTPException } from 'hono/http-exception';\nimport { ZodError }"
},
{
"path": "apps/api/src/lib/hono.ts",
"chars": 2153,
"preview": "import { OpenAPIHono, z } from \"@hono/zod-openapi\";\nimport type { UnkeyContext } from \"@unkey/hono\";\nimport type { Ratel"
},
{
"path": "apps/api/src/lib/posthog.ts",
"chars": 482,
"preview": "import { PostHog } from 'posthog-node'\nimport * as dotenv from 'dotenv';\n\n// Ensure environment variables are loaded\ndot"
},
{
"path": "apps/api/src/lib/ratelimit.ts",
"chars": 465,
"preview": "import { Ratelimit } from \"@unkey/ratelimit\";\nimport type { Context, Middleware } from \"./hono.js\";\nimport type { Next }"
},
{
"path": "apps/api/src/routes/desktop.ts",
"chars": 15793,
"preview": "import { OpenAPIHono } from \"@hono/zod-openapi\";\nimport { env } from 'hono/adapter';\nimport { unkey, type UnkeyContext }"
},
{
"path": "apps/api/src/schema/desktop.ts",
"chars": 11890,
"preview": "import { createRoute, z } from \"@hono/zod-openapi\";\n\nimport { openApiErrorResponses } from \"./errors.js\";\nimport { Insta"
},
{
"path": "apps/api/src/schema/errors.ts",
"chars": 2691,
"preview": "import { z } from \"@hono/zod-openapi\";\n\nconst errorSchema = z.object({\n status: z.literal(\"error\").openapi({ example: \""
},
{
"path": "apps/api/src/schema/gateway.ts",
"chars": 556,
"preview": "import { z } from 'zod';\n\n// Schema for Gateway Execute Command Request\nexport const GatewayExecuteCommandRequestSchema "
},
{
"path": "apps/api/tsconfig.json",
"chars": 442,
"preview": "{\n \"compilerOptions\": {\n \"target\": \"ESNext\",\n \"module\": \"esnext\",\n \"moduleResolution\": \"bundler\",\n \"strict\""
},
{
"path": "apps/docs/.gitignore",
"chars": 472,
"preview": "# Dependencies\nnode_modules/\n.pnp\n.pnp.js\n\n# Build outputs\n.next/\nout/\nbuild/\ndist/\n.cache/\n\n# Generated files\n.docusaur"
},
{
"path": "apps/docs/.map.ts",
"chars": 81,
"preview": "/** Auto-generated **/\ndeclare const map: Record<string, unknown>\n\nexport { map }"
},
{
"path": "apps/docs/README.md",
"chars": 567,
"preview": "# docs\n\nThis is a Next.js application generated with\n[Create Fumadocs](https://github.com/fuma-nama/fumadocs).\n\nRun deve"
},
{
"path": "apps/docs/app/api/search/route.ts",
"chars": 327,
"preview": "import { getPages } from \"@/app/source\";\nimport { createSearchAPI } from \"fumadocs-core/search/server\";\n\nexport const { "
},
{
"path": "apps/docs/app/docs/[[...slug]]/page.tsx",
"chars": 935,
"preview": "import { getPage, getPages } from \"@/app/source\";\nimport { DocsBody, DocsPage } from \"fumadocs-ui/page\";\nimport type { M"
},
{
"path": "apps/docs/app/docs/layout.tsx",
"chars": 352,
"preview": "import { DocsLayout } from \"fumadocs-ui/layout\";\nimport type { ReactNode } from \"react\";\n\nimport { baseOptions } from \"."
},
{
"path": "apps/docs/app/global.css",
"chars": 59,
"preview": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n"
},
{
"path": "apps/docs/app/layout.config.tsx",
"chars": 416,
"preview": "import { type BaseLayoutProps } from \"fumadocs-ui/layout\";\n\n// basic configuration here\nexport const baseOptions: BaseLa"
},
{
"path": "apps/docs/app/layout.tsx",
"chars": 557,
"preview": "import \"./global.css\";\n\nimport { RootProvider } from \"fumadocs-ui/provider\";\nimport { Inter } from \"next/font/google\";\ni"
},
{
"path": "apps/docs/app/page.tsx",
"chars": 105,
"preview": "import { redirect } from 'next/navigation';\n\nexport default function HomePage() {\n redirect('/docs');\n}\n"
},
{
"path": "apps/docs/app/source.ts",
"chars": 257,
"preview": "import { map } from \"@/.map\";\nimport { loader } from \"fumadocs-core/source\";\nimport { createMDXSource } from \"fumadocs-m"
},
{
"path": "apps/docs/content/docs/api-reference.mdx",
"chars": 39137,
"preview": "---\ntitle: API Reference\ndescription: API for Cyberdesk, to create, control, and manage virtual desktop instances.\nfull:"
},
{
"path": "apps/docs/content/docs/conceptual-guide.mdx",
"chars": 6950,
"preview": "---\ntitle: Conceptual Guide\ndescription: Understanding core concepts of Cyberdesk\n---\nUnderstanding the core concepts of"
},
{
"path": "apps/docs/content/docs/index.mdx",
"chars": 2792,
"preview": "---\ntitle: Cyberdesk Documentation\ndescription: Comprehensive documentation for Cyberdesk service\n---\n\nWelcome to the of"
},
{
"path": "apps/docs/content/docs/introduction.mdx",
"chars": 2611,
"preview": "---\ntitle: Introduction\ndescription: Introduction to Cyberdesk\n---\nCyberdesk provides a seamless way to create and inter"
},
{
"path": "apps/docs/content/docs/meta.json",
"chars": 172,
"preview": "{\n \"title\": \"Docs\",\n \"pages\": [\"index\", \"introduction\", \"quickstart\", \"tutorials\", \"conceptual-guide\", \"api-refere"
},
{
"path": "apps/docs/content/docs/quickstart.mdx",
"chars": 8497,
"preview": "---\ntitle: Quickstart\ndescription: Get started quickly with Cyberdesk\n---\nimport { Tab, Tabs } from 'fumadocs-ui/compone"
},
{
"path": "apps/docs/content/docs/tutorials.mdx",
"chars": 16612,
"preview": "---\ntitle: Tutorials\ndescription: Step-by-step tutorials for using the Cyberdesk TypeScript SDK\n---\nLearn how to use the"
},
{
"path": "apps/docs/mdx-components.tsx",
"chars": 238,
"preview": "import defaultComponents from \"fumadocs-ui/mdx\";\nimport type { MDXComponents } from \"mdx/types\";\n\nexport function useMDX"
},
{
"path": "apps/docs/next-env.d.ts",
"chars": 228,
"preview": "/// <reference types=\"next\" />\n/// <reference types=\"next/image-types/global\" />\n\n// NOTE: This file should not be edite"
},
{
"path": "apps/docs/next.config.mjs",
"chars": 195,
"preview": "import createMDX from \"fumadocs-mdx/config\";\n\nconst withMDX = createMDX();\n\n/** @type {import('next').NextConfig} */\ncon"
},
{
"path": "apps/docs/package.json",
"chars": 797,
"preview": "{\n \"name\": \"docs\",\n \"version\": \"0.0.0\",\n \"private\": true,\n \"scripts\": {\n \"generate\": \"node scripts/generate-docs."
},
{
"path": "apps/docs/postcss.config.js",
"chars": 83,
"preview": "module.exports = {\n plugins: {\n tailwindcss: {},\n autoprefixer: {},\n },\n};\n"
},
{
"path": "apps/docs/scripts/generate-docs.mjs",
"chars": 572,
"preview": "import * as path from \"node:path\";\nimport * as OpenAPI from \"fumadocs-openapi\";\nimport * as Typescript from \"fumadocs-ty"
},
{
"path": "apps/docs/tailwind.config.js",
"chars": 1243,
"preview": "import { createPreset } from 'fumadocs-ui/tailwind-plugin';\n\n/** @type {import('tailwindcss').Config} */\nexport default "
},
{
"path": "apps/docs/tsconfig.json",
"chars": 661,
"preview": "{\n \"compilerOptions\": {\n \"baseUrl\": \".\",\n \"target\": \"ESNext\",\n \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n \""
},
{
"path": "apps/web/.eslintrc.json",
"chars": 279,
"preview": "{\n \"parser\": \"@typescript-eslint/parser\",\n \"plugins\": [\"@typescript-eslint\"],\n \"extends\": [\n \"next/core-web-vitals"
},
{
"path": "apps/web/.gitignore",
"chars": 424,
"preview": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pn"
},
{
"path": "apps/web/LICENSE.md",
"chars": 9400,
"preview": "# Tailwind Plus License\n\n## Personal License\n\nTailwind Labs Inc. grants you an on-going, non-exclusive license to use th"
},
{
"path": "apps/web/README.md",
"chars": 1458,
"preview": "## Getting started\n\nTo get started with this template, first install the npm dependencies:\n\n```bash\nnpm install\n```\n\nNex"
},
{
"path": "apps/web/components.json",
"chars": 434,
"preview": "{\n \"$schema\": \"https://ui.shadcn.com/schema.json\",\n \"style\": \"new-york\",\n \"rsc\": true,\n \"tsx\": true,\n \"tailwind\": {"
},
{
"path": "apps/web/config.ts",
"chars": 112,
"preview": "const CONFIG = {\n docsURL: 'https://docs.cyberdesk.io',\n subscriptionLimit: 1000\n}\n\nexport default CONFIG;"
},
{
"path": "apps/web/middleware.ts",
"chars": 604,
"preview": "import { type NextRequest } from 'next/server'\nimport { updateSession } from '@/utils/supabase/middleware'\n\nexport async"
},
{
"path": "apps/web/next.config.mjs",
"chars": 609,
"preview": "/** @type {import('next').NextConfig} */\nconst nextConfig = {\n reactStrictMode: true,\n async rewrites() {\n return ["
},
{
"path": "apps/web/package.json",
"chars": 2369,
"preview": "{\n \"name\": \"web\",\n \"version\": \"0.1.0\",\n \"private\": true,\n \"scripts\": {\n \"dev\": \"next dev\",\n \"build\": \"next bui"
},
{
"path": "apps/web/postcss.config.js",
"chars": 71,
"preview": "module.exports = {\n plugins: {\n '@tailwindcss/postcss': {},\n },\n}\n"
},
{
"path": "apps/web/prettier.config.js",
"chars": 261,
"preview": "/** @type {import('prettier').Options} */\nmodule.exports = {\n singleQuote: true,\n semi: false,\n plugins: ['prettier-p"
},
{
"path": "apps/web/radiant/.gitignore",
"chars": 420,
"preview": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# Dependencies\n/node_modules\n/.pn"
},
{
"path": "apps/web/radiant/README.md",
"chars": 510,
"preview": "# Sanity Clean Content Studio\n\nCongratulations, you have now installed the Sanity Content Studio, an open-source real-ti"
},
{
"path": "apps/web/radiant/eslint.config.mjs",
"chars": 78,
"preview": "import studio from '@sanity/eslint-config-studio'\n\nexport default [...studio]\n"
},
{
"path": "apps/web/radiant/package.json",
"chars": 800,
"preview": "{\n \"name\": \"radiant\",\n \"private\": true,\n \"version\": \"1.0.0\",\n \"main\": \"package.json\",\n \"license\": \"UNLICENSED\",\n \""
},
{
"path": "apps/web/radiant/sanity.cli.ts",
"chars": 281,
"preview": "import {defineCliConfig} from 'sanity/cli'\n\nexport default defineCliConfig({\n api: {\n projectId: '4hdczeqj',\n dat"
},
{
"path": "apps/web/radiant/sanity.config.ts",
"chars": 378,
"preview": "import {defineConfig} from 'sanity'\nimport {structureTool} from 'sanity/structure'\nimport {visionTool} from '@sanity/vis"
},
{
"path": "apps/web/radiant/schemaTypes/index.ts",
"chars": 30,
"preview": "export const schemaTypes = []\n"
},
{
"path": "apps/web/radiant/static/.gitkeep",
"chars": 81,
"preview": "Files placed here will be served by the Sanity server under the `/static`-prefix\n"
},
{
"path": "apps/web/radiant/tsconfig.json",
"chars": 417,
"preview": "{\n \"compilerOptions\": {\n \"target\": \"ES2017\",\n \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n \"allowJs\": true,\n "
},
{
"path": "apps/web/sanity-typegen.json",
"chars": 124,
"preview": "{\n \"path\": \"./src/**/*.{ts,tsx,js,jsx}\",\n \"schema\": \"./src/sanity/extract.json\",\n \"generates\": \"./src/sanity/types.ts"
},
{
"path": "apps/web/sanity.cli.ts",
"chars": 226,
"preview": "import { defineCliConfig } from 'sanity/cli'\n\nconst projectId = process.env.NEXT_PUBLIC_SANITY_PROJECT_ID\nconst dataset "
},
{
"path": "apps/web/sanity.config.ts",
"chars": 424,
"preview": "'use client'\n\nimport { visionTool } from '@sanity/vision'\nimport { defineConfig } from 'sanity'\nimport { structureTool }"
},
{
"path": "apps/web/src/app/api/playground/chat/route.ts",
"chars": 2066,
"preview": "import { anthropic } from \"@ai-sdk/anthropic\";\nimport { streamText, type UIMessage } from \"ai\";\nimport { prunedMessages "
},
{
"path": "apps/web/src/app/api/playground/kill-desktop/route.ts",
"chars": 953,
"preview": "import client from \"@/utils/playground/cyberdesk-client\";\n\n// Common handler for both GET and POST requests\nasync functi"
},
{
"path": "apps/web/src/app/api/stripe/checkout/route.ts",
"chars": 1114,
"preview": "import { stripe, STRIPE_PRICE_ID } from '@/utils/stripe/stripe-server';\nimport { NextRequest, NextResponse } from 'next/"
},
{
"path": "apps/web/src/app/api/stripe/portal/route.ts",
"chars": 841,
"preview": "import { stripe } from '@/utils/stripe/stripe-server';\nimport { NextRequest, NextResponse } from 'next/server';\n\nexport "
},
{
"path": "apps/web/src/app/api/stripe/webhook/route.ts",
"chars": 11564,
"preview": "import { stripe } from '@/utils/stripe/stripe-server';\nimport { headers } from 'next/headers';\nimport { NextRequest, Nex"
},
{
"path": "apps/web/src/app/api/unkey/route.ts",
"chars": 5670,
"preview": "import { NextResponse } from 'next/server';\nimport { createClient } from '@/utils/supabase/server';\n\n// Unkey API endpoi"
},
{
"path": "apps/web/src/app/auth/callback/route.ts",
"chars": 1897,
"preview": "import { createClient } from '@/utils/supabase/server'\nimport { NextRequest, NextResponse } from 'next/server'\nimport Po"
},
{
"path": "apps/web/src/app/blog/[slug]/page.tsx",
"chars": 7748,
"preview": "import { Button } from '@/components/button'\nimport { Container } from '@/components/container'\nimport { Footer } from '"
},
{
"path": "apps/web/src/app/blog/feed.xml/route.ts",
"chars": 1831,
"preview": "import { image } from '@/sanity/image'\nimport { getPostsForFeed } from '@/sanity/queries'\nimport { Feed } from 'feed'\nim"
},
{
"path": "apps/web/src/app/blog/page.tsx",
"chars": 10151,
"preview": "import { Button } from '@/components/button'\nimport { Container } from '@/components/container'\nimport { Footer } from '"
},
{
"path": "apps/web/src/app/company/page.tsx",
"chars": 18273,
"preview": "import { AnimatedNumber } from '@/components/animated-number'\nimport { Button } from '@/components/button'\nimport { Cont"
},
{
"path": "apps/web/src/app/dashboard/dashboard-content.tsx",
"chars": 4006,
"preview": "'use client'\n\nimport { SubscriptionSection } from '@/components/dashboard/subscription-section'\nimport type { Profile } "
},
{
"path": "apps/web/src/app/dashboard/page.tsx",
"chars": 2296,
"preview": "import { redirect } from 'next/navigation';\nimport { stripe } from '@/utils/stripe/stripe-server';\nimport type { Profile"
},
{
"path": "apps/web/src/app/demo/page.tsx",
"chars": 3647,
"preview": "'use client'\n\nimport { DemoSection } from '@/components/demo-section'\nimport { Thread } from '@/components/thread'\nimpor"
},
{
"path": "apps/web/src/app/layout.tsx",
"chars": 939,
"preview": "import '@/styles/tailwind.css'\nimport type { Metadata } from 'next'\nimport { PostHogProvider } from '../components/PostH"
},
{
"path": "apps/web/src/app/login/login-form.d.ts",
"chars": 87,
"preview": "// Type declaration for login-form component\nexport function LoginForm(): JSX.Element;\n"
},
{
"path": "apps/web/src/app/login/login-form.tsx",
"chars": 4307,
"preview": "'use client';\n\nimport { Button } from '@/components/button'\nimport { Link } from '@/components/link'\nimport { Mark } fro"
},
{
"path": "apps/web/src/app/login/page.tsx",
"chars": 622,
"preview": "import { GradientBackground } from '@/components/gradient'\nimport type { Metadata } from 'next'\nimport { LoginForm } fro"
},
{
"path": "apps/web/src/app/page.tsx",
"chars": 654,
"preview": "import { Footer } from '@/components/footer'\nimport type { Metadata } from 'next'\nimport { Hero } from '../components/he"
},
{
"path": "apps/web/src/app/playground/page.tsx",
"chars": 14726,
"preview": "\"use client\";\n\nimport { PreviewMessage } from \"@/components/playground/message\";\nimport { getDesktopURL, startDesktop } "
},
{
"path": "apps/web/src/app/pricing/page.tsx",
"chars": 11820,
"preview": "import { Button } from '@/components/button'\nimport { Container } from '@/components/container'\nimport { Footer } from '"
},
{
"path": "apps/web/src/app/privacy/page.tsx",
"chars": 7289,
"preview": "import { Container } from '@/components/container'\nimport { Footer } from '@/components/footer'\nimport { Gradient, Gradi"
},
{
"path": "apps/web/src/app/studio/[[...tool]]/page.tsx",
"chars": 637,
"preview": "/**\n * This route is responsible for the built-in authoring environment using Sanity Studio.\n * All routes under your st"
},
{
"path": "apps/web/src/app/terms/page.tsx",
"chars": 5713,
"preview": "import { Container } from '@/components/container'\nimport { Footer } from '@/components/footer'\nimport { Gradient, Gradi"
},
{
"path": "apps/web/src/components/LogoText.tsx",
"chars": 466,
"preview": "import React from 'react';\nimport { cn } from '@/utils/misc-utils'; // Assuming you use shadcn/ui or similar for utils\n\n"
},
{
"path": "apps/web/src/components/PostHogProvider.tsx",
"chars": 1298,
"preview": "\"use client\"\n\nimport posthog from \"posthog-js\"\nimport { PostHogProvider as PHProvider, usePostHog } from \"posthog-js/rea"
},
{
"path": "apps/web/src/components/animated-number.tsx",
"chars": 705,
"preview": "'use client'\n\nimport {\n motion,\n useInView,\n useMotionValue,\n useSpring,\n useTransform,\n} from 'framer-motion'\nimpo"
},
{
"path": "apps/web/src/components/bento-card.tsx",
"chars": 1698,
"preview": "'use client'\n\nimport { clsx } from 'clsx'\nimport { motion } from 'framer-motion'\nimport { Subheading } from './text'\n\nex"
},
{
"path": "apps/web/src/components/bento-section.tsx",
"chars": 2763,
"preview": "import { BentoCard } from '@/components/bento-card'\nimport { Container } from '@/components/container'\nimport { Keyboard"
},
{
"path": "apps/web/src/components/button.tsx",
"chars": 1670,
"preview": "import * as Headless from '@headlessui/react'\nimport { clsx } from 'clsx'\nimport { Link } from './link'\n\nconst variants "
},
{
"path": "apps/web/src/components/container.tsx",
"chars": 294,
"preview": "import { clsx } from 'clsx'\n\nexport function Container({\n className,\n children,\n}: {\n className?: string\n children: "
},
{
"path": "apps/web/src/components/dark-bento-section.tsx",
"chars": 2614,
"preview": "import { BentoCard } from '@/components/bento-card'\nimport { Container } from '@/components/container'\nimport { LinkedAv"
},
{
"path": "apps/web/src/components/dashboard/api-key-manager.tsx",
"chars": 8961,
"preview": "'use client'\n\nimport { useState, useEffect } from 'react'\nimport { Button } from '@/components/button'\nimport { Clipboar"
},
{
"path": "apps/web/src/components/dashboard/api-key-section.tsx",
"chars": 6766,
"preview": "'use client'\n\nimport { useState, useEffect } from 'react'\nimport { Button } from '@/components/button'\nimport { CheckIco"
},
{
"path": "apps/web/src/components/dashboard/dashboard-layout.tsx",
"chars": 770,
"preview": "'use client'\n\nimport { useState, type ReactNode } from 'react'\nimport { MobileSidebar } from './mobile-sidebar'\nimport {"
},
{
"path": "apps/web/src/components/dashboard/desktop-sidebar.tsx",
"chars": 4061,
"preview": "'use client'\n\nimport { navigation, classNames } from './sidebar-navigation'\nimport { AppLogo } from '@/components/shared"
},
{
"path": "apps/web/src/components/dashboard/faq-section.tsx",
"chars": 3244,
"preview": "import { Disclosure, DisclosureButton, DisclosurePanel } from '@headlessui/react'\nimport { MinusSmallIcon, PlusSmallIcon"
},
{
"path": "apps/web/src/components/dashboard/mobile-header.tsx",
"chars": 1043,
"preview": "'use client'\n\nimport { Bars3Icon } from '@heroicons/react/24/outline'\n\ninterface MobileHeaderProps {\n setSidebarOpen: ("
},
{
"path": "apps/web/src/components/dashboard/mobile-sidebar.tsx",
"chars": 4577,
"preview": "'use client'\n\nimport { Dialog, DialogBackdrop, DialogPanel, TransitionChild } from '@headlessui/react'\nimport { XMarkIco"
},
{
"path": "apps/web/src/components/dashboard/sidebar-navigation.tsx",
"chars": 1256,
"preview": "'use client'\n\nimport {\n HomeIcon,\n DocumentTextIcon,\n} from '@heroicons/react/24/outline'\nimport CONFIG from '../../.."
},
{
"path": "apps/web/src/components/dashboard/subscription-section.tsx",
"chars": 3515,
"preview": "'use client'\n\nimport type { Profile } from '@/types/database'\nimport { SubscriptionManagement } from '@/components/strip"
},
{
"path": "apps/web/src/components/dashboard/vm-instances-manager.tsx",
"chars": 8663,
"preview": "'use client'\n\nimport { useState, useEffect } from 'react'\nimport { ComputerDesktopIcon, ArrowPathIcon } from '@heroicons"
},
{
"path": "apps/web/src/components/demo-section.tsx",
"chars": 14055,
"preview": "'use client'\n\nimport { Button } from '@/components/button'\nimport { supabase } from '@/utils/supabase/client'\nimport { C"
},
{
"path": "apps/web/src/components/feature-section.tsx",
"chars": 609,
"preview": "import { Container } from '@/components/container'\nimport { Heading } from '@/components/text'\nimport { Screenshot } fro"
},
{
"path": "apps/web/src/components/footer.tsx",
"chars": 6691,
"preview": "'use client'\nimport { PlusGrid, PlusGridItem, PlusGridRow } from '@/components/plus-grid'\nimport { Button } from './butt"
},
{
"path": "apps/web/src/components/gradient.tsx",
"chars": 777,
"preview": "import { clsx } from 'clsx'\n\nexport function Gradient({\n className,\n ...props\n}: React.ComponentPropsWithoutRef<'div'>"
},
{
"path": "apps/web/src/components/hero.tsx",
"chars": 2997,
"preview": "'use client';\n\nimport { Button } from '@/components/button'\nimport { Container } from '@/components/container'\nimport { "
},
{
"path": "apps/web/src/components/keyboard.tsx",
"chars": 98996,
"preview": "'use client'\n\nimport { clsx } from 'clsx'\nimport { motion } from 'framer-motion'\nimport { createContext, useContext } fr"
},
{
"path": "apps/web/src/components/link.tsx",
"chars": 410,
"preview": "import * as Headless from '@headlessui/react'\nimport NextLink, { type LinkProps } from 'next/link'\nimport { forwardRef }"
},
{
"path": "apps/web/src/components/linked-avatars.tsx",
"chars": 2347,
"preview": "'use client'\n\nimport { CheckIcon } from '@heroicons/react/16/solid'\nimport { clsx } from 'clsx'\nimport { motion } from '"
},
{
"path": "apps/web/src/components/logo-cloud.tsx",
"chars": 1016,
"preview": "import { clsx } from 'clsx'\n\nexport function LogoCloud({\n className,\n}: React.ComponentPropsWithoutRef<'div'>) {\n retu"
},
{
"path": "apps/web/src/components/logo-cluster.tsx",
"chars": 3671,
"preview": "'use client'\n\nimport { clsx } from 'clsx'\nimport { motion } from 'framer-motion'\nimport { Mark } from './logo'\n\nfunction"
},
{
"path": "apps/web/src/components/logo-timeline.tsx",
"chars": 4550,
"preview": "import { clsx } from 'clsx'\nimport { Mark } from './logo'\n\nfunction Row({ children }: { children: React.ReactNode }) {\n "
},
{
"path": "apps/web/src/components/logo.tsx",
"chars": 12427,
"preview": "'use client'\n\nimport { clsx } from 'clsx'\nimport { motion } from 'framer-motion'\n\nexport function Logo({ className }: { "
},
{
"path": "apps/web/src/components/map.tsx",
"chars": 1989,
"preview": "'use client'\n\nimport { motion } from 'framer-motion'\n\nfunction Marker({\n src,\n top,\n offset,\n delay,\n}: {\n src: str"
},
{
"path": "apps/web/src/components/markdown-text.tsx",
"chars": 4914,
"preview": "\"use client\";\n\nimport \"@assistant-ui/react-markdown/styles/dot.css\";\n\nimport {\n type CodeHeaderProps,\n MarkdownTextPri"
},
{
"path": "apps/web/src/components/navbar.tsx",
"chars": 8863,
"preview": "'use client'\n\nimport {\n Disclosure,\n DisclosureButton,\n DisclosurePanel,\n} from '@headlessui/react'\nimport { Bars2Ico"
},
{
"path": "apps/web/src/components/playground/chat-error.tsx",
"chars": 923,
"preview": "import React from \"react\";\nimport { FaExclamationTriangle } from \"react-icons/fa\";\n\nexport function ChatError({ error, o"
},
{
"path": "apps/web/src/components/playground/icons.tsx",
"chars": 7656,
"preview": "import Link from \"next/link\";\n\nexport const BotIcon = () => {\n return (\n <svg\n height=\"16\"\n strokeLinejoin"
},
{
"path": "apps/web/src/components/playground/input.tsx",
"chars": 2130,
"preview": "import { ArrowUp } from \"lucide-react\";\nimport { Input as ShadcnInput } from \"@/components/ui/input\";\n\ninterface InputPr"
},
{
"path": "apps/web/src/components/playground/markdown.tsx",
"chars": 2550,
"preview": "/* eslint-disable @typescript-eslint/no-unused-vars */\nimport Link from \"next/link\";\nimport React, { memo } from \"react\""
},
{
"path": "apps/web/src/components/playground/message.tsx",
"chars": 11905,
"preview": "\"use client\";\n\nimport type { Message } from \"ai\";\nimport { AnimatePresence, motion } from \"motion/react\";\nimport { memo "
},
{
"path": "apps/web/src/components/playground/project-info.tsx",
"chars": 1733,
"preview": "import { motion } from \"motion/react\";\nimport { VercelIcon } from \"@/components/playground/icons\";\nimport { ComputerIcon"
},
{
"path": "apps/web/src/components/playground/prompt-suggestions.tsx",
"chars": 1307,
"preview": "import { ArrowUpRight } from \"lucide-react\";\nimport { Button } from \"@/components/ui/button\";\n\nconst suggestions = [\n {"
},
{
"path": "apps/web/src/components/plus-grid.tsx",
"chars": 2259,
"preview": "import { clsx } from 'clsx'\n\nexport function PlusGrid({\n className = '',\n children,\n}: {\n className?: string\n childr"
},
{
"path": "apps/web/src/components/screenshot.tsx",
"chars": 726,
"preview": "import { clsx } from 'clsx'\n\nexport function Screenshot({\n width,\n height,\n src,\n className,\n}: {\n width: number\n "
},
{
"path": "apps/web/src/components/shared/app-logo.tsx",
"chars": 640,
"preview": "'use client'\n\nimport { Mark } from '@/components/logo'\nimport { clsx } from 'clsx'\n\nexport interface AppLogoProps {\n cl"
},
{
"path": "apps/web/src/components/stripe/checkout-button.tsx",
"chars": 3050,
"preview": "\"use client\";\n\nimport { useState } from 'react';\nimport { Button } from '@/components/button';\nimport type { User } from"
},
{
"path": "apps/web/src/components/stripe/client-pricing-card.tsx",
"chars": 2812,
"preview": "\"use client\";\n\nimport { useState } from 'react';\nimport { Button } from '@/components/button';\nimport { Subheading } fro"
},
{
"path": "apps/web/src/components/stripe/client-pricing-cards.tsx",
"chars": 5036,
"preview": "\"use client\";\n\nimport { Container } from '@/components/container';\nimport { Gradient } from '@/components/gradient';\nimp"
},
{
"path": "apps/web/src/components/stripe/payment-success.tsx",
"chars": 1042,
"preview": "import { Button } from '@/components/button';\nimport { Link } from '@/components/link';\nimport { CheckIcon } from '@hero"
},
{
"path": "apps/web/src/components/stripe/subscription-management.tsx",
"chars": 1370,
"preview": "\"use client\";\nimport { Button } from '@/components/button';\nimport { useState } from 'react';\n\ninterface SubscriptionMan"
},
{
"path": "apps/web/src/components/testimonials.tsx",
"chars": 7695,
"preview": "'use client'\n\nimport * as Headless from '@headlessui/react'\nimport { ArrowLongRightIcon } from '@heroicons/react/20/soli"
},
{
"path": "apps/web/src/components/text.tsx",
"chars": 1155,
"preview": "import { clsx } from 'clsx'\n\ntype HeadingProps = {\n as?: 'div' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'\n dark?: boole"
},
{
"path": "apps/web/src/components/thread-list.tsx",
"chars": 1992,
"preview": "import type { FC } from \"react\";\nimport {\n ThreadListItemPrimitive,\n ThreadListPrimitive,\n} from \"@assistant-ui/react\""
},
{
"path": "apps/web/src/components/thread.tsx",
"chars": 9088,
"preview": "import {\n ActionBarPrimitive,\n BranchPickerPrimitive,\n ComposerPrimitive,\n MessagePrimitive,\n ThreadPrimitive,\n} fr"
},
{
"path": "apps/web/src/components/tooltip-icon-button.tsx",
"chars": 1147,
"preview": "\"use client\";\n\nimport { type ComponentPropsWithoutRef, forwardRef } from \"react\";\n\nimport {\n Tooltip,\n TooltipContent,"
},
{
"path": "apps/web/src/components/ui/button.tsx",
"chars": 2245,
"preview": "import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class"
},
{
"path": "apps/web/src/components/ui/input.tsx",
"chars": 956,
"preview": "import * as React from \"react\"\n\nimport { cn } from \"@/utils/misc-utils\"\n\nfunction Input({ className, type, ...props }: R"
},
{
"path": "apps/web/src/components/ui/resizable.tsx",
"chars": 2035,
"preview": "\"use client\"\n\nimport * as React from \"react\"\nimport { GripVerticalIcon } from \"lucide-react\"\nimport * as ResizablePrimit"
},
{
"path": "apps/web/src/components/ui/sonner.tsx",
"chars": 880,
"preview": "\"use client\"\n\nimport { useTheme } from \"next-themes\"\nimport { Toaster as Sonner, type ToasterProps } from \"sonner\"\n\ncons"
},
{
"path": "apps/web/src/components/ui/tooltip.tsx",
"chars": 1898,
"preview": "\"use client\"\n\nimport * as React from \"react\"\nimport * as TooltipPrimitive from \"@radix-ui/react-tooltip\"\n\nimport { cn } "
},
{
"path": "apps/web/src/components/yc-banner.tsx",
"chars": 785,
"preview": "import React from 'react'\n\nexport function YCBanner() {\n return (\n <div className=\"flex justify-center my-5\">\n "
},
{
"path": "apps/web/src/sanity/client.ts",
"chars": 672,
"preview": "import { createClient, type QueryParams } from 'next-sanity'\nimport { apiVersion, dataset, projectId } from './env'\n\ncon"
},
{
"path": "apps/web/src/sanity/env.ts",
"chars": 528,
"preview": "export const apiVersion =\n process.env.NEXT_PUBLIC_SANITY_API_VERSION || '2024-07-25'\n\nexport const dataset = assertVal"
},
{
"path": "apps/web/src/sanity/image.ts",
"chars": 335,
"preview": "import createImageUrlBuilder from '@sanity/image-url'\nimport type { SanityImageSource } from '@sanity/image-url/lib/type"
},
{
"path": "apps/web/src/sanity/queries.ts",
"chars": 2609,
"preview": "import { defineQuery } from 'next-sanity'\nimport { sanityFetch } from './client'\n\nconst TOTAL_POSTS_QUERY = defineQuery("
},
{
"path": "apps/web/src/sanity/schema.ts",
"chars": 368,
"preview": "import type { SchemaTypeDefinition } from 'sanity'\n\nimport { authorType } from './types/author'\nimport { blockContentTyp"
},
{
"path": "apps/web/src/sanity/types/author.ts",
"chars": 643,
"preview": "import { UserIcon } from '@heroicons/react/16/solid'\nimport { defineField, defineType } from 'sanity'\n\nexport const auth"
},
{
"path": "apps/web/src/sanity/types/block-content.ts",
"chars": 1605,
"preview": "import { ImageIcon } from '@sanity/icons'\nimport { defineArrayMember, defineType } from 'sanity'\n\nexport const blockCont"
},
{
"path": "apps/web/src/sanity/types/category.ts",
"chars": 406,
"preview": "import { TagIcon } from '@heroicons/react/16/solid'\nimport { defineField, defineType } from 'sanity'\n\nexport const categ"
},
{
"path": "apps/web/src/sanity/types/post.ts",
"chars": 2747,
"preview": "import { DocumentIcon } from '@heroicons/react/16/solid'\nimport { groq } from 'next-sanity'\nimport { defineField, define"
},
{
"path": "apps/web/src/sanity/types.ts",
"chars": 12609,
"preview": "/**\n * ---------------------------------------------------------------------------------\n * This file has been generated"
},
{
"path": "apps/web/src/styles/tailwind.css",
"chars": 4380,
"preview": "@import 'tailwindcss';\n@import \"tw-animate-css\";\n\n@custom-variant dark (&:is(.dark *));\n\n@theme {\n --font-sans: Switzer"
},
{
"path": "apps/web/src/types/database.ts",
"chars": 682,
"preview": "export interface Profile {\n id: string;\n unkey_key_id?: string;\n stripe_customer_id?: string;\n stripe_subscription_i"
},
{
"path": "apps/web/src/utils/misc-utils.ts",
"chars": 166,
"preview": "import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: Cla"
},
{
"path": "apps/web/src/utils/playground/cyberdesk-client.ts",
"chars": 245,
"preview": "import { createCyberdeskClient } from \"cyberdesk\";\n\nconst client = createCyberdeskClient({\n apiKey: process.env.CYBER"
},
{
"path": "apps/web/src/utils/playground/misc-demo-utils.ts",
"chars": 970,
"preview": "import type { UIMessage } from \"ai\";\nexport const ABORTED = \"User aborted\";\n\nexport const prunedMessages = (messages: UI"
},
{
"path": "apps/web/src/utils/playground/server-actions.ts",
"chars": 1341,
"preview": "\"use server\";\n\nimport client from \"@/utils/playground/cyberdesk-client\";\n\nexport const getDesktopURL = async (id?: strin"
},
{
"path": "apps/web/src/utils/playground/tools.ts",
"chars": 10677,
"preview": "import { anthropic } from \"@ai-sdk/anthropic\";\nimport client from \"@/utils/playground/cyberdesk-client\";\n\nconst wait = a"
},
{
"path": "apps/web/src/utils/playground/use-scroll-to-bottom.ts",
"chars": 1494,
"preview": "import { useEffect, useRef, type RefObject } from 'react';\n\nexport function useScrollToBottom(): [\n RefObject<HTMLDivEl"
},
{
"path": "apps/web/src/utils/posthog/posthog.ts",
"chars": 264,
"preview": "import { PostHog } from \"posthog-node\"\n\nexport default function PostHogClient() {\n const posthogClient = new PostHog(pr"
},
{
"path": "apps/web/src/utils/stripe/stripe-server.ts",
"chars": 554,
"preview": "import Stripe from 'stripe';\n\n// This file should only be imported in server components or API routes\nif (typeof window "
},
{
"path": "apps/web/src/utils/stripe/stripe.ts",
"chars": 202,
"preview": "// Helper function for client-side use\nexport const formatPrice = (price: number) => {\n return new Intl.NumberFormat('e"
},
{
"path": "apps/web/src/utils/stripe/tiers.ts",
"chars": 1765,
"preview": "// Define the tier type\nexport interface Tier {\n name: string;\n slug: string;\n description: string;\n priceMonthly: n"
},
{
"path": "apps/web/src/utils/supabase/client.ts",
"chars": 311,
"preview": "import { createBrowserClient } from '@supabase/ssr'\n\nexport function createClient() {\n return createBrowserClient(\n "
},
{
"path": "apps/web/src/utils/supabase/middleware.ts",
"chars": 2134,
"preview": "import { createServerClient } from '@supabase/ssr'\nimport { NextResponse, type NextRequest } from 'next/server'\n\nexport "
},
{
"path": "apps/web/src/utils/supabase/server.ts",
"chars": 788,
"preview": "import { createServerClient } from '@supabase/ssr'\nimport { cookies } from 'next/headers'\n\nexport function createClient("
},
{
"path": "apps/web/src/utils/supabase/supabaseClient.js",
"chars": 243,
"preview": "// supabaseClient.js\nimport { createBrowserClient } from '@supabase/ssr'\n\nexport function createClient() {\n return crea"
},
{
"path": "apps/web/src/utils/supabase/supabaseServerClient.ts",
"chars": 778,
"preview": "import { createServerClient } from '@supabase/ssr'\nimport { cookies } from 'next/headers'\n\nexport function createClient("
}
]
// ... and 368 more files (download for full content)
About this extraction
This page contains the full source code of the cyberdesk-hq/cyberdesk GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 568 files (3.4 MB), approximately 917.9k tokens, and a symbol index with 1907 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.