ccc-notifier 0.2.0 → 0.4.0
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/README.md +20 -12
- package/dist/{budget-5H2GQRXH.js → budget-EHWPEYXY.js} +2 -2
- package/dist/{chunk-IIYMGLV4.js → chunk-26CISNOE.js} +19 -4
- package/dist/{chunk-64N5SGTT.js → chunk-2VPBBIDW.js} +267 -57
- package/dist/{chunk-OXMHOVUL.js → chunk-5LHZOZZO.js} +228 -34
- package/dist/chunk-CKVK3UCA.js +357 -0
- package/dist/chunk-HTYUYKFW.js +21 -0
- package/dist/{chunk-TBFKGFZX.js → chunk-J5QAYTFE.js} +3 -0
- package/dist/chunk-J6Y3RMMC.js +172 -0
- package/dist/{chunk-OEG3AVU6.js → chunk-LHKBGA5K.js} +27 -1
- package/dist/{chunk-4JNZ7BHO.js → chunk-NV5UOHJA.js} +1 -1
- package/dist/{chunk-KUJZYZSG.js → chunk-TUZVISLD.js} +1 -1
- package/dist/chunk-ZHIZZ6V5.js +92 -0
- package/dist/cli.js +68 -17
- package/dist/{dashboard-LKK6NOBN.js → dashboard-GYKABTTN.js} +5 -3
- package/dist/history-6OUJLXJT.js +162 -0
- package/dist/{mute-2JW3NQXN.js → mute-GBDNN5PB.js} +2 -2
- package/dist/{setup-IXPUR4CM.js → setup-W3CSTHJC.js} +5 -4
- package/dist/{sweep-XKKODGMA.js → sweep-IBSV4LRD.js} +224 -80
- package/dist/track-QT2U3E2R.js +235 -0
- package/package.json +5 -2
- package/dist/chunk-TB5A7U7G.js +0 -82
- package/dist/history-MWFHO5VR.js +0 -114
- package/dist/track-76Q5CZM5.js +0 -168
|
@@ -2,42 +2,177 @@
|
|
|
2
2
|
import {
|
|
3
3
|
notifyOS,
|
|
4
4
|
notifySlack
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-NV5UOHJA.js";
|
|
6
|
+
import {
|
|
7
|
+
codexHome,
|
|
8
|
+
detectCodex
|
|
9
|
+
} from "./chunk-HTYUYKFW.js";
|
|
6
10
|
import {
|
|
7
11
|
paths,
|
|
8
12
|
readConfig
|
|
9
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-26CISNOE.js";
|
|
10
14
|
|
|
11
15
|
// src/setup.ts
|
|
16
|
+
import {
|
|
17
|
+
copyFileSync as copyFileSync2,
|
|
18
|
+
existsSync as existsSync2,
|
|
19
|
+
mkdirSync as mkdirSync2,
|
|
20
|
+
readFileSync as readFileSync2,
|
|
21
|
+
rmSync,
|
|
22
|
+
writeFileSync as writeFileSync2
|
|
23
|
+
} from "fs";
|
|
24
|
+
import { basename, dirname as dirname2, join as join2 } from "path";
|
|
25
|
+
import { homedir } from "os";
|
|
26
|
+
import { fileURLToPath } from "url";
|
|
27
|
+
import * as p from "@clack/prompts";
|
|
28
|
+
|
|
29
|
+
// src/codex/setup.ts
|
|
12
30
|
import {
|
|
13
31
|
copyFileSync,
|
|
14
32
|
existsSync,
|
|
15
33
|
mkdirSync,
|
|
16
34
|
readFileSync,
|
|
17
|
-
rmSync,
|
|
18
35
|
writeFileSync
|
|
19
36
|
} from "fs";
|
|
20
|
-
import {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
37
|
+
import { dirname, join } from "path";
|
|
38
|
+
function isPlainObject(v) {
|
|
39
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
40
|
+
}
|
|
41
|
+
function codexHooksFile() {
|
|
42
|
+
return join(codexHome(), "hooks.json");
|
|
43
|
+
}
|
|
44
|
+
function codexHookCommand(nodePath, cliPath) {
|
|
45
|
+
let node = nodePath;
|
|
46
|
+
let cli = cliPath;
|
|
47
|
+
if (process.platform === "win32") {
|
|
48
|
+
node = node.replace(/\\/g, "/");
|
|
49
|
+
cli = cli.replace(/\\/g, "/");
|
|
50
|
+
}
|
|
51
|
+
return `"${node}" "${cli}" track --codex`;
|
|
52
|
+
}
|
|
53
|
+
function ourCodexStopEntry(command) {
|
|
54
|
+
return { hooks: [{ type: "command", command }] };
|
|
55
|
+
}
|
|
56
|
+
function isOurStopEntry(entry) {
|
|
57
|
+
if (!isPlainObject(entry)) return false;
|
|
58
|
+
const hooks = entry.hooks;
|
|
59
|
+
if (!Array.isArray(hooks)) return false;
|
|
60
|
+
return hooks.some(
|
|
61
|
+
(h) => isPlainObject(h) && typeof h.command === "string" && matchesMarker(h.command)
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
function buildManualSnippet(command) {
|
|
65
|
+
return JSON.stringify(ourCodexStopEntry(command), null, 2);
|
|
66
|
+
}
|
|
67
|
+
function backupHooks(path) {
|
|
68
|
+
const backupPath = `${path}.bak-${Date.now()}`;
|
|
69
|
+
copyFileSync(path, backupPath);
|
|
70
|
+
return backupPath;
|
|
71
|
+
}
|
|
72
|
+
function writeHooks(path, obj) {
|
|
73
|
+
writeFileSync(path, JSON.stringify(obj, null, 2) + "\n", "utf8");
|
|
74
|
+
}
|
|
75
|
+
function registerCodexHook(nodePath, cliPath) {
|
|
76
|
+
const hooksFile = codexHooksFile();
|
|
77
|
+
const command = codexHookCommand(nodePath, cliPath);
|
|
78
|
+
if (!existsSync(hooksFile)) {
|
|
79
|
+
mkdirSync(dirname(hooksFile), { recursive: true });
|
|
80
|
+
writeHooks(hooksFile, { hooks: { Stop: [ourCodexStopEntry(command)] } });
|
|
81
|
+
return { status: "written", backupPath: null };
|
|
82
|
+
}
|
|
83
|
+
const raw = readFileSync(hooksFile, "utf8");
|
|
84
|
+
let parsed;
|
|
85
|
+
try {
|
|
86
|
+
parsed = JSON.parse(raw);
|
|
87
|
+
} catch {
|
|
88
|
+
return { status: "manual", backupPath: null, manualSnippet: buildManualSnippet(command) };
|
|
89
|
+
}
|
|
90
|
+
if (!isPlainObject(parsed)) {
|
|
91
|
+
return { status: "manual", backupPath: null, manualSnippet: buildManualSnippet(command) };
|
|
92
|
+
}
|
|
93
|
+
const obj = parsed;
|
|
94
|
+
const hooksVal = obj.hooks;
|
|
95
|
+
if (hooksVal !== void 0 && !isPlainObject(hooksVal)) {
|
|
96
|
+
return { status: "manual", backupPath: null, manualSnippet: buildManualSnippet(command) };
|
|
97
|
+
}
|
|
98
|
+
const hooks = hooksVal ?? {};
|
|
99
|
+
const stopVal = hooks.Stop;
|
|
100
|
+
if (stopVal !== void 0 && !Array.isArray(stopVal)) {
|
|
101
|
+
return { status: "manual", backupPath: null, manualSnippet: buildManualSnippet(command) };
|
|
102
|
+
}
|
|
103
|
+
const stop = stopVal ?? [];
|
|
104
|
+
const idx = stop.findIndex(isOurStopEntry);
|
|
105
|
+
if (idx >= 0) {
|
|
106
|
+
const entry = stop[idx];
|
|
107
|
+
const entryHooks = entry.hooks;
|
|
108
|
+
const needsUpdate = entryHooks.some(
|
|
109
|
+
(h) => isPlainObject(h) && typeof h.command === "string" && matchesMarker(h.command) && h.command !== command
|
|
110
|
+
);
|
|
111
|
+
if (!needsUpdate) return { status: "unchanged", backupPath: null };
|
|
112
|
+
const backupPath2 = backupHooks(hooksFile);
|
|
113
|
+
for (const h of entryHooks) {
|
|
114
|
+
if (isPlainObject(h) && typeof h.command === "string" && matchesMarker(h.command)) {
|
|
115
|
+
h.command = command;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
obj.hooks = hooks;
|
|
119
|
+
hooks.Stop = stop;
|
|
120
|
+
writeHooks(hooksFile, obj);
|
|
121
|
+
return { status: "written", backupPath: backupPath2 };
|
|
122
|
+
}
|
|
123
|
+
const backupPath = backupHooks(hooksFile);
|
|
124
|
+
stop.push(ourCodexStopEntry(command));
|
|
125
|
+
obj.hooks = hooks;
|
|
126
|
+
hooks.Stop = stop;
|
|
127
|
+
writeHooks(hooksFile, obj);
|
|
128
|
+
return { status: "written", backupPath };
|
|
129
|
+
}
|
|
130
|
+
function removeCodexHook() {
|
|
131
|
+
const hooksFile = codexHooksFile();
|
|
132
|
+
if (!existsSync(hooksFile)) return { status: "unchanged", backupPath: null };
|
|
133
|
+
const raw = readFileSync(hooksFile, "utf8");
|
|
134
|
+
let parsed;
|
|
135
|
+
try {
|
|
136
|
+
parsed = JSON.parse(raw);
|
|
137
|
+
} catch {
|
|
138
|
+
return { status: "unchanged", backupPath: null };
|
|
139
|
+
}
|
|
140
|
+
if (!isPlainObject(parsed)) return { status: "unchanged", backupPath: null };
|
|
141
|
+
const obj = parsed;
|
|
142
|
+
const hooks = isPlainObject(obj.hooks) ? obj.hooks : null;
|
|
143
|
+
const stop = hooks && Array.isArray(hooks.Stop) ? hooks.Stop : null;
|
|
144
|
+
if (!hooks || !stop || !stop.some(isOurStopEntry)) {
|
|
145
|
+
return { status: "unchanged", backupPath: null };
|
|
146
|
+
}
|
|
147
|
+
const backupPath = backupHooks(hooksFile);
|
|
148
|
+
const filtered = stop.filter((e) => !isOurStopEntry(e));
|
|
149
|
+
if (filtered.length === 0) {
|
|
150
|
+
delete hooks.Stop;
|
|
151
|
+
} else {
|
|
152
|
+
hooks.Stop = filtered;
|
|
153
|
+
}
|
|
154
|
+
writeHooks(hooksFile, obj);
|
|
155
|
+
return { status: "written", backupPath };
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// src/setup.ts
|
|
24
159
|
var HOOK_MARKER = "ccc-notifier";
|
|
25
160
|
var HOOK_TIMEOUT = 15;
|
|
26
161
|
var SLACK_PROMPT_CHARS = 100;
|
|
27
162
|
var DEFAULT_BUDGET_USD = 400;
|
|
28
|
-
function
|
|
163
|
+
function isPlainObject2(v) {
|
|
29
164
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
30
165
|
}
|
|
31
166
|
function settingsPath() {
|
|
32
|
-
return process.env.CCCN_CLAUDE_SETTINGS ||
|
|
167
|
+
return process.env.CCCN_CLAUDE_SETTINGS || join2(homedir(), ".claude", "settings.json");
|
|
33
168
|
}
|
|
34
169
|
function resolveCliPath() {
|
|
35
170
|
const override = process.env.CCCN_CLI_PATH;
|
|
36
171
|
if (override) return override;
|
|
37
172
|
const here = fileURLToPath(import.meta.url);
|
|
38
|
-
const dir =
|
|
39
|
-
if (basename(dir) === "dist") return
|
|
40
|
-
return
|
|
173
|
+
const dir = dirname2(here);
|
|
174
|
+
if (basename(dir) === "dist") return join2(dir, "cli.js");
|
|
175
|
+
return join2(dir, "..", "dist", "cli.js");
|
|
41
176
|
}
|
|
42
177
|
function buildHookCommand() {
|
|
43
178
|
let nodePath = process.execPath;
|
|
@@ -51,12 +186,12 @@ function buildHookCommand() {
|
|
|
51
186
|
function matchesMarker(command) {
|
|
52
187
|
return command.includes(HOOK_MARKER);
|
|
53
188
|
}
|
|
54
|
-
function
|
|
55
|
-
if (!
|
|
189
|
+
function isOurStopEntry2(entry) {
|
|
190
|
+
if (!isPlainObject2(entry)) return false;
|
|
56
191
|
const hooks = entry.hooks;
|
|
57
192
|
if (!Array.isArray(hooks)) return false;
|
|
58
193
|
return hooks.some(
|
|
59
|
-
(h) =>
|
|
194
|
+
(h) => isPlainObject2(h) && typeof h.command === "string" && matchesMarker(h.command)
|
|
60
195
|
);
|
|
61
196
|
}
|
|
62
197
|
function ourStopEntry(command) {
|
|
@@ -64,7 +199,7 @@ function ourStopEntry(command) {
|
|
|
64
199
|
}
|
|
65
200
|
function backupSettings(path) {
|
|
66
201
|
const backupPath = `${path}.bak-${Date.now()}`;
|
|
67
|
-
|
|
202
|
+
copyFileSync2(path, backupPath);
|
|
68
203
|
return backupPath;
|
|
69
204
|
}
|
|
70
205
|
function printManualSnippet(path, command, reason) {
|
|
@@ -100,13 +235,22 @@ function takeValue(argv, i, prefix) {
|
|
|
100
235
|
return argv[i + 1];
|
|
101
236
|
}
|
|
102
237
|
function parseInitFlags(argv) {
|
|
103
|
-
const flags = {
|
|
238
|
+
const flags = {
|
|
239
|
+
yes: false,
|
|
240
|
+
osOnly: false,
|
|
241
|
+
slackOnly: false,
|
|
242
|
+
noNotify: false,
|
|
243
|
+
codex: false,
|
|
244
|
+
noCodex: false
|
|
245
|
+
};
|
|
104
246
|
for (let i = 0; i < argv.length; i++) {
|
|
105
247
|
const a = argv[i];
|
|
106
248
|
if (a === "--yes" || a === "-y") flags.yes = true;
|
|
107
249
|
else if (a === "--os-only") flags.osOnly = true;
|
|
108
250
|
else if (a === "--slack-only") flags.slackOnly = true;
|
|
109
251
|
else if (a === "--no-notify") flags.noNotify = true;
|
|
252
|
+
else if (a === "--codex") flags.codex = true;
|
|
253
|
+
else if (a === "--no-codex") flags.noCodex = true;
|
|
110
254
|
else if (a === "--slack-webhook" || a.startsWith("--slack-webhook=")) {
|
|
111
255
|
flags.slackWebhook = takeValue(argv, i, "--slack-webhook");
|
|
112
256
|
if (!a.includes("=")) i++;
|
|
@@ -132,13 +276,13 @@ function parseUninstallFlags(argv) {
|
|
|
132
276
|
return flags;
|
|
133
277
|
}
|
|
134
278
|
function mergeSettings(sPath, command) {
|
|
135
|
-
if (!
|
|
136
|
-
|
|
279
|
+
if (!existsSync2(sPath)) {
|
|
280
|
+
mkdirSync2(dirname2(sPath), { recursive: true });
|
|
137
281
|
const fresh = { hooks: { Stop: [ourStopEntry(command)] } };
|
|
138
|
-
|
|
282
|
+
writeFileSync2(sPath, JSON.stringify(fresh, null, 2) + "\n", "utf8");
|
|
139
283
|
return { ok: true, backupPath: null };
|
|
140
284
|
}
|
|
141
|
-
const raw =
|
|
285
|
+
const raw = readFileSync2(sPath, "utf8");
|
|
142
286
|
let parsed;
|
|
143
287
|
try {
|
|
144
288
|
parsed = JSON.parse(raw);
|
|
@@ -146,22 +290,22 @@ function mergeSettings(sPath, command) {
|
|
|
146
290
|
printManualSnippet(sPath, command, "settings.json \u306E JSON \u89E3\u6790\u306B\u5931\u6557\u3057\u307E\u3057\u305F");
|
|
147
291
|
return { ok: false, backupPath: null };
|
|
148
292
|
}
|
|
149
|
-
if (!
|
|
293
|
+
if (!isPlainObject2(parsed)) {
|
|
150
294
|
printManualSnippet(sPath, command, "settings.json \u306E\u30EB\u30FC\u30C8\u304C\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u3067\u306F\u3042\u308A\u307E\u305B\u3093");
|
|
151
295
|
return { ok: false, backupPath: null };
|
|
152
296
|
}
|
|
153
297
|
const obj = parsed;
|
|
154
298
|
const backupPath = backupSettings(sPath);
|
|
155
|
-
if (!
|
|
299
|
+
if (!isPlainObject2(obj.hooks)) obj.hooks = {};
|
|
156
300
|
const hooks = obj.hooks;
|
|
157
301
|
if (!Array.isArray(hooks.Stop)) hooks.Stop = [];
|
|
158
302
|
const stop = hooks.Stop;
|
|
159
|
-
const idx = stop.findIndex(
|
|
303
|
+
const idx = stop.findIndex(isOurStopEntry2);
|
|
160
304
|
if (idx >= 0) {
|
|
161
305
|
const entry = stop[idx];
|
|
162
306
|
const entryHooks = entry.hooks;
|
|
163
307
|
for (const h of entryHooks) {
|
|
164
|
-
if (
|
|
308
|
+
if (isPlainObject2(h) && typeof h.command === "string" && matchesMarker(h.command)) {
|
|
165
309
|
h.command = command;
|
|
166
310
|
h.timeout = HOOK_TIMEOUT;
|
|
167
311
|
}
|
|
@@ -169,11 +313,16 @@ function mergeSettings(sPath, command) {
|
|
|
169
313
|
} else {
|
|
170
314
|
stop.push(ourStopEntry(command));
|
|
171
315
|
}
|
|
172
|
-
|
|
316
|
+
writeFileSync2(sPath, JSON.stringify(obj, null, 2) + "\n", "utf8");
|
|
173
317
|
return { ok: true, backupPath };
|
|
174
318
|
}
|
|
175
319
|
async function runInit(argv) {
|
|
176
320
|
const flags = parseInitFlags(argv);
|
|
321
|
+
if (flags.codex && flags.noCodex) {
|
|
322
|
+
console.error("--codex \u3068 --no-codex \u306F\u540C\u6642\u306B\u6307\u5B9A\u3067\u304D\u307E\u305B\u3093");
|
|
323
|
+
return 1;
|
|
324
|
+
}
|
|
325
|
+
let installCodex = false;
|
|
177
326
|
const cfg = readConfig();
|
|
178
327
|
const initialChannel = !cfg.notify.os && !cfg.notify.slack ? "none" : cfg.notify.slack ? cfg.notify.os ? "both" : "slack" : "os";
|
|
179
328
|
cfg.notify.os = true;
|
|
@@ -235,6 +384,7 @@ async function runInit(argv) {
|
|
|
235
384
|
} else {
|
|
236
385
|
cfg.monthlyBudgetUSD = budgetDefault;
|
|
237
386
|
}
|
|
387
|
+
installCodex = flags.codex;
|
|
238
388
|
} else {
|
|
239
389
|
p.intro("ccc-notifier \u30BB\u30C3\u30C8\u30A2\u30C3\u30D7");
|
|
240
390
|
const channel = await p.select({
|
|
@@ -316,14 +466,33 @@ async function runInit(argv) {
|
|
|
316
466
|
}
|
|
317
467
|
const parsedBudget = Number(budgetStr);
|
|
318
468
|
if (Number.isFinite(parsedBudget) && parsedBudget >= 0) cfg.monthlyBudgetUSD = parsedBudget;
|
|
469
|
+
if (flags.codex) {
|
|
470
|
+
installCodex = true;
|
|
471
|
+
} else if (flags.noCodex) {
|
|
472
|
+
installCodex = false;
|
|
473
|
+
} else if (detectCodex()) {
|
|
474
|
+
const codexConfirm = await p.confirm({
|
|
475
|
+
message: "Codex CLI \u3092\u691C\u51FA\u3057\u307E\u3057\u305F\u3002Codex \u306B\u3082\u30B3\u30B9\u30C8\u901A\u77E5\u3092\u5165\u308C\u307E\u3059\u304B?",
|
|
476
|
+
initialValue: true
|
|
477
|
+
});
|
|
478
|
+
if (p.isCancel(codexConfirm)) {
|
|
479
|
+
p.cancel("\u30AD\u30E3\u30F3\u30BB\u30EB\u3057\u307E\u3057\u305F");
|
|
480
|
+
return 1;
|
|
481
|
+
}
|
|
482
|
+
installCodex = codexConfirm;
|
|
483
|
+
}
|
|
319
484
|
p.outro("\u8A2D\u5B9A\u3092\u9069\u7528\u3057\u307E\u3059");
|
|
320
485
|
}
|
|
321
486
|
const cccn = paths();
|
|
322
|
-
|
|
487
|
+
writeFileSync2(cccn.configFile, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
323
488
|
const command = buildHookCommand();
|
|
324
489
|
const sPath = settingsPath();
|
|
325
490
|
const result = mergeSettings(sPath, command);
|
|
326
491
|
if (!result.ok) return 1;
|
|
492
|
+
let codexResult = null;
|
|
493
|
+
if (installCodex) {
|
|
494
|
+
codexResult = registerCodexHook(process.execPath, resolveCliPath());
|
|
495
|
+
}
|
|
327
496
|
const notifyDisabled = !cfg.notify.os && !cfg.notify.slack;
|
|
328
497
|
if (notifyDisabled) {
|
|
329
498
|
console.log("\u30C6\u30B9\u30C8\u901A\u77E5: \u901A\u77E5\u306A\u3057\u30E2\u30FC\u30C9\u306E\u305F\u3081\u30B9\u30AD\u30C3\u30D7\u3057\u307E\u3057\u305F");
|
|
@@ -347,15 +516,35 @@ async function runInit(argv) {
|
|
|
347
516
|
} else {
|
|
348
517
|
console.log("Claude Code \u3067\u4F55\u304B\u5B9F\u884C\u3059\u308B\u3068\u901A\u77E5\u304C\u5C4A\u304D\u307E\u3059\u3002\u78BA\u8A8D: npx ccc-notifier doctor");
|
|
349
518
|
}
|
|
519
|
+
if (codexResult) {
|
|
520
|
+
if (codexResult.status === "written") {
|
|
521
|
+
console.log(`Codex \u306B\u3082 Stop hook \u3092\u767B\u9332\u3057\u307E\u3057\u305F: ${codexHooksFile()}`);
|
|
522
|
+
if (codexResult.backupPath) {
|
|
523
|
+
console.log(` \u30D0\u30C3\u30AF\u30A2\u30C3\u30D7: ${codexResult.backupPath}`);
|
|
524
|
+
}
|
|
525
|
+
console.log(
|
|
526
|
+
"\u6B21\u56DE codex \u8D77\u52D5\u6642\u306B\u300EHooks need review\u300F\u304C\u8868\u793A\u3055\u308C\u307E\u3059\u3002\u300ETrust all and continue\u300F\u3092\u9078\u3076\u3068\u6709\u52B9\u306B\u306A\u308A\u307E\u3059(\u627F\u8A8D\u307E\u3067\u306F\u52D5\u304D\u307E\u305B\u3093)"
|
|
527
|
+
);
|
|
528
|
+
} else if (codexResult.status === "unchanged") {
|
|
529
|
+
console.log("Codex \u306E Stop hook \u306F\u767B\u9332\u6E08\u307F\u3067\u3059");
|
|
530
|
+
} else {
|
|
531
|
+
console.error(`Codex \u306E hooks.json \u3092\u81EA\u52D5\u7DE8\u96C6\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F: ${codexHooksFile()}`);
|
|
532
|
+
console.error("\u5B89\u5168\u306E\u305F\u3081 hooks.json \u306E\u81EA\u52D5\u7DE8\u96C6\u3092\u4E2D\u6B62\u3057\u307E\u3057\u305F\u3002");
|
|
533
|
+
console.error("\u4EE5\u4E0B\u306E JSON \u3092 hooks.json \u306E hooks.Stop \u914D\u5217\u306B\u624B\u52D5\u3067\u8FFD\u52A0\u3057\u3066\u304F\u3060\u3055\u3044:");
|
|
534
|
+
console.error("");
|
|
535
|
+
console.error(codexResult.manualSnippet ?? "");
|
|
536
|
+
console.error("");
|
|
537
|
+
}
|
|
538
|
+
}
|
|
350
539
|
return 0;
|
|
351
540
|
}
|
|
352
541
|
async function runUninstall(argv) {
|
|
353
542
|
const flags = parseUninstallFlags(argv);
|
|
354
543
|
const sPath = settingsPath();
|
|
355
|
-
if (!
|
|
544
|
+
if (!existsSync2(sPath)) {
|
|
356
545
|
console.log("\u767B\u9332\u306A\u3057: settings.json \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002");
|
|
357
546
|
} else {
|
|
358
|
-
const raw =
|
|
547
|
+
const raw = readFileSync2(sPath, "utf8");
|
|
359
548
|
let parsed;
|
|
360
549
|
let parseOk = true;
|
|
361
550
|
try {
|
|
@@ -363,29 +552,33 @@ async function runUninstall(argv) {
|
|
|
363
552
|
} catch {
|
|
364
553
|
parseOk = false;
|
|
365
554
|
}
|
|
366
|
-
if (!parseOk || !
|
|
555
|
+
if (!parseOk || !isPlainObject2(parsed)) {
|
|
367
556
|
console.error(`settings.json \u3092\u89E3\u6790\u3067\u304D\u306A\u3044\u305F\u3081\u7DE8\u96C6\u3092\u30B9\u30AD\u30C3\u30D7\u3057\u307E\u3057\u305F: ${sPath}`);
|
|
368
557
|
} else {
|
|
369
558
|
const obj = parsed;
|
|
370
|
-
const hooks =
|
|
559
|
+
const hooks = isPlainObject2(obj.hooks) ? obj.hooks : null;
|
|
371
560
|
const stop = hooks && Array.isArray(hooks.Stop) ? hooks.Stop : null;
|
|
372
|
-
const hasMarker = stop ? stop.some(
|
|
561
|
+
const hasMarker = stop ? stop.some(isOurStopEntry2) : false;
|
|
373
562
|
if (!hasMarker || !hooks || !stop) {
|
|
374
563
|
console.log("\u767B\u9332\u306A\u3057: \u672C\u30C4\u30FC\u30EB\u306E Stop \u30D5\u30C3\u30AF\u306F\u767B\u9332\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002");
|
|
375
564
|
} else {
|
|
376
565
|
const backupPath = backupSettings(sPath);
|
|
377
|
-
const filtered = stop.filter((e) => !
|
|
566
|
+
const filtered = stop.filter((e) => !isOurStopEntry2(e));
|
|
378
567
|
if (filtered.length === 0) {
|
|
379
568
|
delete hooks.Stop;
|
|
380
569
|
} else {
|
|
381
570
|
hooks.Stop = filtered;
|
|
382
571
|
}
|
|
383
|
-
|
|
572
|
+
writeFileSync2(sPath, JSON.stringify(obj, null, 2) + "\n", "utf8");
|
|
384
573
|
console.log(`\u672C\u30C4\u30FC\u30EB\u306E Stop \u30D5\u30C3\u30AF\u3092\u9664\u53BB\u3057\u307E\u3057\u305F: ${sPath}`);
|
|
385
574
|
console.log(` \u30D0\u30C3\u30AF\u30A2\u30C3\u30D7: ${backupPath}`);
|
|
386
575
|
}
|
|
387
576
|
}
|
|
388
577
|
}
|
|
578
|
+
const codexRemoval = removeCodexHook();
|
|
579
|
+
if (codexRemoval.status === "written") {
|
|
580
|
+
console.log("Codex \u306E Stop hook \u3092\u524A\u9664\u3057\u307E\u3057\u305F");
|
|
581
|
+
}
|
|
389
582
|
if (flags.purge) {
|
|
390
583
|
const home = paths().home;
|
|
391
584
|
let doPurge = flags.yes;
|
|
@@ -409,6 +602,7 @@ async function runUninstall(argv) {
|
|
|
409
602
|
}
|
|
410
603
|
|
|
411
604
|
export {
|
|
605
|
+
codexHooksFile,
|
|
412
606
|
matchesMarker,
|
|
413
607
|
runInit,
|
|
414
608
|
runUninstall
|