@neikyun/ciel 5.2.6 → 5.2.8

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 CHANGED
@@ -1,6 +1,128 @@
1
1
  #!/usr/bin/env node
2
2
  // Ciel CLI — bootstrap entry point
3
- // This file exists before build so npm can validate the bin path.
4
- // It loads the compiled CLI from dist/ at runtime.
3
+ // Vérifie si l'initialisation est nécessaire, sinon lance la CLI normalement.
4
+ // Solution de secours quand le postinstall npm ne s'exécute pas.
5
5
 
6
+ const { existsSync, mkdirSync, writeFileSync, readFileSync, copyFileSync, readdirSync, chmodSync, unlinkSync } = require("fs");
7
+ const { join, dirname } = require("path");
8
+ const { execSync } = require("child_process");
9
+
10
+ const PKG_DIR = join(__dirname, "..");
11
+ const PKG = JSON.parse(readFileSync(join(PKG_DIR, "package.json"), "utf-8"));
12
+ const CIEL_VERSION = PKG.version || "0.0.0";
13
+ const ASSETS = join(PKG_DIR, "assets");
14
+
15
+ // Vérifier si une initialisation est nécessaire
16
+ const targetDir = process.env.INIT_CWD || process.cwd();
17
+ const memPath = join(targetDir, ".ciel", "memory.json");
18
+ const needsInit = !existsSync(memPath);
19
+
20
+ function copyDir(src, dest) {
21
+ if (!existsSync(src)) return 0;
22
+ let count = 0;
23
+ mkdirSync(dest, { recursive: true });
24
+ for (const entry of readdirSync(src, { withFileTypes: true })) {
25
+ const s = join(src, entry.name), d = join(dest, entry.name);
26
+ if (entry.isDirectory()) count += copyDir(s, d);
27
+ else { copyFileSync(s, d); if (s.endsWith(".sh")) try { chmodSync(d, 0o755); } catch {} count++; }
28
+ }
29
+ return count;
30
+ }
31
+
32
+ function patchConfig(targetDir, assets) {
33
+ const cfgPath = join(targetDir, "opencode.json");
34
+ if (!existsSync(cfgPath)) return false;
35
+ try {
36
+ const cfg = JSON.parse(readFileSync(cfgPath, "utf-8"));
37
+ if (!cfg.plugin) cfg.plugin = [];
38
+ cfg.plugin = cfg.plugin.filter(p => p !== "./.opencode/plugins/ciel.ts");
39
+ if (!cfg.plugin.includes("@neikyun/ciel")) cfg.plugin.push("@neikyun/ciel");
40
+ if (!cfg.instructions) cfg.instructions = [];
41
+ if (!cfg.instructions.includes("AGENTS.md")) cfg.instructions.push("AGENTS.md");
42
+ writeFileSync(cfgPath, JSON.stringify(cfg, null, 2) + "\n", "utf-8");
43
+ return true;
44
+ } catch { return false; }
45
+ }
46
+
47
+ function runInit(targetDir, assets) {
48
+ let total = 0;
49
+
50
+ // .ciel/ state
51
+ mkdirSync(join(targetDir, ".ciel"), { recursive: true });
52
+ if (!existsSync(join(targetDir, ".ciel/map.json")))
53
+ writeFileSync(join(targetDir, ".ciel/map.json"), JSON.stringify({ modules: [], lastUpdated: "" }), "utf-8");
54
+ if (!existsSync(join(targetDir, ".ciel/parking.md")))
55
+ writeFileSync(join(targetDir, ".ciel/parking.md"), "# Ciel Parking Lot\n\n", "utf-8");
56
+
57
+ // OpenCode files
58
+ if (existsSync(join(targetDir, "opencode.json")) || existsSync(join(targetDir, ".opencode"))) {
59
+ // Clean old curl plugin
60
+ const old = join(targetDir, ".opencode/plugins/ciel.ts");
61
+ if (existsSync(old)) { try { unlinkSync(old); } catch {} }
62
+ // Copy agents
63
+ total += copyDir(join(assets, "platforms/opencode/.opencode/agents"), join(targetDir, ".opencode/agents"));
64
+ // Copy commands
65
+ total += copyDir(join(assets, "platforms/opencode/.opencode/commands"), join(targetDir, ".opencode/commands"));
66
+ // Copy AGENTS.md
67
+ if (existsSync(join(assets, "platforms/opencode/AGENTS.md"))) {
68
+ copyFileSync(join(assets, "platforms/opencode/AGENTS.md"), join(targetDir, "AGENTS.md"));
69
+ total++;
70
+ }
71
+ if (patchConfig(targetDir, assets)) total++;
72
+ console.error(` ${green("✓")} OpenCode: ${total} fichiers`);
73
+ }
74
+
75
+ // Claude Code files
76
+ if (existsSync(join(targetDir, ".claude/settings.json")) || existsSync(join(targetDir, ".claude"))) {
77
+ total += copyDir(join(assets, ".claude/agents"), join(targetDir, ".claude/agents"));
78
+ total += copyDir(join(assets, ".claude/hooks"), join(targetDir, ".claude/hooks"));
79
+ total += copyDir(join(assets, "commands"), join(targetDir, ".claude/commands"));
80
+ if (existsSync(join(assets, ".claude/settings.json"))) {
81
+ copyFileSync(join(assets, ".claude/settings.json"), join(targetDir, ".claude/settings.json"));
82
+ }
83
+ if (existsSync(join(assets, "CLAUDE.md"))) {
84
+ copyFileSync(join(assets, "CLAUDE.md"), join(targetDir, "CLAUDE.md"));
85
+ }
86
+ console.error(` ${green("✓")} Claude Code: ${total} fichiers`);
87
+ }
88
+
89
+ // Save version
90
+ writeFileSync(memPath, JSON.stringify({ cielVersion: CIEL_VERSION, lastUpdated: new Date().toISOString() }, null, 2), "utf-8");
91
+ return total;
92
+ }
93
+
94
+ const c = (code, s) => process.stderr.isTTY ? `\x1b[${code}m${s}\x1b[0m` : s;
95
+ const green = (s) => c(32, s);
96
+ const cyan = (s) => c(36, s);
97
+
98
+ if (needsInit) {
99
+ const args = process.argv.slice(2);
100
+ if (!args.includes("--help") && !args.includes("-h") && !args.includes("--version") && !args.includes("-v")) {
101
+ try {
102
+ const hasOC = existsSync(join(targetDir, "opencode.json")) || existsSync(join(targetDir, ".opencode"));
103
+ const hasClaude = existsSync(join(targetDir, ".claude/settings.json")) || existsSync(join(targetDir, ".claude"));
104
+ const hasOC_CLI = (() => { try { return execSync("opencode --version 2>&1", { stdio: "pipe", timeout: 3000 }).toString().length > 0; } catch { return false; } })();
105
+ const hasClaude_CLI = (() => { try { return execSync("claude --version 2>&1", { stdio: "pipe", timeout: 3000 }).toString().length > 0; } catch { return false; } })();
106
+
107
+ // Créer les configs si CLI détectée mais pas de fichier
108
+ if (hasOC_CLI && !hasOC) {
109
+ writeFileSync(join(targetDir, "opencode.json"), JSON.stringify({ $schema: "https://opencode.ai/config.json", plugin: ["@neikyun/ciel"] }, null, 2) + "\n", "utf-8");
110
+ }
111
+ if (hasClaude_CLI && !hasClaude) {
112
+ mkdirSync(join(targetDir, ".claude"), { recursive: true });
113
+ writeFileSync(join(targetDir, ".claude/settings.json"), "{}\n", "utf-8");
114
+ }
115
+
116
+ if (hasOC || hasClaude || hasOC_CLI || hasClaude_CLI) {
117
+ if (existsSync(ASSETS) && existsSync(join(ASSETS, "platforms/opencode/.opencode/agents/ciel.md"))) {
118
+ console.error(`\n ⚡ Ciel v${CIEL_VERSION} — Premier lancement, initialisation...`);
119
+ const n = runInit(targetDir, ASSETS);
120
+ console.error(` ${green("✓")} Ciel v${CIEL_VERSION} configuré (${n} fichiers)\n`);
121
+ }
122
+ }
123
+ } catch {}
124
+ }
125
+ }
126
+
127
+ // Lancer la CLI normalement
6
128
  require("../dist/cli/index.js");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neikyun/ciel",
