dsh-remote-bridge 0.0.0-stage → 2.2.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.
@@ -0,0 +1,1065 @@
1
+ openapi: 3.1.0
2
+ info:
3
+ title: DeepSeek Harness Mobile API
4
+ version: 2.2.1
5
+ description: Versioned file and chat BFF for mobile and third-party DSH clients. HTTP and HTTPS are both supported.
6
+ servers:
7
+ - url: http://127.0.0.1:3090/api/v1
8
+ description: Default listener; the bind IP and port are configurable from the local DSH WebUI
9
+ security:
10
+ - bearerAuth: []
11
+ paths:
12
+ /healthz:
13
+ get:
14
+ security: []
15
+ operationId: health
16
+ responses:
17
+ '200':
18
+ description: Listener is alive without exposing host details.
19
+ content:
20
+ application/json:
21
+ schema:
22
+ type: object
23
+ required: [ok, version, pluginVersion]
24
+ properties:
25
+ ok: { type: boolean, const: true }
26
+ version: { type: string, const: v1 }
27
+ pluginVersion: { type: string, const: 2.2.1 }
28
+ /pairings/exchange:
29
+ post:
30
+ security: []
31
+ operationId: exchangePairing
32
+ requestBody:
33
+ required: true
34
+ content:
35
+ application/json:
36
+ schema:
37
+ type: object
38
+ required: [code, deviceName]
39
+ properties:
40
+ code: { type: string, minLength: 8 }
41
+ deviceName: { type: string, minLength: 1, maxLength: 120 }
42
+ responses:
43
+ '201':
44
+ description: Device token returned exactly once.
45
+ content:
46
+ application/json:
47
+ schema:
48
+ type: object
49
+ required: [token, device]
50
+ properties:
51
+ token: { type: string }
52
+ device: { $ref: '#/components/schemas/Device' }
53
+ '401': { $ref: '#/components/responses/Error' }
54
+ '429': { $ref: '#/components/responses/Error' }
55
+ /devices/self:
56
+ get:
57
+ operationId: getCurrentDevice
58
+ responses:
59
+ '200':
60
+ description: Current device grants.
61
+ content:
62
+ application/json:
63
+ schema: { $ref: '#/components/schemas/Device' }
64
+ '401': { $ref: '#/components/responses/Error' }
65
+ /roots:
66
+ get:
67
+ operationId: listRoots
68
+ responses:
69
+ '200':
70
+ description: Roots granted to this device. Absolute host paths are omitted.
71
+ content:
72
+ application/json:
73
+ schema:
74
+ type: object
75
+ required: [items]
76
+ properties:
77
+ items:
78
+ type: array
79
+ items: { $ref: '#/components/schemas/Root' }
80
+ '403': { $ref: '#/components/responses/Error' }
81
+ /roots/{rootId}/entries:
82
+ parameters:
83
+ - $ref: '#/components/parameters/RootId'
84
+ get:
85
+ operationId: listEntries
86
+ parameters:
87
+ - $ref: '#/components/parameters/Path'
88
+ - name: cursor
89
+ in: query
90
+ schema: { type: string }
91
+ - name: limit
92
+ in: query
93
+ schema: { type: integer, minimum: 1, maximum: 500, default: 200 }
94
+ responses:
95
+ '200':
96
+ description: One lazy directory page.
97
+ content:
98
+ application/json:
99
+ schema: { $ref: '#/components/schemas/DirectoryPage' }
100
+ '403': { $ref: '#/components/responses/Error' }
101
+ post:
102
+ operationId: createEntry
103
+ requestBody:
104
+ required: true
105
+ content:
106
+ application/json:
107
+ schema:
108
+ type: object
109
+ required: [path, kind]
110
+ properties:
111
+ path: { $ref: '#/components/schemas/WirePath' }
112
+ kind: { type: string, enum: [file, directory] }
113
+ responses:
114
+ '201':
115
+ description: Entry created.
116
+ content:
117
+ application/json:
118
+ schema: { $ref: '#/components/schemas/FileEntry' }
119
+ '409': { $ref: '#/components/responses/Error' }
120
+ patch:
121
+ operationId: moveEntry
122
+ requestBody:
123
+ required: true
124
+ content:
125
+ application/json:
126
+ schema:
127
+ type: object
128
+ required: [path, destinationPath]
129
+ properties:
130
+ path: { $ref: '#/components/schemas/WirePath' }
131
+ destinationPath: { $ref: '#/components/schemas/WirePath' }
132
+ responses:
133
+ '200':
134
+ description: Entry moved or renamed.
135
+ '409': { $ref: '#/components/responses/Error' }
136
+ delete:
137
+ operationId: trashEntry
138
+ parameters:
139
+ - $ref: '#/components/parameters/RequiredPath'
140
+ responses:
141
+ '200':
142
+ description: Entry moved to plugin trash.
143
+ content:
144
+ application/json:
145
+ schema: { $ref: '#/components/schemas/TrashItem' }
146
+ '403': { $ref: '#/components/responses/Error' }
147
+ /roots/{rootId}/content:
148
+ parameters:
149
+ - $ref: '#/components/parameters/RootId'
150
+ - $ref: '#/components/parameters/RequiredPath'
151
+ get:
152
+ operationId: readContent
153
+ parameters:
154
+ - name: Range
155
+ in: header
156
+ schema: { type: string, examples: [bytes=0-1023] }
157
+ responses:
158
+ '200':
159
+ description: Complete raw file content. ETag is always returned.
160
+ headers:
161
+ ETag: { schema: { type: string } }
162
+ content:
163
+ application/octet-stream:
164
+ schema: { type: string, contentEncoding: binary }
165
+ '206':
166
+ description: One byte range.
167
+ '416': { $ref: '#/components/responses/Error' }
168
+ put:
169
+ operationId: writeContent
170
+ parameters:
171
+ - name: If-Match
172
+ in: header
173
+ description: Required for an existing file.
174
+ schema: { type: string }
175
+ - name: If-None-Match
176
+ in: header
177
+ description: Must be `*` when creating a file.
178
+ schema: { type: string, const: '*' }
179
+ requestBody:
180
+ required: true
181
+ content:
182
+ application/octet-stream:
183
+ schema: { type: string, contentEncoding: binary }
184
+ responses:
185
+ '200':
186
+ description: Atomic replacement completed.
187
+ headers:
188
+ ETag: { schema: { type: string } }
189
+ '412': { $ref: '#/components/responses/Error' }
190
+ '428': { $ref: '#/components/responses/Error' }
191
+ /trash:
192
+ get:
193
+ operationId: listTrash
194
+ responses:
195
+ '200':
196
+ description: Trash items belonging to granted roots.
197
+ content:
198
+ application/json:
199
+ schema:
200
+ type: object
201
+ required: [items]
202
+ properties:
203
+ items:
204
+ type: array
205
+ items: { $ref: '#/components/schemas/TrashItem' }
206
+ /trash/{trashId}/restore:
207
+ post:
208
+ operationId: restoreTrash
209
+ parameters:
210
+ - name: trashId
211
+ in: path
212
+ required: true
213
+ schema: { type: string, format: uuid }
214
+ responses:
215
+ '200':
216
+ description: Item restored without overwriting an existing path.
217
+ '409': { $ref: '#/components/responses/Error' }
218
+ /chat/workspaces:
219
+ get:
220
+ operationId: listChatWorkspaces
221
+ description: Lists DSH WebUI workspaces whose canonical directory is inside a root granted to the device. Server absolute paths are not returned.
222
+ responses:
223
+ '200':
224
+ description: Authorized DSH workspace choices.
225
+ content:
226
+ application/json:
227
+ schema:
228
+ type: object
229
+ required: [items]
230
+ properties:
231
+ items:
232
+ type: array
233
+ items: { $ref: '#/components/schemas/ChatWorkspace' }
234
+ post:
235
+ operationId: createChatWorkspace
236
+ description: Registers an existing authorized directory as a DSH WebUI workspace. The server absolute path is never accepted or returned.
237
+ requestBody:
238
+ required: true
239
+ content:
240
+ application/json:
241
+ schema:
242
+ type: object
243
+ required: [rootId, path]
244
+ properties:
245
+ rootId: { type: string, format: uuid }
246
+ path: { $ref: '#/components/schemas/WirePath' }
247
+ responses:
248
+ '201':
249
+ description: DSH workspace created or idempotently resolved.
250
+ content:
251
+ application/json:
252
+ schema:
253
+ type: object
254
+ required: [workspace]
255
+ properties:
256
+ workspace: { $ref: '#/components/schemas/ChatWorkspace' }
257
+ '403': { $ref: '#/components/responses/Error' }
258
+ '404': { $ref: '#/components/responses/Error' }
259
+ /chat/workspaces/{workspaceId}:
260
+ parameters:
261
+ - name: workspaceId
262
+ in: path
263
+ required: true
264
+ schema: { type: string }
265
+ patch:
266
+ operationId: renameChatWorkspace
267
+ description: Renames a DSH WebUI workspace visible to this device.
268
+ requestBody:
269
+ required: true
270
+ content:
271
+ application/json:
272
+ schema:
273
+ type: object
274
+ required: [title]
275
+ properties:
276
+ title: { type: string, minLength: 1 }
277
+ responses:
278
+ '200':
279
+ description: Renamed workspace.
280
+ content:
281
+ application/json:
282
+ schema:
283
+ type: object
284
+ required: [workspace]
285
+ properties:
286
+ workspace: { $ref: '#/components/schemas/ChatWorkspace' }
287
+ '404': { $ref: '#/components/responses/Error' }
288
+ delete:
289
+ operationId: deleteChatWorkspace
290
+ description: Removes only the DSH workspace registration. The directory, files, and session logs are preserved.
291
+ responses:
292
+ '200': { description: Workspace registration removed. }
293
+ '404': { $ref: '#/components/responses/Error' }
294
+ /chat/agent-presets:
295
+ get:
296
+ operationId: listAgentPresets
297
+ description: Lists the same Agent presets offered by DSH WebUI without exposing their composition files.
298
+ responses:
299
+ '200':
300
+ description: Agent preset choices.
301
+ content:
302
+ application/json:
303
+ schema:
304
+ type: object
305
+ required: [items]
306
+ properties:
307
+ items:
308
+ type: array
309
+ items: { $ref: '#/components/schemas/AgentPreset' }
310
+ /settings/providers:
311
+ get:
312
+ operationId: listProviderSettings
313
+ description: Lists DSH model providers and credential status. Secret values are never returned.
314
+ responses:
315
+ '200':
316
+ description: Provider configuration safe for display to an authorized device.
317
+ content:
318
+ application/json:
319
+ schema: { $ref: '#/components/schemas/ProviderSettings' }
320
+ '403': { $ref: '#/components/responses/Error' }
321
+ post:
322
+ operationId: createCustomProvider
323
+ description: Creates a fully custom llm-pi-ai provider using the protocols reported by ProviderSettings.customProvider.
324
+ requestBody:
325
+ required: true
326
+ content:
327
+ application/json:
328
+ schema: { $ref: '#/components/schemas/CustomProviderCreate' }
329
+ responses:
330
+ '201':
331
+ description: Custom provider created; secret values are omitted from the response.
332
+ content:
333
+ application/json:
334
+ schema: { $ref: '#/components/schemas/ProviderSettings' }
335
+ '400': { $ref: '#/components/responses/Error' }
336
+ '409': { $ref: '#/components/responses/Error' }
337
+ /settings/models:
338
+ get:
339
+ operationId: listModelCatalog
340
+ responses:
341
+ '200':
342
+ description: Models currently available through DSH providers.
343
+ content:
344
+ application/json:
345
+ schema: { $ref: '#/components/schemas/ModelCatalog' }
346
+ /settings/providers/{providerId}:
347
+ parameters:
348
+ - name: providerId
349
+ in: path
350
+ required: true
351
+ schema: { type: string }
352
+ patch:
353
+ operationId: updateProvider
354
+ description: Updates provider settings and optionally writes an API key to the DSH credential store.
355
+ requestBody:
356
+ required: true
357
+ content:
358
+ application/json:
359
+ schema: { $ref: '#/components/schemas/ProviderPatch' }
360
+ responses:
361
+ '200':
362
+ description: Updated provider list without secret values.
363
+ content:
364
+ application/json:
365
+ schema: { $ref: '#/components/schemas/ProviderSettings' }
366
+ '403': { $ref: '#/components/responses/Error' }
367
+ '409': { $ref: '#/components/responses/Error' }
368
+ delete:
369
+ operationId: removeProvider
370
+ parameters:
371
+ - name: expectedRevision
372
+ in: query
373
+ schema: { type: integer, minimum: 0 }
374
+ responses:
375
+ '204': { description: Custom provider removed. }
376
+ '409': { $ref: '#/components/responses/Error' }
377
+ /settings/providers/{providerId}/discover:
378
+ post:
379
+ operationId: discoverProviderModels
380
+ parameters:
381
+ - name: providerId
382
+ in: path
383
+ required: true
384
+ schema: { type: string }
385
+ requestBody:
386
+ required: true
387
+ content:
388
+ application/json:
389
+ schema:
390
+ type: object
391
+ properties:
392
+ baseURL: { type: string }
393
+ api: { type: string }
394
+ apiKey: { type: string, writeOnly: true }
395
+ responses:
396
+ '200':
397
+ description: Models reported by the provider.
398
+ content:
399
+ application/json:
400
+ schema:
401
+ type: object
402
+ required: [models]
403
+ properties:
404
+ models:
405
+ type: array
406
+ items: { $ref: '#/components/schemas/ProviderModel' }
407
+ /chat/sessions:
408
+ get:
409
+ operationId: listChatSessions
410
+ responses:
411
+ '200':
412
+ description: Sessions whose cwd is within a granted root.
413
+ content:
414
+ application/json:
415
+ schema:
416
+ type: object
417
+ required: [items]
418
+ properties:
419
+ items:
420
+ type: array
421
+ items: { $ref: '#/components/schemas/ChatSession' }
422
+ post:
423
+ operationId: createChatSession
424
+ requestBody:
425
+ required: true
426
+ content:
427
+ application/json:
428
+ schema:
429
+ type: object
430
+ oneOf:
431
+ - required: [workspaceId]
432
+ - required: [rootId, path]
433
+ properties:
434
+ workspaceId:
435
+ type: string
436
+ description: Preferred DSH WebUI workspace identity returned by listChatWorkspaces.
437
+ rootId: { type: string, format: uuid }
438
+ path: { $ref: '#/components/schemas/WirePath' }
439
+ sessionId: { type: string }
440
+ agentPreset: { type: string }
441
+ clientRequestId: { type: string, maxLength: 200 }
442
+ responses:
443
+ '201': { description: DSH session created or idempotently returned. }
444
+ /chat/sessions/{sessionId}:
445
+ patch:
446
+ operationId: renameChatSession
447
+ parameters:
448
+ - name: sessionId
449
+ in: path
450
+ required: true
451
+ schema: { type: string }
452
+ requestBody:
453
+ required: true
454
+ content:
455
+ application/json:
456
+ schema:
457
+ type: object
458
+ required: [title]
459
+ properties:
460
+ title: { type: string, minLength: 1 }
461
+ responses:
462
+ '200': { description: Session title updated. }
463
+ '404': { $ref: '#/components/responses/Error' }
464
+ /chat/sessions/{sessionId}/fork:
465
+ post:
466
+ operationId: forkChatSession
467
+ description: Forks the session at the latest completed boundary, or at the supplied event sequence.
468
+ parameters:
469
+ - name: sessionId
470
+ in: path
471
+ required: true
472
+ schema: { type: string }
473
+ requestBody:
474
+ content:
475
+ application/json:
476
+ schema:
477
+ type: object
478
+ properties:
479
+ atSeq: { type: integer, minimum: 0 }
480
+ responses:
481
+ '201':
482
+ description: Forked session created in the same DSH workspace.
483
+ content:
484
+ application/json:
485
+ schema:
486
+ type: object
487
+ required: [sessionId]
488
+ properties:
489
+ sessionId: { type: string }
490
+ '404': { $ref: '#/components/responses/Error' }
491
+ /chat/sessions/{sessionId}/archive:
492
+ post:
493
+ operationId: archiveChatSession
494
+ description: Archives the session from default workspace views while preserving its log.
495
+ parameters:
496
+ - name: sessionId
497
+ in: path
498
+ required: true
499
+ schema: { type: string }
500
+ responses:
501
+ '200': { description: Session archived. }
502
+ '404': { $ref: '#/components/responses/Error' }
503
+ /chat/sessions/{sessionId}/messages:
504
+ parameters:
505
+ - name: sessionId
506
+ in: path
507
+ required: true
508
+ schema: { type: string }
509
+ get:
510
+ operationId: listMessages
511
+ parameters:
512
+ - name: beforeSeq
513
+ in: query
514
+ schema: { type: integer, minimum: 0 }
515
+ - name: maxMessages
516
+ in: query
517
+ schema: { type: integer, minimum: 1 }
518
+ responses:
519
+ '200': { description: DSH history events and continuation state. }
520
+ '404': { $ref: '#/components/responses/Error' }
521
+ post:
522
+ operationId: sendMessage
523
+ requestBody:
524
+ required: true
525
+ content:
526
+ application/json:
527
+ schema:
528
+ type: object
529
+ required: [text]
530
+ properties:
531
+ text: { type: string, minLength: 1 }
532
+ mode: { type: string, enum: [queue, steer], default: queue }
533
+ clientTimeZone: { type: string }
534
+ clientRequestId: { type: string, maxLength: 200 }
535
+ responses:
536
+ '202': { description: Prompt accepted by DSH. }
537
+ '409': { $ref: '#/components/responses/Error' }
538
+ /chat/sessions/{sessionId}/approvals:
539
+ get:
540
+ operationId: listPendingApprovals
541
+ description: Lists pending DSH approvals for an authorized session. Tool details are redacted and bounded; private DSH RPC identifiers are never exposed.
542
+ parameters:
543
+ - name: sessionId
544
+ in: path
545
+ required: true
546
+ schema: { type: string }
547
+ responses:
548
+ '200':
549
+ description: Pending approvals visible to the current device.
550
+ content:
551
+ application/json:
552
+ schema:
553
+ type: object
554
+ required: [items]
555
+ properties:
556
+ items:
557
+ type: array
558
+ items: { $ref: '#/components/schemas/PendingApproval' }
559
+ '404': { $ref: '#/components/responses/Error' }
560
+ /chat/sessions/{sessionId}/approvals/{approvalId}/decision:
561
+ post:
562
+ operationId: decideApproval
563
+ description: Allows a pending tool request once or rejects it. Persistent approval is intentionally unsupported.
564
+ parameters:
565
+ - name: sessionId
566
+ in: path
567
+ required: true
568
+ schema: { type: string }
569
+ - name: approvalId
570
+ in: path
571
+ required: true
572
+ schema: { type: string }
573
+ requestBody:
574
+ required: true
575
+ content:
576
+ application/json:
577
+ schema:
578
+ type: object
579
+ required: [outcome]
580
+ properties:
581
+ outcome: { type: string, enum: [allowed-once, rejected] }
582
+ responses:
583
+ '202': { description: Decision accepted by DSH. }
584
+ '409': { $ref: '#/components/responses/Error' }
585
+ /chat/sessions/{sessionId}/commands:
586
+ get:
587
+ operationId: listSessionCommands
588
+ description: Lists the DSH host slash commands currently available to this authorized session.
589
+ parameters:
590
+ - name: sessionId
591
+ in: path
592
+ required: true
593
+ schema: { type: string }
594
+ responses:
595
+ '200':
596
+ description: Current command directory.
597
+ content:
598
+ application/json:
599
+ schema:
600
+ type: object
601
+ required: [items]
602
+ properties:
603
+ items:
604
+ type: array
605
+ items: { $ref: '#/components/schemas/CommandDescriptor' }
606
+ '404': { $ref: '#/components/responses/Error' }
607
+ post:
608
+ operationId: executeSessionCommand
609
+ description: Executes a listed slash command through the DSH host command registry. The line is never sent to the model as a chat message.
610
+ parameters:
611
+ - name: sessionId
612
+ in: path
613
+ required: true
614
+ schema: { type: string }
615
+ requestBody:
616
+ required: true
617
+ content:
618
+ application/json:
619
+ schema:
620
+ type: object
621
+ required: [line]
622
+ properties:
623
+ line: { type: string, minLength: 1, maxLength: 16384, pattern: '^/' }
624
+ responses:
625
+ '200':
626
+ description: Settled DSH command execution.
627
+ content:
628
+ application/json:
629
+ schema:
630
+ type: object
631
+ required: [execution]
632
+ properties:
633
+ execution: { $ref: '#/components/schemas/CommandExecution' }
634
+ '404': { $ref: '#/components/responses/Error' }
635
+ '409': { $ref: '#/components/responses/Error' }
636
+ /chat/sessions/{sessionId}/models:
637
+ get:
638
+ operationId: listSessionModels
639
+ parameters:
640
+ - name: sessionId
641
+ in: path
642
+ required: true
643
+ schema: { type: string }
644
+ responses:
645
+ '200':
646
+ description: Current selection and models routable for this DSH session.
647
+ content:
648
+ application/json:
649
+ schema: { $ref: '#/components/schemas/SessionModels' }
650
+ '404': { $ref: '#/components/responses/Error' }
651
+ /chat/sessions/{sessionId}/model:
652
+ put:
653
+ operationId: selectSessionModel
654
+ parameters:
655
+ - name: sessionId
656
+ in: path
657
+ required: true
658
+ schema: { type: string }
659
+ requestBody:
660
+ required: true
661
+ content:
662
+ application/json:
663
+ schema: { $ref: '#/components/schemas/ModelSelection' }
664
+ responses:
665
+ '200':
666
+ description: Model selection accepted by DSH.
667
+ content:
668
+ application/json:
669
+ schema:
670
+ type: object
671
+ required: [selected]
672
+ properties:
673
+ selected: { $ref: '#/components/schemas/ModelSelection' }
674
+ '409': { $ref: '#/components/responses/Error' }
675
+ /chat/sessions/{sessionId}/agent-preset:
676
+ put:
677
+ operationId: selectSessionAgentPreset
678
+ description: Changes the Agent preset only while the DSH session is blank. DSH locks the preset after the first accepted prompt.
679
+ parameters:
680
+ - name: sessionId
681
+ in: path
682
+ required: true
683
+ schema: { type: string }
684
+ requestBody:
685
+ required: true
686
+ content:
687
+ application/json:
688
+ schema:
689
+ type: object
690
+ required: [agentPreset]
691
+ properties:
692
+ agentPreset: { type: string, minLength: 1 }
693
+ responses:
694
+ '200':
695
+ description: Agent preset recomposed and selected.
696
+ content:
697
+ application/json:
698
+ schema:
699
+ type: object
700
+ required: [agentPreset]
701
+ properties:
702
+ agentPreset: { type: string }
703
+ '409': { $ref: '#/components/responses/Error' }
704
+ /chat/runs/{id}/cancel:
705
+ post:
706
+ operationId: cancelRun
707
+ description: In v1 the run id is the owning DSH session id.
708
+ parameters:
709
+ - name: id
710
+ in: path
711
+ required: true
712
+ schema: { type: string }
713
+ responses:
714
+ '202': { description: Cancellation accepted. }
715
+ components:
716
+ securitySchemes:
717
+ bearerAuth:
718
+ type: http
719
+ scheme: bearer
720
+ bearerFormat: opaque-256-bit-token
721
+ parameters:
722
+ RootId:
723
+ name: rootId
724
+ in: path
725
+ required: true
726
+ schema: { type: string, format: uuid }
727
+ Path:
728
+ name: path
729
+ in: query
730
+ required: false
731
+ schema: { $ref: '#/components/schemas/WirePath' }
732
+ RequiredPath:
733
+ name: path
734
+ in: query
735
+ required: true
736
+ schema: { $ref: '#/components/schemas/WirePath' }
737
+ responses:
738
+ Error:
739
+ description: Versioned API error.
740
+ content:
741
+ application/json:
742
+ schema: { $ref: '#/components/schemas/ErrorEnvelope' }
743
+ schemas:
744
+ WirePath:
745
+ type: string
746
+ description: POSIX-style relative path. Absolute paths, backslashes, empty segments, dot segments, drive letters, UNC and null bytes are rejected.
747
+ examples: [src/main.ts]
748
+ Root:
749
+ type: object
750
+ required: [id, label, createdAt]
751
+ properties:
752
+ id: { type: string, format: uuid }
753
+ label: { type: string }
754
+ createdAt: { type: integer }
755
+ Device:
756
+ type: object
757
+ required: [id, name, scopes, rootIds]
758
+ properties:
759
+ id: { type: string }
760
+ name: { type: string }
761
+ scopes:
762
+ type: array
763
+ items: { type: string, enum: [chat.read, chat.write, files.read, files.write, files.delete, settings.read, settings.write] }
764
+ rootIds:
765
+ type: array
766
+ items: { type: string }
767
+ FileEntry:
768
+ type: object
769
+ required: [name, path, kind, size, modifiedAt, writable]
770
+ properties:
771
+ name: { type: string }
772
+ path: { $ref: '#/components/schemas/WirePath' }
773
+ kind: { type: string, enum: [file, directory, symlink, other] }
774
+ size: { type: integer, minimum: 0 }
775
+ modifiedAt: { type: number }
776
+ writable: { type: boolean }
777
+ DirectoryPage:
778
+ type: object
779
+ required: [path, entries]
780
+ properties:
781
+ path: { $ref: '#/components/schemas/WirePath' }
782
+ entries:
783
+ type: array
784
+ items: { $ref: '#/components/schemas/FileEntry' }
785
+ nextCursor: { type: string }
786
+ TrashItem:
787
+ type: object
788
+ required: [id, rootId, path, kind, size, createdAt, status]
789
+ properties:
790
+ id: { type: string, format: uuid }
791
+ rootId: { type: string, format: uuid }
792
+ path: { $ref: '#/components/schemas/WirePath' }
793
+ kind: { type: string }
794
+ size: { type: integer }
795
+ createdAt: { type: integer }
796
+ status: { type: string }
797
+ ChatSession:
798
+ type: object
799
+ required: [id, rootId, cwd, updatedAt, running, blank]
800
+ properties:
801
+ id: { type: string }
802
+ rootId: { type: string }
803
+ cwd: { $ref: '#/components/schemas/WirePath' }
804
+ updatedAt: { type: integer }
805
+ running: { type: boolean }
806
+ blank: { type: boolean }
807
+ title: { type: string }
808
+ workspaceId: { type: string }
809
+ workspaceTitle: { type: string }
810
+ agentPreset: { type: string }
811
+ pendingInteraction: { type: string, enum: [approval] }
812
+ PendingApproval:
813
+ type: object
814
+ required: [id, sessionId, toolName, risk, requestedAt]
815
+ properties:
816
+ id: { type: string }
817
+ sessionId: { type: string }
818
+ toolName: { type: string, maxLength: 120 }
819
+ reason:
820
+ type: string
821
+ maxLength: 500
822
+ description: Redacted host reason suitable for display.
823
+ detail:
824
+ type: string
825
+ maxLength: 1200
826
+ description: Optional redacted tool or command preview.
827
+ risk: { type: string, enum: [standard, full-access] }
828
+ requestedAt: { type: integer }
829
+ CommandDescriptor:
830
+ type: object
831
+ required: [name, description]
832
+ properties:
833
+ name: { type: string, pattern: '^[a-z][a-z0-9_-]*$' }
834
+ description: { type: string }
835
+ input:
836
+ type: object
837
+ required: [hint]
838
+ properties:
839
+ hint: { type: string }
840
+ CommandResult:
841
+ type: object
842
+ required: [kind]
843
+ properties:
844
+ kind: { type: string, enum: [success, error] }
845
+ text: { type: string }
846
+ sourceEventSeq: { type: integer, minimum: 0 }
847
+ CommandExecution:
848
+ type: object
849
+ required: [commandId, result]
850
+ properties:
851
+ commandId: { type: string }
852
+ result: { $ref: '#/components/schemas/CommandResult' }
853
+ TodoItem:
854
+ type: object
855
+ required: [content, status]
856
+ properties:
857
+ content: { type: string }
858
+ status: { type: string, enum: [pending, in_progress, completed] }
859
+ PermissionOption:
860
+ type: object
861
+ required: [value, name]
862
+ properties:
863
+ value: { type: string }
864
+ name: { type: string }
865
+ description: { type: string }
866
+ PermissionSelect:
867
+ type: object
868
+ required: [options, currentValue]
869
+ properties:
870
+ options:
871
+ type: array
872
+ items: { $ref: '#/components/schemas/PermissionOption' }
873
+ currentValue: { type: string }
874
+ ChatWorkspace:
875
+ type: object
876
+ required: [id, title, rootId, path, createdAt, updatedAt]
877
+ properties:
878
+ id: { type: string }
879
+ title: { type: string }
880
+ rootId: { type: string, format: uuid }
881
+ path: { $ref: '#/components/schemas/WirePath' }
882
+ createdAt: { type: string, format: date-time }
883
+ updatedAt: { type: string, format: date-time }
884
+ AgentPreset:
885
+ type: object
886
+ required: [id, name, trust, isDefault, available]
887
+ properties:
888
+ id: { type: string }
889
+ name: { type: string }
890
+ description: { type: string }
891
+ trust: { type: string, enum: [system, user] }
892
+ isDefault: { type: boolean }
893
+ available: { type: boolean }
894
+ ModelSelection:
895
+ type: object
896
+ required: [provider, model]
897
+ properties:
898
+ provider: { type: string, minLength: 1 }
899
+ model: { type: string, minLength: 1 }
900
+ reasoningEffort: { type: string }
901
+ ModelReasoningEffort:
902
+ type: object
903
+ required: [id, name]
904
+ properties:
905
+ id: { type: string }
906
+ name: { type: string }
907
+ description: { type: string }
908
+ ModelReasoning:
909
+ type: object
910
+ required: [efforts]
911
+ properties:
912
+ efforts:
913
+ type: array
914
+ items: { $ref: '#/components/schemas/ModelReasoningEffort' }
915
+ defaultEffort: { type: string }
916
+ Model:
917
+ type: object
918
+ required: [id, name]
919
+ properties:
920
+ id: { type: string }
921
+ name: { type: string }
922
+ description: { type: string }
923
+ contextWindow: { type: integer, minimum: 1 }
924
+ maxTokens: { type: integer, minimum: 1 }
925
+ reasoning: { $ref: '#/components/schemas/ModelReasoning' }
926
+ ModelProviderGroup:
927
+ type: object
928
+ required: [id, name, models]
929
+ properties:
930
+ id: { type: string }
931
+ name: { type: string }
932
+ models:
933
+ type: array
934
+ items: { $ref: '#/components/schemas/Model' }
935
+ ModelFailure:
936
+ type: object
937
+ required: [provider, message]
938
+ properties:
939
+ provider: { type: string }
940
+ message: { type: string }
941
+ ModelCatalog:
942
+ type: object
943
+ required: [groups, failures]
944
+ properties:
945
+ groups:
946
+ type: array
947
+ items: { $ref: '#/components/schemas/ModelProviderGroup' }
948
+ failures:
949
+ type: array
950
+ items: { $ref: '#/components/schemas/ModelFailure' }
951
+ SessionModels:
952
+ allOf:
953
+ - $ref: '#/components/schemas/ModelCatalog'
954
+ - type: object
955
+ required: [current, routable]
956
+ properties:
957
+ current: { $ref: '#/components/schemas/ModelSelection' }
958
+ routable: { type: boolean }
959
+ ProviderModel:
960
+ type: object
961
+ required: [id]
962
+ properties:
963
+ id: { type: string, minLength: 1 }
964
+ name: { type: string }
965
+ contextWindow: { type: integer, minimum: 1 }
966
+ maxTokens: { type: integer, minimum: 1 }
967
+ ProviderConfig:
968
+ type: object
969
+ required: [models]
970
+ properties:
971
+ baseURL: { type: string }
972
+ api: { type: string }
973
+ displayName: { type: string }
974
+ thinking: { type: string }
975
+ reasoningEffort: { type: string }
976
+ models:
977
+ type: array
978
+ items: { $ref: '#/components/schemas/ProviderModel' }
979
+ modelsInherited:
980
+ type: boolean
981
+ description: True when the listed models come from the live DSH catalog rather than a stored provider override.
982
+ CredentialState:
983
+ type: object
984
+ required: [ref, configured, writable]
985
+ properties:
986
+ ref: { type: string }
987
+ configured: { type: boolean }
988
+ source: { type: string }
989
+ writable: { type: boolean }
990
+ Provider:
991
+ type: object
992
+ required: [id, displayName, active, configurable, configured, removable, credential, config]
993
+ properties:
994
+ id: { type: string }
995
+ displayName: { type: string }
996
+ active: { type: boolean }
997
+ declared: { type: boolean }
998
+ configurable: { type: boolean }
999
+ configured: { type: boolean }
1000
+ removable: { type: boolean }
1001
+ credential: { $ref: '#/components/schemas/CredentialState' }
1002
+ config: { $ref: '#/components/schemas/ProviderConfig' }
1003
+ ProviderSettings:
1004
+ type: object
1005
+ required: [writable, revisionByNamespace, customProvider, providers]
1006
+ properties:
1007
+ writable: { type: boolean }
1008
+ revisionByNamespace:
1009
+ type: object
1010
+ additionalProperties: { type: integer, minimum: 0 }
1011
+ customProvider:
1012
+ $ref: '#/components/schemas/CustomProviderCapability'
1013
+ providers:
1014
+ type: array
1015
+ items: { $ref: '#/components/schemas/Provider' }
1016
+ ProviderPatch:
1017
+ type: object
1018
+ properties:
1019
+ displayName: { type: [string, 'null'] }
1020
+ baseURL: { type: [string, 'null'] }
1021
+ api: { type: [string, 'null'] }
1022
+ apiKey: { type: [string, 'null'], writeOnly: true }
1023
+ thinking: { type: [string, 'null'] }
1024
+ reasoningEffort: { type: [string, 'null'] }
1025
+ models:
1026
+ type: array
1027
+ items: { $ref: '#/components/schemas/ProviderModel' }
1028
+ expectedRevision: { type: integer, minimum: 0 }
1029
+ CustomProviderCapability:
1030
+ type: object
1031
+ required: [available, protocols]
1032
+ properties:
1033
+ available: { type: boolean }
1034
+ protocols:
1035
+ type: array
1036
+ items: { type: string }
1037
+ revision: { type: integer, minimum: 0 }
1038
+ CustomProviderCreate:
1039
+ type: object
1040
+ required: [id, baseURL, api, models]
1041
+ properties:
1042
+ id:
1043
+ type: string
1044
+ pattern: '^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$'
1045
+ displayName: { type: string }
1046
+ baseURL: { type: string, minLength: 1 }
1047
+ api: { type: string, minLength: 1 }
1048
+ apiKey: { type: string, writeOnly: true }
1049
+ models:
1050
+ type: array
1051
+ minItems: 1
1052
+ items: { $ref: '#/components/schemas/ProviderModel' }
1053
+ expectedRevision: { type: integer, minimum: 0 }
1054
+ ErrorEnvelope:
1055
+ type: object
1056
+ required: [error]
1057
+ properties:
1058
+ error:
1059
+ type: object
1060
+ required: [code, message, requestId]
1061
+ properties:
1062
+ code: { type: string }
1063
+ message: { type: string }
1064
+ requestId: { type: string, format: uuid }
1065
+ details: { type: object, additionalProperties: true }