ccakashic 0.2.6 → 0.2.8
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/dist/bin/ccakashic.js +3 -3
- package/dist/discover.js +22 -3
- package/dist/html-generator.js +1 -1
- package/dist/pages.js +30 -2
- package/package.json +1 -1
package/dist/bin/ccakashic.js
CHANGED
|
@@ -64,7 +64,7 @@ const server = http.createServer(async (req, res) => {
|
|
|
64
64
|
return;
|
|
65
65
|
}
|
|
66
66
|
if (pathname === '/' || pathname === '') {
|
|
67
|
-
const projects = (0, discover_1.listProjects)();
|
|
67
|
+
const projects = await (0, discover_1.listProjects)();
|
|
68
68
|
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
69
69
|
res.end((0, pages_1.generateIndex)(projects));
|
|
70
70
|
return;
|
|
@@ -72,7 +72,7 @@ const server = http.createServer(async (req, res) => {
|
|
|
72
72
|
const projectMatch = pathname.match(/^\/project\/(.+)$/);
|
|
73
73
|
if (projectMatch && !pathname.includes('/session/')) {
|
|
74
74
|
const rawName = decodeURIComponent(projectMatch[1]);
|
|
75
|
-
const projects = (0, discover_1.listProjects)();
|
|
75
|
+
const projects = await (0, discover_1.listProjects)();
|
|
76
76
|
const project = projects.find((p) => p.rawName === rawName);
|
|
77
77
|
if (!project) {
|
|
78
78
|
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
|
@@ -88,7 +88,7 @@ const server = http.createServer(async (req, res) => {
|
|
|
88
88
|
if (sessionMatch) {
|
|
89
89
|
const rawName = decodeURIComponent(sessionMatch[1]);
|
|
90
90
|
const sessionId = decodeURIComponent(sessionMatch[2]);
|
|
91
|
-
const projects = (0, discover_1.listProjects)();
|
|
91
|
+
const projects = await (0, discover_1.listProjects)();
|
|
92
92
|
const project = projects.find((p) => p.rawName === rawName);
|
|
93
93
|
if (!project) {
|
|
94
94
|
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
package/dist/discover.js
CHANGED
|
@@ -51,7 +51,7 @@ function decodeDirName(dirName) {
|
|
|
51
51
|
}
|
|
52
52
|
return dirName;
|
|
53
53
|
}
|
|
54
|
-
function listProjects() {
|
|
54
|
+
async function listProjects() {
|
|
55
55
|
if (!fs.existsSync(exports.CLAUDE_DIR)) {
|
|
56
56
|
return [];
|
|
57
57
|
}
|
|
@@ -70,8 +70,17 @@ function listProjects() {
|
|
|
70
70
|
if (stat.mtimeMs > lastModified)
|
|
71
71
|
lastModified = stat.mtimeMs;
|
|
72
72
|
}
|
|
73
|
+
// Prefer the real cwd recorded in the session over the lossy directory-name
|
|
74
|
+
// decoding (dots and slashes both collapse to dashes in the dir name).
|
|
75
|
+
let name = decodeDirName(entry.name);
|
|
76
|
+
const latest = latestSessionFile(projectDir);
|
|
77
|
+
if (latest) {
|
|
78
|
+
const cwd = await readCwdFromSession(path.join(projectDir, latest.file));
|
|
79
|
+
if (cwd)
|
|
80
|
+
name = cwd;
|
|
81
|
+
}
|
|
73
82
|
projects.push({
|
|
74
|
-
name
|
|
83
|
+
name,
|
|
75
84
|
rawName: entry.name,
|
|
76
85
|
dir: projectDir,
|
|
77
86
|
sessionCount: jsonlFiles.length,
|
|
@@ -91,6 +100,8 @@ async function getSessionPreview(filePath) {
|
|
|
91
100
|
preview: '',
|
|
92
101
|
gitBranch: null,
|
|
93
102
|
slug: null,
|
|
103
|
+
customTitle: null,
|
|
104
|
+
aiTitle: null,
|
|
94
105
|
model: null,
|
|
95
106
|
hasSubagents: false,
|
|
96
107
|
totalTokens: 0,
|
|
@@ -117,6 +128,14 @@ async function getSessionPreview(filePath) {
|
|
|
117
128
|
if (!result.slug && obj.slug) {
|
|
118
129
|
result.slug = obj.slug;
|
|
119
130
|
}
|
|
131
|
+
// Title records can appear anywhere and be updated multiple times
|
|
132
|
+
// (e.g. renaming repeatedly), so keep the last non-empty value.
|
|
133
|
+
if (obj.type === 'custom-title' && obj.customTitle) {
|
|
134
|
+
result.customTitle = obj.customTitle;
|
|
135
|
+
}
|
|
136
|
+
if (obj.type === 'ai-title' && obj.aiTitle) {
|
|
137
|
+
result.aiTitle = obj.aiTitle;
|
|
138
|
+
}
|
|
120
139
|
if (!result.model && obj.type === 'assistant' && obj.message?.model) {
|
|
121
140
|
result.model = obj.message.model;
|
|
122
141
|
}
|
|
@@ -207,7 +226,7 @@ async function findSessionForCwd(cwd) {
|
|
|
207
226
|
// Pick the project whose cwd is the most specific (longest) match for the
|
|
208
227
|
// given cwd. A brand-new session in a specific subdir should win over an
|
|
209
228
|
// older, more-active ancestor project.
|
|
210
|
-
const projects = listProjects();
|
|
229
|
+
const projects = await listProjects();
|
|
211
230
|
let bestMatch = null;
|
|
212
231
|
let bestLen = -1;
|
|
213
232
|
for (const project of projects) {
|
package/dist/html-generator.js
CHANGED
|
@@ -300,7 +300,7 @@ function renderStats(stats) {
|
|
|
300
300
|
}
|
|
301
301
|
function generate(parsed, options = {}) {
|
|
302
302
|
const { projectName, session, backUrl } = options;
|
|
303
|
-
const title = session?.slug || session?.id || 'Session';
|
|
303
|
+
const title = session?.customTitle || session?.aiTitle || session?.slug || session?.id || 'Session';
|
|
304
304
|
const date = session?.timestamp
|
|
305
305
|
? new Date(session.timestamp).toLocaleDateString('en-CA')
|
|
306
306
|
: '';
|
package/dist/pages.js
CHANGED
|
@@ -97,6 +97,12 @@ function indexCSS() {
|
|
|
97
97
|
font-size: 0.95rem;
|
|
98
98
|
margin-bottom: 4px;
|
|
99
99
|
}
|
|
100
|
+
.list-item-name {
|
|
101
|
+
font-size: 1.02rem;
|
|
102
|
+
}
|
|
103
|
+
.list-item-name.is-named {
|
|
104
|
+
color: var(--link);
|
|
105
|
+
}
|
|
100
106
|
.list-item-meta {
|
|
101
107
|
font-size: 0.8rem;
|
|
102
108
|
color: var(--text-muted);
|
|
@@ -121,6 +127,16 @@ function indexCSS() {
|
|
|
121
127
|
background: var(--tool-bg);
|
|
122
128
|
border: 1px solid var(--border);
|
|
123
129
|
}
|
|
130
|
+
.badge-named {
|
|
131
|
+
background: var(--link);
|
|
132
|
+
border-color: var(--link);
|
|
133
|
+
color: #fff;
|
|
134
|
+
}
|
|
135
|
+
.badge-ai {
|
|
136
|
+
background: transparent;
|
|
137
|
+
border-color: var(--link);
|
|
138
|
+
color: var(--link);
|
|
139
|
+
}
|
|
124
140
|
.search-box {
|
|
125
141
|
width: 100%;
|
|
126
142
|
padding: 10px 14px;
|
|
@@ -303,9 +319,21 @@ function generateSessionList(project, sessions) {
|
|
|
303
319
|
const tokens = s.totalTokens ? `<span>${formatTokens(s.totalTokens)} tokens</span>` : '';
|
|
304
320
|
const outTok = s.outputTokens ? `<span>out: ${formatTokens(s.outputTokens)}</span>` : '';
|
|
305
321
|
const preview = s.preview ? `<div class="list-item-preview">${escapeHtml(s.preview)}</div>` : '';
|
|
322
|
+
// Prefer a human/AI-given name as the headline; renamed sessions get a
|
|
323
|
+
// distinct treatment so they're easy to spot in the list.
|
|
324
|
+
const displayName = s.customTitle || s.aiTitle;
|
|
325
|
+
const nameBadge = s.customTitle
|
|
326
|
+
? '<span class="badge badge-named">named</span>'
|
|
327
|
+
: s.aiTitle
|
|
328
|
+
? '<span class="badge badge-ai">AI</span>'
|
|
329
|
+
: '';
|
|
330
|
+
const titleRow = displayName
|
|
331
|
+
? `<div class="list-item-title"><span class="list-item-name${s.customTitle ? ' is-named' : ''}">${escapeHtml(displayName)}</span> ${nameBadge} ${slug} ${sub}</div>
|
|
332
|
+
<div class="list-item-meta"><span>${lastModTime}</span><span>started: ${startedTime}</span>${model}${branch}${tokens}${outTok}</div>`
|
|
333
|
+
: `<div class="list-item-title">${lastModTime} ${slug} ${sub}</div>
|
|
334
|
+
<div class="list-item-meta"><span>started: ${startedTime}</span>${model}${branch}${tokens}${outTok}</div>`;
|
|
306
335
|
return `<a class="list-item" href="${href}">
|
|
307
|
-
|
|
308
|
-
<div class="list-item-meta"><span>started: ${startedTime}</span>${model}${branch}${tokens}${outTok}</div>
|
|
336
|
+
${titleRow}
|
|
309
337
|
${preview}
|
|
310
338
|
</a>`;
|
|
311
339
|
}).join('\n');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ccakashic",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
4
4
|
"description": "Browse Claude Code session logs (~/.claude/projects/) as beautiful HTML in your browser — an Akashic Record of your Claude Code sessions",
|
|
5
5
|
"bin": {
|
|
6
6
|
"ccakashic": "dist/bin/ccakashic.js"
|