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.

Return preview URL when exposing port

+69 -5
+15
apps/api/lexicons/sandbox/exposePort.json
··· 37 37 } 38 38 } 39 39 } 40 + }, 41 + "output": { 42 + "encoding": "application/json", 43 + "schema": { 44 + "type": "object", 45 + "nullable": [ 46 + "previewUrl" 47 + ], 48 + "properties": { 49 + "previewUrl": { 50 + "type": "string", 51 + "description": "The preview URL for the exposed port." 52 + } 53 + } 54 + } 40 55 } 41 56 } 42 57 }
+13
apps/api/pkl/defs/sandbox/exposePort.pkl
··· 35 35 } 36 36 } 37 37 } 38 + output { 39 + encoding = "application/json" 40 + schema = new ObjectType { 41 + type = "object" 42 + nullable = List("previewUrl") 43 + properties { 44 + ["previewUrl"] = new StringType { 45 + type = "string" 46 + description = "The preview URL for the exposed port." 47 + } 48 + } 49 + } 50 + } 38 51 } 39 52 }
+13
apps/api/src/lexicon/lexicons.ts
··· 1079 1079 }, 1080 1080 }, 1081 1081 }, 1082 + output: { 1083 + encoding: "application/json", 1084 + schema: { 1085 + type: "object", 1086 + nullable: ["previewUrl"], 1087 + properties: { 1088 + previewUrl: { 1089 + type: "string", 1090 + description: "The preview URL for the exposed port.", 1091 + }, 1092 + }, 1093 + }, 1094 + }, 1082 1095 }, 1083 1096 }, 1084 1097 },
+14 -2
apps/api/src/lexicon/types/io/pocketenv/sandbox/exposePort.ts
··· 6 6 import { lexicons } from "../../../../lexicons"; 7 7 import { isObj, hasProp } from "../../../../util"; 8 8 import { CID } from "multiformats/cid"; 9 - import { type HandlerAuth, HandlerPipeThrough } from "@atproto/xrpc-server"; 9 + import type { HandlerAuth, HandlerPipeThrough } from "@atproto/xrpc-server"; 10 10 11 11 export interface QueryParams { 12 12 /** The sandbox ID. */ ··· 18 18 port: number; 19 19 /** A description of the port. */ 20 20 description?: string; 21 + [k: string]: unknown; 22 + } 23 + 24 + export interface OutputSchema { 25 + /** The preview URL for the exposed port. */ 26 + previewUrl?: string | null; 21 27 [k: string]: unknown; 22 28 } 23 29 ··· 26 32 body: InputSchema; 27 33 } 28 34 35 + export interface HandlerSuccess { 36 + encoding: "application/json"; 37 + body: OutputSchema; 38 + headers?: { [key: string]: string }; 39 + } 40 + 29 41 export interface HandlerError { 30 42 status: number; 31 43 message?: string; 32 44 } 33 45 34 - export type HandlerOutput = HandlerError | void; 46 + export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough; 35 47 export type HandlerReqCtx<HA extends HandlerAuth = never> = { 36 48 auth: HA; 37 49 params: QueryParams;
+9 -2
apps/api/src/xrpc/io/pocketenv/sandbox/exposePort.ts
··· 8 8 import type { 9 9 QueryParams, 10 10 InputSchema, 11 + OutputSchema, 11 12 } from "lexicon/types/io/pocketenv/sandbox/exposePort"; 12 13 import { createAgent } from "lib/agent"; 13 14 import generateJwt from "lib/generateJwt"; ··· 36 37 ); 37 38 } 38 39 39 - await ctx.db.transaction(async (tx) => { 40 + return ctx.db.transaction(async (tx) => { 40 41 const [record] = await tx 41 42 .select() 42 43 .from(schema.sandboxes) ··· 112 113 ) 113 114 .execute(); 114 115 } 116 + 117 + return data.previewUrl; 115 118 }); 116 119 }; 117 120 server.io.pocketenv.sandbox.exposePort({ 118 121 auth: ctx.authVerifier, 119 122 handler: async ({ params, input, auth }) => { 120 - await exposePort(params, input.body, auth); 123 + const previewUrl = await exposePort(params, input.body, auth); 124 + return { 125 + encoding: "application/json", 126 + body: { previewUrl } satisfies OutputSchema, 127 + }; 121 128 }, 122 129 }); 123 130 }
+5 -1
apps/cli/src/cmd/expose.ts
··· 11 11 ) { 12 12 const token = await getAccessToken(); 13 13 try { 14 - await client.post( 14 + const response = await client.post<{ previewUrl?: string }>( 15 15 `/xrpc/io.pocketenv.sandbox.exposePort`, 16 16 { port, description }, 17 17 { ··· 27 27 consola.success( 28 28 `Port ${c.primary(port)} exposed for sandbox ${c.primary(sandbox)}`, 29 29 ); 30 + 31 + if (response.data.previewUrl) { 32 + consola.log(`Preview URL: ${c.secondary(response.data.previewUrl)}`); 33 + } 30 34 } catch (error) { 31 35 consola.error("Failed to expose port:", error); 32 36 process.exit(1);