bps-mcp-server 0.17.0 → 0.18.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.
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEnD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAiD/D,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,aAAa,EACnB,KAAK,EAAE,cAAc,GAAG,IAAI,EAC5B,KAAK,CAAC,EAAE,gBAAgB,GAAG,IAAI,EAC/B,OAAO,CAAC,EAAE,MAAM,GACf;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,cAAc,CAAA;CAAE,CAgDpE"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEnD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAqD/D,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,aAAa,EACnB,KAAK,EAAE,cAAc,GAAG,IAAI,EAC5B,KAAK,CAAC,EAAE,gBAAgB,GAAG,IAAI,EAC/B,OAAO,CAAC,EAAE,MAAM,GACf;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,cAAc,CAAA;CAAE,CAgDpE"}
package/dist/server.js CHANGED
@@ -38,10 +38,14 @@ ATURAN ROUTING (penting, hemat panggilan):
38
38
  - level="provinsi" untuk peringkat provinsi.
39
39
  JANGAN menyusun peringkat kabupaten/kota manual dengan list_variables /
40
40
  get_dynamic_data per provinsi: hasilnya 100+ panggilan dan tahunnya campur.
41
- 2. Angka satu wilayah ("pengangguran Jawa Timur") -> find_data.
42
- 3. Bandingkan 2+ wilayah -> compare_data. Tren multi-tahun -> get_trend.
43
- 4. Butuh angka mentah dari var_id yang sudah diketahui -> get_dynamic_data
44
- (pakai format="json" bila hasilnya akan diolah lagi).
41
+ 2. Angka satu wilayah ("pengangguran Jawa Timur") -> find_data; tren satu wilayah -> get_trend.
42
+ 3. Bandingkan 2+ wilayah -> compare_data. Perbandingan multi-tahun
43
+ ("5 tahun terakhir") juga compare_data: isi years="2021-2025" atau
44
+ start_year/end_year — satu panggilan menghasilkan tabel wilayah x tahun.
45
+ JANGAN memanggil get_trend per wilayah untuk perbandingan.
46
+ 4. Butuh angka mentah dari var_id yang sudah diketahui -> get_dynamic_data.
47
+ Parameter th menerima TAHUN langsung ('2021-2025'), tidak perlu list_periods.
48
+ Pakai format="json" bila hasilnya akan diolah lagi.
45
49
  5. Mencari variabel/tabel/publikasi -> find_variable, search, allstats_search.
46
50
 
