@neikyun/ciel 5.2.9 → 5.2.10

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 (2) hide show
  1. package/bin/ciel.js +88 -70
  2. package/package.json +1 -1
package/bin/ciel.js CHANGED
@@ -1,23 +1,23 @@
1
1
  #!/usr/bin/env node
2
2
  // Ciel CLI — bootstrap entry point
3
- // Vérifie si l'initialisation est nécessaire, sinon lance la CLI normalement.
4
- // Solution de secours quand le postinstall npm ne s'exécute pas.
3
+ // Vérifie si l'initialisation est nécessaire et détecte les nouvelles plateformes.
5
4
 
6
5
  const { existsSync, mkdirSync, writeFileSync, readFileSync, copyFileSync, readdirSync, chmodSync, unlinkSync } = require("fs");
7
- const { join, dirname } = require("path");
6
+ const { join } = require("path");
8
7
  const { execSync } = require("child_process");
9
8
 
10
9
  const PKG_DIR = join(__dirname, "..");
11
10
  const PKG = JSON.parse(readFileSync(join(PKG_DIR, "package.json"), "utf-8"));
12
11
  const CIEL_VERSION = PKG.version || "0.0.0";
13
12
  const ASSETS = join(PKG_DIR, "assets");
14
-
15
- // Vérifier si une (ré)initialisation est nécessaire
16
13
  const targetDir = process.env.INIT_CWD || process.cwd();
17
14
  const memPath = join(targetDir, ".ciel", "memory.json");
18
- const storedVersion = (() => { try { return JSON.parse(readFileSync(memPath, "utf-8")).cielVersion; } catch { return null; } })();
19
- const needsInit = !existsSync(memPath) || storedVersion !== CIEL_VERSION;
20
15
 
