session.ts 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /**
  2. * The outward session face. Feature packages never see the concrete Session
  3. * class: components read lifecycle state through `useSession` (the
  4. * ObservableSnapshot half), and orchestration code calls the behavior verbs
  5. * below — nothing else. Widening this interface is the explicit act of
  6. * widening what features may do to a session (and what every test fixture
  7. * must stub); implementation-internal entry points (history staging, wire-frame
  8. * dispatch) stay on the class, invisible out here.
  9. */
  10. import type { AttachmentIdType, FileAttachmentRef, ImageAttachmentRef } from '@deepseek-ai/dsh-attachment'
  11. import type { MessageId } from '@deepseek-ai/dsh-llm/brand'
  12. import type { SessionId, SessionSeq } from '@deepseek-ai/dsh-session/types'
  13. import type { RemoteResult } from '@deepseek-ai/dsh-typert-protocol'
  14. import type { ObservableSnapshot } from '@deepseek-ai/dsh-client-store'
  15. import type { PromptContentPart, QueueAction, SessionRequestId } from '../../types.ts'
  16. import type { PendingSubmissionAttachment, SessionSnapshot } from './snapshot.ts'
  17. /**
  18. * Why a local submission echo left the snapshot: `observed` when its durable
  19. * `user/message` event or host queue occurrence arrived (with the admitted
  20. * attachment references in prompt order), `failed` when the prompt was rejected,
  21. * threw, or was aborted before acceptance.
  22. */
  23. export type PendingSubmissionRetirement =
  24. | {
  25. readonly reason: 'observed'
  26. readonly attachments: readonly (ImageAttachmentRef | FileAttachmentRef)[]
  27. }
  28. | { readonly reason: 'failed' }
  29. /** Input registering one local submission echo ahead of its prompt call. */
  30. export interface BeginSubmissionInput {
  31. /** Delivery mode used with the upcoming prompt. */
  32. readonly mode: 'queue' | 'steer'
  33. /** Prompt text exactly as the upcoming prompt will send it. */
  34. readonly text: string
  35. /** Ordered image previews and durable file metadata matching the upcoming prompt attachments. */
  36. readonly attachments: readonly PendingSubmissionAttachment[]
  37. /** Settlement callback fired exactly once when the echo retires. */
  38. readonly onRetire?: (retirement: PendingSubmissionRetirement) => void
  39. }
  40. /** One registered submission echo: the identity its prompt must carry, and the pre-prompt escape hatch. */
  41. export interface SubmissionHandle {
  42. /** The prompt RPC identity; pass it to {@link ISession.prompt}. */
  43. readonly requestId: SessionRequestId
  44. /** Retire the echo as failed when the caller cannot reach prompt() (serialization failure); no-op after any other settlement. */
  45. abandon(): void
  46. }
  47. /** Key-addressed projection read face (the useProjection resolution path; see ProjectionValueStore). */
  48. export interface ProjectionsFace {
  49. /**
  50. * The identity-stable bare observable for one projection key (absence is
  51. * an `undefined` snapshot, never a missing face).
  52. * @param key - projection key.
  53. * @returns the key's value face.
  54. */
  55. faceOf(key: string): ObservableSnapshot<unknown>
  56. }
  57. /** Identity plus the behavior verbs features may invoke on a session. */
  58. export interface ISession {
  59. /** The session's host identity (agent id — same axis). */
  60. readonly sessionId: SessionId
  61. /** Host-computed projection values by key (the useProjection seat). */
  62. readonly projections: ProjectionsFace
  63. /**
  64. * Register one local submission echo in `snapshot.pendingSubmissions`,
  65. * synchronously, before the caller serializes and sends the prompt. The
  66. * echo retires when a durable `user/message` event or queue occurrence
  67. * carrying the returned identity arrives, or when the identified prompt
  68. * call fails.
  69. * @param input - echo content and the optional settlement callback.
  70. * @returns the minted identity for {@link prompt} plus the pre-prompt abandon path.
  71. */
  72. beginSubmission(input: BeginSubmissionInput): SubmissionHandle
  73. /**
  74. * Send a prompt into the session.
  75. * @param content - text plus browser-owned temporary image uploads.
  76. * @param mode - 'queue' appends a turn; 'steer' interrupts the running one.
  77. * @param signal - optional caller cancellation for the complete admission round-trip.
  78. * @param requestId - identity from {@link beginSubmission}; a failed identified prompt retires its echo.
  79. * @returns acceptance, or the business error (also mirrored into snapshot.promptError).
  80. */
  81. prompt(
  82. content: PromptContentPart[],
  83. mode: 'queue' | 'steer',
  84. signal?: AbortSignal,
  85. requestId?: SessionRequestId,
  86. ): Promise<RemoteResult<{ accepted: true }>>
  87. /**
  88. * Resolve one durable image referenced by this session.
  89. * @param attachmentId - opaque id found in the folded session log.
  90. * @returns the authenticated reference and decoded bytes.
  91. */
  92. readAttachment(
  93. attachmentId: AttachmentIdType,
  94. ): Promise<RemoteResult<{ attachment: ImageAttachmentRef; data: Uint8Array }>>
  95. /**
  96. * Apply one edit, remove, or strict steer action to a still-pending queue occurrence.
  97. * @param itemId - agent-owned inbox occurrence identity.
  98. * @param action - requested queue operation.
  99. * @returns acceptance, or a business/transport error.
  100. */
  101. updateQueue(itemId: MessageId, action: QueueAction): Promise<RemoteResult<{ accepted: true }>>
  102. /**
  103. * Cancel the running turn. Pending queued work remains and resumes in FIFO
  104. * order after the Host reaches cancellation quiescence.
  105. * @returns acceptance, or the business error.
  106. */
  107. cancel(): Promise<RemoteResult<{ accepted: true }>>
  108. /**
  109. * Rename this session (explicit user title; pins it against automatic
  110. * regeneration).
  111. * @param title - raw title text (the host normalizes acceptance).
  112. * @returns the normalized accepted title and its event seq, or the business error.
  113. */
  114. rename(title: string): Promise<RemoteResult<{ title: string; seq: SessionSeq }>>
  115. /**
  116. * Extend the history window backwards (older messages pagination).
  117. * @returns completion; failures land in snapshot.openState/loadingOlder.
  118. */
  119. loadOlder(): Promise<void>
  120. /**
  121. * Page history backwards until the window covers `seq` (inclusive) — the
  122. * turn-jump loader. Repeated calls while a jump is paging lower its shared
  123. * target and return the in-flight completion; `snapshot.loadingOlder` is
  124. * the busy signal for the whole jump.
  125. * @param seq - durable event seq the window must reach (a turn's `turn/start` seq).
  126. * @returns completion once covered, exhausted, superseded, or failed soft.
  127. */
  128. loadThrough(seq: SessionSeq): Promise<void>
  129. /**
  130. * Execute one slash-command line against this session's agent — pure
  131. * admission semantics (the host executor durably logs the lifecycle).
  132. * @param line - the full command line, leading slash included.
  133. * @returns the admission result, or the Remote face's error branch.
  134. */
  135. command(line: string): Promise<RemoteResult<{ matched: boolean }>>
  136. }
  137. /**
  138. * The full outward face: behavior verbs plus the Session lifecycle read side
  139. * (the `useSession` hook source). This is the type carried by
  140. * `SessionBinding.session` and the provide channel.
  141. */
  142. export type SessionFace = ISession & ObservableSnapshot<SessionSnapshot>