@addozhang/dsh-discord 0.3.0 → 0.5.0-alpha.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.
Files changed (49) hide show
  1. package/README.md +13 -13
  2. package/README.zh.md +13 -13
  3. package/cordis.patch.yml +1 -1
  4. package/lib/client/card-controller.d.ts +1 -1
  5. package/lib/client/card-form.d.ts +2 -1
  6. package/lib/client/index.d.ts +2 -2
  7. package/lib/client/slot-contract.d.ts +7 -0
  8. package/lib/client/snapshot-store.d.ts +1 -1
  9. package/lib/compose.d.ts +22 -2
  10. package/lib/compose.js +9 -4
  11. package/lib/dsh/host-asks.d.ts +90 -0
  12. package/lib/dsh/host-asks.js +143 -0
  13. package/lib/dsh/host-events.d.ts +42 -0
  14. package/lib/dsh/host-events.js +234 -0
  15. package/lib/dsh/host-face.d.ts +418 -0
  16. package/lib/dsh/host-face.js +598 -0
  17. package/lib/features/adapter-status.d.ts +15 -2
  18. package/lib/features/adapter-status.js +100 -4
  19. package/lib/features/approval-store.d.ts +1 -1
  20. package/lib/features/image-collection.d.ts +11 -0
  21. package/lib/features/image-collection.js +22 -8
  22. package/lib/features/image-download.d.ts +6 -0
  23. package/lib/features/image-download.js +21 -0
  24. package/lib/features/interaction-router.d.ts +2 -2
  25. package/lib/features/model-control.d.ts +1 -1
  26. package/lib/features/project-list.d.ts +1 -1
  27. package/lib/features/project-list.js +1 -1
  28. package/lib/features/prompt-submission.d.ts +9 -0
  29. package/lib/features/prompt-submission.js +7 -1
  30. package/lib/features/session-mainline.d.ts +42 -1
  31. package/lib/features/session-mainline.js +29 -3
  32. package/lib/features/session-resume.d.ts +1 -1
  33. package/lib/gateway/inbound.d.ts +14 -0
  34. package/lib/gateway/inbound.js +41 -0
  35. package/lib/i18n.d.ts +1 -0
  36. package/lib/i18n.js +2 -0
  37. package/lib/index.js +142 -65
  38. package/lib/settings.js +5 -2
  39. package/lib/startup.d.ts +1 -1
  40. package/lib/startup.js +14 -7
  41. package/lib/stream/live.d.ts +0 -37
  42. package/lib/stream/live.js +10 -58
  43. package/lib/stream/tool-view.d.ts +12 -2
  44. package/lib/stream/tool-view.js +32 -2
  45. package/package.json +10 -12
  46. package/lib/dsh/api-proxy-face.d.ts +0 -390
  47. package/lib/dsh/api-proxy-face.js +0 -510
  48. package/lib/features/image-submission.d.ts +0 -67
  49. package/lib/features/image-submission.js +0 -57
@@ -2,8 +2,11 @@
2
2
  * The bounded tool activity surface (design.md §8, task 11.8). Parallel tool
3
3
  * calls each own one status row keyed by `callId`. Labels come from a safe
4
4
  * allowlist (generic fallback otherwise — an unknown tool name never reaches
5
- * Discord). Raw arguments and output are accepted for correlation but are
6
- * structurally excluded from every render. Verbosity gates visibility:
5
+ * Discord). Raw arguments and output are accepted for correlation and are
6
+ * structurally excluded from every render, with one curated exception: the
7
+ * shell command title (see {@link shellCommandTitle}) — the field the rc.2
8
+ * host view itself disclosed, now derived locally because the 0.1.6 wire
9
+ * carries no host-curated views. Verbosity gates visibility:
7
10
  * `text-only` renders nothing; `essential-tools` and `full-tools` render the
8
11
  * same bounded rows in Milestone 1.
9
12
  */
@@ -18,6 +21,13 @@ export interface ToolRow {
18
21
  }
19
22
  /** The safe label for a tool name: allowlisted categories, generic fallback. */
20
23
  export declare function toolLabel(toolName: string): string;
