Files

176 lines
6.8 KiB
TypeScript

'use client'
import React from "react";
import { motion } from "@/components/motion";
import { Terminal } from "lucide-react";
import { Button, Box, View, YStack, XStack } from '@hanzo/ui'
import { Head, Words } from '@/components/marketing/band'
import { Line } from '@/components/type'
/** The tile each half of the split sits in. */
const TILE = {
display: 'block',
p: 24,
rounded: 'var(--radius-xl)',
borderWidth: 1,
borderColor: 'var(--neutral-800)',
background: 'color-mix(in oklab, var(--neutral-900) 30%, transparent)',
} as const
/**
* A command, set in the mono face and allowed to scroll rather than wrap.
*
* Four of the seven were drawn on `gray-900` and three on `neutral-900` — two
* different greys for one thing, and `gray` is not a ramp this site has. They
* are one value now.
*/
function Command({ children }: { children: React.ReactNode }) {
return (
<Words render="div" p={12} rounded="var(--radius-md)" bg="var(--neutral-900)" fontFamily="$mono" fontSize="$2" lineHeight="calc(1.25 / 0.875)" color="var(--white)" overflowX="auto">
{children}
</Words>
)
}
const OperativeUsage = () => {
return (
<YStack
render="section"
id="get-started"
position="relative"
overflow="hidden"
py={96}
px={16}
$sm={{ px: 24 }}
$lg={{ px: 32 }}
bg="var(--neutral-950)"
>
<YStack
position="absolute"
t="50%"
l="25%"
width="50%"
height="50%"
rounded={9999}
x="-50%"
y="-50%"
background="color-mix(in oklab, var(--primary) 10%, transparent)"
filter="blur(64px)"
/>
<YStack position="relative" z="var(--z-raised)" width="100%" maxW={1280} mx="auto">
<Head
measure={768}
title="One docker run"
lede="Nothing is installed on your machine. The desktop, the tools and the agent are all inside the image"
/>
{/* The 2:3 split. `flexBasis: '100%'` stacks the halves until 1024,
where basis 0 hands the ratio back to `flexGrow` — the one spelling
that says both without a breakpoint the Grid cannot carry. */}
<XStack flexWrap="wrap" gap={32} items="stretch">
<YStack grow={2} flexBasis="100%" gap={24} $lg={{ flexBasis: 0 }}>
<View
render={<motion.div initial={{ opacity: 0, x: -20 }} whileInView={{ opacity: 1, x: 0 }} viewport={{ once: true }} transition={{ duration: 0.5 }} />}
{...TILE}
>
<Line render="h3" size="xl" weight="600" color="var(--white)" marginBottom={16}>Installation</Line>
<YStack gap={16}>
<Box>
<Line render="p" tone="muted" marginBottom={8}>Pull the image</Line>
<Command>
docker pull ghcr.io/hanzoai/operative:latest
</Command>
</Box>
<Box>
<Line render="p" tone="muted" marginBottom={8}>Run it with your key and the four ports</Line>
<Command>
docker run -e ANTHROPIC_API_KEY -p 8501:8501 -p 6080:6080 -p 5900:5900 -p 8080:8080 -it ghcr.io/hanzoai/operative:latest
</Command>
</Box>
<Box>
<Line render="p" tone="muted">Open localhost:8501 and type an objective</Line>
</Box>
</YStack>
<Box mt={24}>
<Button size="sm" variant="outline" borderColor="var(--neutral-700)">
<View mr={8}>
<Terminal width={16} height={16} color="color-mix(in oklab, var(--foreground) 80%, transparent)" />
</View>
Copy Installation Commands
</Button>
</Box>
</View>
<View
render={<motion.div initial={{ opacity: 0, x: -20 }} whileInView={{ opacity: 1, x: 0 }} viewport={{ once: true }} transition={{ duration: 0.5, delay: 0.2 }} />}
{...TILE}
>
<Line render="h3" size="xl" weight="600" color="var(--white)" marginBottom={16}>System Requirements</Line>
<YStack render="ul" gap={8}>
<Line render="li" tone="muted">• Docker. Nothing else installed on the host</Line>
<Line render="li" tone="muted">• A key for the API, Bedrock, or Vertex</Line>
<Line render="li" tone="muted">• Four ports free: 8501, 6080, 5900, 8080</Line>
<Line render="li" tone="muted">• Give the container the fewest privileges that work</Line>
</YStack>
</View>
</YStack>
{/* The flex props ride a gui stack, not the motion.div: a breakpoint
object is a gui prop and framer has nowhere to put one. */}
<YStack grow={3} flexBasis="100%" $lg={{ flexBasis: 0 }}>
<View
render={<motion.div initial={{ opacity: 0, x: 20 }} whileInView={{ opacity: 1, x: 0 }} viewport={{ once: true }} transition={{ duration: 0.5 }} />}
{...TILE}
height="100%"
>
<Line render="h3" size="xl" weight="600" color="var(--white)" marginBottom={16}>Basic Usage</Line>
<YStack gap={24}>
<Box>
<Line render="p" tone="muted" marginBottom={8}>Watch it in a browser, no VNC client needed</Line>
<Command>
open http://localhost:6080
</Command>
</Box>
<Box>
<Line render="p" tone="muted" marginBottom={8}>Send the model through Bedrock instead</Line>
<Command>
docker run -e API_PROVIDER=bedrock -e AWS_PROFILE -e AWS_REGION=us-west-2 …
</Command>
</Box>
<Box>
<Line render="p" tone="muted" marginBottom={8}>Or through Vertex</Line>
<Command>
docker run -e API_PROVIDER=vertex -e VERTEX_REGION -e VERTEX_PROJECT_ID …
</Command>
</Box>
<Box>
<Line render="p" tone="muted" marginBottom={8}>Keep the session between runs</Line>
<Command>
docker run -v $HOME/.anthropic:/home/operative/.anthropic …
</Command>
</Box>
<Box pt={8}>
<Line render="p" tone="muted">Computer use is beta, and instructions written into a web page or an image can try to talk to the model as if they were you. Limit outbound traffic to domains you name, and ask for a human yes before anything with consequences outside the container.</Line>
</Box>
</YStack>
</View>
</YStack>
</XStack>
</YStack>
</YStack>
);
};
export default OperativeUsage;