hiski-mcp 0.1.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/LICENSE +21 -0
- package/README.md +113 -0
- package/dist/client.js +152 -0
- package/dist/client.js.map +1 -0
- package/dist/data/seurakunnat.json +541 -0
- package/dist/encoding.js +21 -0
- package/dist/encoding.js.map +1 -0
- package/dist/hakutulos.js +206 -0
- package/dist/hakutulos.js.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/lomake.js +133 -0
- package/dist/lomake.js.map +1 -0
- package/dist/muotoilu.js +124 -0
- package/dist/muotoilu.js.map +1 -0
- package/dist/ohjeet.js +26 -0
- package/dist/ohjeet.js.map +1 -0
- package/dist/parishes.js +162 -0
- package/dist/parishes.js.map +1 -0
- package/dist/server.js +39 -0
- package/dist/server.js.map +1 -0
- package/dist/seurakuntasivu.js +125 -0
- package/dist/seurakuntasivu.js.map +1 -0
- package/dist/solu.js +18 -0
- package/dist/solu.js.map +1 -0
- package/dist/tapahtumasivu.js +187 -0
- package/dist/tapahtumasivu.js.map +1 -0
- package/dist/teksti.js +10 -0
- package/dist/teksti.js.map +1 -0
- package/dist/tyokalut.js +317 -0
- package/dist/tyokalut.js.map +1 -0
- package/dist/version.js +6 -0
- package/dist/version.js.map +1 -0
- package/package.json +73 -0
package/dist/encoding.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const latin1 = new TextDecoder("latin1");
|
|
2
|
+
/** Hiski serves its pages as ISO-8859-1. */
|
|
3
|
+
export function decodeLatin1(data) {
|
|
4
|
+
return latin1.decode(data);
|
|
5
|
+
}
|
|
6
|
+
const CLOUDFLARE_SKRIPTI = /<script>[^<]*__CF\$cv\$params[^]*?<\/script>/;
|
|
7
|
+
const CLOUDFLARE_SAHKOPOSTI = /<A HREF="\/cdn-cgi\/l\/email-protection#[0-9a-f]*"><span class="__cf_email__" data-cfemail="[0-9a-f]*">(\[email protected\])<\/span><\/A>/gi;
|
|
8
|
+
/**
|
|
9
|
+
* Removes what Cloudflare adds to every Hiski page with a per-request value:
|
|
10
|
+
* the challenge script and the obfuscated e-mail link. Otherwise saved
|
|
11
|
+
* fixtures would change on every download.
|
|
12
|
+
* Works on raw bytes: Node's "latin1" maps each byte to one character and back.
|
|
13
|
+
*/
|
|
14
|
+
export function poistaCloudflareLisaykset(sivu) {
|
|
15
|
+
const teksti = Buffer.from(sivu)
|
|
16
|
+
.toString("latin1")
|
|
17
|
+
.replace(CLOUDFLARE_SKRIPTI, "")
|
|
18
|
+
.replace(CLOUDFLARE_SAHKOPOSTI, "$1");
|
|
19
|
+
return new Uint8Array(Buffer.from(teksti, "latin1"));
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=encoding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encoding.js","sourceRoot":"","sources":["../src/encoding.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,GAAG,IAAI,WAAW,CAAC,QAAQ,CAAC,CAAC;AAEzC,4CAA4C;AAC5C,MAAM,UAAU,YAAY,CAAC,IAA8B;IACzD,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,kBAAkB,GAAG,8CAA8C,CAAC;AAC1E,MAAM,qBAAqB,GACzB,kJAAkJ,CAAC;AAErJ;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB,CAAC,IAAgB;IACxD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;SAC7B,QAAQ,CAAC,QAAQ,CAAC;SAClB,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;SAC/B,OAAO,CAAC,qBAAqB,EAAE,IAAI,CAAC,CAAC;IACxC,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;AACvD,CAAC"}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import * as cheerio from "cheerio";
|
|
2
|
+
import { SEURAKUNNAT } from "./parishes.js";
|
|
3
|
+
import { jasennaSolu } from "./solu.js";
|
|
4
|
+
import { siisti } from "./teksti.js";
|
|
5
|
+
export const HISKI_URL = "https://hiski.genealogia.fi/hiski";
|
|
6
|
+
const KIRJAT_OTSIKOSTA = {
|
|
7
|
+
kastetut: "kastetut",
|
|
8
|
+
vihityt: "vihityt",
|
|
9
|
+
haudatut: "haudatut",
|
|
10
|
+
sisäänmuuttaneet: "smuutt",
|
|
11
|
+
poismuuttaneet: "umuutt",
|
|
12
|
+
};
|
|
13
|
+
const LOHKON_OTSIKKO = /<FONT SIZE="\+2"><B>([^<]*)<\/B><\/FONT>/gi;
|
|
14
|
+
const TAULUKKO = /<TABLE BORDER=1[^>]*>[^]*?<\/TABLE>/gi;
|
|
15
|
+
const TAPAHTUMALINKKI = /\/hiski\?fi\+(\d{4})\+([a-z]+)\+(\d+)$/;
|
|
16
|
+
const EI_TIETOKANNASSA = "hakutekstiä ei löydy tietokannasta";
|
|
17
|
+
const MUUTON_SARAKKEET = [
|
|
18
|
+
"lahtopaiva",
|
|
19
|
+
"saapumispaiva",
|
|
20
|
+
"kyla",
|
|
21
|
+
"talo",
|
|
22
|
+
"henkilo",
|
|
23
|
+
"toinen_paikka",
|
|
24
|
+
];
|
|
25
|
+
/** Which event field each result column holds, per book. */
|
|
26
|
+
const SARAKKEET = {
|
|
27
|
+
kastetut: ["syntynyt", "kastettu", "kyla", "talo", "isa", "aiti", "lapsi"],
|
|
28
|
+
vihityt: [
|
|
29
|
+
"kuulutettu",
|
|
30
|
+
"vihitty",
|
|
31
|
+
"miehen_kyla",
|
|
32
|
+
"miehen_talo",
|
|
33
|
+
"mies",
|
|
34
|
+
"vaimo",
|
|
35
|
+
"vaimon_kyla",
|
|
36
|
+
"vaimon_talo",
|
|
37
|
+
],
|
|
38
|
+
haudatut: [
|
|
39
|
+
"kuollut",
|
|
40
|
+
"haudattu",
|
|
41
|
+
"kyla",
|
|
42
|
+
"talo",
|
|
43
|
+
"henkilo",
|
|
44
|
+
"kuolinsyy",
|
|
45
|
+
"ika.vuodet",
|
|
46
|
+
"ika.kuukaudet",
|
|
47
|
+
"ika.viikot",
|
|
48
|
+
"ika.paivat",
|
|
49
|
+
],
|
|
50
|
+
smuutt: MUUTON_SARAKKEET,
|
|
51
|
+
umuutt: MUUTON_SARAKKEET,
|
|
52
|
+
};
|
|
53
|
+
/** A trailing number or range after a person, e.g. the mother's age "25" or "25-30". */
|
|
54
|
+
const IKA_LOPUSSA = /^(.*?)\s*\b(\d+(?:-\d+)?)$/;
|
|
55
|
+
/** Parses a Hiski search result page into per-parish, per-book blocks. */
|
|
56
|
+
export function parseHakutulos(html) {
|
|
57
|
+
const otsikot = [...html.matchAll(LOHKON_OTSIKKO)];
|
|
58
|
+
// In an all-books search over several parishes Hiski leaves out the first
|
|
59
|
+
// parish's heading, so tables before the first heading form a block too.
|
|
60
|
+
const ennenOtsikoita = parseLohko(undefined, html.slice(0, otsikot[0]?.index ?? html.length));
|
|
61
|
+
const lohkot = otsikot.flatMap((otsikko, i) => {
|
|
62
|
+
const alku = otsikko.index + otsikko[0].length;
|
|
63
|
+
const loppu = otsikot[i + 1]?.index ?? html.length;
|
|
64
|
+
return parseLohko(otsikko[1], html.slice(alku, loppu));
|
|
65
|
+
});
|
|
66
|
+
const yhteensa = /Seurakunnista löytyi yhteensä (\d+) tapahtumaa/.exec(html)?.[1];
|
|
67
|
+
return {
|
|
68
|
+
lohkot: [...ennenOtsikoita, ...lohkot],
|
|
69
|
+
...(yhteensa && { yhteensa: Number(yhteensa) }),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* One heading may hold several tables: the "kaikki" search prints one per
|
|
74
|
+
* book. Each table becomes its own block.
|
|
75
|
+
*/
|
|
76
|
+
function parseLohko(otsikko, sisalto) {
|
|
77
|
+
const erotin = otsikko?.lastIndexOf(" - ") ?? -1;
|
|
78
|
+
const otsikonNimi = erotin >= 0 ? otsikko.slice(0, erotin) : otsikko;
|
|
79
|
+
const otsikonKirja = erotin >= 0 ? KIRJAT_OTSIKOSTA[otsikko.slice(erotin + 3)] : undefined;
|
|
80
|
+
const { hakutermit, huomautukset } = parseHakutermit(sisalto);
|
|
81
|
+
const taulukot = [...sisalto.matchAll(TAULUKKO)];
|
|
82
|
+
return taulukot.map((taulukko, i) => {
|
|
83
|
+
const perassa = sisalto.slice(taulukko.index + taulukko[0].length, taulukot[i + 1]?.index ?? sisalto.length);
|
|
84
|
+
const lomake = cheerio.load(perassa);
|
|
85
|
+
const kentta = (nimi) => lomake(`input[name="${nimi}" i]`).attr("value");
|
|
86
|
+
const kirja = kentta("kirja") ?? otsikonKirja;
|
|
87
|
+
const koodi = kentta("srk");
|
|
88
|
+
if (!kirja || !koodi) {
|
|
89
|
+
throw new Error(`Hakutuloksen lohkoa "${otsikko ?? "ilman otsikkoa"}" ei tunnistettu`);
|
|
90
|
+
}
|
|
91
|
+
// A block without a heading gets its name from the bundled parish list.
|
|
92
|
+
const nimi = otsikonNimi ?? SEURAKUNNAT.find((s) => s.koodi === koodi)?.koko_nimi ?? koodi;
|
|
93
|
+
const loytyiNoin = /Tapahtumia löytyi noin (\d+)/.exec(perassa)?.[1];
|
|
94
|
+
const jatkokohta = kentta("hakupos");
|
|
95
|
+
return {
|
|
96
|
+
seurakunta: { koodi, nimi },
|
|
97
|
+
kirja,
|
|
98
|
+
hakutermit,
|
|
99
|
+
...(huomautukset.length > 0 && { huomautukset }),
|
|
100
|
+
tapahtumat: parseTapahtumat(taulukko[0]),
|
|
101
|
+
katkaistu: /Loppuja tapahtumista ei näytetty/.test(perassa),
|
|
102
|
+
...(loytyiNoin && { loytyi_noin: Number(loytyiNoin) }),
|
|
103
|
+
...(jatkokohta && { jatkokohta }),
|
|
104
|
+
};
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
function parseHakutermit(sisalto) {
|
|
108
|
+
const hakutermit = [];
|
|
109
|
+
const huomautukset = [];
|
|
110
|
+
const $ = cheerio.load(sisalto.slice(0, sisalto.search(TAULUKKO)));
|
|
111
|
+
$("li").each((_, li) => {
|
|
112
|
+
const rivi = siisti($(li).text());
|
|
113
|
+
if (!rivi)
|
|
114
|
+
return;
|
|
115
|
+
const termi = /^(.+?): (.+?) => (.*)$/.exec(rivi);
|
|
116
|
+
if (!termi) {
|
|
117
|
+
huomautukset.push(rivi);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const [, kentta, haku, muodot] = termi;
|
|
121
|
+
hakutermit.push(muodot === EI_TIETOKANNASSA
|
|
122
|
+
? { kentta, haku, ei_tietokannassa: true }
|
|
123
|
+
: { kentta, haku, muodot: muodot.split(", ") });
|
|
124
|
+
});
|
|
125
|
+
return { hakutermit, huomautukset };
|
|
126
|
+
}
|
|
127
|
+
function parseTapahtumat(taulukko) {
|
|
128
|
+
const $ = cheerio.load(taulukko);
|
|
129
|
+
const tapahtumat = [];
|
|
130
|
+
$("tr").each((_, rivi) => {
|
|
131
|
+
const tapahtuma = parseTapahtumarivi($, rivi);
|
|
132
|
+
if (tapahtuma) {
|
|
133
|
+
tapahtumat.push(tapahtuma);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const edellinen = tapahtumat.at(-1);
|
|
137
|
+
if (edellinen)
|
|
138
|
+
liitaLisarivi($, rivi, edellinen);
|
|
139
|
+
});
|
|
140
|
+
return tapahtumat;
|
|
141
|
+
}
|
|
142
|
+
function parseTapahtumarivi($, rivi) {
|
|
143
|
+
const solut = $(rivi).children("td");
|
|
144
|
+
const href = solut.first().children("a").attr("href");
|
|
145
|
+
const linkki = href && TAPAHTUMALINKKI.exec(href);
|
|
146
|
+
if (!linkki)
|
|
147
|
+
return undefined;
|
|
148
|
+
const kirja = linkki[2];
|
|
149
|
+
const tapahtuma = {
|
|
150
|
+
kirja,
|
|
151
|
+
numero: Number(linkki[3]),
|
|
152
|
+
url: `${HISKI_URL}?fi+${linkki[1]}+${linkki[2]}+${linkki[3]}`,
|
|
153
|
+
};
|
|
154
|
+
const kenttakommentit = {};
|
|
155
|
+
SARAKKEET[kirja].forEach((kentta, i) => {
|
|
156
|
+
const { arvo, kommentit } = jasennaSolu($, solut.eq(i));
|
|
157
|
+
if (kommentit.length > 0)
|
|
158
|
+
kenttakommentit[kentta] = kommentit;
|
|
159
|
+
if (!arvo)
|
|
160
|
+
return;
|
|
161
|
+
// "ika.vuodet" etc. go into a nested object.
|
|
162
|
+
const [ylempi, alempi] = kentta.split(".");
|
|
163
|
+
if (alempi)
|
|
164
|
+
(tapahtuma[ylempi] ??= {})[alempi] = arvo;
|
|
165
|
+
else
|
|
166
|
+
tapahtuma[kentta] = arvo;
|
|
167
|
+
});
|
|
168
|
+
if (Object.keys(kenttakommentit).length > 0)
|
|
169
|
+
tapahtuma.kenttakommentit = kenttakommentit;
|
|
170
|
+
if (kirja === "kastetut")
|
|
171
|
+
erotaAidinIka(tapahtuma);
|
|
172
|
+
return tapahtuma;
|
|
173
|
+
}
|
|
174
|
+
function erotaAidinIka(tapahtuma) {
|
|
175
|
+
const osat = tapahtuma.aiti && IKA_LOPUSSA.exec(tapahtuma.aiti);
|
|
176
|
+
if (!osat)
|
|
177
|
+
return;
|
|
178
|
+
const aiti = siisti(osat[1]);
|
|
179
|
+
if (aiti)
|
|
180
|
+
tapahtuma.aiti = aiti;
|
|
181
|
+
else
|
|
182
|
+
delete tapahtuma.aiti;
|
|
183
|
+
tapahtuma.aidin_ika = osat[2];
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Attaches a row printed below an event to it: a comment row
|
|
187
|
+
* ("alkup - ALKUPKOMM: …") or, for burials, the relative ("omainen: …").
|
|
188
|
+
*/
|
|
189
|
+
function liitaLisarivi($, rivi, tapahtuma) {
|
|
190
|
+
const otsake = $(rivi).find("font").first();
|
|
191
|
+
const otsakkeenTeksti = siisti(otsake.text());
|
|
192
|
+
if (otsakkeenTeksti === "omainen:" && tapahtuma.kirja === "haudatut") {
|
|
193
|
+
const ilmanOtsaketta = $(rivi).clone();
|
|
194
|
+
ilmanOtsaketta.find("font").remove();
|
|
195
|
+
const omainen = siisti(ilmanOtsaketta.text());
|
|
196
|
+
if (omainen)
|
|
197
|
+
tapahtuma.omainen = omainen;
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
const merkinta = /^(\S+) - (.+?):$/.exec(otsakkeenTeksti ?? "");
|
|
201
|
+
const teksti = siisti($(rivi).find("small").first().text());
|
|
202
|
+
if (!merkinta || !teksti)
|
|
203
|
+
return;
|
|
204
|
+
(tapahtuma.kommentit ??= []).push({ tyyppi: merkinta[1], alikentta: merkinta[2], teksti });
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=hakutulos.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hakutulos.js","sourceRoot":"","sources":["../src/hakutulos.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
import { luoPalvelin } from "./server.js";
|
|
4
|
+
// Runs the Hiski MCP server over stdio, as MCP clients launch local servers.
|
|
5
|
+
await luoPalvelin().connect(new StdioServerTransport());
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,6EAA6E;AAC7E,MAAM,WAAW,EAAE,CAAC,OAAO,CAAC,IAAI,oBAAoB,EAAE,CAAC,CAAC"}
|
package/dist/lomake.js
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/** A search request that cannot be sent to Hiski; the message says why. */
|
|
2
|
+
export class LomakeVirhe extends Error {
|
|
3
|
+
constructor(viesti) {
|
|
4
|
+
super(viesti);
|
|
5
|
+
this.name = "LomakeVirhe";
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
const HENKILO = ["ietunimi", "ipatronyymi", "isukunimi", "iammatti", "ikyla"];
|
|
9
|
+
const OMAINEN = ["aetunimi", "apatronyymi", "asukunimi", "aammatti"];
|
|
10
|
+
/** The fields on each book's search form. */
|
|
11
|
+
const KENTAT = {
|
|
12
|
+
kastetut: new Set(["etunimi", ...HENKILO, ...OMAINEN]),
|
|
13
|
+
vihityt: new Set([...HENKILO, ...OMAINEN, "akyla"]),
|
|
14
|
+
haudatut: new Set([...HENKILO, ...OMAINEN, "ksyy", "syntalku", "syntloppu", "ika"]),
|
|
15
|
+
smuutt: new Set([...HENKILO, "kohde"]),
|
|
16
|
+
umuutt: new Set([...HENKILO, "kohde"]),
|
|
17
|
+
kaikki: new Set([...HENKILO, "vapaaAND", "vapaaNOT"]),
|
|
18
|
+
};
|
|
19
|
+
/** Fields holding a date in the same format as the years. */
|
|
20
|
+
const PAIVAMAARAKENTAT = new Set(["syntalku", "syntloppu"]);
|
|
21
|
+
const MAKSIMIT = [15, 30, 50, 100, 250, 500, 1000];
|
|
22
|
+
const OLETUSMAKSIMI = 50;
|
|
23
|
+
/** Hiski's input fields accept at most this many characters. */
|
|
24
|
+
const KENTAN_PITUUS = 30;
|
|
25
|
+
/** Characters a browser leaves unescaped in a form body. */
|
|
26
|
+
const SELLAISENAAN = /[A-Za-z0-9*\-._]/;
|
|
27
|
+
/**
|
|
28
|
+
* Encodes form fields as application/x-www-form-urlencoded in ISO-8859-1,
|
|
29
|
+
* which Hiski expects (URLSearchParams would encode UTF-8, and Hiski would
|
|
30
|
+
* then search for "Bärnilä").
|
|
31
|
+
*/
|
|
32
|
+
export function koodaaLatin1(kentat) {
|
|
33
|
+
return kentat.map(([nimi, arvo]) => `${koodaa(nimi)}=${koodaa(arvo)}`).join("&");
|
|
34
|
+
}
|
|
35
|
+
function koodaa(teksti) {
|
|
36
|
+
let tulos = "";
|
|
37
|
+
// Composed form turns "a" + combining diaeresis into the single latin-1 letter "ä".
|
|
38
|
+
for (const merkki of teksti.normalize("NFC")) {
|
|
39
|
+
const koodi = merkki.codePointAt(0);
|
|
40
|
+
if (merkki === " ")
|
|
41
|
+
tulos += "+";
|
|
42
|
+
else if (SELLAISENAAN.test(merkki))
|
|
43
|
+
tulos += merkki;
|
|
44
|
+
else if (koodi <= 0xff)
|
|
45
|
+
tulos += `%${koodi.toString(16).toUpperCase().padStart(2, "0")}`;
|
|
46
|
+
else
|
|
47
|
+
throw new LomakeVirhe(`Merkkiä "${merkki}" ei voi hakea Hiskistä.`);
|
|
48
|
+
}
|
|
49
|
+
return tulos;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Checks a year or date in a format Hiski understands: vvvv, kk.vvvv or
|
|
53
|
+
* pp.kk.vvvv. Hiski silently ignores anything else and searches all years.
|
|
54
|
+
*/
|
|
55
|
+
export function tarkistaVuosi(arvo, kentta) {
|
|
56
|
+
const virhe = () => new LomakeVirhe(`${kentta} "${arvo}" ei kelpaa. Käytä muotoa vvvv, kk.vvvv tai pp.kk.vvvv (esim. 1834, 5.1834 tai 21.9.1834).`);
|
|
57
|
+
const osat = /^(?:(?:(\d{1,2})\.)?(\d{1,2})\.)?(\d{4})$/.exec(arvo);
|
|
58
|
+
if (!osat)
|
|
59
|
+
throw virhe();
|
|
60
|
+
const [, paiva, kuukausi, vuosi] = osat;
|
|
61
|
+
if (kuukausi === undefined)
|
|
62
|
+
return;
|
|
63
|
+
const kk = Number(kuukausi);
|
|
64
|
+
if (kk < 1 || kk > 12)
|
|
65
|
+
throw virhe();
|
|
66
|
+
if (paiva === undefined)
|
|
67
|
+
return;
|
|
68
|
+
const pv = Number(paiva);
|
|
69
|
+
const paiviaKuussa = new Date(Date.UTC(Number(vuosi), kk, 0)).getUTCDate();
|
|
70
|
+
if (pv < 1 || pv > paiviaKuussa)
|
|
71
|
+
throw virhe();
|
|
72
|
+
}
|
|
73
|
+
/** The smallest per-parish maximum Hiski offers that is at least n (at most 1000). */
|
|
74
|
+
export function pyoristaMaksimi(n) {
|
|
75
|
+
return MAKSIMIT.find((m) => m >= n) ?? MAKSIMIT.at(-1);
|
|
76
|
+
}
|
|
77
|
+
/** Validates a search and returns the form fields to send to Hiski. */
|
|
78
|
+
export function rakennaHakulomake(pyynto) {
|
|
79
|
+
const { kirja, seurakunnat, kentat = {}, alkuvuosi, loppuvuosi, jatkokohta } = pyynto;
|
|
80
|
+
if (!Object.hasOwn(KENTAT, kirja))
|
|
81
|
+
throw new LomakeVirhe(`Kirjalla "${kirja}" ei ole hakua.`);
|
|
82
|
+
const maksimi = pyynto.maksimi ?? OLETUSMAKSIMI;
|
|
83
|
+
if (!Number.isFinite(maksimi) || maksimi < 1) {
|
|
84
|
+
throw new LomakeVirhe(`maksimi ${maksimi} ei kelpaa; anna positiivinen luku.`);
|
|
85
|
+
}
|
|
86
|
+
if (seurakunnat.length === 0)
|
|
87
|
+
throw new LomakeVirhe("Anna vähintään yksi seurakunta.");
|
|
88
|
+
for (const koodi of seurakunnat) {
|
|
89
|
+
if (!/^\d{4}$/.test(koodi)) {
|
|
90
|
+
throw new LomakeVirhe(`Seurakuntakoodi "${koodi}" ei kelpaa; koodissa on neljä numeroa.`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (jatkokohta !== undefined) {
|
|
94
|
+
if (seurakunnat.length !== 1) {
|
|
95
|
+
throw new LomakeVirhe("Hakua voi jatkaa vain yhden seurakunnan osalta kerrallaan.");
|
|
96
|
+
}
|
|
97
|
+
if (!/^\d+$/.test(jatkokohta))
|
|
98
|
+
throw new LomakeVirhe(`jatkokohta "${jatkokohta}" ei kelpaa.`);
|
|
99
|
+
}
|
|
100
|
+
const lomake = [
|
|
101
|
+
["komento", "haku"],
|
|
102
|
+
["srk", seurakunnat.join(",")],
|
|
103
|
+
["kirja", kirja],
|
|
104
|
+
["kieli", "fi"],
|
|
105
|
+
["maxkpl", String(pyoristaMaksimi(maksimi))],
|
|
106
|
+
];
|
|
107
|
+
const vuodet = { alkuvuosi: alkuvuosi?.trim(), loppuvuosi: loppuvuosi?.trim() };
|
|
108
|
+
for (const [nimi, arvo] of Object.entries(vuodet)) {
|
|
109
|
+
if (!arvo)
|
|
110
|
+
continue;
|
|
111
|
+
tarkistaVuosi(arvo, nimi);
|
|
112
|
+
lomake.push([nimi, arvo]);
|
|
113
|
+
}
|
|
114
|
+
for (const [nimi, raaka] of Object.entries(kentat)) {
|
|
115
|
+
// Composed form, so that a decomposed "ä" counts as one letter.
|
|
116
|
+
const arvo = raaka?.normalize("NFC").trim();
|
|
117
|
+
if (!arvo)
|
|
118
|
+
continue;
|
|
119
|
+
if (!KENTAT[kirja].has(nimi)) {
|
|
120
|
+
throw new LomakeVirhe(`Kenttää "${nimi}" ei ole kirjan ${kirja} hakulomakkeella.`);
|
|
121
|
+
}
|
|
122
|
+
if (arvo.length > KENTAN_PITUUS) {
|
|
123
|
+
throw new LomakeVirhe(`Kentän "${nimi}" arvo on liian pitkä (enintään ${KENTAN_PITUUS} merkkiä).`);
|
|
124
|
+
}
|
|
125
|
+
if (PAIVAMAARAKENTAT.has(nimi))
|
|
126
|
+
tarkistaVuosi(arvo, nimi);
|
|
127
|
+
lomake.push([nimi, arvo]);
|
|
128
|
+
}
|
|
129
|
+
if (jatkokohta !== undefined)
|
|
130
|
+
lomake.push(["hakupos", jatkokohta]);
|
|
131
|
+
return lomake;
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=lomake.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lomake.js","sourceRoot":"","sources":["../src/lomake.ts"],"names":[],"mappings":"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"}
|
package/dist/muotoilu.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { HiskiVirhe } from "./client.js";
|
|
2
|
+
import { LomakeVirhe } from "./lomake.js";
|
|
3
|
+
import { SeurakuntaVirhe } from "./parishes.js";
|
|
4
|
+
/** "1697–1710, 1718–1890": compact for the agent, unlike a list of objects. */
|
|
5
|
+
export function vuodetTekstiksi(valit) {
|
|
6
|
+
return valit.map((v) => (v.alku === v.loppu ? `${v.alku}` : `${v.alku}–${v.loppu}`)).join(", ");
|
|
7
|
+
}
|
|
8
|
+
/** Years per book as text, leaving out the books a parish does not have. */
|
|
9
|
+
export function kirjojenVuodet(vuodet) {
|
|
10
|
+
return Object.fromEntries(Object.entries(vuodet)
|
|
11
|
+
.filter(([, valit]) => valit.length > 0)
|
|
12
|
+
.map(([kirja, valit]) => [kirja, vuodetTekstiksi(valit)]));
|
|
13
|
+
}
|
|
14
|
+
/** An expected failure of a tool whose message the agent can act on. */
|
|
15
|
+
export class TyokaluVirhe extends Error {
|
|
16
|
+
constructor(viesti) {
|
|
17
|
+
super(viesti);
|
|
18
|
+
this.name = "TyokaluVirhe";
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const ILMOITA_ONGELMASTA = "https://github.com/jleh/hiski-mcp/issues";
|
|
22
|
+
/** The text the agent sees for an error, with a next step where one helps. */
|
|
23
|
+
export function virheViesti(virhe) {
|
|
24
|
+
if (virhe instanceof SeurakuntaVirhe) {
|
|
25
|
+
return `${virhe.message} Seurakuntia voi etsiä etsi_seurakunta-työkalulla; koodilla ("0366") valinta on yksiselitteinen.`;
|
|
26
|
+
}
|
|
27
|
+
if (virhe instanceof LomakeVirhe ||
|
|
28
|
+
virhe instanceof HiskiVirhe ||
|
|
29
|
+
virhe instanceof TyokaluVirhe) {
|
|
30
|
+
return virhe.message;
|
|
31
|
+
}
|
|
32
|
+
// Anything else means Hiski's page was not what the parsers expect.
|
|
33
|
+
const syy = virhe instanceof Error ? virhe.message : String(virhe);
|
|
34
|
+
return `Hiskin sivu oli odottamattoman muotoinen (${syy}). Hiski on voinut muuttua; ongelmasta voi ilmoittaa: ${ILMOITA_ONGELMASTA}`;
|
|
35
|
+
}
|
|
36
|
+
const KIRJAN_NIMI = {
|
|
37
|
+
kastetut: "kastetut",
|
|
38
|
+
vihityt: "vihityt",
|
|
39
|
+
haudatut: "haudatut",
|
|
40
|
+
smuutt: "sisäänmuuttaneet",
|
|
41
|
+
umuutt: "poismuuttaneet",
|
|
42
|
+
kaikki: "kaikki kirjat",
|
|
43
|
+
};
|
|
44
|
+
/** The year of "vvvv", "kk.vvvv" or "pp.kk.vvvv". */
|
|
45
|
+
const vuosiluku = (arvo) => {
|
|
46
|
+
const teksti = arvo?.trim();
|
|
47
|
+
return teksti ? Number(teksti.slice(-4)) : undefined;
|
|
48
|
+
};
|
|
49
|
+
/** The single-book tool for a book in an all-books result. */
|
|
50
|
+
const KIRJAN_TYOKALU = {
|
|
51
|
+
kastetut: "hae_kastetut",
|
|
52
|
+
vihityt: "hae_vihityt",
|
|
53
|
+
haudatut: "hae_haudatut",
|
|
54
|
+
smuutt: "hae_muuttaneet (suunta sisaan)",
|
|
55
|
+
umuutt: "hae_muuttaneet (suunta pois)",
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* The search result as the agent gets it, with notes. In an all-books search
|
|
59
|
+
* Hiski's continuation point belongs to one book's search, not to the
|
|
60
|
+
* all-books search, so it is left out there.
|
|
61
|
+
*/
|
|
62
|
+
export function muotoileHakutulos(tulos, pyynto) {
|
|
63
|
+
const lohkot = pyynto.kirja === "kaikki"
|
|
64
|
+
? tulos.lohkot.map((lohko) => {
|
|
65
|
+
const kopio = { ...lohko };
|
|
66
|
+
delete kopio.jatkokohta;
|
|
67
|
+
return kopio;
|
|
68
|
+
})
|
|
69
|
+
: tulos.lohkot;
|
|
70
|
+
const valmis = { ...tulos, lohkot };
|
|
71
|
+
const huomautukset = hakutuloksenHuomautukset(valmis, pyynto);
|
|
72
|
+
return { ...valmis, ...(huomautukset.length > 0 && { huomautukset }) };
|
|
73
|
+
}
|
|
74
|
+
function hakutuloksenHuomautukset(tulos, pyynto) {
|
|
75
|
+
const huomautukset = [];
|
|
76
|
+
const kirjanNimi = KIRJAN_NIMI[pyynto.kirja] ?? pyynto.kirja;
|
|
77
|
+
for (const lohko of tulos.lohkot) {
|
|
78
|
+
if (!lohko.katkaistu)
|
|
79
|
+
continue;
|
|
80
|
+
const { nimi, koodi } = lohko.seurakunta;
|
|
81
|
+
const noin = lohko.loytyi_noin === undefined ? "" : `, löytyi noin ${lohko.loytyi_noin}`;
|
|
82
|
+
const jatko = lohko.jatkokohta
|
|
83
|
+
? ` Hakua voi jatkaa antamalla jatkokohta "${lohko.jatkokohta}" samalla haulla pelkälle seurakunnalle ${koodi}, tai hakua voi rajata.`
|
|
84
|
+
: pyynto.kirja === "kaikki"
|
|
85
|
+
? ` Hakua voi rajata tai hakea kirjan omalla työkalulla ${KIRJAN_TYOKALU[lohko.kirja] ?? ""} suuremmalla maksimilla.`
|
|
86
|
+
: " Hakua voi rajata tai maksimia kasvattaa.";
|
|
87
|
+
huomautukset.push(`${nimi} (${KIRJAN_NIMI[lohko.kirja] ?? lohko.kirja}): näytettiin ${lohko.tapahtumat.length}${noin}.${jatko}`);
|
|
88
|
+
}
|
|
89
|
+
// The same word is listed once per parish block; mention it once.
|
|
90
|
+
const tuntemattomat = new Set();
|
|
91
|
+
for (const lohko of tulos.lohkot) {
|
|
92
|
+
for (const termi of lohko.hakutermit) {
|
|
93
|
+
if ("ei_tietokannassa" in termi)
|
|
94
|
+
tuntemattomat.add(`${termi.haku} (${termi.kentta})`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
for (const kuvaus of tuntemattomat) {
|
|
98
|
+
huomautukset.push(`Hakusanaa ${kuvaus} ei ole Hiskin tietokannassa; kirjoitusasu voi olla toinen.`);
|
|
99
|
+
}
|
|
100
|
+
const palautetut = new Set(tulos.lohkot.map((l) => l.seurakunta.koodi));
|
|
101
|
+
for (const seurakunta of pyynto.seurakunnat) {
|
|
102
|
+
if (palautetut.has(seurakunta.koodi))
|
|
103
|
+
continue;
|
|
104
|
+
const vuodet = seurakunta.vuodet[pyynto.kirja];
|
|
105
|
+
huomautukset.push(vuodet && vuodet.length === 0
|
|
106
|
+
? `Seurakunnalla ${seurakunta.nimi} (${seurakunta.koodi}) ei ole Hiskissä kirjaa ${kirjanNimi}.`
|
|
107
|
+
: `Hiski ei palauttanut tuloksia seurakunnalle ${seurakunta.nimi} (${seurakunta.koodi}).`);
|
|
108
|
+
}
|
|
109
|
+
const alku = vuosiluku(pyynto.alkuvuosi);
|
|
110
|
+
const loppu = vuosiluku(pyynto.loppuvuosi);
|
|
111
|
+
if (alku !== undefined || loppu !== undefined) {
|
|
112
|
+
for (const seurakunta of pyynto.seurakunnat) {
|
|
113
|
+
const vuodet = seurakunta.vuodet[pyynto.kirja];
|
|
114
|
+
if (!vuodet || vuodet.length === 0)
|
|
115
|
+
continue;
|
|
116
|
+
const osuu = vuodet.some((v) => (alku === undefined || v.loppu >= alku) && (loppu === undefined || v.alku <= loppu));
|
|
117
|
+
if (!osuu) {
|
|
118
|
+
huomautukset.push(`Seurakunnan ${seurakunta.nimi} ${kirjanNimi} on Hiskissä vuosilta ${vuodetTekstiksi(vuodet)}; haettu väli ${alku ?? ""}–${loppu ?? ""} on niiden ulkopuolella.`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return huomautukset;
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=muotoilu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"muotoilu.js","sourceRoot":"","sources":["../src/muotoilu.ts"],"names":[],"mappings":"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"}
|
package/dist/ohjeet.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guidance for the agent, sent as the server's `instructions`. Tool
|
|
3
|
+
* descriptions stay factual; how to search well lives here.
|
|
4
|
+
*/
|
|
5
|
+
export const OHJEET = `HisKi on Suomen Sukututkimusseuran tietokanta, johon on tallennettu seurakuntien historiakirjojen tapahtumia: kastetut, vihityt, haudatut sekä sisään- ja poismuuttaneet. Tiedot ovat alkuperäisessä kirjoitusasussa, usein ruotsiksi.
|
|
6
|
+
|
|
7
|
+
Aineiston rajat:
|
|
8
|
+
- Aineisto ulottuu 1600-luvulta monessa seurakunnassa 1900-luvun alkupuolelle, mutta näkyvissä ovat vain yli 100 vuotta vanhat tapahtumat. Kunkin seurakunnan ja kirjan indeksoidut vuodet kertovat etsi_seurakunta ja seurakunnan_tiedot; aineisto voi olla vajaa niidenkin sisällä.
|
|
9
|
+
- Tyhjä tulos ei todista, ettei tapahtumaa ole. Silloin voi kokeilla toista kirjoitusasua, naapuriseurakuntia (seurakunnan_tiedot), emäseurakuntaa tai toista kirjaa (esim. vihityt, kun kastetta ei löydy).
|
|
10
|
+
- Luovutetun Karjalan seurakuntien historiakirjat on pääosin tallennettu Karjala-tietokantasäätiön tietokantaan, ei Hiskiin.
|
|
11
|
+
- Tallennuksessa voi olla virheitä; löydöt kannattaa tarkistaa alkuperäislähteestä (SSHY-digiarkiston linkki hae_tapahtuma-tuloksessa).
|
|
12
|
+
|
|
13
|
+
Hakusanat:
|
|
14
|
+
- Nimet haetaan nykyisellä perusmuodolla; Hiski löytää myös vanhat ja ruotsinkieliset muodot (Johan löytää myös Juho, Johannes). Tuloksen hakutermit kertovat, mitä muotoja haettiin, ja jos hakusanaa ei ole tietokannassa.
|
|
15
|
+
- Useampi etunimi välilyönnillä tarkoittaa, että kaikkien on löydyttävä (enintään 3). Vaihtoehdot erotetaan sanalla TAI, esim. "Jussi TAI Matti".
|
|
16
|
+
- Patronyymi toimii päätteen kanssa tai ilman (Johan, Johansson, Juhonpoika); varmin on ruotsinkielinen -son/-dr.
|
|
17
|
+
- Sukunimien normalisointi on puutteellinen: noin 5 alkukirjainta toimii usein parhaiten (Manko löytää Mankonen ja Mankoin). Länsi-Suomessa sukunimeä ei usein ollut, ja sukunimikenttään on voitu kirjata talon nimi.
|
|
18
|
+
- Paikannimiä ei ole normalisoitu kattavasti; alkuperäinen kirjoitusasu tai sanan alku toimii usein paremmin. Kylien nimet ovat kirjoissa usein ruotsiksi tai vanhassa asussa (Niemi → Njemis); seurakunnan_tiedot listaa kylät.
|
|
19
|
+
- Hakusanan loppuun lisätään automaattisesti jokeri: "Kuona" löytää myös "Kuonan torppa". Piste lopussa hakee tarkasti ("Berg."). * on mikä tahansa merkkijono ja ? yksi merkki; sanan alussa oleva jokeri on hidas usean seurakunnan haussa. $ alussa hyväksyy myös tapahtumat, joissa kenttä on tyhjä ("$Mikkola").
|
|
20
|
+
|
|
21
|
+
Hakutapa:
|
|
22
|
+
- Kun seurakunta tiedetään, haku yhdestä seurakunnasta on nopein ja tarkin. Usean seurakunnan haussa ehtoja kannattaa tarkentaa ja pitää maksimi pienenä; seurakuntien määrä × maksimi saa olla enintään 1000.
|
|
23
|
+
- Hakutuloksessa henkilö on yksi merkkijono (ammatti ja nimet yhdessä); hae_tapahtuma antaa ammatin, etunimen, patronyymin, sukunimen ja iän eriteltyinä sekä kommentit.
|
|
24
|
+
- Katkaistun tuloksen voi jatkaa jatkokohdalla samalla haulla samalle seurakunnalle. hae_kaikki-hakua ei voi jatkaa; sen katkennutta kirjaa voi hakea kirjan omalla työkalulla.
|
|
25
|
+
- hae_kaikki hakee henkilöä kaikista kirjoista kerralla; se sopii ensimmäiseksi hauksi, kun tiedossa on vain nimi ja seurakunta.`;
|
|
26
|
+
//# sourceMappingURL=ohjeet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ohjeet.js","sourceRoot":"","sources":["../src/ohjeet.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;iIAoB2G,CAAC"}
|