fix(sdk): narrow TypeScript client interface

This commit is contained in:
Tianyi Cui
2026-07-27 23:41:57 +08:00
parent fed1b23eac
commit 3b5be72086
16 changed files with 89 additions and 42 deletions

View File

@@ -71,11 +71,28 @@ interface SubscriptionState {
failure: Error | undefined
}
/**
* One client-side notification stream. Delivery order matches the wire;
* {@link close} detaches it from the client, after which {@link next} rejects.
*/
export class NotificationSubscription implements AsyncIterable<HarnessNotification> {
/** One client-side notification stream returned by {@link HarnessClient.subscribe}. */
export interface NotificationSubscription extends AsyncIterable<HarnessNotification> {
/**
* Await the next matching notification.
* @returns the notification; after the runtime died, drains what was
* already delivered and then rejects; after {@link close}, rejects
* immediately (the queue is dropped).
*/
next(): Promise<HarnessNotification>
/**
* Drain one already-delivered notification without waiting.
* @returns the next queued notification, or `undefined` when none is queued.
*/
tryNext(): HarnessNotification | undefined
/** Detach from the client; queued items drop and pending waiters reject. */
close(): void
}
/** Internal producer side of a public notification subscription. */
class NotificationSubscriptionImpl implements NotificationSubscription {
constructor(
private readonly state: SubscriptionState,
private readonly unsubscribe: () => void,
@@ -168,7 +185,7 @@ export class HarnessClient {
private child: ChildProcess | undefined
private transport: JsonRpcLineTransport | undefined
private readonly stderrTail: string[] = []
private readonly subscriptions = new Map<string, NotificationSubscription>()
private readonly subscriptions = new Map<string, NotificationSubscriptionImpl>()
private readonly sessionParents = new Map<string, string>()
private subscriptionSerial = 0
private exitCode: number | null | undefined
@@ -324,7 +341,7 @@ export class HarnessClient {
subscribe(filter?: NotificationFilter): NotificationSubscription {
const id = String(this.subscriptionSerial++)
const state: SubscriptionState = { queue: [], waiters: [], filter, failure: undefined }
const subscription = new NotificationSubscription(state, () => { this.subscriptions.delete(id) })
const subscription = new NotificationSubscriptionImpl(state, () => { this.subscriptions.delete(id) })
if (this.closeTask !== undefined || this.exitCode !== undefined || this.spawnError !== undefined) {
subscription.fail(this.closedError('DeepSeek Harness runtime closed'))
return subscription

View File

@@ -9,6 +9,21 @@
* @module @deepseek-ai/dsh-sdk-client
*/
export * from './api.ts'
export * from './client.ts'
export type * from './types.ts'
export { DeepSeekHarness, HarnessSession } from './api.ts'
export type { RunOptions } from './api.ts'
export {
HarnessClient,
RequestTimeoutError,
SdkProtocolError,
TransportClosedError,
} from './client.ts'
export type { NotificationSubscription } from './client.ts'
export { JsonRpcResponseError } from '@deepseek-ai/dsh-sdk-protocol'
export type {
ContentBlock,
DeepSeekHarnessOptions,
HarnessClientOptions,
HarnessNotification,
NotificationFilter,
TurnResult,
} from './types.ts'

View File

@@ -67,9 +67,9 @@ export interface TurnResult {
reason: TurnEndReason | undefined
/** Concatenated text of the session's last assistant message (empty when none). */
finalResponse: string
/** Every `session.event` payload for this session tree, in wire order. */
/** Every `session.event` payload for the root session, in wire order. */
events: SessionEvent[]
/** Every notification observed during the turn, in wire order. */
/** Every notification for the root session and discovered descendants, in wire order. */
notifications: HarnessNotification[]
}