24
+ /**
25
+ * The shell command for one tool call, curated from its JSON arguments the
26
+ * way the rc.2 host view titled terminal cards: only the `command` string of
27
+ * shell-family tools, first line only, sanitized + truncated through the
28
+ * disclosure policy — every other argument field stays unrendered.
29
+ */
30
+ export declare function shellCommandTitle(toolName: string, rawArguments: string | undefined): string | undefined;
21
31
  export interface ToolRecordInput {
22
32
  callId: string;
23
33
  toolName: string;
@@ -2,11 +2,15 @@
2
2
  * The bounded tool activity surface (design.md §8, task 11.8). Parallel tool
3
3
  * calls each own one status row keyed by `callId`. Labels come from a safe
4
4
  * allowlist (generic fallback otherwise — an unknown tool name never reaches
5
- * Discord). Raw arguments and output are accepted for correlation but are
6
- * structurally excluded from every render. Verbosity gates visibility:
5
+ * Discord). Raw arguments and output are accepted for correlation and are
6
+ * structurally excluded from every render, with one curated exception: the
7
+ * shell command title (see {@link shellCommandTitle}) — the field the rc.2
8
+ * host view itself disclosed, now derived locally because the 0.1.6 wire
9
+ * carries no host-curated views. Verbosity gates visibility:
7
10
  * `text-only` renders nothing; `essential-tools` and `full-tools` render the
8
11
  * same bounded rows in Milestone 1.
9
12
  */
13
+ import { safeTitle } from '../policy/disclosure.js';
10
14
  /** Safe, category-level labels for allowlisted tools. */
