@goondocks/myco 1.2.0-beta.1 → 1.2.0-beta.2

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.
@@ -5,7 +5,7 @@
5
5
  <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>Myco</title>
8
- <script type="module" crossorigin src="/assets/index-BnYhMW3F.js"></script>
8
+ <script type="module" crossorigin src="/assets/index-DUb7343F.js"></script>
9
9
  <link rel="stylesheet" crossorigin href="/assets/index-B7gU3-ZJ.css">
10
10
  </head>
11
11
  <body>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goondocks/myco",
3
- "version": "1.2.0-beta.1",
3
+ "version": "1.2.0-beta.2",
4
4
  "description": "Collective agent intelligence — Claude Code plugin",
5
5
  "type": "module",
6
6
  "bin": {
@@ -73,11 +73,11 @@
73
73
  "zod": "^4.4.3"
74
74
  },
75
75
  "optionalDependencies": {
76
- "@goondocks/myco-darwin-arm64": "1.2.0-beta.1",
77
- "@goondocks/myco-darwin-x64": "1.2.0-beta.1",
78
- "@goondocks/myco-linux-arm64": "1.2.0-beta.1",
79
- "@goondocks/myco-linux-x64": "1.2.0-beta.1",
80
- "@goondocks/myco-windows-x64": "1.2.0-beta.1"
76
+ "@goondocks/myco-darwin-arm64": "1.2.0-beta.2",
77
+ "@goondocks/myco-darwin-x64": "1.2.0-beta.2",
78
+ "@goondocks/myco-linux-arm64": "1.2.0-beta.2",
79
+ "@goondocks/myco-linux-x64": "1.2.0-beta.2",
80
+ "@goondocks/myco-windows-x64": "1.2.0-beta.2"
81
81
  },
