@neikyun/ciel 5.2.0 → 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 +1 -1
- package/scripts/postinstall.cjs +92 -173
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neikyun/ciel",
|
|
3
|
-
"version": "5.2.
|
|
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",
|
package/scripts/postinstall.cjs
CHANGED
|
@@ -1,234 +1,153 @@
|
|
|
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
96
|
const targetDir = process.cwd();
|
|
176
|
-
const platforms =
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
const assetsDir = resolveAssetsDir();
|
|
180
|
-
if (!assetsDir) return; // No templates bundled
|
|
97
|
+
const platforms = detectPlatforms(targetDir);
|
|
98
|
+
const assetsDir = resolveAssets();
|
|
181
99
|
|
|
182
|
-
//
|
|
183
|
-
|
|
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 (!
|
|
103
|
+
if (!assetsDir) {
|
|
104
|
+
console.log(` ${yellow("~")} Templates non trouvés (package corrompu ?)\n`);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
189
107
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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
|
-
//
|
|
195
|
-
let
|
|
115
|
+
// Demander confirmation (sauter si non-TTY)
|
|
116
|
+
let ok = true;
|
|
196
117
|
if (process.stdin.isTTY) {
|
|
197
118
|
try {
|
|
198
119
|
const readline = require("readline");
|
|
199
120
|
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
|
-
}
|
|
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; }
|
|
209
123
|
}
|
|
210
124
|
|
|
211
|
-
if (
|
|
125
|
+
if (!ok) {
|
|
212
126
|
console.log(` ${cyan("→")} Annulé.\n`);
|
|
213
127
|
return;
|
|
214
128
|
}
|
|
215
129
|
|
|
216
|
-
//
|
|
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
|
|
217
138
|
let total = 0;
|
|
218
139
|
for (const p of platforms) {
|
|
219
|
-
const n =
|
|
140
|
+
const n = p === "OpenCode" ? installOpenCode(targetDir, assetsDir) : installClaude(targetDir, assetsDir);
|
|
220
141
|
total += n;
|
|
221
142
|
console.log(` ${green("✓")} ${p}: ${n} fichiers`);
|
|
222
143
|
}
|
|
223
144
|
|
|
224
|
-
//
|
|
225
|
-
|
|
145
|
+
// Sauvegarder version
|
|
146
|
+
writeFileSync(join(targetDir, ".ciel/memory.json"), JSON.stringify({ cielVersion: CIEL_VERSION, lastUpdated: new Date().toISOString() }, null, 2), "utf-8");
|
|
226
147
|
|
|
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 .")}`);
|
|
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 .")}`);
|
|
232
151
|
console.log();
|
|
233
152
|
}
|
|
234
153
|
|