eklavya 1.27.1 → 1.28.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.
|
@@ -358,6 +358,66 @@
|
|
|
358
358
|
summary.qa__meta::before { content:'▸'; color:var(--faint); }
|
|
359
359
|
details[open] > summary.qa__meta::before { content:'▾'; color:var(--spot); }
|
|
360
360
|
summary.qa__meta:focus-visible { outline:none; box-shadow:var(--ring); }
|
|
361
|
+
|
|
362
|
+
/* ---------- memory timeline ----------
|
|
363
|
+
One line per entry on a vertical rule. A row is a <details>: the title is
|
|
364
|
+
the summary, the snippet and the link to the full entry open under it, so
|
|
365
|
+
the list stays scannable and detail costs one click. */
|
|
366
|
+
.counts { margin:var(--space-2) 0 0; font-family:var(--font-mono); font-size:12px; color:var(--faint); }
|
|
367
|
+
.counts .warn { color:var(--warning); }
|
|
368
|
+
.tl { list-style:none; margin:var(--space-4) 0 0; padding:0; position:relative; }
|
|
369
|
+
.tl::before { content:''; position:absolute; left:67px; top:8px; bottom:8px; width:1px; background:var(--line-2); }
|
|
370
|
+
.tl-day { display:flex; align-items:baseline; gap:var(--space-3); padding:var(--space-5) 0 var(--space-2) 88px; position:relative; }
|
|
371
|
+
.tl-day:first-child { padding-top:0; }
|
|
372
|
+
.tl-day::before { content:''; position:absolute; left:62px; top:calc(var(--space-5) + 6px); width:11px; height:11px; background:var(--line-2); }
|
|
373
|
+
.tl-day:first-child::before { top:6px; }
|
|
374
|
+
.tl-day h2 { margin:0; font-family:var(--font-disp); font-size:var(--text-lg); font-weight:var(--weight-bold); letter-spacing:-.02em; }
|
|
375
|
+
.tl-day span { font-family:var(--font-mono); font-size:10.5px; letter-spacing:var(--tracking-caps); text-transform:uppercase; color:var(--spot); }
|
|
376
|
+
.tl-gap { padding:var(--space-2) 0 var(--space-2) 88px; font-family:var(--font-mono); font-size:11.5px; color:var(--faint); }
|
|
377
|
+
.tl-item > summary { list-style:none; cursor:pointer; display:grid; grid-template-columns:52px minmax(0,1fr) auto;
|
|
378
|
+
align-items:center; column-gap:36px; min-height:44px; padding-right:var(--space-3); position:relative; }
|
|
379
|
+
.tl-item > summary::-webkit-details-marker { display:none; }
|
|
380
|
+
.tl-item > summary::before { content:''; position:absolute; left:62px; top:50%; width:11px; height:11px; margin-top:-5.5px;
|
|
381
|
+
box-sizing:border-box; border-radius:50%; border:2px solid var(--dim); background:var(--bg); }
|
|
382
|
+
.tl-item > summary:hover { background:var(--panel); }
|
|
383
|
+
.tl-item > summary:focus-visible { outline:none; box-shadow:var(--ring); }
|
|
384
|
+
.tl-item[open] > summary::before { background:var(--spot); border-color:var(--spot); }
|
|
385
|
+
.tl-item[open] { background:var(--panel); }
|
|
386
|
+
.tl-time { font-family:var(--font-mono); font-size:12px; color:var(--faint); text-align:right; font-variant-numeric:tabular-nums; }
|
|
387
|
+
.tl-title { font-size:15px; font-weight:var(--weight-medium); color:var(--ink); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
|
|
388
|
+
.tl-item[open] > summary .tl-title { font-weight:var(--weight-semibold); }
|
|
389
|
+
.tl-type { font-family:var(--font-mono); font-size:10.5px; letter-spacing:.12em; text-transform:uppercase; color:var(--faint); white-space:nowrap; }
|
|
390
|
+
.tl-body { padding:0 var(--space-4) var(--space-4) 88px; display:grid; gap:var(--space-3); }
|
|
391
|
+
.tl-body p { margin:0; color:var(--dim); font-size:13.5px; max-width:72ch; overflow-wrap:anywhere; }
|
|
392
|
+
.tl-meta { display:flex; flex-wrap:wrap; align-items:center; gap:var(--space-2) var(--space-4);
|
|
393
|
+
font-family:var(--font-mono); font-size:11.5px; color:var(--faint); }
|
|
394
|
+
.tl-meta .link { margin-left:auto; font-family:var(--font-body); font-size:13.5px; font-weight:var(--weight-semibold); }
|
|
395
|
+
.tl-item.gone .tl-title { text-decoration:line-through; color:var(--faint); }
|
|
396
|
+
/* A session is a larger ring; its observations fold under it. */
|
|
397
|
+
.tl-session > summary::before { width:15px; height:15px; margin-top:-7.5px; left:60px; border-color:var(--spot); }
|
|
398
|
+
.tl-session[open] > summary::before { background:var(--bg); }
|
|
399
|
+
.tl-session[open] { background:none; }
|
|
400
|
+
.tl-session > summary .tl-title { font-weight:var(--weight-medium); }
|
|
401
|
+
.tl-session > summary .tl-type { color:var(--spot); }
|
|
402
|
+
.tl-kids { list-style:none; margin:0; padding:0; }
|
|
403
|
+
.tl-kids .tl-item > summary::before { left:64px; width:7px; height:7px; margin-top:-3.5px; border-color:var(--faint-2); }
|
|
404
|
+
.tl-kids .tl-item[open] > summary::before { border-color:var(--spot); }
|
|
405
|
+
.tl-kids .tl-title { font-size:14px; padding-left:var(--space-6); }
|
|
406
|
+
.tl-kids .tl-body { padding-left:112px; }
|
|
407
|
+
.tl-kids .tl-gap { padding-left:112px; }
|
|
408
|
+
#mwhen, #mtype, #mtag { max-width:100%; min-width:0; }
|
|
409
|
+
/* Narrow: the title gets the width and two lines; the type drops under it. */
|
|
410
|
+
@media (max-width:560px) {
|
|
411
|
+
.tl-item > summary { grid-template-columns:52px minmax(0,1fr); padding:var(--space-2) var(--space-2) var(--space-2) 0; }
|
|
412
|
+
.tl-item > summary::before { top:calc(var(--space-2) + 11px); margin-top:0; }
|
|
413
|
+
.tl-session > summary::before { top:calc(var(--space-2) + 9px); }
|
|
414
|
+
.tl-kids .tl-item > summary::before { top:calc(var(--space-2) + 13px); }
|
|
415
|
+
.tl-time { align-self:start; padding-top:3px; }
|
|
416
|
+
.tl-title { white-space:normal; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; }
|
|
417
|
+
.tl-type { grid-column:2; margin-top:2px; }
|
|
418
|
+
.tl-kids .tl-type { padding-left:var(--space-6); }
|
|
419
|
+
.tl-body, .tl-kids .tl-body, .tl-kids .tl-gap { padding-left:88px; }
|
|
420
|
+
}
|
|
361
421
|
.raw { font-family:var(--font-mono); font-size:12px; line-height:1.55; white-space:pre-wrap;
|
|
362
422
|
word-break:break-word; color:var(--dim); background:var(--mass); padding:var(--space-3);
|
|
363
423
|
max-height:320px; overflow:auto; margin:var(--space-3) 0 0; }
|
|
@@ -1728,24 +1788,72 @@ function memoryQuery(type) {
|
|
|
1728
1788
|
return p.toString();
|
|
1729
1789
|
}
|
|
1730
1790
|
|
|
1791
|
+
const dayName = (d) => d.toLocaleDateString(undefined, { weekday:'short', day:'numeric', month:'short' });
|
|
1792
|
+
const clock = (d) => d.toLocaleTimeString(undefined, { hour:'2-digit', minute:'2-digit' });
|
|
1793
|
+
|
|
1794
|
+
/** One entry on the timeline: a line that opens to its snippet and a link to the full entry. */
|
|
1795
|
+
function tlEntry(e) {
|
|
1796
|
+
const d = parse(e.occurred_at);
|
|
1797
|
+
const more = e.narrative_length > String(e.snippet ?? '').length;
|
|
1798
|
+
const gone = e.deleted_at || e.superseded_by;
|
|
1799
|
+
return `<li><details class="tl-item${gone ? ' gone' : ''}" data-entry="${esc(e.id)}">
|
|
1800
|
+
<summary><span class="tl-time">${d ? esc(clock(d)) : '—'}</span>
|
|
1801
|
+
<span class="tl-title">${esc(e.title)}</span><span class="tl-type">${esc(e.type ?? e.kind)}</span></summary>
|
|
1802
|
+
<div class="tl-body">
|
|
1803
|
+
${e.snippet ? `<p>${esc(e.snippet)}${more ? '…' : ''}</p>` : ''}
|
|
1804
|
+
<div class="tl-meta"><span>${esc(pname(e.project))}</span><span>${plural(e.event_count, 'evidence event')}</span>
|
|
1805
|
+
${entryMark(e)}<a class="link" data-go="${esc(MH('entry', e.id))}">Open entry →</a></div>
|
|
1806
|
+
</div></details></li>`;
|
|
1807
|
+
}
|
|
1808
|
+
|
|
1809
|
+
/**
|
|
1810
|
+
* The page's entries as a timeline: grouped by local day, and an entry that
|
|
1811
|
+
* shares a session with a session summary on this page folds under that
|
|
1812
|
+
* summary. Grouping is per page — a session whose summary sits on the next page
|
|
1813
|
+
* shows its observations as ordinary lines here — because the server pages
|
|
1814
|
+
* entries, not sessions.
|
|
1815
|
+
*/
|
|
1731
1816
|
function drawMemory(d) {
|
|
1732
1817
|
T.memory.page = d.page; // the server clamps a page number a filter shrank
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1818
|
+
if (!d.rows.length) return '<p class="empty">Nothing in memory matches these filters.</p>';
|
|
1819
|
+
const summaries = new Map(d.rows.filter((e) => e.kind === 'session_summary' && e.session_id).map((e) => [e.session_id, e]));
|
|
1820
|
+
const kids = new Map();
|
|
1821
|
+
for (const e of d.rows) {
|
|
1822
|
+
if (e.kind === 'session_summary' || !summaries.has(e.session_id)) continue;
|
|
1823
|
+
if (!kids.has(e.session_id)) kids.set(e.session_id, []);
|
|
1824
|
+
kids.get(e.session_id).push(e);
|
|
1825
|
+
}
|
|
1826
|
+
const now = new Date();
|
|
1827
|
+
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime();
|
|
1828
|
+
const out = [];
|
|
1829
|
+
let last = null;
|
|
1830
|
+
for (const e of d.rows) {
|
|
1831
|
+
if (e.kind !== 'session_summary' && summaries.has(e.session_id)) continue; // drawn under its summary
|
|
1832
|
+
const at = parse(e.occurred_at);
|
|
1833
|
+
const day = at ? new Date(at.getFullYear(), at.getMonth(), at.getDate()) : null;
|
|
1834
|
+
if (day && (!last || day.getTime() !== last.getTime())) {
|
|
1835
|
+
if (last) {
|
|
1836
|
+
const gap = Math.round((last - day) / DAY_MS) - 1;
|
|
1837
|
+
const after = new Date(day.getFullYear(), day.getMonth(), day.getDate() + 1);
|
|
1838
|
+
const before = new Date(last.getFullYear(), last.getMonth(), last.getDate() - 1);
|
|
1839
|
+
if (gap === 1) out.push(`<li class="tl-gap">Nothing on ${esc(dayName(after))}</li>`);
|
|
1840
|
+
if (gap > 1) out.push(`<li class="tl-gap">Nothing from ${esc(dayName(after))} to ${esc(dayName(before))}</li>`);
|
|
1841
|
+
}
|
|
1842
|
+
const note = day.getTime() === today ? 'Today' : Math.round((today - day.getTime()) / DAY_MS) === 1 ? 'Yesterday' : '';
|
|
1843
|
+
out.push(`<li class="tl-day"><h2>${esc(dayName(day))}</h2>${note ? `<span>${note}</span>` : ''}</li>`);
|
|
1844
|
+
last = day;
|
|
1845
|
+
}
|
|
1846
|
+
const inner = kids.get(e.session_id);
|
|
1847
|
+
if (e.kind === 'session_summary' && inner) {
|
|
1848
|
+
out.push(`<li><details class="tl-item tl-session">
|
|
1849
|
+
<summary><span class="tl-time">${at ? esc(clock(at)) : '—'}</span>
|
|
1850
|
+
<span class="tl-title">${esc(e.title.replace(/^Session:\s*/, ''))}</span>
|
|
1851
|
+
<span class="tl-type">Session · ${plural(inner.length, 'observation')}</span></summary>
|
|
1852
|
+
<ol class="tl-kids">${inner.map(tlEntry).join('')}
|
|
1853
|
+
<li class="tl-gap"><a class="link" data-go="${esc(MH('entry', e.id))}">The session summary →</a></li></ol></details></li>`);
|
|
1854
|
+
} else out.push(tlEntry(e));
|
|
1855
|
+
}
|
|
1856
|
+
return `<ol class="tl" aria-label="Timeline">${out.join('')}</ol>` + pager('memory', d.total, d.page, d.per);
|
|
1749
1857
|
}
|
|
1750
1858
|
|
|
1751
1859
|
/**
|
|
@@ -1754,25 +1862,41 @@ function drawMemory(d) {
|
|
|
1754
1862
|
* selector; indexing, reuse, delivery and assessment are only aggregated for
|
|
1755
1863
|
* the whole database, and say so rather than pretend to be this project's.
|
|
1756
1864
|
*/
|
|
1757
|
-
function
|
|
1865
|
+
function memCounts() {
|
|
1758
1866
|
const M = S.memory;
|
|
1759
1867
|
const scoped = PROJECT !== null;
|
|
1760
1868
|
const inv = projectsInScope();
|
|
1761
1869
|
const sum = (f) => inv.reduce((a, p) => a + f(p), 0);
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1870
|
+
return {
|
|
1871
|
+
scoped,
|
|
1872
|
+
events: scoped ? sum((p) => p.memory.events) : M.captured,
|
|
1873
|
+
pending: scoped ? sum((p) => p.memory.pending) : M.pending,
|
|
1874
|
+
entries: scoped ? sum((p) => p.memory.entries) : M.entries,
|
|
1875
|
+
sessions: scoped ? sum((p) => p.memory.sessions) : INV.projects.reduce((a, p) => a + p.memory.sessions, 0),
|
|
1876
|
+
};
|
|
1877
|
+
}
|
|
1878
|
+
|
|
1879
|
+
function memTiles() {
|
|
1880
|
+
const M = S.memory;
|
|
1881
|
+
const { scoped, events, pending, entries, sessions } = memCounts();
|
|
1765
1882
|
const everywhere = scoped ? 'all projects · ' : '';
|
|
1766
1883
|
return tiles([
|
|
1767
1884
|
['Observations', entries, scoped ? `live here · ${M.indexed} indexed across all projects`
|
|
1768
1885
|
: `${M.entries_total} written · ${M.superseded} superseded · ${M.deleted} deleted · ${M.indexed} indexed`, '', MH('timeline')],
|
|
1769
1886
|
['Evidence', events, `${events - pending} distilled · ${pending} still pending`, pending ? 'warn' : '', MH('health')],
|
|
1770
|
-
['Sessions',
|
|
1887
|
+
['Sessions', sessions, 'that captured or remembered', '', MH('sessions')],
|
|
1771
1888
|
['Reused', M.reused, `${everywhere}${M.exposed} actually delivered`, '', MH('reuse')],
|
|
1772
1889
|
['Assessed', M.assessed, everywhere + 'evidence concepts you were asked about', '', LH('concepts')],
|
|
1773
1890
|
]);
|
|
1774
1891
|
}
|
|
1775
1892
|
|
|
1893
|
+
/** `YYYY-MM-DD` for n days before today, local — what a date input holds. */
|
|
1894
|
+
const daysAgo = (n) => {
|
|
1895
|
+
const d = new Date(); d.setDate(d.getDate() - n);
|
|
1896
|
+
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
|
|
1897
|
+
};
|
|
1898
|
+
const WHEN = { today:0, '7d':6, '30d':29 };
|
|
1899
|
+
|
|
1776
1900
|
function viewMemory(param) {
|
|
1777
1901
|
const t = T.memory;
|
|
1778
1902
|
const M = S.memory;
|
|
@@ -1785,35 +1909,41 @@ function viewMemory(param) {
|
|
|
1785
1909
|
t.until = CUR.query.get('to') || '';
|
|
1786
1910
|
fill('mem-rows', '/api/memory?' + memoryQuery(type), drawMemory);
|
|
1787
1911
|
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
const
|
|
1791
|
-
|
|
1912
|
+
// A preset is only a `from` date, so the URL stays the one date format and a
|
|
1913
|
+
// shared link reads the same; anything else is a custom range.
|
|
1914
|
+
const when = !t.since && !t.until ? 'any'
|
|
1915
|
+
: !t.until && Object.keys(WHEN).find((k) => daysAgo(WHEN[k]) === t.since) || 'custom';
|
|
1916
|
+
const opt = (v, label, on) => `<option value="${esc(v)}"${on ? ' selected' : ''}>${esc(label)}</option>`;
|
|
1917
|
+
const typeOpts = opt('all', 'All types', type === 'all')
|
|
1918
|
+
+ types.map((x) => opt(x.type, `${x.type} (${x.n})`, type === x.type)).join('')
|
|
1919
|
+
+ (type !== 'all' && !types.some((x) => x.type === type) ? opt(type, `${type} (0)`, true) : '');
|
|
1920
|
+
const { entries, sessions, pending } = memCounts();
|
|
1792
1921
|
|
|
1793
1922
|
return [
|
|
1794
1923
|
`<div>
|
|
1795
1924
|
<h1 class="page__title">Timeline</h1>
|
|
1796
|
-
<p class="
|
|
1797
|
-
|
|
1798
|
-
you see is the audit trail and not a tidied version of it.</p>
|
|
1925
|
+
<p class="counts">${plural(entries, 'observation')} · ${plural(sessions, 'session')}${pending
|
|
1926
|
+
? ` · <a class="link warn" data-go="${esc(MH('health'))}">${pending} evidence pending</a>` : ''}</p>
|
|
1799
1927
|
</div>`,
|
|
1800
1928
|
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
<div class="grow"><input type="search" id="mq" value="${esc(t.q)}" placeholder="Search titles, narrative, facts and files…" aria-label="Search memory"></div>
|
|
1929
|
+
`<div>
|
|
1930
|
+
<div class="filters">
|
|
1931
|
+
<div class="grow"><input type="search" id="mq" value="${esc(t.q)}" placeholder="Search memory" aria-label="Search memory"></div>
|
|
1932
|
+
<select id="mtype" aria-label="Type">${typeOpts}</select>
|
|
1806
1933
|
<select id="mtag" aria-label="Tag">
|
|
1807
1934
|
<option value="all">All tags</option>
|
|
1808
|
-
${(M.tags ?? []).map((x) =>
|
|
1935
|
+
${(M.tags ?? []).map((x) => opt(x.tag, `${x.tag} (${x.n})`, t.tag === x.tag)).join('')}
|
|
1809
1936
|
</select>
|
|
1810
|
-
<
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1937
|
+
<select id="mwhen" aria-label="When">
|
|
1938
|
+
${opt('any', 'Any time', when === 'any')}${opt('today', 'Today', when === 'today')}
|
|
1939
|
+
${opt('7d', 'Last 7 days', when === '7d')}${opt('30d', 'Last 30 days', when === '30d')}
|
|
1940
|
+
${opt('custom', 'Custom range', when === 'custom')}
|
|
1941
|
+
</select>
|
|
1942
|
+
${when === 'custom' ? `<input type="date" id="mfrom" value="${esc(t.since)}" aria-label="From date">
|
|
1943
|
+
<input type="date" id="mto" value="${esc(t.until)}" aria-label="To date">` : ''}
|
|
1815
1944
|
</div>
|
|
1816
|
-
<div
|
|
1945
|
+
<div id="mem-rows"><p class="empty">Loading the timeline…</p></div>
|
|
1946
|
+
</div>`,
|
|
1817
1947
|
].join('');
|
|
1818
1948
|
}
|
|
1819
1949
|
|
|
@@ -2782,13 +2912,6 @@ function onActivate(e) {
|
|
|
2782
2912
|
}
|
|
2783
2913
|
const tab = e.target.closest('[data-tab]');
|
|
2784
2914
|
if (tab) { T.review.page = 1; return goTo(LH('review', tab.dataset.tab === 'due' ? null : tab.dataset.tab)); }
|
|
2785
|
-
const mtype = e.target.closest('[data-mtype]');
|
|
2786
|
-
if (mtype) {
|
|
2787
|
-
T.memory.page = 1;
|
|
2788
|
-
const q = CUR.query;
|
|
2789
|
-
return goTo(MH('timeline', mtype.dataset.mtype === 'all' ? null : mtype.dataset.mtype,
|
|
2790
|
-
{ tag: q.get('tag'), from: q.get('from'), to: q.get('to') }));
|
|
2791
|
-
}
|
|
2792
2915
|
const go = e.target.closest('[data-go]');
|
|
2793
2916
|
if (go) return goTo(go.dataset.go);
|
|
2794
2917
|
}
|
|
@@ -2798,7 +2921,7 @@ $('view').addEventListener('click', onActivate);
|
|
|
2798
2921
|
// are divs and table rows, so Enter and Space have to be wired by hand.
|
|
2799
2922
|
$('view').addEventListener('keydown', (e) => {
|
|
2800
2923
|
if (e.key !== 'Enter' && e.key !== ' ') return;
|
|
2801
|
-
if (!e.target.closest('[data-go],[data-state],[data-tab],[data-page]
|
|
2924
|
+
if (!e.target.closest('[data-go],[data-state],[data-tab],[data-page]')) return;
|
|
2802
2925
|
e.preventDefault();
|
|
2803
2926
|
onActivate(e);
|
|
2804
2927
|
});
|
|
@@ -2825,6 +2948,19 @@ $('view').addEventListener('change', (e) => {
|
|
|
2825
2948
|
if (e.target.id === 'dom') { T.concepts.page = 1; setQuery({ domain: e.target.value }); }
|
|
2826
2949
|
if (e.target.id === 'sort') { T.concepts.sort = e.target.value; T.concepts.page = 1; render(); }
|
|
2827
2950
|
if (e.target.id === 'mtag') { T.memory.page = 1; setQuery({ tag: e.target.value }); }
|
|
2951
|
+
if (e.target.id === 'mtype') {
|
|
2952
|
+
T.memory.page = 1;
|
|
2953
|
+
const q = CUR.query;
|
|
2954
|
+
goTo(MH('timeline', e.target.value === 'all' ? null : e.target.value,
|
|
2955
|
+
{ tag: q.get('tag'), from: q.get('from'), to: q.get('to') }));
|
|
2956
|
+
}
|
|
2957
|
+
if (e.target.id === 'mwhen') {
|
|
2958
|
+
T.memory.page = 1;
|
|
2959
|
+
const v = e.target.value;
|
|
2960
|
+
// Custom keeps the range's start, closes it at today and reveals the date boxes.
|
|
2961
|
+
if (v === 'custom') setQuery({ from: CUR.query.get('from') || daysAgo(6), to: daysAgo(0) });
|
|
2962
|
+
else setQuery({ from: v === 'any' ? null : daysAgo(WHEN[v]), to: null });
|
|
2963
|
+
}
|
|
2828
2964
|
if (e.target.id === 'mfrom') { T.memory.page = 1; setQuery({ from: e.target.value }); }
|
|
2829
2965
|
if (e.target.id === 'mto') { T.memory.page = 1; setQuery({ to: e.target.value }); }
|
|
2830
2966
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eklavya",
|
|
3
3
|
"displayName": "Eklavya",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.28.0",
|
|
5
5
|
"description": "Learn while your agent works. Turns coding-agent generation time into adaptive, Socratic learning grounded in the code being written.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Ajay Kumar"
|
package/package.json
CHANGED