@chamvi/ui

中文文档
0.8.0发布于 2026/11/09Apache-2.0TypeScriptES Module零依赖构建来源已验证近 30 天下载 3201

The chamvi dashboard: an agents overview, start and watch runs live, answer approvals, inspect agent state and schedules, served by @chamvi/http.

原始使用文档
文档目录9 节
  1. Installation
  2. Usage
  3. Views
  4. Sign-in
  5. Options
  6. Serving
  7. With @chamvi/app
  8. API
  9. License

@chamvi/ui

@chamvi/ui

The chamvi dashboard.
See what each agent does, start runs, watch them live, answer approvals,
look into agent state and schedules,
served by your own @chamvi/http app on the same origin.

npm version CI License


Table of Contents

Installation

npm install @chamvi/ui @chamvi/http @chamvi/core --save

ESM only, Node.js >=26.0.0. @chamvi/core and @chamvi/http are peer dependencies. The package ships a prebuilt Vue 3 app (dist/app); nothing of it runs on the server but a static file route.

Usage

uiRoutes() returns extra routes for createHttpApp({ routes }):

import { Engine, createMemoryStore } from '@chamvi/core';
import { createHttpApp, staticTokens } from '@chamvi/http';
import { uiRoutes } from '@chamvi/ui';

const engine = new Engine({
    store: createMemoryStore(),
    agents: [],
});

const admin = {
    value: process.env.ADMIN_TOKEN ?? 'admin-token-0123456789',
    id: 'admin',
    permissions: ['*'],
};

export const app = createHttpApp({
    engine,
    auth: [staticTokens({ tokens: [admin] })],
    // the dashboard at /ui: runs, approvals, agent state and schedules
    routes: uiRoutes(),
});

Open http://<host>/ui/ and sign in with a bearer token of the app.

Views

ViewShowsNeeds
AgentsA card per agent: channel chips (its subscriptions), running and waiting runs, next cron fire, 24 h activity, last run, budget, state collections; the landing pagerun:read
AgentBudget, state collections, channel chips, Start run (with an http.on() subscription), and the tabs Overview, Runs, State, Schedulesrun:read; agent:<name>:run to start; state:read for State
RunsEvery run, newest first, filtered by agent and status, with status and tokens; refreshes every 5 srun:read
RunHeader with budgets, the envelope (channel, subscription, address, payload) and the step timeline (llm, tool, wait), live over SSE with streamed text; cancelrun:read or agent:<name>:run; run:cancel to cancel
ApprovalsWaiting runs with the request's title and body, the tool and the channel it went out through; Approve or Deny with a reasonrun:read to list, agent:<name>:approve to answer
SchedulesCron subscriptions per agent with the next fire timerun:read

The 24 h figures are counted from the newest 100 runs (the API has no time filter) and read 100+ beyond.

A channel's approval message links an approval by run: /ui/approvals?run=<runId>&approval=<approvalId> (approval optional, then the run's current one). The link carries no token. Signed out, it goes through sign-in (token form or authup) and comes back to the same URL; signed in, the dashboard scrolls to that run's approval card, highlights and focuses it, and the answer goes through POST /runs/:id/approve as the signed-in principal. A run that no longer waits on that approval (answered, expired, moved on to another one) shows a notice linking the run; the link needs read access to the run (run:read or agent:<name>:run) besides agent:<name>:approve: without the approve grant the card shows read-only under a 403 notice, without read access only a 403 notice shows. The run page and the agent page link waiting runs the same way.

Sign-in

  • Token (default): paste a static bearer token (staticTokens() of @chamvi/http). GET /me checks it before it is kept, in sessionStorage of the tab only; a reload while the API is unreachable keeps it.
  • authup: uiRoutes({ auth: { authup: { url, clientId, realmId? } } }) adds "Continue with authup" (OIDC code flow with PKCE); its tokens live in the tab's sessionStorage too, never in cookies. The authup client needs <origin><uiBase>/login/callback as a redirect URI, e.g. https://chamvi.example.com/ui/login/callback. Pair it with the app's authup() authenticator. auth: { tokens: false } hides the token form.

