fix: coverage
This commit is contained in:
@@ -1,6 +1,10 @@
|
|||||||
import type { SessionEvent } from '@deepseek-ai/dsh-session/types'
|
import type { SessionEvent } from '@deepseek-ai/dsh-session/types'
|
||||||
import type { ToolEventView } from '@deepseek-ai/dsh-client-connection/client'
|
import type { ToolEventView } from '@deepseek-ai/dsh-client-connection/client'
|
||||||
|
|
||||||
|
/* oxlint-disable typescript/no-duplicate-type-constituents, typescript/no-redundant-type-constituents --
|
||||||
|
* The unaugmented declaration-merge maps intentionally resolve to never in the Runtime program;
|
||||||
|
* installed business packages supply their concrete keys in consuming Client programs. */
|
||||||
|
|
||||||
/** One raw log event plus its optional envelope-level presentation view. */
|
/** One raw log event plus its optional envelope-level presentation view. */
|
||||||
export interface ConversationEventInput {
|
export interface ConversationEventInput {
|
||||||
readonly event: SessionEvent
|
readonly event: SessionEvent
|
||||||
|
|||||||
@@ -712,9 +712,8 @@ export class ConversationNodeAssembler {
|
|||||||
context: InternalContext,
|
context: InternalContext,
|
||||||
scope: ConversationLocationDataScope,
|
scope: ConversationLocationDataScope,
|
||||||
): ConversationLocationData | null {
|
): ConversationLocationData | null {
|
||||||
const build = context.definition.buildLocationData
|
if (context.definition.buildLocationData === undefined) return null
|
||||||
if (build === undefined) return null
|
const data = context.definition.buildLocationData(contextSnapshot(context), scope)
|
||||||
const data = build(contextSnapshot(context), scope)
|
|
||||||
if (data === null) return null
|
if (data === null) return null
|
||||||
if (data.kind !== scope) {
|
if (data.kind !== scope) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export interface ConversationLocationDataChange {
|
|||||||
class MutableLocationDataStore {
|
class MutableLocationDataStore {
|
||||||
private entries = new Map<string, OwnedLocationData>()
|
private entries = new Map<string, OwnedLocationData>()
|
||||||
|
|
||||||
get<Key extends string>(key: Key): unknown {
|
get(key: string): unknown {
|
||||||
return this.entries.get(key)?.value
|
return this.entries.get(key)?.value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|||||||
'trt.panel': { kind: 'single'; scope: 'root'; owner: { label?: string } }
|
'trt.panel': { kind: 'single'; scope: 'root'; owner: { label?: string } }
|
||||||
'trt.chat': { kind: 'single'; scope: 'session' }
|
'trt.chat': { kind: 'single'; scope: 'session' }
|
||||||
'trt.rows': { kind: 'list'; scope: 'root' }
|
'trt.rows': { kind: 'list'; scope: 'root' }
|
||||||
|
'trt.rows.hole': { kind: 'single'; scope: 'root' }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -419,7 +420,7 @@ describe('feature mount and disposal', () => {
|
|||||||
await feature.dispose()
|
await feature.dispose()
|
||||||
await feature.dispose() // idempotent
|
await feature.dispose() // idempotent
|
||||||
expect(runtime.slots.entries('trt.rows')).toHaveLength(0)
|
expect(runtime.slots.entries('trt.rows')).toHaveLength(0)
|
||||||
expect(runtime.slots.spec('trt.rows.hole' as never)).toBeUndefined()
|
expect(runtime.slots.spec('trt.rows.hole')).toBeUndefined()
|
||||||
expect(runtime.ctx.get('feature-service')).toBeUndefined()
|
expect(runtime.ctx.get('feature-service')).toBeUndefined()
|
||||||
expect(view.queryByTestId('row')).toBeNull()
|
expect(view.queryByTestId('row')).toBeNull()
|
||||||
await runtime.dispose()
|
await runtime.dispose()
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import type {
|
|||||||
export interface ChatNodeDataMap {}
|
export interface ChatNodeDataMap {}
|
||||||
|
|
||||||
/** Renderer kinds contributed by the currently installed Chat business modules. */
|
/** Renderer kinds contributed by the currently installed Chat business modules. */
|
||||||
export type ChatNodeKind = keyof ChatNodeDataMap & string
|
export type ChatNodeKind = Extract<keyof ChatNodeDataMap, string>
|
||||||
|
|
||||||
/** Final Chat Node narrowed to one registered renderer kind and payload. */
|
/** Final Chat Node narrowed to one registered renderer kind and payload. */
|
||||||
export type ChatNode<Kind extends ChatNodeKind = ChatNodeKind> = {
|
export type ChatNode<Kind extends ChatNodeKind = ChatNodeKind> = {
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ export interface TurnTailOwnerProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Hook constrained to business data published on the current Chat Node's Turn. */
|
/** Hook constrained to business data published on the current Chat Node's Turn. */
|
||||||
export type UseChatNodeTurnData = <Key extends keyof ConversationTurnDataMap & string>(
|
export type UseChatNodeTurnData = <Key extends Extract<keyof ConversationTurnDataMap, string>>(
|
||||||
key: Key,
|
key: Key,
|
||||||
) => Readonly<ConversationTurnDataMap[Key]> | undefined
|
) => Readonly<ConversationTurnDataMap[Key]> | undefined
|
||||||
|
|
||||||
|
|||||||
@@ -78,13 +78,16 @@ class FixtureLocationIndex implements ChatLocationNodeIndex {
|
|||||||
class FixtureTurnDataStore implements ConversationLocationDataStore<ConversationTurnDataMap> {
|
class FixtureTurnDataStore implements ConversationLocationDataStore<ConversationTurnDataMap> {
|
||||||
private readonly values = new Map<string, unknown>()
|
private readonly values = new Map<string, unknown>()
|
||||||
|
|
||||||
get<Key extends keyof ConversationTurnDataMap & string>(
|
get<Key extends Extract<keyof ConversationTurnDataMap, string>>(
|
||||||
key: Key,
|
key: Key,
|
||||||
): Readonly<ConversationTurnDataMap[Key]> | undefined {
|
): Readonly<ConversationTurnDataMap[Key]> | undefined {
|
||||||
return this.values.get(key) as Readonly<ConversationTurnDataMap[Key]> | undefined
|
return this.values.get(key) as Readonly<ConversationTurnDataMap[Key]> | undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
set<Key extends keyof ConversationTurnDataMap & string>(key: Key, value: ConversationTurnDataMap[Key]): void {
|
set<Key extends Extract<keyof ConversationTurnDataMap, string>>(
|
||||||
|
key: Key,
|
||||||
|
value: ConversationTurnDataMap[Key],
|
||||||
|
): void {
|
||||||
this.values.set(key, value)
|
this.values.set(key, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -181,12 +181,14 @@ function makeHarness(init?: Partial<ConversationSnapshot>) {
|
|||||||
if (key !== 'conversation.chat.node') return opts?.fallback ?? null
|
if (key !== 'conversation.chat.node') return opts?.fallback ?? null
|
||||||
const nodeOwner = owner as RoutedChatNodeOwner
|
const nodeOwner = owner as RoutedChatNodeOwner
|
||||||
const nodeKey = opts?.hookContext as string | undefined
|
const nodeKey = opts?.hookContext as string | undefined
|
||||||
const useTurnData = ((dataKey: string) => props.useSession((snapshot) => {
|
const useTurnData = ((dataKey: string) => {
|
||||||
const location = nodeKey === undefined ? undefined : snapshot.chat.nodes.get(nodeKey)?.location
|
return props.useSession((snapshot) => {
|
||||||
return location?.kind === 'turn' || location?.kind === 'step'
|
const location = nodeKey === undefined ? undefined : snapshot.chat.nodes.get(nodeKey)?.location
|
||||||
? location.turn.data.get(dataKey as never)
|
return location?.kind === 'turn' || location?.kind === 'step'
|
||||||
: undefined
|
? location.turn.data.get(dataKey as never)
|
||||||
})) as UseChatNodeTurnData
|
: undefined
|
||||||
|
})
|
||||||
|
}) as UseChatNodeTurnData
|
||||||
const nodeProps = <Kind extends ChatNode['kind']>(): ChatNodeViewProps<Kind> => (
|
const nodeProps = <Kind extends ChatNode['kind']>(): ChatNodeViewProps<Kind> => (
|
||||||
{ ...props, ...nodeOwner, useTurnData } as unknown as ChatNodeViewProps<Kind>
|
{ ...props, ...nodeOwner, useTurnData } as unknown as ChatNodeViewProps<Kind>
|
||||||
)
|
)
|
||||||
@@ -226,7 +228,7 @@ function makeHarness(init?: Partial<ConversationSnapshot>) {
|
|||||||
case 'unknown':
|
case 'unknown':
|
||||||
return <UnknownNodeView {...nodeProps<'unknown'>()} />
|
return <UnknownNodeView {...nodeProps<'unknown'>()} />
|
||||||
case 'tool-call': {
|
case 'tool-call': {
|
||||||
const block = (nodeOwner.node.data as { readonly root: ToolCallBlock }).root
|
const block = nodeOwner.node.data.root
|
||||||
const toolName = 'kind' in block ? block.call?.name ?? '' : block.name
|
const toolName = 'kind' in block ? block.call?.name ?? '' : block.name
|
||||||
const tool = {
|
const tool = {
|
||||||
callId: block.callId,
|
callId: block.callId,
|
||||||
@@ -843,7 +845,7 @@ describe('ChatView', () => {
|
|||||||
mounted()
|
mounted()
|
||||||
return () => { unmounted() }
|
return () => { unmounted() }
|
||||||
}, [])
|
}, [])
|
||||||
const root = (node.data as { readonly root: ToolCallBlock }).root
|
const root = node.data.root
|
||||||
return (
|
return (
|
||||||
<div data-testid="stateful-tool" data-state={'kind' in root ? 'settled' : 'running'}>
|
<div data-testid="stateful-tool" data-state={'kind' in root ? 'settled' : 'running'}>
|
||||||
{root.callId}
|
{root.callId}
|
||||||
|
|||||||
@@ -34,13 +34,16 @@ afterEach(cleanup)
|
|||||||
class TestTurnDataStore implements ConversationLocationDataStore<ConversationTurnDataMap> {
|
class TestTurnDataStore implements ConversationLocationDataStore<ConversationTurnDataMap> {
|
||||||
private readonly values = new Map<string, unknown>()
|
private readonly values = new Map<string, unknown>()
|
||||||
|
|
||||||
get<Key extends keyof ConversationTurnDataMap & string>(
|
get<Key extends Extract<keyof ConversationTurnDataMap, string>>(
|
||||||
key: Key,
|
key: Key,
|
||||||
): Readonly<ConversationTurnDataMap[Key]> | undefined {
|
): Readonly<ConversationTurnDataMap[Key]> | undefined {
|
||||||
return this.values.get(key) as Readonly<ConversationTurnDataMap[Key]> | undefined
|
return this.values.get(key) as Readonly<ConversationTurnDataMap[Key]> | undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
set<Key extends keyof ConversationTurnDataMap & string>(key: Key, value: ConversationTurnDataMap[Key]): void {
|
set<Key extends Extract<keyof ConversationTurnDataMap, string>>(
|
||||||
|
key: Key,
|
||||||
|
value: ConversationTurnDataMap[Key],
|
||||||
|
): void {
|
||||||
this.values.set(key, value)
|
this.values.set(key, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,8 +44,8 @@ describe('ui-settings apply', () => {
|
|||||||
declare(before.slots)
|
declare(before.slots)
|
||||||
await before.ctx.plugin({ inject: [...inject], apply }).await()
|
await before.ctx.plugin({ inject: [...inject], apply }).await()
|
||||||
expect(before.slots.entries('sidebar.settings')[0]!.component).toBe(SettingsRoot)
|
expect(before.slots.entries('sidebar.settings')[0]!.component).toBe(SettingsRoot)
|
||||||
for (const [name, spec] of Object.entries(CHILD_SPECS)) {
|
for (const name of Object.keys(CHILD_SPECS) as Array<keyof typeof CHILD_SPECS>) {
|
||||||
expect(before.slots.spec(name as never)).toEqual(spec)
|
expect(before.slots.spec(name)).toEqual(CHILD_SPECS[name])
|
||||||
}
|
}
|
||||||
|
|
||||||
const after = await bench()
|
const after = await bench()
|
||||||
@@ -120,8 +120,8 @@ describe('ui-settings apply', () => {
|
|||||||
declare(b.slots)
|
declare(b.slots)
|
||||||
await Promise.resolve()
|
await Promise.resolve()
|
||||||
expect(b.slots.entries('sidebar.settings')[0]!.component).toBe(SettingsRoot)
|
expect(b.slots.entries('sidebar.settings')[0]!.component).toBe(SettingsRoot)
|
||||||
for (const [name, spec] of Object.entries(CHILD_SPECS)) {
|
for (const name of Object.keys(CHILD_SPECS) as Array<keyof typeof CHILD_SPECS>) {
|
||||||
expect(b.slots.spec(name as never)).toEqual(spec)
|
expect(b.slots.spec(name)).toEqual(CHILD_SPECS[name])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -132,8 +132,8 @@ describe('ui-settings apply', () => {
|
|||||||
await fiber.await()
|
await fiber.await()
|
||||||
await fiber.dispose()
|
await fiber.dispose()
|
||||||
expect(b.slots.entries('sidebar.settings')).toHaveLength(0)
|
expect(b.slots.entries('sidebar.settings')).toHaveLength(0)
|
||||||
for (const name of Object.keys(CHILD_SPECS)) {
|
for (const name of Object.keys(CHILD_SPECS) as Array<keyof typeof CHILD_SPECS>) {
|
||||||
expect(b.slots.spec(name as never)).toBeUndefined()
|
expect(b.slots.spec(name)).toBeUndefined()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -677,7 +677,10 @@ export class SlotCore {
|
|||||||
>(
|
>(
|
||||||
options: BaseOptions<K, EntryKey, D, H, M, N> & { inject?: undefined },
|
options: BaseOptions<K, EntryKey, D, H, M, N> & { inject?: undefined },
|
||||||
component: C
|
component: C
|
||||||
& SlotComponent<ComposedProps<K, NoInfer<EntryKey>, keyof NoInfer<D> & keyof SlotMap & string, HandleOf<NoInfer<H>>, object, NoInfer<M>, NoInfer<N>>>
|
& SlotComponent<ComposedProps<
|
||||||
|
K, NoInfer<EntryKey>, keyof NoInfer<D> & keyof SlotMap & string,
|
||||||
|
HandleOf<NoInfer<H>>, object, NoInfer<M>, NoInfer<N>
|
||||||
|
>>
|
||||||
& RendersCheck<C, D>,
|
& RendersCheck<C, D>,
|
||||||
): () => void
|
): () => void
|
||||||
/**
|
/**
|
||||||
@@ -702,7 +705,10 @@ export class SlotCore {
|
|||||||
>(
|
>(
|
||||||
options: BaseOptions<K, EntryKey, D, H, M, N> & { inject: (...args: InjectParams<K, H>) => I },
|
options: BaseOptions<K, EntryKey, D, H, M, N> & { inject: (...args: InjectParams<K, H>) => I },
|
||||||
component: C
|
component: C
|
||||||
& SlotComponent<ComposedProps<K, NoInfer<EntryKey>, keyof NoInfer<D> & keyof SlotMap & string, HandleOf<NoInfer<H>>, I, NoInfer<M>, NoInfer<N>>>
|
& SlotComponent<ComposedProps<
|
||||||
|
K, NoInfer<EntryKey>, keyof NoInfer<D> & keyof SlotMap & string,
|
||||||
|
HandleOf<NoInfer<H>>, I, NoInfer<M>, NoInfer<N>
|
||||||
|
>>
|
||||||
& RendersCheck<C, D>,
|
& RendersCheck<C, D>,
|
||||||
): () => void
|
): () => void
|
||||||
/* jscpd:ignore-end */
|
/* jscpd:ignore-end */
|
||||||
|
|||||||
@@ -274,7 +274,7 @@ export class WorkspaceAnalyzer {
|
|||||||
|
|
||||||
constructor(options: WorkspaceAnalyzerOptions) {
|
constructor(options: WorkspaceAnalyzerOptions) {
|
||||||
this.options = {
|
this.options = {
|
||||||
root: resolve(options.root),
|
root: realPath(options.root),
|
||||||
hostConfig: options.hostConfig ?? 'tsconfig.host.json',
|
hostConfig: options.hostConfig ?? 'tsconfig.host.json',
|
||||||
clientConfig: options.clientConfig ?? 'tsconfig.client.json',
|
clientConfig: options.clientConfig ?? 'tsconfig.client.json',
|
||||||
faces: options.faces ?? ['host', 'client'],
|
faces: options.faces ?? ['host', 'client'],
|
||||||
|
|||||||
Reference in New Issue
Block a user