@neikyun/ciel 5.2.9 → 5.2.11
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/bin/ciel.js +101 -71
- package/package.json +1 -1
- package/scripts/postinstall.cjs +10 -5
package/bin/ciel.js
CHANGED
|
@@ -1,23 +1,35 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// Ciel CLI — bootstrap entry point
|
|
3
|
-
// Vérifie si l'initialisation est nécessaire
|
|
4
|
-
// Solution de secours quand le postinstall npm ne s'exécute pas.
|
|
3
|
+
// Vérifie si l'initialisation est nécessaire et détecte les nouvelles plateformes.
|
|
5
4
|
|
|
6
5
|
const { existsSync, mkdirSync, writeFileSync, readFileSync, copyFileSync, readdirSync, chmodSync, unlinkSync } = require("fs");
|
|
7
|
-
const { join,
|
|
8
|
-
const { execSync } = require("child_process");
|
|
6
|
+
const { join, delimiter } = require("path");
|
|
9
7
|
|
|
10
8
|
const PKG_DIR = join(__dirname, "..");
|
|
11
9
|
const PKG = JSON.parse(readFileSync(join(PKG_DIR, "package.json"), "utf-8"));
|
|
12
10
|
const CIEL_VERSION = PKG.version || "0.0.0";
|
|
13
11
|
const ASSETS = join(PKG_DIR, "assets");
|
|
14
|
-
|
|
15
|
-
// Vérifier si une (ré)initialisation est nécessaire
|
|
16
12
|
const targetDir = process.env.INIT_CWD || process.cwd();
|
|
17
13
|
const memPath = join(targetDir, ".ciel", "memory.json");
|
|
18
|
-
const storedVersion = (() => { try { return JSON.parse(readFileSync(memPath, "utf-8")).cielVersion; } catch { return null; } })();
|
|
19
|
-
const needsInit = !existsSync(memPath) || storedVersion !== CIEL_VERSION;
|
|
20
14
|
|
|
15
|
+
const c = (code, s) => process.stderr.isTTY ? `\x1b[${code}m${s}\x1b[0m` : s;
|
|
16
|
+
const green = (s) => c(32, s);
|
|
17
|
+
const cyan = (s) => c(36, s);
|
|
18
|
+
|
|
19
|
+
// Cherche un exécutable dans le PATH (fiable cross-platform, pas besoin de shell)
|
|
20
|
+
function searchPath(name) {
|
|
21
|
+
const pathExt = (process.env.PATHEXT || "").split(";");
|
|
22
|
+
if (!pathExt[0]) pathExt.push("", ".exe", ".cmd", ".bat", ".com");
|
|
23
|
+
const pathDirs = (process.env.PATH || "").split(delimiter);
|
|
24
|
+
for (const dir of pathDirs) {
|
|
25
|
+
for (const ext of pathExt) {
|
|
26
|
+
if (existsSync(join(dir, name + ext))) return true;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// ---- Helpers ----
|
|
21
33
|
function copyDir(src, dest) {
|
|
22
34
|
if (!existsSync(src)) return 0;
|
|
23
35
|
let count = 0;
|
|
@@ -30,7 +42,7 @@ function copyDir(src, dest) {
|
|
|
30
42
|
return count;
|
|
31
43
|
}
|
|
32
44
|
|
|
33
|
-
function
|
|
45
|
+
function patchOpencodeJson(targetDir) {
|
|
34
46
|
const cfgPath = join(targetDir, "opencode.json");
|
|
35
47
|
if (!existsSync(cfgPath)) return false;
|
|
36
48
|
try {
|
|
@@ -45,84 +57,102 @@ function patchConfig(targetDir, assets) {
|
|
|
45
57
|
} catch { return false; }
|
|
46
58
|
}
|
|
47
59
|
|
|
48
|
-
|
|
60
|
+
// ---- Détection des plateformes ----
|
|
61
|
+
function detectPlatforms() {
|
|
62
|
+
const platforms = [];
|
|
63
|
+
const hasOC = existsSync(join(targetDir, "opencode.json")) || existsSync(join(targetDir, ".opencode"));
|
|
64
|
+
const hasClaude = existsSync(join(targetDir, ".claude/settings.json")) || existsSync(join(targetDir, ".claude"));
|
|
65
|
+
|
|
66
|
+
// Détection CLI
|
|
67
|
+
const hasOC_CLI = searchPath("opencode");
|
|
68
|
+
const hasClaude_CLI = searchPath("claude");
|
|
69
|
+
|
|
70
|
+
if (hasOC || hasOC_CLI) platforms.push("OpenCode");
|
|
71
|
+
if (hasClaude || hasClaude_CLI) platforms.push("Claude Code");
|
|
72
|
+
return platforms;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// ---- Installer une plateforme ----
|
|
76
|
+
function installOpenCode() {
|
|
77
|
+
let total = 0;
|
|
78
|
+
// Nettoyer ancien plugin curl
|
|
79
|
+
const old = join(targetDir, ".opencode/plugins/ciel.ts");
|
|
80
|
+
if (existsSync(old)) { try { unlinkSync(old); } catch {} }
|
|
81
|
+
total += copyDir(join(ASSETS, "platforms/opencode/.opencode/agents"), join(targetDir, ".opencode/agents"));
|
|
82
|
+
total += copyDir(join(ASSETS, "platforms/opencode/.opencode/commands"), join(targetDir, ".opencode/commands"));
|
|
83
|
+
if (existsSync(join(ASSETS, "platforms/opencode/AGENTS.md"))) {
|
|
84
|
+
copyFileSync(join(ASSETS, "platforms/opencode/AGENTS.md"), join(targetDir, "AGENTS.md"));
|
|
85
|
+
total++;
|
|
86
|
+
}
|
|
87
|
+
if (patchOpencodeJson(targetDir)) total++;
|
|
88
|
+
return total;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function installClaude() {
|
|
49
92
|
let total = 0;
|
|
93
|
+
total += copyDir(join(ASSETS, ".claude/agents"), join(targetDir, ".claude/agents"));
|
|
94
|
+
total += copyDir(join(ASSETS, ".claude/hooks"), join(targetDir, ".claude/hooks"));
|
|
95
|
+
total += copyDir(join(ASSETS, "commands"), join(targetDir, ".claude/commands"));
|
|
96
|
+
if (existsSync(join(ASSETS, ".claude/settings.json"))) {
|
|
97
|
+
copyFileSync(join(ASSETS, ".claude/settings.json"), join(targetDir, ".claude/settings.json"));
|
|
98
|
+
}
|
|
99
|
+
if (existsSync(join(ASSETS, "CLAUDE.md"))) {
|
|
100
|
+
copyFileSync(join(ASSETS, "CLAUDE.md"), join(targetDir, "CLAUDE.md"));
|
|
101
|
+
}
|
|
102
|
+
return total;
|
|
103
|
+
}
|
|
50
104
|
|
|
51
|
-
|
|
105
|
+
function ensureCielState() {
|
|
52
106
|
mkdirSync(join(targetDir, ".ciel"), { recursive: true });
|
|
53
107
|
if (!existsSync(join(targetDir, ".ciel/map.json")))
|
|
54
108
|
writeFileSync(join(targetDir, ".ciel/map.json"), JSON.stringify({ modules: [], lastUpdated: "" }), "utf-8");
|
|
55
109
|
if (!existsSync(join(targetDir, ".ciel/parking.md")))
|
|
56
110
|
writeFileSync(join(targetDir, ".ciel/parking.md"), "# Ciel Parking Lot\n\n", "utf-8");
|
|
111
|
+
writeFileSync(memPath, JSON.stringify({ cielVersion: CIEL_VERSION, lastUpdated: new Date().toISOString() }, null, 2), "utf-8");
|
|
112
|
+
}
|
|
57
113
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
// Copy AGENTS.md
|
|
68
|
-
if (existsSync(join(assets, "platforms/opencode/AGENTS.md"))) {
|
|
69
|
-
copyFileSync(join(assets, "platforms/opencode/AGENTS.md"), join(targetDir, "AGENTS.md"));
|
|
70
|
-
total++;
|
|
71
|
-
}
|
|
72
|
-
if (patchConfig(targetDir, assets)) total++;
|
|
73
|
-
console.error(` ${green("✓")} OpenCode: ${total} fichiers`);
|
|
74
|
-
}
|
|
114
|
+
// ===== MAIN BOOT =====
|
|
115
|
+
const args = process.argv.slice(2);
|
|
116
|
+
const isHelp = args.includes("--help") || args.includes("-h");
|
|
117
|
+
const isVersion = args.includes("--version") || args.includes("-v");
|
|
118
|
+
|
|
119
|
+
if (!isHelp && !isVersion && ASSETS && existsSync(join(ASSETS, "platforms/opencode/.opencode/agents/ciel.md"))) {
|
|
120
|
+
try {
|
|
121
|
+
const storedVersion = (() => { try { return JSON.parse(readFileSync(memPath, "utf-8")).cielVersion; } catch { return null; } })();
|
|
122
|
+
const needsInit = !storedVersion || storedVersion !== CIEL_VERSION;
|
|
75
123
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
copyFileSync(join(assets, ".claude/settings.json"), join(targetDir, ".claude/settings.json"));
|
|
124
|
+
// Toujours détecter les plateformes
|
|
125
|
+
const platforms = detectPlatforms();
|
|
126
|
+
|
|
127
|
+
// Créer les configs si CLI détectée mais pas de fichiers
|
|
128
|
+
if (platforms.includes("OpenCode") && !existsSync(join(targetDir, "opencode.json"))) {
|
|
129
|
+
writeFileSync(join(targetDir, "opencode.json"), JSON.stringify({ $schema: "https://opencode.ai/config.json", plugin: ["@neikyun/ciel"] }, null, 2) + "\n", "utf-8");
|
|
83
130
|
}
|
|
84
|
-
if (existsSync(join(
|
|
85
|
-
|
|
131
|
+
if (platforms.includes("Claude Code") && !existsSync(join(targetDir, ".claude/settings.json"))) {
|
|
132
|
+
mkdirSync(join(targetDir, ".claude"), { recursive: true });
|
|
133
|
+
writeFileSync(join(targetDir, ".claude/settings.json"), "{}\n", "utf-8");
|
|
86
134
|
}
|
|
87
|
-
console.error(` ${green("✓")} Claude Code: ${total} fichiers`);
|
|
88
|
-
}
|
|
89
135
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
136
|
+
// Vérifier ce qui manque pour chaque plateforme détectée
|
|
137
|
+
const opencodeFilesExist = existsSync(join(targetDir, ".opencode/agents/ciel.md"));
|
|
138
|
+
const claudeFilesExist = existsSync(join(targetDir, ".claude/hooks/check-test-first.sh"));
|
|
94
139
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
140
|
+
if (needsInit || (platforms.includes("OpenCode") && !opencodeFilesExist) || (platforms.includes("Claude Code") && !claudeFilesExist)) {
|
|
141
|
+
let n = 0;
|
|
142
|
+
console.error(`\n ⚡ Ciel v${CIEL_VERSION} — Configuration...`);
|
|
143
|
+
ensureCielState();
|
|
98
144
|
|
|
99
|
-
if (needsInit) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
try {
|
|
103
|
-
const hasOC = existsSync(join(targetDir, "opencode.json")) || existsSync(join(targetDir, ".opencode"));
|
|
104
|
-
const hasClaude = existsSync(join(targetDir, ".claude/settings.json")) || existsSync(join(targetDir, ".claude"));
|
|
105
|
-
const hasOC_CLI = (() => { try { return execSync("opencode --version 2>&1", { stdio: "pipe", timeout: 3000 }).toString().length > 0; } catch { return false; } })();
|
|
106
|
-
const hasClaude_CLI = (() => { try { return execSync("claude --version 2>&1", { stdio: "pipe", timeout: 3000 }).toString().length > 0; } catch { return false; } })();
|
|
107
|
-
|
|
108
|
-
// Créer les configs si CLI détectée mais pas de fichier
|
|
109
|
-
if (hasOC_CLI && !hasOC) {
|
|
110
|
-
writeFileSync(join(targetDir, "opencode.json"), JSON.stringify({ $schema: "https://opencode.ai/config.json", plugin: ["@neikyun/ciel"] }, null, 2) + "\n", "utf-8");
|
|
111
|
-
}
|
|
112
|
-
if (hasClaude_CLI && !hasClaude) {
|
|
113
|
-
mkdirSync(join(targetDir, ".claude"), { recursive: true });
|
|
114
|
-
writeFileSync(join(targetDir, ".claude/settings.json"), "{}\n", "utf-8");
|
|
145
|
+
if (platforms.includes("OpenCode") && (!opencodeFilesExist || needsInit)) {
|
|
146
|
+
n += installOpenCode();
|
|
147
|
+
console.error(` ${green("✓")} OpenCode: agents + commands`);
|
|
115
148
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
console.error(`\n ⚡ Ciel v${CIEL_VERSION} — Premier lancement, initialisation...`);
|
|
120
|
-
const n = runInit(targetDir, ASSETS);
|
|
121
|
-
console.error(` ${green("✓")} Ciel v${CIEL_VERSION} configuré (${n} fichiers)\n`);
|
|
122
|
-
}
|
|
149
|
+
if (platforms.includes("Claude Code") && (!claudeFilesExist || needsInit)) {
|
|
150
|
+
n += installClaude();
|
|
151
|
+
console.error(` ${green("✓")} Claude Code: agents + hooks + commands`);
|
|
123
152
|
}
|
|
124
|
-
|
|
125
|
-
|
|
153
|
+
console.error(` ${green("✓")} Ciel v${CIEL_VERSION} prêt !\n`);
|
|
154
|
+
}
|
|
155
|
+
} catch {}
|
|
126
156
|
}
|
|
127
157
|
|
|
128
158
|
// Lancer la CLI normalement
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neikyun/ciel",
|
|
3
|
-
"version": "5.2.
|
|
3
|
+
"version": "5.2.11",
|
|
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
|
@@ -34,11 +34,16 @@ function resolveAssets() {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
function detectCLI(name) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
// Cherche l'exécutable dans le PATH directement (fiable cross-platform)
|
|
38
|
+
const pathExt = process.env.PATHEXT ? process.env.PATHEXT.split(";") : ["", ".exe", ".cmd", ".bat", ".com"];
|
|
39
|
+
const pathDirs = (process.env.PATH || "").split(require("path").delimiter);
|
|
40
|
+
for (const dir of pathDirs) {
|
|
41
|
+
for (const ext of pathExt) {
|
|
42
|
+
const fullPath = require("path").join(dir, name + ext);
|
|
43
|
+
if (existsSync(fullPath)) return true;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return false;
|
|
42
47
|
}
|
|
43
48
|
|
|
44
49
|
// ---- Installation ----
|