Move the plugin onto the DSH 0.1.5-alpha.1 baseline (peer floor ^0.1.5-alpha.1, CI pinned to the alpha dist-tag) and fix the two host contract changes that alpha line introduced. Baseline: - all @deepseek-ai/dsh-* peer/dev deps -> 0.1.5-alpha.1; optional peer @deepseek-ai/dsh-client-ui-sidebar-right (declared, unused until the native-surface phase); devDep @deepseek-ai/dsh-agent-loop (inbox fold) - dsh.plugin.json engines >=0.1.5-alpha.1; version 0.19.0-alpha.0; SIDEBAR_SERVICE_VERSION follows Live assistant stream (assistant/chunk is gone): - 0.1.5 publishes in-flight model deltas as process-local agent/assistant-stream frames instead of durable assistant/chunk events and embeds the settled stream in assistant/message / assistant/attempt. src/assistant-live.ts folds the frames into a bounded per-session buffer; sidechat.events serves the current attempt as `live` rows (replaced every poll, never a delta) and the transcript renders them; the inherited in-progress snapshot reads message content / attempt stream / live frames. Cold session reads (persistence.inspect is gone): - 0.1.5 reads a stored session through an explicit read handle (open(id,'read') -> handle.read() -> close()). src/session-store.ts owns that protocol; every cold read (sidechat transcript, cold-resume preset, session.cwd, changes replay) goes through it. Dead code and docs: - drop the remote.session.openWorkspacePath interception: 0.1.5's chat opens files through ctx.sidebarRight.openResource instead, so the wrapper had no caller and would hijack the host's "open in app" gesture; the interceptOpenPath pref, its settings row and its locale keys go with it - AGENTS.md §3 + external-plugin-guide.md describe the new baseline - vitest setup bridges Node's localStorage accessor to jsdom's store (the pre-existing 26 failures on Node >= 22) - desktop-layout e2e seeds through host RPC and types into the Lexical composer (0.1.5 replaced the textarea) instead of driving the directory picker Verified: pnpm typecheck / lint / build / test (124 files, 1327 tests) / check:consumer-types, plus pnpm test:mount against a real @deepseek-ai/dsh@0.1.5-alpha.1 host (18/18).
66 lines
2.3 KiB
TypeScript
66 lines
2.3 KiB
TypeScript
/**
|
|
* Cold-session reads over the host `sessionPersistence` service.
|
|
*
|
|
* DSH 0.1.5 removed the detached `inspect(id)` call: a persisted session is
|
|
* read through an explicit handle — `open(id, 'read')` never takes write
|
|
* ownership (so it works while the session is live in another process),
|
|
* `handle.read()` returns one contiguous slice of the log, and `close()`
|
|
* releases it. Every cold read in this plugin goes through
|
|
* {@link readPersistedSession} so the handle is always released, even when
|
|
* the read throws.
|
|
*/
|
|
import type { Context, SidebarSessionEvent, SidebarSessionPersistenceService } from './context-types.ts'
|
|
|
|
/** One persisted session as this plugin reads it. */
|
|
export interface PersistedSession {
|
|
/** Immutable stored header (cwd / agentPreset live here). */
|
|
readonly header: { cwd?: string; agentPreset?: string } & Record<string, unknown>
|
|
/** The full stored event log. */
|
|
readonly events: readonly SidebarSessionEvent[]
|
|
/** Exact fork-inherited prefix length (0 when the header is not seeded). */
|
|
readonly inheritedEventCount: number
|
|
}
|
|
|
|
/**
|
|
* Read one persisted session's header and full event log.
|
|
* @param persistence - the live `sessionPersistence` service.
|
|
* @param sessionId - the stored session to read.
|
|
* @returns the header and log; rejects when the session does not exist.
|
|
*/
|
|
export async function readPersistedSession(
|
|
persistence: SidebarSessionPersistenceService,
|
|
sessionId: string,
|
|
): Promise<PersistedSession> {
|
|
const handle = await persistence.open(sessionId, 'read')
|
|
try {
|
|
const { events } = await handle.read()
|
|
return {
|
|
header: handle.header,
|
|
events,
|
|
inheritedEventCount: handle.inheritedEventCount ?? 0,
|
|
}
|
|
} finally {
|
|
await handle.close()
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Resolve the service and read one persisted session, or `undefined` when
|
|
* the service is absent or the session cannot be read.
|
|
* @param ctx - host plugin context.
|
|
* @param sessionId - the stored session to read.
|
|
* @returns the persisted session, or `undefined`.
|
|
*/
|
|
export async function readPersistedSessionOf(
|
|
ctx: Context,
|
|
sessionId: string,
|
|
): Promise<PersistedSession | undefined> {
|
|
const persistence = ctx.get('sessionPersistence')
|
|
if (persistence === undefined) return undefined
|
|
try {
|
|
return await readPersistedSession(persistence, sessionId)
|
|
} catch {
|
|
return undefined
|
|
}
|
|
}
|