botmux 3.18.3 → 3.18.5

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.
Files changed (101) hide show
  1. package/dist/.runtime-build-id +1 -1
  2. package/dist/adapters/hook-installer.d.ts.map +1 -1
  3. package/dist/adapters/hook-installer.js +75 -2
  4. package/dist/adapters/hook-installer.js.map +1 -1
  5. package/dist/cli/current-actor.d.ts.map +1 -1
  6. package/dist/cli/current-actor.js +2 -1
  7. package/dist/cli/current-actor.js.map +1 -1
  8. package/dist/cli/dashboard-endpoint.d.ts.map +1 -1
  9. package/dist/cli/dashboard-endpoint.js +5 -2
  10. package/dist/cli/dashboard-endpoint.js.map +1 -1
  11. package/dist/cli/exact-chat-grant-client.d.ts.map +1 -1
  12. package/dist/cli/exact-chat-grant-client.js +2 -1
  13. package/dist/cli/exact-chat-grant-client.js.map +1 -1
  14. package/dist/cli/vc-agent.d.ts.map +1 -1
  15. package/dist/cli/vc-agent.js +2 -1
  16. package/dist/cli/vc-agent.js.map +1 -1
  17. package/dist/cli.d.ts.map +1 -1
  18. package/dist/cli.js +105 -11
  19. package/dist/cli.js.map +1 -1
  20. package/dist/core/binary-install-shape.d.ts +77 -0
  21. package/dist/core/binary-install-shape.d.ts.map +1 -0
  22. package/dist/core/binary-install-shape.js +117 -0
  23. package/dist/core/binary-install-shape.js.map +1 -0
  24. package/dist/core/binary-self-update.d.ts +82 -0
  25. package/dist/core/binary-self-update.d.ts.map +1 -0
  26. package/dist/core/binary-self-update.js +239 -0
  27. package/dist/core/binary-self-update.js.map +1 -0
  28. package/dist/core/daemon-ipc-auth.d.ts +9 -1
  29. package/dist/core/daemon-ipc-auth.d.ts.map +1 -1
  30. package/dist/core/daemon-ipc-auth.js +14 -3
  31. package/dist/core/daemon-ipc-auth.js.map +1 -1
  32. package/dist/core/loopback-fetch.d.ts +59 -0
  33. package/dist/core/loopback-fetch.d.ts.map +1 -0
  34. package/dist/core/loopback-fetch.js +347 -0
  35. package/dist/core/loopback-fetch.js.map +1 -0
  36. package/dist/core/maintenance.d.ts +88 -1
  37. package/dist/core/maintenance.d.ts.map +1 -1
  38. package/dist/core/maintenance.js +149 -8
  39. package/dist/core/maintenance.js.map +1 -1
  40. package/dist/core/managed-origin-attestation.d.ts.map +1 -1
  41. package/dist/core/managed-origin-attestation.js +2 -1
  42. package/dist/core/managed-origin-attestation.js.map +1 -1
  43. package/dist/core/release-download.d.ts +13 -0
  44. package/dist/core/release-download.d.ts.map +1 -0
  45. package/dist/core/release-download.js +130 -0
  46. package/dist/core/release-download.js.map +1 -0
  47. package/dist/daemon.d.ts.map +1 -1
  48. package/dist/daemon.js +2 -1
  49. package/dist/daemon.js.map +1 -1
  50. package/dist/dashboard/aggregator.d.ts.map +1 -1
  51. package/dist/dashboard/aggregator.js +2 -1
  52. package/dist/dashboard/aggregator.js.map +1 -1
  53. package/dist/dashboard/daemon-internal-client.d.ts.map +1 -1
  54. package/dist/dashboard/daemon-internal-client.js +6 -1
  55. package/dist/dashboard/daemon-internal-client.js.map +1 -1
  56. package/dist/dashboard/groups-action-helpers.d.ts +0 -10
  57. package/dist/dashboard/groups-action-helpers.d.ts.map +1 -1
  58. package/dist/dashboard/groups-action-helpers.js +3 -2
  59. package/dist/dashboard/groups-action-helpers.js.map +1 -1
  60. package/dist/dashboard/hd2d-assets.d.ts +2 -3
  61. package/dist/dashboard/hd2d-assets.d.ts.map +1 -1
  62. package/dist/dashboard/hd2d-assets.js +7 -109
  63. package/dist/dashboard/hd2d-assets.js.map +1 -1
  64. package/dist/dashboard/web/app.d.ts.map +1 -1
  65. package/dist/dashboard/web/app.js +7 -1
  66. package/dist/dashboard/web/app.js.map +1 -1
  67. package/dist/dashboard/web/settings-page.d.ts.map +1 -1
  68. package/dist/dashboard/web/settings-page.js.map +1 -1
  69. package/dist/dashboard-web/app.js +1 -1
  70. package/dist/dashboard.js +122 -14
  71. package/dist/dashboard.js.map +1 -1
  72. package/dist/services/hook-runner.d.ts.map +1 -1
  73. package/dist/services/hook-runner.js +2 -1
  74. package/dist/services/hook-runner.js.map +1 -1
  75. package/dist/services/voice/openai.d.ts.map +1 -1
  76. package/dist/services/voice/openai.js +10 -1
  77. package/dist/services/voice/openai.js.map +1 -1
  78. package/dist/services/worktree-slug-ai.d.ts.map +1 -1
  79. package/dist/services/worktree-slug-ai.js +8 -1
  80. package/dist/services/worktree-slug-ai.js.map +1 -1
  81. package/dist/utils/file-lock.d.ts +25 -0
  82. package/dist/utils/file-lock.d.ts.map +1 -1
  83. package/dist/utils/file-lock.js +34 -4
  84. package/dist/utils/file-lock.js.map +1 -1
  85. package/dist/utils/global-install.d.ts +19 -0
  86. package/dist/utils/global-install.d.ts.map +1 -1
  87. package/dist/utils/global-install.js +28 -1
  88. package/dist/utils/global-install.js.map +1 -1
  89. package/dist/utils/install-info.d.ts +37 -1
  90. package/dist/utils/install-info.d.ts.map +1 -1
  91. package/dist/utils/install-info.js +45 -3
  92. package/dist/utils/install-info.js.map +1 -1
  93. package/dist/workflows/v3/daemon-ipc-client.d.ts.map +1 -1
  94. package/dist/workflows/v3/daemon-ipc-client.js +2 -1
  95. package/dist/workflows/v3/daemon-ipc-client.js.map +1 -1
  96. package/dist/workflows/v3/session-relay-client.d.ts.map +1 -1
  97. package/dist/workflows/v3/session-relay-client.js +2 -1
  98. package/dist/workflows/v3/session-relay-client.js.map +1 -1
  99. package/package.json +8 -7
  100. package/scripts/install-path-entry.mjs +263 -0
  101. package/scripts/postinstall-bin.mjs +41 -7
