@deepseek-ai/dsh-experimental-inspector 0.2.1-alpha.2 → 0.2.1-alpha.4

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.i18n.yaml CHANGED
@@ -18,8 +18,8 @@
18
18
  en: 6d290aabc543f878
19
19
  zh: 7ad283b159ae2c29
20
20
  /deepseek-ai-dsh-experimental-inspector/runtime-layout:
21
- en: 30dad7b7fe3b3465
22
- zh: 2bda395981802f59
21
+ en: 13f495af2fec307d
22
+ zh: ec4bebf24a87ec54
23
23
  /deepseek-ai-dsh-experimental-inspector/configuration:
24
24
  en: d094842893700446
25
25
  zh: 7a7f880ba795948f
package/README.md CHANGED
@@ -48,7 +48,7 @@ The frontend uses browser runtime adapters and excludes Node-only transports at
48
48
  <a id="runtime-layout"></a>
49
49
  ## Runtime layout
50
50
 
51
- The Worker never accesses live Cordis objects: the shared Host/Client collector projects them into validated snapshots before transport. Cordis owns plugin composition, `ctx.inspector` registration, bootstrap injection, and disposal. A late-loading Client fetches its bootstrap through an authenticated Host route. Bootstrap transport and source-setup failures warn and retain connection-reset recovery for both injected and fetched startup; invalid bootstrap data or service-registration failures reject startup. Source replacement joins old service-consumer cleanup before claiming another source, and unloading an active plugin cancels its pending bootstrap refresh.
51
+ The Worker never accesses live Cordis objects: the shared Host/Client collector projects them into validated snapshots before transport. Cordis owns plugin composition, `ctx.inspector` registration, bootstrap injection, and disposal. A late-loading Client fetches its bootstrap through an authenticated Host route, which the Host registers before it starts the Worker: a request waits for Worker readiness and then receives the bootstrap, or `503` when startup fails; an aborted request stops waiting. When the platform cannot run the Worker and reports Node's `ERR_FEATURE_UNAVAILABLE_ON_PLATFORM`, such as the browser preview's Worker host, the Host logs one warning and the plugin still starts with only that route, which answers `503`; it provides no `ctx.inspector`, DevTools routes, bootstrap injection, or `devtools://` URL. Any other startup error still rejects the plugin. Bootstrap transport and source-setup failures warn and retain connection-reset recovery for both injected and fetched startup; invalid bootstrap data or service-registration failures reject startup. Source replacement joins old service-consumer cleanup before claiming another source, and unloading an active plugin cancels its pending bootstrap refresh.
52
52
 
53
53
  The Host plugin starts the Worker and connects a dedicated `MessagePort`. The Client uses injected or fetched browser-source parameters to open an authenticated WebSocket directly to the Worker; it receives no DevTools URL. 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 debugging remains available while Host JavaScript is paused.
54
54
 
package/README.zh.md CHANGED
@@ -48,7 +48,7 @@ Host 在相对于应用根目录的 `inspector/devtools/devtools_app.html` 路
48
48
  <a id="runtime-layout"></a>
49
49
  ## 运行时布局
50
50
 
51
- Worker 不访问实时 Cordis 对象;共享 Host/Client collector 会在传输前把它们投影成已验证快照。Cordis 负责插件组合、注册 `ctx.inspector`、注入 bootstrap 和 dispose(资源释放)。后加载的 Client 通过已鉴权的 Host 路由获取 bootstrap。初始注入与主动获取两条路径中,bootstrap 传输或 source 建立失败均记录警告并保留连接重置后的重试;bootstrap 数据非法或服务注册失败则使启动失败。替换 source 会等待旧服务消费者清理完成,再申请新 source;卸载已激活插件会取消其未完成的 bootstrap 刷新。
51
+ Worker 不访问实时 Cordis 对象;共享 Host/Client collector 会在传输前把它们投影成已验证快照。Cordis 负责插件组合、注册 `ctx.inspector`、注入 bootstrap 和 dispose(资源释放)。后加载的 Client 通过已鉴权的 Host 路由获取 bootstrap。Host 在启动 Worker 之前注册该路由,请求会等到 Worker 就绪后返回 bootstrap,启动失败时返回 `503`;请求中止时立即停止等待。当前平台无法运行 Worker 并报告 Node 的 `ERR_FEATURE_UNAVAILABLE_ON_PLATFORM` 时(例如浏览器预览的 Worker host),Host 记录一条警告,插件仍照常启动,只保留该路由并返回 `503`,不提供 `ctx.inspector`、DevTools 路由、bootstrap 注入或 `devtools://` URL;其他任何启动错误仍使插件启动失败。初始注入与主动获取两条路径中,bootstrap 传输或 source 建立失败均记录警告并保留连接重置后的重试;bootstrap 数据非法或服务注册失败则使启动失败。替换 source 会等待旧服务消费者清理完成,再申请新 source;卸载已激活插件会取消其未完成的 bootstrap 刷新。
52
52
 
