style: fix lint across client packages

eslint --fix autofixes plus manual repairs: max-len line splits
(fake-api handlers, notifier/slots JSDoc, spec signatures), charAt over
non-null-asserted indexing in slash detect/menu cores, Array.from for
code-point capping, typeof assertions for unbound-method in specs,
generic getByRole for the send-button cast, effect disposer void-wrap in
command register, and dropped unused type imports.
This commit is contained in:
imccyu
2026-07-27 04:08:02 +08:00
parent a27be43ac1
commit f6396f2573
35 changed files with 122 additions and 89 deletions
@@ -89,6 +89,7 @@ async function bench() {
binding: (id: SessionId) => ({ sessionId: id, session: sessionFake, ctx: mint(id) }),
scope: (id: SessionId) => mint(id),
provideInfo: () => undefined,
maybeProvideInfo: () => ({ hooks: {}, props: {} }),
provide: (descriptor: TestProvider) => { providers.push(descriptor); return () => {} },
scopeOf,
sessionOf: (actx: Context) => (scopeOf(actx) === undefined ? undefined : sessionFake),
@@ -37,6 +37,7 @@ async function bench() {
binding: vi.fn(),
scope: () => undefined,
provideInfo: () => undefined,
maybeProvideInfo: () => ({ hooks: {}, props: {} }),
provide: vi.fn(() => () => {}),
create: vi.fn(),
open: vi.fn(),
@@ -94,15 +95,17 @@ describe('apply wiring', () => {
const b = await bench()
await b.fiber.await()
const conversation = renderEntryOf(b.slots, 'conversation')
const conversationSession = renderEntryOf(b.slots, 'conversation.session')
const chatView = renderEntryOf(b.slots, 'conversation.view')
const details = renderEntryOf(b.slots, 'details')
expect(conversation?.inject).toBeTypeOf('function')
expect(chatView?.inject).toBeTypeOf('function')
expect(details?.inject).toBeTypeOf('function')
// The shared handle: one apply-built store value on ALL session entries.
expect(conversation?.store).toBeDefined()
expect(details?.store).toBe(conversation?.store)
expect(chatView?.store).toBe(conversation?.store)
// The shared handle: one apply-built store value on ALL session entries
// (the session-maybe 'conversation' shell carries no store by design).
expect(conversationSession?.store).toBeDefined()
expect(details?.store).toBe(conversationSession?.store)
expect(chatView?.store).toBe(conversationSession?.store)
// The hero workspace picker hole rides the conversation entry's children
// declaration (the empty-state occupant is gone).
expect(b.slots.spec('conversation.hero.workspace')).toEqual({ kind: 'single', scope: 'root' })
@@ -94,8 +94,8 @@ async function bench(snapshot: ConversationSnapshot) {
: undefined),
scope: () => ({ get: () => scoped }),
scopeOf: () => SID,
provide: (provider: (binding: unknown) => { hooks?: Record<string, unknown>; props?: Record<string, unknown> }) => {
const contribution = provider(sessionsFake.binding(SID))
provide: (descriptor: { resolve: (binding: unknown) => { hooks?: Record<string, unknown>; props?: Record<string, unknown> } }) => {
const contribution = descriptor.resolve(sessionsFake.binding(SID))
Object.assign(provided.hooks, contribution.hooks ?? {})
Object.assign(provided.props, contribution.props ?? {})
return () => {}
@@ -103,6 +103,9 @@ async function bench(snapshot: ConversationSnapshot) {
provideInfo: (id: string) => (id === SID
? { sessionId: SID, hooks: { session, ...provided.hooks }, props: provided.props }
: undefined),
maybeProvideInfo: (id: string | undefined) => (id === SID
? { sessionId: SID, hooks: { session, ...provided.hooks }, props: provided.props }
: { hooks: provided.hooks, props: provided.props }),
create: vi.fn(),
open: vi.fn(),
}
@@ -107,7 +107,10 @@ async function bench(nodes: ToolResultNode[]) {
}
return info
},
provide: (fn: (typeof providers)[number]) => { providers.push(fn); return () => {} },
maybeProvideInfo(id: string | undefined) {
return (id === undefined ? undefined : this.provideInfo(id)) ?? { hooks: {}, props: {} }
},
provide: (d: { resolve: (typeof providers)[number] }) => { providers.push(d.resolve); return () => {} },
scopeOf: () => SID,
create: vi.fn(),
open: vi.fn(),
@@ -227,6 +230,7 @@ describe('registrant load-order seam', () => {
binding: () => undefined,
scope: () => undefined,
provideInfo: () => undefined,
maybeProvideInfo: () => ({ hooks: {}, props: {} }),
provide: () => () => {},
create: vi.fn(),
open: vi.fn(),
@@ -23,6 +23,7 @@ function bench(): Bench {
ids: [], byId: {}, current: undefined, phase: 'ready',
}),
provideInfo: () => undefined,
maybeProvideInfo: () => ({ hooks: {}, props: {} }),
provide: () => () => {},
})
ctx.provide('workspaces', {
@@ -42,16 +43,19 @@ function bench(): Bench {
name: 'root',
children: {
'conversation': { kind: 'single', scope: 'session-maybe' },
'conversation.session': { kind: 'single', scope: 'session' },
'details': { kind: 'single', scope: 'session' },
},
}, (_p: { renderSlot?: unknown }) => null)
slots.register({ name: 'conversation', store: chat }, () => null)
// apply.ts mounts the shared chat handle only under session-scope slots
// (the session-maybe 'conversation' shell carries no store).
slots.register({ name: 'conversation.session', store: chat }, () => null)
slots.register({ name: 'details', store: chat }, () => null)
return { slots, chat }
}
/** Resolve the store instance the renderer would hand a slot's component for a session. */
function storeFor(b: Bench, slot: 'conversation' | 'details', sessionId: SessionId) {
function storeFor(b: Bench, slot: 'conversation.session' | 'details', sessionId: SessionId) {
const host = renderHost(b)
const entry = host.entriesOf(slot)[0]!
return host.storeOf(entry, sessionId)! as ReturnType<ReturnType<typeof createChatStore>['create']>
@@ -80,7 +84,7 @@ describe('selection survives on the store seat', () => {
it('one session, two slots: conversation writes, details reads the SAME instance', () => {
const b = bench()
const conv = storeFor(b, 'conversation', sid('s1'))
const conv = storeFor(b, 'conversation.session', sid('s1'))
const details = storeFor(b, 'details', sid('s1'))
conv.actions.select({ turnSeq: 3, callId: 'c1' })
expect(details.store.getSnapshot().selection).toEqual({ turnSeq: 3, callId: 'c1' })
@@ -91,8 +95,8 @@ describe('selection survives on the store seat', () => {
it('sessions are isolated: s2 selection never bleeds into s1', () => {
const b = bench()
const one = storeFor(b, 'conversation', sid('s1'))
const two = storeFor(b, 'conversation', sid('s2'))
const one = storeFor(b, 'conversation.session', sid('s1'))
const two = storeFor(b, 'conversation.session', sid('s2'))
expect(two).not.toBe(one)
one.actions.select({ turnSeq: 1, callId: 'a' })
two.actions.select({ turnSeq: 9, callId: 'z' })
@@ -105,14 +109,14 @@ describe('selection survives on the store seat', () => {
const id = sid('s1')
const projection = createSnapshotStore({ displayTitle: 's1' })
const store = storeFor(b, 'conversation', id)
const store = storeFor(b, 'conversation.session', id)
store.actions.select({ turnSeq: 3, callId: 'c1' })
store.actions.setDraft('half-typed')
projection.set({ displayTitle: 'proj-a' })
expect(projection.getSnapshot().displayTitle).toBe('proj-a')
const after = storeFor(b, 'conversation', id)
const after = storeFor(b, 'conversation.session', id)
expect(after).toBe(store)
expect(after.store.getSnapshot().selection).toEqual({ turnSeq: 3, callId: 'c1' })
expect(after.store.getSnapshot().draft).toBe('half-typed')
@@ -121,7 +125,7 @@ describe('selection survives on the store seat', () => {
it('session death buries the instance and its persisted draft', () => {
const b = bench()
const doomed = storeFor(b, 'conversation', sid('s1'))
const doomed = storeFor(b, 'conversation.session', sid('s1'))
doomed.actions.setDraft('to be buried')
doomed.actions.select({ turnSeq: 1 })
expect(localStorage.getItem('dsh.conversation.chat.s1')).not.toBeNull()
@@ -132,7 +136,7 @@ describe('selection survives on the store seat', () => {
// Persisted residue is gone with the session...
expect(localStorage.getItem('dsh.conversation.chat.s1')).toBeNull()
// ...and a re-created same-id session starts from a FRESH instance.
const reborn = storeFor(b, 'conversation', sid('s1'))
const reborn = storeFor(b, 'conversation.session', sid('s1'))
expect(reborn).not.toBe(doomed)
expect(reborn.store.getSnapshot()).toEqual({ selection: null, draft: '', view: null })
})