@neikyun/ciel 5.1.9 → 5.2.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neikyun/ciel",
3
- "version": "5.1.9",
3
+ "version": "5.2.1",
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",
@@ -1,232 +1,153 @@
1
1
  #!/usr/bin/env node
2
- // Ciel postinstall — auto-configure après npm install / npm update
2
+ // Ciel postinstall — s'exécute après npm install / npm update
3
3
  //
4
- // S'exécute automatiquement après `npm install @neikyun/ciel`.
5
- // Détecte OpenCode / Claude Code, configure tout, gère les mises à jour.
6
- //
7
- // Comportement :
8
- // - Première install → propose et configure
9
- // - npm update (nouvelle version) → détecte et propose la mise à jour
10
- // - npm install (même version) → skip silencieux
11
- // - Désactivable : CI=true npm install @neikyun/ciel
12
- // npm install @neikyun/ciel --ignore-scripts
13
-
14
- const { existsSync, readFileSync, writeFileSync, mkdirSync, copyFileSync, chmodSync, unlinkSync } = require("fs");
4
+ // Toujours visible. Détecte les plateformes, configure, ou guide l'utilisateur.
5
+ // Désactivable avec CI=true ou --ignore-scripts
6
+
7
+ const { existsSync, readFileSync, writeFileSync, mkdirSync, copyFileSync, chmodSync, unlinkSync, readdirSync } = require("fs");
15
8
  const { join, dirname } = require("path");
16
9
 
17
10
  // ---- Version ----
18
- const PKG_PATH = join(__dirname, "..", "package.json");
19
- const PKG = existsSync(PKG_PATH) ? JSON.parse(readFileSync(PKG_PATH, "utf-8")) : {};
11
+ const PKG = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf-8"));
20
12
  const CIEL_VERSION = PKG.version || "0.0.0";
21
13
 
22
- // ---- Colors ----
23
- const cyan = (s) => `\x1b[36m${s}\x1b[0m`;
24
- const green = (s) => `\x1b[32m${s}\x1b[0m`;
25
- const yellow = (s) => `\x1b[33m${s}\x1b[0m`;
26
- const bold = (s) => `\x1b[1m${s}\x1b[0m`;
14
+ // ---- Couleurs ----
15
+ const c = (code, s) => process.stdout.isTTY ? `\x1b[${code}m${s}\x1b[0m` : s;
16
+ const cyan = (s) => c(36, s);
17
+ const green = (s) => c(32, s);
18
+ const yellow = (s) => c(33, s);
19
+ const bold = (s) => c(1, s);
27
20
 