16
+ const c = (code, s) => process.stderr.isTTY ? `\x1b[${code}m${s}\x1b[0m` : s;
17
+ const green = (s) => c(32, s);
18
+ const cyan = (s) => c(36, s);
19
+
20
+ // ---- Helpers ----
21
21
  function copyDir(src, dest) {
22
22
  if (!existsSync(src)) return 0;
23
23
  let count = 0;
@@ -30,7 +30,7 @@ function copyDir(src, dest) {
30
30
  return count;
31
31
  }
32
32
 
33
- function patchConfig(targetDir, assets) {
33
+ function patchOpencodeJson(targetDir) {
34
34
  const cfgPath = join(targetDir, "opencode.json");
35
35
  if (!existsSync(cfgPath)) return false;
36
36
  try {
@@ -45,84 +45,102 @@ function patchConfig(targetDir, assets) {
45
45
  } catch { return false; }
46
46
  }
47
47
 
48
- function runInit(targetDir, assets) {
48
+ // ---- Détection des plateformes ----
49
+ function detectPlatforms() {
50
+ const platforms = [];
51
+ const hasOC = existsSync(join(targetDir, "opencode.json")) || existsSync(join(targetDir, ".opencode"));
52
+ const hasClaude = existsSync(join(targetDir, ".claude/settings.json")) || existsSync(join(targetDir, ".claude"));
53
+
54
+ // Détection CLI
55
+ const hasOC_CLI = (() => { try { const r = execSync("opencode --version 2>&1", { stdio: "pipe", timeout: 5000 }); return r.toString().length > 0; } catch { return false; } })();
56
+ const hasClaude_CLI = (() => { try { const r = execSync("claude --version 2>&1", { stdio: "pipe", timeout: 5000 }); return r.toString().length > 0; } catch { return false; } })();
57
+
58
+ if (hasOC || hasOC_CLI) platforms.push("OpenCode");
59
+ if (hasClaude || hasClaude_CLI) platforms.push("Claude Code");
60
+ return platforms;
61
+ }
62
+
63
+ // ---- Installer une plateforme ----
64
+ function installOpenCode() {
49
65
  let total = 0;
66
+ // Nettoyer ancien plugin curl
67
+ const old = join(targetDir, ".opencode/plugins/ciel.ts");
68
+ if (existsSync(old)) { try { unlinkSync(old); } catch {} }
69
+ total += copyDir(join(ASSETS, "platforms/opencode/.opencode/agents"), join(targetDir, ".opencode/agents"));
70
+ total += copyDir(join(ASSETS, "platforms/opencode/.opencode/commands"), join(targetDir, ".opencode/commands"));
71
+ if (existsSync(join(ASSETS, "platforms/opencode/AGENTS.md"))) {
72
+ copyFileSync(join(ASSETS, "platforms/opencode/AGENTS.md"), join(targetDir, "AGENTS.md"));
73
+ total++;
74
+ }
75
+ if (patchOpencodeJson(targetDir)) total++;
76
+ return total;
77
+ }
78
+
79
+ function installClaude() {
80
+ let total = 0;
81
+ total += copyDir(join(ASSETS, ".claude/agents"), join(targetDir, ".claude/agents"));
82
+ total += copyDir(join(ASSETS, ".claude/hooks"), join(targetDir, ".claude/hooks"));
83
+ total += copyDir(join(ASSETS, "commands"), join(targetDir, ".claude/commands"));
84
+ if (existsSync(join(ASSETS, ".claude/settings.json"))) {
85
+ copyFileSync(join(ASSETS, ".claude/settings.json"), join(targetDir, ".claude/settings.json"));
86
+ }
87
+ if (existsSync(join(ASSETS, "CLAUDE.md"))) {
88
+ copyFileSync(join(ASSETS, "CLAUDE.md"), join(targetDir, "CLAUDE.md"));
89
+ }
90
+ return total;
91
+ }
50
92
 
51
- // .ciel/ state
93
+ function ensureCielState() {
52
94
  mkdirSync(join(targetDir, ".ciel"), { recursive: true });
53
95
  if (!existsSync(join(targetDir, ".ciel/map.json")))
54
96
  writeFileSync(join(targetDir, ".ciel/map.json"), JSON.stringify({ modules: [], lastUpdated: "" }), "utf-8");
55
97
  if (!existsSync(join(targetDir, ".ciel/parking.md")))
56
98
  writeFileSync(join(targetDir, ".ciel/parking.md"), "# Ciel Parking Lot\n\n", "utf-8");
99
+ writeFileSync(memPath, JSON.stringify({ cielVersion: CIEL_VERSION, lastUpdated: new Date().toISOString() }, null, 2), "utf-8");
100
+ }
57
101
 
58
- // OpenCode files
59
- if (existsSync(join(targetDir, "opencode.json")) || existsSync(join(targetDir, ".opencode"))) {
60
- // Clean old curl plugin
61
- const old = join(targetDir, ".opencode/plugins/ciel.ts");
62
- if (existsSync(old)) { try { unlinkSync(old); } catch {} }
63
- // Copy agents
64
- total += copyDir(join(assets, "platforms/opencode/.opencode/agents"), join(targetDir, ".opencode/agents"));
65
- // Copy commands
66
- total += copyDir(join(assets, "platforms/opencode/.opencode/commands"), join(targetDir, ".opencode/commands"));
67
- // Copy AGENTS.md
68
- if (existsSync(join(assets, "platforms/opencode/AGENTS.md"))) {
69
- copyFileSync(join(assets, "platforms/opencode/AGENTS.md"), join(targetDir, "AGENTS.md"));
70
- total++;
71
- }
72
- if (patchConfig(targetDir, assets)) total++;
73
- console.error(` ${green("✓")} OpenCode: ${total} fichiers`);
74
- }
102
+ // ===== MAIN BOOT =====
103
+ const args = process.argv.slice(2);
104
+ const isHelp = args.includes("--help") || args.includes("-h");
105
+ const isVersion = args.includes("--version") || args.includes("-v");
75
106
 
76
- // Claude Code files
77
- if (existsSync(join(targetDir, ".claude/settings.json")) || existsSync(join(targetDir, ".claude"))) {
78
- total += copyDir(join(assets, ".claude/agents"), join(targetDir, ".claude/agents"));
79
- total += copyDir(join(assets, ".claude/hooks"), join(targetDir, ".claude/hooks"));
80
- total += copyDir(join(assets, "commands"), join(targetDir, ".claude/commands"));
81
- if (existsSync(join(assets, ".claude/settings.json"))) {
82
- copyFileSync(join(assets, ".claude/settings.json"), join(targetDir, ".claude/settings.json"));
107
+ if (!isHelp && !isVersion && ASSETS && existsSync(join(ASSETS, "platforms/opencode/.opencode/agents/ciel.md"))) {
108
+ try {
109
+ const storedVersion = (() => { try { return JSON.parse(readFileSync(memPath, "utf-8")).cielVersion; } catch { return null; } })();
110
+ const needsInit = !storedVersion || storedVersion !== CIEL_VERSION;
111
+
112
+ // Toujours détecter les plateformes
113
+ const platforms = detectPlatforms();
114
+
115
+ // Créer les configs si CLI détectée mais pas de fichiers
116
+ if (platforms.includes("OpenCode") && !existsSync(join(targetDir, "opencode.json"))) {
117
+ writeFileSync(join(targetDir, "opencode.json"), JSON.stringify({ $schema: "https://opencode.ai/config.json", plugin: ["@neikyun/ciel"] }, null, 2) + "\n", "utf-8");
83
118
  }
84
- if (existsSync(join(assets, "CLAUDE.md"))) {
85
- copyFileSync(join(assets, "CLAUDE.md"), join(targetDir, "CLAUDE.md"));
119
+ if (platforms.includes("Claude Code") && !existsSync(join(targetDir, ".claude/settings.json"))) {
120
+ mkdirSync(join(targetDir, ".claude"), { recursive: true });
121
+ writeFileSync(join(targetDir, ".claude/settings.json"), "{}\n", "utf-8");
86
122
  }
87
- console.error(` ${green("✓")} Claude Code: ${total} fichiers`);
88
- }
89
123
 
90
- // Save version
91
- writeFileSync(memPath, JSON.stringify({ cielVersion: CIEL_VERSION, lastUpdated: new Date().toISOString() }, null, 2), "utf-8");
92
- return total;
93
- }
124
+ // Vérifier ce qui manque pour chaque plateforme détectée
125
+ const opencodeFilesExist = existsSync(join(targetDir, ".opencode/agents/ciel.md"));
126
+ const claudeFilesExist = existsSync(join(targetDir, ".claude/hooks/check-test-first.sh"));
94
127
 
95
- const c = (code, s) => process.stderr.isTTY ? `\x1b[${code}m${s}\x1b[0m` : s;
96
- const green = (s) => c(32, s);
97
- const cyan = (s) => c(36, s);
128
+ if (needsInit || (platforms.includes("OpenCode") && !opencodeFilesExist) || (platforms.includes("Claude Code") && !claudeFilesExist)) {
129
+ let n = 0;
130
+ console.error(`\n ⚡ Ciel v${CIEL_VERSION} Configuration...`);
131
+ ensureCielState();
98
132
 
99
- if (needsInit) {
100
- const args = process.argv.slice(2);
101
- if (!args.includes("--help") && !args.includes("-h") && !args.includes("--version") && !args.includes("-v")) {
102
- try {
103
- const hasOC = existsSync(join(targetDir, "opencode.json")) || existsSync(join(targetDir, ".opencode"));
104
- const hasClaude = existsSync(join(targetDir, ".claude/settings.json")) || existsSync(join(targetDir, ".claude"));
105
- const hasOC_CLI = (() => { try { return execSync("opencode --version 2>&1", { stdio: "pipe", timeout: 3000 }).toString().length > 0; } catch { return false; } })();
106
- const hasClaude_CLI = (() => { try { return execSync("claude --version 2>&1", { stdio: "pipe", timeout: 3000 }).toString().length > 0; } catch { return false; } })();
107
-
108
- // Créer les configs si CLI détectée mais pas de fichier
109
- if (hasOC_CLI && !hasOC) {
110
- writeFileSync(join(targetDir, "opencode.json"), JSON.stringify({ $schema: "https://opencode.ai/config.json", plugin: ["@neikyun/ciel"] }, null, 2) + "\n", "utf-8");
133
+ if (platforms.includes("OpenCode") && (!opencodeFilesExist || needsInit)) {
134
+ n += installOpenCode();
135
+ console.error(` ${green("")} OpenCode: agents + commands`);
111
136
  }
112
- if (hasClaude_CLI && !hasClaude) {
113
- mkdirSync(join(targetDir, ".claude"), { recursive: true });
114
- writeFileSync(join(targetDir, ".claude/settings.json"), "{}\n", "utf-8");
137
+ if (platforms.includes("Claude Code") && (!claudeFilesExist || needsInit)) {
138
+ n += installClaude();
139
+ console.error(` ${green("")} Claude Code: agents + hooks + commands`);
115
140
  }
116
-
117
- if (hasOC || hasClaude || hasOC_CLI || hasClaude_CLI) {
118
- if (existsSync(ASSETS) && existsSync(join(ASSETS, "platforms/opencode/.opencode/agents/ciel.md"))) {
119
- console.error(`\n ⚡ Ciel v${CIEL_VERSION} — Premier lancement, initialisation...`);
120
- const n = runInit(targetDir, ASSETS);
121
- console.error(` ${green("✓")} Ciel v${CIEL_VERSION} configuré (${n} fichiers)\n`);
122
- }
123
- }
124
- } catch {}
125
- }
141
+ console.error(` ${green("✓")} Ciel v${CIEL_VERSION} prêt !\n`);
142
+ }
143
+ } catch {}
126
144
  }
127
145
 
128
146
  // Lancer la CLI normalement
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neikyun/ciel",
3
- "version": "5.2.9",
3
+ "version": "5.2.10",
4
4
  "description": "Ciel — Deep-reasoning pipeline for LLM-assisted development. OpenCode plugin + multi-platform CLI (OpenCode, Claude Code, more).",
5
5
  "main": "./dist/plugin/index.js",
6
6
  "types": "./dist/plugin/index.d.ts",