chat-logbook 0.8.0 → 0.9.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 +4 -0
- package/api/dist/drizzle/archive/0006_add_project_path.sql +1 -0
- package/api/dist/drizzle/archive/meta/_journal.json +7 -0
- package/api/dist/index.js +40 -11
- package/package.json +1 -1
- package/web/dist/assets/index-BCIIypHs.js +57 -0
- package/web/dist/assets/index-rSLP4i1P.css +2 -0
- package/web/dist/index.html +2 -2
- package/web/dist/assets/index-1hCPKEIk.js +0 -46
- package/web/dist/assets/index-BCVd1SRQ.css +0 -2
package/README.md
CHANGED
|
@@ -69,6 +69,10 @@ The full problem statement, user stories, and direction live in the
|
|
|
69
69
|
- **Live updates.** While Claude Code is actively writing to a chat,
|
|
70
70
|
new messages appear in chat-logbook within seconds — no restart
|
|
71
71
|
needed.
|
|
72
|
+
- **Chat metadata at a glance.** A ⓘ button on the conversation
|
|
73
|
+
header opens a popover showing when the chat started, when it was
|
|
74
|
+
last updated, the agent, the project working directory, and the
|
|
75
|
+
chat's IDs — with one-click copy.
|
|
72
76
|
|
|
73
77
|
## Quick start
|
|
74
78
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ALTER TABLE `chats` ADD `project_path` text;
|
package/api/dist/index.js
CHANGED
|
@@ -8187,7 +8187,8 @@ var chats = sqliteTable(
|
|
|
8187
8187
|
agent: text("agent").notNull(),
|
|
8188
8188
|
sourceId: text("source_id").notNull(),
|
|
8189
8189
|
firstSeenAt: integer("first_seen_at", { mode: "timestamp_ms" }).notNull(),
|
|
8190
|
-
project: text("project")
|
|
8190
|
+
project: text("project"),
|
|
8191
|
+
projectPath: text("project_path")
|
|
8191
8192
|
},
|
|
8192
8193
|
(t) => [uniqueIndex("chats_agent_source_idx").on(t.agent, t.sourceId)]
|
|
8193
8194
|
);
|
|
@@ -8285,18 +8286,32 @@ function createApp({ archive: archive2, metadata: metadata2, webDistDir: webDist
|
|
|
8285
8286
|
for (const row of rows) {
|
|
8286
8287
|
if (!visibility.isVisible(row.id)) continue;
|
|
8287
8288
|
const isDeleted = visibility.isTrashed(row.id);
|
|
8288
|
-
const
|
|
8289
|
+
const latestRaw = archive2.db.select({ sourcePath: rawMessages.sourcePath }).from(rawMessages).where(
|
|
8290
|
+
and(
|
|
8291
|
+
eq(rawMessages.agent, CLAUDE_CODE_AGENT),
|
|
8292
|
+
eq(rawMessages.sourceId, row.sourceId)
|
|
8293
|
+
)
|
|
8294
|
+
).orderBy(desc(rawMessages.ingestedAt)).limit(1).get();
|
|
8295
|
+
const tsRange = archive2.db.select({
|
|
8296
|
+
minTs: sql`min(${messages.ts})`,
|
|
8297
|
+
maxTs: sql`max(${messages.ts})`
|
|
8298
|
+
}).from(messages).where(
|
|
8289
8299
|
and(
|
|
8290
8300
|
eq(messages.agent, CLAUDE_CODE_AGENT),
|
|
8291
8301
|
eq(messages.sourceId, row.sourceId)
|
|
8292
8302
|
)
|
|
8293
|
-
).
|
|
8303
|
+
).get();
|
|
8304
|
+
const firstSeenAtMs = row.firstSeenAt.getTime();
|
|
8294
8305
|
const chat = {
|
|
8295
8306
|
id: row.sourceId,
|
|
8307
|
+
chatId: row.chatId,
|
|
8308
|
+
agent: row.agent,
|
|
8296
8309
|
title: deriveTitle(archive2, metadata2, row),
|
|
8297
8310
|
project: row.project ?? "",
|
|
8298
|
-
|
|
8299
|
-
|
|
8311
|
+
projectPath: row.projectPath ?? null,
|
|
8312
|
+
sourceFilePath: latestRaw?.sourcePath ?? null,
|
|
8313
|
+
createdAt: tsRange?.minTs ?? firstSeenAtMs,
|
|
8314
|
+
updatedAt: tsRange?.maxTs ?? firstSeenAtMs
|
|
8300
8315
|
};
|
|
8301
8316
|
if (isDeleted) chat.isDeleted = true;
|
|
8302
8317
|
chats2.push(chat);
|
|
@@ -8795,7 +8810,14 @@ async function runIngestion(opts) {
|
|
|
8795
8810
|
eq(chatScanState.sourceId, ref.sourceId)
|
|
8796
8811
|
)
|
|
8797
8812
|
).get();
|
|
8798
|
-
ensureChat(
|
|
8813
|
+
ensureChat(
|
|
8814
|
+
opts.archive,
|
|
8815
|
+
plugin.id,
|
|
8816
|
+
ref.sourceId,
|
|
8817
|
+
now(),
|
|
8818
|
+
ref.project,
|
|
8819
|
+
ref.projectPath
|
|
8820
|
+
);
|
|
8799
8821
|
if (stat4 && prior && prior.lastMtimeMs === stat4.mtimeMs && prior.lastSizeBytes === stat4.size) {
|
|
8800
8822
|
result.skippedByMtime += 1;
|
|
8801
8823
|
continue;
|
|
@@ -8880,11 +8902,16 @@ function recordScanState(archive2, agent, sourceId, sourcePath, stat4, scannedAt
|
|
|
8880
8902
|
}).run();
|
|
8881
8903
|
}
|
|
8882
8904
|
}
|
|
8883
|
-
function ensureChat(archive2, agent, sourceId, firstSeenAt, project) {
|
|
8905
|
+
function ensureChat(archive2, agent, sourceId, firstSeenAt, project, projectPath) {
|
|
8884
8906
|
const existing = archive2.db.select().from(chats).where(and(eq(chats.agent, agent), eq(chats.sourceId, sourceId))).get();
|
|
8885
8907
|
if (existing) {
|
|
8886
|
-
|
|
8887
|
-
|
|
8908
|
+
const updates = {};
|
|
8909
|
+
if (project && existing.project !== project) updates.project = project;
|
|
8910
|
+
if (projectPath && existing.projectPath !== projectPath) {
|
|
8911
|
+
updates.projectPath = projectPath;
|
|
8912
|
+
}
|
|
8913
|
+
if (Object.keys(updates).length > 0) {
|
|
8914
|
+
archive2.db.update(chats).set(updates).where(eq(chats.id, existing.id)).run();
|
|
8888
8915
|
}
|
|
8889
8916
|
return existing.id;
|
|
8890
8917
|
}
|
|
@@ -8896,7 +8923,8 @@ function ensureChat(archive2, agent, sourceId, firstSeenAt, project) {
|
|
|
8896
8923
|
agent,
|
|
8897
8924
|
sourceId,
|
|
8898
8925
|
firstSeenAt,
|
|
8899
|
-
project: project ?? null
|
|
8926
|
+
project: project ?? null,
|
|
8927
|
+
projectPath: projectPath ?? null
|
|
8900
8928
|
}).run();
|
|
8901
8929
|
return id;
|
|
8902
8930
|
}
|
|
@@ -10786,7 +10814,8 @@ var ClaudeCodePlugin = class {
|
|
|
10786
10814
|
sourceId,
|
|
10787
10815
|
sourcePath,
|
|
10788
10816
|
watchPaths: [sourcePath],
|
|
10789
|
-
project: cwd ? path3.basename(cwd) : void 0
|
|
10817
|
+
project: cwd ? path3.basename(cwd) : void 0,
|
|
10818
|
+
projectPath: cwd ?? void 0
|
|
10790
10819
|
};
|
|
10791
10820
|
}
|
|
10792
10821
|
}
|