dsh-remote-bridge 2.5.1 → 2.6.0
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.
- package/README.en.md +22 -19
- package/README.md +65 -16
- package/docs/api/asyncapi.yaml +51 -2
- package/docs/api/openapi.yaml +326 -4
- package/lib/client.cjs +1128 -532
- package/lib/index.d.ts +547 -15
- package/lib/index.js +2593 -337
- package/package.json +1 -1
package/docs/api/openapi.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
openapi: 3.1.0
|
|
2
2
|
info:
|
|
3
3
|
title: DeepSeek Harness Mobile API
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.6.0
|
|
5
5
|
description: Versioned file and chat BFF for mobile and third-party DSH clients. HTTP and HTTPS are both supported.
|
|
6
6
|
servers:
|
|
7
7
|
- url: http://127.0.0.1:3090/api/v1
|
|
@@ -24,7 +24,7 @@ paths:
|
|
|
24
24
|
properties:
|
|
25
25
|
ok: { type: boolean, const: true }
|
|
26
26
|
version: { type: string, const: v1 }
|
|
27
|
-
pluginVersion: { type: string, const: 2.
|
|
27
|
+
pluginVersion: { type: string, const: 2.6.0 }
|
|
28
28
|
/debug/host-services:
|
|
29
29
|
get:
|
|
30
30
|
operationId: hostServices
|
|
@@ -39,8 +39,14 @@ paths:
|
|
|
39
39
|
`observed` covers services confirmed present in the web profile but not yet
|
|
40
40
|
consumed (currently only `workingDirectory`, added by DSH 0.2.1).
|
|
41
41
|
|
|
42
|
-
Requires a device token or loopback admin
|
|
43
|
-
|
|
42
|
+
Requires a device token or loopback admin **with the `settings.read`
|
|
43
|
+
scope** (a loopback admin inherits all scopes): it exposes host
|
|
44
|
+
internals. Since 2.5.2 the endpoint sits behind authentication like
|
|
45
|
+
every other `/api/v1` route (SEC-H1); it previously returned before the
|
|
46
|
+
principal was resolved. The response may additionally carry a
|
|
47
|
+
best-effort `metrics` object with runtime diagnostics; it is omitted in
|
|
48
|
+
builds without the metrics collector (and a missing probe still yields
|
|
49
|
+
`404`, not `500`).
|
|
44
50
|
responses:
|
|
45
51
|
'200':
|
|
46
52
|
description: Injection probe snapshot taken while the plugin applied.
|
|
@@ -79,6 +85,14 @@ paths:
|
|
|
79
85
|
injectedAvailable: { type: integer }
|
|
80
86
|
injectedMissing: { type: array, items: { type: string } }
|
|
81
87
|
observedAvailable: { type: array, items: { type: string } }
|
|
88
|
+
metrics:
|
|
89
|
+
type: object
|
|
90
|
+
description: |
|
|
91
|
+
Optional runtime diagnostics attached to the same
|
|
92
|
+
`settings.read`-gated report (no separate route). Omitted
|
|
93
|
+
when the build has no metrics collector. Shape is
|
|
94
|
+
diagnostic and additive.
|
|
95
|
+
additionalProperties: true
|
|
82
96
|
'404':
|
|
83
97
|
description: The probe is not compiled into this build.
|
|
84
98
|
/pairings/exchange:
|
|
@@ -134,6 +148,32 @@ paths:
|
|
|
134
148
|
type: array
|
|
135
149
|
items: { $ref: '#/components/schemas/Root' }
|
|
136
150
|
'403': { $ref: '#/components/responses/Error' }
|
|
151
|
+
/roots/resolve:
|
|
152
|
+
get:
|
|
153
|
+
operationId: resolveAbsolutePath
|
|
154
|
+
summary: Map a host absolute path to its authorized root
|
|
155
|
+
description: |
|
|
156
|
+
Chat events carry server-absolute paths while `GET /roots` deliberately
|
|
157
|
+
omits root absolute paths, so clients cannot perform this mapping
|
|
158
|
+
themselves. Resolves `path` against the device's authorized roots using
|
|
159
|
+
realpath-normalized longest-prefix matching, then stat-checks the
|
|
160
|
+
target (rejecting symlinks inside the path) via the same machinery as
|
|
161
|
+
file content reads. The response never contains an absolute host path.
|
|
162
|
+
Requires `files.read`.
|
|
163
|
+
parameters:
|
|
164
|
+
- name: path
|
|
165
|
+
in: query
|
|
166
|
+
required: true
|
|
167
|
+
description: Absolute host path. Relative paths are rejected rather than guessed.
|
|
168
|
+
schema: { type: string, minLength: 1 }
|
|
169
|
+
responses:
|
|
170
|
+
'200':
|
|
171
|
+
description: Root match plus wire-relative metadata for the target.
|
|
172
|
+
content:
|
|
173
|
+
application/json:
|
|
174
|
+
schema: { $ref: '#/components/schemas/ResolvedPath' }
|
|
175
|
+
'400': { $ref: '#/components/responses/Error' }
|
|
176
|
+
'404': { $ref: '#/components/responses/Error' }
|
|
137
177
|
/roots/{rootId}/entries:
|
|
138
178
|
parameters:
|
|
139
179
|
- $ref: '#/components/parameters/RootId'
|
|
@@ -271,6 +311,74 @@ paths:
|
|
|
271
311
|
'200':
|
|
272
312
|
description: Item restored without overwriting an existing path.
|
|
273
313
|
'409': { $ref: '#/components/responses/Error' }
|
|
314
|
+
/image-handoff:
|
|
315
|
+
get:
|
|
316
|
+
operationId: readImageHandoff
|
|
317
|
+
summary: Fetch one handoff image for a chat session
|
|
318
|
+
description: |
|
|
319
|
+
Returns the raw bytes of an image the agent handed off (content-addressed
|
|
320
|
+
`sha256.<ext>` files written under the session working directory's
|
|
321
|
+
image-handoff subdirectory). `name` must be a bare file name only: the
|
|
322
|
+
directory is always derived by the host from the session working
|
|
323
|
+
directory, so no directory or absolute path can be supplied. Requires
|
|
324
|
+
`files.read` plus ownership of the session; "no such session" and "no
|
|
325
|
+
such file" are indistinguishable (both are 404). This authenticated REST
|
|
326
|
+
route is the device-side counterpart of the token-less browser route
|
|
327
|
+
`GET /plugin/dsh-remote-bridge/raw`.
|
|
328
|
+
parameters:
|
|
329
|
+
- name: sessionId
|
|
330
|
+
in: query
|
|
331
|
+
required: true
|
|
332
|
+
schema: { type: string }
|
|
333
|
+
- name: name
|
|
334
|
+
in: query
|
|
335
|
+
required: true
|
|
336
|
+
description: Bare handoff file name, e.g. `a1b2…e9.png`.
|
|
337
|
+
schema: { type: string, pattern: '^[0-9a-f]{64}\.[A-Za-z0-9]+$' }
|
|
338
|
+
responses:
|
|
339
|
+
'200':
|
|
340
|
+
description: Image bytes; handoff files are temporary artifacts, so the response is private and must be revalidated.
|
|
341
|
+
headers:
|
|
342
|
+
Cache-Control: { schema: { type: string }, description: private, max-age=0, must-revalidate }
|
|
343
|
+
content:
|
|
344
|
+
application/octet-stream:
|
|
345
|
+
schema: { type: string, contentEncoding: binary }
|
|
346
|
+
'400': { $ref: '#/components/responses/Error' }
|
|
347
|
+
'404': { $ref: '#/components/responses/Error' }
|
|
348
|
+
/attachments/{attachmentId}:
|
|
349
|
+
get:
|
|
350
|
+
operationId: readAttachment
|
|
351
|
+
summary: Fetch one session attachment's bytes
|
|
352
|
+
description: |
|
|
353
|
+
Returns the raw bytes of an image attachment referenced by a session
|
|
354
|
+
event. The attachment store is content-addressed, so `attachmentId`
|
|
355
|
+
contains a colon (typically `sha256:<hex>`) and **must be
|
|
356
|
+
percent-encoded in the URL** (`sha256%3A<hex>`). `sessionId` is a
|
|
357
|
+
required query parameter: the host verifies the session actually
|
|
358
|
+
references this attachment and validates bytes/media type against the
|
|
359
|
+
real reference stored in the session event. Requires `files.read` plus
|
|
360
|
+
ownership of the session. Bytes are immutable and may be cached
|
|
361
|
+
privately for a year.
|
|
362
|
+
parameters:
|
|
363
|
+
- name: attachmentId
|
|
364
|
+
in: path
|
|
365
|
+
required: true
|
|
366
|
+
description: Content-addressed attachment id, e.g. `sha256%3A<hex>` (the raw id is `sha256:<hex>` and must be percent-encoded).
|
|
367
|
+
schema: { type: string }
|
|
368
|
+
- name: sessionId
|
|
369
|
+
in: query
|
|
370
|
+
required: true
|
|
371
|
+
schema: { type: string }
|
|
372
|
+
responses:
|
|
373
|
+
'200':
|
|
374
|
+
description: Attachment bytes; immutable and privately cacheable.
|
|
375
|
+
headers:
|
|
376
|
+
Cache-Control: { schema: { type: string }, description: private, max-age=31536000, immutable }
|
|
377
|
+
content:
|
|
378
|
+
application/octet-stream:
|
|
379
|
+
schema: { type: string, contentEncoding: binary }
|
|
380
|
+
'400': { $ref: '#/components/responses/Error' }
|
|
381
|
+
'404': { $ref: '#/components/responses/Error' }
|
|
274
382
|
/chat/workspaces:
|
|
275
383
|
get:
|
|
276
384
|
operationId: listChatWorkspaces
|
|
@@ -471,6 +579,68 @@ paths:
|
|
|
471
579
|
content:
|
|
472
580
|
application/json:
|
|
473
581
|
schema: { $ref: '#/components/schemas/ModelCatalog' }
|
|
582
|
+
/settings/namespaces:
|
|
583
|
+
get:
|
|
584
|
+
operationId: listSettingsNamespaces
|
|
585
|
+
summary: Read every DSH plugin settings namespace
|
|
586
|
+
description: |
|
|
587
|
+
Returns the host's per-plugin settings document as one entry per namespace, so a
|
|
588
|
+
mobile client can build a form from `schema` without a dedicated endpoint per
|
|
589
|
+
plugin. Requires `settings.read`.
|
|
590
|
+
|
|
591
|
+
The top-level `writable` mirrors the host settings document. Each entry's
|
|
592
|
+
`writable` is that value AND the bridge's write policy: namespaces starting with
|
|
593
|
+
`ui-` or ending in `locale` are writable by default; high-risk ones (`llm-*`,
|
|
594
|
+
`permission`, `agent-default-model`, `subagent-*`, …) are read-only unless the
|
|
595
|
+
deployment explicitly allows them through `settingsWriteNamespaces`. When an
|
|
596
|
+
entry is not writable, `reason` says why: `HOST_READONLY` (the whole settings
|
|
597
|
+
document is read-only) or `HIGH_RISK_NAMESPACE` (write policy).
|
|
598
|
+
|
|
599
|
+
Secret values never leave the host: the kernel already redacts fields declared as
|
|
600
|
+
secrets, and the bridge additionally masks string values whose key matches
|
|
601
|
+
`apiKey|secret|token|password|credential|apiKeyEnv` with `***`.
|
|
602
|
+
responses:
|
|
603
|
+
'200':
|
|
604
|
+
description: All namespaces, with secret values redacted and per-namespace writability.
|
|
605
|
+
content:
|
|
606
|
+
application/json:
|
|
607
|
+
schema: { $ref: '#/components/schemas/SettingsNamespaces' }
|
|
608
|
+
'403': { $ref: '#/components/responses/Error' }
|
|
609
|
+
/settings/namespaces/{ns}:
|
|
610
|
+
parameters:
|
|
611
|
+
- name: ns
|
|
612
|
+
in: path
|
|
613
|
+
required: true
|
|
614
|
+
schema: { type: string }
|
|
615
|
+
description: Namespace id (a plugin name such as `ui-chat`).
|
|
616
|
+
patch:
|
|
617
|
+
operationId: mutateSettingsNamespace
|
|
618
|
+
description: |
|
|
619
|
+
Applies path-addressed `set` / `unset` operations to one namespace, mirroring the
|
|
620
|
+
kernel's `settings.mutate`. Requires `settings.write`; at most 32 operations per
|
|
621
|
+
request. A successful mutation is audited as `settings.namespace.mutate` with the
|
|
622
|
+
touched field paths only — never the values.
|
|
623
|
+
|
|
624
|
+
Only namespaces allowed by the write policy can be changed; others answer
|
|
625
|
+
403 `SETTINGS_NAMESPACE_READONLY`. `expectedRevision` is optimistic concurrency:
|
|
626
|
+
a mismatch answers 409 `SETTINGS_CONFLICT`; an invalid ops body answers
|
|
627
|
+
400 `SETTINGS_OPS_INVALID`; a missing host settings service answers
|
|
628
|
+
503 `SETTINGS_UNAVAILABLE`.
|
|
629
|
+
requestBody:
|
|
630
|
+
required: true
|
|
631
|
+
content:
|
|
632
|
+
application/json:
|
|
633
|
+
schema: { $ref: '#/components/schemas/SettingsNamespaceOps' }
|
|
634
|
+
responses:
|
|
635
|
+
'200':
|
|
636
|
+
description: The mutated namespace, in the same shape as one entry of `SettingsNamespaces.namespaces`.
|
|
637
|
+
content:
|
|
638
|
+
application/json:
|
|
639
|
+
schema: { $ref: '#/components/schemas/SettingsNamespaceSummary' }
|
|
640
|
+
'400': { $ref: '#/components/responses/Error' }
|
|
641
|
+
'403': { $ref: '#/components/responses/Error' }
|
|
642
|
+
'409': { $ref: '#/components/responses/Error' }
|
|
643
|
+
'503': { $ref: '#/components/responses/Error' }
|
|
474
644
|
/settings/providers/{providerId}:
|
|
475
645
|
parameters:
|
|
476
646
|
- name: providerId
|
|
@@ -784,6 +954,45 @@ paths:
|
|
|
784
954
|
responses:
|
|
785
955
|
'202': { description: Prompt accepted by DSH. }
|
|
786
956
|
'409': { $ref: '#/components/responses/Error' }
|
|
957
|
+
/chat/sessions/{sessionId}/attachments:
|
|
958
|
+
parameters:
|
|
959
|
+
- name: sessionId
|
|
960
|
+
in: path
|
|
961
|
+
required: true
|
|
962
|
+
schema: { type: string }
|
|
963
|
+
post:
|
|
964
|
+
operationId: uploadSessionAttachment
|
|
965
|
+
summary: Upload one attachment and receive a receipt
|
|
966
|
+
description: |
|
|
967
|
+
Uploads one attachment as base64 text and returns the receipt a later
|
|
968
|
+
message can reference. Kernel file-type content parts require this
|
|
969
|
+
`receiptId` (obtained through an upload); only image content parts may
|
|
970
|
+
be inlined as base64 directly in a message. Requires `chat.write` plus
|
|
971
|
+
ownership of the session. The request body is limited to 24 MiB.
|
|
972
|
+
requestBody:
|
|
973
|
+
required: true
|
|
974
|
+
content:
|
|
975
|
+
application/json:
|
|
976
|
+
schema:
|
|
977
|
+
type: object
|
|
978
|
+
required: [data]
|
|
979
|
+
properties:
|
|
980
|
+
data:
|
|
981
|
+
type: string
|
|
982
|
+
contentEncoding: base64
|
|
983
|
+
minLength: 1
|
|
984
|
+
description: Base64-encoded attachment bytes.
|
|
985
|
+
name:
|
|
986
|
+
type: string
|
|
987
|
+
description: Optional original file name; trimmed by the server.
|
|
988
|
+
responses:
|
|
989
|
+
'201':
|
|
990
|
+
description: Stored; the receipt id is referenced by later message file parts.
|
|
991
|
+
content:
|
|
992
|
+
application/json:
|
|
993
|
+
schema: { $ref: '#/components/schemas/AttachmentReceipt' }
|
|
994
|
+
'400': { $ref: '#/components/responses/Error' }
|
|
995
|
+
'404': { $ref: '#/components/responses/Error' }
|
|
787
996
|
/chat/sessions/{sessionId}/approvals:
|
|
788
997
|
get:
|
|
789
998
|
operationId: listPendingApprovals
|
|
@@ -994,6 +1203,24 @@ paths:
|
|
|
994
1203
|
schema: { $ref: '#/components/schemas/SessionModels' }
|
|
995
1204
|
'404': { $ref: '#/components/responses/Error' }
|
|
996
1205
|
/chat/sessions/{sessionId}/model:
|
|
1206
|
+
get:
|
|
1207
|
+
operationId: getSessionModelAlias
|
|
1208
|
+
description: |
|
|
1209
|
+
Alias of `GET /chat/sessions/{sessionId}/models`; the server route
|
|
1210
|
+
`model(?:s)?$` answers GET on both spellings. New clients should call
|
|
1211
|
+
`/models`.
|
|
1212
|
+
parameters:
|
|
1213
|
+
- name: sessionId
|
|
1214
|
+
in: path
|
|
1215
|
+
required: true
|
|
1216
|
+
schema: { type: string }
|
|
1217
|
+
responses:
|
|
1218
|
+
'200':
|
|
1219
|
+
description: Current selection and models routable for this DSH session.
|
|
1220
|
+
content:
|
|
1221
|
+
application/json:
|
|
1222
|
+
schema: { $ref: '#/components/schemas/SessionModels' }
|
|
1223
|
+
'404': { $ref: '#/components/responses/Error' }
|
|
997
1224
|
put:
|
|
998
1225
|
operationId: selectSessionModel
|
|
999
1226
|
parameters:
|
|
@@ -1155,6 +1382,24 @@ components:
|
|
|
1155
1382
|
id: { type: string, format: uuid }
|
|
1156
1383
|
label: { type: string }
|
|
1157
1384
|
createdAt: { type: integer }
|
|
1385
|
+
ResolvedPath:
|
|
1386
|
+
type: object
|
|
1387
|
+
description: Result of mapping an absolute host path into an authorized root; the root's absolute path itself is never included.
|
|
1388
|
+
required: [rootId, path, kind, size, modifiedAt, contentType]
|
|
1389
|
+
properties:
|
|
1390
|
+
rootId: { type: string, format: uuid }
|
|
1391
|
+
path: { $ref: '#/components/schemas/WirePath' }
|
|
1392
|
+
kind: { type: string, enum: [file, directory] }
|
|
1393
|
+
size: { type: integer, nullable: true }
|
|
1394
|
+
modifiedAt: { type: integer, nullable: true }
|
|
1395
|
+
contentType: { type: string, nullable: true }
|
|
1396
|
+
AttachmentReceipt:
|
|
1397
|
+
type: object
|
|
1398
|
+
description: Upload receipt referenced later as a file-type content part in a message.
|
|
1399
|
+
required: [receiptId, name]
|
|
1400
|
+
properties:
|
|
1401
|
+
receiptId: { type: string }
|
|
1402
|
+
name: { type: string, nullable: true }
|
|
1158
1403
|
Device:
|
|
1159
1404
|
type: object
|
|
1160
1405
|
required: [id, name, scopes, rootIds]
|
|
@@ -1441,6 +1686,83 @@ components:
|
|
|
1441
1686
|
providers:
|
|
1442
1687
|
type: array
|
|
1443
1688
|
items: { $ref: '#/components/schemas/Provider' }
|
|
1689
|
+
SettingsNamespaceSecret:
|
|
1690
|
+
type: object
|
|
1691
|
+
description: One secret slot reported by the host. Only its path and whether it is set are exposed, never the value.
|
|
1692
|
+
required: [path, set]
|
|
1693
|
+
properties:
|
|
1694
|
+
path:
|
|
1695
|
+
type: array
|
|
1696
|
+
items: { type: string }
|
|
1697
|
+
set: { type: boolean }
|
|
1698
|
+
SettingsNamespaceSummary:
|
|
1699
|
+
type: object
|
|
1700
|
+
description: One DSH settings namespace as seen by a remote client, with secret values redacted.
|
|
1701
|
+
required: [ns, revision, value, writable]
|
|
1702
|
+
properties:
|
|
1703
|
+
ns: { type: string, examples: [ui-chat, ui-theme] }
|
|
1704
|
+
revision: { type: integer, minimum: 0 }
|
|
1705
|
+
schema:
|
|
1706
|
+
type: object
|
|
1707
|
+
additionalProperties: true
|
|
1708
|
+
description: Kernel schema tree for form generation; its shape is kernel-defined.
|
|
1709
|
+
value:
|
|
1710
|
+
description: Effective value (base merged with user overrides), recursively redacted.
|
|
1711
|
+
base:
|
|
1712
|
+
description: Built-in default value, recursively redacted.
|
|
1713
|
+
user:
|
|
1714
|
+
description: User overrides only, recursively redacted.
|
|
1715
|
+
autoGenerate:
|
|
1716
|
+
type: object
|
|
1717
|
+
additionalProperties: true
|
|
1718
|
+
description: Kernel-reported fields that are generated automatically.
|
|
1719
|
+
applies:
|
|
1720
|
+
type: object
|
|
1721
|
+
additionalProperties: true
|
|
1722
|
+
description: Kernel-reported applicability conditions for this namespace.
|
|
1723
|
+
secrets:
|
|
1724
|
+
type: array
|
|
1725
|
+
items: { $ref: '#/components/schemas/SettingsNamespaceSecret' }
|
|
1726
|
+
writable:
|
|
1727
|
+
type: boolean
|
|
1728
|
+
description: The host document is writable AND this namespace passes the bridge's write policy.
|
|
1729
|
+
reason:
|
|
1730
|
+
type: string
|
|
1731
|
+
enum: [HOST_READONLY, HIGH_RISK_NAMESPACE]
|
|
1732
|
+
description: Present only when `writable` is false.
|
|
1733
|
+
SettingsNamespaces:
|
|
1734
|
+
type: object
|
|
1735
|
+
required: [writable, namespaces]
|
|
1736
|
+
properties:
|
|
1737
|
+
writable:
|
|
1738
|
+
type: boolean
|
|
1739
|
+
description: Whether the host settings document itself is writable.
|
|
1740
|
+
namespaces:
|
|
1741
|
+
type: array
|
|
1742
|
+
items: { $ref: '#/components/schemas/SettingsNamespaceSummary' }
|
|
1743
|
+
SettingsNamespaceOps:
|
|
1744
|
+
type: object
|
|
1745
|
+
description: Path-addressed operations and optional optimistic-concurrency revision.
|
|
1746
|
+
required: [ops]
|
|
1747
|
+
properties:
|
|
1748
|
+
ops:
|
|
1749
|
+
type: array
|
|
1750
|
+
minItems: 1
|
|
1751
|
+
maxItems: 32
|
|
1752
|
+
items:
|
|
1753
|
+
oneOf:
|
|
1754
|
+
- type: object
|
|
1755
|
+
required: [op, path, value]
|
|
1756
|
+
properties:
|
|
1757
|
+
op: { type: string, const: set }
|
|
1758
|
+
path: { type: array, items: { type: string } }
|
|
1759
|
+
value: {}
|
|
1760
|
+
- type: object
|
|
1761
|
+
required: [op, path]
|
|
1762
|
+
properties:
|
|
1763
|
+
op: { type: string, const: unset }
|
|
1764
|
+
path: { type: array, items: { type: string } }
|
|
1765
|
+
expectedRevision: { type: integer, minimum: 0 }
|
|
1444
1766
|
ProviderPatch:
|
|
1445
1767
|
type: object
|
|
1446
1768
|
properties:
|