@neikyun/ciel 5.1.6 → 5.1.7
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 +3 -1
- package/scripts/postinstall.cjs +231 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neikyun/ciel",
|
|
3
|
-
"version": "5.1.
|
|
3
|
+
"version": "5.1.7",
|
|
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",
|
|
@@ -11,12 +11,14 @@
|
|
|
11
11
|
"dist",
|
|
12
12
|
"assets",
|
|
13
13
|
"bin",
|
|
14
|
+
"scripts/postinstall.cjs",
|
|
14
15
|
"README.md"
|
|
15
16
|
],
|
|
16
17
|
"scripts": {
|
|
17
18
|
"build": "node scripts/copy-assets.cjs && tsc",
|
|
18
19
|
"clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true});require('fs').rmSync('assets',{recursive:true,force:true})\"",
|
|
19
20
|
"test": "npx tsx --test test/**/*.test.ts",
|
|
21
|
+
"postinstall": "node scripts/postinstall.cjs",
|
|
20
22
|
"prepublishOnly": "npm run build && npm test"
|
|
21
23
|
},
|
|
22
24
|
"dependencies": {
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Ciel postinstall — auto-configure après npm install
|
|
3
|
+
//
|
|
4
|
+
// S'exécute automatiquement après `npm install @neikyun/ciel`.
|
|
5
|
+
// Détecte OpenCode / Claude Code, propose de configurer, et installe.
|
|
6
|
+
//
|
|
7
|
+
// Désactivable avec : CI=true npm install @neikyun/ciel
|
|
8
|
+
// npm install @neikyun/ciel --ignore-scripts
|
|
9
|
+
|
|
10
|
+
const { existsSync, readFileSync, writeFileSync, mkdirSync, copyFileSync, chmodSync } = require("fs");
|
|
11
|
+
const { join, dirname } = require("path");
|
|
12
|
+
const { execSync } = require("child_process");
|
|
13
|
+
|
|
14
|
+
const CIEL_VERSION = "5.1.6";
|
|
15
|
+
|
|
16
|
+
// ----- Colors -----
|
|
17
|
+
const cyan = (s) => `\x1b[36m${s}\x1b[0m`;
|
|
18
|
+
const green = (s) => `\x1b[32m${s}\x1b[0m`;
|
|
19
|
+
const yellow = (s) => `\x1b[33m${s}\x1b[0m`;
|
|
20
|
+
const bold = (s) => `\x1b[1m${s}\x1b[0m`;
|
|
21
|
+
|
|
22
|
+
// ----- Helpers -----
|
|
23
|
+
function detectPlatform(targetDir) {
|
|
24
|
+
const platforms = [];
|
|
25
|
+
if (existsSync(join(targetDir, "opencode.json")) || existsSync(join(targetDir, ".opencode"))) {
|
|
26
|
+
platforms.push("opencode");
|
|
27
|
+
}
|
|
28
|
+
if (existsSync(join(targetDir, ".claude/settings.json")) || existsSync(join(targetDir, ".claude"))) {
|
|
29
|
+
platforms.push("claude");
|
|
30
|
+
}
|
|
31
|
+
return platforms;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function resolveAssetsDir() {
|
|
35
|
+
const candidates = [
|
|
36
|
+
// npm install local (workspace)
|
|
37
|
+
join(__dirname, "..", "assets"),
|
|
38
|
+
// npm install global
|
|
39
|
+
join(__dirname, "..", "..", "assets"),
|
|
40
|
+
// GitHub fallback (via npx ciel)
|
|
41
|
+
null,
|
|
42
|
+
];
|
|
43
|
+
for (const dir of candidates) {
|
|
44
|
+
if (dir && existsSync(join(dir, "platforms/opencode/.opencode/agents/ciel.md"))) {
|
|
45
|
+
return dir;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function copyDir(src, dest) {
|
|
52
|
+
if (!existsSync(src)) return 0;
|
|
53
|
+
const { readdirSync } = require("fs");
|
|
54
|
+
let count = 0;
|
|
55
|
+
mkdirSync(dest, { recursive: true });
|
|
56
|
+
for (const entry of readdirSync(src, { withFileTypes: true })) {
|
|
57
|
+
const s = join(src, entry.name);
|
|
58
|
+
const d = join(dest, entry.name);
|
|
59
|
+
if (entry.isDirectory()) {
|
|
60
|
+
count += copyDir(s, d);
|
|
61
|
+
} else {
|
|
62
|
+
copyFileSync(s, d);
|
|
63
|
+
if (s.endsWith(".sh")) try { chmodSync(d, 0o755); } catch {}
|
|
64
|
+
count++;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return count;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function patchOpencodeJson(targetDir) {
|
|
71
|
+
const configPath = join(targetDir, "opencode.json");
|
|
72
|
+
if (!existsSync(configPath)) return false;
|
|
73
|
+
try {
|
|
74
|
+
const raw = readFileSync(configPath, "utf-8");
|
|
75
|
+
const config = JSON.parse(raw);
|
|
76
|
+
if (!config.plugin) config.plugin = [];
|
|
77
|
+
if (!config.plugin.includes("@neikyun/ciel")) {
|
|
78
|
+
config.plugin.push("@neikyun/ciel");
|
|
79
|
+
}
|
|
80
|
+
if (!config.instructions) config.instructions = [];
|
|
81
|
+
if (!config.instructions.includes("AGENTS.md")) {
|
|
82
|
+
config.instructions.push("AGENTS.md");
|
|
83
|
+
}
|
|
84
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
85
|
+
return true;
|
|
86
|
+
} catch {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function installForPlatform(targetDir, assetsDir, platform) {
|
|
92
|
+
let count = 0;
|
|
93
|
+
if (platform === "opencode") {
|
|
94
|
+
// Copy agents
|
|
95
|
+
const agentsSrc = join(assetsDir, "platforms/opencode/.opencode/agents");
|
|
96
|
+
const agentsDest = join(targetDir, ".opencode/agents");
|
|
97
|
+
count += copyDir(agentsSrc, agentsDest);
|
|
98
|
+
|
|
99
|
+
// Copy commands
|
|
100
|
+
const cmdsSrc = join(assetsDir, "platforms/opencode/.opencode/commands");
|
|
101
|
+
const cmdsDest = join(targetDir, ".opencode/commands");
|
|
102
|
+
count += copyDir(cmdsSrc, cmdsDest);
|
|
103
|
+
|
|
104
|
+
// Copy AGENTS.md
|
|
105
|
+
const agentsMdSrc = join(assetsDir, "platforms/opencode/AGENTS.md");
|
|
106
|
+
if (existsSync(agentsMdSrc)) {
|
|
107
|
+
copyFileSync(agentsMdSrc, join(targetDir, "AGENTS.md"));
|
|
108
|
+
count++;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Patch opencode.json
|
|
112
|
+
if (patchOpencodeJson(targetDir)) count++;
|
|
113
|
+
|
|
114
|
+
return count;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (platform === "claude") {
|
|
118
|
+
// Copy agents
|
|
119
|
+
const agentsSrc = join(assetsDir, ".claude/agents");
|
|
120
|
+
const agentsDest = join(targetDir, ".claude/agents");
|
|
121
|
+
count += copyDir(agentsSrc, agentsDest);
|
|
122
|
+
|
|
123
|
+
// Copy hooks
|
|
124
|
+
const hooksSrc = join(assetsDir, ".claude/hooks");
|
|
125
|
+
const hooksDest = join(targetDir, ".claude/hooks");
|
|
126
|
+
count += copyDir(hooksSrc, hooksDest);
|
|
127
|
+
|
|
128
|
+
// Copy settings
|
|
129
|
+
const settingsSrc = join(assetsDir, ".claude/settings.json");
|
|
130
|
+
if (existsSync(settingsSrc)) {
|
|
131
|
+
copyFileSync(settingsSrc, join(targetDir, ".claude/settings.json"));
|
|
132
|
+
count++;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Copy CLAUDE.md
|
|
136
|
+
const claudeMdSrc = join(assetsDir, "CLAUDE.md");
|
|
137
|
+
if (existsSync(claudeMdSrc)) {
|
|
138
|
+
copyFileSync(claudeMdSrc, join(targetDir, "CLAUDE.md"));
|
|
139
|
+
count++;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return count;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return 0;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// ===== MAIN =====
|
|
149
|
+
async function main() {
|
|
150
|
+
// Skip if CI env or --ignore-scripts was used
|
|
151
|
+
if (process.env.CI || process.env.NO_CIEL_POSTINSTALL) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const targetDir = process.cwd();
|
|
156
|
+
const platforms = detectPlatform(targetDir);
|
|
157
|
+
|
|
158
|
+
if (platforms.length === 0) {
|
|
159
|
+
// No recognized platform — silent exit (tool installed in non-Ciel project)
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const assetsDir = resolveAssetsDir();
|
|
164
|
+
if (!assetsDir) {
|
|
165
|
+
// Assets not bundled — postinstall can't configure
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Check if already configured
|
|
170
|
+
const alreadyConfigured = existsSync(join(targetDir, ".ciel/map.json"));
|
|
171
|
+
|
|
172
|
+
if (alreadyConfigured) {
|
|
173
|
+
// Already set up, skip prompt
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// ----- Interactive prompt -----
|
|
178
|
+
const platformNames = platforms.join(" + ");
|
|
179
|
+
console.log(`\n ${bold("✦ Ciel v" + CIEL_VERSION)} — detecté pour ${cyan(platformNames)}`);
|
|
180
|
+
|
|
181
|
+
// Try to read from stdin for the prompt
|
|
182
|
+
let answer = "y";
|
|
183
|
+
try {
|
|
184
|
+
const readline = require("readline");
|
|
185
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
186
|
+
answer = await new Promise((resolve) => {
|
|
187
|
+
rl.question(` ${yellow("?")} Configurer Ciel dans ce projet ? ${green("(Y/n)")} `, (a) => {
|
|
188
|
+
rl.close();
|
|
189
|
+
resolve(a.trim().toLowerCase() || "y");
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
} catch {
|
|
193
|
+
// Non-interactive, use default
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (answer !== "y" && answer !== "yes") {
|
|
197
|
+
console.log(` ${cyan("→")} Annulé. Lancez ${green("npx ciel init")} plus tard.\n`);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// ----- Install -----
|
|
202
|
+
// Create .ciel/ state dir
|
|
203
|
+
mkdirSync(join(targetDir, ".ciel"), { recursive: true });
|
|
204
|
+
if (!existsSync(join(targetDir, ".ciel/map.json"))) {
|
|
205
|
+
writeFileSync(join(targetDir, ".ciel/map.json"), JSON.stringify({ modules: [], lastUpdated: new Date().toISOString() }), "utf-8");
|
|
206
|
+
}
|
|
207
|
+
if (!existsSync(join(targetDir, ".ciel/memory.json"))) {
|
|
208
|
+
writeFileSync(join(targetDir, ".ciel/memory.json"), "{}", "utf-8");
|
|
209
|
+
}
|
|
210
|
+
if (!existsSync(join(targetDir, ".ciel/parking.md"))) {
|
|
211
|
+
writeFileSync(join(targetDir, ".ciel/parking.md"), "# Ciel Parking Lot -- Decouvertes fortuites\n\n", "utf-8");
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
let total = 0;
|
|
215
|
+
for (const p of platforms) {
|
|
216
|
+
const n = installForPlatform(targetDir, assetsDir, p);
|
|
217
|
+
total += n;
|
|
218
|
+
console.log(` ${green("✓")} ${p}: ${n} fichiers installés`);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
console.log(`\n ${green("✓")} Ciel v${CIEL_VERSION} prêt !`);
|
|
222
|
+
for (const p of platforms) {
|
|
223
|
+
if (p === "opencode") console.log(` → OpenCode: plugin chargé automatiquement`);
|
|
224
|
+
if (p === "claude") console.log(` → Claude Code: redémarrez ${cyan("claude .")}`);
|
|
225
|
+
}
|
|
226
|
+
console.log(` → CLI: ${green("npx ciel")} check | init | update | uninstall\n`);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
main().catch(() => {
|
|
230
|
+
// Silent fail — postinstall ne doit jamais bloquer npm install
|
|
231
|
+
});
|