11
15
  const TOOL_LABELS = {
12
16
  bash: 'Shell',
@@ -21,6 +25,32 @@ const TOOL_LABELS = {
21
25
  export function toolLabel(toolName) {
22
26
  return TOOL_LABELS[toolName] ?? 'Tool';
23
27
  }
28
+ /**
29
+ * The shell command for one tool call, curated from its JSON arguments the
30
+ * way the rc.2 host view titled terminal cards: only the `command` string of
31
+ * shell-family tools, first line only, sanitized + truncated through the
32
+ * disclosure policy — every other argument field stays unrendered.
33
+ */
34
+ export function shellCommandTitle(toolName, rawArguments) {
35
+ if (rawArguments === undefined || rawArguments === '')
36
+ return undefined;
37
+ if (toolName !== 'bash' && toolName !== 'pwsh')
38
+ return undefined;
39
+ let parsed;
40
+ try {
41
+ parsed = JSON.parse(rawArguments);
42
+ }
43
+ catch {
44
+ return undefined;
45
+ }
46
+ if (typeof parsed !== 'object' || parsed === null)
47
+ return undefined;
48
+ const command = parsed.command;
49
+ if (typeof command !== 'string' || command.trim() === '')
50
+ return undefined;
51
+ const firstLine = command.split('\n')[0]?.trim() ?? '';
52
+ return firstLine === '' ? undefined : safeTitle(firstLine);
53
+ }
24
54
  export function createToolActivitySurface(options) {
25
55
  const rows = new Map();
26
56
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@addozhang/dsh-discord",
3
- "version": "0.3.0",
3
+ "version": "0.5.0-alpha.1",
4
4
  "description": "Discord-first adapter for DeepSeek Harness",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -46,7 +46,6 @@
46
46
  },
47
47
  "client": {
48
48
  "inject": [
49
- "@deepseek-ai/dsh-client-runtime",
50
49
  "@deepseek-ai/dsh-client-ui-settings"
51
50
  ],
52
51
  "platform": "web",
@@ -54,15 +53,14 @@
54
53
  }
55
54
  },
56
55
  "peerDependencies": {
57
- "@deepseek-ai/cordis": "4.0.1",
58
- "@deepseek-ai/dsh-host-apiproxy": "0.1.1-rc.2"
56
+ "@deepseek-ai/cordis": "^4.0.1"
59
57
  },
60
58
  "devDependencies": {
61
- "@deepseek-ai/cordis": "4.0.1",
62
- "@deepseek-ai/dsh-client-runtime": "0.1.1-rc.2",
63
- "@deepseek-ai/dsh-client-ui-settings": "0.1.1-rc.2",
64
- "@deepseek-ai/dsh-client-ui-slots": "0.1.1-rc.2",
65
- "@deepseek-ai/dsh-host-apiproxy": "0.1.1-rc.2",
59
+ "@deepseek-ai/cordis": "4.0.2",
60
+ "@deepseek-ai/dsh-client-store": "0.1.6-alpha.2",
61
+ "@deepseek-ai/dsh-client-ui-renderer": "0.1.6-alpha.2",
62
+ "@deepseek-ai/dsh-client-ui-settings": "0.1.6-alpha.2",
63
+ "@deepseek-ai/dsh-client-ui-slots": "0.1.6-alpha.2",
66
64
  "@eslint/js": "9.39.1",
67
65
  "@types/node": "24.10.1",
68
66
  "@types/react": "18.3.1",
@@ -77,9 +75,9 @@
77
75
  "vitest": "4.1.11"
78
76
  },
79
77
  "dependencies": {
80
- "@deepseek-ai/dsh-credentials": "0.1.1-rc.2",
81
- "@deepseek-ai/dsh-settings": "0.1.1-rc.2",
82
- "@deepseek-ai/dsh-storage-domain": "0.1.1-rc.2",
78
+ "@deepseek-ai/dsh-credentials": "0.1.6-alpha.2",
79
+ "@deepseek-ai/dsh-settings": "0.1.6-alpha.2",
80
+ "@deepseek-ai/dsh-storage-domain": "0.1.6-alpha.2",
83
81
  "@deepseek-ai/schemastery": "3.18.1",
84
82
  "zod": "^4.4.3"
85
83
  },
@@ -1,390 +0,0 @@
1
- /**
2
- * The typed face over the Host's in-process `ctx.apiProxy` service
3
- * (ApiProxyService, the transport-agnostic gateway's direct implementation).
4
- * Its domain methods speak the narrow RPC signature: `RpcRequest<P>` in,
5
- * `RpcResponse<T>` out, business errors on `result.ok === false` — they never
6
- * throw for business outcomes. Two guarantees are added here:
7
- *
8
- * 1. Boundedness — a Host that never answers must not wedge an interaction
9
- * handler (or a Discord ephemeral) forever; every call races a timeout and
10
- * resolves to an unobservable outcome instead.
11
- * 2. Observability — every terminal outcome is reported through the injected
12
- * log sink, so a silent-void call can never again be misread as a hang.
13
- */
14
- import type { ProjectListPort } from '../features/project-list.js';
15
- import type { WorkspaceResolver } from '../features/project-bind.js';
16
- /** The workspace rows the catalog port needs (subset of WorkspaceView). */
17
- export interface WorkspaceCatalogEntry {
18
- workspaceId: string;
19
- title: string;
20
- /** Canonical directory; present in Host responses, rendered only to proven administrators. */
21
- path?: string | undefined;
22
- }
23
- /** The narrow slice of ApiProxy this module speaks. */
24
- export interface DshApiProxyFace {
25
- workspace: {
26
- list(request: RpcRequestShape<Record<string, never>>): Promise<RpcResponseShape<{
27
- items: WorkspaceCatalogEntry[];
28
- }>>;
29
- };
30
- sessions: {
31
- prompt(request: RpcRequestShape<{
32
- sessionId: string;
33
- mode: 'queue' | 'steer';
34
- content: Array<{
35
- type: 'text';
36
- text: string;
37
- }>;
38
- }>): Promise<RpcResponseShape<{
39
- accepted: true;
40
- }>>;
41
- create(request: RpcRequestShape<{
42
- workspaceId?: string;
43
- sessionId?: string;
44
- agentPreset?: string;
45
- }>): Promise<RpcResponseShape<{
46
- sessionId: string;
47
- }>>;
48
- cancel(request: RpcRequestShape<{
49
- sessionId: string;
50
- }>): Promise<RpcResponseShape<{
51
- accepted: true;
52
- }>>;
53
- updateQueue(request: RpcRequestShape<{
54
- sessionId: string;
55
- itemId: string;
56
- action: {
57
- kind: 'remove';
58
- };
59
- }>): Promise<RpcResponseShape<{
60
- accepted: true;
61
- }>>;
62
- list(request: RpcRequestShape<{
63
- cursor?: string;
64
- }>): Promise<RpcResponseShape<{
65
- items: SessionSummaryShape[];
66
- }>>;
67
- models(request: RpcRequestShape<{
68
- sessionId: string;
69
- }>): Promise<RpcResponseShape<SessionModelsShape>>;
70
- selectModel(request: RpcRequestShape<{
71
- sessionId: string;
72
- provider: string;
73
- model: string;
74
- reasoningEffort?: string;
75
- }>): Promise<RpcResponseShape<{
76
- selected: ModelSelectionShape;
77
- }>>;
78
- };
79
- }
80
- /** Defensive read of the title projection in a list row's values. */
81
- export interface SessionProjectionsShape {
82
- values?: {
83
- title?: unknown;
84
- };
85
- }
86
- /** The per-session summary `sessions.list` returns (rc.2 rich rows). */
87
- export interface SessionSummaryShape {
88
- sessionId: string;
89
- updatedAt: number;
90
- running: boolean;
91
- blank: boolean;
92
- cwd?: string;
93
- agentPreset?: string;
94
- origin?: 'subagent';
95
- projections?: SessionProjectionsShape;
96
- }
97
- /** The complete provider/model/reasoning selection (dsh-agent ModelSelection). */
98
- export interface ModelSelectionShape {
99
- provider: string;
100
- model: string;
101
- reasoningEffort?: string;
102
- }
103
- /** One reasoning effort a model's adapter advertises (sessions.d.ts). */
104
- import type { DshModelPort } from '../features/model-control.js';
105
- export interface ModelReasoningEffortShape {
106
- id: string;
107
- name: string;
108
- description?: string;
109
- }
110
- /** Exact-route reasoning metadata for one catalog model. */
111
- export interface ModelReasoningShape {
112
- efforts: ModelReasoningEffortShape[];
113
- defaultEffort?: string;
114
- }
115
- /** One model inside a provider group (sessions.d.ts ModelCatalogModel). */
116
- export interface ModelCatalogModelShape {
117
- id: string;
118
- name: string;
119
- description?: string;
120
- reasoning?: ModelReasoningShape;
121
- }
122
- /** One provider group and its models (sessions.d.ts ModelProviderGroup). */
123
- export interface ModelProviderGroupShape {
124
- id: string;
125
- name: string;
126
- models: ModelCatalogModelShape[];
127
- }
128
- /** The detached model directory `session.models` returns for one session. */
129
- export interface SessionModelsShape {
130
- current: ModelSelectionShape;
131
- routable: boolean;
132
- groups: ModelProviderGroupShape[];
133
- failures: Array<{
134
- id: string;
135
- name: string;
136
- message: string;
137
- }>;
138
- }
139
- /** Signature-layer narrow request form (RpcId brand erased at this seam). */
140
- export interface RpcRequestShape<P> {
141
- rpcId: string;
142
- payload: P;
143
- }
144
- /** Signature-layer narrow response form with the business ok/error result. */
145
- export interface RpcResponseShape<T> {
146
- rpcId: string;
147
- result: {
148
- ok: true;
149
- value: T;
150
- } | {
151
- ok: false;
152
- error: {
153
- code: string;
154
- message: string;
155
- };
156
- };
157
- }
158
- /** Raised when the Host did not answer within the bounded window. */
159
- export declare class RpcTimeoutError extends Error {
160
- constructor(timeoutMs: number);
161
- }
162
- /** Race one apiProxy promise against a bounded window. */
163
- export declare function withRpcTimeout<T>(promise: Promise<T>, timeoutMs: number): Promise<T>;
164
- /** Diagnostic sink shared by both faces. */
165
- export type ApiProxyLog = (event: string, detail?: unknown) => void;
166
- export interface ApiProxyFaceOptions {
167
- timeoutMs?: number;
168
- log?: ApiProxyLog;
169
- }
170
- /**
171
- * The bind flow's catalog verifier: resolves an opaque `ws:` reference
172
- * against the live workspace list. A well-formed reference the catalog no
173
- * longer knows — and any malformed one — resolve `stale` (fail-closed, no
174
- * write can follow); a Host error is `failed`; a timeout is `unknown`.
175
- */
176
- export declare function createWorkspaceResolver(dsh: DshApiProxyFace, options?: ApiProxyFaceOptions): WorkspaceResolver;
177
- /**
178
- * The `/project list` catalog port satisfied by the in-process apiProxy.
179
- * Outcomes follow the port contract: a definitive Host error is `failed`
180
- * (sanitized before Discord), while a timeout or unreadable body is
181
- * `unknown` — delivery was not observed, so no retry is implied.
182
- */
183
- export declare function createWorkspaceCatalogPort(dsh: DshApiProxyFace, options?: ApiProxyFaceOptions): ProjectListPort;
184
- export type WorkspaceDetailOutcome = {
185
- outcome: 'found';
186
- workspace: {
187
- id: string;
188
- title: string;
189
- path: string | undefined;
190
- };
191
- } | {
192
- outcome: 'stale';
193
- } | {
194
- outcome: 'failed';
195
- } | {
196
- outcome: 'unknown';
197
- };
198
- /**
199
- * Read one Workspace's full view (title plus canonical path). The path is
200
- * for the administrator-only ephemeral info response — the disclosure
201
- * policy owns whether it ever renders; this face only carries it in memory.
202
- */
203
- export declare function readWorkspaceDetail(dsh: DshApiProxyFace, reference: string, options?: ApiProxyFaceOptions): Promise<WorkspaceDetailOutcome>;
204
- export type PromptOutcome = {
205
- outcome: 'accepted';
206
- } | {
207
- outcome: 'rejected';
208
- reason: string;
209
- } | {
210
- outcome: 'unknown';
211
- };
212
- /**
213
- * Submit one prompt turn through the in-process apiProxy. A definitive Host
214
- * error is a rejection carrying the sanitized code; a timeout is `unknown` —
215
- * the turn may or may not have been admitted, so callers must not resubmit.
216
- * `options.rpcId` pins the adapter-owned stable request id, which the Host
217
- * records on the durable `user/message` (`source.rpcId`) for reconciliation.
218
- */
219
- export declare function promptSession(dsh: DshApiProxyFace, request: {
220
- sessionId: string;
221
- prompt: string;
222
- }, options?: ApiProxyFaceOptions & {
223
- rpcId?: string;
224
- }): Promise<PromptOutcome>;
225
- /**
226
- * Steer the session's active turn: `session.prompt` with `mode: 'steer'`,
227
- * carrying the same stable request-id discipline as the queue path.
228
- */
229
- export declare function steerSession(dsh: DshApiProxyFace, request: {
230
- sessionId: string;
231
- prompt: string;
232
- }, options?: ApiProxyFaceOptions & {
233
- rpcId?: string;
234
- }): Promise<PromptOutcome>;
235
- export type CreateSessionOutcome = {
236
- outcome: 'completed';
237
- sessionId: string;
238
- } | {
239
- outcome: 'rejected';
240
- reason: string;
241
- } | {
242
- outcome: 'unknown';
243
- };
244
- /**
245
- * Create one DSH Session against a preallocated id (design.md §10): DSH
246
- * adopts the same session id idempotently, so an uncertain response never
247
- * forks a second Session. Same outcome discipline as the prompt path.
248
- */
249
- export declare function createSessionViaProxy(dsh: DshApiProxyFace, request: {
250
- sessionId: string;
251
- workspaceId: string;
252
- }, options?: ApiProxyFaceOptions): Promise<CreateSessionOutcome>;
253
- /** The durable Session-id baseline reconciliation reconciles against. */
254
- export type SessionIdListOutcome = {
255
- outcome: 'completed';
256
- ids: string[];
257
- } | {
258
- outcome: 'failed';
259
- } | {
260
- outcome: 'unknown';
261
- };
262
- /** List durable Session ids (`session.list`, v1 returns everything). */
263
- export declare function listSessionIds(dsh: DshApiProxyFace, options?: ApiProxyFaceOptions): Promise<SessionIdListOutcome>;
264
- /** A list row narrowed to what the /session resume surface renders. */
265
- export interface SessionResumeRow {
266
- sessionId: string;
267
- title: string | undefined;
268
- updatedAt: number;
269
- running: boolean;
270
- blank: boolean;
271
- cwd: string | undefined;
272
- origin: 'subagent' | undefined;
273
- }
274
- export type SessionSummariesOutcome = {
275
- outcome: 'completed';
276
- sessions: SessionResumeRow[];
277
- } | {
278
- outcome: 'failed';
279
- } | {
280
- outcome: 'unknown';
281
- };
282
- /**
283
- * The rich `sessions.list` for the /session resume surface: titles ride each
284
- * row's projection values (absence = the session has no title yet), blank
285
- * sessions are flagged, and rows arrive updatedAt-descending. Defensive
286
- * narrowing: the wire is untrusted, extra/missing fields never throw.
287
- */
288
- export declare function listSessionSummaries(dsh: DshApiProxyFace, options?: ApiProxyFaceOptions): Promise<SessionSummariesOutcome>;
289
- export type CancelOutcome = {
290
- outcome: 'accepted';
291
- } | {
292
- outcome: 'rejected';
293
- reason: string;
294
- } | {
295
- outcome: 'unknown';
296
- };
297
- /** Cancel the session's active turn (`session.cancel`); DSH preserves the pending inbox. */
298
- export declare function cancelSessionViaProxy(dsh: DshApiProxyFace, request: {
299
- sessionId: string;
300
- }, options?: ApiProxyFaceOptions): Promise<CancelOutcome>;
301
- export type QueueRemoveOutcome = {
302
- outcome: 'accepted';
303
- } | {
304
- outcome: 'rejected';
305
- reason: string;
306
- } | {
307
- outcome: 'unknown';
308
- };
309
- /** Remove one pending inbox item (`session.updateQueue`, action remove). */
310
- export declare function removeQueueItemViaProxy(dsh: DshApiProxyFace, request: {
311
- sessionId: string;
312
- itemId: string;
313
- }, options?: ApiProxyFaceOptions): Promise<QueueRemoveOutcome>;
314
- /** The carrier verdict apiProxy.respond resolves with (RpcReceipt). */
315
- export type RespondReceipt = {
316
- accepted: true;
317
- } | {
318
- accepted: false;
319
- reason: 'not-pending' | 'bad-response';
320
- } | {
321
- accepted: unknown;
322
- };
323
- export type RespondOutcome = {
324
- outcome: 'confirmed';
325
- } | {
326
- outcome: 'rejected';
327
- reason: string;
328
- } | {
329
- outcome: 'unknown';
330
- };
331
- /**
332
- * The respond face for answerable server-requests (approvals, questions).
333
- * Builds the full ClientResponse envelope — {type: 'client-response',
334
- * rpcId, result: {ok: true, value}} is the wire contract; posting the bare
335
- * payload is silently ignored by the Host (rpcId never resolves) — and
336
- * maps the RpcReceipt onto the port outcome. Like every call in this module
337
- * it is bounded (a Host that never resolves the receipt must not wedge an
338
- * interaction handler or an expiry sweep forever) and never throws: a Host
339
- * rejection or timeout resolves to `unknown` — the response may or may not
340
- * have landed, and the callers park the ask `unresolved` on exactly that.
341
- */
342
- export declare function createClientRespondPort(dsh: {
343
- respond(message: unknown): Promise<unknown>;
344
- }, options?: ApiProxyFaceOptions): {
345
- respond(rpcId: string, value: unknown): Promise<RespondOutcome>;
346
- };
347
- export type SessionModelsOutcome = {
348
- outcome: 'completed';
349
- models: SessionModelsShape;
350
- } | {
351
- outcome: 'failed';
352
- } | {
353
- outcome: 'unknown';
354
- };
355
- /**
356
- * The session's detached model directory: the live selection, whether the
357
- * current route still serves, and the per-provider catalog groups the
358
- * /model cascade browses.
359
- */
360
- export declare function sessionModels(dsh: DshApiProxyFace, request: {
361
- sessionId: string;
362
- }, options?: ApiProxyFaceOptions): Promise<SessionModelsOutcome>;
363
- export type SelectModelOutcome = {
364
- outcome: 'completed';
365
- selected: ModelSelectionShape;
366
- } | {
367
- outcome: 'rejected';
368
- reason: string;
369
- } | {
370
- outcome: 'unknown';
371
- };
372
- /**
373
- * Select the complete model selection for one session (session.selectModel):
374
- * the session switches immediately and the Host records the choice as the
375
- * default for sessions that have not logged their own — the response only
376
- * proves the session switch, so callers must not claim the persistence
377
- * outcome (design.md §7).
378
- */
379
- export declare function selectSessionModel(dsh: DshApiProxyFace, request: {
380
- sessionId: string;
381
- provider: string;
382
- model: string;
383
- reasoningEffort?: string;
384
- }, options?: ApiProxyFaceOptions): Promise<SelectModelOutcome>;
385
- /**
386
- * The /model surface over the real session RPCs: the per-session live
387
- * directory (`session.models`) and the guarded selection mutation
388
- * (`session.selectModel`) — the shapes model-control reasons about.
389
- */
390
- export declare function createModelPort(dsh: DshApiProxyFace, options?: ApiProxyFaceOptions): DshModelPort;