Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions vendor/agentos/docs/content/docs/hosted-api.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ EOF
# → { "token": "…", "expires_ts": … }
```

In TypeScript, `vm.issueToken({ subject, expiresIn })` issues the same token,
and `client.getForId("agentOS", vmId)` reaches the VM with it.
A client created with that token reaches the VM with
`client.getForId("agentOS", vmId)`.

## Call an action

Expand Down
5 changes: 5 additions & 0 deletions vendor/agentos/docs/content/docs/networking.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ 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.

Requests reach a preview through the VM's gateway at
`https://api.rivet.dev/gateway/{vm_id}@{token}/request{path}`, where `path` is
the preview's returned path and `token` can reach the VM, such as a
[scoped JWT](/agentos/docs/hosted-api#authentication).

```ts Hosted @nocheck
import { createAgentOsClient } from "@rivet-dev/agentos";

Expand Down
34 changes: 27 additions & 7 deletions vendor/agentos/docs/content/docs/quickstart-hosted.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -127,18 +127,26 @@ curl "https://api.rivet.dev/gateway/$VM_ID/action/v1.filesystem.writeFile" \
"content": "Hello, world!"
}]}'

curl "https://api.rivet.dev/gateway/$VM_ID/action/v1.filesystem.readFile" \
curl "https://api.rivet.dev/gateway/$VM_ID/action/v1.process.run" \
-H "x-rivet-token: $VM_TOKEN" \
--json '{"args": [{"path": "/home/agentos/hello.txt"}]}'
--json '{"args": [{
"command": "cat",
"args": ["/home/agentos/hello.txt"],
"options": { "captureStdio": true }
}]}'
```

</CodeGroup>

`v1.filesystem.readFile` returns raw bytes, which the JSON encoding of the HTTP
API cannot carry, so the HTTP example reads the file through a process.

### 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.
awake. Open the preview at `/gateway/$VM_ID@$VM_TOKEN/request` followed by the
returned `path`, with a token that can reach the VM.

<CodeGroup>

Expand Down Expand Up @@ -255,7 +263,7 @@ their commands appear on `/opt/agentos/bin`.
// 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 ripgrep = artifacts.find((artifact: { name: string }) => artifact.name === "ripgrep");

const installed = await vm.v1.software.install({
source: { url: new URL(ripgrep.path, base).href, digest: ripgrep.digest },
Expand Down Expand Up @@ -289,10 +297,22 @@ 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,
const response = await fetch("https://api.rivet.dev/auth/tokens", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RIVET_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
namespace: process.env.RIVET_NAMESPACE,
subject: "user-123",
duration: 3600,
grants: [
{ resource: "actor_gateway", target: { id: vmId }, operations: ["read"] },
],
}),
});
const { token } = await response.json();

// Client: call the VM directly
const userClient = createAgentOsClient({
Expand Down
28 changes: 25 additions & 3 deletions vendor/agentos/docs/content/docs/self-hosting.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,31 @@ it needs neither.
<Steps>
<Step title="Run the Rivet control plane">

<Note>
The control plane requires an admin token. See [Admin token](/docs/deploy/self-host/control-plane/configuration#admin-token).
</Note>

```sh
docker run -p 6420:6420 rivetdev/engine
export RIVET_ADMIN_TOKEN=$(openssl rand -hex 32)

docker run -p 6420:6420 \
-e RIVET__AUTH__ADMIN_TOKEN="$RIVET_ADMIN_TOKEN" \
rivetdev/engine
```

See the [self-hosting guides](/docs/deploy/) for other ways to run it.

</Step>
<Step title="Register the agentOS worker pool">

The agentOS worker connects to a pool named `services`:

```sh
curl -X PUT "http://localhost:6420/runner-configs/services?namespace=default" \
-H "Authorization: Bearer $RIVET_ADMIN_TOKEN" \
--json '{"datacenters": {"default": {"normal": {}}}}'
```

</Step>
<Step title="Run the agentOS worker">

Expand All @@ -43,13 +62,15 @@ The worker is what actually runs your VMs. It connects to the control plane:
docker run \
--add-host=host.docker.internal:host-gateway \
-e RIVET_ENDPOINT=http://host.docker.internal:6420 \
rivetdev/services
-e RIVET_TOKEN="$RIVET_ADMIN_TOKEN" \
rivetdev/services:0.2.0
```

</Step>
<Step title="Point your client at it">

Create a VM by ID on your control plane from TypeScript or plain HTTP:
Set `RIVET_TOKEN` to the admin token, then create a VM by ID on your control
plane from TypeScript or plain HTTP:

<CodeGroup>

Expand All @@ -64,6 +85,7 @@ const vm = client.agentOS.getOrCreate(["my-vm"]);

```bash HTTP
curl -X PUT "http://localhost:6420/actors?namespace=default" \
-H "Authorization: Bearer $RIVET_ADMIN_TOKEN" \
--json '{
"name": "agentOS",
"key": "my-vm",
Expand Down
5 changes: 3 additions & 2 deletions vendor/agentos/docs/content/docs/software.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const vm = client.agentOS.getOrCreate(["my-vm"]);
// 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 ripgrep = artifacts.find((artifact: { name: string }) => artifact.name === "ripgrep");

const installed = await vm.v1.software.install({
source: { url: new URL(ripgrep.path, base).href, digest: ripgrep.digest },
Expand All @@ -50,7 +50,8 @@ for (const software of await vm.v1.software.list({})) {
console.log(software.packageId, software.commands);
}

await vm.v1.software.uninstall({ packageId: installed.source.packageId });
const { packageId } = installed.source;
if (packageId) await vm.v1.software.uninstall({ packageId });
```

<CodeSnippet file="examples/embedded/software-install.ts" title="Library" />
Expand Down
Loading