Merge remote-tracking branch 'origin/stack/agent-profiles-5-web-ui' into stack/agent-profiles-8-authoring

# Conflicts:
#	packages/client/connection/README.i18n.yaml
#	packages/client/connection/README.md
#	packages/client/connection/README.zh.md
This commit is contained in:
Yichen Jiang
2026-08-09 20:41:55 +08:00
1623 changed files with 15506 additions and 5450 deletions

View File

@@ -3,4 +3,4 @@
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write packages/client/test-runtime/README.md
README.md: 74da8fde7fd9cc3733d2d1ae03dd3d213e4d553e
README.zh.md: a86b9e469a5632886891628267002a14588afeaa
README.zh.md: 1df28f7b25c35333e91476e10480c22a728cdab3

View File

@@ -2,23 +2,23 @@
[English](README.md) | 中文
面向 client feature 测试的 jsdom slot 测试运行时:真实 Cordis `Context`、生产 `SlotsService` 与 web-react 渲染器,围绕带类型的 session/workspace 测试替身组装。feature 套件无需逐套件手搭机器即可测遍声明、注册、scope、store、inject、渲染、更新与销毁——且不存在任何生产逻辑的第二份实现。
面向客户端功能测试的 jsdom slot 测试运行时:真实 Cordis `Context`、生产 `SlotsService` 与 web-react 渲染器,围绕带类型的 session/workspace 测试替身组装。功能套件无需逐套件手搭机器即可测遍声明、注册、scope、store、inject、渲染、更新与销毁——且不存在任何生产逻辑的第二份实现。
替身实现的正是 feature 经 ctx 拿到的对外面(`TestSessions implements ISessions`、`TestWorkspaces implements IWorkspaces`;每个 fixture session 是 `FixtureSession implements SessionFace`),生产面一旦改形,测试台在编译期即断,而非静默漂移。provide bundle 材料化直接运行生产 `SessionProvideChannel`——与 `SessionsService` 共用同一份实现。fixture 灌入的是普通数据:列表行、会话快照(经 `updateSnapshot` 以 immer 补丁改写)、projection 值,以及按 `ISession` 取型的行为桩——spec 调用未打桩的动词时报错自明。带类型的 `provide()` 将已声明服务名的 fake 约束为该服务对外面的 `Partial` 子集。
替身实现的正是功能通过 ctx 获得的对外接口(`TestSessions implements ISessions`、`TestWorkspaces implements IWorkspaces`;每个 fixture session 是 `FixtureSession implements SessionFace`),生产面一旦改形,测试台在编译期即断,而非静默漂移。provide bundle 材料化直接运行生产 `SessionProvideChannel`——与 `SessionsService` 共用同一份实现。fixture 灌入的是普通数据:列表行、会话快照(经 `updateSnapshot` 以 immer 补丁改写)、projection 值,以及按 `ISession` 取型的行为桩——spec 调用未打桩的动词时报错自明。带类型的 `provide()` 将已声明服务名的 fake 约束为该服务对外面的 `Partial` 子集。
局部 DOM 快照:`declare(children)` 注册自动 frame,逐 key 的 `<div data-slot>` 包裹层即快照根;`renderSlot(key, owner)` 返回该 slot 的局部视图(container、限定范围的 Testing Library 查询、原位 `update(owner)`);注册的快照序列化器把 CSS-module 哈希类名折回语义名(`_frame_a1b2c3` → `frame`)保持 `.snap` 只含结构,并把 `<svg>` 内部折叠为 `data-content` 指纹。需要自定义页面 frame 的套件改用 `root.declare(children, Frame)`;`mount(plugin)` 在真实 fiber 上运行并对缺失服务先行报错;`dispose()` 沿单一轴拆除视图、feature fiber、已铸 scope 与持久化 store 状态。
不属于产品插件图(无 `dshClient`);feature 包仅以 `devDependencies` 依赖之。
## Model Experience
## 模型体验
无;本包是浏览器侧测试基础设施,无一物到达模型请求。
#### KV Cache effect
无;本包既不组装也不发送 provider 请求。
无;本包既不组装也不发送提供方请求。
## Known Limitations and Deferred Work
## 已知限制与延期工作
- **仅可经仓内源码别名消费。** spec 通过 tsconfig `paths` 解析到 `src`;构建产物 `lib/` 再导出 `@deepseek-ai/dsh-client-runtime/client`,而该 bundle 是无 Node ESM 导出的浏览器 loader 脚本,故 `lib/index.js` 在纯 Node 下不可导入。所有消费方都是仓内 Vitest 套件;不存在 Node 兼容的运行时入口。
- **会话快照是 fixture 数据,不是重放历史。** `updateSnapshot` 直写快照 store;wire 到快照的运算仍由 runtime 包自身测试与 replay e2e 把守。因此 fixture 可以表达生产投影永不产出的状态。

View File

@@ -40,7 +40,7 @@ export type { SessionBehaviorOverrides, SessionFixture, Stabilizer } from './fix
export { makeTranslate } from './translate.ts'
export { usePinnedBrowserLanguages } from './locale-env.ts'
/** Erased register face for the internal root call (the public declare seam holds the typing). */
/** Erased register face for the internal root call (the public declaration contract holds the typing). */
type ErasedRegister = (options: object, component: unknown) => () => void
/**
@@ -80,7 +80,7 @@ export interface FeatureHandle {
/**
* Owner-props cell behind the auto frame: one external store the frame
* subscribes to, so {@link SlotTestRuntime.renderSlot} and
* {@link SlotView.update} drive React through the standard uSES seam.
* {@link SlotView.update} drive React through the standard uSES boundary.
*/
class OwnerPropsCell {
private readonly owners = new Map<string, object>()
@@ -146,7 +146,7 @@ export class TestRoot {
): Promise<void> {
await this.stabilize(() => {
// Erased hop (same pattern as SlotsService's own implementation arm);
// the declare signature above is the typed seam.
// the declaration signature above is the typed contract.
this.disposeEntry = (this.slots.register as unknown as ErasedRegister)({ name: 'root', children }, frame)
})
}
@@ -267,7 +267,7 @@ export class SlotTestRuntime {
/**
* Render the root slot tree through the ctx-level entry (the shell's own
* seam): `ctx.slots.renderSlot('root', {})` under Testing Library.
* entry point): `ctx.slots.renderSlot('root', {})` under Testing Library.
* @returns the Testing Library view.
*/
renderRoot(): RenderResult {

View File

@@ -368,7 +368,7 @@ export class TestSessions implements ISessions {
}
/**
* Read the session scope tag off a context (service-method seam mirror).
* Read the session scope tag off a context (service-method boundary mirror).
* @param ctx - any client context.
* @returns the session id, or undefined on root contexts.
*/