diff --git a/README.md b/README.md
index 0c868089a..d7f6659b7 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
# OpenAgentCore
-An open-source, self-hosted implementation of the OpenAI Agents API with multiple native harnesses.
+An open-source, self-hosted implementation of the OpenAI Agents API with multiple native Harnesses.
[Website](https://openagentcore.dev/) · [Install](#install) · [Call the API](https://openagentcore.dev/docs/getting-started/quickstart) · [Documentation](https://openagentcore.dev/docs/getting-started/) · [Contributing](CONTRIBUTING.md)
@@ -17,9 +17,9 @@ An open-source, self-hosted implementation of the OpenAI Agents API with multipl
OpenAgentCore runs AI agents on your own infrastructure behind the [OpenAI Agents API](https://developers.openai.com/api/docs/guides/agents-api/overview).
- **Same API as OpenAI.** Point the [OpenAI Agent API](https://developers.openai.com/api/docs/guides/agents/sdk), or plain HTTP, at your installation. No new client to learn.
-- **Your choice of agent.** Each [Session](https://openagentcore.dev/docs/api/public-agent-api) runs a [native harness](https://openagentcore.dev/contracts/agents-api/harness-onboarding): [Codex](https://github.com/openai/codex), [Claude Code](https://code.claude.com/docs/en/overview) or [MiniMax Code](https://github.com/MiniMax-AI/minimax-code), with the [model provider you configure](https://openagentcore.dev/contracts/agents-api/model-execution).
+- **Your choice of agent.** Each [Session](https://openagentcore.dev/docs/api/public-agent-api) runs a [native Harness](https://openagentcore.dev/contracts/agents-api/harness-onboarding): [Codex](https://github.com/openai/codex), [Claude Code](https://code.claude.com/docs/en/overview) or [MiniMax Code](https://github.com/MiniMax-AI/minimax-code), with the [model provider you configure](https://openagentcore.dev/contracts/agents-api/model-execution).
- **Reusable compute, persistent workspaces.** We recommend [microsandbox](https://github.com/zerocore-ai/microsandbox) with [independent workspace storage](https://openagentcore.dev/docs/workspace-provider): idle sandboxes suspend, release compute and resume on compatible nodes. [E2B](https://e2b.dev/) is the managed alternative; Docker and your own Linux, macOS or Windows machine remain supported execution choices.
-- **Every part is replaceable.** [Sandboxes](https://openagentcore.dev/docs/sandbox-provider), [workspace filesystems](https://openagentcore.dev/docs/workspace-provider), [harnesses](https://openagentcore.dev/contracts/agents-api/harness-onboarding) and [model providers](https://openagentcore.dev/contracts/agents-api/model-execution) plug in through [defined protocols](AGENTS.md#protocols-at-every-boundary).
+- **Every part is replaceable.** [Sandboxes](https://openagentcore.dev/docs/sandbox-provider), [workspace filesystems](https://openagentcore.dev/docs/workspace-provider), [Harnesses](https://openagentcore.dev/contracts/agents-api/harness-onboarding) and [model providers](https://openagentcore.dev/contracts/agents-api/model-execution) plug in through [defined protocols](AGENTS.md#protocols-at-every-boundary).
## How it fits together
@@ -32,7 +32,7 @@ Applications and operators use these Core APIs:
| **[Agents API](https://openagentcore.dev/docs/api/public-agent-api)** | `/v1` | Your applications. Same protocol as [OpenAI's Agents API](https://developers.openai.com/api/docs/guides/agents-api/overview) |
| **[Core API](https://openagentcore.dev/contracts/agents-api/admin-api)** | `/core/v1` | Operators, through Web |
-Core keeps durable execution state. The Runtime runs the chosen harness inside the Environment. Each connection is a defined protocol, so any part can be replaced on its own. See the [architecture guide](https://openagentcore.dev/docs/architecture).
+Core keeps durable execution state. The Runtime runs the chosen Harness inside the Environment. Each connection is a defined protocol, so any part can be replaced on its own. See the [architecture guide](https://openagentcore.dev/docs/architecture).
## Screenshots
@@ -73,6 +73,6 @@ The [installation guide](https://openagentcore.dev/docs/getting-started/install)
| Run agents on my own machine | [Self-hosted execution](https://openagentcore.dev/docs/getting-started/self-hosted) |
| Check Harness capabilities and limits | [Harness capabilities](https://openagentcore.dev/contracts/agents-api/harness-capabilities) |
| Understand the design | [Architecture](https://openagentcore.dev/docs/architecture) |
-| Add a sandbox, harness or other component | [Developer guide](https://openagentcore.dev/docs/development) |
+| Add a sandbox, Harness or other component | [Developer guide](https://openagentcore.dev/docs/development) |
All pages: [documentation index](https://openagentcore.dev/docs/getting-started/). Before changing code, read the [contributor rules](CONTRIBUTING.md).
diff --git a/README.zh-CN.md b/README.zh-CN.md
index 14d0c02e7..35938017a 100644
--- a/README.zh-CN.md
+++ b/README.zh-CN.md
@@ -4,7 +4,7 @@
# OpenAgentCore
-OpenAI Agents API 的开源实现,支持多种原生执行引擎,可部署在自己的基础设施上。
+OpenAI Agents API 的开源实现,支持多种原生 Harness,可部署在自己的基础设施上。
[官网](https://openagentcore.dev/zh/) · [安装](#安装) · [调用 API](https://openagentcore.dev/zh/docs/getting-started/quickstart) · [文档](https://openagentcore.dev/zh/docs/getting-started/) · [参与贡献](CONTRIBUTING.md)
@@ -56,8 +56,8 @@ irm https://github.com/MiniMax-AI/OpenAgentCore/releases/latest/download/install
然后:
-1. 用安装器生成的 Core key **登录 Web**(管理控制台),并**配置域名和 HTTPS**。
-2. **设置默认模型**,并**签发 Project API key**。
+1. 用安装器生成的 Core 密钥 **登录 Web**(管理控制台),并**配置域名和 HTTPS**。
+2. **设置默认模型**,并**签发项目 API 密钥**。
3. **添加执行资源**:节点、E2B,或你自己的机器。
4. 用 OpenAI SDK **[运行第一个 Session](https://openagentcore.dev/zh/docs/getting-started/quickstart)**。
diff --git a/apps/web/.impeccable/design.json b/apps/web/.impeccable/design.json
index 05af4657e..ed5f742b6 100644
--- a/apps/web/.impeccable/design.json
+++ b/apps/web/.impeccable/design.json
@@ -739,7 +739,7 @@
},
{
"name": "The Plain Vocabulary Rule",
- "body": "zh-CN copy uses one term per concept: 项目 (project), 沙箱 (sandbox), 运行时 (runtime), 创建者 (creator), 已上报 (reported), 活跃 (active), 提供方 (provider). API terms stay in English (Agent, Session, Turn, Skill, Vault, Credential, API key). Time ranges read \"1 小时 / 6 小时 / 24 小时 / 7 天\" (English \"1h / 6h / 24h / 7d\"), always in the one segmented control style.",
+ "body": "zh-CN copy and the zh docs use one term per concept: 项目 (project), 沙箱 (sandbox), 提供商 (provider: 沙箱提供商 for the sandbox provider, 模型提供商 for the model provider, and the MCP provider behind a Credential), 凭据 (any other credential), 执行器 (executor), 主机 (host), 模板 (template), 密钥 (key: Core 密钥, 项目 API 密钥), 创建者 (creator), 已上报 (reported), 活跃 (active). API terms stay in English (Agent, Session, Turn, Item, Runtime, Environment, Harness, Skill, Vault, Credential), and usage counts are \"token\". Time ranges read \"1 小时 / 6 小时 / 24 小时 / 7 天\" (English \"1h / 6h / 24h / 7d\"), always in the one segmented control style.",
"section": "typography"
},
{
diff --git a/apps/web/.impeccable/surfaces/src-app-tsx.md b/apps/web/.impeccable/surfaces/src-app-tsx.md
index c5092f7ad..a3b0b0337 100644
--- a/apps/web/.impeccable/surfaces/src-app-tsx.md
+++ b/apps/web/.impeccable/surfaces/src-app-tsx.md
@@ -7,7 +7,7 @@ related_targets: ["src/ConsoleApp.tsx"]
# Administrator console (operate)
-Scope: the signed-in console shell and every page behind it, including Getting started on the Overview and the optional console tour. Visitor mode: Operate. Audience: the administrator of one OpenAgentCore deployment. Task: judge health, capacity, usage and failures; inspect and delete project assets; manage projects, keys, nodes and each harness's default model. Constraints: Web API only (`/core/v1`); missing data stays visibly missing; no small print, explanations live in help tips; API terms stay English in Chinese copy; zh-CN and English, light and dark.
+Scope: the signed-in console shell and every page behind it, including Getting started on the Overview and the optional console tour. Visitor mode: Operate. Audience: the administrator of one OpenAgentCore deployment. Task: judge health, capacity, usage and failures; inspect and delete project assets; manage projects, keys, nodes and each Harness's default model. Constraints: Web API only (`/core/v1`); missing data stays visibly missing; no small print, explanations live in help tips; API terms stay English in Chinese copy; zh-CN and English, light and dark.
Information architecture: Monitor (Overview, Core metrics, Agent metrics, Sandbox metrics, Session log) · Resources (Agents, Environment templates, Skills, Files, Vaults) · Platform (Projects and keys, Nodes, System).
diff --git a/apps/web/DESIGN.md b/apps/web/DESIGN.md
index 96bd4058e..875db00db 100644
--- a/apps/web/DESIGN.md
+++ b/apps/web/DESIGN.md
@@ -290,7 +290,7 @@ A restrained neutral ledger with one indigo voice, three signal colours and a se
**The Honest Figure Rule.** Missing data renders as "—", a gap in the line, "Unavailable" or "Unknown"; never as 0. Compact numbers keep two decimals only when the integer part is a single digit ("1.04M"), otherwise one ("415.7万"); values under 10,000 print whole. Durations read "850 ms / 12.4 s / 4m 12s / 3h 5m".
-**The Plain Vocabulary Rule.** zh-CN copy uses one term per concept: 项目 (project), 沙箱 (sandbox), 运行时 (runtime), 创建者 (creator), 已上报 (reported), 活跃 (active), 提供方 (provider). API terms stay in English (Agent, Session, Turn, Skill, Vault, Credential, API key). Time ranges read "1 小时 / 6 小时 / 24 小时 / 7 天" (English "1h / 6h / 24h / 7d"), always in the one segmented control style.
+**The Plain Vocabulary Rule.** zh-CN copy and the zh docs use one term per concept: 项目 (project), 沙箱 (sandbox), 提供商 (provider: 沙箱提供商 for the sandbox provider, 模型提供商 for the model provider, and the MCP provider behind a Credential), 凭据 (any other credential), 执行器 (executor), 主机 (host), 模板 (template), 密钥 (key: Core 密钥, 项目 API 密钥), 创建者 (creator), 已上报 (reported), 活跃 (active). API terms stay in English (Agent, Session, Turn, Item, Runtime, Environment, Harness, Skill, Vault, Credential), and usage counts are "token". Time ranges read "1 小时 / 6 小时 / 24 小时 / 7 天" (English "1h / 6h / 24h / 7d"), always in the one segmented control style.
## Layout
@@ -404,7 +404,7 @@ A local-only installation has the same amber notice on Overview, Nodes and Setti
Signing in and the console tour share one frame: a dark stage on the left (always dark, whatever the theme) and the task panel on the right, which follows the theme. The stage is the product's one authored moment: a flickering indigo dot grid under slow light rays (Magic UI's flickering grid and light rays), Core as the OpenAgentCore mark on a tile with a travelling border beam, and two orbits of Agents, Sessions, Skills, Vaults, files, templates and machines around it; the OpenAgentCore mark is itself nodes on a ring. Brand copy sits bottom-left in solid ink; it is a paragraph, not a heading, because the panel's title names the task. Signing in asks for one thing, the deployment's Core key, in a single password field; a copyable Docker Compose command to read the key stays visible beneath it, with a reminder to substitute a custom installation directory. The key’s authority stays in a help tip. A refused key, too many attempts or an unavailable console is an error beside the field. Signing in opens the console on the Overview. The optional tour has three chapters — Monitor, Resources, Platform — whose stage shows a real dark screenshot of those pages, tilted towards the panel; it takes the place of the console until its last button, Skip or Escape, and then returns the focus to the control that opened it. Entering the console or the tour, and leaving the tour, happen inside a View Transition: the old page dissolves forward and the new one is revealed in a circle growing from the pressed button. With reduced motion the orbits hold their places, the grid is a still frame and no transition runs.
### Getting started
-The first card on the Overview while any step is to do: a card header ("Getting started", "n of 4 done", a help tip, then a ghost Take the tour button and an icon button that hides it) over four rows split by Faint Rules. Each row has a 22px numbered ring (a check on the tile wash when done), a 13px/600 title over one 12.5px Graphite line, a status dot (Done in green, To do in Pencil, Checking pending, Unknown for a failed read) and one outline action while the step is to do: Set up sandboxes, Add node, Open Nodes or Open sandbox backend; Open Settings; Create project (which continues to the new project's first key) or Issue key; See how to call (the newest active project, preferring one with an active key), or Projects and keys without an active project. Add node, Create project and Issue key open their page with the dialog already open; Open Settings brings the Models and credentials tab to the top of the page body and focuses the default harness's Set or Replace; See how to call opens the project and, once its keys, usage and address are read, brings its How to call heading to the top of the page body, focused. Only the page body scrolls; the page header stays. Every step done turns it into one line, "You're set", with Take the tour and Dismiss; it stays, through the tour, until dismissed, and the checklist does not come back on its own. The choice is kept per installation in the browser, also while the deployment cannot be read; Show Getting started, a quiet row above the sidebar's account controls, opens it again at any time.
+The first card on the Overview while any step is to do: a card header ("Getting started", "n of 4 done", a help tip, then a ghost Take the tour button and an icon button that hides it) over four rows split by Faint Rules. Each row has a 22px numbered ring (a check on the tile wash when done), a 13px/600 title over one 12.5px Graphite line, a status dot (Done in green, To do in Pencil, Checking pending, Unknown for a failed read) and one outline action while the step is to do: Set up sandboxes, Add node, Open Nodes or Open sandbox backend; Open Settings; Create project (which continues to the new project's first key) or Issue key; See how to call (the newest active project, preferring one with an active key), or Projects and keys without an active project. Add node, Create project and Issue key open their page with the dialog already open; Open Settings brings the Models and credentials tab to the top of the page body and focuses the default Harness's Set or Replace; See how to call opens the project and, once its keys, usage and address are read, brings its How to call heading to the top of the page body, focused. Only the page body scrolls; the page header stays. Every step done turns it into one line, "You're set", with Take the tour and Dismiss; it stays, through the tour, until dismissed, and the checklist does not come back on its own. The choice is kept per installation in the browser, also while the deployment cannot be read; Show Getting started, a quiet row above the sidebar's account controls, opens it again at any time.
### Sandbox setup
Setting up hosted sandboxes is a set of pages inside Settings → Sandbox and scheduling, one decision each: where sandboxes run (own machines or E2B), then the backend or the E2B account, then the size of each sandbox (three presets; E2B skips it, since each sandbox takes the template build's size), then a review. Choices are large cards that advance on a click; short indigo dashes show the progress; pages slide and blur across. The backend page compares microsandbox and Docker behind a help tip; microsandbox comes first, preselected (a saved backend stays selected), with a neutral Recommended pill beside its title. Docker takes a confirmation (see Dialogs) once per visit to setup; a saved Docker deployment has already made it. The review states where sandboxes run, the size, the Runtime (taken from this console's distribution manifest) and the Core address, read-only: it is config.json's `public_url`, and the console never asks for it. A loopback address carries an amber line under it: only the Core machine reaches it. When Core rejects the configuration for it (E2B with a loopback `public_url`), a red-tinted block under the review keeps Core's message and adds Managed in Settings, which leads to Settings → Service and deployment. A save attempt clears the transient E2B key. Initial setup then asks for it again, with a link to that step; an update may leave it blank to keep the committed key. Advanced settings, one link away, hold the complete form: resources (not for E2B), the Runtime release and the E2B template. A change keeps the saved size and Runtime while the backend stays the same (a saved size outside the presets is offered as Current). Same-backend editing starts at size or E2B credentials with the provider fixed. It is an online configuration update, including when older sandboxes remain: existing node identities and resource ownership are retained. Changing the backend or E2B team requires reset and then a new setup. E2B updates can omit the key to retain it; every explicitly entered key takes the verified replacement path and advances the target generation on success, including the same value. Rejections remain inline with a safe reason and a deliberate way back to reset; never infer teams from a key, auto-reset or auto-resubmit. Optional explanations sit behind help tips; errors and safety consequences remain visible.
@@ -434,7 +434,7 @@ Sandbox and scheduling contains sandbox setup or Deployment provider (Provider,
Workspace storage shows the selected configuration's adapter and tenant capacity (in bytes units, or No tenant capacity limit) under Storage configuration, with Select new configuration in the section header and Edit tenant capacity on the capacity row. The configuration ID and parameters JSON sit in a closed Configuration details disclosure at the end of the card. Select new configuration accepts an adapter identifier, configuration ID, parameters JSON object and optional write-only credential JSON object. Edit tenant capacity keeps the current configuration identity. Explain adapter preparation and existing-workspace behavior behind help tips, with a link to the owning configuration document; keep required form labels and validation visible. Never prefill credentials or persist their drafts across navigation. A failed read is not an unconfigured filesystem, and an uncertain write is not a safe automatic retry.
-Models and credentials stacks one default-model card per harness. Its header carries the harness name, its readiness (Ready in green; Model provider not set in amber, with Set as the primary button; Disabled in neutral, with a View startup settings text action), a Default pill, a help tip and the Set, Replace and Clear actions; rows hold model ID, provider protocol, base URL, key presence, token limits when set and update time, and a foot holds Usage details. Set and Replace open one form dialog. The adapter declaration supplies supported protocols, native JSON support and required limits without harness-specific branches. Native settings use an optional JSON object editor with formatting and inline syntax errors. Changing model identity clears native JSON; replacing only the required write-only API key does not. Keys are never prefilled and are forgotten when the form closes. Core rejections remain visible in the form; Clear uses ConfirmDialog. Usage details opens Core's observations separately.
+Models and credentials stacks one default-model card per Harness. Its header carries the Harness name, its readiness (Ready in green; Model provider not set in amber, with Set as the primary button; Disabled in neutral, with a View startup settings text action), a Default pill, a help tip and the Set, Replace and Clear actions; rows hold model ID, provider protocol, base URL, key presence, token limits when set and update time, and a foot holds Usage details. Set and Replace open one form dialog. The adapter declaration supplies supported protocols, native JSON support and required limits without harness-specific branches. Native settings use an optional JSON object editor with formatting and inline syntax errors. Changing model identity clears native JSON; replacing only the required write-only API key does not. Keys are never prefilled and are forgotten when the form closes. Core rejections remain visible in the form; Clear uses ConfirmDialog. Usage details opens Core's observations separately.
Service and deployment shows installation addresses, an Installation details disclosure, closed by default, with the installation ID and source commit, existing Domain and HTTPS actions, and the startup settings Core loaded. Process settings remain read-only here; their source stays the installation configuration. Each row's label is the setting's environment variable in code style (OAC_LOG_LEVEL), as Core reports it, wrapping after an underscore so a phone keeps all three columns; values show as is, with arrays joined, On or Off for booleans and None for an empty list. How to change a setting in the section header links to the configuration guide. Sensitive settings show only Configured or Not set. Default uses a neutral pill.
diff --git a/apps/web/PRODUCT.md b/apps/web/PRODUCT.md
index 5540b974e..c56384893 100644
--- a/apps/web/PRODUCT.md
+++ b/apps/web/PRODUCT.md
@@ -31,7 +31,7 @@ The console runs beside the administrator's own Core, with execution, files and
- **Monitor**: Overview (service status, running Sessions, sandbox slots, the Needs attention count for the last 24 hours, 24-hour Session activity, a compact inventory of Core and up to four nodes, prioritizing offline and degraded nodes when the list is full, where Core opens Core metrics, a node opens its page on Nodes and E2B opens Sandbox metrics, the Needs attention table, whose rows name each Session, its project, its one-line reason and last activity and open it, with older ones left to the Session log, usage by project), Core metrics (whether Core can run Turns: execution slots, the Turn queue, its p95 wait and interrupted Turns, connected daemons, database latency, the Core process's CPU and memory, and background jobs; Go heap, goroutines and the database pool sit in a collapsed Diagnostics area), Agent metrics (requests, errors, duration, tokens, models, tools, Agents and API keys for 1 h / 6 h / 24 h / 7 d), Sandbox metrics (hosted Runtimes across projects over time, active against total; a sandbox opens in a dialog with its figures and CPU and memory charts; an E2B deployment adds what Core holds in E2B's cloud), Request log (recent public or administration HTTP requests, status, duration, safe error code and correlation IDs; bounded to the serving Core instance, with manual refresh and no body capture), Session log (every Session, read-only, with a failed Session's reason under its status, opening one Session's history, which jumps to its failed Turns; a self-hosted Session's page also has its environment's executor credentials). Session facts and Agent metrics link to an Agent's page only when that saved resource exists; inline snapshots and snapshots of deleted Agents remain readable without a broken resource link. Agent metrics' failed Turns open the Agent's Sessions in the Session log.
- **Resources**: Agents, Environment templates, Skills, Files, Vaults. Each list shows one project or all projects, with a Project column when all are shown and a Creator column naming the creating key. Detail pages show the resource's facts and offer Delete. An empty list says, in one sentence, that applications create these resources through the Agents API, and links to that resource's section of the API guide; Agent metrics does the same for Sessions.
-- **Platform**: Projects and keys (projects, their assets and usage, named keys, write history), Nodes (the node list, each node's capacity and limits, host figures and charts, allocations, Add node, Edit node and individual removal operations), and Settings, the single entry for platform configuration. Settings has four groups: Sandbox and scheduling, Workspace storage, Models and credentials, and Service and deployment. Sandbox and scheduling owns setup, resource edits, rollout, reset and the idle policy, and links to Nodes for nodes and their capacity. Add node on Nodes asks for limits before issuing its one-time command; installers use Core's public URL and require supported node artifacts. Edit node changes a node's name and limits; removal stays on the node page and offers the host's uninstall command. Models and credentials owns each harness's default model and shows whether each harness is ready: Ready when it is enabled and has a default model provider, otherwise the missing step, Model provider not set (with Set as the primary action) or Disabled (with a link to the startup settings). Getting started uses the same readiness. Service and deployment owns installation facts (the public and API base URLs, with the installation ID and source commit behind Installation details), Domain and HTTPS actions and read-only startup settings, each named by its environment variable, with a link to the configuration guide's section on changing them.
+- **Platform**: Projects and keys (projects, their assets and usage, named keys, write history), Nodes (the node list, each node's capacity and limits, host figures and charts, allocations, Add node, Edit node and individual removal operations), and Settings, the single entry for platform configuration. Settings has four groups: Sandbox and scheduling, Workspace storage, Models and credentials, and Service and deployment. Sandbox and scheduling owns setup, resource edits, rollout, reset and the idle policy, and links to Nodes for nodes and their capacity. Add node on Nodes asks for limits before issuing its one-time command; installers use Core's public URL and require supported node artifacts. Edit node changes a node's name and limits; removal stays on the node page and offers the host's uninstall command. Models and credentials owns each Harness's default model and shows whether each Harness is ready: Ready when it is enabled and has a default model provider, otherwise the missing step, Model provider not set (with Set as the primary action) or Disabled (with a link to the startup settings). Getting started uses the same readiness. Service and deployment owns installation facts (the public and API base URLs, with the installation ID and source commit behind Installation details), Domain and HTTPS actions and read-only startup settings, each named by its environment variable, with a link to the configuration guide's section on changing them.
- A node whose provider is not ready names the reason as one Provider-neutral readiness class (provider unavailable, host unsupported, provider files or Runtime image missing, Runtime download failed, a host too small) and its fix in the help tip beside its status, wherever that status shows.
- A node enrolled with an earlier Core address gets no new sandboxes, so on the Nodes list and its page its status is Old address, with "Remove and add again", never Available.
- **Sandbox reset** is an explicit administrator operation in Settings → Sandbox and scheduling. Auto clear is the default, with a one-hour deadline (5 minutes–24 hours); Force clear requires destructive confirmation. Reset stops new hosted Session admission, clears idle, suspended and pending hosted work, and waits for busy Turns and file writes until Core forces the remaining work. It does not affect self-hosted execution. Histories and persisted Files/Artifacts remain; archived Sessions cannot resume, and unpersisted workspace contents may be lost. Cancel stops further clearing without undoing archives. Core alone reports progress and completion, including resources blocked on named offline nodes; force does not bypass their cleanup. Completion clears the backend configuration and retires old nodes/enrollment credentials. A new configuration is then a separate deliberate save.
@@ -39,8 +39,8 @@ The console runs beside the administrator's own Core, with execution, files and
- **E2B credential replacement** uses the same configuration form. Setup requires a key; leaving it blank during an update keeps the saved key. An explicit key, even the same value, is verified as a replacement and advances the target generation after successful verification. Another backend or E2B team requires a deliberate reset. A rejected or uncertain replacement never clears the committed configuration or replays the write.
- **E2B deployments** have no machines: Nodes offers a link to Settings → Sandbox and scheduling. Overview and Sandbox metrics show the sandboxes Core holds in E2B's cloud (running, starting, size, template build) instead of node capacity, with no Add node action; a sandbox's dialog adds its disk use.
- **Automatic suspension** appears when the deployment declares a suspension policy. Nodes shows each node's suspended count and retained limit, the most sandboxes it keeps running and suspended together, with Edit node for its limits; Overview adds the suspended total of all registered nodes under its sandbox slots. Settings → Sandbox and scheduling owns **Automatic suspension**: deployment-wide idle seconds are editable there; snapshot retention remains read-only. Necessary policy explanations belong in help tips, not persistent helper paragraphs. These are Core records, not measured CPU or memory savings. Node allocations show the recorded compute phase and elapsed phase time, never an inferred snapshot-expiry countdown. Sandbox metrics retains Runtime observation status separately from the matching allocation's recorded phase. Independent workspace persistence is explained only when the deployment declares it. Nodes refreshes its inventory every 30 seconds while visible; reset and active preparation retain their faster polling.
-- **Getting started**: signing in opens the console on the Overview; nothing is forced first. While a step is to do, a Getting started checklist on the Overview shows four steps, in any order, each with its state and one action: sandboxes ready (a saved deployment and a node online and ready, or a saved E2B deployment whose template build is not reported as not ready), a default model provider on the default harness (on any enabled harness when none is default), a project with an active key, and a first Session, whose action opens the call samples of the newest active project, preferring one with an active key. Completion comes from reads the console already makes. It can be hidden; Show Getting started in the sidebar opens it again, and it ends with a brief "You're set". While it is open, Add node ends with the next step once its node is ready: the default model provider while that is to do, otherwise back to the checklist. The optional three-chapter tour of the console (Monitor, Resources, Platform) opens from it, on the sign-in stage.
-- Terminology: API terms stay in English in the Chinese UI (Agent, Session, Turn, Skill, Vault, Credential, Harness). The sign-in credential is the Core key ("Core 密钥"); keys issued in a project for applications are project API keys ("项目 API 密钥"). Empty lists read "No … yet" ("还没有…"). Provider readiness is "Provider not ready / 提供方未就绪"; revoked credentials and keys use "Revoked / 已撤销". A default model provider is a service address and write-only key; the application's Agent `model` chooses the provider-supported model name. A sandbox is Core-managed compute; Runtime names Core's execution observations, and Environment is the Session's API execution environment. These are distinct counts and resources, not synonyms.
+- **Getting started**: signing in opens the console on the Overview; nothing is forced first. While a step is to do, a Getting started checklist on the Overview shows four steps, in any order, each with its state and one action: sandboxes ready (a saved deployment and a node online and ready, or a saved E2B deployment whose template build is not reported as not ready), a default model provider on the default Harness (on any enabled Harness when none is default), a project with an active key, and a first Session, whose action opens the call samples of the newest active project, preferring one with an active key. Completion comes from reads the console already makes. It can be hidden; Show Getting started in the sidebar opens it again, and it ends with a brief "You're set". While it is open, Add node ends with the next step once its node is ready: the default model provider while that is to do, otherwise back to the checklist. The optional three-chapter tour of the console (Monitor, Resources, Platform) opens from it, on the sign-in stage.
+- Terminology: API terms stay in English in the Chinese UI and docs (Agent, Session, Turn, Item, Runtime, Environment, Skill, Vault, Credential, Harness); providers are 提供商 (沙箱提供商, 模型提供商). The sign-in credential is the Core key ("Core 密钥"); keys issued in a project for applications are project API keys ("项目 API 密钥"). Empty lists read "No … yet" ("还没有…"). Sandbox provider readiness is "Provider not ready / 沙箱提供商未就绪"; revoked credentials and keys use "Revoked / 已撤销". A default model provider is a service address and write-only key; the application's Agent `model` chooses the provider-supported model name. A sandbox is Core-managed compute; Runtime names Core's execution observations, and Environment is the Session's API execution environment. These are distinct counts and resources, not synonyms.
## Capabilities and Constraints
@@ -56,7 +56,7 @@ The console runs beside the administrator's own Core, with execution, files and
- **Session history is read-only.** A Session page reads the Session, its Items and Turns and polls while work is in flight; there is no live event stream.
- **Failure diagnostics.** Failed Session and Turn rows read Core diagnostics and translate its classified reason. The Session page adds one next step where the reason has one, such as checking the model shown on the Session page and the Session's model provider; lists show the reason alone, with the next step in its tooltip. A next step must hold for every Session kind and deployment: a self-hosted Session never uses the default model provider, and an E2B deployment has no nodes. Provider observations in Settings show the reason alone. Core never returns the Harness's or provider's own message, so an unclassified failure says so. The console never infers a cause from raw logs. Unavailable or mismatched diagnostics offer an explicit read retry; refreshing does not replay execution. Trace Timing keeps each Item's Core receipt interval separate from public Turn times and native tool duration. Historical missing timestamps stay unknown, negative clock intervals stay missing, and bounded response truncation remains visible.
- **Executor credentials.** Core issues executor credentials; the console does so with the deployment's Core key. A Session page whose environment is self-hosted has an Executor credentials section: issue a credential (shown once as one line of JSON, to copy or download, never stored), rotate it (the old one stops working immediately) or revoke it (the executor disconnects; installed Runtime state and workspace contents are not deleted). The file lets one executor connect for that environment only; it cannot call the Agents API.
-- **Default provider observations.** Each configured harness offers Usage details for Core's last successful use and any newer classified provider error. Missing records remain unknown; an error at or before the last success is no longer actionable. These are best-effort observations, not readiness checks. Failed refreshes qualify retained records, and replacing the provider starts a new observation history.
+- **Default provider observations.** Each configured Harness offers Usage details for Core's last successful use and any newer classified provider error. Missing records remain unknown; an error at or before the last success is no longer actionable. These are best-effort observations, not readiness checks. Failed refreshes qualify retained records, and replacing the provider starts a new observation history.
- **Host connection.** Core's connection observation and credential metadata share one five-second read while visible. Never connected, connected, disconnected, bound credential revoked, and unknown are distinct; a recent heartbeat alone never proves connectivity. Only a fresh connected read marks Host connected. Stale or failed reads withhold completion. Recovery rotates the bound key, stops the installed daemon, replaces the host credential file and starts the daemon again.
- **Connect a host.** The Linux/macOS and PowerShell commands come from Core's installation read for the Session's environment; the console shows them as they are, with a link to the native installation guide, and never builds one itself. A command downloads the matching installer, installs the chosen Harnesses, starts the daemon and checks its connection. Its authorization expires after 30 minutes; the console reads a fresh one every 20 minutes, and says the command is unavailable when Core has none. No model readiness is implied. Rotating a credential requires stopping the installed daemon, replacing the configured file and starting that same daemon again. A disconnected daemon may still be running; `start` alone does not replace it.
- **Typed write errors.** Known Core codes use shared bilingual copy and safe typed details. Exact Core field paths attach definite refusals to the relevant input. Unknown codes retain Core's fallback message; uncertain write outcomes stay form-level and are never retried automatically.
diff --git a/apps/web/e2e/diagnostics.spec.ts b/apps/web/e2e/diagnostics.spec.ts
index 8c48c9613..2b9c0c528 100644
--- a/apps/web/e2e/diagnostics.spec.ts
+++ b/apps/web/e2e/diagnostics.spec.ts
@@ -54,7 +54,7 @@ test("shows diagnostics failure honestly and can retry in Chinese", async ({ pag
failed = false;
await page.getByLabel("Session 信息").getByRole("button", { name: "失败详情", exact: true }).click();
await page.getByLabel("Session 信息").getByRole("button", { name: "重试诊断读取", exact: true }).click();
- await expect(page.getByLabel("Session 信息")).toContainText("模型服务认证失败");
+ await expect(page.getByLabel("Session 信息")).toContainText("模型提供商认证失败");
expect(await writes(request)).toEqual([]);
});
diff --git a/apps/web/e2e/nodes.spec.ts b/apps/web/e2e/nodes.spec.ts
index 836049f0d..9c2a4a08f 100644
--- a/apps/web/e2e/nodes.spec.ts
+++ b/apps/web/e2e/nodes.spec.ts
@@ -247,7 +247,7 @@ test("saves E2B without opening Add node, as it has no machines", async ({ page,
await expect(page.getByLabel("E2B provider")).toHaveValue("sandbase");
await expect(page.getByLabel("Sandbox API URL")).toHaveValue("https://sandbox.sandbase.ai");
await expect(page.getByLabel("Sandbox data-plane domain")).toHaveValue("sandbox.sandbase.ai");
- const keyConsole = page.getByRole("link", { name: "Console → API Keys" });
+ const keyConsole = page.getByRole("link", { name: "Console → API keys" });
await expect(keyConsole.locator("..")).toHaveClass(/field-label-row/);
await expect(keyConsole).toHaveCSS("font-size", "11px");
await expect(keyConsole).toHaveAttribute("href", "https://www.sandbase.ai/console/keys");
@@ -272,7 +272,7 @@ test("uses the official E2B preset and clears a selected build when the key chan
await page.getByLabel("E2B provider").selectOption("official");
await expect(page.getByLabel("Sandbox API URL")).toHaveValue("https://api.e2b.app");
await expect(page.getByLabel("Sandbox data-plane domain")).toHaveValue("e2b.app");
- const keyConsole = page.getByRole("link", { name: "Console → API Keys" });
+ const keyConsole = page.getByRole("link", { name: "Console → API keys" });
await expect(keyConsole).toHaveAttribute("href", "https://e2b.dev/dashboard?tab=api-keys");
await page.getByLabel("Sandbox API URL").fill("https://custom.e2b.app");
await expect(keyConsole).toHaveCount(0);
diff --git a/apps/web/e2e/provider-observations.spec.ts b/apps/web/e2e/provider-observations.spec.ts
index b6700897c..03bf103c1 100644
--- a/apps/web/e2e/provider-observations.spec.ts
+++ b/apps/web/e2e/provider-observations.spec.ts
@@ -18,7 +18,7 @@ test("default provider observations are optional details and recover only on Cor
await expect(card).not.toContainText("Last successful use");
await card.getByRole("button", { name: "Usage details", exact: true }).click();
const details = page.getByRole("dialog", { name: "Codex usage details", exact: true });
- await expect(details).toContainText("Not recorded");
+ await expect(details).toContainText("Not recorded yet");
await details.getByRole("button", { name: "Close dialog", exact: true }).click();
observation = { last_used_at: null, last_error_code: "authentication_error", last_error_at: "2026-09-28T08:01:00Z" };
await page.getByRole("button", { name: "Refresh system configuration", exact: true }).click();
diff --git a/apps/web/e2e/resources.spec.ts b/apps/web/e2e/resources.spec.ts
index d66e89ab7..8ba0c99a1 100644
--- a/apps/web/e2e/resources.spec.ts
+++ b/apps/web/e2e/resources.spec.ts
@@ -45,7 +45,7 @@ test("reads an Agent saved with a model provider and no harness, without its key
test("explains on a fresh install that applications create resources through the Agents API", async ({ page, request }) => {
await openConsole(page, request, "agents", { fresh: true });
- for (const [view, title, section] of [["agents", "No Agents yet", "agents"], ["templates", "No Environment Templates yet", "environment-templates"], ["skills", "No Skills yet", "skills"], ["files", "No files yet", "source-files"], ["vaults", "No Vaults yet", "vaults"]]) {
+ for (const [view, title, section] of [["agents", "No Agents yet", "agents"], ["templates", "No Environment templates yet", "environment-templates"], ["skills", "No Skills yet", "skills"], ["files", "No files yet", "source-files"], ["vaults", "No Vaults yet", "vaults"]]) {
await page.goto(`/#${view}`);
await expect(page.getByText(title)).toBeVisible();
await expect(page.getByText(/through the Agents API\.$/)).toBeVisible();
diff --git a/apps/web/src/features/sandbox/NodeDetail.tsx b/apps/web/src/features/sandbox/NodeDetail.tsx
index 3b53da0f3..ca3429095 100644
--- a/apps/web/src/features/sandbox/NodeDetail.tsx
+++ b/apps/web/src/features/sandbox/NodeDetail.tsx
@@ -126,7 +126,7 @@ export function NodeDetail({ node, allocations, coreUrl, targetGeneration, stale
- ) : }
+ ) : }
>
);
diff --git a/apps/web/src/features/sandbox/SandboxManagerView.tsx b/apps/web/src/features/sandbox/SandboxManagerView.tsx
index bcf272326..c00069381 100644
--- a/apps/web/src/features/sandbox/SandboxManagerView.tsx
+++ b/apps/web/src/features/sandbox/SandboxManagerView.tsx
@@ -232,7 +232,7 @@ function SandboxManager({ consoleConfig }: { consoleConfig: SandboxConsoleConfig
{hostedNodes && nodes.some((node) => node.active > node.max_active || node.retained > node.max_retained) ?
{t("Current usage exceeds a saved limit. Existing sandboxes are preserved; new placements wait for capacity.")}
: null}
{hostedNodes ? nodes.length
? navigate("nodes", { id: node.id })} onEdit={(node) => setEditId(node.id)} onRemove={askRemove} />
- : nodesConfirmed ? : null
+ : nodesConfirmed ? : null
: null}
> : null}
diff --git a/apps/web/src/features/sandbox/SandboxSetupWizard.tsx b/apps/web/src/features/sandbox/SandboxSetupWizard.tsx
index b61508872..4fdf6d6df 100644
--- a/apps/web/src/features/sandbox/SandboxSetupWizard.tsx
+++ b/apps/web/src/features/sandbox/SandboxSetupWizard.tsx
@@ -304,7 +304,7 @@ export function SandboxSetupWizard({ coreUrl, expectedGeneration, current, disab
- {t("Console → API Keys")}
+ {t("Console → API keys")}
) : null}>
{ if (editing) { setApiKey(event.target.value); setTemplates([]); setBuilds([]); } else changeConnection(event.target.value, apiURL, domain); setReplacementRequested(Boolean(event.target.value.trim())); setFieldRejection(null); }} />
diff --git a/apps/web/src/features/sessions/executor-credential-ownership.test.tsx b/apps/web/src/features/sessions/executor-credential-ownership.test.tsx
index 4295269c9..92034e579 100644
--- a/apps/web/src/features/sessions/executor-credential-ownership.test.tsx
+++ b/apps/web/src/features/sessions/executor-credential-ownership.test.tsx
@@ -76,7 +76,7 @@ describe("executor credential display ownership", () => {
it("uses the same row ownership and recovery wording in Chinese", async () => {
await i18n.changeLanguage("zh-CN");
const html = render(read(true));
- expect(html).toContain("绑定凭证");
+ expect(html).toContain("绑定凭据");
expect(html.match(/aria-label="轮换以恢复"/g)).toHaveLength(1);
expect(html).toContain("刷新 · 主机连接");
expect(html).toContain('data-host-connected="false"');
diff --git a/apps/web/src/features/sessions/session-diagnostics.test.tsx b/apps/web/src/features/sessions/session-diagnostics.test.tsx
index 330fd1d41..b629d8479 100644
--- a/apps/web/src/features/sessions/session-diagnostics.test.tsx
+++ b/apps/web/src/features/sessions/session-diagnostics.test.tsx
@@ -34,7 +34,7 @@ describe("Core diagnostics in the console", () => {
expect(render("session", sessionData)).toContain("Check the API key of the Session's model provider.");
expect(render("turn", turnData)).toContain("Check the API key of the Session's model provider.");
await i18n.changeLanguage("zh-CN");
- expect(render("session", sessionData)).toContain("模型服务认证失败");
+ expect(render("session", sessionData)).toContain("模型提供商认证失败");
expect(render("turn", turnData)).not.toContain("PRIVATE_NATIVE_SENTINEL");
});
@@ -68,7 +68,7 @@ describe("Core diagnostics in the console", () => {
expect(diagnosticFailure({ code: "connection_failed", params: { http_status: 502 }, failed_at: null }, t)).toContain("HTTP 502. Check the Base URL of the Session's model provider.");
expect(diagnosticFailure({ code: "runtime_unavailable", params: {}, failed_at: null }, t)).toBe("The Runtime is unavailable. Retry later. For a self-hosted Session, check Host connection on the Session page; for a hosted sandbox Session, check Settings → Sandbox and scheduling.");
expect(diagnosticFailure({ code: "harness_error", params: {}, failed_at: null }, t)).toContain("Core does not show the Harness's own message");
- expect(diagnosticFailure({ code: "invalid_request", params: {}, failed_at: null }, i18n.getFixedT("zh-CN", "diagnostics"))).toBe("模型服务拒绝了请求。请检查模型和参数,先看 Session 页显示的模型。Session 及其保存的 Agent 都未设置模型服务时,托管沙箱 Session 使用“设置 → 模型与凭据”中的默认配置。");
+ expect(diagnosticFailure({ code: "invalid_request", params: {}, failed_at: null }, i18n.getFixedT("zh-CN", "diagnostics"))).toBe("模型提供商拒绝了请求。请检查模型和参数,先看 Session 页显示的模型。Session 及其保存的 Agent 都未设置模型提供商时,托管沙箱 Session 使用“设置 → 模型与凭据”中的默认配置。");
// Lists show the reason alone; the next step stays in the title.
const row = render("session", { ...sessionData, failure: { ...sessionData.failure!, code: "invalid_request" } }, false, true);
expect(row).toContain(">The model provider rejected the request.<");
diff --git a/apps/web/src/features/vaults/VaultsPage.tsx b/apps/web/src/features/vaults/VaultsPage.tsx
index 8ff87433f..f7785a874 100644
--- a/apps/web/src/features/vaults/VaultsPage.tsx
+++ b/apps/web/src/features/vaults/VaultsPage.tsx
@@ -11,7 +11,6 @@ import { useConsoleNavigation } from "../../lib/console-navigation";
import { useDeleteFlow } from "../../lib/delete-flow";
import { formatDateTime } from "../../lib/format";
import { CreatorCell, CreatorHeading, forgetCreators, ProjectFilter, ProjectName, projectClient, readAllPages, useCreators, useProjectCollection, useProjects, type Owned } from "../../lib/projects";
-import { vaultName } from "./vault-catalog";
import "./vaults.css";
import { collections } from "../../lib/queries";
import { DetailSkeleton, TableSkeleton } from "../../components/Skeleton";
@@ -90,7 +89,7 @@ function VaultsList() {
{rows.map((row) => {
const vault = row.value;
- const name = vaultName(vault);
+ const name = vault.name ?? t("unnamed");
const open = () => navigate("vaults", { project: row.project.id, id: vault.id });
return (
@@ -138,7 +137,7 @@ function VaultsList() {
onConfirm={() => void remove.confirm()}
onClose={remove.cancel}
>
- {remove.target ? t("deleteVaultPrompt", { name: vaultName(remove.target.value) }) : null}
+ {remove.target ? t("deleteVaultPrompt", { name: remove.target.value.name ?? t("unnamed") }) : null}
);
@@ -180,7 +179,7 @@ function VaultDetail({ projectId, vaultId }: { projectId: string; vaultId: strin
// Detail reads are not polled: each failed read was asked for and is reported.
useFailureToast(vault !== null ? failure : null, t("refreshFailed"), "vault-refresh", read.errorUpdatedAt);
useFailureToast(credentialsRead.data ? credentialsFailure : null, t("refreshFailed"), "vault-credentials-refresh", credentialsRead.errorUpdatedAt);
- const name = vault ? vaultName(vault) : vaultId;
+ const name = vault ? vault.name ?? t("unnamed") : vaultId;
return (
{
- it("loads every Vault and Credential page", async () => {
- const listVaults = vi.fn(async ({ after }: { after?: string }) => after
- ? { object: "list" as const, data: [vaultB], has_more: false, first_id: vaultB.id, last_id: vaultB.id }
- : { object: "list" as const, data: [vaultA], has_more: true, first_id: vaultA.id, last_id: vaultA.id });
- const listVaultCredentials = vi.fn(async (vaultId: string) => ({
- object: "list" as const,
- data: vaultId === vaultA.id ? [credentialA] : [credentialB],
- has_more: false,
- first_id: vaultId === vaultA.id ? credentialA.id : credentialB.id,
- last_id: vaultId === vaultA.id ? credentialA.id : credentialB.id,
- }));
- const core = { listVaults, listVaultCredentials } as unknown as ProjectClient;
-
- await expect(loadVaultCatalog(core)).resolves.toEqual({
- vaults: [vaultA, vaultB],
- credentials: [credentialA, credentialB],
- });
- expect(listVaults).toHaveBeenCalledTimes(2);
- expect(listVaultCredentials).toHaveBeenCalledTimes(2);
- });
-
- it("derives sorted unique owning Vaults from explicit exact-URL Credentials", () => {
- const catalog: VaultCatalog = { vaults: [vaultB, vaultA], credentials: [credentialB, credentialA] };
- const plan = deriveSessionVaultPlan(agent([
- mcp("b", credentialB.auth.mcp_server_url, credentialB.id),
- mcp("a", credentialA.auth.mcp_server_url, credentialA.id),
- mcp("a-again", credentialA.auth.mcp_server_url, credentialA.id),
- ]), catalog);
-
- expect(plan.blocker).toBeNull();
- expect(plan.vaultIds).toEqual([vaultA.id, vaultB.id]);
- expect(plan.requiredVaultIds).toEqual([vaultA.id, vaultB.id]);
- expect(plan.bindings.map((binding) => binding.serverLabel)).toEqual(["b", "a", "a-again"]);
- expect(plan.resolutions.map((resolution) => resolution.kind)).toEqual(["explicit", "explicit", "explicit"]);
- expect(matchingCredentials(catalog, credentialA.auth.mcp_server_url)).toEqual([credentialA]);
- });
-
- it("blocks missing catalogs and URL mismatches", () => {
- const credentialed = agent([mcp("a", credentialA.auth.mcp_server_url, credentialA.id)]);
- expect(deriveSessionVaultPlan(credentialed, null).blocker).toContain("not fully loaded");
- expect(deriveSessionVaultPlan(agent([mcp("a", "https://wrong.example/tools", credentialA.id)]), {
- vaults: [vaultA], credentials: [credentialA],
- }).blocker).toContain("URL-mismatched");
- });
-
- it("previews anonymous, unique implicit, ambiguous, and stale manual Vault selection", () => {
- const anonymous = agent([mcp("docs", credentialA.auth.mcp_server_url)]);
- const catalog: VaultCatalog = {
- vaults: [vaultA, vaultB],
- credentials: [credentialA, credentialB],
- };
-
- expect(deriveSessionVaultPlan(anonymous, catalog)).toMatchObject({
- blocker: null,
- vaultIds: [],
- requiredVaultIds: [],
- resolutions: [{ kind: "anonymous", serverLabel: "docs" }],
- });
- expect(deriveSessionVaultPlan(anonymous, catalog, [vaultA.id])).toMatchObject({
- blocker: null,
- vaultIds: [vaultA.id],
- requiredVaultIds: [],
- resolutions: [{
- kind: "implicit",
- serverLabel: "docs",
- credential: credentialA,
- vault: vaultA,
- }],
- });
-
- const duplicate: VaultCredential = {
- ...credentialB,
- auth: { type: "static_bearer", mcp_server_url: credentialA.auth.mcp_server_url },
- };
- const ambiguous = deriveSessionVaultPlan(anonymous, {
- vaults: [vaultA, vaultB],
- credentials: [credentialA, duplicate],
- }, [vaultA.id, vaultB.id]);
- expect(ambiguous.blocker).toContain("multiple Credentials");
- expect(ambiguous.vaultIds).toEqual([vaultA.id, vaultB.id]);
-
- expect(deriveSessionVaultPlan(anonymous, catalog, ["33333333-3333-4333-8333-333333333333"]).blocker)
- .toContain("no longer available");
- });
-});
diff --git a/apps/web/src/features/vaults/vault-catalog.ts b/apps/web/src/features/vaults/vault-catalog.ts
deleted file mode 100644
index 97bc3cf4c..000000000
--- a/apps/web/src/features/vaults/vault-catalog.ts
+++ /dev/null
@@ -1,253 +0,0 @@
-import type {
- SavedAgent,
- Vault,
- VaultCredential,
-} from "@oac/agents-client";
-
-import type { ProjectClient } from "../../lib/projects";
-import { listAllCollectionPages } from "../../lib/collection-pagination";
-import i18n from "../../i18n";
-
-const tv = (key: string, options?: Record) => i18n.t(key as never, { ns: "vaults", ...options });
-
-export interface VaultCatalog {
- vaults: Vault[];
- credentials: VaultCredential[];
-}
-
-export interface SessionCredentialBinding {
- credential: VaultCredential;
- selection: "explicit" | "implicit";
- serverLabel: string;
- vault: Vault;
-}
-
-export interface SessionMcpResolution {
- credential?: VaultCredential;
- kind: "anonymous" | "explicit" | "implicit";
- serverLabel: string;
- serverURL: string;
- vault?: Vault;
-}
-
-export interface SessionVaultPlan {
- bindings: SessionCredentialBinding[];
- blocker: string | null;
- requiredVaultIds: string[];
- resolutions: SessionMcpResolution[];
- vaultIds: string[];
-}
-
-const CREDENTIAL_READ_CONCURRENCY = 4;
-
-export async function loadVaultCatalog(core: Pick, signal?: AbortSignal): Promise {
- const vaults = await listAllCollectionPages(
- (options) => core.listVaults(options),
- signal,
- );
- const credentialsByVault = new Map();
- let nextIndex = 0;
-
- const worker = async () => {
- while (nextIndex < vaults.length) {
- signal?.throwIfAborted();
- const vault = vaults[nextIndex];
- nextIndex += 1;
- if (!vault) return;
- const credentials = await listAllCollectionPages(
- (options) => core.listVaultCredentials(vault.id, options),
- signal,
- );
- credentialsByVault.set(vault.id, credentials);
- }
- };
-
- await Promise.all(
- Array.from({ length: Math.min(CREDENTIAL_READ_CONCURRENCY, vaults.length) }, () => worker()),
- );
- signal?.throwIfAborted();
- return {
- vaults,
- credentials: vaults.flatMap((vault) => credentialsByVault.get(vault.id) ?? []),
- };
-}
-
-function record(value: unknown): Record | null {
- return value !== null && typeof value === "object" && !Array.isArray(value)
- ? value as Record
- : null;
-}
-
-function savedMCPTools(agent: SavedAgent): Array<{
- credentialId: string | null;
- serverLabel: string;
- serverURL: string;
-}> {
- const tools: Array<{ credentialId: string | null; serverLabel: string; serverURL: string }> = [];
- for (const rawTool of agent.tools) {
- const tool = record(rawTool);
- const transport = record(tool?.transport);
- if (
- tool?.type !== "mcp" ||
- typeof tool.server_label !== "string" ||
- transport?.type !== "http" ||
- typeof transport.server_url !== "string"
- ) continue;
- tools.push({
- credentialId: typeof tool.credential_id === "string" ? tool.credential_id : null,
- serverLabel: tool.server_label,
- serverURL: transport.server_url,
- });
- }
- return tools;
-}
-
-export function agentNeedsCredentialCatalog(agent: SavedAgent): boolean {
- return savedMCPTools(agent).some((tool) => tool.credentialId !== null);
-}
-
-export function deriveSessionVaultPlan(
- agent: SavedAgent,
- catalog: VaultCatalog | null,
- manualVaultIds: readonly string[] = [],
-): SessionVaultPlan {
- const tools = savedMCPTools(agent);
- const credentialed = tools.filter((tool) => tool.credentialId !== null);
- const empty = (blocker: string | null): SessionVaultPlan => ({
- bindings: [],
- blocker,
- requiredVaultIds: [],
- resolutions: [],
- vaultIds: [],
- });
- if (new Set(manualVaultIds).size !== manualVaultIds.length) {
- return empty(tv("errors.uniqueAttachments"));
- }
- if (!catalog && (credentialed.length > 0 || manualVaultIds.length > 0)) {
- return {
- ...empty(tv("errors.catalogIncomplete")),
- blocker: tv("errors.catalogIncomplete"),
- };
- }
-
- if (!catalog) {
- return {
- ...empty(null),
- resolutions: tools.map((tool) => ({
- kind: "anonymous",
- serverLabel: tool.serverLabel,
- serverURL: tool.serverURL,
- })),
- };
- }
-
- const credentials = new Map(catalog.credentials.map((credential) => [credential.id, credential]));
- const vaults = new Map(catalog.vaults.map((vault) => [vault.id, vault]));
- const bindings: SessionCredentialBinding[] = [];
- const requiredVaultIds = new Set();
- for (const vaultId of manualVaultIds) {
- if (!vaults.has(vaultId)) {
- return empty(tv("errors.vaultMissing"));
- }
- }
- for (const tool of credentialed) {
- const credential = credentials.get(tool.credentialId as string);
- if (!credential || credential.auth.mcp_server_url !== tool.serverURL) {
- return {
- bindings: [],
- blocker: tv("errors.credentialMismatch", { server: tool.serverLabel }),
- requiredVaultIds: [],
- resolutions: [],
- vaultIds: [],
- };
- }
- const vault = vaults.get(credential.vault_id);
- if (!vault) {
- return {
- bindings: [],
- blocker: tv("errors.credentialVaultMissing", { server: tool.serverLabel }),
- requiredVaultIds: [],
- resolutions: [],
- vaultIds: [],
- };
- }
- requiredVaultIds.add(vault.id);
- bindings.push({ credential, selection: "explicit", serverLabel: tool.serverLabel, vault });
- }
-
- const vaultIds = [...new Set([...manualVaultIds, ...requiredVaultIds])].sort();
- const attached = new Set(vaultIds);
- const resolutions: SessionMcpResolution[] = [];
- const explicitByLabel = new Map(bindings.map((binding) => [binding.serverLabel, binding]));
- for (const tool of tools) {
- const explicit = explicitByLabel.get(tool.serverLabel);
- if (explicit) {
- resolutions.push({
- credential: explicit.credential,
- kind: "explicit",
- serverLabel: tool.serverLabel,
- serverURL: tool.serverURL,
- vault: explicit.vault,
- });
- continue;
- }
- const matches = catalog.credentials.filter((credential) => (
- attached.has(credential.vault_id) && credential.auth.mcp_server_url === tool.serverURL
- ));
- if (matches.length > 1) {
- return {
- bindings,
- blocker: tv("errors.multipleCredentials", { server: tool.serverLabel }),
- requiredVaultIds: [...requiredVaultIds].sort(),
- resolutions,
- vaultIds,
- };
- }
- const credential = matches[0];
- if (!credential) {
- resolutions.push({ kind: "anonymous", serverLabel: tool.serverLabel, serverURL: tool.serverURL });
- continue;
- }
- const vault = vaults.get(credential.vault_id);
- if (!vault) {
- return {
- bindings,
- blocker: tv("errors.matchedVaultMissing", { server: tool.serverLabel }),
- requiredVaultIds: [...requiredVaultIds].sort(),
- resolutions,
- vaultIds,
- };
- }
- const binding: SessionCredentialBinding = {
- credential,
- selection: "implicit",
- serverLabel: tool.serverLabel,
- vault,
- };
- bindings.push(binding);
- resolutions.push({
- credential,
- kind: "implicit",
- serverLabel: tool.serverLabel,
- serverURL: tool.serverURL,
- vault,
- });
- }
-
- return {
- bindings,
- blocker: null,
- requiredVaultIds: [...requiredVaultIds].sort(),
- resolutions,
- vaultIds,
- };
-}
-
-export function vaultName(vault: Vault): string {
- return vault.name ?? tv("unnamed");
-}
-
-export function matchingCredentials(catalog: VaultCatalog | null, serverURL: string): VaultCredential[] {
- if (!catalog) return [];
- return catalog.credentials.filter((credential) => credential.auth.mcp_server_url === serverURL);
-}
diff --git a/apps/web/src/i18n/README.md b/apps/web/src/i18n/README.md
index 51cda8d31..90e6c40c3 100644
--- a/apps/web/src/i18n/README.md
+++ b/apps/web/src/i18n/README.md
@@ -4,7 +4,7 @@ The console uses `i18next` and `react-i18next`. English is the fallback language
Translations are split by namespace, registered in `resources.ts`:
-- `locales/en/*.ts` and `locales/zh-CN/*.ts` hold one file per feature namespace: `common` (reusable actions and labels, with the Core error messages of `core-errors.ts` nested inside it), `navigation` (the shell), `pages`, `agents`, `templates`, `vaults`, `files`, `skills`, `keys`, `sessions`, `diagnostics`, `dashboard`, `overview`, `metrics`, `system`, `sandbox-navigation` (registered as `sandboxNavigation`) and `onboarding`.
+- `locales/en/*.ts` and `locales/zh-CN/*.ts` hold one file per feature namespace: `common` (reusable actions and labels, with the Core error messages of `core-errors.ts` nested inside it), `navigation` (the shell), `pages`, `agents`, `templates`, `vaults`, `files`, `skills`, `keys`, `sessions`, `diagnostics`, `overview`, `metrics`, `system`, `onboarding`, `sandbox-navigation` (registered as `sandboxNavigation`), `request-log` (`requestLog`) and `workspace-storage` (`workspaceStorage`).
- `sandbox` and `firstRun` use English text as keys in `locales/zh-CN/sandbox.ts` and `locales/zh-CN/first-run.ts`; `resources.ts` projects those keys into the English resources. Keep these keys unchanged when moving copy.
Add a namespace when a feature grows beyond page-level labels; do not grow one application-wide translation object.
diff --git a/apps/web/src/i18n/i18n.test.tsx b/apps/web/src/i18n/i18n.test.tsx
index 59595904b..3c1f91d93 100644
--- a/apps/web/src/i18n/i18n.test.tsx
+++ b/apps/web/src/i18n/i18n.test.tsx
@@ -52,8 +52,8 @@ describe("Web internationalization", () => {
it("does not fall back to English plural variants in Chinese", async () => {
await i18n.changeLanguage("zh-CN");
- expect(i18n.t("turns.linkedItems", { ns: "sessions", count: 1 })).toBe("已关联 1 个条目");
+ expect(i18n.t("turns.linkedItems", { ns: "sessions", count: 1 })).toBe("已关联 1 个 Item");
expect(i18n.t("turns.observed", { ns: "sessions", count: 2 })).toBe("已观测 2 个 Turn");
- expect(i18n.t("turns.unassociated", { ns: "sessions", count: 2 })).toBe("有 2 个条目尚未关联到已观测 Turn。");
+ expect(i18n.t("turns.unassociated", { ns: "sessions", count: 2 })).toBe("有 2 个 Item 尚未关联到已观测 Turn。");
});
});
diff --git a/apps/web/src/i18n/locales/en/agents.ts b/apps/web/src/i18n/locales/en/agents.ts
index 8ad49e59d..5f0add8cc 100644
--- a/apps/web/src/i18n/locales/en/agents.ts
+++ b/apps/web/src/i18n/locales/en/agents.ts
@@ -1,21 +1,11 @@
export const agents = {
- loading: "Loading Agents", requestFailed: "The OpenAgentCore request failed.",
- searchPlaceholder: "Search name, model, or ID…", filtersLabel: "Agent filters", searchLabel: "Search Agents", refreshLabel: "Refresh Agents",
- loadFailed: "Couldn’t load Agents", refreshFailed: "Couldn’t refresh Agents", staleDescription: "The last loaded Agent configurations remain available.",
- loadDescription: "The Web could not read Agent configurations from the connected OpenAgentCore.", connectionHint: "Check the OpenAgentCore connection in the sidebar, then retry.",
- openFailed: "Couldn’t open the latest Agent", retry: "Retry", requestFailure: "Request failed",
- errors: {
- retrievalUnavailable: "Agent retrieval is unavailable for this OpenAgentCore connection.", interrupted: "The Agent request was interrupted by a connection change.", differentRetrieved: "OpenAgentCore returned a different Agent than the one requested.",
- updateUnavailable: "Agent updates are unavailable for this OpenAgentCore connection.", updateInterrupted: "The Agent update was interrupted by a connection change.", differentUpdated: "OpenAgentCore returned a different Agent than the one updated.", deleteUnavailable: "Delete is unavailable for this OpenAgentCore connection.",
- modelRequired: "Enter a model ID.", nameTooLong: "Name must be at most 128 characters.", metadataJson: "Metadata must be valid JSON.", metadataObject: "Metadata must be a JSON object.", metadataStrings: "Every metadata value must be a string.", metadataCount: "Agent metadata supports at most 16 pairs.", metadataLength: "Metadata keys must be at most 64 characters and values at most 512 characters.",
- reasoningDefault: "Current Core Sessions require both reasoning fields to use Core default.", serviceTier: "Current Core Sessions support service tier auto only.", textFormat: "Current Core Sessions support text format only.", verbosity: "Low and high verbosity require a discovered compatible Codex model; use medium for this Web flow.",
- readOnlyTools: "Tools cannot be changed while this Agent contains read-only saved tool definitions.", functionName: "Every Function needs a non-empty name.", functionNameLength: "Function names must be at most 512 UTF-8 bytes.", functionUnique: "Function names must be unique.", functionJson: "Function {{name}} parameters must be valid JSON.", functionSchema: "Function {{name}} parameters must be a JSON object schema.",
- mcpLabel: "Every MCP server needs a non-empty label.", mcpUnique: "MCP server labels must be unique.", mcpUrl: "MCP server {{name}} needs a valid anonymous HTTP(S) URL.", credentialMissing: "MCP server {{name}} references a Credential that is not available in the current catalog.", credentialUrl: "MCP server {{name}} must use the selected Credential's exact URL.", functionCount: "At most 64 Functions can be configured.",
- },
+ loading: "Loading Agents",
+ searchPlaceholder: "Search name, model, or ID…", refreshLabel: "Refresh Agents",
+ loadFailed: "Couldn’t load Agents", refreshFailed: "Couldn’t refresh Agents", retry: "Retry",
view: {
filterLabel: "Filter Agents",
searchPlaceholder: "Search name, model or ID",
- columns: { agent: "Agent", model: "Model", harness: "Harness", tools: "Tools", sessions: "Sessions", tokens: "Tokens", lastActive: "Last active", updated: "Updated", actions: "Actions" },
+ columns: { agent: "Agent", model: "Model", harness: "Harness", tools: "Tools", sessions: "Sessions", tokens: "Tokens", lastActive: "Last active", actions: "Actions" },
open: "Open {{name}}",
coreDefault: "Core default",
back: "Back",
@@ -63,31 +53,10 @@ export const agents = {
delete: "Delete",
},
catalog: {
- listLabel: "Agents", create: "Create agent", untitled: "Untitled Agent", editLabel: "Edit {{name}} ({{id}})", opening: "Opening latest definition…",
- startLabel: "Start a Session with {{name}} ({{id}})", unavailable: "Unavailable", startSession: "Start Session", sessionUnavailable: "Session unavailable: {{reason}}",
- noMatch: "No matching Agents", noSaved: "No Agents yet", clearSearch: "Clear search",
- columns: { agent: "Agent", model: "Model", harness: "Harness", tools: "Tools", updated: "Updated", actions: "Actions" }, coreDefaultHarness: "Core default", copyId: "Copy Agent ID {{id}}", copied: "Copied", unavailableHelp: "Why a Session cannot start",
+ listLabel: "Agents", untitled: "Untitled Agent",
+ noMatch: "No matching Agents", noSaved: "No Agents yet",
},
details: {
- id: "ID", created: "Created", updated: "Updated", model: "Model", name: "Name", instructions: "Instructions", metadata: "Metadata", notSet: "Not set", none: "None",
- blocked: "This Agent can be saved, but the known Core Session profile cannot start it: {{reason}}", runtimeBoundary: "Saved advanced configuration is not runtime proof. Model, provider, host, tools, and conditional verbosity still require executor validation.", advanced: "Advanced configuration · read only", tools: "Tools", reasoning: "Reasoning", text: "Text", serviceTier: "Service tier", multiAgent: "Multi-agent", functionTool: "Function {{name}}", mcpTool: "{{auth}} service-origin HTTP MCP {{name}}", serviceOriginMcp: "service-origin HTTP MCP", vaultBearer: "Vault bearer", anonymous: "Anonymous", readOnly: "{{label}} · read only",
- deletePrompt: "Delete {{name}} from OpenAgentCore?", deleteBefore: "Delete", deleteAfter: "from OpenAgentCore?", exactId: "Exact Agent ID: {{id}}", exactIdLabel: "Exact Agent ID:", deleteWarning: "This removes the saved Agent only after Core confirms success. Existing Sessions keep their durable Agent snapshots.", deleteTitle: "Delete Agent?", cancel: "Cancel", deleting: "Deleting…",
- },
- savedTool: { malformed: "Malformed saved tool definition", toolSearch: "tool_search is saved-only and cannot run in a Session", programmatic: "programmatic_tool_calling is saved-only and cannot run in a Session", webSearchDisabled: "Disabled web_search is read-only in Web; Sessions keep search off", webSearchEnabled: "Enabled web_search is saved-only; Core does not run enabled search in a Session", deferred: "Deferred Function is saved-only", credentialedMcp: "Credentialed MCP is unresolved or URL-mismatched in the current Vault catalog", unsupportedFunction: "Unsupported Function tool definition", unsupportedMcp: "Unsupported MCP tool definition", unsupported: "Unsupported saved tool definition" },
- admission: {
- model: "a non-empty model is required", multiAgent: "multi-agent execution is not supported", reasoning: "explicit reasoning options are saved-only", serviceTier: "service tier must be auto", text: "text format must be text", malformedTool: "the saved tool configuration is not executable", malformedFunction: "the saved function tool is incomplete or malformed", deferred: "deferred functions are saved-only", functionName: "function names must be non-empty and at most 512 bytes", functionUnique: "function names must be unique", malformedMcp: "the saved MCP tool is incomplete or malformed", credential: "attached MCP credentials are unavailable in this Web Session flow", mcpUnique: "MCP server labels must be unique", malformedWebSearch: "the saved web_search tool is incomplete or malformed", enabledWebSearch: "web_search mode must be disabled because Core does not run enabled search", savedOnly: "{{type}} is saved-only", unsupportedTool: "the saved tool type is not executable", functionCount: "at most 64 function tools can execute", webSearchCount: "at most one web_search tool can execute", coreRequires: "Current Core Session admission requires {{reasons}}.", vaultUnavailable: "Session Vault attachment is unavailable. {{reason}}", managedMcp: "Managed hosted Sessions do not yet support MCP tools. Choose no Environment or self-hosted, or use a Function-only Agent.",
- },
- usage: {
- title: "Usage", rangeLabel: "Sessions created", ranges: { all: "All time", "7d": "Last 7 days", "30d": "Last 30 days" },
- help: "Usage is each Session's cumulative total as reported by Core; it is not split by day. A Session belongs to the range in which it was created, and all of its usage counts there.",
- caveat: "Data comes from cumulative Session usage reported by Core. It excludes unreported usage and is not a basis for billing.",
- reading: "Reading Sessions… {{formattedCount}} read", cancel: "Cancel", cancelled_one: "Stopped after reading {{formattedCount}} Session.", cancelled_other: "Stopped after reading {{formattedCount}} Sessions.", continue: "Continue", failed: "Couldn’t read Sessions.", retry: "Retry",
- large: "More than {{formattedCount}} Sessions: statistics may be slow. Try a shorter time range first.", largeShortest: "More than {{formattedCount}} Sessions: statistics may be slow.",
- sessions: "Sessions", tokens: "Tokens", coverage: "Coverage", lastActive: "Last active", noData: "No data", cardLabel: "Usage of {{name}}",
- coverageHelp: "Sessions whose usage Core reported, out of all Sessions in the range. Sessions without reported usage are left out of token totals, not counted as zero.",
- coverageDetail_one: "{{reported}} of {{formattedCount}} Session reported usage", coverageDetail_other: "{{reported}} of {{formattedCount}} Sessions reported usage",
- status: "Status", statuses: { in_progress: "In progress", requires_action: "Requires action", failed: "Failed", idle: "Idle", unknown: "Unrecognized" },
- tokenKinds: { input: "Input", output: "Output", total: "Total", cached: "Cached input", reasoning: "Reasoning" },
- other: { title: "Other Agents", help: "Sessions whose Agent ID is not in the current Agent list: the Agent was deleted, or the Session was created with an inline Agent configuration. Grouped by the raw Agent ID.", agentId: "Agent ID", missingId: "No Agent ID", showAll: "Show all {{formattedCount}}", showLess: "Show less" },
+ reasoning: "Reasoning",
},
} as const;
diff --git a/apps/web/src/i18n/locales/en/common.ts b/apps/web/src/i18n/locales/en/common.ts
index 12698b620..be3e54fb0 100644
--- a/apps/web/src/i18n/locales/en/common.ts
+++ b/apps/web/src/i18n/locales/en/common.ts
@@ -12,7 +12,7 @@ export const common = {
apiEmpty: {
agents: "Applications create Agents through the Agents API.",
sessions: "Applications start Sessions through the Agents API.",
- "environment-templates": "Applications create Environment Templates through the Agents API.",
+ "environment-templates": "Applications create Environment templates through the Agents API.",
skills: "Applications upload Skills through the Agents API.",
"source-files": "Applications upload files through the Agents API.",
vaults: "Applications create Vaults through the Agents API.",
@@ -71,6 +71,5 @@ export const common = {
loadedMore: "{{n}} loaded · more available",
noMatches: "No matches",
deleteUncertain: "The deletion was not confirmed; Core may or may not have removed it. The view was re-read, so check it before trying again.",
- noMatchesDescription: "Nothing matches the current search or filters.",
},
} as const;
diff --git a/apps/web/src/i18n/locales/en/dashboard.ts b/apps/web/src/i18n/locales/en/dashboard.ts
deleted file mode 100644
index 7bc2f2904..000000000
--- a/apps/web/src/i18n/locales/en/dashboard.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-export const dashboard = {
- trends: {
- title: "Resource trends", retained: "Retained samples · durable history", local: "Browser-local samples · reset on reload", source: "Runtime metric source", live: "Live", history: "History",
- historyStale: "History stale", historyLoading: "History · loading", durableResolution: "Durable · {{seconds}}s", liveRetrying: "Live · history retrying", liveUnavailable: "Live · history unavailable", liveLoading: "Live · loading history", staleRetrying: "Stale · retrying", liveInterval: "Live · {{seconds}}s",
- durableStatus: "{{status}}; {{count}} Runtime targets", retainedFailure: "Runtime sampling refresh failed; showing retained samples", samplingInterval: "Live Runtime sampling every {{seconds}} seconds",
- bucket: "bucket", buckets: "buckets", sample: "sample", samples: "samples", observations: "{{actual}}/{{expected}} observations", durableRange: "Runtime durable range", liveRange: "Runtime live range",
- refreshFailed: "Durable history refresh failed: {{error}}", notConfigured: "Durable history is not configured; Live samples remain available.", requestFailed: "Durable Runtime history request failed.",
- },
- charts: {
- collecting: "Collecting live samples", durableHistory: "durable history", live: "live", retainedBuckets: "retained buckets", liveSamples: "live samples", chartLabel: "{{title}} {{source}} chart",
- hideSeries: "Hide {{series}} series", showSeries: "Show {{series}} series", hide: "Hide {{series}}", show: "Show {{series}}", resetZoom: "Reset zoom",
- instructions: "Move the pointer over the plot for exact values. Drag horizontally to select and zoom a time range. Double-click or use Reset zoom to restore the full range. Click to pin a time. Use Left and Right arrows to move the pinned selection, and Escape to clear it.",
- pinned: "Pinned", hover: "Hover", unavailable: "Unavailable", allHidden: "All series hidden", sparse: "Sparse samples", showLegend: "Use the legend to show a series", sparseDetail: "{{count}} valid points · a line requires consecutive buckets", emptyDetail: "{{valid}}/2 valid points · {{count}} snapshots · no history is synthesized",
- table: { series: "Series", latest: "Latest value", missing: "Missing samples" }, runtime: "Runtime", usage: "usage", used: "used", configuredLimit: "configured limit", input: "input", output: "output", gridDurable: "Runtime durable-history charts", gridLive: "Runtime live-window charts",
- cpu: { title: "CPU usage", withoutData: "{{count}} runtime targets have no CPU data in this range", durable: "bucketed cumulative-delta utilization · durable history", live: "reported or cumulative-delta utilization · live window", empty: "No retained CPU samples" },
- memory: { title: "Memory usage", durable: "observed Sandbox aggregate / configured limit · durable history", live: "observed Sandbox working set / configured limit · live window", empty: "No retained observed memory samples" },
- active: { series: "active", sandboxTitle: "Active sandboxes", runtimeTitle: "Runtime active", sumDurable: "observed allocations per retained bucket · durable history", sumLive: "lifecycle state active allocations per snapshot · live window", binaryDurable: "observed allocation in retained bucket · 1 active / 0 inactive", binaryLive: "lifecycle state active · 1 active / 0 inactive", active: "Active", inactive: "Inactive", empty: "No retained active Sandbox samples" },
- tokens: { title: "Token throughput", durable: "canonical Session Usage deltas · durable history", live: "Session Usage deltas · missing usage excluded", empty: "No retained token samples", perMinute: "{{value}}/min" },
- },
-} as const;
diff --git a/apps/web/src/i18n/locales/en/diagnostics.ts b/apps/web/src/i18n/locales/en/diagnostics.ts
index 191df7ada..c907cd7c3 100644
--- a/apps/web/src/i18n/locales/en/diagnostics.ts
+++ b/apps/web/src/i18n/locales/en/diagnostics.ts
@@ -1,5 +1,5 @@
export const diagnostics = {
- providerUnknown: "Not recorded",
+ providerUnknown: "Not recorded yet",
providerStale: "Observation unconfirmed",
providerError: "Recent error",
providerDetails: "Usage details",
diff --git a/apps/web/src/i18n/locales/en/files.ts b/apps/web/src/i18n/locales/en/files.ts
index 0834384cb..8ddb6175e 100644
--- a/apps/web/src/i18n/locales/en/files.ts
+++ b/apps/web/src/i18n/locales/en/files.ts
@@ -1,6 +1,6 @@
export const files = {
title: "Files",
- help: "Files uploaded to this project through the Files API, including uploads made by API callers. Reference a File ID from an Environment Template to copy the file into the workspace of each new Session. User data files cannot be downloaded: Core rejects content requests for them.",
+ help: "Files uploaded to this project through the Files API, including uploads made by API callers. Reference a File ID from an Environment template to copy the file into the workspace of each new Session. User data files cannot be downloaded: Core rejects content requests for them.",
limits: "Uploads accept one file of at most 512 MiB with a 1–1024 byte name; empty files are allowed.",
actions: {
upload: "Upload file",
@@ -31,37 +31,20 @@ export const files = {
size: "Size",
created: "Created",
purpose: "Purpose",
- id: "File ID",
actions: "Actions",
exactBytes: "{{bytes}} bytes",
unrecognized: "Unrecognized file",
unrecognizedHelp: "Core returned metadata this console does not recognize, so only the File ID is shown.",
noMatchTitle: "No loaded files match",
- noMatchDescription: "The filter covers loaded files only. Load more files or clear the filter.",
- loadFailed: "Files could not be loaded",
- refreshFailed: "The list could not be refreshed: {{reason}}",
moreFailed: "More files could not be loaded: {{reason}}",
},
empty: {
title: "No files yet",
},
- unsupported: {
- title: "This Core does not list files",
- description: "The Files list returned HTTP {{status}}.",
- },
- upload: {
- uploading: "Uploading {{name}}…",
- uploaded: "Uploaded {{name}}",
- tooLarge: "{{name}} is larger than 512 MiB, the upload limit.",
- badName: "A file name must be 1 to 1024 UTF-8 bytes and cannot contain NUL characters.",
- rejected: "Core rejected the upload of {{name}}: {{reason}}",
- uncertain: "The upload of {{name}} may have reached Core. Refresh the list to check before uploading it again.",
- },
delete: {
prompt: "Delete {{name}}?",
- consequences: "Copies already placed in Session workspaces are not affected, and neither are existing Sessions. New Sessions from an Environment Template that references this File ID will fail.",
+ consequences: "Copies already placed in Session workspaces are not affected, and neither are existing Sessions. New Sessions from an Environment template that references this File ID will fail.",
deleted: "Deleted {{name}}",
- missing: "{{name}} was already deleted.",
rejected: "Core rejected the deletion: {{reason}}",
uncertain: "The deletion of {{name}} was not confirmed. Refresh the list to check before trying again.",
},
diff --git a/apps/web/src/i18n/locales/en/keys.ts b/apps/web/src/i18n/locales/en/keys.ts
index e2f0c74d3..3ab1758f0 100644
--- a/apps/web/src/i18n/locales/en/keys.ts
+++ b/apps/web/src/i18n/locales/en/keys.ts
@@ -152,7 +152,7 @@ export const keys = {
keysLabel: "Keys of {{name}}",
keysLoading: "Loading keys…",
keysFailed: "Keys could not be loaded.",
- noKeys: "This project has no keys",
+ noKeys: "No keys yet",
copyKeyId: "Copy key ID",
keyStatus: {
active: "Active",
@@ -185,7 +185,7 @@ export const keys = {
id: "ID",
key: "Key",
},
- empty: "No write operations",
+ empty: "No write operations yet",
loading: "Loading write operations…",
failed: "Write operations could not be loaded.",
moreFailed: "More operations could not be loaded.",
diff --git a/apps/web/src/i18n/locales/en/metrics.ts b/apps/web/src/i18n/locales/en/metrics.ts
index 4d1d1013a..4549db524 100644
--- a/apps/web/src/i18n/locales/en/metrics.ts
+++ b/apps/web/src/i18n/locales/en/metrics.ts
@@ -210,8 +210,8 @@ export const metrics = {
setUp: "Set up sandboxes",
runtimeSection: "Hosted Runtimes",
runtimeSectionDetail: "CPU, memory and token history of Core-managed hosted sandboxes. Other environments report no Runtime figures.",
- noRuntimeTitle: "No hosted sandboxes",
- noRuntimeDescription: "No Session uses a Core-managed hosted environment.",
+ noRuntimeTitle: "No hosted sandboxes yet",
+ noRuntimeDescription: "No Session uses a Core-managed hosted environment yet.",
runtimeLoading: "Loading Runtime observations…",
runtimeUnavailable: "Runtime observations are unavailable. {{reason}}",
runtimeStale: "Refresh failed; showing the previous observations. {{reason}}",
diff --git a/apps/web/src/i18n/locales/en/navigation.ts b/apps/web/src/i18n/locales/en/navigation.ts
index d285561a6..244124535 100644
--- a/apps/web/src/i18n/locales/en/navigation.ts
+++ b/apps/web/src/i18n/locales/en/navigation.ts
@@ -27,19 +27,11 @@ export const navigation = {
settings: {"sandbox": "Sandbox and scheduling", "storage": "Workspace storage", "models": "Models and credentials", "service": "Service and deployment"},
showGettingStarted: "Show Getting started",
skipToContent: "Skip to main content",
- configureCore: "Configure OpenAgentCore connection",
- coreApi: "Core API",
- coreState: "Core API {{state}}",
- coreConnecting: "Connecting…",
- coreReady: "API ready",
- coreFailed: "Failed",
theme: "Theme",
lightTheme: "Light theme",
darkTheme: "Dark theme",
language: "Language",
english: "English",
chinese: "简体中文",
- switchToChinese: "Switch to Simplified Chinese",
- switchToEnglish: "Switch to English",
appearanceSettings: "Language and appearance",
} as const;
diff --git a/apps/web/src/i18n/locales/en/overview.ts b/apps/web/src/i18n/locales/en/overview.ts
index 4ff49d88d..4af9fe201 100644
--- a/apps/web/src/i18n/locales/en/overview.ts
+++ b/apps/web/src/i18n/locales/en/overview.ts
@@ -81,7 +81,6 @@ export const overview = {
attentionSplit: "Last 24 hours: {{failed}} failed, {{waiting}} waiting for caller",
},
errors: {
- load: "The overview could not be loaded: {{reason}}",
summary: "The usage summary could not be loaded: {{reason}}",
projects: "Projects could not be loaded: {{reason}}",
},
@@ -149,14 +148,7 @@ export const overview = {
unavailable: "The usage summary is unavailable.",
loading: "Loading usage…",
emptyTitle: "No projects yet",
- assets: "Assets",
sessions: "Sessions",
- agents: "Agents",
- templates: "Templates",
- skills: "Skills",
- files: "Files",
- vaults: "Vaults",
- total: "Total",
running: "Running",
waiting: "Waiting for caller",
failed: "Failed",
@@ -181,10 +173,7 @@ export const overview = {
emptyOlder: "No Session active in the last 24 hours failed or is waiting for its caller. {{count}} older Sessions need attention in the Session log.", emptyOlder_one: "No Session active in the last 24 hours failed or is waiting for its caller. {{count}} older Session needs attention in the Session log.", emptyOlder_other: "No Session active in the last 24 hours failed or is waiting for its caller. {{count}} older Sessions need attention in the Session log.",
session: "Session",
status: "Status",
- reason: "Reason",
lastActive: "Last active",
- noError: "No error reported",
- requiredActions: "Required actions: {{count}}",
},
sessions: {
failed: "Failed",
diff --git a/apps/web/src/i18n/locales/en/pages.ts b/apps/web/src/i18n/locales/en/pages.ts
index 6881cfa99..0e29cbeaf 100644
--- a/apps/web/src/i18n/locales/en/pages.ts
+++ b/apps/web/src/i18n/locales/en/pages.ts
@@ -1,10 +1,6 @@
export const pages = {
- dashboard: {
- agents: "Agents", sessions: "Sessions", runtime: "Runtime", connectionSettings: "Connection settings",
- backend: { label: "OpenAgentCore backend is not ready. Open Docker startup guide", title: "OpenAgentCore backend is not ready", detail: "Web is running, but its local `/v1` proxy cannot reach a ready Core{{failure}}. Start the Docker backend, then test the connection.", openGuide: "Open startup guide", networkFailure: "network failure", collectionFailed: "Collection request failed." },
- },
agents: { title: "Agents", subtitle: "Saved Agents in each project, with their model, Harness, tools and usage." },
sessions: { title: "Sessions", subtitle: "Conversations", recover: "Recover durable state" },
- templates: { title: "Environment Templates", subtitle: "Reusable configuration for managed Sessions.", newTemplate: "New Template" },
- vaults: { title: "Vaults", subtitle: "Core-owned static bearer credentials for exact HTTPS MCP destinations.", refresh: "Refresh Vaults", create: "New Vault" },
+ templates: { title: "Environment templates", subtitle: "Reusable configuration for managed Sessions." },
+ vaults: { title: "Vaults", subtitle: "Core-owned static bearer credentials for exact HTTPS MCP destinations.", refresh: "Refresh Vaults" },
} as const;
diff --git a/apps/web/src/i18n/locales/en/sessions.ts b/apps/web/src/i18n/locales/en/sessions.ts
index 389572f7a..c6c37b977 100644
--- a/apps/web/src/i18n/locales/en/sessions.ts
+++ b/apps/web/src/i18n/locales/en/sessions.ts
@@ -18,7 +18,7 @@ export const sessions = {
sessionStatus: { all: "All", in_progress: "Running", requires_action: "Waiting for caller", failed: "Failed", idle: "Idle", other: "Other" },
environment: { none: "No environment", self_hosted: "Self-hosted", openai_hosted: "Hosted sandbox", other: "Other" },
harness: coreHarnessNames,
- usage: { input: "Input", output: "Output", total: "Total", cached: "Cached", reasoning: "Reasoning" },
+ usage: { input: "Input", output: "Output", total: "Total" },
log: {
title: "Session log",
help: "Sessions that callers created with their projects' API keys, most recent activity first. The console reads them and can delete idle ones; open a Session to read its conversation, trace and Turns.",
@@ -102,7 +102,6 @@ export const sessions = {
noItems: "No Items yet",
itemsFailed: "Items could not be loaded: {{reason}}",
turnsFailed: "Turns could not be loaded: {{reason}}",
- user: "User",
error: "Error",
unassociated: "Items without a Turn",
steps: "{{n}} steps",
@@ -120,7 +119,6 @@ export const sessions = {
output: "Output",
total: "Total tokens",
number: "Turn {{number}}",
- errorLabel: "Turn error",
none: "No Turns yet",
},
runtime: {
@@ -141,19 +139,18 @@ export const sessions = {
sample_timeout: "Sample timed out",
sample_unavailable: "Sample unavailable",
},
- observationFailed: "The runtime observation could not be loaded: {{reason}}",
- historyUnavailable: "Core keeps no runtime history for this Session.",
+ observationFailed: "The Runtime observation could not be loaded: {{reason}}",
+ historyUnavailable: "Core keeps no Runtime history for this Session.",
historyFailed: "Runtime history could not be loaded: {{reason}}",
- historyLoading: "Loading runtime history…",
+ historyLoading: "Loading Runtime history…",
},
executor: {
connection: {
title: "Host connection",
- help: "Core reports a connection only while the executor has current authority and a live connection. Last seen is the last recorded heartbeat and may lag. This does not confirm model or harness readiness.",
+ help: "Core reports a connection only while the executor has current authority and a live connection. Last seen is the last recorded heartbeat and may lag. This does not confirm model or Harness readiness.",
status: { never_enrolled: "Never connected", connected: "Connected", disconnected: "Disconnected", revoked: "Bound credential revoked", unknown: "Unknown" },
boundKey: "Bound credential",
lastSeen: "Last seen",
- notBound: "Not bound",
noHeartbeat: "No heartbeat recorded",
stale: "Refresh failed. Showing the last loaded binding; the current connection is unknown.",
refreshing: "Refreshing the last loaded binding; the current connection is not yet confirmed.",
@@ -261,7 +258,7 @@ export const sessions = {
},
items: {
agentWorkTrace: "Agent work trace", arguments: "Arguments", result: "Result", command: "Command", webSearch: "Web search", functionResult: "Function result", mcpTool: "MCP tool", function: "Function", unknown: "unknown", item: "Item",
- verb: { run: "Run", search: "Search", return: "Return", use: "Use", unsupported: "Unsupported" }, workingNote: "working note", emptyMessage: "Empty message item",
+ verb: { run: "Run", search: "Search", return: "Return", use: "Use", unsupported: "Unsupported" }, workingNote: "working note", emptyMessage: "Empty message Item",
applyPatchDiff: "OpenAgentCore apply patch diff", fileCount: "{{count}} files", changeKind: { add: "add", modify: "modify", delete: "delete" }, unifiedDiffFor: "Unified diff for {{path}}", rawArguments: "Raw arguments", rawResult: "Raw result", noResultYet: "No result yet",
},
@@ -274,7 +271,7 @@ export const sessions = {
trace: {
source: "Source", agentSnapshot: "Agent configuration snapshot", itemSnapshot: "Durable Item snapshot", notApplicable: "Not applicable", group: "Group", configuredModel: "Configured model", itemTiming: "Item timing", notProvidedByCore: "Not provided by Core", toolReportedDuration: "Tool-reported duration",
turnScopedUsage: "Turn-scoped token usage", turnScopedTokens: "Turn-scoped tokens", scopeBoundary: "This view reports Core resource scope. It does not infer a model span, provider, request step, or subagent relationship.", contractUnavailable: "Unavailable from the current Core contract.",
- turnStarted: "Turn started", turnCompleted: "Turn completed", turnWallClock: "Turn wall clock", itemStarted: "Item started", itemCompleted: "Item completed", timingBoundary: "Turn timestamps are server resources. Tool duration has no public absolute start, so it is not positioned on a time-scaled waterfall.",
+ turnStarted: "Turn started", turnCompleted: "Turn completed", turnWallClock: "Turn wall clock",
knownTurnTime: "Known Turn time", turns: "Turns", toolCalls: "Tool calls", search: "Search trace", durableExecutionOrder: "Durable execution order", durableOrder: "Durable order", equalWidth: "Equal-width sequence · not time-scaled",
lane: { input: "Input", model: "Model", tools: "Tools" }, label: { system: "SYSTEM", user: "USER", assistant: "ASSISTANT", tool: "TOOL", item: "ITEM" }, openItem: "Open {{label}} trace item: {{title}}",
contractNote: "Core reports Turn wall-clock time, but not per-item timing. Rows preserve durable order and are not time-scaled.", loadingHistory: "Loading complete durable Turn and Item history…",
@@ -283,30 +280,6 @@ export const sessions = {
toolDurationSentence: "Tool-reported duration: {{duration}}.", toolDuration: "Tool-reported duration: {{duration}}", durationUnknown: "Reported duration is unknown.", durationInvalid: "The reported duration could not be interpreted.", perItemNotProvided: "Per-item timing not provided by Core.", perItemTimingMissing: "Core does not provide per-item timing.",
turnDuration: "Turn {{duration}}", turnTimeUnknown: "Turn time unknown", turnTimeNotProvided: "Turn time not provided", payloadAvailable: "Payload available", resultAvailable: "Result available", noPreview: "No preview available", configuredInstructions: "Configured instructions", userMessage: "User message", assistantMessage: "Assistant message", unsupportedItem: "Unsupported Item", agentConfiguration: "Agent configuration", turnNumber: "Turn {{number}}", unassociatedItemsNumber: "Unassociated Items {{number}}", unknownCount: "{{count}} unknown",
},
- validation: {
- absoluteWorkspace: "Workspace directory must be an absolute POSIX path, for example /workspace.",
- safeWorkspace: "Workspace directory cannot contain NUL, carriage return, line feed, or backslash characters.",
- unsupportedNetworkPolicy: "The managed Environment network policy is unsupported.",
- invalidTemplateId: "The selected Environment Template identifier is invalid.",
- unsupportedEnvironmentType: "The selected Environment type is unsupported.",
- invalidEnvironmentInput: "The Environment input is invalid.",
- invalidNoEnvironment: "The no-Environment request contains unsupported fields.",
- invalidSelfHosted: "The self-hosted Environment request is not the supported Web profile.",
- invalidManaged: "The managed Environment request is not the supported basic profile.",
- firstMessageRequired: "A first message is required without an Environment.",
- nonblankFirstMessage: "Enter a nonblank first message.",
- addUserMessage: "Add at least one user message.",
- supportedTextParts: "User message {{number}} must contain supported text parts.",
- nonblankTextParts: "User message {{number}} needs nonblank text across its parts.",
- atLeastOneTextPart: "User message {{number}} needs at least one text part.",
- selectSavedAgent: "Select a saved Agent before configuring Session-only overrides.",
- nonemptyModelOverride: "Enter a non-empty Session model override.",
- inlineMustNotSendId: "Inline Session creation must not send agent_id.",
- invalidInlineProfile: "The inline Agent request is outside the supported Web profile.",
- selectLoadedOrInline: "Select a loaded saved Agent or use an inline Agent.",
- savedAgentNotLoaded: "The selected saved Agent is not loaded.",
- invalidOverrideProfile: "The Session-only Agent override is outside the supported Web profile.",
- },
actions: {
errors: {
metadataConflict: "Metadata changed in OpenAgentCore while you were editing: {{keys}}. Your draft was kept; review the latest values before saving again.",
diff --git a/apps/web/src/i18n/locales/en/skills.ts b/apps/web/src/i18n/locales/en/skills.ts
index 7ecb4f340..a48a126af 100644
--- a/apps/web/src/i18n/locales/en/skills.ts
+++ b/apps/web/src/i18n/locales/en/skills.ts
@@ -37,22 +37,14 @@ export const skills = {
defaultVersion: "Default version",
latestVersion: "Latest version",
created: "Created",
- id: "ID",
newerThanDefault: "Newer than default",
newerThanDefaultHelp: "A newer version exists but is not the default. New Sessions keep getting the default version.",
noMatchTitle: "No loaded Skill matches",
- noMatchDescription: "Only loaded Skills are filtered. Load more or clear the filter.",
- loadFailed: "Skills could not be loaded",
- refreshFailed: "Refresh failed; the Skills loaded earlier are shown. {{reason}}",
moreFailed: "The next page could not be loaded. {{reason}}",
},
empty: {
title: "No Skills yet",
},
- unsupported: {
- title: "This Core does not offer Skills",
- description: "The connected Core answered the Skill list with {{status}}.",
- },
detail: {
loading: "Loading Skill…",
facts: "Skill details",
@@ -81,16 +73,6 @@ export const skills = {
downloaded: "Saved {{filename}}",
actionFailed: "The request failed. {{reason}}",
},
- setDefault: {
- title: "Make v{{version}} the default?",
- newSessions: "New Sessions that reference this Skill without a version will get v{{version}}.",
- existingSessions: "Existing Sessions are not affected.",
- metadata: "The Skill's name and description become those of v{{version}}.",
- metadataChange: "The Skill's name and description become those of v{{version}}: {{name}}.",
- confirm: "Make default",
- saving: "Saving…",
- done: "v{{version}} is now the default",
- },
deleteVersion: {
title: "Delete v{{version}}?",
body: "Version numbers are never reused. Existing Sessions are not affected.",
@@ -113,69 +95,4 @@ export const skills = {
deleting: "Deleting…",
done: "{{name}} deleted",
},
- upload: {
- title: "Upload Skill",
- versionTitle: "Upload a new version of {{name}}",
- source: "Upload from",
- zip: "ZIP file",
- folder: "Folder",
- zipInput: "Choose a ZIP file",
- folderInput: "Choose a folder",
- reading: "Reading the selection…",
- setDefault: "Make this the default version",
- setDefaultHelp: "New Sessions that reference the Skill without a version will get this version, and the Skill's name and description will follow it. Existing Sessions are not affected.",
- submit: "Upload",
- uploading: "Uploading…",
- cancelUpload: "Cancel upload",
- created: "{{name}} uploaded",
- versionCreated: "v{{version}} uploaded",
- preview: {
- label: "Selection",
- folder: "Folder",
- files: "Files",
- size: "Size",
- archive: "ZIP size",
- name: "Name",
- description: "Description",
- missing: "Not found",
- },
- requirements: {
- title: "Format requirements",
- folder: "One top-level folder that contains SKILL.md.",
- frontmatter: "SKILL.md frontmatter supports only name, description, license, compatibility and string metadata. Hooks, permission controls and subagent directives are rejected.",
- files: "Regular files only: no symbolic links, special files or paths that leave the folder.",
- limits: "At most 5 MiB compressed and 20 MiB uncompressed; at most 500 files in a folder upload or 1,000 entries in a ZIP.",
- authority: "These are limits of this Core, not of the upstream protocol. Core makes the final check.",
- },
- issues: {
- noFiles: "The selection has no files.",
- tooManyFiles: "{{count}} files exceed the limit of {{limit}}.",
- tooLarge: "{{size}} uncompressed exceeds the limit of {{limit}}.",
- zipTooLarge: "The ZIP is {{size}}; the limit is {{limit}}.",
- notZip: "Choose a file that ends in .zip.",
- multipleTopLevel: "Put everything in one top-level folder. Found: {{names}}",
- outsideFolder: "These files are outside a folder: {{paths}}",
- missingManifest: "{{folder}}/SKILL.md is missing.",
- invalidPath: "Unsupported paths: {{paths}}",
- duplicatePath: "Duplicate paths: {{paths}}",
- hiddenFiles: "Hidden files are uploaded as they are: {{paths}}",
- more: "{{list}} and {{count}} more",
- manifestUnreadable: "SKILL.md could not be read for the preview.",
- zipUnreadable: "This ZIP could not be read for the preview. Core still checks it.",
- frontmatterMissing: "SKILL.md does not start with --- frontmatter.",
- frontmatterInvalid: "Part of the SKILL.md frontmatter could not be read.",
- nameMissing: "The frontmatter has no name.",
- descriptionMissing: "The frontmatter has no description.",
- unsupportedKeys: "Core rejects these frontmatter fields: {{keys}}",
- nameFormat: "Core expects a name of lowercase letters, digits, - and _, at most 64 characters.",
- },
- errors: {
- invalid: "Core rejected the Skill: {{message}}",
- tooLarge: "The files exceed the size limit.",
- interrupted: "The upload did not finish. Your selection is kept; Core may have stored it anyway, so check the list before trying again.",
- cancelled: "Upload cancelled. Your selection is kept; Core may have stored it anyway, so check the list before trying again.",
- other: "The upload failed: {{message}}",
- seeRequirements: "Format requirements",
- },
- },
} as const;
diff --git a/apps/web/src/i18n/locales/en/system.ts b/apps/web/src/i18n/locales/en/system.ts
index 1855547f6..4fd419cf0 100644
--- a/apps/web/src/i18n/locales/en/system.ts
+++ b/apps/web/src/i18n/locales/en/system.ts
@@ -8,9 +8,8 @@ export const system = {
publicUrl: "Public address",
publicUrlHelp: "The address applications, nodes and sandboxes use to reach Core.",
apiBaseUrl: "API base URL",
- apiBaseUrlHelp: "Applications use it as OPENAI_BASE_URL, with a Project API key as OPENAI_API_KEY.",
+ apiBaseUrlHelp: "Applications use it as OPENAI_BASE_URL, with a project API key as OPENAI_API_KEY.",
copyApiBaseUrl: "Copy API base URL",
- localOnly: "Only reachable on the Core machine",
details: "Installation details",
id: "Installation ID",
sourceCommit: "Source commit",
diff --git a/apps/web/src/i18n/locales/en/templates.ts b/apps/web/src/i18n/locales/en/templates.ts
index 1c033e1e2..c5e7a0f9a 100644
--- a/apps/web/src/i18n/locales/en/templates.ts
+++ b/apps/web/src/i18n/locales/en/templates.ts
@@ -1,35 +1,27 @@
export const templates = {
- boundary: "Applications create and change Templates through the Agents API with a project API key. The console only inspects and deletes them.",
+ boundary: "Applications create and change templates through the Agents API with a project API key. The console only inspects and deletes them.",
refreshFailed: "The catalog could not be refreshed. Check the connection and try again.",
- savedRefreshFailed: "The change was saved, but the catalog refresh failed. Refresh before making another change.",
created: "Template created. No Runtime was allocated.",
updated: "Template updated. Existing Sessions keep their configuration.",
deleted: "Template deleted.",
- loading: "Loading Environment Templates…",
- unavailableTitle: "Environment Templates are not available",
- unavailableDescription: "This Core does not expose the Template resource. No catalog is inferred.",
- loadFailedTitle: "Environment Templates could not be loaded",
- loadFailedDescription: "Check the Core connection and access permissions. The catalog is unavailable.",
- configureConnection: "Configure connection",
- filterLabel: "Filter Templates",
+ loading: "Loading Environment templates…",
+ loadFailedTitle: "Environment templates could not be loaded",
+ filterLabel: "Filter templates",
filterPlaceholder: "Filter by name or ID",
- count: "{{visible}} of {{total}} Templates",
- emptyTitle: "No Environment Templates yet",
- noMatch: "No matching Templates",
+ count: "{{visible}} of {{total}} templates",
+ emptyTitle: "No Environment templates yet",
+ noMatch: "No matching templates",
clearFilter: "Clear filter",
- listLabel: "Environment Templates",
+ listLabel: "Environment templates",
columns: {
name: "Name", network: "Network", packages: "Packages", files: "Files", skills: "Skills",
plugins: "Plugins", updated: "Updated", actions: "Actions",
},
access: { enabled: "Enabled", disabled: "Disabled", restricted: "Restricted" },
accessHelp: {
- enabled: "Native tools can reach any host.",
- disabled: "Native tools have no network access.",
restricted: "Native tools can reach only the listed hostnames. Subdomains and redirect targets need their own entries.",
},
edit: "Edit",
- editLabel: "Edit {{name}}",
delete: "Delete",
deleteLabel: "Delete {{name}}",
open: "Open {{name}}",
@@ -38,12 +30,12 @@ export const templates = {
unrecognizedHelp: "Core returned configuration this console does not recognize. Recognized sections are shown; the others are not guessed.",
unrecognizedSections: "Not recognized by this console: {{sections}}",
unrecognizedValue: "Not recognized",
- modal: { delete: "Delete Template?", edit: "Edit Template", create: "Create Template" },
+ modal: { delete: "Delete template?" },
deletePrompt: "Delete {{name}}?",
- deleteWarning: "New Sessions can no longer select this Template. Existing Sessions are not affected. This cannot be undone.",
+ deleteWarning: "New Sessions can no longer select this template. Existing Sessions are not affected. This cannot be undone.",
deleting: "Deleting…",
- deleteTemplate: "Delete Template",
- unnamed: "Unnamed Template",
+ deleteTemplate: "Delete template",
+ unnamed: "Unnamed template",
detail: {
facts: "Template facts",
id: "Template ID",
@@ -93,13 +85,11 @@ export const templates = {
domainsPlaceholder: "pypi.org",
domainsRequired: "Enter at least one hostname for restricted access.",
policyLocked: "Core returned a network policy this console does not recognize, so it cannot be edited here.",
- keepsOther: "Only the name and network are saved. Everything else in this Template stays as it is.",
- saving: "Saving…", saveChanges: "Save changes", create: "Create Template",
+ keepsOther: "Only the name and network are saved. Everything else in this template stays as it is.",
+ saving: "Saving…", saveChanges: "Save changes", create: "Create template",
},
errors: {
- forbidden: "Core rejected this request. Check the connection and access permissions.",
- missing: "This Template is no longer available. Refresh the catalog before trying again.",
- invalid: "Core rejected the Template configuration: {{reason}}",
+ invalid: "Core rejected the template configuration: {{reason}}",
uncertain: "The write outcome was not confirmed. Refresh and review Core's catalog before making another change. The request was not replayed.",
},
} as const;
diff --git a/apps/web/src/i18n/locales/en/vaults.ts b/apps/web/src/i18n/locales/en/vaults.ts
index f756206c8..e7fa0d617 100644
--- a/apps/web/src/i18n/locales/en/vaults.ts
+++ b/apps/web/src/i18n/locales/en/vaults.ts
@@ -1,46 +1,15 @@
export const vaults = {
securityNote: "Tokens are write only. This page receives Credential metadata, never token values. Deleting a Vault also deletes all of its stored Credentials and does not revoke provider-side tokens.",
- actionNotConfirmed: "Action not confirmed",
- mutationUncertain: "The write outcome was not confirmed. The catalog was refreshed; review current Core state before explicitly trying again.",
loading: "Loading Vaults",
loadFailed: "Couldn’t load Vaults", refreshFailed: "Couldn’t refresh Vaults",
- failedDescription: "The Web could not load the complete Vault and Credential catalog.", staleDescription: "The previous safe metadata snapshot remains visible, but it cannot authorize new Sessions.",
- failedHint: "Check the Core connection, then refresh. Credentialed Sessions stay blocked until the complete catalog loads.",
credential: "Credential", deleteVaultLabel: "Delete {{name}}", created: "Created", credentialsIn: "Credentials in {{name}}",
- updatedHidden: "Updated {{date}} · token hidden", oauthHelp: "OAuth · Manage authorization and token replacement in your application.",
- replaceTokenLabel: "Replace token for {{name}}", replaceToken: "Replace token", deleteCredentialLabel: "Delete {{name}}",
- noCredentials: "No Credentials in this Vault.", noVaults: "No Vaults yet",
- createVault: "Create Vault", createVaultTitle: "Create a Vault", deleteVaultTitle: "Delete Vault?", deleteCredentialTitle: "Delete Credential?",
+ oauthHelp: "OAuth · Manage authorization and token replacement in your application.",
+ deleteCredentialLabel: "Delete {{name}}",
+ noCredentials: "No Credentials in this Vault yet.", noVaults: "No Vaults yet",
+ deleteVaultTitle: "Delete Vault?", deleteCredentialTitle: "Delete Credential?",
deleting: "Deleting…", delete: "Delete", deleteVaultPrompt: "Delete {{name}} and all of its stored Credentials? Existing Sessions keep frozen IDs, but later secret lookup fails. Provider tokens and running work are not revoked.",
deleteCredentialPrompt: "Delete {{name}}? Existing Sessions keep its frozen identity, but later secret lookup fails. This does not revoke the token at the MCP provider.",
unnamed: "Unnamed Vault",
- list: { label: "Vaults", filterLabel: "Filter Vaults", filterPlaceholder: "Filter by name or ID", name: "Name", credentials: "Credentials", created: "Created", actions: "Actions", open: "Open {{name}}", noMatch: "No matching Vaults" },
+ list: { label: "Vaults", filterLabel: "Filter Vaults", filterPlaceholder: "Filter by name or ID", name: "Name", created: "Created", actions: "Actions", open: "Open {{name}}", noMatch: "No matching Vaults" },
detail: { back: "Back", facts: "Vault details", id: "ID", created: "Created", metadata: "Metadata", credentials: "Credentials", credentialsHelp: "Static bearer tokens are write-only: Core never returns them, so this page shows metadata only. Replacing a token does not revoke the old one at the provider.", name: "Name", url: "MCP server URL", auth: "Authentication", updated: "Updated", addCredential: "Add Credential", deleteVault: "Delete Vault", staticBearer: "Static bearer", oauth: "OAuth", tokenHidden: "Token hidden" },
- createForm: {
- name: "Name", namePlaceholder: "Runtime credentials", nameHelp: "Required. The trimmed name may contain at most 256 UTF-8 bytes.",
- metadata: "Metadata", optional: "Optional", metadataHelp: "Enter a JSON object with string values. Blank input becomes {{emptyObject}}; encoded metadata may be at most 64 KiB.",
- metadataWarning: "Vault metadata is public. Never place secrets, tokens, passwords, credentials, or private connection data here.",
- creating: "Creating…", create: "Create Vault",
- },
- credentialDialog: {
- replaceTitle: "Replace token · {{name}}", addTitle: "Add static bearer Credential", saving: "Saving…", create: "Create Credential",
- notConfirmed: "Credential was not confirmed", name: "Name", namePlaceholder: "Internal MCP", exactUrl: "Exact MCP server URL",
- urlHelp: "The URL must exactly match the Agent MCP definition. Creating this resource makes no network request.",
- replaceWarning: "The old token is never read or shown. Running work may already hold it, and replacing it does not revoke the provider-side token.",
- newToken: "New bearer token", token: "Bearer token", tokenHelp: "Write only. It is sent once, immediately cleared, and never stored in browser state, metadata, previews, or logs.",
- },
- errors: {
- auth: "Core authentication failed. The Credential was not confirmed.", missing: "The Vault or Credential is no longer available. Refresh before trying again.",
- tooLarge: "The Credential request exceeded Core's accepted size.", invalidFields: "Core rejected the Credential fields. Check the name, exact HTTPS URL, and token format.",
- credentialUncertain: "The Credential write outcome was not confirmed. The catalog was refreshed; review it before explicitly trying again.",
- bearer: "Enter a non-empty RFC 6750 bearer token. Whitespace and other opaque storage-only values cannot execute in the current runtime.",
- credentialName: "Credential name must contain 1 to 256 UTF-8 bytes.", exactUrl: "Enter an exact HTTPS MCP URL without credentials, query parameters, fragments, whitespace, or backslashes.",
- createUncertain: "Vault creation was not confirmed. Your draft is unchanged. Review current Core state before explicitly trying again.",
- vaultName: "Name must contain 1 to 256 UTF-8 bytes.", metadataUnknown: "Metadata could not be validated.", metadataJson: "Metadata must be valid JSON.",
- metadataShape: "Metadata must be a JSON object whose values are strings.", metadataStrings: "Metadata values must all be strings; nested values, arrays, numbers, booleans, and null are not supported.",
- metadataLarge: "Metadata must be at most 64 KiB after UTF-8 JSON encoding.", mismatchedMetadata: "OpenAgentCore returned mismatched Vault metadata.",
- uniqueAttachments: "Vault attachments must be unique.", catalogIncomplete: "Credential metadata is not fully loaded from this Core.", vaultMissing: "A selected Vault is no longer available in the current catalog.",
- credentialMismatch: "MCP server {{server}} references an unavailable or URL-mismatched Credential.", credentialVaultMissing: "MCP server {{server}} references a Credential whose Vault is unavailable.",
- multipleCredentials: "Anonymous MCP server {{server}} matches multiple Credentials in the selected Vaults. Select a single matching Vault or configure one Credential explicitly.", matchedVaultMissing: "MCP server {{server}} matched a Credential whose Vault is unavailable.",
- },
} as const;
diff --git a/apps/web/src/i18n/locales/zh-CN/agents.ts b/apps/web/src/i18n/locales/zh-CN/agents.ts
index 9cc0aedf9..5c6f0e7e3 100644
--- a/apps/web/src/i18n/locales/zh-CN/agents.ts
+++ b/apps/web/src/i18n/locales/zh-CN/agents.ts
@@ -1,14 +1,11 @@
import type { agents as english } from "../en/agents";
type TranslationShape = { [K in keyof T]: T[K] extends string ? string : TranslationShape };
export const agents: TranslationShape = {
- loading: "正在加载 Agent", requestFailed: "OpenAgentCore 请求失败。", searchPlaceholder: "按名称、模型或 ID 搜索…", filtersLabel: "Agent 筛选", searchLabel: "搜索 Agent", refreshLabel: "刷新 Agent", loadFailed: "无法加载 Agent", refreshFailed: "无法刷新 Agent", staleDescription: "上次加载的 Agent 配置仍然可用。", loadDescription: "Web 无法从已连接的 OpenAgentCore 读取 Agent 配置。", connectionHint: "请检查侧栏中的 OpenAgentCore 连接后重试。", openFailed: "无法打开最新 Agent", retry: "重试", requestFailure: "请求失败",
- errors: {
- retrievalUnavailable: "此 OpenAgentCore 连接不支持读取 Agent。", interrupted: "Agent 请求因连接变化而中断。", differentRetrieved: "OpenAgentCore 返回了与请求不同的 Agent。", updateUnavailable: "此 OpenAgentCore 连接不支持更新 Agent。", updateInterrupted: "Agent 更新因连接变化而中断。", differentUpdated: "OpenAgentCore 返回了与所更新对象不同的 Agent。", deleteUnavailable: "此 OpenAgentCore 连接不支持删除。", modelRequired: "请输入模型 ID。", nameTooLong: "名称最多 128 个字符。", metadataJson: "元数据必须是有效 JSON。", metadataObject: "元数据必须是 JSON 对象。", metadataStrings: "每个元数据值都必须是字符串。", metadataCount: "Agent 元数据最多支持 16 组键值。", metadataLength: "元数据键最多 64 个字符,值最多 512 个字符。", reasoningDefault: "当前 Core Session 要求两个推理字段都使用 Core 默认值。", serviceTier: "当前 Core Session 仅支持 auto 服务层级。", textFormat: "当前 Core Session 仅支持文本格式。", verbosity: "低或高详细程度需要已发现的兼容 Codex 模型;此 Web 流程请使用 medium。", readOnlyTools: "此 Agent 包含只读的已保存工具定义,因此不能更改工具。", functionName: "每个 Function 都需要非空名称。", functionNameLength: "Function 名称最多 512 个 UTF-8 字节。", functionUnique: "Function 名称不能重复。", functionJson: "Function {{name}} 的参数必须是有效 JSON。", functionSchema: "Function {{name}} 的参数必须是 JSON 对象 schema。", mcpLabel: "每个 MCP 服务都需要非空标签。", mcpUnique: "MCP 服务标签不能重复。", mcpUrl: "MCP 服务 {{name}} 需要有效的匿名 HTTP(S) URL。", credentialMissing: "MCP 服务 {{name}} 引用了当前目录中不存在的 Credential。", credentialUrl: "MCP 服务 {{name}} 必须使用所选 Credential 的精确 URL。", functionCount: "最多可配置 64 个 Function。",
- },
+ loading: "正在加载 Agent", searchPlaceholder: "按名称、模型或 ID 搜索…", refreshLabel: "刷新 Agent", loadFailed: "无法加载 Agent", refreshFailed: "无法刷新 Agent", retry: "重试",
view: {
filterLabel: "筛选 Agent",
searchPlaceholder: "按名称、模型或 ID 搜索",
- columns: { agent: "Agent", model: "模型", harness: "Harness", tools: "工具", sessions: "Session", tokens: "Token", lastActive: "最近活跃", updated: "更新时间", actions: "操作" },
+ columns: { agent: "Agent", model: "模型", harness: "Harness", tools: "工具", sessions: "Session", tokens: "token", lastActive: "最近活跃", actions: "操作" },
open: "打开 {{name}}",
coreDefault: "Core 默认",
back: "返回",
@@ -31,8 +28,8 @@ export const agents: TranslationShape = {
verbosity: "详细程度",
serviceTier: "服务层级",
provider: {
- title: "模型服务",
- help: "保存在此 Agent 上。它的 Session 使用这里的模型服务,除非请求中另外指定。Core 从不返回 API 密钥。",
+ title: "模型提供商",
+ help: "保存在此 Agent 上。它的 Session 使用这里的模型提供商,除非请求中另外指定。Core 从不返回 API 密钥。",
protocol: "协议",
baseUrl: "Base URL",
apiKey: "API 密钥",
@@ -56,25 +53,9 @@ export const agents: TranslationShape = {
delete: "删除",
},
catalog: {
- listLabel: "Agent", create: "创建 Agent", untitled: "未命名 Agent", editLabel: "编辑 {{name}}({{id}})", opening: "正在打开最新定义…", startLabel: "使用 {{name}}({{id}})启动 Session", unavailable: "不可用", startSession: "启动 Session", sessionUnavailable: "Session 不可用:{{reason}}", noMatch: "没有匹配的 Agent", noSaved: "还没有 Agent", clearSearch: "清除搜索",
- columns: { agent: "Agent", model: "模型", harness: "Harness", tools: "工具", updated: "更新时间", actions: "操作" }, coreDefaultHarness: "Core 默认", copyId: "复制 Agent ID {{id}}", copied: "已复制", unavailableHelp: "无法启动 Session 的原因",
+ listLabel: "Agent", untitled: "未命名 Agent", noMatch: "没有匹配的 Agent", noSaved: "还没有 Agent",
},
details: {
- id: "ID", created: "创建时间", updated: "更新时间", model: "模型", name: "名称", instructions: "指令", metadata: "元数据", notSet: "未设置", none: "无", blocked: "此 Agent 可以保存,但已知的 Core Session 配置无法启动它:{{reason}}", runtimeBoundary: "已保存的高级配置不能证明运行时可用。模型、provider、主机、工具和条件性详细程度仍需 executor 验证。", advanced: "高级配置 · 只读", tools: "工具", reasoning: "推理", text: "文本", serviceTier: "服务层级", multiAgent: "多 Agent", functionTool: "Function {{name}}", mcpTool: "{{auth}} 服务来源 HTTP MCP {{name}}", serviceOriginMcp: "服务来源 HTTP MCP", vaultBearer: "Vault bearer", anonymous: "匿名", readOnly: "{{label}} · 只读", deletePrompt: "从 OpenAgentCore 删除 {{name}}?", deleteBefore: "从 OpenAgentCore 删除", deleteAfter: "?", exactId: "精确 Agent ID:{{id}}", exactIdLabel: "精确 Agent ID:", deleteWarning: "只有在 Core 确认成功后才会移除已保存的 Agent。现有 Session 会保留持久化的 Agent 快照。", deleteTitle: "删除 Agent?", cancel: "取消", deleting: "删除中…",
- },
- savedTool: { malformed: "已保存的工具定义格式错误", toolSearch: "tool_search 仅可保存,不能在 Session 中运行", programmatic: "programmatic_tool_calling 仅可保存,不能在 Session 中运行", webSearchDisabled: "已禁用的 web_search 在 Web 中仅可查看;Session 将保持搜索关闭", webSearchEnabled: "已启用的 web_search 仅可保存;Core 不会在 Session 中运行已启用的搜索", deferred: "延迟 Function 仅可保存", credentialedMcp: "当前 Vault 目录中无法解析需要 Credential 的 MCP,或其 URL 不匹配", unsupportedFunction: "不支持的 Function 工具定义", unsupportedMcp: "不支持的 MCP 工具定义", unsupported: "不支持的已保存工具定义" },
- admission: { model: "模型不能为空", multiAgent: "不支持多 Agent 执行", reasoning: "显式推理选项仅可保存", serviceTier: "服务层级必须为 auto", text: "文本格式必须为 text", malformedTool: "已保存的工具配置不可执行", malformedFunction: "已保存的 Function 工具不完整或格式错误", deferred: "延迟 Function 仅可保存", functionName: "Function 名称必须非空且最多 512 字节", functionUnique: "Function 名称必须唯一", malformedMcp: "已保存的 MCP 工具不完整或格式错误", credential: "此 Web Session 流程无法使用附加的 MCP Credential", mcpUnique: "MCP 服务标签必须唯一", malformedWebSearch: "已保存的 web_search 工具不完整或格式错误", enabledWebSearch: "web_search 模式必须禁用,因为 Core 不会运行已启用的搜索", savedOnly: "{{type}} 仅可保存", unsupportedTool: "已保存的工具类型不可执行", functionCount: "最多可执行 64 个 Function 工具", webSearchCount: "最多可执行一个 web_search 工具", coreRequires: "当前 Core Session 准入要求:{{reasons}}。", vaultUnavailable: "无法附加 Session Vault。{{reason}}", managedMcp: "托管 Session 暂不支持 MCP 工具。请选择无环境或自托管环境,或使用仅含 Function 的 Agent。" },
- usage: {
- title: "用量", rangeLabel: "Session 创建时间", ranges: { all: "全部", "7d": "近 7 天", "30d": "近 30 天" },
- help: "用量是 Core 报告的每个 Session 的累计值,不按天拆分。Session 按创建时间归入时间范围,其全部用量都计入该范围。",
- caveat: "数据来自 Core 报告的 Session 累计用量,不包含未报告的部分,不能作为计费依据。",
- reading: "正在读取 Session…已读取 {{formattedCount}} 个", cancel: "取消", cancelled_one: "已在读取 {{formattedCount}} 个 Session 后停止。", cancelled_other: "已在读取 {{formattedCount}} 个 Session 后停止。", continue: "继续", failed: "无法读取 Session。", retry: "重试",
- large: "Session 超过 {{formattedCount}} 个,统计可能较慢。建议先缩小时间范围。", largeShortest: "Session 超过 {{formattedCount}} 个,统计可能较慢。",
- sessions: "Session", tokens: "Token", coverage: "覆盖率", lastActive: "最近活跃", noData: "无数据", cardLabel: "{{name}} 的用量",
- coverageHelp: "Core 报告了用量的 Session 占范围内全部 Session 的比例。没有报告用量的 Session 不计入 Token 合计,也不按 0 计算。",
- coverageDetail_one: "{{formattedCount}} 个 Session 中有 {{reported}} 个报告了用量", coverageDetail_other: "{{formattedCount}} 个 Session 中有 {{reported}} 个报告了用量",
- status: "状态", statuses: { in_progress: "进行中", requires_action: "需要处理", failed: "失败", idle: "空闲", unknown: "无法识别" },
- tokenKinds: { input: "输入", output: "输出", total: "总计", cached: "缓存命中", reasoning: "推理" },
- other: { title: "其他 Agent", help: "这些 Session 的 Agent ID 不在当前 Agent 列表中:Agent 可能已被删除,或创建 Session 时使用了内联配置。按原始 Agent ID 分组。", agentId: "Agent ID", missingId: "无 Agent ID", showAll: "显示全部 {{formattedCount}} 个", showLess: "收起" },
+ reasoning: "推理",
},
};
diff --git a/apps/web/src/i18n/locales/zh-CN/common.ts b/apps/web/src/i18n/locales/zh-CN/common.ts
index 19b551883..b04fdc07b 100644
--- a/apps/web/src/i18n/locales/zh-CN/common.ts
+++ b/apps/web/src/i18n/locales/zh-CN/common.ts
@@ -12,7 +12,7 @@ export const common = {
apiEmpty: {
agents: "应用通过 Agents API 创建 Agent。",
sessions: "应用通过 Agents API 启动 Session。",
- "environment-templates": "应用通过 Agents API 创建环境模板。",
+ "environment-templates": "应用通过 Agents API 创建 Environment 模板。",
skills: "应用通过 Agents API 上传 Skill。",
"source-files": "应用通过 Agents API 上传文件。",
vaults: "应用通过 Agents API 创建 Vault。",
@@ -71,6 +71,5 @@ export const common = {
loadedMore: "已加载 {{n}} 个,还有更多",
noMatches: "没有匹配项",
deleteUncertain: "未能确认删除结果,Core 可能已删除,也可能没有。页面已重新读取,请先确认再决定是否重试。",
- noMatchesDescription: "没有符合当前搜索或筛选条件的结果。",
},
} as const;
diff --git a/apps/web/src/i18n/locales/zh-CN/core-errors.ts b/apps/web/src/i18n/locales/zh-CN/core-errors.ts
index cacd84e03..025305f7c 100644
--- a/apps/web/src/i18n/locales/zh-CN/core-errors.ts
+++ b/apps/web/src/i18n/locales/zh-CN/core-errors.ts
@@ -13,8 +13,8 @@ export const coreErrors = {
"invalid_node_capacity": "请输入有效的整数容量;保留容量不能小于运行容量。",
"model_configuration_model_invalid": "请输入模型 ID,最多 1024 个 UTF-8 字节,且不能包含控制字符。",
"harness_config_invalid": "请检查支持的原生字段及其取值。JSON 对象不能超过 16 KiB,也不能重复定义 Core 管理的设置。",
- "invalid_model_provider": "请填写完整的模型服务配置。",
- "model_provider_base_url_invalid": "请使用 HTTPS 地址,不要包含凭证、查询参数或片段。",
+ "invalid_model_provider": "请填写完整的模型提供商配置。",
+ "model_provider_base_url_invalid": "请使用 HTTPS 地址,不要包含凭据、查询参数或片段。",
"model_provider_protocol_unsupported": "此 Harness 不支持该协议。",
"model_provider_api_key_invalid": "请输入有效的 API 密钥,不要包含控制字符。",
"model_provider_token_limits_invalid": "请填写有效的 token 限制;输出不能超过上下文,必填限制必须大于零。",
@@ -22,7 +22,7 @@ export const coreErrors = {
"project_archived": "此项目已归档。",
"project_exists": "此项目名称已被使用。",
"project_api_key_exists": "此名称已被使用中的 API 密钥占用。",
- "executor_credential_exists": "此名称的执行器凭证已存在。",
+ "executor_credential_exists": "此名称的执行器凭据已存在。",
"internal_error": "Core 未能完成请求。",
"sandbox_generation_stale": "Core 的沙箱配置已更新。请刷新并检查后再提交。",
"sandbox_reset_required": "请先重置沙箱部署,再更改此配置。",
@@ -39,7 +39,7 @@ export const coreErrors = {
"sandbox_deployment_conflict": "沙箱部署在当前状态下无法更改。请刷新并检查重置和资源状态。",
"sandbox_specification_mismatch": "已保存的沙箱规格与部署不一致。请刷新检查配置。",
"sandbox_operation_unsupported": "所选沙箱提供商不支持此操作。",
- "environment_unavailable": "此 Session 的环境已不可用。",
+ "environment_unavailable": "此 Session 的 Environment 已不可用。",
"execution_unavailable": "执行暂时不可用,请稍后重试。",
"runtime_history_unavailable": "Runtime 历史暂时不可用,请稍后重试。",
"runtime_history_unsupported": "此 Session 不支持 Runtime 历史。",
@@ -56,5 +56,5 @@ export const coreErrorDetails = {
"keyLimit": "请输入有效的 API 密钥,长度最多 {{max}} 个字符。",
"resourceRange": "请输入 {{min}} 到 {{max}} 的整数。",
"resourceMin": "请输入不小于 {{min}} 的整数。",
- "runtime": "请使用适用于此后端的有效不可变 Runtime 版本。"
+ "runtime": "请使用适用于此沙箱提供商的有效不可变 Runtime 版本。"
} as const;
diff --git a/apps/web/src/i18n/locales/zh-CN/dashboard.ts b/apps/web/src/i18n/locales/zh-CN/dashboard.ts
deleted file mode 100644
index 230514d60..000000000
--- a/apps/web/src/i18n/locales/zh-CN/dashboard.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-export const dashboard = {
- trends: {
- title: "资源趋势", retained: "保留采样 · 持久历史", local: "浏览器本地采样 · 重新加载后重置", source: "运行时指标数据源", live: "实时", history: "历史",
- historyStale: "历史数据已过期", historyLoading: "历史 · 加载中", durableResolution: "持久数据 · {{seconds}}秒", liveRetrying: "实时 · 正在重试历史数据", liveUnavailable: "实时 · 历史数据不可用", liveLoading: "实时 · 正在加载历史数据", staleRetrying: "已过期 · 正在重试", liveInterval: "实时 · {{seconds}}秒",
- durableStatus: "{{status}};{{count}} 个 运行时目标", retainedFailure: "运行时采样刷新失败,正在显示保留采样", samplingInterval: "运行时每 {{seconds}} 秒实时采样一次",
- bucket: "时间桶", buckets: "时间桶", sample: "个采样", samples: "个采样", observations: "{{actual}}/{{expected}} 个观测", durableRange: "运行时持久时间范围", liveRange: "运行时实时时间范围",
- refreshFailed: "持久历史刷新失败:{{error}}", notConfigured: "未配置持久历史;实时采样仍可用。", requestFailed: "请求 运行时持久历史失败。",
- },
- charts: {
- collecting: "正在收集实时采样", durableHistory: "持久历史", live: "实时", retainedBuckets: "保留时间桶", liveSamples: "实时采样", chartLabel: "{{title}} {{source}} 图表",
- hideSeries: "隐藏 {{series}} 序列", showSeries: "显示 {{series}} 序列", hide: "隐藏 {{series}}", show: "显示 {{series}}", resetZoom: "重置缩放",
- instructions: "将指针移到图表上可查看精确值。水平拖动可选择并缩放时间范围。双击或使用“重置缩放”可恢复完整范围。单击可固定时间点,使用左右方向键移动,按 Esc 清除。",
- pinned: "已固定", hover: "悬停", unavailable: "不可用", allHidden: "已隐藏所有序列", sparse: "采样稀疏", showLegend: "使用图例显示序列", sparseDetail: "{{count}} 个有效点 · 绘制连线需要连续时间桶", emptyDetail: "{{valid}}/2 个有效点 · {{count}} 个快照 · 不会合成历史数据",
- table: { series: "序列", latest: "最新值", missing: "缺失采样" }, runtime: "运行时", usage: "使用率", used: "已使用", configuredLimit: "配置上限", input: "输入", output: "输出", gridDurable: "运行时持久历史图表", gridLive: "运行时实时窗口图表",
- cpu: { title: "CPU 使用率", withoutData: "{{count}} 个运行时目标在此时间段内没有 CPU 数据", durable: "按时间桶聚合的累计差值使用率 · 持久历史", live: "已报告或累计差值使用率 · 实时窗口", empty: "无保留的 CPU 采样" },
- memory: { title: "内存使用", durable: "已观测沙箱 聚合 / 配置上限 · 持久历史", live: "已观测沙箱 工作集 / 配置上限 · 实时窗口", empty: "无保留的已观测内存采样" },
- active: { series: "活跃", sandboxTitle: "活跃沙箱", runtimeTitle: "运行时活跃状态", sumDurable: "每个保留时间桶中的已观测分配数 · 持久历史", sumLive: "每个快照中生命周期状态为活动的分配数 · 实时窗口", binaryDurable: "保留时间桶中存在已观测分配 · 1 活动 / 0 非活跃", binaryLive: "生命周期状态为活动 · 1 活动 / 0 非活跃", active: "活跃", inactive: "非活跃", empty: "无保留的活跃沙箱 采样" },
- tokens: { title: "Token 吞吐量", durable: "规范 Session 用量差值 · 持久历史", live: "Session 用量差值 · 排除缺失用量", empty: "无保留的 Token 采样", perMinute: "{{value}}/分钟" },
- },
-} as const;
diff --git a/apps/web/src/i18n/locales/zh-CN/diagnostics.ts b/apps/web/src/i18n/locales/zh-CN/diagnostics.ts
index f7e530a2c..2b1112d4f 100644
--- a/apps/web/src/i18n/locales/zh-CN/diagnostics.ts
+++ b/apps/web/src/i18n/locales/zh-CN/diagnostics.ts
@@ -1,28 +1,28 @@
export const diagnostics = {
- providerUnknown: "暂无记录",
+ providerUnknown: "还没有记录",
providerStale: "记录尚未确认",
providerError: "近期错误",
providerDetails: "使用详情",
providerTitle: "{{name}} 使用详情",
providerLastUsed: "最近成功使用",
providerLastError: "成功后发生的错误",
- providerNoError: "暂无记录",
+ providerNoError: "没有记录",
providerHelp: "Core 记录使用此部署默认配置的托管 Turn 结果。记录可能延迟或缺失;暂无记录不代表服务已就绪或从未使用。替换默认配置后会重新记录。",
providerStaleHelp: "最新读取失败,当前显示上次确认的记录。",
failure: {
- authentication_error: "模型服务认证失败。",
- rate_limit_exceeded: "已达到模型服务的请求频率上限。",
- usage_limit_exceeded: "已达到模型服务的用量上限。",
- server_overloaded: "模型服务当前负载过高。",
- server_error: "模型服务发生了服务器错误。",
- invalid_request: "模型服务拒绝了请求。",
- resource_not_found: "模型服务找不到该模型。",
- request_timeout: "模型服务请求超时。",
+ authentication_error: "模型提供商认证失败。",
+ rate_limit_exceeded: "已达到模型提供商的请求频率上限。",
+ usage_limit_exceeded: "已达到模型提供商的用量上限。",
+ server_overloaded: "模型提供商当前负载过高。",
+ server_error: "模型提供商发生了服务器错误。",
+ invalid_request: "模型提供商拒绝了请求。",
+ resource_not_found: "模型提供商找不到该模型。",
+ request_timeout: "模型提供商请求超时。",
context_length_exceeded: "输入超出模型的上下文上限。",
- cyber_policy: "模型服务因安全策略拒绝了输入。",
- connection_failed: "与模型服务的连接失败。",
+ cyber_policy: "模型提供商因安全策略拒绝了输入。",
+ connection_failed: "与模型提供商的连接失败。",
harness_error: "Harness 执行失败,Core 无法识别原因。",
- model_provider_required: "此 Session 未配置模型服务。",
+ model_provider_required: "此 Session 未配置模型提供商。",
runtime_unavailable: "Runtime 不可用。",
runtime_disconnected: "执行过程中 Runtime 连接中断。",
runtime_preparation_failed: "Runtime 未能完成执行准备。",
@@ -33,30 +33,30 @@ export const diagnostics = {
core_storage_failed: "Core 未能保存执行数据。",
internal_error: "执行未能完成,未报告具体原因。",
environment_connection_timeout: "执行器未在输入截止时间前连接。",
- environment_unavailable: "此 Session 的环境不可用。",
- environment_provisioning_failed: "环境准备失败。",
+ environment_unavailable: "此 Session 的 Environment 不可用。",
+ environment_provisioning_failed: "Environment 准备失败。",
},
next: {
- authentication_error: "请检查该 Session 所用模型服务的 API 密钥。Session 及其保存的 Agent 都未设置模型服务时,托管沙箱 Session 使用“设置 → 模型与凭据”中的默认配置。",
- rate_limit_exceeded: "请稍后重试,或向模型服务申请提高限额。",
- usage_limit_exceeded: "请在模型服务中检查账户额度。",
+ authentication_error: "请检查该 Session 所用模型提供商的 API 密钥。Session 及其保存的 Agent 都未设置模型提供商时,托管沙箱 Session 使用“设置 → 模型与凭据”中的默认配置。",
+ rate_limit_exceeded: "请稍后重试,或向模型提供商申请提高限额。",
+ usage_limit_exceeded: "请在模型提供商中检查账户额度。",
server_overloaded: "请稍后重试。",
server_error: "请稍后重试。",
- invalid_request: "请检查模型和参数,先看 Session 页显示的模型。Session 及其保存的 Agent 都未设置模型服务时,托管沙箱 Session 使用“设置 → 模型与凭据”中的默认配置。",
- resource_not_found: "请检查 Session 页显示的模型。Session 及其保存的 Agent 都未设置模型服务时,托管沙箱 Session 使用“设置 → 模型与凭据”中的默认配置。",
+ invalid_request: "请检查模型和参数,先看 Session 页显示的模型。Session 及其保存的 Agent 都未设置模型提供商时,托管沙箱 Session 使用“设置 → 模型与凭据”中的默认配置。",
+ resource_not_found: "请检查 Session 页显示的模型。Session 及其保存的 Agent 都未设置模型提供商时,托管沙箱 Session 使用“设置 → 模型与凭据”中的默认配置。",
request_timeout: "请稍后重试。",
context_length_exceeded: "请新建 Session 或缩短输入。",
cyber_policy: "请修改输入后再发送,或新建 Session。",
- connection_failed: "请检查该 Session 所用模型服务的 Base URL。Session 及其保存的 Agent 都未设置模型服务时,托管沙箱 Session 使用“设置 → 模型与凭据”中的默认配置。",
- harness_error: "Core 不显示 Harness 的原始消息。请检查 Session 页显示的模型和 Harness,再检查该 Session 所用的模型服务。Session 及其保存的 Agent 都未设置模型服务时,托管沙箱 Session 使用“设置 → 模型与凭据”中的默认配置。",
- model_provider_required: "请在 Session 或其保存的 Agent 上设置模型服务。托管沙箱 Session 也可以使用“设置 → 模型与凭据”中的默认配置。",
+ connection_failed: "请检查该 Session 所用模型提供商的 Base URL。Session 及其保存的 Agent 都未设置模型提供商时,托管沙箱 Session 使用“设置 → 模型与凭据”中的默认配置。",
+ harness_error: "Core 不显示 Harness 的原始消息。请检查 Session 页显示的模型和 Harness,再检查该 Session 所用的模型提供商。Session 及其保存的 Agent 都未设置模型提供商时,托管沙箱 Session 使用“设置 → 模型与凭据”中的默认配置。",
+ model_provider_required: "请在 Session 或其保存的 Agent 上设置模型提供商。托管沙箱 Session 也可以使用“设置 → 模型与凭据”中的默认配置。",
runtime_unavailable: "请稍后重试。自托管 Session 请检查 Session 页的“主机连接”;托管沙箱 Session 请检查“设置 → 沙箱与调度”。",
runtime_disconnected: "请稍后重试。自托管 Session 请检查 Session 页的“主机连接”;托管沙箱 Session 请检查“设置 → 沙箱与调度”。",
delivery_unconfirmed: "请先检查结果,再决定是否重新发送。",
},
/** Between sentences of one reason. */
sentenceGap: "",
- provisioningStep: "环境准备在{{step}}阶段失败。",
+ provisioningStep: "Environment 准备在{{step}}阶段失败。",
setupIndex: "第 {{number}} 条设置命令。",
exitCode: "退出码 {{code}}。",
httpStatus: "HTTP {{status}}。",
diff --git a/apps/web/src/i18n/locales/zh-CN/files.ts b/apps/web/src/i18n/locales/zh-CN/files.ts
index 5bff5e584..f816833cd 100644
--- a/apps/web/src/i18n/locales/zh-CN/files.ts
+++ b/apps/web/src/i18n/locales/zh-CN/files.ts
@@ -4,7 +4,7 @@ type TranslationShape = { [K in keyof T]: T[K] extends string ? string : Tran
export const files: TranslationShape = {
title: "文件",
- help: "通过 Files API 上传到本项目的文件,包括 API 调用方上传的文件。在环境模板中引用 File ID,即可把文件复制到每个新 Session 的工作区。用户数据(user_data)文件不能下载:Core 会拒绝读取其内容。",
+ help: "通过 Files API 上传到本项目的文件,包括 API 调用方上传的文件。在 Environment 模板中引用 File ID,即可把文件复制到每个新 Session 的工作区。用户数据(user_data)文件不能下载:Core 会拒绝读取其内容。",
limits: "每次上传一个文件,最大 512 MiB,文件名 1–1024 字节;允许空文件。",
actions: {
upload: "上传文件",
@@ -35,37 +35,20 @@ export const files: TranslationShape = {
size: "大小",
created: "创建时间",
purpose: "Purpose",
- id: "File ID",
actions: "操作",
exactBytes: "{{bytes}} 字节",
unrecognized: "无法识别的文件",
unrecognizedHelp: "Core 返回了控制台无法识别的元数据,因此只显示 File ID。",
noMatchTitle: "没有匹配的已加载文件",
- noMatchDescription: "筛选只作用于已加载的文件。请加载更多或清除筛选。",
- loadFailed: "无法加载文件",
- refreshFailed: "列表刷新失败:{{reason}}",
moreFailed: "无法加载更多文件:{{reason}}",
},
empty: {
title: "还没有文件",
},
- unsupported: {
- title: "此 Core 不支持列出文件",
- description: "文件列表请求返回 HTTP {{status}}。",
- },
- upload: {
- uploading: "正在上传 {{name}}…",
- uploaded: "已上传 {{name}}",
- tooLarge: "{{name}} 超过 512 MiB 上传上限。",
- badName: "文件名须为 1–1024 个 UTF-8 字节,且不能包含 NUL 字符。",
- rejected: "Core 拒绝上传 {{name}}:{{reason}}",
- uncertain: "{{name}} 可能已上传到 Core。请先刷新列表确认,再决定是否重新上传。",
- },
delete: {
prompt: "删除 {{name}}?",
- consequences: "已复制到 Session 工作区的副本不受影响,已创建的 Session 也不受影响。通过 File ID 引用此文件的环境模板,之后再新建 Session 会失败。",
+ consequences: "已复制到 Session 工作区的副本不受影响,已创建的 Session 也不受影响。通过 File ID 引用此文件的 Environment 模板,之后再新建 Session 会失败。",
deleted: "已删除 {{name}}",
- missing: "{{name}} 已被删除。",
rejected: "Core 拒绝删除:{{reason}}",
uncertain: "未能确认 {{name}} 是否已删除。请先刷新列表确认,再决定是否重试。",
},
diff --git a/apps/web/src/i18n/locales/zh-CN/keys.ts b/apps/web/src/i18n/locales/zh-CN/keys.ts
index 0239c8c95..21b74a456 100644
--- a/apps/web/src/i18n/locales/zh-CN/keys.ts
+++ b/apps/web/src/i18n/locales/zh-CN/keys.ts
@@ -3,7 +3,7 @@ type TranslationShape = { [K in keyof T]: T[K] extends string ? string : Tran
export const keys: TranslationShape = {
page: {
title: "项目与密钥",
- help: "项目拥有一组资产:Agent、Session、Skill、环境模板、文件和 Vault。同一个项目的所有 API 密钥看到和使用的是同一批资产,项目之间互相隔离。归档项目会撤销它的全部密钥,资产保留。应用用这些项目 API 密钥调用 Agents API(/v1);登录控制台用的 Core 密钥与它们无关,也不在这里列出。",
+ help: "项目拥有一组资产:Agent、Session、Skill、Environment 模板、文件和 Vault。同一个项目的所有 API 密钥看到和使用的是同一批资产,项目之间互相隔离。归档项目会撤销它的全部密钥,资产保留。应用用这些项目 API 密钥调用 Agents API(/v1);登录控制台用的 Core 密钥与它们无关,也不在这里列出。",
create: "创建项目",
refresh: "刷新项目",
loading: "正在加载项目…",
@@ -111,7 +111,7 @@ export const keys: TranslationShape = {
loading: "正在读取 API 地址",
failed: "无法读取 API 地址。",
localOnly: "从其他机器调用前,请先把 OAC_PUBLIC_URL 设为它们能访问的地址。",
- model: "把 {{model}} 换成模型服务提供的模型名;也可以删掉 model 字段,使用本部署的默认模型配置。运行 Agent 需要模型服务:在每个请求里传入、保存在 Agent 上,或使用部署默认值。自托管 Session 不使用部署默认值。",
+ model: "把 {{model}} 换成模型提供商提供的模型名;也可以删掉 model 字段,使用本部署的默认模型配置。运行 Agent 需要模型提供商:在每个请求里传入、保存在 Agent 上,或使用部署默认值。自托管 Session 不使用部署默认值。",
keyPlaceholder: "<项目 API 密钥>",
projectKey: "把 OPENAI_API_KEY 设为这个项目签发的 API 密钥。密钥只在签发时显示一次;丢失后请签发新密钥。",
projectHelp: "应用用这个项目的 API 密钥调用 Agents API 的示例。控制台不会发送这些请求。",
@@ -130,7 +130,7 @@ export const keys: TranslationShape = {
assetsHelp: "来自 Core 对这个项目的汇总。点击数字查看对应资产。",
assetTypes: {
agents: "Agent",
- environment_templates: "环境模板",
+ environment_templates: "Environment 模板",
skills: "Skills",
files: "文件",
vaults: "Vault",
@@ -154,7 +154,7 @@ export const keys: TranslationShape = {
keysLabel: "{{name}} 的密钥",
keysLoading: "正在加载密钥…",
keysFailed: "无法加载密钥。",
- noKeys: "这个项目还没有密钥",
+ noKeys: "还没有密钥",
copyKeyId: "复制密钥 ID",
keyStatus: {
active: "有效",
@@ -187,7 +187,7 @@ export const keys: TranslationShape = {
id: "ID",
key: "密钥",
},
- empty: "暂无写操作记录",
+ empty: "还没有写操作记录",
loading: "正在加载写操作记录…",
failed: "无法加载写操作记录。",
moreFailed: "无法加载更多记录。",
@@ -204,8 +204,8 @@ export const keys: TranslationShape = {
types: {
agent: "Agent",
session: "Session",
- environment: "环境",
- environment_template: "环境模板",
+ environment: "Environment",
+ environment_template: "Environment 模板",
skill: "Skill",
skill_version: "Skill 版本",
file: "文件",
diff --git a/apps/web/src/i18n/locales/zh-CN/metrics.ts b/apps/web/src/i18n/locales/zh-CN/metrics.ts
index 057ae2cb2..f1fecaf15 100644
--- a/apps/web/src/i18n/locales/zh-CN/metrics.ts
+++ b/apps/web/src/i18n/locales/zh-CN/metrics.ts
@@ -37,10 +37,10 @@ export const metrics = {
readsFailedDescription: "部分 Session 列表或 Turn 读取失败,无法判断这段时间是否有 Agent 运行。请检查与 Core 的连接后刷新。",
errorFormula: "错误率 = 失败 ÷ 已结束(完成 + 失败 + 取消)的 Turn。",
tokenCoverage: "{{total}} 个 Turn 中有 {{reported}} 个上报了用量。",
- tokensUnreported: "该时间范围内没有 Turn 上报 Token 用量。",
+ tokensUnreported: "该时间范围内没有 Turn 上报 token 用量。",
inlineAgent: "内联 Agent",
title: "Agent 监控",
- description: "各项目 Agent 运行的请求、错误、耗时、Token 与工具调用。",
+ description: "各项目 Agent 运行的请求、错误、耗时、token 与工具调用。",
projectsFailed: "无法加载项目。",
loadFailed: "无法加载 Agent 指标:{{reason}}",
loading: "正在读取最近的 Turn…",
@@ -59,7 +59,7 @@ export const metrics = {
queueDetail: "平均排队 {{value}}",
p95: "P95 耗时",
p95Detail: "已结束 Turn 从开始到结束",
- tokens: "Token",
+ tokens: "token",
toolCalls: "工具调用",
toolsUnavailable: "未读取工具调用",
requestsSection: "请求",
@@ -68,16 +68,16 @@ export const metrics = {
nonFailed: "未失败",
failed: "失败",
latencyChart: "耗时 / {{bucket}}",
- tokenTrend: "各模型 Token 消耗 / {{bucket}}",
+ tokenTrend: "各模型 token 消耗 / {{bucket}}",
modelSection: "模型",
- modelSectionDetail: "所选时间范围内各模型的 Token 与请求数,图例中是各模型的合计。模型取自 Session 的 Agent 快照。",
+ modelSectionDetail: "所选时间范围内各模型的 token 与请求数,图例中是各模型的合计。模型取自 Session 的 Agent 快照。",
modelTrend: "各模型请求数 / {{bucket}}",
toolSection: "工具调用",
toolSectionDetail: "以 Session Item 记录的 Function、MCP、Shell、网页搜索与子 Agent 调用。",
toolTrend: "各工具调用次数 / {{bucket}}",
noToolCalls: "该时间范围内没有工具调用。",
agentSection: "按 Agent",
- agentSectionDetail: "所选时间范围内每个 Agent 的请求、错误与 Token。每个 Agent 属于一个项目。",
+ agentSectionDetail: "所选时间范围内每个 Agent 的请求、错误与 token。每个 Agent 属于一个项目。",
agent: "Agent",
sessions: "Session",
openAgent: "打开 Agent {{name}}",
@@ -88,7 +88,7 @@ export const metrics = {
},
keys: {
title: "按 API 密钥",
- help: "最近 {{range}} 内新建的 Session,按创建它的 API 密钥分组,来自 Core 的用量汇总。Token 是各 Session 的累计用量,只累加上报了用量的 Session。“未知”汇总没有创建记录的 Session。",
+ help: "最近 {{range}} 内新建的 Session,按创建它的 API 密钥分组,来自 Core 的用量汇总。token 是各 Session 的累计用量,只累加上报了用量的 Session。“未知”汇总没有创建记录的 Session。",
loading: "正在加载按密钥的用量…",
loadFailed: "无法加载按 API 密钥的用量:{{reason}}",
empty: "最近 {{range}} 内没有新建 Session。",
@@ -96,7 +96,7 @@ export const metrics = {
sessions: "Session",
running: "运行中",
failed: "失败",
- tokens: "Token",
+ tokens: "token",
coverage: "用量覆盖",
lastActive: "最近活跃",
unknown: "未知",
@@ -117,7 +117,7 @@ export const metrics = {
notOwner: "未持有执行归属",
status: { running: "运行中", degraded: "降级", unknown: "状态未知" },
slots: "执行并发",
- slotsHelp: "Core 同时最多执行的 Session 数。Turn、环境输入和文件读写共用这些槽位。",
+ slotsHelp: "Core 同时最多执行的 Session 数。Turn、Environment 输入和文件读写共用这些槽位。",
queued: "排队 Turn",
queuedHelp: "等待执行的 Turn。一部分在等空闲槽位,一部分在等所属 Session 的 daemon 连上。",
waitingForDaemon: "{{n}} 个等 daemon",
@@ -174,14 +174,14 @@ export const metrics = {
processed: "处理",
failed: "失败",
empty: "Core 没有报告后台任务。",
- names: { scheduler: "执行调度", runtime_sampler: "运行时采样", history_cleanup: "历史清理", audit_cleanup: "审计清理" },
+ names: { scheduler: "执行调度", runtime_sampler: "Runtime 采样", history_cleanup: "历史清理", audit_cleanup: "审计清理" },
health: { ok: "正常", failing: "失败", stopped: "已停止", unknown: "未知" },
},
},
sandbox: {
configurationGeneration: "沙箱配置代次",
title: "沙箱监控",
- description: "所有项目的托管运行时随时间的状态、CPU 和内存。节点容量见节点页。",
+ description: "所有项目的托管 Runtime 随时间的状态、CPU 和内存。节点容量见节点页。",
cloudDescription: "Core 在 E2B 云端持有的沙箱,以及各项目的托管 Runtime 观测。",
runtimeDialog: {
openLabel: "查看 {{name}} 的沙箱",
@@ -193,7 +193,7 @@ export const metrics = {
title: "E2B 云端",
counts: "运行数量来自 Core 的 E2B 分配记录;下方托管 Runtime 总数统计各项目的托管观测记录,包含所有已报告的生命周期状态。两者覆盖范围不同,并分别刷新。",
help: "这个部署的沙箱在 E2B 的云端运行,没有需要管理的机器。数量是 Core 自己记录的、放在 E2B 上的沙箱。",
- manage: "沙箱后端",
+ manage: "沙箱提供商",
running: "运行中的沙箱",
runningHelp: "Core 当前在 E2B 上占用的沙箱。",
pending: "启动或切换中",
@@ -208,25 +208,25 @@ export const metrics = {
status: "状态",
notSetUpTitle: "还没有设置沙箱",
setUp: "设置沙箱",
- runtimeSection: "托管运行时",
- runtimeSectionDetail: "Core 托管沙箱的 CPU、内存与 Token 历史。其他环境不上报运行时指标。",
- noRuntimeTitle: "没有托管沙箱",
- noRuntimeDescription: "没有使用 Core 托管环境的 Session。",
- runtimeLoading: "正在加载运行时观测…",
- runtimeUnavailable: "运行时观测不可用。{{reason}}",
+ runtimeSection: "托管 Runtime",
+ runtimeSectionDetail: "Core 托管沙箱的 CPU、内存与 token 历史。其他 Environment 不上报 Runtime 指标。",
+ noRuntimeTitle: "还没有托管沙箱",
+ noRuntimeDescription: "还没有 Session 使用 Core 托管 Environment。",
+ runtimeLoading: "正在加载 Runtime 观测…",
+ runtimeUnavailable: "Runtime 观测不可用。{{reason}}",
runtimeStale: "刷新失败,显示的是上次的观测。{{reason}}",
- runtimePartial: "有 {{unread}} 个运行时超过读取上限、{{failed}} 个读取失败,未读取 Session 详情,这些行只显示 Session ID。",
+ runtimePartial: "有 {{unread}} 个 Runtime 超过读取上限、{{failed}} 个读取失败,未读取 Session 详情,这些行只显示 Session ID。",
cpu: "CPU",
cores: "{{value}} 核",
memory: "内存",
disk: "磁盘",
- runtimeList: "托管运行时",
- search: "搜索运行时",
+ runtimeList: "托管 Runtime",
+ search: "搜索 Runtime",
searchPlaceholder: "搜索 Session、Agent、节点或 ID",
searchPlaceholderCloud: "搜索 Session、Agent 或 ID",
session: "Session",
uptime: "运行时长",
- tokens: "Token",
+ tokens: "token",
tokenSplit: "输入 {{input}} · 输出 {{output}}",
recordedCompute: "记录的计算状态",
recordedComputeHelp: "Core 记录的计算阶段,与 Runtime 观测分别读取,刷新时可能短暂不同。",
@@ -245,8 +245,8 @@ export const metrics = {
memory: "内存 / {{bucket}}",
memoryUsed: "已使用",
memoryLimit: "配额上限",
- historyUnavailable: "运行时历史不可用。",
- historyFailed: "无法读取运行时历史。{{reason}}",
+ historyUnavailable: "Runtime 历史不可用。",
+ historyFailed: "无法读取 Runtime 历史。{{reason}}",
historyBudget: "图表最多覆盖 {{limit}} 个 Session。",
historyMixed: "各 Session 返回的时间桶宽度不一致。",
},
diff --git a/apps/web/src/i18n/locales/zh-CN/navigation.ts b/apps/web/src/i18n/locales/zh-CN/navigation.ts
index 55afa7f55..6a3eb847f 100644
--- a/apps/web/src/i18n/locales/zh-CN/navigation.ts
+++ b/apps/web/src/i18n/locales/zh-CN/navigation.ts
@@ -15,31 +15,23 @@ export const navigation = {
sessions: "Session 日志",
session: "Session",
agents: "Agent",
- templates: "环境模板",
+ templates: "Environment 模板",
skills: "Skills",
files: "文件",
vaults: "Vault",
projects: "项目与密钥",
nodes: "节点",
- sandboxBackend: "沙箱后端",
+ sandboxBackend: "沙箱提供商",
settings: "设置",
},
settings: {"sandbox": "沙箱与调度", "storage": "工作区存储", "models": "模型与凭据", "service": "服务与部署"},
showGettingStarted: "显示新手引导",
skipToContent: "跳到主要内容",
- configureCore: "配置 OpenAgentCore 连接",
- coreApi: "Core API",
- coreState: "Core API {{state}}",
- coreConnecting: "连接中…",
- coreReady: "API 已就绪",
- coreFailed: "失败",
theme: "主题",
lightTheme: "浅色主题",
darkTheme: "深色主题",
language: "语言",
english: "English",
chinese: "简体中文",
- switchToChinese: "切换到简体中文",
- switchToEnglish: "切换到英文",
appearanceSettings: "语言和外观",
} as const;
diff --git a/apps/web/src/i18n/locales/zh-CN/onboarding.ts b/apps/web/src/i18n/locales/zh-CN/onboarding.ts
index 2d18a03e1..96f481de0 100644
--- a/apps/web/src/i18n/locales/zh-CN/onboarding.ts
+++ b/apps/web/src/i18n/locales/zh-CN/onboarding.ts
@@ -1,7 +1,7 @@
export const onboarding = {
stage: {
login: { title: "一个 Core,承载所有 Agent。", body: "连接你的机器,运行你的 Agent,在一个控制台里看清每一个 Session。" },
- orbit: "Core 和它管理的一切:Agent、Session、Skills、Vault、文件、环境模板和机器",
+ orbit: "Core 和它管理的一切:Agent、Session、Skills、Vault、文件、Environment 模板和机器",
},
tour: {
label: "认识控制台",
@@ -17,7 +17,7 @@ export const onboarding = {
title: "服务健康吗?哪里在出错?",
points: [
"概览:服务状态、运行中的 Session、沙箱容量,以及需要你处理的 Session。",
- "Core、Agent、沙箱监控:执行队列、请求与错误、节点和运行时。",
+ "Core、Agent、沙箱监控:执行队列、请求与错误、节点和 Runtime。",
"Session 日志:每个 Session 的对话、追踪和 Turn,只读。",
],
},
@@ -25,7 +25,7 @@ export const onboarding = {
name: "资源",
title: "应用创建的一切,都在这里。",
points: [
- "Agent、环境模板和 Skills,每一项都记录由谁创建。",
+ "Agent、Environment 模板和 Skills,每一项都记录由谁创建。",
"文件和 Vault;凭据只写入、不回显。",
"查看任意资产,或安全地删除。",
],
diff --git a/apps/web/src/i18n/locales/zh-CN/overview.ts b/apps/web/src/i18n/locales/zh-CN/overview.ts
index 567f83d28..c76ef271d 100644
--- a/apps/web/src/i18n/locales/zh-CN/overview.ts
+++ b/apps/web/src/i18n/locales/zh-CN/overview.ts
@@ -3,7 +3,7 @@ export const overview = {
title: "沙箱重置进行中",
auto: "等待 Session 结束和资源清理",
force: "强制重置 · 正在清理资源",
- body: "Core 正在清空托管沙箱后端。重置结束前无法启动新的托管 Session,自托管 Session 不受影响。",
+ body: "Core 正在清理托管沙箱提供商。重置结束前无法启动新的托管 Session,自托管 Session 不受影响。",
view: "查看重置",
},
title: "概览",
@@ -29,11 +29,11 @@ export const overview = {
setup: "设置沙箱",
addNode: "添加节点",
nodes: "打开节点",
- backend: "打开沙箱后端",
+ backend: "打开沙箱提供商",
},
model: {
title: "设置默认模型配置",
- body: "为默认 Harness 设置模型服务地址和 API 密钥,让 Agent 可以调用模型。应用也可以在请求或 Agent 上指定其他模型服务。",
+ body: "为默认 Harness 设置模型提供商地址和 API 密钥,让 Agent 可以调用模型。应用也可以在请求或 Agent 上指定其他模型提供商。",
open: "打开设置",
},
key: {
@@ -66,7 +66,7 @@ export const overview = {
runningHelp: "所有项目中正在运行的 Session,来自 Core 的用量汇总。",
summaryUnavailable: "用量汇总不可用",
slots: "沙箱容量",
- slotsHelp: "活跃沙箱数,相对于在线宿主机的活跃上限。",
+ slotsHelp: "活跃沙箱数,相对于在线主机的活跃上限。",
cloudRunning: "运行中的沙箱",
cloudRunningHelp: "Core 当前在 E2B 云端占用的沙箱。E2B 没有可供 Core 读取的上限。",
attention: "需要处理",
@@ -81,7 +81,6 @@ export const overview = {
attentionSplit: "过去 24 小时:失败 {{failed}},等待调用方 {{waiting}}",
},
errors: {
- load: "无法加载概览:{{reason}}",
summary: "无法加载用量汇总:{{reason}}",
projects: "无法加载项目:{{reason}}",
},
@@ -111,7 +110,7 @@ export const overview = {
},
nodeHealth: {
available: "可用",
- degraded: "提供方未就绪",
+ degraded: "沙箱提供商未就绪",
offline: "离线",
},
fleet: {
@@ -136,12 +135,12 @@ export const overview = {
name: "E2B 云端",
open: "E2B 云端,{{running}} 个运行中的沙箱",
running: "{{count}} 个运行中",
- openBackend: "沙箱后端",
+ openBackend: "沙箱提供商",
},
},
projects: {
title: "按项目",
- help: "每个项目的有效密钥和全部 Session,来自 Core 的用量汇总;资产数量在项目详情里。Token 只累加上报了用量的 Session;覆盖率是上报用量的 Session 所占比例。用量是每个 Session 的累计值,不作为计费依据。",
+ help: "每个项目的有效密钥和全部 Session,来自 Core 的用量汇总;资产数量在项目详情里。token 只累加上报了用量的 Session;覆盖率是上报用量的 Session 所占比例。用量是每个 Session 的累计值,不作为计费依据。",
manage: "项目与密钥",
open: "打开 {{name}}",
keys: "有效密钥",
@@ -149,18 +148,11 @@ export const overview = {
unavailable: "用量汇总不可用。",
loading: "正在加载用量…",
emptyTitle: "还没有项目",
- assets: "资产",
sessions: "Session",
- agents: "Agent",
- templates: "环境模板",
- skills: "Skills",
- files: "文件",
- vaults: "Vault",
- total: "总数",
running: "运行中",
waiting: "等待调用方",
failed: "失败",
- tokens: "Token",
+ tokens: "token",
coverage: "用量覆盖",
lastActive: "最近活跃",
tokenDetail: "输入 {{input}} · 输出 {{output}} · 缓存 {{cached}} · 推理 {{reasoning}}",
@@ -181,10 +173,7 @@ export const overview = {
emptyOlder: "过去 24 小时内活跃的 Session 都没有失败或等待调用方。Session 日志中还有 {{count}} 个更早的 Session 需要处理。", emptyOlder_one: "过去 24 小时内活跃的 Session 都没有失败或等待调用方。Session 日志中还有 {{count}} 个更早的 Session 需要处理。", emptyOlder_other: "过去 24 小时内活跃的 Session 都没有失败或等待调用方。Session 日志中还有 {{count}} 个更早的 Session 需要处理。",
session: "Session",
status: "状态",
- reason: "原因",
lastActive: "最近活跃",
- noError: "未上报错误信息",
- requiredActions: "待完成操作:{{count}}",
},
sessions: {
failed: "失败",
diff --git a/apps/web/src/i18n/locales/zh-CN/pages.ts b/apps/web/src/i18n/locales/zh-CN/pages.ts
index a1b45e879..c0cabc288 100644
--- a/apps/web/src/i18n/locales/zh-CN/pages.ts
+++ b/apps/web/src/i18n/locales/zh-CN/pages.ts
@@ -1,10 +1,6 @@
export const pages = {
- dashboard: {
- agents: "Agent", sessions: "Session", runtime: "运行时", connectionSettings: "连接设置",
- backend: { label: "OpenAgentCore 后端未就绪。打开 Docker 启动指南", title: "OpenAgentCore 后端未就绪", detail: "Web 正在运行,但本地 /v1 代理无法连接已就绪的 Core{{failure}}。请启动 Docker 后端,然后测试连接。", openGuide: "打开启动指南", networkFailure: "网络故障", collectionFailed: "数据收集请求失败。" },
- },
agents: { title: "Agent", subtitle: "各项目保存的 Agent,及其模型、Harness、工具和用量。" },
sessions: { title: "Session", subtitle: "对话", recover: "恢复持久状态" },
- templates: { title: "环境模板", subtitle: "用于托管 Session 的可复用配置。", newTemplate: "新建模板" },
- vaults: { title: "Vault", subtitle: "由 Core 管理、仅用于精确 HTTPS MCP 目标的静态 bearer Credential。", refresh: "刷新 Vault", create: "新建 Vault" },
+ templates: { title: "Environment 模板", subtitle: "用于托管 Session 的可复用配置。" },
+ vaults: { title: "Vault", subtitle: "由 Core 管理、仅用于精确 HTTPS MCP 目标的静态 bearer Credential。", refresh: "刷新 Vault" },
} as const;
diff --git a/apps/web/src/i18n/locales/zh-CN/sandbox-navigation.ts b/apps/web/src/i18n/locales/zh-CN/sandbox-navigation.ts
index 72d651c45..8e8ab7544 100644
--- a/apps/web/src/i18n/locales/zh-CN/sandbox-navigation.ts
+++ b/apps/web/src/i18n/locales/zh-CN/sandbox-navigation.ts
@@ -1,6 +1,6 @@
export const sandboxNavigation = {
"title": "沙箱配置",
- "help": "在这里管理部署后端、沙箱规格和重置;主机在节点页面管理。",
+ "help": "在这里管理部署的沙箱提供商、沙箱规格和重置;主机在节点页面管理。",
"open": "管理沙箱配置",
"back": "返回设置",
"nodes": "打开节点",
diff --git a/apps/web/src/i18n/locales/zh-CN/sandbox.ts b/apps/web/src/i18n/locales/zh-CN/sandbox.ts
index 8c097db53..14a73871b 100644
--- a/apps/web/src/i18n/locales/zh-CN/sandbox.ts
+++ b/apps/web/src/i18n/locales/zh-CN/sandbox.ts
@@ -3,7 +3,7 @@ export const sandbox = {
"Current usage exceeds a saved limit. Existing sandboxes are preserved; new placements wait for capacity.": "当前用量超过已保存上限。已有沙箱保留;新的分配需等待容量。",
"The idle policy applies to the whole deployment. Each node's active and retained limits are set on Nodes with Edit node.": "空闲策略对整个部署生效;每个节点的活跃与保留上限在节点页用“编辑节点”设置。",
"Reset": "重置",
- "Clear this configuration to choose a different backend. Hosted Sessions are archived permanently.": "清除当前配置后才能选择其他后端。托管 Session 将被永久归档。",
+ "Clear this configuration to choose a different backend. Hosted Sessions are archived permanently.": "清除当前配置后才能选择其他沙箱提供商。托管 Session 将被永久归档。",
"Idle before suspension (seconds)": "空闲多久后挂起(秒)",
"Deployment-wide: 30–86,400 seconds. Applies to existing and new running sandboxes without restarting them. Suspension already in progress and snapshot retention are unchanged. Capacity pressure may suspend an idle sandbox after 15 seconds.": "整个部署统一生效:30–86,400 秒。适用于现有和新建的运行中沙箱,无需重启。已经开始的挂起和快照保留期不变。容量紧张时,沙箱空闲 15 秒后可能提前挂起。",
"Enter a whole number from 30 to 86,400.": "请输入 30 到 86,400 之间的整数。",
@@ -15,11 +15,11 @@ export const sandbox = {
"Root disk {{root}} · external workspace": "根磁盘 {{root}} · 外部工作区",
"Workspace storage is configured by the operator; no capacity quota is enforced.": "工作区存储由运维人员配置;未实施容量配额。",
- "E2B provider": "E2B 服务商",
- "Other E2B-compatible provider": "其他兼容 E2B 的服务商",
+ "E2B provider": "E2B 提供商",
+ "Other E2B-compatible provider": "其他兼容 E2B 的提供商",
"Loading templates…": "正在读取模板…",
- "Could not load templates. Check the key and provider connection.": "无法读取模板,请检查 Key 和服务商连接。",
- "No templates are visible to this key.": "这个 Key 下没有可见模板。",
+ "Could not load templates. Check the key and provider connection.": "无法读取模板,请检查密钥和提供商连接。",
+ "No templates are visible to this key.": "这个密钥下没有可见模板。",
"Template": "模板",
"Select a template": "选择模板",
"Loading ready builds…": "正在读取可用构建…",
@@ -27,7 +27,7 @@ export const sandbox = {
"This template has no ready builds.": "这个模板没有 ready 构建。",
"Select a ready build": "选择 ready 构建",
"Core validates the exact ready build again when you save.": "保存时 Core 会再次校验所选的 ready 构建。",
- "The selected provider supplies a default. You can edit it for a compatible endpoint.": "服务商已带出默认地址,也可以修改为兼容接口。",
+ "The selected provider supplies a default. You can edit it for a compatible endpoint.": "提供商已带出默认地址,也可以修改为兼容接口。",
...firstRun,
"Hosted Sessions will be archived permanently. Deployment configuration and node registrations will be cleared. Unsaved workspace contents may be lost.": "托管 Session 将归档且无法恢复,部署配置与节点注册将清除。未保存的工作区内容可能丢失。",
"What reset affects": "重置影响范围",
@@ -58,22 +58,18 @@ export const sandbox = {
"Rollout state is unconfirmed. These are the last confirmed observations.": "配置更新状态尚未确认。当前显示的是上次确认的状态。",
"Review affected nodes for preparation errors, incompatible node software or an unconfirmed connection. Qualified earlier generations may still serve work.": "请检查相关节点的准备错误、不兼容的节点程序或尚未确认的连接。符合条件的旧代次仍可提供服务。",
"Existing sandboxes keep their configuration generation. Saving does not move them or prove the target is ready.": "现有沙箱保留所属配置代次。保存不会迁移沙箱,也不代表目标配置已就绪。",
- "Changes keep this backend and existing Sessions and nodes. Core prepares the new target for future work; placement may continue on qualified earlier generations.": "修改会保留当前后端、现有 Session 和节点。Core 为后续任务准备新目标配置,期间仍可能将任务分配到符合条件的旧代次。",
+ "Changes keep this backend and existing Sessions and nodes. Core prepares the new target for future work; placement may continue on qualified earlier generations.": "修改会保留当前沙箱提供商、现有 Session 和节点。Core 为后续任务准备新目标配置,期间仍可能将任务分配到符合条件的旧代次。",
"In-place upgrades from older project versions are not supported. Reinstall using the current version. Existing data is not removed automatically.": "不支持旧项目版本原地升级,请使用当前版本重新安装。现有数据不会自动删除。",
"The saved serving generation is not proof that this node is online, ready or has free capacity.": "已保存的服务代次不代表节点当前在线、已就绪或有空闲容量。",
"Node observations are from an earlier configuration generation. Refreshing does not change their owned sandboxes.": "节点观测来自较早的配置代次。刷新不会改变节点所属的沙箱。",
"Leave blank to keep the saved key. Any key you enter is verified as a replacement, even if unchanged.": "留空可保留已保存的密钥。填写的密钥都会作为替换密钥进行验证,即使内容未变。",
"These limits apply to the selected configuration generation. Existing sandboxes keep their limits. Concurrency is set per node.": "这些限制适用于所选配置代次。现有沙箱保留原有限制。并发数量按节点设置。",
"The target Runtime release. Existing sandboxes keep their owned release while nodes prepare the target.": "目标 Runtime 版本。节点准备目标版本时,现有沙箱仍使用其所属版本。",
- "This E2B key cannot manage the retained deployment. Reset before changing teams.": "此 E2B 密钥无法管理当前保留的部署。更换团队前请先重置。",
- "The E2B API key was rejected. The saved configuration is unchanged.": "E2B API 密钥被拒绝。已保存的配置未改变。",
- "Select a ready immutable E2B template build with matching resources.": "请选择已就绪且资源匹配的不可变 E2B 模板构建。",
- "E2B verification could not be confirmed. Refresh before submitting again.": "无法确认 E2B 验证结果。请刷新后再提交。",
"Cancel editing to use Reset deployment. This change requires an explicit reset; the saved configuration is unchanged.": "取消编辑后可使用“重置部署”。此更改需要明确重置;已保存的配置未改变。",
"Sandbox state is unconfirmed. Refresh before issuing a node command.": "沙箱状态尚未确认。请刷新后再生成节点命令。",
"Change resources": "修改资源",
- "One provider serves this deployment. Reset it before choosing a different backend.": "整个部署使用一个运行后端。请先重置,再选择其他后端。",
+ "One provider serves this deployment. Reset it before choosing a different backend.": "整个部署使用一个沙箱提供商。请先重置,再选择其他沙箱提供商。",
"Reset sandbox deployment?": "重置沙箱部署?",
"Reset deployment": "重置部署",
"Reset in progress": "正在重置",
@@ -96,26 +92,18 @@ export const sandbox = {
"Cancel reset?": "取消重置?",
"Stop the reset and allow new hosted Sessions again. Sessions already archived stay archived and cannot be resumed.": "停止重置并重新允许创建托管 Session。已归档的 Session 会保持归档,无法恢复运行。",
"Reset archives this deployment's hosted Sessions. Archived Sessions cannot be resumed. History, Files and Artifacts are kept; self-hosted Sessions are unchanged.": "重置会归档此部署的托管 Session。已归档的 Session 无法恢复运行。历史记录、File 和 Artifact 会保留;自托管 Session 不受影响。",
- "After cleanup, Core clears the provider and saved E2B credential, retires nodes and enrollment commands, and returns to setup.": "清理完成后,Core 会清除运行后端和保存的 E2B 凭据,作废节点及注册命令,然后返回配置流程。",
+ "After cleanup, Core clears the provider and saved E2B credential, retires nodes and enrollment commands, and returns to setup.": "清理完成后,Core 会清除沙箱提供商和保存的 E2B 凭据,作废节点及注册命令,然后返回配置流程。",
"Force immediately cancels remaining work. Offline resources can still block cleanup.": "强制重置会立即取消剩余任务。离线资源仍可能阻止清理完成。",
"Clear hosted work": "清理托管任务",
"Auto — let busy work finish": "自动 — 等待忙碌任务完成",
"Idle, suspended and queued Sessions are archived immediately. Running or waiting Turns and file writes may finish until the deadline; then Core forces the rest.": "空闲、挂起和排队中的 Session 会立即归档。运行中或等待中的 Turn 及文件写入可在截止时间前继续;之后 Core 会强制清理剩余任务。",
- "Force remaining work after (seconds)": "多久后强制清理剩余任务(秒)",
"Default: 1 hour. Choose a whole number from 300 to 86400 seconds (5 minutes to 24 hours).": "默认 1 小时。请输入 300 到 86400 秒之间的整数(5 分钟到 24 小时)。",
"Enter a whole number from 300 to 86400 seconds.": "请输入 300 到 86400 秒之间的整数。",
"Force — cancel remaining work now": "强制 — 立即取消剩余任务",
"Sandbox state changed. Close this dialog and review the current state.": "沙箱状态已改变。请关闭对话框并查看当前状态。",
"Node state could not be read": "无法读取节点状态",
"Node enrollment is paused while reset is in progress.": "重置过程中暂停注册节点。",
- "Unsaved workspace contents may be lost.": "尚未保存的工作区内容可能丢失。",
- "Core has a newer sandbox configuration. Refresh and review it before submitting again.": "Core 的沙箱配置已更新。请刷新并检查后再提交。",
"Reset the sandbox deployment before changing this configuration.": "请先重置沙箱部署,再更改此配置。",
- "A sandbox reset is in progress. Refresh to see its current progress.": "沙箱正在重置。请刷新查看当前进度。",
- "The sandbox deployment is not configured. Refresh to start setup.": "沙箱部署尚未配置。请刷新以开始配置。",
- "Hosted resources remain. Wait for confirmed cleanup before changing the configuration.": "仍有托管资源。请等待 Core 确认清理完成后再修改配置。",
- "Change provider or resources": "修改运行后端或资源",
- "Sandbox backend": "沙箱后端",
"Core records these sandboxes as suspended. Their next Turn requests a resume when compatible capacity is available. They count toward the retained limit, not the active one.": "Core 将这些沙箱记录为已挂起。下一个 Turn 会在兼容容量可用时请求恢复。它们占用保留名额,不占活跃名额。",
"The most sandboxes this node holds at once: starting, running and suspended.": "这台节点同时最多容纳的沙箱数,包括启动中、运行中和已挂起的。",
"Edit node": "编辑节点",
@@ -129,9 +117,6 @@ export const sandbox = {
"Enter a shorter name.": "名称太长了,请缩短。",
"Enter a whole number from 1 to 1,000,000.": "请输入 1 到 1,000,000 之间的整数。",
"Enter at least the number of sandboxes at once.": "不能少于同时运行的沙箱数。",
- "E2B runs this deployment's sandboxes in its cloud. There are no machines to add.": "这个部署的沙箱由 E2B 在云端运行,不需要添加机器。",
- "Saving does not migrate Sessions or resume placement automatically.": "保存不会迁移 Session,也不会自动恢复分配。",
- "Use an HTTPS Core origin reachable from every node and sandbox guest, without a path or credentials. The console URL may be different.": "请输入所有节点和沙箱都能访问的 HTTPS Core 源地址,不含路径或凭据。此地址可能与控制台地址不同。",
"Needs attention": "需要检查",
"Done": "完成",
"Copy command": "复制命令",
@@ -162,7 +147,7 @@ export const sandbox = {
"SELinux is not enforcing": "SELinux 不是 enforcing 模式",
"In sudo mode, one Core per host: a host already running a sudo-mode node for another Core is refused.": "sudo 模式下,每台主机只能接入一个 Core:已为其他 Core 运行 sudo 模式节点的主机会被拒绝。",
"If the command is interrupted or the download stalls, run it again: unfinished downloads restart, and verified files are reused.": "如果命令被中断或下载卡住,重新运行即可:未完成的下载会从头开始,已校验的完整文件会复用。",
- "What the sandbox backend needs on the host; the installer checks it and names anything missing": "沙箱后端在主机上所需的条件;安装程序会检查并指出缺少的项",
+ "What the sandbox backend needs on the host; the installer checks it and names anything missing": "沙箱提供商在主机上所需的条件;安装程序会检查并指出缺少的项",
"Copy command with --force": "复制命令(--force)",
"Checking this installation's public URL…": "正在检查这个安装的公网地址…",
"The installation couldn't be read, so no command can be issued.": "无法读取安装信息,暂时不能生成命令。",
@@ -187,7 +172,7 @@ export const sandbox = {
"Registration progress": "注册进度",
"Registered · {{name}}": "已注册 · {{name}}",
"{{name}} · Connected": "{{name}} · 已连接",
- "Next: set a default model provider.": "下一步:设置默认模型服务。",
+ "Next: set a default model provider.": "下一步:设置默认模型提供商。",
"Next: finish Getting started.": "下一步:完成新手引导。",
"Open Settings": "打开设置",
"Open Overview": "打开概览",
@@ -202,14 +187,9 @@ export const sandbox = {
"The node registered but its service hasn't reached Core.": "节点已注册,但节点服务还没有连上 Core。",
"The node service keeps retrying while Core is unavailable, and stops once the node is removed.": "Core 不可用时,节点服务会一直重试;节点被移除后才会停止。",
"Check the log on the host:": "在主机上查看日志:",
- "Advanced network settings": "高级网络设置",
-
- "System": "系统",
- "System navigation": "系统导航",
- "Deployment provider, runtime nodes and Session allocations.": "管理部署后端、运行节点和 Session 资源分配。",
"Refresh sandbox state": "刷新沙箱状态",
"Loading sandbox state…": "正在加载沙箱状态…",
- "Provider": "运行后端",
+ "Provider": "沙箱提供商",
"Refresh failed; showing the last loaded state.": "刷新失败,显示的是上次加载的状态。",
"Couldn't confirm the sandbox change": "沙箱更改未能确认",
"Sandbox state couldn't be read": "无法读取沙箱状态",
@@ -227,7 +207,7 @@ export const sandbox = {
"Cleanup pending": "待清理",
"Actions": "操作",
"Remove": "移除",
- "No nodes registered. Add a node to provide hosted capacity.": "尚未注册节点。添加节点后即可提供托管容量。",
+ "No nodes yet. Add a node to provide hosted capacity.": "还没有节点。添加节点后即可提供托管容量。",
"Remove node": "移除节点",
"Core rejects removal while allocations or retained resources remain.": "节点仍有资源分配或保留资源时,Core 会拒绝移除。",
"Confirm removal": "确认移除",
@@ -237,35 +217,19 @@ export const sandbox = {
"Recorded state": "已记录状态",
"Recorded compute": "已记录计算状态",
"In this state": "当前状态持续",
- "Since {{time}}": "{{time}}起",
- "No sandbox allocations.": "暂无沙箱资源分配。",
+ "No sandbox allocations yet.": "还没有沙箱资源分配。",
"Add node": "添加节点",
"One-time enrollment command": "一次性注册命令",
"Offline": "离线",
- "Provider not ready": "提供方未就绪",
+ "Provider not ready": "沙箱提供商未就绪",
"Last seen": "最近心跳",
"Never": "尚无记录",
"Unavailable": "不可用",
"Available": "可用",
- "Sandbox node": "沙箱节点",
- "Automatic placement": "自动分配",
"available": "可用",
"unavailable": "不可用",
- "Loading nodes…": "正在加载节点…",
- "Retry directory": "重新加载节点目录",
- "No nodes are registered.": "尚未注册节点。",
- "Node directory unavailable. Automatic placement remains available; an explicit choice is never replaced automatically.": "节点目录不可用。仍可使用自动分配;明确选择的节点不会被自动替换。",
- "Loading placement…": "正在加载分配信息…",
- "Recorded allocation": "已记录分配状态",
- "Refresh placement": "刷新分配信息",
- "No hosted placement": "无托管分配",
- "Retry placement": "重新加载分配信息",
- "Sandbox placement could not be loaded.": "无法加载沙箱分配信息。",
"The sandbox request failed. Refresh to check the current state before trying again.": "沙箱请求失败。重试前请刷新并检查当前状态。",
"Core did not confirm node removal. Refresh to check its state.": "Core 未确认节点已移除。请刷新以检查状态。",
- "The node has active allocations or retained resources. Clear allocations, snapshots, reservations and pending cleanup before removal.": "节点仍有活跃分配或保留资源。请先清理资源分配、快照、预留资源和待清理项,再移除节点。",
- "The selected sandbox node is unavailable or has no capacity.": "所选沙箱节点不可用或容量不足。",
- "Sign in to the console again to access sandbox management.": "请重新登录控制台以访问沙箱管理。",
"Core rejected the sandbox change": "Core 拒绝了此次沙箱更改",
"Core rejected the sandbox configuration.": "Core 拒绝了这个沙箱配置。",
"The console configuration could not be read. Refresh to try again.": "无法读取控制台配置。请刷新重试。",
@@ -290,19 +254,19 @@ export const sandbox = {
"Node disconnected": "节点已断开",
"Reconnect the assigned node, then refresh. Existing resources stay assigned to this node; Core does not move the Session automatically.": "请重新连接已分配节点,然后刷新。现有资源仍归属该节点;Core 不会自动迁移 Session。",
"Sandbox resource missing": "沙箱资源缺失",
- "Check the provider resource on the assigned node. Core retains the ownership record and does not create a replacement automatically.": "请检查已分配节点上的后端资源。Core 会保留归属记录,不会自动创建替代资源。",
+ "Check the provider resource on the assigned node. Core retains the ownership record and does not create a replacement automatically.": "请检查已分配节点上的沙箱提供商资源。Core 会保留归属记录,不会自动创建替代资源。",
"Compute state unconfirmed": "计算状态未确认",
- "Check the assigned node and its provider, then refresh. The last recorded compute state does not confirm that execution is running.": "请检查已分配节点及其后端,然后刷新。上次记录的计算状态不能确认执行仍在运行。",
+ "Check the assigned node and its provider, then refresh. The last recorded compute state does not confirm that execution is running.": "请检查已分配节点及其沙箱提供商,然后刷新。上次记录的计算状态不能确认执行仍在运行。",
"Sandbox ownership mismatch": "沙箱归属不一致",
"Reconcile the assigned resource and its ownership record before resuming execution.": "请核对已分配资源及其归属记录,再恢复执行。",
- "Sandbox provider unavailable": "沙箱后端不可用",
- "Restore the provider on the assigned node, then refresh. Running the install command again on the host checks its requirements and names the fix; a manually registered node logs the local error.": "请恢复已分配节点上的运行后端,然后刷新。在该主机上重新运行安装命令,会检查主机要求并指出修复方法;手动注册的节点会在日志中记录本地错误。",
+ "Sandbox provider unavailable": "沙箱提供商不可用",
+ "Restore the provider on the assigned node, then refresh. Running the install command again on the host checks its requirements and names the fix; a manually registered node logs the local error.": "请恢复已分配节点上的沙箱提供商,然后刷新。在该主机上重新运行安装命令,会检查主机要求并指出修复方法;手动注册的节点会在日志中记录本地错误。",
"Sandbox state needs attention": "沙箱状态需要检查",
"Inspect the assigned node and resource, then refresh.": "请检查已分配节点和资源,然后刷新。",
"Host unsupported": "主机不满足要求",
- "The host lacks a capability its sandbox provider requires. Running the install command again on the host checks its requirements and names the fix; a manually registered node logs the local error.": "主机缺少沙箱后端所需的能力。在该主机上重新运行安装命令,会检查主机要求并指出修复方法;手动注册的节点会在日志中记录本地错误。",
- "Provider files missing": "后端文件缺失",
- "Pinned provider files are missing or fail their checksum. Run the install command again.": "指定版本的后端文件缺失或校验不通过。请重新运行安装命令。",
+ "The host lacks a capability its sandbox provider requires. Running the install command again on the host checks its requirements and names the fix; a manually registered node logs the local error.": "主机缺少沙箱提供商所需的能力。在该主机上重新运行安装命令,会检查主机要求并指出修复方法;手动注册的节点会在日志中记录本地错误。",
+ "Provider files missing": "沙箱提供商文件缺失",
+ "Pinned provider files are missing or fail their checksum. Run the install command again.": "指定版本的沙箱提供商文件缺失或校验不通过。请重新运行安装命令。",
"Runtime download failed": "Runtime 下载失败",
"Runtime files could not be downloaded or verified. Check the node's network access and the configured Runtime release.": "Runtime 文件下载或验证失败。请检查节点网络连接及配置的 Runtime 发布版本。",
"Runtime image missing": "缺少 Runtime 镜像",
@@ -311,55 +275,33 @@ export const sandbox = {
"The host has less CPU or memory than one sandbox needs. Use a bigger host or a smaller sandbox size.": "主机的 CPU 或内存不够运行一个沙箱。请换一台更大的主机,或调小沙箱规格。",
"Connecting to this console's Core…": "正在连接此控制台的 Core…",
"Saving sandbox change…": "正在保存沙箱更改…",
- "Refresh sandbox state to confirm whether setup was saved before submitting again.": "再次提交前,请刷新沙箱状态以确认配置是否已保存。",
"Set up hosted sandboxes": "配置托管沙箱",
- "Sandbox provider": "沙箱后端",
- "Choose a provider": "选择运行后端",
- "Core origin reachable from nodes and guests": "节点和沙箱可访问的 Core 地址",
- "Initialize sandbox deployment": "初始化沙箱部署",
"Copied": "已复制",
"Select the command above and copy it manually.": "请选择上方命令并手动复制。",
- "Choose the next provider": "选择下一个运行后端",
- "Where to run sandboxes": "沙箱运行位置",
- "Choose where to run": "选择运行位置",
"E2B cloud": "E2B 云端",
"Own machines": "自有机器",
"Core creates E2B sandboxes directly. No node enrollment is needed.": "Core 直接创建 E2B 沙箱,无需注册节点。",
- "E2B API key": "E2B API key",
- "Console → API Keys": "控制台 → API Keys",
+ "E2B API key": "E2B API 密钥",
+ "Console → API keys": "控制台 → API 密钥",
"Sandbox API URL": "沙箱 API 地址",
"Sandbox data-plane domain": "沙箱数据面域名",
- "Leave both endpoint fields blank for official E2B. A compatible service needs its HTTPS API origin and data-plane domain.": "留空使用官方 E2B。兼容服务需同时填写 HTTPS API 地址和数据面域名。",
"Enter both a public HTTPS API origin and a domain.": "请同时填写公网 HTTPS API 地址和域名。",
- "The key is write-only. It is cleared from this form after submission and never saved in browser storage.": "密钥仅供写入,提交后会从表单清除,不会保存在浏览器存储中。",
"Enter a template ID and build UUID separated by a colon.": "请输入模板 ID 和构建 UUID,并用冒号分隔。",
- "Immutable Runtime template": "固定版本 Runtime 模板",
- "Use the qualified managed Runtime template ID followed by its build UUID. A template alias or a generic E2B template cannot provide Core execution.": "请填写已验证的托管 Runtime 模板 ID 和构建 UUID。模板别名或通用 E2B 模板无法提供 Core 执行能力。",
- "Core origin stays unchanged": "Core 地址保持不变",
- "Deployment provider": "部署运行后端",
+ "Deployment provider": "部署的沙箱提供商",
"Allocated resources": "已分配资源",
- "Pending environments": "待处理环境",
+ "Pending environments": "待处理 Environment",
"E2B credential": "E2B 凭据",
"Configured": "已配置",
"Not configured": "未配置",
- "Saved configuration does not confirm execution readiness. Session and Environment state report actual execution.": "配置已保存不代表执行已就绪。实际执行情况以会话和环境状态为准。",
- "Stopped or offline resources, snapshots, uncertain creates and pending environments still block switching. Deleting a Session alone does not prove cleanup; Core must confirm both counts are zero.": "已停止或离线的资源、快照、创建结果未确认的资源和待处理环境均会阻止切换。删除会话并不代表清理完成,需由 Core 确认两项计数均为零。",
- "Open Sessions": "打开会话",
- "Check cleanup": "检查清理状态",
- "Core reports no remaining execution resources. You can choose the next provider.": "Core 确认已无剩余执行资源,可以选择下一个运行后端。",
- "Provider changes are blocked until Core confirms complete cleanup.": "Core 确认清理完成前无法更改运行后端。",
+ "Saved configuration does not confirm execution readiness. Session and Environment state report actual execution.": "配置已保存不代表执行已就绪。实际执行情况以 Session 和 Environment 状态为准。",
"Cancel": "取消",
- "Resume hosted placement": "恢复托管分配",
"Refresh sandbox state to confirm whether the change was saved before submitting again.": "再次提交前,请刷新沙箱状态以确认更改是否已保存。",
- "Hosted sandboxes": "托管沙箱",
- "Manage hosted execution for this Core deployment.": "管理此 Core 部署的托管执行。",
"Status": "状态",
"Added": "加入时间",
"Back": "返回",
"Node not found": "找不到此节点",
"This node is not registered. It may have been removed.": "此节点未注册,可能已被移除。",
"Capacity": "容量",
- "Free memory": "可用内存",
"Free disk": "可用磁盘",
"Issue": "异常",
"Created": "创建时间",
@@ -375,7 +317,7 @@ export const sandbox = {
"Core address": "Core 地址",
"Custom size in advanced settings": "在高级设置里自定义规格",
"Data disk at /environment (MiB)": "数据盘 /environment(MiB)",
- "microsandbox, the recommended default, runs each sandbox as a lightweight virtual machine: stronger isolation and its own root and data disks with size limits, but the host needs KVM. Docker runs each sandbox as a container on the host's kernel: CPU and memory limits but no disk quota, for trusted workloads or hosts without KVM.": "microsandbox(推荐的默认后端):每个沙箱是一个轻量虚拟机,隔离更强,有独立的根盘和数据盘并能限制大小,但主机需要支持 KVM。Docker:每个沙箱是一个共用主机内核的容器,能限制 CPU 和内存,但没有磁盘配额,只适合可信的工作负载或没有 KVM 的主机。",
+ "microsandbox, the recommended default, runs each sandbox as a lightweight virtual machine: stronger isolation and its own root and data disks with size limits, but the host needs KVM. Docker runs each sandbox as a container on the host's kernel: CPU and memory limits but no disk quota, for trusted workloads or hosts without KVM.": "microsandbox(推荐的默认沙箱提供商):每个沙箱是一个轻量虚拟机,隔离更强,有独立的根盘和数据盘并能限制大小,但主机需要支持 KVM。Docker:每个沙箱是一个共用主机内核的容器,能限制 CPU 和内存,但没有磁盘配额,只适合可信的工作负载或没有 KVM 的主机。",
"E2B runs sandboxes in its cloud: no machines to manage, billed by E2B. Own machines run them on hosts you add, with microsandbox (recommended) or Docker.": "E2B 云端:沙箱跑在 E2B 的云上,不用管理机器,由 E2B 计费。自有机器:沙箱跑在你添加的主机上,用 microsandbox(推荐)或 Docker。",
"Each sandbox": "每个沙箱",
"Filled in from this console's distribution when it serves one. Otherwise copy these from the distribution manifest that matches your nodes; image configuration IDs and manifest digests are different values.": "控制台提供发行清单时会自动填好;否则从与节点配套的发行清单里复制。镜像配置 ID 和清单摘要是两个不同的值。",
@@ -406,11 +348,10 @@ export const sandbox = {
"Idle suspension": "空闲挂起",
"After {{idle}} · kept {{retention}}": "{{idle}}后 · 保留 {{retention}}",
"Current": "当前规格",
- "The exact ready build, as template-id:build-uuid. A template alias alone is not enough. Each sandbox gets the build's CPU and memory.": "精确的已就绪构建,格式为 template-id:build-uuid,只填模板别名不行。每个沙箱按这个构建分配 CPU 和内存。",
- "The key is write-only: Core encrypts it and never shows it again.": "key 只写入:Core 加密保存,之后不再显示。",
+ "The key is write-only: Core encrypts it and never shows it again.": "密钥只写入:Core 加密保存,之后不再显示。",
"This console serves no Runtime manifest. Enter the release under advanced settings.": "这个控制台没有提供 Runtime 清单,请在高级设置里填写。",
"Where should sandboxes run?": "沙箱在哪里运行?",
- "Which sandbox backend?": "用哪种沙箱后端?",
+ "Which sandbox backend?": "用哪个沙箱提供商?",
"Recommended": "推荐",
"Use Docker instead of microsandbox?": "改用 Docker 而不是 microsandbox?",
"Weaker isolation": "隔离更弱",
@@ -428,12 +369,12 @@ export const sandbox = {
"The address nodes and sandboxes use to reach Core.": "节点和沙箱访问 Core 使用的地址。",
"Managed in Settings": "在设置中管理",
"Set a public address before connecting remote nodes; E2B sandboxes need an HTTPS one.": "连接远程节点前,请先设置公开地址;E2B 沙箱需要 HTTPS 地址。",
- "Enter the E2B key again to save.": "请重新输入 E2B key 后再保存。",
- "Enter the key": "输入 key",
+ "Enter the E2B key again to save.": "请重新输入 E2B 密钥后再保存。",
+ "Enter the key": "输入密钥",
"{{name}} is still bound to an old Core address. Remove it and add it again.": "{{name}} 仍绑定在旧的 Core 地址上,需要移除后重新添加。",
"{{count}} nodes are still bound to an old Core address: {{names}}. Remove them and add them again.": "有 {{count}} 个节点仍绑定在旧的 Core 地址上:{{names}}。需要移除后重新添加。",
"Sandboxes released on this node that it has not removed yet.": "已在这台节点上释放、但节点尚未移除的沙箱。",
- "Host": "宿主机",
+ "Host": "主机",
"The whole machine as the node reports it with each heartbeat: the busy share of its CPU and its used memory, the highest in each interval. Intervals while the node was offline stay empty.": "节点每次心跳上报的整台机器的情况:CPU 忙碌占比和已用内存,取每个时间段内的最高值。节点离线的时间段留空。",
"Time range": "时间范围",
"1 hour": "1 小时",
@@ -444,10 +385,10 @@ export const sandbox = {
"{{percent}} of {{cores}} CPU": "{{cores}} 核中的 {{percent}}",
"{{cores}} CPU": "{{cores}} 核",
"{{used}} of {{total}} used": "已用 {{used}} / {{total}}",
- "Host history could not be read. {{reason}}": "无法读取宿主机历史。{{reason}}",
- "Loading host history…": "正在加载宿主机历史…",
- "Host CPU / {{bucket}}": "宿主机 CPU / {{bucket}}",
- "Host memory / {{bucket}}": "宿主机内存 / {{bucket}}",
+ "Host history could not be read. {{reason}}": "无法读取主机历史。{{reason}}",
+ "Loading host history…": "正在加载主机历史…",
+ "Host CPU / {{bucket}}": "主机 CPU / {{bucket}}",
+ "Host memory / {{bucket}}": "主机内存 / {{bucket}}",
"Used": "已用",
"Total": "总量",
} as const;
diff --git a/apps/web/src/i18n/locales/zh-CN/sessions.ts b/apps/web/src/i18n/locales/zh-CN/sessions.ts
index b6e1455da..11a738967 100644
--- a/apps/web/src/i18n/locales/zh-CN/sessions.ts
+++ b/apps/web/src/i18n/locales/zh-CN/sessions.ts
@@ -13,35 +13,35 @@ export const sessions = {
running: "运行中", interrupted: "已中断", idle: "空闲",
},
sessionStatus: { all: "全部", in_progress: "运行中", requires_action: "等待调用方", failed: "失败", idle: "空闲", other: "其他" },
- environment: { none: "无环境", self_hosted: "自托管", openai_hosted: "托管沙箱", other: "其他" },
+ environment: { none: "无 Environment", self_hosted: "自托管", openai_hosted: "托管沙箱", other: "其他" },
harness: coreHarnessNames,
- usage: { input: "输入", output: "输出", total: "总计", cached: "缓存", reasoning: "推理" },
+ usage: { input: "输入", output: "输出", total: "总计" },
log: {
title: "Session 日志",
- help: "调用方用各项目的 API key 创建的 Session,按最近活跃排序。控制台只读取 Session,并可删除空闲的 Session;打开 Session 可查看对话、追踪和 Turn。",
+ help: "调用方用各项目的 API 密钥创建的 Session,按最近活跃排序。控制台只读取 Session,并可删除空闲的 Session;打开 Session 可查看对话、追踪和 Turn。",
filters: "Session 筛选",
statusFilter: "状态",
agentFilter: "Agent",
allAgents: "全部 Agent",
- environmentFilter: "环境",
- allEnvironments: "全部环境",
+ environmentFilter: "Environment",
+ allEnvironments: "全部 Environment",
search: "搜索 ID、Agent、模型或错误",
loading: "正在加载 Session…",
loadFailed: "无法加载 Session",
emptyTitle: "还没有 Session",
- emptyDescription: "调用方用项目的 API key 创建 Session 后,会显示在这里。",
+ emptyDescription: "调用方用项目 API 密钥创建 Session 后,会显示在这里。",
noMatch: "没有匹配的 Session",
clearFilters: "清除筛选",
session: "Session",
status: "状态",
model: "模型",
- environment: "环境",
- tokens: "Token",
+ environment: "Environment",
+ tokens: "token",
created: "创建时间",
lastActive: "最近活跃",
actions: "操作",
waitingLabel: "Session 在等待什么",
- exactTokens: "{{tokens}} 个 Token",
+ exactTokens: "{{tokens}} 个 token",
open: "打开 Session {{id}}",
more: "显示更多",
},
@@ -55,7 +55,7 @@ export const sessions = {
agent: "Agent",
model: "模型",
harness: "Harness",
- environment: "环境",
+ environment: "Environment",
created: "创建时间",
lastActive: "最近活跃",
vaults: "Vault",
@@ -63,7 +63,7 @@ export const sessions = {
waitingFor: "等待",
functionCall: "等待应用提交 {{name}} 的结果。",
applicationAction: "此结果须由调用方应用提交,控制台无法代为提交。",
- environmentConnection: "环境连接",
+ environmentConnection: "Environment 连接",
openAgent: "打开 Agent {{name}}",
openVault: "打开 Vault {{id}}",
loading: "正在加载 Session…",
@@ -79,11 +79,11 @@ export const sessions = {
},
kpi: {
label: "Session 用量",
- help: "Token 数是 Core 报告的整个 Session 累计值,不是计费依据。未报告用量的 Session 显示 —。",
+ help: "token 数是 Core 报告的整个 Session 累计值,不是计费依据。未报告用量的 Session 显示 —。",
turns: "Turn",
- input: "输入 Token",
- output: "输出 Token",
- total: "总 Token",
+ input: "输入 token",
+ output: "输出 token",
+ total: "总 token",
cached: "缓存输入",
reasoning: "推理",
},
@@ -96,10 +96,9 @@ export const sessions = {
queued: "排队中…",
trace: "追踪",
turns: "Turn",
- noItems: "还没有条目",
- itemsFailed: "无法加载条目:{{reason}}",
+ noItems: "还没有 Item",
+ itemsFailed: "无法加载 Item:{{reason}}",
turnsFailed: "无法加载 Turn:{{reason}}",
- user: "用户",
error: "错误",
unassociated: "未关联 Turn",
steps: "{{n}} 个步骤",
@@ -112,16 +111,15 @@ export const sessions = {
status: "状态",
started: "开始时间",
duration: "耗时",
- items: "条目",
+ items: "Item",
input: "输入",
output: "输出",
- total: "总 Token",
+ total: "总 token",
number: "Turn {{number}}",
- errorLabel: "Turn 错误",
none: "还没有 Turn",
},
runtime: {
- title: "运行时",
+ title: "Runtime",
help: "Core 观测到的此 Session 托管沙箱的 CPU 和内存,以及所选时间范围内 Core 保留的采样。",
state: "状态",
cpu: "CPU",
@@ -138,36 +136,35 @@ export const sessions = {
sample_timeout: "采样超时",
sample_unavailable: "采样不可用",
},
- observationFailed: "无法加载运行时观测:{{reason}}",
- historyUnavailable: "Core 没有保留此 Session 的运行时历史。",
- historyFailed: "无法加载运行时历史:{{reason}}",
- historyLoading: "正在加载运行时历史…",
+ observationFailed: "无法加载 Runtime 观测:{{reason}}",
+ historyUnavailable: "Core 没有保留此 Session 的 Runtime 历史。",
+ historyFailed: "无法加载 Runtime 历史:{{reason}}",
+ historyLoading: "正在加载 Runtime 历史…",
},
executor: {
connection: {
title: "主机连接",
- help: "只有执行器仍具备有效权限且连接存活时,Core 才报告已连接。最后在线时间来自最近一次心跳,可能有延迟;它不代表模型或运行引擎已就绪。",
- status: { never_enrolled: "尚未连接", connected: "已连接", disconnected: "已断开", revoked: "绑定凭证已撤销", unknown: "未知" },
- boundKey: "绑定凭证",
+ help: "只有执行器仍具备有效权限且连接存活时,Core 才报告已连接。最后在线时间来自最近一次心跳,可能有延迟;它不代表模型或 Harness 已就绪。",
+ status: { never_enrolled: "尚未连接", connected: "已连接", disconnected: "已断开", revoked: "绑定凭据已撤销", unknown: "未知" },
+ boundKey: "绑定凭据",
lastSeen: "最后在线",
- notBound: "尚未绑定",
noHeartbeat: "尚无心跳记录",
stale: "刷新失败。当前显示上次读取的绑定信息,连接状态未知。",
refreshing: "正在刷新上次读取的绑定信息,尚未确认当前连接。",
failed: "无法读取连接状态,请刷新重试。",
- bound: "此 Environment 已绑定凭证 {{id}},签发新凭证不会替换绑定。请轮换绑定凭证以重新连接。",
- restore: "绑定凭证 {{id}} 已撤销。请轮换凭证,停止 daemon,在原配置路径替换凭据文件,再启动 daemon;签发新凭证不会替换绑定。",
+ bound: "此 Environment 已绑定凭据 {{id}},签发新凭据不会替换绑定。请轮换绑定凭据以重新连接。",
+ restore: "绑定凭据 {{id}} 已撤销。请轮换凭据,停止 daemon,在原配置路径替换凭据文件,再启动 daemon;签发新凭据不会替换绑定。",
rotateRestore: "轮换以恢复",
- rotateBound: "轮换绑定凭证",
+ rotateBound: "轮换绑定凭据",
},
- title: "Executor 凭据",
- help: "凭据让一个自托管 executor 连接 Core,只对这个环境有效,不能调用 Agents API。请将下载的凭据 JSON 私密保存在 executor 主机上,并向安装程序提供文件的绝对路径。每份凭据只显示一次;丢失时,轮换凭据即可换一份新的。",
+ title: "执行器凭据",
+ help: "凭据让一个自托管执行器连接 Core,只对这个 Environment 有效,不能调用 Agents API。请将下载的凭据 JSON 私密保存在执行器主机上,并向安装程序提供文件的绝对路径。每份凭据只显示一次;丢失时,轮换凭据即可换一份新的。",
issue: "签发凭据",
issuing: "正在签发…",
- loading: "正在加载 executor 凭据…",
- loadFailed: "无法加载 executor 凭据",
- refreshFailed: "刷新失败,显示的是上次加载的 executor 凭据。",
- empty: "还没有 executor 凭据",
+ loading: "正在加载执行器凭据…",
+ loadFailed: "无法加载执行器凭据",
+ refreshFailed: "刷新失败,显示的是上次加载的执行器凭据。",
+ empty: "还没有执行器凭据",
columns: { credential: "凭据", created: "创建时间", status: "状态" },
status: { active: "有效", revoked: "已撤销" },
copyKeyId: "复制凭据 ID",
@@ -177,20 +174,20 @@ export const sessions = {
rotateLabel: "轮换凭据 {{id}}",
revoke: "撤销",
revokeLabel: "撤销凭据 {{id}}",
- issueRejected: "未签发 executor 凭据",
+ issueRejected: "未签发执行器凭据",
archived: "项目已归档,不能再签发或轮换凭据。",
notIssued: "凭据 {{id}} 没有签发。准备好后可以再次签发。",
existsRevoked: "凭据 {{id}} 已存在且已撤销。再次签发即可获得新凭据。",
issued: {
- title: "Executor 凭据",
+ title: "执行器凭据",
notice: "这份凭据只显示这一次:点击“完成”后将无法再次查看。",
next: "先下载凭据文件并私密保存,再点击“完成”。",
- fileLabel: "Executor 凭据文件",
+ fileLabel: "执行器凭据文件",
copy: "复制凭据",
copied: "已复制",
copyFailed: "无法复制凭据,已为你选中,请手动复制。",
download: "下载凭据文件",
- downloadHint: "安装器只读取私有文件。交互安装时填写其绝对路径,或使用 。不要将 token 放进命令行。",
+ downloadHint: "安装器只读取私有文件。交互安装时填写其绝对路径,或使用 。不要将令牌放进命令行。",
done: "完成",
},
install: {
@@ -205,7 +202,7 @@ export const sessions = {
start: "命令中的安装授权在 30 分钟后过期。连接成功不代表模型调用可用。",
unavailable: "安装命令暂不可用。请刷新 Session,或请 Core 管理员检查原生安装包。",
terminal: "终端",
- command: "Executor 安装命令",
+ command: "执行器安装命令",
copy: "复制命令",
copied: "已复制",
copyFailed: "无法复制命令,已为你选中,请手动复制。",
@@ -235,7 +232,7 @@ export const sessions = {
revokeDialog: {
title: "撤销凭据?",
prompt: "撤销凭据 {{id}}?",
- consequence: "Executor 会断开连接。撤销凭据不会停止已安装的 Runtime,也不会删除工作目录。",
+ consequence: "执行器会断开连接。撤销凭据不会停止已安装的 Runtime,也不会删除工作目录。",
confirm: "撤销",
busy: "正在撤销…",
uncertain: "撤销没有得到确认。列表已重新读取,请先检查再决定是否重试。",
@@ -246,7 +243,7 @@ export const sessions = {
actionLabel: "删除 Session {{id}}",
title: "删除 Session?",
prompt: "删除项目 {{project}} 的 Session {{id}}?",
- consequence: "Core 会删除该 Session 及其 Turn 和条目,无法恢复。",
+ consequence: "Core 会删除该 Session 及其 Turn 和 Item,无法恢复。",
confirm: "删除",
deleting: "正在删除…",
deleted: "已删除 Session {{id}}",
@@ -258,55 +255,30 @@ export const sessions = {
},
items: {
...english.items,
- agentWorkTrace: "Agent 工作追踪", arguments: "参数", result: "结果", command: "命令", webSearch: "网页搜索", functionResult: "函数结果", mcpTool: "MCP 工具", function: "函数", unknown: "未知", item: "条目",
- verb: { run: "运行", search: "搜索", return: "返回", use: "使用", unsupported: "不支持" }, workingNote: "工作记录", emptyMessage: "空消息条目",
- applyPatchDiff: "OpenAgentCore 补丁差异", fileCount: "{{count}} 个文件", changeKind: { add: "新增", modify: "修改", delete: "删除" }, unifiedDiffFor: "{{path}} 的统一差异", rawArguments: "原始参数", rawResult: "原始结果", noResultYet: "暂无结果",
+ agentWorkTrace: "Agent 工作追踪", arguments: "参数", result: "结果", command: "命令", webSearch: "网页搜索", functionResult: "函数结果", mcpTool: "MCP 工具", function: "函数", unknown: "未知", item: "Item",
+ verb: { run: "运行", search: "搜索", return: "返回", use: "使用", unsupported: "不支持" }, workingNote: "工作记录", emptyMessage: "空消息 Item",
+ applyPatchDiff: "OpenAgentCore 补丁差异", fileCount: "{{count}} 个文件", changeKind: { add: "新增", modify: "修改", delete: "删除" }, unifiedDiffFor: "{{path}} 的统一差异", rawArguments: "原始参数", rawResult: "原始结果", noResultYet: "还没有结果",
},
turns: {
...english.turns,
statusTitle: "Turn 状态:{{status}}", coreReadFailed: "OpenAgentCore Turn 读取失败。",
- linkedItems: "已关联 {{count}} 个条目", linkedItems_one: "已关联 {{count}} 个条目", linkedItems_other: "已关联 {{count}} 个条目",
+ linkedItems: "已关联 {{count}} 个 Item", linkedItems_one: "已关联 {{count}} 个 Item", linkedItems_other: "已关联 {{count}} 个 Item",
observed: "已观测 {{count}} 个 Turn", observed_one: "已观测 {{count}} 个 Turn", observed_other: "已观测 {{count}} 个 Turn",
- unassociated: "有 {{count}} 个条目尚未关联到已观测 Turn。", unassociated_one: "有 {{count}} 个条目尚未关联到已观测 Turn。", unassociated_other: "有 {{count}} 个条目尚未关联到已观测 Turn。",
+ unassociated: "有 {{count}} 个 Item 尚未关联到已观测 Turn。", unassociated_one: "有 {{count}} 个 Item 尚未关联到已观测 Turn。", unassociated_other: "有 {{count}} 个 Item 尚未关联到已观测 Turn。",
},
trace: {
...english.trace,
- source: "来源", agentSnapshot: "Agent 配置快照", itemSnapshot: "持久化条目快照", notApplicable: "不适用", group: "分组", configuredModel: "配置的模型", itemTiming: "条目时间", notProvidedByCore: "Core 未提供", toolReportedDuration: "工具报告耗时",
- turnScopedUsage: "Turn 范围令牌用量", turnScopedTokens: "Turn 令牌", scopeBoundary: "此视图报告 Core 资源范围,不推断模型跨度、提供商、请求步骤或子 Agent 关系。", contractUnavailable: "当前 Core 合约未提供。",
- turnStarted: "Turn 开始", turnCompleted: "Turn 完成", turnWallClock: "Turn 总耗时", itemStarted: "条目开始", itemCompleted: "条目完成", timingBoundary: "Turn 时间戳是服务端资源。工具耗时没有公开的绝对开始时间,因此不会定位到按时间缩放的瀑布图中。",
+ source: "来源", agentSnapshot: "Agent 配置快照", itemSnapshot: "持久化 Item 快照", notApplicable: "不适用", group: "分组", configuredModel: "配置的模型", itemTiming: "Item 时间", notProvidedByCore: "Core 未提供", toolReportedDuration: "工具报告耗时",
+ turnScopedUsage: "Turn 范围 token 用量", turnScopedTokens: "Turn token", scopeBoundary: "此视图报告 Core 资源范围,不推断模型跨度、模型提供商、请求步骤或子 Agent 关系。", contractUnavailable: "当前 Core 合约未提供。",
+ turnStarted: "Turn 开始", turnCompleted: "Turn 完成", turnWallClock: "Turn 总耗时",
knownTurnTime: "已知 Turn 耗时", turns: "Turn", toolCalls: "工具调用", search: "搜索追踪", durableExecutionOrder: "持久化执行顺序", durableOrder: "持久化顺序", equalWidth: "等宽序列 · 不按时间缩放",
- lane: { input: "输入", model: "模型", tools: "工具" }, label: { system: "系统", user: "用户", assistant: "助手", tool: "工具", item: "条目" }, openItem: "打开 {{label}} 追踪条目:{{title}}",
- contractNote: "Core 报告 Turn 总耗时,但不报告逐条目时间。行会保持持久化顺序,且不按时间缩放。", loadingHistory: "正在加载完整的持久化 Turn 与条目历史…",
- turnHistoryIncomplete: "Turn 历史不完整", itemHistoryIncomplete: "条目历史不完整", itemReadFailed: "Core 条目读取失败。", items: "追踪条目", itemStatus: "条目状态:{{status}}", turnWallClockDuration: "Turn 总耗时", noItemsForTurn: "此 Turn 未报告持久化条目。", noMatches: "没有符合搜索条件的追踪行。",
- itemDetails: "追踪条目详情", closeDetails: "关闭追踪详情", detailView: "追踪详情视图", tabs: { summary: "摘要", preview: "预览", payload: "载荷", result: "结果", schema: "Schema", timing: "时间", raw: "原始数据" },
- toolDurationSentence: "工具报告耗时:{{duration}}。", toolDuration: "工具报告耗时:{{duration}}", durationUnknown: "报告的耗时未知。", durationInvalid: "无法解析报告的耗时。", perItemNotProvided: "Core 未提供逐条目时间。", perItemTimingMissing: "Core 不提供逐条目时间。",
- turnDuration: "Turn {{duration}}", turnTimeUnknown: "Turn 耗时未知", turnTimeNotProvided: "未提供 Turn 耗时", payloadAvailable: "载荷可用", resultAvailable: "结果可用", noPreview: "无可用预览", configuredInstructions: "已配置指令", userMessage: "用户消息", assistantMessage: "助手消息", unsupportedItem: "不支持的条目", agentConfiguration: "Agent 配置", turnNumber: "Turn {{number}}", unassociatedItemsNumber: "未关联条目 {{number}}", unknownCount: "{{count}} 个未知",
- },
- validation: {
- ...english.validation,
- absoluteWorkspace: "工作区目录必须是绝对 POSIX 路径,例如 /workspace。",
- safeWorkspace: "工作区目录不能包含 NUL、回车、换行或反斜杠字符。",
- unsupportedNetworkPolicy: "不支持所选的托管环境网络策略。",
- invalidTemplateId: "所选环境模板标识符无效。",
- unsupportedEnvironmentType: "不支持所选的环境类型。",
- invalidEnvironmentInput: "环境输入无效。",
- invalidNoEnvironment: "无环境请求包含不支持的字段。",
- invalidSelfHosted: "自托管环境请求不符合 Web 支持的配置。",
- invalidManaged: "托管环境请求不符合支持的基础配置。",
- firstMessageRequired: "未使用环境时,必须填写首条消息。",
- nonblankFirstMessage: "请输入非空的首条消息。",
- addUserMessage: "请至少添加一条用户消息。",
- supportedTextParts: "用户消息 {{number}} 必须包含受支持的文本片段。",
- nonblankTextParts: "用户消息 {{number}} 的文本片段中必须包含非空文本。",
- atLeastOneTextPart: "用户消息 {{number}} 至少需要一个文本片段。",
- selectSavedAgent: "配置 Session 专用覆盖项前,请先选择已保存的 Agent。",
- nonemptyModelOverride: "请输入非空的 Session 模型覆盖值。",
- inlineMustNotSendId: "创建内联 Agent Session 时不得发送 agent_id。",
- invalidInlineProfile: "内联 Agent 请求超出 Web 支持的配置范围。",
- selectLoadedOrInline: "请选择已加载的已保存 Agent,或使用内联 Agent。",
- savedAgentNotLoaded: "所选的已保存 Agent 尚未加载。",
- invalidOverrideProfile: "Session 专用 Agent 覆盖项超出 Web 支持的配置范围。",
+ lane: { input: "输入", model: "模型", tools: "工具" }, label: { system: "系统", user: "用户", assistant: "助手", tool: "工具", item: "Item" }, openItem: "打开 {{label}} 追踪 Item:{{title}}",
+ contractNote: "Core 报告 Turn 总耗时,但不报告逐 Item 时间。行会保持持久化顺序,且不按时间缩放。", loadingHistory: "正在加载完整的持久化 Turn 与 Item 历史…",
+ turnHistoryIncomplete: "Turn 历史不完整", itemHistoryIncomplete: "Item 历史不完整", itemReadFailed: "Core Item 读取失败。", items: "追踪 Item", itemStatus: "Item 状态:{{status}}", turnWallClockDuration: "Turn 总耗时", noItemsForTurn: "此 Turn 未报告持久化 Item。", noMatches: "没有符合搜索条件的追踪行。",
+ itemDetails: "追踪 Item 详情", closeDetails: "关闭追踪详情", detailView: "追踪详情视图", tabs: { summary: "摘要", preview: "预览", payload: "载荷", result: "结果", schema: "Schema", timing: "时间", raw: "原始数据" },
+ toolDurationSentence: "工具报告耗时:{{duration}}。", toolDuration: "工具报告耗时:{{duration}}", durationUnknown: "报告的耗时未知。", durationInvalid: "无法解析报告的耗时。", perItemNotProvided: "Core 未提供逐 Item 时间。", perItemTimingMissing: "Core 不提供逐 Item 时间。",
+ turnDuration: "Turn {{duration}}", turnTimeUnknown: "Turn 耗时未知", turnTimeNotProvided: "未提供 Turn 耗时", payloadAvailable: "载荷可用", resultAvailable: "结果可用", noPreview: "无可用预览", configuredInstructions: "已配置指令", userMessage: "用户消息", assistantMessage: "助手消息", unsupportedItem: "不支持的 Item", agentConfiguration: "Agent 配置", turnNumber: "Turn {{number}}", unassociatedItemsNumber: "未关联 Item {{number}}", unknownCount: "{{count}} 个未知",
},
actions: {
...english.actions,
@@ -325,7 +297,7 @@ export const sessions = {
readFailureWithDetail: "{{detail}} 未发送更新请求;草稿和当前持久化视图均已保留。", writeFailureWithDetail: "{{detail}} Web 已保留当前持久化视图且未自动重试。",
latestReadFailure: "无法读取最新 Session,因此未发送更新请求。草稿和当前持久化视图均已保留。", unknownConnection: "连接在 Core 确认前中断,因此 Session{{action}}结果未知。Web 已保留当前持久化视图且未自动重试;请刷新状态后再决定是否重试。",
invalidUpdateConfirmation: "OpenAgentCore 返回了无效的 Session 更新确认。写入结果未知;Web 已保留当前持久化视图且未自动重试。",
- inputPending: "OpenAgentCore 仅允许删除处于空闲或失败状态且没有必需操作的 Session。此 Session 有等待在环境中启动的输入,无法取消,因此未做任何更改。请等待输入启动、过期或失败后删除;输入启动后,请先取消其工作。",
+ inputPending: "OpenAgentCore 仅允许删除处于空闲或失败状态且没有必需操作的 Session。此 Session 有等待在 Environment 中启动的输入,无法取消,因此未做任何更改。请等待输入启动、过期或失败后删除;输入启动后,请先取消其工作。",
invalidDeletionConfirmation: "OpenAgentCore 返回了无效的删除确认。Web 已保留该 Session;请刷新持久化状态后再操作。",
cancelRejected: "OpenAgentCore 拒绝取消请求({{status}}):{{detail}}", cancelUnknown: "连接在 Core 确认前中断,因此取消结果未知。", cancelDeleteKept: "{{detail}} Session 未删除,Web 也未自动重试。",
waitReadFailure: "已请求取消,但等待 Session 进入空闲状态期间无法读取该 Session,因此未删除。", waitTimeout: "已请求取消,但 {{seconds}} 秒后 Session 仍处于{{status}}状态,因此未删除;请在 Session 空闲后重试。",
diff --git a/apps/web/src/i18n/locales/zh-CN/skills.ts b/apps/web/src/i18n/locales/zh-CN/skills.ts
index 5c342bc30..9a22b5746 100644
--- a/apps/web/src/i18n/locales/zh-CN/skills.ts
+++ b/apps/web/src/i18n/locales/zh-CN/skills.ts
@@ -1,6 +1,6 @@
export const skills = {
title: "Skills",
- help: "Skill 是一个包含 SKILL.md 的文件夹,Agent 可以在托管环境中使用它。每次上传都会生成一个不可变的版本。新建 Session 引用 Skill 时如果没有指定版本,会使用默认版本;已有的 Session 保持创建时的内容。",
+ help: "Skill 是一个包含 SKILL.md 的文件夹,Agent 可以在托管 Environment 中使用它。每次上传都会生成一个不可变的版本。新建 Session 引用 Skill 时如果没有指定版本,会使用默认版本;已有的 Session 保持创建时的内容。",
limits: "Core 没有 Skill 搜索接口,筛选只作用于本页已加载的 Skill。Core 不记录上传者。浏览器中的检查只是辅助,最终以 Core 的校验为准。",
version: "v{{version}}",
actions: {
@@ -37,22 +37,14 @@ export const skills = {
defaultVersion: "默认版本",
latestVersion: "最新版本",
created: "创建时间",
- id: "ID",
newerThanDefault: "有未启用的新版本",
newerThanDefaultHelp: "已有更新的版本,但尚未设为默认。新建 Session 仍会使用默认版本。",
noMatchTitle: "没有匹配的已加载 Skill",
- noMatchDescription: "筛选只作用于已加载的 Skill。可以加载更多,或清除筛选。",
- loadFailed: "无法加载 Skill",
- refreshFailed: "刷新失败,下面是之前加载的 Skill。{{reason}}",
moreFailed: "无法加载下一页。{{reason}}",
},
empty: {
title: "还没有 Skill",
},
- unsupported: {
- title: "当前 Core 不提供 Skill",
- description: "所连接的 Core 对 Skill 列表请求返回了 {{status}}。",
- },
detail: {
loading: "正在加载 Skill…",
facts: "Skill 详情",
@@ -81,16 +73,6 @@ export const skills = {
downloaded: "已保存 {{filename}}",
actionFailed: "请求失败。{{reason}}",
},
- setDefault: {
- title: "将 v{{version}} 设为默认?",
- newSessions: "之后新建的 Session 如果引用这个 Skill 时没有指定版本,会使用 v{{version}}。",
- existingSessions: "已有的 Session 不受影响。",
- metadata: "这个 Skill 的名称和描述会变成 v{{version}} 的。",
- metadataChange: "这个 Skill 的名称和描述会变成 v{{version}} 的:{{name}}。",
- confirm: "设为默认",
- saving: "保存中…",
- done: "v{{version}} 已设为默认",
- },
deleteVersion: {
title: "删除 v{{version}}?",
body: "删除后版本号不会被复用;已有 Session 不受影响。",
@@ -107,75 +89,10 @@ export const skills = {
title: "删除 {{name}}?",
allVersions: "这个 Skill 的所有版本都会被删除。",
existingSessions: "已有的 Session 不受影响。",
- templates: "引用了这个 Skill 的环境模板,之后再用来创建 Session 会失败。",
+ templates: "引用了这个 Skill 的 Environment 模板,之后再用来创建 Session 会失败。",
typeName: "输入 {{name}} 以确认",
confirm: "删除 Skill",
deleting: "删除中…",
done: "{{name}} 已删除",
},
- upload: {
- title: "上传 Skill",
- versionTitle: "上传 {{name}} 的新版本",
- source: "上传方式",
- zip: "ZIP 文件",
- folder: "文件夹",
- zipInput: "选择 ZIP 文件",
- folderInput: "选择文件夹",
- reading: "正在读取所选内容…",
- setDefault: "设为默认版本",
- setDefaultHelp: "之后新建的 Session 如果引用这个 Skill 时没有指定版本,会使用这个版本,Skill 的名称和描述也会随之改变。已有的 Session 不受影响。",
- submit: "上传",
- uploading: "上传中…",
- cancelUpload: "取消上传",
- created: "{{name}} 已上传",
- versionCreated: "v{{version}} 已上传",
- preview: {
- label: "所选内容",
- folder: "文件夹",
- files: "文件数",
- size: "大小",
- archive: "ZIP 大小",
- name: "名称",
- description: "描述",
- missing: "未找到",
- },
- requirements: {
- title: "格式要求",
- folder: "只有一个顶层文件夹,并且里面有 SKILL.md。",
- frontmatter: "SKILL.md 的 frontmatter 只支持 name、description、license、compatibility 和字符串类型的 metadata;hooks、权限控制和 subagent 指令都会被拒绝。",
- files: "只能是普通文件:不能有软链接、特殊文件和路径穿越。",
- limits: "压缩后不超过 5 MiB,解压后不超过 20 MiB;上传文件夹最多 500 个文件,ZIP 最多 1,000 个条目。",
- authority: "这些是当前 Core 的限制,不是上游协议的上限。最终以 Core 的校验为准。",
- },
- issues: {
- noFiles: "所选内容里没有文件。",
- tooManyFiles: "共 {{count}} 个文件,超过上限 {{limit}} 个。",
- tooLarge: "解压后 {{size}},超过上限 {{limit}}。",
- zipTooLarge: "ZIP 大小为 {{size}},上限为 {{limit}}。",
- notZip: "请选择扩展名为 .zip 的文件。",
- multipleTopLevel: "请把所有内容放进一个顶层文件夹。当前有:{{names}}",
- outsideFolder: "这些文件不在文件夹里:{{paths}}",
- missingManifest: "缺少 {{folder}}/SKILL.md。",
- invalidPath: "不支持的路径:{{paths}}",
- duplicatePath: "重复的路径:{{paths}}",
- hiddenFiles: "隐藏文件会原样上传:{{paths}}",
- more: "{{list}} 等 {{count}} 个",
- manifestUnreadable: "无法读取 SKILL.md 用于预览。",
- zipUnreadable: "无法读取这个 ZIP 用于预览,Core 仍会校验它。",
- frontmatterMissing: "SKILL.md 不是以 --- frontmatter 开头。",
- frontmatterInvalid: "SKILL.md 的 frontmatter 有部分内容无法读取。",
- nameMissing: "frontmatter 里没有 name。",
- descriptionMissing: "frontmatter 里没有 description。",
- unsupportedKeys: "Core 会拒绝这些 frontmatter 字段:{{keys}}",
- nameFormat: "Core 要求 name 只包含小写字母、数字、- 和 _,最长 64 个字符。",
- },
- errors: {
- invalid: "Core 拒绝了这个 Skill:{{message}}",
- tooLarge: "文件超出大小限制。",
- interrupted: "上传没有完成。已选的文件仍然保留;Core 可能已经保存了它,重试前请先查看列表。",
- cancelled: "已取消上传。已选的文件仍然保留;Core 可能已经保存了它,重试前请先查看列表。",
- other: "上传失败:{{message}}",
- seeRequirements: "格式要求",
- },
- },
} as const;
diff --git a/apps/web/src/i18n/locales/zh-CN/system.ts b/apps/web/src/i18n/locales/zh-CN/system.ts
index d59d5e6c6..19c5c820d 100644
--- a/apps/web/src/i18n/locales/zh-CN/system.ts
+++ b/apps/web/src/i18n/locales/zh-CN/system.ts
@@ -12,7 +12,6 @@ export const system: TranslationShape = {
apiBaseUrl: "API 基础地址",
apiBaseUrlHelp: "应用把它设为 OPENAI_BASE_URL,并把项目 API 密钥设为 OPENAI_API_KEY。",
copyApiBaseUrl: "复制 API 基础地址",
- localOnly: "只能在 Core 所在的机器上访问",
details: "安装详情",
id: "安装 ID",
sourceCommit: "源码提交",
@@ -33,23 +32,23 @@ export const system: TranslationShape = {
},
models: {
title: "默认模型配置",
- help: "新建的 Core 托管 Session 和无环境 Session 使用这些默认设置,应用显式提供的设置优先。自托管 Session 需自行提供配置;已有 Session 保留原配置。",
+ help: "新建的 Core 托管 Session 和无 Environment Session 使用这些默认设置,应用显式提供的设置优先。自托管 Session 需自行提供配置;已有 Session 保留原配置。",
loadFailed: "无法加载默认模型配置。",
refreshFailed: "刷新失败,显示的是上次加载的默认模型配置。",
none: "Core 没有报告任何 Harness。",
status: {
ready: "就绪",
- needsProvider: "未设置模型服务",
+ needsProvider: "未设置模型提供商",
disabled: "未启用",
},
statusHelp: {
- ready: "新建的 Core 托管 Session 可以使用此 Harness 运行。应用或 Agent 未提供模型服务时,使用这里的默认模型服务。",
- needsProvider: "应用或 Agent 未提供模型服务时,Core 会拒绝在此 Harness 上新建 Core 托管 Session。选择“设置”添加默认模型服务。",
+ ready: "新建的 Core 托管 Session 可以使用此 Harness 运行。应用或 Agent 未提供模型提供商时,使用这里的默认模型提供商。",
+ needsProvider: "应用或 Agent 未提供模型提供商时,Core 会拒绝在此 Harness 上新建 Core 托管 Session。选择“设置”添加默认模型提供商。",
disabled: "Core 不运行此 Harness。启动设置 OAC_HARNESSES 和 OAC_DEFAULT_HARNESS 决定运行哪些 Harness。",
},
startupSettings: "查看启动设置",
default: "默认",
- provider: "模型服务",
+ provider: "模型提供商",
notSet: "未设置",
model: "默认模型 ID",
protocol: "协议",
@@ -80,14 +79,14 @@ export const system: TranslationShape = {
formatJson: "格式化 JSON",
setTitle: "设置 {{harness}} 的默认模型配置",
replaceTitle: "替换 {{harness}} 的默认模型配置",
- modelName: "应用未指定模型时,新会话使用此模型。请填写该服务接受的准确模型 ID。",
+ modelName: "应用未指定模型时,新 Session 使用此模型。请填写该服务接受的准确模型 ID。",
baseUrlInvalid: "请输入包含主机名、不含账号密码、查询参数或片段的 HTTPS URL,例如 https://api.example.com/v1。",
apiKeyHelp: "每次都必须填写。Core 会加密保存,之后不再显示。",
contextHelp: "模型的上下文窗口,单位为 token。可选。",
contextHelpRequired: "模型的上下文窗口,单位为 token。此 Harness 必须填写。",
outputHelp: "模型单次回复最多输出的 token 数。可选;填写时,上下文窗口必须不小于它。",
outputHelpRequired: "模型单次回复最多输出的 token 数。此 Harness 必须填写,且上下文窗口不能小于它。",
- protocolHelp: "选择此 Harness 和模型服务都支持的协议。",
+ protocolHelp: "选择此 Harness 和模型提供商都支持的协议。",
wholeNumber: "请输入整数。",
tooLarge: "请输入不超过 2147483647 的整数。",
needsContext: "请设置不小于该值的上下文窗口。",
@@ -98,7 +97,7 @@ export const system: TranslationShape = {
clearDialog: {
title: "清除默认模型配置",
prompt: "清除 {{harness}} 的默认模型配置?",
- consequence: "新会话将需要应用或 Agent 提供模型配置。已有会话保留原配置。",
+ consequence: "新 Session 将需要应用或 Agent 提供模型配置。已有 Session 保留原配置。",
confirm: "清除默认模型配置",
busy: "正在清除…",
uncertain: "Core 没有确认清除。已重新读取默认模型配置,请先核对再重试。",
diff --git a/apps/web/src/i18n/locales/zh-CN/templates.ts b/apps/web/src/i18n/locales/zh-CN/templates.ts
index fad278f70..5c6e09529 100644
--- a/apps/web/src/i18n/locales/zh-CN/templates.ts
+++ b/apps/web/src/i18n/locales/zh-CN/templates.ts
@@ -3,25 +3,22 @@ type TranslationShape = { [K in keyof T]: T[K] extends string ? string : Tran
export const templates: TranslationShape = {
boundary: "模板由应用使用项目 API 密钥通过 Agents API 创建和修改;控制台只查看和删除。",
refreshFailed: "无法刷新目录。请检查连接后重试。",
- savedRefreshFailed: "更改已保存,但目录刷新失败。请先刷新再进行其他更改。",
- created: "模板已创建,未分配运行时。", updated: "模板已更新。现有 Session 会保留原配置。", deleted: "模板已删除。",
- loading: "正在加载环境模板…", unavailableTitle: "环境模板不可用", unavailableDescription: "此 Core 未提供模板资源,Web 不会推断目录。",
- loadFailedTitle: "无法加载环境模板", loadFailedDescription: "请检查 Core 连接和访问权限;目录当前不可用。", configureConnection: "配置连接",
+ created: "模板已创建,未分配 Runtime。", updated: "模板已更新。现有 Session 会保留原配置。", deleted: "模板已删除。",
+ loading: "正在加载 Environment 模板…",
+ loadFailedTitle: "无法加载 Environment 模板",
filterLabel: "筛选模板", filterPlaceholder: "按名称或 ID 筛选", count: "显示 {{visible}} / {{total}} 个模板",
- emptyTitle: "还没有环境模板", noMatch: "没有匹配的模板", clearFilter: "清除筛选", listLabel: "环境模板",
+ emptyTitle: "还没有 Environment 模板", noMatch: "没有匹配的模板", clearFilter: "清除筛选", listLabel: "Environment 模板",
columns: { name: "名称", network: "网络", packages: "依赖包", files: "文件", skills: "Skill", plugins: "Plugin", updated: "更新时间", actions: "操作" },
access: { enabled: "已启用", disabled: "已禁用", restricted: "受限" },
accessHelp: {
- enabled: "原生工具可以访问任意主机。",
- disabled: "原生工具无法访问网络。",
restricted: "原生工具只能访问列出的主机名。子域名和重定向目标需要单独列出。",
},
- edit: "编辑", editLabel: "编辑 {{name}}", delete: "删除", deleteLabel: "删除 {{name}}", open: "打开 {{name}}", back: "返回",
+ edit: "编辑", delete: "删除", deleteLabel: "删除 {{name}}", open: "打开 {{name}}", back: "返回",
unrecognized: "含无法识别的配置",
unrecognizedHelp: "Core 返回了控制台无法识别的配置。可识别的部分照常显示,其余部分不做推测。",
unrecognizedSections: "控制台无法识别:{{sections}}",
unrecognizedValue: "无法识别",
- modal: { delete: "删除模板?", edit: "编辑模板", create: "创建模板" }, deletePrompt: "删除 {{name}}?", deleteWarning: "新 Session 将无法再选择此模板。已创建的 Session 不受影响。此操作无法撤销。", deleting: "删除中…", deleteTemplate: "删除模板", unnamed: "未命名模板",
+ modal: { delete: "删除模板?" }, deletePrompt: "删除 {{name}}?", deleteWarning: "新 Session 将无法再选择此模板。已创建的 Session 不受影响。此操作无法撤销。", deleting: "删除中…", deleteTemplate: "删除模板", unnamed: "未命名模板",
detail: {
facts: "模板信息",
id: "模板 ID",
@@ -74,8 +71,6 @@ export const templates: TranslationShape = {
saving: "保存中…", saveChanges: "保存更改", create: "创建模板",
},
errors: {
- forbidden: "Core 拒绝了此请求。请检查连接和访问权限。",
- missing: "此模板已不存在。请刷新目录后重试。",
invalid: "Core 拒绝了模板配置:{{reason}}",
uncertain: "未能确认写入结果。再次更改前请刷新并检查 Core 目录;请求未被重放。",
},
diff --git a/apps/web/src/i18n/locales/zh-CN/vaults.ts b/apps/web/src/i18n/locales/zh-CN/vaults.ts
index 6da976153..fecfac1c7 100644
--- a/apps/web/src/i18n/locales/zh-CN/vaults.ts
+++ b/apps/web/src/i18n/locales/zh-CN/vaults.ts
@@ -1,12 +1,9 @@
import type { vaults as english } from "../en/vaults";
type TranslationShape = { [K in keyof T]: T[K] extends string ? string : TranslationShape };
export const vaults: TranslationShape = {
- securityNote: "令牌只可写入。此页面只接收 Credential 元数据,绝不会接收令牌值。删除 Vault 也会删除其中保存的所有 Credential,但不会撤销 provider 侧令牌。",
- actionNotConfirmed: "操作未确认", mutationUncertain: "未能确认写入结果。目录已刷新;再次明确重试前请检查当前 Core 状态。", loading: "正在加载 Vault", loadFailed: "无法加载 Vault", refreshFailed: "无法刷新 Vault", failedDescription: "Web 无法加载完整的 Vault 和 Credential 目录。", staleDescription: "之前的安全元数据快照仍可见,但不能授权新 Session。", failedHint: "请检查 Core 连接后刷新。在完整目录加载前,需要 Credential 的 Session 会保持阻止状态。",
- credential: "Credential", deleteVaultLabel: "删除 {{name}}", created: "创建时间", credentialsIn: "{{name}} 中的 Credential", updatedHidden: "更新于 {{date}} · 令牌已隐藏", oauthHelp: "OAuth · 请在你的应用中管理授权和令牌替换。", replaceTokenLabel: "替换 {{name}} 的令牌", replaceToken: "替换令牌", deleteCredentialLabel: "删除 {{name}}", noCredentials: "此 Vault 中没有 Credential。", noVaults: "还没有 Vault", createVault: "创建 Vault", createVaultTitle: "创建 Vault", deleteVaultTitle: "删除 Vault?", deleteCredentialTitle: "删除 Credential?", deleting: "删除中…", delete: "删除", deleteVaultPrompt: "删除 {{name}} 及其中保存的全部 Credential?现有 Session 会保留冻结的 ID,但后续密钥读取会失败。Provider 令牌和正在运行的工作不会被撤销。", deleteCredentialPrompt: "删除 {{name}}?现有 Session 会保留其冻结标识,但后续密钥读取会失败。此操作不会撤销 MCP provider 上的令牌。", unnamed: "未命名 Vault",
- list: { label: "Vault", filterLabel: "筛选 Vault", filterPlaceholder: "按名称或 ID 筛选", name: "名称", credentials: "Credential", created: "创建时间", actions: "操作", open: "打开 {{name}}", noMatch: "没有匹配的 Vault" },
- detail: { back: "返回", facts: "Vault 详情", id: "ID", created: "创建时间", metadata: "元数据", credentials: "Credential", credentialsHelp: "静态 bearer 令牌只可写入:Core 不会返回令牌,所以这里只显示元数据。替换令牌不会在 provider 侧撤销旧令牌。", name: "名称", url: "MCP 服务 URL", auth: "认证方式", updated: "更新时间", addCredential: "添加 Credential", deleteVault: "删除 Vault", staticBearer: "静态 bearer", oauth: "OAuth", tokenHidden: "令牌已隐藏" },
- createForm: { name: "名称", namePlaceholder: "运行时 Credential", nameHelp: "必填。去除首尾空格后的名称最多 256 个 UTF-8 字节。", metadata: "元数据", optional: "可选", metadataHelp: "输入值为字符串的 JSON 对象。留空会转为 {{emptyObject}};编码后的元数据最大为 64 KiB。", metadataWarning: "Vault 元数据是公开的。切勿在此填写密钥、令牌、密码、凭据或私有连接信息。", creating: "创建中…", create: "创建 Vault" },
- credentialDialog: { replaceTitle: "替换令牌 · {{name}}", addTitle: "添加静态 bearer Credential", saving: "保存中…", create: "创建 Credential", notConfirmed: "Credential 未确认", name: "名称", namePlaceholder: "内部 MCP", exactUrl: "精确 MCP 服务 URL", urlHelp: "此 URL 必须与 Agent MCP 定义完全一致。创建此资源不会发起网络请求。", replaceWarning: "旧令牌不会被读取或显示。正在运行的工作可能已经持有它;替换操作不会撤销 provider 侧令牌。", newToken: "新 bearer 令牌", token: "Bearer 令牌", tokenHelp: "只可写入。令牌只发送一次,随后立即清除,且绝不会保存到浏览器状态、元数据、预览或日志中。" },
- errors: { auth: "Core 认证失败,Credential 未确认。", missing: "Vault 或 Credential 已不存在。请刷新后重试。", tooLarge: "Credential 请求超过 Core 接受的大小。", invalidFields: "Core 拒绝了 Credential 字段。请检查名称、精确 HTTPS URL 和令牌格式。", credentialUncertain: "未能确认 Credential 写入结果。目录已刷新;再次明确重试前请先检查。", bearer: "请输入非空的 RFC 6750 bearer 令牌。空白或其他仅能保存的不透明值无法在当前运行时执行。", credentialName: "Credential 名称必须为 1 至 256 个 UTF-8 字节。", exactUrl: "请输入不含凭据、查询参数、片段、空白或反斜杠的精确 HTTPS MCP URL。", createUncertain: "未能确认 Vault 创建结果。草稿保持不变;再次明确重试前请检查当前 Core 状态。", vaultName: "名称必须为 1 至 256 个 UTF-8 字节。", metadataUnknown: "无法验证元数据。", metadataJson: "元数据必须是有效 JSON。", metadataShape: "元数据必须是值为字符串的 JSON 对象。", metadataStrings: "元数据值必须全部为字符串;不支持嵌套值、数组、数字、布尔值和 null。", metadataLarge: "元数据经 UTF-8 JSON 编码后最大为 64 KiB。", mismatchedMetadata: "OpenAgentCore 返回的 Vault 元数据不匹配。", uniqueAttachments: "附加的 Vault 不能重复。", catalogIncomplete: "尚未从此 Core 完整加载 Credential 元数据。", vaultMissing: "所选 Vault 已不在当前目录中。", credentialMismatch: "MCP 服务 {{server}} 引用了不可用或 URL 不匹配的 Credential。", credentialVaultMissing: "MCP 服务 {{server}} 引用的 Credential 所属 Vault 不可用。", multipleCredentials: "匿名 MCP 服务 {{server}} 在所选 Vault 中匹配到多个 Credential。请选择唯一匹配的 Vault,或明确配置一个 Credential。", matchedVaultMissing: "MCP 服务 {{server}} 匹配到的 Credential 所属 Vault 不可用。" },
+ securityNote: "令牌只可写入。此页面只接收 Credential 元数据,绝不会接收令牌值。删除 Vault 也会删除其中保存的所有 Credential,但不会在提供商撤销令牌。",
+ loading: "正在加载 Vault", loadFailed: "无法加载 Vault", refreshFailed: "无法刷新 Vault",
+ credential: "Credential", deleteVaultLabel: "删除 {{name}}", created: "创建时间", credentialsIn: "{{name}} 中的 Credential", oauthHelp: "OAuth · 请在你的应用中管理授权和令牌替换。", deleteCredentialLabel: "删除 {{name}}", noCredentials: "此 Vault 中还没有 Credential。", noVaults: "还没有 Vault", deleteVaultTitle: "删除 Vault?", deleteCredentialTitle: "删除 Credential?", deleting: "删除中…", delete: "删除", deleteVaultPrompt: "删除 {{name}} 及其中保存的全部 Credential?现有 Session 会保留冻结的 ID,但后续密钥读取会失败。提供商的令牌和正在运行的工作不会被撤销。", deleteCredentialPrompt: "删除 {{name}}?现有 Session 会保留其冻结标识,但后续密钥读取会失败。此操作不会撤销 MCP 提供商的令牌。", unnamed: "未命名 Vault",
+ list: { label: "Vault", filterLabel: "筛选 Vault", filterPlaceholder: "按名称或 ID 筛选", name: "名称", created: "创建时间", actions: "操作", open: "打开 {{name}}", noMatch: "没有匹配的 Vault" },
+ detail: { back: "返回", facts: "Vault 详情", id: "ID", created: "创建时间", metadata: "元数据", credentials: "Credential", credentialsHelp: "静态 bearer 令牌只可写入:Core 不会返回令牌,所以这里只显示元数据。替换令牌不会在提供商撤销旧令牌。", name: "名称", url: "MCP 服务 URL", auth: "认证方式", updated: "更新时间", addCredential: "添加 Credential", deleteVault: "删除 Vault", staticBearer: "静态 bearer", oauth: "OAuth", tokenHidden: "令牌已隐藏" },
};
diff --git a/apps/web/src/i18n/resources.ts b/apps/web/src/i18n/resources.ts
index cb6b2e141..07f5a64cb 100644
--- a/apps/web/src/i18n/resources.ts
+++ b/apps/web/src/i18n/resources.ts
@@ -13,7 +13,6 @@ import { agents as enAgents } from "./locales/en/agents";
import { templates as enTemplates } from "./locales/en/templates";
import { vaults as enVaults } from "./locales/en/vaults";
import { files as enFiles } from "./locales/en/files";
-import { dashboard as enDashboard } from "./locales/en/dashboard";
import { sessions as enSessions } from "./locales/en/sessions";
import { overview as enOverview } from "./locales/en/overview";
import { metrics as enMetrics } from "./locales/en/metrics";
@@ -28,7 +27,6 @@ import { agents as zhCNAgents } from "./locales/zh-CN/agents";
import { templates as zhCNTemplates } from "./locales/zh-CN/templates";
import { vaults as zhCNVaults } from "./locales/zh-CN/vaults";
import { files as zhCNFiles } from "./locales/zh-CN/files";
-import { dashboard as zhCNDashboard } from "./locales/zh-CN/dashboard";
import { sessions as zhCNSessions } from "./locales/zh-CN/sessions";
import { overview as zhCNOverview } from "./locales/zh-CN/overview";
import { metrics as zhCNMetrics } from "./locales/zh-CN/metrics";
@@ -60,7 +58,6 @@ export const resources = {
templates: enTemplates,
vaults: enVaults,
files: enFiles,
- dashboard: enDashboard,
sessions: enSessions,
diagnostics: enDiagnostics,
overview: enOverview,
@@ -83,7 +80,6 @@ export const resources = {
templates: zhCNTemplates,
vaults: zhCNVaults,
files: zhCNFiles,
- dashboard: zhCNDashboard,
sessions: zhCNSessions,
diagnostics: zhDiagnostics,
overview: zhCNOverview,
diff --git a/apps/web/src/lib/collection-pagination.test.ts b/apps/web/src/lib/collection-pagination.test.ts
index fabdaf89e..d62da53da 100644
--- a/apps/web/src/lib/collection-pagination.test.ts
+++ b/apps/web/src/lib/collection-pagination.test.ts
@@ -1,100 +1,12 @@
import type { ListPage } from "@oac/agents-client";
import { describe, expect, it } from "vitest";
-import { appendCollectionPage, listAllCollectionPages, listStableCollectionPages } from "./collection-pagination";
+import { appendCollectionPage } from "./collection-pagination";
function page(data: T[], hasMore: boolean, lastId: string | null = null): ListPage {
return { object: "list", data, first_id: data[0]?.id ?? null, last_id: lastId, has_more: hasMore };
}
-describe("top-level collection pagination", () => {
- it("loads every page in stable descending order and forwards cancellation", async () => {
- const controller = new AbortController();
- const calls: Array<{ after?: string; signal?: AbortSignal }> = [];
- const result = await listAllCollectionPages(async (options) => {
- calls.push({ after: options.after, signal: options.signal });
- return options.after
- ? page([{ id: "agent-1" }], false)
- : page([{ id: "agent-3" }, { id: "agent-2" }], true, "agent-2");
- }, controller.signal);
-
- expect(result.map((value) => value.id)).toEqual(["agent-3", "agent-2", "agent-1"]);
- expect(calls).toEqual([
- { after: undefined, signal: controller.signal },
- { after: "agent-2", signal: controller.signal },
- ]);
- });
-
- it("fails closed for duplicate identities, empty continuation pages, and cyclic cursors", async () => {
- await expect(listAllCollectionPages(async (options) => options.after
- ? page([{ id: "duplicate" }], false)
- : page([{ id: "duplicate" }], true, "next")))
- .rejects.toThrow("duplicate or invalid collection identities");
-
- await expect(listAllCollectionPages(async () => (page([], true))))
- .rejects.toThrow("invalid collection pagination cursor");
-
- await expect(listAllCollectionPages(async (options) => page([{ id: options.after ? "second" : "first" }], true, "same-cursor"))).rejects.toThrow("invalid collection pagination cursor");
- });
-
- it("stops before another page read when cancellation is requested", async () => {
- const controller = new AbortController();
- let calls = 0;
-
- await expect(listAllCollectionPages(async () => {
- calls += 1;
- controller.abort();
- return page([{ id: "first" }], true, "first");
- }, controller.signal)).rejects.toMatchObject({ name: "AbortError" });
-
- expect(calls).toBe(1);
- });
-
- it("accepts a complete hundred-page collection and rejects a required page 101", async () => {
- let completeCalls = 0;
- const complete = await listAllCollectionPages(async () => {
- completeCalls += 1;
- return page([{ id: `complete-${completeCalls}` }], completeCalls < 100, `complete-${completeCalls}`);
- });
-
- expect(complete).toHaveLength(100);
- expect(completeCalls).toBe(100);
-
- let incompleteCalls = 0;
- await expect(listAllCollectionPages(async () => {
- incompleteCalls += 1;
- return page([{ id: `incomplete-${incompleteCalls}` }], true, `incomplete-${incompleteCalls}`);
- })).rejects.toThrow("pagination exceeded the Web safety limit");
- expect(incompleteCalls).toBe(100);
- });
-
- it("rereads an invalidated collection until one complete revision is stable", async () => {
- let revision = 0;
- let reads = 0;
- const result = await listStableCollectionPages(async () => {
- reads += 1;
- if (reads === 1) revision += 1;
- return page([{ id: `snapshot-${reads}` }], false);
- }, () => revision);
-
- expect(result).toEqual([{ id: "snapshot-2" }]);
- expect(reads).toBe(2);
- });
-
- it("returns no publishable snapshot after every allowed read is invalidated", async () => {
- let revision = 0;
- let reads = 0;
- const result = await listStableCollectionPages(async () => {
- reads += 1;
- revision += 1;
- return page([{ id: `unstable-${reads}` }], false);
- }, () => revision);
-
- expect(result).toBeNull();
- expect(reads).toBe(3);
- });
-});
-
describe("load-more collection pages", () => {
it("appends a page and returns the next cursor until Core reports the end", () => {
const first = appendCollectionPage([], page([{ id: "skill_3" }, { id: "skill_2" }], true, "skill_2"));
diff --git a/apps/web/src/lib/collection-pagination.ts b/apps/web/src/lib/collection-pagination.ts
index c9a73fb90..d270e0acd 100644
--- a/apps/web/src/lib/collection-pagination.ts
+++ b/apps/web/src/lib/collection-pagination.ts
@@ -1,67 +1,8 @@
-import type { ListPage, PageOptions } from "@oac/agents-client";
-
-const COLLECTION_PAGE_LIMIT = 100;
-const COLLECTION_PAGE_SAFETY_LIMIT = 100;
-
-export async function listAllCollectionPages(
- readPage: (options: PageOptions) => Promise>,
- signal?: AbortSignal,
-): Promise {
- const values: T[] = [];
- const ids = new Set();
- const cursors = new Set();
- let after: string | undefined;
-
- for (let pageIndex = 0; pageIndex < COLLECTION_PAGE_SAFETY_LIMIT; pageIndex += 1) {
- signal?.throwIfAborted();
- const page = await readPage({
- after,
- limit: COLLECTION_PAGE_LIMIT,
- order: "desc",
- signal,
- });
- if (!Array.isArray(page.data) || typeof page.has_more !== "boolean") {
- throw new Error("OpenAgentCore returned an invalid collection page.");
- }
- for (const value of page.data) {
- if (!value || typeof value.id !== "string" || value.id.length === 0 || ids.has(value.id)) {
- throw new Error("OpenAgentCore returned duplicate or invalid collection identities.");
- }
- ids.add(value.id);
- values.push(value);
- }
- if (!page.has_more) return values;
-
- const nextAfter = page.last_id ?? page.data.at(-1)?.id;
- if (!nextAfter || nextAfter === after || cursors.has(nextAfter)) {
- throw new Error("OpenAgentCore returned an invalid collection pagination cursor.");
- }
- cursors.add(nextAfter);
- after = nextAfter;
- }
-
- throw new Error("OpenAgentCore collection pagination exceeded the Web safety limit.");
-}
-
-export async function listStableCollectionPages(
- readPage: (options: PageOptions) => Promise>,
- readRevision: () => number,
- signal?: AbortSignal,
- attempts = 3,
-): Promise {
- for (let attempt = 0; attempt < attempts; attempt += 1) {
- signal?.throwIfAborted();
- const revision = readRevision();
- const values = await listAllCollectionPages(readPage, signal);
- signal?.throwIfAborted();
- if (revision === readRevision()) return values;
- }
- return null;
-}
+import type { ListPage } from "@oac/agents-client";
/**
- * Appends one cursor page to a "Load more" list. It applies the same identity
- * and cursor checks as the all-pages readers and returns the next cursor, or
+ * Appends one cursor page to a "Load more" list. It rejects repeated
+ * identities and cursors that do not advance, and returns the next cursor, or
* null once Core reports the end of the collection.
*/
export function appendCollectionPage(
diff --git a/apps/web/src/lib/console-routes.test.ts b/apps/web/src/lib/console-routes.test.ts
index 1fc5d04ed..db6e5bc49 100644
--- a/apps/web/src/lib/console-routes.test.ts
+++ b/apps/web/src/lib/console-routes.test.ts
@@ -13,15 +13,10 @@ describe("console routes", () => {
]);
});
- it("routes hashes, keeps old bookmarks and falls back to the overview", () => {
+ it("routes hashes and falls back to the overview", () => {
expect(consoleViewFromHash("")).toBe("overview");
expect(consoleViewFromHash("#vaults")).toBe("vaults");
expect(consoleViewFromHash("#session?project=proj_1&id=s1")).toBe("session");
- expect(consoleViewFromHash("#builder")).toBe("agents");
- expect(consoleViewFromHash("#playground")).toBe("sessions");
- expect(consoleViewFromHash("#workbench")).toBe("overview");
- expect(consoleViewFromHash("#sandbox")).toBe("nodes");
- expect(consoleViewFromHash("#api-keys")).toBe("projects");
expect(consoleViewFromHash("#unknown")).toBe("overview");
expect(consoleHashForView("overview")).toBe("");
expect(consoleHashForView("settings")).toBe("#settings");
diff --git a/apps/web/src/lib/console-routes.ts b/apps/web/src/lib/console-routes.ts
index 2c9cbe1ab..4ea7fb9f4 100644
--- a/apps/web/src/lib/console-routes.ts
+++ b/apps/web/src/lib/console-routes.ts
@@ -47,19 +47,9 @@ const routedViews = new Set([
...Object.keys(consoleSecondaryViews),
]);
-/** Earlier console releases used these hashes; keep bookmarks working. */
-const legacyHashes: Readonly> = {
- dashboard: "overview",
- sandbox: "nodes",
- builder: "agents",
- playground: "sessions",
- workbench: "overview",
- "api-keys": "projects",
-};
-
export function consoleViewFromHash(hash: string): ConsoleView {
const candidate = hash.startsWith("#") ? hash.slice(1).split("?")[0]! : hash;
- return legacyHashes[candidate] ?? (routedViews.has(candidate) ? candidate as ConsoleView : "overview");
+ return routedViews.has(candidate) ? candidate as ConsoleView : "overview";
}
export function consoleHashForView(view: ConsoleView): string {
diff --git a/contracts/agents-api/index.md b/contracts/agents-api/index.md
index feaa326bc..e8b8cc5ea 100644
--- a/contracts/agents-api/index.md
+++ b/contracts/agents-api/index.md
@@ -72,7 +72,7 @@ Each item is Core's deliberate or native behavior where the official service beh
**Agents and Sessions** ([Agents](./wire-semantics.md#agents), [Sessions](./wire-semantics.md#sessions))
- A repeated Session creation with the same `Idempotency-Key` returns the original Session; the official service creates a new one.
-- Omitted programmatic tool calling keeps the harness's native behavior; the official default is on.
+- Omitted programmatic tool calling keeps the Harness's native behavior; the official default is on.
- An omitted reasoning effort stays null instead of taking the model's default.
- A Session's `agent.tools` omits `tool_search` declarations.
- Deleting a Session right after an events 202 returns 409, because Core admits the Turn in the same transaction; the official service returned 200.
diff --git a/contracts/agents-api/message-content.md b/contracts/agents-api/message-content.md
index de27f670e..62f0853f6 100644
--- a/contracts/agents-api/message-content.md
+++ b/contracts/agents-api/message-content.md
@@ -21,15 +21,15 @@ An `input_image` part carries `image_url` as an inline data URI: `data:image/png
| Harness | Message images |
| --- | --- |
-| Codex | Accepted on every placement the harness supports: `none`, `openai_hosted` and `self_hosted` |
+| Codex | Accepted on every placement the Harness supports: `none`, `openai_hosted` and `self_hosted` |
| Claude Code | Accepted on `none`, `openai_hosted` and `self_hosted` |
| MiniMax Code | Rejected |
-Admission checks the harness before anything is written; an image the harness cannot take returns 400. The Runtime must also report message image support: Core binds a Session whose input carries images only to such a Runtime, and delivery to a Runtime without it fails. Use a model that accepts images.
+Admission checks the Harness before anything is written; an image the Harness cannot take returns 400. The Runtime must also report message image support: Core binds a Session whose input carries images only to such a Runtime, and delivery to a Runtime without it fails. Use a model that accepts images.
## Whitespace-only text
-Whitespace-only text such as `" "` or `"\n\t"` is valid content and is stored and returned verbatim. Whether a harness can run it is declared in its engine profile:
+Whitespace-only text such as `" "` or `"\n\t"` is valid content and is stored and returned verbatim. Whether a Harness can run it is declared in its engine profile:
| Harness | A message with no image and no non-whitespace text |
| --- | --- |
@@ -37,7 +37,7 @@ Whitespace-only text such as `" "` or `"\n\t"` is valid content and is stored
| Claude Code | 400 `unsupported_or_invalid_configuration` |
| MiniMax Code | 400 `unsupported_or_invalid_configuration` |
-The rejection applies to Session creation (including streaming and `self_hosted` creation) and to `events.create`, before any write, reservation or Turn, so a running Turn is never disturbed. Whitespace beside non-whitespace text in the same message is admitted for every harness. Whitespace is the union of Go `unicode.IsSpace` and ECMAScript `String.prototype.trim`, for example U+0085 and U+FEFF; Core admission and the Claude bridge use the same set.
+The rejection applies to Session creation (including streaming and `self_hosted` creation) and to `events.create`, before any write, reservation or Turn, so a running Turn is never disturbed. Whitespace beside non-whitespace text in the same message is admitted for every Harness. Whitespace is the union of Go `unicode.IsSpace` and ECMAScript `String.prototype.trim`, for example U+0085 and U+FEFF; Core admission and the Claude bridge use the same set.
## Function results
@@ -49,22 +49,22 @@ An `agent.session.input.tool_result` event carries `success`, an optional nullab
| Harness | Function results |
| --- | --- |
-| Codex | Text and ordered text/image output. Core checks only that each part is well formed and passes image references to the harness unchanged |
-| Claude Code | Text output. Images only in successful results and only as inline PNG or JPEG; an image in a failed result or a remote reference returns 400 before anything is stored, and the pending call stays open. The harness may resize or re-encode images in its own history; public Items keep the submitted bytes |
+| Codex | Text and ordered text/image output. Core checks only that each part is well formed and passes image references to the Harness unchanged |
+| Claude Code | Text output. Images only in successful results and only as inline PNG or JPEG; an image in a failed result or a remote reference returns 400 before anything is stored, and the pending call stays open. The Harness may resize or re-encode images in its own history; public Items keep the submitted bytes |
| MiniMax Code | No public functions |
### Application receipts
-Admission (202) does not mean the harness used the result. The pending call clears when the adapter confirms native application:
+Admission (202) does not mean the Harness used the result. The pending call clears when the adapter confirms native application:
- **Claude Code** confirms with a live root native tool result that matches the Session, call ID, success flag, exact text, block count and order, with a native image at every image position. Replayed, synthetic and Subagent records do not confirm it.
-- **Codex** confirms with the live root dynamic-tool `item/completed` observation that matches thread, Turn, call, function name, status, success flag and the exact ordered content. A write to the harness alone does not confirm it.
+- **Codex** confirms with the live root dynamic-tool `item/completed` observation that matches thread, Turn, call, function name, status, success flag and the exact ordered content. A write to the Harness alone does not confirm it.
-Both adapters wait at most 10 seconds for a receipt. A timeout or native release without confirmation leaves application uncertain. Confirmation means the harness recorded the result, not that the model provider consumed it. Core never replays a result automatically; the submission stays stored for recovery reads.
+Both adapters wait at most 10 seconds for a receipt. A timeout or native release without confirmation leaves application uncertain. Confirmation means the Harness recorded the result, not that the model provider consumed it. Core never replays a result automatically; the submission stays stored for recovery reads.
## Runtime boundary
-The Core–Runtime wire carries messages as `MessageInput` for initial input, prepared start and steering, with the same ordered `InputContent` parts that function results use ([Core–Runtime protocol](../../docs/runtime-protocol.md)). Admission checks the harness's declared profile; binding and delivery check what the Runtime reports. Adapters own native encoding and application receipts. A text-only adapter rejects image parts instead of dropping them.
+The Core–Runtime wire carries messages as `MessageInput` for initial input, prepared start and steering, with the same ordered `InputContent` parts that function results use ([Core–Runtime protocol](../../docs/runtime-protocol.md)). Admission checks the Harness's declared profile; binding and delivery check what the Runtime reports. Adapters own native encoding and application receipts. A text-only adapter rejects image parts instead of dropping them.
- **Codex** flattens a batch into its native input list with a blank-line separator between public messages. Public message boundaries stay in Core's storage; the native history does not keep them.
- **Claude Code** sends native image blocks and a UUID per native user message. One public input is applied only after every message in its batch is consumed. Within one native Turn the bridge accepts at most 64 user messages, including the opening prompt; it rejects a steering batch that would exceed the bound before submitting any part of it, which ends the running Turn. The daemon requires bridge protocol 3.
diff --git a/contracts/agents-api/sessions-events.md b/contracts/agents-api/sessions-events.md
index 49827bc6e..490ff5448 100644
--- a/contracts/agents-api/sessions-events.md
+++ b/contracts/agents-api/sessions-events.md
@@ -29,16 +29,16 @@ A Session stays usable after a Turn fails: new input starts a new Turn. Later re
## Send input
-`POST /v1/agents/sessions/{session_id}/events` takes an ordered array of 1 to 64 events: `agent.session.input.message`, `agent.session.input.cancel` and `agent.session.input.tool_result`. The whole batch is admitted atomically, and the response is 202 with no body once the batch is stored, before any harness reads it. Admission never confirms native application.
+`POST /v1/agents/sessions/{session_id}/events` takes an ordered array of 1 to 64 events: `agent.session.input.message`, `agent.session.input.cancel` and `agent.session.input.tool_result`. The whole batch is admitted atomically, and the response is 202 with no body once the batch is stored, before any Harness reads it. Admission never confirms native application.
- **Limits.** The request body is at most 1 MiB, and the stored input of one request at most 512 KiB.
- **Null batch.** An explicit `null` for `events` is invalid.
- **Empty batch.** `{"events": []}` checks that the Session exists and returns 202. It creates no Turn, Item or retry identity.
- **Retries.** An `Idempotency-Key` of up to 128 bytes identifies the whole ordered batch. The same key and batch return 202 again without admitting anything twice; the same key with another batch returns 409 `idempotency_conflict`. A request without a key is always new.
-- **Messages.** On an idle Session a message batch starts a queued Turn. While a Turn runs, messages join it (steering); they never start a parallel Turn. Each message stays its own user Item, even when the harness receives several as one prompt.
+- **Messages.** On an idle Session a message batch starts a queued Turn. While a Turn runs, messages join it (steering); they never start a parallel Turn. Each message stays its own user Item, even when the Harness receives several as one prompt.
- **Cancellation.** A queued Turn is cancelled without a live Runtime. A running Turn is cancelled when the Runtime confirms it; completion can win that race. The Turn has stopped when it reads `cancelled`, not when the request returns. A cancellation on an idle Session with no pending input is accepted and has no effect; while an input reservation is pending, it returns 409.
-- **Function results.** `turn_id`, `call_id` and `success` are required; `output` and `error` are optional and nullable ([content rules](./message-content.md#function-results)). An identical repeated result returns 202 without another application or event. The result Item appears when the harness applies the result; a result that cancellation prevents from being applied stays stored but produces no Item.
-- **Queueing.** A queued Turn starts when a Runtime that supports the Session's harness and configuration is connected and one of Core's [`OAC_EXECUTION_CONCURRENCY`](../../docs/configuration.md#settings) work slots is free. A Session stays bound to the Runtime that first ran it.
+- **Function results.** `turn_id`, `call_id` and `success` are required; `output` and `error` are optional and nullable ([content rules](./message-content.md#function-results)). An identical repeated result returns 202 without another application or event. The result Item appears when the Harness applies the result; a result that cancellation prevents from being applied stays stored but produces no Item.
+- **Queueing.** A queued Turn starts when a Runtime that supports the Session's Harness and configuration is connected and one of Core's [`OAC_EXECUTION_CONCURRENCY`](../../docs/configuration.md#settings) work slots is free. A Session stays bound to the Runtime that first ran it.
- **Execution availability.** While Core shuts down, or after its Worker loses execution ownership, requests return 503 `execution_unavailable`.
### Sessions with an Environment
@@ -62,7 +62,7 @@ Checks run in this order: request validation, Session lookup, retry lookup, the
| A missing, malformed or foreign Session | 404 `not_found_error` | "Resource not found." |
| New input after an `openai_hosted` Environment failed to provision | 409 `conflict_error` | "the hosted environment failed to provision" |
| New input after a `self_hosted` Environment failed, input already waiting when the Environment failed, or an expired Environment | 409 `environment_unavailable` | "The environment is no longer available for new input." |
-| A message the Session's harness cannot take, such as whitespace-only text on Claude Code | 400 `unsupported_or_invalid_configuration` | See [whitespace-only text](./message-content.md#whitespace-only-text) |
+| A message the Session's Harness cannot take, such as whitespace-only text on Claude Code | 400 `unsupported_or_invalid_configuration` | See [whitespace-only text](./message-content.md#whitespace-only-text) |
An empty `turn_id` or blank `call_id` is the generic 400 `invalid_request`. Error messages never repeat caller input or internal identifiers.
@@ -106,7 +106,7 @@ A retry with the same `Idempotency-Key` and `stream: true` returns 201 with only
- An assistant message follows one sequence: `item.added` in progress with empty `content`, `content_part.added` with empty text, `output_text.delta` events, `output_text.done`, `content_part.done` and `item.done`. A message first observed complete, such as structured output, sends its whole text in one `output_text.delta`, byte for byte. The completed text replaces the accumulated deltas.
- Codex command output streams as `agent.output.command_execution_output.delta` with the command's Item ID and output index. Native output quotas and text conversion apply, so the deltas are not a byte-exact capture; the completed Item is authoritative.
- A cancelled or failed Turn marks its unfinished Items `incomplete` and keeps their partial content.
-- A function call stays in `required_actions` until the harness applies its result, or cancellation or the Turn's end removes it. A repeated notification emits no new state.
+- A function call stays in `required_actions` until the Harness applies its result, or cancellation or the Turn's end removes it. A repeated notification emits no new state.
## Turns and Items
@@ -118,7 +118,7 @@ Turn and Item lists take `after`, `limit` and `order` ([list rules](./wire-seman
| Item `type` | Content |
| --- | --- |
-| `message` | User or assistant content parts. `phase` is the harness's phase when it reports one (`commentary`, `final_answer`), otherwise null |
+| `message` | User or assistant content parts. `phase` is the Harness's phase when it reports one (`commentary`, `final_answer`), otherwise null |
| `command_execution` | Command, reported output, exit code, duration and working directory |
| `mcp_call` | Server and tool identity, arguments, structured result or error |
| `function_call`, `function_call_output` | A linked call and its result. The result always carries `output` and `error`, null when the submission omitted them; stored results keep the submitted field presence. Native file changes appear as an `apply_patch` function call with the changes as arguments and no invented result |
@@ -131,9 +131,9 @@ A failed tool does not fail its Turn. Tool output is readable by the Session's P
Turn and Session `usage` uses the pinned `TokenUsage` fields: input, cached input, output, reasoning output and total tokens. Null means unknown, never zero.
-- **Turn usage** is the latest complete snapshot the harness reported for that Turn. A new snapshot replaces the previous one; repeats never add. Stored snapshots survive cancellation and Worker restarts.
+- **Turn usage** is the latest complete snapshot the Harness reported for that Turn. A new snapshot replaces the previous one; repeats never add. Stored snapshots survive cancellation and Worker restarts.
- **Session usage** is the sum of root Turn usage when every root Turn has ended (completed, failed or cancelled) with known usage. It is null while any root Turn is queued, running or waiting, and stays null once a root Turn ends without usage. Subagent Turns do not count.
-- **By harness.** Codex reports measured snapshots while a Turn runs and at its end; a Turn interrupted before any usage report stays null. Claude Code and MiniMax Code report no complete public breakdown, so their usage is null.
+- **By Harness.** Codex reports measured snapshots while a Turn runs and at its end; a Turn interrupted before any usage report stays null. Claude Code and MiniMax Code report no complete public breakdown, so their usage is null.
Usage is best-effort accounting of reported measurements. It is not an invoice, and Core never estimates missing usage.
diff --git a/contracts/agents-api/wire-semantics.md b/contracts/agents-api/wire-semantics.md
index 2a62ed66b..aca69c414 100644
--- a/contracts/agents-api/wire-semantics.md
+++ b/contracts/agents-api/wire-semantics.md
@@ -207,7 +207,7 @@ Omitted, null and explicit `medium` text verbosity give the same Session configu
### Configuration snapshot
-Session creation copies the effective Agent configuration into an immutable snapshot. With `agent_id`, the saved Agent is read once; fields in the inline `agent` replace the saved field whole, including arrays, and null `tools` clears the list. Omitted fields inherit; an inline `x_agents_core` that omits `harness` keeps the saved harness. Saved Agent metadata never becomes Session metadata. Later Agent updates or deletion affect only new Sessions.
+Session creation copies the effective Agent configuration into an immutable snapshot. With `agent_id`, the saved Agent is read once; fields in the inline `agent` replace the saved field whole, including arrays, and null `tools` clears the list. Omitted fields inherit; an inline `x_agents_core` that omits `harness` keeps the saved Harness. Saved Agent metadata never becomes Session metadata. Later Agent updates or deletion affect only new Sessions.
`stream` defaults to false. `stream` and `agent_id` cannot be null. Omitted or null `metadata` is `{}`.
diff --git a/contracts/agents-api/zh/admin-api.md b/contracts/agents-api/zh/admin-api.md
index 543a0dc5b..594eb9bc0 100644
--- a/contracts/agents-api/zh/admin-api.md
+++ b/contracts/agents-api/zh/admin-api.md
@@ -4,7 +4,7 @@ source: contracts/agents-api/admin-api.md
source_hash: 9c83e8b192408ea96e8614dfa5ffe4bdd65931954bc0359928c1985291b97962
---
-Core 管理 API(`/core/v1`)用于管理安装实例:Project 及其 API 密钥、Project 资源的读取和删除、执行器凭据、部署默认模型、沙箱部署及其节点、监控和审计。Web 的[控制台服务器](../../../docs/zh/web/console-server.md#forwarding-to-core)会为已登录的管理员调用它;运维人员则从 Core 主机上的脚本调用它([编写 Core API 脚本](../../../docs/zh/getting-started/operations.md#script-the-core-api))。生成的架构是 [core.openapi.yaml](../core.openapi.yaml),所有错误都使用 [Core 错误封装](core-errors.md)。
+Core 管理 API(`/core/v1`)用于管理安装实例:项目及其 API 密钥、项目资源的读取和删除、执行器凭据、部署默认模型、沙箱部署及其节点、监控和审计。Web 的[控制台服务器](../../../docs/zh/web/console-server.md#forwarding-to-core)会为已登录的管理员调用它;运维人员则从 Core 主机上的脚本调用它([编写 Core API 脚本](../../../docs/zh/getting-started/operations.md#script-the-core-api))。生成的架构是 [core.openapi.yaml](../core.openapi.yaml),所有错误都使用 [Core 错误封装](core-errors.md)。
应用程序绝不调用 `/core/v1`。它没有任何用于创建或编辑 Agents、Sessions、模板、Files、Skills 或 Vaults,启动或取消工作,读取 Source File 内容或流式传输事件的操作;应用程序通过 [Agents API](../../../docs/zh/api/public-agent-api.md)完成这些操作。
@@ -13,9 +13,9 @@ Core 管理 API(`/core/v1`)用于管理安装实例:Project 及其 API 密
每个 `/core/v1` 请求,包括针对未知路径的请求,都必须发送 `Authorization: Bearer `。缺少该请求头时,Core 会返回 401 `invalid_admin_key` 和 `WWW-Authenticate: Bearer`;只有在身份验证通过后,未知路径才会返回 404 `not_found`。
- Core 将 bearer 凭据的 SHA-256 与启动时从 `generated/core-key-digests.json` 读取的 Core 密钥摘要进行比较;该摘要由 `oac apply` 根据 `secrets/core.key` 派生([Core 密钥](../../../docs/zh/getting-started/operations.md#core-key))。轮换 Core 密钥后,需要重启 Core 才会生效。未配置任何摘要时,Core 不提供 `/core/v1` 路由。
-- Core 密钥仅用于 `/core/v1` 身份验证。Project API 密钥和机器凭据在此处会收到 401,而 Core 密钥在 `/v1` 和 `/api/v1` 上会收到 401([API 命名空间和凭据](../../../docs/zh/api/index.md))。
+- Core 密钥仅用于 `/core/v1` 身份验证。项目 API 密钥和机器凭据在此处会收到 401,而 Core 密钥在 `/v1` 和 `/api/v1` 上会收到 401([API 命名空间和凭据](../../../docs/zh/api/index.md))。
- `X-Core-Console-Actor` 是由调用方声明的标签。Core 会将其记录为审计 `actor_label`,但不会验证。控制台服务器发送 `console`;脚本通常不发送该值,因此会记录空标签。切勿将其用于授权或作为来源证明。
-- 路径中的 `{project_id}` 用于选择目标 Project,包括已归档的 Project;它不会授予任何权限。
+- 路径中的 `{project_id}` 用于选择目标项目,包括已归档的项目;它不会授予任何权限。
## 路由 {#routes}
@@ -25,7 +25,7 @@ Core 管理 API(`/core/v1`)用于管理安装实例:Project 及其 API 密
| --- | --- | --- |
| `installation` | 公共 URL、API 基础 URL、源代码提交、安装器的进程设置,以及绑定到公共 URL 的内容 | [安装信息](#installation-facts) |
| `workspace-storage` | 读取或选择独立工作区文件系统配置 | [工作区存储](#workspace-storage) |
-| `projects`、`projects/{project_id}`、`projects/{project_id}/archive`、`projects/{project_id}/keys[/{key_id}]` | Project 及其 API 密钥 | [Project 与密钥](#projects-and-keys) |
+| `projects`、`projects/{project_id}`、`projects/{project_id}/archive`、`projects/{project_id}/keys[/{key_id}]` | 项目及其 API 密钥 | [项目与密钥](#projects-and-keys) |
| `projects/{project_id}/{agents,environment-templates,skills,files,vaults,sessions}/**` | 资源读取和删除、Session 历史及 Artifact | [资源读取和删除](#resource-reads-and-deletion) |
| `projects/{project_id}/sessions/{session_id}/archive` | 归档一个托管 Session | [Session 归档](#session-archive) |
| `projects/{project_id}/sessions/{session_id}/execution-configuration` | Session 创建时冻结的模型、Harness 和提供商选择 | [执行配置](#execution-configuration) |
@@ -38,14 +38,14 @@ Core 管理 API(`/core/v1`)用于管理安装实例:Project 及其 API 密
| `harnesses`、`harnesses/{harness}/model-configuration` | 已启用的 Harness 及各 Harness 的部署默认模型 | [部署默认值](model-execution.md#deployment-defaults) |
| `sandbox/deployment`、`sandbox/deployment/reset`、`sandbox/providers/{provider}/discovery` | 沙箱提供商、资源和 Runtime、空闲挂起策略、重置,以及提供商配置发现,例如 E2B 模板 | [沙箱部署](sandbox-deployment.md#routes) |
| `sandbox/enrollment-tokens`、`sandbox/nodes[/{node_id}[/allocations]]` | 节点注册令牌、节点及其分配和主机历史 | [节点指南](../../../docs/zh/getting-started/nodes.md)、[沙箱部署](sandbox-deployment.md)、[节点主机历史](runtime-observability-api.md#node-host-observations-and-history) |
-| `summary` | 按 Project、Agent 或密钥统计的 Session 数量和使用情况 | [汇总](#summary) |
+| `summary` | 按项目、Agent 或密钥统计的 Session 数量和使用情况 | [汇总](#summary) |
| `metrics` | Core 自身的进程、执行、数据库和作业指标 | [Core 指标](core-metrics.md) |
| `request-logs` | 近期应用或管理 HTTP 请求及其响应元数据 | [请求日志](#request-log) |
| `audit-log` | 管理员写入 | [审计日志](#audit-log) |
## 请求日志 {#request-log}
-`GET /core/v1/request-logs` 是仅供 Core 密钥调用的诊断读取,由 Web 的 **Request log** 和运维脚本使用。它观察到达 Core `/v1` 与 `/core/v1` API 的 HTTP 请求,包括认证拒绝和失败响应。日志读取本身、健康检查与文档端点、到达 Core 前的 Web 登录或代理失败、机器传输和后台执行不在此视图中。它不是审计档案或分布式执行追踪。
+`GET /core/v1/request-logs` 是仅供 Core 密钥调用的诊断读取,由 Web 的 **请求日志** 和运维脚本使用。它观察到达 Core `/v1` 与 `/core/v1` API 的 HTTP 请求,包括认证拒绝和失败响应。日志读取本身、健康检查与文档端点、到达 Core 前的 Web 登录或代理失败、机器传输和后台执行不在此视图中。它不是审计档案或分布式执行追踪。
每个 API 实例按入口分别保留最近开始的 1,000 个请求:`public` 对应 `/v1`,`admin` 对应 `/core/v1`。管理页面轮询不会挤掉应用请求。各自容量用尽后覆盖较旧条目,包括长连接请求;重启清空记录。`instance_id` 和 `instance_started_at` 标识提供响应的 API 实例;负载均衡可能返回另一个实例的窗口。Core 同时通过现有结构化日志输出请求结束时的元数据,其保留由运维日志系统负责,不属于本端点。
@@ -57,31 +57,31 @@ Core 管理 API(`/core/v1`)用于管理安装实例:Project 及其 API 密
## 工作区存储 {#workspace-storage}
-**Settings → Workspace storage** 和运维脚本使用 Core key 调用 `GET /core/v1/workspace-storage` 和 `PUT /core/v1/workspace-storage`。成功响应为选择结果:`{"id":"","adapter":"","parameters":{...},"tenant_capacity_mib":}`。请求包含相同的必需字段,以及可选的只写 `credential` 对象。`parameters` 和 `credential` 是适配器定义的 JSON 对象,由所选适配器验证。未知顶层字段会被拒绝。
+**设置 → 工作区存储** 和运维脚本使用 Core 密钥调用 `GET /core/v1/workspace-storage` 和 `PUT /core/v1/workspace-storage`。成功响应为选择结果:`{"id":"","adapter":"","parameters":{...},"tenant_capacity_mib":}`。请求包含相同的必需字段,以及可选的只写 `credential` 对象。`parameters` 和 `credential` 是适配器定义的 JSON 对象,由所选适配器验证。未知顶层字段会被拒绝。
GET 返回所选配置和租户容量策略;尚未配置时返回 404 `workspace_storage_not_found`。它绝不返回凭据。PUT 验证并选择不可变配置,同时设置 [`tenant_capacity_mib`](../../../docs/zh/configuration.md#tenant-capacity),以 200 返回选择结果。正的 `tenant_capacity_mib` 要求实施容量配额的配置,此类配置也要求正值;否则 PUT 返回 400 `workspace_operation_unsupported`。Core 加密凭据,绝不返回、记录日志或审计凭据。复用 ID 要求适配器、参数和凭据完全一致;省略 `credential` 会保留已存储的凭据,显式 `null` 无效。更改其含义或与保留归属冲突会返回 409 `workspace_storage_conflict`。配置更改与工作区归属变更串行执行,成功变更携带与其他部署设置相同的管理员审计来源。[工作区文件系统协议](../../../docs/zh/workspace-provider.md) 规定标识、挂载、准入和保留语义。
-无效配置返回 400 `invalid_workspace_configuration`;不支持的适配器或组合返回 400 `workspace_operation_unsupported`。存储不可用或操作尚未确认返回 503 `workspace_storage_unavailable`。错误消息不暴露原生路径或适配器错误文本。此端点独立于 Sandbox Provider 选择配置存储,不创建或删除 Session 工作区。
+无效配置返回 400 `invalid_workspace_configuration`;不支持的适配器或组合返回 400 `workspace_operation_unsupported`。存储不可用或操作尚未确认返回 503 `workspace_storage_unavailable`。错误消息不暴露原生路径或适配器错误文本。此端点独立于沙箱提供商选择配置存储,不创建或删除 Session 工作区。
-## Project 与密钥 {#projects-and-keys}
+## 项目与密钥 {#projects-and-keys}
-每个 Project 拥有一个执行租户;其密钥共享该租户的主体和资产([Project 拥有资产](../../../docs/zh/concepts.md#projects-own-assets))。Web 的 **Projects and keys** 页面使用这些路由。
+每个项目拥有一个执行租户;其密钥共享该租户的主体和资产([项目拥有资产](../../../docs/zh/concepts.md#projects-own-assets))。Web 的 **项目与密钥** 页面使用这些路由。
| 操作 | 路由 | 结果 |
| --- | --- | --- |
-| 列出 Project | `GET /projects` | `{data, has_more}` |
-| 创建 Project | `POST /projects`,请求体为 `{name}` | 201 和 Project |
-| 重命名 Project | `POST /projects/{project_id}`,请求体为 `{name}` | Project |
-| 归档 Project | `POST /projects/{project_id}/archive` | Project |
+| 列出项目 | `GET /projects` | `{data, has_more}` |
+| 创建项目 | `POST /projects`,请求体为 `{name}` | 201 和项目 |
+| 重命名项目 | `POST /projects/{project_id}`,请求体为 `{name}` | 项目 |
+| 归档项目 | `POST /projects/{project_id}/archive` | 项目 |
| 列出密钥 | `GET /projects/{project_id}/keys` | `{data, has_more}` |
| 签发密钥 | `POST /projects/{project_id}/keys`,请求体为 `{name}` | 201、密钥元数据和明文 `key` |
| 吊销密钥 | `DELETE /projects/{project_id}/keys/{key_id}` | `{id, deleted: true}` |
-- Project 包含 `id`、`name`、`created_at`、可为 null 的 `archived_at` 和 `active_key_count`。密钥包含 `id`、`project_id`、`name`、`prefix`、`created_at` 和可为 null 的 `revoked_at`。ID 是服务器生成的 UUID。
-- Project 名称长度为 1–128 个字符,密钥名称长度为 1–80 个字符;名称仅作为标签,可以重复,控制字符会被拒绝。
+- 项目包含 `id`、`name`、`created_at`、可为 null 的 `archived_at` 和 `active_key_count`。密钥包含 `id`、`project_id`、`name`、`prefix`、`created_at` 和可为 null 的 `revoked_at`。ID 是服务器生成的 UUID。
+- 项目名称长度为 1–128 个字符,密钥名称长度为 1–80 个字符;名称仅作为标签,可以重复,控制字符会被拒绝。
- 列表按 ID 排序,可使用 `order=asc|desc`(默认 `desc`)、`limit=1..100`(默认 20)和 `after`。
- 只有签发响应会通过 `key` 包含密钥明文;Core 仅存储其摘要。密钥只应显示一次,且绝不能缓存。如果签发响应不确定,请列出密钥,吊销所有无法使用的密钥,然后再签发新密钥。
-- 归档操作会在一个事务中将 Project 标记为已归档、吊销其所有密钥并写入审计条目。在已归档的 Project 中签发密钥会返回 409 `project_archived`。不支持删除 Project、取消归档或重置密钥。
+- 归档操作会在一个事务中将项目标记为已归档、吊销其所有密钥并写入审计条目。在已归档的项目中签发密钥会返回 409 `project_archived`。不支持删除项目、取消归档或重置密钥。
[`/v1` 身份验证规则](wire-semantics.md#authentication)定义了密钥查找、吊销可见性、作用域标头和身份验证错误。
@@ -92,7 +92,7 @@ GET 返回所选配置和租户容量策略;尚未配置时返回 404 `workspa
| 资源 | 读取 | 删除 |
| --- | --- | --- |
| Agents | `/agents`、`/agents/{agent_id}` | `/agents/{agent_id}` |
-| Environment Templates | `/environment-templates`、`/environment-templates/{environment_template_id}` | 单项路由 |
+| Environment 模板 | `/environment-templates`、`/environment-templates/{environment_template_id}` | 单项路由 |
| Skills | `/skills`、`/skills/{skill_id}`、`/skills/{skill_id}/content`、`/skills/{skill_id}/versions`、`/skills/{skill_id}/versions/{version}` 及其 `/content` | Skill 和版本单项路由 |
| Files | `/files`、`/files/{file_id}` | 单项路由 |
| Vaults | `/vaults`、`/vaults/{vault_id}`、`/vaults/{vault_id}/credentials`、`/vaults/{vault_id}/credentials/{credential_id}` | Vault 和 Credential 单项路由 |
@@ -111,7 +111,7 @@ GET 返回所选配置和租户容量策略;尚未配置时返回 404 `workspa
| --- | --- |
| 代次过期 | 409 `sandbox_generation_stale` |
| Environment 类型不是 `openai_hosted` | 400 |
-| Session 不存在或属于另一个 Project | 404 |
+| Session 不存在或属于另一个项目 | 404 |
一个事务会将 Environment 标记为过期(已失败的 Environment 仍保持失败状态)、请求取消正在运行的工作、吊销 Runtime 的权限并写入审计条目。沙箱及其快照随后通过正常生命周期完成清理;如果资源是否已释放尚不确定,在提供商确认之前,该资源仍归 Core 所有。Session 不会被删除:其历史以及已持久化的 Files 和 Artifacts 仍可读取,未持久化的工作区内容会丢失,并且该 Session 无法恢复运行。
@@ -147,7 +147,7 @@ GET 返回所选配置和租户容量策略;尚未配置时返回 404 `workspa
| `redacted` | 记录了部署选择,但没有安全视图 | null |
| `unavailable` | Core 没有关于该提供商的可靠记录(来源 `unknown`)。执行仍可能已成功 | null |
-Core 会在创建 Session 的同一事务中写入此记录。之后的 Agent 编辑或删除、部署默认模型更改、重启以及使用同一密钥重试创建都不会改变该记录。没有该记录的 Session 会报告其已存储的模型和 Harness,来源均为 `unknown`;未存储任何值时对应字段为 null;提供商为 `unavailable`。Session 不存在和 Session 属于另一个 Project 时返回相同的 404。响应绝不会包含密钥、密文、机密引用、原生标头或查询参数。
+Core 会在创建 Session 的同一事务中写入此记录。之后的 Agent 编辑或删除、部署默认模型更改、重启以及使用同一密钥重试创建都不会改变该记录。没有该记录的 Session 会报告其已存储的模型和 Harness,来源均为 `unknown`;未存储任何值时对应字段为 null;提供商为 `unavailable`。Session 不存在和 Session 属于另一个项目时返回相同的 404。响应绝不会包含密钥、密文、机密引用、原生标头或查询参数。
## 安装信息 {#installation-facts}
@@ -158,7 +158,7 @@ Core 会在创建 Session 的同一事务中写入此记录。之后的 Agent
| `object` | `core.installation` |
| `installation_id` | `OAC_INSTALLATION_ID_FILE` 中的安装 ID([Compose 安装](../../../docs/zh/configuration.md#compose-installations)) |
| `public_url` | `public_url` 设置([设置](../../../docs/zh/configuration.md#settings)):应用程序、节点、沙箱和自托管执行器使用的源地址 |
-| `api_base_url` | 在 `public_url` 后附加 `/v1`,即 Project API 密钥使用的 `OPENAI_BASE_URL` |
+| `api_base_url` | 在 `public_url` 后附加 `/v1`,即项目 API 密钥使用的 `OPENAI_BASE_URL` |
| `local_only` | 当 `public_url` 指向回环主机时为 True,该主机只能由 Core 主机访问 |
| `source_commit` | Core 构建所依据的完整源代码提交;开发构建为 null |
| `configuration` | Core 从环境加载的进程设置,位于 `settings` 中 |
@@ -177,7 +177,7 @@ Core 会在创建 Session 的同一事务中写入此记录。之后的 Agent
## 写入溯源 {#write-provenance}
-Core 会记录是哪个 Project API 密钥完成了每次成功的公共写入;该记录与写入在同一事务中完成,如果记录失败,写入也会失败。读取、被拒绝的请求以及 Core 自身的维护操作(例如 OAuth 令牌刷新和清理)不会被记录。
+Core 会记录是哪个项目 API 密钥完成了每次成功的公共写入;该记录与写入在同一事务中完成,如果记录失败,写入也会失败。读取、被拒绝的请求以及 Core 自身的维护操作(例如 OAuth 令牌刷新和清理)不会被记录。
- 写入在提交时才会被记录。Session 输入一经接纳即记录一次,包括为仍在准备中的 Environment 预留的输入;后续执行失败或响应丢失不会删除该记录。显式提交的空输入批次以及重复的创建或删除操作也会被记录,但不会改变所有权。
- Environment 文件上传会在 Runtime 确认写入时被记录。Core 会在发送文件前保存密钥、请求和追踪信息,并且只记录已确认的上传。
@@ -192,14 +192,14 @@ Core 会记录是哪个 Project API 密钥完成了每次成功的公共写入
| Session 事件 | `send_events` | `session` |
| Artifact 删除 | `delete` | `artifact`(`session`) |
| Environment 文件上传 | `upload_file` | `environment`(`session`) |
-| Environment Template 创建、更新、删除 | `create`、`update`、`delete` | `environment_template` |
+| Environment 模板创建、更新、删除 | `create`、`update`、`delete` | `environment_template` |
| Skill 创建、默认版本更改、删除 | `create`、`update_default_version`、`delete` | `skill` |
| Skill 版本上传、删除 | `upload_version`、`delete` | `skill_version`(`skill`) |
| Source File 上传、删除 | `create`、`delete` | `file` |
| Vault 创建、删除 | `create`、`delete` | `vault` |
| Credential 创建、替换、删除(静态和 OAuth) | `create`、`update`、`delete` | `credential`(`vault`) |
-上述两条路由仅接受列出的参数;未知、重复或空参数会返回 400,Project 不存在则返回 404。
+上述两条路由仅接受列出的参数;未知、重复或空参数会返回 400,项目不存在则返回 404。
`GET /projects/{project_id}/resource-owners?resource_type=agent&resource_ids=id1,id2` 按请求顺序返回同一类型下 1–100 个资源的创建密钥。`resource_type` 可以是 `agent`、`session`、`environment`、`environment_template`、`skill`、`skill_version`、`file`、`vault`、`credential` 或 `artifact`。
@@ -210,7 +210,7 @@ Core 会记录是哪个 Project API 密钥完成了每次成功的公共写入
]}
```
-当 Core 没有创建记录时,`api_key` 为 null,这包括另一个 Project 中的资源。
+当 Core 没有创建记录时,`api_key` 为 null,这包括另一个项目中的资源。
`GET /projects/{project_id}/write-operations` 按 `(created_at, id)` 从新到旧列出写入记录。过滤条件包括:`key_id`、`resource_type`、`resource_id`、包含起始时间的 `created_after` 和不包含结束时间的 `created_before`(RFC 3339)。`limit` 为 1–100,默认值为 50。在过滤条件不变的情况下,将上一个 `next_cursor` 作为 `after` 传入。响应为 `{data, has_more, next_cursor}`;每个条目包含 `id`、`created_at`、`api_key`、`action`、`resource_type`、`resource_id`、`parent_id`(不存在时为空)、`request_id` 和 `trace_id`。
@@ -222,16 +222,16 @@ Core 会记录是哪个 Project API 密钥完成了每次成功的公共写入
| 参数 | 含义 |
| --- | --- |
-| `project_id` | 一个 Project;`group_by=agent` 时必填 |
+| `project_id` | 一个项目;`group_by=agent` 时必填 |
| `group_by` | `project`(默认)、`agent` 或 `key` |
| `created_after`、`created_before` | Session 创建时间的 RFC 3339 下限(含)和上限(不含) |
-| `after`、`limit`、`order` | 对 Project 进行分页 |
+| `after`、`limit`、`order` | 对项目进行分页 |
响应为 `{data, has_more, next_cursor}`。每一行包含 `project_id`、可为 null 的 `agent_id` 和 `key_id`、当前 `assets` 计数(Agent 分组和密钥分组为 null)、`sessions` 计数(`total`、`idle`、`in_progress`、`requires_action`、`failed`)、汇总 `usage`、`coverage`(`measured_sessions`、`total_sessions`、可为 null 的 `ratio`)以及可为 null 的 Unix `last_active_at`。
- 在密钥分组中,每个 Session 都计入创建它的密钥,即使之后由另一个密钥发送输入也是如此。没有记录创建者的 Session 会组成一个 `key_id` 为 null 的分组。
- 公共用量为 null 的 Session 不会增加 token 数量,但仍会计入覆盖率分母。
-- 每个 Project 都在单个数据库快照中读取;一页数据并不是整个部署的单一快照。总计属于运营计数,不是计费记录。
+- 每个项目都在单个数据库快照中读取;一页数据并不是整个部署的单一快照。总计属于运营计数,不是计费记录。
## Runtime 观测 {#runtime-observations}
@@ -245,7 +245,7 @@ Core 会记录是哪个 Project API 密钥完成了每次成功的公共写入
| `resource_type` | `action` | `resource_id` |
| --- | --- | --- |
-| `project` | `create`、`rename`、`archive` | Project ID |
+| `project` | `create`、`rename`、`archive` | 项目 ID |
| `api_key` | `create`、`revoke` | 密钥 ID |
| `executor_credential` | `issue`、`rotate`、`revoke` | 密钥 ID |
| `session` | `archive` | Session ID |
@@ -253,4 +253,4 @@ Core 会记录是哪个 Project API 密钥完成了每次成功的公共写入
| `deployment_model_provider`(部署范围) | `set`、`delete` | Harness |
| `sandbox_deployment`(部署范围) | `change`、`replace_credential`(提交了提供商凭据,即使提交的是同一个凭据)、`reset_start`、`reset_force`、`reset_deadline`、`reset_cancel`、`reset_complete` | 安装 ID |
-管理员写入及其审计条目会在一个事务中提交;如果条目写入失败,写入也会失败。重置在后台执行的归档操作及其 `reset_deadline` 和 `reset_complete` 条目会携带请求方的凭据、操作者标签、请求和追踪信息,并且每个归档操作都会保留其 Session 的 Project。取消重置不会撤销已经提交的归档。被拒绝的提供商验证和无效更新不会写入条目。条目绝不会包含凭据值、请求正文或提供商响应文本,并且会在其资源被删除和密钥被吊销后继续保留。
+管理员写入及其审计条目会在一个事务中提交;如果条目写入失败,写入也会失败。重置在后台执行的归档操作及其 `reset_deadline` 和 `reset_complete` 条目会携带请求方的凭据、操作者标签、请求和追踪信息,并且每个归档操作都会保留其 Session 的项目。取消重置不会撤销已经提交的归档。被拒绝的提供商验证和无效更新不会写入条目。条目绝不会包含凭据值、请求正文或提供商响应文本,并且会在其资源被删除和密钥被吊销后继续保留。
diff --git a/contracts/agents-api/zh/core-errors.md b/contracts/agents-api/zh/core-errors.md
index 95262bdba..6c479bd41 100644
--- a/contracts/agents-api/zh/core-errors.md
+++ b/contracts/agents-api/zh/core-errors.md
@@ -57,7 +57,7 @@ Web 的控制台服务器在 `/core` 路径上发生自身故障时使用此封
| 代码 | Param | 详细信息 | 含义 |
| --- | --- | --- | --- |
-| `invalid_name` | `name` | `max_length`:Projects 和节点为 128,Project 键为 80 | 名称未通过相应资源的验证器 |
+| `invalid_name` | `name` | `max_length`:项目和节点为 128,项目 API 密钥为 80 | 名称未通过相应资源的验证器 |
| `invalid_node_capacity` | `max_active` 或 `max_retained` | `min`:1,`max`:1000000 | 容量无效;保留容量还必须至少等于活动容量 |
| `invalid_model_provider` | null | 省略 | 必须提供完整的模型提供商配置包 |
| `model_provider_base_url_invalid` | `base_url` | 省略 | 必须使用 HTTPS,且不得包含凭据、查询或片段 |
@@ -69,9 +69,9 @@ Web 的控制台服务器在 `/core` 路径上发生自身故障时使用此封
| `invalid_sandbox_configuration` | `resources.cpus` | `min`:1,`max`:255 | CPU 数量超出支持范围 |
| `invalid_sandbox_configuration` | `resources.memory_mib` | `min`:512,`max`:1048576 | 内存超出支持范围 |
| `invalid_sandbox_configuration` | `resources.root_disk_mib` 或 `resources.environment_disk_mib` | `min`:microsandbox 为 1024;Docker 和 E2B 的 `min`:0,`max`:0 | 磁盘容量缺失或提供商不支持 |
-| `invalid_sandbox_configuration` | `runtime` | 省略 | Runtime release 缺失、可变、无效或 E2B 不允许 |
+| `invalid_sandbox_configuration` | `runtime` | 省略 | Runtime 版本缺失、可变、无效或 E2B 不允许 |
-这些边界是验证常量,绝不是提交的值。节点名称按字节数限制;Project 名称和键名称按去除首尾空白后的 Unicode 字符数限制,且不得包含控制字符。系统仅按以下顺序报告第一个失败项:模型提供商 URL、协议、密钥、常规限制、Harness 协议,然后是 Harness 的必需限制;沙箱资源依次为 CPU、内存、磁盘,然后是 Runtime。`model_provider` 对象内的模型提供商字段错误仍以该对象的相应字段作为 `param`。未知的沙箱提供商返回一个不含这些字段的错误。
+这些边界是验证常量,绝不是提交的值。节点名称按字节数限制;项目名称和键名称按去除首尾空白后的 Unicode 字符数限制,且不得包含控制字符。系统仅按以下顺序报告第一个失败项:模型提供商 URL、协议、密钥、常规限制、Harness 协议,然后是 Harness 的必需限制;沙箱资源依次为 CPU、内存、磁盘,然后是 Runtime。`model_provider` 对象内的模型提供商字段错误仍以该对象的相应字段作为 `param`。未知的沙箱提供商返回一个不含这些字段的错误。
## 其他管理错误 {#other-administration-errors}
@@ -85,19 +85,19 @@ Web 的控制台服务器在 `/core` 路径上发生自身故障时使用此封
| 409 | `workspace_storage_conflict` | 工作区存储归属或配置与当前状态冲突 |
| 503 | `workspace_storage_unavailable` | 工作区存储不可用或操作尚未确认 |
| 400 | `sandbox_operation_unsupported` | 所选沙箱提供商不支持该操作 |
-| 401 | `invalid_admin_key` | Bearer 凭据不是有效的 Core Key |
-| 404 | `not_found` | 操作不存在、Harness 未知,或该 Harness 没有部署默认模型服务 |
-| 409 | `project_archived` | 目标 Project 已归档 |
-| 409 | `project_exists` | 该 Project ID 已存在 |
-| 409 | `project_api_key_exists` | 该 API Key ID 已存在 |
-| 409 | `executor_credential_exists` | 该执行器凭证 ID 已存在;要替换密钥,请轮换它 |
+| 401 | `invalid_admin_key` | Bearer 凭据不是有效的 Core 密钥 |
+| 404 | `not_found` | 操作不存在、Harness 未知,或该 Harness 没有部署默认模型提供商 |
+| 409 | `project_archived` | 目标项目已归档 |
+| 409 | `project_exists` | 该项目 ID 已存在 |
+| 409 | `project_api_key_exists` | 该 API 密钥 ID 已存在 |
+| 409 | `executor_credential_exists` | 该执行器凭据 ID 已存在;要替换密钥,请轮换它 |
| 409 | `sandbox_not_configured` | 沙箱部署尚未配置 |
| 409 或 503 | `sandbox_reset_in_progress` | 沙箱正在重置 |
| 409 | `sandbox_configuration_error` | 当前安装无法支持所选提供商,例如公开 URL 为 loopback 时选择 E2B |
| 409 | `sandbox_deployment_conflict` | 沙箱部署在当前状态下无法更改 |
| 409 | `sandbox_specification_mismatch` | 已保存的部署规格对其提供商不再有效 |
| 409 | `runtime_node_in_use` | 节点仍有资源分配、快照、预留资源或待清理项 |
-| 409 | `environment_unavailable` | Session 的环境已不可用,例如托管环境创建失败 |
+| 409 | `environment_unavailable` | Session 的 Environment 已不可用,例如托管 Environment 创建失败 |
| 409 | `runtime_history_unsupported` | 该 Session 不支持 Runtime 历史 |
| 500 | `internal_error` | Core 未能完成操作 |
| 503 | `runtime_node_unavailable` | 没有可用或有剩余容量的沙箱节点 |
@@ -135,7 +135,7 @@ Web 的控制台服务器在 `/core` 路径上发生自身故障时使用此封
| `core_storage_failed` | `event_persistence_failed`、`artifact_capture_failed` |
| `internal_error` | 结果未知或格式错误;不返回原始值 |
| `environment_connection_timeout` | 初始输入连接截止时间已过 |
-| `environment_unavailable` | 初始输入所需环境不可用 |
+| `environment_unavailable` | 初始输入所需 Environment 不可用 |
| `environment_provisioning_failed` | 托管预置失败;params 包含来自已清理回执的可空 `step`、`index`、`exit_code` |
数据库故障属于错误,绝不会产生空快照或健康快照。绝不会解析预置原因或原生消息以确定类别或参数。
diff --git a/contracts/agents-api/zh/environment-executor-credentials.md b/contracts/agents-api/zh/environment-executor-credentials.md
index 59ea8d22c..4a0812f0d 100644
--- a/contracts/agents-api/zh/environment-executor-credentials.md
+++ b/contracts/agents-api/zh/environment-executor-credentials.md
@@ -1,21 +1,21 @@
---
-title: "Environment 执行器凭证"
+title: "Environment 执行器凭据"
source: contracts/agents-api/environment-executor-credentials.md
source_hash: c929752dc1113b777308855ab416bc12aef07ae2d26df71c2e691cbef2832b8b
---
-执行器凭证允许 `oac-daemon` 为一个 `self_hosted` Environment 注册并连接。它只授权该 Environment 的私有 daemon 传输(`/api/v1/agent-daemon/*`),不授权 `/v1`、`/core/v1`、sandbox node 注册或 Project 资源。Project 的 principal 是其执行 principal。Core 只保存密钥摘要。
+执行器凭据允许 `oac-daemon` 为一个 `self_hosted` Environment 注册并连接。它只授权该 Environment 的私有 daemon 传输(`/api/v1/agent-daemon/*`),不授权 `/v1`、`/core/v1`、sandbox node 注册或项目资源。项目的 principal 是其执行 principal。Core 只保存密钥摘要。
-凭证有两个来源:
+凭据有两个来源:
-- **安装授权。** `self_hosted` Session 返回安装命令。安装器使用命令中的短期 grant 领取一个凭证,不需要 Web 或 Core key。[自托管指南](../../../docs/zh/getting-started/self-hosted.md)介绍操作步骤。
-- **Core-key 路由。** 管理员通过 Web 或 `/core/v1` 签发、轮换和撤销凭证。
+- **安装授权。** `self_hosted` Session 返回安装命令。安装器使用命令中的短期 grant 领取一个凭据,不需要 Web 或 Core 密钥。[自托管指南](../../../docs/zh/getting-started/self-hosted.md)介绍操作步骤。
+- **Core-key 路由。** 管理员通过 Web 或 `/core/v1` 签发、轮换和撤销凭据。
-Core 不创建、停止或回收机器。断开连接、撤销凭证或删除 Session 都不能证明所有原生进程已停止;机器所有者负责停止并清理自己的计算资源。
+Core 不创建、停止或回收机器。断开连接、撤销凭据或删除 Session 都不能证明所有原生进程已停止;机器所有者负责停止并清理自己的计算资源。
## 安装授权 {#installation-grant}
-`self_hosted` Session 的创建、查询和更新响应包含 `x_agents_core.installation`,Session 列表不包含。Web 使用 Core key 通过 `GET /core/v1/projects/{project_id}/environments/{environment_id}/installation` 读取同一对象,原样显示命令。
+`self_hosted` Session 的创建、查询和更新响应包含 `x_agents_core.installation`,Session 列表不包含。Web 使用 Core 密钥通过 `GET /core/v1/projects/{project_id}/environments/{environment_id}/installation` 读取同一对象,原样显示命令。
| 字段 | 含义 |
| --- | --- |
@@ -24,9 +24,9 @@ Core 不创建、停止或回收机器。断开连接、撤销凭证或删除 Se
| `expires_at` | grant 到期的 Unix 时间,为响应生成后 30 分钟 |
| `commands.posix`, `commands.powershell` | Linux/macOS 和 Windows PowerShell 的安装命令 |
-grant 绑定 Environment、Session 创建者的 principal 和 Core 构建版本。在到期、Session 被删除、Project 被归档或 Core 运行另一构建版本时失效。重新读取 Session 会获得新 grant。Core 不存储 grant:每个响应重新签名,存储的事件从不包含它。将命令视为临时秘密:它能领取凭证,但不能执行工作或读取文件。
+grant 绑定 Environment、Session 创建者的 principal 和 Core 构建版本。在到期、Session 被删除、项目被归档或 Core 运行另一构建版本时失效。重新读取 Session 会获得新 grant。Core 不存储 grant:每个响应重新签名,存储的事件从不包含它。将命令视为临时秘密:它能领取凭据,但不能执行工作或读取文件。
-安装器生成密钥,在领取前将其私密保存到安装目录的 `daemon/executor-credential.json`。Core 将摘要保存在 key ID 等于 Environment ID 的记录中。响应丢失后可以安全重试,但必须提交同一个密钥。grant 不替换或恢复凭证。如果 Environment 已有不同、已轮换或已撤销的凭证,领取返回 409 `executor_credential_exists`。
+安装器生成密钥,在领取前将其私密保存到安装目录的 `daemon/executor-credential.json`。Core 将摘要保存在 key ID 等于 Environment ID 的记录中。响应丢失后可以安全重试,但必须提交同一个密钥。grant 不替换或恢复凭据。如果 Environment 已有不同、已轮换或已撤销的凭据,领取返回 409 `executor_credential_exists`。
安装器调用 Core 的以下机器路由:
@@ -37,21 +37,21 @@ grant 绑定 Environment、Session 创建者的 principal 和 Core 构建版本
| `POST /api/v1/agent-daemon/installation` | Grant | 固定绑定:`version`、`protocol_version`、`environment_id`、`remote_url`、`workspace_directory`、`harness` |
| `POST /api/v1/agent-daemon/installation/claim` | Grant | `{"executor_token":"SECRET"}`;204 |
-无效或过期的 grant 返回 401 `installation_authorization_invalid`。没有匹配安装器时,grant 路由返回 503 `installation_unavailable`。Core 用安装的 [`secrets/core/credential.key`](../../../docs/zh/configuration.md#compose-installations) 签名每个 grant。格式错误的密钥返回 400。产物路由不携带凭证,grant 只发送给 Core,不发送给产物主机。
+无效或过期的 grant 返回 401 `installation_authorization_invalid`。没有匹配安装器时,grant 路由返回 503 `installation_unavailable`。Core 用安装的 [`secrets/core/credential.key`](../../../docs/zh/configuration.md#compose-installations) 签名每个 grant。格式错误的密钥返回 400。产物路由不携带凭据,grant 只发送给 Core,不发送给产物主机。
## Core-key 路由 {#core-key-routes}
-所有路由位于 `/core/v1/projects/{project_id}/environments/{environment_id}/executor-credentials`,要求 Core key。它们仅适用于该 Project 内 Session 仍存在(未删除)的 `self_hosted` Environment;其他 Project、Environment 类型、缺失 Environment 或已删除 Session 均返回 404。Project API key 无权调用。
+所有路由位于 `/core/v1/projects/{project_id}/environments/{environment_id}/executor-credentials`,要求 Core 密钥。它们仅适用于该项目内 Session 仍存在(未删除)的 `self_hosted` Environment;其他项目、Environment 类型、缺失 Environment 或已删除 Session 均返回 404。项目 API 密钥无权调用。
| 操作 | 请求 | 结果 |
| --- | --- | --- |
-| 列表 | `GET …/executor-credentials` | `data` 中的凭证元数据,以及必需的 `connection` 对象 |
-| 签发或轮换 | `POST …/executor-credentials`,内容为 `{"key_id":"UUID","rotate":false}` | 201 凭证文件,只返回一次 |
+| 列表 | `GET …/executor-credentials` | `data` 中的凭据元数据,以及必需的 `connection` 对象 |
+| 签发或轮换 | `POST …/executor-credentials`,内容为 `{"key_id":"UUID","rotate":false}` | 201 凭据文件,只返回一次 |
| 撤销 | `DELETE …/executor-credentials/{key_id}` | 204 |
-列表只包含限定于此 Environment 的凭证元数据,按最早创建优先排序。有效凭证的 `revoked_at` 为 null。列表不包含密钥。
+列表只包含限定于此 Environment 的凭据元数据,按最早创建优先排序。有效凭据的 `revoked_at` 为 null。列表不包含密钥。
-`key_id` 是请求前选定并保留的规范非零 UUID。`rotate` 可选,默认 false。201 响应使用 daemon 凭证文件格式:
+`key_id` 是请求前选定并保留的规范非零 UUID。`rotate` 可选,默认 false。201 响应使用 daemon 凭据文件格式:
```json
{"key_id":"UUID","environment_id":"ENVIRONMENT_UUID","executor_token":"ONE_TIME_SECRET"}
@@ -59,42 +59,42 @@ grant 绑定 Environment、Session 创建者的 principal 和 Core 构建版本
响应使用 `Cache-Control: no-store`。直接保存到自己拥有、权限为 0600 的文件,不放入 shell 参数、日志、工作区或源码。
-写入有两种 409 冲突。`executor_credential_exists`:签发时 `key_id` 已存在且没有 `rotate:true`,即使已撤销也一样。`project_archived`:Project 已归档,不能签发或轮换凭证;列表和撤销仍可用,因为必须始终能够撤销。
+写入有两种 409 冲突。`executor_credential_exists`:签发时 `key_id` 已存在且没有 `rotate:true`,即使已撤销也一样。`project_archived`:项目已归档,不能签发或轮换凭据;列表和撤销仍可用,因为必须始终能够撤销。
-签发或轮换按以下顺序检查,返回第一个失败:请求体(400);目标 Environment(404);已归档 Project(409 `project_archived`);key 本身(未设置 `rotate` 时为 409 `executor_credential_exists`,轮换从未签发的 `key_id` 时为 404)。
+签发或轮换按以下顺序检查,返回第一个失败:请求体(400);目标 Environment(404);已归档项目(409 `project_archived`);凭据本身(未设置 `rotate` 时为 409 `executor_credential_exists`,轮换从未签发的 `key_id` 时为 404)。
-轮换替换限定于该 Environment 的现有 key 密钥,保留 Environment,立即使旧密钥失效,并恢复已撤销的 key。撤销是幂等操作,每次返回 204,禁止后续注册和连接。
+轮换替换限定于该 Environment 的现有凭据的密钥,保留 Environment,立即使旧密钥失效,并恢复已撤销的凭据。撤销是幂等操作,每次返回 204,禁止后续注册和连接。
-超时等结果不确定的情况下,不要自动重试。先列出凭证,再轮换同一 `key_id`(已签发但密钥丢失),或重新签发(尚未签发)。
+超时等结果不确定的情况下,不要自动重试。先列出凭据,再轮换同一 `key_id`(已签发但密钥丢失),或重新签发(尚未签发)。
签发、轮换和撤销在写入的同一事务中记录管理员审计项:`resource_type:"executor_credential"`,key ID 为 `resource_id`,action 为 `issue`、`rotate` 或 `revoke`。审计不包含密钥。
### 应急命令 {#break-glass-command}
-Core API 不可用时,`oac-core-environment-key` 直接在数据库中签发、轮换或撤销凭证。它读取 Core 数据库设置(`OAC_DATABASE_URL`,以及配置时的 `OAC_DATABASE_PASSWORD_FILE`),并需要 Project 的执行 principal:`--tenant`(`projects` 表中 Project 的 tenant UUID)、`--organization core`、`--project proj_`、`--subject-kind service_account`、`--subject-id project:` 和 `--key-id`。没有其他标志时签发新凭证,`--environment` 限定到一个 Environment。`--rotate` 替换现有凭证的密钥,包括已撤销凭证;`--revoke` 撤销而不输出密钥。轮换和撤销保留存储的限制,拒绝 `--environment`,两个标志互斥。签发和轮换只在标准输出打印一次凭证文件,应重定向到新建的 0600 文件。命令绕过 Core API,跳过 Project 归档检查且不写审计项,因此 Core 运行时应使用 Core-key 路由。没有 Environment 限制的凭证不能通过上述路由管理。
+Core API 不可用时,`oac-core-environment-key` 直接在数据库中签发、轮换或撤销凭据。它读取 Core 数据库设置(`OAC_DATABASE_URL`,以及配置时的 `OAC_DATABASE_PASSWORD_FILE`),并需要项目的执行 principal:`--tenant`(`projects` 表中项目的 tenant UUID)、`--organization core`、`--project proj_`、`--subject-kind service_account`、`--subject-id project:` 和 `--key-id`。没有其他标志时签发新凭据,`--environment` 限定到一个 Environment。`--rotate` 替换现有凭据的密钥,包括已撤销凭据;`--revoke` 撤销而不输出密钥。轮换和撤销保留存储的限制,拒绝 `--environment`,两个标志互斥。签发和轮换只在标准输出打印一次凭据文件,应重定向到新建的 0600 文件。命令绕过 Core API,跳过项目归档检查且不写审计项,因此 Core 运行时应使用 Core-key 路由。没有 Environment 限制的凭据不能通过上述路由管理。
## 连接状态 {#connection-status}
-列表必需的 `connection` 对象包含 `status`(`never_enrolled`、`connected` 或 `disconnected`)、`bound_key_id`、`enrolled_at` 和 `last_seen_at`。注册前,三个绑定字段均为 null。注册后,绑定 key 和注册时间描述已有设备;`last_seen_at` 为 null 表示尚无经过认证的心跳。签发另一 key 不改变绑定。轮换或撤销可能使绑定断开,但历史仍可见。过期 Environment 仍按现有列表规则可读,但不能拥有当前执行器权限。
+列表必需的 `connection` 对象包含 `status`(`never_enrolled`、`connected` 或 `disconnected`)、`bound_key_id`、`enrolled_at` 和 `last_seen_at`。注册前,三个绑定字段均为 null。注册后,绑定的凭据和注册时间描述已有设备;`last_seen_at` 为 null 表示尚无经过认证的心跳。签发另一凭据不改变绑定。轮换或撤销可能使绑定断开,但历史仍可见。过期 Environment 仍按现有列表规则可读,但不能拥有当前执行器权限。
-Connected 表示 Environment 已连接,其设备和执行器 key 仍有当前 Core 权限,且进程内 gateway 有一个用当前 key 认证的开放 peer。Core 观察 peer 后重新检查权限。旧 key 的存活 socket、设备时间戳或看似就绪的 Environment 均不充分;没有 gateway 时 Core 不返回 connected。这些事实是观测结果,不预留连接,也不保证原生执行或模型就绪。`last_seen_at` 可能滞后一个心跳间隔。
+Connected 表示 Environment 已连接,其设备和执行器凭据仍有当前 Core 权限,且进程内 gateway 有一个用当前凭据认证的开放 peer。Core 观察 peer 后重新检查权限。旧凭据的存活 socket、设备时间戳或看似就绪的 Environment 均不充分;没有 gateway 时 Core 不返回 connected。这些事实是观测结果,不预留连接,也不保证原生执行或模型就绪。`last_seen_at` 可能滞后一个心跳间隔。
-列表元数据和绑定事实使用同一个只读数据库快照。快照在实时权限检查前结束,因此已提交的轮换或撤销不会被快照隔离隐藏。已知权限丢失映射为 disconnected;观测和存储失败仍返回错误。设备 ID 和凭证摘要为内部数据,不序列化。公开 `/v1` Environment 形状不变。
+列表元数据和绑定事实使用同一个只读数据库快照。快照在实时权限检查前结束,因此已提交的轮换或撤销不会被快照隔离隐藏。已知权限丢失映射为 disconnected;观测和存储失败仍返回错误。设备 ID 和凭据摘要为内部数据,不序列化。公开 `/v1` Environment 形状不变。
### 私有连接确认 {#private-connection-confirmation}
-`GET /api/v1/agent-daemon/connection?environment_id=UUID` 使用执行器 bearer,直接发往 Core(反向代理将 `/api/v1` 路由到 Core,console 不提供该接口)。它属于私有 daemon 传输,不属于公开 Agents API。它只读取现有授权和绑定,不注册设备、启动执行或修改资源。no-store 响应只包含请求的 `environment_id` 和 `status`(`connected` 或 `disconnected`)。Connected 要求 Environment 观测、确切的 Session 和设备绑定、当前执行器权限,以及用相同凭证认证的存活 gateway socket。过期观测或携带已轮换 key 的 socket 不能确认连接。
+`GET /api/v1/agent-daemon/connection?environment_id=UUID` 使用执行器 bearer,直接发往 Core(反向代理将 `/api/v1` 路由到 Core,console 不提供该接口)。它属于私有 daemon 传输,不属于公开 Agents API。它只读取现有授权和绑定,不注册设备、启动执行或修改资源。no-store 响应只包含请求的 `environment_id` 和 `status`(`connected` 或 `disconnected`)。Connected 要求 Environment 观测、确切的 Session 和设备绑定、当前执行器权限,以及用相同凭据认证的存活 gateway socket。过期观测或携带已轮换凭据的 socket 不能确认连接。
-无效、已撤销、其他范围或已删除 Session 的权限返回 401;已绑定 Environment 使用不同 key 返回 409。响应不暴露实际绑定或数据库诊断。
+无效、已撤销、其他范围或已删除 Session 的权限返回 401;已绑定 Environment 使用不同凭据返回 409。响应不暴露实际绑定或数据库诊断。
-安装器从返回的 `remote_url` 推导此路由,不跟随重定向。启动 daemon 后,每秒轮询一次,最多 45 秒。401 或 409 立即失败。超时后打印 daemon 的 `connect.log` 路径,请求重新执行同一命令;daemon 继续重连,安装、凭证和历史保留。连接确认只证明认证成功,不证明模型访问、Harness 能力或执行完成。
+安装器从返回的 `remote_url` 推导此路由,不跟随重定向。启动 daemon 后,每秒轮询一次,最多 45 秒。401 或 409 立即失败。超时后打印 daemon 的 `connect.log` 路径,请求重新执行同一命令;daemon 继续重连,安装、凭据和历史保留。连接确认只证明认证成功,不证明模型访问、Harness 能力或执行完成。
-## 已撤销或轮换的凭证 {#revoked-or-rotated-credential}
+## 已撤销或轮换的凭据 {#revoked-or-rotated-credential}
Core 永久拒绝 daemon 时(注册 401/409、永久 WebSocket 拒绝,或 daemon 版本来自其他 Core 分发),daemon 只打印一次原因,停止发请求直到被停止;随后成功退出,避免按退出重启的 supervisor 循环。再次启动时只尝试一次注册,然后再次停驻。临时故障保持正常重连行为,不重放执行。
-机器只能使用绑定的 `key_id` 重连,轮换新密钥后替换配置路径的凭证文件;[自托管指南](../../../docs/zh/getting-started/self-hosted.md#rotate-or-revoke)提供步骤。新 `key_id` 无法重新连接已绑定的 Environment:签发成功,但用它注册返回 409。轮换不重装 Harness、不改变工作区、不替换原生历史;不要为恢复凭证创建新 Session 历史。
+机器只能使用绑定的 `key_id` 重连,轮换新密钥后替换配置路径的凭据文件;[自托管指南](../../../docs/zh/getting-started/self-hosted.md#rotate-or-revoke)提供步骤。新 `key_id` 无法重新连接已绑定的 Environment:签发成功,但用它注册返回 409。轮换不重装 Harness、不改变工作区、不替换原生历史;不要为恢复凭据创建新 Session 历史。
-## 模型服务 {#model-provider}
+## 模型提供商 {#model-provider}
-`self_hosted` Session 携带自己的模型服务,部署默认值不适用。[模型执行](model-execution.md)负责交付规则。保存的 Agent 的服务 key 会交给 Project 中用该 Agent 创建的每个 `self_hosted` Session 的执行器,因此任何能在该 Project 创建 `self_hosted` Session 并运行执行器的人都能读取它。
+`self_hosted` Session 携带自己的模型提供商,部署默认值不适用。[模型执行](model-execution.md)负责交付规则。保存的 Agent 的模型提供商密钥会交给项目中用该 Agent 创建的每个 `self_hosted` Session 的执行器,因此任何能在该项目创建 `self_hosted` Session 并运行执行器的人都能读取它。
diff --git a/contracts/agents-api/zh/environment-files.md b/contracts/agents-api/zh/environment-files.md
index a2b6f20aa..bff81f7cc 100644
--- a/contracts/agents-api/zh/environment-files.md
+++ b/contracts/agents-api/zh/environment-files.md
@@ -12,7 +12,7 @@ Session 工作区保存由 agent 及其工具修改的实时文件。`/agents/en
- Environment 文件适用于 `openai_hosted` 和 `self_hosted` Environment。`none` Environment 返回 503 `execution_unavailable`。
- 公开路径从 `/workspace` 开始,代表 Environment 在机器上实际位置的工作区目录。
-- 首先在调用方 Project 查找 Environment;不存在或属于其他范围的 ID 返回 404。
+- 首先在调用方项目查找 Environment;不存在或属于其他范围的 ID 返回 404。
- 仍为 `pending` 的 `openai_hosted` Environment,两种操作均返回 400 `the hosted environment is still provisioning; wait until it is connected before accessing files`。此检查在请求验证之后、任何源 File 查询之前执行。其他状态继续处理,Runtime 不可达时返回 503。
- 文件操作在现有请求期限内等待 Environment 初始化完成;`connected` 本身不表示已就绪,初始化失败或执行容量耗尽仍返回 503。
- 列表和写入不启动 Turn,也不向模型发送输入。
@@ -56,7 +56,7 @@ Session 工作区保存由 agent 及其工具修改的实时文件。`/agents/en
{"type": "file_id", "file_id": "file-…", "path": "/workspace/data/input.csv"}
```
-空 inline `data` 有效,会创建空文件。返回 201 和四个 EnvironmentFile 字段。`file_id` 指定同一 Project 的 [File](source-files.md);Core 联系 Runtime 之前读取字节。
+空 inline `data` 有效,会创建空文件。返回 201 和四个 EnvironmentFile 字段。`file_id` 指定同一项目的 [File](source-files.md);Core 联系 Runtime 之前读取字节。
| 情况 | 结果 |
| --- | --- |
diff --git a/contracts/agents-api/zh/environments.md b/contracts/agents-api/zh/environments.md
index ffed2f938..9021bc8d5 100644
--- a/contracts/agents-api/zh/environments.md
+++ b/contracts/agents-api/zh/environments.md
@@ -1,16 +1,16 @@
---
-title: "环境与模板"
+title: "Environment 与模板"
source: contracts/agents-api/environments.md
source_hash: 9007be1099cf50f5ba376d2de4a060d039b6ee0b1c13c78a94665c28c2fc3fc6
---
-Environment 是 Session 的执行资源,包括 Harness 运行所在的机器、工作区以及已完成准备的能力。Session 通过其 `environment` 配置创建 Environment;不存在独立的 create 调用。Environment Template 是 Session 创建时解析的可复用准备配置。本契约涵盖这两类资源、两种放置方式、输入接纳、能力准备、Skills、Plugins 和 MCP 连接来源。
+Environment 是 Session 的执行资源,包括 Harness 运行所在的机器、工作区以及已完成准备的能力。Session 通过其 `environment` 配置创建 Environment;不存在独立的 create 调用。Environment 模板是 Session 创建时解析的可复用准备配置。本契约涵盖这两类资源、两种放置方式、输入接纳、能力准备、Skills、Plugins 和 MCP 连接来源。
相关职责归属:
- [Environment files](environment-files.md):实时工作区上的 Files API。
-- [Executor credentials](environment-executor-credentials.md):`self_hosted` 机器的注册、安装授权和连接状态。
-- [Sandbox deployment](sandbox-deployment.md):托管 `openai_hosted` Environment 的 Sandbox Provider(E2B、Docker 或 microsandbox)。
+- [执行器凭据](environment-executor-credentials.md):`self_hosted` 机器的注册、安装授权和连接状态。
+- [Sandbox deployment](sandbox-deployment.md):托管 `openai_hosted` Environment 的沙箱提供商(E2B、Docker 或 microsandbox)。
- [Core–Runtime protocol](../../../docs/zh/runtime-protocol.md):`runtime_prepare` 传输及所有其他线上消息。
- [Runtime and outer isolation](../../../docs/zh/concepts.md#runtime-and-outer-isolation):daemon 使用启动用户的权限运行工具;隔离由外层 Environment 提供。
@@ -21,16 +21,16 @@ Environment 是 Session 的执行资源,包括 Harness 运行所在的机器
| 资源 | 操作 | 规则 |
| --- | --- | --- |
| [Environment](https://github.com/openai/openai-python/blob/d7c41efee1b0802b79f3f88a678ef2052b06e9ce/src/openai/resources/beta/agents/environments/environments.py) | `GET /agents/environments/{id}` | 通过 Session 配置创建。返回 `id`、`type`、`status`,以及 Session 创建时记录的 `files`、`plugins` 和 `skills`。 |
-| [Template](https://github.com/openai/openai-python/blob/d7c41efee1b0802b79f3f88a678ef2052b06e9ce/src/openai/resources/beta/agents/environments/templates.py) | `POST`、`GET /agents/environments/templates`;`GET`、`POST`、`DELETE /agents/environments/templates/{id}` | 请参阅 [Templates](#templates)。 |
+| [模板](https://github.com/openai/openai-python/blob/d7c41efee1b0802b79f3f88a678ef2052b06e9ce/src/openai/resources/beta/agents/environments/templates.py) | `POST`、`GET /agents/environments/templates`;`GET`、`POST`、`DELETE /agents/environments/templates/{id}` | 请参阅 [模板](#templates)。 |
| [Files](https://github.com/openai/openai-python/blob/d7c41efee1b0802b79f3f88a678ef2052b06e9ce/src/openai/resources/beta/agents/environments/files.py) | `POST`、`GET /agents/environments/{id}/files` | 请参阅 [Environment files](environment-files.md)。 |
-读取 Environment 时,Core 会在调用方的 Project 范围内与其实时所属的 Session 联查,并返回持久化的连接状态。它不需要活跃的 Runtime,不会启动任何原生工作,也不会改变连接状态。对于两种放置方式,安装项数组都会列出由 API 管理的文件、Plugins 和 Skills:文件使用 `{id, type, path, file_id, size_bytes}` 且不含内容,Skills 使用 `{type, name, description, skill_id, version}`,Plugins 使用 `{type, name, description}`。在本地能力目录中发现的 Capabilities 不会列出。
+读取 Environment 时,Core 会在调用方的项目范围内与其实时所属的 Session 联查,并返回持久化的连接状态。它不需要活跃的 Runtime,不会启动任何原生工作,也不会改变连接状态。对于两种放置方式,安装项数组都会列出由 API 管理的文件、Plugins 和 Skills:文件使用 `{id, type, path, file_id, size_bytes}` 且不含内容,Skills 使用 `{type, name, description, skill_id, version}`,Plugins 使用 `{type, name, description}`。在本地能力目录中发现的 Capabilities 不会列出。
[Session environment input](https://github.com/openai/openai-python/blob/d7c41efee1b0802b79f3f88a678ef2052b06e9ce/src/openai/types/beta/environment_param.py) 与 [output](https://github.com/openai/openai-python/blob/d7c41efee1b0802b79f3f88a678ef2052b06e9ce/src/openai/types/beta/environment.py) 的结构不同:
- `none` 不选择任何 Environment。
- `self_hosted` 输入要求提供 `workspace_directory`;可空的 `capability_directories` 默认为空列表。输出会增加 Environment ID 和仅输出字段 `remote_url`。输出中 `/workspace` 的默认值不会使输入字段变为可选。
-- `openai_hosted` 可以引用 Template,并提供 `capability_directories`、`network`、`packages`、`files`、`plugins`、`skills`、`env` 和 `setup_commands`。
+- `openai_hosted` 可以引用模板,并提供 `capability_directories`、`network`、`packages`、`files`、`plugins`、`skills`、`env` 和 `setup_commands`。
| 投影 | 状态 |
| --- | --- |
@@ -39,7 +39,7 @@ Environment 是 Session 的执行资源,包括 Harness 运行所在的机器
这两套词汇彼此独立;绝不要将其中一套转换为另一套。Session environment 事件携带 Session 和 Environment 的身份标识以及可选的 Turn 身份标识,绝不携带配置、凭据、注册 ID 或修订号。Session 的 `required_actions` 可以包含 `{type: "environment_connection", environment_id}`,这与函数调用相互独立。Environment 连接、Session 状态和 Turn 状态相互独立。
-Core 在 Session 创建事务中创建 Environment 记录;Session upsert 会选出重试的胜者,而重试绝不创建或修复 Environment。Environment 从所属 Session 派生其 Project 和不可变配置。其首个状态为 `pending`。Session 删除后,读取会隐藏 Environment,而 Core 仍保留该记录,用于结算和清理。Session 为 `none` 时没有 Environment。
+Core 在 Session 创建事务中创建 Environment 记录;Session upsert 会选出重试的胜者,而重试绝不创建或修复 Environment。Environment 从所属 Session 派生其项目和不可变配置。其首个状态为 `pending`。Session 删除后,读取会隐藏 Environment,而 Core 仍保留该记录,用于结算和清理。Session 为 `none` 时没有 Environment。
托管的外层 Environment 必须排除权限范围更广的应用程序凭据和其他租户的机密。
@@ -50,30 +50,30 @@ Core 在 Session 创建事务中创建 Environment 记录;Session upsert 会
| 对象 | 责任 |
| --- | --- |
| Session 与 Environment | 持久所有权、配置、待处理交互和连接观察(Core) |
-| Provider 分配 | 计算资源和文件系统的生命周期:`openai_hosted` 使用 Core 的 Sandbox Provider,`self_hosted` 使用应用程序 |
+| 提供商分配 | 计算资源和文件系统的生命周期:`openai_hosted` 使用 Core 的沙箱提供商,`self_hosted` 使用应用程序 |
| 设备与 daemon 连接 | 经认证的 Runtime 身份和可替换的分派传输 |
| Harness 进程与原生会话 | 原生模型和工具循环、其执行状态及原生历史 |
-| 注册 | `self_hosted` 机器的 Environment、设备和 executor key 的精确绑定 |
+| 注册 | `self_hosted` 机器的 Environment、设备和执行器凭据的精确绑定 |
### 托管(`openai_hosted`) {#hosted-openai-hosted}
-部署中配置的 Sandbox Provider(E2B、Docker 或 microsandbox,请参阅 [sandbox deployment](sandbox-deployment.md))承载 Environment。[Harness capabilities](harness-capabilities.md) 列出了可在其中运行的 Harnesses。
+部署中配置的沙箱提供商(E2B、Docker 或 microsandbox,请参阅 [sandbox deployment](sandbox-deployment.md))承载 Environment。[Harness capabilities](harness-capabilities.md) 列出了可在其中运行的 Harnesses。
-- Session 创建时,无论是否包含初始输入,都会在 Worker 配置计算资源之前提交 Session、Environment 和重试身份。若创建在 bootstrap 前中断,可恢复时不会重复执行 Provider 的 Create。
+- Session 创建时,无论是否包含初始输入,都会在 Worker 配置计算资源之前提交 Session、Environment 和重试身份。若创建在 bootstrap 前中断,可恢复时不会重复执行提供商的 Create。
- 置备无需调用方执行任何操作;在 Turn 启动之前,Session 会保持空闲。
- 省略或传入 null 的 `network` 表示启用;`disabled` 和 `restricted` 会在 Session 创建前被拒绝([restricted network](#restricted-network))。
- Core 重启会保留分配、工作区和原生身份,并且绝不重播结果不确定的工作。
-- 终止清理会先在一个事务中撤销权限并结算待处理输入,然后 Provider 才会回收计算资源。向处于终止状态的 Environment 提交新输入会被拒绝。
-- 删除 Session 会回收其 Environment;删除 Template 则不会。
+- 终止清理会先在一个事务中撤销权限并结算待处理输入,然后提供商才会回收计算资源。向处于终止状态的 Environment 提交新输入会被拒绝。
+- 删除 Session 会回收其 Environment;删除模板则不会。
### 自托管(`self_hosted`) {#self-hosted-self-hosted}
-应用程序拥有机器。它使用干净的绝对路径 `workspace_directory` 和可选的绝对本地 `capability_directories` 创建 Session。Core 会返回 Environment ID、`remote_url` 以及 `x_agents_core.installation` 中的一条安装命令;在该机器上运行此命令会安装 daemon 并为其注册([self-hosted guide](../../../docs/zh/getting-started/self-hosted.md)、[executor credentials](environment-executor-credentials.md))。
+应用程序拥有机器。它使用干净的绝对路径 `workspace_directory` 和可选的绝对本地 `capability_directories` 创建 Session。Core 会返回 Environment ID、`remote_url` 以及 `x_agents_core.installation` 中的一条安装命令;在该机器上运行此命令会安装 daemon 并为其注册([自托管指南](../../../docs/zh/getting-started/self-hosted.md)、[执行器凭据](environment-executor-credentials.md))。
- `remote_url` 是根据 Core 的公共 URL 推导出的 daemon WebSocket URL,绝不根据请求头或 daemon 地址生成。它指定 Core 的私有 daemon 传输通道。
-- 注册会将精确的 Session、Environment、设备和 executor key 绑定在一起。它不会创建任何分配,也无法将 Session 迁移到另一台设备。
+- 注册会将精确的 Session、Environment、设备和执行器凭据绑定在一起。它不会创建任何分配,也无法将 Session 迁移到另一台设备。
- Session 的工作区必须等于 `/workspace` 别名,或等于 Runtime 绑定到的精确规范目录。指定某个路径并不会授予对它的访问权限。
-- Session 携带自己的模型提供方;部署默认值绝不适用([model execution](model-execution.md#saved-defaults-and-precedence))。
+- Session 携带自己的模型提供商;部署默认值绝不适用([model execution](model-execution.md#saved-defaults-and-precedence))。
- Session 读取、列表和事件会返回带有 Environment ID、工作区及能力目录的 `self_hosted` 输出,但绝不返回私有配置。`capability_directories` 列出调用方选择的内容;Runtime 的安装位置保持私有。
- 计算资源、工作区和文件仍归应用程序所有。删除 Session 或撤销凭据会拒绝后续访问,但不会停止原生进程;机器所有者负责停止和清理。
- 工作区和原生历史必须能在 daemon 重启后继续存在。丢失它们绝不授权进行静默替换或重播。
@@ -82,8 +82,8 @@ Core 在 Session 创建事务中创建 Environment 记录;Session upsert 会
### 所有权规则 {#ownership-rules}
-- 将 Environment 身份、所有权、配置和生命周期保留在 Core 中,并使其与 Provider 计算资源、设备身份、daemon 套接字和原生会话相分离。将可变连接状态排除在不可变配置之外;替换后的所有者会使过期观察值失效。
-- 调用方、设备和 Environment 连接使用彼此不同的凭据。daemon gateway 会对已注册的 executor key 和精确设备进行认证。连接观察保留 generation 和 revision 栅栏。注册和连接都不表示已就绪。
+- 将 Environment 身份、所有权、配置和生命周期保留在 Core 中,并使其与提供商计算资源、设备身份、daemon 套接字和原生会话相分离。将可变连接状态排除在不可变配置之外;替换后的所有者会使过期观察值失效。
+- 调用方、设备和 Environment 连接使用彼此不同的凭据。daemon gateway 会对已注册的执行器凭据和精确设备进行认证。连接观察保留 generation 和 revision 栅栏。注册和连接都不表示已就绪。
- 轮换、撤销、Session 删除和所有权丧失都会拒绝后续访问;但它们不保证原生效果会立即停止。
- 原生历史保留在绑定的 Runtime 上。替换计算资源时必须保留或以可证明的方式恢复原生历史;绝不能静默移动已绑定的 Session 或重播未知工作。
- 持久元数据读取不需要活跃的 Runtime。实时文件读取需要获得对精确工作区的授权视图和有界操作所有权。写入、替换或撤销工作区所有者的操作也适用变更栅栏。
@@ -160,7 +160,7 @@ Worker 在每个 tick 中最多处理 32 个到期预留,处理顺序是在检
### 所有权与生命周期 {#ownership-and-lifetimes}
-资源管理负责 Provider 放置、容量和分配,以及 Environment 的创建、续期和回收。经认证的 Runtime 连接承载初始化、能力准备和 executor 操作;它绝不分配或销毁计算资源。Provider 绝不运行 Core 初始化命令。
+资源管理负责提供商放置、容量和分配,以及 Environment 的创建、续期和回收。经认证的 Runtime 连接承载初始化、能力准备和 executor 操作;它绝不分配或销毁计算资源。提供商绝不运行 Core 初始化命令。
关闭 Executor、取消 Turn 或传输丢失都会保留已安装的快照、工作区和分配。回收是与活动工作协调的显式操作;断开的套接字不能证明原生效果已经停止。[Harness onboarding](harness-onboarding.md#executor-and-turn-lifetimes) 负责 Executor 和 Turn 的生命周期。
@@ -173,9 +173,9 @@ Core 会在 Session 创建时冻结资源版本、元数据和源选择。随后
3. npm 和 Python 软件包,然后按顺序运行设置命令;
4. 能力目录快照。
-运行器仅使用中立的 Environment 和 Session 身份以及一个 Runtime 对端,不包含 Provider、部署或操作系统分支。Harness 差异保留在适配器中。
+运行器仅使用中立的 Environment 和 Session 身份以及一个 Runtime 对端,不包含提供商、部署或操作系统分支。Harness 差异保留在适配器中。
-**可移植的准备输入。** `self_hosted` 输入仅携带 `workspace_directory` 和 `capability_directories`。无论 Session 采用哪种工作区放置方式,还可以发送 `x_agents_core.environment`,这是 Core 扩展,包含 `environment_template_id`、`files`、`env`、`packages`、`setup_commands`、`skills`、`plugins` 和 `capability_directories`。它使用与 `openai_hosted` 输入相同的解析器和继承规则。若同一字段同时在 `x_agents_core.environment` 和顶层 `environment` 中提供,则会被拒绝,包括显式 null。`self_hosted` Session 只能通过此扩展指定 Template,并且不能使用 network 不是 `enabled` 的 Template(400,param `x_agents_core.environment.environment_template_id`)。机器位置、规格大小和网络策略不是此扩展的字段。
+**可移植的准备输入。** `self_hosted` 输入仅携带 `workspace_directory` 和 `capability_directories`。无论 Session 采用哪种工作区放置方式,还可以发送 `x_agents_core.environment`,这是 Core 扩展,包含 `environment_template_id`、`files`、`env`、`packages`、`setup_commands`、`skills`、`plugins` 和 `capability_directories`。它使用与 `openai_hosted` 输入相同的解析器和继承规则。若同一字段同时在 `x_agents_core.environment` 和顶层 `environment` 中提供,则会被拒绝,包括显式 null。`self_hosted` Session 只能通过此扩展指定模板,并且不能使用 network 不是 `enabled` 的模板(400,param `x_agents_core.environment.environment_template_id`)。机器位置、规格大小和网络策略不是此扩展的字段。
```json
{
@@ -185,7 +185,7 @@ Core 会在 Session 创建时冻结资源版本、元数据和源选择。随后
}
```
-将 `environment` 改为 `{"type":"openai_hosted"}` 会复用相同的准备输入。资源解析、Project 授权、具体 Skill 版本、加密文件内容和机密工具变量都会在 Session 创建时冻结。重试和重连会复用这些快照;新 Session 会解析新版本。`self_hosted` Environment 从不需要分配记录。
+将 `environment` 改为 `{"type":"openai_hosted"}` 会复用相同的准备输入。资源解析、项目授权、具体 Skill 版本、加密文件内容和机密工具变量都会在 Session 创建时冻结。重试和重连会复用这些快照;新 Session 会解析新版本。`self_hosted` Environment 从不需要分配记录。
**就绪性。** 传输 `connected` 是一种连接观察,而不代表就绪。执行和实时文件访问都要等待初始化;随后,原生准备所有者会在接纳 Turn 前验证已安装的快照和 Harness。文件读取保留自身的就绪性和授权,不要求能力或原生就绪。部署模型凭据绝不发送到应用程序所有的机器。
@@ -210,7 +210,7 @@ Executor 接纳仅验证已冻结的描述符。准备所有者会在调用原
daemon 以启动它的账户身份运行,绝不使用 sudo 或提升权限。准备过程中只会安装用户目录中的依赖项。
- 系统依赖必须预先安装在托管镜像中,或由自托管机器的所有者安装。缺少可执行文件或库时,需要该依赖的操作会失败。
-- Templates 和内联配置都会拒绝 `packages.system`,包括 null 或空列表(400,param `packages.system`)。软件包响应仍会包含官方要求的 `system: []`。
+- 模板和内联配置都会拒绝 `packages.system`,包括 null 或空列表(400,param `packages.system`)。软件包响应仍会包含官方要求的 `system: []`。
- npm 会安装到本地 prefix,Python/pip 会安装到 Runtime 软件包目录下的本地 target;Node/npm 和 Python/pip 必须已经安装。其依赖项可被每个工作目录中的原生工具看到。
- 设置命令使用 Bash 运行;在 Windows 上必须使用 Git Bash,且不能由其他 shell 替代。默认工作目录为 `/workspace`。
- 在 Windows 上,npm 安装以及名为 `npm` 或 `npx` 的 stdio MCP 命令(包括其 `.cmd` shim)会通过 Node 调用 npm 的 JavaScript 入口点运行,而不经过额外的 shell。
@@ -219,7 +219,7 @@ daemon 以启动它的账户身份运行,绝不使用 sudo 或提升权限。
每条命令都使用启动用户的权限和主机网络。进程所有权会等待退出及 I/O 结算完成。命令输出会被丢弃;确认失败时只保留一个有界整数退出状态。
-使用外部工作区存储的托管计算替换后,仅持久 Environment 文件系统和已通过资格验证的 Harness 私有原生历史会保留。Setup 命令不会重放。Setup 和工具可以写入启动用户有权访问的其他位置,但冷续接不保留临时系统盘上的修改、进程内存或后台进程。持久输出应写入工作区,软件包应使用已声明的安装路径;[Sandbox Provider 生命周期](../../../docs/zh/sandbox-provider.md#suspension)定义何时可以替换计算。
+使用外部工作区存储的托管计算替换后,仅持久 Environment 文件系统和已通过资格验证的 Harness 私有原生历史会保留。Setup 命令不会重放。Setup 和工具可以写入启动用户有权访问的其他位置,但冷续接不保留临时系统盘上的修改、进程内存或后台进程。持久输出应写入工作区,软件包应使用已声明的安装路径;[沙箱提供商生命周期](../../../docs/zh/sandbox-provider.md#suspension)定义何时可以替换计算。
### 显式本地工具环境 {#explicit-local-tool-environment}
@@ -229,7 +229,7 @@ daemon 以启动它的账户身份运行,绝不使用 sudo 或提升权限。
Environment 的初始化状态为 `pending`、`running`、`complete` 或 `failed`,且独立于任何分配、身份验证和连接发布。
-- Worker 的初始化调度器每次扫描 32 个 Environment,在末尾循环回绕,并依据执行并发度限制并发准备,且独立于 Provider 维护。
+- Worker 的初始化调度器每次扫描 32 个 Environment,在末尾循环回绕,并依据执行并发度限制并发准备,且独立于提供商维护。
- 缺少套接字不会消耗一次 pending 尝试。Harness 不可用时,会在安装前失败。每个操作都会重新检查当前权限和原始套接字;完成时还会重新检查精确绑定。
- 每个文件、Skill 或 Plugin 传输的暂存预算为两分钟。configure、软件包安装、设置命令和快照最终确定共享整个初始化过程的 30 分钟预算,Core 在每项操作中携带剩余时长,由 Runtime 执行。初始输入仍保留其五分钟接纳期限,因此大型安装应从空闲 Session 开始。
- 正在运行且所有权丧失的初始化,包括跨 Core 重启丧失所有权,会作为未确认而失败;不会重播任何内容。已完成的 Environment 在重连或原生恢复时绝不会重新安装,因此用户后续更改会保留下来。
@@ -249,9 +249,9 @@ Environment 的初始化状态为 `pending`、`running`、`complete` 或 `failed
每个初始化操作都会返回有类型的 `rejected`、`failed` 或 `unknown` 结果,并且 daemon 会先确认进程退出和 I/O 结算完成。Core 使用固定标签和整数组成原因,因此命令、env 值、软件包名称、路径和进程输出绝不会进入原因、事件、日志或响应。失败步骤不会重试,后续步骤也不会运行。机密 env 和设置快照会与普通元数据分开加密。初始文件在所有平台上都使用原子替换写入器和工作区锚定路径;Files API 创建则保留其自己的不覆盖规则。
-## Templates {#templates}
+## 模板 {#templates}
-Template 是由 Project 拥有、供 `openai_hosted` Session 和 `x_agents_core.environment` 使用的配置。它不包含运行中的工作区,也与 E2B templates 等 Provider 镜像无关。每个引用它的 Session 都会通过与内联配置相同的准备过程获得自己的 Environment。Template 解析、存储和解析过程绝不会选择 Harness 或 Provider,也不会依赖原生工具名称或 Harness 私有路径,因此新的 Harness 或 Provider 无需修改 Template。
+模板是由项目拥有、供 `openai_hosted` Session 和 `x_agents_core.environment` 使用的配置。它不包含运行中的工作区,也与 E2B 模板等提供商镜像无关。每个引用它的 Session 都会通过与内联配置相同的准备过程获得自己的 Environment。模板解析、存储和解析过程绝不会选择 Harness 或提供商,也不会依赖原生工具名称或 Harness 私有路径,因此新的 Harness 或提供商无需修改模板。
```python
from openai import OpenAI
@@ -271,35 +271,35 @@ session = client.beta.agents.sessions.create(
### 操作 {#operations}
-- 每个操作都需要 Project API key 和 `OpenAI-Beta: agents=v1`。Template 操作无需执行部署,也不会分配计算资源。
+- 每个操作都需要项目 API 密钥和 `OpenAI-Beta: agents=v1`。模板操作无需执行部署,也不会分配计算资源。
- `name` 可选且可为 null,会逐字保留,长度为 1–256 个 Unicode 字符。
- `network.access` 为 `enabled`、`disabled` 或 `restricted`;省略或传入 null 表示启用。请参阅 [Restricted network](#restricted-network)。
- 响应会携带安全元数据,绝不会包含 `env`、`setup_commands` 正文或内联文件数据。
-- 列表操作使用 `after`、`limit`(默认 20;0 按 1 处理,超过 100 的值按 100 处理)和 `order`(默认 `desc`),并按创建时间和 ID 排序。不存在和属于外部 Project 的 Template ID 及游标都会返回相同的 404。
+- 列表操作使用 `after`、`limit`(默认 20;0 按 1 处理,超过 100 的值按 100 处理)和 `order`(默认 `desc`),并按创建时间和 ID 排序。不存在和属于外部项目的模板 ID 及游标都会返回相同的 404。
- 更新时,省略字段会保留原值,提供字段则会替换原值。Null 会清除 `name` 和每个列表,并将 `network` 重置为启用。
- 封装或解封机密内容(文件、env、设置命令、Skills、Plugins)的写入操作和 Session 解析需要 Core 的 [credential key](../../../docs/zh/configuration.md#compose-installations);元数据读取则不需要。
-- Session 会在创建时于其 Project 内解析一次 `environment_template_id`,冻结有效配置,并且绝不将 Template ID 传递给 Provider 或 Runtime。更新或删除 Template 绝不会改变现有 Session。创建重试会在读取 Template 之前恢复已记录的调用方意图,即使 Template 已删除也是如此;意图发生变化时会产生冲突。
+- Session 会在创建时于其项目内解析一次 `environment_template_id`,冻结有效配置,并且绝不将模板 ID 传递给提供商或 Runtime。更新或删除模板绝不会改变现有 Session。创建重试会在读取模板之前恢复已记录的调用方意图,即使模板已删除也是如此;意图发生变化时会产生冲突。
### 继承 {#inheritance}
-Session 会先应用 Template,然后应用自身字段。组合仅在加密 Session 快照写入前执行一次,并使用常规验证器重新验证结果。调用方意图(省略、null 或显式提供)会单独保留,用于重试策略。
+Session 会先应用模板,然后应用自身字段。组合仅在加密 Session 快照写入前执行一次,并使用常规验证器重新验证结果。调用方意图(省略、null 或显式提供)会单独保留,用于重试策略。
| 字段 | Session 中省略或为 null | Session 中提供 |
| --- | --- | --- |
-| `network` | 继承整个 Template 策略 | 必须收窄策略:enabled 可以变为 restricted 或 disabled;restricted 可以变为其主机的子集或 disabled;disabled 不能放宽 |
-| `env` | 继承 Template 键 | 按键叠加;Session 值优先;`{}` 会保留所有 Template 键 |
+| `network` | 继承整个模板策略 | 必须收窄策略:enabled 可以变为 restricted 或 disabled;restricted 可以变为其主机的子集或 disabled;disabled 不能放宽 |
+| `env` | 继承模板键 | 按键叠加;Session 值优先;`{}` 会保留所有模板键 |
| `setup_commands` | 继承该序列 | 替换该序列;`[]` 会清除 |
| `files` | 继承文件集 | 替换整个文件集;`[]` 会清除 |
| `packages` | 继承两个管理器 | 分别解析 `python` 和 `npm`:省略或为 null 的管理器会被继承,列表会替换原值,`[]` 会清除;`system` 会被拒绝 |
| `skills`、`plugins`、`capability_directories` | 继承列表 | 替换列表;`[]` 会清除 |
-作为比较,不带 Template 的内联 `openai_hosted` Session 会将省略或为 null 的 `network` 视为启用。
+作为比较,不带模板的内联 `openai_hosted` Session 会将省略或为 null 的 `network` 视为启用。
### 受限网络 {#restricted-network}
`restricted` 要求在 `allowed_domains` 中提供 1–100 个精确 ASCII 主机名;子域名和重定向目标需要各自的条目。通配符、URL 或端口语法、IP 字面量、Unicode 和尾随点都会被拒绝。读取操作会返回提供的拼写、顺序和重复项;比较操作使用单独的小写去重副本。
-Runtime 不会强制执行 `disabled` 或 `restricted`,也没有 Provider 代为强制执行。因此,Core 会在 Templates 中存储这些策略,但会在分配计算资源之前拒绝任何有效 network 不是 `enabled` 的 Session。初始化和工具使用主机现有的网络。
+Runtime 不会强制执行 `disabled` 或 `restricted`,也没有提供商代为强制执行。因此,Core 会在模板中存储这些策略,但会在分配计算资源之前拒绝任何有效 network 不是 `enabled` 的 Session。初始化和工具使用主机现有的网络。
### Env 与设置命令 {#env-and-setup-commands}
@@ -307,7 +307,7 @@ Agent 代码可以读取 env 值,但它们绝不会出现在公开元数据或
### 初始文件 {#initial-files}
-`files` 条目会将文件放置在 `/workspace` 内的绝对目标路径,来源可以是内联标准 Base64 `data`,也可以是 Project 所有的已上传 `file_id`。
+`files` 条目会将文件放置在 `/workspace` 内的绝对目标路径,来源可以是内联标准 Base64 `data`,也可以是项目所有的已上传 `file_id`。
| 限制 | 值 |
| --- | --- |
@@ -315,13 +315,13 @@ Agent 代码可以读取 env 值,但它们绝不会出现在公开元数据或
| 内联文件 | 5 MiB |
| 所有内联内容 | 10 MiB |
| 引用文件 | 50 MiB |
-| Session 或 Template 请求正文 | 16 MiB |
+| Session 或模板请求正文 | 16 MiB |
-路径必须规范、互不相同且位于逻辑工作区内部;Runtime 会将每次写入锚定到其绑定的工作区。这是 API 路径范围,不是对以同一用户身份运行的原生工具的限制。Template 元数据会将内联文件显示为 type、path 和 size,将引用显示为 type、path 和 `file_id`;无论内联文件还是引用,每个 Session 都会获得全新的文件 ID 和大小。文件数据不会出现在普通配置、响应、事件或命令参数中。Template 会保留引用;每个 Session 会授权并冻结自己的加密源字节,因此之后删除源文件无法改变这些字节。
+路径必须规范、互不相同且位于逻辑工作区内部;Runtime 会将每次写入锚定到其绑定的工作区。这是 API 路径范围,不是对以同一用户身份运行的原生工具的限制。模板元数据会将内联文件显示为 type、path 和 size,将引用显示为 type、path 和 `file_id`;无论内联文件还是引用,每个 Session 都会获得全新的文件 ID 和大小。文件数据不会出现在普通配置、响应、事件或命令参数中。模板会保留引用;每个 Session 会授权并冻结自己的加密源字节,因此之后删除源文件无法改变这些字节。
### Skills {#skills}
-Templates 和内联配置都接受 Project 所有的 Skill 引用及内联 Skill ZIP。通过固定版本 SDK 上传目录,然后引用其默认版本:
+模板和内联配置都接受项目所有的 Skill 引用及内联 Skill ZIP。通过固定版本 SDK 上传目录,然后引用其默认版本:
```python
skill = client.skills.create(files=[
@@ -332,9 +332,9 @@ template = client.beta.agents.environments.templates.create(
)
```
-固定版本的 `/v1/skills` 资源、版本及内容路由使用 Project API key,且不使用 Agents beta 标头。ZIP 上传使用 `files`,目录上传则重复使用 `files[]`。固定版本 SDK 3.13.0 在多部分内容提取过程中会丢弃单文件 tuple,因此应使用原始 HTTP 上传单个 ZIP。一次上传最多包含 500 个常规文件,并且必须恰好包含一个 `SKILL.md`;压缩后为 5 MiB,展开后为 20 MiB。[File resource semantics](source-files.md#versions-and-metadata) 负责默认版本和删除规则。
+固定版本的 `/v1/skills` 资源、版本及内容路由使用项目 API 密钥,且不使用 Agents beta 标头。ZIP 上传使用 `files`,目录上传则重复使用 `files[]`。固定版本 SDK 3.13.0 在多部分内容提取过程中会丢弃单文件 tuple,因此应使用原始 HTTP 上传单个 ZIP。一次上传最多包含 500 个常规文件,并且必须恰好包含一个 `SKILL.md`;压缩后为 5 MiB,展开后为 20 MiB。[File resource semantics](source-files.md#versions-and-metadata) 负责默认版本和删除规则。
-省略或传入 null 版本的引用会在 Session 创建时选择默认版本,`"latest"` 会选择最新版本,正版本号字符串则选择该版本。Template 响应会保留未解析的选择器(默认版本为 `version: null`);Session 元数据会显示 `{type, skill_id, version, name, description}`,其中版本为具体值。Session 会在其创建事务中冻结所选版本的字节和元数据;之后默认版本发生变化、源被删除或 Template 被更新,都无法改变这些内容。
+省略或传入 null 版本的引用会在 Session 创建时选择默认版本,`"latest"` 会选择最新版本,正版本号字符串则选择该版本。模板响应会保留未解析的选择器(默认版本为 `version: null`);Session 元数据会显示 `{type, skill_id, version, name, description}`,其中版本为具体值。Session 会在其创建事务中冻结所选版本的字节和元数据;之后默认版本发生变化、源被删除或模板被更新,都无法改变这些内容。
内联 Skill 携带 `name`、`description` 和 Base64 ZIP `source`(`media_type` 为 `application/zip`)。归档包含一个顶层文件夹,其中有 `SKILL.md` 和可选的支持文件;清单中的 name 和 description 必须与请求一致。Frontmatter 可以包含 `name`、`description`、`license`、`compatibility` 和字符串 `metadata`;原生 hooks、权限控制和 subagent 指令都会被拒绝。只允许常规文件:路径遍历、链接、重复目标位置、特殊文件和无效清单都会被拒绝。内容在安装期间保持惰性,并保留可执行位。内联元数据只显示 type、name 和 description。
@@ -342,7 +342,7 @@ template = client.beta.agents.environments.templates.create(
Plugin 是带有 type、name 和 description 的内联 ZIP,其单个归档根目录包含 `.codex-plugin/plugin.json`。清单中的 `skills` 指定 Skill 目录;整个包布局都会保留。公开 Plugin 元数据只显示 type、name 和 description。
-`openai_hosted` 和 Template 的 `capability_directories` 接受 `/workspace` 内的干净绝对路径,初始文件和设置命令可以填充这些路径。`self_hosted` 能力目录是机器上的绝对本地路径。通过目录发现的 Skills 绝不会显示为 `skills` 或 `plugins` 条目。目录缺失、Skill 名称重复、清单不受支持以及存在非常规文件时,初始化会失败。
+`openai_hosted` 和模板的 `capability_directories` 接受 `/workspace` 内的干净绝对路径,初始文件和设置命令可以填充这些路径。`self_hosted` 能力目录是机器上的绝对本地路径。通过目录发现的 Skills 绝不会显示为 `skills` 或 `plugins` 条目。目录缺失、Skill 名称重复、清单不受支持以及存在非常规文件时,初始化会失败。
| 归档与安装限制 | 值 |
| --- | --- |
@@ -353,11 +353,11 @@ Plugin 是带有 type、name 和 description 的内联 ZIP,其单个归档根
## Skills、Plugins 与 Environment MCP {#skills-plugins-and-environment-mcp}
-Skills 及其不可变版本是 Project 资源,独立于 Session 和原生安装。
+Skills 及其不可变版本是项目资源,独立于 Session 和原生安装。
- 版本分配和指针变更会在所属 Skill 行上串行化。顶层 name 和 description 在同一事务中跟随默认版本;非默认上传不会更改它们。在并发上传和删除过程中,版本身份始终唯一。
-- Bundle 使用服务密码进行加密,并绑定到 Project、Skill 和版本。元数据读取绝不会加载或解密 Bundle。删除 Skill 会回收其版本,但不会影响已冻结的 Session。
-- 引用会在 Session 创建事务中、upsert 建立所有权之后解析。被引用的资源按稳定顺序锁定,版本、元数据和字节会一并冻结。公开引用元数据、未解析的 Template 意图和已解析的 Runtime Bundle 始终彼此独立;引用绝不会报告为内联内容。
+- Bundle 使用服务密码进行加密,并绑定到项目、Skill 和版本。元数据读取绝不会加载或解密 Bundle。删除 Skill 会回收其版本,但不会影响已冻结的 Session。
+- 引用会在 Session 创建事务中、upsert 建立所有权之后解析。被引用的资源按稳定顺序锁定,版本、元数据和字节会一并冻结。公开引用元数据、未解析的模板意图和已解析的 Runtime Bundle 始终彼此独立;引用绝不会报告为内联内容。
内联和引用的 Skills 使用相同的机密快照与安装器。Runtime 会在设置和原生执行之前,将它们安装到能力根目录下的 `skills/`。适配器只注册所选的 Skill 根目录:Codex 将其注册为显式额外根目录,MiniMax Code 通过其原生目录进行注册,Claude 则为每个包使用一个受控封装,其中包含实际目录和不可变硬链接。自动原生 MCP 发现保持禁用。Codex 的嵌套 `SKILL.md` 发现、`agents/openai.yaml` 依赖项配置以及 Claude 内联 shell 预处理都会导致适配器准备失败。原生 Harness 配置绝不会整体透传。
@@ -386,10 +386,10 @@ Agent 的 HTTP MCP 工具([declaration](execution-tools.md#http-mcp))具有
| `service` | Core 的服务端执行主机 | 仅 `none` |
| `environment` | Environment 的工作区 | `openai_hosted` 和启用网络的 `self_hosted` |
-Core 的 Harness profile 会声明 `MCPOrigins`;接纳和分派会将来源与放置方式以及 Runtime 公布的 HTTP、bearer 和必需初始化能力进行核对,Runtime 会在调用适配器之前再次验证来源。不存在按 Harness 名称或 Provider 分支选择不同路径的逻辑。
+Core 的 Harness profile 会声明 `MCPOrigins`;接纳和分派会将来源与放置方式以及 Runtime 公布的 HTTP、bearer 和必需初始化能力进行核对,Runtime 会在调用适配器之前再次验证来源。不存在按 Harness 名称或提供商分支选择不同路径的逻辑。
[Harness capabilities](harness-capabilities.md#tools) 负责每个 Harness 的来源支持和策略限制。
-两种来源都支持匿名 HTTP 和 HTTPS bearer 凭据。所附加 Vault 的选择会冻结凭据身份,包括唯一的隐式 URL 匹配或匿名选择。只有该凭据经 Project 授权后,才会进入瞬时 Runtime 请求;绝不会搜索 Core 默认值或无关 Vault。解密失败或凭据缺失时,执行会失败且不会回退到匿名。公开 Environment MCP 保留 `project_vault` 权限,Plugin 凭据保留 `environment_configuration` 权限;两者都不会覆盖重复的服务器标签。Bearer 令牌绝不会进入持久化的原生配置或进程参数。
+两种来源都支持匿名 HTTP 和 HTTPS bearer 凭据。所附加 Vault 的选择会冻结凭据身份,包括唯一的隐式 URL 匹配或匿名选择。只有该凭据经项目授权后,才会进入瞬时 Runtime 请求;绝不会搜索 Core 默认值或无关 Vault。解密失败或凭据缺失时,执行会失败且不会回退到匿名。公开 Environment MCP 保留 `project_vault` 权限,Plugin 凭据保留 `environment_configuration` 权限;两者都不会覆盖重复的服务器标签。Bearer 令牌绝不会进入持久化的原生配置或进程参数。
工具允许列表和必需初始化遵循 [HTTP MCP contract](execution-tools.md#http-mcp)。
diff --git a/contracts/agents-api/zh/execution-tools.md b/contracts/agents-api/zh/execution-tools.md
index 022a42ed5..b3bf710a0 100644
--- a/contracts/agents-api/zh/execution-tools.md
+++ b/contracts/agents-api/zh/execution-tools.md
@@ -27,7 +27,7 @@ Agent 在 `tools` 中声明应用函数、控制项和 MCP 服务器,并可在
| 调用方 Session 内未知调用或其他 Turn 的调用 | 400 `invalid_request_error`;待执行操作不变 |
| Session 不存在或属于其他范围 | 404 |
-[Session 输入冲突](sessions-events.md#input-errors)记录准确消息。无效或不支持的内容不能消耗待处理调用。准入与应用结果分离:只有匹配的原生工具结果出现在实时根 Turn 中,适配器才确认结果([回执契约](message-content.md#function-results))。传输写入本身不确认任何事实,确认也不代表提供方已消费结果或外部副作用恰好发生一次。Core 不自动重放结果。
+[Session 输入冲突](sessions-events.md#input-errors)记录准确消息。无效或不支持的内容不能消耗待处理调用。准入与应用结果分离:只有匹配的原生工具结果出现在实时根 Turn 中,适配器才确认结果([回执契约](message-content.md#function-results))。传输写入本身不确认任何事实,确认也不代表提供商已消费结果或外部副作用恰好发生一次。Core 不自动重放结果。
### 待执行操作与恢复 {#required-actions-and-recovery}
@@ -49,7 +49,7 @@ Claude 适配器将 `outputFormat` 传给固定版本 SDK,并允许原生 `Str
`tool_search` 工具仅包含 `type`;仅适用于 Responses 的执行字段被拒绝。函数 `defer_loading` 标记延迟加载的定义。发现要求两者同时存在:没有延迟函数的 `tool_search`,或没有 `tool_search` 的延迟函数均被拒绝。已保存 Agent 的工具联合类型保留 `tool_search`;固定版本 Session 响应联合类型省略它,因此 Session 与 SSE 资源投影移除它,冻结配置仍保留它。固定版本 Item 联合类型没有 tool-search Item,Core 不自行创建。
-Core 发送 `PromptRequestPayload.ToolSearch` 和每个 `FunctionTool.DeferLoading`,并要求配置通过资格验证、Runtime 具备 `tool_search` 能力。原生搜索与 schema 延迟加载属于适配器。Claude 适配器的 MCP 服务器将立即加载定义标记为 `anthropic/alwaysLoad:true`,延迟定义标记为 false,并启用原生 ToolSearch;函数配置仅允许所声明回调、ToolSearch 与选定的工作区工具。工作区 Runtime 从桥接层的 `workspace_tool_search` 功能推导 `tool_search`。原生 Harness 管理模型与提供方策略;已知冲突模式和 beta 设置在适配器中拒绝,不透明策略改变后,SDK 不提供可靠的输入前信号来确认延迟加载是否生效。
+Core 发送 `PromptRequestPayload.ToolSearch` 和每个 `FunctionTool.DeferLoading`,并要求配置通过资格验证、Runtime 具备 `tool_search` 能力。原生搜索与 schema 延迟加载属于适配器。Claude 适配器的 MCP 服务器将立即加载定义标记为 `anthropic/alwaysLoad:true`,延迟定义标记为 false,并启用原生 ToolSearch;函数配置仅允许所声明回调、ToolSearch 与选定的工作区工具。工作区 Runtime 从桥接层的 `workspace_tool_search` 功能推导 `tool_search`。原生 Harness 管理模型与提供商策略;已知冲突模式和 beta 设置在适配器中拒绝,不透明策略改变后,SDK 不提供可靠的输入前信号来确认延迟加载是否生效。
## Web 搜索与程序化工具调用 {#web-search-and-programmatic-tool-calling}
diff --git a/contracts/agents-api/zh/harness-capabilities.md b/contracts/agents-api/zh/harness-capabilities.md
index e95d9114d..e8cf6f8fd 100644
--- a/contracts/agents-api/zh/harness-capabilities.md
+++ b/contracts/agents-api/zh/harness-capabilities.md
@@ -27,7 +27,7 @@ source_hash: a88b7238811707dd7fecae6ee8e509572677b49958e36ddabf8b783e97382c13
| 非 `medium` 的 `text.verbosity` | 已准入;由原生模型决定 | 已拒绝 | 已拒绝 |
| [公开 token 用量](sessions-events.md) | 测量计数器 | Null | Null |
-各 Harness 原生模型参数及提供方协议见[模型执行](model-execution.md)。
+各 Harness 原生模型参数及提供商协议见[模型执行](model-execution.md)。
## 工具 {#tools}
@@ -62,4 +62,4 @@ Claude 结构化输出要求单 Agent、medium verbosity,且无 Skill、Plugin
| [stdio Plugin MCP](environments.md#plugin-mcp) | 已验证:托管、自托管 | 已验证:自托管;已准入:托管 | 已验证:自托管;已准入:托管 |
| HTTP Plugin MCP | 已准入,字面值头或 HTTPS bearer | 已准入,匿名或 HTTPS bearer | 已验证:自托管;已准入:托管;匿名或 HTTPS bearer |
-外部工作区存储还要求所选 Harness profile 和 Runtime 支持 `retained_native_history`;自带工作区存储不要求此能力。[Workspace Provider 指南](../../../docs/zh/workspace-provider.md)定义存储组合准入规则。
+外部工作区存储还要求所选 Harness profile 和 Runtime 支持 `retained_native_history`;自带工作区存储不要求此能力。[工作区提供商指南](../../../docs/zh/workspace-provider.md)定义存储组合准入规则。
diff --git a/contracts/agents-api/zh/harness-onboarding.md b/contracts/agents-api/zh/harness-onboarding.md
index 22430ef85..804ff05c6 100644
--- a/contracts/agents-api/zh/harness-onboarding.md
+++ b/contracts/agents-api/zh/harness-onboarding.md
@@ -34,7 +34,7 @@ Runtime: Executor preparation, reuse, idle expiry, recovery
| 服务 profile | 对已认定合格的操作和放置位置进行纯验证 | `services/core/internal/engine` |
| 注册 | 适配器声明、已安装工厂和已验证能力 | `apps/daemon/internal/agent//declaration.go`;`apps/daemon/internal/cli/agent_discovery.go` 中的静态列表 |
-Environment 提供执行资源。受管 E2B、Docker 和 microsandbox 机器以及应用自有机器在预配和连接方式上有所不同;已连接的 Runtime 使用同一契约。daemon 运行于 Linux、macOS 和 Windows,受管 Provider 仅支持 Linux,并且每个适配器自行认定其支持的平台([self-hosted platforms](../../../docs/zh/getting-started/self-hosted.md#platforms))。只有在 Runtime 加载绑定的已安装快照后,原生工厂才会收到能力([capability preparation](environments.md#runtime-capability-preparation))。模型 Provider 提供模型通信设置,而不负责 Turn 调度或原生进程所有权。
+Environment 提供执行资源。受管 E2B、Docker 和 microsandbox 机器以及应用自有机器在预配和连接方式上有所不同;已连接的 Runtime 使用同一契约。daemon 运行于 Linux、macOS 和 Windows,受管提供商仅支持 Linux,并且每个适配器自行认定其支持的平台([self-hosted platforms](../../../docs/zh/getting-started/self-hosted.md#platforms))。只有在 Runtime 加载绑定的已安装快照后,原生工厂才会收到能力([capability preparation](environments.md#runtime-capability-preparation))。模型提供商负责模型通信设置,而不负责 Turn 调度或原生进程所有权。
## 步骤 {#steps}
@@ -51,7 +51,7 @@ Environment 提供执行资源。受管 E2B、Docker 和 microsandbox 机器以
## 架构规则 {#architecture-rules}
- Codex、Claude Code 和未来的 Harness 地位平等。通用 Runtime 线协议以及 Executor 和 Turn 接口负责生命周期、输入回执、取消、恢复和资源访问;每个适配器保留其原生实现以及模型和工具循环。
-- 新引擎需要提供适配器、已认定合格的 profile、注册以及经过独立验证的部署。它不得在 API 处理程序、持久化、调度、调度器或 Environment Provider 中添加按引擎名称分支的实现,也不得为契约已经涵盖的能力添加处理程序、存储表、调度器、事件投影器或模型循环。
+- 新引擎需要提供适配器、已认定合格的 profile、注册以及经过独立验证的部署。它不得在 API 处理程序、持久化、调度、调度器或 Environment 提供商中添加按引擎名称分支的实现,也不得为契约已经涵盖的能力添加处理程序、存储表、调度器、事件投影器或模型循环。
- 将必需的生命周期声明、扩展接口和注册方法保留在 `agent/harness.go` 中。结果类型、错误和 Registry 存储可以保留在聚焦的文件中。
- 使用现有的 `proto.SupportedAgentKind` 和 `AgentKindCapabilities` schema。不要添加第二套能力描述符或组合式可选接口。
- 接入不要求功能完全一致。Harness 不必匹配彼此的可选功能,并且注册时不强制要求 MCP、函数、图像或详细程度控制。验证通用生命周期义务,并对每个声明的操作使用相同的公共断言。缺少声明或扩展实现会阻止接入;原生差异不会。
@@ -90,13 +90,13 @@ func (s *Session) SubmitFunctionResult(context.Context, proto.FunctionResultPayl
工作区能力描述实际 Runtime 与资源所有者的组合。Codex 和 MiniMax 资源对象拒绝原生工作区访问,而通用的授权 `localworkspace` 所有者提供该访问;Claude 可以公开原生读取和列举访问,通用所有者提供写入。仅仅存在相应接口绝不会选择某个资源或宣称支持。
-服务 profile 对公共组合进行资格认定,Runtime 宣称已安装的组合;二者都不能替代 schema 验证或 Project 授权。原生行为测试必须与声明一致。已宣称但返回 Unsupported 的操作属于契约违规,既不是成功,也不能作为重放的依据。
+服务 profile 对公共组合进行资格认定,Runtime 宣称已安装的组合;二者都不能替代 schema 验证或项目授权。原生行为测试必须与声明一致。已宣称但返回 Unsupported 的操作属于契约违规,既不是成功,也不能作为重放的依据。
## Executor 和 Turn 生命周期 {#executor-and-turn-lifetimes}
| 生命周期 | 所有者 | 结束条件 |
| --- | --- | --- |
-| Environment 分配 | Sandbox Provider | 显式回收,并与 Runtime 执行协调 |
+| Environment 分配 | 沙箱提供商 | 显式回收,并与 Runtime 执行协调 |
| Runtime 连接 | Runtime 传输层 | 断开连接或被较新的连接替换 |
| 已安装能力快照 | Runtime | 其 Environment 被回收;绝不因 Executor 关闭而结束 |
| Session Executor | Runtime | 空闲过期、关闭或确认失效时执行 `Executor.Close` |
@@ -201,7 +201,7 @@ profile 是纯逻辑:它使用现有的公共类型和协议类型,声明受
[`internal/harnessconfig/harness.go`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/internal/harnessconfig/harness.go) 负责共享配置声明和纯准备契约。每个适配器在 `internal/harnessconfig/` 中提供一个 `Configuration`,供 Core 组合和 Runtime 的 `RegisterKind` 使用。Executor 路径会在产生原生副作用之前通过该声明进行验证。线协议对象是 `proto.HarnessConfig`。[Model execution](model-execution.md#native-model-parameters) 列出了每个 Harness 接受的字段。
-提供的 `model` 必须是非空字符串,并且显式指定 `model_provider` 时必须提供它。原生所有权连接路径可以省略二者;显式 null 无效。显式为空的声明不接受任何 Provider 或非空原生参数,也不宣称支持 Provider。未知协议格式和重复协议声明会导致注册失败。
+提供的 `model` 必须是非空字符串,并且显式指定 `model_provider` 时必须提供它。原生所有权连接路径可以省略二者;显式 null 无效。显式为空的声明不接受任何提供商或非空原生参数,也不宣称支持提供商。未知协议格式和重复协议声明会导致注册失败。
声明中的有序 `protocols` 列表是接受协议及默认协议(第一个条目)的唯一来源;它还为 Core 的配置支持描述符提供数据,Core 和 Runtime 通过它拒绝不受支持的组合。适配器通过原生配置直接连接;它们绝不引入模型 API 代理或协议转换器、第二套模型能力 registry,也不会从模型名称推断能力。Claude 的私有 bridge 接收编译后的原生选项,并且只执行结构检查,而不是声明规则的第二份副本。
@@ -209,15 +209,15 @@ profile 是纯逻辑:它使用现有的公共类型和协议类型,声明受
开始前,记录操作集、预期结果、排除项和停止条件。当其声明的操作通过时,资格认定即结束;它不会扩展为匹配另一个 Harness 的功能列表。
-1. **契约测试。** 在名为 `TestSharedTextLifecycle` 的测试中,使用适配器准备好的 Executor 和确定性的原生夹具调用 `agent/contracttest.TextLifecycle`;`claudesdk/executor_test.go` 是参考实现。它检查独立的 Turn 流、原生所有者和历史连续性、持久化写入与应用回执、过期取消,以及取消后的健康继续执行。`make check-runtime-contract` 会将它与共享线协议、gateway、传输层和调度器测试、声明完整性检查以及每个适配器的 `TestUnsupportedExtensionsHaveNoNativeEffects` 一起运行。适配器测试还覆盖两个普通 Turn 共享一个原生进程或连接和历史、取消后执行另一个 Turn、过期取消和迟到事件、原生退出、清理失败、输入写入与应用回执、未知结果,以及每 Turn 新鲜的 usage、函数、输入和子项观察状态。必须说明夹具是受控夹具还是真实 Provider。
+1. **契约测试。** 在名为 `TestSharedTextLifecycle` 的测试中,使用适配器准备好的 Executor 和确定性的原生夹具调用 `agent/contracttest.TextLifecycle`;`claudesdk/executor_test.go` 是参考实现。它检查独立的 Turn 流、原生所有者和历史连续性、持久化写入与应用回执、过期取消,以及取消后的健康继续执行。`make check-runtime-contract` 会将它与共享线协议、gateway、传输层和调度器测试、声明完整性检查以及每个适配器的 `TestUnsupportedExtensionsHaveNoNativeEffects` 一起运行。适配器测试还覆盖两个普通 Turn 共享一个原生进程或连接和历史、取消后执行另一个 Turn、过期取消和迟到事件、原生退出、清理失败、输入写入与应用回执、未知结果,以及每 Turn 新鲜的 usage、函数、输入和子项观察状态。必须说明夹具是受控夹具还是真实提供商。
2. **共享集成。** `TestThirdHarnessPublicOnboarding` 让合成 Harness 通过公共 Session 和输入准入、Worker 设备选择、真实 WebSocket gateway、daemon Registry 和 Router、中立事件以及持久化终态投影运行。它在与 API 处理程序和调度器相同的 `execution.Policy` 中使用自定义不可变 `engine.Catalog`,并检查已应用输入回执、已保存原生身份、继续执行、取消、不受支持的可选请求以及缺少强制 Runtime 支持。该夹具没有工作区、MCP 或公共函数,其注册仅保留在测试本地。它证明的是集成路径,而不是原生执行。
-3. **真实验收。** 使用锁定的官方 Python SDK 和针对 Core 的原始 HTTP、真实 Provider API、原生 Harness 以及专用数据库。验证初始执行、热后续执行、取消以及带继续执行的重启;记录原生所有者身份以及相同条件下的冷启动和热运行时间。对于工作区放置方式,还要验证 Files 和 Artifacts、工作区身份、公开响应中未出现凭据,以及外部历史会被拒绝。`services/core/tests/official_hosted_functions_native.py` 保存共享函数断言:成功和错误、原生文件输出和公共 Artifact 字节、重启后的同历史继续执行、外部结果拒绝以及待处理调用取消。合成运行或失败运行绝不计入。下面的选择性测试会在 `services/core/tests` 中针对真实 daemon 和模型运行锁定 SDK 夹具;设置 `OAC_TEST_OFFICIAL_SDK_PYTHON`、`OAC_TEST_NATIVE_DAEMON_BIN`、`OAC_TEST_NATIVE_PROOF_DIR` 及其私有选项文件后,每项测试才会运行。选项文件是一个 JSON 对象,恰好包含 `model` 和 `model_provider`(即 `x_agents_core.model_provider` 的字段);测试会将其设置为部署默认模型 Provider,而夹具的 `environment: none` Session 会在创建时将其冻结。
+3. **真实验收。** 使用锁定的官方 Python SDK 和针对 Core 的原始 HTTP、真实提供商 API、原生 Harness 以及专用数据库。验证初始执行、热后续执行、取消以及带继续执行的重启;记录原生所有者身份以及相同条件下的冷启动和热运行时间。对于工作区放置方式,还要验证 Files 和 Artifacts、工作区身份、公开响应中未出现凭据,以及外部历史会被拒绝。`services/core/tests/official_hosted_functions_native.py` 保存共享函数断言:成功和错误、原生文件输出和公共 Artifact 字节、重启后的同历史继续执行、外部结果拒绝以及待处理调用取消。合成运行或失败运行绝不计入。下面的选择性测试会在 `services/core/tests` 中针对真实 daemon 和模型运行锁定 SDK 夹具;设置 `OAC_TEST_OFFICIAL_SDK_PYTHON`、`OAC_TEST_NATIVE_DAEMON_BIN`、`OAC_TEST_NATIVE_PROOF_DIR` 及其私有选项文件后,每项测试才会运行。选项文件是一个 JSON 对象,恰好包含 `model` 和 `model_provider`(即 `x_agents_core.model_provider` 的字段);测试会将其设置为部署默认模型提供商,而夹具的 `environment: none` Session 会在创建时将其冻结。
4. **回归。** 现有 Harness 必须继续正常工作。先运行定向测试,然后运行 `make check`;API 更改后运行 `make openapi`,查询更改后运行 `make sqlc-generate`。
5. **审查。** 遵循 [blind review workflow](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/CONTRIBUTING.md#review)。
| 操作 | `services/core/tests/integration` 中的测试 | 选项文件变量;测试采用 Harness 变量时也列出该变量 |
| --- | --- | --- |
-| 模型 Provider 协议 | `TestNativeModelProtocolPublicExecution` | [Model execution](model-execution.md#acceptance) |
+| 模型提供商协议 | `TestNativeModelProtocolPublicExecution` | [Model execution](model-execution.md#acceptance) |
| MiniMax Code 文本 | `TestNativeMCodePublicExecution` | `OAC_TEST_MCODE_REAL_OPTIONS` |
| 消息图像 | `TestNativeMessageImagePublicExecution` | `OAC_TEST_MESSAGE_IMAGE_REAL_OPTIONS`、`OAC_TEST_MESSAGE_IMAGE_ENGINE` |
| 带图像的函数结果 | `TestNativeFunctionImagePublicExecution` | `OAC_TEST_FUNCTION_IMAGE_REAL_OPTIONS`、`OAC_TEST_FUNCTION_IMAGE_ENGINE` |
@@ -225,9 +225,9 @@ profile 是纯逻辑:它使用现有的公共类型和协议类型,声明受
| 延迟函数发现 | `TestNativeToolSearchPublicExecution` | `OAC_TEST_TOOL_SEARCH_REAL_OPTIONS` |
| 禁用 Web 搜索和程序化工具调用 | `TestNativeToolPolicyPublicExecution` | `OAC_TEST_TOOL_POLICY_REAL_OPTIONS`、`OAC_TEST_TOOL_POLICY_ENGINE` |
-Environment 验收使用 `services/core/tests/official_environment_{templates,setup,skills,plugins,plugin_mcp,composition,initial_files,network,skill_references}.py`。对于组合式准备,请更改 Skill 默认值和 Template,删除源文件,重试并重启;验证冻结字节、一次 setup 执行和 MCP 取消。`official_hosted_structured_native.py` 覆盖托管结构化输出。随每项验收结果记录精确源修订版本、原生版本和命令。
+Environment 验收使用 `services/core/tests/official_environment_{templates,setup,skills,plugins,plugin_mcp,composition,initial_files,network,skill_references}.py`。对于组合式准备,请更改 Skill 默认值和模板,删除源文件,重试并重启;验证冻结字节、一次 setup 执行和 MCP 取消。`official_hosted_structured_native.py` 覆盖托管结构化输出。随每项验收结果记录精确源修订版本、原生版本和命令。
-将 Provider 密钥保存在私有操作员文件中,绝不能放入提交或日志。相对于 `apps/daemon/internal/agent` 的现有定向测试如下:
+将提供商密钥保存在私有操作员文件中,绝不能放入提交或日志。相对于 `apps/daemon/internal/agent` 的现有定向测试如下:
| 边界 | 测试 |
| --- | --- |
diff --git a/contracts/agents-api/zh/index.md b/contracts/agents-api/zh/index.md
index e27ed60f1..6aa44d1d9 100644
--- a/contracts/agents-api/zh/index.md
+++ b/contracts/agents-api/zh/index.md
@@ -1,7 +1,7 @@
---
title: "Agents API 覆盖台账"
source: contracts/agents-api/index.md
-source_hash: 842e0f7a2685950efaad106244a101e11f213030387426759206ba0bfd44ab61
+source_hash: 582d7e85432d29a79607142ee5dd88f1a5691625a6c6b64b119785b2e95146c9
---
Core 旨在以下方固定版本为准支持完整的 OpenAI Agents API([public API rule](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/AGENTS.md#public-api))。本台账记录 Core 对各项资源实现了哪些内容、哪些契约保存其详细信息,并列出相对于 OpenAI 服务的所有已知差异和所有未解决缺口。[API namespaces and credentials](../../../docs/zh/api/index.md) 说明谁调用哪些 API;[Agents API guide](../../../docs/zh/api/public-agent-api.md) 介绍使用方法。
@@ -40,9 +40,9 @@ Go 输入投影排除 `packages.system`,保留下方记录的明确拒绝行
| Items | list | 部分实现:支持消息、命令、MCP 调用、functions、web search、reasoning 和 Subagent 协调 Items;其他原生变体不会被投影 | [Turns and Items](sessions-events.md#turns-and-items) |
| Artifacts | retrieve, list, delete, content | 已实现 | [Environment files and Artifacts](environment-files.md) |
| Subagents | retrieve, list; Items; Turns retrieve and list; Turn Items | 部分实现:只读子级工作;不支持实时子级进度或可选原生操作 | [Subagents](subagents.md) |
-| Environments | retrieve | 已实现;以 Session 为范围([归属](environments.md#resources-and-states))。固定版本契约会拒绝 `environment.environment_id`;已有 hosted Environment 无法跨 Session 关联。跨 Session 共享的工作区属于应用([Project 拥有资产](../../../docs/zh/concepts.md#projects-own-assets)) | [Environments](environments.md) |
+| Environments | retrieve | 已实现;以 Session 为范围([归属](environments.md#resources-and-states))。固定版本契约会拒绝 `environment.environment_id`;已有 hosted Environment 无法跨 Session 关联。跨 Session 共享的工作区属于应用([项目拥有资产](../../../docs/zh/concepts.md#projects-own-assets)) | [Environments](environments.md) |
| Environment files | create, list | 已实现;列表不会递归 | [Environment files and Artifacts](environment-files.md) |
-| Environment Templates | create, retrieve, update, list, delete | 已实现;执行限制列于 [known gaps](#known-gaps) | [Environment Templates](environments.md#templates) |
+| Environment 模板 | create, retrieve, update, list, delete | 已实现;执行限制列于 [known gaps](#known-gaps) | [Environment 模板](environments.md#templates) |
| Vaults | create, retrieve, list, delete | 已实现;没有归档操作 | [Vaults and Credentials](vaults.md) |
| Vault Credentials | create, retrieve, update, list, delete | 已支持 `static_bearer` 和 `mcp_oauth` | [Vaults and Credentials](vaults.md) |
| Files | create, retrieve, list, delete, content | 已支持 `purpose=user_data`;内容下载会被拒绝 | [Files and Skills](source-files.md) |
@@ -126,7 +126,7 @@ Core 自身字段位于 `x_agents_core` 中([Core extensions](../../../docs/zh
- 对于原生副作用,Core 不提供崩溃安全或恰好一次保证;已认领的工作若不重放,会在重启后失败。
- 图像必须是内嵌的 PNG 或 JPEG data URI;远程 URL、`file_id` 和 `detail` 会被拒绝。
-**Environments 和 Templates**
+**Environments 和模板**
- Hosted 工作区准入受[租户容量策略](../../../docs/zh/configuration.md#tenant-capacity)及既有[输入预留截止时间](environments.md#reservations)限制。
- Runtime 不会实施 `disabled` 或 `restricted` 网络,因此需要这些网络的 Session 会被拒绝([restricted network policy](environments.md#restricted-network))。
@@ -158,7 +158,7 @@ Core 自身字段位于 `x_agents_core` 中([Core extensions](../../../docs/zh
- npm、initial-file 和 Skill 安装的失败原因没有官方样本。
- Codex 对文本旁的空文本部分、失败函数结果中的图像或远程引用图像的行为;Claude 对混合消息中仅含空白或空文本块的行为。
- 在 Core 返回 405 的路由上,官方服务的 `HEAD` 行为。
-- 精确主机名之外的 Environment Template 主机名形式,以及 `disabled` 与域结合使用的情况。
+- 精确主机名之外的 Environment 模板主机名形式,以及 `disabled` 与域结合使用的情况。
- Files 发生变化时的 purpose 筛选和分页;官方 Skill 上传限制和错误时机。
- Environment file 列表的默认值(limit 为 20、默认路径为工作区根目录、不递归、page-token 失效)、50 MiB 的 `file_id` 复制上限,以及创建时的检查顺序。
- Artifact 对硬链接、特殊文件和链接形式的 `outputs` 目录的捕获,内容字节变化后的重新发布,以及内容标头和范围。
diff --git a/contracts/agents-api/zh/machine-api.md b/contracts/agents-api/zh/machine-api.md
index baf8fff18..e68c60d6a 100644
--- a/contracts/agents-api/zh/machine-api.md
+++ b/contracts/agents-api/zh/machine-api.md
@@ -4,7 +4,7 @@ source: contracts/agents-api/machine-api.md
source_hash: e9a16774d2924db9dde18385be315d3a0317c616b029b419165e442fa34fb08d
---
-机器通过 `/api/v1` 调用 Core:包括沙箱节点、Runtime daemon 和自托管安装器。各路由仅接受所列凭据,不接受 Core 密钥或 Project API 密钥;控制台登录也不授予此处权限。反向代理将 `/api/v1` 直接发送给 Core;Web 不提供这些路由。
+机器通过 `/api/v1` 调用 Core:包括沙箱节点、Runtime daemon 和自托管安装器。各路由仅接受所列凭据,不接受 Core 密钥或项目 API 密钥;控制台登录也不授予此处权限。反向代理将 `/api/v1` 直接发送给 Core;Web 不提供这些路由。
## 路由 {#routes}
@@ -30,7 +30,7 @@ source_hash: e9a16774d2924db9dde18385be315d3a0317c616b029b419165e442fa34fb08d
| 凭据 | 签发方 | 接受位置 |
| --- | --- | --- |
-| 登记 token | `POST /core/v1/sandbox/enrollment-tokens`(Web **Add node**),带节点批准容量。使用一次;在响应 `expires_at` 过期 | 无节点 ID 的 `sandbox-node/configuration`、`sandbox-node/enroll` |
+| 登记 token | `POST /core/v1/sandbox/enrollment-tokens`(Web **添加节点**),带节点批准容量。使用一次;在响应 `expires_at` 过期 | 无节点 ID 的 `sandbox-node/configuration`、`sandbox-node/enroll` |
| 节点凭据 | 节点自身:生成 32 至 256 个无空白字符的密钥,在登记时注册 | 带 `X-OAC-Node-ID` 的 `sandbox-node/configuration`、`sandbox-node/identity`、`sandbox-node/connect` |
| 安装授权 | `self_hosted` Session 的 `x_agents_core.installation` 命令;短期有效 | `agent-daemon/installation` 及其 `claim` |
| 执行器凭据 | 安装领取,或 Core 密钥[执行器凭据路由](environment-executor-credentials.md) | `agent-daemon/enroll` 和 `agent-daemon/connection`;登记后也作为绑定设备的 daemon 凭据 |
@@ -50,7 +50,7 @@ OAC_DATABASE_URL=... oac-core-device --tenant --name 'engine host'
oac-daemon connect --profile default
```
-`--tenant` 为 Project 执行租户 UUID,`--url` 为不带路径的 Core origin。命令打印配置一次:`server_url`(origin 加 `/api/v1`)、`runtime_id`(设备 ID)、`runner_credential` 和 `device_name`。使用新配置,不覆盖其他设备文件;私密复制到远程主机相同路径。`oac-core-device --tenant --revoke ` 撤销设备:立即拒绝新连接,已有连接在下一次心跳关闭。Worker 将每个 `none` Session 绑定到其租户内声明所需能力的已连接设备,重试和重启保留绑定;自托管 Session 不使用此路径。
+`--tenant` 为项目执行租户 UUID,`--url` 为不带路径的 Core origin。命令打印配置一次:`server_url`(origin 加 `/api/v1`)、`runtime_id`(设备 ID)、`runner_credential` 和 `device_name`。使用新配置,不覆盖其他设备文件;私密复制到远程主机相同路径。`oac-core-device --tenant --revoke ` 撤销设备:立即拒绝新连接,已有连接在下一次心跳关闭。Worker 将每个 `none` Session 绑定到其租户内声明所需能力的已连接设备,重试和重启保留绑定;自托管 Session 不使用此路径。
## 节点路由 {#node-routes}
@@ -61,7 +61,7 @@ oac-daemon connect --profile default
- 新节点发送登记 token,不带 `X-OAC-Node-ID`。token 必须有效、未过期、未消费且由此安装签发。活动重置拒绝该读取。
- 已注册节点发送节点凭据,并在 `X-OAC-Node-ID` 放其 UUID。无查询时读取当前目标。`?generation=N` 仅读取此节点仍可能需要的代际:当前目标、服务 pin,或其上未释放分配或 placement 持有的代际;其他代际被拒绝。重置期间仍可读取,以恢复已有归属资源。
-响应包含 `installation_id`、`provider`、`core_url`(安装公开 URL)、`generation`、`specification`、`specification_digest`、`max_active` 和 `max_retained`。不包含管理员、Project 或 E2B 凭据,仅适用于节点型提供方。[沙箱部署契约](sandbox-deployment.md#canonical-node-specification)定义 specification 与摘要。
+响应包含 `installation_id`、`provider`、`core_url`(安装公开 URL)、`generation`、`specification`、`specification_digest`、`max_active` 和 `max_retained`。不包含管理员、项目或 E2B 凭据,仅适用于节点型提供商。[沙箱部署契约](sandbox-deployment.md#canonical-node-specification)定义 specification 与摘要。
### 登记节点 {#enroll-a-node}
@@ -72,7 +72,7 @@ oac-daemon connect --profile default
| `node_id` | 节点选定的规范 UUID |
| `credential` | 节点密钥,32 至 256 个无空白字符 |
| `name` | 显示名称 |
-| `provider` | 部署提供方 |
+| `provider` | 部署提供商 |
| `backend_fingerprint` | 节点后端命名空间摘要 |
| `deployment_generation`, `specification_digest` | 节点读取的配置 |
| `core_url` | 节点存储并连接的 Core origin |
@@ -88,7 +88,7 @@ Core 在一个事务中检查 token 有效、部署已初始化且为节点型
| HTTP | 代码 | 时机 |
| --- | --- | --- |
| 400 | `invalid_request_error`, `param: "core_url"` | 登记未提供 `core_url` |
-| 400 | `invalid_request` | 正文、节点 ID 或代际格式错误,或提供方与部署不同 |
+| 400 | `invalid_request` | 正文、节点 ID 或代际格式错误,或提供商与部署不同 |
| 401 | `invalid_node_credential` | token 或节点凭据缺失、无效、过期、已消费或属于其他安装 |
| 409 | `sandbox_specification_mismatch` | 节点代际或摘要不匹配 |
| 409 | `sandbox_node_address_mismatch` | `core_url` 不是安装公开 URL;token 保持未使用 |
diff --git a/contracts/agents-api/zh/message-content.md b/contracts/agents-api/zh/message-content.md
index 6e330bb8f..764a8761b 100644
--- a/contracts/agents-api/zh/message-content.md
+++ b/contracts/agents-api/zh/message-content.md
@@ -1,7 +1,7 @@
---
title: "消息内容"
source: contracts/agents-api/message-content.md
-source_hash: 085ade22b792243b8fea4fb798f1de3cbed872d27752afa4f30b93f251b829a8
+source_hash: 5d0d5ba2710d1a91db22b66054701b863739d54f36d8c62df0b667ad9acb900e
---
用户消息和函数结果共享同一内容模型:由 `input_text` 与 `input_image` 部分组成的有序列表。Core 按发送形式准确存储消息边界、部分顺序和图像引用,并在用户 Item 中原样返回。不下载、转码或修复媒体。Session 创建的 `input` 与 `events.create` 消息共享验证和准入;[Session、事件与历史](sessions-events.md#send-input)定义准入、请求限制和错误。
@@ -62,7 +62,7 @@ source_hash: 085ade22b792243b8fea4fb798f1de3cbed872d27752afa4f30b93f251b829a8
- **Claude Code** 使用实时根原生工具结果确认,要求匹配 Session、调用 ID、成功标志、准确文本、块数和顺序,且每个图像位置都有原生图像。重放、合成和 Subagent 记录不能确认。
- **Codex** 使用实时根 dynamic-tool `item/completed` 观察确认,要求匹配线程、Turn、调用、函数名称、状态、成功标志和准确有序内容。仅写入 Harness 不确认。
-两适配器等待回执最多 10 秒。超时或原生释放且未确认时,应用保持不确定。确认表示 Harness 记录了结果,不表示模型提供方消费了结果。Core 不自动重放结果;提交仍保留用于恢复读取。
+两适配器等待回执最多 10 秒。超时或原生释放且未确认时,应用保持不确定。确认表示 Harness 记录了结果,不表示模型提供商消费了结果。Core 不自动重放结果;提交仍保留用于恢复读取。
## Runtime 边界 {#runtime-boundary}
diff --git a/contracts/agents-api/zh/model-execution.md b/contracts/agents-api/zh/model-execution.md
index 79e50837c..d0e6126ad 100644
--- a/contracts/agents-api/zh/model-execution.md
+++ b/contracts/agents-api/zh/model-execution.md
@@ -20,11 +20,11 @@ source_hash: d26140f4fdaa6d0c68dbeff52a2318ed213799966b224302eb04b9ec718f5fc3
- 创建 Session 时,Core 在处理已保存 Agent 的覆盖值后解析该选择,验证 Harness 配置文件,并将结果存储为 Session 的引擎。当生效的 Agent 包含该扩展时,Session 读取结果会报告它;其他 Session 保持官方 Agent 结构。读取操作从不查询当前 Agent 或部署默认值。
- 使用显式选择器重试创建时会保留调用方意图;在已有 Idempotency-Key 下更改选择器会产生冲突。
-Session 的 `environment` 和 Environment Templates 用于选择准备流程,而不是 Harness 或提供商。该扩展仅在 `contracts/agents-api/v1` 中定义一次;校验器从目录派生,任何处理程序或 schema 都不会维护自己的名称列表。
+Session 的 `environment` 和 Environment 模板用于选择准备流程,而不是 Harness 或提供商。该扩展仅在 `contracts/agents-api/v1` 中定义一次;校验器从目录派生,任何处理程序或 schema 都不会维护自己的名称列表。
## 已保存默认值与优先级 {#saved-defaults-and-precedence}
-已保存 Agent 是可编辑配置,而不是绑定的运行时。创建或更新时,应提供 `model`、可选的 `x_agents_core.harness` 以及可选但完整的 `x_agents_core.model_provider`。响应仅返回安全的提供商字段和只读输出标志 `api_key_configured`,绝不返回 `api_key`、密文或可复用的凭据引用。Agent JSON 仅存储安全视图;密钥配置包拥有自己加密后的数据库行,使用独立的加密用途绑定到 Project 和 Agent,并与 Agent 在同一事务中写入。仅编辑模型时不需要密钥。
+已保存 Agent 是可编辑配置,而不是绑定的运行时。创建或更新时,应提供 `model`、可选的 `x_agents_core.harness` 以及可选但完整的 `x_agents_core.model_provider`。响应仅返回安全的提供商字段和只读输出标志 `api_key_configured`,绝不返回 `api_key`、密文或可复用的凭据引用。Agent JSON 仅存储安全视图;密钥配置包拥有自己加密后的数据库行,使用独立的加密用途绑定到项目和 Agent,并与 Agent 在同一事务中写入。仅编辑模型时不需要密钥。
创建 Session 时,Core 会先解析每个显式的模型或 Harness 覆盖值,再应用已保存默认值;未选择 Harness 时,应用部署默认值。已保存 Agent 必须指定模型。内联 `openai_hosted` 或 `none` Session 可以省略模型,以使用解析后 Harness 的部署模型;`self_hosted` 绝不会使用部署模型设置。Core 绝不会根据模型名称推断模型。
@@ -90,7 +90,7 @@ Core 从同一个数据库快照读取 Agent 配置和加密配置包;显式
不受支持的协议、Harness 或 Environment 组合会在创建 Session 前被拒绝。提供商可用性在执行期间检查,而不是通过探测检查。
-解析后的提供商配置会在 Session 创建事务中被冻结并加密,使用自己的加密用途,并绑定到 Project 和 Session。创建重试会将其纳入请求哈希,因此使用相同 Idempotency-Key 时,更改密钥或端点会产生冲突;密钥进入任何存储哈希时,只会表现为由部署凭据密钥加键控的指纹。任何公开的 Session、Agent、Environment、事件或常规配置均不包含该密钥。顶层扩展仅可写入,无法更新。
+解析后的提供商配置会在 Session 创建事务中被冻结并加密,使用自己的加密用途,并绑定到项目和 Session。创建重试会将其纳入请求哈希,因此使用相同 Idempotency-Key 时,更改密钥或端点会产生冲突;密钥进入任何存储哈希时,只会表现为由部署凭据密钥加键控的指纹。任何公开的 Session、Agent、Environment、事件或常规配置均不包含该密钥。顶层扩展仅可写入,无法更新。
在分派时,Core 会通过绑定到 Session 的 daemon 连接,将快照作为一个机密提供商配置包发送出去;适配器会原生应用该配置并直接连接提供商。快照缺失或无法解密时,Core 绝不会回退到其他凭据。对于 `self_hosted`,接收方 daemon 是为该 Session 自身 Environment 注册的执行器,并持有 Session 创建者主体的当前执行器凭据;凭据轮换或吊销会在继续分派前关闭套接字。执行器主机将该配置包存放在其原生 Harness home 中,与托管 Runtime 的做法相同。原生工具以启动账户的权限运行,并且可以读取该账户有权读取的内容;吊销凭据不会擦除已经交付的配置包。
@@ -102,7 +102,7 @@ Core 从同一个数据库快照读取 Agent 配置和加密配置包;显式
| --- | --- | --- |
| Codex | `model_reasoning_effort`:`none`、`minimal`、`low`、`medium`、`high`、`xhigh` | App-server `-c model_reasoning_effort=...` 以及每个 Turn 的 `collaborationMode.settings.reasoning_effort` |
| Claude SDK | `effort`:`low`、`medium`、`high`、`xhigh`、`max`;`thinking`:SDK 的 `adaptive`、`enabled` 或 `disabled` 对象 | SDK `Options.effort` 和 `Options.thinking` |
-| MiniMax Code | 仅空对象 | 仍必须提供提供商 token 限制 |
+| MiniMax Code | 仅空对象 | 仍必须给出提供商 token 限制 |
对于 `adaptive` 和 `enabled`,Claude `thinking` 接受 `display`(`summarized` 或 `omitted`);只有 `enabled` 接受正整数 `budgetTokens`;拒绝 `maxThinkingTokens`。这些是原生设置,而不是通用推理词汇表;模型可用性和提供商支持均由 Harness 负责。
@@ -125,7 +125,7 @@ PUT 要求提供 `model` 和完整的 `model_provider`;`harness_config` 默认
创建 Session 时,Core 会解密解析后 Harness 的默认值,并像处理其他配置包一样将其冻结在 Session 的加密快照中,因此更改或移除默认值绝不会影响现有 Session。execution-configuration 读取结果会显示冻结的安全视图,其来源为 `deployment`。提供商快照缺失或无效时会安全失败,并且不会回退到其他模型或提供商。
-`model_configuration_support` 派生自 Core 和 Runtime 共享的适配器声明:`protocols` 列出可选择的原生协议,并将默认项放在首位;`accepts_harness_config` 表示是否接受原生参数;`token_limits_required` 表示是否必须提供提供商 token 限制。它描述的是构建版本,而不是实时 Runtime 或远程模型。
+`model_configuration_support` 派生自 Core 和 Runtime 共享的适配器声明:`protocols` 列出可选择的原生协议,并将默认项放在首位;`accepts_harness_config` 表示是否接受原生参数;`token_limits_required` 表示是否必须给出提供商 token 限制。它描述的是构建版本,而不是实时 Runtime 或远程模型。
### 部署默认值观测 {#deployment-default-observations}
diff --git a/contracts/agents-api/zh/node-generation-protocol.md b/contracts/agents-api/zh/node-generation-protocol.md
index b035ab7ab..0b4e9c6bf 100644
--- a/contracts/agents-api/zh/node-generation-protocol.md
+++ b/contracts/agents-api/zh/node-generation-protocol.md
@@ -4,7 +4,7 @@ source: contracts/agents-api/node-generation-protocol.md
source_hash: fb446e91c3df3c9e397e5e9abb794245b0ae11d81176879207718680e8ab4173
---
-沙箱节点在其主机上运行 Docker 或 microsandbox Provider,并通过一个 WebSocket 与 Core 相连。Core 通过该连接发送 Provider 操作;节点针对本地 Provider 执行这些操作,并报告就绪状态、主机测量值及其持有的部署代次。Core 始终是唯一的生命周期所有者:节点绝不重试变更操作或调度工作。帧和校验器位于 [`services/core/internal/sandbox/node`](https://github.com/MiniMax-AI/OpenAgentCore/tree/main/services/core/internal/sandbox/node)(`wire.go`、`generation_wire.go`);节点用于注册和读取配置的 HTTP 路由位于[机器连接 API](machine-api.md#node-routes)。
+沙箱节点在其主机上运行 Docker 或 microsandbox 提供商,并通过一个 WebSocket 与 Core 相连。Core 通过该连接发送提供商操作;节点针对本地提供商执行这些操作,并报告就绪状态、主机测量值及其持有的部署代次。Core 始终是唯一的生命周期所有者:节点绝不重试变更操作或调度工作。帧和校验器位于 [`services/core/internal/sandbox/node`](https://github.com/MiniMax-AI/OpenAgentCore/tree/main/services/core/internal/sandbox/node)(`wire.go`、`generation_wire.go`);节点用于注册和读取配置的 HTTP 路由位于[机器连接 API](machine-api.md#node-routes)。
## 帧与版本 {#frames-and-version}
@@ -17,11 +17,11 @@ source_hash: fb446e91c3df3c9e397e5e9abb794245b0ae11d81176879207718680e8ab4173
3. Core 记录节点的存在状态,然后回复 `welcome`,其中包含新的 `connection_id` 和当前 `owner_epoch`;对于支持代次管理的节点,还包含 `deployment`:目标 `generation`、其 `specification_digest` 和可空的 `serving_generation`。节点保存更高的所有者 epoch,并拒绝更低的值。
4. 节点每 10 秒发送一次 `heartbeat`,其中包含 `connection_id`、`owner_epoch` 和健康状态。对于每次心跳,Core 都会再次认证节点凭据并检查所有者 epoch,记录健康状态并回复 `heartbeat_ack`;对于支持代次管理的节点,回复中还包含 `deployment`。任一端连续 35 秒未收到任何帧时都会关闭连接。
-只要节点在当前所有者 epoch 下保持连接,并且最近一次心跳距今不足 45 秒,Core 就会将该节点计为在线。心跳会确立 Provider 的就绪状态和最近的主机测量值,但绝不表示 Session 活动。
+只要节点在当前所有者 epoch 下保持连接,并且最近一次心跳距今不足 45 秒,Core 就会将该节点计为在线。心跳会确立提供商的就绪状态和最近的主机测量值,但绝不表示 Session 活动。
-健康报告包含 `provider_ready`、可选的固定 `diagnostic`、`observed_at`、最多为 32 的 `active_operations`,以及 [Runtime 遥测 API](runtime-observability-api.md#node-host-observations-and-history) 报告的主机测量值。未启用代次管理的节点每次报告时都会探测其 Provider;未就绪的 Provider 会报告其首个失败检查所属的、与 Provider 无关的就绪类别,该类别取自探测所包装的类别错误;探测文本、厂商细节和主机路径保留在节点上。节点或代次健康状态中的 `diagnostic` 若不是已声明的类别,该帧即无效。[节点指南](../../../docs/zh/getting-started/nodes.md#readiness-codes) 列出了这些类别及其原因。支持代次管理的节点则按下文所述按代次报告就绪状态。
+健康报告包含 `provider_ready`、可选的固定 `diagnostic`、`observed_at`、最多为 32 的 `active_operations`,以及 [Runtime 遥测 API](runtime-observability-api.md#node-host-observations-and-history) 报告的主机测量值。未启用代次管理的节点每次报告时都会探测其提供商;未就绪的提供商会报告其首个失败检查所属的、与提供商无关的就绪类别,该类别取自探测所包装的类别错误;探测文本、厂商细节和主机路径保留在节点上。节点或代次健康状态中的 `diagnostic` 若不是已声明的类别,该帧即无效。[节点指南](../../../docs/zh/getting-started/nodes.md#readiness-codes) 列出了这些类别及其原因。支持代次管理的节点则按下文所述按代次报告就绪状态。
-## Provider 请求 {#provider-requests}
+## 提供商请求 {#provider-requests}
Core 发送包含以下内容的 `request` 帧:
@@ -37,7 +37,7 @@ Core 发送包含以下内容的 `request` 帧:
每个操作都携带自己的参数,并在成功时返回以下结果:
-| `operation` | Provider 方法 | 参数 | 成功结果 |
+| `operation` | 提供商方法 | 参数 | 成功结果 |
| --- | --- | --- | --- |
| `create` | `Create` | `bootstrap` | `info` |
| `info` | `GetInfo` | 无 | `info` |
@@ -55,7 +55,7 @@ Core 发送包含以下内容的 `request` 帧:
| `resume` | `Resume` | `resume` | `state` |
| `delete_snapshot` | `DeleteSnapshot` | `snapshot` | 无 |
-只要 `connection_id`、`owner_epoch` 或 `sequence` 中任一值不匹配,请求就会关闭连接。格式错误的请求会得到 `invalid` 响应。未启用代次管理的节点仅接受其登记的 `deployment_generation`;支持代次管理的节点在对应代次的 Provider 上运行请求,无法运行时回复 `unconfirmed`。Core 仅向节点上已就绪的代次发送 `create` 和非 observe-only 的 `resume`,并且每条连接最多保留 32 个待处理请求。
+只要 `connection_id`、`owner_epoch` 或 `sequence` 中任一值不匹配,请求就会关闭连接。格式错误的请求会得到 `invalid` 响应。未启用代次管理的节点仅接受其登记的 `deployment_generation`;支持代次管理的节点在对应代次的提供商上运行请求,无法运行时回复 `unconfirmed`。Core 仅向节点上已就绪的代次发送 `create` 和非 observe-only 的 `resume`,并且每条连接最多保留 32 个待处理请求。
预算采用相对计时:节点收到请求时以自己的时钟为基准锚定 `timeout_ms`,并在请求排队等待期间持续消耗该预算,因此各主机的时钟无需保持一致。Core 仍会限制自身等待时长。节点队列已满时会关闭连接。
@@ -69,27 +69,27 @@ Core 发送包含以下内容的 `request` 帧:
| `unsupported` | 该操作被声明为不支持;见下文 |
| `unconfirmed` 或任何其他值 | 结果未知 |
-失败响应不携带结果,唯一的例外是作为精确引用 `CreateSettled` 回执的 `info` 结果:即便已确认的原生 Create 在后续检查中失败,仍可证明该尝试已有确定结果。超时、响应丢失或断连属于不可用或不确定情况,绝不能证明资源不存在;发生这些情况后,Core 绝不重放变更操作,而是改为观察原始操作。[Sandbox Provider 指南](../../../docs/zh/sandbox-provider.md#operation-outcomes-and-retries) 定义了每种结果。
+失败响应不携带结果,唯一的例外是作为精确引用 `CreateSettled` 回执的 `info` 结果:即便已确认的原生 Create 在后续检查中失败,仍可证明该尝试已有确定结果。超时、响应丢失或断连属于不可用或不确定情况,绝不能证明资源不存在;发生这些情况后,Core 绝不重放变更操作,而是改为观察原始操作。[沙箱提供商指南](../../../docs/zh/sandbox-provider.md#operation-outcomes-and-retries) 定义了每种结果。
-节点启动和代次加载会在接受工作前验证完整的 Provider 操作声明,Core 代理使用同一份已注册声明,因此不支持的操作会在节点解析或原生 I/O 之前被拒绝。操作清单由[操作契约](../../../docs/zh/sandbox-provider.md#explicit-operation-contracts)维护。`unsupported` 响应包含一个 `unsupported` 对象,其中有精确的方法 `operation` 和经作者编写且安全的 `reason`;代理会将两者与请求进行核对。证据缺失、格式错误或不匹配会得到 `unconfirmed` 结果,而绝不会证明变更操作被拒绝。`unsupported` 始终不同于观察不可用,也不同于计算或命令结果未知;它既不确定资源所有权,也不授权重放。
+节点启动和代次加载会在接受工作前验证完整的提供商操作声明,Core 代理使用同一份已注册声明,因此不支持的操作会在节点解析或原生 I/O 之前被拒绝。操作清单由[操作契约](../../../docs/zh/sandbox-provider.md#explicit-operation-contracts)维护。`unsupported` 响应包含一个 `unsupported` 对象,其中有精确的方法 `operation` 和经作者编写且安全的 `reason`;代理会将两者与请求进行核对。证据缺失、格式错误或不匹配会得到 `unconfirmed` 结果,而绝不会证明变更操作被拒绝。`unsupported` 始终不同于观察不可用,也不同于计算或命令结果未知;它既不确定资源所有权,也不授权重放。
## 代次控制 {#generation-control}
-未启用代次管理的节点只服务其登记的代次,配置固定,并且不会收到准备或保留帧。它可以在 `Health.Generations` 报告该精确代次;支持检查点的 Provider 必须报告,并包含已验证的检查点资格。`provider_ready` 必须与报告的状态一致。支持代次管理的节点会准备 Core 在 `welcome` 和 `heartbeat_ack` 中通告的目标代次,并在此期间继续服务其持久化的服务代次;目标代次的准备独立于服务 Provider 的就绪状态。
+未启用代次管理的节点只服务其登记的代次,配置固定,并且不会收到准备或保留帧。它可以在 `Health.Generations` 报告该精确代次;支持检查点的提供商必须报告,并包含已验证的检查点资格。`provider_ready` 必须与报告的状态一致。支持代次管理的节点会准备 Core 在 `welcome` 和 `heartbeat_ack` 中通告的目标代次,并在此期间继续服务其持久化的服务代次;目标代次的准备独立于服务提供商的就绪状态。
-节点的 `hello` 和心跳最多携带八条代次观察记录。每条记录指定一个正值的有符号 64 位代次编号、其小写 SHA-256 规范摘要、`ready`、`preparing` 或 `failed` 状态,以及可选的固定诊断信息。目标代次和服务代次的记录排在前面,其余记录公平轮换。八条记录限制的是单条消息,而不是节点可保留的代次数量。省略某条观察记录绝不会授权删除,也不会暗示不存在。 支持检查点的 ready 代次携带 `checkpoint`,包含非空且不透明的 `artifact_domain` 和 `execution_class` token,各最多 256 字节。不支持的 Provider 省略该字段;preparing 或 failed 代次不声明它。Core 将声明与已认证连接和代次一起持久化,仅在当前在线连接的该代次仍 ready 时使用。[Provider 契约](../../../docs/zh/sandbox-provider.md#checkpoint-transfer) 定义归档与执行兼容性。
+节点的 `hello` 和心跳最多携带八条代次观察记录。每条记录指定一个正值的有符号 64 位代次编号、其小写 SHA-256 规范摘要、`ready`、`preparing` 或 `failed` 状态,以及可选的固定诊断信息。目标代次和服务代次的记录排在前面,其余记录公平轮换。八条记录限制的是单条消息,而不是节点可保留的代次数量。省略某条观察记录绝不会授权删除,也不会暗示不存在。 支持检查点的 ready 代次携带 `checkpoint`,包含非空且不透明的 `artifact_domain` 和 `execution_class` token,各最多 256 字节。不支持的提供商省略该字段;preparing 或 failed 代次不声明它。Core 将声明与已认证连接和代次一起持久化,仅在当前在线连接的该代次仍 ready 时使用。[提供商契约](../../../docs/zh/sandbox-provider.md#checkpoint-transfer) 定义归档与执行兼容性。
-保留使用独立且有界的交换。`retention` 请求最多指定八个本地 `(generation, specification_digest)` 引用、一个 UUID、一个每次递增 1 的 `sequence`、当前 `connection_id` 和所有者 epoch。`retention_ack` 必须与完整的待处理请求匹配,包括条目顺序和身份信息,并为每个条目给出显式布尔值 `keep`。每条连接只能有一个交换处于待处理状态,断连会将其丢弃。任何未经请求、重放、过期、不完整或混合的确认都不会删除任何内容。保留流量从不使用 Provider 请求队列。
+保留使用独立且有界的交换。`retention` 请求最多指定八个本地 `(generation, specification_digest)` 引用、一个 UUID、一个每次递增 1 的 `sequence`、当前 `connection_id` 和所有者 epoch。`retention_ack` 必须与完整的待处理请求匹配,包括条目顺序和身份信息,并为每个条目给出显式布尔值 `keep`。每条连接只能有一个交换处于待处理状态,断连会将其丢弃。任何未经请求、重放、过期、不完整或混合的确认都不会删除任何内容。保留流量从不使用提供商请求队列。
## 本地保留与辅助程序生命周期 {#local-retention-and-helper-lifetime}
-Core 的丢弃授权是回收的必要条件,但并非充分条件。排队和运行中的 Provider 调用、准备过程、本地目标代次以及服务固定引用都会保留引用;回收会再次检查这些引用,并拒绝在已取消的连接上执行。取消 Provider 调用方并不能证明其原生辅助程序已经停止;节点会将该辅助程序计为存活,直到其实际 `Wait` 返回。
+Core 的丢弃授权是回收的必要条件,但并非充分条件。排队和运行中的提供商调用、准备过程、本地目标代次以及服务固定引用都会保留引用;回收会再次检查这些引用,并拒绝在已取消的连接上执行。取消提供商调用方并不能证明其原生辅助程序已经停止;节点会将该辅助程序计为存活,直到其实际 `Wait` 返回。
-每个代次都拥有一个永久私有租约文件 `state/node/generations/.lease`。在启动原生辅助程序之前,节点先在该文件上获取共享 flock,在持有该锁时验证持久化租约身份,并要求最终 Provider 配置已经发布且不存在 preparing、collecting 或 dropped 日志。辅助程序继承该描述符;节点仅在 `Wait` 返回后关闭自己的副本,且绝不显式解锁该共享打开文件描述,因此取消调用方或节点退出都不会释放仍在运行的辅助程序所持的引用。原生辅助程序在调用 SDK 前会设置描述符的 close-on-exec 标志,因此 VM 和守护进程后代不会继承它。
+每个代次都拥有一个永久私有租约文件 `state/node/generations/.lease`。在启动原生辅助程序之前,节点先在该文件上获取共享 flock,在持有该锁时验证持久化租约身份,并要求最终提供商配置已经发布且不存在 preparing、collecting 或 dropped 日志。辅助程序继承该描述符;节点仅在 `Wait` 返回后关闭自己的副本,且绝不显式解锁该共享打开文件描述,因此取消调用方或节点退出都不会释放仍在运行的辅助程序所持的引用。原生辅助程序在调用 SDK 前会设置描述符的 close-on-exec 标志,因此 VM 和守护进程后代不会继承它。
回收在检查引用、删除共享镜像或版本文件或发布 dropped 标记之前,先获取独占非阻塞 flock,并在这些变更期间持续持有该锁。租约文件属于稳定的节点状态,回收期间绝不删除或替换;符号链接、多重硬链接文件、外来所有权、不安全权限以及被替换的锁定路径都会被拒绝。在第一个辅助程序能够启动之前,安装器先独占创建租约并对其执行 fsync,随后以原子方式持久化私有 `.lease-identity` 记录,并对该记录及其目录执行 fsync。该记录绑定安装、代次、规范摘要、设备号和 inode。Python 回收器和 Go 辅助程序打开器在每次打开时都会验证同一记录,包括重启后;身份记录缺失时,两者都不会进行接管,也不会替换其 inode 或在回收后将其擦除。若安装在身份记录持久化前中断,则会拒绝重新接管,并保留该安装以供检查。身份记录被移除或租约被替换时,即使当前元数据一致,也会拒绝重新接管。
-已丢弃代次绝不能再次准备或使用。辅助程序退出只能证明本地文件方面的状态,不能证明远程变更操作或结果不确定的 Provider 回执已释放;Core 对分配和放置的持久保留仍保持独立。
+已丢弃代次绝不能再次准备或使用。辅助程序退出只能证明本地文件方面的状态,不能证明远程变更操作或结果不确定的提供商回执已释放;Core 对分配和放置的持久保留仍保持独立。
## 完全匹配的新安装 {#matched-fresh-installation}
@@ -101,28 +101,28 @@ Core 的丢弃授权是回收的必要条件,但并非充分条件。排队和
## 重启恢复 {#restart-recovery}
-Runtime 字节缺失时,绝不将固定的放置实例迁移到当前 Runtime。节点将原始代次和规范摘要保留为未就绪状态,并在恢复前通过 Core 的经认证配置路由请求该精确代次。缺少 seccomp 字节可能留下未就绪的 Provider 占位项;Provider 探测发现镜像或原生制品缺失时,会将修复排队,但不会通告就绪状态。
+Runtime 字节缺失时,绝不将固定的放置实例迁移到当前 Runtime。节点将原始代次和规范摘要保留为未就绪状态,并在恢复前通过 Core 的经认证配置路由请求该精确代次。缺少 seccomp 字节可能留下未就绪的提供商占位项;提供商探测发现镜像或原生制品缺失时,会将修复排队,但不会通告就绪状态。
-准备和修复串行执行。目标代次和服务代次优先,其余代次则以有界方式推进。每次尝试的截止时间为 30 分钟;失败后依次退避 1、2、5 和 10 分钟,此后最多退避 30 分钟。在连接提供部署信息之前,不准备任何内容。修复保留现有配置和路径,验证所选版本及每个现有同级文件的校验和,并且只下载缺失的不可变文件。字节冲突或保留规范不同都会拒绝修复;如果缺少 Provider 配置且没有精确的准备计划,也会拒绝,而不是重建该配置。
+准备和修复串行执行。目标代次和服务代次优先,其余代次则以有界方式推进。每次尝试的截止时间为 30 分钟;失败后依次退避 1、2、5 和 10 分钟,此后最多退避 30 分钟。在连接提供部署信息之前,不准备任何内容。修复保留现有配置和路径,验证所选版本及每个现有同级文件的校验和,并且只下载缺失的不可变文件。字节冲突或保留规范不同都会拒绝修复;如果缺少提供商配置且没有精确的准备计划,也会拒绝,而不是重建该配置。
-修复与回收使用相同的独占代次租约和安装锁,因此正在运行的辅助程序或回收器会保持所有权,修复稍后重试。字节恢复后,节点仍会运行 Provider 的就绪探测;文件存在和具备可执行能力永远不能证明就绪。
+修复与回收使用相同的独占代次租约和安装锁,因此正在运行的辅助程序或回收器会保持所有权,修复稍后重试。字节恢复后,节点仍会运行提供商的就绪探测;文件存在和具备可执行能力永远不能证明就绪。
## 准备与回收记录 {#preparation-and-collection-records}
-新的准备过程会写入两条不同的记录。下载前,`.preparing` 保存安装、代次和规范身份、私有 Provider 路径以及 `import_started: false`;它是恢复和回收计划,而不是 Provider。导入器运行前,计划会记录 `import_started: true`。Python 保留发现流程和 Go 重启恢复流程都能识别仅有待处理状态的计划,但绝不会据此构建、探测或获取 Provider;恢复或回收仍需要当前连接上的授权。
+新的准备过程会写入两条不同的记录。下载前,`.preparing` 保存安装、代次和规范身份、私有提供商路径以及 `import_started: false`;它是恢复和回收计划,而不是提供商。导入器运行前,计划会记录 `import_started: true`。Python 保留发现流程和 Go 重启恢复流程都能识别仅有待处理状态的计划,但绝不会据此构建、探测或获取提供商;恢复或回收仍需要当前连接上的授权。
-只有准备成功才会发布最终 `.json` Provider 配置,该配置只写入一次。Docker 记录其解析器返回的不可变本地镜像 ID;对于同一规范,构建器的配置身份或清单身份均可有效。准备日志清除之前,发布结果必须已经持久化。两者之间发生中断时,会重新验证同一计划和最终身份;计划、规范或路径发生漂移时会拒绝。已取消或失败的导入仍会向 Core 的保留交换保持可见,但不会成为服务代次。
+只有准备成功才会发布最终 `.json` 提供商配置,该配置只写入一次。Docker 记录其解析器返回的不可变本地镜像 ID;对于同一规范,构建器的配置身份或清单身份均可有效。准备日志清除之前,发布结果必须已经持久化。两者之间发生中断时,会重新验证同一计划和最终身份;计划、规范或路径发生漂移时会拒绝。已取消或失败的导入仍会向 Core 的保留交换保持可见,但不会成为服务代次。
在删除任何原生层对象或版本文件之前,节点都会持久化一份私有回收日志,并将其绑定到安装、代次和规范摘要。重启后,未完成的日志仅是保留交换的候选项:它不能准备、探测、获取或通告该代次,必须重新获取一份与之关联的新 Core 丢弃授权后才能继续。在删除版本文件之前先持久化原生清理完成状态,因此重试可以完成部分删除的版本,而不会运行已经删除的辅助程序。完成持久化文件清理后,再写入与摘要绑定的 dropped 标记,以防重新接管;这些小型的配置和所有权日志会保留为本地身份记录。
对于仅属于该安装的 microsandbox 存储,成功且完整的原生镜像清单可以区分“不存在”和“CLI 失败”;查询失败、清单格式错误、原生层因正在使用而拒绝或所有权不明时,都会保留这些字节。共享 microsandbox 镜像和私有版本会一直保留到最后一个本地引用消失。Docker 镜像属于主机的共享守护进程:自动回收绝不删除或修剪这些镜像,只有主机管理员在确认主机上没有安装需要它们后才能删除。
-全新安装还会另行记录其 Runtime 文件的已验证校验和,与主机程序分开保存。回收原始代次时,只删除未被任何保留配置引用的确切私有 Runtime 辅助程序、可执行文件、固件、seccomp 和导入缓存文件。第一次删除前会检查每个剩余文件;哈希未知、字节发生变化、存在链接或缺少所有权元数据时,都会拒绝清理。节点可执行文件、准备器、身份、基础 Provider 配置和清单会保留,因此重启后的节点仍可读取其登记身份并构建较新的保留 Provider。删除共享原生路径前,会先在所有保留配置之间对这些路径进行比较。
+全新安装还会另行记录其 Runtime 文件的已验证校验和,与主机程序分开保存。回收原始代次时,只删除未被任何保留配置引用的确切私有 Runtime 辅助程序、可执行文件、固件、seccomp 和导入缓存文件。第一次删除前会检查每个剩余文件;哈希未知、字节发生变化、存在链接或缺少所有权元数据时,都会拒绝清理。节点可执行文件、准备器、身份、基础提供商配置和清单会保留,因此重启后的节点仍可读取其登记身份并构建较新的保留提供商。删除共享原生路径前,会先在所有保留配置之间对这些路径进行比较。
下载中断后,只会修复原始路径中缺失的字节。如果在任何导入尝试之前执行回收,准备日志会证明该代次没有已导入的原生镜像。如果某代次的原生可执行文件缺失,且导入可能已经开始,该代次仍会保留:文件缺失永远不能证明原生制品不存在,而空的原生清单也永远不能抹除回执或存储历史。
就绪类别编写于 `services/core/internal/sandbox/node_diagnostic.go`,每个类别对应一个导出错误和一个代码。共享的 `services/core/internal/sandbox/testdata/node-diagnostics.json` 测试夹具检查 Go 映射、OpenAPI 源注释和生成的枚举,以及 TypeScript 客户端声明。Web 使用客户端规范化器,并检查每个已声明代码的本地化消息。代码变更时要同步更新这些投影;客户端将未知代码读作 `provider_unavailable`。
-准备诊断使用固定的类型化原因。只有制品传输、校验和或版本来源验证失败才会报告 `runtime_download_failed`;私有准备器通过退出类别指示这一类失败,Core 和节点都不解析 stderr。Provider 故障、所有权故障、取消和未分类故障保留其类型化代码,或使用 `provider_unavailable`。协议中不会传输任何 Provider 原始文本。
+准备诊断使用固定的类型化原因。只有制品传输、校验和或版本来源验证失败才会报告 `runtime_download_failed`;私有准备器通过退出类别指示这一类失败,Core 和节点都不解析 stderr。提供商故障、所有权故障、取消和未分类故障保留其类型化代码,或使用 `provider_unavailable`。协议中不会传输任何提供商原始文本。
当前线协议版本为 5。Create 引导和 Resume 请求可携带可选的工作区文件系统绑定。节点在转发前校验其租户及 Environment 与分配引用一致、ObjectID 不可变且有效,以及挂载配置 ID 与所传配置一致。文件系统解析器负责适配器原生所有权校验。未提供绑定时选择自有存储;已提供绑定时不得回退。错误响应仅可保留原生 ID 非空且名称、代次、快照来源均匹配请求的 Resume 目标;这仅为清理证据,不代表恢复成功。
diff --git a/contracts/agents-api/zh/runtime-observability-api.md b/contracts/agents-api/zh/runtime-observability-api.md
index 89ce44997..23040c051 100644
--- a/contracts/agents-api/zh/runtime-observability-api.md
+++ b/contracts/agents-api/zh/runtime-observability-api.md
@@ -6,11 +6,11 @@ source_hash: 4a9c00d1eed9fe51f9e8f2f08e00f1709ddc55eb1c650ed3a5380f44a5b71e1c
Core 通过 `/core/v1` 下的只读管理员路由报告托管 Runtime 和沙箱节点所使用的信息:当前 Runtime 观测值、单个 Session 的已存储 Runtime 历史记录,以及沙箱节点的主机观测值和历史记录。读取操作绝不创建、唤醒、续期或更改计算资源,也绝不向历史记录添加样本。[Runtime observability](runtime-observability.md) 定义了 Core 如何采集和保留这些值;[Console API usage](../../../docs/zh/web/console-api-usage.md) 列出了读取这些值的 Web 页面。
-每个路由都要求以 Core 密钥作为 Bearer 凭证;缺少或无效的密钥会返回 401 `invalid_admin_key`。路径中的 Project ID 用于选择目标 Project,不承担身份验证作用。响应带有 `Cache-Control: no-store`,采用 Core 错误封装格式,且绝不包含提供方响应、原生标识符、路径或凭证。
+每个路由都要求以 Core 密钥作为 Bearer 凭据;缺少或无效的密钥会返回 401 `invalid_admin_key`。路径中的项目 ID 用于选择目标项目,不承担身份验证作用。响应带有 `Cache-Control: no-store`,采用 Core 错误封装格式,且绝不包含提供商响应、原生标识符、路径或凭据。
## 当前 Runtime 观测值 {#current-runtime-observations}
-### 列出所有 Project 的观测值 {#list-observations-of-every-project}
+### 列出所有项目的观测值 {#list-observations-of-every-project}
```http
GET /core/v1/sandbox/runtime-observations?after={session_id}&limit=20&order=desc
@@ -23,7 +23,7 @@ Authorization: Bearer
| `limit` | 1 到 100,默认 20。 |
| `order` | 按 Session 创建时间采用 `asc` 或 `desc`,默认 `desc`。 |
-列表中,每个未删除 Project 下的每个 Session 都有一行,包括模式为 `none`、`self_hosted` 的 Session 以及已释放的托管 Session。每行都包含所属 `project_id` 和一个 `observation`:[`RuntimeObservation`](#runtimeobservation) 与 [`disk`](#disk)。分页采用 Session 列表的创建时间与 ID 键集。观测 ID 就是 Session ID,因此即使 Session 背后的 Runtime 发生变化,分页边界也不会移动。页面不是原子快照:每行都有自己的 `resolved_at`,并在进行了采样时拥有 `observed_at`。未知的查询键会被忽略。
+列表中,每个未删除项目下的每个 Session 都有一行,包括模式为 `none`、`self_hosted` 的 Session 以及已释放的托管 Session。每行都包含所属 `project_id` 和一个 `observation`:[`RuntimeObservation`](#runtimeobservation) 与 [`disk`](#disk)。分页采用 Session 列表的创建时间与 ID 键集。观测 ID 就是 Session ID,因此即使 Session 背后的 Runtime 发生变化,分页边界也不会移动。页面不是原子快照:每行都有自己的 `resolved_at`,并在进行了采样时拥有 `observed_at`。未知的查询键会被忽略。
```json
{
@@ -89,14 +89,14 @@ Authorization: Bearer
| `session_id` | string | 对应的 Session。 |
| `environment_id` | string 或 null | 仅当 mode 为 `none` 时为 null。 |
| `mode` | enum | `none`、`self_hosted` 或 `openai_hosted`。 |
-| `provider_type` | string 或 null | 来源类型,例如 `docker`、`microsandbox` 或 `e2b`;未读取任何提供方数据时为 null。未知值应视为新类型,而不是错误。 |
+| `provider_type` | string 或 null | 来源类型,例如 `docker`、`microsandbox` 或 `e2b`;未读取任何提供商数据时为 null。未知值应视为新类型,而不是错误。 |
| `instance` | object | 当前计算资源标识;请参阅 [`RuntimeInstance`](#runtimeinstance)。 |
| `lifecycle_state` | enum 或 null | Core 自身对托管分配的生命周期视图;对于 `none` 和 `self_hosted` 为 null。请参阅下文。 |
| `status` | enum | `observed`、`unsupported` 或 `unavailable`。 |
| `reason` | enum 或 null | 该行没有样本的原因;请参阅 [Status and reason](#status-and-reason)。 |
| `allocation_created_at` | integer 或 null | 创建托管分配时的 Unix 秒数。 |
| `resolved_at` | integer | Core 解析此行时的 Unix 秒数。 |
-| `observed_at` | integer 或 null | 提供方样本的 Unix 秒数;无样本时为 null。 |
+| `observed_at` | integer 或 null | 提供商样本的 Unix 秒数;无样本时为 null。 |
| `started_at` | integer 或 null | 当前计算实例代次启动时的 Unix 秒数。 |
| `cpu` | object 或 null | 未观测到 CPU 值时为 null。 |
| `memory` | object 或 null | 未观测到内存值时为 null。 |
@@ -129,7 +129,7 @@ Authorization: Bearer
| `usage_seconds_total` | 当前计算实例代次的累计 CPU 秒数(Docker、microsandbox)。 |
| `capacity_cores` | 已配置的 CPU 容量,大于零。 |
| `usage_cores` | 始终为 null。 |
-| `utilization_ratio` | 提供方报告的 `capacity_cores` 占比(E2B),不进行钳制;对于报告累计 CPU 时间的提供方为 null。 |
+| `utilization_ratio` | 提供商报告的 `capacity_cores` 占比(E2B),不进行钳制;对于报告累计 CPU 时间的提供商为 null。 |
### `memory` {#memory}
@@ -143,14 +143,14 @@ Authorization: Bearer
| 状态 | 原因 | 适用情况 |
| --- | --- | --- |
-| `observed` | null | 提供方返回了样本。 |
+| `observed` | null | 提供商返回了样本。 |
| `unsupported` | `runtime_mode_not_observable` | `none` 和 `self_hosted` Session。 |
| `unavailable` | `allocation_pending` | 托管分配尚不存在或正在创建。 |
-| `unavailable` | `runtime_not_running` | 分配正在清理或已释放,或者提供方报告 Runtime 不存在、已停止或已暂停。 |
-| `unavailable` | `sample_timeout` | 提供方读取超过其截止时间。 |
-| `unavailable` | `sample_unavailable` | 提供方无法生成当前样本。 |
+| `unavailable` | `runtime_not_running` | 分配正在清理或已释放,或者提供商报告 Runtime 不存在、已停止或已暂停。 |
+| `unavailable` | `sample_timeout` | 提供商读取超过其截止时间。 |
+| `unavailable` | `sample_unavailable` | 提供商无法生成当前样本。 |
-所有权不匹配、格式错误的持久身份或无效的提供方证据会使请求失败,而不会转换为 `unavailable` 行。生成的 `core.openapi.yaml` 会记录每个字段的类型、可空性和枚举,但无法表达 status、mode 与字段之间哪些组合有效;上表和上述字段规则具有规范效力。
+所有权不匹配、格式错误的持久身份或无效的提供商证据会使请求失败,而不会转换为 `unavailable` 行。生成的 `core.openapi.yaml` 会记录每个字段的类型、可空性和枚举,但无法表达 status、mode 与字段之间哪些组合有效;上表和上述字段规则具有规范效力。
### 错误 {#errors}
@@ -158,8 +158,8 @@ Authorization: Bearer
| --- | --- | --- |
| 400 | `invalid_request_error` | 列表:重复提供 `after`、`limit` 或 `order`,或者 `limit` 或 `order` 无效。 |
| 400 | `unsupported_parameter` | 单项读取:提供任何查询参数。 |
-| 404 | `not_found_error` | Project 不存在;Session 或列表游标不存在、格式错误或属于其他 Project。 |
-| 500 | `internal_error` | 标识不一致或提供方证据无效。 |
+| 404 | `not_found_error` | 项目不存在;Session 或列表游标不存在、格式错误或属于其他项目。 |
+| 500 | `internal_error` | 标识不一致或提供商证据无效。 |
| 503 | `execution_unavailable` | 列表读取超过其采集预算。 |
### 客户端 {#client}
@@ -175,7 +175,7 @@ Authorization: Bearer
`range` 可以是 `1h`(默认值)、`6h` 或 `24h`,并且是唯一的参数。请求不携带任何时间:Core 按自己的时钟,将范围的结束点定在最近一个桶边界上,桶边界从 Unix 纪元起按整桶计算。因此调用方的时钟无法使读取被拒绝或发生偏移,同一个桶内的多次读取会得到相同的范围。`requested_range` 以 Unix 秒报告该范围;`start` 包含在内,`end` 不包含在内。桶宽是范围除以 120,向上取整为整数秒,并取 30 秒或采样间隔中的较长者作为最小值。桶从 `requested_range.start` 开始;最后一个桶在 `requested_range.end` 结束。
-Core 先解析 Project,然后解析 Session 及其 Environment,之后才读取存储;分配和提供方标识都是结果,绝不能作为查询输入。只有 `openai_hosted` Session 存在历史记录。
+Core 先解析项目,然后解析 Session 及其 Environment,之后才读取存储;分配和提供商标识都是结果,绝不能作为查询输入。只有 `openai_hosted` Session 存在历史记录。
```json
{
@@ -206,7 +206,7 @@ Core 先解析 Project,然后解析 Session 及其 Environment,之后才读
### 数据系列 {#series}
-每个托管分配都有一条以 `allocation_id` 为键的 series,因此,即使提供方在同一分配下暂停、恢复或替换计算资源,也只会保留一条 series。`environment_id` 和 `provider_type` 用于标识其来源。`started_at` 是该分配的计算资源在保留范围内最早的 start,以 JSON 安全的 `{seconds, nanoseconds}` 表示,其中纳秒值为 0 到 999,999,999;它不是各个桶的开始时间,而且计算运行时长只能来自当前观测值。
+每个托管分配都有一条以 `allocation_id` 为键的 series,因此,即使提供商在同一分配下暂停、恢复或替换计算资源,也只会保留一条 series。`environment_id` 和 `provider_type` 用于标识其来源。`started_at` 是该分配的计算资源在保留范围内最早的 start,以 JSON 安全的 `{seconds, nanoseconds}` 表示,其中纳秒值为 0 到 999,999,999;它不是各个桶的开始时间,而且计算运行时长只能来自当前观测值。
每个点都包含该桶的边界、该分配样本的覆盖范围计数,以及可空的 `cpu` 和 `memory` 对象;其 `contributor_count` 至少为 1:
@@ -224,7 +224,7 @@ Core 先解析 Project,然后解析 Session 及其 Environment,之后才读
| HTTP | 代码 | 适用情况 |
| --- | --- | --- |
| 400 | `invalid_request` | 提供了 `range` 以外的参数、重复的 `range`,或 `range` 不是 `1h`、`6h` 或 `24h`。 |
-| 404 | `not_found_error` | Project 不存在,或 Session 不属于该 Project。 |
+| 404 | `not_found_error` | 项目不存在,或 Session 不属于该项目。 |
| 409 | `runtime_history_unsupported` | Session 不是 `openai_hosted`。 |
| 500 | `internal_error` | 已存储的标识不一致。 |
| 503 | `runtime_history_unavailable` | 读取失败、超时或产生了超出界限的结果。 |
@@ -273,7 +273,7 @@ Authorization: Bearer
- `total_memory_bytes` 和 `available_memory_bytes` 分别对应 `MemTotal` 和 `MemAvailable`。
- `available_disk_bytes` 是节点状态文件系统的可用空间,而不是沙箱配额。
-节点会测量其命名空间能够看到的内容,因此应让节点运行在其所报告的宿主机上。
+节点会测量其命名空间能够看到的内容,因此应让节点运行在其所报告的主机上。
`history` 按完整的 UTC 桶覆盖指定范围:`1h` 使用 60 秒,`6h` 使用 300 秒,`24h` 使用 900 秒。范围内的每个桶都会存在,但正在进行中的桶除外。`cpu_utilization_max` 和 `memory_used_bytes_max` 是已记录观测值的最大值,其中已用内存按同一观测值中的总内存减去可用内存计算;`available_disk_bytes_min` 是最小值。对于没有记录值的桶,包括离线时段,每个指标均为 null。Core 绝不进行插值或回填。
diff --git a/contracts/agents-api/zh/runtime-observability.md b/contracts/agents-api/zh/runtime-observability.md
index 0832cecf6..5e9aa7473 100644
--- a/contracts/agents-api/zh/runtime-observability.md
+++ b/contracts/agents-api/zh/runtime-observability.md
@@ -1,5 +1,5 @@
---
-title: "运行时可观测性"
+title: "Runtime 可观测性"
source: contracts/agents-api/runtime-observability.md
source_hash: de7eefac37eb9cc5935c28e2425efc323f1555771e48758ce9412455e891b52c
---
@@ -10,7 +10,7 @@ source_hash: de7eefac37eb9cc5935c28e2425efc323f1555771e48758ce9412455e891b52c
## 身份与源选择 {#identity-and-source-selection}
-在读取 provider 之前,Core 会先把每次观测归属到持久化的 Core 身份:
+在读取提供商之前,Core 会先把每次观测归属到持久化的 Core 身份:
```text
managed: tenant_id -> session_id -> environment_id -> runtime_allocation_id
@@ -22,27 +22,27 @@ none: tenant_id -> session_id (no Session-owned Runtime instance)
托管 Docker、microsandbox 和 E2B 分配均会被观测。`none` 和 `self_hosted` Session 为 `unsupported`;Core 绝不会将共享主机统计信息归属于 `environment:none` Session。
-每个托管分配都通过部署所选的 Sandbox Provider 读取;该 Provider 在返回数值前会验证分配的 installation(`provider_key`)以及分配标签或等效所有权数据。在读取任何 provider 之前,部分行的结果由分配状态决定:处于 `creating` 状态或尚无分配时得到 `allocation_pending`,处于 `cleanup_pending` 或 `released` 状态时得到 `runtime_not_running`。provider 读取超出截止时间时得到 `sample_timeout`,返回未运行结果时得到 `runtime_not_running`,返回不可用结果时得到 `sample_unavailable`。任何其他错误、所有权不匹配或无效采样都会使读取失败。
+每个托管分配都通过部署所选的沙箱提供商读取;该提供商在返回数值前会验证分配的 installation(`provider_key`)以及分配标签或等效所有权数据。在读取任何提供商之前,部分行的结果由分配状态决定:处于 `creating` 状态或尚无分配时得到 `allocation_pending`,处于 `cleanup_pending` 或 `released` 状态时得到 `runtime_not_running`。提供商读取超出截止时间时得到 `sample_timeout`,返回未运行结果时得到 `runtime_not_running`,返回不可用结果时得到 `sample_unavailable`。任何其他错误、所有权不匹配或无效采样都会使读取失败。
-`Observe` 属于 [Sandbox Provider 协议](../../../docs/zh/sandbox-provider.md);`services/core/internal/runtimeobs/source.go` 负责观测类型以及 Provider 的 `Source` 视图。Core 每页只加载一次所选 Provider 及其注册 kind,并在该页的每次读取中使用同一不可变 Provider,用 `Observe` 读取每个运行中的目标。没有选择时,加载返回类型化的 `ErrUnavailable`,从而生成不含 provider 类型的 `sample_unavailable`。其他加载错误遵循上述 provider 读取错误规则。
+`Observe` 属于 [沙箱提供商协议](../../../docs/zh/sandbox-provider.md);`services/core/internal/runtimeobs/source.go` 负责观测类型以及提供商的 `Source` 视图。Core 每页只加载一次所选提供商及其注册 kind,并在该页的每次读取中使用同一不可变提供商,用 `Observe` 读取每个运行中的目标。没有选择时,加载返回类型化的 `ErrUnavailable`,从而生成不含提供商类型的 `sample_unavailable`。其他加载错误遵循上述提供商读取错误规则。
-观测的 provider 类型即该注册 kind:`docker`、`microsandbox` 或 `e2b`。重新配置会影响后续页面,但无法更改正在处理页面所选定的 provider 类型或 Provider。Generation 路由器仍会通过每个分配记录的部署代次解析该分配。
+观测的提供商类型即该注册 kind:`docker`、`microsandbox` 或 `e2b`。重新配置会影响后续页面,但无法更改正在处理页面所选定的提供商类型或提供商。Generation 路由器仍会通过每个分配记录的部署代次解析该分配。
## 采样语义 {#sample-semantics}
一个采样包含:
-- `observed_at`,即 provider 的观测时间;以及 `started_at`,即当前计算实例启动周期的开始时间;
+- `observed_at`,即提供商的观测时间;以及 `started_at`,即当前计算实例启动周期的开始时间;
- 累计 CPU 秒数,以及以核心数计的已配置 CPU 容量;
-- provider 报告的 CPU 利用率比率,仅适用于不提供累计 CPU 时间的 provider(E2B);
+- 提供商报告的 CPU 利用率比率,仅适用于不提供累计 CPU 时间的提供商(E2B);
- 当前内存使用量,以及以字节计的内存限制;
-- 当前磁盘使用量和容量,以字节计,且仅在 provider 报告这些值时提供(E2B)。
+- 当前磁盘使用量和容量,以字节计,且仅在提供商报告这些值时提供(E2B)。
每项测量都是可选的。存在的零值表示观测到零;缺失值表示不可用,绝不会显示或聚合为零。Core 会拒绝以下采样:`observed_at` 晚于 Core 自身时钟,`started_at` 晚于 `observed_at`,或任一值为负数、非有限值、容量或限制值为零,或超出 JSON 安全整数范围。
`lifecycle_state` 根据 Core 记录中的分配状态和计算阶段派生,绝不会从采样派生:没有分配或状态为 `creating` 时为 `pending`;状态为 `running` 且计算阶段为 `running` 或 `disabled` 时为 `active`;`suspended` 为 `sleeping`;`quiescing`、`suspending`、`restoring` 或 `waking` 为 `transitioning`;`cleanup_pending` 和 `released` 为 `stopped`。
-## Provider 映射 {#provider-mapping}
+## 提供商映射 {#provider-mapping}
### Docker {#docker}
@@ -69,7 +69,7 @@ E2B 不报告累计 CPU 时间,因此 CPU 秒数保持为 null。`observed_at`
## 读取预算 {#read-budgets}
-当前列表读取处理一页最多 100 个 Session(默认 20 个),provider 读取并发数最多为 8。每次 provider 读取的时限为 2 秒,整个列表请求为 10 秒;超过这些时限时,列表返回 503。单 Session 读取的时限为 2 秒。一次请求内不会重试任何 provider 调用,Core 也不保留观测缓存。
+当前列表读取处理一页最多 100 个 Session(默认 20 个),提供商读取并发数最多为 8。每次提供商读取的时限为 2 秒,整个列表请求为 10 秒;超过这些时限时,列表返回 503。单 Session 读取的时限为 2 秒。一次请求内不会重试任何提供商调用,Core 也不保留观测缓存。
## 时长 {#durations}
@@ -93,9 +93,9 @@ CPU 静默状态、心跳时龄和连接状态都不是空闲时间。
### 存储的历史记录 {#stored-history}
-PostgreSQL 存储仅保留周期性的 `openai_hosted` 记录,因此 API 读取无法虚增覆盖率。每条记录都会写入一行 `runtime_history_samples`,以租户、Session、Environment 和解析时间为键,包括分配信息、provider 类型、状态、观测时间与启动时间、CPU 秒数、容量和利用率比率、内存使用量和限制,以及实测令牌计数器。磁盘数据不存储。缺少 `started_at` 的采样仍计入覆盖范围,但会丢弃资源值,因为这些值无法关联到某次计算实例启动周期。
+PostgreSQL 存储仅保留周期性的 `openai_hosted` 记录,因此 API 读取无法虚增覆盖率。每条记录都会写入一行 `runtime_history_samples`,以租户、Session、Environment 和解析时间为键,包括分配信息、提供商类型、状态、观测时间与启动时间、CPU 秒数、容量和利用率比率、内存使用量和限制,以及实测 token 计数器。磁盘数据不存储。缺少 `started_at` 的采样仍计入覆盖范围,但会丢弃资源值,因为这些值无法关联到某次计算实例启动周期。
-历史服务在查询前解析 Project、Session 和 Environment;查询始终携带该作用域和有界时间范围,但绝不携带 provider 身份。存储保留 7 天。单次读取最多覆盖 24 小时,最多读取 20,000 条原始采样,并从范围起点之前两个采样间隔处开始读取,以查找 CPU 基线;每个数组最多返回 1,000 个桶,最多返回 64 个序列,总点数最多 10,000 个。结果超出请求的作用域、时间范围或限制时,读取失败。API 的 [Series](runtime-observability-api.md#series) 部分说明了聚合方式。
+历史服务在查询前解析项目、Session 和 Environment;查询始终携带该作用域和有界时间范围,但绝不携带提供商身份。存储保留 7 天。单次读取最多覆盖 24 小时,最多读取 20,000 条原始采样,并从范围起点之前两个采样间隔处开始读取,以查找 CPU 基线;每个数组最多返回 1,000 个桶,最多返回 64 个序列,总点数最多 10,000 个。结果超出请求的作用域、时间范围或限制时,读取失败。API 的 [Series](runtime-observability-api.md#series) 部分说明了聚合方式。
`runtimehistory.Capabilities` 声明采样间隔、7 天保留期、最小桶宽度(30 秒或采样间隔,取较长者)、24 小时范围和点数限制;这些值无效时 Core 不会启动。
@@ -105,9 +105,9 @@ PostgreSQL 存储仅保留周期性的 `openai_hosted` 记录,因此 API 读
每次扫描结束后,Core 会在 2 秒内且在检查租约后,将每个新鲜节点心跳复制到 `node_host_history_samples`,其中包含主机 CPU 利用率、已用内存和可用磁盘,并以节点和心跳自身时间为键,因此重复扫描不会增加数据。心跳新鲜的判定条件是:其节点未被移除、在当前所有者 epoch 下处于连接状态、在过去 45 秒内被观察到,并且所报告的主机时间位于过去 45 秒内且不在未来。同样适用 7 天清理期。节点主机历史属于遥测数据,绝不作为调度或容量的权威依据,读取也绝不会对其进行采样或回填。
-### 令牌使用量 {#token-usage}
+### token 使用量 {#token-usage}
-每次观测都携带来自 `MeasuredSessionUsage` 的 Session 实测使用量,即所有已记录根 Turn 快照之和,其中包含活跃 Turn。这不是公开的 Session 使用量规则,并且 Core 绝不会从 provider 计数器、上下文占用量或成本推导令牌数。
+每次观测都携带来自 `MeasuredSessionUsage` 的 Session 实测使用量,即所有已记录根 Turn 快照之和,其中包含活跃 Turn。这不是公开的 Session 使用量规则,并且 Core 绝不会从提供商计数器、上下文占用量或成本推导令牌数。
### OTLP 导出 {#otlp-export}
@@ -117,14 +117,14 @@ PostgreSQL 存储仅保留周期性的 `openai_hosted` 记录,因此 API 读
| --- | --- | --- |
| `agents.runtime.cpu.usage` | 单调累积和,秒 | 累计 CPU 计数器 |
| `agents.runtime.cpu.capacity` | Gauge,核心数 | 已配置的 CPU 容量 |
-| `agents.runtime.cpu.utilization` | Gauge,比率 | Provider 报告的 CPU 占比(E2B) |
+| `agents.runtime.cpu.utilization` | Gauge,比率 | 提供商报告的 CPU 占比(E2B) |
| `agents.runtime.memory.usage` | Gauge,字节 | 内存使用量 |
| `agents.runtime.memory.limit` | Gauge,字节 | 内存限制 |
-| `agents.session.tokens.input` | Gauge,令牌 | 实测 Session 输入令牌 |
-| `agents.session.tokens.output` | Gauge,令牌 | 实测 Session 输出令牌 |
+| `agents.session.tokens.input` | Gauge,token | 实测 Session 输入 token |
+| `agents.session.tokens.output` | Gauge,token | 实测 Session 输出 token |
| `agents.runtime.sample` | 单调差值和 | 每个经验证的结果一条,包括 unavailable 和 unsupported |
-| `agents.runtime.sample.duration` | Delta 直方图,秒 | Provider 读取时长 |
+| `agents.runtime.sample.duration` | Delta 直方图,秒 | 提供商读取时长 |
-仅当采样包含 `started_at` 时才导出 CPU 和内存数据点;缺少测量值不会产生数据点。属性包括 `agents.tenant.id`、`agents.session.id`、`agents.environment.id`、`agents.runtime.allocation.id`、`agents.runtime.mode`、`agents.runtime.provider.type`、`agents.runtime.status`、`agents.runtime.reason`、`agents.runtime.collection.source`,以及以纳秒为单位的 `agents.runtime.resolved_at_unix_nano`、`agents.runtime.observed_at_unix_nano` 和 `agents.runtime.compute.started_at_unix_nano`。这些纳秒时间使记录在后端以较低精度存储事件时间时仍可关联。Provider key、回执、原生标识符、原始错误、路径和凭据绝不会作为属性。
+仅当采样包含 `started_at` 时才导出 CPU 和内存数据点;缺少测量值不会产生数据点。属性包括 `agents.tenant.id`、`agents.session.id`、`agents.environment.id`、`agents.runtime.allocation.id`、`agents.runtime.mode`、`agents.runtime.provider.type`、`agents.runtime.status`、`agents.runtime.reason`、`agents.runtime.collection.source`,以及以纳秒为单位的 `agents.runtime.resolved_at_unix_nano`、`agents.runtime.observed_at_unix_nano` 和 `agents.runtime.compute.started_at_unix_nano`。这些纳秒时间使记录在后端以较低精度存储事件时间时仍可关联。提供商 key、回执、原生标识符、原始错误、路径和凭据绝不会作为属性。
Web 仅通过 Core 读取历史记录;其图表不需要 Collector 或其他指标存储。
diff --git a/contracts/agents-api/zh/sandbox-deployment.md b/contracts/agents-api/zh/sandbox-deployment.md
index 297cf7724..a159cee0d 100644
--- a/contracts/agents-api/zh/sandbox-deployment.md
+++ b/contracts/agents-api/zh/sandbox-deployment.md
@@ -4,15 +4,15 @@ source: contracts/agents-api/sandbox-deployment.md
source_hash: 84fd89164b02406f379720805b6d30b64746b97e5bd322459bffa88496399b91
---
-沙箱部署为 Core 管理的 `openai_hosted` 执行选择 Sandbox Provider、每个沙箱的资源以及不可变的 Runtime 发行版。PostgreSQL 为每个安装维护一个当前有效选择;Web 和 Core API 写入同一配置。节点文件保存其已安装副本和特定于主机的路径,且不能覆盖其资源或 Runtime。该选择独立于 Harness。部署可以保持未配置状态,没有节点;此时它拒绝托管准入。
+沙箱部署为 Core 管理的 `openai_hosted` 执行选择沙箱提供商、每个沙箱的资源以及不可变的 Runtime 发行版。PostgreSQL 为每个安装维护一个当前有效选择;Web 和 Core API 写入同一配置。节点文件保存其已安装副本和特定于主机的路径,且不能覆盖其资源或 Runtime。该选择独立于 Harness。部署可以保持未配置状态,没有节点;此时它拒绝托管准入。
本契约负责下列 Core API 路由及其语义。[节点指南](../../../docs/zh/getting-started/nodes.md)负责操作员工作流,[机器连接 API](machine-api.md#node-routes)负责节点调用的路由,[沙箱节点协议](node-generation-protocol.md)负责节点连接。
## 挂起策略 {#suspension-policy}
-`PATCH /core/v1/sandbox/deployment` 接受 `{"idle_seconds": 300}`。`idle_seconds` 是必填整数,范围为 30–86400 秒,默认为 300。该设置保存在 Core 的数据库中。只有已配置且声明 checkpoint 支持的 Provider 可修改;未配置、不支持或正在重置的部署拒绝写入。成功返回当前部署视图,`suspension.idle_seconds` 反映已保存的值。
+`PATCH /core/v1/sandbox/deployment` 接受 `{"idle_seconds": 300}`。`idle_seconds` 是必填整数,范围为 30–86400 秒,默认为 300。该设置保存在 Core 的数据库中。只有已配置且声明 checkpoint 支持的提供商可修改;未配置、不支持或正在重置的部署拒绝写入。成功返回当前部署视图,`suspension.idle_seconds` 反映已保存的值。
-变更从下一轮生命周期检查起作用于现有和新建的运行中分配,不重启 Core、不推进配置代次,也不重新部署节点。已经开始的挂起不撤销;现有快照和 24 小时快照保留期不变。[容量压力回收](../../../docs/zh/sandbox-provider.md#suspension)仍可在空闲 15 秒后提前挂起。Web 在 **Settings** → **Sandbox and scheduling** → **Automatic suspension** 管理此部署级策略;各节点的容量上限仍属于节点,在 **Nodes** 中通过 **Edit node** 编辑。
+变更从下一轮生命周期检查起作用于现有和新建的运行中分配,不重启 Core、不推进配置代次,也不重新部署节点。已经开始的挂起不撤销;现有快照和 24 小时快照保留期不变。[容量压力回收](../../../docs/zh/sandbox-provider.md#suspension)仍可在空闲 15 秒后提前挂起。Web 在 **设置** → **沙箱与调度** → **自动挂起** 管理此部署级策略;各节点的容量上限仍属于节点,在 **节点** 中通过 **编辑节点** 编辑。
## 路由 {#routes}
@@ -68,7 +68,7 @@ microsandbox 会配置 CPU、内存、托管根磁盘,以及位于 `/environme
响应中可选的 `specification.workspace` 是从所选[工作区文件系统](../../../docs/zh/workspace-provider.md)派生的不可变能力回执,不是可独立写入的设置。它仅包含 `attachment`、`user_xattr` 和 `capacity_quota`;文件系统配置、路径和凭据不进入 Sandbox specification。Core 保存前校验组合声明,保留代次校验与节点构造均使用此回执。缺失 `workspace` 时保留自有磁盘模式及现有容量边界。Create 和 Resume 必须且仅当固定代次选择外部存储时提供绑定。
-为现有自有磁盘部署启用外部存储时,先选择文件系统配置,再使用兼容资源更新 Sandbox 部署(不支持配额的文件系统使用 `environment_disk_mib: 0`)。选择文件系统不会改变现有代次或 allocation。下一次 Sandbox 更新派生外部能力回执;旧的自有磁盘 allocation 保留原磁盘。文件系统选择必须支持 Provider 声明的要求。已采用外部存储的部署要求相同的 `attachment` 和 `user_xattr`;选择可以更改 `capacity_quota`,此后在 Sandbox 更新设置相匹配的 `environment_disk_mib` 之前拒绝新工作区。既有工作区保持其获准时的容量。
+为现有自有磁盘部署启用外部存储时,先选择文件系统配置,再使用兼容资源更新 Sandbox 部署(不支持配额的文件系统使用 `environment_disk_mib: 0`)。选择文件系统不会改变现有代次或 allocation。下一次 Sandbox 更新派生外部能力回执;旧的自有磁盘 allocation 保留原磁盘。文件系统选择必须支持提供商声明的要求。已采用外部存储的部署要求相同的 `attachment` 和 `user_xattr`;选择可以更改 `capacity_quota`,此后在 Sandbox 更新设置相匹配的 `environment_disk_mib` 之前拒绝新工作区。既有工作区保持其获准时的容量。
### Runtime 发行版 {#runtime-release}
@@ -100,9 +100,9 @@ E2B 使用 `template-id:build-uuid` 形式的 `configuration.template`;构建
GET 和成功的写入操作会返回 `installation_id`、`provider`、`core_url`(只读:安装公开 URL,即使配置前也存在)、`mode`、`generation`、`owner_epoch`、`reset`、`rollout`、`suspension`、`resources` 和 `credential_configured`。已配置的部署还会返回 `specification`、`specification_digest`、`configuration` 和 `metadata`:这是适配器对其选择器及其记录的观测结果所作的公开投影,绝不会包含原始存储值或机密。E2B 返回 `configuration.template`、`configuration.api_url`、`configuration.domain`,并在记录后返回 `metadata.template_build`。Docker 和 microsandbox 返回空的 `configuration` 和 `metadata` 对象以及 `credential_configured: false`;未配置的部署则不含这两个对象。
- `metadata.template_build` 为 `{status, resources: {cpus, memory_mib, root_disk_mib}}`:这是保存选择时 Core 通过固定版本 SDK 读取的构建。GET 绝不会调用 E2B,因此 E2B 中断期间该操作仍保持低成本。验证仅接受 CPU 数量和内存与所选值一致的 `ready` 构建;`root_disk_mib` 是构建的原生磁盘大小,Core 不会强制执行该值。未知值为 null,`metadata: {}` 表示未记录任何观测,在不提供凭据的情况下提交完全相同的 PUT 也不会刷新它。
-- 所选 Provider 声明 checkpoint 支持时,`suspension` 为 `{idle_seconds, retention_seconds}`,即 Core 的 [suspension policy](../../../docs/zh/sandbox-provider.md#suspension);其他部署(包括未配置的部署)返回 null。
+- 所选提供商声明 checkpoint 支持时,`suspension` 为 `{idle_seconds, retention_seconds}`,即 Core 的 [suspension policy](../../../docs/zh/sandbox-provider.md#suspension);其他部署(包括未配置的部署)返回 null。
- 请求中的 `resources` 和响应中的 `specification.resources` 是每个沙箱的限制。响应中的 `resources.allocations` 和 `resources.pending` 分别计算尚未释放的分配,以及尚未分配沙箱的待处理托管 Environment。
-- 未配置的部署具有空的 provider 且没有 specification。Docker 和 microsandbox 使用 `mode: nodes`;E2B 使用 `mode: direct`,且没有合成节点。
+- 未配置的部署具有空的提供商且没有 specification。Docker 和 microsandbox 使用 `mode: nodes`;E2B 使用 `mode: direct`,且没有合成节点。
- `generation` 标识已保存的选择。`owner_epoch` 用于对执行所有者和节点连接进行栅栏隔离;它不能替代 `expected_generation`。
- `specification_digest` 是服务器对提供商、限制和 Runtime 发行版的标识;注册过程会原样回显该值。
@@ -110,13 +110,13 @@ GET 和成功的写入操作会返回 `installation_id`、`provider`、`core_url
## 初始设置与同提供商更改 {#initial-setup-and-same-provider-changes}
-POST 会在持久保存候选配置之前对其进行验证,并且不会创建计算资源、Session 或模型请求。在当前代次上,完全相同的选择是无操作;使用旧代次则返回 409 `sandbox_generation_stale`,即使请求体相同也是如此。缺少前置条件或准备失败时,已提交的提供商保持不变。更改后端前必须先重置。POST 还会在重置完成后使用该重置的新代次进行初始化。
+POST 会在持久保存候选配置之前对其进行验证,并且不会创建计算资源、Session 或模型请求。在当前代次上,完全相同的选择是无操作;使用旧代次则返回 409 `sandbox_generation_stale`,即使请求体相同也是如此。缺少前置条件或准备失败时,已提交的提供商保持不变。更改提供商前必须先重置。POST 还会在重置完成后使用该重置的新代次进行初始化。
仅在没有重置进行时,PUT 才接受同一提供商。只发送一次观测到的代次,绝不自动重放结果不确定的写入操作。新分配使用新提交的 specification,现有分配则保留其不可变的部署代次。同提供商更改不会停用任何节点、令牌或所有者 epoch,也不会排空任何执行:Docker 和 microsandbox 节点在继续提供旧固定版本的同时独立准备新目标,而 E2B 更改会立即生效。
### E2B 密钥替换 {#e2b-key-replacement}
-在 PUT 中省略 `credential` 可保留当前密钥;不提供该字段的完全相同选择是无操作。提交密钥时,即使密钥相同,也始终会验证密钥并推进代次;null 或空密钥无效。仅更改密钥时使用相同的完整请求体(provider、现有 configuration、可选 resources、`expected_generation` 和新 `credential`),无需单独路由,也不会隐式重置。
+在 PUT 中省略 `credential` 可保留当前密钥;不提供该字段的完全相同选择是无操作。提交密钥时,即使密钥相同,也始终会验证密钥并推进代次;null 或空密钥无效。仅更改密钥时使用相同的完整请求体(提供商、现有 configuration、可选 resources、`expected_generation` 和新 `credential`),无需单独路由,也不会隐式重置。
初始设置要求所选模板出现在该密钥所属团队的模板列表中;仅可公开读取并不足够。在线更改之前,Core 会验证已提交密钥拥有当前模板,然后要求候选密钥拥有完全相同的模板,从而确立团队所有权。Core 还会使用候选密钥在其原始端点读取候选构建和每个保留构建,并确认带安装标签的沙箱列表中每个已结算的实时回执。
@@ -158,7 +158,7 @@ POST 会在持久保存候选配置之前对其进行验证,并且不会创建
## 重置 {#reset}
-要更改后端,请启动重置:
+要更改提供商,请启动重置:
```json
{"expected_generation": 7, "clear": "auto", "deadline_seconds": 3600}
@@ -179,7 +179,7 @@ POST 会在持久保存候选配置之前对其进行验证,并且不会创建
一个数据库快照会先按 `cleanup`,再按 `busy` 或 `idle`,对每个尚未释放的分配和每个尚未分配沙箱的待处理托管 Environment 进行划分,因此 `busy + idle + cleanup == resources.allocations + resources.pending`。已删除或已过期且具有未释放回执的 Session 计入 cleanup。`offline_nodes` 是通过分配或活动放置持有资源的离线节点的完整列表,并按 ID 排序,其总和等于 `on_offline_nodes`;存在性依据当前所有者 epoch、连接状态以及 45 秒内的心跳判断,而不依据提供商就绪状态。直接 E2B 资源没有节点。离线资源会持续构成阻塞条件,直到清理确认其已释放。
-当两个占用计数均达到零时,所有者会排空执行,并原子清除 provider、mode、specification、provider configuration、credential、metadata 和 provider policy,停用节点和未使用的注册令牌,递增代次与所有者 epoch,并记录 `reset_complete`。安装身份和历史会保留。Core 会立即发布未配置状态,即使没有 provider 也保留新代次,因此延迟加载无法恢复旧配置。使用 POST 和返回的代次即可重新配置,无需重启。
+当两个占用计数均达到零时,所有者会排空执行,并原子清除提供商、mode、specification、提供商 configuration、credential、metadata 和提供商 policy,停用节点和未使用的注册令牌,递增代次与所有者 epoch,并记录 `reset_complete`。安装身份和历史会保留。Core 会立即发布未配置状态,即使没有提供商也保留新代次,因此延迟加载无法恢复旧配置。使用 POST 和返回的代次即可重新配置,无需重启。
重置期间,新的托管准入会返回 503 `sandbox_reset_in_progress`,并且不会留下临时 Session 行;实时输入、回执重试、恢复和清理会继续进行。管理写入和新注册会返回 409 `sandbox_reset_in_progress`,而已注册节点仍可读取其配置,以便恢复并执行清理。每个 Session 的 [archive](admin-api.md#session-archive)仅需要当前代次,无论是否正在重置均可使用。它会保留历史以及已持久化的 Files 和 Artifacts,丢弃未持久化的工作区,并阻止 Session 恢复;轮询 archive GET 以获取实际释放状态。重置绝不会伪造释放回执。
@@ -193,7 +193,7 @@ POST 会在持久保存候选配置之前对其进行验证,并且不会创建
`GET /core/v1/sandbox/nodes` 返回 `{data: [...]}`,其中每个节点包含 `id`、`name`、`provider`、`online`、`last_seen_at`、`created_at`、`max_active`、`max_retained`,计数项 `active`、`reserved`、`running`、`retained`、`snapshots` 和 `cleanup_pending`,以及 `provider_ready`、`diagnostic`、主机测量值 `cpu_count`、`available_memory_bytes` 和 `available_disk_bytes`、`rollout`、`enrollment_id` 和 `core_url`。`enrollment_id` 是注册该节点的命令的句柄;如果 Core 没有该句柄,则为 null。`core_url` 是注册时的安装公开 URL;`core_url` 与当前公开 URL 不同的节点不会收到新放置。已放置到该节点的工作会继续在那里完成,包括已放置但尚未获得分配的 Environment;只要旧地址仍能访问 Core,其保留沙箱仍可恢复。请移除该节点并重新添加。
-不具备代次管理的节点会自行报告其提供商的就绪状态:`provider_ready`,未就绪时则报告一个固定的 `diagnostic` 代码。通过 Web 的命令添加的节点会管理代次,因此其就绪状态取决于服务代次,而目标代次的固定代码会出现在 `rollout.diagnostic` 中。节点会对首次失败的就绪检查进行分类,并且只发送代码;携带任何其他值的帧均无效,且 Core 绝不存储或返回探测文本或主机路径。这些代码是与 Provider 无关的类别:`provider_unavailable`、`host_unsupported`、`artifacts_unavailable`、`runtime_download_failed`、`runtime_image_unavailable` 和 `capacity_insufficient`。`runtime_download_failed` 表示无法传输或验证精确的 Runtime 制品;它绝不会包含制品 URL、凭据或传输输出。[就绪代码](../../../docs/zh/getting-started/nodes.md#readiness-codes)给出了原因和操作员应采取的措施。Core 和节点必须来自同一发行包。
+不具备代次管理的节点会自行报告其提供商的就绪状态:`provider_ready`,未就绪时则报告一个固定的 `diagnostic` 代码。通过 Web 的命令添加的节点会管理代次,因此其就绪状态取决于服务代次,而目标代次的固定代码会出现在 `rollout.diagnostic` 中。节点会对首次失败的就绪检查进行分类,并且只发送代码;携带任何其他值的帧均无效,且 Core 绝不存储或返回探测文本或主机路径。这些代码是与提供商无关的类别:`provider_unavailable`、`host_unsupported`、`artifacts_unavailable`、`runtime_download_failed`、`runtime_image_unavailable` 和 `capacity_insufficient`。`runtime_download_failed` 表示无法传输或验证精确的 Runtime 制品;它绝不会包含制品 URL、凭据或传输输出。[就绪代码](../../../docs/zh/getting-started/nodes.md#readiness-codes)给出了原因和操作员应采取的措施。Core 和节点必须来自同一发行包。
`PATCH /core/v1/sandbox/nodes/{node_id}` 接受 `{name, max_active, max_retained}`;降低限制不会停止任何正在运行的沙箱。当节点仍持有分配、快照、预留或待处理清理时,包括节点离线期间,`DELETE /core/v1/sandbox/nodes/{node_id}` 会拒绝操作并返回 409 `runtime_node_in_use`。移除操作不会删除任何计算资源,并且会停用该节点的身份;该主机只能作为新节点重新加入。不存在节点排空过程。
@@ -228,7 +228,7 @@ POST 会在持久保存候选配置之前对其进行验证,并且不会创建
| 400 | `invalid_request_error` 或 `invalid_request` | 请求格式错误 |
| 400 | `invalid_sandbox_configuration` | 配置验证产生的诊断错误 |
| 409 | `sandbox_generation_stale` | `expected_generation` 不是当前值;`current_generation` 提供当前代次 |
-| 409 | `sandbox_reset_required` | 后端不同;详情会指明当前提供商和请求的提供商 |
+| 409 | `sandbox_reset_required` | 提供商不同;详情会指明当前提供商和请求的提供商 |
| 409 | `sandbox_not_configured` | 更改未配置的部署 |
| 409 | `sandbox_reset_in_progress` | 重置期间执行管理写入或新注册 |
| 409 | `sandbox_deployment_conflict` | 更改无法应用于另一种状态 |
@@ -239,7 +239,7 @@ POST 会在持久保存候选配置之前对其进行验证,并且不会创建
## 规范的节点规格 {#canonical-node-specification}
-`sandbox/deployment_contract.go`负责资源边界、发行版模式和规范字段顺序,每个已注册 Provider 的 `sandbox.DeploymentPolicy` 声明其要求;`sandbox/deployment.go`在 Core 中应用这些规则。安装程序会使用 `deploy/node/node_spec.py` 中生成的声明,TypeScript 客户端和 Web 使用 `packages/agents-client/src/deployment-contract.ts` 中生成的边界、模式和 Provider 声明,因此不存在第二套限制、模式或提供商列表。请在仓库根目录运行 `go run ./services/core/cmd/specification-contract -write` 重新生成两者;作为 `make check` 一部分的沙箱 Go 测试会拒绝过时的投影。
+`sandbox/deployment_contract.go`负责资源边界、发行版模式和规范字段顺序,每个已注册提供商的 `sandbox.DeploymentPolicy` 声明其要求;`sandbox/deployment.go`在 Core 中应用这些规则。安装程序会使用 `deploy/node/node_spec.py` 中生成的声明,TypeScript 客户端和 Web 使用 `packages/agents-client/src/deployment-contract.ts` 中生成的边界、模式和提供商声明,因此不存在第二套限制、模式或提供商列表。请在仓库根目录运行 `go run ./services/core/cmd/specification-contract -write` 重新生成两者;作为 `make check` 一部分的沙箱 Go 测试会拒绝过时的投影。
规范摘要是紧凑 UTF-8 JSON 的 SHA-256,其中 `provider` 位于首位,其次是 `resources`,然后在提供商需要时放置 `runtime`。资源和 Runtime 字段遵循契约的声明顺序;值为零的可选磁盘字段会被省略,必填字段则保持存在。发行版标识采用小写 ASCII,摘要绝不会受传入字段顺序或空白字符影响。`services/core/internal/sandbox/testdata/deployment-contract.json`保存共享验收用例、精确的规范字节和摘要,Go 与 Python 测试都会使用这些内容。
diff --git a/contracts/agents-api/zh/session-diagnostics.md b/contracts/agents-api/zh/session-diagnostics.md
index 6a823c16b..bf260afb3 100644
--- a/contracts/agents-api/zh/session-diagnostics.md
+++ b/contracts/agents-api/zh/session-diagnostics.md
@@ -4,7 +4,7 @@ source: contracts/agents-api/session-diagnostics.md
source_hash: d84a678de2a21f66e2090afff19aea5cff5d3f11d5c32306ebd4387b015cb416
---
-这些只读路由要求 Core 密钥。Project ID 选择目标 Project,不用于认证。两者都返回 `Cache-Control: no-store`:
+这些只读路由要求 Core 密钥。项目 ID 选择目标项目,不用于认证。两者都返回 `Cache-Control: no-store`:
- `GET /core/v1/projects/{project_id}/sessions/{session_id}/diagnostics`
- `GET /core/v1/projects/{project_id}/sessions/{session_id}/turns/{turn_id}/diagnostics`
@@ -23,7 +23,7 @@ source_hash: d84a678de2a21f66e2090afff19aea5cff5d3f11d5c32306ebd4387b015cb416
| `params` | 包含固定安全值的对象;无参数的分类使用 `{}` |
| `failed_at` | RFC 3339 时间戳;时间未知时为 null |
-托管配置失败优先于输入活动,输入活动优先于最新根 Turn;公开 Session 响应使用相同优先级。不会包含私有结果文本、原生消息、提供方响应体、命令文本、路径或凭据。未知结果代码变为 `internal_error`;不使用前缀匹配或原因文本解析。
+托管配置失败优先于输入活动,输入活动优先于最新根 Turn;公开 Session 响应使用相同优先级。不会包含私有结果文本、原生消息、提供商响应体、命令文本、路径或凭据。未知结果代码变为 `internal_error`;不使用前缀匹配或原因文本解析。
配置参数来自已确认的结构化回执,在结算 Environment 及其输入并记录事件的失败事务中持久化。`step` 为 `setup`、`python`、`npm`、`system`、`file`、`skill` 或 null。`index` 仅对 setup 为 JSON 安全的非负整数,其他情况为 null。`exit_code` 对脚本步骤为 1 至 255,其他情况为 null。未记录的详情保持 null。这些私有字段不会改变公开失败原因或 SSE。
diff --git a/contracts/agents-api/zh/sessions-events.md b/contracts/agents-api/zh/sessions-events.md
index 504ffbee1..7d0114a64 100644
--- a/contracts/agents-api/zh/sessions-events.md
+++ b/contracts/agents-api/zh/sessions-events.md
@@ -1,10 +1,10 @@
---
-title: "会话、事件和历史"
+title: "Session、事件和历史"
source: contracts/agents-api/sessions-events.md
-source_hash: a48c49badc66b137c05a1eae4060524e2fb3bb866510d54c8840d84b7086375c
+source_hash: d78ffc4d163049f10a8915b98621bb8a94a2f19724efe1d0fd70cf4b92ac298e
---
-本契约涵盖会话(Session)内部发生的事情:发送输入、实时事件流,以及读取轮次(Turn)、条目(Item)和使用量的持久化历史。会话资源本身(创建配置、重试标识、更新、列出和删除)见 [Core 线协议行为](wire-semantics.md)。消息和函数结果内容见[消息内容](message-content.md)。[Agents API 指南](../../../docs/zh/api/public-agent-api.md)展示了使用 SDK 和 HTTP 的调用方式。
+本契约涵盖 Session 内部发生的事情:发送输入、实时事件流,以及读取 Turn、Item 和使用量的持久化历史。Session 资源本身(创建配置、重试标识、更新、列出和删除)见 [Core 线协议行为](wire-semantics.md)。消息和函数结果内容见[消息内容](message-content.md)。[Agents API 指南](../../../docs/zh/api/public-agent-api.md)展示了使用 SDK 和 HTTP 的调用方式。
## 恢复模型 {#recovery-model}
@@ -12,13 +12,13 @@ source_hash: a48c49badc66b137c05a1eae4060524e2fb3bb866510d54c8840d84b7086375c
1. 在发送输入前打开 `GET /v1/agents/sessions/{session_id}/events`。
2. 断开连接后,再次订阅并缓冲新事件。
-3. 读取会话、其 Turn 和 Item,按 ID 对 Item 去重,并在应用缓冲更新时保留已最终确定的 Item。
+3. 读取 Session、其 Turn 和 Item,按 ID 对 Item 去重,并在应用缓冲更新时保留已最终确定的 Item。
-流只是一个观察器。关闭流绝不会取消已接纳的工作,而且流绝不会重放未由它发送过的事件。输入响应丢失后,使用相同的 `Idempotency-Key` 重试,然后读取会话、Turn 和 Item。
+流只是一个观察器。关闭流绝不会取消已接纳的工作,而且流绝不会重放未由它发送过的事件。输入响应丢失后,使用相同的 `Idempotency-Key` 重试,然后读取 Session、Turn 和 Item。
-## 会话状态 {#session-status}
+## Session 状态 {#session-status}
-会话的 `status` 和 `last_active_at` 由其最新的根 Turn 以及仍在等待 Environment 的输入推导得出:
+Session 的 `status` 和 `last_active_at` 由其最新的根 Turn 以及仍在等待 Environment 的输入推导得出:
| `status` | 适用情况 |
| --- | --- |
@@ -27,115 +27,115 @@ source_hash: a48c49badc66b137c05a1eae4060524e2fb3bb866510d54c8840d84b7086375c
| `requires_action` | 最新 Turn 正在等待函数结果且未请求取消,或输入正在等待 `self_hosted` 机器连接。`required_actions` 列出 `function_call` 或 `environment_connection` 条目 |
| `failed` | 最新 Turn 失败(`error` 为 "The execution could not complete.")、为 Environment 预留的输入失败、初始输入在接纳前到期,或 Environment 初始化失败(见 [Environment 初始化失败](#environment-initialization-failure)) |
-Turn 失败后会话仍可使用:新输入会启动一个新 Turn。后来预留的输入到期时,会话保持为 `idle`。Environment 初始化失败或过期会阻止新工作。
+Turn 失败后 Session 仍可使用:新输入会启动一个新 Turn。后来预留的输入到期时,Session 保持为 `idle`。Environment 初始化失败或过期会阻止新工作。
## 发送输入 {#send-input}
-`POST /v1/agents/sessions/{session_id}/events` 接收包含 1 到 64 个事件的有序数组:`agent.session.input.message`、`agent.session.input.cancel` 和 `agent.session.input.tool_result`。整个批次以原子方式接纳;批次存储后且在任何 harness 读取它之前,响应为无正文的 202。接纳绝不表示已在原生侧应用。
+`POST /v1/agents/sessions/{session_id}/events` 接收包含 1 到 64 个事件的有序数组:`agent.session.input.message`、`agent.session.input.cancel` 和 `agent.session.input.tool_result`。整个批次以原子方式接纳;批次存储后且在任何 Harness 读取它之前,响应为无正文的 202。接纳绝不表示已在原生侧应用。
- **限制。** 请求正文最多为 1 MiB,单次请求存储的输入最多为 512 KiB。
- **空值批次。** 将 `events` 显式设为 `null` 无效。
-- **空批次。** `{"events": []}` 会检查会话是否存在并返回 202。它不会创建 Turn、Item 或重试标识。
+- **空批次。** `{"events": []}` 会检查 Session 是否存在并返回 202。它不会创建 Turn、Item 或重试标识。
- **重试。** 最长 128 字节的 `Idempotency-Key` 标识整个有序批次。相同密钥和批次会再次返回 202,而不会重复接纳任何内容;相同密钥搭配另一个批次会返回 409 `idempotency_conflict`。不带密钥的请求始终是新请求。
-- **消息。** 在空闲会话上,消息批次会启动一个排队的 Turn。Turn 运行时,消息会加入其中(引导);它们绝不会启动并行 Turn。每条消息都保留为独立的用户 Item,即使 harness 将多条消息作为同一个提示接收。
-- **取消。** 排队的 Turn 无需活动 Runtime 即可取消。正在运行的 Turn 只有在 Runtime 确认后才会取消;完成操作可能赢得该竞争。读取到 `cancelled` 时才表示该 Turn 已停止,而不是请求返回时。在没有待处理输入的情况下,对空闲会话执行的取消会被接受且不产生任何效果;而在输入预留待处理期间,取消会返回 409。
-- **函数结果。** `turn_id`、`call_id` 和 `success` 为必填项;`output` 和 `error` 为可选项且可为空([内容规则](message-content.md#function-results))。重复提交完全相同的结果会返回 202,不会再次应用或发出事件。harness 应用结果时才会出现结果 Item;如果取消操作导致结果无法应用,结果仍会存储,但不会产生 Item。
-- **排队。** 当一个已连接且支持该会话 harness 和配置的 Runtime 接入,并且 Core 的 [`OAC_EXECUTION_CONCURRENCY`](../../../docs/zh/configuration.md#settings) 工作槽位有一个空闲时,排队的 Turn 才会启动。会话始终绑定到首次运行它的 Runtime。
+- **消息。** 在空闲 Session 上,消息批次会启动一个排队的 Turn。Turn 运行时,消息会加入其中(引导);它们绝不会启动并行 Turn。每条消息都保留为独立的用户 Item,即使 Harness 将多条消息作为同一个提示接收。
+- **取消。** 排队的 Turn 无需活动 Runtime 即可取消。正在运行的 Turn 只有在 Runtime 确认后才会取消;完成操作可能赢得该竞争。读取到 `cancelled` 时才表示该 Turn 已停止,而不是请求返回时。在没有待处理输入的情况下,对空闲 Session 执行的取消会被接受且不产生任何效果;而在输入预留待处理期间,取消会返回 409。
+- **函数结果。** `turn_id`、`call_id` 和 `success` 为必填项;`output` 和 `error` 为可选项且可为空([内容规则](message-content.md#function-results))。重复提交完全相同的结果会返回 202,不会再次应用或发出事件。Harness 应用结果时才会出现结果 Item;如果取消操作导致结果无法应用,结果仍会存储,但不会产生 Item。
+- **排队。** 当一个已连接且支持该 Session Harness 和配置的 Runtime 接入,并且 Core 的 [`OAC_EXECUTION_CONCURRENCY`](../../../docs/zh/configuration.md#settings) 工作槽位有一个空闲时,排队的 Turn 才会启动。Session 始终绑定到首次运行它的 Runtime。
- **执行可用性。** Core 关闭期间,或其 Worker 失去执行所有权后,请求返回 503 `execution_unavailable`。
-### 包含 Environment 的会话 {#sessions-with-an-environment}
+### 包含 Environment 的 Session {#sessions-with-an-environment}
-在 `openai_hosted` 和 `self_hosted` 会话中,Turn 运行期间发送的消息会立即加入该 Turn。发送给空闲会话的消息会为 Environment 预留该批次:请求等待 Turn 开始,从预留时起最多等待五分钟。预留等待 `self_hosted` 机器连接时,会话显示为 `requires_action`,并带有 `environment_connection` 操作。在这些部署方式下,携带消息的批次只能包含消息。仅取消和仅结果的批次会立即被接纳,并且不会创建 Turn。
+在 `openai_hosted` 和 `self_hosted` Session 中,Turn 运行期间发送的消息会立即加入该 Turn。发送给空闲 Session 的消息会为 Environment 预留该批次:请求等待 Turn 开始,从预留时起最多等待五分钟。预留等待 `self_hosted` 机器连接时,Session 显示为 `requires_action`,并带有 `environment_connection` 操作。在这些部署方式下,携带消息的批次只能包含消息。仅取消和仅结果的批次会立即被接纳,并且不会创建 Turn。
-当 Turn 启动时,等待中的请求以 202 结束;超过截止时间时,以 409 `environment_input_expired` 结束;管理员归档会话或重置其部署并取消预留时,以 409 `environment_input_cancelled` 结束;Environment 失败或过期时,以 409 `environment_unavailable` 结束。断开等待中的请求不会取消预留,也不会重新开始其截止计时。
+当 Turn 启动时,等待中的请求以 202 结束;超过截止时间时,以 409 `environment_input_expired` 结束;管理员归档 Session 或重置其部署并取消预留时,以 409 `environment_input_cancelled` 结束;Environment 失败或过期时,以 409 `environment_unavailable` 结束。断开等待中的请求不会取消预留,也不会重新开始其截止计时。
### 输入错误 {#input-errors}
-检查按以下顺序执行:请求验证、会话查找、重试查找、针对包含消息的批次的 Environment 文件写入门控、待处理输入门控,最后按批次顺序检查每个事件。被拒绝的批次不会写入任何内容,也不会改变任何待处理操作。所有 409 响应的 `type` 都是 `conflict_error`([错误封装](wire-semantics.md))。
+检查按以下顺序执行:请求验证、Session 查找、重试查找、针对包含消息的批次的 Environment 文件写入门控、待处理输入门控,最后按批次顺序检查每个事件。被拒绝的批次不会写入任何内容,也不会改变任何待处理操作。所有 409 响应的 `type` 都是 `conflict_error`([错误封装](wire-semantics.md))。
| 情况 | 状态和代码 | 消息 |
| --- | --- | --- |
-| 发往该会话的较早输入仍在等待接纳,例如正在预配的托管会话所预留的初始输入,或离线 `self_hosted` 会话所预留的初始输入 | 409 `conflict_error` | "Earlier input to this Session is still pending." |
+| 发往该 Session 的较早输入仍在等待接纳,例如正在预配的托管 Session 所预留的初始输入,或离线 `self_hosted` Session 所预留的初始输入 | 409 `conflict_error` | "Earlier input to this Session is still pending." |
| Turn 在当前状态下无法接受的输入,例如取消后提交的结果,或 Turn 已结束且未存储结果后提交的结果 | 409 `conflict_error` | "The Turn cannot accept this input in its current state." |
| 与该调用已存储结果不同的结果,无论其 Turn 结束之前还是之后 | 409 `conflict_error` | "The tool call already has a different result." |
| 相同 `Idempotency-Key` 搭配不同批次 | 409 `idempotency_conflict` | "This idempotency key was used with different input." |
-| `call_id` 未标识该会话的任何函数调用的结果 | 400 `invalid_request_error`, param null | "Unknown pending tool call." |
-| 为该会话的某个调用提交结果,但 `turn_id` 标识另一个 Turn、未知 Turn ID,或不是 Turn ID 的值 | 400 `invalid_request_error`, param null | "The tool call belongs to a different Turn." |
-| 缺失、格式错误或来自其他作用域的会话 | 404 `not_found_error` | "Resource not found." |
+| `call_id` 未标识该 Session 的任何函数调用的结果 | 400 `invalid_request_error`, param null | "Unknown pending tool call." |
+| 为该 Session 的某个调用提交结果,但 `turn_id` 标识另一个 Turn、未知 Turn ID,或不是 Turn ID 的值 | 400 `invalid_request_error`, param null | "The tool call belongs to a different Turn." |
+| 缺失、格式错误或来自其他作用域的 Session | 404 `not_found_error` | "Resource not found." |
| `openai_hosted` Environment 预配失败后提交新输入 | 409 `conflict_error` | "the hosted environment failed to provision" |
| `self_hosted` Environment 失败后提交新输入、Environment 失败时输入已在等待,或 Environment 已过期 | 409 `environment_unavailable` | "The environment is no longer available for new input." |
-| 会话 harness 无法处理的消息,例如 Claude Code 上仅含空白的文本 | 400 `unsupported_or_invalid_configuration` | 见[仅含空白的文本](message-content.md#whitespace-only-text) |
+| Session Harness 无法处理的消息,例如 Claude Code 上仅含空白的文本 | 400 `unsupported_or_invalid_configuration` | 见[仅含空白的文本](message-content.md#whitespace-only-text) |
`turn_id` 为空或 `call_id` 为空白时,会返回通用的 400 `invalid_request`。错误消息绝不会重复调用方输入或内部标识符。
-## 创建会话时的初始输入 {#initial-input-at-session-creation}
+## 创建 Session 时的初始输入 {#initial-input-at-session-creation}
`POST /v1/agents/sessions` 接受字符串形式的 `input`(一条文本消息)或用户消息数组,并执行与 events 端点相同的验证和接纳。
- `none` 必须提供初始输入(400 `invalid_request_error`,"conversation-only sessions currently require initial input");使用 `stream: true` 时,除 `self_hosted` 外的所有部署方式也必须提供初始输入(400,"streaming session creation requires initial input")。这些检查在创建重试查找之前执行。
-- 会话及其初始工作在一个事务中提交。对于 `none`,这包括首个 Turn 和输入 Item。对于 `openai_hosted`,输入会在 Environment 预配期间保留。对于 `self_hosted`,输入会保留并带有 `environment_connection` 操作,即使机器仍处于离线状态,创建操作也会返回。
-- 预留的初始输入与后续输入具有相同的五分钟截止时间。如果截止时间在 Turn 启动前过去,会话将显示为 `failed`,且不会创建 Turn。
-- 创建重试会返回原始会话,绝不会再次接纳其输入,即使之后已经产生新的 Turn([创建重试](wire-semantics.md))。
+- Session 及其初始工作在一个事务中提交。对于 `none`,这包括首个 Turn 和输入 Item。对于 `openai_hosted`,输入会在 Environment 预配期间保留。对于 `self_hosted`,输入会保留并带有 `environment_connection` 操作,即使机器仍处于离线状态,创建操作也会返回。
+- 预留的初始输入与后续输入具有相同的五分钟截止时间。如果截止时间在 Turn 启动前过去,Session 将显示为 `failed`,且不会创建 Turn。
+- 创建重试会返回原始 Session,绝不会再次接纳其输入,即使之后已经产生新的 Turn([创建重试](wire-semantics.md))。
## 创建时流式传输 {#creation-streaming}
-创建会话时使用 `stream: true` 会返回 201 和事件流,而不是 JSON。
+创建 Session 时使用 `stream: true` 会返回 201 和事件流,而不是 JSON。
-1. 第一个事件是 `agent.session.created`,其中包含提交后读取到的已提交会话,与 JSON 201 正文相同。对于带初始输入的 `none`,其状态已经为 `in_progress`;对于 `self_hosted`,其中已经显示 `environment_connection` 操作。
+1. 第一个事件是 `agent.session.created`,其中包含提交后读取到的已提交 Session,与 JSON 201 正文相同。对于带初始输入的 `none`,其状态已经为 `in_progress`;对于 `self_hosted`,其中已经显示 `environment_connection` 操作。
2. 随后,流会从创建操作自身的位置开始,将创建过程中每个已提交事件恰好发送一次,因此即使执行速度很快,也不会漏掉最初的事件。
3. 流会在首次记录到 `agent.session.idle` 后立即结束;该事件会在 Turn 结束时,或输入预留停止等待时(到期、取消或失败)记录。流也会在任何 `agent.session.failed` 之后结束,并且绝不发送后续事件。`requires_action`、函数结果、恢复的工作和 `self_hosted` 连接会使流保持打开。预留会使流保持打开,直到 Turn 进入最终状态或预留结束。
4. 如果创建未接纳任何内容,流会在 `agent.session.created` 后立即结束。如果某个结束过程未记录任何事件,流会在已提交至该最终状态的事件之后结束;另一个客户端在该时刻之前提交的工作仍可能被发送。
在结束中的 Turn 捕获 Artifacts 期间预留的输入,可以启动创建流不会跟踪的后续 Turn。
-使用相同 `Idempotency-Key` 和 `stream: true` 重试会返回 201,流中仅包含连接注释并立即结束:它不会接纳任何内容,也不会跟踪任何工作。要恢复丢失的会话 ID,请使用相同密钥和 `stream: false` 重复请求,然后读取会话、Turn 和 Item。断开连接只会停止观察器。后续 Turn 可通过 GET 流进行观察。
+使用相同 `Idempotency-Key` 和 `stream: true` 重试会返回 201,流中仅包含连接注释并立即结束:它不会接纳任何内容,也不会跟踪任何工作。要恢复丢失的 Session ID,请使用相同密钥和 `stream: false` 重复请求,然后读取 Session、Turn 和 Item。断开连接只会停止观察器。后续 Turn 可通过 GET 流进行观察。
## 实时事件流 {#live-event-stream}
`GET /v1/agents/sessions/{session_id}/events` 从最新已提交事件处开始,只发送此后提交的事件。`Last-Event-ID` 会被忽略。事件会在各自事务提交后发布。
-- **生命周期。** 流会跨 Turn 保持打开,并在 Turn 失败后继续存在。流会在会话被删除时,或在 [Environment 初始化失败](#environment-initialization-failure)产生终止 `agent.session.failed` 后结束;在该失败之后打开的流会保持打开。每 15 秒发送一次 keepalive 注释。
-- **缓冲区。** Core 为每个会话最多保留 256 个事件和 64 MiB 事件,必要时还会额外容纳一个更大的事件。读取方落后于缓冲区时,会收到一个 `error` 事件,其 type 为 `server_error`、code 为 `stream_interrupted`,随后流会关闭。套接字写入阻塞五秒也会关闭流。执行过程绝不会等待读取方。
-- **密钥重新检查。** 打开的流在空闲期间以及发送输出前,每秒最多重新检查一次原始 Project 密钥。撤销密钥或归档 Project 会关闭流,身份验证失败也会关闭流。重新检查使用正常的五秒身份验证超时,并且等待期间不会发送任何会话数据。已经发送的字节无法收回。
-- **仅根工作。** 子 Turn 和子 Item 不发布会话事件;`agent.session.subagent.*` 事件和根协调 Item 会发布。请通过 [Subagent 资源](subagents.md)读取子工作。
+- **生命周期。** 流会跨 Turn 保持打开,并在 Turn 失败后继续存在。流会在 Session 被删除时,或在 [Environment 初始化失败](#environment-initialization-failure)产生终止 `agent.session.failed` 后结束;在该失败之后打开的流会保持打开。每 15 秒发送一次 keepalive 注释。
+- **缓冲区。** Core 为每个 Session 最多保留 256 个事件和 64 MiB 事件,必要时还会额外容纳一个更大的事件。读取方落后于缓冲区时,会收到一个 `error` 事件,其 type 为 `server_error`、code 为 `stream_interrupted`,随后流会关闭。套接字写入阻塞五秒也会关闭流。执行过程绝不会等待读取方。
+- **密钥重新检查。** 打开的流在空闲期间以及发送输出前,每秒最多重新检查一次原始项目 API 密钥。撤销密钥或归档项目会关闭流,身份验证失败也会关闭流。重新检查使用正常的五秒身份验证超时,并且等待期间不会发送任何 Session 数据。已经发送的字节无法收回。
+- **仅根工作。** 子 Turn 和子 Item 不发布 Session 事件;`agent.session.subagent.*` 事件和根协调 Item 会发布。请通过 [Subagent 资源](subagents.md)读取子工作。
### 事件规则 {#event-rules}
-- 会话事件携带 `event_id`、`type`,以及该次状态转换时的 `session` 快照。Turn 事件携带 `session_id` 和 `turn_id`;环境(Environment)事件携带 `session_id` 和值为 null 的 `turn_id`。不存在 Turn `waiting` 事件。
-- 新 Turn 会在一个事务中依次发布 `agent.session.turn.created`、用户条目的 `item.added`、`agent.session.in_progress`,然后发布 `agent.session.turn.in_progress`。当一个批次包含多条消息时,后续消息对应的条目事件会排在会话活动之后。
+- Session 事件携带 `event_id`、`type`,以及该次状态转换时的 `session` 快照。Turn 事件携带 `session_id` 和 `turn_id`;Environment 事件携带 `session_id` 和值为 null 的 `turn_id`。不存在 Turn `waiting` 事件。
+- 新 Turn 会在一个事务中依次发布 `agent.session.turn.created`、用户 Item 的 `item.added`、`agent.session.in_progress`,然后发布 `agent.session.turn.in_progress`。当一个批次包含多条消息时,后续消息对应的Item 事件会排在 Session 活动之后。
- Turn 终止事件(`completed`、`failed`、`cancelled`)携带顶层的 `usage`,其值复制自当时的 Turn 快照;未知时为 null。其他事件省略此字段。
- `item.added` 和 `item.done` 始终携带 `output_index`;输入 Item 的该值为 null。函数结果只发出 `item.added`;`item.done` 用于代理输出。
- 助手消息遵循以下单一顺序:先发送 `content` 为空的进行中 `item.added`,再发送文本为空的 `content_part.added`,然后发送 `output_text.delta` 事件、`output_text.done`、`content_part.done` 和 `item.done`。首次观察时已完整的消息(例如结构化输出)会在一个 `output_text.delta` 中逐字节发送全部文本。完整文本会替换此前累积的增量。
- Codex 命令输出以 `agent.output.command_execution_output.delta` 流式传输,并携带命令的 Item ID 和输出索引。原生输出配额和文本转换规则适用,因此这些增量并非逐字节捕获的原始结果;完整 Item 才是权威结果。
- 已取消或失败的 Turn 会将其未完成的 Item 标记为 `incomplete`,并保留其部分内容。
-- 函数调用会一直保留在 `required_actions` 中,直到 harness 应用其结果,或取消操作或 Turn 结束将其移除。重复通知不会发出新状态。
+- 函数调用会一直保留在 `required_actions` 中,直到 Harness 应用其结果,或取消操作或 Turn 结束将其移除。重复通知不会发出新状态。
-## 轮次与条目 {#turns-and-items}
+## Turn 与 Item {#turns-and-items}
-Turn 和 Item 列表接受 `after`、`limit` 和 `order`([列表规则](wire-semantics.md))。游标是同一会话内的 ID。
+Turn 和 Item 列表接受 `after`、`limit` 和 `order`([列表规则](wire-semantics.md))。游标是同一 Session 内的 ID。
-**Turn。** 会话 Turn 路由只包含根 Turn,按创建时间、再按 ID 排序;在该路由中使用子 Turn ID 会返回 404。失败的 Turn 包含 `error: {code: "internal_error", message: "The execution could not complete."}`,绝不包含引擎原始诊断信息。管理员可通过[会话诊断](session-diagnostics.md)读取失败类别。
+**Turn。** Session Turn 路由只包含根 Turn,按创建时间、再按 ID 排序;在该路由中使用子 Turn ID 会返回 404。失败的 Turn 包含 `error: {code: "internal_error", message: "The execution could not complete."}`,绝不包含引擎原始诊断信息。管理员可通过[Session 诊断](session-diagnostics.md)读取失败类别。
-**Item。** Item 按首次观察时间、再按其在会话中的位置、最后按 ID 排序。更新和重试绝不会移动 Item,也不会更改其 `output_index`;`output_index` 是 Item 在该 Turn 输出 Item 中从零开始的位置,输入 Item 没有此值。读取操作使用已存储的历史索引,绝不会根据原生日志重新构建该索引。Item 列表包含仍在进行中或尚未完成的 Item。
+**Item。** Item 按首次观察时间、再按其在 Session 中的位置、最后按 ID 排序。更新和重试绝不会移动 Item,也不会更改其 `output_index`;`output_index` 是 Item 在该 Turn 输出 Item 中从零开始的位置,输入 Item 没有此值。读取操作使用已存储的历史索引,绝不会根据原生日志重新构建该索引。Item 列表包含仍在进行中或尚未完成的 Item。
| Item `type` | 内容 |
| --- | --- |
-| `message` | 用户或助手内容片段。harness 报告阶段时,`phase` 为其阶段(`commentary`、`final_answer`),否则为 null |
+| `message` | 用户或助手内容片段。Harness 报告阶段时,`phase` 为其阶段(`commentary`、`final_answer`),否则为 null |
| `command_execution` | 命令、报告的输出、退出代码、持续时间和工作目录 |
| `mcp_call` | 服务器和工具标识、参数、结构化结果或错误 |
| `function_call`、`function_call_output` | 关联的调用及其结果。结果始终携带 `output` 和 `error`;提交时省略这些字段则值为 null。存储的结果会保留提交时字段是否存在的信息。原生文件更改显示为 `apply_patch` 函数调用,更改内容作为参数,不会生成虚构结果 |
| `web_search_call` | 支持的操作字段(`search`、`open_page`、`find_in_page`、`other`) |
| `reasoning`、`agent_message` 和 Subagent 协调调用 | 见 [Subagents](subagents.md)。`agent_message` 没有状态;reasoning 状态可以为 null |
-工具失败不会导致其 Turn 失败。会话的 Project 可以读取工具输出,其中可能包含该工具自己的诊断文本。
+工具失败不会导致其 Turn 失败。Session 的项目可以读取工具输出,其中可能包含该工具自己的诊断文本。
## 使用量 {#usage}
-Turn 和会话的 `usage` 使用固定的 `TokenUsage` 字段:输入、缓存输入、输出、推理输出和令牌总数。`null` 表示未知,绝不表示零。
+Turn 和 Session 的 `usage` 使用固定的 `TokenUsage` 字段:输入、缓存输入、输出、推理输出和 token 总数。`null` 表示未知,绝不表示零。
-- **Turn 使用量**是 harness 为该 Turn 报告的最新完整快照。新快照会替换旧快照;重复快照绝不会累加。存储的快照在取消和 Worker 重启后仍会保留。
-- **会话使用量**是所有根 Turn 均已结束(完成、失败或取消)且使用量已知时,各根 Turn 使用量的总和。只要有根 Turn 正在排队、运行或等待,它就为 null;一旦某个根 Turn 在没有使用量的情况下结束,它就会持续保持 null。Subagent Turn 不计入其中。
-- **按 harness 划分。** Codex 会在 Turn 运行期间及其结束时报告测量快照;在任何使用量报告之前被中断的 Turn 会保持 null。Claude Code 和 MiniMax Code 不报告完整的公开明细,因此其使用量为 null。
+- **Turn 使用量**是 Harness 为该 Turn 报告的最新完整快照。新快照会替换旧快照;重复快照绝不会累加。存储的快照在取消和 Worker 重启后仍会保留。
+- **Session 使用量**是所有根 Turn 均已结束(完成、失败或取消)且使用量已知时,各根 Turn 使用量的总和。只要有根 Turn 正在排队、运行或等待,它就为 null;一旦某个根 Turn 在没有使用量的情况下结束,它就会持续保持 null。Subagent Turn 不计入其中。
+- **按 Harness 划分。** Codex 会在 Turn 运行期间及其结束时报告测量快照;在任何使用量报告之前被中断的 Turn 会保持 null。Claude Code 和 MiniMax Code 不报告完整的公开明细,因此其使用量为 null。
使用量是对已报告测量值进行的尽力核算。它不是账单,Core 绝不会估算缺失的使用量。
@@ -147,8 +147,8 @@ Turn 和会话的 `usage` 使用固定的 `TokenUsage` 字段:输入、缓存
| --- | --- |
| `agent.session.environment.failed` | `error: {type: "environment_error", code: "environment_connection_failed", message: "The environment failed to connect."}` |
| `error` | `error: {type: "environment_error", code: "sandbox_error", message: , param: null}` |
-| `agent.session.failed` | 该会话:`status: "failed"`,失败原因为 `error`,`required_actions: []`,失败时间为 `last_active_at` |
+| `agent.session.failed` | 该 Session:`status: "failed"`,失败原因为 `error`,`required_actions: []`,失败时间为 `last_active_at` |
-会话读取和列表操作会返回同一个会话,正在等待 Environment 的输入也会在同一快照中结算为失败。GET 流和创建流会在 `agent.session.failed` 之后结束。新输入会返回 409([输入错误](#input-errors));该会话可以被删除。
+Session 读取和列表操作会返回同一个 Session,正在等待 Environment 的输入也会在同一快照中结算为失败。GET 流和创建流会在 `agent.session.failed` 之后结束。新输入会返回 409([输入错误](#input-errors));该 Session 可以被删除。
[Environment 初始化契约](environments.md#initialization-state-and-failure)定义了固定的失败原因。
diff --git a/contracts/agents-api/zh/source-files.md b/contracts/agents-api/zh/source-files.md
index 659b40456..6f8e1f59c 100644
--- a/contracts/agents-api/zh/source-files.md
+++ b/contracts/agents-api/zh/source-files.md
@@ -4,21 +4,21 @@ source: contracts/agents-api/source-files.md
source_hash: 320216a4e7ac0d1e3e2455dfe622e0f91576ea1d0aa00d11911683b0e98387f1
---
-Files(`/v1/files`)和 Skills(`/v1/skills`)是具有独立生命周期的 Project 资源,不依赖 Session。File 保存上传字节,Environment 通过 ID 复制它们。Skill 保存不可变、版本化的包,由 Template 和 Session 引用。Project 的所有 API 密钥共享这些资源。
+Files(`/v1/files`)和 Skills(`/v1/skills`)是具有独立生命周期的项目资源,不依赖 Session。File 保存上传字节,Environment 通过 ID 复制它们。Skill 保存不可变、版本化的包,由模板和 Session 引用。项目的所有 API 密钥共享这些资源。
-这些路由遵循 [upstream.json](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/contracts/agents-api/upstream.json) 中固定版本 SDK:[Files 资源](https://github.com/openai/openai-python/blob/d7c41efee1b0802b79f3f88a678ef2052b06e9ce/src/openai/resources/files.py)、[创建参数](https://github.com/openai/openai-python/blob/d7c41efee1b0802b79f3f88a678ef2052b06e9ce/src/openai/types/file_create_params.py)、[FileObject](https://github.com/openai/openai-python/blob/d7c41efee1b0802b79f3f88a678ef2052b06e9ce/src/openai/types/file_object.py) 和 [Skills 资源](https://github.com/openai/openai-python/tree/d7c41efee1b0802b79f3f88a678ef2052b06e9ce/src/openai/resources/skills)。要求 Project API 密钥,不要求 `OpenAI-Beta` 头。不存在 ID 与其他 Project 的 ID 返回相同的 404。
+这些路由遵循 [upstream.json](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/contracts/agents-api/upstream.json) 中固定版本 SDK:[Files 资源](https://github.com/openai/openai-python/blob/d7c41efee1b0802b79f3f88a678ef2052b06e9ce/src/openai/resources/files.py)、[创建参数](https://github.com/openai/openai-python/blob/d7c41efee1b0802b79f3f88a678ef2052b06e9ce/src/openai/types/file_create_params.py)、[FileObject](https://github.com/openai/openai-python/blob/d7c41efee1b0802b79f3f88a678ef2052b06e9ce/src/openai/types/file_object.py) 和 [Skills 资源](https://github.com/openai/openai-python/tree/d7c41efee1b0802b79f3f88a678ef2052b06e9ce/src/openai/resources/skills)。要求项目 API 密钥,不要求 `OpenAI-Beta` 头。不存在 ID 与其他项目的 ID 返回相同的 404。
## 文件 {#files}
| 操作 | 行为 |
| --- | --- |
| `POST /files` | Multipart 上传,包含一个 `file` 部分和 `purpose=user_data`,顺序不限。返回 200 和 File |
-| `GET /files` | 列出 Project 的 File,不读取字节 |
+| `GET /files` | 列出项目的 File,不读取字节 |
| `GET /files/{file_id}` | 返回 File |
| `GET /files/{file_id}/content` | 400 `Not allowed to download files of purpose: user_data`,code 与 param 为 null。先检查 ID,因此 File 不存在时返回 404 |
| `DELETE /files/{file_id}` | 删除 File 及其字节;返回 `{"id": …, "object": "file", "deleted": true}` |
-将 File ID 传给 [Environment 文件](environment-files.md#create-a-file),或 Template、Session 的初始 `files`([Environment](environments.md))来使用文件。复制在内部读取字节;公开下载仍被拒绝。
+将 File ID 传给 [Environment 文件](environment-files.md#create-a-file),或模板、Session 的初始 `files`([Environment](environments.md))来使用文件。复制在内部读取字节;公开下载仍被拒绝。
### 上传 {#upload}
@@ -44,7 +44,7 @@ Files(`/v1/files`)和 Skills(`/v1/skills`)是具有独立生命周期的
| 参数 | 规则 |
| --- | --- |
| `order` | `desc`(默认)或 `asc`,按创建时间再按 ID 排序 |
-| `after` | 此 Project 可见的 File ID |
+| `after` | 此项目可见的 File ID |
| `purpose` | `user_data`、`assistants`、`batch`、`fine-tune`、`vision`、`evals`、`assistants_output`、`batch_output`、`fine-tune-results` 之一。其他值(包括不同大小写)在解析游标前返回 400,`param: "purpose"`。非 `user_data` 值返回空页。空值表示不筛选 |
响应为 `{"object": "list", "data": [...], "first_id", "last_id", "has_more"}`;空页的 ID 为 null。`limit`、查询解析及其错误遵循共享[列表规则](wire-semantics.md#lists)。
@@ -91,16 +91,16 @@ curl "$OPENAI_BASE_URL/skills" -H "Authorization: Bearer $OPENAI_API_KEY" -F fil
- 条目为普通文件或目录,使用规范相对路径。链接、特殊文件、绝对路径、`..` 组件和重复项被拒绝。
- 限制:压缩后 5 MiB,展开后 20 MiB,500 个文件,以及含目录在内的 1,000 个 ZIP 条目。
-Core 将每个版本的包加密并绑定到 Project、Skill 与版本。ZIP 上传保留可执行位;目录上传以 mode 0644 存储文件。
+Core 将每个版本的包加密并绑定到项目、Skill 与版本。ZIP 上传保留可执行位;目录上传以 mode 0644 存储文件。
### 版本与元数据 {#versions-and-metadata}
-- 版本号从 1 开始,每次上传加一,即使最新版本删除也不复用。Template 和 Session 选择器按数字指定版本,复用数字可能使保存的选择器指向不同字节。
+- 版本号从 1 开始,每次上传加一,即使最新版本删除也不复用。模板和 Session 选择器按数字指定版本,复用数字可能使保存的选择器指向不同字节。
- Skill 的 `name` 和 `description` 来自默认版本。通过 `POST /skills/{skill_id}` 或 `default=true` 上传修改默认版本时,指针和两个字段一起更新;`id` 和 `created_at` 不变。
- `latest_version` 是剩余版本中的最大版本号。
- 同一 Skill 的上传与删除串行执行,删除不会移除已确认上传的版本。
-Template 和 Session 如何选择版本(默认、`latest` 或数字)并冻结字节,见 [Environment](environments.md#skills-plugins-and-environment-mcp)。
+模板和 Session 如何选择版本(默认、`latest` 或数字)并冻结字节,见 [Environment](environments.md#skills-plugins-and-environment-mcp)。
### 删除版本 {#delete-a-version}
@@ -111,4 +111,4 @@ Template 和 Session 如何选择版本(默认、`latest` 或数字)并冻
| 其他版本 | 200,响应体相同。若为最新版本,`latest_version` 回退到剩余最大版本号 |
| 不存在或属于其他范围的 Skill 或版本 | 404 |
-删除 Skill 或版本不改变已安装它的 Session;Template 保留所存储引用。
+删除 Skill 或版本不改变已安装它的 Session;模板保留所存储引用。
diff --git a/contracts/agents-api/zh/subagents.md b/contracts/agents-api/zh/subagents.md
index 5c6128be2..90322bfc7 100644
--- a/contracts/agents-api/zh/subagents.md
+++ b/contracts/agents-api/zh/subagents.md
@@ -1,40 +1,40 @@
---
-title: "子智能体"
+title: "子 Agent"
source: contracts/agents-api/subagents.md
source_hash: 8fed8b73a8403d2ccf80354b2a981f11240eba3c10d5a0257206a39d048b92a7
---
-启用 `multi_agent.enabled` 后,Harness 可以启动原生子智能体。Core 通过锁定版本的 SDK(见 [`upstream.json`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/contracts/agents-api/upstream.json))中的六项 Subagent 读取操作公开它们,并根据适配器观察结果记录它们。当 `multi_agent.enabled=false` 时,Runtime 会移除原生子智能体工具。[Harness capabilities](harness-capabilities.md) 列出各 Harness 在哪些组合中支持子智能体。
+启用 `multi_agent.enabled` 后,Harness 可以启动原生子 Agent。Core 通过锁定版本的 SDK(见 [`upstream.json`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/contracts/agents-api/upstream.json))中的六项 Subagent 读取操作公开它们,并根据适配器观察结果记录它们。当 `multi_agent.enabled=false` 时,Runtime 会移除原生子 Agent 工具。[Harness capabilities](harness-capabilities.md) 列出各 Harness 在哪些组合中支持子 Agent。
## 公开读取 {#public-reads}
-所有路径都位于 `/v1/agents/sessions/{session_id}` 下,并且需要与普通 Session 读取相同的 Project 身份验证和 `OpenAI-Beta: agents=v1`。
+所有路径都位于 `/v1/agents/sessions/{session_id}` 下,并且需要与普通 Session 读取相同的项目身份验证和 `OpenAI-Beta: agents=v1`。
| 路径 | 结果 |
| --- | --- |
-| `/subagents` | 直接子智能体、嵌套子智能体和已关闭的子智能体 |
-| `/subagents/{subagent_id}` | 单个子智能体 |
-| `/subagents/{subagent_id}/items` | 仅该子智能体自身的 Items |
-| `/subagents/{subagent_id}/turns` | 仅该子智能体自身的 Turns |
+| `/subagents` | 直接子 Agent、嵌套子 Agent 和已关闭的子 Agent |
+| `/subagents/{subagent_id}` | 单个子 Agent |
+| `/subagents/{subagent_id}/items` | 仅该子 Agent 自身的 Items |
+| `/subagents/{subagent_id}/turns` | 仅该子 Agent 自身的 Turns |
| `/subagents/{subagent_id}/turns/{turn_id}` | 一个所属 Turn |
-| `/subagents/{subagent_id}/turns/{turn_id}/items` | 该 Turn 中仅属于该子智能体的 Items |
+| `/subagents/{subagent_id}/turns/{turn_id}/items` | 该 Turn 中仅属于该子 Agent 的 Items |
-列表使用 `after`、`limit`(默认 20)和 `order`(默认 `desc`),并返回 `object: "list"`、`data`、`first_id`、`last_id`(空页面时为 null)和 `has_more`。对于 1–100 范围之外的 `limit`,Subagent 和 Subagent Turn 列表会使用 `limit must be between 1 and 100` 拒绝请求;与 Session Items 一样,两个 Item 列表会将 0 视为 1,并将更大的值视为 100。游标必须属于所请求的 Project、Session、子智能体以及可选的 Turn。
+列表使用 `after`、`limit`(默认 20)和 `order`(默认 `desc`),并返回 `object: "list"`、`data`、`first_id`、`last_id`(空页面时为 null)和 `has_more`。对于 1–100 范围之外的 `limit`,Subagent 和 Subagent Turn 列表会使用 `limit must be between 1 and 100` 拒绝请求;与 Session Items 一样,两个 Item 列表会将 0 视为 1,并将更大的值视为 100。游标必须属于所请求的项目、Session、子 Agent 以及可选的 Turn。
-## 子智能体可见性 {#subagent-visibility}
+## 子 Agent 可见性 {#subagent-visibility}
-子级工作仅出现在子智能体路由上。
+子级工作仅出现在子 Agent 路由上。
- Session 的 `turns.list` 和 `turns.retrieve` 仅返回根级 Turns。将子级 Turn ID 作为路径参数或列表游标使用时,会返回与不存在的 Turn 相同的 404;Core 的 404 消息与官方消息不同。
- Session 事件流和创建流仅传输根级工作:子级 Turns 及其 Items 不会发布任何 `agent.session.turn.*` 或 Item 内容事件。`agent.session.subagent.*` 事件和根级协调 Items 仍会保留。创建流仍会在根级收敛到 idle 状态时结束。
- 子级 Turn 的 `agent_id` 是 Session 的 Agent ID(即直接子级的 `parent_agent_id`,也是 `create_subagent_call` 的 `agent_id`);`subagent_id` 标识该子级。嵌套子级遵循相同规则。根级 Turns 带有 `subagent_id: null`。
- Session Items 始终归根级所有;继承的原生父级对话记录不属于子级工作。Session 用量仅汇总根级 Turns。
-Active 状态包含 idle 状态。成功关闭会记录原生时间;成功重新打开会保留身份和 `opened_at`、清除 `closed_at`,并且只发出一次 `active`。恢复处于 active 状态的子智能体不会执行任何操作。Turn 完成、中断和进程释放绝不会关闭子智能体。未知的 token 度量值保持为 null。
+Active 状态包含 idle 状态。成功关闭会记录原生时间;成功重新打开会保留身份和 `opened_at`、清除 `closed_at`,并且只发出一次 `active`。恢复处于 active 状态的子 Agent 不会执行任何操作。Turn 完成、中断和进程释放绝不会关闭子 Agent。未知的 token 度量值保持为 null。
## 适配器契约 {#adapter-contract}
-适配器通过 `internal/agentdaemon/proto/subagents.go`,利用现有的已认证 Run 和执行日志报告子智能体事实。不存在单独的传输机制、调度器或模型与工具循环。
+适配器通过 `internal/agentdaemon/proto/subagents.go`,利用现有的已认证 Run 和执行日志报告子 Agent 事实。不存在单独的传输机制、调度器或模型与工具循环。
| 事实 | 适配器义务 |
| --- | --- |
@@ -44,7 +44,7 @@ Active 状态包含 idle 状态。成功关闭会记录原生时间;成功重
| 子级 Item | 使用中立词汇提供有序且完整的消息或工具快照 |
| 协调 | 转换原生操作以及操作者和接收者身份,但不得在 Core 中放入原生工具名称 |
-Core 根据已授权的 Session 绑定关系分配合公开 ID 和所有权。身份、生命周期、子级历史和实时事件投影在 Session 锁和执行租约下原子提交。重复观察会保留其 ID,且不会重复生成生命周期事件;检测到冲突效果时操作失败。对不存在子级的失败协调请求会保留其不透明的请求目标,并且不会创建子智能体。
+Core 根据已授权的 Session 绑定关系分配合公开 ID 和所有权。身份、生命周期、子级历史和实时事件投影在 Session 锁和执行租约下原子提交。重复观察会保留其 ID,且不会重复生成生命周期事件;检测到冲突效果时操作失败。对不存在子级的失败协调请求会保留其不透明的请求目标,并且不会创建子 Agent。
子级 Turns 由原生写入方负责,因此它们与 Core 的工作队列分开存储,绝不会成为另一项排队执行。Session Turn 读取直接查询根级 Turns。公开 GET 读取持久化资源;它们绝不会启动原生进程或重放执行。
diff --git a/contracts/agents-api/zh/vaults.md b/contracts/agents-api/zh/vaults.md
index dc500fb7c..4f598f528 100644
--- a/contracts/agents-api/zh/vaults.md
+++ b/contracts/agents-api/zh/vaults.md
@@ -4,11 +4,11 @@ source: contracts/agents-api/vaults.md
source_hash: b27509949dca26f064cda765ea97229e3325dee3ff650b17fa332a756409cf34
---
-Vault 是 Project 所有的 Credential 容器。Credential 保存一个 HTTPS MCP server 的秘密:`static_bearer` token 或 `mcp_oauth` grant。Session 在 `vault_ids` 中关联 Vault;Core 在创建 Session 时为每个 HTTP MCP server 选择一个 Credential,只在分派工作时将解密 token 交给 Runtime。秘密只能写入:任何读取都不返回 token、refresh token、client secret 或密文。
+Vault 是项目所有的 Credential 容器。Credential 保存一个 HTTPS MCP server 的秘密:`static_bearer` token 或 `mcp_oauth` grant。Session 在 `vault_ids` 中关联 Vault;Core 在创建 Session 时为每个 HTTP MCP server 选择一个 Credential,只在分派工作时将解密 token 交给 Runtime。秘密只能写入:任何读取都不返回 token、refresh token、client secret 或密文。
-应用负责 OAuth 授权与同意、服务方撤销以及审批策略。Core 不提供授权重定向、回调、撤销或公开刷新端点;创建或替换 Credential 不联系 MCP server 或 OAuth provider。
+应用负责 OAuth 授权与同意、服务方撤销以及审批策略。Core 不提供授权重定向、回调、撤销或公开刷新端点;创建或替换 Credential 不联系 MCP server 或 OAuth 提供商。
-## 存储并使用凭证 {#store-and-use-a-credential}
+## 存储并使用凭据 {#store-and-use-a-credential}
```python
vault = client.beta.agents.vaults.create(name="internal")
@@ -36,11 +36,11 @@ session = client.beta.agents.sessions.create(
)
```
-MCP tool 可以通过 `credential_id` 指定 Credential;未指定时,Core 选择已关联 Credential 中 `mcp_server_url` 等于 tool 的 `server_url` 的凭证([选择规则](#credential-selection-in-a-session))。能够连接该 server 的 Harness 和 placement 取决于 tool 的 `connection_origin`([MCP 连接来源](environments.md#public-mcp-connection-origin))。
+MCP tool 可以通过 `credential_id` 指定 Credential;未指定时,Core 选择已关联 Credential 中 `mcp_server_url` 等于 tool 的 `server_url` 的凭据([选择规则](#credential-selection-in-a-session))。能够连接该 server 的 Harness 和 placement 取决于 tool 的 `connection_origin`([MCP 连接来源](environments.md#public-mcp-connection-origin))。
## 路由 {#routes}
-所有路由位于 `/v1`,使用 Project API key,要求 `OpenAI-Beta: agents=v1`。Project 的 key 共享其 Vault;其他 Project 的 Vault 或 Credential 与不存在的资源一样返回 404。
+所有路由位于 `/v1`,使用项目 API 密钥,要求 `OpenAI-Beta: agents=v1`。项目的所有密钥共享其 Vault;其他项目的 Vault 或 Credential 与不存在的资源一样返回 404。
| 操作 | 路由 | 结果 |
| --- | --- | --- |
@@ -54,7 +54,7 @@ MCP tool 可以通过 `credential_id` 指定 Credential;未指定时,Core
| 替换秘密 | `POST /vaults/{vault_id}/credentials/{credential_id}` | Credential |
| 删除 Credential | `DELETE /vaults/{vault_id}/credentials/{credential_id}` | `{id, object: "vault.credential.deleted", deleted: true}` |
-格式错误、缺失或其他 Project 的 ID 返回 404 `not_found_error`;通过非所属 Vault 访问 Credential 也一样。两个列表按创建时间、再按 ID 排序,按 `status`(`active`、`archived` 或二者)筛选;[列表规则](wire-semantics.md#lists)说明分页和筛选细节。Core 私有保存 status,默认 `active`,没有归档 Vault 或 Credential 的操作。Credential 的 status 独立于 Vault。
+格式错误、缺失或其他项目的 ID 返回 404 `not_found_error`;通过非所属 Vault 访问 Credential 也一样。两个列表按创建时间、再按 ID 排序,按 `status`(`active`、`archived` 或二者)筛选;[列表规则](wire-semantics.md#lists)说明分页和筛选细节。Core 私有保存 status,默认 `active`,没有归档 Vault 或 Credential 的操作。Credential 的 status 独立于 Vault。
## Vault {#vaults}
@@ -104,9 +104,9 @@ Credential 读取包含 `id`、`vault_id`、`name`、`object: "vault.credential"
更新时改变 Credential 的 `auth.type` 返回 400。
-## Session 中的凭证选择 {#credential-selection-in-a-session}
+## Session 中的凭据选择 {#credential-selection-in-a-session}
-创建 Session 时,`vault_ids` 列出 Session 可以使用凭证的 Vault。省略、`null` 和 `[]` 均不关联任何 Vault;条目为 `null` 无效;每个 Vault 必须属于 Project,否则创建返回 404 `not_found_error`。Agent 上保存 `credential_id` 不提供授权;只有 Session 的关联提供授权。
+创建 Session 时,`vault_ids` 列出 Session 可以使用凭据的 Vault。省略、`null` 和 `[]` 均不关联任何 Vault;条目为 `null` 无效;每个 Vault 必须属于项目,否则创建返回 404 `not_found_error`。Agent 上保存 `credential_id` 不提供授权;只有 Session 的关联提供授权。
创建 Session 时,Core 为每个 HTTP MCP tool 从已关联 Vault 中选择 Credential:
@@ -118,16 +118,16 @@ Credential 读取包含 `id`、`vault_id`、`name`、`object: "vault.credential"
| 情况 | 响应 |
| --- | --- |
| `credential_id` 没有关联 Vault | 400 `invalid_request_error`: `MCP credential_id requires an attached vault` |
-| `credential_id` 缺失、格式错误、属于其他 Project 或未关联 Vault | 400 `invalid_request_error`: `MCP credential_id was not found in an attached vault` |
+| `credential_id` 缺失、格式错误、属于其他项目或未关联 Vault | 400 `invalid_request_error`: `MCP credential_id was not found in an attached vault` |
| Credential 在已关联 Vault 内,但 URL 不同 | 400 `invalid_request_error`: `MCP credential_id does not match server_url ` |
| 未指定 `credential_id` 时匹配多个 Credential | 409 `conflict_error`: `multiple attached vault credentials match MCP server_url ; specify credential_id` |
-| `vault_ids` 中的 Vault 未知或属于其他 Project | 404 `not_found_error` |
+| `vault_ids` 中的 Vault 未知或属于其他项目 | 404 `not_found_error` |
`` 和 `` 仅在请求值不超过 256 字节且为可打印 UTF-8 时原样返回,否则消息省略它们。缺失、其他范围、未关联和格式错误的情况,对同一 ID 给出逐字节相同响应,因此引用不泄露调用方未关联 Vault 的信息。URL 不匹配消息中的 URL 来自 tool。
Session 固定其关联和每次选择,包括匿名选择。后续 Vault 变化不会重新选择:相同的创建重试返回原 Session 和选择。Session 查询、列表和事件快照在 tool 的 `credential_id` 中显示隐式选择的 Credential ID,即使该 Credential 已删除;匿名 tool 显示 `null`,显式 ID 按提交值读取。存储请求保留调用方值,因此重试比较原请求。
-每次分派时,Core 重新检查 Project、已关联 Vault、选中 Credential、type 和确切 URL,然后只在 Runtime 执行请求中解密 token。Session、配置和历史的读取从不包含 token。选中 Credential 的 server 只能运行在声明 `mcp_http_bearer_auth` 的 Runtime 上。Credential 缺失、解密失败或刷新失败会使工作失败;Core 不退回其他 Credential 或匿名连接。
+每次分派时,Core 重新检查项目、已关联 Vault、选中 Credential、type 和确切 URL,然后只在 Runtime 执行请求中解密 token。Session、配置和历史的读取从不包含 token。选中 Credential 的 server 只能运行在声明 `mcp_http_bearer_auth` 的 Runtime 上。Credential 缺失、解密失败或刷新失败会使工作失败;Core 不退回其他 Credential 或匿名连接。
## OAuth 刷新 {#oauth-refresh}
@@ -139,12 +139,12 @@ Token endpoint 必须为 HTTPS。Core 解析主机,拒绝回环、私有、链
## 存储密钥 {#storage-key}
-Core 使用安装的 [`secrets/core/credential.key`](../../../docs/zh/configuration.md#compose-installations),以 AES-256-GCM 加密每个 token、refresh token 和 client secret,绑定 Project、Vault、Credential、auth type 和 `mcp_server_url`。错误密钥、修改的行或移动到其他绑定的行均无法解密。名称是不参与绑定的元数据。key 和明文 token 存在于可信服务内存中;加密保护存储的秘密,不保护已被攻破的服务主机。
+Core 使用安装的 [`secrets/core/credential.key`](../../../docs/zh/configuration.md#compose-installations),以 AES-256-GCM 加密每个 token、refresh token 和 client secret,绑定项目、Vault、Credential、auth type 和 `mcp_server_url`。错误密钥、修改的行或移动到其他绑定的行均无法解密。名称是不参与绑定的元数据。key 和明文 token 存在于可信服务内存中;加密保护存储的秘密,不保护已被攻破的服务主机。
-key 文件不可读或格式错误会使 Core 启动失败。丢失或替换 key 使全部已存储秘密无法使用。读取、列表、删除、Vault 操作、新建 Credential 和替换 `static_bearer` token 仍可用;`mcp_oauth` 更新返回 500 `internal_error`,需要旧秘密的派发会失败。已保存的 E2B 密钥同样失效:托管 Session 返回 503 `execution_unavailable`,直到你打开 **Settings** → **Sandbox and scheduling**,选择 **Reset deployment**(必要时选择 **Force — cancel remaining work now**)并重新配置后端;遗留的沙箱按其 E2B 超时过期。Core 只支持一个 key,不支持轮换或重新加密。
+key 文件不可读或格式错误会使 Core 启动失败。丢失或替换 key 使全部已存储秘密无法使用。读取、列表、删除、Vault 操作、新建 Credential 和替换 `static_bearer` token 仍可用;`mcp_oauth` 更新返回 500 `internal_error`,需要旧秘密的派发会失败。已保存的 E2B 密钥同样失效:托管 Session 返回 503 `execution_unavailable`,直到你打开 **设置** → **沙箱与调度**,选择 **重置部署**(必要时选择 **强制 — 立即取消剩余任务**)并重新配置沙箱提供商;遗留的沙箱按其 E2B 超时过期。Core 只支持一个 key,不支持轮换或重新加密。
## 删除 {#deletion}
-删除 Credential 或其 Vault 会移除凭证行,但不会擦除 PostgreSQL 页面、WAL、备份或原生历史中的秘密。此后查询、更新和重复删除返回 404;列表不再包含它;新 Session 不能选择它;不能在已删除 Vault 中创建新 Credential。
+删除 Credential 或其 Vault 会移除凭据行,但不会擦除 PostgreSQL 页面、WAL、备份或原生历史中的秘密。此后查询、更新和重复删除返回 404;列表不再包含它;新 Session 不能选择它;不能在已删除 Vault 中创建新 Credential。
现有 Session 保留固定的关联和选择,历史仍可读。下一次需要已删除 Credential 的分派失败;Core 不选择其他 Credential,也不匿名连接。删除不取消运行中的工作、不收回已发送 Runtime 的 token,也不在服务方撤销 grant;需要时自行取消 Session 并撤销 grant。已撤销或无效 OAuth grant 同样失败,直到被替换。
diff --git a/contracts/agents-api/zh/wire-semantics.md b/contracts/agents-api/zh/wire-semantics.md
index d688f9444..e448eac7b 100644
--- a/contracts/agents-api/zh/wire-semantics.md
+++ b/contracts/agents-api/zh/wire-semantics.md
@@ -1,7 +1,7 @@
---
title: "Core 协议行为"
source: contracts/agents-api/wire-semantics.md
-source_hash: bed64f05b6e52ab5774063f649173b4a42c0a2da4038bc273f595f81c5dbd128
+source_hash: 13d033e194fe4316dfaeced837907b594e4c95d93ebbf9ef9078f47b42cbec92
---
已锁定版本的 OpenAI Python SDK([upstream.json](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/contracts/agents-api/upstream.json))定义了 `/v1` 路由、字段和类型。本页面说明这些类型未作规定之处 Core 的行为,例如状态码、错误字段、默认值和列表边界,以及 Core 与官方服务存在差异的地方。[coverage ledger](index.md) 列出了这些差异和尚存缺口;[Sessions, events and history](sessions-events.md)、[message content](message-content.md)、[Vaults](vaults.md)、[source Files and Skills](source-files.md) 和 [Environment files and Artifacts](environment-files.md) 分别负责各自资源的规则。
@@ -22,7 +22,7 @@ source_hash: bed64f05b6e52ab5774063f649173b4a42c0a2da4038bc273f595f81c5dbd128
| `/v1` 下的未知子路由,包括带尾斜杠的情况 | 在 Beta 和身份验证检查后返回 404、代码 `unsupported_operation`。 |
| `OPTIONS` 和 CORS | 不处理 CORS。 |
-创建 Agent、Vault、Credential、Environment Template、Environment 文件或 Session 均返回 201,流式 Session 创建也是如此。对 Agent 或 Environment Template 发送空更新正文会推进 `updated_at`,但不会更改其他内容;时间戳精确到秒。
+创建 Agent、Vault、Credential、Environment 模板、Environment 文件或 Session 均返回 201,流式 Session 创建也是如此。对 Agent 或 Environment 模板发送空更新正文会推进 `updated_at`,但不会更改其他内容;时间戳精确到秒。
### 标头 {#headers}
@@ -40,23 +40,23 @@ Beta 路由要求 `OpenAI-Beta` 标头中恰好有一个值,且该值必须等
### 身份验证 {#authentication}
-`/v1` 仅接受 Project API 密钥,形式为 `Authorization: Bearer `。同一 Project 的所有密钥都视为同一调用方:它们共享该 Project 的资源和 Session 创建重试。Core 在每次请求时都在数据库中解析密钥及其 Project,不缓存凭据,超时时间为五秒。撤销密钥或归档其 Project 会在下一次请求时生效。Project 的所有密钥都使用主体 `service_account/project:`。[Projects and keys](admin-api.md#projects-and-keys) 介绍了密钥管理。
+`/v1` 仅接受项目 API 密钥,形式为 `Authorization: Bearer `。同一项目的所有密钥都视为同一调用方:它们共享该项目的资源和 Session 创建重试。Core 在每次请求时都在数据库中解析密钥及其项目,不缓存凭据,超时时间为五秒。撤销密钥或归档其项目会在下一次请求时生效。项目的所有密钥都使用主体 `service_account/project:`。[项目与密钥](admin-api.md#projects-and-keys) 介绍了密钥管理。
可选的 `OpenAI-Organization` 和 `OpenAI-Project` 标头在发送时必须各出现一次,并分别等于 `core` 和 `proj_`;任何其他值都会导致密钥被拒绝。
| 失败情况 | 响应 |
| --- | --- |
-| 未提供密钥、使用其他方案、`Authorization` 标头为空或重复、密钥未知或已撤销、密钥属于已归档的 Project、使用 Core 密钥,或作用域标头不匹配 | 401,`type` 为 `invalid_request_error`,消息为 "A valid Agents API bearer key is required.",`WWW-Authenticate: Bearer`。在 Beta 路由上,`code` 为 null。在 Files and Skills 上,当发送且被拒绝的 Bearer 凭据恰好只有一个时,`code` 为 `invalid_api_key`;其他情况下为 null。 |
+| 未提供密钥、使用其他方案、`Authorization` 标头为空或重复、密钥未知或已撤销、密钥属于已归档的项目、使用 Core 密钥,或作用域标头不匹配 | 401,`type` 为 `invalid_request_error`,消息为 "A valid Agents API bearer key is required.",`WWW-Authenticate: Bearer`。在 Beta 路由上,`code` 为 null。在 Files and Skills 上,当发送且被拒绝的 Bearer 凭据恰好只有一个时,`code` 为 `invalid_api_key`;其他情况下为 null。 |
| 密钥查找失败,例如数据库不可用 | 503,`type` 为 `server_error`,`code` 为 `authentication_unavailable` |
### 请求正文 {#request-bodies}
-每个 `/v1` JSON 路由在路由解码、验证或查找之前都会经过一个正文门禁:Agent 创建和更新、Vault 创建、Credential 创建和更新、Environment Template 创建和更新、Environment 文件创建、Session 创建和更新,以及 Session 事件。DELETE 路由、multipart Files 和 Skills 上传以及 Skill 更新使用各自的读取器。除下述 413 大小错误外,门禁错误均返回 400,`type` 和 `code` 为 `invalid_request_error`,param 为 null。
+每个 `/v1` JSON 路由在路由解码、验证或查找之前都会经过一个正文门禁:Agent 创建和更新、Vault 创建、Credential 创建和更新、Environment 模板创建和更新、Environment 文件创建、Session 创建和更新,以及 Session 事件。DELETE 路由、multipart Files 和 Skills 上传以及 Skill 更新使用各自的读取器。除下述 413 大小错误外,门禁错误均返回 400,`type` 和 `code` 为 `invalid_request_error`,param 为 null。
| 顺序 | 情况 | 响应 |
| --- | --- | --- |
| 1 | `Content-Type` 缺失、不是 JSON 或格式错误,包括无正文的 `POST`。`application/json` 和 `application/*+json` 不区分大小写,并允许附带参数 | "expected request with Content-Type: application/json" |
-| 2 | 正文超过路由限制:Session 创建和 Environment Templates 为 16 MiB,文件创建采用 [Environment file](environment-files.md) 的限制,其他路由为 1 MiB | 413,代码 `request_too_large` |
+| 2 | 正文超过路由限制:Session 创建和 Environment 模板为 16 MiB,文件创建采用 [Environment file](environment-files.md) 的限制,其他路由为 1 MiB | 413,代码 `request_too_large` |
| 3 | 无效 UTF-8 | "Invalid body: encountered a unicode decode error when parsing this JSON value. Please check the value to ensure it is valid unicode." |
| 4 | JSON 格式错误、尾随数据、两个值、字节顺序标记、仅含空白字符的正文,或形成孤立 UTF-16 代理项的转义 | "Invalid body: failed to parse JSON value. Please check the value to ensure it is valid JSON. (Common errors include trailing commas, missing closing brackets, missing quotation marks, etc.)" |
| 5 | 一个对象内任意深度出现重复键 | `"Invalid body: duplicate JSON key '' at ''. Duplicate JSON keys are not supported."` 路径使用 `.` 连接对象键并省略数组索引,例如 `metadata.k` 或 `tools.type`。键在反转义后按大小写敏感方式比较。报告文档顺序中首次出现的重复键。 |
@@ -95,7 +95,7 @@ Beta 路由要求 `OpenAI-Beta` 标头中恰好有一个值,且该值必须等
| Agent `name` 超过 128 个字符 | Param 为 `name`。允许使用空名称和未去除首尾空白的名称。 |
| metadata 键或值中包含 U+0000 | Param 为 `metadata.` |
| 其他任何存储字符串或查询筛选条件中包含 U+0000 或无效 UTF-8 | Param 为 null,消息为 "Request text contains characters this service cannot store or compare, such as U+0000 or invalid UTF-8."。不会写入任何内容。PostgreSQL 无法存储 U+0000,而官方服务允许存储。 |
-| Environment Template 或 Session 内联网络配置被拒绝:通配符、端口、方案、IPv6、空主机、没有域名的 `restricted` 策略、超过 100 个域名,或域名使用其他访问模式 | Param 为 null,并使用 Core 的消息 |
+| Environment 模板或 Session 内联网络配置被拒绝:通配符、端口、方案、IPv6、空主机、没有域名的 `restricted` 策略、超过 100 个域名,或域名使用其他访问模式 | Param 为 null,并使用 Core 的消息 |
| Session 更新正文为空 | "At least one update field is required" |
## 列表 {#lists}
@@ -118,7 +118,7 @@ Vault 和 Credential 列表接受标量 `status`、`status[]` 条目或两者,
| 列表 | 默认值 | 接受范围 | 其他值 |
| --- | --- | --- | --- |
-| Agents、Sessions、Items、Environment Templates、Subagent Items、Subagent Turn Items | 20 | 1–100 | 0 变为 1;大于 100 的值变为 100 |
+| Agents、Sessions、Items、Environment 模板、Subagent Items、Subagent Turn Items | 20 | 1–100 | 0 变为 1;大于 100 的值变为 100 |
| Vaults、Credentials | 20 | 1–100 | 0、负数和更大的整数,包括溢出值,都会限制在 1–100 范围内 |
| Turns、Subagents、Subagent Turns、Artifacts | 20 | 1–100 | 400 `invalid_request_error`,"limit must be between 1 and 100" |
| Skills、Skill 版本 | 20 | 0–100 | 0 返回空页面,其 `has_more` 表示游标后是否还有资源。负数:400 `integer_below_min_value`,param 为 `limit`。大于 100:400 `integer_above_max_value`,param 为 `limit` |
@@ -132,7 +132,7 @@ Vault 和 Credential 列表接受标量 `status`、`status[]` 条目或两者,
| 列表 | 响应 |
| --- | --- |
-| Agents、Sessions、Turns、Environment Templates、Vaults、Credentials | 404,`type` 和 `code` 均为 `not_found_error`,"Resource not found." |
+| Agents、Sessions、Turns、Environment 模板、Vaults、Credentials | 404,`type` 和 `code` 均为 `not_found_error`,"Resource not found." |
| Session Items、Subagent Items、Subagent Turn Items | 400 `invalid_request_error`,param 为 null,"Invalid session item ID in `after`" |
| Subagents、Subagent Turns | 400 `invalid_request_error`,param 为 null,"Invalid resource ID in `after`" |
| Session Artifacts | 400 `invalid_request_error`,param 为 null,"after is not a valid artifact ID" |
@@ -209,11 +209,11 @@ Session 的有效配置还必须通过执行准入,无论配置来自保存还
### 配置快照 {#configuration-snapshot}
-Session 创建会将 Agent 的有效配置复制到不可变快照中。使用 `agent_id` 时,已保存的 Agent 只会读取一次;内联 `agent` 中的字段会整体替换已保存字段,包括数组,而 null `tools` 会清空列表。省略的字段会继承保存值;如果内联 `x_agents_core` 省略 `harness`,则保留已保存的 harness。已保存的 Agent metadata 永远不会成为 Session metadata。后续更新或删除 Agent 只会影响新的 Session。
+Session 创建会将 Agent 的有效配置复制到不可变快照中。使用 `agent_id` 时,已保存的 Agent 只会读取一次;内联 `agent` 中的字段会整体替换已保存字段,包括数组,而 null `tools` 会清空列表。省略的字段会继承保存值;如果内联 `x_agents_core` 省略 `harness`,则保留已保存的 Harness。已保存的 Agent metadata 永远不会成为 Session metadata。后续更新或删除 Agent 只会影响新的 Session。
`stream` 默认为 false。`stream` 和 `agent_id` 不能为 null。省略或 null 的 `metadata` 为 `{}`。
-创建过程会在查找创建重试之前,验证正文和 metadata 类型、请求字段及初始输入,以及放置和流式输入要求。对于新工作,Core 会解析 Template、已保存的 Agent 和模型配置,绑定 Vault Credential,然后验证所选 Harness 和执行配置,再执行写入。依赖项查找失败时会重新检查重试标识,以确保已经提交的创建仍可恢复。
+创建过程会在查找创建重试之前,验证正文和 metadata 类型、请求字段及初始输入,以及放置和流式输入要求。对于新工作,Core 会解析模板、已保存的 Agent 和模型配置,绑定 Vault Credential,然后验证所选 Harness 和执行配置,再执行写入。依赖项查找失败时会重新检查重试标识,以确保已经提交的创建仍可恢复。
### 创建重试 {#creation-retries}
@@ -221,11 +221,11 @@ Session 创建会将 Agent 的有效配置复制到不可变快照中。使用 `
| 情况 | 响应 |
| --- | --- |
-| 键、请求和 Project 均相同 | 返回 201以及 Session 的当前状态。不会再次接纳任何输入。`stream=true` 的重试返回 201,不含任何事件并关闭连接。 |
+| 键、请求和项目均相同 | 返回 201以及 Session 的当前状态。不会再次接纳任何输入。`stream=true` 的重试返回 201,不含任何事件并关闭连接。 |
| 键相同但请求不同 | 409 `idempotency_conflict` |
| 删除 Session 后使用相同键 | 409 `idempotency_conflict` |
-键的作用域限定为 Project;该 Project 的任何键,包括轮换后签发的键,都可以用于重试。如果请求包含缺少 `model` 的内联 Agent,或者指定了已保存的 Agent、Template、初始文件或准备配置、`vault_ids` 或凭据引用、`x_agents_core`,或者 `openai_hosted` 环境,则会在读取上述任何来源之前按发送内容进行比较:即使 Agent、Template、Credential 或 deployment 默认值已更改或删除,匹配的重试仍会返回原有 Session。其他请求则按解析后的配置进行比较。模型提供商密钥仅以指纹形式参与比较。
+键的作用域限定为项目;该项目的任何键,包括轮换后签发的键,都可以用于重试。如果请求包含缺少 `model` 的内联 Agent,或者指定了已保存的 Agent、模板、初始文件或准备配置、`vault_ids` 或凭据引用、`x_agents_core`,或者 `openai_hosted` 环境,则会在读取上述任何来源之前按发送内容进行比较:即使 Agent、模板、Credential 或 deployment 默认值已更改或删除,匹配的重试仍会返回原有 Session。其他请求则按解析后的配置进行比较。模型提供商密钥仅以指纹形式参与比较。
### 更新和列表 {#update-and-list}
diff --git a/docs/api/public-agent-api.md b/docs/api/public-agent-api.md
index ae52db1da..9c754bb67 100644
--- a/docs/api/public-agent-api.md
+++ b/docs/api/public-agent-api.md
@@ -45,7 +45,7 @@ On a shared host, `-H @<(printf 'Authorization: Bearer %s\n' "$OPENAI_API_KEY")`
| Resource | Path | What it is |
| --- | --- | --- |
-| [Agents](#agents) | `/agents` | Reusable configuration: model, instructions, tools, harness |
+| [Agents](#agents) | `/agents` | Reusable configuration: model, instructions, tools, Harness |
| [Sessions](#sessions) | `/agents/sessions` | One agent conversation with its own Environment |
| [Input events](#send-input) | `/agents/sessions/{id}/events` (POST) | Messages, cancellation and tool results |
| [Event stream](#stream-events) | `/agents/sessions/{id}/events` (GET) | Live server-sent events |
@@ -138,27 +138,27 @@ Every response carries `X-Request-Id`; include it when reporting a problem.
### Core extensions: `x_agents_core`
-Core runs several harnesses and accepts your own model access. Those settings are the only additions to the OpenAI shapes, and they sit inside `x_agents_core`:
+Core runs several Harnesses and accepts your own model access. Those settings are the only additions to the OpenAI shapes, and they sit inside `x_agents_core`:
| Field | Where | Value |
| --- | --- | --- |
| `harness` | Agent, or a Session's inline `agent` | `codex`, `claude_sdk` or `mcode` |
-| `model_provider` | Agent, or Session creation (top level) | `protocol`, `base_url`, `api_key`, and for `mcode` also `context_window` and `max_output_tokens`. The protocol must be one of the harness's native protocols |
-| `harness_config` | Agent, inline `agent`, or Session creation (top level, wins) | The harness's native model parameters, such as Codex's `model_reasoning_effort` |
+| `model_provider` | Agent, or Session creation (top level) | `protocol`, `base_url`, `api_key`, and for `mcode` also `context_window` and `max_output_tokens`. The protocol must be one of the Harness's native protocols |
+| `harness_config` | Agent, inline `agent`, or Session creation (top level, wins) | The Harness's native model parameters, such as Codex's `model_reasoning_effort` |
| `environment` | `openai_hosted` or `self_hosted` Session creation (top level) | Portable preparation: `environment_template_id`, `files`, `env`, `packages`, `setup_commands`, `skills`, `plugins`, `capability_directories`. A field may not also appear in `environment`; see [Environments](../../contracts/agents-api/environments.md#preparation-order) |
| `installation` | Read-only, on `self_hosted` Sessions | Short-lived install commands for your machine; see [self-hosted execution](../getting-started/self-hosted.md) |
Any other member is rejected with 400. `api_key` is write-only: reads return `api_key_configured`. `harness_config` replaces the whole object; `{}` clears it. With the SDK, pass these through `extra_body`.
-## Choose a harness and a model
+## Choose a Harness and a model
-The harness is the agent program that runs a Session: Codex (`codex`), Claude Code (`claude_sdk`) or MiniMax Code (`mcode`). Set `x_agents_core.harness` on the Agent or the inline `agent`; without it, the installation's default harness applies ([`OAC_DEFAULT_HARNESS`](../configuration.md#settings), Codex unless the operator changed it).
+The Harness is the agent program that runs a Session: Codex (`codex`), Claude Code (`claude_sdk`) or MiniMax Code (`mcode`). Set `x_agents_core.harness` on the Agent or the inline `agent`; without it, the installation's default Harness applies ([`OAC_DEFAULT_HARNESS`](../configuration.md#settings), Codex unless the operator changed it).
-- **Model.** `model` is the provider's exact model ID. An inline Agent on an `openai_hosted` or `none` Session may omit it to use the default model configuration of its harness. A saved Agent always needs one.
-- **Provider.** The harness calls your provider directly, with one of the harness's native protocols; there is no conversion, and a mismatch is rejected when the Session is created. [Model execution](../../contracts/agents-api/model-execution.md#saved-defaults-and-precedence) lists each harness's protocols and which provider a Session uses on each Environment type. A Session freezes its provider at creation.
-- **Native parameters.** `harness_config` carries the harness's own model settings; see [native model parameters](../../contracts/agents-api/model-execution.md#native-model-parameters).
+- **Model.** `model` is the provider's exact model ID. An inline Agent on an `openai_hosted` or `none` Session may omit it to use the default model configuration of its Harness. A saved Agent always needs one.
+- **Provider.** The Harness calls your provider directly, with one of the Harness's native protocols; there is no conversion, and a mismatch is rejected when the Session is created. [Model execution](../../contracts/agents-api/model-execution.md#saved-defaults-and-precedence) lists each Harness's protocols and which provider a Session uses on each Environment type. A Session freezes its provider at creation.
+- **Native parameters.** `harness_config` carries the Harness's own model settings; see [native model parameters](../../contracts/agents-api/model-execution.md#native-model-parameters).
-Not every combination of harness, placement and operation is supported; the [Harness capabilities](../../contracts/agents-api/harness-capabilities.md) lists them.
+Not every combination of Harness, placement and operation is supported; the [Harness capabilities](../../contracts/agents-api/harness-capabilities.md) lists them.
## Agents
@@ -200,7 +200,7 @@ oac "/agents" -d '{
- **Update** changes only the fields you send. `metadata` replaces all pairs; `null` clears `name` or `instructions`.
- **Delete** keeps existing Sessions.
-- **Tools** are functions, MCP servers, `tool_search` (Claude) and `web_search` with `mode: "disabled"`. Support depends on harness and Environment; see [execution tools](../../contracts/agents-api/execution-tools.md).
+- **Tools** are functions, MCP servers, `tool_search` (Claude) and `web_search` with `mode: "disabled"`. Support depends on Harness and Environment; see [execution tools](../../contracts/agents-api/execution-tools.md).
## Sessions
@@ -529,17 +529,17 @@ client.beta.agents.vaults.credentials.create(
session = client.beta.agents.sessions.create(environment={"type": "none"}, input="...", vault_ids=[vault.id], agent_id=agent.id)
```
-The HTTP path is `/vaults`, with the Beta header. A Session selects credentials from its `vault_ids`, optionally by `credential_id`; the MCP server's URL must match the selected credential's `mcp_server_url` exactly in either case. The [Vaults contract](../../contracts/agents-api/vaults.md) owns selection, errors, OAuth refresh and deletion. An MCP tool's `connection_origin` decides whether Core's side or the workspace connects to the server, and each harness supports a different set: see [MCP connection origin](../../contracts/agents-api/environments.md#public-mcp-connection-origin).
+The HTTP path is `/vaults`, with the Beta header. A Session selects credentials from its `vault_ids`, optionally by `credential_id`; the MCP server's URL must match the selected credential's `mcp_server_url` exactly in either case. The [Vaults contract](../../contracts/agents-api/vaults.md) owns selection, errors, OAuth refresh and deletion. An MCP tool's `connection_origin` decides whether Core's side or the workspace connects to the server, and each Harness supports a different set: see [MCP connection origin](../../contracts/agents-api/environments.md#public-mcp-connection-origin).
## Diagnose a failure
1. Read the Session's `status` and `error`, and the latest Turn's `error`. A failed Turn reports only a generic `internal_error`.
-2. Check that the Environment is connected and its harness is available.
-3. Check the harness, model and tool combination in [Harness capabilities](../../contracts/agents-api/harness-capabilities.md).
+2. Check that the Environment is connected and its Harness is available.
+3. Check the Harness, model and tool combination in [Harness capabilities](../../contracts/agents-api/harness-capabilities.md).
4. Ask the administrator for the Session's [diagnostics](../../contracts/agents-api/session-diagnostics.md), which name the failure category, and to check [troubleshooting](../getting-started/operations.md#troubleshooting) for service logs, credentials and node readiness.
A 401 usually means a key from another namespace; see [API namespaces and credentials](./index.md).
## Differences from OpenAI
-Core differs from the OpenAI service in some behavior, such as Session creation idempotency and harness-specific tool support. The [coverage ledger](../../contracts/agents-api/index.md#differences-from-openai) lists every difference and the per-resource status; the [public OpenAPI](../../contracts/agents-api/openapi.yaml) has the exact schemas.
+Core differs from the OpenAI service in some behavior, such as Session creation idempotency and Harness-specific tool support. The [coverage ledger](../../contracts/agents-api/index.md#differences-from-openai) lists every difference and the per-resource status; the [public OpenAPI](../../contracts/agents-api/openapi.yaml) has the exact schemas.
diff --git a/docs/configuration.md b/docs/configuration.md
index 5a4922346..80f4e6858 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -6,7 +6,7 @@ Every setting of a Core installation has exactly one home, in one of three categ
| Category | Examples | Home | Change it with | Takes effect |
| --- | --- | --- | --- | --- |
-| [Process settings](#process-settings) | Public URL, ports, logging, harnesses, execution concurrency, audit retention, OAuth origins, Runtime history | `.env` in the installation directory (default `~/.oac/core`) | Edit `.env`, then run `oac apply` | `oac apply` recreates the services that read the changed settings |
+| [Process settings](#process-settings) | Public URL, ports, logging, Harnesses, execution concurrency, audit retention, OAuth origins, Runtime history | `.env` in the installation directory (default `~/.oac/core`) | Edit `.env`, then run `oac apply` | `oac apply` recreates the services that read the changed settings |
| [Secrets](#compose-installations) | Database password, credential encryption key, installation ID, Core key and the Core key digest derived from it | `secrets/` in the Compose data volume, one copy each | Initialization generates them once; `oac rotate-core-key` replaces the Core key and its digest | `oac rotate-core-key` restarts Core and Web |
| [Runtime settings](#runtime-settings-web) | Sandbox backend and size, nodes, Projects and keys, default models, executor credentials | Core's PostgreSQL database | Web, or the Core API (`/core/v1`) with the Core key | Saved without a Core restart; nodes prepare Runtime changes asynchronously |
@@ -98,10 +98,10 @@ Runtime settings live in Core's database. Change them in Web; scripts use the sa
| Idle suspension | **Settings** → **Sandbox and scheduling** → **Automatic suspension** → **Idle before suspension (seconds)** → **Save** | `PATCH /core/v1/sandbox/deployment` | Deployment-wide; see [suspension policy](../contracts/agents-api/sandbox-deployment.md#suspension-policy) |
| Independent workspace storage and tenant capacity | **Settings → Workspace storage** | `/core/v1/workspace-storage` | See [independent workspace storage](#independent-workspace-storage); existing workspaces retain their configuration |
| Projects and API keys | **Projects and keys**: **Create project**, **Rename**, **Issue key**, **Revoke**, **Archive** | `/core/v1/projects` | Keys are shown once; Core stores digests |
-| Default model per harness | **Settings** → **Models and credentials**: **Set** | `/core/v1/harnesses/{harness}/model-configuration` | See [Default models](#default-models) |
+| Default model per Harness | **Settings** → **Models and credentials**: **Set** | `/core/v1/harnesses/{harness}/model-configuration` | See [Default models](#default-models) |
| Executor credentials of a self-hosted Session | **Session log**, then the **Session** page: **Executor credentials** | `/core/v1/projects/{project_id}/environments/{environment_id}/executor-credentials` | See [self-hosted executors](./getting-started/self-hosted.md) |
-Which harnesses are enabled, and the default one, are process settings (`OAC_HARNESSES`, `OAC_DEFAULT_HARNESS`); **Settings → Service and deployment** lists them under **Startup settings**. **Settings → Models and credentials** marks each harness **Ready** once it is enabled and has a default model, and otherwise names the missing step: **Model provider not set** or **Disabled**. The [Core administration API](../contracts/agents-api/admin-api.md) lists every Core API route, and the [deployment contract](../contracts/agents-api/sandbox-deployment.md) defines the sandbox fields, limits and change rules.
+Which Harnesses are enabled, and the default one, are process settings (`OAC_HARNESSES`, `OAC_DEFAULT_HARNESS`); **Settings → Service and deployment** lists them under **Startup settings**. **Settings → Models and credentials** marks each Harness **Ready** once it is enabled and has a default model, and otherwise names the missing step: **Model provider not set** or **Disabled**. The [Core administration API](../contracts/agents-api/admin-api.md) lists every Core API route, and the [deployment contract](../contracts/agents-api/sandbox-deployment.md) defines the sandbox fields, limits and change rules.
### Independent workspace storage
diff --git a/docs/development.md b/docs/development.md
index aaaa25d60..e8f000747 100644
--- a/docs/development.md
+++ b/docs/development.md
@@ -111,11 +111,11 @@ For frontend development, run `pnpm dev:web` using the fixture or Core connectio
| `services/core/internal/persistence`, `services/core/internal/db` and `services/core/migrations` | Core's PostgreSQL adapters, transactions, queries and migrations | [Service guide](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/services/core/README.md#database) |
| `services/core/tests/integration` | Tests that drive the HTTP boundaries, the execution Worker and the PostgreSQL adapters together | [Service guide](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/services/core/README.md#tests) |
| `services/core/internal/execution` | Durable Turn dispatch and scheduling | [Runtime protocol](./runtime-protocol.md) |
-| `services/core/internal/engine` | Pure qualification of harness operations and placements | [Harness onboarding](../contracts/agents-api/harness-onboarding.md) |
+| `services/core/internal/engine` | Pure qualification of Harness operations and placements | [Harness onboarding](../contracts/agents-api/harness-onboarding.md) |
| `internal/agentdaemon/proto` | Core–Runtime wire types and validators | [Runtime protocol](./runtime-protocol.md) |
| `internal/runtimebootstrap` | Provider-to-Runtime startup input | [Runtime bootstrap](./runtime-bootstrap.md) |
| `apps/daemon/internal/dispatch` | Runtime preparation, Executor reuse, Turn and cleanup ownership | [Harness lifecycle](../contracts/agents-api/harness-onboarding.md#required-adapter-interfaces) |
-| `apps/daemon/internal/agent` | Native harness adapters | [Native references](../contracts/agents-api/harness-onboarding.md#native-references) |
+| `apps/daemon/internal/agent` | Native Harness adapters | [Native references](../contracts/agents-api/harness-onboarding.md#native-references) |
| `services/core/internal/sandbox` | Provider interfaces and managed compute lifecycle | [Provider onboarding](./sandbox-provider.md) |
| `services/web` | Console login and the server-side management proxy | [Console server](./web/console-server.md) |
| `apps/web` and `packages/agents-client` | Console UI and typed clients | [Web guide](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/apps/web/README.md) |
diff --git a/docs/examples.md b/docs/examples.md
index 2b2f5f97c..67fd2c34a 100644
--- a/docs/examples.md
+++ b/docs/examples.md
@@ -23,7 +23,7 @@ Each feature maps to one part of the API. Read the code next to the guide sectio
| Feature | API used | Guide | Code |
| --- | --- | --- | --- |
| Server-side key and headers | Bearer key, `OpenAI-Beta`, route allowlist | [Before you start](./api/public-agent-api.md#before-you-start) | [`server.mjs`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/example/parsar/server.mjs) |
-| Agents with a harness and model | `x_agents_core.harness`, `model_provider` | [Core extensions](./api/public-agent-api.md#core-extensions-x_agents_core) | [`server/sessions.mjs`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/example/parsar/server/sessions.mjs) |
+| Agents with a Harness and model | `x_agents_core.harness`, `model_provider` | [Core extensions](./api/public-agent-api.md#core-extensions-x_agents_core) | [`server/sessions.mjs`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/example/parsar/server/sessions.mjs) |
| Sessions on three runtimes | `openai_hosted`, `none`, `self_hosted` with `workspace_directory` | [Create a Session](./api/public-agent-api.md#create-a-session) | [`server/sessions.mjs`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/example/parsar/server/sessions.mjs) |
| Crash-safe Session creation | `Idempotency-Key`, recovery from a lost response | [Idempotency](./api/public-agent-api.md#idempotency) | [`server/sessions.mjs`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/example/parsar/server/sessions.mjs) |
| Live replies | Event stream, text deltas, reconnect and reconcile | [Stream events](./api/public-agent-api.md#stream-events) | [`src/lib/live-session.ts`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/example/parsar/src/lib/live-session.ts) |
diff --git a/docs/getting-started/index.md b/docs/getting-started/index.md
index 60d1cb117..f4f3bd1ce 100644
--- a/docs/getting-started/index.md
+++ b/docs/getting-started/index.md
@@ -24,7 +24,7 @@ Application developers call the API with a Project API key, and can run Sessions
| Guide | Covers |
| --- | --- |
| [Quickstart](./quickstart.md) | From a Project API key to a finished Session |
-| [Agents API guide](../api/public-agent-api.md) | Common tasks, harness and model choice, and every resource with SDK and HTTP examples |
+| [Agents API guide](../api/public-agent-api.md) | Common tasks, Harness and model choice, and every resource with SDK and HTTP examples |
| [Self-hosted execution](./self-hosted.md) | Running a Session on your own machine |
| [Examples](../examples.md) | Complete applications built on the API |
| [API index](../api/index.md) | All three namespaces and their credentials |
diff --git a/docs/getting-started/install.md b/docs/getting-started/install.md
index 74c22d6a6..f7771bb40 100644
--- a/docs/getting-started/install.md
+++ b/docs/getting-started/install.md
@@ -82,7 +82,7 @@ Applications, nodes and sandboxes reach Core at one address, the public URL. HTT
## Set a default model
-Core-hosted Sessions without their own model provider use their harness's default model. In **Settings → Models and credentials**, under **Default model configuration**, find the harness marked **Default** (Codex unless you changed `OAC_DEFAULT_HARNESS`); it shows **Model provider not set**. Choose **Set** and enter the model ID, the protocol, and the provider's base URL and API key. MiniMax Code also needs the context window and max output tokens. The harness then shows **Ready**. See [default models](../configuration.md#default-models).
+Core-hosted Sessions without their own model provider use their Harness's default model. In **Settings → Models and credentials**, under **Default model configuration**, find the Harness marked **Default** (Codex unless you changed `OAC_DEFAULT_HARNESS`); it shows **Model provider not set**. Choose **Set** and enter the model ID, the protocol, and the provider's base URL and API key. MiniMax Code also needs the context window and max output tokens. The Harness then shows **Ready**. See [default models](../configuration.md#default-models).
## Issue a Project API key
diff --git a/docs/getting-started/operations.md b/docs/getting-started/operations.md
index 265f70ef9..205fbbcf3 100644
--- a/docs/getting-started/operations.md
+++ b/docs/getting-started/operations.md
@@ -36,7 +36,7 @@ Use these observations for different questions:
| Environment connection | The Runtime transport is connected |
| A finished Turn and its results | The task's recorded outcome |
-Service health does not show that a harness or a model works. Use Session, Turn, Items and Usage reads for execution, and Web's **Nodes** page for node connection, readiness and placement. For local diagnosis, use the installation's own Compose file:
+Service health does not show that a Harness or a model works. Use Session, Turn, Items and Usage reads for execution, and Web's **Nodes** page for node connection, readiness and placement. For local diagnosis, use the installation's own Compose file:
```sh
docker compose -f "$HOME/.oac/core/compose.yaml" ps --all
@@ -95,7 +95,7 @@ core() ( # core METHOD PATH [JSON body]
| Issue an API key (shown once, as `key`) | `core POST /projects/$PROJECT_ID/keys '{"name": "prod"}'` |
| Revoke a key | `core DELETE /projects/$PROJECT_ID/keys/$KEY_ID` |
| Archive a Project (revokes all keys) | `core POST /projects/$PROJECT_ID/archive` |
-| See harnesses and their default models | `core GET /harnesses` |
+| See Harnesses and their default models | `core GET /harnesses` |
| Set Codex's default model | `core PUT /harnesses/codex/model-configuration '{"model": "your-model-id", "model_provider": {"protocol": "responses", "base_url": "https://provider.example/v1", "api_key": "sk-..."}}'` |
| Installation facts, including the API base URL | `core GET /installation` |
@@ -203,7 +203,7 @@ Installation and mutating `oac` commands share the [installation lock](../config
| `Installation and data retained at …` | Read the service logs above it, fix the cause, then [resume installation](./install.md#install); keep the data |
| Web answers 403 `Forbidden` | The browser host is not `OAC_PUBLIC_URL`. Open that origin; a reverse proxy must pass the original Host |
| Web shows that Core is unavailable (502) | Core is stopped or failing: `docker compose ps`, then Core's log |
-| Session creation returns 400 `model_provider_required` | No model provider: set a [default model](../configuration.md#default-models) for the harness, or pass one; self-hosted Sessions always pass their own |
+| Session creation returns 400 `model_provider_required` | No model provider: set a [default model](../configuration.md#default-models) for the Harness, or pass one; self-hosted Sessions always pass their own |
| Add node shows no command | See [Before you add a node](./nodes.md#before-you-add-a-node) |
| A node is not ready | See [node troubleshooting](./nodes.md#troubleshooting) |
diff --git a/docs/getting-started/quickstart.md b/docs/getting-started/quickstart.md
index 3a4535628..a3028a577 100644
--- a/docs/getting-started/quickstart.md
+++ b/docs/getting-started/quickstart.md
@@ -7,7 +7,7 @@ This walkthrough takes you from a Project API key to an agent that has created a
- a Project API key and the API base URL, from your administrator ([Issue a Project API key](./install.md#issue-a-project-api-key));
- a ready node or E2B backend, so Core has somewhere to run the agent ([Nodes](./nodes.md));
- Python 3.9 or newer;
-- a model: the installation's default model, or your own provider's model ID, base URL and API key. [Model execution](../../contracts/agents-api/model-execution.md#saved-defaults-and-precedence) says which one a Session uses and which protocols each harness speaks.
+- a model: the installation's default model, or your own provider's model ID, base URL and API key. [Model execution](../../contracts/agents-api/model-execution.md#saved-defaults-and-precedence) says which one a Session uses and which protocols each Harness speaks.
The example uses Codex, whose model provider must speak the OpenAI Responses API.
@@ -46,7 +46,7 @@ curl "$OPENAI_BASE_URL/agents" -H "OpenAI-Beta: agents=v1" \
## 2. Start a Session
-A Session is one agent conversation with its own workspace. With `openai_hosted`, Core creates a sandbox for it on a node or E2B and starts the harness inside.
+A Session is one agent conversation with its own workspace. With `openai_hosted`, Core creates a sandbox for it on a node or E2B and starts the Harness inside.
With the installation's default model, skip this. To use your own provider:
diff --git a/docs/web/console-api-usage.md b/docs/web/console-api-usage.md
index 4ee0d20fd..879018c5d 100644
--- a/docs/web/console-api-usage.md
+++ b/docs/web/console-api-usage.md
@@ -89,11 +89,11 @@ Summary figures are cumulative per Session and are not billing records. Sessions
| Operation | Route | Console use |
| --- | --- | --- |
-| List harnesses | `GET /core/v1/harnesses` | Settings → Models and credentials default model cards: each harness's readiness (Ready when `enabled` and its model configuration is set, otherwise Model provider not set or Disabled), `default`, its model configuration without the key, and Usage details from the configuration's `last_used_at`, `last_error_code` and `last_error_at`; the Overview's Getting started (the default harness is Ready, or any harness when none is default) |
+| List Harnesses | `GET /core/v1/harnesses` | Settings → Models and credentials default model cards: each Harness's readiness (Ready when `enabled` and its model configuration is set, otherwise Model provider not set or Disabled), `default`, its model configuration without the key, and Usage details from the configuration's `last_used_at`, `last_error_code` and `last_error_at`; the Overview's Getting started (the default Harness is Ready, or any Harness when none is default) |
| Set or replace | `PUT /core/v1/harnesses/{harness}/model-configuration` | **Set** or **Replace**: the complete model configuration with its write-only provider key, never prefilled and never retried; a 400 shows Core's message in the form; then the list is read again |
| Clear | `DELETE /core/v1/harnesses/{harness}/model-configuration` | **Clear**, confirmed, then the list is read again |
-The list carries each harness's configuration, so the console does not read `GET /core/v1/harnesses/{harness}/model-configuration`.
+The list carries each Harness's configuration, so the console does not read `GET /core/v1/harnesses/{harness}/model-configuration`.
## Workspace storage
@@ -151,4 +151,4 @@ Its help tips and coverage notes state what a request is and what is not counted
- Any `/v1/**` route, including Session creation, Session events and their stream, message input, function results and cancellation.
- Creation or update of Agents, Environment templates, Skills, Files, Vaults or Credentials, including uploads and Credential token replacement.
- Single Turn reads, Artifacts, Session execution configuration, Environment Files and administrative Session archive.
-- The administrator audit log (`GET /core/v1/audit-log`). Settings shows the installation, each harness's default model and the sandbox deployment instead.
+- The administrator audit log (`GET /core/v1/audit-log`). Settings shows the installation, each Harness's default model and the sandbox deployment instead.
diff --git a/docs/web/index.md b/docs/web/index.md
index 19c1c8a98..c87352c39 100644
--- a/docs/web/index.md
+++ b/docs/web/index.md
@@ -36,7 +36,7 @@ Missing data is shown as missing (—), never as zero. [Console API usage](./con
| Give the installation an HTTPS address | Set `OAC_PUBLIC_URL` and point a reverse proxy at Web; see [Make Core reachable](../getting-started/install.md#configure-the-domain-and-https) |
| Choose the sandbox backend (microsandbox, E2B or Docker), the sandbox size and Runtime, or reset the backend | **Settings → Sandbox and scheduling**; see [change the sandbox configuration](../getting-started/nodes.md#change-the-sandbox-configuration) |
| Add, resize or remove execution nodes | **Nodes**: **Add node**, **Edit node** and removal; see the [nodes guide](../getting-started/nodes.md) |
-| Set the default model of a harness | **Settings → Models and credentials**; see [default models](../configuration.md#default-models) |
+| Set the default model of a Harness | **Settings → Models and credentials**; see [default models](../configuration.md#default-models) |
| Create a Project and issue its API keys | **Projects and keys**; see [Projects and API keys](../getting-started/operations.md#projects-and-api-keys) |
| Issue, rotate or revoke a self-hosted executor's credential, or copy its install command | The Session's page in the **Session log**; see [self-hosted executors](../getting-started/self-hosted.md) |
| Delete a resource, for example a leaked Credential | The resource's row in its list, or its page; Files are deleted from the Files list. The public deletion rules apply |
diff --git a/docs/zh/api/index.md b/docs/zh/api/index.md
index 6837204f5..c5cfd3f60 100644
--- a/docs/zh/api/index.md
+++ b/docs/zh/api/index.md
@@ -8,13 +8,13 @@ Core 提供三个命名空间。每个命名空间都有一种调用方及其独
| 命名空间 | 调用方 | 凭据 | 内容 | 所有者 |
| --- | --- | --- | --- | --- |
-| `/v1` | 应用程序:业务系统和官方 OpenAI SDK | Project API key | 固定版本官方 Agents API 中全部且仅有的 58 个方法和路径对,列于 [upstream-routes.json](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/contracts/agents-api/upstream-routes.json)。仅属于 Core 的字段位于 `x_agents_core` 中:`harness`、`model_provider`、`harness_config`、`environment`,以及只读的 Session `installation` | [Agents API 指南](public-agent-api.md) |
-| `/core/v1` | Web 的控制台服务器和操作员脚本 | [Core key](../getting-started/operations.md#core-key) | 安装信息、Project 和密钥、资源读取和删除、Session 归档、执行器凭据、默认模型、指标、请求日志、审计、沙箱部署和节点、独立工作区存储配置 | [Core 管理 API](../../../contracts/agents-api/zh/admin-api.md) |
+| `/v1` | 应用程序:业务系统和官方 OpenAI SDK | 项目 API 密钥 | 固定版本官方 Agents API 中全部且仅有的 58 个方法和路径对,列于 [upstream-routes.json](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/contracts/agents-api/upstream-routes.json)。仅属于 Core 的字段位于 `x_agents_core` 中:`harness`、`model_provider`、`harness_config`、`environment`,以及只读的 Session `installation` | [Agents API 指南](public-agent-api.md) |
+| `/core/v1` | Web 的控制台服务器和操作员脚本 | [Core 密钥](../getting-started/operations.md#core-key) | 安装信息、项目和密钥、资源读取和删除、Session 归档、执行器凭据、默认模型、指标、请求日志、审计、沙箱部署和节点、独立工作区存储配置 | [Core 管理 API](../../../contracts/agents-api/zh/admin-api.md) |
| `/api/v1` | 节点、Runtime 守护进程、自托管执行器及其安装程序 | 机器凭据:节点注册令牌和节点凭据、安装授权、执行器凭据和守护进程凭据。每种凭据只能用于其各自的路由 | `/api/v1/sandbox-node/*` 和 `/api/v1/agent-daemon/*` 下的机器初始化与连接(包括 WebSockets),以及公共原生安装程序下载 | [机器连接 API](../../../contracts/agents-api/zh/machine-api.md) |
-在其他命名空间中使用凭据会返回 401:在 `/core/v1` 或 `/api/v1` 上使用 Project API key,或者在 `/v1` 或 `/api/v1` 上使用 Core key。有关 Project 和密钥的行为,请参阅 [Project 自有资产](../concepts.md#projects-own-assets)。
+在其他命名空间中使用凭据会返回 401:在 `/core/v1` 或 `/api/v1` 上使用项目 API 密钥,或者在 `/v1` 或 `/api/v1` 上使用 Core 密钥。有关项目和密钥的行为,请参阅 [项目自有资产](../concepts.md#projects-own-assets)。
-**路由。** Web 把 `/v1`、`/api/v1` 和 `/docs` 原样转发到 Core([控制台服务器](../web/console-server.md))。已登录的浏览器通过 Web 访问 `/core/v1`,由 Web 附上 Core key。操作员脚本在 Core 主机上从 Core 的网络命名空间内调用 `/core/v1`([编写 Core API 脚本](../getting-started/operations.md#script-the-core-api))。
+**路由。** Web 把 `/v1`、`/api/v1` 和 `/docs` 原样转发到 Core([控制台服务器](../web/console-server.md))。已登录的浏览器通过 Web 访问 `/core/v1`,由 Web 附上 Core 密钥。操作员脚本在 Core 主机上从 Core 的网络命名空间内调用 `/core/v1`([编写 Core API 脚本](../getting-started/operations.md#script-the-core-api))。
**API 参考。** Core 在 `/docs` 提供三个命名空间的只读 Swagger UI,文档位于 `/docs/openapi.yaml`、`/docs/core.openapi.yaml` 和 `/docs/runtime.openapi.yaml`。不需要凭据,页面也不发送 API 请求。在控制台源地址打开,例如 `http://localhost:8080/docs`。浏览器从 `unpkg.com` 加载 Swagger UI。
@@ -22,6 +22,6 @@ Core 提供三个命名空间。每个命名空间都有一种调用方及其独
节点、Runtime 守护进程和自托管安装程序使用各自的凭据调用 `/api/v1`。[机器连接 API](../../../contracts/agents-api/zh/machine-api.md) 列出了每个路由、调用方和凭据。
-运维脚本通过经 Core key 认证的 `GET` 和 `PUT /core/v1/workspace-storage` 配置独立文件系统存储;参见[工作区存储](../../../contracts/agents-api/zh/admin-api.md#workspace-storage)。
+运维脚本通过经 Core 密钥认证的 `GET` 和 `PUT /core/v1/workspace-storage` 配置独立文件系统存储;参见[工作区存储](../../../contracts/agents-api/zh/admin-api.md#workspace-storage)。
-Web 和运维脚本通过 Core key 认证的 `PATCH /core/v1/sandbox/deployment` 更新沙箱空闲策略;参见[沙箱部署](../../../contracts/agents-api/zh/sandbox-deployment.md)。
+Web 和运维脚本通过 Core 密钥认证的 `PATCH /core/v1/sandbox/deployment` 更新沙箱空闲策略;参见[沙箱部署](../../../contracts/agents-api/zh/sandbox-deployment.md)。
diff --git a/docs/zh/api/public-agent-api.md b/docs/zh/api/public-agent-api.md
index 17f7212ef..457a1406b 100644
--- a/docs/zh/api/public-agent-api.md
+++ b/docs/zh/api/public-agent-api.md
@@ -1,7 +1,7 @@
---
title: "Agents API 指南"
source: docs/api/public-agent-api.md
-source_hash: c20c794bcdae4935c3384ca7aa61e7baccbf6becb3e44c4a13a754cc5e636cc0
+source_hash: 1648667dbd1c35f043f6e93e5fdb9dbe45c1d28e4634de08fc3fa9e69d3e3f0d
---
Core 在 `/v1` 提供 [OpenAI Agents API](https://platform.openai.com/docs/api-reference)。可以使用官方 OpenAI SDK 或普通 HTTP。本指南针对每项常见操作同时展示这两种方式,并说明 Core 与 OpenAI 存在差异的地方。
@@ -10,7 +10,7 @@ Core 在 `/v1` 提供 [OpenAI Agents API](https://platform.openai.com/docs/api-r
## 准备开始 {#before-you-start}
-**基础 URL 和密钥。** 管理员会为你提供 API 基础 URL,例如 `https://core.example/v1`,以及 Project API 密钥。
+**基础 URL 和密钥。** 管理员会为你提供 API 基础 URL,例如 `https://core.example/v1`,以及项目 API 密钥。
```sh
export OPENAI_BASE_URL=https://core.example/v1
@@ -47,14 +47,14 @@ oac /agents
| 资源 | 路径 | 用途 |
| --- | --- | --- |
-| [Agents](#agents) | `/agents` | 可复用配置:模型、指令、工具和 harness |
+| [Agents](#agents) | `/agents` | 可复用配置:模型、指令、工具和 Harness |
| [Sessions](#sessions) | `/agents/sessions` | 一次 Agent 对话及其独立的 Environment |
| [输入事件](#send-input) | `/agents/sessions/{id}/events`(POST) | 消息、取消和工具结果 |
| [事件流](#stream-events) | `/agents/sessions/{id}/events`(GET) | 实时的服务器发送事件 |
| [Turns 和 Items](#turns-and-items) | `/agents/sessions/{id}/turns`、`/items` | 持久化历史 |
| [Files](#files) | `/files`、`/agents/environments/{id}/files`、`/agents/sessions/{id}/artifacts` | 上传内容、工作区文件和输出 |
| [Skills](#skills) | `/skills` | 带版本的能力捆绑包 |
-| [Environment Templates](#environment-templates) | `/agents/environments/templates` | 可复用的工作区设置 |
+| [Environment 模板](#environment-templates) | `/agents/environments/templates` | 可复用的工作区设置 |
| [Vaults](#vaults) | `/vaults` | MCP 服务器的只写凭据 |
| Subagents | `/agents/sessions/{id}/subagents` | 只读的子任务;请参阅 [subagents](../../../contracts/agents-api/zh/subagents.md) |
@@ -68,7 +68,7 @@ Core 的路由与固定版本 SDK 中的路由完全一致,完整列表见 [up
| 实时查看输出 | [流式传输事件](#stream-events) |
| 停止当前 Turn,或在响应丢失后恢复 | [取消](#cancel)、[幂等性](#idempotency) |
| 从 Agent 调用你自己的代码 | [函数工具](#function-tools) |
-| 为 Agent 提供 Skills、软件包、文件和设置命令 | [Skills](#skills)、[Environment Templates](#environment-templates) |
+| 为 Agent 提供 Skills、软件包、文件和设置命令 | [Skills](#skills)、[Environment 模板](#environment-templates) |
| 连接需要凭据的 MCP 服务器 | [Vaults](#vaults) 和 [execution tools](../../../contracts/agents-api/zh/execution-tools.md) |
| 在自己的计算机上使用 Skill 或 Plugin 目录 | [本地能力目录](../getting-started/self-hosted.md#local-capability-directories) |
| 将文件放入工作区,或下载 Agent 生成的内容 | [Files](#files) |
@@ -130,7 +130,7 @@ client.beta.agents.sessions.create(environment=..., extra_headers={"Idempotency-
| --- | --- | --- |
| 400 | `invalid_request_error`、`invalid_beta`、`model_provider_required`、`unsupported_or_invalid_configuration` | 修正请求。`invalid_beta` 表示 `OpenAI-Beta` 请求头缺失或错误 |
| 401 | `invalid_api_key` 或无代码 | 密钥错误或缺失,或者使用了其他命名空间中的密钥 |
-| 404 | Beta 路由返回 `not_found_error` | 对象不存在,或属于其他 Project。这两种情况看起来完全相同 |
+| 404 | Beta 路由返回 `not_found_error` | 对象不存在,或属于其他项目。这两种情况看起来完全相同 |
| 405 | `unsupported_operation` | Core 不支持此操作 |
| 409 | `conflict_error`、`idempotency_conflict` | 状态冲突,例如删除正在繁忙运行的 Session |
| 413 | `request_too_large` | 正文过大 |
@@ -140,29 +140,29 @@ client.beta.agents.sessions.create(environment=..., extra_headers={"Idempotency-
### Core 扩展:`x_agents_core` {#core-extensions-x-agents-core}
-Core 可以运行多种 harness,并允许接入你自己的模型访问方式。这些设置是对 OpenAI 数据结构仅有的扩展,位于 `x_agents_core` 内:
+Core 可以运行多种 Harness,并允许接入你自己的模型访问方式。这些设置是对 OpenAI 数据结构仅有的扩展,位于 `x_agents_core` 内:
| 字段 | 所在位置 | 值 |
| --- | --- | --- |
| `harness` | Agent,或 Session 的内联 `agent` | `codex`、`claude_sdk` 或 `mcode` |
-| `model_provider` | Agent,或 Session 创建请求(顶层) | `protocol`、`base_url`、`api_key`;对于 `mcode`,还包括 `context_window` 和 `max_output_tokens`。协议必须是该 harness 的原生协议之一 |
-| `harness_config` | Agent、内联 `agent`,或 Session 创建请求(顶层,优先) | harness 的原生模型参数,例如 Codex 的 `model_reasoning_effort` |
+| `model_provider` | Agent,或 Session 创建请求(顶层) | `protocol`、`base_url`、`api_key`;对于 `mcode`,还包括 `context_window` 和 `max_output_tokens`。协议必须是该 Harness 的原生协议之一 |
+| `harness_config` | Agent、内联 `agent`,或 Session 创建请求(顶层,优先) | Harness 的原生模型参数,例如 Codex 的 `model_reasoning_effort` |
| `environment` | `openai_hosted` 或 `self_hosted` Session 创建请求(顶层) | 可移植的准备配置:`environment_template_id`、`files`、`env`、`packages`、`setup_commands`、`skills`、`plugins`、`capability_directories`。同一字段不能也出现在 `environment` 中;请参阅 [Environments](../../../contracts/agents-api/zh/environments.md#preparation-order) |
| `installation` | 只读,适用于 `self_hosted` Session | 在你的计算机上运行的短期安装命令;请参阅 [self-hosted execution](../getting-started/self-hosted.md) |
任何其他成员都会导致 400 错误。`api_key` 为只写字段;读取时会返回 `api_key_configured`。`harness_config` 会替换整个对象;传入 `{}` 可将其清除。使用 SDK 时,请通过 `extra_body` 传入这些字段。
-## 选择 harness 和模型 {#choose-a-harness-and-a-model}
+## 选择 Harness 和模型 {#choose-a-harness-and-a-model}
-harness 是运行 Session 的 Agent 程序:Codex(`codex`)、Claude Code(`claude_sdk`)或 MiniMax Code(`mcode`)。请在 Agent 或内联 `agent` 上设置 `x_agents_core.harness`;如果未设置,则使用安装的默认 harness([`OAC_DEFAULT_HARNESS`](../configuration.md#settings),除非操作员另行更改,否则为 Codex)。
+Harness 是运行 Session 的 Agent 程序:Codex(`codex`)、Claude Code(`claude_sdk`)或 MiniMax Code(`mcode`)。请在 Agent 或内联 `agent` 上设置 `x_agents_core.harness`;如果未设置,则使用安装的默认 Harness([`OAC_DEFAULT_HARNESS`](../configuration.md#settings),除非操作员另行更改,否则为 Codex)。
-- **模型。** `model` 是提供商给出的准确模型 ID。`openai_hosted` 或 `none` Session 上的内联 Agent 可以省略此字段,以使用其 harness 的默认模型配置。保存的 Agent 始终必须指定模型。
-- **提供商。** harness 会使用其原生协议之一直接调用你的提供商;系统不会进行转换,不匹配时会在创建 Session 阶段拒绝请求。[Model execution](../../../contracts/agents-api/zh/model-execution.md#saved-defaults-and-precedence) 列出了每个 harness 的协议,以及各类 Environment 上 Session 使用的提供商。Session 会在创建时冻结其提供商。
-- **原生参数。** `harness_config` 承载 harness 自身的模型设置;请参阅[原生模型参数](../../../contracts/agents-api/zh/model-execution.md#native-model-parameters)。
+- **模型。** `model` 是提供商给出的准确模型 ID。`openai_hosted` 或 `none` Session 上的内联 Agent 可以省略此字段,以使用其 Harness 的默认模型配置。保存的 Agent 始终必须指定模型。
+- **提供商。** Harness 会使用其原生协议之一直接调用你的提供商;系统不会进行转换,不匹配时会在创建 Session 阶段拒绝请求。[Model execution](../../../contracts/agents-api/zh/model-execution.md#saved-defaults-and-precedence) 列出了每个 Harness 的协议,以及各类 Environment 上 Session 使用的提供商。Session 会在创建时冻结其提供商。
+- **原生参数。** `harness_config` 承载 Harness 自身的模型设置;请参阅[原生模型参数](../../../contracts/agents-api/zh/model-execution.md#native-model-parameters)。
-并非每种 harness、部署位置和操作组合都受支持;[Harness capabilities](../../../contracts/agents-api/zh/harness-capabilities.md) 列出了受支持的组合。
+并非每种 Harness、部署位置和操作组合都受支持;[Harness capabilities](../../../contracts/agents-api/zh/harness-capabilities.md) 列出了受支持的组合。
-## Agents(智能体) {#agents}
+## Agents {#agents}
Agent 是保存的配置。Session 启动时会复制该配置,因此编辑 Agent 只会影响新的 Session。
@@ -202,9 +202,9 @@ oac "/agents" -d '{
- **更新**只会更改你发送的字段。`metadata` 会替换所有键值对;`null` 会清除 `name` 或 `instructions`。
- **删除**不会影响现有 Session。
-- **工具**包括函数、MCP 服务器、`tool_search`(Claude)以及设置了 `mode: "disabled"` 的 `web_search`。支持情况取决于 harness 和 Environment;请参阅 [execution tools](../../../contracts/agents-api/zh/execution-tools.md)。
+- **工具**包括函数、MCP 服务器、`tool_search`(Claude)以及设置了 `mode: "disabled"` 的 `web_search`。支持情况取决于 Harness 和 Environment;请参阅 [execution tools](../../../contracts/agents-api/zh/execution-tools.md)。
-## Sessions(会话) {#sessions}
+## Sessions {#sessions}
Session 是一次使用固定配置并拥有独立 Environment 的对话。
@@ -351,9 +351,9 @@ data: {"type": "agent.session.turn.output_text.delta", "item_id": "item_...", "d
**流式传输创建过程本身:**在 `sessions.create` 中传入 `stream=True`。你会先收到 `agent.session.created`,流会在首次出现 `idle` 或 `failed` 时结束。
-**重新连接:**重新订阅,然后读取 Items,并按 ID 丢弃已经拥有的 Item。当流所属的 Project 密钥被吊销或 Project 被归档时,打开的流会关闭。详细信息请参阅[恢复模型](../../../contracts/agents-api/zh/sessions-events.md#recovery-model)。
+**重新连接:**重新订阅,然后读取 Items,并按 ID 丢弃已经拥有的 Item。当流所属的项目 API 密钥被吊销或项目被归档时,打开的流会关闭。详细信息请参阅[恢复模型](../../../contracts/agents-api/zh/sessions-events.md#recovery-model)。
-## Turns 和 Items(轮次和条目) {#turns-and-items}
+## Turns 和 Items {#turns-and-items}
Turn 是由输入启动的一项工作。Items 是其中记录的内容:消息、推理、工具调用及其结果。两者都是持久化的;你可以读取它们来检查结果或在断连后恢复。
@@ -419,7 +419,7 @@ oac "/agents/sessions/$SESSION_ID/events" -d '{
重新发送相同结果是安全的。为同一次调用发送不同结果,或在取消后发送结果,都会失败并返回 409。MiniMax Code 不支持公共函数。
-## Files(文件) {#files}
+## Files {#files}
三种文件具有不同用途:
@@ -427,7 +427,7 @@ oac "/agents/sessions/$SESSION_ID/events" -d '{
| --- | --- | --- |
| [源文件](#source-files) | 一次性上传字节,并通过 ID 引用 | `/files` |
| [工作区文件](#workspace-files) | 将文件放入正在运行的 Session 工作区,或列出其中的文件 | `/agents/environments/{id}/files` |
-| [Artifacts(产物)](#artifacts) | 下载 Agent 生成的内容 | `/agents/sessions/{id}/artifacts` |
+| [Artifacts](#artifacts) | 下载 Agent 生成的内容 | `/agents/sessions/{id}/artifacts` |
### 源文件 {#source-files}
@@ -461,7 +461,7 @@ oac "/agents/environments/$ENV_ID/files" -d '{"type": "file_id", "file_id": "fil
- 系统会创建父目录。已有文件绝不会被覆盖(400)。
- 列表显示单个目录中的普通文件,不会递归列出内容。列表使用 `page` 令牌分页,并返回 `next`。
-### Artifacts(产物) {#artifacts}
+### Artifacts {#artifacts}
Turn 完成时,Core 会捕获工作区 `outputs/` 目录下的普通文件。即使 Environment 消失,Artifacts 仍可读取。
@@ -478,7 +478,7 @@ oac "/agents/sessions/$SESSION_ID/artifacts/$ARTIFACT_ID/content" -o report.md
每个 Artifact 都有 `path`、`size_bytes`、`turn_id` 和 `environment_id`。删除 Artifact 不会删除工作区文件。
-## Skills(技能) {#skills}
+## Skills {#skills}
Skill 是 Agent 可使用的、包含指令和文件的带版本捆绑包。可以上传目录或 ZIP;每次上传都会创建一个版本。
@@ -497,7 +497,7 @@ client.skills.versions.create(skill.id, files=[...], default=True)
详细信息请参阅 [Files and Skills](../../../contracts/agents-api/zh/source-files.md)。Session 会在准备期间一次性安装其 Skills、Plugins 和软件包;之后编辑源文件不会影响正在运行的 Session。准备错误会在任何工作开始前导致 Session 失败:请修复原因,而不是在新 Session 中重试。
-## Environment Templates(环境模板) {#environment-templates}
+## Environment 模板 {#environment-templates}
模板用于保存工作区设置以供复用。`openai_hosted` Session 在 `environment` 中引用模板;`self_hosted` Session 则在 `x_agents_core.environment` 中引用:
@@ -516,9 +516,9 @@ template = client.beta.agents.environments.templates.create(
| `setup_commands`、`env` | 在准备期间运行和设置。读取时从不返回 |
| `files`、`skills`、`plugins` | 初始内容。最多 50 个文件,内联数据总计最多 10 MiB |
-Session 启动时会冻结模板。详细信息请参阅 [Environment Templates](../../../contracts/agents-api/zh/environments.md#templates)。
+Session 启动时会冻结模板。详细信息请参阅 [Environment 模板](../../../contracts/agents-api/zh/environments.md#templates)。
-## Vaults(凭据库) {#vaults}
+## Vaults {#vaults}
Vaults 保存 HTTP MCP 服务器的凭据:`static_bearer` 令牌,或支持可选刷新的 `mcp_oauth` 令牌。令牌为只写字段。
@@ -531,17 +531,17 @@ client.beta.agents.vaults.credentials.create(
session = client.beta.agents.sessions.create(environment={"type": "none"}, input="...", vault_ids=[vault.id], agent_id=agent.id)
```
-HTTP 路径为 `/vaults`,需要 Beta 请求头。Session 从其 `vault_ids` 中选择凭据,也可以通过 `credential_id` 指定具体凭据;无论采用哪种方式,MCP 服务器的 URL 都必须与所选凭据的 `mcp_server_url` 完全匹配。[Vaults contract](../../../contracts/agents-api/zh/vaults.md) 负责选择、错误、OAuth 刷新和删除。MCP 工具的 `connection_origin` 决定由 Core 端还是工作区连接服务器,而且每个 harness 支持的取值集合不同;请参阅 [MCP connection origin](../../../contracts/agents-api/zh/environments.md#public-mcp-connection-origin)。
+HTTP 路径为 `/vaults`,需要 Beta 请求头。Session 从其 `vault_ids` 中选择凭据,也可以通过 `credential_id` 指定具体凭据;无论采用哪种方式,MCP 服务器的 URL 都必须与所选凭据的 `mcp_server_url` 完全匹配。[Vaults contract](../../../contracts/agents-api/zh/vaults.md) 负责选择、错误、OAuth 刷新和删除。MCP 工具的 `connection_origin` 决定由 Core 端还是工作区连接服务器,而且每个 Harness 支持的取值集合不同;请参阅 [MCP connection origin](../../../contracts/agents-api/zh/environments.md#public-mcp-connection-origin)。
## 诊断故障 {#diagnose-a-failure}
1. 读取 Session 的 `status` 和 `error`,以及最新 Turn 的 `error`。失败的 Turn 只会报告通用的 `internal_error`。
-2. 检查 Environment 是否已连接,以及其 harness 是否可用。
-3. 在 [Harness capabilities](../../../contracts/agents-api/zh/harness-capabilities.md) 中检查 harness、模型和工具的组合。
+2. 检查 Environment 是否已连接,以及其 Harness 是否可用。
+3. 在 [Harness capabilities](../../../contracts/agents-api/zh/harness-capabilities.md) 中检查 Harness、模型和工具的组合。
4. 向管理员索取 Session 的[诊断信息](../../../contracts/agents-api/zh/session-diagnostics.md),其中会指出故障类别;同时请查看[故障排除](../getting-started/operations.md#troubleshooting),了解服务日志、凭据和节点就绪状态。
401 通常表示使用了其他命名空间中的密钥;请参阅 [API 命名空间与凭据](index.md)。
## 与 OpenAI 的差异 {#differences-from-openai}
-Core 在某些行为上与 OpenAI 服务不同,例如 Session 创建的幂等性和特定 harness 的工具支持。[覆盖情况清单](../../../contracts/agents-api/zh/index.md#differences-from-openai) 列出了所有差异及各资源的状态;[公共 OpenAPI](../../../contracts/agents-api/openapi.yaml) 包含准确的模式定义。
+Core 在某些行为上与 OpenAI 服务不同,例如 Session 创建的幂等性和特定 Harness 的工具支持。[覆盖情况清单](../../../contracts/agents-api/zh/index.md#differences-from-openai) 列出了所有差异及各资源的状态;[公共 OpenAPI](../../../contracts/agents-api/openapi.yaml) 包含准确的模式定义。
diff --git a/docs/zh/architecture.md b/docs/zh/architecture.md
index cecf809fd..7417c58bc 100644
--- a/docs/zh/architecture.md
+++ b/docs/zh/architecture.md
@@ -4,9 +4,9 @@ source: docs/architecture.md
source_hash: ed19d090bf0b65d33895ff59ee2f134916b03df74536ffb9b2659a3d3cb952c9
---
-OpenAgentCore 是 Agent 运行平台,通过可替换的协议实现统一组织 Harness、模型、工具、Session 和执行环境。它将编排、计算资源和原生执行分开。Core 负责 API 和持久状态。Sandbox Provider 管理计算资源。独立工作区文件系统 adapter 通过单独的协议管理 Environment 持久存储。Runtime daemon 准备 Environment 并运行选定的 Harness;Harness 的原生 SDK 或协议负责模型与工具循环。
+OpenAgentCore 是 Agent 运行平台,通过可替换的协议实现统一组织 Harness、模型、工具、Session 和执行环境。它将编排、计算资源和原生执行分开。Core 负责 API 和持久状态。沙箱提供商管理计算资源。独立工作区文件系统 adapter 通过单独的协议管理 Environment 持久存储。Runtime daemon 准备 Environment 并运行选定的 Harness;Harness 的原生 SDK 或协议负责模型与工具循环。
-推荐的自部署方案是 microsandbox 配合独立持久化工作区存储,当前由 kernel NFS adapter 提供。E2B 是托管计算的另一选择。两者使用相同的 Core 编排和能力检查。Docker 仍是可用的 Provider。计算和文件系统 adapter 声明其支持的组合;部署选择不会引入独立的 Agent 执行流程。具体契约和支持能力见 [Sandbox Provider](./sandbox-provider.md) 和[工作区文件系统 Provider](./workspace-provider.md)。
+推荐的自部署方案是 microsandbox 配合独立持久化工作区存储,当前由 kernel NFS adapter 提供。E2B 是托管计算的另一选择。两者使用相同的 Core 编排和能力检查。Docker 仍是可用的提供商。计算和文件系统 adapter 声明其支持的组合;部署选择不会引入独立的 Agent 执行流程。具体契约和支持能力见 [沙箱提供商](./sandbox-provider.md) 和[工作区文件系统提供商](./workspace-provider.md)。
```mermaid
flowchart TB
@@ -39,21 +39,21 @@ flowchart TB
| 组件 | 职责 | 参考 |
| --- | --- | --- |
| Core | 认证调用方,解析并冻结配置,调度 Turn,处理取消和待处理交互,将资源与执行事实持久化到 PostgreSQL | [Core 服务](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/services/core/README.md) |
-| Sandbox Provider | 创建、观察、续期和回收计算资源;提供 Runtime 启动输入 | [Sandbox Provider](sandbox-provider.md)、[Runtime 引导](runtime-bootstrap.md) |
-| Workspace filesystem adapter | 创建、观察和删除 Environment 持久存储;验证并解析计算资源所需的挂载 | [工作区文件系统 Provider](workspace-provider.md) |
+| 沙箱提供商 | 创建、观察、续期和回收计算资源;提供 Runtime 启动输入 | [沙箱提供商](sandbox-provider.md)、[Runtime 引导](runtime-bootstrap.md) |
+| Workspace filesystem adapter | 创建、观察和删除 Environment 持久存储;验证并解析计算资源所需的挂载 | [工作区文件系统提供商](workspace-provider.md) |
| Sandbox node | 运行 Docker 或 microsandbox 主机,协调分配给它的 generation 与 allocation | [Sandbox node 协议](../../contracts/agents-api/zh/node-generation-protocol.md) |
| Runtime | 准备工作区和能力,管理 Session Executor,执行 Turn 并报告事件与回执 | [Core–Runtime 协议](runtime-protocol.md) |
| Harness adapter | 验证原生配置,调用上游 SDK 或协议,转换事件并确认原生清理完成 | [Harness 接入](../../contracts/agents-api/zh/harness-onboarding.md) |
-| Model provider | 提供 Harness 选定的模型协议 | [模型执行](../../contracts/agents-api/zh/model-execution.md) |
+| 模型提供商 | 提供 Harness 选定的模型协议 | [模型执行](../../contracts/agents-api/zh/model-execution.md) |
| Web | 让管理员通过服务端 Core API 连接配置与观察安装实例 | [控制台服务端](web/console-server.md) |
Harness 负责原生 Agent loop 和上下文管理。应用负责业务工作流、Reviewer 策略和质量评估;这些能力不会成为 Core 执行路径。
-[仓库地图](development.md#repository-map) 标出这些组件的位置。[概念](concepts.md) 解释 Project 边界、管理员权限和工具隔离。
+[仓库地图](development.md#repository-map) 标出这些组件的位置。[概念](concepts.md) 解释项目边界、管理员权限和工具隔离。
## Session 的完整流程 {#a-session-end-to-end}
-应用通过 Agents API 创建 Session。Core 解析其配置与执行位置。托管 Session 通过选定的 Sandbox Provider 获取计算资源;自托管 Session 等待用户运行安装命令。`environment: none` 的 Session 使用已连接的执行设备,不提供工作区。[应用指南](api/public-agent-api.md#create-a-session) 说明这些选项。
+应用通过 Agents API 创建 Session。Core 解析其配置与执行位置。托管 Session 通过选定的沙箱提供商获取计算资源;自托管 Session 等待用户运行安装命令。`environment: none` 的 Session 使用已连接的执行设备,不提供工作区。[应用指南](api/public-agent-api.md#create-a-session) 说明这些选项。
daemon 连接后,Core 检查可用 Harness 和请求的能力。Runtime 准备工作区 Environment 及其能力快照,然后准备或复用 Session Executor。每个 Turn 通过原生 Harness 运行。Core 持久化输出、工具交互和回执,供应用读取和接收事件。完成或取消使 Turn 结算;健康的 Executor 可以在同一 Environment 中执行下一个 Turn。
diff --git a/docs/zh/concepts.md b/docs/zh/concepts.md
index ea03bf7f1..fa0717184 100644
--- a/docs/zh/concepts.md
+++ b/docs/zh/concepts.md
@@ -4,34 +4,34 @@ source: docs/concepts.md
source_hash: 2d65b520ffc8ccce8836d6196fb9daa217a438e4f79ae2aee70d4cb77da4c606
---
-Project 是 OpenAgentCore 的执行租户。应用使用其 API key;运维人员使用独立的 Core key 管理安装实例。[API 索引](api/index.md) 将每类调用方映射到对应命名空间和凭据。
+项目是 OpenAgentCore 的执行租户。应用使用其 API 密钥;运维人员使用独立的 Core 密钥管理安装实例。[API 索引](api/index.md) 将每类调用方映射到对应命名空间和凭据。
-## Project 拥有资产 {#projects-own-assets}
+## 项目拥有资产 {#projects-own-assets}
-Project 拥有自己的 Agent、Session、Environment、Skill、File 和 Vault。其命名 API key 共用相同的主体、权限和资源。Core 不提供产品用户、角色、成员关系或只读 key。名称是标签;稳定 ID 标识 Project 和 key。
+项目拥有自己的 Agent、Session、Environment、Skill、File 和 Vault。其命名 API 密钥共用相同的主体、权限和资源。Core 不提供产品用户、角色、成员关系或只读密钥。名称是标签;稳定 ID 标识项目和密钥。
-Project 和 key 存储在 PostgreSQL 中。Core 仅在签发时返回一次 key 明文。轮换 key 时,在同一 Project 中签发新 key,再撤销旧 key。撤销保留资产、写入来源和已接受的工作。归档 Project 会撤销所有 key 并禁止签发新 key;管理员仍可检查和删除其资源。[管理契约](../../contracts/agents-api/zh/admin-api.md#projects-and-keys) 定义这些操作。
+项目和密钥存储在 PostgreSQL 中。Core 仅在签发时返回一次密钥明文。轮换密钥时,在同一项目中签发新密钥,再撤销旧密钥。撤销保留资产、写入来源和已接受的工作。归档项目会撤销所有密钥并禁止签发新密钥;管理员仍可检查和删除其资源。[管理契约](../../contracts/agents-api/zh/admin-api.md#projects-and-keys) 定义这些操作。
-[Core key](getting-started/operations.md#core-key) 是独立的部署凭据。管理员需要使用应用 API 时,应签发 Project key 并使用该 Project 的权限。产品用户、工作区和业务权限属于应用。
+[Core 密钥](getting-started/operations.md#core-key) 是独立的部署凭据。管理员需要使用应用 API 时,应签发项目 API 密钥并使用该项目的权限。产品用户、工作区和业务权限属于应用。
## 资源隔离 {#resource-isolation}
-应用的读取、写入和引用限定在 key 所属的 Project 内。其他 Project 中的资源与不存在的资源无法区分。Core 不在 Project 之间共享或复制资产。节点、已配置的模型端点和启动设置属于部署基础设施。
+应用的读取、写入和引用限定在密钥所属的项目内。其他项目中的资源与不存在的资源无法区分。Core 不在项目之间共享或复制资产。节点、已配置的模型端点和启动设置属于部署基础设施。
## 管理员可以做什么 {#what-administrators-can-and-cannot-do}
-管理员管理 Project 和 key、沙箱部署、节点、executor 凭据及部署默认模型。他们可以检查资源、执行历史、运行计数与用量,并按删除规则删除资源。归档托管 Session 会请求取消和沙箱回收;参见 [Session 归档](../../contracts/agents-api/zh/admin-api.md#session-archive)。
+管理员管理项目和密钥、沙箱部署、节点、执行器凭据及部署默认模型。他们可以检查资源、执行历史、运行计数与用量,并按删除规则删除资源。归档托管 Session 会请求取消和沙箱回收;参见 [Session 归档](../../contracts/agents-api/zh/admin-api.md#session-archive)。
-创建或编辑应用资产、启动 Session 和提交输入都需要 Project API key。Core key 不提供应用身份,不能读取已保存的秘密。[管理 API](../../contracts/agents-api/zh/admin-api.md) 定义其操作;[控制台服务端](web/console-server.md) 负责 Web 登录与凭据处理。
+创建或编辑应用资产、启动 Session 和提交输入都需要项目 API 密钥。Core 密钥不提供应用身份,不能读取已保存的秘密。[管理 API](../../contracts/agents-api/zh/admin-api.md) 定义其操作;[控制台服务端](web/console-server.md) 负责 Web 登录与凭据处理。
## Runtime 与外层隔离 {#runtime-and-outer-isolation}
-Runtime daemon 在 Linux、macOS 和 Windows 上运行。原生平台行为由 Runtime 及其 Harness adapter 负责;托管 Sandbox Provider 运行 Linux 环境。
+Runtime daemon 在 Linux、macOS 和 Windows 上运行。原生平台行为由 Runtime 及其 Harness adapter 负责;托管沙箱提供商运行 Linux 环境。
工具以启动 daemon 的账户权限运行。daemon 不增加文件系统、权限或网络隔离。应使用外层 Environment 提供隔离:托管 Docker、E2B 或 microsandbox 环境,或在自托管机器的 Runtime 外使用容器或虚拟机。认证、私有存储、锁和进程清理保护连接与生命周期,但以同一用户运行的工具可以访问 Runtime 数据。
## 秘密与审计 {#secrets-and-audit}
-凭据值、模型 key 和机密模板数据仅可写入:应用和管理员读取结果都不包含它们。对话文本、Skill 源码和 Artifact 内容是可读取的资源数据,管理员也可以读取。
+凭据值、模型提供商密钥和机密模板数据仅可写入:应用和管理员读取结果都不包含它们。对话文本、Skill 源码和 Artifact 内容是可读取的资源数据,管理员也可以读取。
-公开写入记录执行写入的 API key。管理员写入记录独立的审计身份与目标 Project。Web 的 actor 标签仅用于显示;Core 授权依据是 Core key。审计失败会回滚写入。读取不进行审计,审计记录不包含请求体、秘密或文件内容。[写入来源](../../contracts/agents-api/zh/admin-api.md#write-provenance) 和[审计日志](../../contracts/agents-api/zh/admin-api.md#audit-log) 契约定义存储的记录。
+公开写入记录执行写入的 API 密钥。管理员写入记录独立的审计身份与目标项目。Web 的 actor 标签仅用于显示;Core 授权依据是 Core 密钥。审计失败会回滚写入。读取不进行审计,审计记录不包含请求体、秘密或文件内容。[写入来源](../../contracts/agents-api/zh/admin-api.md#write-provenance) 和[审计日志](../../contracts/agents-api/zh/admin-api.md#audit-log) 契约定义存储的记录。
diff --git a/docs/zh/configuration.md b/docs/zh/configuration.md
index 6a74d3ac7..432d30886 100644
--- a/docs/zh/configuration.md
+++ b/docs/zh/configuration.md
@@ -1,7 +1,7 @@
---
title: "配置参考"
source: docs/configuration.md
-source_hash: 72de9b828d70f6f96e20de6bf1173c8a1232924517c50b308ed8ed74d6668255
+source_hash: 8a7d64ed4be902844e1cbd5c7725e8364599131f3d7df6ce409300159db0ce47
---
Core 安装的每项设置都恰好只有一个归属位置,分属以下三类:
@@ -10,9 +10,9 @@ Core 安装的每项设置都恰好只有一个归属位置,分属以下三类
| --- | --- | --- | --- | --- |
| [进程设置](#process-settings) | 公共 URL、端口、日志、Harness、执行并发度、审计保留期、OAuth 来源、Runtime 历史记录 | 安装目录中的 `.env`(默认 `~/.oac/core`) | 编辑 `.env`,然后运行 `oac apply` | `oac apply` 会重新创建读取了这些已更改设置的服务 |
| [机密信息](#compose-installations) | 数据库密码、凭据加密密钥、安装 ID、Core 密钥及由其派生的 Core 密钥摘要 | Compose 数据卷中的 `secrets/`,每项一份 | 初始化时一次性生成;`oac rotate-core-key` 替换 Core 密钥及其摘要 | `oac rotate-core-key` 会重启 Core 和 Web |
-| [运行时设置](#runtime-settings-web) | 沙箱后端和大小、节点、项目和密钥、默认模型、执行器凭据 | Core 的 PostgreSQL 数据库 | 在 Web 中修改,或使用 Core 密钥调用 Core API(`/core/v1`) | 保存时无需重启 Core;节点会异步准备 Runtime 变更 |
+| [运行时设置](#runtime-settings-web) | 沙箱提供商和大小、节点、项目和密钥、默认模型、执行器凭据 | Core 的 PostgreSQL 数据库 | 在 Web 中修改,或使用 Core 密钥调用 Core API(`/core/v1`) | 保存时无需重启 Core;节点会异步准备 Runtime 变更 |
-**Settings** 是 Web 中平台配置的唯一入口,包含 **Sandbox and scheduling**、**Workspace storage**、**Models and credentials** 和 **Service and deployment** 四组。每项设置只有一个编辑位置;监控和节点页面跳转到对应设置。各表单通过所属 API 独立保存,不做跨资源整体保存。**Service and deployment** 显示安装地址和 Core 已加载的进程设置;进程设置在 Web 中仍为只读。项目、API 密钥和 Session 执行器凭据仍在各自资源页面管理。没有任何配置文件定义项目或 API 密钥。
+**设置** 是 Web 中平台配置的唯一入口,包含 **沙箱与调度**、**工作区存储**、**模型与凭据** 和 **服务与部署** 四组。每项设置只有一个编辑位置;监控和节点页面跳转到对应设置。各表单通过所属 API 独立保存,不做跨资源整体保存。**服务与部署** 显示安装地址和 Core 已加载的进程设置;进程设置在 Web 中仍为只读。项目、API 密钥和 Session 执行器凭据仍在各自资源页面管理。没有任何配置文件定义项目或 API 密钥。
## 进程设置 {#process-settings}
@@ -96,16 +96,16 @@ Runtime 在发现 Harness 适配器之前解析资源目录。``
| 设置 | Web 中的位置 | Core API | 注意事项 |
| --- | --- | --- | --- |
-| 沙箱后端:Docker、microsandbox 或 E2B | **Settings** → **Sandbox and scheduling**:设置向导,最后点击 **Save configuration** | `/core/v1/sandbox/deployment` | 每个安装只能使用一个后端,在首次登录后选择。要改用其他后端,必须先执行 **Reset deployment**;请参阅[更改沙箱配置](getting-started/nodes.md#change-the-sandbox-configuration) |
-| 沙箱大小、Runtime 发行版、E2B 密钥和模板构建 | **Settings** → **Sandbox and scheduling** → **Change resources** | `/core/v1/sandbox/deployment` | Web 会推荐 [Provider 声明的默认大小](sandbox-provider.md#register-the-provider-kind)。现有沙箱会保留其大小和发行版。E2B 密钥仅可写入,并且已加密 |
-| 节点及其容量 | **Nodes**:**Add node**、**Edit node** 和移除 | `/core/v1/sandbox/enrollment-tokens`、`/core/v1/sandbox/nodes` | 请参阅[节点容量](#node-capacity)和[节点指南](getting-started/nodes.md) |
-| 空闲挂起 | **Settings** → **Sandbox and scheduling** → **Automatic suspension** → **Idle before suspension (seconds)** → **Save** | `PATCH /core/v1/sandbox/deployment` | 整个部署统一生效;参阅[挂起策略](../../contracts/agents-api/zh/sandbox-deployment.md#suspension-policy) |
-| 独立工作区存储和租户容量 | **Settings → Workspace storage** | `/core/v1/workspace-storage` | 参阅[独立工作区存储](#independent-workspace-storage);现有工作区保留自身配置 |
-| 项目和 API 密钥 | **Projects and keys**:**Create project**、**Rename**、**Issue key**、**Revoke**、**Archive** | `/core/v1/projects` | 密钥只显示一次;Core 存储其摘要 |
-| 每个 Harness 的默认模型 | **Settings** → **Models and credentials**:**Set** | `/core/v1/harnesses/{harness}/model-configuration` | 请参阅[默认模型](#default-models) |
-| 自托管 Session 的执行器凭据 | **Session log**,然后进入 **Session** 页面:**Executor credentials** | `/core/v1/projects/{project_id}/environments/{environment_id}/executor-credentials` | 请参阅[自托管执行器](getting-started/self-hosted.md) |
+| 沙箱提供商:Docker、microsandbox 或 E2B | **设置** → **沙箱与调度**:设置向导,最后点击 **保存配置** | `/core/v1/sandbox/deployment` | 每个安装只能使用一个沙箱提供商,在首次登录后选择。要改用其他提供商,必须先执行 **重置部署**;请参阅[更改沙箱配置](getting-started/nodes.md#change-the-sandbox-configuration) |
+| 沙箱大小、Runtime 发行版、E2B 密钥和模板构建 | **设置** → **沙箱与调度** → **修改资源** | `/core/v1/sandbox/deployment` | Web 会推荐 [提供商声明的默认大小](sandbox-provider.md#register-the-provider-kind)。现有沙箱会保留其大小和发行版。E2B 密钥仅可写入,并且已加密 |
+| 节点及其容量 | **节点**:**添加节点**、**编辑节点** 和移除 | `/core/v1/sandbox/enrollment-tokens`、`/core/v1/sandbox/nodes` | 请参阅[节点容量](#node-capacity)和[节点指南](getting-started/nodes.md) |
+| 空闲挂起 | **设置** → **沙箱与调度** → **自动挂起** → **空闲多久后挂起(秒)** → **保存** | `PATCH /core/v1/sandbox/deployment` | 整个部署统一生效;参阅[挂起策略](../../contracts/agents-api/zh/sandbox-deployment.md#suspension-policy) |
+| 独立工作区存储和租户容量 | **设置 → 工作区存储** | `/core/v1/workspace-storage` | 参阅[独立工作区存储](#independent-workspace-storage);现有工作区保留自身配置 |
+| 项目和 API 密钥 | **项目与密钥**:**创建项目**、**改名**、**签发密钥**、**撤销**、**归档** | `/core/v1/projects` | 密钥只显示一次;Core 存储其摘要 |
+| 每个 Harness 的默认模型 | **设置** → **模型与凭据**:**设置** | `/core/v1/harnesses/{harness}/model-configuration` | 请参阅[默认模型](#default-models) |
+| 自托管 Session 的执行器凭据 | **Session 日志**,然后进入 **Session** 页面:**执行器凭据** | `/core/v1/projects/{project_id}/environments/{environment_id}/executor-credentials` | 请参阅[自托管执行器](getting-started/self-hosted.md) |
-哪些 Harness 已启用以及默认 Harness 属于进程设置(`OAC_HARNESSES`、`OAC_DEFAULT_HARNESS`);**Settings → Service and deployment** 在 **Startup settings** 中列出它们。**Settings → Models and credentials** 在 Harness 已启用且设置了默认模型时将其标记为 **Ready**,否则指出缺少的步骤:**Model provider not set** 或 **Disabled**。[Core 管理 API](../../contracts/agents-api/zh/admin-api.md) 列出了所有 Core API 路由,[部署契约](../../contracts/agents-api/zh/sandbox-deployment.md) 定义了沙箱字段、限制和更改规则。
+哪些 Harness 已启用以及默认 Harness 属于进程设置(`OAC_HARNESSES`、`OAC_DEFAULT_HARNESS`);**设置 → 服务与部署** 在 **启动设置** 中列出它们。**设置 → 模型与凭据** 在 Harness 已启用且设置了默认模型时将其标记为 **就绪**,否则指出缺少的步骤:**未设置模型提供商** 或 **已禁用**。[Core 管理 API](../../contracts/agents-api/zh/admin-api.md) 列出了所有 Core API 路由,[部署契约](../../contracts/agents-api/zh/sandbox-deployment.md) 定义了沙箱字段、限制和更改规则。
### 独立工作区存储 {#independent-workspace-storage}
@@ -127,7 +127,7 @@ services:
create_host_path: false
```
-在 **Settings → Workspace storage → Select new configuration** 中选择存储,或按[管理 API](../../contracts/agents-api/zh/admin-api.md#workspace-storage)说明,使用 Core key 调用 `PUT /core/v1/workspace-storage`。首次设置时,分别为不可变配置 `id` 和命名空间标记生成规范 UUID,然后使用实际值提交以下结构。恢复时保留已有标识。选择操作会在 Core 中运行适配器的可用性、所有权和 xattr 检查;它不证明每个节点均能解析该挂载:
+在 **设置 → 工作区存储 → 选择新配置** 中选择存储,或按[管理 API](../../contracts/agents-api/zh/admin-api.md#workspace-storage)说明,使用 Core 密钥调用 `PUT /core/v1/workspace-storage`。首次设置时,分别为不可变配置 `id` 和命名空间标记生成规范 UUID,然后使用实际值提交以下结构。恢复时保留已有标识。选择操作会在 Core 中运行适配器的可用性、所有权和 xattr 检查;它不证明每个节点均能解析该挂载:
```json
{
@@ -144,11 +144,11 @@ services:
此配置不实施单个工作区配额,因此 `tenant_capacity_mib` 必须为 `0`。如需有上限的工作区,应准备[配额模式存储服务器](#quota-mode-storage-server),并改为选择带[租户容量](#tenant-capacity)的配额模式配置。
-随后通过[沙箱部署 API](../../contracts/agents-api/zh/sandbox-deployment.md#routes)创建或更新 microsandbox 部署,并保留所需计算资源、Runtime 和 Provider 配置。`resources.environment_disk_mib` 是每个新工作区的容量:非配额模式下为 `0`,正数会被拒绝;配额模式下至少为 1024 MiB,`0` 会在工作区准入时被拒绝。部署变更时,既有工作区保持其获准时的容量。部署的工作区要求和每个 Session 的挂载凭据均从已选数据库配置派生;不要向部署添加文件系统字段,也不要在节点文件中添加第二份存储配置。
+随后通过[沙箱部署 API](../../contracts/agents-api/zh/sandbox-deployment.md#routes)创建或更新 microsandbox 部署,并保留所需计算资源、Runtime 和提供商配置。`resources.environment_disk_mib` 是每个新工作区的容量:非配额模式下为 `0`,正数会被拒绝;配额模式下至少为 1024 MiB,`0` 会在工作区准入时被拒绝。部署变更时,既有工作区保持其获准时的容量。部署的工作区要求和每个 Session 的挂载凭据均从已选数据库配置派生;不要向部署添加文件系统字段,也不要在节点文件中添加第二份存储配置。
-存储表单接受 adapter 标识、JSON 对象形式的参数和可选的只写凭据 JSON 对象。Core 验证这些由 adapter 定义的值;Web 不定义 Provider 专属存储字段。**Edit tenant capacity** 保留已选的不可变配置。选择另一份配置需要新的 ID,不会迁移现有工作区。
+存储表单接受 adapter 标识、JSON 对象形式的参数和可选的只写凭据 JSON 对象。Core 验证这些由 adapter 定义的值;Web 不定义提供商专属存储字段。**修改租户容量** 保留已选的不可变配置。选择另一份配置需要新的 ID,不会迁移现有工作区。
-选择文件系统和部署后,通过 **Nodes → Add node** 注册已准备的主机。计算资源已连接且就绪并不足以证明外部文件系统具备资格;准入应用流量前,通过每个参与节点验证实际 Session 创建和访问。将独立命名空间纳入[停止写入后的备份恢复流程](./getting-started/operations.md#back-up)。
+选择文件系统和部署后,通过 **节点 → 添加节点** 注册已准备的主机。计算资源已连接且就绪并不足以证明外部文件系统具备资格;准入应用流量前,通过每个参与节点验证实际 Session 创建和访问。将独立命名空间纳入[停止写入后的备份恢复流程](./getting-started/operations.md#back-up)。
#### 配额模式存储服务器 {#quota-mode-storage-server}
@@ -200,13 +200,13 @@ Session 创建可以在异步工作区准入之前成功。容量耗尽时,Cor
### 节点容量 {#node-capacity}
-生成 **Add node** 命令时,Core 会批准节点容量:**Sandboxes at once**(`max_active`,默认值为 2),并且仅对 microsandbox 还会批准 **Retained sandboxes**(`max_retained`,默认值为 8),其中 `max_retained >= max_active >= 1`。Docker 从不暂停沙箱,因此 Web 不会询问此项,并且 Core 会使 `max_retained` 保持等于 `max_active`。之后可在 **Nodes** 使用 **Edit node** 修改这些值。预留和尚未确认的清理操作都会占用容量;调低限制不会停止任何正在运行的沙箱。节点自身的文件无法更改其容量、大小或 Runtime。
+生成 **添加节点** 命令时,Core 会批准节点容量:**同时运行的沙箱**(`max_active`,默认值为 2),并且仅对 microsandbox 还会批准 **保留的沙箱**(`max_retained`,默认值为 8),其中 `max_retained >= max_active >= 1`。Docker 从不暂停沙箱,因此 Web 不会询问此项,并且 Core 会使 `max_retained` 保持等于 `max_active`。之后可在 **节点** 使用 **编辑节点** 修改这些值。预留和尚未确认的清理操作都会占用容量;调低限制不会停止任何正在运行的沙箱。节点自身的文件无法更改其容量、大小或 Runtime。
`OAC_EXECUTION_CONCURRENCY` 与此无关:它限制 Core 中并发执行的工作量。
### 默认模型 {#default-models}
-在 **Settings** → **Models and credentials** 中设置默认值,或使用 `PUT /core/v1/harnesses/{harness}/model-configuration`。Core 使用 `secrets/core/credential.key` 加密提供商密钥,并且绝不返回这些密钥。[模型执行](../../contracts/agents-api/zh/model-execution.md#deployment-defaults) 定义了请求字段和替换规则,[优先级](../../contracts/agents-api/zh/model-execution.md#saved-defaults-and-precedence)说明了哪些 Session 使用默认值。
+在 **设置** → **模型与凭据** 中设置默认值,或使用 `PUT /core/v1/harnesses/{harness}/model-configuration`。Core 使用 `secrets/core/credential.key` 加密提供商密钥,并且绝不返回这些密钥。[模型执行](../../contracts/agents-api/zh/model-execution.md#deployment-defaults) 定义了请求字段和替换规则,[优先级](../../contracts/agents-api/zh/model-execution.md#saved-defaults-and-precedence)说明了哪些 Session 使用默认值。
## Compose 安装 {#compose-installations}
@@ -220,12 +220,12 @@ Session 创建可以在异步工作区准入之前成功。容量耗尽时,Cor
| `secrets/database/` | 生成的数据库密码 | PostgreSQL 和 Core |
| `secrets/core/` | 凭据加密密钥、安装 ID 和 Core 密钥摘要 | Core |
| `secrets/web/` | 生成的 Core 登录密钥 | Web |
-| `state/` | 私有 Provider 状态,在 Core 中挂载到 `/state`。每个适配器拥有一个子目录;E2B 使用 `e2b/`,不允许组或其他用户访问 | Core |
+| `state/` | 私有提供商状态,在 Core 中挂载到 `/state`。每个适配器拥有一个子目录;E2B 使用 `e2b/`,不允许组或其他用户访问 | Core |
| `node-payload/` | 已验证的节点安装元数据 | Web |
初始化会准备该目录;应用服务以只读方式接收各自的机密目录。`docker compose exec web oac-web core-key` 把 Core 密钥打印到运维人员终端,不写入容器日志。数据库密码和凭据加密密钥绝不打印。
-上述路径位于 Docker 命名卷 `_data` 中。所有宿主机平台都由 Docker 管理 Linux 文件权限;每个服务只挂载需要的子目录。数据卷必须和项目定义、公共 URL 一同保留。仅删除机密目录不会重置安装;数据库已存在时初始化会拒绝重建。Core 也会校验安装 ID 与数据库的绑定。运行时设置仍保存在 [Core 数据库](#runtime-settings-web)中。
+上述路径位于 Docker 命名卷 `_data` 中。所有主机平台都由 Docker 管理 Linux 文件权限;每个服务只挂载需要的子目录。数据卷必须和项目定义、公共 URL 一同保留。仅删除机密目录不会重置安装;数据库已存在时初始化会拒绝重建。Core 也会校验安装 ID 与数据库的绑定。运行时设置仍保存在 [Core 数据库](#runtime-settings-web)中。
## Docker 节点配置 {#docker-node-configuration}
@@ -286,6 +286,6 @@ Compose 为 Web 设置这些变量。仅在不使用 Compose 运行控制台时
| `OAC_WEB_UPSTREAM` | `http://core:8091` | Core 的源地址,可以使用 HTTP 或 HTTPS,且不得包含凭据、查询参数或路径。健康检查探测其 `/healthz` |
| `OAC_WEB_CORE_KEY_FILE` | 必填 | 常规文件的绝对路径,该文件没有组或其他用户权限,并保存 Core 密钥:至少 32 个字符、不含空白字符、最大 4 KiB |
| `OAC_WEB_DIST` | `/www` | 已构建控制台的绝对目录;必须包含 `index.html` |
-| `OAC_WEB_NODE_PAYLOAD_DIR` | 未设置 | 所匹配发行版的节点载荷(即安装程序的 `node-payload/`)的绝对路径。未设置时,不提供 `/node-install/*`,且 Add node 不可用 |
+| `OAC_WEB_NODE_PAYLOAD_DIR` | 未设置 | 所匹配发行版的节点载荷(即安装程序的 `node-payload/`)的绝对路径。未设置时,不提供 `/node-install/*`,且 **添加节点** 不可用 |
未设置或为空的变量使用其默认值。无效值会阻止控制台启动,并显示一条指明变量名的消息。控制台还会读取三个日志[进程设置](#settings),并拒绝 Core 拒绝的值。对于不在同一台计算机上的任何浏览器,请使用 HTTPS。
diff --git a/docs/zh/development.md b/docs/zh/development.md
index 5d8cb7718..5ae8dfb49 100644
--- a/docs/zh/development.md
+++ b/docs/zh/development.md
@@ -1,7 +1,7 @@
---
title: "开发 OpenAgentCore"
source: docs/development.md
-source_hash: a3e1dc325f8500863c9424344ac010e9091912e72ac1bf66cca212c3f62192e8
+source_hash: cf241a574a30389dc38d0fdaa87fe5d82714beed489e39e42bd6710478f3a3eb
---
准备工作副本,构建组件并验证修改。如需使用已安装的实例,从[入门指南](getting-started/index.md)开始。修改代码前阅读[贡献者规则](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/CONTRIBUTING.md)。
@@ -17,7 +17,7 @@ git worktree add ../openagentcore-change -b codex/my-change main
cd ../openagentcore-change
```
-安装 [go.mod](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/go.mod) 中指定版本的 Go、Node 22.13 或更高版本、[package.json](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/package.json) 中指定版本的 pnpm,以及 Python 3.9 或更高版本。完整检查在 Linux 上运行,需要专用 PostgreSQL 数据库、microsandbox helper 使用的 OpenSSL 开发库、发行包压缩使用的 pigz 和 Playwright 浏览器。Provider 和 Runtime 构建的其他前提条件见各组件指南。
+安装 [go.mod](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/go.mod) 中指定版本的 Go、Node 22.13 或更高版本、[package.json](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/package.json) 中指定版本的 pnpm,以及 Python 3.9 或更高版本。完整检查在 Linux 上运行,需要专用 PostgreSQL 数据库、microsandbox helper 使用的 OpenSSL 开发库、发行包压缩使用的 pigz 和 Playwright 浏览器。提供商和 Runtime 构建的其他前提条件见各组件指南。
```sh
make node-deps
@@ -72,11 +72,11 @@ python3 "$bundle/install.py" \
--public-url http://YOUR_CORE_HOST:8080
```
-将 `YOUR_CORE_HOST` 替换为浏览器与沙箱节点都能访问的地址。需要时使用反向代理后的 HTTPS 地址;入口配置见[安装选项](getting-started/install-options.md)。安装器输出用于登录的 Core key。它创建标准 Compose 安装,以及包含该构建公共节点制品的只读 `node-payload` 目录。磁盘需同时容纳解压后的构建包和安装副本。Core、Web 均不会获得 Docker socket。
+将 `YOUR_CORE_HOST` 替换为浏览器与沙箱节点都能访问的地址。需要时使用反向代理后的 HTTPS 地址;入口配置见[安装选项](getting-started/install-options.md)。安装器输出用于登录的 Core 密钥。它创建标准 Compose 安装,以及包含该构建公共节点制品的只读 `node-payload` 目录。磁盘需同时容纳解压后的构建包和安装副本。Core、Web 均不会获得 Docker socket。
构建还会生成 `oac--linux-amd64-offline.tar.gz`。可将其复制到另一台 Linux amd64 Docker 主机,解压后执行其中的 `install.py`;目标主机只需要 Python 3.9+ 和 Docker,无需源码、Go、Node 或 pnpm。安装完成前保留解压目录;安装后的服务和节点下载不再依赖它的原始位置。
-在 Web 中配置模型提供方,创建沙箱部署,再使用[节点](getting-started/nodes.md)中显示的命令添加节点。节点前提仍然适用,包括 microsandbox 所需的 KVM。命令直接从本次安装下载匹配的执行制品。此路径构建全部三个受管 Harness;除非提供[原生安装器目录](maintainers.md#native-installers),否则可选的自托管原生安装器不可用,不会生成占位目录。
+在 Web 中配置模型提供商,创建沙箱部署,再使用[节点](getting-started/nodes.md)中显示的命令添加节点。节点前提仍然适用,包括 microsandbox 所需的 KVM。命令直接从本次安装下载匹配的执行制品。此路径构建全部三个受管 Harness;除非提供[原生安装器目录](maintainers.md#native-installers),否则可选的自托管原生安装器不可用,不会生成占位目录。
启动失败或安装已停止时,使用保存的配置,而不是重新安装:
@@ -113,12 +113,12 @@ Core 构建产物和输出目录设置见[独立 Core 构建](maintainers.md#sta
| `services/core/internal/persistence`、`services/core/internal/db` 和 `services/core/migrations` | Core 的 PostgreSQL adapter、事务、查询和迁移 | [服务指南](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/services/core/README.md#database) |
| `services/core/tests/integration` | 共同驱动 HTTP 边界、执行 Worker 和 PostgreSQL adapter 的测试 | [服务指南](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/services/core/README.md#tests) |
| `services/core/internal/execution` | 持久化 Turn 分发与调度 | [Runtime 协议](runtime-protocol.md) |
-| `services/core/internal/engine` | 对 harness 操作与执行位置进行纯资格验证 | [Harness 接入](../../contracts/agents-api/zh/harness-onboarding.md) |
+| `services/core/internal/engine` | 对 Harness 操作与执行位置进行纯资格验证 | [Harness 接入](../../contracts/agents-api/zh/harness-onboarding.md) |
| `internal/agentdaemon/proto` | Core–Runtime wire 类型与验证器 | [Runtime 协议](runtime-protocol.md) |
-| `internal/runtimebootstrap` | Provider 到 Runtime 的启动输入 | [Runtime 引导](runtime-bootstrap.md) |
+| `internal/runtimebootstrap` | 提供商到 Runtime 的启动输入 | [Runtime 引导](runtime-bootstrap.md) |
| `apps/daemon/internal/dispatch` | Runtime 准备、Executor 复用、Turn 和清理所有权 | [Harness 生命周期](../../contracts/agents-api/zh/harness-onboarding.md#required-adapter-interfaces) |
-| `apps/daemon/internal/agent` | 原生 harness adapter | [原生参考](../../contracts/agents-api/zh/harness-onboarding.md#native-references) |
-| `services/core/internal/sandbox` | Provider 接口与托管计算资源生命周期 | [Provider 接入](sandbox-provider.md) |
+| `apps/daemon/internal/agent` | 原生 Harness adapter | [原生参考](../../contracts/agents-api/zh/harness-onboarding.md#native-references) |
+| `services/core/internal/sandbox` | 提供商接口与托管计算资源生命周期 | [提供商接入](sandbox-provider.md) |
| `services/web` | 控制台登录与服务端管理代理 | [控制台服务端](web/console-server.md) |
| `apps/web` 和 `packages/agents-client` | 控制台 UI 与类型化 client | [Web 指南](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/apps/web/README.md) |
| `deploy` 和 `scripts` | 发行、安装和验证工具 | [维护者指南](maintainers.md) |
@@ -126,7 +126,7 @@ Core 构建产物和输出目录设置见[独立 Core 构建](maintainers.md#sta
## 选择扩展边界 {#choose-an-extension-boundary}
-通过[协议地图](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/AGENTS.md#protocols-at-every-boundary)找到新增 Harness、Sandbox Provider、model provider、API 操作或 Runtime 消息所需的代码与指南。指南负责注册、支持的操作和实现资格验证所需检查。工作区能力(如 Skill、Plugin、MCP 和系统包)从 [Environment](../../contracts/agents-api/zh/environments.md) 开始。
+通过[协议地图](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/AGENTS.md#protocols-at-every-boundary)找到新增 Harness、沙箱提供商、模型提供商、API 操作或 Runtime 消息所需的代码与指南。指南负责注册、支持的操作和实现资格验证所需检查。工作区能力(如 Skill、Plugin、MCP 和系统包)从 [Environment](../../contracts/agents-api/zh/environments.md) 开始。
## 验证修改 {#validate-a-change}
@@ -138,13 +138,13 @@ Core 构建产物和输出目录设置见[独立 Core 构建](maintainers.md#sta
| SQL 查询 | `make sqlc-generate`,检查生成文件,再运行 `make check-sqlc` |
| 公共 schema、Core 扩展或内部处理函数注解 | `make openapi`、`make check-openapi`;检查生成类型和三个命名空间的 schema |
| 共享 Runtime 协议 | `make check-runtime-contract` |
-| Provider 集成 | `make check-sandbox-provider-contract` 和 provider 的原生检查 |
+| 提供商集成 | `make check-sandbox-provider-contract` 和提供商的原生检查 |
| Claude SDK bridge 与产物 | `make check-claude-sdk` |
| Web UI 与 client | `make check-web` |
| 发行或安装器 | `make check-distribution` |
| 文档 | `make check-names`;`make check-distribution` 验证 Markdown 链接与打包文档 |
-Fixture 浏览器验收使用 loopback 端口 18092 和 4174。并行验证时通过 `AGENTS_FIXTURE_PORT` 和 `AGENTS_WEB_PORT` 选择空闲端口。验证 worker 之间使用独立数据库、端口和容器。编译、fixture 成功和真实模型/provider 验收分别证明不同事实;应明确报告跳过或不可用的检查。验证后遵循[独立盲审工作流](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/CONTRIBUTING.md#review)。
+Fixture 浏览器验收使用 loopback 端口 18092 和 4174。并行验证时通过 `AGENTS_FIXTURE_PORT` 和 `AGENTS_WEB_PORT` 选择空闲端口。验证 worker 之间使用独立数据库、端口和容器。编译、fixture 成功和真实模型/提供商验收分别证明不同事实;应明确报告跳过或不可用的检查。验证后遵循[独立盲审工作流](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/CONTRIBUTING.md#review)。
## 修改文档 {#change-documentation}
diff --git a/docs/zh/examples.md b/docs/zh/examples.md
index 8730c4a63..601436927 100644
--- a/docs/zh/examples.md
+++ b/docs/zh/examples.md
@@ -1,10 +1,10 @@
---
title: "示例"
source: docs/examples.md
-source_hash: 3c10e50ae47479688cdfac708e82efd73bd5b5f77a2e8b16497a4e02cb14573d
+source_hash: 60a228b1b499d11f5f6f122a5e298962fcc9ced9777688f69f5078a2f5df4c9c
---
-基于 [Agents API](api/public-agent-api.md)构建的完整应用。每个示例都使用 Project API 密钥连接真实的 Core 安装。
+基于 [Agents API](api/public-agent-api.md)构建的完整应用。每个示例都使用项目 API 密钥连接真实的 Core 安装。
| 示例 | 展示内容 |
| --- | --- |
diff --git a/docs/zh/getting-started/index.md b/docs/zh/getting-started/index.md
index 92440e3ac..5f4647628 100644
--- a/docs/zh/getting-started/index.md
+++ b/docs/zh/getting-started/index.md
@@ -1,18 +1,18 @@
---
title: "概览"
source: docs/getting-started/index.md
-source_hash: 232aae563b4d7614f065118f2a625b7b06d4d7384295aab77ac072856b9af380
+source_hash: 50f7acd140432ea6643dce0d3e8186812bf471f5aa844f7a7dde0d4f94bb9b56
---
OpenAgentCore 在你自己的基础设施上运行 AI Agent,并提供 OpenAI Agents API。[架构概览](../architecture.md)介绍各个组成部分。根据你的角色选择指南。
## 运维人员 {#operators}
-运维人员安装 Core 和 Web、添加沙箱容量并签发 Project API 密钥。
+运维人员安装 Core 和 Web、添加沙箱容量并签发项目 API 密钥。
| 指南 | 内容 |
| --- | --- |
-| [安装 Core 和 Web](install.md) | 默认安装流程:从空白主机到第一个 Project API 密钥 |
+| [安装 Core 和 Web](install.md) | 默认安装流程:从空白主机到第一个项目 API 密钥 |
| [安装选项](install-options.md) | 安装参数、已有反向代理、离线主机 |
| [节点](nodes.md) | 添加、修改、移除沙箱节点及排查问题 |
| [运维](operations.md) | `oac` 命令、Core 密钥、备份、卸载、升级及问题排查 |
@@ -21,11 +21,11 @@ OpenAgentCore 在你自己的基础设施上运行 AI Agent,并提供 OpenAI A
## 应用开发者 {#application-developers}
-应用开发者使用 Project API 密钥调用 API,也可以在自己的机器上运行 Session。
+应用开发者使用项目 API 密钥调用 API,也可以在自己的机器上运行 Session。
| 指南 | 内容 |
| --- | --- |
-| [快速开始](quickstart.md) | 从 Project API 密钥到完成一个 Session |
+| [快速开始](quickstart.md) | 从项目 API 密钥到完成一个 Session |
| [Agents API 指南](../api/public-agent-api.md) | 常见任务、Harness 与模型选择,以及各资源的 SDK 和 HTTP 示例 |
| [自托管执行](self-hosted.md) | 在自己的机器上运行 Session |
| [示例](../examples.md) | 基于 API 构建的完整应用 |
diff --git a/docs/zh/getting-started/install-options.md b/docs/zh/getting-started/install-options.md
index db17fac08..08e23edf0 100644
--- a/docs/zh/getting-started/install-options.md
+++ b/docs/zh/getting-started/install-options.md
@@ -33,7 +33,7 @@ docker compose exec web oac-web core-key
### Dokploy {#dokploy}
-创建一个 Docker Compose 应用并粘贴 `compose.yaml`。将 `OAC_PUBLIC_URL` 设置为公共 HTTPS 源地址,启用隔离部署,并为 `web` 服务添加域名和端口 `8080`。部署前,为此域名启用 **HTTPS**,并选择 **Let's Encrypt** 等证书提供程序。部署前移除 `web` 服务的 `ports` 块,让 Dokploy 路由到容器端口,而不发布宿主机端口。将此 Compose 文件打包到 Dokploy 模板目录时,[模板元数据](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/deploy/compose/dokploy.toml)会提供生成的域名和环境;导入后仍需启用 HTTPS 及其证书提供程序。
+创建一个 Docker Compose 应用并粘贴 `compose.yaml`。将 `OAC_PUBLIC_URL` 设置为公共 HTTPS 源地址,启用隔离部署,并为 `web` 服务添加域名和端口 `8080`。部署前,为此域名启用 **HTTPS**,并选择 **Let's Encrypt** 等证书提供程序。部署前移除 `web` 服务的 `ports` 块,让 Dokploy 路由到容器端口,而不发布主机端口。将此 Compose 文件打包到 Dokploy 模板目录时,[模板元数据](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/deploy/compose/dokploy.toml)会提供生成的域名和环境;导入后仍需启用 HTTPS 及其证书提供程序。
### Coolify {#coolify}
@@ -41,7 +41,7 @@ docker compose exec web oac-web core-key
在这两个平台上,打开服务器终端并运行 `docker compose ls`,查找已部署的项目名称和 Compose 文件。使用这些完全一致的值以及该部署的 `OAC_PUBLIC_URL`,运行 `docker compose -p -f exec web oac-web core-key`,然后在已配置的源地址登录。[Dokploy 域名指南](https://docs.dokploy.com/docs/core/docker-compose/domains)和[Coolify Compose 指南](https://coolify.io/docs/services/configuration/docker-compose)介绍了各自的域和服务控制项。这些都是可导入的部署文件;本仓库不发布托管市场条目。
-登录后,使用 [Nodes](nodes.md)选择沙箱后端并添加节点。Compose 堆栈部署控制平面;执行机器仍需单独部署。
+登录后,使用 [Nodes](nodes.md)选择沙箱提供商并添加节点。Compose 堆栈部署控制平面;执行机器仍需单独部署。
使用相同的文件和环境运行 `docker compose stop` 以停止服务。停止服务后,备份数据卷。请遵循[安装版本策略](operations.md#installation-version-policy):使用不同发布版本时,需要创建新的 Compose 项目并使用全新的数据卷。
@@ -66,9 +66,9 @@ docker compose exec web oac-web core-key
只要使用不同的安装目录和端口,多个安装就可以共用一台机器。需要更多安装时,请使用不同的 IP 地址或共享反向代理。每个安装都有自己的数据库、Core 密钥和节点。
-## 沙箱后端 {#sandbox-backend}
+## 沙箱提供商 {#sandbox-backend}
-安装程序不保存沙箱后端。登录后,打开 **Settings** → **Sandbox and scheduling**,选择 Docker、microsandbox 或 E2B;Web 会把 [Provider 声明的默认大小](../sandbox-provider.md#register-the-provider-kind)推荐为 Standard 尺寸。该选择保存在 Core 的数据库中。以后要更改,请[重置部署](nodes.md#change-the-sandbox-configuration)。Docker 沙箱与每个节点共用该节点的内核,其节点服务账户[等效于 root](nodes.md#what-the-installer-sets-up)。E2B 需要一个非回环的公共 HTTPS URL,因为 E2B 沙箱会从 E2B 云端调用 Core。按照 [E2B 指南](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/services/core/deploy/e2b/README.md)准备模板。
+安装程序不保存沙箱提供商。登录后,打开 **设置** → **沙箱与调度**,选择 Docker、microsandbox 或 E2B;Web 会把 [提供商声明的默认大小](../sandbox-provider.md#register-the-provider-kind)推荐为 Standard 尺寸。该选择保存在 Core 的数据库中。以后要更改,请[重置部署](nodes.md#change-the-sandbox-configuration)。Docker 沙箱与每个节点共用该节点的内核,其节点服务账户[等效于 root](nodes.md#what-the-installer-sets-up)。E2B 需要一个非回环的公共 HTTPS URL,因为 E2B 沙箱会从 E2B 云端调用 Core。按照 [E2B 指南](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/services/core/deploy/e2b/README.md)准备模板。
## 监听器与访问 {#listeners-and-access}
diff --git a/docs/zh/getting-started/install.md b/docs/zh/getting-started/install.md
index cf7940572..b33035352 100644
--- a/docs/zh/getting-started/install.md
+++ b/docs/zh/getting-started/install.md
@@ -1,17 +1,17 @@
---
title: "安装 Core 和 Web"
source: docs/getting-started/install.md
-source_hash: 52e9519b47d1c05f00f38968dbeab6a27568b51d454a17aab2d80b56563d0bb0
+source_hash: 9b8c548e48923c2ee6e51deaebb85422db2b568f36a6718af6b44ff13099ff2a
---
-一条命令即可在 Linux、macOS 或 Windows 上安装 Core、Web 控制台和 PostgreSQL。用 Core 密钥登录 Web,设置默认模型并签发 Project API 密钥。应用使用这些密钥调用 Core。Session 在你添加的节点上的沙箱中运行,也可以在 E2B 上运行。
+一条命令即可在 Linux、macOS 或 Windows 上安装 Core、Web 控制台和 PostgreSQL。用 Core 密钥登录 Web,设置默认模型并签发项目 API 密钥。应用使用这些密钥调用 Core。Session 在你添加的节点上的沙箱中运行,也可以在 E2B 上运行。
1. [检查前置条件](#prerequisites)。
2. [运行安装程序](#install)。
3. [登录 Web](#sign-in-to-web)。
4. [配置公开地址](#configure-the-domain-and-https)。
5. [设置默认模型](#set-a-default-model)。
-6. [签发 Project API 密钥](#issue-a-project-api-key)。
+6. [签发项目 API 密钥](#issue-a-project-api-key)。
7. [添加沙箱容量](#add-sandbox-capacity)。
本页介绍默认流程。完整参数、已有反向代理和离线主机请参阅[安装选项](install-options.md)。
@@ -52,7 +52,7 @@ curl -fsSL https://github.com/MiniMax-AI/OpenAgentCore/releases/latest/download/
2. 准备[安装目录](../configuration.md#installation-directory) `~/.oac/core`,写入 `.env` 和原生 `oac` 命令(Windows 为 `oac.exe`);
3. 用 Docker Compose 启动服务。Web 在 8080 端口提供控制台,并把 `/v1`、`/api/v1` 和 `/docs` 转发到 Core。Core 和 PostgreSQL 不发布端口。
-安装器会打印控制台地址和 Core 密钥。登录后,在 Web 中配置执行资源并创建 Project。
+安装器会打印控制台地址和 Core 密钥。登录后,在 Web 中配置执行资源并创建项目。
安装目录就位前,先完成下载和配置检查。之后的失败会保留配置与数据,并报告失败步骤;在安装目录运行 `docker compose logs --tail 100` 查看日志。修复报错后,重新执行同一命令,或指定安装目录即可继续:
@@ -84,20 +84,20 @@ curl -fsSL https://github.com/MiniMax-AI/OpenAgentCore/releases/latest/download/
## 设置默认模型 {#set-a-default-model}
-没有自带模型提供商的 Core 托管 Session 使用其 Harness 的默认模型。在 **Settings → Models and credentials** 的 **Default model configuration** 下,找到标记为 **Default** 的 Harness(除非修改了 `OAC_DEFAULT_HARNESS`,否则为 Codex),它显示 **Model provider not set**。选择 **Set**,输入模型 ID、协议以及提供商的基础 URL 和 API 密钥。MiniMax Code 还需要上下文窗口和最大输出 token 数。之后该 Harness 显示 **Ready**。参阅[默认模型](../configuration.md#default-models)。
+没有自带模型提供商的 Core 托管 Session 使用其 Harness 的默认模型。在 **设置 → 模型与凭据** 的 **默认模型配置** 下,找到标记为 **默认** 的 Harness(除非修改了 `OAC_DEFAULT_HARNESS`,否则为 Codex),它显示 **未设置模型提供商**。选择 **设置**,输入模型 ID、协议以及提供商的基础 URL 和 API 密钥。MiniMax Code 还需要上下文窗口和最大输出 token 数。之后该 Harness 显示 **就绪**。参阅[默认模型](../configuration.md#default-models)。
-## 签发 Project API 密钥 {#issue-a-project-api-key}
+## 签发项目 API 密钥 {#issue-a-project-api-key}
-1. 在 **Projects and keys** 中选择 **Create project**,然后选择 **Issue key**。对话框只显示一次密钥:复制并妥善保存。**How to call** 卡片展示 API 基础 URL 和示例请求。
+1. 在 **项目与密钥** 中选择 **创建项目**,然后选择 **签发密钥**。对话框只显示一次密钥:复制并妥善保存。**如何调用** 卡片展示 API 基础 URL 和示例请求。
2. 将密钥和 API 基础 URL 交给应用开发者,他们可以继续阅读[快速开始](quickstart.md)。
-Web 的 **Overview** 通过 **Getting started** 清单跟踪这些步骤。
+Web 的 **概览** 通过 **新手引导** 清单跟踪这些步骤。
## 添加沙箱容量 {#add-sandbox-capacity}
-安装程序不选择沙箱后端。根据你的基础设施选择部署方案:
+安装程序不选择沙箱提供商。根据你的基础设施选择部署方案:
-- **推荐:microsandbox 配合独立工作区存储。** 先准备 [NFS 文件系统和服务账户](../configuration.md#independent-workspace-storage),再在 **Settings** → **Sandbox and scheduling** 选择 **Own machines** 和 **microsandbox**,通过 **Nodes** [添加 Linux 节点](./nodes.md)。[节点指南](./nodes.md#before-you-add-a-node)同时说明了跨兼容节点恢复内存所需的私有检查点存储。
+- **推荐:microsandbox 配合独立工作区存储。** 先准备 [NFS 文件系统和服务账户](../configuration.md#independent-workspace-storage),再在 **设置** → **沙箱与调度** 选择 **自有机器** 和 **microsandbox**,通过 **节点** [添加 Linux 节点](./nodes.md)。[节点指南](./nodes.md#before-you-add-a-node)同时说明了跨兼容节点恢复内存所需的私有检查点存储。
- **托管计算:E2B。** 在同一个沙箱配置流程中选择 E2B 并配置凭据和模板。不需要执行节点;参阅[部署设置](../../../contracts/agents-api/zh/sandbox-deployment.md#initial-setup-and-same-provider-changes)。
- **其他支持的执行位置。** Docker 节点仍然可用,应用也可以连接[自托管机器](./self-hosted.md)。[提供商对照表](../../../contracts/agents-api/zh/sandbox-deployment.md#what-each-field-means-per-sandbox-provider)区分各方案的文件系统和挂起支持。
diff --git a/docs/zh/getting-started/nodes.md b/docs/zh/getting-started/nodes.md
index 89bff7e69..fc24c564b 100644
--- a/docs/zh/getting-started/nodes.md
+++ b/docs/zh/getting-started/nodes.md
@@ -4,15 +4,15 @@ source: docs/getting-started/nodes.md
source_hash: 56719d358e65d838d05bfb60b902a8d8f0803f833048be4a7c56c4731776ed0a
---
-节点是一台 Linux 主机,在沙箱后端为 microsandbox(推荐)或 Docker 时,为 Core 托管 Session 运行沙箱。Core 将新 Session 分配给有空余容量的节点;节点创建沙箱,沙箱回连 Core。E2B 不需要节点。应用为自己的 Session 连接的机器是[自托管执行器](self-hosted.md),而不是节点。
+节点是一台 Linux 主机,在沙箱提供商为 microsandbox(推荐)或 Docker 时,为 Core 托管 Session 运行沙箱。Core 将新 Session 分配给有空余容量的节点;节点创建沙箱,沙箱回连 Core。E2B 不需要节点。应用为自己的 Session 连接的机器是[自托管执行器](self-hosted.md),而不是节点。
添加节点的方法是在 Web 生成命令并在主机上执行。[沙箱部署协议](../../../contracts/agents-api/zh/sandbox-deployment.md)定义沙箱设置及其变更规则,[节点协议](../../../contracts/agents-api/zh/node-generation-protocol.md)定义节点如何准备和保留 Runtime 代次。
## 添加节点前 {#before-you-add-a-node}
-- **Core 已有主机及沙箱可访问的公开 URL。** 节点从 Core 控制台下载文件,并通过 `public_url` 连接 Core。设置前,Add node 显示 *Set a public address other machines can reach before adding nodes*;参阅[配置公开地址](install.md#configure-the-domain-and-https)。
-- **沙箱配置已保存。** 打开 **Settings** → **Sandbox and scheduling**,选择 **Own machines**、后端和沙箱规格,最后选择 **Save configuration**。要更改后端,先选择 **Reset deployment**。同一安装的所有节点使用同一后端。
-- **控制台能提供节点文件。** 节点从控制台下载 Runtime 和提供商文件;控制台缺少文件时重定向到发行下载地址。节点依据发行清单检查各文件的大小和 SHA-256。因此节点主机需要能访问发行下载地址。缺少文件时,Add node 显示 *This console has no node files for …*。
+- **Core 已有主机及沙箱可访问的公开 URL。** 节点从 Core 控制台下载文件,并通过 `public_url` 连接 Core。设置前,**添加节点** 显示 *添加节点前,请先设置其他机器能访问的公开地址。*参阅[配置公开地址](install.md#configure-the-domain-and-https)。
+- **沙箱配置已保存。** 打开 **设置** → **沙箱与调度**,选择 **自有机器**、沙箱提供商和沙箱规格,最后选择 **保存配置**。要更改沙箱提供商,先选择 **重置部署**。同一安装的所有节点使用同一沙箱提供商。
+- **控制台能提供节点文件。** 节点从控制台下载 Runtime 和提供商文件;控制台缺少文件时重定向到发行下载地址。节点依据发行清单检查各文件的大小和 SHA-256。因此节点主机需要能访问发行下载地址。缺少文件时,**添加节点** 显示 *这个控制台没有 … 的节点文件。*
Core 主机与其他主机一样加入:要在它上面运行沙箱,将它添加为节点。
@@ -24,9 +24,9 @@ Microsandbox 的检查点执行兼容性包含主机内核和 CPU profile。因
## 添加节点 {#add-a-node}
-1. 在 Web 打开 **Nodes**,选择 **Add node**。
-2. 设置 **Sandboxes at once**,使用 microsandbox 时还设置 **Retained sandboxes**,即节点[容量](../configuration.md#node-capacity)。之后可以通过 **Edit node** 修改。
-3. 选择 **Generate command** 并复制命令。命令仅注册一个节点、只能使用一次,且必须在 10 分钟内执行;Web 显示倒计时,过期后提供 **Generate new command**。
+1. 在 Web 打开 **节点**,选择 **添加节点**。
+2. 设置 **同时运行的沙箱**,使用 microsandbox 时还设置 **保留的沙箱**,即节点[容量](../configuration.md#node-capacity)。之后可以通过 **编辑节点** 修改。
+3. 选择 **生成命令** 并复制命令。命令仅注册一个节点、只能使用一次,且必须在 10 分钟内执行;Web 显示倒计时,过期后提供 **生成新命令**。
4. 在主机上执行。Web 跟踪节点从注册、连接到就绪的过程。
命令从你的控制台下载节点安装程序、检查 SHA-256,并使用一次性注册令牌运行它。安装程序下载节点文件并逐一对照发行清单验证、导入 Runtime 镜像、注册节点、启动服务,并等待 Core 报告节点已连接且就绪。程序不安装软件;前置条件缺失时,会在修改任何内容之前停止并输出一行提示。
@@ -35,7 +35,7 @@ Microsandbox 的检查点执行兼容性包含主机内核和 CPU profile。因
### 命令 {#the-command}
-从 **Nodes → Add node** 复制当前命令,其中已填入本安装的地址、校验和与注册令牌。命令先检查 Linux amd64、Python 3.9+ 和必要工具,再下载文件;临时网络故障最多尝试三次。校验失败时,从 Web 复制新命令重试。
+从 **节点 → 添加节点** 复制当前命令,其中已填入本安装的地址、校验和与注册令牌。命令先检查 Linux amd64、Python 3.9+ 和必要工具,再下载文件;临时网络故障最多尝试三次。校验失败时,从 Web 复制新命令重试。
- 下载到当前账号的私有 `~/.oac/node-bootstrap` 目录,检查 SHA-256,再通过 `sudo` 执行;root shell 中则直接执行。每次持锁清理下载残片后重试,已验证的 `.pyz` 保留供安装程序使用。
- 令牌通过标准输入传给安装程序,不出现在进程参数、环境变量或 sudo 日志中。
@@ -93,24 +93,24 @@ root 只准备账号、组和服务单元;其他操作(包括 Docker 网络
## 日志 {#logs}
-安装结束时输出节点日志命令(`Logs: …`)。节点报告问题,或注册约一分钟后仍未连接且就绪时,Add node 对话框也会展示它。
+安装结束时输出节点日志命令(`Logs: …`)。节点报告问题,或注册约一分钟后仍未连接且就绪时,**添加节点** 对话框也会展示它。
-运行 `sudo journalctl -u oac-node-.service`。root shell 中省略 `sudo`。安装 ID 位于命令的 `--installation-id` 参数,以及 **Settings → Service and deployment** 页面的 **Installation details** 中。
+运行 `sudo journalctl -u oac-node-.service`。root shell 中省略 `sudo`。安装 ID 位于命令的 `--installation-id` 参数,以及 **设置 → 服务与部署** 页面的 **安装详情** 中。
## 修改沙箱配置 {#change-the-sandbox-configuration}
沙箱设置适用于整个安装,节点跟随这些设置。
-- **规格、Runtime 版本、E2B 密钥或模板构建。** 打开 **Settings** → **Sandbox and scheduling** → **Change resources**,修改并保存。已有沙箱保持其配置。每个节点继续服务旧配置,同时准备新配置;**Nodes** 展示进度:**Preparing target**、**Ready for target**,或带[原因](#readiness-codes)的 **Preparation failed**。Core 优先在已准备好新配置的节点上放置新 Session;这些节点没有容量时,会使用仍服务旧配置的节点。E2B 变更立即生效。
-- **容量与空闲挂起。** 在 **Nodes** 中通过 **Edit node** 修改节点的活跃和保留上限。在 **Settings** → **Sandbox and scheduling** 中,通过 **Automatic suspension** → **Idle before suspension (seconds)** → **Save** 修改整个部署的[空闲策略](../../../contracts/agents-api/zh/sandbox-deployment.md#suspension-policy)。
-- **后端。** 同一页面选择 **Reset deployment**。自动重置立即归档空闲托管 Session,并让运行中的工作在设定截止时间前完成;强制重置立即取消工作。离线节点必须恢复连接,让 Core 确认清理。重置完成时,Core 已撤销所有节点和未使用命令:配置新后端后重新添加节点。**Cancel reset** 停止剩余工作;已归档 Session 仍保持归档。
+- **规格、Runtime 版本、E2B 密钥或模板构建。** 打开 **设置** → **沙箱与调度** → **修改资源**,修改并保存。已有沙箱保持其配置。每个节点继续服务旧配置,同时准备新配置;**节点** 展示进度:**正在准备目标配置**、**目标配置已就绪**,或带[原因](#readiness-codes)的 **目标配置准备失败**。Core 优先在已准备好新配置的节点上放置新 Session;这些节点没有容量时,会使用仍服务旧配置的节点。E2B 变更立即生效。
+- **容量与空闲挂起。** 在 **节点** 中通过 **编辑节点** 修改节点的活跃和保留上限。在 **设置** → **沙箱与调度** 中,通过 **自动挂起** → **空闲多久后挂起(秒)** → **保存** 修改整个部署的[空闲策略](../../../contracts/agents-api/zh/sandbox-deployment.md#suspension-policy)。
+- **沙箱提供商。** 同一页面选择 **重置部署**。自动重置立即归档空闲托管 Session,并让运行中的工作在设定截止时间前完成;强制重置立即取消工作。离线节点必须恢复连接,让 Core 确认清理。重置完成时,Core 已撤销所有节点和未使用命令:配置新的沙箱提供商后重新添加节点。**取消重置** 停止剩余工作;已归档 Session 仍保持归档。
[重置协议](../../../contracts/agents-api/zh/sandbox-deployment.md#generation-ownership-and-rollout)描述重置会归档和保留哪些内容。归档单个托管 Session 时,使用 [Core API](../../../contracts/agents-api/zh/admin-api.md#session-archive)。
## 移除节点 {#remove-a-node}
-1. 在 Web 打开 **Nodes**,在节点页面选择 **Remove node**,或在列表行选择 **Remove**,再选择 **Confirm removal**。节点仍持有沙箱、快照或待清理资源时,Core 拒绝操作;等待完成或归档对应 Session。移除是永久的:主机只能作为新节点重新加入。移除所有节点仍保留沙箱配置。
-2. Web 随后展示 **Clean up the host** 和卸载命令。在主机执行:
+1. 在 Web 打开 **节点**,在节点页面选择 **移除节点**,或在列表行选择 **移除**,再选择 **确认移除**。节点仍持有沙箱、快照或待清理资源时,Core 拒绝操作;等待完成或归档对应 Session。移除是永久的:主机只能作为新节点重新加入。移除所有节点仍保留沙箱配置。
+2. Web 随后展示 **清理主机** 和卸载命令。在主机执行:
```sh
(umask 077; d=$(mktemp -d) || exit; trap 'rm -rf "$d"' EXIT; s=; [ "$(id -u)" -eq 0 ] || s=sudo
@@ -121,16 +121,16 @@ root 只准备账号、组和服务单元;其他操作(包括 Docker 网络
$s python3 "$d/node-install.pyz" ${NO_COLOR+--no-color} --uninstall --installation-id '')
```
-卸载先向节点注册时使用的 Core 地址确认节点是否已移除;Core 仍列出该节点时拒绝卸载。注册地址与当前公开 URL 不同时,对话框还展示 **Old Core address gone?**:该地址不再响应时,提供带 `--force` 的命令以跳过检查;先在 Nodes 页面移除节点。不使用对话框时,从 `https://core.example/node-install/SHA256SUMS` 的 `node-install.pyz` 行获取安装程序 SHA-256。卸载停止并移除服务、节点状态、记录和 Docker 网络。只有安装程序创建了 `oac-node` 且不再有节点时,才删除该账号;复用的账号仅移除安装程序添加的组。
+卸载先向节点注册时使用的 Core 地址确认节点是否已移除;Core 仍列出该节点时拒绝卸载。注册地址与当前公开 URL 不同时,对话框还展示 **旧 Core 地址已失效?**:该地址不再响应时,提供带 `--force` 的命令以跳过检查;先在 **节点** 页面移除节点。不使用对话框时,从 `https://core.example/node-install/SHA256SUMS` 的 `node-install.pyz` 行获取安装程序 SHA-256。卸载停止并移除服务、节点状态、记录和 Docker 网络。只有安装程序创建了 `oac-node` 且不再有节点时,才删除该账号;复用的账号仅移除安装程序添加的组。
程序不删除沙箱、卷或镜像。保留 Runtime 镜像并输出 `docker image rm` 命令。microsandbox 保留 `/var/lib/oac-node/.oac/m/` 存储,并输出删除方法(`sudo -u oac-node rm -rf `);存储删除前保留所创建的账号,之后重新卸载。使用 `--force` 时 microVM 可能仍使用存储,请先检查 `pgrep -u oac-node`。可以重复卸载直到完成。
## 手动注册节点 {#register-a-node-manually}
-如果自行管理节点文件和服务,而不执行 Web 命令,请使用手动注册。手动注册的节点只服务注册时的配置:规格或 Runtime 修改后,**Nodes** 显示 **Node software incompatible**;它继续服务旧配置,直到移除节点并重新注册主机。
+如果自行管理节点文件和服务,而不执行 Web 命令,请使用手动注册。手动注册的节点只服务注册时的配置:规格或 Runtime 修改后,**节点** 显示 **节点程序不兼容**;它继续服务旧配置,直到移除节点并重新注册主机。
1. 使用与 Core 同一发行版本的 `oac-node`。
-2. 获取注册令牌:使用 **Add node** 命令中的令牌,或通过 Core 密钥调用 `POST /core/v1/sandbox/enrollment-tokens`。令牌一次性使用,包含批准的节点容量;响应的 `expires_at` 给出过期时间。在主机上存入权限为 `0600` 的文件。
+2. 获取注册令牌:使用 **添加节点** 命令中的令牌,或通过 Core 密钥调用 `POST /core/v1/sandbox/enrollment-tokens`。令牌一次性使用,包含批准的节点容量;响应的 `expires_at` 给出过期时间。在主机上存入权限为 `0600` 的文件。
3. 使用令牌读取节点配置,不会消耗令牌:`GET /api/v1/sandbox-node/configuration`,带 `Authorization: Bearer `。
4. 写入私有提供商文件。从响应复制 `provider`、`installation_id`、`core_url`、`generation` 和 `specification`,并添加 `native` 对象,写入该提供商的主机设置。适配器从 `specification` 读取沙箱规格、Runtime 镜像和产物哈希:
- Docker:[Docker 节点配置](../configuration.md#docker-node-configuration)中的字段,其中 `host` 是显式 Unix 套接字,`image` 是导入的 Runtime 镜像的本地 ID,`seccomp_file` 是绝对路径。
@@ -156,29 +156,29 @@ root 只准备账号、组和服务单元;其他操作(包括 Docker 网络
## 节点主机故障时 {#when-a-node-host-fails}
-重启节点服务会保留身份并重新发现已有沙箱。Core 不会仅因节点不可达或沙箱缺失就接管活动或未确认的 writer:所有权未结清时,这些资源显示 **Node disconnected** 或 **Sandbox resource missing**。主机崩溃或挂起时,应重启主机而不是移除其节点:节点重新连接后,节点确认已不存在的运行中沙箱会按[已确认的计算资源丢失](../sandbox-provider.md#confirmed-compute-loss)规则释放,Session 的下一个 input 在新计算资源上续接;其他缺失的沙箱保持 **Sandbox resource missing**。主机始终未恢复时,其 Session 的计算资源归属保持不变。已结清的保留检查点可以遵循[检查点转移契约](../sandbox-provider.md#checkpoint-transfer),确认释放后可以按条件进行[冷替换](../sandbox-provider.md#cold-replacement-after-checkpoint-retention)。丢失节点状态目录属于恢复事件:从[备份](operations.md#back-up)恢复,并同时恢复数据库和提供商存储;不要在已有资源上重新注册主机。
+重启节点服务会保留身份并重新发现已有沙箱。Core 不会仅因节点不可达或沙箱缺失就接管活动或未确认的 writer:所有权未结清时,这些资源显示 **节点已断开** 或 **沙箱资源缺失**。主机崩溃或挂起时,应重启主机而不是移除其节点:节点重新连接后,节点确认已不存在的运行中沙箱会按[已确认的计算资源丢失](../sandbox-provider.md#confirmed-compute-loss)规则释放,Session 的下一个 input 在新计算资源上续接;其他缺失的沙箱保持 **沙箱资源缺失**。主机始终未恢复时,其 Session 的计算资源归属保持不变。已结清的保留检查点可以遵循[检查点转移契约](../sandbox-provider.md#checkpoint-transfer),确认释放后可以按条件进行[冷替换](../sandbox-provider.md#cold-replacement-after-checkpoint-retention)。丢失节点状态目录属于恢复事件:从[备份](operations.md#back-up)恢复,并同时恢复数据库和提供商存储;不要在已有资源上重新注册主机。
## 问题排查 {#troubleshooting}
### 就绪状态码 {#readiness-codes}
-节点在线但沙箱提供商未就绪时,**Nodes** 和 **Overview** 显示 **Provider not ready**。原因展示位置取决于节点添加方式:
+节点在线但沙箱提供商未就绪时,**节点** 和 **概览** 显示 **沙箱提供商未就绪**。原因展示位置取决于节点添加方式:
-- **使用 Web 命令添加的节点**:当前沙箱配置检查失败时,在目标状态显示 **Preparation failed**,帮助提示中给出原因(`GET /core/v1/sandbox/nodes` 的 `rollout.diagnostic`)。**Provider not ready** 旁的提示仅显示 *Sandbox provider unavailable*。
-- **手动注册的节点**:在 **Provider not ready** 旁的帮助提示展示原因(`diagnostic`)。
+- **使用 Web 命令添加的节点**:当前沙箱配置检查失败时,在目标状态显示 **目标配置准备失败**,帮助提示中给出原因(`GET /core/v1/sandbox/nodes` 的 `rollout.diagnostic`)。**沙箱提供商未就绪** 旁的提示仅显示 *沙箱提供商不可用*。
+- **手动注册的节点**:在 **沙箱提供商未就绪** 旁的帮助提示展示原因(`diagnostic`)。
-每个状态码都是与 Provider 无关的类别;其背后的本地错误留在节点上。手动注册的节点会把它写入日志。对于使用 Web 命令添加的节点,请在主机上重新运行该命令:安装程序会先检查主机要求,并指出需要修复的问题([安装程序消息](#installer-messages))。
+每个状态码都是与提供商无关的类别;其背后的本地错误留在节点上。手动注册的节点会把它写入日志。对于使用 Web 命令添加的节点,请在主机上重新运行该命令:安装程序会先检查主机要求,并指出需要修复的问题([安装程序消息](#installer-messages))。
节点按如下顺序仅报告首个失败检查:Docker 守护进程或 KVM、Docker 限制支持、主机容量、已安装的 Runtime 文件。因此无法访问 Docker 守护进程时,会隐藏镜像缺失问题。修复后约十秒的下一次心跳会清除或替换状态码。离线节点保留最后状态码,Web 在节点重连前隐藏它。
| 状态码 | 帮助提示 | 原因 | 解决方法 |
| --- | --- | --- | --- |
-| `provider_unavailable` | Sandbox provider unavailable | 提供商的服务不可达或请求失败(例如 Docker 守护进程已停止),或失败没有类别 | 重新运行节点的命令,或阅读手动注册节点的日志 |
-| `host_unsupported` | Host unsupported | 主机缺少提供商所需的能力,例如 Docker 的 CPU 与内存限制(cgroup v2)或对 `/dev/kvm` 的读写权限 | 重新运行节点的命令,或阅读手动注册节点的日志 |
-| `capacity_insufficient` | Host too small | 主机 CPU 或内存不足以运行一个沙箱 | 使用更大主机或修改沙箱规格 |
-| `runtime_image_unavailable` | Runtime image missing | 提供商中没有固定版本的 Runtime 镜像 | Web 命令添加的节点自动重新下载;其他节点加载匹配发行版镜像 |
-| `artifacts_unavailable` | Provider files missing | 固定版本的提供商文件(例如 microsandbox 的 Runtime、固件或辅助程序)缺失或 SHA-256 检查失败 | Web 命令添加的节点自动下载缺失文件;其他节点从匹配发行版恢复 |
-| `runtime_download_failed` | Runtime download failed | 准备新配置时无法下载或验证 Runtime 文件 | 检查节点到控制台和发行下载地址的 HTTPS 访问。节点以递增间隔重试,最长间隔 30 分钟 |
+| `provider_unavailable` | 沙箱提供商不可用 | 提供商的服务不可达或请求失败(例如 Docker 守护进程已停止),或失败没有类别 | 重新运行节点的命令,或阅读手动注册节点的日志 |
+| `host_unsupported` | 主机不满足要求 | 主机缺少提供商所需的能力,例如 Docker 的 CPU 与内存限制(cgroup v2)或对 `/dev/kvm` 的读写权限 | 重新运行节点的命令,或阅读手动注册节点的日志 |
+| `capacity_insufficient` | 主机资源不足 | 主机 CPU 或内存不足以运行一个沙箱 | 使用更大主机或修改沙箱规格 |
+| `runtime_image_unavailable` | 缺少 Runtime 镜像 | 提供商中没有固定版本的 Runtime 镜像 | Web 命令添加的节点自动重新下载;其他节点加载匹配发行版镜像 |
+| `artifacts_unavailable` | 沙箱提供商文件缺失 | 固定版本的提供商文件(例如 microsandbox 的 Runtime、固件或辅助程序)缺失或 SHA-256 检查失败 | Web 命令添加的节点自动下载缺失文件;其他节点从匹配发行版恢复 |
+| `runtime_download_failed` | Runtime 下载失败 | 准备新配置时无法下载或验证 Runtime 文件 | 检查节点到控制台和发行下载地址的 HTTPS 访问。节点以递增间隔重试,最长间隔 30 分钟 |
新用户组成员关系仅对新进程生效。重启节点服务:`sudo systemctl restart oac-node-.service`。已注册但从未连接的节点通常无法通过公开 URL 访问 Core,或 `/api/v1` WebSocket 无法通过反向代理。
diff --git a/docs/zh/getting-started/operations.md b/docs/zh/getting-started/operations.md
index 49909592b..c40e3dc2a 100644
--- a/docs/zh/getting-started/operations.md
+++ b/docs/zh/getting-started/operations.md
@@ -1,7 +1,7 @@
---
title: "运维"
source: docs/getting-started/operations.md
-source_hash: 71bb1b6be0c26e626f3b93e92ffb566482281f46dbee674beebb7bd345803de0
+source_hash: dbbd6d6729435146779a1fcf0d262ca4b9d4f45859b80f5804c945ef68e4f07c
---
安装运维人员负责 Core 主机、存储和可用性。节点主机运行各自的服务;参阅[节点](nodes.md)。设置见[配置参考](../configuration.md)。
@@ -38,7 +38,7 @@ docker compose -f ~/.oac/core/compose.yaml ps
| Environment 连接 | Runtime 传输已连接 |
| 已完成的 Turn 及结果 | 任务已记录的结果 |
-服务健康状态不表示 Harness 或模型可用。执行情况使用 Session、Turn、Items 和 Usage 读取,节点连接、就绪和分配使用 Web 的 **Nodes** 页面。本地诊断使用安装自身的 Compose 文件:
+服务健康状态不表示 Harness 或模型可用。执行情况使用 Session、Turn、Items 和 Usage 读取,节点连接、就绪和分配使用 Web 的 **节点** 页面。本地诊断使用安装自身的 Compose 文件:
```sh
docker compose -f "$HOME/.oac/core/compose.yaml" ps --all
@@ -52,7 +52,7 @@ docker compose -f "$HOME/.oac/core/compose.yaml" logs --timestamps init
## 请求诊断 {#request-diagnosis}
-打开 **Monitor → Request log** 查看近期请求,并复制请求 ID 与 Core 服务日志关联。[请求日志](../../../contracts/agents-api/zh/admin-api.md#request-log)定义范围、隐私及有限的内存保留方式。请求接受了异步 Turn 时,请到 **Session log** 查看执行结果;HTTP 接受不等于任务成功。跨重启或 Core 实例的留存使用已有日志采集系统。
+打开 **监控 → 请求日志** 查看近期请求,并复制请求 ID 与 Core 服务日志关联。[请求日志](../../../contracts/agents-api/zh/admin-api.md#request-log)定义范围、隐私及有限的内存保留方式。请求接受了异步 Turn 时,请到 **Session 日志** 查看执行结果;HTTP 接受不等于任务成功。跨重启或 Core 实例的留存使用已有日志采集系统。
## 停止与重启 {#stop-and-restart}
@@ -73,7 +73,7 @@ Web 重启(包括 `oac apply` 引起的重启)会让所有控制台用户退
- 用于登录 Web。浏览器获得 HttpOnly 会话 cookie,不持有密钥;
- 通过 `Authorization: Bearer ` 授权 Core API(`/core/v1`)请求;
-- 不授权 Agents API(`/v1`)。应用使用 Project API 密钥,后者也不能调用 `/core/v1`。
+- 不授权 Agents API(`/v1`)。应用使用项目 API 密钥,后者也不能调用 `/core/v1`。
请保密。Web 读取 `secrets/web/core.key`。Core 只读取 `secrets/core/core-key-digests.json` 中的 SHA-256。Core 密钥至少 32 字符且不含空白。Web 限制失败登录。
@@ -92,11 +92,11 @@ core() ( # core METHOD PATH [JSON body]
| 任务 | 命令 |
| --- | --- |
-| 列出 Project | `core GET /projects` |
-| 创建 Project | `core POST /projects '{"name": "billing-bot"}'` |
+| 列出项目 | `core GET /projects` |
+| 创建项目 | `core POST /projects '{"name": "billing-bot"}'` |
| 签发 API 密钥(仅显示一次,字段为 `key`) | `core POST /projects/$PROJECT_ID/keys '{"name": "prod"}'` |
| 撤销密钥 | `core DELETE /projects/$PROJECT_ID/keys/$KEY_ID` |
-| 归档 Project(撤销全部密钥) | `core POST /projects/$PROJECT_ID/archive` |
+| 归档项目(撤销全部密钥) | `core POST /projects/$PROJECT_ID/archive` |
| 查看 Harness 及默认模型 | `core GET /harnesses` |
| 设置 Codex 默认模型 | `core PUT /harnesses/codex/model-configuration '{"model": "your-model-id", "model_provider": {"protocol": "responses", "base_url": "https://provider.example/v1", "api_key": "sk-..."}}'` |
| 安装信息,包括 API 基础 URL | `core GET /installation` |
@@ -111,17 +111,17 @@ core() ( # core METHOD PATH [JSON body]
它在初始化容器中更新数据卷内的 `secrets/web/core.key` 和 `secrets/core/core-key-digests.json`,然后重启 Core 与 Web。Core 重启后旧密钥立即失效,控制台会话也会结束;请重新登录并更新脚本。
-## Project 和 API 密钥 {#projects-and-api-keys}
+## 项目和 API 密钥 {#projects-and-api-keys}
-在 Web 的 **Projects and keys**,或通过 [Core API](#script-the-core-api)创建 Project、签发密钥。Project 和密钥行为见 [Project 拥有资产](../concepts.md#projects-own-assets)。
+在 Web 的 **项目与密钥**,或通过 [Core API](#script-the-core-api)创建项目、签发密钥。项目和密钥行为见 [项目拥有资产](../concepts.md#projects-own-assets)。
轮换应用密钥:
-1. 在同一 Project 签发新密钥。
+1. 在同一项目签发新密钥。
2. 更新应用以使用它。
-3. **Revoke** 旧密钥。
+3. **撤销** 旧密钥。
-**Archive** 禁用 Project 的所有密钥并保留资产。
+**归档** 禁用项目的所有密钥并保留资产。
Core 记录每次公开资源写入所使用的密钥;历史保留策略为 [`OAC_WRITE_AUDIT_RETENTION`](../configuration.md#settings)。
@@ -131,11 +131,11 @@ Core 记录每次公开资源写入所使用的密钥;历史保留策略为 [`
### 备份内容 {#backup-contents}
-- Docker 卷 `_data`,包括 `database/`、`secrets/` 和 `state/`。其中保存 Project、密钥摘要、节点、默认模型、加密凭据和执行历史(含大对象)。`secrets/core/credential.key` 必须与匹配的数据库一起保留,否则存储的凭据无法解密。
+- Docker 卷 `_data`,包括 `database/`、`secrets/` 和 `state/`。其中保存项目、密钥摘要、节点、默认模型、加密凭据和执行历史(含大对象)。`secrets/core/credential.key` 必须与匹配的数据库一起保留,否则存储的凭据无法解密。
- 安装目录,包括 `.env`、`compose.yaml`、Compose 覆盖文件和管理命令。
- 当前或保留对象所使用的每个独立工作区命名空间,即使其位于安装卷之外。备份整个根目录,包括 `.oac-storage-root`、对象标识、staging、live 数据、trash 和删除标记。保留数值所有者、权限、链接及扩展属性,包括全部 `user.*` 属性。仅复制 `live/data` 会丢失生命周期证据,并可能使已删除标识复活。[工作区存储](../workspace-provider.md#kernel-nfs-adapter)负责定义布局与所有权要求。
- 对于[配额模式](../workspace-provider.md#quota-mode)命名空间,将承载导出的整个 XFS 文件系统作为一份块级副本备份:存储或 LVM 快照,或已冻结或已卸载设备的镜像。只有这样的副本能保持 project ID、配额限制、inode 标识、文件系统 UUID 和 `oac-workspace-quota` 日志库的一致。文件级复制、`tar`、`rsync` 或 `xfsdump` 会丢失这些信息;此时该命令会拒绝恢复后的对象,而不是在无上限状态下提供它们。
-- 各节点状态目录 `/var/lib/oac-node/.oac/nodes//` 及其 Provider 存储:Docker 卷或 microsandbox 存储。包含数据库仍然引用的全部计算资源和快照。参见[节点主机故障时](./nodes.md#when-a-node-host-fails)。
+- 各节点状态目录 `/var/lib/oac-node/.oac/nodes//` 及其提供商存储:Docker 卷或 microsandbox 存储。包含数据库仍然引用的全部计算资源和快照。参见[节点主机故障时](./nodes.md#when-a-node-host-fails)。
- 每个私有 `checkpoint_root` 的全部内容,包括 `.oac-checkpoint-store`、归档、operation journal、lock 文件与 tombstone,并与匹配的 Core 数据库一起保留。它独立于原生 SDK store 和工作区 namespace。保留其身份和私有所有权;[检查点转移契约](../sandbox-provider.md#checkpoint-transfer)定义其生命周期。
@@ -143,8 +143,8 @@ Core 记录每次公开资源写入所使用的密钥;历史保留策略为 [`
1. 在安装入口阻止新应用 input、实时文件访问和管理变更。等待活动执行、初始化、文件操作和原生清理完成。停止其他能够写入同一文件系统的应用或主机进程。
2. 保持 Core 和节点可用,确认每个所属写入方均已停止,且所有 Create、Kill、快照清理及文件系统变更均已结算。节点离线、超时、实例缺失或服务停止均不足以证明这一点。确认挂起会停止源计算资源,但保留的检查点也必须纳入备份。最简单的冷恢复基线是等待符合条件的保留 Session 完成检查点到期清理、allocation 已释放,再按[冷替换契约](../sandbox-provider.md#cold-replacement-after-checkpoint-retention)保留文件系统对象及原生历史。
-3. 停止 Core 和 Web,再停止节点控制服务,以防止新的生命周期操作。重新核实精确的原生资源,保持所有写入方停止,直到备份各部分全部完成。**停止 Core 或节点服务不会停止其沙箱。** 节点服务使用 `KillMode=process`;microVM 及其他由 Provider 管理的计算资源可能继续独立运行。
-4. 使用存储平台支持的流程将已停止写入的文件系统中的待写数据落盘,并创建其快照或导出。对于配额模式,在复制其设备期间使用 `xfs_freeze -f` 冻结 XFS 文件系统或将其卸载,完成后解冻。在同一窗口内导出 Core 数据卷、安装目录及所需的节点状态和 Provider 存储。复制 PostgreSQL 的 `database/` 文件前必须停止 PostgreSQL。一起记录版本、备份时间、组成清单和校验值,并将备份保存在被备份安装之外。
+3. 停止 Core 和 Web,再停止节点控制服务,以防止新的生命周期操作。重新核实精确的原生资源,保持所有写入方停止,直到备份各部分全部完成。**停止 Core 或节点服务不会停止其沙箱。** 节点服务使用 `KillMode=process`;microVM 及其他由提供商管理的计算资源可能继续独立运行。
+4. 使用存储平台支持的流程将已停止写入的文件系统中的待写数据落盘,并创建其快照或导出。对于配额模式,在复制其设备期间使用 `xfs_freeze -f` 冻结 XFS 文件系统或将其卸载,完成后解冻。在同一窗口内导出 Core 数据卷、安装目录及所需的节点状态和提供商存储。复制 PostgreSQL 的 `database/` 文件前必须停止 PostgreSQL。一起记录版本、备份时间、组成清单和校验值,并将备份保存在被备份安装之外。
5. 所有复制完成后才恢复服务。先恢复存储,再启动 Core 和节点,验证就绪后开放入口。不要通过重放不确定的原生操作来让备份通过。
当前没有一条命令即可完成且无损的维护排空流程。归档和部署重置会改变 Session 生命周期状态,不能替代保持续接能力的备份暂停。任何写入方或变更仍然未知时,应将备份保留为未完成状态,先解决相应归属。
@@ -162,9 +162,9 @@ docker compose -f "$HOME/.oac/core/compose.yaml" exec -T database \
恢复期间保持应用入口及 Core/节点服务关闭。暴露恢复后的文件系统前,必须隔离或关闭每一个旧写入方;旧主机不可达不代表已隔离。演练必须使用隔离的安装和存储副本,不能连接原节点,也不能共享其可写命名空间。
-启动 Core 前,恢复相匹配的 secrets 和数据库状态、完整的独立文件系统命名空间,以及任何所需的节点标识和 Provider 存储。保留数据库中的配置和命名空间 UUID、对象标识及删除标记;不要对恢复后的存储执行首次命名空间初始化。恢复配额模式文件系统时,将其块级副本写入后备设备,并以 `prjquota` 挂载到配置的挂载点;绝不要对其运行 `oac-workspace-quota init`,也不要将副本与原文件系统同时挂载,二者具有相同的文件系统 UUID。重新建立配置中的挂载路径和服务 UID,然后从每个参与服务的上下文验证所挂载文件系统、所有权及 xattr。[独立工作区存储](../configuration.md#independent-workspace-storage)负责定义部署设置。
+启动 Core 前,恢复相匹配的 secrets 和数据库状态、完整的独立文件系统命名空间,以及任何所需的节点标识和提供商存储。保留数据库中的配置和命名空间 UUID、对象标识及删除标记;不要对恢复后的存储执行首次命名空间初始化。恢复配额模式文件系统时,将其块级副本写入后备设备,并以 `prjquota` 挂载到配置的挂载点;绝不要对其运行 `oac-workspace-quota init`,也不要将副本与原文件系统同时挂载,二者具有相同的文件系统 UUID。重新建立配置中的挂载路径和服务 UID,然后从每个参与服务的上下文验证所挂载文件系统、所有权及 xattr。[独立工作区存储](../configuration.md#independent-workspace-storage)负责定义部署设置。
-已释放计算资源的冷恢复基线仅在新计算资源准入后续接具备资格的原生历史。包含保留检查点的备份还依赖匹配的原生 Runtime、节点标识、Provider 存储和外部文件系统标识。文件级恢复可能改变 inode 标识,即使文件字节一致,也可能阻止严格检查点恢复。此流程不承诺可移植内存快照,也不承诺恢复到任意替代节点;应保留未解决的归属,而不是替换为新沙箱。
+已释放计算资源的冷恢复基线仅在新计算资源准入后续接具备资格的原生历史。包含保留检查点的备份还依赖匹配的原生 Runtime、节点标识、提供商存储和外部文件系统标识。文件级恢复可能改变 inode 标识,即使文件字节一致,也可能阻止严格检查点恢复。此流程不承诺可移植内存快照,也不承诺恢复到任意替代节点;应保留未解决的归属,而不是替换为新沙箱。
恢复依赖全部完整后才启动 database、Core 和节点服务;检查期间保持入口受限。在隔离演练中,验证保留 Session 的文件和具备资格时在新计算资源上的原生续接,确认已删除对象无法重新打开,并检查旧写入方均无法访问恢复后的命名空间。在依赖备份进行恢复前记录结果。
@@ -178,7 +178,7 @@ cd && rm -rf ~/.oac/core
`down --volumes` 会删除安装数据卷。之后删除安装目录;Windows 使用 `Remove-Item -Recurse "$HOME/.oac/core"`。
-全部数据随之删除:Project 和 API 密钥、Session 历史、存储的凭据和 Core 密钥。要保留数据,请用 `docker compose stop` 停止安装,或先[备份](#back-up)。
+全部数据随之删除:项目和 API 密钥、Session 历史、存储的凭据和 Core 密钥。要保留数据,请用 `docker compose stop` 停止安装,或先[备份](#back-up)。
卸载不停止沙箱:节点沙箱在节点继续运行,E2B 沙箱在 E2B 继续运行并计费。Core 仍运行时,归档它们的 Session,或[重置部署](nodes.md#change-the-sandbox-configuration)并等待完成;命令展示 Core 正在使用的沙箱数量。
@@ -206,7 +206,7 @@ cd && rm -rf ~/.oac/core
| Web 返回 403 `Forbidden` | 浏览器主机名不是 `OAC_PUBLIC_URL`。打开该源地址;反向代理必须传递原始 Host |
| Web 显示 Core 不可用(502) | Core 停止或失败:先 `docker compose ps`,再查看 Core 日志 |
| 创建 Session 返回 400 `model_provider_required` | 缺少模型提供商:为 Harness 设置[默认模型](../configuration.md#default-models),或显式提供;自托管 Session 始终自带提供商 |
-| Add node 不展示命令 | 参阅[添加节点前](nodes.md#before-you-add-a-node) |
+| **添加节点** 不展示命令 | 参阅[添加节点前](nodes.md#before-you-add-a-node) |
| 节点未就绪 | 参阅[节点问题排查](nodes.md#troubleshooting) |
## 对外暴露与网络策略 {#exposure-and-network-policy}
diff --git a/docs/zh/getting-started/quickstart.md b/docs/zh/getting-started/quickstart.md
index 276987d31..b4d499ed2 100644
--- a/docs/zh/getting-started/quickstart.md
+++ b/docs/zh/getting-started/quickstart.md
@@ -1,13 +1,13 @@
---
title: "运行第一个 Session"
source: docs/getting-started/quickstart.md
-source_hash: 8c44adf64e32f23578128c60f401b38de809954ceec79540acd10e353c32d6b4
+source_hash: 36731629434acafda8c48640aba3eda4967622525ed1b9dbf49ba40769513bc3
---
-本教程从 Project API 密钥开始,让 Agent 创建一个文件并汇报结果。你需要:
+本教程从项目 API 密钥开始,让 Agent 创建一个文件并汇报结果。你需要:
-- 管理员提供的 Project API 密钥和 API 基础 URL([签发 Project API 密钥](install.md#issue-a-project-api-key));
-- 已就绪的节点或 E2B 后端,让 Core 能运行 Agent([节点](nodes.md));
+- 管理员提供的项目 API 密钥和 API 基础 URL([签发项目 API 密钥](install.md#issue-a-project-api-key));
+- 已就绪的节点或 E2B 沙箱提供商,让 Core 能运行 Agent([节点](nodes.md));
- Python 3.9 或更高版本;
- 一个模型:安装的默认模型,或你自己的提供商的模型 ID、基础 URL 和 API 密钥。[模型执行](../../../contracts/agents-api/zh/model-execution.md#saved-defaults-and-precedence)说明 Session 使用哪个模型,以及每个 Harness 支持哪些协议。
@@ -19,8 +19,8 @@ Core 提供 OpenAI Agents API,因此无需修改官方 OpenAI SDK。SDK 读取
| 变量 | 值 |
| --- | --- |
-| `OPENAI_BASE_URL` | API 基础 URL:公开 URL 加 `/v1`,例如 `https://core.example/v1`。Web 的 **Settings → Service and deployment** 页面会显示它 |
-| `OPENAI_API_KEY` | 你的 Project API 密钥 |
+| `OPENAI_BASE_URL` | API 基础 URL:公开 URL 加 `/v1`,例如 `https://core.example/v1`。Web 的 **设置 → 服务与部署** 页面会显示它 |
+| `OPENAI_API_KEY` | 你的项目 API 密钥 |
```sh
python3 -m venv .venv
diff --git a/docs/zh/getting-started/self-hosted.md b/docs/zh/getting-started/self-hosted.md
index 9a075178b..4698c2402 100644
--- a/docs/zh/getting-started/self-hosted.md
+++ b/docs/zh/getting-started/self-hosted.md
@@ -6,7 +6,7 @@ source_hash: c42a64b5e59406594143866c503817525c55ea844d858f25119c8fa54993134c
`self_hosted` Session 在应用拥有的机器上运行:工作站、虚拟机或你管理的沙箱。应用通过 `/v1` 创建 Session,并获得安装 `oac-daemon`、启动它并连接 Core 的命令。Web 在 Session 页面展示同一命令;Web 是可选的。Core 不创建、停止或回收这台机器。
-**守护进程不是沙箱。** 工具以启动守护进程的账号权限运行,能访问该账号可访问的所有资源。需要隔离时,请使用容器或虚拟机;参阅 [Runtime 与外层隔离](../concepts.md#runtime-and-outer-isolation)。守护进程不限制网络访问,因此要求网络策略的 Template 会被自托管 Session 拒绝。
+**守护进程不是沙箱。** 工具以启动守护进程的账号权限运行,能访问该账号可访问的所有资源。需要隔离时,请使用容器或虚拟机;参阅 [Runtime 与外层隔离](../concepts.md#runtime-and-outer-isolation)。守护进程不限制网络访问,因此要求网络策略的模板会被自托管 Session 拒绝。
Session 自带模型提供商;安装默认模型不适用([原因](../../../contracts/agents-api/zh/model-execution.md#saved-defaults-and-precedence))。机器获得的执行器凭据仅适用于这一个 Environment。
@@ -31,7 +31,7 @@ Session 自带模型提供商;安装默认模型不适用([原因](../../../
## 连接机器 {#connect-a-machine}
-1. 在目标机器上选择绝对工作区路径。使用该路径和应用的 Project API 密钥创建 Session:
+1. 在目标机器上选择绝对工作区路径。使用该路径和应用的项目 API 密钥创建 Session:
```python
import os
@@ -59,7 +59,7 @@ Session 自带模型提供商;安装默认模型不适用([原因](../../../
2. 在目标机器上,以应运行工具的账号执行命令。命令下载与 Core 匹配的安装程序、验证校验和、询问要安装哪些 Harness 以及安装位置、完成安装、按需创建工作区、启动守护进程并检查连接。
3. 发送一个 Turn。机器已连接只证明认证成功;第一个 Turn 才会检查 Harness 和模型。
-在 Web 中打开 Session,复制 **Connect a host** 下的命令。
+在 Web 中打开 Session,复制 **连接主机** 下的命令。
请保密该命令:它包含短期[安装授权](../../../contracts/agents-api/zh/environment-executor-credentials.md#installation-grant),用于领取机器凭据。过期后重新读取 Session,或从 Web 复制新命令。
@@ -103,7 +103,7 @@ environment = {
路径使用机器自身语法的绝对路径(Unix、Windows 驱动器或 UNC);由守护进程而非 Core 检查。守护进程连接前,先准备这些目录。它们是守护进程可见的普通路径;指定路径不会挂载它或创建沙箱。
-使用 `x_agents_core.environment` 提供与托管 Session 相同的 Project 所属 Skills、Plugin 归档、文件、软件包、设置命令或 Template:
+使用 `x_agents_core.environment` 提供与托管 Session 相同的项目所属 Skills、Plugin 归档、文件、软件包、设置命令或模板:
```python
session = client.beta.agents.sessions.create(
@@ -131,7 +131,7 @@ session = client.beta.agents.sessions.create(
| `oac-daemon logs -n 100`、`oac-daemon logs -f` | 输出或持续跟踪守护进程日志 |
| `oac-daemon stop` | 停止守护进程 |
-设置了 `OAC_RUNTIME_HOME` 时,每个命令都使用同一值。在 Web 的 Session 页面 **Host connection** 下检查连接,或使用[连接状态](../../../contracts/agents-api/zh/environment-executor-credentials.md#connection-status)。
+设置了 `OAC_RUNTIME_HOME` 时,每个命令都使用同一值。在 Web 的 Session 页面 **主机连接** 下检查连接,或使用[连接状态](../../../contracts/agents-api/zh/environment-executor-credentials.md#connection-status)。
添加 Harness 时,以同一安装目录重新执行安装命令,并指定要添加的 Harness(命令过期时从 Web 复制新的)。安装程序检查已有内容、只添加缺失组件,并保留已安装的 Harness。之后重启正在运行的守护进程,让它发现新的 Harness。
@@ -139,16 +139,16 @@ session = client.beta.agents.sessions.create(
## 轮换或撤销 {#rotate-or-revoke}
-在 Web 中,Session 的 **Executor credentials** 列出机器凭据:
+在 Web 中,Session 的 **执行器凭据** 列出机器凭据:
| 操作 | 效果 |
| --- | --- |
-| **Rotate** | 凭据获得新密钥;旧密钥立即失效。已撤销凭据的操作为 **Restore** |
-| **Revoke** | 凭据立即失效 |
+| **轮换** | 凭据获得新密钥;旧密钥立即失效。已撤销凭据的操作为 **恢复** |
+| **撤销** | 凭据立即失效 |
轮换后重新连接时,通过 `oac-daemon stop` 停止守护进程,用新凭据替换已配置的凭据文件路径中的 JSON,然后运行 `oac-daemon start`。不要再次对已有安装运行 `install`;轮换现有凭据,而非签发第二个凭据,后者[无法连接](../../../contracts/agents-api/zh/environment-executor-credentials.md#revoked-or-rotated-credential)。
-已归档 Project 无法签发或轮换凭据,仍可撤销。运维人员可以使用 Core 密钥管理凭据;参阅[凭据协议](../../../contracts/agents-api/zh/environment-executor-credentials.md#core-key-routes)。
+已归档项目无法签发或轮换凭据,仍可撤销。运维人员可以使用 Core 密钥管理凭据;参阅[凭据协议](../../../contracts/agents-api/zh/environment-executor-credentials.md#core-key-routes)。
## 从已解压的发行包安装 {#install-from-an-extracted-distribution}
diff --git a/docs/zh/maintainers.md b/docs/zh/maintainers.md
index 2a01d90de..b7529b589 100644
--- a/docs/zh/maintainers.md
+++ b/docs/zh/maintainers.md
@@ -10,7 +10,7 @@ source_hash: 402a990e859cb3fb0155e2b4e60421cd841de88f84a49b678eb918450b253114
分发包是从同一个提交构建的一组相互匹配的发布资源:控制归档(安装器、`oac` 命令,以及 Core、Web、ingress 和 PostgreSQL 镜像)、作为独立文件的 Runtime 镜像和节点构件,以及原生安装器。
-Core、Web 和 ingress 镜像发布为经过校验的 Linux amd64/arm64 多架构索引。arm64 控制归档包含这三个镜像;Node、托管 Runtime 和离线包使用 Linux amd64。发行构建使用 QEMU 执行 ARM 镜像步骤,包括 E2B helper。宿主机 `oac` 从同一份实现构建为 Linux amd64/arm64、macOS amd64/arm64 和 Windows amd64 二进制;启动脚本只选择、校验并运行它们。所有版本索引校验通过后才更新浮动标签。
+Core、Web 和 ingress 镜像发布为经过校验的 Linux amd64/arm64 多架构索引。arm64 控制归档包含这三个镜像;Node、托管 Runtime 和离线包使用 Linux amd64。发行构建使用 QEMU 执行 ARM 镜像步骤,包括 E2B helper。主机 `oac` 从同一份实现构建为 Linux amd64/arm64、macOS amd64/arm64 和 Windows amd64 二进制;启动脚本只选择、校验并运行它们。所有版本索引校验通过后才更新浮动标签。
请在 Linux x86_64 上构建,所需环境包括与 Debian 12 兼容的 glibc、Docker、`go.mod` 中指定的 Go 版本、C 编译器(microsandbox 辅助程序使用 CGO 构建)、Node、pnpm、Python 3.9 或更高版本、curl、tar、pigz 和 sha256sum。源代码必须保持干净并已提交。请先准备固定版本的 Codex 包和 MiniMax Code 配套程序,然后执行构建:
diff --git a/docs/zh/runtime-bootstrap.md b/docs/zh/runtime-bootstrap.md
index d3338fa61..f7d147c2a 100644
--- a/docs/zh/runtime-bootstrap.md
+++ b/docs/zh/runtime-bootstrap.md
@@ -4,7 +4,7 @@ source: docs/runtime-bootstrap.md
source_hash: f7e9275feee79ac1fb1299227e148b85c26efc8b8af5ca0e8f498126c563d182
---
-Sandbox Provider 通过交付一个引导文件来启动托管 Runtime。本文负责 Provider 到 Runtime 的启动输入。类型与验证器位于 [`internal/runtimebootstrap`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/internal/runtimebootstrap/bootstrap.go);Go provider 使用 [`runtime_bootstrap.go`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/services/core/internal/sandbox/runtime_bootstrap.go) 中的 `sandbox.Bootstrap.RuntimeConnection()` 构造输入,SDK helper 原样转发序列化对象。provider 不读取或写入 Runtime 的私有认证存储。
+沙箱提供商通过交付一个引导文件来启动托管 Runtime。本文负责提供商到 Runtime 的启动输入。类型与验证器位于 [`internal/runtimebootstrap`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/internal/runtimebootstrap/bootstrap.go);Go 提供商使用 [`runtime_bootstrap.go`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/services/core/internal/sandbox/runtime_bootstrap.go) 中的 `sandbox.Bootstrap.RuntimeConnection()` 构造输入,SDK helper 原样转发序列化对象。提供商不读取或写入 Runtime 的私有认证存储。
## 启动输入 {#launch-input}
@@ -23,16 +23,16 @@ oac-daemon connect --bootstrap-file /home/runtime/runtime-bootstrap.json
解码器拒绝未知、重复、缺失和大小写别名字段,拒绝其他版本及超过 `runtimebootstrap.MaxBytes`(16 KiB)的文档。错误不包含提交的值。文件缺失或格式错误时,daemon 在连接前失败。
-该文件是此次启动唯一的认证输入:daemon 拒绝将其与自托管注册选项组合使用,并将凭据读入内存而不保存到存储的 profile。凭据不进入命令参数、环境变量或回执。provider 为进程重启保留该文件,仅在明确清理自己拥有的资源时删除。
+该文件是此次启动唯一的认证输入:daemon 拒绝将其与自托管注册选项组合使用,并将凭据读入内存而不保存到存储的 profile。凭据不进入命令参数、环境变量或回执。提供商为进程重启保留该文件,仅在明确清理自己拥有的资源时删除。
## 职责与就绪状态 {#responsibilities-and-readiness}
-provider 创建账户、挂载和工作区,交付该文件,设置 Runtime 的资源与 Environment 绑定配置,然后以无特权 Runtime 账户启动 daemon。Docker 将文件写入 Runtime 拥有的 home volume;microsandbox 和 E2B 在启动同一命令之前交付文件。
+提供商创建账户、挂载和工作区,交付该文件,设置 Runtime 的资源与 Environment 绑定配置,然后以无特权 Runtime 账户启动 daemon。Docker 将文件写入 Runtime 拥有的 home volume;microsandbox 和 E2B 在启动同一命令之前交付文件。
-Runtime 验证输入,并负责认证与连接。启动成功仅证明交付完成:经过认证的连接、已准备的能力和执行就绪是 [Core–Runtime 协议](runtime-protocol.md) 下的独立观测;[Sandbox Provider 指南](sandbox-provider.md#four-distinct-readiness-facts) 列出各自证明的事实。
+Runtime 验证输入,并负责认证与连接。启动成功仅证明交付完成:经过认证的连接、已准备的能力和执行就绪是 [Core–Runtime 协议](runtime-protocol.md) 下的独立观测;[沙箱提供商指南](sandbox-provider.md#four-distinct-readiness-facts) 列出各自证明的事实。
-自托管 executor 和运维人员供应的设备通过其他方式获取 daemon 身份;[机器连接 API](../../contracts/agents-api/zh/machine-api.md#credentials) 列出所有凭据来源。它们都进入同一 Runtime 执行循环。
+自托管执行器和运维人员供应的设备通过其他方式获取 daemon 身份;[机器连接 API](../../contracts/agents-api/zh/machine-api.md#credentials) 列出所有凭据来源。它们都进入同一 Runtime 执行循环。
## 验证 {#verification}
-`go test ./internal/runtimebootstrap ./apps/daemon/internal/cli` 覆盖输入契约、凭据来源互斥规则和重启行为。Provider 测试验证交付与文件权限,不依赖 Runtime 的私有存储。
+`go test ./internal/runtimebootstrap ./apps/daemon/internal/cli` 覆盖输入契约、凭据来源互斥规则和重启行为。提供商测试验证交付与文件权限,不依赖 Runtime 的私有存储。
diff --git a/docs/zh/runtime-protocol.md b/docs/zh/runtime-protocol.md
index 2071b0741..9d3098587 100644
--- a/docs/zh/runtime-protocol.md
+++ b/docs/zh/runtime-protocol.md
@@ -10,11 +10,11 @@ source_hash: 47121442f49eb3b7d6590fa0769d1531fc49fc397169cdc219f9bf9eb05f80f2
## 所有权与连接 {#ownership-and-connection}
-Core 拥有持久化的 Session、Turn、input 和 Environment 记录、调度与协调。Runtime 拥有原生 Executor、活动 Turn、传输状态和清理责任,直到完成结算。Sandbox Provider 拥有执行位置与外围计算资源。释放执行准入或关闭 Executor 不会删除、暂停或回收沙箱。daemon 不是隔离边界;参见 [Runtime 与外层隔离](concepts.md#runtime-and-outer-isolation)。
+Core 拥有持久化的 Session、Turn、input 和 Environment 记录、调度与协调。Runtime 拥有原生 Executor、活动 Turn、传输状态和清理责任,直到完成结算。沙箱提供商拥有执行位置与外围计算资源。释放执行准入或关闭 Executor 不会删除、暂停或回收沙箱。daemon 不是隔离边界;参见 [Runtime 与外层隔离](concepts.md#runtime-and-outer-isolation)。
Runtime 按以下顺序连接:
-1. 获取 daemon 凭据和 device ID。[机器连接 API](../../contracts/agents-api/zh/machine-api.md#credentials) 列出凭据类型;Project API key 和 Core key 都不是 Runtime 凭据。
+1. 获取 daemon 凭据和 device ID。[机器连接 API](../../contracts/agents-api/zh/machine-api.md#credentials) 列出凭据类型;项目 API 密钥和 Core 密钥都不是 Runtime 凭据。
2. 调用 `POST /api/v1/agent-daemon/bootstrap`,通过 Bearer header 提供凭据,并提供 device ID。使用返回的连接 URL。
3. 连接 `/api/v1/agent-daemon/ws` 的 WebSocket,传入 `device_id`、`version` 查询参数和 Bearer header。凭据不得出现在 URL、payload 日志或 trace 中。
4. 立即发送 heartbeat,之后按 bootstrap 返回的间隔发送。每个 heartbeat 声明 `supported_agent_kinds`、其可用性和[能力](#capability-declarations)。第一个 heartbeat 之前能力未知;heartbeat 中缺失的 kind 视为未声明。两者都不允许推断。
@@ -62,7 +62,7 @@ Core 对 `usage` 和 `resume` 没有准入规则。
| 字段 | Core 设置方式 |
| --- | --- |
-| `agent_options` | 始终设置 Agent 的 `model` 和 `system_prompt`;Session 冻结了 model provider 时设置 `model_provider`;Agent 设置 `x_agents_core.harness_config` 时设置 `harness_config`。Core 不发送其他键;Runtime 在准备之前以 `unsupported_configuration` 拒绝任何其他键 |
+| `agent_options` | 始终设置 Agent 的 `model` 和 `system_prompt`;Session 冻结了模型提供商时设置 `model_provider`;Agent 设置 `x_agents_core.harness_config` 时设置 `harness_config`。Core 不发送其他键;Runtime 在准备之前以 `unsupported_configuration` 拒绝任何其他键 |
| `execution_controls` | 始终设置:web search 为 `disabled`、解析后的 text verbosity(默认 `medium`)、明确禁用 programmatic tool calling,以及任何 `json_schema` 输出格式。原生选项名称由 adapter 负责 |
| `observe_messages` | Runtime 声明 `message_items` 时设置。文本 delta 随后携带原生 item ID,`output_message` frame 报告消息开始、完成、phase 和完成文本 |
| `observe_subagent_identities`, `disable_subagents` | 根据 Agent 的 `multi_agent.enabled` 设置 |
@@ -129,7 +129,7 @@ preparation 和 start 在 receive loop 与 router lock 之外运行。admission
Executor 空闲到期属于 Runtime 资源策略,与 Core 的活动 Turn 并发限制独立。关闭时 Runtime 关闭活动和空闲 Executor,保留关闭失败的目标,并允许稍后串行重试。普通断连会关闭失败的 transport 并保留原 router,直到 shutdown 成功;等待超时或清理失败不授权重连,进程 shutdown 继续等待,不丢弃自己拥有的原生资源。对于 Runtime 初始化,shutdown 会等待同步 apply 操作和回执发送结束后才释放连接;`unknown` 结果仍是不确定结果,并阻止该 Router 上的后续准备,但本地变更停止后不再阻止重连。Core 保留失败的初始化状态,绝不重放初始化。工作区操作在跨 Turn 和 Executor 关闭后仍保留绑定与结算规则。
-挂起先关闭准入、排空已接纳工作与回执,同时保留已结算的空闲 Executor,随后才确认 `environment_quiesced`。活动、准备中、失效或其他未结算的所有者会阻止挂起。整个挂起期间停止空闲到期计时并隔离其回调;精确匹配且已认证的 `environment_resume` 为同一批所有者恢复一个新的空闲计时间隔。只有这种计划性重连跨 socket 保留 Router 与原生所有者;普通断连、shutdown 和连接生命周期取消仍要求确认清理完成。排空失败后,准入保持关闭直到 shutdown。恢复后的准备仍检查相同的原生身份与不可变配置,包括凭据冲突;绝不静默替换配置冲突的驻留 Executor。Sandbox Provider 仍负责其 checkpoint 实现的文件系统刷新和计算停止保证;Runtime 静止本身既不证明这些保证,也不证明原生 RAM 或外部网络连接已恢复。
+挂起先关闭准入、排空已接纳工作与回执,同时保留已结算的空闲 Executor,随后才确认 `environment_quiesced`。活动、准备中、失效或其他未结算的所有者会阻止挂起。整个挂起期间停止空闲到期计时并隔离其回调;精确匹配且已认证的 `environment_resume` 为同一批所有者恢复一个新的空闲计时间隔。只有这种计划性重连跨 socket 保留 Router 与原生所有者;普通断连、shutdown 和连接生命周期取消仍要求确认清理完成。排空失败后,准入保持关闭直到 shutdown。恢复后的准备仍检查相同的原生身份与不可变配置,包括凭据冲突;绝不静默替换配置冲突的驻留 Executor。沙箱提供商仍负责其 checkpoint 实现的文件系统刷新和计算停止保证;Runtime 静止本身既不证明这些保证,也不证明原生 RAM 或外部网络连接已恢复。
## 活动输入回执 {#active-input-receipts}
@@ -177,7 +177,7 @@ transport 与 execution 结果分开。Core 唯一 Run 订阅入口是 `Subscrib
| 清理失败 | 保留资源所有权,报告清理未确认;等待方超时不使资源可复用 |
| 取消回执丢失 | 取消可能已经发生;缺失回执既不证明成功,也不授权另一次执行 |
-仅重试其自身契约规定可安全重试的操作。已退出使用的 preparation request ID 最终可能分配新 handle,因此 request ID 不是持久化 idempotency key。恢复原生 Session 是带有已验证身份的显式操作,不是 socket 故障的响应。临时连接错误允许重连;认证或版本拒绝需要运维纠正。Executor 清理与 Sandbox Provider 已确认的计算资源回收独立。
+仅重试其自身契约规定可安全重试的操作。已退出使用的 preparation request ID 最终可能分配新 handle,因此 request ID 不是持久化 idempotency key。恢复原生 Session 是带有已验证身份的显式操作,不是 socket 故障的响应。临时连接错误允许重连;认证或版本拒绝需要运维纠正。Executor 清理与沙箱提供商已确认的计算资源回收独立。
## 原生故障分类 {#native-failure-classification}
@@ -185,7 +185,7 @@ adapter 可以给 Run 的 `error` frame 添加 `code` 和 `http_status`。它们
接受的 code 为 `authentication_error`、`rate_limit_exceeded`、`usage_limit_exceeded`、`server_overloaded`、`server_error`、`invalid_request`、`resource_not_found`、`request_timeout`、`context_length_exceeded`、`cyber_policy` 和 `connection_failed`([`engine_failure.go`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/internal/agentdaemon/proto/engine_failure.go))。仅 `connection_failed` 保留 `http_status`,且只能是 100 到 599 的整数;其他 status 都丢弃。值缺失、格式错误或未知时保持未分类错误,不丢弃 Usage 或 `done`。
-Core 在 Turn outcome 中将接受的值保存为 `engine_error_code` 和 `engine_http_status`。分类从属于终结状态和 Core 的 `error_code`:不能将已完成或已取消 Turn 变成失败、隐藏不完整事件流,或覆盖持久化或取消回执失败。正常 delivery 和 terminal journal draining 使用同一提取逻辑。[Session 诊断](../../contracts/agents-api/zh/session-diagnostics.md)仅为 Core error 为 `engine_failed` 的失败 Turn 暴露类别。[Codex](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/services/core/deploy/codex/README.md) 和 [Claude Code](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/services/core/deploy/claude/README.md) adapter 指南给出各 Harness 的映射。adapter 只依据结构化错误数据分类:Harness 自身的错误类型或状态,或 Harness 原样转交的模型服务 JSON 错误 body,其 `error.code` 或 `error.type` 可以给出接受的 code。adapter 不依据错误文字分类。
+Core 在 Turn outcome 中将接受的值保存为 `engine_error_code` 和 `engine_http_status`。分类从属于终结状态和 Core 的 `error_code`:不能将已完成或已取消 Turn 变成失败、隐藏不完整事件流,或覆盖持久化或取消回执失败。正常 delivery 和 terminal journal draining 使用同一提取逻辑。[Session 诊断](../../contracts/agents-api/zh/session-diagnostics.md)仅为 Core error 为 `engine_failed` 的失败 Turn 暴露类别。[Codex](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/services/core/deploy/codex/README.md) 和 [Claude Code](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/services/core/deploy/claude/README.md) adapter 指南给出各 Harness 的映射。adapter 只依据结构化错误数据分类:Harness 自身的错误类型或状态,或 Harness 原样转交的模型提供商 JSON 错误 body,其 `error.code` 或 `error.type` 可以给出接受的 code。adapter 不依据错误文字分类。
## 工作区操作 {#workspace-operations}
@@ -211,4 +211,4 @@ Core 在 Worker 的 Session 调度预约上运行空闲目录读取,活动执
套件覆盖不兼容版本、preparation 失败、取消结算、连接丢失而不虚构终结事件、重连而不重放、陈旧或重复 handle 与回执、清理失败、有界 transfer 验证,以及超时后的资源所有权。详细故障注入测试放在所测 gateway 和 dispatcher 代码旁。
-其他 Runtime 对接脚本化 Core 重放同一组 scenario,再对每个声明的能力运行原生验收。受控 adapter 测试证明 transport 契约,不证明原生 Harness 行为、操作系统支持、provider 认证或沙箱隔离。共享类型、本文和契约检查应一起修改。Harness adapter 还需运行 [Harness 接入](../../contracts/agents-api/zh/harness-onboarding.md)中描述的共享文本断言。
+其他 Runtime 对接脚本化 Core 重放同一组 scenario,再对每个声明的能力运行原生验收。受控 adapter 测试证明 transport 契约,不证明原生 Harness 行为、操作系统支持、提供商认证或沙箱隔离。共享类型、本文和契约检查应一起修改。Harness adapter 还需运行 [Harness 接入](../../contracts/agents-api/zh/harness-onboarding.md)中描述的共享文本断言。
diff --git a/docs/zh/sandbox-provider.md b/docs/zh/sandbox-provider.md
index d61680e20..aadbc723a 100644
--- a/docs/zh/sandbox-provider.md
+++ b/docs/zh/sandbox-provider.md
@@ -1,33 +1,33 @@
---
-title: "添加 Sandbox Provider"
+title: "添加沙箱提供商"
source: docs/sandbox-provider.md
source_hash: ade105e47436ca60735ba9f084c370d047403ba2f867f38ff55d798d305ae196
---
-**Sandbox Provider** 为 Core 管理的 Environment 提供 Runtime daemon 运行所需的外层计算资源,以及启动 daemon 的有界引导流程。本指南说明如何添加 Provider,并作为 Core 驱动 Provider 的参考。接口为 [`SandboxProvider`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/services/core/internal/sandbox/sandbox_provider.go)。
+**沙箱提供商** 为 Core 管理的 Environment 提供 Runtime daemon 运行所需的外层计算资源,以及启动 daemon 的有界引导流程。本指南说明如何添加提供商,并作为 Core 驱动提供商的参考。接口为 [`SandboxProvider`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/services/core/internal/sandbox/sandbox_provider.go)。
| 术语 | 含义 |
| --- | --- |
| Environment | Core 拥有的持久执行场所;参见 [Environment](../../contracts/agents-api/zh/environments.md) |
| Allocation | Core 为 Environment 拥有的一份计算资源租约,由 `Reference` 标识 |
| Runtime | Environment 内的 daemon;准备能力并执行 Turn |
-| Deployment | 整个部署唯一的 provider 选择;参见[沙箱部署](../../contracts/agents-api/zh/sandbox-deployment.md) |
+| Deployment | 整个部署唯一的提供商选择;参见[沙箱部署](../../contracts/agents-api/zh/sandbox-deployment.md) |
-Core 拥有持久 Environment、allocation、placement 和 cleanup 状态;Provider 仅负责计算资源与引导。Runtime 通过 [Core–Runtime 协议](runtime-protocol.md)准备能力并运行 Turn,provider 通过 [Runtime 引导](runtime-bootstrap.md)文件交付身份。provider 不运行 Environment 初始化、Skill、Plugin、MCP 设置、初始文件、execution 或 Files;这些操作使用 Runtime。隔离属于 provider 基础设施,不属于 daemon;参见 [Runtime 与外层隔离](concepts.md#runtime-and-outer-isolation)。使用薄 adapter 封装厂商维护的 SDK。
+Core 拥有持久 Environment、allocation、placement 和 cleanup 状态;提供商仅负责计算资源与引导。Runtime 通过 [Core–Runtime 协议](runtime-protocol.md)准备能力并运行 Turn,提供商通过 [Runtime 引导](runtime-bootstrap.md)文件交付身份。提供商不运行 Environment 初始化、Skill、Plugin、MCP 设置、初始文件、execution 或 Files;这些操作使用 Runtime。隔离属于提供商基础设施,不属于 daemon;参见 [Runtime 与外层隔离](concepts.md#runtime-and-outer-isolation)。使用薄 adapter 封装厂商维护的 SDK。
## 步骤 {#steps}
1. **阅读契约。** 实现每个方法,支持必需操作,并按[实现接口](#implement-the-interface)对其余每项操作声明决定。
2. **编写 adapter 包**,放在 `services/core/internal/sandbox/`:包括原生 SDK 调用、所有权检查、身份转换、私有配置,以及 node adapter 的 node-local 构造。声明 `var _ sandbox.SandboxProvider = (*YourAdapter)(nil)`。进程外 helper 放在 `services/core/tools/-provider`。
-3. **注册 kind** 一次,遵循[注册 provider kind](#register-the-provider-kind)。注册是明确构造,不是 init 时 plugin registry。
-4. **标记所属资源**,使用 [Runtime 名称](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/CONTRIBUTING.md#openagentcore-runtime-names)表中的 provider ownership label,不接受旧 label 名称作为回退。
+3. **注册 kind** 一次,遵循[注册提供商 kind](#register-the-provider-kind)。注册是明确构造,不是 init 时 plugin registry。
+4. **标记所属资源**,使用 [Runtime 名称](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/CONTRIBUTING.md#openagentcore-runtime-names)表中的提供商 ownership label,不接受旧 label 名称作为回退。
5. **运行契约套件** `make check-sandbox-provider-contract`;参见[验证集成](#validate-the-integration)。
6. **对真实计算资源运行原生验收**,再运行 `make check`。
7. **在 adapter 旁编写文档**,参考[参考 adapter](#reference-adapters)。
## 实现接口 {#implement-the-interface}
-`sandbox_provider.go` 包含 Core–Sandbox Provider 协议:负责 allocation、checkpoint 和观测的 `SandboxProvider` 接口及其请求与结果类型,以及 setup 阶段的 `ConfigurationAdapter` 及其类型化错误。Core 在此边界之外也使用的值类型,例如 `DeploymentSpec` 和 `CallFence`,位于同一 package 的独立文件中。每个方法在编译期都必须实现,`ProviderOperations()` 声明 Provider 支持哪些方法。以下五项操作始终支持:
+`sandbox_provider.go` 包含 Core–沙箱提供商协议:负责 allocation、checkpoint 和观测的 `SandboxProvider` 接口及其请求与结果类型,以及 setup 阶段的 `ConfigurationAdapter` 及其类型化错误。Core 在此边界之外也使用的值类型,例如 `DeploymentSpec` 和 `CallFence`,位于同一 package 的独立文件中。每个方法在编译期都必须实现,`ProviderOperations()` 声明提供商支持哪些方法。以下五项操作始终支持:
| 操作 | 用途 |
| --- | --- |
@@ -41,7 +41,7 @@ Docker 等没有原生可续期租约的 backend 仍遵守 Core 的 hosted expir
### 明确的操作契约 {#explicit-operation-contracts}
-每个 provider 返回完整的 `ProviderOperations()` 声明,`SandboxProvider` 中除 `ProviderOperations` 本身外的每个方法各占一项。接口的方法集就是操作清单,`sandbox.ValidateOperations` 根据它检查声明。下表中的分组是协议文件中的列表,由测试保证它们与该方法集一致,因此新增方法必须加入其中一组。
+每个提供商返回完整的 `ProviderOperations()` 声明,`SandboxProvider` 中除 `ProviderOperations` 本身外的每个方法各占一项。接口的方法集就是操作清单,`sandbox.ValidateOperations` 根据它检查声明。下表中的分组是协议文件中的列表,由测试保证它们与该方法集一致,因此新增方法必须加入其中一组。
| 操作 | 要求 | 职责 |
| --- | --- | --- |
@@ -55,7 +55,7 @@ Docker 等没有原生可续期租约的 backend 仍遵守 Core 的 hosted expir
不支持的方法在任何原生 I/O 前返回 `providercontract.UnsupportedError`。错误指明精确操作和安全 code,不包含原生消息、资源身份、endpoint 或凭据。空结果、nil error、`Unavailable` 或未知 mutation 结果都不能代替 unsupported,五项必需方法不能返回 unsupported。
-每个 adapter 拥有一个 `Operations()` 函数,由实例和注册共享。`providers.ValidateBinding` 根据接口并相互对照检查两者,Runtime admission 与 node generation 加载也拒绝不完整 provider。调用方在调用操作前用 `providercontract.Require` 检查声明,从不使用 type assertion。
+每个 adapter 拥有一个 `Operations()` 函数,由实例和注册共享。`providers.ValidateBinding` 根据接口并相互对照检查两者,Runtime admission 与 node generation 加载也拒绝不完整提供商。调用方在调用操作前用 `providercontract.Require` 检查声明,从不使用 type assertion。
`Observe` 读取一个 allocation,不续期、启动、准备或停止计算资源;参见[观测契约](../../contracts/agents-api/zh/runtime-observability.md)。
@@ -85,50 +85,50 @@ Microsandbox 在返回创建不存在回执前永久关闭初始 Create 准入
| --- | --- | --- | --- |
| `Create` | 匹配计算资源与 bootstrap 证据;执行仍需要 Runtime preparation | 无效或外来配置被拒绝;重复返回 `ErrExists`;transport 失败可能隐藏已创建资源 | 观察原 `Reference`。不重放 `Create`,即使使用新凭据。保留部分资源用于所属清理 |
| `GetInfo` | 不修改的当前计算资源观测 | `ErrNotFound` 仅表示缺少观测;error 不是不存在的证明 | 重复有界读取;不将其变成 create、start 或 renew |
-| `Renew` | 原生租约已延长,或无租约 provider 的观测 | 超时可能隐藏延期;停止或缺失计算资源仍保持原样 | 先观察,再由 reconciler 续期同一 allocation。不复活计算资源或虚构 lease expiry |
+| `Renew` | 原生租约已延长,或无租约提供商的观测 | 超时可能隐藏延期;停止或缺失计算资源仍保持原样 | 先观察,再由 reconciler 续期同一 allocation。不复活计算资源或虚构 lease expiry |
| `Kill` | 所属计算资源与保留存储已移除;重复已确认不存在时成功 | error 保留所有权与清理意图;所有权不匹配不删除外来资源 | 未决创建或 mutation 已隔离后重试同一 `Reference` 的清理;不提前释放 owner |
| `RunCommand`, `RunCommandCompute` | 收集到输出和实际 exit code;非零退出是已结算命令失败 | 缺失原生完成为 `ErrCommandUnconfirmed`;部分输出不是成功 | 不重放。无法证明完成时保留 owner,并在复用前回收 |
-`ErrInvalid`、`ErrOwnership`、`ErrExists`、`ErrNotFound`、`ErrComputeUnconfirmed` 和 `ErrCommandUnconfirmed` 保持其定义含义。未分类原生或 transport error 表示未知,不授权重试 mutation。Core 不将 provider diagnostics 读作生命周期事实,也不暴露原生错误文本或凭据;node transport 将错误映射为固定 code,直接 SDK 细节保持私有。
+`ErrInvalid`、`ErrOwnership`、`ErrExists`、`ErrNotFound`、`ErrComputeUnconfirmed` 和 `ErrCommandUnconfirmed` 保持其定义含义。未分类原生或 transport error 表示未知,不授权重试 mutation。Core 不将提供商 diagnostics 读作生命周期事实,也不暴露原生错误文本或凭据;node transport 将错误映射为固定 code,直接 SDK 细节保持私有。
-Checkpoint 支持增加 `Compute` generation、name、ID 和 `SnapshotIdentity`;原样持久化 operation ID 与 provider snapshot provenance。suspend 或 resume 的 `ObserveOnly` 仅观察上次尝试,不启动另一 capture 或 restore。`ResumeCompute` 仅解冻保留源,不冷启动已停止源。清理针对精确 compute incarnation 和 snapshot,不针对当前同名实例。只有所属节点已验证精确 incarnation 不再存在时,`GetCompute` 才返回 `ErrNotFound`;同名但 native ID 不同的实例为 `ErrOwnership`,节点或后端不可达属于未知结果。`ComputeState.Status` 为 `stopped` 或 `crashed` 表示 adapter 已验证该精确 incarnation 的进程不再存在;其记录或磁盘可保留到 `KillCompute` 将其移除。`paused`、没有 Runtime 连接的 `running` 和未知状态均不证明进程已终止。声明 checkpoint 支持前阅读 [`runtime_compute.go`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/services/core/internal/execution/runtime_compute.go) 及其失败测试。
+Checkpoint 支持增加 `Compute` generation、name、ID 和 `SnapshotIdentity`;原样持久化 operation ID 与提供商 snapshot provenance。suspend 或 resume 的 `ObserveOnly` 仅观察上次尝试,不启动另一 capture 或 restore。`ResumeCompute` 仅解冻保留源,不冷启动已停止源。清理针对精确 compute incarnation 和 snapshot,不针对当前同名实例。只有所属节点已验证精确 incarnation 不再存在时,`GetCompute` 才返回 `ErrNotFound`;同名但 native ID 不同的实例为 `ErrOwnership`,节点或提供商不可达属于未知结果。`ComputeState.Status` 为 `stopped` 或 `crashed` 表示 adapter 已验证该精确 incarnation 的进程不再存在;其记录或磁盘可保留到 `KillCompute` 将其移除。`paused`、没有 Runtime 连接的 `running` 和未知状态均不证明进程已终止。声明 checkpoint 支持前阅读 [`runtime_compute.go`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/services/core/internal/execution/runtime_compute.go) 及其失败测试。
### 四个独立就绪事实 {#four-distinct-readiness-facts}
| 事实 | 证据 | 不证明 |
| --- | --- | --- |
-| 计算资源可用 | Provider 对所属 allocation 的观测 | 已认证 Runtime 连接或已准备能力 |
+| 计算资源可用 | 提供商对所属 allocation 的观测 | 已认证 Runtime 连接或已准备能力 |
| Runtime 已连接 | Gateway 认证和精确 Environment、device 绑定 | preparation 已完成或 Harness 可用 |
| 能力已准备 | 使用固定配置完成公共 Runtime preparation | Turn 已接受或完成 |
| 执行已准入 | 已验证 Harness 能力及 executor、Turn 接受路径 | 输入已完成、取消已完成或计算资源已回收 |
-托管和自托管 Environment 使用相同 Runtime preparation;provider 不实现另一套竞争流程。
+托管和自托管 Environment 使用相同 Runtime preparation;提供商不实现另一套竞争流程。
-## 注册 provider kind {#register-the-provider-kind}
+## 注册提供商 kind {#register-the-provider-kind}
`sandbox/providers/registry.go` 是唯一注册表。每项绑定 adapter 的 specification 与 resource validator、`sandbox.ConfigurationAdapter`、部署模式(`nodes` 或 `direct`)、`sandbox.DeploymentPolicy`(磁盘限制、Runtime 输入,以及 setup 推荐的默认大小)、operation 声明,以及 node-local(`BuildLocal`)或 direct(`BuildDirect`)constructor。`providers.Build` 和 `providers.BuildDirect` 构造 adapter,不分配计算资源。没有 init 时注册或 plugin 加载。
-新 provider 执行以下步骤:
+新提供商执行以下步骤:
1. 在 adapter 包中实现 operation 契约,并编写原生契约测试。
2. 添加 specification 和 resource validator。
-3. 基于类型化原生配置实现 `sandbox.ConfigurationAdapter`。`DecodeInput` 严格解析请求中独立的公开 `configuration` 与只写 `credential` 对象。`Encode` 生成白名单公开 selector、只读观测和独立 secret bytes,不透传请求 JSON。`Decode` 恢复已存储 selector 并保留对所属资源的访问,不做远程 admission 或新模板验证。`Normalize` 修改前复制输入。`ResolveChange`、`Equal` 和 `WithCredential` 负责继承、身份与凭据组合。`Requirements` 声明是否需要凭据和公开 Core origin,以及支持哪些 setup 操作:`Discovery` 对应 `DiscoverConfiguration`,`SelectionDiscovery` 对应 `DiscoverSelection`,`CredentialVerification` 对应 `VerifyCredential`。`DiscoverConfiguration` 验证 query 并返回安全 catalog,不做 mutation 或 admission decision;Core 保留授权、输入限制与 deadline。`DiscoverSelection` 在提交前解析候选项省略的原生值,`VerifyCredential` 验证凭据对所属资源的访问,不修改资源。两者都接收候选项的 `sandbox.DirectConfig`,原生 client 只为该次调用构造。node provider 仅接受空公开对象,拒绝凭据,对每项 setup 操作和 credential replacement 返回 Unsupported。
-4. node adapter 从自己的包中导出 `BuildLocal` constructor、它解码的类型化 `native` 对象,以及它在共享 node artifact 之外添加的原生文件。node-local 设置(如主机路径)只存放在该对象中;resources 和 Runtime release 从 node 配置的 `specification` 读取。
-5. 在 `providers/registry.go` 中注册 constructor、policy、configuration adapter 和 operation 声明。其键即 provider kind,也用于标记该 Provider 的观测;checkpoint 支持读取此项。生成的投影组合每个已注册的部署模式和 deployment policy 与 `sandbox/deployment_contract.go` 中的共享 field bound:installer 从 `deploy/node/node_spec.py` 读取,TypeScript 客户端和 Web 从 `packages/agents-client/src/deployment-contract.ts` 读取,因此 Web 读取这些声明,而不比较 provider kind。通过 `go run ./services/core/cmd/specification-contract -write` 重新生成两者。
-6. 提供 adapter 和 helper 的发行产物,通过已注册 configuration 契约向运维人员提供 provider。
+3. 基于类型化原生配置实现 `sandbox.ConfigurationAdapter`。`DecodeInput` 严格解析请求中独立的公开 `configuration` 与只写 `credential` 对象。`Encode` 生成白名单公开 selector、只读观测和独立 secret bytes,不透传请求 JSON。`Decode` 恢复已存储 selector 并保留对所属资源的访问,不做远程 admission 或新模板验证。`Normalize` 修改前复制输入。`ResolveChange`、`Equal` 和 `WithCredential` 负责继承、身份与凭据组合。`Requirements` 声明是否需要凭据和公开 Core origin,以及支持哪些 setup 操作:`Discovery` 对应 `DiscoverConfiguration`,`SelectionDiscovery` 对应 `DiscoverSelection`,`CredentialVerification` 对应 `VerifyCredential`。`DiscoverConfiguration` 验证 query 并返回安全 catalog,不做 mutation 或 admission decision;Core 保留授权、输入限制与 deadline。`DiscoverSelection` 在提交前解析候选项省略的原生值,`VerifyCredential` 验证凭据对所属资源的访问,不修改资源。两者都接收候选项的 `sandbox.DirectConfig`,原生 client 只为该次调用构造。node 提供商仅接受空公开对象,拒绝凭据,对每项 setup 操作和 credential replacement 返回 Unsupported。
+4. node adapter 从自己的包中导出 `BuildLocal` constructor、它解码的类型化 `native` 对象,以及它在共享 node artifact 之外添加的原生文件。node-local 设置(如主机路径)只存放在该对象中;resources 和 Runtime 版本从 node 配置的 `specification` 读取。
+5. 在 `providers/registry.go` 中注册 constructor、policy、configuration adapter 和 operation 声明。其键即提供商 kind,也用于标记该提供商的观测;checkpoint 支持读取此项。生成的投影组合每个已注册的部署模式和 deployment policy 与 `sandbox/deployment_contract.go` 中的共享 field bound:installer 从 `deploy/node/node_spec.py` 读取,TypeScript 客户端和 Web 从 `packages/agents-client/src/deployment-contract.ts` 读取,因此 Web 读取这些声明,而不比较提供商 kind。通过 `go run ./services/core/cmd/specification-contract -write` 重新生成两者。
+6. 提供 adapter 和 helper 的发行产物,通过已注册 configuration 契约把该提供商交付给运维人员。
-**已知设计缺口:** Web 仍在 setup 向导的后端选择、Docker 确认,以及所有显示或解析 E2B 配置字段的地方(带服务预设的 setup 步骤、部署摘要和客户端的部署投影)中指名 provider,因为协议尚未声明配置字段。通过该界面提供另一 provider 目前需要修改共享的 Web。此耦合不符合[复杂性留在 adapter 内](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/AGENTS.md#complexity-stays-in-the-adapter);新集成必须通过协议表达配置,把厂商专有行为留在 adapter。不得添加 Session 或 Turn 调度路径、厂商专有 column 或 API field,或 store 中的厂商 switch。
+**已知设计缺口:** Web 仍在 setup 向导的提供商选择、Docker 确认,以及所有显示或解析 E2B 配置字段的地方(带服务预设的 setup 步骤、部署摘要和客户端的部署投影)中指名提供商,因为协议尚未声明配置字段。通过该界面提供另一提供商目前需要修改共享的 Web。此耦合不符合[复杂性留在 adapter 内](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/AGENTS.md#complexity-stays-in-the-adapter);新集成必须通过协议表达配置,把厂商专有行为留在 adapter。不得添加 Session 或 Turn 调度路径、厂商专有 column 或 API field,或 store 中的厂商 switch。
-node 配置 `sandbox.NodeConfig` 包含 `provider`、`generation`、`installation_id`、`core_url`、`specification`,以及 adapter 的不透明 `native` 对象。`providers.Build` 验证 `provider`、`generation`、`installation_id` 和 `specification`,并将配置与临时 `sandbox.LocalOptions` 传给 `BuildLocal`,由它严格解码 `native`。调用方通过 `Standalone` 明确选择独立注册或单 provider 执行,或通过 `GenerationStateDirectory` 中的规范绝对 node state directory 选择 generation 拥有的执行。context 缺失或混合时拒绝。adapter 负责 generation 特有的原生 preparation 和 readiness 检查。Microsandbox 将 helper lease 绑定到安装实例、generation 和 specification digest,然后在平台、容量和 artifact readiness 后检查固定 image。
+node 配置 `sandbox.NodeConfig` 包含 `provider`、`generation`、`installation_id`、`core_url`、`specification`,以及 adapter 的不透明 `native` 对象。`providers.Build` 验证 `provider`、`generation`、`installation_id` 和 `specification`,并将配置与临时 `sandbox.LocalOptions` 传给 `BuildLocal`,由它严格解码 `native`。调用方通过 `Standalone` 明确选择独立注册或单提供商执行,或通过 `GenerationStateDirectory` 中的规范绝对 node state directory 选择 generation 拥有的执行。context 缺失或混合时拒绝。adapter 负责 generation 特有的原生 preparation 和 readiness 检查。Microsandbox 将 helper lease 绑定到安装实例、generation 和 specification digest,然后在平台、容量和 artifact readiness 后检查固定 image。
### 注册验证 {#registration-validation}
-`providers.ValidateRegistration` 是唯一 wiring 检查。lookup、constructor binding 和生成的投影在任何 configuration callback 或 constructor 前运行它。未知 provider name 保持为无效输入;格式错误的注册返回安全 `providercontract.ErrContract`,不包含提交的配置或原生诊断。
+`providers.ValidateRegistration` 是唯一 wiring 检查。lookup、constructor binding 和生成的投影在任何 configuration callback 或 constructor 前运行它。未知提供商名称 保持为无效输入;格式错误的注册返回安全 `providercontract.ErrContract`,不包含提交的配置或原生诊断。
- `nodes` 注册仅有 `BuildLocal`,`direct` 注册仅有 `BuildDirect`;缺失、混合或未知 mode 被拒绝。
- specification 和 resource validator、configuration adapter 与完整 operation 声明都是必需项,因此不完整注册不能发布部分投影。声明的默认大小必须通过 adapter 的 resource validator。
- Runtime input policy 要么接受固定 Runtime,要么给出 adapter 拒绝它的固定原因,不能两者兼有。
-- Checkpoint 仅准入 `nodes` 注册,因为公共 lifecycle 只暂停 node allocation;声明 checkpoint 的 `direct` Provider 会被注册拒绝。注册不携带 suspension 数值:Core 对每个声明 checkpoint 支持的 Provider 应用同一个 [suspension policy](#suspension)。
+- Checkpoint 仅准入 `nodes` 注册,因为公共 lifecycle 只暂停 node allocation;声明 checkpoint 的 `direct` 提供商会被注册拒绝。注册不携带 suspension 数值:Core 对每个声明 checkpoint 支持的提供商应用同一个 [suspension policy](#suspension)。
configuration adapter 必须非 nil,包括其具体值。每个 `ConfigurationRequirements` 字段都需要明确有效的决定:`Credential` 和 `PublicOrigin` 为 `Required` 或 `NotRequired`,`Discovery`、`SelectionDiscovery` 和 `CredentialVerification` 使用共享 supported 或 unsupported 声明并携带安全 reason。新增 requirement field 需要明确更新验证,不继承已有决定。要求凭据不承诺支持 `VerifyCredential` 操作。这些检查证明注册完整,不证明原生 SDK 行为正确;constructor 和 adapter 契约测试仍然适用。
@@ -138,65 +138,65 @@ configuration adapter 必须非 nil,包括其具体值。每个 `Configuration
具有凭据的 direct adapter 在替换 key 前验证全部保留 generation 与 allocation reference。公共 `sandbox.CallFence` 排除原生调用并等待 helper 完成,包括调用方已超时的调用;execution 调用已准备的 verification 和 fencing callback,不按厂商分支。
-厂商部署验证和 SDK setup 留在构造边界,构造不创建 Environment。node-local adapter 的 `sandbox.Built` 返回 provider、probe、installation identity、backend fingerprint 和 specification digest;helper 可能比调用方存活更久时,还返回 `Quiescent` 检查,generation 回收会等待它。factory 还返回 close 函数。`execution.RuntimeProvider` 将 adapter 绑定到 kind、installation ID、backend fingerprint、generation、mode 和 node ownership;选择由数据库负责,内存副本不构成另一权限来源。Docker 与 microsandbox 在 node 上运行,E2B 直接构造。node proxy 仅对注册声明支持 checkpoint 的 backend 暴露 checkpoint 操作,公共 lifecycle 通过 checkpoint 声明准入 suspension,不通过 provider name。
+厂商部署验证和 SDK setup 留在构造边界,构造不创建 Environment。node-local adapter 的 `sandbox.Built` 返回提供商、probe、installation identity、backend fingerprint 和 specification digest;helper 可能比调用方存活更久时,还返回 `Quiescent` 检查,generation 回收会等待它。factory 还返回 close 函数。`execution.RuntimeProvider` 将 adapter 绑定到 kind、installation ID、backend fingerprint、generation、mode 和 node ownership;选择由数据库负责,内存副本不构成另一权限来源。Docker 与 microsandbox 在 node 上运行,E2B 直接构造。node proxy 仅对注册声明支持 checkpoint 的 backend 暴露 checkpoint 操作,公共 lifecycle 通过 checkpoint 声明准入 suspension,不通过提供商名称。
backend fingerprint 标识原生资源命名空间,不表示容量。Core 保留部署 generation,使所属 allocation 继续解析到原 backend;不要将保留 allocation 重新指向替代 backend。
### 发行产物与进程路径 {#distribution-artifacts-and-process-paths}
-每个 node adapter 注册负责其类型化 `NodeArtifacts` 声明,即共享 node artifact 加上其包导出的原生文件:逻辑发行路径、release filename suffix 和安装角色(`node`、`runtime`、`policy` 或 `image`)。注册拒绝缺失声明、不安全路径和未知角色。`go run ./services/core/cmd/provider-artifacts -write` 生成共享 Web catalog 和 Python projection。不带 `-write` 运行可检查是否最新。发行打包、Web availability 和 node 安装读取此投影;添加 provider payload 不在这些消费者中增加 provider-name 分支。
+每个 node adapter 注册负责其类型化 `NodeArtifacts` 声明,即共享 node artifact 加上其包导出的原生文件:逻辑发行路径、release filename suffix 和安装角色(`node`、`runtime`、`policy` 或 `image`)。注册拒绝缺失声明、不安全路径和未知角色。`go run ./services/core/cmd/provider-artifacts -write` 生成共享 Web catalog 和 Python projection。不带 `-write` 运行可检查是否最新。发行打包、Web availability 和 node 安装读取此投影;添加提供商 payload 不在这些消费者中增加按提供商名称的分支。
-launcher 从[派生进程环境](configuration.md)提供 `sandbox.ProcessPaths`。Core 读取这些路径一次,并传给 direct construction 和 setup 操作。它们是固定发行属性,不是部署设置或用户可选 helper 路径。每个 adapter 解析自己的相对 helper 和 state 位置;E2B 使用 `e2b/oac-e2b-provider` 和 `e2b/`。root 缺失或不是绝对路径时,在执行 helper 前失败。Provider 构造与发现不读取进程环境变量。
+launcher 从[派生进程环境](configuration.md)提供 `sandbox.ProcessPaths`。Core 读取这些路径一次,并传给 direct construction 和 setup 操作。它们是固定发行属性,不是部署设置或用户可选 helper 路径。每个 adapter 解析自己的相对 helper 和 state 位置;E2B 使用 `e2b/oac-e2b-provider` 和 `e2b/`。root 缺失或不是绝对路径时,在执行 helper 前失败。提供商构造与发现不读取进程环境变量。
## 托管生命周期 {#managed-lifecycle}
-这是 Core 对每个 provider 执行的公共流程。Adapter 不实现这些流程,但依赖它们。
+这是 Core 对每个提供商执行的公共流程。Adapter 不实现这些流程,但依赖它们。
### 部署发布 {#deployment-publication}
-启动时 Core 在选择 provider 前领取稳定 installation identity 和新的 owner epoch。runtime manager 保留了解 generation 的 provider facade。初始 setup 与 replacement 在任何数据库写入前准备并验证 candidate;candidate 被拒绝时不改变活动配置或 worker。backend replacement 使用 deployment mutation gate:暂停 manager admission,排空旧调用与循环,再在 commit transaction 中重复 resource 与 generation guard;新选择、其 generation、旧 node 和未使用 enrollment token 的退役一起提交。提交后,Core 在 manager mutex 下发布预验证配置和共享 observation、bootstrap cache,没有进一步外部工作或可失败步骤,因此提交后取消的请求不能丢弃配置。中断的 drain 保留为重试 barrier。Provider I/O 和 drain 不持有数据库事务或 manager map mutex。
+启动时 Core 在选择提供商前领取稳定 installation identity 和新的 owner epoch。runtime manager 保留了解 generation 的提供商 facade。初始 setup 与 replacement 在任何数据库写入前准备并验证 candidate;candidate 被拒绝时不改变活动配置或 worker。backend replacement 使用 deployment mutation gate:暂停 manager admission,排空旧调用与循环,再在 commit transaction 中重复 resource 与 generation guard;新选择、其 generation、旧 node 和未使用 enrollment token 的退役一起提交。提交后,Core 在 manager mutex 下发布预验证配置和共享 observation、bootstrap cache,没有进一步外部工作或可失败步骤,因此提交后取消的请求不能丢弃配置。中断的 drain 保留为重试 barrier。提供商 I/O 和 drain 不持有数据库事务或 manager map mutex。
-本地 provider 依赖不可用时,现有 scan 等待修复,hosted admission 保持关闭;管理员恢复仍可使用,重启后也如此。数据库和所有权错误仍是失败。未配置的部署以 503 `execution_unavailable` 拒绝 hosted admission,且不创建 Session 状态。Core 从 installation public URL 派生 Runtime bootstrap 和 daemon WebSocket 地址,不使用请求 header;从数据库读取当前选择,不使用 startup file。
+本地提供商依赖不可用时,现有 scan 等待修复,hosted admission 保持关闭;管理员恢复仍可使用,重启后也如此。数据库和所有权错误仍是失败。未配置的部署以 503 `execution_unavailable` 拒绝 hosted admission,且不创建 Session 状态。Core 从 installation public URL 派生 Runtime bootstrap 和 daemon WebSocket 地址,不使用请求 header;从数据库读取当前选择,不使用 startup file。
Node readiness 绑定到精确 generation、当前连接和 owner epoch。持久 serving pin 仅在部署串行化下为当时目标的 readiness 提升,因此已被替代目标的延迟报告不获得 pin。
### Allocation 生命周期 {#allocation-lifecycle}
-allocation、专用 daemon credential digest 和精确 Session binding 在 `Create` 前、execution lease 与 Session lock 下原子提交。只有新 allocation receipt 允许 `Create`;重试和 Core 重启观察同一 reference,不重放或轮换凭据。allocation 是私有计算资源所有权,与公开 Environment connection 和原生 readiness 独立;adapter 验证 bootstrap completion,Core 不从 engine 或 provider name 推断。
+allocation、专用 daemon credential digest 和精确 Session binding 在 `Create` 前、execution lease 与 Session lock 下原子提交。只有新 allocation receipt 允许 `Create`;重试和 Core 重启观察同一 reference,不重放或轮换凭据。allocation 是私有计算资源所有权,与公开 Environment connection 和原生 readiness 独立;adapter 验证 bootstrap completion,Core 不从 engine 或提供商名称 推断。
-配置 provider 后,Worker 扫描已提交且没有 allocation 的 pending hosted Environment,涵盖空闲 Session 创建以及 commit 与 bootstrap 之间中断后的恢复;已有 allocation 不重新进入此路径。scan 有界,由 lifecycle owner 串行化,不需要调用方操作。没有 Turn 的初始预约让 Session 保持空闲,daemon 连接不被当作原生 readiness。同一 scan 在验证精确 Session、device binding 和已结算 bootstrap 后,发布带持久 generation 的认证连接观测。
+配置提供商后,Worker 扫描已提交且没有 allocation 的 pending hosted Environment,涵盖空闲 Session 创建以及 commit 与 bootstrap 之间中断后的恢复;已有 allocation 不重新进入此路径。scan 有界,由 lifecycle owner 串行化,不需要调用方操作。没有 Turn 的初始预约让 Session 保持空闲,daemon 连接不被当作原生 readiness。同一 scan 在验证精确 Session、device binding 和已结算 bootstrap 后,发布带持久 generation 的认证连接观测。
-Core 在 Turn 之间检查已连接且已观察的计算资源仍是其 Session 正在运行的 allocation;该检查不做任何修改,也不复活 cleanup 请求。正在运行的计算资源不会到期:显式生命周期清理、快照保留策略和[已确认的计算资源丢失](#confirmed-compute-loss)管理资源回收。不可达的 container,以及未经该确认的停止或缺失 container,不授权丢弃保留工作区或历史,也不授权选择替代计算资源。禁用 provider 停止新 hosted admission 与 bootstrap,但不阻止现有 Session 的取消、function result 或 input retry outcome。
+Core 在 Turn 之间检查已连接且已观察的计算资源仍是其 Session 正在运行的 allocation;该检查不做任何修改,也不复活 cleanup 请求。正在运行的计算资源不会到期:显式生命周期清理、快照保留策略和[已确认的计算资源丢失](#confirmed-compute-loss)管理资源回收。不可达的 container,以及未经该确认的停止或缺失 container,不授权丢弃保留工作区或历史,也不授权选择替代计算资源。禁用提供商停止新 hosted admission 与 bootstrap,但不阻止现有 Session 的取消、function result 或 input retry outcome。
-终结清理原子撤销 device authority、记录 Environment 失败或到期、结算 pending input 并请求取消,然后才调用 `Kill`;原 input deadline 与 retry outcome 保留。临时 provider outage、未知 Create result 和停止的计算资源不证明永久失败。公开 Session 删除后 Core 保留 allocation,仅在所属 compute 与 volume 清理完成且原 Create 已结算的证明成立后标记 released;未知创建即使观察到不存在也保留 cleanup ownership,有界 scan 继续捕捉延迟资源,不再调用 `Create`。
+终结清理原子撤销 device authority、记录 Environment 失败或到期、结算 pending input 并请求取消,然后才调用 `Kill`;原 input deadline 与 retry outcome 保留。临时提供商 outage、未知 Create result 和停止的计算资源不证明永久失败。公开 Session 删除后 Core 保留 allocation,仅在所属 compute 与 volume 清理完成且原 Create 已结算的证明成立后标记 released;未知创建即使观察到不存在也保留 cleanup ownership,有界 scan 继续捕捉延迟资源,不再调用 `Create`。
### 每节点生命周期 worker {#per-node-lifecycle-workers}
-每个注册 node 有一个串行 lifecycle worker,负责 gate、allocation 与 pending cursor、connection 和 wake hint;E2B allocation 共享一个没有 node 的串行 lifecycle。薄 coordinator 发现 node 并关闭 worker,数据库、provider 或等待操作期间不持有 map mutex。worker 独立推进,因此一个在线 node 的 provider 卡住不会阻塞其他 node:lifecycle 并发为每 node 一项操作,随 node 数量增长。离线 worker 保留,因此其保留资源在重连后仍可观察。
+每个注册 node 有一个串行 lifecycle worker,负责 gate、allocation 与 pending cursor、connection 和 wake hint;E2B allocation 共享一个没有 node 的串行 lifecycle。薄 coordinator 发现 node 并关闭 worker,数据库、提供商或等待操作期间不持有 map mutex。worker 独立推进,因此一个在线 node 的提供商卡住不会阻塞其他 node:lifecycle 并发为每 node 一项操作,随 node 数量增长。离线 worker 保留,因此其保留资源在重连后仍可观察。
allocation scan 在应用 32 行分页限制前按 node 过滤,pending scan join 尚未释放的已提交 placement。每个 node 推进自己的 cursor,包括越过失败观测,并在末尾回绕一次。direct provisioning 在进入该 node gate 前解析 tenant 范围内 placement,活动 allocation 必须与其一致。只有确认释放后才能建立新的 placement;断连不会迁移活动 allocation。
-释放 execution lease 前,coordinator 停止接受工作,取消并排空每个 node worker 和 direct caller。lease 丢失影响全部;普通 provider failure 限于所属 node。计划 deployment drain 或 node retirement 通过五秒有界 lease gate,在 leased operation 之间同步取消 lifecycle context,包括活动 manual reconcile,不仅为了改变配置就取消进行中的 leased query。失败的 cancellation fence 关闭 manager admission 并报告 owner failure。失败的 retirement 保留原 lifecycle identity 和 gate,直到 owner shutdown,drain barrier 保持关闭。Session lock、deployment capacity transaction 和 revision-checked receipt 仍是权威依据,外部操作不持有数据库锁。
+释放 execution lease 前,coordinator 停止接受工作,取消并排空每个 node worker 和 direct caller。lease 丢失影响全部;普通提供商 failure 限于所属 node。计划 deployment drain 或 node retirement 通过五秒有界 lease gate,在 leased operation 之间同步取消 lifecycle context,包括活动 manual reconcile,不仅为了改变配置就取消进行中的 leased query。失败的 cancellation fence 关闭 manager admission 并报告 owner failure。失败的 retirement 保留原 lifecycle identity 和 gate,直到 owner shutdown,drain barrier 保持关闭。Session lock、deployment capacity transaction 和 revision-checked receipt 仍是权威依据,外部操作不持有数据库锁。
### Placement 与容量 {#placement-and-capacity}
-placement 自动完成:Session 创建提交持久的 pending 工作,共同调度器在 allocation 之前预留兼容节点。[部署契约](../../contracts/agents-api/zh/sandbox-deployment.md#generation-ownership-and-rollout) 定义等待、排序与代次选择。调用方不能选择 node;活动 allocation 即使在 node 离线时也保留原 node。确认 allocation 释放后,符合条件的保留 Session 可以重新预约兼容容量,包括其他 node。Node capacity 计入 pending reservation 和未决资源,新 placement 与 suspended-to-restoring 转移共享数据库锁。未知操作保留预约,source teardown 必须确认后才能释放 active capacity,确认 cleanup 后释放 placement capacity。保留所有权需要精确 provider evidence:socket path、缺失 instance 或空列表都不证明 cleanup,也不授权 replacement。
+placement 自动完成:Session 创建提交持久的 pending 工作,共同调度器在 allocation 之前预留兼容节点。[部署契约](../../contracts/agents-api/zh/sandbox-deployment.md#generation-ownership-and-rollout) 定义等待、排序与代次选择。调用方不能选择 node;活动 allocation 即使在 node 离线时也保留原 node。确认 allocation 释放后,符合条件的保留 Session 可以重新预约兼容容量,包括其他 node。Node capacity 计入 pending reservation 和未决资源,新 placement 与 suspended-to-restoring 转移共享数据库锁。未知操作保留预约,source teardown 必须确认后才能释放 active capacity,确认 cleanup 后释放 placement capacity。保留所有权需要精确提供商 evidence:socket path、缺失 instance 或空列表都不证明 cleanup,也不授权 replacement。
部署的 CPU、memory、disk 设置、`max_active`、`max_retained` 和 snapshot retention 限制每个 node。确认释放后的冷替换不提供 node-level drain、不可达写入方的故障转移、并发写入方、multi-active Core、autoscaling 或 snapshot replication。node 持有 allocation、snapshot、reservation、unknown result 或 cleanup 时拒绝移除 node,离线 ownership 保留。
### 暂停 {#suspension}
-Core 用同一个共享 policy 暂停每个声明 checkpoint 支持的 provider 的空闲工作:[可配置的空闲时长](../../contracts/agents-api/zh/sandbox-deployment.md#suspension-policy)默认为 5 分钟(300 秒),snapshot 保留 24 小时(86400 秒)。部署的 [`suspension`](../../contracts/agents-api/zh/sandbox-deployment.md#safe-response) 报告这两个值。Core 在 initialization 完成、没有 root 或 Subagent Turn 排队、进行中或等待、没有 pending input 或 file operation,且真实 activity 已空闲达到该时间后暂停。Session 无需已运行过 Turn。idle clock 不早于 allocation 进入 running compute phase 的时刻开始,包括 wake 后重新进入该 phase。对于 node allocation,Core 在同一事务中用数据库时钟记录首个 root 或 child terminal transition。candidate filter 和 Session-locked recheck 比较数据库已过时间与 idle duration,初始 snapshot retention deadline 也锚定同一数据库观测,因此 Core 与数据库主机时钟无需一致。原生 completion timestamp 在公开历史中保持不变,但不驱动 idle admission,heartbeat 不重置 activity。确认计划暂停前,daemon 关闭 admission 并排空 native cleanup、output receipt 和 file work。
+Core 用同一个共享 policy 暂停每个声明 checkpoint 支持的提供商的空闲工作:[可配置的空闲时长](../../contracts/agents-api/zh/sandbox-deployment.md#suspension-policy)默认为 5 分钟(300 秒),snapshot 保留 24 小时(86400 秒)。部署的 [`suspension`](../../contracts/agents-api/zh/sandbox-deployment.md#safe-response) 报告这两个值。Core 在 initialization 完成、没有 root 或 Subagent Turn 排队、进行中或等待、没有 pending input 或 file operation,且真实 activity 已空闲达到该时间后暂停。Session 无需已运行过 Turn。idle clock 不早于 allocation 进入 running compute phase 的时刻开始,包括 wake 后重新进入该 phase。对于 node allocation,Core 在同一事务中用数据库时钟记录首个 root 或 child terminal transition。candidate filter 和 Session-locked recheck 比较数据库已过时间与 idle duration,初始 snapshot retention deadline 也锚定同一数据库观测,因此 Core 与数据库主机时钟无需一致。原生 completion timestamp 在公开历史中保持不变,但不驱动 idle admission,heartbeat 不重置 activity。确认计划暂停前,daemon 关闭 admission 并排空 native cleanup、output receipt 和 file work。
容量压力可以让已经空闲的 node allocation 在通常超时之前暂停,但仍需经过 15 秒无活动宽限期。Session 锁内的决策重新检查 pending work、wake request 和 activity,再获取共享 deployment 容量锁并确认兼容的等待需求。它不会中断活动 Turn,也不会在普通 quiesce、capture 和 source-stop 证明完成前释放容量。压力触发的回收采用保守策略:只有进行中回收所属的节点当前有资格服务同一需求时,它才会推迟另一次回收。不可用或不兼容的节点保留其 ownership receipt,但不会阻挡健康节点的容量。如果暂停无法使容量可用,等待请求仍保留原始期限。
-Worker lease、Session lock 与 per-node gate 对每个 provider 负责 suspension。新 Turn claim、file-write intent 和 capture admission 在 Session lock 下串行化,共享一个 compute-phase 检查;新 pending work 取消 capture 并唤醒同一 source。正常 preparation 在经过认证的 resume handshake 后等待 compute phase 为 running;pending input 的 promotion 与 lifecycle transition 冲突时保持 pending。compute phase 和 revision-checked receipt 位于 allocation。Core 在 effect 前持久化 quiesce、capture 和 restore intent,仅新 receipt 执行 capture 或 restore,恢复观察精确 attempt,不重试未知 creation、capture 或 restore。已消费 snapshot 不让 running generation 回滚。删除、撤销和 retention expiry 优先于 wake,一直持续到最终数据库 compare-and-swap;未知 cleanup identity 保留,直到确认所属资源不存在。已消费 artifact 和旧 compute 被删除,因此暂停循环不累积可写磁盘链。
+Worker lease、Session lock 与 per-node gate 对每个提供商负责 suspension。新 Turn claim、file-write intent 和 capture admission 在 Session lock 下串行化,共享一个 compute-phase 检查;新 pending work 取消 capture 并唤醒同一 source。正常 preparation 在经过认证的 resume handshake 后等待 compute phase 为 running;pending input 的 promotion 与 lifecycle transition 冲突时保持 pending。compute phase 和 revision-checked receipt 位于 allocation。Core 在 effect 前持久化 quiesce、capture 和 restore intent,仅新 receipt 执行 capture 或 restore,恢复观察精确 attempt,不重试未知 creation、capture 或 restore。已消费 snapshot 不让 running generation 回滚。删除、撤销和 retention expiry 优先于 wake,一直持续到最终数据库 compare-and-swap;未知 cleanup identity 保留,直到确认所属资源不存在。已消费 artifact 和旧 compute 被删除,因此暂停循环不累积可写磁盘链。
排队工作和实时 Environment file access 唤醒 suspended Environment;history 和已发布 Artifact read 不唤醒。实时文件请求在进入文件工作队列前,等待当前 Runtime 通过 credential 授权的连接及 Harness 声明;compute Create 完成并不代表 Runtime 已就绪。计划暂停在 daemon 连接上使用 Environment 和 suspension token。受 PID 与 start-time fencing 的本地 control signal(`RunCommandCompute`)唤醒 parked daemon,daemon 在准入工作前重新认证。确认前临时断连通过有界 attempt 和 backoff 重试同一已 armed suspension;永久认证或协议拒绝则关闭。保留的检查点在原 node 仍具资格时优先恢复,也可以按以下检查点转移规则在其他符合条件的 node 恢复。Core 负责 snapshot retention deadline,daemon 没有相应 timer。quiesce 确认丢失时可以通过明确 rollback 解冻同一 source,但不授权 capture。
### 检查点转移 {#checkpoint-transfer}
-支持检查点的 generation 报告 `CheckpointCompatibility`,包含不透明的 `ArtifactDomain` 与 `ExecutionClass` token。每个已验证 `SnapshotIdentity` 携带同样的资格。Core 只比较这些值,不解释 CPU 特性、文件系统路径或存储实现。恢复目标必须在线、对 allocation 的不可变 deployment generation 已就绪、两个 token 均匹配,并有 active 容量;跨 node 时还需 retained slot。allocation、Device 和 Session 身份保持不变。Session 与 deployment 事务先提交目标路由、placement 和精确 restore intent,再执行目标侧原生操作。没有容量或兼容目标时,保留快照的所有权一直持续到配置期限。目标必须已持有该精确 generation;Core 不会在新节点自动准备历史 generation。升级期间应保留符合条件的节点及其 generation provider,直到检查点保留义务结束。
+支持检查点的 generation 报告 `CheckpointCompatibility`,包含不透明的 `ArtifactDomain` 与 `ExecutionClass` token。每个已验证 `SnapshotIdentity` 携带同样的资格。Core 只比较这些值,不解释 CPU 特性、文件系统路径或存储实现。恢复目标必须在线、对 allocation 的不可变 deployment generation 已就绪、两个 token 均匹配,并有 active 容量;跨 node 时还需 retained slot。allocation、Device 和 Session 身份保持不变。Session 与 deployment 事务先提交目标路由、placement 和精确 restore intent,再执行目标侧原生操作。没有容量或兼容目标时,保留快照的所有权一直持续到配置期限。目标必须已持有该精确 generation;Core 不会在新节点自动准备历史 generation。升级期间应保留符合条件的节点及其 generation 提供商,直到检查点保留义务结束。
`Suspend` 只有在持久发布已验证的完整归档、停止精确 source compute,并结清 source 本地 capture 与 cleanup 义务后,才能报告 `SourceStopped`。Core 先持久化快照,再标记 suspended;仅原生资源不存在并不足够。`Suspend.ObserveOnly` 可以为同一 operation 已验证的快照完成归档发布和源清理,但不能重新捕获快照,也不能停止已经恢复 running 的源。此前已发布的归档缺失或损坏时,`ObserveOnly` 可以返回其精确持久 ownership receipt,标记 `Status: unknown` 和 `SourceStopped: false`,供清理使用;该 receipt 不证明归档当前可用,也不证明源不存在。`Resume` 仍在执行前验证归档。完成源结清屏障后,source node 不可用不再阻止恢复。删除和正常到期可以将空闲 suspended allocation 的清理路由转给同一 artifact domain 内的在线 node;删除不要求 execution class 匹配。清理目标必须已提供同一不可变 generation,且有 retained 容量。没有这样的 node 时,清理保持 pending,不释放所有权;运维需恢复符合条件的 node 或其容量。未知 running 或 restoring writer 不会仅因 node 不可达而迁移。
@@ -224,13 +224,13 @@ Core 在释放 allocation 和 placement 归属前,确认原始创建已结算
[reset](../../contracts/agents-api/zh/sandbox-deployment.md#reset) 是 runtime manager 在计数工作之外推进的持久 execution state。start、escalation、cancellation、setup、update 和 finalization 通过 mutation gate 串行化。空闲状态先在 Session lock 再在 deployment lock 下复查,finalization 时不反向加锁。工作使用 keyset paging,绑定 reset request time 和 generation,并持久化 absolute deadline 与已验证 audit provenance。
-一个 snapshot 和 timestamp 对持有资源分区。离线 ownership 来自 allocation 或 active placement 的 node,与 online presence 使用同一 45 秒 connection 和 owner-epoch predicate,独立于 provider readiness;cleanup failure、offline state 或空 read 都不授权合成 release。held resource 为零时,Core 在数据库事务外 drain,在 deployment lock 下复查,并在一个事务中清空 deployment,再发布携带 generation 的空 provider,没有可失败工作。最终 write 或 drain 失败时,在释放 mutation gate 前使用有界 owner context 恢复已提交 provider;恢复失败时 admission 保持 fenced,owner 停止。
+一个 snapshot 和 timestamp 对持有资源分区。离线 ownership 来自 allocation 或 active placement 的 node,与 online presence 使用同一 45 秒 connection 和 owner-epoch predicate,独立于提供商 readiness;cleanup failure、offline state 或空 read 都不授权合成 release。held resource 为零时,Core 在数据库事务外 drain,在 deployment lock 下复查,并在一个事务中清空 deployment,再发布携带 generation 的空提供商,没有可失败工作。最终 write 或 drain 失败时,在释放 mutation gate 前使用有界 owner context 恢复已提交提供商;恢复失败时 admission 保持 fenced,owner 停止。
-管理员 [Session archive](../../contracts/agents-api/zh/admin-api.md#session-archive) 在 Session-first transaction 中保留 Project scope 与 hosted eligibility 检查,并一起处理 Environment expiry、cancellation、Runtime authority revocation 和 audit;reset 的后台 archive 从可信记录重建实际 Project scope,保留请求方 provenance。普通 provider lifecycle 释放 compute 和 snapshot。archive cancellation 在 terminal commit 前保留健康 receipt path:仅首次撤销 device 的 archive 记录精确 `archive_cancel_turn_id`(普通 revocation 清空它,重复 cleanup 保留它),现有已认证 delivery 可从 Turn 原 `cancel_requested_at` 起最多 20 秒排空该 cancellation。Core 独立于 subscription removal,通过 `done`、cancellation acknowledgement 和 terminal commit 跟踪 delivery,不授予新 connection、input、file 或 MCP authority,也不续期 lease。事务或 lifecycle gate 不等待 receipt,peer 丢失、到期或重启回到普通 failure 与 cleanup,不虚构 cancelled outcome。
+管理员 [Session archive](../../contracts/agents-api/zh/admin-api.md#session-archive) 在 Session-first transaction 中保留项目 scope 与 hosted eligibility 检查,并一起处理 Environment expiry、cancellation、Runtime authority revocation 和 audit;reset 的后台 archive 从可信记录重建实际项目 scope,保留请求方 provenance。普通提供商 lifecycle 释放 compute 和 snapshot。archive cancellation 在 terminal commit 前保留健康 receipt path:仅首次撤销 device 的 archive 记录精确 `archive_cancel_turn_id`(普通 revocation 清空它,重复 cleanup 保留它),现有已认证 delivery 可从 Turn 原 `cancel_requested_at` 起最多 20 秒排空该 cancellation。Core 独立于 subscription removal,通过 `done`、cancellation acknowledgement 和 terminal commit 跟踪 delivery,不授予新 connection、input、file 或 MCP authority,也不续期 lease。事务或 lifecycle gate 不等待 receipt,peer 丢失、到期或重启回到普通 failure 与 cleanup,不虚构 cancelled outcome。
## 验证集成 {#validate-the-integration}
-installer 与 Go adapter 的 E2B template 和 endpoint validator 消费共享 [selector fixture](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/services/core/internal/sandbox/e2b/testdata/configuration-selectors.json)。任何验证修改都扩展这些 case,使两处入口接受相同 selector。
+installer 与 Go adapter 的 E2B 模板和 endpoint validator 消费共享 [selector fixture](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/services/core/internal/sandbox/e2b/testdata/configuration-selectors.json)。任何验证修改都扩展这些 case,使两处入口接受相同 selector。
开发时运行 `make check-sandbox-provider-contract`。它通过真实 adapter 边界和受控原生失败运行共享 [`contracttest`](https://github.com/MiniMax-AI/OpenAgentCore/tree/main/services/core/internal/sandbox/contracttest) 套件,以及 adapter 和 node transport 测试;`make check` 包含相同 package。使用 native-side fixture 调用公开 failure runner,不使用假的 `SandboxProvider`,保留外来 ownership、未知 mutation result、cancellation、不自动 replay、failed cleanup 和 reference-bound settlement 测试。
@@ -248,7 +248,7 @@ node 测试单独覆盖 disconnect、reconnect fencing,以及 Create response
## Docker adapter {#docker-adapter}
-Docker Sandbox Provider([`sandbox/docker`](https://github.com/MiniMax-AI/OpenAgentCore/tree/main/services/core/internal/sandbox/docker))对所有 Runtime image 使用相同 container setting,无论服务哪个 Harness([`container_options.go`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/services/core/internal/sandbox/docker/container_options.go)):
+Docker 沙箱提供商([`sandbox/docker`](https://github.com/MiniMax-AI/OpenAgentCore/tree/main/services/core/internal/sandbox/docker))对所有 Runtime image 使用相同 container setting,无论服务哪个 Harness([`container_options.go`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/services/core/internal/sandbox/docker/container_options.go)):
- user 1000:1000、只读 root filesystem、移除全部 capability、`no-new-privileges`、[seccomp profile](#seccomp-profile) 和 AppArmor `unconfined`;
- node 配置的 network 和 extra host([node 配置](configuration.md#docker-node-configuration));
@@ -258,7 +258,7 @@ Docker Sandbox Provider([`sandbox/docker`](https://github.com/MiniMax-AI/OpenA
Create 拒绝复用没有 container 的保留 volume。它将 [Runtime 引导](runtime-bootstrap.md)文件复制到 `/home/runtime/runtime-bootstrap.json`(mode 0600、UID 1000),并将 `/environment` workspace、staging、initialization 和 package directory 放入 container,然后启动 `oac-daemon connect --profile default --bootstrap-file /home/runtime/runtime-bootstrap.json`。创建的 container 不具备配置的 CPU、memory 和精确 image 时,Create 返回 error 和 `CreateSettled`。Docker 没有 lease,因此 Renew 仅读取 container state。Kill 在删除前检查 container 和两个 volume 的 ownership label,再确认三者都已不存在。
-node 使用 [provider 配置](configuration.md#docker-node-configuration)中的明确 Unix socket,忽略 `DOCKER_HOST`。不将 Docker socket、host home 或 Core credential 挂载进 Runtime。
+node 使用 [提供商配置](configuration.md#docker-node-configuration)中的明确 Unix socket,忽略 `DOCKER_HOST`。不将 Docker socket、host home 或 Core credential 挂载进 Runtime。
### Seccomp profile {#seccomp-profile}
@@ -266,7 +266,7 @@ node 使用 [provider 配置](configuration.md#docker-node-configuration)中的
## 独立工作区挂载 {#independent-workspace-attachment}
-`Bootstrap.Workspace` 和 `ResumeRequest.Workspace` 可携带[工作区文件系统绑定](workspace-provider.md)。未提供时使用 Provider 自有的 Environment 磁盘;提供时选择精确的外部对象,不得回退到自有磁盘。Provider 在解析前校验租户、Environment、绑定及其配置回执。`LocalOptions.Workspace` 注入文件系统解析器;Sandbox Provider 不解释文件系统适配器参数或原生回执。
+`Bootstrap.Workspace` 和 `ResumeRequest.Workspace` 可携带[工作区文件系统绑定](workspace-provider.md)。未提供时使用提供商自有的 Environment 磁盘;提供时选择精确的外部对象,不得回退到自有磁盘。提供商在解析前校验租户、Environment、绑定及其配置回执。`LocalOptions.Workspace` 注入文件系统解析器;沙箱提供商不解释文件系统适配器参数或原生回执。
`DeploymentPolicy.Workspace` 声明挂载要求;未声明表示不支持外部存储。派生的不可变 `DeploymentSpec.Workspace` 回执选择代次的模式和能力;[部署流程](../../contracts/agents-api/zh/sandbox-deployment.md#resources)不会将文件系统配置复制进代次。Microsandbox 要求 `host_directory` 和 `user_xattr`;Docker 和 E2B 拒绝外部挂载。`ValidateWorkspacePolicy` 使用文件系统协议的组合校验器:不强制容量配额的外部文件系统拒绝正值 `EnvironmentDiskMiB`,零表示不请求配额。根磁盘容量仍为必需。未提供外部声明时,继续使用自有磁盘的容量边界。
diff --git a/docs/zh/web/console-api-usage.md b/docs/zh/web/console-api-usage.md
index 73c393cf8..1a4d68106 100644
--- a/docs/zh/web/console-api-usage.md
+++ b/docs/zh/web/console-api-usage.md
@@ -1,7 +1,7 @@
---
title: "控制台 API 使用"
source: docs/web/console-api-usage.md
-source_hash: bfed9ea629660a7018b7993445122e99158bd7b6319f08b0ee6a468f23310bde
+source_hash: 6eb50333e1da66b50f70b0f07835b76fb8717f80a22a307b1b4dda21ec191b44
---
本页列出各控制台页面读取和写入的 Core 路由,以及控制台如何限定读取范围。[administrator API contract](../../../contracts/agents-api/zh/admin-api.md) 定义了路由、响应结构、分页和审计记录;[API namespaces and credentials](../api/index.md) 定义了本文使用的术语。
@@ -10,9 +10,9 @@ source_hash: bfed9ea629660a7018b7993445122e99158bd7b6319f08b0ee6a468f23310bde
| 接口 | 路径 | 身份验证 | 控制台用途 |
| --- | --- | --- | --- |
-| Console server | `/console/auth`、`/console/auth/{login,logout}`、`/console/config`、`/node-install/manifest.json` | 登录时使用 Core 密钥,随后使用控制台会话 Cookie;`/node-install/manifest.json` 无需登录 | 登录和退出;Add node 所用的节点安装程序和节点构件;用于 Docker 和 microsandbox 设置的发行版 Runtime release。参见 [console server](console-server.md) |
+| Console server | `/console/auth`、`/console/auth/{login,logout}`、`/console/config`、`/node-install/manifest.json` | 登录时使用 Core 密钥,随后使用控制台会话 Cookie;`/node-install/manifest.json` 无需登录 | 登录和退出;**添加节点** 所用的节点安装程序和节点构件;用于 Docker 和 microsandbox 设置的发行版 Runtime release。参见 [console server](console-server.md) |
| Administrator API | `/core/v1/**`,不包括 `/core/v1/sandbox` | Core 密钥,由控制台服务器添加 | 项目、密钥、资源读取和删除、诊断、执行器凭据和安装命令、来源信息、汇总、Core 指标、安装信息、默认模型 |
-| Sandbox administration | `/core/v1/sandbox/**` | Core 密钥,由控制台服务器添加 | Sandbox 配置;Nodes;Overview 上的机群与容量摘要;Sandbox metrics 中每个项目的 Runtime observations |
+| Sandbox administration | `/core/v1/sandbox/**` | Core 密钥,由控制台服务器添加 | 沙箱配置;**节点**;**概览** 上的机群与容量摘要;**沙箱监控** 中每个项目的 Runtime 观测 |
| Agents API | `/v1/**` | 项目 API 密钥 | 不使用。控制台会向开发者说明如何调用它(参见 [Provenance and monitoring](#provenance-and-monitoring)) |
浏览器请求均为同源请求,并且仅携带控制台会话 Cookie。浏览器只在登录请求体中发送一次 Core 密钥,且绝不存储该密钥;它既不持有也不发送 API 密钥或 `OpenAI-Beta` 标头。控制台通过 [`packages/agents-client`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/packages/agents-client/README.md) 中的 `AdminClient`、`SandboxAdminClient` 和 `CoreMetricsClient` 执行读取,这些客户端会验证每个响应:格式错误的值会被报告为失败,或按下文说明标记为无法识别,绝不会用猜测值或零值替代。
@@ -21,13 +21,13 @@ source_hash: bfed9ea629660a7018b7993445122e99158bd7b6319f08b0ee6a468f23310bde
| 操作 | 路由 | 控制台用途 |
| --- | --- | --- |
-| 列出项目 | `GET /core/v1/projects` | 每个项目范围页面上的项目筛选器;Projects 和密钥列表;Overview 的 Getting started(一个拥有活动密钥的项目,以及最新的活动项目,优先选择拥有活动密钥的项目,并打开其调用示例以进入首个 Session 步骤);归档确认中的 `active_key_count`,当项目的密钥列表显示更多密钥时,该计数也会增加 |
-| 创建项目 | `POST /core/v1/projects` | **Create project**,也可从 Getting started 进入 |
-| 重命名项目 | `POST /core/v1/projects/{project_id}` | 对活动项目执行 **Rename**;ID 保持不变 |
-| 归档项目 | `POST /core/v1/projects/{project_id}/archive` | **Archive**:吊销所有密钥;项目资产仍可读取和删除 |
+| 列出项目 | `GET /core/v1/projects` | 每个项目范围页面上的项目筛选器;**项目与密钥** 列表;**概览** 的 **新手引导**(一个拥有活动密钥的项目,以及最新的活动项目,优先选择拥有活动密钥的项目,并打开其调用示例以进入首个 Session 步骤);归档确认中的 `active_key_count`,当项目的密钥列表显示更多密钥时,该计数也会增加 |
+| 创建项目 | `POST /core/v1/projects` | **创建项目**,也可从 **新手引导** 进入 |
+| 重命名项目 | `POST /core/v1/projects/{project_id}` | 对活动项目执行 **改名**;ID 保持不变 |
+| 归档项目 | `POST /core/v1/projects/{project_id}/archive` | **归档**:吊销所有密钥;项目资产仍可读取和删除 |
| 列出密钥 | `GET /core/v1/projects/{project_id}/keys` | 项目密钥表:名称、前缀、状态、创建时间和吊销时间;归档确认所统计的活动密钥 |
-| 签发密钥 | `POST /core/v1/projects/{project_id}/keys` | 对活动项目执行 **Issue key**,也可从 Getting started 进入;明文仅显示一次 |
-| 吊销密钥 | `DELETE /core/v1/projects/{project_id}/keys/{key_id}` | **Revoke**;当它是项目最后一个活动密钥时会显示警告 |
+| 签发密钥 | `POST /core/v1/projects/{project_id}/keys` | 对活动项目执行 **签发密钥**,也可从 **新手引导** 进入;明文仅显示一次 |
+| 吊销密钥 | `DELETE /core/v1/projects/{project_id}/keys/{key_id}` | **撤销**;当它是项目最后一个活动密钥时会显示警告 |
发送前会检查名称长度(项目为 1–128 个字符,密钥为 1–80 个字符)和控制字符。已签发密钥的明文会保留在组件内存中,直到管理员确认已保存;绝不会写入浏览器存储、URL 或日志。项目不能删除,明文也无法恢复。
@@ -37,47 +37,47 @@ source_hash: bfed9ea629660a7018b7993445122e99158bd7b6319f08b0ee6a468f23310bde
| 资源 | 使用的读取操作 | 删除对象 | 创建者 | 控制台界面 |
| --- | --- | --- | --- | --- |
-| Agents | `/agents`、`/agents/{agent_id}` | Agent | `agent` | Agents 列表,含每个 Agent 的用量;Agent 页面,含说明、工具、已保存的模型提供商(绝不显示其密钥)、生成设置和元数据 |
-| Environment templates | `/environment-templates`、`/environment-templates/{id}` | Template | `environment_template` | Templates 列表;Template 页面,含所有安全区段 |
-| Skills | `/skills`、`/skills/{skill_id}`、`/skills/{skill_id}/versions`、Skill 和版本的 `/content` | Skill 和 Skill version | `skill`(列表) | Skills 列表;Skill 页面,含版本和归档下载 |
-| Files | `/files` | File | `file` | Files 列表(仅元数据) |
-| Vaults | `/vaults`、`/vaults/{vault_id}`、`/vaults/{vault_id}/credentials` | Vault 和 Credential | `vault`、`credential` | Vaults 列表;Vault 页面,含 Credential 元数据 |
-| Sessions | `/sessions`、`/sessions/{session_id}`、`/sessions/{session_id}/items`、`/sessions/{session_id}/turns`、`/sessions/{session_id}/runtime-observation`、`/sessions/{session_id}/runtime-history` | Session | `session` | Session log;Session 页面;Agent 指标;托管 Runtime 行 |
-| Diagnostics | `/sessions/{session_id}/diagnostics`、`/sessions/{session_id}/turns/{turn_id}/diagnostics` | — | — | Overview 中失败 Session 或 Turn 状态下的分类原因;Session log 和 Session 页面;跟踪中每个 Item 的 Core 接收时间 |
+| Agents | `/agents`、`/agents/{agent_id}` | Agent | `agent` | **Agent** 列表,含每个 Agent 的用量;Agent 页面,含说明、工具、已保存的模型提供商(绝不显示其密钥)、生成设置和元数据 |
+| Environment 模板 | `/environment-templates`、`/environment-templates/{id}` | 模板 | `environment_template` | **Environment 模板** 列表;模板页面,含所有安全区段 |
+| Skills | `/skills`、`/skills/{skill_id}`、`/skills/{skill_id}/versions`、Skill 和版本的 `/content` | Skill 和 Skill version | `skill`(列表) | **Skills** 列表;Skill 页面,含版本和归档下载 |
+| Files | `/files` | File | `file` | **文件** 列表(仅元数据) |
+| Vaults | `/vaults`、`/vaults/{vault_id}`、`/vaults/{vault_id}/credentials` | Vault 和 Credential | `vault`、`credential` | **Vault** 列表;Vault 页面,含 Credential 元数据 |
+| Sessions | `/sessions`、`/sessions/{session_id}`、`/sessions/{session_id}/items`、`/sessions/{session_id}/turns`、`/sessions/{session_id}/runtime-observation`、`/sessions/{session_id}/runtime-history` | Session | `session` | **Session 日志**;Session 页面;**Agent 监控**;托管 Runtime 行 |
+| Diagnostics | `/sessions/{session_id}/diagnostics`、`/sessions/{session_id}/turns/{turn_id}/diagnostics` | — | — | **概览** 中失败 Session 或 Turn 状态下的分类原因;**Session 日志** 和 Session 页面;跟踪中每个 Item 的 Core 接收时间 |
资源专用规则:
-- **Environment templates.** `env` 和安装命令为只写且绝不返回,因此控制台无法判断 Template 是否包含它们。内嵌文件仅报告大小。如果客户端无法识别 Template 的某个区段或字段,则会加以标记;仍会显示可识别的区段,且不会猜测其他内容。
-- **Skills.** 版本上传、默认指针更改及所有其他 Skill 写入操作均使用项目的密钥。控制台会将默认版本或指定版本下载为 ZIP、删除版本(只要仍有其他版本,默认版本就无法删除;删除唯一版本会删除该 Skill),并要求输入 Skill 名称后删除该 Skill。
-- **Files.** 列表每页读取 100 条,可按最新或最早顺序排列。管理员 API 没有 File 内容路由,因此控制台不提供下载。
-- **Vaults.** Credential 令牌绝不返回。控制台显示每个 Credential 的名称、MCP 服务器 URL、身份验证类型和更新时间。
-- **Sessions.** 如果某个 Session 格式错误,其所属项目的读取会失败,而不会跳过该 Session。
-- **Diagnostics.** 控制台会翻译 Core 分类的原因,绝不从原始日志推断原因。Session 页面会补充该原因的下一步操作,例如检查 Session 页显示的模型以及该 Session 所用的模型服务;列表只显示原因,下一步操作放在悬停提示中。Core 不返回 Harness 或模型服务的原始消息,因此无法分类的失败会如实说明。诊断信息不可用或不匹配时,会提供显式的读取重试;重试绝不会重新执行操作。
+- **Environment 模板。** `env` 和安装命令为只写且绝不返回,因此控制台无法判断模板是否包含它们。内嵌文件仅报告大小。如果客户端无法识别模板的某个区段或字段,则会加以标记;仍会显示可识别的区段,且不会猜测其他内容。
+- **Skills。** 版本上传、默认指针更改及所有其他 Skill 写入操作均使用项目的密钥。控制台会将默认版本或指定版本下载为 ZIP、删除版本(只要仍有其他版本,默认版本就无法删除;删除唯一版本会删除该 Skill),并要求输入 Skill 名称后删除该 Skill。
+- **文件。** 列表每页读取 100 条,可按最新或最早顺序排列。管理员 API 没有 File 内容路由,因此控制台不提供下载。
+- **Vault。** Credential 令牌绝不返回。控制台显示每个 Credential 的名称、MCP 服务器 URL、身份验证类型和更新时间。
+- **Session。** 如果某个 Session 格式错误,其所属项目的读取会失败,而不会跳过该 Session。
+- **诊断。** 控制台会翻译 Core 分类的原因,绝不从原始日志推断原因。Session 页面会补充该原因的下一步操作,例如检查 Session 页显示的模型以及该 Session 所用的模型提供商;列表只显示原因,下一步操作放在悬停提示中。Core 不返回 Harness 或模型提供商的原始消息,因此无法分类的失败会如实说明。诊断信息不可用或不匹配时,会提供显式的读取重试;重试绝不会重新执行操作。
## 执行器凭据和主机连接 {#executor-credentials-and-host-connection}
-仅当 Session 的环境为 `self_hosted` 时,Session 页面才会显示 **Executor credentials** 区段,并针对该 Session 的 `project_id` 和 `environment.id` 读取凭据。[executor credential contract](../../../contracts/agents-api/zh/environment-executor-credentials.md) 定义了路由、404 和 409 响应以及凭据文件。
+仅当 Session 的 Environment 为 `self_hosted` 时,Session 页面才会显示 **执行器凭据** 区段,并针对该 Session 的 `project_id` 和 `environment.id` 读取凭据。[执行器凭据契约](../../../contracts/agents-api/zh/environment-executor-credentials.md) 定义了路由、404 和 409 响应以及凭据文件。
| 操作 | 路由 | 控制台用途 |
| --- | --- | --- |
| 列出凭据 | `GET /core/v1/projects/{project_id}/environments/{environment_id}/executor-credentials` | 可见时每 5 秒读取一次。表格显示每个凭据的短 `key_id` 及其复制按钮、创建时间(`created_at`,轮换不会改变该值)和状态(Active,或 Revoked 及其时间),并优先显示活动凭据;绝不会列出凭据本身。同一次读取中的 `connection` 观测值用于驱动主机连接面板:never connected、connected、disconnected、bound credential revoked 和 unknown 保持为不同状态,且只有重新读取并得到 connected 才会将主机标记为已连接 |
| 签发或轮换 | `POST …/executor-credentials`,请求体为 `{"key_id", "rotate"}` | Issue 会在提交前保留生成的密钥 ID。轮换前会确认旧凭据将停止工作;轮换已吊销的凭据会恢复该凭据并生成新密钥。私有 JSON 仅显示一次,供下载或复制,绝不会存储在浏览器存储或查询缓存中,并在 Done 时清除 |
-| 吊销 | `DELETE …/executor-credentials/{key_id}` | **Revoke**,需确认(执行器会断开连接且不会重试;其守护进程会保持停止状态,直到操作员将其停止),随后再次读取列表,并显示凭据为 Revoked |
-| 安装命令 | `GET /core/v1/projects/{project_id}/environments/{environment_id}/installation` | **Connect a host**:按 Core 返回的原始内容显示短效 Linux/macOS 和 PowerShell 命令,并提供平台选择器以及指向 [native installation guide](../getting-started/self-hosted.md) 的链接。这些命令会安装守护进程及其 Harnesses、启动守护进程并检查连接;其授权在 30 分钟后过期,控制台每 20 分钟重新读取一次。如果没有可用且未过期的响应,该区段会说明命令不可用。已归档项目不会读取该信息 |
+| 吊销 | `DELETE …/executor-credentials/{key_id}` | **撤销**,需确认(执行器会断开连接且不会重试;其守护进程会保持停止状态,直到操作员将其停止),随后再次读取列表,并显示凭据为 Revoked |
+| 安装命令 | `GET /core/v1/projects/{project_id}/environments/{environment_id}/installation` | **连接主机**:按 Core 返回的原始内容显示短效 Linux/macOS 和 PowerShell 命令,并提供平台选择器以及指向 [native installation guide](../getting-started/self-hosted.md) 的链接。这些命令会安装守护进程及其 Harnesses、启动守护进程并检查连接;其授权在 30 分钟后过期,控制台每 20 分钟重新读取一次。如果没有可用且未过期的响应,该区段会说明命令不可用。已归档项目不会读取该信息 |
-在已归档项目中,该区段会通过提示隐藏 **Issue credential** 和 **Rotate**,但保留列表和 **Revoke**,因为 Core 仍允许吊销。
+在已归档项目中,该区段会通过提示隐藏 **签发凭据** 和 **轮换**,但保留列表和 **撤销**,因为 Core 仍允许吊销。
## 来源与监控 {#provenance-and-monitoring}
| 操作 | 路由 | 控制台用途 |
| --- | --- | --- |
-| 资源所有者 | `GET /core/v1/projects/{project_id}/resource-owners` | 每个资源列表的 Creator 列和详情页的创建者信息,每批最多处理 100 个 ID:创建密钥的名称;Core 无记录时显示 **Unknown** |
+| 资源所有者 | `GET /core/v1/projects/{project_id}/resource-owners` | 每个资源列表的 Creator 列和详情页的创建者信息,每批最多处理 100 个 ID:创建密钥的名称;Core 无记录时显示 **未知** |
| 写入操作 | `GET /core/v1/projects/{project_id}/write-operations` | 项目的写入历史,按最新优先,可按密钥和资源类型筛选,每页 50 条 |
-| 汇总 | `GET /core/v1/summary` | Overview(按项目)、Agents 列表(`group_by=agent`)、项目页面(按项目并使用 `group_by=key`)、Agent 指标(跳过空闲项目,并统计从范围开始以来按创建密钥划分的使用量)、Projects 列表(最近活动) |
-| 安装 | `GET /core/v1/installation` | Settings → Service and deployment 的 Installation 信息(`public_url`、`api_base_url`、`installation_id`、`source_commit`)和只读 Startup 设置(`configuration.settings`;敏感设置仅显示其是否为 `configured`);调用示例中的 `api_base_url`;作为下载来源以及节点安装和卸载命令中 `--source-url` 的 `public_url`(还包括安装命令中的 `--core-url`)。如果敏感设置包含值,或存在未知成员,读取会失败 |
-| Core 指标 | `GET /core/v1/metrics?range=` | Core 指标页面。不存在该路由的 Core(404)会显示为未报告数据。[Core metrics contract](../../../contracts/agents-api/zh/core-metrics.md) 定义了每项度量 |
+| 汇总 | `GET /core/v1/summary` | **概览**(按项目)、**Agent** 列表(`group_by=agent`)、项目页面(按项目并使用 `group_by=key`)、**Agent 监控**(跳过空闲项目,并统计从范围开始以来按创建密钥划分的使用量)、**项目与密钥** 列表(最近活动) |
+| 安装 | `GET /core/v1/installation` | **设置 → 服务与部署** 的 **安装** 信息(`public_url`、`api_base_url`、`installation_id`、`source_commit`)和只读 **启动设置**(`configuration.settings`;敏感设置仅显示其是否为 `configured`);调用示例中的 `api_base_url`;作为下载来源以及节点安装和卸载命令中 `--source-url` 的 `public_url`(还包括安装命令中的 `--core-url`)。如果敏感设置包含值,或存在未知成员,读取会失败 |
+| Core 指标 | `GET /core/v1/metrics?range=` | **Core 监控** 页面。不存在该路由的 Core(404)会显示为未报告数据。[Core 指标契约](../../../contracts/agents-api/zh/core-metrics.md) 定义了每项度量 |
-如果为 `local_only`,或者没有 `public_url`,Add node 将无法签发命令,Clean up the host 也无法提供命令。随后 Overview、Nodes 和 Settings 会显示醒目警告,并通过 Review the public address 前往 Settings → Service and deployment。Nodes 会禁用 Add node 并显示明确原因,Getting started 则将 sandbox 步骤保留为待办项。
+如果为 `local_only`,或者没有 `public_url`,**添加节点** 将无法签发命令,**清理主机** 也无法提供命令。随后 **概览**、**节点** 和 **设置** 会显示醒目警告,并通过 **查看公开地址** 前往 **设置 → 服务与部署**。**节点** 会禁用 **添加节点** 并显示明确原因,**新手引导** 则将沙箱步骤保留为待办项。
无论是在显示新密钥时,还是在活动项目页面没有显示任何密钥时,控制台都会提供 `OPENAI_BASE_URL`(安装的 `api_base_url`)和 `OPENAI_API_KEY`(新密钥,或项目密钥的占位符)的 shell 导出变量,以及针对 `GET /v1/agents` 和 `POST /v1/agents/sessions` 的 `curl` 和 Python 示例,但不会发送其中任何调用。当安装为 `local_only` 时,控制台会说明 API 只能在 Core 所在计算机上访问;当缺少 `api_base_url` 时,则会提示设置 `public_url`。
@@ -85,45 +85,45 @@ source_hash: bfed9ea629660a7018b7993445122e99158bd7b6319f08b0ee6a468f23310bde
## 请求日志 {#request-log}
-**Request log** 通过 `AdminClient` 读取 `GET /core/v1/request-logs`,按应用或管理入口、精确请求 ID 和请求结果筛选,并按需刷新。列表和本地详情对话框共用一次响应,打开条目不会发出额外请求。读取失败保留上一次响应并明确提示数据已过期。[请求日志契约](../../../contracts/agents-api/zh/admin-api.md#request-log)定义采集、容量限制及响应语义。说明放在问号提示中,不补造缺失的状态或错误数据。
+**请求日志** 通过 `AdminClient` 读取 `GET /core/v1/request-logs`,按应用或管理入口、精确请求 ID 和请求结果筛选,并按需刷新。列表和本地详情对话框共用一次响应,打开条目不会发出额外请求。读取失败保留上一次响应并明确提示数据已过期。[请求日志契约](../../../contracts/agents-api/zh/admin-api.md#request-log)定义采集、容量限制及响应语义。说明放在问号提示中,不补造缺失的状态或错误数据。
## 默认模型 {#default-models}
| 操作 | 路由 | 控制台用途 |
| --- | --- | --- |
-| 列出 Harnesses | `GET /core/v1/harnesses` | Settings → Models and credentials 的 Default model 卡片:每个 Harness 的就绪状态(`enabled` 且已设置模型配置时为 Ready,否则为 Model provider not set 或 Disabled)、`default`、不含密钥的模型配置,以及来自配置中 `last_used_at`、`last_error_code` 和 `last_error_at` 的 Usage details;Overview 的 Getting started(默认 Harness 为 Ready;没有默认 Harness 时,任意 Harness 为 Ready) |
-| 设置或替换 | `PUT /core/v1/harnesses/{harness}/model-configuration` | **Set** 或 **Replace**:提交包含只写提供商密钥的完整模型配置;该密钥绝不预填,写入也绝不重试;400 会在表单中显示 Core 的消息;随后再次读取列表 |
-| 清除 | `DELETE /core/v1/harnesses/{harness}/model-configuration` | **Clear**,需确认,随后再次读取列表 |
+| 列出 Harnesses | `GET /core/v1/harnesses` | **设置 → 模型与凭据** 的 **默认模型配置** 卡片:每个 Harness 的就绪状态(`enabled` 且已设置模型配置时为 **就绪**,否则为 **未设置模型提供商** 或 **已禁用**)、`default`、不含密钥的模型配置,以及来自配置中 `last_used_at`、`last_error_code` 和 `last_error_at` 的 **使用详情**;**概览** 的 **新手引导**(默认 Harness 为 **就绪**;没有默认 Harness 时,任意 Harness 为 **就绪**) |
+| 设置或替换 | `PUT /core/v1/harnesses/{harness}/model-configuration` | **设置** 或 **替换**:提交包含只写提供商密钥的完整模型配置;该密钥绝不预填,写入也绝不重试;400 会在表单中显示 Core 的消息;随后再次读取列表 |
+| 清除 | `DELETE /core/v1/harnesses/{harness}/model-configuration` | **清除**,需确认,随后再次读取列表 |
列表会返回每个 Harness 的配置,因此控制台不会读取 `GET /core/v1/harnesses/{harness}/model-configuration`。
## 工作区存储 {#workspace-storage}
-**Settings → Workspace storage** 通过 `GET`、`PUT /core/v1/workspace-storage` 读取和选择配置,并更新租户容量。参数和只写凭据由 adapter 验证;Web 不定义 Provider 专属字段。表单不回显凭据,也不自动重试结果不确定的写入。完整语义见[管理 API](../../../contracts/agents-api/zh/admin-api.md#workspace-storage)。
+**设置 → 工作区存储** 通过 `GET`、`PUT /core/v1/workspace-storage` 读取和选择配置,并更新租户容量。参数和只写凭据由 adapter 验证;Web 不定义提供商专属字段。表单不回显凭据,也不自动重试结果不确定的写入。完整语义见[管理 API](../../../contracts/agents-api/zh/admin-api.md#workspace-storage)。
## Sandbox 管理 {#sandbox-administration}
| 操作 | 路由 | 控制台用途 |
| --- | --- | --- |
-| 部署 | `GET`、`POST`、`PUT /core/v1/sandbox/deployment` | 读取提供商、只读 `core_url`(即 `OAC_PUBLIC_URL`,会显示在设置审核中且绝不发送)、重置状态、安装 ID 和规范;409 `sandbox_configuration_error`(E2B 搭配回环地址形式的 `public_url`)会在设置向导中显示共享客户端固定的安全地址配置消息,并通过 Managed in Settings 前往 Settings → Service and deployment,且无需确认;使用 `resources` 以及 Docker 或 microsandbox 的 `runtime` release 初始化部署,或者使用 E2B 账户且不提供 `resources`(Core 采用模板构建的 CPU 和内存);使用预期的 generation 更改设置。E2B 的 `metadata.template_build`(状态、CPU、内存、磁盘)会显示在 Settings → Sandbox and scheduling 和 Sandbox metrics 中;当缺少 `specification.resources` 时,它还会确定每个 Sandbox 的大小;microsandbox 的 `suspension`(空闲和保留秒数)会显示在 Settings → Sandbox and scheduling 中 |
+| 部署 | `GET`、`POST`、`PUT /core/v1/sandbox/deployment` | 读取提供商、只读 `core_url`(即 `OAC_PUBLIC_URL`,会显示在设置审核中且绝不发送)、重置状态、安装 ID 和规范;409 `sandbox_configuration_error`(E2B 搭配回环地址形式的 `public_url`)会在设置向导中显示共享客户端固定的安全地址配置消息,并通过 **在设置中管理** 前往 **设置 → 服务与部署**,且无需确认;使用 `resources` 以及 Docker 或 microsandbox 的 `runtime` release 初始化部署,或者使用 E2B 账户且不提供 `resources`(Core 采用模板构建的 CPU 和内存);使用预期的 generation 更改设置。E2B 的 `metadata.template_build`(状态、CPU、内存、磁盘)会显示在 **设置 → 沙箱与调度** 和 **沙箱监控** 中;当缺少 `specification.resources` 时,它还会确定每个 Sandbox 的大小;microsandbox 的 `suspension`(空闲和保留秒数)会显示在 **设置 → 沙箱与调度** 中 |
| E2B 发现 | `POST /core/v1/sandbox/providers/e2b/discovery` | 设置向导先列出输入的 E2B 密钥可见的模板,再列出所选模板的可用构建。该密钥只会通过这些请求体和部署写入请求传输 |
| 重置 | `POST`、`DELETE /core/v1/sandbox/deployment/reset` | 显式清除托管资源,或在观测到的 generation 处取消剩余清除;显示 Core 的剩余资源和离线预测 |
-| Nodes | `GET /core/v1/sandbox/nodes` | Nodes 页面;Overview 上的机群;Sandbox metrics 中每个托管 Runtime 所在的节点。在线节点的 `diagnostic`(一个[就绪状态码](../getting-started/nodes.md#readiness-codes);任何其他值均读取为 `provider_unavailable`)会将其标记为降级,并在 Nodes 列表及节点页面中,紧邻状态的帮助提示里说明原因和修复方法。如果节点的 `core_url`(其注册时使用的地址)与部署的 `core_url` 不同,Nodes 页面会将其标记为绑定到旧地址,需要移除后重新添加;此时它在该页面和节点页面中的状态会显示 Old address,而不是健康状态。**Add node** 仅跟踪 `enrollment_id` 与其命令所含 `enrollment_id` 相等的节点 |
-| 节点详情 | `GET /core/v1/sandbox/nodes/{node_id}?range=1h\|6h\|24h` | Nodes 中的节点页面:主机最近一次心跳报告的 CPU 忙碌占比、内存使用量和可用磁盘,以及 1 小时、6 小时或 24 小时内 CPU 与内存的历史记录;页面可见时每 30 秒刷新一次。**Edit node** 读取 `host.effective_cpu_cores` 和 `host.total_memory_bytes`,用于在每个 Sandbox 大小旁显示主机容量,以及最多可容纳多少个该大小的 Sandbox |
-| 分配 | `GET /core/v1/sandbox/nodes/{node_id}/allocations` | Nodes 页面;Sandbox metrics。节点页面根据 `compute_phase_changed_at` 显示每个分配处于计算阶段的时间;时间为 null 时显示短横线。它不会根据阶段时间或部署的 `suspension.retention_seconds` 推算快照到期时间 |
-| 注册 | `POST /core/v1/sandbox/enrollment-tokens` | **Add node**:管理员先设置节点的 Sandbox 限制(`max_active`;`max_retained` 仅适用于 microsandbox,在 Docker 下等于 `max_active`),然后 Core 才会把一次性令牌放入命令中;该命令会验证安装程序校验和,并包含命令的 `enrollment_id`,节点注册时会报告此 ID。命令使用 sudo 运行安装程序(作为系统服务),并通过标准输入传递令牌;以 root 运行时则直接执行。界面不提供普通用户安装或移除入口,日志提示始终指明系统服务。命令从安装的 `public_url` 下载安装程序。只有成功读取安装信息后才会请求令牌;如果安装信息无法读取、安装为 `local_only`(或其 `public_url` 不是有效的 HTTP 或 HTTPS 来源),或者 `/console/config` 列出的 `node_artifacts` 不包含部署的提供商,则不会请求令牌。对话框在打开时和窗口重新获得焦点时,会再次读取这两项信息 |
-| 更新节点 | `PATCH /core/v1/sandbox/nodes/{node_id}` | **Edit node**:同时修改名称和 Sandbox 限制(保留数量限制仅适用于 microsandbox;在 Docker 下,Core 会将其设为活动数量限制) |
-| 移除节点 | `DELETE /core/v1/sandbox/nodes/{node_id}` | 确认后移除节点;只有 Core 确认删除后该行才会消失,随后 Clean up the host 对话框会提供主机的卸载命令(需要 root 或 sudo;对于使用不同于部署地址的地址注册的节点,还需要使用 `--force`,以跳过安装程序与 Core 的确认) |
-| Runtime 观测 | `GET /core/v1/sandbox/runtime-observations` | Sandbox metrics:每个项目的托管 Runtimes,每项均以所属项目为标签;E2B Sandbox 对话框还会将 `observation.disk` 显示为已用量/限制值(其他位置为 null) |
+| 节点 | `GET /core/v1/sandbox/nodes` | **节点** 页面;**概览** 上的机群;**沙箱监控** 中每个托管 Runtime 所在的节点。在线节点的 `diagnostic`(一个[就绪状态码](../getting-started/nodes.md#readiness-codes);任何其他值均读取为 `provider_unavailable`)会将其标记为降级,并在 **节点** 列表及节点页面中,紧邻状态的帮助提示里说明原因和修复方法。如果节点的 `core_url`(其注册时使用的地址)与部署的 `core_url` 不同,**节点** 页面会将其标记为绑定到旧地址,需要移除后重新添加;此时它在该页面和节点页面中的状态会显示 **地址已过期**,而不是健康状态。**添加节点** 仅跟踪 `enrollment_id` 与其命令所含 `enrollment_id` 相等的节点 |
+| 节点详情 | `GET /core/v1/sandbox/nodes/{node_id}?range=1h\|6h\|24h` | **节点** 中的节点页面:主机最近一次心跳报告的 CPU 忙碌占比、内存使用量和可用磁盘,以及 1 小时、6 小时或 24 小时内 CPU 与内存的历史记录;页面可见时每 30 秒刷新一次。**编辑节点** 读取 `host.effective_cpu_cores` 和 `host.total_memory_bytes`,用于在每个 Sandbox 大小旁显示主机容量,以及最多可容纳多少个该大小的 Sandbox |
+| 分配 | `GET /core/v1/sandbox/nodes/{node_id}/allocations` | **节点** 页面;**沙箱监控**。节点页面根据 `compute_phase_changed_at` 显示每个分配处于计算阶段的时间;时间为 null 时显示短横线。它不会根据阶段时间或部署的 `suspension.retention_seconds` 推算快照到期时间 |
+| 注册 | `POST /core/v1/sandbox/enrollment-tokens` | **添加节点**:管理员先设置节点的 Sandbox 限制(`max_active`;`max_retained` 仅适用于 microsandbox,在 Docker 下等于 `max_active`),然后 Core 才会把一次性令牌放入命令中;该命令会验证安装程序校验和,并包含命令的 `enrollment_id`,节点注册时会报告此 ID。命令使用 sudo 运行安装程序(作为系统服务),并通过标准输入传递令牌;以 root 运行时则直接执行。界面不提供普通用户安装或移除入口,日志提示始终指明系统服务。命令从安装的 `public_url` 下载安装程序。只有成功读取安装信息后才会请求令牌;如果安装信息无法读取、安装为 `local_only`(或其 `public_url` 不是有效的 HTTP 或 HTTPS 来源),或者 `/console/config` 列出的 `node_artifacts` 不包含部署的提供商,则不会请求令牌。对话框在打开时和窗口重新获得焦点时,会再次读取这两项信息 |
+| 更新节点 | `PATCH /core/v1/sandbox/nodes/{node_id}` | **编辑节点**:同时修改名称和 Sandbox 限制(保留数量限制仅适用于 microsandbox;在 Docker 下,Core 会将其设为活动数量限制) |
+| 移除节点 | `DELETE /core/v1/sandbox/nodes/{node_id}` | 确认后移除节点;只有 Core 确认删除后该行才会消失,随后 **清理主机** 对话框会提供主机的卸载命令(需要 root 或 sudo;对于使用不同于部署地址的地址注册的节点,还需要使用 `--force`,以跳过安装程序与 Core 的确认) |
+| Runtime 观测 | `GET /core/v1/sandbox/runtime-observations` | **沙箱监控**:每个项目的托管 Runtime,每项均以所属项目为标签;E2B Sandbox 对话框还会将 `observation.disk` 显示为已用量/限制值(其他位置为 null) |
-E2B 部署没有节点;其 API 密钥为只写。Overview 和 Sandbox metrics 根据部署的 `resources.allocations` 和 `resources.pending` 统计其正在运行和正在启动的 Sandbox,而托管 Runtime 行来自 Runtime observations。两个来源独立刷新,因此控制台不会根据两者之间的差异推断保留或清理状态。用于 Docker 和 microsandbox 的 Runtime release 来自控制台自身的 `GET /node-install/manifest.json`;如果无法获取该信息,管理员需在高级设置中输入 release。
+E2B 部署没有节点;其 API 密钥为只写。**概览** 和 **沙箱监控** 根据部署的 `resources.allocations` 和 `resources.pending` 统计其正在运行和正在启动的 Sandbox,而托管 Runtime 行来自 Runtime 观测。两个来源独立刷新,因此控制台不会根据两者之间的差异推断保留或清理状态。用于 Docker 和 microsandbox 的 Runtime 版本来自控制台自身的 `GET /node-install/manifest.json`;如果无法获取该信息,管理员需在高级设置中输入 release。
## 写入 {#writes}
- 删除操作使用管理员 API,并采用与公开删除操作相同的前置条件。每次删除都需要确认。4xx 会让对话框保持打开并显示 Core 给出的原因,404 视为已删除,其他任何失败都会报告为结果不确定,并随后执行一次全新读取。
- 控制台仅允许删除没有必需操作且处于空闲或失败状态的 Session,并且绝不会为了使 Session 可删除而取消正在执行的工作。
- 项目、密钥、执行器凭据、删除和 Sandbox 写入操作,每项明确的用户操作只发送一次,绝不会自动重试。结果不确定时,相关信息会保持可见,直到管理员重新读取状态并作出决定。
-- 执行器凭据签发结果未知时(无响应、30 秒超时或 5xx),控制台会打开错误对话框,下一步为 **Refresh list**。如果保留的 `key_id` 随后出现在列表中,则说明凭据已签发但其密钥已经丢失;控制台会提议轮换该凭据(`rotate: true`),以生成仅显示一次的新密钥。如果它未出现在列表中,下一次 Issue 会使用相同的 `key_id` 和 `rotate: false`;如果该请求因第一个请求实际上已成功签发而返回 409,控制台会再次读取列表,并且仅当该凭据在活动项目中列为活动状态时才提供相同的轮换操作,否则会将签发报告为已拒绝。已经列出的保留 `key_id` 绝不会被再次发送;从其所在行执行轮换或吊销后,控制台会清除该 ID,下一次 Issue 将生成新的 `key_id`。
+- 执行器凭据签发结果未知时(无响应、30 秒超时或 5xx),控制台会打开错误对话框,下一步为 **刷新列表**。如果保留的 `key_id` 随后出现在列表中,则说明凭据已签发但其密钥已经丢失;控制台会提议轮换该凭据(`rotate: true`),以生成仅显示一次的新密钥。如果它未出现在列表中,下一次 Issue 会使用相同的 `key_id` 和 `rotate: false`;如果该请求因第一个请求实际上已成功签发而返回 409,控制台会再次读取列表,并且仅当该凭据在活动项目中列为活动状态时才提供相同的轮换操作,否则会将签发报告为已拒绝。已经列出的保留 `key_id` 绝不会被再次发送;从其所在行执行轮换或吊销后,控制台会清除该 ID,下一次 Issue 将生成新的 `key_id`。
## 读取上限 {#read-bounds}
@@ -132,11 +132,11 @@ E2B 部署没有节点;其 API 密钥为只写。Overview 和 Sandbox metrics
| 页面 | 读取内容 | 上限 |
| --- | --- | --- |
| 资源列表 | 所选项目的所有页面,或并行读取所有项目的所有页面 | 每个项目最多 10,000 个条目;读取失败的项目会被指明,其他项目仍会显示 |
-| Session log | 所选项目的所有 Session 页面,按最新优先 | 每个项目最多 10,000 个;按请求刷新 |
+| Session 日志 | 所选项目的所有 Session 页面,按最新优先 | 每个项目最多 10,000 个;按请求刷新 |
| Session 页面 | Session、Items 和 Turns | 最多 10,000 个 Items 和 Turns;Session 进行中或等待时每 5 秒轮询一次,失败后退避至 60 秒 |
-| Overview | 汇总;24 小时活动及“需要处理”所用的 Session 列表,后者列出同一 24 小时内活跃的 Session | 每个项目最多 1,000 个 Sessions;跳过整个时段内都空闲的项目;可见时每 30 秒刷新一次。项目或 Session 读取失败时显示 Retry,而不是合成空结果;任何保留的数据或不完整数据都会附带明确的限定说明 |
-| Agent 指标 | 汇总;Session 列表;最近活动的 Sessions 的 Turns 和 Items | 每个项目列出最多 2,000 个 Sessions;每次加载读取 200 个 Sessions,每个 Session 读取 10 个 Turn 页面和 5 个 Item 页面;每个 Session 为 15 秒,每次加载为 45 秒 |
-| Sandbox metrics | Nodes 和 allocations;Runtime observations;按 ID 标识的托管 Sessions;Runtime 历史记录 | 每次刷新读取 100 个托管 Sessions;最多读取 24 个 Session 的历史记录;可见时每 30 秒刷新一次 |
+| 概览 | 汇总;24 小时活动及“需要处理”所用的 Session 列表,后者列出同一 24 小时内活跃的 Session | 每个项目最多 1,000 个 Sessions;跳过整个时段内都空闲的项目;可见时每 30 秒刷新一次。项目或 Session 读取失败时显示 Retry,而不是合成空结果;任何保留的数据或不完整数据都会附带明确的限定说明 |
+| Agent 监控 | 汇总;Session 列表;最近活动的 Sessions 的 Turns 和 Items | 每个项目列出最多 2,000 个 Sessions;每次加载读取 200 个 Sessions,每个 Session 读取 10 个 Turn 页面和 5 个 Item 页面;每个 Session 为 15 秒,每次加载为 45 秒 |
+| 沙箱监控 | 节点和分配;Runtime 观测;按 ID 标识的托管 Sessions;Runtime 历史记录 | 每次刷新读取 100 个托管 Sessions;最多读取 24 个 Session 的历史记录;可见时每 30 秒刷新一次 |
Agent 指标具有以下限制:
@@ -151,6 +151,6 @@ Agent 指标具有以下限制:
## 未使用的接口 {#not-consumed}
- 任何 `/v1/**` 路由,包括 Session 创建、Session 事件及其流、消息输入、函数结果和取消操作。
-- Agents、Environment templates、Skills、Files、Vaults 或 Credentials 的创建或更新,包括上传和 Credential 令牌替换。
+- Agent、Environment 模板、Skill、File、Vault 或 Credential 的创建或更新,包括上传和 Credential 令牌替换。
- 单个 Turn 读取、Artifacts、Session 执行配置、Environment Files 和管理端 Session 归档。
-- 管理员审计日志(`GET /core/v1/audit-log`)。Settings 会改为显示安装信息、每个 Harness 的默认模型和 Sandbox 部署。
+- 管理员审计日志(`GET /core/v1/audit-log`)。**设置** 会改为显示安装信息、每个 Harness 的默认模型和 Sandbox 部署。
diff --git a/docs/zh/web/console-server.md b/docs/zh/web/console-server.md
index a152253ce..ad7553313 100644
--- a/docs/zh/web/console-server.md
+++ b/docs/zh/web/console-server.md
@@ -91,7 +91,7 @@ flowchart LR
| 字段 | 含义 |
| --- | --- |
| `node_installer` | 控制台是否提供节点安装文件 |
-| `node_installer_sha256` | 文件中 `node-install.pyz` 的 SHA-256;Add node 命令执行安装程序前验证它 |
+| `node_installer_sha256` | 文件中 `node-install.pyz` 的 SHA-256;**添加节点** 命令执行安装程序前验证它 |
| `node_artifacts` | 文件中包含节点资产的提供商(`docker`、`microsandbox`),资产在本地或通过固定发行下载提供。每次请求都读取,因此重新运行安装程序新增的资产无需重启即可出现 |
## 节点安装文件 {#node-installation-payload}
@@ -108,7 +108,7 @@ flowchart LR
1. 控制台与 Core 的 `GET /healthz`。各自只证明进程响应。
2. 登录后在浏览器读取 `GET /core/v1/projects`。这证明浏览器到控制台、控制台到 Core 的路径和控制台 Core 密钥有效。
-3. Project API 密钥在 `/v1` 有效,在 `/core/v1` 失败。Core 密钥在 `/v1` 失败;发给控制台的 `/v1` 返回 404。
+3. 项目 API 密钥在 `/v1` 有效,在 `/core/v1` 失败。Core 密钥在 `/v1` 失败;发给控制台的 `/v1` 返回 404。
4. 跨来源控制台写入被拒绝,伪造 `X-Core-Console-Actor` 请求头不会改变审计标签。
5. 登录成功或读取沙箱部署(`GET /core/v1/sandbox/deployment`)均不能证明模型或沙箱就绪。Runtime 观察与历史独立报告执行情况。
diff --git a/docs/zh/web/index.md b/docs/zh/web/index.md
index b4f377b7f..f0104efbb 100644
--- a/docs/zh/web/index.md
+++ b/docs/zh/web/index.md
@@ -1,10 +1,10 @@
---
title: "OpenAgentCore Web"
source: docs/web/index.md
-source_hash: 6a336cfbec02e451ab41d5addb9744755ee60ef11da5121e0ab7abee61e45244
+source_hash: 3c4a694989738a6b8aad43b8554423a0a529f404d100740f4619e6a1669393fc
---
-Web 是单个 OpenAgentCore 部署的管理员控制台。管理员用它查看健康状态、容量、用量和失败情况,检查各 Project 的资源与执行历史,并管理 Project、密钥、节点和部署设置。应用不使用 Web;它们通过自己的 Project API 密钥调用 Core 的 Agents API(`/v1`)。
+Web 是单个 OpenAgentCore 部署的管理员控制台。管理员用它查看健康状态、容量、用量和失败情况,检查各项目的资源与执行历史,并管理项目、密钥、节点和部署设置。应用不使用 Web;它们通过自己的项目 API 密钥调用 Core 的 Agents API(`/v1`)。

@@ -12,22 +12,22 @@ Web 是单个 OpenAgentCore 部署的管理员控制台。管理员用它查看
使用部署的 [Core 密钥](../getting-started/operations.md#core-key)[登录](../getting-started/install.md#sign-in-to-web);控制台没有用户账号。浏览器只保留会话 cookie,[控制台服务器](console-server.md)代它向 Core 发送 Core 密钥;[登录](console-server.md#sign-in)说明会话有效期。
-登录后打开 Overview。仍有未完成步骤时,**Getting started** 清单引导完成四步,顺序不限:沙箱就绪、默认模型提供商、具有活动密钥的 Project、首个 Session。可从清单启动可选的控制台导览。
+登录后打开 **概览**。仍有未完成步骤时,**新手引导** 清单引导完成四步,顺序不限:沙箱就绪、默认模型提供商、具有活动密钥的项目、首个 Session。可从清单启动可选的控制台导览。
## 控制台页面 {#console-pages}
| 分组 | 页面 | 用途 |
| --- | --- | --- |
-| Monitor | Overview | 服务状态、运行中的 Session、沙箱槽位和待处理工作;24 小时 Session 活动;以拓扑展示 Core 与节点,各自打开对应页面;需要处理:过去 24 小时内活跃的失败或等待调用方的 Session,每行附一行原因;按 Project 统计的用量 |
-| Monitor | Core metrics | Core 能否运行 Turn:执行槽位、Turn 队列及其 p95 等待时间、被中断的 Turn、已连接守护进程、数据库延迟、CPU 与常驻内存及其限制、后台任务;Go 堆、goroutine 和数据库连接池位于 **Diagnostics** |
-| Monitor | Agent metrics | 1 小时、6 小时、24 小时或 7 天的请求、错误、耗时、token、模型、工具、Agent 和 API 密钥 |
+| 监控 | 概览 | 服务状态、运行中的 Session、沙箱槽位和待处理工作;24 小时 Session 活动;以拓扑展示 Core 与节点,各自打开对应页面;需要处理:过去 24 小时内活跃的失败或等待调用方的 Session,每行附一行原因;按项目统计的用量 |
+| 监控 | Core 监控 | Core 能否运行 Turn:执行槽位、Turn 队列及其 p95 等待时间、被中断的 Turn、已连接守护进程、数据库延迟、CPU 与常驻内存及其限制、后台任务;Go 堆、goroutine 和数据库连接池位于 **诊断** |
+| 监控 | Agent 监控 | 1 小时、6 小时、24 小时或 7 天的请求、错误、耗时、token、模型、工具、Agent 和 API 密钥 |
| Monitor | Sandbox metrics | 各 Project 托管 Runtime 随时间的变化,显示活跃数量与总数及其 CPU、内存观测;支持时另行显示 **Recorded compute** 生命周期状态;E2B 部署还显示 Core 在 E2B 云中持有的沙箱 |
-| Monitor | Request log | 到达 Core 的近期 HTTP 请求、状态、耗时和安全错误码;[范围及保留方式](../../../contracts/agents-api/zh/admin-api.md#request-log) |
-| Monitor | Session log | 全部 Session;各 Session 的只读对话、跟踪、Turn、失败分类原因及下一步操作;自托管 Session 页面还管理执行器凭据并提供主机连接命令 |
-| Resources | Agents、Environment templates、Skills、Files、Vaults | 检查和允许的删除操作,显示各资源所属 Project 及创建密钥 |
-| Platform | Projects and keys | 创建、重命名和归档 Project;签发与撤销密钥;各 Project 的用量、写入历史和 API 调用方法 |
-| Platform | Nodes | 添加、编辑和移除 microsandbox 或 Docker 节点;各节点的就绪状态、活跃与保留上限、主机 CPU 与内存及其历史、可用磁盘,以及分配及其在各计算阶段的已用时间 |
-| Platform | Settings | **Sandbox and scheduling**、**Workspace storage**、**Models and credentials** 和 **Service and deployment**;参阅[配置](../configuration.md#runtime-settings-web) |
+| 监控 | 请求日志 | 到达 Core 的近期 HTTP 请求、状态、耗时和安全错误码;[范围及保留方式](../../../contracts/agents-api/zh/admin-api.md#request-log) |
+| 监控 | Session 日志 | 全部 Session;各 Session 的只读对话、跟踪、Turn、失败分类原因及下一步操作;自托管 Session 页面还管理执行器凭据并提供主机连接命令 |
+| 资源 | Agent、Environment 模板、Skills、文件、Vault | 检查和允许的删除操作,显示各资源所属项目及创建密钥 |
+| 平台 | 项目与密钥 | 创建、重命名和归档项目;签发与撤销密钥;各项目的用量、写入历史和 API 调用方法 |
+| 平台 | 节点 | 添加、编辑和移除 microsandbox 或 Docker 节点;各节点的就绪状态、活跃与保留上限、主机 CPU 与内存及其历史、可用磁盘,以及分配及其在各计算阶段的已用时间 |
+| 平台 | 设置 | **沙箱与调度**、**工作区存储**、**模型与凭据** 和 **服务与部署**;参阅[配置](../configuration.md#runtime-settings-web) |
缺失数据展示为缺失(—),不会当作零。[控制台 API 使用](console-api-usage.md)列出各页面读取内容及统计边界。
@@ -36,16 +36,16 @@ Web 是单个 OpenAgentCore 部署的管理员控制台。管理员用它查看
| 任务 | 位置 |
| --- | --- |
| 为安装设置 HTTPS 地址 | 设置 `OAC_PUBLIC_URL`,并把反向代理指向 Web;参阅[使 Core 可访问](../getting-started/install.md#configure-the-domain-and-https) |
-| 选择沙箱后端(microsandbox、E2B 或 Docker)、规格和 Runtime,或重置后端 | **Settings → Sandbox and scheduling**;参阅[修改沙箱配置](../getting-started/nodes.md#change-the-sandbox-configuration) |
-| 添加、调整或移除执行节点 | **Nodes**:**Add node**、**Edit node** 和移除;参阅[节点指南](../getting-started/nodes.md) |
-| 设置 Harness 默认模型 | **Settings → Models and credentials**;参阅[默认模型](../configuration.md#default-models) |
-| 创建 Project 并签发 API 密钥 | **Projects and keys**;参阅 [Project 和 API 密钥](../getting-started/operations.md#projects-and-api-keys) |
-| 签发、轮换或撤销自托管执行器凭据,或复制安装命令 | **Session log** 中的 Session 页面;参阅[自托管执行器](../getting-started/self-hosted.md) |
-| 删除资源,例如泄露的 Credential | 资源列表行或资源页面;Files 从 Files 列表删除。适用公开删除规则 |
+| 选择沙箱提供商(microsandbox、E2B 或 Docker)、规格和 Runtime,或重置沙箱提供商 | **设置 → 沙箱与调度**;参阅[修改沙箱配置](../getting-started/nodes.md#change-the-sandbox-configuration) |
+| 添加、调整或移除执行节点 | **节点**:**添加节点**、**编辑节点** 和移除;参阅[节点指南](../getting-started/nodes.md) |
+| 设置 Harness 默认模型 | **设置 → 模型与凭据**;参阅[默认模型](../configuration.md#default-models) |
+| 创建项目并签发 API 密钥 | **项目与密钥**;参阅 [项目和 API 密钥](../getting-started/operations.md#projects-and-api-keys) |
+| 签发、轮换或撤销自托管执行器凭据,或复制安装命令 | **Session 日志** 中的 Session 页面;参阅[自托管执行器](../getting-started/self-hosted.md) |
+| 删除资源,例如泄露的 Credential | 资源列表行或资源页面;文件从 **文件** 列表删除。适用公开删除规则 |
-安装不创建 Project 或密钥。打开控制台不分配计算资源,也不调用模型,安装可以没有节点。Web 不启动 Session,也不发送输入。归档托管 Session 会请求取消和回收;[管理员权限](../concepts.md#what-administrators-can-and-cannot-do)说明管理员能执行与不能执行的操作。
+安装不创建项目或密钥。打开控制台不分配计算资源,也不调用模型,安装可以没有节点。Web 不启动 Session,也不发送输入。归档托管 Session 会请求取消和回收;[管理员权限](../concepts.md#what-administrators-can-and-cannot-do)说明管理员能执行与不能执行的操作。
-部署的沙箱后端服务托管 Session。应用的 `self_hosted` Runtime(包括它自己 E2B 账号中的 Runtime)是独立路径,修改沙箱配置不会影响它。
+部署的沙箱提供商服务托管 Session。应用的 `self_hosted` Runtime(包括它自己 E2B 账号中的 Runtime)是独立路径,修改沙箱配置不会影响它。
回环公开地址(`local_only`)使节点和远程应用无法访问 Core。控制台仍可通过自己的地址访问,并[展示警告](console-api-usage.md#provenance-and-monitoring)。
diff --git a/docs/zh/workspace-provider.md b/docs/zh/workspace-provider.md
index e5383a734..f29da1f80 100644
--- a/docs/zh/workspace-provider.md
+++ b/docs/zh/workspace-provider.md
@@ -1,10 +1,10 @@
---
-title: 工作区文件系统 Provider
+title: 工作区文件系统提供商
source: docs/workspace-provider.md
source_hash: ff018b1117a7f87786a23737212f1ed6b265d17fde43a0ef847f9f104788df2c
---
-独立工作区文件系统边界由 [`workspacefs.go`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/services/core/internal/workspacefs/workspacefs.go) 定义。本文规定必需的集成契约,并不表示所有 Sandbox Provider 或执行位置均已实现。文件系统适配器拥有存储对象与原生挂载解析职责;[Sandbox Provider](sandbox-provider.md) 拥有计算资源职责。Core 在分配任一资源前选择并验证二者的组合。
+独立工作区文件系统边界由 [`workspacefs.go`](https://github.com/MiniMax-AI/OpenAgentCore/blob/main/services/core/internal/workspacefs/workspacefs.go) 定义。本文规定必需的集成契约,并不表示所有沙箱提供商或执行位置均已实现。文件系统适配器拥有存储对象与原生挂载解析职责;[沙箱提供商](sandbox-provider.md) 拥有计算资源职责。Core 在分配任一资源前选择并验证二者的组合。
## 标识与配置 {#identity-and-configuration}
@@ -14,9 +14,9 @@ source_hash: ff018b1117a7f87786a23737212f1ed6b265d17fde43a0ef847f9f104788df2c
`ConfigurationRecord` 在配置之上增加由适配器编码的私有 `Credential`;参数不需要凭据时为空。凭据属于不可变配置。Core 使用安装的凭据加密密钥对其加密,并绑定安装 ID 与配置 ID,仅在 Core 中构造 `Control` 时解密。凭据绝不出现在 `Binding`、管理员响应、审计记录或日志中,节点也绝不会收到它。
-`Attachment` 将适配器签发的 JSON 对象 `Native` 绑定到完整引用、配置 ID 和挂载类型。它是内部归属凭证,不是应用提供的主机路径。共享验证检查信封结构以及预期引用和配置的匹配;所选适配器还必须验证参数、凭证及原生归属。结构有效本身绝不授权文件系统访问。公开 Session 载荷不得提供挂载凭证、配置参数或解析后的主机目录。
+`Attachment` 将适配器签发的 JSON 对象 `Native` 绑定到完整引用、配置 ID 和挂载类型。它是内部归属凭据,不是应用提供的主机路径。共享验证检查信封结构以及预期引用和配置的匹配;所选适配器还必须验证参数、凭据及原生归属。结构有效本身绝不授权文件系统访问。公开 Session 载荷不得提供挂载凭据、配置参数或解析后的主机目录。
-`Binding` 临时携带配置和挂载凭证至节点解析器,不引入第二份持久化节点配置。`Resolver.Resolve` 验证绑定后返回用于本地计算挂载的 `Directory{Path}`。仅适配器负责将原生存储解析为规范绝对路径;Core 不构造路径。结构有效的目录本身不是归属凭证。
+`Binding` 临时携带配置和挂载凭据至节点解析器,不引入第二份持久化节点配置。`Resolver.Resolve` 验证绑定后返回用于本地计算挂载的 `Directory{Path}`。仅适配器负责将原生存储解析为规范绝对路径;Core 不构造路径。结构有效的目录本身不是归属凭据。
## 操作与结果 {#operations-and-outcomes}
@@ -28,20 +28,20 @@ source_hash: ff018b1117a7f87786a23737212f1ed6b265d17fde43a0ef847f9f104788df2c
| --- | --- |
| `Declaration()` | 描述所选配置已经验证的挂载、用户扩展属性和配额行为。 |
| `Check(ctx)` | 验证配置和可用性,不创建对象。 |
-| `Create(ctx, reference, capacityMiB)` | 创建归属对象或收敛到其现有挂载凭证,不覆盖数据;重试与并发调用使用同一不可变引用和获准容量。正容量须在成功返回前实际强制执行,并在每次重试时重新验证。 |
-| `Observe(ctx, reference)` | 返回现有对象的绑定挂载凭证,不创建、修复或准备对象。 |
+| `Create(ctx, reference, capacityMiB)` | 创建归属对象或收敛到其现有挂载凭据,不覆盖数据;重试与并发调用使用同一不可变引用和获准容量。正容量须在成功返回前实际强制执行,并在每次重试时重新验证。 |
+| `Observe(ctx, reference)` | 返回现有对象的绑定挂载凭据,不创建、修复或准备对象。 |
| `Delete(ctx, reference)` | Core 授权删除且确认计算资源停止后,收敛到已验证归属对象的终态删除。 |
| `Resolve(ctx, binding)` | 验证原生归属并为本地计算解析挂载。 |
错误支持 `errors.Is`:`ErrInvalid` 表示无效输入,`ErrOwnership` 表示引用或配置不匹配,`ErrUnavailable` 表示存储不可用,`ErrUnconfirmed` 表示变更结果未知,`ErrNotFound` 表示对象不存在,`ErrUnsupported` 表示不支持的组合。适配器包装错误时保留这些结果。观察到不存在不证明先前变更已结束。超时或上下文取消只结束调用方的等待,不证明原生操作停止或回滚。结果未知时 Core 保留归属。Core 可以使用同一持久化不可变引用和配置重试 `Create` 或 `Delete`,包括收到 `ErrUnconfirmed` 后;绝不能通过替换新对象标识重试结果不确定的操作。
-同一引用的重试与并发收敛是适配器必须提供的保证。`Create` 保留现有对象数据并返回该归属对象的挂载凭证,绝不重新初始化存活对象。重复或并发的 `Delete` 调用收敛到同一终态删除。一旦记录终态删除,并发、延迟或重试的 `Create` 均不得使对象复活,`Resolve` 也不得暴露该对象。允许保留删除元数据,并在先前进行中的操作结束后继续清理。这些保证适用于存储生命周期操作,不表示超时时变更已结束,也不提供分布式计算隔离。
+同一引用的重试与并发收敛是适配器必须提供的保证。`Create` 保留现有对象数据并返回该归属对象的挂载凭据,绝不重新初始化存活对象。重复或并发的 `Delete` 调用收敛到同一终态删除。一旦记录终态删除,并发、延迟或重试的 `Create` 均不得使对象复活,`Resolve` 也不得暴露该对象。允许保留删除元数据,并在先前进行中的操作结束后继续清理。这些保证适用于存储生命周期操作,不表示超时时变更已结束,也不提供分布式计算隔离。
## 能力验证 {#capability-validation}
`Requirements` 声明计算位置的挂载类型及 `user_xattr` 需求。`Declaration` 报告文件系统适配器的挂载类型、`UserXAttr` 支持和 `CapacityQuota` 强制执行能力。`ValidateCombination` 是共享的分配前准入检查。当前挂载类型为 `host_directory`;未知类型会被拒绝。用户扩展属性能力表示挂载后的文件系统支持 Environment 准备流程使用的用户扩展属性。
-请求容量为零表示未请求配额。以 MiB 为单位的正容量仅在适配器实际强制执行该限制时获准;报告可用空间或接受未经检查的数字均不足够。`CapacityQuota` 表示适配器为每个以正容量创建的对象设定上限:限制对象已分配的字节(包括目录和元数据块)及其 inode 数量,而非文件的逻辑大小。超出上限的写入在 write 或 fsync 时报错,不会截断任何内容。适配器不能仅根据 Sandbox Provider 的计算磁盘大小声明配额支持。容量上限不提供任何 I/O 公平性。
+请求容量为零表示未请求配额。以 MiB 为单位的正容量仅在适配器实际强制执行该限制时获准;报告可用空间或接受未经检查的数字均不足够。`CapacityQuota` 表示适配器为每个以正容量创建的对象设定上限:限制对象已分配的字节(包括目录和元数据块)及其 inode 数量,而非文件的逻辑大小。超出上限的写入在 write 或 fsync 时报错,不会截断任何内容。适配器不能仅根据沙箱提供商的计算磁盘大小声明配额支持。容量上限不提供任何 I/O 公平性。
容量按对象准入。对于新绑定,Core 在绑定前根据部署请求验证所选配置的能力声明;随后若其他配置在此期间被选中,绑定事务以可重试的冲突拒绝。Core 将获准容量与引用一同持久化,并原样传给每次 `Create`。保留的绑定按其自身配置和获准容量验证,因此更改部署请求或选择不会调整现有存储的大小,也不会重新绑定。
@@ -75,7 +75,7 @@ source_hash: ff018b1117a7f87786a23737212f1ed6b265d17fde43a0ef847f9f104788df2c
该命令在存储服务器上以 root 运行。它持有一把锁,以不跟随链接的方式相对配置的导出打开 `objects//staging`,验证服务 UID、私有权限、设备及完整标识,拒绝已删除对象,并拒绝 `objects/` 或对象目录上的 project。同一 XFS 文件系统上、导出之外的本地 SQLite 日志库记录每个对象的引用、配置、容量、inode 上限、staging inode 及其 generation,以及从运维人员预留范围分配且永不复用的 project ID。分配先于任何变更提交;随后一次 `FS_IOC_FSSETXATTR` 在仍为空的 staging 目录上同时设置 project ID 和继承标志,服务器设置字节和 inode 硬限制(软限制为零)并回读验证。Stage 继承该 project;`live` 和退役的 trash 在重命名后保持该 project。标识、删除标记、对象目录和 `trash/` 父目录不属于该 project,因此已满的对象仍可标记删除并移除。移除会释放数据占用;保留的 `staging/` inode 仍计入该 project。属于其他文件系统或命名空间的日志库、未启用强制执行、范围耗尽、已有用户数据、外来或继承的 project、被替换的 staging inode、变更的引用、配置或容量,以及就绪对象上被修改或丢失的限制,均被拒绝而非修复。没有 dquot 的 project 读作零限制,绝不视为未使用的 ID。
-`Create` 成功时上限即具权威性;`Resolve` 不重新证明,因此恢复就绪工作区不依赖存储服务器的 SSH 服务。存储管理员事后禁用配额或清除限制会使强制执行失效,直至按支持的流程恢复。Project ID 和限制保存在 XFS 文件系统中,因此配额模式需要为其描述的[块级备份](getting-started/operations.md#back-up)。
+`Create` 成功时上限即具权威性;`Resolve` 不重新证明,因此恢复就绪工作区不依赖存储服务器的 SSH 服务。存储管理员事后禁用配额或清除限制会使强制执行失效,直至按支持的流程恢复。项目 ID 和限制保存在 XFS 文件系统中,因此配额模式需要为其描述的[块级备份](getting-started/operations.md#back-up)。
每个对象拥有 `objects//identity`、`staging/`、`live/`、`trash/`,以及删除开始后的 `deleted-marker`。永久标识绑定租户、Environment 和对象 UUID。Create 先准备并同步唯一的私有 staging 封装目录,再原子发布其非空目录为 `live`;重放不会覆盖现有 live 数据。Delete 先持久记录对象本地的终态标记,将 live 数据退役到唯一的对象本地 trash,再先删除数据、后删除其所有权标记。并发删除者收敛。最少量的标识和删除元数据会有意保留;删除不代表所有元数据文件均消失。Create 和 Resolve 拒绝已退役标识。迟到的在途 Create 可能留下空的受控元数据,需要在其系统调用完成后重复 Delete;它不能授权新写入者或复用对象标识。清理只查看该对象的 staging 和 trash,不全量扫描命名空间,也不使用后台服务。
diff --git a/website/.vitepress/config.mts b/website/.vitepress/config.mts
index afeb2aa8d..1dd497dc0 100644
--- a/website/.vitepress/config.mts
+++ b/website/.vitepress/config.mts
@@ -13,7 +13,7 @@ const require = createRequire(import.meta.url)
const vueDir = dirname(require.resolve('vue/package.json'))
const repo = 'https://github.com/MiniMax-AI/OpenAgentCore'
-const description = 'An open-source, self-hosted implementation of the OpenAI Agents API with multiple native harnesses.'
+const description = 'An open-source, self-hosted implementation of the OpenAI Agents API with multiple native Harnesses.'
const base = siteBase(process.env.WEBSITE_URL)
diff --git a/website/.vitepress/theme/components/SessionFlow.vue b/website/.vitepress/theme/components/SessionFlow.vue
index 8ad38d057..7ac648b8c 100644
--- a/website/.vitepress/theme/components/SessionFlow.vue
+++ b/website/.vitepress/theme/components/SessionFlow.vue
@@ -9,7 +9,7 @@ const props = defineProps<{ lang: Lang }>()
const copy = computed(() => props.lang === 'zh' ? {
stages: ['原生 Agent', '统一执行', '自由组合'],
captions: ['Runtime 准备环境,原生 Harness 运行模型与工具循环。', '应用通过 Agents API 创建 Session,Core 管理执行与持久状态。', '不同 Session 使用不同 Harness 与模型;此示例中的托管 Session 共用 microsandbox 部署,独立工作区可跨计算生命周期保留。'],
- app: '你的应用', api: 'OpenAI SDK · Agents API', state: 'Session 与 Turn', orchestration: '调度 · 取消 · 交互', events: '事件 · 结果 · 持久状态', workspace: '挂载工作区 · Shell · 工具', loop: '原生 Agent 循环', runtime: '环境准备 · 执行管理', model: '模型服务', provider: 'Sandbox Provider', compute: '创建与回收计算资源', next: '下一步', back: '上一步', play: '播放', pause: '暂停', label: 'Session 架构演示', step: '演示阶段',
+ app: '你的应用', api: 'OpenAI SDK · Agents API', state: 'Session 与 Turn', orchestration: '调度 · 取消 · 交互', events: '事件 · 结果 · 持久状态', workspace: '挂载工作区 · Shell · 工具', loop: '原生 Agent 循环', runtime: '环境准备 · 执行管理', model: '模型提供商', provider: '沙箱提供商', compute: '创建与回收计算资源', next: '下一步', back: '上一步', play: '播放', pause: '暂停', label: 'Session 架构演示', step: '演示阶段',
} : {
stages: ['Native agent', 'Managed execution', 'Many combinations'],
captions: ['Runtime prepares the environment. The native harness owns the model and tool loop.', 'Your app creates a Session through the Agents API. Core manages execution and durable state.', 'Sessions use different Harnesses and models. Managed Sessions here share one microsandbox deployment; independent workspaces outlive compute.'],
diff --git a/website/.vitepress/theme/landing-content.ts b/website/.vitepress/theme/landing-content.ts
index 9e105fa2c..99f12ee6f 100644
--- a/website/.vitepress/theme/landing-content.ts
+++ b/website/.vitepress/theme/landing-content.ts
@@ -224,8 +224,8 @@ const zh: LandingCopy = {
lede: 'Core 编排,原生 Harness 在沙箱内执行;计算与持久工作区存储由独立 adapter 管理。',
tabs: [
{ id: 'ecosystem', label: '生态', alt: '应用通过 Agents API 接入 Core;原生 Harness 在沙箱内运行并调用模型,计算与持久工作区存储由独立 adapter 管理。' },
- { 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。' },
+ { id: 'protocols', label: '组件', alt: 'Core 之上是 Agents API 与 Core API;沙箱提供商、Runtime、Harness、模型提供商通过协议连接。' },
+ { id: 'surfaces', label: 'API 命名空间', alt: '三个命名空间、三种凭据:应用用 Agents API,管理员用 Core API,节点用 Machine API。' },
],
more: '阅读架构文档',
},
@@ -254,7 +254,7 @@ const zh: LandingCopy = {
title: '运行情况,看得见。', titleAccent: '看得见。',
lede: 'Session 状态 · 计算资源 · 用量',
tabs: [
- { id: 'overview', label: '部署概览', alt: 'Web 控制台概览:服务状态、运行中的 Session、沙箱容量、节点与 Project。' },
+ { id: 'overview', label: '部署概览', alt: 'Web 控制台概览:服务状态、运行中的 Session、沙箱容量、节点与项目。' },
{ id: 'metrics', label: 'Agent 监控', alt: 'Web 控制台 Agent 监控:请求、错误、耗时、Token 与工具调用。' },
],
caption: '截图数值仅用于展示界面。用量可见性取决于原生 Harness 提供的数据。',
diff --git a/website/index.md b/website/index.md
index 194c9c5ed..92771439e 100644
--- a/website/index.md
+++ b/website/index.md
@@ -2,7 +2,7 @@
layout: page
title: OpenAgentCore — One core. Many agents.
titleTemplate: false
-description: An open-source, self-hosted implementation of the OpenAI Agents API with multiple native harnesses.
+description: An open-source, self-hosted implementation of the OpenAI Agents API with multiple native Harnesses.
---