@agentmemory/agentmemory 0.9.0 → 0.9.2
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 +42 -15
- package/dist/cli.mjs +60 -25
- package/dist/cli.mjs.map +1 -1
- package/dist/hooks/notification.mjs +6 -0
- package/dist/hooks/notification.mjs.map +1 -1
- package/dist/hooks/post-tool-failure.mjs +6 -0
- package/dist/hooks/post-tool-failure.mjs.map +1 -1
- package/dist/hooks/post-tool-use.mjs +35 -1
- package/dist/hooks/post-tool-use.mjs.map +1 -1
- package/dist/hooks/pre-compact.mjs +6 -0
- package/dist/hooks/pre-compact.mjs.map +1 -1
- package/dist/hooks/pre-tool-use.mjs +6 -0
- package/dist/hooks/pre-tool-use.mjs.map +1 -1
- package/dist/hooks/prompt-submit.mjs +6 -0
- package/dist/hooks/prompt-submit.mjs.map +1 -1
- package/dist/hooks/session-end.mjs +6 -0
- package/dist/hooks/session-end.mjs.map +1 -1
- package/dist/hooks/session-start.mjs +6 -0
- package/dist/hooks/session-start.mjs.map +1 -1
- package/dist/hooks/stop.mjs +6 -0
- package/dist/hooks/stop.mjs.map +1 -1
- package/dist/hooks/subagent-start.mjs +6 -0
- package/dist/hooks/subagent-start.mjs.map +1 -1
- package/dist/hooks/subagent-stop.mjs +6 -0
- package/dist/hooks/subagent-stop.mjs.map +1 -1
- package/dist/hooks/task-completed.mjs +6 -0
- package/dist/hooks/task-completed.mjs.map +1 -1
- package/dist/image-refs-Dq5wcV-a.mjs +3 -0
- package/dist/image-store-BLOkD0xV.mjs +3 -0
- package/dist/index.mjs +2054 -144
- package/dist/index.mjs.map +1 -1
- package/dist/{src-B3pEsBSb.mjs → src-tmuZyobT.mjs} +1974 -253
- package/dist/src-tmuZyobT.mjs.map +1 -0
- package/dist/{standalone-DXc-BEqr.mjs → standalone-BiwX0rdC.mjs} +2 -2
- package/dist/{standalone-DXc-BEqr.mjs.map → standalone-BiwX0rdC.mjs.map} +1 -1
- package/dist/standalone.mjs +136 -2
- package/dist/standalone.mjs.map +1 -1
- package/dist/{tools-registry-DXIK5CxQ.mjs → tools-registry-CHH84gIQ.mjs} +166 -12
- package/dist/tools-registry-CHH84gIQ.mjs.map +1 -0
- package/dist/viewer/index.html +249 -62
- package/package.json +5 -3
- package/plugin/.claude-plugin/plugin.json +2 -2
- package/plugin/scripts/notification.mjs +6 -0
- package/plugin/scripts/notification.mjs.map +1 -1
- package/plugin/scripts/post-tool-failure.mjs +6 -0
- package/plugin/scripts/post-tool-failure.mjs.map +1 -1
- package/plugin/scripts/post-tool-use.mjs +35 -1
- package/plugin/scripts/post-tool-use.mjs.map +1 -1
- package/plugin/scripts/pre-compact.mjs +6 -0
- package/plugin/scripts/pre-compact.mjs.map +1 -1
- package/plugin/scripts/pre-tool-use.mjs +6 -0
- package/plugin/scripts/pre-tool-use.mjs.map +1 -1
- package/plugin/scripts/prompt-submit.mjs +6 -0
- package/plugin/scripts/prompt-submit.mjs.map +1 -1
- package/plugin/scripts/session-end.mjs +6 -0
- package/plugin/scripts/session-end.mjs.map +1 -1
- package/plugin/scripts/session-start.mjs +6 -0
- package/plugin/scripts/session-start.mjs.map +1 -1
- package/plugin/scripts/stop.mjs +6 -0
- package/plugin/scripts/stop.mjs.map +1 -1
- package/plugin/scripts/subagent-start.mjs +6 -0
- package/plugin/scripts/subagent-start.mjs.map +1 -1
- package/plugin/scripts/subagent-stop.mjs +6 -0
- package/plugin/scripts/subagent-stop.mjs.map +1 -1
- package/plugin/scripts/task-completed.mjs +6 -0
- package/plugin/scripts/task-completed.mjs.map +1 -1
- package/dist/src-B3pEsBSb.mjs.map +0 -1
- package/dist/tools-registry-DXIK5CxQ.mjs.map +0 -1
- package/dist/transformers-BX_tgxdO.mjs +0 -38684
- package/dist/transformers-BX_tgxdO.mjs.map +0 -1
- package/dist/transformers-KMm1i9no.mjs +0 -38683
- package/dist/transformers-KMm1i9no.mjs.map +0 -1
package/dist/viewer/index.html
CHANGED
|
@@ -790,7 +790,7 @@
|
|
|
790
790
|
<div class="app-header">
|
|
791
791
|
<div class="brand">
|
|
792
792
|
<h1>agentmemory</h1>
|
|
793
|
-
<span class="version">
|
|
793
|
+
<span class="version">v__AGENTMEMORY_VERSION__</span>
|
|
794
794
|
</div>
|
|
795
795
|
<div class="header-right">
|
|
796
796
|
<span class="dateline" id="dateline"></span>
|
|
@@ -900,7 +900,7 @@
|
|
|
900
900
|
activity: { loaded: false, observations: [], sessions: [], typeFilter: '' },
|
|
901
901
|
lessons: { loaded: false, items: [], search: '' },
|
|
902
902
|
actions: { loaded: false, items: [], frontier: [], statusFilter: '', search: '' },
|
|
903
|
-
crystals: { loaded: false, items: [], search: '' },
|
|
903
|
+
crystals: { loaded: false, items: [], search: '', lessonMap: {} },
|
|
904
904
|
profile: { loaded: false, projects: [], selectedProject: '', data: null },
|
|
905
905
|
replay: { loaded: false, sessions: [], selectedId: '', timeline: null, cursor: 0, playing: false, speed: 1, timer: null, startAt: 0, offsetAt: 0 },
|
|
906
906
|
ws: null
|
|
@@ -1078,7 +1078,8 @@
|
|
|
1078
1078
|
var heapTotal = Math.round((snap.memory.heapTotal || 0) / 1024 / 1024);
|
|
1079
1079
|
var rss = Math.round((snap.memory.rss || 0) / 1024 / 1024);
|
|
1080
1080
|
var heapPct = heapTotal > 0 ? Math.round((heapUsed / heapTotal) * 100) : 0;
|
|
1081
|
-
var
|
|
1081
|
+
var rssAboveFloor = rss >= 512;
|
|
1082
|
+
var heapColor = (heapPct > 80 && rssAboveFloor) ? 'var(--red)' : (heapPct > 60 && rssAboveFloor) ? 'var(--yellow)' : 'var(--green)';
|
|
1082
1083
|
html += '<div class="gauge"><span class="gauge-label">Heap</span><div class="gauge-bar"><div class="gauge-fill" style="width:' + heapPct + '%;background:' + heapColor + '"></div></div><span class="gauge-value">' + heapUsed + ' / ' + heapTotal + ' MB</span></div>';
|
|
1083
1084
|
html += '<div class="gauge"><span class="gauge-label">RSS</span><div class="gauge-bar"><div class="gauge-fill" style="width:' + Math.min(100, Math.round(rss / 512 * 100)) + '%;background:var(--blue)"></div></div><span class="gauge-value">' + rss + ' MB</span></div>';
|
|
1084
1085
|
if (snap.memory.external) {
|
|
@@ -1113,6 +1114,14 @@
|
|
|
1113
1114
|
html += '</div>';
|
|
1114
1115
|
}
|
|
1115
1116
|
|
|
1117
|
+
if (snap.notes && snap.notes.length > 0) {
|
|
1118
|
+
html += '<div class="card" style="margin-bottom:16px;"><div class="card-title" style="color:var(--ink-muted);">Notes (' + snap.notes.length + ')</div>';
|
|
1119
|
+
snap.notes.forEach(function(n) {
|
|
1120
|
+
html += '<div style="font-size:12px;color:var(--ink-muted);padding:4px 0;border-bottom:1px solid var(--border-light);font-family:var(--font-ui);">' + esc(n) + '</div>';
|
|
1121
|
+
});
|
|
1122
|
+
html += '</div>';
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1116
1125
|
html += '<div class="two-col">';
|
|
1117
1126
|
|
|
1118
1127
|
html += '<div class="card"><div class="card-title">Recent Sessions</div>';
|
|
@@ -1272,6 +1281,7 @@
|
|
|
1272
1281
|
function startDashboardAutoRefresh() {
|
|
1273
1282
|
if (dashboardTimer) clearInterval(dashboardTimer);
|
|
1274
1283
|
dashboardTimer = setInterval(function() {
|
|
1284
|
+
if (pollTimer) return;
|
|
1275
1285
|
if (state.activeTab === 'dashboard') refreshDashboard();
|
|
1276
1286
|
}, 30000);
|
|
1277
1287
|
}
|
|
@@ -1936,7 +1946,13 @@
|
|
|
1936
1946
|
items.forEach(function(m) { types[m.type] = true; });
|
|
1937
1947
|
var typeOptions = Object.keys(types).sort();
|
|
1938
1948
|
|
|
1939
|
-
var html = '<div class="
|
|
1949
|
+
var html = '<div class="card" style="margin-bottom:12px;padding:12px;background:var(--bg-subtle);">';
|
|
1950
|
+
html += '<div style="font-size:13px;color:var(--ink-muted);line-height:1.5;">';
|
|
1951
|
+
html += '<strong>Memories</strong> are durable facts, architecture notes, conventions, and lessons saved via <code>memory_remember</code> MCP tool or the <code>/agentmemory/remember</code> endpoint. They survive across sessions and supersede each other as v1, v2, etc. ';
|
|
1952
|
+
html += '<span style="color:var(--ink-faint);">Shown: ' + items.length + ' total.</span>';
|
|
1953
|
+
html += '</div></div>';
|
|
1954
|
+
|
|
1955
|
+
html += '<div class="toolbar">';
|
|
1940
1956
|
html += '<input type="text" id="mem-search" placeholder="Search memories..." value="' + esc(state.memories.search) + '">';
|
|
1941
1957
|
html += '<select id="mem-type-filter"><option value="">All types</option>';
|
|
1942
1958
|
typeOptions.forEach(function(t) {
|
|
@@ -1945,12 +1961,14 @@
|
|
|
1945
1961
|
html += '</select></div>';
|
|
1946
1962
|
|
|
1947
1963
|
if (filtered.length === 0) {
|
|
1948
|
-
html += '<div class="empty-state"><div class="empty-icon">📚</div><p>No memories found</p></div>';
|
|
1964
|
+
html += '<div class="empty-state"><div class="empty-icon">📚</div><p>No memories found</p><p style="font-size:12px;color:var(--ink-faint);font-style:italic;">Save facts with the <code>memory_remember</code> MCP tool during Claude Code sessions.</p></div>';
|
|
1949
1965
|
} else {
|
|
1950
1966
|
html += '<table><tr><th>Title</th><th>Type</th><th>Strength</th><th>Version</th><th>Updated</th><th>Actions</th></tr>';
|
|
1951
1967
|
filtered.forEach(function(m) {
|
|
1952
1968
|
var badgeClass = TYPE_BADGES[m.type] || 'badge-muted';
|
|
1953
|
-
var
|
|
1969
|
+
var rawStrength = m.strength || 0;
|
|
1970
|
+
var strength = Math.round(rawStrength <= 1 ? rawStrength * 100 : rawStrength * 10);
|
|
1971
|
+
if (strength > 100) strength = 100;
|
|
1954
1972
|
var barColor = strength > 70 ? 'var(--green)' : strength > 40 ? 'var(--yellow)' : 'var(--red)';
|
|
1955
1973
|
html += '<tr>';
|
|
1956
1974
|
var preview = (m.content || '').split('\n').slice(0, 2).join(' ').trim();
|
|
@@ -2399,6 +2417,10 @@
|
|
|
2399
2417
|
html += '<div class="session-item' + (selected ? ' selected' : '') + '" data-action="select-session" data-session-id="' + esc(s.id) + '">';
|
|
2400
2418
|
html += '<div class="session-top"><span class="session-project">' + esc(s.project ? s.project.split('/').pop() : 'Unknown') + '</span>';
|
|
2401
2419
|
html += '<span class="badge ' + statusBadge + '">' + esc(s.status) + '</span></div>';
|
|
2420
|
+
var preview = s.firstPrompt || s.summary || '';
|
|
2421
|
+
if (preview) {
|
|
2422
|
+
html += '<div class="session-preview" style="font-size:13px;color:var(--ink);margin:4px 0;line-height:1.4;">' + esc(truncate(preview, 140)) + '</div>';
|
|
2423
|
+
}
|
|
2402
2424
|
html += '<div class="session-meta">' + esc(s.id.slice(0, 12)) + ' · ' + esc(formatTime(s.startedAt));
|
|
2403
2425
|
html += ' · ' + (s.observationCount || 0) + ' obs';
|
|
2404
2426
|
if (s.model) html += ' · ' + esc(s.model);
|
|
@@ -2417,24 +2439,96 @@
|
|
|
2417
2439
|
renderSessions();
|
|
2418
2440
|
}
|
|
2419
2441
|
|
|
2420
|
-
function renderSessionDetail() {
|
|
2442
|
+
async function renderSessionDetail() {
|
|
2421
2443
|
var panel = document.getElementById('session-detail');
|
|
2422
2444
|
if (!panel) return;
|
|
2423
2445
|
var s = state.sessions.items.find(function(x) { return x.id === state.sessions.selectedId; });
|
|
2424
2446
|
if (!s) { panel.innerHTML = ''; return; }
|
|
2425
2447
|
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2448
|
+
panel.innerHTML = '<div class="detail-panel"><h3>Loading session details…</h3></div>';
|
|
2449
|
+
|
|
2450
|
+
var obsRes = await apiGet('observations?sessionId=' + encodeURIComponent(s.id));
|
|
2451
|
+
var obs = (obsRes && obsRes.observations) || [];
|
|
2452
|
+
|
|
2453
|
+
var typeCounts = {};
|
|
2454
|
+
var toolCounts = {};
|
|
2455
|
+
var fileSet = new Set();
|
|
2456
|
+
var firstPromptFromObs = '';
|
|
2457
|
+
obs.forEach(function(o) {
|
|
2458
|
+
var t = o.type || o.hookType || 'other';
|
|
2459
|
+
typeCounts[t] = (typeCounts[t] || 0) + 1;
|
|
2460
|
+
var tool = o.title || o.toolName;
|
|
2461
|
+
if (tool && t !== 'conversation') toolCounts[tool] = (toolCounts[tool] || 0) + 1;
|
|
2462
|
+
(o.files || []).forEach(function(f) { fileSet.add(f); });
|
|
2463
|
+
if (!firstPromptFromObs && (o.userPrompt || (o.type === 'conversation' && o.narrative))) {
|
|
2464
|
+
firstPromptFromObs = o.userPrompt || o.narrative || '';
|
|
2465
|
+
}
|
|
2466
|
+
});
|
|
2467
|
+
|
|
2468
|
+
var durationMs = s.endedAt ? new Date(s.endedAt).getTime() - new Date(s.startedAt).getTime() : 0;
|
|
2469
|
+
var durationLabel = durationMs > 0 ? (durationMs < 60000 ? (durationMs / 1000).toFixed(1) + 's' : (durationMs / 60000).toFixed(1) + 'm') : '-';
|
|
2470
|
+
|
|
2471
|
+
var preview = s.firstPrompt || s.summary || firstPromptFromObs || '';
|
|
2472
|
+
|
|
2473
|
+
var html = '<div class="detail-panel">';
|
|
2474
|
+
html += '<div style="display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:12px;">';
|
|
2475
|
+
html += '<h3 style="margin:0;">Session · ' + esc(s.project || 'Unknown') + '</h3>';
|
|
2476
|
+
html += '<span class="badge ' + (s.status === 'active' ? 'badge-green' : 'badge-blue') + '">' + esc(s.status) + '</span>';
|
|
2477
|
+
html += '</div>';
|
|
2478
|
+
|
|
2479
|
+
if (preview) {
|
|
2480
|
+
html += '<div style="padding:10px 12px;margin-bottom:12px;background:var(--bg-alt);border-left:3px solid var(--accent);font-size:13px;line-height:1.5;color:var(--ink);">' + esc(truncate(preview, 600)) + '</div>';
|
|
2481
|
+
}
|
|
2482
|
+
|
|
2483
|
+
html += '<div style="display:grid;grid-template-columns:repeat(4, 1fr);gap:10px;margin-bottom:14px;">';
|
|
2484
|
+
html += '<div class="card" style="padding:10px;"><div style="font-size:10px;letter-spacing:0.08em;color:var(--ink-muted);">OBSERVATIONS</div><div style="font-size:20px;font-weight:600;">' + obs.length + '</div></div>';
|
|
2485
|
+
html += '<div class="card" style="padding:10px;"><div style="font-size:10px;letter-spacing:0.08em;color:var(--ink-muted);">TOOLS USED</div><div style="font-size:20px;font-weight:600;">' + Object.keys(toolCounts).length + '</div></div>';
|
|
2486
|
+
html += '<div class="card" style="padding:10px;"><div style="font-size:10px;letter-spacing:0.08em;color:var(--ink-muted);">FILES TOUCHED</div><div style="font-size:20px;font-weight:600;">' + fileSet.size + '</div></div>';
|
|
2487
|
+
html += '<div class="card" style="padding:10px;"><div style="font-size:10px;letter-spacing:0.08em;color:var(--ink-muted);">DURATION</div><div style="font-size:20px;font-weight:600;">' + esc(durationLabel) + '</div></div>';
|
|
2488
|
+
html += '</div>';
|
|
2489
|
+
|
|
2490
|
+
var topTools = Object.keys(toolCounts).sort(function(a, b) { return toolCounts[b] - toolCounts[a]; }).slice(0, 10);
|
|
2491
|
+
if (topTools.length > 0) {
|
|
2492
|
+
var maxC = toolCounts[topTools[0]] || 1;
|
|
2493
|
+
html += '<div class="card" style="margin-bottom:12px;"><div class="card-title">Tool Invocations</div>';
|
|
2494
|
+
html += '<div class="bar-chart" style="margin-top:8px;">';
|
|
2495
|
+
topTools.forEach(function(t) {
|
|
2496
|
+
var pct = Math.round((toolCounts[t] / maxC) * 100);
|
|
2497
|
+
html += '<div class="bar-row"><span class="bar-label" style="font-family:var(--font-mono);">' + esc(t) + '</span><div class="bar-track"><div class="bar-fill" style="width:' + pct + '%;background:var(--accent);"></div></div><span class="bar-value">' + toolCounts[t] + '</span></div>';
|
|
2498
|
+
});
|
|
2499
|
+
html += '</div></div>';
|
|
2500
|
+
}
|
|
2501
|
+
|
|
2502
|
+
var typeKeys = Object.keys(typeCounts).sort(function(a, b) { return typeCounts[b] - typeCounts[a]; });
|
|
2503
|
+
if (typeKeys.length > 0) {
|
|
2504
|
+
html += '<div class="card" style="margin-bottom:12px;"><div class="card-title">Activity Breakdown</div>';
|
|
2505
|
+
html += '<div style="display:flex;gap:6px;flex-wrap:wrap;margin-top:8px;">';
|
|
2506
|
+
typeKeys.forEach(function(t) {
|
|
2507
|
+
html += '<span class="badge badge-muted" style="font-family:var(--font-mono);">' + esc(t.replace(/_/g, ' ')) + ' · ' + typeCounts[t] + '</span>';
|
|
2508
|
+
});
|
|
2509
|
+
html += '</div></div>';
|
|
2510
|
+
}
|
|
2511
|
+
|
|
2512
|
+
if (fileSet.size > 0) {
|
|
2513
|
+
var filesArr = Array.from(fileSet).slice(0, 30);
|
|
2514
|
+
html += '<div class="card" style="margin-bottom:12px;"><div class="card-title">Files</div>';
|
|
2515
|
+
html += '<div style="font-size:12px;font-family:var(--font-mono);line-height:1.6;margin-top:8px;">';
|
|
2516
|
+
filesArr.forEach(function(f) { html += '<div>• ' + esc(f) + '</div>'; });
|
|
2517
|
+
if (fileSet.size > 30) html += '<div style="color:var(--ink-faint);">+' + (fileSet.size - 30) + ' more</div>';
|
|
2518
|
+
html += '</div></div>';
|
|
2519
|
+
}
|
|
2520
|
+
|
|
2521
|
+
html += '<div class="card" style="margin-bottom:12px;"><div class="card-title">Metadata</div>';
|
|
2522
|
+
html += '<div style="font-size:12px;font-family:var(--font-mono);margin-top:8px;line-height:1.7;">';
|
|
2523
|
+
html += '<div><span style="color:var(--ink-muted);">id:</span> ' + esc(s.id) + '</div>';
|
|
2524
|
+
html += '<div><span style="color:var(--ink-muted);">cwd:</span> ' + esc(s.cwd || '-') + '</div>';
|
|
2525
|
+
html += '<div><span style="color:var(--ink-muted);">started:</span> ' + esc(formatTime(s.startedAt)) + '</div>';
|
|
2526
|
+
if (s.endedAt) html += '<div><span style="color:var(--ink-muted);">ended:</span> ' + esc(formatTime(s.endedAt)) + '</div>';
|
|
2527
|
+
if (s.model) html += '<div><span style="color:var(--ink-muted);">model:</span> ' + esc(s.model) + '</div>';
|
|
2528
|
+
if (s.tags && s.tags.length) html += '<div><span style="color:var(--ink-muted);">tags:</span> ' + s.tags.map(esc).join(', ') + '</div>';
|
|
2529
|
+
html += '</div></div>';
|
|
2530
|
+
|
|
2531
|
+
html += '<div style="display:flex;gap:8px;">';
|
|
2438
2532
|
if (s.status === 'active') {
|
|
2439
2533
|
html += '<button class="btn btn-danger" data-action="end-session" data-session-id="' + esc(s.id) + '">End Session</button>';
|
|
2440
2534
|
}
|
|
@@ -2478,13 +2572,18 @@
|
|
|
2478
2572
|
});
|
|
2479
2573
|
}
|
|
2480
2574
|
|
|
2481
|
-
var html = '<div style="
|
|
2575
|
+
var html = '<div class="card" style="margin-bottom:12px;padding:12px;background:var(--bg-subtle);">';
|
|
2576
|
+
html += '<div style="font-size:13px;color:var(--ink-muted);line-height:1.5;">';
|
|
2577
|
+
html += '<strong>Lessons</strong> are portable heuristics — short imperative rules (always/never/prefer/avoid) extracted from past work. Auto-surface from JSONL imports (low confidence, tag <code>auto-import</code>), get reinforced when the agent applies them, and decay if unused. Higher confidence = more battle-tested.';
|
|
2578
|
+
html += '</div></div>';
|
|
2579
|
+
|
|
2580
|
+
html += '<div style="display:flex;gap:8px;margin-bottom:12px;">';
|
|
2482
2581
|
html += '<input class="search-input" type="text" placeholder="Search lessons..." value="' + esc(state.lessons.search) + '" oninput="state.lessons.search=this.value;renderLessons()" style="flex:1" />';
|
|
2483
2582
|
html += '<span style="font-size:12px;color:var(--ink-faint);align-self:center;">' + items.length + ' lessons</span>';
|
|
2484
2583
|
html += '</div>';
|
|
2485
2584
|
|
|
2486
2585
|
if (items.length === 0) {
|
|
2487
|
-
html += '<div class="empty-state"><div class="empty-icon">💡</div><p>No lessons yet</p><p style="font-size:12px;color:var(--ink-faint);font-style:italic;">
|
|
2586
|
+
html += '<div class="empty-state"><div class="empty-icon">💡</div><p>No lessons yet</p><p style="font-size:12px;color:var(--ink-faint);font-style:italic;">Import a Claude Code JSONL (Replay tab → Import JSONL) or save manually via <code>memory_lesson_save</code>.</p></div>';
|
|
2488
2587
|
} else {
|
|
2489
2588
|
html += '<table><thead><tr><th>Lesson</th><th>Confidence</th><th>Reinforcements</th><th>Source</th><th>Project</th><th>Updated</th></tr></thead><tbody>';
|
|
2490
2589
|
items.forEach(function(l) {
|
|
@@ -2510,7 +2609,7 @@
|
|
|
2510
2609
|
el.innerHTML = '<div class="loading">Loading actions...</div>';
|
|
2511
2610
|
var results = await Promise.all([apiGet('actions'), apiGet('frontier')]);
|
|
2512
2611
|
state.actions.items = (results[0] && results[0].actions) || [];
|
|
2513
|
-
state.actions.frontier = (results[1] && results[1].actions) || [];
|
|
2612
|
+
state.actions.frontier = (results[1] && (results[1].frontier || results[1].actions)) || [];
|
|
2514
2613
|
state.actions.loaded = true;
|
|
2515
2614
|
renderActions();
|
|
2516
2615
|
}
|
|
@@ -2569,15 +2668,13 @@
|
|
|
2569
2668
|
|
|
2570
2669
|
async function loadCrystals() {
|
|
2571
2670
|
var el = document.getElementById('view-crystals');
|
|
2572
|
-
if (state.dashboard.loaded && state.dashboard.crystals.length) {
|
|
2573
|
-
state.crystals.items = state.dashboard.crystals;
|
|
2574
|
-
state.crystals.loaded = true;
|
|
2575
|
-
renderCrystals();
|
|
2576
|
-
return;
|
|
2577
|
-
}
|
|
2578
2671
|
el.innerHTML = '<div class="loading">Loading crystals...</div>';
|
|
2579
|
-
var
|
|
2580
|
-
state.crystals.items = (
|
|
2672
|
+
var results = await Promise.all([apiGet('crystals'), apiGet('lessons')]);
|
|
2673
|
+
state.crystals.items = (results[0] && results[0].crystals) || [];
|
|
2674
|
+
var lessonMap = {};
|
|
2675
|
+
var lessons = (results[1] && results[1].lessons) || [];
|
|
2676
|
+
lessons.forEach(function(l) { if (l && l.id) lessonMap[l.id] = l; });
|
|
2677
|
+
state.crystals.lessonMap = lessonMap;
|
|
2581
2678
|
state.crystals.loaded = true;
|
|
2582
2679
|
renderCrystals();
|
|
2583
2680
|
}
|
|
@@ -2586,54 +2683,83 @@
|
|
|
2586
2683
|
var el = document.getElementById('view-crystals');
|
|
2587
2684
|
var items = state.crystals.items;
|
|
2588
2685
|
var search = state.crystals.search.toLowerCase();
|
|
2686
|
+
var lessonMap = state.crystals.lessonMap || {};
|
|
2589
2687
|
|
|
2590
2688
|
if (search) {
|
|
2591
2689
|
items = items.filter(function(c) {
|
|
2592
|
-
|
|
2690
|
+
var lessonText = (c.lessons || [])
|
|
2691
|
+
.map(function(lid) {
|
|
2692
|
+
var l = lessonMap[lid];
|
|
2693
|
+
return l && typeof l.content === 'string' ? l.content : lid;
|
|
2694
|
+
})
|
|
2695
|
+
.join(' ');
|
|
2696
|
+
var filesText = (c.filesAffected || []).join(' ');
|
|
2697
|
+
var haystack = [
|
|
2698
|
+
c.narrative || '',
|
|
2699
|
+
(c.keyOutcomes || []).join(' '),
|
|
2700
|
+
lessonText,
|
|
2701
|
+
filesText,
|
|
2702
|
+
c.project || '',
|
|
2703
|
+
].join(' ').toLowerCase();
|
|
2704
|
+
return haystack.indexOf(search) >= 0;
|
|
2593
2705
|
});
|
|
2594
2706
|
}
|
|
2595
2707
|
|
|
2596
|
-
var html = '<div style="
|
|
2708
|
+
var html = '<div class="card" style="margin-bottom:12px;padding:12px;background:var(--bg-subtle);">';
|
|
2709
|
+
html += '<div style="font-size:13px;color:var(--ink-muted);line-height:1.5;">';
|
|
2710
|
+
html += '<strong>Crystals</strong> are frozen snapshots of completed work. Each crystal captures one session\'s narrative, the tools invoked (key outcomes), files touched, and lessons surfaced — a replayable summary you keep after raw observations are pruned. Auto-created on JSONL import or via <code>memory_crystallize</code>.';
|
|
2711
|
+
html += '</div></div>';
|
|
2712
|
+
|
|
2713
|
+
html += '<div style="display:flex;gap:8px;margin-bottom:12px;">';
|
|
2597
2714
|
html += '<input class="search-input" type="text" placeholder="Search crystals..." value="' + esc(state.crystals.search) + '" oninput="state.crystals.search=this.value;renderCrystals()" style="flex:1" />';
|
|
2598
2715
|
html += '<span style="font-size:12px;color:var(--ink-faint);align-self:center;">' + items.length + ' crystals</span>';
|
|
2599
2716
|
html += '</div>';
|
|
2600
2717
|
|
|
2601
2718
|
if (items.length === 0) {
|
|
2602
|
-
html += '<div class="empty-state"><div class="empty-icon">💎</div><p>No crystals yet</p><p style="font-size:12px;color:var(--ink-faint);font-style:italic;">Crystals
|
|
2719
|
+
html += '<div class="empty-state"><div class="empty-icon">💎</div><p>No crystals yet</p><p style="font-size:12px;color:var(--ink-faint);font-style:italic;">Crystals auto-generate from JSONL imports, or call <code>memory_crystallize</code> on a session.</p></div>';
|
|
2603
2720
|
} else {
|
|
2604
2721
|
items.forEach(function(c) {
|
|
2605
|
-
html += '<div class="card" style="margin-bottom:12px;">';
|
|
2606
|
-
html += '<div
|
|
2607
|
-
html += '<
|
|
2608
|
-
html += '<
|
|
2722
|
+
html += '<div class="card" style="margin-bottom:12px;border-left:3px solid var(--accent);">';
|
|
2723
|
+
html += '<div style="display:flex;justify-content:space-between;align-items:flex-start;gap:12px;margin-bottom:8px;">';
|
|
2724
|
+
html += '<div style="flex:1;font-size:14px;font-weight:600;color:var(--ink);line-height:1.4;">' + esc(truncate(c.narrative || 'Untitled crystal', 300)) + '</div>';
|
|
2725
|
+
html += '<div style="font-size:10px;color:var(--ink-faint);font-family:var(--font-mono);white-space:nowrap;">' + esc(formatTime(c.createdAt)) + '</div>';
|
|
2609
2726
|
html += '</div>';
|
|
2610
2727
|
|
|
2728
|
+
var pillRow = [];
|
|
2729
|
+
if (c.project) pillRow.push('<span class="badge badge-muted">' + esc(c.project) + '</span>');
|
|
2730
|
+
if (c.sessionId) pillRow.push('<span class="badge badge-blue" style="font-family:var(--font-mono);">' + esc(c.sessionId.slice(0, 14)) + '</span>');
|
|
2731
|
+
if (c.keyOutcomes && c.keyOutcomes.length) pillRow.push('<span style="font-size:11px;color:var(--ink-muted);">' + c.keyOutcomes.length + ' tools</span>');
|
|
2732
|
+
if (c.filesAffected && c.filesAffected.length) pillRow.push('<span style="font-size:11px;color:var(--ink-muted);">' + c.filesAffected.length + ' files</span>');
|
|
2733
|
+
if (c.lessons && c.lessons.length) pillRow.push('<span style="font-size:11px;color:var(--ink-muted);">' + c.lessons.length + ' lessons</span>');
|
|
2734
|
+
if (pillRow.length) html += '<div style="display:flex;gap:6px;flex-wrap:wrap;margin-bottom:10px;">' + pillRow.join('') + '</div>';
|
|
2735
|
+
|
|
2611
2736
|
if (c.keyOutcomes && c.keyOutcomes.length > 0) {
|
|
2612
|
-
html += '<div style="margin:
|
|
2737
|
+
html += '<div style="margin:10px 0;"><div style="font-size:10px;letter-spacing:0.08em;color:var(--ink-muted);margin-bottom:4px;">TOOLS USED</div>';
|
|
2738
|
+
html += '<div style="display:flex;gap:4px;flex-wrap:wrap;">';
|
|
2613
2739
|
c.keyOutcomes.forEach(function(o) {
|
|
2614
|
-
html += '<
|
|
2740
|
+
html += '<span class="badge" style="background:var(--bg-alt);color:var(--ink);font-family:var(--font-mono);">' + esc(o) + '</span>';
|
|
2615
2741
|
});
|
|
2616
|
-
html += '</div>';
|
|
2617
|
-
}
|
|
2618
|
-
|
|
2619
|
-
if (c.lessons && c.lessons.length > 0) {
|
|
2620
|
-
html += '<div style="margin:8px 0;"><strong style="font-size:11px;color:var(--ink-muted);">LESSONS</strong>';
|
|
2621
|
-
c.lessons.forEach(function(l) {
|
|
2622
|
-
html += '<div style="font-size:12px;padding:2px 0;color:var(--ink);">💡 ' + esc(l) + '</div>';
|
|
2623
|
-
});
|
|
2624
|
-
html += '</div>';
|
|
2742
|
+
html += '</div></div>';
|
|
2625
2743
|
}
|
|
2626
2744
|
|
|
2627
2745
|
if (c.filesAffected && c.filesAffected.length > 0) {
|
|
2628
|
-
html += '<div style="margin:
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2746
|
+
html += '<div style="margin:10px 0;"><div style="font-size:10px;letter-spacing:0.08em;color:var(--ink-muted);margin-bottom:4px;">FILES TOUCHED</div>';
|
|
2747
|
+
html += '<div style="font-size:12px;font-family:var(--font-mono);color:var(--ink);line-height:1.6;">';
|
|
2748
|
+
c.filesAffected.slice(0, 10).forEach(function(f) {
|
|
2749
|
+
html += '<div>• ' + esc(f) + '</div>';
|
|
2750
|
+
});
|
|
2751
|
+
if (c.filesAffected.length > 10) html += '<div style="color:var(--ink-faint);">+' + (c.filesAffected.length - 10) + ' more</div>';
|
|
2752
|
+
html += '</div></div>';
|
|
2633
2753
|
}
|
|
2634
2754
|
|
|
2635
|
-
if (c.
|
|
2636
|
-
html += '<div style="font-size:
|
|
2755
|
+
if (c.lessons && c.lessons.length > 0) {
|
|
2756
|
+
html += '<div style="margin:10px 0;"><div style="font-size:10px;letter-spacing:0.08em;color:var(--ink-muted);margin-bottom:4px;">LESSONS SURFACED</div>';
|
|
2757
|
+
c.lessons.slice(0, 8).forEach(function(lid) {
|
|
2758
|
+
var content = lessonMap[lid] ? lessonMap[lid].content : lid;
|
|
2759
|
+
html += '<div style="font-size:12px;padding:4px 8px;margin:2px 0;background:var(--bg-alt);border-radius:3px;color:var(--ink);line-height:1.4;">💡 ' + esc(content) + '</div>';
|
|
2760
|
+
});
|
|
2761
|
+
if (c.lessons.length > 8) html += '<div style="font-size:11px;color:var(--ink-faint);margin-top:4px;">+' + (c.lessons.length - 8) + ' more lessons</div>';
|
|
2762
|
+
html += '</div>';
|
|
2637
2763
|
}
|
|
2638
2764
|
|
|
2639
2765
|
html += '</div>';
|
|
@@ -2825,13 +2951,66 @@
|
|
|
2825
2951
|
|
|
2826
2952
|
var wsReconnectTimer = null;
|
|
2827
2953
|
var wsRetries = 0;
|
|
2828
|
-
var WS_MAX_RETRIES =
|
|
2954
|
+
var WS_MAX_RETRIES = 4;
|
|
2829
2955
|
var directFailed = false;
|
|
2830
2956
|
var directFailures = 0;
|
|
2831
2957
|
var DIRECT_FAILURE_THRESHOLD = 2;
|
|
2958
|
+
var pollTimer = null;
|
|
2959
|
+
var POLL_INTERVAL_MS = 10000;
|
|
2960
|
+
|
|
2961
|
+
function setWsStatus(text, cls) {
|
|
2962
|
+
var el = document.getElementById('ws-status');
|
|
2963
|
+
if (!el) return;
|
|
2964
|
+
el.textContent = text;
|
|
2965
|
+
el.className = 'ws-status ' + cls;
|
|
2966
|
+
}
|
|
2967
|
+
|
|
2968
|
+
var WS_REPROBE_EVERY_TICKS = 6;
|
|
2969
|
+
|
|
2970
|
+
function startPolling() {
|
|
2971
|
+
if (pollTimer) return;
|
|
2972
|
+
setWsStatus('polling · ' + (POLL_INTERVAL_MS / 1000) + 's', 'disconnected');
|
|
2973
|
+
var tick = 0;
|
|
2974
|
+
pollTimer = setInterval(function() {
|
|
2975
|
+
tick++;
|
|
2976
|
+
if (state.activeTab === 'dashboard') {
|
|
2977
|
+
state.dashboard.loaded = false;
|
|
2978
|
+
loadDashboard();
|
|
2979
|
+
} else if (state.activeTab === 'memories') {
|
|
2980
|
+
state.memories.loaded = false;
|
|
2981
|
+
loadMemories();
|
|
2982
|
+
} else if (state.activeTab === 'sessions') {
|
|
2983
|
+
state.sessions.loaded = false;
|
|
2984
|
+
loadSessions();
|
|
2985
|
+
} else if (state.activeTab === 'activity') {
|
|
2986
|
+
state.activity.loaded = false;
|
|
2987
|
+
loadActivity();
|
|
2988
|
+
}
|
|
2989
|
+
if (tick % WS_REPROBE_EVERY_TICKS === 0) {
|
|
2990
|
+
var ws = state.ws;
|
|
2991
|
+
if (!ws || ws.readyState !== WebSocket.OPEN) {
|
|
2992
|
+
wsRetries = 0;
|
|
2993
|
+
directFailures = 0;
|
|
2994
|
+
directFailed = false;
|
|
2995
|
+
connectWs();
|
|
2996
|
+
}
|
|
2997
|
+
}
|
|
2998
|
+
}, POLL_INTERVAL_MS);
|
|
2999
|
+
}
|
|
3000
|
+
|
|
3001
|
+
function stopPolling() {
|
|
3002
|
+
if (!pollTimer) return;
|
|
3003
|
+
clearInterval(pollTimer);
|
|
3004
|
+
pollTimer = null;
|
|
3005
|
+
}
|
|
3006
|
+
|
|
3007
|
+
var WS_CONNECT_TIMEOUT_MS = 5000;
|
|
2832
3008
|
|
|
2833
3009
|
function connectWs() {
|
|
2834
|
-
if (wsRetries >= WS_MAX_RETRIES)
|
|
3010
|
+
if (wsRetries >= WS_MAX_RETRIES) {
|
|
3011
|
+
startPolling();
|
|
3012
|
+
return;
|
|
3013
|
+
}
|
|
2835
3014
|
var useDirect = !directFailed;
|
|
2836
3015
|
var ws;
|
|
2837
3016
|
try {
|
|
@@ -2841,10 +3020,17 @@
|
|
|
2841
3020
|
ws = new WebSocket(WS_URL);
|
|
2842
3021
|
ws.__direct = false;
|
|
2843
3022
|
}
|
|
3023
|
+
var connectTimer = setTimeout(function() {
|
|
3024
|
+
if (ws.readyState === WebSocket.CONNECTING) {
|
|
3025
|
+
try { ws.close(); } catch {}
|
|
3026
|
+
}
|
|
3027
|
+
}, WS_CONNECT_TIMEOUT_MS);
|
|
2844
3028
|
try {
|
|
2845
3029
|
ws.onopen = function() {
|
|
3030
|
+
clearTimeout(connectTimer);
|
|
2846
3031
|
if (state.ws !== ws) return;
|
|
2847
3032
|
wsRetries = 0;
|
|
3033
|
+
stopPolling();
|
|
2848
3034
|
if (ws.__direct) {
|
|
2849
3035
|
directFailures = 0;
|
|
2850
3036
|
directFailed = false;
|
|
@@ -2859,8 +3045,7 @@
|
|
|
2859
3045
|
}
|
|
2860
3046
|
}));
|
|
2861
3047
|
}
|
|
2862
|
-
|
|
2863
|
-
document.getElementById('ws-status').className = 'ws-status connected';
|
|
3048
|
+
setWsStatus('live', 'connected');
|
|
2864
3049
|
};
|
|
2865
3050
|
ws.onmessage = function(e) {
|
|
2866
3051
|
if (state.ws !== ws) return;
|
|
@@ -2874,6 +3059,7 @@
|
|
|
2874
3059
|
} catch {}
|
|
2875
3060
|
};
|
|
2876
3061
|
ws.onclose = function() {
|
|
3062
|
+
clearTimeout(connectTimer);
|
|
2877
3063
|
if (state.ws !== ws) return;
|
|
2878
3064
|
if (ws.__direct) {
|
|
2879
3065
|
directFailures += 1;
|
|
@@ -2881,13 +3067,12 @@
|
|
|
2881
3067
|
directFailed = true;
|
|
2882
3068
|
}
|
|
2883
3069
|
}
|
|
2884
|
-
document.getElementById('ws-status').textContent = 'reconnecting...';
|
|
2885
|
-
document.getElementById('ws-status').className = 'ws-status disconnected';
|
|
2886
3070
|
wsRetries++;
|
|
2887
3071
|
if (wsRetries < WS_MAX_RETRIES) {
|
|
3072
|
+
setWsStatus('connecting...', 'disconnected');
|
|
2888
3073
|
wsReconnectTimer = setTimeout(connectWs, 2000 + Math.min(wsRetries * 1000, 8000));
|
|
2889
3074
|
} else {
|
|
2890
|
-
|
|
3075
|
+
startPolling();
|
|
2891
3076
|
}
|
|
2892
3077
|
};
|
|
2893
3078
|
ws.onerror = function() {
|
|
@@ -2899,6 +3084,8 @@
|
|
|
2899
3084
|
wsRetries++;
|
|
2900
3085
|
if (wsRetries < WS_MAX_RETRIES) {
|
|
2901
3086
|
wsReconnectTimer = setTimeout(connectWs, 2000 + Math.min(wsRetries * 1000, 8000));
|
|
3087
|
+
} else {
|
|
3088
|
+
startPolling();
|
|
2902
3089
|
}
|
|
2903
3090
|
}
|
|
2904
3091
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentmemory/agentmemory",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.2",
|
|
4
4
|
"description": "Persistent memory for AI coding agents, powered by iii-engine's three primitives",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.mjs",
|
|
@@ -58,11 +58,13 @@
|
|
|
58
58
|
"@anthropic-ai/sdk": "^0.39.0",
|
|
59
59
|
"@clack/prompts": "^1.2.0",
|
|
60
60
|
"dotenv": "^16.4.7",
|
|
61
|
-
"iii-sdk": "^0.11.
|
|
61
|
+
"iii-sdk": "^0.11.2",
|
|
62
62
|
"zod": "^4.0.0"
|
|
63
63
|
},
|
|
64
64
|
"optionalDependencies": {
|
|
65
|
-
"@xenova/transformers": "^2.17.2"
|
|
65
|
+
"@xenova/transformers": "^2.17.2",
|
|
66
|
+
"onnxruntime-node": "^1.14.0",
|
|
67
|
+
"onnxruntime-web": "^1.14.0"
|
|
66
68
|
},
|
|
67
69
|
"devDependencies": {
|
|
68
70
|
"@types/node": "^22.0.0",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentmemory",
|
|
3
|
-
"version": "0.9.
|
|
4
|
-
"description": "Persistent memory for AI coding agents -- captures tool usage, compresses via LLM, injects context into future sessions. 12 hooks,
|
|
3
|
+
"version": "0.9.2",
|
|
4
|
+
"description": "Persistent memory for AI coding agents -- captures tool usage, compresses via LLM, injects context into future sessions. 12 hooks, 51 MCP tools, 4 skills, real-time viewer.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Rohit Ghumare",
|
|
7
7
|
"url": "https://github.com/rohitg00"
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
//#region src/hooks/notification.ts
|
|
3
|
+
function isSdkChildContext(payload) {
|
|
4
|
+
if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
|
|
5
|
+
if (!payload || typeof payload !== "object") return false;
|
|
6
|
+
return payload.entrypoint === "sdk-ts";
|
|
7
|
+
}
|
|
3
8
|
const REST_URL = process.env["AGENTMEMORY_URL"] || "http://localhost:3111";
|
|
4
9
|
const SECRET = process.env["AGENTMEMORY_SECRET"] || "";
|
|
5
10
|
function authHeaders() {
|
|
@@ -16,6 +21,7 @@ async function main() {
|
|
|
16
21
|
} catch {
|
|
17
22
|
return;
|
|
18
23
|
}
|
|
24
|
+
if (isSdkChildContext(data)) return;
|
|
19
25
|
if (data.notification_type !== "permission_prompt") return;
|
|
20
26
|
const sessionId = data.session_id || "unknown";
|
|
21
27
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notification.mjs","names":[],"sources":["../../src/hooks/notification.ts"],"sourcesContent":["#!/usr/bin/env node\n\nconst REST_URL = process.env[\"AGENTMEMORY_URL\"] || \"http://localhost:3111\";\nconst SECRET = process.env[\"AGENTMEMORY_SECRET\"] || \"\";\n\nfunction authHeaders(): Record<string, string> {\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (SECRET) h[\"Authorization\"] = `Bearer ${SECRET}`;\n return h;\n}\n\nasync function main() {\n let input = \"\";\n for await (const chunk of process.stdin) {\n input += chunk;\n }\n\n let data: Record<string, unknown>;\n try {\n data = JSON.parse(input);\n } catch {\n return;\n }\n\n if (data.notification_type !== \"permission_prompt\") return;\n\n const sessionId = (data.session_id as string) || \"unknown\";\n\n try {\n await fetch(`${REST_URL}/agentmemory/observe`, {\n method: \"POST\",\n headers: authHeaders(),\n body: JSON.stringify({\n hookType: \"notification\",\n sessionId,\n project: data.cwd || process.cwd(),\n cwd: data.cwd || process.cwd(),\n timestamp: new Date().toISOString(),\n data: {\n notification_type: data.notification_type,\n title: data.title,\n message: data.message,\n },\n }),\n signal: AbortSignal.timeout(2000),\n });\n } catch {\n // fire and forget\n }\n}\n\nmain();\n"],"mappings":";;AAEA,MAAM,WAAW,QAAQ,IAAI,sBAAsB;AACnD,MAAM,SAAS,QAAQ,IAAI,yBAAyB;AAEpD,SAAS,cAAsC;CAC7C,MAAM,IAA4B,EAAE,gBAAgB,oBAAoB;AACxE,KAAI,OAAQ,GAAE,mBAAmB,UAAU;AAC3C,QAAO;;AAGT,eAAe,OAAO;CACpB,IAAI,QAAQ;AACZ,YAAW,MAAM,SAAS,QAAQ,MAChC,UAAS;CAGX,IAAI;AACJ,KAAI;AACF,SAAO,KAAK,MAAM,MAAM;SAClB;AACN;;AAGF,KAAI,KAAK,sBAAsB,oBAAqB;CAEpD,MAAM,YAAa,KAAK,cAAyB;AAEjD,KAAI;AACF,QAAM,MAAM,GAAG,SAAS,uBAAuB;GAC7C,QAAQ;GACR,SAAS,aAAa;GACtB,MAAM,KAAK,UAAU;IACnB,UAAU;IACV;IACA,SAAS,KAAK,OAAO,QAAQ,KAAK;IAClC,KAAK,KAAK,OAAO,QAAQ,KAAK;IAC9B,4BAAW,IAAI,MAAM,EAAC,aAAa;IACnC,MAAM;KACJ,mBAAmB,KAAK;KACxB,OAAO,KAAK;KACZ,SAAS,KAAK;KACf;IACF,CAAC;GACF,QAAQ,YAAY,QAAQ,IAAK;GAClC,CAAC;SACI;;AAKV,MAAM"}
|
|
1
|
+
{"version":3,"file":"notification.mjs","names":[],"sources":["../../src/hooks/notification.ts"],"sourcesContent":["#!/usr/bin/env node\n\nfunction isSdkChildContext(payload: unknown): boolean {\n if (process.env[\"AGENTMEMORY_SDK_CHILD\"] === \"1\") return true;\n if (!payload || typeof payload !== \"object\") return false;\n return (payload as { entrypoint?: unknown }).entrypoint === \"sdk-ts\";\n}\n\nconst REST_URL = process.env[\"AGENTMEMORY_URL\"] || \"http://localhost:3111\";\nconst SECRET = process.env[\"AGENTMEMORY_SECRET\"] || \"\";\n\nfunction authHeaders(): Record<string, string> {\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (SECRET) h[\"Authorization\"] = `Bearer ${SECRET}`;\n return h;\n}\n\nasync function main() {\n let input = \"\";\n for await (const chunk of process.stdin) {\n input += chunk;\n }\n\n let data: Record<string, unknown>;\n try {\n data = JSON.parse(input);\n } catch {\n return;\n }\n\n if (isSdkChildContext(data)) return;\n if (data.notification_type !== \"permission_prompt\") return;\n\n const sessionId = (data.session_id as string) || \"unknown\";\n\n try {\n await fetch(`${REST_URL}/agentmemory/observe`, {\n method: \"POST\",\n headers: authHeaders(),\n body: JSON.stringify({\n hookType: \"notification\",\n sessionId,\n project: data.cwd || process.cwd(),\n cwd: data.cwd || process.cwd(),\n timestamp: new Date().toISOString(),\n data: {\n notification_type: data.notification_type,\n title: data.title,\n message: data.message,\n },\n }),\n signal: AbortSignal.timeout(2000),\n });\n } catch {\n // fire and forget\n }\n}\n\nmain();\n"],"mappings":";;AAEA,SAAS,kBAAkB,SAA2B;AACpD,KAAI,QAAQ,IAAI,6BAA6B,IAAK,QAAO;AACzD,KAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AACpD,QAAQ,QAAqC,eAAe;;AAG9D,MAAM,WAAW,QAAQ,IAAI,sBAAsB;AACnD,MAAM,SAAS,QAAQ,IAAI,yBAAyB;AAEpD,SAAS,cAAsC;CAC7C,MAAM,IAA4B,EAAE,gBAAgB,oBAAoB;AACxE,KAAI,OAAQ,GAAE,mBAAmB,UAAU;AAC3C,QAAO;;AAGT,eAAe,OAAO;CACpB,IAAI,QAAQ;AACZ,YAAW,MAAM,SAAS,QAAQ,MAChC,UAAS;CAGX,IAAI;AACJ,KAAI;AACF,SAAO,KAAK,MAAM,MAAM;SAClB;AACN;;AAGF,KAAI,kBAAkB,KAAK,CAAE;AAC7B,KAAI,KAAK,sBAAsB,oBAAqB;CAEpD,MAAM,YAAa,KAAK,cAAyB;AAEjD,KAAI;AACF,QAAM,MAAM,GAAG,SAAS,uBAAuB;GAC7C,QAAQ;GACR,SAAS,aAAa;GACtB,MAAM,KAAK,UAAU;IACnB,UAAU;IACV;IACA,SAAS,KAAK,OAAO,QAAQ,KAAK;IAClC,KAAK,KAAK,OAAO,QAAQ,KAAK;IAC9B,4BAAW,IAAI,MAAM,EAAC,aAAa;IACnC,MAAM;KACJ,mBAAmB,KAAK;KACxB,OAAO,KAAK;KACZ,SAAS,KAAK;KACf;IACF,CAAC;GACF,QAAQ,YAAY,QAAQ,IAAK;GAClC,CAAC;SACI;;AAKV,MAAM"}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
//#region src/hooks/post-tool-failure.ts
|
|
3
|
+
function isSdkChildContext(payload) {
|
|
4
|
+
if (process.env["AGENTMEMORY_SDK_CHILD"] === "1") return true;
|
|
5
|
+
if (!payload || typeof payload !== "object") return false;
|
|
6
|
+
return payload.entrypoint === "sdk-ts";
|
|
7
|
+
}
|
|
3
8
|
const REST_URL = process.env["AGENTMEMORY_URL"] || "http://localhost:3111";
|
|
4
9
|
const SECRET = process.env["AGENTMEMORY_SECRET"] || "";
|
|
5
10
|
function authHeaders() {
|
|
@@ -16,6 +21,7 @@ async function main() {
|
|
|
16
21
|
} catch {
|
|
17
22
|
return;
|
|
18
23
|
}
|
|
24
|
+
if (isSdkChildContext(data)) return;
|
|
19
25
|
if (data.is_interrupt) return;
|
|
20
26
|
const sessionId = data.session_id || "unknown";
|
|
21
27
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"post-tool-failure.mjs","names":[],"sources":["../../src/hooks/post-tool-failure.ts"],"sourcesContent":["#!/usr/bin/env node\n\nconst REST_URL = process.env[\"AGENTMEMORY_URL\"] || \"http://localhost:3111\";\nconst SECRET = process.env[\"AGENTMEMORY_SECRET\"] || \"\";\n\nfunction authHeaders(): Record<string, string> {\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (SECRET) h[\"Authorization\"] = `Bearer ${SECRET}`;\n return h;\n}\n\nasync function main() {\n let input = \"\";\n for await (const chunk of process.stdin) {\n input += chunk;\n }\n\n let data: Record<string, unknown>;\n try {\n data = JSON.parse(input);\n } catch {\n return;\n }\n\n if (data.is_interrupt) return;\n\n const sessionId = (data.session_id as string) || \"unknown\";\n\n try {\n await fetch(`${REST_URL}/agentmemory/observe`, {\n method: \"POST\",\n headers: authHeaders(),\n body: JSON.stringify({\n hookType: \"post_tool_failure\",\n sessionId,\n project: data.cwd || process.cwd(),\n cwd: data.cwd || process.cwd(),\n timestamp: new Date().toISOString(),\n data: {\n tool_name: data.tool_name,\n tool_input:\n typeof data.tool_input === \"string\"\n ? data.tool_input.slice(0, 4000)\n : JSON.stringify(data.tool_input ?? \"\").slice(0, 4000),\n error:\n typeof data.error === \"string\"\n ? data.error.slice(0, 4000)\n : JSON.stringify(data.error ?? \"\").slice(0, 4000),\n },\n }),\n signal: AbortSignal.timeout(3000),\n });\n } catch {\n // fire and forget\n }\n}\n\nmain();\n"],"mappings":";;AAEA,MAAM,WAAW,QAAQ,IAAI,sBAAsB;AACnD,MAAM,SAAS,QAAQ,IAAI,yBAAyB;AAEpD,SAAS,cAAsC;CAC7C,MAAM,IAA4B,EAAE,gBAAgB,oBAAoB;AACxE,KAAI,OAAQ,GAAE,mBAAmB,UAAU;AAC3C,QAAO;;AAGT,eAAe,OAAO;CACpB,IAAI,QAAQ;AACZ,YAAW,MAAM,SAAS,QAAQ,MAChC,UAAS;CAGX,IAAI;AACJ,KAAI;AACF,SAAO,KAAK,MAAM,MAAM;SAClB;AACN;;AAGF,KAAI,KAAK,aAAc;CAEvB,MAAM,YAAa,KAAK,cAAyB;AAEjD,KAAI;AACF,QAAM,MAAM,GAAG,SAAS,uBAAuB;GAC7C,QAAQ;GACR,SAAS,aAAa;GACtB,MAAM,KAAK,UAAU;IACnB,UAAU;IACV;IACA,SAAS,KAAK,OAAO,QAAQ,KAAK;IAClC,KAAK,KAAK,OAAO,QAAQ,KAAK;IAC9B,4BAAW,IAAI,MAAM,EAAC,aAAa;IACnC,MAAM;KACJ,WAAW,KAAK;KAChB,YACE,OAAO,KAAK,eAAe,WACvB,KAAK,WAAW,MAAM,GAAG,IAAK,GAC9B,KAAK,UAAU,KAAK,cAAc,GAAG,CAAC,MAAM,GAAG,IAAK;KAC1D,OACE,OAAO,KAAK,UAAU,WAClB,KAAK,MAAM,MAAM,GAAG,IAAK,GACzB,KAAK,UAAU,KAAK,SAAS,GAAG,CAAC,MAAM,GAAG,IAAK;KACtD;IACF,CAAC;GACF,QAAQ,YAAY,QAAQ,IAAK;GAClC,CAAC;SACI;;AAKV,MAAM"}
|
|
1
|
+
{"version":3,"file":"post-tool-failure.mjs","names":[],"sources":["../../src/hooks/post-tool-failure.ts"],"sourcesContent":["#!/usr/bin/env node\n\nfunction isSdkChildContext(payload: unknown): boolean {\n if (process.env[\"AGENTMEMORY_SDK_CHILD\"] === \"1\") return true;\n if (!payload || typeof payload !== \"object\") return false;\n return (payload as { entrypoint?: unknown }).entrypoint === \"sdk-ts\";\n}\n\nconst REST_URL = process.env[\"AGENTMEMORY_URL\"] || \"http://localhost:3111\";\nconst SECRET = process.env[\"AGENTMEMORY_SECRET\"] || \"\";\n\nfunction authHeaders(): Record<string, string> {\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (SECRET) h[\"Authorization\"] = `Bearer ${SECRET}`;\n return h;\n}\n\nasync function main() {\n let input = \"\";\n for await (const chunk of process.stdin) {\n input += chunk;\n }\n\n let data: Record<string, unknown>;\n try {\n data = JSON.parse(input);\n } catch {\n return;\n }\n\n if (isSdkChildContext(data)) return;\n if (data.is_interrupt) return;\n\n const sessionId = (data.session_id as string) || \"unknown\";\n\n try {\n await fetch(`${REST_URL}/agentmemory/observe`, {\n method: \"POST\",\n headers: authHeaders(),\n body: JSON.stringify({\n hookType: \"post_tool_failure\",\n sessionId,\n project: data.cwd || process.cwd(),\n cwd: data.cwd || process.cwd(),\n timestamp: new Date().toISOString(),\n data: {\n tool_name: data.tool_name,\n tool_input:\n typeof data.tool_input === \"string\"\n ? data.tool_input.slice(0, 4000)\n : JSON.stringify(data.tool_input ?? \"\").slice(0, 4000),\n error:\n typeof data.error === \"string\"\n ? data.error.slice(0, 4000)\n : JSON.stringify(data.error ?? \"\").slice(0, 4000),\n },\n }),\n signal: AbortSignal.timeout(3000),\n });\n } catch {\n // fire and forget\n }\n}\n\nmain();\n"],"mappings":";;AAEA,SAAS,kBAAkB,SAA2B;AACpD,KAAI,QAAQ,IAAI,6BAA6B,IAAK,QAAO;AACzD,KAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AACpD,QAAQ,QAAqC,eAAe;;AAG9D,MAAM,WAAW,QAAQ,IAAI,sBAAsB;AACnD,MAAM,SAAS,QAAQ,IAAI,yBAAyB;AAEpD,SAAS,cAAsC;CAC7C,MAAM,IAA4B,EAAE,gBAAgB,oBAAoB;AACxE,KAAI,OAAQ,GAAE,mBAAmB,UAAU;AAC3C,QAAO;;AAGT,eAAe,OAAO;CACpB,IAAI,QAAQ;AACZ,YAAW,MAAM,SAAS,QAAQ,MAChC,UAAS;CAGX,IAAI;AACJ,KAAI;AACF,SAAO,KAAK,MAAM,MAAM;SAClB;AACN;;AAGF,KAAI,kBAAkB,KAAK,CAAE;AAC7B,KAAI,KAAK,aAAc;CAEvB,MAAM,YAAa,KAAK,cAAyB;AAEjD,KAAI;AACF,QAAM,MAAM,GAAG,SAAS,uBAAuB;GAC7C,QAAQ;GACR,SAAS,aAAa;GACtB,MAAM,KAAK,UAAU;IACnB,UAAU;IACV;IACA,SAAS,KAAK,OAAO,QAAQ,KAAK;IAClC,KAAK,KAAK,OAAO,QAAQ,KAAK;IAC9B,4BAAW,IAAI,MAAM,EAAC,aAAa;IACnC,MAAM;KACJ,WAAW,KAAK;KAChB,YACE,OAAO,KAAK,eAAe,WACvB,KAAK,WAAW,MAAM,GAAG,IAAK,GAC9B,KAAK,UAAU,KAAK,cAAc,GAAG,CAAC,MAAM,GAAG,IAAK;KAC1D,OACE,OAAO,KAAK,UAAU,WAClB,KAAK,MAAM,MAAM,GAAG,IAAK,GACzB,KAAK,UAAU,KAAK,SAAS,GAAG,CAAC,MAAM,GAAG,IAAK;KACtD;IACF,CAAC;GACF,QAAQ,YAAY,QAAQ,IAAK;GAClC,CAAC;SACI;;AAKV,MAAM"}
|