dsh-coding-sidebar 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +5 -5
  2. package/lib/client-editor.js +416 -355
  3. package/lib/client-mermaid.js +304 -273
  4. package/lib/client-registry.js +555 -421
  5. package/lib/client-terminal.js +216 -208
  6. package/lib/client.js +557 -423
  7. package/lib/index.js +20 -12
  8. package/lib/types/client/locales.d.ts +4 -0
  9. package/lib/types/context-types.d.ts +19 -10
  10. package/package.json +26 -27
  11. package/src/client/SideCardSection.module.css +2 -2
  12. package/src/client/SideChatView.module.css +12 -12
  13. package/src/client/SubagentView.module.css +41 -0
  14. package/src/client/SubagentView.tsx +63 -7
  15. package/src/client/locales-ar.ts +4 -0
  16. package/src/client/locales-de.ts +4 -0
  17. package/src/client/locales-fr.ts +4 -0
  18. package/src/client/locales-hi.ts +4 -0
  19. package/src/client/locales-id.ts +4 -0
  20. package/src/client/locales-it.ts +4 -0
  21. package/src/client/locales-ja.ts +4 -0
  22. package/src/client/locales-ko.ts +4 -0
  23. package/src/client/locales-nl.ts +4 -0
  24. package/src/client/locales-pl.ts +4 -0
  25. package/src/client/locales-pt.ts +4 -0
  26. package/src/client/locales-ru.ts +4 -0
  27. package/src/client/locales-sv.ts +4 -0
  28. package/src/client/locales-th.ts +4 -0
  29. package/src/client/locales-tr.ts +4 -0
  30. package/src/client/locales-vi.ts +4 -0
  31. package/src/client/locales-zh-HK.ts +4 -0
  32. package/src/client/locales-zh-MO.ts +4 -0
  33. package/src/client/locales-zh-TW.ts +4 -0
  34. package/src/client/locales.ts +8 -0
  35. package/src/context-types.ts +12 -7
  36. package/src/index.ts +5 -4
  37. package/src/jobs-routes.ts +3 -2
  38. package/src/sidechat-routes.ts +13 -8
  39. package/src/subagent-live-route.ts +2 -1
