Every side-card switch was dead: settings.update returned OK and cordis.patch.yml was written, yet the running plugin never saw the new value and nothing reported an error. Root cause: the plugin declared Config with the plain npm `schemastery` (3.18.0), which has no volatile support. The host resolves plugin config via `runtime.Config['~standard'].validate()` — i.e. the plugin's OWN schemastery — so `meta.volatile` nodes were never wrapped in cosmokit volatile references. `cordis-plugin-loader`'s `_commitVolatile()` bails out as soon as `volatileEntries(fiber.config)` is empty, so every volatile-only edit was silently dropped: no in-place update, no plugin restart. Fix: import z from '@deepseek-ai/schemastery' (peer provided by the host at mount; pinned 3.18.4 as a devDependency for the dev tree), matching the repo's existing pnpm-workspace convention for @deepseek-ai/* peers. Verified: probe reports tabsIsVolatile=true and revision climbing 0->6 across six writes, each read-back matching the written value (previously the value was frozen and revision stuck at 1). Also in this change: - apes tab ids lose their colon (apes:tasks -> apesTasks, ...): the host's settings projection dropped map keys containing a colon. - sidebar prefs ns follows the profile entry id (`better-sidebar`). - subagent rows degrade to summary rows when the root catalog never hydrates. - docs/feedback-0.2.0-rc2-contract-gaps.md: four host contract gaps, gap 4 documenting the silent volatile-write drop above. Gates: typecheck 0, lint 0, build 0, test 131 files / 1385 passed.
49 lines
2.0 KiB
TypeScript
49 lines
2.0 KiB
TypeScript
/**
|
|
* apes:* information-layer tabs — the fork's own contribution on top of the
|
|
* upstream dsh-better-sidebar. Five tabs ship (tasks / agents / messages /
|
|
* apps / profile).
|
|
*
|
|
* History (C7): `apesTasks` was removed under the old C6 decision (it looked
|
|
* redundant next to the official DSH session tree). The `v2-revive` line
|
|
* restores it — the native tree is a *navigator* (one focused lineage), this
|
|
* panel is a *list* (every session, with an idle filter and a running badge),
|
|
* so the two answer different questions. `messages` is still an honest
|
|
* placeholder: no DSH message-stream feed exists yet.
|
|
*
|
|
* Isolated under `src/client/apes/` so the upstream `builtins/` tree stays
|
|
* untouched: cherry-picking upstream releases only has to keep the single
|
|
* `registerApesTabs(...)` call site in `index.tsx` (see D1 = module B).
|
|
*
|
|
* Every descriptor is registered through the same `BetterSidebarService`
|
|
* the builtins use (dogfood), so the apes tabs get the full sidebar
|
|
* lifecycle for free: + menu, enable/disable switches, badge pills,
|
|
* dedupe/focus, and HMR-safe disposal via the returned disposer.
|
|
*/
|
|
import type { Context } from '../../context-types.ts'
|
|
import type { BetterSidebarService } from '../service.ts'
|
|
import { apesTabs } from './tabs.tsx'
|
|
|
|
// Re-exported so index.tsx can register the apes dictionaries + attach the
|
|
// locale service in one import (keeps the apes module self-contained).
|
|
export { APES_LOCALE_NS, apesZh, apesEn, apesJa, attachApesLocale } from './locales.ts'
|
|
|
|
/**
|
|
* Register the apes:* tabs with the sidebar service. Returns a disposer that
|
|
* unregisters all of them (cordis auto-invokes it on fiber disposal, so HMR
|
|
* re-activation re-registers cleanly — same contract as registerBuiltins).
|
|
*/
|
|
export function registerApesTabs(
|
|
_ctx: Context,
|
|
service: BetterSidebarService,
|
|
): () => void {
|
|
const disposers: (() => void)[] = []
|
|
for (const tab of apesTabs) {
|
|
disposers.push(service.registerTab(tab))
|
|
}
|
|
return () => {
|
|
for (const d of disposers) {
|
|
try { d() } catch { /* already disposed */ }
|
|
}
|
|
}
|
|
}
|