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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
467 changes: 457 additions & 10 deletions Cargo.lock

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,17 @@ Copyright 2026 fliaping
This product is licensed under the Apache License, Version 2.0 (see LICENSE).
Third-party components bundled in container images and desktop builds keep
their own licenses; see docs/licenses/.

Model protocol translation includes code ported or adapted from:

- pleaseai/shunt, commit 9d42ba251dd1f0651e9d150767e3ff98a1ae042b,
MIT OR Apache-2.0; crates/cranibox-llm/src/proto/vendor/shunt/.
- link-assistant/router, commit 07901ad24576e7f045270fe62ac56f8a72446c53,
Unlicense; crates/cranibox-llm/src/proto/chat.rs, with license in
crates/cranibox-llm/src/proto/vendor/link_assistant/.
- yetone/magpie, commit 865b61808690bc9fd716257949414ec97618a5a5,
MIT; crates/cranibox-llm/src/proto/port/magpie/ and provider adaptations.

Original copyright and license texts are retained alongside the vendored
code. See crates/cranibox-llm/tests/THIRD-PARTY.md for source paths,
adaptations and provider protocol attribution.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ Cranibox 是你自己部署的 AI Agent “脑壳”:一个跑在你的服务

## 架构

Cranibox 新里程碑的目标规格与逐项完成情况见[设计文档](docs/design/README.md)及[实现核对与缺口](docs/design/IMPLEMENTATION-STATUS.md)。

