Signals: index the judge's query, six calls at once, one call per item on the server's key, tokens counted, a week's look-back an admin sets, edits that ask again only what was picked out (#274, #275, #276)
The judge's query read all of entries (605 MB, 566 ms) on every wake; an index on each feed's items by date, as the query asks, and the rechecks in a half of their own. Calls ran one at a time, about 150 ms each, so a new Signal's month of about 8,000 items took twenty minutes: six in flight now. On the server's key everyone's Signals on an item share one call. TypeSafe's token counts go to /metrics and each jev span. An item's text is cut at 1,000 characters instead of 2,000: on 55 real items of eight podcast feeds and six Signals, on the development key, 1,000 changed none of 330 verdicts (nor did the same request twice) and saved 12% of the input tokens, 1,266 to 1,112 a call; 500 changed one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -14,10 +14,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
### Added
|
||||
|
||||
- Admin, Server: a setting to give everyone Signals on the server's TypeSafe key (#271).
|
||||
- Admin, Server: how many days back a new Signal reads (#276).
|
||||
|
||||
### Changed
|
||||
|
||||
- Unless the server pays for them, Signals are turned on in Settings with your own TypeSafe key, and the Signals folder shows only once they are on (#271).
|
||||
- A Signal's dialog says how far back it reads, and that an edit reads again only what was picked out (#276).
|
||||
|
||||
## [1.1.0] - 2026-10-16
|
||||
|
||||
|
||||
@@ -58,6 +58,11 @@ async function drawServer(){
|
||||
<span class="hint">${g.typesafe_server_key
|
||||
? 'On, everyone has Signals and every item read for one is a call on this server\'s key. Off, each person turns Signals on in their own Settings with a key of their own.'
|
||||
: 'This server has no TypeSafe key (<code>TYPESAFE_KEY</code>), so each person uses their own.'}</span></div>
|
||||
<div class="field"><label for="gsigdays">Signals look back (days)</label>
|
||||
<input type="number" id="gsigdays" min="1" max="365" value="${g.signal_days}">
|
||||
<span class="hint">How far back a new Signal reads. Each item read is a call to TypeSafe, so a
|
||||
longer look back costs more, once for each new Signal. Editing a Signal reads again only what
|
||||
it had picked out.</span></div>
|
||||
<div class="field"><label>Download folder</label>
|
||||
<span class="hint" style="overflow-wrap:anywhere">${esc(g.download_dir)}</span></div>
|
||||
<div class="cardacts"><button class="btn primary" id="gsave">${ICON.check} Save</button></div>`;
|
||||
@@ -70,6 +75,7 @@ async function drawServer(){
|
||||
max_total_gb: Number($<HTMLInputElement>('#gquota').value) || 0,
|
||||
max_age_days: Number($<HTMLInputElement>('#gage').value) || 0,
|
||||
art_cache_mb: Math.max(0, Number($<HTMLInputElement>('#gart').value) || 0),
|
||||
signal_days: Math.min(365, Math.max(1, Number($<HTMLInputElement>('#gsigdays').value) || 7)),
|
||||
// Left alone while the server has no key to offer, rather than switched off.
|
||||
...($<HTMLInputElement>('#gsig').disabled ? {} : {signals_on_server: $<HTMLInputElement>('#gsig').checked})})});
|
||||
toast('Settings saved');
|
||||
|
||||
@@ -151,9 +151,9 @@ function signalModal(sg?: Signal){
|
||||
<div class="chips" id="sgkw">${chipsHTML(sg?.keywords||[],'sgkwin')}</div></div>
|
||||
<div class="field"><label for="sgdesc">In your own words (optional)</label>
|
||||
<input type="text" id="sgdesc" value="${esc(sg?.description||'')}" placeholder="AI tools for writing software: coding agents, vibe coding">
|
||||
<span class="hint">Every item in the feeds you subscribe to is read, the last 30 days of them
|
||||
<span class="hint">Every item in the feeds you subscribe to is read, the last ${plural(S.me?.signal_days??7,'day')} of them
|
||||
and each new one, and the ones about this subject are pulled out: its name, these words and
|
||||
your sentence together. The rest stays noise, in its own feed.${S.me?.signals==='server'?'':' Each item is one call on your TypeSafe key.'}${sg?' A change here reads everything again.':''}</span></div>
|
||||
your sentence together. The rest stays noise, in its own feed.${S.me?.signals==='server'?'':' Each item is one call on your TypeSafe key.'}${sg?' A change here reads again what was picked out, and listens for it in new items; what was passed over stays passed over.':''}</span></div>
|
||||
${nokey?`<p class="hint" style="color:var(--warn)">Without a TypeSafe key, nothing is picked out. ${KEY_LINKS}</p>`:''}
|
||||
<div class="cardacts"><button class="btn ico" onclick="closeModal()" title="Cancel" aria-label="Cancel">${ICON.close}</button>
|
||||
<button class="btn ico primary" id="sgsave" title="${sg?'Save':'Make signal'}" aria-label="${sg?'Save':'Make signal'}">${sg?ICON.check:ICON.plus}</button></div>`);
|
||||
|
||||
@@ -86,6 +86,8 @@ interface Me {
|
||||
typesafe_key_set: boolean;
|
||||
/// Whose TypeSafe key Signals are judged on (#271): the server's, for everyone, or each person's own.
|
||||
signals: 'server' | 'own';
|
||||
/// How many days back a new Signal reads (#276), an admin's setting.
|
||||
signal_days: number;
|
||||
}
|
||||
|
||||
/// A Signal in your sidebar, `/api/signals` (db.rs SignalRow).
|
||||
|
||||
Reference in New Issue
Block a user