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.

at main 127 lines 3.5 kB view raw
1import { Sandbox } from '@pocketenv/sdk'; 2import consola from 'consola'; 3import z from 'zod'; 4import { c } from '../theme'; 5import process from "node:process"; 6import Table from "cli-table3"; 7import dayjs from "dayjs"; 8import relativeTime from "dayjs/plugin/relativeTime"; 9 10dayjs.extend(relativeTime); 11 12const ttlSchema = z 13 .string() 14 .regex(/^\d+(m|h|d)$/, 'Invalid TTL format (e.g. 10m, 2h, 7d)') 15 .transform((value) => { 16 const amount = parseInt(value.slice(0, -1), 10); 17 const unit = value.slice(-1); 18 19 switch (unit) { 20 case 'm': 21 return amount * 60; 22 case 'h': 23 return amount * 60 * 60; 24 case 'd': 25 return amount * 60 * 60 * 24; 26 default: 27 throw new Error('Invalid TTL unit'); 28 } 29 }); 30 31const backupOptionsSchema = z.object({ 32 description: z.string().optional(), 33 ttl: ttlSchema.optional(), 34}); 35 36export type BackupOptions = z.infer<typeof backupOptionsSchema>; 37 38export async function createBackup(sandboxId: string, directory: string, options: BackupOptions) { 39 try { 40 const { data, error } = backupOptionsSchema.safeParse(options); 41 if (error) { 42 consola.error(`Invalid backup options: ${error.issues[0]?.message}`); 43 process.exit(1); 44 } 45 46 const sandbox = await Sandbox.get(sandboxId); 47 48 if (sandbox.data.provider !== "cloudflare") { 49 consola.error(`Backups are only supported for sandboxes running on Cloudflare Workers`); 50 process.exit(1); 51 } 52 53 const { description, ttl } = data; 54 55 await sandbox.backup.create( 56 directory, 57 description, 58 ttl, 59 ); 60 consola.success(`Backup request for sandbox ${c.primary(sandboxId)} at directory ${c.primary(directory)} created successfully`); 61 consola.log(` This may take a few moments to complete.\n Run ${c.primary(`pocketenv backup ls ${sandboxId}`)} to check the status of your backup.`); 62 } catch (e) { 63 consola.error(`Failed to create backup for sandbox`, e); 64 process.exit(1); 65 } 66} 67 68export async function restoreBackup(backupId: string) { 69 try { 70 await Sandbox.restoreBackup(backupId); 71 consola.success(`Backup ${c.primary(backupId)} restored successfully`); 72 } catch { 73 consola.error(`Failed to restore backup ${c.primary(backupId)}`); 74 process.exit(1); 75 } 76} 77 78export async function listBackups(sandboxId: string) { 79 const sandbox = await Sandbox.get(sandboxId); 80 try { 81 const { backups } = await sandbox.backup.list(); 82 83 const table = new Table({ 84 head: [ 85 c.primary("BACKUP ID"), 86 c.primary("DIRECTORY"), 87 c.primary("CREATED AT"), 88 c.primary("EXPIRES AT"), 89 ], 90 chars: { 91 top: "", 92 "top-mid": "", 93 "top-left": "", 94 "top-right": "", 95 bottom: "", 96 "bottom-mid": "", 97 "bottom-left": "", 98 "bottom-right": "", 99 left: "", 100 "left-mid": "", 101 mid: "", 102 "mid-mid": "", 103 right: "", 104 "right-mid": "", 105 middle: " ", 106 }, 107 style: { 108 border: [], 109 head: [], 110 }, 111 }); 112 113 for (const backup of backups) { 114 table.push([ 115 c.secondary(backup.id), 116 backup.directory, 117 dayjs(backup.createdAt).fromNow(), 118 backup.expiresAt ? dayjs(backup.expiresAt).fromNow() : "Never", 119 ]); 120 } 121 122 consola.log(table.toString()); 123 } catch { 124 consola.error(`Failed to list backups for sandbox ${c.primary(sandboxId)}`); 125 process.exit(1); 126 } 127}