3
- "version": "5.2.6",
3
+ "version": "5.2.8",
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",
@@ -33,6 +33,14 @@ function resolveAssets() {
33
33
  return null;
34
34
  }
35
35
 
36
+ function detectCLI(name) {
37
+ try {
38
+ const { execSync } = require("child_process");
39
+ const r = execSync(name + " --version 2>&1", { stdio: "pipe", timeout: 3000, encoding: "utf8" });
40
+ return r.length > 0 && !r.includes("not found");
41
+ } catch { return false; }
42
+ }
43
+
36
44
  // ---- Installation ----
37
45
  function copyDir(src, dest) {
38
46
  if (!existsSync(src)) return 0;
@@ -109,25 +117,55 @@ async function main() {
109
117
  }
110
118
 
111
119
  if (platforms.length === 0) {
112
- // Aucune plateforme détectée → proposer de créer opencode.json
113
- let creer = !process.stdin.isTTY; // auto en non-TTY
120
+ // Aucune plateforme détectée → chercher les CLIs installées
121
+ const hasOpenCode = detectCLI("opencode");
122
+ const hasClaude = detectCLI("claude");
123
+
124
+ if (!hasOpenCode && !hasClaude) {
125
+ console.error(` ${yellow("~")} Aucune plateforme détectée.`);
126
+ console.error(` Installez ${cyan("opencode")} ou ${cyan("claude")} puis relancez.`);
127
+ console.error(` Ou: ${green("npx ciel init")}\n`);
128
+ return;
129
+ }
130
+
131
+ // Proposer de configurer les CLIs détectées
132
+ let creer = !process.stdin.isTTY;
114
133
  if (process.stdin.isTTY) {
134
+ const detected = [hasOpenCode && "OpenCode", hasClaude && "Claude Code"].filter(Boolean).join(" + ");
115
135
  try {
116
136
  const readline = require("readline");
117
137
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
118
- creer = await new Promise(r => rl.question(` ${yellow("?")} Configurer Ciel pour OpenCode ? ${green("(Y/n)")} `, a => { rl.close(); r(a.trim().toLowerCase() !== "n"); }));
138
+ creer = await new Promise(r => rl.question(` ${yellow("?")} Configurer Ciel pour ${cyan(detected)} ? ${green("(Y/n)")} `, a => { rl.close(); r(a.trim().toLowerCase() !== "n"); }));
119
139
  } catch { creer = true; }
120
140
  }
121
- if (creer) {
122
- // Créer opencode.json
141
+
142
+ if (!creer) {
143
+ console.error(` ${cyan("→")} Annulé. Utilisez ${green("npx ciel init")} plus tard.\n`);
144
+ return;
145
+ }
146
+
147
+ // Configurer les plateformes détectées
148
+ if (hasOpenCode) {
123
149
  const cfgPath = join(targetDir, "opencode.json");
124
- const cfg = { $schema: "https://opencode.ai/config.json", plugin: ["@neikyun/ciel"] };
125
- writeFileSync(cfgPath, JSON.stringify(cfg, null, 2) + "\n", "utf-8");
126
- console.error(` ${green("✓")} opencode.json créé avec le plugin ${cyan("@neikyun/ciel")}`);
150
+ if (!existsSync(cfgPath)) {
151
+ const cfg = { $schema: "https://opencode.ai/config.json", plugin: ["@neikyun/ciel"] };
152
+ writeFileSync(cfgPath, JSON.stringify(cfg, null, 2) + "\n", "utf-8");
153
+ console.error(` ${green("✓")} opencode.json créé`);
154
+ }
127
155
  platforms.push("OpenCode");
128
- } else {
129
- console.error(` ${cyan("→")} Utilisez ${green("npx ciel init")} plus tard.\n`);
130
- return;
156
+ }
157
+
158
+ if (hasClaude) {
159
+ const claudeDir = join(targetDir, ".claude");
160
+ if (!existsSync(claudeDir)) {
161
+ mkdirSync(claudeDir, { recursive: true });
162
+ }
163
+ const settingsPath = join(claudeDir, "settings.json");
164
+ if (!existsSync(settingsPath)) {
165
+ writeFileSync(settingsPath, JSON.stringify({}, null, 2) + "\n", "utf-8");
166
+ console.error(` ${green("✓")} .claude/settings.json créé`);
167
+ }
168
+ platforms.push("Claude Code");
131
169
  }
132
170
  }
133
171