agentacta 1.1.1 → 1.1.3

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/config.js CHANGED
@@ -53,3 +53,4 @@ function loadConfig() {
53
53
  }
54
54
 
55
55
  module.exports = { loadConfig, CONFIG_FILE };
56
+ // v1.1.3
package/db.js CHANGED
@@ -114,6 +114,7 @@ function init(dbPath) {
114
114
  if (!cols.includes('output_tokens')) db.exec("ALTER TABLE sessions ADD COLUMN output_tokens INTEGER DEFAULT 0");
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
+ if (!cols.includes('models')) db.exec("ALTER TABLE sessions ADD COLUMN models TEXT");
117
118
 
118
119
  db.close();
119
120
  }
@@ -126,7 +127,7 @@ function createStmts(db) {
126
127
  deleteSession: db.prepare('DELETE FROM sessions WHERE id = ?'),
127
128
  deleteFileActivity: db.prepare('DELETE FROM file_activity WHERE session_id = ?'),
128
129
  insertEvent: db.prepare(`INSERT OR REPLACE INTO events (id, session_id, timestamp, type, role, content, tool_name, tool_args, tool_result) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`),
129
- 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) 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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`),
130
131
  upsertState: db.prepare(`INSERT OR REPLACE INTO index_state (file_path, last_offset, last_modified) VALUES (?, ?, ?)`),
131
132
  insertFileActivity: db.prepare(`INSERT INTO file_activity (session_id, file_path, operation, timestamp) VALUES (?, ?, ?, ?)`),
132
133
  deleteArchive: db.prepare('DELETE FROM archive WHERE session_id = ?'),
package/indexer.js CHANGED
@@ -126,6 +126,7 @@ function indexFile(db, filePath, agentName, stmts, archiveMode) {
126
126
  let msgCount = 0;
127
127
  let toolCount = 0;
128
128
  let model = null;
129
+ const modelsSet = new Set();
129
130
  let summary = '';
130
131
  let sessionType = null;
131
132
  let agent = agentName;
@@ -182,7 +183,10 @@ function indexFile(db, filePath, agentName, stmts, archiveMode) {
182
183
  try { obj = JSON.parse(line); } catch { continue; }
183
184
 
184
185
  if (obj.type === 'session' || obj.type === 'model_change' || obj.type === 'thinking_level_change' || obj.type === 'custom' || obj.type === 'file-history-snapshot') {
185
- if (obj.type === 'model_change') model = obj.modelId || model;
186
+ if (obj.type === 'model_change' && obj.modelId) {
187
+ if (!model) model = obj.modelId; // First model for backwards compat
188
+ modelsSet.add(obj.modelId); // Collect all unique models
189
+ }
186
190
  continue;
187
191
  }
188
192
 
@@ -204,9 +208,10 @@ function indexFile(db, filePath, agentName, stmts, archiveMode) {
204
208
  if (msg) {
205
209
  sessionEnd = ts;
206
210
 
207
- // Extract model from assistant messages as fallback
208
- if (!model && msg.role === 'assistant' && msg.model && msg.model !== 'delivery-mirror' && !msg.model.startsWith('<')) {
209
- model = msg.model;
211
+ // Extract model from assistant messages
212
+ if (msg.role === 'assistant' && msg.model && msg.model !== 'delivery-mirror' && !msg.model.startsWith('<')) {
213
+ if (!model) model = msg.model; // Keep first model for backwards compat
214
+ modelsSet.add(msg.model); // Collect all unique models
210
215
  }
211
216
 
212
217
  // Cost tracking
@@ -285,14 +290,18 @@ function indexFile(db, filePath, agentName, stmts, archiveMode) {
285
290
  }
286
291
  if (!sessionType && !initialPrompt) sessionType = 'heartbeat';
287
292
  // Detect subagent: task-style prompts injected by sessions_spawn
288
- // These typically start with a date/time stamp and contain a detailed task
293
+ // These typically start with a date/time stamp (e.g. "[Wed 2026-...")
294
+ // But exclude System Messages (cron announcements injected into main session)
289
295
  if (!sessionType && initialPrompt) {
290
296
  const p = initialPrompt.trim();
291
- // Sub-agent prompts start with "[Wed 2026-..." or "You are working on..."
292
- if (/^\[(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)\s+\d{4}-/.test(p)) sessionType = 'subagent';
297
+ // Sub-agent prompts start with "[Wed 2026-..." but NOT "[... [System Message]"
298
+ if (/^\[(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)\s+\d{4}-/.test(p) && !p.includes('[System Message]')) {
299
+ sessionType = 'subagent';
300
+ }
293
301
  }
294
302
 
295
- stmts.upsertSession.run(sessionId, sessionStart, sessionEnd, msgCount, toolCount, model, summary, agent, sessionType, totalCost, totalTokens, totalInputTokens, totalOutputTokens, totalCacheReadTokens, totalCacheWriteTokens, initialPrompt, firstMessageId, firstMessageTimestamp);
303
+ const modelsJson = modelsSet.size > 0 ? JSON.stringify([...modelsSet]) : null;
304
+ stmts.upsertSession.run(sessionId, sessionStart, sessionEnd, msgCount, toolCount, model, summary, agent, sessionType, totalCost, totalTokens, totalInputTokens, totalOutputTokens, totalCacheReadTokens, totalCacheWriteTokens, initialPrompt, firstMessageId, firstMessageTimestamp, modelsJson);
296
305
  for (const ev of pendingEvents) stmts.insertEvent.run(...ev);
297
306
  for (const fa of fileActivities) stmts.insertFileActivity.run(...fa);
298
307
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentacta",
3
- "version": "1.1.1",
3
+ "version": "1.1.3",
4
4
  "description": "Audit trail and search engine for AI agent sessions",
5
5
  "main": "index.js",
6
6
  "bin": {
package/public/app.js CHANGED
@@ -113,6 +113,16 @@ 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 renderModelTags(s) {
117
+ // Prefer models array if present, fall back to single model
118
+ let models = [];
119
+ if (s.models) {
120
+ try { models = JSON.parse(s.models); } catch {}
121
+ }
122
+ if (!models.length && s.model) models = [s.model];
123
+ return models.map(m => `<span class="session-model">${escHtml(m)}</span>`).join('');
124
+ }
125
+
116
126
  function renderSessionItem(s) {
117
127
  const duration = fmtDuration(s.start_time, s.end_time);
118
128
  const timeRange = `${fmtTime(s.start_time)} → ${s.end_time ? fmtTimeOnly(s.end_time) : 'now'}`;
@@ -121,10 +131,10 @@ function renderSessionItem(s) {
121
131
  <div class="session-item" data-id="${s.id}">
122
132
  <div class="session-header">
123
133
  <span class="session-time">${timeRange} · ${duration}</span>
124
- <span style="display:flex;gap:6px;align-items:center">
134
+ <span style="display:flex;gap:6px;align-items:center;flex-wrap:wrap">
125
135
  ${s.agent && s.agent !== 'main' ? `<span class="session-agent">${escHtml(s.agent)}</span>` : ''}
126
136
  ${s.session_type ? `<span class="session-type">${escHtml(s.session_type)}</span>` : ''}
127
- ${s.model ? `<span class="session-model">${escHtml(s.model)}</span>` : ''}
137
+ ${renderModelTags(s)}
128
138
  </span>
129
139
  </div>
130
140
  <div class="session-summary">${escHtml(truncate(s.summary || 'No summary', 120))}</div>
@@ -307,10 +317,10 @@ async function viewSession(id) {
307
317
  <div class="session-item" style="cursor:default">
308
318
  <div class="session-header">
309
319
  <span class="session-time">${fmtDate(s.start_time)} · ${fmtTimeShort(s.start_time)} – ${fmtTimeShort(s.end_time)}</span>
310
- <span style="display:flex;gap:6px;align-items:center">
320
+ <span style="display:flex;gap:6px;align-items:center;flex-wrap:wrap">
311
321
  ${s.agent && s.agent !== 'main' ? `<span class="session-agent">${escHtml(s.agent)}</span>` : ''}
312
322
  ${s.session_type ? `<span class="session-type">${escHtml(s.session_type)}</span>` : ''}
313
- ${s.model ? `<span class="session-model">${escHtml(s.model)}</span>` : ''}
323
+ ${renderModelTags(s)}
314
324
  </span>
315
325
  </div>
316
326
  <div class="session-meta" style="display:grid;grid-template-columns:repeat(2,1fr);gap:6px 16px">