-
+
{t('apesProfileCurrent')}
@@ -294,13 +224,13 @@ function ApesAppsView(props: TabComponentProps) {
}
/**
- * The four apes:* tab descriptors (order 900-903: tasks/agents/apps/profile),
+ * The three apes:* tab descriptors (C6: `apes:tasks` removed — overlaps the
+ * official DSH session tree). Order 901-903: agents/apps/profile. Each is
* already shaped as `TabDescriptor` (component + single-instance + icon
* element + i18n title function) so `registerApesTabs` can hand them straight
* to `service.registerTab`. Information-layer tabs are single-instance.
*/
export const apesTabs: TabDescriptor[] = [
- { id: 'apes:tasks', title: () => t('apesTasksTitle'), icon: , order: 900, single: true, component: ApesTasksView },
{ id: 'apes:agents', title: () => t('apesAgentsTitle'), icon: , order: 901, single: true, component: ApesAgentsView },
{ id: 'apes:apps', title: () => t('apesAppsTitle'), icon: , order: 902, single: true, component: ApesAppsView },
{ id: 'apes:profile', title: () => t('apesProfileTitle'), icon: , order: 903, single: true, component: ApesProfileView },
diff --git a/tests/apes-tabs.spec.ts b/tests/apes-tabs.spec.ts
index 208b1dc..0a36f07 100644
--- a/tests/apes-tabs.spec.ts
+++ b/tests/apes-tabs.spec.ts
@@ -1,10 +1,12 @@
/**
- * apes:* tab registration tests (Phase 1/1b): the fork registers its four
- * information-layer tabs (tasks / agents / apps / profile) through the same
- * BetterSidebarService the upstream builtins use (dogfood). The spec pins
- * the registration contract (id / single / order / component presence) and
- * the isolated i18n contract (the apes namespace resolves zh vs en through
- * the attached locale service, and every apesZh key has an apesEn entry).
+ * apes:* tab registration tests (Phase 1/1b, C6: 3 tabs). The fork registers
+ * its three information-layer tabs (agents / apps / profile) through the same
+ * BetterSidebarService the upstream builtins use (dogfood). `apes:tasks` was
+ * removed in C6 — it overlaps the official DSH session tree in the native
+ * sidebar. The spec pins the registration contract (id / single / order /
+ * component presence) and the isolated i18n contract (the apes namespace
+ * resolves zh vs en through the attached locale service, and every apesZh
+ * key has an apesEn entry).
*
* Runs in the node vitest environment like builtins.spec.ts — no DOM, no
* real DSH host (a live cordis scratch mount is Phase 2+).
@@ -31,11 +33,11 @@ function setup(): {
}
describe('apes:* tab registrations', () => {
- it('registers the 4 apes tabs with the apes: namespace', () => {
+ it('registers the 3 apes tabs with the apes: namespace', () => {
const { service, dispose } = setup()
try {
expect(service.getTabs().map(t => t.id).sort()).toEqual(
- ['apes:agents', 'apes:apps', 'apes:profile', 'apes:tasks'],
+ ['apes:agents', 'apes:apps', 'apes:profile'],
)
} finally {
dispose()
@@ -45,7 +47,7 @@ describe('apes:* tab registrations', () => {
it('every apes tab is single-instance, visible, and component-carrying', () => {
const { service, dispose } = setup()
try {
- for (const id of ['apes:tasks', 'apes:agents', 'apes:apps', 'apes:profile']) {
+ for (const id of ['apes:agents', 'apes:apps', 'apes:profile']) {
const tab = service.getTab(id)
expect(tab, `${id} registered`).toBeDefined()
expect(tab?.single, `${id} single`).toBe(true)
@@ -62,17 +64,14 @@ describe('apes:* tab registrations', () => {
const { service, dispose } = setup()
try {
const orders = {
- tasks: service.getTab('apes:tasks')?.order,
agents: service.getTab('apes:agents')?.order,
apps: service.getTab('apes:apps')?.order,
profile: service.getTab('apes:profile')?.order,
}
- expect(orders.tasks).toBeGreaterThanOrEqual(900)
expect(orders.agents).toBeGreaterThanOrEqual(900)
expect(orders.apps).toBeGreaterThanOrEqual(900)
expect(orders.profile).toBeGreaterThanOrEqual(900)
- // Strictly ordered: tasks < agents < apps < profile.
- expect(orders.tasks!).toBeLessThan(orders.agents!)
+ // Strictly ordered: agents < apps < profile.
expect(orders.agents!).toBeLessThan(orders.apps!)
expect(orders.apps!).toBeLessThan(orders.profile!)
} finally {
@@ -84,7 +83,7 @@ describe('apes:* tab registrations', () => {
const store = createSidebarStore()
const service = createBetterSidebarService(store)
const dispose = registerApesTabs({} as Context, service)
- expect(service.getTabs()).toHaveLength(4)
+ expect(service.getTabs()).toHaveLength(3)
dispose()
expect(service.getTabs()).toHaveLength(0)
})
@@ -102,30 +101,20 @@ describe('apes i18n contract', () => {
it('resolves zh when the DSH preference is zh', () => {
attachApesLocale({ getSnapshot: () => ({ active: 'zh-CN' }) })
- expect(t('apesTasks')).toBe('任务')
- expect(t('apesAgents')).toBe('智能体')
- expect(t('apesApps')).toBe('应用')
- expect(t('apesProfile')).toBe('画像')
+ expect(t('apesAgentsTitle')).toBe('智能体')
+ expect(t('apesAppsTitle')).toBe('应用')
+ expect(t('apesProfileTitle')).toBe('画像')
})
it('resolves en when the DSH preference is en', () => {
attachApesLocale({ getSnapshot: () => ({ active: 'en' }) })
- expect(t('apesTasks')).toBe('Tasks')
- expect(t('apesAgents')).toBe('Agents')
- expect(t('apesApps')).toBe('Apps')
- expect(t('apesProfile')).toBe('Profile')
+ expect(t('apesAgentsTitle')).toBe('Agents')
+ expect(t('apesAppsTitle')).toBe('Apps')
+ expect(t('apesProfileTitle')).toBe('Profile')
})
it('falls back to zh when no locale service is attached', () => {
attachApesLocale(undefined)
- expect(t('apesTasks')).toBe('任务')
- })
-
- it('supports {param} interpolation', () => {
- attachApesLocale({ getSnapshot: () => ({ active: 'zh' }) })
- // The duration strings carry {seconds} params — assert the mechanism via
- // a real key (the t() contract, not a synthetic one).
- expect(t('apesDurationSeconds', { seconds: 5 })).toBe('5 秒')
- expect(t('apesDurationMinutes', { minutes: 2, seconds: 7 })).toBe('2 分 7 秒')
+ expect(t('apesAgentsTitle')).toBe('智能体')
})
})
diff --git a/tests/sidechat-seed-validation.spec.ts b/tests/sidechat-seed-validation.spec.ts
index 9407d1f..b7f1f11 100644
--- a/tests/sidechat-seed-validation.spec.ts
+++ b/tests/sidechat-seed-validation.spec.ts
@@ -56,7 +56,7 @@ function parentLog(): SidebarSessionEvent[] {
ev('user/message', 0, userMessage('first question')),
ev('turn/start', 1, { turn: 1 }),
ev('step/start', 2, { turn: 1, step: 1 }),
- ev('assistant/message', 3, { turn: 1, step: 1, message: assistantMessage('first answer') }),
+ ev('assistant/message', 3, { turn: 1, step: 1, stream: [], message: assistantMessage('first answer') }),
ev('step/end', 4, { turn: 1, step: 1 }),
ev('turn/end', 5, { turn: 1, reason: { kind: 'completed' } }),
ev('user/message', 6, userMessage('pending question')),