47
51
  CATATAN DATA: periode antar provinsi tidak seragam (2024-2026). Selalu sebutkan
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { BpsClient } from "../client/bps-client.js";
2
+ export interface YearSpec {
3
+ /** True when the caller supplied anything at all. */
4
+ hasSpec: boolean;
5
+ /** Years requested, ascending. */
6
+ years: string[];
7
+ /** Tokens that are not years (assumed to be raw period IDs). */
8
+ periodIds: string[];
9
+ }
10
+ /** Parse "2021,2022", "2021;2022", "2021-2025", "2021 s.d. 2025" or raw IDs. */
11
+ export declare function parseYearSpec(spec?: string | null): YearSpec;
12
+ export interface ResolvedPeriodEntry {
13
+ id: string;
14
+ label: string;
15
+ year?: string;
16
+ }
17
+ export interface ResolvedPeriodsForSpec {
18
+ hasSpec: boolean;
19
+ entries: ResolvedPeriodEntry[];
20
+ missingYears: string[];
21
+ /** Years the variable actually has data for, ascending. */
22
+ availableYears: string[];
23
+ /** Up to 12 recent period labels, for error messages. */
24
+ availableLabels: string[];
25
+ }
26
+ export declare function resolvePeriodsForSpec(client: BpsClient, domain: string, varId: number, spec?: string | null): Promise<ResolvedPeriodsForSpec>;
27
+ /** Human readable note about years that had no data. */
28
+ export declare function describeMissingYears(missing: string[], available: string[]): string;
29
+ //# sourceMappingURL=period-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"period-resolver.d.ts","sourceRoot":"","sources":["../../src/services/period-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAazD,MAAM,WAAW,QAAQ;IACvB,qDAAqD;IACrD,OAAO,EAAE,OAAO,CAAC;IACjB,kCAAkC;IAClC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,gEAAgE;IAChE,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,gFAAgF;AAChF,wBAAgB,aAAa,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,QAAQ,CAsC5D;AAgBD,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,2DAA2D;IAC3D,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,yDAAyD;IACzD,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAgBD,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,GACnB,OAAO,CAAC,sBAAsB,CAAC,CAqEjC;AAED,wDAAwD;AACxD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAMnF"}
@@ -0,0 +1,132 @@
1
+ import { getPeriodId, getPeriodLabel, isNeutralPeriodLabel } from "../client/fields.js";
2
+ /**
3
+ * BPS' WebAPI only accepts period *IDs* (`th`) — never years. Agents naturally
4
+ * pass "2021,2022" or "2021-2025", which the API silently answers with an empty
5
+ * dataset. This module maps human year specs to period IDs so no caller has to
6
+ * call `list_periods` first.
7
+ */
8
+ const YEAR_PATTERN = /^(19|20)\d{2}$/;
9
+ /** Parse "2021,2022", "2021;2022", "2021-2025", "2021 s.d. 2025" or raw IDs. */
10
+ export function parseYearSpec(spec) {
11
+ if (!spec || !spec.trim())
12
+ return { hasSpec: false, years: [], periodIds: [] };
13
+ // Normalize word-based ranges ("2021 s.d. 2023", "2021 sampai 2023") so the
14
+ // whitespace split below does not separate the endpoints.
15
+ const normalizedSpec = spec.replace(/((?:19|20)\d{2})\s*(?:s\.?\s*d\.?|sampai|hingga|to)\s*((?:19|20)\d{2})/gi, "$1-$2");
16
+ const tokens = normalizedSpec
17
+ .split(/[,;|]+|\s+/)
18
+ .map((token) => token.trim())
19
+ .filter(Boolean);
20
+ const years = new Set();
21
+ const periodIds = new Set();
22
+ for (const token of tokens) {
23
+ const range = token.match(/^((?:19|20)\d{2})\s*(?:-|–|—|s\.?\s*d\.?|sampai|hingga|to)\s*((?:19|20)\d{2})$/i);
24
+ if (range) {
25
+ const start = Number(range[1]);
26
+ const end = Number(range[2]);
27
+ if (Number.isFinite(start) && Number.isFinite(end) && end >= start && end - start <= 60) {
28
+ for (let year = start; year <= end; year++)
29
+ years.add(String(year));
30
+ }
31
+ continue;
32
+ }
33
+ if (YEAR_PATTERN.test(token)) {
34
+ years.add(token);
35
+ continue;
36
+ }
37
+ periodIds.add(token);
38
+ }
39
+ return { hasSpec: true, years: [...years].sort(), periodIds: [...periodIds] };
40
+ }
41
+ /**
42
+ * Prefer a comparable series across years: annual > first semester (Maret) >
43
+ * second semester (September) > anything else.
44
+ */
45
+ function periodPreference(label) {
46
+ // A bare year (or "Tahunan") is the annual series — the best comparable one.
47
+ if (/^\s*(19|20)\d{2}\s*$/.test(label))
48
+ return 5;
49
+ if (isNeutralPeriodLabel(label))
50
+ return 4;
51
+ if (/semester\s*1|maret|triwulan\s*(i{1}|1)\b|kwartal\s*1/i.test(label))
52
+ return 3;
53
+ if (/semester\s*2|september/i.test(label))
54
+ return 2;
55
+ if (/desember|desember|december/i.test(label))
56
+ return 1.5;
57
+ return 1;
58
+ }
59
+ async function listAllPeriodsSafe(client, domain, varId) {
60
+ const maybeAll = client.listAllPeriods;
61
+ if (typeof maybeAll === "function") {
62
+ return maybeAll.call(client, domain, varId);
63
+ }
64
+ return client.listPeriods(domain, varId);
65
+ }
66
+ export async function resolvePeriodsForSpec(client, domain, varId, spec) {
67
+ const parsed = parseYearSpec(spec);
68
+ const periods = await listAllPeriodsSafe(client, domain, varId);
69
+ const labels = periods
70
+ .map((period) => ({ id: getPeriodId(period), label: getPeriodLabel(period) }))
71
+ .filter((entry) => entry.id !== "");
72
+ const availableYears = [
73
+ ...new Set(labels
74
+ .map((entry) => entry.label.match(/\d{4}/)?.[0])
75
+ .filter((year) => Boolean(year))),
76
+ ].sort();
77
+ const availableLabels = [...labels]
78
+ .sort((a, b) => a.label.localeCompare(b.label, "id", { numeric: true }))
79
+ .reverse()
80
+ .slice(0, 12)
81
+ .map((entry) => entry.label);
82
+ if (!parsed.hasSpec) {
83
+ const latest = [...labels].sort((a, b) => a.label.localeCompare(b.label, "id", { numeric: true })).pop();
84
+ return {
85
+ hasSpec: false,
86
+ entries: latest ? [{ id: latest.id, label: latest.label, year: latest.label.match(/\d{4}/)?.[0] }] : [],
87
+ missingYears: [],
88
+ availableYears,
89
+ availableLabels,
90
+ };
91
+ }
92
+ const entries = [];
93
+ const seen = new Set();
94
+ for (const id of parsed.periodIds) {
95
+ const match = labels.find((entry) => entry.id === id);
96
+ if (match && !seen.has(match.id)) {
97
+ seen.add(match.id);
98
+ entries.push({ id: match.id, label: match.label, year: match.label.match(/\d{4}/)?.[0] });
99
+ }
100
+ }
101
+ const missingYears = [];
102
+ for (const year of parsed.years) {
103
+ const candidates = labels.filter((entry) => entry.label.includes(year));
104
+ if (candidates.length === 0) {
105
+ missingYears.push(year);
106
+ continue;
107
+ }
108
+ const best = [...candidates].sort((a, b) => periodPreference(b.label) - periodPreference(a.label) ||
109
+ a.label.localeCompare(b.label, "id", { numeric: true }))[0];
110
+ if (seen.has(best.id))
111
+ continue;
112
+ seen.add(best.id);
113
+ entries.push({ id: best.id, label: best.label, year });
114
+ }
115
+ return {
116
+ hasSpec: true,
117
+ entries,
118
+ missingYears,
119
+ availableYears,
120
+ availableLabels,
121
+ };
122
+ }
123
+ /** Human readable note about years that had no data. */
124
+ export function describeMissingYears(missing, available) {
125
+ if (missing.length === 0)
126
+ return "";
127
+ const availableNote = available.length > 0
128
+ ? ` Tahun yang tersedia: ${available.join(", ")}.`
129
+ : "";
130
+ return `Tahun ${missing.join(", ")} tidak tersedia untuk variabel ini.${availableNote}`;
131
+ }
132
+ //# sourceMappingURL=period-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"period-resolver.js","sourceRoot":"","sources":["../../src/services/period-resolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ import type { BpsClient } from "../client/bps-client.js";
2
+ import type { BpsDynamicDataResponse } from "../client/types.js";
3
+ import type { IPersistentStore } from "./persistent-store.js";
4
+ import { getPeriodId, getPeriodLabel } from "../client/fields.js";
5
+ /**
6
+ * Builds one comparable series (year → value) for a region.
7
+ *
8
+ * BPS provincial domains reuse national tables whose only row is "Indonesia",
9
+ * so "kemiskinan Jawa Timur" used to answer with the national number. Candidates
10
+ * are therefore accepted only when they actually contain a row for the region,
11
+ * and the candidate with the widest year coverage wins.
12
+ */
13
+ export declare function normalizeRegionLabel(label: string): string;
14
+ /** Pick the vervar id that represents the requested region. */
15
+ export declare function pickRegionVervarId(response: BpsDynamicDataResponse, domain: string, domainName?: string): string | null;
16
+ export declare function hasRegionRow(response: BpsDynamicDataResponse, domain: string, domainName?: string): boolean;
17
+ export interface SeriesPoint {
18
+ id: string;
19
+ label: string;
20
+ year: string;
21
+ value: number;
22
+ }
23
+ export interface RegionSeries {
24
+ region: string;
25
+ domain: string;
26
+ domainName: string;
27
+ varId: number | null;
28
+ varTitle: string;
29
+ unit?: string;
30
+ seriesLabel?: string;
31
+ points: SeriesPoint[];
32
+ missingYears: string[];
33
+ availableYears: string[];
34
+ notes: string[];
35
+ }
36
+ export interface BuildSeriesOptions {
37
+ years: string[];
38
+ /** How many candidate variables to try before giving up. */
39
+ maxCandidates?: number;
40
+ }
41
+ export declare function buildRegionSeries(client: BpsClient, store: IPersistentStore | null, query: string, region: string, domain: string, domainName: string, options: BuildSeriesOptions): Promise<RegionSeries>;
42
+ /** List all periods for a variable (used for diagnostics in error messages). */
43
+ export declare function listPeriodLabels(client: BpsClient, domain: string, varId: number): Promise<Array<{
44
+ id: string;
45
+ label: string;
46
+ }>>;
47
+ export { getPeriodId, getPeriodLabel };
48
+ export interface NationalBreakdown {
49
+ varId: number;
50
+ varTitle: string;
51
+ unit?: string;
52
+ seriesLabel?: string;
53
+ byRegion: Map<string, SeriesPoint[]>;
54
+ }
55
+ /**
56
+ * One national table (e.g. "Jumlah Penduduk Miskin Menurut Provinsi", var 185)
57
+ * already carries every province with a consistent unit and precision. Using it
58
+ * for a province comparison costs ONE request instead of one per province and
59
+ * avoids "Ribu Jiwa" vs "Juta Jiwa" mixes.
60
+ */
61
+ export declare function buildNationalBreakdown(client: BpsClient, query: string, regions: Array<{
62
+ name: string;
63
+ domainName: string;
64
+ }>, years: string[]): Promise<NationalBreakdown | null>;
65
+ //# sourceMappingURL=region-series.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"region-series.d.ts","sourceRoot":"","sources":["../../src/services/region-series.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAI9D,OAAO,EACL,WAAW,EACX,cAAc,EAQf,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;GAOG;AAEH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAM1D;AAED,+DAA+D;AAC/D,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,sBAAsB,EAChC,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,MAAM,GAClB,MAAM,GAAG,IAAI,CAoCf;AAED,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,sBAAsB,EAChC,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAMT;AAuFD,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,4DAA4D;IAC5D,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,gBAAgB,GAAG,IAAI,EAC9B,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,YAAY,CAAC,CA+IvB;AAED,gFAAgF;AAChF,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAO/C;AAED,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC;AAQvC,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;CACtC;AAED;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,EACpD,KAAK,EAAE,MAAM,EAAE,GACd,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CA4GnC"}