@deepseek-ai/dsh-experimental-inspector 0.1.6-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.
- package/LICENSE +21 -0
- package/README.i18n.yaml +6 -0
- package/README.md +156 -0
- package/README.zh.md +156 -0
- package/lib/client.js +3424 -0
- package/lib/index.js +2406 -0
- package/lib/types/client/bridge/controller.d.ts +10 -0
- package/lib/types/client/bridge/dispatcher.d.ts +26 -0
- package/lib/types/client/bridge/lifecycle.d.ts +20 -0
- package/lib/types/client/bridge/publisher.d.ts +42 -0
- package/lib/types/client/bridge/rpc.d.ts +13 -0
- package/lib/types/client/bridge/transport.d.ts +34 -0
- package/lib/types/client/cdp/console.d.ts +45 -0
- package/lib/types/client/cdp/debugger.d.ts +8 -0
- package/lib/types/client/cdp/errors.d.ts +8 -0
- package/lib/types/client/cdp/heap-profiler.d.ts +8 -0
- package/lib/types/client/cdp/index.d.ts +10 -0
- package/lib/types/client/cdp/objects.d.ts +69 -0
- package/lib/types/client/cdp/profiler.d.ts +8 -0
- package/lib/types/client/cdp/properties.d.ts +16 -0
- package/lib/types/client/cdp/runtime.d.ts +79 -0
- package/lib/types/client/cdp/sources.d.ts +52 -0
- package/lib/types/client/cdp/stack.d.ts +27 -0
- package/lib/types/client/index.d.ts +3 -0
- package/lib/types/client/inspection/cordis.d.ts +3 -0
- package/lib/types/client/inspection/network.d.ts +4 -0
- package/lib/types/client/inspection/realm.d.ts +27 -0
- package/lib/types/client/plugin.d.ts +28 -0
- package/lib/types/host/bridge/controller.d.ts +108 -0
- package/lib/types/host/bridge/dispatcher.d.ts +16 -0
- package/lib/types/host/bridge/lifecycle.d.ts +42 -0
- package/lib/types/host/bridge/publisher.d.ts +31 -0
- package/lib/types/host/bridge/rpc.d.ts +15 -0
- package/lib/types/host/bridge/transport.d.ts +28 -0
- package/lib/types/host/cdp/console.d.ts +14 -0
- package/lib/types/host/cdp/debugger.d.ts +8 -0
- package/lib/types/host/cdp/errors.d.ts +6 -0
- package/lib/types/host/cdp/heap-profiler.d.ts +8 -0
- package/lib/types/host/cdp/index.d.ts +10 -0
- package/lib/types/host/cdp/objects.d.ts +8 -0
- package/lib/types/host/cdp/profiler.d.ts +8 -0
- package/lib/types/host/cdp/properties.d.ts +7 -0
- package/lib/types/host/cdp/runtime.d.ts +16 -0
- package/lib/types/host/cdp/sources.d.ts +14 -0
- package/lib/types/host/cdp/stack.d.ts +4 -0
- package/lib/types/host/index.d.ts +3 -0
- package/lib/types/host/inspection/cordis.d.ts +3 -0
- package/lib/types/host/inspection/network.d.ts +23 -0
- package/lib/types/host/inspection/realm.d.ts +9 -0
- package/lib/types/host/plugin.d.ts +19 -0
- package/lib/types/index.d.ts +50 -0
- package/lib/types/shared/bridge/buffer.d.ts +62 -0
- package/lib/types/shared/bridge/codec.d.ts +4 -0
- package/lib/types/shared/bridge/control-codec.d.ts +27 -0
- package/lib/types/shared/bridge/ids.d.ts +19 -0
- package/lib/types/shared/bridge/messages/control.d.ts +64 -0
- package/lib/types/shared/bridge/messages/cordis.d.ts +4 -0
- package/lib/types/shared/bridge/messages/network.d.ts +4 -0
- package/lib/types/shared/bridge/messages/observation.d.ts +110 -0
- package/lib/types/shared/bridge/messages/query/codec.d.ts +40 -0
- package/lib/types/shared/bridge/messages/query/commands.d.ts +35 -0
- package/lib/types/shared/bridge/messages/query/frames.d.ts +31 -0
- package/lib/types/shared/bridge/messages/query/index.d.ts +5 -0
- package/lib/types/shared/bridge/messages/runtime/command-codec.d.ts +9 -0
- package/lib/types/shared/bridge/messages/runtime/commands.d.ts +76 -0
- package/lib/types/shared/bridge/messages/runtime/console-frames.d.ts +52 -0
- package/lib/types/shared/bridge/messages/runtime/frames.d.ts +98 -0
- package/lib/types/shared/bridge/messages/runtime/index.d.ts +5 -0
- package/lib/types/shared/bridge/messages/runtime/value-codec.d.ts +28 -0
- package/lib/types/shared/bridge/messages/sources/codec.d.ts +15 -0
- package/lib/types/shared/bridge/messages/sources/commands.d.ts +42 -0
- package/lib/types/shared/bridge/messages/sources/frames.d.ts +67 -0
- package/lib/types/shared/bridge/messages/sources/index.d.ts +5 -0
- package/lib/types/shared/bridge/publisher.d.ts +33 -0
- package/lib/types/shared/bridge/query-reader.d.ts +10 -0
- package/lib/types/shared/bridge/rpc.d.ts +62 -0
- package/lib/types/shared/bridge/validation.d.ts +3 -0
- package/lib/types/shared/bridge/version.d.ts +3 -0
- package/lib/types/shared/cdp/capabilities.d.ts +17 -0
- package/lib/types/shared/cdp/console.d.ts +28 -0
- package/lib/types/shared/cdp/debugger.d.ts +69 -0
- package/lib/types/shared/cdp/errors.d.ts +27 -0
- package/lib/types/shared/cdp/ids.d.ts +9 -0
- package/lib/types/shared/cdp/index.d.ts +11 -0
- package/lib/types/shared/cdp/operations.d.ts +86 -0
- package/lib/types/shared/cdp/property.d.ts +28 -0
- package/lib/types/shared/cdp/realm.d.ts +137 -0
- package/lib/types/shared/cdp/remote-object.d.ts +44 -0
- package/lib/types/shared/cdp/sources.d.ts +18 -0
- package/lib/types/shared/cordis/collector.d.ts +26 -0
- package/lib/types/shared/cordis/ids.d.ts +7 -0
- package/lib/types/shared/cordis/model.d.ts +61 -0
- package/lib/types/shared/cordis/object-reference.d.ts +14 -0
- package/lib/types/shared/cordis/object-registry.d.ts +80 -0
- package/lib/types/shared/cordis/observer.d.ts +15 -0
- package/lib/types/shared/cordis/projector.d.ts +34 -0
- package/lib/types/shared/cordis/publisher.d.ts +13 -0
- package/lib/types/shared/cordis/reader.d.ts +18 -0
- package/lib/types/shared/cordis/snapshot.d.ts +39 -0
- package/lib/types/shared/identity.d.ts +12 -0
- package/lib/types/shared/index.d.ts +18 -0
- package/lib/types/shared/json.d.ts +35 -0
- package/lib/types/shared/network/event-source.d.ts +20 -0
- package/lib/types/shared/network/observation.d.ts +52 -0
- package/lib/types/shared/service.d.ts +23 -0
- package/lib/types/shared/validation.d.ts +52 -0
- package/lib/types/worker/bridge/endpoint.d.ts +49 -0
- package/lib/types/worker/bridge/hub.d.ts +108 -0
- package/lib/types/worker/bridge/runtime-rpc.d.ts +90 -0
- package/lib/types/worker/bridge/session.d.ts +15 -0
- package/lib/types/worker/bridge/source-rpc.d.ts +42 -0
- package/lib/types/worker/cdp/domains/debugger/cdp-params.d.ts +15 -0
- package/lib/types/worker/cdp/domains/debugger/index.d.ts +6 -0
- package/lib/types/worker/cdp/domains/debugger/projector.d.ts +22 -0
- package/lib/types/worker/cdp/domains/debugger/script-registry.d.ts +70 -0
- package/lib/types/worker/cdp/domains/debugger/session.d.ts +47 -0
- package/lib/types/worker/cdp/domains/dom/index.d.ts +4 -0
- package/lib/types/worker/cdp/domains/dom/model.d.ts +108 -0
- package/lib/types/worker/cdp/domains/dom/session.d.ts +74 -0
- package/lib/types/worker/cdp/domains/native.d.ts +25 -0
- package/lib/types/worker/cdp/domains/network/session.d.ts +46 -0
- package/lib/types/worker/cdp/domains/runtime/cdp-params.d.ts +82 -0
- package/lib/types/worker/cdp/domains/runtime/index.d.ts +3 -0
- package/lib/types/worker/cdp/domains/runtime/object-table.d.ts +117 -0
- package/lib/types/worker/cdp/domains/runtime/session.d.ts +97 -0
- package/lib/types/worker/cdp/ids.d.ts +37 -0
- package/lib/types/worker/cdp/protocol.d.ts +46 -0
- package/lib/types/worker/cdp/realm-sessions.d.ts +64 -0
- package/lib/types/worker/cdp/session.d.ts +34 -0
- package/lib/types/worker/cdp/target.d.ts +17 -0
- package/lib/types/worker/entry.d.ts +3 -0
- package/lib/types/worker/inspection/cordis-query.d.ts +11 -0
- package/lib/types/worker/inspection/cordis-store.d.ts +94 -0
- package/lib/types/worker/inspection/network-store.d.ts +110 -0
- package/lib/types/worker/inspection/query-router.d.ts +78 -0
- package/lib/types/worker/inspection/realm-store.d.ts +58 -0
- package/lib/types/worker/inspection/realm.d.ts +43 -0
- package/lib/types/worker/realms/client/bridge.d.ts +18 -0
- package/lib/types/worker/realms/client/console.d.ts +21 -0
- package/lib/types/worker/realms/client/debugger.d.ts +8 -0
- package/lib/types/worker/realms/client/index.d.ts +18 -0
- package/lib/types/worker/realms/client/runtime.d.ts +28 -0
- package/lib/types/worker/realms/client/scripts.d.ts +15 -0
- package/lib/types/worker/realms/client/sources.d.ts +30 -0
- package/lib/types/worker/realms/client/values.d.ts +55 -0
- package/lib/types/worker/realms/host/bridge.d.ts +49 -0
- package/lib/types/worker/realms/host/console.d.ts +25 -0
- package/lib/types/worker/realms/host/debugger.d.ts +25 -0
- package/lib/types/worker/realms/host/index.d.ts +13 -0
- package/lib/types/worker/realms/host/runtime.d.ts +54 -0
- package/lib/types/worker/realms/host/scripts.d.ts +9 -0
- package/lib/types/worker/realms/host/sources.d.ts +26 -0
- package/lib/types/worker/realms/host/values.d.ts +22 -0
- package/lib/types/worker/server.d.ts +16 -0
- package/lib/worker.js +7184 -0
- package/package.json +64 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 DeepSeek
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.i18n.yaml
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
|
2
|
+
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
|
+
# after editing either side, bring the other along and re-record with:
|
|
4
|
+
# pnpm run verify-translation-pairing --write packages/experimental/inspector/README.md
|
|
5
|
+
README.md: 2b2986d49bbc970c70cc7bc85de38ba6fb6d9593
|
|
6
|
+
README.zh.md: a24b17d3a8a88736fe5efe83b4185de9379b5903
|
package/README.md
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Experimental Chrome DevTools inspection for Host and browser Client Cordis runtimes, including Console evaluation, Sources, Network capture, Elements trees, and a CDP-independent query API."
|
|
3
|
+
kind: "package-reference"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @deepseek-ai/dsh-experimental-inspector
|
|
7
|
+
|
|
8
|
+
English | [中文](README.zh.md)
|
|
9
|
+
|
|
10
|
+
## Summary
|
|
11
|
+
|
|
12
|
+
Use this experimental inspector to inspect one running dsh Host and its browser Clients in Chrome DevTools. It exposes Host and Client Console contexts, Host Sources and debugging, captured Host fetches, and a shared Cordis tree while keeping all CDP state in a Worker.
|
|
13
|
+
|
|
14
|
+
The package publishes under its experimental name and requires an explicit composition. The Worker never accesses live Cordis objects: the shared Host/Client collector projects them into validated snapshots before transport. Cordis also owns plugin composition, `ctx.inspector` registration, bootstrap injection, and disposal.
|
|
15
|
+
|
|
16
|
+
## Table of Contents
|
|
17
|
+
|
|
18
|
+
- [Runtime layout](#runtime-layout)
|
|
19
|
+
- [Configuration](#configuration)
|
|
20
|
+
- [Observation API](#observation-api)
|
|
21
|
+
- [Cordis tree inspection](#cordis-tree-inspection)
|
|
22
|
+
- [Host fetch capture](#host-fetch-capture)
|
|
23
|
+
- [Security](#security)
|
|
24
|
+
- [Model Experience](#model-experience)
|
|
25
|
+
- [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
|
|
26
|
+
- [Dev Note](#dev-note)
|
|
27
|
+
|
|
28
|
+
-----
|
|
29
|
+
|
|
30
|
+
<a id="runtime-layout"></a>
|
|
31
|
+
## Runtime layout
|
|
32
|
+
|
|
33
|
+
The Host plugin starts the Worker and connects a dedicated `MessagePort`. The Client plugin reads the injected `globalThis.__DSH_INSPECTOR__` bootstrap and opens a separate authenticated WebSocket directly to the Worker. Chrome DevTools connects to the Worker's CDP WebSocket. A private `node:inspector.Session` per DevTools connection attaches from the Worker to the Host main thread, so Host Console evaluation, Sources, breakpoints, and resume remain available while Host JavaScript is paused.
|
|
34
|
+
|
|
35
|
+
The source tree follows those execution environments: `client/` and `host/` provide mirrored adapter entry paths, `worker/` contains only Worker-thread orchestration and Chrome protocol state, and `shared/` contains environment-independent Cordis and network models, normalized realm backend interfaces, and the internal bridge protocol. Worker-side Client and Host adapters are mirrored under `worker/realms/`; a Client adapter in that directory still executes in the Worker.
|
|
36
|
+
|
|
37
|
+
Host and Client producers send internal observation records rather than CDP messages. Records contain a source generation, sequence, source-clock timestamp, topic, and JSON payload. The Worker validates every process or network frame, owns source state and retention, and translates recognized topics to standard CDP domains.
|
|
38
|
+
|
|
39
|
+
Client sources declare typed Runtime, Console, and read-only Sources capabilities. `Runtime.enable` publishes the real Host execution context and one synthetic context for every connected Client source. Selecting a Client context routes evaluation, property access, function calls, promise awaiting, and object release to that browser realm. Client Console arguments use the same session-local object table, while `Debugger.enable` publishes the built `lib/client.js` catalog and `Debugger.getScriptSource` reads bounded content chunks. Client-script breakpoints, step, and call frames remain unsupported; target-wide pause and resume control the Host debugger only.
|
|
40
|
+
|
|
41
|
+
Both plugin faces run the same browser-safe Cordis collector. It converts reachable Context and Fiber objects into a versioned `CordisTreeSnapshot`; the Worker stores that CDP-independent representation and projects each Host or Client source into the Elements panel.
|
|
42
|
+
|
|
43
|
+
<a id="configuration"></a>
|
|
44
|
+
## Configuration
|
|
45
|
+
|
|
46
|
+
The Host plugin injects `webServer` and accepts these fields:
|
|
47
|
+
|
|
48
|
+
| Field | Default | Meaning |
|
|
49
|
+
|---|---:|---|
|
|
50
|
+
| `host` | `127.0.0.1` | Worker endpoint bind address; only loopback is accepted |
|
|
51
|
+
| `port` | `9230` | First Worker endpoint port; occupied ports advance upward, while `0` requests an OS-assigned port |
|
|
52
|
+
| `clientOrigins` | `[]` | Additional exact browser origins accepted by `/ingest`; loopback origins remain accepted |
|
|
53
|
+
| `captureFetch` | `true` | Wrap `globalThis.fetch` and publish every later call |
|
|
54
|
+
| `maxRequestBodyBytes` | 8 MiB | Per-request captured request-body prefix |
|
|
55
|
+
| `maxResponseBodyBytes` | 32 MiB | Per-request captured response-body prefix |
|
|
56
|
+
| `maxBodyChunkBytes` | 48 KiB | Raw bytes carried by one body record before base64 encoding |
|
|
57
|
+
| `maxJournalBytes` | 256 MiB | Worker-retained request and response body bytes |
|
|
58
|
+
| `maxRetainedRequests` | `2000` | Active and completed requests retained by the Worker |
|
|
59
|
+
| `maxSourceFrameBytes` | 128 KiB | Encoded source-frame limit |
|
|
60
|
+
| `maxSourceRecordsPerFrame` | `128` | Records in one source batch |
|
|
61
|
+
| `maxQueuedRecords` | `2048` | Per-producer records waiting for transport |
|
|
62
|
+
| `maxQueuedBytes` | 16 MiB | Per-producer queued encoded bytes |
|
|
63
|
+
| `startupTimeoutMs` | 10 seconds | Worker readiness deadline |
|
|
64
|
+
| `stopTimeoutMs` | 5 seconds | Graceful Worker shutdown deadline before termination |
|
|
65
|
+
| `clientReconnectBaseMs` | 250 ms | First Client reconnect backoff cap |
|
|
66
|
+
| `clientReconnectMaxMs` | 5 seconds | Maximum Client reconnect backoff cap |
|
|
67
|
+
| `clientRuntimeTimeoutMs` | 30 seconds | Deadline for one Worker-to-Client Runtime or Sources command |
|
|
68
|
+
| `queryTimeoutMs` | 10 seconds | Deadline for one non-CDP semantic query |
|
|
69
|
+
| `maxClientRuntimeObjects` | `10000` | Live Client object handles retained per DevTools connection |
|
|
70
|
+
| `maxClientRuntimeProperties` | `2000` | Property descriptors returned by one Client object inspection |
|
|
71
|
+
| `maxClientSourceBytes` | 8 MiB | Maximum encoded bytes read from one Client script or source map |
|
|
72
|
+
| `maxCordisNodes` | `2048` | Context and Fiber nodes admitted from one realm snapshot before truncation |
|
|
73
|
+
| `maxDisconnectedCordisTrees` | `8` | Last disconnected realm trees retained as non-live snapshots |
|
|
74
|
+
|
|
75
|
+
The generated [configuration catalog](../../../docs/config-catalog.md#deepseek-aidsh-experimental-inspector) is the exhaustive source for accepted fields and their declarations.
|
|
76
|
+
|
|
77
|
+
The Host logs a `devtools://` URL after the Worker listens. The same Worker serves `/json`, `/json/list`, `/json/version`, the target WebSocket under `/devtools/page/<id>`, and the Client source at `/ingest`.
|
|
78
|
+
|
|
79
|
+
<a id="observation-api"></a>
|
|
80
|
+
## Observation API
|
|
81
|
+
|
|
82
|
+
Both plugin faces provide the same service:
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
86
|
+
import type { InspectorJsonValue } from '@deepseek-ai/dsh-experimental-inspector'
|
|
87
|
+
|
|
88
|
+
declare const ctx: Context
|
|
89
|
+
declare const topic: string
|
|
90
|
+
declare const jsonPayload: InspectorJsonValue
|
|
91
|
+
|
|
92
|
+
ctx.inspector.publish(topic, jsonPayload)
|
|
93
|
+
await ctx.inspector.cordis.getTree()
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Publishing validates lossless JSON and schedules delivery without waiting for the Worker. Each source has a bounded queue. Overflow is reported as a sequence gap and never delays the observed application operation. `cordis.getTree()` reads the Worker's latest detached semantic snapshot without creating a CDP session or enabling Runtime, Debugger, or Sources.
|
|
97
|
+
|
|
98
|
+
<a id="cordis-tree-inspection"></a>
|
|
99
|
+
## Cordis tree inspection
|
|
100
|
+
|
|
101
|
+
The Elements document has fixed `<host>` and `<clients>` containers. `<host>` contains the Host root Context; `<clients>` contains one `<client>` per Client source, and each `<client>` contains that realm's root Context. The Cordis root Fiber is omitted. Every other Fiber is a child of `fiber.parent`, owns exactly one Context child for `fiber.ctx`, and carries only `uid="<Cordis Fiber.uid>"`; Context elements have no attributes. Context-only `extend()`, `isolate()`, and `intercept()` layers remain direct Context descendants.
|
|
102
|
+
|
|
103
|
+
Host and Client publish the same nested `CordisTreeSnapshot` type. Context and Fiber nodes carry opaque object handles for realm-local object lookup; Fiber nodes additionally carry Cordis `uid`. The Worker composes those realm snapshots into one `{ host, clients }` inspection tree. It assigns `BackendNodeId` values per source generation; each DevTools connection assigns its own `NodeId` values; `DOM.resolveNode` asks the owning Host or Client Runtime for a connection-local `RemoteObjectId`. `DOM.requestNode` maps that object id back to the same Elements node. `ctx.inspector.cordis.getTree()` and `DSHInspector.getCordisTree` read the detached consumer-neutral tree without routing handles or CDP ids.
|
|
104
|
+
|
|
105
|
+
Node delivery is depth-limited per DevTools connection: `DOM.getDocument` serves three document levels when the caller omits `depth`, withheld levels advertise `childNodeCount`, and expansion fetches them through `DOM.requestChildNodes` (`depth: -1` for a whole subtree). NodeIds leaving through `DOM.performSearch`, `DOM.requestNode`, or `DOM.pushNodesByBackendIdsToFrontend` first push the not-yet-sent ancestor levels as `DOM.setChildNodes` events.
|
|
106
|
+
|
|
107
|
+
Sources publish complete snapshots, while the Worker compares stable backend node identities before notifying DevTools. Unchanged snapshots emit no DOM event; additions, removals, and attribute changes use node-level CDP events, inserted-node payloads withhold their subtree, and sibling reordering replaces only that parent's children. Existing `NodeId` values and unaffected Elements expansion remain stable.
|
|
108
|
+
|
|
109
|
+
When a Client disconnects, its Console execution context and live object ids are destroyed immediately. With disconnected-tree retention enabled, Elements keeps the last tree unchanged while connection state remains in the inspection model rather than becoming an unreviewed DOM attribute. Reconnection keeps the logical source id, creates a new synthetic CDP context id for the new transport generation, and replaces the stale tree after its complete snapshot arrives. The Client retains its logical id in `sessionStorage` and claims it through Web Locks for the page lifetime, so refresh reuses the id while a duplicated live tab receives a new one. The Worker retains at most `maxDisconnectedCordisTrees` such snapshots; zero removes them immediately.
|
|
110
|
+
|
|
111
|
+
<a id="host-fetch-capture"></a>
|
|
112
|
+
## Host fetch capture
|
|
113
|
+
|
|
114
|
+
Fetch capture is on by default and records the complete URL, all request and response headers, request body, response body, status, timing, errors, and cancellation. It does not redact credentials, cookies, query values, or payloads. Body capture reads clones; the caller receives the original Response as soon as the original fetch resolves.
|
|
115
|
+
|
|
116
|
+
The configured body limits bound retention rather than select fields: capture keeps the prefix and marks the result truncated. `Network.getRequestPostData` and `Network.getResponseBody` read the Worker's retained bytes. `Network.streamResourceContent` returns the buffered prefix and adds later response bytes to `Network.dataReceived` for that DevTools connection, which drives live Response and EventStream views. Direct Undici Client/Dispatcher calls and fetch references retained before plugin activation are outside this observer.
|
|
117
|
+
|
|
118
|
+
After response headers arrive, a caller-side abort can stop the observer's clone; captured bytes remain available through `Network.getResponseBody`, capture metadata records the error and truncation, and CDP emits `Network.loadingFinished` because fetch returned a Response. A fetch rejection before response headers emits `Network.loadingFailed`, with `canceled: true` for an abort.
|
|
119
|
+
|
|
120
|
+
<a id="security"></a>
|
|
121
|
+
## Security
|
|
122
|
+
|
|
123
|
+
The CDP target grants arbitrary code execution in both Host and connected Client realms through `Runtime.evaluate`; Host Debugger operations provide additional control. Full fetch capture includes secrets. The Worker therefore accepts only a `127.0.0.1` bind address. Client ingest additionally requires a random WebSocket subprotocol token injected by the Host and rejects non-loopback origins unless explicitly configured. The CDP socket itself has no token; loopback binding is its only access control.
|
|
124
|
+
|
|
125
|
+
<a id="model-experience"></a>
|
|
126
|
+
## Model Experience
|
|
127
|
+
|
|
128
|
+
None, as this developer-only inspector observes runtime activity without changing model requests.
|
|
129
|
+
|
|
130
|
+
#### KV Cache effect
|
|
131
|
+
|
|
132
|
+
None; this package neither assembles nor sends a provider request.
|
|
133
|
+
|
|
134
|
+
## Known Limitations and Deferred Work
|
|
135
|
+
|
|
136
|
+
<a id="known-limitations-and-deferred-work"></a>
|
|
137
|
+
|
|
138
|
+
- **Client active debugging is unsupported** — Console events, Runtime evaluation, RemoteObject access, and read-only `lib/client.js` Sources work. Client-script debugger requests return explicit unsupported errors; target-wide pause and resume control the Host only.
|
|
139
|
+
- **Client Sources expose the Inspector bundle only** — other page scripts are not cataloged by this package.
|
|
140
|
+
- **Client evaluation uses page JavaScript** — page Content Security Policy can block dynamic evaluation, and the synthetic context does not provide DevTools command-line helpers or native REPL declaration semantics.
|
|
141
|
+
- **Client identity arbitration requires Web Locks** — browsers without that API retain reconnect and refresh identity through `sessionStorage`, but cannot distinguish two simultaneously live tabs copied from the same storage state.
|
|
142
|
+
- **Fetch interception covers `globalThis.fetch`** — direct Undici APIs and fetch references retained before activation are not observed.
|
|
143
|
+
- **Body cloning has cost** — full capture tees request and response streams up to the configured limits and can increase memory and I/O pressure. The retained-body limit does not include buffering inside the stream tee, including an oversized source chunk or data queued for a slower application reader.
|
|
144
|
+
- **No automatic Worker restart** — an unexpected Worker exit fails the current Inspector instance; lifecycle recovery belongs to a later change.
|
|
145
|
+
|
|
146
|
+
<a id="dev-note"></a>
|
|
147
|
+
### Dev Note
|
|
148
|
+
|
|
149
|
+
<details>
|
|
150
|
+
<summary>Working context for maintainers — click to expand</summary>
|
|
151
|
+
|
|
152
|
+
None.
|
|
153
|
+
|
|
154
|
+
</details>
|
|
155
|
+
|
|
156
|
+
**Runtime invariant:** No companion is published. Wire parsing, generations, Worker lifecycle, and CDP sessions reject invalid relationships in their owning operations.
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "面向 Host 与浏览器 Client Cordis 运行时的实验性 Chrome DevTools 检查,包括 Console 求值、Sources、Network 采集、Elements 树和独立于 CDP 的查询 API。"
|
|
3
|
+
kind: "package-reference"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @deepseek-ai/dsh-experimental-inspector
|
|
7
|
+
|
|
8
|
+
[English](README.md) | 中文
|
|
9
|
+
|
|
10
|
+
## 概述
|
|
11
|
+
|
|
12
|
+
使用这个实验性 Inspector,可以在 Chrome DevTools 中检查一个运行中的 dsh Host 及其浏览器 Client。它提供 Host 与 Client Console context、Host Sources 与调试、Host fetch 采集和共享 Cordis 树,并让 Worker 独占全部 CDP 状态。
|
|
13
|
+
|
|
14
|
+
本包以实验性名称发布,需要显式组合。Worker 不访问实时 Cordis 对象;共享 Host/Client collector 会在传输前把它们投影成已验证快照。Cordis 还负责插件组合、注册 `ctx.inspector`、注入 bootstrap 和 dispose(资源释放)。
|
|
15
|
+
|
|
16
|
+
## 目录
|
|
17
|
+
|
|
18
|
+
- [运行时布局](#runtime-layout)
|
|
19
|
+
- [配置](#configuration)
|
|
20
|
+
- [观测 API](#observation-api)
|
|
21
|
+
- [Cordis 树检查](#cordis-tree-inspection)
|
|
22
|
+
- [Host fetch 采集](#host-fetch-capture)
|
|
23
|
+
- [安全](#security)
|
|
24
|
+
- [模型体验](#model-experience)
|
|
25
|
+
- [已知限制与延期工作](#known-limitations-and-deferred-work)
|
|
26
|
+
- [开发备注](#dev-note)
|
|
27
|
+
|
|
28
|
+
-----
|
|
29
|
+
|
|
30
|
+
<a id="runtime-layout"></a>
|
|
31
|
+
## 运行时布局
|
|
32
|
+
|
|
33
|
+
Host 插件启动 Worker 并连接专用 `MessagePort`。Client 插件读取注入的 `globalThis.__DSH_INSPECTOR__` bootstrap,直接向 Worker 打开一条独立、带鉴权的 WebSocket。Chrome DevTools 连接 Worker 的 CDP WebSocket。每条 DevTools 连接在 Worker 中独占一个连接 Host 主线程的 `node:inspector.Session`,因此 Host JavaScript 暂停时,Host Console 求值、Sources、断点和 resume 仍然可用。
|
|
34
|
+
|
|
35
|
+
源码树遵循这些执行环境:`client/` 与 `host/` 提供镜像的适配器 entry path,`worker/` 只包含 Worker thread orchestration 与 Chrome protocol 状态,`shared/` 包含与环境无关的 Cordis 和 network model、规范化 realm 后端接口及内部 bridge protocol。Worker 侧 Client 与 Host 适配器镜像放在 `worker/realms/` 下;其中的 Client 适配器仍然在 Worker 中执行。
|
|
36
|
+
|
|
37
|
+
Host 与 Client producer 发送内部观测记录,不发送 CDP 消息。记录包含 source generation、sequence、source 时钟时间、topic 和 JSON payload。Worker 验证每个进程或网络帧,独占 source 状态与保留历史,并把已识别 topic 转换成标准 CDP domain。
|
|
38
|
+
|
|
39
|
+
Client source 声明类型化 Runtime、Console 和只读 Sources 能力。`Runtime.enable` 发布真实 Host execution context,并为每个已连接的 Client source 发布一个 synthetic context。选择 Client context 后,求值、属性读取、函数调用、Promise await 和对象释放都会路由到该浏览器 realm。Client Console argument 使用同一份会话本地 object table;`Debugger.enable` 发布构建后的 `lib/client.js` catalog,`Debugger.getScriptSource` 读取有界 content chunk。Client script 断点、step 和 call frame 仍不支持;target-wide pause 与 resume 只控制 Host debugger。
|
|
40
|
+
|
|
41
|
+
两个插件端运行同一份可在浏览器中安全运行的 Cordis collector。它把可达 Context 与 Fiber 对象转换成有版本的 `CordisTreeSnapshot`;Worker 存储这份与 CDP 无关的表示,并把每个 Host 或 Client source 投影到 Elements 面板。
|
|
42
|
+
|
|
43
|
+
<a id="configuration"></a>
|
|
44
|
+
## 配置
|
|
45
|
+
|
|
46
|
+
Host 插件注入 `webServer`,接受以下字段:
|
|
47
|
+
|
|
48
|
+
| 字段 | 默认值 | 含义 |
|
|
49
|
+
|---|---:|---|
|
|
50
|
+
| `host` | `127.0.0.1` | Worker endpoint 监听地址;只接受 loopback |
|
|
51
|
+
| `port` | `9230` | Worker endpoint 起始端口;端口占用时向上递增,`0` 表示由操作系统分配 |
|
|
52
|
+
| `clientOrigins` | `[]` | `/ingest` 额外接受的精确浏览器 origin;loopback origin 始终允许 |
|
|
53
|
+
| `captureFetch` | `true` | 包装 `globalThis.fetch` 并发布之后的每次调用 |
|
|
54
|
+
| `maxRequestBodyBytes` | 8 MiB | 每次请求保留的 request body 前缀 |
|
|
55
|
+
| `maxResponseBodyBytes` | 32 MiB | 每次请求保留的 response body 前缀 |
|
|
56
|
+
| `maxBodyChunkBytes` | 48 KiB | base64 编码前一条 body 记录携带的原始字节数 |
|
|
57
|
+
| `maxJournalBytes` | 256 MiB | Worker 保留的请求与响应 body 总字节数 |
|
|
58
|
+
| `maxRetainedRequests` | `2000` | Worker 保留的进行中与已完成请求总数 |
|
|
59
|
+
| `maxSourceFrameBytes` | 128 KiB | 编码后的 source frame 上限 |
|
|
60
|
+
| `maxSourceRecordsPerFrame` | `128` | 每个 source batch 的记录数 |
|
|
61
|
+
| `maxQueuedRecords` | `2048` | 每个 producer 等待发送的记录数 |
|
|
62
|
+
| `maxQueuedBytes` | 16 MiB | 每个 producer 等待发送的编码字节数 |
|
|
63
|
+
| `startupTimeoutMs` | 10 秒 | Worker ready 截止时间 |
|
|
64
|
+
| `stopTimeoutMs` | 5 秒 | 强制终止前的 Worker 优雅关闭期限 |
|
|
65
|
+
| `clientReconnectBaseMs` | 250 ms | Client 首次重连退避上限 |
|
|
66
|
+
| `clientReconnectMaxMs` | 5 秒 | Client 最大重连退避上限 |
|
|
67
|
+
| `clientRuntimeTimeoutMs` | 30 秒 | 一次 Worker 到 Client Runtime 或 Sources 命令的截止时间 |
|
|
68
|
+
| `queryTimeoutMs` | 10 秒 | 一次非 CDP 语义查询的截止时间 |
|
|
69
|
+
| `maxClientRuntimeObjects` | `10000` | 每条 DevTools 连接保留的 Client 实时对象 handle 数 |
|
|
70
|
+
| `maxClientRuntimeProperties` | `2000` | 单次 Client 对象检查返回的属性描述符数 |
|
|
71
|
+
| `maxClientSourceBytes` | 8 MiB | 单个 Client script 或 source map 允许读取的最大编码字节数 |
|
|
72
|
+
| `maxCordisNodes` | `2048` | 一个 realm 快照截断前允许的 Context 与 Fiber 节点数 |
|
|
73
|
+
| `maxDisconnectedCordisTrees` | `8` | 作为非实时快照保留的最近断联 realm 树数量 |
|
|
74
|
+
|
|
75
|
+
生成的[配置目录](../../../docs/config-catalog.zh.md#deepseek-aidsh-experimental-inspector)是全部已接受字段及其声明的详尽来源。
|
|
76
|
+
|
|
77
|
+
Worker 监听后,Host 会记录一个 `devtools://` URL。同一个 Worker 提供 `/json`、`/json/list`、`/json/version`、`/devtools/page/<id>` target WebSocket 和 `/ingest` Client source。
|
|
78
|
+
|
|
79
|
+
<a id="observation-api"></a>
|
|
80
|
+
## 观测 API
|
|
81
|
+
|
|
82
|
+
两个插件端都提供同一个服务:
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
86
|
+
import type { InspectorJsonValue } from '@deepseek-ai/dsh-experimental-inspector'
|
|
87
|
+
|
|
88
|
+
declare const ctx: Context
|
|
89
|
+
declare const topic: string
|
|
90
|
+
declare const jsonPayload: InspectorJsonValue
|
|
91
|
+
|
|
92
|
+
ctx.inspector.publish(topic, jsonPayload)
|
|
93
|
+
await ctx.inspector.cordis.getTree()
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
发布操作先验证无损 JSON,再调度发送,不等待 Worker。每个 source 的队列都有上限;溢出表现为 sequence gap,绝不延迟被观察的应用操作。`cordis.getTree()` 读取 Worker 最新的 detached semantic 快照,不创建 CDP 会话,也不启用 Runtime、Debugger 或 Sources。
|
|
97
|
+
|
|
98
|
+
<a id="cordis-tree-inspection"></a>
|
|
99
|
+
## Cordis 树检查
|
|
100
|
+
|
|
101
|
+
Elements document 包含固定的 `<host>` 与 `<clients>` 容器。`<host>` 包含 Host root Context;`<clients>` 为每个 Client source 包含一个 `<client>`,每个 `<client>` 再包含该 realm 的根 Context。Cordis root Fiber 不显示。其他 Fiber 都是 `fiber.parent` 的子节点,并包含唯一一个表示 `fiber.ctx` 的 Context 子节点;Fiber 只携带 `uid="<Cordis Fiber.uid>"`,Context element 不携带 attribute。只有 Context 的 `extend()`、`isolate()` 与 `intercept()` 层仍然是直接 Context 后代。
|
|
102
|
+
|
|
103
|
+
Host 与 Client 发布同一种嵌套 `CordisTreeSnapshot` 类型。Context 与 Fiber 节点携带用于 realm-local 对象查询的不透明 object 句柄;Fiber 还携带 Cordis `uid`。Worker 把这些 realm 快照组合成一棵 `{ host, clients }` inspection tree。Worker 按 source generation 分配 `BackendNodeId`;每条 DevTools 连接分配自己的 `NodeId`;`DOM.resolveNode` 请求所属 Host 或 Client Runtime 生成连接本地 `RemoteObjectId`。`DOM.requestNode` 把该 object id 映射回同一个 Elements 节点。`ctx.inspector.cordis.getTree()` 与 `DSHInspector.getCordisTree` 读取不含 routing 句柄或 CDP id 的 detached 消费方无关 tree。
|
|
104
|
+
|
|
105
|
+
节点按 DevTools 连接做深度受限下发:调用方省略 `depth` 时 `DOM.getDocument` 提供三层 document,被扣留的层级通过 `childNodeCount` 声明数量,展开时经 `DOM.requestChildNodes` 获取(`depth: -1` 取整棵子树)。经 `DOM.performSearch`、`DOM.requestNode` 或 `DOM.pushNodesByBackendIdsToFrontend` 流出的 NodeId 会先把尚未下发的祖先层级以 `DOM.setChildNodes` 事件推送出去。
|
|
106
|
+
|
|
107
|
+
source 仍发布完整 snapshot,Worker 在通知 DevTools 前按稳定的 backend node identity 比较差异。无变化的 snapshot 不发送 DOM 事件;新增、移除和 attribute 变化使用节点级 CDP 事件,插入节点的载荷扣留其子树,兄弟节点重排只替换对应 parent 的 children。现有 `NodeId` 与未受影响的 Elements 展开状态保持稳定。
|
|
108
|
+
|
|
109
|
+
Client 断联时,其 Console execution context 与 live object id 会立即销毁。启用断联树保留后,Elements 会原样保留最后一棵树;连接状态留在 inspection model 中,不会未经审查就成为 DOM attribute。重连会沿用逻辑 source id,为新的 transport generation 创建新的 synthetic CDP context id,并在完整 snapshot 到达后替换旧树。Client 把逻辑 id 保存在 `sessionStorage` 中,并通过 Web Locks 在页面存活期间独占该 id,因此刷新会复用 id,而复制出的另一个 live tab 会取得新 id。Worker 最多保留 `maxDisconnectedCordisTrees` 棵此类 snapshot;设为零会立即移除。
|
|
110
|
+
|
|
111
|
+
<a id="host-fetch-capture"></a>
|
|
112
|
+
## Host fetch 采集
|
|
113
|
+
|
|
114
|
+
fetch 采集默认开启,记录完整 URL、全部请求与响应 headers、请求体、响应体、状态、时间、错误和取消。它不脱敏 credential、Cookie、query value 或 payload。body 采集读取 clone;原始 fetch resolve 后,调用方立即拿到原始 Response。
|
|
115
|
+
|
|
116
|
+
配置的 body 上限限制保留量,而不选择字段:采集保留前缀并标记 truncated。`Network.getRequestPostData` 与 `Network.getResponseBody` 读取 Worker 保留的字节。`Network.streamResourceContent` 返回已缓冲的前缀,并仅为发起调用的 DevTools 连接把后续 response 字节附加到 `Network.dataReceived`,以驱动实时 Response 与 EventStream 视图。直接调用 Undici Client/Dispatcher,以及插件激活前保存的 fetch 引用,不在观察范围内。
|
|
117
|
+
|
|
118
|
+
response headers 到达后,调用方 abort 可能会终止 observer clone;已采集的字节仍可通过 `Network.getResponseBody` 读取,采集 metadata 记录错误与截断,并且 CDP 因 fetch 已返回 Response 而发送 `Network.loadingFinished`。response headers 到达前发生的 fetch rejection 会发送 `Network.loadingFailed`,其中 abort 对应 `canceled: true`。
|
|
119
|
+
|
|
120
|
+
<a id="security"></a>
|
|
121
|
+
## 安全
|
|
122
|
+
|
|
123
|
+
CDP target 通过 `Runtime.evaluate` 提供 Host 和已连接 Client realm 中的任意代码执行能力,Host Debugger 操作还会提供额外控制,完整 fetch 采集也包含敏感信息。因此 Worker 只接受 `127.0.0.1` 监听地址。Client ingest 还要求 Host 注入的随机 WebSocket subprotocol token;除非配置明确允许,否则拒绝非 loopback origin。CDP socket 本身不携带 token,loopback 监听是它唯一的访问控制。
|
|
124
|
+
|
|
125
|
+
<a id="model-experience"></a>
|
|
126
|
+
## 模型体验
|
|
127
|
+
|
|
128
|
+
无:这个仅供开发者使用的 Inspector 只观察运行时活动,不改变模型请求。
|
|
129
|
+
|
|
130
|
+
#### KV Cache 影响
|
|
131
|
+
|
|
132
|
+
无:本包既不组装也不发送提供方请求。
|
|
133
|
+
|
|
134
|
+
## 已知限制与延期工作
|
|
135
|
+
|
|
136
|
+
<a id="known-limitations-and-deferred-work"></a>
|
|
137
|
+
|
|
138
|
+
- **Client active debugging 不受支持**——Console event、Runtime 求值、RemoteObject 访问和只读 `lib/client.js` Sources 可用。Client script debugger request 返回明确的 unsupported error;target-wide pause 与 resume 只控制 Host。
|
|
139
|
+
- **Client Sources 只暴露 Inspector bundle**——本包不收录页面中的其他 script。
|
|
140
|
+
- **Client 求值使用页面 JavaScript**——页面 Content Security Policy 可能阻止动态求值;synthetic context 不提供 DevTools command-line helper 或原生 REPL 声明语义。
|
|
141
|
+
- **Client 身份仲裁依赖 Web Locks**——缺少该 API 的浏览器仍会通过 `sessionStorage` 保持重连与刷新身份,但无法区分从同一存储状态复制出的两个同时存活 tab。
|
|
142
|
+
- **fetch 拦截范围是 `globalThis.fetch`**——直接调用 Undici API,以及激活前保存的 fetch 引用不会被观察。
|
|
143
|
+
- **body clone 有运行成本**——完整采集会 tee 请求与响应流,直至达到配置上限,可能增加内存与 I/O 压力。保留 body 的上限不包含流 tee 内部的缓冲,包括来源提供的超大 chunk,或为读取较慢的应用分支排队的数据。
|
|
144
|
+
- **不自动重启 Worker**——Worker 意外退出会使当前 Inspector 实例失败;生命周期恢复留待后续改动。
|
|
145
|
+
|
|
146
|
+
<a id="dev-note"></a>
|
|
147
|
+
### 开发备注
|
|
148
|
+
|
|
149
|
+
<details>
|
|
150
|
+
<summary>维护者的工作上下文——点击展开</summary>
|
|
151
|
+
|
|
152
|
+
无。
|
|
153
|
+
|
|
154
|
+
</details>
|
|
155
|
+
|
|
156
|
+
**运行时不变式:** 不发布伴生入口。wire 解析、generation、Worker 生命周期与 CDP 会话会在所属操作中拒绝无效关系。
|