@liuyoumi/codex-history 0.1.4 → 0.2.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/CHANGELOG.md +6 -0
- package/README.en.md +1 -5
- package/README.md +1 -5
- package/dist/cli.js +6 -56
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/README.en.md
CHANGED
|
@@ -159,7 +159,7 @@ For scripts or non-interactive shells, use `--force`:
|
|
|
159
159
|
codex-history purge-orphans --force
|
|
160
160
|
```
|
|
161
161
|
|
|
162
|
-
`--force` skips only interactive confirmation. It still keeps schema validation, active-thread protection, and post-purge verification.
|
|
162
|
+
`--force` skips only interactive confirmation. It still keeps schema validation, active-thread protection, and post-purge verification.
|
|
163
163
|
|
|
164
164
|
Space reporting is an estimate. After SQLite rows are deleted, database files may not shrink until Codex or another SQLite maintenance step runs vacuum.
|
|
165
165
|
|
|
@@ -167,13 +167,9 @@ Space reporting is an estimate. After SQLite rows are deleted, database files ma
|
|
|
167
167
|
|
|
168
168
|
```bash
|
|
169
169
|
codex-history --codex-home /path/to/.codex list
|
|
170
|
-
codex-history --json list --grep "Astro"
|
|
171
|
-
codex-history --json purge 019e6885 --force
|
|
172
170
|
```
|
|
173
171
|
|
|
174
172
|
- `--codex-home` defaults to `~/.codex`.
|
|
175
|
-
- `--json` prints machine-readable output. For `purge`, JSON output requires `--force` because interactive confirmation is text-only.
|
|
176
|
-
- `purge-orphans` does not support JSON output.
|
|
177
173
|
- Color is enabled only in interactive terminals and respects `NO_COLOR`.
|
|
178
174
|
|
|
179
175
|
## Safety
|
package/README.md
CHANGED
|
@@ -159,7 +159,7 @@ codex-history purge-orphans
|
|
|
159
159
|
codex-history purge-orphans --force
|
|
160
160
|
```
|
|
161
161
|
|
|
162
|
-
`--force` 只跳过交互确认,不会跳过数据结构校验、active thread
|
|
162
|
+
`--force` 只跳过交互确认,不会跳过数据结构校验、active thread 保护和删除后的验证。
|
|
163
163
|
|
|
164
164
|
空间统计是估算值。SQLite 删除记录后,数据库文件可能不会立刻缩小,直到 Codex 或其他 SQLite 维护步骤执行 vacuum。
|
|
165
165
|
|
|
@@ -167,13 +167,9 @@ codex-history purge-orphans --force
|
|
|
167
167
|
|
|
168
168
|
```bash
|
|
169
169
|
codex-history --codex-home /path/to/.codex list
|
|
170
|
-
codex-history --json list --grep "Astro"
|
|
171
|
-
codex-history --json purge 019e6885 --force
|
|
172
170
|
```
|
|
173
171
|
|
|
174
172
|
- `--codex-home` 默认是 `~/.codex`。
|
|
175
|
-
- `--json` 输出机器可读的 JSON。`purge` 使用 JSON 输出时必须加 `--force`,因为交互确认只适合文本模式。
|
|
176
|
-
- `purge-orphans` 不支持 JSON 输出。
|
|
177
173
|
- 颜色只会在交互式终端中启用,并遵守 `NO_COLOR`。
|
|
178
174
|
|
|
179
175
|
## 安全机制
|
package/dist/cli.js
CHANGED
|
@@ -1049,11 +1049,7 @@ function executePurgeOrphansPlanCommand(paths, plan) {
|
|
|
1049
1049
|
}
|
|
1050
1050
|
|
|
1051
1051
|
// src/core/output.ts
|
|
1052
|
-
function printOutput(value
|
|
1053
|
-
if (mode === "json") {
|
|
1054
|
-
console.log(JSON.stringify(value, null, 2));
|
|
1055
|
-
return;
|
|
1056
|
-
}
|
|
1052
|
+
function printOutput(value) {
|
|
1057
1053
|
if (typeof value === "string") {
|
|
1058
1054
|
if (value.length === 0) {
|
|
1059
1055
|
return;
|
|
@@ -1077,7 +1073,7 @@ function shortId(id) {
|
|
|
1077
1073
|
var TITLE_MAX_LENGTH = 80;
|
|
1078
1074
|
var packageVersion = JSON.parse(readFileSync5(new URL("../package.json", import.meta.url), "utf8")).version;
|
|
1079
1075
|
var program = new Command();
|
|
1080
|
-
program.name("codex-history").description("Inspect and safely purge local Codex conversation history.").version(packageVersion).option("--codex-home <path>", "Path to Codex home directory", "~/.codex")
|
|
1076
|
+
program.name("codex-history").description("Inspect and safely purge local Codex conversation history.").version(packageVersion).option("--codex-home <path>", "Path to Codex home directory", "~/.codex");
|
|
1081
1077
|
program.command("doctor").description("Check whether the local Codex data model is supported.").action(
|
|
1082
1078
|
() => runCommand(() => {
|
|
1083
1079
|
const report = doctorCommand(currentPaths());
|
|
@@ -1107,9 +1103,6 @@ program.command("purge").argument("<threadId>", "Codex thread id or unique short
|
|
|
1107
1103
|
const paths = currentPaths();
|
|
1108
1104
|
const plan = planPurgeCommand(paths, threadId);
|
|
1109
1105
|
const force = Boolean(options.force);
|
|
1110
|
-
if (currentOutputModeIsJson() && !force) {
|
|
1111
|
-
throw new UsageError("JSON purge output requires --force because interactive confirmation is text-only.");
|
|
1112
|
-
}
|
|
1113
1106
|
if (!force) {
|
|
1114
1107
|
await confirmPurge(plan);
|
|
1115
1108
|
}
|
|
@@ -1118,9 +1111,6 @@ program.command("purge").argument("<threadId>", "Codex thread id or unique short
|
|
|
1118
1111
|
);
|
|
1119
1112
|
program.command("purge-orphans").option("--force", "Skip interactive confirmation").description("Purge orphaned local Codex data after target confirmation.").action(
|
|
1120
1113
|
(options) => runCommand(async () => {
|
|
1121
|
-
if (currentOutputModeIsJson()) {
|
|
1122
|
-
throw new UsageError("purge-orphans does not support JSON output.");
|
|
1123
|
-
}
|
|
1124
1114
|
const paths = currentPaths();
|
|
1125
1115
|
const plan = planPurgeOrphansCommand(paths);
|
|
1126
1116
|
const force = Boolean(options.force);
|
|
@@ -1134,23 +1124,16 @@ program.command("purge-orphans").option("--force", "Skip interactive confirmatio
|
|
|
1134
1124
|
})
|
|
1135
1125
|
);
|
|
1136
1126
|
await program.parseAsync();
|
|
1137
|
-
function currentOutputMode() {
|
|
1138
|
-
return program.opts().json ? "json" : "text";
|
|
1139
|
-
}
|
|
1140
1127
|
function currentPaths() {
|
|
1141
1128
|
return resolvePaths(program.opts().codexHome);
|
|
1142
1129
|
}
|
|
1143
1130
|
async function runCommand(produce) {
|
|
1144
1131
|
try {
|
|
1145
|
-
printOutput(await produce()
|
|
1132
|
+
printOutput(await produce());
|
|
1146
1133
|
} catch (error) {
|
|
1147
1134
|
const exitCode = error instanceof CodexHistoryError ? error.exitCode : 1;
|
|
1148
1135
|
const message = error instanceof Error ? error.message : String(error);
|
|
1149
|
-
|
|
1150
|
-
console.error(JSON.stringify({ error: message, exitCode }, null, 2));
|
|
1151
|
-
} else {
|
|
1152
|
-
console.error(`${colorizeError("red", "Error:")} ${message}`);
|
|
1153
|
-
}
|
|
1136
|
+
console.error(`${colorizeError("red", "Error:")} ${message}`);
|
|
1154
1137
|
process.exitCode = exitCode;
|
|
1155
1138
|
}
|
|
1156
1139
|
}
|
|
@@ -1168,10 +1151,7 @@ function parsePretty(value) {
|
|
|
1168
1151
|
throw new Error(`Expected pretty format oneline, medium, or full; got: ${value}`);
|
|
1169
1152
|
}
|
|
1170
1153
|
function shouldUsePager(options) {
|
|
1171
|
-
return Boolean(options.limit === void 0 && process.stdout.isTTY
|
|
1172
|
-
}
|
|
1173
|
-
function currentOutputModeIsJson() {
|
|
1174
|
-
return currentOutputMode() === "json";
|
|
1154
|
+
return Boolean(options.limit === void 0 && process.stdout.isTTY);
|
|
1175
1155
|
}
|
|
1176
1156
|
async function confirmPurge(plan) {
|
|
1177
1157
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
@@ -1212,9 +1192,6 @@ async function confirmPurgeOrphans(plan) {
|
|
|
1212
1192
|
}
|
|
1213
1193
|
}
|
|
1214
1194
|
function formatDoctor(report) {
|
|
1215
|
-
if (currentOutputMode() === "json") {
|
|
1216
|
-
return report;
|
|
1217
|
-
}
|
|
1218
1195
|
const lines = [
|
|
1219
1196
|
`${colorize("dim", "Codex home:")} ${colorize("dim", report.codexHome)}`,
|
|
1220
1197
|
`${colorize("dim", "Supported:")} ${report.supported ? colorize("green", "yes") : colorize("red", "no")}`,
|
|
@@ -1226,9 +1203,6 @@ function formatDoctor(report) {
|
|
|
1226
1203
|
return lines.join("\n");
|
|
1227
1204
|
}
|
|
1228
1205
|
function formatThreads(threads, pretty = "oneline", usePager = false) {
|
|
1229
|
-
if (currentOutputMode() === "json") {
|
|
1230
|
-
return { count: threads.length, threads: threads.map(toPublicThread) };
|
|
1231
|
-
}
|
|
1232
1206
|
if (threads.length === 0) {
|
|
1233
1207
|
return "No Codex conversations found.";
|
|
1234
1208
|
}
|
|
@@ -1274,9 +1248,6 @@ function pageText(text) {
|
|
|
1274
1248
|
return "";
|
|
1275
1249
|
}
|
|
1276
1250
|
function formatPurgeResult(result) {
|
|
1277
|
-
if (currentOutputMode() === "json") {
|
|
1278
|
-
return sanitizePurgeResult(result);
|
|
1279
|
-
}
|
|
1280
1251
|
const lines = [
|
|
1281
1252
|
colorize("green", "Purge executed."),
|
|
1282
1253
|
"",
|
|
@@ -1473,7 +1444,7 @@ function errorColorsEnabled() {
|
|
|
1473
1444
|
return streamColorsEnabled(process.stderr);
|
|
1474
1445
|
}
|
|
1475
1446
|
function streamColorsEnabled(stream) {
|
|
1476
|
-
return !
|
|
1447
|
+
return !("NO_COLOR" in process.env) && Boolean(stream.isTTY);
|
|
1477
1448
|
}
|
|
1478
1449
|
function displayTitle(title) {
|
|
1479
1450
|
const normalized = title.trim().replaceAll(/\s+/g, " ");
|
|
@@ -1485,24 +1456,3 @@ function displayTitle(title) {
|
|
|
1485
1456
|
}
|
|
1486
1457
|
return `${normalized.slice(0, TITLE_MAX_LENGTH - 3)}...`;
|
|
1487
1458
|
}
|
|
1488
|
-
function toPublicThread(thread) {
|
|
1489
|
-
return {
|
|
1490
|
-
id: thread.id,
|
|
1491
|
-
title: displayTitle(thread.title),
|
|
1492
|
-
titleTruncated: thread.title.trim().replaceAll(/\s+/g, " ").length > TITLE_MAX_LENGTH,
|
|
1493
|
-
rolloutPath: thread.rolloutPath,
|
|
1494
|
-
createdAtMs: thread.createdAtMs,
|
|
1495
|
-
updatedAtMs: thread.updatedAtMs,
|
|
1496
|
-
cwd: thread.cwd,
|
|
1497
|
-
archived: thread.archived
|
|
1498
|
-
};
|
|
1499
|
-
}
|
|
1500
|
-
function sanitizePurgeResult(result) {
|
|
1501
|
-
return {
|
|
1502
|
-
...result,
|
|
1503
|
-
plan: {
|
|
1504
|
-
...result.plan,
|
|
1505
|
-
target: toPublicThread(result.plan.target)
|
|
1506
|
-
}
|
|
1507
|
-
};
|
|
1508
|
-
}
|