agentacta 1.1.3 → 1.1.4
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/db.js +2 -1
- package/indexer.js +48 -1
- package/package.json +1 -1
- package/public/app.js +10 -0
- package/public/style.css +1 -0
package/db.js
CHANGED
|
@@ -115,6 +115,7 @@ function init(dbPath) {
|
|
|
115
115
|
if (!cols.includes('cache_read_tokens')) db.exec("ALTER TABLE sessions ADD COLUMN cache_read_tokens INTEGER DEFAULT 0");
|
|
116
116
|
if (!cols.includes('cache_write_tokens')) db.exec("ALTER TABLE sessions ADD COLUMN cache_write_tokens INTEGER DEFAULT 0");
|
|
117
117
|
if (!cols.includes('models')) db.exec("ALTER TABLE sessions ADD COLUMN models TEXT");
|
|
118
|
+
if (!cols.includes('projects')) db.exec("ALTER TABLE sessions ADD COLUMN projects TEXT");
|
|
118
119
|
|
|
119
120
|
db.close();
|
|
120
121
|
}
|
|
@@ -127,7 +128,7 @@ function createStmts(db) {
|
|
|
127
128
|
deleteSession: db.prepare('DELETE FROM sessions WHERE id = ?'),
|
|
128
129
|
deleteFileActivity: db.prepare('DELETE FROM file_activity WHERE session_id = ?'),
|
|
129
130
|
insertEvent: db.prepare(`INSERT OR REPLACE INTO events (id, session_id, timestamp, type, role, content, tool_name, tool_args, tool_result) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`),
|
|
130
|
-
upsertSession: db.prepare(`INSERT OR REPLACE INTO sessions (id, start_time, end_time, message_count, tool_count, model, summary, agent, session_type, total_cost, total_tokens, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens, initial_prompt, first_message_id, first_message_timestamp, models) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`),
|
|
131
|
+
upsertSession: db.prepare(`INSERT OR REPLACE INTO sessions (id, start_time, end_time, message_count, tool_count, model, summary, agent, session_type, total_cost, total_tokens, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens, initial_prompt, first_message_id, first_message_timestamp, models, projects) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`),
|
|
131
132
|
upsertState: db.prepare(`INSERT OR REPLACE INTO index_state (file_path, last_offset, last_modified) VALUES (?, ?, ?)`),
|
|
132
133
|
insertFileActivity: db.prepare(`INSERT INTO file_activity (session_id, file_path, operation, timestamp) VALUES (?, ?, ?, ?)`),
|
|
133
134
|
deleteArchive: db.prepare('DELETE FROM archive WHERE session_id = ?'),
|
package/indexer.js
CHANGED
|
@@ -107,6 +107,38 @@ function extractFilePaths(toolName, toolArgs) {
|
|
|
107
107
|
return paths;
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
function extractProjectFromPath(filePath) {
|
|
111
|
+
if (!filePath || typeof filePath !== 'string') return null;
|
|
112
|
+
|
|
113
|
+
const normalized = filePath.replace(/\\/g, '/');
|
|
114
|
+
|
|
115
|
+
// Relative paths are usually from workspace cwd -> treat as workspace activity
|
|
116
|
+
if (!normalized.startsWith('/') && !normalized.startsWith('~')) return 'workspace';
|
|
117
|
+
|
|
118
|
+
let rel = normalized
|
|
119
|
+
.replace(/^\/home\/[^/]+\//, '')
|
|
120
|
+
.replace(/^\/Users\/[^/]+\//, '')
|
|
121
|
+
.replace(/^~\//, '');
|
|
122
|
+
|
|
123
|
+
const parts = rel.split('/').filter(Boolean);
|
|
124
|
+
if (!parts.length) return null;
|
|
125
|
+
|
|
126
|
+
// Common repo location: ~/Developer/<repo>/...
|
|
127
|
+
if (parts[0] === 'Developer' && parts[1]) return parts[1];
|
|
128
|
+
|
|
129
|
+
// OpenClaw workspace and agent stores
|
|
130
|
+
if (parts[0] === '.openclaw' && parts[1] === 'workspace') return 'workspace';
|
|
131
|
+
if (parts[0] === '.openclaw' && parts[1] === 'agents' && parts[2]) return `agent:${parts[2]}`;
|
|
132
|
+
|
|
133
|
+
// Claude Code projects
|
|
134
|
+
if (parts[0] === '.claude' && parts[1] === 'projects' && parts[2]) return `claude:${parts[2]}`;
|
|
135
|
+
|
|
136
|
+
// Shared files area
|
|
137
|
+
if (parts[0] === 'Shared') return 'shared';
|
|
138
|
+
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
|
|
110
142
|
function indexFile(db, filePath, agentName, stmts, archiveMode) {
|
|
111
143
|
const stat = fs.statSync(filePath);
|
|
112
144
|
const mtime = stat.mtime.toISOString();
|
|
@@ -177,6 +209,13 @@ function indexFile(db, filePath, agentName, stmts, archiveMode) {
|
|
|
177
209
|
|
|
178
210
|
const pendingEvents = [];
|
|
179
211
|
const fileActivities = [];
|
|
212
|
+
const projectCounts = new Map();
|
|
213
|
+
|
|
214
|
+
// Seed project from session cwd when available (helps chat-only sessions)
|
|
215
|
+
if (firstLine && firstLine.cwd) {
|
|
216
|
+
const p = extractProjectFromPath(firstLine.cwd);
|
|
217
|
+
if (p) projectCounts.set(p, 1);
|
|
218
|
+
}
|
|
180
219
|
|
|
181
220
|
for (const line of lines) {
|
|
182
221
|
let obj;
|
|
@@ -272,6 +311,9 @@ function indexFile(db, filePath, agentName, stmts, archiveMode) {
|
|
|
272
311
|
: tool.name.includes('edit') || tool.name === 'Edit' ? 'edit'
|
|
273
312
|
: 'read';
|
|
274
313
|
fileActivities.push([sessionId, fp, op, ts]);
|
|
314
|
+
|
|
315
|
+
const project = extractProjectFromPath(fp);
|
|
316
|
+
if (project) projectCounts.set(project, (projectCounts.get(project) || 0) + 1);
|
|
275
317
|
}
|
|
276
318
|
}
|
|
277
319
|
}
|
|
@@ -301,7 +343,12 @@ function indexFile(db, filePath, agentName, stmts, archiveMode) {
|
|
|
301
343
|
}
|
|
302
344
|
|
|
303
345
|
const modelsJson = modelsSet.size > 0 ? JSON.stringify([...modelsSet]) : null;
|
|
304
|
-
|
|
346
|
+
const projects = [...projectCounts.entries()]
|
|
347
|
+
.sort((a, b) => (b[1] - a[1]) || a[0].localeCompare(b[0]))
|
|
348
|
+
.map(([name]) => name);
|
|
349
|
+
const projectsJson = projects.length > 0 ? JSON.stringify(projects) : null;
|
|
350
|
+
|
|
351
|
+
stmts.upsertSession.run(sessionId, sessionStart, sessionEnd, msgCount, toolCount, model, summary, agent, sessionType, totalCost, totalTokens, totalInputTokens, totalOutputTokens, totalCacheReadTokens, totalCacheWriteTokens, initialPrompt, firstMessageId, firstMessageTimestamp, modelsJson, projectsJson);
|
|
305
352
|
for (const ev of pendingEvents) stmts.insertEvent.run(...ev);
|
|
306
353
|
for (const fa of fileActivities) stmts.insertFileActivity.run(...fa);
|
|
307
354
|
|
package/package.json
CHANGED
package/public/app.js
CHANGED
|
@@ -113,6 +113,14 @@ function fmtTimeOnly(ts) {
|
|
|
113
113
|
return new Date(ts).toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit', hour12: true });
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
+
function renderProjectTags(s) {
|
|
117
|
+
let projects = [];
|
|
118
|
+
if (s.projects) {
|
|
119
|
+
try { projects = JSON.parse(s.projects); } catch {}
|
|
120
|
+
}
|
|
121
|
+
return projects.map(p => `<span class="session-project">${escHtml(p)}</span>`).join('');
|
|
122
|
+
}
|
|
123
|
+
|
|
116
124
|
function renderModelTags(s) {
|
|
117
125
|
// Prefer models array if present, fall back to single model
|
|
118
126
|
let models = [];
|
|
@@ -132,6 +140,7 @@ function renderSessionItem(s) {
|
|
|
132
140
|
<div class="session-header">
|
|
133
141
|
<span class="session-time">${timeRange} · ${duration}</span>
|
|
134
142
|
<span style="display:flex;gap:6px;align-items:center;flex-wrap:wrap">
|
|
143
|
+
${renderProjectTags(s)}
|
|
135
144
|
${s.agent && s.agent !== 'main' ? `<span class="session-agent">${escHtml(s.agent)}</span>` : ''}
|
|
136
145
|
${s.session_type ? `<span class="session-type">${escHtml(s.session_type)}</span>` : ''}
|
|
137
146
|
${renderModelTags(s)}
|
|
@@ -318,6 +327,7 @@ async function viewSession(id) {
|
|
|
318
327
|
<div class="session-header">
|
|
319
328
|
<span class="session-time">${fmtDate(s.start_time)} · ${fmtTimeShort(s.start_time)} – ${fmtTimeShort(s.end_time)}</span>
|
|
320
329
|
<span style="display:flex;gap:6px;align-items:center;flex-wrap:wrap">
|
|
330
|
+
${renderProjectTags(s)}
|
|
321
331
|
${s.agent && s.agent !== 'main' ? `<span class="session-agent">${escHtml(s.agent)}</span>` : ''}
|
|
322
332
|
${s.session_type ? `<span class="session-type">${escHtml(s.session_type)}</span>` : ''}
|
|
323
333
|
${renderModelTags(s)}
|
package/public/style.css
CHANGED
|
@@ -180,6 +180,7 @@ body {
|
|
|
180
180
|
}
|
|
181
181
|
|
|
182
182
|
.session-time { font-size: 13px; color: var(--text2); font-family: var(--mono); }
|
|
183
|
+
.session-project { font-size: 11px; color: var(--accent2); background: rgba(63,185,80,0.14); padding: 2px 8px; border-radius: 10px; }
|
|
183
184
|
.session-model { font-size: 11px; color: var(--purple); background: rgba(188,140,255,0.1); padding: 2px 8px; border-radius: 10px; }
|
|
184
185
|
.session-summary { font-size: 14px; color: var(--text); line-height: 1.4; }
|
|
185
186
|
.session-meta { display: flex; gap: 16px; margin-top: 8px; font-size: 12px; color: var(--text2); }
|