@liuyoumi/codex-history 0.3.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/CHANGELOG.md +6 -0
- package/README.en.md +16 -0
- package/README.md +16 -0
- package/dist/cli.js +65 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/README.en.md
CHANGED
|
@@ -52,6 +52,8 @@ codex-history list
|
|
|
52
52
|
codex-history list --grep "Astro"
|
|
53
53
|
codex-history purge 019e6885
|
|
54
54
|
codex-history purge 019e6885 019e6874
|
|
55
|
+
codex-history purge --cwd /Users/me/Projects/example
|
|
56
|
+
codex-history purge --grep "Astro"
|
|
55
57
|
codex-history purge-orphans
|
|
56
58
|
```
|
|
57
59
|
|
|
@@ -77,6 +79,8 @@ Type 019e6885 to confirm:
|
|
|
77
79
|
| `codex-history list` | List local conversations. |
|
|
78
80
|
| `codex-history list --grep <keyword>` | Filter conversations by title, id, or cwd. |
|
|
79
81
|
| `codex-history purge <id...>` | Remove one or more resolved local conversations after confirmation. |
|
|
82
|
+
| `codex-history purge --cwd <path>` | Remove local conversations matching a working directory after confirmation. |
|
|
83
|
+
| `codex-history purge --grep <keyword>` | Remove local conversations matching title, id, or cwd after confirmation. |
|
|
80
84
|
| `codex-history purge-orphans` | Remove orphaned local data after confirmation. |
|
|
81
85
|
|
|
82
86
|
### `doctor`
|
|
@@ -139,11 +143,23 @@ codex-history purge 019e6885 019e6874
|
|
|
139
143
|
|
|
140
144
|
When multiple targets are provided, the tool resolves all targets and prints a batch plan before deletion. If any id is missing, ambiguous, or active, the whole batch is refused before mutation. Interactive batch purge requires typing `purge-selected`.
|
|
141
145
|
|
|
146
|
+
You can also select local conversations with filters:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
codex-history purge --cwd /Users/me/Projects/example
|
|
150
|
+
codex-history purge --grep "Astro"
|
|
151
|
+
codex-history purge --archived
|
|
152
|
+
codex-history purge --cwd /Users/me/Projects/example --grep "Astro"
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
`--cwd`, `--grep`, and `--archived` can be combined. Combined filters delete only conversations that match every provided condition. By default, filter mode matches non-archived conversations only; use `--archived` to target archived conversations. Filtered purge prints a batch plan and requires typing `purge-selected`. Filters cannot be combined with explicit ids.
|
|
156
|
+
|
|
142
157
|
For scripts or non-interactive shells, use `--force`:
|
|
143
158
|
|
|
144
159
|
```bash
|
|
145
160
|
codex-history purge 019e6885 --force
|
|
146
161
|
codex-history purge 019e6885 019e6874 --force
|
|
162
|
+
codex-history purge --cwd /Users/me/Projects/example --force
|
|
147
163
|
```
|
|
148
164
|
|
|
149
165
|
`--force` skips only interactive confirmation. It still keeps schema validation, active-thread protection, and post-purge verification.
|
package/README.md
CHANGED
|
@@ -52,6 +52,8 @@ codex-history list
|
|
|
52
52
|
codex-history list --grep "Astro"
|
|
53
53
|
codex-history purge 019e6885
|
|
54
54
|
codex-history purge 019e6885 019e6874
|
|
55
|
+
codex-history purge --cwd /Users/me/Projects/example
|
|
56
|
+
codex-history purge --grep "Astro"
|
|
55
57
|
codex-history purge-orphans
|
|
56
58
|
```
|
|
57
59
|
|
|
@@ -77,6 +79,8 @@ Type 019e6885 to confirm:
|
|
|
77
79
|
| `codex-history list` | 列出本地对话。 |
|
|
78
80
|
| `codex-history list --grep <keyword>` | 按标题、id 或 cwd 过滤对话。 |
|
|
79
81
|
| `codex-history purge <id...>` | 确认后删除一条或多条解析到的本地对话。 |
|
|
82
|
+
| `codex-history purge --cwd <path>` | 确认后删除匹配工作目录的本地对话。 |
|
|
83
|
+
| `codex-history purge --grep <keyword>` | 确认后删除匹配标题、id 或 cwd 的本地对话。 |
|
|
80
84
|
| `codex-history purge-orphans` | 确认后清理本地孤儿数据。 |
|
|
81
85
|
|
|
82
86
|
### `doctor`
|
|
@@ -139,11 +143,23 @@ codex-history purge 019e6885 019e6874
|
|
|
139
143
|
|
|
140
144
|
删除多个目标时,工具会先解析全部目标并展示批量计划;只要任意一个 id 不存在、不唯一,或命中 active thread,整个批量操作都会拒绝执行,不会部分删除。交互式批量删除需要输入 `purge-selected` 确认。
|
|
141
145
|
|
|
146
|
+
也可以直接用过滤条件选择要删除的本地对话:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
codex-history purge --cwd /Users/me/Projects/example
|
|
150
|
+
codex-history purge --grep "Astro"
|
|
151
|
+
codex-history purge --archived
|
|
152
|
+
codex-history purge --cwd /Users/me/Projects/example --grep "Astro"
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
`--cwd`、`--grep`、`--archived` 可以组合,组合后只删除同时满足全部条件的对话。默认只匹配未归档对话;如果要删除已归档对话,请使用 `--archived`。过滤式删除会展示批量计划,并要求输入 `purge-selected` 确认。过滤条件不能和 id 同时使用。
|
|
156
|
+
|
|
142
157
|
脚本或非交互环境可以使用 `--force`:
|
|
143
158
|
|
|
144
159
|
```bash
|
|
145
160
|
codex-history purge 019e6885 --force
|
|
146
161
|
codex-history purge 019e6885 019e6874 --force
|
|
162
|
+
codex-history purge --cwd /Users/me/Projects/example --force
|
|
147
163
|
```
|
|
148
164
|
|
|
149
165
|
`--force` 只跳过交互确认,不会跳过数据结构校验、active thread 保护和删除后的验证。
|
package/dist/cli.js
CHANGED
|
@@ -853,11 +853,35 @@ function planBatchPurgeCommand(paths, threadIds) {
|
|
|
853
853
|
}
|
|
854
854
|
return {
|
|
855
855
|
mode: "planned",
|
|
856
|
+
source: "explicit",
|
|
856
857
|
requestedCount: threadIds.length,
|
|
857
858
|
plans,
|
|
858
859
|
duplicateInputs
|
|
859
860
|
};
|
|
860
861
|
}
|
|
862
|
+
function planFilteredPurgeCommand(paths, filters) {
|
|
863
|
+
validateSupportedDataModel(paths);
|
|
864
|
+
if (!hasPurgeFilter(filters)) {
|
|
865
|
+
throw new UsageError("Provide thread id(s) or at least one filter such as --cwd, --grep, or --archived.");
|
|
866
|
+
}
|
|
867
|
+
const listOptions = {
|
|
868
|
+
cwd: filters.cwd,
|
|
869
|
+
grep: filters.grep,
|
|
870
|
+
archived: filters.archived
|
|
871
|
+
};
|
|
872
|
+
const targets = listThreads(paths, listOptions);
|
|
873
|
+
return {
|
|
874
|
+
mode: "planned",
|
|
875
|
+
source: "filtered",
|
|
876
|
+
requestedCount: targets.length,
|
|
877
|
+
plans: targets.map((target) => buildPurgePlan(paths, target)),
|
|
878
|
+
filters,
|
|
879
|
+
duplicateInputs: []
|
|
880
|
+
};
|
|
881
|
+
}
|
|
882
|
+
function hasPurgeFilter(filters) {
|
|
883
|
+
return Boolean(filters.cwd || filters.grep || filters.archived);
|
|
884
|
+
}
|
|
861
885
|
function executePurgePlanCommand(paths, plan) {
|
|
862
886
|
validateSupportedDataModel(paths);
|
|
863
887
|
return executePurge(paths, plan);
|
|
@@ -1130,12 +1154,29 @@ program.command("list").description("List local Codex conversations.").option("-
|
|
|
1130
1154
|
)
|
|
1131
1155
|
)
|
|
1132
1156
|
);
|
|
1133
|
-
program.command("purge").argument("
|
|
1157
|
+
program.command("purge").argument("[threadIds...]", "Codex thread id(s) or unique short id prefix(es) to purge").option("--force", "Skip interactive confirmation").option("--cwd <path>", "Filter conversations by exact working directory").option("--grep <keyword>", "Filter conversations by title, id, or cwd keyword").option("--archived", "Filter archived conversations").description("Purge local Codex conversation(s) after target confirmation.").action(
|
|
1134
1158
|
(threadIds, options) => runCommand(async () => {
|
|
1135
1159
|
const paths = currentPaths();
|
|
1136
|
-
const
|
|
1160
|
+
const requestedThreadIds = threadIds ?? [];
|
|
1161
|
+
const filters = {
|
|
1162
|
+
cwd: options.cwd,
|
|
1163
|
+
grep: options.grep,
|
|
1164
|
+
archived: Boolean(options.archived)
|
|
1165
|
+
};
|
|
1166
|
+
const hasExplicitTargets = requestedThreadIds.length > 0;
|
|
1167
|
+
const hasFilters = hasPurgeFilter(filters);
|
|
1168
|
+
if (hasExplicitTargets && hasFilters) {
|
|
1169
|
+
throw new UsageError("Thread ids cannot be combined with --cwd, --grep, or --archived.");
|
|
1170
|
+
}
|
|
1171
|
+
if (!hasExplicitTargets && !hasFilters) {
|
|
1172
|
+
throw new UsageError("Provide thread id(s) or at least one filter such as --cwd, --grep, or --archived.");
|
|
1173
|
+
}
|
|
1174
|
+
const plan = hasExplicitTargets ? planBatchPurgeCommand(paths, requestedThreadIds) : planFilteredPurgeCommand(paths, filters);
|
|
1137
1175
|
const force = Boolean(options.force);
|
|
1138
|
-
const useBatchConfirmation = plan.requestedCount > 1;
|
|
1176
|
+
const useBatchConfirmation = plan.source === "filtered" || plan.requestedCount > 1;
|
|
1177
|
+
if (plan.plans.length === 0) {
|
|
1178
|
+
return "No matching local Codex conversations found.";
|
|
1179
|
+
}
|
|
1139
1180
|
if (plan.plans.length === 1 && !useBatchConfirmation) {
|
|
1140
1181
|
if (!force) {
|
|
1141
1182
|
await confirmPurge(plan.plans[0]);
|
|
@@ -1343,7 +1384,7 @@ function formatBatchPurgeResult(result) {
|
|
|
1343
1384
|
colorize("green", "Batch purge executed."),
|
|
1344
1385
|
"",
|
|
1345
1386
|
"Summary:",
|
|
1346
|
-
`-
|
|
1387
|
+
`- Selection: ${formatBatchPurgeSelection(result.plan)}`,
|
|
1347
1388
|
`- Unique targets purged: ${result.plan.plans.length}`,
|
|
1348
1389
|
`- Duplicate inputs skipped: ${result.plan.duplicateInputs.length}`,
|
|
1349
1390
|
`- SQLite row changes: ${sqliteChanges.reduce((sum, change) => sum + change.rows, 0)}`,
|
|
@@ -1424,7 +1465,7 @@ function formatBatchPurgeConfirmation(plan) {
|
|
|
1424
1465
|
return [
|
|
1425
1466
|
"About to purge selected local Codex conversations:",
|
|
1426
1467
|
"",
|
|
1427
|
-
`
|
|
1468
|
+
`Selection: ${formatBatchPurgeSelection(plan)}`,
|
|
1428
1469
|
`Unique targets: ${plan.plans.length}`,
|
|
1429
1470
|
`Duplicate inputs skipped: ${plan.duplicateInputs.length}`,
|
|
1430
1471
|
"",
|
|
@@ -1436,6 +1477,25 @@ function formatBatchPurgeConfirmation(plan) {
|
|
|
1436
1477
|
""
|
|
1437
1478
|
].join("\n");
|
|
1438
1479
|
}
|
|
1480
|
+
function formatBatchPurgeSelection(plan) {
|
|
1481
|
+
if (plan.source === "explicit") {
|
|
1482
|
+
return `${plan.requestedCount} requested target(s)`;
|
|
1483
|
+
}
|
|
1484
|
+
return formatPurgeFilters(plan.filters ?? {});
|
|
1485
|
+
}
|
|
1486
|
+
function formatPurgeFilters(filters) {
|
|
1487
|
+
const parts = [];
|
|
1488
|
+
if (filters.cwd) {
|
|
1489
|
+
parts.push(`cwd=${filters.cwd}`);
|
|
1490
|
+
}
|
|
1491
|
+
if (filters.grep) {
|
|
1492
|
+
parts.push(`grep=${filters.grep}`);
|
|
1493
|
+
}
|
|
1494
|
+
if (filters.archived) {
|
|
1495
|
+
parts.push("archived=true");
|
|
1496
|
+
}
|
|
1497
|
+
return parts.length > 0 ? parts.join(", ") : "filtered conversations";
|
|
1498
|
+
}
|
|
1439
1499
|
function formatPurgeOrphansConfirmation(plan) {
|
|
1440
1500
|
return [
|
|
1441
1501
|
"About to purge orphaned local Codex data:",
|