dsh-side-chat-plus 0.4.0-alpha.2 → 0.4.1

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.
@@ -1,454 +1,464 @@
1
- /**
2
- * Structural types for the cordis services this plugin consumes, plus the
3
- * Context augmentation both halves share. A third-party plugin resolves
4
- * outside the DSH monorepo's single cordis instance, so the upstream
5
- * `declare module 'cordis'` augmentations do not reach this Context; the
6
- * members below mirror the actual runtime shapes this plugin touches.
7
- *
8
- * The `sessions` field is a union of the HOST store face (get/list) and the
9
- * CLIENT list feed (list.getSnapshot/subscribe): each half only touches its
10
- * own side, and the shared declaration keeps the two cordis instance layers
11
- * from colliding under one tsconfig.
12
- */
13
- import type { IncomingMessage, ServerResponse } from 'node:http'
14
- import type { Context } from 'cordis'
15
-
16
- /** One named webserver route. */
17
- export interface SideWebRoute {
18
- kind: 'exact' | 'prefix'
19
- path: string
20
- handler: (req: IncomingMessage, res: ServerResponse) => void | Promise<void>
21
- }
22
-
23
- /** The webServer service face this plugin uses. */
24
- export interface SideWebServer {
25
- register(route: SideWebRoute): () => void
26
- }
27
-
28
- /** A published session's header slice (authoritative cwd, lineage, origin). */
29
- export interface SideSessionHeader {
30
- cwd?: string
31
- parentSession?: string
32
- origin?: 'subagent'
33
- delegationDepth?: number
34
- }
35
-
36
- /** One session event (fold source for history and permission current). */
37
- export interface SideSessionEvent {
38
- type: string
39
- seq: number
40
- time: number
41
- data: Record<string, unknown>
42
- surfaceOp?: 'append' | 'replace' | 'remove'
43
- sourceEventSeqs?: number[]
44
- }
45
-
46
- /**
47
- * The live session face the host reads. Event reads go through
48
- * `sessionQuery.readSession` instead: DSH 0.1.6 deprecated the Session's
49
- * synchronous event getters (`events` before 0.1.5, `snapshotEvents` after).
50
- */
51
- export interface SideSession {
52
- id: string
53
- header: SideSessionHeader
54
- requestHeader?: () => { config?: { provider?: string; model?: string; reasoningEffort?: string; maxTokens?: number } } | undefined
55
- }
56
-
57
- /** The host session store face (`ctx.sessions` host side). */
58
- export interface SideSessionStore {
59
- get(id: string): SideSession | undefined
60
- list(): SideSession[]
61
- }
62
-
63
- /** One session list row (client list feed). */
64
- export interface SideSessionSummary {
65
- id: string
66
- displayTitle: string
67
- cwd?: string
68
- origin?: 'subagent'
69
- parentId?: string
70
- running: boolean
71
- }
72
-
73
- /** The session list snapshot the browser half subscribes to. */
74
- export interface SideSessionList {
75
- /**
76
- * The selected session id. Present through DSH 0.1.6-alpha.1; 0.1.6-alpha.2
77
- * moved the selection out of the list store (multi-instance Client Sessions),
78
- * so it is optional here and read through {@link SideUiSessionService} instead.
79
- */
80
- current?: string | undefined
81
- byId: Record<string, SideSessionSummary>
82
- }
83
-
84
- /** One selectable answer in a user-question dialog. */
85
- export interface SideQuestionOption {
86
- label: string
87
- description?: string
88
- }
89
-
90
- /** One question in a pending user-question dialog. */
91
- export interface SideQuestionItem {
92
- id: string
93
- question: string
94
- detail?: string
95
- header?: string
96
- options?: SideQuestionOption[]
97
- multiSelect?: boolean
98
- }
99
-
100
- /** A pending main-conversation interaction (question / plan-review / approval dialog). */
101
- export interface SidePendingInteraction {
102
- /** Presentation discriminator: the question family, or an approval. */
103
- kind: 'question' | 'plan-review' | 'approval'
104
- /** Opaque render identity and request key (e.g. `question:1`). */
105
- key: string
106
- sessionId: string
107
- /** The request's question list (present for the question family). */
108
- questions?: SideQuestionItem[]
109
- }
110
-
111
- /** The per-session pending-interaction source exposed by the `uiSession` service. */
112
- export interface SidePendingInteractionStore {
113
- getSnapshot(): ReadonlyMap<string, SidePendingInteraction>
114
- subscribe(fn: () => void): () => void
115
- }
116
-
117
- /** The client sessions service face (list feed + scope resolution). */
118
- export interface SideSessionsService {
119
- list: {
120
- getSnapshot(): SideSessionList
121
- subscribe(fn: () => void): () => void
122
- }
123
- /** Resolve an Agent-scoped context view for a listed session id (use-and-discard). */
124
- scope(id: string): Context | undefined
125
- }
126
-
127
- /** Minimal standard binding of one Session scope (`uiSession.adapter.current`). */
128
- export interface SideScopeBinding {
129
- /** The bound session id; absent while no Session is selected. */
130
- readonly key: string | undefined
131
- }
132
-
133
- /** One Session's UI status row (DSH 0.1.6-alpha.2+). */
134
- export interface SideSessionStatus {
135
- /** Highest-precedence pending interaction awaiting the user, if any. */
136
- readonly pendingInteraction?: SidePendingInteraction
137
- }
138
-
139
- /** The client UI-session service face (current Session binding + pending interactions). */
140
- export interface SideUiSessionService {
141
- /**
142
- * Pre-0.1.6-alpha.2 per-session pending-interaction feed. Removed in
143
- * 0.1.6-alpha.2, where the interaction moved onto {@link sessionStatus}.
144
- */
145
- pendingInteractions?: SidePendingInteractionStore
146
- /**
147
- * DSH 0.1.6-alpha.2+ unified Session UI status. The pending interaction is
148
- * `getSnapshot().get(sessionId)?.pendingInteraction`.
149
- */
150
- sessionStatus?: {
151
- getSnapshot(): ReadonlyMap<string, SideSessionStatus>
152
- subscribe(fn: () => void): () => void
153
- }
154
- /**
155
- * Default Session-scope binding (including its absent projection). Its
156
- * `current.key` is the selected Session id — the post-0.1.6-alpha.2 home of
157
- * the selection the sessions list no longer carries.
158
- */
159
- adapter?: {
160
- current: {
161
- getSnapshot(): SideScopeBinding
162
- subscribe(fn: () => void): () => void
163
- }
164
- }
165
- }
166
-
167
- /** Agent options (provider/model/maxTokens). */
168
- export interface SideAgentOptions {
169
- provider?: string
170
- model?: string
171
- maxTokens?: number
172
- }
173
-
174
- /** The live agent face (`ctx.agents.get(id)` / `AgentHandle.agent`). */
175
- export interface SideAgent {
176
- readonly id: string
177
- readonly options: SideAgentOptions
178
- readonly session: SideSession
179
- readonly status: string
180
- readonly ctx: Context
181
- followup(message: unknown): void
182
- inject(message: unknown): void
183
- cancel(cause: { kind: 'user' | 'parent' | 'disposed' } | { kind: 'hook'; reason: string }): void
184
- whenIdle(): Promise<void>
185
- }
186
-
187
- /** The agent handle `ctx.agents.create` resolves (owner tears the agent down). */
188
- export interface SideAgentHandle {
189
- agent: SideAgent
190
- dispose(): Promise<void>
191
- }
192
-
193
- /** `ctx.agents.create` options (mirror of CreateAgentOptions). */
194
- export interface SideCreateAgentOptions {
195
- sessionId: string
196
- meta?: {
197
- cwd?: string
198
- parentSession?: string
199
- agentPreset?: string
200
- }
201
- agentOptions?: SideAgentOptions
202
- setup?: (agentCtx: Context) => void | Promise<void>
203
- }
204
-
205
- /** The host agent registry face. */
206
- export interface SideAgentsService {
207
- get(id: string): SideAgent | undefined
208
- create(options: SideCreateAgentOptions): Promise<SideAgentHandle>
209
- }
210
-
211
- /** Live provider / model / reasoning-effort selection for one agent. */
212
- export interface SideModelSelection {
213
- provider: string
214
- model: string
215
- reasoningEffort?: string
216
- }
217
-
218
- /**
219
- * Mutable selection plus the value captured when the current step entered
220
- * prompt assembly (`current` / `assembled`).
221
- */
222
- export interface SideModelSelectionRef {
223
- current: SideModelSelection | undefined
224
- assembled: SideModelSelection | undefined
225
- }
226
-
227
- /**
228
- * Couple a mutable selection to an agent's prompt assembly and request routing
229
- * (`installModelSelection` on the agent package). Typed structurally rather
230
- * than imported: this plugin resolves outside the DSH monorepo's single cordis
231
- * instance, so the upstream export is reached through a loose signature.
232
- */
233
- export type SideInstallModelSelection = (agentCtx: Context, selection: SideModelSelectionRef) => () => void
234
-
235
- /** The workspace registry face (archive a session durably). */
236
- export interface SideWorkspaceRegistry {
237
- archiveSession(sessionId: string): Promise<void>
238
- }
239
-
240
- /** `sessionQuery.readSession` snapshot. */
241
- export interface SideSessionLogSnapshot {
242
- session: SideSessionHeader
243
- events: SideSessionEvent[]
244
- }
245
-
246
- /** The session query face. */
247
- export interface SideSessionQuery {
248
- readSession(sessionId: string): Promise<SideSessionLogSnapshot>
249
- }
250
-
251
- /** One permission preset option. */
252
- export interface SidePresetOption {
253
- value: string
254
- name: string
255
- description?: string
256
- }
257
-
258
- /** The permission presets face (`current` reads the SESSION, not event rows). */
259
- export interface SidePermissionPresets {
260
- current(session: SideSession): string
261
- set(session: SideSession, name: string): void
262
- /** 0.1.6+: process-level catalog of selectable presets. */
263
- catalog?(): { options: SidePresetOption[] }
264
- /** 0.1.6+: the preset selected as the default for future sessions. */
265
- defaultPreset?: string
266
- /** 0.1.5 and earlier: combined catalog plus current value. Removed in 0.1.6. */
267
- selectFor?(state: unknown): { options: SidePresetOption[]; currentValue: string }
268
- }
269
-
270
- /** The agent presets face (composeFrom joins a child to the parent's composition). */
271
- export interface SideAgentPresets {
272
- composeFrom(agentCtx: Context, parentCtx: Context): string | undefined
273
- }
274
-
275
- /** One provider route. */
276
- export interface SideLlmProvider {
277
- id: string
278
- name: string
279
- }
280
-
281
- /** One model entry. */
282
- export interface SideLlmModel {
283
- provider: string
284
- id: string
285
- name: string
286
- description?: string
287
- }
288
-
289
- /** One reasoning-effort entry. */
290
- export interface SideLlmEffort {
291
- id: string
292
- name: string
293
- description?: string
294
- }
295
-
296
- /** One model-request stream chunk (minimal structural view for text collection). */
297
- export interface SideLlmStreamChunk {
298
- type: string
299
- text?: string
300
- }
301
-
302
- /** Minimal generate options the summarize route builds (a hand-built user prompt). */
303
- export interface SideLlmGenerateOptions {
304
- provider: string
305
- model: string
306
- reasoningEffort?: string
307
- maxTokens?: number
308
- signal?: AbortSignal
309
- messages: Array<{
310
- id?: string
311
- role: 'user' | 'assistant' | 'system'
312
- content: Array<{ type: 'text'; text: string }>
313
- source?: { kind: string }
314
- }>
315
- }
316
-
317
- /** The llm face (model/effort catalog + one-shot streaming calls). */
318
- export interface SideLlm {
319
- listProviders(): SideLlmProvider[]
320
- listModels(provider: string): Promise<SideLlmModel[]>
321
- resolveModelInfo(provider: string, model: string): Promise<{
322
- provider: string
323
- id: string
324
- name: string
325
- reasoning?: { efforts: readonly SideLlmEffort[]; defaultEffort?: string }
326
- }>
327
- stream(options: SideLlmGenerateOptions): AsyncIterable<SideLlmStreamChunk>
328
- }
329
-
330
- /** The client locale service face. */
331
- export interface SideLocaleService {
332
- getSnapshot(): { active: string }
333
- subscribe(fn: () => void): () => void
334
- register(ns: string, locale: string, dict: Record<string, string>): () => void
335
- }
336
-
337
- /** The host settings service face (namespace registration + read/write). */
338
- export interface SideSettingsService {
339
- register(ns: unknown, schema: unknown): { get(): unknown; watch(cb: (next: unknown, prev: unknown) => void): () => void }
340
- describe(opts: { redactSecrets?: boolean }): Array<{ ns: unknown; value?: unknown; revision?: number }>
341
- update(ns: unknown, patch: Record<string, unknown>, expectedRevision?: number): Promise<void>
342
- }
343
-
344
- /** The client slots service face (settings.section registration). */
345
- export interface SideSlotsService {
346
- inject(name: string, factory: () => () => void): () => void
347
- register(options: Record<string, unknown>, component: unknown): () => void
348
- }
349
-
350
- /** One right-sidebar tab type definition (dsh-client-ui-sidebar-right contract, mirror). */
351
- export interface SideTabDefinition {
352
- /** Stable unique key; the body seat entry registers under the same key. */
353
- id: string
354
- /** Discriminator used by `openTab(kind)` and the pane dispatch. */
355
- kind: string
356
- /** Registry band ('builtin' | 'extension' | 'fallback'); defaults to the extension band. */
357
- priority?: string
358
- /** Fresh title for the tab chip captured at open time. */
359
- title(address: string): string
360
- }
361
-
362
- /** The right-sidebar tab-type registry face (`ctx.sidebarRight.tabs`). */
363
- export interface SideSidebarRightTabs {
364
- /** Register a tab type; returns a disposer (hold it in the caller's ctx.effect). */
365
- register(definition: SideTabDefinition): () => void
366
- }
367
-
368
- /** The cross-plugin right-sidebar face (`ctx.sidebarRight`, ui-sidebar-right). */
369
- export interface SideSidebarRight {
370
- /**
371
- * The controller's tab registry. TypeScript-private upstream (it works at
372
- * runtime, but the standalone `sidebarRightTabs` service is the public
373
- * home), so optional here.
374
- */
375
- tabs?: SideSidebarRightTabs
376
- /** Open a page type by kind in the mounted session; reveals the column. */
377
- openTab(kind: string, options?: { paneId?: string; replaceTab?: boolean; revealIfOpened?: boolean }): void
378
- }
379
-
380
- /** One durable image reference (mirror of ImageAttachmentRef). */
381
- export interface SideImageAttachmentRef {
382
- attachmentId: string
383
- mediaType: 'image/png' | 'image/jpeg' | 'image/webp' | 'image/gif'
384
- bytes: number
385
- width: number
386
- height: number
387
- name?: string
388
- }
389
-
390
- /** The host attachment store face (`ctx.attachments`). */
391
- export interface SideAttachmentStore {
392
- readonly imageLimits: {
393
- maxImageBytes: number
394
- maxImagesPerMessage: number
395
- maxMessageImageBytes: number
396
- maxImagePixels: number
397
- /** 0.1.6+ per-image intrinsic width/height ceiling; absent on earlier lines. */
398
- maxImageDimension?: number
399
- mediaTypes: readonly string[]
400
- }
401
- validateImage(input: { data: Uint8Array; mediaType: string; name?: string }): Promise<void>
402
- saveImage(input: { data: Uint8Array; mediaType: string; name?: string }): Promise<SideImageAttachmentRef>
403
- readImage(ref: SideImageAttachmentRef): Promise<{ ref: SideImageAttachmentRef; data: Uint8Array }>
404
- }
405
-
406
- /** The host command registry face (`ctx.commands`). */
407
- export interface SideCommandsService {
408
- list(agent: SideAgent): Array<{ name: string; description: string }>
409
- execute(agent: SideAgent, line: string, submittedAttachments: readonly unknown[], signal: AbortSignal): Promise<unknown>
410
- }
411
-
412
- /** The per-session composer input face this plugin writes to (draft-only). */
413
- export interface SideSessionInput {
414
- /** Replace the session composer draft (never submits). */
415
- setDraft(text: string): void
416
- /** Live input state store (draft read). */
417
- state: { getSnapshot(): { draft: string } }
418
- /** Surface a notice on the session composer. */
419
- notify(level: 'info' | 'error', text: string): void
420
- }
421
-
422
- /** The conversation service face (`ctx.conversation`) — input registry only. */
423
- export interface SideConversationService {
424
- input: {
425
- /** Resolve the input facade for one session-scope context. */
426
- for(actx: Context): SideSessionInput
427
- }
428
- }
429
-
430
- declare module 'cordis' {
431
- interface Context {
432
- webServer: SideWebServer
433
- sessions: SideSessionStore & SideSessionsService
434
- agents: SideAgentsService
435
- workspaceRegistry: SideWorkspaceRegistry
436
- sessionQuery: SideSessionQuery
437
- permissionPresets: SidePermissionPresets
438
- agentPresets: SideAgentPresets
439
- llm: SideLlm
440
- locale: SideLocaleService
441
- settings: SideSettingsService
442
- slots: SideSlotsService
443
- attachments: SideAttachmentStore
444
- commands: SideCommandsService
445
- conversation: SideConversationService
446
- uiSession: SideUiSessionService
447
- inject(deps: string[], callback: (ctx: Context) => void): void
448
- get(name: string): unknown | undefined
449
- on(name: string, listener: (...args: any[]) => any): () => void
450
- effect(fn: () => void | (() => void), label?: string): void
451
- }
452
- }
453
-
454
- export type { Context }
1
+ /**
2
+ * Structural types for the cordis services this plugin consumes, plus the
3
+ * Context augmentation both halves share. A third-party plugin resolves
4
+ * outside the DSH monorepo's single cordis instance, so the upstream
5
+ * `declare module 'cordis'` augmentations do not reach this Context; the
6
+ * members below mirror the actual runtime shapes this plugin touches.
7
+ *
8
+ * The `sessions` field is a union of the HOST store face (get/list) and the
9
+ * CLIENT list feed (list.getSnapshot/subscribe): each half only touches its
10
+ * own side, and the shared declaration keeps the two cordis instance layers
11
+ * from colliding under one tsconfig.
12
+ */
13
+ import type { IncomingMessage, ServerResponse } from 'node:http'
14
+ import type { Context } from 'cordis'
15
+
16
+ /** One named webserver route. */
17
+ export interface SideWebRoute {
18
+ kind: 'exact' | 'prefix'
19
+ path: string
20
+ handler: (req: IncomingMessage, res: ServerResponse) => void | Promise<void>
21
+ }
22
+
23
+ /** The webServer service face this plugin uses. */
24
+ export interface SideWebServer {
25
+ register(route: SideWebRoute): () => void
26
+ }
27
+
28
+ /** A published session's header slice (authoritative cwd, lineage, origin). */
29
+ export interface SideSessionHeader {
30
+ cwd?: string
31
+ parentSession?: string
32
+ origin?: 'subagent'
33
+ delegationDepth?: number
34
+ }
35
+
36
+ /** One session event (fold source for history and permission current). */
37
+ export interface SideSessionEvent {
38
+ type: string
39
+ seq: number
40
+ time: number
41
+ data: Record<string, unknown>
42
+ surfaceOp?: 'append' | 'replace' | 'remove'
43
+ sourceEventSeqs?: number[]
44
+ }
45
+
46
+ /**
47
+ * The live session face the host reads. Event reads go through
48
+ * `sessionQuery.readSession` instead: DSH 0.1.6 deprecated the Session's
49
+ * synchronous event getters (`events` before 0.1.5, `snapshotEvents` after).
50
+ */
51
+ export interface SideSession {
52
+ id: string
53
+ header: SideSessionHeader
54
+ requestHeader?: () => { config?: { provider?: string; model?: string; reasoningEffort?: string; maxTokens?: number } } | undefined
55
+ }
56
+
57
+ /** The host session store face (`ctx.sessions` host side). */
58
+ export interface SideSessionStore {
59
+ get(id: string): SideSession | undefined
60
+ list(): SideSession[]
61
+ }
62
+
63
+ /** One session list row (client list feed). */
64
+ export interface SideSessionSummary {
65
+ id: string
66
+ displayTitle: string
67
+ cwd?: string
68
+ origin?: 'subagent'
69
+ parentId?: string
70
+ running: boolean
71
+ }
72
+
73
+ /** The session list snapshot the browser half subscribes to. */
74
+ export interface SideSessionList {
75
+ /**
76
+ * The selected session id. Present through DSH 0.1.6-alpha.1; 0.1.6-alpha.2
77
+ * moved the selection out of the list store (multi-instance Client Sessions),
78
+ * so it is optional here and read through {@link SideUiSessionService} instead.
79
+ */
80
+ current?: string | undefined
81
+ byId: Record<string, SideSessionSummary>
82
+ }
83
+
84
+ /** One selectable answer in a user-question dialog. */
85
+ export interface SideQuestionOption {
86
+ label: string
87
+ description?: string
88
+ }
89
+
90
+ /** One question in a pending user-question dialog. */
91
+ export interface SideQuestionItem {
92
+ id: string
93
+ question: string
94
+ detail?: string
95
+ header?: string
96
+ options?: SideQuestionOption[]
97
+ multiSelect?: boolean
98
+ }
99
+
100
+ /** A pending main-conversation interaction (question / plan-review / approval dialog). */
101
+ export interface SidePendingInteraction {
102
+ /** Presentation discriminator: the question family, or an approval. */
103
+ kind: 'question' | 'plan-review' | 'approval'
104
+ /** Opaque render identity and request key (e.g. `question:1`). */
105
+ key: string
106
+ sessionId: string
107
+ /** The request's question list (present for the question family). */
108
+ questions?: SideQuestionItem[]
109
+ }
110
+
111
+ /** The per-session pending-interaction source exposed by the `uiSession` service. */
112
+ export interface SidePendingInteractionStore {
113
+ getSnapshot(): ReadonlyMap<string, SidePendingInteraction>
114
+ subscribe(fn: () => void): () => void
115
+ }
116
+
117
+ /** The client sessions service face (list feed + scope resolution). */
118
+ export interface SideSessionsService {
119
+ list: {
120
+ getSnapshot(): SideSessionList
121
+ subscribe(fn: () => void): () => void
122
+ }
123
+ /** Resolve an Agent-scoped context view for a listed session id (use-and-discard). */
124
+ scope(id: string): Context | undefined
125
+ }
126
+
127
+ /** Minimal standard binding of one Session scope (`uiSession.adapter.current`). */
128
+ export interface SideScopeBinding {
129
+ /** The bound session id; absent while no Session is selected. */
130
+ readonly key: string | undefined
131
+ }
132
+
133
+ /** One Session's UI status row (DSH 0.1.6-alpha.2+). */
134
+ export interface SideSessionStatus {
135
+ /** Highest-precedence pending interaction awaiting the user, if any. */
136
+ readonly pendingInteraction?: SidePendingInteraction
137
+ }
138
+
139
+ /** The client UI-session service face (current Session binding + pending interactions). */
140
+ export interface SideUiSessionService {
141
+ /**
142
+ * Pre-0.1.6-alpha.2 per-session pending-interaction feed. Removed in
143
+ * 0.1.6-alpha.2, where the interaction moved onto {@link sessionStatus}.
144
+ */
145
+ pendingInteractions?: SidePendingInteractionStore
146
+ /**
147
+ * DSH 0.1.6-alpha.2+ unified Session UI status. The pending interaction is
148
+ * `getSnapshot().get(sessionId)?.pendingInteraction`.
149
+ */
150
+ sessionStatus?: {
151
+ getSnapshot(): ReadonlyMap<string, SideSessionStatus>
152
+ subscribe(fn: () => void): () => void
153
+ }
154
+ /**
155
+ * Default Session-scope binding (including its absent projection). Its
156
+ * `current.key` is the selected Session id — the post-0.1.6-alpha.2 home of
157
+ * the selection the sessions list no longer carries.
158
+ */
159
+ adapter?: {
160
+ current: {
161
+ getSnapshot(): SideScopeBinding
162
+ subscribe(fn: () => void): () => void
163
+ }
164
+ }
165
+ }
166
+
167
+ /** Agent options (provider/model/maxTokens). */
168
+ export interface SideAgentOptions {
169
+ provider?: string
170
+ model?: string
171
+ maxTokens?: number
172
+ }
173
+
174
+ /** The live agent face (`ctx.agents.get(id)` / `AgentHandle.agent`). */
175
+ export interface SideAgent {
176
+ readonly id: string
177
+ readonly options: SideAgentOptions
178
+ readonly session: SideSession
179
+ readonly status: string
180
+ readonly ctx: Context
181
+ followup(message: unknown): void
182
+ inject(message: unknown): void
183
+ cancel(cause: { kind: 'user' | 'parent' | 'disposed' } | { kind: 'hook'; reason: string }): void
184
+ whenIdle(): Promise<void>
185
+ }
186
+
187
+ /** The agent handle `ctx.agents.create` resolves (owner tears the agent down). */
188
+ export interface SideAgentHandle {
189
+ agent: SideAgent
190
+ dispose(): Promise<void>
191
+ }
192
+
193
+ /** `ctx.agents.create` options (mirror of CreateAgentOptions). */
194
+ export interface SideCreateAgentOptions {
195
+ sessionId: string
196
+ meta?: {
197
+ cwd?: string
198
+ parentSession?: string
199
+ agentPreset?: string
200
+ }
201
+ agentOptions?: SideAgentOptions
202
+ setup?: (agentCtx: Context) => void | Promise<void>
203
+ }
204
+
205
+ /** The host agent registry face. */
206
+ export interface SideAgentsService {
207
+ get(id: string): SideAgent | undefined
208
+ create(options: SideCreateAgentOptions): Promise<SideAgentHandle>
209
+ }
210
+
211
+ /** Live provider / model / reasoning-effort selection for one agent. */
212
+ export interface SideModelSelection {
213
+ provider: string
214
+ model: string
215
+ reasoningEffort?: string
216
+ }
217
+
218
+ /**
219
+ * Mutable selection plus the value captured when the current step entered
220
+ * prompt assembly (`current` / `assembled`).
221
+ */
222
+ export interface SideModelSelectionRef {
223
+ current: SideModelSelection | undefined
224
+ assembled: SideModelSelection | undefined
225
+ }
226
+
227
+ /**
228
+ * Couple a mutable selection to an agent's prompt assembly and request routing
229
+ * (`installModelSelection` on the agent package). Typed structurally rather
230
+ * than imported: this plugin resolves outside the DSH monorepo's single cordis
231
+ * instance, so the upstream export is reached through a loose signature.
232
+ */
233
+ export type SideInstallModelSelection = (agentCtx: Context, selection: SideModelSelectionRef) => () => void
234
+
235
+ /**
236
+ * The workspace registry face. `archiveSession` hides a session from every
237
+ * grouping surface; `unarchiveSession` (0.1.6+) restores it. Both are writable
238
+ * through the registry's serialized operation queue.
239
+ */
240
+ export interface SideWorkspaceRegistry {
241
+ archiveSession(sessionId: string): Promise<void>
242
+ /**
243
+ * Restore one archived session. The plugin lifts the archive for exactly as
244
+ * long as a side-chat turn has to run: DSH 0.1.7 rejects `agent/pre-step` for
245
+ * an archived session, so an archived side chat can never answer.
246
+ */
247
+ unarchiveSession?(sessionId: string): Promise<void>
248
+ }
249
+
250
+ /** `sessionQuery.readSession` snapshot. */
251
+ export interface SideSessionLogSnapshot {
252
+ session: SideSessionHeader
253
+ events: SideSessionEvent[]
254
+ }
255
+
256
+ /** The session query face. */
257
+ export interface SideSessionQuery {
258
+ readSession(sessionId: string): Promise<SideSessionLogSnapshot>
259
+ }
260
+
261
+ /** One permission preset option. */
262
+ export interface SidePresetOption {
263
+ value: string
264
+ name: string
265
+ description?: string
266
+ }
267
+
268
+ /** The permission presets face (`current` reads the SESSION, not event rows). */
269
+ export interface SidePermissionPresets {
270
+ current(session: SideSession): string
271
+ set(session: SideSession, name: string): void
272
+ /** 0.1.6+: process-level catalog of selectable presets. */
273
+ catalog?(): { options: SidePresetOption[] }
274
+ /** 0.1.6+: the preset selected as the default for future sessions. */
275
+ defaultPreset?: string
276
+ /** 0.1.5 and earlier: combined catalog plus current value. Removed in 0.1.6. */
277
+ selectFor?(state: unknown): { options: SidePresetOption[]; currentValue: string }
278
+ }
279
+
280
+ /** The agent presets face (composeFrom joins a child to the parent's composition). */
281
+ export interface SideAgentPresets {
282
+ composeFrom(agentCtx: Context, parentCtx: Context): string | undefined
283
+ }
284
+
285
+ /** One provider route. */
286
+ export interface SideLlmProvider {
287
+ id: string
288
+ name: string
289
+ }
290
+
291
+ /** One model entry. */
292
+ export interface SideLlmModel {
293
+ provider: string
294
+ id: string
295
+ name: string
296
+ description?: string
297
+ }
298
+
299
+ /** One reasoning-effort entry. */
300
+ export interface SideLlmEffort {
301
+ id: string
302
+ name: string
303
+ description?: string
304
+ }
305
+
306
+ /** One model-request stream chunk (minimal structural view for text collection). */
307
+ export interface SideLlmStreamChunk {
308
+ type: string
309
+ text?: string
310
+ }
311
+
312
+ /** Minimal generate options the summarize route builds (a hand-built user prompt). */
313
+ export interface SideLlmGenerateOptions {
314
+ provider: string
315
+ model: string
316
+ reasoningEffort?: string
317
+ maxTokens?: number
318
+ signal?: AbortSignal
319
+ messages: Array<{
320
+ id?: string
321
+ role: 'user' | 'assistant' | 'system'
322
+ content: Array<{ type: 'text'; text: string }>
323
+ source?: { kind: string }
324
+ }>
325
+ }
326
+
327
+ /** The llm face (model/effort catalog + one-shot streaming calls). */
328
+ export interface SideLlm {
329
+ listProviders(): SideLlmProvider[]
330
+ listModels(provider: string): Promise<SideLlmModel[]>
331
+ resolveModelInfo(provider: string, model: string): Promise<{
332
+ provider: string
333
+ id: string
334
+ name: string
335
+ reasoning?: { efforts: readonly SideLlmEffort[]; defaultEffort?: string }
336
+ }>
337
+ stream(options: SideLlmGenerateOptions): AsyncIterable<SideLlmStreamChunk>
338
+ }
339
+
340
+ /** The client locale service face. */
341
+ export interface SideLocaleService {
342
+ getSnapshot(): { active: string }
343
+ subscribe(fn: () => void): () => void
344
+ register(ns: string, locale: string, dict: Record<string, string>): () => void
345
+ }
346
+
347
+ /** DSH 0.1.7 profile-entry settings forms. */
348
+ export interface SideSettingsService {
349
+ configure(presentation: { auto?: boolean }, owner?: Context['fiber']): () => void
350
+ describe(opts: { redactSecrets?: boolean }): Array<{ ns: unknown; value?: unknown; revision?: number }>
351
+ update(ns: unknown, patch: Record<string, unknown>, expectedRevision?: number): Promise<void>
352
+ }
353
+
354
+ /** The client slots service face (settings.section registration). */
355
+ export interface SideSlotsService {
356
+ inject(name: string, factory: () => () => void): () => void
357
+ register(options: Record<string, unknown>, component: unknown): () => void
358
+ }
359
+
360
+ /** One right-sidebar tab type definition (dsh-client-ui-sidebar-right contract, mirror). */
361
+ export interface SideTabDefinition {
362
+ /** Stable unique key; the body seat entry registers under the same key. */
363
+ id: string
364
+ /** Discriminator used by `openTab(kind)` and the pane dispatch. */
365
+ kind: string
366
+ /** Registry band ('builtin' | 'extension' | 'fallback'); defaults to the extension band. */
367
+ priority?: string
368
+ /** Fresh title for the tab chip captured at open time. */
369
+ title(address: string): string
370
+ }
371
+
372
+ /** The right-sidebar tab-type registry face (`ctx.sidebarRight.tabs`). */
373
+ export interface SideSidebarRightTabs {
374
+ /** Register a tab type; returns a disposer (hold it in the caller's ctx.effect). */
375
+ register(definition: SideTabDefinition): () => void
376
+ }
377
+
378
+ /** The cross-plugin right-sidebar face (`ctx.sidebarRight`, ui-sidebar-right). */
379
+ export interface SideSidebarRight {
380
+ /**
381
+ * The controller's tab registry. TypeScript-private upstream (it works at
382
+ * runtime, but the standalone `sidebarRightTabs` service is the public
383
+ * home), so optional here.
384
+ */
385
+ tabs?: SideSidebarRightTabs
386
+ /** Open a page type by kind in the mounted session; reveals the column. */
387
+ openTab(kind: string, options?: { paneId?: string; replaceTab?: boolean; revealIfOpened?: boolean }): void
388
+ }
389
+
390
+ /** One durable image reference (mirror of ImageAttachmentRef). */
391
+ export interface SideImageAttachmentRef {
392
+ attachmentId: string
393
+ mediaType: 'image/png' | 'image/jpeg' | 'image/webp' | 'image/gif'
394
+ bytes: number
395
+ width: number
396
+ height: number
397
+ name?: string
398
+ }
399
+
400
+ /** The host attachment store face (`ctx.attachments`). */
401
+ export interface SideAttachmentStore {
402
+ readonly imageLimits: {
403
+ maxImageBytes: number
404
+ maxImagesPerMessage: number
405
+ maxMessageImageBytes: number
406
+ maxImagePixels: number
407
+ /** 0.1.6+ per-image intrinsic width/height ceiling; absent on earlier lines. */
408
+ maxImageDimension?: number
409
+ mediaTypes: readonly string[]
410
+ }
411
+ validateImage(input: { data: Uint8Array; mediaType: string; name?: string }): Promise<void>
412
+ saveImage(input: { data: Uint8Array; mediaType: string; name?: string }): Promise<SideImageAttachmentRef>
413
+ readImage(ref: SideImageAttachmentRef): Promise<{ ref: SideImageAttachmentRef; data: Uint8Array }>
414
+ }
415
+
416
+ /** The host command registry face (`ctx.commands`). */
417
+ export interface SideCommandsService {
418
+ list(agent: SideAgent): Array<{ name: string; description: string }>
419
+ execute(agent: SideAgent, line: string, submittedAttachments: readonly unknown[], signal: AbortSignal): Promise<unknown>
420
+ }
421
+
422
+ /** The per-session composer input face this plugin writes to (draft-only). */
423
+ export interface SideSessionInput {
424
+ /** Replace the session composer draft (never submits). */
425
+ setDraft(text: string): void
426
+ /** Live input state store (draft read). */
427
+ state: { getSnapshot(): { draft: string } }
428
+ /** Surface a notice on the session composer. */
429
+ notify(level: 'info' | 'error', text: string): void
430
+ }
431
+
432
+ /** The conversation service face (`ctx.conversation`) — input registry only. */
433
+ export interface SideConversationService {
434
+ input: {
435
+ /** Resolve the input facade for one session-scope context. */
436
+ for(actx: Context): SideSessionInput
437
+ }
438
+ }
439
+
440
+ declare module 'cordis' {
441
+ interface Context {
442
+ webServer: SideWebServer
443
+ sessions: SideSessionStore & SideSessionsService
444
+ agents: SideAgentsService
445
+ workspaceRegistry: SideWorkspaceRegistry
446
+ sessionQuery: SideSessionQuery
447
+ permissionPresets: SidePermissionPresets
448
+ agentPresets: SideAgentPresets
449
+ llm: SideLlm
450
+ locale: SideLocaleService
451
+ settings: SideSettingsService
452
+ slots: SideSlotsService
453
+ attachments: SideAttachmentStore
454
+ commands: SideCommandsService
455
+ conversation: SideConversationService
456
+ uiSession: SideUiSessionService
457
+ inject(deps: string[], callback: (ctx: Context) => void): void
458
+ get(name: string): unknown | undefined
459
+ on(name: string, listener: (...args: any[]) => any): () => void
460
+ effect(fn: () => void | (() => void), label?: string): void
461
+ }
462
+ }
463
+
464
+ export type { Context }