OpenHands Canvas Extensions 扩展机制解析:契约、信任模型与前后端运行时实现
本文基于 OpenHands 仓库中的规范文档 specs/canvas-extensions.md 展开,系统讲解 Canvas Extensions 的产品定位、v1 信任决策、canvas-extension.json 清单契约、Agent Server API、前端运行时激活流程与交付切分。读完本文,你将理解一个 Canvas 扩展包从安装、启用、热激活到卸载的完整生命周期,并能对照仓库中已落地的类型定义、服务层、模块加载器、路由与 fixture 实现验证每一项契约。
一、产品定位:扩展改变的是"应用",不是"Agent"
规范开篇给出了一个清晰的产品定义:Canvas Extensions 是安装后会改变 Agent Canvas(前端应用)本身的安装包,它们贡献 UI 与本地产品行为——路由页面(routed pages)、会话面板(conversation panels)、渲染器(renderers)、插槽(slots)与主题(themes)。规范用一个对比句划定了边界:
Skills 和 plugins 改变的是 agent;Canvas Extensions 改变的是 app。
同时规范约定了产品入口:Customize 区域是 Skills、Plugins、MCP 与 Canvas Extensions 的唯一清单(inventory),清单条目统一命名为 Extensions("addon" 只是非正式别名)。从仓库源码看,这一入口对应 extensions-hub 路由:route("customize", "routes/extensions-hub.tsx"),而扩展管理页挂在 route("extensions", "routes/canvas-extensions.tsx"),扩展页面路由为 route("extensions/:extensionName/*", "routes/canvas-extension-page.tsx")。
规范开头还声明了状态属性:这是"实现计划与 v1 契约"(Implementation plan and v1 contract)。前端纵向切片(vertical slice)可以在 Agent Server 端点尚未就绪时,依托后端的**能力探测(capability detection)**先行发布。
二、六项关键决策:信任模型是理解一切的前提
规范用六个编号决策框定了 v1 的行为边界,每一条都有明确的实现对应。
1. 活跃的 Agent Server 拥有扩展
扩展安装在运行 Agent Server 的计算机或容器上。它的源码、解析后的 revision、文件、清单与启用状态都存放在后端;Canvas(前端)只从当前活跃后端发现并加载扩展。切换后端即整体替换活跃扩展集合。这一决策在源码中体现为查询键设计:use-canvas-extensions.ts 中 query key 由 backend.id、orgId、connectionRevision 三元组构成,且 retry: false、staleTime: 0,确保不同后端的扩展清单互不串扰。
2. 扩展代码是受信的同域代码(trusted, same-realm)
v1 没有 iframe、worker 沙箱或细粒度权限系统。启用后,扩展拥有与 Canvas 自身代码相同的浏览器环境权限。Shadow DOM 未来可能作为可选样式隔离提供,但绝不作为安全边界。规范第 7 节的 non-goals 再次强调这一点(见下文"v1 明确不做的事")。
3. 安装与启用是分离的
安装永远产生一个禁用态扩展。Agent 可以安装或更新扩展,但必须由用户回到 Customize → Extensions 显式启用。v1 将"安装与启用分离"作为产品同意不变量(product consent invariant),而不是针对 agent 的人类在场证明——因为 agent 可以调用同样的已认证 API。未来后端策略可能允许 agent 驱动启用。
4. 启用是热的(Enablement is hot)
启用无需重启应用或 Agent Server 即可加载并激活扩展;禁用会卸载已注册的界面并调用生命周期清理(disposer)。由于代码是受信的同域 JavaScript,清理是**尽力而为(best-effort)**的——扩展可以创建宿主无法撤销的全局副作用。这一流程在 canvas-extensions-runtime.tsx 中完整实现:激活效果函数在 cleanup 阶段反向遍历 disposers 逐一调用,异常仅记录日志而不阻断其余清理。
5. 分发跟随 plugins 的模式,而非其运行时
安装坐标为 source、可选 ref、可选 repo_path,由 Agent Server 负责解析与 pin(锁定版本)。一个仓库可以在子路径下包含多个扩展及其他工件类型。后端本地路径在后端机器上解释,绝不在前端进程解释。
6. 更新保留启用状态
Refresh 以原子方式解析并安装新 revision,保留先前的启用状态,UI 展示解析后的 revision。v1 是受信代码模型,因此不存在误导性的权限 diff 审批门。规范同时说明:staged check/apply 流程目前只存在于 Agent Server 服务层,在通过 HTTP 暴露之前,Customize UI 不提供 Refresh 操作。
三、信任披露:如实告知,不虚构权限
规范对信任披露(trust disclosure)有明确规定:
- 启用前,Canvas 明确告知用户:该扩展可以访问并修改 Canvas 页面,并可以发起当前浏览器会话可用的已认证请求;
- 审查界面展示:来源(source)、请求的 ref、解析后的 revision、清单元数据、贡献的界面(surfaces);
- 界面不展示虚构的细粒度权限。
规范特别强调:安装和更新仍是有效的信任动作,因为它们选择了后端存储的代码 revision;而"启用"是 Canvas 实际执行该代码的显式时点。在前端实现中,管理页 canvas-extensions.tsx 顶部常驻一条琥珀色信任提示条(I18nKey.SETTINGS$CANVAS_EXTENSIONS_TRUST_NOTICE),且启用操作会先弹出 ConfirmationModal 确认框,只有禁用和解安装是直接执行或二次确认后的操作——与规范"install/enable 分离、enable 需显式同意"的不变量一致。
四、包契约:canvas-extension.json 与 activate 导出
4.1 清单文件格式
清单文件名固定为 canvas-extension.json。规范给出的 v1 示例:
{
"schema_version": 1,
"name": "example-dashboard",
"display_name": "Example dashboard",
"version": "0.1.0",
"description": "A backend-specific project dashboard.",
"entrypoint": "dist/extension.js",
"contributes": {
"pages": [
{
"id": "dashboard",
"title": "Dashboard",
"path": "/dashboard",
"nav_label": "Dashboard"
}
]
}
}
v1 清单规则:
name与贡献 ID 只允许小写字母、数字和连字符;- Page 的
path是绝对 kebab-case 路由(以/开头);Canvas 将其挂载在/extensions/{name}之下; entrypoint是安装包内部的路径;- entrypoint 必须是单个自包含的浏览器 ESM bundle——不允许未解析的裸导入(bare imports)或外部 chunk;依赖、CSS 与小资源由作者模板负责打包或内嵌;
- 后端会校验 manifest、entrypoint 以及未来任何 asset 路径不得逃逸出已安装扩展根目录;
- 面向市场分发的宿主兼容字段将在市场分发前补充;初始 schema 刻意保持精简,页面 ABI(应用二进制接口)由一个独立构建的示例扩展先行验证。
仓库中恰好存在规范所指的"示例扩展"——fixture 扩展 demo-page。其清单 canvas-extension.json 与规范示例同构:schema_version: 1、name: "demo-page"、entrypoint: "extension.js",并在 contributes.pages 中声明了 id: "hello"、path: "/hello" 的页面。README 说明该 fixture 是"清单 schema 1 与 host API 1 的独立、无依赖实现",其 extension.js 本身就是自包含浏览器 ES 模块,Agent Server 测试实现可直接安装该目录并从已认证的 bundle 端点提供 extension.js。
共享的 TypeScript 类型定义落在 src/types/canvas-extension.ts:CANVAS_EXTENSION_MANIFEST_SCHEMA_VERSION = 1、CANVAS_EXTENSION_HOST_API_VERSION = "1",以及 CanvasExtensionManifest、InstalledCanvasExtensionInfo、InstallCanvasExtensionRequest、CanvasExtensionHost 等接口。其中 InstalledCanvasExtensionInfo.manifest 字段标注为"在 OSS-10048 之前后端不返回页面贡献时缺席"——即规范中"manifest 字段尚未由当前路由返回,Canvas 将其视为可选"这一过渡态的类型化表达。
4.2 模块导出 activate 与宿主 API
v1 模块导出 activate,规范给出的最小示例:
export function activate(host: CanvasExtensionHost): void | (() => void) {
return host.registerPage("dashboard", ({ container, path, navigate }) => {
container.textContent = `Extension route: ${path}`;
return () => container.replaceChildren();
});
}
fixture 扩展 extension.js 是该 ABI 的无依赖落地版本:activate(host) 调用 host.registerPage("hello", mount),mount 向 container 追加 DOM 并返回 disposer(() => wrapper.remove());渲染内容使用 var(--oh-text-primary) 等宿主 CSS token 与 host.apiVersion、host.backend.id 元数据,直观演示了宿主 API 的使用方式。
CanvasExtensionHost 独立于 manifest 版本演进。首个宿主 API 包含(类型定义见 src/types/canvas-extension.ts 的 CanvasExtensionHost 接口):
apiVersion: "1";- 不可变的扩展/后端元数据(
extension: { name, version, resolvedRef }与backend: { id, kind, orgId },运行时用Object.freeze冻结后传入); registerPage(id, mount),用于注册清单中声明的页面工厂;navigate(path),走 Canvas 感知 base path 的路由(实现中直接委托 React Router 的navigate);agentServer.request(...),指向扩展所属后端的已认证请求辅助。
4.3 为什么用 Blob URL 加载 bundle
规范给出了一条关键实现约束:运行时以已认证文本方式获取 bundle,再通过临时 Blob URL 导入。原因是直接 <script src> 或 import(backendUrl) 无法携带 X-Session-API-Key 请求头,因此不是 v1 的加载路径。同时,导入 bundle 不等于激活——Canvas 只对已启用的安装调用 activate。
源码 canvas-extension-module-loader.ts 精确实现了该契约:
export async function loadCanvasExtensionModule(
source: string,
): Promise<CanvasExtensionModule> {
const blob = new Blob([source], { type: "text/javascript" });
const moduleUrl = URL.createObjectURL(blob);
try {
const imported: unknown = await import(/* @vite-ignore */ moduleUrl);
assertCanvasExtensionModule(imported);
return imported;
} finally {
URL.revokeObjectURL(moduleUrl);
}
}
配套的 assertCanvasExtensionModule 断言模块必须导出名为 activate 的函数,否则抛出 InvalidCanvasExtensionModuleError。函数注释直接点明动机:"不把 Agent Server 会话密钥放进 URL,来源已经通过 Canvas 的已认证 HTTP 客户端获取"。
五、Agent Server API:与插件分发管理同构、运行时独立
规范声明该 API "刻意镜像插件的分发管理,但保持独立的运行时",并给出端点表:
| Method | Path | Purpose |
|---|---|---|
GET |
/api/canvas-extensions/installed |
列出已安装扩展与解析后的清单 |
POST |
/api/canvas-extensions/install |
从 git 或后端本地路径安装;始终禁用态 |
GET |
/api/canvas-extensions/installed/{name} |
读取单个安装项 |
PATCH |
/api/canvas-extensions/installed/{name} |
设置启用状态 |
DELETE |
/api/canvas-extensions/installed/{name} |
卸载 |
GET |
/api/canvas-extensions/installed/{name}/bundle |
以 JavaScript 文本返回 entrypoint |
Refresh 端点(POST /api/canvas-extensions/installed/{name}/refresh)已规划但不在当前路由中;其背后的服务层 staged check/apply 流程单独跟踪。列表端点把结果包在 canvas_extensions 数组里。
安装请求体:
{
"source": "github:owner/repository",
"ref": "main",
"repo_path": "extensions/example-dashboard",
"force": false
}
安装响应体:
{
"name": "example-dashboard",
"version": "0.1.0",
"description": "A backend-specific project dashboard.",
"enabled": false,
"source": "github:owner/repository",
"resolved_ref": "6f5f9a...",
"repo_path": "extensions/example-dashboard",
"installed_at": "2026-08-01T12:00:00Z",
"install_path": "/home/user/.openhands/canvas-extensions/installed/example-dashboard",
"manifest": {}
}
manifest 字段(解析后的 canvas-extension.json,含 contributes.pages)在当前路由实现中尚未返回;在其上线之前,Canvas 将其视为可选,对没有页面贡献或 display name 的安装项照常渲染。
服务层实现 canvas-extensions-service.ts 与规范逐条对应:
listInstalled()请求GET /api/canvas-extensions/installed并解包canvas_extensions数组(response.canvas_extensions ?? []),与"列表端点包裹在 canvas_extensions 数组"一致;install(request)对应 POST install;setEnabled(name, enabled)走 PATCH;uninstall(name)走 DELETE;fetchBundle(name, backend?)以responseType: "text"拉取installed/{name}/bundle,即"以 JavaScript 文本返回 entrypoint"的已认证文本加载路径;- 一个值得注意的细节:
requestAgentServer强制path必须以/开头且不能以//开头(根相对路径校验),这正是规范"后端本地路径在后端机器上解释、绝不进入前端"以及请求必须锚定在后端路由空间的具体约束。
404 能力探测:不把所有失败混为一谈
规范对过渡期有一处硬性要求:在 API 存在之前,Canvas 把 HTTP 404 视为"该后端不支持 Canvas Extensions"。Customize 页面显示升级提示,而全局运行时保持静默。并且必须不能把"不支持"、"不可达"与"空清单"折叠成同一种状态。
服务层的实现方式是 mapUnsupported 包装:捕获到 404 状态错误时转换为 CanvasExtensionsUnsupportedError("missing-api")。该类还定义了另外两种原因——no-backend(未添加 Agent Server 后端)与 cloud-backend(Cloud 后端暂不可用),分别对应不同的用户提示文案。管理页 canvas-extensions.tsx 据此渲染"不可用"空态(含具体原因文案与重试按钮),而查询层 use-canvas-extensions.ts 设置 retry: false 且 query meta 中 disableToast: true,注释写明:"旧后端返回 404 是预期的能力探测结果,管理页负责渲染它,全局运行时保持安静"。三种状态(不支持 / 错误 / 空清单)在 UI 上是彼此独立分支,满足规范的要求。
六、前端运行时:键控激活、清单准入与错误边界
规范对前端运行时给出了七步流程。运行时以后端 ID、组织作用域与连接 revision 为键,防止某个后端的已启用 bundle 或缓存清单在切换/重连后出现在另一个后端上。
对每个已启用的安装项:
- 从所属后端获取已认证的 entrypoint 文本;
- 从 Blob URL 导入自包含 ESM bundle;
- 校验
activate及其宿主 API 版本; - 创建扩展作用域的注册表并调用
activate; - 只有 ID 已在清单中声明的注册才被准入("Admit registrations only when their IDs were declared in the manifest");
- 每个界面渲染在 Canvas 拥有的错误边界之内;
- 在禁用、卸载、更新或切换后端时,卸载所有界面、调用扩展 disposer、移除其注册表条目。
初始路由形状为 /extensions/{extension-name}/{declared-page-path};/extensions 本身是 Customize 清单页;所有路由经过 React Router,保证 VITE_BASE_PATH 继续生效。
canvas-extensions-runtime.tsx 是上述流程的实现主体,几个细节与规范严格对应:
- 激活签名(activation signature):以
JSON.stringify({ backendId, backendKind, connectionRevision, orgId, extensions: [...] })作为 effect 依赖,注释解释了原因——useActiveBackend可能在每次渲染合成新的backend对象、refetch 产生内容相同的新数组,若按引用做依赖会反复拆毁重建扩展。这正是规范"运行时键控于后端 ID、组织作用域、连接 revision"的代码化。 - 清单准入:
registerPage调用getDeclaredPage,在manifest.contributes.pages中查找同 ID 声明;未声明者直接抛错registered undeclared page;同时校验扩展名、贡献 ID、路径段均匹配/^[a-z0-9]+(?:-[a-z0-9]+)*$/,与规范"name 与贡献 ID 使用小写字母、数字、连字符"以及"绝对 kebab-case 路由"的规则一致;同一 contributionId 重复注册也会抛错。 - 路径规范化:后端声明的页面路径是绝对路由(如
/dashboard),前端归一化为相对形式用于 href 构造(buildCanvasExtensionPageHref生成/extensions/{name}/{path}),保证与 React Router 的extensions/:extensionName/*通配路由匹配。 - agentServer.request 委托:宿主对象的
agentServer.request直接绑定到CanvasExtensionsService.requestAgentServer(request, backend),即扩展发出的请求由前端服务层代理、携带当前后端凭据发出,对应规范"指向扩展所属后端的已认证请求辅助"。 - 清理即卸载:effect cleanup 中先清空
pages,再反序执行所有 disposer,单个 disposer 抛错仅console.error,其余继续——即规范"best-effort 清理"的实现。
路由侧,/extensions/:extensionName/* 由 canvas-extension-page.tsx 承接,其中 path 挂载上下文会把声明路径之下的剩余段作为 remainder 传给扩展(CanvasExtensionPageMountContext.path 的注释:"the remainder of the route below the page contribution's declared path"),使扩展页面自身支持嵌套路由。
七、本地验证:fixture、MSW 模拟与 Mock-LLM E2E
规范第 8 节(Verification)要求:每个切片都新增服务与运行时单元测试;路由页面切片另增一个 Mock-LLM 端到端用例,驱动生产构建走完 install → enable → page render → disable → uninstall;在 pinned agent-server 提供端点之前,用例通过 Playwright 路由拦截、从 src/fixtures/canvas-extensions/demo-page 提供 API 契约,端点就位后移除 stub、同步骤改跑真实后端。合并前必须运行 npm run lint、npm test、npm run build、npm run build:lib。
仓库中这些验证均已落地:
- fixture:src/fixtures/canvas-extensions/demo-page/ 提供自包含清单与 bundle(见第四节);
- MSW 开发模拟:src/mocks/canvas-extensions-handlers.ts 在浏览器内存中实现整套
/api/canvas-extensions端点,直接以?raw导入 demo fixture 的 manifest 与 bundle 来应答,安装状态持久化到 sessionStorage(键openhands-canvas-extension-dev-installation)。配套文档 docs/CANVAS_EXTENSIONS_TESTING.md 给出手动测试命令:
VITE_FRONTEND_PORT=3102 \
VITE_BACKEND_BASE_URL=http://127.0.0.1:8000 \
VITE_SESSION_API_KEY=canvas-extension-dev \
npm run dev:mock
文档说明:3102 端口避开常规本地栈使用的 3001 Vite 进程;后端 URL 只为给 Canvas 一个本地后端身份,MSW 会在浏览器内拦截扩展请求;mock 还覆盖了设置与服务信息探测端点,使该后端被标记为健康——因此 Agent Server 既不需要实现扩展端点,甚至无需运行。测试入口为 http://localhost:3102/extensions。该路径只面向前端开发,不测试 Agent Server 的安装、文件系统校验、持久化、认证或 Git 解析。
- Mock-LLM E2E:tests/e2e/mock-llm/canvas-extensions/mock-llm-canvas-extensions.spec.ts 驱动真实构建的 agent-canvas 栈(预构建静态前端、ingress、后端注册表、会话认证)走完完整生命周期:①从 source 路径安装 → 禁用态、无侧边栏项;②在信任确认之后启用 → 侧边栏项出现、贡献页面渲染在
/extensions/{name}/{path}(含嵌套 remainder 路径);③禁用 → 侧边栏项与页面被拆毁;④卸载 → 清单为空。其文件头注释还特别说明:这是唯一在真实浏览器中导入扩展 bundle 的测试(即canvas-extension-module-loader.ts的 Blob-URL ESM 导入路径),单元测试则注入 loader stub;由于 pinned agent-server 尚无/api/canvas-extensions端点,用例目前在浏览器层用 demo fixture 应答 API,"一旦 pin 包含端点,删除该 helper 并以绝对路径安装 fixture,UI 步骤保持不变"——与规范 Verification 一节的 stub→真实后端的切换计划完全一致。
八、交付计划与 v1 非目标
交付切片
规范的 Delivery plan 分为五个切片,仓库现状可对照判断其推进程度:
- Slice 1(契约与管理):落地规范与共享 TypeScript 类型(已见于 src/types/canvas-extension.ts);后端键控的服务与查询钩子(已见于 canvas-extensions-service.ts、use-canvas-extensions.ts、use-manage-canvas-extensions.ts);Customize → Extensions 页面,含不支持后端态、源码安装表单、来源/revision/贡献审查与显式启用控件(已见于 canvas-extensions.tsx 与 add-canvas-extension-modal.tsx);活跃后端返回 404 时全局运行时保持静默(已实现于 query meta 的
disableToast)。 - Slice 2(路由页面证明):版本化宿主 API、模块加载器、生命周期注册表、错误边界(已见于 canvas-extensions-runtime.tsx 与 canvas-extension-module-loader.ts);动态页面路由与左侧导航(见 sidebar-rail-body.tsx 对扩展侧边栏项的渲染);独立 fixture 扩展(已见于 demo-page);以及规范列出的验证清单:enable、热激活、导航、禁用清理、更新、后端切换、带会话密钥认证的 bundle 加载、
VITE_BASE_PATH。 - Slice 3(主题证明):定义无代码的主题贡献(严格 Canvas token schema)、后端校验主题清单、在 Settings 中展示已安装主题;主题选择在浏览器/用户作用域内,可用性跟随活跃后端,切离提供后端时干净回退。
- Slice 4(会话界面):用命名空间运行时 ID 替换封闭的会话 tab 联合类型、集中化持久化准入;先加扩展 tab/面板,再加宿主拥有的 header/footer/badge 插槽;在开放给作者前定义移动端行为、排序、冲突、扩展缺失回退与按会话的生命周期上下文。
- Slice 5(可视化器与作者闭环):增加 augment/replace 可视化器注册(显式事件匹配、优先级、内建回退);发布稳定的扩展 SDK 类型、打包器模板、校验命令与示例仓库;到那时才发布
/build-canvas-extension(含后端本地 vs 远端工作区指导、临时安装、手动启用说明、git 发布/更新流程)。
v1 明确不做的事
规范以非目标清单划界,这些"不做"与前述决策同等重要:
- 不做 iframe/worker 隔离或可执行的细粒度权限;
- 不在安装期运行任意生命周期脚本;
- 不允许 agent 自动启用;
- 不做市场排序或发布者签名;
- 首个纵向切片不包含会话 tab、插槽或可视化器替换;
- 不把
@openhands/extensions当作可安装运行时格式对待。
九、小结:契约如何贯穿三层
Canvas Extensions 的架构可以用一句话概括:清单声明界面,后端托管代码与信任,前端按版本化宿主 API 热激活。清单(canvas-extension.json,schema v1)声明"能贡献什么";Agent Server API(/api/canvas-extensions/*)负责"装在哪、装的是哪个 revision、谁有资格启用";前端运行时(runtime provider + 模块加载器 + 路由)负责"安全地、可撤销地执行"。三者之间靠两个独立的版本号解耦:schema_version 约束清单形状,apiVersion: "1" 约束宿主 API 形状——这使得宿主 API 可以独立于清单演进,也为 Slice 3–5 逐步开放主题、会话界面与可视化器保留了契约扩展空间。
对希望在本地先行体验该机制的开发者,最短路径是:按 docs/CANVAS_EXTENSIONS_TESTING.md 的命令启动 mock 前端,访问 /extensions,安装指向 src/fixtures/canvas-extensions/demo-page 的演示扩展,走一遍安装 → 启用 → 页面渲染 → 禁用 → 卸载;对实现细节有疑虑时,可直接对照本文引用的服务层、运行时与 loader 源码验证契约的落地情况。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00