strom-research 1.13.0-beta.2 → 1.13.0-beta.4
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 +10 -2
- package/assets/lang/de.json +10 -2
- package/dist/cli/help.js +8 -7
- package/dist/cli/main.js +3 -3
- package/dist/cli/menu-links.js +4 -1
- package/dist/cli/menu.js +3 -3
- package/dist/cli/registry.js +20 -3
- package/dist/cli/ui.js +10 -2
- package/dist/cli/wizard.js +7 -3
- package/dist/commands/analysis.js +3 -0
- package/dist/commands/meta.js +7 -6
- package/dist/commands/setup.js +28 -10
- package/dist/commands/start.js +23 -5
- package/dist/commands/sync.js +3 -1
- package/dist/core/appbrowser.js +2 -2
- package/dist/core/config.js +31 -15
- package/dist/core/git.js +50 -18
- package/dist/core/import.js +46 -25
- package/dist/core/live.js +8 -3
- package/dist/core/people.js +12 -0
- package/dist/core/stromapp.js +88 -17
- package/dist/core/sync.js +47 -21
- package/dist/core/tree.js +1 -1
- package/dist/gedcom/export.js +12 -4
- package/package.json +1 -1
package/assets/lang/cs.json
CHANGED
|
@@ -275,6 +275,9 @@
|
|
|
275
275
|
"ui.doc.app.seen": "nalezena v počítači",
|
|
276
276
|
"ui.doc.app.no": "není chtěná",
|
|
277
277
|
"ui.doc.app.unknown": "nenalezena",
|
|
278
|
+
"ui.doc.appurl": "adresa aplikace Strom",
|
|
279
|
+
"ui.doc.appurl.config": "nastavení strom.app.url „{value}“ není adresa aplikace Strom – strom app nic neotevře, dokud se neopraví nebo neodebere",
|
|
280
|
+
"ui.doc.appurl.env": "proměnná STROM_APP_URL „{value}“ není adresa aplikace Strom – strom app nic neotevře, dokud se neopraví nebo neodebere",
|
|
278
281
|
"ui.doc.tree.ok": "{name}: data v pořádku a zapečetěná",
|
|
279
282
|
"ui.doc.tree.bad": "{name}: problémů {n}",
|
|
280
283
|
"ui.doc.allok": "Všechno potřebné je na místě.",
|
|
@@ -654,7 +657,7 @@
|
|
|
654
657
|
"ui.help.archive.stats": "Archiv v kostce: osoby, jak jisté jsou údaje, předkové v každé generaci",
|
|
655
658
|
"ui.help.archive.pack": "Zabalit archiv do jednoho souboru ZIP, aby v něm mohl pokračovat někdo jiný",
|
|
656
659
|
"ui.help.archive.intake": "Přidat podklady od rodiny: dokumenty, fotky, rodokmen, co je známo",
|
|
657
|
-
"ui.help.title": "strom <příkaz> – co člověk se stromem dělá (nebo jen {strom}: menu)",
|
|
660
|
+
"ui.help.title": "{strom} <příkaz> – co člověk se stromem dělá (nebo jen {strom}: menu)",
|
|
658
661
|
"ui.help.more": "Nápověda k jednomu příkazu: strom help <příkaz> --human · všechny příkazy anglicky (co čte agent): strom help",
|
|
659
662
|
"ui.help.more.archive": "Nápověda k jednomu příkazu: strom help <příkaz> --human",
|
|
660
663
|
"ui.help.examples": "Příklady:",
|
|
@@ -1496,6 +1499,10 @@
|
|
|
1496
1499
|
"ui.error.arg.missing": "chybí <{arg}>",
|
|
1497
1500
|
"ui.error.arg.missing.hint": "strom help {cmd}",
|
|
1498
1501
|
"ui.error.prefix": "chyba",
|
|
1502
|
+
"ui.error.config.app-url": "neplatné strom.app.url „{value}“: není to adresa aplikace Strom",
|
|
1503
|
+
"ui.error.config.app-url.hint": "aplikace Strom: {web}, nebo její kopie na tomto počítači http://127.0.0.1:<port>/",
|
|
1504
|
+
"ui.error.config.app-url.config.hint": "aplikace Strom: {web}, nebo její kopie na tomto počítači http://127.0.0.1:<port>/\nopravit: strom config set strom.app.url <adresa> – nebo odebrat: strom config unset strom.app.url",
|
|
1505
|
+
"ui.error.config.app-url.env.hint": "aplikace Strom: {web}, nebo její kopie na tomto počítači http://127.0.0.1:<port>/\nproměnnou STROM_APP_URL opravit, nebo odebrat",
|
|
1499
1506
|
"ui.error.backup.failed": "Zálohu před přechodem z {from} na {to} se nepodařilo vytvořit: {detail}. Nic se nepřepíná: tento strom neotevře žádný rodokmen k zápisu, dokud záloha nebude hotová.",
|
|
1500
1507
|
"ui.error.backup.failed.hint": "Uvolnit místo na disku ({where}) a spustit strom znovu – nebo se vrátit: strom update --channel {back}",
|
|
1501
1508
|
"ui.error.backup.failed.update": "Zálohu před přechodem z {from} na {to} se nepodařilo vytvořit: {detail}. Nic se nenainstalovalo.",
|
|
@@ -1587,6 +1594,7 @@
|
|
|
1587
1594
|
"ui.arg.tree-name": "název",
|
|
1588
1595
|
"ui.arg.url": "adresa",
|
|
1589
1596
|
"ui.arg.value": "hodnota",
|
|
1597
|
+
"ui.arg.address": "adresa",
|
|
1590
1598
|
"ui.arg.what": "co",
|
|
1591
1599
|
"ui.arg.where": "kde",
|
|
1592
1600
|
"ui.arg.who": "kdo",
|
|
@@ -1614,7 +1622,7 @@
|
|
|
1614
1622
|
"ui.error.event.needs-reason.hint": "např. --reason \"záznam S0012 uvádí 1811, ne 1813\"",
|
|
1615
1623
|
"ui.error.family.needs-reason": "změna toho, kdo do rodiny patří nebo jak, potřebuje --reason",
|
|
1616
1624
|
"ui.error.family.needs-reason.hint": "např. --reason \"křest uvádí Jana jako otčíma\"",
|
|
1617
|
-
"ui.error.person.needs-reason": "změna jména nebo známého pohlaví potřebuje --reason",
|
|
1625
|
+
"ui.error.person.needs-reason": "změna jména, jeho titulu nebo známého pohlaví potřebuje --reason",
|
|
1618
1626
|
"ui.error.person.needs-reason.hint": "např. --reason \"špatně přečteno: matrika má Novák, ne Nowak\"",
|
|
1619
1627
|
"ui.error.retract.needs-reason": "stažení potřebuje --reason",
|
|
1620
1628
|
"ui.error.retract.needs-reason.hint": "např. --reason \"špatně přečteno: zápis uvádí Annu, ne Antona\"",
|
package/assets/lang/de.json
CHANGED
|
@@ -275,6 +275,9 @@
|
|
|
275
275
|
"ui.doc.app.seen": "auf dem Computer gefunden",
|
|
276
276
|
"ui.doc.app.no": "nicht gewünscht",
|
|
277
277
|
"ui.doc.app.unknown": "nicht gefunden",
|
|
278
|
+
"ui.doc.appurl": "Adresse der Strom-App",
|
|
279
|
+
"ui.doc.appurl.config": "die Einstellung strom.app.url „{value}“ ist keine Adresse der Strom-App – strom app öffnet nichts, bis sie berichtigt oder entfernt ist",
|
|
280
|
+
"ui.doc.appurl.env": "die Variable STROM_APP_URL „{value}“ ist keine Adresse der Strom-App – strom app öffnet nichts, bis sie berichtigt oder entfernt ist",
|
|
278
281
|
"ui.doc.tree.ok": "{name}: Daten in Ordnung und versiegelt",
|
|
279
282
|
"ui.doc.tree.bad": "{name}: Probleme: {n}",
|
|
280
283
|
"ui.doc.allok": "Alles Nötige ist vorhanden.",
|
|
@@ -654,7 +657,7 @@
|
|
|
654
657
|
"ui.help.archive.stats": "Das Archiv auf einen Blick: Personen, wie sicher die Angaben sind, Vorfahren je Generation",
|
|
655
658
|
"ui.help.archive.pack": "Das Archiv in eine ZIP-Datei packen, damit jemand anderes weitermachen kann",
|
|
656
659
|
"ui.help.archive.intake": "Material der Familie hinzufügen: Dokumente, Fotos, einen Stammbaum, eigenes Wissen",
|
|
657
|
-
"ui.help.title": "strom <Befehl> – was ein Mensch mit strom tut (oder nur {strom}: das Menü)",
|
|
660
|
+
"ui.help.title": "{strom} <Befehl> – was ein Mensch mit strom tut (oder nur {strom}: das Menü)",
|
|
658
661
|
"ui.help.more": "Hilfe zu einem Befehl: strom help <Befehl> --human · alle Befehle auf Englisch (was ein Agent liest): strom help",
|
|
659
662
|
"ui.help.more.archive": "Hilfe zu einem Befehl: strom help <Befehl> --human",
|
|
660
663
|
"ui.help.examples": "Beispiele:",
|
|
@@ -1496,6 +1499,10 @@
|
|
|
1496
1499
|
"ui.error.arg.missing": "<{arg}> fehlt",
|
|
1497
1500
|
"ui.error.arg.missing.hint": "strom help {cmd}",
|
|
1498
1501
|
"ui.error.prefix": "Fehler",
|
|
1502
|
+
"ui.error.config.app-url": "ungültige strom.app.url „{value}“: keine Adresse der Strom-App",
|
|
1503
|
+
"ui.error.config.app-url.hint": "die Strom-App: {web}, oder eine Kopie auf diesem Computer http://127.0.0.1:<port>/",
|
|
1504
|
+
"ui.error.config.app-url.config.hint": "die Strom-App: {web}, oder eine Kopie auf diesem Computer http://127.0.0.1:<port>/\nberichtigen: strom config set strom.app.url <Adresse> – oder entfernen: strom config unset strom.app.url",
|
|
1505
|
+
"ui.error.config.app-url.env.hint": "die Strom-App: {web}, oder eine Kopie auf diesem Computer http://127.0.0.1:<port>/\ndie Variable STROM_APP_URL berichtigen oder entfernen",
|
|
1499
1506
|
"ui.error.backup.failed": "Die Sicherung vor dem Wechsel von {from} auf {to} ließ sich nicht erstellen: {detail}. Es wird nichts umgestellt: dieses strom öffnet keinen Stammbaum zum Schreiben, bis die Sicherung erstellt ist.",
|
|
1500
1507
|
"ui.error.backup.failed.hint": "Platz auf dem Datenträger freimachen ({where}) und strom erneut starten – oder zurück: strom update --channel {back}",
|
|
1501
1508
|
"ui.error.backup.failed.update": "Die Sicherung vor dem Wechsel von {from} auf {to} ließ sich nicht erstellen: {detail}. Es wurde nichts installiert.",
|
|
@@ -1587,6 +1594,7 @@
|
|
|
1587
1594
|
"ui.arg.tree-name": "Name",
|
|
1588
1595
|
"ui.arg.url": "Adresse",
|
|
1589
1596
|
"ui.arg.value": "Wert",
|
|
1597
|
+
"ui.arg.address": "Adresse",
|
|
1590
1598
|
"ui.arg.what": "was",
|
|
1591
1599
|
"ui.arg.where": "wo",
|
|
1592
1600
|
"ui.arg.who": "wer",
|
|
@@ -1614,7 +1622,7 @@
|
|
|
1614
1622
|
"ui.error.event.needs-reason.hint": "z. B. --reason \"Eintrag S0012 nennt 1811, nicht 1813\"",
|
|
1615
1623
|
"ui.error.family.needs-reason": "wer zur Familie gehört oder wie, ändert sich nur mit --reason",
|
|
1616
1624
|
"ui.error.family.needs-reason.hint": "z. B. --reason \"die Taufe nennt Jan als Stiefvater\"",
|
|
1617
|
-
"ui.error.person.needs-reason": "ein Name oder ein bekanntes Geschlecht ändert sich nur mit --reason",
|
|
1625
|
+
"ui.error.person.needs-reason": "ein Name, sein Titel oder ein bekanntes Geschlecht ändert sich nur mit --reason",
|
|
1618
1626
|
"ui.error.person.needs-reason.hint": "z. B. --reason \"falsch gelesen: im Register steht Novák, nicht Nowak\"",
|
|
1619
1627
|
"ui.error.retract.needs-reason": "Zurückziehen braucht --reason",
|
|
1620
1628
|
"ui.error.retract.needs-reason.hint": "z. B. --reason \"falsch gelesen: der Eintrag nennt Anna, nicht Anton\"",
|
package/dist/cli/help.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Help text generated from the registry. Short by design: examples first,
|
|
2
2
|
// then arguments and options.
|
|
3
|
-
import { GROUPS, GLOBAL_OPTIONS, WRITE_OPTIONS, commands, match, subcommandsOf, usageLine } from "./registry.js";
|
|
3
|
+
import { GROUPS, GLOBAL_OPTIONS, WRITE_OPTIONS, commands, descriptionOf, match, subcommandsOf, usageLine } from "./registry.js";
|
|
4
4
|
import { table } from "./format.js";
|
|
5
5
|
import { suggest } from "./execute.js";
|
|
6
6
|
import { UI, ui } from "./ui.js";
|
|
@@ -43,13 +43,14 @@ function inArchive(def) {
|
|
|
43
43
|
return own;
|
|
44
44
|
return AI_WORDS.test(def.summary) ? undefined : def.summary;
|
|
45
45
|
}
|
|
46
|
-
export function commandHelp(def, archive
|
|
46
|
+
export function commandHelp(def, archive, appUrl) {
|
|
47
47
|
const summary = archive ? inArchive(def) : def.summary;
|
|
48
48
|
if (summary === undefined)
|
|
49
49
|
return `strom ${def.path.join(" ")}: not in an archive (research is switched on by the user: strom mode research)`;
|
|
50
50
|
const out = [usageLine(def), "", summary];
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
const description = descriptionOf(def, appUrl);
|
|
52
|
+
if (description && !(archive && AI_WORDS.test(description)))
|
|
53
|
+
out.push("", description);
|
|
53
54
|
const examples = (def.examples ?? []).filter((e) => !(archive && AI_WORDS.test(e)));
|
|
54
55
|
if (examples.length)
|
|
55
56
|
out.push("", "Examples:", ...examples.map((e) => ` ${e}`));
|
|
@@ -111,14 +112,14 @@ export function overview(archive = false) {
|
|
|
111
112
|
out.push("", "One command — usage, examples, options: strom help <command>", archive ? "Each command with what it does: strom commands <group>" : "Each command with what it does: strom commands [<group>] · with options and examples: strom commands <group> --json");
|
|
112
113
|
return out.join("\n");
|
|
113
114
|
}
|
|
114
|
-
export function helpFor(input, archive
|
|
115
|
+
export function helpFor(input, archive, appUrl) {
|
|
115
116
|
// "strom help 'research new'" — one quoted argument with several words.
|
|
116
117
|
const words = input.flatMap((w) => w.trim().split(/\s+/)).filter(Boolean);
|
|
117
118
|
if (words.length === 0)
|
|
118
119
|
return overview(archive);
|
|
119
120
|
const found = match(words);
|
|
120
121
|
if (found && found.used === words.length)
|
|
121
|
-
return commandHelp(found.def, archive);
|
|
122
|
+
return commandHelp(found.def, archive, appUrl);
|
|
122
123
|
if (subcommandsOf(words).length > 0)
|
|
123
124
|
return groupHelp(words, archive);
|
|
124
125
|
const all = commands().filter((c) => c.path.length > 0).map((c) => c.path.join(" "));
|
|
@@ -185,7 +186,7 @@ function pointer(words, as) {
|
|
|
185
186
|
export function helpAs(input, as) {
|
|
186
187
|
const words = input.flatMap((w) => w.trim().split(/\s+/)).filter(Boolean);
|
|
187
188
|
if (!as.human)
|
|
188
|
-
return helpFor(words, as.archive) + pointer(words, as);
|
|
189
|
+
return helpFor(words, as.archive, as.appUrl) + pointer(words, as);
|
|
189
190
|
if (words.length === 0)
|
|
190
191
|
return humanOverview(as);
|
|
191
192
|
const found = match(words);
|
package/dist/cli/main.js
CHANGED
|
@@ -16,7 +16,7 @@ import { fireHooks, HOOK_INTERFACE } from "../core/hooks.js";
|
|
|
16
16
|
import { prependPath } from "../runners/runner.js";
|
|
17
17
|
import { shimDir } from "../commands/session.js";
|
|
18
18
|
import { isAgent } from "../core/which.js";
|
|
19
|
-
import { noticeStromApp } from "../core/stromapp.js";
|
|
19
|
+
import { appUrlShown, noticeStromApp } from "../core/stromapp.js";
|
|
20
20
|
import { lastChannelOf, pendingTransition, updateChannel } from "../core/update.js";
|
|
21
21
|
import { backupBefore, backupSaid } from "./backups.js";
|
|
22
22
|
import { installation } from "../core/self.js";
|
|
@@ -157,7 +157,7 @@ export async function main(argv, io, env, cwd) {
|
|
|
157
157
|
catch (err) {
|
|
158
158
|
if (err instanceof GroupOnly) {
|
|
159
159
|
const c = Context.fromOptions({ env, cwd, io, json, values: {} });
|
|
160
|
-
io.stdout(groupHelpAs(err.group, { archive: c.archiveHere(), human: false, lang: c.uiLang(), pointer: io.tty && !isAgent(env) }) + "\n");
|
|
160
|
+
io.stdout(groupHelpAs(err.group, { archive: c.archiveHere(), human: false, lang: c.uiLang(), appUrl: appUrlShown(c.settings), pointer: io.tty && !isAgent(env) }) + "\n");
|
|
161
161
|
return EXIT.ok;
|
|
162
162
|
}
|
|
163
163
|
throw err;
|
|
@@ -170,7 +170,7 @@ export async function main(argv, io, env, cwd) {
|
|
|
170
170
|
// the agent's help, whoever asks (Milan, 2026-10-04: "výchozí je pro agenta"); a person at a terminal is told in a
|
|
171
171
|
// line of their language how to get theirs (strom help <command> --human)
|
|
172
172
|
const c = Context.fromOptions({ env, cwd, io, json, values: v });
|
|
173
|
-
io.stdout(helpAs(def.path, { archive: c.archiveHere(), human: false, lang: c.uiLang(), pointer: io.tty && !isAgent(env) }) + "\n");
|
|
173
|
+
io.stdout(helpAs(def.path, { archive: c.archiveHere(), human: false, lang: c.uiLang(), appUrl: appUrlShown(c.settings), pointer: io.tty && !isAgent(env) }) + "\n");
|
|
174
174
|
return EXIT.ok;
|
|
175
175
|
}
|
|
176
176
|
if (v.version) {
|
package/dist/cli/menu-links.js
CHANGED
|
@@ -20,7 +20,7 @@ import { appWindow } from "../core/appbrowser.js";
|
|
|
20
20
|
import { moveTree } from "./move.js";
|
|
21
21
|
import { changeLines } from "../core/changelog.js";
|
|
22
22
|
import { startLive } from "../core/live.js";
|
|
23
|
-
import { adoptAppUrl, appTreeNameFromInstall, defaultAppUrl } from "../core/stromapp.js";
|
|
23
|
+
import { adoptAppUrl, appTreeNameFromInstall, defaultAppUrl, stromAppUrl } from "../core/stromapp.js";
|
|
24
24
|
import { stromReadsTags } from "../gedcom/export.js";
|
|
25
25
|
import { appMarkFromInstall } from "../core/links.js";
|
|
26
26
|
import { settleFromApp } from "./wizard.js";
|
|
@@ -288,6 +288,9 @@ export async function newFromApp(ctx, runIn, token, openAt, forward, opts = {})
|
|
|
288
288
|
ctx.settings.config.stromAppUrl = move.mark.app;
|
|
289
289
|
ctx.settings.save();
|
|
290
290
|
}
|
|
291
|
+
// a strom.app.url that is no address of the app: refused before anything is asked or made — the tree's way back
|
|
292
|
+
// would be an address built on it with the bridge's secret (B1-c)
|
|
293
|
+
stromAppUrl(ctx.settings);
|
|
291
294
|
let lang = ctx.uiLang();
|
|
292
295
|
let t = translator(lang);
|
|
293
296
|
out(ctx, t("ui.link.new.title"));
|
package/dist/cli/menu.js
CHANGED
|
@@ -24,7 +24,7 @@ import { lacksImages } from "../core/queue.js";
|
|
|
24
24
|
import { othersAtWork } from "../core/session.js";
|
|
25
25
|
import { DEFAULT_RUN_MINUTES } from "../core/config.js";
|
|
26
26
|
import { truncate } from "./format.js";
|
|
27
|
-
import { installedStromApp, noticeStromApp, stromAppState
|
|
27
|
+
import { appUrlSetting, installedStromApp, noticeStromApp, stromAppState } from "../core/stromapp.js";
|
|
28
28
|
import { appBrowsers } from "../core/chromium.js";
|
|
29
29
|
import { liveWorkers, runsAtWork } from "../core/workers.js";
|
|
30
30
|
import { askStromApp, settleInstall, shortcutName } from "./wizard.js";
|
|
@@ -344,7 +344,7 @@ export async function runMenu(ctx, run) {
|
|
|
344
344
|
const app = stromAppState(ctx.settings);
|
|
345
345
|
if (app !== "no") {
|
|
346
346
|
const atWork = liveWorkers(root).length > 0 || runsAtWork(root).length > 0;
|
|
347
|
-
const hasApp = app !== "unknown" || Boolean(installedStromApp(ctx.env, process.platform,
|
|
347
|
+
const hasApp = app !== "unknown" || Boolean(installedStromApp(ctx.env, process.platform, appUrlSetting(ctx.settings).url));
|
|
348
348
|
appItem = {
|
|
349
349
|
key: "7",
|
|
350
350
|
label: t(!hasApp ? "ui.menu.app.new" : atWork ? "ui.menu.app.watch" : "ui.menu.app"),
|
|
@@ -500,7 +500,7 @@ async function openStromApp(ctx, run, lang, said) {
|
|
|
500
500
|
await run(["app"]);
|
|
501
501
|
return;
|
|
502
502
|
}
|
|
503
|
-
if (!installedStromApp(ctx.env, process.platform,
|
|
503
|
+
if (!installedStromApp(ctx.env, process.platform, appUrlSetting(ctx.settings).url) && (await ctx.confirm(t("ui.app.notinstalled"), true))) {
|
|
504
504
|
await run(["app", "install"]);
|
|
505
505
|
return;
|
|
506
506
|
}
|
package/dist/cli/registry.js
CHANGED
|
@@ -73,11 +73,28 @@ export function usageLine(def) {
|
|
|
73
73
|
});
|
|
74
74
|
return ["strom", ...def.path, ...args, (def.options?.some((o) => !o.hidden) || def.writes) ? "[options]" : ""].filter(Boolean).join(" ");
|
|
75
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* A command's description as it is said here: {appUrl} the copy of the Strom app `strom app` opens (stromAppUrl — the
|
|
78
|
+
* beta for a strom of the beta channel, strom.app.url where it says another; found: help app named stromapp.info on the
|
|
79
|
+
* beta).
|
|
80
|
+
*/
|
|
81
|
+
export function descriptionOf(def, appUrl) {
|
|
82
|
+
const said = def.description?.replace(/\{appUrl\}/g, appUrl.url);
|
|
83
|
+
// an address of no Strom app in the setting: the help names the default and says so (B1-b)
|
|
84
|
+
return said && appUrl.invalid && def.description.includes("{appUrl}") ? `${said}\n${APP_URL_INVALID}` : said;
|
|
85
|
+
}
|
|
86
|
+
/** What a help says under the address of the Strom app when strom.app.url says no address of it (B1-b). */
|
|
87
|
+
export const APP_URL_INVALID = "Note: the setting strom.app.url (or STROM_APP_URL) is no address of the Strom app, so the address above is the default.\n" +
|
|
88
|
+
"Set it right (strom config set strom.app.url <address>) or remove it (strom config unset strom.app.url).";
|
|
89
|
+
/** What strom config where / config get say under a strom.app.url that is no address of the Strom app (B1-e). */
|
|
90
|
+
export const APP_URL_INVALID_SETTING = "Note: the setting strom.app.url (or STROM_APP_URL) is no address of the Strom app: strom app refuses it, and where only an address is named, the default is.\n" +
|
|
91
|
+
"Set it right (strom config set strom.app.url <address>) or remove it (strom config unset strom.app.url).";
|
|
76
92
|
/** Catalog entry for `strom commands --json`: only what is there (empty fields are left out). */
|
|
77
|
-
export function describe(def) {
|
|
93
|
+
export function describe(def, appUrl) {
|
|
78
94
|
const out = { command: def.path.join(" "), usage: usageLine(def), summary: def.summary, group: def.group };
|
|
79
|
-
|
|
80
|
-
|
|
95
|
+
const description = descriptionOf(def, appUrl);
|
|
96
|
+
if (description)
|
|
97
|
+
out.description = description;
|
|
81
98
|
if (def.writes)
|
|
82
99
|
out.writes = true;
|
|
83
100
|
if (def.tree)
|
package/dist/cli/ui.js
CHANGED
|
@@ -242,6 +242,9 @@ export const UI = {
|
|
|
242
242
|
"ui.doc.app.seen": "found on this computer",
|
|
243
243
|
"ui.doc.app.no": "not wanted",
|
|
244
244
|
"ui.doc.app.unknown": "not found",
|
|
245
|
+
"ui.doc.appurl": "address of the Strom app",
|
|
246
|
+
"ui.doc.appurl.config": "the setting strom.app.url \"{value}\" is no address of the Strom app — strom app opens nothing until it is set right or removed",
|
|
247
|
+
"ui.doc.appurl.env": "the variable STROM_APP_URL \"{value}\" is no address of the Strom app — strom app opens nothing until it is set right or removed",
|
|
245
248
|
"ui.doc.tree.ok": "{name}: data consistent and sealed",
|
|
246
249
|
"ui.doc.tree.bad": "{name}: {n} problem(s)",
|
|
247
250
|
"ui.doc.allok": "Everything needed is in place.",
|
|
@@ -561,7 +564,7 @@ export const UI = {
|
|
|
561
564
|
"ui.help.archive.stats": "The archive at a glance: people, how sure the facts are, ancestors in each generation",
|
|
562
565
|
"ui.help.archive.pack": "Pack the archive into one ZIP file for someone to go on with it",
|
|
563
566
|
"ui.help.archive.intake": "Add material from the family: documents, photos, a family tree, what the family knows",
|
|
564
|
-
"ui.help.title": "strom <command> — what a person does with strom (or just {strom}: the menu)",
|
|
567
|
+
"ui.help.title": "{strom} <command> — what a person does with strom (or just {strom}: the menu)",
|
|
565
568
|
"ui.help.more": "Help for one command: strom help <command> --human · every command in English (what an agent reads): strom help",
|
|
566
569
|
"ui.help.more.archive": "Help for one command: strom help <command> --human",
|
|
567
570
|
"ui.help.examples": "Examples:",
|
|
@@ -1346,6 +1349,10 @@ export const UI = {
|
|
|
1346
1349
|
"ui.error.arg.missing": "<{arg}> is missing",
|
|
1347
1350
|
"ui.error.arg.missing.hint": "strom help {cmd}",
|
|
1348
1351
|
"ui.error.prefix": "error",
|
|
1352
|
+
"ui.error.config.app-url": "invalid strom.app.url \"{value}\": no address of the Strom app",
|
|
1353
|
+
"ui.error.config.app-url.hint": "the Strom app: {web}, or a copy on this computer http://127.0.0.1:<port>/",
|
|
1354
|
+
"ui.error.config.app-url.config.hint": "the Strom app: {web}, or a copy on this computer http://127.0.0.1:<port>/\nset it right: strom config set strom.app.url <address> — or remove it: strom config unset strom.app.url",
|
|
1355
|
+
"ui.error.config.app-url.env.hint": "the Strom app: {web}, or a copy on this computer http://127.0.0.1:<port>/\nthe variable STROM_APP_URL set right, or removed",
|
|
1349
1356
|
"ui.error.backup.failed": "The backup before going from {from} to {to} could not be made: {detail}. Nothing is switched: this strom opens no family tree for writing until the backup is made.",
|
|
1350
1357
|
"ui.error.backup.failed.hint": "Free room on the disk ({where}), then run strom again — or go back: strom update --channel {back}",
|
|
1351
1358
|
"ui.error.backup.failed.update": "The backup before going from {from} to {to} could not be made: {detail}. Nothing was installed.",
|
|
@@ -1421,6 +1428,7 @@ export const UI = {
|
|
|
1421
1428
|
"ui.arg.tree-name": "tree name",
|
|
1422
1429
|
"ui.arg.url": "url",
|
|
1423
1430
|
"ui.arg.value": "value",
|
|
1431
|
+
"ui.arg.address": "address",
|
|
1424
1432
|
"ui.arg.what": "what",
|
|
1425
1433
|
"ui.arg.where": "where",
|
|
1426
1434
|
"ui.arg.who": "who",
|
|
@@ -1449,7 +1457,7 @@ export const UI = {
|
|
|
1449
1457
|
"ui.error.event.needs-reason.hint": "e.g. --reason \"record S0012 gives 1811, not 1813\"",
|
|
1450
1458
|
"ui.error.family.needs-reason": "changing who belongs to a family, or how, needs --reason",
|
|
1451
1459
|
"ui.error.family.needs-reason.hint": "e.g. --reason \"the baptism names Jan as stepfather\"",
|
|
1452
|
-
"ui.error.person.needs-reason": "changing a name or a known sex needs --reason",
|
|
1460
|
+
"ui.error.person.needs-reason": "changing a name, its title or a known sex needs --reason",
|
|
1453
1461
|
"ui.error.person.needs-reason.hint": "e.g. --reason \"misread: the register has Novák, not Nowak\"",
|
|
1454
1462
|
"ui.error.retract.needs-reason": "retracting needs --reason",
|
|
1455
1463
|
"ui.error.retract.needs-reason.hint": "e.g. --reason \"misread: the entry names Anna, not Anton\"",
|
package/dist/cli/wizard.js
CHANGED
|
@@ -14,7 +14,7 @@ import { chooseWay, wayName } from "./ways.js";
|
|
|
14
14
|
import { PROFILES } from "../agents/profiles.js";
|
|
15
15
|
import { writeStored, PERMISSION_LEVELS } from "../core/config.js";
|
|
16
16
|
import { globalTargets, installGlobal } from "../agents/global.js";
|
|
17
|
-
import { appCopyOfInstall, appOpensLinks, defaultAppUrl, noticeStromApp, researchUrl, STROM_APP_URL, stromAppState,
|
|
17
|
+
import { appCopyOfInstall, appOpensLinks, defaultAppUrl, noticeStromApp, researchUrl, STROM_APP_URL, stromAppState, appUrlSetting } from "../core/stromapp.js";
|
|
18
18
|
import { openForUser } from "../core/open.js";
|
|
19
19
|
import { createShortcut } from "../core/shortcut.js";
|
|
20
20
|
import { appMarkFromInstall, linkFiles, linkHandlerState, linkOwner, registerLinks } from "../core/links.js";
|
|
@@ -355,8 +355,12 @@ export async function askStromApp(ctx, lang, back = ui(lang, "ui.browse.back"))
|
|
|
355
355
|
ctx.settings.config.stromApp = answer === "no" ? "no" : "yes";
|
|
356
356
|
ctx.settings.save();
|
|
357
357
|
if (answer === "install") {
|
|
358
|
-
|
|
359
|
-
|
|
358
|
+
// a strom.app.url that is no address of the app: nothing opened, said how it stands (strom doctor says how to put it right)
|
|
359
|
+
const said = appUrlSetting(ctx.settings);
|
|
360
|
+
if (said.invalid)
|
|
361
|
+
ctx.io.stdout(ui(lang, said.invalid.source === "env" ? "ui.doc.appurl.env" : "ui.doc.appurl.config", { value: said.invalid.value }) + "\n");
|
|
362
|
+
else
|
|
363
|
+
ctx.io.stdout(ui(lang, openForUser(said.url, ctx.env) ? "ui.app.install" : "ui.app.url", { url: said.url }) + "\n");
|
|
360
364
|
}
|
|
361
365
|
return answer;
|
|
362
366
|
}
|
|
@@ -577,6 +577,9 @@ function haystack(r) {
|
|
|
577
577
|
Object.values(v).forEach(add);
|
|
578
578
|
};
|
|
579
579
|
const { id: _i, type: _t, created: _c, updated: _u, ...rest } = r;
|
|
580
|
+
// a person's titles ("Ing.", "ml.") are never searched as their name — the Strom app finds nobody by them either
|
|
581
|
+
if (r.type === "person")
|
|
582
|
+
rest.names = r.names.map(({ prefix: _p, suffix: _s, ...n }) => n);
|
|
580
583
|
add(rest);
|
|
581
584
|
return parts.join(" \u0001 ");
|
|
582
585
|
}
|
package/dist/commands/meta.js
CHANGED
|
@@ -5,7 +5,7 @@ import fs from "node:fs";
|
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { newerVersion } from "../core/update.js";
|
|
7
7
|
import { mb, tidyPlan, TIDY_SAID } from "../core/tidy.js";
|
|
8
|
-
import { appOpensResearch,
|
|
8
|
+
import { appOpensResearch, appUrlSetting, appUrlShown, installedStromApp } from "../core/stromapp.js";
|
|
9
9
|
import { register, commands, describe, GROUPS } from "../cli/registry.js";
|
|
10
10
|
import { UsageError } from "../core/errors.js";
|
|
11
11
|
import { helpAs } from "../cli/help.js";
|
|
@@ -88,7 +88,7 @@ function orientation(ctx) {
|
|
|
88
88
|
// What a conversation tells the user once, not again after it starts afresh (a new conversation, /clear): the Strom app, the stories, asking here.
|
|
89
89
|
const told = ctx.settings.config.told ?? {};
|
|
90
90
|
if (fs.existsSync(file))
|
|
91
|
-
base.results = { file, app: !wanted ? "not-wanted" : installedStromApp(ctx.env, process.platform,
|
|
91
|
+
base.results = { file, app: !wanted ? "not-wanted" : installedStromApp(ctx.env, process.platform, appUrlSetting(ctx.settings).url) ? "installed" : "offer", ...(told.app ? { told: true } : {}) };
|
|
92
92
|
const vision = ctx.settings.models(ctx.settings.agent(tree.config).value, tree.config).vision;
|
|
93
93
|
if (vision) {
|
|
94
94
|
const other = readByOtherModels(tree, vision);
|
|
@@ -185,7 +185,7 @@ register({
|
|
|
185
185
|
? appOpensResearch(ctx.settings) && !o.results.told ? "ui.o.results.installed.live" : "ui.o.results.installed"
|
|
186
186
|
: o.results.app === "offer"
|
|
187
187
|
? o.results.told ? "ui.o.results.offered" : appOpensResearch(ctx.settings) ? "ui.o.results.offer.live" : "ui.o.results.offer"
|
|
188
|
-
: "ui.o.results.plain", { file: ctx.display(o.results.file), url:
|
|
188
|
+
: "ui.o.results.plain", { file: ctx.display(o.results.file), url: appUrlSetting(ctx.settings).url }))
|
|
189
189
|
: undefined, archive ? row(t("ui.o.mode"), t("ui.o.mode.archive")) : undefined, o.stories && !archive ? row(t("ui.o.stories"), t(`ui.o.stories.${o.stories}`)) : undefined, o.ask && !archive ? row(t("ui.o.ask"), t("ui.o.ask.tell")) : undefined, o.reread && !archive ? row(t("ui.o.reread"), t("ui.o.reread.offer", { n: o.reread.facts, models: o.reread.models.join(", "), model: o.reread.model })) : undefined, o.researches?.length
|
|
190
190
|
? t("ui.o.research") + "\n" + table(o.researches.map((r) => [` ${r.id}`, r.name, `[${r.state}]`, r.focus]))
|
|
191
191
|
: t("ui.o.research.none"), o.working?.length
|
|
@@ -218,7 +218,7 @@ register({
|
|
|
218
218
|
group: "start",
|
|
219
219
|
args: [{ name: "filter", description: "only commands starting with these words, or of this group", variadic: true }],
|
|
220
220
|
examples: ["strom commands", "strom commands source --json", "strom commands analysis"],
|
|
221
|
-
run(
|
|
221
|
+
run(ctx, { args }) {
|
|
222
222
|
const words = args.flatMap((a) => a.split(/\s+/)).filter(Boolean);
|
|
223
223
|
const prefix = words.join(" ");
|
|
224
224
|
const defs = commands().filter((c) => c.path.length > 0 && (!prefix || c.group === prefix || c.path.join(" ") === prefix || c.path.join(" ").startsWith(`${prefix} `)));
|
|
@@ -231,7 +231,8 @@ register({
|
|
|
231
231
|
})
|
|
232
232
|
.filter(Boolean)
|
|
233
233
|
.join("\n\n");
|
|
234
|
-
|
|
234
|
+
const appUrl = appUrlShown(ctx.settings);
|
|
235
|
+
return { text, data: { version: VERSION, commands: defs.map((d) => describe(d, appUrl)), ...(appUrl.invalid ? { invalid: ["strom.app.url"] } : {}) } };
|
|
235
236
|
},
|
|
236
237
|
}, {
|
|
237
238
|
path: ["help"],
|
|
@@ -247,7 +248,7 @@ register({
|
|
|
247
248
|
// the agent's help, whoever asks — a person's only with --human (Milan, 2026-10-04); a person at a terminal is told
|
|
248
249
|
// how in a line of their language
|
|
249
250
|
const human = Boolean(input.opts.human) && !input.opts.agent;
|
|
250
|
-
const text = helpAs(input.args, { archive: ctx.archiveHere(), human, lang: ctx.uiLang(), pointer: !human && ctx.io.tty && !isAgent(ctx.env) });
|
|
251
|
+
const text = helpAs(input.args, { archive: ctx.archiveHere(), human, lang: ctx.uiLang(), appUrl: appUrlShown(ctx.settings), pointer: !human && ctx.io.tty && !isAgent(ctx.env) });
|
|
251
252
|
return { text, data: { help: text } };
|
|
252
253
|
},
|
|
253
254
|
});
|
package/dist/commands/setup.js
CHANGED
|
@@ -3,7 +3,7 @@ import { gitSize, lastCompacted } from "../core/history.js";
|
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { spawnSync } from "node:child_process";
|
|
6
|
-
import { register } from "../cli/registry.js";
|
|
6
|
+
import { APP_URL_INVALID_SETTING, register } from "../cli/registry.js";
|
|
7
7
|
import { lines, table } from "../cli/format.js";
|
|
8
8
|
import { checkValue, configFile, DEFAULT_BUDGET, DEFAULT_RUN_MINUTES, OTHER_ENV, SETTINGS, settingDef, writeStored } from "../core/config.js";
|
|
9
9
|
import { syncAgentFiles } from "../agents/files.js";
|
|
@@ -27,7 +27,7 @@ import { configDir, defaultHome, desktopDir, isolated, noLinks, ownCommand } fro
|
|
|
27
27
|
import { backupBefore, backupSaid, lastBackupLine } from "../cli/backups.js";
|
|
28
28
|
import { BACKUP_SAID_DAYS, lastBackup } from "../core/backup.js";
|
|
29
29
|
import { planMove, sameFolder } from "../core/relocate.js";
|
|
30
|
-
import { appOpensLinks,
|
|
30
|
+
import { appOpensLinks, appUrlSetting, researchUrl, stromAppUrl, stromAppState } from "../core/stromapp.js";
|
|
31
31
|
import { isInstalled } from "../agents/global.js";
|
|
32
32
|
import { offerLinks, shortcutName } from "../cli/wizard.js";
|
|
33
33
|
import { linkHandlerState, linkScheme } from "../core/links.js";
|
|
@@ -357,6 +357,11 @@ function diagnose(ctx) {
|
|
|
357
357
|
add("app", "ok", t("ui.doc.app.isolated"));
|
|
358
358
|
else
|
|
359
359
|
add("app", "ok", t(`ui.doc.app.${app}`), app === "unknown" ? FIX : undefined, app === "unknown" ? "app" : undefined);
|
|
360
|
+
// the copy of the app strom opens: a setting that says no address of it (STROM_APP_URL, or written by hand into the
|
|
361
|
+
// settings) is a problem said with its way out — doctor never fails on it (strom app refuses to open it)
|
|
362
|
+
const appUrl = appUrlSetting(ctx.settings).invalid;
|
|
363
|
+
if (appUrl)
|
|
364
|
+
add("appurl", "fail", t(appUrl.source === "env" ? "ui.doc.appurl.env" : "ui.doc.appurl.config", { value: appUrl.value }), appUrl.source === "env" ? undefined : placeholders(lang, "strom config set strom.app.url <address> · strom config unset strom.app.url"));
|
|
360
365
|
// …and whether it may start the research here (strom-research:// links): only while the app is wanted
|
|
361
366
|
if (app !== "no" && appOpensLinks(ctx.settings)) {
|
|
362
367
|
const links = linkHandlerState(ctx.env);
|
|
@@ -404,7 +409,8 @@ async function repair(ctx, checks, out) {
|
|
|
404
409
|
}
|
|
405
410
|
if (todo.has("links") && person)
|
|
406
411
|
await offerLinks(ctx, lang);
|
|
407
|
-
|
|
412
|
+
// (never into the address of an invalid strom.app.url: its check says how to put it right)
|
|
413
|
+
if (todo.has("app") && person && !appUrlSetting(ctx.settings).invalid && (await ctx.confirm(ui(lang, "ui.fix.app"), false))) {
|
|
408
414
|
openForUser(stromAppUrl(ctx.settings), ctx.env);
|
|
409
415
|
out(ui(lang, "ui.app.install"));
|
|
410
416
|
}
|
|
@@ -607,6 +613,15 @@ function treeSettings(ctx) {
|
|
|
607
613
|
/** Effective value of a setting, with the default filled in. */
|
|
608
614
|
function effective(ctx, def) {
|
|
609
615
|
const s = ctx.settings;
|
|
616
|
+
// the address of the Strom app: read as everything reads it (appUrlSetting) — never failing; one that is no address of
|
|
617
|
+
// the app is shown as found, marked invalid (B1-e)
|
|
618
|
+
if (def.key === "strom.app.url") {
|
|
619
|
+
const said = appUrlSetting(s);
|
|
620
|
+
if (said.invalid)
|
|
621
|
+
return { value: said.invalid.value, source: said.invalid.source, invalid: true };
|
|
622
|
+
const r = s.resolve(def.key);
|
|
623
|
+
return r ?? { value: said.url, source: "default" };
|
|
624
|
+
}
|
|
610
625
|
const tree = treeSettings(ctx);
|
|
611
626
|
if (def.key === "home")
|
|
612
627
|
return s.home() ?? { value: undefined, source: "unset" };
|
|
@@ -631,8 +646,6 @@ function effective(ctx, def) {
|
|
|
631
646
|
return { value: DEFAULT_RUN_MINUTES, source: "default" };
|
|
632
647
|
if (def.key === "connectors.consent")
|
|
633
648
|
return { value: "off", source: "default" };
|
|
634
|
-
if (def.key === "strom.app.url")
|
|
635
|
-
return { value: defaultAppUrl(ctx.env), source: "default" };
|
|
636
649
|
if (def.key === "browser.downloads")
|
|
637
650
|
return { value: downloadsDir(ctx.env), source: "detected" };
|
|
638
651
|
if (def.key === "agent.permissions")
|
|
@@ -749,10 +762,11 @@ register({
|
|
|
749
762
|
run(ctx) {
|
|
750
763
|
const rows = SETTINGS.map((def) => {
|
|
751
764
|
const r = effective(ctx, def);
|
|
752
|
-
return { key: def.key, value: r.value, source: r.source, env: def.env, tree: def.tree, description: def.description };
|
|
765
|
+
return { key: def.key, value: r.value, source: r.source, env: def.env, tree: def.tree, description: def.description, ...(r.invalid ? { invalid: true } : {}) };
|
|
753
766
|
});
|
|
754
|
-
const
|
|
755
|
-
|
|
767
|
+
const invalid = rows.filter((r) => r.invalid).map((r) => r.key);
|
|
768
|
+
const text = lines(table(rows.map((r) => [r.key, `${display(ctx, settingDef(r.key), r.value)}${r.invalid ? " (invalid)" : ""}`, r.source, r.env])), "", ...(invalid.length ? [APP_URL_INVALID_SETTING, ""] : []), "order: flag > env > tree (strom.json) > config > default", `change: strom config set <key> <value> [--for-tree] · strom config unset <key> [--for-tree]`, `other env: ${OTHER_ENV.map((e) => e.env).join(" ")} (strom help config where)`, `config file: ${ctx.display(configFile(ctx.env))}`);
|
|
769
|
+
return { text, data: { settings: rows, otherEnv: OTHER_ENV, file: configFile(ctx.env), ...(invalid.length ? { invalid } : {}) } };
|
|
756
770
|
},
|
|
757
771
|
description: "Settings a tree can carry (lang, agent, model.*, brief.budget, run.minutes) are set per tree with --for-tree.\n" +
|
|
758
772
|
OTHER_ENV.map((e) => `${e.env}: ${e.description}`).join("\n"),
|
|
@@ -764,7 +778,11 @@ register({
|
|
|
764
778
|
run(ctx, { args }) {
|
|
765
779
|
const def = settingDef(args[0]);
|
|
766
780
|
const r = effective(ctx, def);
|
|
767
|
-
|
|
781
|
+
const shown = r.value === undefined ? "" : display(ctx, def, r.value);
|
|
782
|
+
// a strom.app.url that is no address of the app: as found, and said so (B1-e)
|
|
783
|
+
if (r.invalid)
|
|
784
|
+
return { text: lines(`${shown} (invalid)`, APP_URL_INVALID_SETTING), data: { key: def.key, value: r.value, source: r.source, invalid: [def.key] } };
|
|
785
|
+
return { text: shown, data: { key: def.key, value: r.value, source: r.source } };
|
|
768
786
|
},
|
|
769
787
|
}, {
|
|
770
788
|
path: ["config", "set"],
|
|
@@ -778,7 +796,7 @@ register({
|
|
|
778
796
|
examples: ["strom config set lang cs", 'strom config set shared "/Volumes/Big/strom-shared"', "strom config set model.vision opus --for-tree", "strom config set run.minutes 45"],
|
|
779
797
|
run: async (ctx, { args, opts }) => {
|
|
780
798
|
const def = settingDef(args[0]);
|
|
781
|
-
const value = checkValue(def, args[1], (p) => ctx.resolvePath(p));
|
|
799
|
+
const value = checkValue(def, args[1], (p) => ctx.resolvePath(p), ctx.env);
|
|
782
800
|
// In their own terminal the user reads what full means and says yes once more.
|
|
783
801
|
if (def.key === "agent.permissions" && value === "full" && ctx.settings.agentPermissions() !== "full" && !opts["for-tree"] && ctx.interactive && !isAgent(ctx.env)) {
|
|
784
802
|
const lang = ctx.uiLang();
|
package/dist/commands/start.js
CHANGED
|
@@ -19,7 +19,7 @@ import { assertIntact } from "../core/integrity.js";
|
|
|
19
19
|
import { agentBrowser } from "../core/connector.js";
|
|
20
20
|
import { browserNote } from "./connectors.js";
|
|
21
21
|
import { offerLinks } from "../cli/wizard.js";
|
|
22
|
-
import { appOpensLinks, appOpensResearch, importAppUrl, installedStromApp, liveAppUrl,
|
|
22
|
+
import { appOpensLinks, appOpensResearch, appUrlSetting, importAppUrl, installedStromApp, liveAppUrl, liveAppUrlShown, noticeStromApp, stromAppUrl } from "../core/stromapp.js";
|
|
23
23
|
import { forgetLive, liveRunning, serveLive, startLive, stopLive } from "../core/live.js";
|
|
24
24
|
import { openForUser } from "../core/open.js";
|
|
25
25
|
import { createShortcut, openInNewTerminal } from "../core/shortcut.js";
|
|
@@ -72,6 +72,21 @@ function bridgeTree(ctx) {
|
|
|
72
72
|
const tree = ctx.tree();
|
|
73
73
|
return { root: tree.root, lang: tree.lang };
|
|
74
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* What strom live and live start say of the app that follows the bridge: its address — or, where strom.app.url says no
|
|
77
|
+
* address of the app, how that stands, and no address built on it with the bridge's secret (the bridge runs all the same).
|
|
78
|
+
*/
|
|
79
|
+
function liveAppLine(ctx, lang, bridge) {
|
|
80
|
+
const url = liveAppUrlShown(bridge, ctx.settings);
|
|
81
|
+
if (url)
|
|
82
|
+
return ui(lang, "ui.live.app", { url });
|
|
83
|
+
const bad = appUrlSetting(ctx.settings).invalid;
|
|
84
|
+
return ui(lang, bad.source === "env" ? "ui.doc.appurl.env" : "ui.doc.appurl.config", { value: bad.value });
|
|
85
|
+
}
|
|
86
|
+
function liveAppData(ctx, bridge) {
|
|
87
|
+
const url = liveAppUrlShown(bridge, ctx.settings);
|
|
88
|
+
return url ? { app: url } : {};
|
|
89
|
+
}
|
|
75
90
|
register({
|
|
76
91
|
path: ["chat"],
|
|
77
92
|
summary: "Talk with the AI agent about the research — in its desktop app or in this terminal, set up the way you chose",
|
|
@@ -209,7 +224,7 @@ register({
|
|
|
209
224
|
description: "In a tree, with an app that can take it (from its version 3.0.0), the app opens this research itself — the first time as\n" +
|
|
210
225
|
"a new tree, after that the same tree updated — and follows it while somebody is at work on it (the live bridge).\n" +
|
|
211
226
|
`Otherwise the results are ready for it in output/tree-strom.ged (in the app: Import). Each entry comes with its image,\n` +
|
|
212
|
-
`cut out of its scan (the settings excerpts.*; excerpts.for none: without). Web:
|
|
227
|
+
`cut out of its scan (the settings excerpts.*; excerpts.for none: without). Web: {appUrl}`,
|
|
213
228
|
options: [
|
|
214
229
|
{ name: "live", type: "boolean", description: "the app follows this research while it goes on (the live bridge)" },
|
|
215
230
|
{ name: "images", type: "boolean", description: "each entry with its image (the default; kept for older scripts)" },
|
|
@@ -217,6 +232,9 @@ register({
|
|
|
217
232
|
examples: ["strom app", "strom app --live", "strom app install"],
|
|
218
233
|
async run(ctx, { opts }) {
|
|
219
234
|
const lang = ctx.uiLang();
|
|
235
|
+
// a strom.app.url that is no address of the app (the variable, or written by hand into the settings): refused
|
|
236
|
+
// before anything starts — nothing opened, no address built on it with the bridge's secret (B1-c)
|
|
237
|
+
stromAppUrl(ctx.settings);
|
|
220
238
|
const root = appOpensResearch(ctx.settings) ? ctx.locateTree() : undefined;
|
|
221
239
|
if (root) {
|
|
222
240
|
const tree = Tree.open(root, ctx.env);
|
|
@@ -308,7 +326,7 @@ register({
|
|
|
308
326
|
const lang = tree.lang;
|
|
309
327
|
const info = liveRunning(tree.root);
|
|
310
328
|
return info
|
|
311
|
-
? { text: lines(ui(lang, "ui.live.runs", { url: info.url }),
|
|
329
|
+
? { text: lines(ui(lang, "ui.live.runs", { url: info.url }), liveAppLine(ctx, lang, info.url), ui(lang, "ui.live.stophow")), data: { running: true, ...info, ...liveAppData(ctx, info.url) } }
|
|
312
330
|
: { text: ui(lang, "ui.live.none"), data: { running: false } };
|
|
313
331
|
},
|
|
314
332
|
}, {
|
|
@@ -324,8 +342,8 @@ register({
|
|
|
324
342
|
if (!info)
|
|
325
343
|
throw new StromError("the bridge did not start", { hint: "strom live serve shows why", code: "live.not-started" });
|
|
326
344
|
return {
|
|
327
|
-
text: lines(ui(lang, "ui.live.runs", { url: info.url }),
|
|
328
|
-
data: { ...info,
|
|
345
|
+
text: lines(ui(lang, "ui.live.runs", { url: info.url }), liveAppLine(ctx, lang, info.url), info.moved ? ui(lang, "ui.live.moved") : undefined),
|
|
346
|
+
data: { ...info, ...liveAppData(ctx, info.url) },
|
|
329
347
|
};
|
|
330
348
|
},
|
|
331
349
|
}, {
|
package/dist/commands/sync.js
CHANGED
|
@@ -19,7 +19,7 @@ import { isArchive } from "../core/mode.js";
|
|
|
19
19
|
import { applySync, discardReceived, nothingSince, withoutImages, planSync, readTreeFile, receivedAll, receivedPending, receivedSince, receivedOf, settleReceived, SYNC_INBOX, syncConflicts, undoReceived, undoSync } from "../core/sync.js";
|
|
20
20
|
import { labels } from "../gedcom/labels.js";
|
|
21
21
|
import { startLive } from "../core/live.js";
|
|
22
|
-
import { appSendsChanges, sendAppUrl } from "../core/stromapp.js";
|
|
22
|
+
import { appSendsChanges, sendAppUrl, stromAppUrl } from "../core/stromapp.js";
|
|
23
23
|
import { appWindow, openAppIn, replaceGone } from "../core/appbrowser.js";
|
|
24
24
|
import { isAgent } from "../core/which.js";
|
|
25
25
|
/**
|
|
@@ -181,6 +181,8 @@ async function fromApp(ctx, tree, lang) {
|
|
|
181
181
|
const root = tree.root;
|
|
182
182
|
if (!appSendsChanges(ctx.settings))
|
|
183
183
|
return { text: ui(lang, "ui.sync.nosend") };
|
|
184
|
+
// a strom.app.url that is no address of the app: refused before the bridge starts — no address built on it (B1-c)
|
|
185
|
+
stromAppUrl(ctx.settings);
|
|
184
186
|
// what the app sends the bridge writes at once (unless the user reviews each send): what came of it is said, not shown to write
|
|
185
187
|
const atOnce = isArchive(tree) || !ctx.settings.syncReview(tree.config);
|
|
186
188
|
const info = startLive(root, ctx.env, { current: true });
|
package/dist/core/appbrowser.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// Never one it cannot reach strom from (Safari). A tree handed over (`holdsTree`: ?adopt=) waits in the storage of
|
|
7
7
|
// the browser it came from: there only — its app, else its tab — while that browser is here.
|
|
8
8
|
import { appBrowsers, browserKind, browserName, defaultBrowser, openInBrowser, openWebApp } from "./chromium.js";
|
|
9
|
-
import {
|
|
9
|
+
import { appUrlSetting, installedStromApps } from "./stromapp.js";
|
|
10
10
|
/**
|
|
11
11
|
* Where the Strom app opens on this computer — nothing when no browser here reaches strom. `holdsTree`: the address
|
|
12
12
|
* needs the app's storage in the browser its tree came from (a tree handed over), so another browser's app is no use.
|
|
@@ -14,7 +14,7 @@ import { installedStromApps, stromAppUrl } from "./stromapp.js";
|
|
|
14
14
|
export function appWindow(settings, env, platform = process.platform, opts = {}) {
|
|
15
15
|
const reach = appBrowsers(env, platform);
|
|
16
16
|
// the copies of the app (strom.app.url) installed from a browser that is here
|
|
17
|
-
const apps = installedStromApps(env, platform,
|
|
17
|
+
const apps = installedStromApps(env, platform, appUrlSetting(settings).url).filter((a) => a.appId && a.browser && reach.some((b) => b.name === a.browser));
|
|
18
18
|
const appOf = (b) => {
|
|
19
19
|
const a = b && apps.find((x) => x.browser === b.name);
|
|
20
20
|
return a?.appId && a.browser ? { browser: a.browser, appId: a.appId, ...(a.profile ? { profile: a.profile } : {}) } : undefined;
|