feat: slash system / input service / agent scope
This commit is contained in:
@@ -26,8 +26,8 @@ export interface SlotMap {}
|
||||
/** Slot cardinality: single occupant, ordered list, key-dispatched, or selector-routed chain. */
|
||||
export type SlotKind = 'single' | 'list' | 'keyed' | 'chain'
|
||||
|
||||
/** Slot data context: root (no session) or session-bound. */
|
||||
export type SlotScope = 'root' | 'session'
|
||||
/** Slot data context: global, current-session-optional, or strict session-bound. */
|
||||
export type SlotScope = 'root' | 'session-maybe' | 'session'
|
||||
|
||||
/**
|
||||
* One SlotMap entry: kind/scope axes plus the optional owner-supplied props
|
||||
@@ -73,6 +73,13 @@ export type ScopeOf<K extends keyof SlotMap & string> = SlotMap[K]['scope']
|
||||
*/
|
||||
export interface SessionStandardProps {}
|
||||
|
||||
/**
|
||||
* Framework standard kit delivered to current-session-optional slots. Its
|
||||
* hooks stay callable while no session is selected and return `undefined`
|
||||
* until one becomes current; concrete members merge in at runtime packages.
|
||||
*/
|
||||
export interface SessionMaybeStandardProps {}
|
||||
|
||||
/**
|
||||
* Framework standard kit delivered to EVERY slot component (the global seat).
|
||||
* Declared empty here; the runtime package merges the global object-layer
|
||||
@@ -93,14 +100,27 @@ export type SessionIdOf = SessionStandardProps extends { sessionId: infer S } ?
|
||||
*/
|
||||
export type PropsRuntime<K extends keyof SlotMap & string> =
|
||||
OwnerOf<K> &
|
||||
(ScopeOf<K> extends 'session' ? SessionStandardProps : object) &
|
||||
(ScopeOf<K> extends 'session' ? SessionStandardProps
|
||||
: ScopeOf<K> extends 'session-maybe' ? SessionMaybeStandardProps
|
||||
: object) &
|
||||
GlobalStandardProps
|
||||
|
||||
/** renderSlot dispatch options: keyed dispatch key, list filtering, empty fallback. */
|
||||
export interface RenderOpts { entryKey?: string; only?: string; fallback?: ReactNode }
|
||||
|
||||
/** renderSlotChain dispatch options: the owner's fallback body, rendered when every entry's selector declines. */
|
||||
export interface ChainRenderOpts { fallback?: ReactNode }
|
||||
/** renderSlotChain dispatch options. */
|
||||
export interface ChainRenderOpts {
|
||||
/** The owner's fallback body, rendered when every entry's selector declines. */
|
||||
fallback?: ReactNode
|
||||
/**
|
||||
* Keep the fallback permanently mounted: an election hides it (wrapped,
|
||||
* display:none) instead of unmounting it, and the all-decline case shows it
|
||||
* as-is — fallback-held state (composer drafts, DOM state) survives a
|
||||
* takeover. Chain kind only. Sole consumer today: the
|
||||
* 'conversation.composer' chain.
|
||||
*/
|
||||
overlay?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Chain-entry selector: the routing decision of one chain contribution.
|
||||
@@ -210,15 +230,20 @@ export type ComposedProps<
|
||||
|
||||
/**
|
||||
* Inject factory parameter list, derived from the registration's declaration:
|
||||
* session slots receive the framework-resolved `sessionId`; a declared store
|
||||
* appends the baked `actions` (the same callbacks the component receives);
|
||||
* root slots without a store take no parameters. Business data access happens
|
||||
* through the apply closure's ctx — no binding object parameter exists.
|
||||
* strict session slots receive a definite framework-resolved `sessionId`;
|
||||
* session-maybe slots receive the current id or `undefined`; a declared store
|
||||
* appends the baked `actions` (the same callbacks the component receives).
|
||||
* Business data access happens through the apply closure's ctx — no binding
|
||||
* object parameter exists.
|
||||
*/
|
||||
export type InjectParams<K extends keyof SlotMap & string, H> =
|
||||
ScopeOf<K> extends 'session'
|
||||
? ([H] extends [StoreDecl] ? [sessionId: SessionIdOf, actions: BoundActions<HandleOf<H>>] : [sessionId: SessionIdOf])
|
||||
: ([H] extends [StoreDecl] ? [actions: BoundActions<HandleOf<H>>] : [])
|
||||
: ScopeOf<K> extends 'session-maybe'
|
||||
? ([H] extends [StoreDecl]
|
||||
? [sessionId: SessionIdOf | undefined, actions: BoundActions<HandleOf<H>> | undefined]
|
||||
: [sessionId: SessionIdOf | undefined])
|
||||
: ([H] extends [StoreDecl] ? [actions: BoundActions<HandleOf<H>>] : [])
|
||||
|
||||
/** Kind shape fields carried in register options (keyed dispatch key; list id/order/label; chain select/priority). */
|
||||
export type KindOptions<E extends SlotEntryDef, M = never> =
|
||||
|
||||
@@ -26,15 +26,31 @@ export interface StoreInstanceLike {
|
||||
readonly actions: Record<string, (...params: never[]) => void>
|
||||
}
|
||||
|
||||
/** Session standard kit resolved per session id (identity-stable per session scope; a recreated scope yields a new cell). */
|
||||
export interface SessionCell {
|
||||
sessionId: string
|
||||
/**
|
||||
* Per-session standard props resolved per session id (identity-stable per
|
||||
* session scope; a recreated scope yields a new info). Plugins contribute
|
||||
* members through the runtime `sessions.provide` seam; the render side binds
|
||||
* every `hooks` source into a `use<Name>` selector hook (hooks never appear
|
||||
* on the host contract) and spreads `props` verbatim. The runtime itself
|
||||
* contributes the first entry (`'session'` → `useSession`).
|
||||
*/
|
||||
export interface SessionMaybeProvideInfo {
|
||||
/** Current session id, absent while the application is in no-session mode. */
|
||||
sessionId: string | undefined
|
||||
/**
|
||||
* Bare conversation-snapshot source (wide here; runtime narrows at its
|
||||
* export seam). The React side binds the `useSession` hook per cell —
|
||||
* hooks never appear on the host contract.
|
||||
* Static hook roster. Each value is absent with the session; keys remain so
|
||||
* session-maybe entries always receive the same hook-shaped standard kit.
|
||||
*/
|
||||
session: HostObservable<unknown>
|
||||
hooks: Record<string, HostObservable<unknown> | undefined>
|
||||
/** Static plain-member roster; values are undefined with the session. */
|
||||
props: Record<string, unknown>
|
||||
}
|
||||
|
||||
/** Definite per-session standard props resolved for strict session slots. */
|
||||
export interface SessionProvideInfo extends SessionMaybeProvideInfo {
|
||||
sessionId: string
|
||||
/** Bare observable sources, keyed by hook base name ('session' → useSession). */
|
||||
hooks: Record<string, HostObservable<unknown>>
|
||||
}
|
||||
|
||||
/** renderSlot dispatch options at the machinery level: keyed dispatch key, list filtering, empty fallback. */
|
||||
@@ -91,12 +107,16 @@ export interface SlotRendererHost {
|
||||
list: HostObservable<unknown>
|
||||
/** Current-session source used by SessionProvider. */
|
||||
current: HostObservable<string | undefined>
|
||||
/** Resolve a definite session bundle, or undefined when the id is unknown. */
|
||||
provideInfo(id: string): SessionProvideInfo | undefined
|
||||
/**
|
||||
* Resolve the session standard kit.
|
||||
* @param id - session id.
|
||||
* @returns the cell, or undefined for an unknown session (provider falls to empty).
|
||||
* Resolve the current-session-optional standard props bundle. The result
|
||||
* always carries the static provider roster, even when `id` is absent or
|
||||
* cannot resolve to a live session.
|
||||
* @param id - current session id, when selected.
|
||||
* @returns the optional provide info.
|
||||
*/
|
||||
cell(id: string): SessionCell | undefined
|
||||
maybeProvideInfo(id: string | undefined): SessionMaybeProvideInfo
|
||||
}
|
||||
/** Workspace-side standard-kit sources. */
|
||||
workspaces: {
|
||||
|
||||
@@ -7,6 +7,15 @@
|
||||
*/
|
||||
export type SnapshotSelectorHook<T> = <S>(sel: (s: T) => S, eq?: (a: S, b: S) => boolean) => S
|
||||
|
||||
/**
|
||||
* Selector hook over a source that follows the current session. The hook is
|
||||
* always present, while its selected value is absent whenever no session is
|
||||
* current. This keeps hook call sites stable across no-session/session
|
||||
* transitions without pretending that a session snapshot exists.
|
||||
*/
|
||||
export type MaybeSnapshotSelectorHook<T> =
|
||||
<S>(sel: (s: T) => S, eq?: (a: S, b: S) => boolean) => S | undefined
|
||||
|
||||
/**
|
||||
* Action declaration table: pure immer-draft transforms over the store state,
|
||||
* declared as the store's complete write set (the audit face — components can
|
||||
|
||||
Reference in New Issue
Block a user