53
53
  Host 插件启动 Worker 并连接专用 `MessagePort`。Client 使用注入或主动获取的浏览器 source 参数,直接向 Worker 打开带鉴权的 WebSocket,不接收 DevTools URL。Chrome DevTools 连接 Worker 的 CDP WebSocket。每条 DevTools 连接在 Worker 中独占一个连接 Host 主线程的 `node:inspector.Session`,因此 Host JavaScript 暂停时仍可调试 Host。
54
54
 
package/icon.svg CHANGED
@@ -1,12 +1,23 @@
1
1
  <svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
2
- <circle cx="15.5" cy="15.5" r="8.5" fill="url(#a)" />
3
- <circle cx="15.5" cy="15.5" r="5" fill="#FFFFFF" />
4
- <path d="M13.2 15.5L14.9 17.2L18.2 13.9" stroke="#145AF3" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" />
5
- <path d="M22 22L29 29" stroke="#145AF3" stroke-width="3.2" stroke-linecap="round" />
2
+ <g mask="url(#data-lens-cutout)">
3
+ <rect x="11" y="7" width="16" height="16" rx="2" fill="#7FB7FC" fill-opacity="0.55" />
4
+ <rect x="7" y="11" width="17" height="15" rx="2" fill="url(#data-panel)" />
5
+ <path d="M10 15H18M10 18H15" stroke="#FFFFFF" stroke-width="1.5" />
6
+ </g>
7
+ <path d="M26 26L30 30" stroke="#658EFF" stroke-width="3" />
8
+ <circle cx="23" cy="23" r="4.5" stroke="url(#data-lens)" stroke-width="2.5" />
6
9
  <defs>
7
- <linearGradient id="a" x1="7" y1="7" x2="24" y2="24" gradientUnits="userSpaceOnUse">
8
- <stop stop-color="#7CB7FF" />
9
- <stop offset="1" stop-color="#45D9E7" />
10
+ <mask id="data-lens-cutout" maskUnits="userSpaceOnUse" x="0" y="0" width="36" height="36">
11
+ <rect width="36" height="36" fill="#FFFFFF" />
12
+ <circle cx="23" cy="23" r="3.25" fill="#000000" />
13
+ </mask>
14
+ <linearGradient id="data-panel" x1="9" y1="11" x2="23" y2="26" gradientUnits="userSpaceOnUse">
15
+ <stop stop-color="#6DB9FB" />
16
+ <stop offset="1" stop-color="#3650DE" />
17
+ </linearGradient>
18
+ <linearGradient id="data-lens" x1="19" y1="19" x2="27" y2="27" gradientUnits="userSpaceOnUse">
19
+ <stop stop-color="#45D9E7" />
20
+ <stop offset="1" stop-color="#67C7FE" />
10
21
  </linearGradient>
11
22
  </defs>
12
23
  </svg>
package/lib/index.js CHANGED
@@ -1,8 +1,6 @@
1
1
  import z from "@deepseek-ai/schemastery";
2
2
  import { fileURLToPath } from "node:url";
3
3
  import { connect } from "node:net";
4
- import serveStatic from "serve-static";
5
- import open, { apps } from "open";
6
4
  import { randomBytes, randomUUID } from "node:crypto";
7
5
  import { tmpdir } from "node:os";
8
6
  import { MessageChannel, Worker } from "node:worker_threads";
