strom-research 1.13.2-beta.5 → 1.13.2-beta.6
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/assets/lang/cs.json +63 -1
- package/assets/lang/de.json +63 -1
- package/assets/method/core.md +13 -3
- package/assets/method/reading.md +12 -11
- package/assets/plugins/gates/README.md +28 -1
- package/assets/plugins/gates/claude-usage/gate.json +1 -1
- package/assets/plugins/gates/claude-usage/gate.ts +100 -22
- package/dist/agents/files.js +5 -3
- package/dist/agents/profiles.js +12 -8
- package/dist/agents/scanreader.js +16 -9
- package/dist/brief/brief.js +226 -64
- package/dist/brief/sheet.js +2 -0
- package/dist/cli/help.js +1 -1
- package/dist/cli/main.js +4 -3
- package/dist/cli/menu-settings.js +19 -1
- package/dist/cli/menu.js +7 -0
- package/dist/cli/ui.js +49 -1
- package/dist/commands/analysis.js +21 -11
- package/dist/commands/calibrate.js +203 -0
- package/dist/commands/connectors.js +69 -6
- package/dist/commands/gates.js +8 -4
- package/dist/commands/guide.js +5 -3
- package/dist/commands/index.js +1 -0
- package/dist/commands/media.js +18 -12
- package/dist/commands/meta.js +8 -2
- package/dist/commands/read.js +9 -4
- package/dist/commands/readers.js +11 -6
- package/dist/commands/session.js +46 -8
- package/dist/commands/setup.js +23 -5
- package/dist/commands/tasks.js +39 -7
- package/dist/core/assets.js +11 -4
- package/dist/core/changelog.js +105 -14
- package/dist/core/clock.js +37 -2
- package/dist/core/config.js +5 -1
- package/dist/core/connector.js +49 -0
- package/dist/core/edge.js +8 -2
- package/dist/core/evidence.js +7 -0
- package/dist/core/gate.js +42 -7
- package/dist/core/hypolinks.js +121 -6
- package/dist/core/live.js +22 -7
- package/dist/core/mediaindex.js +24 -2
- package/dist/core/phrases.js +15 -0
- package/dist/core/session.js +2 -2
- package/dist/core/tree.js +1 -1
- package/dist/core/viewsample.js +366 -0
- package/dist/core/viewsizes.js +78 -0
- package/dist/gedcom/export.js +24 -4
- package/dist/gedcom/validate.js +7 -4
- package/dist/runners/claude.js +46 -5
- package/dist/runners/runner.js +9 -0
- package/package.json +1 -1
package/assets/lang/cs.json
CHANGED
|
@@ -137,6 +137,37 @@
|
|
|
137
137
|
"ui.chat.app.model.chosen": "V aplikaci {app} zvolit pro výzkum model {model} (zvolený v nastavení).",
|
|
138
138
|
"ui.settings.model": "Model výzkumu ({agent}): {model}",
|
|
139
139
|
"ui.settings.model.own": "vlastní model agenta",
|
|
140
|
+
"ui.views.title": "Ladění čtení snímků · {agent}: snímků {n}, knih {books}, velikosti {sizes} px",
|
|
141
|
+
"ui.views.find": "Nalezení zápisu na celém snímku:",
|
|
142
|
+
"ui.views.find.row": " {size} px na místě {located} z {n} · na snímku bez něj {wrong} z {neg} · {cost}",
|
|
143
|
+
"ui.views.read": "Přečtení zápisu z poloviny nebo strany:",
|
|
144
|
+
"ui.views.read.row": " {size} px přečteno {keys} z {total} · nejistých míst {unsure} · {cost}",
|
|
145
|
+
"ui.views.rule": "Menší velikost se uloží jen při jasném výsledku: každý zápis nalezený na místě jako u největší velikosti a žádný navíc na snímku bez něj; přečteno celkem aspoň tolik, žádný zápis o víc než jeden údaj méně, nejistých míst ne víc.",
|
|
146
|
+
"ui.views.stored": "Uloženo pro {agent} ({date}): hledání {find} px · čtení {read} px — řídí se tím strom media view a strom read; zpět na výchozí: strom media calibrate --reset",
|
|
147
|
+
"ui.views.kept": "Bez jasného výsledku: nic se neuložilo, velikosti zůstávají, jak byly.",
|
|
148
|
+
"ui.views.unclear.find": "Hledání: bez jasného výsledku — zůstává výchozí ({size} px).",
|
|
149
|
+
"ui.views.unclear.read": "Čtení: bez jasného výsledku — zůstává výchozí ({size} px).",
|
|
150
|
+
"ui.views.failed": "Čtení, která nedoběhla: {failed} — nic se neuložilo, velikosti zůstávají, jak byly.",
|
|
151
|
+
"ui.views.few": "Na vyladění čtení snímků je málo snímků se známou pravdou: {have} z potřebných {need}. Takový snímek je sken záznamu, který cituje doložený údaj, s jeho slovy (přepisem) a už na tomto počítači; chybí ještě {more} — vzniknou běžnou prací agenta, zkusit znovu po několika sezeních. Do té doby platí výchozí velikosti.",
|
|
152
|
+
"ui.views.ask": "Vyladit čtení snímků pro {agent}: {readers} placených čtení {n} snímků tohoto výzkumu ve velikostech {sizes} px, asi {cost} (typický odhad; ceny agenta se mohou lišit). Spustit?",
|
|
153
|
+
"ui.views.no": "Nic se nespustilo; velikosti zůstávají, jak byly.",
|
|
154
|
+
"ui.views.reset": "Vyladění pro {agent} zapomenuto: platí výchozí velikosti (hledání {find} px · čtení {read} px).",
|
|
155
|
+
"ui.views.reset.none": "Pro {agent} nic vyladěno není: platí výchozí velikosti (hledání {find} px · čtení {read} px).",
|
|
156
|
+
"ui.views.estimate": "Snímků {n}, knih {books}, {readers} čtení ve velikostech {sizes} px, asi {cost} — spouští člověk: strom media calibrate",
|
|
157
|
+
"ui.views.offer": "čtení snímků bylo vyladěno pro {before}, pro {now} zatím ne: strom media calibrate (spouští člověk; placená práce modelu)",
|
|
158
|
+
"ui.views.progress": "▶ {what} · {size} px · snímky: {n}",
|
|
159
|
+
"ui.views.what.find": "hledání",
|
|
160
|
+
"ui.views.what.read": "čtení",
|
|
161
|
+
"ui.views.cost.unknown": "cena neznámá",
|
|
162
|
+
"ui.views.spent": "Čtení stála {cost}.",
|
|
163
|
+
"ui.o.views": "snímky",
|
|
164
|
+
"ui.settings.views": "Vyladit čtení snímků ({state})",
|
|
165
|
+
"ui.settings.views.default": "výchozí velikosti",
|
|
166
|
+
"ui.settings.views.done": "vyladěno {date}",
|
|
167
|
+
"ui.settings.views.other": "zatím vyladěno pro jiný model",
|
|
168
|
+
"ui.doc.views": "čtení snímků",
|
|
169
|
+
"ui.doc.views.default": "výchozí velikosti: hledání {find} px · čtení {read} px",
|
|
170
|
+
"ui.doc.views.done": "vyladěno {date}: hledání {find} px · čtení {read} px",
|
|
140
171
|
"ui.setup.level": "Co smí agent dělat bez ptaní?",
|
|
141
172
|
"ui.setup.level.ask": "Ptát se mě na všechno mimo výzkum",
|
|
142
173
|
"ui.setup.level.auto": "Pracovat samostatně – ptát se jen u riskantních kroků (doporučeno)",
|
|
@@ -662,6 +693,7 @@
|
|
|
662
693
|
"ui.help.cmd.pack": "Zabalit výzkum do jednoho souboru ZIP, aby v něm mohl pokračovat někdo jiný",
|
|
663
694
|
"ui.help.cmd.unpack": "Rozbalit rodokmen, který někdo poslal",
|
|
664
695
|
"ui.help.cmd.tidy": "Uvolnit místo, které si strom drží vedle výzkumu (nejdřív ukáže, pak se zeptá)",
|
|
696
|
+
"ui.help.cmd.media.calibrate": "Vyladit velikost snímků pro agenta a model výzkumu na jeho vlastních doložených záznamech (placená práce modelu; cena se řekne předem)",
|
|
665
697
|
"ui.help.cmd.check": "Zkontrolovat výzkum: vše v pořádku, nic změněné mimo strom",
|
|
666
698
|
"ui.help.cmd.config.get": "Přečíst nastavení",
|
|
667
699
|
"ui.help.cmd.config.set": "Změnit nastavení",
|
|
@@ -978,7 +1010,7 @@
|
|
|
978
1010
|
"ui.run.which.bad": "Čísla ze seznamu, 1 až {n}: např. 2 nebo 1,4 nebo 2-5.",
|
|
979
1011
|
"ui.run.limit": "Na jeden úkol má agent nejvýš {minutes} minut; pak ho strom zastaví a úkol vrátí do fronty (nastavení run.minutes).",
|
|
980
1012
|
"ui.run.empty": "Fronta je prázdná – co hledat, stačí agentovi říct v rozhovoru.",
|
|
981
|
-
"ui.run.browser": "· {name}: snímky přes prohlížeč –
|
|
1013
|
+
"ui.run.browser": "· {name}: snímky přes prohlížeč – nástroje prohlížeče pro {hosts} v sezeních, jejichž úkol je může potřebovat; musí běžet Chrome s rozšířením Claude",
|
|
982
1014
|
"ui.run.browser.model": " pozor: nástroje prohlížeče potřebují model, který své kroky zkontroluje – Sonnet nebo Opus, ne {model}: strom config set model.lead sonnet",
|
|
983
1015
|
"ui.run.full": "· oprávnění: plná – agent smí vše kromě toho, co oprávnění rodokmenu zakazují (zpět: strom config set agent.permissions auto)",
|
|
984
1016
|
"ui.menu.working.more": "Samostatně teď pracují agenti: {n}.",
|
|
@@ -994,6 +1026,11 @@
|
|
|
994
1026
|
"ui.run.gate.no": "ne",
|
|
995
1027
|
"ui.run.gate.noanswer": "neodpověděla, jak má (strom gate test)",
|
|
996
1028
|
"ui.run.stop.gate.declined": "nespuštěno — podmínka „{name}“: {reason}",
|
|
1029
|
+
"ui.run.gate.cap": "· {name}: nastavený strop – kontroluje se před každým sezením; žádné „přesto začít“ ho nepřekročí",
|
|
1030
|
+
"ui.run.stop.gate.cap": "strop podmínky „{name}“ – {reason} (pevná hranice z run.gate; „přesto začít“ ji nepřekročí)",
|
|
1031
|
+
"ui.run.cap.finish": "⏳ {session}: limit agenta na {used} % ({kind}) – sezení dostalo žádost zapsat, co našlo, a skončit; za stropem další sezení nezačne",
|
|
1032
|
+
"ui.run.limit.five_hour": "pětihodinové okno",
|
|
1033
|
+
"ui.run.limit.seven_day": "týden",
|
|
997
1034
|
"ui.run.loop": "Nechat ho pracovat, dokud je co dělat a dovolí to podmínka „{name}“",
|
|
998
1035
|
"ui.consent.gate.set": "Nechat podmínku „{name}“ rozhodovat, kdy agent pracující sám pokračuje?",
|
|
999
1036
|
"ui.consent.gate.unset": "Odebrat podmínku „{name}“ — agent pracující sám se jí už nebude ptát?",
|
|
@@ -1318,6 +1355,24 @@
|
|
|
1318
1355
|
"log.research.done": "Směr ukončen: {name}",
|
|
1319
1356
|
"log.mode.archive": "Výzkum je teď archiv",
|
|
1320
1357
|
"log.mode.research": "Výzkum je znovu zapnutý",
|
|
1358
|
+
"log.reading.loose": "Pročteno snímků: {n}",
|
|
1359
|
+
"log.clips": "Zápisy vyznačené na snímcích: {n} z {total}",
|
|
1360
|
+
"log.transcripts": "Zápisy přepsané z výřezů: {n} z {total}",
|
|
1361
|
+
"log.tree.create": "Výzkum založen: {name}",
|
|
1362
|
+
"log.repair": "Data vrácena do posledního zapečetěného stavu",
|
|
1363
|
+
"log.chat.saved": "Uloženo po rozhovoru s agentem",
|
|
1364
|
+
"log.migrate": "Data rodokmenu převedena pro novější strom",
|
|
1365
|
+
"log.setting": "Změněno nastavení výzkumu: {key}",
|
|
1366
|
+
"log.image": "{name}, obr. {image}",
|
|
1367
|
+
"log.media.edit": "Upravený snímek: {name}",
|
|
1368
|
+
"log.media.retract": "Odvolaný snímek: {name}",
|
|
1369
|
+
"log.input.edit": "Materiál doplněn: {name}",
|
|
1370
|
+
"log.input.skip": "Materiál odložen jako nepoužitelný: {name}",
|
|
1371
|
+
"log.input.sort": "Materiál roztříděn: {name}",
|
|
1372
|
+
"log.record.edit": "Upraveno: {name}",
|
|
1373
|
+
"ui.gate.timeout": "neodpověděla do {s} s",
|
|
1374
|
+
"ui.gate.signal": "ukončena signálem {signal}",
|
|
1375
|
+
"ui.gate.status": "skončila s kódem {status}",
|
|
1321
1376
|
"ui.waiting.title": "Agent potřebuje ({n}):",
|
|
1322
1377
|
"ui.waiting.do": "Co udělat: {what}",
|
|
1323
1378
|
"ui.waiting.ask": "agent to řekne v rozhovoru",
|
|
@@ -1478,6 +1533,13 @@
|
|
|
1478
1533
|
"ui.gate.asked": "před každým sezením strom run se ptá: {gate} (strom config unset run.gate: žádná)",
|
|
1479
1534
|
"ui.gate.unset": "žádná se neptá: strom config set run.gate <název> (jen uživatel)",
|
|
1480
1535
|
"ui.gate.folder": "složka: {folder} – složka podmínky nakopírovaná sem je nainstalovaná (rozhraní: README.md tamtéž)",
|
|
1536
|
+
"ui.gate.cap.week": "strop nastaven: ptá se před každým sezením každého běhu; sezení v práci je požádáno o dokončení při {pct} % týdne",
|
|
1537
|
+
"ui.gate.cap.window": "strop nastaven: ptá se před každým sezením každého běhu; sezení v práci je požádáno o dokončení při {pct} % pětihodinového okna",
|
|
1538
|
+
"ui.gate.test.go": "pokračovat",
|
|
1539
|
+
"ui.gate.test.wait": "počkat do {at}",
|
|
1540
|
+
"ui.gate.test.stop": "zastavit",
|
|
1541
|
+
"ui.gate.test.error": "chyba – běh by se zastavil",
|
|
1542
|
+
"ui.gate.test.hard": "(strop: pevné zastavení, žádné „přesto začít“)",
|
|
1481
1543
|
"ui.hook.none": "žádné hooky",
|
|
1482
1544
|
"ui.hook.on": "zapnuté: {hooks} (strom hook off <název>)",
|
|
1483
1545
|
"ui.hook.unset": "žádný není zapnutý: strom hook on <název> (jen uživatel)",
|
package/assets/lang/de.json
CHANGED
|
@@ -137,6 +137,37 @@
|
|
|
137
137
|
"ui.chat.app.model.chosen": "In {app} für die Forschung das Modell {model} wählen (das in den Einstellungen gewählte).",
|
|
138
138
|
"ui.settings.model": "Modell der Forschung ({agent}): {model}",
|
|
139
139
|
"ui.settings.model.own": "das eigene des Agenten",
|
|
140
|
+
"ui.views.title": "Abstimmung des Lesens der Scans · {agent}: {n} Bilder aus {books} Büchern, Größen {sizes} px",
|
|
141
|
+
"ui.views.find": "Finden eines Eintrags auf dem ganzen Bild:",
|
|
142
|
+
"ui.views.find.row": " {size} px an der Stelle {located} von {n} · auf einem Bild ohne ihn {wrong} von {neg} · {cost}",
|
|
143
|
+
"ui.views.read": "Lesen eines Eintrags aus einer Hälfte oder einer Seite:",
|
|
144
|
+
"ui.views.read.row": " {size} px gelesen {keys} von {total} · unsichere Stellen {unsure} · {cost}",
|
|
145
|
+
"ui.views.rule": "Eine kleinere Größe wird nur bei klarem Ergebnis gespeichert: jeder Eintrag an der Stelle gefunden wie bei der größten Größe und keiner mehr auf einem Bild ohne ihn; insgesamt mindestens so viel gelesen, kein Eintrag um mehr als eine Angabe weniger, nicht mehr unsichere Stellen.",
|
|
146
|
+
"ui.views.stored": "Gespeichert für {agent} ({date}): Suchen {find} px · Lesen {read} px — danach richten sich strom media view und strom read; zurück zu den Vorgaben: strom media calibrate --reset",
|
|
147
|
+
"ui.views.kept": "Kein klares Ergebnis: nichts gespeichert, die Größen bleiben, wie sie waren.",
|
|
148
|
+
"ui.views.unclear.find": "Suchen: kein klares Ergebnis — die Vorgabe bleibt ({size} px).",
|
|
149
|
+
"ui.views.unclear.read": "Lesen: kein klares Ergebnis — die Vorgabe bleibt ({size} px).",
|
|
150
|
+
"ui.views.failed": "Nicht beendete Lesungen: {failed} — nichts gespeichert, die Größen bleiben, wie sie waren.",
|
|
151
|
+
"ui.views.few": "Zu wenige Bilder mit bekannter Wahrheit, um das Lesen der Scans abzustimmen: {have} von {need} nötigen. Ein solches Bild ist der Scan eines Eintrags, den eine belegte Angabe zitiert, mit seinem Wortlaut (einer Abschrift), schon auf diesem Computer; {more} weitere entstehen durch die gewöhnliche Arbeit des Agenten — nach einigen Sitzungen erneut versuchen. Bis dahin gelten die vorgegebenen Größen.",
|
|
152
|
+
"ui.views.ask": "Das Lesen der Scans für {agent} abstimmen: {readers} bezahlte Lesungen von {n} Bildern dieser Forschung in {sizes} px, etwa {cost} (ein typischer Wert; die Preise des Agenten können abweichen). Starten?",
|
|
153
|
+
"ui.views.no": "Nichts gestartet; die Größen bleiben, wie sie waren.",
|
|
154
|
+
"ui.views.reset": "Die Abstimmung für {agent} ist vergessen: es gelten die vorgegebenen Größen (Suchen {find} px · Lesen {read} px).",
|
|
155
|
+
"ui.views.reset.none": "Für {agent} ist nichts abgestimmt: es gelten die vorgegebenen Größen (Suchen {find} px · Lesen {read} px).",
|
|
156
|
+
"ui.views.estimate": "{n} Bilder aus {books} Büchern, {readers} Lesungen in {sizes} px, etwa {cost} — startet ein Mensch: strom media calibrate",
|
|
157
|
+
"ui.views.offer": "das Lesen der Scans wurde für {before} abgestimmt, für {now} noch nicht: strom media calibrate (startet ein Mensch; bezahlte Arbeit des Modells)",
|
|
158
|
+
"ui.views.progress": "▶ {what} · {size} px · Bilder: {n}",
|
|
159
|
+
"ui.views.what.find": "Suchen",
|
|
160
|
+
"ui.views.what.read": "Lesen",
|
|
161
|
+
"ui.views.cost.unknown": "Kosten unbekannt",
|
|
162
|
+
"ui.views.spent": "Die Lesungen kosteten {cost}.",
|
|
163
|
+
"ui.o.views": "Scans",
|
|
164
|
+
"ui.settings.views": "Das Lesen der Scans abstimmen ({state})",
|
|
165
|
+
"ui.settings.views.default": "die vorgegebenen Größen",
|
|
166
|
+
"ui.settings.views.done": "abgestimmt {date}",
|
|
167
|
+
"ui.settings.views.other": "bisher für ein anderes Modell abgestimmt",
|
|
168
|
+
"ui.doc.views": "Lesen der Scans",
|
|
169
|
+
"ui.doc.views.default": "die vorgegebenen Größen: Suchen {find} px · Lesen {read} px",
|
|
170
|
+
"ui.doc.views.done": "abgestimmt {date}: Suchen {find} px · Lesen {read} px",
|
|
140
171
|
"ui.setup.level": "Was darf der Agent tun, ohne nachzufragen?",
|
|
141
172
|
"ui.setup.level.ask": "Mich bei allem außerhalb der Forschung fragen",
|
|
142
173
|
"ui.setup.level.auto": "Selbstständig arbeiten – nur bei riskanten Schritten fragen (empfohlen)",
|
|
@@ -662,6 +693,7 @@
|
|
|
662
693
|
"ui.help.cmd.pack": "Die Forschung in eine ZIP-Datei packen, damit jemand anderes weitermachen kann",
|
|
663
694
|
"ui.help.cmd.unpack": "Einen zugeschickten Stammbaum entpacken",
|
|
664
695
|
"ui.help.cmd.tidy": "Platz freigeben, den strom neben der Forschung belegt (erst gezeigt, nach Zustimmung)",
|
|
696
|
+
"ui.help.cmd.media.calibrate": "Die Größe der Scan-Ansichten für Agent und Modell der Forschung an ihren eigenen belegten Einträgen abstimmen (bezahlte Arbeit des Modells; die Kosten werden vorher genannt)",
|
|
665
697
|
"ui.help.cmd.check": "Die Forschung prüfen: alles in Ordnung, nichts an strom vorbei geändert",
|
|
666
698
|
"ui.help.cmd.config.get": "Eine Einstellung lesen",
|
|
667
699
|
"ui.help.cmd.config.set": "Eine Einstellung ändern",
|
|
@@ -978,7 +1010,7 @@
|
|
|
978
1010
|
"ui.run.which.bad": "Nummern aus der Liste, 1 bis {n}: z. B. 2 oder 1,4 oder 2-5.",
|
|
979
1011
|
"ui.run.limit": "Für eine Aufgabe hat der Agent höchstens {minutes} Minuten; dann hält strom ihn an und die Aufgabe kommt zurück in die Warteschlange (Einstellung run.minutes).",
|
|
980
1012
|
"ui.run.empty": "Die Warteschlange ist leer – dem Agenten im Gespräch sagen, was er suchen soll.",
|
|
981
|
-
"ui.run.browser": "· {name}: Bilder über den eigenen Browser –
|
|
1013
|
+
"ui.run.browser": "· {name}: Bilder über den eigenen Browser – Browser-Werkzeuge für {hosts} in den Sitzungen, deren Aufgabe sie brauchen kann; Chrome mit der Claude-Erweiterung muss laufen",
|
|
982
1014
|
"ui.run.browser.model": " Hinweis: Browser-Werkzeuge brauchen ein Modell, das seine Schritte prüft – Sonnet oder Opus, nicht {model}: strom config set model.lead sonnet",
|
|
983
1015
|
"ui.run.full": "· Berechtigungen: voll – der Agent darf alles außer dem, was die Berechtigungen des Stammbaums verbieten (zurück: strom config set agent.permissions auto)",
|
|
984
1016
|
"ui.menu.working.more": "Gerade arbeiten Agenten selbstständig: {n}.",
|
|
@@ -994,6 +1026,11 @@
|
|
|
994
1026
|
"ui.run.gate.no": "nein",
|
|
995
1027
|
"ui.run.gate.noanswer": "keine gültige Antwort (strom gate test)",
|
|
996
1028
|
"ui.run.stop.gate.declined": "nicht gestartet — die Bedingung „{name}“: {reason}",
|
|
1029
|
+
"ui.run.gate.cap": "· {name}: eine Obergrenze ist gesetzt – vor jeder Sitzung geprüft; kein „trotzdem starten“ geht darüber hinaus",
|
|
1030
|
+
"ui.run.stop.gate.cap": "die Obergrenze der Bedingung „{name}“ – {reason} (eine feste Grenze aus run.gate; kein „trotzdem starten“ geht darüber hinaus)",
|
|
1031
|
+
"ui.run.cap.finish": "⏳ {session}: das Limit des Agenten bei {used} % ({kind}) – die Sitzung ist gebeten aufzuschreiben, was gefunden wurde, und zu schließen; über der Obergrenze beginnt keine nächste Sitzung",
|
|
1032
|
+
"ui.run.limit.five_hour": "Fünf-Stunden-Fenster",
|
|
1033
|
+
"ui.run.limit.seven_day": "Woche",
|
|
997
1034
|
"ui.run.loop": "Weiterarbeiten lassen, solange es Arbeit gibt und die Bedingung „{name}“ es erlaubt",
|
|
998
1035
|
"ui.consent.gate.set": "Die Bedingung „{name}“ entscheiden lassen, wann der allein arbeitende Agent weitermacht?",
|
|
999
1036
|
"ui.consent.gate.unset": "Die Bedingung „{name}“ entfernen — der allein arbeitende Agent fragt sie nicht mehr?",
|
|
@@ -1318,6 +1355,24 @@
|
|
|
1318
1355
|
"log.research.done": "Richtung beendet: {name}",
|
|
1319
1356
|
"log.mode.archive": "Die Forschung ist jetzt ein Archiv",
|
|
1320
1357
|
"log.mode.research": "Die Forschung ist wieder eingeschaltet",
|
|
1358
|
+
"log.reading.loose": "Durchgelesene Bilder: {n}",
|
|
1359
|
+
"log.clips": "Einträge auf ihren Scans markiert: {n} von {total}",
|
|
1360
|
+
"log.transcripts": "Einträge aus ihren Ausschnitten abgeschrieben: {n} von {total}",
|
|
1361
|
+
"log.tree.create": "Forschung begonnen: {name}",
|
|
1362
|
+
"log.repair": "Die Daten auf den zuletzt versiegelten Stand zurückgesetzt",
|
|
1363
|
+
"log.chat.saved": "Nach einem Gespräch mit dem Agenten gespeichert",
|
|
1364
|
+
"log.migrate": "Die Daten des Stammbaums für ein neueres strom aktualisiert",
|
|
1365
|
+
"log.setting": "Einstellung der Forschung geändert: {key}",
|
|
1366
|
+
"log.image": "{name}, Bild {image}",
|
|
1367
|
+
"log.media.edit": "Bild geändert: {name}",
|
|
1368
|
+
"log.media.retract": "Bild zurückgezogen: {name}",
|
|
1369
|
+
"log.input.edit": "Material ergänzt: {name}",
|
|
1370
|
+
"log.input.skip": "Material als unbrauchbar beiseitegelegt: {name}",
|
|
1371
|
+
"log.input.sort": "Material sortiert: {name}",
|
|
1372
|
+
"log.record.edit": "Geändert: {name}",
|
|
1373
|
+
"ui.gate.timeout": "keine Antwort innerhalb von {s} s",
|
|
1374
|
+
"ui.gate.signal": "durch {signal} beendet",
|
|
1375
|
+
"ui.gate.status": "mit Exit-Status {status} beendet",
|
|
1321
1376
|
"ui.waiting.title": "Der Agent braucht eine Antwort ({n}):",
|
|
1322
1377
|
"ui.waiting.do": "Was zu tun ist: {what}",
|
|
1323
1378
|
"ui.waiting.ask": "der Agent sagt es im Gespräch",
|
|
@@ -1478,6 +1533,13 @@
|
|
|
1478
1533
|
"ui.gate.asked": "vor jeder Sitzung von strom run gefragt: {gate} (strom config unset run.gate: keine)",
|
|
1479
1534
|
"ui.gate.unset": "keine wird gefragt: strom config set run.gate <Name> (nur der Benutzer)",
|
|
1480
1535
|
"ui.gate.folder": "Ordner: {folder} – der hineinkopierte Ordner einer Bedingung ist installiert (die Schnittstelle: README.md dort)",
|
|
1536
|
+
"ui.gate.cap.week": "Obergrenze gesetzt: vor jeder Sitzung jedes Laufs gefragt; eine laufende Sitzung wird bei {pct} % der Woche um den Abschluss gebeten",
|
|
1537
|
+
"ui.gate.cap.window": "Obergrenze gesetzt: vor jeder Sitzung jedes Laufs gefragt; eine laufende Sitzung wird bei {pct} % des Fünf-Stunden-Fensters um den Abschluss gebeten",
|
|
1538
|
+
"ui.gate.test.go": "weiter",
|
|
1539
|
+
"ui.gate.test.wait": "warten bis {at}",
|
|
1540
|
+
"ui.gate.test.stop": "anhalten",
|
|
1541
|
+
"ui.gate.test.error": "Fehler – ein Lauf würde anhalten",
|
|
1542
|
+
"ui.gate.test.hard": "(Obergrenze: ein fester Halt, kein „trotzdem starten“)",
|
|
1481
1543
|
"ui.hook.none": "keine Hooks",
|
|
1482
1544
|
"ui.hook.on": "eingeschaltet: {hooks} (strom hook off <Name>)",
|
|
1483
1545
|
"ui.hook.unset": "keiner ist eingeschaltet: strom hook on <Name> (nur der Benutzer)",
|
package/assets/method/core.md
CHANGED
|
@@ -4,14 +4,14 @@ You work to the Genealogical Proof Standard: search thoroughly, cite every
|
|
|
4
4
|
fact, analyse and correlate the evidence, resolve conflicts, and write the
|
|
5
5
|
conclusion so the next researcher can follow it.
|
|
6
6
|
|
|
7
|
-
<!-- for link verify enrich intake locate narrate -->
|
|
7
|
+
<!-- for link verify enrich intake locate narrate links -->
|
|
8
8
|
- **Certainty is explicit.** `proven` — you read the original record yourself
|
|
9
9
|
and it states the fact directly. `probable` — good evidence, but indirect or a
|
|
10
10
|
single reading of hard handwriting. `possible` — weak evidence. `lead` — a
|
|
11
11
|
family story, a family tree, an index or a guess: something to check, never a
|
|
12
12
|
fact. Family trees and memories are leads, always.
|
|
13
13
|
<!-- end -->
|
|
14
|
-
<!-- for link verify enrich intake locate -->
|
|
14
|
+
<!-- for link verify enrich intake locate links -->
|
|
15
15
|
- **A namesake is not your person.** Identify by year, place, house, occupation,
|
|
16
16
|
spouse and parents — the mother's maiden name decides most cases. Two entries
|
|
17
17
|
that give one name different parents (another mother) are **two people** —
|
|
@@ -65,7 +65,7 @@ conclusion so the next researcher can follow it.
|
|
|
65
65
|
(`strom task list --off-tree`); they come back by themselves once the link
|
|
66
66
|
is recorded.
|
|
67
67
|
<!-- end -->
|
|
68
|
-
<!-- for link verify enrich intake -->
|
|
68
|
+
<!-- for link verify enrich intake links -->
|
|
69
69
|
- **Say what a hypothesis would connect.** A hypothesis about a connection —
|
|
70
70
|
whose child, the same person, a couple, siblings — gets each variant's links
|
|
71
71
|
when you record or argue it: `strom hypothesis link H… B --child P… --of F…`
|
|
@@ -80,6 +80,16 @@ conclusion so the next researcher can follow it.
|
|
|
80
80
|
links names the variant it is decided for:
|
|
81
81
|
`strom hypothesis decide H… --variant B --decision "…"`.
|
|
82
82
|
<!-- end -->
|
|
83
|
+
<!-- for links -->
|
|
84
|
+
Read each variant whole (`strom hypothesis show H…`) and the people it
|
|
85
|
+
names (`strom person show P…`, `strom family show F…`); link only what its
|
|
86
|
+
words say beyond doubt — a namesake stays out. A link its claim does not say
|
|
87
|
+
comes off with `strom hypothesis link H… B --remove`; a variant that
|
|
88
|
+
connects nothing clear keeps none, and one that says what the tree records
|
|
89
|
+
already (marked so) has no link to make — the hypothesis stays open until
|
|
90
|
+
the records decide it. You read no records here: what would
|
|
91
|
+
decide a hypothesis is a task (`strom task add … --about H…`), not a search now.
|
|
92
|
+
<!-- end -->
|
|
83
93
|
- **Stay within the task.** New questions become new tasks (`strom task add`,
|
|
84
94
|
with where and done-when), not detours.
|
|
85
95
|
<!-- for link verify enrich intake locate -->
|
package/assets/method/reading.md
CHANGED
|
@@ -7,9 +7,9 @@ search depends on** (a surname, a birthplace, a parish) is read again on a
|
|
|
7
7
|
crop at full resolution before it is recorded; what stays unsure is recorded
|
|
8
8
|
as unsure and said so.
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
Look at as few pixels as the question needs and write down what you saw at
|
|
11
|
+
once: after about 30 views write down what you found before you open more, and
|
|
12
|
+
never open again a view cleared from your context — your notes hold it.
|
|
13
13
|
|
|
14
14
|
- **Look only through views**: `strom media view B0001:57` (record set and
|
|
15
15
|
image number) makes a file in `.strom/views/` — open that file. Whole images
|
|
@@ -24,18 +24,19 @@ about 80 views write down what you found before you open more.
|
|
|
24
24
|
page, where they are sharper than one view of it), `--crop … --crop …`
|
|
25
25
|
(several entries of one image), `--split 2x2` (a page in overlapping parts),
|
|
26
26
|
`strom media view B0001 --page 112 113`. Each file comes with its image, page
|
|
27
|
-
and `--clip`. At most 12 images and 24 views in one call
|
|
27
|
+
and `--clip`. At most 12 images and 24 views in one call: with 4 views an
|
|
28
|
+
image (halves and crops), 6 images a call.
|
|
28
29
|
- **Find, then crop.** `--grid` overlays tenths with labels; read off where the
|
|
29
30
|
entry is and ask for exactly that part: `--crop 0.05,0.40,0.45,0.18` (x, y,
|
|
30
31
|
width, height as fractions) or `--half left|right` for one page of a spread.
|
|
31
32
|
A crop comes at full resolution (small ones enlarged). `--contrast` for faded
|
|
32
33
|
ink, `--rotate 90` for sideways pages.
|
|
33
34
|
<!-- for link verify enrich part -->
|
|
34
|
-
- **Too small to read?**
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
- **Too small to read?** A crop said enlarged: the scan has no more detail.
|
|
36
|
+
A connector that fetches a part sharper says so in that line: `strom fetch
|
|
37
|
+
<connector> --recordset B0001 --images 57 --crop …`; the same crop viewed
|
|
38
|
+
again comes from it. Whole images first, a part only where entries need
|
|
39
|
+
it: an archive's hourly cap stops the rest.
|
|
39
40
|
<!-- end -->
|
|
40
41
|
- **Browsing a book is a reader's job**: `strom read B0001 --images 40-69
|
|
41
42
|
--question "…"` — readers in batches of ten, each with the full question.
|
|
@@ -51,8 +52,8 @@ about 80 views write down what you found before you open more.
|
|
|
51
52
|
foreground and let it finish — your session ends with your turn, and
|
|
52
53
|
whatever is left running in the background ends with it.
|
|
53
54
|
(A scan-reader subagent where your agent has one, strom-scan-reader, or your
|
|
54
|
-
own subagents — on your own model, never a faster one — read too,
|
|
55
|
-
|
|
55
|
+
own subagents — on your own model, never a faster one — read too, about six scans
|
|
56
|
+
each with the whole question; what they report is lost with
|
|
56
57
|
your session unless you write it down: record each report as it comes back,
|
|
57
58
|
before you send the next readers.) Only the entries
|
|
58
59
|
that will be cited need your own eyes, at full resolution.
|
|
@@ -49,6 +49,17 @@ One line of JSON on stdout (the last line) may say more:
|
|
|
49
49
|
- `reason`: why, for the user (in their language: `STROM_LANG`).
|
|
50
50
|
- `wait` (seconds) or `until` (a time): when to ask again. Without them: in
|
|
51
51
|
15 minutes; never sooner than a minute.
|
|
52
|
+
- `hard` (`true`, with status 1 or 2): this answer is the user's own hard
|
|
53
|
+
limit — a cap set in `run.gate`. The run ends, saying the reason; no
|
|
54
|
+
"start anyway" goes past it.
|
|
55
|
+
- `watch` (`{"kind": "seven_day", "finish": 0.99}`): the gate holds a cap on
|
|
56
|
+
that window of the agent's plan (`five_hour` or `seven_day`). strom then asks
|
|
57
|
+
it before **every** session, also of the runs you started yourself (there
|
|
58
|
+
only its hard stop counts), and asks a session at work to finish — write
|
|
59
|
+
down what it found and close — once the agent says the window's use reached
|
|
60
|
+
`finish` (0–1). A gate that never says `watch` is asked as before.
|
|
61
|
+
|
|
62
|
+
Both are optional; an older strom ignores them.
|
|
52
63
|
|
|
53
64
|
Plain text instead of JSON is the reason.
|
|
54
65
|
|
|
@@ -66,9 +77,13 @@ Environment variables, besides the user's own:
|
|
|
66
77
|
| `STROM_SESSIONS` | sessions this run has had |
|
|
67
78
|
| `STROM_COST_USD` | what this run has cost so far (as the agent reported it) |
|
|
68
79
|
| `STROM_NEXT_TASK` | the task the next session would take |
|
|
80
|
+
| `STROM_AGENT_LIMITS` | what the agent said of its plan's limits in this run, when it said any (Claude Code): JSON `[{"kind": "five_hour" \| "seven_day", "used": 0.97, "resetsAt": "<ISO time>", "at": "<when it said it>"}]` — absent otherwise; an older gate ignores it |
|
|
69
81
|
|
|
70
82
|
A session already at work is never stopped by a gate: it is asked between
|
|
71
|
-
sessions only (a session's own time limit is `run.minutes`).
|
|
83
|
+
sessions only (a session's own time limit is `run.minutes`). Under a cap
|
|
84
|
+
(`watch`) the session is asked to finish, as `strom session finish` does: its
|
|
85
|
+
agent hears it from its next strom command and starts no new reader; work it
|
|
86
|
+
delegated inside itself (a subagent) strom cannot stop half-way.
|
|
72
87
|
|
|
73
88
|
The gate holds the runs that go on by themselves: `strom run --loop` and
|
|
74
89
|
`--until`. Tasks you start yourself (one, `--max 3`, `--task T0007`, "work
|
|
@@ -91,5 +106,17 @@ Not enough in hand: it waits until the week has caught up (past the reset: the
|
|
|
91
106
|
new week's share). A used-up session: until it resets. Another agent than
|
|
92
107
|
Claude Code: it lets the work go on.
|
|
93
108
|
|
|
109
|
+
**A cap** — your own hard stop for the week:
|
|
110
|
+
|
|
111
|
+
strom config set run.gate "claude-usage 10 --cap 95"
|
|
112
|
+
|
|
113
|
+
At 95 % of the week used no session starts: in every run, `--max` and
|
|
114
|
+
`--task` and the menu's too, asked before each session, and no "start anyway"
|
|
115
|
+
goes past it — the run ends saying the use and when the week resets. A session
|
|
116
|
+
at work is asked to finish when Claude Code says the week is at 99 %. What
|
|
117
|
+
Claude Code said in the run (`STROM_AGENT_LIMITS`, at most 15 minutes old) is
|
|
118
|
+
read instead of asking `claude -p /usage`. `--cap` alone: the cap without the
|
|
119
|
+
pace (`claude-usage --cap 95`).
|
|
120
|
+
|
|
94
121
|
A gate is a program on this computer, put here by you (or by strom); the
|
|
95
122
|
`.gitignore` of the plugins folder keeps it out of any repository.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"interface": 1,
|
|
3
3
|
"title": "Claude usage",
|
|
4
|
-
"description": "Keeps working alone to the daily ration of your Claude subscription: a session starts only while the week's usage is at least n points behind the share of the week gone (a day ≈ 14.3): strom config set run.gate \"claude-usage 10\" (without a number: 0).",
|
|
4
|
+
"description": "Keeps working alone to the daily ration of your Claude subscription: a session starts only while the week's usage is at least n points behind the share of the week gone (a day ≈ 14.3): strom config set run.gate \"claude-usage 10\" (without a number: 0). A cap: \"claude-usage 10 --cap 95\" — at 95 % of the week no session starts, in any run, and no \"start anyway\" goes past it.",
|
|
5
5
|
"command": [
|
|
6
6
|
"node",
|
|
7
7
|
"gate.ts"
|
|
@@ -11,11 +11,22 @@
|
|
|
11
11
|
// Without a number: 0 — no faster than the week goes. Else it waits until the
|
|
12
12
|
// week has caught up (or past the reset); a full session: until it resets.
|
|
13
13
|
//
|
|
14
|
+
// A cap (strom config set run.gate "claude-usage 15 --cap 95"): at 95 % of the
|
|
15
|
+
// week used no session starts — the user's own hard stop, asked before every
|
|
16
|
+
// session of every run, and no "start anyway" goes past it; a session at work
|
|
17
|
+
// is asked to finish when the week reaches 99 %. What the agent said of its
|
|
18
|
+
// limits in this run (STROM_AGENT_LIMITS, at most 15 minutes old) is read
|
|
19
|
+
// instead of asking `claude -p /usage`.
|
|
20
|
+
//
|
|
14
21
|
// strom writes this file; a copy of your own goes into a folder of its own name.
|
|
15
22
|
|
|
16
23
|
import { spawnSync } from "node:child_process";
|
|
17
24
|
|
|
18
25
|
const DAY = 86_400_000;
|
|
26
|
+
/** What the agent said of its limits counts for this long; older: `claude -p /usage` is asked. */
|
|
27
|
+
const FRESH_MS = 15 * 60_000;
|
|
28
|
+
/** Under a cap, a session at work is asked to finish at this much of the week. */
|
|
29
|
+
const FINISH_AT = 0.99;
|
|
19
30
|
const WEEK = 7 * DAY;
|
|
20
31
|
const lang = (process.env.STROM_LANG ?? "en").slice(0, 2);
|
|
21
32
|
|
|
@@ -27,7 +38,11 @@ const T: Record<string, Record<string, string>> = {
|
|
|
27
38
|
session: "the session is used up — until it resets",
|
|
28
39
|
week: "week {used} % used, {gone} % gone, {behind} in hand (at least {min} needed) — until the week catches up",
|
|
29
40
|
bad: "the number must be 0 to 99, not \"{arg}\"",
|
|
41
|
+
badcap: "the cap must be 1 to 100 (\"--cap 95\"), not \"{arg}\"",
|
|
42
|
+
cap: "week {used} % used — the cap of {cap} % reached; it resets {resets}",
|
|
30
43
|
unread: "cannot read `claude -p /usage`: {detail}",
|
|
44
|
+
noweek: "no line \"Current week … resets …\"",
|
|
45
|
+
exit: "it ended with exit status {status}",
|
|
31
46
|
},
|
|
32
47
|
cs: {
|
|
33
48
|
other: "agent není Claude Code — není co hlídat",
|
|
@@ -36,7 +51,11 @@ const T: Record<string, Record<string, string>> = {
|
|
|
36
51
|
session: "sezení je vyčerpané — do jeho obnovení",
|
|
37
52
|
week: "týden: využito {used} %, uplynulo {gone} %, náskok {behind} (potřeba aspoň {min}) — dokud čas nedožene",
|
|
38
53
|
bad: "číslo musí být 0 až 99, ne \"{arg}\"",
|
|
54
|
+
badcap: "strop musí být 1 až 100 (\"--cap 95\"), ne \"{arg}\"",
|
|
55
|
+
cap: "týden: využito {used} % – strop {cap} % dosažen; obnoví se {resets}",
|
|
39
56
|
unread: "nelze přečíst `claude -p /usage`: {detail}",
|
|
57
|
+
noweek: "chybí řádek „Current week … resets …“",
|
|
58
|
+
exit: "skončilo s kódem {status}",
|
|
40
59
|
},
|
|
41
60
|
de: {
|
|
42
61
|
other: "der Agent ist nicht Claude Code — nichts zu prüfen",
|
|
@@ -45,50 +64,82 @@ const T: Record<string, Record<string, string>> = {
|
|
|
45
64
|
session: "die Sitzung ist aufgebraucht — bis sie zurückgesetzt wird",
|
|
46
65
|
week: "Woche: {used} % genutzt, {gone} % vergangen, Vorsprung {behind} (mindestens {min} nötig) — bis die Zeit aufholt",
|
|
47
66
|
bad: "die Zahl muss 0 bis 99 sein, nicht \"{arg}\"",
|
|
67
|
+
badcap: "die Obergrenze muss 1 bis 100 sein (\"--cap 95\"), nicht \"{arg}\"",
|
|
68
|
+
cap: "Woche: {used} % genutzt – Obergrenze {cap} % erreicht; zurückgesetzt {resets}",
|
|
48
69
|
unread: "`claude -p /usage` nicht lesbar: {detail}",
|
|
70
|
+
noweek: "keine Zeile „Current week … resets …“",
|
|
71
|
+
exit: "mit Exit-Status {status} beendet",
|
|
49
72
|
},
|
|
50
73
|
};
|
|
51
74
|
function say(key: string, v: Record<string, string | number> = {}): string {
|
|
52
75
|
const s = (T[lang] ?? T.en!)[key] ?? T.en![key]!;
|
|
53
76
|
return s.replace(/\{(\w+)\}/g, (_, k: string) => String(v[k] ?? ""));
|
|
54
77
|
}
|
|
55
|
-
function answer(code: 0 | 1 | 2, reason: string, until?: Date): never {
|
|
56
|
-
|
|
78
|
+
function answer(code: 0 | 1 | 2, reason: string, until?: Date, hard?: boolean): never {
|
|
79
|
+
// under a cap: strom asks before every session and asks a session at work to finish near the week's end
|
|
80
|
+
const watch = cap !== undefined ? { kind: "seven_day", finish: FINISH_AT } : undefined;
|
|
81
|
+
console.log(JSON.stringify({ reason, ...(until ? { until: until.toISOString() } : {}), ...(hard ? { hard: true } : {}), ...(watch ? { watch } : {}) }));
|
|
57
82
|
process.exit(code);
|
|
58
83
|
}
|
|
59
84
|
|
|
60
|
-
// ── your number: how many points usage must be behind the week gone
|
|
61
|
-
const
|
|
85
|
+
// ── your number: how many points usage must be behind the week gone; --cap: the week's hard stop ─
|
|
86
|
+
const argv = process.argv.slice(2);
|
|
87
|
+
let cap: number | undefined;
|
|
88
|
+
let arg = "0";
|
|
89
|
+
for (let i = 0; i < argv.length; i++) {
|
|
90
|
+
const a = argv[i]!;
|
|
91
|
+
if (a === "--cap" || a.startsWith("--cap=")) {
|
|
92
|
+
const v = a === "--cap" ? (argv[++i] ?? "") : a.slice(6);
|
|
93
|
+
if (!/^\d{1,3}$/.test(v) || Number(v) < 1 || Number(v) > 100) answer(2, say("badcap", { arg: v }));
|
|
94
|
+
cap = Number(v);
|
|
95
|
+
} else arg = a;
|
|
96
|
+
}
|
|
62
97
|
const min = Number(arg);
|
|
63
98
|
if (!/^\d{1,2}$/.test(arg)) answer(2, say("bad", { arg }));
|
|
64
99
|
|
|
65
|
-
if ((process.env.STROM_AGENT ?? "claude") !== "claude")
|
|
100
|
+
if ((process.env.STROM_AGENT ?? "claude") !== "claude") {
|
|
101
|
+
cap = undefined; // another agent: no limits of Claude's to hold
|
|
102
|
+
answer(0, say("other"));
|
|
103
|
+
}
|
|
66
104
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
const text = r.stdout;
|
|
71
|
-
if (/API key/i.test(text) && !/Current week/i.test(text)) answer(0, say("api"));
|
|
105
|
+
type Use = { used: number; resets?: Date };
|
|
106
|
+
let session: Use | undefined;
|
|
107
|
+
let week: Use | undefined;
|
|
72
108
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
if (
|
|
81
|
-
|
|
82
|
-
|
|
109
|
+
// ── what the agent said in this run, when it is fresh ───────────────────────
|
|
110
|
+
const said = fromAgent(process.env.STROM_AGENT_LIMITS);
|
|
111
|
+
if (said) ({ session, week } = said);
|
|
112
|
+
else {
|
|
113
|
+
// ── what Claude Code says ─────────────────────────────────────────────────
|
|
114
|
+
const r = spawnSync("claude", ["-p", "/usage"], { encoding: "utf8", timeout: 90_000, shell: process.platform === "win32", windowsHide: true });
|
|
115
|
+
// what Claude Code or the system said is said as it is; the gate's own words in the research language (STROM_LANG)
|
|
116
|
+
if (r.error || r.status !== 0) answer(2, say("unread", { detail: r.error?.message ?? ((r.stderr || r.stdout || "").trim().split("\n")[0] || say("exit", { status: String(r.status) })) }));
|
|
117
|
+
const text = r.stdout;
|
|
118
|
+
if (/API key/i.test(text) && !/Current week/i.test(text)) {
|
|
119
|
+
cap = undefined;
|
|
120
|
+
answer(0, say("api"));
|
|
121
|
+
}
|
|
122
|
+
const LINE = /^Current (session|week)(?: \(([^)]+)\))?:\s*(\d+)%\s*used(?:\s*·\s*resets\s*(.+))?$/i;
|
|
123
|
+
for (const raw of text.split(/\r?\n/)) {
|
|
124
|
+
const m = LINE.exec(raw.trim());
|
|
125
|
+
if (!m) continue;
|
|
126
|
+
const item = { used: Number(m[3]), ...(m[4] ? { resets: resetAt(m[4]) } : {}) };
|
|
127
|
+
if (m[1]!.toLowerCase() === "session") session = item;
|
|
128
|
+
// the limit of all models is the one that stops the work; a model's own week only if there is no other
|
|
129
|
+
else if (!week || /all models/i.test(m[2] ?? "")) week = item;
|
|
130
|
+
}
|
|
83
131
|
}
|
|
84
|
-
if (!week?.resets) answer(2, say("unread", { detail: "
|
|
132
|
+
if (!week?.resets) answer(2, say("unread", { detail: say("noweek") }));
|
|
133
|
+
// the cap first: the user's own hard stop, whatever the pace
|
|
134
|
+
if (cap !== undefined && week.used >= cap)
|
|
135
|
+
answer(2, say("cap", { used: Math.floor(week.used), cap, resets: week.resets.toLocaleString(lang, { weekday: "short", day: "numeric", month: "numeric", hour: "2-digit", minute: "2-digit" }) }), undefined, true);
|
|
85
136
|
|
|
86
137
|
const now = Date.now();
|
|
87
138
|
const start = week.resets.getTime() - WEEK;
|
|
88
139
|
const gone = Math.max(0, Math.min(100, ((now - start) / WEEK) * 100));
|
|
89
140
|
const behind = gone - week.used;
|
|
90
141
|
// shown rounded down: never "15 in hand (at least 15 needed)" for 14.6 — and gone − used stays what it says
|
|
91
|
-
const v = { used: week.used, gone: Math.floor(gone), behind: Math.floor(behind), min };
|
|
142
|
+
const v = { used: Math.floor(week.used), gone: Math.floor(gone), behind: Math.floor(behind), min };
|
|
92
143
|
if (session && session.used >= 100) answer(1, say("session"), session.resets ? new Date(session.resets.getTime() + 60_000) : undefined);
|
|
93
144
|
if (behind < min) {
|
|
94
145
|
// when the week gone reaches usage + the number; past the reset, the new week's number
|
|
@@ -98,6 +149,33 @@ if (behind < min) {
|
|
|
98
149
|
}
|
|
99
150
|
answer(0, say("go", v));
|
|
100
151
|
|
|
152
|
+
/**
|
|
153
|
+
* The limits Claude Code said in this run (strom passes them: [{kind, used 0–1, resetsAt, at}]), when the week's is
|
|
154
|
+
* at most FRESH_MS old and not past its reset; else nothing — `claude -p /usage` is asked.
|
|
155
|
+
*/
|
|
156
|
+
function fromAgent(json: string | undefined): { session?: Use; week: Use } | undefined {
|
|
157
|
+
if (!json) return undefined;
|
|
158
|
+
let list: unknown;
|
|
159
|
+
try {
|
|
160
|
+
list = JSON.parse(json);
|
|
161
|
+
} catch {
|
|
162
|
+
return undefined;
|
|
163
|
+
}
|
|
164
|
+
if (!Array.isArray(list)) return undefined;
|
|
165
|
+
const of = (kind: string): Use | undefined => {
|
|
166
|
+
const l = list.find((x) => x && typeof x === "object" && (x as { kind?: unknown }).kind === kind) as { used?: unknown; resetsAt?: unknown; at?: unknown } | undefined;
|
|
167
|
+
if (!l || typeof l.used !== "number" || !Number.isFinite(l.used) || typeof l.at !== "string") return undefined;
|
|
168
|
+
const at = Date.parse(l.at);
|
|
169
|
+
const resets = typeof l.resetsAt === "string" ? new Date(l.resetsAt) : undefined;
|
|
170
|
+
if (Number.isNaN(at) || Date.now() - at > FRESH_MS || !resets || Number.isNaN(resets.getTime()) || resets.getTime() <= Date.now()) return undefined;
|
|
171
|
+
return { used: l.used * 100, resets };
|
|
172
|
+
};
|
|
173
|
+
const week = of("seven_day");
|
|
174
|
+
if (!week) return undefined;
|
|
175
|
+
const session = of("five_hour");
|
|
176
|
+
return { week, ...(session ? { session } : {}) };
|
|
177
|
+
}
|
|
178
|
+
|
|
101
179
|
/** "Sep 30 at 2pm (Europe/Prague)", "Oct 2 at 11:30am (UTC)" → the moment. */
|
|
102
180
|
function resetAt(s: string): Date | undefined {
|
|
103
181
|
const m = /^(\w{3})\w*\s+(\d{1,2})\s+at\s+(\d{1,2})(?::(\d{2}))?\s*(am|pm)\s*\(([^)]+)\)/i.exec(s.trim());
|
package/dist/agents/files.js
CHANGED
|
@@ -74,9 +74,11 @@ they ask.
|
|
|
74
74
|
- the agent working on its own: they start it from strom's menu ("Let the
|
|
75
75
|
agent work on its own"); it works the task queue and tells them the result;
|
|
76
76
|
with many tasks in the queue, suggest it — every task gets a fresh session;
|
|
77
|
-
- one task, one fresh context: after a session closes
|
|
78
|
-
user clears your context (Claude Code: /clear)
|
|
79
|
-
keeps it all; suggest it in a sentence, go on
|
|
77
|
+
- one task, one fresh context — in a conversation: after a session closes
|
|
78
|
+
there, strom says how the user clears your context (Claude Code: /clear)
|
|
79
|
+
— nothing is lost, strom keeps it all; suggest it in a sentence, go on
|
|
80
|
+
here if they prefer. Working alone (strom run) each task starts fresh by
|
|
81
|
+
itself and nobody reads a closing message: no such advice there;
|
|
80
82
|
- what only they can do: when strom needs their consent it opens a window
|
|
81
83
|
on their screen — tell them to answer it, you cannot; images a portal gives
|
|
82
84
|
only by hand — strom says which ones and where to save them.
|
package/dist/agents/profiles.js
CHANGED
|
@@ -12,11 +12,14 @@
|
|
|
12
12
|
export const TIERS = ["lead", "vision", "text", "cheap"];
|
|
13
13
|
const DELEGATION_RULES = `- Browsing a book, an index or a range of images ("is our surname on this page?")
|
|
14
14
|
is delegated; so is anything self-contained that returns little.
|
|
15
|
-
- About
|
|
16
|
-
|
|
17
|
-
about
|
|
18
|
-
|
|
15
|
+
- About six scans (images B…:n) per delegate, four views each (halves and
|
|
16
|
+
crops); tell it to write down what each call gave before the next, to stop
|
|
17
|
+
at about 30 views and return what it has, and never to open again a view
|
|
18
|
+
cleared from its context (its notes hold it). It asks for the
|
|
19
|
+
views of a scan (or of a few) in one call —
|
|
19
20
|
\`strom media view B0001:57-60 --half both\` — and opens them together.
|
|
21
|
+
- Fetch the images before you delegate: a delegate never fetches, nor waits
|
|
22
|
+
for an archive — it reports the images missing or too small, and you fetch them.
|
|
20
23
|
- Every delegate gets the full question (what counts as a find, which years,
|
|
21
24
|
which names) and returns for each image: image and page, find or nothing,
|
|
22
25
|
what was illegible, the hand, and certainty per name — written as it goes.
|
|
@@ -28,11 +31,12 @@ export const SELF_READING = `## Reading scans (Codex, Antigravity, OpenCode, Gro
|
|
|
28
31
|
|
|
29
32
|
Read the images yourself, with your strongest model — never hand old
|
|
30
33
|
handwriting to a faster or cheaper model, subagent or pass. Read them
|
|
31
|
-
in batches of
|
|
32
|
-
\`strom media view B0001:57-
|
|
34
|
+
in batches of about six: open a batch (one call gives its views —
|
|
35
|
+
\`strom media view B0001:57-62 --half both\` — open them together), write
|
|
33
36
|
down what it gave (strom search add … for what was not found, facts for what
|
|
34
|
-
was), then open the next.
|
|
35
|
-
|
|
37
|
+
was), then open the next. After about 30 views, write down what you found
|
|
38
|
+
and go on; a view cleared from your context is not opened again — your
|
|
39
|
+
notes hold it. A name or place the next search depends on:
|
|
36
40
|
read it again on a crop at full resolution (\`strom media view … --crop\`)
|
|
37
41
|
before you record it.
|
|
38
42
|
OpenCode: this tree's subagent strom-scan-reader (strom and the file reader
|