chat-logbook 0.16.0 → 0.17.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 CHANGED
@@ -37,7 +37,7 @@ The full problem statement, user stories, and direction live in the [PRD](docs/P
37
37
  - **Solarized Dark theme.** Easy on the eyes, consistent with Claude
38
38
  Code's terminal look.
39
39
  - **Soft delete with Trash.** Hide chats you don't want to see; restore
40
- them anytime.
40
+ them anytime. Select several at once to move them together.
41
41
  - **Sortable lists.** Sort your chats by title, created time, or updated time, and the choice sticks between visits. Trash sorts independently — by deleted time by default.
42
42
  - **Custom chat titles.** Rename any chat — click its title in the list or conversation header, or select it and press `F2` / `↵`. Clear the title to fall back to the first message.
43
43
  - **Keyboard navigation.** Walk the chat list with `↑` / `↓` — each row you land on opens, and clicking a row picks up where the arrows continue from.
package/api/dist/index.js CHANGED
@@ -3500,6 +3500,39 @@ function createApp({
3500
3500
  });
3501
3501
  return c.json({ total });
3502
3502
  });
3503
+ async function resolveBatchIds(c) {
3504
+ let body;
3505
+ try {
3506
+ body = await c.req.json();
3507
+ } catch {
3508
+ return null;
3509
+ }
3510
+ const chatIds = body?.chatIds;
3511
+ if (!Array.isArray(chatIds)) return null;
3512
+ const internalIds = [];
3513
+ for (const wireId of chatIds) {
3514
+ if (typeof wireId !== "string") continue;
3515
+ const row = reader.findChat(wireId);
3516
+ if (row) internalIds.push(row.id);
3517
+ }
3518
+ return internalIds;
3519
+ }
3520
+ app2.post("/api/chats/batch/trash", async (c) => {
3521
+ const internalIds = await resolveBatchIds(c);
3522
+ if (internalIds === null) {
3523
+ return c.json({ error: "Invalid chatIds" }, 400);
3524
+ }
3525
+ metadata2.softDeleteBatch(internalIds);
3526
+ return c.json({ count: internalIds.length });
3527
+ });
3528
+ app2.post("/api/chats/batch/restore", async (c) => {
3529
+ const internalIds = await resolveBatchIds(c);
3530
+ if (internalIds === null) {
3531
+ return c.json({ error: "Invalid chatIds" }, 400);
3532
+ }
3533
+ metadata2.restoreBatch(internalIds);
3534
+ return c.json({ count: internalIds.length });
3535
+ });
3503
3536
  app2.delete("/api/chats/:id", (c) => {
3504
3537
  const row = reader.findChat(c.req.param("id"));
3505
3538
  if (!row) {
@@ -9734,6 +9767,31 @@ function createMetadataRepository({
9734
9767
  const now = /* @__PURE__ */ new Date();
9735
9768
  db.update(chatsMeta).set({ isDeleted: false, updatedAt: now, deletedAt: null }).where(eq(chatsMeta.id, internalId)).run();
9736
9769
  },
9770
+ softDeleteBatch(internalIds) {
9771
+ if (internalIds.length === 0) return;
9772
+ const now = /* @__PURE__ */ new Date();
9773
+ db.transaction((tx) => {
9774
+ for (const id of internalIds) {
9775
+ tx.insert(chatsMeta).values({
9776
+ id,
9777
+ isDeleted: true,
9778
+ createdAt: now,
9779
+ updatedAt: now,
9780
+ deletedAt: now
9781
+ }).onConflictDoUpdate({
9782
+ target: chatsMeta.id,
9783
+ set: { isDeleted: true, updatedAt: now, deletedAt: now }
9784
+ }).run();
9785
+ }
9786
+ });
9787
+ },
9788
+ restoreBatch(internalIds) {
9789
+ if (internalIds.length === 0) return;
9790
+ const now = /* @__PURE__ */ new Date();
9791
+ db.transaction((tx) => {
9792
+ tx.update(chatsMeta).set({ isDeleted: false, updatedAt: now, deletedAt: null }).where(inArray(chatsMeta.id, internalIds)).run();
9793
+ });
9794
+ },
9737
9795
  isDeleted(internalId) {
9738
9796
  const row = db.select({ isDeleted: chatsMeta.isDeleted }).from(chatsMeta).where(eq(chatsMeta.id, internalId)).get();
9739
9797
  return row?.isDeleted ?? false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chat-logbook",
3
- "version": "0.16.0",
3
+ "version": "0.17.0",
4
4
  "description": "A local-first conversation manager for Claude Code",
5
5
  "license": "AGPL-3.0-only",
6
6
  "type": "module",