@@ -1,7 +1,24 @@
1
1
  /** Pure check: is `rootDir` a source working copy rather than an npm install? */
2
2
  export declare function isLocalDevInstallAt(rootDir: string): boolean;
3
- /** Classify this running install. Cached — it cannot change at runtime. */
3
+ /**
4
+ * Classify this running install. Cached — it cannot change at runtime.
5
+ *
6
+ * ⚠️ A COMPILED BINARY IS NEVER A SOURCE CHECKOUT, and the naive check cannot
7
+ * see that. `packageRoot()` walks up looking for package.json; inside a
8
+ * single-file executable there is none on disk (the module graph lives in the
9
+ * virtual `/$bunfs/`), so it returns `/` — and the test then becomes "does the
10
+ * FILESYSTEM ROOT have .git or src?". On this box neither exists so the answer is
11
+ * accidentally correct, but plenty of container images do have `/src`, and there
12
+ * the compiled binary would be misclassified as a dev checkout and sent down the
13
+ * `git pull --ff-only` update path.
14
+ *
15
+ * The standalone check is therefore an explicit early return, not a refinement of
16
+ * the filesystem probe. Node behaviour is bit-for-bit unchanged.
17
+ */
4
18
  export declare function isLocalDevInstall(): boolean;
19
+ /** Test seam: drop the cached classification. Production never calls this — the
20
+ * answer genuinely cannot change within one process. */
21
+ export declare function __resetLocalDevInstallCacheForTests(): void;
5
22
  /**
6
23
  * The version baked in at compile time by scripts/build-bun-binary.mjs, or
7
24
  * undefined when running from Node.
@@ -25,6 +42,25 @@ export declare function bakedBinaryVersion(): string | undefined;
25
42
  * npm-global install this is the real published version; in a source checkout
26
43
  * it's the unbuilt '0.0.0' (CI injects the real version at publish). */
27
44
  export declare function botmuxVersionAt(rootDir: string): string;
45
+ /**
46
+ * The version recorded in `rootDir`'s package.json, IGNORING the baked value.
47
+ *
48
+ * ⚠️ WHY THIS EXISTS — THE BAKED VERSION SHADOWS A COMPLETED UPDATE. `baked` is
49
+ * compiled into the running executable, so `botmuxVersionAt` returns it no matter
50
+ * which directory you ask about. That is right for "what am I running", and WRONG
51
+ * for "what is now installed on disk": after a package-manager update replaces the
52
+ * install tree, a compiled binary asking `botmuxVersionAt(root)` still gets its OWN
53
+ * old version (measured: package.json says 3.19.0, the call returns 3.18.4).
54
+ *
55
+ * The maintenance tick gates its restart on `after !== before`, so that shadowing
56
+ * makes a successful update look like "already on the latest version" — it never
57
+ * restarts onto what it just installed. Post-update reads must therefore use this
58
+ * function, not `botmuxVersionAt`.
59
+ *
60
+ * (Under Node `bakedBinaryVersion()` is undefined, so the two are identical there
61
+ * — which is why this defect only surfaces for the compiled binary.)
62
+ */
63
+ export declare function diskVersionAt(rootDir: string): string;
28
64
  export declare function botmuxVersion(): string;
29
65
  /** Absolute path to this install's CLI entrypoint (`dist/cli.js`). The correct
30
66
  * way to restart is `node <this>/dist/cli.js restart` — a raw `pm2 restart`
@@ -1 +1 @@
1
- {"version":3,"file":"install-info.d.ts","sourceRoot":"","sources":["../../src/utils/install-info.ts"],"names":[],"mappings":"AAcA,iFAAiF;AACjF,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE5D;AAID,2EAA2E;AAC3E,wBAAgB,iBAAiB,IAAI,OAAO,CAG3C;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,GAAG,SAAS,CASvD;AAED;;yEAEyE;AACzE,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAUvD;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;+CAE+C;AAC/C,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED;;iEAEiE;AACjE,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C"}
1
+ {"version":3,"file":"install-info.d.ts","sourceRoot":"","sources":["../../src/utils/install-info.ts"],"names":[],"mappings":"AAeA,iFAAiF;AACjF,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE5D;AAID;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAK3C;AAED;yDACyD;AACzD,wBAAgB,mCAAmC,IAAI,IAAI,CAE1D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,GAAG,SAAS,CASvD;AAED;;yEAEyE;AACzE,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAKvD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAOrD;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;+CAE+C;AAC/C,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED;;iEAEiE;AACjE,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C"}
@@ -11,17 +11,38 @@
11
11
  import { existsSync, readFileSync } from 'node:fs';
12
12
  import { dirname, join } from 'node:path';
13
13
  import { fileURLToPath } from 'node:url';
14
+ import { isStandaloneBinary } from '../core/self-spawn.js';
14
15
  /** Pure check: is `rootDir` a source working copy rather than an npm install? */
15
16
  export function isLocalDevInstallAt(rootDir) {
16
17
  return existsSync(join(rootDir, '.git')) || existsSync(join(rootDir, 'src'));
17
18
  }
