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
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
paths
|
|
4
|
+
} from "./chunk-26CISNOE.js";
|
|
5
|
+
|
|
6
|
+
// src/dashboard-state.ts
|
|
7
|
+
import {
|
|
8
|
+
closeSync,
|
|
9
|
+
existsSync,
|
|
10
|
+
openSync,
|
|
11
|
+
readFileSync,
|
|
12
|
+
readSync,
|
|
13
|
+
renameSync,
|
|
14
|
+
rmSync,
|
|
15
|
+
writeFileSync
|
|
16
|
+
} from "fs";
|
|
17
|
+
import { randomUUID } from "crypto";
|
|
18
|
+
function localDate(now) {
|
|
19
|
+
const y = now.getFullYear();
|
|
20
|
+
const m = String(now.getMonth() + 1).padStart(2, "0");
|
|
21
|
+
const d = String(now.getDate()).padStart(2, "0");
|
|
22
|
+
return `${y}-${m}-${d}`;
|
|
23
|
+
}
|
|
24
|
+
function timeZone() {
|
|
25
|
+
return Intl.DateTimeFormat().resolvedOptions().timeZone || "unknown";
|
|
26
|
+
}
|
|
27
|
+
function makeFullDashboardState(now = /* @__PURE__ */ new Date()) {
|
|
28
|
+
return { localDate: localDate(now), timeZone: timeZone(), generatedAt: now.toISOString() };
|
|
29
|
+
}
|
|
30
|
+
function readState() {
|
|
31
|
+
const file = paths().dashboardFullStateFile;
|
|
32
|
+
if (!existsSync(file)) return null;
|
|
33
|
+
try {
|
|
34
|
+
const value = JSON.parse(readFileSync(file, "utf8"));
|
|
35
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return null;
|
|
36
|
+
const v = value;
|
|
37
|
+
if (typeof v.localDate !== "string" || !/^\d{4}-\d{2}-\d{2}$/.test(v.localDate) || typeof v.timeZone !== "string" || v.timeZone.length === 0 || typeof v.generatedAt !== "string" || !Number.isFinite(Date.parse(v.generatedAt))) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
return v;
|
|
41
|
+
} catch {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function isFullDashboardDue(now = /* @__PURE__ */ new Date()) {
|
|
46
|
+
const p = paths();
|
|
47
|
+
if (!existsSync(p.fullDashboardFile)) return true;
|
|
48
|
+
try {
|
|
49
|
+
const fd = openSync(p.fullDashboardFile, "r");
|
|
50
|
+
try {
|
|
51
|
+
const head = Buffer.alloc(512);
|
|
52
|
+
const n = readSync(fd, head, 0, head.length, 0);
|
|
53
|
+
if (head.toString("utf8", 0, n).includes('name="cccn-placeholder"')) return true;
|
|
54
|
+
} finally {
|
|
55
|
+
closeSync(fd);
|
|
56
|
+
}
|
|
57
|
+
} catch {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
const state = readState();
|
|
61
|
+
if (state === null) return true;
|
|
62
|
+
const expected = makeFullDashboardState(now);
|
|
63
|
+
if (state.timeZone !== expected.timeZone) return true;
|
|
64
|
+
if (state.localDate !== expected.localDate) return true;
|
|
65
|
+
if (state.localDate > expected.localDate) return true;
|
|
66
|
+
if (Date.parse(state.generatedAt) > now.getTime()) return true;
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
function writeFullDashboardStateAtomic(state) {
|
|
70
|
+
const file = paths().dashboardFullStateFile;
|
|
71
|
+
const tmp = `${file}.${process.pid}.${randomUUID()}.tmp`;
|
|
72
|
+
try {
|
|
73
|
+
writeFileSync(tmp, `${JSON.stringify(state)}
|
|
74
|
+
`, "utf8");
|
|
75
|
+
renameSync(tmp, file);
|
|
76
|
+
} finally {
|
|
77
|
+
rmSync(tmp, { force: true });
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function invalidateCanonicalDashboards() {
|
|
81
|
+
const p = paths();
|
|
82
|
+
for (const file of [p.recentDashboardFile, p.fullDashboardFile, p.dashboardFullStateFile]) {
|
|
83
|
+
rmSync(file, { force: true });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export {
|
|
88
|
+
makeFullDashboardState,
|
|
89
|
+
isFullDashboardDue,
|
|
90
|
+
writeFullDashboardStateAtomic,
|
|
91
|
+
invalidateCanonicalDashboards
|
|
92
|
+
};
|
package/dist/cli.js
CHANGED
|
@@ -1,36 +1,41 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
fmtMuteUntil
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-TUZVISLD.js";
|
|
5
5
|
import {
|
|
6
|
+
codexHooksFile,
|
|
6
7
|
matchesMarker
|
|
7
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-5LHZOZZO.js";
|
|
8
9
|
import {
|
|
9
10
|
notifyOS,
|
|
10
11
|
notifySlack,
|
|
11
12
|
selectNotifyBackend
|
|
12
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-NV5UOHJA.js";
|
|
13
14
|
import {
|
|
14
15
|
isWSL
|
|
15
16
|
} from "./chunk-DGXUSPS4.js";
|
|
17
|
+
import {
|
|
18
|
+
codexHome,
|
|
19
|
+
detectCodex
|
|
20
|
+
} from "./chunk-HTYUYKFW.js";
|
|
16
21
|
import {
|
|
17
22
|
aggregateNewTurn,
|
|
18
23
|
computeCost,
|
|
19
24
|
getUsdJpy,
|
|
20
25
|
loadPriceTable
|
|
21
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-LHKBGA5K.js";
|
|
22
27
|
import {
|
|
23
28
|
formatJPY,
|
|
24
29
|
formatTokens,
|
|
25
30
|
formatUSD
|
|
26
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-J5QAYTFE.js";
|
|
27
32
|
import {
|
|
28
33
|
isMuted,
|
|
29
34
|
paths,
|
|
30
35
|
readConfig,
|
|
31
36
|
readMuteState,
|
|
32
37
|
readTurns
|
|
33
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-26CISNOE.js";
|
|
34
39
|
|
|
35
40
|
// src/cli.ts
|
|
36
41
|
import { realpathSync } from "fs";
|
|
@@ -156,6 +161,50 @@ async function checkHookRegistration() {
|
|
|
156
161
|
}
|
|
157
162
|
return true;
|
|
158
163
|
}
|
|
164
|
+
async function checkCodex() {
|
|
165
|
+
if (!detectCodex()) {
|
|
166
|
+
log("ok", "Codex CLI \u306F\u672A\u691C\u51FA\u3067\u3059(\u672A\u4F7F\u7528\u306A\u3089\u554F\u984C\u3042\u308A\u307E\u305B\u3093)");
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
const hooksFile = codexHooksFile();
|
|
170
|
+
const matchedCommands = [];
|
|
171
|
+
if (existsSync(hooksFile)) {
|
|
172
|
+
try {
|
|
173
|
+
const raw = await readFile(hooksFile, "utf8");
|
|
174
|
+
const parsed = JSON.parse(raw);
|
|
175
|
+
if (isRecord(parsed)) {
|
|
176
|
+
const hooks = parsed.hooks;
|
|
177
|
+
const stopEntries = isRecord(hooks) ? hooks.Stop : void 0;
|
|
178
|
+
if (Array.isArray(stopEntries)) {
|
|
179
|
+
for (const entry of stopEntries) {
|
|
180
|
+
if (!isRecord(entry)) continue;
|
|
181
|
+
const innerHooks = entry.hooks;
|
|
182
|
+
if (!Array.isArray(innerHooks)) continue;
|
|
183
|
+
for (const h of innerHooks) {
|
|
184
|
+
if (isRecord(h) && typeof h.command === "string" && matchesMarker(h.command)) {
|
|
185
|
+
matchedCommands.push(h.command);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
} catch {
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
if (matchedCommands.length > 0) {
|
|
195
|
+
log("ok", `Codex \u306E Stop hook \u304C\u767B\u9332\u3055\u308C\u3066\u3044\u307E\u3059: ${matchedCommands.join(" / ")}`);
|
|
196
|
+
log("ok", "codex \u5074\u3067 hook \u3092\u627F\u8A8D\u6E08\u307F\u304B\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044(\u672A\u627F\u8A8D\u3060\u3068\u901A\u77E5\u3055\u308C\u307E\u305B\u3093)");
|
|
197
|
+
} else {
|
|
198
|
+
log("warn", "Codex \u3092\u691C\u51FA\u3057\u307E\u3057\u305F\u304C hook \u304C\u672A\u767B\u9332\u3067\u3059\u3002init --codex \u3067\u767B\u9332\u3067\u304D\u307E\u3059");
|
|
199
|
+
}
|
|
200
|
+
const sessionsDir = join(codexHome(), "sessions");
|
|
201
|
+
if (existsSync(sessionsDir)) {
|
|
202
|
+
log("ok", `Codex \u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092\u78BA\u8A8D\u3057\u307E\u3057\u305F: ${sessionsDir}`);
|
|
203
|
+
} else {
|
|
204
|
+
log("ok", `Codex \u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306F\u307E\u3060\u3042\u308A\u307E\u305B\u3093: ${sessionsDir}(\u30BB\u30C3\u30B7\u30E7\u30F3\u672A\u4F5C\u6210\u306E\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059)`);
|
|
205
|
+
}
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
159
208
|
function readDirSafe(dir) {
|
|
160
209
|
try {
|
|
161
210
|
return readdirSync(dir, { withFileTypes: true });
|
|
@@ -339,6 +388,7 @@ async function checkRecentSessionTotal(latestTranscript) {
|
|
|
339
388
|
async function runDoctor() {
|
|
340
389
|
const results = [];
|
|
341
390
|
results.push(await safeRun("settings.json", () => checkHookRegistration()));
|
|
391
|
+
results.push(await safeRun("codex", () => checkCodex()));
|
|
342
392
|
let latestTranscript = null;
|
|
343
393
|
results.push(
|
|
344
394
|
await safeRun("projects", async () => {
|
|
@@ -536,7 +586,7 @@ var COMMANDS = [
|
|
|
536
586
|
en: "Print an aggregated cost report"
|
|
537
587
|
},
|
|
538
588
|
{
|
|
539
|
-
cmd: "dashboard [--days N] [--no-open] [--out <path>] [--refresh <sec>|--no-refresh]",
|
|
589
|
+
cmd: "dashboard [--all|--days N] [--no-open] [--out <path>] [--refresh <sec>|--no-refresh]",
|
|
540
590
|
ja: "HTML\u30C0\u30C3\u30B7\u30E5\u30DC\u30FC\u30C9\u3092\u751F\u6210\u3057\u3066\u30D6\u30E9\u30A6\u30B6\u3067\u958B\u304F",
|
|
541
591
|
en: "Generate and open the HTML dashboard"
|
|
542
592
|
},
|
|
@@ -631,19 +681,20 @@ async function main(argv) {
|
|
|
631
681
|
switch (cmd) {
|
|
632
682
|
case "track": {
|
|
633
683
|
const text = await readStdin();
|
|
684
|
+
const codex = rest.includes("--codex");
|
|
634
685
|
try {
|
|
635
|
-
const trackMod = await import("./track-
|
|
636
|
-
await trackMod.runTrack(text);
|
|
686
|
+
const trackMod = await import("./track-QT2U3E2R.js");
|
|
687
|
+
await trackMod.runTrack(text, { codex });
|
|
637
688
|
} catch {
|
|
638
689
|
}
|
|
639
690
|
return 0;
|
|
640
691
|
}
|
|
641
692
|
case "init": {
|
|
642
|
-
const { runInit } = await import("./setup-
|
|
693
|
+
const { runInit } = await import("./setup-W3CSTHJC.js");
|
|
643
694
|
return await runInit(rest);
|
|
644
695
|
}
|
|
645
696
|
case "uninstall": {
|
|
646
|
-
const { runUninstall } = await import("./setup-
|
|
697
|
+
const { runUninstall } = await import("./setup-W3CSTHJC.js");
|
|
647
698
|
return await runUninstall(rest);
|
|
648
699
|
}
|
|
649
700
|
case "doctor":
|
|
@@ -651,27 +702,27 @@ async function main(argv) {
|
|
|
651
702
|
case "report":
|
|
652
703
|
return await runReport(rest);
|
|
653
704
|
case "dashboard": {
|
|
654
|
-
const { runDashboard } = await import("./dashboard-
|
|
705
|
+
const { runDashboard } = await import("./dashboard-GYKABTTN.js");
|
|
655
706
|
return await runDashboard(rest);
|
|
656
707
|
}
|
|
657
708
|
case "sweep": {
|
|
658
|
-
const { runSweep } = await import("./sweep-
|
|
709
|
+
const { runSweep } = await import("./sweep-IBSV4LRD.js");
|
|
659
710
|
return await runSweep(rest);
|
|
660
711
|
}
|
|
661
712
|
case "history": {
|
|
662
|
-
const { runHistory } = await import("./history-
|
|
713
|
+
const { runHistory } = await import("./history-6OUJLXJT.js");
|
|
663
714
|
return await runHistory(rest);
|
|
664
715
|
}
|
|
665
716
|
case "budget": {
|
|
666
|
-
const { runBudget } = await import("./budget-
|
|
717
|
+
const { runBudget } = await import("./budget-EHWPEYXY.js");
|
|
667
718
|
return runBudget(rest);
|
|
668
719
|
}
|
|
669
720
|
case "mute": {
|
|
670
|
-
const { runMute } = await import("./mute-
|
|
721
|
+
const { runMute } = await import("./mute-GBDNN5PB.js");
|
|
671
722
|
return runMute(rest);
|
|
672
723
|
}
|
|
673
724
|
case "unmute": {
|
|
674
|
-
const { runUnmute } = await import("./mute-
|
|
725
|
+
const { runUnmute } = await import("./mute-GBDNN5PB.js");
|
|
675
726
|
return runUnmute();
|
|
676
727
|
}
|
|
677
728
|
case "--version":
|
|
@@ -3,10 +3,12 @@ import {
|
|
|
3
3
|
browserOpenPlan,
|
|
4
4
|
runDashboard,
|
|
5
5
|
writeDashboardHtml
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-2VPBBIDW.js";
|
|
7
7
|
import "./chunk-DGXUSPS4.js";
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-ZHIZZ6V5.js";
|
|
9
|
+
import "./chunk-J6Y3RMMC.js";
|
|
10
|
+
import "./chunk-J5QAYTFE.js";
|
|
11
|
+
import "./chunk-26CISNOE.js";
|
|
10
12
|
export {
|
|
11
13
|
browserOpenPlan,
|
|
12
14
|
runDashboard,
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
invalidateCanonicalDashboards
|
|
4
|
+
} from "./chunk-ZHIZZ6V5.js";
|
|
5
|
+
import {
|
|
6
|
+
waitForDataLock
|
|
7
|
+
} from "./chunk-J6Y3RMMC.js";
|
|
8
|
+
import {
|
|
9
|
+
paths
|
|
10
|
+
} from "./chunk-26CISNOE.js";
|
|
11
|
+
|
|
12
|
+
// src/history.ts
|
|
13
|
+
import { existsSync, readFileSync, writeFileSync, renameSync, rmSync } from "fs";
|
|
14
|
+
import { createHash } from "crypto";
|
|
15
|
+
import * as p from "@clack/prompts";
|
|
16
|
+
function parseFlags(argv) {
|
|
17
|
+
let days = null;
|
|
18
|
+
let yes = false;
|
|
19
|
+
for (let i = 0; i < argv.length; i++) {
|
|
20
|
+
const a = argv[i];
|
|
21
|
+
if (a === "--yes" || a === "-y") {
|
|
22
|
+
yes = true;
|
|
23
|
+
} else if (a === "--days") {
|
|
24
|
+
const n = Number.parseInt(argv[i + 1] ?? "", 10);
|
|
25
|
+
if (Number.isFinite(n) && n > 0) days = n;
|
|
26
|
+
i++;
|
|
27
|
+
} else if (a.startsWith("--days=")) {
|
|
28
|
+
const n = Number.parseInt(a.slice("--days=".length), 10);
|
|
29
|
+
if (Number.isFinite(n) && n > 0) days = n;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return { days, yes };
|
|
33
|
+
}
|
|
34
|
+
function readLines(file) {
|
|
35
|
+
const raw = readFileSync(file, "utf8");
|
|
36
|
+
const lines = [];
|
|
37
|
+
for (const line of raw.split("\n")) {
|
|
38
|
+
if (!line.trim()) continue;
|
|
39
|
+
let rec = null;
|
|
40
|
+
try {
|
|
41
|
+
rec = JSON.parse(line);
|
|
42
|
+
} catch {
|
|
43
|
+
rec = null;
|
|
44
|
+
}
|
|
45
|
+
lines.push({ raw: line, rec });
|
|
46
|
+
}
|
|
47
|
+
return lines;
|
|
48
|
+
}
|
|
49
|
+
function isTargeted(rec, cutoffMs) {
|
|
50
|
+
if (cutoffMs === null) return true;
|
|
51
|
+
const ts = Date.parse(rec.ts);
|
|
52
|
+
if (!Number.isFinite(ts)) return false;
|
|
53
|
+
return ts < cutoffMs;
|
|
54
|
+
}
|
|
55
|
+
function atomicWrite(file, content) {
|
|
56
|
+
const tmp = `${file}.tmp`;
|
|
57
|
+
writeFileSync(tmp, content, "utf8");
|
|
58
|
+
renameSync(tmp, file);
|
|
59
|
+
}
|
|
60
|
+
function collectTargets(lines, sub, cutoff) {
|
|
61
|
+
const targetSet = /* @__PURE__ */ new Set();
|
|
62
|
+
for (let i = 0; i < lines.length; i++) {
|
|
63
|
+
const rec = lines[i].rec;
|
|
64
|
+
if (!rec || !isTargeted(rec, cutoff)) continue;
|
|
65
|
+
if (sub === "redact" && !(typeof rec.prompt === "string" && rec.prompt.length > 0)) continue;
|
|
66
|
+
targetSet.add(i);
|
|
67
|
+
}
|
|
68
|
+
return targetSet;
|
|
69
|
+
}
|
|
70
|
+
function targetFingerprint(lines, targets) {
|
|
71
|
+
const hash = createHash("sha256");
|
|
72
|
+
hash.update(`count:${targets.size}
|
|
73
|
+
`);
|
|
74
|
+
for (const i of [...targets].sort((a, b) => a - b)) {
|
|
75
|
+
hash.update(`${i}:${lines[i]?.raw ?? ""}
|
|
76
|
+
`);
|
|
77
|
+
}
|
|
78
|
+
return hash.digest("hex");
|
|
79
|
+
}
|
|
80
|
+
async function runHistory(argv, deps = {}) {
|
|
81
|
+
const [sub, ...rest] = argv;
|
|
82
|
+
if (sub !== "clear" && sub !== "redact") {
|
|
83
|
+
console.error(
|
|
84
|
+
"\u4F7F\u3044\u65B9 / Usage: ccc-notifier history <clear|redact> [--days N] [--yes]\n clear \u2026 \u30EC\u30B3\u30FC\u30C9\u3054\u3068\u524A\u9664(\u30C1\u30E3\u30FC\u30C8\u30FB\u96C6\u8A08\u304B\u3089\u3082\u6D88\u3048\u308B) / delete records\n redact \u2026 \u30D7\u30ED\u30F3\u30D7\u30C8\u5168\u6587\u3060\u3051\u6D88\u3059(\u30B3\u30B9\u30C8\u30FB\u30C1\u30E3\u30FC\u30C8\u306F\u6B8B\u3059) / strip prompts only"
|
|
85
|
+
);
|
|
86
|
+
return 1;
|
|
87
|
+
}
|
|
88
|
+
const flags = parseFlags(rest);
|
|
89
|
+
const file = paths().historyFile;
|
|
90
|
+
let lines = existsSync(file) ? readLines(file) : [];
|
|
91
|
+
const cutoff = flags.days !== null ? Date.now() - flags.days * 864e5 : null;
|
|
92
|
+
const scope = flags.days !== null ? `${flags.days}\u65E5\u3088\u308A\u524D` : "\u5168\u671F\u9593";
|
|
93
|
+
let targetSet = collectTargets(lines, sub, cutoff);
|
|
94
|
+
const initialFingerprint = targetFingerprint(lines, targetSet);
|
|
95
|
+
const action = sub === "clear" ? "\u30EC\u30B3\u30FC\u30C9\u3054\u3068\u524A\u9664" : "\u30D7\u30ED\u30F3\u30D7\u30C8\u5168\u6587\u3092\u6D88\u53BB";
|
|
96
|
+
if (targetSet.size > 0 && !flags.yes) {
|
|
97
|
+
const confirmed = await (deps.confirm ?? p.confirm)({
|
|
98
|
+
message: `${scope}\u306E\u5C65\u6B74 ${targetSet.size} \u4EF6\u3092${action}\u3057\u307E\u3059\u3002\u5143\u306B\u623B\u305B\u307E\u305B\u3093\u3002\u3088\u308D\u3057\u3044\u3067\u3059\u304B?`,
|
|
99
|
+
initialValue: false
|
|
100
|
+
});
|
|
101
|
+
if (p.isCancel(confirmed) || !confirmed) {
|
|
102
|
+
p.cancel("\u30AD\u30E3\u30F3\u30BB\u30EB\u3057\u307E\u3057\u305F");
|
|
103
|
+
return 0;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
const lock = await waitForDataLock();
|
|
107
|
+
if (lock === null) {
|
|
108
|
+
console.error("\u5C65\u6B74\u306E\u66F4\u65B0\u30ED\u30C3\u30AF\u3092\u53D6\u5F97\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u5F8C\u3067\u3082\u3046\u4E00\u5EA6\u304A\u8A66\u3057\u304F\u3060\u3055\u3044 / history lock is busy");
|
|
109
|
+
return 1;
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
lines = existsSync(file) ? readLines(file) : [];
|
|
113
|
+
targetSet = collectTargets(lines, sub, cutoff);
|
|
114
|
+
if (!flags.yes && targetFingerprint(lines, targetSet) !== initialFingerprint) {
|
|
115
|
+
console.error(
|
|
116
|
+
"\u78BA\u8A8D\u4E2D\u306B\u5C65\u6B74\u304C\u5909\u66F4\u3055\u308C\u305F\u305F\u3081\u51E6\u7406\u3057\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u3082\u3046\u4E00\u5EA6\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044 / history changed; retry"
|
|
117
|
+
);
|
|
118
|
+
return 1;
|
|
119
|
+
}
|
|
120
|
+
invalidateCanonicalDashboards();
|
|
121
|
+
if (!existsSync(file)) {
|
|
122
|
+
console.log("\u5C65\u6B74\u304C\u3042\u308A\u307E\u305B\u3093(history.jsonl \u306F\u672A\u4F5C\u6210\u3067\u3059)\u3002");
|
|
123
|
+
return 0;
|
|
124
|
+
}
|
|
125
|
+
if (targetSet.size === 0) {
|
|
126
|
+
console.log(`\u5BFE\u8C61\u304C\u3042\u308A\u307E\u305B\u3093(${scope})\u3002`);
|
|
127
|
+
return 0;
|
|
128
|
+
}
|
|
129
|
+
try {
|
|
130
|
+
if (sub === "clear") {
|
|
131
|
+
const kept = lines.filter((_, i) => !targetSet.has(i)).map((l) => l.raw);
|
|
132
|
+
if (kept.length === 0) {
|
|
133
|
+
rmSync(file, { force: true });
|
|
134
|
+
} else {
|
|
135
|
+
atomicWrite(file, kept.join("\n") + "\n");
|
|
136
|
+
}
|
|
137
|
+
console.log(`\u5C65\u6B74 ${targetSet.size} \u4EF6\u3092\u524A\u9664\u3057\u307E\u3057\u305F(${scope})\u3002`);
|
|
138
|
+
} else {
|
|
139
|
+
const out = lines.map((l, i) => {
|
|
140
|
+
if (!targetSet.has(i) || l.rec === null) return l.raw;
|
|
141
|
+
return JSON.stringify({ ...l.rec, prompt: "" });
|
|
142
|
+
});
|
|
143
|
+
atomicWrite(file, out.join("\n") + "\n");
|
|
144
|
+
console.log(
|
|
145
|
+
`\u30D7\u30ED\u30F3\u30D7\u30C8\u5168\u6587\u3092 ${targetSet.size} \u4EF6\u6D88\u53BB\u3057\u307E\u3057\u305F(${scope}\u3002\u30B3\u30B9\u30C8\u96C6\u8A08\u30FB\u30C1\u30E3\u30FC\u30C8\u306F\u4FDD\u6301\u3055\u308C\u307E\u3059)\u3002`
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
} catch (err) {
|
|
149
|
+
console.error(
|
|
150
|
+
`\u5C65\u6B74\u306E\u66F4\u65B0\u306B\u5931\u6557\u3057\u307E\u3057\u305F / failed to update history: ${err instanceof Error ? err.message : String(err)}`
|
|
151
|
+
);
|
|
152
|
+
return 1;
|
|
153
|
+
}
|
|
154
|
+
invalidateCanonicalDashboards();
|
|
155
|
+
return 0;
|
|
156
|
+
} finally {
|
|
157
|
+
lock.release();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
export {
|
|
161
|
+
runHistory
|
|
162
|
+
};
|
|
@@ -3,11 +3,12 @@ import {
|
|
|
3
3
|
matchesMarker,
|
|
4
4
|
runInit,
|
|
5
5
|
runUninstall
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-5LHZOZZO.js";
|
|
7
|
+
import "./chunk-NV5UOHJA.js";
|
|
8
8
|
import "./chunk-DGXUSPS4.js";
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-HTYUYKFW.js";
|
|
10
|
+
import "./chunk-J5QAYTFE.js";
|
|
11
|
+
import "./chunk-26CISNOE.js";
|
|
11
12
|
export {
|
|
12
13
|
matchesMarker,
|
|
13
14
|
runInit,
|