@neikyun/ciel 5.2.0 → 5.2.2
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 +1 -1
- package/scripts/postinstall.cjs +95 -174
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neikyun/ciel",
|
|
3
|
-
"version": "5.2.
|
|
3
|
+
"version": "5.2.2",
|
|
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",
|
package/scripts/postinstall.cjs
CHANGED
|
@@ -1,234 +1,155 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// Ciel postinstall —
|
|
2
|
+
// Ciel postinstall — s'exécute après npm install / npm update
|
|
3
3
|
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
|
|
7
|
-
|
|
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
|
|
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
|
-
// ----
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
const
|
|
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
|
-
// ----
|
|
29
|
-
function
|
|
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
|
-
|
|
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
|
|
39
|
-
const
|
|
40
|
-
join(
|
|
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
|
-
|
|
58
|
-
if (
|
|
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
|
|
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
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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
|
-
|
|
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
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
const assetsDir =
|
|
180
|
-
if (!assetsDir) return; // No templates bundled
|
|
96
|
+
// INIT_CWD = répertoire où l'utilisateur a lancé npm install
|
|
97
|
+
// (npm lance les lifecycle scripts dans node_modules/<pkg>/, pas dans le projet)
|
|
98
|
+
const targetDir = process.env.INIT_CWD || process.cwd();
|
|
99
|
+
const platforms = detectPlatforms(targetDir);
|
|
100
|
+
const assetsDir = resolveAssets();
|
|
181
101
|
|
|
182
|
-
//
|
|
183
|
-
|
|
184
|
-
const installedVersion = memory.cielVersion || null;
|
|
185
|
-
const isUpdate = installedVersion && installedVersion !== CIEL_VERSION;
|
|
186
|
-
const isFirstInstall = !installedVersion;
|
|
102
|
+
// Toujours afficher le message Ciel
|
|
103
|
+
console.log(`\n ${bold("✦ Ciel v" + CIEL_VERSION)}`);
|
|
187
104
|
|
|
188
|
-
if (!
|
|
105
|
+
if (!assetsDir) {
|
|
106
|
+
console.log(` ${yellow("~")} Templates non trouvés (package corrompu ?)\n`);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
189
109
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
110
|
+
if (platforms.length === 0) {
|
|
111
|
+
console.log(` ${yellow("~")} Aucune plateforme détectée.`);
|
|
112
|
+
console.log(` Ajoutez ${cyan("opencode.json")} ou créez ${cyan(".claude/")} puis relancez npm install.`);
|
|
113
|
+
console.log(` Ou utilisez ${green("npx ciel init")} pour configurer manuellement.\n`);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
193
116
|
|
|
194
|
-
//
|
|
195
|
-
let
|
|
117
|
+
// Demander confirmation (sauter si non-TTY)
|
|
118
|
+
let ok = true;
|
|
196
119
|
if (process.stdin.isTTY) {
|
|
197
120
|
try {
|
|
198
121
|
const readline = require("readline");
|
|
199
122
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
rl.close();
|
|
203
|
-
resolve(a.trim().toLowerCase() || "y");
|
|
204
|
-
});
|
|
205
|
-
});
|
|
206
|
-
} catch {
|
|
207
|
-
answer = "y";
|
|
208
|
-
}
|
|
123
|
+
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"); }));
|
|
124
|
+
} catch { ok = true; }
|
|
209
125
|
}
|
|
210
126
|
|
|
211
|
-
if (
|
|
127
|
+
if (!ok) {
|
|
212
128
|
console.log(` ${cyan("→")} Annulé.\n`);
|
|
213
129
|
return;
|
|
214
130
|
}
|
|
215
131
|
|
|
216
|
-
//
|
|
132
|
+
// Créer .ciel/
|
|
133
|
+
mkdirSync(join(targetDir, ".ciel"), { recursive: true });
|
|
134
|
+
if (!existsSync(join(targetDir, ".ciel/map.json")))
|
|
135
|
+
writeFileSync(join(targetDir, ".ciel/map.json"), JSON.stringify({ modules: [], lastUpdated: "" }), "utf-8");
|
|
136
|
+
if (!existsSync(join(targetDir, ".ciel/parking.md")))
|
|
137
|
+
writeFileSync(join(targetDir, ".ciel/parking.md"), "# Ciel Parking Lot\n\n", "utf-8");
|
|
138
|
+
|
|
139
|
+
// Installer
|
|
217
140
|
let total = 0;
|
|
218
141
|
for (const p of platforms) {
|
|
219
|
-
const n =
|
|
142
|
+
const n = p === "OpenCode" ? installOpenCode(targetDir, assetsDir) : installClaude(targetDir, assetsDir);
|
|
220
143
|
total += n;
|
|
221
144
|
console.log(` ${green("✓")} ${p}: ${n} fichiers`);
|
|
222
145
|
}
|
|
223
146
|
|
|
224
|
-
//
|
|
225
|
-
|
|
147
|
+
// Sauvegarder version
|
|
148
|
+
writeFileSync(join(targetDir, ".ciel/memory.json"), JSON.stringify({ cielVersion: CIEL_VERSION, lastUpdated: new Date().toISOString() }, null, 2), "utf-8");
|
|
226
149
|
|
|
227
|
-
console.log(`\n ${green("✓")} Ciel v${CIEL_VERSION}
|
|
228
|
-
if (platforms.includes("
|
|
229
|
-
|
|
230
|
-
if (platforms.includes("claude"))
|
|
231
|
-
console.log(` → Claude Code: redémarrez ${cyan("claude .")}`);
|
|
150
|
+
console.log(`\n ${green("✓")} Ciel v${CIEL_VERSION} installé !`);
|
|
151
|
+
if (platforms.includes("OpenCode")) console.log(` → plugin ${cyan("@neikyun/ciel")} ajouté à opencode.json`);
|
|
152
|
+
if (platforms.includes("Claude Code")) console.log(` → redémarrez ${cyan("claude .")}`);
|
|
232
153
|
console.log();
|
|
233
154
|
}
|
|
234
155
|
|