test(sdk): snapshot suite over the SDK path; docs for the SDK stack

- examples/jsonrpc-agent gains its first snapshot suite (sdk.snapshot.ts):
  the real dsh-jsonrpc-agent runtime driven through the real dsh-sdk-client,
  keyless llm-replay behind a new cordis.snapshot.yml overlay; three recorded
  scenarios (text turn, bash tool, spawn subagent) pin the notification
  stream, the SDK turn result, and the persisted parent+child session logs.
- Bilingual READMEs for dsh-sdk-protocol / dsh-sdk-client / dsh-subagent-sdk;
  sdk/ and subagent/ group tables extended; dsh-jsonrpc README points at the
  extracted protocol package; Agent Note (en+zh) owns the decision.
- The proposed make-jsonrpc-directional note is updated for the transport's
  new home and its second (client) consumer.
- Model Experience sentence allowlist entries for the two client-side
  packages; module graph + config catalog regenerated; i18n pairings
  recorded. doc-sync passes 24/24.
This commit is contained in:
Tianyi Cui
2026-07-27 04:37:23 +08:00
parent 3e89a73c71
commit 34aabc4183
42 changed files with 1570 additions and 39 deletions
+13 -3
View File
@@ -107,13 +107,19 @@ export class NotificationSubscription implements AsyncIterable<HarnessNotificati
this.fail(new TransportClosedError('notification subscription closed'))
}
/** Reject pending and future waits with `error` (delivery stops). */
/**
* Reject pending and future waits (delivery stops; the first failure wins).
* @param error - the terminal failure delivered to waiters.
*/
fail(error: Error): void {
this.state.failure ??= error
for (const waiter of this.state.waiters.splice(0)) waiter.reject(this.state.failure)
}
/** Deliver one notification to a waiter or the queue when the filter matches. */
/**
* Deliver one notification to a waiter or the queue when the filter matches.
* @param notification - the wire notification to deliver.
*/
push(notification: HarnessNotification): void {
if (this.state.filter !== undefined && !this.state.filter(notification)) return
const waiter = this.state.waiters.shift()
@@ -413,7 +419,11 @@ export class HarnessClient {
}
}
/** Whether `value` is a plain JSON object (the wire-boundary shape probe). */
/**
* Whether `value` is a plain JSON object (the wire-boundary shape probe).
* @param value - the wire value to probe.
* @returns `true` iff `value` is a non-null, non-array object.
*/
export function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === 'object' && value !== null && !Array.isArray(value)
}