@@ -2369,14 +2367,38 @@ async function disposeInspectorResources(disposers, close, message) {
2369
2367
  //#region lib/types/host/plugin.js
2370
2368
  /** Host Cordis plugin for the cross-realm Inspector Worker and full fetch capture. */
2371
2369
  const DEVTOOLS_PATH = "/inspector/devtools";
2372
- /** Start the Worker, expose `ctx.inspector`, and inject the matching Client bootstrap. */
2370
+ /** Node's standard code for a feature the running platform cannot provide, such as `worker_threads` in a browser Worker host. */
2371
+ const FEATURE_UNAVAILABLE_ON_PLATFORM = "ERR_FEATURE_UNAVAILABLE_ON_PLATFORM";
2372
+ /**
2373
+ * Start the Worker, expose `ctx.inspector`, and inject the matching Client bootstrap.
2374
+ * The bootstrap route exists before the Worker is ready, so a Client published during startup waits instead of failing.
2375
+ * When the platform cannot run the Worker (`ERR_FEATURE_UNAVAILABLE_ON_PLATFORM`), the plugin warns once and stays active
2376
+ * with only that route, which answers 503; every other startup failure rolls back and rejects the fiber.
2377
+ */
2373
2378
  async function apply$1(ctx, config) {
2374
2379
  await ctx.effect(async () => {
2375
2380
  const spec = resolveInspectorOptions(config);
2376
- const handle = await startInspector(spec);
2381
+ const ready = Promise.withResolvers();
2377
2382
  const disposers = [];
2378
- const dispose = () => disposeInspectorResources(disposers, () => handle.close(), "experimental-inspector: disposal failed");
2383
+ let worker;
2384
+ const dispose = () => disposeInspectorResources(disposers, () => worker?.close(), "experimental-inspector: disposal failed");
2379
2385
  try {
2386
+ disposers.push(ctx.connection.fetch.register({
2387
+ path: INSPECTOR_BOOTSTRAP_PATH,
2388
+ methods: ["GET"],
2389
+ requestBody: "buffered",
2390
+ fetch: (request) => bootstrapResponse(ready.promise, request.signal)
2391
+ }));
2392
+ const handle = await startInspector(spec).catch((error) => {
2393
+ if (!isUnavailableOnPlatform(error)) throw error;
2394
+ ctx.logger.warn("experimental-inspector: NodeJS Inspector is unavailable on this platform; Host inspection stays disabled", error);
2395
+ });
2396
+ if (handle === void 0) {
2397
+ ready.resolve(void 0);
2398
+ return dispose;
2399
+ }
2400
+ worker = handle;
2401
+ const { default: serveStatic } = await import("serve-static");
2380
2402
  disposers.push(publishCordisTree(ctx, handle.source, {
2381
2403
  maxNodes: spec.maxCordisNodes,
2382
2404
  maxBytes: spec.maxSourceFrameBytes - 4096
@@ -2389,12 +2411,6 @@ async function apply$1(ctx, config) {
2389
2411
  value: handle.endpoint.client
2390
2412
  });
2391
2413
  }));
2392
- disposers.push(ctx.connection.fetch.register({
2393
- path: INSPECTOR_BOOTSTRAP_PATH,
2394
- methods: ["GET"],
2395
- requestBody: "buffered",
2396
- fetch: () => Promise.resolve(Response.json(handle.endpoint.client, { headers: { "cache-control": "no-store" } }))
2397
- }));
2398
2414
  const assets = serveStatic(fileURLToPath(new URL("./lib/devtools/", import.meta.resolve("@deepseek-ai/dsh-experimental-inspector/package.json"))), {
2399
2415
  index: false,
2400
2416
  redirect: false,
@@ -2484,13 +2500,18 @@ async function apply$1(ctx, config) {
2484
2500
  }
2485
2501
  }));
2486
2502
  console.log(`dsh inspector: ${handle.endpoint.devtoolsFrontendUrl}`);
2487
- if (ctx.get("cmdlineArgs")?.get().includes("--inspect")) await open(handle.endpoint.devtoolsFrontendUrl, {
2488
- app: { name: apps.chrome },
2489
- wait: false
2490
- }).catch((error) => {
2491
- ctx.logger.error("experimental-inspector: Chrome could not open DevTools", error);
2492
- });
2503
+ ready.resolve(handle.endpoint.client);
2504
+ if (ctx.get("cmdlineArgs")?.get().includes("--inspect")) {
2505
+ const { default: open, apps } = await import("open");
2506
+ await open(handle.endpoint.devtoolsFrontendUrl, {
2507
+ app: { name: apps.chrome },
2508
+ wait: false
2509
+ }).catch((error) => {
2510
+ ctx.logger.error("experimental-inspector: Chrome could not open DevTools", error);
2511
+ });
2512
+ }
2493
2513
  } catch (error) {
2514
+ ready.resolve(void 0);
2494
2515
  await dispose().catch((cleanupError) => {
2495
2516
  ctx.logger.error("experimental-inspector: initialization rollback failed", cleanupError);
2496
2517
  });
@@ -2499,6 +2520,38 @@ async function apply$1(ctx, config) {
2499
2520
  return dispose;
2500
2521
  }, "experimental-inspector: Host Worker");
2501
2522
  }
2523
+ /**
2524
+ * Report whether a Worker startup failure means this platform cannot run the Inspector at all.
2525
+ * @param error - Rejection from {@link startInspector}.
2526
+ * @returns True only for Node's `ERR_FEATURE_UNAVAILABLE_ON_PLATFORM` code; messages are never inspected.
2527
+ */
2528
+ function isUnavailableOnPlatform(error) {
2529
+ return error instanceof Error && "code" in error && error.code === FEATURE_UNAVAILABLE_ON_PLATFORM;
2530
+ }
2531
+ /**
2532
+ * Answer one bootstrap request once Host initialization settles or the browser abandons the request.
2533
+ * @param ready - Resolves with the Client bootstrap, or with undefined after initialization failed or found the platform unavailable.
2534
+ * @param signal - Request signal; an aborted request stops waiting and receives no endpoint.
2535
+ * @returns The bootstrap JSON, or 503 when the Inspector is unavailable or the request was aborted.
2536
+ */
2537
+ async function bootstrapResponse(ready, signal) {
2538
+ const headers = { "cache-control": "no-store" };
2539
+ const abandoned = Promise.withResolvers();
2540
+ const abandon = () => {
2541
+ abandoned.resolve(void 0);
2542
+ };
2543
+ if (signal.aborted) abandon();
2544
+ else signal.addEventListener("abort", abandon, { once: true });
2545
+ try {
2546
+ const client = await Promise.race([ready, abandoned.promise]);
2547
+ return client === void 0 ? new Response(null, {
2548
+ status: 503,
2549
+ headers
2550
+ }) : Response.json(client, { headers });
2551
+ } finally {
2552
+ signal.removeEventListener("abort", abandon);
2553
+ }
2554
+ }
2502
2555
  //#endregion
2503
2556
  //#region lib/types/index.js
2504
2557
  /** Repository-facing Host package entry over the mirrored implementation tree. */
@@ -14,6 +14,11 @@ export interface HostPluginConfig extends Omit<InspectorOptions, 'clientOrigins'
14
14
  /** Browser origins allowed to open the Client ingest WebSocket. */
15
15
  clientOrigins?: string[];
16
16
  }