28
- // ---- Helpers ----
29
- function detectPlatform(targetDir) {
21
+ // ---- Détection de plateforme ----
22
+ function detectPlatforms(targetDir) {
30
23
  const platforms = [];
31
- if (existsSync(join(targetDir, "opencode.json")) || existsSync(join(targetDir, ".opencode")))
32
- platforms.push("opencode");
33
- if (existsSync(join(targetDir, ".claude/settings.json")) || existsSync(join(targetDir, ".claude")))
34
- platforms.push("claude");
24
+ if (existsSync(join(targetDir, "opencode.json")) || existsSync(join(targetDir, ".opencode"))) platforms.push("OpenCode");
25
+ if (existsSync(join(targetDir, ".claude/settings.json")) || existsSync(join(targetDir, ".claude"))) platforms.push("Claude Code");
35
26
  return platforms;
36
27
  }
37
28
 
38
- function resolveAssetsDir() {
39
- const candidates = [
40
- join(__dirname, "..", "assets"),
41
- join(__dirname, "..", "..", "assets"),
42
- ];
43
- for (const dir of candidates) {
44
- if (dir && existsSync(join(dir, "platforms/opencode/.opencode/agents/ciel.md")))
45
- return dir;
29
+ function resolveAssets() {
30
+ for (const dir of [join(__dirname, "..", "assets"), join(__dirname, "..", "..", "assets")]) {
31
+ if (existsSync(join(dir, "platforms/opencode/.opencode/agents/ciel.md"))) return dir;
46
32
  }
47
33
  return null;
48
34
  }
49
35
 
36
+ // ---- Installation ----
50
37
  function copyDir(src, dest) {
51
38
  if (!existsSync(src)) return 0;
52
- const { readdirSync } = require("fs");
53
39
  let count = 0;
54
40
  mkdirSync(dest, { recursive: true });
55
41
  for (const entry of readdirSync(src, { withFileTypes: true })) {
56
- const s = join(src, entry.name);
57
- const d = join(dest, entry.name);
58
- if (entry.isDirectory()) {
59
- count += copyDir(s, d);
60
- } else {
61
- copyFileSync(s, d);
62
- if (s.endsWith(".sh")) try { chmodSync(d, 0o755); } catch {}
63
- count++;
64
- }
42
+ const s = join(src, entry.name), d = join(dest, entry.name);
43
+ if (entry.isDirectory()) count += copyDir(s, d);
44
+ else { copyFileSync(s, d); if (s.endsWith(".sh")) try { chmodSync(d, 0o755); } catch {} count++; }
65
45
  }
66
46
  return count;
67
47
  }
68
48
 
69
- function patchOpencodeJson(targetDir) {
70
- const configPath = join(targetDir, "opencode.json");
71
- if (!existsSync(configPath)) return false;
72
- try {
73
- const raw = readFileSync(configPath, "utf-8");
74
- const config = JSON.parse(raw);
75
- let changed = false;
76
-
77
- // Remove old local plugin reference (curl install)
78
- if (config.plugin) {
79
- const filtered = config.plugin.filter((p) => p !== "./.opencode/plugins/ciel.ts");
80
- if (filtered.length !== config.plugin.length) changed = true;
81
- config.plugin = filtered;
82
- }
83
-
84
- // Add new npm plugin reference
85
- if (!config.plugin) config.plugin = [];
86
- if (!config.plugin.includes("@neikyun/ciel")) {
87
- config.plugin.push("@neikyun/ciel");
88
- changed = true;
89
- }
90
-
91
- // Add instructions
92
- if (!config.instructions) config.instructions = [];
93
- if (!config.instructions.includes("AGENTS.md")) {
94
- config.instructions.push("AGENTS.md");
95
- changed = true;
96
- }
97
-
98
- if (changed) {
99
- writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
100
- }
101
- return changed;
102
- } catch {
103
- return false;
104
- }
105
- }
106
-
107
- function installForPlatform(targetDir, assetsDir, platform) {
49
+ function installOpenCode(targetDir, assets) {
108
50
  let count = 0;
109
- if (platform === "opencode") {
110
- // Clean old curl files
111
- const oldPlugin = join(targetDir, ".opencode/plugins/ciel.ts");
112
- if (existsSync(oldPlugin)) {
113
- try { unlinkSync(oldPlugin); count++; } catch {}
114
- }
115
-
116
- // Copy fresh agents
117
- count += copyDir(
118
- join(assetsDir, "platforms/opencode/.opencode/agents"),
119
- join(targetDir, ".opencode/agents")
120
- );
121
- // Copy fresh commands
122
- count += copyDir(
123
- join(assetsDir, "platforms/opencode/.opencode/commands"),
124
- join(targetDir, ".opencode/commands")
125
- );
126
- // Copy AGENTS.md
127
- const agentsMdSrc = join(assetsDir, "platforms/opencode/AGENTS.md");
128
- if (existsSync(agentsMdSrc)) {
129
- copyFileSync(agentsMdSrc, join(targetDir, "AGENTS.md"));
130
- count++;
131
- }
132
- // Patch config
133
- if (patchOpencodeJson(targetDir)) count++;
134
- return count;
51
+ // Nettoyer ancien plugin curl
52
+ const old = join(targetDir, ".opencode/plugins/ciel.ts");
53
+ if (existsSync(old)) { try { unlinkSync(old); count++; } catch {} }
54
+ // Copier agents
55
+ count += copyDir(join(assets, "platforms/opencode/.opencode/agents"), join(targetDir, ".opencode/agents"));
56
+ // Copier commandes
57
+ count += copyDir(join(assets, "platforms/opencode/.opencode/commands"), join(targetDir, ".opencode/commands"));
58
+ // Copier AGENTS.md
59
+ if (existsSync(join(assets, "platforms/opencode/AGENTS.md"))) {
60
+ copyFileSync(join(assets, "platforms/opencode/AGENTS.md"), join(targetDir, "AGENTS.md"));
61
+ count++;
135
62
  }
136
-
137
- if (platform === "claude") {
138
- count += copyDir(join(assetsDir, ".claude/agents"), join(targetDir, ".claude/agents"));
139
- count += copyDir(join(assetsDir, ".claude/hooks"), join(targetDir, ".claude/hooks"));
140
- const settingsSrc = join(assetsDir, ".claude/settings.json");
141
- if (existsSync(settingsSrc)) {
142
- copyFileSync(settingsSrc, join(targetDir, ".claude/settings.json"));
143
- count++;
144
- }
145
- const claudeMdSrc = join(assetsDir, "CLAUDE.md");
146
- if (existsSync(claudeMdSrc)) {
147
- copyFileSync(claudeMdSrc, join(targetDir, "CLAUDE.md"));
63
+ // Patcher opencode.json
64
+ try {
65
+ const cfgPath = join(targetDir, "opencode.json");
66
+ if (existsSync(cfgPath)) {
67
+ let cfg = JSON.parse(readFileSync(cfgPath, "utf-8"));
68
+ if (!cfg.plugin) cfg.plugin = [];
69
+ // Remplacer ancienne ref locale par npm
70
+ cfg.plugin = cfg.plugin.filter(p => p !== "./.opencode/plugins/ciel.ts");
71
+ if (!cfg.plugin.includes("@neikyun/ciel")) cfg.plugin.push("@neikyun/ciel");
72
+ if (!cfg.instructions) cfg.instructions = [];
73
+ if (!cfg.instructions.includes("AGENTS.md")) cfg.instructions.push("AGENTS.md");
74
+ writeFileSync(cfgPath, JSON.stringify(cfg, null, 2) + "\n", "utf-8");
148
75
  count++;
149
76
  }
150
- return count;
151
- }
152
- return 0;
153
- }
154
-
155
- function readMemory(targetDir) {
156
- const memPath = join(targetDir, ".ciel/memory.json");
157
- try {
158
- return JSON.parse(readFileSync(memPath, "utf-8"));
159
- } catch {
160
- return {};
161
- }
77
+ } catch {}
78
+ return count;
162
79
  }
163
80
 
164
- function writeMemory(targetDir, data) {
165
- const memPath = join(targetDir, ".ciel/memory.json");
166
- mkdirSync(join(targetDir, ".ciel"), { recursive: true });
167
- writeFileSync(memPath, JSON.stringify(data, null, 2), "utf-8");
81
+ function installClaude(targetDir, assets) {
82
+ let count = 0;
83
+ count += copyDir(join(assets, ".claude/agents"), join(targetDir, ".claude/agents"));
84
+ count += copyDir(join(assets, ".claude/hooks"), join(targetDir, ".claude/hooks"));
85
+ const settings = join(assets, ".claude/settings.json");
86
+ if (existsSync(settings)) { copyFileSync(settings, join(targetDir, ".claude/settings.json")); count++; }
87
+ const claudeMd = join(assets, "CLAUDE.md");
88
+ if (existsSync(claudeMd)) { copyFileSync(claudeMd, join(targetDir, "CLAUDE.md")); count++; }
89
+ return count;
168
90
  }
169
91
 
170
- // ===== MAIN =====
92
+ // ---- MAIN ----
171
93
  async function main() {
172
- // Skip in CI
173
94
  if (process.env.CI || process.env.NO_CIEL_POSTINSTALL) return;
174
95
 
175
96
  const targetDir = process.cwd();
176
- const platforms = detectPlatform(targetDir);
177
- if (platforms.length === 0) return; // Not a Ciel-compatible project
178
-
179
- const assetsDir = resolveAssetsDir();
180
- if (!assetsDir) return; // No templates bundled
97
+ const platforms = detectPlatforms(targetDir);
98
+ const assetsDir = resolveAssets();
181
99
 
182
- // Check installed version vs current version
183
- const memory = readMemory(targetDir);
184
- const installedVersion = memory.cielVersion || null;
185
- const isUpdate = installedVersion && installedVersion !== CIEL_VERSION;
186
- const isFirstInstall = !installedVersion;
100
+ // Toujours afficher le message Ciel
101
+ console.log(`\n ${bold("✦ Ciel v" + CIEL_VERSION)}`);
187
102
 
188
- if (!isFirstInstall && !isUpdate) return; // Same version → skip
103
+ if (!assetsDir) {
104
+ console.log(` ${yellow("~")} Templates non trouvés (package corrompu ?)\n`);
105
+ return;
106
+ }
189
107
 
190
- // Show banner
191
- const action = isUpdate ? "mise à jour" : "configuration";
192
- console.log(`\n ${bold("✦ Ciel v" + CIEL_VERSION)} ${action} pour ${cyan(platforms.join(" + "))}`);
108
+ if (platforms.length === 0) {
109
+ console.log(` ${yellow("~")} Aucune plateforme détectée.`);
110
+ console.log(` Ajoutez ${cyan("opencode.json")} ou créez ${cyan(".claude/")} puis relancez npm install.`);
111
+ console.log(` Ou utilisez ${green("npx ciel init")} pour configurer manuellement.\n`);
112
+ return;
113
+ }
193
114
 
194
- // Prompt (skip if unattended already accepted)
195
- let answer = "y";
196
- try {
197
- const readline = require("readline");
198
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
199
- answer = await new Promise((resolve) => {
200
- rl.question(` ${yellow("?")} ${isUpdate ? "Mettre à jour" : "Configurer"} Ciel ? ${green("(Y/n)")} `, (a) => {
201
- rl.close();
202
- resolve(a.trim().toLowerCase() || "y");
203
- });
204
- });
205
- } catch {
206
- answer = "y";
115
+ // Demander confirmation (sauter si non-TTY)
116
+ let ok = true;
117
+ if (process.stdin.isTTY) {
118
+ try {
119
+ const readline = require("readline");
120
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
121
+ ok = await new Promise(r => rl.question(` ${yellow("?")} Configurer Ciel pour ${cyan(platforms.join(" + "))} ? ${green("(Y/n)")} `, a => { rl.close(); r(a.trim().toLowerCase() !== "n"); }));
122
+ } catch { ok = true; }
207
123
  }
208
124
 
209
- if (answer !== "y" && answer !== "yes") {
125
+ if (!ok) {
210
126
  console.log(` ${cyan("→")} Annulé.\n`);
211
127
  return;
212
128
  }
213
129
 
214
- // ---- Execute ----
130
+ // Créer .ciel/
131
+ mkdirSync(join(targetDir, ".ciel"), { recursive: true });
132
+ if (!existsSync(join(targetDir, ".ciel/map.json")))
133
+ writeFileSync(join(targetDir, ".ciel/map.json"), JSON.stringify({ modules: [], lastUpdated: "" }), "utf-8");
134
+ if (!existsSync(join(targetDir, ".ciel/parking.md")))
135
+ writeFileSync(join(targetDir, ".ciel/parking.md"), "# Ciel Parking Lot\n\n", "utf-8");
136
+
137
+ // Installer
215
138
  let total = 0;
216
139
  for (const p of platforms) {
217
- const n = installForPlatform(targetDir, assetsDir, p);
140
+ const n = p === "OpenCode" ? installOpenCode(targetDir, assetsDir) : installClaude(targetDir, assetsDir);
218
141
  total += n;
219
142
  console.log(` ${green("✓")} ${p}: ${n} fichiers`);
220
143
  }
221
144
 
222
- // Store version
223
- writeMemory(targetDir, { ...memory, cielVersion: CIEL_VERSION, lastUpdated: new Date().toISOString() });
145
+ // Sauvegarder version
146
+ writeFileSync(join(targetDir, ".ciel/memory.json"), JSON.stringify({ cielVersion: CIEL_VERSION, lastUpdated: new Date().toISOString() }, null, 2), "utf-8");
224
147
 
225
- console.log(`\n ${green("✓")} Ciel v${CIEL_VERSION} ${isUpdate ? "mis à jour" : "prêt"} !`);
226
- if (platforms.includes("opencode"))
227
- console.log(` → OpenCode: plugin "${cyan("@neikyun/ciel")}" dans opencode.json`);
228
- if (platforms.includes("claude"))
229
- console.log(` → Claude Code: redémarrez ${cyan("claude .")}`);
148
+ console.log(`\n ${green("✓")} Ciel v${CIEL_VERSION} installé !`);
149
+ if (platforms.includes("OpenCode")) console.log(` → plugin ${cyan("@neikyun/ciel")} ajouté à opencode.json`);
150
+ if (platforms.includes("Claude Code")) console.log(` → redémarrez ${cyan("claude .")}`);
230
151
  console.log();
231
152
  }
232
153