@reinamaccredy/maestro 1.0.1 → 1.1.0

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.
@@ -26,3 +26,4 @@ export * from "./session-cursor";
26
26
  export * from "./shell-env";
27
27
  export * from "./system-directive";
28
28
  export * from "./agent-tool-restrictions";
29
+ export * from "./platform-detection";
@@ -0,0 +1,42 @@
1
+ export type Platform = "opencode" | "claude-code" | "amp" | "codex" | "unknown";
2
+ /**
3
+ * Detect which AI coding platform is running this plugin.
4
+ *
5
+ * Detection priority:
6
+ * 1. Plugin context (for OpenCode - ctx.client exists)
7
+ * 2. Environment variables (most reliable for other platforms)
8
+ * 3. Directory presence (fallback)
9
+ */
10
+ export declare function detectPlatform(ctx?: {
11
+ client?: unknown;
12
+ directory?: string;
13
+ }): Platform;
14
+ /**
15
+ * Check if running on Amp Code with native oracle tool.
16
+ *
17
+ * Amp Code provides oracle/librarian as NATIVE TOOLS, not agents.
18
+ * When true, we should NOT register our Virtuoso/Archivist agents.
19
+ *
20
+ * Detection: Check if platform is Amp or if tool registry contains
21
+ * a tool named "oracle" that is NOT one of our registered agents.
22
+ */
23
+ export declare function hasNativeOracle(ctx?: {
24
+ tools?: Map<string, unknown>;
25
+ }): boolean;
26
+ /**
27
+ * Check if running on Amp Code with native librarian tool.
28
+ * Same logic as hasNativeOracle.
29
+ */
30
+ export declare function hasNativeLibrarian(ctx?: {
31
+ tools?: Map<string, unknown>;
32
+ }): boolean;
33
+ /**
34
+ * Get platform-specific skill directory.
35
+ * Different platforms look for skills in different locations.
36
+ */
37
+ export declare function getSkillDirectory(platform: Platform): string;
38
+ /**
39
+ * Check if we should skip registering our agents because
40
+ * native equivalents exist on the current platform.
41
+ */
42
+ export declare function shouldSkipAgent(agentName: string): boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reinamaccredy/maestro",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "Maestro - Context-driven development for AI coding agents with music-themed orchestration",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/postinstall.mjs CHANGED
@@ -1,10 +1,16 @@
1
1
  // postinstall.mjs
2
- // Runs after npm install to verify platform binary is available
2
+ // Runs after npm install to:
3
+ // 1. Verify platform binary is available
4
+ // 2. Create skill symlinks for multi-platform compatibility
3
5
 
4
6
  import { createRequire } from "node:module";
7
+ import { existsSync, symlinkSync, mkdirSync, realpathSync, lstatSync } from "node:fs";
8
+ import { join, dirname } from "node:path";
9
+ import { fileURLToPath } from "node:url";
5
10
  import { getPlatformPackage, getBinaryPath } from "./bin/platform.js";
6
11
 
7
12
  const require = createRequire(import.meta.url);
13
+ const __dirname = dirname(fileURLToPath(import.meta.url));
8
14
 
9
15
  /**
10
16
  * Detect libc family on Linux
@@ -22,7 +28,89 @@ function getLibcFamily() {
22
28
  }
23
29
  }
24
30
 
25
- function main() {
31
+ /**
32
+ * Check if path is a symlink
33
+ */
34
+ function isSymlink(path) {
35
+ try {
36
+ return lstatSync(path).isSymbolicLink();
37
+ } catch {
38
+ return false;
39
+ }
40
+ }
41
+
42
+ /**
43
+ * Create skill symlinks for multi-platform compatibility.
44
+ * Creates symlinks from platform-specific skill directories to our builtin-skills.
45
+ */
46
+ function createSkillSymlinks() {
47
+ // Skills are in the npm package at src/features/builtin-skills/
48
+ // __dirname is the package root (where postinstall.mjs lives)
49
+ const skillsSource = join(__dirname, "src", "features", "builtin-skills");
50
+
51
+ // Verify skills source exists (should always exist in published package)
52
+ if (!existsSync(skillsSource)) {
53
+ console.log("[SKIP] Skills source not found (development install?)");
54
+ return;
55
+ }
56
+
57
+ // User's project root (where npm install was run)
58
+ const projectRoot = process.cwd();
59
+
60
+ // Skip if we're in the package directory itself (development)
61
+ if (projectRoot === __dirname) {
62
+ console.log("[SKIP] Development install detected");
63
+ return;
64
+ }
65
+
66
+ const symlinks = [
67
+ { target: ".claude/skills", platform: "claude-code" },
68
+ { target: ".opencode/skill", platform: "opencode" },
69
+ { target: ".codex/skills", platform: "codex" },
70
+ { target: ".agents/skills", platform: "amp" },
71
+ ];
72
+
73
+ console.log("Creating skill symlinks...");
74
+
75
+ for (const { target, platform } of symlinks) {
76
+ const targetPath = join(projectRoot, target);
77
+ const targetDir = dirname(targetPath);
78
+
79
+ // Don't overwrite existing directories/files (unless it's our symlink)
80
+ if (existsSync(targetPath) && !isSymlink(targetPath)) {
81
+ console.log(` [SKIP] ${target} already exists (${platform})`);
82
+ continue;
83
+ }
84
+
85
+ // If it's an existing symlink, skip (already set up)
86
+ if (isSymlink(targetPath)) {
87
+ console.log(` [OK] ${target} symlink exists (${platform})`);
88
+ continue;
89
+ }
90
+
91
+ try {
92
+ // Create parent directory if needed
93
+ if (!existsSync(targetDir)) {
94
+ mkdirSync(targetDir, { recursive: true });
95
+ }
96
+
97
+ // On Windows, use junction (doesn't require admin)
98
+ // On Unix, use absolute path for reliability
99
+ if (process.platform === "win32") {
100
+ symlinkSync(skillsSource, targetPath, "junction");
101
+ } else {
102
+ const absoluteSource = realpathSync(skillsSource);
103
+ symlinkSync(absoluteSource, targetPath);
104
+ }
105
+ console.log(` [OK] Created ${target} -> builtin-skills (${platform})`);
106
+ } catch (error) {
107
+ // Warn but don't fail installation
108
+ console.warn(` [WARN] Failed to create ${target}: ${error.message}`);
109
+ }
110
+ }
111
+ }
112
+
113
+ function checkBinary() {
26
114
  const { platform, arch } = process;
27
115
  const libcFamily = getLibcFamily();
28
116
 
@@ -32,12 +120,17 @@ function main() {
32
120
 
33
121
  // Try to resolve the binary
34
122
  require.resolve(binPath);
35
- console.log(`✓ oh-my-opencode binary installed for ${platform}-${arch}`);
123
+ console.log(`[OK] Maestro binary installed for ${platform}-${arch}`);
36
124
  } catch (error) {
37
- console.warn(`⚠ oh-my-opencode: ${error.message}`);
125
+ console.warn(`[WARN] Maestro: ${error.message}`);
38
126
  console.warn(` The CLI may not work on this platform.`);
39
127
  // Don't fail installation - let user try anyway
40
128
  }
41
129
  }
42
130
 
131
+ function main() {
132
+ checkBinary();
133
+ createSkillSymlinks();
134
+ }
135
+
43
136
  main();