82
82
  "devDependencies": {
83
83
  "@goondocks/myco-shared": "*",
@@ -8,9 +8,16 @@
8
8
  // `bin/myco` dispatch can find it), and then CONVERGES: it copies the
9
9
  // selected binary into the canonical managed location (`~/.myco/bin/myco`),
10
10
  // reconciles the `runtime.command` pin so every CLI invocation re-execs the
11
- // managed binary, writes the install marker, and re-points the OS service at
12
- // the managed binary. npm thus becomes a one-time bootstrap that hands off to
13
- // the same self-updating binary the curl installer produces.
11
+ // managed binary, and writes the install marker. The daemon heals the OS
12
+ // service unit on its next startup via `ensureSelfInstalledAsService`, so
13
+ // the postinstall does NOT need to call any service-install logic doing so
14
+ // would require `dist/src/` modules that are never emitted in the published
15
+ // tarball (the build only produces a bun binary + `dist/ui/`).
16
+ //
17
+ // Path layout helpers are inlined here (not imported from `dist/src/`) for
18
+ // the same reason: this script is the only .mjs in the published package and
19
+ // must be self-contained. The layout it produces MUST match what
20
+ // `src/install/managed-binary.ts` computes (verified by the pack smoke test).
14
21
  //
15
22
  // This module exports `convergeNpmInstall` so the convergence mechanics are
16
23
  // unit-testable in isolation. The postinstall side effects run only when the
@@ -23,6 +30,31 @@ import os from 'node:os';
23
30
  import { createRequire } from 'node:module';
24
31
  import { fileURLToPath, pathToFileURL } from 'node:url';
25
32
 
33
+ // ---------------------------------------------------------------------------
34
+ // Inlined path helpers — must match src/install/managed-binary.ts exactly.
35
+ // We cannot import dist/src/ because it is never emitted in the published
36
+ // tarball (the build only produces a bun binary + dist/ui/).
37
+ // ---------------------------------------------------------------------------
38
+
39
+ function managedBinDir(home, platform, localAppData) {
40
+ if (platform === 'win32') {
41
+ const appDataLocal = localAppData ?? path.win32.join(home, 'AppData', 'Local');
42
+ return path.win32.join(appDataLocal, 'Myco', 'bin');
43
+ }
44
+ return path.posix.join(home, '.myco', 'bin');
45
+ }
46
+
47
+ function managedBinaryPath(home, platform, localAppData) {
48
+ const binaryName = platform === 'win32' ? 'myco.exe' : 'myco';
49
+ return (platform === 'win32' ? path.win32 : path.posix).join(managedBinDir(home, platform, localAppData), binaryName);
50
+ }
51
+
52
+ function versionBinaryPath(home, platform, version, localAppData) {
53
+ const binaryName = platform === 'win32' ? 'myco.exe' : 'myco';
54
+ const p = platform === 'win32' ? path.win32 : path.posix;
55
+ return p.join(managedBinDir(home, platform, localAppData), 'versions', version, binaryName);
56
+ }
57
+
26
58
  function detectTarget() {
27
59
  const { platform, arch } = process;
28
60
  if (platform === 'darwin') return arch === 'arm64' ? 'darwin-arm64' : 'darwin-x64';
@@ -37,10 +69,8 @@ function detectTarget() {
37
69
  * to stderr and is NON-FATAL — npm postinstall must never fail because the
38
70
  * daemon's lazy-spawn path and `myco doctor` still recover the gap.
39
71
  *
40
- * `dest` and `versionedDest` are INJECTED (not computed here) so the paths
41
- * live in exactly one place — `@myco/install/managed-binary` — which prod
42
- * computes from the compiled `dist` module and tests compute from the `.ts`.
43
- * Same source, zero `.ts`/`.mjs` drift.
72
+ * `dest` and `versionedDest` are INJECTED so tests can supply arbitrary paths
73
+ * without touching the real home directory.
44
74
  *
45
75
  * Layout produced (mirrors install.sh / the daemon helpers):
46
76
  * `versionedDest` → <bindir>/versions/<bare-semver>/myco[.exe]
@@ -157,11 +187,8 @@ export function convergeNpmInstall({ home, platform, resolvedBinary, dest, chann
157
187
  }
158
188
 
159
189
  // --- Install marker -----------------------------------------------------
160
- // When `writeMarker` is injected (production: `managed.writeInstallMarker`
161
- // from dist/src/install/managed-binary.js), delegate to the canonical helper
162
- // so the format is defined in exactly one place. Tests that call
163
- // convergeNpmInstall directly do not inject `writeMarker`, so the inline
164
- // fallback keeps convergence unit-testable without a compiled dist/.
190
+ // `writeMarker` is an optional injection seam for tests. Production callers
191
+ // omit it; the inline fallback writes the same JSON shape.
165
192
  try {
166
193
  if (writeMarker) {
167
194
  writeMarker(mycoHome, { channel, source: 'npm', bin: dest });
@@ -251,66 +278,44 @@ async function main() {
251
278
 
252
279
  process.stdout.write(`[myco] Selected platform binary: ${binaryPath}\n`);
253
280
 
254
- // Converge npm into the single managed binary, then self-install/repoint the
255
- // OS service at it. Skipped in source checkouts (no published dist/). Both
256
- // steps are wrapped so neither can fail the postinstall — the daemon's
257
- // lazy-spawn path still works and `myco doctor` surfaces any gap.
258
- // Plan reference: Decision 13 / Step 12.
281
+ // Converge npm into the single managed binary. Skipped in source checkouts
282
+ // (no platform binary present before `make dev-link`). Wrapped so a failure
283
+ // logs to stderr and is NON-FATAL — the daemon's lazy-spawn path still works
284
+ // and `myco doctor` surfaces any gap. Plan reference: Decision 13 / Step 12.
285
+ //
286
+ // Service install is intentionally NOT performed here. The daemon calls
287
+ // `ensureSelfInstalledAsService` on every startup (daemon/main.ts), which is
288
+ // idempotent and handles the service unit. Attempting it from the postinstall
289
+ // would require dist/src/service/self-install.js, which is never emitted in
290
+ // the published tarball.
259
291
  if (!isSourceCheckout) {
260
- const distManagedBinary = path.join(pkgRoot, 'dist/src/install/managed-binary.js');
261
- let dest = null;
262
- if (fs.existsSync(distManagedBinary)) {
263
- try {
264
- const managed = await import(distManagedBinary);
265
- const home = os.homedir();
266
- const platform = process.platform;
267
- // `pkg.version` is the bare semver (e.g. "1.2.3") — npm packages never
268
- // carry the "myco/v" tag prefix that curl installers use. This is the
269
- // exact version string the daemon's versionBinaryPath() expects.
270
- let pkg = { version: null };
271
- try {
272
- pkg = JSON.parse(fs.readFileSync(path.join(pkgRoot, 'package.json'), 'utf8'));
273
- } catch { /* version stays null; versionedDest skipped */ }
274
- const version = pkg.version ?? null;
275
- dest = managed.managedBinaryPath(home, platform);
276
- const versionedDest = version
277
- ? managed.versionBinaryPath(home, platform, version)
278
- : null;
279
- const channel = deriveChannel(pkgRoot);
280
- convergeNpmInstall({
281
- home,
282
- platform,
283
- resolvedBinary: binaryPath,
284
- dest,
285
- channel,
286
- version,
287
- versionedDest,
288
- writeMarker: managed.writeInstallMarker,
289
- });
290
- } catch (err) {
291
- process.stderr.write(`[myco] Convergence skipped: ${err?.message ?? err}\n`);
292
- }
293
- } else {
294
- process.stderr.write('[myco] Convergence skipped: managed-binary module not found in dist/\n');
295
- }
296
-
297
- const distSelfInstall = path.join(pkgRoot, 'dist/src/service/self-install.js');
298
- if (fs.existsSync(distSelfInstall)) {
292
+ try {
293
+ const home = os.homedir();
294
+ const platform = process.platform;
295
+ // `pkg.version` is the bare semver (e.g. "1.2.3") — npm packages never
296
+ // carry the "myco/v" tag prefix that curl installers use. This is the
297
+ // exact version string the daemon's versionBinaryPath() expects.
298
+ let pkg = { version: null };
299
299
  try {
300
- const mod = await import(distSelfInstall);
301
- const stderrLogger = {
302
- info: (kind, message) => process.stderr.write(`[myco] ${kind}: ${message}\n`),
303
- debug: () => undefined,
304
- warn: (kind, message) => process.stderr.write(`[myco] ${kind}: ${message}\n`),
305
- error: (kind, message) => process.stderr.write(`[myco] ${kind}: ${message}\n`),
306
- };
307
- // Re-point the service unit at the managed binary so a self-update's
308
- // in-place swap takes effect on the next supervisor restart. Falls
309
- // back to the default executable inside self-install if `dest` is null.
310
- await mod.ensureSelfInstalledAsService(stderrLogger, dest ? { executable: dest } : {});
311
- } catch (err) {
312
- process.stderr.write(`[myco] Service install skipped: ${err?.message ?? err}\n`);
313
- }
300
+ pkg = JSON.parse(fs.readFileSync(path.join(pkgRoot, 'package.json'), 'utf8'));
301
+ } catch { /* version stays null; versionedDest skipped */ }
302
+ const version = pkg.version ?? null;
303
+ const dest = managedBinaryPath(home, platform, process.env.LOCALAPPDATA);
304
+ const versionedDest = version
305
+ ? versionBinaryPath(home, platform, version, process.env.LOCALAPPDATA)
306
+ : null;
307
+ const channel = deriveChannel(pkgRoot);
308
+ convergeNpmInstall({
309
+ home,
310
+ platform,
311
+ resolvedBinary: binaryPath,
312
+ dest,
313
+ channel,
314
+ version,
315
+ versionedDest,
316
+ });
317
+ } catch (err) {
318
+ process.stderr.write(`[myco] Convergence skipped: ${err?.message ?? err}\n`);
314
319
  }
315
320
  }
316
321
  }