An expired or revoked credential answers 401: the dashboard refreshes an authup session once, else returns to sign-in and back to the page it was on.

Options

OptionDefaultPurpose
basePath'/ui'The dashboard's path under the app's basePath, lower case (/api + /console serves /api/console/)
auth.tokenstrueOffer the token form
auth.authupnone{ url, clientId, realmId? } of an authup server
rootthe package's dist/appAnother build folder

Invalid options throw InvalidAgentDefinitionError of @chamvi/core. A missing build is reported on the first request (500, onError), not at construction, so the build may arrive later.

Serving

  • Every GET below basePath: a file of the build, else index.html for a path without an extension (client routes), else 404. index.html gets <base href="<uiBase>/"> and the config as a JSON block.
  • Hashed files under assets/ are cache-control: public, max-age=31536000, immutable, everything else no-cache.
  • Paths are decoded once and refused on .., ., empty segments, backslashes, NUL and double encoding: nothing outside the build is ever read.
  • Every answer carries Content-Security-Policy (default-src 'self', scripts only from the app, connect-src and form-action add the authup origin, frame-ancestors 'none'), referrer-policy: no-referrer (an approval link's ids never leave as a referrer), x-content-type-options: nosniff and x-frame-options: DENY.
  • The route is unauthenticated (the app holds no secret; every API call carries the signed-in bearer token) and skips the rate limiter.

Behind a proxy that mounts the app under a prefix, set the app's basePath; the dashboard follows it.

With @chamvi/app

uiModule() from @chamvi/ui/module contributes the dashboard route (/ui under CHAMVI_BASE_PATH) and reads CHAMVI_UI_AUTHUP_CLIENT_ID, CHAMVI_UI_AUTHUP_REALM_ID and AUTHUP_URL when it is called, unless auth is given. @chamvi/app is an optional peer; the main entry never imports it.

import { createApp } from '@chamvi/app';
import { uiModule } from '@chamvi/ui/module';

export default createApp({ agents, modules: [uiModule()] });

API

ExportKindPurpose
uiRoutesfunctionThe dashboard route for createHttpApp({ routes })
DEFAULT_UI_BASE_PATHconstant'/ui'
ASSET_CACHE_CONTROLconstant'public, max-age=31536000, immutable'
DOCUMENT_CACHE_CONTROLconstant'no-cache'
CONFIG_ELEMENT_IDconstant'chamvi-config', the id of the injected config block

Types: UiRoutesOptions, UiConfig, UiAuthupConfig.

@chamvi/ui/module: uiModule, UiModule, UI_MODULE_NAME, type UiModuleOptions.

License

Published under Apache License 2.0.

版本与发布记录

@chamvi/ui 共发布 15 个版本,首次发布于 2026/10/25;过去 12 个月发布了 15 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.8.0latest2026/11/09今天
0.7.32026/11/063 天前
0.7.22026/11/053 天前
0.7.12026/11/054 天前
0.7.02026/11/045 天前
0.6.12026/11/045 天前

关于 @chamvi/ui 的常见问题

@chamvi/ui 是什么?

The chamvi dashboard: an agents overview, start and watch runs live, answer approvals, inspect agent state and schedules, served by @chamvi/http.

如何安装 @chamvi/ui?

在项目目录运行 npm install @chamvi/ui,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@chamvi/core(^0.8.0)、@chamvi/http(^0.8.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@chamvi/ui 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@chamvi/ui 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@chamvi/ui 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=26.0.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@chamvi/ui 可以商用吗?

@chamvi/ui 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@chamvi/ui 的下载量有多少?

根据 npm 官方下载统计,@chamvi/ui 在 2026/10/10 – 2026/11/08 这 30 天内被下载 3,201 次,日均约 107 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@chamvi/ui 还在维护吗?

最新版本 0.8.0 发布于 2026/11/09(今天);至今共发布 15 个版本,其中过去 12 个月发布了 15 个;首次发布于 2026/10/25。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。