@thanhthi2895/luna-ai 2.16.3 → 2.16.4

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.
package/README.md CHANGED
@@ -4,13 +4,29 @@ Agentic Workflow Framework for the **Vibe Coding** era, with an integrated **Dyn
4
4
 
5
5
  ## 🚀 Quick Start
6
6
 
7
+ ### Global Installation (Recommended)
8
+ Installs the framework globally, available for all your projects.
9
+
10
+ ```bash
11
+ # 1. Install the framework globally into ~/.claude
12
+ npx @thanhthi2895/luna-ai -g
13
+
14
+ # 2. Initialize global metadata (first time only)
15
+ luna init -g
16
+
17
+ # 3. Open Claude Code in any project and start Vibe Coding!
18
+ claude
19
+ ```
20
+
21
+ ### Local Project Installation
22
+ Installs the framework directly into the current project's directory.
23
+
7
24
  ```bash
8
- # 1. Install the framework
9
- npx @thanhthi2895/luna-ai # local project
10
- npx @thanhthi2895/luna-ai -g # global
25
+ # 1. Install the framework locally
26
+ npx @thanhthi2895/luna-ai
11
27
 
12
- # 2. Initialize project data
13
- luna
28
+ # 2. Initialize project structure and memory
29
+ luna init
14
30
 
15
31
  # 3. Open Claude Code and start Vibe Coding!
16
32
  claude
@@ -21,7 +37,7 @@ claude
21
37
  ## 🎯 Goal: Vibe Coding - Full Auto
22
38
  Users simply provide an idea. The system automatically coordinates a team of specialized Agents to assess risk, create multi-level plans, execute with TDD standards, and deliver the product at optimal speed.
23
39
 
24
- ## 🚀 Breakthrough Features (V2.5)
40
+ ## 🚀 Breakthrough Features (V2.16)
25
41
  - **Layered Cache**: Multi-level memory cache (L1/L2/L3) for large projects (20+ modules, 200+ files).
26
42
  - **Semantic Code Graph**: Uses `lu:gkg` (GitLab Knowledge Graph) to see all project connections and run impact analysis.
27
43
  - **Context Distilling**: Automatically filters out code noise, helping AI think faster and save tokens.
@@ -439,6 +439,27 @@ async function copyClaude_global(rootDir, claudeHome) {
439
439
  throw new Error(`Canonical Claude directory missing: ${srcClaude}`);
440
440
  }
441
441
  const destClaude = claudeHome;
442
+
443
+ // PREVENT fs-extra "Source and destination must not be the same" error
444
+ // If destClaude contains symlinks pointing to srcClaude elements, fs.copy will crash.
445
+ // We remove those specific symlinks before copying.
446
+ try {
447
+ const srcItems = await fs.readdir(srcClaude);
448
+ for (const item of srcItems) {
449
+ const destPath = path.join(destClaude, item);
450
+ try {
451
+ const tgtStat = await fs.lstat(destPath);
452
+ if (tgtStat.isSymbolicLink()) {
453
+ await fs.remove(destPath);
454
+ }
455
+ } catch (e) {
456
+ // Ignore if doesn't exist
457
+ }
458
+ }
459
+ } catch (err) {
460
+ console.error(` Warning: Could not run symlink cleanup in ${destClaude}:`, err.message);
461
+ }
462
+
442
463
  const skipPaths = [
443
464
  path.join(srcClaude, 'ai-cache'),
444
465
  path.join(srcClaude, 'hook-state'), // Runtime data, don't copy
@@ -690,21 +711,27 @@ export async function installGlobal(rootDir) {
690
711
  // Copy statusline.cjs and its lib/ dependency from canonical .claude/ to ~/.claude/
691
712
  const canonicalClaude = getCanonicalClaudeDir(rootDir);
692
713
  const statuslineSrc = path.join(canonicalClaude, 'statusline.cjs');
714
+ const statuslineDest = path.join(claudeHome, 'statusline.cjs');
715
+ const libDest = path.join(claudeHome, 'lib');
693
716
  if (await fs.pathExists(statuslineSrc)) {
694
- await fs.copy(statuslineSrc, path.join(claudeHome, 'statusline.cjs'), { overwrite: true });
717
+ try { await fs.remove(statuslineDest); } catch(e){}
718
+ await fs.copy(statuslineSrc, statuslineDest, { overwrite: true });
695
719
  // statusline.cjs requires ./lib/ — copy lib/ to ~/.claude/lib/
696
720
  const libSrc = path.join(canonicalClaude, 'lib');
697
721
  if (await fs.pathExists(libSrc)) {
698
- await fs.copy(libSrc, path.join(claudeHome, 'lib'), { overwrite: true });
722
+ try { await fs.remove(libDest); } catch(e){}
723
+ await fs.copy(libSrc, libDest, { overwrite: true });
699
724
  }
700
725
  console.log(` Copied statusline.cjs + lib/ → ~/.claude/`);
701
726
  }
702
727
 
703
728
  // Copy canonical .luna.json to ~/.claude/.luna.json
704
729
  const lunaJsonSrc = path.join(rootDir, 'agentic', 'claude', '.luna.json');
730
+ const lunaJsonDest = path.join(claudeHome, '.luna.json');
705
731
 
706
732
  if (await fs.pathExists(lunaJsonSrc)) {
707
- await fs.copy(lunaJsonSrc, path.join(claudeHome, '.luna.json'), { overwrite: true });
733
+ try { await fs.remove(lunaJsonDest); } catch(e){}
734
+ await fs.copy(lunaJsonSrc, lunaJsonDest, { overwrite: true });
708
735
  console.log(` Copied .luna.json → ~/.claude/.luna.json`);
709
736
  } else {
710
737
  console.log(' Warning: canonical agentic/claude/.luna.json missing. Skip publishing ~/.claude/.luna.json');
@@ -714,12 +741,16 @@ export async function installGlobal(rootDir) {
714
741
  await ensureLunaCli(claudeHome);
715
742
 
716
743
  // Copy CLAUDE.md into ~/.claude/ (Claude Code reads global instructions from here)
717
- await fs.copy(getCanonicalClaudeMd(rootDir), path.join(claudeHome, 'CLAUDE.md'), { overwrite: true });
744
+ const claudeMdDest = path.join(claudeHome, 'CLAUDE.md');
745
+ try { await fs.remove(claudeMdDest); } catch(e){}
746
+ await fs.copy(getCanonicalClaudeMd(rootDir), claudeMdDest, { overwrite: true });
718
747
  await ensureGeminiSymlink(claudeHome);
719
748
  }
720
749
 
721
750
  // Copy CLAUDE.md + GEMINI.md symlink into ~/.luna-ai/ (as reference)
722
- await fs.copy(getCanonicalClaudeMd(rootDir), path.join(lunaHome, 'CLAUDE.md'), { overwrite: true });
751
+ const lunaAiClaudeMdDest = path.join(lunaHome, 'CLAUDE.md');
752
+ try { await fs.remove(lunaAiClaudeMdDest); } catch(e){}
753
+ await fs.copy(getCanonicalClaudeMd(rootDir), lunaAiClaudeMdDest, { overwrite: true });
723
754
  await ensureGeminiSymlink(lunaHome);
724
755
 
725
756
  // Create plans/archive directory at ~/.luna-ai/
@@ -827,6 +858,7 @@ async function writeGlobalSettingsJson(rootDir, claudeHome) {
827
858
 
828
859
  if (!await fs.pathExists(srcPath)) return;
829
860
 
861
+ try { await fs.remove(destPath); } catch (e) {}
830
862
  await fs.copy(srcPath, destPath, { overwrite: true });
831
863
  console.log(` Copied .agents/settings.json → ~/.claude/settings.json`);
832
864
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thanhthi2895/luna-ai",
3
- "version": "2.16.3",
3
+ "version": "2.16.4",
4
4
  "description": "Agentic Workflow Framework cho Claude - Tự động hóa quy trình lập trình Vibe Coding",
5
5
  "type": "module",
6
6
  "private": false,