@neikyun/ciel 6.0.2 → 6.0.3
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/assets/dist/plugin/index.js +509 -0
- package/assets/platforms/opencode/.opencode/commands/ciel-update.md +43 -11
- package/dist/cli/check.d.ts.map +1 -1
- package/dist/cli/check.js +18 -9
- package/dist/cli/check.js.map +1 -1
- package/dist/cli/index.js +2 -2
- package/dist/cli/opencode.d.ts.map +1 -1
- package/dist/cli/opencode.js +43 -11
- package/dist/cli/opencode.js.map +1 -1
- package/package.json +2 -2
- package/scripts/postinstall.cjs +16 -7
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Ciel -- OpenCode plugin (v6.0.0)
|
|
3
|
+
// Full 16-step pipeline: DOCS -> QUOI -> ASK -> AVEC QUOI -> DIVERGE
|
|
4
|
+
// -> RECHERCHE -> SECURITE -> CODEBASE -> EVALUER -> ASK2
|
|
5
|
+
// -> FAIRE -> ADR -> RELIRE -> PROUVER -> MEMOIRE -> META
|
|
6
|
+
//
|
|
7
|
+
// Injection model:
|
|
8
|
+
// - shell.env -> inject CIEL_SESSION_ID, CIEL_DEPTH, CIEL_MODE
|
|
9
|
+
// - experimental.chat.system.transform -> CIEL WORKFLOW v6 + overlay + state
|
|
10
|
+
// - experimental.chat.messages.transform -> depth classification
|
|
11
|
+
// - session.* events -> tracking, META-CRITIQUER, RELIRE reminders
|
|
12
|
+
// - tool.execute.before -> FAIRE gates reminder + critical file detection
|
|
13
|
+
// - tool.execute.after -> file tracking + RELIRE trigger + map update
|
|
14
|
+
// - experimental.session.compacting -> persist learnings + map
|
|
15
|
+
// - tool helper -> custom ciel-status tool
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
const plugin_1 = require("@opencode-ai/plugin");
|
|
18
|
+
const fs_1 = require("fs");
|
|
19
|
+
const path_1 = require("path");
|
|
20
|
+
// ----- Constants -----
|
|
21
|
+
const CODE_EXT_RE = /\.(kt|java|ts|tsx|js|jsx|py|go|rs|rb|php|cs|cpp|c|swift|scala|vue|svelte|sql)$/i;
|
|
22
|
+
const TEST_FILE_RE = /(\.test\.|\.spec\.|_test\.|_spec\.)(ts|tsx|js|jsx|py|go|rs|rb|php|cs|cpp|c|swift|scala|vue|svelte)$/i;
|
|
23
|
+
const CRITICAL_FILE_RE = /(auth|Auth|security|Security|Route|Service|Controller|Repository|Gateway|Middleware|Proxy|Token|Session|Password|Secret|Payment|Account|Credential)/;
|
|
24
|
+
const CRITICAL_KEYWORD_RE = /\b(auth|authenti|author|jwt|oauth|password|secret|token|session|payment|credit.card|migration.*schema|2fa|mfa|encryption|credential|cookie.*security)\b/i;
|
|
25
|
+
const TRIVIAL_KEYWORD_RE = /\b(rename|typo|copyright|comment|readme|1-line|one.line|fix.typo|spelling)\b/i;
|
|
26
|
+
const CIEL_DIR = ".ciel";
|
|
27
|
+
const MAP_FILE = (0, path_1.join)(CIEL_DIR, "map.json");
|
|
28
|
+
const PARKING_FILE = (0, path_1.join)(CIEL_DIR, "parking.md");
|
|
29
|
+
const LEARNINGS_FILE = (0, path_1.join)(CIEL_DIR, "learnings.md");
|
|
30
|
+
const EXPLORATION_FLAG = (0, path_1.join)(CIEL_DIR, "exploration.active");
|
|
31
|
+
const MEMORY_FILE = (0, path_1.join)(CIEL_DIR, "memory.json");
|
|
32
|
+
// ----- V5 WORKFLOW INJECTION -----
|
|
33
|
+
const CIEL_WORKFLOW_INSTRUCTION = `
|
|
34
|
+
Every response MUST start with depth classification. Then follow the matching pipeline.
|
|
35
|
+
|
|
36
|
+
CLASSIFY: Trivial / Standard / Critical / Spike
|
|
37
|
+
|
|
38
|
+
| Depth | Pipeline |
|
|
39
|
+
|-------|----------|
|
|
40
|
+
| Standard/Critical | DOCS -> QUOI -> ASK -> AVEC QUOI -> DIVERGE -> RECHERCHE -> SECURITE -> CODEBASE -> EVALUER -> ASK2 -> FAIRE -> ADR -> RELIRE -> PROUVER -> MEMOIRE -> META |
|
|
41
|
+
| Trivial | QUOI -> FAIRE -> META |
|
|
42
|
+
| Spike | QUOI -> ASK -> AVEC QUOI -> DIVERGE -> FAIRE (relaxed) -> META |
|
|
43
|
+
|
|
44
|
+
USE the question tool for ASK/ASK2. NEVER skip steps. NEVER code on assumptions.
|
|
45
|
+
`;
|
|
46
|
+
const FAIRE_BEFORE_REMINDER = `
|
|
47
|
+
[CIEL FAIRE GATES -- BEFORE WRITE/EDIT]
|
|
48
|
+
Before executing this write/edit, verify:
|
|
49
|
+
1. TEST-FIRST (RED): Have you written tests FIRST? If this is source code, a corresponding test file must exist or be created first.
|
|
50
|
+
2. ALTERNATIVES: Can you justify X over Y? (comment or commit message)
|
|
51
|
+
3. IDIOMATIC: Are you using the framework's idiomatic pattern? If bypassing, justify why.
|
|
52
|
+
4. QUALITY: complexity < 15, nesting < 4, functions < 50 lines
|
|
53
|
+
5. REMOVAL: If deleting code -- who uses it? What replaces it? What degrades?
|
|
54
|
+
6. BOY-SCOUT: Did you leave the code better than you found it?
|
|
55
|
+
`;
|
|
56
|
+
const META_CRITIQUER = `
|
|
57
|
+
[CIEL META-CRITIQUER -- 30s POST-TASK REFLECTION]
|
|
58
|
+
After completing the task, reflect on:
|
|
59
|
+
(1) Depth match -- etait-ce Trivial/Standard/Critical/Spike correct ?
|
|
60
|
+
(2) Failure mode -- nouveau mode d'echec decouvert ?
|
|
61
|
+
(3) User correction -- l'utilisateur a-t-il corrige quelque chose ? -> persist dans learnings
|
|
62
|
+
(4) Stale branches -- branches a nettoyer ?
|
|
63
|
+
(5) Uncovered issues -- problemes non resolus ?
|
|
64
|
+
(6) Context health -- suggerer /compact si > 50% ?
|
|
65
|
+
(7) Dead code -- code mort introduit ?
|
|
66
|
+
(8) Map update -- la carte du projet (.ciel/map.json) est-elle a jour ?
|
|
67
|
+
(9) Parking -- y a-t-il des decouvertes fortuites a noter dans .ciel/parking.md ?
|
|
68
|
+
(10) Boy-scout -- le code est-il meilleur qu'avant ?
|
|
69
|
+
`;
|
|
70
|
+
// ----- Helpers -----
|
|
71
|
+
function getTestPathForSource(sourcePath) {
|
|
72
|
+
const base = (0, path_1.basename)(sourcePath);
|
|
73
|
+
const dir = (0, path_1.dirname)(sourcePath);
|
|
74
|
+
const nameWithoutExt = base.replace(/\.[^.]+$/, "");
|
|
75
|
+
const ext = base.match(/\.[^.]+$/)?.[0] ?? "";
|
|
76
|
+
const candidates = [
|
|
77
|
+
(0, path_1.join)(dir, `${nameWithoutExt}.test${ext}`),
|
|
78
|
+
(0, path_1.join)(dir, `${nameWithoutExt}.spec${ext}`),
|
|
79
|
+
(0, path_1.join)(dir, `${nameWithoutExt}_test${ext}`),
|
|
80
|
+
(0, path_1.join)(dir, `${nameWithoutExt}_spec${ext}`),
|
|
81
|
+
(0, path_1.join)(dir, "__tests__", `${nameWithoutExt}${ext}`),
|
|
82
|
+
(0, path_1.join)(dir, "test", `${nameWithoutExt}${ext}`),
|
|
83
|
+
(0, path_1.join)(dir, "tests", `${nameWithoutExt}${ext}`),
|
|
84
|
+
];
|
|
85
|
+
if (ext === ".ts" || ext === ".tsx") {
|
|
86
|
+
candidates.push((0, path_1.join)(dir, `${nameWithoutExt}.test.js`));
|
|
87
|
+
candidates.push((0, path_1.join)(dir, `${nameWithoutExt}.spec.js`));
|
|
88
|
+
}
|
|
89
|
+
return candidates;
|
|
90
|
+
}
|
|
91
|
+
function sourceFileHasTest(sourcePath) {
|
|
92
|
+
const candidates = getTestPathForSource(sourcePath);
|
|
93
|
+
for (const candidate of candidates) {
|
|
94
|
+
if ((0, fs_1.existsSync)(candidate))
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
function isTestFile(filePath) {
|
|
100
|
+
return TEST_FILE_RE.test(filePath);
|
|
101
|
+
}
|
|
102
|
+
function isSourceFile(filePath) {
|
|
103
|
+
return CODE_EXT_RE.test(filePath) && !isTestFile(filePath);
|
|
104
|
+
}
|
|
105
|
+
function isSpikeMode() {
|
|
106
|
+
return (0, fs_1.existsSync)(EXPLORATION_FLAG);
|
|
107
|
+
}
|
|
108
|
+
function ensureCielDir() {
|
|
109
|
+
if (!(0, fs_1.existsSync)(CIEL_DIR)) {
|
|
110
|
+
(0, fs_1.mkdirSync)(CIEL_DIR, { recursive: true });
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function writeParkingEntry(entry) {
|
|
114
|
+
ensureCielDir();
|
|
115
|
+
const timestamp = new Date().toISOString().split("T")[0];
|
|
116
|
+
const formatted = `- [${timestamp}] ${entry}\n`;
|
|
117
|
+
try {
|
|
118
|
+
const existing = (0, fs_1.existsSync)(PARKING_FILE) ? (0, fs_1.readFileSync)(PARKING_FILE, "utf-8") : "";
|
|
119
|
+
const header = "# Ciel Parking Lot -- Decouvertes fortuites\n\n";
|
|
120
|
+
const content = existing.startsWith("#") ? existing : header + existing;
|
|
121
|
+
(0, fs_1.writeFileSync)(PARKING_FILE, content + formatted, "utf-8");
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
// silent
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// ----- Plugin -----
|
|
128
|
+
const ciel = async ({ client }) => {
|
|
129
|
+
const writtenFiles = new Set();
|
|
130
|
+
const MAX_TRACKED_FILES = 100;
|
|
131
|
+
let relireSticky = false;
|
|
132
|
+
let lastDepthHint = null;
|
|
133
|
+
let overlayContent = null;
|
|
134
|
+
let faireBlocked = null;
|
|
135
|
+
let sessionId = "unknown";
|
|
136
|
+
let taskCount = 0;
|
|
137
|
+
let readDocsAttempted = false;
|
|
138
|
+
let askWindowUsed = false;
|
|
139
|
+
return {
|
|
140
|
+
// ----- CUSTOM TOOLS -----
|
|
141
|
+
tool: {
|
|
142
|
+
"ciel-status": (0, plugin_1.tool)({
|
|
143
|
+
description: "Shows current Ciel session state: depth classification, files changed, RELIRE status, FAIRE gate state, spike mode. Use when user asks 'what is the Ciel status' or 'show Ciel state'.",
|
|
144
|
+
args: {},
|
|
145
|
+
async execute(_args, _context) {
|
|
146
|
+
const changed = Array.from(writtenFiles);
|
|
147
|
+
return JSON.stringify({
|
|
148
|
+
sessionId,
|
|
149
|
+
depthHint: lastDepthHint,
|
|
150
|
+
filesChanged: changed.length,
|
|
151
|
+
files: changed.slice(0, 10),
|
|
152
|
+
relireRequired: relireSticky,
|
|
153
|
+
spikeMode: isSpikeMode(),
|
|
154
|
+
taskCount,
|
|
155
|
+
askWindowUsed,
|
|
156
|
+
readDocsAttempted,
|
|
157
|
+
faireBlocked: faireBlocked ? {
|
|
158
|
+
file: faireBlocked.filePath,
|
|
159
|
+
gate: faireBlocked.gate,
|
|
160
|
+
} : null,
|
|
161
|
+
overlayLoaded: overlayContent != null,
|
|
162
|
+
}, null, 2);
|
|
163
|
+
},
|
|
164
|
+
}),
|
|
165
|
+
},
|
|
166
|
+
// ----- SHELL ENV -----
|
|
167
|
+
"shell.env": async (_input, output) => {
|
|
168
|
+
output.env.CIEL_SESSION_ID = sessionId;
|
|
169
|
+
output.env.CIEL_DEPTH = lastDepthHint ?? "unclassified";
|
|
170
|
+
output.env.CIEL_MODE = isSpikeMode() ? "spike" : "standard";
|
|
171
|
+
},
|
|
172
|
+
// ----- EVENTS -----
|
|
173
|
+
event: async ({ event }) => {
|
|
174
|
+
// Log all event types for debugging session ID detection
|
|
175
|
+
if (event.type && !event.type.startsWith("tool.") && event.type !== "session.diff") {
|
|
176
|
+
await client.app.log({
|
|
177
|
+
body: { service: "ciel", level: "debug", message: `Event: ${event.type}` },
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
if (event.type === "session.created" || event.type === "session.updated" || event.type === "session.status") {
|
|
181
|
+
// Try multiple locations for session ID
|
|
182
|
+
const evt = event;
|
|
183
|
+
const rawId = evt?.info?.id ?? evt?.sessionID ?? evt?.sessionId ?? evt?.id ?? evt?.session?.id ?? `s-${Date.now().toString(36)}`;
|
|
184
|
+
sessionId = typeof rawId === "string" ? rawId.slice(0, 8) : "unknown";
|
|
185
|
+
taskCount = 0;
|
|
186
|
+
}
|
|
187
|
+
// Always ensure .ciel/ directory exists (runs on ANY session event)
|
|
188
|
+
if (event.type === "session.created" || event.type === "session.updated" || event.type === "session.status" || event.type === "session.diff") {
|
|
189
|
+
// Initialize .ciel/ directory if missing
|
|
190
|
+
ensureCielDir();
|
|
191
|
+
if (!(0, fs_1.existsSync)(MAP_FILE)) {
|
|
192
|
+
(0, fs_1.writeFileSync)(MAP_FILE, JSON.stringify({ modules: [], lastUpdated: new Date().toISOString() }, null, 2), "utf-8");
|
|
193
|
+
}
|
|
194
|
+
if (!(0, fs_1.existsSync)(MEMORY_FILE)) {
|
|
195
|
+
(0, fs_1.writeFileSync)(MEMORY_FILE, "{}", "utf-8");
|
|
196
|
+
}
|
|
197
|
+
if (!(0, fs_1.existsSync)(PARKING_FILE)) {
|
|
198
|
+
(0, fs_1.writeFileSync)(PARKING_FILE, "# Ciel Parking Lot -- Decouvertes fortuites\n\n", "utf-8");
|
|
199
|
+
}
|
|
200
|
+
await client.app.log({
|
|
201
|
+
body: { service: "ciel", level: "info", message: `Session ${sessionId} started` },
|
|
202
|
+
});
|
|
203
|
+
// Load overlay
|
|
204
|
+
if ((0, fs_1.existsSync)("./ciel-overlay.md")) {
|
|
205
|
+
try {
|
|
206
|
+
const rawOverlay = (0, fs_1.readFileSync)("./ciel-overlay.md", "utf-8");
|
|
207
|
+
overlayContent = rawOverlay.replace(/##\s*\S*sensitive[:\s]*true\S*\s*\n([\s\S]*?)(?=\n##\s|\n*$)/gi, "## [REDACTED -- sensitive section]\n");
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
// silent
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
writtenFiles.clear();
|
|
214
|
+
relireSticky = false;
|
|
215
|
+
lastDepthHint = null;
|
|
216
|
+
faireBlocked = null;
|
|
217
|
+
readDocsAttempted = false;
|
|
218
|
+
askWindowUsed = false;
|
|
219
|
+
}
|
|
220
|
+
if (event.type === "session.diff") {
|
|
221
|
+
const diffs = event.diff ?? [];
|
|
222
|
+
for (const fileDiff of diffs) {
|
|
223
|
+
const path = fileDiff?.path ?? "";
|
|
224
|
+
if (CODE_EXT_RE.test(path)) {
|
|
225
|
+
if (writtenFiles.size >= MAX_TRACKED_FILES) {
|
|
226
|
+
const firstKey = writtenFiles.values().next().value;
|
|
227
|
+
writtenFiles.delete(firstKey);
|
|
228
|
+
}
|
|
229
|
+
writtenFiles.add(path);
|
|
230
|
+
if (writtenFiles.size >= 5 || CRITICAL_FILE_RE.test(path)) {
|
|
231
|
+
relireSticky = true;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
if (event.type === "session.idle") {
|
|
237
|
+
taskCount++;
|
|
238
|
+
lastDepthHint = `CIEL STOP -- META-CRITIQUER: (1) depth match? (2) failure mode? (3) user correction -> learnings? (4) stale branches? (8) map update? (9) parking note?`;
|
|
239
|
+
relireSticky = true;
|
|
240
|
+
faireBlocked = null;
|
|
241
|
+
}
|
|
242
|
+
if (event.type === "session.deleted") {
|
|
243
|
+
const rawId = event.sessionID ?? event.info?.id ?? "unknown";
|
|
244
|
+
const sid = typeof rawId === "string" ? rawId.slice(0, 8) : "unknown";
|
|
245
|
+
const isChild = event.parentSessionId != null;
|
|
246
|
+
await client.app.log({
|
|
247
|
+
body: { service: "ciel", level: "info", message: `Session ${sid} deleted${isChild ? " (subagent child)" : ""}` },
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
if (event.type === "session.error") {
|
|
251
|
+
const errorName = event.error?.name ?? "UnknownError";
|
|
252
|
+
const errorMessage = event.error?.message ?? "";
|
|
253
|
+
if (errorName === "ProviderAuthError" || errorName === "MessageAbortedError") {
|
|
254
|
+
await client.app.log({
|
|
255
|
+
body: { service: "ciel", level: "error", message: `${errorName}: ${errorMessage}` },
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
if (event.type === "session.compacted") {
|
|
260
|
+
await client.app.log({
|
|
261
|
+
body: { service: "ciel", level: "info", message: `Session ${sessionId} compacted -- state preserved` },
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
// ----- SYSTEM TRANSFORM -----
|
|
266
|
+
"experimental.chat.system.transform": async (_input, output) => {
|
|
267
|
+
if (!Array.isArray(output?.system))
|
|
268
|
+
return;
|
|
269
|
+
// Mandatory workflow injection (first -- highest priority)
|
|
270
|
+
output.system.push(CIEL_WORKFLOW_INSTRUCTION);
|
|
271
|
+
// Overlay injection
|
|
272
|
+
if (overlayContent) {
|
|
273
|
+
output.system.push(`Project Overlay:\n${overlayContent}`);
|
|
274
|
+
}
|
|
275
|
+
// Load .ciel/map.json if it exists
|
|
276
|
+
if ((0, fs_1.existsSync)(MAP_FILE)) {
|
|
277
|
+
try {
|
|
278
|
+
const mapContent = (0, fs_1.readFileSync)(MAP_FILE, "utf-8");
|
|
279
|
+
output.system.push(`Project Map (.ciel/map.json):\n${mapContent}`);
|
|
280
|
+
}
|
|
281
|
+
catch {
|
|
282
|
+
// silent
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
// Load .ciel/memory.json if it exists
|
|
286
|
+
if ((0, fs_1.existsSync)(MEMORY_FILE)) {
|
|
287
|
+
try {
|
|
288
|
+
const memoryContent = (0, fs_1.readFileSync)(MEMORY_FILE, "utf-8");
|
|
289
|
+
output.system.push(`Session Memory (.ciel/memory.json):\n${memoryContent}`);
|
|
290
|
+
}
|
|
291
|
+
catch {
|
|
292
|
+
// silent
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
// SPIKE mode indicator
|
|
296
|
+
if (isSpikeMode()) {
|
|
297
|
+
output.system.push("[CIEL SPIKE MODE] Exploration/prototype mode active. Quality gates are ASSOUPLIES.\n" +
|
|
298
|
+
"This code is experimental. FIXME/TODO markers required. Must be refactored properly after.\n" +
|
|
299
|
+
"To exit spike mode, remove .ciel/exploration.active");
|
|
300
|
+
}
|
|
301
|
+
// Depth hint
|
|
302
|
+
if (lastDepthHint) {
|
|
303
|
+
output.system.push(lastDepthHint);
|
|
304
|
+
}
|
|
305
|
+
// META-CRITIQUER always injected
|
|
306
|
+
output.system.push(META_CRITIQUER);
|
|
307
|
+
// FAIRE gate blocked
|
|
308
|
+
if (faireBlocked) {
|
|
309
|
+
output.system.push(`[CIEL FAIRE GATE TRIGGERED] You just wrote ${faireBlocked.filePath} without a corresponding test file.\n\n` +
|
|
310
|
+
`This means you skipped the Ciel workflow. You MUST now:\n` +
|
|
311
|
+
`1. Classify depth (Trivial/Standard/Critical/Spike)\n` +
|
|
312
|
+
`2. Follow the pipeline: DOCS -> QUOI -> ASK -> AVEC QUOI -> ... -> FAIRE -> RELIRE -> PROUVER -> MEMOIRE -> META\n` +
|
|
313
|
+
`3. Dispatch subagents if required (@ciel-researcher, @ciel-explorer)\n` +
|
|
314
|
+
`4. Write the test file FIRST, then implement\n\n` +
|
|
315
|
+
`Candidates checked: ${faireBlocked.candidates.slice(0, 3).join(", ")}\n\n` +
|
|
316
|
+
`Do NOT continue writing source code until tests exist. Follow the full Ciel pipeline.`);
|
|
317
|
+
}
|
|
318
|
+
// RELIRE sticky notice
|
|
319
|
+
if (relireSticky) {
|
|
320
|
+
const changed = Array.from(writtenFiles);
|
|
321
|
+
output.system.push(`[CIEL RELIRE REQUIRED] ${changed.length} files changed. Dispatch @ciel-critic MODE=RELIRE -- 3 RISQUES + FIX/ACCEPT/DEFER.`);
|
|
322
|
+
}
|
|
323
|
+
},
|
|
324
|
+
// ----- MESSAGES TRANSFORM (depth classification) -----
|
|
325
|
+
// Read the most recent user message and classify depth.
|
|
326
|
+
// Does NOT modify the messages array -- splicing synthetic messages
|
|
327
|
+
// causes "U.parts.length undefined" crashes in the OpenCode SDK
|
|
328
|
+
// (the injected message lacks the expected message shape).
|
|
329
|
+
// Depth hints are injected via experimental.chat.system.transform instead.
|
|
330
|
+
"experimental.chat.messages.transform": async (_input, output) => {
|
|
331
|
+
const msgs = output?.messages;
|
|
332
|
+
if (!Array.isArray(msgs) || msgs.length === 0)
|
|
333
|
+
return;
|
|
334
|
+
// Find the most recent user text part.
|
|
335
|
+
let prompt = "";
|
|
336
|
+
for (let i = msgs.length - 1; i >= 0 && !prompt; i--) {
|
|
337
|
+
const m = msgs[i];
|
|
338
|
+
if (m?.info?.role !== "user")
|
|
339
|
+
continue;
|
|
340
|
+
const parts = m?.parts;
|
|
341
|
+
if (!Array.isArray(parts))
|
|
342
|
+
continue;
|
|
343
|
+
for (let j = parts.length - 1; j >= 0; j--) {
|
|
344
|
+
const p = parts[j];
|
|
345
|
+
if (p?.type === "text" && typeof p.text === "string") {
|
|
346
|
+
prompt = p.text;
|
|
347
|
+
break;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
if (!prompt)
|
|
352
|
+
return;
|
|
353
|
+
let depth = null;
|
|
354
|
+
let reason = "";
|
|
355
|
+
if (CRITICAL_KEYWORD_RE.test(prompt)) {
|
|
356
|
+
depth = "Critical";
|
|
357
|
+
reason = "auth/security/payment keyword detected";
|
|
358
|
+
}
|
|
359
|
+
else if (TRIVIAL_KEYWORD_RE.test(prompt)) {
|
|
360
|
+
depth = "Trivial";
|
|
361
|
+
reason = "rename/typo/docs keyword detected";
|
|
362
|
+
}
|
|
363
|
+
lastDepthHint = depth
|
|
364
|
+
? `[CIEL] Depth: ${depth} (${reason}). Route the pipeline accordingly.`
|
|
365
|
+
: null;
|
|
366
|
+
},
|
|
367
|
+
// ----- COMPACTING (cross-session memory -- persist automatically) -----
|
|
368
|
+
"experimental.session.compacting": async (_input, output) => {
|
|
369
|
+
// Persist .ciel/memory.json with current state
|
|
370
|
+
try {
|
|
371
|
+
ensureCielDir();
|
|
372
|
+
const memory = {
|
|
373
|
+
sessionId,
|
|
374
|
+
depthHint: lastDepthHint,
|
|
375
|
+
filesChanged: Array.from(writtenFiles).slice(-20),
|
|
376
|
+
taskCount,
|
|
377
|
+
timestamp: new Date().toISOString(),
|
|
378
|
+
};
|
|
379
|
+
(0, fs_1.writeFileSync)(MEMORY_FILE, JSON.stringify(memory, null, 2), "utf-8");
|
|
380
|
+
}
|
|
381
|
+
catch {
|
|
382
|
+
// silent
|
|
383
|
+
}
|
|
384
|
+
// Inject context for the LLM to update learnings, map, and parking
|
|
385
|
+
output.context.push("CIEL PRE-COMPACT -- Persist if needed: (1) user corrections -> .ciel/learnings.md, " +
|
|
386
|
+
"(2) project map updates -> .ciel/map.json, " +
|
|
387
|
+
"(3) fortuitous discoveries -> .ciel/parking.md. " +
|
|
388
|
+
"Memory already saved at .ciel/memory.json");
|
|
389
|
+
},
|
|
390
|
+
// ----- BEFORE HOOK -- FAIRE gates -----
|
|
391
|
+
"tool.execute.before": async (input, output) => {
|
|
392
|
+
if (!["write", "edit"].includes(input.tool))
|
|
393
|
+
return;
|
|
394
|
+
const filePath = output?.args?.filePath ?? "";
|
|
395
|
+
if (!filePath || !CODE_EXT_RE.test(filePath))
|
|
396
|
+
return;
|
|
397
|
+
// Skip for the plugin itself and test files
|
|
398
|
+
if (filePath.includes("ciel.ts") || isTestFile(filePath))
|
|
399
|
+
return;
|
|
400
|
+
// Gate 1: TEST-FIRST (RED) -- only block if NOT in SPIKE mode
|
|
401
|
+
if (isSourceFile(filePath) && !sourceFileHasTest(filePath) && !isSpikeMode()) {
|
|
402
|
+
const testCandidates = getTestPathForSource(filePath);
|
|
403
|
+
faireBlocked = { filePath, gate: "test-first", candidates: testCandidates };
|
|
404
|
+
}
|
|
405
|
+
else {
|
|
406
|
+
faireBlocked = null;
|
|
407
|
+
}
|
|
408
|
+
// Gate 2: CRITICAL FILE WARNING
|
|
409
|
+
if (CRITICAL_FILE_RE.test(filePath)) {
|
|
410
|
+
await client.app.log({
|
|
411
|
+
body: { service: "ciel", level: "warn", message: `CRITICAL FILE: ${filePath} -- stride-analyzer + security-regression-check required` },
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
// Gate 3: PARKING LOT -- detect if this is a tangential discovery
|
|
415
|
+
if (filePath.includes("parking") || filePath.includes("FIXME") || filePath.includes("TODO")) {
|
|
416
|
+
writeParkingEntry(`Tangential file noted during task: ${filePath}`);
|
|
417
|
+
}
|
|
418
|
+
// Inject FAIRE reminder into the tool output
|
|
419
|
+
const faireReminder = FAIRE_BEFORE_REMINDER.trim();
|
|
420
|
+
if (typeof output?.output === "string") {
|
|
421
|
+
output.output = faireReminder + "\n" + output.output;
|
|
422
|
+
}
|
|
423
|
+
else if (output) {
|
|
424
|
+
output.output = faireReminder;
|
|
425
|
+
}
|
|
426
|
+
},
|
|
427
|
+
// ----- AFTER HOOK -- file tracking + map update -----
|
|
428
|
+
"tool.execute.after": async (input, output) => {
|
|
429
|
+
const toolName = input?.tool ?? "";
|
|
430
|
+
// Track ASK window usage for any question tool call
|
|
431
|
+
if (toolName === "question") {
|
|
432
|
+
askWindowUsed = true;
|
|
433
|
+
return; // question tool has no file path, nothing else to do
|
|
434
|
+
}
|
|
435
|
+
// Only process write/edit tools for file tracking
|
|
436
|
+
if (!["write", "edit"].includes(toolName))
|
|
437
|
+
return;
|
|
438
|
+
const filePath = output?.metadata?.filepath ??
|
|
439
|
+
output?.metadata?.filediff?.file ??
|
|
440
|
+
output?.args?.filePath ??
|
|
441
|
+
"";
|
|
442
|
+
if (!filePath || !CODE_EXT_RE.test(filePath))
|
|
443
|
+
return;
|
|
444
|
+
if (writtenFiles.size >= MAX_TRACKED_FILES) {
|
|
445
|
+
const firstKey = writtenFiles.values().next().value;
|
|
446
|
+
writtenFiles.delete(firstKey);
|
|
447
|
+
}
|
|
448
|
+
writtenFiles.add(filePath);
|
|
449
|
+
if (writtenFiles.size >= 5 || CRITICAL_FILE_RE.test(filePath)) {
|
|
450
|
+
relireSticky = true;
|
|
451
|
+
}
|
|
452
|
+
const isCritical = CRITICAL_FILE_RE.test(filePath);
|
|
453
|
+
const spike = isSpikeMode();
|
|
454
|
+
const reminder = isCritical
|
|
455
|
+
? `\n\n[CIEL CRITIQUE] ${filePath} -- FAIRE gates + stride-analyzer + test-first (RED). Dispatch @ciel-critic MODE=RELIRE.`
|
|
456
|
+
: spike
|
|
457
|
+
? `\n\n[CIEL SPIKE] ${filePath} -- gates assouplies. Marquer comme experimental (FIXME/TODO).`
|
|
458
|
+
: `\n\n[CIEL] ${filePath} -- FAIRE gates: alternatives, idiomatic, test-first, boy-scout.`;
|
|
459
|
+
if (typeof output?.output === "string") {
|
|
460
|
+
output.output += reminder;
|
|
461
|
+
}
|
|
462
|
+
else if (output) {
|
|
463
|
+
output.output = reminder.trimStart();
|
|
464
|
+
}
|
|
465
|
+
// Track DOCS phase attempt
|
|
466
|
+
if (!readDocsAttempted && (filePath.endsWith("README.md") || filePath.endsWith("AGENTS.md") || filePath.endsWith("CLAUDE.md") || filePath.includes("ciel-overlay") || filePath.endsWith("docs/"))) {
|
|
467
|
+
readDocsAttempted = true;
|
|
468
|
+
}
|
|
469
|
+
// Update .ciel/map.json with modules discovered during exploration
|
|
470
|
+
if (filePath.endsWith(".ts") || filePath.endsWith(".tsx") || filePath.endsWith(".js") || filePath.endsWith(".py") || filePath.endsWith(".go") || filePath.endsWith(".rs")) {
|
|
471
|
+
try {
|
|
472
|
+
ensureCielDir();
|
|
473
|
+
let map = { modules: [], lastUpdated: new Date().toISOString() };
|
|
474
|
+
if ((0, fs_1.existsSync)(MAP_FILE)) {
|
|
475
|
+
map = JSON.parse((0, fs_1.readFileSync)(MAP_FILE, "utf-8"));
|
|
476
|
+
}
|
|
477
|
+
// Simple heuristic: the directory 2 levels deep is a module
|
|
478
|
+
const parts = filePath.replace(/^\.\//, "").split("/");
|
|
479
|
+
if (parts.length >= 2) {
|
|
480
|
+
const moduleName = parts[parts.length - 2];
|
|
481
|
+
const existingModule = map.modules?.find((m) => m.name === moduleName);
|
|
482
|
+
if (!existingModule) {
|
|
483
|
+
map.modules = map.modules || [];
|
|
484
|
+
map.modules.push({
|
|
485
|
+
name: moduleName,
|
|
486
|
+
path: parts.slice(0, -1).join("/"),
|
|
487
|
+
key_files: [{ path: filePath, responsibility: "auto-detected" }],
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
else {
|
|
491
|
+
const existingFile = existingModule.key_files?.find((f) => f.path === filePath);
|
|
492
|
+
if (!existingFile) {
|
|
493
|
+
existingModule.key_files = existingModule.key_files || [];
|
|
494
|
+
existingModule.key_files.push({ path: filePath, responsibility: "auto-detected" });
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
map.lastUpdated = new Date().toISOString();
|
|
498
|
+
(0, fs_1.writeFileSync)(MAP_FILE, JSON.stringify(map, null, 2), "utf-8");
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
catch {
|
|
502
|
+
// silent
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
},
|
|
506
|
+
};
|
|
507
|
+
};
|
|
508
|
+
exports.default = ciel;
|
|
509
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -1,18 +1,50 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
description: Update Ciel to the latest version
|
|
4
|
-
subtask: false
|
|
2
|
+
description: Update Ciel to the latest version via NPM. Checks NPM registry, updates global package, force-reinstalls in project.
|
|
5
3
|
---
|
|
6
4
|
|
|
7
|
-
# /ciel-update — Update Ciel
|
|
5
|
+
# /ciel-update — Update Ciel to the latest version
|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
## Steps
|
|
10
8
|
|
|
11
|
-
|
|
9
|
+
### Global install (recommended)
|
|
12
10
|
|
|
13
|
-
|
|
11
|
+
```bash
|
|
12
|
+
# 1. Check
|
|
13
|
+
ciel check
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
# 2. Update global package
|
|
16
|
+
npm update -g @neikyun/ciel
|
|
17
|
+
|
|
18
|
+
# 3. Force reinstall in project (new plugin JS, agents, commands, hooks)
|
|
19
|
+
ciel update
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Project-local install
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm update @neikyun/ciel # postinstall auto-updates everything
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## What's preserved
|
|
29
|
+
|
|
30
|
+
- `ciel-overlay.md` — project-specific rules
|
|
31
|
+
- `.ciel/map.json`, `.ciel/memory.json`, `.ciel/parking.md` — persistent state
|
|
32
|
+
- `opencode.json` — existing config patched non-destructively
|
|
33
|
+
|
|
34
|
+
## What's replaced
|
|
35
|
+
|
|
36
|
+
- `.opencode/plugins/ciel.js` — compiled plugin
|
|
37
|
+
- `.opencode/agents/ciel-*.md` — agent definitions
|
|
38
|
+
- `.opencode/commands/ciel-*.md` — command files
|
|
39
|
+
- `.claude/agents/ciel-*.md` — Claude Code agents
|
|
40
|
+
- `.claude/hooks/*.sh` — shell hooks
|
|
41
|
+
- `CLAUDE.md` — root instruction
|
|
42
|
+
- `.claude/settings.json` — hook config
|
|
43
|
+
|
|
44
|
+
## Troubleshooting
|
|
45
|
+
|
|
46
|
+
| Symptom | Fix |
|
|
47
|
+
|---------|-----|
|
|
48
|
+
| Plugin not loaded after update | Restart OpenCode (plugin loaded at session start) |
|
|
49
|
+
| `ciel: command not found` | Reinstall globally: `npm install -g @neikyun/ciel` |
|
|
50
|
+
| NPM registry unreachable | Check internet or proxy: `HTTPS_PROXY=... ciel check` |
|
package/dist/cli/check.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/cli/check.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/cli/check.ts"],"names":[],"mappings":"AAsCA,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAuC9C"}
|
package/dist/cli/check.js
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// Check command — compare local version against
|
|
2
|
+
// Check command — compare local version against NPM registry
|
|
3
|
+
// (NPM is the canonical distribution channel for Ciel v6+)
|
|
3
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
5
|
exports.runCheck = runCheck;
|
|
5
6
|
const https_1 = require("https");
|
|
6
7
|
const utils_1 = require("./utils");
|
|
7
8
|
const version_1 = require("./version");
|
|
8
|
-
const
|
|
9
|
+
const NPM_REGISTRY = "https://registry.npmjs.org/@neikyun/ciel/latest";
|
|
9
10
|
const CIEL_VERSION = (0, version_1.getVersion)();
|
|
10
11
|
function fetchUrl(url) {
|
|
11
12
|
return new Promise((resolve, reject) => {
|
|
12
|
-
(0, https_1.get)(url, (res) => {
|
|
13
|
+
(0, https_1.get)(url, { headers: { Accept: "application/json" } }, (res) => {
|
|
13
14
|
let data = "";
|
|
14
15
|
res.on("data", (chunk) => (data += chunk));
|
|
15
|
-
res.on("end", () => resolve(data
|
|
16
|
+
res.on("end", () => resolve(data));
|
|
16
17
|
}).on("error", reject);
|
|
17
18
|
});
|
|
18
19
|
}
|
|
@@ -37,9 +38,11 @@ function compareVersions(a, b) {
|
|
|
37
38
|
}
|
|
38
39
|
async function runCheck() {
|
|
39
40
|
try {
|
|
40
|
-
const
|
|
41
|
+
const raw = await fetchUrl(NPM_REGISTRY);
|
|
42
|
+
const pkg = JSON.parse(raw);
|
|
43
|
+
const remoteVersion = pkg.version;
|
|
41
44
|
if (!remoteVersion) {
|
|
42
|
-
(0, utils_1.err)("Could not fetch
|
|
45
|
+
(0, utils_1.err)("Could not fetch latest version from NPM registry.");
|
|
43
46
|
(0, utils_1.err)("Check your internet connection.");
|
|
44
47
|
process.exit(2);
|
|
45
48
|
}
|
|
@@ -50,12 +53,18 @@ async function runCheck() {
|
|
|
50
53
|
}
|
|
51
54
|
if (cmp < 0) {
|
|
52
55
|
// Remote is newer
|
|
53
|
-
console.log(` Update available: v${CIEL_VERSION} → ${remoteVersion}`);
|
|
54
|
-
console.log("
|
|
56
|
+
console.log(` Update available: v${CIEL_VERSION} → v${remoteVersion}`);
|
|
57
|
+
console.log("");
|
|
58
|
+
console.log(" If installed globally:");
|
|
59
|
+
console.log(" npm update -g @neikyun/ciel");
|
|
60
|
+
console.log(" ciel update");
|
|
61
|
+
console.log("");
|
|
62
|
+
console.log(" If installed in project:");
|
|
63
|
+
console.log(" npm update @neikyun/ciel");
|
|
55
64
|
process.exit(0);
|
|
56
65
|
}
|
|
57
66
|
// Local is newer (dev mode)
|
|
58
|
-
(0, utils_1.say)(`Ciel v${CIEL_VERSION} (ahead of
|
|
67
|
+
(0, utils_1.say)(`Ciel v${CIEL_VERSION} (ahead of npm v${remoteVersion} — dev mode)`);
|
|
59
68
|
process.exit(0);
|
|
60
69
|
}
|
|
61
70
|
catch (error) {
|
package/dist/cli/check.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/cli/check.ts"],"names":[],"mappings":";AAAA,
|
|
1
|
+
{"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/cli/check.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/index.js
CHANGED
|
@@ -26,9 +26,9 @@ USAGE:
|
|
|
26
26
|
|
|
27
27
|
COMMANDS:
|
|
28
28
|
init Install Ciel in the current project (default)
|
|
29
|
-
update Force reinstall
|
|
29
|
+
update Force reinstall (run after npm update -g @neikyun/ciel)
|
|
30
30
|
uninstall Remove all Ciel files from the project
|
|
31
|
-
check Check
|
|
31
|
+
check Check NPM for a newer version
|
|
32
32
|
|
|
33
33
|
OPTIONS:
|
|
34
34
|
-y, --yes Skip confirmation prompt (non-interactive)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opencode.d.ts","sourceRoot":"","sources":["../../src/cli/opencode.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAKzD;
|
|
1
|
+
{"version":3,"file":"opencode.d.ts","sourceRoot":"","sources":["../../src/cli/opencode.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAKzD;AAsBD;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,eAAe,GAAG,aAAa,CAgGpE"}
|
package/dist/cli/opencode.js
CHANGED
|
@@ -14,6 +14,26 @@ function detectOpenCode(targetDir) {
|
|
|
14
14
|
return ((0, fs_1.existsSync)((0, path_1.join)(targetDir, "opencode.json")) ||
|
|
15
15
|
(0, fs_1.existsSync)((0, path_1.join)(targetDir, ".opencode")));
|
|
16
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Find the compiled plugin JS file from various install locations.
|
|
19
|
+
* Returns the absolute path to dist/plugin/index.js or null.
|
|
20
|
+
*/
|
|
21
|
+
function findPluginJs(srcDir) {
|
|
22
|
+
const candidates = [
|
|
23
|
+
// NPM local: node_modules/@neikyun/ciel/dist/plugin/index.js
|
|
24
|
+
(0, path_1.join)(srcDir, "dist/plugin/index.js"),
|
|
25
|
+
// NPM global: from assets/, go up to package root
|
|
26
|
+
(0, path_1.join)(srcDir, "..", "dist/plugin/index.js"),
|
|
27
|
+
(0, path_1.join)(srcDir, "../..", "dist/plugin/index.js"),
|
|
28
|
+
// Dev mode: from repo root
|
|
29
|
+
(0, path_1.join)(srcDir, "packages/ciel/dist/plugin/index.js"),
|
|
30
|
+
];
|
|
31
|
+
for (const candidate of candidates) {
|
|
32
|
+
if ((0, fs_1.existsSync)(candidate))
|
|
33
|
+
return candidate;
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
17
37
|
/**
|
|
18
38
|
* Install Ciel files for OpenCode platform.
|
|
19
39
|
*/
|
|
@@ -21,8 +41,6 @@ function installOpenCode(opts) {
|
|
|
21
41
|
const { targetDir, srcDir, force } = opts;
|
|
22
42
|
const installed = [];
|
|
23
43
|
const skipped = [];
|
|
24
|
-
const pluginSrc = (0, path_1.join)(srcDir, "platforms/opencode/.opencode/plugins/ciel.ts");
|
|
25
|
-
const pluginDest = (0, path_1.join)(targetDir, ".opencode/plugins/ciel.ts");
|
|
26
44
|
const agentsSrc = (0, path_1.join)(srcDir, "platforms/opencode/.opencode/agents");
|
|
27
45
|
const agentsDest = (0, path_1.join)(targetDir, ".opencode/agents");
|
|
28
46
|
const commandsSrc = (0, path_1.join)(srcDir, "platforms/opencode/.opencode/commands");
|
|
@@ -31,13 +49,25 @@ function installOpenCode(opts) {
|
|
|
31
49
|
(0, fs_1.mkdirSync)((0, path_1.join)(targetDir, ".opencode/plugins"), { recursive: true });
|
|
32
50
|
(0, fs_1.mkdirSync)(agentsDest, { recursive: true });
|
|
33
51
|
(0, fs_1.mkdirSync)(commandsDest, { recursive: true });
|
|
34
|
-
// Copy plugin
|
|
35
|
-
|
|
36
|
-
|
|
52
|
+
// Copy compiled plugin JS (self-contained, no node_modules needed)
|
|
53
|
+
const pluginJs = findPluginJs(srcDir);
|
|
54
|
+
if (pluginJs) {
|
|
55
|
+
const pluginDest = (0, path_1.join)(targetDir, ".opencode/plugins/ciel.js");
|
|
56
|
+
const action = copyIfNewer(pluginJs, pluginDest, force);
|
|
37
57
|
if (action === "copied")
|
|
38
|
-
installed.push(".opencode/plugins/ciel.
|
|
58
|
+
installed.push(".opencode/plugins/ciel.js");
|
|
39
59
|
else
|
|
40
|
-
skipped.push("plugin");
|
|
60
|
+
skipped.push("plugin.js");
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
// Fallback: try old .ts source (dev mode)
|
|
64
|
+
const pluginTs = (0, path_1.join)(srcDir, "platforms/opencode/.opencode/plugins/ciel.ts");
|
|
65
|
+
if ((0, fs_1.existsSync)(pluginTs)) {
|
|
66
|
+
const pluginTsDest = (0, path_1.join)(targetDir, ".opencode/plugins/ciel.ts");
|
|
67
|
+
const action = copyIfNewer(pluginTs, pluginTsDest, force);
|
|
68
|
+
if (action === "copied")
|
|
69
|
+
installed.push(".opencode/plugins/ciel.ts");
|
|
70
|
+
}
|
|
41
71
|
}
|
|
42
72
|
// Copy agents
|
|
43
73
|
const agentFiles = [
|
|
@@ -110,7 +140,7 @@ function generateOpencodeConfig(configPath) {
|
|
|
110
140
|
const config = {
|
|
111
141
|
$schema: "https://opencode.ai/config.json",
|
|
112
142
|
instructions: ["AGENTS.md"],
|
|
113
|
-
plugin: ["
|
|
143
|
+
plugin: ["./.opencode/plugins/ciel.js"],
|
|
114
144
|
permission: {
|
|
115
145
|
edit: "allow",
|
|
116
146
|
bash: "allow",
|
|
@@ -211,11 +241,13 @@ function patchOpencodeConfig(configPath) {
|
|
|
211
241
|
try {
|
|
212
242
|
const raw = (0, fs_1.readFileSync)(configPath, "utf-8");
|
|
213
243
|
const config = JSON.parse(raw);
|
|
214
|
-
// Ensure plugin array contains the Ciel plugin
|
|
244
|
+
// Ensure plugin array contains the local Ciel plugin
|
|
215
245
|
if (!config.plugin)
|
|
216
246
|
config.plugin = [];
|
|
217
|
-
|
|
218
|
-
|
|
247
|
+
// Replace old npm reference with local path
|
|
248
|
+
config.plugin = config.plugin.filter((p) => p !== "@neikyun/ciel" && p !== "./.opencode/plugins/ciel.ts");
|
|
249
|
+
if (!config.plugin.includes("./.opencode/plugins/ciel.js")) {
|
|
250
|
+
config.plugin.push("./.opencode/plugins/ciel.js");
|
|
219
251
|
}
|
|
220
252
|
// Ensure instructions contain AGENTS.md
|
|
221
253
|
if (!config.instructions)
|
package/dist/cli/opencode.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../src/cli/opencode.ts"],"names":[],"mappings":";AAAA,oCAAoC;AACpC,4EAA4E;;AAqB5E,wCAKC;
|
|
1
|
+
{"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../src/cli/opencode.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neikyun/ciel",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.3",
|
|
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",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"README.md"
|
|
16
16
|
],
|
|
17
17
|
"scripts": {
|
|
18
|
-
"build": "node scripts/copy-assets.cjs
|
|
18
|
+
"build": "tsc && node scripts/copy-assets.cjs",
|
|
19
19
|
"clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true});require('fs').rmSync('assets',{recursive:true,force:true})\"",
|
|
20
20
|
"test": "npx tsx --test test/**/*.test.ts",
|
|
21
21
|
"postinstall": "node scripts/postinstall.cjs",
|
package/scripts/postinstall.cjs
CHANGED
|
@@ -79,9 +79,18 @@ function installOpenCode(targetDir, assets) {
|
|
|
79
79
|
cleanDir(join(targetDir, ".opencode/agents"));
|
|
80
80
|
cleanDir(join(targetDir, ".opencode/commands"));
|
|
81
81
|
cleanDir(join(targetDir, ".opencode/skills"));
|
|
82
|
-
// Nettoyer
|
|
83
|
-
const old
|
|
84
|
-
|
|
82
|
+
// Nettoyer anciens plugins
|
|
83
|
+
for (const old of ["ciel.ts", "ciel.js"]) {
|
|
84
|
+
const p = join(targetDir, ".opencode/plugins", old);
|
|
85
|
+
if (existsSync(p)) { try { unlinkSync(p); count++; } catch {} }
|
|
86
|
+
}
|
|
87
|
+
// Copier le plugin JS compilé (auto-suffisant, pas de node_modules requis)
|
|
88
|
+
const pluginJs = join(__dirname, "..", "dist/plugin/index.js");
|
|
89
|
+
if (existsSync(pluginJs)) {
|
|
90
|
+
mkdirSync(join(targetDir, ".opencode/plugins"), { recursive: true });
|
|
91
|
+
copyFileSync(pluginJs, join(targetDir, ".opencode/plugins/ciel.js"));
|
|
92
|
+
count++;
|
|
93
|
+
}
|
|
85
94
|
// Copier agents
|
|
86
95
|
count += copyDir(join(assets, "platforms/opencode/.opencode/agents"), join(targetDir, ".opencode/agents"));
|
|
87
96
|
// Copier commandes
|
|
@@ -93,15 +102,15 @@ function installOpenCode(targetDir, assets) {
|
|
|
93
102
|
copyFileSync(join(assets, "platforms/opencode/AGENTS.md"), join(targetDir, "AGENTS.md"));
|
|
94
103
|
count++;
|
|
95
104
|
}
|
|
96
|
-
// Patcher opencode.json
|
|
105
|
+
// Patcher opencode.json (local plugin path)
|
|
97
106
|
try {
|
|
98
107
|
const cfgPath = join(targetDir, "opencode.json");
|
|
99
108
|
if (existsSync(cfgPath)) {
|
|
100
109
|
let cfg = JSON.parse(readFileSync(cfgPath, "utf-8"));
|
|
101
110
|
if (!cfg.plugin) cfg.plugin = [];
|
|
102
|
-
// Remplacer
|
|
103
|
-
cfg.plugin = cfg.plugin.filter(p => p !== "./.opencode/plugins/ciel.ts");
|
|
104
|
-
if (!cfg.plugin.includes("
|
|
111
|
+
// Remplacer anciennes refs par le chemin local
|
|
112
|
+
cfg.plugin = cfg.plugin.filter(p => p !== "@neikyun/ciel" && p !== "./.opencode/plugins/ciel.ts");
|
|
113
|
+
if (!cfg.plugin.includes("./.opencode/plugins/ciel.js")) cfg.plugin.push("./.opencode/plugins/ciel.js");
|
|
105
114
|
if (!cfg.instructions) cfg.instructions = [];
|
|
106
115
|
if (!cfg.instructions.includes("AGENTS.md")) cfg.instructions.push("AGENTS.md");
|
|
107
116
|
writeFileSync(cfgPath, JSON.stringify(cfg, null, 2) + "\n", "utf-8");
|