feat: adapt to DSH 0.1.2-alpha.5 and bump to v0.19.0-alpha.0

- pins: CI mount-gate CLI, dsh.plugin.json engines floor, and the
  @deepseek-ai/* peer floor / devDependencies baseline move to
  0.1.2-alpha.5 (dsh-client-locale trails at 0.1.2-alpha.3 — no such
  release upstream; ^0.1.2-alpha.3 already accepts the alpha.5 runtime)
- code: migrate the alpha.4 Session.events removal to snapshotEvents()
  (sidechat transcript live reads, fork inheritance, jobs.output replay,
  subagent activity) and drop the seedLength meta field the host removed
  from CreateAgentOptions.meta
- gates: pnpm peers check clean, typecheck + 1137 unit tests green,
  real-host mount smoke 14/14 on npm-published 0.1.2-alpha.5
This commit is contained in:
Menghuan1918
2026-09-02 21:43:34 +08:00
parent dd499b2560
commit a78dd57b23
20 changed files with 327 additions and 333 deletions
+1 -1
View File
@@ -472,7 +472,7 @@ export function matchUrlTarget(tabs: readonly TabDescriptor[], url: URL): TabDes
* The plugin version this service instance reports. Keep in lockstep with
* `package.json`'s version — `tests/service.spec.ts` asserts the pair.
*/
export const SIDEBAR_SERVICE_VERSION = '0.18.1-alpha.0'
export const SIDEBAR_SERVICE_VERSION = '0.19.0-alpha.0'
/**
* Monotonic capability list consumers use to gate new API usage (features
+5 -4
View File
@@ -87,11 +87,12 @@ export interface SidebarSessionStore {
get(id: string): {
header: SidebarSessionHeader
/**
* The live session's append-only event log (immutable snapshot; absent
* on sessions the runtime has not hydrated). Read-only access — the
* jobs.output route replays `job_output` tool/result rows from it.
* The live session's append-only event log as an immutable snapshot.
* Read-only access — the jobs.output route replays `job_output`
* tool/result rows from it. (The `Session.events` property this face
* mirrored was renamed to `snapshotEvents()` in DSH 0.1.2-alpha.4.)
*/
events?: readonly SidebarSessionEvent[]
snapshotEvents(): readonly SidebarSessionEvent[]
} | undefined
}
+1 -1
View File
@@ -473,7 +473,7 @@ function buildApi(
// log opens on a tool event (subagent seeds do) carries seq 0, which a
// literal `> 0` comparison would drop, so the absent case floors at -1.
const afterSeq = rawAfter ?? -1
let events: readonly SidebarSessionEvent[] | undefined = ctx.sessions.get(sessionId)?.events
let events: readonly SidebarSessionEvent[] | undefined = ctx.sessions.get(sessionId)?.snapshotEvents()
if (events === undefined) {
const persistence = ctx.get('sessionPersistence')
if (persistence !== undefined) {
+1 -1
View File
@@ -211,7 +211,7 @@ export function buildJobsApi(ctx: Context, outputLimit: number): SidebarJobsRout
// Merge the store's event log (durable seed + whatever it received)
// with the live mirror, deduped by seq — a trace never double-counts.
const bySeq = new Map<number, JobOutputTrace>()
for (const event of ctx.sessions.get(sessionId)?.events ?? []) {
for (const event of ctx.sessions.get(sessionId)?.snapshotEvents() ?? []) {
const trace = traceOf(event)
if (trace !== undefined) bySeq.set(trace.seq, trace)
}
+10 -9
View File
@@ -168,15 +168,17 @@ function liveThreadAgent(ctx: Context, childId: string): Agent | undefined {
* agent's in-memory log while the thread is attached — the freshest read,
* including events not yet flushed — else the persisted logical log. Both
* DSH generations expose these seams with the same shape (the 0.1.2
* persistence layer packs chunk rows on disk but expands them on inspect),
* which is why the transcript reads here instead of the client's
* session-history RPC: that face (`ctx.connection.api`) was removed in
* 0.1.2-alpha.1's Remote-gateway migration.
* persistence layer packs chunk rows on disk but expands them on inspect;
* the live log is `Session.snapshotEvents()`, the 0.1.2-alpha.4 rename of
* the `Session.events` property), which is why the transcript reads here
* instead of the client's session-history RPC: that face
* (`ctx.connection.api`) was removed in 0.1.2-alpha.1's Remote-gateway
* migration.
*/
async function threadLogEvents(ctx: Context, childId: string): Promise<readonly SidechatLogEvent[]> {
const agent = liveThreadAgent(ctx, childId)
if (agent !== undefined) {
return agent.session.events as unknown as readonly SidechatLogEvent[]
return agent.session.snapshotEvents() as unknown as readonly SidechatLogEvent[]
}
const persistence = ctx.get('sessionPersistence') as SidebarSessionPersistenceService | undefined
if (persistence === undefined) {
@@ -209,11 +211,11 @@ export function buildSidechatApi(ctx: Context): SidechatRoutes {
}
const parentSession = parent.session
const inheritance = buildSidechatInheritance(
parentSession.events as unknown as readonly SidechatLogEvent[],
parentSession.snapshotEvents() as unknown as readonly SidechatLogEvent[],
)
const { agentPreset, setup } = await composeChildSetup(
ctx,
resolvePresetId(parentSession.header, parentSession.events),
resolvePresetId(parentSession.header, parentSession.snapshotEvents()),
)
const childId = `session-${randomUUID()}` as SessionId
const label = question === '' ? SIDE_NEW_THREAD_TITLE : sideLabel(question)
@@ -241,7 +243,6 @@ export function buildSidechatApi(ctx: Context): SidechatRoutes {
meta: {
...(parentSession.header.cwd === undefined ? {} : { cwd: parentSession.header.cwd }),
parentSession: parentSession.id,
seedLength: seed.length,
origin: 'subagent',
delegationDepth: (parentSession.header.delegationDepth ?? 0) + 1,
...(agentPreset === undefined ? {} : { agentPreset }),
@@ -310,7 +311,7 @@ export function buildSidechatApi(ctx: Context): SidechatRoutes {
throw new SidebarError('sidechat-error', `thread resume failed: ${error instanceof Error ? error.message : String(error)}`, 500)
}
}
if (boundaryDelivered(agent.session.events as unknown as readonly SidechatLogEvent[])) {
if (boundaryDelivered(agent.session.snapshotEvents() as unknown as readonly SidechatLogEvent[])) {
admitFollowup(agent, textPrompt(text))
} else {
// First message of an immediately-created thread: it carries the
+1 -1
View File
@@ -77,7 +77,7 @@ export function buildSubagentLiveApi(ctx: Context): SidebarSubagentLiveRoutes {
if (entry.label?.startsWith(SIDE_LABEL_PREFIX) ?? false) continue
try {
const activity = lastActivity(
ctx.sessions.get(entry.id)?.events ?? [],
ctx.sessions.get(entry.id)?.snapshotEvents() ?? [],
LIVE_WINDOW_MESSAGES,
)
if (activity.text !== undefined || activity.tool !== undefined) {