@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 +1 -1
- package/scripts/postinstall.cjs +96 -175
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neikyun/ciel",
|
|
3
|
-
"version": "5.1
|
|
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,232 +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
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
rl.question(` ${yellow("?")}
|
|
201
|
-
|
|
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 (
|
|
125
|
+
if (!ok) {
|
|
210
126
|
console.log(` ${cyan("→")} Annulé.\n`);
|
|
211
127
|
return;
|
|
212
128
|
}
|
|
213
129
|
|
|
214
|
-
//
|
|
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 =
|
|
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
|
-
//
|
|
223
|
-
|
|
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}
|
|
226
|
-
if (platforms.includes("
|
|
227
|
-
|
|
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
|
|