diff --git a/website/.vitepress/theme/assets/fonts/Virgil-LICENSE.md b/website/.vitepress/theme/assets/fonts/Virgil-LICENSE.md new file mode 100644 index 00000000..3e936729 --- /dev/null +++ b/website/.vitepress/theme/assets/fonts/Virgil-LICENSE.md @@ -0,0 +1,45 @@ +Copyright (c) 2021 - Present, Ellinor Rapp, with Reserved Font Name Virgil. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is copied below, and is also available with a FAQ at: [scripts.sil.org/OFL](https://scripts.sil.org/OFL). + +# SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 + +## PREAMBLE + +The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. + +The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. + +## DEFINITIONS + +"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the copyright statement(s). + +"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. + +"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. + +## PERMISSION & CONDITIONS + +Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: + +1. Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. + +2. Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. + +3. No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. + +4. The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. + +5. The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. + +## TERMINATION + +This license becomes null and void if any of the above conditions are not met. + +## DISCLAIMER + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/website/.vitepress/theme/assets/fonts/Virgil.woff2 b/website/.vitepress/theme/assets/fonts/Virgil.woff2 new file mode 100644 index 00000000..cb222253 Binary files /dev/null and b/website/.vitepress/theme/assets/fonts/Virgil.woff2 differ diff --git a/website/.vitepress/theme/components/Landing.vue b/website/.vitepress/theme/components/Landing.vue index ed56a151..53aaa337 100644 --- a/website/.vitepress/theme/components/Landing.vue +++ b/website/.vitepress/theme/components/Landing.vue @@ -4,12 +4,10 @@ import { withBase } from 'vitepress' import AsciiCanvas from './AsciiCanvas.vue' import ComposeLab from './ComposeLab.vue' import LogoWall from './LogoWall.vue' -import TypeTerminal, { type TermLine } from './TypeTerminal.vue' +import SessionFlow from './SessionFlow.vue' +import TitleAccent from './TitleAccent.vue' import { copy, installCommand, repoUrl, type Lang } from '../landing-content' -import { data as docsGroups } from '../docs.data.mts' import architectureImg from '../../../../docs/assets/architecture.png' -import componentsImg from '../../../../docs/assets/development-architecture.png' -import surfacesImg from '../../../../docs/assets/architecture-api-surfaces.png' import overviewEn from '../../../../docs/assets/console-overview-en.webp' import overviewZh from '../../../../docs/assets/console-overview-zh.webp' import metricsEn from '../../../../docs/assets/console-agent-metrics-en.webp' @@ -18,19 +16,14 @@ import metricsZh from '../../../../docs/assets/console-agent-metrics-zh.webp' const props = withDefaults(defineProps<{ lang?: Lang }>(), { lang: 'en' }) const t = computed(() => copy[props.lang]) -const archImages: Record = { ecosystem: architectureImg, protocols: componentsImg, surfaces: surfacesImg } const consoleImages = computed(() => props.lang === 'zh' ? { overview: overviewZh, metrics: metricsZh } : { overview: overviewEn, metrics: metricsEn }, ) -const archTab = ref('ecosystem') const consoleTab = ref<'overview' | 'metrics'>('overview') -const archAlt = computed(() => t.value.architecture.tabs.find((tab) => tab.id === archTab.value)!.alt) const consoleAlt = computed(() => t.value.observe.tabs.find((tab) => tab.id === consoleTab.value)!.alt) -const localizedDocs = computed(() => docsGroups.map(group => ({ ...group, group: props.lang === 'zh' ? group.zhGroup : group.group, pages: group.pages.map(page => props.lang === 'zh' ? page.zh : page) }))) function localLink(path: string) { return withBase(props.lang === 'zh' ? `/zh${path}` : path) } -const pageCount = docsGroups.reduce((n, g) => n + g.pages.length, 0) const copied = ref(false) async function copyInstall() { @@ -43,16 +36,6 @@ async function copyInstall() { } } -const termLines = computed(() => [ - { kind: 'comment', text: props.lang === 'zh' ? '# 1. 安装 Core 和 Web' : '# 1. install Core and Web' }, - { kind: 'cmd', text: installCommand }, - { kind: 'comment', text: props.lang === 'zh' ? '# 2. 在 Web 中设置默认模型,创建 Project API key' : '# 2. set a default model in Web, issue a Project API key' }, - { kind: 'cmd', text: 'export OPENAI_BASE_URL=https://core.example/v1' }, - { kind: 'cmd', text: 'read -rs OPENAI_API_KEY && export OPENAI_API_KEY' }, - { kind: 'comment', text: props.lang === 'zh' ? '# 3. 用官方 SDK 运行第一个 Session' : '# 3. run your first Session with the official SDK' }, - { kind: 'cmd', text: 'pip install openai==3.13.0 && python session.py' }, -]) - // Scrambles the hero title in from random glyphs. const GLYPHS = '01<>/\\{}[]#%&@$=+*' const titleLines = ref([...t.value.hero.title]) @@ -155,240 +138,80 @@ onBeforeUnmount(() => { - -
-
-
// {{ t.problem.index }}{{ t.problem.kicker }}
-
-
-

{{ t.problem.title }}

-

{{ t.problem.lede }}

-
-
    -
  1. -

    ?{{ item.q }}

    -

    →{{ item.a }}

    -
  2. -
-
-

{{ t.problem.punch }}

-
-
- - +
// {{ t.compose.index }}{{ t.compose.kicker }}
-

{{ t.compose.title }}

+

{{ t.compose.lede }}

-
    -
  • - [{{ p.tag }}] -

    {{ p.title }}

    -

    {{ p.body }}

    -
  • -
+
- +
// {{ t.architecture.index }}{{ t.architecture.kicker }}
-

{{ t.architecture.title }}

+

{{ t.architecture.lede }}

-
-
- -
- - - -
- + + + + {{ t.architecture.more }} →
- +
// {{ t.session.index }}{{ t.session.kicker }}
-

{{ t.session.title }}

+

{{ t.session.lede }}

-
    -
  • - -

    {{ rule.title }}

    -

    {{ rule.body }}

    -
  • -
-

!{{ t.session.honest }}

+ + {{ t.session.more }} →
- +
// {{ t.observe.index }}{{ t.observe.kicker }}
-
-
-

{{ t.observe.title }}

-

{{ t.observe.lede }}

-
- -
-

{{ t.observe.caption }}

-
-
-
web · {{ consoleTab }}
- +
+

{{ t.observe.lede }}

+
+
-
-
- - -
-
-
// {{ t.compare.index }}{{ t.compare.kicker }}
-

{{ t.compare.title }}

-
- - - - - - - - - - - -
{{ h }}
{{ row[0] }}{{ row[1] }}{{ row[2] }}
-
-
-
- - -
-
-
// {{ t.tradeoffs.index }}{{ t.tradeoffs.kicker }}
-

{{ t.tradeoffs.motto[0] }}{{ t.tradeoffs.motto[1] }}

-

{{ t.tradeoffs.title }}

-
    -
  1. - 0{{ i + 1 }} -

    {{ item.title }}

    -

    {{ item.body }}

    -
  2. -
-
-
- - -
-
-
// {{ t.start.index }}{{ t.start.kicker }}
-
-
-

{{ t.start.title }}

-

{{ t.start.lede }}

-
    -
  1. - [{{ i + 1 }}] -

    {{ step.title }}

    {{ step.body }}

    -
  2. -
- -
-
- -
+
+
web · {{ consoleTab }}
+
+

{{ t.observe.caption }}

- -
-
-
// {{ t.roadmap.index }}{{ t.roadmap.kicker }}
-

{{ t.roadmap.title }}

-

{{ t.roadmap.lede }}

-
    -
  1. - {{ track.layer }} -

    {{ track.title }}

    -

    {{ track.body }}

    -
  2. -
-
-
- - -
-
-
// {{ t.docs.index }}{{ t.docs.kicker }}
-

{{ t.docs.title }}

-

{{ t.docs.lede(pageCount) }}

-
-
-

{{ String(gi + 1).padStart(2, '0') }}/{{ group.group }}

- -
-
-
-
+ - +
+
+
// {{ t.start.index }}{{ t.start.kicker }}
+

+

{{ t.hero.installLabel }}

+
$ {{ installCommand }}
+
  1. 0{{ i + 1 }}{{ step.title }}
+ +
-
@@ -708,7 +531,7 @@ onBeforeUnmount(() => { /* ---------- sections ---------- */ .sec { position: relative; - padding: 112px 0 0; + padding: 64px 0 0; } .sec-head { display: flex; @@ -777,88 +600,6 @@ h3 { color: var(--l-accent); } -/* 01 */ -.qa { - margin: 0; - padding: 0; - list-style: none; - border: 1px solid var(--l-line); - border-radius: 3px; - background: var(--l-panel); - overflow: hidden; -} -.qa li { - padding: 16px 20px; - border-bottom: 1px dashed var(--l-line); - transition: background 0.2s; -} -.qa li:last-child { - border-bottom: 0; -} -.qa li:hover { - background: var(--l-hover); -} -.qa p { - display: flex; - margin: 0; - line-height: 1.55; -} -.q { - font-weight: 600; - font-size: 15px; -} -.q .sigil { - color: var(--l-danger); -} -.a { - margin-top: 6px !important; - font-size: 14px; - color: var(--l-text-2); -} -.punch { - max-width: 36em; - margin: 56px 0 0; - padding-left: 18px; - border-left: 2px solid var(--l-accent); - font: 500 clamp(18px, 2vw, 22px) / 1.55 var(--l-sans); -} - -/* 02 */ -.pillars { - display: grid; - grid-template-columns: repeat(4, minmax(0, 1fr)); - gap: 14px; - margin: 36px 0 0; - padding: 0; - list-style: none; -} -.pillars li { - padding: 20px; - border: 1px solid var(--l-line); - border-radius: 3px; - background: var(--l-panel); - transition: border-color 0.2s, transform 0.2s; -} -.pillars li:hover { - border-color: var(--l-accent); - transform: translateY(-2px); -} -.tag { - display: block; - margin-bottom: 12px; - font: 12px var(--l-mono); - color: var(--l-accent); -} -.pillars p, -.rules p, -.tradeoffs p, -.roadmap p { - margin: 8px 0 0; - font-size: 14.5px; - line-height: 1.6; - color: var(--l-text-2); -} - /* 03 */ .figure { border: 1px solid var(--l-line); @@ -1050,191 +791,6 @@ h3 { .dots i:nth-child(2) { background: #febc2e; } .dots i:nth-child(3) { background: #28c840; } -/* 06 */ -.table-wrap { - margin-top: 36px; - overflow-x: auto; - border: 1px solid var(--l-line); - border-radius: 3px; - background: var(--l-panel); -} -.compare { - display: table; - width: 100%; - margin: 0; - border-collapse: collapse; - font-size: 14.5px; -} -.compare th, -.compare td { - padding: 16px 20px; - border: 0; - border-bottom: 1px solid var(--l-line); - text-align: left; - vertical-align: top; - line-height: 1.55; - background: none; -} -.compare thead th { - font: 12px var(--l-mono); - text-transform: uppercase; - letter-spacing: 0.1em; - color: var(--l-muted); -} -.compare tbody th { - font: 600 14px var(--l-mono); - white-space: nowrap; -} -.compare td { - color: var(--l-text-2); -} -.compare tr { - background: none; - border: 0; -} -.compare tr.ours th, -.compare tr.ours td { - border-bottom: 0; - background: var(--l-accent-soft); -} -.compare tr.ours th { - color: var(--l-accent); -} - -/* 07 */ -.motto { - display: flex; - flex-direction: column; - margin: 8px 0 44px; - font: 700 clamp(28px, 4.4vw, 56px) / 1.1 var(--l-mono); - letter-spacing: -0.035em; -} -.tradeoffs { - display: grid; - grid-template-columns: repeat(3, minmax(0, 1fr)); - gap: 28px; - margin: 0; - padding: 0; - list-style: none; -} -.tradeoffs li { - padding-top: 18px; - border-top: 1px solid var(--l-line-strong); -} -.num { - display: block; - margin-bottom: 10px; - font: 12px var(--l-mono); - color: var(--l-accent); -} - -/* 08 */ -.steps { - display: grid; - gap: 16px; - margin: 0; - padding: 0; - list-style: none; -} -.steps li { - display: flex; - gap: 14px; -} -.step-n { - font: 14px/1.4 var(--l-mono); - color: var(--l-accent); -} -.steps p { - margin: 4px 0 0; - font-size: 14.5px; - color: var(--l-text-2); -} - -/* 09 */ -.roadmap { - position: relative; - display: grid; - grid-template-columns: repeat(4, minmax(0, 1fr)); - gap: 14px; - margin: 0; - padding: 0; - list-style: none; -} -.roadmap li { - position: relative; - padding: 20px; - border: 1px dashed var(--l-line-strong); - border-radius: 3px; -} -.layer { - display: inline-block; - margin-bottom: 12px; - padding: 3px 8px; - border-radius: 4px; - background: var(--l-accent-soft); - font: 12px var(--l-mono); - color: var(--l-accent); -} - -/* 10 */ -.docs-grid { - display: grid; - align-items: start; - grid-template-columns: repeat(4, minmax(0, 1fr)); - gap: 14px; -} -.docs-group { - padding: 18px; - border: 1px solid var(--l-line); - border-radius: 3px; - background: var(--l-panel); -} -.docs-group h3 { - margin-bottom: 12px; - font: 600 14px var(--l-mono); -} -.dir { - color: var(--l-accent); - margin-right: 4px; -} -.docs-group ul { - margin: 0; - padding: 0; - list-style: none; -} -.docs-group li + li { - border-top: 1px dashed var(--l-line); -} -.docs-group a { - display: block; - padding: 10px 0; - color: var(--l-text); -} -.doc-title { - display: block; - font-size: 14px; - font-weight: 500; - transition: color 0.15s; -} -.doc-title::before { - content: '› '; - color: var(--l-faint); - font-family: var(--l-mono); -} -.docs-group a:hover .doc-title { - color: var(--l-accent); -} -.doc-summary { - display: -webkit-box; - margin-top: 3px; - overflow: hidden; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; - font-size: 12.5px; - line-height: 1.5; - color: var(--l-muted); -} - /* outro */ .outro { position: relative; @@ -1310,8 +866,8 @@ h3 { .hero-title .accent { font-style: italic; } .cursor { font-style: normal; } .eyebrow { border-radius: 0; background: transparent; border: 0; border-left: 3px solid var(--l-accent); padding-left: 12px; } -.sec { border-top: 1px solid var(--l-line-strong); padding-bottom: 80px; } -.sec.docs-section { padding-bottom: 32px; } +.sec { border-top: 1px solid var(--l-line-strong); padding-bottom: 56px; } + .sec-head { align-items: center; } .idx { background: var(--l-accent); color: var(--l-bg); padding: 7px 10px; } h2, .motto { font-family: var(--l-display); letter-spacing: -0.045em; } @@ -1327,3 +883,56 @@ h3 { font-family: var(--l-display); } .hero-title { letter-spacing: -0.05em; } } + + + + diff --git a/website/.vitepress/theme/components/LogoWall.vue b/website/.vitepress/theme/components/LogoWall.vue index bdb668a1..70063329 100644 --- a/website/.vitepress/theme/components/LogoWall.vue +++ b/website/.vitepress/theme/components/LogoWall.vue @@ -1,4 +1,5 @@ + + + + diff --git a/website/.vitepress/theme/components/TitleAccent.vue b/website/.vitepress/theme/components/TitleAccent.vue new file mode 100644 index 00000000..842bf11f --- /dev/null +++ b/website/.vitepress/theme/components/TitleAccent.vue @@ -0,0 +1,15 @@ + + + + + diff --git a/website/.vitepress/theme/landing-content.ts b/website/.vitepress/theme/landing-content.ts index 301a4157..efd797ca 100644 --- a/website/.vitepress/theme/landing-content.ts +++ b/website/.vitepress/theme/landing-content.ts @@ -16,18 +16,11 @@ export interface LandingCopy { hud: [string, string][] } ticker: string[] - problem: { - index: string - kicker: string - title: string - lede: string - questions: { q: string; a: string }[] - punch: string - } compose: { index: string kicker: string title: string + titleAccent: string lede: string harness: string protocol: string @@ -39,72 +32,46 @@ export interface LandingCopy { footnote: string footnoteLink: string } - pillars: { tag: string; title: string; body: string }[] architecture: { index: string kicker: string title: string + titleAccent: string lede: string tabs: { id: string; label: string; alt: string }[] - boundariesTitle: string - boundaries: { from: string; to: string; doc: string; link: string }[] more: string } session: { index: string kicker: string title: string + titleAccent: string lede: string rules: { title: string; body: string; art: string }[] - honest: string + animation: { label: string; steps: string[]; messages: string[]; states: string[]; pause: string; play: string; replay: string; next: string; note: string } + more: string } observe: { index: string kicker: string title: string + titleAccent: string lede: string tabs: { id: 'overview' | 'metrics'; label: string; alt: string }[] caption: string } - compare: { - index: string - kicker: string - title: string - head: [string, string, string] - rows: [string, string, string][] - } - tradeoffs: { - index: string - kicker: string - title: string - motto: [string, string] - items: { title: string; body: string }[] - } start: { index: string kicker: string title: string + titleAccent: string lede: string steps: { title: string; body: string }[] cta: string trial: string } - roadmap: { - index: string - kicker: string - title: string - lede: string - tracks: { layer: string; title: string; body: string }[] - } - docs: { - index: string - kicker: string - title: string - lede: (pages: number) => string - open: string - } - ecosystem: { title: string; agents: string; compute: string; pause: string; resume: string } - outro: { line: string; primary: string; secondary: string } + docs: { title: string; links: { label: string; path: string }[] } + ecosystem: { title: string; titleAccent: string; agents: string; compute: string; pause: string; resume: string } } const en: LandingCopy = { @@ -126,25 +93,11 @@ const en: LandingCopy = { ], }, ticker: ['Codex', 'Claude Code', 'MiniMax Code', 'Responses API', 'Anthropic Messages', 'Chat Completions', 'Docker', 'microsandbox', 'E2B', 'Linux', 'macOS', 'Windows', 'PostgreSQL', 'OpenAI SDK'], - problem: { - index: '01', - kicker: 'the missing layer', - title: 'Calling a model is solved. Letting an agent do the work is not.', - lede: 'An agent reads files, runs commands, waits for tests and asks for approval. A single model response is one step of that. Put it inside a product and a new set of questions appears.', - questions: [ - { q: 'The user closed the tab. What happens to the work already submitted?', a: 'A dropped connection is an observer leaving. The Turn keeps running; read its durable state.' }, - { q: 'The request timed out. Send it again, or look up the original?', a: 'Poll durable state. Supported submission paths are idempotent, so a lost response does not duplicate work.' }, - { q: 'The user pressed Stop. Did the output stop, or the agent and everything it started?', a: 'Cancellation has a receipt: Core confirms the Turn\'s execution and cleanup state.' }, - { q: 'Which model and which machine ran this? Where are the files and the log?', a: 'Sessions, Turns, Items, artifacts and usage are stored by Core and queryable through the API.' }, - { q: 'Switching from Codex to Claude Code, or Docker to E2B. How much product code changes?', a: 'Your code keeps the same API calls. The harness is a Session setting with a matching model provider, and the sandbox is the administrator\'s choice, behind a Sandbox Provider.' }, - ], - punch: 'Between an agent that works in a terminal and an agent a product can call, there is a whole layer of engineering. OpenAgentCore is that layer.', - }, compose: { - index: '02', + index: '01', kicker: 'pick each part', - title: 'Choose the model, the agent and the machine separately.', - lede: 'They are three different decisions. Each Session names its harness, its model provider and its Environment; Core validates the combination before anything runs.', + title: 'Your agent. Your model. Your machine.', titleAccent: 'Your machine.', + lede: 'Choose a combination. See the API call.', harness: 'harness', protocol: 'model protocol', environment: 'environment', @@ -158,115 +111,68 @@ const en: LandingCopy = { footnote: 'The supported combinations are declared by each harness, not guessed.', footnoteLink: 'Harness capabilities', }, - pillars: [ - { tag: 'api', title: 'Same API as OpenAI', body: 'Point the official OpenAI SDK, or plain HTTP, at your installation. No new client to learn.' }, - { tag: 'agent', title: 'Your choice of agent', body: 'Each Session runs a native harness: Codex, Claude Code or MiniMax Code, with the model provider you configure.' }, - { tag: 'machine', title: 'Your choice of machine', body: 'A managed sandbox (Docker, microsandbox or E2B), or your own Linux, macOS or Windows machine.' }, - { tag: 'swap', title: 'Every part is replaceable', body: 'Sandboxes, harnesses and model providers plug in through defined protocols. Swap one without touching Core.' }, - ], architecture: { - index: '03', + index: '02', kicker: 'protocols at every boundary', - title: 'Every part plugs in through a protocol.', - lede: 'Core keeps durable execution state and schedules work. The Runtime prepares the Environment and starts the native harness. The harness calls the model and tools, and reports back through the Runtime.', + title: 'One API. Replaceable parts.', titleAccent: 'Replaceable parts.', + lede: 'Core orchestrates. Native harnesses execute. Protocols connect them.', tabs: [ { id: 'ecosystem', label: 'ecosystem', alt: 'Applications reach OpenAgentCore through the Agents API; harnesses, models and compute connect through their own boundaries.' }, { id: 'protocols', label: 'components', alt: 'Agents API and Core API on top of Core; Sandbox Provider, Runtime, Harness and Model Provider connected by protocols.' }, { id: 'surfaces', label: 'api namespaces', alt: 'Three namespaces with three credentials: Agents API for applications, Core API for operators, Machine API for nodes.' }, ], - boundariesTitle: 'one boundary · one protocol · one document', - boundaries: [ - { from: 'Application', to: 'Core', doc: 'Agents API', link: '/docs/api/public-agent-api' }, - { from: 'Core', to: 'Sandbox Provider', doc: 'Sandbox Provider guide', link: '/docs/sandbox-provider' }, - { from: 'Provider', to: 'Runtime', doc: 'Runtime bootstrap', link: '/docs/runtime-bootstrap' }, - { from: 'Core', to: 'Runtime', doc: 'Core–Runtime protocol', link: '/docs/runtime-protocol' }, - { from: 'Runtime', to: 'Harness', doc: 'Harness onboarding', link: '/contracts/agents-api/harness-onboarding' }, - { from: 'Harness', to: 'Model', doc: 'Model execution', link: '/contracts/agents-api/model-execution' }, - ], more: 'Read the architecture', }, session: { - index: '04', + index: '03', kicker: 'execution you can manage', - title: 'A run becomes a Session you can manage.', - lede: 'A Session is a continuing piece of agent work; a Turn is one input executed inside it. Both have identities and durable state. Four rules decide what "running", "waiting", "cancelled" and "failed" mean.', + title: 'Session is all you need.', titleAccent: 'Session', + lede: 'Submit work, follow its progress, and pick up the conversation.', rules: [ - { title: 'Connection ≠ work', body: 'Closing the stream only removes an observer. Submitted work stays with the execution system.', art: 'client ──────╳ disconnect\nturn ━━━━━━━━━━━━━━▶ completed' }, - { title: 'Retries have identity', body: 'Supported submission paths carry a stable key, so a lost response never creates the work twice.', art: 'POST Idempotency-Key: a1f ──▶ turn_01\nPOST Idempotency-Key: a1f ──▶ turn_01' }, - { title: 'Cancel has a receipt', body: 'Closing output proves nothing. Core confirms the target Turn\'s execution and cleanup.', art: 'cancel ──▶ turn in_progress\n ──▶ turn cancelled ✓ confirmed' }, - { title: 'Execution ≠ machine', body: 'A Turn ending, the executor closing and the Environment being reclaimed are separate lifecycles.', art: 'turn ━━━━┫\nexecutor ━━━━━━━━┫\nenvironment ━━━━━━━━━━━━━┫' }, + { title: 'Connection ≠ work', body: 'Submitted work continues after the stream closes.', art: 'client ──────╳ disconnect\nturn ━━━━━━━━━━━━━━▶ completed' }, + { title: 'Retries have identity', body: 'Stable keys prevent duplicates on supported submission paths.', art: 'POST Idempotency-Key: a1f ──▶ turn_01\nPOST Idempotency-Key: a1f ──▶ turn_01' }, + { title: 'Cancel has a receipt', body: 'Core confirms the target Turn\'s execution and cleanup.', art: 'cancel ──▶ turn in_progress\n ──▶ turn cancelled ✓ confirmed' }, + { title: 'Execution ≠ machine', body: 'Track Turns, executors and Environments separately.', art: 'turn ━━━━┫\nexecutor ━━━━━━━━┫\nenvironment ━━━━━━━━━━━━━┫' }, ], - honest: 'Recovery has limits, and they are explicit: an unknown outcome is never reported as success.', + animation: { + label: 'Execution demo', steps: ['Submit', 'Run', 'Input needed', 'Resume', 'Complete'], + messages: ['Your application submits a task.', 'The native harness runs the task.', 'The turn waits for input from your application.', 'Your application responds. Execution continues.', 'The result is ready for your application.'], + states: ['Submitted', 'Running', 'Waiting', 'Running', 'Completed'], + pause: 'Pause', play: 'Play', replay: 'Replay', next: 'Next', note: 'Illustrative workflow · Each harness declares its supported interactions.', + }, + more: 'Session lifecycle', }, observe: { - index: '05', + index: '04', kicker: 'see it run', - title: 'Operations you can actually see.', - lede: 'Web is the operator console: Sessions, node capacity, work waiting for the caller, errors, latency, tokens and tool calls, per Project.', + title: 'Operations you can actually see.', titleAccent: 'actually see.', + lede: 'Sessions · Compute capacity · Usage', tabs: [ { id: 'overview', label: 'overview', alt: 'Web console overview: service status, running Sessions, sandbox capacity, fleet and Projects.' }, { id: 'metrics', label: 'agent metrics', alt: 'Web console agent metrics: requests, errors, latency, tokens and tool calls.' }, ], caption: 'Screenshot values are illustrative. Usage visibility depends on what each native harness reports.', }, - compare: { - index: '06', - kicker: 'where it fits', - title: 'What you still own, depending on how you build.', - head: ['approach', 'fits when', 'you still own'], - rows: [ - ['Call a model API', 'One-off inference, or you want full control of the agent loop', 'Context, tool execution, the loop and the whole task lifecycle'], - ['Call a native CLI or SDK', 'Personal automation, or one integration around one harness', 'Session mapping, processes, resources and every engine\'s differences'], - ['Use a sandbox service', 'You need an isolated computer', 'The agent engine, execution, interaction, records and the product API'], - ['Use OpenAgentCore', 'Self-hosted, many native harnesses and environments behind one API', 'Business permissions, product experience, team orchestration and operating your installation'], - ], - }, - tradeoffs: { - index: '07', - kicker: 'trade-offs, stated', - title: 'The choices behind the design.', - motto: ['State belongs to the infrastructure.', 'Intelligence belongs to the harness.'], - items: [ - { title: 'Native harnesses, with their constraints', body: 'The Runtime and the native harness run inside the Environment; Core holds the durable control plane. Native engines are reused as-is, so the Environment, native history and recovery still matter.' }, - { title: 'One protocol, real differences', body: 'A capability one harness supports is not silently granted to another. Core checks each combination before running, rejects what is unsupported and records what is unverified.' }, - { title: 'Simple for the caller', body: 'Callers think in tasks, input, state and results. Machine connections, native executors and cleanup belong behind clear component boundaries. The interface is the product.' }, - ], - }, start: { - index: '08', + index: '05', kicker: 'get started', - title: 'From install to first Session.', + title: 'From install to first Session.', titleAccent: 'first Session.', lede: 'On a Linux amd64 host with Docker and Python 3.9+:', steps: [ - { title: 'Sign in to Web', body: 'Use the Core key the installer created, then configure the domain and HTTPS.' }, - { title: 'Set a default model', body: 'Then issue a Project API key for your application.' }, - { title: 'Add execution capacity', body: 'A node, E2B, or your own machine.' }, - { title: 'Run your first Session', body: 'With the official OpenAI SDK, against your own Core.' }, + { title: 'Install & sign in', body: '' }, + { title: 'Configure model & compute', body: '' }, + { title: 'Run your first Session', body: '' }, ], cta: 'Installation guide', trial: 'Quickstart', }, - roadmap: { - index: '09', - kicker: 'what comes next', - title: 'Version 1 is the foundation.', - lede: 'OpenAgentCore is pre-release; support is qualified per harness, environment and operation. The next layers we are working toward:', - tracks: [ - { layer: 'harness', title: 'Agent loop, decoupled', body: 'Run the agent loop on the server and tool execution on a local machine or a cloud sandbox, with enterprise authorization at the tool layer.' }, - { layer: 'compute', title: 'Faster, denser compute', body: 'Separate compute from storage, restore state quickly and scale sandbox capacity on demand.' }, - { layer: 'storage', title: 'More storage backends', body: 'S3, OSS, shared file systems and agent-native file systems.' }, - { layer: 'apps', title: 'Applications on the Agents API', body: 'Keep building real products on the public API, the same way any application uses it.' }, - ], - }, - docs: { - index: '10', - kicker: 'documentation', - title: 'Everything is in the docs.', - lede: (pages) => `${pages} pages, listed straight from the repository's docs.json. New guides appear here when they are added.`, - open: 'open', - }, - ecosystem: { title: 'One core. An open ecosystem.', agents: 'Harnesses & models', compute: 'Cloud & compute', pause: 'Pause', resume: 'Resume' }, - outro: { line: 'Products differ in interaction, model and engine. They can share one execution layer.', primary: 'Get started', secondary: 'Star on GitHub' }, + docs: { title: 'Explore the docs', links: [ + { label: 'Quickstart', path: '/docs/getting-started/quickstart' }, + { label: 'API reference', path: '/docs/api/public-agent-api' }, + { label: 'Deployment', path: '/docs/getting-started/install' }, + { label: 'Build an adapter', path: '/docs/development' }, + ] }, + ecosystem: { title: 'One core. An open ecosystem.', titleAccent: 'An open ecosystem.', agents: 'Harnesses & models', compute: 'Cloud & compute', pause: 'Pause', resume: 'Resume' }, } const zh: LandingCopy = { @@ -288,25 +194,11 @@ const zh: LandingCopy = { ], }, ticker: en.ticker, - problem: { - index: '01', - kicker: '缺失的一层', - title: '调用模型已经标准化,让 Agent 干活还没有。', - lede: 'Agent 要读文件、执行命令、等待测试,中途还可能需要用户确认。模型的一次返回,只是其中一步。把它接进产品,又会冒出另一组问题。', - questions: [ - { q: '用户关掉网页,已经提交的工作怎么办?', a: '连接与任务分开。连接断开只是观察者离开,Turn 继续执行,随时查询持久状态。' }, - { q: '请求超时了,应该再发一次,还是先查原来的任务?', a: '查询持久状态。已支持的提交路径带幂等标识,响应丢失也不会重复创建工作。' }, - { q: '点击“停止”,停的是输出,还是 Agent 和它启动的工作?', a: '取消要有回执:Core 确认目标 Turn 的执行和清理状态。' }, - { q: '这次用了哪个模型、哪台机器?输出文件和执行记录在哪?', a: 'Session、Turn、Items、产物和用量由 Core 保存,通过 API 查询。' }, - { q: '从 Codex 换到 Claude Code,从 Docker 换到 E2B,产品要改多少代码?', a: 'API 调用不变。Harness 是 Session 上的设置,配上相应协议的模型服务;沙箱由管理员选择,藏在 Sandbox Provider 后面。' }, - ], - punch: '一个 Agent 在终端里好用,和它能被产品稳定调用,中间还有一整层工程。OpenAgentCore 就是这一层。', - }, compose: { - index: '02', + index: '01', kicker: '自由组合', - title: '选模型、选 Agent、选机器,是三个独立的决定。', - lede: '每个 Session 指定自己的 Harness、模型服务和执行环境。Core 在执行前校验组合,不支持的直接拒绝。', + title: 'Agent、模型、机器,自由组合。', titleAccent: '自由组合。', + lede: '选一个组合,看看对应的 API 调用。', harness: 'harness', protocol: '模型协议', environment: '执行环境', @@ -320,108 +212,68 @@ const zh: LandingCopy = { footnote: '支持哪些组合,由每个 Harness 明确声明,而不是猜测。', footnoteLink: 'Harness 能力表', }, - pillars: [ - { tag: 'api', title: '与 OpenAI 相同的 API', body: '用官方 OpenAI SDK 或 HTTP,连接你自己的 Core 地址,不用学新客户端。' }, - { tag: 'agent', title: '自选 Agent', body: '每个 Session 运行一个原生 Harness:Codex、Claude Code 或 MiniMax Code,模型服务由你配置。' }, - { tag: 'machine', title: '自选机器', body: '托管沙箱(Docker、microsandbox、E2B),或你自己的 Linux、macOS、Windows 机器。' }, - { tag: 'swap', title: '部件可替换', body: '沙箱、Harness 和模型服务都通过明确的协议接入,替换任何一个都不动 Core。' }, - ], architecture: { - index: '03', + index: '02', kicker: '每条边界都是协议', - title: '每个部件,都通过协议接入。', - lede: 'Core 保存持久执行状态并调度工作;Runtime 在 Environment 中准备文件和能力,启动原生 Harness;Harness 调用模型和工具,经 Runtime 把事件回传给 Core。', + title: '一个 API,部件自由替换。', titleAccent: '部件自由替换。', + lede: 'Core 编排,原生 Harness 执行,协议连接各个部件。', tabs: [ { id: 'ecosystem', label: '生态', alt: '上层应用通过 Agents API 接入,Harness、模型服务和计算资源通过各自边界连接。' }, { id: 'protocols', label: '组件', alt: 'Core 之上是 Agents API 与 Core API;Sandbox Provider、Runtime、Harness、Model Provider 通过协议连接。' }, { id: 'surfaces', label: 'API 命名空间', alt: '三个命名空间、三种凭证:应用用 Agents API,管理员用 Core API,节点用 Machine API。' }, ], - boundariesTitle: '一条边界 · 一个协议 · 一份文档', - boundaries: en.architecture.boundaries.map((b) => ({ ...b })), more: '阅读架构文档', }, session: { - index: '04', + index: '03', kicker: '可管理的执行', - title: '把一次执行,变成可以管理的 Session。', - lede: 'Session 表示一段持续的 Agent 工作,Turn 是其中一次输入的执行。它们都有标识和持久状态。四条约定,决定了“执行中”“等待处理”“已取消”“失败”分别意味着什么。', + title: 'Session is all you need.', titleAccent: 'Session', + lede: '提交任务,追踪进度,继续对话。', rules: [ - { title: '连接 ≠ 任务', body: '关闭输出流只是观察者离开,已提交的工作仍由执行系统管理。', art: en.session.rules[0].art }, - { title: '重试有身份', body: '已支持的提交路径带稳定标识,响应丢失也不会重复创建工作。', art: en.session.rules[1].art }, - { title: '取消要有回执', body: '关闭输出流证明不了什么,Core 确认目标 Turn 的执行和清理状态。', art: en.session.rules[2].art }, - { title: '执行 ≠ 机器', body: '一轮任务结束、Executor 关闭、Environment 回收,是三个不同的生命周期。', art: en.session.rules[3].art }, + { title: '连接 ≠ 任务', body: '关闭输出流,已提交的任务仍继续执行。', art: en.session.rules[0].art }, + { title: '重试有身份', body: '支持的提交路径用稳定标识避免重复任务。', art: en.session.rules[1].art }, + { title: '取消要有回执', body: 'Core 确认任务停止与资源清理。', art: en.session.rules[2].art }, + { title: '执行 ≠ 机器', body: '分别追踪 Turn、Executor 与 Environment。', art: en.session.rules[3].art }, ], - honest: '故障恢复有边界,而且是明确的:未知结果永远不会被当成成功。', + animation: { + label: '执行流程演示', steps: ['提交', '执行', '等待输入', '继续执行', '完成'], + messages: ['应用提交一项任务。', '原生 Harness 开始执行。', 'Turn 等待应用提供输入。', '应用回应,任务继续执行。', '结果已就绪,应用可以读取。'], + states: ['已提交', '执行中', '等待中', '执行中', '已完成'], + pause: '暂停', play: '播放', replay: '重播', next: '下一步', note: '流程示意 · 交互支持范围由各 Harness 声明。', + }, + more: 'Session 生命周期', }, observe: { - index: '05', + index: '04', kicker: '看见运行', - title: '运行情况,看得见。', - lede: 'Web 是管理员控制台:按 Project 查看 Session、节点容量、等待调用方处理的工作,以及错误、耗时、Token 和工具调用。', + title: '运行情况,看得见。', titleAccent: '看得见。', + lede: 'Session 状态 · 计算资源 · 用量', tabs: [ { id: 'overview', label: '部署概览', alt: 'Web 控制台概览:服务状态、运行中的 Session、沙箱容量、节点与 Project。' }, { id: 'metrics', label: 'Agent 监控', alt: 'Web 控制台 Agent 监控:请求、错误、耗时、Token 与工具调用。' }, ], caption: '截图数值仅用于展示界面。用量可见性取决于原生 Harness 提供的数据。', }, - compare: { - index: '06', - kicker: '适用场景', - title: '不同接法,产品还要自己负责什么。', - head: ['接法', '适合什么', '还要自己负责'], - rows: [ - ['直接调用模型 API', '单次推理,或希望完全控制 Agent 循环', '上下文、工具执行、循环推进,以及完整的任务生命周期'], - ['直接调用原生 CLI / SDK', '个人自动化,或围绕一种 Harness 构建集成', '会话映射、执行进程、资源管理和不同引擎的差异'], - ['使用沙箱服务', '需要隔离的计算环境', '接入 Agent 引擎,管理执行、交互、记录和产品接口'], - ['使用 OpenAgentCore', '自部署,通过统一 API 使用多个原生 Harness 和执行环境', '业务权限、产品体验、团队编排,以及自身部署的运维'], - ], - }, - tradeoffs: { - index: '07', - kicker: '关键取舍', - title: '设计背后的选择。', - motto: ['状态归基础设施,', '智能归 Harness。'], - items: [ - { title: '保留原生 Harness,也接受它的约束', body: 'Runtime 和原生 Harness 运行在执行环境中,持久控制面放在 Core。原生引擎得以直接复用,运行环境、原生历史和恢复能力也因此仍然重要。' }, - { title: '共享协议,保留真实差异', body: '某个 Harness 支持的能力,不会被默认赋予其他 Harness。Core 在执行前检查组合,不支持的明确拒绝,待验证的如实记录。' }, - { title: '把简单留给调用者', body: '调用者只需要理解任务、输入、状态和结果。机器连接、原生执行器、资源清理,由清楚的组件边界承接。接口本身就是产品。' }, - ], - }, start: { - index: '08', + index: '05', kicker: '开始使用', - title: '从安装到第一个 Session。', + title: '从安装到第一个 Session。', titleAccent: '第一个 Session。', lede: '在装有 Docker 和 Python 3.9+ 的 Linux amd64 主机上:', steps: [ - { title: '登录 Web', body: '用安装器生成的 Core key 登录,配置域名和 HTTPS。' }, - { title: '设置默认模型', body: '再为你的应用创建 Project API key。' }, - { title: '添加执行资源', body: '节点、E2B,或你自己的机器。' }, - { title: '运行第一个 Session', body: '用官方 OpenAI SDK,连接你自己的 Core。' }, + { title: '安装并登录', body: '' }, + { title: '配置模型与计算资源', body: '' }, + { title: '运行第一个 Session', body: '' }, ], cta: '安装指南', trial: '快速开始', }, - roadmap: { - index: '09', - kicker: '下一步', - title: '1.0 只是地基。', - lede: 'OpenAgentCore 仍处于 pre-release 阶段,支持范围以具体的 Harness、环境和操作组合为单位验收。接下来的方向:', - tracks: [ - { layer: 'harness', title: 'Agent loop 与工具解耦', body: 'Loop 运行在服务端,工具在用户本地或云端沙箱执行,工具层实现企业级鉴权。' }, - { layer: 'compute', title: '更快、更密的计算', body: '存算分离、快速恢复状态,按需扩容沙箱容量。' }, - { layer: 'storage', title: '更多存储介质', body: 'S3、OSS、共享文件系统,以及面向 Agent 的文件系统。' }, - { layer: 'apps', title: '基于 Agents API 的应用', body: '继续在公开 API 上打磨真实产品,和任何应用的接入方式完全一样。' }, - ], - }, - docs: { - index: '10', - kicker: '文档', - title: '一切细节,都在文档里。', - lede: (pages) => `共 ${pages} 页,直接读取仓库的 docs.json 生成。新增文档会自动出现在这里。支持中英文阅读。`, - open: '打开', - }, - ecosystem: { title: '一个内核,开放的生态。', agents: 'Harness 与模型', compute: '云计算与沙箱', pause: '暂停', resume: '继续' }, - outro: { line: '产品可以有不同的交互、模型和执行引擎,共用同一层执行基础设施。', primary: '开始使用', secondary: '在 GitHub 上 Star' }, + docs: { title: '文档入口', links: [ + { label: '快速开始', path: '/docs/getting-started/quickstart' }, + { label: 'API 参考', path: '/docs/api/public-agent-api' }, + { label: '部署指南', path: '/docs/getting-started/install' }, + { label: '扩展适配器', path: '/docs/development' }, + ] }, + ecosystem: { title: '一个内核,开放的生态。', titleAccent: '开放的生态。', agents: 'Harness 与模型', compute: '云计算与沙箱', pause: '暂停', resume: '继续' }, } export const copy: Record = { en, zh } diff --git a/website/README.md b/website/README.md index 714049b6..b9af5b4e 100644 --- a/website/README.md +++ b/website/README.md @@ -15,7 +15,7 @@ pnpm --dir website preview # serve the build at http://127.0.0.1:4181 ## How documentation reaches the site - The content root is the repository root. `docs/**` and `contracts/**` keep their paths as URLs, so `docs/architecture.md` is `/docs/architecture`. `website/index.md` and `website/zh/index.md` are mapped onto `/` and `/zh/`. Chinese sources in `docs/zh/` and `contracts/agents-api/zh/` map to `/zh/docs/` and `/zh/contracts/agents-api/`; the language switch opens the matching page. -- `docs.json` owns the page list and order. The sidebar, the landing page's documentation index and `/llms.txt` are generated from it at build time; each page's frontmatter `title` is its label. Every Markdown page under `docs/` and `contracts/` is built; listing it in `docs.json` adds it to the sidebar, the landing page and `llms.txt`. +- `docs.json` owns the page list and order. The sidebar and `/llms.txt` are generated from it at build time; each page's frontmatter `title` is its label. Every Markdown page under `docs/` and `contracts/` is built; listing it in `docs.json` adds it to the sidebar and `llms.txt`. - Each page's source Markdown is published next to its HTML (`/docs/architecture.md`), and the `README` paths declared in `docs.json` redirect to their section index. - Relative links from a page to a file that is not a published page, such as `CONTRIBUTING.md` or `openapi.yaml`, are rewritten to GitHub at build time, so the Markdown works unchanged on GitHub and on the site. @@ -25,9 +25,11 @@ Site appearance and metadata are configured in `.vitepress/config.mts` and `.vit The landing page lives in `.vitepress/theme/`. `landing-content.ts` holds its English and Chinese copy; every claim there must be backed by a page in `docs/` or `contracts/`, and its harness protocols follow [Model execution](../contracts/agents-api/model-execution.md). +The landing page has five numbered sections: the interactive combination example, an architecture image, execution lifecycle, console screenshots and installation. Four documentation shortcuts link to the detailed guides. `components/SessionFlow.vue` illustrates native execution, Core orchestration and multiple Session environments through a three-stage hand-drawn animation. It autoplays while visible and offers previous/next buttons, a stage slider and pause/play. Reduced-motion preferences disable autoplay. The diagram uses the locally bundled [Virgil font](https://github.com/excalidraw/virgil); its OFL license is stored beside the font in `.vitepress/theme/assets/fonts/`. Section headings share the hero’s display font with white text and green italic accents. + ### Ecosystem logo wall -`components/LogoWall.vue` places two full-width white logo rows between section 10 and the closing section. The wall is transparent and borderless, allowing the landing page's background and grid to continue through it. Harness and model brands occupy the first row; cloud and compute brands occupy the second. They scroll in opposite directions, pause on hover or row keyboard focus, and have an explicit pause control. Reduced-motion preferences disable animation and leave both rows manually scrollable. Labels and controls use the landing page's English and Chinese copy. +`components/LogoWall.vue` places two full-width white logo rows between the documentation shortcuts and the closing installation section. The wall is transparent and borderless, allowing the landing page's background and grid to continue through it. Harness and model brands occupy the first row; cloud and compute brands occupy the second. They scroll in opposite directions, pause on hover or row keyboard focus, and have an explicit pause control. Reduced-motion preferences disable animation and leave both rows manually scrollable. Labels and controls use the landing page's English and Chinese copy. `.vitepress/theme/ecosystem-logos.ts` owns the brand list. These are ecosystem illustrations; supported Harness combinations remain defined by [Model execution](../contracts/agents-api/model-execution.md), and host requirements by [Installation](../docs/getting-started/install.md). Brand artwork does not establish deployment qualification or a partnership.