building-standards-act-mcp 1.7.0 → 1.9.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/README.md +97 -74
- package/dist/data/kokuji-term-aliases.d.ts +2 -0
- package/dist/data/kokuji-term-aliases.js +21 -0
- package/dist/data/kokuji-term-aliases.js.map +1 -0
- package/dist/lib/article-analyzer.js +3 -4
- package/dist/lib/article-analyzer.js.map +1 -1
- package/dist/lib/article-fetcher.d.ts +12 -0
- package/dist/lib/article-fetcher.js +65 -0
- package/dist/lib/article-fetcher.js.map +1 -0
- package/dist/lib/article-ref.d.ts +14 -0
- package/dist/lib/article-ref.js +52 -0
- package/dist/lib/article-ref.js.map +1 -0
- package/dist/lib/article-schemas.d.ts +51 -0
- package/dist/lib/article-schemas.js +47 -0
- package/dist/lib/article-schemas.js.map +1 -0
- package/dist/lib/citation-verifier.js +5 -6
- package/dist/lib/citation-verifier.js.map +1 -1
- package/dist/lib/egov-client.d.ts +13 -1
- package/dist/lib/egov-client.js +59 -1
- package/dist/lib/egov-client.js.map +1 -1
- package/dist/lib/egov-parser.d.ts +38 -0
- package/dist/lib/egov-parser.js +14 -3
- package/dist/lib/egov-parser.js.map +1 -1
- package/dist/lib/errors.d.ts +3 -2
- package/dist/lib/errors.js +5 -3
- package/dist/lib/errors.js.map +1 -1
- package/dist/lib/kokuji-amendment.d.ts +2 -0
- package/dist/lib/kokuji-amendment.js +26 -0
- package/dist/lib/kokuji-amendment.js.map +1 -0
- package/dist/lib/kokuji-registry.d.ts +2 -3
- package/dist/lib/kokuji-registry.js +9 -91
- package/dist/lib/kokuji-registry.js.map +1 -1
- package/dist/lib/mlit-client.d.ts +10 -7
- package/dist/lib/mlit-client.js +136 -16
- package/dist/lib/mlit-client.js.map +1 -1
- package/dist/lib/openapi-spec.js +2 -1
- package/dist/lib/openapi-spec.js.map +1 -1
- package/dist/lib/pdf-extractor.d.ts +7 -1
- package/dist/lib/pdf-extractor.js +20 -9
- package/dist/lib/pdf-extractor.js.map +1 -1
- package/dist/lib/related-law-finder.js +3 -4
- package/dist/lib/related-law-finder.js.map +1 -1
- package/dist/lib/resilience.js +3 -1
- package/dist/lib/resilience.js.map +1 -1
- package/dist/lib/revision-tracker.d.ts +5 -5
- package/dist/lib/revision-tracker.js +16 -8
- package/dist/lib/revision-tracker.js.map +1 -1
- package/dist/lib/tool-helpers.d.ts +15 -0
- package/dist/lib/tool-helpers.js +37 -0
- package/dist/lib/tool-helpers.js.map +1 -1
- package/dist/lib/tool-invoker.d.ts +4 -0
- package/dist/lib/tool-invoker.js +2 -1
- package/dist/lib/tool-invoker.js.map +1 -1
- package/dist/lib/types.d.ts +17 -0
- package/dist/lib/version.d.ts +2 -0
- package/dist/lib/version.js +3 -0
- package/dist/lib/version.js.map +1 -0
- package/dist/server.js +8 -5
- package/dist/server.js.map +1 -1
- package/dist/tools/analyze-article.js +37 -2
- package/dist/tools/analyze-article.js.map +1 -1
- package/dist/tools/check-law-updates.js +31 -9
- package/dist/tools/check-law-updates.js.map +1 -1
- package/dist/tools/get-full-law.js +23 -3
- package/dist/tools/get-full-law.js.map +1 -1
- package/dist/tools/get-kokuji.js +107 -28
- package/dist/tools/get-kokuji.js.map +1 -1
- package/dist/tools/get-law.js +52 -8
- package/dist/tools/get-law.js.map +1 -1
- package/dist/tools/get-laws-batch.js +44 -41
- package/dist/tools/get-laws-batch.js.map +1 -1
- package/dist/tools/get-metrics.js +28 -2
- package/dist/tools/get-metrics.js.map +1 -1
- package/dist/tools/search-articles.d.ts +2 -0
- package/dist/tools/search-articles.js +86 -0
- package/dist/tools/search-articles.js.map +1 -0
- package/dist/tools/search-law.js +7 -2
- package/dist/tools/search-law.js.map +1 -1
- package/dist/tools/suggest-related.js +7 -2
- package/dist/tools/suggest-related.js.map +1 -1
- package/dist/tools/verify-citation.js +41 -3
- package/dist/tools/verify-citation.js.map +1 -1
- package/package.json +14 -6
package/README.md
CHANGED
|
@@ -11,12 +11,13 @@ AI の建築法規回答に含まれるハルシネーションを、条文原
|
|
|
11
11
|
|
|
12
12
|
## 特徴
|
|
13
13
|
|
|
14
|
-
- **法令取得** — e-Gov 法令 API v2
|
|
15
|
-
- **法令検索** —
|
|
14
|
+
- **法令取得** — e-Gov 法令 API v2 から条文を条単位(`elm` 指定)で取得。1 条あたり数 KB で済み、全文 1 MB 超を読まない
|
|
15
|
+
- **法令検索** — 法令名で建築関連法令を横断検索
|
|
16
|
+
- **条文本文検索** — e-Gov のキーワード検索 API で条文本文を全文検索(`search_articles`)
|
|
16
17
|
- **法令全文取得** — 法令全体のテキストを取得
|
|
17
18
|
- **告示取得** — 建築基準法が技術基準を委任している告示を国土交通省の告示データベース(PDF)から取得
|
|
18
19
|
- **検索ファースト** — e-Gov API 検索による動的な法令解決。プリセットに限らず、e-Gov 収録の全法令を取得可能
|
|
19
|
-
- **略称マップ** — 建築基準法・消防法・都市計画法ほか
|
|
20
|
+
- **略称マップ** — 建築基準法・消防法・都市計画法ほか 116 法令の略称を登録済み。「建基法」「都計法」「消防法」等の略称で指定可能
|
|
20
21
|
- **キャッシュ** — 検索 30 分・法令データ 24 時間の TTL キャッシュ(永続化オプションあり)
|
|
21
22
|
- **API 耐障害性** — 自動リトライ(exponential backoff)+ サーキットブレーカー
|
|
22
23
|
- **運用可視化** — 構造化 JSON ログ + 使用量メトリクス(`get_metrics` ツール)
|
|
@@ -25,27 +26,29 @@ AI の建築法規回答に含まれるハルシネーションを、条文原
|
|
|
25
26
|
|
|
26
27
|
Vercel にデプロイすると、Claude.ai からすぐに使えます。環境変数の設定は不要です(e-Gov API は公開 API)。
|
|
27
28
|
|
|
29
|
+
公開インスタンス: `https://building-standards-act-mcp.vercel.app/api/mcp`(自分でデプロイしなくても、この URL をそのまま Custom Connector に登録できます)
|
|
30
|
+
|
|
28
31
|
[](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FSora-bluesky%2Fbuilding-standards-act-mcp)
|
|
29
32
|
|
|
30
33
|
### Claude.ai でのセットアップ(Free/Pro/Max/Team/Enterprise)
|
|
31
34
|
|
|
32
|
-
>
|
|
35
|
+
> Custom Connectors は Free / Pro / Max / Team / Enterprise の各プランで利用できます(Free プランは 1 件まで)。ローカルで動かしたい場合は [npx(ローカル)でのセットアップ](#npx推奨) を参照してください。
|
|
33
36
|
|
|
34
|
-
1.
|
|
35
|
-
2. [claude.ai](https://claude.ai) →
|
|
36
|
-
3.
|
|
37
|
-
4. URL に `https://
|
|
37
|
+
1. 公開インスタンスを使う場合はこの手順を飛ばす。自分でホストする場合は上の「Deploy with Vercel」ボタンでデプロイ(ワンクリック)
|
|
38
|
+
2. [claude.ai](https://claude.ai) → Customize → Connectors
|
|
39
|
+
3. 「+ Add」→「Add custom connector」をクリック
|
|
40
|
+
4. URL に `https://building-standards-act-mcp.vercel.app/api/mcp`(自分でデプロイした場合はその URL)を入力し、認証は「No sign in」を選択
|
|
38
41
|
5. チャットで「+」→「Connectors」→ building-standards-act を有効化
|
|
39
42
|
6. 「建築基準法第20条を教えて」と質問
|
|
40
43
|
|
|
41
44
|
> 参考: [Get started with custom connectors using remote MCP](https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp)
|
|
42
45
|
|
|
43
|
-
### Vercel
|
|
46
|
+
### Vercel での実行時間
|
|
44
47
|
|
|
45
|
-
-
|
|
46
|
-
- `get_kokuji`(告示取得)は PDF ダウンロード +
|
|
47
|
-
- `check_law_updates` の大規模グループ(9章: 53
|
|
48
|
-
- `BUILDING_LAW_REQUEST_TIMEOUT=8000`
|
|
48
|
+
- Vercel Functions の実行時間は Hobby プランでも既定 300 秒です(Fluid compute)。本リポの `vercel.json` は `maxDuration` を 60 秒に設定しています
|
|
49
|
+
- `get_kokuji`(告示取得)は PDF ダウンロード + パースが重いため、60 秒を超える場合は `vercel.json` の `maxDuration` を引き上げてください
|
|
50
|
+
- `check_law_updates` の大規模グループ(9章: 53法令)は最大 5 並行で実行します(`BUILDING_LAW_CONCURRENCY` で調整可能)
|
|
51
|
+
- `BUILDING_LAW_REQUEST_TIMEOUT=8000` を設定して e-Gov API 呼び出しのタイムアウトを短縮できます
|
|
49
52
|
|
|
50
53
|
---
|
|
51
54
|
|
|
@@ -56,9 +59,11 @@ Vercel にデプロイすると、Claude.ai からすぐに使えます。環境
|
|
|
56
59
|
インストール不要で実行できます。
|
|
57
60
|
|
|
58
61
|
```bash
|
|
59
|
-
npx -y building-standards-act-mcp
|
|
62
|
+
npx -y building-standards-act-mcp@latest
|
|
60
63
|
```
|
|
61
64
|
|
|
65
|
+
`@latest` を付けると、npx のキャッシュに古い版が残っていても最新版で起動します。
|
|
66
|
+
|
|
62
67
|
### Claude Desktop
|
|
63
68
|
|
|
64
69
|
`claude_desktop_config.json` に以下を追加してください。
|
|
@@ -68,7 +73,7 @@ npx -y building-standards-act-mcp
|
|
|
68
73
|
"mcpServers": {
|
|
69
74
|
"building-standards-act": {
|
|
70
75
|
"command": "npx",
|
|
71
|
-
"args": ["-y", "building-standards-act-mcp"]
|
|
76
|
+
"args": ["-y", "building-standards-act-mcp@latest"]
|
|
72
77
|
}
|
|
73
78
|
}
|
|
74
79
|
}
|
|
@@ -77,43 +82,37 @@ npx -y building-standards-act-mcp
|
|
|
77
82
|
### Claude Code
|
|
78
83
|
|
|
79
84
|
```bash
|
|
80
|
-
claude mcp add building-standards-act -- npx -y building-standards-act-mcp
|
|
85
|
+
claude mcp add building-standards-act -- npx -y building-standards-act-mcp@latest
|
|
81
86
|
```
|
|
82
87
|
|
|
83
88
|
#### Windows + VS Code 拡張機能の場合
|
|
84
89
|
|
|
85
|
-
VS Code 拡張機能では `npx` 経由の起動が `Connection closed`
|
|
86
|
-
プロジェクトルートに `.mcp.json` を作成してください。
|
|
87
|
-
|
|
88
|
-
**Step 1: グローバルインストール**
|
|
89
|
-
|
|
90
|
-
```bash
|
|
91
|
-
npm install -g building-standards-act-mcp
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
**Step 2: パスの確認**
|
|
90
|
+
VS Code 拡張機能では `npx` 経由の起動が `Connection closed` エラーになる場合があります。その場合は、公開中の Vercel 版に HTTP で接続するのが確実です。
|
|
95
91
|
|
|
96
92
|
```bash
|
|
97
|
-
|
|
98
|
-
npm root -g # → グローバル node_modules のパス
|
|
93
|
+
claude mcp add --transport http building-standards-act https://building-standards-act-mcp.vercel.app/api/mcp
|
|
99
94
|
```
|
|
100
95
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
取得したパスで置き換えてください(パス区切りは `/` を使用):
|
|
96
|
+
プロジェクト単位で設定するなら、プロジェクトルートの `.mcp.json` に次を書きます。
|
|
104
97
|
|
|
105
98
|
```json
|
|
106
99
|
{
|
|
107
100
|
"mcpServers": {
|
|
108
101
|
"building-standards-act": {
|
|
109
|
-
"
|
|
110
|
-
"
|
|
102
|
+
"type": "http",
|
|
103
|
+
"url": "https://building-standards-act-mcp.vercel.app/api/mcp"
|
|
111
104
|
}
|
|
112
105
|
}
|
|
113
106
|
}
|
|
114
107
|
```
|
|
115
108
|
|
|
116
|
-
|
|
109
|
+
ローカルの stdio で動かしたい場合は、`npx` を `cmd /c` で包みます。
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
claude mcp add building-standards-act -- cmd /c npx -y building-standards-act-mcp@latest
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
> **注意**: グローバルインストールした `dist/index.js` のパスを `.mcp.json` に直接書く方法は使わないでください。パッケージの更新・削除やフォルダの移動で、エラーを出さずに接続できなくなります。
|
|
117
116
|
|
|
118
117
|
### ローカル(ソースから)
|
|
119
118
|
|
|
@@ -137,18 +136,19 @@ npm run build
|
|
|
137
136
|
|
|
138
137
|
## MCP ツール
|
|
139
138
|
|
|
140
|
-
| ツール | 説明
|
|
141
|
-
| ------------------- |
|
|
142
|
-
| `get_law` | 条番号を指定して法令の条文を取得する。略称・正式名称のいずれでも指定可能
|
|
143
|
-
| `get_full_law` |
|
|
144
|
-
| `search_law` |
|
|
145
|
-
| `
|
|
146
|
-
| `
|
|
147
|
-
| `
|
|
148
|
-
| `
|
|
149
|
-
| `
|
|
150
|
-
| `
|
|
151
|
-
| `
|
|
139
|
+
| ツール | 説明 |
|
|
140
|
+
| ------------------- | --------------------------------------------------------------------------------------------------------------- |
|
|
141
|
+
| `get_law` | 条番号を指定して法令の条文を取得する。略称・正式名称のいずれでも指定可能 |
|
|
142
|
+
| `get_full_law` | 法令の全文を取得する。`max_chars`(既定 100,000)で区切り、続きは `offset` で取る |
|
|
143
|
+
| `search_law` | 法令名(タイトル)で建築関連法令を検索する。略称マップと e-Gov API の両方を検索。条文本文の検索は `search_articles` |
|
|
144
|
+
| `search_articles` | 条文本文をキーワードで全文検索する(e-Gov `/keyword`)。法令名で絞り込み可。条番号は返らないので `get_law` で確定する |
|
|
145
|
+
| `get_kokuji` | 建築基準法が技術基準を委任している告示の全文を取得する(省エネ告示は国交省 PDF から直接取得) |
|
|
146
|
+
| `check_law_updates` | 法令の改正状況を e-Gov API で確認する。`since`(既定は 12 か月前)より後の改正だけを「改正あり」にする |
|
|
147
|
+
| `get_laws_batch` | 複数の法令・条文を一括取得する(最大20件、1 条ごとに条単位で取得) |
|
|
148
|
+
| `verify_citation` | AIの回答に含まれる法令引用を検証する(条文存在確認・テキスト照合、最大10件) |
|
|
149
|
+
| `suggest_related` | 指定した条文の関連法令・委任先・同法令内参照を自動抽出して提案する |
|
|
150
|
+
| `analyze_article` | 条文の構造解析メタデータ(項数・号数・参照統計・プレビュー)をJSON形式で返す |
|
|
151
|
+
| `get_metrics` | サーバーの使用量メトリクスを返す(ツール呼び出し回数・APIリクエスト数・キャッシュヒット率) |
|
|
152
152
|
|
|
153
153
|
### パラメータ
|
|
154
154
|
|
|
@@ -162,21 +162,34 @@ npm run build
|
|
|
162
162
|
|
|
163
163
|
#### `get_full_law`
|
|
164
164
|
|
|
165
|
-
| パラメータ
|
|
166
|
-
|
|
|
167
|
-
| `law_name`
|
|
165
|
+
| パラメータ | 説明 | 例 |
|
|
166
|
+
| ----------- | --------------------------------------------- | ---------------------------- |
|
|
167
|
+
| `law_name` | 法令名(正式名称または略称) | `建築基準法施行令`, `建基令` |
|
|
168
|
+
| `max_chars` | 1 回に返す最大文字数(既定 100,000) | `50000` |
|
|
169
|
+
| `offset` | 続きを取るときの開始位置(末尾の案内に出る値) | `100000` |
|
|
168
170
|
|
|
169
171
|
#### `search_law`
|
|
170
172
|
|
|
171
|
-
| パラメータ | 説明
|
|
172
|
-
| ---------- |
|
|
173
|
-
| `keyword` |
|
|
173
|
+
| パラメータ | 説明 | 例 |
|
|
174
|
+
| ---------- | ---------------------- | ---------------------- |
|
|
175
|
+
| `keyword` | 法令名に含まれる語 | `建築`, `都市計画` |
|
|
176
|
+
|
|
177
|
+
#### `search_articles`
|
|
178
|
+
|
|
179
|
+
| パラメータ | 説明 | 例 |
|
|
180
|
+
| ----------- | ------------------------------------------------------------ | ---------------------- |
|
|
181
|
+
| `keyword` | 条文本文に含まれる語。AND / OR / NOT と `*` `?` が使える | `耐火構造`, `壁量` |
|
|
182
|
+
| `law_title` | 法令名または略称で絞り込み(省略時は e-Gov の全法令) | `建築基準法` |
|
|
183
|
+
| `limit` | 返す該当文の数(既定 10、最大 50) | `20` |
|
|
184
|
+
| `offset` | 続きを取るときの開始位置(応答の `next_offset` を渡す) | `10` |
|
|
174
185
|
|
|
175
186
|
#### `get_kokuji`
|
|
176
187
|
|
|
177
|
-
| パラメータ | 説明
|
|
178
|
-
| ------------- |
|
|
179
|
-
| `kokuji_name` | 告示名
|
|
188
|
+
| パラメータ | 説明 | 例 |
|
|
189
|
+
| ------------- | ------------------------------------- | ------------------------------ |
|
|
190
|
+
| `kokuji_name` | 告示名 | `耐火構造の構造方法を定める件` |
|
|
191
|
+
| `max_chars` | 1 回に返す最大文字数(既定 100,000) | `50000` |
|
|
192
|
+
| `offset` | 続きを取るときの開始位置 | `100000` |
|
|
180
193
|
|
|
181
194
|
#### `check_law_updates`
|
|
182
195
|
|
|
@@ -185,6 +198,7 @@ npm run build
|
|
|
185
198
|
| `law_name` | 法令名または略称(単体チェック) | `建築基準法` |
|
|
186
199
|
| `group` | 章グループ(バッチチェック、省略時は全章) | `1章` |
|
|
187
200
|
| `show_history` | 改正履歴の詳細を表示(`law_name` 指定時) | `true` |
|
|
201
|
+
| `since` | 基準日。これより後の改正だけを報告(省略時は 12 か月前) | `2026-01-01` |
|
|
188
202
|
|
|
189
203
|
#### `get_laws_batch`
|
|
190
204
|
|
|
@@ -235,8 +249,16 @@ npm run build
|
|
|
235
249
|
### 法令検索
|
|
236
250
|
|
|
237
251
|
```
|
|
238
|
-
|
|
239
|
-
→ search_law(keyword="
|
|
252
|
+
都市計画に関する法令を検索して
|
|
253
|
+
→ search_law(keyword="都市計画")
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### 条文本文検索
|
|
257
|
+
|
|
258
|
+
```
|
|
259
|
+
建築基準法で「耐火構造」が出てくる条文を探して
|
|
260
|
+
→ search_articles(keyword="耐火構造", law_title="建築基準法")
|
|
261
|
+
→ 該当文と区分(本則 / 附則)が返るので、条番号は get_law で確定する
|
|
240
262
|
```
|
|
241
263
|
|
|
242
264
|
### 全文取得
|
|
@@ -261,6 +283,9 @@ npm run build
|
|
|
261
283
|
|
|
262
284
|
建築基準法施行令の附則第1条を取得して
|
|
263
285
|
→ get_law(law_name="建築基準法施行令", article_number="附則第1条")
|
|
286
|
+
|
|
287
|
+
未施行の改正附則(現行データに無いときは改正履歴から未施行版を取る)
|
|
288
|
+
→ get_law(law_name="建築基準法施行令", article_number="附則(令和8年政令第284号)")
|
|
264
289
|
```
|
|
265
290
|
|
|
266
291
|
### 別表取得
|
|
@@ -315,9 +340,9 @@ AI が建築法規について回答する際、条文の引用ミスや存在
|
|
|
315
340
|
→ 「第20条第1項第三号の記載に誤りがあります。正しくは…」
|
|
316
341
|
```
|
|
317
342
|
|
|
318
|
-
## 対応法令一覧(
|
|
343
|
+
## 対応法令一覧(116 法令 + e-Gov 全法令)
|
|
319
344
|
|
|
320
|
-
> 以下の
|
|
345
|
+
> 以下の 116 法令は略称マップに登録済みです。略称マップに含まれない法令も、正式名称を指定すれば e-Gov API 検索で動的に取得できます。
|
|
321
346
|
|
|
322
347
|
### 総則(4 法令)
|
|
323
348
|
|
|
@@ -495,21 +520,19 @@ AI が建築法規について回答する際、条文の引用ミスや存在
|
|
|
495
520
|
| 被災市街地復興特別措置法 | 被災市街地復興法 |
|
|
496
521
|
| 被災区分所有建物の再建等に関する特別措置法 | 被災マンション法 |
|
|
497
522
|
|
|
498
|
-
##
|
|
523
|
+
## 告示の取得
|
|
499
524
|
|
|
500
|
-
e-Gov API は告示を収録していないため、`get_kokuji` は国土交通省の告示・通達データベース(Excel → PDF
|
|
525
|
+
e-Gov API は告示を収録していないため、`get_kokuji` は国土交通省の告示・通達データベース(Excel → PDF)から正式名称で動的に取得します。見つからない場合は e-Gov API のキーワード検索にフォールバックします。
|
|
501
526
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
| 建築物エネルギー消費性能基準等を定める省令における算出方法等に係る事項 | 省エネ(UA値) |
|
|
512
|
-
| 住宅部分の外壁、窓等を通しての熱の損失の防止に関する基準及び一次エネルギー消費量に関する基準 | 省エネ(断熱等性能等級) |
|
|
527
|
+
ハードコードされたプリセットは持たず、常に最新の告示データベースから取得するため、改正後も陳腐化しません。
|
|
528
|
+
|
|
529
|
+
```
|
|
530
|
+
耐火構造の構造方法を定める件を取得して
|
|
531
|
+
→ get_kokuji(kokuji_name="耐火構造の構造方法を定める件")
|
|
532
|
+
|
|
533
|
+
木造建築物の軸組の設置の基準を定める件を取得して
|
|
534
|
+
→ get_kokuji(kokuji_name="木造建築物の軸組の設置の基準を定める件")
|
|
535
|
+
```
|
|
513
536
|
|
|
514
537
|
## 法令解決の仕組み
|
|
515
538
|
|
|
@@ -539,7 +562,7 @@ e-Gov API は告示を収録していないため、`get_kokuji` は国土交通
|
|
|
539
562
|
"mcpServers": {
|
|
540
563
|
"building-standards-act": {
|
|
541
564
|
"command": "npx",
|
|
542
|
-
"args": ["-y", "building-standards-act-mcp"],
|
|
565
|
+
"args": ["-y", "building-standards-act-mcp@latest"],
|
|
543
566
|
"env": {
|
|
544
567
|
"BUILDING_LAW_CACHE": "file"
|
|
545
568
|
}
|
|
@@ -563,7 +586,7 @@ e-Gov API は告示を収録していないため、`get_kokuji` は国土交通
|
|
|
563
586
|
| API 並行呼び出し | 最大 5 並行(200ms 間隔) |
|
|
564
587
|
| Vercel デプロイ | 対応(MCP-over-HTTP + REST API) |
|
|
565
588
|
| Vercel 関数タイムアウト | 60 秒(maxDuration) |
|
|
566
|
-
| Node.js | >=
|
|
589
|
+
| Node.js | >= 22.12.0 |
|
|
567
590
|
|
|
568
591
|
## セキュリティ
|
|
569
592
|
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Terms absent from the legacy MLIT titles; keep aliases tied to provisions. */
|
|
2
|
+
const KOKUJI_TERM_ALIASES = {
|
|
3
|
+
// Reiwa 6 MLIT Notice 447 moved wall-quantity rules to Showa 56 Notice 1100, titled with Order Article 46(4).
|
|
4
|
+
壁量: "令46条4項",
|
|
5
|
+
// Required wall quantity is governed by the same Order Article 46(4) rule in Showa 56 Notice 1100.
|
|
6
|
+
必要壁量: "令46条4項",
|
|
7
|
+
// Wall-quantity calculations use Order Article 46(4), named in the legacy title of Showa 56 Notice 1100.
|
|
8
|
+
壁量計算: "令46条4項",
|
|
9
|
+
// Wall-quantity standards moved under Showa 56 Notice 1100 through Reiwa 6 MLIT Notice 447.
|
|
10
|
+
壁量基準: "令46条4項",
|
|
11
|
+
// Existing wall quantity is assessed against the Order Article 46(4) wall-quantity rule.
|
|
12
|
+
存在壁量: "令46条4項",
|
|
13
|
+
};
|
|
14
|
+
/** Append distinct provision aliases while preserving the user's original text. */
|
|
15
|
+
export function expandKokujiAliases(text) {
|
|
16
|
+
const targets = new Set(Object.entries(KOKUJI_TERM_ALIASES)
|
|
17
|
+
.filter(([term]) => text.includes(term))
|
|
18
|
+
.map(([, target]) => target));
|
|
19
|
+
return [text, ...targets].join(" ");
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=kokuji-term-aliases.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kokuji-term-aliases.js","sourceRoot":"","sources":["../../src/data/kokuji-term-aliases.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,MAAM,mBAAmB,GAAqC;IAC5D,8GAA8G;IAC9G,EAAE,EAAE,QAAQ;IACZ,mGAAmG;IACnG,IAAI,EAAE,QAAQ;IACd,yGAAyG;IACzG,IAAI,EAAE,QAAQ;IACd,4FAA4F;IAC5F,IAAI,EAAE,QAAQ;IACd,yFAAyF;IACzF,IAAI,EAAE,QAAQ;CACf,CAAC;AAEF,mFAAmF;AACnF,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,MAAM,OAAO,GAAG,IAAI,GAAG,CACrB,MAAM,CAAC,OAAO,CAAC,mBAAmB,CAAC;SAChC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;SACvC,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAC/B,CAAC;IACF,OAAO,CAAC,IAAI,EAAE,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACtC,CAAC"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { parseArticleStructured } from "./egov-parser.js";
|
|
1
|
+
import { fetchParsedArticle } from "./article-fetcher.js";
|
|
3
2
|
import { formatArticleRef } from "./errors.js";
|
|
4
3
|
import { resolveLawId } from "./law-resolver.js";
|
|
5
4
|
const PREVIEW_LENGTH = 100;
|
|
@@ -60,8 +59,8 @@ export async function analyzeArticle(lawName, articleNumber) {
|
|
|
60
59
|
if (!resolved) {
|
|
61
60
|
throw new Error(`法令「${lawName}」が見つかりませんでした。`);
|
|
62
61
|
}
|
|
63
|
-
const
|
|
64
|
-
const article =
|
|
62
|
+
const fetched = await fetchParsedArticle(resolved.law_id, articleNumber, "structured");
|
|
63
|
+
const article = fetched?.article;
|
|
65
64
|
if (!article) {
|
|
66
65
|
throw new Error(`${resolved.title}に${formatArticleRef(articleNumber)}が見つかりませんでした。`);
|
|
67
66
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"article-analyzer.js","sourceRoot":"","sources":["../../src/lib/article-analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"article-analyzer.js","sourceRoot":"","sources":["../../src/lib/article-analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,MAAM,cAAc,GAAG,GAAG,CAAC;AAE3B;;;GAGG;AACH,SAAS,gBAAgB,CAAC,OAAe;IACvC,OAAO,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;AAC3D,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CAAC,OAA0B;IACjD,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;QACtC,KAAK,IAAI,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC;QACxC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,KAAK,IAAI,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;YACnC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAChC,KAAK,IAAI,iBAAiB,CAAC,GAAG,CAAC,CAAC;YAClC,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,iBAAiB,CACxB,GAAkE;IAElE,IAAI,KAAK,GAAG,GAAG,CAAC,gBAAgB,CAAC,MAAM,CAAC;IACxC,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;QACjC,KAAK,IAAI,iBAAiB,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CAAC,OAA0B;IAC/C,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;QACtC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,KAAK,IAAI,sBAAsB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,sBAAsB,CAC7B,IAAgE;IAEhE,IAAI,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC;IACxB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,KAAK,IAAI,sBAAsB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAChD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAe,EACf,aAAqB;IAErB,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,CAAC;IAC7C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,MAAM,OAAO,eAAe,CAAC,CAAC;IAChD,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,kBAAkB,CACtC,QAAQ,CAAC,MAAM,EACf,aAAa,EACb,YAAY,CACb,CAAC;IACF,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,CAAC;IAEjC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,GAAG,QAAQ,CAAC,KAAK,IAAI,gBAAgB,CAAC,aAAa,CAAC,cAAc,CACnE,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,MAAM,CACzC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,EAChC,CAAC,CACF,CAAC;IAEF,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,IAAI,EAAE,CAAC;IACtC,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,WAAW,CAAC,CAAC;IACpE,MAAM,cAAc,GAAG;QACrB,GAAG,IAAI,GAAG,CACR,YAAY;aACT,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC;aACxB,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAC/C;KACF,CAAC;IAEF,OAAO;QACL,QAAQ,EAAE,QAAQ,CAAC,KAAK;QACxB,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC,eAAe,CAAC;QAClD,SAAS,EAAE;YACT,eAAe,EAAE,OAAO,CAAC,UAAU,CAAC,MAAM;YAC1C,UAAU,EAAE,SAAS;YACrB,aAAa,EAAE,aAAa,CAAC,OAAO,CAAC;YACrC,gBAAgB,EAAE,eAAe,CAAC,OAAO,CAAC;SAC3C;QACD,mBAAmB,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAClD,aAAa,EAAE,CAAC,CAAC,aAAa;YAC9B,OAAO,EACL,CAAC,CAAC,kBAAkB,CAAC,MAAM,GAAG,cAAc;gBAC1C,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,EAAE,cAAc,CAAC,GAAG,GAAG;gBACrD,CAAC,CAAC,CAAC,CAAC,kBAAkB;YAC1B,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM;SAC3B,CAAC,CAAC;QACH,iBAAiB,EAAE;YACjB,KAAK,EAAE,IAAI,CAAC,MAAM;YAClB,SAAS,EAAE,YAAY,CAAC,MAAM;YAC9B,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,MAAM;YAC9D,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,MAAM;YAC9D,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,YAAY,CAAC,CAAC,MAAM;YAClE,eAAe,EAAE,cAAc;SAChC;QACD,eAAe,EAAE,OAAO;KACzB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { EgovLawDataResponse, EgovRevisionInfo, ParsedArticle, StructuredArticle } from "./types.js";
|
|
2
|
+
export interface FetchedArticle<T> {
|
|
3
|
+
article: T;
|
|
4
|
+
revision?: Pick<EgovRevisionInfo, "law_revision_id" | "amendment_enforcement_date" | "current_revision_status">;
|
|
5
|
+
revisionNote?: string;
|
|
6
|
+
}
|
|
7
|
+
/** Choose the smallest API response that can satisfy the request. */
|
|
8
|
+
export declare function fetchArticleData(lawId: string, articleNumber: string): Promise<EgovLawDataResponse | null>;
|
|
9
|
+
/** Resolve amendment supplements against a matching revision only after a miss. */
|
|
10
|
+
export declare function fetchParsedArticle(lawId: string, articleNumber: string, format?: "text"): Promise<FetchedArticle<ParsedArticle> | null>;
|
|
11
|
+
export declare function fetchParsedArticle(lawId: string, articleNumber: string, format: "structured"): Promise<FetchedArticle<StructuredArticle> | null>;
|
|
12
|
+
export declare function fetchParsedArticle(lawId: string, articleNumber: string, format: "text" | "structured"): Promise<FetchedArticle<ParsedArticle | StructuredArticle> | null>;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { getLawArticle, getLawData, getLawDataByRevision, getLawRevisions, } from "./egov-client.js";
|
|
2
|
+
import { detectSpecialSection, findAmendmentSupplProvision, getSupplProvisionArticleNumbers, matchAmendLawNum, parseArticle, parseArticleStructured, toArticleElm, } from "./egov-parser.js";
|
|
3
|
+
import { ArticleNotFoundError } from "./errors.js";
|
|
4
|
+
/** Choose the smallest API response that can satisfy the request. */
|
|
5
|
+
export async function fetchArticleData(lawId, articleNumber) {
|
|
6
|
+
const elm = toArticleElm(articleNumber);
|
|
7
|
+
return elm !== null ? await getLawArticle(lawId, elm) : await getLawData(lawId);
|
|
8
|
+
}
|
|
9
|
+
export async function fetchParsedArticle(lawId, articleNumber, format = "text") {
|
|
10
|
+
const data = await fetchArticleData(lawId, articleNumber);
|
|
11
|
+
if (!data)
|
|
12
|
+
return null;
|
|
13
|
+
const parse = format === "structured" ? parseArticleStructured : parseArticle;
|
|
14
|
+
const article = parse(data.law_full_text, articleNumber);
|
|
15
|
+
if (article)
|
|
16
|
+
return { article };
|
|
17
|
+
const special = detectSpecialSection(articleNumber);
|
|
18
|
+
if (special?.type !== "suppl_amendment" &&
|
|
19
|
+
special?.type !== "suppl_amendment_article") {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
const revisions = await getLawRevisions(lawId);
|
|
23
|
+
const revision = revisions.revisions.find((entry) => entry.law_revision_id !== data.revision_info.law_revision_id &&
|
|
24
|
+
matchAmendLawNum(special.amendLawNum, entry.amendment_law_num));
|
|
25
|
+
let missingData = data;
|
|
26
|
+
if (revision) {
|
|
27
|
+
const revisionData = await getLawDataByRevision(revision.law_revision_id);
|
|
28
|
+
const revisedArticle = parse(revisionData.law_full_text, articleNumber);
|
|
29
|
+
if (revisedArticle) {
|
|
30
|
+
const metadata = {
|
|
31
|
+
law_revision_id: revision.law_revision_id,
|
|
32
|
+
amendment_enforcement_date: revision.amendment_enforcement_date,
|
|
33
|
+
current_revision_status: revision.current_revision_status,
|
|
34
|
+
};
|
|
35
|
+
const label = revision.current_revision_status === "UnEnforced"
|
|
36
|
+
? "未施行の改正"
|
|
37
|
+
: "別の改正";
|
|
38
|
+
return {
|
|
39
|
+
article: revisedArticle,
|
|
40
|
+
revision: metadata,
|
|
41
|
+
revisionNote: `※ この附則は${label}(施行日 ${revision.amendment_enforcement_date})の法令データから取得しました。`,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
if (findAmendmentSupplProvision(revisionData.law_full_text, special.amendLawNum)) {
|
|
45
|
+
missingData = revisionData;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (special.type === "suppl_amendment_article") {
|
|
49
|
+
const suppl = findAmendmentSupplProvision(missingData.law_full_text, special.amendLawNum);
|
|
50
|
+
if (suppl) {
|
|
51
|
+
const numbers = getSupplProvisionArticleNumbers(suppl).map((num) => {
|
|
52
|
+
const [main, ...branches] = num.split("_");
|
|
53
|
+
return `第${main}条${branches.map((branch) => `の${branch}`).join("")}`;
|
|
54
|
+
});
|
|
55
|
+
const title = missingData.revision_info.law_title;
|
|
56
|
+
const qualifier = suppl.attr?.["Extract"] === "true" ? "は抄録で、" : "には";
|
|
57
|
+
const contents = numbers.length > 0
|
|
58
|
+
? `${numbers.join("・")}のみ収録されています。`
|
|
59
|
+
: "条番号付きの条文は収録されていません。";
|
|
60
|
+
throw new ArticleNotFoundError(articleNumber, title, `${title}の附則(${special.amendLawNum})${qualifier}${contents}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=article-fetcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"article-fetcher.js","sourceRoot":"","sources":["../../src/lib/article-fetcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** A reference and its source span; numeral strings retain kanji spelling. */
|
|
2
|
+
export interface ArticleRef {
|
|
3
|
+
law?: string;
|
|
4
|
+
article: string;
|
|
5
|
+
branches: string[];
|
|
6
|
+
paragraph?: string;
|
|
7
|
+
item?: string;
|
|
8
|
+
start: number;
|
|
9
|
+
end: number;
|
|
10
|
+
}
|
|
11
|
+
/** Parse bare references and explicit law names without assuming a law context. */
|
|
12
|
+
export declare function parseArticleRefs(text: string): ArticleRef[];
|
|
13
|
+
/** Render the kanji reference form used in notice titles, without the law name. */
|
|
14
|
+
export declare function formatArticleRef(ref: ArticleRef): string;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const NUMERAL = "[0-90-9〇零一二三四五六七八九十百千万億兆]+";
|
|
2
|
+
const LAW = "[\\u4E00-\\u9FFF]+(?:法(?:施行令|施行規則)?|施行令|規則)|施行令|規則|法|令";
|
|
3
|
+
/** Parse bare references and explicit law names without assuming a law context. */
|
|
4
|
+
export function parseArticleRefs(text) {
|
|
5
|
+
const pattern = new RegExp(`(?:(${LAW})\\s*)?第?(${NUMERAL})条((?:の第?${NUMERAL})*)(?:第?(${NUMERAL})項)?(?:第?(${NUMERAL})号)?`, "g");
|
|
6
|
+
return [...text.matchAll(pattern)].map((match) => {
|
|
7
|
+
const prefix = match[1];
|
|
8
|
+
const law = prefix === "法"
|
|
9
|
+
? "建築基準法"
|
|
10
|
+
: prefix === "令" || prefix === "施行令"
|
|
11
|
+
? "建築基準法施行令"
|
|
12
|
+
: prefix;
|
|
13
|
+
return {
|
|
14
|
+
law,
|
|
15
|
+
article: match[2],
|
|
16
|
+
branches: match[3] ? match[3].split("の").slice(1) : [],
|
|
17
|
+
paragraph: match[4],
|
|
18
|
+
item: match[5],
|
|
19
|
+
start: match.index,
|
|
20
|
+
end: match.index + match[0].length,
|
|
21
|
+
};
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
function integerToKanji(value) {
|
|
25
|
+
const digits = "〇一二三四五六七八九";
|
|
26
|
+
for (const [unit, label] of [
|
|
27
|
+
[1_0000_0000_0000, "兆"], [1_0000_0000, "億"], [1_0000, "万"],
|
|
28
|
+
[1000, "千"], [100, "百"], [10, "十"],
|
|
29
|
+
]) {
|
|
30
|
+
if (value < unit)
|
|
31
|
+
continue;
|
|
32
|
+
const count = Math.floor(value / unit);
|
|
33
|
+
const prefix = count === 1 && unit <= 1000 ? "" : integerToKanji(count);
|
|
34
|
+
const remainder = value % unit;
|
|
35
|
+
return prefix + label + (remainder ? integerToKanji(remainder) : "");
|
|
36
|
+
}
|
|
37
|
+
return digits[value];
|
|
38
|
+
}
|
|
39
|
+
function formatNumeral(value) {
|
|
40
|
+
const normalized = value.replace(/^第/, "").replace(/[0-9]/g, (digit) => String(digit.charCodeAt(0) - "0".charCodeAt(0)));
|
|
41
|
+
return /^\d+$/.test(normalized)
|
|
42
|
+
? integerToKanji(Number(normalized))
|
|
43
|
+
: normalized;
|
|
44
|
+
}
|
|
45
|
+
/** Render the kanji reference form used in notice titles, without the law name. */
|
|
46
|
+
export function formatArticleRef(ref) {
|
|
47
|
+
return `第${formatNumeral(ref.article)}条`
|
|
48
|
+
+ ref.branches.map((branch) => `の${formatNumeral(branch)}`).join("")
|
|
49
|
+
+ (ref.paragraph ? `第${formatNumeral(ref.paragraph)}項` : "")
|
|
50
|
+
+ (ref.item ? `第${formatNumeral(ref.item)}号` : "");
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=article-ref.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"article-ref.js","sourceRoot":"","sources":["../../src/lib/article-ref.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { StructuredSubitem } from "./types.js";
|
|
3
|
+
export declare const parsedArticleSchema: z.ZodObject<{
|
|
4
|
+
article_num: z.ZodString;
|
|
5
|
+
article_caption: z.ZodString;
|
|
6
|
+
article_title: z.ZodString;
|
|
7
|
+
text: z.ZodString;
|
|
8
|
+
references: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
9
|
+
raw_text: z.ZodString;
|
|
10
|
+
ref_type: z.ZodEnum<{
|
|
11
|
+
same_law: "same_law";
|
|
12
|
+
cross_law: "cross_law";
|
|
13
|
+
relative: "relative";
|
|
14
|
+
delegation: "delegation";
|
|
15
|
+
unknown: "unknown";
|
|
16
|
+
}>;
|
|
17
|
+
target_law: z.ZodOptional<z.ZodString>;
|
|
18
|
+
target_article: z.ZodOptional<z.ZodString>;
|
|
19
|
+
target_paragraph: z.ZodOptional<z.ZodString>;
|
|
20
|
+
target_item: z.ZodOptional<z.ZodString>;
|
|
21
|
+
}, z.core.$strip>>>;
|
|
22
|
+
}, z.core.$strip>;
|
|
23
|
+
export declare const structuredArticleSchema: z.ZodObject<{
|
|
24
|
+
article_num: z.ZodString;
|
|
25
|
+
article_caption: z.ZodString;
|
|
26
|
+
article_title: z.ZodString;
|
|
27
|
+
paragraphs: z.ZodArray<z.ZodObject<{
|
|
28
|
+
paragraph_num: z.ZodString;
|
|
29
|
+
paragraph_sentence: z.ZodString;
|
|
30
|
+
items: z.ZodArray<z.ZodObject<{
|
|
31
|
+
item_num: z.ZodString;
|
|
32
|
+
item_title: z.ZodString;
|
|
33
|
+
item_sentence: z.ZodString;
|
|
34
|
+
subitems: z.ZodArray<z.ZodType<StructuredSubitem, unknown, z.core.$ZodTypeInternals<StructuredSubitem, unknown>>>;
|
|
35
|
+
}, z.core.$strip>>;
|
|
36
|
+
}, z.core.$strip>>;
|
|
37
|
+
references: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
38
|
+
raw_text: z.ZodString;
|
|
39
|
+
ref_type: z.ZodEnum<{
|
|
40
|
+
same_law: "same_law";
|
|
41
|
+
cross_law: "cross_law";
|
|
42
|
+
relative: "relative";
|
|
43
|
+
delegation: "delegation";
|
|
44
|
+
unknown: "unknown";
|
|
45
|
+
}>;
|
|
46
|
+
target_law: z.ZodOptional<z.ZodString>;
|
|
47
|
+
target_article: z.ZodOptional<z.ZodString>;
|
|
48
|
+
target_paragraph: z.ZodOptional<z.ZodString>;
|
|
49
|
+
target_item: z.ZodOptional<z.ZodString>;
|
|
50
|
+
}, z.core.$strip>>>;
|
|
51
|
+
}, z.core.$strip>;
|