From 40790a94e3d0252cc7df8e8cd904a9b2d49a9ed6 Mon Sep 17 00:00:00 2001 From: Sree Narayanan Date: Mon, 12 Oct 2026 11:11:26 +0000 Subject: [PATCH] docs(agentos): sync from rivet-dev/agentos@221382a Amp-Thread-ID: https://ampcode.com/threads/T-c7d08b58-92c1-4fc0-abb9-7a15f4504a4f Co-authored-by: Amp --- .../docs/content/docs/agent-to-agent.mdx | 46 --- .../docs/content/docs/agents/claude.mdx | 65 --- .../docs/content/docs/agents/codex.mdx | 45 --- .../docs/content/docs/agents/custom.mdx | 98 ----- .../docs/content/docs/agents/opencode.mdx | 79 ---- .../agentos/docs/content/docs/agents/pi.mdx | 60 --- .../agentos/docs/content/docs/approvals.mdx | 50 --- .../docs/content/docs/architecture.mdx | 380 ++---------------- .../docs/architecture/agent-sdk-snapshots.mdx | 79 ---- .../docs/architecture/agent-sessions.mdx | 53 --- .../content/docs/architecture/filesystem.mdx | 6 +- .../docs/architecture/javascript-executor.mdx | 4 +- .../architecture/limits-and-observability.mdx | 6 +- .../content/docs/architecture/networking.mdx | 19 +- .../packages-and-command-resolution.mdx | 284 +++---------- .../content/docs/architecture/processes.mdx | 31 +- .../architecture/sessions-persistence.mdx | 85 ---- .../docs/architecture/software-cache.mdx | 63 +++ .../content/docs/architecture/tls-ssl.mdx | 4 +- .../docs/content/docs/authentication.mdx | 33 -- vendor/agentos/docs/content/docs/bash.mdx | 109 ++++- vendor/agentos/docs/content/docs/browser.mdx | 89 +--- vendor/agentos/docs/content/docs/cron.mdx | 117 +++--- .../docs/custom-software/building-wasm.mdx | 68 +--- .../docs/custom-software/definition.mdx | 245 +---------- .../docs/custom-software/publishing.mdx | 88 +--- .../agentos/docs/content/docs/debugging.mdx | 62 --- vendor/agentos/docs/content/docs/embedded.mdx | 90 +---- .../agentos/docs/content/docs/filesystem.mdx | 194 +++++---- .../docs/content/docs/host-functions.mdx | 43 +- .../agentos/docs/content/docs/hosted-api.mdx | 257 ++++++++++++ vendor/agentos/docs/content/docs/index.mdx | 31 +- .../agentos/docs/content/docs/javascript.mdx | 141 +++++-- .../agentos/docs/content/docs/limitations.mdx | 9 +- .../content/docs/models-and-credentials.mdx | 47 --- .../agentos/docs/content/docs/multiplayer.mdx | 23 -- .../agentos/docs/content/docs/networking.mdx | 103 ++--- .../agentos/docs/content/docs/performance.mdx | 209 ++-------- .../agentos/docs/content/docs/permissions.mdx | 131 +----- .../agentos/docs/content/docs/persistence.mdx | 99 ++--- .../agentos/docs/content/docs/processes.mdx | 152 +++++-- vendor/agentos/docs/content/docs/python.mdx | 84 ++-- .../docs/content/docs/quickstart-embedded.mdx | 79 +--- .../docs/content/docs/quickstart-hosted.mdx | 330 +++++++++++++++ .../agentos/docs/content/docs/quickstart.mdx | 161 +++----- .../docs/content/docs/resource-limits.mdx | 199 ++++----- .../agentos/docs/content/docs/sandboxes.mdx | 151 +------ .../docs/content/docs/security-model.mdx | 246 ++++-------- .../docs/content/docs/self-hosting.mdx | 84 ++++ vendor/agentos/docs/content/docs/sessions.mdx | 166 -------- vendor/agentos/docs/content/docs/software.mdx | 120 +++++- .../docs/content/docs/system-prompt.mdx | 19 - .../docs/content/docs/versus-sandbox.mdx | 20 +- .../agentos/docs/content/docs/workflows.mdx | 43 -- .../docs/content/integrations/flue.mdx | 122 ------ .../content/integrations/rivet-actors.mdx | 83 ---- .../docs/content/integrations/vercel-eve.mdx | 162 -------- .../agentos/docs/content/use-cases/index.mdx | 66 +++ vendor/agentos/docs/registry.json | 168 ++------ vendor/agentos/docs/sidebar.json | 165 ++------ .../agentos/examples/agent-to-agent/README.md | 26 -- .../agentos/examples/agent-to-agent/client.ts | 22 - .../examples/agent-to-agent/package.json | 28 -- .../agentos/examples/agent-to-agent/server.ts | 66 --- .../examples/agent-to-agent/tsconfig.json | 13 - .../examples/agentos-typecheck/package.json | 19 - .../examples/agentos-typecheck/src/index.ts | 142 ------- .../examples/agentos-typecheck/tsconfig.json | 20 - vendor/agentos/examples/approvals/README.md | 38 -- .../examples/approvals/auto-approve-client.ts | 17 - .../examples/approvals/auto-approve.ts | 9 - vendor/agentos/examples/approvals/client.ts | 35 -- .../examples/approvals/human-in-the-loop.ts | 16 - .../agentos/examples/approvals/package.json | 28 -- .../examples/approvals/selective-client.ts | 36 -- .../agentos/examples/approvals/selective.ts | 18 - vendor/agentos/examples/approvals/server.ts | 9 - .../agentos/examples/approvals/tsconfig.json | 13 - .../examples/apps-ai-builder/README.md | 20 - .../apps-ai-builder/fixtures/app/package.json | 17 - .../apps-ai-builder/fixtures/app/src/index.ts | 23 -- .../fixtures/app/tsconfig.json | 12 - .../examples/apps-ai-builder/package.json | 24 -- .../examples/apps-ai-builder/src/actors.ts | 11 - .../examples/apps-ai-builder/src/server.ts | 132 ------ .../examples/apps-ai-builder/tsconfig.json | 12 - .../examples/apps-hello-world/README.md | 21 - .../fixtures/app/package.json | 12 - .../fixtures/app/src/index.ts | 29 -- .../examples/apps-hello-world/package.json | 22 - .../examples/apps-hello-world/src/actors.ts | 11 - .../examples/apps-hello-world/src/deploy.ts | 32 -- .../examples/apps-hello-world/src/server.ts | 18 - .../examples/apps-hello-world/tsconfig.json | 12 - .../examples/apps-multiplayer/README.md | 19 - .../fixtures/app/package.json | 13 - .../fixtures/app/src/index.ts | 40 -- .../examples/apps-multiplayer/package.json | 23 -- .../examples/apps-multiplayer/src/actors.ts | 11 - .../examples/apps-multiplayer/src/client.ts | 24 -- .../examples/apps-multiplayer/src/server.ts | 26 -- .../examples/apps-multiplayer/tsconfig.json | 12 - vendor/agentos/examples/apps-sqlite/README.md | 19 - .../apps-sqlite/fixtures/app/package.json | 13 - .../apps-sqlite/fixtures/app/src/index.ts | 36 -- .../agentos/examples/apps-sqlite/package.json | 23 -- .../examples/apps-sqlite/src/actors.ts | 11 - .../examples/apps-sqlite/src/client.ts | 24 -- .../examples/apps-sqlite/src/server.ts | 26 -- .../examples/apps-sqlite/tsconfig.json | 12 - .../examples/apps-static-website/README.md | 18 - .../apps-static-website/fixtures/app/app.js | 2 - .../fixtures/app/index.html | 15 - .../apps-static-website/fixtures/app/logo.svg | 4 - .../fixtures/app/styles.css | 10 - .../examples/apps-static-website/package.json | 22 - .../apps-static-website/src/actors.ts | 11 - .../apps-static-website/src/server.ts | 26 -- .../apps-static-website/tsconfig.json | 12 - .../agentos/examples/apps-workflows/README.md | 18 - .../apps-workflows/fixtures/app/package.json | 13 - .../apps-workflows/fixtures/app/src/index.ts | 37 -- .../examples/apps-workflows/package.json | 23 -- .../examples/apps-workflows/src/actors.ts | 11 - .../examples/apps-workflows/src/client.ts | 23 -- .../examples/apps-workflows/src/server.ts | 26 -- .../examples/apps-workflows/tsconfig.json | 12 - .../agentos/examples/authentication/README.md | 28 -- .../agentos/examples/authentication/client.ts | 23 -- .../examples/authentication/package.json | 28 -- .../agentos/examples/authentication/server.ts | 27 -- .../examples/authentication/tsconfig.json | 13 - .../examples/browser-terminal/.gitignore | 4 - .../examples/browser-terminal/README.md | 81 ---- .../examples/browser-terminal/index.html | 12 - .../examples/browser-terminal/package.json | 39 -- .../examples/browser-terminal/server.ts | 12 - .../browser-terminal/src/ActorView.tsx | 258 ------------ .../examples/browser-terminal/src/App.tsx | 84 ---- .../browser-terminal/src/TerminalPane.tsx | 127 ------ .../examples/browser-terminal/src/main.tsx | 7 - .../examples/browser-terminal/src/rivet.ts | 10 - .../examples/browser-terminal/src/store.ts | 57 --- .../examples/browser-terminal/src/styles.css | 218 ---------- .../browser-terminal/src/vite-env.d.ts | 1 - .../examples/browser-terminal/tsconfig.json | 18 - .../examples/browser-terminal/vite.config.ts | 9 - vendor/agentos/examples/browserbase/README.md | 42 -- .../examples/browserbase/client-agent.ts | 30 -- .../examples/browserbase/client-direct.ts | 28 -- vendor/agentos/examples/browserbase/client.ts | 56 --- .../agentos/examples/browserbase/embedded.ts | 32 -- .../agentos/examples/browserbase/package.json | 24 -- .../examples/browserbase/server-minimal.ts | 11 - .../examples/browserbase/server-skills-pi.ts | 21 - vendor/agentos/examples/browserbase/server.ts | 26 -- .../browserbase/skills/browse/SKILL.md | 368 ----------------- .../examples/browserbase/tsconfig.json | 14 - vendor/agentos/examples/claude/README.md | 25 -- vendor/agentos/examples/claude/client.ts | 149 ------- vendor/agentos/examples/claude/package.json | 28 -- vendor/agentos/examples/claude/server.ts | 7 - vendor/agentos/examples/claude/tsconfig.json | 13 - vendor/agentos/examples/codex/README.md | 29 -- vendor/agentos/examples/codex/client.ts | 125 ------ vendor/agentos/examples/codex/package.json | 28 -- vendor/agentos/examples/codex/server.ts | 7 - vendor/agentos/examples/codex/tsconfig.json | 13 - .../agentos/examples/crash-course/README.md | 37 -- .../crash-course/agent-to-agent-client.ts | 22 - .../crash-course/agent-to-agent-server.ts | 51 --- .../examples/crash-course/cron-client.ts | 21 - .../crash-course/filesystem-client.ts | 18 - .../examples/crash-course/minimal-client.ts | 29 -- .../crash-course/multiplayer-client.ts | 30 -- .../crash-course/networking-client.ts | 14 - .../examples/crash-course/package.json | 22 - .../crash-course/permissions-client.ts | 32 -- .../crash-course/permissions-server.ts | 15 - .../examples/crash-course/processes-client.ts | 20 - .../examples/crash-course/sandbox-stubs.d.ts | 58 --- .../agentos/examples/crash-course/sandbox.ts | 24 -- .../agentos/examples/crash-course/server.ts | 9 - .../examples/crash-course/sessions-client.ts | 25 -- .../examples/crash-course/tsconfig.json | 13 - .../examples/crash-course/workflows.ts | 56 --- vendor/agentos/examples/cron/README.md | 25 -- vendor/agentos/examples/cron/heartbeat.ts | 17 - vendor/agentos/examples/cron/list-cancel.ts | 14 - vendor/agentos/examples/cron/monitor.ts | 17 - vendor/agentos/examples/cron/overlap.ts | 15 - vendor/agentos/examples/cron/package.json | 28 -- .../agentos/examples/cron/schedule-command.ts | 15 - .../agentos/examples/cron/schedule-session.ts | 15 - vendor/agentos/examples/cron/server.ts | 9 - vendor/agentos/examples/cron/tsconfig.json | 13 - vendor/agentos/examples/custom/opencode.ts | 6 - vendor/agentos/examples/custom/package.json | 26 -- vendor/agentos/examples/custom/pi-cli.ts | 9 - vendor/agentos/examples/custom/tsconfig.json | 11 - .../agentos/examples/debugging/agent-exit.ts | 15 - .../agentos/examples/debugging/agent-logs.ts | 16 - .../agentos/examples/debugging/package.json | 26 -- .../agentos/examples/debugging/tsconfig.json | 11 - vendor/agentos/examples/embedded/README.md | 53 +-- .../examples/embedded/agent-to-agent.ts | 54 --- .../examples/embedded/config-reference.ts | 24 +- vendor/agentos/examples/embedded/hooks.ts | 15 - .../examples/embedded/host-functions-bash.ts | 33 ++ .../embedded/host-functions-javascript.ts | 36 ++ .../embedded/host-functions-python.ts | 43 ++ .../examples/embedded/host-functions.ts | 5 +- vendor/agentos/examples/embedded/limits.ts | 3 +- .../embedded/models-and-credentials.ts | 18 - vendor/agentos/examples/embedded/mounts.ts | 13 +- vendor/agentos/examples/embedded/package.json | 3 - .../agentos/examples/embedded/permissions.ts | 4 +- .../agentos/examples/embedded/persistence.ts | 6 + .../agentos/examples/embedded/quickstart.ts | 80 +++- .../examples/embedded/software-install.ts | 36 ++ vendor/agentos/examples/embedded/vm.ts | 57 +-- vendor/agentos/examples/filesystem/README.md | 28 -- .../agentos/examples/filesystem/host-api.ts | 12 - .../agentos/examples/filesystem/isolation.ts | 33 -- .../examples/filesystem/mount-custom-vfs.ts | 8 - .../examples/filesystem/mount-google-drive.ts | 24 -- .../examples/filesystem/mount-host-dir.ts | 16 - .../agentos/examples/filesystem/mount-s3.ts | 22 - .../agentos/examples/filesystem/operations.ts | 71 ---- .../agentos/examples/filesystem/package.json | 28 -- vendor/agentos/examples/filesystem/server.ts | 15 - .../agentos/examples/filesystem/tsconfig.json | 14 - vendor/agentos/examples/flue/README.md | 34 -- vendor/agentos/examples/flue/actors.ts | 7 - .../agentos/examples/flue/agents/assistant.ts | 8 - vendor/agentos/examples/flue/flue.config.ts | 6 - vendor/agentos/examples/flue/package.json | 25 -- vendor/agentos/examples/flue/tsconfig.json | 10 - .../agentos/examples/host-functions/README.md | 27 -- .../agentos/examples/host-functions/client.ts | 17 - .../examples/host-functions/exec-bash.ts | 31 -- .../host-functions/exec-javascript.ts | 37 -- .../examples/host-functions/exec-python.ts | 41 -- .../agentos/examples/host-functions/guest.mjs | 14 - .../agentos/examples/host-functions/guest.py | 12 - .../examples/host-functions/package.json | 28 -- .../agentos/examples/host-functions/server.ts | 37 -- .../examples/host-functions/tsconfig.json | 15 - .../examples/js-ai-agent-code-exec/README.md | 2 +- .../js-ai-agent-code-exec/src/index.ts | 4 +- .../agentos/examples/js-code-mode/README.md | 2 +- .../agentos/examples/js-dev-servers/README.md | 2 +- .../examples/js-networking-wasm/src/index.ts | 2 +- .../examples/js-networking/src/index.ts | 2 +- .../examples/js-plugin-systems/README.md | 2 +- .../examples/js-runtime/node-modules-mount.ts | 9 - .../agentos/examples/js-runtime/package.json | 28 -- .../agentos/examples/js-runtime/tsconfig.json | 13 - .../examples/llm-credentials/README.md | 26 -- .../examples/llm-credentials/client.ts | 13 - .../examples/llm-credentials/package.json | 28 -- .../examples/llm-credentials/per-tenant.ts | 23 -- .../examples/llm-credentials/server.ts | 12 - .../examples/llm-credentials/tsconfig.json | 13 - vendor/agentos/examples/multiplayer/README.md | 28 -- .../examples/multiplayer/collaborative.ts | 28 -- .../examples/multiplayer/observe-session.ts | 33 -- .../agentos/examples/multiplayer/package.json | 28 -- vendor/agentos/examples/multiplayer/server.ts | 14 - .../examples/multiplayer/shared-output.ts | 22 - .../examples/multiplayer/tsconfig.json | 13 - vendor/agentos/examples/networking/README.md | 31 -- .../networking/client-fetch-options.ts | 16 - .../examples/networking/client-fetch.ts | 10 - .../examples/networking/client-preview.ts | 18 - .../examples/networking/client-revoke.ts | 10 - .../examples/networking/client-run-server.ts | 18 - .../agentos/examples/networking/package.json | 28 -- .../examples/networking/server-loopback.ts | 10 - .../examples/networking/server-preview.ts | 12 - vendor/agentos/examples/networking/server.ts | 6 - .../agentos/examples/networking/tsconfig.json | 13 - vendor/agentos/examples/opencode/README.md | 27 -- vendor/agentos/examples/opencode/client.ts | 155 ------- vendor/agentos/examples/opencode/package.json | 28 -- vendor/agentos/examples/opencode/server.ts | 7 - .../agentos/examples/opencode/tsconfig.json | 13 - vendor/agentos/examples/permissions/README.md | 31 -- .../examples/permissions/bind-policy.ts | 11 - .../agentos/examples/permissions/combine.ts | 45 --- .../agentos/examples/permissions/fs-rules.ts | 32 -- .../agentos/examples/permissions/package.json | 28 -- vendor/agentos/examples/permissions/server.ts | 54 --- .../examples/permissions/tsconfig.json | 13 - vendor/agentos/examples/persistence/README.md | 29 -- .../examples/persistence/lifecycle-client.ts | 21 - .../agentos/examples/persistence/package.json | 28 -- .../persistence/restore-filesystem.ts | 11 - vendor/agentos/examples/persistence/server.ts | 9 - .../examples/persistence/tsconfig.json | 13 - vendor/agentos/examples/pi/README.md | 25 -- vendor/agentos/examples/pi/client.ts | 175 -------- vendor/agentos/examples/pi/package.json | 28 -- vendor/agentos/examples/pi/server.ts | 7 - vendor/agentos/examples/pi/tsconfig.json | 13 - vendor/agentos/examples/processes/README.md | 33 -- vendor/agentos/examples/processes/exec.ts | 11 - .../agentos/examples/processes/lifecycle.ts | 25 -- .../agentos/examples/processes/package.json | 28 -- .../examples/processes/process-events.ts | 22 - vendor/agentos/examples/processes/server.ts | 9 - .../examples/processes/shell-events.ts | 14 - vendor/agentos/examples/processes/shell.ts | 23 -- vendor/agentos/examples/processes/spawn.ts | 23 -- vendor/agentos/examples/processes/stdin.ts | 17 - .../agentos/examples/processes/tsconfig.json | 13 - .../agentos/examples/processes/visibility.ts | 18 - .../agentos/examples/quickstart-app/Agent.tsx | 41 -- .../agentos/examples/quickstart-app/README.md | 26 -- .../agentos/examples/quickstart-app/client.ts | 28 -- .../examples/quickstart-app/package.json | 31 -- .../agentos/examples/quickstart-app/server.ts | 9 - .../examples/quickstart-app/tsconfig.json | 13 - .../quickstart/agent-session/README.md | 25 -- .../quickstart/agent-session/index.ts | 43 -- .../quickstart/agent-session/package.json | 27 -- .../quickstart/agent-session/tsconfig.json | 11 - .../examples/quickstart/bash/package.json | 3 - .../examples/quickstart/cron/package.json | 3 - .../quickstart/filesystem/package.json | 3 - .../agentos/examples/quickstart/git/index.ts | 6 +- .../examples/quickstart/git/package.json | 3 - .../quickstart/hello-world/package.json | 3 - .../examples/quickstart/network/README.md | 2 +- .../examples/quickstart/network/index.ts | 3 +- .../examples/quickstart/network/package.json | 3 - .../examples/quickstart/nodejs/package.json | 3 - .../agentos/examples/quickstart/package.json | 3 - .../quickstart/pi-extensions/README.md | 29 -- .../quickstart/pi-extensions/index.ts | 131 ------ .../quickstart/pi-extensions/package.json | 27 -- .../quickstart/pi-extensions/tsconfig.json | 11 - .../examples/quickstart/processes/index.ts | 17 +- .../quickstart/processes/package.json | 3 - .../examples/quickstart/python/index.ts | 2 +- .../quickstart/s3-filesystem/package.json | 3 - .../examples/quickstart/sandbox/README.md | 2 +- .../examples/quickstart/sandbox/index.ts | 24 -- .../examples/quickstart/sandbox/package.json | 3 - .../examples/resource-limits/README.md | 25 -- .../examples/resource-limits/package.json | 28 -- .../examples/resource-limits/server.ts | 40 -- .../examples/resource-limits/tsconfig.json | 13 - vendor/agentos/examples/sandbox/README.md | 26 -- vendor/agentos/examples/sandbox/client.ts | 31 -- .../examples/sandbox/existing-client.ts | 14 - vendor/agentos/examples/sandbox/package.json | 28 -- vendor/agentos/examples/sandbox/server.ts | 13 - vendor/agentos/examples/sandbox/tsconfig.json | 14 - vendor/agentos/examples/sessions/README.md | 27 -- .../examples/sessions/cancel-prompt.ts | 30 -- vendor/agentos/examples/sessions/client.ts | 237 ----------- .../examples/sessions/close-destroy.ts | 18 - .../examples/sessions/create-session.ts | 12 - .../examples/sessions/multiple-sessions.ts | 37 -- vendor/agentos/examples/sessions/package.json | 28 -- .../examples/sessions/runtime-config.ts | 20 - .../agentos/examples/sessions/send-prompt.ts | 21 - .../agentos/examples/sessions/server-logs.ts | 17 - vendor/agentos/examples/sessions/server.ts | 7 - .../examples/sessions/stream-responses.ts | 21 - .../agentos/examples/sessions/tsconfig.json | 13 - vendor/agentos/examples/software/README.md | 24 -- vendor/agentos/examples/software/client.ts | 12 - vendor/agentos/examples/software/package.json | 31 -- .../software/quickstart-agent/index.ts | 9 - .../software/quickstart-agent/my-agent.ts | 11 - .../software/quickstart-node/index.ts | 8 - .../software/quickstart-node/my-tool.ts | 11 - .../software/quickstart-wasm/index.ts | 8 - .../software/quickstart-wasm/my-cmds.ts | 8 - .../examples/software/registry-usage.ts | 8 - vendor/agentos/examples/software/server.ts | 15 - .../examples/software/software/common.ts | 12 - .../agentos/examples/software/software/pi.ts | 12 - .../agentos/examples/software/tsconfig.json | 14 - vendor/agentos/examples/vercel-eve/.gitignore | 6 - vendor/agentos/examples/vercel-eve/README.md | 36 -- vendor/agentos/examples/vercel-eve/actors.ts | 8 - .../examples/vercel-eve/agent/agent.ts | 19 - .../examples/vercel-eve/agent/instructions.md | 3 - .../examples/vercel-eve/agent/sandbox.ts | 7 - vendor/agentos/examples/vercel-eve/core.ts | 23 -- .../agentos/examples/vercel-eve/package.json | 32 -- .../agentos/examples/vercel-eve/tsconfig.json | 10 - vendor/agentos/examples/vercel-eve/world.ts | 4 - vendor/agentos/examples/webhooks/package.json | 23 -- vendor/agentos/examples/webhooks/server.ts | 64 --- .../agentos/examples/webhooks/tsconfig.json | 13 - vendor/agentos/examples/workflows/README.md | 28 -- .../examples/workflows/chaining-client.ts | 14 - vendor/agentos/examples/workflows/client.ts | 20 - .../agentos/examples/workflows/package.json | 28 -- vendor/agentos/examples/workflows/server.ts | 144 ------- .../agentos/examples/workflows/tsconfig.json | 13 - 405 files changed, 2386 insertions(+), 12973 deletions(-) delete mode 100644 vendor/agentos/docs/content/docs/agent-to-agent.mdx delete mode 100644 vendor/agentos/docs/content/docs/agents/claude.mdx delete mode 100644 vendor/agentos/docs/content/docs/agents/codex.mdx delete mode 100644 vendor/agentos/docs/content/docs/agents/custom.mdx delete mode 100644 vendor/agentos/docs/content/docs/agents/opencode.mdx delete mode 100644 vendor/agentos/docs/content/docs/agents/pi.mdx delete mode 100644 vendor/agentos/docs/content/docs/approvals.mdx delete mode 100644 vendor/agentos/docs/content/docs/architecture/agent-sdk-snapshots.mdx delete mode 100644 vendor/agentos/docs/content/docs/architecture/agent-sessions.mdx delete mode 100644 vendor/agentos/docs/content/docs/architecture/sessions-persistence.mdx create mode 100644 vendor/agentos/docs/content/docs/architecture/software-cache.mdx delete mode 100644 vendor/agentos/docs/content/docs/authentication.mdx delete mode 100644 vendor/agentos/docs/content/docs/debugging.mdx create mode 100644 vendor/agentos/docs/content/docs/hosted-api.mdx delete mode 100644 vendor/agentos/docs/content/docs/models-and-credentials.mdx delete mode 100644 vendor/agentos/docs/content/docs/multiplayer.mdx create mode 100644 vendor/agentos/docs/content/docs/quickstart-hosted.mdx create mode 100644 vendor/agentos/docs/content/docs/self-hosting.mdx delete mode 100644 vendor/agentos/docs/content/docs/sessions.mdx delete mode 100644 vendor/agentos/docs/content/docs/system-prompt.mdx delete mode 100644 vendor/agentos/docs/content/docs/workflows.mdx delete mode 100644 vendor/agentos/docs/content/integrations/flue.mdx delete mode 100644 vendor/agentos/docs/content/integrations/rivet-actors.mdx delete mode 100644 vendor/agentos/docs/content/integrations/vercel-eve.mdx create mode 100644 vendor/agentos/docs/content/use-cases/index.mdx delete mode 100644 vendor/agentos/examples/agent-to-agent/README.md delete mode 100644 vendor/agentos/examples/agent-to-agent/client.ts delete mode 100644 vendor/agentos/examples/agent-to-agent/package.json delete mode 100644 vendor/agentos/examples/agent-to-agent/server.ts delete mode 100644 vendor/agentos/examples/agent-to-agent/tsconfig.json delete mode 100644 vendor/agentos/examples/agentos-typecheck/package.json delete mode 100644 vendor/agentos/examples/agentos-typecheck/src/index.ts delete mode 100644 vendor/agentos/examples/agentos-typecheck/tsconfig.json delete mode 100644 vendor/agentos/examples/approvals/README.md delete mode 100644 vendor/agentos/examples/approvals/auto-approve-client.ts delete mode 100644 vendor/agentos/examples/approvals/auto-approve.ts delete mode 100644 vendor/agentos/examples/approvals/client.ts delete mode 100644 vendor/agentos/examples/approvals/human-in-the-loop.ts delete mode 100644 vendor/agentos/examples/approvals/package.json delete mode 100644 vendor/agentos/examples/approvals/selective-client.ts delete mode 100644 vendor/agentos/examples/approvals/selective.ts delete mode 100644 vendor/agentos/examples/approvals/server.ts delete mode 100644 vendor/agentos/examples/approvals/tsconfig.json delete mode 100644 vendor/agentos/examples/apps-ai-builder/README.md delete mode 100644 vendor/agentos/examples/apps-ai-builder/fixtures/app/package.json delete mode 100644 vendor/agentos/examples/apps-ai-builder/fixtures/app/src/index.ts delete mode 100644 vendor/agentos/examples/apps-ai-builder/fixtures/app/tsconfig.json delete mode 100644 vendor/agentos/examples/apps-ai-builder/package.json delete mode 100644 vendor/agentos/examples/apps-ai-builder/src/actors.ts delete mode 100644 vendor/agentos/examples/apps-ai-builder/src/server.ts delete mode 100644 vendor/agentos/examples/apps-ai-builder/tsconfig.json delete mode 100644 vendor/agentos/examples/apps-hello-world/README.md delete mode 100644 vendor/agentos/examples/apps-hello-world/fixtures/app/package.json delete mode 100644 vendor/agentos/examples/apps-hello-world/fixtures/app/src/index.ts delete mode 100644 vendor/agentos/examples/apps-hello-world/package.json delete mode 100644 vendor/agentos/examples/apps-hello-world/src/actors.ts delete mode 100644 vendor/agentos/examples/apps-hello-world/src/deploy.ts delete mode 100644 vendor/agentos/examples/apps-hello-world/src/server.ts delete mode 100644 vendor/agentos/examples/apps-hello-world/tsconfig.json delete mode 100644 vendor/agentos/examples/apps-multiplayer/README.md delete mode 100644 vendor/agentos/examples/apps-multiplayer/fixtures/app/package.json delete mode 100644 vendor/agentos/examples/apps-multiplayer/fixtures/app/src/index.ts delete mode 100644 vendor/agentos/examples/apps-multiplayer/package.json delete mode 100644 vendor/agentos/examples/apps-multiplayer/src/actors.ts delete mode 100644 vendor/agentos/examples/apps-multiplayer/src/client.ts delete mode 100644 vendor/agentos/examples/apps-multiplayer/src/server.ts delete mode 100644 vendor/agentos/examples/apps-multiplayer/tsconfig.json delete mode 100644 vendor/agentos/examples/apps-sqlite/README.md delete mode 100644 vendor/agentos/examples/apps-sqlite/fixtures/app/package.json delete mode 100644 vendor/agentos/examples/apps-sqlite/fixtures/app/src/index.ts delete mode 100644 vendor/agentos/examples/apps-sqlite/package.json delete mode 100644 vendor/agentos/examples/apps-sqlite/src/actors.ts delete mode 100644 vendor/agentos/examples/apps-sqlite/src/client.ts delete mode 100644 vendor/agentos/examples/apps-sqlite/src/server.ts delete mode 100644 vendor/agentos/examples/apps-sqlite/tsconfig.json delete mode 100644 vendor/agentos/examples/apps-static-website/README.md delete mode 100644 vendor/agentos/examples/apps-static-website/fixtures/app/app.js delete mode 100644 vendor/agentos/examples/apps-static-website/fixtures/app/index.html delete mode 100644 vendor/agentos/examples/apps-static-website/fixtures/app/logo.svg delete mode 100644 vendor/agentos/examples/apps-static-website/fixtures/app/styles.css delete mode 100644 vendor/agentos/examples/apps-static-website/package.json delete mode 100644 vendor/agentos/examples/apps-static-website/src/actors.ts delete mode 100644 vendor/agentos/examples/apps-static-website/src/server.ts delete mode 100644 vendor/agentos/examples/apps-static-website/tsconfig.json delete mode 100644 vendor/agentos/examples/apps-workflows/README.md delete mode 100644 vendor/agentos/examples/apps-workflows/fixtures/app/package.json delete mode 100644 vendor/agentos/examples/apps-workflows/fixtures/app/src/index.ts delete mode 100644 vendor/agentos/examples/apps-workflows/package.json delete mode 100644 vendor/agentos/examples/apps-workflows/src/actors.ts delete mode 100644 vendor/agentos/examples/apps-workflows/src/client.ts delete mode 100644 vendor/agentos/examples/apps-workflows/src/server.ts delete mode 100644 vendor/agentos/examples/apps-workflows/tsconfig.json delete mode 100644 vendor/agentos/examples/authentication/README.md delete mode 100644 vendor/agentos/examples/authentication/client.ts delete mode 100644 vendor/agentos/examples/authentication/package.json delete mode 100644 vendor/agentos/examples/authentication/server.ts delete mode 100644 vendor/agentos/examples/authentication/tsconfig.json delete mode 100644 vendor/agentos/examples/browser-terminal/.gitignore delete mode 100644 vendor/agentos/examples/browser-terminal/README.md delete mode 100644 vendor/agentos/examples/browser-terminal/index.html delete mode 100644 vendor/agentos/examples/browser-terminal/package.json delete mode 100644 vendor/agentos/examples/browser-terminal/server.ts delete mode 100644 vendor/agentos/examples/browser-terminal/src/ActorView.tsx delete mode 100644 vendor/agentos/examples/browser-terminal/src/App.tsx delete mode 100644 vendor/agentos/examples/browser-terminal/src/TerminalPane.tsx delete mode 100644 vendor/agentos/examples/browser-terminal/src/main.tsx delete mode 100644 vendor/agentos/examples/browser-terminal/src/rivet.ts delete mode 100644 vendor/agentos/examples/browser-terminal/src/store.ts delete mode 100644 vendor/agentos/examples/browser-terminal/src/styles.css delete mode 100644 vendor/agentos/examples/browser-terminal/src/vite-env.d.ts delete mode 100644 vendor/agentos/examples/browser-terminal/tsconfig.json delete mode 100644 vendor/agentos/examples/browser-terminal/vite.config.ts delete mode 100644 vendor/agentos/examples/browserbase/README.md delete mode 100644 vendor/agentos/examples/browserbase/client-agent.ts delete mode 100644 vendor/agentos/examples/browserbase/client-direct.ts delete mode 100644 vendor/agentos/examples/browserbase/client.ts delete mode 100644 vendor/agentos/examples/browserbase/embedded.ts delete mode 100644 vendor/agentos/examples/browserbase/package.json delete mode 100644 vendor/agentos/examples/browserbase/server-minimal.ts delete mode 100644 vendor/agentos/examples/browserbase/server-skills-pi.ts delete mode 100644 vendor/agentos/examples/browserbase/server.ts delete mode 100644 vendor/agentos/examples/browserbase/skills/browse/SKILL.md delete mode 100644 vendor/agentos/examples/browserbase/tsconfig.json delete mode 100644 vendor/agentos/examples/claude/README.md delete mode 100644 vendor/agentos/examples/claude/client.ts delete mode 100644 vendor/agentos/examples/claude/package.json delete mode 100644 vendor/agentos/examples/claude/server.ts delete mode 100644 vendor/agentos/examples/claude/tsconfig.json delete mode 100644 vendor/agentos/examples/codex/README.md delete mode 100644 vendor/agentos/examples/codex/client.ts delete mode 100644 vendor/agentos/examples/codex/package.json delete mode 100644 vendor/agentos/examples/codex/server.ts delete mode 100644 vendor/agentos/examples/codex/tsconfig.json delete mode 100644 vendor/agentos/examples/crash-course/README.md delete mode 100644 vendor/agentos/examples/crash-course/agent-to-agent-client.ts delete mode 100644 vendor/agentos/examples/crash-course/agent-to-agent-server.ts delete mode 100644 vendor/agentos/examples/crash-course/cron-client.ts delete mode 100644 vendor/agentos/examples/crash-course/filesystem-client.ts delete mode 100644 vendor/agentos/examples/crash-course/minimal-client.ts delete mode 100644 vendor/agentos/examples/crash-course/multiplayer-client.ts delete mode 100644 vendor/agentos/examples/crash-course/networking-client.ts delete mode 100644 vendor/agentos/examples/crash-course/package.json delete mode 100644 vendor/agentos/examples/crash-course/permissions-client.ts delete mode 100644 vendor/agentos/examples/crash-course/permissions-server.ts delete mode 100644 vendor/agentos/examples/crash-course/processes-client.ts delete mode 100644 vendor/agentos/examples/crash-course/sandbox-stubs.d.ts delete mode 100644 vendor/agentos/examples/crash-course/sandbox.ts delete mode 100644 vendor/agentos/examples/crash-course/server.ts delete mode 100644 vendor/agentos/examples/crash-course/sessions-client.ts delete mode 100644 vendor/agentos/examples/crash-course/tsconfig.json delete mode 100644 vendor/agentos/examples/crash-course/workflows.ts delete mode 100644 vendor/agentos/examples/cron/README.md delete mode 100644 vendor/agentos/examples/cron/heartbeat.ts delete mode 100644 vendor/agentos/examples/cron/list-cancel.ts delete mode 100644 vendor/agentos/examples/cron/monitor.ts delete mode 100644 vendor/agentos/examples/cron/overlap.ts delete mode 100644 vendor/agentos/examples/cron/package.json delete mode 100644 vendor/agentos/examples/cron/schedule-command.ts delete mode 100644 vendor/agentos/examples/cron/schedule-session.ts delete mode 100644 vendor/agentos/examples/cron/server.ts delete mode 100644 vendor/agentos/examples/cron/tsconfig.json delete mode 100644 vendor/agentos/examples/custom/opencode.ts delete mode 100644 vendor/agentos/examples/custom/package.json delete mode 100644 vendor/agentos/examples/custom/pi-cli.ts delete mode 100644 vendor/agentos/examples/custom/tsconfig.json delete mode 100644 vendor/agentos/examples/debugging/agent-exit.ts delete mode 100644 vendor/agentos/examples/debugging/agent-logs.ts delete mode 100644 vendor/agentos/examples/debugging/package.json delete mode 100644 vendor/agentos/examples/debugging/tsconfig.json delete mode 100644 vendor/agentos/examples/embedded/agent-to-agent.ts delete mode 100644 vendor/agentos/examples/embedded/hooks.ts create mode 100644 vendor/agentos/examples/embedded/host-functions-bash.ts create mode 100644 vendor/agentos/examples/embedded/host-functions-javascript.ts create mode 100644 vendor/agentos/examples/embedded/host-functions-python.ts delete mode 100644 vendor/agentos/examples/embedded/models-and-credentials.ts create mode 100644 vendor/agentos/examples/embedded/software-install.ts delete mode 100644 vendor/agentos/examples/filesystem/README.md delete mode 100644 vendor/agentos/examples/filesystem/host-api.ts delete mode 100644 vendor/agentos/examples/filesystem/isolation.ts delete mode 100644 vendor/agentos/examples/filesystem/mount-custom-vfs.ts delete mode 100644 vendor/agentos/examples/filesystem/mount-google-drive.ts delete mode 100644 vendor/agentos/examples/filesystem/mount-host-dir.ts delete mode 100644 vendor/agentos/examples/filesystem/mount-s3.ts delete mode 100644 vendor/agentos/examples/filesystem/operations.ts delete mode 100644 vendor/agentos/examples/filesystem/package.json delete mode 100644 vendor/agentos/examples/filesystem/server.ts delete mode 100644 vendor/agentos/examples/filesystem/tsconfig.json delete mode 100644 vendor/agentos/examples/flue/README.md delete mode 100644 vendor/agentos/examples/flue/actors.ts delete mode 100644 vendor/agentos/examples/flue/agents/assistant.ts delete mode 100644 vendor/agentos/examples/flue/flue.config.ts delete mode 100644 vendor/agentos/examples/flue/package.json delete mode 100644 vendor/agentos/examples/flue/tsconfig.json delete mode 100644 vendor/agentos/examples/host-functions/README.md delete mode 100644 vendor/agentos/examples/host-functions/client.ts delete mode 100644 vendor/agentos/examples/host-functions/exec-bash.ts delete mode 100644 vendor/agentos/examples/host-functions/exec-javascript.ts delete mode 100644 vendor/agentos/examples/host-functions/exec-python.ts delete mode 100644 vendor/agentos/examples/host-functions/guest.mjs delete mode 100644 vendor/agentos/examples/host-functions/guest.py delete mode 100644 vendor/agentos/examples/host-functions/package.json delete mode 100644 vendor/agentos/examples/host-functions/server.ts delete mode 100644 vendor/agentos/examples/host-functions/tsconfig.json delete mode 100644 vendor/agentos/examples/js-runtime/node-modules-mount.ts delete mode 100644 vendor/agentos/examples/js-runtime/package.json delete mode 100644 vendor/agentos/examples/js-runtime/tsconfig.json delete mode 100644 vendor/agentos/examples/llm-credentials/README.md delete mode 100644 vendor/agentos/examples/llm-credentials/client.ts delete mode 100644 vendor/agentos/examples/llm-credentials/package.json delete mode 100644 vendor/agentos/examples/llm-credentials/per-tenant.ts delete mode 100644 vendor/agentos/examples/llm-credentials/server.ts delete mode 100644 vendor/agentos/examples/llm-credentials/tsconfig.json delete mode 100644 vendor/agentos/examples/multiplayer/README.md delete mode 100644 vendor/agentos/examples/multiplayer/collaborative.ts delete mode 100644 vendor/agentos/examples/multiplayer/observe-session.ts delete mode 100644 vendor/agentos/examples/multiplayer/package.json delete mode 100644 vendor/agentos/examples/multiplayer/server.ts delete mode 100644 vendor/agentos/examples/multiplayer/shared-output.ts delete mode 100644 vendor/agentos/examples/multiplayer/tsconfig.json delete mode 100644 vendor/agentos/examples/networking/README.md delete mode 100644 vendor/agentos/examples/networking/client-fetch-options.ts delete mode 100644 vendor/agentos/examples/networking/client-fetch.ts delete mode 100644 vendor/agentos/examples/networking/client-preview.ts delete mode 100644 vendor/agentos/examples/networking/client-revoke.ts delete mode 100644 vendor/agentos/examples/networking/client-run-server.ts delete mode 100644 vendor/agentos/examples/networking/package.json delete mode 100644 vendor/agentos/examples/networking/server-loopback.ts delete mode 100644 vendor/agentos/examples/networking/server-preview.ts delete mode 100644 vendor/agentos/examples/networking/server.ts delete mode 100644 vendor/agentos/examples/networking/tsconfig.json delete mode 100644 vendor/agentos/examples/opencode/README.md delete mode 100644 vendor/agentos/examples/opencode/client.ts delete mode 100644 vendor/agentos/examples/opencode/package.json delete mode 100644 vendor/agentos/examples/opencode/server.ts delete mode 100644 vendor/agentos/examples/opencode/tsconfig.json delete mode 100644 vendor/agentos/examples/permissions/README.md delete mode 100644 vendor/agentos/examples/permissions/bind-policy.ts delete mode 100644 vendor/agentos/examples/permissions/combine.ts delete mode 100644 vendor/agentos/examples/permissions/fs-rules.ts delete mode 100644 vendor/agentos/examples/permissions/package.json delete mode 100644 vendor/agentos/examples/permissions/server.ts delete mode 100644 vendor/agentos/examples/permissions/tsconfig.json delete mode 100644 vendor/agentos/examples/persistence/README.md delete mode 100644 vendor/agentos/examples/persistence/lifecycle-client.ts delete mode 100644 vendor/agentos/examples/persistence/package.json delete mode 100644 vendor/agentos/examples/persistence/restore-filesystem.ts delete mode 100644 vendor/agentos/examples/persistence/server.ts delete mode 100644 vendor/agentos/examples/persistence/tsconfig.json delete mode 100644 vendor/agentos/examples/pi/README.md delete mode 100644 vendor/agentos/examples/pi/client.ts delete mode 100644 vendor/agentos/examples/pi/package.json delete mode 100644 vendor/agentos/examples/pi/server.ts delete mode 100644 vendor/agentos/examples/pi/tsconfig.json delete mode 100644 vendor/agentos/examples/processes/README.md delete mode 100644 vendor/agentos/examples/processes/exec.ts delete mode 100644 vendor/agentos/examples/processes/lifecycle.ts delete mode 100644 vendor/agentos/examples/processes/package.json delete mode 100644 vendor/agentos/examples/processes/process-events.ts delete mode 100644 vendor/agentos/examples/processes/server.ts delete mode 100644 vendor/agentos/examples/processes/shell-events.ts delete mode 100644 vendor/agentos/examples/processes/shell.ts delete mode 100644 vendor/agentos/examples/processes/spawn.ts delete mode 100644 vendor/agentos/examples/processes/stdin.ts delete mode 100644 vendor/agentos/examples/processes/tsconfig.json delete mode 100644 vendor/agentos/examples/processes/visibility.ts delete mode 100644 vendor/agentos/examples/quickstart-app/Agent.tsx delete mode 100644 vendor/agentos/examples/quickstart-app/README.md delete mode 100644 vendor/agentos/examples/quickstart-app/client.ts delete mode 100644 vendor/agentos/examples/quickstart-app/package.json delete mode 100644 vendor/agentos/examples/quickstart-app/server.ts delete mode 100644 vendor/agentos/examples/quickstart-app/tsconfig.json delete mode 100644 vendor/agentos/examples/quickstart/agent-session/README.md delete mode 100644 vendor/agentos/examples/quickstart/agent-session/index.ts delete mode 100644 vendor/agentos/examples/quickstart/agent-session/package.json delete mode 100644 vendor/agentos/examples/quickstart/agent-session/tsconfig.json delete mode 100644 vendor/agentos/examples/quickstart/pi-extensions/README.md delete mode 100644 vendor/agentos/examples/quickstart/pi-extensions/index.ts delete mode 100644 vendor/agentos/examples/quickstart/pi-extensions/package.json delete mode 100644 vendor/agentos/examples/quickstart/pi-extensions/tsconfig.json delete mode 100644 vendor/agentos/examples/resource-limits/README.md delete mode 100644 vendor/agentos/examples/resource-limits/package.json delete mode 100644 vendor/agentos/examples/resource-limits/server.ts delete mode 100644 vendor/agentos/examples/resource-limits/tsconfig.json delete mode 100644 vendor/agentos/examples/sandbox/README.md delete mode 100644 vendor/agentos/examples/sandbox/client.ts delete mode 100644 vendor/agentos/examples/sandbox/existing-client.ts delete mode 100644 vendor/agentos/examples/sandbox/package.json delete mode 100644 vendor/agentos/examples/sandbox/server.ts delete mode 100644 vendor/agentos/examples/sandbox/tsconfig.json delete mode 100644 vendor/agentos/examples/sessions/README.md delete mode 100644 vendor/agentos/examples/sessions/cancel-prompt.ts delete mode 100644 vendor/agentos/examples/sessions/client.ts delete mode 100644 vendor/agentos/examples/sessions/close-destroy.ts delete mode 100644 vendor/agentos/examples/sessions/create-session.ts delete mode 100644 vendor/agentos/examples/sessions/multiple-sessions.ts delete mode 100644 vendor/agentos/examples/sessions/package.json delete mode 100644 vendor/agentos/examples/sessions/runtime-config.ts delete mode 100644 vendor/agentos/examples/sessions/send-prompt.ts delete mode 100644 vendor/agentos/examples/sessions/server-logs.ts delete mode 100644 vendor/agentos/examples/sessions/server.ts delete mode 100644 vendor/agentos/examples/sessions/stream-responses.ts delete mode 100644 vendor/agentos/examples/sessions/tsconfig.json delete mode 100644 vendor/agentos/examples/software/README.md delete mode 100644 vendor/agentos/examples/software/client.ts delete mode 100644 vendor/agentos/examples/software/package.json delete mode 100644 vendor/agentos/examples/software/quickstart-agent/index.ts delete mode 100644 vendor/agentos/examples/software/quickstart-agent/my-agent.ts delete mode 100644 vendor/agentos/examples/software/quickstart-node/index.ts delete mode 100644 vendor/agentos/examples/software/quickstart-node/my-tool.ts delete mode 100644 vendor/agentos/examples/software/quickstart-wasm/index.ts delete mode 100644 vendor/agentos/examples/software/quickstart-wasm/my-cmds.ts delete mode 100644 vendor/agentos/examples/software/registry-usage.ts delete mode 100644 vendor/agentos/examples/software/server.ts delete mode 100644 vendor/agentos/examples/software/software/common.ts delete mode 100644 vendor/agentos/examples/software/software/pi.ts delete mode 100644 vendor/agentos/examples/software/tsconfig.json delete mode 100644 vendor/agentos/examples/vercel-eve/.gitignore delete mode 100644 vendor/agentos/examples/vercel-eve/README.md delete mode 100644 vendor/agentos/examples/vercel-eve/actors.ts delete mode 100644 vendor/agentos/examples/vercel-eve/agent/agent.ts delete mode 100644 vendor/agentos/examples/vercel-eve/agent/instructions.md delete mode 100644 vendor/agentos/examples/vercel-eve/agent/sandbox.ts delete mode 100644 vendor/agentos/examples/vercel-eve/core.ts delete mode 100644 vendor/agentos/examples/vercel-eve/package.json delete mode 100644 vendor/agentos/examples/vercel-eve/tsconfig.json delete mode 100644 vendor/agentos/examples/vercel-eve/world.ts delete mode 100644 vendor/agentos/examples/webhooks/package.json delete mode 100644 vendor/agentos/examples/webhooks/server.ts delete mode 100644 vendor/agentos/examples/webhooks/tsconfig.json delete mode 100644 vendor/agentos/examples/workflows/README.md delete mode 100644 vendor/agentos/examples/workflows/chaining-client.ts delete mode 100644 vendor/agentos/examples/workflows/client.ts delete mode 100644 vendor/agentos/examples/workflows/package.json delete mode 100644 vendor/agentos/examples/workflows/server.ts delete mode 100644 vendor/agentos/examples/workflows/tsconfig.json diff --git a/vendor/agentos/docs/content/docs/agent-to-agent.mdx b/vendor/agentos/docs/content/docs/agent-to-agent.mdx deleted file mode 100644 index 0557bcee..00000000 --- a/vendor/agentos/docs/content/docs/agent-to-agent.mdx +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: "Agent-to-Agent Communication" -description: "Connect agents through agentOS host functions so one coding agent can call another while sessions, permissions, and results remain isolated." -skill: true ---- - -Agents communicate through [host functions](/agentos/docs/host-functions). You define a host-function collection that lets one agent send work to another, and the agent calls it like any other CLI command. - -## Example: code writer + reviewer - -This example gives the writer agent a `review` host function. The writer sends the file's full contents (the VMs share no filesystem), and the host function writes them into a separate reviewer VM and sends a review prompt back through the reviewer. - - - - - - -The writer agent sees the review host function as a CLI command. Because the VMs share no filesystem, it sends the full file contents, not a path: - -```bash -agentos-review submit --code "$(cat api.ts)" -``` - -The host function writes the contents into the reviewer's VM, prompts the reviewer, and returns the review to the writer as JSON. - -## Why host functions? - -Host functions are the natural communication layer between agents because: - -- **The agent doesn't need to know about other agents.** It just calls a host function. You can swap the implementation without changing the agent's behavior. -- **No credentials in the VM.** The host function executes on the server, so it can access other agents directly without exposing connection details. -- **Composable.** Chain any number of agents by adding more host functions. Each host function is a self-contained bridge to another agent. - -## Recommendations - -- Each agent has its own isolated VM and filesystem (they share no filesystem). Pass file contents through the host-function input, then use `writeFile` in the host function to place them in the other VM. -- Use [Workflows](/agentos/docs/workflows) to make multi-agent pipelines durable across restarts. - -## Embedded API - -Create one `AgentOs` handle per agent and call the reviewer from a host function. -Your application owns both handles and their lifecycle. - - - -Read more in the [embedded API quickstart](/agentos/docs/quickstart-embedded). diff --git a/vendor/agentos/docs/content/docs/agents/claude.mdx b/vendor/agentos/docs/content/docs/agents/claude.mdx deleted file mode 100644 index ab623dd5..00000000 --- a/vendor/agentos/docs/content/docs/agents/claude.mdx +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: "Claude Code" -description: "Run Claude Code inside an agentOS VM with durable sessions, configurable skills, MCP servers, credentials, and filesystem access." -skill: false ---- - -## Quickstart - - - - - - - -Read [Sessions](/agentos/docs/sessions) first for session options, streaming events, prompts, and lifecycle management. - -## Model & credentials - -Set the relevant variable(s) on the session's `env`, sourced from your server's environment: - -- `ANTHROPIC_API_KEY` — Anthropic API key (direct API). -- `ANTHROPIC_AUTH_TOKEN` — bearer token for proxy / OAuth auth. -- `ANTHROPIC_BASE_URL` — route through a gateway or proxy endpoint. -- `ANTHROPIC_MODEL` — override the default model. -- `CLAUDE_CODE_USE_BEDROCK=1` — use Amazon Bedrock (auth via the AWS credential chain: `AWS_REGION`, `AWS_PROFILE`, …). -- `CLAUDE_CODE_USE_VERTEX=1` — use Google Vertex AI (auth via Google Cloud credentials). - -See [Models & Credentials](/agentos/docs/models-and-credentials), and Claude Code's [environment variables](https://code.claude.com/docs/en/env-vars) for the full list. - -## System prompt - -By default, the agentOS [system prompt](/agentos/docs/system-prompt), including your `additionalInstructions`, is appended to Claude Code's built-in `claude_code` system prompt. - -To use only your own system prompt, set `ACP_SYSTEM_PROMPT_MODE=replace` on the session's `env`. The built-in Claude Code prompt is dropped, and Claude receives the assembled agentOS prompt instead. Use `skipOsInstructions: true` with `additionalInstructions` to send only your text. - -```ts -await agent.sessions.open({ - agent: "claude", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY!, ACP_SYSTEM_PROMPT_MODE: "replace" }, - skipOsInstructions: true, - additionalInstructions: "You are a support assistant for Acme's billing API.", -}); -``` - -`ACP_SYSTEM_PROMPT_MODE` accepts `append` (the default) or `replace`. Any other value makes the session fail to start with an error that names the variable. `replace` also needs a non-empty prompt, so don't combine it with `skipOsInstructions` unless you set `additionalInstructions`. - -## Skills - -Claude Code discovers [agent skills](https://docs.claude.com/en/docs/claude-code/skills) from `SKILL.md` files under its skills directory. Write the skill into the VM before creating a session and Claude Code loads it automatically. - - - -## MCP servers - -Expose extra tools to the agent by passing `mcpServers` to `openSession`. Both local child-process servers and remote URLs are supported. - - - - -**Pre-install `npx`-launched servers.** A local server started with `npx -y …` writes install progress to **stdout** on its first run, which corrupts the MCP stdio handshake (you'll see `Connection closed`). Pre-install it in the VM so `npx` is silent — `await agent.process.exec("npm install -g @modelcontextprotocol/server-filesystem")` before the session — or pin the package and point `command` at the installed binary. - - -## Customizing the agent - -Claude Code is a built-in agent, but it's just a software package under the hood. To ship your own ACP adapter, swap the underlying agent SDK, or register a tweaked build as a new agent, see [Custom Agents](/agentos/docs/agents/custom). diff --git a/vendor/agentos/docs/content/docs/agents/codex.mdx b/vendor/agentos/docs/content/docs/agents/codex.mdx deleted file mode 100644 index a3fce686..00000000 --- a/vendor/agentos/docs/content/docs/agents/codex.mdx +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: "Codex" -seoTitle: "Run the Codex Coding Agent in agentOS" -description: "Run Codex inside an agentOS VM with durable sessions, configurable skills, MCP servers, credentials, and filesystem access." -skill: false ---- - -## Quickstart - - - - - - -Read [Sessions](/agentos/docs/sessions) first for session options, streaming events, prompts, and lifecycle management. - -## Model & credentials - -Set the relevant variable(s) on the session's `env`, sourced from your server's environment: - -- `OPENAI_API_KEY` — OpenAI API key (built-in `openai` provider). -- `OPENAI_BASE_URL` — route through a gateway or OpenAI-compatible endpoint. -- Custom providers — defined in `~/.codex/config.toml`; each provider's `env_key` names the variable Codex reads for its key (e.g. `AZURE_OPENAI_API_KEY`, `MISTRAL_API_KEY`). - -See [Models & Credentials](/agentos/docs/models-and-credentials), and Codex's [config reference](https://developers.openai.com/codex/config-reference) for details. - -## Skills - -Codex discovers `SKILL.md` files from its skills directory. Write the skill into the VM before creating a session and Codex loads it automatically. - - - -## MCP servers - -Expose extra tools to the agent by passing `mcpServers` to `openSession`. Both local child-process servers and remote URLs are supported. - - - - -**Pre-install `npx`-launched servers.** A local server started with `npx -y …` writes install progress to **stdout** on its first run, which corrupts the MCP stdio handshake (you'll see `Connection closed`). Pre-install it in the VM so `npx` is silent — `await agent.process.exec("npm install -g @modelcontextprotocol/server-filesystem")` before the session — or pin the package and point `command` at the installed binary. - - -## Customizing the agent - -Codex is a built-in agent, but it's just a software package under the hood. To ship your own ACP adapter, swap the underlying agent SDK, or register a tweaked build as a new agent, see [Custom Agents](/agentos/docs/agents/custom). diff --git a/vendor/agentos/docs/content/docs/agents/custom.mdx b/vendor/agentos/docs/content/docs/agents/custom.mdx deleted file mode 100644 index 05134c8c..00000000 --- a/vendor/agentos/docs/content/docs/agents/custom.mdx +++ /dev/null @@ -1,98 +0,0 @@ ---- -title: "Custom Agents" -description: "Integrate a custom coding agent with agentOS through the Agent Client Protocol, then configure its package, commands, and session behavior." ---- - -A custom agent is a program that runs **inside the VM** to drive a coding agent. AgentOS spawns it when you call `openSession({ sessionId, agent })` and talks to it over the Agent Client Protocol. You ship it as a software package, exactly like the built-in agents. - -## Agent Client Protocol (ACP) - -agentOS speaks the [Agent Client Protocol (ACP)](https://agentclientprotocol.com) to every agent: JSON-RPC over stdio. The agent reads protocol messages on **stdin** and writes them on **stdout**, so stdout is reserved for ACP and **stderr is used for logs**. Your program only needs to speak ACP; how it runs the underlying model is up to you. See the [ACP documentation](https://agentclientprotocol.com) for the full protocol. - -## Two ways to build an agent - -There are two shapes, depending on whether the agent runs in the ACP process or in its own. - -### Single process (embedded) - -The ACP adapter **embeds the agent SDK** and runs it in the same process. One process inside the VM, lower memory footprint. - - - - - - - - - Host - - ACP - - VM - - ACP adapter + - agent (embedded) - - -For example, an adapter to run **OpenCode**, which speaks ACP natively. One package is both the ACP process and the agent, so there's no separate adapter and nothing else is spawned. - - - -### ACP adapter (separate agent) - -The ACP adapter is a thin **bridge** that spawns the real agent as its **own process** (a CLI or SDK) and translates between it and ACP. Full agent feature set, higher memory. - - - - - - - - - Host - - ACP - - VM - - ACP adapter - - spawns - - Agent process - (CLI / SDK) - - -For example, an adapter to run **Pi**: the `pi` CLI doesn't speak ACP, so `pi-acp` speaks ACP and spawns the CLI as a separate process. The packaged agent bundles both — its `agentos-package.json` names `pi-acp` as the `acpEntrypoint` and points it at the `pi` CLI via `agent.env`. - - - -## Use your agent - -Register the package on the server with `software`. Sessions are then created from the client by `id`, exactly like any built-in agent. - -```ts title="server.ts" -import { agentOS, setup, defineSoftware } from "@rivet-dev/agentos"; - -const myAgent = defineSoftware({ - packagePath, // the packed agent .aospkg; its embedded manifest carries the agent block -}); - -const vm = agentOS({ software: [myAgent] }); - -export const registry = setup({ use: { vm } }); -registry.start(); -``` - -See [Sessions](/agentos/docs/sessions) for creating and driving sessions. Package your adapter with `agentos-toolchain pack --agent my-agent-acp` so its dependencies are bundled into the self-contained package directory and the `agent` block (naming the `bin/` ACP entrypoint) is written into the package's `agentos-package.json`, rather than shipping it as a loose file. - -All built-in agents are defined exactly this way. Browse them for reference on [GitHub](https://github.com/rivet-dev/agentos/tree/main/software). - -## Read more - -- [Defining software packages](/agentos/docs/custom-software/definition): the full descriptor reference, including the `agentos-package.json` schema and every `agent` field (`acpEntrypoint`, `env`, `launchArgs`, `snapshot`). -- [Building binaries](/agentos/docs/custom-software/building-wasm): compile WASM command binaries and use the registry. - -## Debugging - -When a custom agent exits mid-turn or a tool call fails, capture the agent's stderr with the `onAgentStderr` hook on `AgentOs.create()`. The agent uses stdout for ACP, so stderr carries its logs and crash output. See [Debugging](/agentos/docs/debugging) for that hook and the runtime (sidecar) logs. diff --git a/vendor/agentos/docs/content/docs/agents/opencode.mdx b/vendor/agentos/docs/content/docs/agents/opencode.mdx deleted file mode 100644 index 4292c051..00000000 --- a/vendor/agentos/docs/content/docs/agents/opencode.mdx +++ /dev/null @@ -1,79 +0,0 @@ ---- -title: "OpenCode" -description: "Run OpenCode inside an agentOS VM with durable sessions, configurable skills, MCP servers, credentials, and filesystem access." -skill: false ---- - -## Quickstart - - - - - - - -Read [Sessions](/agentos/docs/sessions) first for session options, streaming events, prompts, and lifecycle management. - -## Model & credentials - -OpenCode auto-detects a provider when its key is present on the session's `env`, sourced from your server's environment. Common variables: - -- `ANTHROPIC_API_KEY` — Anthropic (Claude), the default. -- `OPENAI_API_KEY` — OpenAI. -- `OPENROUTER_API_KEY` — OpenRouter. -- `GEMINI_API_KEY` — Google Gemini. -- `GROQ_API_KEY` — Groq. -- …plus Amazon Bedrock, Azure, Google Vertex, and 70+ providers via [models.dev](https://models.dev). - -See [Models & Credentials](/agentos/docs/models-and-credentials), and OpenCode's [providers docs](https://opencode.ai/docs/providers/) for the full list. - -## Model configuration - -To pin a specific model — or point a provider at a custom endpoint — write an OpenCode config file into the VM before creating the session. OpenCode reads `/.config/opencode/opencode.json` (the agent's `HOME` is `/home/agentos` by default). - - -Two settings will silently produce an **empty response** if wrong: -- The Anthropic provider **`baseURL` must end in `/v1`** (`https://api.anthropic.com/v1`). Without `/v1`, OpenCode calls `…/messages` and Anthropic returns `404 Not Found`. -- The **`model` must be a current model id.** A retired id returns a `404 not_found_error` and the turn ends with zero output. - - -```ts -// Write the config before creating the session -await agent.filesystem.mkdir("/home/agentos/.config/opencode", { recursive: true }); -await agent.filesystem.writeFile( - "/home/agentos/.config/opencode/opencode.json", - JSON.stringify({ - $schema: "https://opencode.ai/config.json", - model: "anthropic/claude-haiku-4-5-20251001", // use a current model id - provider: { - // The Anthropic baseURL MUST include /v1, or requests 404. - anthropic: { options: { baseURL: "https://api.anthropic.com/v1" } }, - }, - }), -); - -await agent.sessions.open({ - agent: "opencode", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, -}); -``` - -## Skills - -OpenCode discovers `SKILL.md` files from its skills directory. Write the skill into the VM before creating a session and OpenCode loads it automatically. - - - -## MCP servers - -Expose extra tools to the agent by passing `mcpServers` to `openSession`. Both local child-process servers and remote URLs are supported. - - - - -**Pre-install `npx`-launched servers.** A local server started with `npx -y …` writes install progress to **stdout** on its first run, which corrupts the MCP stdio handshake (you'll see `Connection closed`). Pre-install it in the VM so `npx` is silent — `await agent.process.exec("npm install -g @modelcontextprotocol/server-filesystem")` before the session — or pin the package and point `command` at the installed binary. - - -## Customizing the agent - -OpenCode is a built-in agent, but it's just a software package under the hood. To ship your own ACP adapter, swap the underlying agent SDK, or register a tweaked build as a new agent, see [Custom Agents](/agentos/docs/agents/custom). diff --git a/vendor/agentos/docs/content/docs/agents/pi.mdx b/vendor/agentos/docs/content/docs/agents/pi.mdx deleted file mode 100644 index aafad71e..00000000 --- a/vendor/agentos/docs/content/docs/agents/pi.mdx +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: "Pi" -seoTitle: "Run the Pi Coding Agent in agentOS" -description: "Run Pi inside an agentOS VM with durable sessions, extensions, custom configuration, provider credentials, and filesystem access." -skill: true ---- - -## Quickstart - - - - - - - -Read [Sessions](/agentos/docs/sessions) first for session options, streaming events, prompts, and lifecycle management. - -## Model & credentials - -Set the relevant variable on the session's `env`, sourced from your server's environment: - -- `ANTHROPIC_API_KEY` — Anthropic (Claude), the default. -- Other providers — use the provider-named key (e.g. `OPENAI_API_KEY`, `GEMINI_API_KEY`, `OPENROUTER_API_KEY`). - -See [Models & Credentials](/agentos/docs/models-and-credentials), and Pi's [providers docs](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/docs/providers.md) for the full list. - -## Skills - -Pi discovers `SKILL.md` files from its skills directory. Write the skill into the VM before creating a session and Pi loads it automatically. - - - -## MCP servers - -Expose extra tools to the agent by passing `mcpServers` to `openSession`. Both local child-process servers and remote URLs are supported. - - - - -**Pre-install `npx`-launched servers.** A local server started with `npx -y …` writes install progress to **stdout** on its first run, which corrupts the MCP stdio handshake (you'll see `Connection closed`). Pre-install it in the VM so `npx` is silent — `await agent.process.exec("npm install -g @modelcontextprotocol/server-filesystem")` before the session — or pin the package and point `command` at the installed binary. - - -## Extensions - -Pi supports [extensions](https://github.com/badlogic/pi-mono/tree/main/packages/coding-agent/examples/extensions) that let you register custom tools, modify the system prompt, and hook into agent lifecycle events. Write a `.js` file into the VM's extensions directory before creating a session and Pi discovers it automatically. - -Pi scans two directories for `.js` extension files: - -| Directory | Scope | -|-----------|-------| -| `~/.pi/agent/extensions/` | Global — applies to all Pi sessions | -| `/.pi/extensions/` | Project — applies only when cwd matches | - - - -See the [Pi extension documentation](https://github.com/badlogic/pi-mono/tree/main/packages/coding-agent/examples/extensions) for the full extension API. - -## Customizing the agent - -Pi is a built-in agent, but it's just a software package under the hood. To ship your own ACP adapter, swap the underlying agent SDK, or register a tweaked Pi build as a new agent, see [Custom Agents](/agentos/docs/agents/custom). diff --git a/vendor/agentos/docs/content/docs/approvals.mdx b/vendor/agentos/docs/content/docs/approvals.mdx deleted file mode 100644 index b2366b13..00000000 --- a/vendor/agentos/docs/content/docs/approvals.mdx +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: "Approvals" -description: "Handle Agent Client Protocol permission requests in agentOS, present durable approval choices, and correlate responses with active sessions." ---- - -Set a session's immutable `permissionPolicy` when calling `openSession`: - -- `reject_all` prefers a native `reject_once` option, then `reject_always`, and fails with `permission_policy_unsatisfied` when neither exists. -- `allow_all` (the default) prefers `allow_once`, then `allow_always`. -- `ask` durably records the exact ACP `RequestPermissionRequest` in the ordinary sequenced session-event stream. - -This controls how AgentOS answers an adapter's native ACP permission request. It does not grant VM filesystem or network permissions, change which tools the adapter exposes, or become ACP adapter configuration. - -Subscribing to session events does not enable interactive approval. You must set `permissionPolicy: "ask"` in `openSession`; if it is omitted, the default `allow_all` policy resolves requests automatically and no `permission_request` event is emitted or persisted. - -## Human in the loop - -With `ask`, respond using the AgentOS `requestId` plus one of the exact `optionId` values supplied by the adapter. Do not translate options into AgentOS-specific `once`/`always` strings. - - - - - - -The `permission_request` session-event variant contains: - -- `sessionId`: stable public AgentOS session ID from the durable event envelope. -- `requestId`: globally unique AgentOS correlation ID; the adapter JSON-RPC ID is private. -- `toolCall`, `options`, and optional `_meta`: exact native ACP request fields exposed directly, without a nested `request` object. - -`respondPermission` requires an explicit `sessionId` and returns `accepted` or `not_pending` with a specific terminal reason. The first valid response wins atomically. Invalid options fail with `invalid_permission_option` and list the offered IDs. `accepted` means the decision reached the active ACP waiter; it does not mean the tool operation succeeded. - -Permission requests have no sidecar expiry. They remain pending until answered or terminated by prompt cancellation, adapter exit, session deletion, or VM shutdown. RivetKit's actor-wide safety bound defaults to about 24.8 days rather than the old 15-minute action timeout. Both the request and its accepted response are durable history entries, so reconnecting consumers subscribe, read history after their last sequence, and deduplicate by `(sessionId, sequence)`. - -## Automatic policy - -For a fully automated session, omit `permissionPolicy` or choose `allow_all` explicitly. No permission event or client round-trip is required. - - - -For unattended fail-closed work, choose `reject_all` explicitly. ACP approval is advisory; VM filesystem, network, and process permissions remain the security boundary. Automatically handled requests are neither emitted nor persisted. - -## Embedded API - -Approval requests arrive through the embedded VM's process-local -`onSessionEvent()` callback. - - - -Read more in the [embedded API quickstart](/agentos/docs/quickstart-embedded). diff --git a/vendor/agentos/docs/content/docs/architecture.mdx b/vendor/agentos/docs/content/docs/architecture.mdx index 3cc9b1c7..b0a43696 100644 --- a/vendor/agentos/docs/content/docs/architecture.mdx +++ b/vendor/agentos/docs/content/docs/architecture.mdx @@ -1,367 +1,35 @@ --- -title: "Overview" -description: "Explore agentOS architecture from trusted clients and sidecars to isolated VMs, kernels, executors, coding-agent sessions, and Rivet Actor persistence." -skill: true +title: "Architecture" +description: "How Core, the sidecar, kernel, VFS, and executors fit together." --- -agentOS runs AI agents and untrusted code safely inside fully virtualized Linux VMs. Nothing the guest does touches your host directly: there is no real host filesystem, no real host network socket, and no real host process. Every guest operation is serviced by a kernel that agentOS owns. +`@rivet-dev/agentos-core` controls the runtime from a trusted Node.js process. +It may retain host-only state such as host function handlers, mount plugins, +local package paths, and custom scheduling. -This page is a high-level tour. It walks through the overall shape, the parts that make up a VM, how agent sessions work, and the orchestration layer underneath. Each section links out to a detailed page when you want to go deeper. +## Runtime boundary -## The big picture +The trusted sidecar owns the kernel, VFS, process and socket tables, +permissions, resource policy, package acquisition and projection, and language +executors. Untrusted JavaScript, Python, WASM, and third-party package code runs +on the guest side of that boundary. -A running agentOS system has three roles: your **app** (the client), your **server** (which runs the sidecar that hosts the VMs), and the **VM** where guest code actually runs. Your app never runs guest code itself, it asks the server to. +The native sidecar binary uses fd 0 for requests, stdout for +ordinary events, and inherited fd 3 for responses, callbacks, heartbeats, and +shutdown control. - - - - - - - - OS - - - - Client - JS · Browser · Backend - - - Server - - - - - - - - - - - - - - - - - - - - - - - OS - = an isolated VM - - +## Durability -The client speaks to the agentOS server over the wire. The server runs the **sidecar**, the trusted core that hosts every VM: it owns each VM's kernel and brokers every guest syscall the agent makes (filesystem, processes, network, permissions) before carrying it out. Each VM is a fully isolated world, so agents are isolated from one another and from your host. +The VM database has independent schema owners: -### Your app (the client) +| Owner | Namespace | +| --- | --- | +| Filesystem | `agentos_fs_*` | +| Core | `agentos_core_*` | -- **Trusted caller.** Your app drives agentOS. It creates VMs, opens sessions, sends prompts, and reads results back. -- **Never runs guest code.** The agent and any code it generates run in the VM, not in your app's process. -- **Available everywhere.** There is a TypeScript client and a Rust client, and the same VM is reachable from a Node script, a browser/React app, or a separate backend. -- **Owns the configuration.** Everything you send (VM setup, permission policy, resource limits, mounts) is trusted input. See the [Security Model](/agentos/docs/security-model) for why your configuration is not an attack surface. +Each owner advances only its own migration ladder. There is no legacy storage +adoption path. -### Your server (the sidecar) - -- **The trusted core.** The sidecar is the part of the system that owns everything: the kernel, the virtual filesystem, the process and socket tables, pipes, PTYs, the permission policy, and DNS. -- **The enforcement point.** Every request the VM makes is serviced here. The sidecar decides what is allowed before carrying it out. -- **Hosts every VM.** A single sidecar manages many VMs side by side, each with its own kernel, filesystem, and process table, so every agent runs in its own isolated world. A crash or runaway in one VM never affects another. - -### The VM - -- **A fully virtualized Linux environment.** Each VM has its own filesystem, process table, and network policy. Two VMs share nothing. -- **The unit of isolation.** A crash or runaway in one VM never affects another. -- **Where guest code lives.** The agent, the shell, npm packages, and any generated code all run inside the VM, behind the kernel's boundary. - -## Anatomy of a Linux VM - -Inside every VM there are two halves. The **kernel** is the trusted core that owns all the resources and rules. The **executor** is where untrusted guest code actually runs. Guest code can only *ask* the kernel for things, it never holds a real capability of its own. - - - - - - - - - The VM - - - Kernel - trusted core, every operation goes through here - - virtual filesystem - process table - socket table - pipes / PTYs - DNS - permission policy · network allowlist · resource limits - - - - - syscalls / replies - - - Executor - untrusted, runs guest code, holds no capabilities - - guest JavaScript (native V8) - WASM - shell · coreutils · npm packages · native binaries - - - -### Kernel: the trusted core - - - - - - - - - guest request - - - Kernel - - - - - - filesystem - processes - network & DNS - policy & limits - - - -The kernel is the single chokepoint. Each kind of guest operation is serviced by a kernel-owned subsystem, never by a real host capability. - -- **Virtual filesystem.** A per-VM filesystem. Guest reads and writes hit the VFS, not your host disk. -- **Process table.** A virtual process table. Child processes are kernel-managed and visible only inside their VM. No real host process is ever spawned for guest work. -- **Socket table and DNS.** A virtual network stack. Outbound traffic is gated by the network allowlist. -- **Pipes and PTYs.** Kernel-owned IPC and terminal devices, so shells and pipelines behave like real Linux. -- **Policy and limits.** The kernel checks the applied permission policy, network allowlist, and resource limits on every request. - -### Executor: where guest code runs - - - - - - - - - Executor - untrusted · no capabilities - - JS (V8) - WASM - nativebinaries - - - syscall - - reply - - Kernel - - -The executor is the untrusted half of the VM. It runs the guest code and reaches the kernel for everything else. - -- **JavaScript Acceleration.** Guest JavaScript runs on a native V8 runtime (the same engine in Chrome and Node.js, with the full JIT compiler) inside an isolate. This is what we call **JavaScript Acceleration**: the guest's JavaScript executes at native speed, not through an interpreter or a translation shim. It is genuinely fast, and it presents normal Node.js semantics. See [JavaScript](/agentos/docs/javascript). -- **WASM alongside it.** The shell (`sh`) and the coreutils behind process execution ship as WebAssembly modules, and you can run your own WASM too. See [POSIX Syscalls](/agentos/docs/architecture/posix-syscalls) and the [Compiler Toolchain](/agentos/docs/architecture/compiler-toolchain). -- **Native binaries.** Tools mounted into the VM run inside the same boundary as everything else. -- **No host fallthrough.** The executor holds no capability of its own. For every file read, process spawn, or socket open, it issues a syscall and blocks for the kernel's reply. - -### Processes & shell - - - - - - - - - exec() / run() - spawn / shell - - - - - process table - virtual · per-VM - - - pipes & PTYs - - -- **A real process model.** `exec()` and `run()` start fresh guest processes; you can also `spawn` long-running ones and open interactive shells. -- **Kernel-managed.** Every process lives in the virtual process table, with stdio bridged through kernel-owned pipes and PTYs. -- **Fresh each run.** Each `exec()` / `run()` starts a brand new guest process, so in-memory state never leaks from one run into the next. -- See [Processes](/agentos/docs/architecture/processes) for the internals. - -### Virtual filesystem - - - - overlay (guest writes) - root layer (snapshot) - - - host dir mount - S3 mount - cloud store - - mount points grafted onto guest paths - - -- **Layered engines.** The VFS is a tree of engines: a root layer bootstrapped from a snapshot, an overlay for writes, and mount points that graft other backends onto guest paths. -- **Host-backed mounts.** A guest path can be backed by a host directory, S3, or a cloud store. The kernel confines all guest I/O to the mount root, even against symlink and `..` tricks. -- **Persisted.** The `/home/agentos` filesystem survives sleep/wake. -- See [Filesystem](/agentos/docs/architecture/filesystem) for the internals. - -### Networking - - - - - - - - - fetch() - node:http - node:net - WASM sockets - - - - - - - socket table - kernel-owned - - - egress allowlist - - -- **One authoritative transport.** Guest `fetch()`, `node:http`, `node:net`, and WASM sockets all target the same kernel socket table. No part of guest networking opens a real host socket on its own. -- **Egress policy.** Outbound traffic is gated by the network allowlist; loopback traffic stays confined to the VM. -- **Preview URLs.** Servers a guest starts can be exposed through signed preview URLs. -- See [Networking](/agentos/docs/architecture/networking) for the internals. - -The security boundary that matters is between the trusted sidecar and the untrusted executor. Everything the guest tries to do crosses into the kernel, where the policy is checked before the operation runs. See the [Security Model](/agentos/docs/security-model) for the full threat model. - -## Agents & sessions - -An agent (such as [Pi](https://github.com/mariozechner/pi-coding-agent)) is just another guest process running inside a VM, behind the same boundary as any other code. A **session** keeps that agent alive across many prompts and streams its output back to your app as events. - - - - - - - - - Client - your app - - - prompt - - events - - - The VM - - Agent session - long-lived agent process - - - - Filesystem - SQLite over UDS - - -### Sessions & durable files - -- **Long-lived.** Where a bare `exec()` runs once and exits, a session keeps an agent alive across many prompts. -- **Streamed.** The agent's output flows back to your app in real time as `sessionEvent`s. -- **Durable semantic events.** Completed ACP updates and interactive permission request/response records are sequenced in SQLite; streaming message deltas remain live-only. -- **Durable files.** Files under `/home/agentos` survive sleep through the sidecar's direct SQLite-over-UDS connection. -- **Context injected.** agentOS adds a system prompt describing the VM environment, available commands, and host functions, layered on top of the agent's own instructions. See [System Prompt](/agentos/docs/system-prompt). -- See [Agent Sessions](/agentos/docs/architecture/agent-sessions) for the internals. - -### Permissions & approvals - -- **Two layers, different jobs.** The lower-level [permission policy](/agentos/docs/permissions) is enforced by the kernel on every guest syscall (nothing is allowed until you opt in). On top of that, [approvals](/agentos/docs/approvals) are about an agent asking before it uses a tool. -- **Human-in-the-loop or automatic.** Use the default `allow_all`, explicit `reject_all`, or subscribe to `permission_request` variants on the ordinary session-event stream with `permissionPolicy: "ask"`. -- **Blocks until answered.** An `ask` request has no expiry and keeps the active turn awake until a response or explicit lifecycle transition wins the race. - -## Orchestration (Rivet Actors) - -The `agentOS()` actor (from `@rivet-dev/agentos`) wraps the raw VM in a [Rivet Actor](/actors/docs/), which adds durable state, scheduling, and orchestration. This is what gives you persistence, cron, and workflows out of the box. It also registers inspector tabs in the Rivet dashboard, so every actor comes with a live view of its transcript, filesystem, and processes. - - - - Rivet Actor - durable, addressable server object - - - agentOS VM - the virtual Linux VM - - - Cron - Workflows - Persistence · sleep / wake - Durablestate - - - -### What are actors? - -- **Durable server objects.** A Rivet Actor is a long-lived, addressable object with its own state. You reach a specific VM by name (`vm.getOrCreate("my-agent")`). -- **Stateful by default.** The actor persists its filesystem, actor state, durable session metadata, and completed ACP history. Active adapter processes remain runtime state. -- **The portable runtime.** Actors give you a consistent way to run `agentOS()` on any infrastructure, with persistence, networking, and orchestration built in. - -### Cron - -- **Recurring work.** Schedule a shell command or an agent session on a cron expression. -- **Overlap control.** Choose what happens when a run is still going when the next is due (`allow`, `skip`, or `queue`). -- **Observable.** Stream `cronEvent`s to watch executions. See [Crons & Loops](/agentos/docs/cron). - -### Workflows - -- **Durable multi-step tasks.** A workflow is the actor's `run` handler wrapped in `workflow()`, where each `ctx.step()` is recorded, retried, and resumed independently. -- **Crash-proof.** If the process dies mid-run, replay skips completed steps and continues where it left off. -- **Composable.** The output of one step feeds the next: clone a repo, let an agent fix a bug, run the tests. See [Workflows & Graphs](/agentos/docs/workflows). - -### Persistence & sleep/wake - -- **Sleeps when idle.** After a grace period (15 minutes by default) with no activity, the VM sleeps to free resources. -- **Wakes on demand.** It wakes automatically when a client connects or a cron job fires. -- **What survives.** The `/home/agentos` filesystem, actor state, preview tokens, durable session metadata, and completed ACP history persist. On wake, `openSession` restores the adapter when possible and otherwise starts it with AgentOS history as context. In-flight deltas, running processes, and open shells do not survive. See [Persistence & Sleep](/agentos/docs/persistence). - -## Going deeper - -This page is the map. Each subsystem has its own detailed page in the Advanced architecture section: - -- **[Agent Sessions](/agentos/docs/architecture/agent-sessions)**: how a session is bound to a VM, and how prompts and events flow end to end. -- **[Processes](/agentos/docs/architecture/processes)**: the virtual process table, `exec()` / `run()`, child processes, and PTYs. -- **[Filesystem](/agentos/docs/architecture/filesystem)**: the per-VM virtual filesystem, overlays, and host-backed mounts. -- **[Networking](/agentos/docs/architecture/networking)**: the virtual socket table, DNS, the allowlist, and guest `fetch()`. -- **[JavaScript Executor & Socket Reactor](/agentos/docs/architecture/javascript-executor)**: how the shared Tokio runtime, V8 executor threads, coalesced readiness, bounded channels, and Node stream backpressure fit together. -- **[POSIX Syscalls](/agentos/docs/architecture/posix-syscalls)**: how WebAssembly guests behave like normal POSIX programs on top of the kernel. -- **[Compiler Toolchain](/agentos/docs/architecture/compiler-toolchain)**: how the shell and coreutils are compiled to WebAssembly and mounted into the VM. -- **[System Prompt](/agentos/docs/system-prompt)**: the context agentOS injects into every agent session. -- **[Persistence & Sleep](/agentos/docs/persistence)**: what survives sleep/wake, and how VMs sleep and wake. - -For the trust model and what counts as a sandbox escape, see the [Security Model](/agentos/docs/security-model). +The default VM root is an ephemeral in-memory overlay over the bundled base +image. Store the root filesystem in the VM's SQLite database for files that +must survive VM recreation; see [Persistence](/agentos/docs/persistence). diff --git a/vendor/agentos/docs/content/docs/architecture/agent-sdk-snapshots.mdx b/vendor/agentos/docs/content/docs/architecture/agent-sdk-snapshots.mdx deleted file mode 100644 index c6f7f885..00000000 --- a/vendor/agentos/docs/content/docs/architecture/agent-sdk-snapshots.mdx +++ /dev/null @@ -1,79 +0,0 @@ ---- -title: "Agent SDK Snapshots" -description: "Learn how agentOS evaluates a coding agent's SDK once, creates a reusable V8 heap snapshot, restores isolated sessions, and enforces snapshot safety." -skill: true ---- - -These internal architecture docs are mostly generated and maintained by LLMs, then reviewed by humans. They are intentionally verbose; use your preferred LLM to ask focused questions about the architecture as needed. - -This page is an internals deep-dive on **agent SDK snapshotting** — an optional optimization that loads an agent's SDK *once per sidecar* and reuses it for every session, instead of re-evaluating the whole SDK module graph on each `openSession`. For the agent-author view (how to opt in and the rules your SDK must follow), see [Software Definition → SDK snapshotting & snapshot-safety](/agentos/docs/custom-software/definition). For how sessions work in general, see [Agent Sessions](/agentos/docs/architecture/agent-sessions). - -## The problem: per-session SDK re-evaluation - -When a session starts, its agent adapter runs inside a fresh [V8 isolate](/agentos/docs/architecture/agent-sessions) and imports the agent SDK (for Pi, `@mariozechner/pi-coding-agent`). Importing a real-world SDK means resolving, loading, compiling, and **evaluating** a large module graph — hundreds of modules running their top-level initialization. That evaluation dominates session-creation latency, and because every session gets a fresh isolate, it is paid *again on every `openSession`*. - -The work is identical every time: the same modules, evaluated to the same post-init heap, only to be thrown away when the session ends. Snapshotting captures that post-init heap once and stamps it into every new isolate. - -## How V8 heap snapshots work here - -agentOS already boots every guest isolate from a **V8 startup snapshot** of the runtime bridge (the polyfill layer that provides `fetch`, node builtins, the kernel-backed module loader, etc.). A startup snapshot is a serialized image of a V8 heap *after* some code has run; restoring it into a fresh isolate reproduces that heap by deserialization rather than re-execution, and each restore produces an independent context. - -Agent SDK snapshotting extends that same mechanism: it evaluates the agent SDK **into the same snapshot context, right after the bridge**, so the captured image contains the bridge *and* the fully-initialized SDK. Restoring it gives a fresh isolate where the SDK is already present — no import, no evaluation. - -## Where it sits in the component model - -The [three components](/agentos/docs/architecture#the-big-picture) are unchanged. Snapshotting only changes *how* the executor's isolate is seeded: - -- **Client.** Builds the SDK bundle at package-build time and passes it to the sidecar as trusted VM configuration (`jsRuntime.snapshotUserlandCode`). It decides which agents opt in. -- **Sidecar.** Owns the snapshot. It builds the snapshot once, caches it process-wide, and seeds each session's isolate from it. The SDK runs inside the isolate under the same [permission policy](/agentos/docs/permissions) as any guest code — snapshotting grants the SDK no extra capability. -- **Executor.** The agent adapter restores into an isolate where the SDK is already on the global, reads it, and proceeds. It is untrusted guest code as always. - -## The pipeline - -### 1. Bundle the SDK to one snapshottable unit - -The agent SDK and its transitive dependencies are bundled (esbuild, IIFE) into a single file shipped with the agent package (`dist/sdk-snapshot.js`). The bundle evaluates the SDK and publishes its public API on a well-known global (e.g. `globalThis.__PI_SDK_RUNTIME__`). Node builtins stay external (resolved by the bridge's in-snapshot polyfills); heavy provider SDKs that are only reached via dynamic `import()` stay lazy and load post-restore from the VFS. - -### 2. Capture the evaluated SDK into the snapshot - -The sidecar runs the bridge, then the SDK bundle, in one snapshot-creation context, then serializes the heap. The result is a startup blob containing both. Per-session configuration (cwd, model, API keys) is **not** captured — it is injected after restore, so one blob serves every session. - -### 3. Cache it process-wide, keyed by content - -The blob is stored in a **sidecar-process-wide cache keyed by `sha256(bridge + bundle)`**. Any change to the bridge or the bundled dependency graph changes the key and triggers exactly one rebuild; an unchanged bundle is a cache hit. This is what makes it **build-once-per-sidecar**: the cache is shared across every VM and session in the process. - -### 4. Pre-warm so the first session is warm - -Building the snapshot is itself the expensive evaluation, just done once. To keep it off the session-create critical path, the sidecar **pre-warms** at VM creation: when a VM is configured with a snapshot bundle, the sidecar builds the blob into the cache *before* the first session is created. The first session then restores from a warm cache like every session after it. - - -**Pre-warm and V8 initialization order** -The V8 platform must be initialized on a long-lived thread *before* any pre-warm runs. agentOS initializes the embedded runtime on the sidecar's main thread at startup. Initializing V8 lazily on a transient worker thread that then exits corrupts the platform and wedges later isolate creation — so the startup init is load-bearing, not incidental. - - -### 5. Restore a fresh isolate per session - -On `openSession`, the agent's isolate is created from the cached blob. The SDK is already evaluated in the snapshot's default context, and each session gets a **fresh context cloned from it**. The adapter reads the SDK off the global instead of importing it. If no snapshot is configured — or snapshot creation fails — the adapter transparently falls back to the per-session dynamic-import path, so snapshotting never affects correctness, only latency. - -## Isolation - -Each session leases a **fresh context** cloned from the snapshot's default context. The captured SDK is shared read-only through the blob, but live state is not: a global, a captured-object mutation, or even a built-in prototype change made in one session is **not** observable in another. This is the same isolation guarantee as a non-snapshot session — a fresh isolate per session — and is covered by dedicated tests (a session that mutates `globalThis`, an SDK object, and `Array.prototype`, with a second session from the same snapshot seeing none of it). - -## Snapshot-safety: what an SDK must avoid - -A startup snapshot can only capture a pure JS heap. The SDK's **module-initialization** code (everything that runs at import time, before any function is called) must not, at top level: - -- Create a **native handle** — load a `.node` addon, instantiate WebAssembly, or produce any V8 *External* object (for example an ICU-backed `Intl.Segmenter` singleton). These cannot be serialized and abort snapshot creation. -- Open an **fd, socket, timer, or worker**, or leave a **pending promise** at the end of evaluation. -- Read **non-deterministic or per-session state** (`process.env`, cwd, model, `Date.now()`, `Math.random()`, a random UUID) into a module constant — it would be frozen to the build-time value. - -Real-world SDKs frequently break these by accident. agentOS makes such an SDK snapshottable with **build-time transforms in the bundle** that defer the offending work to first use (e.g. wrap a module-level native singleton in a lazy proxy, inline a top-level config-file read, convert eager fire-and-forget imports to synchronous module references). Each transform asserts the source shape it expects, so an upstream SDK change surfaces as a build error rather than a silent regression. The full author-facing rules live in the [Software Definition](/agentos/docs/custom-software/definition) reference. - -## Opt-in, per agent - -Snapshotting is **opt-in per agent**, via `agent.snapshot: true` on the [agent software descriptor](/agentos/docs/custom-software/definition), and requires the agent package to ship a snapshot-safe `dist/sdk-snapshot.js`. Today only the Pi agent opts in; other agents run the normal per-session import path. An agent qualifies by (1) being snapshot-safe and (2) building the bundle — there is nothing Pi-specific in the runtime mechanism. - - -**Current trade-off** -The bundle is currently delivered inline in the (trusted) VM config, which moves bytes onto VM creation. The intended refinement is to ship the bundle as a build-time blob the sidecar loads from the guest VFS by path, keeping the config small. Either way the snapshot is built once per sidecar and reused across sessions. - diff --git a/vendor/agentos/docs/content/docs/architecture/agent-sessions.mdx b/vendor/agentos/docs/content/docs/architecture/agent-sessions.mdx deleted file mode 100644 index 98f32056..00000000 --- a/vendor/agentos/docs/content/docs/architecture/agent-sessions.mdx +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: "Agent Sessions" -description: "Understand how agentOS creates durable coding-agent sessions, connects ACP adapters, processes prompts, applies permissions, and stores history." -skill: true ---- - -An AgentOS session is a durable SQLite record with an optional live ACP adapter. The stable public session ID and the adapter's private ACP session ID are deliberately separate. - -## Ownership - -- **Actor:** lifecycle and `keepAwake` for active turns; one actor owns one VM. -- **Core SDK:** thin TypeScript or Rust transport and native ACP data types. -- **Sidecar:** session policy, SQLite transactions, adapter lifecycle, restore selection, and event delivery. -- **ACP adapter:** agent-specific private context and native protocol behavior. - -```text -client -> actor/core -> sidecar -> ACP adapter - ↘ VM SQLite event log -``` - -The sidecar—not the actor or SDK—owns defaults and orchestration. TypeScript and Rust send omitted fields as omissions and expose the same methods. - -## Turn lifecycle - -1. `openSession` creates the SQLite record and negotiates an adapter, or reuses the compatible existing record. It resolves without returning metadata. -2. `prompt` restores an unloaded adapter if needed. -3. AgentOS atomically marks the session running, records the prompt, and appends complete user-message ACP updates. -4. The prompt is dispatched exactly once. Live message/thought deltas are ephemeral; committed completed updates receive durable sequence numbers. -5. The prompt result and terminal idle/failed state commit atomically. Only then does the actor release `keepAwake`. - -One prompt may run per session. Cancellation races are first-writer-wins. AgentOS does not automatically replay interrupted prompts because tool side effects may already have occurred. - -The ACP runtime and AgentOS client transports impose no wall-clock deadline on prompts or human permission waits. After 30 seconds without ACP activity, AgentOS logs an inactivity warning with the total elapsed time and last observed activity, repeating every 30 seconds until activity resumes. Streaming output resets that interval. Bootstrap, teardown, filesystem, terminal, and other machine-to-machine operations retain bounded failure deadlines. Actor-hosted calls currently inherit RivetKit's maximum timer-safe action bound of about 24.8 days because RivetKit does not yet support an unbounded action. - -## Reads versus adapter operations - -`getSession`, `listSessions`, `readHistory`, and cached negotiation getters read SQLite without starting an adapter. `prompt` and configuration setters may restore one. `unloadSession` preserves SQLite while stopping the adapter; `deleteSession` removes both runtime and durable state. - -## Native ACP data - -Prompt content, stop reasons, session updates, configuration options, agent information, capabilities, and permission requests use upstream ACP shapes. AgentOS adds persistence envelopes and load/save semantics; it does not invent a parallel event vocabulary. - -ACP has no portable durable history-read method. Native restore is also inconsistent across real adapters, so adapter storage cannot be AgentOS's public history source. SQLite remains authoritative even if an adapter emitted output that failed to commit. - -## Adapter exits - -An unexpected adapter exit evicts the live route and fails the active turn. AgentOS does not respawn the adapter or replay work implicitly. The next explicit prompt can restore the session through native resume/load or the bounded continuation fallback. - -## Next - -- [Sessions](/agentos/docs/sessions) for the public API. -- [Sessions & Persistence](/agentos/docs/architecture/sessions-persistence) for SQLite and restoration. -- [Approvals](/agentos/docs/approvals) for ACP permission options. diff --git a/vendor/agentos/docs/content/docs/architecture/filesystem.mdx b/vendor/agentos/docs/content/docs/architecture/filesystem.mdx index 36546fea..7e45c8a2 100644 --- a/vendor/agentos/docs/content/docs/architecture/filesystem.mdx +++ b/vendor/agentos/docs/content/docs/architecture/filesystem.mdx @@ -51,7 +51,7 @@ Resolution is **longest-prefix wins**: if `/mnt/data` is a mount and the guest o \- ... ``` -The base layer is in-memory and per-VM; the runtime transparently persists it to backing storage so it survives sleep/wake. Mounts are pluggable: any guest path can be backed by the host, a remote, or a cloud store. See [Mounting filesystems](/agentos/docs/filesystem#mounts) for the user-facing config. +The base layer is in-memory and per-VM, and is discarded when the VM is disposed. A root or mount backed by the VM's SQLite database survives VM recreation; see [Persistence](/agentos/docs/persistence). Mounts are pluggable: any guest path can be backed by the host, a remote, or a cloud store. See [Mounting filesystems](/agentos/docs/filesystem#mounts) for the user-facing config. ## Routing a guest syscall @@ -63,7 +63,9 @@ When the guest calls, say, `readFileSync("/mnt/data/report.csv")`: 4. **Backend operation.** The owning engine's backend services the read/write/stat/etc. against its store (in-memory pages, the persisted base, a host directory, S3, ...). 5. **Reply.** The result crosses back to the executor, which unblocks. -Host-side APIs (`agent.writeFile`, `agent.readFile`) enter the *same* VFS from the trusted side, which is why the host can seed and read files the guest sees, without ever exposing the real host disk to the guest. +Host-side APIs (`filesystem.writeFile`, `filesystem.readFile`) enter the *same* +VFS from the trusted side, which is why the caller can seed and read files the +guest sees without exposing the real host disk to the guest. ## Mount confinement diff --git a/vendor/agentos/docs/content/docs/architecture/javascript-executor.mdx b/vendor/agentos/docs/content/docs/architecture/javascript-executor.mdx index 42232d95..a5bb2b8a 100644 --- a/vendor/agentos/docs/content/docs/architecture/javascript-executor.mdx +++ b/vendor/agentos/docs/content/docs/architecture/javascript-executor.mdx @@ -242,9 +242,9 @@ one cross-boundary event per packet. ## Relationship to Node.js -AgentOS copies Node's evented-I/O invariants, not its process topology. +agentOS copies Node's evented-I/O invariants, not its process topology. -| Concern | Node.js | AgentOS | +| Concern | Node.js | agentOS | | --- | --- | --- | | I/O runtime | One libuv loop per Node process | One Tokio runtime shared by the sidecar process | | JavaScript execution | Event-loop thread enters V8 | Separate admitted V8 executor thread enters its isolate | diff --git a/vendor/agentos/docs/content/docs/architecture/limits-and-observability.mdx b/vendor/agentos/docs/content/docs/architecture/limits-and-observability.mdx index 911cf08a..774b87c2 100644 --- a/vendor/agentos/docs/content/docs/architecture/limits-and-observability.mdx +++ b/vendor/agentos/docs/content/docs/architecture/limits-and-observability.mdx @@ -43,7 +43,7 @@ follows the same contract: ## Backpressure, not catastrophe The path from guest code to the host is a **chain of bounded queues**: the V8 -runtime → a per-session frame channel → the V8→host event channel → the sidecar +runtime → a per-execution frame channel → the V8→host event channel → the sidecar stdout frame queue → the host. Streaming channels apply backpressure where the producer can safely wait. Process/runtime delivery queues that cannot block reject the crossing event with an error naming `limits.process.pendingEventCount` @@ -86,4 +86,6 @@ a parsed log line. ## See also - [Resource Limits](/agentos/docs/resource-limits) — the full `limits` config surface. -- [Processes](/agentos/docs/architecture/processes) and [Sessions & Persistence](/agentos/docs/architecture/sessions-persistence) — the layers the queue chain runs through. +- [Processes](/agentos/docs/architecture/processes) and + [Persistence](/agentos/docs/persistence) — the layers the queue chain runs + through. diff --git a/vendor/agentos/docs/content/docs/architecture/networking.mdx b/vendor/agentos/docs/content/docs/architecture/networking.mdx index ad4da661..cada2bd4 100644 --- a/vendor/agentos/docs/content/docs/architecture/networking.mdx +++ b/vendor/agentos/docs/content/docs/architecture/networking.mdx @@ -1,12 +1,12 @@ --- title: "Networking" -description: "Explore the agentOS kernel socket table, JavaScript and WASM traffic, DNS, egress policy, loopback isolation, and preview routing." +description: "Explore the agentOS kernel socket table, JavaScript and WASM traffic, DNS, egress policy, and loopback isolation." skill: true --- These internal architecture docs are mostly generated and maintained by LLMs, then reviewed by humans. They are intentionally verbose; use your preferred LLM to ask focused questions about the architecture as needed. -This is the internals view of agentOS networking: the kernel socket table, the layers a request crosses, and where policy is enforced. For the user-facing API (`httpRequest`, preview URLs, the confinement model from a caller's perspective), see [Networking & Previews](/agentos/docs/networking). For the trust boundary this all sits inside, see [Architecture](/agentos/docs/architecture). +This is the internals view of agentOS networking: the kernel socket table, the layers a request crosses, and where policy is enforced. For the user-facing API (`httpRequest`, `fetch`, the confinement model from a caller's perspective), see [Networking](/agentos/docs/networking). For the trust boundary this all sits inside, see [Architecture](/agentos/docs/architecture). The governing rule for TCP is that there is exactly **one authoritative transport for everything VM-local**: the kernel socket table. No untrusted guest code opens a host socket directly. Guest `fetch()`, `node:http`, TCP `node:net`, WASM TCP clients and servers, and host-into-guest requests (`httpRequest` / `rt.fetch`) all target the same listener table. The trusted sidecar implements `AF_UNIX` streams with a separate, per-VM private host transport while keeping pathname inodes and permissions authoritative in the guest VFS. @@ -25,7 +25,7 @@ Because every server is a kernel TCP listener, a client never needs to know whet `AF_UNIX` has three explicit limits. Datagram and sequenced-packet Unix sockets return `ENOTSUP`; only streams are implemented. The current string-based VFS cannot represent invalid-UTF-8 filename bytes, so the WASM boundary returns `EILSEQ` instead of corrupting them (valid UTF-8 control characters are supported). Unix sockets on read-only host-backed mounts fail with `EROFS`, and sockets on writable host-backed mounts fail closed with `ENOTSUP`: host `bind(2)` and `connect(2)` have no descriptor-relative form that can preserve the mount confinement boundary. Symlinks into either kind of mount are rejected before a host socket is created. -Blocking WASM `AF_UNIX` connect, accept, read/receive, and poll calls honor nonblocking mode and signals; accept and reads also honor `SO_RCVTIMEO`, returning Linux's `EAGAIN` when that socket timeout expires. Every blocking wait is additionally capped by `limits.resources.maxBlockingReadMs` (30 seconds by default); the runtime warns near the cap and returns `ETIMEDOUT` at the AgentOS safeguard. Raise that limit for workloads that intentionally wait longer. +Blocking WASM `AF_UNIX` connect, accept, read/receive, and poll calls honor nonblocking mode and signals; accept and reads also honor `SO_RCVTIMEO`, returning Linux's `EAGAIN` when that socket timeout expires. Every blocking wait is additionally capped by `limits.resources.maxBlockingReadMs` (30 seconds by default); the runtime warns near the cap and returns `ETIMEDOUT` at the agentOS safeguard. Raise that limit for workloads that intentionally wait longer. An earlier design carried two listener models at once: stream-mode listeners (`net.createServer`, WASM) on real kernel TCP sockets, and object-mode HTTP listeners (`http.createServer`) on a separate table that exchanged JSON request/response objects over stream events. A second guest process could not reach the object-mode table reliably, because the client expected byte-stream TCP semantics while the server only spoke object-mode dispatch. The current architecture removes the second model: everything is one socket table. @@ -118,20 +118,9 @@ Every guest connect, listen, read, and write passes through sidecar ownership an Host-to-guest requests bypass egress, not the table. `httpRequest` / `rt.fetch` terminate at the guest's loopback listener and never leave the VM, so they work even when guest egress (layer 3) or outbound `connect` (layer 1) is denied. They are host control-plane traffic, not guest egress, and only ever reach VM-owned listeners, while still going through the same kernel socket table as everything else. -## Preview URLs - -A preview URL is port forwarding for a VM service: a time-limited, signed, publicly reachable URL that proxies HTTP to a port inside the VM. Mechanically it reuses the host-to-guest path: - -- A signed token is minted for a `(VM, port)` pair with an expiration, capped by `preview.maxExpiresInSeconds`. Tokens are stored in SQLite, survive sleep/wake cycles, and expired ones are cleaned up automatically. Active tokens are bounded by `preview.maxActiveTokens` (1,024 by default); creation fails with a limit error that names the option when the bound is reached. -- An incoming request to the preview path is authenticated against the token, then proxied into the VM exactly like `httpRequest`: resolve the port to a VM-owned kernel listener, connect over loopback, frame HTTP/1.1, drive the target process, and return the bounded buffered response. The same fail-closed, VM-owned-listener-only rules apply. -- CORS is enabled so browsers can reach preview URLs from any origin. -- Revocation (`agent.expirePreviewUrl`) invalidates the token immediately, after which the proxy refuses the request before touching the socket table. - -Because previews ride the host fetch path, they are subject to loopback confinement at the kernel but **not** to the guest egress allowlist: the request enters the listener from the host side and never becomes guest outbound traffic. - ## Where to go next -- [Networking & Previews](/agentos/docs/networking): the `httpRequest` and preview URL API, with usage examples. +- [Networking](/agentos/docs/networking): the `httpRequest` and `fetch` API, with usage examples. - [JavaScript Executor & Socket Reactor](/agentos/docs/architecture/javascript-executor): how Tokio readiness wakes V8, how the channel lanes are separated, and how Node stream backpressure reaches the transport. - [Architecture](/agentos/docs/architecture): the client / sidecar / executor trust boundary this stack lives inside. - [Security Model](/agentos/docs/security-model): the full in-scope and out-of-scope threat model. diff --git a/vendor/agentos/docs/content/docs/architecture/packages-and-command-resolution.mdx b/vendor/agentos/docs/content/docs/architecture/packages-and-command-resolution.mdx index b8333818..f390936d 100644 --- a/vendor/agentos/docs/content/docs/architecture/packages-and-command-resolution.mdx +++ b/vendor/agentos/docs/content/docs/architecture/packages-and-command-resolution.mdx @@ -1,257 +1,79 @@ --- title: "Packages & Command Resolution" seoTitle: "agentOS Package and Command Resolution" -description: "Understand how agentOS packages software, projects commands into VM paths, resolves executables, and selects the runtime for each file." +description: "How immutable .aospkg files become commands inside an agentOS VM." skill: true --- -These internal architecture docs are mostly generated and maintained by LLMs, then reviewed by humans. They are intentionally verbose; use your preferred LLM to ask focused questions about the architecture as needed. +agentOS software is distributed as immutable version 2 `.aospkg` files. npm is +not a runtime registry and the sidecar never scans `node_modules` to discover +software. -How a command name becomes a running program, and how the software that provides it -is packaged and linked. Everything is real files under -[`/opt/agentos`](/agentos/docs/architecture/filesystem) — there is no command registry; the -filesystem and `$PATH` are the only source of truth. For the host API that produces -packages, see [Software Definition](/agentos/docs/custom-software/definition). +## Package container -## Overview +Each artifact contains four sections: - - - - - - - - exec "pi" - - - $PATH walk over the VFS - - - /opt/agentos/bin/pi - a real symlink in the VFS - - - read header (binfmt) - - - - - - #!…node - JavaScript · V8 - - #!…python3 - Python · Pyodide - - {'\\0asm'} - WebAssembly - - ELF / Mach-O / PE - ENOEXEC - - - - - spawn under the VM permission policy - +1. the fixed package header; +2. one vbare runtime manifest; +3. one vbare mount index; +4. the mount tar payload. -- **Resolve** — a real `$PATH` walk over the VFS; the first executable match wins. -- **Dispatch** — by the file's *header* (`binfmt`): a `#!` shebang or a magic number. Never the name, never the extension. -- **Run** — on one of three runtimes: JavaScript (V8), WebAssembly, Python (Pyodide). See [Processes](/agentos/docs/architecture/processes). -- **Confine** — every process runs under the VM's single [permission policy](/agentos/docs/security-model). No per-command tiers. +`agentos-package.json` is toolchain input. The packer converts its runtime +fields into the vbare manifest and does not ship or materialize the JSON file +inside the VM. -## Packages +Release tooling computes a SHA-256 digest for every artifact and uploads it at +a digest-addressed object path. A release manifest maps the logical package +name to its immutable relative URL, digest, and byte size. -A package is a directory; its metadata is a normal `package.json` (`name`, `version`, -and a `bin` command map) plus a small `agentos-package.json` (the agentOS-specific -`name`/`agent`/`provides`). The shipped package contains **real files** — it's a plain npm -dependency. The `/opt/agentos///` tree below, with its `bin/` symlink farm, -is what the runtime **projects** from that package when it mounts it: +## Projection -``` -/opt/agentos/// -├── package.json # name, version, and the "bin" map (command → entry file) -├── agentos-package.json # agentOS metadata: name, optional agent block, provides -├── bin/ # symlinks the PROJECTION builds from package.json "bin" -│ ├── ls → ../libexec/coreutils # → multicall blob -│ └── vdir → ../libexec/coreutils # an "alias" is just another symlink -├── libexec/coreutils # helpers run by other programs, never on $PATH -├── node_modules/ | lib/ # support payload (a JS CLI's flat, self-contained closure) -└── share/man/man1/ls.1 # man pages and other FHS content -/opt/agentos//current → # version pointer; upgrade re-points it (atomic rename) -``` - -| Path | Contents | -|---|---| -| `package.json` | `name`, `version`, and a `bin` map (command → entry file). | -| `agentos-package.json` | agentOS metadata the sidecar reads on mount: `name`, an optional `agent` block, and any `provides` (files/env). Generated for command/WASM packages; carries the `agent` block for agents. | -| `bin/` | Command symlinks the projection builds from `package.json` `bin`; each basename is the command name. (Not part of the shipped package — npm can't carry symlinks.) | -| `libexec/` | Helpers invoked by other programs, never on `$PATH` (e.g. a multicall blob). | -| `node_modules/`, `lib/` | Non-executable payload — bundled deps and assets. | -| `share/` | FHS data — `share/man/man/*`, etc. | -| `current` | Symlink `→ `; switching versions is one atomic rename. | +The VFS memory-maps the package and projects it without unpacking a mutable +host directory: -```json -// package.json — commands come from "bin"; an agent's ACP entrypoint is just one of them -{ "name": "@agentos-software/pi", "version": "0.0.1", "bin": { "pi-acp": "dist/pi-acp.wasm" } } +```text +/opt/agentos/ +├── pkgs/// # package payload +└── bin/ # links to commands exported by manifests ``` -A directory is a **valid package** when: - -- **Commands come from `package.json` `bin`** (command → a real entry file), and each entry - **dispatches by header** — a magic number or `#!` shebang, no `.wasm`/`.js` extension or - `runtime`/`type` field; a headerless entry is `ENOEXEC`. The package ships **no symlinks** - (npm-safe); the runtime builds the `bin/` farm under `/opt/agentos` itself. -- **Aliases are symlinks** in the projected `bin/` farm — several names for one program (or a - multicall blob); `argv[0]` is the invoked name. -- **It is self-contained** — every import/require/asset resolves inside the package; nothing - comes from a host `node_modules`, pnpm store, or workspace at runtime - ([packaging](/agentos/docs/custom-software/definition) flattens/bundles deps in). -- **Minimal metadata** — `package.json` carries only the command set (`bin`) and `version`; there - is no command list beyond `bin`, no permission tiers (the [VM policy](#confinement--trust) - governs every command), and no dependency list. A small **`agentos-package.json`** alongside it - holds the agentOS-specific fields the sidecar reads when it mounts the package — the `name`, an - optional `agent` block, and any `provides` (files/env). The client never carries this on the - wire; it forwards only the package directory. - -## Linking - -Linking is creating the `bin/` symlinks in a `$PATH` directory. agentOS follows Homebrew: -`/opt/agentos/` is the cellar, and every command is symlinked into one managed prefix, -**`/opt/agentos/bin`**, which is on `$PATH`. The standard dirs (`/usr/bin`, `/usr/local/bin`, -`/bin`) stay ordinary writable Linux dirs — agentOS never writes to them. - - - - - - - - Searched left → right — first match wins (left shadows right) - - - /usr/local/sbin - - /usr/local/bin - - /opt/agentos/bin - - /usr/sbin - - /usr/bin - - /sbin - - /bin - agentOS links into /opt/agentos/bin; the rest are ordinary writable Linux dirs — drop a binary in /usr/local/bin to shadow an agentOS tool. - - -| Software | Stored | Linked into | -|---|---|---| -| Base, mounted, and runtime-installed agentOS software | `/opt/agentos//` (or the mount) | `/opt/agentos/bin` | -| The user's own files | wherever they put them | `/usr/local/bin`, `/usr/bin`, … (normal) | - -- **Base & mounts** link into `/opt/agentos/bin` in a **read-only layer** projected from the - host and shared across VMs — the symlinks are real but cost nothing per boot. A mounted host - directory is linked the same way, with no copy. -- **Runtime installs** add symlinks to `/opt/agentos/bin` in the **writable layer** via - [`agentos-software link`](#the-agentos-software-cli) — ordinary symlinks, found by the normal walk. - -## Persistence - -Links and installed files are **filesystem entries**, so they persist exactly when their -[filesystem](/agentos/docs/architecture/filesystem) layer does — the same rule as VFS-persistent -`pip`. A snapshotted/persistent volume keeps runtime installs and links across restart; an -ephemeral one drops them on teardown. There is no package-specific persistence mechanism. - - -Persisting a layer an untrusted guest can write to also persists whatever the guest linked -there. Treat a guest-writable `/usr/local/bin` as guest-controlled on restore (see -[Confinement & trust](#confinement--trust)). - +`/opt/agentos` is the live source of truth. Listing installed software and +resolving commands read the projection rather than a package list captured +during VM creation. -## Execution dispatch (binfmt) +Changing a filesystem mount does not uninstall software linked after VM +creation. The sidecar retains those package identities and projections until +an explicit unlink; clients do not need to mirror the live package list when +they reconfigure mounts. -A resolved file's leading bytes are read into a fixed buffer and dispatched like the Linux -kernel's binary-format handlers. The command's **name plays no part** — `python3`, `node`, -and `pi` are runtimes only by virtue of their files' headers. +## Source policy -| Header | Result | -|---|---| -| `#!` at bytes 0–1 (`binfmt_script`) | the interpreter named on the line | -| `\0asm` (`00 61 73 6d`) | WebAssembly runtime | -| `\x7fELF` / Mach-O / PE | **`ENOEXEC`** — foreign binary format, no native-arch handler | -| anything else | `ENOEXEC` (no implicit `/bin/sh` fallback here) | +The shared Core package-source model is closed: -Shebang handling matches `binfmt_script`: - -- The interpreter path is **literal and absolute** — not `$PATH`-searched. `#!/usr/bin/env node` - works only because `/usr/bin/env` looks up its argument. -- At most **one** argument follows, **not** whitespace-split (`#!/usr/bin/env node --flag` passes - `node --flag` as a single arg). -- The header read is bounded to a fixed buffer (`BINPRM_BUF_SIZE`); a longer line truncates. - Interpreter chaining is depth-bounded (`ELOOP`); a missing interpreter is **`ENOENT`**, not `ENOEXEC`. - - -**Shell fallback.** On `ENOEXEC`, a POSIX shell re-runs a headerless script via `/bin/sh`. That -retry lives in the shell ([agentos-shell](/agentos/docs/architecture/processes)), not the dispatcher, -which stays strictly `binfmt`-faithful. - - -### Multicall (busybox-style) - -`bin/ls → ../libexec/coreutils` resolves at open to the shared `coreutils` blob. `argv[0]` is -the caller's value **verbatim** (`"ls"`) — never derived from the symlink — and the blob selects -its applet with `basename(argv[0])`, like busybox. Always invoke via the `bin/` name; calling the -blob by its own path yields an `argv[0]` that selects no applet. - -## Command resolution - -A `$PATH` walk over the [VFS](/agentos/docs/architecture/filesystem), full Linux semantics: - -- A name **containing `/`** bypasses `$PATH` and resolves directly (relative to cwd, or absolute). -- Otherwise each `:`-separated dir is searched in order; the first **executable** regular file - wins (execute bit required — a non-executable match yields `EACCES`). Left shadows right. -- An **empty `$PATH` element** (leading/trailing/`::`) means the **current working directory** — - the POSIX footgun, kept for fidelity. -- Matches are real VFS files/symlinks — `ls -l`-able, `stat`-able, removable, replaceable. The - filesystem is authoritative; there is no resolution cache to grow stale. - -## The `agentos-software` CLI - -``` -agentos-software link -``` +- `Url { url, expected_digest? }` downloads a remote artifact under strict + size, time, and redirect limits; +- `Path { path, expected_digest? }` reads a trusted local artifact from the + host. -- `` is a package directory or a node module directory (its `package.json` `bin` map is - the command list). -- It brokers a request to the sidecar, which owns the filesystem; the CLI has no privilege of - its own. -- Linked names are validated (no `/`, `..`, control chars, overlong names), and for a - guest-supplied package each symlink target must resolve inside the package root. +There is no custom resolver callback. A host that installs packages on behalf +of untrusted users should accept only `Url` sources from them. -## Confinement & trust +Both variants verify the bytes before publishing them into the same +process-local content-addressed cache. Cache identity is the content digest, +not the URL. Installed packages are pinned while a VM uses them and +otherwise participate in bounded LRU eviction. -Every process runs under the VM's single [permission policy](/agentos/docs/security-model) — like a -Linux process running with its user/namespace/container privileges, not privileges declared by -the binary. A package cannot grant itself permissions. The [trust boundary](/agentos/docs/security-model) -is the sidecar (trusted) vs. the guest (untrusted): +## Command execution -- **Linking changes discoverability, not privilege** — the policy is enforced at spawn, - regardless of how a command was found. -- **Shadowing is allowed, Linux-style** — a guest may drop a `node`/`ls` into a writable `$PATH` - dir; trusted in-VM components defend by invoking tools via **absolute paths** (or a `$PATH` - that excludes guest-writable dirs). The shadowing binary still runs only under the VM policy. -- **Guest env is sanitized** like a privileged exec — `LD_*`, `DYLD_*`, `NODE_OPTIONS`, `PATH`, - `BASH_ENV`, `*PRELOAD` are stripped, as glibc does under `AT_SECURE`. -- **Trusted vs. guest packages** — symlink-escape checks apply only to guest-writable runtime packages. -- **Bounded** — the runtime link count is bounded; it warns on approach and fails with a typed - error naming the limit (see [Limits & Observability](/agentos/docs/architecture/limits-and-observability)). +The shell resolves a command with the normal `$PATH` walk. The kernel then +dispatches the resolved file by its bytes: a shebang selects an interpreter and +the WebAssembly magic header selects the WASM executor. Names and filename +extensions do not select a runtime. -## See also +If multiple packages export the same command, configuration validation rejects +the collision unless the package projection policy explicitly resolves it. +Removing a package removes only its managed projection and command links. -- [Software Definition](/agentos/docs/custom-software/definition) — the host API that produces these packages. -- [Processes](/agentos/docs/architecture/processes) — the JavaScript, WebAssembly, and Python runtimes. -- [Filesystem](/agentos/docs/architecture/filesystem) — the VFS, layers, and persistence. -- [Security Model](/agentos/docs/security-model) — the trust boundary and VM permission policy. +See [Software](/agentos/docs/software) for the public installation API and +[Software Package Definition](/agentos/docs/custom-software/definition) for +building artifacts. diff --git a/vendor/agentos/docs/content/docs/architecture/processes.mdx b/vendor/agentos/docs/content/docs/architecture/processes.mdx index c443e1be..996ccdaf 100644 --- a/vendor/agentos/docs/content/docs/architecture/processes.mdx +++ b/vendor/agentos/docs/content/docs/architecture/processes.mdx @@ -7,9 +7,9 @@ skill: true These internal architecture docs are mostly generated and maintained by LLMs, then reviewed by humans. They are intentionally verbose; use your preferred LLM to ask focused questions about the architecture as needed. This page is an internals deep-dive on the kernel's **process model**: the data -structures and syscall paths behind every guest process. For the client-facing +structures and syscall paths behind every guest process. For the host-facing API (`process.exec`, `process.spawn`, `terminal.open`, lifecycle, the process tree), see -[Processes & Shell](/agentos/docs/processes). For the surrounding component and trust +[Processes & Shells](/agentos/docs/processes). For the surrounding component and trust model, see [Architecture](/agentos/docs/architecture). Two invariants frame everything below: @@ -23,31 +23,30 @@ Each VM owns one process table. It is the authority for what is "running" inside that VM; nothing in it corresponds to a host PID. - **Per-VM and isolated.** Two VMs have two independent tables. A PID in one VM is meaningless in another, and processes are never visible across the VM boundary. -- **Holds every guest process,** not only the ones a client started explicitly. A `spawn` from the client, a child spawned by guest `node:child_process`, and the processes behind a shell pipeline are all table entries. This is why the system-wide views (`allProcesses`, `processTree`) can show more than what the client launched. +- **Holds every guest process,** not only the ones a client started explicitly. A `process.spawn` from the client, a child spawned by guest `node:child_process`, and the processes behind a shell pipeline are all table entries. This is why `process.tree` can show more than what the client launched. - **Tracks lifecycle and lineage.** Each entry carries its PID, the command and arguments, parent PID (so the tree can be reconstructed), running/exited status, exit code once collected, and its attached stdio endpoints. -- **Records a driver.** An entry knows which execution backend services it (for example a V8 isolate versus a WASM runtime). This is the `driver` field surfaced on `allProcesses`. Drivers differ in *how* the code runs; they share the same table, the same kernel-owned stdio, and the same boundary. +- **Records a driver.** An entry knows which execution backend services it (for example a V8 isolate versus a WASM runtime). This is the `driver` field surfaced by `process.tree`. Drivers differ in *how* the code runs; they share the same table, the same kernel-owned stdio, and the same boundary. The process table is part of the kernel the sidecar owns. The executor never mutates it directly; it can only ask the kernel to create, wait on, or signal an entry. That request-only relationship is the sidecar-to-executor boundary applied to processes. ## How a spawn is serviced -A spawn, whether it originates from a client `spawn`/`exec` call or from guest +A spawn, whether it originates from a host `spawn`/`exec` call or from guest `node:child_process`, follows one path through the kernel: -1. **The request crosses into the kernel.** A client call arrives over the wire protocol; a guest call arrives as a syscall from the executor. Either way the kernel, not the caller, performs the work. -2. **Permission check.** The kernel applies the VM's permission policy before doing anything. Process execution is denied by default and must be granted; the policy is trusted input, the guest making the request is not. +1. **The request crosses into the kernel.** A host call arrives over the sidecar protocol; a guest call arrives as a syscall from the executor. Either way the kernel, not the caller, performs the work. +2. **Permission check.** The kernel applies the VM's configured permission policy before doing anything. The policy is trusted input; the guest making the request is not. 3. **Resolve the program.** The command is resolved against the VM's virtual filesystem (PATH lookup over the VFS), not the host. The resolved program decides the driver: a JavaScript entrypoint runs in a V8 isolate; a `.wasm` program (including `sh` and coreutils) runs on the WASM runtime. 4. **Allocate the table entry.** The kernel assigns a virtual PID, records the command, arguments, environment, working directory, and parent PID, and links stdio endpoints (see below). -5. **Start execution.** The driver begins running the program. For a one-shot `exec` the kernel additionally collects stdout, stderr, and the exit code and returns them as the call's result; for `spawn` it leaves the process running and streams output via events. -6. **Reap and record exit.** When the program finishes, the kernel records the exit code on the table entry and marks it exited, which is what a `wait`/`waitProcess` resolves against and what `processExit` reports. +5. **Start execution.** The driver begins running the program. For a one-shot `exec`, output and exit status are collected for the call's result; for `spawn`, the process remains available for explicit waiting and output replay. +6. **Reap and record exit.** When the program finishes, the kernel records the exit code on the table entry and marks it exited, which is what `process.wait` resolves against and what `onProcessExit` reports. -Signals (`stopProcess` / SIGTERM, `killProcess` / SIGKILL) are the same shape: a -request into the kernel, which applies it to the virtualized process rather than -to any host process. +Signals (`process.signal`) are the same shape: a request into the kernel, which +applies it to the virtualized process rather than to any host process. ## Process image replacement -Guest `execve` is distinct from the client-facing one-shot `exec` API. It +Guest `execve` is distinct from the host's one-shot `process.exec` API. It replaces the current process image in place, following Linux process semantics: - the virtual PID, parent, process group, session, working directory, pending signals, blocked-signal mask, stdio, and non-`FD_CLOEXEC` descriptors survive; @@ -68,8 +67,8 @@ Standard streams are kernel-owned objects, not host file descriptors. Each process entry has stdin, stdout, and stderr endpoints that the kernel wires up when the entry is created. -- **Capture vs. stream.** For `exec`, the kernel buffers stdout and stderr and hands them back when the process exits. For `spawn`, output is delivered incrementally as `processOutput` events tagged with the PID and the stream (`stdout`/`stderr`), and `processExit` signals completion. -- **Writable stdin.** `writeProcessStdin` pushes bytes into the process's stdin endpoint; `closeProcessStdin` closes the write side so programs that read to EOF (like `cat`) can finish. None of this touches a real pipe on the host. +- **Capture vs. stream.** `process.exec` returns bounded stdout and stderr after the process exits. For `process.spawn`, `onProcessOutput` delivers live output and, when output retention is enabled, `process.readOutput` pages through bounded replay; `onProcessExit` signals completion. Replay uses a sidecar-owned retention and cursor implementation, so `maxEvents`, `maxBytes`, truncation, and progress behavior are identical across Rust Core and TypeScript Core. Events are low-latency hints; replay is the authoritative recovery path. +- **Writable stdin.** `process.writeStdin` pushes bytes into the process's stdin endpoint; `process.closeStdin` closes the write side so programs that read to EOF (like `cat`) can finish. None of this touches a real pipe on the host. - **Pipes between processes.** Shell pipelines (`a | b`) connect one process's stdout endpoint to the next process's stdin endpoint through kernel-owned pipes. The pipe is a virtual object in the kernel, so a pipeline behaves like Linux without any host IPC. Because these endpoints are kernel objects, the same bridging works identically @@ -83,7 +82,7 @@ control signals, and window size all depend on a PTY. The kernel provides virtual PTY devices for this. - **A shell is a process plus a PTY.** `terminal.open` allocates a kernel PTY and starts a shell process attached to it, returning a `shellId`. The PTY is a virtualized terminal device, never a host `/dev/pts` entry. -- **Bidirectional terminal I/O.** `terminal.write` feeds keystrokes into the PTY master side; everything the shell and its children emit comes back as `shellData` events. This carries terminal control sequences, so full-screen TUIs behave correctly. +- **Bidirectional terminal I/O.** `terminal.write` feeds keystrokes into the PTY master side; output arrives through `onShellData`. This carries terminal control sequences, so full-screen TUIs behave correctly. - **Resize is a terminal operation.** `terminal.resize` updates the PTY's window size (columns and rows), which the kernel propagates to the foreground process the way a real terminal resize would, so programs relying on `TIOCGWINSZ`-style sizing redraw correctly. - **Teardown.** `terminal.close` tears down the PTY and the attached shell process. An open shell keeps the VM active, the same way an open PTY keeps a session alive on a real system. diff --git a/vendor/agentos/docs/content/docs/architecture/sessions-persistence.mdx b/vendor/agentos/docs/content/docs/architecture/sessions-persistence.mdx deleted file mode 100644 index 6b124c6f..00000000 --- a/vendor/agentos/docs/content/docs/architecture/sessions-persistence.mdx +++ /dev/null @@ -1,85 +0,0 @@ ---- -title: "Sessions & Persistence" -description: "Learn how agentOS stores exact Agent Client Protocol history in VM SQLite and restores adapters, sessions, and transcripts after wake." ---- - -SQLite is the AgentOS source of truth for public session metadata, prompts, pending requests, and durable ACP events. Adapter-owned session files or databases remain private adapter state; AgentOS does not mirror them into the VFS or import adapter replay into public history. - -## One SQLite descriptor per VM - -VM creation supplies exactly one trusted database descriptor: - -- `actor_uds` talks directly to Rivet actor SQLite through its authenticated Unix socket. -- `sqlite_file` opens one local SQLite file for the logical VM on the sidecar's bounded blocking executor. - -The sidecar resolves the descriptor once and injects the same database handle into VFS metadata, VFS block storage, and the AgentOS core session store. Filesystem plugins receive only filesystem policy, not another SQLite path or UDS credential. One Rivet actor is one logical VM, so tables do not repeat a VM ID. - -Each actor-UDS transaction generates a fresh UUID transaction key and attaches it to `BEGIN`, every statement, and `COMMIT` or `ROLLBACK`. Rivet owns transaction affinity and isolation. AgentOS adds no second UDS mux, pool, writer scheduler, or retry layer. - -## Independent schema owners - -Three owners share the physical per-VM database without sharing a migration sequence: - -| Owner | Version table | Data tables | -|---|---|---| -| Native filesystem | `agentos_fs_schema_version` | `agentos_fs_*` | -| Sidecar/core durable state | `agentos_core_schema_version` | `agentos_core_*` | -| TypeScript actor hosting metadata | `agentos_actor_schema_version` | `agentos_actor_*` | - -Each version table is a `STRICT` singleton table. Its owner alone validates and advances its append-only migration ladder, updating the schema and version in the same transaction. A future version fails closed. There is no shared schema-version table, global AgentOS migration sequence, or AgentOS use of `PRAGMA user_version`; Rivet-owned schema metadata remains independent. Owners do not create cross-owner foreign keys. - -## Session event log - -`agentos_core_events` keeps the durable envelope in scalar columns: public session ID, sequence, timestamp, negotiated ACP version, internal storage kind, correlation ID, payload byte length, and permission outcome fields. `payload_json` contains only the exact native ACP payload: - -- `session_update` stores an ACP `SessionUpdate`, including its `sessionUpdate` discriminator, optional fields, and `_meta`. -- `permission_request` stores the ACP `RequestPermissionRequest` selected for public delivery. -- `permission_response` stores the ACP `RequestPermissionResponse`. - -The internal `session_update` storage kind is not a public event discriminator. On read, AgentOS exposes `SessionUpdate.sessionUpdate` as the event's top-level `type` and places that ACP variant's native fields directly beside it. Permission request and response fields are flattened the same way. The public AgentOS durability envelope is reconstructed from the scalar columns; it is not duplicated inside `payload_json`, and the row is not a raw JSON-RPC frame. This keeps event data ACP-native while giving AgentOS a stable sequence, timestamp, and public request correlation. - -Complete user content is committed before prompt dispatch. Agent message and thought deltas are live and ephemeral; they receive no durable sequence and are coalesced into native ACP chunk updates only at a completed-message boundary. Other ACP updates are stored unchanged. Events are published only after their SQLite transaction commits. If an adapter emitted an event that never committed, SQLite wins, and AgentOS never automatically resends a prompt whose delivery is uncertain. - -## Trusted plaintext storage - -The per-VM SQLite database is trusted runtime storage. Session environment values, MCP headers or credentials, prompts, message content, tool arguments and results, permission payloads, and cached adapter metadata may be stored as plaintext JSON or SQLite values so a session can restore after sleep. AgentOS does not currently encrypt, redact, or replace these values with secret references. Operators must protect database and backup access according to the sensitivity of the workload. - -## Retention and default bounds - -Defaults are generous, VM-configurable `limits.acp` safeguards. AgentOS warns at 80% and returns a typed error naming the setting to raise when a hard-admission limit is reached. - -| Durable collection | Default | Contract | -|---|---:|---| -| Sessions | 10,000 per VM | Hard admission limit; sessions are never evicted implicitly. | -| History | 1,000,000 events and 1 GiB per session | Oldest committed events are pruned in bounded batches; an older reconnect cursor returns `history_cursor_expired`. | -| Prompt/idempotency records | 100,000 per session; 1,000,000 per VM | Oldest unreferenced terminal records are pruned to admit new prompts. An idempotency key is authoritative only while its prompt record is retained. | -| Pending `ask` permissions | 1,000 per session; 10,000 per VM | Hard admission limit with no time-based expiry; lifecycle resolution is required. | -| Terminal permission outcomes | 10,000 per session; 100,000 per VM | Oldest outcomes are pruned. A late response gets its specific terminal reason while retained and `request_not_found` after pruning. | - -History counters and payload-byte totals are updated transactionally with insertion and pruning. Bootstrap reconciliation repairs counter drift from event rows. A single batch larger than the configured history event or byte bound fails atomically rather than partially committing. - -Related request bounds default to 64 MiB and 16,384 blocks per prompt, 4 MiB of fallback continuation context, and 10,000 rows per session-list or history page. - -## Adapter restoration - -Public session IDs do not depend on adapter IDs. When no live route exists, the sidecar starts the configured adapter and tries native ACP restoration in this order: - -1. `session/resume` when advertised by `sessionCapabilities.resume`. -2. Stable `session/load` when `loadSession` is advertised. -3. `session/new` plus bounded continuation context derived from recent SQLite history. - -Notifications replayed by `resume` or `load` are discarded. This avoids duplicate public history and accommodates adapters whose restoration behavior differs despite ACP negotiation. - -## Actor lifecycle - -Merely having durable sessions does not keep the actor awake. The prompt action uses actor `keepAwake` from dispatch through the terminal SQLite commit so the VM cannot sleep halfway through a turn. Read-only session operations never start an adapter and do not hold the actor awake. - -## Core tables - -- `agentos_core_sessions`: scalar session state and creation options, complex creation-option JSON, cached negotiation, retained-history counters, sequence bounds, and timestamps. -- `agentos_core_events`: ordered exact ACP payloads with a scalar AgentOS envelope. -- `agentos_core_prompts`: prompt idempotency hashes and terminal result or error; accepted input is represented by durable native ACP user updates rather than duplicate prompt JSON. -- `agentos_core_permission_records`: actionable and terminal permission correlation. -- `agentos_core_permission_outcomes`: bounded terminal outcomes used to answer late responses. - -The filesystem's `agentos_fs_*` and actor's `agentos_actor_*` tables share the database handle but remain independently owned. diff --git a/vendor/agentos/docs/content/docs/architecture/software-cache.mdx b/vendor/agentos/docs/content/docs/architecture/software-cache.mdx new file mode 100644 index 00000000..67f8caaf --- /dev/null +++ b/vendor/agentos/docs/content/docs/architecture/software-cache.mdx @@ -0,0 +1,63 @@ +--- +title: "Software Installation and Preloading" +description: "Understand URL package installation, process caching, readiness, and preload coordination for hosted agentOS VMs." +--- + +Each VM projects installed packages as read-only filesystem leaves. The +projection is bounded by `config.limits.agentosPackages.maxMounts` (4,096 by +default), including command aliases and `provides.files` directory mounts. +Installing another package can fail with a resource-limit error even when the +download succeeded; the existing VM projection remains in place. + +Hosted VMs install immutable `.aospkg` files from HTTPS URLs. Embedded Core +also accepts a trusted local file path. A hosted VM never receives or +materializes a host path. + +## Resolution and projection + +The resolver validates the URL, blocks ambient credentials and private network +destinations, bounds redirects and response headers, downloads into a temporary +file, verifies the optional SHA-256 digest, and validates the package format. +The verified content digest becomes the package identity. + +The sidecar projects installed packages under +`/opt/agentos/pkgs//` and command links under +`/opt/agentos/bin`. `v1.software.list` reads the current installed set. +`v1.software.install` and `v1.software.uninstall` are durable config mutations, +so they use the same revision checks and reconciliation as `v1.config.patch`. + +## Process cache + +All VMs in one worker process share the child sidecar's content-addressed +cache. Concurrent requests for the same digest are coalesced into one +acquisition. The cache is bounded by bytes, entries, active downloads, pending +downloads, and acquisition time. Live VM generations pin their package files. +Unpinned entries are evicted in least-recently-used order. + +By default, each worker gets an isolated process-lifetime temporary cache. For +persistent recovery, set a distinct `AGENTOS_PACKAGE_CACHE_DIR` for each +concurrently running worker. An OS lock prevents startup recovery or eviction +from removing another worker's live package files. Restarting a worker with the +same directory recovers verified packages. + +The services worker removes its temporary cache after normal shutdown or +startup failure. Forced termination or a host crash can leave temporary +directories behind; configure host temporary-directory cleanup for those +leftovers. Persistent directories are never removed at worker shutdown. + +Partial downloads and failed publications use temporary files that are removed +when their operation is cancelled or fails. Package source URLs are kept only +as a short-lived bounded hint. Bytes are still verified before projection. + +## Startup preloading + +The `agentOS-preload-coordinator` is a central Rivet Actor that stores a +low-frequency popularity hint. It is not an authoritative registry or cache. +Each worker process reads one bounded plan at startup, coalesces that read for +the process, and warms likely package digests with bounded concurrency. The +default process warm deadline is 10 seconds. + +Required packages still determine VM readiness. An advisory preload timeout or +coordinator failure only reduces the cache hit rate. + +See [Software](/agentos/docs/software#install-while-running) for the installation API. diff --git a/vendor/agentos/docs/content/docs/architecture/tls-ssl.mdx b/vendor/agentos/docs/content/docs/architecture/tls-ssl.mdx index c374b4c7..c5628eed 100644 --- a/vendor/agentos/docs/content/docs/architecture/tls-ssl.mdx +++ b/vendor/agentos/docs/content/docs/architecture/tls-ssl.mdx @@ -25,9 +25,9 @@ We use **mbedTLS 3.6 LTS** as the in-guest TLS backend. It fits because it is ** Two artifacts make the whole class of tools work: 1. **`libmbedtls` / `libmbedx509` / `libmbedcrypto`** built for `wasm32-wasip1` in the toolchain Makefile. -2. **A CA bundle inside the VM** at the common Linux path `/etc/ssl/certs/ca-certificates.crt`, with `/etc/ssl/cert.pem` pointing to it. Verification then runs in each tool's own code path against a trust store shipped in the VM — hermetic, with correct Linux exit codes and tool-specific trust overrides (`--cacert` / `CURL_CA_BUNDLE` for curl and `--ca-certificate` for wget). AgentOS generates the bundle at build time from an exact-pinned `webpki-root-certs` Mozilla snapshot and installs it directly in native and browser guest roots before the first execution, including read-only and restored roots. Explicit root-filesystem entries at either trust path take precedence. +2. **A CA bundle inside the VM** at the common Linux path `/etc/ssl/certs/ca-certificates.crt`, with `/etc/ssl/cert.pem` pointing to it. Verification then runs in each tool's own code path against a trust store shipped in the VM — hermetic, with correct Linux exit codes and tool-specific trust overrides (`--cacert` / `CURL_CA_BUNDLE` for curl and `--ca-certificate` for wget). agentOS generates the bundle at build time from an exact-pinned `webpki-root-certs` Mozilla snapshot and installs it directly in native and browser guest roots before the first execution, including read-only and restored roots. Explicit root-filesystem entries at either trust path take precedence. -This provides the conventional file locations and Mozilla public roots, **not a byte-for-byte Debian or Alpine `ca-certificates` installation**. Distribution packages can select a different snapshot, add policy-managed or local roots, generate OpenSSL hash links, and provide tools such as `update-ca-certificates`; AgentOS does not imply those distro-specific files or update behavior. Supply a custom root-filesystem entry or use the tool-specific trust flags when you need a different trust policy. +This provides the conventional file locations and Mozilla public roots, **not a byte-for-byte Debian or Alpine `ca-certificates` installation**. Distribution packages can select a different snapshot, add policy-managed or local roots, generate OpenSSL hash links, and provide tools such as `update-ca-certificates`; agentOS does not imply those distro-specific files or update behavior. Supply a custom root-filesystem entry or use the tool-specific trust flags when you need a different trust policy. mbedTLS is **not** a general OpenSSL replacement — it lacks providers/engines, CMS/PKCS#7, the `openssl` CLI, and much of libcrypto's breadth. It **is** a complete replacement for OpenSSL's role as curl/wget/git's TLS backend, which is all an HTTPS client needs. diff --git a/vendor/agentos/docs/content/docs/authentication.mdx b/vendor/agentos/docs/content/docs/authentication.mdx deleted file mode 100644 index 6851d396..00000000 --- a/vendor/agentos/docs/content/docs/authentication.mdx +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: "Authentication" -description: "Authenticate connections to agentOS actors with Rivet Actor connection parameters and hooks, then carry trusted identity into sessions." -skill: true ---- - -agentOS uses the same authentication system as [Rivet Actors](/actors/docs/authentication): clients send credentials as connection params, and you validate them server-side. - -- Clients pass credentials in `params` when they connect. -- Validate them on the server in `onBeforeConnect` (throw to reject the connection), or extract user data into connection state with `createConnState` (read it in actions via `c.conn.state`). -- You can declare the credential shape with `agentOS(...)` to document what you accept, but the client's `params` is `unknown` and is not checked against it. The real check is your hook, not the types. -- AgentOS uses ordinary Rivet actor connection hooks, so authentication runs before the connection reaches an action. - -## Example - -The server declares the credential shape and validates it in `onBeforeConnect` (throw to reject); the client passes credentials as `params`. - - - - - - - -See [Actor Authentication](/actors/docs/authentication) for JWT validation, role-based access control, external auth providers, and token caching. - -## Embedded API - -This layer requires Rivet Actors. An [embedded](/agentos/docs/embedded) VM has no connections, no `params`, and no `onBeforeConnect`, so `AgentOs.create()` authenticates nobody. Your application authenticates its own callers before it touches the VM handle, and decides which caller may reach which VM. - -Session credentials still work through `vm.sessions.open()`; see -[Models & Credentials](/agentos/docs/models-and-credentials#embedded-api). - -Read more in the [embedded API quickstart](/agentos/docs/quickstart-embedded). diff --git a/vendor/agentos/docs/content/docs/bash.mdx b/vendor/agentos/docs/content/docs/bash.mdx index cb8d1e46..61bbeda8 100644 --- a/vendor/agentos/docs/content/docs/bash.mdx +++ b/vendor/agentos/docs/content/docs/bash.mdx @@ -9,50 +9,125 @@ Run bash inside the VM. Shell commands are the simplest agentOS execution surface, and share the same execution lifecycle as JavaScript, TypeScript, Python, and package workflows. -- **`process.exec()`**: Runs a bash command line. Use for pipes, redirects, globs. -- **`process.execFile()`**: Injection-safe; args are never parsed by a shell. +- **Hosted `v1.process.run`** takes an executable and an argument array. Run + `sh` with `-c` for pipes, redirects, and globs. +- **Library `process.exec()`** runs a bash command line, and + **`process.execFile()`** runs an executable whose arguments are never parsed + by a shell. - **In-VM only**: Commands run inside the VM, never in the host shell. -For multi-step work, consider letting the agent write [JavaScript](/agentos/docs/javascript) -or [Python](/agentos/docs/python) instead — one round trip and real data structures -rather than a chain of shell calls. +For multi-step work, consider [JavaScript](/agentos/docs/javascript) or +[Python](/agentos/docs/python) instead. One call returns real data structures +instead of a chain of shell calls. ## Run commands - + + +```ts Hosted @nocheck +import { createAgentOsClient } from "@rivet-dev/agentos"; + +const client = createAgentOsClient({ endpoint: "https://api.rivet.dev" }); +const vm = client.agentOS.getOrCreate(["my-vm"]); + +// Pipes, redirects, and globs need a shell, so run `sh -c`. +const piped = await vm.v1.process.run({ + command: "sh", + args: ["-c", "echo 'hello world' | tr a-z A-Z"], + options: { captureStdio: true }, +}); +console.log(piped.stdout.trim()); // "HELLO WORLD" + +// Arguments are passed verbatim, so nothing is parsed by a shell. +const raw = await vm.v1.process.run({ + command: "echo", + args: ["$(whoami)"], + options: { captureStdio: true }, +}); +console.log(raw.stdout.trim(), raw.status.exitCode); // "$(whoami)" 0 +``` + + + + ## Background and interactive work -`spawn` starts a long-lived process and returns a `pid`. From there you get +`spawn` starts a long-lived process and returns a handle. From there you get stdin, a PTY, output replay, signals, and waiting. - + + +```ts Hosted @nocheck +import { createAgentOsClient } from "@rivet-dev/agentos"; + +const client = createAgentOsClient({ endpoint: "https://api.rivet.dev" }); +const vm = client.agentOS.getOrCreate(["my-vm"]); + +const shell = await vm.v1.process.spawn({ command: "sh", args: [] }); + +await vm.v1.process.stdin.write({ process: shell, data: "echo from the background\n" }); +await vm.v1.process.stdin.close({ process: shell }); + +await vm.v1.process.wait({ process: shell }); +const replay = await vm.v1.process.output.read({ process: shell }); +console.log(replay.events.length); +``` + + + + ## Files and software -Shell commands see the persistent [filesystem](/agentos/docs/filesystem) shared by -agents, JavaScript, and Python. Common POSIX commands ship by default; more is +Shell commands see the same [filesystem](/agentos/docs/filesystem) as +JavaScript and Python. Common POSIX commands ship by default; more is projected through the [software registry](/agentos/docs/software). - + + +```ts Hosted @nocheck +import { createAgentOsClient } from "@rivet-dev/agentos"; + +const client = createAgentOsClient({ endpoint: "https://api.rivet.dev" }); +const vm = client.agentOS.getOrCreate(["my-vm"]); + +await vm.v1.process.run({ + command: "sh", + args: ["-c", "printf 'a\\nb\\nc\\n' > /workspace/out.txt"], +}); + +const lines = await vm.v1.process.run({ + command: "sh", + args: ["-c", "cat /workspace/out.txt | wc -l"], + options: { captureStdio: true }, +}); +console.log(lines.stdout.trim()); // "3" +``` + + + + ## Host functions -[Host functions](/agentos/docs/host-functions) appear as commands, so pipelines use trusted host -capabilities without putting credentials inside the VM. +[Host functions](/agentos/docs/host-functions) appear as commands, so pipelines +use trusted host capabilities without putting credentials inside the VM. Host +functions are library-only. - + ## Permissions, limits, and timeouts Every command inherits the VM [permission policy](/agentos/docs/permissions) and [resource limits](/agentos/docs/resource-limits). - + ## Embedded API -The examples above already use `AgentOs.create()`. The host owns `dispose()`, -and filesystem state only outlives the VM when you configure `database`. +The library examples use `AgentOs.create()`. The host owns `dispose()`, and +files only outlive the VM when its root filesystem is stored in SQLite; see +[Persistence](/agentos/docs/persistence). Read more in the [embedded API quickstart](/agentos/docs/quickstart-embedded). diff --git a/vendor/agentos/docs/content/docs/browser.mdx b/vendor/agentos/docs/content/docs/browser.mdx index bd4e6df4..7bda693b 100644 --- a/vendor/agentos/docs/content/docs/browser.mdx +++ b/vendor/agentos/docs/content/docs/browser.mdx @@ -1,86 +1,15 @@ --- title: "Browser Automation" -description: "Let agents read and search the web from an agentOS VM using Browserbase's cloud browser through the browse CLI — no local browser or sandbox required." -skill: true +description: "Run a packaged browser CLI as ordinary agentOS software." --- -Agents can read and search the web with the [Browserbase](https://www.browserbase.com) `browse` CLI. The page loads in a real browser in Browserbase's cloud and comes back as clean content — the VM never runs a browser. +Browser automation is ordinary VM software. Install a browser CLI package, such +as Browserbase from the [registry](/agentos/docs/registry), at boot or with +`software.install`, then run it like any other command. See +[Software](/agentos/docs/software). -## Setup +The guest receives only the credentials explicitly passed to the process +environment. agentOS does not provide a browser-specific API. - - - - -[Sign up](https://www.browserbase.com/sign-up) and grab your API key and project id from the [dashboard](https://www.browserbase.com/settings): - -```bash -export BROWSERBASE_API_KEY=bb_... -export BROWSERBASE_PROJECT_ID=... -``` - - - - - -```bash -npm install @rivet-dev/agentos @agentos-software/pi @agentos-software/browserbase -``` - - - - - - - - -Mount the [`browse` CLI skill](https://github.com/browserbase/stagehand/tree/main/packages/cli) into the agent's skills directory so it reaches for `browse` unprompted ([copy the skill folder from the example](https://github.com/rivet-dev/agentos/tree/main/examples/browserbase/skills)): - - - - - - - - - - - - - - - - - - - - - - - - - - - - -## Command reference - -```bash -browse cloud fetch https://example.com # retrieve a page as markdown -browse cloud search "web scraping tools" # search the web -browse cloud sessions list # list cloud browser sessions -browse cloud projects list # list Browserbase projects -``` - - -The [interactive driver mode](https://docs.browserbase.com/integrations/skills/browse-cli) (`browse open`, `browse click`, …) is not supported inside the VM yet ([#1631](https://github.com/rivet-dev/agentos/issues/1631)). For interactive automation, run `browse` inside an external sandbox via [External Sandboxes](/agentos/docs/sandboxes). - - -## Embedded API - -Install the same Browserbase software package and pass its credentials through -the embedded session environment. - - - -Read more in the [embedded API quickstart](/agentos/docs/quickstart-embedded). +For workloads that need a full local browser, mount an +[external sandbox](/agentos/docs/sandboxes) and run the browser there. diff --git a/vendor/agentos/docs/content/docs/cron.mdx b/vendor/agentos/docs/content/docs/cron.mdx index b72889bc..2337e042 100644 --- a/vendor/agentos/docs/content/docs/cron.mdx +++ b/vendor/agentos/docs/content/docs/cron.mdx @@ -1,83 +1,68 @@ --- -title: "Crons & Loops" -description: "Schedule recurring commands and coding-agent sessions in agentOS VMs with durable loops that survive restarts, sleep, and worker movement." +title: "Crons & Schedules" +description: "Schedule recurring and one-shot VM commands." skill: true --- -Schedule recurring work and long-running agent loops with cron expressions, -running either a shell command (`exec`) or an agent session (`session`), with -overlap modes (`allow`, `skip`, `queue`) and native `cronEvent` streaming to -monitor execution. Cron jobs keep the actor alive while a job runs; the actor -can sleep between executions. +Schedule commands to run inside the VM on a cron expression. Hosted VMs store +their jobs with the VM. Library jobs run while the embedding process and the VM +are alive, so durable scheduling across process restarts is up to the +application that owns the VM. ## Schedule a command -Run a shell command on a recurring schedule. Pass a custom `id` to make a job easier to manage and cancel later. - - - - - - -## Schedule an agent session - -Create a recurring agent session that runs a prompt on a schedule. - - - - - - -## Overlap modes - -Control what happens when a cron job triggers while a previous execution is still running. - -| Mode | Behavior | -|------|----------| -| `"skip"` | Skip this trigger if the previous run is still active | -| `"allow"` | Allow concurrent executions (default) | -| `"queue"` | Queue this trigger and run it after the previous one finishes | - -Prefer `"skip"` for most jobs to avoid unbounded concurrency if a run takes longer than the interval. Use `"queue"` when every trigger must eventually execute. - - - - -## Monitor cron events +```ts Hosted @nocheck +import { createAgentOsClient } from "@rivet-dev/agentos"; -Subscribe with `connection.on("cronEvent", ...)` to track job execution. Event and job timestamps are ISO strings. The callback receives a `CronEvent` directly, with no `{ event }` wrapper. +const client = createAgentOsClient({ endpoint: "https://api.rivet.dev" }); +const vm = client.agentOS.getOrCreate(["my-vm"]); - +const job = await vm.v1.cron.schedule({ + name: "cleanup", + expression: "0 * * * *", + command: "rm", + args: ["-rf", "/tmp/cache"], + options: { env: {} }, +}); +console.log("Scheduled:", job.name); -Subscribe before scheduling so you do not miss early runs. +const conn = vm.connect(); +await conn.ready; +conn.on("cron.fired", (event) => { + console.log("Cron event:", event); +}); - - - - +for (const scheduled of await vm.v1.cron.list({})) { + console.log(scheduled.name, scheduled.expression); +} +``` -## List and cancel cron jobs + - - - -## Example: Heartbeat pattern - -Schedule a recurring agent session to periodically check on a task. This is the core pattern behind [OpenClaw](https://openclaw.org), where an agent wakes up on a schedule to review progress, take action, and go back to sleep. - - - -The agent sleeps between executions and only consumes resources when the cron job fires. - -## Embedded API - -The cron API is identical, but events are process-local. Jobs only run while -the embedded VM is alive, so the host must reschedule them after a restart. - - - -Read more in the [embedded API quickstart](/agentos/docs/quickstart-embedded). +Hosted jobs are identified by `name` and run a command with arguments. A hosted +VM holds up to 1,024 jobs, with names and expressions up to 256 bytes, and +retains 32 runs per job by default (256 maximum). + +In the library, `schedule` takes a standard cron expression or an ISO 8601 +timestamp for a one-shot job. `action` is either `{ type: "exec", command, args }`, +which runs a command in the VM, or `{ type: "callback", fn }`, which calls a +function in the host process. `overlap` controls what happens when a job fires +while its previous run is still going: `"allow"` (the default) starts another +run, `"skip"` drops the new run, and `"queue"` waits for the previous run to +finish. + +## Inspect and cancel jobs + +| Operation | Hosted | Library | +|---|---|---| +| List jobs | `v1.cron.list` | `cron.list()`, with `lastRun`, `nextRun`, `runCount`, and `running` | +| Cancel a job | `v1.cron.cancel({ name })` | `cron.cancel(id)`, or `cancel()` on the returned job | +| Run events | `cron.fired` | `vm.onCronEvent` with `cron:fire`, `cron:complete`, and `cron:error` | + +In the library, pass `scheduleDriver` to `AgentOs.create()` to replace the +default timer-based driver, for example with one backed by your own durable +scheduler. diff --git a/vendor/agentos/docs/content/docs/custom-software/building-wasm.mdx b/vendor/agentos/docs/content/docs/custom-software/building-wasm.mdx index 18662c6e..f0e6af8c 100644 --- a/vendor/agentos/docs/content/docs/custom-software/building-wasm.mdx +++ b/vendor/agentos/docs/content/docs/custom-software/building-wasm.mdx @@ -1,64 +1,26 @@ --- -title: "Building Binaries" -description: "Compile command-line software to WebAssembly for agentOS VMs, package the resulting binaries, and verify they run in the guest environment." +title: "Building Software" +description: "Compile Linux-compatible commands and pack them for agentOS." --- -WASM command packages ship **compiled `.wasm` binaries** in their `bin/` that run inside the VM as guest commands. The binaries are build artifacts and are not checked into git, so to add or change a command you build it from source in the AgentOS repo. +agentOS builds real upstream command implementations for its Linux-in-WASM +runtime. Missing libc or POSIX behavior belongs in the owned sysroot and host +imports, not in command wrappers. - -You only need this to author new commands. To use existing ones, install the published package (e.g. `@agentos-software/ripgrep`) and pass it to `software`. See [using the registry](#using-the-registry) below. - - -## Where it lives - -Command packages live under top-level `software/`, while shared build infrastructure lives under `toolchain/`: - -- **`software//native/crates/cmd-/`**: the Rust source for each command — a cargo package named `cmd-` that emits a `` binary. -- **`software//native/c/`**: the C source for C-built package commands. -- **`software//`**: the npm package for each command set (`@agentos-software/`). It exports a `{ packagePath }` descriptor pointing at the packed `dist/package.aospkg`, and declares which binaries it ships in its `agentos-package.json` (`commands`, plus optional `aliases` and `stubs`). - -## Build - -Everything runs through `just` recipes at the AgentOS repo root: +From the repository root: ```bash -just toolchain-build # compile ALL native wasm binaries (slow; once per checkout) -just toolchain-cmd sh # recompile ONE command (cargo package cmd-sh) -just software-build # stage + assemble every software package -just software-build ripgrep # ... or just one +pnpm install --frozen-lockfile +just tools-rebuild ``` -The native build compiles each command for `wasm32-wasip1` with the pinned **nightly** toolchain from `rust-toolchain.toml` (the build vendors and patches `std` for WASI), optimizes with `wasm-opt`, and drops the binaries in `toolchain/target/wasm32-wasip1/release/commands/`. C-based commands (e.g. `sqlite3`, `unzip`, `wget`, `zip`) compile with a **wasi-sdk** clang toolchain via `make -C toolchain/c`. - -Each package's build then runs the **agentos-toolchain** lifecycle: `agentos-toolchain stage` copies the binaries listed in the package's `agentos-package.json` into its `bin/`, and `agentos-toolchain build` assembles the clean `dist/package/` dir with a `bin` map in its `package.json` and packs it into `dist/package.aospkg` (the `{ packagePath }` target). - -## Add a new command package +For one command: -1. Add the command source as `software//native/crates/cmd-/` (cargo package `cmd-`; Rust) or under `software//native/c/` (C). -2. Create `software//` as an `@agentos-software/` npm package that exports a `{ packagePath }` descriptor pointing at `dist/package.aospkg`. -3. Declare the shipped binaries in its `agentos-package.json`: `{ "commands": [""] }` (plus `aliases`/`stubs` if needed). -4. If it belongs in a meta-package (e.g. `common` or `build-essential`), add it there. -5. Verify with `just toolchain-cmd && just software-build ` and `pnpm --filter './software/*' test`. - -## Let an agent build it - -This is a mechanical, well-scoped task, so you can hand it to a coding agent. A prompt like: - -```text -Add a WASM command package for `` to AgentOS: -- put the Rust source at software//native/crates/cmd-/ as a cargo - package named cmd-, -- create software// as an @agentos-software/ npm - package that exports a { packagePath } descriptor and declares the command in - its agentos-package.json, -then run `just toolchain-cmd && just software-build ` -and `pnpm --filter './software/*' test`, and fix any failures. +```bash +just toolchain-cmd +just software-build ``` -## Using the registry - -Install a published package and pass it to `software`. Registry WASM packages are `{ packagePath }` descriptors — import and pass them directly: - - - -Meta-packages bundle a full set, e.g. `@agentos-software/common` (coreutils, sed, grep, gawk, findutils, diffutils, tar, gzip). Run the commands from the client; see [Processes & Shell](/agentos/docs/processes/). Browse the full catalog on the [Registry](/agentos/registry/), and see the package descriptor in [Software Definition](/agentos/docs/custom-software/definition/). To ship your package to npm or use a local build, see [Publishing Packages](/agentos/docs/custom-software/publishing/). +The toolchain stages generated commands into each package and writes +`software//dist/package.aospkg`. Generated binaries, sysroots, and +package artifacts are not committed. diff --git a/vendor/agentos/docs/content/docs/custom-software/definition.mdx b/vendor/agentos/docs/content/docs/custom-software/definition.mdx index 016ffb7a..230ce4ac 100644 --- a/vendor/agentos/docs/content/docs/custom-software/definition.mdx +++ b/vendor/agentos/docs/content/docs/custom-software/definition.mdx @@ -1,236 +1,25 @@ --- -title: "Software Definition" -description: "Define custom agentOS software packages, provide packed or local package paths, and expose commands and coding-agent adapters inside VMs." +title: "Software Package Definition" +description: "Define an immutable agentOS .aospkg artifact." --- -**Software** is anything you install into a VM — **commands** (executables in a package's `bin/`) or an **agent** (a package that also exposes an ACP session). +An agentOS software package is a packed v2 `.aospkg` file containing commands +and their runtime files. -A package is **self-contained**: package it first, then point `defineSoftware()` at it with `{ packagePath }` — the packed `.aospkg` the toolchain emits, or (for local development) the package directory itself. The package's name, optional agent block, and any files/env it provides are authored in an `agentos-package.json` next to your sources; the toolchain compiles that JSON into the `.aospkg`'s embedded manifest at pack time (the JSON itself is never shipped into the VM). Pick the quickstart that matches what you're packaging. +The container contains: -## Quickstart +1. a fixed header; +2. a versioned vbare package manifest; +3. a versioned mount index; +4. the mount tar. -### WebAssembly +`agentos-package.json` is toolchain input only. Packing encodes its runtime +fields into the vbare manifest and removes the JSON file from the mounted +payload. - +Commands are projected under `/opt/agentos/pkgs//` and linked +under `/opt/agentos/bin`. The sidecar reads the package projection live. - - -C or Rust source for a command. (Most common commands already ship as `@agentos-software/*` packages you can use directly — compile only new or custom ones.) - - - - - -Compile it to WebAssembly. See [Building Binaries](/agentos/docs/custom-software/building-wasm). There's **no `pack` step**: WASM binaries are self-contained, so the compile output is already the package — a `bin/` of `\0asm` files plus a `package.json` for the name/version: - -``` -my-cmds/ -├── package.json -└── bin/ - ├── tool-a # \0asm WebAssembly - └── tool-b -``` - - - - - -Point `defineSoftware()` at that directory: - - - - - - - -Pass it to a VM. The commands are on `$PATH`: - - - - - - - -### Node.js - - - - - -A local project whose `package.json` `bin` names its commands: - -``` -my-tool/ -├── package.json # "bin": { "my-tool": "cli.js" } -└── cli.js # #!/usr/bin/env node -``` - - - - - -`pack` installs the full dependency closure into a self-contained package directory (a flat `node_modules` plus a `bin` map of real files): - -```bash -npx @rivet-dev/agentos-toolchain pack ./my-tool -# writes ./my-tool-package/ (override the location with --out ) -# my-tool-package/ -# ├── package.json # "bin": { "my-tool": "node_modules/my-tool/cli.js" } -# └── node_modules/ # flat, self-contained closure -``` - -Commands come from the package's `package.json` `bin` map — **real files, no symlinks** — so the result ships cleanly as an npm dependency. (The runtime makes the `/opt/agentos/bin` symlinks itself when it mounts the package.) A native `.node` addon is an error (it can't run in V8); re-run with `--prune-native` to drop unreachable ones. - - - - - -Point `defineSoftware()` at the packaged directory: - - - - - - - -Pass it to a VM. `my-tool` is now on `$PATH`: - - - - - - - -### Agent - -An agent is a Node.js or WASM package (packaged exactly as above) whose `agentos-package.json` carries an **`agent` block** naming a `bin/` command that speaks ACP over stdio. - - - - - -An npm package with a `bin/` command that speaks ACP over stdio. - - - - - -Use the same `pack` command as Node.js, with `--agent` naming the ACP entrypoint. That writes the `agent` block into the package's `agentos-package.json`: - -```bash -npx @rivet-dev/agentos-toolchain pack @scope/my-agent --out ./packages --agent my-agent-acp -# → ./packages/my-agent/current (its agentos-package.json now has the agent block) -``` - - - - - -Point `defineSoftware()` at the packaged directory. The agent block is already in its `agentos-package.json`: - - - - - - - -Choose a session ID, then `openSession({ sessionId, agent })` launches the agent by spawning its `acpEntrypoint`: - - - - - - - -## Reference - -### The descriptor - -A software entry is just a pointer to the packed package: - -```ts -defineSoftware({ - packagePath: string, // absolute host path to the packed .aospkg - // (or a package directory, for local development) -}) -``` - -The normal `packagePath` is the `dist/package.aospkg` that `agentos-toolchain build`/`pack` emit — -a single file holding the package manifest, a precomputed mount index, and the package's mount tar. -A directory is accepted for local development; it must contain **only the package** — a -`package.json` with a `bin` map, the runtime files (`bin/`, a flat `node_modules`), and an -`agentos-package.json`. It is mounted read-only, so **don't point it at a source root**: that drags -`src/`, dev `node_modules/`, `tsconfig`, and build caches into the VM. - - -`pack` already emits the packed `.aospkg`. For a package you build by hand (e.g. compiled WASM), -run `agentos-toolchain build` to assemble `dist/package/` and pack `dist/package.aospkg`, then -point `packagePath` there — never at the workspace root: - -```ts -const packagePath = resolve(import.meta.dirname, "dist/package.aospkg"); -export default defineSoftware({ packagePath }); -``` - - -### `agentos-package.json` - -The package's name, optional agent block, and any files/env it provides are authored in an -`agentos-package.json` at the package root. It is **toolchain input**: at pack time it is compiled -into the `.aospkg`'s embedded manifest (which is what the sidecar reads) and stripped from the -packed files, so the JSON never ships into the VM and the metadata never travels on the wire. For -command/WASM packages it is **generated** for you (name from `package.json`); for agents you -author the `agent` block (or `agentos-toolchain pack --agent ` writes it). - -```json -{ - "name": "my-agent", // → /opt/agentos/ - "agent": { // optional — also exposes an agent session - "acpEntrypoint": "my-agent-acp", // bin/ command that speaks ACP over stdio - "env": { }, // static env for the adapter - "launchArgs": [], - "snapshot": false // SDK snapshot optimization - }, - "provides": { // optional — files + env the package contributes - "env": { "EXAMPLE_HOME": "/opt/agentos/my-agent" }, - "files": [{ "source": "etc/example.conf", "target": "/etc/example.conf" }] - } -} -``` - -- **`name`** — the package name; commands and the package mount under `/opt/agentos/`. -- **`agent.acpEntrypoint`** — the `bin/` command spawned to start a session; speaks ACP over stdio. -- **`agent.env`** — static env vars for the adapter, merged under the user env. Every command is on `$PATH`, so point at one directly, e.g. `{ "PI_ACP_PI_COMMAND": "/opt/agentos/bin/pi" }` so `pi-acp` can spawn the `pi` CLI. -- **`agent.launchArgs`** — extra CLI args prepended when launching the adapter. -- **`agent.snapshot`** (default `false`) — load the SDK [once per sidecar](#sdk-snapshotting--snapshot-safety) via a shared V8 heap snapshot instead of per session. Falls back to per-session loading if the SDK isn't snapshot-safe, so it only affects startup latency. -- **`provides.env`** — env vars merged into the VM's base environment (existing values win — a package never clobbers the user env). -- **`provides.files`** — read-only files overlaid into the VM filesystem. Each `{ source, target }` maps a path **inside the package** to an **absolute VM path**; the sidecar mounts them as zero-copy read-only lower layers (a guest write copies-up, never touching the host). A missing `source` is a fatal packaging error. - -## Advanced - -### Meta-packages - -A software entry may be an **array** of descriptors, so one package can bundle several. Pass arrays directly to `software`: - -```ts -const vm = agentOS({ - software: [pi, buildEssential /* = [coreutils, make, git, curl] */], -}); -``` - -### SDK snapshotting & snapshot-safety - -A V8 heap snapshot freezes the heap *after* the SDK's modules are evaluated, then seeds each new session's isolate from it. This works only if the SDK's **module-init** code (everything that runs at `import`/`require` time) doesn't: - -- Create **native handles** — load a `.node` addon, instantiate WebAssembly, or produce a V8 `External`/`Foreign` at top level. -- Open a **file descriptor, socket, timer, or worker**, or leave a **pending promise**. -- Bake in **non-deterministic or per-session state** — `process.env`, cwd, `Date.now()`, `Math.random()`, a UUID. - -Defer all of the above behind functions or lazy `import()` that run per session. Leave `agent.snapshot: false` for any SDK that can't — the agent still runs, just without the speedup. - -## Next steps - -- [Custom Agents](/agentos/docs/agents/custom): the agent-focused guide. -- [Building Binaries](/agentos/docs/custom-software/building-wasm): compile WASM commands and use the registry. -- [Packages & command resolution](/agentos/docs/architecture/packages-and-command-resolution): how packages mount and resolve. -- [Request Software](https://github.com/rivet-dev/agentos/issues/new/choose): ask for a package you need. +The package format contains no callback or host-path metadata. Install a package +from an HTTPS URL or a trusted local path, each with an optional exact digest; +see [Software](/agentos/docs/software). diff --git a/vendor/agentos/docs/content/docs/custom-software/publishing.mdx b/vendor/agentos/docs/content/docs/custom-software/publishing.mdx index 471b11f7..a4888d60 100644 --- a/vendor/agentos/docs/content/docs/custom-software/publishing.mdx +++ b/vendor/agentos/docs/content/docs/custom-software/publishing.mdx @@ -1,80 +1,36 @@ --- -title: "Publishing Packages" -description: "Package, publish, and consume custom agentOS software through local paths, npm registries, or private repositories with pinned versions." +title: "Publishing Software" +description: "Stage and upload digest-addressed .aospkg artifacts." --- -agentOS packages — WASM command sets and packed JS agents alike — go through one lifecycle, owned by the **`@rivet-dev/agentos-toolchain`** CLI. This page covers the full flow: building a package, publishing it to npm, and wiring a consumer at either a published version or a local checkout. +Registry software is not published to npm. The release workflow builds every +package, computes its SHA-256 digest, and stages: -## The lifecycle - -Every package is an npm package whose default export points at a self-contained runtime dir (`dist/package/`) that the sidecar projects under `/opt/agentos//`. The toolchain provides four subcommands: - -| Command | What it does | -|---|---| -| `stage --commands-dir ` | Populate `bin/` from a directory of compiled binaries, per the `commands` / `aliases` / `stubs` lists in the package's `agentos-package.json`. | -| `build` | Assemble `dist/package/` from `bin/` (+ optional `share/`) and pack it into `dist/package.aospkg` — the runtime artifact with the embedded manifest (the `agentos-package.json` is pack-time input, not shipped). | -| `pack` | Build a self-contained node-closure package from an npm package or local dir (JS agents; validates headers, rejects native addons). | -| `publish` | Publish the built package to npm. Dist-tag is **`dev` by default**; the `latest` pointer only moves with an explicit `--latest`. | - -## Building - -In the AgentOS registry, the `just` recipes drive the toolchain (see [Building Binaries](/agentos/docs/custom-software/building-wasm)): - -```bash -just toolchain-build # compile the native wasm binaries (once per checkout) -just software-build # stage + assemble every software package -just software-build coreutils # ... or one package +```text +software/ +├── manifest.json +└── packages//.aospkg ``` -## Publishing +`manifest.json` contains a package name, exact `sha256:` digest, byte size, +and a path relative to the manifest URL. It is a build inventory, not a +semantic-version resolver. -Registry packages **version independently** — each package carries its own semver in its `package.json`. Bump and commit the version, then: +Run the credential-free release staging path locally: ```bash -just registry-publish coreutils # publish under dist-tag `dev` -just registry-publish coreutils my-branch # ... under a custom tag -just registry-publish coreutils latest # DELIBERATE release: moves `latest` -just registry-publish-all # every built software package, tag `dev` +just software-artifacts-dry-run ``` -Consumers installing `@agentos-software/` with no tag resolve `latest`, so `latest` is reserved for deliberate releases — a dev publish can never clobber what users install. - -## Consuming published packages - -In agent-os, the `@agentos-software/*` packages are pinned **per-package** in the workspace catalog. Manage the pins with the `just` recipes (never hand-edit them): - -```bash -just agentos-pkgs-status # current mode + pinned versions -just agentos-pkgs-set-version coreutils 0.3.1 # pin one package -just agentos-pkgs-update # re-pin all from the `latest` dist-tag -just agentos-pkgs-update dev # ... or from another tag -``` +The release workflow uploads the same directory under immutable commit and +version prefixes, and copies the newest release to `latest`: -## Local development - -AgentOS consumes local registry builds by default because the software packages -are pnpm workspace members. Build the native commands with `just toolchain-build` -and assemble packages with `just software-build`; no sibling checkout or -published package is required while iterating. - -Published-version pins exist only in release validation and downstream -consumers. The AgentOS workspace itself stays self-contained. - -## Publishing from your own repo - -The toolchain is not registry-specific — any repo can produce and publish agentOS packages with `npx @rivet-dev/agentos-toolchain`: - -```bash -# a package dir with package.json + agentos-package.json + your compiled binaries -npx @rivet-dev/agentos-toolchain stage --commands-dir ./build/wasm -npx @rivet-dev/agentos-toolchain build -npx @rivet-dev/agentos-toolchain publish --tag dev # or --latest for a release -``` - -For a JS agent, `pack` replaces `stage`/`build`: - -```bash -npx @rivet-dev/agentos-toolchain pack . --out dist/package --agent my-acp-entrypoint +```text +https://releases.rivet.dev/agent-os//software/manifest.json +https://releases.rivet.dev/agent-os/latest/software/manifest.json ``` -The published package is a plain npm dependency — consumers import its descriptor and pass it to `software` exactly like the software packages. See [Software Definition](/agentos/docs/custom-software/definition) for the descriptor shape. +The same directory also holds `default-software.json`, the manifest of the +packages every VM installs by default. Consumers pass an artifact URL and +digest from the manifest directly to `software.install`; see +[Software](/agentos/docs/software#install-while-running). diff --git a/vendor/agentos/docs/content/docs/debugging.mdx b/vendor/agentos/docs/content/docs/debugging.mdx deleted file mode 100644 index f54f4cdf..00000000 --- a/vendor/agentos/docs/content/docs/debugging.mdx +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: "Debugging" -description: "Diagnose agentOS sessions, tool calls, VM crashes, and runtime failures by collecting coding-agent logs, sidecar logs, and execution context." ---- - -Before reaching for logs, open the actor inspector in the Rivet dashboard. It shows the live transcript, pending permission requests (the most common reason an agent looks stuck), and the process tree. - -Two log streams help diagnose what's happening inside a VM: the **agent's** own output and the **runtime (sidecar)** logs. - -## Agent logs (`onAgentStderr`) - -The coding agent (ACP adapter) runs as a process inside the VM and uses **stdout for the ACP protocol**, so its **stderr** carries the agent's logs, warnings, and crash output — the first place to look when a tool call or session fails mid-turn. Capture it with `onAgentStderr` on the VM: - - - -It's a VM-level option covering every session's agent process; if omitted, -chunks are written to the host `process.stderr` by default. See -[Sessions](/agentos/docs/sessions) for session lifecycle and history. - -## Agent crashes (`onAgentExit`) - -If an adapter exits unexpectedly, the runtime logs the exit, does **not** restart it or replay an uncertain prompt, and fires `onAgentExit`: - - - -The durable session and committed SQLite history remain available. The crash *reason* is on the adapter's stderr; the exit event reports that the live runtime disappeared. A later explicit prompt performs restoration. See [Sessions](/agentos/docs/sessions). - -## Runtime logs (sidecar) - -The agentOS sidecar emits structured **logfmt** logs for request handling, networking, and lifecycle. Configure them with environment variables on the **host process** (the sidecar inherits the host environment): - -| env var | effect | -|---------|--------| -| `AGENTOS_LOG_LEVEL` / `LOG_LEVEL` / `RUST_LOG` | log filter, in that priority. Uses [EnvFilter](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html) syntax, e.g. `debug`, `info`, `agentos_sidecar=debug,info`. Default `info`. | -| `RUST_LOG_FORMAT` | `logfmt` (default) or `text` | -| `AGENTOS_LOG_FILE` | append logs to this file instead of stderr (never stdout, which carries the wire protocol) | -| `RUST_LOG_{SPAN_NAME,SPAN_PATH,TARGET,LOCATION,MODULE_PATH,ANSI_COLOR}` | per-field toggles (`=1` to enable) | - -```bash -AGENTOS_LOG_LEVEL=debug AGENTOS_LOG_FILE=./sidecar.log RUST_LOG_FORMAT=logfmt node app.mjs -``` - -Produces logfmt lines such as: - -```text -ts=2026-… level=info message="ext request received" kind=create_session -ts=2026-… level=info message="ext request handled" kind=create_session elapsed_ms=1798 -ts=2026-… level=debug message="querying: api.anthropic.com. A" -``` - - -Most sidecar log activity is on the session/ACP path. A bare `AgentOs.create()` or a single `exec()` emits almost nothing — create a session (and send a prompt) to see request-handling logs. - - -Use **agent logs** to see what the agent did (tool calls, model errors), and **runtime logs** to see what the sidecar did around it (request timing, DNS, lifecycle). - -## Embedded API - -The examples above already use `AgentOs.create()`. Its callbacks and sidecar -logs are process-local; the actor inspector is not available. - -Read more in the [embedded API quickstart](/agentos/docs/quickstart-embedded). diff --git a/vendor/agentos/docs/content/docs/embedded.mdx b/vendor/agentos/docs/content/docs/embedded.mdx index 4efebbda..4f36ebae 100644 --- a/vendor/agentos/docs/content/docs/embedded.mdx +++ b/vendor/agentos/docs/content/docs/embedded.mdx @@ -1,84 +1,34 @@ --- title: "Embedded VMs" -description: "Reference for embedding agentOS VMs in an existing Node.js application without Rivet Actors." +description: "Embed agentOS Core in a trusted Node.js application." skill: true --- -Use the embedded API when you already have a Node.js application and want to -control agentOS VMs directly. You manage VM identity, persistence, and lifecycle -yourself instead of using Rivet Actors. +`@rivet-dev/agentos-core` runs agentOS VMs inside your Node.js process. Your +application owns VM identity, persistence, and disposal. Its native sidecar and +platform package must match the installed agentOS version. If resolution +reports a missing or mismatched binary, reinstall the packages; +`AGENTOS_SIDECAR_BIN` can select a custom local build. -To create your first embedded VM, start with the -[embedded quickstart](/agentos/docs/quickstart-embedded). + -This page covers only what is different about embedding. Each capability is -documented on its own page, which ends with a short `Embedded API` section. +## Trusted host capabilities -## Embedded API vs actor +Because the embedding process is trusted, Core accepts values that run in or +read from the host: -| | Embedded API | Actor | -|-|---|---| -| Persistence | In-memory unless you configure `database`, plus [mounts](/agentos/docs/filesystem#mounts) | Actor SQLite injected automatically | -| Distributed state | Manage yourself | Built-in | -| Stateful VMs | Complex to run yourself | Built into Rivet | -| Sleep/wake | Manual `dispose()` / `create()` | Automatic | -| Events | Direct in-process callbacks | Broadcast to every connected client | -| Preview URLs | Serve them from your own application | Built-in signed URL server | -| Multiplayer | Fan out from your own application | Multiple clients per actor | -| Orchestration | VM-local [cron](/agentos/docs/cron) while the VM is alive | Workflows, queues, and cron | -| Agent-to-agent | [Host functions](/agentos/docs/agent-to-agent) between VMs you own | Built into [Rivet Actors](/agentos/docs/agent-to-agent) | -| Authentication | Your application's own | [Docs](/agentos/docs/authentication) | - -- Use [Rivet Actors](/actors/docs/) for persistence, networking, and - orchestration. -- Use `AgentOs.create()` to embed VM control in a Node.js application. -- `agentOS()` returns an ordinary TypeScript Rivet actor definition: VM options - plus normal actor state, actions, events, queues, connection types, and - lifecycle hooks (`onBeforeConnect`). -- agentOS actions/events merge in automatically; their names are reserved. -- The VM is created lazily on the first agentOS action after wake, disposed on - sleep, so a connection can subscribe before `vmBooted`. -- Creation input flows through `client.vm.create("key", { input })` and reaches - `createState(c, input)` and `onCreate(c, input)`. - -## Lifecycle - -- `AgentOs.create()` resolves to a VM handle. There is no actor server, client, - or connection, so your application owns VM identity: there is no actor key, - no `getOrCreate`, and no routing. -- The VM stays alive until you call `dispose()`. Nothing sleeps it for you. -- Action timeouts and automatic sleep/wake are [`agentOS()` actor](/agentos/docs/quickstart) - features. See [Persistence & Sleep](/agentos/docs/persistence) for the actor - behavior the embedded API leaves to you. -- Every `on*` callback is registered on one handle in one process. Nothing is - broadcast to other processes or clients. - -## Configuration reference - -All VM config is a single flat object passed to `AgentOs.create()`. The -[`agentOS()` actor](/agentos/docs/quickstart) accepts the same options and layers -persistence, sleep/wake, and preview URLs on top. - -Durability is the one option you must supply yourself. Actors inject their own -SQLite database; an embedded VM keeps the root filesystem and session catalog -in memory until you pass `database`, and loses both on `dispose()`. +- [host functions](/agentos/docs/host-functions); +- host-directory and other [mount plugins](/agentos/docs/filesystem#mounts); +- [external sandboxes](/agentos/docs/sandboxes); +- local `.aospkg` paths; +- custom schedule drivers and sidecar placement. -See [Filesystem](/agentos/docs/filesystem#mounts) for mount plugins and -[Software](/agentos/docs/software) for the package list. - -## Sidecar process +## Sidecar placement -- Every VM runs inside a **shared sidecar process**, not its own process. -- All VMs default to a single process-global sidecar (the `default` pool); each - extra VM adds only a V8 isolate + its kernel state. -- This keeps per-VM memory in the tens of MB and warm creation in single-digit - ms (see [Performance](/agentos/docs/performance)). -- Automatic for `agentOS()`, `AgentOs.create()`, and Rivet Actors. -- Disposing a VM tears down only that VM; the sidecar is reused for the host - process lifetime. -- Advanced: the embedded API exposes explicit sidecar handles to isolate a - group of VMs in their own process. +VMs share a pooled sidecar process by default. Create a dedicated sidecar with +`AgentOs.createSidecar()` and pass it as `sidecar: { kind: "explicit", handle }` +to isolate a group of VMs or configure process-wide limits. - + diff --git a/vendor/agentos/docs/content/docs/filesystem.mdx b/vendor/agentos/docs/content/docs/filesystem.mdx index 9c3f53bd..f72f7b23 100644 --- a/vendor/agentos/docs/content/docs/filesystem.mdx +++ b/vendor/agentos/docs/content/docs/filesystem.mdx @@ -1,119 +1,109 @@ --- title: "Filesystem" -description: "Read, write, mount, and manage files inside agentOS, all backed by a virtual filesystem isolated from the host disk." -skill: true +description: "Read and write VM files, and mount durable storage, host directories, S3, and other filesystem backends." --- -Each VM has its own filesystem that the agent works in. Guest `fs` calls never touch the host disk, and it persists automatically across sleep/wake with no setup. See [Persistence](/agentos/docs/persistence) for the details. +Every language and shell in the VM sees the same filesystem, so files written +here are immediately visible to Bash, JavaScript, Python, and installed +software. + + + +```ts Hosted @nocheck +import { createAgentOsClient } from "@rivet-dev/agentos"; + +const client = createAgentOsClient({ endpoint: "https://api.rivet.dev" }); +const vm = client.agentOS.getOrCreate(["my-vm"]); + +await vm.v1.filesystem.writeFile({ + path: "/home/agentos/hello.txt", + content: "Hello, world!", +}); +const content = await vm.v1.filesystem.readFile({ + path: "/home/agentos/hello.txt", +}); +console.log(new TextDecoder().decode(content)); + +await vm.v1.filesystem.mkdir({ path: "/home/agentos/src", recursive: false }); +await vm.v1.filesystem.writeFiles({ + entries: [ + { path: "/home/agentos/src/index.ts", content: "console.log('hi');" }, + { + path: "/home/agentos/src/utils.ts", + content: "export const add = (a: number, b: number) => a + b;", + }, + ], +}); + +const entries = await vm.v1.filesystem.readdirRecursive({ + path: "/home/agentos", + exclude: [], +}); +for (const entry of entries) { + console.log(entry.type, entry.path); +} +``` + + + + + +Both APIs also provide batch `readFiles`, `stat`, `readdir`, `readdirEntries`, +`exists`, `move`, `remove`, `export` for a snapshot of the root filesystem, and +`listMounts`. Hosted VMs report byte counts in `stat` and `readdirRecursive` as +`sizeBytes`; the library reports them as `size`. The library can also `mount` +and `unmount` filesystems on a running VM. + +## Root filesystem + +By default, each VM uses an in-memory overlay over the bundled base image. +Writes survive for the VM's lifetime and are discarded when the VM is replaced +or disposed. See [Persistence](/agentos/docs/persistence) to keep files across +VM recreation. ## Mounts -Back a guest path with external storage by adding it to the `mounts` config. Each mount takes a `path` and an optional `readOnly` flag, and the guest only ever sees the mounted subtree, never the wider host. +Mount additional filesystem backends at any guest path. - +Hosted VMs resolve filesystem configuration through a closed registry, such as +`durable` storage. Unknown backends, JavaScript VFS objects, callbacks, and host +paths are rejected. The library accepts native mount plugins, each identified +by an `id` and a `config` object: - +| Plugin | Backend | +|---|---| +| `host_dir` | A directory on the host, confined to the configured path | +| `chunked_s3` | An S3 or S3-compatible bucket | +| `chunked_sqlite` | The VM's SQLite `database` | +| `google_drive` | A Google Drive folder | -Project a real host directory into the filesystem, Docker-style. The guest sees only the mounted subtree, never the wider host filesystem. Path-escape attempts (symlinks, `..`, path aliasing) are confined to the mount root. + - +```ts Hosted @nocheck +import { createAgentOsClient } from "@rivet-dev/agentos"; - +const client = createAgentOsClient({ endpoint: "https://api.rivet.dev" }); - +// Mount durable storage at /data when the VM is first created. +const vm = client.agentOS.getOrCreate(["my-vm"], { + createWithInput: { + config: { + filesystem: { + mounts: [{ path: "/data", backend: { type: "durable" } }], + }, + }, + }, +}); +``` -Mount an S3 bucket with the built-in `s3` plugin. Pass an optional `prefix` to scope storage to a key path within the bucket, useful for sharing one bucket across multiple agents. + -The backend is a block store, not a one-object-per-file mapping: file contents are split into fixed-size chunks (4 MB by default) stored as individual S3 objects, with a separate metadata layer mapping each file to its chunks. This keeps large files, partial reads and writes, and snapshots efficient without rewriting whole objects. + - +Host-backed mounts are confined to their configured root on every operation, +including symlink and `..` resolution. `nodeModulesMount()` is a library +shortcut that exposes a host `node_modules` tree read-only at +`/root/node_modules`. -The `s3` plugin config also accepts `credentials` (`{ accessKeyId, secretAccessKey }`) and a custom `endpoint` for S3-compatible providers. - - - - - -Mount a Google Drive folder with the built-in `google_drive` plugin. - - - - - - - -Use the built-in `memory` plugin for an ephemeral mounted directory in the RivetKit `agentOS()` actor. - - - - - - - -Use `mountFs()` with a serializable, sidecar-owned plugin descriptor. The same descriptor works through Core and RivetKit; the actor persists dynamic descriptors in SQLite and replays them on wake. `mountFs()` resolves only once the mount is visible to guest code, and `unmountFs(path)` removes it. - - - -The actor's durable root is handled separately: the sidecar connects directly to Rivet's actor SQLite UDS, so root filesystem reads and writes never pass through JavaScript. `listMounts()` returns live sanitized metadata without plugin configuration. - - - - - -## File operations - -These operations are primarily what the agent uses inside the VM, and are also available from the client to seed inputs and read results. For large or read-only inputs (a repo, a dataset), a read-only [host mount](#mounts) is faster than copying files in. Programs that need stdin or live output use exec instead (see [Processes & Shell](/agentos/docs/processes)). - -### Read and write - - - -### Batch read and write - - - -### Directories - - - -### File metadata - - - -### Move and delete - - - -## Permissions - -Filesystem access is governed by the VM permission policy. The filesystem scope is granted by default; restrict it by path, for example to deny a sensitive directory: - - - -See [Permissions](/agentos/docs/permissions) for the full configuration. - -## Sandboxes - -For heavier workloads, run a full Linux [external sandbox](/agentos/docs/sandboxes) alongside the VM and mount its filesystem into agentOS. The agent then reads and writes the sandbox's files through the same `fs` APIs while the sandbox handles execution. - -## Default layout - -With no `mounts` configured, every VM boots an Alpine-based root filesystem with the standard POSIX directories: - -- `/home/agentos`: the agent's home directory (`$HOME`) and default working directory (`pwd`) when spawned, where it reads and writes (mounts land under it, e.g. `/home/agentos/data`). -- `/bin`, `/sbin`, `/usr`: installed commands (common POSIX utilities by default, plus any [software](/agentos/docs/software) you add). -- `/etc`, `/lib`, `/opt`, `/root`, `/run`, `/srv`, `/tmp`, `/var`, `/mnt`: standard system paths. - -It is backed by the VM's own filesystem and persisted across sleep/wake. Nothing comes from or touches the host disk. - -## Embedded API - -Filesystem methods and mount descriptors are identical. Configure `database` -when the root filesystem must survive `dispose()`; mounts persist through their -own backends. - - - - - -Read more in the [embedded API quickstart](/agentos/docs/quickstart-embedded). +File transfers are bounded. An operation that exceeds a payload limit fails +with a typed limit error that names the limit. diff --git a/vendor/agentos/docs/content/docs/host-functions.mdx b/vendor/agentos/docs/content/docs/host-functions.mdx index 697e9794..819abe25 100644 --- a/vendor/agentos/docs/content/docs/host-functions.mdx +++ b/vendor/agentos/docs/content/docs/host-functions.mdx @@ -1,20 +1,16 @@ --- title: "Custom Host Functions" -description: "Expose trusted host functions to agentOS coding agents as typed CLI commands, with scoped input, output, and execution behavior." +description: "Expose trusted host functions to guest programs in agentOS VMs as typed CLI commands and JavaScript globals." skill: true --- -Expose your host JavaScript functions (defined with Zod input schemas) to agents as auto-generated CLI commands installed at `/bin/agentos-{name}` inside the VM, injected into the agent's [system prompt](/agentos/docs/system-prompt) and callable inside scripts for code-mode token savings. +Host functions expose JavaScript functions from your process to code running inside the VM. They run as in-process callbacks, so they are available in the library only, not on hosted VMs. Each function is defined with a Zod input schema and becomes an auto-generated CLI command at `/bin/agentos-{name}`, plus an async function that inline JavaScript can call directly. ## Getting started -Pass `agentOS({ hostFunctions })` a record of collections. The keys name everything: the collection key becomes the CLI binary `agentos-{name}` and a guest global, and each function key becomes a subcommand. A function needs only an `inputSchema` and an `execute` handler. `.describe()` on the schema is what the agent reads. +Pass `AgentOs.create({ hostFunctions })` a record of collections. The keys name everything: the collection key becomes the CLI binary `agentos-{name}` and a guest global, and each function key becomes a subcommand. A function needs only an `inputSchema` and an `execute` handler. `.describe()` on the schema becomes the command's help text. - - - - - + Each host function can override its `timeout` in milliseconds. The default is 30 seconds and can be changed with `limits.hostFunctions.defaultTimeoutMs`. @@ -32,11 +28,9 @@ Zod schema fields are converted to CLI flags automatically. Field names are conv Optional fields (via `.optional()`) become optional flags. Required fields are enforced at validation time. Use `.describe()` on Zod fields to generate useful `--help` output, and `.describe()` on the whole schema to describe the function itself. -### What the agent sees - -When host functions are registered, CLI shims are installed at `/bin/agentos-{name}` inside the VM and the function list is injected into the agent's [system prompt](/agentos/docs/system-prompt), so keep each schema's `.describe()` concise to save tokens. +### Calling host functions from the shell -The agent interacts with host functions as shell commands: +Guest programs call host functions as shell commands: ```bash # List all available host-function collections @@ -85,30 +79,21 @@ violation, a thrown error, or a timeout. A collection whose name is already a global, such as `process`, is not defined, and a warning is written to stderr. The `hostFunction` permission scope applies exactly as it does to the commands. -## Host functions and MCP servers - -agentOS supports two ways to give agents access to external functionality: **host functions** and session-scoped **MCP servers**. Both work, but they have different tradeoffs. - -| | Host functions | MCP servers | -|---|---|---| -| **How it works** | Call JavaScript functions on the host directly | Connect to a standard MCP server | -| **Authentication** | None required. Calls go directly to the host process. | Requires custom auth configuration per server | -| **Code mode** | Built in. Host functions are exposed as CLI commands, so agents can call them inside scripts for up to 80% token reduction. | Requires extra work to make code mode work out of the box | -| **Latency** | Near-zero. Bound directly to the host process. | Extra network hop to reach the MCP server | -| **Setup** | Define host functions in your actor code with Zod schemas | Configure any standard MCP server | - -Use host functions when you want to expose your own JavaScript functions to agents. Use MCP servers when you want to connect to existing third-party services. See [Sessions](/agentos/docs/sessions#open-a-session) for MCP server configuration. +See [Bash](/agentos/docs/bash#host-functions), +[Node.js](/agentos/docs/javascript#host-functions), and +[Python](/agentos/docs/python#host-functions) for calling host functions from +each language. ## Security -Host-function calls from the agent invoke your `execute()` functions on the host. Your functions run with full access to the host environment, so you can call databases, APIs, and services directly without proxying credentials into the VM. The agent never sees the credentials, only the function's input/output contract. +Host function calls from guest code invoke your `execute()` functions on the host. Your functions run with full access to the host environment, so you can call databases, APIs, and services directly without proxying credentials into the VM. Guest code never sees the credentials, only the function's input and output contract. -Host functions run on the host with full access to the host environment, so do not expose functions that could compromise the host without appropriate safeguards. +Because handlers run with full host access, do not expose functions that could compromise the host without appropriate safeguards. Use the `hostFunction` [permission](/agentos/docs/permissions) scope to restrict which collections guest code may call. ## Embedded API -Pass the same host-function collections to `AgentOs.create()`. The function contract and -generated VM commands are unchanged. +Host functions are passed to `AgentOs.create()` and their handlers run in the +embedding process. diff --git a/vendor/agentos/docs/content/docs/hosted-api.mdx b/vendor/agentos/docs/content/docs/hosted-api.mdx new file mode 100644 index 00000000..792d1320 --- /dev/null +++ b/vendor/agentos/docs/content/docs/hosted-api.mdx @@ -0,0 +1,257 @@ +--- +title: "Hosted HTTP API" +description: "Reference for the hosted agentOS VM API: creating VMs, authentication, actions, configuration, lifecycle, events, and errors." +--- + +Each hosted VM is one instance of the prebuilt `agentOS` Rivet Actor. You +create it by key, then call its actions over the Rivet gateway. The +`@rivet-dev/agentos` TypeScript client is generated from the same contract and +calls the same actions. See the [hosted quickstart](/agentos/docs/quickstart-hosted) +for a walkthrough. + +## Overview + +| Field | Value | +|---|---| +| **Base URL** | `https://api.rivet.dev`, or your control plane when [self-hosting](/agentos/docs/self-hosting) | +| **Actor name** | `agentOS` | +| **Create a VM** | `PUT /actors?namespace={namespace}` | +| **Call an action** | `POST /gateway/{vm_id}/action/v1.{group}.{action}` | +| **Request body** | `{ "args": [input] }` | +| **Response body** | `{ "output": result }` | +| **Authentication** | `Authorization: Bearer` to create VMs and tokens; `x-rivet-token` for actions | + +## Create a VM + +```bash HTTP +curl -X PUT "https://api.rivet.dev/actors?namespace=$RIVET_NAMESPACE" \ + -H "Authorization: Bearer $RIVET_TOKEN" \ + --json '{ + "name": "agentOS", + "key": "my-vm", + "runner_name_selector": "services", + "crash_policy": "sleep" + }' +# → { "actor": { "actor_id": "…" }, "created": true } +``` + +The returned `actor_id` is the VM ID used in every action path. A second request +with the same key returns the existing VM. + +The TypeScript client does the same with `getOrCreate`, and can pass creation +input on first creation: + +```ts TypeScript @nocheck +import { createAgentOsClient } from "@rivet-dev/agentos"; + +const client = createAgentOsClient({ endpoint: "https://api.rivet.dev" }); + +const vm = client.agentOS.getOrCreate(["my-vm"], { + createWithInput: { config: { environment: { CI: "true" } } }, +}); +const vmId = await vm.resolve(); +``` + +## Authentication + +Keep your admin token on the backend. To let a browser or other untrusted +client call one VM directly, issue a JWT scoped to that VM. See +[JWTs](/docs/jwt). + +```bash HTTP +curl -X POST "https://api.rivet.dev/auth/tokens" \ + -H "Authorization: Bearer $RIVET_TOKEN" \ + --json @- < { + console.log(data.process.pid, data.stream, new TextDecoder().decode(data.data)); +}); +conn.on("process.exit", (data) => { + console.log(data.process.pid, "exited with code", data.status.exitCode); +}); +``` + +## Errors + +| Code | Cause | +| --- | --- | +| `stale_generation` | A process, terminal, context, or stream handle from before a `v1.vm.restart` was used. | +| `expired` | A fetch-stream handle expired. | +| `timeout` | A required package-resolution deadline passed. | +| `not_found` | A closed terminal's replay was evicted from the bounded retention window. | + +Final terminal output and its confirmed exit remain readable after exit within +the bounded closed-terminal retention window. + +## Contract compatibility + +The `@rivet-dev/agentos` package exports `AGENTOS_API_VERSION`, +`AGENTOS_CONTRACT_MAJOR`, `AGENTOS_CONTRACT_HASH`, and `AGENTOS_CAPABILITIES`. +Rust DTOs and the action registry generate the TypeScript surface. + +The contract is currently `agentos-sdk.dev/v1alpha1`, major `1`. The hash covers +the canonical public actions, events, DTOs, and capabilities. Private cron and +maintenance actions are excluded from both the client and the hash. + +## Inspector + +The Rivet Inspector shows a hosted VM's filesystem, processes, terminals, +software, previews, configuration, status, and limit warnings through the same +public contract. It can restart the VM but cannot edit host mounts. + +Published services binaries and the services container include the Inspector +tabs. A source or custom deployment can point the service at another built +copy: + +```sh +AGENTOS_INSPECTOR_TABS_DIR=node_modules/@rivet-dev/agentos/assets/inspector-tabs-app \ + rivet-services start +``` diff --git a/vendor/agentos/docs/content/docs/index.mdx b/vendor/agentos/docs/content/docs/index.mdx index 366fc315..2589e907 100644 --- a/vendor/agentos/docs/content/docs/index.mdx +++ b/vendor/agentos/docs/content/docs/index.mdx @@ -1,20 +1,31 @@ --- title: "Introduction" -description: "Run coding agents in isolated agentOS VMs with controlled filesystems, processes, networking, durable sessions, and Rivet Actor persistence." +description: "Run isolated Linux-compatible VMs with agentOS Core." --- -agentOS runs coding agents in lightweight, isolated VMs inside your process, with -filesystem and process support, network controls, host functions, permissions, -and orchestration built in. +agentOS provides isolated filesystem, process, terminal, language, and networking +APIs in a lightweight VM. - - Boot a VM and run your first coding agent. + + Create durable VMs by ID and control them over RivetKit or HTTP. - - Run agentOS directly inside an existing Node.js application. + + Run a VM inside a trusted Node.js backend. - - Run Pi, Claude Code, Codex, and OpenCode. + + Install immutable `.aospkg` command packages. + +Run agentOS two ways: + +- **Hosted:** the prebuilt `agentOS` Rivet Actor gives each VM a durable ID, + versioned configuration, replayable output, and expiring previews, controlled + from `@rivet-dev/agentos` or plain HTTP. +- **Library:** `@rivet-dev/agentos-core` runs VMs inside your Node.js backend. + Your application owns the VM's lifecycle, persistence, and access to host + resources such as [host functions](/agentos/docs/host-functions) and + [mounts](/agentos/docs/filesystem#mounts). + +See [which one to use](/agentos/docs/quickstart-hosted#which-one-should-i-use). diff --git a/vendor/agentos/docs/content/docs/javascript.mdx b/vendor/agentos/docs/content/docs/javascript.mdx index d0922308..44447721 100644 --- a/vendor/agentos/docs/content/docs/javascript.mdx +++ b/vendor/agentos/docs/content/docs/javascript.mdx @@ -7,7 +7,7 @@ skill: true agentOS runs JavaScript and TypeScript on native V8 inside the VM, backed by a real Node.js surface: `node:fs`, `node:child_process`, sockets, and npm. -Letting an agent write code instead of chaining one tool call per step is called +Running a multi-step operation as code instead of chaining one host call per step is called [Code Mode](https://blog.cloudflare.com/code-mode/). It has a few advantages over driving [Bash](/agentos/docs/bash): @@ -20,7 +20,21 @@ driving [Bash](/agentos/docs/bash): `evaluate()` returns a JSON-serializable value. - + + +```ts Hosted @nocheck +import { createAgentOsClient } from "@rivet-dev/agentos"; + +const client = createAgentOsClient({ endpoint: "https://api.rivet.dev" }); +const vm = client.agentOS.getOrCreate(["my-vm"]); + +const sum = await vm.v1.javascript.evaluate({ expression: "1 + 2" }); +console.log(sum.value); // 3 +``` + + + + Returning `undefined`, a function, a symbol, or a circular value fails with `evaluation_serialization_failed` rather than silently losing the value. @@ -29,27 +43,43 @@ Returning `undefined`, a function, a symbol, or a circular value fails with `execute()` runs source and captures its output instead of returning a value. - + + +```ts Hosted @nocheck +import { createAgentOsClient } from "@rivet-dev/agentos"; + +const client = createAgentOsClient({ endpoint: "https://api.rivet.dev" }); +const vm = client.agentOS.getOrCreate(["my-vm"]); -Executions are ephemeral, so capture stdio only when you want it — `"stderr"` for +const result = await vm.v1.javascript.execute({ + source: `console.log("hello from agentOS")`, +}); +console.log(result); +``` + + + + + +Executions are ephemeral, so capture stdio only when you want it: `"stderr"` for diagnostics, `"all"` for both streams. `onStdout`/`onStderr` stream live and work independently of capture. ## Pass data into code -`inputs` hands host values to the guest as real objects, so data never gets +In the library, `inputs` hands host values to the guest as real objects, so data never gets interpolated into source. - + ## Keep state between calls Pass a `contextId` to keep one V8 isolate and its global state alive across calls. - + -A context runs one operation at a time — reusing a busy `contextId` fails +A context runs one operation at a time, so reusing a busy `contextId` fails immediately. Files, npm, Bash, and type checks may pass the same id, but they run in fresh processes and never touch retained memory. @@ -63,19 +93,50 @@ Create the context explicitly before use; an unknown id fails instead of silentl starting fresh state. A context pins to the first inline language that used it, though JavaScript and TypeScript intentionally share one isolate. -Contexts live for the VM lifetime. They do not survive actor sleep/wake, because -the VM is disposed; create them lazily on the first stateful use after wake. +Contexts live until the VM is disposed. They are in-memory state, so they do +not survive a library VM recreated from the same `database`, or a hosted VM's +sleep and wake. Create them lazily on first use. ## Type check before running -Executing TypeScript transpiles it without a semantic check, so validate the -agent's generated code explicitly. +Executing TypeScript transpiles it without a semantic check, so validate +generated code explicitly. + + + +```ts Hosted @nocheck +import { createAgentOsClient } from "@rivet-dev/agentos"; + +const client = createAgentOsClient({ endpoint: "https://api.rivet.dev" }); +const vm = client.agentOS.getOrCreate(["my-vm"]); + +// Type checking validates generated code before it executes. +const checked = await vm.v1.typescript.check({ + source: `const total: number = "not a number";`, +}); +console.log(checked); +``` - + + + ## Install npm packages - + + +```ts Hosted @nocheck +import { createAgentOsClient } from "@rivet-dev/agentos"; + +const client = createAgentOsClient({ endpoint: "https://api.rivet.dev" }); +const vm = client.agentOS.getOrCreate(["my-vm"]); + +await vm.v1.javascript.npm.install({}); +``` + + + + Installs modify the VM-wide filesystem, so a package installed once is importable by every later execution in that VM, in any language. Only one npm/Python @@ -83,42 +144,68 @@ mutation runs at a time per VM; a concurrent install fails with `execution_busy` ## Background processes and web servers -`spawn` starts a long-lived process and returns a `pid`. From there you get +`spawn` starts a long-lived process and returns a handle. From there you get stdin, output, signals, and waiting. - + + +```ts Hosted @nocheck +import { createAgentOsClient } from "@rivet-dev/agentos"; + +const client = createAgentOsClient({ endpoint: "https://api.rivet.dev" }); +const vm = client.agentOS.getOrCreate(["my-vm"]); + +const server = await vm.v1.javascript.spawn({ + source: ` + import http from "node:http"; + http.createServer((req, res) => res.end("ok")).listen(3000, "127.0.0.1"); + await new Promise(() => {}); + `, +}); + +// The listener stays inside the VM. No host port is exposed. +const response = await vm.v1.network.fetch({ + request: { port: 3000, path: "/health" }, +}); +console.log(response.status); // 200 + +await vm.v1.process.signal({ process: server, signal: "SIGTERM" }); +``` + + + + Spawned processes always start with fresh state, so they take no `contextId`. ## A full Linux environment underneath There is a real Linux environment behind all of this, shared by every language. -Files and installed packages are immediately visible to Bash, Python, agents, and -other executions. +Files and installed packages are immediately visible to Bash, Python, and other +executions. - + See [Filesystem](/agentos/docs/filesystem), [Processes & Shells](/agentos/docs/processes), and -[Networking & Previews](/agentos/docs/networking). +[Networking](/agentos/docs/networking). ## Host functions -Guest code invokes [host functions](/agentos/docs/host-functions) as ordinary typed commands, so host -credentials stay outside the VM. +Guest JavaScript calls [host functions](/agentos/docs/host-functions) as async globals, so host +credentials stay outside the VM. Host functions are library-only. - + ## Permissions, limits, and timeouts Every operation inherits the VM [permission policy](/agentos/docs/permissions) and [resource limits](/agentos/docs/resource-limits). - + ## Embedded API -The examples above already use `AgentOs.create()`. Contexts remain available -until the host calls `dispose()`; there is no actor sleep cycle to recreate them -after. +The library examples use `AgentOs.create()`. Contexts remain available until +the host calls `dispose()`. Read more in the [embedded API quickstart](/agentos/docs/quickstart-embedded). diff --git a/vendor/agentos/docs/content/docs/limitations.mdx b/vendor/agentos/docs/content/docs/limitations.mdx index abcd8e2b..656b3395 100644 --- a/vendor/agentos/docs/content/docs/limitations.mdx +++ b/vendor/agentos/docs/content/docs/limitations.mdx @@ -4,11 +4,14 @@ description: "Understand current agentOS VM limitations, unsupported features, a skill: true --- -agentOS is a Linux environment with a POSIX-compliant virtual kernel. It handles most agent workloads (coding, scripting, file I/O, networking) with near-zero overhead. +agentOS is a Linux environment with a POSIX-compatible virtual kernel. It +handles scripting, file I/O, networking, and language execution with low +overhead. ## Sandbox mounting -When a workload needs a full Linux OS, agents can escalate to a full sandbox on demand without changing code. The [external sandbox](/agentos/docs/sandboxes) extension mounts the sandbox as a filesystem and lets you execute commands on it, like mounting a hard drive on your own machine. Files written in the VM are available in the sandbox and vice versa. +When a workload needs a full Linux OS, mount an +[external sandbox](/agentos/docs/sandboxes) into the VM. See [agentOS vs Sandbox](/agentos/docs/versus-sandbox) for a detailed comparison. @@ -16,7 +19,7 @@ See [agentOS vs Sandbox](/agentos/docs/versus-sandbox) for a detailed comparison ### Software registry -agentOS uses its own [software registry](/agentos/registry/) of popular tools cross-compiled for the runtime. You cannot download and install arbitrary binaries (for example via `curl` or `apt`), and standard Linux package managers (`apt`, `yum`) are not available since agentOS runs a streamlined Linux environment rather than a full distribution. Native binaries that are not yet available in the registry (such as Go, Rust, or C++ toolchains) require a full [external sandbox](/agentos/docs/sandboxes/). +agentOS uses its own [software registry](/agentos/docs/registry) of popular tools cross-compiled for the runtime. You cannot download and install arbitrary binaries (for example via `curl` or `apt`), and standard Linux package managers (`apt`, `yum`) are not available since agentOS runs a streamlined Linux environment rather than a full distribution. Native binaries that are not yet available in the registry (such as Go, Rust, or C++ toolchains) require a full [external sandbox](/agentos/docs/sandboxes). See [Software](/agentos/docs/software) for how to install and configure available packages. diff --git a/vendor/agentos/docs/content/docs/models-and-credentials.mdx b/vendor/agentos/docs/content/docs/models-and-credentials.mdx deleted file mode 100644 index 508a3d26..00000000 --- a/vendor/agentos/docs/content/docs/models-and-credentials.mdx +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: "Models & Credentials" -description: "Choose coding-agent models, pass provider credentials securely to agentOS sessions, and control which secrets are available to each adapter." -skill: true ---- - -- Choose the model through your **agent adapter**. -- Pass provider credentials from trusted server code. -- Credentials are injected at session creation. -- The VM does **not** inherit the host `process.env` — keys must be passed - explicitly. - -## Passing API keys - -Pass LLM provider keys via the `env` option on `openSession`. - - - -## Per-tenant credentials - -- Look up the tenant's key on the server, inject via session `env`. -- Keys stay on the server and never reach the client, and one tenant's key - never reaches another. - -Declare the agent software on the server: - - - -Resolve each tenant's key and pass it at session creation: - - - -## Models - -- Model selection belongs to the configured agent adapter. -- AgentOS forwards the session environment and preserves the agent's native - model behavior — no second model-selection layer. -- See your [agent](/agentos/docs/agents/pi) page for supported models and providers. - -## Embedded API - -Pass provider credentials through `env` on `vm.sessions.open()`. The host owns -the mapping between callers and VM handles. - - - -Read more in the [embedded API quickstart](/agentos/docs/quickstart-embedded). diff --git a/vendor/agentos/docs/content/docs/multiplayer.mdx b/vendor/agentos/docs/content/docs/multiplayer.mdx deleted file mode 100644 index 28511b62..00000000 --- a/vendor/agentos/docs/content/docs/multiplayer.mdx +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: "Multiplayer" -description: "Connect multiple clients to one agentOS actor for collaborative coding-agent sessions with shared transcripts, state, and realtime updates." -skill: true ---- - -Connect multiple clients to the same agentOS actor so all subscribers receive broadcasted session output, process logs, and shell data, enabling collaborative patterns where one user prompts and others observe. - -## Multiple clients observing a session - -All clients connected to the same actor receive broadcasted events. This enables building collaborative UIs where multiple users watch an agent work. - - - - - - - -## Embedded API - -Multiplayer requires Rivet Actors. An [embedded](/agentos/docs/embedded) VM has no connections and no broadcast: `vm.onSessionEvent()` and the other `on*` callbacks fire only in the process that created the VM. To let several clients watch one agent, either use an actor, or fan those callbacks out over your own application's transport and let it own client identity. - -Read more in the [embedded API quickstart](/agentos/docs/quickstart-embedded). diff --git a/vendor/agentos/docs/content/docs/networking.mdx b/vendor/agentos/docs/content/docs/networking.mdx index 33703e75..5dfa1aaa 100644 --- a/vendor/agentos/docs/content/docs/networking.mdx +++ b/vendor/agentos/docs/content/docs/networking.mdx @@ -1,74 +1,77 @@ --- title: "Networking & Previews" -description: "Proxy HTTP traffic into agentOS VMs, configure network access, and create shareable preview URLs for services started by coding agents." -skill: true +description: "Send HTTP requests to servers running inside an agentOS VM, expose them through expiring previews, and control guest network access." --- -Proxy buffered HTTP requests into VM services with `httpRequest` and create time-limited, actor-only preview URLs (with configurable expiration, revocation, and CORS), all carried over one transport (the kernel socket table) that is loopback-only by default under a three-layer confinement model. - -## Run an HTTP server in the VM - -Guest code runs a normal Node HTTP server: it binds a loopback port inside the VM exactly like any Node process. Write the server file and spawn it. +Servers inside the VM listen on VM-local ports. They are not exposed on the +host network. Send a bounded HTTP request to a VM port and get the buffered +response back. - - - -## Fetch from a VM service +```ts Hosted @nocheck +import { createAgentOsClient } from "@rivet-dev/agentos"; -With the HTTP server running in the VM (above), send requests to it with `httpRequest`, including custom methods, headers, and body. +const client = createAgentOsClient({ endpoint: "https://api.rivet.dev" }); +const vm = client.agentOS.getOrCreate(["my-vm"]); - - - - - - -## Preview URLs - -Preview URLs are port forwarding for VM services: a time-limited, public URL that proxies HTTP to a port inside the VM, for browser or external access (use `httpRequest` for server-to-server). Preview creation is intentionally actor-only through the native `createPreviewUrl` and `expirePreviewUrl` actions; tokens survive sleep/wake and CORS is enabled. See [Security](/agentos/docs/security-model) for details. +// Start a server inside the VM +await vm.v1.filesystem.writeFile({ + path: "/tmp/app.mjs", + content: 'import http from "http"; http.createServer((req, res) => res.end("hello")).listen(3000);', +}); +await vm.v1.process.spawn({ command: "node", args: ["/tmp/app.mjs"] }); -### Create a preview URL +// fetch reaches services running in the VM. +const response = await vm.v1.network.fetch({ + request: { port: 3000, path: "/", method: "GET", headers: {} }, +}); +console.log(response.status); +``` -Token lifetimes are configured under the `preview` key: + - - - -### Revoke a preview URL +For large responses, hosted VMs stream the body with the pull-based +`v1.network.fetchStream.start`, `read`, and `cancel` actions. The library +provides `vm.fetch(port, request)` with standard `Request` and `Response` +objects, and `fetchStreamStart`, `fetchStreamRead`, and `fetchStreamCancel` for +bounded chunks. Either way, the caller owns backpressure. -Mint short-lived preview tokens so access expires automatically; the lifetime is capped by `preview.maxExpiresInSeconds`. +## Previews - - - - +Hosted VMs can expose any port through an expiring preview. A preview is a +signed URL path that proxies HTTP to a port inside the VM until it expires or is +revoked. `config.preview.defaultTtlMs` sets the default lifetime. -## Permissions +```ts Hosted @nocheck +import { createAgentOsClient } from "@rivet-dev/agentos"; -Network access is governed by the VM permission policy. By default the guest cannot reach the network; grant it, or allow only specific destinations: +const client = createAgentOsClient({ endpoint: "https://api.rivet.dev" }); +const vm = client.agentOS.getOrCreate(["my-vm"]); -```ts -const vm = agentOS({ - permissions: { - network: { - default: "deny", - rules: [{ mode: "allow", operations: ["*"], patterns: ["dns://api.example.com", "tcp://api.example.com:*"] }], - }, - }, -}); -``` +await vm.v1.process.spawn({ command: "node", args: ["/home/agentos/app.js"] }); -See [Permissions](/agentos/docs/permissions) for the full configuration. +// Create a preview URL for port 3000, valid for 1 hour +const preview = await vm.v1.network.preview.create({ + port: 3000, + ttlMs: 60 * 60 * 1_000, +}); +console.log(preview.path, new Date(Number(preview.expiresAtMs))); -## Embedded API +// Revoke it early +await vm.v1.network.preview.expire({ token: preview.token }); +``` -Use `httpRequest()` directly on the VM handle. Preview URLs remain actor-only; -an embedded host must proxy and authenticate browser traffic itself. +The library does not create public URLs. To expose a library VM's server to +browsers, route requests through your application and forward them with +`httpRequest` or `fetch`. - +## Guest network access -Read more in the [embedded API quickstart](/agentos/docs/quickstart-embedded). +Guest listeners and loopback traffic stay inside the VM. Outbound access is +limited to the sidecar's default allowlist unless the `network` +[permission](/agentos/docs/permissions) scope allows more. Requests from the +host and previews enter the VM from the host side, so they are subject to +loopback confinement but not to the guest egress policy. diff --git a/vendor/agentos/docs/content/docs/performance.mdx b/vendor/agentos/docs/content/docs/performance.mdx index 6d487dae..2fbb98cd 100644 --- a/vendor/agentos/docs/content/docs/performance.mdx +++ b/vendor/agentos/docs/content/docs/performance.mdx @@ -1,194 +1,65 @@ --- title: "Performance" -description: "Measure and optimize agentOS VM startup latency, memory use, execution cost, throughput, and benchmarks with reproducible methodology." +description: "Measure agentOS VM startup latency, memory use, and execution throughput." skill: true --- -Benchmark figures shown on the agentOS marketing page, computed from the same -data source. Use the methodology below to measure your own workload and -hardware. +Measure the exact workload and hardware used in production. VM startup includes +Core configuration, filesystem bootstrap, software projection, and the first +execution. -## Cold start +## Cold-start phases -Time from requesting an execution to first code running. Measured with the sleep -workload (minimal VM, idle Node.js process). Baseline: **E2B**, fastest -mainstream sandbox as of March 30, 2026. See -[ComputeSDK benchmarks](https://www.computesdk.com/benchmarks/). +Record these phases separately: -| Metric | agentOS | Fastest sandbox (E2B) | -|---|--:|--:| -| Cold start p50 | 4.8 ms | 440 ms | -| Cold start p95 | 5.6 ms | 950 ms | -| Cold start p99 | 6.1 ms | 3,150 ms | +1. sidecar process startup, or reuse of a shared sidecar; +2. software acquisition; +3. Core and filesystem boot; +4. first guest instruction. -## Memory per instance +Software passed at boot must be available before the VM is ready. The sidecar's +content-addressed package cache should make a digest hit visible as a separate +metric from a network download. -Measured via staircase benchmarking: +## Memory per VM -1. **Warmup** — a throwaway VM is created and destroyed to pay one-time costs - (module cache, JIT) amortized away in real deployments. -2. **Baseline** — GC forced twice (`--expose-gc`), then RSS sampled across the - whole process tree via `/proc/[pid]/statm` (captures child V8 isolate - processes `process.memoryUsage().rss` would miss). -3. **Staircase** — add VMs one at a time; after each settles, force GC and - resample. Delta = incremental cost of that VM. -4. **Average** — per-VM cost is the mean of step deltas. -5. **Teardown** — dispose all VMs, record reclaimed RSS. +Use staircase measurement to isolate marginal VM cost: -RSS includes thread stacks and OS-mapped pages beyond the VM, so the reported -figure is an **upper bound**. Baseline: **Daytona**, cheapest mainstream -sandbox as of March 30, 2026 (1 vCPU + 1 GiB). +1. create and destroy one warmup VM; +2. force garbage collection and record the process-tree RSS baseline; +3. add VMs one at a time and sample RSS after each settles; +4. average the step deltas; +5. dispose every VM and record reclaimed RSS. -### Full coding agent +Process-tree RSS matters because execution workers may not be represented by +the embedding Node.js process's `process.memoryUsage()` value. -Pi session with MCP servers and mounted filesystems. +## Repository benchmarks -| Metric | agentOS | Cheapest sandbox (Daytona) | -|---|--:|--:| -| Memory per instance | ~131 MB | ~1024 MB | - -### Simple shell command - -| Metric | agentOS | Cheapest sandbox (Daytona) | -|---|--:|--:| -| Memory per instance | ~22 MB | ~1024 MB | - -## Cost per execution-second - -- Assumes one agent per sandbox (isolation) and 70% host utilization (standard - HPA threshold). -- Formula: `server cost per second / concurrent executions per server`, where - `concurrent = floor(server RAM / agent memory) × 0.7`. -- Baseline: **Daytona** at $0.0504/vCPU-h + $0.0162/GiB-h, 1 vCPU + 1 GiB min. - Source: [daytona.io/pricing](https://www.daytona.io/pricing). - -### Full coding agent - -| Host tier | agentOS | Cheapest sandbox | Difference | -|---|--:|--:|--:| -| AWS ARM | $0.00000058/s | $0.000018/s | 32x cheaper | -| AWS x86 | $0.00000072/s | $0.000018/s | 26x cheaper | -| Hetzner ARM | $0.000000066/s | $0.000018/s | 281x cheaper | -| Hetzner x86 | $0.00000011/s | $0.000018/s | 171x cheaper | - -### Simple shell command - -| Host tier | agentOS | Cheapest sandbox | Difference | -|---|--:|--:|--:| -| AWS ARM | $0.000000073/s | $0.000018/s | 254x cheaper | -| AWS x86 | $0.000000090/s | $0.000018/s | 205x cheaper | -| Hetzner ARM | $0.000000011/s | $0.000018/s | 1738x cheaper | -| Hetzner x86 | $0.000000017/s | $0.000018/s | 1061x cheaper | - -## Evaluating your own cost - -- agentOS runs on hardware you provision, not per-VM-second billing. -- Estimate: instance cost per second ÷ concurrent VMs it holds with realistic - memory + utilization headroom. -- Reusing a VM for sequential work amortizes boot and filesystem setup. -- Small short executions benefit most from dense packing; heavy long-lived work - depends more on hardware choice and avoiding per-sandbox minimums. - -Provider prices, instance prices, and workload memory change. Measure -on your target hardware before quoting a cost ratio. - -## Test environment - -| Component | Details | -|---|---| -| CPU | 12th Gen Intel i7-12700KF, 12 cores / 20 threads @ 3.7 GHz, 25 MB cache | -| RAM | 2× 32 GB DDR4 @ 2400 MT/s | -| Node.js | v24.13.0 | -| OS | Linux 6.1.0 (Debian), x86_64 | - -## Sandbox baselines - -| Comparison | Provider | Why | -|---|---|---| -| Cold start | E2B | Fastest mainstream sandbox on [ComputeSDK](https://www.computesdk.com/benchmarks/) as of March 30, 2026 | -| Memory and cost | Daytona | Cheapest mainstream sandbox as of March 30, 2026 ($0.0504/vCPU-h + $0.0162/GiB-h) | - -Self-hosted tiers: AWS t4g.micro (ARM, $0.0084/h, 1 GiB), AWS t3.micro (x86, -$0.0104/h, 1 GiB), Hetzner CAX11 (ARM, €3.29/mo, 4 GiB), Hetzner CX22 (x86, -€5.39/mo, 4 GiB). On-demand pricing. - -## Reproducing - -Benchmarks live in the -[agent-os repository](https://github.com/rivet-dev/agentos) under -`scripts/benchmarks/`. - -**Prerequisites:** - -- Node.js (see `.nvmrc`) and `pnpm`; `pnpm install`. -- A Rust toolchain (`cargo`) — benchmarks build and run the native release - sidecar. -- An **idle machine** — cold-start tails are sensitive to background CPU/GC - jitter. - -**Run everything** (from repo root): +From the repository root: ```sh ./scripts/benchmarks/run-benchmarks.sh ``` -Builds the TS packages + an **optimized release sidecar**, points the SDK at it -via `AGENT_OS_SIDECAR_BIN`, and writes one JSON per benchmark to -`scripts/benchmarks/results/`: - -| Result file | Feeds marketing input | -|---|---| -| `coldstart-sleep.json` | `COLDSTART_P50/P95/P99_MS` | -| `memory-sleep.json` | `MEMORY_SHELL_MB` (`result.avgPerVmRssBytes / 1024²`) | -| `memory-pi-session.json` | `MEMORY_AGENT_MB` (`result.avgPerVmRssBytes / 1024²`) | - -Copy those into `website/src/data/bench.ts`; every figure recomputes from them. +The benchmark script builds an optimized native binary, points the Core client +at it with `AGENTOS_SIDECAR_BIN`, and writes JSON results under +`scripts/benchmarks/results/`. -**Run a single benchmark** — build first (`pnpm build` and -`cargo build --release -p agent-os-sidecar`), then: +For a focused run, build first and select the minimal sleep/command workload: ```sh -export AGENT_OS_SIDECAR_BIN="$PWD/target/release/agent-os-sidecar" - -# Cold start (sleep workload) -pnpm exec tsx scripts/benchmarks/coldstart.bench.ts --workload=sleep --iterations=2000 - -# Memory — simple shell command -pnpm exec tsx --expose-gc scripts/benchmarks/memory.bench.ts --workload=sleep --count=20 - -# Memory — full coding agent -pnpm exec tsx --expose-gc scripts/benchmarks/memory.bench.ts --workload=pi-session --count=10 +pnpm build +cargo build --release -p agentos-native-sidecar +export AGENTOS_SIDECAR_BIN="$PWD/target/release/agentos-native-sidecar" + +pnpm exec tsx scripts/benchmarks/coldstart.bench.ts \ + --workload=sleep --iterations=2000 +pnpm exec tsx --expose-gc scripts/benchmarks/memory.bench.ts \ + --workload=sleep --count=20 ``` -JSON → stdout; human-readable table + progress → stderr. - -**Sample sizes** — percentiles are nearest-rank -(`sorted[ceil(p/100 · n) − 1]`). Too few samples makes the tail meaningless -(at `n = 30`, p99 is literally the single slowest run): - -| Statistic | Minimum iterations | -|---|--:| -| p50 (median) | ~30 | -| p95 | ~200 | -| p99 | ~1,000 | - -- `run-benchmarks.sh` uses `--iterations=2000` for cold start so p95/p99 are - trustworthy. -- Memory per VM is a low-variance mean of step deltas, so `--count=20` (shell) / - `--count=10` (agent) suffices. - -> The `pi-session` memory workload needs a working in-VM agent runtime. Where -> unavailable it fails its process check instead of reporting a number. - -**Methodology:** - -- Each benchmark **creates the sidecar once** (`AgentOs.createSidecar()`) and - leases all VMs from it — VMs are incremental tenants of one shared process, so - figures measure the marginal cost of a VM, not a fresh process. - (`AgentOs.create()` with no `sidecar` option already uses the shared - `default`-pool sidecar — the default everywhere, including RivetKit actors.) -- Before any measured iteration, a **cold run** (throwaway VM, created, started, - snapshotted for cold start) pays one-time spawn + bootstrap, so numbers - reflect warm steady-state per-VM cost. -- The release sidecar is required — a debug build is several times slower and - inflates numbers. +Use a release build and an otherwise idle machine. Percentiles require enough +samples: roughly 30 for p50, 200 for p95, and 1,000 for p99. Keep the raw JSON +with any published comparison so changes in hardware, package cache state, and +workload remain auditable. diff --git a/vendor/agentos/docs/content/docs/permissions.mdx b/vendor/agentos/docs/content/docs/permissions.mdx index d9b5163f..23d22ec3 100644 --- a/vendor/agentos/docs/content/docs/permissions.mdx +++ b/vendor/agentos/docs/content/docs/permissions.mdx @@ -1,124 +1,25 @@ --- title: "Permissions" -description: "Define scoped agentOS kernel permissions that authorize guest filesystem, process, and network operations for each VM and session." -skill: true +description: "Constrain untrusted guest filesystem, process, network, environment, and host function access." --- -The sandbox permission policy is the kernel-level enforcement layer. Every guest syscall the agent's sandboxed code makes is checked against a per-scope policy before any host resource is touched. +Pass a permission tree when creating the VM. The trusted sidecar enforces it +for every guest operation. Hosted VMs take the same serializable tree in their +creation config or a later complete `v1.config.set` replacement. -- **Six scopes**, configured independently: `fs`, `network`, `childProcess`, `process`, `env`, `hostFunction`. -- **Each scope** is a mode (`"allow"` or `"deny"`), or a rule set. -- **A denied operation** is rejected with `EACCES` before any host resource is touched. -- **Merged over a secure default**, so partial policies work. + -For the higher-level agent tool-approval layer (human-in-the-loop, auto-approve), see [Approvals](/agentos/docs/approvals). +The tree has one scope per capability: `fs`, `network`, `childProcess`, +`process`, `env`, and `hostFunction`. A scope can be `"allow"`, `"deny"`, or a +rule set with a `default` mode and `rules` that match operations and target +patterns. -## Defaults and merge semantics +Your policy is merged over the default, so an omitted scope keeps its default. +By default the guest behaves like a sandboxed machine: its virtual filesystem, +processes, environment, listeners, and loopback networking work, and outbound +network access is limited to the sidecar's default allowlist. Library host +functions are governed by the `hostFunction` scope. -The sandbox is deny-by-default for outward-facing capabilities. When you pass no policy, this baseline applies: +See the [Security Model](/agentos/docs/security-model) for the trust boundary +these policies enforce. -```ts -{ - fs: "allow", // virtualized in-memory filesystem only - childProcess: "allow", - process: "allow", - env: "allow", - hostFunction: "allow", - network: { // VM-local listeners and loopback only - default: "deny", - rules: [ - { mode: "allow", operations: ["listen"], patterns: ["tcp://**", "unix:**"] }, - { - mode: "allow", - operations: ["http"], - patterns: ["tcp://127.0.0.1:*", "tcp://localhost:*", "tcp://::1:*", "unix:**"], - }, - ], - }, -} -``` - -- `fs`/`childProcess`/`process`/`env` are allowed because they are fully virtualized (the guest sees only the VM, never the host) and are required to run a program at all. `hostFunction` is allowed so the host functions you register can be called. -- Guest listeners and loopback connections work because they stay inside the VM. External DNS and network connections are denied until you opt in; model providers have no special exception. -- The sidecar owns this baseline, so the TypeScript and Rust clients behave identically. -- Your policy is merged **over** this baseline. Omitted scopes keep their default; they are **not** denied. So `{ network: "allow" }` grants the network while keeping the execution essentials. - - - -## Permission scopes - -| Scope | Controls | Default | -|---|---|---| -| `fs` | Filesystem reads, writes, and metadata operations | `allow` | -| `network` | External connections, DNS, VM-local connections, and `listen` | VM-local only | -| `childProcess` | Spawning child processes | `allow` | -| `process` | Process-control operations | `allow` | -| `env` | Environment variable access | `allow` | -| `hostFunction` | Invoking host functions registered with the runtime | `deny`* | - -\* The `hostFunction` scope is auto-granted to `allow` when you register host functions and set no `hostFunction` policy of your own. Pass a `hostFunction` policy to gate individual host functions. - -## Bind a policy to the VM - -A policy is a plain object keyed by scope. Pass it as `permissions` to `agentOS(...)` and it gates every guest syscall on that VM. - - - -## Grant or deny a whole scope - -The simplest value for a scope is a single mode string. `"allow"` permits every operation in the scope; `"deny"` rejects every one with `EACCES`. Omitted scopes keep their secure default, so you only list what you want to change. - -```ts -const permissions = { - network: "allow", // turn on network egress - fs: "deny", // turn off all filesystem access -}; -``` - -There is no typed `"ask"` mode. Interactive, human-in-the-loop approval lives in the higher-level [Approvals](/agentos/docs/approvals) layer, not the kernel policy. To block at the kernel level, use `"deny"`. - -## Allow only specific filesystem paths - -For finer control, a scope can be a rule set instead of a bare mode: a `default` mode plus an ordered list of `rules`. The `fs` scope matches by `paths` (filesystem globs). Each rule names its `operations` (`read`, `write`, `stat`, `readdir`, `create_dir`, `rm`, `rename`, `symlink`, `readlink`, `chmod`, `truncate`, `mount_sensitive`, or `["*"]` for all). Last matching rule wins; if no rule matches, `default` applies. - - - -To invert it, flip `default` to `"deny"` and allow just one subtree: - - - -## Allow only specific network hosts - -Every non-`fs` scope matches by `patterns` instead of `paths`. For `network`, a pattern matches a resource, not a bare hostname: `dns://` for name resolution and `tcp://:` for the connection. Allowing a host needs both, and `*` matches any port. The operations are `fetch`, `http`, `dns`, and `listen`. - -A bare hostname such as `api.example.com` matches nothing, so the host stays denied. - - - -## Allow only specific host functions - -Host functions registered with the runtime are gated by the `hostFunction` scope and matched by name via `patterns`. Use `["invoke"]` for `operations`. - - - -The `childProcess`, `process`, and `env` scopes work the same way: `childProcess` patterns match the command (`operations: ["spawn"]`), `env` patterns match the variable name (`operations: ["read", "write"]`), and `process` is matched by pattern with `operations: ["*"]`. Setting `childProcess: "deny"` blocks subprocesses created by guest code; it does not block the trusted runtime from starting the VM's requested root program. - -## Combine policies and see denials - -Each policy above sets one scope, so you can spread several into one `permissions` object and bind them together. - - - -When a scope or matching rule denies an operation, the kernel rejects it with `EACCES` before any host resource is touched. For example, with `network: "deny"`, an outbound `fetch()` inside the guest throws: - -``` -EACCES: permission denied, tcp://example.com:80: blocked by network.http policy -``` - -## Embedded API - -Pass the same permission policy to `AgentOs.create()`. - - - -Read more in the [embedded API quickstart](/agentos/docs/quickstart-embedded). diff --git a/vendor/agentos/docs/content/docs/persistence.mdx b/vendor/agentos/docs/content/docs/persistence.mdx index 4d16c55a..765fe63a 100644 --- a/vendor/agentos/docs/content/docs/persistence.mdx +++ b/vendor/agentos/docs/content/docs/persistence.mdx @@ -1,84 +1,57 @@ --- title: "Persistence & Sleep" -description: "Understand how agentOS persists VM files, durable session catalogs, and completed history across actor sleep, wake, restart, and worker movement." -skill: true +description: "Persist an agentOS VM's filesystem in SQLite so files survive VM recreation." --- -agentOS persists the `/home/agentos` filesystem, durable session catalog, and completed session history across actor sleep. A later client call wakes a fresh VM. Adapter processes, running commands, shells, live subscriptions, and in-progress ACP deltas do not survive VM shutdown. +By default, a VM's root filesystem is an in-memory overlay over the bundled +base image. Its files are discarded when the VM is replaced or disposed. -## What persists across sleep +To keep files, give a hosted VM a `durable` root in its config. In the library, +give the VM a SQLite `database` and store its root filesystem there with the +`chunked_sqlite` plugin; a new VM created with the same options sees the same +files. -| Data | Storage | Persists? | -|------|---------|-----------| -| Files in `/home/agentos` | Actor SQLite over UDS | Yes | -| Preview URL tokens | Actor SQLite | Yes | -| Session catalog and configuration | Actor SQLite over UDS | Yes | -| Completed ACP session history | Actor SQLite over UDS | Yes | -| Live ACP adapter process | VM memory | No; restored lazily | -| In-progress message deltas | Live event stream | No | -| Cron job definitions | VM memory | No | -| Running processes | VM kernel | No | -| Active shells | VM kernel | No | -| In-memory mounts | VM memory | No | - -The native sidecar reads and writes filesystem chunks directly through the actor's authenticated SQLite Unix socket. File contents do not pass through the TypeScript or JavaScript actor layer. VM creation supplies one SQLite descriptor, which the sidecar resolves once and shares with filesystem metadata, filesystem blocks, and core session persistence; plugins do not open additional UDS or file connections. - -## Sleep and active turns + -An active prompt turn uses RivetKit's keep-awake scope through the terminal SQLite commit. An idle durable session does not keep the actor awake. +```ts Hosted @nocheck +import { createAgentOsClient } from "@rivet-dev/agentos"; -```text -Actor becomes idle -> idle timeout -> actor sleeps and the VM shuts down +const client = createAgentOsClient({ endpoint: "https://api.rivet.dev" }); -listSessions/readHistory -> actor wakes -> VM boots -> SQLite is read without starting an adapter +const vm = client.agentOS.getOrCreate(["my-vm"], { + createWithInput: { + config: { filesystem: { root: { type: "durable" } } }, + }, +}); -prompt -> actor wakes -> VM boots -> adapter is restored lazily -> turn runs +await vm.v1.filesystem.writeFile({ + path: "/home/agentos/result.txt", + content: "persistent", +}); ``` -RivetKit's default idle sleep timeout is 30 seconds. agentOS sets the graceful shutdown budget to 15 minutes and the action timeout to the largest Node timer-safe delay (2,147,483,647 ms, about 24.8 days), so a normal human permission review is not cut off by the previous 15-minute bound. These can be changed through the actor's `options` configuration. - -## Sleep vs destroy - -| | Sleep | Destroy | -|-|-------|---------| -| Filesystem | Preserved | Deleted | -| Preview tokens | Preserved | Deleted | -| Session catalog and completed history | Preserved | Deleted | -| Adapter process, live deltas, and subscriptions | Lost; restored or recreated as needed | Lost | -| Processes and shells | Lost | Lost | - -## VM lifecycle events - -Use native RivetKit subscriptions, `connection.on("vmBooted", ...)` and `connection.on("vmShutdown", ...)`, to observe actor-owned VM lifecycle changes. These are hosting events and are intentionally absent from Core. + - - - -## Reading durable state after sleep - -When the actor wakes, a fresh VM is created over the same actor SQLite database. Files under `/home/agentos`, the session catalog, and completed history remain available. `listSessions()`, `getSession()`, and `readHistory()` read that stored state without starting an ACP adapter. Prompting an existing session ID restores its adapter lazily, preferring native ACP `session/load` when supported and falling back to a new adapter session with bounded durable history context when necessary. - -Live subscriptions resume only from new events. Ephemeral message deltas that had not completed before shutdown are not reconstructed. - - - -## SQLite tables - -`agentos_fs_metadata_heads` and `agentos_fs_metadata_chunks` store the chunked inode and directory metadata for each filesystem namespace. `agentos_fs_blocks` stores content-addressed file chunks. - -`agentos_core_sessions` stores durable session metadata and cached ACP negotiation state. `agentos_core_events` stores exact native ACP payloads plus a compact scalar AgentOS envelope. `agentos_core_prompts`, `agentos_core_permission_records`, and `agentos_core_permission_outcomes` store bounded prompt, idempotency, and permission bookkeeping. The sidecar treats SQLite as the source of truth; it does not depend on adapter-owned history for listing or reading sessions. +In the library, `database` on its own stores Core and filesystem metadata, but +does not make the default in-memory root durable. A SQLite-backed root starts +without the bundled base image's files. -The filesystem, core, and TypeScript actor independently own `agentos_fs_schema_version`, `agentos_core_schema_version`, and `agentos_actor_schema_version`. There is no shared schema-version table or global migration sequence. `agentos_actor_preview_tokens`, `agentos_actor_dynamic_mounts`, and `agentos_actor_linked_software` are actor-owned hosting metadata. +Persisted filesystems survive VM recreation. Running processes, terminals, +language contexts, open streams, and live subscriptions do not. -This per-VM database is trusted plaintext storage. Session environment values, MCP credentials, prompts, messages, and tool or permission payloads may be stored without encryption or redaction so they can survive sleep. Protect database and backup access accordingly. See [Sessions & Persistence](/agentos/docs/architecture/sessions-persistence/) for exact event storage and retention bounds. +## Sleep -## Embedded API +A hosted VM sleeps when idle unless a process is running, and reports +`vm.shutdown` with reason `"sleep"`. The VM starts lazily on the first action +after wake. Durable files, configuration, and cron jobs survive sleep. See +[actor lifecycle](/actors/docs/lifecycle). -Configure a SQLite database, then recreate the VM with the same configuration. -Processes, contexts, subscriptions, and cron jobs remain VM-local. +Library durable state uses `agentos_core_*` tables and filesystem storage uses +`agentos_fs_*`. Each owner has an independent schema version and migration +transaction. - +In the library, the embedding application owns VM identity and decides when to +recreate or dispose the VM. -Read more in the [embedded API quickstart](/agentos/docs/quickstart-embedded). diff --git a/vendor/agentos/docs/content/docs/processes.mdx b/vendor/agentos/docs/content/docs/processes.mdx index 278a2642..838d091f 100644 --- a/vendor/agentos/docs/content/docs/processes.mdx +++ b/vendor/agentos/docs/content/docs/processes.mdx @@ -1,60 +1,140 @@ --- -title: "Processes & Shell" -description: "Run commands, start long-lived processes, and open interactive shells inside agentOS VMs with controlled environment and lifecycle management." -skill: true +title: "Processes & Shells" +description: "Execute commands, manage long-running processes, replay their output, and open interactive shells." --- -Run commands with one-shot `exec`, spawn long-running processes with streaming stdout/stderr and stdin, manage their lifecycle (stop, kill, wait, inspect), open interactive PTY-backed shells, and inspect the process tree across all VM runtimes. +Every guest process is an entry in the VM's kernel process table, never a host +process. -## One-shot execution - -Use `exec` to run a command and wait for completion. Returns stdout, stderr, and exit code. +| | Hosted | Library | +|---|---|---| +| Run to completion with an argument array | `v1.process.run({ command, args })` | `process.execFile(file, args)` | +| Run a shell command line | `v1.process.run({ command: "sh", args: ["-c", line] })` | `process.exec(line)` | +| Start a long-running process | `v1.process.spawn({ command, args })` returns `{ generation, pid }` | `process.spawn(command, args)` returns `{ pid }` | - - + +```ts Hosted @nocheck +import { createAgentOsClient } from "@rivet-dev/agentos"; + +const client = createAgentOsClient({ endpoint: "https://api.rivet.dev" }); +const vm = client.agentOS.getOrCreate(["my-vm"]); + +// One-shot execution +const result = await vm.v1.process.run({ + command: "ls", + args: ["-la", "/home/agentos"], + options: { captureStdio: true }, +}); +console.log(result.stdout); + +// Long-running process with live output and exit events. +const conn = vm.connect(); +await conn.ready; +const server = await conn.v1.process.spawn({ + command: "node", + args: ["/tmp/server.mjs"], +}); + +conn.on("process.output", (event) => { + if (event.process.pid !== server.pid) return; + console.log(event.stream, new TextDecoder().decode(event.data)); +}); +conn.on("process.exit", (event) => { + if (event.process.pid !== server.pid) return; + console.log("exited:", event.status.exitCode); +}); + +// Write to stdin +await conn.v1.process.stdin.write({ process: server, data: "some input\n" }); + +// Stop or kill +await conn.v1.process.signal({ process: server, signal: "SIGTERM" }); +``` + + + -## Spawn a long-running process +Process arguments are passed as individual argv entries. An empty string is a +valid argument; it is not dropped or treated as an omitted argument. Empty +commands or working directories are invalid input. -Use `spawn` for processes that run in the background. Call `connect()` and subscribe to native `processOutput` and `processExit` events, filtering their `pid` in application code. +## Manage running processes - - - - +| Operation | Hosted | Library | +|---|---|---| +| Write and close stdin | `v1.process.stdin.write`, `v1.process.stdin.close` | `process.writeStdin`, `process.closeStdin` | +| Send a signal | `v1.process.signal` | `process.signal`, `process.kill` | +| Resize a PTY | `v1.process.pty.resize` | `process.resizePty` | +| Wait for exit | `v1.process.wait` | `process.wait` | +| Inspect | `v1.process.get`, `v1.process.list`, `v1.process.tree` | `process.get`, `process.list`, `process.tree` | -## Write to stdin +Hosted operations take the process handle `{ generation, pid }`; library +operations take the `pid`. A hosted handle from before a `v1.vm.restart` fails +with `stale_generation`. -Send input to a running process. +`get` and `list` report `startedAtMs` as a Unix timestamp in milliseconds. +`tree` includes guest child processes as well as processes launched through the +API, so it can show more than you started. Use the returned handle or `pid` +rather than reconstructing one from a node; guest children that were not +launched through the API have no hosted process handle. - - - - +A process wait returns an exit only after agentOS observes a guest exit. A +rejected launch or lost exit observation rejects the wait instead of inventing +an exit code. An observation failure does not prove the guest has stopped; +inspect the VM or recreate it before assuming it is safe to retry work. -## Process lifecycle +## Output events and replay + +Process output can be replayed after the fact, even after the process has +exited or a live event was missed. Hosted VMs retain output for every spawned +process; in the library, pass `output: { retainEvents: true }` to `spawn`. +Then page through retained output with a sequence cursor. - - - -## Interactive shells +```ts Hosted @nocheck +import { createAgentOsClient } from "@rivet-dev/agentos"; -Open an interactive shell with PTY support. Subscribe to native `shellData`, `shellStderr`, and `shellExit` events, filtering their `shellId` in application code. +const client = createAgentOsClient({ endpoint: "https://api.rivet.dev" }); +const vm = client.agentOS.getOrCreate(["my-vm"]); + +const shell = await vm.v1.process.spawn({ command: "sh", args: [] }); + +await vm.v1.process.stdin.write({ process: shell, data: "echo from the background\n" }); +await vm.v1.process.stdin.close({ process: shell }); +await vm.v1.process.wait({ process: shell }); + +// Later, from any client +const replay = await vm.v1.process.output.read({ + process: shell, + maxEvents: 32, + maxBytes: 64 * 1024, +}); +console.log(replay.events.length, replay.nextCursor); +``` + + - - - -## Embedded API +Pass the last cursor as `after` to read the next page. A replay page reports +`nextCursor`, `hasMore`, and `truncated`. Live events are low-latency hints: +`process.output` and `process.exit` on a hosted connection, or +`vm.onProcessOutput` and `vm.onProcessExit` in the library. Retention is +bounded; see [Resource Limits](/agentos/docs/resource-limits) for the defaults. + +## Interactive shells -Process and terminal methods are identical except for actor-only shell listing -and replay. Embedded output and exit callbacks are already scoped to one VM and -one host process. +Interactive terminals allocate a kernel PTY and start a shell attached to it. - +| Operation | Hosted | Library | +|---|---|---| +| Open | `v1.terminal.open` | `terminal.open`, returns a `shellId` | +| Write input | `v1.terminal.stdin.write` | `terminal.write` | +| Resize | `v1.terminal.pty.resize` | `terminal.resize` | +| Wait and close | `v1.terminal.wait`, `v1.terminal.close` | `terminal.wait`, `terminal.close` | +| Output | `terminal.output` and `terminal.exit` events, `v1.terminal.output.read` replay | `vm.onShellData`, `vm.onShellStderr`, `vm.onShellExit` | -Read more in the [embedded API quickstart](/agentos/docs/quickstart-embedded). +Hosted VMs also list open terminals with `v1.terminal.list`. diff --git a/vendor/agentos/docs/content/docs/python.mdx b/vendor/agentos/docs/content/docs/python.mdx index 4ba5390f..362c56a1 100644 --- a/vendor/agentos/docs/content/docs/python.mdx +++ b/vendor/agentos/docs/content/docs/python.mdx @@ -6,10 +6,10 @@ skill: true --- agentOS runs CPython 3.13 as a first-class VM execution engine. Python shares the -VM filesystem, process tree, networking, permissions, and limits with agents, -Bash, JavaScript, and installed software. +VM filesystem, process tree, networking, permissions, and limits with Bash, +JavaScript, and installed software. -Letting an agent write code instead of chaining one tool call per step is called +Running a multi-step operation as code instead of chaining one host call per step is called [Code Mode](https://blog.cloudflare.com/code-mode/). It has a few advantages over driving [Bash](/agentos/docs/bash): @@ -22,7 +22,21 @@ driving [Bash](/agentos/docs/bash): `evaluate()` returns a JSON-serializable value. - + + +```ts Hosted @nocheck +import { createAgentOsClient } from "@rivet-dev/agentos"; + +const client = createAgentOsClient({ endpoint: "https://api.rivet.dev" }); +const vm = client.agentOS.getOrCreate(["my-vm"]); + +const result = await vm.v1.python.evaluate({ expression: "21 * 2" }); +console.log(result.value); // 42 +``` + + + + A value the JSON encoder can't represent fails with `evaluation_serialization_failed` rather than silently losing the value. @@ -31,81 +45,103 @@ A value the JSON encoder can't represent fails with `execute()` runs source and captures its output instead of returning a value. - + + +```ts Hosted @nocheck +import { createAgentOsClient } from "@rivet-dev/agentos"; -Executions are ephemeral, so capture stdio only when you want it — `"stderr"` for +const client = createAgentOsClient({ endpoint: "https://api.rivet.dev" }); +const vm = client.agentOS.getOrCreate(["my-vm"]); + +const result = await vm.v1.python.execute({ + source: `print("hello from agentOS")`, +}); +console.log(result); +``` + + + + + +Executions are ephemeral, so capture stdio only when you want it: `"stderr"` for diagnostics, `"all"` for both streams. `onStdout`/`onStderr` stream live and work independently of capture. ## Pass data into code -`inputs` hands host values to the guest as real objects, so data never gets +In the library, `inputs` hands host values to the guest as real objects, so data never gets interpolated into source. - + ## Keep state between calls Pass a `contextId` to keep globals, functions, imports, and modules alive in one interpreter. - + Only inline `execute()`/`evaluate()` retain memory. Files, modules, installs, and Bash may pass the same id, but they run fresh. A context runs one operation at a -time — reusing a busy `contextId` fails immediately. +time, so reusing a busy `contextId` fails immediately. Contexts do not survive +a hosted VM's sleep and wake; create them lazily on first use. ## Files, modules, and async - + Awaited work counts against the deadline; unawaited `asyncio` tasks are not promised to survive between operations. ## Install packages - + Installs modify the VM-wide filesystem, so a package installed once is importable by every later execution in that VM, in any language. Only one npm/Python mutation runs at a time per VM; a concurrent install fails with `execution_busy`. +pandas, numpy, python-dateutil, pytz, six, and click are bundled. They import +without an install step and need no network. Other packages download over the +network, so the VM needs a [network grant](/agentos/docs/permissions) for their +host: Pyodide builds of compiled packages such as Pillow come from +`cdn.jsdelivr.net`, and pure-Python wheels come from PyPI. + ## Background processes and web servers -`spawn*` starts a long-lived process and returns a `pid`. From there you get +`spawn*` starts a long-lived process and returns a handle. From there you get stdin, output, signals, and waiting. - + ## A full Linux environment underneath There is a real Linux environment behind all of this, shared by every language. -Files and installed packages are immediately visible to Bash, JavaScript, agents, -and other executions. +Files and installed packages are immediately visible to Bash, JavaScript, and +other executions. - + See [Filesystem](/agentos/docs/filesystem), [Processes & Shells](/agentos/docs/processes), and -[Networking & Previews](/agentos/docs/networking). +[Networking](/agentos/docs/networking). ## Host functions Python calls [host functions](/agentos/docs/host-functions) as normal commands via `subprocess`, so -host credentials stay outside the VM. +host credentials stay outside the VM. Host functions are library-only. - + ## Permissions, limits, and timeouts Every operation inherits the VM [permission policy](/agentos/docs/permissions) and [resource limits](/agentos/docs/resource-limits). - + ## Embedded API -The examples above already use `AgentOs.create()`. Python contexts remain -available until the host calls `dispose()`; there is no actor sleep cycle to -recreate them after. +The library examples use `AgentOs.create()`. Python contexts remain available +until the host calls `dispose()`. Read more in the [embedded API quickstart](/agentos/docs/quickstart-embedded). diff --git a/vendor/agentos/docs/content/docs/quickstart-embedded.mdx b/vendor/agentos/docs/content/docs/quickstart-embedded.mdx index a3635c22..1e24bc8f 100644 --- a/vendor/agentos/docs/content/docs/quickstart-embedded.mdx +++ b/vendor/agentos/docs/content/docs/quickstart-embedded.mdx @@ -1,76 +1,35 @@ --- title: "Quickstart (Embedded)" -description: "Run a coding agent in an embedded agentOS VM from an existing Node.js application." +description: "Run an agentOS VM directly inside a Node.js application." skill: true --- -Use the embedded API when you want to run agentOS directly inside an existing -Node.js application without Rivet Actors. Your application owns VM identity, -persistence, and lifecycle. +`@rivet-dev/agentos-core` runs VMs inside your Node.js process. Your +application owns VM identity, persistence, and lifecycle, and +`AgentOs.create()` returns a VM handle directly. -## Choosing between Actors and embedded - -Use [Rivet Actors](/agentos/docs/quickstart) when you want agentOS to manage -persistence, distributed state, sleep and wake, multiplayer, and orchestration. -Use the embedded API when your application needs direct VM control and will own -those responsibilities itself. - -| | Embedded API | Actor | -|-|---|---| -| Persistence | In-memory unless you configure `database`, plus [mounts](/agentos/docs/filesystem#mounts) | Actor SQLite injected automatically | -| Distributed state | Manage yourself | Built-in | -| Stateful VMs | Complex to run yourself | Built into Rivet | -| Sleep/wake | Manual `dispose()` / `create()` | Automatic | -| Events | Direct in-process callbacks | Broadcast to every connected client | -| Preview URLs | Serve them from your own application | Built-in signed URL server | -| Multiplayer | Fan out from your own application | Multiple clients per actor | -| Orchestration | VM-local [cron](/agentos/docs/cron) while the VM is alive | Workflows, queues, and cron | -| Agent-to-agent | [Host functions](/agentos/docs/agent-to-agent) between VMs you own | Built into [Rivet Actors](/agentos/docs/agent-to-agent) | -| Authentication | Your application's own | [Docs](/agentos/docs/authentication) | - -## Quick Start - - - - - -Install the core VM API and the Pi coding agent: - -```bash -npm install @rivet-dev/agentos-core @agentos-software/pi -``` - - - - +## Install ```bash -export ANTHROPIC_API_KEY=your-api-key +npm install @rivet-dev/agentos-core ``` - - - +## Create a VM - + - - - - -```bash -npx tsx quickstart.ts -``` +The VM remains active until `dispose()` is called. Its filesystem is in memory +by default; see [Persistence](/agentos/docs/persistence) to keep files across VM +recreation. - +## Configuration - +The embedding process is trusted, so it can also give the VM access to host +resources: -`AgentOs.create()` returns a VM handle directly. There is no actor server or -separate client, and the VM stays alive until you call `dispose()`. +- [host functions](/agentos/docs/host-functions) implemented as in-process callbacks; +- host-directory and other [mounts](/agentos/docs/filesystem#mounts); +- local `.aospkg` paths; +- explicit ownership of a shared sidecar process. -See [Embedded VMs](/agentos/docs/embedded) for lifecycle, persistence, -configuration, and the shared sidecar, plus links to each capability page's -`Embedded API` section. Use the [actor quickstart](/agentos/docs/quickstart) when -you want built-in persistence, sleep and wake, multiplayer, preview URLs, and -orchestration. + diff --git a/vendor/agentos/docs/content/docs/quickstart-hosted.mdx b/vendor/agentos/docs/content/docs/quickstart-hosted.mdx new file mode 100644 index 00000000..7b0e19fb --- /dev/null +++ b/vendor/agentos/docs/content/docs/quickstart-hosted.mdx @@ -0,0 +1,330 @@ +--- +title: "Quickstart (Hosted)" +description: "Create durable agentOS VMs by ID and control them from the RivetKit client or plain HTTP." +skill: true +--- + +Hosted agentOS VMs run as the prebuilt `agentOS` Rivet Actor, on Rivet Cloud or +on your own Rivet control plane. Create a VM by key, then control it from the +`@rivet-dev/agentos` client or plain HTTP. To run VMs inside your own Node.js +process instead, see the [library quickstart](/agentos/docs/quickstart). + +## Which one should I use? + +| | [Hosted](/agentos/docs/quickstart-hosted) | [Library](/agentos/docs/quickstart) | +|---|---|---| +| **Runs** | As a durable instance on Rivet Cloud or a [self-hosted](/agentos/docs/self-hosting) Docker image | Embedded inside your process as a library | +| **Lifecycle** | Durable, sleeps when idle unless a process is running; see [actor lifecycle](/actors/docs/lifecycle) | Ephemeral, runs until `dispose()` or process exit | +| **Package** | `@rivet-dev/agentos`, or plain HTTP | `@rivet-dev/agentos-core` | +| **VM identity** | A durable VM you create by key and reach by ID | A handle your process owns until `dispose()` | +| **Configuration** | Stored with the VM and versioned | Passed to `AgentOs.create()` | +| **Clients** | Your backend, or browsers with a scoped JWT | Your backend | +| **Host access** | None | Host functions, host mounts, external sandboxes | +| **Previews** | Expiring preview URLs | None | +| **Best for** | Long-lived VMs shared across clients | Embedding VMs in an existing backend | + +## Create a VM + +### Rivet Cloud + + + + +Sign up at the [Rivet dashboard](https://dashboard.rivet.dev) and create a new project. + + + + +When creating the project, choose agentOS as the product. + + + + +Set `RIVET_NAMESPACE` and `RIVET_TOKEN` from your project, then create a VM by +ID from TypeScript or plain HTTP: + + + +```ts TypeScript @nocheck +// npm install @rivet-dev/agentos +import { createAgentOsClient } from "@rivet-dev/agentos"; + +const client = createAgentOsClient({ endpoint: "https://api.rivet.dev" }); + +const vm = client.agentOS.getOrCreate(["my-vm"]); +``` + +```bash HTTP +curl -X PUT "https://api.rivet.dev/actors?namespace=$RIVET_NAMESPACE" \ + -H "Authorization: Bearer $RIVET_TOKEN" \ + --json '{ + "name": "agentOS", + "key": "my-vm", + "runner_name_selector": "services", + "crash_policy": "sleep" + }' +# → { "actor": { "actor_id": "…" }, "created": true } +``` + + + + + + +### Self-hosting + +See [Self-Hosting (Hosted)](/agentos/docs/self-hosting) to run hosted VMs on your own +infrastructure. + +## Show me the code + +### Run Bash Commands + + + +```ts TypeScript @nocheck +const result = await vm.v1.process.run({ + command: "sh", + args: ["-c", "echo hello && ls /home/agentos"], + options: { captureStdio: true }, +}); + +console.log(result.stdout); +``` + +```bash HTTP +curl "https://api.rivet.dev/gateway/$VM_ID/action/v1.process.run" \ + -H "x-rivet-token: $VM_TOKEN" \ + --json '{"args": [{ + "command": "sh", + "args": ["-c", "echo hello && ls /home/agentos"], + "options": { "captureStdio": true } + }]}' +``` + + + +### Work With the Filesystem + + + +```ts TypeScript @nocheck +await vm.v1.filesystem.writeFile({ + path: "/home/agentos/hello.txt", + content: "Hello, world!", +}); + +const file = await vm.v1.filesystem.readFile({ + path: "/home/agentos/hello.txt", +}); +``` + +```bash HTTP +curl "https://api.rivet.dev/gateway/$VM_ID/action/v1.filesystem.writeFile" \ + -H "x-rivet-token: $VM_TOKEN" \ + --json '{"args": [{ + "path": "/home/agentos/hello.txt", + "content": "Hello, world!" + }]}' + +curl "https://api.rivet.dev/gateway/$VM_ID/action/v1.filesystem.readFile" \ + -H "x-rivet-token: $VM_TOKEN" \ + --json '{"args": [{"path": "/home/agentos/hello.txt"}]}' +``` + + + +### Run a Dev Server & Create Preview URLs + +Start a Node.js server in the VM, then expose its port through a signed URL +that expires on its own, or revoke it early. A running server keeps the VM +awake. + + + +```ts TypeScript @nocheck +await vm.v1.filesystem.writeFile({ + path: "/home/agentos/server.js", + content: `require("node:http") + .createServer((req, res) => res.end("hello")) + .listen(3000);`, +}); + +await vm.v1.process.spawn({ + command: "node", + args: ["/home/agentos/server.js"], +}); + +const preview = await vm.v1.network.preview.create({ + port: 3000, + ttlMs: 60 * 60 * 1_000, +}); + +await vm.v1.network.preview.expire({ token: preview.token }); +``` + +```bash HTTP +curl "https://api.rivet.dev/gateway/$VM_ID/action/v1.filesystem.writeFile" \ + -H "x-rivet-token: $VM_TOKEN" \ + --json '{"args": [{ + "path": "/home/agentos/server.js", + "content": "require(\"node:http\").createServer((req, res) => res.end(\"hello\")).listen(3000);" + }]}' + +curl "https://api.rivet.dev/gateway/$VM_ID/action/v1.process.spawn" \ + -H "x-rivet-token: $VM_TOKEN" \ + --json '{"args": [{"command": "node", "args": ["/home/agentos/server.js"]}]}' + +curl "https://api.rivet.dev/gateway/$VM_ID/action/v1.network.preview.create" \ + -H "x-rivet-token: $VM_TOKEN" \ + --json '{"args": [{"port": 3000, "ttlMs": 3600000}]}' +# → { "output": { "path": "/preview/…/", "token": "…", … } } + +curl "https://api.rivet.dev/gateway/$VM_ID/action/v1.network.preview.expire" \ + -H "x-rivet-token: $VM_TOKEN" \ + --json '{"args": [{"token": "…"}]}' +``` + + + +### Use the Language Runtimes + +Run JavaScript, TypeScript, and Python directly, with npm and pip installs +built in. + + + +```ts TypeScript @nocheck +await vm.v1.javascript.execute({ source: "console.log(1 + 2)" }); +await vm.v1.typescript.execute({ + source: "const n: number = 3; console.log(n)", +}); + +const { value } = await vm.v1.python.evaluate({ + expression: "21 * 2", +}); +``` + +```bash HTTP +curl "https://api.rivet.dev/gateway/$VM_ID/action/v1.javascript.execute" \ + -H "x-rivet-token: $VM_TOKEN" \ + --json '{"args": [{"source": "console.log(1 + 2)"}]}' + +curl "https://api.rivet.dev/gateway/$VM_ID/action/v1.python.evaluate" \ + -H "x-rivet-token: $VM_TOKEN" \ + --json '{"args": [{"expression": "21 * 2"}]}' +``` + + + +### Schedule Cron Jobs + + + +```ts TypeScript @nocheck +await vm.v1.cron.schedule({ + name: "cleanup", + expression: "0 * * * *", + command: "rm", + args: ["-rf", "/tmp/cache"], +}); +``` + +```bash HTTP +curl "https://api.rivet.dev/gateway/$VM_ID/action/v1.cron.schedule" \ + -H "x-rivet-token: $VM_TOKEN" \ + --json '{"args": [{ + "name": "cleanup", + "expression": "0 * * * *", + "command": "rm", + "args": ["-rf", "/tmp/cache"] + }]}' +``` + + + +### Install Software + +Install tools from the [software registry](/agentos/docs/registry/software) +while the VM is running. Packages are verified against their digest before +their commands appear on `/opt/agentos/bin`. + + + +```ts TypeScript @nocheck +// Registry packages are published next to a manifest with each release. +const base = "https://releases.rivet.dev/agent-os/latest/software/"; +const { artifacts } = await (await fetch(`${base}manifest.json`)).json(); +const ripgrep = artifacts.find((artifact) => artifact.name === "ripgrep"); + +const installed = await vm.v1.software.install({ + source: { url: new URL(ripgrep.path, base).href, digest: ripgrep.digest }, +}); +if (installed.config.state === "restart_required") { + await vm.v1.vm.restart({}); +} +``` + +```bash HTTP +curl "https://api.rivet.dev/gateway/$VM_ID/action/v1.software.install" \ + -H "x-rivet-token: $VM_TOKEN" \ + --json '{"args": [{ + "source": { + "url": "https://releases.rivet.dev/agent-os/latest/software/packages/ripgrep/.aospkg", + "digest": "sha256:" + } + }]}' +``` + + + +### Give Clients Direct Access With JWTs + +Keep your admin token on the backend and issue a JWT scoped to one VM. +Browsers and other untrusted clients can then call that VM directly, and +nothing else. + + + +```ts TypeScript @nocheck +// Backend: issue a token for this VM only +const vmId = await vm.resolve(); +const { token } = await vm.issueToken({ + subject: "user-123", + expiresIn: 3600, +}); + +// Client: call the VM directly +const userClient = createAgentOsClient({ + endpoint: "https://api.rivet.dev", + namespace: "my-namespace", + token, +}); +const userVm = userClient.getForId("agentOS", vmId); +``` + +```bash HTTP +curl -X POST "https://api.rivet.dev/auth/tokens" \ + -H "Authorization: Bearer $RIVET_TOKEN" \ + --json @- < + +## Next steps + +- See the [Hosted HTTP API](/agentos/docs/hosted-api) for configuration, + events, errors, and every action. +- Keep files across restarts with [Persistence & Sleep](/agentos/docs/persistence). diff --git a/vendor/agentos/docs/content/docs/quickstart.mdx b/vendor/agentos/docs/content/docs/quickstart.mdx index c54835b0..86c529fc 100644 --- a/vendor/agentos/docs/content/docs/quickstart.mdx +++ b/vendor/agentos/docs/content/docs/quickstart.mdx @@ -1,143 +1,92 @@ --- -title: "Quickstart" -description: "Create an agentOS actor, launch an isolated VM session, run a coding agent, send a prompt, and inspect the durable result." +title: "Quickstart (Library)" +description: "Run agentOS VMs directly inside a Node.js application with @rivet-dev/agentos-core." skill: true --- -import { Hosting } from "@/components/docs/Hosting"; - -import { AGENT_PROMPT } from '@/data/agentPrompt'; - -
-Use this pre-built prompt to get started faster. - -
- -
-Prefer to read code? Clone the example repository. -View on GitHub -
- - - - - - - - - OS - - - - Client - JS · Browser · Backend - - - Server - - - - - - - - - - - - - - - - - - - - - - - OS - = agentOS VM - - - -## Quick Start +Use agentOS as a library to run VMs inside your own Node.js process. To create +durable VMs by ID and control them over HTTP instead, see the +[hosted quickstart](/agentos/docs/quickstart-hosted). - +## Which one should I use? + +| | [Hosted](/agentos/docs/quickstart-hosted) | [Library](/agentos/docs/quickstart) | +|---|---|---| +| **Runs** | As a durable instance on Rivet Cloud or a [self-hosted](/agentos/docs/self-hosting) Docker image | Embedded inside your process as a library | +| **Lifecycle** | Durable, sleeps when idle unless a process is running; see [actor lifecycle](/actors/docs/lifecycle) | Ephemeral, runs until `dispose()` or process exit | +| **Package** | `@rivet-dev/agentos`, or plain HTTP | `@rivet-dev/agentos-core` | +| **VM identity** | A durable VM you create by key and reach by ID | A handle your process owns until `dispose()` | +| **Configuration** | Stored with the VM and versioned | Passed to `AgentOs.create()` | +| **Clients** | Your backend, or browsers with a scoped JWT | Your backend | +| **Host access** | None | Host functions, host mounts, external sandboxes | +| **Previews** | Expiring preview URLs | None | +| **Best for** | Long-lived VMs shared across clients | Embedding VMs in an existing backend | - +## Create a VM -- **@rivet-dev/agentos** — Actor framework with built-in persistence and orchestration -- **@agentos-software/pi** — [Pi](https://github.com/mariozechner/pi-coding-agent) coding agent. [Claude Code](/agentos/docs/agents/claude), [Codex](/agentos/docs/agents/codex), and [OpenCode](/agentos/docs/agents/opencode) install the same way. + + ```bash -npm install @rivet-dev/agentos @agentos-software/pi +npm install @rivet-dev/agentos-core ``` + - + - +The VM runs until `dispose()` is called or your process exits. + - - -The client can be any public frontend or another backend. The same `vm` actor is reachable from a plain Node script, a browser/React app, or a separate server. - - - - - - +## Show me the code - +### Run Bash Commands - + -Start the server, then run the client in a second terminal: +### Work With the Filesystem -```bash -# Terminal 1: start the server -npx tsx server.ts + -# Terminal 2: run the client -npx tsx client.ts -``` +### Run a Dev Server -With the server running, open http://localhost:6420/ui to watch the VM in the actor inspector: the live transcript, the filesystem, and its processes. +Start a Node.js server in the VM, then send it a request from your process. +The listener is not exposed on the host network. - + - +### Use the Language Runtimes -Now that you have a working agent, customize it to fit your needs: +Run JavaScript, TypeScript, and Python directly, with npm and pip installs +built in. -- **[Software](/agentos/docs/software)** — Install software packages inside the VM -- **[Filesystem](/agentos/docs/filesystem)** — Read, write, and manage files inside the VM -- **[Permissions & Resource Limits](/agentos/docs/permissions)** — Gate what the agent can do and cap its resource usage -- **[Host functions](/agentos/docs/host-functions)** expose your JavaScript functions to agents as CLI commands. + - +### Schedule Cron Jobs - + -By default, agentOS runs locally with `npx rivetkit dev` — no infrastructure needed. To run in production, deploy to any of these targets: +### Install Software - +Install tools from the [software registry](/agentos/docs/registry/software) +while the VM is running. Packages are verified against their digest before +their commands appear on `/opt/agentos/bin`. - + - +### Persist Files - -agentOS is in preview and the API is subject to change. If you run into issues, please [report them on GitHub](https://github.com/rivet-dev/rivet/issues) or [join our Discord](https://rivet.dev/discord). - +The filesystem is in memory by default. Store the root filesystem in SQLite to +keep files across VM recreation. -## Embedded API + -The `@rivet-dev/agentos-core` package exports `AgentOs.create()` for embedded VM -control without the actor lifecycle, multiplayer, or orchestration layer. +## Next steps -Read more in the [embedded API quickstart](/agentos/docs/quickstart-embedded). +- Expose your own functions to guest code with + [host functions](/agentos/docs/host-functions). +- Lock the VM down with [Permissions](/agentos/docs/permissions) and + [Resource Limits](/agentos/docs/resource-limits). diff --git a/vendor/agentos/docs/content/docs/resource-limits.mdx b/vendor/agentos/docs/content/docs/resource-limits.mdx index c7f8ec2a..b7eb6b4a 100644 --- a/vendor/agentos/docs/content/docs/resource-limits.mdx +++ b/vendor/agentos/docs/content/docs/resource-limits.mdx @@ -1,135 +1,78 @@ --- title: "Resource Limits" -description: "Cap per-VM resources, JavaScript CPU/wall-clock time, Python execution, and WASM runtime work so guest code can never exhaust the host." -skill: true +description: "Configure bounded VM, process, JavaScript, Python, and WASM resources." --- -Every agentOS VM runs with **per-VM resource and runtime caps**. These caps contain runaway or malicious guest work to its VM and give the host an explicit failure instead of silent data loss. - -- **Secure defaults**: unset fields fall back to built-in defaults that match the runtime's historical constants. Optional execution budgets such as WASM fuel explicitly document when their default has no additional budget. -- **Per-VM**: every VM gets its own budget. Limits are not shared across VMs. -- **Enforced by the sidecar/runtime**: a guest that exceeds a cap fails inside the VM (out-of-memory, `EMFILE`, `EAGAIN`, runtime timeout, etc.) instead of consuming past the configured budget. -- **Operator-raisable**: the operator (the trusted process that creates the VM) may raise any cap for trusted workloads. Guest code can never raise its own caps. - -## Setting limits - -Set caps on the `limits` object in the `agentOS` config. Limits are grouped by subsystem (`resources`, `process`, `jsRuntime`, `python`, `wasm`, and more). Omitted limits keep their secure default. - -V8 executor admission is process-wide rather than per-VM. It is uncapped by -default and does not derive a ceiling from the sidecar's reported CPU count. -Operators can set `runtime.executor.maxActiveVms` when creating a sidecar to -enforce an explicit concurrent-executor ceiling. - - - -## Available caps - -| Limit | Controls | Notes | -|---|---|---| -| `resources.maxProcesses` | Concurrent processes in the VM process table | Caps fork bombs and runaway spawning. New spawns fail with `EAGAIN`. | -| `resources.maxOpenFds` | Open file descriptors | Exhausting the table fails with `EMFILE` / `ENFILE`. | -| `resources.maxSockets` | Open sockets in the socket table | Default is `256`. This includes guest sockets and the sidecar-owned sockets used to send host requests into VM services. Excess socket operations fail instead of consuming more host resources. | -| `resources.maxFilesystemBytes` | Total bytes stored in the virtual filesystem | Bounds VFS storage; writes past the budget fail with a no-space error. | -| `resources.maxInodeCount` | Inodes retained by the virtual filesystem | Default is `16384`; creating another file or directory fails with a no-space error. This is the expected upper bound for filesystem-schema sizing and benchmarks. | -| `resources.maxWasmFuel` | WASM execution budget | Bounds WASM execution work; unset means no explicit fuel budget. | -| `resources.maxWasmMemoryBytes` | WASM linear memory, in bytes | Default is `128 MiB`. | -| `resources.maxWasmStackBytes` | Maximum WASM call-stack size, in bytes | Deep recursion fails with a stack overflow instead of crashing the VM. | -| `resources.maxBlockingReadMs` | AgentOS safety backstop for otherwise-blocking guest operations | Default is `30000`. Socket waits, poll, and contended `F_SETLKW` warn near the limit and fail with `ETIMEDOUT` if it expires; raise it for workloads that intentionally wait longer. Linux has no equivalent global backstop. | -| `process.pendingStdinBytes` | Stdin accepted by the sidecar but not yet written into kernel pipes | Default is `64 MiB` per process and across the VM. Sibling processes share the same aggregate envelope, so this is a tighter bound for multi-process workloads. A non-draining process rejects further writes with an error naming `limits.process.pendingStdinBytes`. | -| `process.pendingEventCount` | Event count at each bounded VM/process delivery-queue stage | Default is `10000`. The crossing event is rejected with an error naming `limits.process.pendingEventCount`; it is never silently dropped. | -| `process.pendingEventBytes` | Retained process-event bytes at each bounded delivery-queue stage | Default is `64 MiB` per process and across all process queues in the VM. Sibling processes share the VM-wide envelope. Large stdout/stderr bursts are rejected with an error naming `limits.process.pendingEventBytes`, independently of event count. | -| `acp.maxSessionsPerVm` | Durable sessions retained in one VM SQLite database | Default is `10000`. Opening another session fails with a typed error naming this field. | -| `acp.maxPromptsPerSession` | Prompt and idempotency records retained for one durable session | Default is `100000`; it must not exceed `acp.maxPromptsPerVm`. | -| `acp.maxPromptsPerVm` | Prompt and idempotency records retained across one VM | Default is `1000000`. | -| `acp.maxPendingPermissionsPerSession` | Actionable ACP permission requests for one session | Default is `1000`; it must not exceed `acp.maxPendingPermissionsPerVm`. | -| `acp.maxPendingPermissionsPerVm` | Actionable ACP permission requests across one VM | Default is `10000`. | -| `acp.maxPermissionOutcomesPerSession` | Terminal ACP permission outcomes retained for one session | Default is `10000`; it must not exceed `acp.maxPermissionOutcomesPerVm`. | -| `acp.maxPermissionOutcomesPerVm` | Terminal ACP permission outcomes retained across one VM | Default is `100000`. Old outcomes are bounded independently from pending requests. | -| `jsRuntime.v8HeapLimitMb` | Guest JavaScript V8 heap, in MiB | Default is `128`. | -| `jsRuntime.cpuTimeLimitMs` | Active JavaScript CPU time | Default is `30000`; `0` disables the CPU watchdog. | -| `jsRuntime.wallClockLimitMs` | JavaScript elapsed wall-clock backstop | Default is `0`, disabled. Use this for finite commands, not long-lived adapters. | -| `jsRuntime.importCacheMaterializeTimeoutMs` | Node import-cache materialization timeout | Default is `30000`. | -| `jsRuntime.syncRpcWaitTimeoutMs` | JavaScript sync host-RPC wait | Unset keeps the engine default, currently `30000`. | -| `python.executionTimeoutMs` | Python execution wall-clock timeout | Default is `300000`. | -| `python.maxOldSpaceMb` | Pyodide runner V8 old-space heap, in MiB | Default is `0`, which keeps the engine default. | -| `wasm.prewarmTimeoutMs` | WASM compile-cache warmup timeout | Default is `30000`. | -| `wasm.runnerHeapLimitMb` | Trusted WASI/WASM runner V8 heap, in MiB | Default is `2048`; this is not guest linear memory. | -| `wasm.runnerCpuTimeLimitMs` | Trusted WASI/WASM runner active-CPU budget | Default is `30000`; `0` disables this budget for trusted configurations. | -| `process.maxSpawnFileActions` | File actions decoded for one `posix_spawn` call | Default is `4096`; excess actions fail with `E2BIG`. | -| `process.maxSpawnFileActionBytes` | Serialized file-action bytes for one `posix_spawn` call | Default is `1 MiB`; excess input fails with `E2BIG`. | - -### Streaming fetch responses - -A VM may have at most `256` host-to-VM streaming HTTP responses open at once. -This is a fixed runtime limit and does not have a `limits` configuration field. -A stream occupies one slot after `fetchStreamStart()` returns and releases it -when `fetchStreamRead()` reports `done: true` or the host calls -`fetchStreamCancel()`. Opening another stream at the limit fails with -`ERR_AGENTOS_VM_FETCH_STREAM_LIMIT`. - -This limit bounds concurrent streams, not the number of requests a warm VM can -serve over its lifetime. Completed and cancelled streams do not accumulate -toward the limit. - -## Behavior at the limit - -- **WASM stack**: deep recursion throws a stack-overflow error in the guest, never a host crash. -- **JavaScript CPU time**: CPU-bound loops terminate with a CPU-budget error once active JS CPU exceeds `jsRuntime.cpuTimeLimitMs`. -- **JavaScript wall time**: awaiting or blocked JS terminates only when you set `jsRuntime.wallClockLimitMs`; the default is disabled for long-lived adapters. -- **Filesystem bytes**: writing past the VFS budget fails with a no-space error to the guest. -- **Counts (fds / processes / sockets)**: hitting a table cap returns the standard POSIX errno appropriate to that cap (`EMFILE`/`ENFILE`, `EAGAIN`, etc.). -- **Durable ACP collections**: session, prompt, pending-permission, and terminal-outcome caps fail atomically with typed errors naming the exact `limits.acp.*` field to raise. Per-session caps are validated not to exceed their corresponding per-VM cap. - -### WASM memory residency calls - -V8 owns the physical backing pages for WASM linear memory, and the runtime -cannot currently pin those pages against host swapping. Nonempty `mlock()` and -valid `mlockall()` requests therefore return `ENOTSUP` rather than falsely -claiming that secrets or other guest memory were pinned. `munlock()` and -`munlockall()` succeed because no guest lock can be established and the memory -is already unlocked. - -Non-destructive `madvise()` access-pattern calls are accepted as best-effort -hints, which Linux is also permitted to ignore. Advice that would discard data -or change fork, core-dump, or host VM mapping policy returns `ENOTSUP` because -the runtime cannot apply it. - -## Sidecar liveness - -Separate from the guest caps above, the host detects a dead or wedged sidecar -process by silence, not by per-request deadlines. The sidecar emits a liveness -heartbeat every 10 seconds from a dedicated thread — so it keeps beating even -mid-way through a long turn — and the host treats 30 seconds with no inbound -frames at all as a dead sidecar: it kills the process and fails in-flight -requests with a typed `SidecarSilenceTimeout` error. - -Because liveness is silence-based, individual requests have no time limit of -their own: an agent turn may legitimately run for many minutes without being -torn down. Neither the heartbeat cadence nor the silence window is -configurable — they are fixed protocol constants. - -## Warnings & observability - -Limits are observable, not just enforced. Live resource gauges and internal -bounded queues are tracked in a central limit registry that: - -- **Warns before the limit is hit.** As usage crosses ~80% of a cap, the runtime - emits a structured warning (once per crossing, re-armed only after it recovers), - so a slow consumer or a runaway guest is visible *before* it fails. -- **Never drops data silently.** Internal queues either apply backpressure or - fail with a typed error naming the exhausted limit and the setting used to - raise it. A rejected event is not popped and forgotten. -- **Surfaces through logs.** The agentOS sidecar logs to stderr (stdout is the wire - protocol); set `AGENTOS_LOG=warn` (the default) to see near-limit warnings - or `AGENTOS_LOG=debug` for live per-limit usage snapshots. - -See [Limits & Observability](/agentos/docs/architecture/limits-and-observability) for the -full architecture. +Pass a `limits` tree in the VM's configuration. The sidecar applies it when the +VM starts. Near-limit pressure is reported as the `vm.limitWarning` event on a +hosted VM, or through `onLimitWarning` in the library. + + + +```ts Hosted @nocheck +import { createAgentOsClient } from "@rivet-dev/agentos"; + +const client = createAgentOsClient({ endpoint: "https://api.rivet.dev" }); +const vm = client.agentOS.getOrCreate(["my-vm"]); + +await vm.v1.config.set({ + config: { + limits: { + tls: { maxBufferedBytes: 2048 }, + execution: { completedTtlMs: 60_000, liveExecutionWarningThreshold: 32 }, + agentosPackages: { maxMounts: 8192 }, + }, + }, +}); + +// Changed limits apply to the next VM generation. +await vm.v1.vm.restart({}); +``` + + + + + +Use `limits.tls.maxBufferedBytes` to bound TLS plaintext buffering. +`limits.execution.completedTtlMs` and `limits.execution.maxCompletedExecutions` +bound retained completed language executions. `limits.execution.liveExecutionWarningThreshold` +sets the live execution count that triggers a warning, not a rejection. +These fields are optional; omission keeps the sidecar default. + +Process output replay is also sidecar-owned. The defaults retain +up to 1,024 events or 1 MiB for each opted-in process, return at most 256 events +or 768 KiB per read, and retain at most 1,024 replay records per VM. Override +them with `limits.process.outputReplayEvents`, `outputReplayBytes`, +`outputReplayPageEvents`, `outputReplayPageBytes`, and `maxOutputReplays`. +Page limits cannot exceed their corresponding retention limits. Omitting a page +bound in `process.readOutput` uses the VM's configured limit; explicit zero or a +value above the limit is rejected. + +Every queue, buffer, timeout, and resource collection has a bounded default. +Near-capacity conditions call `onLimitWarning`; exhausted limits fail with a +typed error naming the limit and the field used to raise it. + +`limits.reactor.shutdownDeadlineMs` bounds the SQLite close wait and subsequent +resource drain together. Process termination and filesystem flushing happen +before this budget. If close exceeds the deadline, +VM shutdown reports a typed `timeout` with the limit name instead of reporting +a clean stop. Close completion can no longer be confirmed, so the VM stays +quarantined until the sidecar process restarts, even if local resource counts +reach zero. Quarantined VMs count toward VM admission capacity. + +Limits are fixed for the life of a VM. To change them on a hosted VM, update +the config and call `v1.vm.restart`. In the library, dispose the VM and create +a new one with the new limits. The hosted actor also has a fixed ten-second +shutdown wait; raising the sidecar deadline does not extend it. + +## Sidecar limits + +Library VMs share a sidecar process by default. Limits that apply to the whole +process, such as `runtime.executor.maxActiveVms`, are set when creating a +dedicated sidecar with `AgentOs.createSidecar()`, as in the example above. ## Embedded API -Pass limits and the process-local warning callback to `AgentOs.create()`. - - - -Read more in the [embedded API quickstart](/agentos/docs/quickstart-embedded). +Limits apply to VMs created with `AgentOs.create()` and sidecars created with +`AgentOs.createSidecar()`. Read more in the +[embedded API quickstart](/agentos/docs/quickstart-embedded). diff --git a/vendor/agentos/docs/content/docs/sandboxes.mdx b/vendor/agentos/docs/content/docs/sandboxes.mdx index 4a72f583..73363449 100644 --- a/vendor/agentos/docs/content/docs/sandboxes.mdx +++ b/vendor/agentos/docs/content/docs/sandboxes.mdx @@ -1,147 +1,22 @@ --- title: "External Sandboxes" -description: "Extend agentOS with full sandboxes for heavy workloads like browsers, desktop automation, and compilation." -skill: true +description: "Mount a full external sandbox into an agentOS VM for workloads that need a real Linux kernel." --- -Pair agentOS with a full sandbox on demand for heavy workloads. The sandbox -filesystem mounts into the VM as a native directory, and its process management -is exposed as [host functions](/agentos/docs/host-functions), provider-agnostic through -[Sandbox Agent](https://sandboxagent.dev). +When a workload needs a full Linux environment, attach an external sandbox to +a library VM with the `sandbox` option. External sandboxes rely on trusted host +callbacks and mounts, so they are not available on hosted VMs. agentOS mounts the sandbox filesystem into +the VM at `/mnt/sandbox` and registers `agentos-sandbox` host functions for +running commands and listing processes in the sandbox. -- agentOS covers most use cases; a sandbox adds a full Linux environment for - special software. -- Lazily start a sandbox only when a task needs it, then tear it down. -- One agent session can mix lightweight coding with heavy system work. -- See [agentOS vs Sandbox](/agentos/docs/versus-sandbox) for the full comparison. + -## When to use a sandbox +Guest code reads and writes sandbox files the same way it reads local files. +Providers live in `@rivet-dev/agentos-sandbox`. -- **Native binaries** not yet supported in the agentOS runtime. -- **Browsers / desktop automation** — Playwright, Puppeteer, Selenium, anything - needing a display server. -- **Heavy compilation** — large builds or native toolchains. -- **GUI apps** — desktop apps, VNC, graphical workloads. -- **npm packages with native extensions** — `sharp`, `bcrypt`, - `better-sqlite3`. +The sandbox bridge runs through trusted host callbacks in the embedding +process, so credentials for the sandbox provider stay on the host. -Default to the agentOS VM; spin up a sandbox only when required. Sandboxes bill -per second of uptime. +See [agentOS vs Sandbox](/agentos/docs/versus-sandbox) to decide when a +workload needs one. -## Getting started - -Ships as `@rivet-dev/agentos-sandbox`, working through two mechanisms: - -- **Filesystem mount** — projects the sandbox into the VM as a native - directory. Read/write files through the mount. -- **Host functions** expose sandbox process management as - [host functions](/agentos/docs/host-functions). Run commands on the sandbox from the VM. - -Both powered by [Sandbox Agent](https://sandboxagent.dev); swap providers -without changing agent code. - -```bash -npm install @rivet-dev/agentos-sandbox sandbox-agent -``` - -- `createSandboxFs`, `createSandboxHostFunctions` from `@rivet-dev/agentos-sandbox`. -- `SandboxAgent` and provider helpers (for example, `docker`) from `sandbox-agent`. -- Pass a provider as `sandbox: { provider: docker() }`. agentOS starts the - client, mounts it at `/mnt/sandbox`, registers process host functions, and disposes - it with the VM. -- In RivetKit actors, pass the provider to `agentOS(...)` — a fresh client per - actor VM. - - - - - -## Configuration - -The sandbox is mounted at `/mnt/sandbox` by default. The `sandbox` object also -accepts these options alongside `provider` or `client`: - -| Option | Purpose | -| --- | --- | -| `mountPath` | Changes the directory where the external filesystem appears inside the agentOS VM. | -| `sandboxRoot` | Restricts the mount to a directory inside the external sandbox instead of exposing its root. | -| `readOnly` | Prevents the VM from modifying files through the mount. Defaults to `false`. | -| `timeoutMs` | Sets the per-request timeout for Sandbox Agent filesystem calls. | -| `maxFullReadBytes` | Bounds files buffered by full-read and truncate fallbacks. | - -The server example above changes `mountPath` to -`/home/agentos/sandbox`. Paths used inside the external sandbox remain relative -to `sandboxRoot`, so a VM file such as `/home/agentos/sandbox/app/index.ts` maps -to `/app/index.ts` when `sandboxRoot` is `/`. - -## Calling the mounted host functions - -Write code through the filesystem, then run it inside the sandbox. Host functions are CLI -commands called through the same `exec`/`spawn` surface as any other command. - - - -## Host-function reference - -```bash -# Run a command synchronously -agentos-sandbox run-command --command "npm install" --cwd "/app" - -# Start a background process -agentos-sandbox create-process --command "npm" --args "run" --args "dev" - -# List running processes -agentos-sandbox list-processes - -# Get process output -agentos-sandbox get-process-logs --id "proc_abc123" - -# Stop or kill a process -agentos-sandbox stop-process --id "proc_abc123" -agentos-sandbox kill-process --id "proc_abc123" - -# Send input to an interactive process -agentos-sandbox send-input --id "proc_abc123" --data "yes" -``` - -## Sandbox providers - -The package provides isolated entrypoints for Docker, local execution, E2B, -Daytona, Vercel, Cloudflare, Modal, ComputeSDK, and Sprites. Import only the -provider you use (for example, `@rivet-dev/agentos-sandbox/e2b`) so its optional -SDK is isolated from the rest of your application. Docker is also exported from -the package root, as shown above. - -Install the provider's SDK when required: `@e2b/code-interpreter` for E2B, -`@daytonaio/sdk` for Daytona, `@vercel/sandbox` for Vercel, -`@cloudflare/sandbox` for Cloudflare, `modal` for Modal, `computesdk` for -ComputeSDK, or `@fly/sprites` for Sprites. Docker and local execution need no -additional provider SDK. - -For another backend, adapt any [Sandbox Agent](https://sandboxagent.dev) -provider with `sandboxAgentProvider` from `@rivet-dev/agentos-sandbox`. Provider -mode is the preferred lifecycle: each VM gets a fresh sandbox, and disposal of -the VM destroys it. - -## Advanced: mount an existing client - -Standalone `AgentOs.create()` can mount an already-connected, -Sandbox-Agent-compatible client. Install `sandbox-agent` directly for this -manual path. The caller owns the client by default; set `dispose` to `true` when -the client implements disposal, or provide a callback to transfer lifecycle -ownership to the VM. - - - -RivetKit `agentOS()` intentionally rejects the `client` form because one client -cannot be shared safely across actor VMs. Pass a `provider` there so every actor -VM starts and owns a fresh sandbox. - -## Embedded API - -Pass a provider or an existing Sandbox Agent client to `AgentOs.create()`. -With an existing client, set `dispose` when the VM should own its lifecycle. - - - -Read more in the [embedded API quickstart](/agentos/docs/quickstart-embedded). diff --git a/vendor/agentos/docs/content/docs/security-model.mdx b/vendor/agentos/docs/content/docs/security-model.mdx index 0da3476c..c61b6205 100644 --- a/vendor/agentos/docs/content/docs/security-model.mdx +++ b/vendor/agentos/docs/content/docs/security-model.mdx @@ -1,185 +1,91 @@ --- title: "Security Model" -description: "Understand agentOS trust boundaries, VM isolation, permission enforcement, guest threats, and the responsibilities of trusted host components." +description: "Understand agentOS trust boundaries, VM isolation, and host responsibilities." skill: true --- -agentOS is in beta and still undergoing security review. The security model described here is subject to change. +agentOS is in beta and is still undergoing security review. -agentOS is a sandbox: it runs **untrusted code safely on behalf of a trusted caller**. Every actor boots its own fully virtualized VM with a virtual filesystem, process table, socket table, pipes, PTYs, a permission policy, and managed language runtimes. Guest JavaScript executes in a V8 isolate, and every guest syscall is serviced by the kernel rather than the host. There are no host escapes: guest code cannot spawn a real host process, touch the real host filesystem, or open a real host network socket. +agentOS runs untrusted guest code on behalf of a trusted host application. Each VM has a +kernel-owned filesystem, process table, socket table, pipes, PTYs, permission +policy, and language runtimes. Guest JavaScript executes in V8; WASM and Python +use their managed executors. Guest operations reach the host only through the +sidecar's policy-enforcing interfaces. + +## Trust boundary + +| Component | Trust | Responsibility | +| --- | --- | --- | +| Host application | Trusted, except for submitted guest code and data | Chooses configuration, permissions, software sources, host functions, mounts, and credentials | +| Sidecar, kernel, and VFS | Trusted enforcement point | Applies limits and permissions; owns processes, filesystems, sockets, and mounts | +| Executor | Untrusted | Runs guest JavaScript, Python, WASM, and third-party code | + +The security boundary is **sidecar/runtime to executor**. A guest bypassing an +applied permission, mount boundary, egress rule, or resource limit is in scope. +A trusted host deliberately choosing a permissive configuration or unsafe +credential is not a runtime escape. + +## Host capabilities + +Core runs inside the trusted application process, so the host may explicitly +give a VM access to host resources: host functions, host-backed mounts, external +sandboxes, and local software paths. Each of these runs with the host's +privileges. Expose them deliberately, and never pass guest-controlled values +into their configuration. + +If your application lets untrusted users configure VMs, accept only +serializable configuration from them and resolve it against your own allowlist +of mounts and software sources. + +## Hosted VM restrictions + +The hosted `agentOS` actor accepts only serializable configuration. Its +filesystem descriptors are resolved through a fixed registry, and software +installation accepts only remote HTTPS `.aospkg` sources. It cannot receive: + +- a host filesystem path or host-directory mount; +- a host function callback, closure, or arbitrary host object; +- a custom filesystem or software resolver; +- an unregistered actor implementation or lifecycle hook. + +Use [scoped JWTs](/docs/jwt) to give an untrusted client access to exactly one +hosted VM. + +## Isolation guarantees + +- Guest processes are kernel-managed and never become host processes. +- Guest sockets pass through the kernel socket table and applied network policy. +- Trusted VM setup can update mounts and command stubs without relaxing guest + filesystem permissions, including while a VM is running. +- Each VM's filesystem, process table, and runtime state are isolated from other VMs. +- Host-backed embedded mounts are confined to the configured root on every + operation, including symlink and `..` resolution. +- Resource limits bound process count, descriptors, sockets, filesystem bytes, + runtime memory, CPU time, queues, payloads, and waits. +- Limit pressure is logged or emitted as a structured warning; exhaustion fails + with a typed error naming the limit and how to raise it. ## Deny by default -No syscalls are bound to the system by default. Everything is denied until explicitly opted in. +Network access and host capabilities require explicit policy. Filesystem and +guest process capabilities operate only within the VM-owned namespace. A scope +can be `"allow"`, `"deny"`, or a rule set that matches the operation and target. -- **Network access** is denied until you opt in with a `network` permission. -- **Filesystem mounts** expose nothing of the host until you configure them. -- **Process spawning** runs only kernel-managed guest processes, never host processes. -- **All other host capabilities** must be configured by the host before the VM can use them. + -Other in-VM scopes (the virtual filesystem, child processes, process info, env) are enabled so that normal programs run, but they are mediated entirely by the kernel and never touch the host. +## Operator responsibilities -## Trust model: three components +- Authenticate and authorize users before they can reach a VM. +- Keep object-store credentials and package-download settings out of + configuration that guest code or untrusted users can read. +- Choose permissions and resource limits for the workload. +- Treat software URLs and config as trusted control-plane input, while treating + the downloaded bytes and executed code as hostile. +- Harden the host/container that runs the trusted sidecar. +- Prefer a distinct VM identity for mutually untrusted tenants. -Before judging whether something is a security bug, decide which side of the boundary it is on. agentOS has three components with very different trust levels. - - - - Client - (trusted) - Your host app - Configures the VM - Untrusted: only the - code it submits - - Sidecar / Kernel - (trusted = TCB) - Owns VFS, processes, - sockets, policy - Enforces the - boundary - - Executor - (untrusted = adversary) - V8 isolate / WASM - Runs guest code - Assume actively - hostile - - - wire - syscalls - SECURITY BOUNDARY - - - - - - -### Client (trusted) - -The party that configures and manages the VM: your application code, container, or serverless function. - -- The client process and **every value it sends** are trusted: VM config, mount descriptors and their plugin configs (host directory paths, S3 endpoints and credentials, etc.), the permission policy, network allowlist, resource limits, env, and DNS overrides. -- **Configuration is not an attack surface.** A defect that requires the client to supply a malicious config, endpoint, credential, or policy is not a sandbox vulnerability: the client is configuring its own VM and already controls the host. -- The **one** thing from the client that is *not* trusted is the **code/payload** it asks to run, because that runs in the executor. How code reached the executor never makes it trusted. - -You are responsible for hardening this side. See [What you are responsible for](#what-you-are-responsible-for). - -### Sidecar / kernel (trusted, the enforcement point) - -The trusted computing base. It brokers client requests and owns the kernel, VFS, mount/plugin registry, socket table, and permission policy. It is responsible for enforcing the boundary against the executor. - -### Executor (untrusted, the adversary) - -V8 isolates or WASM running guest JS/Python/WASM plus any third-party, npm, or agent-generated code. - -- Assume everything here is **actively hostile**. -- The executor reaches the outside world only through kernel-owned VFS, process, socket, pipe, PTY, permission, and DNS paths. - -## The security boundary - -**The security boundary is sidecar ↔ executor.** The runtime must stop guest code in the executor from: - -- Escaping the kernel boundary (the real host filesystem, network, process table, or memory). -- Bypassing the **applied** permission policy, allowlist, or limits. -- Exhausting host resources beyond configured bounds. -- Reading another VM's state. - -Two corollaries that are easy to get wrong: - -- **Trusted policy, untrusted subject.** The permission policy and limits are trusted input, but the guest executor is the subject they bind. "Guest bypasses an applied permission, egress rule, or resource cap" is in-scope and serious. Trusted = who sets the rule; untrusted = who is bound by it. -- **Trusted mount, untrusted traffic.** A host-backed mount (host directory, S3, etc.) comes from trusted config, so its existence, target, and credentials are not attack surface. But the guest drives I/O through it, so confining those guest operations to the mount root (symlink, `..`, TOCTOU, and path-aliasing escapes) is in-scope. - -### In scope vs out of scope - -| In scope (sandbox escape) | Out of scope (not a sandbox bug) | -| --- | --- | -| Guest reaches the real host fs / net / process / memory | Client supplies a malicious config / endpoint / credential / policy | -| Guest bypasses an applied permission, egress rule, or limit | Hardening that only guards trusted client-provided configuration | -| Guest exhausts host resources past configured bounds | Wire-level authn/authz between mutually distrusting clients | -| Guest reads another VM's state | VM-to-VM access via forged connection IDs (single-client transport) | -| Guest escapes a host-backed mount root (symlink / `..` / TOCTOU) | The existence or target of a configured mount | - -**Transport scope.** The wire protocol is same-version lockstep and single-client over stdio (one trusted client per sidecar process). There is no second, mutually-distrusting client, so wire-level authn/authz between clients and VM-to-VM access via forged connection IDs are out of scope until a multi-client transport exists. - -## VM isolation - -Each agentOS actor runs in its own isolated VM. - -- **Sandboxed execution.** All agent code runs inside a V8 isolate with WebAssembly. No code escapes the isolate boundary. -- **Virtual filesystem.** The VM has its own in-memory filesystem. Guest reads and writes never reach the real host filesystem. Agents cannot access host files unless explicitly mounted. -- **Virtual network.** The VM has no direct access to the host network. Outbound requests are proxied through the host with configurable controls. -- **Process isolation.** No host process is visible or accessible from inside the VM. -- **Per-actor containment.** Each actor is its own VM. Two actors share no filesystem, globals, module state, memory, or crash fate. The sidecar process that hosts those VMs may be shared by default as a performance optimization, but isolation is enforced at the VM level, not the host-process level. - -### Kernel-owned syscall paths - -Every guest syscall is mediated by the kernel and checked against the runtime's permission policy. Concretely, the kernel mediates: - -- **Filesystem.** A virtual, in-memory filesystem. Guest reads and writes never reach the real host filesystem. Host data enters the VM only through the `files`, `mounts`, or `nodeModules` you configure explicitly. See [Filesystem](/agentos/docs/filesystem). -- **Processes.** `node:child_process` spawns kernel-managed guest processes, never real host processes. Children can only run the commands the VM mounts (WASM-backed `sh` and coreutils, V8-backed `node`). See [Processes](/agentos/docs/processes). -- **Network.** Guest `fetch()`, `node:http`, and raw sockets all flow through the kernel socket table. Guest `fetch()` runs through undici inside the isolate and then through the kernel socket table; it never opens a real host socket. See [Networking](/agentos/docs/networking). -- **DNS, pipes, and PTYs** are likewise kernel-owned: no guest path reaches the host directly. -- **Host functions.** Registered [host functions](/agentos/docs/host-functions) are the only sanctioned way to hand the guest a named host capability. The guest invokes a function by name with JSON input, the call round-trips to the host handler, and only the handler's return value comes back. The guest never receives the underlying host access. - -## What enters the VM - -The host filesystem is never exposed to the guest by default. Host data crosses the boundary only through options you configure: - -- **`files`** seed bytes into the virtual filesystem. The bytes are copied in; the host path is never exposed. -- **`mounts`** project a host directory at a guest path, Docker-style. The guest sees only the mounted subtree, read through the VFS lazily, never the wider host filesystem. Mounts are read-only unless you opt out. -- **`nodeModules`** project a host `node_modules` directory (read-only, lazily) at a guest path so guest `import`/`require` resolves real installed packages. - -In every case the guest sees only the subtree you mount, and writes to read-only mounts are rejected. - -## Permissions - -Permissions are the capability gate at the boundary. They merge over a secure default that denies the network and enables the filesystem, child processes, process info, and env. Because the merge is partial, you name only the scope you change. - -```ts -// Grant network egress; everything else keeps the secure defaults. -permissions: { network: "allow" } -``` - -A scope can be `"allow"`, `"deny"`, or a `{ default, rules }` policy that matches request patterns. Guest servers are reachable only over loopback inside the VM unless you exempt a port explicitly. See [Permissions](/agentos/docs/permissions) and [Networking](/agentos/docs/networking) for the full policy shape. - -## Resource and timing limits - -The VM bounds guest execution so runaway or hostile code cannot hang or exhaust the host: - -- **Timeouts and cancellation** kill or cancel a run from the outside. -- **Memory, CPU-time, and payload limits** are enforced by the VM. -- **Timing-side-channel mitigation.** In the default mode, high-resolution clocks (`Date.now()`, `performance.now()`, `process.hrtime()`) are frozen within a run and `SharedArrayBuffer` is removed, to blunt timing side channels of the kind used in Spectre-style attacks. - -See [Security & Auth](/agentos/docs/security-model) for resource limits, network control, and authentication setup. - -## What agentOS guarantees - -- Agent code cannot read or write host files outside configured mounts. -- Agent code cannot make network requests except through the host proxy. -- Agent code cannot access host environment variables or secrets. -- Each actor's filesystem, sessions, and state are isolated from other actors. -- Resource limits (CPU, memory) are enforced at the VM level. -- A crash, resource exhaustion, or escape attempt is contained to a single VM; other VMs keep running, even when they share a sidecar process. - -## What you are responsible for - -The boundary protects the host from the guest. It does **not** harden your host process against everything else. The VM alone is not enough without a hardened host, and a hardened host alone does not protect against code that runs with full host access inside your own process. - -- Hardening the host process and deployment environment. For internet-facing workloads that take untrusted input, run your host inside an already-hardened environment (for example AWS Lambda, Google Cloud Run, or a similar sandboxed platform). -- Validating authentication tokens in `onBeforeConnect`. -- Scoping [permissions](/agentos/docs/permissions) appropriately for your use case. -- Managing API keys and secrets on the host side (see [Models & Credentials](/agentos/docs/models-and-credentials)). -- Configuring [resource limits and network controls](/agentos/docs/security-model) to match your threat model. -- Choosing your blast radius: prefer a fresh VM per untrusted or high-risk task so an escape attempt cannot outlive a single VM. - -The boundary contains guest code, but you still own the host. Treat the host process as trusted infrastructure and harden it. - -## Further reading - -- [Security configuration](/agentos/docs/security-model) for resource limits, network control, and authentication setup -- [Permissions](/agentos/docs/permissions) for agent tool-use approval patterns -- [agentOS vs Sandbox](/agentos/docs/versus-sandbox) for when to escalate to a full sandbox +See [Permissions](/agentos/docs/permissions), +[Resource Limits](/agentos/docs/resource-limits), and +[Filesystem](/agentos/docs/filesystem) for the public configuration surfaces. diff --git a/vendor/agentos/docs/content/docs/self-hosting.mdx b/vendor/agentos/docs/content/docs/self-hosting.mdx new file mode 100644 index 00000000..05e3e573 --- /dev/null +++ b/vendor/agentos/docs/content/docs/self-hosting.mdx @@ -0,0 +1,84 @@ +--- +title: "Self-Hosting (Hosted)" +description: "Run hosted agentOS VMs on your own infrastructure with the Rivet control plane and the agentOS worker image." +--- + +Self-hosting runs the hosted agentOS API on your own infrastructure instead of +Rivet Cloud. It needs two processes: the Rivet control plane, and the agentOS +worker that runs the `agentOS` actor and its VMs. If you only need VMs inside +your own Node.js process, use the [library](/agentos/docs/quickstart) instead; +it needs neither. + +## Which one should I use? + +| | [Hosted](/agentos/docs/quickstart-hosted) | [Library](/agentos/docs/quickstart) | +|---|---|---| +| **Runs** | As a durable instance on Rivet Cloud or a [self-hosted](/agentos/docs/self-hosting) Docker image | Embedded inside your process as a library | +| **Lifecycle** | Durable, sleeps when idle unless a process is running; see [actor lifecycle](/actors/docs/lifecycle) | Ephemeral, runs until `dispose()` or process exit | +| **Package** | `@rivet-dev/agentos`, or plain HTTP | `@rivet-dev/agentos-core` | +| **VM identity** | A durable VM you create by key and reach by ID | A handle your process owns until `dispose()` | +| **Configuration** | Stored with the VM and versioned | Passed to `AgentOs.create()` | +| **Clients** | Your backend, or browsers with a scoped JWT | Your backend | +| **Host access** | None | Host functions, host mounts, external sandboxes | +| **Previews** | Expiring preview URLs | None | +| **Best for** | Long-lived VMs shared across clients | Embedding VMs in an existing backend | + +## Run it + + + + +```sh +docker run -p 6420:6420 rivetdev/engine +``` + +See the [self-hosting guides](/docs/deploy/) for other ways to run it. + + + + +The worker is what actually runs your VMs. It connects to the control plane: + +```sh +docker run \ + --add-host=host.docker.internal:host-gateway \ + -e RIVET_ENDPOINT=http://host.docker.internal:6420 \ + rivetdev/services +``` + + + + +Create a VM by ID on your control plane from TypeScript or plain HTTP: + + + +```ts TypeScript @nocheck +// npm install @rivet-dev/agentos +import { createAgentOsClient } from "@rivet-dev/agentos"; + +const client = createAgentOsClient({ endpoint: "http://localhost:6420" }); + +const vm = client.agentOS.getOrCreate(["my-vm"]); +``` + +```bash HTTP +curl -X PUT "http://localhost:6420/actors?namespace=default" \ + --json '{ + "name": "agentOS", + "key": "my-vm", + "runner_name_selector": "services", + "crash_policy": "sleep" + }' +# → { "actor": { "actor_id": "…" }, "created": true } +``` + + + + + + +Everything in the [hosted quickstart](/agentos/docs/quickstart-hosted) and the +[Hosted HTTP API](/agentos/docs/hosted-api) works the same way. Use +`http://localhost:6420`, or wherever your control plane is reachable, as the +base URL instead of `https://api.rivet.dev`. diff --git a/vendor/agentos/docs/content/docs/sessions.mdx b/vendor/agentos/docs/content/docs/sessions.mdx deleted file mode 100644 index a9fd1878..00000000 --- a/vendor/agentos/docs/content/docs/sessions.mdx +++ /dev/null @@ -1,166 +0,0 @@ ---- -title: "Sessions" -description: "Open durable Agent Client Protocol sessions in agentOS, send prompts, stream events, read transcripts, and restore coding-agent adapters." -skill: true ---- - -AgentOS sessions are durable records backed by the VM's SQLite database. - -- The public session ID is stable across VM sleep and adapter restarts. -- The adapter's private ACP session ID stays internal. -- The Rivet dashboard's Transcript tab renders the same session stream live, with a composer for prompting sessions by hand. - -## Open a session - -`openSession` creates or restores a session, completes ACP negotiation, and -resolves without a value. - -- Choose and retain the `sessionId` before calling; omitted → `main`. -- `getSession` — call separately for durable metadata. -- Idempotent to repeat; changing immutable creation options for an existing ID - returns `session_conflict`. - - - - - - -Input fields: `agent`, `cwd`, `additionalDirectories`, `env`, `mcpServers`, -`permissionPolicy`, `skipOsInstructions`, `additionalInstructions`. - -- Omitted `cwd` → `/home/agentos`. -- Actor deployments inject their SQLite database automatically; standalone core - clients must configure a VM SQLite file or descriptor. - -## MCP servers - -- MCP config belongs to the session — its tools are part of the agent's runtime - context. -- Configure local child-process or remote servers **before** opening the - session. -- Config path and transports come from the selected agent adapter (e.g. Pi - reads `.mcp.json` from its AgentOS home). -- Install local MCP server packages before opening the session so first-run - package-manager output can't corrupt a stdio handshake. -- See the [agent guide](/agentos/docs/agents/pi) for adapter specifics. - - - -## Prompt - -- `prompt` accepts native ACP `ContentBlock[]` — not a special text format. -- Never creates a missing session. -- The complete user message is committed before dispatch; a prompt whose - delivery may have reached the adapter is never auto-replayed. -- Bounded by `limits.acp.maxPromptBytes` and `limits.acp.maxPromptBlocks`; limit - errors name the field to raise. -- An oversized durable update batch is rejected before it changes history. - - - - - - -- `idempotencyKey` — use when the caller may retry. Reusing a key with different - content fails; retrying while the first call is active waits and returns its - committed result. - -## Events and history - -`sessionEvent` is a flat discriminated union. - -- Top-level `type` = native ACP `SessionUpdate.sessionUpdate` value; ACP payload - fields (`content`, `toolCallId`, `entries`) sit beside the durability - envelope. No nested `update` wrapper. -- `durability: "ephemeral"` — live agent-message/thought delta; not sequenced or - stored. -- `durability: "durable"` — has a session sequence, emitted only after its - SQLite commit. Completed/coalesced message chunks are durable. -- Permission request/response variants use the same flat shape with top-level - `options`, `toolCall`, or `outcome`. - - - - - - -- `readHistory({ sessionId, before, after, limit })` — SQLite-only, never starts - an adapter. `before`/`after` are exclusive and mutually exclusive. Dedup live - durable delivery by `(sessionId, sequence)`. -- Also SQLite-only reads: `getSession`, `listSessions`, `getSessionConfig`, - `getSessionCapabilities`, `getSessionAgentInfo`. Listing uses an opaque keyset - cursor — not a frozen snapshot. - -## Restoration - -After VM sleep, the next `prompt` transparently starts the adapter. AgentOS -tries, in order: - -1. Native ACP `session/resume`. -2. Stable `session/load`. -3. A fresh private ACP session with bounded continuation context from AgentOS - history. - -- Adapter replay during load is suppressed — SQLite is the sole history source - of truth. -- Fallback transcript bounded by `limits.acp.maxFallbackContinuationBytes`. -- AgentOS stores its own exact ACP updates because ACP has no portable - history-reading API and adapters restore inconsistently. - -## Permissions - -`permissionPolicy` is `reject_all`, `ask`, or `allow_all` (default -`allow_all`). - -- Controls how AgentOS answers native ACP permission requests — not VM - permissions or adapter tool access. -- Set `ask` when opening the session; subscribing alone doesn't change the - immutable policy. -- `ask` — durably records the request as a `permission_request` event. -- `allow_all` — resolves automatically, emits no permission event. -- Reply with the exact adapter-supplied `optionId` and explicit session ID: - -```ts -await agent.sessions.respondPermission({ - sessionId: request.sessionId, - requestId: request.requestId, - optionId: request.options[0].optionId, -}); -``` - -- First valid response wins atomically. -- Requests don't expire; cancellation, adapter exit, deletion, or VM shutdown - records a terminal reason. -- Accepted responses are sequenced in durable history. - -## Cancel, unload, and delete - -- `cancelPrompt` — cooperative ACP cancellation; returns `cancelled` or - `no_active_prompt`. -- `unloadSession` — releases the live adapter, keeps SQLite metadata/history; a - later prompt restores it. -- `deleteSession` — permanently removes the session and history. Omitted ID → - `main`; repeated deletion is idempotent. - - - - - - -## Runtime configuration - -- `getSessionConfig` — returns the negotiated native ACP config collection + a - revision. -- `setSessionConfigOption` — may restore the adapter, lets ACP validate the - value, then replaces the cached collection. - - - -## Embedded API - -The session API is identical. Embedded callbacks are process-local, and history -only outlives `dispose()` when the VM has a configured `database`. - - - -Read more in the [embedded API quickstart](/agentos/docs/quickstart-embedded). diff --git a/vendor/agentos/docs/content/docs/software.mdx b/vendor/agentos/docs/content/docs/software.mdx index db109730..c9cb8e7a 100644 --- a/vendor/agentos/docs/content/docs/software.mdx +++ b/vendor/agentos/docs/content/docs/software.mdx @@ -1,41 +1,121 @@ --- title: "Software" -description: "Install and configure agentOS software packages to control the commands, tools, and coding-agent adapters available inside each VM." -skill: true +description: "Install immutable .aospkg command packages when a VM is created or while it is running." --- -agentOS ships with a common set of POSIX utilities (coreutils, sed, grep, gawk, findutils, diffutils, tar, gzip) out of the box. The `software` option installs additional packages, each providing one or more CLI commands. +agentOS software ships as immutable `.aospkg` packages containing real compiled +tools. Installed packages are projected read-only under +`/opt/agentos/pkgs//`, and their commands are linked under +`/opt/agentos/bin`. Every VM includes a default bundle with `sh`, coreutils, and +the standard CLI tools programs rely on. -## Install +Browse the available packages in the [registry](/agentos/docs/registry). -```bash -npm install @rivet-dev/agentos @agentos-software/pi -``` +## Registry packages -Add packages like `@agentos-software/ripgrep` or `@agentos-software/jq` for anything beyond the default utilities. Browse the full catalog on the [Registry](/agentos/registry/). +Registry packages are published with each release under +`https://releases.rivet.dev/agent-os//software/`, or `latest` for the +newest release. Its `manifest.json` lists each package's name, digest, size, +and path relative to the manifest. Registry software is not installed from npm; +see [Publishing Software](/agentos/docs/custom-software/publishing). -## Usage +## Install while running -Import the software packages you want, list them in the `software` array on the actor, then run commands through the client handle. +Install a package into a running VM from an HTTPS URL, with an optional exact +`sha256:<64 lowercase hex>` digest. The library also accepts a trusted local +path. - - +```ts Hosted @nocheck +import { createAgentOsClient } from "@rivet-dev/agentos"; + +const client = createAgentOsClient({ endpoint: "https://api.rivet.dev" }); +const vm = client.agentOS.getOrCreate(["my-vm"]); + +// Registry software is published as digest-addressed .aospkg files next to a +// manifest. Use a release version, or `latest`. +const base = "https://releases.rivet.dev/agent-os/latest/software/"; +const { artifacts } = await (await fetch(`${base}manifest.json`)).json(); +const ripgrep = artifacts.find((artifact) => artifact.name === "ripgrep"); + +const installed = await vm.v1.software.install({ + source: { url: new URL(ripgrep.path, base).href, digest: ripgrep.digest }, +}); +if (installed.config.state === "restart_required") { + await vm.v1.vm.restart({}); +} + +for (const software of await vm.v1.software.list({})) { + console.log(software.packageId, software.commands); +} + +await vm.v1.software.uninstall({ packageId: installed.source.packageId }); +``` + + + -## Available Packages +On hosted VMs, software is part of the VM's durable configuration, so install +and uninstall use the same revision checks as `v1.config.patch`. A change +applies live when the VM is ready and its desired configuration is fully +applied; otherwise it reports `restart_required`, and `v1.vm.restart` applies +it. Both mutations return `{ source, software, config }`. `v1.software.list` +reads the live installed set, and the desired package sources live in +`v1.config.get`. -Browse all available software packages on the [Registry](/agentos/registry/). +In the library, `software.install(source)` returns the installed package's +`packageId`, `digest`, `sizeBytes`, `packageName`, `version`, and `commands`. +`software.installed()` lists packages installed through `software.install`, and +`software.list()` reports every package that provides commands in the VM. Only +one software or mount mutation runs at a time per VM; a concurrent call fails +with `invalid_state` instead of queueing. -## Custom Software +## Install when the VM is created -Package your own agents, command packages, and WASM commands. See [Software Definition](/agentos/docs/custom-software/definition) to define a package, and [Building Binaries](/agentos/docs/custom-software/building-wasm) to compile WASM commands from source in the [agentos registry](https://github.com/rivet-dev/agentos/tree/main/registry). + -## Embedded API +```ts Hosted @nocheck +import { createAgentOsClient } from "@rivet-dev/agentos"; + +const client = createAgentOsClient({ endpoint: "https://api.rivet.dev" }); + +const vm = client.agentOS.getOrCreate(["my-vm"], { + createWithInput: { + config: { + software: [ + { + url: "https://releases.rivet.dev/agent-os/latest/software/packages/git/.aospkg", + }, + ], + }, + }, +}); +``` + + + + -Pass software packages directly to `AgentOs.create()`. +Hosted VMs take package URLs in their `software` config. The library takes +`{ packagePath }` references to packed `.aospkg` files, which is what the +`@agentos-software/*` packages in the agentOS repository export, and +`defaultSoftware: false` for a bare VM with only the software you list. - +## Verification and caching + +Each URL source is downloaded under strict size, time, and redirect limits, +verified against the expected digest when one is given, and validated before +it is projected. The verified content digest is the package identity. + +Packages are cached by content digest, so VMs that share a worker or sidecar +reuse one verified copy, and repeat installs of the same bytes skip the +download. Hosted workers also warm popular packages at startup; see +[Software Installation and Preloading](/agentos/docs/architecture/software-cache). + +## Embedded API -Read more in the [embedded API quickstart](/agentos/docs/quickstart-embedded). +The embedding process is trusted, so `software.install` accepts local package +paths as well as URLs. Read more in the +[embedded API quickstart](/agentos/docs/quickstart-embedded). diff --git a/vendor/agentos/docs/content/docs/system-prompt.mdx b/vendor/agentos/docs/content/docs/system-prompt.mdx deleted file mode 100644 index 9aaa4359..00000000 --- a/vendor/agentos/docs/content/docs/system-prompt.mdx +++ /dev/null @@ -1,19 +0,0 @@ ---- -title: "System Prompt" -description: "Configure the context agentOS injects into coding-agent sessions, including environment details, available tools, and workspace guidance." -skill: true ---- - -These internal architecture docs are mostly generated and maintained by LLMs, then reviewed by humans. They are intentionally verbose; use your preferred LLM to ask focused questions about the architecture as needed. - -agentOS automatically injects a system prompt into every agent session that describes the VM environment, available commands, and host functions. The prompt is additive and never replaces the agent's own instructions (CLAUDE.md, AGENTS.md, etc.). - -The base prompt is embedded in the sidecar (not written to a file inside the VM). At session start the sidecar assembles the base prompt with your additional instructions and generated host-function docs, then injects the result into the agent adapter's launch arguments (for example, `--append-system-prompt` for Pi). - -## Customization - -- `additionalInstructions` appends session-specific text after the base OS prompt and before the generated host-function docs, rather than replacing the agent's own instructions. -- `skipOsInstructions` suppresses the base OS prompt while still injecting the generated host-function docs. -- For Claude Code, `ACP_SYSTEM_PROMPT_MODE=replace` in the session `env` replaces Claude Code's built-in system prompt with the assembled prompt. See [Claude Code](/agentos/docs/agents/claude#system-prompt). - - diff --git a/vendor/agentos/docs/content/docs/versus-sandbox.mdx b/vendor/agentos/docs/content/docs/versus-sandbox.mdx index f55ac3be..ba2cffab 100644 --- a/vendor/agentos/docs/content/docs/versus-sandbox.mdx +++ b/vendor/agentos/docs/content/docs/versus-sandbox.mdx @@ -6,7 +6,8 @@ skill: true - **agentOS** is a lightweight VM that runs inside your process. Near-zero cold start, low memory, and direct backend integration via [host functions](/agentos/docs/host-functions). - **Sandboxes** are full Linux environments with root access, system packages, and native binary support. -- **You can use both.** agentOS works with sandboxes through the [external sandbox extension](/agentos/docs/sandboxes). Agents run in the lightweight VM by default and spin up a full sandbox on demand. +- **You can compose both.** agentOS can mount a full sandbox into the VM through + trusted host functions and mounts. ## Comparison @@ -15,22 +16,22 @@ skill: true | **Cost** | Very low. Runs in your process. | Pay per second of uptime. | | **Startup** | Near-zero cold start (~6 ms). | Seconds to spin up. | | **Backend integration** | Direct. [Host functions](/agentos/docs/host-functions) call your functions with zero latency. | Indirect. Requires network calls back to your backend. | -| **Credentials** | Stay on the host. [Host functions](/agentos/docs/host-functions) run your functions server-side; agents see only inputs and outputs. | Must be injected into the sandbox environment. | +| **Credentials** | [Host functions](/agentos/docs/host-functions) keep credentials on the host. | Must be injected into the sandbox environment. | | **Permissions** | Granular, deny-by-default. | Coarse-grained (container-level). | -| **Infrastructure** | `npm install` | Vendor account + API keys. | +| **Infrastructure** | An npm package in your backend, or [hosted VMs](/agentos/docs/quickstart-hosted). | Vendor account + API keys. | | **Best for** | Coding, file manipulation, scripting, API calls, orchestration. | Browsers, desktop automation, native compilation, dev servers. | ## When to use each ### agentOS VM -Use the lightweight VM for most agent workloads: +Use the lightweight VM for isolated command and language workloads: - Coding and file editing - Running scripts and CLI tools - Calling APIs and services via host functions -- Multi-agent orchestration and workflows -- Tasks where backend integration matters (permissions, tool access, LLM routing) +- Durable command workflows +- Tasks where backend integration matters (permissions and tool access) ### Full sandbox @@ -43,9 +44,10 @@ Spin up a sandbox when the workload needs a real Linux kernel: ### Both together -Use agentOS with [external sandboxes](/agentos/docs/sandboxes) for workflows that need both: +Use agentOS with [external sandboxes](/agentos/docs/sandboxes) when a workflow +needs both: -- Agent runs in the agentOS VM with full access to host functions and permissions +- Guest code runs in the agentOS VM with access to configured bindings and permissions - Sandbox spins up on demand for heavy tasks - Sandbox filesystem is mounted into the VM as a native directory -- Agent reads and writes sandbox files the same way it reads local files +- Guest code reads and writes sandbox files the same way it reads local files diff --git a/vendor/agentos/docs/content/docs/workflows.mdx b/vendor/agentos/docs/content/docs/workflows.mdx deleted file mode 100644 index 66b62e0a..00000000 --- a/vendor/agentos/docs/content/docs/workflows.mdx +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: "Workflows & Graphs" -description: "Orchestrate multi-step coding-agent tasks with durable agentOS workflows, graph dependencies, retries, state, and resumable execution." -skill: true ---- - -Orchestrate multi-step agent tasks with durable workflows that survive crashes and restarts. Build them with RivetKit's `workflow()` run handler, where each `ctx.step()` is recorded, retried, and resumed independently, and the output of one step can feed into the next. - -## Basic workflow - -A workflow is the durable `run` handler of an actor. Wrap it in `workflow()` and drive a multi-step agent task as an ordered series of steps: clone the repo, let an agent fix the bug, then run the tests. Each actor instance is one workflow run initialized with creation input, so no application queue is required. - -Session creation and prompting happen within the step that uses them, so a session never has to outlive the work it backs (sessions are ephemeral and would not survive a replay). Steps reach the agentOS VM, a separate actor, through `ctx.client()`. - - - - - - -## Agent chaining - -Output of one agent session feeds into the next. Each session is created and completed within its own step, and data passes between steps through the VM filesystem (a review file) and step return values. - - - - - - -## Recommendations - -- Build the actor's `run` handler with `workflow()` so each `ctx.step()` is durable: recorded, retried, and resumed independently across crashes and restarts. -- Keep step names stable across code changes. Renaming a step breaks replay for in-progress workflows. -- Create and close sessions within the step that uses them. Sessions are ephemeral, so keep their lifetime scoped to one unit of work. -- Pass data between steps via the filesystem or step return values, not session state. -- Keep `state` changes and other actor-local side effects inside `ctx.step()` callbacks; use non-step workflow code only for orchestration. -- Reach the agentOS VM, a separate actor, from inside a step with `ctx.client()`. -- See [Workflows](/workflows/docs/) for the full workflow API reference including timers, joins, and races. - -## Embedded API - -Durable workflows require Rivet Actors. `AgentOs.create()` records no steps and replays nothing, so an [embedded](/agentos/docs/embedded) host either drives the VM from its own durable orchestrator or uses an actor. VM state survives a host restart only if you configured a `database`, and the VM itself has to be recreated. - -Read more in the [embedded API quickstart](/agentos/docs/quickstart-embedded). diff --git a/vendor/agentos/docs/content/integrations/flue.mdx b/vendor/agentos/docs/content/integrations/flue.mdx deleted file mode 100644 index c28b21ae..00000000 --- a/vendor/agentos/docs/content/integrations/flue.mdx +++ /dev/null @@ -1,122 +0,0 @@ ---- -title: "Flue" -description: "Use agentOS as the durable sandbox backend for Flue." -skill: true ---- - -import DeployTargets from '@/components/docs/DeployTargets.astro'; - -{/* - Sync policy: examples/flue and examples/vercel-eve in this repository are the - source of truth. Before changing either integration, manually compare both - agentOS examples and guides with both hardcoded Rivet guides: - rivet-dev/rivet/website/src/content/docs/integrations/{flue,vercel-eve}.mdx. - Use CodeSnippet for whole example files in agentOS. Update both repositories - whenever either example changes. -*/} - -Flue owns the agent runtime and session lifecycle. Rivet maps each agent instance and workflow run to a durable Rivet Actor, while agentOS gives each Flue context an isolated VM with a persistent `/workspace` filesystem. - -[View the complete example →](https://github.com/rivet-dev/agentos/tree/main/examples/flue) - -## Quickstart - - - - - -```sh -mkdir my-agent && cd my-agent -npm init -y -npm pkg set type=module - -# Install the Flue packages -npm add "@flue/runtime@npm:@rivet-dev/labs-flue-runtime@1.0.0-beta.9-rivet.2" -npm add --save-dev "@flue/cli@npm:@rivet-dev/labs-flue-cli@1.0.0-beta.9-rivet.2" - -# Install the Rivet packages -npm add @rivet-dev/flue @rivet-dev/agentos @rivet-dev/agentos-flue rivetkit - -# Initialize the project -npx flue init --target node -``` - -- `@flue/cli` and `@flue/runtime`: Build and run the Flue project using Rivet's preview Flue packages. -- `@rivet-dev/flue`: Runs Flue agents and workflows as Rivet Actors. -- `@rivet-dev/agentos` and `@rivet-dev/agentos-flue`: Provide the agentOS VM and connect Flue's sandbox API to it. - -*This uses [Rivet's Flue fork](https://github.com/rivet-dev/flue). We're working to merge its extension APIs upstream so Flue can support actor-model runtimes without a Rivet fork.* - - - - - -Create `actors.ts`: - - - -Update `flue.config.ts`: - - - - - - - -Create `agents/assistant.ts`: - - - - - - - -Set the provider key required by your model, such as `ANTHROPIC_API_KEY`, in `.env`. - -Run the agent: - -```sh -npx flue run assistant --id local \ - --input '{"message":"Write hello from Flue to /workspace/hello.txt, run wc -c /workspace/hello.txt, then read the file back."}' -``` - - - - - -Deploy to one of the supported platforms: - - - - - - - -## Runtime model - - -agentOS does not support Cloudflare Workers yet. It works with Node.js, Bun, or -Deno on platforms such as Railway, Kubernetes, or Vercel. - - -## Default filesystem - -agentOS persists the VM filesystem, including `/workspace`, to Rivet Actor storage by default. Additional mounts can be configured as needed. - -## Configuration - -### Virtual machine - -See the `agentOS()` [configuration reference](/agentos/docs/embedded#configuration-reference) to configure the VM. - -### Flue sandbox - -`agentOSSandbox()` accepts: - -| Option | Required | Description | -| --- | --- | --- | -| `actor` | Yes | Actor registered with `setup()`, such as `vm`. | -| `registry` | Yes | The application registry exported from `actors.ts`. | -| `cwd` | No | Base directory exposed to Flue. Defaults to `/workspace`. | -| `params` | No | Connection parameters forwarded to the actor's `onBeforeConnect` hook. | -| `client` | No | An existing client configured for the same registry. | diff --git a/vendor/agentos/docs/content/integrations/rivet-actors.mdx b/vendor/agentos/docs/content/integrations/rivet-actors.mdx deleted file mode 100644 index 886d34b6..00000000 --- a/vendor/agentos/docs/content/integrations/rivet-actors.mdx +++ /dev/null @@ -1,83 +0,0 @@ ---- -title: "Rivet Actors" -description: "Run agentOS natively as Rivet Actors." -skill: true ---- - -import DeployTargets from '@/components/docs/DeployTargets.astro'; - -Rivet is agentOS's native framework. The `agentOS()` function returns an ordinary [Rivet Actor](/actors/docs/), so each agentOS VM is a directly addressable actor with its own durable filesystem, state, and session history—no adapter layer required. - -[View the complete example →](https://github.com/rivet-dev/agentos/tree/main/examples/quickstart-app) - -## Quickstart - - - - - -```sh -mkdir my-agent && cd my-agent -npm init -y -npm pkg set type=module -npm add @rivet-dev/agentos @agentos-software/pi -npm add --save-dev tsx typescript -``` - - - - - -Create `server.ts`. The `agentOS()` call returns a normal Rivet Actor definition, and `setup()` registers it with the Rivet runtime: - - - - - - - -Create `client.ts` to address an actor by name, subscribe to its events, open a session, and send a prompt: - - - - - - - -Start the actor, then run the client in a second terminal with the provider key required by your model: - -```sh -# Terminal 1 -npx tsx server.ts - -# Terminal 2 -ANTHROPIC_API_KEY=... npx tsx client.ts -``` - - - - - -Because an agentOS VM is a Rivet Actor, you can compose it with Rivet's orchestration primitives: - -- **[Durable workflows](/agentos/docs/workflows)** — Run multi-step agent tasks that retry and resume after crashes. -- **[Multiplayer agents](/agentos/docs/multiplayer)** — Stream agent output to multiple connected clients in real time. -- **[Agent-to-agent systems](/agentos/docs/agent-to-agent)** connect isolated agents through typed host functions and durable pipelines. -- **[Scheduled agents](/agentos/docs/cron)** — Run commands and agent sessions on timers or cron schedules. -- **[Human-in-the-loop flows](/agentos/docs/approvals)** — Pause for tool approval and resume from durable event history. - - - - - -Deploy to one of the supported platforms: - - - - - - - -## Learn more - -See the [agentOS quickstart](/agentos/docs/quickstart/) for VM configuration and the [Rivet Actor documentation](/actors/docs/) for state, actions, events, queues, workflows, and deployment. diff --git a/vendor/agentos/docs/content/integrations/vercel-eve.mdx b/vendor/agentos/docs/content/integrations/vercel-eve.mdx deleted file mode 100644 index b8679a6a..00000000 --- a/vendor/agentos/docs/content/integrations/vercel-eve.mdx +++ /dev/null @@ -1,162 +0,0 @@ ---- -title: "Vercel Eve" -description: "Run Vercel Eve with agentOS and Rivet World." -skill: true ---- - -import DeployTargets from '@/components/docs/DeployTargets.astro'; - -{/* - Sync policy: examples/flue and examples/vercel-eve in this repository are the - source of truth. Before changing either integration, manually compare both - agentOS examples and guides with both hardcoded Rivet guides: - rivet-dev/rivet/website/src/content/docs/integrations/{flue,vercel-eve}.mdx. - Use CodeSnippet for whole example files in agentOS. Update both repositories - whenever either example changes. -*/} - -Eve owns the agent runtime and session lifecycle. agentOS maps every sandbox session to an isolated VM actor with a durable `/workspace` filesystem, while Rivet World runs Eve workflows on Rivet Actors. - -[View the complete example →](https://github.com/rivet-dev/agentos/tree/main/examples/vercel-eve) - -## Quickstart - - - - - -```sh -npx eve@latest init my-agent -cd my-agent -``` - - - - - -```sh -npm add @rivet-dev/agentos @rivet-dev/agentos-eve @rivet-dev/vercel-world -``` - -- `@rivet-dev/agentos` and `@rivet-dev/agentos-eve`: Provide the agentOS VM and connect Eve's sandbox API to it. -- `@rivet-dev/vercel-world`: Runs Eve workflows on [Rivet World](https://workflow-sdk.dev/worlds). - - - - - -Update `agent/agent.ts`: - - - - - - - -Rivet World lets you run Eve on top of Rivet. - -Add the World module import to `package.json`: - -```json title="package.json" -{ - "imports": { - "#world": "./world.ts" - } -} -``` - -Create `world.ts`: - - - -The first World operation starts this registry and waits for the Rivet envoy to -be ready. - - - - - -Create `actors.ts`: - - - -Create `agent/sandbox.ts`: - - - - - - - -Install the Vercel CLI, then link Eve once so it can call your configured model: - -```sh -npm install --global vercel@latest -npx eve link -``` - -Then run the agent: - -```sh -npx eve dev -``` - - - - - -By default, agentOS runs locally with `npx rivetkit dev` — no infrastructure needed. To run in production, deploy to any of these targets: - - - -See [Deployment](/agentos/self-host) for managed, self-hosted, and agentOS Core options. - - - - - -## Default Filesystem - -agentOS persists the VM filesystem, including `/workspace`, to Rivet Actor storage by default. Additional mounts can be configured as needed. - -## Configuration - -### Virtual Machine - -See the `agentOS()` [configuration reference](/agentos/docs/embedded#configuration-reference) to configure the VM. - -### Eve Sandbox Backend - -`agentOSBackend()` accepts: - -| Option | Required | Description | -| --- | --- | --- | -| `actor` | Yes | Actor registered with `setup()`, such as `vm`. | -| `registry` | Yes | The application registry containing that actor. It is started lazily and shared by Eve sessions. | -| `client` | No | An existing client configured for the same registry. | - -### Rivet World - -Rivet World stores Eve workflow runs in Rivet Actors so they resume instead of restarting. - -[Read the Rivet Workflows integration documentation →](/actors/integrations/workflow-sdk/) - -## Advanced - -### agentOS Core Backend - -Use `agentOSCoreBackend()` when Eve should create agentOS Core VMs directly without Rivet Actor orchestration. The `create` callback owns the complete VM configuration: - -```sh -pnpm add @rivet-dev/agentos-core -``` - - - -When using agentOS Core instead of regular agentOS, you lose: - -- **Durable filesystem and session history.** Core's root filesystem is ephemeral by default, so you must provide your own persistent mount at `/workspace`. -- **Stable per-session actor identity.** Core cannot reconnect to the same VM across Eve process restarts. -- **Automatic sleep and wake.** The VM lives inside Eve's short-lived server process instead staying awake for a given grace period. `shutdown()` disposes it. - -Use Core only when your application owns equivalent persistence and lifecycle management. diff --git a/vendor/agentos/docs/content/use-cases/index.mdx b/vendor/agentos/docs/content/use-cases/index.mdx new file mode 100644 index 00000000..71e714bc --- /dev/null +++ b/vendor/agentos/docs/content/use-cases/index.mdx @@ -0,0 +1,66 @@ +--- +title: "Use Cases" +description: "What people build with agentOS." +--- + +agentOS runs untrusted code inside isolated VMs with a real filesystem, shell, +and process model. Agent frameworks can use that execution surface, but agentOS +does not own agent sessions, prompts, messaging, or workflow orchestration. + +## Programming Agents + +Purpose-built for agents that write, test, and deploy code autonomously. + +- Native file system access with git support +- Shell execution with full toolchain access +- Package installation and dependency management +- Test runner integration + +**Example:** An agent that takes a GitHub issue, writes the fix, runs tests, and opens a pull request. + +## Background Commands + +Run long-lived commands asynchronously and observe their bounded output. + +- Durable files survive VM recreation +- Spawn and signal independent guest processes +- Recover bounded output by sequence cursor +- Monitor progress in real-time + +**Example:** A migration tool that refactors a large codebase over several hours +and commits changes incrementally. + +## Evals + +Run agent evaluations and benchmarks at scale without spinning up expensive sandboxes for each test. + +- Low memory per instance compared to sandboxes +- Near-zero cold starts for rapid iteration +- Bounded process-output replay for debugging +- Cost-effective at thousands of runs + +**Example:** Evaluating 10,000 agent responses in parallel to measure performance across different prompts. + +## Data Processing + +Run ETL pipelines, data transformations, and analysis commands. + +- Process and network streaming capabilities +- Database connections and queries +- File format conversion +- Scheduled command execution + +**Example:** A command that ingests raw data, cleans it, runs analysis, and +generates reports on a schedule. + +## Workflow Automation + +Use agentOS as the execution layer beneath an external workflow system. + +- Isolated command execution +- Durable files +- Scheduled command runs +- Typed failures and resource limits + +**Example:** A CI workflow that delegates each untrusted build step to an +agentOS VM and keeps approvals in the workflow product. diff --git a/vendor/agentos/docs/registry.json b/vendor/agentos/docs/registry.json index 46755b0b..64a0ec43 100644 --- a/vendor/agentos/docs/registry.json +++ b/vendor/agentos/docs/registry.json @@ -3,91 +3,27 @@ { "slug": "browserbase", "title": "Browserbase", - "description": "The Browserbase `browse` CLI: let agents browse the web with a cloud browser, no sandbox required.", + "description": "The Browserbase `browse` CLI for controlling a cloud browser from guest programs.", "types": [ "browser" ], "category": "browser", "priority": 0, - "package": "@agentos-software/browserbase", + "artifactName": "browserbase", "status": "available", "beta": true, "image": "/images/registry/browserbase.svg" }, - { - "slug": "everything", - "title": "Everything", - "description": "Meta-package: all available WASM command packages.", - "types": [ - "software" - ], - "category": "meta", - "priority": 110, - "package": "@agentos-software/everything", - "status": "available" - }, - { - "slug": "build-essential", - "title": "Build Essential", - "description": "Meta-package: common + git + curl.", - "types": [ - "software" - ], - "category": "meta", - "priority": 100, - "package": "@agentos-software/build-essential", - "status": "available" - }, - { - "slug": "pi", - "title": "PI", - "description": "Run the PI coding agent with lightweight, fast execution.", - "types": [ - "software" - ], - "category": "agents", - "priority": 100, - "package": "@agentos-software/pi", - "status": "available", - "image": "/images/registry/pi.svg" - }, - { - "slug": "common", - "title": "Common", - "description": "Meta-package: coreutils + sed + grep + gawk + findutils + diffutils + tar + gzip.", - "types": [ - "software" - ], - "category": "meta", - "priority": 95, - "package": "@agentos-software/common", - "status": "available" - }, - { - "slug": "claude-code", - "title": "Claude Code", - "description": "Run Claude Code as an agentOS agent with full tool access, file editing, and shell execution.", - "types": [ - "software" - ], - "category": "agents", - "priority": 90, - "package": "@agentos-software/claude-code", - "status": "docs", - "beta": true, - "image": "/images/registry/claude-code.svg", - "docsHref": "/docs/agents/claude" - }, { "slug": "git", "title": "git", - "description": "Upstream Git version control for AgentOS VMs.", + "description": "Upstream Git version control for agentOS VMs.", "types": [ "software" ], "category": "developer-tools", "priority": 90, - "package": "@agentos-software/git", + "artifactName": "git", "status": "available", "image": "/images/registry/git.svg" }, @@ -100,24 +36,9 @@ ], "category": "developer-tools", "priority": 85, - "package": "@agentos-software/ripgrep", + "artifactName": "ripgrep", "status": "available" }, - { - "slug": "codex", - "title": "Codex", - "description": "Run OpenAI's Codex coding agent inside agentOS with programmatic API access.", - "types": [ - "software" - ], - "category": "agents", - "priority": 80, - "package": "@agentos-software/codex", - "status": "docs", - "beta": true, - "image": "/images/registry/codex.svg", - "docsHref": "/docs/agents/codex" - }, { "slug": "jq", "title": "jq", @@ -127,7 +48,7 @@ ], "category": "data", "priority": 80, - "package": "@agentos-software/jq", + "artifactName": "jq", "status": "available", "image": "/images/registry/jq.svg" }, @@ -140,7 +61,7 @@ ], "category": "data", "priority": 75, - "package": "@agentos-software/sqlite3", + "artifactName": "sqlite3", "status": "available", "image": "/images/registry/sqlite3.svg" }, @@ -153,24 +74,10 @@ ], "category": "data", "priority": 70, - "package": "@agentos-software/duckdb", + "artifactName": "duckdb", "status": "available", "image": "/images/registry/duckdb.svg" }, - { - "slug": "opencode", - "title": "OpenCode", - "description": "Run OpenCode, an open-source coding agent, inside agentOS.", - "types": [ - "software" - ], - "category": "agents", - "priority": 70, - "package": "@agentos-software/opencode", - "status": "docs", - "image": "/images/registry/opencode.svg", - "docsHref": "/docs/agents/opencode" - }, { "slug": "vim", "title": "vim", @@ -180,7 +87,7 @@ ], "category": "editors", "priority": 65, - "package": "@agentos-software/vim", + "artifactName": "vim", "status": "available", "image": "/images/registry/vim.svg" }, @@ -193,7 +100,7 @@ ], "category": "core", "priority": 60, - "package": "@agentos-software/tar", + "artifactName": "tar", "status": "available", "image": "/images/registry/tar.svg" }, @@ -206,7 +113,7 @@ ], "category": "networking", "priority": 55, - "package": "@agentos-software/ssh", + "artifactName": "ssh", "status": "available", "image": "/images/registry/ssh.svg" }, @@ -219,7 +126,7 @@ ], "category": "networking", "priority": 55, - "package": "@agentos-software/wget", + "artifactName": "wget", "status": "available", "image": "/images/registry/wget.svg" }, @@ -232,7 +139,7 @@ ], "category": "networking", "priority": 50, - "package": "@agentos-software/curl", + "artifactName": "curl", "status": "available", "image": "/images/registry/curl.svg" }, @@ -245,7 +152,7 @@ ], "category": "core", "priority": 45, - "package": "@agentos-software/coreutils", + "artifactName": "coreutils", "status": "available", "image": "/images/registry/coreutils.svg" }, @@ -258,7 +165,7 @@ ], "category": "core", "priority": 45, - "package": "@agentos-software/sh", + "artifactName": "sh", "status": "available" }, { @@ -270,7 +177,7 @@ ], "category": "core", "priority": 43, - "package": "@agentos-software/xfsprogs", + "artifactName": "xfsprogs", "status": "available" }, { @@ -282,7 +189,7 @@ ], "category": "core", "priority": 42, - "package": "@agentos-software/acl", + "artifactName": "acl", "status": "available" }, { @@ -294,7 +201,7 @@ ], "category": "core", "priority": 41, - "package": "@agentos-software/attr", + "artifactName": "attr", "status": "available" }, { @@ -306,7 +213,7 @@ ], "category": "core", "priority": 40, - "package": "@agentos-software/grep", + "artifactName": "grep", "status": "available", "image": "/images/registry/grep.svg" }, @@ -319,7 +226,7 @@ ], "category": "core", "priority": 35, - "package": "@agentos-software/sed", + "artifactName": "sed", "status": "available", "image": "/images/registry/sed.svg" }, @@ -332,7 +239,7 @@ ], "category": "developer-tools", "priority": 30, - "package": "@agentos-software/fd", + "artifactName": "fd", "status": "available" }, { @@ -344,7 +251,7 @@ ], "category": "core", "priority": 25, - "package": "@agentos-software/tree", + "artifactName": "tree", "status": "available" }, { @@ -356,7 +263,7 @@ ], "category": "core", "priority": 20, - "package": "@agentos-software/gawk", + "artifactName": "gawk", "status": "available", "image": "/images/registry/gawk.svg" }, @@ -369,7 +276,7 @@ ], "category": "core", "priority": 15, - "package": "@agentos-software/findutils", + "artifactName": "findutils", "status": "available", "image": "/images/registry/findutils.svg" }, @@ -382,7 +289,7 @@ ], "category": "core", "priority": 12, - "package": "@agentos-software/zip", + "artifactName": "zip", "status": "available" }, { @@ -394,7 +301,7 @@ ], "category": "core", "priority": 10, - "package": "@agentos-software/envsubst", + "artifactName": "envsubst", "status": "available" }, { @@ -406,7 +313,7 @@ ], "category": "core", "priority": 10, - "package": "@agentos-software/unzip", + "artifactName": "unzip", "status": "available" }, { @@ -418,7 +325,7 @@ ], "category": "core", "priority": 8, - "package": "@agentos-software/gzip", + "artifactName": "gzip", "status": "available", "image": "/images/registry/gzip.svg" }, @@ -431,7 +338,7 @@ ], "category": "core", "priority": 6, - "package": "@agentos-software/diffutils", + "artifactName": "diffutils", "status": "available", "image": "/images/registry/diffutils.svg" }, @@ -444,7 +351,7 @@ ], "category": "data", "priority": 4, - "package": "@agentos-software/yq", + "artifactName": "yq", "status": "available" }, { @@ -456,21 +363,8 @@ ], "category": "core", "priority": 2, - "package": "@agentos-software/file", + "artifactName": "file", "status": "available" - }, - { - "slug": "codex-cli", - "title": "Codex CLI", - "description": "OpenAI Codex CLI integration.", - "types": [ - "software" - ], - "category": "agents", - "priority": 0, - "package": "@agentos-software/codex-cli", - "status": "available", - "image": "/images/registry/codex.svg" } ] } diff --git a/vendor/agentos/docs/sidebar.json b/vendor/agentos/docs/sidebar.json index 6ccd5d64..863a1bd7 100644 --- a/vendor/agentos/docs/sidebar.json +++ b/vendor/agentos/docs/sidebar.json @@ -9,13 +9,13 @@ "icon": "faSquareInfo" }, { - "title": "Quickstart", - "href": "/agentos/docs/quickstart", + "title": "Quickstart (Hosted)", + "href": "/agentos/docs/quickstart-hosted", "icon": "faForwardFast" }, { - "title": "Quickstart (Embedded)", - "href": "/agentos/docs/quickstart-embedded", + "title": "Quickstart (Library)", + "href": "/agentos/docs/quickstart", "icon": "faForwardFast" }, { @@ -25,68 +25,6 @@ } ] }, - { - "title": "Agent", - "pages": [ - { - "title": "Agents", - "collapsible": true, - "icon": "faRobot", - "pages": [ - { - "title": "Pi", - "href": "/agentos/docs/agents/pi", - "icon": { - "src": "/images/registry/pi.svg" - } - }, - { - "title": "ClaudeCode", - "href": "/agentos/docs/agents/claude", - "badge": "Beta", - "icon": { - "src": "/images/registry/claude-code.svg" - } - }, - { - "title": "Codex", - "href": "/agentos/docs/agents/codex", - "badge": "Beta", - "icon": { - "src": "/images/registry/codex.svg" - } - }, - { - "title": "OpenCode", - "href": "/agentos/docs/agents/opencode", - "icon": { - "src": "/images/registry/opencode.svg" - } - }, - { - "title": "Custom Agents", - "href": "/agentos/docs/agents/custom", - "icon": "faWrench" - } - ] - }, - { - "title": "Sessions & Transcripts", - "href": "/agentos/docs/sessions", - "icon": "faMessages" - }, - { - "title": "Approvals", - "href": "/agentos/docs/approvals", - "icon": "faCheck" - }, - { - "title": "Models & Credentials", - "href": "/agentos/docs/models-and-credentials", - "icon": "faKey" - } - ] - }, { "title": "Execution", "pages": [ @@ -107,31 +45,6 @@ } ] }, - { - "title": "Orchestration", - "pages": [ - { - "title": "Multiplayer", - "href": "/agentos/docs/multiplayer", - "icon": "faTowerBroadcast" - }, - { - "title": "Workflows & Graphs", - "href": "/agentos/docs/workflows", - "icon": "faDiagramNext" - }, - { - "title": "Crons & Loops", - "href": "/agentos/docs/cron", - "icon": "faClock" - }, - { - "title": "Agent-to-Agent", - "href": "/agentos/docs/agent-to-agent", - "icon": "faArrowsLeftRight" - } - ] - }, { "title": "Operating System", "pages": [ @@ -150,6 +63,11 @@ "href": "/agentos/docs/processes", "icon": "faTerminal" }, + { + "title": "Crons & Schedules", + "href": "/agentos/docs/cron", + "icon": "faClock" + }, { "title": "Networking & Previews", "href": "/agentos/docs/networking", @@ -193,8 +111,12 @@ "title": "Reference", "pages": [ { - "title": "Authentication", - "href": "/agentos/docs/authentication" + "title": "Hosted HTTP API", + "href": "/agentos/docs/hosted-api" + }, + { + "title": "Self-Hosting (Hosted)", + "href": "/agentos/docs/self-hosting" }, { "title": "Custom Software", @@ -208,6 +130,10 @@ "title": "Building Binaries", "href": "/agentos/docs/custom-software/building-wasm" }, + { + "title": "Publishing", + "href": "/agentos/docs/custom-software/publishing" + }, { "title": "Request Software", "href": "https://github.com/rivet-dev/agentos/issues/new/choose", @@ -240,18 +166,6 @@ "title": "Advanced", "collapsible": true, "pages": [ - { - "title": "Agent Sessions", - "href": "/agentos/docs/architecture/agent-sessions" - }, - { - "title": "Agent SDK Snapshots", - "href": "/agentos/docs/architecture/agent-sdk-snapshots" - }, - { - "title": "Sessions & Persistence", - "href": "/agentos/docs/architecture/sessions-persistence" - }, { "title": "Processes", "href": "/agentos/docs/architecture/processes" @@ -280,6 +194,10 @@ "title": "Packages & Command Resolution", "href": "/agentos/docs/architecture/packages-and-command-resolution" }, + { + "title": "Software Installation & Preloading", + "href": "/agentos/docs/architecture/software-cache" + }, { "title": "Compiler Toolchain", "href": "/agentos/docs/architecture/compiler-toolchain" @@ -288,10 +206,6 @@ "title": "Limits & Observability", "href": "/agentos/docs/architecture/limits-and-observability" }, - { - "title": "System Prompt", - "href": "/agentos/docs/system-prompt" - }, { "title": "Persistence & Sleep", "href": "/agentos/docs/persistence" @@ -308,10 +222,6 @@ "title": "Embedded VMs", "href": "/agentos/docs/embedded" }, - { - "title": "Debugging", - "href": "/agentos/docs/debugging" - }, { "title": "Performance", "href": "/agentos/docs/performance" @@ -320,34 +230,5 @@ } ] } - ], - "integrations": [ - { - "title": "General", - "pages": [ - { - "title": "Overview", - "href": "/agentos/integrations", - "icon": "faSquareInfo" - } - ] - }, - { - "title": "Frameworks", - "pages": [ - { - "title": "Flue", - "href": "/agentos/integrations/flue" - }, - { - "title": "Rivet Actors", - "href": "/agentos/integrations/rivet-actors" - }, - { - "title": "Vercel Eve", - "href": "/agentos/integrations/vercel-eve" - } - ] - } ] } diff --git a/vendor/agentos/examples/agent-to-agent/README.md b/vendor/agentos/examples/agent-to-agent/README.md deleted file mode 100644 index 9c21fd0b..00000000 --- a/vendor/agentos/examples/agent-to-agent/README.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: "Agent to Agent" -description: "Bridge two isolated agent VMs: a writer agent calls a reviewer agent through a host function." -category: "Agents" -order: 5 ---- - -Run two agents in separate isolated VMs and let one delegate to the other. The writer agent produces code, then hands it to a reviewer agent for feedback — without the two VMs ever sharing a filesystem. Reach for this when you want specialized agents that collaborate but stay isolated. - -## How it works - -Both agents are independent `agentOS` VMs registered under one `setup`. The writer receives a host-side `review` function it can invoke by name. When the writer runs `agentos-review submit --path ...`, the function's `execute` runs on the host, where it reads the file out of the writer's VM, copies it into the reviewer's VM, opens a reviewer session, and prompts the reviewer to review the code. The review text is returned to the writer as the function's result. The two VMs never touch directly; the host bridge is the only path between them. - -## Run it - -```sh -npm install -ANTHROPIC_API_KEY=sk-... npx tsx server.ts # start both agent VMs -ANTHROPIC_API_KEY=sk-... npx tsx client.ts # drive the writer, which calls the reviewer -``` - -The writer writes an API, submits it through the host function, and receives the reviewer's feedback inline. - -## Source - -View the source on GitHub: https://github.com/rivet-dev/agent-os/tree/main/examples/agent-to-agent diff --git a/vendor/agentos/examples/agent-to-agent/client.ts b/vendor/agentos/examples/agent-to-agent/client.ts deleted file mode 100644 index 89a72720..00000000 --- a/vendor/agentos/examples/agent-to-agent/client.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); -const writerAgent = client.writer.getOrCreate("my-project"); - -await writerAgent.sessions.open({ - agent: "claude", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, -}); - -// The writer calls the `review` host-function collection, which bridges to the reviewer VM. -await writerAgent.sessions.prompt({ - content: [ - { - type: "text", - text: "Write a small REST API, then send it to the review agent for review.", - }, - ], -}); diff --git a/vendor/agentos/examples/agent-to-agent/package.json b/vendor/agentos/examples/agent-to-agent/package.json deleted file mode 100644 index 6cf4cade..00000000 --- a/vendor/agentos/examples/agent-to-agent/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-agent-to-agent", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-sandbox": "workspace:*", - "sandbox-agent": "^0.4.2", - "dockerode": "^4.0.9", - "get-port": "^7.1.0", - "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", - "zod": "^4.1.11", - "@rivet-dev/agentos": "workspace:*", - "rivetkit": "catalog:rivetkit" - }, - "devDependencies": { - "@types/node": "^22.10.2", - "tsx": "^4.19.0", - "typescript": "^5.7.2" - } -} diff --git a/vendor/agentos/examples/agent-to-agent/server.ts b/vendor/agentos/examples/agent-to-agent/server.ts deleted file mode 100644 index 64449fdd..00000000 --- a/vendor/agentos/examples/agent-to-agent/server.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; -import { createClient } from "@rivet-dev/agentos/client"; -import { z } from "zod"; - -// The reviewer is its own isolated agent VM. -const reviewer = agentOS({}); - -// Bridge the writer to the reviewer. The VMs share no filesystem, so the writer -// sends the full file contents; the bridge writes them into the reviewer's VM -// and asks the reviewer to review. Runs on the host. -async function reviewCode(code: string): Promise { - const client = createClient({ - endpoint: "http://localhost:6420", - }); - const reviewerHandle = client.reviewer.getOrCreate("my-project"); - - // Write the submitted contents into the reviewer's VM. - await reviewerHandle.filesystem.writeFile("/home/agentos/review.ts", code); - - // Ask the reviewer to review. - await reviewerHandle.sessions.open({ - agent: "claude", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - }); - const result = await reviewerHandle.sessions.prompt({ - content: [ - { - type: "text", - text: "Review the code at /home/agentos/review.ts and list any issues.", - }, - ], - }); - await reviewerHandle.sessions.delete(); - - return ( - result.message?.content - .filter((block) => block.type === "text") - .map((block) => block.text) - .join("") ?? "" - ); -} - -// The writer agent gets a `review` host-function collection. When the writer runs -// `agentos-review submit`, the bridge above executes on the host. -const writer = agentOS({ - hostFunctions: { - review: { - submit: { - inputSchema: z - .object({ - code: z.string().describe("The full source code to review."), - }) - .describe( - "Submit the full contents of a file to the reviewer agent for review. Returns the reviewer's feedback as text.", - ), - execute: async (input: { code: string }) => ({ - review: await reviewCode(input.code), - }), - }, - }, - }, -}); - -export const registry = setup({ use: { writer, reviewer } }); - -registry.start(); diff --git a/vendor/agentos/examples/agent-to-agent/tsconfig.json b/vendor/agentos/examples/agent-to-agent/tsconfig.json deleted file mode 100644 index e7937905..00000000 --- a/vendor/agentos/examples/agent-to-agent/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "moduleResolution": "bundler", "noEmit": true, "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], "types": ["node"], "baseUrl": ".", - "paths": { - "@rivet-dev/agentos": ["../../packages/agentos/src/index.ts"], - "@rivet-dev/agentos/client": ["../../packages/agentos/src/client.ts"], - "@rivet-dev/agentos/react": ["../../packages/agentos/src/react.ts"] - } - }, - "include": ["**/*.ts", "**/*.tsx"] -} diff --git a/vendor/agentos/examples/agentos-typecheck/package.json b/vendor/agentos/examples/agentos-typecheck/package.json deleted file mode 100644 index 01cdaa24..00000000 --- a/vendor/agentos/examples/agentos-typecheck/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "@rivet-dev/agentos-typecheck-example", - "version": "0.0.1", - "private": true, - "description": "Type-checking example that exercises the @rivet-dev/agentos public type surface.", - "type": "module", - "scripts": { - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@agentos-software/pi": "workspace:*", - "@rivet-dev/agentos": "workspace:*", - "rivetkit": "catalog:rivetkit" - }, - "devDependencies": { - "@types/node": "^22.10.2", - "typescript": "^5.7.2" - } -} diff --git a/vendor/agentos/examples/agentos-typecheck/src/index.ts b/vendor/agentos/examples/agentos-typecheck/src/index.ts deleted file mode 100644 index 34a89822..00000000 --- a/vendor/agentos/examples/agentos-typecheck/src/index.ts +++ /dev/null @@ -1,142 +0,0 @@ -/** - * Type-checking example for `@rivet-dev/agentos`. - * - * This file exercises the public actor package surface. It is not meant to - * run: the actor delegates VM operations to the AgentOS runtime and sidecar. - */ - -import pi from "@agentos-software/pi"; -import { - type AgentOSConfigInput, - type AgentOsEvents, - agentOS, - type NodeModulesMountConfig, - nodeModulesMount, - type PromptResult, - type SerializableCronJobInfo, - type SerializableCronJobOptions, - type SessionInfo, - setup, -} from "@rivet-dev/agentos"; -import { createClient } from "@rivet-dev/agentos/client"; - -const mount: NodeModulesMountConfig = nodeModulesMount( - "/abs/host/node_modules", - { - readOnly: true, - }, -); - -const config: AgentOSConfigInput = { - software: [pi], - mounts: [mount], - allowedNodeBuiltins: ["path", "fs"], - loopbackExemptPorts: [3000], - preview: { - defaultExpiresInSeconds: 3600, - maxExpiresInSeconds: 86_400, - }, - onSessionEvent: async (c, sessionId, event) => { - console.log(c.actorId, sessionId, event.type); - }, -}; - -const vm = agentOS(config); -const inputVm = agentOS< - undefined, - undefined, - undefined, - undefined, - { workspace: string } ->({ - onCreate: (_c, input) => { - console.log(input.workspace); - }, -}); -const registry = setup({ use: { vm, inputVm } }); -const client = createClient({ - endpoint: "http://localhost:6420", -}); - -type PublicDomainTypes = PromptResult | SerializableCronJobInfo | SessionInfo; -type SessionStreamEntry = AgentOsEvents["sessionEvent"]; - -function acceptPublicDomainType(value: PublicDomainTypes): PublicDomainTypes { - return value; -} - -function acceptSessionStreamEntry(event: SessionStreamEntry): SessionStreamEntry { - return event; -} - -function acceptEvent( - name: K, - payload: AgentOsEvents[K], -): AgentOsEvents[K] { - console.log(name); - return payload; -} - -const cron: SerializableCronJobOptions = { - schedule: "*/5 * * * *", - action: { type: "exec", command: "echo", args: ["tick"] }, - overlap: "skip", -}; - -async function main(): Promise { - const handle = client.vm.getOrCreate("my-agent"); - void client.vm.get("my-agent").createPreviewUrl; - void client.vm.getForId("actor-id").createPreviewUrl; - const connection = handle.connect(); - connection.on("sessionEvent", (event) => acceptSessionStreamEntry(event)); - connection.on("sessionEvent", (event) => { - if (event.sessionId === "session-1") acceptSessionStreamEntry(event); - }); - const createdHandle = await client.inputVm.create("input-agent", { - input: { workspace: "/work" }, - }); - void createdHandle.createPreviewUrl; - - const sessionId = "session-1"; - await handle.sessions.open({ - sessionId, - agent: "pi", - cwd: "/work", - permissionPolicy: "ask", - }); - const session = await handle.sessions.get({ sessionId }); - await handle.sessions.prompt({ - sessionId: "session-1", - content: [{ type: "text", text: "List the files in /work." }], - }); - await handle.cron.schedule(cron); - await handle.createPreviewUrl(3000, 300); - - acceptEvent("sessionEvent", { - durability: "ephemeral", - type: "agent_message_chunk", - sessionId: "session-1", - afterSequence: 0, - content: { type: "text", text: "Working…" }, - }); - acceptEvent("sessionEvent", { - durability: "durable", - type: "permission_request", - sessionId: "session-1", - sequence: 1, - timestamp: new Date().toISOString(), - requestId: "request-1", - toolCall: { toolCallId: "tool-1", title: "Write a file" }, - options: [ - { - optionId: "allow_once", - name: "Allow once", - kind: "allow_once", - }, - ], - }); - - acceptPublicDomainType(session); -} - -export { main }; diff --git a/vendor/agentos/examples/agentos-typecheck/tsconfig.json b/vendor/agentos/examples/agentos-typecheck/tsconfig.json deleted file mode 100644 index 4b143325..00000000 --- a/vendor/agentos/examples/agentos-typecheck/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "module": "ESNext", - "moduleResolution": "bundler", - "noEmit": true, - "types": ["node"], - "baseUrl": ".", - "paths": { - "@agentos-software/common": ["./src/software/common.ts"], - "@rivet-dev/agentos": ["../../packages/agentos/src/index.ts"], - "@rivet-dev/agentos/client": [ - "../../packages/agentos/src/client.ts" - ], - "@rivet-dev/agentos/react": ["../../packages/agentos/src/react.ts"] - } - }, - "include": ["src/**/*"], - "exclude": ["node_modules", "dist"] -} diff --git a/vendor/agentos/examples/approvals/README.md b/vendor/agentos/examples/approvals/README.md deleted file mode 100644 index 496538cc..00000000 --- a/vendor/agentos/examples/approvals/README.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: "Approvals" -description: "Handle live permission requests with auto-approve and selective-approval flows." -category: "Sessions & Permissions" -order: 3 ---- - -When an agent asks to use a tool, its ACP adapter can raise a permission request. This example shows unattended `allow_all` and interactive `ask` policies. ACP decisions are advisory; VM permissions remain the runtime security boundary. - -## How it works - -Permissions use the ordinary durable session-event stream: - -- **Automatic**: omit `permissionPolicy` or set `allow_all`. AgentOS deterministically selects an adapter-supplied allow option without emitting or persisting the request. -- **Interactive**: set `permissionPolicy: "ask"`, consume `permission_request` variants from `sessionEvent`, and call `respondPermission({ sessionId, requestId, optionId })` with an exact offered option ID. - -Subscribing to `sessionEvent` does not enable interactive approval. The policy is fixed when the session opens; if `permissionPolicy` is omitted, the default `allow_all` policy resolves the adapter request automatically and no `permission_request` event is emitted. - -The `selective` client inspects the exact native tool call and chooses an offered allow or reject option. Requests have no expiry; they remain pending until answered or terminated by prompt/session/adapter/VM lifecycle. A local `pi` software fixture stands in for a real agent package so the example runs self-contained. - -## Run it - -```bash -npm install -# Auto-approve everything server-side: -npx tsx server.ts # in one terminal -npx tsx client.ts # in another - -# Or run the auto-approve / selective variants: -npx tsx auto-approve.ts & npx tsx auto-approve-client.ts -npx tsx selective.ts & npx tsx selective-client.ts -``` - -The agent runs its prompt and each interactive request is recoverable from durable session history. Reconnecting consumers merge history with live events and deduplicate by `(sessionId, sequence)`. - -## Source - -View the source on GitHub: https://github.com/rivet-dev/agent-os/tree/main/examples/approvals diff --git a/vendor/agentos/examples/approvals/auto-approve-client.ts b/vendor/agentos/examples/approvals/auto-approve-client.ts deleted file mode 100644 index 3c461ec2..00000000 --- a/vendor/agentos/examples/approvals/auto-approve-client.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); -const agent = client.vm.getOrCreate("my-agent"); - -// allow_all selects an adapter-supplied allow option without a client round-trip. -await agent.sessions.open({ - agent: "pi", - permissionPolicy: "allow_all", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, -}); -await agent.sessions.prompt({ - content: [{ type: "text", text: "Write files as needed" }], -}); diff --git a/vendor/agentos/examples/approvals/auto-approve.ts b/vendor/agentos/examples/approvals/auto-approve.ts deleted file mode 100644 index f4628578..00000000 --- a/vendor/agentos/examples/approvals/auto-approve.ts +++ /dev/null @@ -1,9 +0,0 @@ -import pi from "@agentos-software/pi"; -import { agentOS, setup } from "@rivet-dev/agentos"; - -const vm = agentOS({ - software: [pi], -}); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/approvals/client.ts b/vendor/agentos/examples/approvals/client.ts deleted file mode 100644 index 7aef7abe..00000000 --- a/vendor/agentos/examples/approvals/client.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); -const agent = client.vm.getOrCreate("my-agent"); - -// Permission requests use the ordinary durable session-event stream. -const conn = agent.connect(); -conn.on("sessionEvent", (event) => { - if (event.type !== "permission_request") return; - const option = event.options.find( - (candidate) => candidate.kind === "allow_once", - ); - if (option) { - agent.sessions - .respondPermission({ - sessionId: event.sessionId, - requestId: event.requestId, - optionId: option.optionId, - }) - .catch((error) => console.error("Permission response failed:", error)); - } -}); - -await agent.sessions.open({ - agent: "pi", - // Required for permission_request events; the default is allow_all. - permissionPolicy: "ask", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, -}); -await agent.sessions.prompt({ - content: [{ type: "text", text: "Create /workspace/output.txt" }], -}); diff --git a/vendor/agentos/examples/approvals/human-in-the-loop.ts b/vendor/agentos/examples/approvals/human-in-the-loop.ts deleted file mode 100644 index 35ea5f06..00000000 --- a/vendor/agentos/examples/approvals/human-in-the-loop.ts +++ /dev/null @@ -1,16 +0,0 @@ -import pi from "@agentos-software/pi"; -import { agentOS, setup } from "@rivet-dev/agentos"; - -const vm = agentOS({ - software: [pi], - // This generic hook observes the same durable event union as clients. A - // connected client answers permission_request variants with respondPermission. - onSessionEvent: async (_c, sessionId, event) => { - if (event.type === "permission_request") { - console.log("permission requested:", sessionId, event.requestId); - } - }, -}); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/approvals/package.json b/vendor/agentos/examples/approvals/package.json deleted file mode 100644 index 95af0354..00000000 --- a/vendor/agentos/examples/approvals/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-approvals", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-sandbox": "workspace:*", - "sandbox-agent": "^0.4.2", - "dockerode": "^4.0.9", - "get-port": "^7.1.0", - "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", - "zod": "^4.1.11", - "@rivet-dev/agentos": "workspace:*", - "rivetkit": "catalog:rivetkit" - }, - "devDependencies": { - "@types/node": "^22.10.2", - "tsx": "^4.19.0", - "typescript": "^5.7.2" - } -} diff --git a/vendor/agentos/examples/approvals/selective-client.ts b/vendor/agentos/examples/approvals/selective-client.ts deleted file mode 100644 index e5b32689..00000000 --- a/vendor/agentos/examples/approvals/selective-client.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); -const agent = client.vm.getOrCreate("my-agent"); - -// Select exact adapter-supplied options from the generic session-event stream. -const conn = agent.connect(); -conn.on("sessionEvent", (event) => { - if (event.type !== "permission_request") return; - const toolCall = JSON.stringify(event.toolCall).toLowerCase(); - const desiredKind = toolCall.includes("read") ? "allow_once" : "reject_once"; - const option = event.options.find( - (candidate) => candidate.kind === desiredKind, - ); - if (!option) return; - agent.sessions - .respondPermission({ - sessionId: event.sessionId, - requestId: event.requestId, - optionId: option.optionId, - }) - .catch((error) => console.error("Permission response failed:", error)); -}); - -await agent.sessions.open({ - agent: "claude", - // Required for permission_request events; the default is allow_all. - permissionPolicy: "ask", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, -}); -await agent.sessions.prompt({ - content: [{ type: "text", text: "Read config.json and update it" }], -}); diff --git a/vendor/agentos/examples/approvals/selective.ts b/vendor/agentos/examples/approvals/selective.ts deleted file mode 100644 index d91cb04d..00000000 --- a/vendor/agentos/examples/approvals/selective.ts +++ /dev/null @@ -1,18 +0,0 @@ -import pi from "@agentos-software/pi"; -import { agentOS, setup } from "@rivet-dev/agentos"; - -const vm = agentOS({ - software: [pi], - onSessionEvent: async (_c, sessionId, event) => { - if (event.type === "permission_request") { - console.log( - "permission request audited server-side", - sessionId, - event.requestId, - ); - } - }, -}); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/approvals/server.ts b/vendor/agentos/examples/approvals/server.ts deleted file mode 100644 index ba01a582..00000000 --- a/vendor/agentos/examples/approvals/server.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; -import pi from "@agentos-software/pi"; - -const vm = agentOS({ - software: [pi], -}); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/approvals/tsconfig.json b/vendor/agentos/examples/approvals/tsconfig.json deleted file mode 100644 index e7937905..00000000 --- a/vendor/agentos/examples/approvals/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "moduleResolution": "bundler", "noEmit": true, "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], "types": ["node"], "baseUrl": ".", - "paths": { - "@rivet-dev/agentos": ["../../packages/agentos/src/index.ts"], - "@rivet-dev/agentos/client": ["../../packages/agentos/src/client.ts"], - "@rivet-dev/agentos/react": ["../../packages/agentos/src/react.ts"] - } - }, - "include": ["**/*.ts", "**/*.tsx"] -} diff --git a/vendor/agentos/examples/apps-ai-builder/README.md b/vendor/agentos/examples/apps-ai-builder/README.md deleted file mode 100644 index 90097560..00000000 --- a/vendor/agentos/examples/apps-ai-builder/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# agentOS Apps: AI App Builder - -This trusted host uses the Vercel AI SDK to generate a bounded three-file -RivetKit application. `deployApp()` runs the real TypeScript build in an -agentOS VM. Bounded diagnostics are fed back to the model for at most three -repairs, and a failed build never replaces the previous active release. - -Run the checked workspace example with Node.js 22 or newer: - -```sh -ANTHROPIC_API_KEY=... pnpm --dir examples/apps-ai-builder start -# In another terminal: -curl -X POST http://localhost:3000/deploy/ai-generated-app \ - -H 'content-type: application/json' \ - -d '{"prompt":"Build a collaborative counter"}' -``` - -RivetKit starts its local Engine automatically. Against an existing Rivet -deployment, use the standard Rivet connection variables instead. The successful app is mounted at -`http://localhost:3000/apps/ai-generated-app`. diff --git a/vendor/agentos/examples/apps-ai-builder/fixtures/app/package.json b/vendor/agentos/examples/apps-ai-builder/fixtures/app/package.json deleted file mode 100644 index b365b0f7..00000000 --- a/vendor/agentos/examples/apps-ai-builder/fixtures/app/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "generated-rivetkit-app", - "version": "0.0.0", - "private": true, - "type": "module", - "main": "dist/index.js", - "scripts": { - "build": "tsc", - "check-types": "tsc --noEmit" - }, - "dependencies": { - "rivetkit": "2.3.10" - }, - "devDependencies": { - "typescript": "5.7.3" - } -} diff --git a/vendor/agentos/examples/apps-ai-builder/fixtures/app/src/index.ts b/vendor/agentos/examples/apps-ai-builder/fixtures/app/src/index.ts deleted file mode 100644 index 94562d62..00000000 --- a/vendor/agentos/examples/apps-ai-builder/fixtures/app/src/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { actor, setup } from "rivetkit"; - -const generatedState = actor({ - state: { requests: 0 }, - actions: { - record(c) { - c.state.requests += 1; - return c.state.requests; - }, - }, -}); - -export const registry = setup({ - use: { generatedState }, -}); - -registry.start(); - -export default function fetch() { - return Response.json({ - message: "Replace this seed with the generated application.", - }); -} diff --git a/vendor/agentos/examples/apps-ai-builder/fixtures/app/tsconfig.json b/vendor/agentos/examples/apps-ai-builder/fixtures/app/tsconfig.json deleted file mode 100644 index eb0ab515..00000000 --- a/vendor/agentos/examples/apps-ai-builder/fixtures/app/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "lib": ["ES2022", "DOM"], - "module": "NodeNext", - "moduleResolution": "NodeNext", - "strict": true, - "outDir": "dist", - "skipLibCheck": true - }, - "include": ["src"] -} diff --git a/vendor/agentos/examples/apps-ai-builder/package.json b/vendor/agentos/examples/apps-ai-builder/package.json deleted file mode 100644 index e5e57276..00000000 --- a/vendor/agentos/examples/apps-ai-builder/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-apps-ai-builder", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "start": "node --import tsx src/server.ts", - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@ai-sdk/anthropic": "^4.0.19", - "@hono/node-server": "^2.0.11", - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-apps": "workspace:*", - "ai": "^7.0.37", - "hono": "^4.12.9", - "rivetkit": "catalog:rivetkit" - }, - "devDependencies": { - "@types/node": "^22.19.15", - "tsx": "^4.20.6", - "typescript": "^5.7.3" - } -} diff --git a/vendor/agentos/examples/apps-ai-builder/src/actors.ts b/vendor/agentos/examples/apps-ai-builder/src/actors.ts deleted file mode 100644 index 1664777e..00000000 --- a/vendor/agentos/examples/apps-ai-builder/src/actors.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { setup } from "@rivet-dev/agentos"; -import { setupApps } from "@rivet-dev/agentos-apps"; - -const { appsActors } = setupApps(); - -export const registry = setup({ - use: { - // These actors manage app deployments and scaling. - ...appsActors, - }, -}); diff --git a/vendor/agentos/examples/apps-ai-builder/src/server.ts b/vendor/agentos/examples/apps-ai-builder/src/server.ts deleted file mode 100644 index e2ef9990..00000000 --- a/vendor/agentos/examples/apps-ai-builder/src/server.ts +++ /dev/null @@ -1,132 +0,0 @@ -import { readFile } from "node:fs/promises"; -import { anthropic } from "@ai-sdk/anthropic"; -import { serve } from "@hono/node-server"; -import { - AgentOSAppsError, - appsRouter, - deployApp, -} from "@rivet-dev/agentos-apps"; -import { generateText } from "ai"; -import { Hono } from "hono"; -import { registry } from "./actors.js"; - -const editablePaths = [ - "package.json", - "tsconfig.json", - "src/index.ts", -] as const; -const maxRepairs = 3; -const maxFileBytes = 64 * 1024; - -registry.start(); - -async function loadSeed(): Promise> { - const files: Record = {}; - for (const path of editablePaths) { - files[path] = await readFile( - new URL(`../fixtures/app/${path}`, import.meta.url), - "utf8", - ); - } - return files; -} - -function parseFiles(text: string): Record { - const json = text.match(/```json\s*([\s\S]*?)```/)?.[1] ?? text; - const value = JSON.parse(json) as { files?: Record }; - if (!value.files || typeof value.files !== "object") { - throw new TypeError("model response must contain a files object"); - } - const files: Record = {}; - for (const path of editablePaths) { - const content = value.files[path]; - if (typeof content !== "string") { - throw new TypeError(`model response is missing ${path}`); - } - if (Buffer.byteLength(content) > maxFileBytes) { - throw new RangeError(`${path} exceeds ${maxFileBytes} bytes`); - } - files[path] = content; - } - return files; -} - -async function revise( - prompt: string, - files: Record, - diagnostics?: string, -): Promise> { - const result = await generateText({ - model: anthropic(process.env.AI_MODEL ?? "claude-sonnet-4-5"), - maxOutputTokens: 8_000, - prompt: [ - 'Return JSON only as {"files":{"path":"content"}}.', - `You may edit only: ${editablePaths.join(", ")}.`, - "The app must compile, start a RivetKit registry, and export a Web fetch handler.", - `User request: ${prompt}`, - diagnostics ? `Previous build diagnostics:\n${diagnostics}` : "", - `Current files:\n${JSON.stringify(files)}`, - ] - .filter(Boolean) - .join("\n\n"), - }); - return parseFiles(result.text); -} - -async function generateApp(appId: string, prompt: string) { - let files = await revise(prompt, await loadSeed()); - for (let attempt = 0; attempt <= maxRepairs; attempt += 1) { - try { - return await deployApp({ - appId, - files, - }); - } catch (error) { - const appsError = - error instanceof AgentOSAppsError || - (typeof error === "object" && - error !== null && - "code" in error && - typeof error.code === "string" && - error.code.startsWith("agentos_apps_")); - if (!appsError || attempt === maxRepairs) { - throw error; - } - const details = error as { - code: string; - message?: string; - metadata?: unknown; - }; - const diagnostics = JSON.stringify({ - code: details.code, - message: details.message ?? String(error), - metadata: details.metadata, - }).slice(0, 16 * 1024); - files = await revise(prompt, files, diagnostics); - } - } - throw new Error("unreachable"); -} - -const server = new Hono(); -// An agent or any other part of the system can call this route. A generic -// deployment endpoint could accept multipart files; this example generates the -// files from a prompt instead. -server.post("/deploy/:name", async (context) => { - const body = await context.req.json<{ prompt?: unknown }>(); - if (typeof body.prompt !== "string" || body.prompt.length > 4_000) { - return context.json( - { error: "prompt must be at most 4,000 characters" }, - 400, - ); - } - return context.json( - await generateApp(context.req.param("name"), body.prompt), - ); -}); -server.route("/apps", appsRouter); - -serve({ - fetch: server.fetch, - port: 3000, -}); diff --git a/vendor/agentos/examples/apps-ai-builder/tsconfig.json b/vendor/agentos/examples/apps-ai-builder/tsconfig.json deleted file mode 100644 index 05028f5c..00000000 --- a/vendor/agentos/examples/apps-ai-builder/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "lib": ["ES2022", "DOM"], - "module": "NodeNext", - "moduleResolution": "NodeNext", - "strict": true, - "noEmit": true, - "skipLibCheck": true - }, - "include": ["src"] -} diff --git a/vendor/agentos/examples/apps-hello-world/README.md b/vendor/agentos/examples/apps-hello-world/README.md deleted file mode 100644 index 5d5b2f88..00000000 --- a/vendor/agentos/examples/apps-hello-world/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# agentOS Apps: Hello World - -This smallest example registers the three infrastructure actors, mounts the -Apps router, and deploys generated files from a separate script. The app runs at -`http://localhost:3000/apps/hello-world/`. - -The uploaded fixture serves an HTML page at `/` and a JSON endpoint at -`/api/hello`. It does not use RivetKit because it has no durable or coordinated -state; the SQLite, workflows, and multiplayer examples add RivetKit while still -serving ordinary HTTP requests. - -Run the checked workspace example with Node.js 22 or newer: - -```sh -pnpm --dir examples/apps-hello-world start -# In another terminal: -pnpm --dir examples/apps-hello-world deploy -``` - -agentOS Apps starts its local Rivet Engine automatically. Against an existing -Rivet deployment, use the standard Rivet connection variables instead. diff --git a/vendor/agentos/examples/apps-hello-world/fixtures/app/package.json b/vendor/agentos/examples/apps-hello-world/fixtures/app/package.json deleted file mode 100644 index 29af844f..00000000 --- a/vendor/agentos/examples/apps-hello-world/fixtures/app/package.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "hello-world-app", - "version": "0.0.0", - "private": true, - "main": "src/index.ts", - "scripts": { - "check-types": "node --check src/index.mjs" - }, - "dependencies": { - "hono": "^4.12.9" - } -} diff --git a/vendor/agentos/examples/apps-hello-world/fixtures/app/src/index.ts b/vendor/agentos/examples/apps-hello-world/fixtures/app/src/index.ts deleted file mode 100644 index 2a97acf1..00000000 --- a/vendor/agentos/examples/apps-hello-world/fixtures/app/src/index.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Hono } from "hono"; - -const app = new Hono(); - -// Serve the application's frontend. -app.get("/", (c) => { - return c.html(` - - - - - Hello from agentOS Apps - - -
-

Hello from agentOS Apps

-

This HTML is served by an HTTP app running inside an agentOS VM.

-

Call the JSON API

-
- -`); -}); - -// Serve a REST API request from the same application. -app.get("/api/hello", (c) => { - return c.json({ message: "Hello from agentOS Apps" }); -}); - -export default app; diff --git a/vendor/agentos/examples/apps-hello-world/package.json b/vendor/agentos/examples/apps-hello-world/package.json deleted file mode 100644 index 6d26971b..00000000 --- a/vendor/agentos/examples/apps-hello-world/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-apps-hello-world", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "start": "node --import tsx src/server.ts", - "deploy": "node --import tsx src/deploy.ts", - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@hono/node-server": "^2.0.11", - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-apps": "workspace:*", - "hono": "^4.12.9" - }, - "devDependencies": { - "@types/node": "^22.19.15", - "tsx": "^4.20.6", - "typescript": "^5.7.3" - } -} diff --git a/vendor/agentos/examples/apps-hello-world/src/actors.ts b/vendor/agentos/examples/apps-hello-world/src/actors.ts deleted file mode 100644 index 1664777e..00000000 --- a/vendor/agentos/examples/apps-hello-world/src/actors.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { setup } from "@rivet-dev/agentos"; -import { setupApps } from "@rivet-dev/agentos-apps"; - -const { appsActors } = setupApps(); - -export const registry = setup({ - use: { - // These actors manage app deployments and scaling. - ...appsActors, - }, -}); diff --git a/vendor/agentos/examples/apps-hello-world/src/deploy.ts b/vendor/agentos/examples/apps-hello-world/src/deploy.ts deleted file mode 100644 index 472f02ee..00000000 --- a/vendor/agentos/examples/apps-hello-world/src/deploy.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { deployApp } from "@rivet-dev/agentos-apps"; - -// An agent, upload endpoint, or any other part of the system can call -// deployApp() with the files it generated. -await deployApp({ - appId: "hello-world", - files: { - "package.json": JSON.stringify({ - name: "hello-world-app", - version: "0.0.0", - private: true, - type: "module", - main: "src/index.ts", - dependencies: { - hono: "^4.12.9", - }, - }), - "src/index.ts": ` -import { Hono } from "hono"; - -const app = new Hono(); - -// Serve the application's frontend. -app.get("/", (c) => c.html("

Hello from agentOS Apps

")); - -// Serve a REST API request from the same application. -app.get("/api/hello", (c) => c.json({ message: "Hello from agentOS Apps" })); - -export default app; -`, - }, -}); diff --git a/vendor/agentos/examples/apps-hello-world/src/server.ts b/vendor/agentos/examples/apps-hello-world/src/server.ts deleted file mode 100644 index c2a5a28b..00000000 --- a/vendor/agentos/examples/apps-hello-world/src/server.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { serve } from "@hono/node-server"; -import { appsRouter } from "@rivet-dev/agentos-apps"; -import { Hono } from "hono"; -import { registry } from "./actors.js"; - -// Start the actor registry before routing applications. -registry.start(); - -const server = new Hono(); - -// Mount every deployed application at /apps/:appId. -server.route("/apps", appsRouter); - -// Serve the host router over HTTP. -serve({ - fetch: server.fetch, - port: 3000, -}); diff --git a/vendor/agentos/examples/apps-hello-world/tsconfig.json b/vendor/agentos/examples/apps-hello-world/tsconfig.json deleted file mode 100644 index 05028f5c..00000000 --- a/vendor/agentos/examples/apps-hello-world/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "lib": ["ES2022", "DOM"], - "module": "NodeNext", - "moduleResolution": "NodeNext", - "strict": true, - "noEmit": true, - "skipLibCheck": true - }, - "include": ["src"] -} diff --git a/vendor/agentos/examples/apps-multiplayer/README.md b/vendor/agentos/examples/apps-multiplayer/README.md deleted file mode 100644 index 09adde10..00000000 --- a/vendor/agentos/examples/apps-multiplayer/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# agentOS Apps: Multiplayer - -The deployed server defines keyed room actors and an HTTP handler. The separate -`src/client.ts` deploys it, connects with the returned namespace and pool, then -joins and moves through DirectActor. - -Run the checked workspace example with Node.js 22 or newer: - -```sh -pnpm --dir examples/apps-multiplayer start -# In another terminal: -pnpm --dir examples/apps-multiplayer client -``` - -RivetKit starts its local Engine automatically. Against an existing Rivet -deployment, use the standard Rivet connection variables instead. - -The deployed HTTP handler is available at -`http://localhost:3000/apps/multiplayer-room`. diff --git a/vendor/agentos/examples/apps-multiplayer/fixtures/app/package.json b/vendor/agentos/examples/apps-multiplayer/fixtures/app/package.json deleted file mode 100644 index d326a453..00000000 --- a/vendor/agentos/examples/apps-multiplayer/fixtures/app/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "multiplayer-room-app", - "version": "0.0.0", - "private": true, - "type": "module", - "main": "src/index.ts", - "scripts": { - "check-types": "node --check src/index.mjs" - }, - "dependencies": { - "rivetkit": "2.3.10" - } -} diff --git a/vendor/agentos/examples/apps-multiplayer/fixtures/app/src/index.ts b/vendor/agentos/examples/apps-multiplayer/fixtures/app/src/index.ts deleted file mode 100644 index 213a218b..00000000 --- a/vendor/agentos/examples/apps-multiplayer/fixtures/app/src/index.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { actor, event, setup } from "rivetkit"; - -type Position = { x: number; y: number }; - -const room = actor({ - state: { - players: {} as Record, - }, - events: { - changed: event(), - }, - actions: { - join(c, player: string) { - c.state.players[player] ??= { x: 0, y: 0 }; - c.broadcast("changed", c.state.players); - return c.state.players; - }, - move(c, player: string, x: number, y: number) { - c.state.players[player] = { x, y }; - c.broadcast("changed", c.state.players); - return c.state.players; - }, - inspect(c) { - return c.state.players; - }, - }, -}); - -export const registry = setup({ - use: { room }, -}); - -registry.start(); - -export default function fetch() { - return Response.json({ - app: "multiplayer-room", - message: "Use the RivetKit client to join and move in a room.", - }); -} diff --git a/vendor/agentos/examples/apps-multiplayer/package.json b/vendor/agentos/examples/apps-multiplayer/package.json deleted file mode 100644 index f103b371..00000000 --- a/vendor/agentos/examples/apps-multiplayer/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-apps-multiplayer", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "start": "node --import tsx src/server.ts", - "client": "node --import tsx src/client.ts", - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@hono/node-server": "^2.0.11", - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-apps": "workspace:*", - "hono": "^4.12.9", - "rivetkit": "catalog:rivetkit" - }, - "devDependencies": { - "@types/node": "^22.19.15", - "tsx": "^4.20.6", - "typescript": "^5.7.3" - } -} diff --git a/vendor/agentos/examples/apps-multiplayer/src/actors.ts b/vendor/agentos/examples/apps-multiplayer/src/actors.ts deleted file mode 100644 index 1664777e..00000000 --- a/vendor/agentos/examples/apps-multiplayer/src/actors.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { setup } from "@rivet-dev/agentos"; -import { setupApps } from "@rivet-dev/agentos-apps"; - -const { appsActors } = setupApps(); - -export const registry = setup({ - use: { - // These actors manage app deployments and scaling. - ...appsActors, - }, -}); diff --git a/vendor/agentos/examples/apps-multiplayer/src/client.ts b/vendor/agentos/examples/apps-multiplayer/src/client.ts deleted file mode 100644 index fd7b4305..00000000 --- a/vendor/agentos/examples/apps-multiplayer/src/client.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { Deployment } from "@rivet-dev/agentos-apps"; -import { createClient } from "rivetkit/client"; -import type { registry as appRegistry } from "../fixtures/app/src/index.js"; - -const response = await fetch("http://localhost:3000/deploy/multiplayer-room", { - method: "POST", -}); -if (!response.ok) { - throw new Error(`deployment failed: ${response.status} ${await response.text()}`); -} -const deployment = (await response.json()) as Deployment; - -const client = createClient({ - namespace: deployment.namespace, - poolName: deployment.pool, -}); - -try { - const room = client.room.getOrCreate(["lobby"]); - await room.join("alice"); - console.log(await room.move("alice", 4, 8)); -} finally { - await client.dispose(); -} diff --git a/vendor/agentos/examples/apps-multiplayer/src/server.ts b/vendor/agentos/examples/apps-multiplayer/src/server.ts deleted file mode 100644 index 751ae7ef..00000000 --- a/vendor/agentos/examples/apps-multiplayer/src/server.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { serve } from "@hono/node-server"; -import { appsRouter, deployApp } from "@rivet-dev/agentos-apps"; -import { Hono } from "hono"; -import { registry } from "./actors.js"; - -registry.start(); - -const server = new Hono(); - -// In production, an agent or any other part of the system can upload app files -// here as multipart form data. This static example deploys its checked fixture. -server.post("/deploy/:name", async (context) => { - return context.json( - await deployApp({ - appId: context.req.param("name"), - source: new URL("../fixtures/app/", import.meta.url), - }), - ); -}); - -server.route("/apps", appsRouter); - -serve({ - fetch: server.fetch, - port: 3000, -}); diff --git a/vendor/agentos/examples/apps-multiplayer/tsconfig.json b/vendor/agentos/examples/apps-multiplayer/tsconfig.json deleted file mode 100644 index 05028f5c..00000000 --- a/vendor/agentos/examples/apps-multiplayer/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "lib": ["ES2022", "DOM"], - "module": "NodeNext", - "moduleResolution": "NodeNext", - "strict": true, - "noEmit": true, - "skipLibCheck": true - }, - "include": ["src"] -} diff --git a/vendor/agentos/examples/apps-sqlite/README.md b/vendor/agentos/examples/apps-sqlite/README.md deleted file mode 100644 index 159bdf25..00000000 --- a/vendor/agentos/examples/apps-sqlite/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# agentOS Apps: SQLite - -The deployed server defines a Rivet Actor backed by SQLite and still serves -HTTP. The separate `src/client.ts` deploys it, connects with the returned -namespace and pool, and adds and lists notes through DirectActor. - -Run the checked workspace example with Node.js 22 or newer: - -```sh -pnpm --dir examples/apps-sqlite start -# In another terminal: -pnpm --dir examples/apps-sqlite client -``` - -RivetKit starts its local Engine automatically. Against an existing Rivet -deployment, use the standard Rivet connection variables instead. - -The deployed HTTP handler is available at -`http://localhost:3000/apps/sqlite-notes`. diff --git a/vendor/agentos/examples/apps-sqlite/fixtures/app/package.json b/vendor/agentos/examples/apps-sqlite/fixtures/app/package.json deleted file mode 100644 index caea9941..00000000 --- a/vendor/agentos/examples/apps-sqlite/fixtures/app/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "sqlite-notes-app", - "version": "0.0.0", - "private": true, - "type": "module", - "main": "src/index.ts", - "scripts": { - "check-types": "node --check src/index.mjs" - }, - "dependencies": { - "rivetkit": "2.3.10" - } -} diff --git a/vendor/agentos/examples/apps-sqlite/fixtures/app/src/index.ts b/vendor/agentos/examples/apps-sqlite/fixtures/app/src/index.ts deleted file mode 100644 index 7970a300..00000000 --- a/vendor/agentos/examples/apps-sqlite/fixtures/app/src/index.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { actor, setup } from "rivetkit"; -import { db } from "rivetkit/db"; - -const notes = actor({ - db: db({ - async onMigrate(database) { - await database.execute(` - CREATE TABLE IF NOT EXISTS notes ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - body TEXT NOT NULL - ) - `); - }, - }), - actions: { - async add(c, body: string) { - await c.db.execute("INSERT INTO notes (body) VALUES (?)", body); - }, - async list(c) { - return c.db.execute("SELECT id, body FROM notes ORDER BY id"); - }, - }, -}); - -export const registry = setup({ - use: { notes }, -}); - -registry.start(); - -export default function fetch() { - return Response.json({ - app: "sqlite-notes", - message: "Use the RivetKit client to add and list notes.", - }); -} diff --git a/vendor/agentos/examples/apps-sqlite/package.json b/vendor/agentos/examples/apps-sqlite/package.json deleted file mode 100644 index 959d0285..00000000 --- a/vendor/agentos/examples/apps-sqlite/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-apps-sqlite", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "start": "node --import tsx src/server.ts", - "client": "node --import tsx src/client.ts", - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@hono/node-server": "^2.0.11", - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-apps": "workspace:*", - "hono": "^4.12.9", - "rivetkit": "catalog:rivetkit" - }, - "devDependencies": { - "@types/node": "^22.19.15", - "tsx": "^4.20.6", - "typescript": "^5.7.3" - } -} diff --git a/vendor/agentos/examples/apps-sqlite/src/actors.ts b/vendor/agentos/examples/apps-sqlite/src/actors.ts deleted file mode 100644 index 1664777e..00000000 --- a/vendor/agentos/examples/apps-sqlite/src/actors.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { setup } from "@rivet-dev/agentos"; -import { setupApps } from "@rivet-dev/agentos-apps"; - -const { appsActors } = setupApps(); - -export const registry = setup({ - use: { - // These actors manage app deployments and scaling. - ...appsActors, - }, -}); diff --git a/vendor/agentos/examples/apps-sqlite/src/client.ts b/vendor/agentos/examples/apps-sqlite/src/client.ts deleted file mode 100644 index 91beafcb..00000000 --- a/vendor/agentos/examples/apps-sqlite/src/client.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { Deployment } from "@rivet-dev/agentos-apps"; -import { createClient } from "rivetkit/client"; -import type { registry as appRegistry } from "../fixtures/app/src/index.js"; - -const response = await fetch("http://localhost:3000/deploy/sqlite-notes", { - method: "POST", -}); -if (!response.ok) { - throw new Error(`deployment failed: ${response.status} ${await response.text()}`); -} -const deployment = (await response.json()) as Deployment; - -const client = createClient({ - namespace: deployment.namespace, - poolName: deployment.pool, -}); - -try { - const notes = client.notes.getOrCreate(["shared"]); - await notes.add("Hello from the RivetKit client"); - console.log(await notes.list()); -} finally { - await client.dispose(); -} diff --git a/vendor/agentos/examples/apps-sqlite/src/server.ts b/vendor/agentos/examples/apps-sqlite/src/server.ts deleted file mode 100644 index 751ae7ef..00000000 --- a/vendor/agentos/examples/apps-sqlite/src/server.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { serve } from "@hono/node-server"; -import { appsRouter, deployApp } from "@rivet-dev/agentos-apps"; -import { Hono } from "hono"; -import { registry } from "./actors.js"; - -registry.start(); - -const server = new Hono(); - -// In production, an agent or any other part of the system can upload app files -// here as multipart form data. This static example deploys its checked fixture. -server.post("/deploy/:name", async (context) => { - return context.json( - await deployApp({ - appId: context.req.param("name"), - source: new URL("../fixtures/app/", import.meta.url), - }), - ); -}); - -server.route("/apps", appsRouter); - -serve({ - fetch: server.fetch, - port: 3000, -}); diff --git a/vendor/agentos/examples/apps-sqlite/tsconfig.json b/vendor/agentos/examples/apps-sqlite/tsconfig.json deleted file mode 100644 index 05028f5c..00000000 --- a/vendor/agentos/examples/apps-sqlite/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "lib": ["ES2022", "DOM"], - "module": "NodeNext", - "moduleResolution": "NodeNext", - "strict": true, - "noEmit": true, - "skipLibCheck": true - }, - "include": ["src"] -} diff --git a/vendor/agentos/examples/apps-static-website/README.md b/vendor/agentos/examples/apps-static-website/README.md deleted file mode 100644 index e63d5405..00000000 --- a/vendor/agentos/examples/apps-static-website/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# agentOS Apps: Static Website - -A directory with `index.html` and no `package.json` is served directly. CSS, -JavaScript, SVG, and other byte assets are included in the immutable release. -A package with a build script is treated as a built static site when it emits -`dist/index.html`. - -Run the checked workspace example with Node.js 22 or newer: - -```sh -pnpm --dir examples/apps-static-website start -# In another terminal: -curl -X POST http://localhost:3000/deploy/static-website -``` - -RivetKit starts its local Engine automatically. Against an existing Rivet -deployment, use the standard Rivet connection variables instead. Open -`http://localhost:3000/apps/static-website/`. diff --git a/vendor/agentos/examples/apps-static-website/fixtures/app/app.js b/vendor/agentos/examples/apps-static-website/fixtures/app/app.js deleted file mode 100644 index 5282ceff..00000000 --- a/vendor/agentos/examples/apps-static-website/fixtures/app/app.js +++ /dev/null @@ -1,2 +0,0 @@ -document.querySelector("#status").textContent = - "Served from a warm AgentOS execution replica."; diff --git a/vendor/agentos/examples/apps-static-website/fixtures/app/index.html b/vendor/agentos/examples/apps-static-website/fixtures/app/index.html deleted file mode 100644 index 329460e9..00000000 --- a/vendor/agentos/examples/apps-static-website/fixtures/app/index.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - AgentOS Apps - - - - -

Static sites scale to zero too.

-

Loading JavaScript…

- - - diff --git a/vendor/agentos/examples/apps-static-website/fixtures/app/logo.svg b/vendor/agentos/examples/apps-static-website/fixtures/app/logo.svg deleted file mode 100644 index 0cef9946..00000000 --- a/vendor/agentos/examples/apps-static-website/fixtures/app/logo.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/vendor/agentos/examples/apps-static-website/fixtures/app/styles.css b/vendor/agentos/examples/apps-static-website/fixtures/app/styles.css deleted file mode 100644 index c9acfaa9..00000000 --- a/vendor/agentos/examples/apps-static-website/fixtures/app/styles.css +++ /dev/null @@ -1,10 +0,0 @@ -:root { - color-scheme: dark; - font: 18px/1.5 system-ui, sans-serif; -} - -body { - max-width: 42rem; - margin: 6rem auto; - padding: 0 1.5rem; -} diff --git a/vendor/agentos/examples/apps-static-website/package.json b/vendor/agentos/examples/apps-static-website/package.json deleted file mode 100644 index 71eac20c..00000000 --- a/vendor/agentos/examples/apps-static-website/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-apps-static-website", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "start": "node --import tsx src/server.ts", - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@hono/node-server": "^2.0.11", - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-apps": "workspace:*", - "hono": "^4.12.9", - "rivetkit": "catalog:rivetkit" - }, - "devDependencies": { - "@types/node": "^22.19.15", - "tsx": "^4.20.6", - "typescript": "^5.7.3" - } -} diff --git a/vendor/agentos/examples/apps-static-website/src/actors.ts b/vendor/agentos/examples/apps-static-website/src/actors.ts deleted file mode 100644 index 1664777e..00000000 --- a/vendor/agentos/examples/apps-static-website/src/actors.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { setup } from "@rivet-dev/agentos"; -import { setupApps } from "@rivet-dev/agentos-apps"; - -const { appsActors } = setupApps(); - -export const registry = setup({ - use: { - // These actors manage app deployments and scaling. - ...appsActors, - }, -}); diff --git a/vendor/agentos/examples/apps-static-website/src/server.ts b/vendor/agentos/examples/apps-static-website/src/server.ts deleted file mode 100644 index 751ae7ef..00000000 --- a/vendor/agentos/examples/apps-static-website/src/server.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { serve } from "@hono/node-server"; -import { appsRouter, deployApp } from "@rivet-dev/agentos-apps"; -import { Hono } from "hono"; -import { registry } from "./actors.js"; - -registry.start(); - -const server = new Hono(); - -// In production, an agent or any other part of the system can upload app files -// here as multipart form data. This static example deploys its checked fixture. -server.post("/deploy/:name", async (context) => { - return context.json( - await deployApp({ - appId: context.req.param("name"), - source: new URL("../fixtures/app/", import.meta.url), - }), - ); -}); - -server.route("/apps", appsRouter); - -serve({ - fetch: server.fetch, - port: 3000, -}); diff --git a/vendor/agentos/examples/apps-static-website/tsconfig.json b/vendor/agentos/examples/apps-static-website/tsconfig.json deleted file mode 100644 index 05028f5c..00000000 --- a/vendor/agentos/examples/apps-static-website/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "lib": ["ES2022", "DOM"], - "module": "NodeNext", - "moduleResolution": "NodeNext", - "strict": true, - "noEmit": true, - "skipLibCheck": true - }, - "include": ["src"] -} diff --git a/vendor/agentos/examples/apps-workflows/README.md b/vendor/agentos/examples/apps-workflows/README.md deleted file mode 100644 index 22ea82c3..00000000 --- a/vendor/agentos/examples/apps-workflows/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# agentOS Apps: Workflows - -The deployed server defines a keyed `job` actor and an HTTP handler. The -separate `src/client.ts` deploys it, connects with the returned namespace and -pool, and creates a durable workflow through DirectActor. - -Run the checked workspace example with Node.js 22 or newer: - -```sh -pnpm --dir examples/apps-workflows start -# In another terminal: -pnpm --dir examples/apps-workflows client -``` - -RivetKit starts its local Engine automatically. Against an existing Rivet -deployment, use the standard Rivet connection variables instead. The deployed -HTTP handler is available at -`http://localhost:3000/apps/durable-workflow`. diff --git a/vendor/agentos/examples/apps-workflows/fixtures/app/package.json b/vendor/agentos/examples/apps-workflows/fixtures/app/package.json deleted file mode 100644 index 203476cf..00000000 --- a/vendor/agentos/examples/apps-workflows/fixtures/app/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "durable-workflow-app", - "version": "0.0.0", - "private": true, - "type": "module", - "main": "src/index.ts", - "scripts": { - "check-types": "node --check src/index.mjs" - }, - "dependencies": { - "rivetkit": "2.3.10" - } -} diff --git a/vendor/agentos/examples/apps-workflows/fixtures/app/src/index.ts b/vendor/agentos/examples/apps-workflows/fixtures/app/src/index.ts deleted file mode 100644 index 28553b14..00000000 --- a/vendor/agentos/examples/apps-workflows/fixtures/app/src/index.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { actor, setup } from "rivetkit"; -import { workflow } from "rivetkit/workflow"; - -const job = actor({ - state: { - id: "", - status: "queued" as "queued" | "running" | "complete", - }, - onCreate(c) { - c.state.id = c.key[0] ?? ""; - }, - actions: { - inspect: (c) => c.state, - }, - run: workflow(async (workflowContext) => { - await workflowContext.step("start", async (c) => { - c.state.status = "running"; - }); - await workflowContext.sleep("work", 1_000); - await workflowContext.step("finish", async (c) => { - c.state.status = "complete"; - }); - }), -}); - -export const registry = setup({ - use: { job }, -}); - -registry.start(); - -export default function fetch() { - return Response.json({ - app: "durable-workflow", - message: "Use the RivetKit client to create and inspect jobs.", - }); -} diff --git a/vendor/agentos/examples/apps-workflows/package.json b/vendor/agentos/examples/apps-workflows/package.json deleted file mode 100644 index 8e35840d..00000000 --- a/vendor/agentos/examples/apps-workflows/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-apps-workflows", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "start": "node --import tsx src/server.ts", - "client": "node --import tsx src/client.ts", - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@hono/node-server": "^2.0.11", - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-apps": "workspace:*", - "hono": "^4.12.9", - "rivetkit": "catalog:rivetkit" - }, - "devDependencies": { - "@types/node": "^22.19.15", - "tsx": "^4.20.6", - "typescript": "^5.7.3" - } -} diff --git a/vendor/agentos/examples/apps-workflows/src/actors.ts b/vendor/agentos/examples/apps-workflows/src/actors.ts deleted file mode 100644 index 1664777e..00000000 --- a/vendor/agentos/examples/apps-workflows/src/actors.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { setup } from "@rivet-dev/agentos"; -import { setupApps } from "@rivet-dev/agentos-apps"; - -const { appsActors } = setupApps(); - -export const registry = setup({ - use: { - // These actors manage app deployments and scaling. - ...appsActors, - }, -}); diff --git a/vendor/agentos/examples/apps-workflows/src/client.ts b/vendor/agentos/examples/apps-workflows/src/client.ts deleted file mode 100644 index 8ec6aea3..00000000 --- a/vendor/agentos/examples/apps-workflows/src/client.ts +++ /dev/null @@ -1,23 +0,0 @@ -import type { Deployment } from "@rivet-dev/agentos-apps"; -import { createClient } from "rivetkit/client"; -import type { registry as appRegistry } from "../fixtures/app/src/index.js"; - -const response = await fetch("http://localhost:3000/deploy/durable-workflow", { - method: "POST", -}); -if (!response.ok) { - throw new Error(`deployment failed: ${response.status} ${await response.text()}`); -} -const deployment = (await response.json()) as Deployment; - -const client = createClient({ - namespace: deployment.namespace, - poolName: deployment.pool, -}); - -try { - const job = client.job.getOrCreate(["example-job"]); - console.log(await job.inspect()); -} finally { - await client.dispose(); -} diff --git a/vendor/agentos/examples/apps-workflows/src/server.ts b/vendor/agentos/examples/apps-workflows/src/server.ts deleted file mode 100644 index 751ae7ef..00000000 --- a/vendor/agentos/examples/apps-workflows/src/server.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { serve } from "@hono/node-server"; -import { appsRouter, deployApp } from "@rivet-dev/agentos-apps"; -import { Hono } from "hono"; -import { registry } from "./actors.js"; - -registry.start(); - -const server = new Hono(); - -// In production, an agent or any other part of the system can upload app files -// here as multipart form data. This static example deploys its checked fixture. -server.post("/deploy/:name", async (context) => { - return context.json( - await deployApp({ - appId: context.req.param("name"), - source: new URL("../fixtures/app/", import.meta.url), - }), - ); -}); - -server.route("/apps", appsRouter); - -serve({ - fetch: server.fetch, - port: 3000, -}); diff --git a/vendor/agentos/examples/apps-workflows/tsconfig.json b/vendor/agentos/examples/apps-workflows/tsconfig.json deleted file mode 100644 index 05028f5c..00000000 --- a/vendor/agentos/examples/apps-workflows/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "lib": ["ES2022", "DOM"], - "module": "NodeNext", - "moduleResolution": "NodeNext", - "strict": true, - "noEmit": true, - "skipLibCheck": true - }, - "include": ["src"] -} diff --git a/vendor/agentos/examples/authentication/README.md b/vendor/agentos/examples/authentication/README.md deleted file mode 100644 index a50d9ce9..00000000 --- a/vendor/agentos/examples/authentication/README.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: "Authentication" -description: "Validate client credentials server-side with onBeforeConnect connection hooks." -category: "Sessions & Permissions" -order: 4 ---- - -# Authentication - -Gate access to your VMs by validating client credentials on the server before any connection is established. Reach for this whenever clients must present a token (a JWT, API key, or session ID) that you verify before letting them create sessions or send prompts. - -## How it works - -The client passes credentials as connection `params` when it calls `getOrCreate`. Those params are forwarded to the server, where an `onBeforeConnect` hook inspects them and rejects the connection by throwing. Because `params` is typed as `unknown` on the wire, the hook is the real enforcement point: it checks the token's shape and validity (signature, lookup, expiry) and either returns to admit the connection or throws to deny it. Once admitted, every action on the handle runs against that authenticated connection. - -## Run it - -```bash -npm install -ANTHROPIC_API_KEY=sk-... npx tsx server.ts # in one terminal -ANTHROPIC_API_KEY=sk-... npx tsx client.ts # in another -``` - -A client with a valid `authToken` connects and lists the working directory; one with a missing or empty token is rejected before any session is created. - -## Source - -View the source on GitHub: https://github.com/rivet-dev/agent-os/tree/main/examples/authentication diff --git a/vendor/agentos/examples/authentication/client.ts b/vendor/agentos/examples/authentication/client.ts deleted file mode 100644 index e8e8349e..00000000 --- a/vendor/agentos/examples/authentication/client.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); - -// Pass credentials when connecting. They are forwarded as the connection -// params for your server-side validation hooks to check. `params` is typed as -// unknown, so the shape is not checked against the actor's ConnParams here. -const agent = client.vm.getOrCreate("my-agent", { - params: { authToken: "my-jwt-token" }, -}); - -// Actions on the handle run against the authenticated connection. -// `openSession` resolves with no value; the caller keeps the chosen session ID. -await agent.sessions.open({ - agent: "claude", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, -}); -await agent.sessions.prompt({ - content: [{ type: "text", text: "List the files in the working directory." }], -}); diff --git a/vendor/agentos/examples/authentication/package.json b/vendor/agentos/examples/authentication/package.json deleted file mode 100644 index 55ecab11..00000000 --- a/vendor/agentos/examples/authentication/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-authentication", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-sandbox": "workspace:*", - "sandbox-agent": "^0.4.2", - "dockerode": "^4.0.9", - "get-port": "^7.1.0", - "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", - "zod": "^4.1.11", - "@rivet-dev/agentos": "workspace:*", - "rivetkit": "catalog:rivetkit" - }, - "devDependencies": { - "@types/node": "^22.10.2", - "tsx": "^4.19.0", - "typescript": "^5.7.2" - } -} diff --git a/vendor/agentos/examples/authentication/server.ts b/vendor/agentos/examples/authentication/server.ts deleted file mode 100644 index 0161f4e0..00000000 --- a/vendor/agentos/examples/authentication/server.ts +++ /dev/null @@ -1,27 +0,0 @@ -import pi from "@agentos-software/pi"; -import { agentOS, setup } from "@rivet-dev/agentos"; - -// The credential shape clients pass when they connect. This documents the -// connection params; the client's params are typed as unknown, so the real -// check is the onBeforeConnect hook below. -interface ConnParams { - authToken: string; -} - -// Validate credentials server-side. onBeforeConnect receives the connection -// params and rejects the connection by throwing. Wired via the underlying Rivet -// Actor; see Actor Authentication for the full hook signatures. -export function onBeforeConnect(_c: unknown, params: ConnParams): void { - if (typeof params?.authToken !== "string" || params.authToken.length === 0) { - throw new Error("missing or invalid authToken"); - } - // verify the token (JWT signature, lookup, ...) here -} - -const vm = agentOS({ - software: [pi], - onBeforeConnect, -}); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/authentication/tsconfig.json b/vendor/agentos/examples/authentication/tsconfig.json deleted file mode 100644 index e7937905..00000000 --- a/vendor/agentos/examples/authentication/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "moduleResolution": "bundler", "noEmit": true, "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], "types": ["node"], "baseUrl": ".", - "paths": { - "@rivet-dev/agentos": ["../../packages/agentos/src/index.ts"], - "@rivet-dev/agentos/client": ["../../packages/agentos/src/client.ts"], - "@rivet-dev/agentos/react": ["../../packages/agentos/src/react.ts"] - } - }, - "include": ["**/*.ts", "**/*.tsx"] -} diff --git a/vendor/agentos/examples/browser-terminal/.gitignore b/vendor/agentos/examples/browser-terminal/.gitignore deleted file mode 100644 index ad035272..00000000 --- a/vendor/agentos/examples/browser-terminal/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -node_modules -dist -package-lock.json -*.log diff --git a/vendor/agentos/examples/browser-terminal/README.md b/vendor/agentos/examples/browser-terminal/README.md deleted file mode 100644 index 84711879..00000000 --- a/vendor/agentos/examples/browser-terminal/README.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -title: "Browser Terminal" -description: "A full xterm.js terminal in the browser for Agent OS VMs, driving PTY shells over the shipped agentOS() RivetKit actor with a VM sidebar, tabs, and reconnect." -category: "Processes & Shell" -order: 2 ---- - -A full terminal for Agent OS VMs that runs in the browser, talking to the shipped -Agent OS actor (`agentOS()` from `@rivet-dev/agentos`) over its live -[RivetKit](https://rivetkit.org) connection — no bespoke WebSocket server. - -- **Left sidebar** — a list of VMs. Each is one Agent OS VM (one RivetKit actor - instance). The VM ids are kept in `localStorage`, so reopening the page — or - clicking a VM again — reconnects to the same running VM. -- **Tabs** — each VM can have multiple terminal sessions (PTY shells). -- **Reconnect** — the actor keeps its VM (and shells) alive, so a browser that - reconnects re-adopts the running shells (by the ids it saved in `localStorage`) - and resumes their live I/O. - -## How it works - -``` -Browser (React + xterm.js) Node (server.ts) - ├─ useActor({ name:"shellVm", key }) ├─ agentOS({ software:[…] }) - ├─ terminal.open/write/resize ───────────▶│ setup({ use:{ shellVm } }) - ├─ terminal.close │ registry.start() - └─ conn.on("shellData"|"shellExit") ◀────┘ terminal.open ─▶ broadcast events -``` - -The browser opens a shell with `terminal.open`, sends keystrokes with -`terminal.write`, -and renders the ordered stdout/stderr bytes delivered by the `shellData` broadcast -**event** (routed to the right tab by `shellId`, with a small buffer for output -that arrives before a tab subscribes). `shellStderr` remains available as an -optional diagnostic tap and must not be rendered alongside `shellData`. This -mirrors the actor terminal in `packages/shell/src/actor-vm.ts`. The VM and its -shells live inside the actor's Rust plugin, so there is no server-side terminal -code here — `registry.start()` hosts the actor and the browser talks to it -directly. - -## Run - -From the repo root: - -```bash -pnpm install -pnpm --filter @rivet-dev/agentos-example-browser-terminal dev -``` - -or from this directory: - -```bash -pnpm dev # RivetKit server (:6420) + Vite (:5173) -``` - -Open http://localhost:5173, click **+ New VM**, then **+** to open a terminal and -start typing (`ls`, `echo hi | tr a-z A-Z`, `cd /tmp`, …). - -Run the pieces separately if you prefer: - -```bash -pnpm server # registry.start() on :6420 -pnpm web # Vite dev server on :5173 -``` - -Override the web→server endpoint with `VITE_AGENTOS_ENDPOINT` (default -`http://localhost:6420`). - -## Notes - -- Software: `@agentos-software/common` (provides `sh` + coreutils) plus `git`, - `curl`, `ripgrep`, `jq`, and `sqlite3`. Agent OS has no vim/editor package, so - there is no in-VM editor. -- This client predates the actor's `listShells` and `shellSnapshot` actions: it - re-adopts saved shell ids on reconnect and resumes **live** output only, so - history from before the reload is not replayed. Stale ids (VM recreated) are - dropped after a liveness probe. The dashboard Terminal tab uses the - server-owned list and server-rendered repaint instead. -- The VM shell is line-buffered (it only echoes a line on Enter), so the client - does **local echo + line editing** (printable chars, Backspace, Ctrl-C) and - suppresses the shell's own echo of the submitted line to avoid double display. diff --git a/vendor/agentos/examples/browser-terminal/index.html b/vendor/agentos/examples/browser-terminal/index.html deleted file mode 100644 index 280bbdc8..00000000 --- a/vendor/agentos/examples/browser-terminal/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - Agent OS · Browser Terminal - - -
- - - diff --git a/vendor/agentos/examples/browser-terminal/package.json b/vendor/agentos/examples/browser-terminal/package.json deleted file mode 100644 index 954ea7c5..00000000 --- a/vendor/agentos/examples/browser-terminal/package.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-browser-terminal", - "version": "0.0.1", - "private": true, - "type": "module", - "description": "Browser terminal for Agent OS VMs — RivetKit actor + xterm.js.", - "scripts": { - "server": "tsx server.ts", - "web": "vite", - "dev": "concurrently -k -n server,web -c blue,magenta \"tsx server.ts\" \"vite\"", - "build": "vite build", - "preview": "vite preview", - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@agentos-software/common": "workspace:*", - "@agentos-software/curl": "workspace:*", - "@agentos-software/git": "workspace:*", - "@agentos-software/jq": "workspace:*", - "@agentos-software/ripgrep": "workspace:*", - "@agentos-software/sqlite3": "workspace:*", - "@rivet-dev/agentos": "workspace:*", - "@rivetkit/react": "catalog:rivetkit", - "@xterm/addon-fit": "^0.10.0", - "@xterm/xterm": "^5.5.0", - "react": "^19.0.0", - "react-dom": "^19.0.0", - "rivetkit": "catalog:rivetkit" - }, - "devDependencies": { - "@types/react": "^19.0.0", - "@types/react-dom": "^19.0.0", - "@vitejs/plugin-react": "^4.3.4", - "concurrently": "^9.1.0", - "tsx": "^4.19.0", - "typescript": "^5.7.2", - "vite": "^6.0.0" - } -} diff --git a/vendor/agentos/examples/browser-terminal/server.ts b/vendor/agentos/examples/browser-terminal/server.ts deleted file mode 100644 index 6aac03e5..00000000 --- a/vendor/agentos/examples/browser-terminal/server.ts +++ /dev/null @@ -1,12 +0,0 @@ -import common from "@agentos-software/common"; -import { agentOS, setup } from "@rivet-dev/agentos"; - -// TEMP (local debug): only `common` (sha 42d8146) has valid projected packs; -// `sqlite3` (efc374f) is missing its `dist/package`, so it's dropped for now. -const shellVm = agentOS({ - software: [common], -}); - -export const registry = setup({ use: { shellVm } }); - -registry.start(); diff --git a/vendor/agentos/examples/browser-terminal/src/ActorView.tsx b/vendor/agentos/examples/browser-terminal/src/ActorView.tsx deleted file mode 100644 index aeee7547..00000000 --- a/vendor/agentos/examples/browser-terminal/src/ActorView.tsx +++ /dev/null @@ -1,258 +0,0 @@ -import { useCallback, useEffect, useRef, useState } from "react"; -import { ACTOR_NAME, useActor } from "./rivet"; -import { loadShellIds, saveShellIds } from "./store"; -import { TerminalPane } from "./TerminalPane"; - -interface Tab { - shellId: string; - title: string; -} - -interface ShellDataPayload { - shellId: string; - data: unknown; -} -interface ShellExitPayload { - shellId: string; -} - -interface TerminalActions { - open(options?: { cols?: number; rows?: number }): Promise<{ shellId: string }>; - write(shellId: string, data: string): Promise; - resize(shellId: string, cols: number, rows: number): Promise; - close(shellId: string): Promise; -} - -function terminalActions(connection: unknown): TerminalActions { - return (connection as { terminal: TerminalActions }).terminal; -} - -function toBytes(data: unknown): Uint8Array { - if (data instanceof Uint8Array) return data; - if (data instanceof ArrayBuffer) return new Uint8Array(data); - if (Array.isArray(data)) return new Uint8Array(data as number[]); - if (typeof data === "string") { - const bin = atob(data); - const bytes = new Uint8Array(bin.length); - for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i); - return bytes; - } - return new Uint8Array(); -} - -export function ActorView({ actorId }: { actorId: string }) { - const agent = useActor({ name: ACTOR_NAME, key: actorId }); - const conn = agent.connection; - - const [tabs, setTabs] = useState([]); - const [active, setActive] = useState(null); - const [busy, setBusy] = useState(false); - const [error, setError] = useState(null); - const initedRef = useRef(false); - - const writers = useRef void>>(new Map()); - const pending = useRef>(new Map()); - - const dispatchData = useCallback((shellId: string, bytes: Uint8Array) => { - const writer = writers.current.get(shellId); - if (writer) { - writer(bytes); - return; - } - const buf = pending.current.get(shellId) ?? []; - buf.push(bytes); - pending.current.set(shellId, buf); - }, []); - - const dropTab = useCallback( - (shellId: string) => { - writers.current.delete(shellId); - pending.current.delete(shellId); - setTabs((prev) => { - const next = prev.filter((t) => t.shellId !== shellId); - saveShellIds( - actorId, - next.map((t) => t.shellId), - ); - setActive((cur) => - cur === shellId ? (next[next.length - 1]?.shellId ?? null) : cur, - ); - return next; - }); - }, - [actorId], - ); - - const subscribe = useCallback( - (shellId: string) => (onData: (bytes: Uint8Array) => void) => { - writers.current.set(shellId, onData); - const buf = pending.current.get(shellId); - if (buf) { - for (const b of buf) onData(b); - pending.current.delete(shellId); - } - return () => { - writers.current.delete(shellId); - }; - }, - [], - ); - - useEffect(() => { - if (!conn) return; - const events = conn as unknown as { - on(name: string, cb: (p: never) => void): () => void; - }; - const offData = events.on("shellData", (p: ShellDataPayload) => - dispatchData(p.shellId, toBytes(p.data)), - ); - const offExit = events.on("shellExit", (p: ShellExitPayload) => - dropTab(p.shellId), - ); - return () => { - offData(); - offExit(); - }; - }, [conn, dispatchData, dropTab]); - - useEffect(() => { - if (!conn || initedRef.current) return; - initedRef.current = true; - const ids = loadShellIds(actorId); - if (ids.length === 0) return; - Promise.all( - ids.map(async (shellId) => { - try { - await terminalActions(conn).resize(shellId, 80, 24); - return shellId; - } catch { - return null; - } - }), - ) - .then((probed) => { - const live = probed.filter((id): id is string => id !== null); - saveShellIds(actorId, live); - if (live.length === 0) return; - setTabs(live.map((id, i) => ({ shellId: id, title: `shell ${i + 1}` }))); - setActive(live[0]); - }) - .catch((e: unknown) => setError(String(e))); - }, [conn, actorId]); - - useEffect(() => { - initedRef.current = false; - writers.current.clear(); - pending.current.clear(); - setTabs([]); - setActive(null); - setError(null); - }, [actorId]); - - const openTerminal = useCallback(async () => { - if (!conn) return; - setBusy(true); - setError(null); - try { - const { shellId } = await terminalActions(conn).open({ - cols: 80, - rows: 24, - }); - setTabs((prev) => { - const next = [ - ...prev, - { shellId, title: `shell ${prev.length + 1}` }, - ]; - saveShellIds( - actorId, - next.map((t) => t.shellId), - ); - return next; - }); - setActive(shellId); - } catch (e) { - setError(String(e)); - } finally { - setBusy(false); - } - }, [conn, actorId]); - - const closeTab = useCallback( - async (shellId: string) => { - dropTab(shellId); - try { - if (conn) await terminalActions(conn).close(shellId); - } catch (closeError) { - console.warn("Failed to close terminal", closeError); - } - }, - [conn, dropTab], - ); - - return ( -
-
- {tabs.map((t) => ( -
setActive(t.shellId)} - > - {t.title} - -
- ))} - - - {conn ? "connected" : "connecting…"} - -
- - {error &&
{error}
} - -
- {tabs.length === 0 && ( -
- {conn - ? "No terminals yet — click + to open one." - : "Connecting to the VM…"} -
- )} - {tabs.map((t) => ( - - conn ? terminalActions(conn).write(t.shellId, text) : undefined - } - onResize={(cols, rows) => - conn - ? terminalActions(conn).resize(t.shellId, cols, rows) - : undefined - } - subscribe={subscribe(t.shellId)} - /> - ))} -
-
- ); -} diff --git a/vendor/agentos/examples/browser-terminal/src/App.tsx b/vendor/agentos/examples/browser-terminal/src/App.tsx deleted file mode 100644 index bb5ab20b..00000000 --- a/vendor/agentos/examples/browser-terminal/src/App.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import { useEffect, useState } from "react"; -import { ActorView } from "./ActorView"; -import { type ActorEntry, createActor, loadActors, saveActors } from "./store"; - -export function App() { - const [actors, setActors] = useState(() => loadActors()); - const [selected, setSelected] = useState( - () => loadActors()[0]?.id ?? null, - ); - - useEffect(() => { - saveActors(actors); - }, [actors]); - - const addActor = () => { - setActors((prev) => { - const entry = createActor(prev); - setSelected(entry.id); - return [...prev, entry]; - }); - }; - - const removeActor = (id: string) => { - setActors((prev) => { - const next = prev.filter((a) => a.id !== id); - setSelected((cur) => (cur === id ? (next[0]?.id ?? null) : cur)); - return next; - }); - }; - - return ( -
- - -
- {selected ? ( - - ) : ( -
- Create a VM to open a terminal. -
- )} -
-
- ); -} diff --git a/vendor/agentos/examples/browser-terminal/src/TerminalPane.tsx b/vendor/agentos/examples/browser-terminal/src/TerminalPane.tsx deleted file mode 100644 index 0dbb8b04..00000000 --- a/vendor/agentos/examples/browser-terminal/src/TerminalPane.tsx +++ /dev/null @@ -1,127 +0,0 @@ -import { FitAddon } from "@xterm/addon-fit"; -import { Terminal } from "@xterm/xterm"; -import "@xterm/xterm/css/xterm.css"; -import { useEffect, useRef } from "react"; - -export interface TerminalPaneProps { - shellId: string; - active: boolean; - onInput: (text: string) => void; - onResize: (cols: number, rows: number) => void; - subscribe: (onData: (bytes: Uint8Array) => void) => () => void; -} - -export function TerminalPane(props: TerminalPaneProps) { - const { shellId, active, onInput, onResize, subscribe } = props; - const containerRef = useRef(null); - const termRef = useRef(null); - const fitRef = useRef(null); - - const onInputRef = useRef(onInput); - const onResizeRef = useRef(onResize); - const subscribeRef = useRef(subscribe); - onInputRef.current = onInput; - onResizeRef.current = onResize; - subscribeRef.current = subscribe; - - // biome-ignore lint/correctness/useExhaustiveDependencies: one-time xterm setup keyed by shellId. - useEffect(() => { - const term = new Terminal({ - convertEol: true, - cursorBlink: true, - fontFamily: - 'ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace', - fontSize: 13, - theme: { background: "#0b0e14", foreground: "#c7d0e0" }, - scrollback: 5000, - }); - const fit = new FitAddon(); - term.loadAddon(fit); - termRef.current = term; - fitRef.current = fit; - if (containerRef.current) term.open(containerRef.current); - try { - fit.fit(); - } catch {} - - let line = ""; - const encoder = new TextEncoder(); - const suppress: number[] = []; - term.onData((data) => { - for (const ch of data) { - const code = ch.codePointAt(0) ?? 0; - if (ch === "\r" || ch === "\n") { - term.write("\r\n"); - const cmd = line; - line = ""; - for (const b of encoder.encode(`${cmd}\n`)) suppress.push(b); - onInputRef.current(`${cmd}\n`); - } else if (code === 0x7f || ch === "\b") { - if (line.length > 0) { - line = line.slice(0, -1); - term.write("\b \b"); - } - } else if (code === 0x03) { - line = ""; - onInputRef.current(String.fromCharCode(3)); - } else if (code >= 0x20) { - line += ch; - term.write(ch); - } - } - }); - - const writeOutput = (bytes: Uint8Array) => { - if (suppress.length === 0) { - term.write(bytes); - return; - } - const out: number[] = []; - for (let i = 0; i < bytes.length; i++) { - const b = bytes[i]; - if (suppress.length > 0) { - if (b === suppress[0]) { - suppress.shift(); - continue; - } - if (b === 0x0d) continue; - suppress.length = 0; - } - out.push(b); - } - if (out.length > 0) term.write(new Uint8Array(out)); - }; - - term.onResize(({ cols, rows }) => onResizeRef.current(cols, rows)); - - const unsubscribe = subscribeRef.current(writeOutput); - - return () => { - unsubscribe(); - term.dispose(); - termRef.current = null; - fitRef.current = null; - }; - }, [shellId]); - - useEffect(() => { - if (!active) return; - const refit = () => { - try { - fitRef.current?.fit(); - termRef.current?.focus(); - } catch {} - }; - refit(); - window.addEventListener("resize", refit); - return () => window.removeEventListener("resize", refit); - }, [active]); - - return ( -
- ); -} diff --git a/vendor/agentos/examples/browser-terminal/src/main.tsx b/vendor/agentos/examples/browser-terminal/src/main.tsx deleted file mode 100644 index 48b762e0..00000000 --- a/vendor/agentos/examples/browser-terminal/src/main.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { createRoot } from "react-dom/client"; -import { App } from "./App"; -import "./styles.css"; - -const el = document.getElementById("root"); -if (!el) throw new Error("missing #root"); -createRoot(el).render(); diff --git a/vendor/agentos/examples/browser-terminal/src/rivet.ts b/vendor/agentos/examples/browser-terminal/src/rivet.ts deleted file mode 100644 index 65f70615..00000000 --- a/vendor/agentos/examples/browser-terminal/src/rivet.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { createRivetKit } from "@rivetkit/react"; -import type { registry } from "../server"; - -const ENDPOINT = - (import.meta.env.VITE_AGENTOS_ENDPOINT as string | undefined) ?? - "http://localhost:6420"; - -export const { useActor } = createRivetKit(ENDPOINT); - -export const ACTOR_NAME = "shellVm"; diff --git a/vendor/agentos/examples/browser-terminal/src/store.ts b/vendor/agentos/examples/browser-terminal/src/store.ts deleted file mode 100644 index 36e46ac8..00000000 --- a/vendor/agentos/examples/browser-terminal/src/store.ts +++ /dev/null @@ -1,57 +0,0 @@ -export interface ActorEntry { - id: string; - name: string; -} - -const KEY = "agentos.browser-terminal.actors"; - -export function loadActors(): ActorEntry[] { - try { - const raw = localStorage.getItem(KEY); - if (!raw) return []; - const parsed = JSON.parse(raw); - if (!Array.isArray(parsed)) return []; - return parsed.filter( - (e): e is ActorEntry => - e && typeof e.id === "string" && typeof e.name === "string", - ); - } catch { - return []; - } -} - -export function saveActors(actors: ActorEntry[]): void { - localStorage.setItem(KEY, JSON.stringify(actors)); -} - -function randomId(): string { - if (typeof crypto !== "undefined" && "randomUUID" in crypto) { - return crypto.randomUUID(); - } - return `vm-${Math.random().toString(36).slice(2, 10)}`; -} - -export function createActor(existing: ActorEntry[]): ActorEntry { - const n = existing.length + 1; - return { id: `vm-${randomId()}`, name: `VM ${n}` }; -} - -const shellsKey = (actorId: string) => - `agentos.browser-terminal.shells.${actorId}`; - -export function loadShellIds(actorId: string): string[] { - try { - const raw = localStorage.getItem(shellsKey(actorId)); - if (!raw) return []; - const parsed = JSON.parse(raw); - return Array.isArray(parsed) - ? parsed.filter((s): s is string => typeof s === "string") - : []; - } catch { - return []; - } -} - -export function saveShellIds(actorId: string, ids: string[]): void { - localStorage.setItem(shellsKey(actorId), JSON.stringify(ids)); -} diff --git a/vendor/agentos/examples/browser-terminal/src/styles.css b/vendor/agentos/examples/browser-terminal/src/styles.css deleted file mode 100644 index f0c26141..00000000 --- a/vendor/agentos/examples/browser-terminal/src/styles.css +++ /dev/null @@ -1,218 +0,0 @@ -:root { - --bg: #0b0e14; - --panel: #11151f; - --panel-2: #161b26; - --border: #232a39; - --text: #c7d0e0; - --muted: #7c869c; - --accent: #4c8dff; -} - -* { - box-sizing: border-box; -} - -html, -body, -#root { - height: 100%; - margin: 0; -} - -body { - background: var(--bg); - color: var(--text); - font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, - sans-serif; - font-size: 14px; -} - -.app { - display: flex; - height: 100%; -} - -.sidebar { - width: 240px; - flex: 0 0 240px; - background: var(--panel); - border-right: 1px solid var(--border); - display: flex; - flex-direction: column; - padding: 12px; - gap: 10px; -} - -.sidebar-header { - display: flex; - flex-direction: column; - line-height: 1.1; -} -.brand { - font-weight: 700; - font-size: 15px; -} -.brand-sub { - color: var(--muted); - font-size: 12px; -} - -.new-vm { - background: var(--accent); - color: white; - border: none; - border-radius: 6px; - padding: 8px; - cursor: pointer; - font-weight: 600; -} -.new-vm:hover { - filter: brightness(1.1); -} - -.actor-list { - flex: 1; - overflow-y: auto; - display: flex; - flex-direction: column; - gap: 6px; -} -.actor-empty, -.sidebar-foot { - color: var(--muted); - font-size: 12px; -} -.sidebar-foot { - border-top: 1px solid var(--border); - padding-top: 8px; - line-height: 1.4; -} - -.actor-item { - position: relative; - background: var(--panel-2); - border: 1px solid var(--border); - border-radius: 6px; - padding: 8px 26px 8px 10px; - cursor: pointer; -} -.actor-item:hover { - border-color: #33405a; -} -.actor-active { - border-color: var(--accent); -} -.actor-name { - font-weight: 600; -} -.actor-id { - color: var(--muted); - font-size: 11px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} -.actor-remove { - position: absolute; - top: 6px; - right: 6px; - background: transparent; - border: none; - color: var(--muted); - cursor: pointer; - font-size: 16px; - line-height: 1; -} -.actor-remove:hover { - color: #ff6b6b; -} - -.main { - flex: 1; - min-width: 0; - display: flex; - flex-direction: column; -} -.no-actor, -.empty-hint { - color: var(--muted); - padding: 24px; -} - -.actor-view { - display: flex; - flex-direction: column; - height: 100%; -} - -.tabbar { - display: flex; - align-items: center; - gap: 6px; - padding: 8px; - background: var(--panel); - border-bottom: 1px solid var(--border); - flex-wrap: wrap; -} -.tab { - display: flex; - align-items: center; - gap: 8px; - background: var(--panel-2); - border: 1px solid var(--border); - border-radius: 6px; - padding: 5px 8px; - cursor: pointer; - font-size: 13px; -} -.tab-active { - border-color: var(--accent); -} -.tab-close, -.tab-new { - background: transparent; - border: none; - color: var(--muted); - cursor: pointer; - font-size: 15px; - line-height: 1; -} -.tab-new { - border: 1px solid var(--border); - border-radius: 6px; - padding: 4px 10px; - font-size: 16px; -} -.tab-new:disabled { - opacity: 0.4; - cursor: default; -} -.tab-close:hover { - color: #ff6b6b; -} -.conn-status { - margin-left: auto; - color: var(--muted); - font-size: 12px; -} - -.error-banner { - background: #3a1113; - color: #ffb4b4; - padding: 6px 10px; - font-size: 12px; - border-bottom: 1px solid #5a1a1e; - white-space: pre-wrap; -} - -.terminals { - position: relative; - flex: 1; - min-height: 0; - background: #0b0e14; -} -.terminal-pane { - position: absolute; - inset: 0; - padding: 6px; -} diff --git a/vendor/agentos/examples/browser-terminal/src/vite-env.d.ts b/vendor/agentos/examples/browser-terminal/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2..00000000 --- a/vendor/agentos/examples/browser-terminal/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/vendor/agentos/examples/browser-terminal/tsconfig.json b/vendor/agentos/examples/browser-terminal/tsconfig.json deleted file mode 100644 index c97ccc68..00000000 --- a/vendor/agentos/examples/browser-terminal/tsconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "module": "ESNext", - "moduleResolution": "bundler", - "lib": ["ES2022", "DOM", "DOM.Iterable"], - "types": ["node"], - "jsx": "react-jsx", - "strict": true, - "skipLibCheck": true, - "noEmit": true, - "esModuleInterop": true, - "resolveJsonModule": true, - "allowImportingTsExtensions": true, - "verbatimModuleSyntax": false - }, - "include": ["server.ts", "vite.config.ts", "src"] -} diff --git a/vendor/agentos/examples/browser-terminal/vite.config.ts b/vendor/agentos/examples/browser-terminal/vite.config.ts deleted file mode 100644 index 46ec40b1..00000000 --- a/vendor/agentos/examples/browser-terminal/vite.config.ts +++ /dev/null @@ -1,9 +0,0 @@ -import react from "@vitejs/plugin-react"; -import { defineConfig } from "vite"; - -export default defineConfig({ - plugins: [react()], - server: { - port: 5173, - }, -}); diff --git a/vendor/agentos/examples/browserbase/README.md b/vendor/agentos/examples/browserbase/README.md deleted file mode 100644 index 6ec6c20c..00000000 --- a/vendor/agentos/examples/browserbase/README.md +++ /dev/null @@ -1,42 +0,0 @@ -# Browserbase example - -Read the web from an agentOS VM using the Browserbase [`browse`](https://docs.browserbase.com) CLI. - -`browse cloud fetch ` retrieves a page through the Browserbase cloud — the page is rendered by a -real browser in Browserbase's infrastructure and returned as JSON with the page content as clean -markdown, so the VM never runs a local browser and no sandbox is required. The CLI ships as the -`@agentos-software/browserbase` package and is exposed inside the VM as the `browse` command. - -`server.ts` defines the agentOS VM (with the Claude Code agent and the `browse` CLI). `client.ts` connects -to it and shows both ways to use `browse`: running the CLI yourself through the VM's process API, then -letting a Claude Code agent use it. For the agent, the server mounts the local `skills/` folder into Claude -Code's skills directory (`~/.claude/skills`). It holds the [`browse` CLI skill](https://github.com/browserbase/stagehand/tree/main/packages/cli) -that Browserbase bundles (the one `browse skills install` installs), copied verbatim, so the agent -discovers `browse` and reaches for it on its own; the prompt never mentions it. - -## Setup - -Get an API key and project id from the [Browserbase dashboard](https://www.browserbase.com/settings), then: - -```bash -export BROWSERBASE_API_KEY=bb_... -export BROWSERBASE_PROJECT_ID=... -export ANTHROPIC_API_KEY=sk-ant-... # for the Claude Code agent (client.ts only) -``` - -## Run - -Start the server, then run a client against it: - -```bash -pnpm start # start the agentOS server (server.ts) -pnpm client # run browse directly, then let a Claude Code agent use it -``` - -## Interactive browsing - -`browse`'s interactive driver commands (`browse open`, `browse snapshot`, `browse click`, …) drive a -live browser session step by step. That mode runs a local driver daemon that the in-VM runtime does -not host — for interactive, multi-step browser automation, run `browse` inside a full sandbox via -[External Sandboxes](https://rivet.dev/agentos/docs/sandboxes). The `browse cloud` commands used here need -no daemon and run directly in the VM. diff --git a/vendor/agentos/examples/browserbase/client-agent.ts b/vendor/agentos/examples/browserbase/client-agent.ts deleted file mode 100644 index 6a0e1546..00000000 --- a/vendor/agentos/examples/browserbase/client-agent.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server-minimal"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); -const agent = client.vm.getOrCreate("my-agent"); - -// The Browserbase credentials go into the session environment, so every -// command the agent runs — including `browse` — inherits them. -await agent.sessions.open({ - agent: "pi", - env: { - BROWSERBASE_API_KEY: process.env.BROWSERBASE_API_KEY!, - BROWSERBASE_PROJECT_ID: process.env.BROWSERBASE_PROJECT_ID!, - ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY!, - }, -}); - -const response = await agent.sessions.prompt({ - content: [ - { - type: "text", - text: "Run `browse cloud fetch https://example.com` and tell me in one sentence what the page is about.", - }, - ], -}); -console.log(response.message?.content ?? []); - -await agent.sessions.delete(); diff --git a/vendor/agentos/examples/browserbase/client-direct.ts b/vendor/agentos/examples/browserbase/client-direct.ts deleted file mode 100644 index dd7aec63..00000000 --- a/vendor/agentos/examples/browserbase/client-direct.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server-minimal"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); -const agent = client.vm.getOrCreate("my-agent"); - -// Drive `browse` directly through the VM's process API. `browse cloud fetch` -// retrieves a page through the Browserbase cloud and returns it as JSON with the -// page rendered as markdown. `browse` reads its credentials from the command -// environment, which we pass through `exec`. -const env = { - BROWSERBASE_API_KEY: process.env.BROWSERBASE_API_KEY!, - BROWSERBASE_PROJECT_ID: process.env.BROWSERBASE_PROJECT_ID!, -}; - -const { stdout } = await agent.process.exec("browse cloud fetch https://example.com", { - env, - output: { capture: "all" }, -}); -if (!stdout) { - throw new Error("Browserbase command returned no output"); -} - -const page = JSON.parse(stdout) as { statusCode: number; content: string }; -console.log(`fetched status ${page.statusCode}`); -console.log(page.content); diff --git a/vendor/agentos/examples/browserbase/client.ts b/vendor/agentos/examples/browserbase/client.ts deleted file mode 100644 index 6d9ac035..00000000 --- a/vendor/agentos/examples/browserbase/client.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); -const agent = client.vm.getOrCreate("my-agent"); - -// ── 1. Run the browse CLI yourself ────────────────────────────────────────── -// Drive `browse` directly through the VM's process API. `browse cloud fetch` -// retrieves a page through the Browserbase cloud and returns it as JSON with the -// page rendered as markdown. `browse` reads its credentials from the command -// environment, which we pass through `exec`. -const env = { - BROWSERBASE_API_KEY: process.env.BROWSERBASE_API_KEY!, - BROWSERBASE_PROJECT_ID: process.env.BROWSERBASE_PROJECT_ID!, -}; - -const { stdout } = await agent.process.exec("browse cloud fetch https://example.com", { - env, - output: { capture: "all" }, -}); -if (!stdout) { - throw new Error("Browserbase command returned no output"); -} - -const page = JSON.parse(stdout) as { statusCode: number; content: string }; -console.log(`fetched status ${page.statusCode}`); -console.log(page.content); - -// ── 2. Let an agent use the browse CLI ────────────────────────────────────── -// The server mounts `skills/` into Claude Code's skills directory, so the agent -// discovers Browserbase's `browse` CLI skill and reaches for it on its own. The -// Browserbase credentials go into the session environment, so every command the -// agent runs — including `browse` — inherits them. -await agent.sessions.open({ - agent: "claude", - env: { - BROWSERBASE_API_KEY: process.env.BROWSERBASE_API_KEY!, - BROWSERBASE_PROJECT_ID: process.env.BROWSERBASE_PROJECT_ID!, - ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY!, - }, -}); - -// Note: no mention of `browse` — the mounted skill tells the agent to use it. -const response = await agent.sessions.prompt({ - content: [ - { - type: "text", - text: "What is the page at https://example.com about? Answer in one sentence.", - }, - ], -}); -console.log(response.message?.content ?? []); - -await agent.sessions.delete(); diff --git a/vendor/agentos/examples/browserbase/embedded.ts b/vendor/agentos/examples/browserbase/embedded.ts deleted file mode 100644 index 63e42c01..00000000 --- a/vendor/agentos/examples/browserbase/embedded.ts +++ /dev/null @@ -1,32 +0,0 @@ -import browserbase from "@agentos-software/browserbase"; -import pi from "@agentos-software/pi"; -import { AgentOs } from "@rivet-dev/agentos-core"; - -const { ANTHROPIC_API_KEY, BROWSERBASE_API_KEY, BROWSERBASE_PROJECT_ID } = - process.env; -if (!ANTHROPIC_API_KEY || !BROWSERBASE_API_KEY || !BROWSERBASE_PROJECT_ID) { - throw new Error("Set the Anthropic and Browserbase environment variables."); -} - -const vm = await AgentOs.create({ software: [pi, browserbase] }); - -try { - await vm.sessions.open({ - agent: "pi", - env: { - ANTHROPIC_API_KEY, - BROWSERBASE_API_KEY, - BROWSERBASE_PROJECT_ID, - }, - }); - await vm.sessions.prompt({ - content: [ - { - type: "text", - text: "Use browse to summarize https://example.com.", - }, - ], - }); -} finally { - await vm.dispose(); -} diff --git a/vendor/agentos/examples/browserbase/package.json b/vendor/agentos/examples/browserbase/package.json deleted file mode 100644 index cfeb5e2c..00000000 --- a/vendor/agentos/examples/browserbase/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-browserbase", - "version": "0.1.0", - "private": true, - "type": "module", - "scripts": { - "start": "node --import tsx server.ts", - "client": "node --import tsx client.ts", - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-core": "workspace:*", - "rivetkit": "catalog:rivetkit", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/pi": "workspace:*", - "@agentos-software/browserbase": "workspace:*" - }, - "devDependencies": { - "@types/node": "^22.10.2", - "tsx": "^4.19.0", - "typescript": "^5.7.2" - } -} diff --git a/vendor/agentos/examples/browserbase/server-minimal.ts b/vendor/agentos/examples/browserbase/server-minimal.ts deleted file mode 100644 index 95db47ba..00000000 --- a/vendor/agentos/examples/browserbase/server-minimal.ts +++ /dev/null @@ -1,11 +0,0 @@ -import browserbase from "@agentos-software/browserbase"; -import pi from "@agentos-software/pi"; -import { agentOS, setup } from "@rivet-dev/agentos"; - -// `browse` is exposed inside the VM as a command on `$PATH`. -const vm = agentOS({ - software: [pi, browserbase], -}); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/browserbase/server-skills-pi.ts b/vendor/agentos/examples/browserbase/server-skills-pi.ts deleted file mode 100644 index 88065e58..00000000 --- a/vendor/agentos/examples/browserbase/server-skills-pi.ts +++ /dev/null @@ -1,21 +0,0 @@ -import browserbase from "@agentos-software/browserbase"; -import pi from "@agentos-software/pi"; -import { agentOS, setup } from "@rivet-dev/agentos"; - -// Mount the local `skills/` folder into Pi's skills directory -// (`~/.pi/agent/skills`) so the agent can discover the `browse` CLI skill. -const skillsDir = new URL("./skills", import.meta.url).pathname; - -const vm = agentOS({ - software: [pi, browserbase], - mounts: [ - { - path: "/home/agentos/.pi/agent/skills", - plugin: { id: "host_dir", config: { hostPath: skillsDir } }, - readOnly: true, - }, - ], -}); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/browserbase/server.ts b/vendor/agentos/examples/browserbase/server.ts deleted file mode 100644 index a6423fb8..00000000 --- a/vendor/agentos/examples/browserbase/server.ts +++ /dev/null @@ -1,26 +0,0 @@ -import browserbase from "@agentos-software/browserbase"; -import claude from "@agentos-software/claude-code"; -import { agentOS, setup } from "@rivet-dev/agentos"; - -// Install the `browse` CLI alongside the Claude Code agent. Because `browse` -// reaches the web through the Browserbase cloud, no local browser or sandbox is -// needed — `browse` is exposed inside the VM as a command on `$PATH`. -// -// Mount the local `skills/` folder into Claude Code's skills directory -// (`~/.claude/skills`) so the agent discovers Browserbase's `browse` CLI skill -// and reaches for it on its own, without being told to in the prompt. -const skillsDir = new URL("./skills", import.meta.url).pathname; - -const vm = agentOS({ - software: [claude, browserbase], - mounts: [ - { - path: "/home/agentos/.claude/skills", - plugin: { id: "host_dir", config: { hostPath: skillsDir } }, - readOnly: true, - }, - ], -}); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/browserbase/skills/browse/SKILL.md b/vendor/agentos/examples/browserbase/skills/browse/SKILL.md deleted file mode 100644 index 343e9757..00000000 --- a/vendor/agentos/examples/browserbase/skills/browse/SKILL.md +++ /dev/null @@ -1,368 +0,0 @@ ---- -name: browse -description: Use the browse CLI for Browserbase browser automation, Browserbase cloud APIs, Browserbase Functions, templates, web fetch/search, diagnostics, and Browse.sh skill discovery/installation. Use when the user asks to navigate pages, inspect browser state, run local or remote browser sessions, manage Browserbase resources, call Browserbase Functions, browse or scaffold Browserbase templates, fetch or search web content, diagnose browse setup, find or install a skill for a website task, discover site-specific Browse.sh skills, or install/refresh this browse skill. -compatibility: "Requires the browse CLI (`npm install -g browse`). Remote Browserbase sessions and cloud API commands require `BROWSERBASE_API_KEY`. Local mode uses Chrome/Chromium on the machine." -license: MIT -allowed-tools: Bash -metadata: - openclaw: - requires: - bins: - - browse - install: - - kind: node - package: browse - bins: [browse] - homepage: https://github.com/browserbase/stagehand/tree/main/packages/cli ---- - -# Browse CLI - -Use `browse` as the primary Browserbase command-line interface. - -It can: - -- drive a local or Browserbase-hosted browser session -- inspect pages through accessibility snapshots, screenshots, DOM/text reads, and network capture -- interact with pages by refs, selectors, XPath, keyboard, mouse, files, and viewport controls -- manage Browserbase projects, sessions, contexts, extensions, fetch, and search APIs -- develop, publish, and invoke Browserbase Functions -- browse and scaffold Browserbase templates -- diagnose local or remote browser setup issues -- discover and install Browse.sh catalog skills -- install or refresh this Browse CLI skill - -## Setup Check - -Verify the CLI exists before relying on it: - -```bash -which browse || npm install -g browse -browse --help -``` - -Install or refresh this skill with: - -```bash -browse skills install -``` - -Use `browse --help` for exact flags before running unfamiliar commands. - -## Browser Target Selection - -Browser driver commands auto-start the browse daemon when needed. Choose the browser target per command with flags: - -```bash -browse open https://example.com --local -browse open https://example.com --local --headed -browse open https://example.com --remote -browse open https://example.com --remote --verified --proxies -browse open https://example.com --auto-connect -browse open https://example.com --cdp 9222 -browse open https://example.com --cdp ws://127.0.0.1:9222/devtools/browser/ -``` - -Use local mode for development, localhost, trusted sites, and fast iteration. Use `--auto-connect` only when the user explicitly wants to attach to an already-running debuggable Chrome session with existing cookies or login state; use `--local` when no debuggable Chrome is available. Use remote mode when Browserbase credentials are available and the site needs hosted browser infrastructure, Verified browser mode, CAPTCHA solving, proxies, or session persistence. - -For a Verified and/or proxied remote session, add `--verified` and/or `--proxies` to `--remote` — a single command that keeps the Browserbase session identity, so `browse status` and `browse doctor` report the session ID and live-view URL. `--verified` requires a Browserbase Scale plan. These flags only apply to `--remote` and are sticky for the session's lifetime, like `--headed`. Reach for `browse cloud sessions create` + `--cdp` only when you need session options `open` doesn't expose (region, keep-alive, contexts). - -Choose headed/headless and local/remote mode when starting a session. A running session keeps its mode: passing a conflicting flag such as `--headed` to an already-running headless session fails until you run `browse stop --session ` or target a different session. - -Use named sessions for any non-trivial work, especially when multiple agents or parallel tasks may run at once. Every browser command accepts `--session ` (or `-s `); the `BROWSE_SESSION` env var sets the default, and commands without either share the `default` session. - -```bash -browse open https://example.com --session research --local -browse snapshot --session research -``` - -Remote browser and cloud API commands require: - -```bash -export BROWSERBASE_API_KEY=... -``` - -## Browser Automation Workflow - -Start by opening the page, then inspect state, act, and verify. - -```bash -browse open https://example.com --session research --local -browse snapshot --session research -browse click @0-5 --session research -browse type "hello" --session research -browse snapshot --session research -browse stop --session research -``` - -Prefer `browse snapshot` over screenshots for most browser work. It is structured, fast, and returns refs like `@0-5` for reliable element interaction. Use screenshots when visual layout, images, or pixel-level state matter. - -Refs are refreshed on every snapshot. After clicks, form submits, navigation, or UI re-renders, take a new snapshot before using another ref. - -## Parallel Browser Work - -Use a different `--session` value for each independent browser task. Sessions isolate tabs, cookies, refs, and daemon state; parallel tasks that omit `--session` share the `default` session and overwrite each other's active page. - -```bash -browse open https://example.com/search-a --session search-a --local -browse open https://example.com/search-b --session search-b --local -browse snapshot --session search-a -browse snapshot --session search-b -``` - -When a task is complete, stop only that task's session: - -```bash -browse stop --session search-a -``` - -## Core Browser Commands - -Navigation: - -```bash -browse open -browse reload -browse back -browse forward -browse wait load -browse wait selector "#result" -``` - -Page state: - -```bash -browse snapshot -browse snapshot --compact -browse get url -browse get title -browse get text body -browse get html "#main" -browse get value "#email" -browse get markdown body # page/element content as markdown -browse eval "document.title" # run JavaScript in the active page -browse screenshot # saves screenshot-.png, prints { "saved": "" } -browse screenshot --path page.png # choose the output path -browse screenshot --base64 # legacy: print base64 JSON to stdout (avoid in agent loops) -``` - -Interaction: - -```bash -browse click @0-5 -browse fill @0-8 "search query" -browse type "text for the focused element" -browse press Enter -browse select "select[name=country]" "United States" -browse upload @0-12 ./file.pdf -browse highlight @0-5 -browse is visible "#modal" -``` - -Mouse and viewport: - -```bash -browse mouse click 240 320 -browse mouse hover 240 320 -browse mouse drag 80 80 310 100 -browse mouse scroll 500 300 0 600 -browse viewport 1280 720 -browse cursor # show a visible cursor overlay -``` - -Tabs, network, and CDP: - -```bash -browse tab list -browse tab new https://example.com -browse tab switch -browse tab close # refuses to close the last tab -browse network on -browse network off -browse network path -browse network clear -browse cdp 9222 --pretty -``` - -Session management: - -```bash -browse doctor -browse doctor --json -browse status -browse stop -browse stop --force -``` - -Use `browse doctor` before debugging a broken browser session. Use `browse doctor --json` when another agent or CI needs structured diagnostics. - -If a page command reports that no active page is available, inspect and recover the named session: - -```bash -browse status --session research -browse tab list --session research -browse tab new https://example.com --session research -browse open https://example.com --session research -``` - -## Cloud APIs - -Use `browse cloud` for Browserbase platform APIs: - -```bash -browse cloud projects list -browse cloud projects get -browse cloud projects usage -browse cloud sessions create -browse cloud sessions create --proxies --verified -browse cloud sessions list -browse cloud sessions get -browse cloud sessions update -browse cloud sessions debug -browse cloud sessions logs -browse cloud sessions downloads get -browse cloud sessions uploads create ./file.pdf -browse cloud contexts create --name github -browse cloud contexts add github -browse cloud contexts list -browse cloud contexts get -browse cloud contexts update -browse cloud contexts delete -browse cloud extensions upload ./extension.zip -browse cloud extensions get -browse cloud extensions delete -browse cloud fetch https://example.com -browse cloud search "browser automation" -``` - -For remote sessions with context persistence: - -```bash -browse cloud sessions create --context-id --persist -``` - -Contexts persist cookies and local storage (logins) across sessions. Name a -context once with `--name` to save a local alias, then reuse the name anywhere a -context ID is accepted instead of memorizing the ID: - -```bash -browse cloud contexts create --name github # saves github -> ctx_... -browse cloud contexts add github # name a context you already have -browse cloud sessions create --context-id github --persist -browse cloud contexts list # show saved names -``` - -Use `--verified` when the task needs Browserbase Verified browser mode. To drive a Verified/proxied session directly, prefer `browse open --remote --verified --proxies` over create-then-attach — it keeps the session identity so `browse status`/`browse doctor` can report it. Use `browse cloud sessions create` for session options the driver flags don't cover (region, keep-alive, contexts, full `--stdin` body). - -Use `browse cloud fetch` when the user needs a simple HTTP fetch without browser interaction. It returns markdown-formatted page content by default; pass `--format raw` for the original response body or `--format json --schema ` for structured extraction. Use `browse cloud search` when the user asks for web search results. - -## Browserbase Functions - -Use `browse functions` to create, develop, publish, and invoke Browserbase Functions: - -```bash -browse functions init my-function -browse functions dev index.ts -browse functions publish index.ts -browse functions publish index.ts --dry-run -browse functions invoke --params '{"url":"https://example.com"}' -browse functions invoke --check-status -``` - -Functions commands use `BROWSERBASE_API_KEY`. Generated projects import `defineFn` from `@browserbasehq/sdk-functions`. - -## Templates - -Use `browse templates` to discover and scaffold Browserbase starter templates: - -```bash -browse templates list -browse templates list --tag Python --source Browserbase -browse templates find google-trends-keywords -browse templates find amazon --json -browse templates clone google-trends-keywords -browse templates clone amazon-product-scraping --language python ./my-scraper -browse templates clone dynamic-form-filling ./form-bot --language typescript -``` - -Use `browse templates find` before cloning when the exact slug is uncertain. Use `--language typescript` or `--language python` to choose the generated project runtime when a template supports both. - -## Skills - -Install or refresh this bundled CLI skill: - -```bash -browse skills install -``` - -### Discovering Browse.sh Skills - -Browse.sh (https://browse.sh) is a catalog of site-specific browser automation skills. Each skill is scoped to one task on one website and identified by a `/` slug. An installed skill encodes a proven strategy for that site — API endpoints, selectors, anti-bot handling — so it completes the task faster and more reliably than exploring the site from scratch. - -Search the catalog proactively when: - -- the user asks to complete a task on a specific website — search the domain before automating it by hand -- the user asks for a task in a common category like flights, food delivery, reviews, recipes, tickets, jobs, or shopping — search the keyword -- the user asks "is there a skill for X" or wants new capabilities - -```bash -browse skills list # browse the catalog -browse skills find # search by slug, domain, title, description, category, alias, or tag -browse skills add / # install an exact slug -``` - -### Search Strategy - -Search the domain first, then the task, then broaden: - -```bash -browse skills find yelp.com # 1. exact domain -browse skills find yelp # 2. site name -browse skills find reviews # 3. task keyword -browse skills find "restaurant reviews" # 4. multi-word query -browse skills find food --limit 5 # 5. category keyword, capped -``` - -- Querying an exact slug (`browse skills find yelp.com/extract-reviews-2ikb22`) prints a detail view with the full description and install command. -- If a search returns nothing, try synonyms (`flights` vs `travel`, `food` vs `restaurants`) before concluding no skill exists. -- Each result shows a recommended method — `api`, `fetch`, `browser`, or `hybrid` — indicating how the skill drives the site. Install counts signal which skills are proven. -- Many slugs end in a generated suffix (`-2ikb22`), so never guess or construct them. Install only with an exact slug copied from `list` or `find` output: `browse skills add yelp.com/extract-reviews-2ikb22`. The installed skill becomes available to the agent as a regular skill; a new agent session may be needed to pick it up. - -### Output Formats - -Output is a table in a terminal and JSON when piped, so agents get structured JSON by default. Force a format with `--format table|json` or `--json`. - -```bash -browse skills find food --format table --limit 10 -browse skills find food --json | jq -r '.skills[] | "\(.slug)\t\(.title)"' -``` - -JSON output includes every match with full descriptions and ignores `--limit`; `browse skills list --json` returns the entire catalog, which is large. Prefer `browse skills find ` to narrow first, or `--format table --limit ` for a compact view. - -## Best Practices - -1. Run the real command and inspect its output instead of guessing. -2. Use `browse snapshot` before interacting so you have current refs. -3. Re-run `browse snapshot` after navigation or DOM-changing actions because refs can change. -4. Prefer refs from snapshots for clicks and uploads; use selectors or XPath when refs are unavailable. -5. Use `--local` for localhost and repeatable development; use `--remote` for protected sites or Browserbase-specific behavior. -6. Use a distinct `--session ` for each parallel or long-running task; commands without the flag share the `default` session. -7. Use `--auto-connect` only when attaching to an existing debuggable local Chrome session is intended. -8. Use `browse doctor` when session startup, browser discovery, CDP attach, or Browserbase auth looks wrong. -9. Never retry a failing command unchanged. If the same command fails twice with the same error, stop — run `browse doctor --json`, then change approach (fix the key, switch `--local`/`--remote`, or `browse stop --force` and start fresh). Repeating an identical failing command will keep failing. -10. Use `browse stop` (or `browse stop --session `) when finished to clean up daemon state. -11. For unfamiliar command details, run `browse --help` and follow the exact dash-case flags. - -## Troubleshooting - -- "No active page": run `browse status --session `, then `browse open --session ` or `browse tab new --session `; use `browse stop --force` if the daemon is stale. -- Chrome not found: use `--remote` with Browserbase credentials, install Chrome, or attach with `--cdp`. -- Action fails: run `browse snapshot` and use a visible ref from the current page state. -- 401 Unauthorized on `open`, `get`, or other driver commands: a set `BROWSERBASE_API_KEY` makes `browse` default to remote mode. Fix the key at https://browserbase.com/settings, unset it, or pass `--local` to run a managed local browser (no key needed). -- Same command fails twice with the same error: stop retrying — never retry a failing command unchanged. Init failures are cached for several seconds, so instant retries return identical errors. Run `browse doctor --json`, then change approach: fix the key, switch `--local`/`--remote`, or `browse stop --force` and start fresh. -- Remote command fails: verify `BROWSERBASE_API_KEY` and inspect `browse cloud projects list`. -- Session setup is unclear: run `browse doctor` or `browse doctor --json`. -- Protected site blocks local mode: retry with `--remote`. -- `browse skills find` returns nothing: broaden the query — bare domain, then site name, then a task keyword or synonym. -- `browse skills add` fails on `npx`: install Node.js from https://nodejs.org, then rerun. -- Newly added skill is not available: it installs for future sessions; list installed skills or start a new agent session. diff --git a/vendor/agentos/examples/browserbase/tsconfig.json b/vendor/agentos/examples/browserbase/tsconfig.json deleted file mode 100644 index 78b4a00b..00000000 --- a/vendor/agentos/examples/browserbase/tsconfig.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "moduleResolution": "bundler", "noEmit": true, "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], "types": ["node"], "baseUrl": ".", - "paths": { - "@rivet-dev/agentos": ["../../packages/agentos/src/index.ts"], - "@rivet-dev/agentos-core": ["../../packages/core/src/index.ts"], - "@rivet-dev/agentos/client": ["../../packages/agentos/src/client.ts"], - "@rivet-dev/agentos/react": ["../../packages/agentos/src/react.ts"] - } - }, - "include": ["**/*.ts", "**/*.tsx"] -} diff --git a/vendor/agentos/examples/claude/README.md b/vendor/agentos/examples/claude/README.md deleted file mode 100644 index b4334bbb..00000000 --- a/vendor/agentos/examples/claude/README.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: "Claude Agent" -description: "Run the Claude Code agent in a session using an Anthropic API key." -category: "Agents" -order: 2 ---- - -Run the Claude Code agent inside a VM session and drive it with prompts. Reach for this when you want a coding agent that reads, writes, and runs commands in an isolated environment instead of calling the model API directly. - -## How it works - -The server registers a VM with the Claude Code software and starts the registry. The client calls `openSession({ agent: "claude", env: … })`, which infers the default `main` session, passes `ANTHROPIC_API_KEY` through the session env, then calls `prompt({ content })` to get the agent's response. From there you can layer on extras: drop a `SKILL.md` into `~/.claude/skills/` before opening the session and the agent discovers it automatically, or configure MCP servers in Claude Code's native `~/.claude.json` file. Pre-install local MCP servers with `exec` so first-run `npx` output does not corrupt the stdio handshake. - -## Run it - -```sh -npm install -ANTHROPIC_API_KEY=sk-ant-... npm run start -``` - -The agent answers the prompt and prints its response to the console. - -## Source - -View the source on GitHub: https://github.com/rivet-dev/agent-os/tree/main/examples/claude diff --git a/vendor/agentos/examples/claude/client.ts b/vendor/agentos/examples/claude/client.ts deleted file mode 100644 index 76c09730..00000000 --- a/vendor/agentos/examples/claude/client.ts +++ /dev/null @@ -1,149 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); -const agent = client.vm.getOrCreate("my-agent"); - -// ── Quickstart ──────────────────────────────────────────────────── -async function quickStart() { - // docs:start quickstart - await agent.sessions.open({ - agent: "claude", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - }); - - const result = await agent.sessions.prompt({ - content: [ - { type: "text", text: "What files are in the current directory?" }, - ], - }); - console.log(result.message?.content ?? []); - // docs:end quickstart -} - -// ── Skills ──────────────────────────────────────────────────────── -// -// Write a SKILL.md into the agent's skills directory before creating the -// session and the agent discovers it automatically. -async function withSkill() { - // docs:start skill - const skill = `--- -name: commit-style -description: How to write commit messages in this project. ---- - -Write commit messages in the imperative mood and keep the subject under 50 characters. -`; - - // Write the skill before creating the session - await agent.filesystem.mkdir("/home/agentos/.claude/skills/commit-style"); - await agent.filesystem.writeFile( - "/home/agentos/.claude/skills/commit-style/SKILL.md", - skill, - ); - - // Claude Code discovers the skill automatically - await agent.sessions.open({ - agent: "claude", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - }); - // docs:end skill -} - -// ── MCP servers ─────────────────────────────────────────────────── -// -// Claude Code reads its MCP server list from `~/.claude.json`. Write that file -// into the VM before creating the session — local child-process servers and -// remote URLs are both supported. -async function withMcp() { - // Pre-install the MCP server so `npx` is silent — first-run install output - // would otherwise corrupt the MCP stdio handshake ("Connection closed"). - await agent.process.exec("npm install -g @modelcontextprotocol/server-filesystem"); - - // docs:start mcp - const mcpConfig = { - mcpServers: { - filesystem: { - command: "npx", - args: [ - "-y", - "@modelcontextprotocol/server-filesystem", - "/home/agentos", - ], - }, - remote: { - type: "sse", - url: "https://mcp.example.com/sse", - headers: { Authorization: "Bearer my-token" }, - }, - }, - }; - await agent.filesystem.writeFile( - "/home/agentos/.claude.json", - JSON.stringify(mcpConfig), - ); - - await agent.sessions.open({ - agent: "claude", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - }); - // docs:end mcp -} - -// ── Skills + MCP together ───────────────────────────────────────── -async function withSkillAndMcp() { - const skill = `--- -name: commit-style -description: How to write commit messages in this project. ---- - -Write commit messages in the imperative mood and keep the subject under 50 characters. -`; - - await agent.filesystem.mkdir("/home/agentos/.claude/skills/commit-style"); - await agent.filesystem.writeFile( - "/home/agentos/.claude/skills/commit-style/SKILL.md", - skill, - ); - - // Pre-install the MCP server so `npx` is silent — first-run install output - // would otherwise corrupt the MCP stdio handshake ("Connection closed"). - await agent.process.exec("npm install -g @modelcontextprotocol/server-filesystem"); - - // Claude Code reads its MCP servers from ~/.claude.json (see `withMcp`). - const mcpConfig = { - mcpServers: { - filesystem: { - command: "npx", - args: [ - "-y", - "@modelcontextprotocol/server-filesystem", - "/home/agentos", - ], - }, - }, - }; - await agent.filesystem.writeFile( - "/home/agentos/.claude.json", - JSON.stringify(mcpConfig), - ); - - await agent.sessions.open({ - agent: "claude", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - }); - - const result = await agent.sessions.prompt({ - content: [ - { - type: "text", - text: "Stage everything and write a commit message following the project skill.", - }, - ], - }); - console.log(result.message?.content ?? []); -} - -export { quickStart, withSkill, withMcp, withSkillAndMcp }; diff --git a/vendor/agentos/examples/claude/package.json b/vendor/agentos/examples/claude/package.json deleted file mode 100644 index 9b49d802..00000000 --- a/vendor/agentos/examples/claude/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-claude", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-sandbox": "workspace:*", - "sandbox-agent": "^0.4.2", - "dockerode": "^4.0.9", - "get-port": "^7.1.0", - "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", - "zod": "^4.1.11", - "@rivet-dev/agentos": "workspace:*", - "rivetkit": "catalog:rivetkit" - }, - "devDependencies": { - "@types/node": "^22.10.2", - "tsx": "^4.19.0", - "typescript": "^5.7.2" - } -} diff --git a/vendor/agentos/examples/claude/server.ts b/vendor/agentos/examples/claude/server.ts deleted file mode 100644 index d4dc919a..00000000 --- a/vendor/agentos/examples/claude/server.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; -import claude from "@agentos-software/claude-code"; - -const vm = agentOS({ software: [claude] }); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/claude/tsconfig.json b/vendor/agentos/examples/claude/tsconfig.json deleted file mode 100644 index e7937905..00000000 --- a/vendor/agentos/examples/claude/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "moduleResolution": "bundler", "noEmit": true, "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], "types": ["node"], "baseUrl": ".", - "paths": { - "@rivet-dev/agentos": ["../../packages/agentos/src/index.ts"], - "@rivet-dev/agentos/client": ["../../packages/agentos/src/client.ts"], - "@rivet-dev/agentos/react": ["../../packages/agentos/src/react.ts"] - } - }, - "include": ["**/*.ts", "**/*.tsx"] -} diff --git a/vendor/agentos/examples/codex/README.md b/vendor/agentos/examples/codex/README.md deleted file mode 100644 index 5372e256..00000000 --- a/vendor/agentos/examples/codex/README.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: "Codex Agent" -description: "Run the Codex agent in a session using an OpenAI API key." -category: "Agents" -order: 3 ---- - -# Codex Agent - -Run OpenAI's Codex agent inside a VM session and prompt it with natural language. Reach for this when you want a coding agent that can read and act on the VM's filesystem, backed by your own OpenAI API key. - -## How it works - -Register the `codex` software with `agentOS({ software: [codex] })` so the VM knows how to launch the agent. The client calls `agent.sessions.open({ agent: "codex", ... })`, which infers the default `main` session, passes `OPENAI_API_KEY` through `env`, then drives the agent with `agent.sessions.prompt({ content })`. Two optional extensions build on the same flow: drop a `SKILL.md` into `/home/agentos/.codex/skills/` before opening the session and the agent auto-discovers it, or configure MCP servers in Codex's native config file. - -## Run it - -```bash -npm install -export OPENAI_API_KEY=sk-... -npx tsx server.ts # starts the registry on http://localhost:6420 -npx tsx client.ts # creates a Codex session and prints the agent's reply -``` - -You should see the agent describe the files in its working directory. - -## Source - -View the source on GitHub: https://github.com/rivet-dev/agent-os/tree/main/examples/codex diff --git a/vendor/agentos/examples/codex/client.ts b/vendor/agentos/examples/codex/client.ts deleted file mode 100644 index 6143777d..00000000 --- a/vendor/agentos/examples/codex/client.ts +++ /dev/null @@ -1,125 +0,0 @@ -// docs:start quickstart -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); -const agent = client.vm.getOrCreate("my-agent"); - -// ── Quickstart ──────────────────────────────────────────────────── -async function quickStart() { - await agent.sessions.open({ - agent: "codex", - env: { OPENAI_API_KEY: process.env.OPENAI_API_KEY! }, - }); - - const result = await agent.sessions.prompt({ - content: [ - { type: "text", text: "What files are in the current directory?" }, - ], - }); - console.log(result.message?.content ?? []); -} -// docs:end quickstart - -// docs:start skills -// ── Skills ──────────────────────────────────────────────────────── -// -// Write a SKILL.md into the agent's skills directory before creating the -// session and the agent discovers it automatically. -async function withSkill() { - const skill = `--- -name: commit-style -description: How to write commit messages in this project. ---- - -Write commit messages in the imperative mood and keep the subject under 50 characters. -`; - - await agent.filesystem.mkdir("/home/agentos/.codex/skills/commit-style"); - await agent.filesystem.writeFile( - "/home/agentos/.codex/skills/commit-style/SKILL.md", - skill, - ); - - await agent.sessions.open({ - agent: "codex", - env: { OPENAI_API_KEY: process.env.OPENAI_API_KEY! }, - }); -} -// docs:end skills - -// docs:start mcp -// ── MCP servers ─────────────────────────────────────────────────── -// -// Codex reads MCP servers from its own config file. Write a `config.toml` -// into the VM before creating the session — local child-process servers and -// remote URLs are both supported. -async function withMcp() { - // Pre-install the MCP server so `npx` is silent — first-run install output - // would otherwise corrupt the MCP stdio handshake ("Connection closed"). - await agent.process.exec("npm install -g @modelcontextprotocol/server-filesystem"); - - const config = `[mcp_servers.filesystem] -command = "npx" -args = ["-y", "@modelcontextprotocol/server-filesystem", "/home/agentos"] - -[mcp_servers.example] -url = "https://mcp.example.com/sse" -http_headers = { Authorization = "Bearer my-token" } -`; - - await agent.filesystem.writeFile("/home/agentos/.codex/config.toml", config); - - await agent.sessions.open({ - agent: "codex", - env: { OPENAI_API_KEY: process.env.OPENAI_API_KEY! }, - }); -} -// docs:end mcp - -// ── Skills + MCP together ───────────────────────────────────────── -async function withSkillAndMcp() { - const skill = `--- -name: commit-style -description: How to write commit messages in this project. ---- - -Write commit messages in the imperative mood and keep the subject under 50 characters. -`; - - await agent.filesystem.mkdir("/home/agentos/.codex/skills/commit-style"); - await agent.filesystem.writeFile( - "/home/agentos/.codex/skills/commit-style/SKILL.md", - skill, - ); - - // Pre-install the MCP server so `npx` is silent — first-run install output - // would otherwise corrupt the MCP stdio handshake ("Connection closed"). - await agent.process.exec("npm install -g @modelcontextprotocol/server-filesystem"); - - const config = `[mcp_servers.filesystem] -command = "npx" -args = ["-y", "@modelcontextprotocol/server-filesystem", "/home/agentos"] -`; - - await agent.filesystem.writeFile("/home/agentos/.codex/config.toml", config); - - await agent.sessions.open({ - agent: "codex", - env: { OPENAI_API_KEY: process.env.OPENAI_API_KEY! }, - }); - - const result = await agent.sessions.prompt({ - content: [ - { - type: "text", - text: "Stage everything and write a commit message following the project skill.", - }, - ], - }); - console.log(result.message?.content ?? []); -} - -export { quickStart, withSkill, withMcp, withSkillAndMcp }; diff --git a/vendor/agentos/examples/codex/package.json b/vendor/agentos/examples/codex/package.json deleted file mode 100644 index fba1f033..00000000 --- a/vendor/agentos/examples/codex/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-codex", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-sandbox": "workspace:*", - "sandbox-agent": "^0.4.2", - "dockerode": "^4.0.9", - "get-port": "^7.1.0", - "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", - "zod": "^4.1.11", - "@rivet-dev/agentos": "workspace:*", - "rivetkit": "catalog:rivetkit" - }, - "devDependencies": { - "@types/node": "^22.10.2", - "tsx": "^4.19.0", - "typescript": "^5.7.2" - } -} diff --git a/vendor/agentos/examples/codex/server.ts b/vendor/agentos/examples/codex/server.ts deleted file mode 100644 index 99e2c7f1..00000000 --- a/vendor/agentos/examples/codex/server.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; -import codex from "@agentos-software/codex"; - -const vm = agentOS({ software: [codex] }); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/codex/tsconfig.json b/vendor/agentos/examples/codex/tsconfig.json deleted file mode 100644 index e7937905..00000000 --- a/vendor/agentos/examples/codex/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "moduleResolution": "bundler", "noEmit": true, "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], "types": ["node"], "baseUrl": ".", - "paths": { - "@rivet-dev/agentos": ["../../packages/agentos/src/index.ts"], - "@rivet-dev/agentos/client": ["../../packages/agentos/src/client.ts"], - "@rivet-dev/agentos/react": ["../../packages/agentos/src/react.ts"] - } - }, - "include": ["**/*.ts", "**/*.tsx"] -} diff --git a/vendor/agentos/examples/crash-course/README.md b/vendor/agentos/examples/crash-course/README.md deleted file mode 100644 index 7ec54593..00000000 --- a/vendor/agentos/examples/crash-course/README.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: "Crash Course" -description: "Guided tour through core capabilities: sessions, filesystem, processes, networking, cron, permissions, and multiplayer." -category: "Quickstart" -order: 15 ---- - -# Crash Course - -A guided tour through the core capabilities of Agent OS, one small client per feature. Reach for it when you want to see the whole surface area — sessions, filesystem, processes, networking, cron, permissions, and multiplayer — without reading the full docs. - -## How it works - -A single `server.ts` stands up an Agent OS registry with the `pi` agent software, and each `*-client.ts` file connects to it to exercise one capability: - -- **Sessions** (`minimal-client.ts`, `sessions-client.ts`) — create a session, stream `sessionEvent`s, send prompts, and read back files the agent wrote. -- **Filesystem** (`filesystem-client.ts`) — `writeFile`, `readFile`, and recursive directory listing. -- **Processes** (`processes-client.ts`) — one-shot `exec` plus long-running `spawn` with streamed `processOutput`. -- **Networking** (`networking-client.ts`) — `httpRequest` against an in-VM service and actor-namespaced signed preview URLs. -- **Cron** (`cron-client.ts`) — schedule recurring `exec` commands and agent sessions. -- **Permissions** (`permissions-client.ts`, `permissions-server.ts`) — observe interactive permission requests through the generic session-event stream; use `permissionPolicy: "ask"` when prompting for a decision, or the default `allow_all` for unattended approval. -- **Multiplayer** (`multiplayer-client.ts`) — two clients observing the same shared agent session. -- **Agent-to-agent** (`agent-to-agent-*.ts`) lets a coder agent call a `review` host function that drives a separate reviewer agent. - -## Run it - -```bash -npm install -npx tsx server.ts # start the registry -npx tsx minimal-client.ts # then run any client in another terminal -``` - -Each client prints its results — streamed events, file contents, process output, or URLs — to the console. - -## Source - -View the source on GitHub: https://github.com/rivet-dev/agent-os/tree/main/examples/crash-course diff --git a/vendor/agentos/examples/crash-course/agent-to-agent-client.ts b/vendor/agentos/examples/crash-course/agent-to-agent-client.ts deleted file mode 100644 index 04c5ce32..00000000 --- a/vendor/agentos/examples/crash-course/agent-to-agent-client.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./agent-to-agent-server"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); -const coderAgent = client.coder.getOrCreate("feature-auth"); -await coderAgent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, -}); - -// The coder implements the feature, then calls the `review` host function itself so the -// reviewer agent reviews the code. This is true agent-to-agent: the coder drives it. -await coderAgent.sessions.prompt({ - content: [ - { - type: "text", - text: "Implement the login feature in /home/agentos/src/auth.ts, then run `agentos-review submit --path /home/agentos/src/auth.ts` to have it reviewed.", - }, - ], -}); diff --git a/vendor/agentos/examples/crash-course/agent-to-agent-server.ts b/vendor/agentos/examples/crash-course/agent-to-agent-server.ts deleted file mode 100644 index 0b304ba6..00000000 --- a/vendor/agentos/examples/crash-course/agent-to-agent-server.ts +++ /dev/null @@ -1,51 +0,0 @@ -import pi from "@agentos-software/pi"; -import { agentOS, setup } from "@rivet-dev/agentos"; -import { createClient } from "@rivet-dev/agentos/client"; -import { z } from "zod"; - -// The reviewer is its own isolated agent VM. -const reviewer = agentOS({ software: [pi] }); - -// The coder gets a `review` host-function collection it can call itself: it copies a file from the -// coder's VM into the reviewer's VM and asks the reviewer to review it. -const coder = agentOS({ - software: [pi], - hostFunctions: { - review: { - submit: { - inputSchema: z - .object({ path: z.string() }) - .describe("Submit a file path for review by the reviewer agent."), - execute: async ({ path }: { path: string }) => { - const client = createClient({ - endpoint: "http://localhost:6420", - }); - const content = await client.coder - .getOrCreate("feature-auth") - .filesystem.readFile(path); - const reviewerHandle = client.reviewer.getOrCreate("feature-auth"); - await reviewerHandle.filesystem.writeFile(path, content); - await reviewerHandle.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - }); - const result = await reviewerHandle.sessions.prompt({ - content: [ - { type: "text", text: `Review ${path} for security issues` }, - ], - }); - return { - review: - result.message?.content - .filter((block) => block.type === "text") - .map((block) => block.text) - .join("") ?? "", - }; - }, - }, - }, - }, -}); - -export const registry = setup({ use: { coder, reviewer } }); -registry.start(); diff --git a/vendor/agentos/examples/crash-course/cron-client.ts b/vendor/agentos/examples/crash-course/cron-client.ts deleted file mode 100644 index 10fb7c0f..00000000 --- a/vendor/agentos/examples/crash-course/cron-client.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ endpoint: "http://localhost:6420" }); -const agent = client.vm.getOrCreate("my-agent"); - -// Schedule a command every hour -await agent.cron.schedule({ - schedule: "0 * * * *", - action: { type: "exec", command: "rm", args: ["-rf", "/tmp/cache/*"] }, -}); - -// Schedule an agent session daily at 9 AM -await agent.cron.schedule({ - schedule: "0 9 * * *", - action: { - type: "session", - agentType: "pi", - prompt: "Review the codebase for security issues and write a report to /home/agentos/audit.md", - }, -}); diff --git a/vendor/agentos/examples/crash-course/filesystem-client.ts b/vendor/agentos/examples/crash-course/filesystem-client.ts deleted file mode 100644 index 0d200089..00000000 --- a/vendor/agentos/examples/crash-course/filesystem-client.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ endpoint: "http://localhost:6420" }); -const agent = client.vm.getOrCreate("my-agent"); - -// Write a file -await agent.filesystem.writeFile("/home/agentos/config.json", JSON.stringify({ key: "value" })); - -// Read a file -const content = await agent.filesystem.readFile("/home/agentos/config.json"); -console.log(new TextDecoder().decode(content)); - -// List directory contents recursively -const files = await agent.filesystem.readdirRecursive("/home/agentos"); -for (const entry of files) { - console.log(entry.type, entry.path); -} diff --git a/vendor/agentos/examples/crash-course/minimal-client.ts b/vendor/agentos/examples/crash-course/minimal-client.ts deleted file mode 100644 index af0e6743..00000000 --- a/vendor/agentos/examples/crash-course/minimal-client.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); -const agent = client.vm.getOrCreate("my-agent"); - -// Subscribe to streaming events -const conn = agent.connect(); -conn.on("sessionEvent", (event) => { - console.log(event); -}); - -// Create a session and send a prompt -await agent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, -}); -const response = await agent.sessions.prompt({ - content: [ - { type: "text", text: "Write a hello world script to /workspace/hello.js" }, - ], -}); -console.log(response.message?.content ?? []); - -// Read the file the agent created -const content = await agent.filesystem.readFile("/workspace/hello.js"); -console.log(new TextDecoder().decode(content)); diff --git a/vendor/agentos/examples/crash-course/multiplayer-client.ts b/vendor/agentos/examples/crash-course/multiplayer-client.ts deleted file mode 100644 index e8d7ddc1..00000000 --- a/vendor/agentos/examples/crash-course/multiplayer-client.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -// Client A: creates the session and sends prompts -const clientA = createClient({ - endpoint: "http://localhost:6420", -}); -const agentA = clientA.vm.getOrCreate("shared-agent"); -const connA = agentA.connect(); -connA.on("sessionEvent", (event) => { - console.log("[A]", event); -}); - -await agentA.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, -}); -await agentA.sessions.prompt({ - content: [{ type: "text", text: "Build a REST API" }], -}); - -// Client B: observes the same session (separate process) -const clientB = createClient({ - endpoint: "http://localhost:6420", -}); -const connB = clientB.vm.getOrCreate("shared-agent").connect(); -connB.on("sessionEvent", (event) => { - console.log("[B]", event); -}); -// Client B sees the same events as Client A diff --git a/vendor/agentos/examples/crash-course/networking-client.ts b/vendor/agentos/examples/crash-course/networking-client.ts deleted file mode 100644 index 1c46bf39..00000000 --- a/vendor/agentos/examples/crash-course/networking-client.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ endpoint: "http://localhost:6420" }); -const agent = client.vm.getOrCreate("my-agent"); - -// Fetch from a service running inside the VM -const response = await agent.network.httpRequest({ port: 3000, path: "/api/health" }); -console.log("Status:", response.status); - -// Create a preview path (port forwarding through the actor), valid for 1 hour -const preview = await agent.createPreviewUrl(3000, 3600); -console.log("Preview path:", preview.path); -console.log("Expires at:", new Date(preview.expiresAt)); diff --git a/vendor/agentos/examples/crash-course/package.json b/vendor/agentos/examples/crash-course/package.json deleted file mode 100644 index c1f9593a..00000000 --- a/vendor/agentos/examples/crash-course/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-crash-course", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { "check-types": "tsc --noEmit" }, - "dependencies": { - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-sandbox": "workspace:*", - "rivetkit": "catalog:rivetkit", - "sandbox-agent": "^0.4.2", - "dockerode": "^4.0.9", - "get-port": "^7.1.0", - "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", - "zod": "^4.1.11" - }, - "devDependencies": { "@types/node": "^22.10.2", "tsx": "^4.19.0", "typescript": "^5.7.2" } -} diff --git a/vendor/agentos/examples/crash-course/permissions-client.ts b/vendor/agentos/examples/crash-course/permissions-client.ts deleted file mode 100644 index 9fbed256..00000000 --- a/vendor/agentos/examples/crash-course/permissions-client.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ endpoint: "http://localhost:6420" }); -const agent = client.vm.getOrCreate("my-agent"); - -// Handle permission requests through the generic session event stream. -const connection = agent.connect(); -connection.on("sessionEvent", (event) => { - if (event.type !== "permission_request") return; - const option = event.options.find( - (candidate) => candidate.kind === "allow_once", - ); - if (!option) return; - agent.sessions - .respondPermission({ - sessionId: event.sessionId, - requestId: event.requestId, - optionId: option.optionId, - }) - .catch((error) => console.error("Permission response failed:", error)); -}); - -await agent.sessions.open({ - agent: "pi", - // Required for permission_request events; the default is allow_all. - permissionPolicy: "ask", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, -}); -await agent.sessions.prompt({ - content: [{ type: "text", text: "Create /workspace/output.txt" }], -}); diff --git a/vendor/agentos/examples/crash-course/permissions-server.ts b/vendor/agentos/examples/crash-course/permissions-server.ts deleted file mode 100644 index 59275465..00000000 --- a/vendor/agentos/examples/crash-course/permissions-server.ts +++ /dev/null @@ -1,15 +0,0 @@ -import pi from "@agentos-software/pi"; -import { agentOS, setup } from "@rivet-dev/agentos"; - -// Observe native ACP permission requests through the ordinary event hook. -const vm = agentOS({ - software: [pi], - onSessionEvent: async (_c, sessionId, event) => { - if (event.type === "permission_request") { - console.log("Permission requested", sessionId, event.requestId); - } - }, -}); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/crash-course/processes-client.ts b/vendor/agentos/examples/crash-course/processes-client.ts deleted file mode 100644 index a1ec6eb9..00000000 --- a/vendor/agentos/examples/crash-course/processes-client.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ endpoint: "http://localhost:6420" }); -const agent = client.vm.getOrCreate("my-agent"); - -// One-shot execution -const result = await agent.process.exec("echo hello && ls /home/agentos"); -console.log("stdout:", result.stdout); -console.log("exit code:", result.exitCode); - -// Spawn a long-running process -const conn = agent.connect(); -const { pid } = await agent.process.spawn("node", ["server.js"]); -conn.on("processOutput", (data) => { - if (data.pid !== pid) return; - console.log(`[pid ${data.pid}]`, new TextDecoder().decode(data.data)); -}); - -console.log("Process ID:", pid); diff --git a/vendor/agentos/examples/crash-course/sandbox-stubs.d.ts b/vendor/agentos/examples/crash-course/sandbox-stubs.d.ts deleted file mode 100644 index 1ae6d863..00000000 --- a/vendor/agentos/examples/crash-course/sandbox-stubs.d.ts +++ /dev/null @@ -1,58 +0,0 @@ -/** - * Local ambient stubs for this example only. - * - * The sandbox integration ships as `@rivet-dev/agentos-sandbox`, which depends on - * the third-party `sandbox-agent` package. Their runtimes pull native/Docker - * deps, so these declarations model just enough of the public surface for the - * sandbox example to type-check. Remove once the packages are installed here. - * - * Real packages and exports: - * - `@rivet-dev/agentos-sandbox` -> `createSandboxFs`, `createSandboxHostFunctions` - * - `sandbox-agent` -> `SandboxAgent` - * - `sandbox-agent/docker` -> `docker` - */ - -declare module "sandbox-agent" { - export class SandboxAgent { - static start(options: { sandbox: unknown }): Promise; - dispose(): Promise; - } -} - -declare module "sandbox-agent/docker" { - export function docker(options?: unknown): unknown; -} - -declare module "@rivet-dev/agentos-sandbox" { - import type { - HostFunctionCollection, - NativeMountPluginDescriptor, - } from "@rivet-dev/agentos"; - import type { SandboxAgent } from "sandbox-agent"; - - export interface SandboxFsOptions { - /** A connected SandboxAgent client instance. */ - client: SandboxAgent; - /** Base path to scope all operations under. Defaults to "/". */ - basePath?: string; - /** Per-request timeout for sandbox-agent HTTP calls. */ - timeoutMs?: number; - /** Maximum file size allowed for buffered pread/truncate fallbacks. */ - maxFullReadBytes?: number; - } - export interface SandboxHostFunctionsOptions { - /** A connected SandboxAgent client instance. */ - client: SandboxAgent; - } - /** - * Build the mount plugin descriptor that projects the sandbox filesystem into - * the VM. Use it as the `plugin` of a `{ path, plugin }` mount entry. - */ - export function createSandboxFs( - options: SandboxFsOptions, - ): NativeMountPluginDescriptor; - /** Build a host-function collection that exposes the sandbox's process management. */ - export function createSandboxHostFunctions( - options: SandboxHostFunctionsOptions, - ): HostFunctionCollection; -} diff --git a/vendor/agentos/examples/crash-course/sandbox.ts b/vendor/agentos/examples/crash-course/sandbox.ts deleted file mode 100644 index 5bda4968..00000000 --- a/vendor/agentos/examples/crash-course/sandbox.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; -import { - createSandboxFs, - createSandboxHostFunctions, -} from "@rivet-dev/agentos-sandbox"; -import { SandboxAgent } from "sandbox-agent"; -import { docker } from "sandbox-agent/docker"; - -const sandbox = await SandboxAgent.start({ sandbox: docker() }); - -const vm = agentOS({ - // Host functions let the agent control the sandbox. - hostFunctions: { sandbox: createSandboxHostFunctions({ client: sandbox }) }, - // Mounts let the agent read the sandbox filesystem (optional) - mounts: [ - { - path: "/home/agentos/sandbox", - plugin: createSandboxFs({ client: sandbox }), - }, - ], -}); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/crash-course/server.ts b/vendor/agentos/examples/crash-course/server.ts deleted file mode 100644 index ba01a582..00000000 --- a/vendor/agentos/examples/crash-course/server.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; -import pi from "@agentos-software/pi"; - -const vm = agentOS({ - software: [pi], -}); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/crash-course/sessions-client.ts b/vendor/agentos/examples/crash-course/sessions-client.ts deleted file mode 100644 index 20aff3a7..00000000 --- a/vendor/agentos/examples/crash-course/sessions-client.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); -const agent = client.vm.getOrCreate("my-agent"); - -// Stream events as they arrive -const conn = agent.connect(); -conn.on("sessionEvent", (event) => { - console.log(event); -}); - -// Create a session -await agent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, -}); - -// Send a prompt and wait for the response -const response = await agent.sessions.prompt({ - content: [{ type: "text", text: "List all files in the home directory" }], -}); -console.log(response.message?.content ?? []); diff --git a/vendor/agentos/examples/crash-course/tsconfig.json b/vendor/agentos/examples/crash-course/tsconfig.json deleted file mode 100644 index e7937905..00000000 --- a/vendor/agentos/examples/crash-course/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "moduleResolution": "bundler", "noEmit": true, "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], "types": ["node"], "baseUrl": ".", - "paths": { - "@rivet-dev/agentos": ["../../packages/agentos/src/index.ts"], - "@rivet-dev/agentos/client": ["../../packages/agentos/src/client.ts"], - "@rivet-dev/agentos/react": ["../../packages/agentos/src/react.ts"] - } - }, - "include": ["**/*.ts", "**/*.tsx"] -} diff --git a/vendor/agentos/examples/crash-course/workflows.ts b/vendor/agentos/examples/crash-course/workflows.ts deleted file mode 100644 index 928076c4..00000000 --- a/vendor/agentos/examples/crash-course/workflows.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; -import pi from "@agentos-software/pi"; -import { actor } from "rivetkit"; -import { workflow } from "rivetkit/workflow"; - -const vm = agentOS({ software: [pi] }); - -// Each created actor is one durable workflow run. The run input lives in state, -// so no application queue is needed; AgentOS serializes prompts per session. -const bugFixer = actor({ - state: { - repo: "", - issue: "", - status: "running" as "running" | "complete", - }, - onCreate: (c, input: { repo: string; issue: string }) => { - c.state.repo = input.repo; - c.state.issue = input.issue; - }, - run: workflow(async (ctx) => { - await ctx.step("clone-repo", (step) => - step - .client() - .vm.getOrCreate("bug-fixer") - .process.exec(`git clone ${step.state.repo} /home/agentos/repo`), - ); - - await ctx.step("fix-bug", async (step) => { - const agent = step - .client() - .vm.getOrCreate("bug-fixer"); - await agent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - }); - await agent.sessions.prompt({ - content: [ - { type: "text", text: `Fix the bug in issue: ${step.state.issue}` }, - ], - }); - }); - - await ctx.step("run-tests", (step) => - step - .client() - .vm.getOrCreate("bug-fixer") - .process.exec("cd /home/agentos/repo && npm test"), - ); - await ctx.step("complete", async (step) => { - step.state.status = "complete"; - }); - }), -}); - -export const registry = setup({ use: { vm, bugFixer } }); -registry.start(); diff --git a/vendor/agentos/examples/cron/README.md b/vendor/agentos/examples/cron/README.md deleted file mode 100644 index f704a969..00000000 --- a/vendor/agentos/examples/cron/README.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: "Cron" -description: "Schedule recurring commands and agent sessions with cron, including overlap handling, monitoring, and cancellation." -category: "Orchestration" -order: 1 ---- - -Run work on a schedule inside a VM — a shell command on a fixed interval, or a recurring agent session that reviews logs or triages issues. Reach for this when you need background jobs that fire on a cron expression instead of on demand. - -## How it works - -Each VM handle exposes `scheduleCron({ schedule, action, overlap })`. The `schedule` is a standard cron expression, and the `action` is either an `exec` (run a command with args) or a `session` (spawn an agent of a given `agentType` with a `prompt`). The `overlap` policy decides what happens when a run is still going when the next tick arrives. Scheduling returns a job `id` you can later pass to `cancelCronJob`, and `listCronJobs` enumerates everything registered on the VM. Subscribe to the native `cronEvent` event on a connection to monitor each run; timestamps are ISO strings in both events and job metadata. - -## Run it - -```sh -npm install -npx tsx server.ts # start the registry, then run any example, e.g. npx tsx schedule-session.ts -``` - -You should see the cron job registered and its `id` printed; scheduled runs fire on their interval and surface as `cronEvent`s. - -## Source - -View the source on GitHub: https://github.com/rivet-dev/agent-os/tree/main/examples/cron diff --git a/vendor/agentos/examples/cron/heartbeat.ts b/vendor/agentos/examples/cron/heartbeat.ts deleted file mode 100644 index 869e22cd..00000000 --- a/vendor/agentos/examples/cron/heartbeat.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ endpoint: "http://localhost:6420" }); -const handle = client.vm.getOrCreate("my-agent"); - -// docs:start heartbeat -await handle.cron.schedule({ - schedule: "*/30 * * * *", - overlap: "skip", - action: { - type: "session", - agentType: "pi", - prompt: "Check the status of open issues and take any necessary action", - }, -}); -// docs:end heartbeat diff --git a/vendor/agentos/examples/cron/list-cancel.ts b/vendor/agentos/examples/cron/list-cancel.ts deleted file mode 100644 index ed9c1b6a..00000000 --- a/vendor/agentos/examples/cron/list-cancel.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ endpoint: "http://localhost:6420" }); -const handle = client.vm.getOrCreate("my-agent"); - -// List all cron jobs -const jobs = await handle.cron.list(); -for (const job of jobs) { - console.log(job.id, job.schedule); -} - -// Cancel a specific job -await handle.cron.cancel(jobs[0].id); diff --git a/vendor/agentos/examples/cron/monitor.ts b/vendor/agentos/examples/cron/monitor.ts deleted file mode 100644 index c8718c7e..00000000 --- a/vendor/agentos/examples/cron/monitor.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ endpoint: "http://localhost:6420" }); -const handle = client.vm.getOrCreate("my-agent"); - -// docs:start subscribe -const conn = handle.connect(); -conn.on("cronEvent", (event) => { - console.log("Cron event:", event); -}); -// docs:end subscribe - -await handle.cron.schedule({ - schedule: "*/1 * * * *", - action: { type: "exec", command: "echo", args: ["heartbeat"] }, -}); diff --git a/vendor/agentos/examples/cron/overlap.ts b/vendor/agentos/examples/cron/overlap.ts deleted file mode 100644 index 9687d2dd..00000000 --- a/vendor/agentos/examples/cron/overlap.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ endpoint: "http://localhost:6420" }); - -// Queue overlapping executions -await client.vm.getOrCreate("my-agent").cron.schedule({ - schedule: "*/5 * * * *", - overlap: "queue", - action: { - type: "session", - agentType: "pi", - prompt: "Process the next batch of tasks", - }, -}); diff --git a/vendor/agentos/examples/cron/package.json b/vendor/agentos/examples/cron/package.json deleted file mode 100644 index d2a1f539..00000000 --- a/vendor/agentos/examples/cron/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-cron", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-sandbox": "workspace:*", - "sandbox-agent": "^0.4.2", - "dockerode": "^4.0.9", - "get-port": "^7.1.0", - "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", - "zod": "^4.1.11", - "@rivet-dev/agentos": "workspace:*", - "rivetkit": "catalog:rivetkit" - }, - "devDependencies": { - "@types/node": "^22.10.2", - "tsx": "^4.19.0", - "typescript": "^5.7.2" - } -} diff --git a/vendor/agentos/examples/cron/schedule-command.ts b/vendor/agentos/examples/cron/schedule-command.ts deleted file mode 100644 index af1daa6b..00000000 --- a/vendor/agentos/examples/cron/schedule-command.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ endpoint: "http://localhost:6420" }); - -// Schedule a cleanup script every hour -const { id } = await client.vm.getOrCreate("my-agent").cron.schedule({ - schedule: "0 * * * *", - action: { - type: "exec", - command: "rm", - args: ["-rf", "/tmp/cache/*"], - }, -}); -console.log("Cron job ID:", id); diff --git a/vendor/agentos/examples/cron/schedule-session.ts b/vendor/agentos/examples/cron/schedule-session.ts deleted file mode 100644 index a38a6950..00000000 --- a/vendor/agentos/examples/cron/schedule-session.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ endpoint: "http://localhost:6420" }); - -// Run an agent every day at 9 AM to check for issues -await client.vm.getOrCreate("my-agent").cron.schedule({ - schedule: "0 9 * * *", - action: { - type: "session", - agentType: "pi", - prompt: "Review the logs in /workspace/logs/ and summarize any errors", - cwd: "/workspace", - }, -}); diff --git a/vendor/agentos/examples/cron/server.ts b/vendor/agentos/examples/cron/server.ts deleted file mode 100644 index ba01a582..00000000 --- a/vendor/agentos/examples/cron/server.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; -import pi from "@agentos-software/pi"; - -const vm = agentOS({ - software: [pi], -}); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/cron/tsconfig.json b/vendor/agentos/examples/cron/tsconfig.json deleted file mode 100644 index e7937905..00000000 --- a/vendor/agentos/examples/cron/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "moduleResolution": "bundler", "noEmit": true, "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], "types": ["node"], "baseUrl": ".", - "paths": { - "@rivet-dev/agentos": ["../../packages/agentos/src/index.ts"], - "@rivet-dev/agentos/client": ["../../packages/agentos/src/client.ts"], - "@rivet-dev/agentos/react": ["../../packages/agentos/src/react.ts"] - } - }, - "include": ["**/*.ts", "**/*.tsx"] -} diff --git a/vendor/agentos/examples/custom/opencode.ts b/vendor/agentos/examples/custom/opencode.ts deleted file mode 100644 index 3813eb88..00000000 --- a/vendor/agentos/examples/custom/opencode.ts +++ /dev/null @@ -1,6 +0,0 @@ -import opencode from "@agentos-software/opencode"; - -// OpenCode *is* the ACP process: it speaks ACP on stdio itself, so there is no -// separate adapter to spawn the agent. The published @agentos-software/opencode -// descriptor already encodes the right entrypoint and env, so use it as-is. -export default opencode; diff --git a/vendor/agentos/examples/custom/package.json b/vendor/agentos/examples/custom/package.json deleted file mode 100644 index a80145a8..00000000 --- a/vendor/agentos/examples/custom/package.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-custom", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@rivet-dev/agentos-core": "workspace:*", - "@rivet-dev/agentos-sandbox": "workspace:*", - "sandbox-agent": "^0.4.2", - "dockerode": "^4.0.9", - "get-port": "^7.1.0", - "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", - "zod": "^4.1.11" - }, - "devDependencies": { - "@types/node": "^22.10.2", - "tsx": "^4.19.0", - "typescript": "^5.7.2" - } -} diff --git a/vendor/agentos/examples/custom/pi-cli.ts b/vendor/agentos/examples/custom/pi-cli.ts deleted file mode 100644 index 7791660a..00000000 --- a/vendor/agentos/examples/custom/pi-cli.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { dirname, resolve } from "node:path"; -import { fileURLToPath } from "node:url"; -import { defineSoftware } from "@rivet-dev/agentos-core"; - -const packagePath = resolve(dirname(fileURLToPath(import.meta.url)), ".."); - -// Example: a pi-acp adapter that runs the Pi CLI. -// The agent block lives in the package's agentos-package.json, generated by `agentos-toolchain pack --agent`. -export default defineSoftware({ packagePath }); diff --git a/vendor/agentos/examples/custom/tsconfig.json b/vendor/agentos/examples/custom/tsconfig.json deleted file mode 100644 index 703536a7..00000000 --- a/vendor/agentos/examples/custom/tsconfig.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "moduleResolution": "bundler", "noEmit": true, "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], "types": ["node"], "baseUrl": ".", - "paths": { - "@rivet-dev/agentos-core": ["../../packages/core/src/index.ts"] - } - }, - "include": ["**/*.ts", "**/*.tsx"] -} diff --git a/vendor/agentos/examples/debugging/agent-exit.ts b/vendor/agentos/examples/debugging/agent-exit.ts deleted file mode 100644 index c326abc1..00000000 --- a/vendor/agentos/examples/debugging/agent-exit.ts +++ /dev/null @@ -1,15 +0,0 @@ -import pi from "@agentos-software/pi"; -import { AgentOs } from "@rivet-dev/agentos-core"; - -const agentOs = await AgentOs.create({ - software: [pi], - onAgentExit(event) { - // A later explicit prompt restores the durable session through resume, - // load, or bounded transcript continuation. - console.warn( - `agent exited (code ${event.exitCode}), restart=${event.restart}`, - ); - }, -}); - -await agentOs.dispose(); diff --git a/vendor/agentos/examples/debugging/agent-logs.ts b/vendor/agentos/examples/debugging/agent-logs.ts deleted file mode 100644 index d23bdea7..00000000 --- a/vendor/agentos/examples/debugging/agent-logs.ts +++ /dev/null @@ -1,16 +0,0 @@ -// Capture the coding agent's stderr at the VM level to diagnose tool calls, -// model errors, and crashes mid-turn. - -import pi from "@agentos-software/pi"; -import { AgentOs } from "@rivet-dev/agentos-core"; - -const agentOs = await AgentOs.create({ - software: [pi], - onAgentStderr(event) { - // event: { sessionId, agentType, processId, pid, chunk: Uint8Array } - process.stderr.write(`[agent:${event.agentType}] `); - process.stderr.write(event.chunk); - }, -}); - -await agentOs.dispose(); diff --git a/vendor/agentos/examples/debugging/package.json b/vendor/agentos/examples/debugging/package.json deleted file mode 100644 index 6f5968f6..00000000 --- a/vendor/agentos/examples/debugging/package.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-debugging", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@rivet-dev/agentos-core": "workspace:*", - "@rivet-dev/agentos-sandbox": "workspace:*", - "sandbox-agent": "^0.4.2", - "dockerode": "^4.0.9", - "get-port": "^7.1.0", - "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", - "zod": "^4.1.11" - }, - "devDependencies": { - "@types/node": "^22.10.2", - "tsx": "^4.19.0", - "typescript": "^5.7.2" - } -} diff --git a/vendor/agentos/examples/debugging/tsconfig.json b/vendor/agentos/examples/debugging/tsconfig.json deleted file mode 100644 index 703536a7..00000000 --- a/vendor/agentos/examples/debugging/tsconfig.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "moduleResolution": "bundler", "noEmit": true, "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], "types": ["node"], "baseUrl": ".", - "paths": { - "@rivet-dev/agentos-core": ["../../packages/core/src/index.ts"] - } - }, - "include": ["**/*.ts", "**/*.tsx"] -} diff --git a/vendor/agentos/examples/embedded/README.md b/vendor/agentos/examples/embedded/README.md index 687888a0..c1bea6f7 100644 --- a/vendor/agentos/examples/embedded/README.md +++ b/vendor/agentos/examples/embedded/README.md @@ -1,49 +1,26 @@ --- title: "Embedded VMs" -description: "Embedded agentOS API: exec, configuration, lifecycle events, and mounts." +description: "Embedded agentOS runtime API." category: "Reference" order: 1 --- -The embedded `@rivet-dev/agentos-core` API surface in one place: boot a VM with -`AgentOs.create()` and control it from your application for exec, filesystem, -processes, agent sessions, networking, and cron. There is no actor runtime or -client/server split. Reach for this when you already own the application -lifecycle and want a reference for what an `AgentOs` instance can do and how it -is configured. - -## How it works - -`AgentOs.create({ ... })` boots a VM through a shared sidecar process with its -mounts, software, and network settings, then returns an `AgentOs` instance to -the application. Everything runs through that instance: `exec`/`spawn` for processes, `readFile`/`writeFiles`/`readdirEntries` -for the filesystem, `openSession`/`prompt` for agents, `httpRequest` for in-VM -servers, and `scheduleCron` for jobs. Portable process, shell, session, adapter, -and cron events use explicit subscription methods. Interactive permission -requests and responses are variants of the generic `onSessionEvent` union. - -- `vm.ts`: boot a VM and every instance capability (exec, filesystem, - processes, sessions, networking, cron). -- `quickstart.ts`: run a coding agent directly from a Node.js application. -- `advanced.ts`: pin VMs to a dedicated sidecar process. -- `agent-to-agent.ts`: connect two embedded agents through a host function. -- `host-functions.ts`: expose a host function as a command inside the VM. -- `config-reference.ts`: common `AgentOs.create()` configuration. -- `hooks.ts`: generic durable session-event observation. -- `limits.ts`: configure resource limits and receive local warnings. -- `models-and-credentials.ts`: pass provider credentials to a session. -- `mounts.ts`: host-directory and S3 mount descriptors. -- `persistence.ts`: restore filesystem state from a SQLite database. -- `permissions.ts`: apply a kernel permission policy at VM creation. -- `software.ts`: install a software package and run its command. - -## Run it +Use `@rivet-dev/agentos-core` to boot and control a VM directly from a trusted +Node.js application. The embedded API covers files, processes, terminals, +language execution, networking, command scheduling, software, permissions, +limits, host functions, and trusted host-backed mounts. + +- `vm.ts`: the complete embedded runtime surface. +- `advanced.ts`: a dedicated sidecar process. +- `host-functions.ts`: expose a trusted host function to guest programs. +- `config-reference.ts`: common VM configuration. +- `limits.ts`: resource limits and warnings. +- `mounts.ts`: host-directory and S3 mounts. +- `persistence.ts`: restore filesystem state from SQLite. +- `permissions.ts`: configure the kernel permission policy. +- `software.ts`: install a local software package and run its command. ```sh npm install npx tsx vm.ts ``` - -## Source - -View the source on GitHub: https://github.com/rivet-dev/agentos/tree/main/examples/embedded diff --git a/vendor/agentos/examples/embedded/agent-to-agent.ts b/vendor/agentos/examples/embedded/agent-to-agent.ts deleted file mode 100644 index 33ea744f..00000000 --- a/vendor/agentos/examples/embedded/agent-to-agent.ts +++ /dev/null @@ -1,54 +0,0 @@ -import pi from "@agentos-software/pi"; -import { AgentOs } from "@rivet-dev/agentos-core"; -import { z } from "zod"; - -const apiKey = process.env.ANTHROPIC_API_KEY; -if (!apiKey) { - throw new Error("Set ANTHROPIC_API_KEY before running this example."); -} - -const reviewer = await AgentOs.create({ software: [pi] }); -await reviewer.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: apiKey }, -}); - -const review = { - draft: { - inputSchema: z.object({ draft: z.string() }).describe("Review a draft"), - execute: async ({ draft }: { draft: string }) => { - const response = await reviewer.sessions.prompt({ - content: [{ type: "text", text: `Review this draft:\n\n${draft}` }], - }); - const feedback = - response.message?.content - .filter((block) => block.type === "text") - .map((block) => block.text) - .join("") ?? ""; - return { feedback }; - }, - }, -}; - -const writer = await AgentOs.create({ - software: [pi], - hostFunctions: { review: review }, -}); - -try { - await writer.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: apiKey }, - }); - await writer.sessions.prompt({ - content: [ - { - type: "text", - text: "Draft a release note, then ask the review host function for feedback.", - }, - ], - }); -} finally { - await writer.dispose(); - await reviewer.dispose(); -} diff --git a/vendor/agentos/examples/embedded/config-reference.ts b/vendor/agentos/examples/embedded/config-reference.ts index dd6a7fa2..0ee1bbc6 100644 --- a/vendor/agentos/examples/embedded/config-reference.ts +++ b/vendor/agentos/examples/embedded/config-reference.ts @@ -1,22 +1,26 @@ -import pi from "@agentos-software/pi"; import { AgentOs, nodeModulesMount } from "@rivet-dev/agentos-core"; -// Common embedded AgentOs.create() configuration. The agentOS() actor accepts -// the same options and layers persistence, sleep/wake, and preview URLs on top. +// Common AgentOs.create() configuration. The embedding process is trusted, so +// it may also configure host resources such as host directories and local +// package paths. const vm = await AgentOs.create({ - // Durable SQLite storage for the root filesystem and the session catalog. - // Omit it for an in-memory VM that keeps nothing after dispose(). + // SQLite storage for VM-owned state. On its own it does not make the root + // filesystem durable; see /agentos/docs/persistence. database: { type: "sqlite_file", path: ".agentos/agentos.sqlite" }, + // Store the root filesystem in `database` so files survive VM recreation. + // Omit it for the default in-memory root, discarded on dispose(). + rootFilesystem: { + type: "native", + plugin: { id: "chunked_sqlite", config: {} }, + }, // Filesystems to mount at boot. Use nodeModulesMount() to expose a host // node_modules tree at /root/node_modules. mounts: [nodeModulesMount("/path/to/project/node_modules")], - // Kernel permission policy (see /agentos/docs/permissions) and runtime caps - // (see /agentos/docs/resource-limits) take the same values as the actor. - // `hostFunctions` does too (see /agentos/docs/host-functions). + // Kernel permission policy (see /agentos/docs/permissions) and runtime caps. permissions: { network: "allow" }, limits: { jsRuntime: { v8HeapLimitMb: 128 } }, - // Software packages to install in the VM (see /agentos/docs/software). - software: [pi], + // Install a packed .aospkg from a trusted local path at boot. + software: [{ packagePath: "/path/to/tool.aospkg" }], // Also install the default software bundle (sh + coreutils). Defaults to true; // set false for a bare VM with only the software you list. defaultSoftware: true, diff --git a/vendor/agentos/examples/embedded/hooks.ts b/vendor/agentos/examples/embedded/hooks.ts deleted file mode 100644 index e9641b1d..00000000 --- a/vendor/agentos/examples/embedded/hooks.ts +++ /dev/null @@ -1,15 +0,0 @@ -import pi from "@agentos-software/pi"; -import { AgentOs } from "@rivet-dev/agentos-core"; - -// In the embedded API, ACP updates and permission records share one durable event union. -const vm = await AgentOs.create({ software: [pi] }); -await vm.sessions.open({ agent: "pi", permissionPolicy: "ask" }); - -// Runs for every event on this session. -vm.onSessionEvent((event) => { - if (event.type === "permission_request") { - console.log("Permission request:", event.requestId, event.toolCall); - } else { - console.log("Session update:", event.durability, event); - } -}); diff --git a/vendor/agentos/examples/embedded/host-functions-bash.ts b/vendor/agentos/examples/embedded/host-functions-bash.ts new file mode 100644 index 00000000..25ca01e1 --- /dev/null +++ b/vendor/agentos/examples/embedded/host-functions-bash.ts @@ -0,0 +1,33 @@ +import { AgentOs } from "@rivet-dev/agentos-core"; +import { z } from "zod"; + +// The handler runs on the host, so the API key never enters the VM. +const vm = await AgentOs.create({ + hostFunctions: { + weather: { + forecast: { + inputSchema: z + .object({ city: z.string() }) + .describe("Get the weather forecast for a city"), + execute: async ({ city }) => { + const res = await fetch( + `https://api.weather.example/forecast?city=${city}&key=${process.env.WEATHER_API_KEY}`, + ); + return res.json(); + }, + }, + }, + }, +}); + +try { + // The collection is projected into the VM as an `agentos-weather` command, + // so it composes with pipes and redirects like any other program. + const result = await vm.process.exec( + "agentos-weather forecast --city Paris > /tmp/forecast.json && wc -c < /tmp/forecast.json", + { output: { capture: "all" } }, + ); + console.log(result.outcome === "succeeded" ? result.stdout : result.error); +} finally { + await vm.dispose(); +} diff --git a/vendor/agentos/examples/embedded/host-functions-javascript.ts b/vendor/agentos/examples/embedded/host-functions-javascript.ts new file mode 100644 index 00000000..71cbe9e4 --- /dev/null +++ b/vendor/agentos/examples/embedded/host-functions-javascript.ts @@ -0,0 +1,36 @@ +import { AgentOs } from "@rivet-dev/agentos-core"; +import { z } from "zod"; + +// The handler runs on the host, so the API key never enters the VM. +const vm = await AgentOs.create({ + hostFunctions: { + weather: { + forecast: { + inputSchema: z + .object({ city: z.string() }) + .describe("Get the weather forecast for a city"), + execute: async ({ city }) => { + const res = await fetch( + `https://api.weather.example/forecast?city=${city}&key=${process.env.WEATHER_API_KEY}`, + ); + return res.json(); + }, + }, + }, + }, +}); + +try { + // Guest JavaScript gets each collection as a global, and each host function + // as an async function. + const result = await vm.javascript.execute( + ` + const forecast = await weather.forecast({ city: "Paris" }); + console.log(forecast); + `, + { output: { capture: "all" } }, + ); + console.log(result.outcome === "succeeded" ? result.stdout : result.error); +} finally { + await vm.dispose(); +} diff --git a/vendor/agentos/examples/embedded/host-functions-python.ts b/vendor/agentos/examples/embedded/host-functions-python.ts new file mode 100644 index 00000000..025f050f --- /dev/null +++ b/vendor/agentos/examples/embedded/host-functions-python.ts @@ -0,0 +1,43 @@ +import { AgentOs } from "@rivet-dev/agentos-core"; +import { z } from "zod"; + +// The handler runs on the host, so the API key never enters the VM. +const vm = await AgentOs.create({ + hostFunctions: { + weather: { + forecast: { + inputSchema: z + .object({ city: z.string() }) + .describe("Get the weather forecast for a city"), + execute: async ({ city }) => { + const res = await fetch( + `https://api.weather.example/forecast?city=${city}&key=${process.env.WEATHER_API_KEY}`, + ); + return res.json(); + }, + }, + }, + }, +}); + +try { + // Python calls the `agentos-weather` command like any other program. + const result = await vm.python.execute( + ` +import json +import subprocess + +completed = subprocess.run( + ["agentos-weather", "forecast", "--city", "Paris"], + check=True, + capture_output=True, + text=True, +) +print(json.loads(completed.stdout)["result"]) +`, + { output: { capture: "all" } }, + ); + console.log(result.outcome === "succeeded" ? result.stdout : result.error); +} finally { + await vm.dispose(); +} diff --git a/vendor/agentos/examples/embedded/host-functions.ts b/vendor/agentos/examples/embedded/host-functions.ts index 858994d7..97c00ea9 100644 --- a/vendor/agentos/examples/embedded/host-functions.ts +++ b/vendor/agentos/examples/embedded/host-functions.ts @@ -1,9 +1,8 @@ import { AgentOs } from "@rivet-dev/agentos-core"; import { z } from "zod"; -// Host functions are defined exactly as they are for the actor. Pass them to -// AgentOs.create() and `execute` runs in this host process, with its input typed -// by its own schema. +// Pass host functions to AgentOs.create(). `execute` runs in this host process, +// with its input typed by its own schema. const vm = await AgentOs.create({ hostFunctions: { weather: { diff --git a/vendor/agentos/examples/embedded/limits.ts b/vendor/agentos/examples/embedded/limits.ts index da2fe4c5..3a9c90d4 100644 --- a/vendor/agentos/examples/embedded/limits.ts +++ b/vendor/agentos/examples/embedded/limits.ts @@ -4,8 +4,7 @@ const sidecar = await AgentOs.createSidecar({ runtime: { executor: { maxActiveVms: 8 } }, }); -// The same `limits` object the actor takes. `onLimitWarning` is an embedded -// create option rather than a broadcast event, so it fires only in this process. +// `onLimitWarning` surfaces near-limit pressure to the embedding process. const vm = await AgentOs.create({ sidecar: { kind: "explicit", handle: sidecar }, limits: { diff --git a/vendor/agentos/examples/embedded/models-and-credentials.ts b/vendor/agentos/examples/embedded/models-and-credentials.ts deleted file mode 100644 index c1d1046b..00000000 --- a/vendor/agentos/examples/embedded/models-and-credentials.ts +++ /dev/null @@ -1,18 +0,0 @@ -import pi from "@agentos-software/pi"; -import { AgentOs } from "@rivet-dev/agentos-core"; - -const apiKey = process.env.ANTHROPIC_API_KEY; -if (!apiKey) { - throw new Error("Set ANTHROPIC_API_KEY before running this example."); -} - -const vm = await AgentOs.create({ software: [pi] }); - -try { - await vm.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: apiKey }, - }); -} finally { - await vm.dispose(); -} diff --git a/vendor/agentos/examples/embedded/mounts.ts b/vendor/agentos/examples/embedded/mounts.ts index 69fd96a2..5cbeb50e 100644 --- a/vendor/agentos/examples/embedded/mounts.ts +++ b/vendor/agentos/examples/embedded/mounts.ts @@ -1,8 +1,8 @@ import { AgentOs } from "@rivet-dev/agentos-core"; -// Embedded applications configure filesystem backends at boot. Native mount plugins (host -// directories, S3, etc.) are passed via `plugin`, each identified by an `id` -// and a `config` object. +// Configure filesystem backends at boot. Native mount plugins (host +// directories, S3, Google Drive, etc.) are passed via `plugin`, each identified +// by an `id` and a `config` object. const vm = await AgentOs.create({ mounts: [ // Host directory (read-only) @@ -14,7 +14,12 @@ const vm = await AgentOs.create({ // S3 bucket { path: "/mnt/data", - plugin: { id: "s3", config: { bucket: "my-bucket", prefix: "agent/" } }, + plugin: { + id: "chunked_s3", + config: { bucket: "my-bucket", prefix: "agent/", region: "us-east-1" }, + }, }, ], }); + +await vm.dispose(); diff --git a/vendor/agentos/examples/embedded/package.json b/vendor/agentos/examples/embedded/package.json index 1d909f37..9d95fd0c 100644 --- a/vendor/agentos/examples/embedded/package.json +++ b/vendor/agentos/examples/embedded/package.json @@ -13,9 +13,6 @@ "dockerode": "^4.0.9", "get-port": "^7.1.0", "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", "zod": "^4.1.11" }, "devDependencies": { diff --git a/vendor/agentos/examples/embedded/permissions.ts b/vendor/agentos/examples/embedded/permissions.ts index 1003cd08..002d943a 100644 --- a/vendor/agentos/examples/embedded/permissions.ts +++ b/vendor/agentos/examples/embedded/permissions.ts @@ -1,7 +1,7 @@ import { AgentOs, type Permissions } from "@rivet-dev/agentos-core"; -// The kernel permission policy is the same object the actor takes. Pass it to -// AgentOs.create() instead of agentOS(). +// Core accepts the kernel permission tree plus policies for trusted host +// bindings and mounts. const permissions = { network: { default: "deny", diff --git a/vendor/agentos/examples/embedded/persistence.ts b/vendor/agentos/examples/embedded/persistence.ts index 0ae29806..934e1427 100644 --- a/vendor/agentos/examples/embedded/persistence.ts +++ b/vendor/agentos/examples/embedded/persistence.ts @@ -4,10 +4,16 @@ import { AgentOs, type AgentOsOptions } from "@rivet-dev/agentos-core"; mkdirSync(".agentos", { recursive: true }); const options = { + // The SQLite file that stores the VM's durable state. database: { type: "sqlite_file", path: resolve(".agentos/agentos.sqlite"), }, + // Store the root filesystem in that database instead of in memory. + rootFilesystem: { + type: "native", + plugin: { id: "chunked_sqlite", config: {} }, + }, } satisfies AgentOsOptions; let vm = await AgentOs.create(options); diff --git a/vendor/agentos/examples/embedded/quickstart.ts b/vendor/agentos/examples/embedded/quickstart.ts index c3b6d242..bf1eaa56 100644 --- a/vendor/agentos/examples/embedded/quickstart.ts +++ b/vendor/agentos/examples/embedded/quickstart.ts @@ -1,30 +1,72 @@ -import pi from "@agentos-software/pi"; +// docs:start create import { AgentOs } from "@rivet-dev/agentos-core"; -const apiKey = process.env.ANTHROPIC_API_KEY; -if (!apiKey) { - throw new Error("Set ANTHROPIC_API_KEY before running this example."); -} - -const vm = await AgentOs.create({ software: [pi] }); +// `AgentOs.create()` boots a VM inside this process and returns a handle to it. +const vm = await AgentOs.create(); +// docs:end create try { - await vm.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: apiKey }, + // docs:start bash + const result = await vm.process.exec("echo hello && ls /home/agentos", { + output: { capture: "all" }, }); - await vm.sessions.prompt({ - content: [ - { - type: "text", - text: "Create /home/agentos/hello-world.js that prints hello world.", - }, - ], + console.log(result.stdout); + // docs:end bash + + // docs:start filesystem + await vm.filesystem.writeFile("/home/agentos/hello.txt", "Hello, world!"); + + const file = await vm.filesystem.readFile("/home/agentos/hello.txt"); + // docs:end filesystem + console.log(new TextDecoder().decode(file)); + + // docs:start dev-server + await vm.filesystem.writeFile( + "/home/agentos/server.js", + `require("node:http") + .createServer((req, res) => res.end("hello")) + .listen(3000);`, + ); + + await vm.process.spawn("node", ["/home/agentos/server.js"]); + + // The listener stays inside the VM. Send it a request from the host. + const response = await vm.network.httpRequest({ port: 3000, path: "/" }); + console.log(new TextDecoder().decode(response.body)); + // docs:end dev-server + + // docs:start languages + await vm.javascript.execute("console.log(1 + 2)"); + await vm.typescript.execute("const n: number = 3; console.log(n)"); + + const answer = await vm.python.evaluate("21 * 2"); + // docs:end languages + console.log(answer.outcome === "succeeded" ? answer.value : answer.error); + + // docs:start cron + vm.cron.schedule({ + id: "cleanup", + schedule: "0 * * * *", + action: { type: "exec", command: "rm", args: ["-rf", "/tmp/cache"] }, }); + // docs:end cron + + // docs:start software + // Registry packages are published next to a manifest with each release. + const base = "https://releases.rivet.dev/agent-os/latest/software/"; + const manifest = (await (await fetch(`${base}manifest.json`)).json()) as { + artifacts: { name: string; digest: string; path: string }[]; + }; + const ripgrep = manifest.artifacts.find((artifact) => artifact.name === "ripgrep"); + if (!ripgrep) throw new Error("ripgrep is not in the manifest"); - const script = await vm.filesystem.readFile("/home/agentos/hello-world.js"); - console.log(new TextDecoder().decode(script)); + await vm.software.install({ + type: "url", + url: new URL(ripgrep.path, base).href, + expectedDigest: ripgrep.digest, + }); + // docs:end software } finally { await vm.dispose(); } diff --git a/vendor/agentos/examples/embedded/software-install.ts b/vendor/agentos/examples/embedded/software-install.ts new file mode 100644 index 00000000..d17349b2 --- /dev/null +++ b/vendor/agentos/examples/embedded/software-install.ts @@ -0,0 +1,36 @@ +import { AgentOs } from "@rivet-dev/agentos-core"; + +// Registry software is published as digest-addressed .aospkg files next to a +// manifest. Use a release version, or `latest`. +const base = "https://releases.rivet.dev/agent-os/latest/software/"; +const manifest = (await (await fetch(`${base}manifest.json`)).json()) as { + artifacts: { name: string; digest: string; path: string }[]; +}; +const ripgrep = manifest.artifacts.find((artifact) => artifact.name === "ripgrep"); +if (!ripgrep) throw new Error("ripgrep is not in the manifest"); + +const vm = await AgentOs.create(); + +try { + // Install a package while the VM is running. The bytes are verified against + // the digest before the package is projected into /opt/agentos. + const installed = await vm.software.install({ + type: "url", + url: new URL(ripgrep.path, base).href, + expectedDigest: ripgrep.digest, + }); + console.log(installed.packageName, installed.version, installed.commands); + + const result = await vm.process.execFile("rg", ["--version"], { + output: { capture: "all" }, + }); + console.log(result.stdout); + + // Packages installed through this API, and every command the VM provides. + console.log(vm.software.installed()); + console.log(await vm.software.list()); + + await vm.software.uninstall(installed.packageId); +} finally { + await vm.dispose(); +} diff --git a/vendor/agentos/examples/embedded/vm.ts b/vendor/agentos/examples/embedded/vm.ts index 79548772..c9c71e89 100644 --- a/vendor/agentos/examples/embedded/vm.ts +++ b/vendor/agentos/examples/embedded/vm.ts @@ -1,19 +1,8 @@ // docs:start boot -import { mkdirSync } from "node:fs"; -import { resolve } from "node:path"; -import pi from "@agentos-software/pi"; import { AgentOs } from "@rivet-dev/agentos-core"; -// Embed a VM with the agentOS package. There is no actor runtime or -// client/server split. `AgentOs.create()` returns a handle to the VM. -mkdirSync(".agentos", { recursive: true }); -const vm = await AgentOs.create({ - database: { - type: "sqlite_file", - path: resolve(".agentos/agentos.sqlite"), - }, - software: [pi], -}); +// `AgentOs.create()` boots a VM inside this process and returns a handle to it. +const vm = await AgentOs.create(); const result = await vm.process.exec("echo hello"); console.log(result.stdout); // "hello\n" @@ -86,35 +75,6 @@ async function contexts() { // docs:end contexts } -// ── Agent sessions ──────────────────────────────────────────────── -async function agentSessions() { - // docs:start sessions - // openSession() negotiates ACP and durably records the session in SQLite. - await vm.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - permissionPolicy: "ask", - }); - - // Native ACP updates and permission records share one session event union. - vm.onSessionEvent((event) => { - if (event.type === "permission_request") { - console.log("Permission:", event.requestId, event.toolCall); - } else { - console.log(event.durability, event); - } - }); - - const result = await vm.sessions.prompt({ - content: [{ type: "text", text: "Write a hello world script" }], - }); - console.log(result.message?.content ?? []); - - // Unload releases the adapter but preserves SQLite history for restoration. - await vm.sessions.unload(); - // docs:end sessions -} - // ── Networking ──────────────────────────────────────────────────── async function networking() { // docs:start networking @@ -141,17 +101,6 @@ async function cronJobs() { }); console.log("Scheduled:", job.id); - // Run an agent session on a schedule - vm.cron.schedule({ - schedule: "0 9 * * *", - action: { - type: "session", - agentType: "pi", - prompt: "Review the logs and summarize any errors", - options: { cwd: "/workspace" }, - }, - }); - vm.onCronEvent((event) => { console.log("Cron event:", event.type, event.jobId); }); @@ -160,4 +109,4 @@ async function cronJobs() { // docs:end cron } -export { agentSessions, cronJobs, filesystem, networking, processes }; +export { contexts, cronJobs, filesystem, networking, processes }; diff --git a/vendor/agentos/examples/filesystem/README.md b/vendor/agentos/examples/filesystem/README.md deleted file mode 100644 index 692e6c55..00000000 --- a/vendor/agentos/examples/filesystem/README.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: "Filesystem" -description: "Filesystem access: host-side file APIs, VFS isolation, and mounting memory, host directories, S3, and Google Drive." -category: "Filesystem" -order: 1 ---- - -Every VM gets an isolated virtual filesystem (VFS) that you drive from the host. Reach for this when you need to seed files into a VM, read results back out, or expose external storage to the guest without leaking the host disk. - -## How it works - -The host client exposes file APIs directly on a VM handle — `writeFile`/`readFile` for single files, `writeFiles`/`readFiles` for batches, plus `mkdir`, `readdir`, `readdirRecursive`, `stat`, `exists`, `move`, and `remove`. Bytes you write land in the kernel's in-memory VFS, which the guest sees through the normal `node:fs` API; the real host disk is never exposed, so a path that exists in the VFS does not exist on the host. - -To bridge in external storage, declare `mounts` on `agentOS({ ... })`. Each mount maps a guest path to a plugin: `memory` for scratch space, `host_dir` for a host directory (optionally `readOnly`), `s3` for a bucket/prefix, or `google_drive` for a Drive folder. The guest reads and writes those paths like any other directory. - -## Run it - -```bash -npm install -npx tsx server.ts # start the VM host -npx tsx operations.ts # in another shell: exercise the file APIs -``` - -`operations.ts` writes, reads, lists, moves, and deletes files; `isolation.ts` shows the VFS is sealed from the host disk; the `mount-*.ts` servers swap in different storage backends. - -## Source - -View the source on GitHub: https://github.com/rivet-dev/agent-os/tree/main/examples/filesystem diff --git a/vendor/agentos/examples/filesystem/host-api.ts b/vendor/agentos/examples/filesystem/host-api.ts deleted file mode 100644 index b4aa4eb5..00000000 --- a/vendor/agentos/examples/filesystem/host-api.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ endpoint: "http://localhost:6420" }); -const agent = client.vm.getOrCreate("my-agent"); - -// Write into the VFS (creates parent dirs). Accepts string | Uint8Array. -await agent.filesystem.writeFile("/home/agentos/out.txt", "hi"); - -// Read back to the host as raw bytes. -const bytes = await agent.filesystem.readFile("/home/agentos/out.txt"); -console.log(new TextDecoder().decode(bytes)); diff --git a/vendor/agentos/examples/filesystem/isolation.ts b/vendor/agentos/examples/filesystem/isolation.ts deleted file mode 100644 index 1195cefa..00000000 --- a/vendor/agentos/examples/filesystem/isolation.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ endpoint: "http://localhost:6420" }); -const agent = client.vm.getOrCreate("my-agent"); - -// Seed a file into the VFS at boot. Bytes are copied into the kernel's -// in-memory filesystem; the host filesystem is never exposed to the guest. -await agent.filesystem.writeFile("/home/agentos/seed.json", JSON.stringify({ ok: true })); - -// Write another file from the host after boot. -await agent.filesystem.writeFile("/home/agentos/note.txt", "written from the host\n"); - -// The guest reads both files through the normal node:fs API. -const result = await agent.process.exec(`node -e ' - const { readFileSync } = require("node:fs"); - const seed = JSON.parse(readFileSync("/home/agentos/seed.json", "utf8")); - const note = readFileSync("/home/agentos/note.txt", "utf8").trim(); - console.log("guest read seed:", JSON.stringify(seed)); - console.log("guest read note:", note); -'`, { output: { capture: "all" } }); -console.log("guest stdout:", (result.stdout ?? "").trim()); - -// Read a guest-written file back on the host. -const bytes = await agent.filesystem.readFile("/home/agentos/seed.json"); -console.log("host readFile:", new TextDecoder().decode(bytes)); - -// The same path on the real host disk does not exist. The VFS is isolated. -const { existsSync } = await import("node:fs"); -console.log( - "host disk sees /home/agentos/seed.json?", - existsSync("/home/agentos/seed.json") ? "YES (unexpected!)" : "NO - isolated from host", -); diff --git a/vendor/agentos/examples/filesystem/mount-custom-vfs.ts b/vendor/agentos/examples/filesystem/mount-custom-vfs.ts deleted file mode 100644 index 43c15015..00000000 --- a/vendor/agentos/examples/filesystem/mount-custom-vfs.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { AgentOs } from "@rivet-dev/agentos-core"; - -const vm = await AgentOs.create({ defaultSoftware: false }); -await vm.filesystem.mount({ - path: "/home/agentos/scratch", - plugin: { id: "memory", config: {} }, -}); -await vm.filesystem.writeFile("/home/agentos/scratch/hello.txt", "hello"); diff --git a/vendor/agentos/examples/filesystem/mount-google-drive.ts b/vendor/agentos/examples/filesystem/mount-google-drive.ts deleted file mode 100644 index 549f2e85..00000000 --- a/vendor/agentos/examples/filesystem/mount-google-drive.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; -import pi from "@agentos-software/pi"; - -const vm = agentOS({ - software: [pi], - mounts: [ - { - path: "/mnt/drive", - plugin: { - id: "google_drive", - config: { - credentials: { - clientEmail: process.env.GOOGLE_DRIVE_CLIENT_EMAIL!, - privateKey: process.env.GOOGLE_DRIVE_PRIVATE_KEY!, - }, - folderId: process.env.GOOGLE_DRIVE_FOLDER_ID!, - }, - }, - }, - ], -}); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/filesystem/mount-host-dir.ts b/vendor/agentos/examples/filesystem/mount-host-dir.ts deleted file mode 100644 index 2976d6fb..00000000 --- a/vendor/agentos/examples/filesystem/mount-host-dir.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; -import pi from "@agentos-software/pi"; - -const vm = agentOS({ - software: [pi], - mounts: [ - { - path: "/mnt/code", - plugin: { id: "host_dir", config: { hostPath: "/path/to/repo" } }, - readOnly: true, - }, - ], -}); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/filesystem/mount-s3.ts b/vendor/agentos/examples/filesystem/mount-s3.ts deleted file mode 100644 index 0d5ea3fd..00000000 --- a/vendor/agentos/examples/filesystem/mount-s3.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; -import pi from "@agentos-software/pi"; - -const vm = agentOS({ - software: [pi], - mounts: [ - { - path: "/mnt/data", - plugin: { - id: "s3", - config: { - bucket: "my-bucket", - prefix: "agent-data/", - region: "us-east-1", - }, - }, - }, - ], -}); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/filesystem/operations.ts b/vendor/agentos/examples/filesystem/operations.ts deleted file mode 100644 index 54071bf0..00000000 --- a/vendor/agentos/examples/filesystem/operations.ts +++ /dev/null @@ -1,71 +0,0 @@ -// docs:start read-write -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ endpoint: "http://localhost:6420" }); -const agent = client.vm.getOrCreate("my-agent"); - -// Write a file (string or Uint8Array) -await agent.filesystem.writeFile("/home/agentos/hello.txt", "Hello, world!"); - -// Read a file (returns Uint8Array) -const content = await agent.filesystem.readFile("/home/agentos/hello.txt"); -console.log(new TextDecoder().decode(content)); -// docs:end read-write - -// docs:start batch -// Batch write (creates parent directories automatically) -const writeResults = await agent.filesystem.writeFiles([ - { path: "/home/agentos/src/index.ts", content: "console.log('hello');" }, - { path: "/home/agentos/src/utils.ts", content: "export function add(a: number, b: number) { return a + b; }" }, -]); - -// Batch read -const readResults = await agent.filesystem.readFiles([ - "/home/agentos/src/index.ts", - "/home/agentos/src/utils.ts", -]); -for (const result of readResults) { - console.log(result.path, new TextDecoder().decode(result.content ?? new Uint8Array())); -} -// docs:end batch - -// docs:start directories -// Create a directory -await agent.filesystem.mkdir("/home/agentos/projects"); - -// List directory contents -const entries = await agent.filesystem.readdir("/home/agentos/projects"); - -// Recursive listing (entries carry path, type, and size) -const tree = await agent.filesystem.readdirRecursive("/home/agentos"); -for (const entry of tree) { - const name = entry.path.split("/").pop() ?? entry.path; - console.log(entry.type, entry.path, name); -} -// docs:end directories - -// docs:start metadata -// Check if a path exists -const fileExists = await agent.filesystem.exists("/home/agentos/hello.txt"); - -// Get file metadata -const info = await agent.filesystem.stat("/home/agentos/hello.txt"); -console.log(info.size, info.isDirectory, info.mtimeMs); -// docs:end metadata - -// docs:start move-delete -// Move/rename -await agent.filesystem.move("/home/agentos/old.txt", "/home/agentos/new.txt"); - -// Delete a file -await agent.filesystem.remove("/home/agentos/new.txt"); - -// Delete a directory recursively -await agent.filesystem.remove("/home/agentos/temp", { recursive: true }); -// docs:end move-delete - -// Keep batch + directory results referenced for the type-check. -void writeResults; -void entries; -void fileExists; diff --git a/vendor/agentos/examples/filesystem/package.json b/vendor/agentos/examples/filesystem/package.json deleted file mode 100644 index 493da029..00000000 --- a/vendor/agentos/examples/filesystem/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-filesystem", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-core": "workspace:*", - "@rivet-dev/agentos-sandbox": "workspace:*", - "sandbox-agent": "^0.4.2", - "dockerode": "^4.0.9", - "get-port": "^7.1.0", - "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", - "zod": "^4.1.11", - "rivetkit": "catalog:rivetkit" - }, - "devDependencies": { - "@types/node": "^22.10.2", - "tsx": "^4.19.0", - "typescript": "^5.7.2" - } -} diff --git a/vendor/agentos/examples/filesystem/server.ts b/vendor/agentos/examples/filesystem/server.ts deleted file mode 100644 index ff7c0dc9..00000000 --- a/vendor/agentos/examples/filesystem/server.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; -import pi from "@agentos-software/pi"; - -const vm = agentOS({ - software: [pi], - mounts: [ - { - path: "/home/agentos/scratch", - plugin: { id: "memory", config: {} }, - }, - ], -}); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/filesystem/tsconfig.json b/vendor/agentos/examples/filesystem/tsconfig.json deleted file mode 100644 index 78b4a00b..00000000 --- a/vendor/agentos/examples/filesystem/tsconfig.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "moduleResolution": "bundler", "noEmit": true, "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], "types": ["node"], "baseUrl": ".", - "paths": { - "@rivet-dev/agentos": ["../../packages/agentos/src/index.ts"], - "@rivet-dev/agentos-core": ["../../packages/core/src/index.ts"], - "@rivet-dev/agentos/client": ["../../packages/agentos/src/client.ts"], - "@rivet-dev/agentos/react": ["../../packages/agentos/src/react.ts"] - } - }, - "include": ["**/*.ts", "**/*.tsx"] -} diff --git a/vendor/agentos/examples/flue/README.md b/vendor/agentos/examples/flue/README.md deleted file mode 100644 index ff42ce04..00000000 --- a/vendor/agentos/examples/flue/README.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: "Flue" -description: "Run a Flue agent with a durable agentOS sandbox." -category: "Integrations" -order: 2 ---- - -# Flue - -Run a Flue agent with agentOS as its sandbox. Flue owns the agent runtime; -agentOS supplies the isolated VM and durable `/workspace` filesystem. - -## Run it - -```sh -pnpm install -npx flue run assistant --id local \ - --input '{"message":"Write hello from Flue to /workspace/hello.txt, run wc -c /workspace/hello.txt, then read the file back."}' -``` - -Set `ANTHROPIC_API_KEY` in `.env` before running the agent. - -## Configuration - -- Change the actor name passed to `agentOSSandbox()` when your registry uses a name other than `vm`. -- Configure software, permissions, and resource limits on `agentOS()` in `actors.ts`. -- Keep files that must persist under `/workspace`. - -See the [Flue integration guide](https://rivet.dev/agentos/docs/frameworks/flue) -for the complete setup. - -## Source - -View the source on GitHub: https://github.com/rivet-dev/agentos/tree/main/examples/flue diff --git a/vendor/agentos/examples/flue/actors.ts b/vendor/agentos/examples/flue/actors.ts deleted file mode 100644 index 98d85d1b..00000000 --- a/vendor/agentos/examples/flue/actors.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; - -const vm = agentOS({ - // Configure software, permissions, mounts, and resource limits here. -}); - -export const registry = setup({ use: { vm } }); diff --git a/vendor/agentos/examples/flue/agents/assistant.ts b/vendor/agentos/examples/flue/agents/assistant.ts deleted file mode 100644 index 31868ed1..00000000 --- a/vendor/agentos/examples/flue/agents/assistant.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { createAgent } from "@flue/runtime"; -import { agentOSSandbox } from "@rivet-dev/agentos-flue"; -import { registry } from "../actors.js"; - -export default createAgent(() => ({ - model: "anthropic/claude-sonnet-5", - sandbox: agentOSSandbox({ actor: "vm", registry }), -})); diff --git a/vendor/agentos/examples/flue/flue.config.ts b/vendor/agentos/examples/flue/flue.config.ts deleted file mode 100644 index d83f630e..00000000 --- a/vendor/agentos/examples/flue/flue.config.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { defineConfig } from "@flue/cli/config"; -import { rivet } from "@rivet-dev/flue"; - -export default defineConfig({ - target: rivet(), -}); diff --git a/vendor/agentos/examples/flue/package.json b/vendor/agentos/examples/flue/package.json deleted file mode 100644 index 73500f7a..00000000 --- a/vendor/agentos/examples/flue/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-flue", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "build": "flue build", - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@flue/cli": "npm:@rivet-dev/labs-flue-cli@1.0.0-beta.9-rivet.2", - "@flue/runtime": "npm:@rivet-dev/labs-flue-runtime@1.0.0-beta.9-rivet.2", - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-flue": "workspace:*", - "@rivet-dev/flue": "2.3.9", - "rivetkit": "2.3.10" - }, - "devDependencies": { - "@types/node": "^24.0.0", - "typescript": "^5.7.2" - }, - "engines": { - "node": ">=24" - } -} diff --git a/vendor/agentos/examples/flue/tsconfig.json b/vendor/agentos/examples/flue/tsconfig.json deleted file mode 100644 index 9c5c10e2..00000000 --- a/vendor/agentos/examples/flue/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "moduleResolution": "bundler", - "noEmit": true, - "lib": ["ESNext", "DOM"], - "types": ["node"] - }, - "include": ["actors.ts", "agents/**/*.ts", "flue.config.ts"] -} diff --git a/vendor/agentos/examples/host-functions/README.md b/vendor/agentos/examples/host-functions/README.md deleted file mode 100644 index 710bf63b..00000000 --- a/vendor/agentos/examples/host-functions/README.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: "Host Functions" -description: "Expose host functions to the agent as CLI commands with Zod-typed inputs." -category: "Reference" -order: 3 ---- - -Give an agent access to your own host code, such as API calls, database lookups, and internal services, through type-safe inputs and an auto-generated CLI surface inside the VM. - -## How it works - -A host-function collection bundles a `name`, a `description`, and a map of named `functions`. Each function declares a Zod `inputSchema`, an `execute` handler that runs on the host, and optional `examples`. Pass collections to `agentOS({ hostFunctions: [...] })`; agentOS exposes each collection as `/bin/agentos-{name}` inside the VM. When an agent invokes a function, its schema validates the arguments before the handler executes on the host. - -## Run it - -```sh -npm install -ANTHROPIC_API_KEY=sk-... npx tsx server.ts -# in another terminal: -npx tsx client.ts -``` - -The agent receives the prompt, calls the `weather` forecast host function, and answers using the host-side result. - -## Source - -View the source on GitHub: https://github.com/rivet-dev/agent-os/tree/main/examples/host-functions diff --git a/vendor/agentos/examples/host-functions/client.ts b/vendor/agentos/examples/host-functions/client.ts deleted file mode 100644 index efceacb2..00000000 --- a/vendor/agentos/examples/host-functions/client.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); -const agent = client.vm.getOrCreate("my-agent"); - -// The agent invokes the host function itself as a shell command: -// agentos-weather forecast --city Paris --days 3 -await agent.sessions.open({ - agent: "claude", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, -}); -await agent.sessions.prompt({ - content: [{ type: "text", text: "What's the weather in Paris?" }], -}); diff --git a/vendor/agentos/examples/host-functions/exec-bash.ts b/vendor/agentos/examples/host-functions/exec-bash.ts deleted file mode 100644 index 141500c5..00000000 --- a/vendor/agentos/examples/host-functions/exec-bash.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { AgentOs } from "@rivet-dev/agentos-core"; -import { z } from "zod"; - -// The handler runs on the host, so the API key never enters the VM. -const weather = { - forecast: { - inputSchema: z - .object({ city: z.string() }) - .describe("Get the weather forecast for a city"), - execute: async ({ city }: { city: string }) => { - const res = await fetch( - `https://api.weather.example/forecast?city=${city}&key=${process.env.WEATHER_API_KEY}`, - ); - return res.json(); - }, - }, -}; - -// The collection is projected into the VM as an `agentos-weather` command, so -// it composes with pipes and redirects like any other program. -const runtime = await AgentOs.create({ hostFunctions: { weather: weather } }); - -try { - const result = await runtime.process.exec( - "agentos-weather forecast --city Paris > /workspace/forecast.json && wc -c < /workspace/forecast.json", - { output: { capture: "all" } }, - ); - console.log(result.outcome === "succeeded" ? result.stdout : result.error); -} finally { - await runtime.dispose(); -} diff --git a/vendor/agentos/examples/host-functions/exec-javascript.ts b/vendor/agentos/examples/host-functions/exec-javascript.ts deleted file mode 100644 index dd547877..00000000 --- a/vendor/agentos/examples/host-functions/exec-javascript.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { AgentOs } from "@rivet-dev/agentos-core"; -import { z } from "zod"; - -// The handler runs on the host, so the API key never enters the VM. -const weather = { - forecast: { - inputSchema: z - .object({ city: z.string() }) - .describe("Get the weather forecast for a city"), - execute: async ({ city }: { city: string }) => { - const res = await fetch( - `https://api.weather.example/forecast?city=${city}&key=${process.env.WEATHER_API_KEY}`, - ); - return res.json(); - }, - }, -}; - -// The collection is projected into the VM as an `agentos-weather` command. -const runtime = await AgentOs.create({ hostFunctions: { weather: weather } }); - -try { - const result = await runtime.javascript.execute( - ` - import { execFile } from "node:child_process"; - import { promisify } from "node:util"; - - const run = promisify(execFile); - const { stdout } = await run("agentos-weather", ["forecast", "--city", "Paris"]); - console.log(JSON.parse(stdout).result); - `, - { output: { capture: "all" } }, - ); - console.log(result.outcome === "succeeded" ? result.stdout : result.error); -} finally { - await runtime.dispose(); -} diff --git a/vendor/agentos/examples/host-functions/exec-python.ts b/vendor/agentos/examples/host-functions/exec-python.ts deleted file mode 100644 index ebaed28f..00000000 --- a/vendor/agentos/examples/host-functions/exec-python.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { AgentOs } from "@rivet-dev/agentos-core"; -import { z } from "zod"; - -// The handler runs on the host, so the API key never enters the VM. -const weather = { - forecast: { - inputSchema: z - .object({ city: z.string() }) - .describe("Get the weather forecast for a city"), - execute: async ({ city }: { city: string }) => { - const res = await fetch( - `https://api.weather.example/forecast?city=${city}&key=${process.env.WEATHER_API_KEY}`, - ); - return res.json(); - }, - }, -}; - -// The collection is projected into the VM as an `agentos-weather` command. -const runtime = await AgentOs.create({ hostFunctions: { weather: weather } }); - -try { - const result = await runtime.python.execute( - ` -import json -import subprocess - -completed = subprocess.run( - ["agentos-weather", "forecast", "--city", "Paris"], - check=True, - capture_output=True, - text=True, -) -print(json.loads(completed.stdout)["result"]) - `, - { output: { capture: "all" } }, - ); - console.log(result.outcome === "succeeded" ? result.stdout : result.error); -} finally { - await runtime.dispose(); -} diff --git a/vendor/agentos/examples/host-functions/guest.mjs b/vendor/agentos/examples/host-functions/guest.mjs deleted file mode 100644 index bc88921a..00000000 --- a/vendor/agentos/examples/host-functions/guest.mjs +++ /dev/null @@ -1,14 +0,0 @@ -import { execFile } from "node:child_process"; -import { promisify } from "node:util"; - -const run = promisify(execFile); -const { stdout } = await run("agentos-weather", [ - "forecast", - "--city", - "Paris", - "--days", - "3", -]); - -const response = JSON.parse(stdout); -console.log(response.result); diff --git a/vendor/agentos/examples/host-functions/guest.py b/vendor/agentos/examples/host-functions/guest.py deleted file mode 100644 index 254850ee..00000000 --- a/vendor/agentos/examples/host-functions/guest.py +++ /dev/null @@ -1,12 +0,0 @@ -import json -import subprocess - -completed = subprocess.run( - ["agentos-weather", "forecast", "--city", "Paris", "--days", "3"], - check=True, - capture_output=True, - text=True, -) - -response = json.loads(completed.stdout) -print(response["result"]) diff --git a/vendor/agentos/examples/host-functions/package.json b/vendor/agentos/examples/host-functions/package.json deleted file mode 100644 index 5c75568d..00000000 --- a/vendor/agentos/examples/host-functions/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-host-functions", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-core": "workspace:*", - "@rivet-dev/agentos-sandbox": "workspace:*", - "sandbox-agent": "^0.4.2", - "dockerode": "^4.0.9", - "get-port": "^7.1.0", - "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", - "zod": "^4.1.11", - "rivetkit": "catalog:rivetkit" - }, - "devDependencies": { - "@types/node": "^22.10.2", - "tsx": "^4.19.0", - "typescript": "^5.7.2" - } -} diff --git a/vendor/agentos/examples/host-functions/server.ts b/vendor/agentos/examples/host-functions/server.ts deleted file mode 100644 index 068b1976..00000000 --- a/vendor/agentos/examples/host-functions/server.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; -import { z } from "zod"; - -// Host functions are a record of collections. The keys name everything: the -// collection key becomes the CLI command /bin/agentos-{name} inside the VM, and -// each function key becomes one of its subcommands. A function needs only a Zod -// input schema and an `execute` handler that runs on the host; `.describe()` on -// the schema is what the agent reads. -const vm = agentOS({ - hostFunctions: { - weather: { - forecast: { - inputSchema: z - .object({ - city: z.string().describe("City name"), - days: z.number().optional().describe("Number of days"), - }) - .describe("Get the weather forecast for a city"), - execute: async ({ city, days }) => { - const res = await fetch( - `https://api.weather.example/forecast?city=${city}&days=${days ?? 3}`, - ); - return res.json(); - }, - examples: [ - { - description: "3-day forecast for Paris", - input: { city: "Paris", days: 3 }, - }, - ], - }, - }, - }, -}); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/host-functions/tsconfig.json b/vendor/agentos/examples/host-functions/tsconfig.json deleted file mode 100644 index b190633e..00000000 --- a/vendor/agentos/examples/host-functions/tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "moduleResolution": "bundler", "noEmit": true, "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], "types": ["node"], "baseUrl": ".", - "paths": { - "@rivet-dev/agentos": ["../../packages/agentos/src/index.ts"], - "@rivet-dev/agentos-core": ["../../packages/core/src/index.ts"], - "@rivet-dev/agentos/client": ["../../packages/agentos/src/client.ts"], - "@rivet-dev/agentos/react": ["../../packages/agentos/src/react.ts"], - "@agentos-software/common": ["./software/common.ts"] - } - }, - "include": ["**/*.ts", "**/*.tsx"] -} diff --git a/vendor/agentos/examples/js-ai-agent-code-exec/README.md b/vendor/agentos/examples/js-ai-agent-code-exec/README.md index 382f6e1c..7f6d34ad 100644 --- a/vendor/agentos/examples/js-ai-agent-code-exec/README.md +++ b/vendor/agentos/examples/js-ai-agent-code-exec/README.md @@ -1,6 +1,6 @@ --- title: "AI Agent Code Exec" -description: "Execute agent-generated code inside an isolated AgentOS VM." +description: "Execute generated code inside an isolated agentOS VM." --- Treat every generated program as hostile input. This example creates one diff --git a/vendor/agentos/examples/js-ai-agent-code-exec/src/index.ts b/vendor/agentos/examples/js-ai-agent-code-exec/src/index.ts index a40ed316..61b466d3 100644 --- a/vendor/agentos/examples/js-ai-agent-code-exec/src/index.ts +++ b/vendor/agentos/examples/js-ai-agent-code-exec/src/index.ts @@ -1,7 +1,7 @@ import { AgentOs } from "@rivet-dev/agentos-core"; -// Imagine this expression came from an AI agent. It executes inside an -// isolated AgentOS VM and can only use capabilities granted to that VM. +// Imagine this expression came from an untrusted model. It executes inside an +// isolated agentOS VM and can only use capabilities granted to that VM. const untrustedExpression = ` (async () => { const fib = [0, 1]; diff --git a/vendor/agentos/examples/js-code-mode/README.md b/vendor/agentos/examples/js-code-mode/README.md index 621c4651..a5251ac9 100644 --- a/vendor/agentos/examples/js-code-mode/README.md +++ b/vendor/agentos/examples/js-code-mode/README.md @@ -8,7 +8,7 @@ directly. This example registers a Zod-validated weather host function, lets a generated expression invoke it more than once, and returns one structured result. -Host-function handlers run in the trusted host. Only validated input and JSON output +Binding handlers run in the trusted host. Only validated input and JSON output cross the agentOS boundary, so credentials and direct host resources stay out of generated code. diff --git a/vendor/agentos/examples/js-dev-servers/README.md b/vendor/agentos/examples/js-dev-servers/README.md index e54ba8ac..a70a9271 100644 --- a/vendor/agentos/examples/js-dev-servers/README.md +++ b/vendor/agentos/examples/js-dev-servers/README.md @@ -1,6 +1,6 @@ --- title: "Dev Servers" -description: "Run a long-lived guest server and request it through AgentOS." +description: "Run a long-lived guest server and request it through agentOS." --- This example starts a Node.js HTTP server with `runtime.javascript.spawn()`, diff --git a/vendor/agentos/examples/js-networking-wasm/src/index.ts b/vendor/agentos/examples/js-networking-wasm/src/index.ts index 9584e152..caf6f802 100644 --- a/vendor/agentos/examples/js-networking-wasm/src/index.ts +++ b/vendor/agentos/examples/js-networking-wasm/src/index.ts @@ -7,7 +7,7 @@ const runtime = await AgentOs.create({ try { const result = await runtime.process.execFile( "sh", - ["-c", "printf 'hello from a WASM-backed AgentOS command\\n'"], + ["-c", "printf 'hello from a WASM-backed agentOS command\\n'"], { output: { capture: "all" } }, ); console.log(result.stdout?.trim()); diff --git a/vendor/agentos/examples/js-networking/src/index.ts b/vendor/agentos/examples/js-networking/src/index.ts index 0ec7ea6f..cb4be484 100644 --- a/vendor/agentos/examples/js-networking/src/index.ts +++ b/vendor/agentos/examples/js-networking/src/index.ts @@ -13,7 +13,7 @@ * loopbackExemptPorts. * * Run with: - * AGENTOS_SIDECAR_BIN=../../../target/debug/agentos-sidecar \ + * AGENTOS_SIDECAR_BIN=../../../target/debug/agentos-native-sidecar \ * npx tsx src/index.ts */ diff --git a/vendor/agentos/examples/js-plugin-systems/README.md b/vendor/agentos/examples/js-plugin-systems/README.md index 3759c393..54ab9810 100644 --- a/vendor/agentos/examples/js-plugin-systems/README.md +++ b/vendor/agentos/examples/js-plugin-systems/README.md @@ -1,6 +1,6 @@ --- title: "Plugin Systems" -description: "Evaluate untrusted JavaScript plugins with a narrow AgentOS policy." +description: "Evaluate untrusted JavaScript plugins with a narrow agentOS policy." --- This example evaluates plugin source inside an isolated VM and returns a diff --git a/vendor/agentos/examples/js-runtime/node-modules-mount.ts b/vendor/agentos/examples/js-runtime/node-modules-mount.ts deleted file mode 100644 index f20634a2..00000000 --- a/vendor/agentos/examples/js-runtime/node-modules-mount.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { agentOS, setup, nodeModulesMount } from "@rivet-dev/agentos"; - -const vm = agentOS({ - // Project a host node_modules tree into the VM (read-only by default). - mounts: [nodeModulesMount("/absolute/path/to/node_modules")], -}); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/js-runtime/package.json b/vendor/agentos/examples/js-runtime/package.json deleted file mode 100644 index 30ac4069..00000000 --- a/vendor/agentos/examples/js-runtime/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-js-runtime", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-sandbox": "workspace:*", - "sandbox-agent": "^0.4.2", - "dockerode": "^4.0.9", - "get-port": "^7.1.0", - "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", - "zod": "^4.1.11", - "@rivet-dev/agentos": "workspace:*", - "rivetkit": "catalog:rivetkit" - }, - "devDependencies": { - "@types/node": "^22.10.2", - "tsx": "^4.19.0", - "typescript": "^5.7.2" - } -} diff --git a/vendor/agentos/examples/js-runtime/tsconfig.json b/vendor/agentos/examples/js-runtime/tsconfig.json deleted file mode 100644 index e7937905..00000000 --- a/vendor/agentos/examples/js-runtime/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "moduleResolution": "bundler", "noEmit": true, "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], "types": ["node"], "baseUrl": ".", - "paths": { - "@rivet-dev/agentos": ["../../packages/agentos/src/index.ts"], - "@rivet-dev/agentos/client": ["../../packages/agentos/src/client.ts"], - "@rivet-dev/agentos/react": ["../../packages/agentos/src/react.ts"] - } - }, - "include": ["**/*.ts", "**/*.tsx"] -} diff --git a/vendor/agentos/examples/llm-credentials/README.md b/vendor/agentos/examples/llm-credentials/README.md deleted file mode 100644 index 349303c6..00000000 --- a/vendor/agentos/examples/llm-credentials/README.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: "LLM Credentials" -description: "Pass LLM provider keys per session via env, including a per-tenant credential pattern." -category: "Sessions & Permissions" -order: 5 ---- - -A VM never inherits the host `process.env`, so LLM provider keys must be handed to each session explicitly. Reach for this when your agent needs an `ANTHROPIC_API_KEY` (or any provider secret) and you want that key scoped to a single session — or to a single tenant — rather than baked into the server. - -## How it works - -The server declares the agent software but holds no credentials. The client passes keys through the `env` option on `openSession`, which injects them into that session's adapter environment. For multi-tenant setups, resolve each tenant's key from your own credential store when opening the session. Keys live on the server and are never sent to the browser. - -## Run it - -```bash -npm install -ANTHROPIC_API_KEY=sk-... npx tsx server.ts # then, in another shell: -ANTHROPIC_API_KEY=sk-... npx tsx client.ts -``` - -The client prints a new session id; the agent inside the VM sees the key via its environment. See `per-tenant.ts` for the per-tenant variant. - -## Source - -View the source on GitHub: https://github.com/rivet-dev/agent-os/tree/main/examples/llm-credentials diff --git a/vendor/agentos/examples/llm-credentials/client.ts b/vendor/agentos/examples/llm-credentials/client.ts deleted file mode 100644 index ae641b9d..00000000 --- a/vendor/agentos/examples/llm-credentials/client.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); - -// Pass LLM provider keys via the `env` option on openSession. The VM does -// not inherit from the host process.env, so keys must be passed explicitly. -await client.vm.getOrCreate("my-agent").sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, -}); diff --git a/vendor/agentos/examples/llm-credentials/package.json b/vendor/agentos/examples/llm-credentials/package.json deleted file mode 100644 index 340ea1d3..00000000 --- a/vendor/agentos/examples/llm-credentials/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-llm-credentials", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-sandbox": "workspace:*", - "sandbox-agent": "^0.4.2", - "dockerode": "^4.0.9", - "get-port": "^7.1.0", - "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", - "zod": "^4.1.11", - "@rivet-dev/agentos": "workspace:*", - "rivetkit": "catalog:rivetkit" - }, - "devDependencies": { - "@types/node": "^22.10.2", - "tsx": "^4.19.0", - "typescript": "^5.7.2" - } -} diff --git a/vendor/agentos/examples/llm-credentials/per-tenant.ts b/vendor/agentos/examples/llm-credentials/per-tenant.ts deleted file mode 100644 index 3ec01b87..00000000 --- a/vendor/agentos/examples/llm-credentials/per-tenant.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); - -// Stand-in for your own per-tenant credential store. -declare function lookupTenantApiKey(tenantId: string): Promise; - -// Look up each tenant's API key from your database and inject it at session -// creation. Keys stay on the -// server and never reach the client. -async function startTenantSession(tenantId: string) { - const anthropicApiKey = await lookupTenantApiKey(tenantId); - - await client.vm.getOrCreate(tenantId).sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: anthropicApiKey }, - }); -} - -await startTenantSession("tenant-123"); diff --git a/vendor/agentos/examples/llm-credentials/server.ts b/vendor/agentos/examples/llm-credentials/server.ts deleted file mode 100644 index 6995f140..00000000 --- a/vendor/agentos/examples/llm-credentials/server.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; -import pi from "@agentos-software/pi"; - -// The VM does not inherit the host process.env. LLM provider keys are passed -// explicitly per session, so the server just declares the agent software here. -const vm = agentOS({ - software: [pi], -}); - -export const registry = setup({ use: { vm } }); - -registry.start(); diff --git a/vendor/agentos/examples/llm-credentials/tsconfig.json b/vendor/agentos/examples/llm-credentials/tsconfig.json deleted file mode 100644 index e7937905..00000000 --- a/vendor/agentos/examples/llm-credentials/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "moduleResolution": "bundler", "noEmit": true, "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], "types": ["node"], "baseUrl": ".", - "paths": { - "@rivet-dev/agentos": ["../../packages/agentos/src/index.ts"], - "@rivet-dev/agentos/client": ["../../packages/agentos/src/client.ts"], - "@rivet-dev/agentos/react": ["../../packages/agentos/src/react.ts"] - } - }, - "include": ["**/*.ts", "**/*.tsx"] -} diff --git a/vendor/agentos/examples/multiplayer/README.md b/vendor/agentos/examples/multiplayer/README.md deleted file mode 100644 index b3e07327..00000000 --- a/vendor/agentos/examples/multiplayer/README.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: "Multiplayer" -description: "Multiple clients observing one live session with shared output and collaborative input." -category: "Sessions & Permissions" -order: 6 ---- - -Run one agent session and let several clients watch and drive it at once. Reach for this when a session needs more than one viewer — pair programming, a shared review session, or a dashboard mirroring what an agent is doing live. - -## How it works - -Clients connect to the same VM actor by id (`getOrCreate("shared-agent")`), so they share its durable sessions. Each connection subscribes to the same live event stream—`sessionEvent`, `processOutput`, and `shellData` all fan out to every connected client. One client can open the session and call `prompt`, while others observe the streaming response without driving it. Because the server fans events out from a single session, the `onSessionEvent` server hook still fires once per event regardless of how many clients are attached. Reconnecting clients receive new stream entries after subscribing and can recover missed durable entries with `readHistory({ sessionId })`. - -## Run it - -```sh -npm install -# terminal 1 — start the server -npx tsx server.ts -# terminal 2+ — attach observers / drivers -npx tsx collaborative.ts -``` - -Multiple clients print the same session events; an observer sees the driver's prompt response stream in real time. - -## Source - -View the source on GitHub: https://github.com/rivet-dev/agent-os/tree/main/examples/multiplayer diff --git a/vendor/agentos/examples/multiplayer/collaborative.ts b/vendor/agentos/examples/multiplayer/collaborative.ts deleted file mode 100644 index 47da1ccc..00000000 --- a/vendor/agentos/examples/multiplayer/collaborative.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -// Driver client -const driver = createClient({ - endpoint: "http://localhost:6420", -}); -const driverAgent = driver.vm.getOrCreate("shared-agent"); - -await driverAgent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, -}); - -// Observer client (different user, same actor) -const observer = createClient({ - endpoint: "http://localhost:6420", -}); - -const observerConn = observer.vm.getOrCreate("shared-agent").connect(); -observerConn.on("sessionEvent", (event) => { - console.log("[observer]", event); -}); - -// Driver sends a prompt. Observer sees the streaming response. -await driverAgent.sessions.prompt({ - content: [{ type: "text", text: "Refactor the auth module" }], -}); diff --git a/vendor/agentos/examples/multiplayer/observe-session.ts b/vendor/agentos/examples/multiplayer/observe-session.ts deleted file mode 100644 index dc0db1ae..00000000 --- a/vendor/agentos/examples/multiplayer/observe-session.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -// Client A: creates the session and sends prompts -const clientA = createClient({ - endpoint: "http://localhost:6420", -}); -const agentA = clientA.vm.getOrCreate("shared-agent"); - -const connA = agentA.connect(); -connA.on("sessionEvent", (event) => { - console.log("[A]", event); -}); - -await agentA.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, -}); -await agentA.sessions.prompt({ - content: [{ type: "text", text: "Build a REST API" }], -}); - -// Client B: observes the same session (in a separate process) -const clientB = createClient({ - endpoint: "http://localhost:6420", -}); - -const connB = clientB.vm.getOrCreate("shared-agent").connect(); -connB.on("sessionEvent", (event) => { - console.log("[B]", event); -}); - -// Client B sees the same events as Client A diff --git a/vendor/agentos/examples/multiplayer/package.json b/vendor/agentos/examples/multiplayer/package.json deleted file mode 100644 index b71a87b8..00000000 --- a/vendor/agentos/examples/multiplayer/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-multiplayer", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-sandbox": "workspace:*", - "sandbox-agent": "^0.4.2", - "dockerode": "^4.0.9", - "get-port": "^7.1.0", - "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", - "zod": "^4.1.11", - "@rivet-dev/agentos": "workspace:*", - "rivetkit": "catalog:rivetkit" - }, - "devDependencies": { - "@types/node": "^22.10.2", - "tsx": "^4.19.0", - "typescript": "^5.7.2" - } -} diff --git a/vendor/agentos/examples/multiplayer/server.ts b/vendor/agentos/examples/multiplayer/server.ts deleted file mode 100644 index fb45cea3..00000000 --- a/vendor/agentos/examples/multiplayer/server.ts +++ /dev/null @@ -1,14 +0,0 @@ -import pi from "@agentos-software/pi"; -import { agentOS, setup } from "@rivet-dev/agentos"; - -const vm = agentOS({ - software: [pi], - onSessionEvent: async (_c, sessionId, event) => { - // Server-side hook runs once per event, even with multiple clients - console.log("Session event:", sessionId, event); - }, -}); - -export const registry = setup({ use: { vm } }); - -registry.start(); diff --git a/vendor/agentos/examples/multiplayer/shared-output.ts b/vendor/agentos/examples/multiplayer/shared-output.ts deleted file mode 100644 index 01a716f8..00000000 --- a/vendor/agentos/examples/multiplayer/shared-output.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ endpoint: "http://localhost:6420" }); -const handle = client.vm.getOrCreate("shared-agent"); -const conn = handle.connect(); -const { pid } = await handle.process.spawn("node", ["/home/agentos/server.js"]); -const { shellId } = await handle.terminal.open(); - -// All connected clients see process output -conn.on("processOutput", (data) => { - if (data.pid !== pid) return; - const text = new TextDecoder().decode(data.data); - console.log(`[pid ${data.pid}] ${data.stream}: ${text}`); -}); - -// All connected clients see shell data -conn.on("shellData", (data) => { - if (data.shellId !== shellId) return; - const text = new TextDecoder().decode(data.data); - process.stdout.write(text); -}); diff --git a/vendor/agentos/examples/multiplayer/tsconfig.json b/vendor/agentos/examples/multiplayer/tsconfig.json deleted file mode 100644 index e7937905..00000000 --- a/vendor/agentos/examples/multiplayer/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "moduleResolution": "bundler", "noEmit": true, "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], "types": ["node"], "baseUrl": ".", - "paths": { - "@rivet-dev/agentos": ["../../packages/agentos/src/index.ts"], - "@rivet-dev/agentos/client": ["../../packages/agentos/src/client.ts"], - "@rivet-dev/agentos/react": ["../../packages/agentos/src/react.ts"] - } - }, - "include": ["**/*.ts", "**/*.tsx"] -} diff --git a/vendor/agentos/examples/networking/README.md b/vendor/agentos/examples/networking/README.md deleted file mode 100644 index 8858050e..00000000 --- a/vendor/agentos/examples/networking/README.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: "Networking" -description: "VM networking: loopback servers, fetch from inside and outside the VM, and signed preview URLs." -category: "Networking" -order: 1 ---- - -# Networking - -Run a service inside a VM and reach it — from the client and from the public web. Reach for this when an agent spins up a dev server, API, or web app that you need to call or share. - -## How it works - -A process inside the VM binds a normal loopback port (e.g. `3000`), exactly like any Node server. The client reaches it with `agent.network.httpRequest({ port, path, ...options })`, which proxies a buffered HTTP request straight to that loopback port without exposing it to the network. To expose a port beyond loopback, set `loopbackExemptPorts` on the VM config. For external sharing, call `agent.createPreviewUrl(port, expiresInSeconds)` directly on the handle; the actor's `preview` config sets default and maximum lifetimes plus a bounded maximum active-token count, and old tokens are removed automatically as they expire. - -## Run it - -```bash -npm install -# Start the VM host -npx tsx server.ts -# In another terminal, run a server in the VM and fetch it -npx tsx client-run-server.ts -npx tsx client-fetch.ts -``` - -Expect a `200` status and `Hello from inside the VM` printed by the fetch client. - -## Source - -View the source on GitHub: https://github.com/rivet-dev/agent-os/tree/main/examples/networking diff --git a/vendor/agentos/examples/networking/client-fetch-options.ts b/vendor/agentos/examples/networking/client-fetch-options.ts deleted file mode 100644 index 76369aa4..00000000 --- a/vendor/agentos/examples/networking/client-fetch-options.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ endpoint: "http://localhost:6420" }); - -const response = await client.vm.getOrCreate("my-agent").network.httpRequest({ - port: 3000, - path: "/api/data", - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ key: "value" }), -}); - -console.log("Status:", response.status, response.statusText); -console.log("Headers:", response.headers); -console.log("Body:", new TextDecoder().decode(response.body)); diff --git a/vendor/agentos/examples/networking/client-fetch.ts b/vendor/agentos/examples/networking/client-fetch.ts deleted file mode 100644 index 8aad1497..00000000 --- a/vendor/agentos/examples/networking/client-fetch.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ endpoint: "http://localhost:6420" }); -const agent = client.vm.getOrCreate("my-agent"); - -// Fetch from the VM service started above. -const response = await agent.network.httpRequest({ port: 3000, path: "/" }); -console.log("Status:", response.status); -console.log("Body:", new TextDecoder().decode(response.body)); diff --git a/vendor/agentos/examples/networking/client-preview.ts b/vendor/agentos/examples/networking/client-preview.ts deleted file mode 100644 index f8485ce1..00000000 --- a/vendor/agentos/examples/networking/client-preview.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ endpoint: "http://localhost:6420" }); -const agent = client.vm.getOrCreate("my-agent"); - -// Start a web app in the VM -await agent.process.spawn("node", ["/home/agentos/app.js"]); - -// Create a preview URL for port 3000, valid for 1 hour -const preview = await agent.createPreviewUrl(3000, 3600); -console.log("Preview path:", preview.path); -console.log("Token:", preview.token); -console.log("Expires at:", new Date(preview.expiresAt)); - -// Create a preview URL with a shorter expiration -const shortPreview = await agent.createPreviewUrl(3000, 300); // 5 minutes -console.log("Short-lived preview:", shortPreview.path); diff --git a/vendor/agentos/examples/networking/client-revoke.ts b/vendor/agentos/examples/networking/client-revoke.ts deleted file mode 100644 index edd3d7da..00000000 --- a/vendor/agentos/examples/networking/client-revoke.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ endpoint: "http://localhost:6420" }); - -// Mint a short-lived preview token so access expires automatically. -const agent = client.vm.getOrCreate("my-agent"); -const preview = await agent.createPreviewUrl(3000, 300); // 5 minutes -console.log("Preview path:", preview.path); -console.log("Expires at:", new Date(preview.expiresAt)); diff --git a/vendor/agentos/examples/networking/client-run-server.ts b/vendor/agentos/examples/networking/client-run-server.ts deleted file mode 100644 index c17fced5..00000000 --- a/vendor/agentos/examples/networking/client-run-server.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ endpoint: "http://localhost:6420" }); -const agent = client.vm.getOrCreate("my-agent"); - -// Write a simple Node HTTP server and run it inside the VM. It binds a loopback -// port (3000) exactly like any normal Node process. -await agent.filesystem.writeFile( - "/home/agentos/server.js", - `const http = require("http"); -http.createServer((req, res) => { - res.writeHead(200, { "Content-Type": "text/plain" }); - res.end("Hello from inside the VM"); -}).listen(3000, () => console.log("listening on http://127.0.0.1:3000"));`, -); -const { pid } = await agent.process.spawn("node", ["/home/agentos/server.js"]); -console.log("server pid:", pid); diff --git a/vendor/agentos/examples/networking/package.json b/vendor/agentos/examples/networking/package.json deleted file mode 100644 index eb25fff7..00000000 --- a/vendor/agentos/examples/networking/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-networking", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-sandbox": "workspace:*", - "sandbox-agent": "^0.4.2", - "dockerode": "^4.0.9", - "get-port": "^7.1.0", - "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", - "zod": "^4.1.11", - "@rivet-dev/agentos": "workspace:*", - "rivetkit": "catalog:rivetkit" - }, - "devDependencies": { - "@types/node": "^22.10.2", - "tsx": "^4.19.0", - "typescript": "^5.7.2" - } -} diff --git a/vendor/agentos/examples/networking/server-loopback.ts b/vendor/agentos/examples/networking/server-loopback.ts deleted file mode 100644 index 7b878a16..00000000 --- a/vendor/agentos/examples/networking/server-loopback.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; - -const vm = agentOS({ - software: [], - // Ports exempt from SSRF checks (reachable beyond loopback) - loopbackExemptPorts: [3000], -}); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/networking/server-preview.ts b/vendor/agentos/examples/networking/server-preview.ts deleted file mode 100644 index 6d07b380..00000000 --- a/vendor/agentos/examples/networking/server-preview.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; - -const vm = agentOS({ - software: [], - preview: { - defaultExpiresInSeconds: 3600, // 1 hour default - maxExpiresInSeconds: 86400, // 24 hour maximum - }, -}); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/networking/server.ts b/vendor/agentos/examples/networking/server.ts deleted file mode 100644 index 005d9a1d..00000000 --- a/vendor/agentos/examples/networking/server.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; - -const vm = agentOS({ software: [] }); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/networking/tsconfig.json b/vendor/agentos/examples/networking/tsconfig.json deleted file mode 100644 index e7937905..00000000 --- a/vendor/agentos/examples/networking/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "moduleResolution": "bundler", "noEmit": true, "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], "types": ["node"], "baseUrl": ".", - "paths": { - "@rivet-dev/agentos": ["../../packages/agentos/src/index.ts"], - "@rivet-dev/agentos/client": ["../../packages/agentos/src/client.ts"], - "@rivet-dev/agentos/react": ["../../packages/agentos/src/react.ts"] - } - }, - "include": ["**/*.ts", "**/*.tsx"] -} diff --git a/vendor/agentos/examples/opencode/README.md b/vendor/agentos/examples/opencode/README.md deleted file mode 100644 index a4e6fe11..00000000 --- a/vendor/agentos/examples/opencode/README.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: "OpenCode Agent" -description: "Run the OpenCode agent in a session using an Anthropic API key." -category: "Agents" -order: 4 ---- - -Spin up the OpenCode coding agent inside a VM session and prompt it with natural language. Reach for this when you want an autonomous coding agent that can read files, run commands, and follow project conventions — backed by your own Anthropic API key. - -## How it works - -Register the `opencode` software with `agentOS({ software: [opencode] })` so the runtime knows the agent type. The client calls `agent.sessions.open({ agent: "opencode", ... })`, which infers the default `main` session, passes `ANTHROPIC_API_KEY` through `env`, and then drives the agent with `agent.sessions.prompt`. The example also shows two extension points: drop a `SKILL.md` into `~/.config/opencode/skills/` before opening the session and the agent auto-discovers it, and wire in extra tools through native ACP `mcpServers`. Pre-install any `npx` MCP server first so install output does not corrupt the stdio handshake. - -## Run it - -```bash -npm install -export ANTHROPIC_API_KEY=sk-ant-... -npx tsx server.ts # starts the registry on http://localhost:6420 -npx tsx client.ts # creates a session and prints the agent's reply -``` - -The agent answers your prompt — e.g. listing the files in the working directory. - -## Source - -View the source on GitHub: https://github.com/rivet-dev/agent-os/tree/main/examples/opencode diff --git a/vendor/agentos/examples/opencode/client.ts b/vendor/agentos/examples/opencode/client.ts deleted file mode 100644 index a3751ad5..00000000 --- a/vendor/agentos/examples/opencode/client.ts +++ /dev/null @@ -1,155 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); -const agent = client.vm.getOrCreate("my-agent"); - -// ── Quickstart ──────────────────────────────────────────────────── -async function quickStart() { - // docs:start quickstart - await agent.sessions.open({ - agent: "opencode", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - }); - - const result = await agent.sessions.prompt({ - content: [ - { type: "text", text: "What files are in the current directory?" }, - ], - }); - console.log(result.message?.content ?? []); - // docs:end quickstart -} - -// ── Skills ──────────────────────────────────────────────────────── -// -// Write a SKILL.md into the agent's skills directory before creating the -// session and the agent discovers it automatically. -async function withSkill() { - // docs:start skills - const skill = `--- -name: commit-style -description: How to write commit messages in this project. ---- - -Write commit messages in the imperative mood and keep the subject under 50 characters. -`; - - // Write the skill before creating the session - await agent.filesystem.mkdir("/home/agentos/.config/opencode/skills/commit-style"); - await agent.filesystem.writeFile( - "/home/agentos/.config/opencode/skills/commit-style/SKILL.md", - skill, - ); - - // OpenCode discovers the skill automatically - await agent.sessions.open({ - agent: "opencode", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - }); - // docs:end skills -} - -// ── MCP servers ─────────────────────────────────────────────────── -// -// OpenCode reads MCP servers from its own config file. Write an -// `opencode.json` into the VM before creating the session — local -// child-process servers and remote URLs are both supported. -async function withMcp() { - // Pre-install the MCP server so `npx` is silent — first-run install output - // would otherwise corrupt the MCP stdio handshake ("Connection closed"). - await agent.process.exec("npm install -g @modelcontextprotocol/server-filesystem"); - - // docs:start mcp - const config = { - mcp: { - filesystem: { - type: "local", - command: [ - "npx", - "-y", - "@modelcontextprotocol/server-filesystem", - "/home/agentos", - ], - enabled: true, - }, - example: { - type: "remote", - url: "https://mcp.example.com/sse", - headers: { Authorization: "Bearer my-token" }, - enabled: true, - }, - }, - }; - - await agent.filesystem.writeFile( - "/home/agentos/.config/opencode/opencode.json", - JSON.stringify(config, null, 2), - ); - - await agent.sessions.open({ - agent: "opencode", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - }); - // docs:end mcp -} - -// ── Skills + MCP together ───────────────────────────────────────── -async function withSkillAndMcp() { - const skill = `--- -name: commit-style -description: How to write commit messages in this project. ---- - -Write commit messages in the imperative mood and keep the subject under 50 characters. -`; - - await agent.filesystem.mkdir("/home/agentos/.config/opencode/skills/commit-style"); - await agent.filesystem.writeFile( - "/home/agentos/.config/opencode/skills/commit-style/SKILL.md", - skill, - ); - - // Pre-install the MCP server so `npx` is silent — first-run install output - // would otherwise corrupt the MCP stdio handshake ("Connection closed"). - await agent.process.exec("npm install -g @modelcontextprotocol/server-filesystem"); - - const config = { - mcp: { - filesystem: { - type: "local", - command: [ - "npx", - "-y", - "@modelcontextprotocol/server-filesystem", - "/home/agentos", - ], - enabled: true, - }, - }, - }; - - await agent.filesystem.writeFile( - "/home/agentos/.config/opencode/opencode.json", - JSON.stringify(config, null, 2), - ); - - await agent.sessions.open({ - agent: "opencode", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - }); - - const result = await agent.sessions.prompt({ - content: [ - { - type: "text", - text: "Stage everything and write a commit message following the project skill.", - }, - ], - }); - console.log(result.message?.content ?? []); -} - -export { quickStart, withSkill, withMcp, withSkillAndMcp }; diff --git a/vendor/agentos/examples/opencode/package.json b/vendor/agentos/examples/opencode/package.json deleted file mode 100644 index e31d4e16..00000000 --- a/vendor/agentos/examples/opencode/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-opencode", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-sandbox": "workspace:*", - "sandbox-agent": "^0.4.2", - "dockerode": "^4.0.9", - "get-port": "^7.1.0", - "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", - "zod": "^4.1.11", - "@rivet-dev/agentos": "workspace:*", - "rivetkit": "catalog:rivetkit" - }, - "devDependencies": { - "@types/node": "^22.10.2", - "tsx": "^4.19.0", - "typescript": "^5.7.2" - } -} diff --git a/vendor/agentos/examples/opencode/server.ts b/vendor/agentos/examples/opencode/server.ts deleted file mode 100644 index 6801448b..00000000 --- a/vendor/agentos/examples/opencode/server.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; -import opencode from "@agentos-software/opencode"; - -const vm = agentOS({ software: [opencode] }); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/opencode/tsconfig.json b/vendor/agentos/examples/opencode/tsconfig.json deleted file mode 100644 index e7937905..00000000 --- a/vendor/agentos/examples/opencode/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "moduleResolution": "bundler", "noEmit": true, "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], "types": ["node"], "baseUrl": ".", - "paths": { - "@rivet-dev/agentos": ["../../packages/agentos/src/index.ts"], - "@rivet-dev/agentos/client": ["../../packages/agentos/src/client.ts"], - "@rivet-dev/agentos/react": ["../../packages/agentos/src/react.ts"] - } - }, - "include": ["**/*.ts", "**/*.tsx"] -} diff --git a/vendor/agentos/examples/permissions/README.md b/vendor/agentos/examples/permissions/README.md deleted file mode 100644 index d642a3b7..00000000 --- a/vendor/agentos/examples/permissions/README.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: "Permissions" -description: "Apply permission policies: grant network, deny filesystem paths, and scope what the guest can do." -category: "Sessions & Permissions" -order: 2 ---- - -Permission policies decide what guest code is allowed to touch: the network, the filesystem, and named host functions. Reach for this when you need to hand untrusted or agent-generated code a VM that can only do exactly what you intend. - -## How it works - -Each policy is a small object passed to `agentOS({ permissions })`. A policy sets a `default` (`allow` or `deny`) and a list of `rules` that flip the decision for specific paths, hosts, or host-function names. This example composes four policies and merges them into one permission set: - -- **Network** granted outright, with a stricter override that denies by default and allows only `api.example.com`. -- **Filesystem** allowed by default but denied for anything under `/vault/**`. -- **Host functions** denied by default, allowing only `add` by name. - -Rules are evaluated against the defaults, so you compose from broad posture down to narrow exceptions. The resulting VM enforces all of them on every guest operation. - -## Run it - -```sh -npm install -npx tsx server.ts -``` - -The registry starts with a VM whose guest can reach `api.example.com`, cannot read `/vault`, and can only invoke the `add` host function. - -## Source - -View the source on GitHub: https://github.com/rivet-dev/agent-os/tree/main/examples/permissions diff --git a/vendor/agentos/examples/permissions/bind-policy.ts b/vendor/agentos/examples/permissions/bind-policy.ts deleted file mode 100644 index f56f7d51..00000000 --- a/vendor/agentos/examples/permissions/bind-policy.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; - -const vm = agentOS({ - permissions: { - network: "allow", - fs: "deny", - }, -}); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/permissions/combine.ts b/vendor/agentos/examples/permissions/combine.ts deleted file mode 100644 index 1f2db4d9..00000000 --- a/vendor/agentos/examples/permissions/combine.ts +++ /dev/null @@ -1,45 +0,0 @@ -import type { Permissions } from "@rivet-dev/agentos"; -import { agentOS, setup } from "@rivet-dev/agentos"; - -// Allow the filesystem everywhere, but deny anything under /home/agentos/vault. -const denyVault = { - fs: { - default: "allow", - rules: [ - { mode: "deny", operations: ["*"], paths: ["/home/agentos/vault/**"] }, - ], - }, -} satisfies Permissions; - -// Deny the network by default, allow only api.example.com. -const allowOneHost = { - network: { - default: "deny", - rules: [ - { - mode: "allow", - operations: ["*"], - patterns: ["dns://api.example.com", "tcp://api.example.com:*"], - }, - ], - }, -} satisfies Permissions; - -// Deny all host functions by default, then allow only "add" by name. -const allowOneHostFunction = { - hostFunction: { - default: "deny", - rules: [{ mode: "allow", operations: ["invoke"], patterns: ["add"] }], - }, -} satisfies Permissions; - -const vm = agentOS({ - permissions: { - ...denyVault, - ...allowOneHost, - ...allowOneHostFunction, - }, -}); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/permissions/fs-rules.ts b/vendor/agentos/examples/permissions/fs-rules.ts deleted file mode 100644 index 5883c401..00000000 --- a/vendor/agentos/examples/permissions/fs-rules.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; -import type { Permissions } from "@rivet-dev/agentos"; - -// docs:start deny-vault -// Allow the filesystem everywhere, but deny anything under /home/agentos/vault. -const denyVault = { - fs: { - default: "allow", - rules: [{ mode: "deny", operations: ["*"], paths: ["/home/agentos/vault/**"] }], - }, -} satisfies Permissions; -// docs:end deny-vault - -// docs:start allow-only-data -// Deny the filesystem by default, allow only reads under /home/agentos/data. -const allowOnlyData = { - fs: { - default: "deny", - rules: [{ mode: "allow", operations: ["read", "readdir", "stat"], paths: ["/home/agentos/data/**"] }], - }, -} satisfies Permissions; -// docs:end allow-only-data - -const vm = agentOS({ - permissions: { - ...denyVault, - ...allowOnlyData, - }, -}); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/permissions/package.json b/vendor/agentos/examples/permissions/package.json deleted file mode 100644 index 2ae34984..00000000 --- a/vendor/agentos/examples/permissions/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-permissions", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-sandbox": "workspace:*", - "sandbox-agent": "^0.4.2", - "dockerode": "^4.0.9", - "get-port": "^7.1.0", - "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", - "zod": "^4.1.11", - "@rivet-dev/agentos": "workspace:*", - "rivetkit": "catalog:rivetkit" - }, - "devDependencies": { - "@types/node": "^22.10.2", - "tsx": "^4.19.0", - "typescript": "^5.7.2" - } -} diff --git a/vendor/agentos/examples/permissions/server.ts b/vendor/agentos/examples/permissions/server.ts deleted file mode 100644 index acf2d75e..00000000 --- a/vendor/agentos/examples/permissions/server.ts +++ /dev/null @@ -1,54 +0,0 @@ -import type { Permissions } from "@rivet-dev/agentos"; -import { agentOS, setup } from "@rivet-dev/agentos"; - -// docs:start grant-network -// Grant the network, leave everything else at the secure default. -const grantNetwork = { network: "allow" } satisfies Permissions; -// docs:end grant-network - -// fs: allow by default, but deny anything under /vault. -const denyVault = { - fs: { - default: "allow", - rules: [{ mode: "deny", operations: ["*"], paths: ["/vault/**"] }], - }, -} satisfies Permissions; - -// docs:start allow-one-host -// Deny the network by default, allow only api.example.com. -const allowOneHost = { - network: { - default: "deny", - rules: [ - { - mode: "allow", - operations: ["*"], - patterns: ["dns://api.example.com", "tcp://api.example.com:*"], - }, - ], - }, -} satisfies Permissions; -// docs:end allow-one-host - -// docs:start allow-one-host-function -// Deny all host functions by default, then allow only "add" by name. -const allowOneHostFunction = { - hostFunction: { - default: "deny", - rules: [{ mode: "allow", operations: ["invoke"], patterns: ["add"] }], - }, -} satisfies Permissions; -// docs:end allow-one-host-function - -// Combine the policies above and bind them to the VM via `agentOS`. -const vm = agentOS({ - permissions: { - ...grantNetwork, - ...denyVault, - ...allowOneHost, - ...allowOneHostFunction, - }, -}); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/permissions/tsconfig.json b/vendor/agentos/examples/permissions/tsconfig.json deleted file mode 100644 index e7937905..00000000 --- a/vendor/agentos/examples/permissions/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "moduleResolution": "bundler", "noEmit": true, "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], "types": ["node"], "baseUrl": ".", - "paths": { - "@rivet-dev/agentos": ["../../packages/agentos/src/index.ts"], - "@rivet-dev/agentos/client": ["../../packages/agentos/src/client.ts"], - "@rivet-dev/agentos/react": ["../../packages/agentos/src/react.ts"] - } - }, - "include": ["**/*.ts", "**/*.tsx"] -} diff --git a/vendor/agentos/examples/persistence/README.md b/vendor/agentos/examples/persistence/README.md deleted file mode 100644 index e14dfa34..00000000 --- a/vendor/agentos/examples/persistence/README.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: "Persistence" -description: "Filesystem persistence and VM sleep/wake lifecycle management." -category: "Sessions & Permissions" -order: 7 ---- - -VMs sleep when idle and wake on demand while files under `/home/agentos`, the durable session catalog, and completed session history remain in actor SQLite. Reach for this when agent work must survive client disconnects, actor sleep, or long gaps between turns. - -## How it works - -The server registers a VM with `agentOS({ software: [pi] })` and `setup`. On the client, native RivetKit `connect().on("vmBooted", ...)` and `connect().on("vmShutdown", ...)` subscriptions expose lifecycle events; the shutdown payload's `reason` (`"sleep"`, `"destroy"`, or `"error"`) tells you why the VM stopped. Files, durable session data, dynamic mount descriptors, and linked software descriptors are stored in actor SQLite and replayed when the VM wakes. - -An active prompt turn keeps the actor awake through its terminal SQLite commit; an idle session does not. Sleep discards adapter processes, running processes, shells, subscriptions, and incomplete message deltas. A storage-only session list or history read wakes the VM without starting an ACP adapter. The next prompt for a durable session restores the adapter lazily, while completed history remains available from SQLite. - -## Run it - -```sh -npm install -npx tsx examples/persistence/server.ts # terminal 1: start the registry -npx tsx examples/persistence/lifecycle-client.ts # terminal 2: watch boot/shutdown events -npx tsx examples/persistence/restore-filesystem.ts # later: verify persisted files -``` - -The lifecycle client logs `VM is ready` then shutdown reasons; the restore client reads a file created before the actor slept. - -## Source - -View the source on GitHub: https://github.com/rivet-dev/agent-os/tree/main/examples/persistence diff --git a/vendor/agentos/examples/persistence/lifecycle-client.ts b/vendor/agentos/examples/persistence/lifecycle-client.ts deleted file mode 100644 index b26c7e29..00000000 --- a/vendor/agentos/examples/persistence/lifecycle-client.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); - -const conn = client.vm.getOrCreate("my-agent").connect(); - -conn.on("vmBooted", () => { - console.log("VM is ready"); -}); - -conn.on("vmShutdown", (payload) => { - console.log("VM shutdown reason:", payload.reason); - // reason: "sleep" | "destroy" | "error" -}); - -// The VM starts lazily on the first AgentOS action after wake, after the -// lifecycle subscriptions above are active. -await conn.filesystem.exists("/"); diff --git a/vendor/agentos/examples/persistence/package.json b/vendor/agentos/examples/persistence/package.json deleted file mode 100644 index bef232cd..00000000 --- a/vendor/agentos/examples/persistence/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-persistence", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-sandbox": "workspace:*", - "sandbox-agent": "^0.4.2", - "dockerode": "^4.0.9", - "get-port": "^7.1.0", - "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", - "zod": "^4.1.11", - "@rivet-dev/agentos": "workspace:*", - "rivetkit": "catalog:rivetkit" - }, - "devDependencies": { - "@types/node": "^22.10.2", - "tsx": "^4.19.0", - "typescript": "^5.7.2" - } -} diff --git a/vendor/agentos/examples/persistence/restore-filesystem.ts b/vendor/agentos/examples/persistence/restore-filesystem.ts deleted file mode 100644 index 75c1aed7..00000000 --- a/vendor/agentos/examples/persistence/restore-filesystem.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); -const vm = client.vm.getOrCreate("persistent-agent"); - -// Files written before sleep are restored when the actor wakes. -const contents = await vm.filesystem.readFile("/home/agentos/notes.md"); -console.log(new TextDecoder().decode(contents)); diff --git a/vendor/agentos/examples/persistence/server.ts b/vendor/agentos/examples/persistence/server.ts deleted file mode 100644 index ba01a582..00000000 --- a/vendor/agentos/examples/persistence/server.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; -import pi from "@agentos-software/pi"; - -const vm = agentOS({ - software: [pi], -}); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/persistence/tsconfig.json b/vendor/agentos/examples/persistence/tsconfig.json deleted file mode 100644 index e7937905..00000000 --- a/vendor/agentos/examples/persistence/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "moduleResolution": "bundler", "noEmit": true, "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], "types": ["node"], "baseUrl": ".", - "paths": { - "@rivet-dev/agentos": ["../../packages/agentos/src/index.ts"], - "@rivet-dev/agentos/client": ["../../packages/agentos/src/client.ts"], - "@rivet-dev/agentos/react": ["../../packages/agentos/src/react.ts"] - } - }, - "include": ["**/*.ts", "**/*.tsx"] -} diff --git a/vendor/agentos/examples/pi/README.md b/vendor/agentos/examples/pi/README.md deleted file mode 100644 index 21f8556f..00000000 --- a/vendor/agentos/examples/pi/README.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: "Pi Agent" -description: "Run the Pi coding agent in a session, including quickstart and session management." -category: "Agents" -order: 1 ---- - -Spin up the Pi coding agent inside a VM, open a session, and send it prompts. Reach for this when you want an end-to-end agent loop from quickstart through the session knobs for skills and MCP servers. - -## How it works - -The server registers a VM with the `pi` software package and starts the registry. The client grabs a VM with `getOrCreate`, then calls `openSession({ agent: "pi", env: … })`, which infers the default `main` session and passes `ANTHROPIC_API_KEY` through `env`. From there `prompt({ content })` runs a turn and returns the agent's `text`. Drop a `SKILL.md` into the agent's skills directory before opening the session and it is auto-discovered; Pi reads MCP servers from its native `.mcp.json` config. Pre-install any `npx`-launched MCP server so install output does not corrupt the stdio handshake. - -## Run it - -```sh -npm install -ANTHROPIC_API_KEY=sk-... npx tsx server.ts # then run the client in another shell -``` - -The agent answers the prompt and prints its response to the console. - -## Source - -View the source on GitHub: https://github.com/rivet-dev/agent-os/tree/main/examples/pi diff --git a/vendor/agentos/examples/pi/client.ts b/vendor/agentos/examples/pi/client.ts deleted file mode 100644 index 32eea592..00000000 --- a/vendor/agentos/examples/pi/client.ts +++ /dev/null @@ -1,175 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); -const agent = client.vm.getOrCreate("my-agent"); - -// ── Quickstart ──────────────────────────────────────────────────── -// docs:start quickstart -async function quickStart() { - await agent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - }); - - const result = await agent.sessions.prompt({ - content: [ - { type: "text", text: "What files are in the current directory?" }, - ], - }); - console.log(result.message?.content ?? []); -} -// docs:end quickstart - -// ── Skills ──────────────────────────────────────────────────────── -// -// Write a SKILL.md into the agent's skills directory before creating the -// session and the agent discovers it automatically. -// docs:start skill -async function withSkill() { - const skill = `--- -name: commit-style -description: How to write commit messages in this project. ---- - -Write commit messages in the imperative mood and keep the subject under 50 characters. -`; - - await agent.filesystem.mkdir("/home/agentos/.pi/agent/skills/commit-style"); - await agent.filesystem.writeFile( - "/home/agentos/.pi/agent/skills/commit-style/SKILL.md", - skill, - ); - - await agent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - }); -} -// docs:end skill - -// ── MCP servers ─────────────────────────────────────────────────── -// -// Pi discovers MCP servers from its own config file. Write an `.mcp.json` -// into the agent's config directory before creating the session — local -// child-process servers and remote URLs are both supported. -async function withMcp() { - // Pre-install the MCP server so `npx` is silent — first-run install output - // would otherwise corrupt the MCP stdio handshake ("Connection closed"). - await agent.process.exec("npm install -g @modelcontextprotocol/server-filesystem"); - - // docs:start mcp - const mcpConfig = JSON.stringify({ - mcpServers: { - filesystem: { - command: "npx", - args: [ - "-y", - "@modelcontextprotocol/server-filesystem", - "/home/agentos", - ], - }, - remote: { - url: "https://mcp.example.com/sse", - headers: { Authorization: "Bearer my-token" }, - }, - }, - }); - - await agent.filesystem.mkdir("/home/agentos/.pi/agent"); - await agent.filesystem.writeFile("/home/agentos/.pi/agent/.mcp.json", mcpConfig); - - await agent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - }); - // docs:end mcp -} - -// ── Skills + MCP together ───────────────────────────────────────── -async function withSkillAndMcp() { - const skill = `--- -name: commit-style -description: How to write commit messages in this project. ---- - -Write commit messages in the imperative mood and keep the subject under 50 characters. -`; - - await agent.filesystem.mkdir("/home/agentos/.pi/agent/skills/commit-style"); - await agent.filesystem.writeFile( - "/home/agentos/.pi/agent/skills/commit-style/SKILL.md", - skill, - ); - - // Pre-install the MCP server so `npx` is silent — first-run install output - // would otherwise corrupt the MCP stdio handshake ("Connection closed"). - await agent.process.exec("npm install -g @modelcontextprotocol/server-filesystem"); - - const mcpConfig = JSON.stringify({ - mcpServers: { - filesystem: { - command: "npx", - args: [ - "-y", - "@modelcontextprotocol/server-filesystem", - "/home/agentos", - ], - }, - }, - }); - await agent.filesystem.mkdir("/home/agentos/.pi/agent"); - await agent.filesystem.writeFile("/home/agentos/.pi/agent/.mcp.json", mcpConfig); - - await agent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - }); - - const result = await agent.sessions.prompt({ - content: [ - { - type: "text", - text: "Stage everything and write a commit message following the project skill.", - }, - ], - }); - console.log(result.message?.content ?? []); -} - -// ── Extensions ──────────────────────────────────────────────────── -// -// Write a `.js` extension into the agent's extensions directory before -// creating the session and the agent discovers it automatically. -async function withExtension() { - // docs:start extension - const extensionCode = ` -export default function(pi) { - // Modify the system prompt before each agent turn - pi.on("before_agent_start", async (event) => { - return { - systemPrompt: event.systemPrompt + - "\\n\\nAlways respond in formal English." - }; - }); -} -`; - - // Write the extension before creating the session - await agent.filesystem.mkdir("/home/agentos/.pi/agent/extensions"); - await agent.filesystem.writeFile( - "/home/agentos/.pi/agent/extensions/formal.js", - extensionCode, - ); - - // Pi discovers the extension automatically - await agent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - }); - // docs:end extension -} - -export { quickStart, withSkill, withMcp, withSkillAndMcp, withExtension }; diff --git a/vendor/agentos/examples/pi/package.json b/vendor/agentos/examples/pi/package.json deleted file mode 100644 index 209dfe79..00000000 --- a/vendor/agentos/examples/pi/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-pi", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-sandbox": "workspace:*", - "sandbox-agent": "^0.4.2", - "dockerode": "^4.0.9", - "get-port": "^7.1.0", - "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", - "zod": "^4.1.11", - "@rivet-dev/agentos": "workspace:*", - "rivetkit": "catalog:rivetkit" - }, - "devDependencies": { - "@types/node": "^22.10.2", - "tsx": "^4.19.0", - "typescript": "^5.7.2" - } -} diff --git a/vendor/agentos/examples/pi/server.ts b/vendor/agentos/examples/pi/server.ts deleted file mode 100644 index 32a86b30..00000000 --- a/vendor/agentos/examples/pi/server.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; -import pi from "@agentos-software/pi"; - -const vm = agentOS({ software: [pi] }); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/pi/tsconfig.json b/vendor/agentos/examples/pi/tsconfig.json deleted file mode 100644 index e7937905..00000000 --- a/vendor/agentos/examples/pi/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "moduleResolution": "bundler", "noEmit": true, "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], "types": ["node"], "baseUrl": ".", - "paths": { - "@rivet-dev/agentos": ["../../packages/agentos/src/index.ts"], - "@rivet-dev/agentos/client": ["../../packages/agentos/src/client.ts"], - "@rivet-dev/agentos/react": ["../../packages/agentos/src/react.ts"] - } - }, - "include": ["**/*.ts", "**/*.tsx"] -} diff --git a/vendor/agentos/examples/processes/README.md b/vendor/agentos/examples/processes/README.md deleted file mode 100644 index 68b03270..00000000 --- a/vendor/agentos/examples/processes/README.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: "Processes" -description: "Process management inside the VM: exec, spawn, stdin, lifecycle, shell sessions, process events, and visibility." -category: "Processes & Shell" -order: 1 ---- - -Run commands and long-lived processes inside a VM, stream their output, and drive interactive shells. Reach for this whenever an agent needs to invoke tools, start a dev server, pipe data over stdin, or attach a terminal. - -## How it works - -A `server.ts` registers a VM with its software, and each script connects with `createClient` and grabs a VM via `client.vm.getOrCreate("my-agent")`. From there the VM handle exposes the full process surface: - -- **`exec`** — run a command to completion and collect `stdout`, `stderr`, and `exitCode` in one call. -- **`spawn` + lifecycle** — start a process for a `pid`, then `listProcesses`, `getProcess`, `waitProcess`, `stopProcess` (SIGTERM), and `killProcess` (SIGKILL). -- **stdin** — `writeProcessStdin` and `closeProcessStdin` to feed a running process, including an interactive `sh` (see `shell.ts`). -- **subscriptions** — call `agent.connect()` and use `onProcessOutput`, `onProcessExit`, `onShellData`, `onShellStderr`, and `onShellExit`. The connection filters RivetKit broadcasts to the requested process or shell. - -`visibility.ts` shows how to enumerate and inspect everything running in the VM. - -## Run it - -```bash -npm install -npx tsx server.ts & # start the VM registry on :6420 -npx tsx exec.ts # then run any of the scripts (spawn.ts, stdin.ts, shell.ts, ...) -``` - -Each script prints its process output and exit codes to the console. - -## Source - -View the source on GitHub: https://github.com/rivet-dev/agent-os/tree/main/examples/processes diff --git a/vendor/agentos/examples/processes/exec.ts b/vendor/agentos/examples/processes/exec.ts deleted file mode 100644 index 91e9defa..00000000 --- a/vendor/agentos/examples/processes/exec.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ endpoint: "http://localhost:6420" }); - -const result = await client.vm - .getOrCreate("my-agent") - .process.exec("echo hello && ls /home/agentos"); -console.log("stdout:", result.stdout); -console.log("stderr:", result.stderr); -console.log("exit code:", result.exitCode); diff --git a/vendor/agentos/examples/processes/lifecycle.ts b/vendor/agentos/examples/processes/lifecycle.ts deleted file mode 100644 index ee7db6f9..00000000 --- a/vendor/agentos/examples/processes/lifecycle.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); -const agent = client.vm.getOrCreate("my-agent"); - -const { pid } = await agent.process.spawn("node", ["/home/agentos/server.js"]); - -// List all processes tracked by the VM -const processes = await agent.process.list(); -for (const p of processes) { - console.log(p.pid, p.command, p.state); -} - -// Inspect a specific process by pid -const info = await agent.process.get(pid); -console.log(info.pid, info.state); - -// Graceful stop (SIGTERM) -await agent.process.signal(pid, "SIGTERM"); - -// Force kill (SIGKILL) -await agent.process.kill(pid); diff --git a/vendor/agentos/examples/processes/package.json b/vendor/agentos/examples/processes/package.json deleted file mode 100644 index b4550635..00000000 --- a/vendor/agentos/examples/processes/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-processes", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-sandbox": "workspace:*", - "sandbox-agent": "^0.4.2", - "dockerode": "^4.0.9", - "get-port": "^7.1.0", - "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", - "zod": "^4.1.11", - "@rivet-dev/agentos": "workspace:*", - "rivetkit": "catalog:rivetkit" - }, - "devDependencies": { - "@types/node": "^22.10.2", - "tsx": "^4.19.0", - "typescript": "^5.7.2" - } -} diff --git a/vendor/agentos/examples/processes/process-events.ts b/vendor/agentos/examples/processes/process-events.ts deleted file mode 100644 index 48f354ba..00000000 --- a/vendor/agentos/examples/processes/process-events.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ endpoint: "http://localhost:6420" }); -const conn = client.vm.getOrCreate("my-agent").connect(); -const { pid } = await conn.process.spawn("node", ["/home/agentos/server.js"]); - -conn.on("processOutput", (data) => { - if (data.pid !== pid) return; - // data.pid: number - // data.stream: "stdout" | "stderr" - // data.data: Uint8Array - const text = new TextDecoder().decode(data.data); - console.log(`[${data.pid}] ${data.stream}: ${text}`); -}); - -conn.on("processExit", (data) => { - if (data.pid !== pid) return; - // data.pid: number - // data.exitCode: number - console.log(`Process ${data.pid} exited with code ${data.exitCode}`); -}); diff --git a/vendor/agentos/examples/processes/server.ts b/vendor/agentos/examples/processes/server.ts deleted file mode 100644 index ba01a582..00000000 --- a/vendor/agentos/examples/processes/server.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; -import pi from "@agentos-software/pi"; - -const vm = agentOS({ - software: [pi], -}); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/processes/shell-events.ts b/vendor/agentos/examples/processes/shell-events.ts deleted file mode 100644 index 0557e8a8..00000000 --- a/vendor/agentos/examples/processes/shell-events.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ endpoint: "http://localhost:6420" }); -const conn = client.vm.getOrCreate("my-agent").connect(); -const { shellId } = await conn.terminal.open(); - -conn.on("shellData", (data) => { - if (data.shellId !== shellId) return; - // data.shellId: string - // data.data: Uint8Array - const text = new TextDecoder().decode(data.data); - process.stdout.write(text); -}); diff --git a/vendor/agentos/examples/processes/shell.ts b/vendor/agentos/examples/processes/shell.ts deleted file mode 100644 index d4665942..00000000 --- a/vendor/agentos/examples/processes/shell.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ endpoint: "http://localhost:6420" }); -const agent = client.vm.getOrCreate("my-agent"); -const conn = agent.connect(); - -// Spawn an interactive shell process -const { pid } = await agent.process.spawn("sh", []); - -// Stream this process's output as it is produced -conn.on("processOutput", (data) => { - if (data.pid !== pid) return; - const text = new TextDecoder().decode(data.data); - process.stdout.write(text); -}); - -// Drive it by writing commands to stdin -await agent.process.writeStdin(pid, "ls -la /home/agentos\n"); - -// Close stdin to let the shell exit, then wait for it -await agent.process.closeStdin(pid); -await agent.process.wait(pid); diff --git a/vendor/agentos/examples/processes/spawn.ts b/vendor/agentos/examples/processes/spawn.ts deleted file mode 100644 index 47dafed9..00000000 --- a/vendor/agentos/examples/processes/spawn.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ endpoint: "http://localhost:6420" }); -const agent = client.vm.getOrCreate("my-agent"); -const conn = agent.connect(); - -// Spawn a dev server -const { pid } = await agent.process.spawn("node", ["/home/agentos/server.js"]); - -// Subscribe to process output -conn.on("processOutput", (data) => { - if (data.pid !== pid) return; - const text = new TextDecoder().decode(data.data); - console.log(`[pid ${data.pid}] ${data.stream}: ${text}`); -}); - -conn.on("processExit", (data) => { - if (data.pid !== pid) return; - console.log(`[pid ${data.pid}] exited with code ${data.exitCode}`); -}); - -console.log("Started process:", pid); diff --git a/vendor/agentos/examples/processes/stdin.ts b/vendor/agentos/examples/processes/stdin.ts deleted file mode 100644 index e603ace5..00000000 --- a/vendor/agentos/examples/processes/stdin.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ endpoint: "http://localhost:6420" }); -const agent = client.vm.getOrCreate("my-agent"); - -const { pid } = await agent.process.spawn("cat", []); - -// Write to stdin -await agent.process.writeStdin(pid, "hello from stdin\n"); - -// Close stdin when done -await agent.process.closeStdin(pid); - -// Wait for the process to exit -const exitCode = await agent.process.wait(pid); -console.log("exit code:", exitCode); diff --git a/vendor/agentos/examples/processes/tsconfig.json b/vendor/agentos/examples/processes/tsconfig.json deleted file mode 100644 index e7937905..00000000 --- a/vendor/agentos/examples/processes/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "moduleResolution": "bundler", "noEmit": true, "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], "types": ["node"], "baseUrl": ".", - "paths": { - "@rivet-dev/agentos": ["../../packages/agentos/src/index.ts"], - "@rivet-dev/agentos/client": ["../../packages/agentos/src/client.ts"], - "@rivet-dev/agentos/react": ["../../packages/agentos/src/react.ts"] - } - }, - "include": ["**/*.ts", "**/*.tsx"] -} diff --git a/vendor/agentos/examples/processes/visibility.ts b/vendor/agentos/examples/processes/visibility.ts deleted file mode 100644 index f26153e1..00000000 --- a/vendor/agentos/examples/processes/visibility.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ endpoint: "http://localhost:6420" }); -const agent = client.vm.getOrCreate("my-agent"); - -// All processes spawned in the VM -const all = await agent.process.list(); -for (const p of all) { - console.log(p.pid, p.command, p.state); -} - -// Inspect a single process by pid -const first = all[0]; -if (first) { - const info = await agent.process.get(first.pid); - console.log(info.pid, info.command, "status:", info.state); -} diff --git a/vendor/agentos/examples/quickstart-app/Agent.tsx b/vendor/agentos/examples/quickstart-app/Agent.tsx deleted file mode 100644 index 18457c2d..00000000 --- a/vendor/agentos/examples/quickstart-app/Agent.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { createRivetKit } from "@rivet-dev/agentos/react"; -import { useState } from "react"; -import type { registry } from "./server"; - -const { useActor } = createRivetKit("http://localhost:6420"); - -export function Agent() { - const [log, setLog] = useState(""); - const agent = useActor({ name: "vm", key: "my-agent" }); - - // Stream agent events into component state - agent.useEvent("sessionEvent", (event) => { - setLog((prev) => prev + JSON.stringify(event) + "\n"); - }); - - async function run() { - // In production, inject credentials on the server (see /docs/models-and-credentials) - const connection = agent.connection; - if (!connection) return; - - await connection.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.VITE_ANTHROPIC_API_KEY! }, - }); - await connection.sessions.prompt({ - content: [ - { - type: "text", - text: "Write a hello world script to /workspace/hello.js", - }, - ], - }); - } - - return ( -
- -
{log}
-
- ); -} diff --git a/vendor/agentos/examples/quickstart-app/README.md b/vendor/agentos/examples/quickstart-app/README.md deleted file mode 100644 index 535a6f94..00000000 --- a/vendor/agentos/examples/quickstart-app/README.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: "Quickstart App" -description: "Full RivetKit app: an agentOS server registry plus a client that streams session events." -category: "Quickstart" -order: 14 ---- - -A complete starting point that wires an agentOS server to a client. Reach for this when you want the whole loop in one place: a server that registers a VM with agent software, and a client that opens a session, sends a prompt, and streams the agent's events back. - -## How it works - -`server.ts` builds a VM with `agentOS({ software: [pi] })`, registers it via `setup`, and starts the RivetKit registry. The client connects to that registry, calls `getOrCreate` to obtain a VM handle, and subscribes to `sessionEvent` over a live connection. It then creates a `pi` session (passing the Anthropic API key through `env`), sends a prompt, and reads back the file the agent wrote to `/workspace`. An `Agent.tsx` component shows the same flow from React, streaming events into component state with `useEvent`. - -## Run it - -```sh -npm install -ANTHROPIC_API_KEY=sk-... npx tsx server.ts # start the registry -ANTHROPIC_API_KEY=sk-... npx tsx client.ts # in another shell, drive a session -``` - -The client prints streamed session events and the contents of the `hello.js` file the agent creates. - -## Source - -View the source on GitHub: https://github.com/rivet-dev/agent-os/tree/main/examples/quickstart-app diff --git a/vendor/agentos/examples/quickstart-app/client.ts b/vendor/agentos/examples/quickstart-app/client.ts deleted file mode 100644 index 2947b819..00000000 --- a/vendor/agentos/examples/quickstart-app/client.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); -const handle = client.vm.getOrCreate("my-agent"); - -// Subscribe to streaming events. The payload is inferred from the event schema. -const conn = handle.connect(); -conn.on("sessionEvent", (event) => { - console.log(event); -}); - -// Open a durable session and send a prompt. -await handle.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, -}); -await handle.sessions.prompt({ - content: [ - { type: "text", text: "Write a hello world script to /workspace/hello.js" }, - ], -}); - -// Read the file the agent created -const content = await handle.filesystem.readFile("/workspace/hello.js"); -console.log(new TextDecoder().decode(content)); diff --git a/vendor/agentos/examples/quickstart-app/package.json b/vendor/agentos/examples/quickstart-app/package.json deleted file mode 100644 index 0272be75..00000000 --- a/vendor/agentos/examples/quickstart-app/package.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-quickstart-app", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-sandbox": "workspace:*", - "sandbox-agent": "^0.4.2", - "dockerode": "^4.0.9", - "get-port": "^7.1.0", - "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", - "zod": "^4.1.11", - "@rivet-dev/agentos": "workspace:*", - "rivetkit": "catalog:rivetkit", - "react": "^18.3.1", - "react-dom": "^18.3.1" - }, - "devDependencies": { - "@types/node": "^22.10.2", - "@types/react": "^18.3.1", - "tsx": "^4.19.0", - "typescript": "^5.7.2" - } -} diff --git a/vendor/agentos/examples/quickstart-app/server.ts b/vendor/agentos/examples/quickstart-app/server.ts deleted file mode 100644 index ba01a582..00000000 --- a/vendor/agentos/examples/quickstart-app/server.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; -import pi from "@agentos-software/pi"; - -const vm = agentOS({ - software: [pi], -}); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/quickstart-app/tsconfig.json b/vendor/agentos/examples/quickstart-app/tsconfig.json deleted file mode 100644 index e7937905..00000000 --- a/vendor/agentos/examples/quickstart-app/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "moduleResolution": "bundler", "noEmit": true, "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], "types": ["node"], "baseUrl": ".", - "paths": { - "@rivet-dev/agentos": ["../../packages/agentos/src/index.ts"], - "@rivet-dev/agentos/client": ["../../packages/agentos/src/client.ts"], - "@rivet-dev/agentos/react": ["../../packages/agentos/src/react.ts"] - } - }, - "include": ["**/*.ts", "**/*.tsx"] -} diff --git a/vendor/agentos/examples/quickstart/agent-session/README.md b/vendor/agentos/examples/quickstart/agent-session/README.md deleted file mode 100644 index 3a60fe63..00000000 --- a/vendor/agentos/examples/quickstart/agent-session/README.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: "Agent Session" -description: "Create an agent session and send a prompt using a coding agent (Pi, Claude, or OpenCode)." -category: "Quickstart" -order: 12 ---- - -Run a coding agent inside an Agent OS VM, send it a prompt, and read back its reply. Reach for this when you want to drive an agent (Pi, Claude, or OpenCode) programmatically rather than through a chat UI. - -## How it works - -Register the agent software bundles when you `AgentOs.create` a VM, then call `openSession({ agent, env })` for the agent of your choice; omitting `sessionId` selects `main`. Subscribe with `onSessionEvent` to watch streamed text and tool use as it happens, call `prompt({ content })` to send a message, and use `unloadSession()` to release the adapter while retaining durable history. Agents read credentials such as `ANTHROPIC_API_KEY` from the session `env`. - -## Run it - -```sh -npm install -ANTHROPIC_API_KEY=sk-... npx tsx index.ts -``` - -Expected: the script prints a session ID, streams session events, and logs the agent's answer (`4`). - -## Source - -View the source on GitHub: https://github.com/rivet-dev/agent-os/tree/main/examples/quickstart/agent-session diff --git a/vendor/agentos/examples/quickstart/agent-session/index.ts b/vendor/agentos/examples/quickstart/agent-session/index.ts deleted file mode 100644 index 8491478b..00000000 --- a/vendor/agentos/examples/quickstart/agent-session/index.ts +++ /dev/null @@ -1,43 +0,0 @@ -// Create an agent session and send a prompt using a coding agent. -// -// NOTE: This example requires an API key for the chosen agent and a working -// agent runtime. It may not complete in all environments. - -import claude from "@agentos-software/claude-code"; -import opencode from "@agentos-software/opencode"; -import pi from "@agentos-software/pi"; -import type { SoftwareInput } from "@rivet-dev/agentos-core"; -import { AgentOs } from "@rivet-dev/agentos-core"; - -const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY; - -const software: SoftwareInput[] = [claude, opencode, pi]; - -const vm = await AgentOs.create({ - software, -}); - -// Change the agent here: "claude", "opencode", or "pi" -const agent = "pi"; - -const env: Record = {}; -if (ANTHROPIC_API_KEY) env.ANTHROPIC_API_KEY = ANTHROPIC_API_KEY; - -await vm.sessions.open({ agent, env }); - -// Listen for session events (streamed text, tool use, etc.) -vm.onSessionEvent((event) => { - console.log("Event:", JSON.stringify(event, null, 2)); -}); - -// Send a prompt and wait for the response -const result = await vm.sessions.prompt({ - content: [ - { type: "text", text: "What is 2 + 2? Reply with just the number." }, - ], -}); -console.log("Response:", result.message?.content ?? []); - -// Close the session -await vm.sessions.delete(); -await vm.dispose(); diff --git a/vendor/agentos/examples/quickstart/agent-session/package.json b/vendor/agentos/examples/quickstart/agent-session/package.json deleted file mode 100644 index 8d3d54e4..00000000 --- a/vendor/agentos/examples/quickstart/agent-session/package.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-quickstart-agent-session", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "start": "node --import tsx index.ts", - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@rivet-dev/agentos-core": "workspace:*", - "@rivet-dev/agentos-sandbox": "workspace:*", - "sandbox-agent": "^0.4.2", - "dockerode": "^4.0.9", - "get-port": "^7.1.0", - "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", - "zod": "^4.1.11" - }, - "devDependencies": { - "@types/node": "^22.10.2", - "tsx": "^4.19.0", - "typescript": "^5.7.2" - } -} diff --git a/vendor/agentos/examples/quickstart/agent-session/tsconfig.json b/vendor/agentos/examples/quickstart/agent-session/tsconfig.json deleted file mode 100644 index b12309a7..00000000 --- a/vendor/agentos/examples/quickstart/agent-session/tsconfig.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "extends": "../../../tsconfig.base.json", - "compilerOptions": { - "module": "NodeNext", - "moduleResolution": "NodeNext", - "esModuleInterop": true, - "noEmit": true - }, - "include": ["*.ts"], - "exclude": ["node_modules", "dist"] -} diff --git a/vendor/agentos/examples/quickstart/bash/package.json b/vendor/agentos/examples/quickstart/bash/package.json index 61979d59..a7c85504 100644 --- a/vendor/agentos/examples/quickstart/bash/package.json +++ b/vendor/agentos/examples/quickstart/bash/package.json @@ -14,9 +14,6 @@ "dockerode": "^4.0.9", "get-port": "^7.1.0", "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", "zod": "^4.1.11" }, "devDependencies": { diff --git a/vendor/agentos/examples/quickstart/cron/package.json b/vendor/agentos/examples/quickstart/cron/package.json index 7fdc1ac4..24051970 100644 --- a/vendor/agentos/examples/quickstart/cron/package.json +++ b/vendor/agentos/examples/quickstart/cron/package.json @@ -14,9 +14,6 @@ "dockerode": "^4.0.9", "get-port": "^7.1.0", "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", "zod": "^4.1.11" }, "devDependencies": { diff --git a/vendor/agentos/examples/quickstart/filesystem/package.json b/vendor/agentos/examples/quickstart/filesystem/package.json index fc54f781..98a6aee4 100644 --- a/vendor/agentos/examples/quickstart/filesystem/package.json +++ b/vendor/agentos/examples/quickstart/filesystem/package.json @@ -14,9 +14,6 @@ "dockerode": "^4.0.9", "get-port": "^7.1.0", "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", "zod": "^4.1.11" }, "devDependencies": { diff --git a/vendor/agentos/examples/quickstart/git/index.ts b/vendor/agentos/examples/quickstart/git/index.ts index 7887a775..67e96903 100644 --- a/vendor/agentos/examples/quickstart/git/index.ts +++ b/vendor/agentos/examples/quickstart/git/index.ts @@ -57,7 +57,11 @@ async function run(command: string): Promise { if (result.exitCode !== 0) { throw new Error(`command failed: ${command}\n${stderr || stdout}`); } - return { stdout, stderr, exitCode: result.exitCode ?? 0 }; + return { + exitCode: result.exitCode, + stdout: result.stdout ?? "", + stderr: result.stderr ?? "", + }; } await run("git init /tmp/origin"); diff --git a/vendor/agentos/examples/quickstart/git/package.json b/vendor/agentos/examples/quickstart/git/package.json index 80e4b63c..808b44aa 100644 --- a/vendor/agentos/examples/quickstart/git/package.json +++ b/vendor/agentos/examples/quickstart/git/package.json @@ -14,9 +14,6 @@ "dockerode": "^4.0.9", "get-port": "^7.1.0", "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", "zod": "^4.1.11" }, "devDependencies": { diff --git a/vendor/agentos/examples/quickstart/hello-world/package.json b/vendor/agentos/examples/quickstart/hello-world/package.json index dbabf99c..f1497bb2 100644 --- a/vendor/agentos/examples/quickstart/hello-world/package.json +++ b/vendor/agentos/examples/quickstart/hello-world/package.json @@ -14,9 +14,6 @@ "dockerode": "^4.0.9", "get-port": "^7.1.0", "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", "zod": "^4.1.11" }, "devDependencies": { diff --git a/vendor/agentos/examples/quickstart/network/README.md b/vendor/agentos/examples/quickstart/network/README.md index bcefd614..01de5197 100644 --- a/vendor/agentos/examples/quickstart/network/README.md +++ b/vendor/agentos/examples/quickstart/network/README.md @@ -13,7 +13,7 @@ Run a real HTTP server inside the VM and call it from your host code. Reach for Create a VM with `network` and `childProcess` permissions, then `filesystem.writeFile` a small Node server script into the VM. `vm.process.spawn` launches it, and the server prints its bound port on stdout, which an `onProcessOutput` subscription parses out. With the port in hand, `vm.network.httpRequest({ port, path })` routes a buffered request to that in-VM server over localhost and returns the serializable `HttpResponse` DTO. Cleanup waits briefly on the process and disposes the VM. -> Preview URLs (`agent.createPreviewUrl`) live only in the RivetKit actor wrapper, not the embedded API. See `examples/networking/`. +> Preview URLs (`network.preview.create`) live only in the static actor, not the embedded API. See `examples/networking/`. ## Run it diff --git a/vendor/agentos/examples/quickstart/network/index.ts b/vendor/agentos/examples/quickstart/network/index.ts index c8b3c4d1..47ecc02b 100644 --- a/vendor/agentos/examples/quickstart/network/index.ts +++ b/vendor/agentos/examples/quickstart/network/index.ts @@ -1,8 +1,7 @@ // Networking: start a server inside the VM and fetch from it. // // vm.network.httpRequest() routes HTTP requests to services running inside the VM. -// Note: Preview URLs (agent.createPreviewUrl) are only available in the -// RivetKit actor wrapper, not in the embedded API. See the actor examples for that. +// Public preview URLs are provided by a hosting service, not embedded Core. import { AgentOs } from "@rivet-dev/agentos-core"; diff --git a/vendor/agentos/examples/quickstart/network/package.json b/vendor/agentos/examples/quickstart/network/package.json index d8ac7ae7..d54eb8c5 100644 --- a/vendor/agentos/examples/quickstart/network/package.json +++ b/vendor/agentos/examples/quickstart/network/package.json @@ -14,9 +14,6 @@ "dockerode": "^4.0.9", "get-port": "^7.1.0", "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", "zod": "^4.1.11" }, "devDependencies": { diff --git a/vendor/agentos/examples/quickstart/nodejs/package.json b/vendor/agentos/examples/quickstart/nodejs/package.json index 1feb7bda..f29d71fc 100644 --- a/vendor/agentos/examples/quickstart/nodejs/package.json +++ b/vendor/agentos/examples/quickstart/nodejs/package.json @@ -14,9 +14,6 @@ "dockerode": "^4.0.9", "get-port": "^7.1.0", "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", "zod": "^4.1.11" }, "devDependencies": { diff --git a/vendor/agentos/examples/quickstart/package.json b/vendor/agentos/examples/quickstart/package.json index 89ee0262..52df74f3 100644 --- a/vendor/agentos/examples/quickstart/package.json +++ b/vendor/agentos/examples/quickstart/package.json @@ -28,9 +28,6 @@ "dockerode": "^4.0.9", "get-port": "^7.1.0", "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", "zod": "^4.1.11" }, "devDependencies": { diff --git a/vendor/agentos/examples/quickstart/pi-extensions/README.md b/vendor/agentos/examples/quickstart/pi-extensions/README.md deleted file mode 100644 index 975b669f..00000000 --- a/vendor/agentos/examples/quickstart/pi-extensions/README.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: "Pi Extensions" -description: "Write a custom Pi extension into the VM and have Pi discover and load it at session start." -category: "Quickstart" -order: 13 ---- - -# Pi Extensions - -Drop a custom Pi extension into the VM before a session starts and let Pi discover, load, and run it automatically. Reach for this when you want to register tools, reshape the system prompt, or hook agent lifecycle events without forking the agent. - -## How it works - -Pi scans `~/.pi/agent/extensions/` and `/.pi/extensions/` for `.js` files at session start. Each file exports a default factory that receives Pi's `ExtensionAPI`, so it can register tools, subscribe to lifecycle events, and mutate the system prompt. - -This example boots a VM with the Pi software bundle, writes a small extension into `/home/agentos/.pi/agent/extensions/` that hooks `before_agent_start` to prepend a mandatory `EXTENSION_OK:` prefix to the system prompt, then creates a Pi session and prompts it. If the reply carries the prefix, the extension was loaded and applied. - -## Run it - -```sh -npm install -ANTHROPIC_API_KEY=sk-... npx tsx index.ts -``` - -Expected: the agent answers and prefixes its response with `EXTENSION_OK:`, printing `SUCCESS — Pi extension loaded and modified the system prompt.` - -## Source - -View the source on GitHub: https://github.com/rivet-dev/agent-os/tree/main/examples/quickstart/pi-extensions diff --git a/vendor/agentos/examples/quickstart/pi-extensions/index.ts b/vendor/agentos/examples/quickstart/pi-extensions/index.ts deleted file mode 100644 index 46f28dca..00000000 --- a/vendor/agentos/examples/quickstart/pi-extensions/index.ts +++ /dev/null @@ -1,131 +0,0 @@ -// Pi extensions: write a custom extension into the VM before creating a -// session and verify Pi discovers and loads it. -// -// The adapter scans ~/.pi/agent/extensions/ and /.pi/extensions/ for -// .js files at session start. Each file exports a function that receives -// Pi's ExtensionAPI, which can register tools, modify the system prompt, -// subscribe to lifecycle events, and more. -// -// Extensions should export a default factory function. -// -// NOTE: Requires ANTHROPIC_API_KEY to be set. To run this against llmock, -// also set ANTHROPIC_BASE_URL and the example will write ~/.pi/agent/models.json -// inside the VM before creating the session. - -import { createRequire } from "node:module"; -import { dirname, join, resolve } from "node:path"; -import pi from "@agentos-software/pi"; -import { AgentOs, nodeModulesMount } from "@rivet-dev/agentos-core"; - -const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY; -const ANTHROPIC_BASE_URL = process.env.ANTHROPIC_BASE_URL; -if (!ANTHROPIC_API_KEY) { - console.error("Set ANTHROPIC_API_KEY to run this example."); - process.exit(1); -} - -const require = createRequire(import.meta.url); -const MODULE_ACCESS_CWD = resolve( - dirname(require.resolve("@rivet-dev/agentos-core")), - "..", -); -const HOME_DIR = "/home/agentos"; -const WORKSPACE_DIR = `${HOME_DIR}/workspace`; - -// ── Extension source code ────────────────────────────────────────── -// -// This extension hooks Pi's before_agent_start event to append a custom -// instruction to the system prompt. No imports needed — the ExtensionAPI -// is passed as a parameter. - -const extensionSource = ` -export default function(pi) { - pi.on("before_agent_start", async (event) => { - return { - systemPrompt: event.systemPrompt + - "\\n\\nCRITICAL INSTRUCTION: You MUST begin every response with " + - "exactly the phrase 'EXTENSION_OK: ' followed by your answer. " + - "This is mandatory and non-negotiable." - }; - }); -} -`; - -// ── Create VM and write extension ────────────────────────────────── - -const vm = await AgentOs.create({ - ...(ANTHROPIC_BASE_URL - ? { - loopbackExemptPorts: [Number(new URL(ANTHROPIC_BASE_URL).port)], - } - : {}), - mounts: [nodeModulesMount(join(MODULE_ACCESS_CWD, "node_modules"))], - software: [pi], -}); - -// Write the extension into Pi's global extensions directory. -// In the VM, HOME is /home/agentos, so ~/.pi/agent/extensions/ resolves there. -const extensionsDir = "/home/agentos/.pi/agent/extensions"; -await vm.filesystem.mkdir(extensionsDir, { recursive: true }); -await vm.filesystem.mkdir(WORKSPACE_DIR, { recursive: true }); -await vm.filesystem.writeFile( - `${extensionsDir}/custom-greeting.js`, - extensionSource, -); - -if (ANTHROPIC_BASE_URL) { - await vm.filesystem.writeFile( - `${HOME_DIR}/.pi/agent/models.json`, - JSON.stringify( - { - providers: { - anthropic: { - baseUrl: ANTHROPIC_BASE_URL, - apiKey: ANTHROPIC_API_KEY, - }, - }, - }, - null, - 2, - ), - ); -} - -console.log("Extension written. Creating Pi session...\n"); - -// ── Create session and prompt ────────────────────────────────────── - -await vm.sessions.open({ - agent: "pi", - cwd: WORKSPACE_DIR, - env: { - HOME: HOME_DIR, - ANTHROPIC_API_KEY, - ...(ANTHROPIC_BASE_URL ? { ANTHROPIC_BASE_URL } : {}), - }, -}); - -// Ask a simple question — if the extension loaded, the agent will -// prefix its response with "EXTENSION_OK: " -const result = await vm.sessions.prompt({ - content: [ - { type: "text", text: "What is 2 + 2? Reply with just the number." }, - ], -}); -const responseText = - result.message?.content - .filter((block) => block.type === "text") - .map((block) => block.text) - .join("") ?? ""; -console.log("Agent:", responseText); - -// ── Verify ───────────────────────────────────────────────────────── - -if (responseText.includes("EXTENSION_OK:")) { - console.log("SUCCESS — Pi extension loaded and modified the system prompt."); -} else { - throw new Error("FAIL — Response did not include the expected prefix."); -} - -await vm.sessions.delete(); -await vm.dispose(); diff --git a/vendor/agentos/examples/quickstart/pi-extensions/package.json b/vendor/agentos/examples/quickstart/pi-extensions/package.json deleted file mode 100644 index 09a53108..00000000 --- a/vendor/agentos/examples/quickstart/pi-extensions/package.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-quickstart-pi-extensions", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "start": "node --import tsx index.ts", - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@rivet-dev/agentos-core": "workspace:*", - "@rivet-dev/agentos-sandbox": "workspace:*", - "sandbox-agent": "^0.4.2", - "dockerode": "^4.0.9", - "get-port": "^7.1.0", - "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", - "zod": "^4.1.11" - }, - "devDependencies": { - "@types/node": "^22.10.2", - "tsx": "^4.19.0", - "typescript": "^5.7.2" - } -} diff --git a/vendor/agentos/examples/quickstart/pi-extensions/tsconfig.json b/vendor/agentos/examples/quickstart/pi-extensions/tsconfig.json deleted file mode 100644 index b12309a7..00000000 --- a/vendor/agentos/examples/quickstart/pi-extensions/tsconfig.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "extends": "../../../tsconfig.base.json", - "compilerOptions": { - "module": "NodeNext", - "moduleResolution": "NodeNext", - "esModuleInterop": true, - "noEmit": true - }, - "include": ["*.ts"], - "exclude": ["node_modules", "dist"] -} diff --git a/vendor/agentos/examples/quickstart/processes/index.ts b/vendor/agentos/examples/quickstart/processes/index.ts index 35f07128..c99b4508 100644 --- a/vendor/agentos/examples/quickstart/processes/index.ts +++ b/vendor/agentos/examples/quickstart/processes/index.ts @@ -5,30 +5,27 @@ import { AgentOs } from "@rivet-dev/agentos-core"; const vm = await AgentOs.create(); // Run shell commands with exec() -// exec() captures nothing unless you ask for it. -const capture = { output: { capture: "all" } } as const; -const result = await vm.process.exec("echo 'hello from shell'", capture); -console.log("exec stdout:", (result.stdout ?? "").trim()); +const result = await vm.process.exec("echo 'hello from shell'"); +console.log("exec stdout:", result.stdout?.trim()); console.log("exec exit code:", result.exitCode); // Shell pipeline -const piped = await vm.process.exec("echo hello | tr a-z A-Z", capture); -console.log("piped:", (piped.stdout ?? "").trim()); +const piped = await vm.process.exec("echo hello | tr a-z A-Z"); +console.log("piped:", piped.stdout?.trim()); // grep await vm.filesystem.writeFile( "/tmp/data.txt", "apple\nbanana\ncherry\napricot\n", ); -const grepped = await vm.process.exec("grep ap /tmp/data.txt", capture); -console.log("grep:", (grepped.stdout ?? "").trim()); +const grepped = await vm.process.exec("grep ap /tmp/data.txt"); +console.log("grep:", grepped.stdout?.trim()); // sed const sedResult = await vm.process.exec( "echo 'hello world' | sed 's/world/agentOS/'", - capture, ); -console.log("sed:", (sedResult.stdout ?? "").trim()); +console.log("sed:", sedResult.stdout?.trim()); // Spawn a Node.js script and wait for it to complete await vm.filesystem.writeFile( diff --git a/vendor/agentos/examples/quickstart/processes/package.json b/vendor/agentos/examples/quickstart/processes/package.json index cf1725cd..ad904a60 100644 --- a/vendor/agentos/examples/quickstart/processes/package.json +++ b/vendor/agentos/examples/quickstart/processes/package.json @@ -14,9 +14,6 @@ "dockerode": "^4.0.9", "get-port": "^7.1.0", "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", "zod": "^4.1.11" }, "devDependencies": { diff --git a/vendor/agentos/examples/quickstart/python/index.ts b/vendor/agentos/examples/quickstart/python/index.ts index 53d7b63f..2a00a23d 100644 --- a/vendor/agentos/examples/quickstart/python/index.ts +++ b/vendor/agentos/examples/quickstart/python/index.ts @@ -1,4 +1,4 @@ -// Run a Python program inside an AgentOS VM. +// Run a Python program inside an agentOS VM. import { AgentOs } from "@rivet-dev/agentos-core"; diff --git a/vendor/agentos/examples/quickstart/s3-filesystem/package.json b/vendor/agentos/examples/quickstart/s3-filesystem/package.json index 77bfe35e..fa24bb47 100644 --- a/vendor/agentos/examples/quickstart/s3-filesystem/package.json +++ b/vendor/agentos/examples/quickstart/s3-filesystem/package.json @@ -14,9 +14,6 @@ "dockerode": "^4.0.9", "get-port": "^7.1.0", "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", "zod": "^4.1.11" }, "devDependencies": { diff --git a/vendor/agentos/examples/quickstart/sandbox/README.md b/vendor/agentos/examples/quickstart/sandbox/README.md index a99d0de7..34bad586 100644 --- a/vendor/agentos/examples/quickstart/sandbox/README.md +++ b/vendor/agentos/examples/quickstart/sandbox/README.md @@ -9,7 +9,7 @@ Back a VM with a Docker-backed sandbox so guest reads, writes, and commands run ## How it works -The `docker()` provider starts one Docker container for the VM. agentOS mounts its filesystem at `/mnt/sandbox`, registers a `sandbox` host-function collection for running commands, and destroys the container when the VM is disposed. Set `SKIP_DOCKER=1` to skip the example when Docker is unavailable. +The `docker()` provider starts one Docker container for the VM. agentOS mounts its filesystem at `/mnt/sandbox`, registers a `sandbox` binding collection for running commands, and destroys the container when the VM is disposed. Set `SKIP_DOCKER=1` to no-op the example where Docker is unavailable. ## Run it diff --git a/vendor/agentos/examples/quickstart/sandbox/index.ts b/vendor/agentos/examples/quickstart/sandbox/index.ts index 07939ff6..b5af5b4a 100644 --- a/vendor/agentos/examples/quickstart/sandbox/index.ts +++ b/vendor/agentos/examples/quickstart/sandbox/index.ts @@ -44,30 +44,6 @@ try { const processList = await vm.process.exec("agentos-sandbox list-processes"); console.log("Sandbox processes:", (processList.stdout ?? "").trim()); - const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY; - if (ANTHROPIC_API_KEY) { - await vm.sessions.open({ - agent: "pi", - cwd: SANDBOX_MOUNT, - env: { ANTHROPIC_API_KEY }, - }); - const result = await vm.sessions.prompt({ - content: [ - { - type: "text", - text: "Create a C source file named fib.c in the current directory that prints Fibonacci numbers.", - }, - ], - }); - console.log("Agent:", result.message?.content ?? []); - if (!(await vm.filesystem.exists(`${SANDBOX_MOUNT}/fib.c`))) { - throw new Error(`Expected the agent to create ${SANDBOX_MOUNT}/fib.c`); - } - console.log(`Verified ${SANDBOX_MOUNT}/fib.c exists.`); - await vm.sessions.delete(); - } else { - console.log("Skipping agent prompt because ANTHROPIC_API_KEY is not set."); - } } finally { await vm.dispose(); } diff --git a/vendor/agentos/examples/quickstart/sandbox/package.json b/vendor/agentos/examples/quickstart/sandbox/package.json index d369dd9c..fd0c5998 100644 --- a/vendor/agentos/examples/quickstart/sandbox/package.json +++ b/vendor/agentos/examples/quickstart/sandbox/package.json @@ -14,9 +14,6 @@ "dockerode": "^4.0.9", "get-port": "^7.1.0", "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", "zod": "^4.1.11" }, "devDependencies": { diff --git a/vendor/agentos/examples/resource-limits/README.md b/vendor/agentos/examples/resource-limits/README.md deleted file mode 100644 index 488f45e3..00000000 --- a/vendor/agentos/examples/resource-limits/README.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: "Resource Limits" -description: "Configure VM resource limits, JavaScript CPU/wall-clock budgets, Python caps, and WASM runtime limits." -category: "Reference" -order: 4 ---- - -Cap how much of the host a VM can consume. Reach for this when you run untrusted or agent-generated code and need hard ceilings on processes, file descriptors, sockets, filesystem storage, JavaScript CPU time, Python execution, and WASM runtime work. - -## How it works - -The VM accepts a typed `limits` block when you call `agentOS({ ... })`. Kernel resources live under `limits.resources`; JavaScript, Python, and WASM runtime limits live under `limits.jsRuntime`, `limits.python`, and `limits.wasm`. The sidecar forwards these over the VM creation wire, so guest env vars cannot raise or override its own caps. - -## Run it - -```sh -npm install -npx tsx server.ts -``` - -This starts a registry whose VM is provisioned with the configured resource caps. - -## Source - -View the source on GitHub: https://github.com/rivet-dev/agentos/tree/main/examples/resource-limits diff --git a/vendor/agentos/examples/resource-limits/package.json b/vendor/agentos/examples/resource-limits/package.json deleted file mode 100644 index f2091698..00000000 --- a/vendor/agentos/examples/resource-limits/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-resource-limits", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-sandbox": "workspace:*", - "sandbox-agent": "^0.4.2", - "dockerode": "^4.0.9", - "get-port": "^7.1.0", - "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", - "zod": "^4.1.11", - "@rivet-dev/agentos": "workspace:*", - "rivetkit": "catalog:rivetkit" - }, - "devDependencies": { - "@types/node": "^22.10.2", - "tsx": "^4.19.0", - "typescript": "^5.7.2" - } -} diff --git a/vendor/agentos/examples/resource-limits/server.ts b/vendor/agentos/examples/resource-limits/server.ts deleted file mode 100644 index 8037333f..00000000 --- a/vendor/agentos/examples/resource-limits/server.ts +++ /dev/null @@ -1,40 +0,0 @@ -import pi from "@agentos-software/pi"; -import { agentOS, setup } from "@rivet-dev/agentos"; - -const vm = agentOS({ - software: [pi], - limits: { - resources: { - maxProcesses: 64, // concurrent processes - maxOpenFds: 256, // open file descriptors - maxSockets: 128, // open sockets - maxFilesystemBytes: 256 * 1024 * 1024, // VFS storage budget - maxWasmFuel: 30_000, // WASM execution budget - maxWasmMemoryBytes: 128 * 1024 * 1024, // WASM linear memory - maxWasmStackBytes: 4 * 1024 * 1024, // WASM call-stack ceiling - }, - process: { - pendingStdinBytes: 64 * 1024 * 1024, // stdin waiting on a kernel pipe - pendingEventCount: 10_000, // queued process/runtime events per stage - pendingEventBytes: 64 * 1024 * 1024, // queued event payload per stage - }, - jsRuntime: { - v8HeapLimitMb: 128, // JS isolate heap - cpuTimeLimitMs: 30_000, // active JS CPU time - wallClockLimitMs: 0, // 0 disables elapsed wall-clock cutoff - importCacheMaterializeTimeoutMs: 30_000, // Node import-cache setup - syncRpcWaitTimeoutMs: 30_000, // host sync-RPC wait - }, - python: { - executionTimeoutMs: 300_000, // Python wall-clock execution - maxOldSpaceMb: 0, // 0 keeps the Pyodide runner default - }, - wasm: { - prewarmTimeoutMs: 30_000, // WASM compile-cache warmup - runnerHeapLimitMb: 2048, // trusted WASI runner V8 heap - }, - }, -}); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/resource-limits/tsconfig.json b/vendor/agentos/examples/resource-limits/tsconfig.json deleted file mode 100644 index e7937905..00000000 --- a/vendor/agentos/examples/resource-limits/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "moduleResolution": "bundler", "noEmit": true, "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], "types": ["node"], "baseUrl": ".", - "paths": { - "@rivet-dev/agentos": ["../../packages/agentos/src/index.ts"], - "@rivet-dev/agentos/client": ["../../packages/agentos/src/client.ts"], - "@rivet-dev/agentos/react": ["../../packages/agentos/src/react.ts"] - } - }, - "include": ["**/*.ts", "**/*.tsx"] -} diff --git a/vendor/agentos/examples/sandbox/README.md b/vendor/agentos/examples/sandbox/README.md deleted file mode 100644 index 04e115e5..00000000 --- a/vendor/agentos/examples/sandbox/README.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: "Sandbox" -description: "Mount a Sandbox Agent (Docker) filesystem into the VM and expose its process management as host functions." -category: "Reference" -order: 5 ---- - -Back a VM with a real Sandbox Agent container: the sandbox's filesystem appears as a mount inside the VM, and its process management is callable through host functions. Reach for this when you want guest code to read, write, and run against a live Docker sandbox instead of the in-memory VFS. - -## How it works - -The server passes `docker()` as the sandbox provider. Each actor VM gets its own Docker sandbox, mounted under `/home/agentos/sandbox`, plus a `sandbox` host-function collection surfaced as the `agentos-sandbox` CLI command. Disposing the VM destroys its sandbox. - -## Run it - -```sh -npm install -npm run server # starts the VM with the sandbox mount and host functions -npm run client # writes a file, runs it, and streams process output -``` - -You should see `hello` printed from a file executed inside the Docker sandbox. - -## Source - -View the source on GitHub: https://github.com/rivet-dev/agent-os/tree/main/examples/sandbox diff --git a/vendor/agentos/examples/sandbox/client.ts b/vendor/agentos/examples/sandbox/client.ts deleted file mode 100644 index 5d94a880..00000000 --- a/vendor/agentos/examples/sandbox/client.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); -const vm = client.vm.getOrCreate("my-agent"); - -// Write code via the filesystem. The /home/agentos/sandbox mount maps to the sandbox root. -await vm.filesystem.writeFile("/home/agentos/sandbox/app/index.ts", 'console.log("hello")'); - -// Run it inside the sandbox through the generated host-function command. -// The VM path above maps to /app/index.ts at the sandbox root. -const result = await vm.process.exec( - "agentos-sandbox run-command --command node --args /app/index.ts", -); -console.log(result.stdout); // "hello\n" - -const install = await vm.process.exec( - "agentos-sandbox run-command --command npm --args install --args --prefix --args /app", -); -console.log(install.exitCode, install.stdout); - -// Spawn a long-running process and stream its output. Connect to the VM, -// then subscribe to `processOutput` events for the spawned pid. -const { pid } = await vm.process.spawn("npm", ["run", "dev", "--prefix", "/home/agentos/sandbox/app"]); -const conn = vm.connect(); - conn.on("processOutput", (payload) => { - if (payload.pid !== pid) return; - console.log(payload.stream, new TextDecoder().decode(payload.data)); -}); diff --git a/vendor/agentos/examples/sandbox/existing-client.ts b/vendor/agentos/examples/sandbox/existing-client.ts deleted file mode 100644 index 62f5b775..00000000 --- a/vendor/agentos/examples/sandbox/existing-client.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { AgentOs } from "@rivet-dev/agentos-core"; -import { SandboxAgent } from "sandbox-agent"; -import { docker } from "sandbox-agent/docker"; - -const sandbox = await SandboxAgent.start({ sandbox: docker() }); - -const vm = await AgentOs.create({ - sandbox: { - client: sandbox, - dispose: () => sandbox.destroySandbox(), - }, -}); - -await vm.dispose(); diff --git a/vendor/agentos/examples/sandbox/package.json b/vendor/agentos/examples/sandbox/package.json deleted file mode 100644 index d79b3170..00000000 --- a/vendor/agentos/examples/sandbox/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-sandbox", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-core": "workspace:*", - "@rivet-dev/agentos-sandbox": "workspace:*", - "sandbox-agent": "^0.4.2", - "dockerode": "^4.0.9", - "get-port": "^7.1.0", - "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", - "zod": "^4.1.11", - "rivetkit": "catalog:rivetkit" - }, - "devDependencies": { - "@types/node": "^22.10.2", - "tsx": "^4.19.0", - "typescript": "^5.7.2" - } -} diff --git a/vendor/agentos/examples/sandbox/server.ts b/vendor/agentos/examples/sandbox/server.ts deleted file mode 100644 index 2f56cd1a..00000000 --- a/vendor/agentos/examples/sandbox/server.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; -import { docker } from "@rivet-dev/agentos-sandbox"; - -const vm = agentOS({ - sandbox: { - provider: docker(), - mountPath: "/home/agentos/sandbox", - }, -}); - -export const registry = setup({ use: { vm } }); - -registry.start(); diff --git a/vendor/agentos/examples/sandbox/tsconfig.json b/vendor/agentos/examples/sandbox/tsconfig.json deleted file mode 100644 index 78b4a00b..00000000 --- a/vendor/agentos/examples/sandbox/tsconfig.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "moduleResolution": "bundler", "noEmit": true, "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], "types": ["node"], "baseUrl": ".", - "paths": { - "@rivet-dev/agentos": ["../../packages/agentos/src/index.ts"], - "@rivet-dev/agentos-core": ["../../packages/core/src/index.ts"], - "@rivet-dev/agentos/client": ["../../packages/agentos/src/client.ts"], - "@rivet-dev/agentos/react": ["../../packages/agentos/src/react.ts"] - } - }, - "include": ["**/*.ts", "**/*.tsx"] -} diff --git a/vendor/agentos/examples/sessions/README.md b/vendor/agentos/examples/sessions/README.md deleted file mode 100644 index ffdf7896..00000000 --- a/vendor/agentos/examples/sessions/README.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: "Sessions" -description: "Create, manage, and stream agent sessions over the RivetKit actor client." -category: "Sessions & Permissions" -order: 1 ---- - -Spin up an agent VM, open sessions against it, and drive them end to end: send prompts, stream responses, switch models, and tear sessions down. Reach for this when you need full lifecycle control over an agent rather than a one-shot prompt. - -## How it works - -The server registers an agent VM with `agentOS({ software: [pi] })` and exposes it through a typed RivetKit `setup` registry. The client connects with `createClient` and grabs a VM handle with `getOrCreate`. From that handle, `openSession` creates or restores a durable session using options such as `env`, `cwd`, `mcpServers`, and `additionalInstructions`; `prompt` and `cancelPrompt` drive turns. A `connect()` connection surfaces live `sessionEvent`, `vmBooted`, and `vmShutdown` events. Completed ACP updates are retained in SQLite and can be recovered with `readHistory`; streaming deltas remain ephemeral. Use `getSession` and `listSessions` without starting an adapter, `getSessionConfig` and `setSessionConfigOption` for adapter-defined controls, `unloadSession` to release only the runtime, and `deleteSession` to permanently remove a session and its history. - -## Run it - -```bash -npm install -ANTHROPIC_API_KEY=sk-... npx tsx server.ts # start the registry -# in another shell: drive the client functions -ANTHROPIC_API_KEY=sk-... npx tsx client.ts -``` - -The server boots the agent VM and the client opens sessions, streams events, and prints session IDs and responses. - -## Source - -View the source on GitHub: https://github.com/rivet-dev/agent-os/tree/main/examples/sessions diff --git a/vendor/agentos/examples/sessions/cancel-prompt.ts b/vendor/agentos/examples/sessions/cancel-prompt.ts deleted file mode 100644 index f90e7b3e..00000000 --- a/vendor/agentos/examples/sessions/cancel-prompt.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); -const agent = client.vm.getOrCreate("my-agent"); - -await agent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, -}); - -// Start a long-running prompt -const promptPromise = agent.sessions.prompt({ - content: [ - { - type: "text", - text: "Refactor the entire codebase to use TypeScript strict mode", - }, - ], -}); - -// Cancellation is cooperative and does not delete durable history. -setTimeout(async () => { - await agent.sessions.cancelPrompt(); -}, 10_000); - -const response = await promptPromise; -console.log(response.message?.content ?? []); diff --git a/vendor/agentos/examples/sessions/client.ts b/vendor/agentos/examples/sessions/client.ts deleted file mode 100644 index b62a4316..00000000 --- a/vendor/agentos/examples/sessions/client.ts +++ /dev/null @@ -1,237 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); -const agent = client.vm.getOrCreate("my-agent"); - -// ── Open a session ────────────────────────────────────────────── -async function openSession() { - // The caller owns the durable session ID; openSession resolves with no value. - await agent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - }); -} - -// ── openSession options: env ──────────────────────────────────── -async function withEnv() { - await agent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - }); -} - -// ── openSession options: cwd ──────────────────────────────────── -async function withCwd() { - await agent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - cwd: "/home/agentos/project", - }); -} - -// ── openSession options: additionalInstructions ───────────────── -async function withInstructions() { - await agent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - additionalInstructions: "Always write tests before implementation.", - }); -} - -// ── openSession options: skipOsInstructions ───────────────────── -async function withSkipOsInstructions() { - await agent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - skipOsInstructions: true, - }); -} - -// ── openSession options: system prompt customization ──────────── -async function withSystemPrompt() { - // docs:start system-prompt - await agent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - // Extra instructions appended to the agent system prompt - additionalInstructions: "Always write tests before implementation.", - // Suppress the base OS prompt (host-function docs are still injected). - skipOsInstructions: true, - }); - // docs:end system-prompt -} - -// ── Prompt a session ───────────────────────────────────────────────── -async function promptSession() { - await agent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - }); - const response = await agent.sessions.prompt({ - content: [ - { - type: "text", - text: "Create a TypeScript function that checks if a number is prime", - }, - ], - }); - console.log(response.message?.content ?? []); -} - -// ── Stream responses ────────────────────────────────────────────── -async function streamResponses() { - const conn = agent.connect(); - - // Subscribe to session events before sending the prompt - conn.on("sessionEvent", (event) => { - console.log(`[${event.sessionId}]`, event.durability, event); - }); - - await agent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - }); - await agent.sessions.prompt({ - content: [{ type: "text", text: "Explain how async/await works" }], - }); -} - -// ── Client events ───────────────────────────────────────────────── -function clientEvents() { - const conn = agent.connect(); - - conn.on("sessionEvent", (event) => { - console.log(event.sessionId, event.durability, event); - }); - - conn.on("vmBooted", () => { - console.log("VM is ready"); - }); - - conn.on("vmShutdown", (data) => { - console.log("VM shutting down:", data.reason); - }); -} - -// ── Client events: subscribe before triggering ──────────────────── -async function subscribeFirst() { - const conn = agent.connect(); - - // Subscribe first - conn.on("sessionEvent", (event) => { - console.log("Session:", event); - }); - - // Then trigger actions - await agent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - }); - await agent.sessions.prompt({ - content: [{ type: "text", text: "Run the test suite" }], - }); -} - -// ── Cancel a prompt ─────────────────────────────────────────────── -async function cancelPrompt() { - await agent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - }); - - // Start a long-running prompt - const promptPromise = agent.sessions.prompt({ - content: [ - { - type: "text", - text: "Refactor the entire codebase to use TypeScript strict mode", - }, - ], - }); - - // Cancel the in-flight prompt while keeping the session available. - setTimeout(async () => { - await agent.sessions.cancelPrompt(); - }, 10_000); - - const response = await promptPromise; - console.log(response.message?.content ?? []); -} - -// ── Unload a session runtime ─────────────────────────────────────────────── -async function unloadSession() { - await agent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - }); - - // Release the adapter without deleting the durable session or its history. - await agent.sessions.unload(); -} - -// ── List durable sessions ───────────────────────────────────────────────── -async function listDurableSessions() { - await agent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - }); - const page = await agent.sessions.list(); - for (const session of page.sessions) { - console.log(session.sessionId, session.agent); - } -} - -// ── Multiple sessions ───────────────────────────────────────────── -async function multipleSessions() { - // Create two sessions in the same VM - const coderSessionId = "coder"; - await agent.sessions.open({ - sessionId: coderSessionId, - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - }); - const reviewerSessionId = "reviewer"; - await agent.sessions.open({ - sessionId: reviewerSessionId, - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - }); - - // Coder writes code - await agent.sessions.prompt({ - sessionId: coderSessionId, - content: [ - { type: "text", text: "Write a REST API at /home/agentos/api.ts" }, - ], - }); - - // Reviewer reads and reviews the same file - await agent.sessions.prompt({ - sessionId: reviewerSessionId, - content: [{ type: "text", text: "Review /home/agentos/api.ts for issues" }], - }); - - // Unload each adapter independently while preserving both histories. - await agent.sessions.unload({ sessionId: coderSessionId }); - await agent.sessions.unload({ sessionId: reviewerSessionId }); -} - -export { - openSession, - withEnv, - withCwd, - withInstructions, - withSkipOsInstructions, - withSystemPrompt, - promptSession, - streamResponses, - clientEvents, - subscribeFirst, - cancelPrompt, - unloadSession, - listDurableSessions, - multipleSessions, -}; diff --git a/vendor/agentos/examples/sessions/close-destroy.ts b/vendor/agentos/examples/sessions/close-destroy.ts deleted file mode 100644 index f0315b6e..00000000 --- a/vendor/agentos/examples/sessions/close-destroy.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); -const agent = client.vm.getOrCreate("my-agent"); - -await agent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, -}); - -// Release only the adapter. SQLite history remains and the next prompt restores it. -await agent.sessions.unload(); - -// Permanent deletion requires an explicit public session ID. -await agent.sessions.delete(); diff --git a/vendor/agentos/examples/sessions/create-session.ts b/vendor/agentos/examples/sessions/create-session.ts deleted file mode 100644 index 98fe3f80..00000000 --- a/vendor/agentos/examples/sessions/create-session.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); -const agent = client.vm.getOrCreate("my-agent"); - -await agent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, -}); diff --git a/vendor/agentos/examples/sessions/multiple-sessions.ts b/vendor/agentos/examples/sessions/multiple-sessions.ts deleted file mode 100644 index 66974ae8..00000000 --- a/vendor/agentos/examples/sessions/multiple-sessions.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); -const agent = client.vm.getOrCreate("my-agent"); - -// Create two sessions in the same VM -const coderSessionId = "coder"; -await agent.sessions.open({ - sessionId: coderSessionId, - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, -}); -const reviewerSessionId = "reviewer"; -await agent.sessions.open({ - sessionId: reviewerSessionId, - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, -}); - -// Coder writes code -await agent.sessions.prompt({ - sessionId: coderSessionId, - content: [{ type: "text", text: "Write a REST API at /workspace/api.ts" }], -}); - -// Reviewer reads and reviews the same file -await agent.sessions.prompt({ - sessionId: reviewerSessionId, - content: [{ type: "text", text: "Review /workspace/api.ts for issues" }], -}); - -// Unload each adapter independently while retaining both histories. -await agent.sessions.unload({ sessionId: coderSessionId }); -await agent.sessions.unload({ sessionId: reviewerSessionId }); diff --git a/vendor/agentos/examples/sessions/package.json b/vendor/agentos/examples/sessions/package.json deleted file mode 100644 index 27fe5c71..00000000 --- a/vendor/agentos/examples/sessions/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-sessions", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-sandbox": "workspace:*", - "sandbox-agent": "^0.4.2", - "dockerode": "^4.0.9", - "get-port": "^7.1.0", - "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", - "zod": "^4.1.11", - "@rivet-dev/agentos": "workspace:*", - "rivetkit": "catalog:rivetkit" - }, - "devDependencies": { - "@types/node": "^22.10.2", - "tsx": "^4.19.0", - "typescript": "^5.7.2" - } -} diff --git a/vendor/agentos/examples/sessions/runtime-config.ts b/vendor/agentos/examples/sessions/runtime-config.ts deleted file mode 100644 index 03265680..00000000 --- a/vendor/agentos/examples/sessions/runtime-config.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); -const agent = client.vm.getOrCreate("my-agent"); - -await agent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, -}); - -const config = await agent.sessions.getConfig(); -console.log(config.options); - -await agent.sessions.setConfigOption({ - configId: "model", - value: "anthropic/claude-sonnet-4", -}); diff --git a/vendor/agentos/examples/sessions/send-prompt.ts b/vendor/agentos/examples/sessions/send-prompt.ts deleted file mode 100644 index 102e56a5..00000000 --- a/vendor/agentos/examples/sessions/send-prompt.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); -const agent = client.vm.getOrCreate("my-agent"); - -await agent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, -}); -const response = await agent.sessions.prompt({ - content: [ - { - type: "text", - text: "Create a TypeScript function that checks if a number is prime", - }, - ], -}); -console.log(response.message?.content ?? []); diff --git a/vendor/agentos/examples/sessions/server-logs.ts b/vendor/agentos/examples/sessions/server-logs.ts deleted file mode 100644 index c76f4036..00000000 --- a/vendor/agentos/examples/sessions/server-logs.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; -import pi from "@agentos-software/pi"; - -// Swap in your own structured logger. -const logger = console; - -const vm = agentOS({ - software: [pi], - onAgentStderr(event) { - // event: { sessionId, agentType, processId, pid, chunk: Uint8Array } - const line = new TextDecoder().decode(event.chunk); - logger.info(`[agent:${event.agentType} session:${event.sessionId}] ${line}`); - }, -}); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/sessions/server.ts b/vendor/agentos/examples/sessions/server.ts deleted file mode 100644 index 32a86b30..00000000 --- a/vendor/agentos/examples/sessions/server.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; -import pi from "@agentos-software/pi"; - -const vm = agentOS({ software: [pi] }); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/sessions/stream-responses.ts b/vendor/agentos/examples/sessions/stream-responses.ts deleted file mode 100644 index baf41714..00000000 --- a/vendor/agentos/examples/sessions/stream-responses.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); -const agent = client.vm.getOrCreate("my-agent"); -const conn = agent.connect(); - -// Subscribe to session events before sending the prompt -conn.on("sessionEvent", (event) => { - console.log(`[${event.sessionId}]`, event.durability, event); -}); - -await agent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, -}); -await agent.sessions.prompt({ - content: [{ type: "text", text: "Explain how async/await works" }], -}); diff --git a/vendor/agentos/examples/sessions/tsconfig.json b/vendor/agentos/examples/sessions/tsconfig.json deleted file mode 100644 index e7937905..00000000 --- a/vendor/agentos/examples/sessions/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "moduleResolution": "bundler", "noEmit": true, "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], "types": ["node"], "baseUrl": ".", - "paths": { - "@rivet-dev/agentos": ["../../packages/agentos/src/index.ts"], - "@rivet-dev/agentos/client": ["../../packages/agentos/src/client.ts"], - "@rivet-dev/agentos/react": ["../../packages/agentos/src/react.ts"] - } - }, - "include": ["**/*.ts", "**/*.tsx"] -} diff --git a/vendor/agentos/examples/software/README.md b/vendor/agentos/examples/software/README.md deleted file mode 100644 index 005a09c2..00000000 --- a/vendor/agentos/examples/software/README.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: "Software" -description: "Declare which software packages and CLI commands are available inside the VM." -category: "Reference" -order: 2 ---- - -The commands an agent can run are determined by the software you install into its VM. This example declares a software set so a shell pipeline like `echo hello | grep hello` resolves inside the sandbox. - -## How it works - -`agentOS({ software: [...] })` takes a list of imported software packages, and together they define the CLI surface available to the guest. Common utilities — coreutils, sed, grep, gawk, findutils, diffutils, tar, and gzip — ship by default, so you only list the extras you need; here `pi` adds the agent itself. The client then runs commands through the VM via `exec`, which only succeed when the underlying binaries are present in the declared software set. - -## Run it - -```sh -npm install -npm run server # starts the registry on http://localhost:6420 -npm run client # runs "echo hello | grep hello" in the VM, prints "hello" -``` - -## Source - -View the source on GitHub: https://github.com/rivet-dev/agent-os/tree/main/examples/software diff --git a/vendor/agentos/examples/software/client.ts b/vendor/agentos/examples/software/client.ts deleted file mode 100644 index 3039a18a..00000000 --- a/vendor/agentos/examples/software/client.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ - endpoint: "http://localhost:6420", -}); -const agent = client.vm.getOrCreate("my-agent"); - -// `rg` (ripgrep) and `jq` are now available inside the VM. Find files containing -// "TODO" and pretty-print the matching paths as JSON. -const result = await agent.process.exec("rg --files-with-matches TODO /home/agentos | jq -R ."); -console.log(result.stdout); diff --git a/vendor/agentos/examples/software/package.json b/vendor/agentos/examples/software/package.json deleted file mode 100644 index e8a2c2a1..00000000 --- a/vendor/agentos/examples/software/package.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-software", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-sandbox": "workspace:*", - "sandbox-agent": "^0.4.2", - "dockerode": "^4.0.9", - "get-port": "^7.1.0", - "@agentos-software/git": "workspace:*", - "@agentos-software/coreutils": "workspace:*", - "@agentos-software/ripgrep": "workspace:*", - "@agentos-software/jq": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", - "zod": "^4.1.11", - "@rivet-dev/agentos": "workspace:*", - "rivetkit": "catalog:rivetkit" - }, - "devDependencies": { - "@types/node": "^22.10.2", - "tsx": "^4.19.0", - "typescript": "^5.7.2" - } -} diff --git a/vendor/agentos/examples/software/quickstart-agent/index.ts b/vendor/agentos/examples/software/quickstart-agent/index.ts deleted file mode 100644 index a1c9253d..00000000 --- a/vendor/agentos/examples/software/quickstart-agent/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; -import myAgent from "./my-agent.ts"; - -const vm = agentOS({ software: [myAgent] }); -// openSession() launches or restores the agent through its acpEntrypoint: -// await vm.sessions.open({ agent: "my-agent" }); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/software/quickstart-agent/my-agent.ts b/vendor/agentos/examples/software/quickstart-agent/my-agent.ts deleted file mode 100644 index 03fb65f7..00000000 --- a/vendor/agentos/examples/software/quickstart-agent/my-agent.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { defineSoftware } from "@rivet-dev/agentos"; -import { dirname, resolve } from "node:path"; -import { fileURLToPath } from "node:url"; - -const packagePath = resolve( - dirname(fileURLToPath(import.meta.url)), - "packages/my-agent/current", -); - -// The agent block lives in the package's agentos-package.json, generated by `agentos-toolchain pack --agent`. -export default defineSoftware({ packagePath }); diff --git a/vendor/agentos/examples/software/quickstart-node/index.ts b/vendor/agentos/examples/software/quickstart-node/index.ts deleted file mode 100644 index 68f7b16f..00000000 --- a/vendor/agentos/examples/software/quickstart-node/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; -import myTool from "./my-tool.ts"; - -// `my-tool` is now on $PATH inside the VM. -const vm = agentOS({ software: [myTool] }); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/software/quickstart-node/my-tool.ts b/vendor/agentos/examples/software/quickstart-node/my-tool.ts deleted file mode 100644 index 66589aea..00000000 --- a/vendor/agentos/examples/software/quickstart-node/my-tool.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { defineSoftware } from "@rivet-dev/agentos"; -import { dirname, resolve } from "node:path"; -import { fileURLToPath } from "node:url"; - -// Point at the self-contained directory produced by `agentos-toolchain pack`. -const packagePath = resolve( - dirname(fileURLToPath(import.meta.url)), - "my-tool-package", -); - -export default defineSoftware({ packagePath }); diff --git a/vendor/agentos/examples/software/quickstart-wasm/index.ts b/vendor/agentos/examples/software/quickstart-wasm/index.ts deleted file mode 100644 index 484f0564..00000000 --- a/vendor/agentos/examples/software/quickstart-wasm/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; -import myCmds from "./my-cmds.ts"; - -// The compiled commands are now on $PATH inside the VM. -const vm = agentOS({ software: [myCmds] }); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/software/quickstart-wasm/my-cmds.ts b/vendor/agentos/examples/software/quickstart-wasm/my-cmds.ts deleted file mode 100644 index 7941ea01..00000000 --- a/vendor/agentos/examples/software/quickstart-wasm/my-cmds.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { defineSoftware } from "@rivet-dev/agentos"; -import { dirname, resolve } from "node:path"; -import { fileURLToPath } from "node:url"; - -// WASM output is already a package - no `pack` step. -const packagePath = resolve(dirname(fileURLToPath(import.meta.url)), "my-cmds"); - -export default defineSoftware({ packagePath }); diff --git a/vendor/agentos/examples/software/registry-usage.ts b/vendor/agentos/examples/software/registry-usage.ts deleted file mode 100644 index 922db353..00000000 --- a/vendor/agentos/examples/software/registry-usage.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; -import coreutils from "@agentos-software/coreutils"; -import ripgrep from "@agentos-software/ripgrep"; - -const vm = agentOS({ software: [coreutils, ripgrep] }); - -export const registry = setup({ use: { vm } }); -registry.start(); diff --git a/vendor/agentos/examples/software/server.ts b/vendor/agentos/examples/software/server.ts deleted file mode 100644 index 68405322..00000000 --- a/vendor/agentos/examples/software/server.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; -import pi from "@agentos-software/pi"; -import ripgrep from "@agentos-software/ripgrep"; -import jq from "@agentos-software/jq"; - -// Each entry adds its CLI commands to the VM. Common POSIX utilities ship by -// default; `pi` is the agent, and `ripgrep`/`jq` add the `rg` and `jq` -// commands. Browse the registry for more packages. -const vm = agentOS({ - software: [pi, ripgrep, jq], -}); - -export const registry = setup({ use: { vm } }); - -registry.start(); diff --git a/vendor/agentos/examples/software/software/common.ts b/vendor/agentos/examples/software/software/common.ts deleted file mode 100644 index 061eb332..00000000 --- a/vendor/agentos/examples/software/software/common.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Local stand-in for the `@agentos-software/common` software bundle. - * - * In a real app you would `import common from "@agentos-software/common"`; this - * fixture is self-contained, so it provides an illustrative package-dir ref to - * exercise the `software: [...]` config field. - */ -const common = { - packagePath: "/opt/example-agentos-software/common", -} as const; - -export default common; diff --git a/vendor/agentos/examples/software/software/pi.ts b/vendor/agentos/examples/software/software/pi.ts deleted file mode 100644 index 8952b55e..00000000 --- a/vendor/agentos/examples/software/software/pi.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Local stand-in for the `@agentos-software/pi` agent package. - * - * In a real app you would `import pi from "@agentos-software/pi"`; this fixture - * is self-contained, so it provides an illustrative package-dir ref to exercise - * the `software: [...]` config field. - */ -const pi = { - packagePath: "/opt/example-agentos-software/pi", -} as const; - -export default pi; diff --git a/vendor/agentos/examples/software/tsconfig.json b/vendor/agentos/examples/software/tsconfig.json deleted file mode 100644 index c7a6f251..00000000 --- a/vendor/agentos/examples/software/tsconfig.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "moduleResolution": "bundler", "noEmit": true, "jsx": "react-jsx", - "allowImportingTsExtensions": true, - "lib": ["ESNext", "DOM"], "types": ["node"], "baseUrl": ".", - "paths": { - "@rivet-dev/agentos": ["../../packages/agentos/src/index.ts"], - "@rivet-dev/agentos/client": ["../../packages/agentos/src/client.ts"], - "@rivet-dev/agentos/react": ["../../packages/agentos/src/react.ts"] - } - }, - "include": ["**/*.ts", "**/*.tsx"] -} diff --git a/vendor/agentos/examples/vercel-eve/.gitignore b/vendor/agentos/examples/vercel-eve/.gitignore deleted file mode 100644 index 7dfd9cf4..00000000 --- a/vendor/agentos/examples/vercel-eve/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -node_modules -.env -.eve -.output -.vercel -dist diff --git a/vendor/agentos/examples/vercel-eve/README.md b/vendor/agentos/examples/vercel-eve/README.md deleted file mode 100644 index 38f84e67..00000000 --- a/vendor/agentos/examples/vercel-eve/README.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: "Vercel Eve" -description: "Run a Vercel Eve agent with a durable agentOS sandbox." -category: "Integrations" -order: 1 ---- - -# Vercel Eve - -Run a Vercel Eve agent with agentOS as its sandbox backend. Eve owns the agent runtime; agentOS supplies the isolated VM and durable `/workspace` filesystem. - -## Run it - -```sh -pnpm install -AI_GATEWAY_API_KEY=... pnpm dev -``` - -`eve dev` starts the Eve server. The first World or sandbox operation lazily -starts the shared registry in the same process and waits for it to become ready, -so there is no second development server. Reconnect to the same Eve session to -verify that the actor-owned workspace survives sandbox sleep and resume. - -## Configuration - -- Change the actor name passed to `agentOSBackend()` when your registry uses a name other than `vm`. -- Configure software, permissions, and resource limits on `agentOS()` in `actors.ts`. -- Keep files that must persist under `/workspace`. - -agentOS is the default in this example, but Eve accepts any compatible sandbox backend. Changing the sandbox does not require changing the agent or selecting a different World. - -See the [Vercel Eve integration guide](https://rivet.dev/agentos/docs/frameworks/vercel-eve) for the complete setup. - -## Source - -View the source on GitHub: https://github.com/rivet-dev/agentos/tree/main/examples/vercel-eve diff --git a/vendor/agentos/examples/vercel-eve/actors.ts b/vendor/agentos/examples/vercel-eve/actors.ts deleted file mode 100644 index 7f694268..00000000 --- a/vendor/agentos/examples/vercel-eve/actors.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; -import { vercelWorldActors } from "@rivet-dev/vercel-world/registry"; - -const vm = agentOS(); - -export const registry = setup({ - use: { ...vercelWorldActors, vm }, -}); diff --git a/vendor/agentos/examples/vercel-eve/agent/agent.ts b/vendor/agentos/examples/vercel-eve/agent/agent.ts deleted file mode 100644 index 16a0a3b4..00000000 --- a/vendor/agentos/examples/vercel-eve/agent/agent.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { defineAgent } from "eve"; - -export default defineAgent({ - model: "anthropic/claude-sonnet-5", - build: { - externalDependencies: [ - "@rivet-dev/agentos", - "@rivet-dev/agentos-core", - "@rivet-dev/agentos-eve", - "@rivet-dev/agentos-runtime-core", - "@rivet-dev/agentos-sidecar", - "@rivet-dev/vercel-world", - "@rivetkit/engine-cli", - ], - }, - experimental: { - workflow: { world: "#world" }, - }, -}); diff --git a/vendor/agentos/examples/vercel-eve/agent/instructions.md b/vendor/agentos/examples/vercel-eve/agent/instructions.md deleted file mode 100644 index fb78d74d..00000000 --- a/vendor/agentos/examples/vercel-eve/agent/instructions.md +++ /dev/null @@ -1,3 +0,0 @@ -You are a coding agent working in `/workspace`. - -Keep project files in `/workspace` so they remain available when the sandbox sleeps and resumes. diff --git a/vendor/agentos/examples/vercel-eve/agent/sandbox.ts b/vendor/agentos/examples/vercel-eve/agent/sandbox.ts deleted file mode 100644 index 65b7de4b..00000000 --- a/vendor/agentos/examples/vercel-eve/agent/sandbox.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { agentOSBackend } from "@rivet-dev/agentos-eve"; -import { defineSandbox } from "eve/sandbox"; -import { registry } from "../actors"; - -export default defineSandbox({ - backend: agentOSBackend({ actor: "vm", registry }), -}); diff --git a/vendor/agentos/examples/vercel-eve/core.ts b/vendor/agentos/examples/vercel-eve/core.ts deleted file mode 100644 index 9f15bc77..00000000 --- a/vendor/agentos/examples/vercel-eve/core.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { AgentOs } from "@rivet-dev/agentos-core"; -import { agentOSCoreBackend } from "@rivet-dev/agentos-eve"; -import { defineSandbox } from "eve/sandbox"; - -export default defineSandbox({ - backend: agentOSCoreBackend({ - create: ({ sessionKey }) => - AgentOs.create({ - mounts: [ - { - path: "/workspace", - plugin: { - id: "host_dir", - config: { - hostPath: `/var/lib/eve/${encodeURIComponent(sessionKey)}`, - }, - }, - readOnly: false, - }, - ], - }), - }), -}); diff --git a/vendor/agentos/examples/vercel-eve/package.json b/vendor/agentos/examples/vercel-eve/package.json deleted file mode 100644 index ed752a16..00000000 --- a/vendor/agentos/examples/vercel-eve/package.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-vercel-eve", - "version": "0.0.1", - "private": true, - "type": "module", - "imports": { - "#world": "./world.ts" - }, - "scripts": { - "build": "eve build", - "dev": "eve dev", - "start": "eve start", - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-core": "workspace:*", - "@rivet-dev/agentos-eve": "workspace:*", - "@rivet-dev/vercel-world": "2.3.10", - "@vercel/connect": "0.4.0", - "ai": "7.0.26", - "eve": "0.27.0", - "zod": "4.3.6" - }, - "devDependencies": { - "@types/node": "^24.0.0", - "typescript": "^5.7.2" - }, - "engines": { - "node": ">=24" - } -} diff --git a/vendor/agentos/examples/vercel-eve/tsconfig.json b/vendor/agentos/examples/vercel-eve/tsconfig.json deleted file mode 100644 index 65e53a4c..00000000 --- a/vendor/agentos/examples/vercel-eve/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "moduleResolution": "bundler", - "noEmit": true, - "lib": ["ESNext", "DOM"], - "types": ["node"] - }, - "include": ["actors.ts", "agent/**/*.ts", "core.ts", "world.ts"] -} diff --git a/vendor/agentos/examples/vercel-eve/world.ts b/vendor/agentos/examples/vercel-eve/world.ts deleted file mode 100644 index e4e70c59..00000000 --- a/vendor/agentos/examples/vercel-eve/world.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { createWorld as createRivetWorld } from "@rivet-dev/vercel-world"; -import { registry } from "./actors"; - -export const createWorld = () => createRivetWorld({ registry }); diff --git a/vendor/agentos/examples/webhooks/package.json b/vendor/agentos/examples/webhooks/package.json deleted file mode 100644 index 3cac521c..00000000 --- a/vendor/agentos/examples/webhooks/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-webhooks", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { "check-types": "tsc --noEmit" }, - "dependencies": { - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-sandbox": "workspace:*", - "rivetkit": "catalog:rivetkit", - "hono": "^4.6.0", - "sandbox-agent": "^0.4.2", - "dockerode": "^4.0.9", - "get-port": "^7.1.0", - "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", - "zod": "^4.1.11" - }, - "devDependencies": { "@types/node": "^22.10.2", "tsx": "^4.19.0", "typescript": "^5.7.2" } -} diff --git a/vendor/agentos/examples/webhooks/server.ts b/vendor/agentos/examples/webhooks/server.ts deleted file mode 100644 index c715cc7a..00000000 --- a/vendor/agentos/examples/webhooks/server.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { agentOS, setup } from "@rivet-dev/agentos"; -import { createClient } from "@rivet-dev/agentos/client"; -import { Hono } from "hono"; -import pi from "@agentos-software/pi"; - -const vm = agentOS({ - software: [pi], -}); - -export const registry = setup({ use: { vm } }); -registry.start(); - -// Hono server to receive Slack webhooks -const app = new Hono(); -const client = createClient({ - endpoint: "http://localhost:6420", -}); - -app.post("/slack/events", async (c) => { - const body = await c.req.json(); - - // Handle Slack URL verification - if (body.type === "url_verification") { - return c.json({ challenge: body.challenge }); - } - - // Prompt calls for one session are serialized automatically by AgentOS. - if (body.event?.type === "message" && !body.event?.bot_id) { - const agent = client.vm.getOrCreate("slack-agent"); - await agent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - additionalInstructions: "You answer Slack messages concisely.", - }); - const result = await agent.sessions.prompt({ - content: [ - { - type: "text", - text: `Slack message from ${body.event.user} in #${body.event.channel}:\n\n${body.event.text}\n\nRespond helpfully.`, - }, - ], - }); - const text = - result.message?.content - .filter((block) => block.type === "text") - .map((block) => block.text) - .join("") ?? ""; - const response = await fetch("https://slack.com/api/chat.postMessage", { - method: "POST", - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${process.env.SLACK_BOT_TOKEN}`, - }, - body: JSON.stringify({ channel: body.event.channel, text }), - }); - if (!response.ok) { - throw new Error(`Slack reply failed with status ${response.status}`); - } - } - - return c.json({ ok: true }); -}); - -export default app; diff --git a/vendor/agentos/examples/webhooks/tsconfig.json b/vendor/agentos/examples/webhooks/tsconfig.json deleted file mode 100644 index e7937905..00000000 --- a/vendor/agentos/examples/webhooks/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "moduleResolution": "bundler", "noEmit": true, "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], "types": ["node"], "baseUrl": ".", - "paths": { - "@rivet-dev/agentos": ["../../packages/agentos/src/index.ts"], - "@rivet-dev/agentos/client": ["../../packages/agentos/src/client.ts"], - "@rivet-dev/agentos/react": ["../../packages/agentos/src/react.ts"] - } - }, - "include": ["**/*.ts", "**/*.tsx"] -} diff --git a/vendor/agentos/examples/workflows/README.md b/vendor/agentos/examples/workflows/README.md deleted file mode 100644 index bd14e281..00000000 --- a/vendor/agentos/examples/workflows/README.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: "Workflows" -description: "Durable multi-step workflows that drive a VM across restarts, chaining each step's output into the next." -category: "Orchestration" -order: 3 ---- - -# Workflows - -Run multi-step agent work that survives crashes and restarts. Reach for this when a task has distinct stages — clone, fix, test, record — and you want each stage to be durable, retryable, and resumable rather than a single fragile call. - -## How it works - -A RivetKit `actor` whose `run` handler is built with `workflow()` orchestrates the steps, while a separate `agentOS` VM actor does the actual work over the client. Each workflow actor instance represents one run and stores its immutable creation input in actor state. Each `ctx.step(...)` is recorded, retried, and resumed independently: if the process crashes mid-run, replay skips completed steps and continues from where it left off. Output flows step-to-step through return values and the VM filesystem — the bug-fixer chains clone -> fix -> test -> record, and the code-reviewer writes a review file and feeds it into the next step. No application queue is required; AgentOS itself serializes prompts targeting the same session. - -## Run it - -```bash -npm install -ANTHROPIC_API_KEY=sk-... npx tsx server.ts # start the orchestrator + VM -npx tsx client.ts # trigger the durable bug-fix workflow -``` - -The client creates a workflow actor with input, waits for its durable status to become complete, and prints the test exit code. - -## Source - -View the source on GitHub: https://github.com/rivet-dev/agent-os/tree/main/examples/workflows diff --git a/vendor/agentos/examples/workflows/chaining-client.ts b/vendor/agentos/examples/workflows/chaining-client.ts deleted file mode 100644 index 96a133f7..00000000 --- a/vendor/agentos/examples/workflows/chaining-client.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { randomUUID } from "node:crypto"; -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ endpoint: "http://localhost:6420" }); -const handle = await client.codeReviewer.create(randomUUID(), { - input: { filePath: "/home/agentos/src/auth.ts" }, -}); - -let state = await handle.getState(); -while (state.status !== "complete") { - await new Promise((resolve) => setTimeout(resolve, 1_000)); - state = await handle.getState(); -} diff --git a/vendor/agentos/examples/workflows/client.ts b/vendor/agentos/examples/workflows/client.ts deleted file mode 100644 index 460068d4..00000000 --- a/vendor/agentos/examples/workflows/client.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { randomUUID } from "node:crypto"; -import { createClient } from "@rivet-dev/agentos/client"; -import type { registry } from "./server"; - -const client = createClient({ endpoint: "http://localhost:6420" }); - -// Creating one actor starts one durable workflow with immutable input. -const handle = await client.bugFixer.create(randomUUID(), { - input: { - repo: "https://github.com/example/repo.git", - issue: "Fix the login redirect bug", - }, -}); - -let state = await handle.getState(); -while (state.status !== "complete") { - await new Promise((resolve) => setTimeout(resolve, 1_000)); - state = await handle.getState(); -} -console.log("Exit code:", state.exitCode); diff --git a/vendor/agentos/examples/workflows/package.json b/vendor/agentos/examples/workflows/package.json deleted file mode 100644 index 2b507953..00000000 --- a/vendor/agentos/examples/workflows/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "@rivet-dev/agentos-example-workflows", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "check-types": "tsc --noEmit" - }, - "dependencies": { - "@rivet-dev/agentos": "workspace:*", - "@rivet-dev/agentos-sandbox": "workspace:*", - "sandbox-agent": "^0.4.2", - "dockerode": "^4.0.9", - "get-port": "^7.1.0", - "@agentos-software/git": "workspace:*", - "@agentos-software/claude-code": "workspace:*", - "@agentos-software/opencode": "workspace:*", - "@agentos-software/pi": "workspace:*", - "zod": "^4.1.11", - "@rivet-dev/agentos": "workspace:*", - "rivetkit": "catalog:rivetkit" - }, - "devDependencies": { - "@types/node": "^22.10.2", - "tsx": "^4.19.0", - "typescript": "^5.7.2" - } -} diff --git a/vendor/agentos/examples/workflows/server.ts b/vendor/agentos/examples/workflows/server.ts deleted file mode 100644 index fb152315..00000000 --- a/vendor/agentos/examples/workflows/server.ts +++ /dev/null @@ -1,144 +0,0 @@ -// docs:start basic -import { agentOS, setup } from "@rivet-dev/agentos"; -import pi from "@agentos-software/pi"; -import { actor } from "rivetkit"; -import { type WorkflowStepContextOf, workflow } from "rivetkit/workflow"; - -const vm = agentOS({ software: [pi] }); - -interface BugFixInput { - repo: string; - issue: string; -} - -// Each actor instance is one durable workflow run. Its creation input is stored -// in actor state, so no queue is needed to trigger or order agent prompts. -const bugFixer = actor({ - state: { - repo: "", - issue: "", - status: "running" as "running" | "complete", - exitCode: null as number | null, - }, - onCreate: (c, input: BugFixInput) => { - c.state.repo = input.repo; - c.state.issue = input.issue; - }, - run: workflow(async (ctx) => { - await ctx.step("clone-repo", (step) => cloneRepo(step, step.state.repo)); - await ctx.step("fix-bug", (step) => - fixBugWithAgent(step, step.state.issue), - ); - const exitCode = await ctx.step("run-tests", (step) => runTests(step)); - await ctx.step("record-result", async (step) => { - step.state.exitCode = exitCode; - step.state.status = "complete"; - }); - }), - actions: { - getState: (c) => c.state, - }, -}); - -async function cloneRepo( - step: WorkflowStepContextOf, - repo: string, -): Promise { - const agent = step.client().vm.getOrCreate("bug-fixer"); - await agent.process.exec(`git clone ${repo} /home/agentos/repo`); -} - -async function fixBugWithAgent( - step: WorkflowStepContextOf, - issue: string, -): Promise { - const agent = step.client().vm.getOrCreate("bug-fixer"); - await agent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - }); - await agent.sessions.prompt({ - content: [{ type: "text", text: `Fix the bug described in issue: ${issue}` }], - }); -} - -async function runTests( - step: WorkflowStepContextOf, -): Promise { - const agent = step.client().vm.getOrCreate("bug-fixer"); - const tests = await agent.process.exec("cd /home/agentos/repo && npm test"); - return tests.exitCode ?? 1; -} -// docs:end basic - -// docs:start chaining -interface CodeReviewInput { - filePath: string; -} - -const codeReviewer = actor({ - state: { - filePath: "", - status: "running" as "running" | "complete", - }, - onCreate: (c, input: CodeReviewInput) => { - c.state.filePath = input.filePath; - }, - run: workflow(async (ctx) => { - await ctx.step("review", (step) => - reviewCode(step, step.state.filePath), - ); - const review = await ctx.step("read-review", (step) => readReview(step)); - await ctx.step("fix", (step) => applyReview(step, review)); - await ctx.step("record-review", async (step) => { - step.state.status = "complete"; - }); - }), - actions: { - getState: (c) => c.state, - }, -}); - -async function reviewCode( - step: WorkflowStepContextOf, - filePath: string, -): Promise { - const agent = step.client().vm.getOrCreate("reviewer"); - await agent.sessions.open({ - agent: "pi", - env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, - }); - await agent.sessions.prompt({ - content: [ - { - type: "text", - text: `Review ${filePath} and write findings to /home/agentos/review.md`, - }, - ], - }); -} - -async function readReview( - step: WorkflowStepContextOf, -): Promise { - const agent = step.client().vm.getOrCreate("reviewer"); - return new TextDecoder().decode( - await agent.filesystem.readFile("/home/agentos/review.md"), - ); -} - -async function applyReview( - step: WorkflowStepContextOf, - review: string, -): Promise { - const agent = step.client().vm.getOrCreate("reviewer"); - await agent.sessions.prompt({ - content: [ - { type: "text", text: `Apply the following review feedback:\n\n${review}` }, - ], - }); -} - -export const registry = setup({ use: { vm, bugFixer, codeReviewer } }); -registry.start(); -// docs:end chaining diff --git a/vendor/agentos/examples/workflows/tsconfig.json b/vendor/agentos/examples/workflows/tsconfig.json deleted file mode 100644 index e7937905..00000000 --- a/vendor/agentos/examples/workflows/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "moduleResolution": "bundler", "noEmit": true, "jsx": "react-jsx", - "lib": ["ESNext", "DOM"], "types": ["node"], "baseUrl": ".", - "paths": { - "@rivet-dev/agentos": ["../../packages/agentos/src/index.ts"], - "@rivet-dev/agentos/client": ["../../packages/agentos/src/client.ts"], - "@rivet-dev/agentos/react": ["../../packages/agentos/src/react.ts"] - } - }, - "include": ["**/*.ts", "**/*.tsx"] -}