18
19
  let cached;
19
- /** Classify this running install. Cached — it cannot change at runtime. */
20
+ /**
21
+ * Classify this running install. Cached — it cannot change at runtime.
22
+ *
23
+ * ⚠️ A COMPILED BINARY IS NEVER A SOURCE CHECKOUT, and the naive check cannot
24
+ * see that. `packageRoot()` walks up looking for package.json; inside a
25
+ * single-file executable there is none on disk (the module graph lives in the
26
+ * virtual `/$bunfs/`), so it returns `/` — and the test then becomes "does the
27
+ * FILESYSTEM ROOT have .git or src?". On this box neither exists so the answer is
28
+ * accidentally correct, but plenty of container images do have `/src`, and there
29
+ * the compiled binary would be misclassified as a dev checkout and sent down the
30
+ * `git pull --ff-only` update path.
31
+ *
32
+ * The standalone check is therefore an explicit early return, not a refinement of
33
+ * the filesystem probe. Node behaviour is bit-for-bit unchanged.
34
+ */
20
35
  export function isLocalDevInstall() {
21
- if (cached === undefined)
22
- cached = isLocalDevInstallAt(packageRoot());
36
+ if (cached === undefined) {
37
+ cached = isStandaloneBinary() ? false : isLocalDevInstallAt(packageRoot());
38
+ }
23
39
  return cached;
24
40
  }
