strom-research 1.17.0-beta.5 → 1.17.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.
- package/CHANGELOG.cs.md +6 -2
- package/CHANGELOG.de.md +7 -2
- package/CHANGELOG.md +7 -2
- package/assets/lang/cs.json +6 -2
- package/assets/lang/de.json +4 -0
- package/dist/cli/ui.js +4 -0
- package/dist/commands/output.js +7 -3
- package/dist/commands/session.js +3 -3
- package/dist/commands/start.js +8 -6
- package/dist/core/live.js +35 -10
- package/dist/core/tree.js +1 -1
- package/package.json +1 -4
package/CHANGELOG.cs.md
CHANGED
|
@@ -7,10 +7,14 @@ Změny každé verze ve zkratce. Úplné poznámky a instalační řádky jsou n
|
|
|
7
7
|
|
|
8
8
|
## 1.17.0
|
|
9
9
|
|
|
10
|
-
*
|
|
10
|
+
*19. 10. 2026 · patří k aplikaci Strom 3.13.1.*
|
|
11
11
|
|
|
12
12
|
- **Nejdřív, co by hypotézy spojovaly.** Úkoly doplnit, co by spojovaly verze otevřené hypotézy, jdou ve frontě
|
|
13
13
|
první — i ve stávajícím výzkumu po aktualizaci —, takže aplikace Strom brzy ukáže tyto vazby.
|
|
14
|
+
- **Most aplikace Strom běží, dokud pracuje agent.** Most už neskončí po dvou hodinách klidu, dokud ve stromu
|
|
15
|
+
pracuje agent (i pozastavený běh), takže aplikace Strom vidí výzkum v práci i u stromu, který právě nesleduje.
|
|
16
|
+
Most ukončený pro klid se vrátí na svou adresu, když práce znovu začne; most zastavený `strom live stop` zůstane
|
|
17
|
+
zastavený.
|
|
14
18
|
- **Přerušené stahování se ohlásí a uklidí.** Stahování, jehož proces skončil uprostřed, se ohlásí jako přerušené,
|
|
15
19
|
s tím, co se uložilo a co chybí; jeho pracovní složka se uklidí.
|
|
16
20
|
- **Nový materiál v jazyce výzkumu.** Co přišlo (zaregistrovaný materiál, co přibylo, pravděpodobné duplicity,
|
|
@@ -19,7 +23,7 @@ Změny každé verze ve zkratce. Úplné poznámky a instalační řádky jsou n
|
|
|
19
23
|
1 task, 2 tasks, německy 1 Änderung, 2 Änderungen — místo „úkol(ů)“.
|
|
20
24
|
- **Víc v jazyce výzkumu.** Osoby bez vlastního záznamu (`strom person list --unproven`, kam odkazuje
|
|
21
25
|
`strom check`), co zapsal `strom export gedcom`, a varování počítadla ve `strom check` jsou v jazyce výzkumu,
|
|
22
|
-
i s počty.
|
|
26
|
+
i s počty – velikost a kvalita obrázků tak, jak je píše jazyk výzkumu (0,4 MB · kvalita běžná).
|
|
23
27
|
- **Ukládání na Windows počká na antivir.** Soubor, který antivir nebo indexování vyhledávání na chvíli drží, se po
|
|
24
28
|
krátkém čekání uloží – nebo přečte –, místo aby zápis selhal. Soubor držený déle zastaví příkaz celý, nic z něj
|
|
25
29
|
nezůstane uložené napůl a hláška říká, že soubor drží jiný program a příkaz jde prostě spustit znovu.
|
package/CHANGELOG.de.md
CHANGED
|
@@ -7,11 +7,15 @@ Die Änderungen jeder Version in Kürze. Die vollständigen Hinweise und die Ins
|
|
|
7
7
|
|
|
8
8
|
## 1.17.0
|
|
9
9
|
|
|
10
|
-
*
|
|
10
|
+
*19.10.2026 · gehört zur Strom-App 3.13.1.*
|
|
11
11
|
|
|
12
12
|
- **Zuerst, was Hypothesen verbinden würden.** Die Aufgaben, zu ergänzen, was die Varianten einer offenen Hypothese
|
|
13
13
|
verbinden würden, kommen in der Warteschlange zuerst — auch in einer bestehenden Forschung nach dem Update —, so
|
|
14
14
|
zeigt die Strom-App diese Verbindungen bald.
|
|
15
|
+
- **Die Brücke der Strom-App läuft, solange ein Agent arbeitet.** Die Brücke endet nicht mehr nach zwei ruhigen
|
|
16
|
+
Stunden, solange ein Agent im Stammbaum arbeitet (auch ein pausierter Lauf), so sieht die Strom-App die Forschung
|
|
17
|
+
bei der Arbeit auch in einem Stammbaum, dem sie gerade nicht folgt. Eine wegen Ruhe beendete Brücke kommt an ihrer
|
|
18
|
+
Adresse zurück, sobald die Arbeit wieder beginnt; eine mit `strom live stop` angehaltene bleibt angehalten.
|
|
15
19
|
- **Ein unterbrochener Download wird gemeldet und aufgeräumt.** Ein Download, dessen Prozess mittendrin endete, wird
|
|
16
20
|
als unterbrochen gemeldet, mit dem, was gespeichert ist und was fehlt; sein Arbeitsordner wird entfernt.
|
|
17
21
|
- **Neues Material in der Sprache der Forschung.** Was hereinkam (registriertes Material, was hinzukam, wahrscheinliche
|
|
@@ -20,7 +24,8 @@ Die Änderungen jeder Version in Kürze. Die vollständigen Hinweise und die Ins
|
|
|
20
24
|
englisch 1 task, 2 tasks, tschechisch 1 úkol, 2 úkoly, 5 úkolů — statt „Änderung(en)“.
|
|
21
25
|
- **Mehr in der Sprache der Forschung.** Die Personen ohne eigenen Eintrag (`strom person list --unproven`, worauf
|
|
22
26
|
`strom check` verweist), was `strom export gedcom` geschrieben hat, und eine Zählerwarnung von `strom check` stehen
|
|
23
|
-
in der Sprache der Forschung, samt ihren Zahlen
|
|
27
|
+
in der Sprache der Forschung, samt ihren Zahlen – Größe und Qualität der Bilder so, wie die
|
|
28
|
+
Sprache sie schreibt (0,4 MB · Qualität normal).
|
|
24
29
|
- **Speichern unter Windows wartet auf den Virenschutz.** Eine Datei, die ein Virenschutz oder die Suchindizierung
|
|
25
30
|
kurz festhält, wird nach kurzem Warten gespeichert – oder gelesen –, statt dass das Schreiben scheitert. Eine länger
|
|
26
31
|
festgehaltene Datei hält den Befehl als Ganzes an, nichts davon bleibt halb gespeichert, und die Meldung sagt, dass
|
package/CHANGELOG.md
CHANGED
|
@@ -7,11 +7,15 @@ The changes of each version in short. The full notes and the install lines are o
|
|
|
7
7
|
|
|
8
8
|
## 1.17.0
|
|
9
9
|
|
|
10
|
-
*
|
|
10
|
+
*2026-10-19 · goes with the Strom app 3.13.1.*
|
|
11
11
|
|
|
12
12
|
- **What hypotheses would connect, first.** The tasks to fill in what the variants of an open hypothesis would
|
|
13
13
|
connect go first in the queue — also in an existing research after the update — so the Strom app can show those
|
|
14
14
|
links soon.
|
|
15
|
+
- **The Strom app's bridge runs while an agent works.** The bridge no longer ends after two quiet hours while an
|
|
16
|
+
agent works in the tree (a paused run too), so the Strom app sees the research at work even in a tree it does not
|
|
17
|
+
follow. A bridge that ended for quiet comes back at its address when work starts again; one stopped with
|
|
18
|
+
`strom live stop` stays stopped.
|
|
15
19
|
- **An interrupted download is said and tidied.** A download whose process ended midway is reported as interrupted,
|
|
16
20
|
with what was saved and what is missing; its work folder is cleared away.
|
|
17
21
|
- **New material reported in the research's language.** What came in (registered material, what was added, likely
|
|
@@ -20,7 +24,8 @@ The changes of each version in short. The full notes and the install lines are o
|
|
|
20
24
|
Czech 1 úkol, 2 úkoly, 5 úkolů, in German 1 Änderung, 2 Änderungen — instead of "task(s)".
|
|
21
25
|
- **More in the research's language.** The people without a record of their own (`strom person list --unproven`,
|
|
22
26
|
where `strom check` points), what `strom export gedcom` wrote and a counter warning of `strom check` are said in
|
|
23
|
-
the research's language, their counts too
|
|
27
|
+
the research's language, their counts too — the size and quality of the images as the language writes them (in
|
|
28
|
+
Czech 0,4 MB · kvalita běžná).
|
|
24
29
|
- **Saving on Windows waits for an antivirus.** A file written while an antivirus or the search indexer briefly holds
|
|
25
30
|
it is saved — or read — after a short wait instead of failing. A file held longer stops the command as a whole,
|
|
26
31
|
with nothing of it half saved, and the message says another program holds the file and the command can simply run
|
package/assets/lang/cs.json
CHANGED
|
@@ -778,7 +778,7 @@
|
|
|
778
778
|
"ui.app.nolive": "Průběžné sledování výzkumu potřebuje Chrome nebo Edge – Safari webové stránce nedovolí přístup k tomuto počítači.",
|
|
779
779
|
"ui.app.images": "S obrázky: {n, plural, one {# zápis vyříznutý} few {# zápisy vyříznuté} other {# zápisů vyříznutých}} ze skenů ({mb} MB).",
|
|
780
780
|
"ui.app.images.unclipped": "{n, plural, one {Další # pramen je na snímcích, ale u něj} few {Další # prameny jsou na snímcích, ale u nich} other {Dalších # pramenů je na snímcích, ale u nich}} zatím nikdo nevyznačil, kde zápis je — agent to umí doplnit.",
|
|
781
|
-
"ui.app.images.smaller": "Aby se obrázky vešly do limitu {limit} MB, jsou menší, než je nastaveno: {level}
|
|
781
|
+
"ui.app.images.smaller": "Aby se obrázky vešly do limitu {limit} MB, jsou menší, než je nastaveno: kvalita {level}, nastavena {asked}.",
|
|
782
782
|
"ui.app.images.left": "{n, plural, one {# zápis nejdál od výzkumu je} few {# zápisy nejdál od výzkumu jsou} other {# zápisů nejdál od výzkumu je}} bez obrázku, aby se vše vešlo do limitu {limit} MB.",
|
|
783
783
|
"ui.app.images.scope": "{n, plural, one {# zápis lidí vzdálenějších od výzkumu je} few {# zápisy lidí vzdálenějších od výzkumu jsou} other {# zápisů lidí vzdálenějších od výzkumu je}} bez obrázku (nastavení excerpts.for: {for}).",
|
|
784
784
|
"ui.doc.installed": "strom {version} na vlastním Node {node} (oficiálním, z nodejs.org)",
|
|
@@ -1305,7 +1305,11 @@
|
|
|
1305
1305
|
"ui.export.valid.warnings": " platný GEDCOM 5.5.1 ({n} varování)",
|
|
1306
1306
|
"ui.export.committed": "zapsáno do historie",
|
|
1307
1307
|
"ui.export.images": " {excerpts, plural, one {# výřez} few {# výřezy} other {# výřezů}} z {sources, plural, one {# pramene} other {# pramenů}}, {size} · kvalita {level}",
|
|
1308
|
-
"ui.export.
|
|
1308
|
+
"ui.export.quality.small": "nízká",
|
|
1309
|
+
"ui.export.quality.normal": "běžná",
|
|
1310
|
+
"ui.export.quality.sharp": "vysoká",
|
|
1311
|
+
"ui.export.quality.smaller": "nejnižší",
|
|
1312
|
+
"ui.export.images.smaller": " POZOR: zmenšeno, aby se vešlo do limitu {mb} MB: kvalita {level}, nastavena {asked} — víc místa: --images-max-mb <n> (strom config set excerpts.mb <n>)",
|
|
1309
1313
|
"ui.export.images.dropped": " POZOR: vynecháno, aby se vešlo do limitu {mb} MB, nejdřív nejvzdálenější od výzkumu: {n, plural, one {# pramen} few {# prameny} other {# pramenů}} ({ids}) — víc místa: --images-max-mb <n>",
|
|
1310
1314
|
"ui.export.images.scope": " prameny lidí vzdálenějších od výzkumu, než říká excerpts.for={for}: {n} — všechny: --images-for all",
|
|
1311
1315
|
"ui.export.images.missing": " snímek není na tomto počítači: {ids}",
|
package/assets/lang/de.json
CHANGED
|
@@ -1305,6 +1305,10 @@
|
|
|
1305
1305
|
"ui.export.valid.warnings": " gültiges GEDCOM 5.5.1 ({n, plural, one {# Warnung} other {# Warnungen}})",
|
|
1306
1306
|
"ui.export.committed": "in die Geschichte geschrieben",
|
|
1307
1307
|
"ui.export.images": " {excerpts, plural, one {# Ausschnitt} other {# Ausschnitte}} aus {sources, plural, one {# Quelle} other {# Quellen}}, {size} · Qualität {level}",
|
|
1308
|
+
"ui.export.quality.small": "niedrig",
|
|
1309
|
+
"ui.export.quality.normal": "normal",
|
|
1310
|
+
"ui.export.quality.sharp": "hoch",
|
|
1311
|
+
"ui.export.quality.smaller": "sehr niedrig",
|
|
1308
1312
|
"ui.export.images.smaller": " ACHTUNG: verkleinert, damit es in die Grenze von {mb} MB passt: {level} statt {asked} — mehr Platz: --images-max-mb <n> (strom config set excerpts.mb <n>)",
|
|
1309
1313
|
"ui.export.images.dropped": " ACHTUNG: ausgelassen, damit es in die Grenze von {mb} MB passt, das von der Forschung am weitesten Entfernte zuerst: {n, plural, one {# Quelle} other {# Quellen}} ({ids}) — mehr Platz: --images-max-mb <n>",
|
|
1310
1314
|
"ui.export.images.scope": " {n, plural, one {# Quelle} other {# Quellen}} von Personen, die der Forschung ferner stehen als excerpts.for={for} — alle: --images-for all",
|
package/dist/cli/ui.js
CHANGED
|
@@ -1218,6 +1218,10 @@ export const UI = {
|
|
|
1218
1218
|
"ui.export.valid.warnings": " valid GEDCOM 5.5.1 ({n, plural, one {# warning} other {# warnings}})",
|
|
1219
1219
|
"ui.export.committed": "committed",
|
|
1220
1220
|
"ui.export.images": " {excerpts, plural, one {# excerpt} other {# excerpts}} of {sources, plural, one {# source} other {# sources}}, {size} · quality {level}",
|
|
1221
|
+
"ui.export.quality.small": "small",
|
|
1222
|
+
"ui.export.quality.normal": "normal",
|
|
1223
|
+
"ui.export.quality.sharp": "sharp",
|
|
1224
|
+
"ui.export.quality.smaller": "smaller",
|
|
1221
1225
|
"ui.export.images.smaller": " WARNING made smaller to fit the limit of {mb} MB: {level} instead of {asked} — more room: --images-max-mb <n> (strom config set excerpts.mb <n>)",
|
|
1222
1226
|
"ui.export.images.dropped": " WARNING left out to fit the limit of {mb} MB, the farthest from the research first: {n, plural, one {# source} other {# sources}} ({ids}) — more room: --images-max-mb <n>",
|
|
1223
1227
|
"ui.export.images.scope": " {n, plural, one {# source} other {# sources}} of people farther from the research than excerpts.for={for} — all of them: --images-for all",
|
package/dist/commands/output.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { register } from "../cli/registry.js";
|
|
5
|
-
import { counted, lines, table } from "../cli/format.js";
|
|
5
|
+
import { counted, lines, numberIn, table } from "../cli/format.js";
|
|
6
6
|
import { exportGedcom, GED_PROFILES } from "../gedcom/export.js";
|
|
7
7
|
import { hasGedErrors, validateGedcom } from "../gedcom/validate.js";
|
|
8
8
|
import { writeFileAtomic } from "../core/json.js";
|
|
@@ -101,14 +101,18 @@ export function writeTreeGed(tree, opts) {
|
|
|
101
101
|
}
|
|
102
102
|
return { ...result, findings, file, for: opts.for, ...(images && set ? { images: images.report, imageSettings: set } : {}) };
|
|
103
103
|
}
|
|
104
|
-
|
|
104
|
+
/** A size of images as the language writes it (0,4 MB in Czech, 0.4 MB in English). */
|
|
105
|
+
const mbIn = (bytes, lang) => `${numberIn(lang, bytes / 1024 / 1024, { minimumFractionDigits: 1, maximumFractionDigits: 1 })} MB`;
|
|
106
|
+
/** A quality of the images (excerpt.ts LEVELS) as the language says it; in English its name, the value excerpts.quality takes. */
|
|
107
|
+
const QUALITY_WORDS = { sharp: "ui.export.quality.sharp", normal: "ui.export.quality.normal", small: "ui.export.quality.small", smaller: "ui.export.quality.smaller" };
|
|
108
|
+
export const qualityIn = (q, lang) => (Object.hasOwn(QUALITY_WORDS, q) ? ui(lang, QUALITY_WORDS[q]) : q);
|
|
105
109
|
/**
|
|
106
110
|
* What an export with images took in and left out, and what to do about it — what strom decided itself is said as a
|
|
107
111
|
* warning; in `lang` (a person's research language, else English).
|
|
108
112
|
*/
|
|
109
113
|
export function imagesLines(r, images, lang = "en") {
|
|
110
114
|
const few = (ids) => `${ids.slice(0, 8).join(", ")}${ids.length > 8 ? ` … (${ids.length})` : ""}`;
|
|
111
|
-
return lines(ui(lang, "ui.export.images", { excerpts: r.excerpts, sources: r.sources, size:
|
|
115
|
+
return lines(ui(lang, "ui.export.images", { excerpts: r.excerpts, sources: r.sources, size: mbIn(r.bytes, lang), level: qualityIn(r.level, lang) }), r.level !== r.asked ? ui(lang, "ui.export.images.smaller", { mb: numberIn(lang, images.mb, { maximumFractionDigits: 3, useGrouping: false }), level: qualityIn(r.level, lang), asked: qualityIn(r.asked, lang) }) : undefined, r.dropped.length ? ui(lang, "ui.export.images.dropped", { mb: numberIn(lang, images.mb, { maximumFractionDigits: 3, useGrouping: false }), n: r.dropped.length, ids: few(r.dropped) }) : undefined, r.outOfScope ? ui(lang, "ui.export.images.scope", { n: r.outOfScope, for: images.for }) : undefined, r.missing.length ? ui(lang, "ui.export.images.missing", { ids: few(r.missing) }) : undefined, r.unclipped.length ? ui(lang, "ui.export.images.unclipped", { ids: few(r.unclipped) }) : undefined, r.later.length ? ui(lang, "ui.export.images.later", { n: r.later.length }) : undefined);
|
|
112
116
|
}
|
|
113
117
|
/** The images of an export: the settings, each overridden by its option. */
|
|
114
118
|
export function imageSettings(ctx, tree, opts) {
|
package/dist/commands/session.js
CHANGED
|
@@ -136,7 +136,7 @@ register({
|
|
|
136
136
|
if (task && !["open", "doing", "parked"].includes(task.state))
|
|
137
137
|
throw new UsageError(`${task.id} is ${task.state}`);
|
|
138
138
|
const s = startSession(tree, { ...(task ? { task } : {}), ...(research ? { research: research.id } : {}) });
|
|
139
|
-
reviveLive(tree.root, ctx.env);
|
|
139
|
+
reviveLive(tree.root, ctx.env, { work: true });
|
|
140
140
|
const shared = ctx.settings.shared()?.value;
|
|
141
141
|
const brief = buildBrief(tree, { ...(task ? { task } : {}), session: s, budget: ctx.settings.number("brief.budget", tree.config, DEFAULT_BUDGET), shared, browser: briefBrowser(tree, shared, s, task) });
|
|
142
142
|
// a task the queue holds back, started by its ID: the agent hears why before it begins
|
|
@@ -947,8 +947,8 @@ register({
|
|
|
947
947
|
}
|
|
948
948
|
gateTrail.length = 0;
|
|
949
949
|
}
|
|
950
|
-
// the Strom app followed the research and its bridge ended without a word: on its address again
|
|
951
|
-
reviveLive(root, ctx.env);
|
|
950
|
+
// the Strom app followed the research and its bridge ended without a word, or idle: on its address again
|
|
951
|
+
reviveLive(root, ctx.env, { work: true });
|
|
952
952
|
// The Strom app follows it from the first session on — not while the run still waits for its gate.
|
|
953
953
|
if (opts.follow && !followed) {
|
|
954
954
|
followed = true;
|
package/dist/commands/start.js
CHANGED
|
@@ -6,7 +6,7 @@ import path from "node:path";
|
|
|
6
6
|
import { configDir, userHome } from "../core/paths.js";
|
|
7
7
|
import { prependPath, spawnAgent } from "../runners/runner.js";
|
|
8
8
|
import { register } from "../cli/registry.js";
|
|
9
|
-
import { lines, truncate } from "../cli/format.js";
|
|
9
|
+
import { lines, numberIn, truncate } from "../cli/format.js";
|
|
10
10
|
import { ui } from "../cli/ui.js";
|
|
11
11
|
import { StromError, UsageError } from "../core/errors.js";
|
|
12
12
|
import { PROFILES } from "../agents/profiles.js";
|
|
@@ -37,7 +37,7 @@ import { commitNow, shimDir } from "./session.js";
|
|
|
37
37
|
import { abandonedSessions, closeSession, openSessions } from "../core/session.js";
|
|
38
38
|
import { enterWorker, liveWorkers } from "../core/workers.js";
|
|
39
39
|
import { phrase } from "../core/phrases.js";
|
|
40
|
-
import { imageSettings, writeGedcoms, writeTreeGed } from "./output.js";
|
|
40
|
+
import { imageSettings, qualityIn, writeGedcoms, writeTreeGed } from "./output.js";
|
|
41
41
|
import { shortcutName } from "../cli/wizard.js";
|
|
42
42
|
import { refuseInArchive } from "../core/state.js";
|
|
43
43
|
/** Has the user trusted this folder in Claude Code already? (Its own record, read only.) */
|
|
@@ -293,7 +293,7 @@ register({
|
|
|
293
293
|
const r = ged.images;
|
|
294
294
|
const set = ged.imageSettings;
|
|
295
295
|
const withImages = r && set
|
|
296
|
-
? lines(ui(lang, "ui.app.images", { n: String(r.excerpts), mb: (r.bytes / 1024 / 1024
|
|
296
|
+
? lines(ui(lang, "ui.app.images", { n: String(r.excerpts), mb: numberIn(lang, r.bytes / 1024 / 1024, { minimumFractionDigits: 1, maximumFractionDigits: 1 }) }), r.level !== r.asked ? ui(lang, "ui.app.images.smaller", { limit: numberIn(lang, set.mb, { maximumFractionDigits: 3, useGrouping: false }), level: qualityIn(r.level, lang), asked: qualityIn(r.asked, lang) }) : undefined, r.dropped.length ? ui(lang, "ui.app.images.left", { n: String(r.dropped.length), limit: numberIn(lang, set.mb, { maximumFractionDigits: 3, useGrouping: false }) }) : undefined, r.outOfScope ? ui(lang, "ui.app.images.scope", { n: String(r.outOfScope), for: set.for }) : undefined, r.unclipped.length ? ui(lang, "ui.app.images.unclipped", { n: String(r.unclipped.length) }) : undefined)
|
|
297
297
|
: undefined;
|
|
298
298
|
// B, D: the app reaches strom on this computer — the app installed from a browser first (that of the browser
|
|
299
299
|
// its tree came from, app.browser, when several), else a tab of that browser, else of the default one when the
|
|
@@ -361,11 +361,13 @@ register({
|
|
|
361
361
|
tree: true,
|
|
362
362
|
description: "A small web server on this computer only (127.0.0.1, a secret address), that only reads: the Strom app, opened with\n" +
|
|
363
363
|
"strom app --live, takes the tree from it and hears what changes — who is at work on what, what was recorded, what\n" +
|
|
364
|
-
"waits for the user. It ends by itself when nobody asks it anything for two hours
|
|
364
|
+
"waits for the user. It ends by itself when nobody asks it anything for two hours while nobody works in the tree,\n" +
|
|
365
|
+
"or with strom live stop.\n" +
|
|
365
366
|
"One error does not end it (a read that fails is tried again); what it did and what went wrong is in .strom/live.log.\n" +
|
|
366
367
|
"Started again by itself (strom updated, one that ended without a word or when idle) it takes the address it had\n" +
|
|
367
|
-
"(its port while free), so the app following it goes on by itself; one that ended without a word
|
|
368
|
-
"when a session starts
|
|
368
|
+
"(its port while free), so the app following it goes on by itself; one that ended without a word or when idle is\n" +
|
|
369
|
+
"started again when a session starts (idle: only one the app was given, never in an archive). Stopped with strom\n" +
|
|
370
|
+
"live stop, the next one gets a new secret address.",
|
|
369
371
|
examples: ["strom live", "strom live start", "strom live stop"],
|
|
370
372
|
run(ctx) {
|
|
371
373
|
const tree = bridgeTree(ctx);
|
package/dist/core/live.js
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
// ?live=<address>, takes the tree's GEDCOM from it and hears what changes —
|
|
5
5
|
// who is at work on what, what was recorded, what waits for the user. Nothing
|
|
6
6
|
// leaves the computer. The bridge ends by itself when nobody has asked it
|
|
7
|
-
// anything for a while (LIVE_IDLE_MS), or with
|
|
7
|
+
// anything for a while (LIVE_IDLE_MS) and nobody works in the tree, or with
|
|
8
|
+
// strom live stop.
|
|
8
9
|
//
|
|
9
10
|
// GET <token>/status the tree, its researches, who is at work, what waits; what the research takes from
|
|
10
11
|
// the app (accepts). ?poll=1: the app asking now and then — the bridge's idle time goes on
|
|
@@ -57,7 +58,8 @@
|
|
|
57
58
|
//
|
|
58
59
|
// The secret: started again by itself — a newer strom on disk (live start
|
|
59
60
|
// --current), one that ended without a word (reviveLive), the first run of a
|
|
60
|
-
// newer strom bringing its bridges back, a start after it ended when idle
|
|
61
|
+
// newer strom bringing its bridges back, a start after it ended when idle (a new
|
|
62
|
+
// session too, when its secret is kept and the tree is no archive) — it
|
|
61
63
|
// takes the address it had (.strom/live-last.json: its port while free, its
|
|
62
64
|
// token), so the app following it goes on by itself. Ended for good (strom live
|
|
63
65
|
// stop, strom uninstall) its secret is dropped: the next bridge gets a new one
|
|
@@ -86,7 +88,7 @@ import { phrase } from "./phrases.js";
|
|
|
86
88
|
import { exportGedcom } from "../gedcom/export.js";
|
|
87
89
|
import { excerptSettings, planExcerpts } from "./excerpt.js";
|
|
88
90
|
import { adoptedAt, adoptedEmpty, adoptionWait, noteAdoptAsked, markSentAgain, undoneSend, undoneSince, failReceived, inboxTrees, markAdopted, noteAdoptFailed, noteNothingSent, pendingAdoption, receiveAdopted, receivedAll, receivedPending, receiveTree, recentSends, stampAppVersion, syncConflicts, SYNC_INBOX, SYNC_MAX_BYTES, namesOf } from "./sync.js";
|
|
89
|
-
import { modeOf, settleArchive } from "./mode.js";
|
|
91
|
+
import { isArchive, modeOf, settleArchive } from "./mode.js";
|
|
90
92
|
import { actsAsArchive, stateOf } from "./state.js";
|
|
91
93
|
import { raiseHypothesisLinkTasks, settleHypothesisLinks } from "./hypolinks.js";
|
|
92
94
|
import { PROFILES } from "../agents/profiles.js";
|
|
@@ -98,7 +100,7 @@ import { checkOriginalMeta, freeBytes, knownOriginal, materialWaiting, originalM
|
|
|
98
100
|
import { BATCH_ID, batchEstimate, batchLimits, batchRoom, batchPath, batchStatus, idleBatches, noteBatch, openBatch, readBatch } from "./batches.js";
|
|
99
101
|
/** New images for the app, made for at most so long when the tree changed (the rest the next time). */
|
|
100
102
|
const LIVE_IMAGES_MS = 20_000;
|
|
101
|
-
import { liveWorkers } from "./workers.js";
|
|
103
|
+
import { anyoneAtWork, liveWorkers } from "./workers.js";
|
|
102
104
|
import { monthSpend, openSessions } from "./session.js";
|
|
103
105
|
import { rankTasks } from "./queue.js";
|
|
104
106
|
import { humanTask } from "../cli/human.js";
|
|
@@ -570,16 +572,37 @@ export function stopLive(root, why = "strom live stop", opts = {}) {
|
|
|
570
572
|
// no bridge of that number ran (it ended meanwhile, the number another program's): none was stopped
|
|
571
573
|
return how === "gone" ? "none" : how;
|
|
572
574
|
}
|
|
575
|
+
/** Whether a bridge's end was its idle time running out (the reason it wrote: "idle: …"). */
|
|
576
|
+
function endedIdle(last) {
|
|
577
|
+
return /^idle\b/.test(last.ended?.reason ?? "");
|
|
578
|
+
}
|
|
573
579
|
/**
|
|
574
580
|
* The bridge of a tree that ended without a word (a crash, killed) is started again — on its address, so the
|
|
575
|
-
* Strom app following it goes on by itself. One that ended as it should (idle, stopped) stays so
|
|
581
|
+
* Strom app following it goes on by itself. One that ended as it should (idle, stopped) stays so — but new work in the
|
|
582
|
+
* tree (work: a session starts) brings back one that ended idle, at its address, when the app was given it (its secret
|
|
583
|
+
* kept: never after strom live stop or uninstall) and the tree is no archive: the app watching the tree without
|
|
584
|
+
* following it (/status?poll=1) sees it at work again.
|
|
576
585
|
*/
|
|
577
|
-
export function reviveLive(root, env) {
|
|
586
|
+
export function reviveLive(root, env, opts = {}) {
|
|
578
587
|
const last = readLast(root);
|
|
579
|
-
if (!last ||
|
|
588
|
+
if (!last || alive(last.pid) || liveRunning(root))
|
|
580
589
|
return undefined;
|
|
581
|
-
|
|
582
|
-
|
|
590
|
+
if (last.ended) {
|
|
591
|
+
if (!opts.work || !last.token || !endedIdle(last))
|
|
592
|
+
return undefined;
|
|
593
|
+
try {
|
|
594
|
+
if (isArchive({ config: readJsonIfExists(path.join(root, TREE_FILE)) ?? {} }))
|
|
595
|
+
return undefined;
|
|
596
|
+
}
|
|
597
|
+
catch {
|
|
598
|
+
return undefined;
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
const why = last.ended
|
|
602
|
+
? `work in the tree again: the bridge ${last.pid} that ended idle started again at its address`
|
|
603
|
+
: `the bridge ${last.pid} ended without a word: started again`;
|
|
604
|
+
const info = startLive(root, env, { why });
|
|
605
|
+
// one that does not come up is not tried at every session again (each try waits for it some seconds)
|
|
583
606
|
if (!info)
|
|
584
607
|
writeLast(root, { ...last, ended: { at: new Date().toISOString(), reason: "did not start again" } });
|
|
585
608
|
return info;
|
|
@@ -2610,7 +2633,9 @@ export function serveLive(root, env) {
|
|
|
2610
2633
|
tidied = Date.now();
|
|
2611
2634
|
safe("keeping order", () => autoTidy(Tree.open(root, env)));
|
|
2612
2635
|
}
|
|
2613
|
-
|
|
2636
|
+
// the idle time runs only while nobody works in the tree (a run waiting for its gate works too): the app watching
|
|
2637
|
+
// the tree without following it (/status?poll=1) still finds the bridge while an agent is at work
|
|
2638
|
+
if (streams.size || anyoneAtWork(root))
|
|
2614
2639
|
lastAsked = Date.now();
|
|
2615
2640
|
if (Date.now() - lastAsked > idleMs)
|
|
2616
2641
|
return stop("idle: nobody asked for a while", "idle", false);
|
package/dist/core/tree.js
CHANGED
|
@@ -27,7 +27,7 @@ import { lastBackup } from "./backup.js";
|
|
|
27
27
|
export const TREE_FILE = "strom.json";
|
|
28
28
|
// between releases the candidate being made (a bridge run from the sources says what it is: the Strom app goes by it);
|
|
29
29
|
// at a release the release's own (package.json)
|
|
30
|
-
export const VERSION = "1.17.0
|
|
30
|
+
export const VERSION = "1.17.0";
|
|
31
31
|
const GITIGNORE = `# Strom Research — local state and large files are not versioned
|
|
32
32
|
.strom/
|
|
33
33
|
/media/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "strom-research",
|
|
3
|
-
"version": "1.17.0
|
|
3
|
+
"version": "1.17.0",
|
|
4
4
|
"description": "Genealogical research toolkit for AI coding agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -57,8 +57,5 @@
|
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@types/node": "^22.20.4",
|
|
59
59
|
"typescript": "^7.0.2"
|
|
60
|
-
},
|
|
61
|
-
"publishConfig": {
|
|
62
|
-
"tag": "beta"
|
|
63
60
|
}
|
|
64
61
|
}
|