跳到内容
Lenso
简体中文
Esc
导航打开⌘J预览
本页内容

为自己的 App 添加 Console

不依赖 Agent,启动 App 自有 Console 并贡献页面与授权服务。

这里的 Console 属于你构建的应用,可以完全没有 Agent。 面向 Agent 的 Console 工作台是另一条启动路径; npx @lenso/agent web 不会为你的应用添加 Console。

使用预编译开发包

使用匹配平台的 Console 开发包,将其 bin 加入 PATH。包内包含 Engine CLI、Bun、 已准入 native Host、内嵌 Shell、页面 compiler 和 SDK。应用作者无需 Cargo、rustc、 Node、pnpm 或 Console 源码;首次安装页面依赖仍需访问 registry。

当前开发包预发布 下载与平台匹配的压缩包和校验和。Apple silicon 使用 aarch64-apple-darwin,Linux x64 使用 x86_64-unknown-linux-gnu;校验并解压后,再把其中的工具加入 shell:

kit_tag=console-dev-b50d10087226-35466769287
target=aarch64-apple-darwin # Linux x64 改为 x86_64-unknown-linux-gnu
archive="console-development-host-$target.tar.gz"
base="https://github.com/LioRael/lenso-console/releases/download/$kit_tag"
curl -fLO "$base/$archive"
curl -fLO "$base/$archive.sha256"
shasum -a 256 -c "$archive.sha256"
tar -xzf "$archive"
export PATH="$PWD/development-host/bin:$PATH"
lenso app create my-app --console
lenso app dev --root my-app
# 停止开发进程后:
lenso app build --root my-app
lenso app start --from my-app/dist

打开 Host 打印的 HTTP 地址。开发模式完整重建并重启,不是 React Fast Refresh; 成功重启可能打印新端口。Scaffold 在 lenso.tomldevelopment_hostplugin_sources 中记录本地开发包位置,移动开发包时两处都需更新。

截至 2026-09-20,macOS ARM64 和 Linux x64 均已通过原生 CI 验收, 包括下载包解压后仅使用包内工具创建、构建、启动,以及真实 HTTP 服务的允许/拒绝检查。 Windows 不属于此 POSIX 开发包。Console SDK 随开发包提供,不代表存在独立 npm 发布。 新增原生 Rust Plugin 需要匹配的预编译 Host 或 Cargo 源码构建;源码身份、目标平台或 完整性不匹配会明确失败,不会静默回退到 Cargo 编译。

注册页面

生成的 app/orders/console/ 是页面贡献目录:

console/
├── page.tsx
├── layout.tsx           # 可选
├── loading.tsx          # 可选
├── error.tsx            # 可选
├── not-found.tsx        # 可选,仅根目录
├── services.ts          # 可选,仅服务端
└── orders/[id]/page.tsx
import type { PageProps } from '@lenso/console-sdk';

export default function Order({ params, navigation }: PageProps) {
  return <section>
    <h1>Order {String(params.id)}</h1>
    <a href={navigation.href([])}>Back to workspace</a>
  </section>;
}

页面使用 Shell 的 React 单例和普通 React hooks,无需另建 React root。 导航限制在当前 contribution 的 mount 中。SDK 还导出 definePageLayoutPropsErrorProps、Contribution 和 Workspace Service 的生成投影。

Convention 行为
[id] 字符串参数
[...path] 非空字符串数组
[[...path]] 可以为空的字符串数组
layout.tsx children 包裹后代
loading.tsx Suspense fallback
error.tsx 后代渲染错误边界,提供 errorreset
not-found.tsx 未匹配路由 fallback

静态路由优先于动态路由,catch-all 只能放末尾,歧义模式编译失败。 Layout 自身错误交给父级边界,导航重置错误状态。打包前用隔离的严格配置检查全部 TS/TSX 和组件签名;可用私有 console/package.json 声明前端依赖。 这些是具体支持的语义,不等于全部 Next.js 功能,也不承诺 SSR。

注册 owner service

可选 console/services.ts@lenso/console-sdk/server 导入并默认导出 defineServices(...)。每个 operation 必须提供 parseauthorizehandle, 授权成功后才执行 handler。开发包的 Orders 示例允许订单 42、拒绝其他 ID; 这是演示业务规则,不是生产身份认证。

import { defineServices, operation } from "@lenso/console-sdk/server";

export default defineServices({
  orders: {
    capabilityId: "example.orders.query@1",
    version: "1.0.0",
    operations: {
      read: operation({
        parse(value: unknown) {
          if (
            typeof value !== "object" ||
            value === null ||
            !("id" in value) ||
            typeof value.id !== "string"
          ) {
            throw new Error("An order ID is required");
          }
          return { id: value.id };
        },
        // Example business rule. Production authorization belongs here or in
        // the domain provider this adapter invokes, never in page navigation.
        authorize(_context, input) {
          return input.id === "42";
        },
        handle(input) {
          return { id: input.id, title: "Example order" };
        },
      }),
    },
  },
});

页面通过 SDK 调用已准入的 alias:

const order = await props.services.invoke<
  { id: string }, { id: string; title: string }
>('orders', 'read', { id: '42' }, { signal: props.signal });

生成的 service adapter 和 contribution 属于同一个 Plugin Instance。 Alias 通过既有 owner-scoped Plan 合约绑定,不是任意上游 URL。 Compiler 拒绝浏览器依赖图导入 server SDK 或 services 源码。 该 helper 当前支持 request;手写 Workspace Service provider 仍可使用 stream。

领域 Plugin 保留私有状态和最终授权。访问其他 Plugin 仍需显式生成的 Capability 依赖。 添加页面、路由或 alias 不授予业务权限,也不授予 Agent Tool 权限。

移除可选体验

Scaffold 用 plugins/lenso.console.web/default.toml 选择 Console。 在旁边增加空的 default.disabled,构建到新的输出目录,即可禁用 Console 及页面编译。 分别验证选中和禁用后的 App。Host 可以包含可用 factory,但不表示 App 已激活它们。

最后更新于 2026年9月19日

这个页面有帮助吗?