<p align="center">
<a href="images/architecture.zh.svg"><img src="images/architecture.zh.png" width="900" alt="Agent Workspace 架构图"></a>
<br><sub>点击图片查看可缩放的 SVG 版本</sub>
Expand Down Expand Up @@ -257,7 +259,7 @@ docker run -d --name agent-workspace \
-e SELKIES_CONGESTION_CONTROL=false \
-e SELKIES_ENABLE_RESIZE=true \
-e AGENT_WORKSPACE_BOOTSTRAP=remote \
-e AGENT_WORKSPACE_AGENT=codex \
-e AGENT_WORKSPACE_AGENT=deepseek-harness \
-p 3001:3001 -p 8443:8443 \
-v ~/agent-workspace-data:/config \
xuping/agent-workspace:ubuntu-xfce
Expand Down Expand Up @@ -322,7 +324,7 @@ code-server 默认监听 `0.0.0.0:8443`,因此需要在创建容器时映射 `
| `START_DOCKER` | `false` | 启用容器内 Docker(需 `--privileged`) |
| `USE_CHINA_MIRROR` | `false` | 运行时切换国内镜像源 |
| `AGENT_WORKSPACE_BOOTSTRAP` | 不设置 | 设为 `remote`(或 `foundation` / `base`)时,首次启动自动安装 code-server、Control Center 和桌面集成;`remote-up.sh` 会设置为 `remote` |
| `AGENT_WORKSPACE_AGENT` | `none`(`remote-up.sh` 默认 `codex`) | 首次引导时安装 `codex`、`claude-code`、`hermes`、`deepseek-harness`、`openclaw` 或 `none`;仅在设置 `AGENT_WORKSPACE_BOOTSTRAP` 时生效 |
| `AGENT_WORKSPACE_AGENT` | `deepseek-harness` | 首次引导时安装 `codex`、`claude-code`、`pi`、`hermes`、`deepseek-harness`、`openclaw` 或 `none`;仅在设置 `AGENT_WORKSPACE_BOOTSTRAP` 时生效 |
| `CODE_SERVER_BIND` / `CODE_SERVER_AUTH` / `CODE_SERVER_CERT` | `0.0.0.0:8443` / `password` / `true` | code-server 监听地址、认证方式和自签名证书;密码默认取 `PASSWORD` |
| `SSH_PASSWORD` | 不设置 | 设置后启用 SSH 服务(容器端口 22),值为 abc 用户密码;compose 文件默认不映射该端口,需要时添加如 `-p 2222:22` |
| `NODE_OPTIONS` | - | Node.js 选项(如 `--max-old-space-size=2048`) |
Expand Down
4 changes: 2 additions & 2 deletions README_en.md
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ docker run -d --name agent-workspace \
-e SELKIES_CONGESTION_CONTROL=false \
-e SELKIES_ENABLE_RESIZE=true \
-e AGENT_WORKSPACE_BOOTSTRAP=remote \
-e AGENT_WORKSPACE_AGENT=codex \
-e AGENT_WORKSPACE_AGENT=deepseek-harness \
-p 3001:3001 -p 8443:8443 \
-v ~/agent-workspace-data:/config \
xuping/agent-workspace:ubuntu-xfce
Expand Down Expand Up @@ -332,7 +332,7 @@ Each release also publishes pinned tags such as `ubuntu-xfce-1.0.35`; see
| `START_DOCKER` | `false` | Enable Docker inside container (requires `--privileged`) |
| `USE_CHINA_MIRROR` | `false` | Switch to China mirrors at runtime |
| `AGENT_WORKSPACE_BOOTSTRAP` | unset | `remote` (or `foundation` / `base`) installs code-server, Control Center, and desktop integration on first boot; `remote-up.sh` sets `remote` |
| `AGENT_WORKSPACE_AGENT` | `none` (`codex` with `remote-up.sh`) | First-boot Agent: `codex`, `claude-code`, `hermes`, `deepseek-harness`, `openclaw`, or `none`; only used when `AGENT_WORKSPACE_BOOTSTRAP` is set |
| `AGENT_WORKSPACE_AGENT` | `deepseek-harness` | First-boot Agent: `codex`, `claude-code`, `pi`, `hermes`, `deepseek-harness`, `openclaw`, or `none`; only used when `AGENT_WORKSPACE_BOOTSTRAP` is set |
| `CODE_SERVER_BIND` / `CODE_SERVER_AUTH` / `CODE_SERVER_CERT` | `0.0.0.0:8443` / `password` / `true` | code-server listen address, authentication, and self-signed certificate; the password defaults to `PASSWORD` |
| `SSH_PASSWORD` | unset | Set to enable SSH service (container port 22), value is abc user password; the compose files do not publish it, add e.g. `-p 2222:22` |
| `NODE_OPTIONS` | - | Node.js options (e.g., `--max-old-space-size=2048`) |
Expand Down
2 changes: 1 addition & 1 deletion addons/control-center/index.en.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!doctype html>
<html lang="en"><head>
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'self' 'nonce-__WORKSPACE_NONCE__'; style-src 'self' 'unsafe-inline'; connect-src 'self'; img-src 'self' data:; font-src 'self'; base-uri 'none'; form-action 'self';">
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'self' 'nonce-__WORKSPACE_NONCE__'; style-src 'self' 'unsafe-inline'; connect-src 'self'; frame-src 'self'; img-src 'self' data:; font-src 'self'; base-uri 'none'; form-action 'self';">
<meta name="color-scheme" content="dark light"><title>Cranibox · Agent Workspace</title>
<link rel="icon" href="data:,"><link rel="stylesheet" href="/web.css">
<script nonce="__WORKSPACE_NONCE__">try{document.documentElement.dataset.theme=localStorage.getItem("workspace.theme")==="light"?"light":"dark"}catch{}</script>
Expand Down
2 changes: 1 addition & 1 deletion addons/control-center/index.zh-cn.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!doctype html>
<html lang="zh-cn"><head>
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'self' 'nonce-__WORKSPACE_NONCE__'; style-src 'self' 'unsafe-inline'; connect-src 'self'; img-src 'self' data:; font-src 'self'; base-uri 'none'; form-action 'self';">
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'self' 'nonce-__WORKSPACE_NONCE__'; style-src 'self' 'unsafe-inline'; connect-src 'self'; frame-src 'self'; img-src 'self' data:; font-src 'self'; base-uri 'none'; form-action 'self';">
<meta name="color-scheme" content="dark light"><title>Cranibox · Agent Workspace</title>
<link rel="icon" href="data:,"><link rel="stylesheet" href="/web.css">
<script nonce="__WORKSPACE_NONCE__">try{document.documentElement.dataset.theme=localStorage.getItem("workspace.theme")==="light"?"light":"dark"}catch{}</script>
Expand Down
16 changes: 15 additions & 1 deletion addons/control-center/ui/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import { WebTerminalEnvironment } from './terminal/WebTerminalEnvironment';
import { Nodes } from './pages/Nodes';
import { Performance } from './pages/Performance';
import './style.css';
import { PersonalApp } from './personal/PersonalApp';
import { httpApi } from './personal/api';
import './terminal/terminal.css';
import './terminal/window.css';
import { openUrl,t,useWorkspace,WorkspaceProvider } from './workspace';
Expand Down Expand Up @@ -84,4 +86,16 @@ function LinkBrand() { return <a className="brand" href="#/overview"><span class
// Keep bookmarks from the previous control center working.
const legacy = location.hash.slice(1);
if (nav.some(item => item.id === legacy)) history.replaceState(null, '', '#/' + legacy);
createRoot(document.getElementById('root')!).render(<HashRouter><TerminalWindowProvider><WorkspaceProvider><WebTerminalEnvironment><App /></WebTerminalEnvironment></WorkspaceProvider></TerminalWindowProvider></HashRouter>);
const personalApi = httpApi(window.workspaceWeb.csrf);
function PersonalShell() {
const navigate = useNavigate();
const location = useLocation();
useEffect(() => {
if (location.pathname === '/app/advanced') navigate('/overview', { replace: true });
}, [location.pathname, navigate]);
// HashRouter commits navigation in a transition. Wait for its location before
// mounting the legacy routes, whose fallback would redirect the previous URL.
const personalRoute = location.pathname === '/' || location.pathname.startsWith('/app/');
return <PersonalApp api={personalApi} language={window.workspaceWeb.language} advanced={personalRoute ? null : <App />} onNavigate={navigate} />;
}
createRoot(document.getElementById('root')!).render(<HashRouter><TerminalWindowProvider><WorkspaceProvider><WebTerminalEnvironment><PersonalShell /></WebTerminalEnvironment></WorkspaceProvider></TerminalWindowProvider></HashRouter>);
Loading
Loading