@@ -296,6 +296,8 @@ export const ja: Record<string, string> = {
296
296
  subagentDiagUnsupported: '未サポートのエントリ',
297
297
  subagentDiagUnavailable: '利用不可',
298
298
  subagentThinking: '思考中…',
299
+ subagentShowHistory: '前のサブエージェント {count} 件を表示',
300
+ subagentHideHistory: '前のサブエージェントを折りたたむ',
299
301
  sideChat: 'サイドチャット(beta)',
300
302
  sideChatNew: '新規スレッド',
301
303
  sideChatUntitled: '新規スレッド',
@@ -323,6 +325,8 @@ export const ja: Record<string, string> = {
323
325
  jobs: 'バックグラウンドタスク',
324
326
  jobsCount: '{count} 個のバックグラウンドタスク',
325
327
  jobsCountRunning: '{count} 個のバックグラウンドタスク ・ {running} 個実行中',
328
+ jobsShowHistory: '前のバックグラウンドタスク {count} 件を表示',
329
+ jobsHideHistory: '前のバックグラウンドタスクを折りたたむ',
326
330
  jobStatusRunning: '実行中',
327
331
  jobStatusStopping: '停止中',
328
332
  jobStatusCompleted: '完了',
@@ -288,6 +288,8 @@ export const ko: Record<string, string> = {
288
288
  subagentDiagUnsupported: '지원되지 않는 항목',
289
289
  subagentDiagUnavailable: '사용할 수 없음',
290
290
  subagentThinking: '생각하는 중…',
291
+ subagentShowHistory: '이전 서브 에이전트 {count}개 표시',
292
+ subagentHideHistory: '이전 서브 에이전트 접기',
291
293
  sideChat: '사이드 채팅(beta)',
292
294
  sideChatNew: '새 대화',
293
295
  sideChatUntitled: '새 대화',
@@ -315,6 +317,8 @@ export const ko: Record<string, string> = {
315
317
  jobs: '백그라운드 작업',
316
318
  jobsCount: '백그라운드 작업 {count}개',
317
319
  jobsCountRunning: '백그라운드 작업 {count}개 · {running} 실행 중',
320
+ jobsShowHistory: '이전 백그라운드 작업 {count}개 표시',
321
+ jobsHideHistory: '이전 백그라운드 작업 접기',
318
322
  jobStatusRunning: '실행 중',
319
323
  jobStatusStopping: '종료 중',
320
324
  jobStatusCompleted: '완료됨',
@@ -294,6 +294,8 @@ export const nl: Record<string, string> = {
294
294
  subagentDiagUnsupported: 'Niet ondersteund',
295
295
  subagentDiagUnavailable: 'Niet beschikbaar',
296
296
  subagentThinking: 'Nadenken…',
297
+ subagentShowHistory: '{count} eerdere subagents weergeven',
298
+ subagentHideHistory: 'Eerdere subagents samenvouwen',
297
299
  sideChat: 'Side Chat (bèta)',
298
300
  sideChatNew: 'Nieuwe thread',
299
301
  sideChatUntitled: 'Nieuwe thread',
@@ -321,6 +323,8 @@ export const nl: Record<string, string> = {
321
323
  jobs: 'Achtergrondtaken',
322
324
  jobsCount: '{count} achtergrondtaken',
323
325
  jobsCountRunning: '{count} achtergrondtaken · {running} actief',
326
+ jobsShowHistory: '{count} eerdere achtergrondtaken weergeven',
327
+ jobsHideHistory: 'Eerdere achtergrondtaken samenvouwen',
324
328
  jobStatusRunning: 'Actief',
325
329
  jobStatusStopping: 'Stoppen',
326
330
  jobStatusCompleted: 'Voltooid',
@@ -298,6 +298,8 @@ export const pl: Record<string, string> = {
298
298
  subagentDiagUnsupported: 'Nieobsługiwany',
299
299
  subagentDiagUnavailable: 'Niedostępny',
300
300
  subagentThinking: 'Myśli…',
301
+ subagentShowHistory: 'Pokaż {count} starszych podagentów',
302
+ subagentHideHistory: 'Zwiń starszych podagentów',
301
303
  sideChat: 'Czat boczny (beta)',
302
304
  sideChatNew: 'Nowy wątek',
303
305
  sideChatUntitled: 'Nowy wątek',
@@ -325,6 +327,8 @@ export const pl: Record<string, string> = {
325
327
  jobs: 'Zadania w tle',
326
328
  jobsCount: '{count} zadań w tle',
327
329
  jobsCountRunning: '{count} zadań w tle · {running} działa',
330
+ jobsShowHistory: 'Pokaż {count} starszych zadań w tle',
331
+ jobsHideHistory: 'Zwiń starsze zadania w tle',
328
332
  jobStatusRunning: 'Działa',
329
333
  jobStatusStopping: 'Zatrzymywanie',
330
334
  jobStatusCompleted: 'Ukończono',
@@ -279,6 +279,8 @@ export const pt: Record<string, string> = {
279
279
  subagentDiagUnsupported: 'Não suportado',
280
280
  subagentDiagUnavailable: 'Indisponível',
281
281
  subagentThinking: 'Pensando…',
282
+ subagentShowHistory: 'Mostrar {count} subagentes anteriores',
283
+ subagentHideHistory: 'Recolher subagentes anteriores',
282
284
  sideChat: 'Chat lateral (beta)',
283
285
  sideChatNew: 'Novo tópico',
284
286
  sideChatUntitled: 'Novo tópico',
@@ -306,6 +308,8 @@ export const pt: Record<string, string> = {
306
308
  jobs: 'Tarefas em segundo plano',
307
309
  jobsCount: '{count} tarefas em segundo plano',
308
310
  jobsCountRunning: '{count} tarefas em segundo plano · {running} executando',
311
+ jobsShowHistory: 'Mostrar {count} tarefas em segundo plano anteriores',
312
+ jobsHideHistory: 'Recolher tarefas em segundo plano anteriores',
309
313
  jobStatusRunning: 'Executando',
310
314
  jobStatusStopping: 'Parando',
311
315
  jobStatusCompleted: 'Concluída',
@@ -294,6 +294,8 @@ export const ru: Record<string, string> = {
294
294
  subagentDiagUnsupported: 'Не поддерживается',
295
295
  subagentDiagUnavailable: 'Недоступен',
296
296
  subagentThinking: 'Размышляет…',
297
+ subagentShowHistory: 'Показать {count} более ранних субагентов',
298
+ subagentHideHistory: 'Свернуть более ранних субагентов',
297
299
  sideChat: 'Боковой чат (бета)',
298
300
  sideChatNew: 'Новый поток',
299
301
  sideChatUntitled: 'Новый поток',
@@ -321,6 +323,8 @@ export const ru: Record<string, string> = {
321
323
  jobs: 'Фоновые задачи',
322
324
  jobsCount: '{count} фоновых задач',
323
325
  jobsCountRunning: '{count} фоновых задач · {running} выполняется',
326
+ jobsShowHistory: 'Показать {count} более ранних фоновых задач',
327
+ jobsHideHistory: 'Свернуть более ранние фоновые задачи',
324
328
  jobStatusRunning: 'Выполняется',
325
329
  jobStatusStopping: 'Останавливается',
326
330
  jobStatusCompleted: 'Завершено',
@@ -279,6 +279,8 @@ export const sv: Record<string, string> = {
279
279
  subagentDiagUnsupported: 'Stöds ej',
280
280
  subagentDiagUnavailable: 'Otillgänglig',
281
281
  subagentThinking: 'Tänker…',
282
+ subagentShowHistory: 'Visa {count} tidigare subagenter',
283
+ subagentHideHistory: 'Fäll ihop tidigare subagenter',
282
284
  sideChat: 'Sidochatt (beta)',
283
285
  sideChatNew: 'Ny tråd',
284
286
  sideChatUntitled: 'Ny tråd',
@@ -306,6 +308,8 @@ export const sv: Record<string, string> = {
306
308
  jobs: 'Bakgrundsjobb',
307
309
  jobsCount: '{count} bakgrundsjobb',
308
310
  jobsCountRunning: '{count} bakgrundsjobb · {running} kör',
311
+ jobsShowHistory: 'Visa {count} tidigare bakgrundsjobb',
312
+ jobsHideHistory: 'Fäll ihop tidigare bakgrundsjobb',
309
313
  jobStatusRunning: 'Kör',
310
314
  jobStatusStopping: 'Stoppar',
311
315
  jobStatusCompleted: 'Klar',
@@ -296,6 +296,8 @@ export const th: Record<string, string> = {
296
296
  subagentDiagUnsupported: 'ไม่รองรับ',
297
297
  subagentDiagUnavailable: 'ไม่พร้อมใช้งาน',
298
298
  subagentThinking: 'กำลังคิด…',
299
+ subagentShowHistory: 'แสดงตัวแทนย่อยก่อนหน้า {count} รายการ',
300
+ subagentHideHistory: 'ย่อตัวแทนย่อยก่อนหน้า',
299
301
  sideChat: 'แชทด้านข้าง (เบต้า)',
300
302
  sideChatNew: 'เธรดใหม่',
301
303
  sideChatUntitled: 'เธรดใหม่',
@@ -323,6 +325,8 @@ export const th: Record<string, string> = {
323
325
  jobs: 'งานเบื้องหลัง',
324
326
  jobsCount: '{count} งานเบื้องหลัง',
325
327
  jobsCountRunning: '{count} งานเบื้องหลัง · {running} กำลังทำงาน',
328
+ jobsShowHistory: 'แสดงงานเบื้องหลังก่อนหน้า {count} รายการ',
329
+ jobsHideHistory: 'ย่องานเบื้องหลังก่อนหน้า',
326
330
  jobStatusRunning: 'กำลังทำงาน',
327
331
  jobStatusStopping: 'กำลังหยุด',
328
332
  jobStatusCompleted: 'เสร็จสิ้น',
@@ -296,6 +296,8 @@ export const tr: Record<string, string> = {
296
296
  subagentDiagUnsupported: 'Desteklenmiyor',
297
297
  subagentDiagUnavailable: 'Kullanılamıyor',
298
298
  subagentThinking: 'Düşünüyor…',
299
+ subagentShowHistory: 'Önceki {count} alt aracıyı göster',
300
+ subagentHideHistory: 'Önceki alt araçları daralt',
299
301
  sideChat: 'Yan sohbet (beta)',
300
302
  sideChatNew: 'Yeni iş parçacığı',
301
303
  sideChatUntitled: 'Yeni iş parçacığı',
@@ -323,6 +325,8 @@ export const tr: Record<string, string> = {
323
325
  jobs: 'Arka plan işleri',
324
326
  jobsCount: '{count} arka plan işi',
325
327
  jobsCountRunning: '{count} arka plan işi · {running} çalışıyor',
328
+ jobsShowHistory: 'Önceki {count} arka plan işini göster',
329
+ jobsHideHistory: 'Önceki arka plan işlerini daralt',
326
330
  jobStatusRunning: 'Çalışıyor',
327
331
  jobStatusStopping: 'Durduruluyor',
328
332
  jobStatusCompleted: 'Tamamlandı',
@@ -296,6 +296,8 @@ export const vi: Record<string, string> = {
296
296
  subagentDiagUnsupported: 'Không hỗ trợ',
297
297
  subagentDiagUnavailable: 'Không khả dụng',
298
298
  subagentThinking: 'Đang suy nghĩ…',
299
+ subagentShowHistory: 'Hiện {count} tác nhân con cũ hơn',
300
+ subagentHideHistory: 'Thu gọn tác nhân con cũ hơn',
299
301
  sideChat: 'Chat bên (beta)',
300
302
  sideChatNew: 'Luồng mới',
301
303
  sideChatUntitled: 'Luồng mới',
@@ -323,6 +325,8 @@ export const vi: Record<string, string> = {
323
325
  jobs: 'Tác vụ nền',
324
326
  jobsCount: '{count} tác vụ nền',
325
327
  jobsCountRunning: '{count} tác vụ nền · {running} đang chạy',
328
+ jobsShowHistory: 'Hiện {count} tác vụ nền cũ hơn',
329
+ jobsHideHistory: 'Thu gọn tác vụ nền cũ hơn',
326
330
  jobStatusRunning: 'Đang chạy',
327
331
  jobStatusStopping: 'Đang dừng',
328
332
  jobStatusCompleted: 'Đã hoàn thành',
@@ -311,6 +311,8 @@ export const zhHK: Record<string, string> = {
311
311
  subagentDiagUnsupported: '不支援的條目',
312
312
  subagentDiagUnavailable: '不可用',
313
313
  subagentThinking: '思考中…',
314
+ subagentShowHistory: '展開較早的 {count} 個子代理',
315
+ subagentHideHistory: '收起較早的子代理',
314
316
  sideChat: '側邊對話(beta)',
315
317
  sideChatNew: '新增對話',
316
318
  sideChatUntitled: '新對話',
@@ -338,6 +340,8 @@ export const zhHK: Record<string, string> = {
338
340
  jobs: '背景任務',
339
341
  jobsCount: '{count} 個背景任務',
340
342
  jobsCountRunning: '{count} 個背景任務 · {running} 執行中',
343
+ jobsShowHistory: '展開較早的 {count} 個背景任務',
344
+ jobsHideHistory: '收起較早的背景任務',
341
345
  jobStatusRunning: '執行中',
342
346
  jobStatusStopping: '終止中',
343
347
  jobStatusCompleted: '已完成',
@@ -311,6 +311,8 @@ export const zhMO: Record<string, string> = {
311
311
  subagentDiagUnsupported: '不支援的條目',
312
312
  subagentDiagUnavailable: '不可用',
313
313
  subagentThinking: '思考中…',
314
+ subagentShowHistory: '展開較早的 {count} 個子代理',
315
+ subagentHideHistory: '收起較早的子代理',
314
316
  sideChat: '側邊對話(beta)',
315
317
  sideChatNew: '新增對話',
316
318
  sideChatUntitled: '新對話',
@@ -338,6 +340,8 @@ export const zhMO: Record<string, string> = {
338
340
  jobs: '背景任務',
339
341
  jobsCount: '{count} 個背景任務',
340
342
  jobsCountRunning: '{count} 個背景任務 · {running} 執行中',
343
+ jobsShowHistory: '展開較早的 {count} 個背景任務',
344
+ jobsHideHistory: '收起較早的背景任務',
341
345
  jobStatusRunning: '執行中',
342
346
  jobStatusStopping: '終止中',
343
347
  jobStatusCompleted: '已完成',
@@ -311,6 +311,8 @@ export const zhTW: Record<string, string> = {
311
311
  subagentDiagUnsupported: '不支援的條目',
312
312
  subagentDiagUnavailable: '不可用',
313
313
  subagentThinking: '思考中…',
314
+ subagentShowHistory: '展開較早的 {count} 個子代理',
315
+ subagentHideHistory: '收起較早的子代理',
314
316
  sideChat: '側邊對話(beta)',
315
317
  sideChatNew: '新增對話',
316
318
  sideChatUntitled: '新對話',
@@ -338,6 +340,8 @@ export const zhTW: Record<string, string> = {
338
340
  jobs: '背景任務',
339
341
  jobsCount: '{count} 個背景任務',
340
342
  jobsCountRunning: '{count} 個背景任務 · {running} 執行中',
343
+ jobsShowHistory: '展開較早的 {count} 個背景任務',
344
+ jobsHideHistory: '收起較早的背景任務',
341
345
  jobStatusRunning: '執行中',
342
346
  jobStatusStopping: '終止中',
343
347
  jobStatusCompleted: '已完成',
@@ -303,6 +303,8 @@ export const zh = {
303
303
  subagentDiagUnsupported: '不支持的条目',
304
304
  subagentDiagUnavailable: '不可用',
305
305
  subagentThinking: '思考中…',
306
+ subagentShowHistory: '展开更早的 {count} 个子代理',
307
+ subagentHideHistory: '收起更早的子代理',
306
308
  sideChat: '侧边对话(beta)',
307
309
  sideChatNew: '新建对话',
308
310
  sideChatUntitled: '新对话',
@@ -330,6 +332,8 @@ export const zh = {
330
332
  jobs: '后台任务',
331
333
  jobsCount: '{count} 个后台任务',
332
334
  jobsCountRunning: '{count} 个后台任务 · {running} 运行中',
335
+ jobsShowHistory: '展开更早的 {count} 个后台任务',
336
+ jobsHideHistory: '收起更早的后台任务',
333
337
  jobStatusRunning: '运行中',
334
338
  jobStatusStopping: '终止中',
335
339
  jobStatusCompleted: '已完成',
@@ -655,6 +659,8 @@ export const en: Record<keyof typeof zh, string> = {
655
659
  subagentDiagUnsupported: 'Unsupported',
656
660
  subagentDiagUnavailable: 'Unavailable',
657
661
  subagentThinking: 'Thinking…',
662
+ subagentShowHistory: 'Show {count} earlier subagents',
663
+ subagentHideHistory: 'Collapse earlier subagents',
658
664
  sideChat: 'Side Chat (beta)',
659
665
  sideChatNew: 'New thread',
660
666
  sideChatUntitled: 'New thread',
@@ -682,6 +688,8 @@ export const en: Record<keyof typeof zh, string> = {
682
688
  jobs: 'Background jobs',
683
689
  jobsCount: '{count} background jobs',
684
690
  jobsCountRunning: '{count} background jobs · {running} running',
691
+ jobsShowHistory: 'Show {count} earlier jobs',
692
+ jobsHideHistory: 'Collapse earlier jobs',
685
693
  jobStatusRunning: 'Running',
686
694
  jobStatusStopping: 'Stopping',
687
695
  jobStatusCompleted: 'Completed',
@@ -87,11 +87,11 @@ export interface SidebarSessionStore {
87
87
  get(id: string): {
88
88
  header: SidebarSessionHeader
89
89
  /**
90
- * The live session's append-only event log (immutable snapshot; absent
90
+ * The live session's immutable event snapshot (0.1.5 Session API; absent
91
91
  * on sessions the runtime has not hydrated). Read-only access — the
92
92
  * jobs.output route replays `job_output` tool/result rows from it.
93
93
  */
94
- events?: readonly SidebarSessionEvent[]
94
+ snapshotEvents?(fromSeq?: number, toSeqExclusive?: number): readonly SidebarSessionEvent[]
95
95
  } | undefined
96
96
  }
97
97
 
@@ -295,13 +295,18 @@ export interface SidebarSessionTitleService {
295
295
  }
296
296
 
297
297
  /** The host session-persistence face (mirror of the sessionPersistence
298
- * service): detached inspection of a persisted session, used to compose the
299
- * recorded preset when a Side Chat thread cold-resumes. */
300
- export interface SidebarSessionPersistenceService {
301
- inspect(sessionId: string): Promise<{
302
- meta: { cwd?: string; agentPreset?: string }
298
+ * service, 0.1.5 handle-seam form): a short-lived read handle over one
299
+ * persisted session, used to compose the recorded preset when a Side Chat
300
+ * thread cold-resumes. */
301
+ export interface SidebarSessionPersistenceHandle {
302
+ readonly header: { cwd?: string; agentPreset?: string }
303
+ read(fromSeq?: number, toSeqExclusive?: number, options?: { signal?: AbortSignal }): Promise<{
303
304
  events: readonly SidebarSessionEvent[]
304
305
  }>
306
+ close(): Promise<void>
307
+ }
308
+ export interface SidebarSessionPersistenceService {
309
+ open(sessionId: string, access: 'read', options?: { signal?: AbortSignal }): Promise<SidebarSessionPersistenceHandle>
305
310
  }
306
311
 
307
312
  /** RPC result slot mirror (`RpcResult<T>` on the wire). */
package/src/index.ts CHANGED
@@ -18,7 +18,7 @@ import { basename, dirname, extname, isAbsolute, join } from 'node:path'
18
18
  import type { IncomingMessage } from 'node:http'
19
19
  import type { Duplex } from 'node:stream'
20
20
  import { WebSocket, WebSocketServer } from 'ws'
21
- import type { Context, SidebarHttpRequest } from './context-types.ts'
21
+ import type { Context, SidebarHttpRequest, SidebarSessionPersistenceService } from './context-types.ts'
22
22
  import {
23
23
  Config,
24
24
  PrefsSchema,
@@ -126,10 +126,11 @@ async function sessionCwdOf(ctx: Context, sessionId: string, clientCwd?: string)
126
126
  throw new SidebarError('bad-request', `invalid working directory "${clientCwd}"`)
127
127
  }
128
128
  }
129
- const persistence = ctx.get('sessionPersistence')
129
+ const persistence = ctx.get('sessionPersistence') as SidebarSessionPersistenceService | undefined
130
130
  if (persistence !== undefined) {
131
- const inspected = await persistence.inspect(sessionId)
132
- const metaCwd = inspected.meta.cwd
131
+ const handle = await persistence.open(sessionId, 'read')
132
+ const metaCwd = handle.header.cwd
133
+ await handle.close()
133
134
  if (metaCwd !== undefined && metaCwd !== '') {
134
135
  try {
135
136
  return requireAbsolute(metaCwd)
@@ -135,7 +135,7 @@ const MIRROR_MAX_ENTRIES = 200
135
135
  * The live job_output mirror: subscribes to the session append feed and
136
136
  * caches the job_output traces the session store's own log can lag behind
137
137
  * (after a host restart the store session stays frozen at its rehydration
138
- * boundary, so `session.events` misses everything appended since — the very
138
+ * boundary, so a stale snapshot misses everything appended since — the very
139
139
  * reads the pane exists to show). Zero DSH writes: the api-proxy pushes the
140
140
  * same feed to browsers.
141
141
  */
@@ -211,7 +211,8 @@ export function buildJobsApi(ctx: Context, outputLimit: number): SidebarJobsRout
211
211
  // Merge the store's event log (durable seed + whatever it received)
212
212
  // with the live mirror, deduped by seq — a trace never double-counts.
213
213
  const bySeq = new Map<number, JobOutputTrace>()
214
- for (const event of ctx.sessions.get(sessionId)?.events ?? []) {
214
+ const store = ctx.sessions.get(sessionId)
215
+ for (const event of (store?.snapshotEvents !== undefined ? store.snapshotEvents() : []) ?? []) {
215
216
  const trace = traceOf(event)
216
217
  if (trace !== undefined) bySeq.set(trace.seq, trace)
217
218
  }
@@ -26,6 +26,7 @@ import type { Agent, AgentSetup, CreateAgentOptions, ResumeAgentOptions } from '
26
26
  import { snapshotSubagentDescriptor } from '@deepseek-ai/dsh-subagent'
27
27
  import type { Context as CordisContext } from '@deepseek-ai/cordis'
28
28
  import type { SessionEvent, SessionId } from '@deepseek-ai/dsh-session'
29
+ import type { SidebarSessionEvent } from './context-types.ts'
29
30
  import type {
30
31
  Context,
31
32
  SidebarAgentPresetsService,
@@ -104,8 +105,10 @@ async function composePersistedSetup(
104
105
  if (persistence === undefined) {
105
106
  return () => Promise.resolve()
106
107
  }
107
- const inspected = await persistence.inspect(childId)
108
- const presetId = resolvePresetId(inspected.meta, inspected.events)
108
+ const handle = await persistence.open(childId, 'read')
109
+ const { events } = await handle.read()
110
+ const presetId = resolvePresetId(handle.header as never, events as unknown as readonly SidebarSessionEvent[])
111
+ await handle.close()
109
112
  const presets = ctx.get('agentPresets') as SidebarAgentPresetsService | undefined
110
113
  if (presets === undefined || presetId === undefined) {
111
114
  return () => Promise.resolve()
@@ -166,11 +169,11 @@ export function buildSidechatApi(ctx: Context): SidechatRoutes {
166
169
  }
167
170
  const parentSession = parent.session
168
171
  const inheritance = buildSidechatInheritance(
169
- parentSession.events as unknown as readonly SidechatLogEvent[],
172
+ parentSession.snapshotEvents() as unknown as readonly SidechatLogEvent[],
170
173
  )
171
174
  const { agentPreset, setup } = await composeChildSetup(
172
175
  ctx,
173
- resolvePresetId(parentSession.header, parentSession.events),
176
+ resolvePresetId(parentSession.header, parentSession.snapshotEvents()),
174
177
  )
175
178
  const childId = `session-${randomUUID()}` as SessionId
176
179
  const label = question === '' ? SIDE_NEW_THREAD_TITLE : sideLabel(question)
@@ -198,7 +201,7 @@ export function buildSidechatApi(ctx: Context): SidechatRoutes {
198
201
  meta: {
199
202
  ...(parentSession.header.cwd === undefined ? {} : { cwd: parentSession.header.cwd }),
200
203
  parentSession: parentSession.id,
201
- seedLength: seed.length,
204
+ isSeeded: seed.length > 0,
202
205
  origin: 'subagent',
203
206
  delegationDepth: (parentSession.header.delegationDepth ?? 0) + 1,
204
207
  ...(agentPreset === undefined ? {} : { agentPreset }),
@@ -267,7 +270,7 @@ export function buildSidechatApi(ctx: Context): SidechatRoutes {
267
270
  throw new SidebarError('sidechat-error', `thread resume failed: ${error instanceof Error ? error.message : String(error)}`, 500)
268
271
  }
269
272
  }
270
- if (boundaryDelivered(agent.session.events as unknown as readonly SidechatLogEvent[])) {
273
+ if (boundaryDelivered(agent.session.snapshotEvents() as unknown as readonly SidechatLogEvent[])) {
271
274
  admitFollowup(agent, textPrompt(text))
272
275
  } else {
273
276
  // First message of an immediately-created thread: it carries the
@@ -331,8 +334,10 @@ export function buildSidechatApi(ctx: Context): SidechatRoutes {
331
334
  const persistence = ctx.get('sessionPersistence') as SidebarSessionPersistenceService | undefined
332
335
  if (persistence !== undefined) {
333
336
  try {
334
- const inspected = await persistence.inspect(childId)
335
- const preset = resolvePresetId(inspected.meta, inspected.events)
337
+ const handle = await persistence.open(childId, 'read')
338
+ const { events } = await handle.read()
339
+ const preset = resolvePresetId(handle.header as never, events as unknown as readonly SidebarSessionEvent[])
340
+ await handle.close()
336
341
  return { live: false, ...(preset === undefined ? {} : { preset }) }
337
342
  } catch {
338
343
  // Unknown/gone session: report a bare cold info.
@@ -76,8 +76,9 @@ export function buildSubagentLiveApi(ctx: Context): SidebarSubagentLiveRoutes {
76
76
  // never topology — keep them out of the live map too.
77
77
  if (entry.label?.startsWith(SIDE_LABEL_PREFIX) ?? false) continue
78
78
  try {
79
+ const stored = ctx.sessions.get(entry.id)
79
80
  const activity = lastActivity(
80
- ctx.sessions.get(entry.id)?.events ?? [],
81
+ stored?.snapshotEvents !== undefined ? stored.snapshotEvents() : [],
81
82
  LIVE_WINDOW_MESSAGES,
82
83
  )
83
84
  if (activity.text !== undefined || activity.tool !== undefined) {