chore(gen1): 第一代版本封板 — DSH 2.0.17 兼容 + settings API 迁移 + React #130 修复
- peerDeps 升级到 0.2.0-rc.2 - settings API 迁移: register() → describe() + settings/document-updated - turnTail slots.register 补 id 字段 - EditorHost viewer.component undefined guard - 56/56 测试全绿, typecheck/build 通过 tag: v1.2.0-gen1
This commit is contained in:
@@ -483,7 +483,7 @@ export function EditorHost(props: {
|
||||
? <FenceErrorNotice store={store} onDisabled={() => { setReloadSeq(sequence => sequence + 1) }} />
|
||||
: <div className={css.editorError}>{load.message}</div>)}
|
||||
{!showEmpty && load.status === 'binary' && <BinaryDownload scope={scope} path={path} />}
|
||||
{!showEmpty && load.status === 'ready' && createElement(load.viewer.component, {
|
||||
{!showEmpty && load.status === 'ready' && load.viewer.component !== undefined && createElement(load.viewer.component, {
|
||||
ctx, store, scope, path, title,
|
||||
viewerId: load.viewer.id,
|
||||
content: load.content,
|
||||
|
||||
@@ -112,6 +112,7 @@ export function SidebarProducedFiles(props: {
|
||||
export function registerTurnTailInterception(ctx: Context, store: SidebarStore): () => void {
|
||||
return ctx.slots.inject('conversation.chat.turnTail', () => ctx.slots.register({
|
||||
name: 'conversation.chat.turnTail',
|
||||
id: 'dsh-apes-sidebar:turn-tail',
|
||||
// Decline the takeover while the editor tab type is disabled in the side
|
||||
// card settings: the produced-files row falls back to the default
|
||||
// deliverables behavior instead of offering chips that cannot open. Also
|
||||
|
||||
+28
-13
@@ -799,22 +799,28 @@ export function apply(ctx: Context, config?: SidebarConfig): void {
|
||||
}
|
||||
}
|
||||
ctx.inject(['settings'], (sctx) => {
|
||||
// DSH 0.1.2-alpha.2 validates namespaces at compile time
|
||||
// (SettingsNamespaceInput); the 'dsh-apes-sidebar' literal passes, so the
|
||||
// runtime helper this used to call (settingsNamespace) is gone upstream.
|
||||
const ns = SIDEBAR_PREFS_NS
|
||||
// The structural settings mirror types `schema` as unknown, so the
|
||||
// generic is not inferred here; the real service resolves it from the
|
||||
// schemastery schema (PrefsSchema) — narrow the owner scope explicitly.
|
||||
const scope = sctx.settings.register(ns, PrefsSchema) as {
|
||||
get(): SidebarPrefs
|
||||
watch(callback: (next: SidebarPrefs, prev: SidebarPrefs) => void): () => void
|
||||
// 0.2.0-rc.2: `settings.register()` is gone. The plugin's Config schema
|
||||
// (config.ts → Config) is auto-registered by the loader under ns =
|
||||
// entry.options.id (= package name). We read it through describe() and
|
||||
// watch for changes via the `settings/document-updated` event.
|
||||
const readPrefs = (): SidebarPrefs => {
|
||||
const descriptor = sctx.settings.describe({ redactSecrets: true }).find(c => c.ns === ns)
|
||||
const raw = descriptor?.value as Record<string, unknown> | undefined
|
||||
return raw !== null && typeof raw === 'object'
|
||||
? raw as unknown as SidebarPrefs
|
||||
: SIDEBAR_PREFS_DEFAULTS
|
||||
}
|
||||
const scope = { get: readPrefs }
|
||||
const viewOf = (): { value?: unknown; revision?: number } => {
|
||||
const descriptor = sctx.settings.describe({ redactSecrets: true }).find(candidate => candidate.ns === ns)
|
||||
return descriptor === undefined
|
||||
? { value: undefined, revision: undefined }
|
||||
: { value: descriptor.value, revision: descriptor.revision }
|
||||
if (descriptor === undefined) return { value: undefined, revision: undefined }
|
||||
// 0.2.0-rc.2: describe() may return value=undefined for a namespace that
|
||||
// has no user-set document yet (the Config schema defaults are applied
|
||||
// lazily). Fall back to the schema defaults so the client always gets a
|
||||
// well-formed object (React #130 guard).
|
||||
const value = descriptor.value ?? SIDEBAR_PREFS_DEFAULTS
|
||||
return { value, revision: descriptor.revision }
|
||||
}
|
||||
// Mutual exclusion with the dsh-web-ui family right panel: the aionui
|
||||
// panel's provider choice (`aionui-panel.rightPanel`) is the authority.
|
||||
@@ -869,7 +875,12 @@ export function apply(ctx: Context, config?: SidebarConfig): void {
|
||||
// ONE watch subscription drives both gates: settings commits re-evaluate
|
||||
// the terminal tools AND the open tool together (each gate is idempotent
|
||||
// and owns its own disposer).
|
||||
scope.watch(() => { syncToolsGate(scope); syncOpenToolsGate() })
|
||||
// 0.2.0-rc.2: `scope.watch()` is gone; use the `settings/document-updated`
|
||||
// event emitted on the plugin context (ownerContext) by the SettingsForms
|
||||
// service on every describe() call that detects a raw-value change.
|
||||
ctx.on('settings/document-updated', (changedNs: string) => {
|
||||
if (changedNs === ns) { syncToolsGate(scope); syncOpenToolsGate() }
|
||||
})
|
||||
})
|
||||
|
||||
// ── JSON API ────────────────────────────────────────────────────────────
|
||||
@@ -880,6 +891,10 @@ export function apply(ctx: Context, config?: SidebarConfig): void {
|
||||
// effect releases the listener on fiber disposal.
|
||||
const assistantLive = createAssistantLiveBuffer(ctx)
|
||||
ctx.effect(() => () => { assistantLive.dispose() }, 'dsh-apes-sidebar: live assistant stream buffer')
|
||||
// NOTE: `buildApi` must come AFTER `ctx.inject(['settings'], ...)` so the
|
||||
// closure captures the settingsFace value set inside the inject callback.
|
||||
// 0.2.0-rc.2 removed `settings.register()`; settingsFace is now populated
|
||||
// synchronously during inject, not lazily at first call.
|
||||
const api = buildApi(ctx, ptyManager, agentPtyRegistry, resolved, terminalShell, () => settingsFace, assistantLive)
|
||||
ctx.effect(() => ctx.webServer.register({
|
||||
kind: 'prefix',
|
||||
|
||||
Reference in New Issue
Block a user