17
- /** Start the Worker, expose `ctx.inspector`, and inject the matching Client bootstrap. */
17
+ /**
18
+ * Start the Worker, expose `ctx.inspector`, and inject the matching Client bootstrap.
19
+ * The bootstrap route exists before the Worker is ready, so a Client published during startup waits instead of failing.
20
+ * When the platform cannot run the Worker (`ERR_FEATURE_UNAVAILABLE_ON_PLATFORM`), the plugin warns once and stays active
21
+ * with only that route, which answers 503; every other startup failure rolls back and rejects the fiber.
22
+ */
18
23
  export declare function apply(ctx: Context, config: HostPluginConfig): Promise<void>;
19
24
  //# sourceMappingURL=plugin.d.ts.map
package/lib/worker.js CHANGED
@@ -7272,18 +7272,22 @@ controlPort.on("message", (message) => {
7272
7272
  });
7273
7273
  }
7274
7274
  });
7275
- try {
7276
- runtime = await startInspectorWorker(boot);
7277
- controlPort.postMessage({
7278
- type: "ready",
7279
- ...runtime.endpoint
7280
- });
7281
- } catch (error) {
7282
- controlPort.postMessage({
7283
- type: "failure",
7284
- message: error instanceof Error ? error.message : String(error)
7285
- });
7286
- await stop();
7275
+ /** Start the Worker server and report readiness, or report the failure and stop. */
7276
+ async function main() {
7277
+ try {
7278
+ runtime = await startInspectorWorker(boot);
7279
+ controlPort.postMessage({
7280
+ type: "ready",
7281
+ ...runtime.endpoint
7282
+ });
7283
+ } catch (error) {
7284
+ controlPort.postMessage({
7285
+ type: "failure",
7286
+ message: error instanceof Error ? error.message : String(error)
7287
+ });
7288
+ await stop();
7289
+ }
7287
7290
  }
7291
+ main();
7288
7292
  //#endregion
7289
7293
  export {};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-experimental-inspector",
3
3
  "description": "Experimental cross-realm CDP hub for Host debugging and Client Runtime inspection",
4
- "version": "0.2.1-alpha.2",
4
+ "version": "0.2.1-alpha.4",
5
5
  "icon": "./icon.svg",
6
6
  "publishConfig": {
7
7
  "access": "public"
@@ -46,43 +46,39 @@
46
46
  ],
47
47
  "license": "MIT",
48
48
  "dependencies": {
49
- "@deepseek-ai/dsh-app-boot": "0.2.1-alpha.2",
50
- "@deepseek-ai/dsh-brand": "0.2.1-alpha.2",
51
- "@deepseek-ai/dsh-util-crypto": "0.2.1-alpha.2",
52
- "@deepseek-ai/schemastery": "~3.18.5-alpha.1",
49
+ "@deepseek-ai/dsh-app-boot": "0.2.1-alpha.4",
50
+ "@deepseek-ai/dsh-util-crypto": "0.2.1-alpha.4",
51
+ "@deepseek-ai/schemastery": "~3.18.5-alpha.2",
53
52
  "open": "^11.0.2",
54
53
  "serve-static": "^2.2.1",
55
54
  "ws": "^8.21.3"
56
55
  },
57
56
  "peerDependencies": {
58
- "@deepseek-ai/cordis": "~4.0.5-alpha.1",
59
- "@deepseek-ai/cordis-plugin-loader": "~1.0.6-alpha.1",
60
- "@deepseek-ai/dsh-client-modules": "0.2.1-alpha.2",
61
- "@deepseek-ai/dsh-client-connection": "0.2.1-alpha.2",
62
- "@deepseek-ai/dsh-host-webserver": "0.2.1-alpha.2"
57
+ "@deepseek-ai/cordis": "~4.0.5-alpha.2"
63
58
  },
64
59
  "devDependencies": {
65
60
  "chrome-devtools-frontend": "1.0.1638082",
66
61
  "@types/serve-static": "^2.2.0",
67
- "@deepseek-ai/dsh-client-test-runtime": "0.2.1-alpha.2",
62
+ "@deepseek-ai/dsh-client-test-runtime": "0.2.1-alpha.4",
68
63
  "@testing-library/react": "^16.3.3",
69
- "@deepseek-ai/dsh-client-ui-renderer": "0.2.1-alpha.2",
70
- "@types/react": "~18.3.1",
71
- "@deepseek-ai/dsh-client-ui-layout": "0.2.1-alpha.2",
72
- "@deepseek-ai/dsh-client-shortcuts": "0.2.1-alpha.2",
73
- "@deepseek-ai/dsh-client-store": "0.2.1-alpha.2",
74
- "@deepseek-ai/dsh-client-ui-slots": "0.2.1-alpha.2",
75
- "@deepseek-ai/dsh-client-ui-primitives": "0.2.1-alpha.2",
76
- "@deepseek-ai/dsh-client-locale": "0.2.1-alpha.2",
64
+ "@deepseek-ai/dsh-client-ui-renderer": "0.2.1-alpha.4",
65
+ "@deepseek-ai/dsh-client-ui-layout": "0.2.1-alpha.4",
66
+ "@deepseek-ai/dsh-client-shortcuts": "0.2.1-alpha.4",
67
+ "@deepseek-ai/dsh-client-store": "0.2.1-alpha.4",
68
+ "@deepseek-ai/dsh-client-ui-slots": "0.2.1-alpha.4",
69
+ "@deepseek-ai/dsh-client-ui-primitives": "0.2.1-alpha.4",
70
+ "@deepseek-ai/dsh-client-locale": "0.2.1-alpha.4",
77
71
  "react": "^18.2.0",
78
- "@deepseek-ai/cordis": "~4.0.5-alpha.1",
79
- "@deepseek-ai/cordis-plugin-include": "~1.0.10-alpha.1",
80
- "@deepseek-ai/cordis-plugin-loader": "~1.0.6-alpha.1",
81
- "@deepseek-ai/dsh-host-webserver": "0.2.1-alpha.2",
82
- "@deepseek-ai/dsh-cmdline": "0.2.1-alpha.2",
83
- "@deepseek-ai/dsh-client-connection": "0.2.1-alpha.2",
72
+ "@deepseek-ai/cordis": "~4.0.5-alpha.2",
73
+ "@deepseek-ai/cordis-plugin-include": "~1.0.10-alpha.2",
74
+ "@deepseek-ai/cordis-plugin-loader": "~1.0.6-alpha.2",
75
+ "@deepseek-ai/dsh-host-webserver": "0.2.1-alpha.4",
76
+ "@deepseek-ai/dsh-cmdline": "0.2.1-alpha.4",
77
+ "@deepseek-ai/dsh-client-connection": "0.2.1-alpha.4",
84
78
  "@types/ws": "^8.18.1",
85
79
  "playwright": "^1.49.0",
86
- "tsx": "^4.23.13"
80
+ "tsx": "^4.23.13",
81
+ "@deepseek-ai/dsh-brand": "0.2.1-alpha.4",
82
+ "@deepseek-ai/dsh-client-modules": "0.2.1-alpha.4"
87
83
  }
88
84
  }