41
+ /** Test seam: drop the cached classification. Production never calls this — the
42
+ * answer genuinely cannot change within one process. */
43
+ export function __resetLocalDevInstallCacheForTests() {
44
+ cached = undefined;
45
+ }
25
46
  /**
26
47
  * The version baked in at compile time by scripts/build-bun-binary.mjs, or
27
48
  * undefined when running from Node.
@@ -60,6 +81,27 @@ export function botmuxVersionAt(rootDir) {
60
81
  const baked = bakedBinaryVersion();
61
82
  if (baked)
62
83
  return baked;
84
+ return diskVersionAt(rootDir);
85
+ }
86
+ /**
87
+ * The version recorded in `rootDir`'s package.json, IGNORING the baked value.
88
+ *
89
+ * ⚠️ WHY THIS EXISTS — THE BAKED VERSION SHADOWS A COMPLETED UPDATE. `baked` is
90
+ * compiled into the running executable, so `botmuxVersionAt` returns it no matter
91
+ * which directory you ask about. That is right for "what am I running", and WRONG
92
+ * for "what is now installed on disk": after a package-manager update replaces the
93
+ * install tree, a compiled binary asking `botmuxVersionAt(root)` still gets its OWN
94
+ * old version (measured: package.json says 3.19.0, the call returns 3.18.4).
95
+ *
96
+ * The maintenance tick gates its restart on `after !== before`, so that shadowing
97
+ * makes a successful update look like "already on the latest version" — it never
98
+ * restarts onto what it just installed. Post-update reads must therefore use this
99
+ * function, not `botmuxVersionAt`.
100
+ *
101
+ * (Under Node `bakedBinaryVersion()` is undefined, so the two are identical there
102
+ * — which is why this defect only surfaces for the compiled binary.)
103
+ */
104
+ export function diskVersionAt(rootDir) {
63
105
  try {
64
106
  const pkg = JSON.parse(readFileSync(join(rootDir, 'package.json'), 'utf-8'));
65
107
  return typeof pkg.version === 'string' ? pkg.version : '0.0.0';
@@ -1 +1 @@
1
- {"version":3,"file":"install-info.js","sourceRoot":"","sources":["../../src/utils/install-info.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,iFAAiF;AACjF,MAAM,UAAU,mBAAmB,CAAC,OAAe;IACjD,OAAO,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;AAC/E,CAAC;AAED,IAAI,MAA2B,CAAC;AAEhC,2EAA2E;AAC3E,MAAM,UAAU,iBAAiB;IAC/B,IAAI,MAAM,KAAK,SAAS;QAAE,MAAM,GAAG,mBAAmB,CAAC,WAAW,EAAE,CAAC,CAAC;IACtE,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,kBAAkB;IAChC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;IAC/C,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAChD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,8EAA8E;IAC9E,2EAA2E;IAC3E,6DAA6D;IAC7D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,KAAK,OAAO;QAAE,OAAO,SAAS,CAAC;IAClE,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;yEAEyE;AACzE,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,4EAA4E;IAC5E,MAAM,KAAK,GAAG,kBAAkB,EAAE,CAAC;IACnC,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC;IACxB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;QAC7E,OAAO,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,eAAe,CAAC,WAAW,EAAE,CAAC,CAAC;AACxC,CAAC;AAED;;+CAE+C;AAC/C,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,OAAO,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,gBAAgB,CAAC,WAAW,EAAE,CAAC,CAAC;AACzC,CAAC;AAED;;iEAEiE;AACjE,MAAM,UAAU,iBAAiB;IAC/B,OAAO,WAAW,EAAE,CAAC;AACvB,CAAC;AAED,2EAA2E;AAC3E,SAAS,WAAW;IAClB,IAAI,GAAG,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAClD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;YAAE,OAAO,GAAG,CAAC;QACtD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,MAAM,KAAK,GAAG;YAAE,MAAM;QAC1B,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
1
+ {"version":3,"file":"install-info.js","sourceRoot":"","sources":["../../src/utils/install-info.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"daemon-ipc-client.d.ts","sourceRoot":"","sources":["../../../src/workflows/v3/daemon-ipc-client.ts"],"names":[],"mappings":"AAAA,oEAAoE;AAEpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,EAML,KAAK,uBAAuB,EAC7B,MAAM,sBAAsB,CAAC;AAE9B,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;AAE5E,MAAM,WAAW,8BAA8B;IAC7C,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,oCAAqC,SAAQ,KAAK;aAChB,UAAU,CAAC,EAAE,OAAO;gBAArD,OAAO,EAAE,MAAM,EAAkB,UAAU,CAAC,EAAE,OAAO,YAAA;CAIlE;AAED,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,IAAI,CACV,gBAAgB,EAChB,WAAW,GAAG,SAAS,GAAG,gBAAgB,GAAG,qBAAqB,CACnE,GACA,uBAAuB,CAWzB;AAED,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,sBAAsB,GAC/B,MAAM,CAER;AAED;;;;GAIG;AACH,wBAAsB,0BAA0B,CAAC,KAAK,EAAE;IACtD,MAAM,EAAE,IAAI,CACV,gBAAgB,EAChB,WAAW,GAAG,SAAS,GAAG,gBAAgB,GAAG,qBAAqB,CACnE,CAAC;IACF,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,sBAAsB,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,8BAA8B,CAAC,CAgD1C"}
1
+ {"version":3,"file":"daemon-ipc-client.d.ts","sourceRoot":"","sources":["../../../src/workflows/v3/daemon-ipc-client.ts"],"names":[],"mappings":"AAAA,oEAAoE;AAEpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAExE,OAAO,EAML,KAAK,uBAAuB,EAC7B,MAAM,sBAAsB,CAAC;AAE9B,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;AAE5E,MAAM,WAAW,8BAA8B;IAC7C,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,oCAAqC,SAAQ,KAAK;aAChB,UAAU,CAAC,EAAE,OAAO;gBAArD,OAAO,EAAE,MAAM,EAAkB,UAAU,CAAC,EAAE,OAAO,YAAA;CAIlE;AAED,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,IAAI,CACV,gBAAgB,EAChB,WAAW,GAAG,SAAS,GAAG,gBAAgB,GAAG,qBAAqB,CACnE,GACA,uBAAuB,CAWzB;AAED,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,sBAAsB,GAC/B,MAAM,CAER;AAED;;;;GAIG;AACH,wBAAsB,0BAA0B,CAAC,KAAK,EAAE;IACtD,MAAM,EAAE,IAAI,CACV,gBAAgB,EAChB,WAAW,GAAG,SAAS,GAAG,gBAAgB,GAAG,qBAAqB,CACnE,CAAC;IACF,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,sBAAsB,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,8BAA8B,CAAC,CAgD1C"}
@@ -1,4 +1,5 @@
1
1
  /** Shared client for authenticated Workflow v3 daemon mutations. */
2
+ import { loopbackFetchImpl } from '../../core/loopback-fetch.js';
2
3
  import { generateWorkflowDaemonIpcNonce, loadWorkflowDaemonIpcSecret, WORKFLOW_DAEMON_IPC_ROUTE_PREFIX, verifyWorkflowDaemonIpcResponse, workflowDaemonIpcHeaders, } from './daemon-ipc-auth.js';
3
4
  export class WorkflowDaemonMutationTransportError extends Error {
4
5
  causeValue;
@@ -42,7 +43,7 @@ export async function postWorkflowDaemonMutation(input) {
42
43
  timestamp,
43
44
  nonce,
44
45
  });
45
- const fetchImpl = input.fetchImpl ?? fetch;
46
+ const fetchImpl = input.fetchImpl ?? loopbackFetchImpl;
46
47
  let response;
47
48
  try {
48
49
  response = await fetchImpl(`http://127.0.0.1:${target.ipcPort}${pathWithQuery}`, {
@@ -1 +1 @@
1
- {"version":3,"file":"daemon-ipc-client.js","sourceRoot":"","sources":["../../../src/workflows/v3/daemon-ipc-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"daemon-ipc-client.js","sourceRoot":"","sources":["../../../src/workflows/v3/daemon-ipc-client.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"session-relay-client.d.ts","sourceRoot":"","sources":["../../../src/workflows/v3/session-relay-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EACL,2BAA2B,EAC5B,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,KAAK,EAAE,sBAAsB,EAAE,8BAA8B,EAAE,MAAM,wBAAwB,CAAC;AAIrG,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,+BAA+B,CAAC,OAAO,EAAE;IACvD,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB;IAClB,SAAS,CAAC,EAAE,OAAO,2BAA2B,CAAC;IAC/C,UAAU,CAAC,EAAE,OAAO,0BAA0B,CAAC;CAChD,GAAG,2BAA2B,GAAG,IAAI,CAgCrC;AAED;;;;GAIG;AACH,wBAAsB,8BAA8B,CAAC,KAAK,EAAE;IAC1D,OAAO,EAAE,2BAA2B,CAAC;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,sBAAsB,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,8EAA8E;IAC9E,cAAc,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,KAAK,MAAM,GAAG,SAAS,CAAC;IACvE,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B,GAAG,OAAO,CAAC,8BAA8B,CAAC,CAqC1C"}
1
+ {"version":3,"file":"session-relay-client.d.ts","sourceRoot":"","sources":["../../../src/workflows/v3/session-relay-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EACL,2BAA2B,EAC5B,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,KAAK,EAAE,sBAAsB,EAAE,8BAA8B,EAAE,MAAM,wBAAwB,CAAC;AAKrG,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,+BAA+B,CAAC,OAAO,EAAE;IACvD,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB;IAClB,SAAS,CAAC,EAAE,OAAO,2BAA2B,CAAC;IAC/C,UAAU,CAAC,EAAE,OAAO,0BAA0B,CAAC;CAChD,GAAG,2BAA2B,GAAG,IAAI,CAgCrC;AAED;;;;GAIG;AACH,wBAAsB,8BAA8B,CAAC,KAAK,EAAE;IAC1D,OAAO,EAAE,2BAA2B,CAAC;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,sBAAsB,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,8EAA8E;IAC9E,cAAc,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,KAAK,MAAM,GAAG,SAAS,CAAC;IACvE,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B,GAAG,OAAO,CAAC,8BAA8B,CAAC,CAqC1C"}
@@ -16,6 +16,7 @@ import { readManagedOriginCapability, } from '../../core/managed-origin-capabili
16
16
  import { findAncestorSessionContext } from '../../core/session-marker.js';
17
17
  import { WorkflowDaemonMutationTransportError } from './daemon-ipc-client.js';
18
18
  import { V3_SESSION_RUN_MUTATION_ROUTE_PREFIX } from './session-relay.js';
19
+ import { loopbackFetchImpl } from '../../core/loopback-fetch.js';
19
20
  /**
20
21
  * Detect an isolated session and load its per-turn capability.
21
22
  *
@@ -83,7 +84,7 @@ export async function postWorkflowSessionRunMutation(input) {
83
84
  ? { originDispatchAttempt: input.context.dispatchAttempt }
84
85
  : {}),
85
86
  });
86
- const fetchImpl = input.fetchImpl ?? fetch;
87
+ const fetchImpl = input.fetchImpl ?? loopbackFetchImpl;
87
88
  let response;
88
89
  try {
89
90
  response = await fetchImpl(`http://127.0.0.1:${ipcPort}${path}`, {
@@ -1 +1 @@
1
- {"version":3,"file":"session-relay-client.js","sourceRoot":"","sources":["../../../src/workflows/v3/session-relay-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EACL,2BAA2B,GAC5B,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAE1E,OAAO,EAAE,oCAAoC,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,EAAE,oCAAoC,EAAE,MAAM,oBAAoB,CAAC;AAa1E;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,+BAA+B,CAAC,OAO/C;IACC,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,IAAI,EAAE,CAAC;IACxD,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAC5B,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,0BAA0B,CAAC;IACpE,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IACxF,IAAI,MAAM,EAAE,SAAS;QAAE,OAAO,IAAI,CAAC;IACnC,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,2BAA2B,CAAC;IACnE,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,IAAI,EAAE,CAAC;IACvD,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,wBAAwB,EAAE,IAAI,EAAE,CAAC;IACrE,MAAM,KAAK,GAAG,SAAS,CACrB,OAAO,CAAC,OAAO,EACf,SAAS,EACT,QAAQ,IAAI,SAAS,EACrB,eAAe,IAAI,SAAS,CAC7B,CAAC;IACF,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IAC3D,qEAAqE;IACrE,wEAAwE;IACxE,uEAAuE;IACvE,MAAM,eAAe,GAAG,KAAK,CAAC,OAAO;WAChC,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAC1E,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,IAAI,EAAE,CAAC;IACzD,OAAO;QACL,SAAS;QACT,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjD,GAAG,CAAC,KAAK,CAAC,eAAe,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,KAAK,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1F,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnC,GAAG,CAAC,eAAe,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9D,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAAC,KAQpD;IACC,MAAM,UAAU,GAAG,KAAK,CAAC,cAAc,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACnE,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,eAAe,IAAI,UAAU,CAAC;IAC5D,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,oCAAoC,CAC5C,yEAAyE,CAC1E,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,GAAG,oCAAoC,IAAI,kBAAkB,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;IAC5G,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC;QACjC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,SAAS;QAClC,gBAAgB,EAAE,KAAK,CAAC,OAAO,CAAC,UAAU;QAC1C,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,eAAe;YAC/B,CAAC,CAAC,EAAE,eAAe,EAAE,KAAK,CAAC,OAAO,CAAC,eAAe,EAAE;YACpD,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvE,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,eAAe,KAAK,SAAS;YAC7C,CAAC,CAAC,EAAE,qBAAqB,EAAE,KAAK,CAAC,OAAO,CAAC,eAAe,EAAE;YAC1D,CAAC,CAAC,EAAE,CAAC;KACR,CAAC,CAAC;IACH,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC;IAC3C,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,SAAS,CAAC,oBAAoB,OAAO,GAAG,IAAI,EAAE,EAAE;YAC/D,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,WAAW;SAClB,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,oCAAoC,CAC5C,qBAAqB,OAAO,MAAM,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EACpF,GAAG,CACJ,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACtC,OAAO,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;AAC/D,CAAC"}
1
+ {"version":3,"file":"session-relay-client.js","sourceRoot":"","sources":["../../../src/workflows/v3/session-relay-client.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "botmux",
3
- "version": "3.18.3",
3
+ "version": "3.18.5",
4
4
  "description": "Bridge between IM platforms and AI coding CLIs — one topic, one CLI session with live streaming",
5
5
  "type": "module",
6
6
  "main": "dist/index-daemon.js",
7
7
  "files": [
8
8
  "dist/",
9
9
  "scripts/postinstall-bin.mjs",
10
+ "scripts/install-path-entry.mjs",
10
11
  "ecosystem.config.cjs",
11
12
  "README.md",
12
13
  "README.en.md",
@@ -79,12 +80,12 @@
79
80
  },
80
81
  "optionalDependencies": {
81
82
  "@napi-rs/canvas": "^0.1.65",
82
- "botmux-darwin-arm64": "3.18.3",
83
- "botmux-darwin-x64": "3.18.3",
84
- "botmux-linux-arm64": "3.18.3",
85
- "botmux-linux-arm64-musl": "3.18.3",
86
- "botmux-linux-x64": "3.18.3",
87
- "botmux-linux-x64-musl": "3.18.3"
83
+ "botmux-darwin-arm64": "3.18.5",
84
+ "botmux-darwin-x64": "3.18.5",
85
+ "botmux-linux-arm64": "3.18.5",
86
+ "botmux-linux-arm64-musl": "3.18.5",
87
+ "botmux-linux-x64": "3.18.5",
88
+ "botmux-linux-x64-musl": "3.18.5"
88
89
  },
89
90
  "devDependencies": {
90
91
  "@midscene/web": "^1.7.6",
@@ -0,0 +1,263 @@
1
+ /**
2
+ * Put `~/.botmux/bin` on the user's PATH by writing their shell's startup file.
3
+ *
4
+ * WHY THIS EXISTS
5
+ * `npm i -g botmux` has no `bin` field (removed with the Node fallback — see
6
+ * postinstall-bin.mjs), so the ONLY `botmux` command is the launcher written to
7
+ * `~/.botmux/bin/botmux`. If that directory is not on PATH, a successful install
8
+ * still leaves the user with `botmux: command not found`.
9
+ *
10
+ * Both installers used to just PRINT a hint, and the hint was:
11
+ *
12
+ * echo 'export PATH="…"' >> ~/.profile
13
+ *
14
+ * which is wrong for a large share of users, because **zsh never reads
15
+ * `~/.profile`** (measured: `zsh -lic` on a home dir containing `.profile` reads
16
+ * `.zshenv` + `.zprofile` + `.zshrc` and the `.profile` echo never fires). A zsh
17
+ * user who followed the hint verbatim got a file that is silently ignored — the
18
+ * command stayed missing with no indication why. That was the reported bug.
19
+ *
20
+ * ── WHICH FILE PER SHELL (all measured, not recalled) ─────────────────────────
21
+ * Startup files actually sourced, by shell and invocation mode:
22
+ *
23
+ * zsh -c → .zshenv
24
+ * -i → .zshenv .zshrc
25
+ * -li → .zshenv .zprofile .zshrc
26
+ * bash -c → (none)
27
+ * -i → .bashrc
28
+ * -li → the FIRST of .bash_profile → .bash_login → .profile
29
+ * fish → ~/.config/fish/conf.d/*.fish in all three modes
30
+ *
31
+ * So the target per shell is the file that covers the most modes:
32
+ * • zsh → ~/.zshenv (the only file read in all 3)
33
+ * • bash → ~/.bashrc AND its login file (login vs interactive are disjoint)
34
+ * • fish → ~/.config/fish/conf.d/botmux.fish
35
+ *
36
+ * bash genuinely needs both: writing only `.bashrc` misses login shells, and
37
+ * writing only the login file misses ordinary interactive ones.
38
+ *
39
+ * ⚠️ bash's login file is "the first that EXISTS", not always `.bash_profile` —
40
+ * see bashLoginFile() below for why creating the wrong one destroys the user's
41
+ * existing login config.
42
+ *
43
+ * ── fish SYNTAX ──────────────────────────────────────────────────────────────
44
+ * fish is not POSIX; `export PATH="$INSTALL_DIR:$PATH"` is not its syntax. (fish
45
+ * 3.6 happens to tolerate `export` as a compatibility shim and even produces a
46
+ * correct PATH — measured — but `set -gx` is the real form and is what we write.)
47
+ */
48
+
49
+ import { existsSync, readFileSync, appendFileSync, mkdirSync, writeFileSync } from 'node:fs';
50
+ import { join, dirname } from 'node:path';
51
+ import { homedir } from 'node:os';
52
+ import { basename } from 'node:path';
53
+
54
+ /** Marker so we can detect our own previous edit and never write twice. */
55
+ export const PATH_ENTRY_MARKER = '# added by botmux installer';
56
+
57
+ /**
58
+ * Which shell is the user actually on? `$SHELL` is the login shell recorded in
59
+ * passwd, which is what future terminals will start — the right question here,
60
+ * and better than `process.ppid` guessing (the parent of a postinstall is npm,
61
+ * not the user's shell).
62
+ */
63
+ export function detectShell(env = process.env) {
64
+ const shell = env.SHELL ?? '';
65
+ const name = basename(shell);
66
+ if (name.includes('zsh')) return 'zsh';
67
+ if (name.includes('fish')) return 'fish';
68
+ if (name.includes('bash')) return 'bash';
69
+ // Unknown or unset (containers, cron, exotic shells): POSIX `.profile` is the
70
+ // most portable thing we can offer, and sh/ksh/dash all read it at login.
71
+ return name ? 'other' : 'unknown';
72
+ }
73
+
74
+ /**
75
+ * bash's LOGIN startup file, chosen without shadowing anything.
76
+ *
77
+ * ⚠️ bash reads only the FIRST of `.bash_profile` → `.bash_login` → `.profile`.
78
+ * So creating `.bash_profile` on a machine whose login config lives in
79
+ * `.profile` (or `.bash_login`) silently stops that file from ever being read.
80
+ * Measured — a sentinel exported from `.profile` is visible to `bash -lic`, and
81
+ * becomes MISSING the moment an unrelated `.bash_profile` appears; same for
82
+ * `.bash_login`. That is destroying the user's environment to fix a PATH entry,
83
+ * which is far worse than the bug being fixed.
84
+ *
85
+ * So: append to whichever of the three already exists (that is the file bash is
86
+ * actually reading), and only fall back to CREATING `.bash_profile` when none of
87
+ * them exists — in which case there is nothing to shadow.
88
+ */
89
+ function bashLoginFile(home) {
90
+ for (const name of ['.bash_profile', '.bash_login', '.profile']) {
91
+ const file = join(home, name);
92
+ if (existsSync(file)) return file;
93
+ }
94
+ return join(home, '.bash_profile');
95
+ }
96
+
97
+ /**
98
+ * Quote a path for literal use inside a shell startup file.
99
+ *
100
+ * ⚠️ SECURITY, not cosmetics. The install dir is caller-controlled
101
+ * (`BOTMUX_INSTALL_DIR`, or just an unusual home), and the line we write is
102
+ * EXECUTED by the user's shell on every startup. Interpolating it into double
103
+ * quotes lets `$(…)`, backticks and `$VAR` run: measured — an install dir
104
+ * containing `$(touch /tmp/PWNED)` created that file the first time zsh started,
105
+ * and did so on every shell thereafter.
106
+ *
107
+ * Single quotes make the shell treat every byte literally; the only character
108
+ * needing care is `'` itself, closed and re-opened via `'\''`. This form is
109
+ * identical in POSIX shells and in fish.
110
+ */
111
+ function shellQuote(value) {
112
+ return `'${String(value).replace(/'/g, `'\\''`)}'`;
113
+ }
114
+
115
+ /**
116
+ * The startup files to write for a shell, plus the line to write into each.
117
+ * Returns [] when we have nothing safe to say.
118
+ *
119
+ * `env` is read for the two relocation variables below; both are honoured
120
+ * because writing the un-relocated path produces a file the shell never reads —
121
+ * the same class of bug as writing `.profile` for zsh.
122
+ */
123
+ export function pathEntryTargets(shell, installDir, home = homedir(), env = process.env) {
124
+ const q = shellQuote(installDir);
125
+ // ⚠️ The STATEMENT has to be idempotent too, not just the file write. An
126
+ // unconditional `export PATH=<dir>:$PATH` re-prepends on every shell startup, so
127
+ // a nested or re-sourced shell keeps growing PATH — measured: the same directory
128
+ // appeared twice at nesting depth 2, and `.bash_profile` files that source
129
+ // `.bashrc` hit it within a single login. `case` is POSIX and quote-safe (no
130
+ // subshell, no `grep`), and the `:` padding makes it an exact ELEMENT test, so a
131
+ // sibling like `<dir>-old` never satisfies it.
132
+ const posix = `case ":$PATH:" in *:${q}:*) ;; *) export PATH=${q}":$PATH" ;; esac ${PATH_ENTRY_MARKER}`;
133
+ switch (shell) {
134
+ case 'zsh': {
135
+ // ⚠️ zsh reads its dotfiles from $ZDOTDIR when that is set, falling back to
136
+ // $HOME. Writing $HOME/.zshenv on a machine with ZDOTDIR set produces a file
137
+ // zsh never reads — measured: `zsh -c botmux` → "command not found".
138
+ const zdotdir = env.ZDOTDIR?.trim();
139
+ const base = zdotdir ? zdotdir : home;
140
+ return [{ file: join(base, '.zshenv'), line: posix }];
141
+ }
142
+ case 'bash': {
143
+ // Disjoint coverage — see header. Both, or one of the two common ways of
144
+ // opening a terminal is left broken. The login half must not shadow (above).
145
+ const login = bashLoginFile(home);
146
+ const targets = [{ file: join(home, '.bashrc'), line: posix }];
147
+ // When bash's login file IS .bashrc-adjacent there is nothing more to add;
148
+ // dedupe so we never append the same line to the same file twice.
149
+ if (login !== join(home, '.bashrc')) targets.push({ file: login, line: posix });
150
+ return targets;
151
+ }
152
+ case 'fish': {
153
+ // ⚠️ fish's config dir is $XDG_CONFIG_HOME/fish, defaulting to ~/.config/fish.
154
+ // Same failure as ZDOTDIR above — measured: with XDG_CONFIG_HOME set, a file
155
+ // under ~/.config/fish is ignored, while the same line under
156
+ // $XDG_CONFIG_HOME/fish/conf.d works (positive control).
157
+ const xdg = env.XDG_CONFIG_HOME?.trim();
158
+ const configHome = xdg ? xdg : join(home, '.config');
159
+ return [{
160
+ file: join(configHome, 'fish', 'conf.d', 'botmux.fish'),
161
+ // fish: `contains` is its own exact list-element test — PATH is a real list
162
+ // here, so no delimiter padding is needed.
163
+ line: `contains ${q} $PATH; or set -gx PATH ${q} $PATH ${PATH_ENTRY_MARKER}`,
164
+ }];
165
+ }
166
+ case 'other':
167
+ case 'unknown':
168
+ default:
169
+ return [{ file: join(home, '.profile'), line: posix }];
170
+ }
171
+ }
172
+
173
+ /** Is `installDir` already handled by this file (ours or the user's own line)? */
174
+ export function fileAlreadyHasEntry(file, installDir) {
175
+ if (!existsSync(file)) return false;
176
+ let text;
177
+ try { text = readFileSync(file, 'utf8'); } catch { return false; }
178
+
179
+ // ⚠️ TWO SEPARATE PREDICATES, deliberately not one clever one.
180
+ //
181
+ // Attempt #1 searched for the raw directory as a substring: `<installDir>-old`,
182
+ // `/backup<installDir>` and `<installDir>/other` all counted as configured, so
183
+ // the REAL directory was never written (measured, written=0 for each).
184
+ // Attempt #2 split the line into tokens and compared them — but the line we
185
+ // WRITE for a directory containing a quote is
186
+ // export PATH='/x/q'\''bin'":$PATH"
187
+ // and ANY tokenizer that treats `'` as a separator shreds that into `/x/q`,
188
+ // `\`, `bin`, so the quoted spelling can never match a token (measured: marker
189
+ // count 1 → 2 on every re-install). Shell quoting cannot be undone by splitting
190
+ // on characters.
191
+ //
192
+ // So: recognise OUR line by its own known syntax (marker + the exact quoted
193
+ // form we would generate), and use conservative whole-token matching only for a
194
+ // line the USER wrote by hand.
195
+ const ourQuoted = shellQuote(installDir);
196
+ const lines = text.split('\n').filter(l => !/^\s*#/.test(l));
197
+
198
+ // (a) Our own line, byte-for-byte on the part that identifies the directory.
199
+ // `PATH=` + the exact quoted dir is enough; the suffix may legitimately
200
+ // differ (`":$PATH"` vs fish's ` $PATH`).
201
+ if (lines.some(l => l.includes(PATH_ENTRY_MARKER) && l.includes(ourQuoted))) return true;
202
+
203
+ // (b) A hand-written line. Compare whole PATH elements, and do NOT treat quotes
204
+ // as element separators — strip the wrapping quotes first, then split on the
205
+ // characters that actually delimit PATH elements.
206
+ const PATH_ASSIGNMENT = new RegExp(
207
+ [
208
+ 'export\\s+PATH\\s*=', // POSIX: export PATH="…"
209
+ '^\\s*PATH\\s*=', // POSIX: PATH=…
210
+ 'set\\s+(-\\w+\\s+)*PATH', // fish: set -gx PATH …
211
+ 'fish_add_path', // fish: fish_add_path …
212
+ '\\bpath\\+=', // zsh: path+=(…)
213
+ '\\bpath=\\(', // zsh: path=(…)
214
+ ].join('|'),
215
+ 'i',
216
+ );
217
+ const target = installDir.replace(/\/+$/, '');
218
+ return lines.some(l => {
219
+ if (!PATH_ASSIGNMENT.test(l)) return false;
220
+ // Quotes here are shell syntax around a plain path (the quote-containing case
221
+ // is handled by (a)); dropping them leaves the path bytes intact.
222
+ const bare = l.replace(/["']/g, '');
223
+ return bare
224
+ .split(/[:\s()=]+/)
225
+ .map(t => t.replace(/\/+$/, ''))
226
+ .some(t => t !== '' && t === target);
227
+ });
228
+ }
229
+
230
+ /**
231
+ * Append the PATH line to every startup file the user's shell reads.
232
+ *
233
+ * Returns `{ written: string[], skipped: string[], failed: [{file, error}] }`.
234
+ * Never throws: a PATH edit failing must not fail the install (the launcher is
235
+ * already in place and the caller prints a manual fallback).
236
+ */
237
+ export function ensurePathEntry(opts) {
238
+ const installDir = opts.installDir;
239
+ const env = opts.env ?? process.env;
240
+ const home = opts.home ?? homedir();
241
+ const shell = opts.shell ?? detectShell(env);
242
+ const targets = pathEntryTargets(shell, installDir, home, env);
243
+
244
+ const written = [], skipped = [], failed = [];
245
+ for (const { file, line } of targets) {
246
+ if (fileAlreadyHasEntry(file, installDir)) { skipped.push(file); continue; }
247
+ try {
248
+ mkdirSync(dirname(file), { recursive: true });
249
+ if (existsSync(file)) {
250
+ // Keep the user's file intact; only append, and only with a leading
251
+ // newline so we never glue onto an unterminated last line.
252
+ const prev = readFileSync(file, 'utf8');
253
+ appendFileSync(file, `${prev.endsWith('\n') || prev === '' ? '' : '\n'}${line}\n`);
254
+ } else {
255
+ writeFileSync(file, `${line}\n`);
256
+ }
257
+ written.push(file);
258
+ } catch (err) {
259
+ failed.push({ file, error: err && err.message ? err.message : String(err) });
260
+ }
261
+ }
262
+ return { shell, written, skipped, failed };
263
+ }
@@ -219,11 +219,45 @@ try {
219
219
  );
220
220
  }
221
221
 
222
- // ── PATH hint ─────────────────────────────────────────────────────────────────
223
- // Mirrors install.sh. Without ~/.botmux/bin on PATH the launcher we just wrote is
224
- // never the `botmux` the user's shell resolves.
225
- const pathEntries = (process.env.PATH ?? '').split(':');
226
- if (!pathEntries.includes(binDir)) {
227
- console.log(`[botmux] add ${binDir} to your PATH so this launcher is the \`botmux\` your shell finds:`);
228
- console.log(`[botmux] echo 'export PATH="${binDir}:$PATH"' >> ~/.profile && . ~/.profile`);
222
+ // ── PATH: write it, don't just suggest it ─────────────────────────────────────
223
+ // This used to only PRINT `echo 'export PATH=…' >> ~/.profile`. Two problems:
224
+ // the user had to act on it, and for zsh users the suggested file is WRONG —
225
+ // zsh never reads ~/.profile (measured), so following the hint verbatim left
226
+ // `botmux` still not found. There is no `bin` field any more, so PATH is the
227
+ // only way this launcher becomes a command; we now write the right startup file
228
+ // for the user's actual shell (bash/zsh/fish/other) and tell them what we did.
229
+ //
230
+ // ⚠️ FAIL-SOFT, and never `fail()`: the launcher is already installed and working
231
+ // at this point, so a PATH edit that cannot happen must degrade to the printed
232
+ // hint — not abort a successful install. That includes the sibling module simply
233
+ // not being there: it ships via package.json `files`, and if a future edit drops
234
+ // it (or a mirror repacks the tarball without it) the import throws. Guarding it
235
+ // keeps `npm i -g botmux` succeeding either way.
236
+ if (!(process.env.PATH ?? '').split(':').includes(binDir)) {
237
+ let ensurePathEntry = null;
238
+ try {
239
+ ({ ensurePathEntry } = await import('./install-path-entry.mjs'));
240
+ } catch (err) {
241
+ console.error(`[botmux] PATH helper unavailable (${err && err.message ? err.message : String(err)})`);
242
+ }
243
+ let written = [], skipped = [];
244
+ if (ensurePathEntry) {
245
+ try {
246
+ const r = ensurePathEntry({ installDir: binDir });
247
+ ({ written, skipped } = r);
248
+ for (const f of written) console.log(`[botmux] added ${binDir} to PATH in ${f} (${r.shell})`);
249
+ for (const f of skipped) console.log(`[botmux] ${f} already puts ${binDir} on PATH`);
250
+ for (const { file, error } of r.failed) console.error(`[botmux] could not update ${file}: ${error}`);
251
+ } catch (err) {
252
+ console.error(`[botmux] could not update your shell startup file: ${err && err.message ? err.message : String(err)}`);
253
+ }
254
+ }
255
+ if (written.length > 0) {
256
+ console.log('[botmux] open a new terminal (or re-source that file) and `botmux` will be on PATH');
257
+ } else if (skipped.length === 0) {
258
+ // Nothing written and nothing already present — fall back to telling them.
259
+ // Deliberately not naming a specific file here: the correct one depends on
260
+ // the shell, and naming the wrong one is what caused the original bug.
261
+ console.log(`[botmux] add ${binDir} to your PATH so this launcher is the \`botmux\` your shell finds`);
262
+ }
229
263
  }