fix(schedule): reconcile latest master contracts

This commit is contained in:
Tianyi Cui
2026-08-08 22:39:07 +08:00
parent 31e83f8ee7
commit 1f88085b53
35 changed files with 260 additions and 141 deletions

View File

@@ -3,9 +3,8 @@
// one, the durable event type and JSON sidecar remain inspectable in the flow.
import { useMemo, useState } from 'react'
import { IconSparkle16 } from '@deepseek-ai/dsh-client-ui-primitives'
import { DisclosureRow, IconSparkle16 } from '@deepseek-ai/dsh-client-ui-primitives'
import type { ChatViewSlotProps, EventRowOwnerProps } from '../contract/slots.ts'
import { DisclosureRow } from './DisclosureRow.tsx'
import css from './ContextInjectionRow.module.css'
/** Card props: the event owner payload plus the render site's locale seat. */

View File

@@ -63,8 +63,6 @@
"lib/index.js",
"lib/invariant.js",
"lib/client.js",
"lib/types/**/*.d.ts",
"lib/types/**/*.d.ts.map",
"src"
"lib/types/**/*.d.ts"
]
}

View File

@@ -7,7 +7,6 @@ interface ReminderPresentation {
scheduleId: string
prompt: string
occurrenceAt: string
deliveryMode: 'session-local'
}
/** Full Schedule row props: event owner/runtime share plus the locale seat. */
@@ -20,12 +19,10 @@ function reminderPresentation(value: unknown): ReminderPresentation | null {
if (typeof record['scheduleId'] !== 'string' || record['scheduleId'].length === 0) return null
if (typeof record['prompt'] !== 'string') return null
if (typeof record['occurrenceAt'] !== 'string' || record['occurrenceAt'].length === 0) return null
if (record['deliveryMode'] !== 'session-local') return null
return {
scheduleId: record['scheduleId'],
prompt: record['prompt'],
occurrenceAt: record['occurrenceAt'],
deliveryMode: record['deliveryMode'],
}
}

View File

@@ -15,11 +15,7 @@ declare module '@deepseek-ai/dsh-client-ui-slots' {
}
}
/**
* `conversation` is an ordering edge: its service is published after the chat
* entry has declared `conversation.chat.eventview`.
*/
export const inject = ['slots', 'conversation', 'locale']
export const inject = ['slots', 'locale']
/**
* Register bilingual copy and the Schedule reminder keyed row.
@@ -27,12 +23,12 @@ export const inject = ['slots', 'conversation', 'locale']
*/
export function apply(ctx: ClientContext): void {
ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'ui-schedule: dictionaries')
ctx.effect(
ctx.slots.inject(
'conversation.chat.eventview',
() => ctx.slots.register({
name: 'conversation.chat.eventview',
key: 'schedule/change',
locale: NS,
}, ReminderRow),
'ui-schedule: reminder row registration',
)
}

View File

@@ -1,6 +1,7 @@
import { Context } from 'cordis'
import { describe, expect, it } from 'vitest'
import { LocaleService } from '@deepseek-ai/dsh-client-locale/client'
import { SlotsService } from '@deepseek-ai/dsh-client-runtime/client'
import { apply, inject } from '../src/client/index.ts'
import { ReminderRow } from '../src/client/ReminderRow.tsx'
import { apply as nodeApply } from '../src/index.ts'
@@ -10,41 +11,55 @@ import {
name as invariantName,
} from '../src/invariant.ts'
interface CapturedEntry {
name: string
key?: string
locale?: string
component: unknown
}
function bench() {
async function bench(declareBeforeApply = true) {
const ctx = new Context()
let entry: CapturedEntry | undefined
ctx.provide('slots', {
register(options: Omit<CapturedEntry, 'component'>, component: unknown) {
entry = { ...options, component }
return () => { entry = undefined }
},
})
ctx.provide('conversation', {})
await ctx.plugin(SlotsService)
const slots = ctx.slots as unknown as {
register: (options: object, component: unknown) => () => void
}
const declareHost = () => slots.register({
name: 'root',
children: { 'conversation.chat.eventview': { kind: 'keyed', scope: 'session' } },
}, () => null)
const initialHost = declareBeforeApply ? declareHost() : undefined
ctx.provide('locale', new LocaleService(ctx))
const fiber = ctx.plugin({ inject: [...inject], apply })
return { ctx, fiber, entry: () => entry }
await fiber.await()
return {
ctx,
fiber,
declareHost,
initialHost,
entry: () => ctx.slots.entries('conversation.chat.eventview')[0],
}
}
describe('ui-schedule browser plugin', () => {
it('registers the keyed reminder renderer and unloads it with the fiber', async () => {
const b = bench()
await b.fiber.await()
expect(b.entry()).toEqual({
name: 'conversation.chat.eventview',
key: 'schedule/change',
locale: 'schedule',
component: ReminderRow,
})
const b = await bench()
expect(b.entry()?.options).toEqual({ key: 'schedule/change' })
expect(b.entry()?.locale).toBe('schedule')
expect(b.entry()?.component).toBe(ReminderRow)
await b.fiber.dispose()
expect(b.entry()).toBeUndefined()
b.initialHost?.()
})
it('follows delayed declaration, collapse, and redeclaration until contributor disposal', async () => {
const b = await bench(false)
expect(b.entry()).toBeUndefined()
const firstHost = b.declareHost()
expect(b.entry()?.component).toBe(ReminderRow)
firstHost()
expect(b.entry()).toBeUndefined()
const secondHost = b.declareHost()
expect(b.entry()?.component).toBe(ReminderRow)
await b.fiber.dispose()
expect(b.entry()).toBeUndefined()
secondHost()
})
})

View File

@@ -19,7 +19,6 @@ const invalidSidecars: ReadonlyArray<{ name: string; view: unknown }> = [
scheduleId: null,
prompt: 'not trusted',
occurrenceAt: '2026-08-05T08:00:00.000Z',
deliveryMode: 'session-local',
},
},
{
@@ -28,7 +27,6 @@ const invalidSidecars: ReadonlyArray<{ name: string; view: unknown }> = [
scheduleId: '',
prompt: 'not trusted',
occurrenceAt: '2026-08-05T08:00:00.000Z',
deliveryMode: 'session-local',
},
},
{
@@ -37,7 +35,6 @@ const invalidSidecars: ReadonlyArray<{ name: string; view: unknown }> = [
scheduleId: 'schedule-7',
prompt: 7,
occurrenceAt: '2026-08-05T08:00:00.000Z',
deliveryMode: 'session-local',
},
},
{
@@ -46,7 +43,6 @@ const invalidSidecars: ReadonlyArray<{ name: string; view: unknown }> = [
scheduleId: 'schedule-7',
prompt: 'not trusted',
occurrenceAt: 7,
deliveryMode: 'session-local',
},
},
{
@@ -55,16 +51,6 @@ const invalidSidecars: ReadonlyArray<{ name: string; view: unknown }> = [
scheduleId: 'schedule-7',
prompt: 'not trusted',
occurrenceAt: '',
deliveryMode: 'session-local',
},
},
{
name: 'unsupported delivery mode',
view: {
scheduleId: 'schedule-7',
prompt: 'not trusted',
occurrenceAt: '2026-08-05T08:00:00.000Z',
deliveryMode: 'external',
},
},
]
@@ -88,7 +74,6 @@ describe('ReminderRow', () => {
scheduleId: 'schedule-7',
prompt: 'Check the deploy',
occurrenceAt: '2026-08-05T08:00:00.000Z',
deliveryMode: 'session-local',
})} />)
expect(screen.getByRole('note')).toBeTruthy()