pi-mega-compact 0.4.7 → 0.4.9

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.
@@ -24,7 +24,7 @@
24
24
  * before_agent_start systemPrompt prepend (PREVENT-PI-003).
25
25
  */
26
26
  import { sessionEntryToContextMessages } from "@earendil-works/pi-coding-agent";
27
- import { join, dirname } from "node:path";
27
+ import { join, dirname, sep } from "node:path";
28
28
  import { fileURLToPath } from "node:url";
29
29
  import { STATE_DIR_DEFAULT } from "../src/config.js";
30
30
  import { VectorStore } from "../src/vectorStore.js";
@@ -651,6 +651,10 @@ export default function (pi) {
651
651
  // ---- Dashboard server commands ----------------------------------------
652
652
  const portFile = join(currentStateDir, "port.pid");
653
653
  const runnerFile = join(currentStateDir, "_dashboard-runner.mjs");
654
+ // Whether the runner must be spawned with --experimental-strip-types (true only
655
+ // when we fall back to the .ts source outside node_modules; false when using
656
+ // the shipped compiled dist/extensions/dashboard-server.js).
657
+ let dashboardNeedsStrip = false;
654
658
  /** Try to reach a running dashboard server. Returns { port, url } or null. */
655
659
  async function isServerRunning() {
656
660
  if (!existsSync(portFile))
@@ -674,23 +678,54 @@ export default function (pi) {
674
678
  }
675
679
  return null;
676
680
  }
681
+ /**
682
+ * Resolve the launchable dashboard-server module.
683
+ *
684
+ * CRITICAL: Node's `--experimental-strip-types` REFUSES to strip .ts files that
685
+ * live under `node_modules` (ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING). Since
686
+ * the published package installs under node_modules, importing the .ts source
687
+ * fails in every real install (it only worked from a source checkout). So we
688
+ * prefer the COMPILED dist/extensions/dashboard-server.js (which the package
689
+ * ships from v0.4.6 — it imports only Node built-ins, so it runs standalone),
690
+ * and only fall back to the .ts source (with strip-types) when the compiled
691
+ * file is absent AND we're not under node_modules (dev checkout without a build).
692
+ *
693
+ * Returns { entry, needsStripTypes }.
694
+ */
695
+ function resolveDashboardEntry() {
696
+ const here = dirname(fileURLToPath(import.meta.url)); // .../extensions
697
+ const candidates = [
698
+ // 1. Compiled sibling when running from dist/ (import.meta is dist/extensions/…js)
699
+ { entry: join(here, "dashboard-server.js"), strip: false },
700
+ // 2. Compiled under the package's dist/ when running from source extensions/…ts
701
+ { entry: join(here, "..", "dist", "extensions", "dashboard-server.js"), strip: false },
702
+ // 3. Last resort: the .ts source (only strippable OUTSIDE node_modules)
703
+ { entry: join(here, "dashboard-server.ts"), strip: true },
704
+ ];
705
+ for (const c of candidates) {
706
+ if (!existsSync(c.entry))
707
+ continue;
708
+ if (c.strip && c.entry.includes(`${sep}node_modules${sep}`))
709
+ continue; // unstrippable
710
+ return { entry: c.entry, needsStripTypes: c.strip };
711
+ }
712
+ return null;
713
+ }
677
714
  /** Write a small ESM runner script that imports and launches the dashboard server. */
678
715
  function writeRunnerScript() {
679
- // The npm package ships SOURCE only (no dist/), so the launchable entry is
680
- // the .ts file — not dashboard-server.js (which only exists after a local
681
- // build). dashboard-server.ts imports only Node built-ins, so it loads under
682
- // node's --experimental-strip-types without any other compiled code. The
683
- // child is spawned with that flag (see the spawn below) so the import below
684
- // resolves from the source install path.
685
- const sourceServer = join(dirname(fileURLToPath(import.meta.url)), "dashboard-server.ts");
716
+ const resolved = resolveDashboardEntry();
717
+ if (!resolved)
718
+ return false;
719
+ dashboardNeedsStrip = resolved.needsStripTypes;
686
720
  const script = [
687
- `import { launchDashboardServer } from ${JSON.stringify(sourceServer)};`,
721
+ `import { launchDashboardServer } from ${JSON.stringify(resolved.entry)};`,
688
722
  `launchDashboardServer(${JSON.stringify(currentStateDir)}).catch(err => {`,
689
723
  ` console.error("[mega-compact] dashboard failed:", err);`,
690
724
  ` process.exit(1);`,
691
725
  `});`,
692
726
  ].join("\n");
693
727
  writeFileSync(runnerFile, script);
728
+ return true;
694
729
  }
695
730
  /** Open a URL in the default browser. Platform-aware. Uses spawn (not exec) to avoid shell injection. */
696
731
  function openBrowser(url) {
@@ -718,8 +753,12 @@ export default function (pi) {
718
753
  }
719
754
  // Start the server
720
755
  ctx.ui.notify("[mega-compact] starting dashboard server…");
721
- writeRunnerScript();
722
- const child = spawn(process.execPath, ["--experimental-strip-types", runnerFile], {
756
+ if (!writeRunnerScript()) {
757
+ ctx.ui.notify("[mega-compact] dashboard entry not found check logs.");
758
+ return;
759
+ }
760
+ const args = dashboardNeedsStrip ? ["--experimental-strip-types", runnerFile] : [runnerFile];
761
+ const child = spawn(process.execPath, args, {
723
762
  detached: true,
724
763
  stdio: "ignore",
725
764
  });
@@ -27,7 +27,7 @@
27
27
  import type { ExtensionAPI, ExtensionContext, ContextEvent, SessionBeforeCompactEvent } from "@earendil-works/pi-coding-agent";
28
28
  import { sessionEntryToContextMessages } from "@earendil-works/pi-coding-agent";
29
29
  import type { AgentMessage } from "@earendil-works/pi-agent-core";
30
- import { join, dirname } from "node:path";
30
+ import { join, dirname, sep } from "node:path";
31
31
  import { fileURLToPath } from "node:url";
32
32
  import { STATE_DIR_DEFAULT } from "../src/config.js";
33
33
  import { VectorStore } from "../src/vectorStore.js";
@@ -790,6 +790,10 @@ export default function (pi: ExtensionAPI) {
790
790
 
791
791
  const portFile = join(currentStateDir, "port.pid");
792
792
  const runnerFile = join(currentStateDir, "_dashboard-runner.mjs");
793
+ // Whether the runner must be spawned with --experimental-strip-types (true only
794
+ // when we fall back to the .ts source outside node_modules; false when using
795
+ // the shipped compiled dist/extensions/dashboard-server.js).
796
+ let dashboardNeedsStrip = false;
793
797
 
794
798
  /** Try to reach a running dashboard server. Returns { port, url } or null. */
795
799
  async function isServerRunning(): Promise<{ port: number; url: string } | null> {
@@ -808,23 +812,52 @@ export default function (pi: ExtensionAPI) {
808
812
  return null;
809
813
  }
810
814
 
815
+ /**
816
+ * Resolve the launchable dashboard-server module.
817
+ *
818
+ * CRITICAL: Node's `--experimental-strip-types` REFUSES to strip .ts files that
819
+ * live under `node_modules` (ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING). Since
820
+ * the published package installs under node_modules, importing the .ts source
821
+ * fails in every real install (it only worked from a source checkout). So we
822
+ * prefer the COMPILED dist/extensions/dashboard-server.js (which the package
823
+ * ships from v0.4.6 — it imports only Node built-ins, so it runs standalone),
824
+ * and only fall back to the .ts source (with strip-types) when the compiled
825
+ * file is absent AND we're not under node_modules (dev checkout without a build).
826
+ *
827
+ * Returns { entry, needsStripTypes }.
828
+ */
829
+ function resolveDashboardEntry(): { entry: string; needsStripTypes: boolean } | null {
830
+ const here = dirname(fileURLToPath(import.meta.url)); // .../extensions
831
+ const candidates = [
832
+ // 1. Compiled sibling when running from dist/ (import.meta is dist/extensions/…js)
833
+ { entry: join(here, "dashboard-server.js"), strip: false },
834
+ // 2. Compiled under the package's dist/ when running from source extensions/…ts
835
+ { entry: join(here, "..", "dist", "extensions", "dashboard-server.js"), strip: false },
836
+ // 3. Last resort: the .ts source (only strippable OUTSIDE node_modules)
837
+ { entry: join(here, "dashboard-server.ts"), strip: true },
838
+ ];
839
+ for (const c of candidates) {
840
+ if (!existsSync(c.entry)) continue;
841
+ if (c.strip && c.entry.includes(`${sep}node_modules${sep}`)) continue; // unstrippable
842
+ return { entry: c.entry, needsStripTypes: c.strip };
843
+ }
844
+ return null;
845
+ }
846
+
811
847
  /** Write a small ESM runner script that imports and launches the dashboard server. */
812
- function writeRunnerScript(): void {
813
- // The npm package ships SOURCE only (no dist/), so the launchable entry is
814
- // the .ts file — not dashboard-server.js (which only exists after a local
815
- // build). dashboard-server.ts imports only Node built-ins, so it loads under
816
- // node's --experimental-strip-types without any other compiled code. The
817
- // child is spawned with that flag (see the spawn below) so the import below
818
- // resolves from the source install path.
819
- const sourceServer = join(dirname(fileURLToPath(import.meta.url)), "dashboard-server.ts");
848
+ function writeRunnerScript(): boolean {
849
+ const resolved = resolveDashboardEntry();
850
+ if (!resolved) return false;
851
+ dashboardNeedsStrip = resolved.needsStripTypes;
820
852
  const script = [
821
- `import { launchDashboardServer } from ${JSON.stringify(sourceServer)};`,
853
+ `import { launchDashboardServer } from ${JSON.stringify(resolved.entry)};`,
822
854
  `launchDashboardServer(${JSON.stringify(currentStateDir)}).catch(err => {`,
823
855
  ` console.error("[mega-compact] dashboard failed:", err);`,
824
856
  ` process.exit(1);`,
825
857
  `});`,
826
858
  ].join("\n");
827
859
  writeFileSync(runnerFile, script);
860
+ return true;
828
861
  }
829
862
 
830
863
  /** Open a URL in the default browser. Platform-aware. Uses spawn (not exec) to avoid shell injection. */
@@ -855,9 +888,13 @@ export default function (pi: ExtensionAPI) {
855
888
 
856
889
  // Start the server
857
890
  ctx.ui.notify("[mega-compact] starting dashboard server…");
858
- writeRunnerScript();
891
+ if (!writeRunnerScript()) {
892
+ ctx.ui.notify("[mega-compact] dashboard entry not found — check logs.");
893
+ return;
894
+ }
859
895
 
860
- const child = spawn(process.execPath, ["--experimental-strip-types", runnerFile], {
896
+ const args = dashboardNeedsStrip ? ["--experimental-strip-types", runnerFile] : [runnerFile];
897
+ const child = spawn(process.execPath, args, {
861
898
  detached: true,
862
899
  stdio: "ignore",
863
900
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-mega-compact",
3
- "version": "0.4.7",
3
+ "version": "0.4.9",
4
4
  "description": "Layered, local, vector-backed context compressor for pi — supersede/collapse/cluster compaction with deduped inline recall.",
5
5
  "type": "module",
6
6
  "license": "BSD-2-Clause",