ccc-notifier 0.3.0 → 0.5.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 +11 -7
- package/dist/{budget-KKTFYAXH.js → budget-TBWVHUKA.js} +1 -1
- package/dist/chunk-5PH7PPD6.js +1077 -0
- package/dist/{chunk-4RZ6OGTD.js → chunk-DDUK4EWQ.js} +1 -1
- package/dist/chunk-ENGUOLTD.js +92 -0
- package/dist/chunk-HLJAJS2W.js +55 -0
- package/dist/{chunk-LHKBGA5K.js → chunk-LVMKY6JB.js} +304 -29
- package/dist/chunk-O2AR4PXU.js +82 -0
- package/dist/chunk-O34L3NSI.js +172 -0
- package/dist/{chunk-QX5KIRSU.js → chunk-QWBQN4XY.js} +183 -54
- package/dist/{chunk-7KVOQ4UZ.js → chunk-S3XKO7MY.js} +235 -108
- package/dist/cli.js +382 -73
- package/dist/{dashboard-TH3NOVT3.js → dashboard-6F2QNUJT.js} +4 -2
- package/dist/history-7KN26LJH.js +162 -0
- package/dist/{mute-EPLYH67P.js → mute-MPX3K7QN.js} +2 -2
- package/dist/{setup-PTO5N46B.js → setup-IXPMVWOE.js} +2 -2
- package/dist/subagent-store-A6MIN22X.js +31 -0
- package/dist/{sweep-25EZAOGC.js → sweep-UIONM4UA.js} +143 -126
- package/dist/track-KEZON6KI.js +245 -0
- package/package.json +1 -1
- package/dist/chunk-DSV75EF7.js +0 -357
- package/dist/chunk-ECADO26T.js +0 -316
- package/dist/history-DLFYQJFM.js +0 -114
- package/dist/track-PXFSGMGL.js +0 -184
|
@@ -8,14 +8,16 @@ import {
|
|
|
8
8
|
detectCodex
|
|
9
9
|
} from "./chunk-HTYUYKFW.js";
|
|
10
10
|
import {
|
|
11
|
+
configFilePath,
|
|
11
12
|
paths,
|
|
12
13
|
readConfig
|
|
13
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-5PH7PPD6.js";
|
|
14
15
|
|
|
15
16
|
// src/setup.ts
|
|
16
17
|
import {
|
|
17
18
|
copyFileSync as copyFileSync2,
|
|
18
19
|
existsSync as existsSync2,
|
|
20
|
+
lstatSync,
|
|
19
21
|
mkdirSync as mkdirSync2,
|
|
20
22
|
readFileSync as readFileSync2,
|
|
21
23
|
rmSync,
|
|
@@ -35,123 +37,201 @@ import {
|
|
|
35
37
|
writeFileSync
|
|
36
38
|
} from "fs";
|
|
37
39
|
import { dirname, join } from "path";
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
var CODEX_HOOK_EVENTS = ["Stop", "UserPromptSubmit", "SubagentStart", "SubagentStop"];
|
|
41
|
+
var CODEX_HOOK_TIMEOUT_SECONDS = 20;
|
|
42
|
+
function isPlainObject(value) {
|
|
43
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
40
44
|
}
|
|
41
45
|
function codexHooksFile() {
|
|
42
46
|
return join(codexHome(), "hooks.json");
|
|
43
47
|
}
|
|
44
|
-
function
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
function normalizeExecutablePath(value) {
|
|
49
|
+
return process.platform === "win32" ? value.replace(/\\/g, "/") : value;
|
|
50
|
+
}
|
|
51
|
+
function codexHookCommand(nodePath, cliPath, event = "Stop") {
|
|
52
|
+
const node = normalizeExecutablePath(nodePath);
|
|
53
|
+
const cli = normalizeExecutablePath(cliPath);
|
|
54
|
+
return `"${node}" "${cli}" __ccc-notifier-codex-hook ${event}`;
|
|
55
|
+
}
|
|
56
|
+
function tokenize(command) {
|
|
57
|
+
const result = [];
|
|
58
|
+
const re = /\s*(?:"([^"]*)"|'([^']*)'|(\S+))/gy;
|
|
59
|
+
let offset = 0;
|
|
60
|
+
while (offset < command.length) {
|
|
61
|
+
re.lastIndex = offset;
|
|
62
|
+
const match = re.exec(command);
|
|
63
|
+
if (!match) return null;
|
|
64
|
+
result.push(match[1] ?? match[2] ?? match[3]);
|
|
65
|
+
offset = re.lastIndex;
|
|
50
66
|
}
|
|
51
|
-
return
|
|
67
|
+
return result;
|
|
52
68
|
}
|
|
53
|
-
function
|
|
54
|
-
|
|
69
|
+
function parseLegacyOwnedCommand(command) {
|
|
70
|
+
const tokens = tokenize(command);
|
|
71
|
+
if (tokens === null || tokens.length !== 4 || !isCccNotifierExecutablePair(tokens[0], tokens[1]) || tokens[2] !== "track" || tokens[3] !== "--codex") return null;
|
|
72
|
+
return {
|
|
73
|
+
nodePath: normalizeExecutablePath(tokens[0]),
|
|
74
|
+
cliPath: normalizeExecutablePath(tokens[1]),
|
|
75
|
+
event: "Stop"
|
|
76
|
+
};
|
|
55
77
|
}
|
|
56
|
-
function
|
|
57
|
-
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
78
|
+
function isCccNotifierExecutablePair(nodePath, cliPath) {
|
|
79
|
+
const node = normalizeExecutablePath(nodePath);
|
|
80
|
+
const cli = normalizeExecutablePath(cliPath);
|
|
81
|
+
const nodeAbsolute = node.startsWith("/") || /^[a-z]:\//i.test(node);
|
|
82
|
+
const cliAbsolute = cli.startsWith("/") || /^[a-z]:\//i.test(cli);
|
|
83
|
+
return nodeAbsolute && cliAbsolute && /(^|\/)node(?:\.exe)?$/i.test(node) && /\/(?:ccc-notifier\/dist|ccc-notifier-dist)\/cli\.js$/i.test(cli);
|
|
84
|
+
}
|
|
85
|
+
function parseOwnedCodexHookCommand(command) {
|
|
86
|
+
if (typeof command !== "string") return null;
|
|
87
|
+
const tokens = tokenize(command);
|
|
88
|
+
if (tokens === null || tokens.length !== 4 || tokens[2] !== "__ccc-notifier-codex-hook") return null;
|
|
89
|
+
if (!CODEX_HOOK_EVENTS.includes(tokens[3])) return null;
|
|
90
|
+
if (!isCccNotifierExecutablePair(tokens[0], tokens[1])) return null;
|
|
91
|
+
return {
|
|
92
|
+
nodePath: normalizeExecutablePath(tokens[0]),
|
|
93
|
+
cliPath: normalizeExecutablePath(tokens[1]),
|
|
94
|
+
event: tokens[3]
|
|
95
|
+
};
|
|
63
96
|
}
|
|
64
|
-
function
|
|
65
|
-
|
|
97
|
+
function parseConfiguredOwnedCodexHookCommand(command, event) {
|
|
98
|
+
const parsed = parseOwnedCodexHookCommand(command) ?? (typeof command === "string" ? parseLegacyOwnedCommand(command) : null);
|
|
99
|
+
return parsed !== null && (event === void 0 || parsed.event === event) ? parsed : null;
|
|
100
|
+
}
|
|
101
|
+
function isOwnedHandler(value, event) {
|
|
102
|
+
if (!isPlainObject(value) || value.type !== "command") return false;
|
|
103
|
+
return parseConfiguredOwnedCodexHookCommand(value.command, event) !== null;
|
|
104
|
+
}
|
|
105
|
+
function canonicalHandler(command) {
|
|
106
|
+
return { type: "command", command, timeout: CODEX_HOOK_TIMEOUT_SECONDS };
|
|
107
|
+
}
|
|
108
|
+
function manualSnippet(nodePath, cliPath) {
|
|
109
|
+
const hooks = Object.fromEntries(
|
|
110
|
+
CODEX_HOOK_EVENTS.map((event) => [
|
|
111
|
+
event,
|
|
112
|
+
[{ hooks: [canonicalHandler(codexHookCommand(nodePath, cliPath, event))] }]
|
|
113
|
+
])
|
|
114
|
+
);
|
|
115
|
+
return JSON.stringify({ hooks }, null, 2);
|
|
66
116
|
}
|
|
67
|
-
function
|
|
117
|
+
function backup(path) {
|
|
68
118
|
const backupPath = `${path}.bak-${Date.now()}`;
|
|
69
119
|
copyFileSync(path, backupPath);
|
|
70
120
|
return backupPath;
|
|
71
121
|
}
|
|
72
|
-
function
|
|
73
|
-
writeFileSync(path, JSON.stringify(
|
|
122
|
+
function write(path, value) {
|
|
123
|
+
writeFileSync(path, `${JSON.stringify(value, null, 2)}
|
|
124
|
+
`, "utf8");
|
|
125
|
+
}
|
|
126
|
+
function validateShape(root) {
|
|
127
|
+
if (root.hooks !== void 0 && !isPlainObject(root.hooks)) return null;
|
|
128
|
+
const hooks = root.hooks ?? {};
|
|
129
|
+
for (const event of CODEX_HOOK_EVENTS) {
|
|
130
|
+
if (hooks[event] !== void 0 && !Array.isArray(hooks[event])) return null;
|
|
131
|
+
const groups = hooks[event] ?? [];
|
|
132
|
+
for (const group of groups) {
|
|
133
|
+
if (!isPlainObject(group) || !Array.isArray(group.hooks)) return null;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return hooks;
|
|
74
137
|
}
|
|
75
138
|
function registerCodexHook(nodePath, cliPath) {
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
139
|
+
const path = codexHooksFile();
|
|
140
|
+
if (!existsSync(path)) {
|
|
141
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
142
|
+
const hooks2 = {};
|
|
143
|
+
for (const event of CODEX_HOOK_EVENTS) {
|
|
144
|
+
hooks2[event] = [{ hooks: [canonicalHandler(codexHookCommand(nodePath, cliPath, event))] }];
|
|
145
|
+
}
|
|
146
|
+
write(path, { hooks: hooks2 });
|
|
81
147
|
return { status: "written", backupPath: null };
|
|
82
148
|
}
|
|
83
|
-
const raw = readFileSync(
|
|
149
|
+
const raw = readFileSync(path, "utf8");
|
|
84
150
|
let parsed;
|
|
85
151
|
try {
|
|
86
152
|
parsed = JSON.parse(raw);
|
|
87
153
|
} catch {
|
|
88
|
-
return { status: "manual", backupPath: null, manualSnippet:
|
|
154
|
+
return { status: "manual", backupPath: null, manualSnippet: manualSnippet(nodePath, cliPath) };
|
|
89
155
|
}
|
|
90
156
|
if (!isPlainObject(parsed)) {
|
|
91
|
-
return { status: "manual", backupPath: null, manualSnippet:
|
|
157
|
+
return { status: "manual", backupPath: null, manualSnippet: manualSnippet(nodePath, cliPath) };
|
|
92
158
|
}
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
return { status: "manual", backupPath: null, manualSnippet: buildManualSnippet(command) };
|
|
159
|
+
const hooks = validateShape(parsed);
|
|
160
|
+
if (hooks === null) {
|
|
161
|
+
return { status: "manual", backupPath: null, manualSnippet: manualSnippet(nodePath, cliPath) };
|
|
97
162
|
}
|
|
98
|
-
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
163
|
+
let changed = false;
|
|
164
|
+
for (const event of CODEX_HOOK_EVENTS) {
|
|
165
|
+
const groups = hooks[event] ?? [];
|
|
166
|
+
const wanted = canonicalHandler(codexHookCommand(nodePath, cliPath, event));
|
|
167
|
+
let found = false;
|
|
168
|
+
const groupsToRemove = /* @__PURE__ */ new Set();
|
|
169
|
+
for (const group of groups) {
|
|
170
|
+
const handlers = group.hooks;
|
|
171
|
+
for (let i = 0; i < handlers.length; i++) {
|
|
172
|
+
if (!isOwnedHandler(handlers[i], event)) continue;
|
|
173
|
+
if (!found) {
|
|
174
|
+
found = true;
|
|
175
|
+
const current = handlers[i];
|
|
176
|
+
const needsUpdate = !isPlainObject(current) || current.type !== wanted.type || current.command !== wanted.command || current.timeout !== wanted.timeout;
|
|
177
|
+
if (needsUpdate) {
|
|
178
|
+
handlers[i] = isPlainObject(current) ? { ...current, ...wanted } : wanted;
|
|
179
|
+
changed = true;
|
|
180
|
+
}
|
|
181
|
+
} else {
|
|
182
|
+
handlers.splice(i--, 1);
|
|
183
|
+
changed = true;
|
|
184
|
+
if (handlers.length === 0) groupsToRemove.add(group);
|
|
185
|
+
}
|
|
116
186
|
}
|
|
117
187
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
188
|
+
if (!found) {
|
|
189
|
+
groups.push({ hooks: [wanted] });
|
|
190
|
+
changed = true;
|
|
191
|
+
}
|
|
192
|
+
const retainedGroups = groups.filter((group) => !groupsToRemove.has(group));
|
|
193
|
+
if (retainedGroups.length !== groups.length) changed = true;
|
|
194
|
+
hooks[event] = retainedGroups;
|
|
122
195
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
writeHooks(hooksFile, obj);
|
|
196
|
+
if (!changed) return { status: "unchanged", backupPath: null };
|
|
197
|
+
const backupPath = backup(path);
|
|
198
|
+
parsed.hooks = hooks;
|
|
199
|
+
write(path, parsed);
|
|
128
200
|
return { status: "written", backupPath };
|
|
129
201
|
}
|
|
130
202
|
function removeCodexHook() {
|
|
131
|
-
const
|
|
132
|
-
if (!existsSync(
|
|
133
|
-
const raw = readFileSync(hooksFile, "utf8");
|
|
203
|
+
const path = codexHooksFile();
|
|
204
|
+
if (!existsSync(path)) return { status: "unchanged", backupPath: null };
|
|
134
205
|
let parsed;
|
|
135
206
|
try {
|
|
136
|
-
parsed = JSON.parse(
|
|
207
|
+
parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
137
208
|
} catch {
|
|
138
209
|
return { status: "unchanged", backupPath: null };
|
|
139
210
|
}
|
|
140
211
|
if (!isPlainObject(parsed)) return { status: "unchanged", backupPath: null };
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
212
|
+
const hooks = validateShape(parsed);
|
|
213
|
+
if (hooks === null) return { status: "unchanged", backupPath: null };
|
|
214
|
+
let changed = false;
|
|
215
|
+
for (const event of CODEX_HOOK_EVENTS) {
|
|
216
|
+
const original = hooks[event] ?? [];
|
|
217
|
+
const groups = [];
|
|
218
|
+
for (const group of original) {
|
|
219
|
+
const handlers = group.hooks;
|
|
220
|
+
const filtered = handlers.filter((handler) => !isOwnedHandler(handler, event));
|
|
221
|
+
const removedOwned = filtered.length !== handlers.length;
|
|
222
|
+
if (removedOwned) changed = true;
|
|
223
|
+
if (!removedOwned) groups.push(group);
|
|
224
|
+
else if (filtered.length > 0) groups.push({ ...group, hooks: filtered });
|
|
225
|
+
}
|
|
226
|
+
if (groups.length === 0) {
|
|
227
|
+
if (event in hooks) delete hooks[event];
|
|
228
|
+
} else {
|
|
229
|
+
hooks[event] = groups;
|
|
230
|
+
}
|
|
153
231
|
}
|
|
154
|
-
|
|
232
|
+
if (!changed) return { status: "unchanged", backupPath: null };
|
|
233
|
+
const backupPath = backup(path);
|
|
234
|
+
write(path, parsed);
|
|
155
235
|
return { status: "written", backupPath };
|
|
156
236
|
}
|
|
157
237
|
|
|
@@ -186,7 +266,7 @@ function buildHookCommand() {
|
|
|
186
266
|
function matchesMarker(command) {
|
|
187
267
|
return command.includes(HOOK_MARKER);
|
|
188
268
|
}
|
|
189
|
-
function
|
|
269
|
+
function isOurStopEntry(entry) {
|
|
190
270
|
if (!isPlainObject2(entry)) return false;
|
|
191
271
|
const hooks = entry.hooks;
|
|
192
272
|
if (!Array.isArray(hooks)) return false;
|
|
@@ -246,10 +326,13 @@ function parseInitFlags(argv) {
|
|
|
246
326
|
for (let i = 0; i < argv.length; i++) {
|
|
247
327
|
const a = argv[i];
|
|
248
328
|
if (a === "--yes" || a === "-y") flags.yes = true;
|
|
249
|
-
else if (a === "--os-only")
|
|
250
|
-
|
|
251
|
-
else if (a === "--
|
|
252
|
-
|
|
329
|
+
else if (a === "--os-only") {
|
|
330
|
+
flags.osOnly = true;
|
|
331
|
+
} else if (a === "--slack-only") {
|
|
332
|
+
flags.slackOnly = true;
|
|
333
|
+
} else if (a === "--no-notify") {
|
|
334
|
+
flags.noNotify = true;
|
|
335
|
+
} else if (a === "--codex") flags.codex = true;
|
|
253
336
|
else if (a === "--no-codex") flags.noCodex = true;
|
|
254
337
|
else if (a === "--slack-webhook" || a.startsWith("--slack-webhook=")) {
|
|
255
338
|
flags.slackWebhook = takeValue(argv, i, "--slack-webhook");
|
|
@@ -267,6 +350,38 @@ function parseInitFlags(argv) {
|
|
|
267
350
|
}
|
|
268
351
|
return flags;
|
|
269
352
|
}
|
|
353
|
+
function configPathEntryExists(path) {
|
|
354
|
+
try {
|
|
355
|
+
lstatSync(path);
|
|
356
|
+
return true;
|
|
357
|
+
} catch (err) {
|
|
358
|
+
if (isPlainObject2(err) && err.code === "ENOENT") return false;
|
|
359
|
+
return null;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
function isExactCodexMigrationInvocation(argv, flags) {
|
|
363
|
+
return flags.yes && flags.codex && argv.every((arg) => arg === "--yes" || arg === "-y" || arg === "--codex");
|
|
364
|
+
}
|
|
365
|
+
function printCodexHookResult(codexResult) {
|
|
366
|
+
if (codexResult.status === "written") {
|
|
367
|
+
console.log(`Codex \u306B Stop/UserPromptSubmit/SubagentStart/SubagentStop hook \u3092\u767B\u9332\u3057\u307E\u3057\u305F: ${codexHooksFile()}`);
|
|
368
|
+
if (codexResult.backupPath) {
|
|
369
|
+
console.log(` \u30D0\u30C3\u30AF\u30A2\u30C3\u30D7: ${codexResult.backupPath}`);
|
|
370
|
+
}
|
|
371
|
+
console.log(
|
|
372
|
+
"\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)"
|
|
373
|
+
);
|
|
374
|
+
} else if (codexResult.status === "unchanged") {
|
|
375
|
+
console.log("Codex \u306E Stop/UserPromptSubmit/SubagentStart/SubagentStop hook \u306F\u767B\u9332\u6E08\u307F\u3067\u3059");
|
|
376
|
+
} else {
|
|
377
|
+
console.error(`Codex \u306E hooks.json \u3092\u81EA\u52D5\u7DE8\u96C6\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F: ${codexHooksFile()}`);
|
|
378
|
+
console.error("\u5B89\u5168\u306E\u305F\u3081 hooks.json \u306E\u81EA\u52D5\u7DE8\u96C6\u3092\u4E2D\u6B62\u3057\u307E\u3057\u305F\u3002");
|
|
379
|
+
console.error("\u4EE5\u4E0B\u306E JSON \u306E4\u30A4\u30D9\u30F3\u30C8\u3092 hooks.json \u3078\u624B\u52D5\u3067\u8FFD\u52A0\u3057\u3066\u304F\u3060\u3055\u3044:");
|
|
380
|
+
console.error("");
|
|
381
|
+
console.error(codexResult.manualSnippet ?? "");
|
|
382
|
+
console.error("");
|
|
383
|
+
}
|
|
384
|
+
}
|
|
270
385
|
function parseUninstallFlags(argv) {
|
|
271
386
|
const flags = { yes: false, purge: false };
|
|
272
387
|
for (const a of argv) {
|
|
@@ -300,7 +415,7 @@ function mergeSettings(sPath, command) {
|
|
|
300
415
|
const hooks = obj.hooks;
|
|
301
416
|
if (!Array.isArray(hooks.Stop)) hooks.Stop = [];
|
|
302
417
|
const stop = hooks.Stop;
|
|
303
|
-
const idx = stop.findIndex(
|
|
418
|
+
const idx = stop.findIndex(isOurStopEntry);
|
|
304
419
|
if (idx >= 0) {
|
|
305
420
|
const entry = stop[idx];
|
|
306
421
|
const entryHooks = entry.hooks;
|
|
@@ -322,6 +437,33 @@ async function runInit(argv) {
|
|
|
322
437
|
console.error("--codex \u3068 --no-codex \u306F\u540C\u6642\u306B\u6307\u5B9A\u3067\u304D\u307E\u305B\u3093");
|
|
323
438
|
return 1;
|
|
324
439
|
}
|
|
440
|
+
const exactMigrationInvocation = isExactCodexMigrationInvocation(argv, flags);
|
|
441
|
+
const configEntryState = exactMigrationInvocation ? configPathEntryExists(configFilePath()) : false;
|
|
442
|
+
if (configEntryState === null) {
|
|
443
|
+
console.error(`config.json \u306E\u5B58\u5728\u3092\u5B89\u5168\u306B\u78BA\u8A8D\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F: ${configFilePath()}`);
|
|
444
|
+
console.error("\u5B89\u5168\u306E\u305F\u3081 Codex hook \u3092\u542B\u3080\u3059\u3079\u3066\u306E\u5909\u66F4\u3092\u4E2D\u6B62\u3057\u307E\u3057\u305F\u3002");
|
|
445
|
+
return 1;
|
|
446
|
+
}
|
|
447
|
+
const codexOnlyMigration = exactMigrationInvocation && configEntryState;
|
|
448
|
+
if (codexOnlyMigration) {
|
|
449
|
+
const codexResult2 = registerCodexHook(process.execPath, resolveCliPath());
|
|
450
|
+
printCodexHookResult(codexResult2);
|
|
451
|
+
if (codexResult2.status === "manual") {
|
|
452
|
+
console.error(
|
|
453
|
+
"Codex hook \u9650\u5B9A\u79FB\u884C\u3092\u5B8C\u4E86\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002config.json\u3001Claude settings\u3001\u901A\u77E5\u8A2D\u5B9A\u306F\u5909\u66F4\u3057\u3066\u3044\u307E\u305B\u3093\u3002"
|
|
454
|
+
);
|
|
455
|
+
return 1;
|
|
456
|
+
}
|
|
457
|
+
console.log(
|
|
458
|
+
"Codex hook \u306E\u307F\u3092\u78BA\u8A8D\u30FB\u66F4\u65B0\u3057\u307E\u3057\u305F\u3002config.json\u3001Claude settings\u3001\u901A\u77E5\u8A2D\u5B9A\u306F\u5909\u66F4\u305B\u305A\u3001\u30C6\u30B9\u30C8\u901A\u77E5\u3082\u9001\u4FE1\u3057\u3066\u3044\u307E\u305B\u3093\u3002"
|
|
459
|
+
);
|
|
460
|
+
if (codexResult2.status === "written") {
|
|
461
|
+
console.log(
|
|
462
|
+
"Codex \u3092\u518D\u8D77\u52D5\u3057\u3001/hooks \u3067 Stop / UserPromptSubmit / SubagentStart / SubagentStop \u3092\u4FE1\u983C\u6E08\u307F\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
|
|
463
|
+
);
|
|
464
|
+
}
|
|
465
|
+
return 0;
|
|
466
|
+
}
|
|
325
467
|
let installCodex = false;
|
|
326
468
|
const cfg = readConfig();
|
|
327
469
|
const initialChannel = !cfg.notify.os && !cfg.notify.slack ? "none" : cfg.notify.slack ? cfg.notify.os ? "both" : "slack" : "os";
|
|
@@ -517,24 +659,7 @@ async function runInit(argv) {
|
|
|
517
659
|
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");
|
|
518
660
|
}
|
|
519
661
|
if (codexResult) {
|
|
520
|
-
|
|
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
|
-
}
|
|
662
|
+
printCodexHookResult(codexResult);
|
|
538
663
|
}
|
|
539
664
|
return 0;
|
|
540
665
|
}
|
|
@@ -558,12 +683,12 @@ async function runUninstall(argv) {
|
|
|
558
683
|
const obj = parsed;
|
|
559
684
|
const hooks = isPlainObject2(obj.hooks) ? obj.hooks : null;
|
|
560
685
|
const stop = hooks && Array.isArray(hooks.Stop) ? hooks.Stop : null;
|
|
561
|
-
const hasMarker = stop ? stop.some(
|
|
686
|
+
const hasMarker = stop ? stop.some(isOurStopEntry) : false;
|
|
562
687
|
if (!hasMarker || !hooks || !stop) {
|
|
563
688
|
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");
|
|
564
689
|
} else {
|
|
565
690
|
const backupPath = backupSettings(sPath);
|
|
566
|
-
const filtered = stop.filter((e) => !
|
|
691
|
+
const filtered = stop.filter((e) => !isOurStopEntry(e));
|
|
567
692
|
if (filtered.length === 0) {
|
|
568
693
|
delete hooks.Stop;
|
|
569
694
|
} else {
|
|
@@ -577,7 +702,7 @@ async function runUninstall(argv) {
|
|
|
577
702
|
}
|
|
578
703
|
const codexRemoval = removeCodexHook();
|
|
579
704
|
if (codexRemoval.status === "written") {
|
|
580
|
-
console.log("Codex \u306E Stop hook \u3092\u524A\u9664\u3057\u307E\u3057\u305F");
|
|
705
|
+
console.log("Codex \u306E Stop/UserPromptSubmit/SubagentStart/SubagentStop hook \u3092\u524A\u9664\u3057\u307E\u3057\u305F");
|
|
581
706
|
}
|
|
582
707
|
if (flags.purge) {
|
|
583
708
|
const home = paths().home;
|
|
@@ -602,7 +727,9 @@ async function runUninstall(argv) {
|
|
|
602
727
|
}
|
|
603
728
|
|
|
604
729
|
export {
|
|
605
|
-
|
|
730
|
+
CODEX_HOOK_EVENTS,
|
|
731
|
+
CODEX_HOOK_TIMEOUT_SECONDS,
|
|
732
|
+
parseConfiguredOwnedCodexHookCommand,
|
|
606
733
|
matchesMarker,
|
|
607
734
|
runInit,
|
|
608
735
|
runUninstall
|