| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- /**
- * sessions domain contract. Method signatures are the source of truth:
- * unary methods take the RpcRequest<P> narrow form and the impl echoes rpcId; everything
- * else references RequestPayload<'session.*'> / ResponseValue<'session.*'>.
- */
- import type { ContentBlock } from '@deepseek-ai/dsh-llm/types'
- import type { SessionEvent, SessionId } from '@deepseek-ai/dsh-session/types'
- // The pure-type outlet: api/ is browser-importable, and the package root's
- // cordis Context merge (via dsh-agent) must not enter client aggregates.
- import type { SessionProjectionMap } from '@deepseek-ai/dsh-session-projection/types'
- import type { RpcId, RpcRequest, RpcResponse } from './rpc.ts'
- import type { ToolEventView } from './events.ts'
- import type { WorkspaceId } from './workspace.ts'
- declare module '@deepseek-ai/dsh-llm' {
- interface MessageSourceMap {
- /**
- * The prompt's rpcId is passed through MessageSource into the `user/message` event
- * (the client uses it to reconcile the optimistically
- * echoed provisional message with the event stream). kind stays `'user'` — the model face
- * carries no transport vocabulary; rpcId is an extra durable-JSON field passed back to the client with the event.
- */
- 'user-rpc': { kind: 'user'; rpcId: RpcId }
- }
- }
- /**
- * One history page entry: the raw event plus the optional host-computed render
- * intent (same semantics as the mux frame's `view` slot — a pagination-time
- * derivation, never persisted).
- */
- export interface HistoryEntry {
- event: SessionEvent
- view?: ToolEventView
- }
- /**
- * The projection baseline riding the history tail page: one synchronous cut
- * over every registered projection unit, read from the registry's watermark
- * cache. `asOfSeq` is the seq of the last committed event every value
- * reflects — the window tail event seq (`-1` for an empty log, mirroring
- * `session/subscribed.lastSeq`), directly comparable with
- * `session/projection` frame seqs under the client's higher-seq-wins rule. A
- * key absent from `values` means the capability is absent (its domain plugin
- * is unmounted).
- */
- export interface SessionProjectionsBlock {
- /** Seq of the last event the values reflect; -1 for an empty log. */
- asOfSeq: number
- /** Whole current value per registered projection key. */
- values: Partial<SessionProjectionMap>
- }
- /** Complete model target selected for one session. */
- export interface ModelTarget {
- /** Registered provider route. */
- provider: string
- /** Provider-owned model id. */
- model: string
- /** Adapter-owned reasoning effort; absence preserves adapter/provider default behavior. */
- reasoningEffort?: string
- }
- /** One adapter-owned reasoning effort displayed for an exact model route. */
- export interface ModelReasoningEffort {
- /** Opaque value submitted back to the owning adapter. */
- id: string
- /** Adapter-supplied display name. */
- name: string
- /** Optional adapter-supplied description. */
- description?: string
- }
- /** Selectable reasoning metadata for one exact model route. */
- export interface ModelReasoning {
- /** Efforts in adapter-preferred display order. */
- efforts: ModelReasoningEffort[]
- /** Adapter-configured default; absence preserves the provider default. */
- defaultEffort?: string
- }
- /** One model displayed inside its provider group. */
- export interface ModelCatalogModel {
- /** Provider-owned model id. */
- id: string
- /** Provider-supplied display name. */
- name: string
- /** Optional provider-supplied description. */
- description?: string
- /** The current model was inserted because the advisory catalog omitted it. */
- unlisted?: true
- /** Exact-route reasoning metadata when the adapter exposes it. */
- reasoning?: ModelReasoning
- }
- /** One provider and the models it advertised successfully. */
- export interface ModelProviderGroup {
- /** Provider route id used for requests. */
- id: string
- /** Provider display name. */
- name: string
- /** Models in provider-preferred order. */
- models: ModelCatalogModel[]
- }
- /** A provider whose asynchronous catalog lookup failed. */
- export interface ModelCatalogFailure {
- /** Provider route id. */
- id: string
- /** Provider display name. */
- name: string
- /** Lookup failure diagnostic. */
- message: string
- }
- /** Detached model-directory snapshot for one session. */
- export interface SessionModels {
- /** Target selected for the session's next assembled step. */
- current: ModelTarget
- /** Successfully loaded provider groups. */
- groups: ModelProviderGroup[]
- /** Provider-local failures; successful groups remain usable. */
- failures: ModelCatalogFailure[]
- }
- /** Session list entry (v1 builds no index: list does readdir+stat). */
- export interface SessionSummary {
- sessionId: SessionId
- /** Persisted file mtime. */
- updatedAt: number
- /** Status of the attached agent; always false for cold (unattached) sessions. */
- running: boolean
- /**
- * Derived conversation-not-started bit: true while no turn has run (no
- * prompt was accepted yet). Standalone plugin events — command lifecycle
- * records, plan/mode, titles, goals — do not open a turn and therefore do
- * not clear it. Clients hide blank sessions from lists and reuse them for
- * New Session on the same workspace. Always false for cold sessions —
- * lazy persistence keeps a never-appended session out of the store, and a
- * listed cold session's log holds its turns.
- */
- blank: boolean
- /** fork/spawn lineage (session.header.parentSession passthrough); absent for root sessions. */
- parentSessionId?: SessionId
- /** Session working directory (header.cwd passthrough); absent when unrecorded. */
- cwd?: string
- /**
- * Projection baseline for this row, with zero log loads: attached sessions
- * read the registry's live watermark cut; cold sessions read the persisted
- * projection cache's stored rows — as stale as that session's last durable
- * checkpoint (`asOfSeq` says exactly how stale), never wrong, and directly
- * seedable into the client's per-session value store under its
- * higher-seq-wins rule (a list baseline can never overwrite a newer push
- * frame). Absent when no value is available (no registry, no cache row for
- * a cold session, or a fail-soft cache read miss); a listing client treats
- * absence as "no title yet", exactly like a blank session.
- */
- projections?: SessionProjectionsBlock
- }
- /** Session-domain unary methods (the map keys session.* of RpcMethodMap). */
- export interface SessionsApi {
- /** Lists persisted sessions (updatedAt descending). v1 returns everything; cursor is a reserved seat, unimplemented. */
- list(request: RpcRequest<{ cursor?: string }>): Promise<RpcResponse<{ items: SessionSummary[] }>>
- /**
- * Creates a real session and its idle agent. At most one of `workspaceId` /
- * `cwd` is accepted; an omitted project uses the Host cwd. A caller may
- * preallocate `sessionId`: retries with the same id and cwd return the same
- * session, while a different cwd fails with `session-conflict`. Workspace
- * creation attaches the session after publication; an attach failure
- * returns `workspace-attach-failed` with the published session id.
- */
- create(request: RpcRequest<{ workspaceId?: WorkspaceId; cwd?: string; sessionId?: SessionId }>):
- Promise<RpcResponse<{ sessionId: SessionId }>>
- /**
- * Reads a window of history events; page boundaries align to append-origin human-message
- * boundaries: one page = all raw events owned by a whole number of such messages (including
- * their chunk / tool events), never cut mid-message. Model-only replacement copies consume no
- * `maxMessages`, so a compaction's provenance stays on the page of its replacement. The tail
- * page (beforeSeq absent) additionally carries the in-flight
- * partial — chunk events already emitted for the last unfinalized message.
- * Each entry pairs the raw SessionEvent with the host-computed view (tool events whose
- * presenter produced one, evaluated against the registry at pagination time); the client
- * rebuilds the surface from the events with the shared fold.
- * The tail page — and only the tail page — additionally carries `projections`
- * when the deployment mounts the session-projection registry: every moment
- * the client needs a fresh baseline already pulls the tail page, and
- * loadOlder (the only beforeSeq path) is the only path that never needs one.
- * A deployment without the registry serves histories without the block.
- */
- history(request: RpcRequest<{ sessionId: SessionId; beforeSeq?: number; maxMessages?: number }>):
- Promise<RpcResponse<{ events: HistoryEntry[]; hasMore: boolean; projections?: SessionProjectionsBlock }>>
- /** Reads a fresh advisory model directory for this session. Provider lookups run independently. */
- models(request: RpcRequest<{ sessionId: SessionId }>): Promise<RpcResponse<SessionModels>>
- /**
- * Selects the complete target for this session. Exact model metadata
- * validates an optional reasoning effort, while catalog membership remains
- * advisory.
- */
- selectModel(request: RpcRequest<{
- sessionId: SessionId
- provider: string
- model: string
- reasoningEffort?: string
- }>):
- Promise<RpcResponse<{ selected: ModelTarget }>>
- /**
- * Sends a message. content is core's ContentBlock[] verbatim; mode maps 1:1 — queue→send, steer→steer.
- * A prompt whose content is exactly one text block starting with '/' is a slash command: the host
- * executes it through the command registry (mode-agnostic) and it is never sent to the model. A
- * successful command returns ok with the command slot (its success text, when the command produced
- * one — carried for future rendering; the state change is the feedback). A usage/state error is an
- * RPC error with code command-error; an unrecognized name is an RPC error with code unknown-command.
- */
- prompt(request: RpcRequest<{ sessionId: SessionId; mode: 'queue' | 'steer'; content: ContentBlock[] }>):
- Promise<RpcResponse<{ accepted: true; command?: { kind: 'success'; text?: string } }>>
- /** Stops: clears both FIFOs + aborts the current step (1:1 with agent.cancel). */
- cancel(request: RpcRequest<{ sessionId: SessionId }>): Promise<RpcResponse<{ accepted: true }>>
- }
|