dsh-context 0.49.3 → 0.49.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/lib/client.js CHANGED
@@ -6680,7 +6680,7 @@ window.__ModuleLoader__.load({
6680
6680
  return function PluginInfo() {
6681
6681
  const [latest, setLatest] = (0, react.useState)(null);
6682
6682
  (0, react.useEffect)(() => {
6683
- if ("0.49.3".includes("-dev")) return;
6683
+ if ("0.49.4".includes("-dev")) return;
6684
6684
  let on = true;
6685
6685
  fetchLatestVersion().then((v) => {
6686
6686
  if (on && v) setLatest(v);
@@ -6689,8 +6689,8 @@ window.__ModuleLoader__.load({
6689
6689
  on = false;
6690
6690
  };
6691
6691
  }, []);
6692
- const update = latest !== null && isNewerVersion(latest, "0.49.3") ? latest : null;
6693
- const nameText = "dsh-context (v0.49.3)";
6692
+ const update = latest !== null && isNewerVersion(latest, "0.49.4") ? latest : null;
6693
+ const nameText = "dsh-context (v0.49.4)";
6694
6694
  const nameValue = [nameText];
6695
6695
  if (update) nameValue.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
6696
6696
  className: "lc-pi-update",
package/lib/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { createRequire } from "node:module";
2
2
  import { existsSync, readFileSync } from "node:fs";
3
- import { dirname, join, normalize } from "node:path";
3
+ import { dirname, join, normalize, relative } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import { z } from "zod";
6
6
  import { deriveEventMessage } from "@deepseek-ai/dsh-session";
@@ -2009,7 +2009,7 @@ function watchDetailChannel(ctx, bounds) {
2009
2009
  * host probes and gates; the client displays what the wire record carries),
2010
2010
  * so this module must stay dependency-free.
2011
2011
  *
2012
- * The baseline mirrors the support matrix (AGENTS.md "Compatibility" and the
2012
+ * The baseline mirrors the support matrix (docs/compatibility.md and the
2013
2013
  * package's `dsh.compatibility.dshReleases` declaration): the oldest dsh
2014
2014
  * release this plugin works on. A harness BELOW it gets the fallback units
2015
2015
  * (host/fallback.ts) instead of the real folds.
@@ -2712,35 +2712,72 @@ function watchStepIdentity(ctx) {
2712
2712
  * The probe never imports a harness package for its version; it reads
2713
2713
  * manifests through Node resolution from two anchors, in order:
2714
2714
  *
2715
- * 1. The harness home's healed `profiles/node_modules` mirror (located via
2716
- * the app-boot `dshHomePath` service) it symlinks/proxies the running
2717
- * installation's dependency closure, so it names the true release even
2718
- * when this plugin is a `link:`-installed dev checkout.
2719
- * 2. This module itself in a real profile install the plugin sits inside
2720
- * the profile's node_modules and walk-up resolution reaches the same
2721
- * mirror; this anchor also covers harnesses too old to provide the home
2722
- * service.
2715
+ * 1. This module's own ESM resolution of the library packages the Host half
2716
+ * imports at runtime. That is the very pipeline the process resolves those
2717
+ * imports through, so an embedding shell that redirects plugin imports —
2718
+ * the packaged Desktop's ASAR resolver bridge does exactly this — redirects
2719
+ * the probe identically, and the answer names the module instances the
2720
+ * harness is actually running. A witness that lands inside this package's
2721
+ * own tree is the plugin's dependency closure (a `link:`-installed dev
2722
+ * checkout's pinned devDependencies), never the harness, so it is discarded
2723
+ * for the home anchor.
2724
+ * 2. The harness home's healed `profiles/node_modules` mirror (located via
2725
+ * the app-boot `dshHomePath` service). It names the installation that last
2726
+ * healed it: authoritative for a dev checkout, whose own tree holds pinned
2727
+ * devDependencies, but only as fresh as the last CLI profile boot. A
2728
+ * packaged Desktop never heals it, so a stale global-CLI mirror can outlive
2729
+ * the CLI and misname the running harness — that is why it answers only
2730
+ * when the running anchor has nothing it can trust.
2723
2731
  *
2724
2732
  * The `@deepseek-ai/dsh` CLI package is probed ONLY through the home anchor:
2725
- * the plugin never depends on it, so a hit from the module anchor can only
2726
- * be an ambient install above the plugin's tree (e.g. a global copy under
2733
+ * the plugin never imports it, so a hit from the running anchor can only be an
2734
+ * ambient install above the plugin's tree (e.g. a global copy under
2727
2735
  * ~/node_modules) — not necessarily the RUNNING harness.
2728
2736
  *
2729
2737
  * Every step is guarded: any failure (absent service, unresolvable package,
2730
- * unreadable/invalid manifest, non-string version) degrades to `undefined`,
2731
- * and the gate treats an unknown version as SATISFIED — a probe misfire must
2732
- * never blank a working deployment.
2738
+ * non-file URL, unreadable/invalid manifest, non-string version) degrades to
2739
+ * `undefined`, and the gate treats an unknown version as SATISFIED — a probe
2740
+ * misfire must never blank a working deployment.
2733
2741
  */
2734
2742
  /**
2735
- * Library packages whose manifest version IS the harness release version
2736
- * (the dsh monorepo versions every package in lockstep). From the plugin's
2737
- * own tree they resolve to its pinned devDependencies in dev and to the
2738
- * healed profiles mirror in real installs — both correct — so they are safe
2739
- * to probe from either anchor.
2743
+ * Library packages whose manifest version IS the harness release version (the
2744
+ * dsh monorepo versions every package in lockstep). The home anchor probes
2745
+ * them after the CLI package; the running anchor probes the two first- and
2746
+ * second-ordered.
2740
2747
  */
2741
2748
  const LIBRARY_PROBE_PACKAGES = ["@deepseek-ai/dsh-session-projection", "@deepseek-ai/dsh-session"];
2749
+ /**
2750
+ * Running-anchor probe order: the package the Host half genuinely imports at
2751
+ * runtime first (host/fold.ts imports it, so it MUST resolve whenever this
2752
+ * plugin runs), then its co-versioned sibling.
2753
+ */
2754
+ const RUNNING_PROBE_PACKAGES = ["@deepseek-ai/dsh-session", "@deepseek-ai/dsh-session-projection"];
2742
2755
  /** Home-anchor probe order: the user-facing CLI version first, then the libraries. */
2743
2756
  const HOME_PROBE_PACKAGES = ["@deepseek-ai/dsh", ...LIBRARY_PROBE_PACKAGES];
2757
+ /**
2758
+ * This package's root. A running-anchor witness under it belongs to the
2759
+ * plugin's own dependency closure, not to the harness.
2760
+ *
2761
+ * Located through the package's own `./package.json` self-reference: Node
2762
+ * resolves that against the nearest package.json, so the answer is the package
2763
+ * root in the source tree and in the bundled profile install alike — a fixed
2764
+ * number of `..` steps cannot be, since `src/host/` and `lib/` differ by a
2765
+ * level. A loader that cannot self-resolve (an exotic loader, or a fork renamed
2766
+ * without a matching `exports`) falls back to this module's own directory: the
2767
+ * guard then covers less of the package, but it still can never mistake the
2768
+ * plugin's own `node_modules` for the harness.
2769
+ */
2770
+ function ownPackageRoot() {
2771
+ try {
2772
+ return dirname(fileURLToPath(import.meta.resolve("dsh-context/package.json")));
2773
+ } catch {
2774
+ /* v8 ignore next -- a loader that cannot resolve one of its own package's
2775
+ published subpaths is out of the suite's reach; the fallback keeps one
2776
+ probe path (an unanswered probe fails open either way). */
2777
+ return dirname(fileURLToPath(import.meta.url));
2778
+ }
2779
+ }
2780
+ const PLUGIN_ROOT = ownPackageRoot();
2744
2781
  /** One manifest's `version`, or undefined on any read/shape failure. */
2745
2782
  function versionOfManifest(manifestPath, expectedName) {
2746
2783
  try {
@@ -2790,11 +2827,51 @@ function probeAnchor(resolve, packageNames) {
2790
2827
  }
2791
2828
  }
2792
2829
  /**
2830
+ * Whether `candidate` lies inside `root`'s tree. A `..`-prefixed relative path
2831
+ * escapes it; a sibling such as `dsh-context-extra` is reached through `..` too,
2832
+ * so it never counts as a child. A pathological child literally named `..foo`
2833
+ * would degrade to the home anchor, which is the safe direction.
2834
+ */
2835
+ function isInside(root, candidate) {
2836
+ return !relative(root, candidate).startsWith("..");
2837
+ }
2838
+ /**
2839
+ * The running module tree's answer, or undefined when it cannot be trusted.
2840
+ * Each probe package is checked on its own: a witness inside the plugin's own
2841
+ * closure is the plugin's dependency, not the harness, and a trusted witness
2842
+ * whose manifest cannot be read is no answer either — the next package may
2843
+ * still resolve to one.
2844
+ */
2845
+ function probeRunningTree(resolve, pluginRoot) {
2846
+ for (const packageName of RUNNING_PROBE_PACKAGES) {
2847
+ let witness;
2848
+ try {
2849
+ witness = resolve(packageName);
2850
+ } catch {
2851
+ continue;
2852
+ }
2853
+ if (isInside(pluginRoot, witness)) continue;
2854
+ const version = versionViaManifest(resolve, packageName) ?? versionViaEntry(resolve, packageName);
2855
+ if (version !== void 0) return version;
2856
+ }
2857
+ }
2858
+ /** The default running anchor: this module's own ESM resolution. */
2859
+ function resolveRunningModule(specifier) {
2860
+ return import.meta.resolve(specifier);
2861
+ }
2862
+ /**
2793
2863
  * The running harness's version string, or undefined when nothing answers
2794
2864
  * (the gate fails open on it — see the header note).
2795
- * @param selfUrl - the module anchor (injectable for hermetic tests).
2796
- */
2797
- function detectHarnessVersion(ctx, selfUrl = import.meta.url) {
2865
+ * @param resolveUrl - the running anchor's URL resolver (injectable for hermetic tests).
2866
+ * @param pluginRoot - this package's root for the own-closure check (injectable for hermetic tests).
2867
+ */
2868
+ function detectHarnessVersion(ctx, resolveUrl = resolveRunningModule, pluginRoot = PLUGIN_ROOT) {
2869
+ const running = probeRunningTree((specifier) => {
2870
+ const url = resolveUrl(specifier);
2871
+ if (!url.startsWith("file:")) throw new Error(`dsh-context: non-file module URL for ${specifier}`);
2872
+ return fileURLToPath(url);
2873
+ }, pluginRoot);
2874
+ if (running !== void 0) return running;
2798
2875
  try {
2799
2876
  const homePath = ctx.get("dshHomePath");
2800
2877
  if (typeof homePath === "function") {
@@ -2803,12 +2880,6 @@ function detectHarnessVersion(ctx, selfUrl = import.meta.url) {
2803
2880
  if (home !== void 0) return home;
2804
2881
  }
2805
2882
  } catch {}
2806
- try {
2807
- const req = createRequire(selfUrl);
2808
- return probeAnchor((specifier) => req.resolve(specifier), LIBRARY_PROBE_PACKAGES);
2809
- } catch {
2810
- return;
2811
- }
2812
2883
  }
2813
2884
  //#endregion
2814
2885
  //#region src/host/index.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-context",
3
- "version": "0.49.3",
3
+ "version": "0.49.4",
4
4
  "description": "A DeepSeek Harness plugin for context insight and management, with context dashboard and context command, for understanding how the context is made of, and how it evolves.",
5
5
  "author": "bowenliang123",
6
6
  "repository": {