@nex-ai/nex 0.1.17 → 0.1.19

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 (69) hide show
  1. package/README.md +42 -23
  2. package/dist/commands/integrate.js +11 -2
  3. package/dist/commands/integrate.js.map +1 -1
  4. package/dist/commands/setup.d.ts +5 -4
  5. package/dist/commands/setup.js +141 -43
  6. package/dist/commands/setup.js.map +1 -1
  7. package/dist/lib/client.js +12 -1
  8. package/dist/lib/client.js.map +1 -1
  9. package/dist/lib/file-scanner.d.ts +1 -1
  10. package/dist/lib/file-scanner.js +4 -2
  11. package/dist/lib/file-scanner.js.map +1 -1
  12. package/dist/lib/installers.d.ts +62 -5
  13. package/dist/lib/installers.js +373 -34
  14. package/dist/lib/installers.js.map +1 -1
  15. package/dist/lib/platform-detect.d.ts +7 -0
  16. package/dist/lib/platform-detect.js +150 -8
  17. package/dist/lib/platform-detect.js.map +1 -1
  18. package/dist/lib/project-config.js +1 -1
  19. package/dist/plugin/adapters/cline-capture.d.ts +7 -0
  20. package/dist/plugin/adapters/cline-capture.js +25 -0
  21. package/dist/plugin/adapters/cline-capture.js.map +1 -0
  22. package/dist/plugin/adapters/cline-recall.d.ts +7 -0
  23. package/dist/plugin/adapters/cline-recall.js +30 -0
  24. package/dist/plugin/adapters/cline-recall.js.map +1 -0
  25. package/dist/plugin/adapters/cline-task-start.d.ts +7 -0
  26. package/dist/plugin/adapters/cline-task-start.js +30 -0
  27. package/dist/plugin/adapters/cline-task-start.js.map +1 -0
  28. package/dist/plugin/adapters/cursor-recall.d.ts +7 -0
  29. package/dist/plugin/adapters/cursor-recall.js +31 -0
  30. package/dist/plugin/adapters/cursor-recall.js.map +1 -0
  31. package/dist/plugin/adapters/cursor-session-start.d.ts +7 -0
  32. package/dist/plugin/adapters/cursor-session-start.js +30 -0
  33. package/dist/plugin/adapters/cursor-session-start.js.map +1 -0
  34. package/dist/plugin/adapters/cursor-stop.d.ts +7 -0
  35. package/dist/plugin/adapters/cursor-stop.js +25 -0
  36. package/dist/plugin/adapters/cursor-stop.js.map +1 -0
  37. package/dist/plugin/adapters/windsurf-capture.d.ts +7 -0
  38. package/dist/plugin/adapters/windsurf-capture.js +25 -0
  39. package/dist/plugin/adapters/windsurf-capture.js.map +1 -0
  40. package/dist/plugin/adapters/windsurf-recall.d.ts +7 -0
  41. package/dist/plugin/adapters/windsurf-recall.js +31 -0
  42. package/dist/plugin/adapters/windsurf-recall.js.map +1 -0
  43. package/dist/plugin/auto-capture.js +5 -106
  44. package/dist/plugin/auto-capture.js.map +1 -1
  45. package/dist/plugin/auto-recall.js +5 -79
  46. package/dist/plugin/auto-recall.js.map +1 -1
  47. package/dist/plugin/auto-session-start.d.ts +0 -3
  48. package/dist/plugin/auto-session-start.js +8 -114
  49. package/dist/plugin/auto-session-start.js.map +1 -1
  50. package/dist/plugin/shared.d.ts +38 -0
  51. package/dist/plugin/shared.js +241 -0
  52. package/dist/plugin/shared.js.map +1 -0
  53. package/package.json +3 -1
  54. package/platform-plugins/continue-provider.ts +62 -0
  55. package/platform-plugins/kilocode-modes.yaml +17 -0
  56. package/platform-plugins/opencode-plugin.ts +103 -0
  57. package/platform-plugins/vscode-agent.md +34 -0
  58. package/platform-plugins/windsurf-workflows/nex-ask.md +10 -0
  59. package/platform-plugins/windsurf-workflows/nex-remember.md +10 -0
  60. package/platform-plugins/windsurf-workflows/nex-search.md +10 -0
  61. package/platform-rules/aider-conventions.md +38 -0
  62. package/platform-rules/cline-rules.md +34 -0
  63. package/platform-rules/continue-rules.md +34 -0
  64. package/platform-rules/cursor-rules.md +34 -0
  65. package/platform-rules/kilocode-rules.md +34 -0
  66. package/platform-rules/opencode-agents.md +38 -0
  67. package/platform-rules/vscode-instructions.md +38 -0
  68. package/platform-rules/windsurf-rules.md +34 -0
  69. package/platform-rules/zed-rules.md +38 -0
