mirror of
https://github.com/harivansh-afk/sandbox-agent.git
synced 2026-04-15 06:04:43 +00:00
Sync upstream changes: multiplayer docs, logos, openapi spec, foundry config
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
f5d64ca0fd
commit
d008283c17
9 changed files with 52 additions and 12 deletions
|
|
@ -20,8 +20,43 @@ Use [actor keys](https://rivet.dev/docs/actors/keys) to map each workspace to on
|
|||
|
||||
```ts Actor (server)
|
||||
import { actor, setup } from "rivetkit";
|
||||
import { SandboxAgent } from "sandbox-agent";
|
||||
import { RivetSessionPersistDriver, type RivetPersistState } from "@sandbox-agent/persist-rivet";
|
||||
import { SandboxAgent, type SessionPersistDriver, type SessionRecord, type SessionEvent, type ListPageRequest, type ListPage, type ListEventsRequest } from "sandbox-agent";
|
||||
|
||||
// Inline Rivet persist driver — copy into your project.
|
||||
// See https://github.com/nichochar/sandbox-agent/tree/main/examples/persist-rivet
|
||||
interface ActorContextLike { state: Record<string, unknown>; }
|
||||
interface RivetPersistData { sessions: Record<string, SessionRecord>; events: Record<string, SessionEvent[]>; }
|
||||
type RivetPersistState = { _sandboxAgentPersist: RivetPersistData };
|
||||
|
||||
class RivetSessionPersistDriver implements SessionPersistDriver {
|
||||
private readonly stateKey: string;
|
||||
private readonly ctx: ActorContextLike;
|
||||
constructor(ctx: ActorContextLike, options: { stateKey?: string } = {}) {
|
||||
this.ctx = ctx;
|
||||
this.stateKey = options.stateKey ?? "_sandboxAgentPersist";
|
||||
if (!this.ctx.state[this.stateKey]) {
|
||||
this.ctx.state[this.stateKey] = { sessions: {}, events: {} };
|
||||
}
|
||||
}
|
||||
private get data(): RivetPersistData { return this.ctx.state[this.stateKey] as RivetPersistData; }
|
||||
async getSession(id: string) { const s = this.data.sessions[id]; return s ? { ...s } : undefined; }
|
||||
async listSessions(request: ListPageRequest = {}): Promise<ListPage<SessionRecord>> {
|
||||
const sorted = Object.values(this.data.sessions).sort((a, b) => a.createdAt - b.createdAt || a.id.localeCompare(b.id));
|
||||
const offset = Number(request.cursor ?? 0);
|
||||
const limit = request.limit ?? 100;
|
||||
const slice = sorted.slice(offset, offset + limit);
|
||||
return { items: slice, nextCursor: offset + slice.length < sorted.length ? String(offset + slice.length) : undefined };
|
||||
}
|
||||
async updateSession(session: SessionRecord) { this.data.sessions[session.id] = { ...session }; if (!this.data.events[session.id]) this.data.events[session.id] = []; }
|
||||
async listEvents(request: ListEventsRequest): Promise<ListPage<SessionEvent>> {
|
||||
const all = [...(this.data.events[request.sessionId] ?? [])].sort((a, b) => a.eventIndex - b.eventIndex || a.id.localeCompare(b.id));
|
||||
const offset = Number(request.cursor ?? 0);
|
||||
const limit = request.limit ?? 100;
|
||||
const slice = all.slice(offset, offset + limit);
|
||||
return { items: slice, nextCursor: offset + slice.length < all.length ? String(offset + slice.length) : undefined };
|
||||
}
|
||||
async insertEvent(sessionId: string, event: SessionEvent) { const events = this.data.events[sessionId] ?? []; events.push({ ...event, payload: JSON.parse(JSON.stringify(event.payload)) }); this.data.events[sessionId] = events; }
|
||||
}
|
||||
|
||||
type WorkspaceState = RivetPersistState & {
|
||||
sandboxId: string;
|
||||
|
|
@ -111,5 +146,5 @@ await conn.prompt({
|
|||
## Notes
|
||||
|
||||
- Keep sandbox calls actor-only. Browser clients should not call Sandbox Agent directly.
|
||||
- Use `@sandbox-agent/persist-rivet` so session history persists in actor state.
|
||||
- Inline the Rivet persist driver (shown above) so session history persists in actor state.
|
||||
- For client connection patterns, see [Rivet JavaScript client](https://rivet.dev/docs/clients/javascript).
|
||||
|
|
|
|||
|
|
@ -7,13 +7,10 @@ if (process.env.ANTHROPIC_API_KEY) envs.ANTHROPIC_API_KEY = process.env.ANTHROPI
|
|||
if (process.env.OPENAI_API_KEY) envs.OPENAI_API_KEY = process.env.OPENAI_API_KEY;
|
||||
|
||||
const client = await SandboxAgent.start({
|
||||
sandbox: e2b({
|
||||
create: { envs },
|
||||
}),
|
||||
// ✨ NEW ✨
|
||||
sandbox: e2b({ create: { envs } }),
|
||||
});
|
||||
|
||||
console.log(`UI: ${client.inspectorUrl}`);
|
||||
|
||||
const session = await client.createSession({
|
||||
agent: detectAgent(),
|
||||
cwd: "/home/user",
|
||||
|
|
|
|||
|
|
@ -65,7 +65,6 @@ services:
|
|||
- "foundry_backend_root_node_modules:/app/node_modules"
|
||||
- "foundry_backend_backend_node_modules:/app/foundry/packages/backend/node_modules"
|
||||
- "foundry_backend_shared_node_modules:/app/foundry/packages/shared/node_modules"
|
||||
- "foundry_backend_persist_rivet_node_modules:/app/sdks/persist-rivet/node_modules"
|
||||
- "foundry_backend_typescript_node_modules:/app/sdks/typescript/node_modules"
|
||||
- "foundry_backend_pnpm_store:/root/.local/share/pnpm/store"
|
||||
# Persist RivetKit local storage across container restarts.
|
||||
|
|
@ -120,7 +119,6 @@ volumes:
|
|||
foundry_backend_root_node_modules: {}
|
||||
foundry_backend_backend_node_modules: {}
|
||||
foundry_backend_shared_node_modules: {}
|
||||
foundry_backend_persist_rivet_node_modules: {}
|
||||
foundry_backend_typescript_node_modules: {}
|
||||
foundry_backend_pnpm_store: {}
|
||||
foundry_rivetkit_storage: {}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ RUN pnpm --filter @sandbox-agent/foundry-shared build
|
|||
RUN pnpm --filter acp-http-client build
|
||||
RUN pnpm --filter @sandbox-agent/cli-shared build
|
||||
RUN SKIP_OPENAPI_GEN=1 pnpm --filter sandbox-agent build
|
||||
RUN pnpm --filter @sandbox-agent/persist-rivet build
|
||||
RUN pnpm --filter @sandbox-agent/foundry-backend build
|
||||
RUN pnpm --filter @sandbox-agent/foundry-backend deploy --prod /out
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@
|
|||
"@hono/node-ws": "^1.3.0",
|
||||
"@iarna/toml": "^2.2.5",
|
||||
"@sandbox-agent/foundry-shared": "workspace:*",
|
||||
"@sandbox-agent/persist-rivet": "workspace:*",
|
||||
"better-auth": "^1.5.5",
|
||||
"dockerode": "^4.0.9",
|
||||
"drizzle-kit": "^0.31.8",
|
||||
|
|
|
|||
3
frontend/packages/website/public/logos/cloudflare.svg
Normal file
3
frontend/packages/website/public/logos/cloudflare.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<svg viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M16.5088 16.8447c.1475-.5068.0908-.9707-.1553-1.3154-.2246-.3164-.6045-.499-1.0615-.5205l-8.6592-.1123a.1559.1559 0 0 1-.1333-.0713c-.0283-.042-.0351-.0986-.021-.1553.0278-.084.1123-.1484.2036-.1562l8.7359-.1123c1.0351-.0489 2.1601-.8868 2.5537-1.9136l.499-1.3013c.0215-.0561.0293-.1128.0147-.168-.5625-2.5463-2.835-4.4453-5.5499-4.4453-2.5039 0-4.6284 1.6177-5.3876 3.8614-.4927-.3658-1.1187-.5625-1.794-.499-1.2026.119-2.1665 1.083-2.2861 2.2856-.0283.31-.0069.6128.0635.894C1.5683 13.171 0 14.7754 0 16.752c0 .1748.0142.3515.0352.5273.0141.083.0844.1475.1689.1475h15.9814c.0909 0 .1758-.0645.2032-.1553l.12-.4268zm2.7568-5.5634c-.0771 0-.1611 0-.2383.0112-.0566 0-.1054.0415-.127.0976l-.3378 1.1744c-.1475.5068-.0918.9707.1543 1.3164.2256.3164.6055.498 1.0625.5195l1.8437.1133c.0557 0 .1055.0263.1329.0703.0283.043.0351.1074.0214.1562-.0283.084-.1132.1485-.204.1553l-1.921.1123c-1.041.0488-2.1582.8867-2.5527 1.914l-.1406.3585c-.0283.0713.0215.1416.0986.1416h6.5977c.0771 0 .1474-.0489.169-.126.1122-.4082.1757-.837.1757-1.2803 0-2.6025-2.125-4.727-4.7344-4.727"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
3
frontend/packages/website/public/logos/computesdk.svg
Normal file
3
frontend/packages/website/public/logos/computesdk.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<svg viewBox="0 0 1711 1711" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1036.26 1002.28H1274.13L1273.2 1021.37C1264.82 1131.69 1223.39 1219.67 1149.38 1283.44C1076.29 1346.75 978.54 1378.87 858.9 1378.87C728.09 1378.87 623.35 1334.18 547.47 1245.27C472.99 1157.29 434.82 1035.79 434.82 884.04V823.53C434.82 726.7 452.52 640.12 486.5 566.1C521.41 491.15 571.69 432.49 636.39 392.47C701.09 352.43 776.51 331.95 861.69 331.95C979.46 331.95 1075.82 364.07 1147.98 427.85C1220.6 491.15 1262.96 581.46 1274.13 695.52L1275.99 714.6H1037.65L1036.72 698.77C1032.07 639.66 1015.77 596.83 988.77 571.69C961.77 546.09 918.94 533.52 861.69 533.52C799.78 533.52 754.63 554.47 724.36 598.69C692.71 643.84 676.42 716.46 675.49 814.22V888.7C675.49 991.11 690.85 1066.53 721.11 1112.61C749.97 1156.83 795.12 1178.24 858.9 1178.24C917.09 1178.24 960.38 1165.67 987.85 1140.07C1014.84 1114.93 1031.14 1073.97 1035.33 1018.57L1036.26 1002.27V1002.28Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 965 B |
3
frontend/packages/website/public/logos/docker.svg
Normal file
3
frontend/packages/website/public/logos/docker.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<svg viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M13.983 11.078h2.119a.186.186 0 00.186-.185V9.006a.186.186 0 00-.186-.186h-2.119a.185.185 0 00-.185.185v1.888c0 .102.083.185.185.185m-2.954-5.43h2.118a.186.186 0 00.186-.186V3.574a.186.186 0 00-.186-.185h-2.118a.185.185 0 00-.185.185v1.888c0 .102.082.185.185.185m0 2.716h2.118a.187.187 0 00.186-.186V6.29a.186.186 0 00-.186-.185h-2.118a.185.185 0 00-.185.185v1.887c0 .102.082.185.185.186m-2.93 0h2.12a.186.186 0 00.184-.186V6.29a.185.185 0 00-.185-.185H8.1a.185.185 0 00-.185.185v1.887c0 .102.083.185.185.186m-2.964 0h2.119a.186.186 0 00.185-.186V6.29a.185.185 0 00-.185-.185H5.136a.186.186 0 00-.186.185v1.887c0 .102.084.185.186.186m5.893 2.715h2.118a.186.186 0 00.186-.185V9.006a.186.186 0 00-.186-.186h-2.118a.185.185 0 00-.185.185v1.888c0 .102.082.185.185.185m-2.93 0h2.12a.185.185 0 00.184-.185V9.006a.185.185 0 00-.184-.186h-2.12a.185.185 0 00-.184.185v1.888c0 .102.083.185.185.185m-2.964 0h2.119a.185.185 0 00.185-.185V9.006a.185.185 0 00-.184-.186h-2.12a.186.186 0 00-.186.186v1.887c0 .102.084.185.186.185m-2.92 0h2.12a.185.185 0 00.184-.185V9.006a.185.185 0 00-.184-.186h-2.12a.185.185 0 00-.184.185v1.888c0 .102.082.185.185.185M23.763 9.89c-.065-.051-.672-.51-1.954-.51-.338.001-.676.03-1.01.087-.248-1.7-1.653-2.53-1.716-2.566l-.344-.199-.226.327c-.284.438-.49.922-.612 1.43-.23.97-.09 1.882.403 2.661-.595.332-1.55.413-1.744.42H.751a.751.751 0 00-.75.748 11.376 11.376 0 00.692 4.062c.545 1.428 1.355 2.48 2.41 3.124 1.18.723 3.1 1.137 5.275 1.137.983.003 1.963-.086 2.93-.266a12.248 12.248 0 003.823-1.389c.98-.567 1.86-1.288 2.61-2.136 1.252-1.418 1.998-2.997 2.553-4.4h.221c1.372 0 2.215-.549 2.68-1.009.309-.293.55-.65.707-1.046l.098-.288Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
3
frontend/packages/website/public/logos/modal.svg
Normal file
3
frontend/packages/website/public/logos/modal.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<svg viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4.89 5.57 0 14.002l2.521 4.4h5.05l4.396-7.718 4.512 7.709 4.996.037L24 14.057l-4.857-8.452-5.073-.015-2.076 3.598L9.94 5.57Zm.837.729h3.787l1.845 3.252H7.572Zm9.189.021 3.803.012 4.228 7.355-3.736-.027zm-9.82.346L6.94 9.914l-4.209 7.389-1.892-3.3Zm9.187.014 4.297 7.343-1.892 3.282-4.3-7.344zm-6.713 3.6h3.79l-4.212 7.394H3.361Zm11.64 4.109 3.74.027-1.893 3.281-3.74-.027z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 476 B |
Loading…
Add table
Add a link
Reference in a new issue