the universal sandbox runtime for agents and humans. pocketenv.io
sandbox openclaw agent claude-code vercel-sandbox deno-sandbox cloudflare-sandbox atproto sprites daytona
7
fork

Configure Feed

Select the types of activity you want to include in your feed.

Update sandbox schema, DB, and web

- Add ports array to sandbox lexicon and TypeScript types (ints 1–65535,
max 100)
- Add migration 0009 that provides base62_encode and sandbox_id() (sbx_
prefix)
- Add generated snapshot and journal entry for migration
- Add @xterm/xterm to web dependencies
- Minor web UI tweaks: Stop Sandbox button, AT Protocol link, and remove
unused import

+832 -3
+9
apps/api/lexicons/sandbox/defs.json
··· 61 61 "type": "integer", 62 62 "description": "Amount of disk space in GB allocated to the sandbox" 63 63 }, 64 + "ports": { 65 + "type": "array", 66 + "items": { 67 + "type": "integer", 68 + "maximum": 65535, 69 + "minimum": 1 70 + }, 71 + "maxLength": 100 72 + }, 64 73 "installs": { 65 74 "type": "integer", 66 75 "description": "Number of times the sandbox has been installed by users."
+9
apps/api/pkl/defs/sandbox/defs.pkl
··· 62 62 type = "integer" 63 63 description = "Amount of disk space in GB allocated to the sandbox" 64 64 } 65 + ["ports"] = new Array { 66 + type = "array" 67 + items = new IntegerType { 68 + type = "integer" 69 + minimum = 1 70 + maximum = 65535 71 + } 72 + maxLength = 100 73 + } 65 74 ["installs"] = new IntegerType { 66 75 type = "integer" 67 76 description = "Number of times the sandbox has been installed by users."
+9
apps/api/src/lexicon/lexicons.ts
··· 309 309 type: "integer", 310 310 description: "Amount of disk space in GB allocated to the sandbox", 311 311 }, 312 + ports: { 313 + type: "array", 314 + items: { 315 + type: "integer", 316 + maximum: 65535, 317 + minimum: 1, 318 + }, 319 + maxLength: 100, 320 + }, 312 321 installs: { 313 322 type: "integer", 314 323 description:
+1
apps/api/src/lexicon/types/io/pocketenv/sandbox/defs.ts
··· 27 27 memory?: number; 28 28 /** Amount of disk space in GB allocated to the sandbox */ 29 29 disk?: number; 30 + ports?: number[]; 30 31 /** Number of times the sandbox has been installed by users. */ 31 32 installs?: number; 32 33 createdAt?: string;
+34
apps/cf-sandbox/drizzle/0009_sticky_madame_masque.sql
··· 1 + CREATE EXTENSION IF NOT EXISTS pgcrypto; 2 + 3 + CREATE OR REPLACE FUNCTION base62_encode(data bytea) 4 + RETURNS text 5 + LANGUAGE plpgsql 6 + AS $$ 7 + DECLARE 8 + chars text := '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; 9 + num numeric := 0; 10 + result text := ''; 11 + remainder int; 12 + BEGIN 13 + -- convert bytea to numeric 14 + FOR i IN 0..length(data)-1 LOOP 15 + num := num * 256 + get_byte(data, i); 16 + END LOOP; 17 + 18 + -- convert numeric to base62 19 + WHILE num > 0 LOOP 20 + remainder := (num % 62)::int; 21 + result := substr(chars, remainder+1, 1) || result; 22 + num := floor(num / 62); 23 + END LOOP; 24 + 25 + RETURN result; 26 + END; 27 + $$; 28 + 29 + CREATE OR REPLACE FUNCTION sandbox_id() 30 + RETURNS text 31 + LANGUAGE sql 32 + AS $$ 33 + SELECT 'sbx_' || base62_encode(gen_random_bytes(16)); 34 + $$;
+732
apps/cf-sandbox/drizzle/meta/0009_snapshot.json
··· 1 + { 2 + "id": "d1c82d20-d1e2-4d46-8662-108d46349bb7", 3 + "prevId": "abd2ef17-5288-4dba-804d-72c62f3f1ca1", 4 + "version": "7", 5 + "dialect": "postgresql", 6 + "tables": { 7 + "public.authorized_keys": { 8 + "name": "authorized_keys", 9 + "schema": "", 10 + "columns": { 11 + "id": { 12 + "name": "id", 13 + "type": "text", 14 + "primaryKey": true, 15 + "notNull": true, 16 + "default": "xata_id()" 17 + }, 18 + "sandbox_id": { 19 + "name": "sandbox_id", 20 + "type": "text", 21 + "primaryKey": false, 22 + "notNull": false 23 + }, 24 + "public_key": { 25 + "name": "public_key", 26 + "type": "text", 27 + "primaryKey": false, 28 + "notNull": true 29 + }, 30 + "created_at": { 31 + "name": "created_at", 32 + "type": "timestamp", 33 + "primaryKey": false, 34 + "notNull": true, 35 + "default": "now()" 36 + } 37 + }, 38 + "indexes": {}, 39 + "foreignKeys": { 40 + "authorized_keys_sandbox_id_sandboxes_id_fk": { 41 + "name": "authorized_keys_sandbox_id_sandboxes_id_fk", 42 + "tableFrom": "authorized_keys", 43 + "tableTo": "sandboxes", 44 + "columnsFrom": [ 45 + "sandbox_id" 46 + ], 47 + "columnsTo": [ 48 + "id" 49 + ], 50 + "onDelete": "no action", 51 + "onUpdate": "no action" 52 + } 53 + }, 54 + "compositePrimaryKeys": {}, 55 + "uniqueConstraints": {}, 56 + "policies": {}, 57 + "checkConstraints": {}, 58 + "isRLSEnabled": false 59 + }, 60 + "public.sandbox_secrets": { 61 + "name": "sandbox_secrets", 62 + "schema": "", 63 + "columns": { 64 + "id": { 65 + "name": "id", 66 + "type": "text", 67 + "primaryKey": true, 68 + "notNull": true, 69 + "default": "xata_id()" 70 + }, 71 + "sandbox_id": { 72 + "name": "sandbox_id", 73 + "type": "text", 74 + "primaryKey": false, 75 + "notNull": true 76 + }, 77 + "secret_id": { 78 + "name": "secret_id", 79 + "type": "text", 80 + "primaryKey": false, 81 + "notNull": true 82 + } 83 + }, 84 + "indexes": { 85 + "unique_sandbox_secret": { 86 + "name": "unique_sandbox_secret", 87 + "columns": [ 88 + { 89 + "expression": "sandbox_id", 90 + "isExpression": false, 91 + "asc": true, 92 + "nulls": "last" 93 + }, 94 + { 95 + "expression": "secret_id", 96 + "isExpression": false, 97 + "asc": true, 98 + "nulls": "last" 99 + } 100 + ], 101 + "isUnique": true, 102 + "concurrently": false, 103 + "method": "btree", 104 + "with": {} 105 + } 106 + }, 107 + "foreignKeys": { 108 + "sandbox_secrets_sandbox_id_sandboxes_id_fk": { 109 + "name": "sandbox_secrets_sandbox_id_sandboxes_id_fk", 110 + "tableFrom": "sandbox_secrets", 111 + "tableTo": "sandboxes", 112 + "columnsFrom": [ 113 + "sandbox_id" 114 + ], 115 + "columnsTo": [ 116 + "id" 117 + ], 118 + "onDelete": "no action", 119 + "onUpdate": "no action" 120 + }, 121 + "sandbox_secrets_secret_id_secrets_id_fk": { 122 + "name": "sandbox_secrets_secret_id_secrets_id_fk", 123 + "tableFrom": "sandbox_secrets", 124 + "tableTo": "secrets", 125 + "columnsFrom": [ 126 + "secret_id" 127 + ], 128 + "columnsTo": [ 129 + "id" 130 + ], 131 + "onDelete": "no action", 132 + "onUpdate": "no action" 133 + } 134 + }, 135 + "compositePrimaryKeys": {}, 136 + "uniqueConstraints": {}, 137 + "policies": {}, 138 + "checkConstraints": {}, 139 + "isRLSEnabled": false 140 + }, 141 + "public.sandbox_variables": { 142 + "name": "sandbox_variables", 143 + "schema": "", 144 + "columns": { 145 + "id": { 146 + "name": "id", 147 + "type": "text", 148 + "primaryKey": true, 149 + "notNull": true, 150 + "default": "xata_id()" 151 + }, 152 + "sandbox_id": { 153 + "name": "sandbox_id", 154 + "type": "text", 155 + "primaryKey": false, 156 + "notNull": true 157 + }, 158 + "variable_id": { 159 + "name": "variable_id", 160 + "type": "text", 161 + "primaryKey": false, 162 + "notNull": true 163 + } 164 + }, 165 + "indexes": { 166 + "unique_sandbox_variables": { 167 + "name": "unique_sandbox_variables", 168 + "columns": [ 169 + { 170 + "expression": "sandbox_id", 171 + "isExpression": false, 172 + "asc": true, 173 + "nulls": "last" 174 + }, 175 + { 176 + "expression": "variable_id", 177 + "isExpression": false, 178 + "asc": true, 179 + "nulls": "last" 180 + } 181 + ], 182 + "isUnique": true, 183 + "concurrently": false, 184 + "method": "btree", 185 + "with": {} 186 + } 187 + }, 188 + "foreignKeys": { 189 + "sandbox_variables_sandbox_id_sandboxes_id_fk": { 190 + "name": "sandbox_variables_sandbox_id_sandboxes_id_fk", 191 + "tableFrom": "sandbox_variables", 192 + "tableTo": "sandboxes", 193 + "columnsFrom": [ 194 + "sandbox_id" 195 + ], 196 + "columnsTo": [ 197 + "id" 198 + ], 199 + "onDelete": "no action", 200 + "onUpdate": "no action" 201 + }, 202 + "sandbox_variables_variable_id_variables_id_fk": { 203 + "name": "sandbox_variables_variable_id_variables_id_fk", 204 + "tableFrom": "sandbox_variables", 205 + "tableTo": "variables", 206 + "columnsFrom": [ 207 + "variable_id" 208 + ], 209 + "columnsTo": [ 210 + "id" 211 + ], 212 + "onDelete": "no action", 213 + "onUpdate": "no action" 214 + } 215 + }, 216 + "compositePrimaryKeys": {}, 217 + "uniqueConstraints": {}, 218 + "policies": {}, 219 + "checkConstraints": {}, 220 + "isRLSEnabled": false 221 + }, 222 + "public.sandbox_volumes": { 223 + "name": "sandbox_volumes", 224 + "schema": "", 225 + "columns": { 226 + "id": { 227 + "name": "id", 228 + "type": "text", 229 + "primaryKey": true, 230 + "notNull": true, 231 + "default": "xata_id()" 232 + }, 233 + "sandbox_id": { 234 + "name": "sandbox_id", 235 + "type": "text", 236 + "primaryKey": false, 237 + "notNull": true 238 + }, 239 + "volume_id": { 240 + "name": "volume_id", 241 + "type": "text", 242 + "primaryKey": false, 243 + "notNull": true 244 + } 245 + }, 246 + "indexes": {}, 247 + "foreignKeys": { 248 + "sandbox_volumes_sandbox_id_sandboxes_id_fk": { 249 + "name": "sandbox_volumes_sandbox_id_sandboxes_id_fk", 250 + "tableFrom": "sandbox_volumes", 251 + "tableTo": "sandboxes", 252 + "columnsFrom": [ 253 + "sandbox_id" 254 + ], 255 + "columnsTo": [ 256 + "id" 257 + ], 258 + "onDelete": "no action", 259 + "onUpdate": "no action" 260 + }, 261 + "sandbox_volumes_volume_id_volumes_id_fk": { 262 + "name": "sandbox_volumes_volume_id_volumes_id_fk", 263 + "tableFrom": "sandbox_volumes", 264 + "tableTo": "volumes", 265 + "columnsFrom": [ 266 + "volume_id" 267 + ], 268 + "columnsTo": [ 269 + "id" 270 + ], 271 + "onDelete": "no action", 272 + "onUpdate": "no action" 273 + } 274 + }, 275 + "compositePrimaryKeys": {}, 276 + "uniqueConstraints": {}, 277 + "policies": {}, 278 + "checkConstraints": {}, 279 + "isRLSEnabled": false 280 + }, 281 + "public.sandboxes": { 282 + "name": "sandboxes", 283 + "schema": "", 284 + "columns": { 285 + "id": { 286 + "name": "id", 287 + "type": "text", 288 + "primaryKey": true, 289 + "notNull": true, 290 + "default": "sbx_id()" 291 + }, 292 + "base": { 293 + "name": "base", 294 + "type": "text", 295 + "primaryKey": false, 296 + "notNull": false 297 + }, 298 + "name": { 299 + "name": "name", 300 + "type": "text", 301 + "primaryKey": false, 302 + "notNull": true 303 + }, 304 + "display_name": { 305 + "name": "display_name", 306 + "type": "text", 307 + "primaryKey": false, 308 + "notNull": false 309 + }, 310 + "uri": { 311 + "name": "uri", 312 + "type": "text", 313 + "primaryKey": false, 314 + "notNull": false 315 + }, 316 + "provider": { 317 + "name": "provider", 318 + "type": "text", 319 + "primaryKey": false, 320 + "notNull": true, 321 + "default": "'cloudflare'" 322 + }, 323 + "description": { 324 + "name": "description", 325 + "type": "text", 326 + "primaryKey": false, 327 + "notNull": false 328 + }, 329 + "logo": { 330 + "name": "logo", 331 + "type": "text", 332 + "primaryKey": false, 333 + "notNull": false 334 + }, 335 + "readme": { 336 + "name": "readme", 337 + "type": "text", 338 + "primaryKey": false, 339 + "notNull": false 340 + }, 341 + "public_key": { 342 + "name": "public_key", 343 + "type": "text", 344 + "primaryKey": false, 345 + "notNull": true 346 + }, 347 + "user_id": { 348 + "name": "user_id", 349 + "type": "text", 350 + "primaryKey": false, 351 + "notNull": false 352 + }, 353 + "instance_type": { 354 + "name": "instance_type", 355 + "type": "text", 356 + "primaryKey": false, 357 + "notNull": false 358 + }, 359 + "vcpus": { 360 + "name": "vcpus", 361 + "type": "integer", 362 + "primaryKey": false, 363 + "notNull": false 364 + }, 365 + "memory": { 366 + "name": "memory", 367 + "type": "integer", 368 + "primaryKey": false, 369 + "notNull": false 370 + }, 371 + "disk": { 372 + "name": "disk", 373 + "type": "integer", 374 + "primaryKey": false, 375 + "notNull": false 376 + }, 377 + "status": { 378 + "name": "status", 379 + "type": "text", 380 + "primaryKey": false, 381 + "notNull": true 382 + }, 383 + "keep_alive": { 384 + "name": "keep_alive", 385 + "type": "boolean", 386 + "primaryKey": false, 387 + "notNull": true, 388 + "default": false 389 + }, 390 + "sleep_after": { 391 + "name": "sleep_after", 392 + "type": "text", 393 + "primaryKey": false, 394 + "notNull": false 395 + }, 396 + "sandbox_id": { 397 + "name": "sandbox_id", 398 + "type": "text", 399 + "primaryKey": false, 400 + "notNull": false 401 + }, 402 + "installs": { 403 + "name": "installs", 404 + "type": "integer", 405 + "primaryKey": false, 406 + "notNull": true, 407 + "default": 0 408 + }, 409 + "created_at": { 410 + "name": "created_at", 411 + "type": "timestamp", 412 + "primaryKey": false, 413 + "notNull": true, 414 + "default": "now()" 415 + }, 416 + "updated_at": { 417 + "name": "updated_at", 418 + "type": "timestamp", 419 + "primaryKey": false, 420 + "notNull": true, 421 + "default": "now()" 422 + } 423 + }, 424 + "indexes": {}, 425 + "foreignKeys": { 426 + "sandboxes_user_id_users_id_fk": { 427 + "name": "sandboxes_user_id_users_id_fk", 428 + "tableFrom": "sandboxes", 429 + "tableTo": "users", 430 + "columnsFrom": [ 431 + "user_id" 432 + ], 433 + "columnsTo": [ 434 + "id" 435 + ], 436 + "onDelete": "no action", 437 + "onUpdate": "no action" 438 + } 439 + }, 440 + "compositePrimaryKeys": {}, 441 + "uniqueConstraints": { 442 + "sandboxes_name_unique": { 443 + "name": "sandboxes_name_unique", 444 + "nullsNotDistinct": false, 445 + "columns": [ 446 + "name" 447 + ] 448 + }, 449 + "sandboxes_uri_unique": { 450 + "name": "sandboxes_uri_unique", 451 + "nullsNotDistinct": false, 452 + "columns": [ 453 + "uri" 454 + ] 455 + } 456 + }, 457 + "policies": {}, 458 + "checkConstraints": {}, 459 + "isRLSEnabled": false 460 + }, 461 + "public.secrets": { 462 + "name": "secrets", 463 + "schema": "", 464 + "columns": { 465 + "id": { 466 + "name": "id", 467 + "type": "text", 468 + "primaryKey": true, 469 + "notNull": true, 470 + "default": "secret_id()" 471 + }, 472 + "name": { 473 + "name": "name", 474 + "type": "text", 475 + "primaryKey": false, 476 + "notNull": true 477 + }, 478 + "value": { 479 + "name": "value", 480 + "type": "text", 481 + "primaryKey": false, 482 + "notNull": true 483 + }, 484 + "created_at": { 485 + "name": "created_at", 486 + "type": "timestamp", 487 + "primaryKey": false, 488 + "notNull": true, 489 + "default": "now()" 490 + } 491 + }, 492 + "indexes": {}, 493 + "foreignKeys": {}, 494 + "compositePrimaryKeys": {}, 495 + "uniqueConstraints": {}, 496 + "policies": {}, 497 + "checkConstraints": {}, 498 + "isRLSEnabled": false 499 + }, 500 + "public.snapshots": { 501 + "name": "snapshots", 502 + "schema": "", 503 + "columns": { 504 + "id": { 505 + "name": "id", 506 + "type": "text", 507 + "primaryKey": true, 508 + "notNull": true, 509 + "default": "snapshot_id()" 510 + }, 511 + "slug": { 512 + "name": "slug", 513 + "type": "text", 514 + "primaryKey": false, 515 + "notNull": true 516 + }, 517 + "created_at": { 518 + "name": "created_at", 519 + "type": "timestamp", 520 + "primaryKey": false, 521 + "notNull": true, 522 + "default": "now()" 523 + } 524 + }, 525 + "indexes": {}, 526 + "foreignKeys": {}, 527 + "compositePrimaryKeys": {}, 528 + "uniqueConstraints": { 529 + "snapshots_slug_unique": { 530 + "name": "snapshots_slug_unique", 531 + "nullsNotDistinct": false, 532 + "columns": [ 533 + "slug" 534 + ] 535 + } 536 + }, 537 + "policies": {}, 538 + "checkConstraints": {}, 539 + "isRLSEnabled": false 540 + }, 541 + "public.users": { 542 + "name": "users", 543 + "schema": "", 544 + "columns": { 545 + "id": { 546 + "name": "id", 547 + "type": "text", 548 + "primaryKey": true, 549 + "notNull": true, 550 + "default": "xata_id()" 551 + }, 552 + "did": { 553 + "name": "did", 554 + "type": "text", 555 + "primaryKey": false, 556 + "notNull": true 557 + }, 558 + "display_name": { 559 + "name": "display_name", 560 + "type": "text", 561 + "primaryKey": false, 562 + "notNull": false 563 + }, 564 + "handle": { 565 + "name": "handle", 566 + "type": "text", 567 + "primaryKey": false, 568 + "notNull": true 569 + }, 570 + "avatar": { 571 + "name": "avatar", 572 + "type": "text", 573 + "primaryKey": false, 574 + "notNull": false 575 + }, 576 + "created_at": { 577 + "name": "created_at", 578 + "type": "timestamp", 579 + "primaryKey": false, 580 + "notNull": true, 581 + "default": "now()" 582 + }, 583 + "updated_at": { 584 + "name": "updated_at", 585 + "type": "timestamp", 586 + "primaryKey": false, 587 + "notNull": true, 588 + "default": "now()" 589 + } 590 + }, 591 + "indexes": {}, 592 + "foreignKeys": {}, 593 + "compositePrimaryKeys": {}, 594 + "uniqueConstraints": { 595 + "users_did_unique": { 596 + "name": "users_did_unique", 597 + "nullsNotDistinct": false, 598 + "columns": [ 599 + "did" 600 + ] 601 + }, 602 + "users_handle_unique": { 603 + "name": "users_handle_unique", 604 + "nullsNotDistinct": false, 605 + "columns": [ 606 + "handle" 607 + ] 608 + } 609 + }, 610 + "policies": {}, 611 + "checkConstraints": {}, 612 + "isRLSEnabled": false 613 + }, 614 + "public.variables": { 615 + "name": "variables", 616 + "schema": "", 617 + "columns": { 618 + "id": { 619 + "name": "id", 620 + "type": "text", 621 + "primaryKey": true, 622 + "notNull": true, 623 + "default": "variable_id()" 624 + }, 625 + "name": { 626 + "name": "name", 627 + "type": "text", 628 + "primaryKey": false, 629 + "notNull": true 630 + }, 631 + "value": { 632 + "name": "value", 633 + "type": "text", 634 + "primaryKey": false, 635 + "notNull": true 636 + }, 637 + "created_at": { 638 + "name": "created_at", 639 + "type": "timestamp", 640 + "primaryKey": false, 641 + "notNull": true, 642 + "default": "now()" 643 + }, 644 + "updated_at": { 645 + "name": "updated_at", 646 + "type": "timestamp", 647 + "primaryKey": false, 648 + "notNull": true, 649 + "default": "now()" 650 + } 651 + }, 652 + "indexes": {}, 653 + "foreignKeys": {}, 654 + "compositePrimaryKeys": {}, 655 + "uniqueConstraints": {}, 656 + "policies": {}, 657 + "checkConstraints": {}, 658 + "isRLSEnabled": false 659 + }, 660 + "public.volumes": { 661 + "name": "volumes", 662 + "schema": "", 663 + "columns": { 664 + "id": { 665 + "name": "id", 666 + "type": "text", 667 + "primaryKey": true, 668 + "notNull": true, 669 + "default": "volume_id()" 670 + }, 671 + "slug": { 672 + "name": "slug", 673 + "type": "text", 674 + "primaryKey": false, 675 + "notNull": true 676 + }, 677 + "size": { 678 + "name": "size", 679 + "type": "integer", 680 + "primaryKey": false, 681 + "notNull": true 682 + }, 683 + "size_unit": { 684 + "name": "size_unit", 685 + "type": "text", 686 + "primaryKey": false, 687 + "notNull": true 688 + }, 689 + "created_at": { 690 + "name": "created_at", 691 + "type": "timestamp", 692 + "primaryKey": false, 693 + "notNull": true, 694 + "default": "now()" 695 + }, 696 + "updated_at": { 697 + "name": "updated_at", 698 + "type": "timestamp", 699 + "primaryKey": false, 700 + "notNull": true, 701 + "default": "now()" 702 + } 703 + }, 704 + "indexes": {}, 705 + "foreignKeys": {}, 706 + "compositePrimaryKeys": {}, 707 + "uniqueConstraints": { 708 + "volumes_slug_unique": { 709 + "name": "volumes_slug_unique", 710 + "nullsNotDistinct": false, 711 + "columns": [ 712 + "slug" 713 + ] 714 + } 715 + }, 716 + "policies": {}, 717 + "checkConstraints": {}, 718 + "isRLSEnabled": false 719 + } 720 + }, 721 + "enums": {}, 722 + "schemas": {}, 723 + "sequences": {}, 724 + "roles": {}, 725 + "policies": {}, 726 + "views": {}, 727 + "_meta": { 728 + "columns": {}, 729 + "schemas": {}, 730 + "tables": {} 731 + } 732 + }
+7
apps/cf-sandbox/drizzle/meta/_journal.json
··· 64 64 "when": 1771135267679, 65 65 "tag": "0008_futuristic_the_hand", 66 66 "breakpoints": true 67 + }, 68 + { 69 + "idx": 9, 70 + "version": "7", 71 + "when": 1771395054419, 72 + "tag": "0009_sticky_madame_masque", 73 + "breakpoints": true 67 74 } 68 75 ] 69 76 }
+3
apps/web/bun.lock
··· 13 13 "@tanstack/react-router": "^1.159.5", 14 14 "@tanstack/react-router-devtools": "^1.159.5", 15 15 "@tanstack/router-plugin": "^1.159.5", 16 + "@xterm/xterm": "^6.0.0", 16 17 "axios": "^1.13.5", 17 18 "consola": "^3.4.2", 18 19 "dayjs": "^1.11.19", ··· 366 367 "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.55.0", "", { "dependencies": { "@typescript-eslint/types": "8.55.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-AxNRwEie8Nn4eFS1FzDMJWIISMGoXMb037sgCBJ3UR6o0fQTzr2tqN9WT+DkWJPhIdQCfV7T6D387566VtnCJA=="], 367 368 368 369 "@vitejs/plugin-react-swc": ["@vitejs/plugin-react-swc@4.2.3", "", { "dependencies": { "@rolldown/pluginutils": "1.0.0-rc.2", "@swc/core": "^1.15.11" }, "peerDependencies": { "vite": "^4 || ^5 || ^6 || ^7" } }, "sha512-QIluDil2prhY1gdA3GGwxZzTAmLdi8cQ2CcuMW4PB/Wu4e/1pzqrwhYWVd09LInCRlDUidQjd0B70QWbjWtLxA=="], 370 + 371 + "@xterm/xterm": ["@xterm/xterm@6.0.0", "", {}, "sha512-TQwDdQGtwwDt+2cgKDLn0IRaSxYu1tSUjgKarSDkUM0ZNiSRXFpjxEsvc/Zgc5kq5omJ+V0a8/kIM2WD3sMOYg=="], 369 372 370 373 "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], 371 374
+1
apps/web/package.json
··· 18 18 "@tanstack/react-router": "^1.159.5", 19 19 "@tanstack/react-router-devtools": "^1.159.5", 20 20 "@tanstack/router-plugin": "^1.159.5", 21 + "@xterm/xterm": "^6.0.0", 21 22 "axios": "^1.13.5", 22 23 "consola": "^3.4.2", 23 24 "dayjs": "^1.11.19",
+9 -2
apps/web/src/components/signin/SignIn.tsx
··· 1 1 import { useEffect, useRef, useState } from "react"; 2 2 import { API_URL } from "../../consts"; 3 - import { useSearch } from "@tanstack/react-router"; 4 3 5 4 export type SignInProps = { 6 5 isOpen: boolean; ··· 111 110 > 112 111 Bluesky 113 112 </a>{" "} 114 - or any other AT Protocol service. 113 + or any other{" "} 114 + <a 115 + href={"https://atproto.com"} 116 + className="text-primary" 117 + target="_blank" 118 + > 119 + AT Protocol 120 + </a>{" "} 121 + service. 115 122 </p> 116 123 </div> 117 124 </div>
+9
apps/web/src/pages/sandbox/Sandbox.tsx
··· 40 40 </button> 41 41 </div> 42 42 )} 43 + <div className="p-4"> 44 + <div className="mt-[50px] flex space-between"> 45 + <div className="flex-1"></div> 46 + <button className="btn btn-outline btn-lg hover:text-white"> 47 + <span className="icon-[tabler--player-stop-filled] size-5 shrink-0"></span> 48 + Stop Sandbox 49 + </button> 50 + </div> 51 + </div> 43 52 </div> 44 53 <SignIn 45 54 isOpen={signInModalOpen}
+9 -1
apps/web/src/pages/signin/SignIn.tsx
··· 53 53 > 54 54 Bluesky 55 55 </a>{" "} 56 - or any other AT Protocol service. 56 + or any other{" "} 57 + <a 58 + href={"https://atproto.com"} 59 + className="text-primary" 60 + target="_blank" 61 + > 62 + AT Protocol 63 + </a>{" "} 64 + service. 57 65 </p> 58 66 </div> 59 67 </div>