@@ -4,6 +4,16 @@
4
4
  */
5
5
  import { AuthError, RateLimitError, ServerError } from "./errors.js";
6
6
  import { API_BASE, REGISTER_URL } from "./config.js";
7
+ // Pre-process JSON text: quote integer values for "id" fields that exceed
8
+ // Number.MAX_SAFE_INTEGER, preventing JS precision loss on snowflake IDs.
9
+ const UNSAFE_ID_RE = /("(?:[^"]*_)?id"\s*:\s*)(\d{16,})/g;
10
+ function safenIds(jsonText) {
11
+ return jsonText.replace(UNSAFE_ID_RE, (_match, prefix, digits) => {
12
+ if (Number.isSafeInteger(Number(digits)))
13
+ return `${prefix}${digits}`;
14
+ return `${prefix}"${digits}"`;
15
+ });
16
+ }
7
17
  export class NexClient {
8
18
  apiKey;
9
19
  timeoutMs;
@@ -61,7 +71,8 @@ export class NexClient {
61
71
  const text = await res.text();
62
72
  if (!text || !text.trim())
63
73
  return {};
64
- return JSON.parse(text);
74
+ // Preserve large integer IDs as strings to avoid JS precision loss
75
+ return JSON.parse(safenIds(text));
65
76
  }
66
77
  finally {
67
78
  clearTimeout(timer);
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/lib/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/lib/client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAErD,0EAA0E;AAC1E,0EAA0E;AAC1E,MAAM,YAAY,GAAG,oCAAoC,CAAC;AAC1D,SAAS,QAAQ,CAAC,QAAgB;IAChC,OAAO,QAAQ,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,MAAM,EAAE,MAAc,EAAE,MAAc,EAAE,EAAE;QAC/E,IAAI,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAAE,OAAO,GAAG,MAAM,GAAG,MAAM,EAAE,CAAC;QACtE,OAAO,GAAG,MAAM,IAAI,MAAM,GAAG,CAAC;IAChC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,OAAO,SAAS;IACZ,MAAM,CAAqB;IAC3B,SAAS,CAAS;IAE1B,YAAY,MAAe,EAAE,SAAS,GAAG,OAAO;QAC9C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IAED,IAAI,eAAe;QACjB,OAAO,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IAC7D,CAAC;IAED,SAAS,CAAC,GAAW;QACnB,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC;IACpB,CAAC;IAEO,WAAW;QACjB,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;YAC1B,MAAM,IAAI,SAAS,EAAE,CAAC;QACxB,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,OAAO,CACnB,MAAc,EACd,IAAY,EACZ,IAAc,EACd,SAAkB;QAElB,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,MAAM,GAAG,GAAG,GAAG,QAAQ,GAAG,IAAI,EAAE,CAAC;QACjC,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC;QAEhF,IAAI,CAAC;YACH,MAAM,OAAO,GAA2B;gBACtC,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;aACvC,CAAC;YACF,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACvB,OAAO,CAAC,cAAc,CAAC,GAAG,kBAAkB,CAAC;YAC/C,CAAC;YAED,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAC3B,MAAM;gBACN,OAAO;gBACP,IAAI,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;gBAC3D,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAC;YAEH,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC7C,MAAM,IAAI,SAAS,CAAC,6BAA6B,CAAC,CAAC;YACrD,CAAC;YAED,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBACvB,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;gBAClD,MAAM,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;gBACjE,MAAM,IAAI,cAAc,CAAC,EAAE,CAAC,CAAC;YAC/B,CAAC;YAED,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,IAAI,SAA6B,CAAC;gBAClC,IAAI,CAAC;oBACH,SAAS,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;gBAC/B,CAAC;gBAAC,MAAM,CAAC;oBACP,SAAS;gBACX,CAAC;gBACD,MAAM,IAAI,WAAW,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;YAC/C,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC9B,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;gBAAE,OAAO,EAAO,CAAC;YAC1C,mEAAmE;YACnE,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAM,CAAC;QACzC,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,KAAa,EAAE,IAAa,EAAE,WAAoB;QAC/D,MAAM,IAAI,GAA2B,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QAC9D,IAAI,IAAI,KAAK,SAAS;YAAE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACzC,IAAI,WAAW,KAAK,SAAS;YAAE,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC;QAE/D,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,YAAY,EAAE;YACpC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;YAC1B,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC;SAC5C,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,IAAI,SAA6B,CAAC;YAClC,IAAI,CAAC;gBACH,SAAS,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC/B,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;YACD,MAAM,IAAI,WAAW,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAC/C,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA4B,CAAC;QAC3D,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5B,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACvB,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,GAAG,CAAc,IAAY,EAAE,SAAkB;QACrD,OAAO,IAAI,CAAC,OAAO,CAAI,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;IAC5D,CAAC;IAED,KAAK,CAAC,IAAI,CAAc,IAAY,EAAE,IAAc,EAAE,SAAkB;QACtE,OAAO,IAAI,CAAC,OAAO,CAAI,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IACxD,CAAC;IAED,KAAK,CAAC,GAAG,CAAc,IAAY,EAAE,IAAc,EAAE,SAAkB;QACrE,OAAO,IAAI,CAAC,OAAO,CAAI,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IACvD,CAAC;IAED,KAAK,CAAC,KAAK,CAAc,IAAY,EAAE,IAAc,EAAE,SAAkB;QACvE,OAAO,IAAI,CAAC,OAAO,CAAI,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,MAAM,CAAc,IAAY,EAAE,SAAkB;QACxD,OAAO,IAAI,CAAC,OAAO,CAAI,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;IAC/D,CAAC;CACF"}
@@ -35,4 +35,4 @@ export declare function loadScanConfig(overrides?: Partial<ScanOptions>): ScanOp
35
35
  export declare function isScanEnabled(): boolean;
36
36
  export declare function loadManifest(): Manifest;
37
37
  export declare function saveManifest(manifest: Manifest): void;
38
- export declare function scanFiles(dir: string, opts: ScanOptions, ingestFn: (content: string, context: string) => Promise<unknown>): Promise<ScanResult>;
38
+ export declare function scanFiles(dir: string, opts: ScanOptions, ingestFn: (content: string, context: string) => Promise<unknown>, onProgress?: (current: number, total: number, filePath: string) => void): Promise<ScanResult>;
@@ -110,7 +110,7 @@ function hashFile(filePath) {
110
110
  return "sha256-" + createHash("sha256").update(content).digest("hex");
111
111
  }
112
112
  // --- Scanner ---
113
- export async function scanFiles(dir, opts, ingestFn) {
113
+ export async function scanFiles(dir, opts, ingestFn, onProgress) {
114
114
  const absDir = resolve(dir);
115
115
  const extSet = new Set(opts.extensions.map((e) => (e.startsWith(".") ? e : `.${e}`).toLowerCase()));
116
116
  // Discover files
@@ -120,7 +120,9 @@ export async function scanFiles(dir, opts, ingestFn) {
120
120
  const candidates = discovered.slice(0, opts.maxFiles);
121
121
  const manifest = opts.force ? { version: 1, files: {} } : loadManifest();
122
122
  const result = { scanned: 0, skipped: 0, errors: 0, files: [] };
123
- for (const file of candidates) {
123
+ for (let i = 0; i < candidates.length; i++) {
124
+ const file = candidates[i];
125
+ onProgress?.(i + 1, candidates.length, file.path);
124
126
  const hash = hashFile(file.path);
125
127
  const existing = manifest.files[file.path];
126
128
  // Skip if hash matches (already ingested)
@@ -1 +1 @@
1
- {"version":3,"file":"file-scanner.js","sourceRoot":"","sources":["../../src/lib/file-scanner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"file-scanner.js","sourceRoot":"","sources":["../../src/lib/file-scanner.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,13 @@
1
1
  /**
2
- * Platform-specific installers for Nex MCP server and Claude Code plugin.
2
+ * Platform-specific installers for Nex MCP server, hooks, plugins, agents, and workflows.
3
3
  *
4
- * - Generic MCP installer handles 9/12 platforms (same JSON mcpServers format)
5
- * - Claude Code installer handles hooks + slash commands
6
- * - Zed installer uses context_servers instead of mcpServers
7
- * - Continue.dev writes YAML config
4
+ * Installation hierarchy (per platform):
5
+ * 1. Hooks (event-driven scripts)
6
+ * 2. Custom tools/plugins (OpenCode plugin, OpenClaw plugin)
7
+ * 3. Custom agents/modes (VS Code agent, Kilo Code mode)
8
+ * 4. Workflows/slash commands (Windsurf workflows)
9
+ * 5. Rules (instruction files)
10
+ * 6. MCP (tool protocol)
8
11
  */
9
12
  import type { Platform } from "./platform-detect.js";
10
13
  export declare function installMcpServer(platform: Platform, apiKey: string): {
@@ -16,4 +19,58 @@ export declare function installClaudeCodePlugin(): {
16
19
  hooksAdded: string[];
17
20
  commandsCopied: string[];
18
21
  };
22
+ /**
23
+ * Install hook scripts for platforms that support event-driven hooks.
24
+ * Each platform has its own adapter scripts in dist/plugin/adapters/.
25
+ */
26
+ export declare function installHooks(platform: Platform): {
27
+ installed: boolean;
28
+ hooksAdded: string[];
29
+ };
30
+ /**
31
+ * Install OpenCode plugin template to .opencode/plugins/nex.ts.
32
+ */
33
+ export declare function installOpenCodePlugin(): {
34
+ installed: boolean;
35
+ pluginPath: string;
36
+ };
37
+ /**
38
+ * Install OpenClaw plugin via CLI.
39
+ */
40
+ export declare function installOpenClawPlugin(apiKey: string): {
41
+ installed: boolean;
42
+ message: string;
43
+ };
44
+ /**
45
+ * Install VS Code custom agent (.github/agents/nex.agent.md).
46
+ */
47
+ export declare function installVSCodeAgent(): {
48
+ installed: boolean;
49
+ agentPath: string;
50
+ };
51
+ /**
52
+ * Install Kilo Code custom mode (.kilocodemodes YAML).
53
+ */
54
+ export declare function installKiloCodeMode(): {
55
+ installed: boolean;
56
+ modePath: string;
57
+ };
58
+ /**
59
+ * Install Continue.dev context provider template.
60
+ */
61
+ export declare function installContinueProvider(): {
62
+ installed: boolean;
63
+ providerPath: string;
64
+ };
65
+ /**
66
+ * Install Windsurf workflow files (slash commands).
67
+ */
68
+ export declare function installWindsurfWorkflows(): {
69
+ installed: boolean;
70
+ workflowCount: number;
71
+ };
72
+ export declare function installRulesFile(platform: Platform): {
73
+ installed: boolean;
74
+ rulesPath: string;
75
+ };
19
76
  export declare function syncApiKeyToMcpConfig(apiKey: string): void;
@@ -1,15 +1,19 @@
1
1
  /**
2
- * Platform-specific installers for Nex MCP server and Claude Code plugin.
2
+ * Platform-specific installers for Nex MCP server, hooks, plugins, agents, and workflows.
3
3
  *
4
- * - Generic MCP installer handles 9/12 platforms (same JSON mcpServers format)
5
- * - Claude Code installer handles hooks + slash commands
6
- * - Zed installer uses context_servers instead of mcpServers
7
- * - Continue.dev writes YAML config
4
+ * Installation hierarchy (per platform):
5
+ * 1. Hooks (event-driven scripts)
6
+ * 2. Custom tools/plugins (OpenCode plugin, OpenClaw plugin)
7
+ * 3. Custom agents/modes (VS Code agent, Kilo Code mode)
8
+ * 4. Workflows/slash commands (Windsurf workflows)
9
+ * 5. Rules (instruction files)
10
+ * 6. MCP (tool protocol)
8
11
  */
9
12
  import { readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync, unlinkSync, copyFileSync } from "node:fs";
10
13
  import { join, dirname } from "node:path";
11
14
  import { homedir } from "node:os";
12
15
  import { fileURLToPath } from "node:url";
16
+ import { execFileSync } from "node:child_process";
13
17
  const __filename = fileURLToPath(import.meta.url);
14
18
  const __dirname = dirname(__filename);
15
19
  const MCP_SERVER_ENTRY = {
@@ -17,7 +21,7 @@ const MCP_SERVER_ENTRY = {
17
21
  args: ["-y", "@nex-crm/mcp-server"],
18
22
  env: {},
19
23
  };
20
- // --- Generic MCP Installer ---
24
+ // ── Shared helpers ──────────────────────────────────────────────────────
21
25
  function readJsonFile(path) {
22
26
  try {
23
27
  const raw = readFileSync(path, "utf-8");
@@ -31,7 +35,32 @@ function writeJsonFile(path, data) {
31
35
  mkdirSync(dirname(path), { recursive: true });
32
36
  writeFileSync(path, JSON.stringify(data, null, 2) + "\n", "utf-8");
33
37
  }
38
+ /**
39
+ * Resolve bundled plugin paths.
40
+ * From dist/lib/installers.js:
41
+ * __dirname = <pkg>/dist/lib/
42
+ * dist/plugin/ = __dirname/../plugin/
43
+ * plugin-commands/ = __dirname/../../plugin-commands/
44
+ * platform-plugins/ = __dirname/../../platform-plugins/
45
+ * platform-rules/ = __dirname/../../platform-rules/
46
+ */
47
+ function getPluginDistDir() {
48
+ return join(__dirname, "..", "plugin");
49
+ }
50
+ function getPluginCommandsDir() {
51
+ return join(__dirname, "..", "..", "plugin-commands");
52
+ }
53
+ function getPluginRulesDir() {
54
+ return join(__dirname, "..", "..", "platform-rules");
55
+ }
56
+ function getPlatformPluginsDir() {
57
+ return join(__dirname, "..", "..", "platform-plugins");
58
+ }
59
+ // ── 1. Generic MCP Installer ───────────────────────────────────────────
34
60
  export function installMcpServer(platform, apiKey) {
61
+ if (!platform.configPath) {
62
+ return { installed: false, configPath: "" };
63
+ }
35
64
  const entry = {
36
65
  ...MCP_SERVER_ENTRY,
37
66
  env: { NEX_API_KEY: apiKey },
@@ -63,8 +92,6 @@ function installZedMcp(configPath, entry) {
63
92
  return { installed: true, configPath };
64
93
  }
65
94
  function installContinueMcp(configPath, apiKey) {
66
- // Continue.dev can also accept JSON in a separate mcpServers config
67
- // Write a simple JSON file alongside the YAML
68
95
  const mcpPath = configPath.replace("config.yaml", "mcp.json");
69
96
  const config = readJsonFile(mcpPath);
70
97
  if (!config.mcpServers || typeof config.mcpServers !== "object") {
@@ -77,22 +104,6 @@ function installContinueMcp(configPath, apiKey) {
77
104
  writeJsonFile(mcpPath, config);
78
105
  return { installed: true, configPath: mcpPath };
79
106
  }
80
- /**
81
- * Resolve bundled plugin paths.
82
- * Plugin source is compiled into dist/plugin/ alongside the CLI.
83
- * Slash commands are at plugin-commands/ in the package root.
84
- *
85
- * From dist/lib/installers.js:
86
- * __dirname = <pkg>/dist/lib/
87
- * dist/plugin/ = __dirname/../plugin/
88
- * plugin-commands/ = __dirname/../../plugin-commands/
89
- */
90
- function getPluginDistDir() {
91
- return join(__dirname, "..", "plugin");
92
- }
93
- function getPluginCommandsDir() {
94
- return join(__dirname, "..", "..", "plugin-commands");
95
- }
96
107
  export function installClaudeCodePlugin() {
97
108
  const home = homedir();
98
109
  const claudeDir = join(home, ".claude");
@@ -172,29 +183,357 @@ export function installClaudeCodePlugin() {
172
183
  continue;
173
184
  const target = join(commandsDir, entry);
174
185
  const source = join(sourceCommandsDir, entry);
175
- // Remove stale symlink or existing file, then copy fresh
176
186
  try {
177
187
  unlinkSync(target);
178
188
  }
179
- catch {
180
- // File didn't exist — fine
181
- }
189
+ catch { /* File didn't exist */ }
182
190
  try {
183
191
  copyFileSync(source, target);
184
192
  commandsCopied.push(entry);
185
193
  }
186
- catch {
187
- // Copy failed — non-critical
188
- }
194
+ catch { /* Copy failed — non-critical */ }
189
195
  }
190
196
  }
197
+ catch { /* Commands dir read failed — non-critical */ }
198
+ }
199
+ return { installed: true, hooksAdded, commandsCopied };
200
+ }
201
+ // ── 3. Hook Installers (Cursor, Windsurf, Cline) ──────────────────────
202
+ /**
203
+ * Install hook scripts for platforms that support event-driven hooks.
204
+ * Each platform has its own adapter scripts in dist/plugin/adapters/.
205
+ */
206
+ export function installHooks(platform) {
207
+ // Claude Code handled separately via installClaudeCodePlugin
208
+ if (platform.id === "claude-code") {
209
+ return { installed: false, hooksAdded: [] };
210
+ }
211
+ const adapterDir = join(getPluginDistDir(), "adapters");
212
+ if (!existsSync(adapterDir)) {
213
+ return { installed: false, hooksAdded: [] };
214
+ }
215
+ if (platform.id === "cursor")
216
+ return installCursorHooks(adapterDir, platform);
217
+ if (platform.id === "windsurf")
218
+ return installWindsurfHooks(adapterDir, platform);
219
+ if (platform.id === "cline")
220
+ return installClineHooks(adapterDir, platform);
221
+ return { installed: false, hooksAdded: [] };
222
+ }
223
+ function installCursorHooks(adapterDir, platform) {
224
+ const hookConfigPath = platform.hookConfigPath;
225
+ if (!hookConfigPath)
226
+ return { installed: false, hooksAdded: [] };
227
+ const config = readJsonFile(hookConfigPath);
228
+ if (!config.hooks || typeof config.hooks !== "object") {
229
+ config.hooks = {};
230
+ }
231
+ const hooks = config.hooks;
232
+ const hooksAdded = [];
233
+ const cursorHookDefs = [
234
+ { event: "sessionStart", script: "cursor-session-start.js", timeout: 120000 },
235
+ { event: "userPromptSubmit", script: "cursor-recall.js", timeout: 10000 },
236
+ { event: "stop", script: "cursor-stop.js", timeout: 10000 },
237
+ ];
238
+ for (const def of cursorHookDefs) {
239
+ const scriptPath = join(adapterDir, def.script);
240
+ if (!existsSync(scriptPath))
241
+ continue;
242
+ if (!hooks[def.event])
243
+ hooks[def.event] = [];
244
+ // Remove existing nex hooks
245
+ hooks[def.event] = hooks[def.event].filter((h) => !String(h.command ?? "").includes("nex"));
246
+ hooks[def.event].push({
247
+ type: "command",
248
+ command: `node ${scriptPath}`,
249
+ timeout: def.timeout,
250
+ });
251
+ hooksAdded.push(def.event);
252
+ }
253
+ writeJsonFile(hookConfigPath, config);
254
+ return { installed: true, hooksAdded };
255
+ }
256
+ function installWindsurfHooks(adapterDir, platform) {
257
+ const hookConfigPath = platform.hookConfigPath;
258
+ if (!hookConfigPath)
259
+ return { installed: false, hooksAdded: [] };
260
+ const config = readJsonFile(hookConfigPath);
261
+ if (!config.hooks || typeof config.hooks !== "object") {
262
+ config.hooks = {};
263
+ }
264
+ const hooks = config.hooks;
265
+ const hooksAdded = [];
266
+ const windsurfHookDefs = [
267
+ { event: "pre_user_prompt", script: "windsurf-recall.js", timeout: 10000 },
268
+ { event: "post_cascade_response", script: "windsurf-capture.js", timeout: 10000 },
269
+ ];
270
+ for (const def of windsurfHookDefs) {
271
+ const scriptPath = join(adapterDir, def.script);
272
+ if (!existsSync(scriptPath))
273
+ continue;
274
+ if (!hooks[def.event])
275
+ hooks[def.event] = [];
276
+ hooks[def.event] = hooks[def.event].filter((h) => !String(h.command ?? "").includes("nex"));
277
+ hooks[def.event].push({
278
+ type: "command",
279
+ command: `node ${scriptPath}`,
280
+ timeout: def.timeout,
281
+ });
282
+ hooksAdded.push(def.event);
283
+ }
284
+ writeJsonFile(hookConfigPath, config);
285
+ return { installed: true, hooksAdded };
286
+ }
287
+ function installClineHooks(adapterDir, platform) {
288
+ // Cline uses executable files in .clinerules/hooks/
289
+ const hookDir = platform.hookConfigPath;
290
+ if (!hookDir)
291
+ return { installed: false, hooksAdded: [] };
292
+ mkdirSync(hookDir, { recursive: true });
293
+ const hooksAdded = [];
294
+ const clineHookDefs = [
295
+ { event: "UserPromptSubmit", script: "cline-recall.js" },
296
+ { event: "TaskStart", script: "cline-task-start.js" },
297
+ { event: "TaskComplete", script: "cline-capture.js" },
298
+ ];
299
+ for (const def of clineHookDefs) {
300
+ const scriptPath = join(adapterDir, def.script);
301
+ if (!existsSync(scriptPath))
302
+ continue;
303
+ // Write a shell wrapper that invokes node with the adapter script
304
+ const wrapperPath = join(hookDir, `nex-${def.event.toLowerCase()}`);
305
+ const wrapper = `#!/usr/bin/env sh\nexec node "${scriptPath}" "$@"\n`;
306
+ writeFileSync(wrapperPath, wrapper, { mode: 0o755 });
307
+ hooksAdded.push(def.event);
308
+ }
309
+ return { installed: true, hooksAdded };
310
+ }
311
+ // ── 4. Custom Tool/Plugin Installers ───────────────────────────────────
312
+ /**
313
+ * Install OpenCode plugin template to .opencode/plugins/nex.ts.
314
+ */
315
+ export function installOpenCodePlugin() {
316
+ const templatePath = join(getPlatformPluginsDir(), "opencode-plugin.ts");
317
+ if (!existsSync(templatePath)) {
318
+ return { installed: false, pluginPath: "" };
319
+ }
320
+ const targetDir = join(process.cwd(), ".opencode", "plugins");
321
+ const targetPath = join(targetDir, "nex.ts");
322
+ mkdirSync(targetDir, { recursive: true });
323
+ copyFileSync(templatePath, targetPath);
324
+ return { installed: true, pluginPath: targetPath };
325
+ }
326
+ /**
327
+ * Install OpenClaw plugin via CLI.
328
+ */
329
+ export function installOpenClawPlugin(apiKey) {
330
+ // Check if openclaw CLI is available
331
+ let hasOpenClaw = false;
332
+ try {
333
+ execFileSync("which", ["openclaw"], { stdio: "ignore" });
334
+ hasOpenClaw = true;
335
+ }
336
+ catch { /* not installed */ }
337
+ if (!hasOpenClaw) {
338
+ return {
339
+ installed: false,
340
+ message: "Install OpenClaw to enable: https://docs.openclaw.ai/install",
341
+ };
342
+ }
343
+ // Check if plugin already installed
344
+ const configPath = join(homedir(), ".openclaw", "openclaw.json");
345
+ const config = readJsonFile(configPath);
346
+ const plugins = (config.plugins ?? {});
347
+ const entries = (plugins.entries ?? {});
348
+ if (!entries.nex) {
349
+ // Install the plugin
350
+ try {
351
+ execFileSync("openclaw", ["plugins", "install", "@nex-ai/openclaw-plugin"], {
352
+ stdio: "ignore",
353
+ timeout: 30_000,
354
+ });
355
+ }
191
356
  catch {
192
- // Commands dir read failed non-critical
357
+ return { installed: false, message: "Failed to install OpenClaw plugin" };
193
358
  }
194
359
  }
195
- return { installed: true, hooksAdded, commandsCopied };
360
+ // Configure API key
361
+ const freshConfig = readJsonFile(configPath);
362
+ const freshPlugins = (freshConfig.plugins ?? {});
363
+ const freshEntries = (freshPlugins.entries ?? {});
364
+ if (!freshEntries.nex)
365
+ freshEntries.nex = {};
366
+ if (!freshEntries.nex.config)
367
+ freshEntries.nex.config = {};
368
+ freshEntries.nex.config.apiKey = apiKey;
369
+ freshEntries.nex.enabled = true;
370
+ freshPlugins.entries = freshEntries;
371
+ freshConfig.plugins = freshPlugins;
372
+ writeJsonFile(configPath, freshConfig);
373
+ return { installed: true, message: "OpenClaw plugin installed and configured" };
374
+ }
375
+ // ── 5. Custom Agent/Mode Installers ────────────────────────────────────
376
+ /**
377
+ * Install VS Code custom agent (.github/agents/nex.agent.md).
378
+ */
379
+ export function installVSCodeAgent() {
380
+ const templatePath = join(getPlatformPluginsDir(), "vscode-agent.md");
381
+ if (!existsSync(templatePath)) {
382
+ return { installed: false, agentPath: "" };
383
+ }
384
+ const targetDir = join(process.cwd(), ".github", "agents");
385
+ const targetPath = join(targetDir, "nex.agent.md");
386
+ mkdirSync(targetDir, { recursive: true });
387
+ copyFileSync(templatePath, targetPath);
388
+ return { installed: true, agentPath: targetPath };
389
+ }
390
+ /**
391
+ * Install Kilo Code custom mode (.kilocodemodes YAML).
392
+ */
393
+ export function installKiloCodeMode() {
394
+ const templatePath = join(getPlatformPluginsDir(), "kilocode-modes.yaml");
395
+ if (!existsSync(templatePath)) {
396
+ return { installed: false, modePath: "" };
397
+ }
398
+ const targetPath = join(process.cwd(), ".kilocodemodes");
399
+ // Read existing modes file if present
400
+ let existing = "";
401
+ try {
402
+ existing = readFileSync(targetPath, "utf-8");
403
+ }
404
+ catch { /* doesn't exist */ }
405
+ // If already has nex-crm mode, skip
406
+ if (existing.includes("nex-crm")) {
407
+ return { installed: true, modePath: targetPath };
408
+ }
409
+ const template = readFileSync(templatePath, "utf-8");
410
+ if (existing) {
411
+ // Append to existing customModes
412
+ // Remove the "customModes:" header from template since it already exists
413
+ const modesContent = template.replace(/^customModes:\s*\n/, "");
414
+ writeFileSync(targetPath, existing.trimEnd() + "\n" + modesContent, "utf-8");
415
+ }
416
+ else {
417
+ writeFileSync(targetPath, template, "utf-8");
418
+ }
419
+ return { installed: true, modePath: targetPath };
420
+ }
421
+ /**
422
+ * Install Continue.dev context provider template.
423
+ */
424
+ export function installContinueProvider() {
425
+ const templatePath = join(getPlatformPluginsDir(), "continue-provider.ts");
426
+ if (!existsSync(templatePath)) {
427
+ return { installed: false, providerPath: "" };
428
+ }
429
+ const continueBase = existsSync(join(process.cwd(), ".continue"))
430
+ ? join(process.cwd(), ".continue")
431
+ : join(homedir(), ".continue");
432
+ const targetDir = join(continueBase, ".plugins");
433
+ const targetPath = join(targetDir, "nex-provider.ts");
434
+ mkdirSync(targetDir, { recursive: true });
435
+ copyFileSync(templatePath, targetPath);
436
+ return { installed: true, providerPath: targetPath };
437
+ }
438
+ // ── 6. Workflow Installers ─────────────────────────────────────────────
439
+ /**
440
+ * Install Windsurf workflow files (slash commands).
441
+ */
442
+ export function installWindsurfWorkflows() {
443
+ const sourceDir = join(getPlatformPluginsDir(), "windsurf-workflows");
444
+ if (!existsSync(sourceDir)) {
445
+ return { installed: false, workflowCount: 0 };
446
+ }
447
+ const targetDir = join(process.cwd(), ".windsurf", "workflows");
448
+ mkdirSync(targetDir, { recursive: true });
449
+ let count = 0;
450
+ try {
451
+ const entries = readdirSync(sourceDir);
452
+ for (const entry of entries) {
453
+ if (!entry.endsWith(".md"))
454
+ continue;
455
+ copyFileSync(join(sourceDir, entry), join(targetDir, entry));
456
+ count++;
457
+ }
458
+ }
459
+ catch { /* non-critical */ }
460
+ return { installed: count > 0, workflowCount: count };
461
+ }
462
+ // ── 7. Rules File Installer ────────────────────────────────────────────
463
+ const NEX_RULES_MARKER_START = "# --- Nex Context & Memory ---";
464
+ const NEX_RULES_MARKER_END = "# --- End Nex ---";
465
+ /**
466
+ * Map platform ID to its rules template filename.
467
+ */
468
+ const RULES_TEMPLATE_MAP = {
469
+ cursor: "cursor-rules.md",
470
+ vscode: "vscode-instructions.md",
471
+ windsurf: "windsurf-rules.md",
472
+ cline: "cline-rules.md",
473
+ continue: "continue-rules.md",
474
+ zed: "zed-rules.md",
475
+ kilocode: "kilocode-rules.md",
476
+ opencode: "opencode-agents.md",
477
+ aider: "aider-conventions.md",
478
+ };
479
+ /**
480
+ * Platforms where rules are APPENDED to an existing file (with markers)
481
+ * rather than written as a standalone file.
482
+ */
483
+ const APPEND_PLATFORMS = new Set(["zed", "opencode", "aider"]);
484
+ export function installRulesFile(platform) {
485
+ const rulesPath = platform.rulesPath;
486
+ if (!rulesPath) {
487
+ return { installed: false, rulesPath: "" };
488
+ }
489
+ const templateName = RULES_TEMPLATE_MAP[platform.id];
490
+ if (!templateName) {
491
+ return { installed: false, rulesPath: "" };
492
+ }
493
+ const templatePath = join(getPluginRulesDir(), templateName);
494
+ if (!existsSync(templatePath)) {
495
+ return { installed: false, rulesPath: "" };
496
+ }
497
+ const template = readFileSync(templatePath, "utf-8");
498
+ if (APPEND_PLATFORMS.has(platform.id)) {
499
+ // Append mode: add/replace section in existing file
500
+ let existing = "";
501
+ try {
502
+ existing = readFileSync(rulesPath, "utf-8");
503
+ }
504
+ catch {
505
+ // File doesn't exist — will create
506
+ }
507
+ // Check if nex section already exists
508
+ const startIdx = existing.indexOf(NEX_RULES_MARKER_START);
509
+ const endIdx = existing.indexOf(NEX_RULES_MARKER_END);
510
+ if (startIdx !== -1 && endIdx !== -1) {
511
+ // Replace existing section
512
+ const before = existing.slice(0, startIdx);
513
+ const after = existing.slice(endIdx + NEX_RULES_MARKER_END.length);
514
+ const updated = before + template.trim() + after;
515
+ mkdirSync(dirname(rulesPath), { recursive: true });
516
+ writeFileSync(rulesPath, updated, "utf-8");
517
+ }
518
+ else if (existing.includes("nex_ask") || existing.includes("Nex Context")) {
519
+ // Already has nex content without markers — skip to avoid duplicates
520
+ return { installed: true, rulesPath };
521
+ }
522
+ else {
523
+ // Append to end
524
+ const separator = existing && !existing.endsWith("\n\n") ? "\n\n" : "";
525
+ mkdirSync(dirname(rulesPath), { recursive: true });
526
+ writeFileSync(rulesPath, existing + separator + template.trim() + "\n", "utf-8");
527
+ }
528
+ }
529
+ else {
530
+ // Standalone mode: write the file directly
531
+ mkdirSync(dirname(rulesPath), { recursive: true });
532
+ writeFileSync(rulesPath, template, "utf-8");
533
+ }
534
+ return { installed: true, rulesPath };
196
535
  }
197
- // --- Sync API key to ~/.nex-mcp.json ---
536
+ // ── 8. Sync API key to ~/.nex-mcp.json ─────────────────────────────────
198
537
  export function syncApiKeyToMcpConfig(apiKey) {
199
538
  const mcpConfigPath = join(homedir(), ".nex-mcp.json");
200
539
  const config = readJsonFile(mcpConfigPath);